summaryrefslogtreecommitdiff
path: root/chromium/content
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/content')
-rw-r--r--chromium/content/BUILD.gn29
-rw-r--r--chromium/content/DEPS24
-rw-r--r--chromium/content/OWNERS1
-rw-r--r--chromium/content/README.md (renamed from chromium/content/README)5
-rw-r--r--chromium/content/app/BUILD.gn43
-rw-r--r--chromium/content/app/DEPS3
-rw-r--r--chromium/content/app/android/child_process_service.cc19
-rw-r--r--chromium/content/app/android/content_main.cc1
-rw-r--r--chromium/content/app/android/download_main.cc21
-rw-r--r--chromium/content/app/android/library_loader_hooks.cc13
-rw-r--r--chromium/content/app/content_main_runner.cc213
-rw-r--r--chromium/content/app/mojo/mojo_init.cc32
-rw-r--r--chromium/content/app/strings/content_strings.grd200
-rw-r--r--chromium/content/app/strings/translations/content_strings_am.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_ar.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_bg.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_bn.xtb60
-rw-r--r--chromium/content/app/strings/translations/content_strings_ca.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_cs.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_da.xtb60
-rw-r--r--chromium/content/app/strings/translations/content_strings_de.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_el.xtb60
-rw-r--r--chromium/content/app/strings/translations/content_strings_en-GB.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_es-419.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_es.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_et.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_fa.xtb62
-rw-r--r--chromium/content/app/strings/translations/content_strings_fi.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_fil.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_fr.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_gu.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_hi.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_hr.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_hu.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_id.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_it.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_iw.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_ja.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_kn.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_ko.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_lt.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_lv.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_ml.xtb62
-rw-r--r--chromium/content/app/strings/translations/content_strings_mr.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_ms.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_nl.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_no.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_pl.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_pt-BR.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_pt-PT.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_ro.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_ru.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_sk.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_sl.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_sr.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_sv.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_sw.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_ta.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_te.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_th.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_tr.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_uk.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_vi.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_zh-CN.xtb58
-rw-r--r--chromium/content/app/strings/translations/content_strings_zh-TW.xtb58
-rw-r--r--chromium/content/browser/BUILD.gn263
-rw-r--r--chromium/content/browser/DEPS15
-rw-r--r--chromium/content/browser/accessibility/accessibility_event_recorder_win.cc2
-rw-r--r--chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc1
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc10
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc3
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc47
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm8
-rw-r--r--chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc102
-rw-r--r--chromium/content/browser/accessibility/android_hit_testing_browsertest.cc79
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.cc301
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility.h53
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_android.cc437
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_android.h4
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_auralinux.cc37
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_auralinux.h7
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_cocoa.h34
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_cocoa.mm1369
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_mac.h8
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_mac.mm14
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm3
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.cc438
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager.h126
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_android.cc312
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_android.h12
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_mac.h29
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm205
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc367
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_win.cc145
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_manager_win.h24
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_state_impl.cc2
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_state_impl_mac.mm44
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc1
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win.cc669
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win.h61
-rw-r--r--chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc342
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc168
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_browsertest_base.h8
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc26
-rw-r--r--chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc102
-rw-r--r--chromium/content/browser/accessibility/hit_testing_browsertest.cc171
-rw-r--r--chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc246
-rw-r--r--chromium/content/browser/accessibility/one_shot_accessibility_tree_search.h41
-rw-r--r--chromium/content/browser/accessibility/site_per_process_accessibility_browsertest.cc14
-rw-r--r--chromium/content/browser/accessibility/snapshot_ax_tree_browsertest.cc66
-rw-r--r--chromium/content/browser/android/browser_surface_texture_manager.h8
-rw-r--r--chromium/content/browser/android/child_process_launcher_android.cc56
-rw-r--r--chromium/content/browser/android/child_process_launcher_android.h8
-rw-r--r--chromium/content/browser/android/composited_touch_handle_drawable.cc2
-rw-r--r--chromium/content/browser/android/content_startup_flags.cc9
-rw-r--r--chromium/content/browser/android/content_video_view.cc111
-rw-r--r--chromium/content/browser/android/content_video_view.h88
-rw-r--r--chromium/content/browser/android/content_view_core_impl.cc99
-rw-r--r--chromium/content/browser/android/content_view_core_impl.h29
-rw-r--r--chromium/content/browser/android/content_view_core_impl_observer.h22
-rw-r--r--chromium/content/browser/android/content_view_render_view.cc16
-rw-r--r--chromium/content/browser/android/content_view_render_view.h7
-rw-r--r--chromium/content/browser/android/download_controller_android_impl.cc101
-rw-r--r--chromium/content/browser/android/download_controller_android_impl.h14
-rw-r--r--chromium/content/browser/android/in_process/context_provider_in_process.cc53
-rw-r--r--chromium/content/browser/android/in_process/context_provider_in_process.h11
-rw-r--r--chromium/content/browser/android/in_process/synchronous_compositor_factory_impl.cc193
-rw-r--r--chromium/content/browser/android/in_process/synchronous_compositor_factory_impl.h25
-rw-r--r--chromium/content/browser/android/in_process/synchronous_compositor_impl.cc60
-rw-r--r--chromium/content/browser/android/in_process/synchronous_compositor_impl.h17
-rw-r--r--chromium/content/browser/android/in_process/synchronous_compositor_renderer_statics.cc15
-rw-r--r--chromium/content/browser/android/in_process/synchronous_compositor_renderer_statics.h16
-rw-r--r--chromium/content/browser/android/in_process/synchronous_input_event_filter.cc38
-rw-r--r--chromium/content/browser/android/in_process/synchronous_input_event_filter.h18
-rw-r--r--chromium/content/browser/android/in_process_surface_texture_manager.h8
-rw-r--r--chromium/content/browser/android/java/OWNERS2
-rw-r--r--chromium/content/browser/android/service_registry_android_impl.cc (renamed from chromium/content/browser/mojo/service_registry_android.cc)51
-rw-r--r--chromium/content/browser/android/service_registry_android_impl.h53
-rw-r--r--chromium/content/browser/android/synchronous_compositor_base.cc32
-rw-r--r--chromium/content/browser/android/synchronous_compositor_base.h3
-rw-r--r--chromium/content/browser/android/synchronous_compositor_host.cc140
-rw-r--r--chromium/content/browser/android/synchronous_compositor_host.h19
-rw-r--r--chromium/content/browser/android/web_contents_observer_proxy.cc24
-rw-r--r--chromium/content/browser/android/web_contents_observer_proxy.h4
-rw-r--r--chromium/content/browser/appcache/appcache_database.cc2
-rw-r--r--chromium/content/browser/appcache/appcache_database.h1
-rw-r--r--chromium/content/browser/appcache/appcache_disk_cache.cc2
-rw-r--r--chromium/content/browser/appcache/appcache_disk_cache.h2
-rw-r--r--chromium/content/browser/appcache/appcache_interceptor.cc11
-rw-r--r--chromium/content/browser/appcache/appcache_interceptor.h4
-rw-r--r--chromium/content/browser/appcache/appcache_internals_ui.cc2
-rw-r--r--chromium/content/browser/appcache/appcache_request_handler.cc2
-rw-r--r--chromium/content/browser/appcache/appcache_request_handler.h7
-rw-r--r--chromium/content/browser/appcache/appcache_response.cc30
-rw-r--r--chromium/content/browser/appcache/appcache_response.h40
-rw-r--r--chromium/content/browser/appcache/appcache_service_impl.cc5
-rw-r--r--chromium/content/browser/appcache/appcache_service_unittest.cc4
-rw-r--r--chromium/content/browser/appcache/appcache_storage_impl.cc24
-rw-r--r--chromium/content/browser/appcache/appcache_update_job.cc8
-rw-r--r--chromium/content/browser/appcache/appcache_update_job.h1
-rw-r--r--chromium/content/browser/appcache/appcache_url_request_job.cc6
-rw-r--r--chromium/content/browser/appcache/appcache_url_request_job.h1
-rw-r--r--chromium/content/browser/appcache/chrome_appcache_service_unittest.cc9
-rw-r--r--chromium/content/browser/appcache/mock_appcache_storage.cc8
-rw-r--r--chromium/content/browser/background_sync/background_sync.proto16
-rw-r--r--chromium/content/browser/background_sync/background_sync_browsertest.cc299
-rw-r--r--chromium/content/browser/background_sync/background_sync_context_impl.cc13
-rw-r--r--chromium/content/browser/background_sync/background_sync_context_impl.h12
-rw-r--r--chromium/content/browser/background_sync/background_sync_manager.cc808
-rw-r--r--chromium/content/browser/background_sync/background_sync_manager.h184
-rw-r--r--chromium/content/browser/background_sync/background_sync_manager_unittest.cc1048
-rw-r--r--chromium/content/browser/background_sync/background_sync_metrics.cc101
-rw-r--r--chromium/content/browser/background_sync/background_sync_metrics.h15
-rw-r--r--chromium/content/browser/background_sync/background_sync_power_observer.cc62
-rw-r--r--chromium/content/browser/background_sync/background_sync_power_observer.h51
-rw-r--r--chromium/content/browser/background_sync/background_sync_power_observer_unittest.cc72
-rw-r--r--chromium/content/browser/background_sync/background_sync_registration.cc62
-rw-r--r--chromium/content/browser/background_sync/background_sync_registration.h35
-rw-r--r--chromium/content/browser/background_sync/background_sync_registration_handle.cc53
-rw-r--r--chromium/content/browser/background_sync/background_sync_registration_handle.h95
-rw-r--r--chromium/content/browser/background_sync/background_sync_registration_options.cc4
-rw-r--r--chromium/content/browser/background_sync/background_sync_registration_options.h3
-rw-r--r--chromium/content/browser/background_sync/background_sync_service_impl.cc216
-rw-r--r--chromium/content/browser/background_sync/background_sync_service_impl.h46
-rw-r--r--chromium/content/browser/background_sync/background_sync_service_impl_unittest.cc257
-rw-r--r--chromium/content/browser/background_sync/background_sync_status.h3
-rw-r--r--chromium/content/browser/bad_message.h13
-rw-r--r--chromium/content/browser/battery_status/battery_monitor_integration_browsertest.cc7
-rw-r--r--chromium/content/browser/blob_storage/blob_async_builder_host_unittest.cc476
-rw-r--r--chromium/content/browser/blob_storage/blob_async_transport_request_builder_unittest.cc356
-rw-r--r--chromium/content/browser/blob_storage/blob_async_transport_strategy_unittest.cc458
-rw-r--r--chromium/content/browser/blob_storage/blob_dispatcher_host.cc370
-rw-r--r--chromium/content/browser/blob_storage/blob_dispatcher_host.h148
-rw-r--r--chromium/content/browser/blob_storage/blob_dispatcher_host_unittest.cc1199
-rw-r--r--chromium/content/browser/blob_storage/blob_storage_registry_unittest.cc27
-rw-r--r--chromium/content/browser/bluetooth/README.md24
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.cc65
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.h29
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_allowed_devices_map_unittest.cc355
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_blacklist.cc185
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_blacklist.h104
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_blacklist_unittest.cc398
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_dispatcher_host.cc849
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_dispatcher_host.h105
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_metrics.cc40
-rw-r--r--chromium/content/browser/bluetooth/bluetooth_metrics.h22
-rw-r--r--chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc156
-rw-r--r--chromium/content/browser/bluetooth/web_bluetooth_service_impl.h77
-rw-r--r--chromium/content/browser/browser_child_process_host_impl.cc80
-rw-r--r--chromium/content/browser/browser_child_process_host_impl.h9
-rw-r--r--chromium/content/browser/browser_context.cc66
-rw-r--r--chromium/content/browser/browser_main.cc1
-rw-r--r--chromium/content/browser/browser_main_loop.cc177
-rw-r--r--chromium/content/browser/browser_main_loop.h26
-rw-r--r--chromium/content/browser/browser_main_runner.cc95
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_embedder.cc4
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest.cc102
-rw-r--r--chromium/content/browser/browser_plugin/browser_plugin_guest.h26
-rw-r--r--chromium/content/browser/browser_process_sub_thread.cc2
-rw-r--r--chromium/content/browser/browser_process_sub_thread.h1
-rw-r--r--chromium/content/browser/browser_side_navigation_browsertest.cc46
-rw-r--r--chromium/content/browser/browser_thread_impl.cc36
-rw-r--r--chromium/content/browser/browsing_instance.cc53
-rw-r--r--chromium/content/browser/browsing_instance.h39
-rw-r--r--chromium/content/browser/cache_storage/cache_storage.cc353
-rw-r--r--chromium/content/browser/cache_storage/cache_storage.h79
-rw-r--r--chromium/content/browser/cache_storage/cache_storage.proto1
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.cc3
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.h16
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc2
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache.cc389
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache.h90
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc320
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_context_impl.cc18
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_context_impl.h8
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc62
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h30
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_manager.cc212
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_manager.h20
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc296
-rw-r--r--chromium/content/browser/cache_storage/cache_storage_unittest.cc26
-rw-r--r--chromium/content/browser/child_process_launcher.cc121
-rw-r--r--chromium/content/browser/child_process_launcher.h13
-rw-r--r--chromium/content/browser/child_process_security_policy_impl.cc10
-rw-r--r--chromium/content/browser/child_process_security_policy_unittest.cc9
-rw-r--r--chromium/content/browser/cocoa/system_hotkey_helper_mac.h1
-rw-r--r--chromium/content/browser/cocoa/system_hotkey_map.mm29
-rw-r--r--chromium/content/browser/cocoa/system_hotkey_map_unittest.mm10
-rw-r--r--chromium/content/browser/compositor/browser_compositor_output_surface.h2
-rw-r--r--chromium/content/browser/compositor/browser_compositor_overlay_candidate_validator_mac.mm9
-rw-r--r--chromium/content/browser/compositor/buffer_queue.cc25
-rw-r--r--chromium/content/browser/compositor/buffer_queue.h9
-rw-r--r--chromium/content/browser/compositor/buffer_queue_unittest.cc9
-rw-r--r--chromium/content/browser/compositor/gl_helper.cc (renamed from chromium/content/common/gpu/client/gl_helper.cc)365
-rw-r--r--chromium/content/browser/compositor/gl_helper.h (renamed from chromium/content/common/gpu/client/gl_helper.h)11
-rw-r--r--chromium/content/browser/compositor/gl_helper_benchmark.cc247
-rw-r--r--chromium/content/browser/compositor/gl_helper_readback_support.cc (renamed from chromium/content/common/gpu/client/gl_helper_readback_support.cc)23
-rw-r--r--chromium/content/browser/compositor/gl_helper_readback_support.h (renamed from chromium/content/common/gpu/client/gl_helper_readback_support.h)15
-rw-r--r--chromium/content/browser/compositor/gl_helper_scaling.cc (renamed from chromium/content/common/gpu/client/gl_helper_scaling.cc)149
-rw-r--r--chromium/content/browser/compositor/gl_helper_scaling.h (renamed from chromium/content/common/gpu/client/gl_helper_scaling.h)69
-rw-r--r--chromium/content/browser/compositor/gl_helper_unittest.cc (renamed from chromium/content/common/gpu/client/gl_helper_unittest.cc)752
-rw-r--r--chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc4
-rw-r--r--chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h7
-rw-r--r--chromium/content/browser/compositor/gpu_process_transport_factory.cc125
-rw-r--r--chromium/content/browser/compositor/gpu_process_transport_factory.h7
-rw-r--r--chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc4
-rw-r--r--chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h9
-rw-r--r--chromium/content/browser/compositor/owned_mailbox.cc2
-rw-r--r--chromium/content/browser/compositor/reflector_texture.cc2
-rw-r--r--chromium/content/browser/compositor/software_output_device_mac.h4
-rw-r--r--chromium/content/browser/compositor/software_output_device_mac.mm4
-rw-r--r--chromium/content/browser/compositor/software_output_device_win.cc10
-rw-r--r--chromium/content/browser/compositor/software_output_device_win.h4
-rw-r--r--chromium/content/browser/compositor/surface_utils.cc177
-rw-r--r--chromium/content/browser/compositor/surface_utils.h12
-rw-r--r--chromium/content/browser/cross_site_transfer_browsertest.cc6
-rw-r--r--chromium/content/browser/database_util_unittest.cc27
-rw-r--r--chromium/content/browser/device_monitor_mac.h51
-rw-r--r--chromium/content/browser/device_monitor_mac.mm568
-rw-r--r--chromium/content/browser/device_monitor_udev.cc89
-rw-r--r--chromium/content/browser/device_monitor_udev.h44
-rw-r--r--chromium/content/browser/device_sensors/data_fetcher_shared_memory_mac.cc1
-rw-r--r--chromium/content/browser/device_sensors/data_fetcher_shared_memory_win.cc3
-rw-r--r--chromium/content/browser/device_sensors/device_light_message_filter.cc43
-rw-r--r--chromium/content/browser/device_sensors/device_light_message_filter.h12
-rw-r--r--chromium/content/browser/device_sensors/device_motion_message_filter.cc45
-rw-r--r--chromium/content/browser/device_sensors/device_motion_message_filter.h12
-rw-r--r--chromium/content/browser/device_sensors/device_orientation_absolute_message_filter.cc42
-rw-r--r--chromium/content/browser/device_sensors/device_orientation_absolute_message_filter.h13
-rw-r--r--chromium/content/browser/device_sensors/device_orientation_message_filter.cc47
-rw-r--r--chromium/content/browser/device_sensors/device_orientation_message_filter.h12
-rw-r--r--chromium/content/browser/device_sensors/device_sensor_message_filter.cc44
-rw-r--r--chromium/content/browser/device_sensors/device_sensor_message_filter.h40
-rw-r--r--chromium/content/browser/device_sensors/sensor_manager_android.cc1
-rw-r--r--chromium/content/browser/device_sensors/sensor_manager_chromeos.cc1
-rw-r--r--chromium/content/browser/device_sensors/sensor_manager_chromeos_unittest.cc1
-rw-r--r--chromium/content/browser/devtools/browser_devtools_agent_host.cc5
-rw-r--r--chromium/content/browser/devtools/devtools_agent_host_impl.cc7
-rw-r--r--chromium/content/browser/devtools/devtools_agent_host_impl.h2
-rw-r--r--chromium/content/browser/devtools/devtools_frame_trace_recorder.cc2
-rw-r--r--chromium/content/browser/devtools/devtools_frame_trace_recorder.h1
-rw-r--r--chromium/content/browser/devtools/devtools_manager.h1
-rw-r--r--chromium/content/browser/devtools/devtools_netlog_observer.cc4
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc32
-rw-r--r--chromium/content/browser/devtools/protocol/devtools_protocol_client.h1
-rwxr-xr-xchromium/content/browser/devtools/protocol/devtools_protocol_handler_generator.py1
-rw-r--r--chromium/content/browser/devtools/protocol/emulation_handler.cc43
-rw-r--r--chromium/content/browser/devtools/protocol/emulation_handler.h26
-rw-r--r--chromium/content/browser/devtools/protocol/input_handler.cc11
-rw-r--r--chromium/content/browser/devtools/protocol/inspector_handler.cc5
-rw-r--r--chromium/content/browser/devtools/protocol/inspector_handler.h1
-rw-r--r--chromium/content/browser/devtools/protocol/memory_handler.cc6
-rw-r--r--chromium/content/browser/devtools/protocol/network_handler.cc34
-rw-r--r--chromium/content/browser/devtools/protocol/page_handler.cc15
-rw-r--r--chromium/content/browser/devtools/protocol/page_handler.h3
-rw-r--r--chromium/content/browser/devtools/protocol/service_worker_handler.cc80
-rw-r--r--chromium/content/browser/devtools/protocol/service_worker_handler.h6
-rw-r--r--chromium/content/browser/devtools/protocol/system_info_handler.cc7
-rw-r--r--chromium/content/browser/devtools/protocol/tethering_handler.cc9
-rw-r--r--chromium/content/browser/devtools/protocol/tracing_handler.cc118
-rw-r--r--chromium/content/browser/devtools/protocol/tracing_handler.h16
-rw-r--r--chromium/content/browser/devtools/protocol/tracing_handler_unittest.cc73
-rw-r--r--chromium/content/browser/devtools/render_frame_devtools_agent_host.cc205
-rw-r--r--chromium/content/browser/devtools/render_frame_devtools_agent_host.h16
-rw-r--r--chromium/content/browser/devtools/service_worker_devtools_agent_host.cc4
-rw-r--r--chromium/content/browser/devtools/service_worker_devtools_agent_host.h1
-rw-r--r--chromium/content/browser/devtools/service_worker_devtools_manager.cc12
-rw-r--r--chromium/content/browser/devtools/service_worker_devtools_manager.h6
-rw-r--r--chromium/content/browser/devtools/shared_worker_devtools_manager_unittest.cc8
-rw-r--r--chromium/content/browser/devtools/site_per_process_devtools_browsertest.cc65
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_browsertest.cc1
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc194
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_context_wrapper.h20
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_host.cc2
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_host.h1
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_namespace.cc2
-rw-r--r--chromium/content/browser/dom_storage/dom_storage_namespace.h1
-rw-r--r--chromium/content/browser/dom_storage/session_storage_database.cc3
-rw-r--r--chromium/content/browser/download/OWNERS2
-rw-r--r--chromium/content/browser/download/base_file.cc201
-rw-r--r--chromium/content/browser/download/base_file.h190
-rw-r--r--chromium/content/browser/download/base_file_linux.cc7
-rw-r--r--chromium/content/browser/download/base_file_mac.cc9
-rw-r--r--chromium/content/browser/download/base_file_unittest.cc459
-rw-r--r--chromium/content/browser/download/base_file_win.cc11
-rw-r--r--chromium/content/browser/download/docs/save-page-as.md137
-rw-r--r--chromium/content/browser/download/download_browsertest.cc999
-rw-r--r--chromium/content/browser/download/download_create_info.cc21
-rw-r--r--chromium/content/browser/download/download_create_info.h50
-rw-r--r--chromium/content/browser/download/download_destination_observer.h (renamed from chromium/content/public/browser/download_destination_observer.h)19
-rw-r--r--chromium/content/browser/download/download_file.h29
-rw-r--r--chromium/content/browser/download/download_file_factory.cc13
-rw-r--r--chromium/content/browser/download/download_file_factory.h10
-rw-r--r--chromium/content/browser/download/download_file_impl.cc158
-rw-r--r--chromium/content/browser/download/download_file_impl.h66
-rw-r--r--chromium/content/browser/download/download_file_unittest.cc221
-rw-r--r--chromium/content/browser/download/download_interrupt_reasons_impl.cc3
-rw-r--r--chromium/content/browser/download/download_item_factory.h2
-rw-r--r--chromium/content/browser/download/download_item_impl.cc1061
-rw-r--r--chromium/content/browser/download/download_item_impl.h392
-rw-r--r--chromium/content/browser/download/download_item_impl_delegate.cc5
-rw-r--r--chromium/content/browser/download/download_item_impl_delegate.h5
-rw-r--r--chromium/content/browser/download/download_item_impl_unittest.cc1180
-rw-r--r--chromium/content/browser/download/download_manager_impl.cc305
-rw-r--r--chromium/content/browser/download/download_manager_impl.h35
-rw-r--r--chromium/content/browser/download/download_manager_impl_unittest.cc179
-rw-r--r--chromium/content/browser/download/download_net_log_parameters.cc9
-rw-r--r--chromium/content/browser/download/download_net_log_parameters.h3
-rw-r--r--chromium/content/browser/download/download_request_core.cc527
-rw-r--r--chromium/content/browser/download/download_request_core.h88
-rw-r--r--chromium/content/browser/download/download_request_handle.cc86
-rw-r--r--chromium/content/browser/download/download_request_handle.h29
-rw-r--r--chromium/content/browser/download/download_resource_handler.cc105
-rw-r--r--chromium/content/browser/download/download_resource_handler.h25
-rw-r--r--chromium/content/browser/download/drag_download_file.cc4
-rw-r--r--chromium/content/browser/download/mhtml_generation_manager.cc5
-rw-r--r--chromium/content/browser/download/mock_download_file.h9
-rw-r--r--chromium/content/browser/download/save_file.cc23
-rw-r--r--chromium/content/browser/download/save_file.h1
-rw-r--r--chromium/content/browser/download/save_file_manager.cc26
-rw-r--r--chromium/content/browser/download/save_file_manager.h14
-rw-r--r--chromium/content/browser/download/save_file_resource_handler.cc2
-rw-r--r--chromium/content/browser/download/save_item.cc4
-rw-r--r--chromium/content/browser/download/save_item.h8
-rw-r--r--chromium/content/browser/download/save_package.cc121
-rw-r--r--chromium/content/browser/download/save_package.h25
-rw-r--r--chromium/content/browser/download/save_package_unittest.cc3
-rw-r--r--chromium/content/browser/download/save_types.cc3
-rw-r--r--chromium/content/browser/download/save_types.h8
-rw-r--r--chromium/content/browser/download/url_downloader.cc115
-rw-r--r--chromium/content/browser/download/url_downloader.h48
-rw-r--r--chromium/content/browser/fileapi/blob_reader_unittest.cc54
-rw-r--r--chromium/content/browser/fileapi/blob_storage_context_unittest.cc274
-rw-r--r--chromium/content/browser/fileapi/blob_storage_host.cc116
-rw-r--r--chromium/content/browser/fileapi/blob_storage_host.h75
-rw-r--r--chromium/content/browser/fileapi/blob_url_request_job_unittest.cc2
-rw-r--r--chromium/content/browser/fileapi/copy_or_move_operation_delegate_unittest.cc4
-rw-r--r--chromium/content/browser/fileapi/dragged_file_util_unittest.cc1
-rw-r--r--chromium/content/browser/fileapi/file_system_dir_url_request_job_unittest.cc11
-rw-r--r--chromium/content/browser/fileapi/file_system_quota_client_unittest.cc1
-rw-r--r--chromium/content/browser/fileapi/file_system_url_request_job_unittest.cc1
-rw-r--r--chromium/content/browser/fileapi/fileapi_message_filter.cc116
-rw-r--r--chromium/content/browser/fileapi/fileapi_message_filter.h25
-rw-r--r--chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc2
-rw-r--r--chromium/content/browser/fileapi/local_file_util_unittest.cc1
-rw-r--r--chromium/content/browser/fileapi/native_file_util_unittest.cc1
-rw-r--r--chromium/content/browser/fileapi/recursive_operation_delegate_unittest.cc1
-rw-r--r--chromium/content/browser/fileapi/sandbox_origin_database_unittest.cc1
-rw-r--r--chromium/content/browser/fileapi/upload_file_system_file_element_reader.h1
-rw-r--r--chromium/content/browser/frame_host/OWNERS1
-rw-r--r--chromium/content/browser/frame_host/PRESUBMIT.py53
-rw-r--r--chromium/content/browser/frame_host/cross_process_frame_connector.cc145
-rw-r--r--chromium/content/browser/frame_host/cross_process_frame_connector.h40
-rw-r--r--chromium/content/browser/frame_host/debug_urls.cc26
-rw-r--r--chromium/content/browser/frame_host/frame_mojo_shell.cc42
-rw-r--r--chromium/content/browser/frame_host/frame_mojo_shell.h34
-rw-r--r--chromium/content/browser/frame_host/frame_navigation_entry.cc19
-rw-r--r--chromium/content/browser/frame_host/frame_navigation_entry.h6
-rw-r--r--chromium/content/browser/frame_host/frame_tree.cc230
-rw-r--r--chromium/content/browser/frame_host/frame_tree.h66
-rw-r--r--chromium/content/browser/frame_host/frame_tree_browsertest.cc31
-rw-r--r--chromium/content/browser/frame_host/frame_tree_node.cc156
-rw-r--r--chromium/content/browser/frame_host/frame_tree_node.h84
-rw-r--r--chromium/content/browser/frame_host/frame_tree_unittest.cc166
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl.cc81
-rw-r--r--chromium/content/browser/frame_host/interstitial_page_impl.h16
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_android.cc4
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_android.h6
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_delegate.h5
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl.cc177
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl.h26
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc424
-rw-r--r--chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc403
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl.cc56
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl.h7
-rw-r--r--chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc30
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl.cc146
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl.h76
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc560
-rw-r--r--chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc170
-rw-r--r--chromium/content/browser/frame_host/navigation_request.cc147
-rw-r--r--chromium/content/browser/frame_host/navigation_request.h36
-rw-r--r--chromium/content/browser/frame_host/navigator.cc5
-rw-r--r--chromium/content/browser/frame_host/navigator.h8
-rw-r--r--chromium/content/browser/frame_host/navigator_impl.cc395
-rw-r--r--chromium/content/browser/frame_host/navigator_impl.h24
-rw-r--r--chromium/content/browser/frame_host/navigator_impl_unittest.cc168
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_delegate.cc7
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_delegate.h11
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_factory.cc6
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_factory.h4
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl.cc650
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_impl.h225
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager.cc924
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager.h125
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc395
-rw-r--r--chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc438
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter.cc188
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter.h26
-rw-r--r--chromium/content/browser/frame_host/render_frame_message_filter_browsertest.cc67
-rw-r--r--chromium/content/browser/frame_host/render_frame_proxy_host.cc35
-rw-r--r--chromium/content/browser/frame_host/render_frame_proxy_host.h4
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_child_frame.cc234
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_child_frame.h66
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc47
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest.cc150
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest.h23
-rw-r--r--chromium/content/browser/frame_host/render_widget_host_view_guest_unittest.cc89
-rw-r--r--chromium/content/browser/frame_host/traced_frame_tree_node.cc69
-rw-r--r--chromium/content/browser/frame_host/traced_frame_tree_node.h36
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc14
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h8
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc26
-rw-r--r--chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.h7
-rw-r--r--chromium/content/browser/gamepad/gamepad_provider.cc3
-rw-r--r--chromium/content/browser/gamepad/gamepad_provider.h1
-rw-r--r--chromium/content/browser/geofencing/geofencing_manager.cc8
-rw-r--r--chromium/content/browser/geofencing/geofencing_service.h1
-rw-r--r--chromium/content/browser/geolocation/fake_access_token_store.cc10
-rw-r--r--chromium/content/browser/geolocation/fake_access_token_store.h11
-rw-r--r--chromium/content/browser/geolocation/geolocation_provider_impl.cc24
-rw-r--r--chromium/content/browser/geolocation/geolocation_provider_impl.h10
-rw-r--r--chromium/content/browser/geolocation/geolocation_provider_impl_unittest.cc8
-rw-r--r--chromium/content/browser/geolocation/geolocation_service_context.cc2
-rw-r--r--chromium/content/browser/geolocation/geolocation_service_context.h6
-rw-r--r--chromium/content/browser/geolocation/geolocation_service_impl.cc5
-rw-r--r--chromium/content/browser/geolocation/geolocation_service_impl.h20
-rw-r--r--chromium/content/browser/geolocation/location_api_adapter_android.cc2
-rw-r--r--chromium/content/browser/geolocation/location_api_adapter_android.h23
-rw-r--r--chromium/content/browser/geolocation/location_arbitrator.h2
-rw-r--r--chromium/content/browser/geolocation/location_arbitrator_impl.cc32
-rw-r--r--chromium/content/browser/geolocation/location_arbitrator_impl.h6
-rw-r--r--chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc4
-rw-r--r--chromium/content/browser/geolocation/mock_location_arbitrator.cc2
-rw-r--r--chromium/content/browser/geolocation/mock_location_arbitrator.h2
-rw-r--r--chromium/content/browser/geolocation/network_location_provider.cc18
-rw-r--r--chromium/content/browser/geolocation/network_location_provider.h2
-rw-r--r--chromium/content/browser/geolocation/network_location_provider_unittest.cc6
-rw-r--r--chromium/content/browser/geolocation/network_location_request.cc58
-rw-r--r--chromium/content/browser/geolocation/network_location_request.h6
-rw-r--r--chromium/content/browser/geolocation/wifi_data.cc2
-rw-r--r--chromium/content/browser/geolocation/wifi_data.h1
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider.cc17
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider.h16
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_chromeos.cc18
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_chromeos.h1
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_chromeos_unittest.cc17
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_common.cc2
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_common_unittest.cc80
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_corewlan_mac.mm3
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_linux_unittest.cc9
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_manager.h1
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_win.cc1
-rw-r--r--chromium/content/browser/geolocation/wifi_data_provider_win_unittest.cc5
-rw-r--r--chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc83
-rw-r--r--chromium/content/browser/gpu/browser_gpu_channel_host_factory.h25
-rw-r--r--chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc77
-rw-r--r--chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h12
-rw-r--r--chromium/content/browser/gpu/compositor_util.cc42
-rw-r--r--chromium/content/browser/gpu/compositor_util.h7
-rw-r--r--chromium/content/browser/gpu/gpu_arc_video_service_host.cc76
-rw-r--r--chromium/content/browser/gpu/gpu_arc_video_service_host.h54
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl.cc29
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl.h22
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private.cc224
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private.h38
-rw-r--r--chromium/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc66
-rw-r--r--chromium/content/browser/gpu/gpu_internals_ui.cc51
-rw-r--r--chromium/content/browser/gpu/gpu_ipc_browsertests.cc117
-rw-r--r--chromium/content/browser/gpu/gpu_process_host.cc245
-rw-r--r--chromium/content/browser/gpu/gpu_process_host.h77
-rw-r--r--chromium/content/browser/gpu/gpu_process_host_ui_shim.cc18
-rw-r--r--chromium/content/browser/gpu/gpu_process_host_ui_shim.h19
-rw-r--r--chromium/content/browser/gpu/gpu_surface_tracker.cc55
-rw-r--r--chromium/content/browser/gpu/gpu_surface_tracker.h25
-rw-r--r--chromium/content/browser/histogram_controller.cc10
-rw-r--r--chromium/content/browser/host_zoom_map_impl.cc2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store.cc117
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store.h11
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_backing_store_unittest.cc33
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_browsertest.cc23
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_callbacks.cc5
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_context_impl.cc183
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_context_impl.h34
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database.cc63
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database.h3
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database_callbacks.cc2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_database_unittest.cc38
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc217
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h15
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory_impl.cc1
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc36
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc3
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_fake_backing_store.h3
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_internals_ui.cc9
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc167
-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.cc4
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_metadata.cc7
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_metadata.h11
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_pending_connection.cc3
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_pending_connection.h1
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_quota_client.cc31
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc5
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc2
-rw-r--r--chromium/content/browser/indexed_db/indexed_db_unittest.cc47
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_database.cc32
-rw-r--r--chromium/content/browser/indexed_db/leveldb/leveldb_database.h11
-rw-r--r--chromium/content/browser/indexed_db/leveldb_coding_scheme.md323
-rw-r--r--chromium/content/browser/leveldb_wrapper_impl.cc143
-rw-r--r--chromium/content/browser/leveldb_wrapper_impl.h68
-rw-r--r--chromium/content/browser/loader/async_resource_handler.cc223
-rw-r--r--chromium/content/browser/loader/async_resource_handler.h11
-rw-r--r--chromium/content/browser/loader/async_resource_handler_browsertest.cc10
-rw-r--r--chromium/content/browser/loader/async_revalidation_driver.cc4
-rw-r--r--chromium/content/browser/loader/async_revalidation_driver.h10
-rw-r--r--chromium/content/browser/loader/async_revalidation_driver_unittest.cc24
-rw-r--r--chromium/content/browser/loader/async_revalidation_manager.cc6
-rw-r--r--chromium/content/browser/loader/async_revalidation_manager.h9
-rw-r--r--chromium/content/browser/loader/async_revalidation_manager_browsertest.cc43
-rw-r--r--chromium/content/browser/loader/async_revalidation_manager_unittest.cc15
-rw-r--r--chromium/content/browser/loader/cross_site_resource_handler.cc7
-rw-r--r--chromium/content/browser/loader/cross_site_resource_handler.h2
-rw-r--r--chromium/content/browser/loader/cross_site_resource_handler_browsertest.cc19
-rw-r--r--chromium/content/browser/loader/detachable_resource_handler.cc2
-rw-r--r--chromium/content/browser/loader/detachable_resource_handler.h9
-rw-r--r--chromium/content/browser/loader/global_routing_id.h29
-rw-r--r--chromium/content/browser/loader/layered_resource_handler.cc2
-rw-r--r--chromium/content/browser/loader/layered_resource_handler.h7
-rw-r--r--chromium/content/browser/loader/mime_type_resource_handler.cc94
-rw-r--r--chromium/content/browser/loader/mime_type_resource_handler.h9
-rw-r--r--chromium/content/browser/loader/mime_type_resource_handler_unittest.cc116
-rw-r--r--chromium/content/browser/loader/navigation_resource_handler.cc11
-rw-r--r--chromium/content/browser/loader/navigation_resource_handler.h3
-rw-r--r--chromium/content/browser/loader/navigation_resource_throttle.cc26
-rw-r--r--chromium/content/browser/loader/navigation_url_loader.cc6
-rw-r--r--chromium/content/browser/loader/navigation_url_loader.h10
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_delegate.h5
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_factory.h7
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl.cc13
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl.h11
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl_core.cc11
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_impl_core.h10
-rw-r--r--chromium/content/browser/loader/navigation_url_loader_unittest.cc77
-rw-r--r--chromium/content/browser/loader/power_save_block_resource_throttle.h4
-rw-r--r--chromium/content/browser/loader/redirect_to_file_resource_handler.cc8
-rw-r--r--chromium/content/browser/loader/redirect_to_file_resource_handler.h7
-rw-r--r--chromium/content/browser/loader/resource_buffer.cc12
-rw-r--r--chromium/content/browser/loader/resource_buffer.h9
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc14
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.cc694
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_impl.h173
-rw-r--r--chromium/content/browser/loader/resource_dispatcher_host_unittest.cc553
-rw-r--r--chromium/content/browser/loader/resource_loader.cc60
-rw-r--r--chromium/content/browser/loader/resource_loader.h36
-rw-r--r--chromium/content/browser/loader/resource_loader_unittest.cc93
-rw-r--r--chromium/content/browser/loader/resource_message_filter.h3
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.cc17
-rw-r--r--chromium/content/browser/loader/resource_request_info_impl.h2
-rw-r--r--chromium/content/browser/loader/resource_scheduler.cc447
-rw-r--r--chromium/content/browser/loader/resource_scheduler.h106
-rw-r--r--chromium/content/browser/loader/resource_scheduler_unittest.cc1908
-rw-r--r--chromium/content/browser/loader/stream_resource_handler.h3
-rw-r--r--chromium/content/browser/loader/temporary_file_stream.cc15
-rw-r--r--chromium/content/browser/loader/temporary_file_stream.h5
-rw-r--r--chromium/content/browser/loader/temporary_file_stream_unittest.cc4
-rw-r--r--chromium/content/browser/loader/throttling_resource_handler.cc2
-rw-r--r--chromium/content/browser/loader/throttling_resource_handler.h2
-rw-r--r--chromium/content/browser/loader/upload_data_stream_builder.cc17
-rw-r--r--chromium/content/browser/loader/upload_data_stream_builder.h5
-rw-r--r--chromium/content/browser/loader/upload_data_stream_builder_unittest.cc32
-rw-r--r--chromium/content/browser/mach_broker_mac.h62
-rw-r--r--chromium/content/browser/mach_broker_mac.mm173
-rw-r--r--chromium/content/browser/mach_broker_mac_unittest.cc112
-rw-r--r--chromium/content/browser/media/OWNERS11
-rw-r--r--chromium/content/browser/media/android/OWNERS3
-rw-r--r--chromium/content/browser/media/android/browser_demuxer_android.cc4
-rw-r--r--chromium/content/browser/media/android/browser_demuxer_android.h2
-rw-r--r--chromium/content/browser/media/android/browser_media_player_manager.cc140
-rw-r--r--chromium/content/browser/media/android/browser_media_player_manager.h37
-rw-r--r--chromium/content/browser/media/android/browser_media_session_manager.cc23
-rw-r--r--chromium/content/browser/media/android/browser_media_session_manager.h2
-rw-r--r--chromium/content/browser/media/android/browser_surface_view_manager.cc86
-rw-r--r--chromium/content/browser/media/android/browser_surface_view_manager.h54
-rw-r--r--chromium/content/browser/media/android/media_resource_getter_impl.cc4
-rw-r--r--chromium/content/browser/media/android/media_session.h181
-rw-r--r--chromium/content/browser/media/android/media_web_contents_observer_android.cc102
-rw-r--r--chromium/content/browser/media/android/media_web_contents_observer_android.h48
-rw-r--r--chromium/content/browser/media/android/provision_fetcher_impl.cc2
-rw-r--r--chromium/content/browser/media/android/provision_fetcher_impl.h10
-rw-r--r--chromium/content/browser/media/android/url_provision_fetcher.cc5
-rw-r--r--chromium/content/browser/media/android/url_provision_fetcher.h2
-rw-r--r--chromium/content/browser/media/audible_metrics.cc3
-rw-r--r--chromium/content/browser/media/audible_metrics.h6
-rw-r--r--chromium/content/browser/media/audible_metrics_unittest.cc61
-rw-r--r--chromium/content/browser/media/audio_stream_monitor_unittest.cc2
-rw-r--r--chromium/content/browser/media/capture/audio_mirroring_manager.cc3
-rw-r--r--chromium/content/browser/media/capture/audio_mirroring_manager.h1
-rw-r--r--chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc40
-rw-r--r--chromium/content/browser/media/capture/aura_window_capture_machine.cc171
-rw-r--r--chromium/content/browser/media/capture/aura_window_capture_machine.h61
-rw-r--r--chromium/content/browser/media/capture/cursor_renderer.h2
-rw-r--r--chromium/content/browser/media/capture/cursor_renderer_aura.cc56
-rw-r--r--chromium/content/browser/media/capture/cursor_renderer_aura.h13
-rw-r--r--chromium/content/browser/media/capture/cursor_renderer_aura_unittest.cc55
-rw-r--r--chromium/content/browser/media/capture/cursor_renderer_mac.h48
-rw-r--r--chromium/content/browser/media/capture/cursor_renderer_mac.mm189
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device.cc104
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device.h14
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_aura.cc13
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_aura.h9
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_aura_unittest.cc33
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_uma_types.h3
-rw-r--r--chromium/content/browser/media/capture/desktop_capture_device_unittest.cc65
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_input_stream.cc28
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc4
-rw-r--r--chromium/content/browser/media/capture/web_contents_audio_muter.cc12
-rw-r--r--chromium/content/browser/media/capture/web_contents_tracker.cc6
-rw-r--r--chromium/content/browser/media/capture/web_contents_video_capture_device.cc260
-rw-r--r--chromium/content/browser/media/capture/web_contents_video_capture_device.h7
-rw-r--r--chromium/content/browser/media/capture/web_contents_video_capture_device_unittest.cc338
-rw-r--r--chromium/content/browser/media/capture/window_activity_tracker.cc54
-rw-r--r--chromium/content/browser/media/capture/window_activity_tracker.h33
-rw-r--r--chromium/content/browser/media/capture/window_activity_tracker_aura.cc39
-rw-r--r--chromium/content/browser/media/capture/window_activity_tracker_aura.h11
-rw-r--r--chromium/content/browser/media/capture/window_activity_tracker_mac.h62
-rw-r--r--chromium/content/browser/media/capture/window_activity_tracker_mac.mm82
-rw-r--r--chromium/content/browser/media/cdm/browser_cdm_manager.cc43
-rw-r--r--chromium/content/browser/media/cdm/browser_cdm_manager.h23
-rw-r--r--chromium/content/browser/media/encrypted_media_browsertest.cc20
-rw-r--r--chromium/content/browser/media/media_browsertest.cc10
-rw-r--r--chromium/content/browser/media/media_canplaytype_browsertest.cc791
-rw-r--r--chromium/content/browser/media/media_internals.cc51
-rw-r--r--chromium/content/browser/media/media_internals.h5
-rw-r--r--chromium/content/browser/media/media_internals_proxy.cc2
-rw-r--r--chromium/content/browser/media/media_internals_proxy.h2
-rw-r--r--chromium/content/browser/media/media_internals_unittest.cc12
-rw-r--r--chromium/content/browser/media/media_web_contents_observer.cc118
-rw-r--r--chromium/content/browser/media/media_web_contents_observer.h41
-rw-r--r--chromium/content/browser/media/midi_host.cc10
-rw-r--r--chromium/content/browser/media/midi_host.h2
-rw-r--r--chromium/content/browser/media/midi_host_unittest.cc2
-rw-r--r--chromium/content/browser/media/session/OWNERS2
-rw-r--r--chromium/content/browser/media/session/media_session.cc (renamed from chromium/content/browser/media/android/media_session.cc)145
-rw-r--r--chromium/content/browser/media/session/media_session.h212
-rw-r--r--chromium/content/browser/media/session/media_session_browsertest.cc (renamed from chromium/content/browser/media/android/media_session_browsertest.cc)380
-rw-r--r--chromium/content/browser/media/session/media_session_controller.cc109
-rw-r--r--chromium/content/browser/media/session/media_session_controller.h71
-rw-r--r--chromium/content/browser/media/session/media_session_controller_unittest.cc214
-rw-r--r--chromium/content/browser/media/session/media_session_controllers_manager.cc94
-rw-r--r--chromium/content/browser/media/session/media_session_controllers_manager.h63
-rw-r--r--chromium/content/browser/media/session/media_session_delegate.h26
-rw-r--r--chromium/content/browser/media/session/media_session_delegate_android.cc95
-rw-r--r--chromium/content/browser/media/session/media_session_delegate_android.h59
-rw-r--r--chromium/content/browser/media/session/media_session_delegate_android_browsertest.cc65
-rw-r--r--chromium/content/browser/media/session/media_session_delegate_default.cc62
-rw-r--r--chromium/content/browser/media/session/media_session_delegate_default_browsertest.cc49
-rw-r--r--chromium/content/browser/media/session/media_session_observer.h (renamed from chromium/content/browser/media/android/media_session_observer.h)11
-rw-r--r--chromium/content/browser/media/session/media_session_uma_helper.cc (renamed from chromium/content/browser/media/android/media_session_uma_helper.cc)4
-rw-r--r--chromium/content/browser/media/session/media_session_uma_helper.h (renamed from chromium/content/browser/media/android/media_session_uma_helper.h)14
-rw-r--r--chromium/content/browser/media/session/media_session_uma_helper_unittest.cc (renamed from chromium/content/browser/media/android/media_session_uma_helper_unittest.cc)36
-rw-r--r--chromium/content/browser/media/session/media_session_visibility_browsertest.cc266
-rw-r--r--chromium/content/browser/media/session/mock_media_session_observer.cc70
-rw-r--r--chromium/content/browser/media/session/mock_media_session_observer.h59
-rw-r--r--chromium/content/browser/media/webrtc/OWNERS5
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_audio_debug_recordings_browsertest.cc (renamed from chromium/content/browser/media/webrtc_audio_debug_recordings_browsertest.cc)4
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_browsertest.cc (renamed from chromium/content/browser/media/webrtc_browsertest.cc)0
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_getusermedia_browsertest.cc (renamed from chromium/content/browser/media/webrtc_getusermedia_browsertest.cc)7
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_identity_store.cc (renamed from chromium/content/browser/media/webrtc_identity_store.cc)6
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_identity_store.h (renamed from chromium/content/browser/media/webrtc_identity_store.h)6
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_identity_store_backend.cc (renamed from chromium/content/browser/media/webrtc_identity_store_backend.cc)11
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_identity_store_backend.h (renamed from chromium/content/browser/media/webrtc_identity_store_backend.h)11
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_identity_store_unittest.cc (renamed from chromium/content/browser/media/webrtc_identity_store_unittest.cc)10
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_internals.cc (renamed from chromium/content/browser/media/webrtc_internals.cc)132
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_internals.h (renamed from chromium/content/browser/media/webrtc_internals.h)70
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_internals_browsertest.cc (renamed from chromium/content/browser/media/webrtc_internals_browsertest.cc)4
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_internals_message_handler.cc (renamed from chromium/content/browser/media/webrtc_internals_message_handler.cc)4
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_internals_message_handler.h (renamed from chromium/content/browser/media/webrtc_internals_message_handler.h)8
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_internals_ui.cc (renamed from chromium/content/browser/media/webrtc_internals_ui.cc)4
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_internals_ui.h (renamed from chromium/content/browser/media/webrtc_internals_ui.h)6
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_internals_ui_observer.h (renamed from chromium/content/browser/media/webrtc_internals_ui_observer.h)6
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_internals_unittest.cc (renamed from chromium/content/browser/media/webrtc_internals_unittest.cc)214
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_ip_permissions_browsertest.cc (renamed from chromium/content/browser/media/webrtc_ip_permissions_browsertest.cc)0
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_media_recorder_browsertest.cc (renamed from chromium/content/browser/media/webrtc_media_recorder_browsertest.cc)0
-rw-r--r--chromium/content/browser/media/webrtc/webrtc_webcam_browsertest.cc (renamed from chromium/content/browser/media/webrtc_webcam_browsertest.cc)0
-rw-r--r--chromium/content/browser/memory/memory_message_filter.cc7
-rw-r--r--chromium/content/browser/memory/memory_message_filter.h4
-rw-r--r--chromium/content/browser/memory/memory_pressure_controller_impl.cc (renamed from chromium/content/browser/memory/memory_pressure_controller.cc)33
-rw-r--r--chromium/content/browser/memory/memory_pressure_controller_impl.h (renamed from chromium/content/browser/memory/memory_pressure_controller.h)44
-rw-r--r--chromium/content/browser/memory/memory_pressure_controller_impl_browsertest.cc (renamed from chromium/content/browser/memory/memory_pressure_controller_browsertest.cc)16
-rw-r--r--chromium/content/browser/message_port_service.cc11
-rw-r--r--chromium/content/browser/message_port_service.h3
-rw-r--r--chromium/content/browser/mojo/OWNERS13
-rw-r--r--chromium/content/browser/mojo/constants.cc19
-rw-r--r--chromium/content/browser/mojo/constants.h15
-rw-r--r--chromium/content/browser/mojo/mojo_app_connection_impl.cc28
-rw-r--r--chromium/content/browser/mojo/mojo_app_connection_impl.h16
-rw-r--r--chromium/content/browser/mojo/mojo_application_host.cc55
-rw-r--r--chromium/content/browser/mojo/mojo_application_host.h11
-rw-r--r--chromium/content/browser/mojo/mojo_child_connection.cc137
-rw-r--r--chromium/content/browser/mojo/mojo_child_connection.h36
-rw-r--r--chromium/content/browser/mojo/mojo_shell_client_host.cc219
-rw-r--r--chromium/content/browser/mojo/mojo_shell_client_host.h48
-rw-r--r--chromium/content/browser/mojo/mojo_shell_context.cc269
-rw-r--r--chromium/content/browser/mojo/mojo_shell_context.h53
-rw-r--r--chromium/content/browser/mojo/renderer_capability_filter.cc22
-rw-r--r--chromium/content/browser/mojo/service_registrar_android.cc2
-rw-r--r--chromium/content/browser/mojo/service_registry_android.h56
-rw-r--r--chromium/content/browser/mojo_shell_browsertest.cc33
-rw-r--r--chromium/content/browser/navigator_connect/OWNERS1
-rw-r--r--chromium/content/browser/navigator_connect/navigator_connect_context_impl.cc266
-rw-r--r--chromium/content/browser/navigator_connect/navigator_connect_context_impl.h133
-rw-r--r--chromium/content/browser/navigator_connect/service_port_service_impl.cc132
-rw-r--r--chromium/content/browser/navigator_connect/service_port_service_impl.h85
-rw-r--r--chromium/content/browser/net/quota_policy_cookie_store.cc18
-rw-r--r--chromium/content/browser/net/quota_policy_cookie_store_unittest.cc8
-rw-r--r--chromium/content/browser/notifications/notification_database.h2
-rw-r--r--chromium/content/browser/notifications/notification_database_data.proto16
-rw-r--r--chromium/content/browser/notifications/notification_database_data_conversions.cc49
-rw-r--r--chromium/content/browser/notifications/notification_database_data_unittest.cc73
-rw-r--r--chromium/content/browser/notifications/notification_event_dispatcher_impl.cc277
-rw-r--r--chromium/content/browser/notifications/notification_event_dispatcher_impl.h12
-rw-r--r--chromium/content/browser/notifications/notification_message_filter.cc55
-rw-r--r--chromium/content/browser/notifications/notification_message_filter.h13
-rw-r--r--chromium/content/browser/permissions/permission_service_context.cc2
-rw-r--r--chromium/content/browser/permissions/permission_service_context.h17
-rw-r--r--chromium/content/browser/permissions/permission_service_impl.cc67
-rw-r--r--chromium/content/browser/permissions/permission_service_impl.h53
-rw-r--r--chromium/content/browser/plugin_data_remover_impl.cc85
-rw-r--r--chromium/content/browser/plugin_loader_posix.cc237
-rw-r--r--chromium/content/browser/plugin_loader_posix.h134
-rw-r--r--chromium/content/browser/plugin_loader_posix_unittest.cc426
-rw-r--r--chromium/content/browser/plugin_process_host.cc442
-rw-r--r--chromium/content/browser/plugin_process_host.h219
-rw-r--r--chromium/content/browser/plugin_process_host_mac.cc107
-rw-r--r--chromium/content/browser/plugin_service_impl.cc473
-rw-r--r--chromium/content/browser/plugin_service_impl.h93
-rw-r--r--chromium/content/browser/power_save_blocker_impl.cc4
-rw-r--r--chromium/content/browser/power_save_blocker_x11.cc67
-rw-r--r--chromium/content/browser/ppapi_plugin_process_host.cc25
-rw-r--r--chromium/content/browser/ppapi_plugin_process_host.h5
-rw-r--r--chromium/content/browser/presentation/presentation_service_impl.cc116
-rw-r--r--chromium/content/browser/presentation/presentation_service_impl.h43
-rw-r--r--chromium/content/browser/presentation/presentation_service_impl_unittest.cc185
-rw-r--r--chromium/content/browser/presentation/presentation_type_converters.cc39
-rw-r--r--chromium/content/browser/presentation/presentation_type_converters.h27
-rw-r--r--chromium/content/browser/presentation/presentation_type_converters_unittest.cc9
-rw-r--r--chromium/content/browser/push_messaging/push_messaging_message_filter.cc72
-rw-r--r--chromium/content/browser/push_messaging/push_messaging_message_filter.h16
-rw-r--r--chromium/content/browser/push_messaging/push_messaging_router.cc38
-rw-r--r--chromium/content/browser/push_messaging/push_messaging_router.h18
-rw-r--r--chromium/content/browser/quota/mock_quota_manager_proxy.cc10
-rw-r--r--chromium/content/browser/quota/mock_quota_manager_proxy.h2
-rw-r--r--chromium/content/browser/quota/quota_backend_impl_unittest.cc1
-rw-r--r--chromium/content/browser/quota/quota_manager_unittest.cc13
-rw-r--r--chromium/content/browser/quota/quota_reservation_manager_unittest.cc1
-rw-r--r--chromium/content/browser/quota/quota_temporary_storage_evictor_unittest.cc6
-rw-r--r--chromium/content/browser/quota/storage_monitor_unittest.cc2
-rw-r--r--chromium/content/browser/quota/usage_tracker_unittest.cc2
-rw-r--r--chromium/content/browser/quota_dispatcher_host.cc2
-rw-r--r--chromium/content/browser/renderer_host/DEPS7
-rw-r--r--chromium/content/browser/renderer_host/browser_compositor_view_mac.h (renamed from chromium/content/browser/compositor/browser_compositor_view_mac.h)6
-rw-r--r--chromium/content/browser/renderer_host/browser_compositor_view_mac.mm (renamed from chromium/content/browser/compositor/browser_compositor_view_mac.mm)14
-rw-r--r--chromium/content/browser/renderer_host/clipboard_message_filter.cc4
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.cc146
-rw-r--r--chromium/content/browser/renderer_host/compositor_impl_android.h3
-rw-r--r--chromium/content/browser/renderer_host/compositor_resize_lock_aura.h2
-rw-r--r--chromium/content/browser/renderer_host/database_message_filter.cc9
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host.cc (renamed from chromium/content/browser/compositor/delegated_frame_host.cc)532
-rw-r--r--chromium/content/browser/renderer_host/delegated_frame_host.h (renamed from chromium/content/browser/compositor/delegated_frame_host.h)69
-rw-r--r--chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc60
-rw-r--r--chromium/content/browser/renderer_host/event_with_latency_info.h55
-rw-r--r--chromium/content/browser/renderer_host/font_utils_linux.cc40
-rw-r--r--chromium/content/browser/renderer_host/gpu_message_filter.cc95
-rw-r--r--chromium/content/browser/renderer_host/gpu_message_filter.h54
-rw-r--r--chromium/content/browser/renderer_host/ime_adapter_android.cc54
-rw-r--r--chromium/content/browser/renderer_host/ime_adapter_android.h7
-rw-r--r--chromium/content/browser/renderer_host/input/composited_scrolling_browsertest.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_event_queue.cc22
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_event_queue.h2
-rw-r--r--chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc25
-rw-r--r--chromium/content/browser/renderer_host/input/input_router.h4
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_client.h7
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl.cc150
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl.h41
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl_perftest.cc5
-rw-r--r--chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc109
-rw-r--r--chromium/content/browser/renderer_host/input/mock_input_router_client.cc8
-rw-r--r--chromium/content/browser/renderer_host/input/mock_input_router_client.h3
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.cc288
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.h110
-rw-r--r--chromium/content/browser/renderer_host/input/mouse_wheel_event_queue_unittest.cc547
-rw-r--r--chromium/content/browser/renderer_host/input/non_blocking_event_browsertest.cc218
-rw-r--r--chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc47
-rw-r--r--chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.h2
-rw-r--r--chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc284
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture.cc4
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture.h2
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_controller.h2
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc41
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_pointer_action.cc45
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_pointer_action.h15
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc3
-rw-r--r--chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.h2
-rw-r--r--chromium/content/browser/renderer_host/input/touch_action_browsertest.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/touch_emulator.cc3
-rw-r--r--chromium/content/browser/renderer_host/input/touch_emulator.h2
-rw-r--r--chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc7
-rw-r--r--chromium/content/browser/renderer_host/input/touch_event_queue.cc24
-rw-r--r--chromium/content/browser/renderer_host/input/touch_event_queue.h3
-rw-r--r--chromium/content/browser/renderer_host/input/touch_event_queue_unittest.cc98
-rw-r--r--chromium/content/browser/renderer_host/input/touch_input_browsertest.cc101
-rw-r--r--chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc299
-rw-r--r--chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc2
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_android.cc78
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_android.h37
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_android_unittest.cc169
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_mac.mm9
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm188
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_util.cc110
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_util.h5
-rw-r--r--chromium/content/browser/renderer_host/input/web_input_event_util_unittest.cc8
-rw-r--r--chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc10
-rw-r--r--chromium/content/browser/renderer_host/media/OWNERS4
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_debug_writer.cc166
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_debug_writer.h28
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_debug_writer_unittest.cc270
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_device_manager.cc7
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_device_manager.h5
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_device_manager_unittest.cc17
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc84
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_renderer_host.h8
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_sync_writer.cc11
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_sync_writer.h4
-rw-r--r--chromium/content/browser/renderer_host/media/audio_input_sync_writer_unittest.cc10
-rw-r--r--chromium/content/browser/renderer_host/media/audio_output_device_enumerator.cc7
-rw-r--r--chromium/content/browser/renderer_host/media/audio_output_device_enumerator.h4
-rw-r--r--chromium/content/browser/renderer_host/media/audio_output_device_enumerator_unittest.cc7
-rw-r--r--chromium/content/browser/renderer_host/media/audio_renderer_host.cc102
-rw-r--r--chromium/content/browser/renderer_host/media/audio_renderer_host.h12
-rw-r--r--chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc20
-rw-r--r--chromium/content/browser/renderer_host/media/audio_sync_reader.cc22
-rw-r--r--chromium/content/browser/renderer_host/media/audio_sync_reader.h7
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_dispatcher_host_unittest.cc11
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager.cc159
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager.h26
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_manager_unittest.cc22
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_ui_controller_unittest.cc14
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc24
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_ui_proxy.h13
-rw-r--r--chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc67
-rw-r--r--chromium/content/browser/renderer_host/media/peer_connection_tracker_host.cc2
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_buffer_pool.cc451
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_buffer_pool.h55
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_buffer_pool_unittest.cc187
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller.cc28
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller.h13
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller_event_handler.h3
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_controller_unittest.cc80
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_device_client.cc108
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_device_client.h35
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_device_client_unittest.cc69
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc26
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h23
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host.cc21
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host.h4
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc11
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager.cc184
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager.h65
-rw-r--r--chromium/content/browser/renderer_host/media/video_capture_manager_unittest.cc20
-rw-r--r--chromium/content/browser/renderer_host/media/webrtc_identity_service_host.cc2
-rw-r--r--chromium/content/browser/renderer_host/media/webrtc_identity_service_host_unittest.cc20
-rw-r--r--chromium/content/browser/renderer_host/memory_benchmark_message_filter.cc41
-rw-r--r--chromium/content/browser/renderer_host/memory_benchmark_message_filter.h31
-rw-r--r--chromium/content/browser/renderer_host/native_web_keyboard_event_android.cc49
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller.cc90
-rw-r--r--chromium/content/browser/renderer_host/overscroll_controller.h8
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc23
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h11
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host.cc430
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host.h27
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc17
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.cc1
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_test_utils.cc9
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h1
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_udp.cc13
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_udp.h1
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_udp_unittest.cc4
-rw-r--r--chromium/content/browser/renderer_host/p2p/socket_host_unittest.cc386
-rw-r--r--chromium/content/browser/renderer_host/pepper/browser_ppapi_host_impl.cc2
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc4
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_file_io_host.h1
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc4
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_host_resolver_message_filter.cc2
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_internal_file_ref_backend.cc12
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc2
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.cc15
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.h1
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_socket_utils.cc5
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.cc15
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc21
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.cc31
-rw-r--r--chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h6
-rw-r--r--chromium/content/browser/renderer_host/pepper/quota_reservation.cc1
-rw-r--r--chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc1
-rw-r--r--chromium/content/browser/renderer_host/render_message_filter.cc134
-rw-r--r--chromium/content/browser/renderer_host/render_message_filter.h16
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.cc469
-rw-r--r--chromium/content/browser/renderer_host/render_process_host_impl.h52
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_factory.cc3
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_factory.h16
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_impl.cc85
-rw-r--r--chromium/content/browser/renderer_host/render_view_host_impl.h40
-rw-r--r--chromium/content/browser/renderer_host/render_widget_helper.cc26
-rw-r--r--chromium/content/browser/renderer_host/render_widget_helper.h7
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_delegate.cc7
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_delegate.h31
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.cc181
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_impl.h50
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc205
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_input_event_router.h66
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_owner_delegate.h4
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_unittest.cc16
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.cc425
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_android.h40
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.cc476
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura.h64
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc915
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.cc405
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base.h94
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base_observer.cc14
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_base_observer.h32
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_browsertest.cc7
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac.h50
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac.mm365
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mac_unittest.mm118
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mus.cc34
-rw-r--r--chromium/content/browser/renderer_host/render_widget_host_view_mus.h13
-rw-r--r--chromium/content/browser/renderer_host/resize_lock.cc (renamed from chromium/content/browser/compositor/resize_lock.cc)5
-rw-r--r--chromium/content/browser/renderer_host/resize_lock.h (renamed from chromium/content/browser/compositor/resize_lock.h)6
-rw-r--r--chromium/content/browser/renderer_host/sandbox_ipc_linux.cc63
-rw-r--r--chromium/content/browser/renderer_host/sandbox_ipc_linux.h8
-rw-r--r--chromium/content/browser/renderer_host/text_input_client_mac_unittest.mm3
-rw-r--r--chromium/content/browser/renderer_host/text_input_client_message_filter.h2
-rw-r--r--chromium/content/browser/renderer_host/text_input_client_message_filter.mm11
-rw-r--r--chromium/content/browser/renderer_host/web_input_event_aura.cc16
-rw-r--r--chromium/content/browser/renderer_host/web_input_event_aura_unittest.cc8
-rw-r--r--chromium/content/browser/renderer_host/websocket_blob_sender.cc284
-rw-r--r--chromium/content/browser/renderer_host/websocket_blob_sender.h139
-rw-r--r--chromium/content/browser/renderer_host/websocket_blob_sender_unittest.cc446
-rw-r--r--chromium/content/browser/renderer_host/websocket_dispatcher_host.cc31
-rw-r--r--chromium/content/browser/renderer_host/websocket_dispatcher_host.h29
-rw-r--r--chromium/content/browser/renderer_host/websocket_host.cc206
-rw-r--r--chromium/content/browser/renderer_host/websocket_host.h10
-rw-r--r--chromium/content/browser/resolve_proxy_msg_helper.cc2
-rw-r--r--chromium/content/browser/resolve_proxy_msg_helper_unittest.cc3
-rw-r--r--chromium/content/browser/resource_context_impl.cc10
-rw-r--r--chromium/content/browser/resources/gpu/browser_bridge.js17
-rw-r--r--chromium/content/browser/resources/gpu/info_view.html15
-rw-r--r--chromium/content/browser/resources/gpu/info_view.js19
-rw-r--r--chromium/content/browser/resources/media/OWNERS4
-rw-r--r--chromium/content/browser/resources/media/dump_creator.js24
-rw-r--r--chromium/content/browser/resources/service_worker/serviceworker_internals.html5
-rw-r--r--chromium/content/browser/resources/service_worker/serviceworker_internals.js2
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_browsertest.cc18
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_delegate_win.cc133
-rw-r--r--chromium/content/browser/screen_orientation/screen_orientation_delegate_win.h30
-rw-r--r--chromium/content/browser/security_exploit_browsertest.cc136
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance.cc277
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance.h36
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc199
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_test_helper.cc101
-rw-r--r--chromium/content/browser/service_worker/embedded_worker_test_helper.h41
-rw-r--r--chromium/content/browser/service_worker/foreign_fetch_request_handler.cc25
-rw-r--r--chromium/content/browser/service_worker/foreign_fetch_request_handler.h5
-rw-r--r--chromium/content/browser/service_worker/link_header_support.cc311
-rw-r--r--chromium/content/browser/service_worker/link_header_support.h38
-rw-r--r--chromium/content/browser/service_worker/link_header_support_unittest.cc410
-rw-r--r--chromium/content/browser/service_worker/service_worker_browsertest.cc400
-rw-r--r--chromium/content/browser/service_worker/service_worker_cache_writer_unittest.cc43
-rw-r--r--chromium/content/browser/service_worker/service_worker_client_utils.cc138
-rw-r--r--chromium/content/browser/service_worker/service_worker_client_utils.h14
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core.cc84
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_core.h26
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_observer.h2
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_request_handler.cc4
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_request_handler_unittest.cc27
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_watcher.cc14
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_watcher.h3
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_wrapper.cc73
-rw-r--r--chromium/content/browser/service_worker/service_worker_context_wrapper.h33
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc31
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler.h7
-rw-r--r--chromium/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc21
-rw-r--r--chromium/content/browser/service_worker/service_worker_database.cc15
-rw-r--r--chromium/content/browser/service_worker/service_worker_database.h3
-rw-r--r--chromium/content/browser/service_worker/service_worker_database.proto1
-rw-r--r--chromium/content/browser/service_worker/service_worker_database_task_manager.h1
-rw-r--r--chromium/content/browser/service_worker/service_worker_database_unittest.cc6
-rw-r--r--chromium/content/browser/service_worker/service_worker_disk_cache.cc6
-rw-r--r--chromium/content/browser/service_worker/service_worker_disk_cache.h18
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host.cc428
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host.h78
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc257
-rw-r--r--chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc81
-rw-r--r--chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h14
-rw-r--r--chromium/content/browser/service_worker/service_worker_handle.h1
-rw-r--r--chromium/content/browser/service_worker/service_worker_handle_unittest.cc21
-rw-r--r--chromium/content/browser/service_worker/service_worker_info.cc10
-rw-r--r--chromium/content/browser/service_worker/service_worker_info.h5
-rw-r--r--chromium/content/browser/service_worker/service_worker_internals_ui.cc81
-rw-r--r--chromium/content/browser/service_worker/service_worker_internals_ui.h1
-rw-r--r--chromium/content/browser/service_worker/service_worker_job_coordinator.cc3
-rw-r--r--chromium/content/browser/service_worker/service_worker_job_coordinator.h1
-rw-r--r--chromium/content/browser/service_worker/service_worker_job_unittest.cc132
-rw-r--r--chromium/content/browser/service_worker/service_worker_metrics.cc264
-rw-r--r--chromium/content/browser/service_worker/service_worker_metrics.h80
-rw-r--r--chromium/content/browser/service_worker/service_worker_process_manager.cc65
-rw-r--r--chromium/content/browser/service_worker/service_worker_process_manager.h12
-rw-r--r--chromium/content/browser/service_worker/service_worker_process_manager_unittest.cc11
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host.cc106
-rw-r--r--chromium/content/browser/service_worker/service_worker_provider_host.h28
-rw-r--r--chromium/content/browser/service_worker/service_worker_read_from_cache_job.cc2
-rw-r--r--chromium/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc53
-rw-r--r--chromium/content/browser/service_worker/service_worker_register_job.cc101
-rw-r--r--chromium/content/browser/service_worker/service_worker_register_job.h10
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration.cc34
-rw-r--r--chromium/content/browser/service_worker/service_worker_registration.h14
-rw-r--r--chromium/content/browser/service_worker/service_worker_request_handler.cc9
-rw-r--r--chromium/content/browser/service_worker/service_worker_request_handler.h6
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage.cc58
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage.h20
-rw-r--r--chromium/content/browser/service_worker/service_worker_storage_unittest.cc271
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_request_job.cc48
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_request_job.h27
-rw-r--r--chromium/content/browser/service_worker/service_worker_url_request_job_unittest.cc54
-rw-r--r--chromium/content/browser/service_worker/service_worker_version.cc800
-rw-r--r--chromium/content/browser/service_worker/service_worker_version.h225
-rw-r--r--chromium/content/browser/service_worker/service_worker_version_unittest.cc563
-rw-r--r--chromium/content/browser/service_worker/service_worker_write_to_cache_job.cc27
-rw-r--r--chromium/content/browser/service_worker/service_worker_write_to_cache_job.h11
-rw-r--r--chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc1
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_host.cc17
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_host.h5
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_instance.cc3
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_instance.h6
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_instance_unittest.cc19
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_message_filter.cc17
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_message_filter.h6
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_service_impl.cc18
-rw-r--r--chromium/content/browser/shared_worker/shared_worker_service_impl.h8
-rw-r--r--chromium/content/browser/shared_worker/worker_browsertest.cc6
-rw-r--r--chromium/content/browser/site_instance_impl.cc52
-rw-r--r--chromium/content/browser/site_instance_impl.h50
-rw-r--r--chromium/content/browser/site_instance_impl_unittest.cc355
-rw-r--r--chromium/content/browser/site_per_process_browsertest.cc1853
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl.cc6
-rw-r--r--chromium/content/browser/speech/speech_recognizer_impl.h1
-rw-r--r--chromium/content/browser/ssl/ssl_client_auth_handler.cc9
-rw-r--r--chromium/content/browser/ssl/ssl_client_auth_handler.h1
-rw-r--r--chromium/content/browser/storage_partition_impl.cc73
-rw-r--r--chromium/content/browser/storage_partition_impl.h37
-rw-r--r--chromium/content/browser/storage_partition_impl_map.cc52
-rw-r--r--chromium/content/browser/streams/stream_url_request_job.cc33
-rw-r--r--chromium/content/browser/streams/stream_url_request_job.h5
-rw-r--r--chromium/content/browser/system_message_window_win.cc164
-rw-r--r--chromium/content/browser/system_message_window_win.h51
-rw-r--r--chromium/content/browser/system_message_window_win_unittest.cc45
-rw-r--r--chromium/content/browser/theme_helper_mac.mm44
-rw-r--r--chromium/content/browser/top_document_isolation_browsertest.cc571
-rw-r--r--chromium/content/browser/tracing/BUILD.gn2
-rw-r--r--chromium/content/browser/tracing/DEPS1
-rw-r--r--chromium/content/browser/tracing/background_tracing_config_impl.cc8
-rw-r--r--chromium/content/browser/tracing/background_tracing_config_impl.h1
-rw-r--r--chromium/content/browser/tracing/background_tracing_config_unittest.cc38
-rw-r--r--chromium/content/browser/tracing/background_tracing_manager_impl.cc4
-rw-r--r--chromium/content/browser/tracing/battor_power_trace_provider.cc31
-rw-r--r--chromium/content/browser/tracing/battor_power_trace_provider.h31
-rw-r--r--chromium/content/browser/tracing/etw_system_event_consumer_win.cc18
-rw-r--r--chromium/content/browser/tracing/etw_system_event_consumer_win.h5
-rw-r--r--chromium/content/browser/tracing/power_tracing_agent.cc182
-rw-r--r--chromium/content/browser/tracing/power_tracing_agent.h61
-rw-r--r--chromium/content/browser/tracing/trace_message_filter.cc47
-rw-r--r--chromium/content/browser/tracing/trace_message_filter.h8
-rw-r--r--chromium/content/browser/tracing/tracing_controller_browsertest.cc170
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl.cc494
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl.h55
-rw-r--r--chromium/content/browser/tracing/tracing_controller_impl_data_sinks.cc7
-rw-r--r--chromium/content/browser/tracing/tracing_ui.cc77
-rw-r--r--chromium/content/browser/tracing/tracing_ui.h1
-rw-r--r--chromium/content/browser/udev_linux.cc66
-rw-r--r--chromium/content/browser/udev_linux.h97
-rw-r--r--chromium/content/browser/utility_process_host_impl.cc67
-rw-r--r--chromium/content/browser/utility_process_host_impl.h7
-rw-r--r--chromium/content/browser/vr/android/cardboard/cardboard_vr_device.cc36
-rw-r--r--chromium/content/browser/vr/android/cardboard/cardboard_vr_device.h4
-rw-r--r--chromium/content/browser/vr/vr_device.h4
-rw-r--r--chromium/content/browser/vr/vr_device_manager.cc9
-rw-r--r--chromium/content/browser/vr/vr_device_manager.h12
-rw-r--r--chromium/content/browser/vr/vr_device_manager_unittest.cc10
-rw-r--r--chromium/content/browser/wake_lock/wake_lock_browsertest.cc8
-rw-r--r--chromium/content/browser/wake_lock/wake_lock_service_context.cc6
-rw-r--r--chromium/content/browser/wake_lock/wake_lock_service_context.h2
-rw-r--r--chromium/content/browser/wake_lock/wake_lock_service_impl.cc2
-rw-r--r--chromium/content/browser/wake_lock/wake_lock_service_impl.h6
-rw-r--r--chromium/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc8
-rw-r--r--chromium/content/browser/web_contents/aura/shadow_layer_delegate.cc8
-rw-r--r--chromium/content/browser/web_contents/web_contents_android.cc93
-rw-r--r--chromium/content/browser/web_contents/web_contents_android.h14
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.cc777
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl.h95
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl_browsertest.cc250
-rw-r--r--chromium/content/browser/web_contents/web_contents_impl_unittest.cc106
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura.cc232
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura.h14
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_aura_browsertest.cc2
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mac.h5
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mac.mm69
-rw-r--r--chromium/content/browser/web_contents/web_contents_view_mus.cc1
-rw-r--r--chromium/content/browser/web_contents/web_drag_dest_mac.mm4
-rw-r--r--chromium/content/browser/web_contents/web_drag_dest_mac_unittest.mm76
-rw-r--r--chromium/content/browser/web_contents/web_drag_source_mac.mm8
-rw-r--r--chromium/content/browser/web_contents/web_drag_source_mac_unittest.mm22
-rw-r--r--chromium/content/browser/webui/OWNERS1
-rw-r--r--chromium/content/browser/webui/content_web_ui_controller_factory.cc2
-rw-r--r--chromium/content/browser/webui/url_data_manager_backend.cc7
-rw-r--r--chromium/content/browser/webui/web_ui_data_source_impl.cc62
-rw-r--r--chromium/content/browser/webui/web_ui_data_source_impl.h12
-rw-r--r--chromium/content/browser/webui/web_ui_impl.h1
-rw-r--r--chromium/content/browser/webui/web_ui_mojo_browsertest.cc34
-rw-r--r--chromium/content/browser/zygote_host/zygote_communication_linux.cc437
-rw-r--r--chromium/content/browser/zygote_host/zygote_communication_linux.h93
-rw-r--r--chromium/content/browser/zygote_host/zygote_handle_linux.cc22
-rw-r--r--chromium/content/browser/zygote_host/zygote_host_impl_linux.cc512
-rw-r--r--chromium/content/browser/zygote_host/zygote_host_impl_linux.h89
-rw-r--r--chromium/content/child/BUILD.gn90
-rw-r--r--chromium/content/child/OWNERS3
-rw-r--r--chromium/content/child/appcache/appcache_dispatcher.h4
-rw-r--r--chromium/content/child/appcache/appcache_frontend_impl.cc86
-rw-r--r--chromium/content/child/appcache/web_application_cache_host_impl.cc2
-rw-r--r--chromium/content/child/appcache/web_application_cache_host_impl.h2
-rw-r--r--chromium/content/child/assert_matching_enums.cc67
-rw-r--r--chromium/content/child/background_sync/background_sync_provider.cc306
-rw-r--r--chromium/content/child/background_sync/background_sync_provider.h70
-rw-r--r--chromium/content/child/background_sync/background_sync_type_converters.cc128
-rw-r--r--chromium/content/child/background_sync/background_sync_type_converters.h78
-rw-r--r--chromium/content/child/background_sync/background_sync_type_converters_unittest.cc170
-rw-r--r--chromium/content/child/blink_platform_impl.cc354
-rw-r--r--chromium/content/child/blink_platform_impl.h71
-rw-r--r--chromium/content/child/blob_storage/blob_consolidation.cc4
-rw-r--r--chromium/content/child/blob_storage/blob_consolidation.h10
-rw-r--r--chromium/content/child/blob_storage/blob_message_filter.cc61
-rw-r--r--chromium/content/child/blob_storage/blob_message_filter.h63
-rw-r--r--chromium/content/child/blob_storage/blob_transport_controller.cc119
-rw-r--r--chromium/content/child/blob_storage/blob_transport_controller.h58
-rw-r--r--chromium/content/child/blob_storage/blob_transport_controller_unittest.cc145
-rw-r--r--chromium/content/child/browser_font_resource_trusted.cc8
-rw-r--r--chromium/content/child/browser_font_resource_trusted.h4
-rw-r--r--chromium/content/child/child_discardable_shared_memory_manager.cc33
-rw-r--r--chromium/content/child/child_discardable_shared_memory_manager.h6
-rw-r--r--chromium/content/child/child_gpu_memory_buffer_manager.cc24
-rw-r--r--chromium/content/child/child_gpu_memory_buffer_manager.h7
-rw-r--r--chromium/content/child/child_histogram_message_filter.cc31
-rw-r--r--chromium/content/child/child_histogram_message_filter.h12
-rw-r--r--chromium/content/child/child_process.cc7
-rw-r--r--chromium/content/child/child_process.h9
-rw-r--r--chromium/content/child/child_shared_bitmap_manager.cc41
-rw-r--r--chromium/content/child/child_shared_bitmap_manager.h11
-rw-r--r--chromium/content/child/child_thread_impl.cc193
-rw-r--r--chromium/content/child/child_thread_impl.h49
-rw-r--r--chromium/content/child/child_thread_impl_browsertest.cc15
-rw-r--r--chromium/content/child/content_child_helpers.cc13
-rw-r--r--chromium/content/child/db_message_filter.cc23
-rw-r--r--chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.cc49
-rw-r--r--chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.h6
-rw-r--r--chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc58
-rw-r--r--chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.h7
-rw-r--r--chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win_unittest.cc6
-rw-r--r--chromium/content/child/fileapi/webfilesystem_impl.cc58
-rw-r--r--chromium/content/child/fileapi/webfilewriter_base_unittest.cc5
-rw-r--r--chromium/content/child/fileapi/webfilewriter_impl.cc2
-rw-r--r--chromium/content/child/font_warmup_win.cc (renamed from chromium/content/common/font_warmup_win.cc)95
-rw-r--r--chromium/content/child/font_warmup_win.h (renamed from chromium/content/common/font_warmup_win.h)17
-rw-r--r--chromium/content/child/font_warmup_win_unittest.cc (renamed from chromium/content/common/font_warmup_win_unittest.cc)28
-rw-r--r--chromium/content/child/ftp_directory_listing_response_delegate.cc9
-rw-r--r--chromium/content/child/geofencing/geofencing_dispatcher.cc3
-rw-r--r--chromium/content/child/geofencing/geofencing_dispatcher.h2
-rw-r--r--chromium/content/child/indexed_db/indexed_db_dispatcher.cc43
-rw-r--r--chromium/content/child/indexed_db/indexed_db_dispatcher.h20
-rw-r--r--chromium/content/child/indexed_db/indexed_db_dispatcher_unittest.cc25
-rw-r--r--chromium/content/child/indexed_db/webidbcursor_impl.cc4
-rw-r--r--chromium/content/child/indexed_db/webidbcursor_impl_unittest.cc13
-rw-r--r--chromium/content/child/indexed_db/webidbfactory_impl.cc26
-rw-r--r--chromium/content/child/indexed_db/webidbfactory_impl.h7
-rw-r--r--chromium/content/child/mojo/mojo_application.cc18
-rw-r--r--chromium/content/child/mojo/mojo_application.h2
-rw-r--r--chromium/content/child/mojo/type_converters.h8
-rw-r--r--chromium/content/child/multipart_response_delegate.cc394
-rw-r--r--chromium/content/child/multipart_response_delegate.h153
-rw-r--r--chromium/content/child/multipart_response_delegate_unittest.cc680
-rw-r--r--chromium/content/child/navigator_connect/OWNERS1
-rw-r--r--chromium/content/child/navigator_connect/service_port_dispatcher_impl.cc80
-rw-r--r--chromium/content/child/navigator_connect/service_port_dispatcher_impl.h57
-rw-r--r--chromium/content/child/navigator_connect/service_port_provider.cc134
-rw-r--r--chromium/content/child/navigator_connect/service_port_provider.h101
-rw-r--r--chromium/content/child/notifications/notification_data_conversions.cc38
-rw-r--r--chromium/content/child/notifications/notification_data_conversions_unittest.cc84
-rw-r--r--chromium/content/child/notifications/notification_image_loader.cc41
-rw-r--r--chromium/content/child/notifications/notification_image_loader.h21
-rw-r--r--chromium/content/child/notifications/notification_manager.cc91
-rw-r--r--chromium/content/child/notifications/notification_manager.h11
-rw-r--r--chromium/content/child/notifications/pending_notification.cc123
-rw-r--r--chromium/content/child/notifications/pending_notification.h78
-rw-r--r--chromium/content/child/notifications/pending_notifications_tracker.cc105
-rw-r--r--chromium/content/child/notifications/pending_notifications_tracker.h96
-rw-r--r--chromium/content/child/notifications/pending_notifications_tracker_unittest.cc299
-rw-r--r--chromium/content/child/npapi/DEPS4
-rw-r--r--chromium/content/child/npapi/OWNERS2
-rw-r--r--chromium/content/child/npapi/np_channel_base.cc393
-rw-r--r--chromium/content/child/npapi/np_channel_base.h200
-rw-r--r--chromium/content/child/npapi/npobject_base.h31
-rw-r--r--chromium/content/child/npapi/npobject_proxy.cc509
-rw-r--r--chromium/content/child/npapi/npobject_proxy.h130
-rw-r--r--chromium/content/child/npapi/npobject_stub.cc424
-rw-r--r--chromium/content/child/npapi/npobject_stub.h99
-rw-r--r--chromium/content/child/npapi/npobject_util.cc310
-rw-r--r--chromium/content/child/npapi/npobject_util.h74
-rw-r--r--chromium/content/child/npapi/npruntime_util.cc54
-rw-r--r--chromium/content/child/npapi/npruntime_util.h24
-rw-r--r--chromium/content/child/npapi/plugin_host.cc938
-rw-r--r--chromium/content/child/npapi/plugin_host.h63
-rw-r--r--chromium/content/child/npapi/plugin_instance.cc430
-rw-r--r--chromium/content/child/npapi/plugin_instance.h293
-rw-r--r--chromium/content/child/npapi/plugin_instance_mac.mm56
-rw-r--r--chromium/content/child/npapi/plugin_lib.cc333
-rw-r--r--chromium/content/child/npapi/plugin_lib.h135
-rw-r--r--chromium/content/child/npapi/plugin_lib_unittest.cc64
-rw-r--r--chromium/content/child/npapi/plugin_web_event_converter_mac.h55
-rw-r--r--chromium/content/child/npapi/plugin_web_event_converter_mac.mm189
-rw-r--r--chromium/content/child/npapi/webplugin.h133
-rw-r--r--chromium/content/child/npapi/webplugin_accelerated_surface_mac.h39
-rw-r--r--chromium/content/child/npapi/webplugin_delegate.h96
-rw-r--r--chromium/content/child/npapi/webplugin_delegate_impl.cc242
-rw-r--r--chromium/content/child/npapi/webplugin_delegate_impl.h449
-rw-r--r--chromium/content/child/npapi/webplugin_delegate_impl_android.cc80
-rw-r--r--chromium/content/child/npapi/webplugin_delegate_impl_aura.cc66
-rw-r--r--chromium/content/child/npapi/webplugin_delegate_impl_mac.mm726
-rw-r--r--chromium/content/child/npapi/webplugin_delegate_impl_win.cc1496
-rw-r--r--chromium/content/child/npapi/webplugin_ime_win.cc327
-rw-r--r--chromium/content/child/npapi/webplugin_ime_win.h184
-rw-r--r--chromium/content/child/npapi/webplugin_resource_client.h45
-rw-r--r--chromium/content/child/permissions/permission_dispatcher.cc107
-rw-r--r--chromium/content/child/permissions/permission_dispatcher.h34
-rw-r--r--chromium/content/child/plugin_message_generator.cc33
-rw-r--r--chromium/content/child/plugin_message_generator.h7
-rw-r--r--chromium/content/child/plugin_messages.h346
-rw-r--r--chromium/content/child/plugin_param_traits.cc136
-rw-r--r--chromium/content/child/plugin_param_traits.h87
-rw-r--r--chromium/content/child/power_monitor_broadcast_source_unittest.cc4
-rw-r--r--chromium/content/child/process_control_impl.cc20
-rw-r--r--chromium/content/child/process_control_impl.h26
-rw-r--r--chromium/content/child/push_messaging/push_provider.cc20
-rw-r--r--chromium/content/child/request_extra_data.cc1
-rw-r--r--chromium/content/child/request_extra_data.h15
-rw-r--r--chromium/content/child/request_info.h7
-rw-r--r--chromium/content/child/resource_dispatcher.cc192
-rw-r--r--chromium/content/child/resource_dispatcher.h44
-rw-r--r--chromium/content/child/resource_dispatcher_unittest.cc546
-rw-r--r--chromium/content/child/resource_scheduling_filter.cc3
-rw-r--r--chromium/content/child/resource_scheduling_filter.h6
-rw-r--r--chromium/content/child/runtime_features.cc88
-rw-r--r--chromium/content/child/scoped_web_callbacks.h17
-rw-r--r--chromium/content/child/service_worker/service_worker_dispatcher.cc53
-rw-r--r--chromium/content/child/service_worker/service_worker_dispatcher.h7
-rw-r--r--chromium/content/child/service_worker/service_worker_dispatcher_unittest.cc17
-rw-r--r--chromium/content/child/service_worker/service_worker_handle_reference.cc19
-rw-r--r--chromium/content/child/service_worker/service_worker_handle_reference.h7
-rw-r--r--chromium/content/child/service_worker/service_worker_network_provider.cc12
-rw-r--r--chromium/content/child/service_worker/service_worker_network_provider.h7
-rw-r--r--chromium/content/child/service_worker/service_worker_provider_context.cc52
-rw-r--r--chromium/content/child/service_worker/service_worker_provider_context.h13
-rw-r--r--chromium/content/child/service_worker/service_worker_registration_handle_reference.cc13
-rw-r--r--chromium/content/child/service_worker/service_worker_registration_handle_reference.h7
-rw-r--r--chromium/content/child/service_worker/web_service_worker_impl.cc54
-rw-r--r--chromium/content/child/service_worker/web_service_worker_impl.h12
-rw-r--r--chromium/content/child/service_worker/web_service_worker_registration_impl.cc10
-rw-r--r--chromium/content/child/service_worker/web_service_worker_registration_impl.h8
-rw-r--r--chromium/content/child/shared_memory_data_consumer_handle.cc28
-rw-r--r--chromium/content/child/shared_memory_data_consumer_handle.h11
-rw-r--r--chromium/content/child/shared_memory_data_consumer_handle_unittest.cc66
-rw-r--r--chromium/content/child/shared_memory_received_data_factory.cc11
-rw-r--r--chromium/content/child/shared_memory_received_data_factory.h8
-rw-r--r--chromium/content/child/shared_memory_received_data_factory_unittest.cc40
-rw-r--r--chromium/content/child/shared_worker_devtools_agent.cc1
-rw-r--r--chromium/content/child/simple_webmimeregistry_impl.cc12
-rw-r--r--chromium/content/child/simple_webmimeregistry_impl.h1
-rw-r--r--chromium/content/child/site_isolation_stats_gatherer.cc8
-rw-r--r--chromium/content/child/site_isolation_stats_gatherer.h6
-rw-r--r--chromium/content/child/storage_util.cc26
-rw-r--r--chromium/content/child/storage_util.h24
-rw-r--r--chromium/content/child/threaded_data_provider.cc349
-rw-r--r--chromium/content/child/threaded_data_provider.h106
-rw-r--r--chromium/content/child/v8_value_converter_impl.cc43
-rw-r--r--chromium/content/child/v8_value_converter_impl_unittest.cc310
-rw-r--r--chromium/content/child/web_data_consumer_handle_impl.cc6
-rw-r--r--chromium/content/child/web_data_consumer_handle_impl.h5
-rw-r--r--chromium/content/child/web_data_consumer_handle_impl_unittest.cc20
-rw-r--r--chromium/content/child/web_database_observer_impl.cc97
-rw-r--r--chromium/content/child/web_database_observer_impl.h20
-rw-r--r--chromium/content/child/web_discardable_memory_impl.cc50
-rw-r--r--chromium/content/child/web_discardable_memory_impl.h46
-rw-r--r--chromium/content/child/web_memory_allocator_dump_impl.cc41
-rw-r--r--chromium/content/child/web_memory_allocator_dump_impl.h48
-rw-r--r--chromium/content/child/web_memory_dump_provider_adapter.cc131
-rw-r--r--chromium/content/child/web_memory_dump_provider_adapter.h49
-rw-r--r--chromium/content/child/web_process_memory_dump_impl.cc165
-rw-r--r--chromium/content/child/web_process_memory_dump_impl.h111
-rw-r--r--chromium/content/child/web_process_memory_dump_impl_unittest.cc124
-rw-r--r--chromium/content/child/web_url_loader_impl.cc429
-rw-r--r--chromium/content/child/web_url_loader_impl.h11
-rw-r--r--chromium/content/child/web_url_loader_impl_unittest.cc245
-rw-r--r--chromium/content/child/web_url_request_util.cc262
-rw-r--r--chromium/content/child/webblobregistry_impl.cc150
-rw-r--r--chromium/content/child/webblobregistry_impl.h29
-rw-r--r--chromium/content/child/webfallbackthemeengine_impl.h5
-rw-r--r--chromium/content/child/webfileutilities_impl.cc9
-rw-r--r--chromium/content/child/webmessageportchannel_impl.cc22
-rw-r--r--chromium/content/child/webmessageportchannel_impl.h12
-rw-r--r--chromium/content/child/webthemeengine_impl_android.cc29
-rw-r--r--chromium/content/child/webthemeengine_impl_android.h2
-rw-r--r--chromium/content/child/worker_thread_registry.cc3
-rw-r--r--chromium/content/common/BUILD.gn176
-rw-r--r--chromium/content/common/DEPS9
-rw-r--r--chromium/content/common/OWNERS13
-rw-r--r--chromium/content/common/accelerated_surface_buffers_swapped_params_mac.cc14
-rw-r--r--chromium/content/common/accelerated_surface_buffers_swapped_params_mac.h28
-rw-r--r--chromium/content/common/accessibility_messages.h21
-rw-r--r--chromium/content/common/android/address_parser_internal.cc2
-rw-r--r--chromium/content/common/android/address_parser_internal.h1
-rw-r--r--chromium/content/common/android/media_metadata_android.cc33
-rw-r--r--chromium/content/common/android/media_metadata_android.h29
-rw-r--r--chromium/content/common/android/surface_texture_manager.cc28
-rw-r--r--chromium/content/common/android/surface_texture_manager.h42
-rw-r--r--chromium/content/common/android/surface_texture_peer.cc33
-rw-r--r--chromium/content/common/android/surface_texture_peer.h38
-rw-r--r--chromium/content/common/android/sync_compositor_messages.cc5
-rw-r--r--chromium/content/common/android/sync_compositor_messages.h33
-rw-r--r--chromium/content/common/appcache_interfaces.cc5
-rw-r--r--chromium/content/common/appcache_interfaces.h1
-rw-r--r--chromium/content/common/appcache_messages.h1
-rw-r--r--chromium/content/common/application_setup.mojom9
-rw-r--r--chromium/content/common/ax_content_node_data.cc2
-rw-r--r--chromium/content/common/ax_content_node_data.h1
-rw-r--r--chromium/content/common/background_sync_service.mojom30
-rw-r--r--chromium/content/common/bluetooth/bluetooth_messages.h59
-rw-r--r--chromium/content/common/bluetooth/bluetooth_scan_filter.cc3
-rw-r--r--chromium/content/common/bluetooth/bluetooth_scan_filter.h1
-rw-r--r--chromium/content/common/browser_plugin/browser_plugin_messages.h23
-rw-r--r--chromium/content/common/buffer_presented_params_mac.cc13
-rw-r--r--chromium/content/common/buffer_presented_params_mac.h23
-rw-r--r--chromium/content/common/cache_storage/cache_storage_messages.h12
-rw-r--r--chromium/content/common/cache_storage/cache_storage_types.cc3
-rw-r--r--chromium/content/common/cache_storage/cache_storage_types.h5
-rw-r--r--chromium/content/common/cc_messages.cc124
-rw-r--r--chromium/content/common/cc_messages.h73
-rw-r--r--chromium/content/common/cc_messages_unittest.cc12
-rw-r--r--chromium/content/common/child_process_host_impl.cc22
-rw-r--r--chromium/content/common/child_process_messages.h57
-rw-r--r--chromium/content/common/child_process_sandbox_support_impl_linux.h5
-rw-r--r--chromium/content/common/clipboard_messages.h5
-rw-r--r--chromium/content/common/common.sb7
-rw-r--r--chromium/content/common/common_param_traits_unittest.cc63
-rw-r--r--chromium/content/common/content_constants_internal.cc5
-rw-r--r--chromium/content/common/content_constants_internal.h7
-rw-r--r--chromium/content/common/content_message_generator.h7
-rw-r--r--chromium/content/common/content_param_traits.cc5
-rw-r--r--chromium/content/common/content_param_traits.h14
-rw-r--r--chromium/content/common/content_param_traits_macros.h3
-rw-r--r--chromium/content/common/content_switches_internal.cc37
-rw-r--r--chromium/content/common/content_switches_internal.h6
-rw-r--r--chromium/content/common/database_identifier_unittest.cc38
-rw-r--r--chromium/content/common/devtools_messages.h14
-rw-r--r--chromium/content/common/discardable_shared_memory_heap.cc4
-rw-r--r--chromium/content/common/dom_storage/dom_storage_messages.h2
-rw-r--r--chromium/content/common/drag_messages.h1
-rw-r--r--chromium/content/common/dwrite_font_platform_win.cc1282
-rw-r--r--chromium/content/common/dwrite_font_platform_win_unittest.cc71
-rw-r--r--chromium/content/common/establish_channel_params.cc18
-rw-r--r--chromium/content/common/establish_channel_params.h27
-rw-r--r--chromium/content/common/experiments/api_key.cc144
-rw-r--r--chromium/content/common/experiments/api_key.h95
-rw-r--r--chromium/content/common/experiments/api_key_unittest.cc191
-rw-r--r--chromium/content/common/fileapi/webblob_messages.h80
-rw-r--r--chromium/content/common/font_config_ipc_linux.cc16
-rw-r--r--chromium/content/common/font_config_ipc_linux.h16
-rw-r--r--chromium/content/common/font_list_win.cc2
-rw-r--r--chromium/content/common/frame_message_enums.h6
-rw-r--r--chromium/content/common/frame_messages.h225
-rw-r--r--chromium/content/common/frame_param.cc40
-rw-r--r--chromium/content/common/frame_param.h10
-rw-r--r--chromium/content/common/frame_param_macros.h60
-rw-r--r--chromium/content/common/frame_replication_state.cc15
-rw-r--r--chromium/content/common/frame_replication_state.h45
-rw-r--r--chromium/content/common/gamepad_param_traits.cc6
-rw-r--r--chromium/content/common/gamepad_param_traits.h5
-rw-r--r--chromium/content/common/geolocation_service.mojom20
-rw-r--r--chromium/content/common/gpu/DEPS3
-rw-r--r--chromium/content/common/gpu/ca_layer_partial_damage_tree_mac.h56
-rw-r--r--chromium/content/common/gpu/ca_layer_partial_damage_tree_mac.mm287
-rw-r--r--chromium/content/common/gpu/ca_layer_tree_mac.h190
-rw-r--r--chromium/content/common/gpu/ca_layer_tree_mac.mm455
-rw-r--r--chromium/content/common/gpu/child_window_surface_win.cc214
-rw-r--r--chromium/content/common/gpu/child_window_surface_win.h45
-rw-r--r--chromium/content/common/gpu/client/DEPS7
-rw-r--r--chromium/content/common/gpu/client/command_buffer_metrics.cc6
-rw-r--r--chromium/content/common/gpu/client/command_buffer_metrics.h2
-rw-r--r--chromium/content/common/gpu/client/command_buffer_proxy_impl.cc820
-rw-r--r--chromium/content/common/gpu/client/command_buffer_proxy_impl.h279
-rw-r--r--chromium/content/common/gpu/client/context_provider_command_buffer.cc63
-rw-r--r--chromium/content/common/gpu/client/context_provider_command_buffer.h12
-rw-r--r--chromium/content/common/gpu/client/gl_helper_benchmark.cc310
-rw-r--r--chromium/content/common/gpu/client/gpu_channel_host.cc552
-rw-r--r--chromium/content/common/gpu/client/gpu_channel_host.h318
-rw-r--r--chromium/content/common/gpu/client/gpu_context_tests.h72
-rw-r--r--chromium/content/common/gpu/client/gpu_in_process_context_tests.cc42
-rw-r--r--chromium/content/common/gpu/client/gpu_jpeg_decode_accelerator_host.cc204
-rw-r--r--chromium/content/common/gpu/client/gpu_jpeg_decode_accelerator_host.h73
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl.cc94
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl.h68
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.cc125
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h63
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface_unittest.cc16
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_pixmap.cc112
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_pixmap.h63
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_pixmap_unittest.cc16
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.cc224
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h77
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory_unittest.cc40
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.cc151
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.h60
-rw-r--r--chromium/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture_unittest.cc8
-rw-r--r--chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.cc292
-rw-r--r--chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.h106
-rw-r--r--chromium/content/common/gpu/client/gpu_video_encode_accelerator_host.cc323
-rw-r--r--chromium/content/common/gpu/client/gpu_video_encode_accelerator_host.h131
-rw-r--r--chromium/content/common/gpu/client/grcontext_for_gles2_interface.cc62
-rw-r--r--chromium/content/common/gpu/client/grcontext_for_gles2_interface.h42
-rw-r--r--chromium/content/common/gpu/client/grcontext_for_webgraphicscontext3d.cc108
-rw-r--r--chromium/content/common/gpu/client/grcontext_for_webgraphicscontext3d.h66
-rw-r--r--chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc126
-rw-r--r--chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h53
-rw-r--r--chromium/content/common/gpu/gpu_channel.cc1086
-rw-r--r--chromium/content/common/gpu/gpu_channel.h485
-rw-r--r--chromium/content/common/gpu/gpu_channel_manager.cc380
-rw-r--r--chromium/content/common/gpu/gpu_channel_manager.h227
-rw-r--r--chromium/content/common/gpu/gpu_channel_manager_unittest.cc120
-rw-r--r--chromium/content/common/gpu/gpu_channel_test_common.cc112
-rw-r--r--chromium/content/common/gpu/gpu_channel_test_common.h93
-rw-r--r--chromium/content/common/gpu/gpu_channel_unittest.cc329
-rw-r--r--chromium/content/common/gpu/gpu_command_buffer_stub.cc1269
-rw-r--r--chromium/content/common/gpu/gpu_command_buffer_stub.h307
-rw-r--r--chromium/content/common/gpu/gpu_config.h12
-rw-r--r--chromium/content/common/gpu/gpu_memory_buffer_factory.cc53
-rw-r--r--chromium/content/common/gpu/gpu_memory_buffer_factory.h71
-rw-r--r--chromium/content/common/gpu/gpu_memory_buffer_factory_io_surface.cc121
-rw-r--r--chromium/content/common/gpu/gpu_memory_buffer_factory_io_surface.h80
-rw-r--r--chromium/content/common/gpu/gpu_memory_buffer_factory_io_surface_unittest.cc16
-rw-r--r--chromium/content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.cc139
-rw-r--r--chromium/content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.h70
-rw-r--r--chromium/content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap_unittest.cc20
-rw-r--r--chromium/content/common/gpu/gpu_memory_buffer_factory_surface_texture.cc124
-rw-r--r--chromium/content/common/gpu/gpu_memory_buffer_factory_surface_texture.h75
-rw-r--r--chromium/content/common/gpu/gpu_memory_buffer_factory_surface_texture_unittest.cc16
-rw-r--r--chromium/content/common/gpu/gpu_memory_manager.cc124
-rw-r--r--chromium/content/common/gpu/gpu_memory_manager.h78
-rw-r--r--chromium/content/common/gpu/gpu_memory_tracking.cc37
-rw-r--r--chromium/content/common/gpu/gpu_memory_tracking.h53
-rw-r--r--chromium/content/common/gpu/gpu_memory_uma_stats.h33
-rw-r--r--chromium/content/common/gpu/gpu_messages.h878
-rw-r--r--chromium/content/common/gpu/gpu_result_codes.h20
-rw-r--r--chromium/content/common/gpu/gpu_stream_priority.h20
-rw-r--r--chromium/content/common/gpu/gpu_surface_lookup.cc33
-rw-r--r--chromium/content/common/gpu/gpu_surface_lookup.h40
-rw-r--r--chromium/content/common/gpu/gpu_watchdog.h28
-rw-r--r--chromium/content/common/gpu/image_transport_surface.cc302
-rw-r--r--chromium/content/common/gpu/image_transport_surface.h224
-rw-r--r--chromium/content/common/gpu/image_transport_surface_android.cc42
-rw-r--r--chromium/content/common/gpu/image_transport_surface_linux.cc28
-rw-r--r--chromium/content/common/gpu/image_transport_surface_mac.mm82
-rw-r--r--chromium/content/common/gpu/image_transport_surface_overlay_mac.h148
-rw-r--r--chromium/content/common/gpu/image_transport_surface_overlay_mac.mm522
-rw-r--r--chromium/content/common/gpu/image_transport_surface_win.cc53
-rw-r--r--chromium/content/common/gpu/media/OWNERS13
-rw-r--r--chromium/content/common/gpu/media/android_copying_backing_strategy.cc113
-rw-r--r--chromium/content/common/gpu/media/android_copying_backing_strategy.h10
-rw-r--r--chromium/content/common/gpu/media/android_deferred_rendering_backing_strategy.cc329
-rw-r--r--chromium/content/common/gpu/media/android_deferred_rendering_backing_strategy.h40
-rw-r--r--chromium/content/common/gpu/media/android_video_decode_accelerator.cc897
-rw-r--r--chromium/content/common/gpu/media/android_video_decode_accelerator.h206
-rw-r--r--chromium/content/common/gpu/media/android_video_decode_accelerator_unittest.cc23
-rw-r--r--chromium/content/common/gpu/media/android_video_encode_accelerator.cc86
-rw-r--r--chromium/content/common/gpu/media/android_video_encode_accelerator.h9
-rw-r--r--chromium/content/common/gpu/media/avda_codec_image.cc154
-rw-r--r--chromium/content/common/gpu/media/avda_codec_image.h60
-rw-r--r--chromium/content/common/gpu/media/avda_shared_state.cc14
-rw-r--r--chromium/content/common/gpu/media/avda_shared_state.h11
-rw-r--r--chromium/content/common/gpu/media/avda_state_provider.h3
-rw-r--r--chromium/content/common/gpu/media/dxva_video_decode_accelerator_win.cc1017
-rw-r--r--chromium/content/common/gpu/media/dxva_video_decode_accelerator_win.h118
-rw-r--r--chromium/content/common/gpu/media/fake_video_decode_accelerator.cc35
-rw-r--r--chromium/content/common/gpu/media/fake_video_decode_accelerator.h14
-rw-r--r--chromium/content/common/gpu/media/gpu_arc_video_service.cc92
-rw-r--r--chromium/content/common/gpu/media/gpu_arc_video_service.h68
-rw-r--r--chromium/content/common/gpu/media/gpu_jpeg_decode_accelerator.cc56
-rw-r--r--chromium/content/common/gpu/media/gpu_jpeg_decode_accelerator.h12
-rw-r--r--chromium/content/common/gpu/media/gpu_video_accelerator_util.cc155
-rw-r--r--chromium/content/common/gpu/media/gpu_video_accelerator_util.h63
-rw-r--r--chromium/content/common/gpu/media/gpu_video_decode_accelerator.cc446
-rw-r--r--chromium/content/common/gpu/media/gpu_video_decode_accelerator.h71
-rw-r--r--chromium/content/common/gpu/media/gpu_video_decode_accelerator_factory_impl.cc242
-rw-r--r--chromium/content/common/gpu/media/gpu_video_decode_accelerator_factory_impl.h123
-rw-r--r--chromium/content/common/gpu/media/gpu_video_decode_accelerator_helpers.h59
-rw-r--r--chromium/content/common/gpu/media/gpu_video_encode_accelerator.cc207
-rw-r--r--chromium/content/common/gpu/media/gpu_video_encode_accelerator.h41
-rw-r--r--chromium/content/common/gpu/media/media_channel.cc145
-rw-r--r--chromium/content/common/gpu/media/media_channel.h57
-rw-r--r--chromium/content/common/gpu/media/media_service.cc40
-rw-r--r--chromium/content/common/gpu/media/media_service.h42
-rw-r--r--chromium/content/common/gpu/media/rendering_helper.cc14
-rw-r--r--chromium/content/common/gpu/media/rendering_helper.h7
-rw-r--r--chromium/content/common/gpu/media/shared_memory_region.cc42
-rw-r--r--chromium/content/common/gpu/media/shared_memory_region.h57
-rw-r--r--chromium/content/common/gpu/media/v4l2_image_processor.cc30
-rw-r--r--chromium/content/common/gpu/media/v4l2_jpeg_decode_accelerator.cc45
-rw-r--r--chromium/content/common/gpu/media/v4l2_jpeg_decode_accelerator.h11
-rw-r--r--chromium/content/common/gpu/media/v4l2_slice_video_decode_accelerator.cc98
-rw-r--r--chromium/content/common/gpu/media/v4l2_slice_video_decode_accelerator.h29
-rw-r--r--chromium/content/common/gpu/media/v4l2_video_decode_accelerator.cc202
-rw-r--r--chromium/content/common/gpu/media/v4l2_video_decode_accelerator.h31
-rw-r--r--chromium/content/common/gpu/media/v4l2_video_encode_accelerator.cc103
-rw-r--r--chromium/content/common/gpu/media/vaapi_drm_picture.cc8
-rw-r--r--chromium/content/common/gpu/media/vaapi_drm_picture.h5
-rw-r--r--chromium/content/common/gpu/media/vaapi_jpeg_decode_accelerator.cc39
-rw-r--r--chromium/content/common/gpu/media/vaapi_jpeg_decode_accelerator.h9
-rw-r--r--chromium/content/common/gpu/media/vaapi_picture.cc6
-rw-r--r--chromium/content/common/gpu/media/vaapi_picture.h6
-rw-r--r--chromium/content/common/gpu/media/vaapi_tfp_picture.cc8
-rw-r--r--chromium/content/common/gpu/media/vaapi_tfp_picture.h5
-rw-r--r--chromium/content/common/gpu/media/vaapi_video_decode_accelerator.cc63
-rw-r--r--chromium/content/common/gpu/media/vaapi_video_decode_accelerator.h30
-rw-r--r--chromium/content/common/gpu/media/vaapi_video_encode_accelerator.cc40
-rw-r--r--chromium/content/common/gpu/media/vaapi_wrapper.cc24
-rw-r--r--chromium/content/common/gpu/media/vaapi_wrapper.h2
-rw-r--r--chromium/content/common/gpu/media/video_decode_accelerator_unittest.cc187
-rw-r--r--chromium/content/common/gpu/media/video_encode_accelerator_unittest.cc58
-rw-r--r--chromium/content/common/gpu/media/vt_video_decode_accelerator_mac.cc135
-rw-r--r--chromium/content/common/gpu/media/vt_video_decode_accelerator_mac.h19
-rw-r--r--chromium/content/common/gpu/media/vt_video_encode_accelerator_mac.cc552
-rw-r--r--chromium/content/common/gpu/media/vt_video_encode_accelerator_mac.h142
-rw-r--r--chromium/content/common/gpu/stream_texture_android.cc386
-rw-r--r--chromium/content/common/gpu/stream_texture_android.h110
-rw-r--r--chromium/content/common/gpu/x_util.h40
-rw-r--r--chromium/content/common/gpu_host_messages.h300
-rw-r--r--chromium/content/common/gpu_process_launch_causes.h (renamed from chromium/content/common/gpu/gpu_process_launch_causes.h)8
-rw-r--r--chromium/content/common/host_discardable_shared_memory_manager.cc8
-rw-r--r--chromium/content/common/host_discardable_shared_memory_manager.h1
-rw-r--r--chromium/content/common/host_shared_bitmap_manager.cc5
-rw-r--r--chromium/content/common/id_type.h112
-rw-r--r--chromium/content/common/id_type_unittest.cc205
-rw-r--r--chromium/content/common/image_downloader/image_downloader.mojom23
-rw-r--r--chromium/content/common/in_process_child_thread_params.cc9
-rw-r--r--chromium/content/common/in_process_child_thread_params.h7
-rw-r--r--chromium/content/common/indexed_db/indexed_db_messages.h17
-rw-r--r--chromium/content/common/indexed_db/indexed_db_param_traits.cc14
-rw-r--r--chromium/content/common/indexed_db/indexed_db_param_traits.h18
-rw-r--r--chromium/content/common/input/event_with_latency_info.h63
-rw-r--r--chromium/content/common/input/event_with_latency_info_unittest.cc (renamed from chromium/content/browser/renderer_host/event_with_latency_info_unittest.cc)31
-rw-r--r--chromium/content/common/input/input_event_ack_state.h3
-rw-r--r--chromium/content/common/input/input_event_dispatch_type.h26
-rw-r--r--chromium/content/common/input/input_event_utils.cc17
-rw-r--r--chromium/content/common/input/input_event_utils.h17
-rw-r--r--chromium/content/common/input/input_param_traits.cc24
-rw-r--r--chromium/content/common/input/input_param_traits.h12
-rw-r--r--chromium/content/common/input/input_param_traits_unittest.cc60
-rw-r--r--chromium/content/common/input/synthetic_gesture_params.h4
-rw-r--r--chromium/content/common/input/synthetic_pointer_action_params.cc48
-rw-r--r--chromium/content/common/input/synthetic_pointer_action_params.h86
-rw-r--r--chromium/content/common/input/synthetic_web_input_event_builders.cc17
-rw-r--r--chromium/content/common/input/synthetic_web_input_event_builders.h8
-rw-r--r--chromium/content/common/input/web_input_event_queue.h79
-rw-r--r--chromium/content/common/input/web_input_event_traits.cc45
-rw-r--r--chromium/content/common/input/web_input_event_traits.h2
-rw-r--r--chromium/content/common/input/web_input_event_traits_unittest.cc28
-rw-r--r--chromium/content/common/input/web_touch_event_traits.cc4
-rw-r--r--chromium/content/common/input_messages.h27
-rw-r--r--chromium/content/common/leveldb_wrapper.mojom51
-rw-r--r--chromium/content/common/mac/attributed_string_coder.h17
-rw-r--r--chromium/content/common/mac/attributed_string_coder.mm10
-rw-r--r--chromium/content/common/media/OWNERS6
-rw-r--r--chromium/content/common/media/audio_messages.h1
-rw-r--r--chromium/content/common/media/media_param_traits.cc9
-rw-r--r--chromium/content/common/media/media_param_traits.h12
-rw-r--r--chromium/content/common/media/media_player_delegate_messages.h51
-rw-r--r--chromium/content/common/media/media_player_messages_android.h8
-rw-r--r--chromium/content/common/media/media_session_messages_android.h11
-rw-r--r--chromium/content/common/media/media_stream_options.cc2
-rw-r--r--chromium/content/common/media/media_stream_options.h1
-rw-r--r--chromium/content/common/media/surface_view_manager_messages_android.h26
-rw-r--r--chromium/content/common/media/video_capture_messages.h6
-rw-r--r--chromium/content/common/memory_benchmark_messages.h15
-rw-r--r--chromium/content/common/message_router.cc57
-rw-r--r--chromium/content/common/message_router.h71
-rw-r--r--chromium/content/common/mojo/DEPS5
-rw-r--r--chromium/content/common/mojo/channel_init.cc46
-rw-r--r--chromium/content/common/mojo/channel_init.h26
-rw-r--r--chromium/content/common/mojo/current_thread_loader.cc25
-rw-r--r--chromium/content/common/mojo/current_thread_loader.h46
-rw-r--r--chromium/content/common/mojo/mojo_messages.h5
-rw-r--r--chromium/content/common/mojo/mojo_shell_connection_impl.cc120
-rw-r--r--chromium/content/common/mojo/mojo_shell_connection_impl.h56
-rw-r--r--chromium/content/common/mojo/service_registry_impl.cc35
-rw-r--r--chromium/content/common/mojo/service_registry_impl.h33
-rw-r--r--chromium/content/common/mojo/static_loader.cc93
-rw-r--r--chromium/content/common/mojo/static_loader.h66
-rw-r--r--chromium/content/common/navigation_params.cc41
-rw-r--r--chromium/content/common/navigation_params.h20
-rw-r--r--chromium/content/common/net/url_request_service_worker_data.cc17
-rw-r--r--chromium/content/common/net/url_request_service_worker_data.h28
-rw-r--r--chromium/content/common/notification_constants.h12
-rw-r--r--chromium/content/common/one_writer_seqlock_unittest.cc8
-rw-r--r--chromium/content/common/origin_trials/trial_token.cc193
-rw-r--r--chromium/content/common/origin_trials/trial_token.h90
-rw-r--r--chromium/content/common/origin_trials/trial_token_unittest.cc300
-rw-r--r--chromium/content/common/origin_trials/trial_token_validator.cc30
-rw-r--r--chromium/content/common/origin_trials/trial_token_validator.h26
-rw-r--r--chromium/content/common/origin_trials/trial_token_validator_unittest.cc160
-rw-r--r--chromium/content/common/origin_util.cc2
-rw-r--r--chromium/content/common/p2p_messages.h5
-rw-r--r--chromium/content/common/page_messages.h25
-rw-r--r--chromium/content/common/page_state_serialization.cc6
-rw-r--r--chromium/content/common/page_state_serialization.h1
-rw-r--r--chromium/content/common/pepper_plugin_list.cc13
-rw-r--r--chromium/content/common/permission_service.mojom42
-rw-r--r--chromium/content/common/platform_notification_messages.h42
-rw-r--r--chromium/content/common/plugin_constants_win.cc29
-rw-r--r--chromium/content/common/plugin_constants_win.h52
-rw-r--r--chromium/content/common/plugin_list.cc160
-rw-r--r--chromium/content/common/plugin_list.h72
-rw-r--r--chromium/content/common/plugin_list_mac.mm307
-rw-r--r--chromium/content/common/plugin_list_posix.cc37
-rw-r--r--chromium/content/common/plugin_list_unittest.cc8
-rw-r--r--chromium/content/common/plugin_list_win.cc493
-rw-r--r--chromium/content/common/plugin_process_messages.h87
-rw-r--r--chromium/content/common/presentation/presentation_service.mojom14
-rw-r--r--chromium/content/common/process_control.mojom7
-rw-r--r--chromium/content/common/process_type.cc2
-rw-r--r--chromium/content/common/push_messaging_messages.h13
-rw-r--r--chromium/content/common/render_frame_setup.mojom11
-rw-r--r--chromium/content/common/resize_params.cc20
-rw-r--r--chromium/content/common/resize_params.h58
-rw-r--r--chromium/content/common/resource_messages.cc31
-rw-r--r--chromium/content/common/resource_messages.h55
-rw-r--r--chromium/content/common/sandbox_init_mac.cc11
-rw-r--r--chromium/content/common/sandbox_init_win.cc15
-rw-r--r--chromium/content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.cc85
-rw-r--r--chromium/content/common/sandbox_linux/bpf_renderer_policy_linux.cc23
-rw-r--r--chromium/content/common/sandbox_linux/bpf_utility_policy_linux.cc3
-rw-r--r--chromium/content/common/sandbox_linux/sandbox_linux.h2
-rw-r--r--chromium/content/common/sandbox_mac.h3
-rw-r--r--chromium/content/common/sandbox_mac.mm87
-rw-r--r--chromium/content/common/sandbox_mac_diraccess_unittest.mm1
-rw-r--r--chromium/content/common/sandbox_mac_system_access_unittest.mm11
-rw-r--r--chromium/content/common/sandbox_util.cc26
-rw-r--r--chromium/content/common/sandbox_win.cc66
-rw-r--r--chromium/content/common/service_port_service.mojom37
-rw-r--r--chromium/content/common/service_port_type_converters.cc32
-rw-r--r--chromium/content/common/service_port_type_converters.h31
-rw-r--r--chromium/content/common/service_worker/embedded_worker_messages.h15
-rw-r--r--chromium/content/common/service_worker/embedded_worker_settings.h19
-rw-r--r--chromium/content/common/service_worker/embedded_worker_setup.mojom11
-rw-r--r--chromium/content/common/service_worker/service_worker_client_info.cc23
-rw-r--r--chromium/content/common/service_worker/service_worker_client_info.h6
-rw-r--r--chromium/content/common/service_worker/service_worker_messages.h94
-rw-r--r--chromium/content/common/service_worker/service_worker_status_code.h51
-rw-r--r--chromium/content/common/service_worker/service_worker_type_converters.cc10
-rw-r--r--chromium/content/common/service_worker/service_worker_type_converters.h4
-rw-r--r--chromium/content/common/service_worker/service_worker_types.cc40
-rw-r--r--chromium/content/common/service_worker/service_worker_types.h39
-rw-r--r--chromium/content/common/service_worker/service_worker_utils.cc20
-rw-r--r--chromium/content/common/service_worker/service_worker_utils.h4
-rw-r--r--chromium/content/common/service_worker/service_worker_utils_unittest.cc2
-rw-r--r--chromium/content/common/site_isolation_policy.cc23
-rw-r--r--chromium/content/common/site_isolation_policy.h15
-rw-r--r--chromium/content/common/storage_partition_service.mojom15
-rw-r--r--chromium/content/common/swapped_out_messages.cc7
-rw-r--r--chromium/content/common/text_input_client_messages.h2
-rw-r--r--chromium/content/common/url_schemes.cc34
-rw-r--r--chromium/content/common/url_schemes.h12
-rw-r--r--chromium/content/common/utility_messages.h32
-rw-r--r--chromium/content/common/view_messages.h188
-rw-r--r--chromium/content/common/vr_service.mojom2
-rw-r--r--chromium/content/common/wake_lock_service.mojom2
-rw-r--r--chromium/content/common/webplugin_geometry.cc27
-rw-r--r--chromium/content/common/webplugin_geometry.h46
-rw-r--r--chromium/content/common/websocket_messages.h30
-rw-r--r--chromium/content/common/worker_messages.h11
-rw-r--r--chromium/content/content.gni12
-rw-r--r--chromium/content/content.gyp292
-rw-r--r--chromium/content/content_app.gypi15
-rw-r--r--chromium/content/content_browser.gypi412
-rw-r--r--chromium/content/content_browsertests.isolate3
-rw-r--r--chromium/content/content_browsertests_apk.isolate2
-rw-r--r--chromium/content/content_child.gypi115
-rw-r--r--chromium/content/content_common.gypi355
-rw-r--r--chromium/content/content_common_mojo_bindings.gyp36
-rw-r--r--chromium/content/content_gpu.gypi7
-rw-r--r--chromium/content/content_jni.gypi3
-rw-r--r--chromium/content/content_plugin.gypi46
-rw-r--r--chromium/content/content_ppapi_plugin.gypi1
-rw-r--r--chromium/content/content_renderer.gypi73
-rw-r--r--chromium/content/content_resources.grd3
-rw-r--r--chromium/content/content_resources.gypi8
-rw-r--r--chromium/content/content_shell.gypi195
-rw-r--r--chromium/content/content_shell_and_tests.gyp10
-rw-r--r--chromium/content/content_shell_test_apk.isolate1
-rw-r--r--chromium/content/content_shell_test_apk_run.isolate4
-rw-r--r--chromium/content/content_site_isolation_browsertests.isolate21
-rw-r--r--chromium/content/content_tests.gypi1430
-rw-r--r--chromium/content/content_unittests_apk.isolate1
-rw-r--r--chromium/content/content_utility.gypi4
-rw-r--r--chromium/content/gpu/BUILD.gn36
-rw-r--r--chromium/content/gpu/DEPS2
-rw-r--r--chromium/content/gpu/gpu_child_thread.cc249
-rw-r--r--chromium/content/gpu/gpu_child_thread.h105
-rw-r--r--chromium/content/gpu/gpu_main.cc45
-rw-r--r--chromium/content/gpu/gpu_process.cc4
-rw-r--r--chromium/content/gpu/gpu_process.h2
-rw-r--r--chromium/content/gpu/gpu_process_control_impl.cc24
-rw-r--r--chromium/content/gpu/gpu_process_control_impl.h2
-rw-r--r--chromium/content/gpu/gpu_watchdog_thread.cc55
-rw-r--r--chromium/content/gpu/gpu_watchdog_thread.h25
-rw-r--r--chromium/content/gpu/in_process_gpu_thread.cc28
-rw-r--r--chromium/content/gpu/in_process_gpu_thread.h13
-rw-r--r--chromium/content/plugin/BUILD.gn46
-rw-r--r--chromium/content/plugin/DEPS9
-rw-r--r--chromium/content/plugin/OWNERS3
-rw-r--r--chromium/content/plugin/plugin_channel.cc331
-rw-r--r--chromium/content/plugin/plugin_channel.h111
-rw-r--r--chromium/content/plugin/plugin_interpose_util_mac.h16
-rw-r--r--chromium/content/plugin/plugin_interpose_util_mac.mm261
-rw-r--r--chromium/content/plugin/plugin_main.cc71
-rw-r--r--chromium/content/plugin/plugin_main_mac.mm16
-rw-r--r--chromium/content/plugin/plugin_thread.cc160
-rw-r--r--chromium/content/plugin/plugin_thread.h65
-rw-r--r--chromium/content/plugin/webplugin_accelerated_surface_proxy_mac.cc83
-rw-r--r--chromium/content/plugin/webplugin_accelerated_surface_proxy_mac.h49
-rw-r--r--chromium/content/plugin/webplugin_delegate_stub.cc352
-rw-r--r--chromium/content/plugin/webplugin_delegate_stub.h117
-rw-r--r--chromium/content/plugin/webplugin_proxy.cc566
-rw-r--r--chromium/content/plugin/webplugin_proxy.h212
-rw-r--r--chromium/content/ppapi_plugin/BUILD.gn14
-rw-r--r--chromium/content/ppapi_plugin/DEPS3
-rw-r--r--chromium/content/ppapi_plugin/ppapi_blink_platform_impl.cc8
-rw-r--r--chromium/content/ppapi_plugin/ppapi_plugin_main.cc26
-rw-r--r--chromium/content/ppapi_plugin/ppapi_thread.cc36
-rw-r--r--chromium/content/public/DEPS2
-rw-r--r--chromium/content/public/android/BUILD.gn214
-rw-r--r--chromium/content/public/app/BUILD.gn16
-rw-r--r--chromium/content/public/app/DEPS2
-rw-r--r--chromium/content/public/app/content_main_delegate.cc24
-rw-r--r--chromium/content/public/app/content_main_delegate.h8
-rw-r--r--chromium/content/public/app/mojo/content_browser_manifest.json14
-rw-r--r--chromium/content/public/app/mojo/content_renderer_manifest.json5
-rw-r--r--chromium/content/public/browser/BUILD.gn43
-rw-r--r--chromium/content/public/browser/access_token_store.h10
-rw-r--r--chromium/content/public/browser/android/compositor.h4
-rw-r--r--chromium/content/public/browser/android/download_controller_android.h16
-rw-r--r--chromium/content/public/browser/android/service_registry_android.h51
-rw-r--r--chromium/content/public/browser/android/synchronous_compositor.cc27
-rw-r--r--chromium/content/public/browser/android/synchronous_compositor.h26
-rw-r--r--chromium/content/public/browser/arc_video_host_delegate.h21
-rw-r--r--chromium/content/public/browser/ax_event_notification_details.cc3
-rw-r--r--chromium/content/public/browser/ax_event_notification_details.h1
-rw-r--r--chromium/content/public/browser/background_tracing_config.h1
-rw-r--r--chromium/content/public/browser/background_tracing_manager.h1
-rw-r--r--chromium/content/public/browser/bluetooth_chooser.h8
-rw-r--r--chromium/content/public/browser/browser_child_process_host.h4
-rw-r--r--chromium/content/public/browser/browser_child_process_observer.h6
-rw-r--r--chromium/content/public/browser/browser_context.h48
-rw-r--r--chromium/content/public/browser/browser_message_filter.cc30
-rw-r--r--chromium/content/public/browser/browser_message_filter.h5
-rw-r--r--chromium/content/public/browser/content_browser_client.cc51
-rw-r--r--chromium/content/public/browser/content_browser_client.h98
-rw-r--r--chromium/content/public/browser/cookie_store_factory.h9
-rw-r--r--chromium/content/public/browser/desktop_media_id.cc20
-rw-r--r--chromium/content/public/browser/desktop_media_id.h6
-rw-r--r--chromium/content/public/browser/download_interrupt_reason_values.h7
-rw-r--r--chromium/content/public/browser/download_item.h22
-rw-r--r--chromium/content/public/browser/download_manager.h32
-rw-r--r--chromium/content/public/browser/download_save_info.cc9
-rw-r--r--chromium/content/public/browser/download_save_info.h14
-rw-r--r--chromium/content/public/browser/download_url_parameters.h133
-rw-r--r--chromium/content/public/browser/geolocation_provider.h6
-rw-r--r--chromium/content/public/browser/gpu_data_manager.h4
-rw-r--r--chromium/content/public/browser/gpu_data_manager_observer.h7
-rw-r--r--chromium/content/public/browser/gpu_service_registry.cc18
-rw-r--r--chromium/content/public/browser/gpu_service_registry.h19
-rw-r--r--chromium/content/public/browser/gpu_utils.cc103
-rw-r--r--chromium/content/public/browser/gpu_utils.h17
-rw-r--r--chromium/content/public/browser/host_zoom_map.h1
-rw-r--r--chromium/content/public/browser/indexed_db_context.h3
-rw-r--r--chromium/content/public/browser/javascript_dialog_manager.h2
-rw-r--r--chromium/content/public/browser/memory_pressure_controller.cc27
-rw-r--r--chromium/content/public/browser/memory_pressure_controller.h40
-rw-r--r--chromium/content/public/browser/message_port_delegate.h5
-rw-r--r--chromium/content/public/browser/mojo_app_connection.h23
-rw-r--r--chromium/content/public/browser/native_web_keyboard_event.h24
-rw-r--r--chromium/content/public/browser/navigation_controller.h26
-rw-r--r--chromium/content/public/browser/navigation_details.cc3
-rw-r--r--chromium/content/public/browser/navigation_details.h1
-rw-r--r--chromium/content/public/browser/navigation_entry.h7
-rw-r--r--chromium/content/public/browser/navigation_handle.cc4
-rw-r--r--chromium/content/public/browser/navigation_handle.h32
-rw-r--r--chromium/content/public/browser/navigation_throttle.cc5
-rw-r--r--chromium/content/public/browser/navigation_throttle.h9
-rw-r--r--chromium/content/public/browser/navigator_connect_context.h36
-rw-r--r--chromium/content/public/browser/navigator_connect_service_factory.h49
-rw-r--r--chromium/content/public/browser/notification_event_dispatcher.h16
-rw-r--r--chromium/content/public/browser/page_navigator.cc2
-rw-r--r--chromium/content/public/browser/page_navigator.h1
-rw-r--r--chromium/content/public/browser/permission_manager.h12
-rw-r--r--chromium/content/public/browser/permission_type.h1
-rw-r--r--chromium/content/public/browser/platform_notification_service.h13
-rw-r--r--chromium/content/public/browser/plugin_service.h36
-rw-r--r--chromium/content/public/browser/plugin_service_filter.h7
-rw-r--r--chromium/content/public/browser/presentation_service_delegate.h19
-rw-r--r--chromium/content/public/browser/presentation_session.h8
-rw-r--r--chromium/content/public/browser/push_messaging_service.h29
-rw-r--r--chromium/content/public/browser/readback_types.h5
-rw-r--r--chromium/content/public/browser/render_frame_host.h26
-rw-r--r--chromium/content/public/browser/render_process_host.h18
-rw-r--r--chromium/content/public/browser/render_view_host.h9
-rw-r--r--chromium/content/public/browser/render_widget_host_view.h24
-rw-r--r--chromium/content/public/browser/render_widget_host_view_mac_delegate.h3
-rw-r--r--chromium/content/public/browser/resource_context.h2
-rw-r--r--chromium/content/public/browser/resource_dispatcher_host.cc28
-rw-r--r--chromium/content/public/browser/resource_dispatcher_host.h48
-rw-r--r--chromium/content/public/browser/resource_request_info.h5
-rw-r--r--chromium/content/public/browser/screen_orientation_provider.cc2
-rw-r--r--chromium/content/public/browser/screen_orientation_provider.h3
-rw-r--r--chromium/content/public/browser/service_worker_context.h17
-rw-r--r--chromium/content/public/browser/service_worker_usage_info.cc3
-rw-r--r--chromium/content/public/browser/service_worker_usage_info.h1
-rw-r--r--chromium/content/public/browser/site_instance.h24
-rw-r--r--chromium/content/public/browser/speech_recognition_session_config.cc3
-rw-r--r--chromium/content/public/browser/speech_recognition_session_config.h1
-rw-r--r--chromium/content/public/browser/speech_recognition_session_context.cc3
-rw-r--r--chromium/content/public/browser/speech_recognition_session_context.h1
-rw-r--r--chromium/content/public/browser/storage_partition.h2
-rw-r--r--chromium/content/public/browser/tracing_controller.h62
-rw-r--r--chromium/content/public/browser/utility_process_host.h9
-rw-r--r--chromium/content/public/browser/web_contents.cc10
-rw-r--r--chromium/content/public/browser/web_contents.h42
-rw-r--r--chromium/content/public/browser/web_contents_delegate.cc9
-rw-r--r--chromium/content/public/browser/web_contents_delegate.h18
-rw-r--r--chromium/content/public/browser/web_contents_observer.h39
-rw-r--r--chromium/content/public/browser/web_ui_data_source.h3
-rw-r--r--chromium/content/public/browser/zygote_handle_linux.h24
-rw-r--r--chromium/content/public/browser/zygote_host_linux.h8
-rw-r--r--chromium/content/public/child/BUILD.gn2
-rw-r--r--chromium/content/public/child/child_thread.h26
-rw-r--r--chromium/content/public/child/request_peer.h21
-rw-r--r--chromium/content/public/child/resource_dispatcher_delegate.h20
-rw-r--r--chromium/content/public/common/BUILD.gn43
-rw-r--r--chromium/content/public/common/appcache_info.h1
-rw-r--r--chromium/content/public/common/background_sync.mojom19
-rw-r--r--chromium/content/public/common/bindings_policy.h10
-rw-r--r--chromium/content/public/common/common_param_traits.cc72
-rw-r--r--chromium/content/public/common/common_param_traits.h45
-rw-r--r--chromium/content/public/common/common_param_traits_macros.h9
-rw-r--r--chromium/content/public/common/content_client.cc18
-rw-r--r--chromium/content/public/common/content_client.h28
-rw-r--r--chromium/content/public/common/content_constants.cc1
-rw-r--r--chromium/content/public/common/content_descriptors.h10
-rw-r--r--chromium/content/public/common/content_features.cc76
-rw-r--r--chromium/content/public/common/content_features.h14
-rw-r--r--chromium/content/public/common/content_switches.cc233
-rw-r--r--chromium/content/public/common/content_switches.h63
-rw-r--r--chromium/content/public/common/context_menu_params.cc2
-rw-r--r--chromium/content/public/common/context_menu_params.h2
-rw-r--r--chromium/content/public/common/drop_data.cc2
-rw-r--r--chromium/content/public/common/drop_data.h1
-rw-r--r--chromium/content/public/common/dwrite_font_platform_win.h47
-rw-r--r--chromium/content/public/common/favicon_url.cc2
-rw-r--r--chromium/content/public/common/favicon_url.h1
-rw-r--r--chromium/content/public/common/feature_h264_with_openh264_ffmpeg.cc17
-rw-r--r--chromium/content/public/common/feature_h264_with_openh264_ffmpeg.h22
-rw-r--r--chromium/content/public/common/file_chooser_file_info.cc3
-rw-r--r--chromium/content/public/common/file_chooser_file_info.h1
-rw-r--r--chromium/content/public/common/file_chooser_params.cc2
-rw-r--r--chromium/content/public/common/file_chooser_params.h1
-rw-r--r--chromium/content/public/common/frame_navigate_params.cc3
-rw-r--r--chromium/content/public/common/frame_navigate_params.h7
-rw-r--r--chromium/content/public/common/geoposition.cc2
-rw-r--r--chromium/content/public/common/geoposition.h2
-rw-r--r--chromium/content/public/common/gpu_memory_stats.cc25
-rw-r--r--chromium/content/public/common/gpu_memory_stats.h50
-rw-r--r--chromium/content/public/common/manifest.cc4
-rw-r--r--chromium/content/public/common/manifest.h2
-rw-r--r--chromium/content/public/common/media_metadata.cc23
-rw-r--r--chromium/content/public/common/media_metadata.h40
-rw-r--r--chromium/content/public/common/media_stream_request.cc8
-rw-r--r--chromium/content/public/common/media_stream_request.h5
-rw-r--r--chromium/content/public/common/mojo_channel_switches.cc32
-rw-r--r--chromium/content/public/common/mojo_channel_switches.h4
-rw-r--r--chromium/content/public/common/mojo_geoposition.mojom56
-rw-r--r--chromium/content/public/common/mojo_shell_connection.h32
-rw-r--r--chromium/content/public/common/navigator_connect_client.cc21
-rw-r--r--chromium/content/public/common/navigator_connect_client.h33
-rw-r--r--chromium/content/public/common/notification_resources.cc16
-rw-r--r--chromium/content/public/common/notification_resources.h36
-rw-r--r--chromium/content/public/common/pepper_plugin_info.cc6
-rw-r--r--chromium/content/public/common/pepper_plugin_info.h15
-rw-r--r--chromium/content/public/common/permission_status.mojom12
-rw-r--r--chromium/content/public/common/platform_notification_data.cc6
-rw-r--r--chromium/content/public/common/platform_notification_data.h33
-rw-r--r--chromium/content/public/common/process_type.h4
-rw-r--r--chromium/content/public/common/push_event_payload.h37
-rw-r--r--chromium/content/public/common/push_subscription_options.h32
-rw-r--r--chromium/content/public/common/referrer.cc2
-rw-r--r--chromium/content/public/common/renderer_preferences.cc3
-rw-r--r--chromium/content/public/common/renderer_preferences.h1
-rw-r--r--chromium/content/public/common/resource_response.cc1
-rw-r--r--chromium/content/public/common/resource_response_info.cc3
-rw-r--r--chromium/content/public/common/resource_response_info.h9
-rw-r--r--chromium/content/public/common/sandbox_init.h19
-rw-r--r--chromium/content/public/common/sandboxed_process_launcher_delegate.cc6
-rw-r--r--chromium/content/public/common/sandboxed_process_launcher_delegate.h7
-rw-r--r--chromium/content/public/common/service_registry.h12
-rw-r--r--chromium/content/public/common/service_worker_event_status.mojom2
-rw-r--r--chromium/content/public/common/speech_recognition_result.cc3
-rw-r--r--chromium/content/public/common/speech_recognition_result.h1
-rw-r--r--chromium/content/public/common/ssl_status.cc2
-rw-r--r--chromium/content/public/common/ssl_status.h1
-rw-r--r--chromium/content/public/common/url_constants.cc8
-rw-r--r--chromium/content/public/common/url_constants.h7
-rw-r--r--chromium/content/public/common/url_utils.cc5
-rw-r--r--chromium/content/public/common/web_preferences.cc77
-rw-r--r--chromium/content/public/common/web_preferences.h21
-rw-r--r--chromium/content/public/common/webplugininfo.cc6
-rw-r--r--chromium/content/public/common/webplugininfo.h2
-rw-r--r--chromium/content/public/common/zygote_fork_delegate_linux.h1
-rw-r--r--chromium/content/public/common/zygote_handle.h23
-rw-r--r--chromium/content/public/gpu/BUILD.gn42
-rw-r--r--chromium/content/public/gpu/DEPS10
-rw-r--r--chromium/content/public/gpu/content_gpu_client.h27
-rw-r--r--chromium/content/public/gpu/gpu_video_decode_accelerator_factory.cc72
-rw-r--r--chromium/content/public/gpu/gpu_video_decode_accelerator_factory.h93
-rw-r--r--chromium/content/public/plugin/BUILD.gn30
-rw-r--r--chromium/content/public/plugin/content_plugin_client.h28
-rw-r--r--chromium/content/public/renderer/BUILD.gn15
-rw-r--r--chromium/content/public/renderer/DEPS1
-rw-r--r--chromium/content/public/renderer/content_renderer_client.cc16
-rw-r--r--chromium/content/public/renderer/content_renderer_client.h30
-rw-r--r--chromium/content/public/renderer/document_state.h2
-rw-r--r--chromium/content/public/renderer/media_stream_api.cc134
-rw-r--r--chromium/content/public/renderer/media_stream_api.h54
-rw-r--r--chromium/content/public/renderer/media_stream_audio_renderer.h28
-rw-r--r--chromium/content/public/renderer/media_stream_audio_sink.cc11
-rw-r--r--chromium/content/public/renderer/media_stream_utils.cc139
-rw-r--r--chromium/content/public/renderer/media_stream_utils.h64
-rw-r--r--chromium/content/public/renderer/media_stream_video_sink.cc35
-rw-r--r--chromium/content/public/renderer/media_stream_video_sink.h47
-rw-r--r--chromium/content/public/renderer/render_frame_observer.h8
-rw-r--r--chromium/content/public/renderer/render_process_observer.h3
-rw-r--r--chromium/content/public/renderer/render_thread.h25
-rw-r--r--chromium/content/public/renderer/render_view.h10
-rw-r--r--chromium/content/public/renderer/render_view_observer.cc35
-rw-r--r--chromium/content/public/renderer/render_view_observer.h2
-rw-r--r--chromium/content/public/renderer/resource_fetcher.h3
-rw-r--r--chromium/content/public/renderer/video_encode_accelerator.cc2
-rw-r--r--chromium/content/public/utility/BUILD.gn2
-rw-r--r--chromium/content/public/utility/content_utility_client.h4
-rw-r--r--chromium/content/renderer/BUILD.gn69
-rw-r--r--chromium/content/renderer/DEPS4
-rw-r--r--chromium/content/renderer/OWNERS3
-rw-r--r--chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc7
-rw-r--r--chromium/content/renderer/accessibility/blink_ax_tree_source.cc71
-rw-r--r--chromium/content/renderer/accessibility/renderer_accessibility.cc32
-rw-r--r--chromium/content/renderer/accessibility/renderer_accessibility_browsertest.cc100
-rw-r--r--chromium/content/renderer/android/phone_number_detector.cc8
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_external_begin_frame_source.cc10
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_external_begin_frame_source.h4
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_factory.cc4
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_factory.h8
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_filter.cc74
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_filter.h25
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_output_surface.cc51
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_output_surface.h17
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_proxy.cc130
-rw-r--r--chromium/content/renderer/android/synchronous_compositor_proxy.h35
-rw-r--r--chromium/content/renderer/background_sync/background_sync_client_impl.cc57
-rw-r--r--chromium/content/renderer/background_sync/background_sync_client_impl.h22
-rw-r--r--chromium/content/renderer/battery_status/OWNERS1
-rw-r--r--chromium/content/renderer/battery_status/battery_status_dispatcher.cc49
-rw-r--r--chromium/content/renderer/battery_status/battery_status_dispatcher.h38
-rw-r--r--chromium/content/renderer/battery_status/battery_status_dispatcher_unittest.cc83
-rw-r--r--chromium/content/renderer/bluetooth/bluetooth_dispatcher.cc194
-rw-r--r--chromium/content/renderer/bluetooth/bluetooth_dispatcher.h73
-rw-r--r--chromium/content/renderer/bluetooth/web_bluetooth_impl.cc69
-rw-r--r--chromium/content/renderer/bluetooth/web_bluetooth_impl.h53
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin.cc99
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin.h6
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin_manager.cc26
-rw-r--r--chromium/content/renderer/browser_plugin/browser_plugin_manager.h3
-rw-r--r--chromium/content/renderer/browser_render_view_browsertest.cc12
-rw-r--r--chromium/content/renderer/cache_storage/cache_storage_dispatcher.cc23
-rw-r--r--chromium/content/renderer/cache_storage/cache_storage_dispatcher.h14
-rw-r--r--chromium/content/renderer/cache_storage/webserviceworkercachestorage_impl.cc5
-rw-r--r--chromium/content/renderer/cache_storage/webserviceworkercachestorage_impl.h5
-rw-r--r--chromium/content/renderer/child_frame_compositing_helper.cc191
-rw-r--r--chromium/content/renderer/child_frame_compositing_helper.h32
-rw-r--r--chromium/content/renderer/device_sensors/OWNERS2
-rw-r--r--chromium/content/renderer/devtools/devtools_agent.cc71
-rw-r--r--chromium/content/renderer/devtools/devtools_agent.h6
-rw-r--r--chromium/content/renderer/devtools/render_widget_screen_metrics_emulator.cc177
-rw-r--r--chromium/content/renderer/devtools/render_widget_screen_metrics_emulator.h89
-rw-r--r--chromium/content/renderer/devtools/render_widget_screen_metrics_emulator_delegate.h44
-rw-r--r--chromium/content/renderer/devtools/v8_sampling_profiler.cc46
-rw-r--r--chromium/content/renderer/devtools/v8_sampling_profiler.h1
-rw-r--r--chromium/content/renderer/devtools/v8_sampling_profiler_browsertest.cc1
-rw-r--r--chromium/content/renderer/dom_serializer_browsertest.cc60
-rw-r--r--chromium/content/renderer/dom_storage/DEPS11
-rw-r--r--chromium/content/renderer/dom_storage/dom_storage_cached_area.cc4
-rw-r--r--chromium/content/renderer/dom_storage/dom_storage_cached_area.h2
-rw-r--r--chromium/content/renderer/dom_storage/dom_storage_dispatcher.cc11
-rw-r--r--chromium/content/renderer/dom_storage/local_storage_area.cc57
-rw-r--r--chromium/content/renderer/dom_storage/local_storage_area.h48
-rw-r--r--chromium/content/renderer/dom_storage/local_storage_cached_area.cc336
-rw-r--r--chromium/content/renderer/dom_storage/local_storage_cached_area.h114
-rw-r--r--chromium/content/renderer/dom_storage/local_storage_cached_areas.cc34
-rw-r--r--chromium/content/renderer/dom_storage/local_storage_cached_areas.h50
-rw-r--r--chromium/content/renderer/dom_storage/local_storage_namespace.cc40
-rw-r--r--chromium/content/renderer/dom_storage/local_storage_namespace.h34
-rw-r--r--chromium/content/renderer/dom_storage/webstoragearea_impl.cc4
-rw-r--r--chromium/content/renderer/dom_storage/webstoragearea_impl.h1
-rw-r--r--chromium/content/renderer/dom_storage/webstoragenamespace_impl.cc3
-rw-r--r--chromium/content/renderer/drop_data_builder.cc8
-rw-r--r--chromium/content/renderer/external_popup_menu_browsertest.cc8
-rw-r--r--chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc2
-rw-r--r--chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.h3
-rw-r--r--chromium/content/renderer/fetchers/resource_fetcher_impl.cc3
-rw-r--r--chromium/content/renderer/fetchers/resource_fetcher_impl.h3
-rw-r--r--chromium/content/renderer/frame_blame_context.cc41
-rw-r--r--chromium/content/renderer/frame_blame_context.h26
-rw-r--r--chromium/content/renderer/geolocation_dispatcher.cc21
-rw-r--r--chromium/content/renderer/geolocation_dispatcher.h13
-rw-r--r--chromium/content/renderer/gpu/compositor_dependencies.h2
-rw-r--r--chromium/content/renderer/gpu/compositor_external_begin_frame_source.cc26
-rw-r--r--chromium/content/renderer/gpu/compositor_external_begin_frame_source.h6
-rw-r--r--chromium/content/renderer/gpu/compositor_output_surface.cc45
-rw-r--r--chromium/content/renderer/gpu/compositor_output_surface.h11
-rw-r--r--chromium/content/renderer/gpu/delegated_compositor_output_surface.cc6
-rw-r--r--chromium/content/renderer/gpu/delegated_compositor_output_surface.h3
-rw-r--r--chromium/content/renderer/gpu/gpu_benchmarking_extension.cc154
-rw-r--r--chromium/content/renderer/gpu/gpu_benchmarking_extension.h5
-rw-r--r--chromium/content/renderer/gpu/mailbox_output_surface.cc3
-rw-r--r--chromium/content/renderer/gpu/render_widget_compositor.cc216
-rw-r--r--chromium/content/renderer/gpu/render_widget_compositor.h30
-rw-r--r--chromium/content/renderer/gpu/render_widget_compositor_delegate.h103
-rw-r--r--chromium/content/renderer/gpu/render_widget_compositor_unittest.cc10
-rw-r--r--chromium/content/renderer/gpu/stream_texture_host_android.cc16
-rw-r--r--chromium/content/renderer/gpu/stream_texture_host_android.h13
-rw-r--r--chromium/content/renderer/history_controller.cc53
-rw-r--r--chromium/content/renderer/history_controller.h8
-rw-r--r--chromium/content/renderer/idle_user_detector.cc6
-rw-r--r--chromium/content/renderer/idle_user_detector.h4
-rw-r--r--chromium/content/renderer/image_downloader/image_downloader_impl.cc38
-rw-r--r--chromium/content/renderer/image_downloader/image_downloader_impl.h11
-rw-r--r--chromium/content/renderer/ime_event_guard.cc13
-rw-r--r--chromium/content/renderer/ime_event_guard.h1
-rw-r--r--chromium/content/renderer/in_process_renderer_thread.h1
-rw-r--r--chromium/content/renderer/input/input_event_filter.cc57
-rw-r--r--chromium/content/renderer/input/input_event_filter.h22
-rw-r--r--chromium/content/renderer/input/input_event_filter_unittest.cc281
-rw-r--r--chromium/content/renderer/input/input_handler_manager.cc81
-rw-r--r--chromium/content/renderer/input/input_handler_manager.h51
-rw-r--r--chromium/content/renderer/input/input_handler_manager_client.h27
-rw-r--r--chromium/content/renderer/input/input_handler_wrapper.cc5
-rw-r--r--chromium/content/renderer/input/input_handler_wrapper.h3
-rw-r--r--chromium/content/renderer/input/main_thread_event_queue.cc122
-rw-r--r--chromium/content/renderer/input/main_thread_event_queue.h121
-rw-r--r--chromium/content/renderer/input/main_thread_event_queue_unittest.cc139
-rw-r--r--chromium/content/renderer/input/render_widget_input_handler.cc157
-rw-r--r--chromium/content/renderer/input/render_widget_input_handler.h8
-rw-r--r--chromium/content/renderer/input/render_widget_input_handler_delegate.h13
-rw-r--r--chromium/content/renderer/internal_document_state_data.cc5
-rw-r--r--chromium/content/renderer/internal_document_state_data.h12
-rw-r--r--chromium/content/renderer/java/gin_java_bridge_value_converter_unittest.cc2
-rw-r--r--chromium/content/renderer/manifest/manifest_parser.cc7
-rw-r--r--chromium/content/renderer/manifest/manifest_parser.h6
-rw-r--r--chromium/content/renderer/manifest/manifest_parser_unittest.cc4
-rw-r--r--chromium/content/renderer/media/DEPS2
-rw-r--r--chromium/content/renderer/media/OWNERS7
-rw-r--r--chromium/content/renderer/media/aec_dump_message_filter.h3
-rw-r--r--chromium/content/renderer/media/android/media_info_loader.cc2
-rw-r--r--chromium/content/renderer/media/android/media_info_loader.h6
-rw-r--r--chromium/content/renderer/media/android/media_info_loader_unittest.cc4
-rw-r--r--chromium/content/renderer/media/android/media_source_delegate.cc85
-rw-r--r--chromium/content/renderer/media/android/media_source_delegate.h36
-rw-r--r--chromium/content/renderer/media/android/renderer_media_player_manager.cc31
-rw-r--r--chromium/content/renderer/media/android/renderer_media_player_manager.h6
-rw-r--r--chromium/content/renderer/media/android/renderer_media_session_manager.cc26
-rw-r--r--chromium/content/renderer/media/android/renderer_media_session_manager.h10
-rw-r--r--chromium/content/renderer/media/android/renderer_surface_view_manager.cc50
-rw-r--r--chromium/content/renderer/media/android/renderer_surface_view_manager.h46
-rw-r--r--chromium/content/renderer/media/android/stream_texture_factory.h9
-rw-r--r--chromium/content/renderer/media/android/stream_texture_factory_impl.cc17
-rw-r--r--chromium/content/renderer/media/android/stream_texture_factory_impl.h10
-rw-r--r--chromium/content/renderer/media/android/stream_texture_factory_synchronous_impl.cc60
-rw-r--r--chromium/content/renderer/media/android/stream_texture_factory_synchronous_impl.h11
-rw-r--r--chromium/content/renderer/media/android/webmediaplayer_android.cc560
-rw-r--r--chromium/content/renderer/media/android/webmediaplayer_android.h162
-rw-r--r--chromium/content/renderer/media/android/webmediasession_android.cc25
-rw-r--r--chromium/content/renderer/media/android/webmediasession_android.h4
-rw-r--r--chromium/content/renderer/media/android/webmediasession_android_unittest.cc35
-rw-r--r--chromium/content/renderer/media/audio_decoder.cc4
-rw-r--r--chromium/content/renderer/media/audio_device_factory.cc141
-rw-r--r--chromium/content/renderer/media/audio_device_factory.h81
-rw-r--r--chromium/content/renderer/media/audio_input_message_filter.cc6
-rw-r--r--chromium/content/renderer/media/audio_input_message_filter.h6
-rw-r--r--chromium/content/renderer/media/audio_message_filter.cc4
-rw-r--r--chromium/content/renderer/media/audio_message_filter.h6
-rw-r--r--chromium/content/renderer/media/audio_message_filter_unittest.cc6
-rw-r--r--chromium/content/renderer/media/audio_renderer_mixer_manager.cc68
-rw-r--r--chromium/content/renderer/media/audio_renderer_mixer_manager.h8
-rw-r--r--chromium/content/renderer/media/audio_renderer_mixer_manager_unittest.cc167
-rw-r--r--chromium/content/renderer/media/audio_repetition_detector_unittest.cc8
-rw-r--r--chromium/content/renderer/media/audio_track_recorder.cc373
-rw-r--r--chromium/content/renderer/media/audio_track_recorder.h19
-rw-r--r--chromium/content/renderer/media/audio_track_recorder_unittest.cc171
-rw-r--r--chromium/content/renderer/media/canvas_capture_handler.cc133
-rw-r--r--chromium/content/renderer/media/canvas_capture_handler.h19
-rw-r--r--chromium/content/renderer/media/canvas_capture_handler_unittest.cc80
-rw-r--r--chromium/content/renderer/media/cdm/pepper_cdm_wrapper.h6
-rw-r--r--chromium/content/renderer/media/cdm/pepper_cdm_wrapper_impl.cc16
-rw-r--r--chromium/content/renderer/media/cdm/pepper_cdm_wrapper_impl.h11
-rw-r--r--chromium/content/renderer/media/cdm/ppapi_decryptor.cc23
-rw-r--r--chromium/content/renderer/media/cdm/ppapi_decryptor.h23
-rw-r--r--chromium/content/renderer/media/cdm/proxy_media_keys.cc20
-rw-r--r--chromium/content/renderer/media/cdm/proxy_media_keys.h19
-rw-r--r--chromium/content/renderer/media/cdm/render_cdm_factory.cc6
-rw-r--r--chromium/content/renderer/media/cdm/render_cdm_factory.h2
-rw-r--r--chromium/content/renderer/media/html_video_element_capturer_source.cc15
-rw-r--r--chromium/content/renderer/media/html_video_element_capturer_source.h11
-rw-r--r--chromium/content/renderer/media/html_video_element_capturer_source_unittest.cc14
-rw-r--r--chromium/content/renderer/media/media_interface_provider.cc68
-rw-r--r--chromium/content/renderer/media/media_interface_provider.h49
-rw-r--r--chromium/content/renderer/media/media_permission_dispatcher.cc109
-rw-r--r--chromium/content/renderer/media/media_permission_dispatcher.h55
-rw-r--r--chromium/content/renderer/media/media_permission_dispatcher_impl.cc99
-rw-r--r--chromium/content/renderer/media/media_permission_dispatcher_impl.h69
-rw-r--r--chromium/content/renderer/media/media_permission_dispatcher_proxy.cc161
-rw-r--r--chromium/content/renderer/media/media_permission_dispatcher_proxy.h57
-rw-r--r--chromium/content/renderer/media/media_recorder_handler.cc58
-rw-r--r--chromium/content/renderer/media/media_recorder_handler.h16
-rw-r--r--chromium/content/renderer/media/media_recorder_handler_unittest.cc74
-rw-r--r--chromium/content/renderer/media/media_stream.cc2
-rw-r--r--chromium/content/renderer/media/media_stream_audio_level_calculator.cc35
-rw-r--r--chromium/content/renderer/media/media_stream_audio_level_calculator.h49
-rw-r--r--chromium/content/renderer/media/media_stream_audio_processor.cc79
-rw-r--r--chromium/content/renderer/media/media_stream_audio_processor.h16
-rw-r--r--chromium/content/renderer/media/media_stream_audio_processor_options.cc235
-rw-r--r--chromium/content/renderer/media/media_stream_audio_processor_options.h48
-rw-r--r--chromium/content/renderer/media/media_stream_audio_processor_unittest.cc197
-rw-r--r--chromium/content/renderer/media/media_stream_audio_source.cc37
-rw-r--r--chromium/content/renderer/media/media_stream_audio_source.h60
-rw-r--r--chromium/content/renderer/media/media_stream_audio_track.cc33
-rw-r--r--chromium/content/renderer/media/media_stream_audio_track.h30
-rw-r--r--chromium/content/renderer/media/media_stream_center.cc17
-rw-r--r--chromium/content/renderer/media/media_stream_constraints_util.cc187
-rw-r--r--chromium/content/renderer/media/media_stream_constraints_util.h77
-rw-r--r--chromium/content/renderer/media/media_stream_constraints_util_unittest.cc137
-rw-r--r--chromium/content/renderer/media/media_stream_dispatcher.h2
-rw-r--r--chromium/content/renderer/media/media_stream_dispatcher_unittest.cc34
-rw-r--r--chromium/content/renderer/media/media_stream_renderer_factory_impl.cc104
-rw-r--r--chromium/content/renderer/media/media_stream_track.cc4
-rw-r--r--chromium/content/renderer/media/media_stream_video_capturer_source.cc50
-rw-r--r--chromium/content/renderer/media/media_stream_video_capturer_source.h10
-rw-r--r--chromium/content/renderer/media/media_stream_video_capturer_source_unittest.cc100
-rw-r--r--chromium/content/renderer/media/media_stream_video_renderer_sink.cc10
-rw-r--r--chromium/content/renderer/media/media_stream_video_renderer_sink.h8
-rw-r--r--chromium/content/renderer/media/media_stream_video_renderer_sink_unittest.cc45
-rw-r--r--chromium/content/renderer/media/media_stream_video_source.cc328
-rw-r--r--chromium/content/renderer/media/media_stream_video_source.h6
-rw-r--r--chromium/content/renderer/media/media_stream_video_source_unittest.cc276
-rw-r--r--chromium/content/renderer/media/media_stream_video_track.cc19
-rw-r--r--chromium/content/renderer/media/media_stream_video_track.h4
-rw-r--r--chromium/content/renderer/media/media_stream_video_track_unittest.cc69
-rw-r--r--chromium/content/renderer/media/midi_dispatcher.cc31
-rw-r--r--chromium/content/renderer/media/midi_dispatcher.h16
-rw-r--r--chromium/content/renderer/media/midi_message_filter.cc1
-rw-r--r--chromium/content/renderer/media/midi_message_filter.h12
-rw-r--r--chromium/content/renderer/media/mock_constraint_factory.cc50
-rw-r--r--chromium/content/renderer/media/mock_constraint_factory.h37
-rw-r--r--chromium/content/renderer/media/mock_data_channel_impl.h2
-rw-r--r--chromium/content/renderer/media/mock_media_constraint_factory.cc109
-rw-r--r--chromium/content/renderer/media/mock_media_constraint_factory.h38
-rw-r--r--chromium/content/renderer/media/mock_media_stream_registry.cc15
-rw-r--r--chromium/content/renderer/media/mock_media_stream_video_sink.h13
-rw-r--r--chromium/content/renderer/media/mock_media_stream_video_source.cc20
-rw-r--r--chromium/content/renderer/media/mock_media_stream_video_source.h6
-rw-r--r--chromium/content/renderer/media/mock_peer_connection_impl.cc9
-rw-r--r--chromium/content/renderer/media/mock_peer_connection_impl.h24
-rw-r--r--chromium/content/renderer/media/peer_connection_identity_store.cc9
-rw-r--r--chromium/content/renderer/media/peer_connection_identity_store.h2
-rw-r--r--chromium/content/renderer/media/peer_connection_tracker.cc348
-rw-r--r--chromium/content/renderer/media/peer_connection_tracker.h49
-rw-r--r--chromium/content/renderer/media/peer_connection_tracker_unittest.cc82
-rw-r--r--chromium/content/renderer/media/pepper_to_video_track_adapter_unittest.cc2
-rw-r--r--chromium/content/renderer/media/remote_media_stream_impl.cc27
-rw-r--r--chromium/content/renderer/media/remote_media_stream_impl.h13
-rw-r--r--chromium/content/renderer/media/render_media_client.cc4
-rw-r--r--chromium/content/renderer/media/render_media_client.h10
-rw-r--r--chromium/content/renderer/media/render_media_client_unittest.cc2
-rw-r--r--chromium/content/renderer/media/render_media_log.cc125
-rw-r--r--chromium/content/renderer/media/render_media_log.h39
-rw-r--r--chromium/content/renderer/media/render_media_log_unittest.cc2
-rw-r--r--chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.cc97
-rw-r--r--chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.h28
-rw-r--r--chromium/content/renderer/media/renderer_webaudiodevice_impl.cc35
-rw-r--r--chromium/content/renderer/media/renderer_webaudiodevice_impl.h14
-rw-r--r--chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc160
-rw-r--r--chromium/content/renderer/media/renderer_webmediaplayer_delegate.h74
-rw-r--r--chromium/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc266
-rw-r--r--chromium/content/renderer/media/renderer_webmidiaccessor_impl.h4
-rw-r--r--chromium/content/renderer/media/rtc_certificate.cc5
-rw-r--r--chromium/content/renderer/media/rtc_certificate.h2
-rw-r--r--chromium/content/renderer/media/rtc_certificate_generator.cc34
-rw-r--r--chromium/content/renderer/media/rtc_certificate_generator.h2
-rw-r--r--chromium/content/renderer/media/rtc_data_channel_handler.cc13
-rw-r--r--chromium/content/renderer/media/rtc_data_channel_handler.h9
-rw-r--r--chromium/content/renderer/media/rtc_data_channel_handler_unittest.cc8
-rw-r--r--chromium/content/renderer/media/rtc_dtmf_sender_handler.h2
-rw-r--r--chromium/content/renderer/media/rtc_media_constraints.cc107
-rw-r--r--chromium/content/renderer/media/rtc_media_constraints.h51
-rw-r--r--chromium/content/renderer/media/rtc_peer_connection_handler.cc300
-rw-r--r--chromium/content/renderer/media/rtc_peer_connection_handler.h21
-rw-r--r--chromium/content/renderer/media/rtc_peer_connection_handler_unittest.cc125
-rw-r--r--chromium/content/renderer/media/rtc_video_decoder.cc118
-rw-r--r--chromium/content/renderer/media/rtc_video_decoder.h41
-rw-r--r--chromium/content/renderer/media/rtc_video_decoder_factory.cc3
-rw-r--r--chromium/content/renderer/media/rtc_video_decoder_factory.h2
-rw-r--r--chromium/content/renderer/media/rtc_video_decoder_unittest.cc113
-rw-r--r--chromium/content/renderer/media/rtc_video_encoder.cc18
-rw-r--r--chromium/content/renderer/media/rtc_video_encoder.h4
-rw-r--r--chromium/content/renderer/media/rtc_video_encoder_factory.cc2
-rw-r--r--chromium/content/renderer/media/rtc_video_encoder_factory.h2
-rw-r--r--chromium/content/renderer/media/speech_recognition_audio_sink.cc7
-rw-r--r--chromium/content/renderer/media/speech_recognition_audio_sink.h13
-rw-r--r--chromium/content/renderer/media/speech_recognition_audio_sink_unittest.cc39
-rw-r--r--chromium/content/renderer/media/track_audio_renderer.cc390
-rw-r--r--chromium/content/renderer/media/track_audio_renderer.h182
-rw-r--r--chromium/content/renderer/media/user_media_client_impl.cc203
-rw-r--r--chromium/content/renderer/media/user_media_client_impl.h22
-rw-r--r--chromium/content/renderer/media/user_media_client_impl_unittest.cc95
-rw-r--r--chromium/content/renderer/media/video_capture_impl.cc21
-rw-r--r--chromium/content/renderer/media/video_capture_impl.h7
-rw-r--r--chromium/content/renderer/media/video_capture_impl_manager.cc13
-rw-r--r--chromium/content/renderer/media/video_capture_impl_manager.h6
-rw-r--r--chromium/content/renderer/media/video_capture_impl_manager_unittest.cc4
-rw-r--r--chromium/content/renderer/media/video_capture_impl_unittest.cc4
-rw-r--r--chromium/content/renderer/media/video_capture_message_filter_unittest.cc17
-rw-r--r--chromium/content/renderer/media/video_track_adapter.cc8
-rw-r--r--chromium/content/renderer/media/video_track_recorder.cc99
-rw-r--r--chromium/content/renderer/media/video_track_recorder.h7
-rw-r--r--chromium/content/renderer/media/video_track_recorder_unittest.cc43
-rw-r--r--chromium/content/renderer/media/video_track_to_pepper_adapter.cc12
-rw-r--r--chromium/content/renderer/media/video_track_to_pepper_adapter.h4
-rw-r--r--chromium/content/renderer/media/video_track_to_pepper_adapter_unittest.cc4
-rw-r--r--chromium/content/renderer/media/webaudio_capturer_source.cc87
-rw-r--r--chromium/content/renderer/media/webaudio_capturer_source.h52
-rw-r--r--chromium/content/renderer/media/webmediaplayer_ms.cc177
-rw-r--r--chromium/content/renderer/media/webmediaplayer_ms.h80
-rw-r--r--chromium/content/renderer/media/webmediaplayer_ms_compositor.cc79
-rw-r--r--chromium/content/renderer/media/webmediaplayer_ms_compositor.h4
-rw-r--r--chromium/content/renderer/media/webmediaplayer_ms_unittest.cc146
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_remote_audio_track.cc18
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_remote_audio_track.h9
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc35
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_remote_video_source.h8
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc29
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_track_metrics.cc2
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_track_metrics.h2
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc15
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc145
-rw-r--r--chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.h14
-rw-r--r--chromium/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.cc224
-rw-r--r--chromium/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h132
-rw-r--r--chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc285
-rw-r--r--chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h46
-rw-r--r--chromium/content/renderer/media/webrtc/peer_connection_dependency_factory_unittest.cc4
-rw-r--r--chromium/content/renderer/media/webrtc/stun_field_trial.cc2
-rw-r--r--chromium/content/renderer/media/webrtc/stun_field_trial.h2
-rw-r--r--chromium/content/renderer/media/webrtc/track_observer.h2
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_audio_sink_adapter.cc2
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_audio_sink_adapter.h5
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.cc87
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h45
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter_unittest.cc28
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.cc19
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.h4
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc25
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc20
-rw-r--r--chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h6
-rw-r--r--chromium/content/renderer/media/webrtc_audio_capturer.cc173
-rw-r--r--chromium/content/renderer/media/webrtc_audio_capturer.h32
-rw-r--r--chromium/content/renderer/media/webrtc_audio_capturer_unittest.cc57
-rw-r--r--chromium/content/renderer/media/webrtc_audio_device_impl.cc124
-rw-r--r--chromium/content/renderer/media/webrtc_audio_device_impl.h20
-rw-r--r--chromium/content/renderer/media/webrtc_audio_device_not_impl.cc3
-rw-r--r--chromium/content/renderer/media/webrtc_audio_device_not_impl.h2
-rw-r--r--chromium/content/renderer/media/webrtc_audio_renderer.cc188
-rw-r--r--chromium/content/renderer/media/webrtc_audio_renderer.h29
-rw-r--r--chromium/content/renderer/media/webrtc_audio_renderer_unittest.cc189
-rw-r--r--chromium/content/renderer/media/webrtc_identity_service.cc3
-rw-r--r--chromium/content/renderer/media/webrtc_identity_service.h1
-rw-r--r--chromium/content/renderer/media/webrtc_identity_service_unittest.cc2
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_renderer.cc356
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_renderer.h183
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_source_provider.h8
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc23
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_track.cc116
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_track.h64
-rw-r--r--chromium/content/renderer/media/webrtc_local_audio_track_unittest.cc186
-rw-r--r--chromium/content/renderer/media/webrtc_uma_histograms.h1
-rw-r--r--chromium/content/renderer/memory_benchmarking_extension.cc88
-rw-r--r--chromium/content/renderer/memory_benchmarking_extension.h45
-rw-r--r--chromium/content/renderer/mojo/blink_service_registry_impl.cc28
-rw-r--r--chromium/content/renderer/mojo/blink_service_registry_impl.h37
-rw-r--r--chromium/content/renderer/mojo/service_registry_js_wrapper.cc75
-rw-r--r--chromium/content/renderer/mojo/service_registry_js_wrapper.h28
-rw-r--r--chromium/content/renderer/mojo_bindings_controller.cc21
-rw-r--r--chromium/content/renderer/mojo_bindings_controller.h8
-rw-r--r--chromium/content/renderer/mojo_context_state.cc100
-rw-r--r--chromium/content/renderer/mojo_context_state.h5
-rw-r--r--chromium/content/renderer/mus/BUILD.gn14
-rw-r--r--chromium/content/renderer/mus/compositor_mus_connection.cc36
-rw-r--r--chromium/content/renderer/mus/compositor_mus_connection.h21
-rw-r--r--chromium/content/renderer/mus/compositor_mus_connection_unittest.cc454
-rw-r--r--chromium/content/renderer/mus/render_widget_mus_connection.cc27
-rw-r--r--chromium/content/renderer/mus/render_widget_mus_connection.h14
-rw-r--r--chromium/content/renderer/mus/render_widget_window_tree_client_factory.cc13
-rw-r--r--chromium/content/renderer/notification_permission_dispatcher.cc14
-rw-r--r--chromium/content/renderer/notification_permission_dispatcher.h6
-rw-r--r--chromium/content/renderer/npapi/plugin_channel_host.cc168
-rw-r--r--chromium/content/renderer/npapi/plugin_channel_host.h77
-rw-r--r--chromium/content/renderer/npapi/webplugin_delegate_proxy.cc1088
-rw-r--r--chromium/content/renderer/npapi/webplugin_delegate_proxy.h286
-rw-r--r--chromium/content/renderer/npapi/webplugin_impl.cc1228
-rw-r--r--chromium/content/renderer/npapi/webplugin_impl.h327
-rw-r--r--chromium/content/renderer/npapi/webplugin_impl_unittest.cc235
-rw-r--r--chromium/content/renderer/origin_trials/web_trial_token_validator_impl.cc22
-rw-r--r--chromium/content/renderer/origin_trials/web_trial_token_validator_impl.h37
-rw-r--r--chromium/content/renderer/p2p/filtering_network_manager.cc4
-rw-r--r--chromium/content/renderer/p2p/filtering_network_manager.h4
-rw-r--r--chromium/content/renderer/p2p/filtering_network_manager_unittest.cc12
-rw-r--r--chromium/content/renderer/p2p/host_address_request.h2
-rw-r--r--chromium/content/renderer/p2p/ipc_network_manager.cc17
-rw-r--r--chromium/content/renderer/p2p/ipc_network_manager.h8
-rw-r--r--chromium/content/renderer/p2p/ipc_network_manager_unittest.cc55
-rw-r--r--chromium/content/renderer/p2p/ipc_socket_factory.cc5
-rw-r--r--chromium/content/renderer/p2p/network_list_observer.h7
-rw-r--r--chromium/content/renderer/p2p/port_allocator.cc4
-rw-r--r--chromium/content/renderer/p2p/port_allocator.h6
-rw-r--r--chromium/content/renderer/p2p/socket_dispatcher.cc4
-rw-r--r--chromium/content/renderer/p2p/socket_dispatcher.h10
-rw-r--r--chromium/content/renderer/pepper/DEPS2
-rw-r--r--chromium/content/renderer/pepper/content_decryptor_delegate.cc5
-rw-r--r--chromium/content/renderer/pepper/content_renderer_pepper_host_factory.cc58
-rw-r--r--chromium/content/renderer/pepper/content_renderer_pepper_host_factory.h2
-rw-r--r--chromium/content/renderer/pepper/event_conversion.cc5
-rw-r--r--chromium/content/renderer/pepper/fullscreen_container.h2
-rw-r--r--chromium/content/renderer/pepper/host_globals.cc6
-rw-r--r--chromium/content/renderer/pepper/host_var_tracker_unittest.cc1
-rw-r--r--chromium/content/renderer/pepper/message_channel.cc2
-rw-r--r--chromium/content/renderer/pepper/pepper_broker.cc3
-rw-r--r--chromium/content/renderer/pepper/pepper_broker.h1
-rw-r--r--chromium/content/renderer/pepper/pepper_compositor_host.cc12
-rw-r--r--chromium/content/renderer/pepper/pepper_compositor_host.h5
-rw-r--r--chromium/content/renderer/pepper/pepper_file_chooser_host.cc1
-rw-r--r--chromium/content/renderer/pepper/pepper_file_chooser_host_unittest.cc2
-rw-r--r--chromium/content/renderer/pepper/pepper_graphics_2d_host.cc34
-rw-r--r--chromium/content/renderer/pepper/pepper_media_stream_video_track_host.cc44
-rw-r--r--chromium/content/renderer/pepper/pepper_media_stream_video_track_host.h7
-rw-r--r--chromium/content/renderer/pepper/pepper_platform_video_capture.cc2
-rw-r--r--chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc160
-rw-r--r--chromium/content/renderer/pepper/pepper_plugin_instance_impl.h10
-rw-r--r--chromium/content/renderer/pepper/pepper_proxy_channel_delegate_impl.cc9
-rw-r--r--chromium/content/renderer/pepper/pepper_url_loader_host.cc2
-rw-r--r--chromium/content/renderer/pepper/pepper_url_request_unittest.cc30
-rw-r--r--chromium/content/renderer/pepper/pepper_video_capture_host.cc3
-rw-r--r--chromium/content/renderer/pepper/pepper_video_capture_host.h1
-rw-r--r--chromium/content/renderer/pepper/pepper_video_decoder_host.cc28
-rw-r--r--chromium/content/renderer/pepper/pepper_video_decoder_host.h1
-rw-r--r--chromium/content/renderer/pepper/pepper_video_encoder_host.cc34
-rw-r--r--chromium/content/renderer/pepper/pepper_video_encoder_host.h11
-rw-r--r--chromium/content/renderer/pepper/pepper_video_source_host.cc14
-rw-r--r--chromium/content/renderer/pepper/pepper_webplugin_impl.cc100
-rw-r--r--chromium/content/renderer/pepper/pepper_webplugin_impl.h6
-rw-r--r--chromium/content/renderer/pepper/pepper_websocket_host.cc24
-rw-r--r--chromium/content/renderer/pepper/pepper_websocket_host.h10
-rw-r--r--chromium/content/renderer/pepper/plugin_instance_throttler_impl.cc2
-rw-r--r--chromium/content/renderer/pepper/plugin_module.cc7
-rw-r--r--chromium/content/renderer/pepper/plugin_object.cc22
-rw-r--r--chromium/content/renderer/pepper/plugin_power_saver_helper.cc3
-rw-r--r--chromium/content/renderer/pepper/plugin_power_saver_helper.h1
-rw-r--r--chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc95
-rw-r--r--chromium/content/renderer/pepper/ppb_graphics_3d_impl.h35
-rw-r--r--chromium/content/renderer/pepper/ppb_image_data_impl.cc12
-rw-r--r--chromium/content/renderer/pepper/ppb_image_data_impl.h4
-rw-r--r--chromium/content/renderer/pepper/ppb_video_decoder_impl.cc28
-rw-r--r--chromium/content/renderer/pepper/ppb_video_decoder_impl.h1
-rw-r--r--chromium/content/renderer/pepper/resource_converter.cc5
-rw-r--r--chromium/content/renderer/pepper/resource_creation_impl.cc4
-rw-r--r--chromium/content/renderer/pepper/resource_creation_impl.h2
-rw-r--r--chromium/content/renderer/pepper/url_response_info_util.cc4
-rw-r--r--chromium/content/renderer/pepper/v8_var_converter.h1
-rw-r--r--chromium/content/renderer/pepper/v8_var_converter_unittest.cc2
-rw-r--r--chromium/content/renderer/pepper/video_decoder_shim.cc25
-rw-r--r--chromium/content/renderer/pepper/video_encoder_shim.cc22
-rw-r--r--chromium/content/renderer/presentation/presentation_connection_client.cc5
-rw-r--r--chromium/content/renderer/presentation/presentation_connection_client.h2
-rw-r--r--chromium/content/renderer/presentation/presentation_dispatcher.cc113
-rw-r--r--chromium/content/renderer/presentation/presentation_dispatcher.h35
-rw-r--r--chromium/content/renderer/push_messaging/push_messaging_dispatcher.cc70
-rw-r--r--chromium/content/renderer/push_messaging/push_messaging_dispatcher.h8
-rw-r--r--chromium/content/renderer/raster_worker_pool.cc201
-rw-r--r--chromium/content/renderer/raster_worker_pool.h44
-rw-r--r--chromium/content/renderer/raster_worker_pool_unittest.cc6
-rw-r--r--chromium/content/renderer/render_frame_impl.cc1775
-rw-r--r--chromium/content/renderer/render_frame_impl.h236
-rw-r--r--chromium/content/renderer/render_frame_impl_browsertest.cc92
-rw-r--r--chromium/content/renderer/render_frame_proxy.cc145
-rw-r--r--chromium/content/renderer/render_frame_proxy.h24
-rw-r--r--chromium/content/renderer/render_process_impl.cc42
-rw-r--r--chromium/content/renderer/render_thread_impl.cc427
-rw-r--r--chromium/content/renderer/render_thread_impl.h72
-rw-r--r--chromium/content/renderer/render_thread_impl_browsertest.cc32
-rw-r--r--chromium/content/renderer/render_view_browsertest.cc929
-rw-r--r--chromium/content/renderer/render_view_browsertest_mac.mm16
-rw-r--r--chromium/content/renderer/render_view_impl.cc875
-rw-r--r--chromium/content/renderer/render_view_impl.h141
-rw-r--r--chromium/content/renderer/render_view_mouse_lock_dispatcher.cc4
-rw-r--r--chromium/content/renderer/render_view_win.cc5
-rw-r--r--chromium/content/renderer/render_widget.cc1095
-rw-r--r--chromium/content/renderer/render_widget.h174
-rw-r--r--chromium/content/renderer/render_widget_browsertest.cc25
-rw-r--r--chromium/content/renderer/render_widget_fullscreen_pepper.cc14
-rw-r--r--chromium/content/renderer/render_widget_fullscreen_pepper.h6
-rw-r--r--chromium/content/renderer/render_widget_owner_delegate.h58
-rw-r--r--chromium/content/renderer/render_widget_unittest.cc110
-rw-r--r--chromium/content/renderer/renderer.sb4
-rw-r--r--chromium/content/renderer/renderer_blink_platform_impl.cc294
-rw-r--r--chromium/content/renderer/renderer_blink_platform_impl.h66
-rw-r--r--chromium/content/renderer/renderer_main.cc43
-rw-r--r--chromium/content/renderer/renderer_main_platform_delegate_linux.cc2
-rw-r--r--chromium/content/renderer/renderer_main_platform_delegate_win.cc17
-rw-r--r--chromium/content/renderer/renderer_webapplicationcachehost_impl.cc3
-rw-r--r--chromium/content/renderer/renderer_webcookiejar_impl.cc5
-rw-r--r--chromium/content/renderer/renderer_webcookiejar_impl.h3
-rw-r--r--chromium/content/renderer/resizing_mode_selector.cc5
-rw-r--r--chromium/content/renderer/resizing_mode_selector.h6
-rw-r--r--chromium/content/renderer/savable_resources.cc12
-rw-r--r--chromium/content/renderer/scheduler/resource_dispatch_throttler.cc26
-rw-r--r--chromium/content/renderer/scheduler/resource_dispatch_throttler.h3
-rw-r--r--chromium/content/renderer/scheduler/resource_dispatch_throttler_unittest.cc40
-rw-r--r--chromium/content/renderer/service_worker/embedded_worker_devtools_agent.cc1
-rw-r--r--chromium/content/renderer/service_worker/embedded_worker_dispatcher.cc23
-rw-r--r--chromium/content/renderer/service_worker/embedded_worker_dispatcher.h1
-rw-r--r--chromium/content/renderer/service_worker/service_worker_context_client.cc226
-rw-r--r--chromium/content/renderer/service_worker/service_worker_context_client.h54
-rw-r--r--chromium/content/renderer/shared_worker/embedded_shared_worker_content_settings_client_proxy.cc12
-rw-r--r--chromium/content/renderer/shared_worker/embedded_shared_worker_content_settings_client_proxy.h3
-rw-r--r--chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc23
-rw-r--r--chromium/content/renderer/shared_worker/embedded_shared_worker_stub.h5
-rw-r--r--chromium/content/renderer/shared_worker_repository.cc2
-rw-r--r--chromium/content/renderer/shared_worker_repository.h2
-rw-r--r--chromium/content/renderer/skia_benchmarking_extension.cc7
-rw-r--r--chromium/content/renderer/text_input_client_observer.cc3
-rw-r--r--chromium/content/renderer/top_level_blame_context.cc25
-rw-r--r--chromium/content/renderer/top_level_blame_context.h25
-rw-r--r--chromium/content/renderer/usb/DEPS3
-rw-r--r--chromium/content/renderer/usb/type_converters.cc35
-rw-r--r--chromium/content/renderer/usb/type_converters.h4
-rw-r--r--chromium/content/renderer/usb/web_usb_client_impl.cc56
-rw-r--r--chromium/content/renderer/usb/web_usb_client_impl.h11
-rw-r--r--chromium/content/renderer/usb/web_usb_device_impl.cc250
-rw-r--r--chromium/content/renderer/usb/web_usb_device_impl.h20
-rw-r--r--chromium/content/renderer/vr/vr_dispatcher.cc9
-rw-r--r--chromium/content/renderer/vr/vr_dispatcher.h8
-rw-r--r--chromium/content/renderer/vr/vr_type_converters.cc16
-rw-r--r--chromium/content/renderer/vr/vr_type_converters.h36
-rw-r--r--chromium/content/renderer/wake_lock/wake_lock_dispatcher.h2
-rw-r--r--chromium/content/renderer/webgraphicscontext3d_provider_impl.cc10
-rw-r--r--chromium/content/renderer/webgraphicscontext3d_provider_impl.h8
-rw-r--r--chromium/content/renderer/websharedworker_proxy.cc4
-rw-r--r--chromium/content/renderer/websharedworker_proxy.h11
-rw-r--r--chromium/content/shell/common/DEPS1
-rw-r--r--chromium/content/shell/common/layout_test/layout_test_bluetooth_fake_adapter_setter.mojom14
-rw-r--r--chromium/content/shell/common/layout_test/layout_test_content_client.cc24
-rw-r--r--chromium/content/shell/common/layout_test/layout_test_content_client.h24
-rw-r--r--chromium/content/shell/common/layout_test/layout_test_messages.h19
-rw-r--r--chromium/content/shell/common/layout_test/layout_test_switches.cc48
-rw-r--r--chromium/content/shell/common/layout_test/layout_test_switches.h28
-rw-r--r--chromium/content/shell/common/shell_content_client.cc31
-rw-r--r--chromium/content/shell/common/shell_content_client.h5
-rw-r--r--chromium/content/shell/common/shell_messages.h47
-rw-r--r--chromium/content/shell/common/shell_switches.cc46
-rw-r--r--chromium/content/shell/common/shell_switches.h17
-rw-r--r--chromium/content/shell/shell_resources.grd18
-rw-r--r--chromium/content/utility/BUILD.gn23
-rw-r--r--chromium/content/utility/in_process_utility_thread.h1
-rw-r--r--chromium/content/utility/utility_blink_platform_impl.h1
-rw-r--r--chromium/content/utility/utility_process_control_impl.cc19
-rw-r--r--chromium/content/utility/utility_process_control_impl.h2
-rw-r--r--chromium/content/utility/utility_thread_impl.cc31
-rw-r--r--chromium/content/utility/utility_thread_impl.h12
-rw-r--r--chromium/content/utility/webthread_impl_for_utility_thread.cc4
-rw-r--r--chromium/content/utility/webthread_impl_for_utility_thread.h4
-rw-r--r--chromium/content/zygote/zygote_linux.cc15
-rw-r--r--chromium/content/zygote/zygote_main_linux.cc37
2592 files changed, 90719 insertions, 96251 deletions
diff --git a/chromium/content/BUILD.gn b/chromium/content/BUILD.gn
index cb50de5f703..56941b8f427 100644
--- a/chromium/content/BUILD.gn
+++ b/chromium/content/BUILD.gn
@@ -37,14 +37,31 @@ config("content_implementation") {
# //content/public/browser and similar targets to avoid double-linking (these
# targets make sure the dependency goes through the content shared library
# when doing a component build).
+#
+# TESTS
+# -----
+# Tests are a challenge. The content tests need to access internals of
+# content/browser, for example, but the tests themselves are outside of the
+# content component (which is a shared library in the component build). To
+# prevent external-to-content targets from depending on private headers,
+# the non-public content/browser target is not a public dep of the content
+# component. But this means there is also no public path for the content
+# tests and no way to restrict that just to //content/test/* if we added one.
+#
+# As a result, we check deps for //content/test/* only in non-component builds
+# (which should verify the dependencies are correct for both component and
+# non-component cases equally). There are targets like
+# //content/browser:for_content_tests that allow content/test to depend on the
+# //content/browser target only in non-component builds (when there are no
+# linking problems) for when check is enabled.
if (!is_nacl_nonsfi) {
content_shared_components = [
"//content/gpu:gpu_sources",
"//content/public/browser:browser_sources",
"//content/public/child:child_sources",
+ "//content/public/gpu:gpu_sources",
"//content/public/common:common_sources",
- "//content/public/plugin:plugin_sources",
"//content/public/renderer:renderer_sources",
"//content/public/utility:utility_sources",
]
@@ -93,11 +110,21 @@ grit("resources") {
"grit/content_resources.h",
"content_resources.pak",
]
+ grit_flags = [
+ "-E",
+ "root_out_dir=" + rebase_path(root_out_dir, root_build_dir),
+ ]
+ deps = [
+ "//content/public/app:browser_manifest",
+ "//content/public/app:renderer_manifest",
+ "//mojo/services/catalog:manifest",
+ ]
}
# This target exists to "hold" the content_export header so we can do proper
# inclusion testing of it.
source_set("export") {
+ # Must only be used inside of content.
visibility = [ "//content/*" ]
sources = [
"common/content_export.h",
diff --git a/chromium/content/DEPS b/chromium/content/DEPS
index e62959c7e43..531e5edaa59 100644
--- a/chromium/content/DEPS
+++ b/chromium/content/DEPS
@@ -10,14 +10,8 @@ include_rules = [
"+content/grit",
"+content/public/common",
"+content/public/test",
- "+content/shell", # for content_browsertests
"+content/test",
- # content isn't tied to prefs so that other embedders are able to pick
- # different ways of storing their preferences. Also, this is to avoid prefs
- # being used as a parallel API to the Content API.
- "-base/prefs",
-
"+blink",
"+cc",
@@ -34,6 +28,9 @@ include_rules = [
"+dbus",
"+gpu",
"+mojo/common",
+ "+mojo/edk/embedder",
+ "+mojo/edk/js",
+ "+mojo/edk/test",
"+mojo/message_pump",
"+mojo/public",
"+net",
@@ -62,16 +59,11 @@ include_rules = [
"+third_party/angle",
"+third_party/flac",
"+third_party/libjingle",
- "+third_party/mojo/src/mojo/edk/embedder",
- "+third_party/mojo/src/mojo/edk/js",
- "+third_party/mojo/src/mojo/edk/test",
"+third_party/mozilla",
- "+third_party/npapi/bindings",
"+third_party/ocmock",
"+third_party/re2",
"+third_party/skia",
"+third_party/sqlite",
- "+third_party/tcmalloc",
"+third_party/khronos",
"+third_party/webrtc",
"+third_party/zlib/google",
@@ -85,6 +77,7 @@ include_rules = [
"+ui/aura",
"+ui/base",
"+ui/compositor",
+ "+ui/display",
"+ui/events",
"+ui/gfx",
"+ui/gl",
@@ -118,3 +111,12 @@ include_rules = [
# For generated JNI includes.
"+jni",
]
+
+# content -> content/shell dependency is not allowed, except for browser tests.
+specific_include_rules = {
+ ".*_browsertest[a-z_]*\.cc": [
+ "+content/shell/browser",
+ "+content/shell/common",
+ ],
+}
+
diff --git a/chromium/content/OWNERS b/chromium/content/OWNERS
index cf7197c2f46..2d7b39db9f0 100644
--- a/chromium/content/OWNERS
+++ b/chromium/content/OWNERS
@@ -1,7 +1,6 @@
avi@chromium.org
creis@chromium.org
darin@chromium.org
-davidben@chromium.org
jam@chromium.org
jochen@chromium.org
kinuko@chromium.org
diff --git a/chromium/content/README b/chromium/content/README.md
index 930fedfe25c..984f02a19b0 100644
--- a/chromium/content/README
+++ b/chromium/content/README.md
@@ -4,3 +4,8 @@ browser.
Developer documentation:
http://www.chromium.org/developers/content-module
+Internal Documentation:
+
+* [Bluetooth](browser/bluetooth/README.md)
+
+
diff --git a/chromium/content/app/BUILD.gn b/chromium/content/app/BUILD.gn
index 6abee2318b4..149143920f6 100644
--- a/chromium/content/app/BUILD.gn
+++ b/chromium/content/app/BUILD.gn
@@ -3,7 +3,6 @@
# found in the LICENSE file.
import("//build/config/chrome_build.gni")
-import("//build/config/ui.gni")
content_app_sources = [
"android/app_jni_registrar.cc",
@@ -13,6 +12,7 @@ content_app_sources = [
"android/content_jni_onload.cc",
"android/content_main.cc",
"android/content_main.h",
+ "android/download_main.cc",
"android/library_loader_hooks.cc",
"android/library_loader_hooks.h",
"content_main.cc",
@@ -26,16 +26,13 @@ content_app_sources = [
content_app_deps = [
"//base",
"//base:i18n",
-
- # This is needed by app/content_main_runner.cc
- # TODO(brettw) this shouldn't be here, only final executables should be
- # picking the allocator. http://crbug.com/571731
- "//base/allocator",
"//content:export",
"//content:sandbox_helper_win",
"//content/public/common:common_sources",
"//content/public/common:mojo_bindings",
"//crypto",
+ "//mojo/shell/public/interfaces",
+ "//mojo/edk/system",
"//ui/base",
"//ui/gfx",
"//ui/gfx/geometry",
@@ -47,26 +44,11 @@ if (is_win) {
content_app_sources -= [ "content_main.cc" ]
content_app_deps += [
"//content/public/android:jni",
+ "//device/usb",
"//device/vibration",
"//skia",
"//third_party/android_tools:cpu_features",
- ]
- if (!use_aura) {
- content_app_deps += [ "//ui/android" ]
- }
-}
-
-if (is_ios) {
- content_app_sources -= [
- "content_main.cc",
- "mojo/mojo_init.cc",
- "mojo/mojo_init.h",
- ]
-} else {
- content_app_deps += [
- "//mojo/shell/public/interfaces",
- "//mojo/environment:chromium",
- "//third_party/mojo/src/mojo/edk/system",
+ "//ui/android",
]
}
@@ -85,13 +67,26 @@ if (!is_multi_dll_chrome) {
source_set("both") {
# Only the public target should depend on this. All other targets (even
# internal content ones) should depend on the public one.
- visibility = [ "//content/public/app:*" ]
+ visibility = [
+ ":both_for_content_tests", # See top of //content/BUILD.gn for why.
+ "//content/public/app:*",
+ ]
sources = content_app_sources
configs += content_app_extra_configs
deps = content_app_deps
}
+# See comment at the top of //content/BUILD.gn for how this works.
+group("both_for_content_tests") {
+ visibility = [ "//content/test/*" ]
+ if (!is_component_build) {
+ public_deps = [
+ ":both",
+ ]
+ }
+}
+
if (is_multi_dll_chrome) {
# It doesn't make sense to do the browser/child dll split in component mode.
assert(!is_component_build)
diff --git a/chromium/content/app/DEPS b/chromium/content/app/DEPS
index 774523882ac..550e9a6303f 100644
--- a/chromium/content/app/DEPS
+++ b/chromium/content/app/DEPS
@@ -10,5 +10,6 @@ include_rules = [
"+gin/public/snapshot_fd_data.h",
"+gin/v8_initializer.h",
"+media/base", # For initializing media library.
- "+media/midi", # For initializing midi library.
+ "+media/capture/video/android/capture_jni_registrar.h",
+ "+media/midi/midi_jni_registrar.h",
]
diff --git a/chromium/content/app/android/child_process_service.cc b/chromium/content/app/android/child_process_service.cc
index 3627eba8877..e44974535dd 100644
--- a/chromium/content/app/android/child_process_service.cc
+++ b/chromium/content/app/android/child_process_service.cc
@@ -14,10 +14,10 @@
#include "base/macros.h"
#include "base/posix/global_descriptors.h"
#include "content/child/child_thread_impl.h"
-#include "content/common/android/surface_texture_manager.h"
-#include "content/common/android/surface_texture_peer.h"
-#include "content/common/gpu/gpu_surface_lookup.h"
#include "content/public/common/content_descriptors.h"
+#include "gpu/ipc/common/android/surface_texture_manager.h"
+#include "gpu/ipc/common/android/surface_texture_peer.h"
+#include "gpu/ipc/common/gpu_surface_lookup.h"
#include "ipc/ipc_descriptors.h"
#include "jni/ChildProcessService_jni.h"
#include "ui/gl/android/scoped_java_surface.h"
@@ -32,9 +32,9 @@ namespace {
// TODO(sievers): Use two different implementations of this depending on if
// we're in a renderer or gpu process.
-class SurfaceTextureManagerImpl : public SurfaceTextureManager,
- public SurfaceTexturePeer,
- public GpuSurfaceLookup {
+class SurfaceTextureManagerImpl : public gpu::SurfaceTextureManager,
+ public gpu::SurfaceTexturePeer,
+ public gpu::GpuSurfaceLookup {
public:
// |service| is the instance of
// org.chromium.content.app.ChildProcessService.
@@ -42,11 +42,11 @@ class SurfaceTextureManagerImpl : public SurfaceTextureManager,
const base::android::JavaRef<jobject>& service)
: service_(service) {
SurfaceTexturePeer::InitInstance(this);
- GpuSurfaceLookup::InitInstance(this);
+ gpu::GpuSurfaceLookup::InitInstance(this);
}
~SurfaceTextureManagerImpl() override {
SurfaceTexturePeer::InitInstance(NULL);
- GpuSurfaceLookup::InitInstance(NULL);
+ gpu::GpuSurfaceLookup::InitInstance(NULL);
}
// Overridden from SurfaceTextureManager:
@@ -146,7 +146,8 @@ void InternalInitChildProcess(JNIEnv* env,
jlong cpu_features) {
// Set the CPU properties.
android_setCpu(cpu_count, cpu_features);
- SurfaceTextureManager::SetInstance(new SurfaceTextureManagerImpl(service));
+ gpu::SurfaceTextureManager::SetInstance(
+ new SurfaceTextureManagerImpl(service));
base::android::MemoryPressureListenerAndroid::RegisterSystemCallback(env);
}
diff --git a/chromium/content/app/android/content_main.cc b/chromium/content/app/android/content_main.cc
index 4eaa3a3375b..fa4c781b542 100644
--- a/chromium/content/app/android/content_main.cc
+++ b/chromium/content/app/android/content_main.cc
@@ -8,6 +8,7 @@
#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/lazy_instance.h"
+#include "base/memory/scoped_ptr.h"
#include "base/trace_event/trace_event.h"
#include "content/public/app/content_main.h"
#include "content/public/app/content_main_delegate.h"
diff --git a/chromium/content/app/android/download_main.cc b/chromium/content/app/android/download_main.cc
new file mode 100644
index 00000000000..3280e29a3cc
--- /dev/null
+++ b/chromium/content/app/android/download_main.cc
@@ -0,0 +1,21 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/message_loop/message_loop.h"
+#include "base/threading/platform_thread.h"
+#include "content/public/common/main_function_params.h"
+
+namespace content {
+
+// Mainline routine for running as the download process.
+int DownloadMain(const MainFunctionParams& parameters) {
+ // The main message loop of the utility process.
+ base::MessageLoop main_message_loop;
+ base::PlatformThread::SetName("CrDownloadMain");
+ base::MessageLoop::current()->Run();
+
+ return 0;
+}
+
+} // namespace content
diff --git a/chromium/content/app/android/library_loader_hooks.cc b/chromium/content/app/android/library_loader_hooks.cc
index 21e51b36b92..699d7e8e9b9 100644
--- a/chromium/content/app/android/library_loader_hooks.cc
+++ b/chromium/content/app/android/library_loader_hooks.cc
@@ -28,6 +28,7 @@
#include "device/bluetooth/android/bluetooth_jni_registrar.h"
#include "device/usb/android/usb_jni_registrar.h"
#include "media/base/android/media_jni_registrar.h"
+#include "media/capture/video/android/capture_jni_registrar.h"
#include "media/midi/midi_jni_registrar.h"
#include "net/android/net_jni_registrar.h"
#include "ui/android/ui_android_jni_registrar.h"
@@ -35,10 +36,7 @@
#include "ui/events/android/events_jni_registrar.h"
#include "ui/gfx/android/gfx_jni_registrar.h"
#include "ui/gl/android/gl_jni_registrar.h"
-
-#if !defined(USE_AURA)
#include "ui/shell_dialogs/android/shell_dialogs_jni_registrar.h"
-#endif
namespace content {
@@ -64,6 +62,9 @@ bool EnsureJniRegistered(JNIEnv* env) {
if (!ui::events::android::RegisterJni(env))
return false;
+ if (!ui::shell_dialogs::RegisterJni(env))
+ return false;
+
if (!content::android::RegisterCommonJni(env))
return false;
@@ -82,16 +83,14 @@ bool EnsureJniRegistered(JNIEnv* env) {
if (!media::RegisterJni(env))
return false;
- if (!media::midi::RegisterJni(env))
+ if (!media::RegisterCaptureJni(env))
return false;
-#if !defined(USE_AURA)
- if (!ui::shell_dialogs::RegisterJni(env))
+ if (!media::midi::RegisterJni(env))
return false;
if (!ui::RegisterUIAndroidJni(env))
return false;
-#endif
g_jni_init_done = true;
}
diff --git a/chromium/content/app/content_main_runner.cc b/chromium/content/app/content_main_runner.cc
index 037c79bd512..209dc90496e 100644
--- a/chromium/content/app/content_main_runner.cc
+++ b/chromium/content/app/content_main_runner.cc
@@ -13,9 +13,11 @@
#include "base/allocator/allocator_check.h"
#include "base/allocator/allocator_extension.h"
#include "base/at_exit.h"
+#include "base/base_switches.h"
#include "base/command_line.h"
#include "base/debug/debugger.h"
#include "base/debug/stack_trace.h"
+#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/i18n/icu_util.h"
#include "base/lazy_instance.h"
@@ -23,12 +25,13 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
+#include "base/metrics/field_trial.h"
+#include "base/metrics/histogram_base.h"
#include "base/metrics/statistics_recorder.h"
#include "base/path_service.h"
#include "base/process/launch.h"
#include "base/process/memory.h"
#include "base/process/process_handle.h"
-#include "base/profiler/alternate_timer.h"
#include "base/profiler/scoped_tracker.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
@@ -38,7 +41,11 @@
#include "components/tracing/trace_config_file.h"
#include "components/tracing/trace_to_console.h"
#include "components/tracing/tracing_switches.h"
+#include "content/app/mojo/mojo_init.h"
#include "content/browser/browser_main.h"
+#include "content/browser/gpu/gpu_process_host.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/browser/utility_process_host_impl.h"
#include "content/common/set_process_title.h"
#include "content/common/url_schemes.h"
#include "content/gpu/in_process_gpu_thread.h"
@@ -51,6 +58,9 @@
#include "content/public/common/content_switches.h"
#include "content/public/common/main_function_params.h"
#include "content/public/common/sandbox_init.h"
+#include "content/public/gpu/content_gpu_client.h"
+#include "content/public/renderer/content_renderer_client.h"
+#include "content/public/utility/content_utility_client.h"
#include "content/renderer/in_process_renderer_thread.h"
#include "content/utility/in_process_utility_thread.h"
#include "ipc/ipc_descriptors.h"
@@ -64,20 +74,6 @@
#include "gin/v8_initializer.h"
#endif
-#if defined(USE_TCMALLOC)
-#include "third_party/tcmalloc/chromium/src/gperftools/malloc_extension.h"
-#endif
-
-#if !defined(OS_IOS)
-#include "content/app/mojo/mojo_init.h"
-#include "content/browser/gpu/gpu_process_host.h"
-#include "content/browser/renderer_host/render_process_host_impl.h"
-#include "content/browser/utility_process_host_impl.h"
-#include "content/public/plugin/content_plugin_client.h"
-#include "content/public/renderer/content_renderer_client.h"
-#include "content/public/utility/content_utility_client.h"
-#endif
-
#if defined(OS_WIN)
#include <malloc.h>
#include <cstring>
@@ -88,12 +84,10 @@
#include "ui/gfx/win/dpi.h"
#elif defined(OS_MACOSX)
#include "base/mac/scoped_nsautorelease_pool.h"
-#if !defined(OS_IOS)
#include "base/power_monitor/power_monitor_device_source.h"
#include "content/app/mac/mac_init.h"
#include "content/browser/mach_broker_mac.h"
#include "content/common/sandbox_init_mac.h"
-#endif // !OS_IOS
#endif // OS_WIN
#if defined(OS_POSIX)
@@ -115,12 +109,6 @@
#include "crypto/nss_util.h"
#endif
-#if !defined(OS_MACOSX) && defined(USE_TCMALLOC)
-extern "C" {
-int tc_set_new_mode(int mode);
-}
-#endif
-
namespace content {
extern int GpuMain(const content::MainFunctionParams&);
#if defined(ENABLE_PLUGINS)
@@ -132,29 +120,74 @@ extern int PpapiBrokerMain(const MainFunctionParams&);
#endif
extern int RendererMain(const content::MainFunctionParams&);
extern int UtilityMain(const MainFunctionParams&);
+#if defined(OS_ANDROID)
+extern int DownloadMain(const MainFunctionParams&);
+#endif
} // namespace content
namespace content {
+namespace {
+
+// This sets up two singletons responsible for managing field trials. The
+// |field_trial_list| singleton lives on the stack and must outlive the Run()
+// method of the process.
+void InitializeFieldTrialAndFeatureList(
+ scoped_ptr<base::FieldTrialList>* field_trial_list) {
+ const base::CommandLine& command_line =
+ *base::CommandLine::ForCurrentProcess();
+ std::string process_type =
+ command_line.GetSwitchValueASCII(switches::kProcessType);
+
+ // Initialize statistical testing infrastructure. We set the entropy
+ // provider to nullptr to disallow non-browser processes from creating
+ // their own one-time randomized trials; they should be created in the
+ // browser process.
+ field_trial_list->reset(new base::FieldTrialList(nullptr));
+
+ // Ensure any field trials in browser are reflected into the child
+ // process.
+ if (command_line.HasSwitch(switches::kForceFieldTrials)) {
+ bool result = base::FieldTrialList::CreateTrialsFromString(
+ command_line.GetSwitchValueASCII(switches::kForceFieldTrials),
+ std::set<std::string>());
+ DCHECK(result);
+ }
+
+ scoped_ptr<base::FeatureList> feature_list(new base::FeatureList);
+ feature_list->InitializeFromCommandLine(
+ command_line.GetSwitchValueASCII(switches::kEnableFeatures),
+ command_line.GetSwitchValueASCII(switches::kDisableFeatures));
+ base::FeatureList::SetInstance(std::move(feature_list));
+}
+
+} // namespace
+
#if !defined(CHROME_MULTIPLE_DLL_CHILD)
base::LazyInstance<ContentBrowserClient>
g_empty_content_browser_client = LAZY_INSTANCE_INITIALIZER;
#endif // !CHROME_MULTIPLE_DLL_CHILD
-#if !defined(OS_IOS) && !defined(CHROME_MULTIPLE_DLL_BROWSER)
-base::LazyInstance<ContentPluginClient>
- g_empty_content_plugin_client = LAZY_INSTANCE_INITIALIZER;
+#if !defined(CHROME_MULTIPLE_DLL_BROWSER)
+base::LazyInstance<ContentGpuClient>
+ g_empty_content_gpu_client = LAZY_INSTANCE_INITIALIZER;
base::LazyInstance<ContentRendererClient>
g_empty_content_renderer_client = LAZY_INSTANCE_INITIALIZER;
base::LazyInstance<ContentUtilityClient>
g_empty_content_utility_client = LAZY_INSTANCE_INITIALIZER;
-#endif // !OS_IOS && !CHROME_MULTIPLE_DLL_BROWSER
-
-#if defined(OS_WIN)
+#endif // !CHROME_MULTIPLE_DLL_BROWSER
-#endif // defined(OS_WIN)
+#if defined(V8_USE_EXTERNAL_STARTUP_DATA) && defined(OS_ANDROID)
+#if defined __LP64__
+#define kV8NativesDataDescriptor kV8NativesDataDescriptor64
+#define kV8SnapshotDataDescriptor kV8SnapshotDataDescriptor64
+#else
+#define kV8NativesDataDescriptor kV8NativesDataDescriptor32
+#define kV8SnapshotDataDescriptor kV8SnapshotDataDescriptor32
+#endif
+#endif
-#if defined(OS_POSIX) && !defined(OS_IOS)
+#if defined(OS_POSIX)
// Setup signal-handling state: resanitize most signals, ignore SIGPIPE.
void SetupSignalHandlers() {
@@ -178,7 +211,7 @@ void SetupSignalHandlers() {
CHECK_NE(SIG_ERR, signal(SIGPIPE, SIG_IGN));
}
-#endif // OS_POSIX && !OS_IOS
+#endif // OS_POSIX
void CommonSubprocessInit(const std::string& process_type) {
#if defined(OS_WIN)
@@ -204,7 +237,10 @@ void CommonSubprocessInit(const std::string& process_type) {
#if !defined(OFFICIAL_BUILD)
// Print stack traces to stderr when crashes occur. This opens up security
// holes so it should never be enabled for official builds.
- base::debug::EnableInProcessStackDumping();
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableInProcessStackTraces)) {
+ base::debug::EnableInProcessStackDumping();
+ }
#if defined(OS_WIN)
base::RouteStdioToConsole(false);
LoadLibraryA("dbghelp.dll");
@@ -226,17 +262,19 @@ class ContentClientInitializer {
}
#endif // !CHROME_MULTIPLE_DLL_CHILD
-#if !defined(OS_IOS) && !defined(CHROME_MULTIPLE_DLL_BROWSER)
- if (process_type == switches::kPluginProcess ||
- process_type == switches::kPpapiPluginProcess) {
+#if !defined(CHROME_MULTIPLE_DLL_BROWSER)
+ if (process_type == switches::kGpuProcess ||
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSingleProcess)) {
if (delegate)
- content_client->plugin_ = delegate->CreateContentPluginClient();
- if (!content_client->plugin_)
- content_client->plugin_ = &g_empty_content_plugin_client.Get();
- // Single process not supported in split dll mode.
- } else if (process_type == switches::kRendererProcess ||
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kSingleProcess)) {
+ content_client->gpu_ = delegate->CreateContentGpuClient();
+ if (!content_client->gpu_)
+ content_client->gpu_ = &g_empty_content_gpu_client.Get();
+ }
+
+ if (process_type == switches::kRendererProcess ||
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSingleProcess)) {
if (delegate)
content_client->renderer_ = delegate->CreateContentRendererClient();
if (!content_client->renderer_)
@@ -252,7 +290,7 @@ class ContentClientInitializer {
if (!content_client->utility_)
content_client->utility_ = &g_empty_content_utility_client.Get();
}
-#endif // !OS_IOS && !CHROME_MULTIPLE_DLL_BROWSER
+#endif // !CHROME_MULTIPLE_DLL_BROWSER
}
};
@@ -301,6 +339,9 @@ int RunZygote(const MainFunctionParams& main_function_params,
MainFunctionParams main_params(command_line);
main_params.zygote_child = true;
+ scoped_ptr<base::FieldTrialList> field_trial_list;
+ InitializeFieldTrialAndFeatureList(&field_trial_list);
+
for (size_t i = 0; i < arraysize(kMainFunctions); ++i) {
if (process_type == kMainFunctions[i].name)
return kMainFunctions[i].function(main_params);
@@ -314,7 +355,6 @@ int RunZygote(const MainFunctionParams& main_function_params,
}
#endif // defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
-#if !defined(OS_IOS)
static void RegisterMainThreadFactories() {
#if !defined(CHROME_MULTIPLE_DLL_BROWSER) && !defined(CHROME_MULTIPLE_DLL_CHILD)
UtilityProcessHostImpl::RegisterUtilityMainThreadFactory(
@@ -349,15 +389,15 @@ int RunNamedProcessTypeMain(
#endif
#if !defined(CHROME_MULTIPLE_DLL_BROWSER)
#if defined(ENABLE_PLUGINS)
-#if !defined(OS_LINUX)
- { switches::kPluginProcess, PluginMain },
-#endif
{ switches::kPpapiPluginProcess, PpapiPluginMain },
{ switches::kPpapiBrokerProcess, PpapiBrokerMain },
#endif // ENABLE_PLUGINS
{ switches::kUtilityProcess, UtilityMain },
{ switches::kRendererProcess, RendererMain },
{ switches::kGpuProcess, GpuMain },
+#if defined(OS_ANDROID)
+ { switches::kDownloadProcess, DownloadMain},
+#endif
#endif // !CHROME_MULTIPLE_DLL_BROWSER
};
@@ -397,7 +437,6 @@ int RunNamedProcessTypeMain(
NOTREACHED() << "Unknown process type: " << process_type;
return 1;
}
-#endif // !OS_IOS
class ContentMainRunnerImpl : public ContentMainRunner {
public:
@@ -417,16 +456,6 @@ class ContentMainRunnerImpl : public ContentMainRunner {
Shutdown();
}
-#if defined(USE_TCMALLOC)
- static bool GetNumericPropertyThunk(const char* name, size_t* value) {
- return MallocExtension::instance()->GetNumericProperty(name, value);
- }
-
- static void ReleaseFreeMemoryThunk() {
- MallocExtension::instance()->ReleaseFreeMemory();
- }
-#endif
-
int Initialize(const ContentMainParams& params) override {
ui_task_ = params.ui_task;
@@ -445,35 +474,7 @@ class ContentMainRunnerImpl : public ContentMainRunner {
TRACE_EVENT0("startup,benchmark", "ContentMainRunnerImpl::Initialize");
#endif // OS_ANDROID
- // NOTE(willchan): One might ask why these TCMalloc-related calls are done
- // here rather than in process_util_linux.cc with the definition of
- // EnableTerminationOnOutOfMemory(). That's because base shouldn't have a
- // dependency on TCMalloc. Really, we ought to have our allocator shim code
- // implement this EnableTerminationOnOutOfMemory() function. Whateverz.
- // This works for now.
-#if !defined(OS_MACOSX) && defined(USE_TCMALLOC)
- // For tcmalloc, we need to tell it to behave like new.
- tc_set_new_mode(1);
-
- // On windows, we've already set these thunks up in _heap_init()
- base::allocator::SetGetNumericPropertyFunction(GetNumericPropertyThunk);
- base::allocator::SetReleaseFreeMemoryFunction(ReleaseFreeMemoryThunk);
-
- // Provide optional hook for monitoring allocation quantities on a
- // per-thread basis. Only set the hook if the environment indicates this
- // needs to be enabled.
- const char* profiling = getenv(tracked_objects::kAlternateProfilerTime);
- if (profiling &&
- (atoi(profiling) == tracked_objects::TIME_SOURCE_TYPE_TCMALLOC)) {
- tracked_objects::SetAlternateTimeSource(
- MallocExtension::GetBytesAllocatedOnCurrentThread,
- tracked_objects::TIME_SOURCE_TYPE_TCMALLOC);
- }
-#endif // !OS_MACOSX && USE_TCMALLOC
-
-#if !defined(OS_IOS)
base::GlobalDescriptors* g_fds = base::GlobalDescriptors::GetInstance();
-#endif
// On Android,
// - setlocale() is not supported.
@@ -481,7 +482,7 @@ class ContentMainRunnerImpl : public ContentMainRunner {
// stack trace when crashing.
// - The ipc_fd is passed through the Java service.
// Thus, these are all disabled.
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#if !defined(OS_ANDROID)
// Set C library locale to make sure CommandLine can parse argument values
// in correct encoding.
setlocale(LC_ALL, "");
@@ -489,7 +490,9 @@ class ContentMainRunnerImpl : public ContentMainRunner {
SetupSignalHandlers();
g_fds->Set(kPrimaryIPCChannel,
kPrimaryIPCChannel + base::GlobalDescriptors::kBaseDescriptor);
-#endif // !OS_ANDROID && !OS_IOS
+ g_fds->Set(kMojoIPCChannel,
+ kMojoIPCChannel + base::GlobalDescriptors::kBaseDescriptor);
+#endif // !OS_ANDROID
#if defined(OS_LINUX) || defined(OS_OPENBSD)
g_fds->Set(kCrashDumpSignal,
@@ -504,22 +507,18 @@ class ContentMainRunnerImpl : public ContentMainRunner {
// The exit manager is in charge of calling the dtors of singleton objects.
// On Android, AtExitManager is set up when library is loaded.
- // On iOS, it's set up in main(), which can't call directly through to here.
// A consequence of this is that you can't use the ctor/dtor-based
// TRACE_EVENT methods on Linux or iOS builds till after we set this up.
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
+#if !defined(OS_ANDROID)
if (!ui_task_) {
// When running browser tests, don't create a second AtExitManager as that
// interfers with shutdown when objects created before ContentMain is
// called are destructed when it returns.
exit_manager_.reset(new base::AtExitManager);
}
-#endif // !OS_ANDROID && !OS_IOS
+#endif // !OS_ANDROID
- // Don't create this loop on iOS, since the outer loop is already handled
- // and a loop that's destroyed in shutdown interleaves badly with the event
- // loop pool on iOS.
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MACOSX)
// We need this pool for all the objects created before we get to the
// event loop, but we don't want to leave them hanging around until the
// app quits. Each "main" needs to flush this pool right before it goes into
@@ -551,9 +550,7 @@ class ContentMainRunnerImpl : public ContentMainRunner {
if (delegate_ && delegate_->ShouldEnableProfilerRecording())
tracked_objects::ScopedTracker::Enable();
-#if !defined(OS_IOS)
SetProcessTitleFromCommandLine(argv);
-#endif
#endif // !OS_ANDROID
int exit_code = 0;
@@ -567,10 +564,8 @@ class ContentMainRunnerImpl : public ContentMainRunner {
std::string process_type =
command_line.GetSwitchValueASCII(switches::kProcessType);
-#if !defined(OS_IOS)
// Initialize mojo here so that services can be registered.
InitializeMojo();
-#endif
#if defined(OS_WIN)
if (command_line.HasSwitch(switches::kDeviceScaleFactor)) {
@@ -636,7 +631,7 @@ class ContentMainRunnerImpl : public ContentMainRunner {
TRACE_EVENT0("startup,benchmark", "ContentMainRunnerImpl::Initialize");
#endif // !OS_ANDROID
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MACOSX)
// We need to allocate the IO Ports before the Sandbox is initialized or
// the first instance of PowerMonitor is created.
// It's important not to allocate the ports for processes which don't
@@ -749,7 +744,7 @@ class ContentMainRunnerImpl : public ContentMainRunner {
#if defined(OS_WIN)
CHECK(InitializeSandbox(params.sandbox_info));
-#elif defined(OS_MACOSX) && !defined(OS_IOS)
+#elif defined(OS_MACOSX)
if (process_type == switches::kRendererProcess ||
process_type == switches::kPpapiPluginProcess ||
(delegate_ && delegate_->DelaySandboxInitialization(process_type))) {
@@ -775,6 +770,14 @@ class ContentMainRunnerImpl : public ContentMainRunner {
std::string process_type =
command_line.GetSwitchValueASCII(switches::kProcessType);
+ // Run this logic on all child processes. Zygotes will run this at a later
+ // point in time when the command line has been updated.
+ scoped_ptr<base::FieldTrialList> field_trial_list;
+ if (!process_type.empty() && process_type != switches::kZygoteProcess)
+ InitializeFieldTrialAndFeatureList(&field_trial_list);
+
+ base::HistogramBase::EnableActivityReportHistogram(process_type);
+
MainFunctionParams main_params(command_line);
main_params.ui_task = ui_task_;
#if defined(OS_WIN)
@@ -783,11 +786,7 @@ class ContentMainRunnerImpl : public ContentMainRunner {
main_params.autorelease_pool = autorelease_pool_.get();
#endif
-#if !defined(OS_IOS)
return RunNamedProcessTypeMain(process_type, main_params, delegate_);
-#else
- return 1;
-#endif
}
void Shutdown() override {
@@ -809,7 +808,7 @@ class ContentMainRunnerImpl : public ContentMainRunner {
#endif // _CRTDBG_MAP_ALLOC
#endif // OS_WIN
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MACOSX)
autorelease_pool_.reset(NULL);
#endif
diff --git a/chromium/content/app/mojo/mojo_init.cc b/chromium/content/app/mojo/mojo_init.cc
index b289aa738b8..828887dead7 100644
--- a/chromium/content/app/mojo/mojo_init.cc
+++ b/chromium/content/app/mojo/mojo_init.cc
@@ -9,11 +9,7 @@
#include "base/memory/scoped_ptr.h"
#include "content/public/common/content_switches.h"
#include "ipc/ipc_channel.h"
-#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
-
-#if defined(MOJO_SHELL_CLIENT)
-#include "content/common/mojo/mojo_shell_connection_impl.h"
-#endif
+#include "mojo/edk/embedder/embedder.h"
namespace content {
@@ -22,30 +18,8 @@ namespace {
class MojoInitializer {
public:
MojoInitializer() {
- const base::CommandLine& command_line =
- *base::CommandLine::ForCurrentProcess();
- std::string process_type =
- command_line.GetSwitchValueASCII(switches::kProcessType);
- if (0 && process_type.empty() && !command_line.HasSwitch("use-old-edk")) {
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- "use-new-edk");
- }
-
- if (command_line.HasSwitch("use-new-edk")) {
- bool initialize_as_parent = process_type.empty();
-#if defined(MOJO_SHELL_CLIENT)
- if (IsRunningInMojoShell())
- initialize_as_parent = false;
-#endif
- if (initialize_as_parent) {
- mojo::embedder::PreInitializeParentProcess();
- } else {
- mojo::embedder::PreInitializeChildProcess();
- }
- }
-
- mojo::embedder::SetMaxMessageSize(IPC::Channel::kMaximumMessageSize);
- mojo::embedder::Init();
+ mojo::edk::SetMaxMessageSize(IPC::Channel::kMaximumMessageSize);
+ mojo::edk::Init();
}
};
diff --git a/chromium/content/app/strings/content_strings.grd b/chromium/content/app/strings/content_strings.grd
index e56c6856c15..9219357a5b9 100644
--- a/chromium/content/app/strings/content_strings.grd
+++ b/chromium/content/app/strings/content_strings.grd
@@ -39,7 +39,8 @@ below:
<outputs>
<!-- TODO add each of your output files. Modify the three below, and add
your own for your various languages. See the user's guide
- (http://wiki/Main/GritUsersGuide) for more details.
+ (https://www.chromium.org/developers/tools-we-use-in-chromium/grit/grit-users-guide)
+ for more details.
Note that all output references are relative to the output directory
which is specified at build time. -->
<output filename="grit/content_strings.h" type="rc_header">
@@ -167,6 +168,9 @@ below:
<message name="IDS_DETAILS_WITHOUT_SUMMARY_LABEL" desc="Clickable label to show detailed information or to hide the detailed information.">
Details
</message>
+ <message name="IDS_DOWNLOAD_BUTTON_LABEL" desc="Clickable button label to download media file.">
+ Save
+ </message>
<message name="IDS_SEARCHABLE_INDEX_INTRO" desc="Text that appears at the start of nearly-obsolete webpages in the form of a 'searchable index'.">
This is a searchable index. Enter search keywords: '''
</message>
@@ -266,9 +270,6 @@ below:
<ph name="WEEK">$1<ex>Week 38, 2014</ex></ph>, starting on <ph name="WEEK_START_DATE">$2<ex>September 15, 2014</ex></ph>
</message>
- <message name="IDS_AX_ROLE_ADDRESS" desc="accessibility role description for an address (as in a person's contact information)">
- address
- </message>
<message name="IDS_AX_ROLE_ARTICLE" desc="accessibility role description for article">
article
</message>
@@ -281,7 +282,10 @@ below:
<message name="IDS_AX_ROLE_CHECK_BOX" desc="accessibility role description for a check box">
checkbox
</message>
- <message name="IDS_AX_ROLE_DESCRIPTION_DETAIL" desc="accessibility role description for a definition">
+ <message name="IDS_AX_ROLE_CONTENT_INFO" desc="accessibility role description for credits and information about the content of the page, like copyrights and privacy statements">
+ content info
+ </message>
+ <message name="IDS_AX_ROLE_DEFINITION" desc="accessibility role description for a definition">
definition
</message>
<message name="IDS_AX_ROLE_DESCRIPTION_LIST" desc="accessibility role description for a definition list">
@@ -296,17 +300,17 @@ below:
<message name="IDS_AX_ROLE_FORM" desc="accessibility role description for form">
form
</message>
+ <message name="IDS_AX_ROLE_FOOTER" desc="accessibility role description for footers">
+ footer
+ </message>
<if expr="is_macosx">
- <message name="IDS_AX_ROLE_FOOTER" desc="accessibility role description for footers">
- footer
- </message>
<message name="IDS_AX_ROLE_STEPPER" desc="accessibility role description for a stepper - a control where you can use up/down arrows to increment or decrement it. The name 'stepper' is how this user interface element is described by VoiceOver on Mac OS X; the translation should be consistent with VoiceOver.">
stepper
</message>
- <message name="IDS_AX_ROLE_TOGGLE_BUTTON" desc="accessibility role description for a toggle button">
- toggle button
- </message>
</if>
+ <message name="IDS_AX_ROLE_TOGGLE_BUTTON" desc="accessibility role description for a toggle button">
+ toggle button
+ </message>
<message name="IDS_AX_ROLE_HEADING" desc="accessibility role description for headings">
heading
</message>
@@ -346,7 +350,167 @@ below:
<message name="IDS_AX_ROLE_WEB_AREA" desc="accessibility role description for web area">
HTML content
</message>
-
+ <if expr="is_android">
+ <message name="IDS_AX_ROLE_ALERT" desc="accessibility role description for an alert">
+ alert
+ </message>
+ <message name="IDS_AX_ROLE_ALERT_DIALOG" desc="accessibility role description for an alert dialog">
+ alert_dialog
+ </message>
+ <message name="IDS_AX_ROLE_APPLICATION" desc="accessibility role description for an application">
+ application
+ </message>
+ <message name="IDS_AX_ROLE_BLOCKQUOTE" desc="accessibility role description for a blockquote">
+ blockquote
+ </message>
+ <message name="IDS_AX_ROLE_BUSY_INDICATOR" desc="accessibility role description for a busy indicator">
+ busy indicator
+ </message>
+ <message name="IDS_AX_ROLE_BUTTON" desc="accessibility role description for a button">
+ button
+ </message>
+ <message name="IDS_AX_ROLE_BUTTON_DROP_DOWN" desc="accessibility role description for a button that drops down">
+ drop down button
+ </message>
+ <message name="IDS_AX_ROLE_CELL" desc="accessibility role description for a cell, like in a table or grid">
+ cell
+ </message>
+ <message name="IDS_AX_ROLE_COLOR_WELL" desc="accessibility role description for a color picker">
+ color picker
+ </message>
+ <message name="IDS_AX_ROLE_COLUMN_HEADER" desc="accessibility role description for a column header">
+ column header
+ </message>
+ <message name="IDS_AX_ROLE_COMBO_BOX" desc="accessibility role description for a combo box, an editable text control with an associated drop-down list">
+ combo box
+ </message>
+ <message name="IDS_AX_ROLE_DATE" desc="accessibility role description for a date picker">
+ date picker
+ </message>
+ <message name="IDS_AX_ROLE_DATE_TIME" desc="accessibility role description for a date / time picker">
+ date and time picker
+ </message>
+ <message name="IDS_AX_ROLE_DIALOG" desc="accessibility role description for a dialog">
+ dialog
+ </message>
+ <message name="IDS_AX_ROLE_DIRECTORY" desc="accessibility role description for a directory, for example a table of contents or list of employees">
+ directory
+ </message>
+ <message name="IDS_AX_ROLE_DISCLOSURE_TRIANGLE" desc="accessibility role description for a disclosure triangle, a control shaped like a triangle that expands or collapses to show or hide extra content">
+ disclosure triangle
+ </message>
+ <message name="IDS_AX_ROLE_DOCUMENT" desc="accessibility role description for a document">
+ document
+ </message>
+ <message name="IDS_AX_ROLE_EMBEDDED_OBJECT" desc="accessibility role description for an embedded object, like a video inside a web page">
+ object
+ </message>
+ <message name="IDS_AX_ROLE_GRAPHIC" desc="accessibility role description for a graphic or image">
+ graphic
+ </message>
+ <message name="IDS_AX_ROLE_HEADING_WITH_LEVEL" desc="accessibility role description for a heading with a heading level, for example 'heading 1' is the most important heading and 'heading 3' is less important">
+ heading <ph name="HEADING_LEVEL">$1<ex>1</ex></ph>
+ </message>
+ <message name="IDS_AX_ROLE_INPUT_TIME" desc="accessibility role description for a time picker control">
+ time picker
+ </message>
+ <message name="IDS_AX_ROLE_LIST_BOX" desc="accessibility role description for a list box control">
+ list box
+ </message>
+ <message name="IDS_AX_ROLE_LOG" desc="accessibility role description for an information log, such as a chat log or error log">
+ log
+ </message>
+ <message name="IDS_AX_ROLE_MARQUEE" desc="accessibility role description for a marquee, such as a stock ticker or ad banner that frequently changes">
+ marquee
+ </message>
+ <message name="IDS_AX_ROLE_MENU" desc="accessibility role description for a menu">
+ menu
+ </message>
+ <message name="IDS_AX_ROLE_MENU_BAR" desc="accessibility role description for a menu bar">
+ menu bar
+ </message>
+ <message name="IDS_AX_ROLE_MENU_BUTTON" desc="accessibility role description for a menu button, a button that opens a menu">
+ menu button
+ </message>
+ <message name="IDS_AX_ROLE_MENU_ITEM" desc="accessibility role description for a menu item">
+ menu item
+ </message>
+ <message name="IDS_AX_ROLE_METER" desc="accessibility role description for a meter, for example a temperature indicator or progress bar">
+ meter
+ </message>
+ <message name="IDS_AX_ROLE_NOTE" desc="accessibility role description for a note">
+ note
+ </message>
+ <message name="IDS_AX_ROLE_OUTLINE" desc="accessibility role description for an outline, a presentation of information in a tree-like structure">
+ outline
+ </message>
+ <message name="IDS_AX_ROLE_POP_UP_BUTTON" desc="accessibility role description for a pop up button">
+ pop up button
+ </message>
+ <message name="IDS_AX_ROLE_PROGRESS_INDICATOR" desc="accessibility role description for a progress indicator">
+ progress indicator
+ </message>
+ <message name="IDS_AX_ROLE_RADIO" desc="accessibility role description for a radio button">
+ radio button
+ </message>
+ <message name="IDS_AX_ROLE_RADIO_GROUP" desc="accessibility role description for a group of related radio buttons">
+ radio group
+ </message>
+ <message name="IDS_AX_ROLE_ROW_HEADER" desc="accessibility role description for a row header in a table">
+ row header
+ </message>
+ <message name="IDS_AX_ROLE_RULER" desc="accessibility role description for a ruler">
+ ruler
+ </message>
+ <message name="IDS_AX_ROLE_SCROLL_BAR" desc="accessibility role description for a scroll bar">
+ scroll bar
+ </message>
+ <message name="IDS_AX_ROLE_SEARCH" desc="accessibility role description for the section of a web page containing controls for searching the page or site">
+ search
+ </message>
+ <message name="IDS_AX_ROLE_SLIDER" desc="accessibility role description for a slider">
+ slider
+ </message>
+ <message name="IDS_AX_ROLE_SPIN_BUTTON" desc="accessibility role description for a spin button, a control containing a numerical value that can be incremented or decremented by 1">
+ spin button
+ </message>
+ <message name="IDS_AX_ROLE_SPLITTER" desc="accessibility role description for a splitter, a control that splits the window in two pieces and can usually be dragged">
+ splitter
+ </message>
+ <message name="IDS_AX_ROLE_TAB" desc="accessibility role description for a tab">
+ tab
+ </message>
+ <message name="IDS_AX_ROLE_TABLE" desc="accessibility role description for a table">
+ table
+ </message>
+ <message name="IDS_AX_ROLE_TAB_LIST" desc="accessibility role description for a tab list">
+ tab list
+ </message>
+ <message name="IDS_AX_ROLE_TAB_PANEL" desc="accessibility role description for a tab panel, the part of the window that changes when selecting a new tab">
+ tab panel
+ </message>
+ <message name="IDS_AX_ROLE_TIME" desc="accessibility role description for a time">
+ time
+ </message>
+ <message name="IDS_AX_ROLE_TIMER" desc="accessibility role description for a timer">
+ timer
+ </message>
+ <message name="IDS_AX_ROLE_TOOLBAR" desc="accessibility role description for a toolbar">
+ toolbar
+ </message>
+ <message name="IDS_AX_ROLE_TOOLTIP" desc="accessibility role description for a tooltip">
+ tooltip
+ </message>
+ <message name="IDS_AX_ROLE_TREE" desc="accessibility role description for a tree">
+ tree
+ </message>
+ <message name="IDS_AX_ROLE_TREE_GRID" desc="accessibility role description for a tree grid">
+ tree grid
+ </message>
+ <message name="IDS_AX_ROLE_TREE_ITEM" desc="accessibility role description for a tree item">
+ tree item
+ </message>
+ </if>
<message name="IDS_AX_BUTTON_ACTION_VERB" desc="Verb stating the action that will occur when a button is pressed, as used by accessibility.">
press
</message>
@@ -365,6 +529,12 @@ below:
<message name="IDS_AX_LINK_ACTION_VERB" desc="Verb stating the action that will occur when a link is clicked, as used by accessibility.">
jump
</message>
+ <message name="IDS_AX_POP_UP_BUTTON_ACTION_VERB" desc="Verb stating the action that will occur when a pop-up button is clicked, as used by accessibility.">
+ open
+ </message>
+ <message name="IDS_AX_DEFAULT_ACTION_VERB" desc="Verb stating the action that will occur when clicking on a generic clickable object, when we don't know what that action is, as used by accessibility.">
+ click
+ </message>
<message name="IDS_AX_AM_PM_FIELD_TEXT" desc="Accessible description of the AM/PM field in a date/time control">
AM/PM
@@ -445,11 +615,11 @@ below:
<message name="IDS_AX_MEDIA_HIDE_CLOSED_CAPTIONS_BUTTON" desc="accessibility role description for hide closed captions button">
hide closed captions
</message>
-
+
<message name="IDS_AX_MEDIA_CAST_OFF_BUTTON" desc="accessibility role description for remote playback button">
play on remote device
</message>
-
+
<message name="IDS_AX_MEDIA_CAST_ON_BUTTON" desc="accessibility role description for remote playback control button">
control remote playback
</message>
@@ -521,7 +691,7 @@ below:
<message name="IDS_AX_MEDIA_CAST_OFF_BUTTON_HELP" desc="accessibility help description for remote playback button">
play on remote device
</message>
-
+
<message name="IDS_AX_MEDIA_CAST_ON_BUTTON_HELP" desc="accessibility help description for remote playback control button">
control remote playback
</message>
diff --git a/chromium/content/app/strings/translations/content_strings_am.xtb b/chromium/content/app/strings/translations/content_strings_am.xtb
index e21a9f31462..50d23f929e2 100644
--- a/chromium/content/app/strings/translations/content_strings_am.xtb
+++ b/chromium/content/app/strings/translations/content_strings_am.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="am">
<translation id="1014825444426747588">ባዶ</translation>
+<translation id="1018939186200882850">የምናሌ ንጥል</translation>
<translation id="1020833440720551630">የድምጽ ትራክ ላይ ድምጸ-ከል አድርግ</translation>
<translation id="10623998915015855">የማቀያየሪያ አዝራር</translation>
<translation id="1088086359088493902">ሰኮንዶች</translation>
<translation id="1171774979989969504">እባክዎ የኢሜይል አድራሻ ያስገቡ።</translation>
<translation id="1188858454923323853">ማሟያ</translation>
+<translation id="1206619573307042055">መልሶ መልስ</translation>
+<translation id="1206693055195146388">ተንሸራታች</translation>
<translation id="1235745349614807883">የቅርብ ጊዜ ፍለጋዎችን አጽዳ</translation>
+<translation id="1281252709823657822">መገናኛ</translation>
<translation id="1342835525016946179">ጽሑፍ</translation>
<translation id="1359897965706325498">ሰንደቅ</translation>
<translation id="1589122976691792535">ክልል</translation>
<translation id="1591562245178063882">በዚህ ወር</translation>
<translation id="1637811476055996098">ፋይሎችን ይምረጡ</translation>
+<translation id="167575180612809735">የስራ ላይ አመልካች</translation>
<translation id="1729654308190250600">እባክዎ ባዶ ያልሆነ የኢሜይል አድራሻ ያስገቡ።</translation>
<translation id="1758486001363313524">ሌላ...</translation>
+<translation id="1806710327868736751">የማንቂያ_መገናኛ</translation>
+<translation id="1821985195704844674">የዛፍ ፍርግርግ</translation>
<translation id="1822429046913737220">ጥዋት/ከሰዓት</translation>
<translation id="1832974991323546415">በርቀት መሳሪያ ላይ አጫውት</translation>
<translation id="1842960171412779397">ምረጥ</translation>
+<translation id="1880518467580572141">ቢጋር</translation>
<translation id="1921819250265091946">ቀቀ</translation>
<translation id="1930711995431081526">ሁኔታ</translation>
<translation id="1938124657309484470">ዋጋ <ph name="MAXIMUM_DATE_OR_TIME" /> ወይም ከዚያ በፊት መሆን አለበት።</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">እባክዎ ይህ ጽሑፍ ወደ <ph name="MAX_CHARACTERS" /> ወይም ከዚያ በታች ቁምፊዎች ያሳጥሩት (በአሁኑ ጊዜ <ph name="CURRENT_LENGTH" /> ቁምፊዎችን እየተጠቀሙ ነዎት)።</translation>
<translation id="2247351761944213033">ሳምንት <ph name="WEEKNUMBER" />፣ <ph name="YEAR" /></translation>
<translation id="2291999235780842123">አመልካች ሳጥን</translation>
+<translation id="2335594187091864976">የቀን እና የሰዓት መራጭ</translation>
<translation id="248395913932153421">ቀን</translation>
<translation id="2507943997699731163">እባክዎ ይህን መስክ ይሙሉት።</translation>
+<translation id="2508569020611168319">የትር ዝርዝር</translation>
<translation id="2548326553472216322">የቅርብ ጊዜ ፍለጋዎች የሉም</translation>
<translation id="2572483411312390101">አጫውት</translation>
<translation id="2613802280814924224">እባክዎ የሚሰራ ዋጋ ያስገቡ። የሚቀርበው ዋጋ <ph name="VALID_VALUE" /> ነው።</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">ግርጌ</translation>
<translation id="2723001399770238859">ድምጽ</translation>
<translation id="2746543609216772311">ዋጋ <ph name="MINIMUM_DATE_OR_TIME" /> ወይም ከዚያ በኋላ መሆን አለበት።</translation>
+<translation id="2759744352195237655">የብቅ-ባይ አዝራር</translation>
<translation id="2761667185364618470">ለመቀጠል ከፈለጉ እባክዎ ይህ ሳጥን ላይ ምልክት ያድርጉ።</translation>
<translation id="2846343701378493991">1024(መካከለኛ ደረጃ)</translation>
+<translation id="2896972712917208084">የሬዲዮ ስብስብ</translation>
<translation id="2901282870647571346">የአሁኑ የፊልም ሁኔታ</translation>
<translation id="2908441821576996758">እባክዎ በኮማ የተለዩ የኢሜይል አድራሻዎች ዝርዝር ያስገቡ።</translation>
+<translation id="2931838996092594335">ጠቅ ያድርጉ</translation>
+<translation id="2940813599313844715">ነገር</translation>
<translation id="2942448076852699108">የደመቀ ይዘት</translation>
<translation id="3040011195152428237">አገናኝ</translation>
<translation id="3075154866155599887">እባክዎ የሚሰራ ዋጋ ያስገቡ። መስኩ ያልተጠናቀቀ ነው ወይም ልክ ያልሆነ ቀን አለው።</translation>
+<translation id="3078740164268491126">ሠንጠረዥ</translation>
+<translation id="3086746722712840547">note</translation>
<translation id="310520048233152454">እባክዎ አንድ ዩአርኤል ያስገቡ።</translation>
+<translation id="3175736971608411871">ሰዓት ቆጣሪ</translation>
+<translation id="3199563858620722075">ጥምድ ሳጥን</translation>
<translation id="3450233048674729344">ዋጋ ከ<ph name="MAXIMUM" /> የሚያንስ ወይም ከእሱ እኩል መሆን አለበት።</translation>
<translation id="3486220673238053218">ብየና</translation>
+<translation id="3557673793733683882">አርዕስት <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">የፊልሙ ቀሪ ሰከንዶች</translation>
<translation id="3706100364254443312">ቀይር</translation>
<translation id="3732799496749320381">ሚሜ</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">የጊዜ ቆይታ</translation>
<translation id="3822383571486410024">እባክዎ ይህን ጽሑፍ ወደ <ph name="MIN_CHARACTERS" /> ቁምፊዎች ወይም ከዚያ በላይ ያራዝሙት (አሁን እየተጠቀሙ ያሉት <ph name="CURRENT_LENGTH" />ቁምፊዎችን ነው)።</translation>
<translation id="383465348367842624">ከ«<ph name="ATSIGN" />» በፊት የሚመጣ ክፍል የ«<ph name="INVALIDCHARACTER" />» ምልክት መያዝ የለበትም።</translation>
+<translation id="3924558731517983934">መተግበሪያ</translation>
+<translation id="3960700977367013758">የማሸብለያ አሞሌ</translation>
<translation id="4103419683916926126">ሚሊሰኮንዶች</translation>
+<translation id="4151657705144244502">ግራፊክ</translation>
<translation id="4201051445878709314">ቀዳሚውን ወር አሳይ</translation>
<translation id="4202807286478387388">ዝለል</translation>
+<translation id="421884353938374759">color picker</translation>
+<translation id="4248100235867064564">የምናሌ አሞሌ</translation>
+<translation id="4254339807215791271">የይዘት መረጃ</translation>
<translation id="4360991593054037559">እባክዎ የሚሰራ ዋጋ ያስገቡ። ሁለቱ የሚቀርቡ ዋጋዎች <ph name="VALID_VALUE_LOW" /> እና <ph name="VALID_VALUE_HIGHER" /> ናቸው።</translation>
+<translation id="4413860115965805769">የምናሌ አዝራር</translation>
<translation id="4522570452068850558">ዝርዝሮች</translation>
<translation id="4597532268155981612">ቅጽ</translation>
+<translation id="4661075872484491155">ዛፍ</translation>
<translation id="4664250907885839816">ከ«<ph name="ATSIGN" />» በኋላ የሚመጣ ክፍል የ«<ph name="INVALIDCHARACTER" />» ምልክት መያዝ የለበትም።</translation>
+<translation id="4757246831282535685">የትር ፓነል</translation>
<translation id="4763480195061959176">ቪዲዮ</translation>
+<translation id="479989351350248267">ፈልግ</translation>
<translation id="4812940957355064477">እባክዎ ቁጥር ያስገቡ።</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> ተመርጠዋል</translation>
<translation id="49969490063480558">እባክዎ ከ«<ph name="ATSIGN" />» በኋላ አንድ ክፍል ያስገቡ። «<ph name="INVALIDADDRESS" />» ያልተሟላ ነው።</translation>
+<translation id="5034860022980953847">የሂደት አመልካች</translation>
<translation id="5048533449481078685">ዝርዝር አመልካች</translation>
<translation id="5117590920725113268">ቀጣዩን ወር አሳይ</translation>
+<translation id="512758898067543763">የረድፍ ራስጌ</translation>
<translation id="5164977714490026579">ዋጋ ከ<ph name="MINIMUM" /> የሚበልጥ ወይም ከእሱ እኩል መሆን አለበት።</translation>
<translation id="5307600278924710095">እባክዎ አንድ ክፍል ያስገቡና «<ph name="ATSIGN" />»ን ያስከትሉ። «<ph name="INVALIDADDRESS" />» ያልተሟላ ነው።</translation>
+<translation id="5317780077021120954">አስቀምጥ</translation>
<translation id="5406322316791861025">ምስል</translation>
+<translation id="5453733299334684579">የዛፍ ንጥል</translation>
<translation id="5466621249238537318">እባክዎ አንድ ወይም ተጨማሪ ፋይሎችን ይምረጡ።</translation>
<translation id="5468998798572797635">ከሙሉ ማያ ገጽ ውጣ</translation>
<translation id="5476505524087279545">አታመልክት</translation>
+<translation id="5516424706154626233">ቀን መራጭ</translation>
<translation id="5546461542133609677">ድምፅ-ከልን አንሳ</translation>
+<translation id="561939826962581046">ሰዓት</translation>
<translation id="5641012560118721995">መልሶ ማጫወትን ለአፍታ አቁም</translation>
+<translation id="5643186887447432888">አዝራር</translation>
<translation id="5843503607508392247">ሌላ...</translation>
<translation id="5939518447894949180">ዳግም አስጀምር</translation>
<translation id="5944544982112848342">2048(ከፍተኛ ደረጃ)</translation>
<translation id="5966707198760109579">ሳምንት</translation>
-<translation id="598301471034819706">አድራሻ</translation>
+<translation id="5987525920412732405">ማሾሪያ አዝራር</translation>
<translation id="6015796118275082299">ዓመት</translation>
+<translation id="6023896073578205740">የዝርዝር ሳጥን</translation>
<translation id="6101327004457443354">የድምጹ ትራክ ድምጸ-ከል አንሳ</translation>
<translation id="6119846243427417423">አንቃ</translation>
+<translation id="6164829606128959761">ሜትር</translation>
<translation id="6270583010843788609">የፊልም ሰዓት መስመር አውራ ጣት</translation>
<translation id="6359256949422175976">የፊልም ሰዓት አንፏቃቂ አውራ ጣት</translation>
<translation id="6398862346408813489">የወር መምረጫ ፓነል አሳይ</translation>
<translation id="6404546809543547843">የኦዲዮ ሰዓት አንፏቃቂ</translation>
+<translation id="648732519525291180">ሰዓት መራጭ</translation>
<translation id="658823671542763450">ወደ ሙሉ ገጽ ዕይታ ግባ</translation>
+<translation id="6637586476836377253">የምዝግብ ማስታወሻ</translation>
<translation id="6643016212128521049">አጽዳ</translation>
<translation id="6663448176199120256">የቅርብ ጊዜ ፍለጋዎችን</translation>
<translation id="668171684555832681">ሌላ…</translation>
<translation id="6692633176391053278">አስኪያጅ</translation>
+<translation id="6739588121953935928">ማስመሪያ</translation>
+<translation id="6755330956360078551">ጠቃሚ የመሣሪያ ምክር</translation>
<translation id="6820355525329141109">ተሰኪን መጫን አልተቻለም።</translation>
<translation id="6843725295806269523">ድምጸ-ከል ያድርጉ</translation>
<translation id="6845533974506654842">ተጫን</translation>
<translation id="6853785296079745596">የተዘጉ የስዕል መግለጫዎችን ይደብቁ</translation>
+<translation id="6885760532393684712">ማውጫ</translation>
+<translation id="6934078000481955284">የጽሑፍ ጥቅስ</translation>
<translation id="7057186640035488495">የፊልም ሰዓት</translation>
<translation id="709897737746224366">እባክዎ የተጠየቀውን ቅርጸት ያዛምዱ።</translation>
<translation id="7223624360433298498">ያለፈው ጊዜ</translation>
<translation id="7263440858009898357">እባክዎ በዝርዝሩ ውስጥ አንድ ንጥል ይምረጡ።</translation>
+<translation id="727747134524199931">የአምድ ራስጌ</translation>
<translation id="7364796246159120393">ፋይል ምረጥ</translation>
<translation id="739024184232394898">ሌላ...</translation>
+<translation id="7491962110804786152">TAB</translation>
<translation id="7673697353781729403">ሰዓቶች</translation>
<translation id="7720026100085573005">ቀሪ ጊዜ</translation>
<translation id="7740016676195725605">የተዘጉ የስዕል መግለጫዎችን ማሳየት አቁም</translation>
<translation id="7740050170769002709">የኤች ቲ ኤም ኤል ይዘት</translation>
<translation id="7789962463072032349">ላፍታ አቁም</translation>
+<translation id="7802800022689234070">ይፋ ማሳወቂያ ሶስት ማዕዘን</translation>
<translation id="7888071071722539607">እባክዎ በኢሜይል አድራሻው ውስጥ «<ph name="ATSIGN" />» ያካትቱ። «<ph name="INVALIDADDRESS" />» ውስጥ «<ph name="ATSIGN" />» ይጎድላል።</translation>
+<translation id="7891486169920085145">መክፈያ</translation>
<translation id="795667975304826397">ምንም ፋይል አልተመረጠም</translation>
<translation id="8053789581856978548">የጽሑፍ መስክ ፈልግ</translation>
<translation id="8115662671911883373">የተዘጉ የስዕል መግለጫዎችን ማሳየት ጀምር</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">የምስል ካርታ</translation>
<translation id="835897206747267392">ልክ ያልሆነ እሴት።</translation>
<translation id="838869780401515933">አመልክት</translation>
+<translation id="8433900881053900389">የመሣሪያ አሞሌ</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ፋይሎች</translation>
<translation id="8451268428117625855">እባክዎ ፋይል ይምረጡ።</translation>
+<translation id="8461852803063341183">የሬዲዮ አዝራር</translation>
+<translation id="8511325616783751178">የተቆልቋይ አዝራር</translation>
<translation id="8534579021159131403">ደቂቃዎች</translation>
<translation id="8541249477527128034">የማህደረ መረጃ ቁጥጥር</translation>
<translation id="8583702881314752957">የብየና ዝርዝር</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">መልሶ ማጫወት ይጀምሩ</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8987927404178983737">ወር</translation>
+<translation id="9002566407876343676">ክፈት</translation>
<translation id="901493112792887934">የአሁኑ ጊዜ በሰከንዶች</translation>
<translation id="9048119486235211610">አሰሳ</translation>
<translation id="9050748414552849310">የተዘጉ የስዕል መግለጫዎችን አሳይ</translation>
+<translation id="9062295712474918030">ሰነድ</translation>
<translation id="9108370397979208512">ሒሳብ</translation>
<translation id="9132465097189459683">ሌላ...</translation>
+<translation id="9138385573473225930">ማንቂያ</translation>
<translation id="9155987714137265666"><ph name="WEEK" />፣ የሚጀምረው በ<ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">ሕዋስ</translation>
+<translation id="966787709310836684">ምናሌ</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ar.xtb b/chromium/content/app/strings/translations/content_strings_ar.xtb
index 067d3a75f11..5fc9afe8780 100644
--- a/chromium/content/app/strings/translations/content_strings_ar.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ar.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="ar">
<translation id="1014825444426747588">فارغ</translation>
+<translation id="1018939186200882850">عنصر القائمة</translation>
<translation id="1020833440720551630">كتم صوت المقطع الصوتي</translation>
<translation id="10623998915015855">زر التبديل</translation>
<translation id="1088086359088493902">ثوانٍ‬‬</translation>
<translation id="1171774979989969504">الرجاء إدخال عنوان البريد الإلكتروني.</translation>
<translation id="1188858454923323853">تكميلي</translation>
+<translation id="1206619573307042055">صورة بها نص متحرك</translation>
+<translation id="1206693055195146388">شريط تمرير</translation>
<translation id="1235745349614807883">محو آخر عمليات البحث</translation>
+<translation id="1281252709823657822">مربع حوار</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">إعلان بانر</translation>
<translation id="1589122976691792535">منطقة</translation>
<translation id="1591562245178063882">هذا الشهر</translation>
<translation id="1637811476055996098">اختيار الملفات</translation>
+<translation id="167575180612809735">مؤشر مشغول</translation>
<translation id="1729654308190250600">يُرجى إدخال عنوان البريد الإلكتروني وعدم ترك الحق فارغًا.</translation>
<translation id="1758486001363313524">آخر...</translation>
+<translation id="1806710327868736751">مربع حوار_للتنبيه</translation>
+<translation id="1821985195704844674">شبكة متفرعة</translation>
<translation id="1822429046913737220">صباحًا/مساءً</translation>
<translation id="1832974991323546415">تشغيل على جهاز بعيد</translation>
<translation id="1842960171412779397">الاختيار</translation>
+<translation id="1880518467580572141">مخطط</translation>
<translation id="1921819250265091946">يوم</translation>
<translation id="1930711995431081526">الحالة</translation>
<translation id="1938124657309484470">يجب أن تكون القيمة <ph name="MAXIMUM_DATE_OR_TIME" /> أو قبل ذلك.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">الرجاء اختصار هذا النص حتى يصل إلى <ph name="MAX_CHARACTERS" /> من الحروف أو أقل (أنت الآن تستخدم <ph name="CURRENT_LENGTH" /> من الحروف).</translation>
<translation id="2247351761944213033">الأسبوع <ph name="WEEKNUMBER" />، <ph name="YEAR" /></translation>
<translation id="2291999235780842123">مربع اختيار</translation>
+<translation id="2335594187091864976">منتقي التاريخ والوقت</translation>
<translation id="248395913932153421">يوم</translation>
<translation id="2507943997699731163">الرجاء ملء هذا الحقل.</translation>
+<translation id="2508569020611168319">قائمة علامات التبويب</translation>
<translation id="2548326553472216322">لا عمليات بحث حديثة</translation>
<translation id="2572483411312390101">تشغيل</translation>
<translation id="2613802280814924224">يُرجى إدخال قيمة صالحة. علمًا بأن أقرب قيمة صالحة هي <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">تذييل</translation>
<translation id="2723001399770238859">الصوت</translation>
<translation id="2746543609216772311">يجب أن تكون القيمة <ph name="MINIMUM_DATE_OR_TIME" /> أو بعد ذلك.</translation>
+<translation id="2759744352195237655">زر بقائمة منبثقة</translation>
<translation id="2761667185364618470">الرجاء تحديد هذا المربع إذا أردت المتابعة.</translation>
<translation id="2846343701378493991">1024 (درجة متوسطة)</translation>
+<translation id="2896972712917208084">مجموعة أزرار الاختيار</translation>
<translation id="2901282870647571346">حالة الفيلم الحالية</translation>
<translation id="2908441821576996758">الرجاء إدخال قائمة مفصولة بفواصل لعناوين البريد الإلكتروني.</translation>
+<translation id="2931838996092594335">النقر</translation>
+<translation id="2940813599313844715">كائن</translation>
<translation id="2942448076852699108">المحتوى المميز</translation>
<translation id="3040011195152428237">رابط</translation>
<translation id="3075154866155599887">يرجى إدخال قيمة صالحة. الحقل غير مكتمل أو أن التاريخ غير صالح.</translation>
+<translation id="3078740164268491126">جدول</translation>
+<translation id="3086746722712840547">note</translation>
<translation id="310520048233152454">‏الرجاء إدخال عنوان URL.</translation>
+<translation id="3175736971608411871">الموقّت</translation>
+<translation id="3199563858620722075">مربع تحرير وسرد</translation>
<translation id="3450233048674729344">يجب أن تكون القيمة أقل من أو تساوي <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">تعريف</translation>
+<translation id="3557673793733683882">عنوان <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">عدد الثواني المتبقية من الفيلم</translation>
<translation id="3706100364254443312">تبديل</translation>
<translation id="3732799496749320381">شهر</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">عبارة</translation>
<translation id="3822383571486410024">يُرجى إطالة هذا النص إلى <ph name="MIN_CHARACTERS" /> من الحروف أو أكثر (أنت تستخدم حاليًا <ph name="CURRENT_LENGTH" /> من الحروف).</translation>
<translation id="383465348367842624">الجزء المتبوع بالعلامة "<ph name="ATSIGN" />" يجب ألا يشتمل على الرمز "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3924558731517983934">التطبيق</translation>
+<translation id="3960700977367013758">شريط التمرير</translation>
<translation id="4103419683916926126">مللي ثانية</translation>
+<translation id="4151657705144244502">الرسم</translation>
<translation id="4201051445878709314">عرض الشهر السابق</translation>
<translation id="4202807286478387388">الدخول</translation>
+<translation id="421884353938374759">علبة الألوان</translation>
+<translation id="4248100235867064564">شريط قوائم</translation>
+<translation id="4254339807215791271">معلومات المحتوى</translation>
<translation id="4360991593054037559">يُرجى إدخال قيمة صالحة. علمًا بأن القيم الصالحة تتراوح بين <ph name="VALID_VALUE_LOW" /> و<ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">زر القائمة</translation>
<translation id="4522570452068850558">التفاصيل</translation>
<translation id="4597532268155981612">نموذج</translation>
+<translation id="4661075872484491155">متفرع</translation>
<translation id="4664250907885839816">يجب ألا يشتمل الجزء الذي يلي العلامة "<ph name="ATSIGN" />" على الرمز "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4757246831282535685">لوحة علامة التبويب</translation>
<translation id="4763480195061959176">فيديو</translation>
+<translation id="479989351350248267">بحث</translation>
<translation id="4812940957355064477">الرجاء إدخال عدد.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> محددة</translation>
<translation id="49969490063480558">يُرجى إدخال الجزء الذي يلي العلامة "<ph name="ATSIGN" />"، حيث إن "<ph name="INVALIDADDRESS" />" غير مكتمل.</translation>
+<translation id="5034860022980953847">مؤشر التقدم</translation>
<translation id="5048533449481078685">محدّد القائمة</translation>
<translation id="5117590920725113268">عرض الشهر التالي</translation>
+<translation id="512758898067543763">عنوان الصف</translation>
<translation id="5164977714490026579">يجب أن تكون القيمة أكبر من أو تساوي <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">يُرجى إدخال جزء متبوع بعلامة "<ph name="ATSIGN" />"، حيث إن "<ph name="INVALIDADDRESS" />" غير مكتمل.</translation>
+<translation id="5317780077021120954">حفظ</translation>
<translation id="5406322316791861025">شكل</translation>
+<translation id="5453733299334684579">عنصر متفرع</translation>
<translation id="5466621249238537318">الرجاء تحديد ملف واحد أو أكثر.</translation>
<translation id="5468998798572797635">إنهاء وضع ملء الشاشة</translation>
<translation id="5476505524087279545">إزالة علامة الاختيار</translation>
+<translation id="5516424706154626233">منتقي التاريخ</translation>
<translation id="5546461542133609677">إعادة الصوت</translation>
+<translation id="561939826962581046">الوقت</translation>
<translation id="5641012560118721995">إيقاف التشغيل مؤقتًا</translation>
+<translation id="5643186887447432888">زر</translation>
<translation id="5843503607508392247">آخر...</translation>
<translation id="5939518447894949180">إعادة</translation>
<translation id="5944544982112848342">2048 (درجة عالية)</translation>
<translation id="5966707198760109579">الأسبوع</translation>
-<translation id="598301471034819706">عنوان</translation>
+<translation id="5987525920412732405">زر الدوران</translation>
<translation id="6015796118275082299">عام</translation>
+<translation id="6023896073578205740">مربع القائمة</translation>
<translation id="6101327004457443354">إعادة صوت المقطع الصوتي</translation>
<translation id="6119846243427417423">تنشيط</translation>
+<translation id="6164829606128959761">متر</translation>
<translation id="6270583010843788609">صورة مصغرة للتسلسل الزمني للفيلم</translation>
<translation id="6359256949422175976">صورة مصغرة لشريط تمرير وقت الفيلم</translation>
<translation id="6398862346408813489">عرض لوحة تحديد الشهر</translation>
<translation id="6404546809543547843">شريط تمرير وقت الصوت</translation>
+<translation id="648732519525291180">منتقي الوقت</translation>
<translation id="658823671542763450">تشغيل وضع ملء الشاشة</translation>
+<translation id="6637586476836377253">log</translation>
<translation id="6643016212128521049">محو</translation>
<translation id="6663448176199120256">آخر عمليات البحث</translation>
<translation id="668171684555832681">ملف تعريف آخر...</translation>
<translation id="6692633176391053278">تخطي</translation>
+<translation id="6739588121953935928">مسطرة</translation>
+<translation id="6755330956360078551">تلميح</translation>
<translation id="6820355525329141109">تعذر تحميل المكوّن الإضافي.</translation>
<translation id="6843725295806269523">كتم الصوت</translation>
<translation id="6845533974506654842">اضغط</translation>
<translation id="6853785296079745596">إخفاء التسميات التوضيحية المغلقة</translation>
+<translation id="6885760532393684712">الدليل</translation>
+<translation id="6934078000481955284">علامة اقتباس فقرة</translation>
<translation id="7057186640035488495">وقت الفيلم</translation>
<translation id="709897737746224366">الرجاء مطابقة التنسيق المطلوب.</translation>
<translation id="7223624360433298498">المدة المنقضية</translation>
<translation id="7263440858009898357">الرجاء تحديد عنصر من القائمة.</translation>
+<translation id="727747134524199931">عنوان العمود</translation>
<translation id="7364796246159120393">اختيار ملفّ</translation>
<translation id="739024184232394898">آخر...</translation>
+<translation id="7491962110804786152">علامة تبويب</translation>
<translation id="7673697353781729403">ساعات</translation>
<translation id="7720026100085573005">المدة المتبقية</translation>
<translation id="7740016676195725605">إيقاف عرض التسميات التوضيحية المغلقة</translation>
<translation id="7740050170769002709">‏محتوى HTML</translation>
<translation id="7789962463072032349">إيقاف مؤقت</translation>
+<translation id="7802800022689234070">مثلث الإفصاح</translation>
<translation id="7888071071722539607">يُرجى تضمين العلامة "<ph name="ATSIGN" />" في عنوان البريد الإلكتروني، حيث يفتقر "<ph name="INVALIDADDRESS" />" إلى العلامة "<ph name="ATSIGN" />".</translation>
+<translation id="7891486169920085145">أداة التقسيم</translation>
<translation id="795667975304826397">ّلم يتمّ اختيار أيّ ملفّ</translation>
<translation id="8053789581856978548">الحقل النصي للبحث</translation>
<translation id="8115662671911883373">بدء عرض التسميات التوضيحية المغلقة</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">مخطّط صورة</translation>
<translation id="835897206747267392">قيمة غير صحيحة</translation>
<translation id="838869780401515933">الاختيار</translation>
+<translation id="8433900881053900389">شريط الأدوات</translation>
<translation id="8444882422881193423">عدد الملفات: <ph name="NUMBER_OF_FILES" /></translation>
<translation id="8451268428117625855">الرجاء تحديد ملف.</translation>
+<translation id="8461852803063341183">زر الاختيار</translation>
+<translation id="8511325616783751178">زر القائمة المنسدلة</translation>
<translation id="8534579021159131403">دقائق</translation>
<translation id="8541249477527128034">التحكم في الوسائط</translation>
<translation id="8583702881314752957">قائمة تعريف</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">بدء التشغيل</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8987927404178983737">شهر</translation>
+<translation id="9002566407876343676">الفتح</translation>
<translation id="901493112792887934">المدة الحالية بالثواني</translation>
<translation id="9048119486235211610">تنقل</translation>
<translation id="9050748414552849310">عرض التسميات التوضيحية المغلقة</translation>
+<translation id="9062295712474918030">المستند</translation>
<translation id="9108370397979208512">math</translation>
<translation id="9132465097189459683">آخر...</translation>
+<translation id="9138385573473225930">تنبيه</translation>
<translation id="9155987714137265666"><ph name="WEEK" />، ابتداء من <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">خلية</translation>
+<translation id="966787709310836684">القائمة</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_bg.xtb b/chromium/content/app/strings/translations/content_strings_bg.xtb
index 986322a788f..aea4837571b 100644
--- a/chromium/content/app/strings/translations/content_strings_bg.xtb
+++ b/chromium/content/app/strings/translations/content_strings_bg.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="bg">
<translation id="1014825444426747588">празно</translation>
+<translation id="1018939186200882850">елемент от меню</translation>
<translation id="1020833440720551630">заглушаване на аудиозаписа</translation>
<translation id="10623998915015855">бутон за превключване</translation>
<translation id="1088086359088493902">Секунди</translation>
<translation id="1171774979989969504">Моля, въведете имейл адрес.</translation>
<translation id="1188858454923323853">допълнение</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">плъзгач</translation>
<translation id="1235745349614807883">Изчистване на скорошните търсения</translation>
+<translation id="1281252709823657822">диалогов прозорец</translation>
<translation id="1342835525016946179">статия</translation>
<translation id="1359897965706325498">банер</translation>
<translation id="1589122976691792535">регион</translation>
<translation id="1591562245178063882">Този месец</translation>
<translation id="1637811476055996098">Избор на файлове</translation>
+<translation id="167575180612809735">индикатор за заетост</translation>
<translation id="1729654308190250600">Моля, въведете имейл адрес.</translation>
<translation id="1758486001363313524">Други...</translation>
+<translation id="1806710327868736751">диалогов прозорец със сигнал</translation>
+<translation id="1821985195704844674">дървовидна таблица</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">възпроизвеждане на отдалечено устройство</translation>
<translation id="1842960171412779397">Избиране</translation>
+<translation id="1880518467580572141">структура</translation>
<translation id="1921819250265091946">дд</translation>
<translation id="1930711995431081526">състояние</translation>
<translation id="1938124657309484470">Стойността трябва да е <ph name="MAXIMUM_DATE_OR_TIME" /> или по-рано.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Моля, съкратете този текст до <ph name="MAX_CHARACTERS" /> знака или по-малко (понастоящем използвате <ph name="CURRENT_LENGTH" /> знака).</translation>
<translation id="2247351761944213033">Седмица <ph name="WEEKNUMBER" />, <ph name="YEAR" /> г.</translation>
<translation id="2291999235780842123">квадратче за отметка</translation>
+<translation id="2335594187091864976">инструмент за избор на дата и час</translation>
<translation id="248395913932153421">Ден</translation>
<translation id="2507943997699731163">Моля, попълнете това поле.</translation>
+<translation id="2508569020611168319">списък с раздели</translation>
<translation id="2548326553472216322">Няма скорошни търсения</translation>
<translation id="2572483411312390101">пускане</translation>
<translation id="2613802280814924224">Моля, въведете валидна стойност. Най-близката такава е <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">долен колонтитул</translation>
<translation id="2723001399770238859">звук</translation>
<translation id="2746543609216772311">Стойността трябва да е <ph name="MINIMUM_DATE_OR_TIME" /> или по-късно.</translation>
+<translation id="2759744352195237655">бутон с изскачащ прозорец</translation>
<translation id="2761667185364618470">Моля, поставете отметка в това квадратче, ако искате да продължите.</translation>
<translation id="2846343701378493991">1024 (средна степен на сложност)</translation>
+<translation id="2896972712917208084">група бутони за избор</translation>
<translation id="2901282870647571346">текущо състояние на филма</translation>
<translation id="2908441821576996758">Моля, въведете списък с имейл адреси, разделени със запетаи.</translation>
+<translation id="2931838996092594335">кликвам</translation>
+<translation id="2940813599313844715">обект</translation>
<translation id="2942448076852699108">откроено съдържание</translation>
<translation id="3040011195152428237">връзка</translation>
<translation id="3075154866155599887">Моля, въведете валидна стойност. Данните в полето са непълни или датата е невалидна.</translation>
+<translation id="3078740164268491126">таблица</translation>
+<translation id="3086746722712840547">забележка</translation>
<translation id="310520048233152454">Моля, въведете URL адрес.</translation>
+<translation id="3175736971608411871">таймер</translation>
+<translation id="3199563858620722075">разгъващ се списък</translation>
<translation id="3450233048674729344">Стойността трябва да е по-малка или равна на <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">дефиниция</translation>
+<translation id="3557673793733683882">заглавие от ниво <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">брой оставащи секунди от филма</translation>
<translation id="3706100364254443312">превключвател</translation>
<translation id="3732799496749320381">мм</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">термин</translation>
<translation id="3822383571486410024">Моля, удължете този текст поне до <ph name="MIN_CHARACTERS" /> знака (понастоящем използвате <ph name="CURRENT_LENGTH" />).</translation>
<translation id="383465348367842624">Текстът преди „<ph name="ATSIGN" />“ не бива да съдържа символа „<ph name="INVALIDCHARACTER" />“.</translation>
+<translation id="3924558731517983934">приложение</translation>
+<translation id="3960700977367013758">лента за превъртане</translation>
<translation id="4103419683916926126">Милисекунди</translation>
+<translation id="4151657705144244502">графика</translation>
<translation id="4201051445878709314">Показване на предишния месец</translation>
<translation id="4202807286478387388">преминаване</translation>
+<translation id="421884353938374759">инструмент за избор на цветове</translation>
+<translation id="4248100235867064564">лента с менюта</translation>
+<translation id="4254339807215791271">информация за съдържанието</translation>
<translation id="4360991593054037559">Моля, въведете валидна стойност. Двете най-близки такива са <ph name="VALID_VALUE_LOW" /> и <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">бутон за меню</translation>
<translation id="4522570452068850558">Подробности</translation>
<translation id="4597532268155981612">формуляр</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Текстът след „<ph name="ATSIGN" />“ не бива да съдържа символа „<ph name="INVALIDCHARACTER" />“.</translation>
+<translation id="4757246831282535685">панел с раздели</translation>
<translation id="4763480195061959176">видео</translation>
+<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Моля, въведете номер.</translation>
<translation id="4975562563186953947">Избрани: <ph name="SELECTED_COUNT" /></translation>
<translation id="49969490063480558">Моля, въведете текст след „<ph name="ATSIGN" />“. „<ph name="INVALIDADDRESS" />“ е непълно.</translation>
+<translation id="5034860022980953847">индикатор за напредък</translation>
<translation id="5048533449481078685">списъчен показалец</translation>
<translation id="5117590920725113268">Показване на следващия месец</translation>
+<translation id="512758898067543763">заглавка на ред</translation>
<translation id="5164977714490026579">Стойността трябва да е по-голяма или равна на <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Моля, въведете текст преди „<ph name="ATSIGN" />“. „<ph name="INVALIDADDRESS" />“ е непълно.</translation>
+<translation id="5317780077021120954">Запазване</translation>
<translation id="5406322316791861025">фигура</translation>
+<translation id="5453733299334684579">елемент от дърво</translation>
<translation id="5466621249238537318">Моля, изберете един или повече файлове.</translation>
<translation id="5468998798572797635">изход от цял екран</translation>
<translation id="5476505524087279545">премахване на отметката</translation>
+<translation id="5516424706154626233">инструмент за избор на дата</translation>
<translation id="5546461542133609677">пускане на звука</translation>
+<translation id="561939826962581046">time</translation>
<translation id="5641012560118721995">поставяне на възпроизвеждането на пауза</translation>
+<translation id="5643186887447432888">бутон</translation>
<translation id="5843503607508392247">Други...</translation>
<translation id="5939518447894949180">Нулиране</translation>
<translation id="5944544982112848342">2048 (висока степен на сложност)</translation>
<translation id="5966707198760109579">Седмица</translation>
-<translation id="598301471034819706">адрес</translation>
+<translation id="5987525920412732405">брояч</translation>
<translation id="6015796118275082299">Година</translation>
+<translation id="6023896073578205740">списъчно поле</translation>
<translation id="6101327004457443354">пускане на аудиозаписа</translation>
<translation id="6119846243427417423">активиране</translation>
+<translation id="6164829606128959761">индикатор</translation>
<translation id="6270583010843788609">миниизображение за времевата контрола за филма</translation>
<translation id="6359256949422175976">миниизображение за времевия плъзгач за филма</translation>
<translation id="6398862346408813489">Показване на панела за избиране на месец</translation>
<translation id="6404546809543547843">времеви плъзгач за аудиозаписа</translation>
+<translation id="648732519525291180">инструмент за избор на час</translation>
<translation id="658823671542763450">вход за цял екран</translation>
+<translation id="6637586476836377253">регистрационен файл</translation>
<translation id="6643016212128521049">Изчистване</translation>
<translation id="6663448176199120256">Скорошни търсения</translation>
<translation id="668171684555832681">Друг...</translation>
<translation id="6692633176391053278">stepper</translation>
+<translation id="6739588121953935928">линия</translation>
+<translation id="6755330956360078551">подсказка</translation>
<translation id="6820355525329141109">Приставката не можа да се зареди.</translation>
<translation id="6843725295806269523">заглушаване</translation>
<translation id="6845533974506654842">натискане</translation>
<translation id="6853785296079745596">скриване на надписите</translation>
+<translation id="6885760532393684712">директория</translation>
+<translation id="6934078000481955284">блоков цитат</translation>
<translation id="7057186640035488495">време от филма</translation>
<translation id="709897737746224366">Моля, спазвайте изисквания формат.</translation>
<translation id="7223624360433298498">изминало време</translation>
<translation id="7263440858009898357">Моля, изберете елемент в списъка.</translation>
+<translation id="727747134524199931">заглавка на колона</translation>
<translation id="7364796246159120393">Избор на файл</translation>
<translation id="739024184232394898">Други...</translation>
+<translation id="7491962110804786152">раздел</translation>
<translation id="7673697353781729403">Часове</translation>
<translation id="7720026100085573005">оставащо време</translation>
<translation id="7740016676195725605">спиране на показването на надписите</translation>
<translation id="7740050170769002709">HTML съдържание</translation>
<translation id="7789962463072032349">поставяне на пауза</translation>
+<translation id="7802800022689234070">триъгълник за разкриване на съдържание</translation>
<translation id="7888071071722539607">Моля, включете „<ph name="ATSIGN" />“ в имейл адреса. В/ъв „<ph name="INVALIDADDRESS" />“ липсва „<ph name="ATSIGN" />“.</translation>
+<translation id="7891486169920085145">разделител</translation>
<translation id="795667975304826397">Няма избран файл</translation>
<translation id="8053789581856978548">текстово поле за търсене</translation>
<translation id="8115662671911883373">започване на показването на надписите</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">карта с изображения</translation>
<translation id="835897206747267392">Невалидна стойност.</translation>
<translation id="838869780401515933">отмятане</translation>
+<translation id="8433900881053900389">лента с инструменти</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> файла</translation>
<translation id="8451268428117625855">Моля, изберете файл.</translation>
+<translation id="8461852803063341183">бутон за избор</translation>
+<translation id="8511325616783751178">бутон за падащо меню</translation>
<translation id="8534579021159131403">Минути</translation>
<translation id="8541249477527128034">медийна контрола</translation>
<translation id="8583702881314752957">списък с дефиниции</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">начало на възпроизвеждането</translation>
<translation id="8851136666856101339">основен елемент</translation>
<translation id="8987927404178983737">Месец</translation>
+<translation id="9002566407876343676">отварям</translation>
<translation id="901493112792887934">текущо време в секунди</translation>
<translation id="9048119486235211610">навигация</translation>
<translation id="9050748414552849310">показване на надписите</translation>
+<translation id="9062295712474918030">документ</translation>
<translation id="9108370397979208512">математически израз</translation>
<translation id="9132465097189459683">Други...</translation>
+<translation id="9138385573473225930">сигнал</translation>
<translation id="9155987714137265666"><ph name="WEEK" /> – започва от <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">клетка</translation>
+<translation id="966787709310836684">меню</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_bn.xtb b/chromium/content/app/strings/translations/content_strings_bn.xtb
index 122e1a7e18b..15921b2a576 100644
--- a/chromium/content/app/strings/translations/content_strings_bn.xtb
+++ b/chromium/content/app/strings/translations/content_strings_bn.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="bn">
<translation id="1014825444426747588">খালি</translation>
+<translation id="1018939186200882850">মেনু আইটেম</translation>
<translation id="1020833440720551630">অডিও ট্র্যাক নিঃশব্দ করুন</translation>
<translation id="10623998915015855">টগল বোতাম</translation>
<translation id="1088086359088493902">সেকেন্ড</translation>
<translation id="1171774979989969504">দয়া করে কোন ইমেল ঠিকানা প্রবেশ করান:</translation>
<translation id="1188858454923323853">পরিপূরক</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">স্লাইডার</translation>
<translation id="1235745349614807883">সাম্প্রতিক অনুসন্ধানগুলি সাফ করুন</translation>
+<translation id="1281252709823657822">ডায়ালগ</translation>
<translation id="1342835525016946179">নিবন্ধ</translation>
<translation id="1359897965706325498">ব্যানার</translation>
<translation id="1589122976691792535">অঞ্চল</translation>
<translation id="1591562245178063882">এই মাস</translation>
<translation id="1637811476055996098">ফাইল চয়ন করুন</translation>
+<translation id="167575180612809735">ব্যস্ততার সূচক</translation>
<translation id="1729654308190250600">দয়া করে একটি খালি না থাকা ইমেল ঠিকানা লিখুন৷</translation>
<translation id="1758486001363313524">অন্যান্য...</translation>
+<translation id="1806710327868736751">সতর্কতার_ডায়ালগ</translation>
+<translation id="1821985195704844674">ট্রি গ্রিড</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">রিমোট ডিভাইসে প্লে করুন</translation>
<translation id="1842960171412779397">নির্বাচন করুন</translation>
+<translation id="1880518467580572141">রূপরেখা</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">স্থিতি</translation>
<translation id="1938124657309484470">মানকে অবশ্যই <ph name="MAXIMUM_DATE_OR_TIME" /> বা আগের হতে হবে৷</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">দয়া করে এই পাঠ্যটি <ph name="MAX_CHARACTERS" />টি অক্ষর বা তার কমে (আপনি বর্তমানে <ph name="CURRENT_LENGTH" />টি অক্ষর ব্যবহার করছেন) সংক্ষিপ্ত করুন৷</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" /> সপ্তাহ, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">চেকবাক্স</translation>
+<translation id="2335594187091864976">তারিখ এবং সময় চয়নকারি</translation>
<translation id="248395913932153421">দিন</translation>
<translation id="2507943997699731163">দয়া করে এই ক্ষেত্রটি পূরণ করুন৷</translation>
+<translation id="2508569020611168319">ট্যাব তালিকা</translation>
<translation id="2548326553472216322">কোন সাম্প্রতিক অনুসন্ধান নেই</translation>
<translation id="2572483411312390101">চালনা করুন</translation>
<translation id="2613802280814924224">দয়া করে একটি বৈধ মান লিখুন৷ কাছাকাছির বৈধ মান হল <ph name="VALID_VALUE" />৷</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">পাদলেখ</translation>
<translation id="2723001399770238859">অডিও</translation>
<translation id="2746543609216772311">মানকে অবশ্যই <ph name="MINIMUM_DATE_OR_TIME" /> বা পরবর্তী হতে হবে৷</translation>
+<translation id="2759744352195237655">পপ আপ বোতাম</translation>
<translation id="2761667185364618470">আপনি যদি এগিয়ে যেতে চান তবে দয়া করে এই বাক্সটি পরীক্ষা করুন৷</translation>
<translation id="2846343701378493991">1024 (মধ্যম গ্রেড)</translation>
+<translation id="2896972712917208084">রেডিও বোতাম গোষ্ঠী</translation>
<translation id="2901282870647571346">চলচ্চিত্রের বর্তমান অবস্থা</translation>
<translation id="2908441821576996758">দয়া করে ইমেল ঠিকানাগুলির একটি কমা দিয়ে আলাদা করা মান প্রবেশ করান৷</translation>
+<translation id="2931838996092594335">ক্লিক করুন</translation>
+<translation id="2940813599313844715">অবজেক্ট</translation>
<translation id="2942448076852699108">হাইলাইট করা সামগ্রী</translation>
<translation id="3040011195152428237">লিঙ্ক</translation>
<translation id="3075154866155599887">দয়া করে একটি বৈধ মান লিখুন৷ ক্ষেত্রটি অসম্পূর্ণ অথবা একটি অবৈধ তারিখ আছে৷</translation>
+<translation id="3078740164268491126">সারণী</translation>
+<translation id="3086746722712840547">দ্রষ্টব্য</translation>
<translation id="310520048233152454">দয়া করে একটি বৈধ URL প্রবেশ করুন৷</translation>
+<translation id="3175736971608411871">টাইমার</translation>
+<translation id="3199563858620722075">কম্বো বাক্স</translation>
<translation id="3450233048674729344">মানটি অবশ্যই <ph name="MAXIMUM" />এর চেয়ে কম বা সমান হবে৷</translation>
<translation id="3486220673238053218">সংজ্ঞা</translation>
+<translation id="3557673793733683882">শিরোনাম <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">চলচ্চিত্রের অবশিষ্ট সেকেন্ড</translation>
<translation id="3706100364254443312">পরিবর্তন করুন</translation>
<translation id="3732799496749320381">মিমি</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">পদ</translation>
<translation id="3822383571486410024">দয়া করে এই পাঠ্যকে ন্যূনতম <ph name="MIN_CHARACTERS" /> অক্ষরের বা তার বেশি (আপনি বর্তমানে <ph name="CURRENT_LENGTH" />টি অক্ষর ব্যবহার করেছেন) দৈর্ঘের করুন।</translation>
<translation id="383465348367842624">'<ph name="ATSIGN" />' অনুসরণ করে এমন একটি অংশে '<ph name="INVALIDCHARACTER" />' চিহ্ন থাকা উচিত নয়৷</translation>
+<translation id="3924558731517983934">অ্যাপ্লিকেশান</translation>
+<translation id="3960700977367013758">স্ক্রোল বার</translation>
<translation id="4103419683916926126">মিলিসেকেন্ড</translation>
+<translation id="4151657705144244502">গ্রাফিক</translation>
<translation id="4201051445878709314">পূর্ববর্তী মাস দেখান</translation>
<translation id="4202807286478387388">লাফ দিন</translation>
+<translation id="421884353938374759">রঙ চয়নকারী</translation>
+<translation id="4248100235867064564">মেনু বার</translation>
+<translation id="4254339807215791271">সামগ্রীর তথ্য</translation>
<translation id="4360991593054037559">দয়া করে একটি বৈধ মান লিখুন৷ দুটি কাছাকাছির বৈধ মান হল <ph name="VALID_VALUE_LOW" /> এবং <ph name="VALID_VALUE_HIGHER" />৷</translation>
+<translation id="4413860115965805769">মেনু বোতাম</translation>
<translation id="4522570452068850558">বিশদ বিবরণ</translation>
<translation id="4597532268155981612">ফর্ম</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' অনুসরণ করে এমন একটি অংশে '<ph name="INVALIDCHARACTER" />' চিহ্ন থাকা উচিত নয়৷</translation>
+<translation id="4757246831282535685">ট্যাব প্যানেল</translation>
<translation id="4763480195061959176">ভিডিও</translation>
+<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">দয়া করে একটি সংখ্যা লিখুন৷</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" />টি নির্বাচিত</translation>
<translation id="49969490063480558">দয়া করে '<ph name="ATSIGN" />' অনুসরণ করে একটি অংশ লিখুন৷ '<ph name="INVALIDADDRESS" />' অসম্পূর্ণ৷</translation>
+<translation id="5034860022980953847">অগ্রগতি সূচক</translation>
<translation id="5048533449481078685">তালিকা নির্দেশক</translation>
<translation id="5117590920725113268">পরবর্তী মাস দেখান</translation>
+<translation id="512758898067543763">সারি শিরোলেখ</translation>
<translation id="5164977714490026579">মানটি অবশ্যই <ph name="MINIMUM" />এর চেয়ে বেশি বা সমান হবে৷</translation>
<translation id="5307600278924710095">'<ph name="ATSIGN" />' অনুসরণ করে একটি অংশ লিখুন৷ '<ph name="INVALIDADDRESS" />' অসম্পূর্ণ৷</translation>
+<translation id="5317780077021120954">সংরক্ষণ করুন</translation>
<translation id="5406322316791861025">আকার</translation>
+<translation id="5453733299334684579">ট্রি আইটেম</translation>
<translation id="5466621249238537318">দয়া করে এক বা একাধিক ফাইল নির্বাচন করুন৷</translation>
<translation id="5468998798572797635">পূর্ণ স্ক্রীন বন্ধ করুন</translation>
<translation id="5476505524087279545">আনচেক</translation>
+<translation id="5516424706154626233">তারিখ চয়নকারি</translation>
<translation id="5546461542133609677">সশব্দ</translation>
+<translation id="561939826962581046">time</translation>
<translation id="5641012560118721995">প্লেব্যাক বিরতি</translation>
+<translation id="5643186887447432888">বোতাম</translation>
<translation id="5843503607508392247">অন্যান্য...</translation>
<translation id="5939518447894949180">রিসেট করুন</translation>
<translation id="5944544982112848342">2048 (উচ্চ গ্রেড)</translation>
<translation id="5966707198760109579">সপ্তাহ</translation>
-<translation id="598301471034819706">ঠিকানা</translation>
+<translation id="5987525920412732405">ঘোড়ানোর বোতাম</translation>
<translation id="6015796118275082299">বছর</translation>
+<translation id="6023896073578205740">তালিকা বাক্স</translation>
<translation id="6101327004457443354">অডিও ট্র্যাক সশব্দ করুন</translation>
<translation id="6119846243427417423">সক্রিয় করুন</translation>
+<translation id="6164829606128959761">মিটার</translation>
<translation id="6270583010843788609">চলচ্চিত্র টাইমলাইন থাম্ব</translation>
<translation id="6359256949422175976">চলচ্চিত্রের সময় স্ক্রাবার থাম্ব</translation>
<translation id="6398862346408813489">মাস নির্বাচনের প্যানেল দেখান</translation>
<translation id="6404546809543547843">অডিও সময় স্ক্রাবার</translation>
+<translation id="648732519525291180">সময় চয়নকারি</translation>
<translation id="658823671542763450">পূর্ণ স্ক্রীনে প্রবেশ করুন</translation>
+<translation id="6637586476836377253">লগ</translation>
<translation id="6643016212128521049">সাফ করুন</translation>
<translation id="6663448176199120256">সাম্প্রতিক অনুসন্ধানগুলি</translation>
<translation id="668171684555832681">অন্যান্য...</translation>
<translation id="6692633176391053278">পদক্ষেপকারী</translation>
+<translation id="6739588121953935928">রুলার</translation>
+<translation id="6755330956360078551">সরঞ্জামটিপ</translation>
<translation id="6820355525329141109">প্লাগ ইন লোড করা যায়নি।</translation>
<translation id="6843725295806269523">নিঃশব্দ</translation>
<translation id="6845533974506654842">টিপুন</translation>
<translation id="6853785296079745596">বন্ধ করা পরিচয়লিপিগুলি লুকান</translation>
+<translation id="6885760532393684712">ডিরেক্টরি</translation>
+<translation id="6934078000481955284">ব্লক উদ্ধৃতি</translation>
<translation id="7057186640035488495">চলচ্চিত্রের সময়</translation>
<translation id="709897737746224366">দয়া করে অনুরোধ হওয়া বিন্যাসটি মেলান৷</translation>
<translation id="7223624360433298498">অতিবাহিত সময়</translation>
<translation id="7263440858009898357">তালিকা থেকে একটি আইটেম নির্বাচন করুন৷ </translation>
+<translation id="727747134524199931">কলাম শিরোলেখ</translation>
<translation id="7364796246159120393">ফাইল চয়ন করুন</translation>
<translation id="739024184232394898">অন্যান্য...</translation>
-<translation id="7673697353781729403">ঘন্টা</translation>
+<translation id="7491962110804786152">ট্যাব</translation>
+<translation id="7673697353781729403">ঘণ্টা</translation>
<translation id="7720026100085573005">অবশিষ্ট সময়</translation>
<translation id="7740016676195725605">বদ্ধ পরিচয়লিপিগুলির প্রদর্শন থামান</translation>
<translation id="7740050170769002709">HTML সামগ্রী</translation>
<translation id="7789962463072032349">বিরাম</translation>
+<translation id="7802800022689234070">উম্মোচন ত্রিভুজ</translation>
<translation id="7888071071722539607">ইমেল ঠিনাকাটিতে দয়া করে একটি '<ph name="ATSIGN" />' অন্তর্ভুক্ত করুন৷ '<ph name="INVALIDADDRESS" />' এ একটি '<ph name="ATSIGN" />' অনুপস্থিত৷</translation>
+<translation id="7891486169920085145">স্প্লিটার</translation>
<translation id="795667975304826397">কোনও ফাইল চয়ন করা হয় নি</translation>
<translation id="8053789581856978548">অনুসন্ধান পাঠ্য ফিল্ড</translation>
<translation id="8115662671911883373">বন্ধ পরিচয়লিপিগুলির প্রদর্শন শুরু করুন</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">ছবি মানচিত্র</translation>
<translation id="835897206747267392">অকার্যকর মান৷</translation>
<translation id="838869780401515933">চেক করুন</translation>
+<translation id="8433900881053900389">সরঞ্জাম দণ্ড</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> টি ফাইল</translation>
<translation id="8451268428117625855">দয়া করে একটি ফাইল নির্বাচন করুন৷</translation>
+<translation id="8461852803063341183">রেডিও বোতাম</translation>
+<translation id="8511325616783751178">ড্রপ ডাউন বোতাম</translation>
<translation id="8534579021159131403">মিনিট</translation>
<translation id="8541249477527128034">মিডিয়া নিয়ন্ত্রণ</translation>
<translation id="8583702881314752957">সংজ্ঞার তালিকা</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">প্লেব্যাক শুরু করুন</translation>
<translation id="8851136666856101339">প্রধান</translation>
<translation id="8987927404178983737">মাস</translation>
+<translation id="9002566407876343676">খুলুন</translation>
<translation id="901493112792887934">সেকেন্ডে বর্তমান সময়</translation>
<translation id="9048119486235211610">নেভিগেশন</translation>
<translation id="9050748414552849310">বন্ধ করা পরিচয়লিপিগুলি দেখান</translation>
+<translation id="9062295712474918030">দস্তাবেজ</translation>
<translation id="9108370397979208512">গণিত</translation>
<translation id="9132465097189459683">অন্যান্য...</translation>
+<translation id="9138385573473225930">সতর্কতা</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, <ph name="WEEK_START_DATE" /> এ শুরু</translation>
+<translation id="947831847158436616">কক্ষ</translation>
+<translation id="966787709310836684">মেনু</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ca.xtb b/chromium/content/app/strings/translations/content_strings_ca.xtb
index c2d8803d0ae..151fd19cf01 100644
--- a/chromium/content/app/strings/translations/content_strings_ca.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ca.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="ca">
<translation id="1014825444426747588">buit</translation>
+<translation id="1018939186200882850">element del menú</translation>
<translation id="1020833440720551630">silencia la pista d'àudio</translation>
<translation id="10623998915015855">botó de commutació</translation>
<translation id="1088086359088493902">Segons</translation>
<translation id="1171774979989969504">Introduïu una adreça electrònica.</translation>
<translation id="1188858454923323853">complementari</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">control lliscant</translation>
<translation id="1235745349614807883">Esborra les cerques recents</translation>
+<translation id="1281252709823657822">quadre de diàleg</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">bàner</translation>
<translation id="1589122976691792535">regió</translation>
<translation id="1591562245178063882">Aquest mes</translation>
<translation id="1637811476055996098">Trieu els fitxers</translation>
+<translation id="167575180612809735">indicador d'ocupat</translation>
<translation id="1729654308190250600">Introduïu una adreça electrònica.</translation>
<translation id="1758486001363313524">Altres...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">quadrícula d'arbre</translation>
<translation id="1822429046913737220">a. m./p. m.</translation>
<translation id="1832974991323546415">reprodueix al dispositiu remot</translation>
<translation id="1842960171412779397">selecciona</translation>
+<translation id="1880518467580572141">esquema</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">estat</translation>
<translation id="1938124657309484470">El valor ha de ser <ph name="MAXIMUM_DATE_OR_TIME" /> o anterior.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Escurceu aquest text a un màxim de <ph name="MAX_CHARACTERS" /> caràcters (ara n'esteu utilitzant <ph name="CURRENT_LENGTH" />).</translation>
<translation id="2247351761944213033">Setmana <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">casella de selecció</translation>
+<translation id="2335594187091864976">selector de data i hora</translation>
<translation id="248395913932153421">Dia</translation>
<translation id="2507943997699731163">Empleneu aquest camp.</translation>
+<translation id="2508569020611168319">llista de pestanyes</translation>
<translation id="2548326553472216322">No hi ha cerques recents</translation>
<translation id="2572483411312390101">reprodueix</translation>
<translation id="2613802280814924224">Introduïu un valor vàlid. El valor vàlid més proper és <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">peu</translation>
<translation id="2723001399770238859">àudio</translation>
<translation id="2746543609216772311">El valor ha de ser <ph name="MINIMUM_DATE_OR_TIME" /> o posterior.</translation>
+<translation id="2759744352195237655">botó emergent</translation>
<translation id="2761667185364618470">Marqueu aquesta casella si voleu continuar.</translation>
<translation id="2846343701378493991">1024 (Mitjà)</translation>
+<translation id="2896972712917208084">grup de botons d'opció</translation>
<translation id="2901282870647571346">estat actual de la pel·lícula</translation>
<translation id="2908441821576996758">Introduïu una llista d'adreces electròniques separades per comes.</translation>
+<translation id="2931838996092594335">fer clic</translation>
+<translation id="2940813599313844715">objecte</translation>
<translation id="2942448076852699108">contingut realçat</translation>
<translation id="3040011195152428237">enllaç</translation>
<translation id="3075154866155599887">Introduïu un valor vàlid. El camp està incomplet o conté una data no vàlida.</translation>
+<translation id="3078740164268491126">taula</translation>
+<translation id="3086746722712840547">nota</translation>
<translation id="310520048233152454">Introduïu un URL.</translation>
+<translation id="3175736971608411871">temporitzador</translation>
+<translation id="3199563858620722075">quadre combinat</translation>
<translation id="3450233048674729344">El valor ha de ser més petit o igual que <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">definició</translation>
+<translation id="3557673793733683882">capçalera <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">nombre de segons restants de la pel·lícula</translation>
<translation id="3706100364254443312">commutador</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">terme</translation>
<translation id="3822383571486410024">Allargueu aquest text fins a un mínim de <ph name="MIN_CHARACTERS" /> caràcters (ara n'utilitzeu <ph name="CURRENT_LENGTH" />).</translation>
<translation id="383465348367842624">Un nom d'usuari seguit de "<ph name="ATSIGN" />" no pot contenir el símbol "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3924558731517983934">aplicació</translation>
+<translation id="3960700977367013758">barra de desplaçament</translation>
<translation id="4103419683916926126">Mil·lisegons</translation>
+<translation id="4151657705144244502">gràfic</translation>
<translation id="4201051445878709314">Mostra el mes anterior</translation>
<translation id="4202807286478387388">salta</translation>
+<translation id="421884353938374759">selector de color</translation>
+<translation id="4248100235867064564">barra de menús</translation>
+<translation id="4254339807215791271">informació sobre el contingut</translation>
<translation id="4360991593054037559">Introduïu un valor vàlid. Els valors vàlids més propers són <ph name="VALID_VALUE_LOW" /> i <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">botó de menú</translation>
<translation id="4522570452068850558">Detalls</translation>
<translation id="4597532268155981612">formulari</translation>
+<translation id="4661075872484491155">arbre</translation>
<translation id="4664250907885839816">Un domini precedit per "<ph name="ATSIGN" />" no pot contenir el símbol "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4757246831282535685">tauler de pestanyes</translation>
<translation id="4763480195061959176">vídeo</translation>
+<translation id="479989351350248267">cerca</translation>
<translation id="4812940957355064477">Introduïu un número.</translation>
<translation id="4975562563186953947">Elements seleccionats: <ph name="SELECTED_COUNT" /></translation>
<translation id="49969490063480558">Introduïu un domini precedit per "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" no és una adreça electrònica completa.</translation>
+<translation id="5034860022980953847">indicador de progrés</translation>
<translation id="5048533449481078685">marcador de llistes</translation>
<translation id="5117590920725113268">Mostra el mes següent</translation>
+<translation id="512758898067543763">capçalera de la fila</translation>
<translation id="5164977714490026579">El valor ha de ser més gran o igual que <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Introduïu un nom d'usuari seguit de "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" no és una adreça completa.</translation>
+<translation id="5317780077021120954">Desa</translation>
<translation id="5406322316791861025">figura</translation>
+<translation id="5453733299334684579">element de l'arbre</translation>
<translation id="5466621249238537318">Seleccioneu un o diversos fitxers.</translation>
<translation id="5468998798572797635">surt de la pantalla completa</translation>
<translation id="5476505524087279545">desmarca</translation>
+<translation id="5516424706154626233">selector de data</translation>
<translation id="5546461542133609677">activa el so</translation>
+<translation id="561939826962581046">time</translation>
<translation id="5641012560118721995">pausa la reproducció</translation>
+<translation id="5643186887447432888">botó</translation>
<translation id="5843503607508392247">Altres...</translation>
<translation id="5939518447894949180">Restableix</translation>
<translation id="5944544982112848342">2048 (Gran)</translation>
<translation id="5966707198760109579">Setmana</translation>
-<translation id="598301471034819706">adreça</translation>
+<translation id="5987525920412732405">botó de selecció de valors</translation>
<translation id="6015796118275082299">Any</translation>
+<translation id="6023896073578205740">quadre de llista</translation>
<translation id="6101327004457443354">activa el so de la pista d'àudio</translation>
<translation id="6119846243427417423">activa</translation>
+<translation id="6164829606128959761">comptador</translation>
<translation id="6270583010843788609">miniatura de cronologia de pel·lícula</translation>
<translation id="6359256949422175976">miniatura de la barra de moment de la pel·lícula</translation>
<translation id="6398862346408813489">Mostra el tauler de la selecció de mes</translation>
<translation id="6404546809543547843">barra de moment de l'àudio</translation>
+<translation id="648732519525291180">selector d'hora</translation>
<translation id="658823671542763450">visualitza en pantalla completa</translation>
+<translation id="6637586476836377253">registre</translation>
<translation id="6643016212128521049">Esborra</translation>
<translation id="6663448176199120256">Cerques recents</translation>
<translation id="668171684555832681">Altres...</translation>
<translation id="6692633176391053278">desplaçador</translation>
+<translation id="6739588121953935928">regle</translation>
+<translation id="6755330956360078551">descripció emergent</translation>
<translation id="6820355525329141109">El connector no s'ha pogut carregar.</translation>
<translation id="6843725295806269523">silencia</translation>
<translation id="6845533974506654842">prem</translation>
<translation id="6853785296079745596">amaga els subtítols ocults</translation>
+<translation id="6885760532393684712">directori</translation>
+<translation id="6934078000481955284">cita en bloc</translation>
<translation id="7057186640035488495">moment de la pel·lícula</translation>
<translation id="709897737746224366">Feu servir el format sol·licitat.</translation>
<translation id="7223624360433298498">temps transcorregut</translation>
<translation id="7263440858009898357">Seleccioneu un element de la llista.</translation>
+<translation id="727747134524199931">capçalera de columna</translation>
<translation id="7364796246159120393">Tria un fitxer</translation>
<translation id="739024184232394898">Altres...</translation>
+<translation id="7491962110804786152">pestanya</translation>
<translation id="7673697353781729403">Hores</translation>
<translation id="7720026100085573005">temps restant</translation>
<translation id="7740016676195725605">deixa de mostrar subtítols ocults</translation>
<translation id="7740050170769002709">Contingut HTML</translation>
<translation id="7789962463072032349">pausa</translation>
+<translation id="7802800022689234070">triangle desplegable</translation>
<translation id="7888071071722539607">Incloeu el símbol "<ph name="ATSIGN" />" a l'adreça electrònica. Al camp "<ph name="INVALIDADDRESS" />" falta el símbol "<ph name="ATSIGN" />".</translation>
+<translation id="7891486169920085145">divisor</translation>
<translation id="795667975304826397">No s'ha triat cap fitxer</translation>
<translation id="8053789581856978548">camp de text de la cerca</translation>
<translation id="8115662671911883373">comença a mostrar subtítols ocults</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">mapa d'imatges</translation>
<translation id="835897206747267392">Valor no vàlid.</translation>
<translation id="838869780401515933">marca</translation>
+<translation id="8433900881053900389">barra d'eines</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> fitxers</translation>
<translation id="8451268428117625855">Seleccioneu un fitxer.</translation>
+<translation id="8461852803063341183">botó d'opció</translation>
+<translation id="8511325616783751178">botó desplegable</translation>
<translation id="8534579021159131403">Minuts</translation>
<translation id="8541249477527128034">control de mitjans</translation>
<translation id="8583702881314752957">llista de definicions</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">inicia la reproducció</translation>
<translation id="8851136666856101339">principal</translation>
<translation id="8987927404178983737">Mes</translation>
+<translation id="9002566407876343676">obrir</translation>
<translation id="901493112792887934">temps actual en segons</translation>
<translation id="9048119486235211610">navegació</translation>
<translation id="9050748414552849310">mostra els subtítols ocults</translation>
+<translation id="9062295712474918030">document</translation>
<translation id="9108370397979208512">matemàtiques</translation>
<translation id="9132465097189459683">Altres...</translation>
+<translation id="9138385573473225930">alerta</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, a partir del dia <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">cel·la</translation>
+<translation id="966787709310836684">menú</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_cs.xtb b/chromium/content/app/strings/translations/content_strings_cs.xtb
index 499ec8496ad..4ad833de376 100644
--- a/chromium/content/app/strings/translations/content_strings_cs.xtb
+++ b/chromium/content/app/strings/translations/content_strings_cs.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="cs">
<translation id="1014825444426747588">prázdné</translation>
+<translation id="1018939186200882850">položka nabídky</translation>
<translation id="1020833440720551630">ztlumit zvukovou stopu</translation>
<translation id="10623998915015855">přepínací tlačítko</translation>
<translation id="1088086359088493902">Sekundy</translation>
<translation id="1171774979989969504">Zadejte prosím e-mailovou adresu.</translation>
<translation id="1188858454923323853">doplňkové</translation>
+<translation id="1206619573307042055">běžící text</translation>
+<translation id="1206693055195146388">posuvník</translation>
<translation id="1235745349614807883">Smazat nedávná vyhledávání</translation>
+<translation id="1281252709823657822">dialogové okno</translation>
<translation id="1342835525016946179">čl</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">oblast</translation>
<translation id="1591562245178063882">Tento měsíc</translation>
<translation id="1637811476055996098">Zvolit soubory</translation>
+<translation id="167575180612809735">indikátor stavu zaneprázdnění</translation>
<translation id="1729654308190250600">Vyplňte e-mailovou adresu.</translation>
<translation id="1758486001363313524">Jiné…</translation>
+<translation id="1806710327868736751">dialog upozornění</translation>
+<translation id="1821985195704844674">stromová mřížka</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">přehrát ve vzdáleném zařízení</translation>
<translation id="1842960171412779397">zvolit</translation>
+<translation id="1880518467580572141">osnova</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">stav</translation>
<translation id="1938124657309484470">Datum musí být <ph name="MAXIMUM_DATE_OR_TIME" /> nebo dříve.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Zkraťte prosím tento text na <ph name="MAX_CHARACTERS" /> znaků nebo méně. (Aktuálně má <ph name="CURRENT_LENGTH" /> znaků.)</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. týden, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">zaškrtávací políčko</translation>
+<translation id="2335594187091864976">výběr data a času</translation>
<translation id="248395913932153421">Den</translation>
<translation id="2507943997699731163">Vyplňte prosím toto pole.</translation>
+<translation id="2508569020611168319">seznam karet</translation>
<translation id="2548326553472216322">Žádná nedávná vyhledávání</translation>
<translation id="2572483411312390101">přehrát</translation>
<translation id="2613802280814924224">Zadejte platnou hodnotu. Nejbližší platná hodnota je <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">zápatí</translation>
<translation id="2723001399770238859">zvuk</translation>
<translation id="2746543609216772311">Datum musí být <ph name="MINIMUM_DATE_OR_TIME" /> nebo později.</translation>
+<translation id="2759744352195237655">vyskakovací tlačítko</translation>
<translation id="2761667185364618470">Chcete-li pokračovat, zaškrtněte toto políčko.</translation>
<translation id="2846343701378493991">1024 (Střední kvalita)</translation>
+<translation id="2896972712917208084">skupina přepínačů</translation>
<translation id="2901282870647571346">aktuální stav filmu</translation>
<translation id="2908441821576996758">Zadejte seznam e-mailových adres oddělených čárkami.</translation>
+<translation id="2931838996092594335">kliknout</translation>
+<translation id="2940813599313844715">objekt</translation>
<translation id="2942448076852699108">zvýrazněný obsah</translation>
<translation id="3040011195152428237">odkaz</translation>
<translation id="3075154866155599887">Zadejte prosím platnou hodnotu. Pole obsahuje neúplnou hodnotu nebo neplatné datum.</translation>
+<translation id="3078740164268491126">tabulka</translation>
+<translation id="3086746722712840547">pozn</translation>
<translation id="310520048233152454">Zadejte prosím adresu URL.</translation>
+<translation id="3175736971608411871">časovač</translation>
+<translation id="3199563858620722075">rozbalovací seznam</translation>
<translation id="3450233048674729344">Hodnota musí být menší nebo rovna <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">definice</translation>
+<translation id="3557673793733683882">nadpis <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">zbývající čas filmu v sekundách</translation>
<translation id="3706100364254443312">přepínač</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">výraz</translation>
<translation id="3822383571486410024">Prodlužte prosím tento text na <ph name="MIN_CHARACTERS" /> či více znaků. (Aktuálně má <ph name="CURRENT_LENGTH" /> znaků.)</translation>
<translation id="383465348367842624">Část před znakem <ph name="ATSIGN" /> nesmí obsahovat znak <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="3924558731517983934">aplikace</translation>
+<translation id="3960700977367013758">posuvník</translation>
<translation id="4103419683916926126">Milisekundy</translation>
+<translation id="4151657705144244502">obrázek</translation>
<translation id="4201051445878709314">Zobrazit předchozí měsíc</translation>
<translation id="4202807286478387388">přejít</translation>
+<translation id="421884353938374759">výběr barev</translation>
+<translation id="4248100235867064564">panel nabídky</translation>
+<translation id="4254339807215791271">informace o obsahu</translation>
<translation id="4360991593054037559">Zadejte platnou hodnotu. Dvě nejbližší hodnoty jsou <ph name="VALID_VALUE_LOW" /> a <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">tlačítko nabídky</translation>
<translation id="4522570452068850558">Podrobnosti</translation>
<translation id="4597532268155981612">formulář</translation>
+<translation id="4661075872484491155">strom</translation>
<translation id="4664250907885839816">Část za znakem <ph name="ATSIGN" /> nesmí obsahovat znak <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="4757246831282535685">panel karty</translation>
<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Zadejte prosím číslo.</translation>
<translation id="4975562563186953947">Vybráno: <ph name="SELECTED_COUNT" /></translation>
<translation id="49969490063480558">Zadejte část za znakem <ph name="ATSIGN" />. Adresa <ph name="INVALIDADDRESS" /> není úplná.</translation>
+<translation id="5034860022980953847">indikátor průběhu</translation>
<translation id="5048533449481078685">značka seznamu</translation>
<translation id="5117590920725113268">Zobrazit další měsíc</translation>
+<translation id="512758898067543763">záhlaví řádku</translation>
<translation id="5164977714490026579">Hodnota musí být větší nebo rovna <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Zadejte část před znakem <ph name="ATSIGN" />. Adresa <ph name="INVALIDADDRESS" /> není úplná.</translation>
+<translation id="5317780077021120954">Uložit</translation>
<translation id="5406322316791861025">číslice</translation>
+<translation id="5453733299334684579">položka stromu</translation>
<translation id="5466621249238537318">Vyberte prosím jeden nebo více souborů.</translation>
<translation id="5468998798572797635">ukončit režim celé obrazovky</translation>
<translation id="5476505524087279545">odstranit zaškrtnutí</translation>
+<translation id="5516424706154626233">výběr data</translation>
<translation id="5546461542133609677">zapnout zvuk</translation>
+<translation id="561939826962581046">čas</translation>
<translation id="5641012560118721995">pozastavit přehrávání</translation>
+<translation id="5643186887447432888">tlačítko</translation>
<translation id="5843503607508392247">Jiné…</translation>
<translation id="5939518447894949180">Resetovat</translation>
<translation id="5944544982112848342">2048 (vysoká kvalita)</translation>
<translation id="5966707198760109579">Týden</translation>
-<translation id="598301471034819706">adresa</translation>
+<translation id="5987525920412732405">číselník</translation>
<translation id="6015796118275082299">Rok</translation>
+<translation id="6023896073578205740">seznam</translation>
<translation id="6101327004457443354">zapnout zvukovou stopu</translation>
<translation id="6119846243427417423">aktivovat</translation>
+<translation id="6164829606128959761">měřič</translation>
<translation id="6270583010843788609">náhled na časové ose filmu</translation>
<translation id="6359256949422175976">náhled na posuvníku filmu</translation>
<translation id="6398862346408813489">Zobrazit panel pro výběr měsíců</translation>
<translation id="6404546809543547843">posuvník času zvuku</translation>
+<translation id="648732519525291180">výběr času</translation>
<translation id="658823671542763450">přejít do režimu celé obrazovky</translation>
+<translation id="6637586476836377253">protokol</translation>
<translation id="6643016212128521049">Vymazat</translation>
<translation id="6663448176199120256">Nedávná vyhledávání</translation>
<translation id="668171684555832681">Další...</translation>
<translation id="6692633176391053278">stepper</translation>
+<translation id="6739588121953935928">pravítko</translation>
+<translation id="6755330956360078551">popisek</translation>
<translation id="6820355525329141109">Plugin se nepodařilo načíst.</translation>
<translation id="6843725295806269523">ztlumit</translation>
<translation id="6845533974506654842">zmáčknout</translation>
<translation id="6853785296079745596">skrýt titulky</translation>
+<translation id="6885760532393684712">adresář</translation>
+<translation id="6934078000481955284">bloková citace</translation>
<translation id="7057186640035488495">čas filmu</translation>
<translation id="709897737746224366">Zadejte hodnotu, která odpovídá požadovanému formátu.</translation>
<translation id="7223624360433298498">přehraný čas</translation>
<translation id="7263440858009898357">Vyberte prosím v seznamu některou položku.</translation>
+<translation id="727747134524199931">záhlaví sloupce</translation>
<translation id="7364796246159120393">Vybrat soubor</translation>
<translation id="739024184232394898">Jiné…</translation>
+<translation id="7491962110804786152">karta</translation>
<translation id="7673697353781729403">Hodiny</translation>
<translation id="7720026100085573005">zbývající čas</translation>
<translation id="7740016676195725605">ukončit zobrazování titulků</translation>
<translation id="7740050170769002709">Obsah ve formátu HTML</translation>
<translation id="7789962463072032349">pozastavit</translation>
+<translation id="7802800022689234070">tlačítko k zobrazení skrytého obsahu</translation>
<translation id="7888071071722539607">Do e-mailové adresy zahrňte znak <ph name="ATSIGN" />. V adrese <ph name="INVALIDADDRESS" /> chybí znak <ph name="ATSIGN" />.</translation>
+<translation id="7891486169920085145">rozdělovač</translation>
<translation id="795667975304826397">Soubor nevybrán</translation>
<translation id="8053789581856978548">pole pro vyhledání textu</translation>
<translation id="8115662671911883373">zahájit zobrazování titulků</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">obrázková mapa</translation>
<translation id="835897206747267392">Neplatná hodnota.</translation>
<translation id="838869780401515933">zaškrtnout</translation>
+<translation id="8433900881053900389">lišta</translation>
<translation id="8444882422881193423">Počet souborů: <ph name="NUMBER_OF_FILES" /></translation>
<translation id="8451268428117625855">Vyberte prosím soubor.</translation>
+<translation id="8461852803063341183">přepínač</translation>
+<translation id="8511325616783751178">tlačítko rozbalovací nabídky</translation>
<translation id="8534579021159131403">Minuty</translation>
<translation id="8541249477527128034">ovládání médií</translation>
<translation id="8583702881314752957">seznam definic</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">zahájit přehrávání</translation>
<translation id="8851136666856101339">hlavní</translation>
<translation id="8987927404178983737">Měsíc</translation>
+<translation id="9002566407876343676">otevřít</translation>
<translation id="901493112792887934">aktuální čas v sekundách</translation>
<translation id="9048119486235211610">navigace</translation>
<translation id="9050748414552849310">zobrazit titulky</translation>
+<translation id="9062295712474918030">dokument</translation>
<translation id="9108370397979208512">matematika</translation>
<translation id="9132465097189459683">Jiné…</translation>
+<translation id="9138385573473225930">upozornění</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, začíná <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">buňka</translation>
+<translation id="966787709310836684">nabídka</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_da.xtb b/chromium/content/app/strings/translations/content_strings_da.xtb
index 42323406269..b6022aa94f4 100644
--- a/chromium/content/app/strings/translations/content_strings_da.xtb
+++ b/chromium/content/app/strings/translations/content_strings_da.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="da">
<translation id="1014825444426747588">tom</translation>
+<translation id="1018939186200882850">menupunkt</translation>
<translation id="1020833440720551630">slå lydspor fra</translation>
<translation id="10623998915015855">til/fra-knap</translation>
<translation id="1088086359088493902">Sekunder</translation>
<translation id="1171774979989969504">Angiv en e-mailadresse.</translation>
<translation id="1188858454923323853">supplerende</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">skyder</translation>
<translation id="1235745349614807883">Slet nylige søgninger</translation>
+<translation id="1281252709823657822">dialogboks</translation>
<translation id="1342835525016946179">artikel</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">område</translation>
<translation id="1591562245178063882">Denne måned</translation>
<translation id="1637811476055996098">Vælg filer</translation>
+<translation id="167575180612809735">optagetindikator</translation>
<translation id="1729654308190250600">Angiv en e-mailadresse, der ikke er tom.</translation>
<translation id="1758486001363313524">Andet...</translation>
-<translation id="1822429046913737220">AM/PM</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">trægitter</translation>
+<translation id="1822429046913737220">f.m./e.m.</translation>
<translation id="1832974991323546415">afspil på en enhed via fjernadgang</translation>
<translation id="1842960171412779397">vælg</translation>
+<translation id="1880518467580572141">kontur</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">status</translation>
<translation id="1938124657309484470">Værdien må ikke være senere end <ph name="MAXIMUM_DATE_OR_TIME" />.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Forkort denne tekst til <ph name="MAX_CHARACTERS" /> tegn eller færre (du bruger i øjeblikket <ph name="CURRENT_LENGTH" /> tegn).</translation>
<translation id="2247351761944213033">Uge <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">afkrydsningsfelt</translation>
+<translation id="2335594187091864976">dato- og tidsvælger</translation>
<translation id="248395913932153421">Dag</translation>
<translation id="2507943997699731163">Udfyld dette felt.</translation>
+<translation id="2508569020611168319">faneliste</translation>
<translation id="2548326553472216322">Ingen nylige søgninger</translation>
<translation id="2572483411312390101">afspil</translation>
<translation id="2613802280814924224">Angiv en gyldig værdi. Den nærmeste gyldige værdi er <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">sidefod</translation>
<translation id="2723001399770238859">lyd</translation>
<translation id="2746543609216772311">Værdien må ikke være tidligere end <ph name="MINIMUM_DATE_OR_TIME" />.</translation>
+<translation id="2759744352195237655">pop op-knap</translation>
<translation id="2761667185364618470">Markér dette felt, hvis du vil fortsætte.</translation>
<translation id="2846343701378493991">1024 (Mellemklasse)</translation>
+<translation id="2896972712917208084">gruppe af alternativknapper</translation>
<translation id="2901282870647571346">aktuel filmstatus</translation>
<translation id="2908441821576996758">Angiv en kommasepareret liste over e-mailadresser.</translation>
+<translation id="2931838996092594335">klik</translation>
+<translation id="2940813599313844715">objekt</translation>
<translation id="2942448076852699108">fremhævet indhold</translation>
<translation id="3040011195152428237">link</translation>
<translation id="3075154866155599887">Angiv en gyldig værdi. Feltet er ufuldstændigt eller har en ugyldig dato.</translation>
+<translation id="3078740164268491126">tabel</translation>
+<translation id="3086746722712840547">bmrk</translation>
<translation id="310520048233152454">Angiv en webadresse.</translation>
+<translation id="3175736971608411871">timer</translation>
+<translation id="3199563858620722075">kombifelt</translation>
<translation id="3450233048674729344">Værdien skal være mindre end eller lig med <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">definition</translation>
+<translation id="3557673793733683882">overskrift <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">antal sekunder tilbage af filmen</translation>
<translation id="3706100364254443312">kontakt</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">term</translation>
<translation id="3822383571486410024">Forlæng denne tekst til <ph name="MIN_CHARACTERS" /> eller flere tegn (du bruger i øjeblikket <ph name="CURRENT_LENGTH" /> tegn).</translation>
<translation id="383465348367842624">Den del, der kommer før "<ph name="ATSIGN" />", må ikke indeholde "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3924558731517983934">applikation</translation>
+<translation id="3960700977367013758">rullepanel</translation>
<translation id="4103419683916926126">Millisekunder</translation>
+<translation id="4151657705144244502">grafik</translation>
<translation id="4201051445878709314">Vis den foregående måned</translation>
<translation id="4202807286478387388">hop</translation>
+<translation id="421884353938374759">farvevælger</translation>
+<translation id="4248100235867064564">menulinje</translation>
+<translation id="4254339807215791271">indholdsoplysninger</translation>
<translation id="4360991593054037559">Angiv en gyldig værdi. De to nærmeste gyldige værdier er <ph name="VALID_VALUE_LOW" /> og <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">menuknap</translation>
<translation id="4522570452068850558">Detaljer</translation>
<translation id="4597532268155981612">formular</translation>
+<translation id="4661075872484491155">træ</translation>
<translation id="4664250907885839816">Den del, der kommer efter "<ph name="ATSIGN" />", må ikke indeholde symbolet "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4757246831282535685">fanepanel</translation>
<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">søg</translation>
<translation id="4812940957355064477">Angiv et nummer.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> er valgt</translation>
<translation id="49969490063480558">Angiv den del, der kommer efter "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" er ufuldstændig.</translation>
+<translation id="5034860022980953847">statusindikator</translation>
<translation id="5048533449481078685">listemarkering</translation>
<translation id="5117590920725113268">Vis næste måned</translation>
+<translation id="512758898067543763">rækkeoverskrift</translation>
<translation id="5164977714490026579">Værdien skal være større end eller lig med <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Angiv den del, der kommer før "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" er ufuldstændig.</translation>
+<translation id="5317780077021120954">Gem</translation>
<translation id="5406322316791861025">tal</translation>
+<translation id="5453733299334684579">træelement</translation>
<translation id="5466621249238537318">Vælg en eller flere filer.</translation>
<translation id="5468998798572797635">afslut fuld skærm</translation>
<translation id="5476505524087279545">fjern markering</translation>
+<translation id="5516424706154626233">datovælger</translation>
<translation id="5546461542133609677">slå lyd til</translation>
+<translation id="561939826962581046">tidspunkt</translation>
<translation id="5641012560118721995">pause</translation>
+<translation id="5643186887447432888">knap</translation>
<translation id="5843503607508392247">Andet...</translation>
<translation id="5939518447894949180">Nulstil</translation>
<translation id="5944544982112848342">2048 (Høj klasse)</translation>
<translation id="5966707198760109579">Uge</translation>
-<translation id="598301471034819706">adresse</translation>
+<translation id="5987525920412732405">skalafelt</translation>
<translation id="6015796118275082299">År</translation>
+<translation id="6023896073578205740">listefelt</translation>
<translation id="6101327004457443354">slå lydspor til</translation>
<translation id="6119846243427417423">aktiver</translation>
+<translation id="6164829606128959761">måler</translation>
<translation id="6270583010843788609">miniature for tidslinje</translation>
<translation id="6359256949422175976">miniature for filmtidsskyder</translation>
<translation id="6398862346408813489">Vis panel til valg af måned</translation>
<translation id="6404546809543547843">afspilningsbjælke for lyd</translation>
+<translation id="648732519525291180">tidsvælger</translation>
<translation id="658823671542763450">åbn fuld skærm</translation>
+<translation id="6637586476836377253">log</translation>
<translation id="6643016212128521049">Ryd</translation>
<translation id="6663448176199120256">Nylige søgninger</translation>
<translation id="668171684555832681">Andre...</translation>
<translation id="6692633176391053278">stepper</translation>
+<translation id="6739588121953935928">lineal</translation>
+<translation id="6755330956360078551">værktøjstip</translation>
<translation id="6820355525329141109">Pluginnet kunne ikke indlæses.</translation>
<translation id="6843725295806269523">slå lyden fra</translation>
<translation id="6845533974506654842">tryk</translation>
<translation id="6853785296079745596">skjul undertekster</translation>
+<translation id="6885760532393684712">indeks</translation>
+<translation id="6934078000481955284">blockquote</translation>
<translation id="7057186640035488495">filmtid</translation>
<translation id="709897737746224366">Find et match til det anmodede format.</translation>
<translation id="7223624360433298498">forløbet tid</translation>
<translation id="7263440858009898357">Vælg et punkt på listen.</translation>
+<translation id="727747134524199931">kolonneoverskrift</translation>
<translation id="7364796246159120393">Vælg fil</translation>
<translation id="739024184232394898">Andet...</translation>
+<translation id="7491962110804786152">fane</translation>
<translation id="7673697353781729403">Timer</translation>
<translation id="7720026100085573005">resterende tid</translation>
<translation id="7740016676195725605">stop visning af undertekster</translation>
<translation id="7740050170769002709">HTML-indhold</translation>
<translation id="7789962463072032349">pause</translation>
+<translation id="7802800022689234070">Trekant til at vise eller skjule indhold</translation>
<translation id="7888071071722539607">E-mailadressen skal indeholde et "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" mangler et "<ph name="ATSIGN" />".</translation>
+<translation id="7891486169920085145">splitter</translation>
<translation id="795667975304826397">Der er ikke valgt nogen fil</translation>
<translation id="8053789581856978548">tekstfelt til søgning</translation>
<translation id="8115662671911883373">start visning af undertekster</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">billedekort</translation>
<translation id="835897206747267392">Ugyldig værdi.</translation>
<translation id="838869780401515933">markér</translation>
+<translation id="8433900881053900389">værktøjslinje</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> filer</translation>
<translation id="8451268428117625855">Vælg en fil.</translation>
+<translation id="8461852803063341183">alternativknap</translation>
+<translation id="8511325616783751178">rullemenuknap</translation>
<translation id="8534579021159131403">Minutter</translation>
<translation id="8541249477527128034">mediekontrol</translation>
<translation id="8583702881314752957">liste over definitioner</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">start afspilning</translation>
<translation id="8851136666856101339">hovd</translation>
<translation id="8987927404178983737">Måned</translation>
+<translation id="9002566407876343676">åbn</translation>
<translation id="901493112792887934">aktuel tid i sekunder</translation>
<translation id="9048119486235211610">navigation</translation>
<translation id="9050748414552849310">vis undertekster</translation>
+<translation id="9062295712474918030">dokument</translation>
<translation id="9108370397979208512">matematik</translation>
<translation id="9132465097189459683">Andet...</translation>
+<translation id="9138385573473225930">underretning</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, med start <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">celle</translation>
+<translation id="966787709310836684">menu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_de.xtb b/chromium/content/app/strings/translations/content_strings_de.xtb
index 7a8c65bf77f..3559c80a823 100644
--- a/chromium/content/app/strings/translations/content_strings_de.xtb
+++ b/chromium/content/app/strings/translations/content_strings_de.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="de">
<translation id="1014825444426747588">leer</translation>
+<translation id="1018939186200882850">Menüpunkt</translation>
<translation id="1020833440720551630">Ton ausschalten</translation>
<translation id="10623998915015855">Schaltfläche zum Umschalten</translation>
<translation id="1088086359088493902">Sekunden</translation>
<translation id="1171774979989969504">Geben Sie eine E-Mail-Adresse ein.</translation>
<translation id="1188858454923323853">ergänzend</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">Schieberegler</translation>
<translation id="1235745349614807883">Vor Kurzem durchgeführte Suchanfragen löschen</translation>
+<translation id="1281252709823657822">Kleines Fenster</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">Banner</translation>
<translation id="1589122976691792535">Region</translation>
<translation id="1591562245178063882">Aktueller Monat</translation>
<translation id="1637811476055996098">Dateien auswählen</translation>
+<translation id="167575180612809735">Anzeige für fehlende Verfügbarkeit</translation>
<translation id="1729654308190250600">Geben Sie eine E-Mail-Adresse ein.</translation>
<translation id="1758486001363313524">Andere...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">Baumraster</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">auf Remote-Gerät wiedergeben</translation>
<translation id="1842960171412779397">auswählen</translation>
+<translation id="1880518467580572141">Übersicht</translation>
<translation id="1921819250265091946">tt</translation>
<translation id="1930711995431081526">Status</translation>
<translation id="1938124657309484470">Verwenden Sie <ph name="MAXIMUM_DATE_OR_TIME" /> oder einen früheren Wert.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Kürzen Sie diesen Text auf max. <ph name="MAX_CHARACTERS" /> Zeichen. Zurzeit verwenden Sie <ph name="CURRENT_LENGTH" /> Zeichen.</translation>
<translation id="2247351761944213033">Woche <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">Kästchen</translation>
+<translation id="2335594187091864976">Datums- und Uhrzeitauswahl</translation>
<translation id="248395913932153421">Tag</translation>
<translation id="2507943997699731163">Füllen Sie dieses Feld aus.</translation>
+<translation id="2508569020611168319">Tabliste</translation>
<translation id="2548326553472216322">Keine vor Kurzem durchgeführte Suchanfragen</translation>
<translation id="2572483411312390101">Wiedergeben</translation>
<translation id="2613802280814924224">Geben Sie einen gültigen Wert ein. Der nächstliegende gültige Wert ist <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">Fußzeile</translation>
<translation id="2723001399770238859">Audio</translation>
<translation id="2746543609216772311">Verwenden Sie <ph name="MINIMUM_DATE_OR_TIME" /> oder einen späteren Wert.</translation>
+<translation id="2759744352195237655">Pop-up-Schaltfläche</translation>
<translation id="2761667185364618470">Aktivieren Sie dieses Kästchen, wenn Sie fortfahren möchten.</translation>
<translation id="2846343701378493991">1024 (mittlere Stufe)</translation>
+<translation id="2896972712917208084">Optionsfeldgruppe</translation>
<translation id="2901282870647571346">Aktueller Filmstatus</translation>
<translation id="2908441821576996758">Geben Sie eine durch Kommas getrennte Liste der E-Mail-Adressen ein.</translation>
+<translation id="2931838996092594335">Klicken</translation>
+<translation id="2940813599313844715">Objekt</translation>
<translation id="2942448076852699108">markierte Inhalte</translation>
<translation id="3040011195152428237">Link</translation>
<translation id="3075154866155599887">Geben Sie einen gültigen Wert ein. Das Feld ist nicht vollständig oder enthält ein ungültiges Datum.</translation>
+<translation id="3078740164268491126">Tabelle</translation>
+<translation id="3086746722712840547">note</translation>
<translation id="310520048233152454">Geben Sie eine URL ein.</translation>
+<translation id="3175736971608411871">Timer</translation>
+<translation id="3199563858620722075">Kombinationsfeld</translation>
<translation id="3450233048674729344">Wert muss kleiner als oder gleich <ph name="MAXIMUM" /> sein.</translation>
<translation id="3486220673238053218">Definition</translation>
+<translation id="3557673793733683882">Überschrift <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">Verbleibende Dauer in Sekunden</translation>
<translation id="3706100364254443312">wechseln</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">Begriff</translation>
<translation id="3822383571486410024">Verlängern Sie diesen Text auf mindestens <ph name="MIN_CHARACTERS" /> Zeichen. Derzeit verwenden Sie <ph name="CURRENT_LENGTH" /> Zeichen.</translation>
<translation id="383465348367842624">Vor dem <ph name="ATSIGN" />-Zeichen darf das Zeichen "<ph name="INVALIDCHARACTER" />" nicht verwendet werden.</translation>
+<translation id="3924558731517983934">Anwendung</translation>
+<translation id="3960700977367013758">Bildlaufleiste</translation>
<translation id="4103419683916926126">Millisekunden</translation>
+<translation id="4151657705144244502">Grafik</translation>
<translation id="4201051445878709314">Vorherigen Monat anzeigen</translation>
<translation id="4202807286478387388">springen</translation>
+<translation id="421884353938374759">color picker</translation>
+<translation id="4248100235867064564">Menüleiste</translation>
+<translation id="4254339807215791271">Inhaltsinformationen</translation>
<translation id="4360991593054037559">Geben Sie einen gültigen Wert ein. Die zwei nächstliegenden gültigen Werte sind <ph name="VALID_VALUE_LOW" /> und <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">Menüschaltfläche</translation>
<translation id="4522570452068850558">Details</translation>
<translation id="4597532268155981612">Formular</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Nach dem <ph name="ATSIGN" />-Zeichen darf das Zeichen "<ph name="INVALIDCHARACTER" />" nicht verwendet werden.</translation>
+<translation id="4757246831282535685">Tabsteuerfeld</translation>
<translation id="4763480195061959176">Video</translation>
+<translation id="479989351350248267">Suchen</translation>
<translation id="4812940957355064477">Geben Sie eine Nummer ein.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> ausgewählt</translation>
<translation id="49969490063480558">Geben Sie etwas nach dem <ph name="ATSIGN" />-Zeichen ein. Die Angabe "<ph name="INVALIDADDRESS" />" ist unvollständig.</translation>
+<translation id="5034860022980953847">Fortschrittsanzeige</translation>
<translation id="5048533449481078685">Listenmarkierung</translation>
<translation id="5117590920725113268">Nächsten Monat anzeigen</translation>
+<translation id="512758898067543763">Zeilenüberschrift</translation>
<translation id="5164977714490026579">Wert muss größer als oder gleich <ph name="MINIMUM" /> sein.</translation>
<translation id="5307600278924710095">Geben Sie etwas vor dem <ph name="ATSIGN" />-Zeichen ein. Die Angabe "<ph name="INVALIDADDRESS" />" ist unvollständig.</translation>
+<translation id="5317780077021120954">Speichern</translation>
<translation id="5406322316791861025">Zahl</translation>
+<translation id="5453733299334684579">Baumelement</translation>
<translation id="5466621249238537318">Wählen Sie eine oder mehrere Dateien aus.</translation>
<translation id="5468998798572797635">Vollbildmodus beenden</translation>
<translation id="5476505524087279545">Auswahl aufheben</translation>
+<translation id="5516424706154626233">Datumsauswahl</translation>
<translation id="5546461542133609677">Ton an</translation>
+<translation id="561939826962581046">time</translation>
<translation id="5641012560118721995">Wiedergabe anhalten</translation>
+<translation id="5643186887447432888">Schaltfläche</translation>
<translation id="5843503607508392247">Andere...</translation>
<translation id="5939518447894949180">Zurücksetzen</translation>
<translation id="5944544982112848342">2048 (High Grade)</translation>
<translation id="5966707198760109579">Woche</translation>
-<translation id="598301471034819706">Adresse</translation>
+<translation id="5987525920412732405">Drehfeld</translation>
<translation id="6015796118275082299">Jahr</translation>
+<translation id="6023896073578205740">Listenfeld</translation>
<translation id="6101327004457443354">Ton anschalten</translation>
<translation id="6119846243427417423">aktivieren</translation>
+<translation id="6164829606128959761">Messinstrument</translation>
<translation id="6270583010843788609">Zeitachsen-Ziehpunkt</translation>
<translation id="6359256949422175976">Ziehpunkt für Video-Zeitachse</translation>
<translation id="6398862346408813489">Auswahlbereich für Monatsanzeige</translation>
<translation id="6404546809543547843">Audio-Zeitachse</translation>
+<translation id="648732519525291180">Uhrzeitauswahl</translation>
<translation id="658823671542763450">Vollbildmodus aktivieren</translation>
+<translation id="6637586476836377253">log</translation>
<translation id="6643016212128521049">Löschen</translation>
<translation id="6663448176199120256">Vor Kurzem durchgeführte Suchanfragen</translation>
<translation id="668171684555832681">Andere...</translation>
<translation id="6692633176391053278">Stepper</translation>
+<translation id="6739588121953935928">Lineal</translation>
+<translation id="6755330956360078551">Kurzinfo</translation>
<translation id="6820355525329141109">Plug-in konnte nicht geladen werden.</translation>
<translation id="6843725295806269523">Stumm</translation>
<translation id="6845533974506654842">klicken</translation>
<translation id="6853785296079745596">Untertitel ausblenden</translation>
+<translation id="6885760532393684712">Verzeichnis</translation>
+<translation id="6934078000481955284">blockquote</translation>
<translation id="7057186640035488495">Filmdauer</translation>
<translation id="709897737746224366">Ihre Eingabe muss mit dem geforderten Format übereinstimmen.</translation>
<translation id="7223624360433298498">Vergangene Zeit</translation>
<translation id="7263440858009898357">Wählen Sie ein Element in der Liste aus.</translation>
+<translation id="727747134524199931">Spaltenüberschrift</translation>
<translation id="7364796246159120393">Datei auswählen</translation>
<translation id="739024184232394898">Andere...</translation>
+<translation id="7491962110804786152">tab</translation>
<translation id="7673697353781729403">Stunden</translation>
<translation id="7720026100085573005">Verbleibende Zeit</translation>
<translation id="7740016676195725605">Keine Untertitel mehr anzeigen</translation>
<translation id="7740050170769002709">HTML-Inhalte</translation>
<translation id="7789962463072032349">Pausieren</translation>
+<translation id="7802800022689234070">Aufklappdreieck</translation>
<translation id="7888071071722539607">Die E-Mail-Adresse muss ein <ph name="ATSIGN" />-Zeichen enthalten. In der Angabe "<ph name="INVALIDADDRESS" />" fehlt ein <ph name="ATSIGN" />-Zeichen.</translation>
+<translation id="7891486169920085145">Teilungsfunktion</translation>
<translation id="795667975304826397">Keine ausgewählt</translation>
<translation id="8053789581856978548">Feld für den Suchtext</translation>
<translation id="8115662671911883373">Untertitel ab sofort anzeigen</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">Imagemap</translation>
<translation id="835897206747267392">Ungültiger Wert.</translation>
<translation id="838869780401515933">auswählen</translation>
+<translation id="8433900881053900389">Symbolleiste</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> Dateien</translation>
<translation id="8451268428117625855">Wählen Sie eine Datei aus.</translation>
+<translation id="8461852803063341183">Optionsfeld</translation>
+<translation id="8511325616783751178">Drop-down-Schaltfläche</translation>
<translation id="8534579021159131403">Minuten</translation>
<translation id="8541249477527128034">Mediensteuerung</translation>
<translation id="8583702881314752957">Definitionsliste</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">Wiedergabe starten</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8987927404178983737">Monat</translation>
+<translation id="9002566407876343676">Öffnen</translation>
<translation id="901493112792887934">Aktuelle Dauer in Sekunden</translation>
<translation id="9048119486235211610">Navigation</translation>
<translation id="9050748414552849310">Untertitel anzeigen</translation>
+<translation id="9062295712474918030">Dokument</translation>
<translation id="9108370397979208512">math</translation>
<translation id="9132465097189459683">Andere...</translation>
+<translation id="9138385573473225930">Benachrichtigung</translation>
<translation id="9155987714137265666"><ph name="WEEK" /> ab dem <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">Zelle</translation>
+<translation id="966787709310836684">Menü</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_el.xtb b/chromium/content/app/strings/translations/content_strings_el.xtb
index 730b1041933..bac8a3d4534 100644
--- a/chromium/content/app/strings/translations/content_strings_el.xtb
+++ b/chromium/content/app/strings/translations/content_strings_el.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="el">
<translation id="1014825444426747588">κενό</translation>
+<translation id="1018939186200882850">στοιχείο μενού</translation>
<translation id="1020833440720551630">σίγαση ήχου</translation>
<translation id="10623998915015855">κουμπί εναλλαγής</translation>
<translation id="1088086359088493902">Δευτερόλεπτα</translation>
<translation id="1171774979989969504">Εισαγάγετε μια διεύθυνση ηλεκτρονικού ταχυδρομείου.</translation>
<translation id="1188858454923323853">συμπληρωματικό</translation>
+<translation id="1206619573307042055">μαρκίζα</translation>
+<translation id="1206693055195146388">ρυθμιστικό</translation>
<translation id="1235745349614807883">Διαγραφή πρόσφατων αναζητήσεων</translation>
+<translation id="1281252709823657822">παράθυρο διαλόγου</translation>
<translation id="1342835525016946179">άρθρο</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">περιοχή</translation>
<translation id="1591562245178063882">Αυτόν το μήνα</translation>
<translation id="1637811476055996098">Επιλογή αρχείων</translation>
+<translation id="167575180612809735">ένδειξη "απασχολημένος"</translation>
<translation id="1729654308190250600">Καταχωρίστε μια διεύθυνση ηλεκτρονικού ταχυδρομείου.</translation>
<translation id="1758486001363313524">Άλλες…</translation>
+<translation id="1806710327868736751">παράθυρο διαλόγου ειδοποιήσεων</translation>
+<translation id="1821985195704844674">πλέγμα δέντρου</translation>
<translation id="1822429046913737220">Π.Μ./Μ.Μ.</translation>
<translation id="1832974991323546415">αναπαραγωγή σε απομακρυσμένη συσκευή</translation>
<translation id="1842960171412779397">επιλογή</translation>
+<translation id="1880518467580572141">διάρθρωση</translation>
<translation id="1921819250265091946">ηη</translation>
<translation id="1930711995431081526">κατάσταση</translation>
<translation id="1938124657309484470">Η τιμή πρέπει να είναι <ph name="MAXIMUM_DATE_OR_TIME" /> ή προγενέστερη.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Κάντε πιο σύντομο αυτό το κείμενο ώστε να έχει το πολύ <ph name="MAX_CHARACTERS" /> χαρακτήρες (αυτήν τη στιγμή χρησιμοποιείτε <ph name="CURRENT_LENGTH" /> χαρακτήρες).</translation>
<translation id="2247351761944213033">Εβδομάδα <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">πλαίσιο ελέγχου</translation>
+<translation id="2335594187091864976">εργαλείο επιλογής ημερομηνίας και ώρας</translation>
<translation id="248395913932153421">Ημέρα</translation>
<translation id="2507943997699731163">Συμπληρώστε αυτό το πεδίο.</translation>
+<translation id="2508569020611168319">λίστα καρτελών</translation>
<translation id="2548326553472216322">Δεν υπάρχουν πρόσφατες αναζητήσεις</translation>
<translation id="2572483411312390101">αναπαραγωγή</translation>
<translation id="2613802280814924224">Καταχωρίστε μια έγκυρη τιμή. Η κοντινότερη έγκυρη τιμή είναι <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">υποσέλιδο</translation>
<translation id="2723001399770238859">ήχος</translation>
<translation id="2746543609216772311">Η τιμή πρέπει να είναι <ph name="MINIMUM_DATE_OR_TIME" /> ή μεταγενέστερη.</translation>
+<translation id="2759744352195237655">αναδυόμενο κουμπί</translation>
<translation id="2761667185364618470">Αν θέλετε να συνεχίσετε, επιλέξτε αυτό το πλαίσιο.</translation>
<translation id="2846343701378493991">1024 (Μέτριος βαθμός)</translation>
+<translation id="2896972712917208084">ομάδα κουμπιών επιλογής</translation>
<translation id="2901282870647571346">τρέχουσα κατάσταση ταινίας</translation>
<translation id="2908441821576996758">Εισαγάγετε μια λίστα διευθύνσεων ηλεκτρονικού ταχυδρομείου διαχωρισμένη με κόμματα.</translation>
+<translation id="2931838996092594335">κάνω κλικ</translation>
+<translation id="2940813599313844715">αντικείμενο</translation>
<translation id="2942448076852699108">επισημασμένο περιεχόμενο</translation>
<translation id="3040011195152428237">σύνδεσμος</translation>
<translation id="3075154866155599887">Καταχωρίστε μια έγκυρη τιμή. Το πεδίο είναι ελλιπές ή περιέχει μη έγκυρη ημερομηνία.</translation>
+<translation id="3078740164268491126">πίνακας</translation>
+<translation id="3086746722712840547">σημείωση</translation>
<translation id="310520048233152454">Εισαγάγετε μια διεύθυνση URL.</translation>
+<translation id="3175736971608411871">χρονόμετρο</translation>
+<translation id="3199563858620722075">σύνθετο πλαίσιο</translation>
<translation id="3450233048674729344">Η τιμή πρέπει να είναι μικρότερη ή ίση του <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">ορισμός</translation>
+<translation id="3557673793733683882">επικεφαλίδα <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">αριθμός δευτερολέπτων της ταινίας που απομένουν</translation>
<translation id="3706100364254443312">εναλλαγή</translation>
<translation id="3732799496749320381">μμ</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">όρος</translation>
<translation id="3822383571486410024">Αυξήστε την έκταση αυτού του κειμένου στους <ph name="MIN_CHARACTERS" /> χαρακτήρες ή περισσότερο (αυτήν τη στιγμή χρησιμοποιείτε <ph name="CURRENT_LENGTH" /> χαρακτήρες).</translation>
<translation id="383465348367842624">Το τμήμα της διεύθυνσης πριν το σύμβολο "<ph name="ATSIGN" />" δεν πρέπει να περιέχει το σύμβολο "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3924558731517983934">εφαρμογή</translation>
+<translation id="3960700977367013758">γραμμή κύλισης</translation>
<translation id="4103419683916926126">Χιλιοστά του δευτερολέπτου</translation>
+<translation id="4151657705144244502">γραφικό</translation>
<translation id="4201051445878709314">Εμφάνιση προηγούμενου μήνα</translation>
<translation id="4202807286478387388">μεταπήδηση</translation>
+<translation id="421884353938374759">επιλογέας χρώματος</translation>
+<translation id="4248100235867064564">γραμμή μενού</translation>
+<translation id="4254339807215791271">πληροφορίες περιεχομένου</translation>
<translation id="4360991593054037559">Καταχωρίστε μια έγκυρη τιμή. Οι δύο πιο κοντινές έγκυρες τιμές είναι <ph name="VALID_VALUE_LOW" /> και <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">κουμπί μενού</translation>
<translation id="4522570452068850558">Λεπτομέρειες</translation>
<translation id="4597532268155981612">φόρμα</translation>
+<translation id="4661075872484491155">δέντρο</translation>
<translation id="4664250907885839816">Το τμήμα της διεύθυνσης μετά το σύμβολο "<ph name="ATSIGN" />" δεν πρέπει να περιέχει το σύμβολο "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4757246831282535685">παράθυρο καρτέλας</translation>
<translation id="4763480195061959176">βίντεο</translation>
+<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Εισαγάγετε έναν αριθμό.</translation>
<translation id="4975562563186953947">Επιλέχτηκαν <ph name="SELECTED_COUNT" /></translation>
<translation id="49969490063480558">Καταχωρίστε το τμήμα της διεύθυνσης μετά το σύμβολο "<ph name="ATSIGN" />". Η διεύθυνση "<ph name="INVALIDADDRESS" />" δεν είναι πλήρης.</translation>
+<translation id="5034860022980953847">ένδειξη προόδου</translation>
<translation id="5048533449481078685">δείκτης λίστας</translation>
<translation id="5117590920725113268">Εμφάνιση επόμενου μήνα</translation>
+<translation id="512758898067543763">κεφαλίδα σειράς</translation>
<translation id="5164977714490026579">Η τιμή πρέπει να είναι μεγαλύτερη ή ίση του <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Καταχωρίστε το τμήμα της διεύθυνσης πριν το σύμβολο "<ph name="ATSIGN" />". Η διεύθυνση "<ph name="INVALIDADDRESS" />" δεν είναι πλήρης.</translation>
+<translation id="5317780077021120954">Αποθήκευση</translation>
<translation id="5406322316791861025">αριθμός</translation>
+<translation id="5453733299334684579">στοιχείο δέντρου</translation>
<translation id="5466621249238537318">Επιλέξτε ένα ή περισσότερα αρχεία.</translation>
<translation id="5468998798572797635">έξοδος από πλήρη οθόνη</translation>
<translation id="5476505524087279545">απενεργοποίηση</translation>
+<translation id="5516424706154626233">εργαλείο επιλογής ημερομηνίας</translation>
<translation id="5546461542133609677">κατάργηση σίγασης</translation>
+<translation id="561939826962581046">ώρα</translation>
<translation id="5641012560118721995">παύση αναπαραγωγής</translation>
+<translation id="5643186887447432888">κουμπί</translation>
<translation id="5843503607508392247">Άλλες…</translation>
<translation id="5939518447894949180">Επαναφορά</translation>
<translation id="5944544982112848342">2048 (Υψηλός βαθμός)</translation>
<translation id="5966707198760109579">Εβδομάδα</translation>
-<translation id="598301471034819706">διεύθυνση</translation>
+<translation id="5987525920412732405">κουμπί αυξομείωσης</translation>
<translation id="6015796118275082299">Έτος</translation>
+<translation id="6023896073578205740">πλαίσιο λίστας</translation>
<translation id="6101327004457443354">κατάργηση σίγασης ήχου</translation>
<translation id="6119846243427417423">ενεργοποίηση</translation>
-<translation id="6270583010843788609">δείκτης κύλισης χρονικού πλαισίου ταινίας</translation>
+<translation id="6164829606128959761">μετρητής</translation>
+<translation id="6270583010843788609">δείκτης κύλισης χρονολογίου ταινίας</translation>
<translation id="6359256949422175976">δείκτης κύλισης χρόνου ταινίας</translation>
<translation id="6398862346408813489">Εμφάνιση παραθύρου επιλογής μήνα</translation>
<translation id="6404546809543547843">δείκτης χρόνου ήχου</translation>
+<translation id="648732519525291180">εργαλείο επιλογής ώρας</translation>
<translation id="658823671542763450">ενεργοποίηση πλήρους οθόνης</translation>
+<translation id="6637586476836377253">αρχείο καταγραφής</translation>
<translation id="6643016212128521049">Διαγραφή</translation>
<translation id="6663448176199120256">Πρόσφατες αναζητήσεις</translation>
<translation id="668171684555832681">Άλλο...</translation>
<translation id="6692633176391053278">stepper</translation>
+<translation id="6739588121953935928">χάρακας</translation>
+<translation id="6755330956360078551">επεξήγηση εργαλείου</translation>
<translation id="6820355525329141109">Δεν είναι δυνατή η φόρτωση της προσθήκης.</translation>
<translation id="6843725295806269523">σίγαση</translation>
<translation id="6845533974506654842">πατήστε</translation>
<translation id="6853785296079745596">απόκρυψη υπότιτλων</translation>
+<translation id="6885760532393684712">κατάλογος</translation>
+<translation id="6934078000481955284">blockquote</translation>
<translation id="7057186640035488495">χρόνος ταινίας</translation>
<translation id="709897737746224366">Αντιστοιχίστε τη ζητούμενη μορφή.</translation>
<translation id="7223624360433298498">χρόνος που παρήλθε</translation>
<translation id="7263440858009898357">Επιλέξτε ένα στοιχείο από τη λίστα.</translation>
+<translation id="727747134524199931">κεφαλίδα στήλης</translation>
<translation id="7364796246159120393">Επιλογή αρχείου</translation>
<translation id="739024184232394898">Άλλες…</translation>
+<translation id="7491962110804786152">καρτέλα</translation>
<translation id="7673697353781729403">Ώρες</translation>
<translation id="7720026100085573005">χρόνος που απομένει</translation>
<translation id="7740016676195725605">διακοπή προβολής υπότιτλων</translation>
<translation id="7740050170769002709">Περιεχόμενο HTML</translation>
<translation id="7789962463072032349">παύση</translation>
+<translation id="7802800022689234070">τρίγωνο εμφάνισης/απόκρυψης</translation>
<translation id="7888071071722539607">Συμπεριλάβετε το σύμβολο "<ph name="ATSIGN" />" στη διεύθυνση ηλεκτρονικού ταχυδρομείου. Από τη διεύθυνση "<ph name="INVALIDADDRESS" />" λείπει το σύμβολο "<ph name="ATSIGN" />".</translation>
+<translation id="7891486169920085145">διαχωριστής</translation>
<translation id="795667975304826397">Δεν επιλέχθηκε κανένα αρχείο.</translation>
<translation id="8053789581856978548">αναζήτηση πεδίου κειμένου</translation>
<translation id="8115662671911883373">έναρξη προβολής υπότιτλων</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">χάρτης εικόνας</translation>
<translation id="835897206747267392">Μη έγκυρη τιμή.</translation>
<translation id="838869780401515933">ενεργοποίηση</translation>
+<translation id="8433900881053900389">γραμμή εργαλείων</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> αρχεία</translation>
<translation id="8451268428117625855">Επιλέξτε ένα αρχείο.</translation>
+<translation id="8461852803063341183">κουμπί επιλογής</translation>
+<translation id="8511325616783751178">αναπτυσσόμενο κουμπί</translation>
<translation id="8534579021159131403">Λεπτά</translation>
<translation id="8541249477527128034">έλεγχος μέσων</translation>
<translation id="8583702881314752957">λίστα ορισμών</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">έναρξη αναπαραγωγής</translation>
<translation id="8851136666856101339">κύριο</translation>
<translation id="8987927404178983737">Μήνας</translation>
+<translation id="9002566407876343676">ανοίγω</translation>
<translation id="901493112792887934">τρέχων χρόνος σε δευτερόλεπτα</translation>
<translation id="9048119486235211610">πλοήγηση</translation>
<translation id="9050748414552849310">εμφάνιση υπότιτλων</translation>
+<translation id="9062295712474918030">έγγραφο</translation>
<translation id="9108370397979208512">μαθηματικά</translation>
<translation id="9132465097189459683">Άλλες…</translation>
+<translation id="9138385573473225930">ειδοποίηση</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, από τις <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">κελί</translation>
+<translation id="966787709310836684">μενού</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_en-GB.xtb b/chromium/content/app/strings/translations/content_strings_en-GB.xtb
index b819bc38e70..8e9b336a81d 100644
--- a/chromium/content/app/strings/translations/content_strings_en-GB.xtb
+++ b/chromium/content/app/strings/translations/content_strings_en-GB.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="en-GB">
<translation id="1014825444426747588">blank</translation>
+<translation id="1018939186200882850">menu item</translation>
<translation id="1020833440720551630">mute audio track</translation>
<translation id="10623998915015855">toggle button</translation>
<translation id="1088086359088493902">Seconds</translation>
<translation id="1171774979989969504">Please enter an email address.</translation>
<translation id="1188858454923323853">complementary</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">slider</translation>
<translation id="1235745349614807883">Clear Recent Searches</translation>
+<translation id="1281252709823657822">dialogue</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">region</translation>
<translation id="1591562245178063882">This month</translation>
<translation id="1637811476055996098">Choose Files</translation>
+<translation id="167575180612809735">busy indicator</translation>
<translation id="1729654308190250600">Please enter a non-empty email address.</translation>
<translation id="1758486001363313524">Other...</translation>
+<translation id="1806710327868736751">alert_dialogue</translation>
+<translation id="1821985195704844674">tree grid</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">play on remote device</translation>
<translation id="1842960171412779397">select</translation>
+<translation id="1880518467580572141">outline</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">status</translation>
<translation id="1938124657309484470">Value must be <ph name="MAXIMUM_DATE_OR_TIME" /> or earlier.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Please shorten this text to <ph name="MAX_CHARACTERS" /> characters or less (you are currently using <ph name="CURRENT_LENGTH" /> characters).</translation>
<translation id="2247351761944213033">Week <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">Tick box</translation>
+<translation id="2335594187091864976">date and time picker</translation>
<translation id="248395913932153421">Day</translation>
<translation id="2507943997699731163">Please fill in this field.</translation>
+<translation id="2508569020611168319">tab list</translation>
<translation id="2548326553472216322">No recent searches</translation>
<translation id="2572483411312390101">play</translation>
<translation id="2613802280814924224">Please enter a valid value. The nearest valid value is <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">footer</translation>
<translation id="2723001399770238859">audio</translation>
<translation id="2746543609216772311">Value must be <ph name="MINIMUM_DATE_OR_TIME" /> or later.</translation>
+<translation id="2759744352195237655">pop-up button</translation>
<translation id="2761667185364618470">Please tick this box if you want to proceed.</translation>
<translation id="2846343701378493991">1024 (Medium Grade)</translation>
+<translation id="2896972712917208084">radio group</translation>
<translation id="2901282870647571346">current film status</translation>
<translation id="2908441821576996758">Please enter a comma-separated list of email addresses.</translation>
+<translation id="2931838996092594335">click</translation>
+<translation id="2940813599313844715">object</translation>
<translation id="2942448076852699108">highlighted content</translation>
<translation id="3040011195152428237">link</translation>
<translation id="3075154866155599887">Please enter a valid value. The field is incomplete or has an invalid date.</translation>
+<translation id="3078740164268491126">table</translation>
+<translation id="3086746722712840547">note</translation>
<translation id="310520048233152454">Please enter a URL.</translation>
+<translation id="3175736971608411871">timer</translation>
+<translation id="3199563858620722075">combo box</translation>
<translation id="3450233048674729344">Value must be less than or equal to <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">definition</translation>
+<translation id="3557673793733683882">heading <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">number of seconds of film remaining</translation>
<translation id="3706100364254443312">switch</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">term</translation>
<translation id="3822383571486410024">Please lengthen this text to <ph name="MIN_CHARACTERS" /> characters or more (you are currently using <ph name="CURRENT_LENGTH" /> characters).</translation>
<translation id="383465348367842624">A part followed by '<ph name="ATSIGN" />' should not contain the symbol '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="3924558731517983934">application</translation>
+<translation id="3960700977367013758">scroll bar</translation>
<translation id="4103419683916926126">Milliseconds</translation>
+<translation id="4151657705144244502">graphic</translation>
<translation id="4201051445878709314">Show previous month</translation>
<translation id="4202807286478387388">jump</translation>
+<translation id="421884353938374759">colour picker</translation>
+<translation id="4248100235867064564">menu bar</translation>
+<translation id="4254339807215791271">content info</translation>
<translation id="4360991593054037559">Please enter a valid value. The two nearest valid values are <ph name="VALID_VALUE_LOW" /> and <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">menu button</translation>
<translation id="4522570452068850558">Details</translation>
<translation id="4597532268155981612">form</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">A part following '<ph name="ATSIGN" />' should not contain the symbol '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="4757246831282535685">tab panel</translation>
<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Please enter a number.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> selected</translation>
<translation id="49969490063480558">Please enter a part following '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' is incomplete.</translation>
+<translation id="5034860022980953847">progress indicator</translation>
<translation id="5048533449481078685">list marker</translation>
<translation id="5117590920725113268">Show next month</translation>
+<translation id="512758898067543763">row header</translation>
<translation id="5164977714490026579">Value must be greater than or equal to <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Please enter a part followed by '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' is incomplete.</translation>
+<translation id="5317780077021120954">Save</translation>
<translation id="5406322316791861025">figure</translation>
+<translation id="5453733299334684579">tree item</translation>
<translation id="5466621249238537318">Please select one or more files.</translation>
<translation id="5468998798572797635">exit full screen</translation>
<translation id="5476505524087279545">untick</translation>
+<translation id="5516424706154626233">date picker</translation>
<translation id="5546461542133609677">un-mute</translation>
+<translation id="561939826962581046">time</translation>
<translation id="5641012560118721995">pause playback</translation>
+<translation id="5643186887447432888">button</translation>
<translation id="5843503607508392247">Other...</translation>
<translation id="5939518447894949180">Reset</translation>
<translation id="5944544982112848342">2048 (High Grade)</translation>
<translation id="5966707198760109579">Week</translation>
-<translation id="598301471034819706">address</translation>
+<translation id="5987525920412732405">spin button</translation>
<translation id="6015796118275082299">Year</translation>
+<translation id="6023896073578205740">list box</translation>
<translation id="6101327004457443354">un-mute audio track</translation>
<translation id="6119846243427417423">activate</translation>
+<translation id="6164829606128959761">meter</translation>
<translation id="6270583010843788609">film timeline thumb</translation>
<translation id="6359256949422175976">film time scrubber thumb</translation>
<translation id="6398862346408813489">Show month selection panel</translation>
<translation id="6404546809543547843">audio time scrubber</translation>
+<translation id="648732519525291180">time picker</translation>
<translation id="658823671542763450">enter full screen</translation>
+<translation id="6637586476836377253">log</translation>
<translation id="6643016212128521049">Clear</translation>
<translation id="6663448176199120256">Recent Searches</translation>
<translation id="668171684555832681">Other...</translation>
<translation id="6692633176391053278">stepper</translation>
+<translation id="6739588121953935928">ruler</translation>
+<translation id="6755330956360078551">tooltip</translation>
<translation id="6820355525329141109">Couldn't load plug-in.</translation>
<translation id="6843725295806269523">mute</translation>
<translation id="6845533974506654842">press</translation>
<translation id="6853785296079745596">hide closed captions</translation>
+<translation id="6885760532393684712">directory</translation>
+<translation id="6934078000481955284">blockquote</translation>
<translation id="7057186640035488495">film time</translation>
<translation id="709897737746224366">Please match the format requested.</translation>
<translation id="7223624360433298498">elapsed time</translation>
<translation id="7263440858009898357">Please select an item in the list.</translation>
+<translation id="727747134524199931">column header</translation>
<translation id="7364796246159120393">Choose file</translation>
<translation id="739024184232394898">Other...</translation>
+<translation id="7491962110804786152">tab</translation>
<translation id="7673697353781729403">Hours</translation>
<translation id="7720026100085573005">remaining time</translation>
<translation id="7740016676195725605">stop displaying closed captions</translation>
<translation id="7740050170769002709">HTML content</translation>
<translation id="7789962463072032349">pause</translation>
+<translation id="7802800022689234070">disclosure triangle</translation>
<translation id="7888071071722539607">Please include an '<ph name="ATSIGN" />' in the email address. '<ph name="INVALIDADDRESS" />' is missing an '<ph name="ATSIGN" />'.</translation>
+<translation id="7891486169920085145">splitter</translation>
<translation id="795667975304826397">No file chosen</translation>
<translation id="8053789581856978548">search text field</translation>
<translation id="8115662671911883373">start displaying closed captions</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">image map</translation>
<translation id="835897206747267392">Invalid value.</translation>
<translation id="838869780401515933">tick</translation>
+<translation id="8433900881053900389">toolbar</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> files</translation>
<translation id="8451268428117625855">Please select a file.</translation>
+<translation id="8461852803063341183">radio button</translation>
+<translation id="8511325616783751178">drop-down button</translation>
<translation id="8534579021159131403">Minutes</translation>
<translation id="8541249477527128034">media control</translation>
<translation id="8583702881314752957">definition list</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">begin playback</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8987927404178983737">Month</translation>
+<translation id="9002566407876343676">open</translation>
<translation id="901493112792887934">current time in seconds</translation>
<translation id="9048119486235211610">navigation</translation>
<translation id="9050748414552849310">show closed captions</translation>
+<translation id="9062295712474918030">document</translation>
<translation id="9108370397979208512">math</translation>
<translation id="9132465097189459683">Other...</translation>
+<translation id="9138385573473225930">alert</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, starting on <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">cell</translation>
+<translation id="966787709310836684">menu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_es-419.xtb b/chromium/content/app/strings/translations/content_strings_es-419.xtb
index be71f95b901..64452f99bf6 100644
--- a/chromium/content/app/strings/translations/content_strings_es-419.xtb
+++ b/chromium/content/app/strings/translations/content_strings_es-419.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="es-419">
<translation id="1014825444426747588">espacio en blanco</translation>
+<translation id="1018939186200882850">elemento del menú</translation>
<translation id="1020833440720551630">silenciar pista de audio</translation>
<translation id="10623998915015855">botón de activación</translation>
<translation id="1088086359088493902">Segundos</translation>
<translation id="1171774979989969504">Ingresa una dirección de correo electrónico.</translation>
<translation id="1188858454923323853">complementario</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">control deslizante</translation>
<translation id="1235745349614807883">Eliminar búsquedas recientes</translation>
+<translation id="1281252709823657822">diálogo</translation>
<translation id="1342835525016946179">artículo</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">región</translation>
<translation id="1591562245178063882">Este mes</translation>
<translation id="1637811476055996098">Elegir archivos</translation>
+<translation id="167575180612809735">indicador de ocupado</translation>
<translation id="1729654308190250600">Ingresa una dirección de correo electrónico que no esté vacía.</translation>
<translation id="1758486001363313524">Otra...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">cuadrícula de árbol</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">jugar en el dispositivo remoto</translation>
<translation id="1842960171412779397">seleccionar</translation>
+<translation id="1880518467580572141">contorno</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">estado</translation>
<translation id="1938124657309484470">El valor debe ser igual o anterior a <ph name="MAXIMUM_DATE_OR_TIME" />.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Acorta este texto a <ph name="MAX_CHARACTERS" /> caracteres o menos (actualmente estás usando <ph name="CURRENT_LENGTH" /> caracteres).</translation>
<translation id="2247351761944213033">Semana <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">casilla de verificación</translation>
+<translation id="2335594187091864976">selector de fecha y hora</translation>
<translation id="248395913932153421">Día</translation>
<translation id="2507943997699731163">Completa este campo</translation>
+<translation id="2508569020611168319">lista de pestañas</translation>
<translation id="2548326553472216322">No hay búsquedas recientes</translation>
<translation id="2572483411312390101">reproducir</translation>
<translation id="2613802280814924224">Ingresa un valor válido. El valor válido más aproximado es <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">pie de página</translation>
<translation id="2723001399770238859">audio</translation>
<translation id="2746543609216772311">El valor debe ser igual o posterior a <ph name="MINIMUM_DATE_OR_TIME" />.</translation>
+<translation id="2759744352195237655">botón con ventana emergente</translation>
<translation id="2761667185364618470">Controla esta casilla si deseas continuar.</translation>
<translation id="2846343701378493991">1024 (Mediano)</translation>
+<translation id="2896972712917208084">grupo de botones de selección</translation>
<translation id="2901282870647571346">estado actual de la película</translation>
<translation id="2908441821576996758">Ingresa una lista de direcciones de correo electrónico separadas por coma</translation>
+<translation id="2931838996092594335">hacer clic</translation>
+<translation id="2940813599313844715">objeto</translation>
<translation id="2942448076852699108">contenido destacado</translation>
<translation id="3040011195152428237">enlace</translation>
<translation id="3075154866155599887">Debes ingresar un valor válido. El campo está incompleto o contiene una fecha no válida.</translation>
+<translation id="3078740164268491126">tabla</translation>
+<translation id="3086746722712840547">nota</translation>
<translation id="310520048233152454">Ingresa una URL.</translation>
+<translation id="3175736971608411871">cronómetro</translation>
+<translation id="3199563858620722075">cuadro combinado</translation>
<translation id="3450233048674729344">El valor debe ser menor de o igual a <ph name="MAXIMUM" /></translation>
<translation id="3486220673238053218">definición</translation>
+<translation id="3557673793733683882">encabezado <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">cantidad de segundos restantes de la película</translation>
<translation id="3706100364254443312">cambiar</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">término</translation>
<translation id="3822383571486410024">Alarga el texto a <ph name="MIN_CHARACTERS" /> o más caracteres (actualmente, usas <ph name="CURRENT_LENGTH" /> caracteres).</translation>
<translation id="383465348367842624">El texto antes del signo "<ph name="ATSIGN" />" no debe incluir el símbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3924558731517983934">aplicación</translation>
+<translation id="3960700977367013758">barra de desplazamiento</translation>
<translation id="4103419683916926126">Milisegundos</translation>
+<translation id="4151657705144244502">gráfico</translation>
<translation id="4201051445878709314">Mostrar el mes anterior</translation>
<translation id="4202807286478387388">saltar</translation>
+<translation id="421884353938374759">selector de color</translation>
+<translation id="4248100235867064564">barra de menús</translation>
+<translation id="4254339807215791271">información del contenido</translation>
<translation id="4360991593054037559">Ingresa un valor válido. Los dos valores válidos más aproximados son <ph name="VALID_VALUE_LOW" /> y <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">botón de menú</translation>
<translation id="4522570452068850558">Detalles</translation>
<translation id="4597532268155981612">formulario</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">El texto después del signo "<ph name="ATSIGN" />" no debe incluir el símbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4757246831282535685">panel de pestañas</translation>
<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Debes ingresar un número.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> elementos seleccionados</translation>
<translation id="49969490063480558">Ingresa texto después del signo "<ph name="ATSIGN" />". La dirección "<ph name="INVALIDADDRESS" />" está incompleta.</translation>
+<translation id="5034860022980953847">indicador de progreso</translation>
<translation id="5048533449481078685">marcador de listas</translation>
<translation id="5117590920725113268">Mostrar el mes siguiente</translation>
+<translation id="512758898067543763">encabezado de fila</translation>
<translation id="5164977714490026579">El valor debe ser mayor de o igual a <ph name="MINIMUM" /></translation>
<translation id="5307600278924710095">Ingresa texto antes del signo "<ph name="ATSIGN" />". La dirección "<ph name="INVALIDADDRESS" />" está incompleta.</translation>
+<translation id="5317780077021120954">Guardar</translation>
<translation id="5406322316791861025">figura</translation>
+<translation id="5453733299334684579">elemento de árbol</translation>
<translation id="5466621249238537318">Selecciona uno o más archivos.</translation>
<translation id="5468998798572797635">salir de pantalla completa</translation>
<translation id="5476505524087279545">desmarcar</translation>
+<translation id="5516424706154626233">selector de fecha</translation>
<translation id="5546461542133609677">desactivar silencio</translation>
+<translation id="561939826962581046">time</translation>
<translation id="5641012560118721995">pausar reproducción</translation>
+<translation id="5643186887447432888">botón</translation>
<translation id="5843503607508392247">Otra...</translation>
<translation id="5939518447894949180">Restablecer</translation>
<translation id="5944544982112848342">2048 (Grado elevado)</translation>
<translation id="5966707198760109579">Semana</translation>
-<translation id="598301471034819706">dirección</translation>
+<translation id="5987525920412732405">botón de control numérico</translation>
<translation id="6015796118275082299">Año</translation>
+<translation id="6023896073578205740">cuadro de lista</translation>
<translation id="6101327004457443354">desactivar silencio de la pista de audio</translation>
<translation id="6119846243427417423">activar</translation>
+<translation id="6164829606128959761">medidor</translation>
<translation id="6270583010843788609">miniatura de línea de tiempo de la película</translation>
<translation id="6359256949422175976">miniatura del control deslizante de duración de la película</translation>
<translation id="6398862346408813489">Mostrar el panel de selección de meses</translation>
<translation id="6404546809543547843">control deslizante de duración del audio</translation>
+<translation id="648732519525291180">selector de hora</translation>
<translation id="658823671542763450">ingresar a pantalla completa</translation>
+<translation id="6637586476836377253">rgstr</translation>
<translation id="6643016212128521049">Borrar</translation>
<translation id="6663448176199120256">Búsquedas recientes</translation>
<translation id="668171684555832681">Otro...</translation>
<translation id="6692633176391053278">secuenciador</translation>
+<translation id="6739588121953935928">regla</translation>
+<translation id="6755330956360078551">información sobre la herramienta</translation>
<translation id="6820355525329141109">No se pudo cargar el complemento.</translation>
<translation id="6843725295806269523">silencio</translation>
<translation id="6845533974506654842">hacer clic</translation>
<translation id="6853785296079745596">ocultar los subtítulos</translation>
+<translation id="6885760532393684712">directorio</translation>
+<translation id="6934078000481955284">bloque entrecomillado</translation>
<translation id="7057186640035488495">horario de película</translation>
<translation id="709897737746224366">Haz coincidir el formato solicitado.</translation>
<translation id="7223624360433298498">tiempo transcurrido</translation>
<translation id="7263440858009898357">Selecciona un elemento de la lista</translation>
+<translation id="727747134524199931">encabezado de columna</translation>
<translation id="7364796246159120393">Seleccionar archivo</translation>
<translation id="739024184232394898">Otra...</translation>
+<translation id="7491962110804786152">tab</translation>
<translation id="7673697353781729403">Horas</translation>
<translation id="7720026100085573005">tiempo restante</translation>
<translation id="7740016676195725605">dejar de mostrar subtítulos</translation>
<translation id="7740050170769002709">Contenido HTML</translation>
<translation id="7789962463072032349">pausa</translation>
+<translation id="7802800022689234070">triángulo desplegable</translation>
<translation id="7888071071722539607">Incluye un signo "<ph name="ATSIGN" />" en la dirección de correo electrónico. La dirección "<ph name="INVALIDADDRESS" />" no incluye el signo "<ph name="ATSIGN" />".</translation>
+<translation id="7891486169920085145">separador</translation>
<translation id="795667975304826397">No se eligió archivo</translation>
<translation id="8053789581856978548">campo de texto de búsqueda</translation>
<translation id="8115662671911883373">empezar a mostrar subtítulos</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">mapa de imágenes</translation>
<translation id="835897206747267392">Valor no válido.</translation>
<translation id="838869780401515933">marcar</translation>
+<translation id="8433900881053900389">barra de herramientas</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> archivos</translation>
<translation id="8451268428117625855">Selecciona un archivo.</translation>
+<translation id="8461852803063341183">botón de selección</translation>
+<translation id="8511325616783751178">botón desplegable</translation>
<translation id="8534579021159131403">Minutos</translation>
<translation id="8541249477527128034">control de medios</translation>
<translation id="8583702881314752957">lista de definiciones</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">comenzar la reproducción</translation>
<translation id="8851136666856101339">ppal</translation>
<translation id="8987927404178983737">Mes</translation>
+<translation id="9002566407876343676">abrir</translation>
<translation id="901493112792887934">tiempo actual en segundos</translation>
<translation id="9048119486235211610">navegación</translation>
<translation id="9050748414552849310">mostrar subtítulos</translation>
+<translation id="9062295712474918030">documento</translation>
<translation id="9108370397979208512">expr mtmtc</translation>
<translation id="9132465097189459683">Otra...</translation>
+<translation id="9138385573473225930">alerta</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, a partir del <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">celda</translation>
+<translation id="966787709310836684">menú</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_es.xtb b/chromium/content/app/strings/translations/content_strings_es.xtb
index 72266f3acd4..68e999fce5c 100644
--- a/chromium/content/app/strings/translations/content_strings_es.xtb
+++ b/chromium/content/app/strings/translations/content_strings_es.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="es">
<translation id="1014825444426747588">vacío</translation>
+<translation id="1018939186200882850">elemento de menú</translation>
<translation id="1020833440720551630">silenciar pista de audio</translation>
<translation id="10623998915015855">botón de activación</translation>
<translation id="1088086359088493902">Segundos</translation>
<translation id="1171774979989969504">Introduce una dirección de correo electrónico</translation>
<translation id="1188858454923323853">complementario</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">control deslizante</translation>
<translation id="1235745349614807883">Eliminar búsquedas recientes</translation>
+<translation id="1281252709823657822">cuadro de diálogo</translation>
<translation id="1342835525016946179">artículo</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">región</translation>
<translation id="1591562245178063882">Este mes</translation>
<translation id="1637811476055996098">Elegir archivos</translation>
+<translation id="167575180612809735">indicador de carga</translation>
<translation id="1729654308190250600">Introduce una dirección de correo electrónico que no esté vacía.</translation>
<translation id="1758486001363313524">Otra...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">cuadrícula de árbol</translation>
<translation id="1822429046913737220">A.M./P.M.</translation>
<translation id="1832974991323546415">reproducir en dispositivo remoto</translation>
<translation id="1842960171412779397">seleccionar</translation>
+<translation id="1880518467580572141">contorno</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">estado</translation>
<translation id="1938124657309484470">El valor debe ser igual o anterior a <ph name="MAXIMUM_DATE_OR_TIME" />.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Reduce la longitud de este texto a <ph name="MAX_CHARACTERS" /> caracteres o menos (actualmente, el texto tiene <ph name="CURRENT_LENGTH" /> caracteres)</translation>
<translation id="2247351761944213033">Semana <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">casilla de verificación</translation>
+<translation id="2335594187091864976">selector de fecha y hora</translation>
<translation id="248395913932153421">Día</translation>
<translation id="2507943997699731163">Completa este campo</translation>
+<translation id="2508569020611168319">lista de pestañas</translation>
<translation id="2548326553472216322">No hay búsquedas recientes</translation>
<translation id="2572483411312390101">reproducir</translation>
<translation id="2613802280814924224">Introduce un valor válido. El valor válido más aproximado es <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">pie de página</translation>
<translation id="2723001399770238859">audio</translation>
<translation id="2746543609216772311">El valor debe ser igual o posterior a <ph name="MINIMUM_DATE_OR_TIME" />.</translation>
+<translation id="2759744352195237655">botón emergente</translation>
<translation id="2761667185364618470">Selecciona esta casilla de verificación si quieres continuar</translation>
<translation id="2846343701378493991">1024 (Mediano)</translation>
+<translation id="2896972712917208084">grupo de selección</translation>
<translation id="2901282870647571346">estado actual de la película</translation>
<translation id="2908441821576996758">Introduce una lista de direcciones de correo electrónico separada por comas</translation>
+<translation id="2931838996092594335">hacer clic</translation>
+<translation id="2940813599313844715">objeto</translation>
<translation id="2942448076852699108">contenido resaltado</translation>
<translation id="3040011195152428237">enlace</translation>
<translation id="3075154866155599887">Debes introducir un valor válido. El campo está incompleto o incluye una fecha no válida.</translation>
+<translation id="3078740164268491126">tabla</translation>
+<translation id="3086746722712840547">nota</translation>
<translation id="310520048233152454">Introduce una URL</translation>
+<translation id="3175736971608411871">temporizador</translation>
+<translation id="3199563858620722075">cuadro combinado</translation>
<translation id="3450233048674729344">El valor debe inferior o igual a <ph name="MAXIMUM" /></translation>
<translation id="3486220673238053218">definición</translation>
+<translation id="3557673793733683882">encabezado <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">número de segundos restantes de la película</translation>
<translation id="3706100364254443312">interruptor</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">término</translation>
<translation id="3822383571486410024">Aumenta la longitud del texto a <ph name="MIN_CHARACTERS" /> caracteres como mínimo (actualmente, el texto tiene <ph name="CURRENT_LENGTH" /> caracteres).</translation>
<translation id="383465348367842624">El texto seguido del signo "<ph name="ATSIGN" />" no debe incluir el símbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3924558731517983934">aplicación</translation>
+<translation id="3960700977367013758">barra de desplazamiento</translation>
<translation id="4103419683916926126">Millisegundos</translation>
+<translation id="4151657705144244502">gráfico</translation>
<translation id="4201051445878709314">Mostrar mes anterior</translation>
<translation id="4202807286478387388">saltar</translation>
+<translation id="421884353938374759">selector de color</translation>
+<translation id="4248100235867064564">barra de menús</translation>
+<translation id="4254339807215791271">información del contenido</translation>
<translation id="4360991593054037559">Introduce un valor válido. Los dos valores válidos más aproximados son <ph name="VALID_VALUE_LOW" /> y <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">botón de menú</translation>
<translation id="4522570452068850558">Detalles</translation>
<translation id="4597532268155981612">formulario</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">El texto detrás del signo "<ph name="ATSIGN" />" no debe incluir el símbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4757246831282535685">panel de pestaña</translation>
<translation id="4763480195061959176">vídeo</translation>
+<translation id="479989351350248267">buscar</translation>
<translation id="4812940957355064477">Debes introducir un número.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> seleccionados</translation>
<translation id="49969490063480558">Introduce texto detrás del signo "<ph name="ATSIGN" />". La dirección "<ph name="INVALIDADDRESS" />" está incompleta.</translation>
+<translation id="5034860022980953847">indicador de progreso</translation>
<translation id="5048533449481078685">marcador de listas</translation>
<translation id="5117590920725113268">Mostrar mes siguiente</translation>
+<translation id="512758898067543763">encabezado de fila</translation>
<translation id="5164977714490026579">El valor debe superior o igual a <ph name="MINIMUM" /></translation>
<translation id="5307600278924710095">Introduce texto seguido del signo "<ph name="ATSIGN" />". La dirección "<ph name="INVALIDADDRESS" />" está incompleta.</translation>
+<translation id="5317780077021120954">Guardar</translation>
<translation id="5406322316791861025">cifra</translation>
+<translation id="5453733299334684579">elemento del árbol</translation>
<translation id="5466621249238537318">Selecciona uno o varios archivos</translation>
<translation id="5468998798572797635">salir de pantalla completa</translation>
<translation id="5476505524087279545">desmarcar</translation>
+<translation id="5516424706154626233">selector de fecha</translation>
<translation id="5546461542133609677">activar sonido</translation>
+<translation id="561939826962581046">time</translation>
<translation id="5641012560118721995">pausar reproducción</translation>
+<translation id="5643186887447432888">botón</translation>
<translation id="5843503607508392247">Otra...</translation>
<translation id="5939518447894949180">Restablecer</translation>
<translation id="5944544982112848342">2048 (Grado elevado)</translation>
<translation id="5966707198760109579">Semana</translation>
-<translation id="598301471034819706">dirección</translation>
+<translation id="5987525920412732405">botón de control numérico</translation>
<translation id="6015796118275082299">Año</translation>
+<translation id="6023896073578205740">cuadro de lista</translation>
<translation id="6101327004457443354">activar sonido de la pista de audio</translation>
<translation id="6119846243427417423">activar</translation>
+<translation id="6164829606128959761">medidor</translation>
<translation id="6270583010843788609">miniatura de línea de tiempo de la película</translation>
<translation id="6359256949422175976">miniatura del control deslizante de duración de la película</translation>
<translation id="6398862346408813489">Mostrar panel para seleccionar el mes</translation>
<translation id="6404546809543547843">control deslizante de duración de audio</translation>
+<translation id="648732519525291180">selector de hora</translation>
<translation id="658823671542763450">activar pantalla completa</translation>
+<translation id="6637586476836377253">registro</translation>
<translation id="6643016212128521049">Eliminar</translation>
<translation id="6663448176199120256">Búsquedas recientes</translation>
<translation id="668171684555832681">Otros...</translation>
<translation id="6692633176391053278">secuenciador</translation>
+<translation id="6739588121953935928">regla</translation>
+<translation id="6755330956360078551">descripción emergente</translation>
<translation id="6820355525329141109">No se ha podido cargar el complemento.</translation>
<translation id="6843725295806269523">silenciar</translation>
<translation id="6845533974506654842">pulsar</translation>
<translation id="6853785296079745596">ocultar subtítulos opcionales</translation>
+<translation id="6885760532393684712">directorio</translation>
+<translation id="6934078000481955284">blockquote</translation>
<translation id="7057186640035488495">cronología de la película</translation>
<translation id="709897737746224366">Utiliza un formato que coincida con el solicitado</translation>
<translation id="7223624360433298498">tiempo transcurrido</translation>
<translation id="7263440858009898357">Selecciona un elemento de la lista</translation>
+<translation id="727747134524199931">encabezado de columna</translation>
<translation id="7364796246159120393">Seleccionar archivo</translation>
<translation id="739024184232394898">Otra...</translation>
+<translation id="7491962110804786152">tabulador</translation>
<translation id="7673697353781729403">Horas</translation>
<translation id="7720026100085573005">tiempo restante</translation>
<translation id="7740016676195725605">dejar de mostrar subtítulos opcionales</translation>
<translation id="7740050170769002709">Contenido HTML</translation>
<translation id="7789962463072032349">pausar</translation>
+<translation id="7802800022689234070">triángulo de revelación</translation>
<translation id="7888071071722539607">Incluye un signo "<ph name="ATSIGN" />" en la dirección de correo electrónico. La dirección "<ph name="INVALIDADDRESS" />" no incluye el signo "<ph name="ATSIGN" />".</translation>
+<translation id="7891486169920085145">divisor</translation>
<translation id="795667975304826397">Ningún archivo seleccionado</translation>
<translation id="8053789581856978548">campo para buscar texto</translation>
<translation id="8115662671911883373">iniciar la visualización de subtítulos opcionales</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">mapa de imágenes</translation>
<translation id="835897206747267392">Valor no válido</translation>
<translation id="838869780401515933">marcar</translation>
+<translation id="8433900881053900389">barra de herramientas</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> archivos</translation>
<translation id="8451268428117625855">Selecciona un archivo</translation>
+<translation id="8461852803063341183">botón de selección</translation>
+<translation id="8511325616783751178">botón desplegable</translation>
<translation id="8534579021159131403">Minutos</translation>
<translation id="8541249477527128034">control de medios</translation>
<translation id="8583702881314752957">lista de definiciones</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">iniciar reproducción</translation>
<translation id="8851136666856101339">principal</translation>
<translation id="8987927404178983737">Mes</translation>
+<translation id="9002566407876343676">abrir</translation>
<translation id="901493112792887934">tiempo actual en segundos</translation>
<translation id="9048119486235211610">navegación</translation>
<translation id="9050748414552849310">mostrar subtítulos opcionales</translation>
+<translation id="9062295712474918030">documento</translation>
<translation id="9108370397979208512">expresión matemática</translation>
<translation id="9132465097189459683">Otra...</translation>
+<translation id="9138385573473225930">alerta</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, a partir del <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">celda</translation>
+<translation id="966787709310836684">menú</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_et.xtb b/chromium/content/app/strings/translations/content_strings_et.xtb
index 43053ac56a0..40771dbbd46 100644
--- a/chromium/content/app/strings/translations/content_strings_et.xtb
+++ b/chromium/content/app/strings/translations/content_strings_et.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="et">
<translation id="1014825444426747588">tühi</translation>
+<translation id="1018939186200882850">menüü-üksus</translation>
<translation id="1020833440720551630">heliraja vaigistamine</translation>
<translation id="10623998915015855">ümberlülitusnupp</translation>
<translation id="1088086359088493902">Sekundid</translation>
<translation id="1171774979989969504">Sisestage meiliaadress.</translation>
<translation id="1188858454923323853">täiendav</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">liugur</translation>
<translation id="1235745349614807883">Kustuta viimased otsingud</translation>
+<translation id="1281252709823657822">dialoog</translation>
<translation id="1342835525016946179">artikkel</translation>
<translation id="1359897965706325498">bänner</translation>
<translation id="1589122976691792535">piirkond</translation>
<translation id="1591562245178063882">See kuu</translation>
<translation id="1637811476055996098">Vali failid</translation>
+<translation id="167575180612809735">hõivatuse näidik</translation>
<translation id="1729654308190250600">Sisestage mittetühi e-posti aadress.</translation>
<translation id="1758486001363313524">Muu ...</translation>
+<translation id="1806710327868736751">hoiatusdialoog</translation>
+<translation id="1821985195704844674">puuruudustik</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">kaugseadmes esitamine</translation>
<translation id="1842960171412779397">vali</translation>
+<translation id="1880518467580572141">kontuur</translation>
<translation id="1921819250265091946">pp</translation>
<translation id="1930711995431081526">olek</translation>
<translation id="1938124657309484470">Väärtus peab olema <ph name="MAXIMUM_DATE_OR_TIME" /> või varasem.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Lühendage seda teksti <ph name="MAX_CHARACTERS" /> tähemärgini või rohkem (praegu kasutate <ph name="CURRENT_LENGTH" /> tähemärki).</translation>
<translation id="2247351761944213033">Nädal <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">märkeruut</translation>
+<translation id="2335594187091864976">kuupäeva ja kellaaja valija</translation>
<translation id="248395913932153421">päev</translation>
<translation id="2507943997699731163">Täitke see väli.</translation>
+<translation id="2508569020611168319">vahelehtede loend</translation>
<translation id="2548326553472216322">Pole viimaseid otsingud</translation>
<translation id="2572483411312390101">esitus</translation>
<translation id="2613802280814924224">Sisestage kehtiv väärtus. Lähim kehtiv väärtus on <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">jalus</translation>
<translation id="2723001399770238859">heli</translation>
<translation id="2746543609216772311">Väärtus peab olema <ph name="MINIMUM_DATE_OR_TIME" /> või hilisem.</translation>
+<translation id="2759744352195237655">hüpikunupp</translation>
<translation id="2761667185364618470">Märkige see ruut, kui soovite jätkata.</translation>
<translation id="2846343701378493991">1024 (keskmine)</translation>
+<translation id="2896972712917208084">raadionuppude grupp</translation>
<translation id="2901282870647571346">video praegune olek</translation>
<translation id="2908441821576996758">Sisestage meiliaadresside loend komadega eraldatult.</translation>
+<translation id="2931838996092594335">klõpsake</translation>
+<translation id="2940813599313844715">objekt</translation>
<translation id="2942448076852699108">esiletõstetud sisu</translation>
<translation id="3040011195152428237">link</translation>
<translation id="3075154866155599887">Sisestage kehtiv väärtus. Väli on täitmata või sisaldab sobimatut kuupäeva.</translation>
+<translation id="3078740164268491126">tabel</translation>
+<translation id="3086746722712840547">märge</translation>
<translation id="310520048233152454">Sisestage URL.</translation>
+<translation id="3175736971608411871">taimer</translation>
+<translation id="3199563858620722075">liitkast</translation>
<translation id="3450233048674729344">Väärtus peab olema väiksem või võrdne <ph name="MAXIMUM" />-ga.</translation>
<translation id="3486220673238053218">definitsioon</translation>
+<translation id="3557673793733683882">päis <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">video järelejäänud aeg sekundites</translation>
<translation id="3706100364254443312">lüliti</translation>
<translation id="3732799496749320381">kk</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">termin</translation>
<translation id="3822383571486410024">Pikendage teksti vähemalt <ph name="MIN_CHARACTERS" /> tähemärgini (kasutate praegu <ph name="CURRENT_LENGTH" /> tähemärki).</translation>
<translation id="383465348367842624">Märgile „<ph name="ATSIGN" />” eelnev osa ei tohi sisaldada sümbolit „<ph name="INVALIDCHARACTER" />”.</translation>
+<translation id="3924558731517983934">rakendus</translation>
+<translation id="3960700977367013758">kerimisriba</translation>
<translation id="4103419683916926126">Millisekundid</translation>
+<translation id="4151657705144244502">graafika</translation>
<translation id="4201051445878709314">Eelmise kuu kuvamine</translation>
<translation id="4202807286478387388">liigu</translation>
+<translation id="421884353938374759">värvivalija</translation>
+<translation id="4248100235867064564">menüüriba</translation>
+<translation id="4254339807215791271">sisu teave</translation>
<translation id="4360991593054037559">Sisestage kehtiv väärtus. Kaks lähimat kehtivat väärtust on <ph name="VALID_VALUE_LOW" /> ja <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">menüünupp</translation>
<translation id="4522570452068850558">Üksikasjad</translation>
<translation id="4597532268155981612">vorm</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Märgile „<ph name="ATSIGN" />” järgnev osa ei tohi sisaldada sümbolit „<ph name="INVALIDCHARACTER" />”.</translation>
+<translation id="4757246831282535685">vahelehepaneel</translation>
<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">otsing</translation>
<translation id="4812940957355064477">Sisestage arv.</translation>
<translation id="4975562563186953947">Valitud on <ph name="SELECTED_COUNT" /> üksust</translation>
<translation id="49969490063480558">Sisestage märgile „<ph name="ATSIGN" />” järgnev osa. Aadress „<ph name="INVALIDADDRESS" />” pole täielik.</translation>
+<translation id="5034860022980953847">edenemise näidik</translation>
<translation id="5048533449481078685">loendilooja</translation>
<translation id="5117590920725113268">Järgmise kuu kuvamine</translation>
+<translation id="512758898067543763">rea päis</translation>
<translation id="5164977714490026579">Väärtus peab olema suurem või võrdne <ph name="MINIMUM" />-ga.</translation>
<translation id="5307600278924710095">Sisestage märgile „<ph name="ATSIGN" />” eelnev osa. Aadress „<ph name="INVALIDADDRESS" />” pole täielik.</translation>
+<translation id="5317780077021120954">Salvesta</translation>
<translation id="5406322316791861025">joonis</translation>
+<translation id="5453733299334684579">puuüksus</translation>
<translation id="5466621249238537318">Valige üks või mitu faili.</translation>
<translation id="5468998798572797635">täisekraanilt väljumine</translation>
<translation id="5476505524087279545">eemalda mrgistus</translation>
+<translation id="5516424706154626233">kuupäeva valija</translation>
<translation id="5546461542133609677">vaigistuse tühistamine</translation>
+<translation id="561939826962581046">time</translation>
<translation id="5641012560118721995">taasesituse peatamine</translation>
+<translation id="5643186887447432888">nupp</translation>
<translation id="5843503607508392247">Muu ...</translation>
<translation id="5939518447894949180">Lähtesta</translation>
<translation id="5944544982112848342">2048 (kõrge)</translation>
<translation id="5966707198760109579">Nädal</translation>
-<translation id="598301471034819706">aadress</translation>
+<translation id="5987525920412732405">pöördnupp</translation>
<translation id="6015796118275082299">Aasta</translation>
+<translation id="6023896073578205740">loendikast</translation>
<translation id="6101327004457443354">heliraja vaigistamise tühistamine</translation>
<translation id="6119846243427417423">aktiveeri</translation>
+<translation id="6164829606128959761">mõõdik</translation>
<translation id="6270583010843788609">video ajajoone pisipilt</translation>
<translation id="6359256949422175976">video ajakursori pisipilt</translation>
<translation id="6398862346408813489">Kuu valikupaneeli kuvamine</translation>
<translation id="6404546809543547843">heli ajamõõdik</translation>
+<translation id="648732519525291180">kellaaja valija</translation>
<translation id="658823671542763450">kuvamine täisekraanil</translation>
+<translation id="6637586476836377253">logi</translation>
<translation id="6643016212128521049">Tühjenda</translation>
<translation id="6663448176199120256">Viimased otsingud</translation>
<translation id="668171684555832681">Muu...</translation>
<translation id="6692633176391053278">stepper</translation>
+<translation id="6739588121953935928">joonlaud</translation>
+<translation id="6755330956360078551">tööriistavihje</translation>
<translation id="6820355525329141109">Pistikprogrammi ei saanud laadida.</translation>
<translation id="6843725295806269523">vaigista</translation>
<translation id="6845533974506654842">vajuta</translation>
<translation id="6853785296079745596">subtiitrite peitmine</translation>
+<translation id="6885760532393684712">kataloog</translation>
+<translation id="6934078000481955284">plokktsitaat</translation>
<translation id="7057186640035488495">video aeg</translation>
<translation id="709897737746224366">Vastendage nõutav vorming.</translation>
<translation id="7223624360433298498">möödunud aeg</translation>
<translation id="7263440858009898357">Valige loendist element.</translation>
+<translation id="727747134524199931">veeru päis</translation>
<translation id="7364796246159120393">Vali fail</translation>
<translation id="739024184232394898">Muu ...</translation>
+<translation id="7491962110804786152">Tabulaator</translation>
<translation id="7673697353781729403">Tunnid</translation>
<translation id="7720026100085573005">järelejäänud aeg</translation>
<translation id="7740016676195725605">subtiitrite kuvamise peatamine</translation>
<translation id="7740050170769002709">HTML-sisu</translation>
<translation id="7789962463072032349">peata</translation>
+<translation id="7802800022689234070">avalikustamise kolmnurk</translation>
<translation id="7888071071722539607">Lisage e-posti aadressile märk „<ph name="ATSIGN" />”. Aadressist „<ph name="INVALIDADDRESS" />” puudub märk „<ph name="ATSIGN" />”.</translation>
+<translation id="7891486169920085145">jagaja</translation>
<translation id="795667975304826397">Pole valitud</translation>
<translation id="8053789581856978548">otsinguteksti väli</translation>
<translation id="8115662671911883373">subtiitrite kuvamise alustamine</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">hüperpilt</translation>
<translation id="835897206747267392">Kehtetu väärtus.</translation>
<translation id="838869780401515933">mrgista</translation>
+<translation id="8433900881053900389">tööriistariba</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> faili</translation>
<translation id="8451268428117625855">Valige üks fail.</translation>
+<translation id="8461852803063341183">raadionupp</translation>
+<translation id="8511325616783751178">rippmenüü nupp</translation>
<translation id="8534579021159131403">Minutid</translation>
<translation id="8541249477527128034">meedia juhtimine</translation>
<translation id="8583702881314752957">definitsioonide loend</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">taasesituse alustamine</translation>
<translation id="8851136666856101339">pea</translation>
<translation id="8987927404178983737">kuu</translation>
+<translation id="9002566407876343676">avage</translation>
<translation id="901493112792887934">praegune aeg sekundites</translation>
<translation id="9048119486235211610">navigeerimine</translation>
<translation id="9050748414552849310">subtiitrite kuvamine</translation>
+<translation id="9062295712474918030">dokument</translation>
<translation id="9108370397979208512">matemaatika</translation>
<translation id="9132465097189459683">Muu ...</translation>
+<translation id="9138385573473225930">hoiatus</translation>
<translation id="9155987714137265666"><ph name="WEEK" /> alates kuupäevast <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">lahter</translation>
+<translation id="966787709310836684">menüü</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_fa.xtb b/chromium/content/app/strings/translations/content_strings_fa.xtb
index 22bd4ba5559..bf1cc8ff553 100644
--- a/chromium/content/app/strings/translations/content_strings_fa.xtb
+++ b/chromium/content/app/strings/translations/content_strings_fa.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="fa">
<translation id="1014825444426747588">خالی</translation>
+<translation id="1018939186200882850">مورد منو</translation>
<translation id="1020833440720551630">بیصداکردن تراک صوتی</translation>
<translation id="10623998915015855">دکمه تغییر حالت</translation>
<translation id="1088086359088493902">ثانیه</translation>
<translation id="1171774979989969504">لطفاً یک آدرس ایمیل وارد کنید.</translation>
<translation id="1188858454923323853">تکمیلی</translation>
+<translation id="1206619573307042055">نوشتار متحرک روی صفحه</translation>
+<translation id="1206693055195146388">لغزنده</translation>
<translation id="1235745349614807883">پاک کردن جستجوهای اخیر</translation>
+<translation id="1281252709823657822">کادر گفتگو</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">برنما</translation>
<translation id="1589122976691792535">منطقه</translation>
<translation id="1591562245178063882">این ماه</translation>
<translation id="1637811476055996098">انتخاب فایل‌ها</translation>
+<translation id="167575180612809735">نشانگر مشغول</translation>
<translation id="1729654308190250600">لطفاً یک آدرس ایمیل غیرخالی وارد کنید.</translation>
<translation id="1758486001363313524">موارد دیگر...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">شبکه درختی</translation>
<translation id="1822429046913737220">ق.ظ/ب.ظ</translation>
<translation id="1832974991323546415">پخش در دستگاه راه دور</translation>
<translation id="1842960171412779397">انتخاب</translation>
+<translation id="1880518467580572141">طرح کلی</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">وضعیت</translation>
<translation id="1938124657309484470">مقدار باید <ph name="MAXIMUM_DATE_OR_TIME" /> یا قبل از آن باشد.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">لطفاً این متن را به اندازه <ph name="MAX_CHARACTERS" /> نویسه یا کمتر کوتاه کنید (شما در حال حاضر از <ph name="CURRENT_LENGTH" /> نویسه استفاده می‌کنید).</translation>
<translation id="2247351761944213033">هفته <ph name="WEEKNUMBER" />، <ph name="YEAR" /></translation>
<translation id="2291999235780842123">کادر تأیید</translation>
+<translation id="2335594187091864976">انتخابگر تاریخ و زمان</translation>
<translation id="248395913932153421">روز</translation>
<translation id="2507943997699731163">لطفاً این قسمت را تکمیل کنید.</translation>
+<translation id="2508569020611168319">فهرست برگه</translation>
<translation id="2548326553472216322">جستجوی جدیدی وجود ندارد</translation>
<translation id="2572483411312390101">پخش</translation>
<translation id="2613802280814924224">لطفاً یک مقدار معتبر وارد کنید. نزدیک‌ترین مقدار معتبر <ph name="VALID_VALUE" /> است.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">پانویس</translation>
<translation id="2723001399770238859">صدا</translation>
<translation id="2746543609216772311">مقدار باید <ph name="MINIMUM_DATE_OR_TIME" /> یا بعد از آن باشد.</translation>
+<translation id="2759744352195237655">دکمه بازشو</translation>
<translation id="2761667185364618470">درصورتی‌که می‌خواهید ادامه دهید، این کادر را انتخاب کنید.</translation>
<translation id="2846343701378493991">1024 (درجه متوسط)</translation>
+<translation id="2896972712917208084">گروه رادیویی</translation>
<translation id="2901282870647571346">وضعیت کنونی فیلم</translation>
<translation id="2908441821576996758">لطفاً لیستی از آدرس‌های ایمیل که با کاما از هم جدا شده‌اند را وارد کنید.</translation>
+<translation id="2931838996092594335">کلیک کنید</translation>
+<translation id="2940813599313844715">شیء</translation>
<translation id="2942448076852699108">محتوای برجسته شده</translation>
<translation id="3040011195152428237">پیوند</translation>
<translation id="3075154866155599887">لطفاً یک مقدار معتبر وارد کنید. این قسمت کامل نیست و یا تاریخ نامعتبر است.</translation>
+<translation id="3078740164268491126">جدول</translation>
+<translation id="3086746722712840547">نت</translation>
<translation id="310520048233152454">لطفاً یک نشانی وب وارد کنید.</translation>
+<translation id="3175736971608411871">تایمر</translation>
+<translation id="3199563858620722075">کادر ترکیبی</translation>
<translation id="3450233048674729344">مقدار باید کمتر یا برابر با <ph name="MAXIMUM" /> باشد.</translation>
<translation id="3486220673238053218">معنی</translation>
+<translation id="3557673793733683882">عنوان <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">مقدار ثانیه‌های باقیمانده فیلم</translation>
<translation id="3706100364254443312">تعویض</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">اصطلاح</translation>
<translation id="3822383571486410024">لطفاً این نوشتار را به <ph name="MIN_CHARACTERS" /> نویسه یا بیشتر افزایش دهید (درحال حاضر از <ph name="CURRENT_LENGTH" /> نویسه استفاده می‌کنید).</translation>
<translation id="383465348367842624">قسمت قبل از «<ph name="ATSIGN" />» نباید حاوی نماد «<ph name="INVALIDCHARACTER" />» باشد.</translation>
+<translation id="3924558731517983934">برنامه</translation>
+<translation id="3960700977367013758">نوار پیمایش</translation>
<translation id="4103419683916926126">میلی‌ ثانیه</translation>
+<translation id="4151657705144244502">گرافیک</translation>
<translation id="4201051445878709314">نمایش ماه قبلی</translation>
<translation id="4202807286478387388">پرش</translation>
+<translation id="421884353938374759">انتخابگر رنگ</translation>
+<translation id="4248100235867064564">نوار منو</translation>
+<translation id="4254339807215791271">اطلاعات محتوا</translation>
<translation id="4360991593054037559">لطفاً یک مقدار معتبر وارد کنید. نزدیک‌ترین مقادیر معتبر <ph name="VALID_VALUE_LOW" /> و <ph name="VALID_VALUE_HIGHER" /> هستند.</translation>
+<translation id="4413860115965805769">دکمه منو</translation>
<translation id="4522570452068850558">جزئیات</translation>
<translation id="4597532268155981612">فرم</translation>
+<translation id="4661075872484491155">درخت</translation>
<translation id="4664250907885839816">قسمت بعد از «<ph name="ATSIGN" />» نباید حاوی نماد «<ph name="INVALIDCHARACTER" />» باشد.</translation>
+<translation id="4757246831282535685">پانل برگه</translation>
<translation id="4763480195061959176">ویدیو</translation>
+<translation id="479989351350248267">جستجو</translation>
<translation id="4812940957355064477">لطفاً شماره‌ای را وارد کنید.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> انتخاب شد</translation>
<translation id="49969490063480558">لطفاً قسمت بعد از «<ph name="ATSIGN" />» را وارد کنید. «<ph name="INVALIDADDRESS" />» ناقص است.</translation>
-<translation id="5048533449481078685">علامت گذار لیست</translation>
+<translation id="5034860022980953847">نشانگر پیشرفت</translation>
+<translation id="5048533449481078685">علامت گذار فهرست</translation>
<translation id="5117590920725113268">نمایش ماه بعدی</translation>
+<translation id="512758898067543763">عنوان ردیف</translation>
<translation id="5164977714490026579">مقدار باید بیشتر یا مساوی با <ph name="MINIMUM" /> باشد.</translation>
<translation id="5307600278924710095">لطفاً قسمت قبل از «<ph name="ATSIGN" />» را وارد کنید. «<ph name="INVALIDADDRESS" />» ناقص است.</translation>
+<translation id="5317780077021120954">ذخیره</translation>
<translation id="5406322316791861025">شکل</translation>
+<translation id="5453733299334684579">مورد درختی</translation>
<translation id="5466621249238537318">لطفاً یک یا چند فایل را انتخاب کنید.</translation>
<translation id="5468998798572797635">خروج از حالت تمام صفحه</translation>
<translation id="5476505524087279545">برداشتن علامت</translation>
+<translation id="5516424706154626233">انتخابگر تاریخ</translation>
<translation id="5546461542133609677">صدادارکردن</translation>
+<translation id="561939826962581046">زمان</translation>
<translation id="5641012560118721995">مکث بازپخش</translation>
+<translation id="5643186887447432888">دکمه</translation>
<translation id="5843503607508392247">موارد دیگر...</translation>
<translation id="5939518447894949180">بازنشانی</translation>
<translation id="5944544982112848342">2048 (درجه بالا)</translation>
<translation id="5966707198760109579">هفته</translation>
-<translation id="598301471034819706">آدرس</translation>
+<translation id="5987525920412732405">دکمه چرخش</translation>
<translation id="6015796118275082299">سال</translation>
+<translation id="6023896073578205740">کادر فهرست</translation>
<translation id="6101327004457443354">صدادارکردن تراک صوتی</translation>
<translation id="6119846243427417423">فعالسازی</translation>
+<translation id="6164829606128959761">متر</translation>
<translation id="6270583010843788609">نشانگر خط زمان فیلم</translation>
<translation id="6359256949422175976">نشانگر حذف‌کننده زمان فیلم</translation>
<translation id="6398862346408813489">نمایش پانل انتخاب ماه</translation>
<translation id="6404546809543547843">انتخابگر زمان صدا</translation>
+<translation id="648732519525291180">انتخابگر زمان</translation>
<translation id="658823671542763450">رفتن به حالت تمام صفحه</translation>
+<translation id="6637586476836377253">log</translation>
<translation id="6643016212128521049">پاک کردن</translation>
<translation id="6663448176199120256">جستجوهای جدید</translation>
<translation id="668171684555832681">دیگر...</translation>
<translation id="6692633176391053278">گام به گام</translation>
+<translation id="6739588121953935928">خط‌کش</translation>
+<translation id="6755330956360078551">نکته ابزار</translation>
<translation id="6820355525329141109">افزایه بارگیری نشد.</translation>
<translation id="6843725295806269523">بیصداکردن</translation>
<translation id="6845533974506654842">فشار دادن</translation>
<translation id="6853785296079745596">پنهان کردن توصیف‌های بسته</translation>
+<translation id="6885760532393684712">فهرست راهنما</translation>
+<translation id="6934078000481955284">نقل‌قول</translation>
<translation id="7057186640035488495">زمان فیلم</translation>
<translation id="709897737746224366">لطفاً با قالب درخواستی مطابقت دهید.</translation>
<translation id="7223624360433298498">مدت سپری شده</translation>
-<translation id="7263440858009898357">لطفاً یک مورد را در لیست انتخاب کنید.</translation>
+<translation id="7263440858009898357">لطفاً یک مورد را در فهرست انتخاب کنید.</translation>
+<translation id="727747134524199931">عنوان ستون</translation>
<translation id="7364796246159120393">انتخاب فایل</translation>
<translation id="739024184232394898">موارد دیگر...</translation>
+<translation id="7491962110804786152">برگه</translation>
<translation id="7673697353781729403">ساعت</translation>
<translation id="7720026100085573005">زمان باقی‌مانده</translation>
<translation id="7740016676195725605">توقف نمایش توصیف‌های بسته</translation>
<translation id="7740050170769002709">‏محتوای HTML</translation>
<translation id="7789962463072032349">مکث</translation>
+<translation id="7802800022689234070">مثلث افشا</translation>
<translation id="7888071071722539607">لطفاً نماد «<ph name="ATSIGN" />» را به آدرس ایمیل اضافه کنید. «<ph name="INVALIDADDRESS" />» در «<ph name="ATSIGN" />» موجود نیست.</translation>
+<translation id="7891486169920085145">تقسیم‌کننده</translation>
<translation id="795667975304826397">فایلی انتخاب نشده است</translation>
<translation id="8053789581856978548">فیلد نوشتاری جستجو</translation>
<translation id="8115662671911883373">شروع به نمایش توصیف‌های بسته</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">نقشه تصویر</translation>
<translation id="835897206747267392">مقدار نامعتبر.</translation>
<translation id="838869780401515933">علامت‌گذاری</translation>
+<translation id="8433900881053900389">نوار ابزار</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> فایل</translation>
<translation id="8451268428117625855">لطفاً یک فایل انتخاب کنید.</translation>
+<translation id="8461852803063341183">دکمه رادیو</translation>
+<translation id="8511325616783751178">دکمه کرکره‌ای</translation>
<translation id="8534579021159131403">دقیقه</translation>
<translation id="8541249477527128034">کنترل رسانه</translation>
<translation id="8583702881314752957">فهرست معنی‌ها</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">شروع بازپخش</translation>
<translation id="8851136666856101339">اصلی</translation>
<translation id="8987927404178983737">ماه</translation>
+<translation id="9002566407876343676">باز کنید</translation>
<translation id="901493112792887934">زمان کنونی به ثانیه</translation>
<translation id="9048119486235211610">پیمایش</translation>
<translation id="9050748414552849310">نمایش توصیف‌های بسته</translation>
+<translation id="9062295712474918030">سند</translation>
<translation id="9108370397979208512">حساب</translation>
<translation id="9132465097189459683">موارد دیگر...</translation>
+<translation id="9138385573473225930">هشدار</translation>
<translation id="9155987714137265666"><ph name="WEEK" />، شروع از <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">سلول</translation>
+<translation id="966787709310836684">منو</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_fi.xtb b/chromium/content/app/strings/translations/content_strings_fi.xtb
index 774105b60d5..a3a22cf0588 100644
--- a/chromium/content/app/strings/translations/content_strings_fi.xtb
+++ b/chromium/content/app/strings/translations/content_strings_fi.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="fi">
<translation id="1014825444426747588">tyhjä</translation>
+<translation id="1018939186200882850">valikkokohde</translation>
<translation id="1020833440720551630">mykistä ääniraita</translation>
<translation id="10623998915015855">vaihtopainike</translation>
<translation id="1088086359088493902">Sekuntia</translation>
<translation id="1171774979989969504">Anna sähköpostiosoite.</translation>
<translation id="1188858454923323853">täydentävä</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">liukusäädin</translation>
<translation id="1235745349614807883">Poista viimeisimmät haut</translation>
+<translation id="1281252709823657822">valintaikkuna</translation>
<translation id="1342835525016946179">artikkeli</translation>
<translation id="1359897965706325498">banneri</translation>
<translation id="1589122976691792535">alue</translation>
<translation id="1591562245178063882">Tässä kuussa</translation>
<translation id="1637811476055996098">Valitse tiedostot</translation>
+<translation id="167575180612809735">varausosoitin</translation>
<translation id="1729654308190250600">Kirjoita ei-tyhjä sähköpostiosoite.</translation>
<translation id="1758486001363313524">Muu...</translation>
+<translation id="1806710327868736751">ilmoitusvalintaikkuna</translation>
+<translation id="1821985195704844674">puuruudukko</translation>
<translation id="1822429046913737220">AP/IP</translation>
<translation id="1832974991323546415">toista etälaitteella</translation>
<translation id="1842960171412779397">Valitse</translation>
+<translation id="1880518467580572141">hahmotelma</translation>
<translation id="1921819250265091946">pp</translation>
<translation id="1930711995431081526">tila</translation>
<translation id="1938124657309484470">Arvon on oltava <ph name="MAXIMUM_DATE_OR_TIME" /> tai aiempi.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Lyhennä tämä teksti alle <ph name="MAX_CHARACTERS" /> merkkiin (tällä hetkellä käytössä <ph name="CURRENT_LENGTH" /> merkkiä).</translation>
<translation id="2247351761944213033">Viikko <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">valintaruutu</translation>
+<translation id="2335594187091864976">päivämäärän ja ajan valitsin</translation>
<translation id="248395913932153421">Päivä</translation>
<translation id="2507943997699731163">Täytä tämä kenttä.</translation>
+<translation id="2508569020611168319">välilehtiluettelo</translation>
<translation id="2548326553472216322">Ei viimeisimpiä hakuja</translation>
<translation id="2572483411312390101">toista</translation>
<translation id="2613802280814924224">Syötä kelvollinen arvo. Lähin kelvollinen arvo on <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">alaviite</translation>
<translation id="2723001399770238859">ääni</translation>
<translation id="2746543609216772311">Arvon on oltava <ph name="MINIMUM_DATE_OR_TIME" /> tai myöhempi.</translation>
+<translation id="2759744352195237655">ponnahduspainike</translation>
<translation id="2761667185364618470">Valitse tämä ruutu jatkaaksesi.</translation>
<translation id="2846343701378493991">1024 (keskitaso)</translation>
+<translation id="2896972712917208084">valintapainikeryhmä</translation>
<translation id="2901282870647571346">elokuvan nykyinen tila</translation>
<translation id="2908441821576996758">Anna pilkuilla erotettu sähköpostiosoitteiden luettelo.</translation>
+<translation id="2931838996092594335">klikata</translation>
+<translation id="2940813599313844715">kohde</translation>
<translation id="2942448076852699108">korostettu sisältö</translation>
<translation id="3040011195152428237">linkki</translation>
<translation id="3075154866155599887">Anna kelvollinen arvo. Kentän arvo on puutteellinen tai annettu päivä on virheellinen.</translation>
+<translation id="3078740164268491126">taulukko</translation>
+<translation id="3086746722712840547">huom.</translation>
<translation id="310520048233152454">Anna URL-osoite.</translation>
+<translation id="3175736971608411871">ajastin</translation>
+<translation id="3199563858620722075">yhdistelmäruutu</translation>
<translation id="3450233048674729344">Arvon tulee olla pienempi tai yhtä suuri kuin <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">määritelmä</translation>
+<translation id="3557673793733683882">otsikko <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">elokuvan jäljellä oleva aika sekunteina</translation>
<translation id="3706100364254443312">vaihto</translation>
<translation id="3732799496749320381">kk</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">termi</translation>
<translation id="3822383571486410024">Pidennä tämä teksti yli <ph name="MIN_CHARACTERS" /> merkkiin (tällä hetkellä käytössä <ph name="CURRENT_LENGTH" /> merkkiä).</translation>
<translation id="383465348367842624"><ph name="ATSIGN" />-osaa ennen tulevassa osassa ei pitäisi olla merkkiä <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="3924558731517983934">sovellus</translation>
+<translation id="3960700977367013758">vierityspalkki</translation>
<translation id="4103419683916926126">Millisekuntia</translation>
+<translation id="4151657705144244502">kuva</translation>
<translation id="4201051445878709314">Näytä edellinen kuukausi</translation>
<translation id="4202807286478387388">siirry</translation>
+<translation id="421884353938374759">värinvalitsin</translation>
+<translation id="4248100235867064564">valikkopalkki</translation>
+<translation id="4254339807215791271">sisällön tiedot</translation>
<translation id="4360991593054037559">Syötä kelvollinen arvo. Kaksi lähintä kelvollista arvoa ovat <ph name="VALID_VALUE_LOW" /> ja <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">valikkopainike</translation>
<translation id="4522570452068850558">Tiedot</translation>
<translation id="4597532268155981612">lomake</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816"><ph name="ATSIGN" />-osan jälkeen tulevassa osassa ei pitäisi olla merkkiä <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="4757246831282535685">välilehtipaneeli</translation>
<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">haku</translation>
<translation id="4812940957355064477">Anna numero.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> valittu</translation>
<translation id="49969490063480558">Lisää <ph name="ATSIGN" />-osaa seuraava osa. <ph name="INVALIDADDRESS" /> on puutteellinen.</translation>
+<translation id="5034860022980953847">etenemisen osoitin</translation>
<translation id="5048533449481078685">luettelon merkitsijä</translation>
<translation id="5117590920725113268">Näytä seuraava kuukausi</translation>
+<translation id="512758898067543763">rivin otsikko</translation>
<translation id="5164977714490026579">Arvon tulee olla suurempi tai yhtä suuri kuin <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Lisää <ph name="ATSIGN" />-osaa ennen tuleva osa. <ph name="INVALIDADDRESS" /> on puutteellinen.</translation>
+<translation id="5317780077021120954">Tallenna</translation>
<translation id="5406322316791861025">kuva</translation>
+<translation id="5453733299334684579">puukohde</translation>
<translation id="5466621249238537318">Valitse vähintään yksi tiedosto.</translation>
<translation id="5468998798572797635">poistu koko näytön tilasta</translation>
<translation id="5476505524087279545">poista valinta</translation>
+<translation id="5516424706154626233">päivämäärän valitsin</translation>
<translation id="5546461542133609677">peruuta mykistys</translation>
+<translation id="561939826962581046">time</translation>
<translation id="5641012560118721995">keskeytä toisto</translation>
+<translation id="5643186887447432888">painike</translation>
<translation id="5843503607508392247">Muu...</translation>
<translation id="5939518447894949180">Tyhjennä</translation>
<translation id="5944544982112848342">2048 (korkea taso)</translation>
<translation id="5966707198760109579">Viikko</translation>
-<translation id="598301471034819706">osoite</translation>
+<translation id="5987525920412732405">pyöräytyspainike</translation>
<translation id="6015796118275082299">Vuosi</translation>
+<translation id="6023896073578205740">luetteloruutu</translation>
<translation id="6101327004457443354">peruuta ääniraidan mykistys</translation>
<translation id="6119846243427417423">aktivoi</translation>
+<translation id="6164829606128959761">mittari</translation>
<translation id="6270583010843788609">elokuvan aikajanan pikkukuva</translation>
<translation id="6359256949422175976">elokuvan ajan säätimen pikkukuva</translation>
<translation id="6398862346408813489">Näytä kuukaudenvalintapaneeli</translation>
<translation id="6404546809543547843">äänen ajan liukusäädin</translation>
+<translation id="648732519525291180">ajan valitsin</translation>
<translation id="658823671542763450">siirry koko näytön tilaan</translation>
+<translation id="6637586476836377253">loki</translation>
<translation id="6643016212128521049">Tyhjennä</translation>
<translation id="6663448176199120256">Viimeisimmät haut</translation>
<translation id="668171684555832681">Joku muu profiili...</translation>
<translation id="6692633176391053278">askellin</translation>
+<translation id="6739588121953935928">viivoitin</translation>
+<translation id="6755330956360078551">työkaluvinkki</translation>
<translation id="6820355525329141109">Laajennuksen lataaminen epäonnistui.</translation>
<translation id="6843725295806269523">äänetön</translation>
<translation id="6845533974506654842">paina</translation>
<translation id="6853785296079745596">piilota tekstitykset</translation>
+<translation id="6885760532393684712">hakemisto</translation>
+<translation id="6934078000481955284">muotoiltu lainaus</translation>
<translation id="7057186640035488495">elokuvan aikajana</translation>
<translation id="709897737746224366">Käytä pyydettyä muotoilua.</translation>
<translation id="7223624360433298498">kulunut aika</translation>
<translation id="7263440858009898357">Valitse kohde luettelosta.</translation>
+<translation id="727747134524199931">sarakkeen otsikko</translation>
<translation id="7364796246159120393">Valitse tiedosto</translation>
<translation id="739024184232394898">Muu...</translation>
+<translation id="7491962110804786152">sarkain</translation>
<translation id="7673697353781729403">Tuntia</translation>
<translation id="7720026100085573005">jäljellä oleva aika</translation>
<translation id="7740016676195725605">älä näytä tekstityksiä</translation>
<translation id="7740050170769002709">HTML-sisältö</translation>
<translation id="7789962463072032349">tauko</translation>
+<translation id="7802800022689234070">näyttämiskolmio</translation>
<translation id="7888071071722539607">Sähköpostiosoitteeseen kuuluu <ph name="ATSIGN" />-osa. Osoitteesta <ph name="INVALIDADDRESS" /> puuttuu <ph name="ATSIGN" />.</translation>
+<translation id="7891486169920085145">jakaja</translation>
<translation id="795667975304826397">Ei valittua tiedostoa</translation>
<translation id="8053789581856978548">hakutekstikenttä</translation>
<translation id="8115662671911883373">näytä tekstitykset</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">kuvakartta</translation>
<translation id="835897206747267392">Virheellinen arvo.</translation>
<translation id="838869780401515933">valitse</translation>
+<translation id="8433900881053900389">työkalupalkki</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> tiedostoa</translation>
<translation id="8451268428117625855">Valitse tiedosto.</translation>
+<translation id="8461852803063341183">valintapainike</translation>
+<translation id="8511325616783751178">avattavan valikon painike</translation>
<translation id="8534579021159131403">Minuuttia</translation>
<translation id="8541249477527128034">median hallinta</translation>
<translation id="8583702881314752957">määritelmäluettelo</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">aloita toisto</translation>
<translation id="8851136666856101339">pää</translation>
<translation id="8987927404178983737">Kuukausi</translation>
+<translation id="9002566407876343676">avata</translation>
<translation id="901493112792887934">nykyinen toistoaika sekunteina</translation>
<translation id="9048119486235211610">navigointi</translation>
<translation id="9050748414552849310">näytä tekstitykset</translation>
+<translation id="9062295712474918030">dokumentti</translation>
<translation id="9108370397979208512">matematiikka</translation>
<translation id="9132465097189459683">Muu...</translation>
+<translation id="9138385573473225930">ilmoitus</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, alkupäivä: <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">solu</translation>
+<translation id="966787709310836684">valikko</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_fil.xtb b/chromium/content/app/strings/translations/content_strings_fil.xtb
index 03a0a8e2f53..d62cc1970e1 100644
--- a/chromium/content/app/strings/translations/content_strings_fil.xtb
+++ b/chromium/content/app/strings/translations/content_strings_fil.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="fil">
<translation id="1014825444426747588">blangko</translation>
+<translation id="1018939186200882850">item sa menu</translation>
<translation id="1020833440720551630">i-mute ang audio track</translation>
<translation id="10623998915015855">button sa pag-toggle</translation>
<translation id="1088086359088493902">Segundo</translation>
<translation id="1171774979989969504">Mangyaring magpasok ng email address.</translation>
<translation id="1188858454923323853">complementary</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">slider</translation>
<translation id="1235745349614807883">Lisiman ang Kasalukuyang Mga Paghahanap</translation>
+<translation id="1281252709823657822">dialog</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">rehiyon</translation>
<translation id="1591562245178063882">Buwang ito</translation>
<translation id="1637811476055996098">Pumili ng Mga File</translation>
+<translation id="167575180612809735">indicator kapag busy</translation>
<translation id="1729654308190250600">Mangyaring maglagay ng isang non-empty na email address.</translation>
<translation id="1758486001363313524">Iba pa...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">tree grid</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">i-play sa malayuang device</translation>
<translation id="1842960171412779397">piliin</translation>
+<translation id="1880518467580572141">balangkas</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">katayuan</translation>
<translation id="1938124657309484470">Dapat <ph name="MAXIMUM_DATE_OR_TIME" /> o mas nauna ang value.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Mangyaring paikliin ang tekstong ito ng <ph name="MAX_CHARACTERS" /> (na) character o mas mababa (kasalukuyan kang gumagamit ng <ph name="CURRENT_LENGTH" /> (na) character).</translation>
<translation id="2247351761944213033">Linggo <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">checkbox</translation>
+<translation id="2335594187091864976">picker ng petsa at oras</translation>
<translation id="248395913932153421">Araw</translation>
<translation id="2507943997699731163">Pakipunan ang field na ito.</translation>
+<translation id="2508569020611168319">listahan ng tab</translation>
<translation id="2548326553472216322">Walang kamakailang mga paghahanap</translation>
<translation id="2572483411312390101">i-play</translation>
<translation id="2613802280814924224">Mangyaring maglagay ng isang wastong value. Ang pinakamalapit na wastong value ay <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">footer</translation>
<translation id="2723001399770238859">audio</translation>
<translation id="2746543609216772311">Dapat <ph name="MINIMUM_DATE_OR_TIME" /> o mas bago ang value.</translation>
+<translation id="2759744352195237655">pop up na button</translation>
<translation id="2761667185364618470">Pakitingnan ang kahon na ito kung gusto mong magpatuloy.</translation>
<translation id="2846343701378493991">1024 (Katamtamang Grado)</translation>
+<translation id="2896972712917208084">pangkat ng radyo</translation>
<translation id="2901282870647571346">kasalukuyang katayuan ng pelikula</translation>
<translation id="2908441821576996758">Mangyaring magpasok ng listahan ng email address na pinaghihiwalay ng kuwit.</translation>
+<translation id="2931838996092594335">i-click</translation>
+<translation id="2940813599313844715">object</translation>
<translation id="2942448076852699108">naka-highlight na content</translation>
<translation id="3040011195152428237">link</translation>
<translation id="3075154866155599887">Mangyaring maglagay ng wastong halaga. Hindi kumpleto ang field o may isang di-wastong petsa.</translation>
+<translation id="3078740164268491126">talahanayan</translation>
+<translation id="3086746722712840547">note</translation>
<translation id="310520048233152454">Mangyaring magpasok ng URL.</translation>
+<translation id="3175736971608411871">timer</translation>
+<translation id="3199563858620722075">combo box</translation>
<translation id="3450233048674729344">Dapat mas mababa kaysa sa o katumbas ng <ph name="MAXIMUM" /> ang halaga.</translation>
<translation id="3486220673238053218">kahulugan</translation>
+<translation id="3557673793733683882">heading <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">bilang ng segundong natitira sa pelikula</translation>
<translation id="3706100364254443312">lumipat</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">termino</translation>
<translation id="3822383571486410024">Pakihabaan ang text na ito hanggang <ph name="MIN_CHARACTERS" /> (na) character o higit pa (kasalukuyan kang gumagamit ng <ph name="CURRENT_LENGTH" /> (na) character).</translation>
<translation id="383465348367842624">Hindi dapat naglalaman ng simbolong '<ph name="INVALIDCHARACTER" />' ang bahagi bago ang '<ph name="ATSIGN" />.'</translation>
+<translation id="3924558731517983934">application</translation>
+<translation id="3960700977367013758">scroll bar</translation>
<translation id="4103419683916926126">Milliseconds</translation>
+<translation id="4151657705144244502">graphic</translation>
<translation id="4201051445878709314">Ipakita ang nakaraang buwan</translation>
<translation id="4202807286478387388">tumalon</translation>
+<translation id="421884353938374759">tagapili ng kulay</translation>
+<translation id="4248100235867064564">menu bar</translation>
+<translation id="4254339807215791271">impormasyon ng content</translation>
<translation id="4360991593054037559">Mangyaring maglagay ng isang wastong value. Ang dalawang pinakamalapit na wastong value ay <ph name="VALID_VALUE_LOW" /> at <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">button ng menu</translation>
<translation id="4522570452068850558">Mga Detalye</translation>
<translation id="4597532268155981612">form</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Hindi dapat naglalaman ng simbolong '<ph name="INVALIDCHARACTER" />' ang bahagi pagkatapos ng '<ph name="ATSIGN" />.'</translation>
+<translation id="4757246831282535685">panel ng tab</translation>
<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Mangyaring maglagay ng numero.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> ang napili</translation>
<translation id="49969490063480558">Mangyaring maglagay ng isang bahagi pagkatapos ng '<ph name="ATSIGN" />.' Hindi kumpleto ang '<ph name="INVALIDADDRESS" />.'</translation>
+<translation id="5034860022980953847">indicator ng pag-usad</translation>
<translation id="5048533449481078685">Ilista ang marker</translation>
<translation id="5117590920725113268">Ipakita ang susunod na buwan</translation>
+<translation id="512758898067543763">header ng row</translation>
<translation id="5164977714490026579">Dapat mas mataas kaysa sa o katumbas ng <ph name="MINIMUM" /> ang halaga.</translation>
<translation id="5307600278924710095">Mangyaring maglagay ng isang bahagi na sinusundan ng '<ph name="ATSIGN" />.' Hindi kumpleto ang '<ph name="INVALIDADDRESS" />.'</translation>
+<translation id="5317780077021120954">I-save</translation>
<translation id="5406322316791861025">anyo</translation>
+<translation id="5453733299334684579">item sa tree</translation>
<translation id="5466621249238537318">Mangyaring pumili ng isa o higit pang mga file.</translation>
<translation id="5468998798572797635">lumabas sa full screen</translation>
<translation id="5476505524087279545">i-uncheck</translation>
+<translation id="5516424706154626233">picker ng petsa</translation>
<translation id="5546461542133609677">i-unmute</translation>
+<translation id="561939826962581046">oras</translation>
<translation id="5641012560118721995">i-pause ang pag-playback</translation>
+<translation id="5643186887447432888">button</translation>
<translation id="5843503607508392247">Iba pa...</translation>
<translation id="5939518447894949180">I-reset</translation>
<translation id="5944544982112848342">2048 (Pinakamataas na Marka)</translation>
<translation id="5966707198760109579">Linggo</translation>
-<translation id="598301471034819706">address</translation>
+<translation id="5987525920412732405">button ng pag-spin</translation>
<translation id="6015796118275082299">Taon</translation>
+<translation id="6023896073578205740">kahon ng listahan</translation>
<translation id="6101327004457443354">i-unmute ang audio track</translation>
<translation id="6119846243427417423">isaaktibo</translation>
+<translation id="6164829606128959761">metro</translation>
<translation id="6270583010843788609">thumb ng timeline ng pelikula</translation>
<translation id="6359256949422175976">thumb ng scrubber ng oras ng pelikula</translation>
<translation id="6398862346408813489">Ipakita ang panel ng pagpipilian ng buwan</translation>
<translation id="6404546809543547843">scrubber ng oras ng audio</translation>
+<translation id="648732519525291180">picker ng petsa</translation>
<translation id="658823671542763450">mag-full screen</translation>
+<translation id="6637586476836377253">log</translation>
<translation id="6643016212128521049">I-clear</translation>
<translation id="6663448176199120256">Kasalukuyang Mga Paghahanap</translation>
<translation id="668171684555832681">Iba pa...</translation>
<translation id="6692633176391053278">stepper</translation>
+<translation id="6739588121953935928">ruler</translation>
+<translation id="6755330956360078551">tooltip</translation>
<translation id="6820355525329141109">Hindi ma-load ang plugin.</translation>
<translation id="6843725295806269523">i-mute</translation>
<translation id="6845533974506654842">pindutin</translation>
<translation id="6853785296079745596">itago ang mga nakasarang caption</translation>
+<translation id="6885760532393684712">direktoryo</translation>
+<translation id="6934078000481955284">blockquote</translation>
<translation id="7057186640035488495">oras ng pelikula</translation>
<translation id="709897737746224366">Pakitugma ang hiniling na format.</translation>
<translation id="7223624360433298498">lumipas na oras</translation>
<translation id="7263440858009898357">Mangyaring pumili ng item sa listahan.</translation>
+<translation id="727747134524199931">header ng column</translation>
<translation id="7364796246159120393">Pumili ng File</translation>
<translation id="739024184232394898">Iba pa...</translation>
+<translation id="7491962110804786152">tab</translation>
<translation id="7673697353781729403">Oras</translation>
<translation id="7720026100085573005">natitirang oras</translation>
<translation id="7740016676195725605">ihinto ang pagpapakita ng mga nakasarang caption</translation>
<translation id="7740050170769002709">HTML na nilalaman</translation>
<translation id="7789962463072032349">i-pause</translation>
+<translation id="7802800022689234070">disclosure triangle</translation>
<translation id="7888071071722539607">Mangyaring magsama ng '<ph name="ATSIGN" />' sa email address. Kulang ng '<ph name="ATSIGN" />' ang '<ph name="INVALIDADDRESS" />.'</translation>
+<translation id="7891486169920085145">splitter</translation>
<translation id="795667975304826397">Walang napiling file</translation>
<translation id="8053789581856978548">text field ng paghahanap</translation>
<translation id="8115662671911883373">simulan ang pagpapakita ng mga nakasarang caption</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">mapa ng imahe</translation>
<translation id="835897206747267392">Di-wastong halaga.</translation>
<translation id="838869780401515933">I-tsek</translation>
+<translation id="8433900881053900389">toolbar</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> mga file</translation>
<translation id="8451268428117625855">Mangyaring pumili ng file.</translation>
+<translation id="8461852803063341183">radio button</translation>
+<translation id="8511325616783751178">button ng drop-down</translation>
<translation id="8534579021159131403">Minuto</translation>
<translation id="8541249477527128034">kontrol sa media</translation>
<translation id="8583702881314752957">listahan ng kahulugan</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">simulan ang pag-playback</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8987927404178983737">Buwan</translation>
+<translation id="9002566407876343676">buksan</translation>
<translation id="901493112792887934">kasalukuyang oras ayon sa segundo</translation>
<translation id="9048119486235211610">navigation</translation>
<translation id="9050748414552849310">ipakita ang mga nakasarang caption</translation>
+<translation id="9062295712474918030">dokumento</translation>
<translation id="9108370397979208512">math</translation>
<translation id="9132465097189459683">Iba pa...</translation>
+<translation id="9138385573473225930">alerto</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, na magsisimula sa <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">cell</translation>
+<translation id="966787709310836684">menu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_fr.xtb b/chromium/content/app/strings/translations/content_strings_fr.xtb
index cbdadaf1b56..4bd0f3abb36 100644
--- a/chromium/content/app/strings/translations/content_strings_fr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_fr.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="fr">
<translation id="1014825444426747588">vide</translation>
+<translation id="1018939186200882850">élément de menu</translation>
<translation id="1020833440720551630">désactiver le son de la piste audio</translation>
<translation id="10623998915015855">bouton d'activation/de désactivation</translation>
<translation id="1088086359088493902">Secondes</translation>
<translation id="1171774979989969504">Veuillez saisir une adresse e-mail.</translation>
<translation id="1188858454923323853">complémentaire</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">curseur</translation>
<translation id="1235745349614807883">Effacer les recherches récentes</translation>
+<translation id="1281252709823657822">boîte de dialogue</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">bannière</translation>
<translation id="1589122976691792535">région</translation>
<translation id="1591562245178063882">Ce mois</translation>
<translation id="1637811476055996098">Sélect. fichiers</translation>
+<translation id="167575180612809735">indicateur d'état "Occupé"</translation>
<translation id="1729654308190250600">Veuillez saisir une adresse e-mail dans le champ correspondant.</translation>
<translation id="1758486001363313524">Autre…</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">arborescence</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">lire sur un appareil à distance</translation>
<translation id="1842960171412779397">sélectionner</translation>
+<translation id="1880518467580572141">vue d'ensemble</translation>
<translation id="1921819250265091946">jj</translation>
<translation id="1930711995431081526">état</translation>
<translation id="1938124657309484470">La date ou l'heure doit être égale ou antérieure à "<ph name="MAXIMUM_DATE_OR_TIME" />".</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Veuillez réduire ce texte à <ph name="MAX_CHARACTERS" /> caractères maximum (il compte actuellement <ph name="CURRENT_LENGTH" /> caractères).</translation>
<translation id="2247351761944213033">Semaine <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">case à cocher</translation>
+<translation id="2335594187091864976">outil de sélection de la date et de l'heure</translation>
<translation id="248395913932153421">Jour</translation>
<translation id="2507943997699731163">Veuillez renseigner ce champ.</translation>
+<translation id="2508569020611168319">liste d'onglets</translation>
<translation id="2548326553472216322">Aucune recherche récente</translation>
<translation id="2572483411312390101">lire</translation>
<translation id="2613802280814924224">Veuillez saisir une valeur valide. La valeur valide la plus proche est "<ph name="VALID_VALUE" />".</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">pied de page</translation>
<translation id="2723001399770238859">audio</translation>
<translation id="2746543609216772311">La date ou l'heure doit être égale ou postérieure à "<ph name="MINIMUM_DATE_OR_TIME" />".</translation>
+<translation id="2759744352195237655">bouton pop-up</translation>
<translation id="2761667185364618470">Veuillez cocher cette case si vous souhaitez continuer.</translation>
<translation id="2846343701378493991">1024 (sécurité moyenne)</translation>
+<translation id="2896972712917208084">groupe de cases d'option</translation>
<translation id="2901282870647571346">état actuel du film</translation>
<translation id="2908441821576996758">Veuillez saisir une liste d'adresses e-mail séparées par une virgule.</translation>
+<translation id="2931838996092594335">cliquer</translation>
+<translation id="2940813599313844715">objet</translation>
<translation id="2942448076852699108">contenu en surbrillance</translation>
<translation id="3040011195152428237">Lien</translation>
<translation id="3075154866155599887">Veuillez saisir une valeur valide. Le champ n'est pas complet ou contient une date non valide.</translation>
+<translation id="3078740164268491126">tableau</translation>
+<translation id="3086746722712840547">remarque</translation>
<translation id="310520048233152454">Veuillez saisir une URL.</translation>
+<translation id="3175736971608411871">minuteur</translation>
+<translation id="3199563858620722075">boîte combinée</translation>
<translation id="3450233048674729344">Cette valeur doit être inférieure ou égale à <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">définition</translation>
+<translation id="3557673793733683882">titre <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">nombre de secondes du film restantes</translation>
<translation id="3706100364254443312">interrupteur</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">terme</translation>
<translation id="3822383571486410024">Veuillez allonger ce texte pour qu'il comporte au moins <ph name="MIN_CHARACTERS" /> caractères. Il en compte actuellement <ph name="CURRENT_LENGTH" />.</translation>
<translation id="383465348367842624">La partie suivie du symbole "<ph name="ATSIGN" />" ne doit pas contenir le caractère "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3924558731517983934">application</translation>
+<translation id="3960700977367013758">barre de défilement</translation>
<translation id="4103419683916926126">Millisecondes</translation>
+<translation id="4151657705144244502">élément graphique</translation>
<translation id="4201051445878709314">Afficher le mois précédent</translation>
<translation id="4202807286478387388">accéder</translation>
+<translation id="421884353938374759">palette couleurs</translation>
+<translation id="4248100235867064564">barre de menu</translation>
+<translation id="4254339807215791271">infos sur le contenu</translation>
<translation id="4360991593054037559">Veuillez saisir une valeur valide. Les deux valeurs valides les plus proches sont "<ph name="VALID_VALUE_LOW" />" et "<ph name="VALID_VALUE_HIGHER" />".</translation>
+<translation id="4413860115965805769">bouton de menu</translation>
<translation id="4522570452068850558">Détails</translation>
<translation id="4597532268155981612">formulaire</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">La partie précédée du symbole "<ph name="ATSIGN" />" ne doit pas contenir le caractère "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4757246831282535685">panneau des onglets</translation>
<translation id="4763480195061959176">vidéo</translation>
+<translation id="479989351350248267">rechercher</translation>
<translation id="4812940957355064477">Veuillez saisir un nombre.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> élément(s) sélectionné(s)</translation>
<translation id="49969490063480558">Veuillez saisir la partie manquante après le symbole "<ph name="ATSIGN" />". L'adresse "<ph name="INVALIDADDRESS" />" est incomplète.</translation>
+<translation id="5034860022980953847">indicateur de progression</translation>
<translation id="5048533449481078685">marqueur de liste</translation>
<translation id="5117590920725113268">Afficher le mois suivant</translation>
+<translation id="512758898067543763">en-tête de ligne</translation>
<translation id="5164977714490026579">Cette valeur doit être supérieure ou égale à <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Veuillez saisir la partie manquante avant le caractère "<ph name="ATSIGN" />". L'adresse "<ph name="INVALIDADDRESS" />" est incomplète.</translation>
+<translation id="5317780077021120954">Enregistrer</translation>
<translation id="5406322316791861025">nombre</translation>
+<translation id="5453733299334684579">élément d'arborescence</translation>
<translation id="5466621249238537318">Veuillez sélectionner un ou plusieurs fichiers.</translation>
<translation id="5468998798572797635">quitter le mode plein écran</translation>
<translation id="5476505524087279545">décocher</translation>
+<translation id="5516424706154626233">outil de sélection de la date</translation>
<translation id="5546461542133609677">réactiver le son</translation>
+<translation id="561939826962581046">horodatage</translation>
<translation id="5641012560118721995">interrompre la lecture</translation>
+<translation id="5643186887447432888">bouton</translation>
<translation id="5843503607508392247">Autre…</translation>
<translation id="5939518447894949180">Réinitialiser</translation>
<translation id="5944544982112848342">2048 (haute sécurité)</translation>
<translation id="5966707198760109579">Semaine</translation>
-<translation id="598301471034819706">adresse</translation>
+<translation id="5987525920412732405">bouton toupie</translation>
<translation id="6015796118275082299">Année</translation>
+<translation id="6023896073578205740">zone de liste</translation>
<translation id="6101327004457443354">réactiver le son de la piste audio</translation>
<translation id="6119846243427417423">activer</translation>
+<translation id="6164829606128959761">outil de mesure</translation>
<translation id="6270583010843788609">vignette de la chronologie du film</translation>
<translation id="6359256949422175976">vignette de la barre de défilement de la durée du film</translation>
<translation id="6398862346408813489">Afficher le panneau de sélection du mois</translation>
<translation id="6404546809543547843">curseur durée audio</translation>
+<translation id="648732519525291180">outil de sélection de l'heure</translation>
<translation id="658823671542763450">activer le mode plein écran</translation>
+<translation id="6637586476836377253">journal</translation>
<translation id="6643016212128521049">Effacer</translation>
<translation id="6663448176199120256">Recherches récentes</translation>
<translation id="668171684555832681">Autre...</translation>
<translation id="6692633176391053278">curseur</translation>
+<translation id="6739588121953935928">règle</translation>
+<translation id="6755330956360078551">info-bulle</translation>
<translation id="6820355525329141109">Impossible de charger le plug-in.</translation>
<translation id="6843725295806269523">muet</translation>
<translation id="6845533974506654842">appuyer</translation>
<translation id="6853785296079745596">masquer les sous-titres</translation>
+<translation id="6885760532393684712">annuaire</translation>
+<translation id="6934078000481955284">bloc de citation</translation>
<translation id="7057186640035488495">durée du film</translation>
<translation id="709897737746224366">Veuillez respecter le format requis.</translation>
<translation id="7223624360433298498">temps écoulé</translation>
<translation id="7263440858009898357">Sélectionnez un élément dans la liste.</translation>
+<translation id="727747134524199931">en-tête de colonne</translation>
<translation id="7364796246159120393">Choisissez un fichier</translation>
<translation id="739024184232394898">Autre…</translation>
+<translation id="7491962110804786152">tabulation</translation>
<translation id="7673697353781729403">Heures</translation>
<translation id="7720026100085573005">temps restant</translation>
<translation id="7740016676195725605">ne plus afficher les sous-titres</translation>
<translation id="7740050170769002709">Contenu HTML</translation>
<translation id="7789962463072032349">pause</translation>
+<translation id="7802800022689234070">triangle d'expansion</translation>
<translation id="7888071071722539607">Veuillez inclure "<ph name="ATSIGN" />" dans l'adresse e-mail. Il manque un symbole "<ph name="ATSIGN" />" dans "<ph name="INVALIDADDRESS" />".</translation>
+<translation id="7891486169920085145">séparateur</translation>
<translation id="795667975304826397">Aucun fichier choisi</translation>
<translation id="8053789581856978548">champ de recherche de texte</translation>
<translation id="8115662671911883373">commencer à afficher les sous-titres</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">image map</translation>
<translation id="835897206747267392">Valeur incorrecte</translation>
<translation id="838869780401515933">cocher</translation>
+<translation id="8433900881053900389">barre d'outils</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> fichiers</translation>
<translation id="8451268428117625855">Veuillez sélectionner un fichier.</translation>
+<translation id="8461852803063341183">case d'option</translation>
+<translation id="8511325616783751178">bouton déroulant</translation>
<translation id="8534579021159131403">Minutes</translation>
<translation id="8541249477527128034">commande multimédia</translation>
<translation id="8583702881314752957">liste de définitions</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">commencer la lecture</translation>
<translation id="8851136666856101339">principal</translation>
<translation id="8987927404178983737">Mois</translation>
+<translation id="9002566407876343676">ouvrir</translation>
<translation id="901493112792887934">durée actuelle en secondes</translation>
<translation id="9048119486235211610">navigation</translation>
<translation id="9050748414552849310">afficher les sous-titres</translation>
+<translation id="9062295712474918030">document</translation>
<translation id="9108370397979208512">math.</translation>
<translation id="9132465097189459683">Autre…</translation>
+<translation id="9138385573473225930">alerte</translation>
<translation id="9155987714137265666"><ph name="WEEK" /> (premier jour de la semaine : <ph name="WEEK_START_DATE" />)</translation>
+<translation id="947831847158436616">cellule</translation>
+<translation id="966787709310836684">menu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_gu.xtb b/chromium/content/app/strings/translations/content_strings_gu.xtb
index 7f07e911954..f0547f017d9 100644
--- a/chromium/content/app/strings/translations/content_strings_gu.xtb
+++ b/chromium/content/app/strings/translations/content_strings_gu.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="gu">
<translation id="1014825444426747588">ખાલી</translation>
+<translation id="1018939186200882850">મેનૂ આઇટમ</translation>
<translation id="1020833440720551630">ઑડિઓ ટ્રેક મ્યૂટ કરો</translation>
<translation id="10623998915015855">ટોગલ બટન</translation>
<translation id="1088086359088493902">સેકંડ</translation>
<translation id="1171774979989969504">કૃપા કરી કોઈ ઇમેઇલ સરનામું દાખલ કરો.</translation>
<translation id="1188858454923323853">પૂરક</translation>
+<translation id="1206619573307042055">માર્કી</translation>
+<translation id="1206693055195146388">સ્લાઇડર</translation>
<translation id="1235745349614807883">હાલની શોધને સાફ કરો</translation>
+<translation id="1281252709823657822">સંવાદ</translation>
<translation id="1342835525016946179">લેખ</translation>
<translation id="1359897965706325498">બેનર</translation>
<translation id="1589122976691792535">પ્રદેશ</translation>
<translation id="1591562245178063882">આ મહિને</translation>
<translation id="1637811476055996098">ફાઇલો પસંદ કરો</translation>
+<translation id="167575180612809735">વ્યસ્ત સૂચક</translation>
<translation id="1729654308190250600">કૃપા કરીને એક બિન-ખાલી ઇમેઇલ સરનામું દાખલ કરો.</translation>
<translation id="1758486001363313524">અન્ય...</translation>
+<translation id="1806710327868736751">ચેતવણી_સંવાદ</translation>
+<translation id="1821985195704844674">ટ્રી ગ્રિડ</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">રિમોટ ઉપકરણ પર ચલાવો</translation>
<translation id="1842960171412779397">પસંદ કરો</translation>
+<translation id="1880518467580572141">રૂપરેખા</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">સ્થિતિ</translation>
<translation id="1938124657309484470">મૂલ્ય <ph name="MAXIMUM_DATE_OR_TIME" /> અથવા પહેલાંનું હોવું આવશ્યક છે.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">કૃપા કરીને આ ટેક્સ્ટને <ph name="MAX_CHARACTERS" /> અક્ષર અથવા તેથી ઓછા સુધી નાનો કરો (તમે હાલમાં <ph name="CURRENT_LENGTH" /> અક્ષરોનો ઉપયોગ કરી રહ્યા છો).</translation>
<translation id="2247351761944213033">અઠવાડિયું <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">ચેકબોક્સ</translation>
+<translation id="2335594187091864976">તારીખ અને સમય પીકર</translation>
<translation id="248395913932153421">દિવસ</translation>
<translation id="2507943997699731163">કૃપા કરીને આ ફીલ્ડ ભરો.</translation>
+<translation id="2508569020611168319">ટેબ સૂચિ</translation>
<translation id="2548326553472216322">હાલની શોધો નથી</translation>
<translation id="2572483411312390101">ચલાવો</translation>
<translation id="2613802280814924224">કૃપા કરીને એક માન્ય મૂલ્ય દાખલ કરો. નિકટતમ માન્ય મૂલ્ય <ph name="VALID_VALUE" /> છે.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">ફૂટર</translation>
<translation id="2723001399770238859">ઑડિઓ</translation>
<translation id="2746543609216772311">મૂલ્ય <ph name="MINIMUM_DATE_OR_TIME" /> અથવા પછીનું હોવું આવશ્યક છે.</translation>
+<translation id="2759744352195237655">પોપ અપ બટન</translation>
<translation id="2761667185364618470">જો તમે આગળ વધવા માંગતા હો તો કૃપા કરીને આ બૉક્સને ચેક કરો.</translation>
<translation id="2846343701378493991">1024 (મધ્યમ ગ્રેડ)</translation>
+<translation id="2896972712917208084">રેડિઓ જૂથ</translation>
<translation id="2901282870647571346">વર્તમાન મૂવીની સ્થિતિ</translation>
<translation id="2908441821576996758">કૃપા કરીને અલ્પવિરામથી વિભાજિત ઇમેઇલ સરનામાંઓની સૂચિ દાખલ કરો.</translation>
+<translation id="2931838996092594335">ક્લિક કરો</translation>
+<translation id="2940813599313844715">ઑબ્જેક્ટ</translation>
<translation id="2942448076852699108">હાઇલાઇટ કરેલ સામગ્રી</translation>
<translation id="3040011195152428237">લિંક</translation>
<translation id="3075154866155599887">કૃપા કરીને માન્ય કિંમત દાખલ કરો. ફીલ્ડ અપૂર્ણ છે અથવા અમાન્ય તારીખ ધરાવે છે.</translation>
+<translation id="3078740164268491126">કોષ્ટક</translation>
+<translation id="3086746722712840547">નોંધ</translation>
<translation id="310520048233152454">કૃપા કરી કોઈ URL દાખલ કરો.</translation>
+<translation id="3175736971608411871">ટાઇમર</translation>
+<translation id="3199563858620722075">કૉમ્બો બૉક્સ</translation>
<translation id="3450233048674729344">મૂલ્ય <ph name="MAXIMUM" /> જેટલું અથવા આનાથી ઓછું હોવું આવશ્યક છે.</translation>
<translation id="3486220673238053218">વિવરણ</translation>
+<translation id="3557673793733683882">મથાળું <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">ofmovie ની બાકી સેકન્ડ્સની સંખ્યા</translation>
<translation id="3706100364254443312">સ્વિચ</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">ટર્મ</translation>
<translation id="3822383571486410024">કૃપા કરીને આ ટેક્સ્ટને <ph name="MIN_CHARACTERS" /> અક્ષર અથવા તેથી વધુ સુધી લંબાવો (તમે હાલમાં <ph name="CURRENT_LENGTH" /> અક્ષરોનો ઉપયોગ કરી રહ્યાં છો).</translation>
<translation id="383465348367842624">'<ph name="ATSIGN" />' દ્વારા અનુસરાઈ રહેલા ભાગમાં '<ph name="INVALIDCHARACTER" />' પ્રતીક શામેલ હોવું જોઈએ નહીં.</translation>
+<translation id="3924558731517983934">ઍપ્લિકેશન</translation>
+<translation id="3960700977367013758">સ્ક્રોલ બાર</translation>
<translation id="4103419683916926126">મીલીસેકન્ડ</translation>
+<translation id="4151657705144244502">ગ્રાફિક</translation>
<translation id="4201051445878709314">પહેલાનો મહિનો દર્શાવો</translation>
<translation id="4202807286478387388">જંપ કરો</translation>
+<translation id="421884353938374759">રંગ ચૂંટનાર</translation>
+<translation id="4248100235867064564">મેનૂ બાર</translation>
+<translation id="4254339807215791271">સામગ્રી માહિતી</translation>
<translation id="4360991593054037559">કૃપા કરીને એક માન્ય મૂલ્ય દાખલ કરો. બે નિકટતમ માન્ય મૂલ્યો <ph name="VALID_VALUE_LOW" /> અને <ph name="VALID_VALUE_HIGHER" /> છે.</translation>
+<translation id="4413860115965805769">મેનૂ બટન</translation>
<translation id="4522570452068850558">વિગતો</translation>
<translation id="4597532268155981612">ફોર્મ</translation>
+<translation id="4661075872484491155">ટ્રી</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' ને અનુસરી રહેલા ભાગમાં '<ph name="INVALIDCHARACTER" />' પ્રતીક શામેલ હોવું જોઈએ નહીં.</translation>
+<translation id="4757246831282535685">ટેબ પેનલ</translation>
<translation id="4763480195061959176">વિડિઓ</translation>
+<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">કૃપા કરીને એક નંબર દાખલ કરો.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> પસંદ કર્યા</translation>
<translation id="49969490063480558">કૃપા કરીને '<ph name="ATSIGN" />' ને અનુસરી રહેલો ભાગ દાખલ કરો. '<ph name="INVALIDADDRESS" />' અપૂર્ણ છે.</translation>
+<translation id="5034860022980953847">પ્રગતિ સૂચક</translation>
<translation id="5048533449481078685">સૂચિ માર્કર</translation>
<translation id="5117590920725113268">આગલો મહિનો દર્શાવો</translation>
+<translation id="512758898067543763">પંક્તિ હેડર</translation>
<translation id="5164977714490026579">મૂલ્ય <ph name="MINIMUM" /> જેટલું અથવા આનાથી વધુ હોવું આવશ્યક છે.</translation>
<translation id="5307600278924710095">કૃપા કરીને '<ph name="ATSIGN" />' ની આગળનો ભાગ દાખલ કરો. '<ph name="INVALIDADDRESS" />' અપૂર્ણ છે.</translation>
+<translation id="5317780077021120954">સાચવો</translation>
<translation id="5406322316791861025">આકૃતિ</translation>
+<translation id="5453733299334684579">ટ્રી આઇટમ</translation>
<translation id="5466621249238537318">કૃપા કરીને એક અથવા વધુ ફાઇલ પસંદ કરો. </translation>
<translation id="5468998798572797635">પૂર્ણ સ્ક્રીનથી બહાર નીકળો</translation>
<translation id="5476505524087279545">અનચેક કરો</translation>
+<translation id="5516424706154626233">તારીખ પીકર</translation>
<translation id="5546461542133609677">અનમ્યૂટ કરો</translation>
+<translation id="561939826962581046">સમય</translation>
<translation id="5641012560118721995">પ્લેબેક થોભાવો</translation>
+<translation id="5643186887447432888">બટન</translation>
<translation id="5843503607508392247">અન્ય...</translation>
<translation id="5939518447894949180">રીસેટ કરો</translation>
<translation id="5944544982112848342">2048 (ઉચ્ચ ગ્રેડ)</translation>
<translation id="5966707198760109579">અઠવાડિયું</translation>
-<translation id="598301471034819706">સરનામું</translation>
+<translation id="5987525920412732405">સ્પિન બટન</translation>
<translation id="6015796118275082299">વર્ષ</translation>
+<translation id="6023896073578205740">સૂચિ બૉક્સ</translation>
<translation id="6101327004457443354">ઑડિઓ ટ્રેક અનમ્યૂટ કરો</translation>
<translation id="6119846243427417423">સક્રિય કરો</translation>
+<translation id="6164829606128959761">મીટર</translation>
<translation id="6270583010843788609">મૂવી સમયરેખા થમ્બ</translation>
<translation id="6359256949422175976">મૂવી સમય સ્ક્રબર થમ્બ</translation>
<translation id="6398862346408813489">મહિના પસંદગી પેનલ દર્શાવો</translation>
<translation id="6404546809543547843">ઑડિઓ સમય સ્ક્રબર</translation>
+<translation id="648732519525291180">સમય પીકર</translation>
<translation id="658823671542763450">પૂર્ણ સ્ક્રીનમાં દાખલ થાઓ</translation>
+<translation id="6637586476836377253">લૉગ</translation>
<translation id="6643016212128521049">સાફ કરો</translation>
<translation id="6663448176199120256">તાજેતરની શોધ</translation>
<translation id="668171684555832681">અન્ય...</translation>
<translation id="6692633176391053278">સ્ટેપર</translation>
+<translation id="6739588121953935928">આંકણી</translation>
+<translation id="6755330956360078551">ટૂલટીપ</translation>
<translation id="6820355525329141109">પ્લગિન લોડ કરી શક્યાં નથી.</translation>
<translation id="6843725295806269523">બંધ કરો</translation>
<translation id="6845533974506654842">દબાવો</translation>
<translation id="6853785296079745596">ઉપશીર્ષક છુપાવો</translation>
+<translation id="6885760532393684712">નિર્દેશિકા</translation>
+<translation id="6934078000481955284">બ્લૉકક્વોટ</translation>
<translation id="7057186640035488495">મૂવીનો સમય</translation>
<translation id="709897737746224366">કૃપા કરીને વિનંતી કરેલા ફોર્મેટ સાથે મેળ કરો.</translation>
<translation id="7223624360433298498">વીતેલો સમય</translation>
<translation id="7263440858009898357">કૃપા કરીને સૂચિમાંથી એક આઇટમ પસંદ કરો.</translation>
+<translation id="727747134524199931">કૉલમ હેડર</translation>
<translation id="7364796246159120393">ફાઇલ પસંદ કરો</translation>
<translation id="739024184232394898">અન્ય...</translation>
+<translation id="7491962110804786152">ટેબ</translation>
<translation id="7673697353781729403">કલાક</translation>
<translation id="7720026100085573005">બાકીનો સમય</translation>
<translation id="7740016676195725605">વિગતવાર ઉપશીર્ષકનું પ્રદર્શન અટકાવો</translation>
<translation id="7740050170769002709">HTML સામગ્રી</translation>
<translation id="7789962463072032349">થોભો</translation>
+<translation id="7802800022689234070">પ્રકટીકરણ ત્રિકોણ</translation>
<translation id="7888071071722539607">કૃપા કરીને ઇમેઇલ સરનામાંમાં '<ph name="ATSIGN" />' શામેલ કરો. '<ph name="INVALIDADDRESS" />' માં '<ph name="ATSIGN" />' ખૂટી રહ્યું છે.</translation>
+<translation id="7891486169920085145">વિભાજનકર્તા</translation>
<translation id="795667975304826397">કોઈ ફાઇલ પસંદ કરેલી નથી</translation>
<translation id="8053789581856978548">ટેક્સ્ટ ફીલ્ડ શોધો</translation>
<translation id="8115662671911883373">ઉપશીર્ષક પ્રદર્શન પ્રારંભ કરો</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">છબી નકશો</translation>
<translation id="835897206747267392">અમાન્ય મૂલ્ય.</translation>
<translation id="838869780401515933">તપાસો</translation>
+<translation id="8433900881053900389">ટુલબાર</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ફાઇલો</translation>
<translation id="8451268428117625855">કૃપા કરીને કોઈ ફાઇલ પસંદ કરો.</translation>
+<translation id="8461852803063341183">રેડિઓ બટન</translation>
+<translation id="8511325616783751178">ડ્રોપ ડાઉન બટન</translation>
<translation id="8534579021159131403">મિનિટ</translation>
<translation id="8541249477527128034">મીડિયાનું નિયંત્રણ</translation>
<translation id="8583702881314752957">વિવરણ સૂચિ</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">પ્લેબૅક શરૂ કરો</translation>
<translation id="8851136666856101339">મુખ્ય</translation>
<translation id="8987927404178983737">મહિનો</translation>
+<translation id="9002566407876343676">ખોલો</translation>
<translation id="901493112792887934">સેકન્ડ્સમાં વર્તમાન સમય</translation>
<translation id="9048119486235211610">નેવિગેશન</translation>
<translation id="9050748414552849310">ઉપશીર્ષક બતાવો</translation>
+<translation id="9062295712474918030">દસ્તાવેજ</translation>
<translation id="9108370397979208512">ગણિત</translation>
<translation id="9132465097189459683">અન્ય...</translation>
+<translation id="9138385573473225930">ચેતવણી</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, <ph name="WEEK_START_DATE" /> થી શરૂ કરીને</translation>
+<translation id="947831847158436616">કોષ</translation>
+<translation id="966787709310836684">મેનૂ</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_hi.xtb b/chromium/content/app/strings/translations/content_strings_hi.xtb
index cfc4011ba87..0f1b2549285 100644
--- a/chromium/content/app/strings/translations/content_strings_hi.xtb
+++ b/chromium/content/app/strings/translations/content_strings_hi.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="hi">
<translation id="1014825444426747588">खाली</translation>
+<translation id="1018939186200882850">मेनू आइटम</translation>
<translation id="1020833440720551630">ऑडियो ट्रैक म्यूट करें</translation>
<translation id="10623998915015855">टॉगल बटन</translation>
<translation id="1088086359088493902">सेकंड</translation>
<translation id="1171774979989969504">कृपया ई-मेल पता दर्ज करें.</translation>
<translation id="1188858454923323853">पूरक</translation>
+<translation id="1206619573307042055">मार्की</translation>
+<translation id="1206693055195146388">स्लाइडर</translation>
<translation id="1235745349614807883">हाल ही की खोजें साफ़ करें</translation>
+<translation id="1281252709823657822">संवाद</translation>
<translation id="1342835525016946179">लेख</translation>
<translation id="1359897965706325498">बैनर</translation>
<translation id="1589122976691792535">क्षेत्र</translation>
<translation id="1591562245178063882">इस माह</translation>
<translation id="1637811476055996098">फ़ाइलें चुनें</translation>
+<translation id="167575180612809735">व्यस्त संकेतक</translation>
<translation id="1729654308190250600">कृपया गैर-खाली ईमेल पता डालें.</translation>
<translation id="1758486001363313524">अन्य...</translation>
+<translation id="1806710327868736751">सूचना संवाद</translation>
+<translation id="1821985195704844674">ट्री ग्रिड</translation>
<translation id="1822429046913737220">पूर्वाह्न/अपराह्न</translation>
<translation id="1832974991323546415">दूरस्थ डिवाइस पर चलाएं</translation>
<translation id="1842960171412779397">चुनें</translation>
+<translation id="1880518467580572141">बाह्यरेखा</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">स्थिति</translation>
<translation id="1938124657309484470">मान <ph name="MAXIMUM_DATE_OR_TIME" /> या पहले का होना चाहिए.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">कृपया इस टेक्स्ट को <ph name="MAX_CHARACTERS" /> वर्णों या कम तक छोटा करें (वर्तमान में आप <ph name="CURRENT_LENGTH" /> वर्णों का उपयोग कर रहे हैं).</translation>
<translation id="2247351761944213033">सप्ताह <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">चेकबॉक्स</translation>
+<translation id="2335594187091864976">दिनांक और समय पिकर</translation>
<translation id="248395913932153421">दिन</translation>
<translation id="2507943997699731163">कृपया इस फ़ील्ड को भरें.</translation>
+<translation id="2508569020611168319">टैब सूची</translation>
<translation id="2548326553472216322">हाल ही कोई खोज नहीं</translation>
<translation id="2572483411312390101">चलाएं</translation>
<translation id="2613802280814924224">कृपया कोई मान्य मान डालें. निकटतम मान्य मान <ph name="VALID_VALUE" /> है.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">पाद लेख</translation>
<translation id="2723001399770238859">ऑडियो</translation>
<translation id="2746543609216772311">मान <ph name="MINIMUM_DATE_OR_TIME" /> या बाद का होना चाहिए.</translation>
+<translation id="2759744352195237655">पॉप अप बटन</translation>
<translation id="2761667185364618470">यदि आप आगे बढ़ना चाहते हैं तो इस बॉक्‍स को चेक करें.</translation>
<translation id="2846343701378493991">1024 (मध्यम ग्रेड)</translation>
+<translation id="2896972712917208084">रेडियो समूह</translation>
<translation id="2901282870647571346">फ़िल्म की वर्तमान स्थिति</translation>
<translation id="2908441821576996758">कृपया ईमेल पतों की अल्पविराम द्वारा विभाजित सूची दर्ज करें.</translation>
+<translation id="2931838996092594335">क्लिक करें</translation>
+<translation id="2940813599313844715">ऑब्जेक्ट</translation>
<translation id="2942448076852699108">हाइलाइट की गई सामग्री</translation>
<translation id="3040011195152428237">संपर्क</translation>
<translation id="3075154866155599887">कृपया मान्य मान डालें. फ़ील्ड अधूरी है या उसमें एक अमान्य दिनांक है.</translation>
+<translation id="3078740164268491126">तालिका</translation>
+<translation id="3086746722712840547">नोट</translation>
<translation id="310520048233152454">कृपया URL लिखें.</translation>
+<translation id="3175736971608411871">टाइमर</translation>
+<translation id="3199563858620722075">कॉम्बो बॉक्स</translation>
<translation id="3450233048674729344">मान <ph name="MAXIMUM" /> से कम या इसके बराबर होना चाहिए.</translation>
<translation id="3486220673238053218">परिभाषा</translation>
+<translation id="3557673793733683882">शीर्षक <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">फ़िल्म के शेष सेकंड</translation>
<translation id="3706100364254443312">स्विच करें</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">शब्द</translation>
<translation id="3822383571486410024">कृपया इस लेख को <ph name="MIN_CHARACTERS" /> वर्णों या अधिक तक बढ़ाएं (वर्तमान में आप <ph name="CURRENT_LENGTH" /> वर्णों का उपयोग कर रहे हैं).</translation>
<translation id="383465348367842624">'<ph name="ATSIGN" />' के बाद आने वाले भाग में '<ph name="INVALIDCHARACTER" />' प्रतीक शामिल नहीं होना चाहिए.</translation>
+<translation id="3924558731517983934">ऐप्लिकेशन</translation>
+<translation id="3960700977367013758">स्क्रॉल बार</translation>
<translation id="4103419683916926126">मिलीसेकंड</translation>
+<translation id="4151657705144244502">ग्राफ़‍िक</translation>
<translation id="4201051445878709314">पिछला माह दिखाएं</translation>
<translation id="4202807286478387388">जाएं</translation>
+<translation id="421884353938374759">रंग पिकर</translation>
+<translation id="4248100235867064564">मेनू बार</translation>
+<translation id="4254339807215791271">सामग्री की जानकारी</translation>
<translation id="4360991593054037559">कृपया कोई मान्य मान डालें. दो निकटतम मान्य मान <ph name="VALID_VALUE_LOW" /> और <ph name="VALID_VALUE_HIGHER" /> हैं.</translation>
+<translation id="4413860115965805769">मेनू बटन</translation>
<translation id="4522570452068850558">विवरण</translation>
<translation id="4597532268155981612">फ़ॉर्म</translation>
+<translation id="4661075872484491155">ट्री</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' के बाद आने वाले भाग में '<ph name="INVALIDCHARACTER" />' प्रतीक शामिल नहीं होना चाहिए.</translation>
+<translation id="4757246831282535685">टैब फलक</translation>
<translation id="4763480195061959176">वीडियो</translation>
+<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">कृपया कोई संख्या डालें.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> चुने गए</translation>
<translation id="49969490063480558">कृपया '<ph name="ATSIGN" />' के बाद आने वाला भाग डालें. '<ph name="INVALIDADDRESS" />' अधूरा है.</translation>
+<translation id="5034860022980953847">प्रगति संकेतक</translation>
<translation id="5048533449481078685">सूची चिन्हक</translation>
<translation id="5117590920725113268">अगला माह दिखाएं</translation>
+<translation id="512758898067543763">पंक्ति शीर्षलेख</translation>
<translation id="5164977714490026579">मान <ph name="MINIMUM" /> से कम या इसके बराबर होना चाहिए.</translation>
<translation id="5307600278924710095">कृपया '<ph name="ATSIGN" />' के पहले वाला भाग डालें. '<ph name="INVALIDADDRESS" />' अधूरा है.</translation>
+<translation id="5317780077021120954">सहेजें</translation>
<translation id="5406322316791861025">आकृति</translation>
+<translation id="5453733299334684579">ट्री आइटम</translation>
<translation id="5466621249238537318">कृपया एक या अधिक फ़ाइल को चुनें.</translation>
<translation id="5468998798572797635">पूर्ण स्क्रीन से बाहर निकलें</translation>
<translation id="5476505524087279545">अनचेक करें</translation>
+<translation id="5516424706154626233">दिनांक पिकर</translation>
<translation id="5546461542133609677">अनम्यूट करें</translation>
+<translation id="561939826962581046">समय</translation>
<translation id="5641012560118721995">प्लेबैक रोकें</translation>
+<translation id="5643186887447432888">बटन</translation>
<translation id="5843503607508392247">अन्य...</translation>
<translation id="5939518447894949180">रीसेट करें</translation>
<translation id="5944544982112848342">2048 (उच्च ग्रेड)</translation>
<translation id="5966707198760109579">सप्ताह</translation>
-<translation id="598301471034819706">पता</translation>
+<translation id="5987525920412732405">स्पिन बटन</translation>
<translation id="6015796118275082299">वर्ष</translation>
+<translation id="6023896073578205740">सूची बॉक्स</translation>
<translation id="6101327004457443354">ऑडियो ट्रैक अनम्यूट करें</translation>
<translation id="6119846243427417423">सक्रिय करें</translation>
+<translation id="6164829606128959761">मीटर</translation>
<translation id="6270583010843788609">फ़िल्म टाइमलाइन झलक</translation>
<translation id="6359256949422175976">फ़िल्म समय स्क्रबर झलक</translation>
<translation id="6398862346408813489">माह चयन फलक दिखाएं</translation>
<translation id="6404546809543547843">ऑडियो समय स्क्रबर</translation>
+<translation id="648732519525291180">समय पिकर</translation>
<translation id="658823671542763450">पूर्ण स्क्रीन में प्रवेश करें</translation>
+<translation id="6637586476836377253">लॉग</translation>
<translation id="6643016212128521049">साफ़ करें</translation>
<translation id="6663448176199120256">हाल ही में की गई खोजें</translation>
<translation id="668171684555832681">अन्य...</translation>
<translation id="6692633176391053278">स्टेपर</translation>
+<translation id="6739588121953935928">पैमाना</translation>
+<translation id="6755330956360078551">टूलटिप</translation>
<translation id="6820355525329141109">प्लग इन लोड नहीं किया जा सका.</translation>
<translation id="6843725295806269523">म्यूट करें</translation>
<translation id="6845533974506654842">दबाएं</translation>
<translation id="6853785296079745596">बंद कैप्शन छिपाएं</translation>
+<translation id="6885760532393684712">निर्देशिका</translation>
+<translation id="6934078000481955284">ब्लॉककोट</translation>
<translation id="7057186640035488495">फि़ल्म का समय</translation>
<translation id="709897737746224366">कृपया अनुरोधित प्रारूप का मिलान करें.</translation>
<translation id="7223624360433298498">बीता हुआ समय</translation>
<translation id="7263440858009898357">कृपया सूची में किसी आइटम को चुनें.</translation>
+<translation id="727747134524199931">स्तंभ शीर्षलेख</translation>
<translation id="7364796246159120393">फ़ाइल चुनें</translation>
<translation id="739024184232394898">अन्य...</translation>
+<translation id="7491962110804786152">टैब</translation>
<translation id="7673697353781729403">घंटे</translation>
<translation id="7720026100085573005">शेष समय</translation>
<translation id="7740016676195725605">बंद कैप्शन दिखाना रोकें</translation>
<translation id="7740050170769002709">HTML सामग्री</translation>
<translation id="7789962463072032349">पॉज़ करें</translation>
+<translation id="7802800022689234070">प्रकटीकरण त्रिकोण</translation>
<translation id="7888071071722539607">कृपया ईमेल पते में '<ph name="ATSIGN" />' शामिल करें. '<ph name="INVALIDADDRESS" />' में '<ph name="ATSIGN" />' नहीं है.</translation>
+<translation id="7891486169920085145">विभाजक</translation>
<translation id="795667975304826397">कोई फाइल नहीं चुनी गई</translation>
<translation id="8053789581856978548">लेख फ़ील्ड खोजें</translation>
<translation id="8115662671911883373">बंद कैप्शन दिखाना प्रारंभ करें</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">चित्र मानचित्र</translation>
<translation id="835897206747267392">अमान्य मान.</translation>
<translation id="838869780401515933">चेक करें</translation>
+<translation id="8433900881053900389">टूलबार</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> फ़ाइल</translation>
<translation id="8451268428117625855">कृपया किसी फ़ाइल को चुनें.</translation>
+<translation id="8461852803063341183">रेडियो बटन</translation>
+<translation id="8511325616783751178">ड्रॉप डाउन बटन</translation>
<translation id="8534579021159131403">मिनट</translation>
<translation id="8541249477527128034">मीडिया नियंत्रण</translation>
<translation id="8583702881314752957">परिभाषा सूची</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">प्लेबैक शुरू करें</translation>
<translation id="8851136666856101339">मुख्य</translation>
<translation id="8987927404178983737">माह</translation>
+<translation id="9002566407876343676">खोलें</translation>
<translation id="901493112792887934">वर्तमान समय, सेकंड में</translation>
<translation id="9048119486235211610">मार्गदर्शक</translation>
<translation id="9050748414552849310">बंद कैप्शन दिखाएं</translation>
+<translation id="9062295712474918030">दस्तावेज़</translation>
<translation id="9108370397979208512">गणित</translation>
<translation id="9132465097189459683">अन्य...</translation>
+<translation id="9138385573473225930">सूचना</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, <ph name="WEEK_START_DATE" /> से प्रारंभ हो रहा है</translation>
+<translation id="947831847158436616">सेल</translation>
+<translation id="966787709310836684">मेनू</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_hr.xtb b/chromium/content/app/strings/translations/content_strings_hr.xtb
index 42bab11b76f..ee21500f683 100644
--- a/chromium/content/app/strings/translations/content_strings_hr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_hr.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="hr">
<translation id="1014825444426747588">prazno</translation>
+<translation id="1018939186200882850">stavka izbornika</translation>
<translation id="1020833440720551630">isključivanje zvučnog zapisa</translation>
<translation id="10623998915015855">preklopni gumb</translation>
<translation id="1088086359088493902">Sekunde</translation>
<translation id="1171774979989969504">Unesite e-adresu.</translation>
<translation id="1188858454923323853">dopunski</translation>
+<translation id="1206619573307042055">pomični tekst</translation>
+<translation id="1206693055195146388">klizač</translation>
<translation id="1235745349614807883">Obriši najnovija pretraživanja</translation>
+<translation id="1281252709823657822">dijalog</translation>
<translation id="1342835525016946179">članak</translation>
<translation id="1359897965706325498">natpis</translation>
<translation id="1589122976691792535">regija</translation>
<translation id="1591562245178063882">Ovaj mjesec</translation>
<translation id="1637811476055996098">Odabir datoteka</translation>
+<translation id="167575180612809735">pokazivač zauzetosti</translation>
<translation id="1729654308190250600">Unesite e-adresu koja nije prazna vrijednost.</translation>
<translation id="1758486001363313524">Drugo...</translation>
+<translation id="1806710327868736751">dijaloški okvir upozorenja</translation>
+<translation id="1821985195704844674">rešetka u obliku stabla</translation>
<translation id="1822429046913737220">prijepodne/poslijepodne</translation>
<translation id="1832974991323546415">reproduciraj na udaljenom uređaju</translation>
<translation id="1842960171412779397">odaberi</translation>
+<translation id="1880518467580572141">obris</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">status</translation>
<translation id="1938124657309484470">Vrijednost mora biti <ph name="MAXIMUM_DATE_OR_TIME" /> ili prije toga.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Skratite taj tekst na <ph name="MAX_CHARACTERS" /> znakova ili manje (trenutačno upotrebljavate <ph name="CURRENT_LENGTH" /> znakova).</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. tjedan, <ph name="YEAR" />. godina</translation>
<translation id="2291999235780842123">potvrdni okvir</translation>
+<translation id="2335594187091864976">alat za odabir datuma i vremena</translation>
<translation id="248395913932153421">Dan</translation>
<translation id="2507943997699731163">Ispunite ovo polje.</translation>
+<translation id="2508569020611168319">popis kartica</translation>
<translation id="2548326553472216322">Nema najnovijih pretraživanja</translation>
<translation id="2572483411312390101">reprodukcija</translation>
<translation id="2613802280814924224">Unesite važeću vrijednost. Najbliža je važeća vrijednost <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">podnožje</translation>
<translation id="2723001399770238859">zvuk</translation>
<translation id="2746543609216772311">Vrijednost mora biti <ph name="MINIMUM_DATE_OR_TIME" /> ili nakon toga.</translation>
+<translation id="2759744352195237655">gumb skočnog prozora</translation>
<translation id="2761667185364618470">Označite taj okvir ako želite ići dalje.</translation>
<translation id="2846343701378493991">1024 (srednji)</translation>
+<translation id="2896972712917208084">grupa izbornih gumba</translation>
<translation id="2901282870647571346">trenutačan status filma</translation>
<translation id="2908441821576996758">Unesite popis adresa e-pošte odijeljen zarezima.</translation>
+<translation id="2931838996092594335">klikanje</translation>
+<translation id="2940813599313844715">objekt</translation>
<translation id="2942448076852699108">istaknuti sadržaj</translation>
<translation id="3040011195152428237">veza</translation>
<translation id="3075154866155599887">Unesite važeću vrijednost. Ovo je polje nepotpuno ili sadrži nevažeći datum.</translation>
+<translation id="3078740164268491126">tablica</translation>
+<translation id="3086746722712840547">napom</translation>
<translation id="310520048233152454">Unesite URL.</translation>
+<translation id="3175736971608411871">odbrojavanje</translation>
+<translation id="3199563858620722075">kombinirani okvir</translation>
<translation id="3450233048674729344">Vrijednost mora biti <ph name="MAXIMUM" /> ili manja.</translation>
<translation id="3486220673238053218">definicija</translation>
+<translation id="3557673793733683882">naslov <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">preostali broj sekundi filma</translation>
<translation id="3706100364254443312">prebaci</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">pojam</translation>
<translation id="3822383571486410024">Produljite broj znakova u tekstu na minimalno <ph name="MIN_CHARACTERS" />. Trenutačno imate premalo znakova (<ph name="CURRENT_LENGTH" />).</translation>
<translation id="383465348367842624">Dio adrese ispred znaka "<ph name="ATSIGN" />" ne smije sadržavati simbol "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3924558731517983934">aplikacija</translation>
+<translation id="3960700977367013758">klizač</translation>
<translation id="4103419683916926126">Milisekunde</translation>
+<translation id="4151657705144244502">slika</translation>
<translation id="4201051445878709314">Prikaži prethodni mjesec</translation>
<translation id="4202807286478387388">skoči</translation>
+<translation id="421884353938374759">odabir boja</translation>
+<translation id="4248100235867064564">traka izbornika</translation>
+<translation id="4254339807215791271">informacije o sadržaju</translation>
<translation id="4360991593054037559">Unesite važeću vrijednost. Dvije su najbliže važeće vrijednosti <ph name="VALID_VALUE_LOW" /> i <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">gumb izbornika</translation>
<translation id="4522570452068850558">Detalji</translation>
<translation id="4597532268155981612">obrazac</translation>
+<translation id="4661075872484491155">stablo</translation>
<translation id="4664250907885839816">Dio adrese iza znaka "<ph name="ATSIGN" />" ne smije sadržavati simbol "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4757246831282535685">ploča kartice</translation>
<translation id="4763480195061959176">videozapis</translation>
+<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Unesite broj.</translation>
<translation id="4975562563186953947">Odabrano: <ph name="SELECTED_COUNT" /></translation>
<translation id="49969490063480558">Unesite dio adrese iza znaka "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" nije potpuna e-adresa.</translation>
+<translation id="5034860022980953847">pokazivač napretka</translation>
<translation id="5048533449481078685">oznaka popisa</translation>
<translation id="5117590920725113268">Prikaži sljedeći mjesec</translation>
+<translation id="512758898067543763">zaglavlje retka</translation>
<translation id="5164977714490026579">Vrijednost mora biti <ph name="MINIMUM" /> ili veća.</translation>
<translation id="5307600278924710095">Unesite dio adrese ispred znaka "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" nije potpuna e-adresa.</translation>
+<translation id="5317780077021120954">Spremi</translation>
<translation id="5406322316791861025">lik</translation>
+<translation id="5453733299334684579">stavka stabla</translation>
<translation id="5466621249238537318">Izaberite jednu ili više datoteka.</translation>
<translation id="5468998798572797635">izlazak iz cijelog zaslona</translation>
<translation id="5476505524087279545">ukloni oznaku</translation>
+<translation id="5516424706154626233">alat za odabir datuma</translation>
<translation id="5546461542133609677">uključivanje zvuka</translation>
+<translation id="561939826962581046">vrijeme</translation>
<translation id="5641012560118721995">pauziranje reprodukcije</translation>
+<translation id="5643186887447432888">gumb</translation>
<translation id="5843503607508392247">Drugo...</translation>
<translation id="5939518447894949180">Ponovno postavi</translation>
<translation id="5944544982112848342">2048 (visoki stupanj)</translation>
<translation id="5966707198760109579">Tjedan</translation>
-<translation id="598301471034819706">adresa</translation>
+<translation id="5987525920412732405">okretni gumb</translation>
<translation id="6015796118275082299">Godina</translation>
+<translation id="6023896073578205740">okvir s popisom</translation>
<translation id="6101327004457443354">uključivanje zvučnog zapisa</translation>
<translation id="6119846243427417423">aktiviraj</translation>
+<translation id="6164829606128959761">mjerač</translation>
<translation id="6270583010843788609">gumb na vremenskom klizaču filma</translation>
<translation id="6359256949422175976">gumb vremenskog klizača filma</translation>
<translation id="6398862346408813489">Prikaži ploču za odabir mjeseca</translation>
<translation id="6404546809543547843">klizač vremena audiozapisa</translation>
+<translation id="648732519525291180">alat za odabir vremena</translation>
<translation id="658823671542763450">otvaranje na cijelom zaslonu</translation>
+<translation id="6637586476836377253">zap</translation>
<translation id="6643016212128521049">Izbriši</translation>
<translation id="6663448176199120256">Najnovija pretraživanja</translation>
<translation id="668171684555832681">Ostalo...</translation>
<translation id="6692633176391053278">povećanje/smanjenje strelicama gore/dolje (stepper)</translation>
+<translation id="6739588121953935928">ravnalo</translation>
+<translation id="6755330956360078551">opis</translation>
<translation id="6820355525329141109">Nije bilo moguće učitati dodatak.</translation>
<translation id="6843725295806269523">isključi ton</translation>
<translation id="6845533974506654842">pritisni</translation>
<translation id="6853785296079745596">sakrivanje titlova</translation>
+<translation id="6885760532393684712">direktorij</translation>
+<translation id="6934078000481955284">uvučeni citat</translation>
<translation id="7057186640035488495">vrijeme filma</translation>
<translation id="709897737746224366">Udovoljite zadanom formatu.</translation>
<translation id="7223624360433298498">proteklo vrijeme</translation>
<translation id="7263440858009898357">Odaberite stavku s popisa.</translation>
+<translation id="727747134524199931">zaglavlje stupca</translation>
<translation id="7364796246159120393">Odaberi datoteku</translation>
<translation id="739024184232394898">Drugo...</translation>
+<translation id="7491962110804786152">kart</translation>
<translation id="7673697353781729403">Sati</translation>
<translation id="7720026100085573005">preostalo vrijeme</translation>
<translation id="7740016676195725605">zaustavljanje prikazivanja titlova</translation>
<translation id="7740050170769002709">HTML sadržaj</translation>
<translation id="7789962463072032349">pauziraj</translation>
+<translation id="7802800022689234070">trokut za otkrivanje</translation>
<translation id="7888071071722539607">Uključite znak "<ph name="ATSIGN" />" u e-adresu. U adresi "<ph name="INVALIDADDRESS" />" nedostaje znak "<ph name="ATSIGN" />".</translation>
+<translation id="7891486169920085145">razdjelnik</translation>
<translation id="795667975304826397">Nije odabrana niti jedna datoteka.</translation>
<translation id="8053789581856978548">pretraži tekstno polje</translation>
<translation id="8115662671911883373">početak prikazivanja titlova</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">karta slika</translation>
<translation id="835897206747267392">Nevažeća vrijednost.</translation>
<translation id="838869780401515933">označi</translation>
+<translation id="8433900881053900389">alatna traka</translation>
<translation id="8444882422881193423">Broj datoteka: <ph name="NUMBER_OF_FILES" /></translation>
<translation id="8451268428117625855">Odaberite datoteku.</translation>
+<translation id="8461852803063341183">izborni gumb</translation>
+<translation id="8511325616783751178">gumb padajućeg izbornika</translation>
<translation id="8534579021159131403">Minute</translation>
<translation id="8541249477527128034">kontrola medija</translation>
<translation id="8583702881314752957">popis definicija</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">početak reprodukcije</translation>
<translation id="8851136666856101339">glav</translation>
<translation id="8987927404178983737">Mjesec</translation>
+<translation id="9002566407876343676">otvaranje</translation>
<translation id="901493112792887934">trenutačno vrijeme u sekundama</translation>
<translation id="9048119486235211610">navigacija</translation>
<translation id="9050748414552849310">prikazivanje titlova</translation>
+<translation id="9062295712474918030">dokument</translation>
<translation id="9108370397979208512">mat</translation>
<translation id="9132465097189459683">Drugo...</translation>
+<translation id="9138385573473225930">upozorenje</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, počevši od <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">ćelija</translation>
+<translation id="966787709310836684">izbornik</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_hu.xtb b/chromium/content/app/strings/translations/content_strings_hu.xtb
index f2ad7a60824..5fa02530d00 100644
--- a/chromium/content/app/strings/translations/content_strings_hu.xtb
+++ b/chromium/content/app/strings/translations/content_strings_hu.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="hu">
<translation id="1014825444426747588">üres</translation>
+<translation id="1018939186200882850">menüelem</translation>
<translation id="1020833440720551630">hangsáv némítása</translation>
<translation id="10623998915015855">átkapcsológomb</translation>
<translation id="1088086359088493902">Másodperc</translation>
<translation id="1171774979989969504">Kérjük, adjon meg egy e-mail címet.</translation>
<translation id="1188858454923323853">kiegészítő</translation>
+<translation id="1206619573307042055">fényújság</translation>
+<translation id="1206693055195146388">csúszka</translation>
<translation id="1235745349614807883">Friss keresések törlése</translation>
+<translation id="1281252709823657822">párbeszédpanel</translation>
<translation id="1342835525016946179">cikk</translation>
<translation id="1359897965706325498">szalaghirdetés</translation>
<translation id="1589122976691792535">régió</translation>
<translation id="1591562245178063882">Ebben a hónapban</translation>
<translation id="1637811476055996098">Fájlok kiválasztása</translation>
+<translation id="167575180612809735">„elfoglalt” kijelző</translation>
<translation id="1729654308190250600">Kérjük, ne hagyja üresen az e-mail-cím mezőjét.</translation>
<translation id="1758486001363313524">Más...</translation>
+<translation id="1806710327868736751">értesítő párbeszédpanel</translation>
+<translation id="1821985195704844674">farács</translation>
<translation id="1822429046913737220">de./du.</translation>
<translation id="1832974991323546415">lejátszás távoli eszközön</translation>
<translation id="1842960171412779397">Kiválasztás</translation>
+<translation id="1880518467580572141">áttekintés</translation>
<translation id="1921819250265091946">nn</translation>
<translation id="1930711995431081526">állapot</translation>
<translation id="1938124657309484470">Az érték <ph name="MAXIMUM_DATE_OR_TIME" /> vagy azt megelőző kell, hogy legyen.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Kérjük, rövidítse le a szöveget legfeljebb <ph name="MAX_CHARACTERS" /> karakterre (jelenleg <ph name="CURRENT_LENGTH" /> karaktert használ).</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. hét, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">jelölőnégyzet</translation>
+<translation id="2335594187091864976">dátum- és időválasztó</translation>
<translation id="248395913932153421">nap</translation>
<translation id="2507943997699731163">Kérjük, töltse ki ezt a mezőt.</translation>
+<translation id="2508569020611168319">laplista</translation>
<translation id="2548326553472216322">Nincsenek friss keresések</translation>
<translation id="2572483411312390101">lejátszás</translation>
<translation id="2613802280814924224">Kérjük, érvényes értéket adjon meg. A legközelebbi érvényes érték <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">lábléc</translation>
<translation id="2723001399770238859">audio</translation>
<translation id="2746543609216772311">Az érték <ph name="MINIMUM_DATE_OR_TIME" /> vagy azt követő kell, hogy legyen.</translation>
+<translation id="2759744352195237655">előugró gomb</translation>
<translation id="2761667185364618470">Kérjük, jelölje be ezt a jelölőnégyzetet, ha tovább kíván haladni.</translation>
<translation id="2846343701378493991">1024 (Közepes)</translation>
+<translation id="2896972712917208084">választógombcsoport</translation>
<translation id="2901282870647571346">a jelenlegi film állapota</translation>
<translation id="2908441821576996758">Kérjük, adjon meg egy vesszőkkel elválasztott e-mail címlistát.</translation>
+<translation id="2931838996092594335">kattintás</translation>
+<translation id="2940813599313844715">objektum</translation>
<translation id="2942448076852699108">kijelölt tartalom</translation>
<translation id="3040011195152428237">link</translation>
<translation id="3075154866155599887">Kérjük, adjon meg érvényes értéket. A mező hiányos, vagy érvénytelen dátum van megadva.</translation>
+<translation id="3078740164268491126">táblázat</translation>
+<translation id="3086746722712840547">jegyzet</translation>
<translation id="310520048233152454">Adjon meg egy URL-t.</translation>
+<translation id="3175736971608411871">időzítő</translation>
+<translation id="3199563858620722075">legördülő lista</translation>
<translation id="3450233048674729344">Az érték legyen kisebb vagy egyenlő, mint <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">definíció</translation>
+<translation id="3557673793733683882"><ph name="HEADING_LEVEL" />. címsor</translation>
<translation id="3632707345189162177">a filmből hátralévő másodpercek</translation>
<translation id="3706100364254443312">váltás</translation>
<translation id="3732799496749320381">hh</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">kifejezés</translation>
<translation id="3822383571486410024">Kérjük, <ph name="MIN_CHARACTERS" /> karakter hosszú vagy annál hosszabb szöveget adjon meg (jelenleg <ph name="CURRENT_LENGTH" /> karaktert használ).</translation>
<translation id="383465348367842624">A „<ph name="ATSIGN" />” előtti rész nem tartalmazhat „<ph name="INVALIDCHARACTER" />” karaktert.</translation>
+<translation id="3924558731517983934">alkalmazás</translation>
+<translation id="3960700977367013758">görgetősáv</translation>
<translation id="4103419683916926126">Ezredmásodperc</translation>
+<translation id="4151657705144244502">grafika</translation>
<translation id="4201051445878709314">Az előző hónap megjelenítése</translation>
<translation id="4202807286478387388">Mehet</translation>
+<translation id="421884353938374759">színválasztó</translation>
+<translation id="4248100235867064564">menüsor</translation>
+<translation id="4254339807215791271">tartalominformáció</translation>
<translation id="4360991593054037559">Kérjük, érvényes értéket adjon meg. A két legközelebbi érvényes érték <ph name="VALID_VALUE_LOW" /> és <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">menügomb</translation>
<translation id="4522570452068850558">Részletek</translation>
<translation id="4597532268155981612">űrlap</translation>
+<translation id="4661075872484491155">fa</translation>
<translation id="4664250907885839816">A „<ph name="ATSIGN" />” utáni rész nem tartalmazhat „<ph name="INVALIDCHARACTER" />” karaktert.</translation>
+<translation id="4757246831282535685">lappanel</translation>
<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Kérjük, adjon meg egy számot.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> kiválasztva</translation>
<translation id="49969490063480558">Kérjük, adja meg a „<ph name="ATSIGN" />” utáni részt is. A(z) „<ph name="INVALIDADDRESS" />” cím nem teljes.</translation>
+<translation id="5034860022980953847">folyamatjelző</translation>
<translation id="5048533449481078685">listajelölő</translation>
<translation id="5117590920725113268">A következő hónap megjelenítése</translation>
+<translation id="512758898067543763">sorfejléc</translation>
<translation id="5164977714490026579">Az érték legyen nagyobb vagy egyenlő, mint <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Kérjük, adja meg a „<ph name="ATSIGN" />” előtti részt is. A „<ph name="INVALIDADDRESS" />” cím nem teljes.</translation>
+<translation id="5317780077021120954">Mentés</translation>
<translation id="5406322316791861025">alak</translation>
+<translation id="5453733299334684579">faelem</translation>
<translation id="5466621249238537318">Kérjük, válasszon ki egy vagy több fájlt.</translation>
<translation id="5468998798572797635">kilépés a teljes képernyős nézetből</translation>
<translation id="5476505524087279545">Megjelölés eltávolítása</translation>
+<translation id="5516424706154626233">dátumválasztó</translation>
<translation id="5546461542133609677">némítás feloldása</translation>
+<translation id="561939826962581046">idő</translation>
<translation id="5641012560118721995">lejátszás szüneteltetése</translation>
+<translation id="5643186887447432888">gomb</translation>
<translation id="5843503607508392247">Más...</translation>
<translation id="5939518447894949180">Visszaállítás</translation>
<translation id="5944544982112848342">2048 (magasfokú)</translation>
<translation id="5966707198760109579">Hét</translation>
-<translation id="598301471034819706">cím</translation>
+<translation id="5987525920412732405">léptetőnyíl</translation>
<translation id="6015796118275082299">Év</translation>
+<translation id="6023896073578205740">listamező</translation>
<translation id="6101327004457443354">hangsáv némításának feloldása</translation>
<translation id="6119846243427417423">Aktiválás</translation>
+<translation id="6164829606128959761">mérő</translation>
<translation id="6270583010843788609">film idővonalának indexképe</translation>
<translation id="6359256949422175976">a filmidővezérlő indexképe</translation>
<translation id="6398862346408813489">A hónapválasztási panel megjelenítése</translation>
<translation id="6404546809543547843">hang idővonalának vezérlője</translation>
+<translation id="648732519525291180">időválasztó</translation>
<translation id="658823671542763450">teljes képernyős nézet</translation>
+<translation id="6637586476836377253">napló</translation>
<translation id="6643016212128521049">Törlés</translation>
<translation id="6663448176199120256">Friss keresések</translation>
<translation id="668171684555832681">Egyéb...</translation>
<translation id="6692633176391053278">léptető</translation>
+<translation id="6739588121953935928">vonalzó</translation>
+<translation id="6755330956360078551">elemleírás</translation>
<translation id="6820355525329141109">Nem sikerült betölteni a beépülő modult.</translation>
<translation id="6843725295806269523">némítás</translation>
<translation id="6845533974506654842">Gomb lenyomása</translation>
<translation id="6853785296079745596">feliratok elrejtése</translation>
+<translation id="6885760532393684712">címtár</translation>
+<translation id="6934078000481955284">bekezdésszintű idézet</translation>
<translation id="7057186640035488495">film ideje</translation>
<translation id="709897737746224366">Kérjük, tartsa magát a kívánt formátumhoz.</translation>
<translation id="7223624360433298498">eltelt idő</translation>
<translation id="7263440858009898357">Kérjük, válasszon egyet a lista elemei közül.</translation>
+<translation id="727747134524199931">oszlopfejléc</translation>
<translation id="7364796246159120393">Fájl kiválasztása</translation>
<translation id="739024184232394898">Más...</translation>
+<translation id="7491962110804786152">tab</translation>
<translation id="7673697353781729403">Óra</translation>
<translation id="7720026100085573005">hátralévő idő</translation>
<translation id="7740016676195725605">feliratok elrejtése</translation>
<translation id="7740050170769002709">HTML-tartalom</translation>
<translation id="7789962463072032349">szüneteltetés</translation>
+<translation id="7802800022689234070">plusz tartalom kibontására szolgáló háromszög</translation>
<translation id="7888071071722539607">Kérjük, írjon egy „<ph name="ATSIGN" />” karaktert az e-mail címbe. A(z) „<ph name="INVALIDADDRESS" />” címből hiányzik a „<ph name="ATSIGN" />” jel.</translation>
+<translation id="7891486169920085145">felosztó</translation>
<translation id="795667975304826397">Nincs fájl kiválasztva</translation>
<translation id="8053789581856978548">keresés a szövegmezőben</translation>
<translation id="8115662671911883373">feliratok megjelenítése</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">interaktív kép</translation>
<translation id="835897206747267392">Érvénytelen érték.</translation>
<translation id="838869780401515933">Megjelölés</translation>
+<translation id="8433900881053900389">eszköztár</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> fájl</translation>
<translation id="8451268428117625855">Válasszon egy fájlt.</translation>
+<translation id="8461852803063341183">választógomb</translation>
+<translation id="8511325616783751178">legördülő gomb</translation>
<translation id="8534579021159131403">Perc</translation>
<translation id="8541249477527128034">médiavezérlő</translation>
<translation id="8583702881314752957">definíciós lista</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">lejátszás indítása</translation>
<translation id="8851136666856101339">fő</translation>
<translation id="8987927404178983737">hónap</translation>
+<translation id="9002566407876343676">megnyitás</translation>
<translation id="901493112792887934">jelenlegi idő másodpercben</translation>
<translation id="9048119486235211610">navigáció</translation>
<translation id="9050748414552849310">feliratok megjelenítése</translation>
+<translation id="9062295712474918030">dokumentum</translation>
<translation id="9108370397979208512">matematika</translation>
<translation id="9132465097189459683">Más...</translation>
+<translation id="9138385573473225930">értesítés</translation>
<translation id="9155987714137265666"><ph name="WEEK" />. hét (<ph name="WEEK_START_DATE" />-i dátummal kezdődik)</translation>
+<translation id="947831847158436616">cella</translation>
+<translation id="966787709310836684">menü</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_id.xtb b/chromium/content/app/strings/translations/content_strings_id.xtb
index 8f0b1f71390..61a611a49b7 100644
--- a/chromium/content/app/strings/translations/content_strings_id.xtb
+++ b/chromium/content/app/strings/translations/content_strings_id.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="id">
<translation id="1014825444426747588">kosong</translation>
+<translation id="1018939186200882850">item menu</translation>
<translation id="1020833440720551630">bisukan trek audio</translation>
<translation id="10623998915015855">tombol beralih</translation>
<translation id="1088086359088493902">Detik</translation>
<translation id="1171774979989969504">Masukkan alamat email.</translation>
<translation id="1188858454923323853">komplementer</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">penggeser</translation>
<translation id="1235745349614807883">Hapus Penelusuran Barusan</translation>
+<translation id="1281252709823657822">dialog</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">spanduk</translation>
<translation id="1589122976691792535">wilayah</translation>
<translation id="1591562245178063882">Bulan ini</translation>
<translation id="1637811476055996098">Pilih File</translation>
+<translation id="167575180612809735">indikator sibuk</translation>
<translation id="1729654308190250600">Jangan mengosongkan bidang alamat email.</translation>
<translation id="1758486001363313524">Lainnya...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">kisi pohon</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">putar di perangkat jarak jauh</translation>
<translation id="1842960171412779397">pilih</translation>
+<translation id="1880518467580572141">garis batas</translation>
<translation id="1921819250265091946">hh</translation>
<translation id="1930711995431081526">status</translation>
<translation id="1938124657309484470">Tanggal harus <ph name="MAXIMUM_DATE_OR_TIME" /> atau lebih awal.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Pendekkan teks ini menjadi <ph name="MAX_CHARACTERS" /> karakter atau kurang (saat ini Anda menggunakan <ph name="CURRENT_LENGTH" /> karakter).</translation>
<translation id="2247351761944213033">Minggu <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">kotak centang</translation>
+<translation id="2335594187091864976">pemilih tanggal dan waktu</translation>
<translation id="248395913932153421">Hari</translation>
<translation id="2507943997699731163">Harap isi bidang ini.</translation>
+<translation id="2508569020611168319">daftar tab</translation>
<translation id="2548326553472216322">Tidak ada penelusuran terkini</translation>
<translation id="2572483411312390101">main</translation>
<translation id="2613802280814924224">Masukkan nilai yang valid. Nilai valid terdekatnya adalah <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">footer</translation>
<translation id="2723001399770238859">audio</translation>
<translation id="2746543609216772311">Tanggal harus <ph name="MINIMUM_DATE_OR_TIME" /> atau setelahnya.</translation>
+<translation id="2759744352195237655">tombol munculan</translation>
<translation id="2761667185364618470">Centang kotak ini jika Anda ingin melanjutkan.</translation>
<translation id="2846343701378493991">1024 (Tingkat Menengah)</translation>
+<translation id="2896972712917208084">grup radio</translation>
<translation id="2901282870647571346">status film saat ini</translation>
<translation id="2908441821576996758">Masukkan daftar alamat email yang dipisahkan dengan koma.</translation>
+<translation id="2931838996092594335">klik</translation>
+<translation id="2940813599313844715">objek</translation>
<translation id="2942448076852699108">konten yang disorot</translation>
<translation id="3040011195152428237">tautan</translation>
<translation id="3075154866155599887">Masukkan nilai yang valid. Bidang tersebut tidak lengkap atau memiliki tanggal yang tidak valid.</translation>
+<translation id="3078740164268491126">tabel</translation>
+<translation id="3086746722712840547">note</translation>
<translation id="310520048233152454">Masukkan URL.</translation>
+<translation id="3175736971608411871">pewaktu</translation>
+<translation id="3199563858620722075">kotak kombo</translation>
<translation id="3450233048674729344">Nilai harus lebih kecil atau sama dengan <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">definisi</translation>
+<translation id="3557673793733683882">judul <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">sisa waktu film dalam detik</translation>
<translation id="3706100364254443312">saklar</translation>
<translation id="3732799496749320381">bb</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">istilah</translation>
<translation id="3822383571486410024">Perpanjang teks ini hingga <ph name="MIN_CHARACTERS" /> karakter atau lebih (saat ini Anda menggunakan <ph name="CURRENT_LENGTH" /> karakter).</translation>
<translation id="383465348367842624">Bagian sebelum '<ph name="ATSIGN" />' tidak boleh berisi simbol '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="3924558731517983934">aplikasi</translation>
+<translation id="3960700977367013758">bilah gulir</translation>
<translation id="4103419683916926126">Milidetik</translation>
+<translation id="4151657705144244502">grafis</translation>
<translation id="4201051445878709314">Tampilkan bulan sebelumnya</translation>
<translation id="4202807286478387388">lompati</translation>
+<translation id="421884353938374759">pemilih warna</translation>
+<translation id="4248100235867064564">bilah menu</translation>
+<translation id="4254339807215791271">info konten</translation>
<translation id="4360991593054037559">Masukkan nilai yang valid. Dua nilai valid terdekat adalah <ph name="VALID_VALUE_LOW" /> dan <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">tombol menu</translation>
<translation id="4522570452068850558">Detail</translation>
<translation id="4597532268155981612">formulir</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Bagian setelah '<ph name="ATSIGN" />' tidak boleh berisi simbol '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="4757246831282535685">panel tab</translation>
<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Masukkan nomor.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> dipilih</translation>
<translation id="49969490063480558">Masukkan bagian setelah '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' tidak lengkap.</translation>
+<translation id="5034860022980953847">indikator kemajuan</translation>
<translation id="5048533449481078685">penanda daftar</translation>
<translation id="5117590920725113268">Tampilkan bulan berikutnya</translation>
+<translation id="512758898067543763">judul baris</translation>
<translation id="5164977714490026579">Nilai harus lebih besar daripada atau sama dengan <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Masukkan bagian yang diikuti dengan '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' tidak lengkap.</translation>
+<translation id="5317780077021120954">Simpan</translation>
<translation id="5406322316791861025">sosok</translation>
+<translation id="5453733299334684579">item pohon</translation>
<translation id="5466621249238537318">Pilih salah satu atau beberapa file.</translation>
<translation id="5468998798572797635">keluar dari tampilan layar penuh</translation>
<translation id="5476505524087279545">batalkan centang</translation>
+<translation id="5516424706154626233">pemilih tanggal</translation>
<translation id="5546461542133609677">suarakan</translation>
+<translation id="561939826962581046">waktu</translation>
<translation id="5641012560118721995">jeda pemutaran</translation>
+<translation id="5643186887447432888">tombol</translation>
<translation id="5843503607508392247">Lainnya...</translation>
<translation id="5939518447894949180">Setel ulang</translation>
<translation id="5944544982112848342">2048 (Tingkat Tinggi)</translation>
<translation id="5966707198760109579">Minggu</translation>
-<translation id="598301471034819706">alamat</translation>
+<translation id="5987525920412732405">tombol putar</translation>
<translation id="6015796118275082299">Tahun</translation>
+<translation id="6023896073578205740">kotak daftar</translation>
<translation id="6101327004457443354">suarakan trek audio</translation>
<translation id="6119846243427417423">aktifkan</translation>
+<translation id="6164829606128959761">pengukur</translation>
<translation id="6270583010843788609">jempol garis waktu film</translation>
<translation id="6359256949422175976">jempol scrubber waktu film</translation>
<translation id="6398862346408813489">Tampilkan panel pilihan bulan</translation>
<translation id="6404546809543547843">scrubber waktu audio</translation>
+<translation id="648732519525291180">pemilih waktu</translation>
<translation id="658823671542763450">masuk layar penuh</translation>
+<translation id="6637586476836377253">log</translation>
<translation id="6643016212128521049">Hapus</translation>
<translation id="6663448176199120256">Penelusuran Barusan</translation>
<translation id="668171684555832681">Lainnya...</translation>
<translation id="6692633176391053278">stepper</translation>
+<translation id="6739588121953935928">penggaris</translation>
+<translation id="6755330956360078551">keterangan alat</translation>
<translation id="6820355525329141109">Tidak dapat memuat plugin.</translation>
<translation id="6843725295806269523">bisukan</translation>
<translation id="6845533974506654842">tekan</translation>
<translation id="6853785296079745596">sembunyikan teks</translation>
+<translation id="6885760532393684712">direktori</translation>
+<translation id="6934078000481955284">blockquote</translation>
<translation id="7057186640035488495">waktu film</translation>
<translation id="709897737746224366">Sesuaikan dengan format yang diminta.</translation>
<translation id="7223624360433298498">waktu berlalu</translation>
<translation id="7263440858009898357">Pilih item pada daftar.</translation>
+<translation id="727747134524199931">judul kolom</translation>
<translation id="7364796246159120393">Pilih File</translation>
<translation id="739024184232394898">Lainnya...</translation>
+<translation id="7491962110804786152">tab</translation>
<translation id="7673697353781729403">Jam</translation>
<translation id="7720026100085573005">sisa waktu</translation>
<translation id="7740016676195725605">berhenti menampilkan teks</translation>
<translation id="7740050170769002709">Konten HTML</translation>
<translation id="7789962463072032349">jeda</translation>
+<translation id="7802800022689234070">segitiga pengungkapan</translation>
<translation id="7888071071722539607">Sertakan '<ph name="ATSIGN" />' pada alamat email. '<ph name="INVALIDADDRESS" />' tidak memiliki '<ph name="ATSIGN" />'.</translation>
+<translation id="7891486169920085145">pemisah</translation>
<translation id="795667975304826397">Tidak ada file yang dipilih</translation>
<translation id="8053789581856978548">bidang teks penelusuran</translation>
<translation id="8115662671911883373">mulai menampilkan teks</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">gambar peta</translation>
<translation id="835897206747267392">Nilai tidak valid.</translation>
<translation id="838869780401515933">centangi</translation>
+<translation id="8433900881053900389">bilah alat</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> file</translation>
<translation id="8451268428117625855">Pilih file.</translation>
+<translation id="8461852803063341183">tombol radio</translation>
+<translation id="8511325616783751178">tombol tarik-turun</translation>
<translation id="8534579021159131403">Menit</translation>
<translation id="8541249477527128034">kontrol media</translation>
<translation id="8583702881314752957">daftar definisi</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">mulai pemutaran</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8987927404178983737">Bulan</translation>
+<translation id="9002566407876343676">buka</translation>
<translation id="901493112792887934">waktu saat ini dalam detik</translation>
<translation id="9048119486235211610">navigasi</translation>
<translation id="9050748414552849310">tampilkan teks</translation>
+<translation id="9062295712474918030">dokumen</translation>
<translation id="9108370397979208512">math</translation>
<translation id="9132465097189459683">Lainnya...</translation>
+<translation id="9138385573473225930">lansiran</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, dimulai pada <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">sel</translation>
+<translation id="966787709310836684">menu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_it.xtb b/chromium/content/app/strings/translations/content_strings_it.xtb
index 6327156cb3d..b282d4a9e8d 100644
--- a/chromium/content/app/strings/translations/content_strings_it.xtb
+++ b/chromium/content/app/strings/translations/content_strings_it.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="it">
<translation id="1014825444426747588">vuoto</translation>
+<translation id="1018939186200882850">voce di menu</translation>
<translation id="1020833440720551630">disattiva traccia audio</translation>
<translation id="10623998915015855">pulsante di attivazione/disattivazione</translation>
<translation id="1088086359088493902">Secondi</translation>
<translation id="1171774979989969504">Inserisci un indirizzo email.</translation>
<translation id="1188858454923323853">elementi complementari</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">dispositivo di scorrimento</translation>
<translation id="1235745349614807883">Cancella ricerche recenti</translation>
+<translation id="1281252709823657822">finestra di dialogo</translation>
<translation id="1342835525016946179">articolo</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">regione</translation>
<translation id="1591562245178063882">Questo mese</translation>
<translation id="1637811476055996098">Scegli file</translation>
+<translation id="167575180612809735">indicatore di occupato</translation>
<translation id="1729654308190250600">Inserisci un indirizzo email valido.</translation>
<translation id="1758486001363313524">Altro...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">griglia ad albero</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">riproduci su dispositivo remoto</translation>
<translation id="1842960171412779397">seleziona</translation>
+<translation id="1880518467580572141">contorno</translation>
<translation id="1921819250265091946">gg</translation>
<translation id="1930711995431081526">stato</translation>
<translation id="1938124657309484470">Il valore deve essere <ph name="MAXIMUM_DATE_OR_TIME" /> o precedente.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Riduci questo testo a <ph name="MAX_CHARACTERS" /> caratteri o meno (attualmente stai utilizzando <ph name="CURRENT_LENGTH" /> caratteri).</translation>
<translation id="2247351761944213033">Settimana <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">casella di controllo</translation>
+<translation id="2335594187091864976">selettore di data e ora</translation>
<translation id="248395913932153421">Giorno</translation>
<translation id="2507943997699731163">Compila questo campo.</translation>
+<translation id="2508569020611168319">elenco schede</translation>
<translation id="2548326553472216322">Nessuna ricerca recente</translation>
<translation id="2572483411312390101">riproduci</translation>
<translation id="2613802280814924224">Inserisci un valore valido. Il valore valido più vicino è <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">piè di pagina</translation>
<translation id="2723001399770238859">audio</translation>
<translation id="2746543609216772311">Il valore deve essere <ph name="MINIMUM_DATE_OR_TIME" /> o successivo.</translation>
+<translation id="2759744352195237655">pulsante popup</translation>
<translation id="2761667185364618470">Seleziona questa casella se intendi procedere.</translation>
<translation id="2846343701378493991">1024 (Medium Grade)</translation>
+<translation id="2896972712917208084">gruppo pulsanti di opzione</translation>
<translation id="2901282870647571346">stato corrente del filmato</translation>
<translation id="2908441821576996758">Inserisci un elenco di indirizzi email separati da virgola.</translation>
+<translation id="2931838996092594335">fai clic</translation>
+<translation id="2940813599313844715">oggetto</translation>
<translation id="2942448076852699108">contenuti evidenziati</translation>
<translation id="3040011195152428237">link</translation>
<translation id="3075154866155599887">Inserisci un valore valido. Il campo è incompleto o presenta una data non valida.</translation>
+<translation id="3078740164268491126">tabella</translation>
+<translation id="3086746722712840547">nota</translation>
<translation id="310520048233152454">Inserisci un URL.</translation>
+<translation id="3175736971608411871">timer</translation>
+<translation id="3199563858620722075">casella combinata</translation>
<translation id="3450233048674729344">Il valore deve essere inferiore o uguale a <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">definizione</translation>
+<translation id="3557673793733683882">intestazione <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">numero di secondi di filmato rimanenti</translation>
<translation id="3706100364254443312">strumento per il passaggio ad altri elementi</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">termine</translation>
<translation id="3822383571486410024">Prolunga questo testo a <ph name="MIN_CHARACTERS" /> o più caratteri (al momento stai utilizzando <ph name="CURRENT_LENGTH" /> caratteri).</translation>
<translation id="383465348367842624">Una parte seguita da "<ph name="ATSIGN" />" non deve contenere il simbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3924558731517983934">applicazione</translation>
+<translation id="3960700977367013758">barra di scorrimento</translation>
<translation id="4103419683916926126">Millisecondi</translation>
+<translation id="4151657705144244502">immagine</translation>
<translation id="4201051445878709314">Mostra mese precedente</translation>
<translation id="4202807286478387388">vai</translation>
+<translation id="421884353938374759">selettore colori</translation>
+<translation id="4248100235867064564">barra dei menu</translation>
+<translation id="4254339807215791271">informazioni sui contenuti</translation>
<translation id="4360991593054037559">Inserisci un valore valido. I due valori validi più vicini sono <ph name="VALID_VALUE_LOW" /> e <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">pulsante di menu</translation>
<translation id="4522570452068850558">Dettagli</translation>
<translation id="4597532268155981612">modulo</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Una parte che segue "<ph name="ATSIGN" />" non deve contenere il simbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4757246831282535685">riquadro a schede</translation>
<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">ricerca</translation>
<translation id="4812940957355064477">Inserisci un numero.</translation>
<translation id="4975562563186953947">Elementi selezionati: <ph name="SELECTED_COUNT" /></translation>
<translation id="49969490063480558">Inserisci una parte dopo "<ph name="ATSIGN" />". Il valore "<ph name="INVALIDADDRESS" />" è incompleto.</translation>
+<translation id="5034860022980953847">indicatore di avanzamento</translation>
<translation id="5048533449481078685">indicatore elenco</translation>
<translation id="5117590920725113268">Mostra mese successivo</translation>
+<translation id="512758898067543763">intestazione di riga</translation>
<translation id="5164977714490026579">Il valore deve essere superiore o uguale a <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Inserisci una parte seguita da "<ph name="ATSIGN" />". Il valore "<ph name="INVALIDADDRESS" />" è incompleto.</translation>
+<translation id="5317780077021120954">Salva</translation>
<translation id="5406322316791861025">figura</translation>
+<translation id="5453733299334684579">elemento albero</translation>
<translation id="5466621249238537318">Seleziona uno o più file.</translation>
<translation id="5468998798572797635">esci da schermo intero</translation>
<translation id="5476505524087279545">deseleziona</translation>
+<translation id="5516424706154626233">selettore di data</translation>
<translation id="5546461542133609677">riattiva audio</translation>
+<translation id="561939826962581046">time</translation>
<translation id="5641012560118721995">sospendi riproduzione</translation>
+<translation id="5643186887447432888">pulsante</translation>
<translation id="5843503607508392247">Altro...</translation>
<translation id="5939518447894949180">Ripristina</translation>
<translation id="5944544982112848342">2048 (alta qualità)</translation>
<translation id="5966707198760109579">Settimana</translation>
-<translation id="598301471034819706">indirizzo</translation>
+<translation id="5987525920412732405">pulsante di selezione</translation>
<translation id="6015796118275082299">Anno</translation>
+<translation id="6023896073578205740">casella di riepilogo</translation>
<translation id="6101327004457443354">riattiva traccia audio</translation>
<translation id="6119846243427417423">attiva</translation>
+<translation id="6164829606128959761">indicatore</translation>
<translation id="6270583010843788609">cursore sequenza temporale filmato</translation>
<translation id="6359256949422175976">cursore dispositivo di scorrimento tempo filmato</translation>
<translation id="6398862346408813489">Mostra il riquadro di selezione del mese</translation>
<translation id="6404546809543547843">dispositivo di scorrimento durata audio</translation>
+<translation id="648732519525291180">selettore di ora</translation>
<translation id="658823671542763450">passa a schermo intero</translation>
+<translation id="6637586476836377253">log</translation>
<translation id="6643016212128521049">Cancella</translation>
<translation id="6663448176199120256">Ricerche recenti</translation>
<translation id="668171684555832681">Altro...</translation>
<translation id="6692633176391053278">stepper</translation>
+<translation id="6739588121953935928">righello</translation>
+<translation id="6755330956360078551">descrizione comando</translation>
<translation id="6820355525329141109">Impossibile caricare il plug-in</translation>
<translation id="6843725295806269523">disattiva audio</translation>
<translation id="6845533974506654842">premi</translation>
<translation id="6853785296079745596">nascondi sottotitoli</translation>
+<translation id="6885760532393684712">directory</translation>
+<translation id="6934078000481955284">citazione lunga</translation>
<translation id="7057186640035488495">tempo filmato</translation>
<translation id="709897737746224366">Rispetta il formato richiesto.</translation>
<translation id="7223624360433298498">tempo trascorso</translation>
<translation id="7263440858009898357">Seleziona un elemento nell'elenco.</translation>
+<translation id="727747134524199931">intestazione di colonna</translation>
<translation id="7364796246159120393">Scegli file</translation>
<translation id="739024184232394898">Altro...</translation>
+<translation id="7491962110804786152">Tab</translation>
<translation id="7673697353781729403">Orario</translation>
<translation id="7720026100085573005">tempo rimanente</translation>
<translation id="7740016676195725605">interrompi la visualizzazione dei sottotitoli</translation>
<translation id="7740050170769002709">Contenuti HTML</translation>
<translation id="7789962463072032349">pausa</translation>
+<translation id="7802800022689234070">triangolo descrittivo</translation>
<translation id="7888071071722539607">Aggiungi un simbolo "<ph name="ATSIGN" />" nell'indirizzo email. In "<ph name="INVALIDADDRESS" />" manca un simbolo "<ph name="ATSIGN" />".</translation>
+<translation id="7891486169920085145">barra di divisione</translation>
<translation id="795667975304826397">Nessun file selezionato</translation>
<translation id="8053789581856978548">campo di testo della ricerca</translation>
<translation id="8115662671911883373">avvia la visualizzazione dei sottotitoli</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">image map</translation>
<translation id="835897206747267392">Valore non valido.</translation>
<translation id="838869780401515933">seleziona</translation>
+<translation id="8433900881053900389">barra degli strumenti</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> file</translation>
<translation id="8451268428117625855">Seleziona un file.</translation>
+<translation id="8461852803063341183">pulsante di opzione</translation>
+<translation id="8511325616783751178">pulsante a discesa</translation>
<translation id="8534579021159131403">Minuti</translation>
<translation id="8541249477527128034">controllo contenuti multimediali</translation>
<translation id="8583702881314752957">elenco di definizioni</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">inizia riproduzione</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8987927404178983737">Mese</translation>
+<translation id="9002566407876343676">apri</translation>
<translation id="901493112792887934">tempo attuale in secondi</translation>
<translation id="9048119486235211610">navigazione</translation>
<translation id="9050748414552849310">mostra sottotitoli</translation>
+<translation id="9062295712474918030">documento</translation>
<translation id="9108370397979208512">elemento matematico</translation>
<translation id="9132465097189459683">Altro...</translation>
+<translation id="9138385573473225930">avviso</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, a partire dal giorno <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">cella</translation>
+<translation id="966787709310836684">menu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_iw.xtb b/chromium/content/app/strings/translations/content_strings_iw.xtb
index bafc1c8c3f6..fcb26542c37 100644
--- a/chromium/content/app/strings/translations/content_strings_iw.xtb
+++ b/chromium/content/app/strings/translations/content_strings_iw.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="iw">
<translation id="1014825444426747588">ריק</translation>
+<translation id="1018939186200882850">פריט בתפריט</translation>
<translation id="1020833440720551630">השתק רצועת אודיו</translation>
<translation id="10623998915015855">לחצן החלפה</translation>
<translation id="1088086359088493902">שניות</translation>
<translation id="1171774979989969504">הזן כתובת אימייל.</translation>
<translation id="1188858454923323853">משלים</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">מחוון</translation>
<translation id="1235745349614807883">הסר חיפושים אחרונים</translation>
+<translation id="1281252709823657822">דו-שיח</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">מודעת באנר</translation>
<translation id="1589122976691792535">אזור</translation>
<translation id="1591562245178063882">החודש</translation>
<translation id="1637811476055996098">בחר קבצים</translation>
+<translation id="167575180612809735">סימן ויזואלי 'לא פנוי/ה'</translation>
<translation id="1729654308190250600">הזן ערך נדרש בשדה של כתובת האימייל.</translation>
<translation id="1758486001363313524">אחר...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">רשת של עץ</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">הפעלה במכשיר מרוחק</translation>
<translation id="1842960171412779397">בחר</translation>
+<translation id="1880518467580572141">קו מתאר</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">מצב</translation>
<translation id="1938124657309484470">על הערך להיות <ph name="MAXIMUM_DATE_OR_TIME" /> או מוקדם יותר.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">קצר טקסט זה ל-<ph name="MAX_CHARACTERS" /> תווים או פחות (אתה משתמש כעת ב-<ph name="CURRENT_LENGTH" /> תווים).</translation>
<translation id="2247351761944213033">שבוע <ph name="WEEKNUMBER" />‏, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">תיבת סימון</translation>
+<translation id="2335594187091864976">בוחר תאריך ושעה</translation>
<translation id="248395913932153421">יום</translation>
<translation id="2507943997699731163">מלא שדה זה.</translation>
+<translation id="2508569020611168319">רשימת כרטיסיות</translation>
<translation id="2548326553472216322">אין חיפושים אחרונים</translation>
<translation id="2572483411312390101">הפעל</translation>
<translation id="2613802280814924224">הזן ערך חוקי. הערך החוקי הקרוב ביותר הוא <ph name="VALID_VALUE" /></translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">כותרת תחתונה</translation>
<translation id="2723001399770238859">אודיו</translation>
<translation id="2746543609216772311">על הערך להיות <ph name="MINIMUM_DATE_OR_TIME" /> ומעלה.</translation>
+<translation id="2759744352195237655">לחצן קופץ</translation>
<translation id="2761667185364618470">סמן תיבה זו אם אתה רוצה להמשיך.</translation>
<translation id="2846343701378493991">1024 (Medium Grade)</translation>
+<translation id="2896972712917208084">קבוצת לחצני בחירה</translation>
<translation id="2901282870647571346">מצב סרט נוכחי</translation>
<translation id="2908441821576996758">הזן רשימה של כתובות אימייל המופרדות באמצעות פסיקים.</translation>
+<translation id="2931838996092594335">לחץ</translation>
+<translation id="2940813599313844715">אובייקט</translation>
<translation id="2942448076852699108">תוכן מודגש</translation>
<translation id="3040011195152428237">קישור</translation>
<translation id="3075154866155599887">הזן ערך חוקי. השדה ריק או שהוא מכיל תאריך לא חוקי.</translation>
+<translation id="3078740164268491126">טבלה</translation>
+<translation id="3086746722712840547">note</translation>
<translation id="310520048233152454">הזן כתובת אתר.</translation>
+<translation id="3175736971608411871">טיימר</translation>
+<translation id="3199563858620722075">תיבה משולבת</translation>
<translation id="3450233048674729344">הערך חייב להיות קטן מ-<ph name="MAXIMUM" /> או שווה לו.</translation>
<translation id="3486220673238053218">הגדרה</translation>
+<translation id="3557673793733683882">כותרת <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">מספר שניות שנותרו עד לסיום הסרט</translation>
<translation id="3706100364254443312">מעבר</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">מונח</translation>
<translation id="3822383571486410024">הארך טקסט זה ל-<ph name="MIN_CHARACTERS" /> תווים או יותר (אתה משתמש כרגע ב-<ph name="CURRENT_LENGTH" /> תווים).</translation>
<translation id="383465348367842624">חלק ולאחריו '<ph name="ATSIGN" />' לא אמור לכלול את הסמל '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="3924558731517983934">יישום</translation>
+<translation id="3960700977367013758">סרגל גלילה</translation>
<translation id="4103419683916926126">אלפיות שנייה</translation>
+<translation id="4151657705144244502">פריט גרפי</translation>
<translation id="4201051445878709314">הצג חודש קודם</translation>
<translation id="4202807286478387388">קפוץ</translation>
+<translation id="421884353938374759">color picker</translation>
+<translation id="4248100235867064564">שורת תפריטים</translation>
+<translation id="4254339807215791271">פרטי תוכן</translation>
<translation id="4360991593054037559">הזן ערך חוקי. שני הערכים החוקיים הקרובים ביותר הם <ph name="VALID_VALUE_LOW" /> ו-<ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">לחצן תפריט</translation>
<translation id="4522570452068850558">פרטים</translation>
<translation id="4597532268155981612">טופס</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">חלק ולאחריו '<ph name="ATSIGN" />' לא אמור לכלול את הסמל '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="4757246831282535685">חלונית כרטיסיות</translation>
<translation id="4763480195061959176">סרטוני וידאו</translation>
+<translation id="479989351350248267">Search</translation>
<translation id="4812940957355064477">הזן מספר.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> נבחרו</translation>
<translation id="49969490063480558">הזן חלק ולאחריו '<ph name="ATSIGN" />'‏. השדה '<ph name="INVALIDADDRESS" />' אינו מלא.</translation>
+<translation id="5034860022980953847">סימן ויזואלי להתקדמות</translation>
<translation id="5048533449481078685">סמן רשימה</translation>
<translation id="5117590920725113268">הצג את החודש הבא</translation>
+<translation id="512758898067543763">כותרת שורה</translation>
<translation id="5164977714490026579">הערך חייב להיות גדול מ-<ph name="MINIMUM" /> או שווה לו.</translation>
<translation id="5307600278924710095">הזן חלק ולאחריו '<ph name="ATSIGN" />'‏. השדה '<ph name="INVALIDADDRESS" />' אינו מלא.</translation>
+<translation id="5317780077021120954">שמור</translation>
<translation id="5406322316791861025">ספרה</translation>
+<translation id="5453733299334684579">פריט בעץ</translation>
<translation id="5466621249238537318">בחר קובץ אחד או יותר.</translation>
<translation id="5468998798572797635">צא ממסך מלא</translation>
<translation id="5476505524087279545">בטל סימון</translation>
+<translation id="5516424706154626233">בוחר תאריכים</translation>
<translation id="5546461542133609677">בטל השתקה</translation>
+<translation id="561939826962581046">time</translation>
<translation id="5641012560118721995">השהה הפעלה</translation>
+<translation id="5643186887447432888">לחצן</translation>
<translation id="5843503607508392247">אחר...</translation>
<translation id="5939518447894949180">אפס</translation>
<translation id="5944544982112848342">2048 (High Grade)</translation>
<translation id="5966707198760109579">שבוע</translation>
-<translation id="598301471034819706">כתובת</translation>
+<translation id="5987525920412732405">לחצן קביעת ערך</translation>
<translation id="6015796118275082299">שנה</translation>
+<translation id="6023896073578205740">תיבת רשימה</translation>
<translation id="6101327004457443354">בטל השתקה של רצועת אודיו</translation>
<translation id="6119846243427417423">הפעל</translation>
+<translation id="6164829606128959761">מד</translation>
<translation id="6270583010843788609">תמונה ממוזערת של משך סרט</translation>
<translation id="6359256949422175976">תמונה ממוזערת של מסתיר זמן סרט</translation>
<translation id="6398862346408813489">הצג חלונית לבחירת חודש</translation>
<translation id="6404546809543547843">מסתיר משך אודיו</translation>
+<translation id="648732519525291180">בוחר שעות</translation>
<translation id="658823671542763450">היכנס למסך מלא</translation>
+<translation id="6637586476836377253">log</translation>
<translation id="6643016212128521049">נקה</translation>
<translation id="6663448176199120256">חיפושים אחרונים</translation>
<translation id="668171684555832681">אחר...</translation>
<translation id="6692633176391053278">פקד חצים</translation>
+<translation id="6739588121953935928">סרגל</translation>
+<translation id="6755330956360078551">הסבר קצר</translation>
<translation id="6820355525329141109">לא ניתן היה לטעון את הפלאגין.</translation>
<translation id="6843725295806269523">השתק</translation>
<translation id="6845533974506654842">לחץ</translation>
<translation id="6853785296079745596">הסתר כתוביות סגורות</translation>
+<translation id="6885760532393684712">ספריה</translation>
+<translation id="6934078000481955284">‏רכיב blockquote</translation>
<translation id="7057186640035488495">משך הסרט</translation>
<translation id="709897737746224366">התאם את הפורמט המבוקש.</translation>
<translation id="7223624360433298498">זמן שחלף</translation>
<translation id="7263440858009898357">בחר פריט מהרשימה.</translation>
+<translation id="727747134524199931">כותרת עמודה</translation>
<translation id="7364796246159120393">בחר קובץ</translation>
<translation id="739024184232394898">אחר...</translation>
+<translation id="7491962110804786152">tab</translation>
<translation id="7673697353781729403">שעות</translation>
<translation id="7720026100085573005">זמן שנותר</translation>
<translation id="7740016676195725605">הפסק להציג כתוביות סגורות</translation>
<translation id="7740050170769002709">‏תוכן HTML</translation>
<translation id="7789962463072032349">השהה</translation>
+<translation id="7802800022689234070">משולש הצגה/הסתרה</translation>
<translation id="7888071071722539607">כלול '<ph name="ATSIGN" />' בכתובת האימייל. ב-'<ph name="INVALIDADDRESS" />' חסר '<ph name="ATSIGN" />'.</translation>
+<translation id="7891486169920085145">מפצל</translation>
<translation id="795667975304826397">לא נבחר קובץ</translation>
<translation id="8053789581856978548">שדה טקסט לחיפוש</translation>
<translation id="8115662671911883373">התחל להציג כתוביות סגורות</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">מפת תמונות</translation>
<translation id="835897206747267392">ערך לא חוקי.</translation>
<translation id="838869780401515933">סמן</translation>
+<translation id="8433900881053900389">סרגל כלים</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> קבצים</translation>
<translation id="8451268428117625855">בחר קובץ.</translation>
+<translation id="8461852803063341183">לחצן בחירה</translation>
+<translation id="8511325616783751178">לחצן רשימה נפתחת</translation>
<translation id="8534579021159131403">דקות</translation>
<translation id="8541249477527128034">שליטה במדיה</translation>
<translation id="8583702881314752957">רשימת הגדרות</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">התחל בהפעלה</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8987927404178983737">חודש</translation>
+<translation id="9002566407876343676">פתח</translation>
<translation id="901493112792887934">זמן נוכחי בשניות</translation>
<translation id="9048119486235211610">ניווט</translation>
<translation id="9050748414552849310">הצג כתוביות סגורות</translation>
+<translation id="9062295712474918030">מסמך</translation>
<translation id="9108370397979208512">math</translation>
<translation id="9132465097189459683">אחר...</translation>
+<translation id="9138385573473225930">התראה</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, שמתחיל בתאריך <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">תא</translation>
+<translation id="966787709310836684">תפריט</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ja.xtb b/chromium/content/app/strings/translations/content_strings_ja.xtb
index 949545d1610..dc5d484da6a 100644
--- a/chromium/content/app/strings/translations/content_strings_ja.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ja.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="ja">
<translation id="1014825444426747588">空白</translation>
+<translation id="1018939186200882850">メニュー項目</translation>
<translation id="1020833440720551630">音声トラックをミュート</translation>
<translation id="10623998915015855">切り替えボタン</translation>
<translation id="1088086359088493902">秒</translation>
<translation id="1171774979989969504">メール アドレスを入力してください。</translation>
<translation id="1188858454923323853">捕捉</translation>
+<translation id="1206619573307042055">マーキー</translation>
+<translation id="1206693055195146388">スライダ</translation>
<translation id="1235745349614807883">最近の検索履歴を消去</translation>
+<translation id="1281252709823657822">ダイアログ</translation>
<translation id="1342835525016946179">記事</translation>
<translation id="1359897965706325498">バナー</translation>
<translation id="1589122976691792535">地域</translation>
<translation id="1591562245178063882">今月</translation>
<translation id="1637811476055996098">ファイル選択</translation>
+<translation id="167575180612809735">ビジー インジケータ</translation>
<translation id="1729654308190250600">メール アドレスを入力してください。</translation>
<translation id="1758486001363313524">その他...</translation>
+<translation id="1806710327868736751">アラート ダイアログ</translation>
+<translation id="1821985195704844674">ツリーグリッド</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">リモート デバイスで再生</translation>
<translation id="1842960171412779397">選択</translation>
+<translation id="1880518467580572141">アウトライン</translation>
<translation id="1921819250265091946">日</translation>
<translation id="1930711995431081526">ステータス</translation>
<translation id="1938124657309484470"><ph name="MAXIMUM_DATE_OR_TIME" /> 以前の値を指定する必要があります。</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">このテキストを半角 <ph name="MAX_CHARACTERS" /> 文字以下にしてください(現時点で半角 <ph name="CURRENT_LENGTH" /> 文字です)。</translation>
<translation id="2247351761944213033"><ph name="YEAR" />年第<ph name="WEEKNUMBER" />週</translation>
<translation id="2291999235780842123">チェックボックス</translation>
+<translation id="2335594187091864976">日時選択ツール</translation>
<translation id="248395913932153421">日</translation>
<translation id="2507943997699731163">このフィールドを入力してください。</translation>
+<translation id="2508569020611168319">タブリスト</translation>
<translation id="2548326553472216322">最近の検索はありません</translation>
<translation id="2572483411312390101">再生</translation>
<translation id="2613802280814924224">有効な値を入力してください。有効な値として最も近いのは <ph name="VALID_VALUE" /> です。</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">フッター</translation>
<translation id="2723001399770238859">音声</translation>
<translation id="2746543609216772311"><ph name="MINIMUM_DATE_OR_TIME" /> 以降の値を指定する必要があります。</translation>
+<translation id="2759744352195237655">ポップアップ ボタン</translation>
<translation id="2761667185364618470">次に進むにはこのチェックボックスをオンにしてください。</translation>
<translation id="2846343701378493991">1024 (中)</translation>
+<translation id="2896972712917208084">ラジオボタン グループ</translation>
<translation id="2901282870647571346">現在の映画のステータス</translation>
<translation id="2908441821576996758">メール アドレスのカンマ区切りリストを入力してください。</translation>
+<translation id="2931838996092594335">クリック</translation>
+<translation id="2940813599313844715">オブジェクト</translation>
<translation id="2942448076852699108">ハイライト表示されたコンテンツ</translation>
<translation id="3040011195152428237">リンク</translation>
<translation id="3075154866155599887">有効な値を入力してください。フィールドの入力が不完全か、日付が無効です。</translation>
+<translation id="3078740164268491126">表</translation>
+<translation id="3086746722712840547">注記</translation>
<translation id="310520048233152454">URL を入力してください。</translation>
+<translation id="3175736971608411871">タイマー</translation>
+<translation id="3199563858620722075">コンボボックス</translation>
<translation id="3450233048674729344">値は <ph name="MAXIMUM" /> 以下にする必要があります。</translation>
<translation id="3486220673238053218">定義</translation>
+<translation id="3557673793733683882">見出し <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">残り時間(秒)</translation>
<translation id="3706100364254443312">切り替え</translation>
<translation id="3732799496749320381">月</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">用語</translation>
<translation id="3822383571486410024">このテキストは <ph name="MIN_CHARACTERS" /> 文字以上で指定してください(現在は <ph name="CURRENT_LENGTH" /> 文字です)。</translation>
<translation id="383465348367842624">「<ph name="ATSIGN" />」の前の文字列に記号「<ph name="INVALIDCHARACTER" />」を使用しないでください。</translation>
+<translation id="3924558731517983934">アプリケーション</translation>
+<translation id="3960700977367013758">スクロールバー</translation>
<translation id="4103419683916926126">ミリ秒</translation>
+<translation id="4151657705144244502">グラフィック</translation>
<translation id="4201051445878709314">前の月を表示</translation>
<translation id="4202807286478387388">ジャンプ</translation>
+<translation id="421884353938374759">色の選択</translation>
+<translation id="4248100235867064564">メニューバー</translation>
+<translation id="4254339807215791271">コンテンツ情報</translation>
<translation id="4360991593054037559">有効な値を入力してください。有効な値として最も近いのは <ph name="VALID_VALUE_LOW" /> と <ph name="VALID_VALUE_HIGHER" /> です。</translation>
+<translation id="4413860115965805769">メニューボタン</translation>
<translation id="4522570452068850558">詳細</translation>
<translation id="4597532268155981612">フォーム</translation>
+<translation id="4661075872484491155">ツリー</translation>
<translation id="4664250907885839816">「<ph name="ATSIGN" />」に続く文字列に記号「<ph name="INVALIDCHARACTER" />」を使用しないでください。</translation>
+<translation id="4757246831282535685">タブパネル</translation>
<translation id="4763480195061959176">動画</translation>
+<translation id="479989351350248267">検索</translation>
<translation id="4812940957355064477">数字を入力してください。</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> 件選択</translation>
<translation id="49969490063480558">「<ph name="ATSIGN" />」に続く文字列を入力してください。「<ph name="INVALIDADDRESS" />」は完全なメール アドレスではありません。</translation>
+<translation id="5034860022980953847">プログレスバー</translation>
<translation id="5048533449481078685">リスト マーカー</translation>
<translation id="5117590920725113268">次の月を表示</translation>
+<translation id="512758898067543763">行見出し</translation>
<translation id="5164977714490026579">値は <ph name="MINIMUM" /> 以上にする必要があります。</translation>
<translation id="5307600278924710095">「<ph name="ATSIGN" />」の前の文字列を入力してください。「<ph name="INVALIDADDRESS" />」は完全なメール アドレスではありません。</translation>
+<translation id="5317780077021120954">保存</translation>
<translation id="5406322316791861025">図</translation>
+<translation id="5453733299334684579">ツリー項目</translation>
<translation id="5466621249238537318">1 つ以上のファイルを選択してください。</translation>
<translation id="5468998798572797635">全画面表示を終了</translation>
<translation id="5476505524087279545">チェックを外す</translation>
+<translation id="5516424706154626233">日付選択ツール</translation>
<translation id="5546461542133609677">ミュートを解除</translation>
+<translation id="561939826962581046">日時</translation>
<translation id="5641012560118721995">再生を一時停止</translation>
+<translation id="5643186887447432888">ボタン</translation>
<translation id="5843503607508392247">その他...</translation>
<translation id="5939518447894949180">リセット</translation>
<translation id="5944544982112848342">2048 (高)</translation>
<translation id="5966707198760109579">週</translation>
-<translation id="598301471034819706">アドレス</translation>
+<translation id="5987525920412732405">スピンボタン</translation>
<translation id="6015796118275082299">年</translation>
+<translation id="6023896073578205740">リストボックス</translation>
<translation id="6101327004457443354">音声トラックのミュートを解除</translation>
<translation id="6119846243427417423">アクティブにする</translation>
+<translation id="6164829606128959761">メーター</translation>
<translation id="6270583010843788609">タイムラインのサムネイル</translation>
<translation id="6359256949422175976">シークバーのサムネイル</translation>
<translation id="6398862346408813489">月選択パネルを表示</translation>
<translation id="6404546809543547843">オーディオ再生バー</translation>
+<translation id="648732519525291180">時間選択ツール</translation>
<translation id="658823671542763450">全画面表示</translation>
+<translation id="6637586476836377253">ログ</translation>
<translation id="6643016212128521049">クリア</translation>
<translation id="6663448176199120256">最近の検索</translation>
<translation id="668171684555832681">その他...</translation>
<translation id="6692633176391053278">ステッパー</translation>
+<translation id="6739588121953935928">ルーラー</translation>
+<translation id="6755330956360078551">ツールチップ</translation>
<translation id="6820355525329141109">プラグインを読み込むことができませんでした。</translation>
<translation id="6843725295806269523">ミュート</translation>
<translation id="6845533974506654842">押す</translation>
<translation id="6853785296079745596">クローズド キャプションを非表示</translation>
+<translation id="6885760532393684712">ディレクトリ</translation>
+<translation id="6934078000481955284">引用</translation>
<translation id="7057186640035488495">上映時間</translation>
<translation id="709897737746224366">指定されている形式で入力してください。</translation>
<translation id="7223624360433298498">経過時間</translation>
<translation id="7263440858009898357">リスト内の項目を選択してください。</translation>
+<translation id="727747134524199931">列見出し</translation>
<translation id="7364796246159120393">ファイルを選択</translation>
<translation id="739024184232394898">その他...</translation>
+<translation id="7491962110804786152">タブ</translation>
<translation id="7673697353781729403">時間</translation>
<translation id="7720026100085573005">残り時間</translation>
<translation id="7740016676195725605">クローズド キャプションの表示を終了</translation>
<translation id="7740050170769002709">HTML コンテンツ</translation>
<translation id="7789962463072032349">一時停止</translation>
+<translation id="7802800022689234070">三角形の展開ボタン</translation>
<translation id="7888071071722539607">メール アドレスに「<ph name="ATSIGN" />」を挿入してください。「<ph name="INVALIDADDRESS" />」内に「<ph name="ATSIGN" />」がありません。</translation>
+<translation id="7891486169920085145">分割バー</translation>
<translation id="795667975304826397">選択されていません</translation>
<translation id="8053789581856978548">検索テキスト欄</translation>
<translation id="8115662671911883373">クローズド キャプションの表示を開始</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">イメージ マップ</translation>
<translation id="835897206747267392">値が無効です。</translation>
<translation id="838869780401515933">チェックを付ける</translation>
+<translation id="8433900881053900389">ツールバー</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ファイル</translation>
<translation id="8451268428117625855">ファイルを選択してください。</translation>
+<translation id="8461852803063341183">ラジオボタン</translation>
+<translation id="8511325616783751178">プルダウン ボタン</translation>
<translation id="8534579021159131403">分</translation>
<translation id="8541249477527128034">メディア管理</translation>
<translation id="8583702881314752957">定義リスト</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">再生を開始</translation>
<translation id="8851136666856101339">本文</translation>
<translation id="8987927404178983737">月</translation>
+<translation id="9002566407876343676">開く</translation>
<translation id="901493112792887934">現在の時間(秒単位)</translation>
<translation id="9048119486235211610">ナビゲーション</translation>
<translation id="9050748414552849310">クローズド キャプションを表示</translation>
+<translation id="9062295712474918030">ドキュメント</translation>
<translation id="9108370397979208512">数式</translation>
<translation id="9132465097189459683">その他...</translation>
+<translation id="9138385573473225930">アラート</translation>
<translation id="9155987714137265666"><ph name="WEEK_START_DATE" /> から始まる <ph name="WEEK" /></translation>
+<translation id="947831847158436616">セル</translation>
+<translation id="966787709310836684">メニュー</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_kn.xtb b/chromium/content/app/strings/translations/content_strings_kn.xtb
index 3b132cc07e6..27ae0ef8fc7 100644
--- a/chromium/content/app/strings/translations/content_strings_kn.xtb
+++ b/chromium/content/app/strings/translations/content_strings_kn.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="kn">
<translation id="1014825444426747588">ಖಾಲಿ</translation>
+<translation id="1018939186200882850">ಮೆನು ಐಟಂ</translation>
<translation id="1020833440720551630">ಆಡಿಯೋ ಟ್ರ್ಯಾಕ್ ಮ್ಯೂಟ್ ಮಾಡು</translation>
<translation id="10623998915015855">ಟಾಗಲ್ ಬಟನ್</translation>
<translation id="1088086359088493902">ಸೆಕೆಂಡುಗಳು</translation>
<translation id="1171774979989969504">ದಯವಿಟ್ಟು ಇಮೇಲ್ ವಿಳಾಸವನ್ನು ನಮೂದಿಸಿ.</translation>
<translation id="1188858454923323853">ಪೂರಕವಾಗಿ</translation>
+<translation id="1206619573307042055">ಮಾರ್ಕ್ಯೂ</translation>
+<translation id="1206693055195146388">ಸ್ಲೈಡರ್</translation>
<translation id="1235745349614807883">ಇತ್ತೀಚಿನ ಹುಡುಕಾಟವನ್ನು ತೆರವುಗೊಳಿಸಿ</translation>
+<translation id="1281252709823657822">ಸಂವಾದ</translation>
<translation id="1342835525016946179">ಲೇಖನ</translation>
<translation id="1359897965706325498">ಬ್ಯಾನರ್</translation>
<translation id="1589122976691792535">ಪ್ರದೇಶ</translation>
<translation id="1591562245178063882">ಈ ತಿಂಗಳು</translation>
<translation id="1637811476055996098">ಫೈಲ್‌ಗಳನ್ನು ಆರಿಸಿ</translation>
+<translation id="167575180612809735">ಕಾರ್ಯನಿರತ ಸೂಚಕ</translation>
<translation id="1729654308190250600">ಖಾಲಿ-ಅಲ್ಲದ ಇಮೇಲ್ ವಿಳಾಸವನ್ನು ನಮೂದಿಸಿ.</translation>
<translation id="1758486001363313524">ಇತರೆ...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">ಟ್ರೀ ಗ್ರಿಡ್</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">ರಿಮೋಟ್ ಸಾಧನದಲ್ಲಿ ಪ್ಲೇ ಮಾಡಿ</translation>
<translation id="1842960171412779397">ಆಯ್ಕೆ ಮಾಡಿ</translation>
+<translation id="1880518467580572141">ಔಟ್‌ಲೈನ್</translation>
<translation id="1921819250265091946">ದಿದಿ</translation>
<translation id="1930711995431081526">ಸ್ಥಿತಿ</translation>
<translation id="1938124657309484470">ಮೌಲ್ಯವು <ph name="MAXIMUM_DATE_OR_TIME" /> ಅಥವಾ ಹಿಂದಿನದ್ದಾಗಿರಬೇಕು.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">ದಯವಿಟ್ಟು ಈ ಪಠ್ಯವನ್ನು <ph name="MAX_CHARACTERS" /> ಅಕ್ಷರಗಳಿಗೆ ಅಥವಾ ಅದಕ್ಕಿಂತಲೂ ಕಡಿಮೆಗೆ ಸೀಮಿತಗೊಳಿಸಿ (ನೀವು ಪ್ರಸ್ತುತ <ph name="CURRENT_LENGTH" /> ಅಕ್ಷರಗಳನ್ನು ಬಳಸುತ್ತಿರುವಿರಿ).</translation>
<translation id="2247351761944213033">ವಾರ <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">ಚೆಕ್‌ಬಾಕ್ಸ್</translation>
+<translation id="2335594187091864976">ದಿನಾಂಕ ಮತ್ತು ಸಮಯ ಪಿಕರ್</translation>
<translation id="248395913932153421">ದಿನ</translation>
<translation id="2507943997699731163">ದಯವಿಟ್ಟು ಈ ಕ್ಷೇತ್ರವನ್ನು ಭರ್ತಿ ಮಾಡಿ.</translation>
+<translation id="2508569020611168319">ಟ್ಯಾಬ್ ಪಟ್ಟಿ</translation>
<translation id="2548326553472216322">ಇತ್ತೀಚಿನ ಹುಡುಕಾಟಗಳು ಇಲ್ಲ</translation>
<translation id="2572483411312390101">ಪ್ಲೇ ಮಾಡಿ</translation>
<translation id="2613802280814924224">ಮಾನ್ಯ ಮೌಲ್ಯವನ್ನು ನಮೂದಿಸಿ. ಹತ್ತಿರದ ಮಾನ್ಯ ಮೌಲ್ಯವು <ph name="VALID_VALUE" /> ಆಗಿದೆ.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">ಅಡಿಟಿಪ್ಪಣಿ</translation>
<translation id="2723001399770238859">ಆಡಿಯೋ</translation>
<translation id="2746543609216772311">ಮೌಲ್ಯವು <ph name="MINIMUM_DATE_OR_TIME" /> ಅಥವಾ ನಂತರದ್ದಾಗಿರಬೇಕು.</translation>
+<translation id="2759744352195237655">ಪಾಪ್ ಅಪ್ ಬಟನ್</translation>
<translation id="2761667185364618470">ನೀವು ಮುಂದುವರೆಯಬೇಕಾದರೆ ದಯವಿಟ್ಟು ಈ ಬಾಕ್ಸ್ ಅನ್ನು ಪರೀಕ್ಷಿಸಿ.</translation>
<translation id="2846343701378493991">1024 (ಮದ್ಯಮ ಶ್ರೇಣಿ)</translation>
+<translation id="2896972712917208084">ರೇಡಿಯೋ ಗುಂಪು</translation>
<translation id="2901282870647571346">ಪ್ರಸ್ತುತ ಚಲನಚಿತ್ರದ ಸ್ಥಿತಿ</translation>
<translation id="2908441821576996758">ದಯವಿಟ್ಟು ಅಲ್ಪ ವಿರಾಮದಿಂದ ಬೇರ್ಪಡಿಸಿದ ಇಮೇಲ್ ವಿಳಾಸಗಳ ಪಟ್ಟಿಯನ್ನು ನಮೂದಿಸಿ.</translation>
+<translation id="2931838996092594335">ಕ್ಲಿಕ್‌ ಮಾಡಿ</translation>
+<translation id="2940813599313844715">ವಸ್ತು</translation>
<translation id="2942448076852699108">ಹೈಲೈಟ್ ಮಾಡಲಾದ ವಿಷಯ</translation>
<translation id="3040011195152428237">ಲಿಂಕ್</translation>
<translation id="3075154866155599887">ದಯವಿಟ್ಟು ಮಾನ್ಯ ಮೌಲ್ಯವನ್ನು ನಮೂದಿಸಿ. ಕ್ಷೇತ್ರವು ಅಪೂರ್ಣವಾಗಿದೆ ಅಥವಾ ಅಮಾನ್ಯ ದಿನಾಂಕವನ್ನು ಹೊಂದಿದೆ.</translation>
+<translation id="3078740164268491126">ಕೋಷ್ಟಕ</translation>
+<translation id="3086746722712840547">ಟಿಪ್ಪಣಿ</translation>
<translation id="310520048233152454">ದಯವಿಟ್ಟು URL ಅನ್ನು ನಮೂದಿಸಿ.</translation>
+<translation id="3175736971608411871">ಟೈಮರ್</translation>
+<translation id="3199563858620722075">ಕಾಂಬೊ ಬಾಕ್ಸ್</translation>
<translation id="3450233048674729344">ಮೌಲ್ಯವು <ph name="MAXIMUM" /> ಕ್ಕೆ ಸಮನಾಗಿರಬಹುದು ಅಥವಾ ಅದಕ್ಕಿಂತಲೂ ಕಡಿಮೆ ಆಗಿರಬಹುದು.</translation>
<translation id="3486220673238053218">ವಿವರಣೆ</translation>
+<translation id="3557673793733683882">ಶಿರೋನಾಮೆ <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">ಚಲನಚಿತ್ರ ಬಾಕಿ ಉಳಿದಿರುವ ಸೆಕುಂಡುಗಳ ಸಂಖ್ಯೆ</translation>
<translation id="3706100364254443312">ಸ್ವಿಚ್</translation>
<translation id="3732799496749320381">ಮಿಮೀ</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">ನಿಯಮ</translation>
<translation id="3822383571486410024">ಈ ಪಠ್ಯವನ್ನು <ph name="MIN_CHARACTERS" /> ಅಕ್ಷರಗಳಿಗೆ ಅಥವಾ ಅದಕ್ಕಿಂತಲೂ ಹೆಚ್ಚಿಗೆ ಸೀಮಿತಗೊಳಿಸಿ (ನೀವು ಪ್ರಸ್ತುತವಾಗಿ <ph name="CURRENT_LENGTH" /> ಅಕ್ಷರಗಳನ್ನು ಬಳಸುತ್ತಿರುವಿರಿ).</translation>
<translation id="383465348367842624">'<ph name="ATSIGN" />' ನಂತರದ ಭಾಗವು '<ph name="INVALIDCHARACTER" />' ಚಿಹ್ನೆಯನ್ನು ಒಳಗೊಂಡಿರಬಾರದು.</translation>
+<translation id="3924558731517983934">ಅಪ್ಲಿಕೇಶನ್</translation>
+<translation id="3960700977367013758">ಸ್ಕ್ರಾಲ್ ಪಟ್ಟಿ</translation>
<translation id="4103419683916926126">ಮಿಲಿಸೆಕೆಂಡುಗಳು</translation>
+<translation id="4151657705144244502">ಗ್ರಾಫಿಕ್</translation>
<translation id="4201051445878709314">ಹಿಂದಿನ ತಿಂಗಳು ತೋರಿಸು</translation>
<translation id="4202807286478387388">ಹಾರು</translation>
+<translation id="421884353938374759">ಬಣ್ಣದ ಆಯ್ಕೆಮಾಡುವಿಕೆ</translation>
+<translation id="4248100235867064564">ಮೆನು ಬಾರ್‌</translation>
+<translation id="4254339807215791271">ವಿಷಯ ಮಾಹಿತಿ</translation>
<translation id="4360991593054037559">ಮಾನ್ಯವಾದ ಮೌಲ್ಯವನ್ನು ನಮೂದಿಸಿ. <ph name="VALID_VALUE_LOW" /> ಮತ್ತು <ph name="VALID_VALUE_HIGHER" /> ಎರಡು ಹತ್ತಿರದ ಮಾನ್ಯ ಮೌಲ್ಯಗಳಾಗಿವೆ.</translation>
+<translation id="4413860115965805769">ಮೆನು ಬಟನ್</translation>
<translation id="4522570452068850558">ವಿವರಗಳು</translation>
<translation id="4597532268155981612">ಫಾರ್ಮ್</translation>
+<translation id="4661075872484491155">ಮರ</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' ನಂತರದ ಭಾಗವು '<ph name="INVALIDCHARACTER" />' ಚಿಹ್ನೆಯನ್ನು ಒಳಗೊಂಡಿರಬಾರದು.</translation>
+<translation id="4757246831282535685">ಟ್ಯಾಬ್ ಫಲಕ</translation>
<translation id="4763480195061959176">ವೀಡಿಯೊ</translation>
+<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">ದಯವಿಟ್ಟು ಸಂಖ್ಯೆಯನ್ನು ನಮೂದಿಸಿ.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> ಆಯ್ಕೆ ಮಾಡಲಾಗಿದೆ</translation>
<translation id="49969490063480558">'<ph name="ATSIGN" />' ನಂತರದ ಒಂದು ಭಾಗವನ್ನು ನಮೂದಿಸಿ. '<ph name="INVALIDADDRESS" />' ಅಪೂರ್ಣವಾಗಿದೆ.</translation>
+<translation id="5034860022980953847">ಪ್ರಗತಿ ಸೂಚಕ</translation>
<translation id="5048533449481078685">ಪಟ್ಟಿ ಗುರುತು</translation>
<translation id="5117590920725113268">ಮುಂದಿನ ತಿಂಗಳು ತೋರಿಸಿ</translation>
+<translation id="512758898067543763">ಸಾಲಿನ ಶಿರೋನಾಮೆ</translation>
<translation id="5164977714490026579">ಮೌಲ್ಯವು <ph name="MINIMUM" /> ಕ್ಕಿಂತಲೂ ಹೆಚ್ಚಾಗಿರಬೇಕು ಅಥವಾ ಸಮನಾಗಿರಬೇಕು.</translation>
<translation id="5307600278924710095">'<ph name="ATSIGN" />' ನಂತರದ ಭಾಗವನ್ನು ನಮೂದಿಸಿ. '<ph name="INVALIDADDRESS" />' ಅಪೂರ್ಣವಾಗಿದೆ.</translation>
+<translation id="5317780077021120954">ಉಳಿಸು</translation>
<translation id="5406322316791861025">ಆಕೃತಿ</translation>
+<translation id="5453733299334684579">ಟ್ರೀ ಐಟಂ</translation>
<translation id="5466621249238537318">ದಯವಿಟ್ಟು ಒಂದು ಅಥವಾ ಹೆಚ್ಚು ಫೈಲ್‌ಗಳನ್ನು ಆಯ್ಕೆಮಾಡಿ.</translation>
<translation id="5468998798572797635">ಪೂರ್ಣಪರದೆಯಿಂದ ನಿರ್ಗಮಿಸು</translation>
<translation id="5476505524087279545">ಪರೀಕ್ಷಿಸಬೇಡಿ</translation>
+<translation id="5516424706154626233">ದಿನಾಂಕದ ಪಿಕರ್</translation>
<translation id="5546461542133609677">ಅನ್‌ಮ್ಯೂಟ್ ಮಾಡು</translation>
+<translation id="561939826962581046">ಸಮಯ</translation>
<translation id="5641012560118721995">ಪ್ಲೇಬ್ಯಾಕ್ ವಿರಾಮಗೊಳಿಸು</translation>
+<translation id="5643186887447432888">ಬಟನ್</translation>
<translation id="5843503607508392247">ಇತರೆ...</translation>
<translation id="5939518447894949180">ಮರುಹೊಂದಿಸು</translation>
<translation id="5944544982112848342">2048 (ಉನ್ನತ ಶ್ರೇಣಿ)</translation>
<translation id="5966707198760109579">ವಾರ</translation>
-<translation id="598301471034819706">ವಿಳಾಸ</translation>
+<translation id="5987525920412732405">ಸ್ಪಿನ್ ಬಟನ್</translation>
<translation id="6015796118275082299">ವರ್ಷ</translation>
+<translation id="6023896073578205740">ಪಟ್ಟಿಯ ಬಾಕ್ಸ್</translation>
<translation id="6101327004457443354">ಆಡಿಯೋ ಟ್ರ್ಯಾಕ್ ಅನ್‌ಮ್ಯೂಟ್ ಮಾಡು</translation>
<translation id="6119846243427417423">ಸಕ್ರಿಯಗೊಳಿಸು</translation>
+<translation id="6164829606128959761">ಮೀಟರ್</translation>
<translation id="6270583010843788609">ಚಲನಚಿತ್ರ ಸಮಯಮಿತಿಯ ಥಂಬ್‌</translation>
<translation id="6359256949422175976">ಚಲನಚಿತ್ರ ಸಮಯ ಸ್ಕ್ರಬ್ಬರ್ ಥಂಬ್</translation>
<translation id="6398862346408813489">ತಿಂಗಳ ಆಯ್ಕೆ ಪ್ಯಾನಲ್ ತೋರಿಸಿ</translation>
<translation id="6404546809543547843">ಆಡಿಯೊ ಸಮಯ ಸ್ಕ್ರಬ್ಬರ್</translation>
+<translation id="648732519525291180">ಸಮಯ ಪಿಕರ್</translation>
<translation id="658823671542763450">ಪೂರ್ಣ ಪರದೆ ನಮೂದಿಸು</translation>
+<translation id="6637586476836377253">ಲಾಗ್</translation>
<translation id="6643016212128521049">ತೆರವುಗೊಳಿಸಿ</translation>
<translation id="6663448176199120256">ಇತ್ತೀಚಿನ ಹುಡುಕಾಟಗಳು</translation>
<translation id="668171684555832681">ಇತರೆ...</translation>
<translation id="6692633176391053278">ಸ್ಟೀಪರ್</translation>
+<translation id="6739588121953935928">ರೂಲರ್‌</translation>
+<translation id="6755330956360078551">ಟೂಲ್‌ ಟಿಪ್‌</translation>
<translation id="6820355525329141109">ಪ್ಲಗ್-ಇನ್ ಲೋಡ್ ಮಾಡಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ.</translation>
<translation id="6843725295806269523">ಮ್ಯೂಟ್</translation>
<translation id="6845533974506654842">ಒತ್ತಿ</translation>
<translation id="6853785296079745596">ಮುಚ್ಚಿರುವ ಶೀರ್ಷಿಕೆಗಳನ್ನು ಮರೆಮಾಡಿ</translation>
+<translation id="6885760532393684712">ಡೈರೆಕ್ಟರಿ</translation>
+<translation id="6934078000481955284">ಬ್ಲಾಕ್‌ಕೋಟ್</translation>
<translation id="7057186640035488495">ಚಲನಚಿತ್ರ ಸಮಯ</translation>
<translation id="709897737746224366">ದಯವಿಟ್ಟು ವಿನಂತಿಸಿದ ಸ್ವರೂಪವನ್ನು ಹೊಂದಿಸಿ.</translation>
<translation id="7223624360433298498">ಕಳೆದುಹೋದ ಸಮಯ</translation>
<translation id="7263440858009898357">ಪಟ್ಟಿಯಲ್ಲಿನ ಐಟಂ ಅನ್ನು ದಯವಿಟ್ಟು ಆಯ್ಕೆ ಮಾಡಿ.</translation>
+<translation id="727747134524199931">ಕಾಲಮ್ ಶಿರೋನಾಮೆ</translation>
<translation id="7364796246159120393">ಫೈಲ್ ಆಯ್ಕೆ ಮಾಡಿ</translation>
<translation id="739024184232394898">ಇತರೆ...</translation>
+<translation id="7491962110804786152">ಟ್ಯಾಬ್</translation>
<translation id="7673697353781729403">ಗಂಟೆಗಳು</translation>
<translation id="7720026100085573005">ಉಳಿದಿರುವ ಸಮಯ</translation>
<translation id="7740016676195725605">ಮುಚ್ಚಲಾಗಿರುವ ಶೀರ್ಷಿಕೆಗಳ ಪ್ರದರ್ಶಿಸುವಿಕೆಯನ್ನು ನಿಲ್ಲಿಸಿ</translation>
<translation id="7740050170769002709">HTML ವಿಷಯ</translation>
<translation id="7789962463072032349">ವಿರಾಮ</translation>
+<translation id="7802800022689234070">ತ್ರಿಕೋನ ಪ್ರಕಟಣೆ</translation>
<translation id="7888071071722539607">ಇಮೇಲ್ ವಿಳಾಸದಲ್ಲಿ ಒಂದು '<ph name="ATSIGN" />' ಅನ್ನು ಸೇರಿಸಿ. '<ph name="ATSIGN" />' ನಲ್ಲಿ '<ph name="INVALIDADDRESS" />' ಕಾಣೆಯಾಗಿದೆ.</translation>
+<translation id="7891486169920085145">ಛೇದಕ</translation>
<translation id="795667975304826397">ಯಾವುದೇ ಫೈಲ್ ಆಯ್ಕೆ ಮಾಡಿಲ್ಲ</translation>
<translation id="8053789581856978548">ಪಠ್ಯ ಕ್ಷೇತ್ರವನ್ನು ಹುಡುಕಿ</translation>
<translation id="8115662671911883373">ಮುಚ್ಚಲಾಗಿರುವ ಶೀರ್ಷಿಕೆಗಳ ಪ್ರದರ್ಶಿಸುವಿಕೆಯನ್ನು ಪ್ರಾರಂಭಿಸಿ</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">ಇಮೇಜ್ ನಕ್ಷೆ</translation>
<translation id="835897206747267392">ಅಮಾನ್ಯ ಮೌಲ್ಯ.</translation>
<translation id="838869780401515933">ಪರಿಶೀಲಿಸು</translation>
+<translation id="8433900881053900389">ಟೂಲ್‌ಬಾರ್</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ಫೈಲ್‌ಗಳು</translation>
<translation id="8451268428117625855">ದಯವಿಟ್ಟು ಫೈಲ್ ಆಯ್ಕೆಮಾಡಿ.</translation>
+<translation id="8461852803063341183">ರೇಡಿಯೋ ಬಟನ್</translation>
+<translation id="8511325616783751178">ಡ್ರಾಪ್ ಡೌನ್ ಬಟನ್</translation>
<translation id="8534579021159131403">ನಿಮಿಷಗಳು</translation>
<translation id="8541249477527128034">ಮಾಧ್ಯಮ ನಿಯಂತ್ರಣ</translation>
<translation id="8583702881314752957">ವಿವರಣೆ ಪಟ್ಟಿ</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">ಪ್ಲೇಬ್ಯಾಕ್ ಪ್ರಾರಂಭಿಸಿ</translation>
<translation id="8851136666856101339">ಮುಖ್ಯ</translation>
<translation id="8987927404178983737">ತಿಂಗಳು</translation>
+<translation id="9002566407876343676">ತೆರೆ</translation>
<translation id="901493112792887934">ಸೆಕೆಂಡ್‌ಗಳಲ್ಲಿ ಪ್ರಸ್ತುತ ಸಮಯ</translation>
<translation id="9048119486235211610">ನ್ಯಾವಿಗೇಷನ್</translation>
<translation id="9050748414552849310">ಮುಚ್ಚಿರುವ ಶೀರ್ಷಿಕೆಗಳನ್ನು ತೋರಿಸಿ</translation>
+<translation id="9062295712474918030">ಡಾಕ್ಯುಮೆಂಟ್</translation>
<translation id="9108370397979208512">ಮ್ಯಾಥ್</translation>
<translation id="9132465097189459683">ಇತರೆ...</translation>
+<translation id="9138385573473225930">ಎಚ್ಚರಿಕೆ</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, <ph name="WEEK_START_DATE" /> ರಂದು ಪ್ರಾರಂಭವಾಗುತ್ತದೆ</translation>
+<translation id="947831847158436616">ಸೆಲ್</translation>
+<translation id="966787709310836684">ಮೆನು</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ko.xtb b/chromium/content/app/strings/translations/content_strings_ko.xtb
index ad076ebfa53..71c58a10e83 100644
--- a/chromium/content/app/strings/translations/content_strings_ko.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ko.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="ko">
<translation id="1014825444426747588">비어 있음</translation>
+<translation id="1018939186200882850">메뉴 항목</translation>
<translation id="1020833440720551630">오디오 트랙 음소거</translation>
<translation id="10623998915015855">전환 버튼</translation>
<translation id="1088086359088493902">초</translation>
<translation id="1171774979989969504">이메일 주소를 입력하세요.</translation>
<translation id="1188858454923323853">상호 보완</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">슬라이더</translation>
<translation id="1235745349614807883">최근 검색 삭제</translation>
+<translation id="1281252709823657822">대화상자</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">배너</translation>
<translation id="1589122976691792535">지역</translation>
<translation id="1591562245178063882">이번 달</translation>
<translation id="1637811476055996098">파일 선택</translation>
+<translation id="167575180612809735">바쁨 표시기</translation>
<translation id="1729654308190250600">비어 있지 않은 이메일 주소를 입력해 주세요.</translation>
<translation id="1758486001363313524">다른 일자...</translation>
+<translation id="1806710327868736751">알림 대화상자</translation>
+<translation id="1821985195704844674">트리 격자</translation>
<translation id="1822429046913737220">오전/오후</translation>
<translation id="1832974991323546415">원격 기기에서 재생</translation>
<translation id="1842960171412779397">선택</translation>
+<translation id="1880518467580572141">개요</translation>
<translation id="1921819250265091946">일</translation>
<translation id="1930711995431081526">상태</translation>
<translation id="1938124657309484470">값은 <ph name="MAXIMUM_DATE_OR_TIME" /> 이전이어야 합니다.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">이 텍스트를 <ph name="MAX_CHARACTERS" />자 이하로 줄이세요(현재 <ph name="CURRENT_LENGTH" />자 사용 중).</translation>
<translation id="2247351761944213033"><ph name="YEAR" />, <ph name="WEEKNUMBER" />번째 주</translation>
<translation id="2291999235780842123">체크박스</translation>
+<translation id="2335594187091864976">날짜 및 시간 선택기</translation>
<translation id="248395913932153421">일</translation>
<translation id="2507943997699731163">이 입력란을 작성하세요.</translation>
+<translation id="2508569020611168319">탭 목록</translation>
<translation id="2548326553472216322">최근 수행된 검색 없음</translation>
<translation id="2572483411312390101">재생</translation>
<translation id="2613802280814924224">유효한 값을 입력해 주세요. 가장 근접한 유효 값은 <ph name="VALID_VALUE" />입니다.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">바닥글</translation>
<translation id="2723001399770238859">오디오</translation>
<translation id="2746543609216772311">값은 <ph name="MINIMUM_DATE_OR_TIME" /> 이후여야 합니다.</translation>
+<translation id="2759744352195237655">팝업 버튼</translation>
<translation id="2761667185364618470">계속하려면 이 확인란을 선택하세요.</translation>
<translation id="2846343701378493991">1024(중간 등급)</translation>
+<translation id="2896972712917208084">라디오 그룹</translation>
<translation id="2901282870647571346">현재 영화 상태</translation>
<translation id="2908441821576996758">이메일 주소를 쉼표로 구분하여 입력하세요.</translation>
+<translation id="2931838996092594335">클릭</translation>
+<translation id="2940813599313844715">객체</translation>
<translation id="2942448076852699108">강조표시된 콘텐츠</translation>
<translation id="3040011195152428237">링크</translation>
<translation id="3075154866155599887">유효한 값을 입력하세요. 입력을 완료하지 않았거나 날짜가 잘못되었습니다.</translation>
+<translation id="3078740164268491126">표</translation>
+<translation id="3086746722712840547">note</translation>
<translation id="310520048233152454">URL을 입력하세요.</translation>
+<translation id="3175736971608411871">타이머</translation>
+<translation id="3199563858620722075">콤보 상자</translation>
<translation id="3450233048674729344">값은 <ph name="MAXIMUM" /> 이하여야 합니다.</translation>
<translation id="3486220673238053218">정의</translation>
+<translation id="3557673793733683882">제목 <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">영화 남은 시간(초)</translation>
<translation id="3706100364254443312">전환</translation>
<translation id="3732799496749320381">월</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">용어</translation>
<translation id="3822383571486410024">이 텍스트를 <ph name="MIN_CHARACTERS" />자 이상으로 늘리세요(현재 <ph name="CURRENT_LENGTH" />자 사용 중).</translation>
<translation id="383465348367842624">'<ph name="ATSIGN" />' 앞 부분에 '<ph name="INVALIDCHARACTER" />' 기호가 포함되면 안됩니다.</translation>
+<translation id="3924558731517983934">애플리케이션</translation>
+<translation id="3960700977367013758">스크롤바</translation>
<translation id="4103419683916926126">밀리초</translation>
+<translation id="4151657705144244502">그래픽</translation>
<translation id="4201051445878709314">이전 달 표시</translation>
<translation id="4202807286478387388">건너뛰기</translation>
+<translation id="421884353938374759">color picker</translation>
+<translation id="4248100235867064564">메뉴 표시줄</translation>
+<translation id="4254339807215791271">콘텐츠 정보</translation>
<translation id="4360991593054037559">유효한 값을 입력해 주세요. 가장 근접한 유효 값 2개는 <ph name="VALID_VALUE_LOW" /> 및 <ph name="VALID_VALUE_HIGHER" />입니다.</translation>
+<translation id="4413860115965805769">메뉴 버튼</translation>
<translation id="4522570452068850558">세부정보</translation>
<translation id="4597532268155981612">양식</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' 다음 부분에 '<ph name="INVALIDCHARACTER" />' 기호가 포함되면 안됩니다.</translation>
+<translation id="4757246831282535685">탭 패널</translation>
<translation id="4763480195061959176">동영상</translation>
+<translation id="479989351350248267">검색</translation>
<translation id="4812940957355064477">숫자를 입력하세요.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" />개 선택됨</translation>
<translation id="49969490063480558">'<ph name="ATSIGN" />' 뒷 부분을 입력해 주세요. '<ph name="INVALIDADDRESS" />'(이)가 완전하지 않습니다.</translation>
+<translation id="5034860022980953847">진행률 표시기</translation>
<translation id="5048533449481078685">목록 표시기</translation>
<translation id="5117590920725113268">다음 달 표시</translation>
+<translation id="512758898067543763">행 헤더</translation>
<translation id="5164977714490026579">값은 <ph name="MINIMUM" /> 이상이어야 합니다.</translation>
<translation id="5307600278924710095">'<ph name="ATSIGN" />' 앞 부분을 입력해 주세요. '<ph name="INVALIDADDRESS" />'(이)가 완전하지 않습니다.</translation>
+<translation id="5317780077021120954">저장</translation>
<translation id="5406322316791861025">그림</translation>
+<translation id="5453733299334684579">트리 항목</translation>
<translation id="5466621249238537318">파일을 한 개 이상 선택하세요.</translation>
<translation id="5468998798572797635">전체화면 닫기</translation>
<translation id="5476505524087279545">선택취소</translation>
+<translation id="5516424706154626233">날짜 선택기</translation>
<translation id="5546461542133609677">음소거 해제</translation>
+<translation id="561939826962581046">time</translation>
<translation id="5641012560118721995">재생 일시중지</translation>
+<translation id="5643186887447432888">버튼</translation>
<translation id="5843503607508392247">다른 시간...</translation>
<translation id="5939518447894949180">초기화</translation>
<translation id="5944544982112848342">2048(높은 등급)</translation>
<translation id="5966707198760109579">주</translation>
-<translation id="598301471034819706">주소</translation>
+<translation id="5987525920412732405">스핀 버튼</translation>
<translation id="6015796118275082299">연도</translation>
+<translation id="6023896073578205740">목록 상자</translation>
<translation id="6101327004457443354">오디오 트랙 음소거 해제</translation>
<translation id="6119846243427417423">활성화</translation>
+<translation id="6164829606128959761">미터</translation>
<translation id="6270583010843788609">영화 타임라인 썸</translation>
<translation id="6359256949422175976">영화 시간 스크러버 썸</translation>
<translation id="6398862346408813489">월 선택 패널 표시</translation>
<translation id="6404546809543547843">오디오 시간 스크러버</translation>
+<translation id="648732519525291180">시간 선택기</translation>
<translation id="658823671542763450">전체화면 열기</translation>
+<translation id="6637586476836377253">log</translation>
<translation id="6643016212128521049">삭제</translation>
<translation id="6663448176199120256">최근 수행된 검색</translation>
<translation id="668171684555832681">기타...</translation>
<translation id="6692633176391053278">증감자</translation>
+<translation id="6739588121953935928">눈금자</translation>
+<translation id="6755330956360078551">도움말</translation>
<translation id="6820355525329141109">플러그인을 로드할 수 없습니다.</translation>
<translation id="6843725295806269523">음소거</translation>
<translation id="6845533974506654842">누르기</translation>
<translation id="6853785296079745596">캡션 숨기기</translation>
+<translation id="6885760532393684712">디렉토리</translation>
+<translation id="6934078000481955284">인용구</translation>
<translation id="7057186640035488495">영화 시간</translation>
<translation id="709897737746224366">요청한 형식과 일치시키세요.</translation>
<translation id="7223624360433298498">경과 시간</translation>
<translation id="7263440858009898357">목록에서 항목을 선택하세요.</translation>
+<translation id="727747134524199931">열 헤더</translation>
<translation id="7364796246159120393">파일 선택</translation>
<translation id="739024184232394898">다른 주...</translation>
+<translation id="7491962110804786152">tab</translation>
<translation id="7673697353781729403">시간</translation>
<translation id="7720026100085573005">남은 시간</translation>
<translation id="7740016676195725605">캡션 표시 중지</translation>
<translation id="7740050170769002709">HTML 콘텐츠</translation>
<translation id="7789962463072032349">일시중지</translation>
+<translation id="7802800022689234070">펼치기/접기 삼각형</translation>
<translation id="7888071071722539607">이메일 주소에 '<ph name="ATSIGN" />'를 포함해 주세요. '<ph name="INVALIDADDRESS" />'에 '<ph name="ATSIGN" />'가 없습니다.</translation>
+<translation id="7891486169920085145">분할선</translation>
<translation id="795667975304826397">선택된 파일 없음</translation>
<translation id="8053789581856978548">검색어 입력란</translation>
<translation id="8115662671911883373">캡션 표시 시작</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">이미지 지도</translation>
<translation id="835897206747267392">값이 잘못되었습니다.</translation>
<translation id="838869780401515933">선택</translation>
+<translation id="8433900881053900389">툴바</translation>
<translation id="8444882422881193423">파일 <ph name="NUMBER_OF_FILES" />개</translation>
<translation id="8451268428117625855">파일을 선택하세요.</translation>
+<translation id="8461852803063341183">라디오 버튼</translation>
+<translation id="8511325616783751178">드롭다운 버튼</translation>
<translation id="8534579021159131403">분</translation>
<translation id="8541249477527128034">미디어 컨트롤</translation>
<translation id="8583702881314752957">정의 목록</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">재생 시작</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8987927404178983737">월</translation>
+<translation id="9002566407876343676">열기</translation>
<translation id="901493112792887934">현재 시간(초)</translation>
<translation id="9048119486235211610">탐색</translation>
<translation id="9050748414552849310">캡션 표시</translation>
+<translation id="9062295712474918030">문서</translation>
<translation id="9108370397979208512">math</translation>
<translation id="9132465097189459683">다른 달...</translation>
+<translation id="9138385573473225930">알림</translation>
<translation id="9155987714137265666"><ph name="WEEK" />(<ph name="WEEK_START_DATE" />에 시작)</translation>
+<translation id="947831847158436616">셀</translation>
+<translation id="966787709310836684">메뉴</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_lt.xtb b/chromium/content/app/strings/translations/content_strings_lt.xtb
index 21642cdd3a9..acc8d3632b3 100644
--- a/chromium/content/app/strings/translations/content_strings_lt.xtb
+++ b/chromium/content/app/strings/translations/content_strings_lt.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="lt">
<translation id="1014825444426747588">tuščia</translation>
+<translation id="1018939186200882850">meniu elementas</translation>
<translation id="1020833440720551630">nutildyti garso įrašo takelį</translation>
<translation id="10623998915015855">perjungimo mygtukas</translation>
<translation id="1088086359088493902">Sekundės</translation>
<translation id="1171774979989969504">Įveskite el. pašto adresą.</translation>
<translation id="1188858454923323853">papildomas</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">šliaužiklis</translation>
<translation id="1235745349614807883">Išvalyti pastarąsias paieškas</translation>
+<translation id="1281252709823657822">dialogo langas</translation>
<translation id="1342835525016946179">artikelis</translation>
<translation id="1359897965706325498">reklamjuostė</translation>
<translation id="1589122976691792535">regionas</translation>
<translation id="1591562245178063882">Šis mėnuo</translation>
<translation id="1637811476055996098">Pasirinkti failus</translation>
+<translation id="167575180612809735">užimtumo indikatorius</translation>
<translation id="1729654308190250600">Įveskite el. pašto adresą (nepalikite lauko tuščio).</translation>
<translation id="1758486001363313524">Kita...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">medžio tinklelis</translation>
<translation id="1822429046913737220">iki pietų / po pietų</translation>
<translation id="1832974991323546415">leisti naudojant nuotolinį įrenginį</translation>
<translation id="1842960171412779397">pasirinkti</translation>
+<translation id="1880518467580572141">kontūras</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">būsena</translation>
<translation id="1938124657309484470">Vertė turi būti <ph name="MAXIMUM_DATE_OR_TIME" /> ar ankstesnė data.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Sutrumpinkite šį tekstą iki <ph name="MAX_CHARACTERS" /> simb. ar mažiau (šiuo metu naudojate <ph name="CURRENT_LENGTH" /> simb.).</translation>
<translation id="2247351761944213033"><ph name="YEAR" /> m. <ph name="WEEKNUMBER" /> sav.</translation>
<translation id="2291999235780842123">žymimasis laukelis</translation>
+<translation id="2335594187091864976">datos ir laiko rinkiklis</translation>
<translation id="248395913932153421">Diena</translation>
<translation id="2507943997699731163">Užpildykite šį lauką.</translation>
+<translation id="2508569020611168319">skirtukų sąrašas</translation>
<translation id="2548326553472216322">Pastaruoju metu paieškų nevykdyta</translation>
<translation id="2572483411312390101">paleisti</translation>
<translation id="2613802280814924224">Įveskite tinkamą vertę. Artimiausia tinkama vertė yra <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">poraštė</translation>
<translation id="2723001399770238859">garso įrašas</translation>
<translation id="2746543609216772311">Vertė turi būti <ph name="MINIMUM_DATE_OR_TIME" /> ar vėlesnė data.</translation>
+<translation id="2759744352195237655">Iššokantysis mygtukas</translation>
<translation id="2761667185364618470">Jei norite tęsti, pažymėkite šį laukelį.</translation>
<translation id="2846343701378493991">1024 (vidutinio lygio)</translation>
+<translation id="2896972712917208084">akučių grupė</translation>
<translation id="2901282870647571346">dabartinė filmo būsena</translation>
<translation id="2908441821576996758">Įveskite kableliais atskirtą el. pašto adresų sąrašą.</translation>
+<translation id="2931838996092594335">spustelėti</translation>
+<translation id="2940813599313844715">objektas</translation>
<translation id="2942448076852699108">paryškintas turinys</translation>
<translation id="3040011195152428237">nuoroda</translation>
<translation id="3075154866155599887">Įveskite tinkamą vertę. Laukas užpildytas nevisiškai arba įvesta netinkama data.</translation>
+<translation id="3078740164268491126">lentelė</translation>
+<translation id="3086746722712840547">pastaba</translation>
<translation id="310520048233152454">Įveskite URL.</translation>
+<translation id="3175736971608411871">laikmatis</translation>
+<translation id="3199563858620722075">jungtinis laukelis</translation>
<translation id="3450233048674729344">Vertė turi būti <ph name="MAXIMUM" /> arba mažesnė.</translation>
<translation id="3486220673238053218">apibrėžimas</translation>
+<translation id="3557673793733683882"><ph name="HEADING_LEVEL" /> antraštė</translation>
<translation id="3632707345189162177">likusių filmo sekundžių skaičius</translation>
<translation id="3706100364254443312">jungiklis</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">terminas</translation>
<translation id="3822383571486410024">Pailginkite šį tekstą iki <ph name="MIN_CHARACTERS" /> simb. ar daugiau (šiuo metu naudojate <ph name="CURRENT_LENGTH" /> simb.).</translation>
<translation id="383465348367842624">Prieš „<ph name="ATSIGN" />“ esančioje dalyje neturėtų būti simbolio „<ph name="INVALIDCHARACTER" />“.</translation>
+<translation id="3924558731517983934">programa</translation>
+<translation id="3960700977367013758">slinkties juosta</translation>
<translation id="4103419683916926126">Milisekundės</translation>
+<translation id="4151657705144244502">grafinis elementas</translation>
<translation id="4201051445878709314">Rodyti ankstesnį mėnesį</translation>
<translation id="4202807286478387388">peršokti</translation>
+<translation id="421884353938374759">spalvos parinkiklis</translation>
+<translation id="4248100235867064564">meniu juosta</translation>
+<translation id="4254339807215791271">turinio informacija</translation>
<translation id="4360991593054037559">Įveskite galiojančią vertę. Dvi artimiausios vertės yra <ph name="VALID_VALUE_LOW" /> ir <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">meniu mygtukas</translation>
<translation id="4522570452068850558">Išsami informacija</translation>
<translation id="4597532268155981612">forma</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Po „<ph name="ATSIGN" />“ esančioje dalyje neturėtų būti simbolio „<ph name="INVALIDCHARACTER" />“.</translation>
+<translation id="4757246831282535685">skirtuko skydelis</translation>
<translation id="4763480195061959176">vaizdo įrašas</translation>
+<translation id="479989351350248267">ieškoti</translation>
<translation id="4812940957355064477">Įveskite skaičių.</translation>
<translation id="4975562563186953947">Pasirinkta: <ph name="SELECTED_COUNT" /></translation>
<translation id="49969490063480558">Įveskite dalį po „<ph name="ATSIGN" />“. „<ph name="INVALIDADDRESS" />“ nėra visas el. pašto adresas.</translation>
+<translation id="5034860022980953847">eigos indikatorius</translation>
<translation id="5048533449481078685">sąrašo žymeklis</translation>
<translation id="5117590920725113268">Rodyti kitą mėnesį</translation>
+<translation id="512758898067543763">eilutės antraštė</translation>
<translation id="5164977714490026579">Vertė turi būti <ph name="MINIMUM" /> arba didesnė.</translation>
<translation id="5307600278924710095">Įveskite el. pašto adreso dalį iki „<ph name="ATSIGN" />“. „<ph name="INVALIDADDRESS" />“ nėra visas el. pašto adresas.</translation>
+<translation id="5317780077021120954">Išsaugoti</translation>
<translation id="5406322316791861025">iliustracija</translation>
+<translation id="5453733299334684579">medžio elementas</translation>
<translation id="5466621249238537318">Pasirinkite bent vieną failą.</translation>
<translation id="5468998798572797635">išeiti iš viso ekrano režimo</translation>
<translation id="5476505524087279545">Nuimti žymėjimą</translation>
+<translation id="5516424706154626233">datos rinkiklis</translation>
<translation id="5546461542133609677">įjungti garsą</translation>
+<translation id="561939826962581046">time</translation>
<translation id="5641012560118721995">pristabdyti atkūrimą</translation>
+<translation id="5643186887447432888">mygtukas</translation>
<translation id="5843503607508392247">Kita...</translation>
<translation id="5939518447894949180">Nustatyti iš naujo</translation>
<translation id="5944544982112848342">2048 (Aukšto laipsnio)</translation>
<translation id="5966707198760109579">Savaitė</translation>
-<translation id="598301471034819706">adresas</translation>
+<translation id="5987525920412732405">sukimo mygtukas</translation>
<translation id="6015796118275082299">Metai</translation>
+<translation id="6023896073578205740">sąrašo laukelis</translation>
<translation id="6101327004457443354">įjungti garso įrašo takelio garsą</translation>
<translation id="6119846243427417423">aktyvinti</translation>
+<translation id="6164829606128959761">matuoklis</translation>
<translation id="6270583010843788609">filmo laiko juostos miniatiūra</translation>
<translation id="6359256949422175976">filmo laiko valdiklio miniatiūra</translation>
<translation id="6398862346408813489">Rodyti mėnesio pasirinkimo skydelį</translation>
<translation id="6404546809543547843">garso laiko valdiklis</translation>
+<translation id="648732519525291180">laiko rinkiklis</translation>
<translation id="658823671542763450">įjungti viso ekrano režimą</translation>
+<translation id="6637586476836377253">log</translation>
<translation id="6643016212128521049">Išvalyti</translation>
<translation id="6663448176199120256">Naujausios paieškos</translation>
<translation id="668171684555832681">Kita...</translation>
<translation id="6692633176391053278">ėjimo aukštyn / žemyn valdiklis</translation>
+<translation id="6739588121953935928">liniuotė</translation>
+<translation id="6755330956360078551">patarimas</translation>
<translation id="6820355525329141109">Nepavyko įkelti papildinio.</translation>
<translation id="6843725295806269523">nutildyti</translation>
<translation id="6845533974506654842">paspausti</translation>
<translation id="6853785296079745596">slėpti subtitrus</translation>
+<translation id="6885760532393684712">katalogas</translation>
+<translation id="6934078000481955284">citata</translation>
<translation id="7057186640035488495">filmo laikas</translation>
<translation id="709897737746224366">Priderinkite reikalaujamą formatą.</translation>
<translation id="7223624360433298498">praėjęs laikas</translation>
<translation id="7263440858009898357">Pasirinkite sąraše pateiktą elementą.</translation>
+<translation id="727747134524199931">stulpelio antraštė</translation>
<translation id="7364796246159120393">Pasirinkti failą</translation>
<translation id="739024184232394898">Kita...</translation>
+<translation id="7491962110804786152">Tabuliavimo klavišas</translation>
<translation id="7673697353781729403">Valandos</translation>
<translation id="7720026100085573005">likęs laikas</translation>
<translation id="7740016676195725605">nebepateikti subtitrų</translation>
<translation id="7740050170769002709">HTML turinys</translation>
<translation id="7789962463072032349">pristabdyti</translation>
+<translation id="7802800022689234070">paskelbimo trikampis</translation>
<translation id="7888071071722539607">Į el. pašto adresą įtraukite „<ph name="ATSIGN" />“. „<ph name="INVALIDADDRESS" />“ trūksta „<ph name="ATSIGN" />“.</translation>
+<translation id="7891486169920085145">skaidiklis</translation>
<translation id="795667975304826397">Nepasirinktas joks failas</translation>
<translation id="8053789581856978548">paieškos teksto laukas</translation>
<translation id="8115662671911883373">pateikti subtitrus</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">paveikslėlio žemėlapis</translation>
<translation id="835897206747267392">Neteisinga vertė.</translation>
<translation id="838869780401515933">tikrinti</translation>
+<translation id="8433900881053900389">įrankių juosta</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> failai (-ų)</translation>
<translation id="8451268428117625855">Pasirinkite failą.</translation>
+<translation id="8461852803063341183">akutė</translation>
+<translation id="8511325616783751178">išskleidžiamasis mygtukas</translation>
<translation id="8534579021159131403">Minutės</translation>
<translation id="8541249477527128034">medijos valdiklis</translation>
<translation id="8583702881314752957">apibrėžimų sąrašas</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">pradėti atkūrimą</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8987927404178983737">Mėnuo</translation>
+<translation id="9002566407876343676">atidaryti</translation>
<translation id="901493112792887934">dabartinis laikas sekundėmis</translation>
<translation id="9048119486235211610">naršymas</translation>
<translation id="9050748414552849310">rodyti subtitrus</translation>
+<translation id="9062295712474918030">dokumentas</translation>
<translation id="9108370397979208512">matematika</translation>
<translation id="9132465097189459683">Kita...</translation>
+<translation id="9138385573473225930">įspėjimas</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, nuo <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">langelis</translation>
+<translation id="966787709310836684">meniu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_lv.xtb b/chromium/content/app/strings/translations/content_strings_lv.xtb
index 358d1e0b5a4..2a47086d44c 100644
--- a/chromium/content/app/strings/translations/content_strings_lv.xtb
+++ b/chromium/content/app/strings/translations/content_strings_lv.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="lv">
<translation id="1014825444426747588">tukšs</translation>
+<translation id="1018939186200882850">izvēlnes vienums</translation>
<translation id="1020833440720551630">izslēgt audio ieraksta skaņu</translation>
<translation id="10623998915015855">pārslēgšanas poga</translation>
<translation id="1088086359088493902">Sekundes</translation>
<translation id="1171774979989969504">Ievadiet e-pasta adresi.</translation>
<translation id="1188858454923323853">papildu</translation>
+<translation id="1206619573307042055">slīdošais teksts</translation>
+<translation id="1206693055195146388">slīdnis</translation>
<translation id="1235745349614807883">Dzēst nesenos meklējumus</translation>
+<translation id="1281252709823657822">dialoglodziņš</translation>
<translation id="1342835525016946179">raksts</translation>
<translation id="1359897965706325498">reklāmkarogs</translation>
<translation id="1589122976691792535">reģions</translation>
<translation id="1591562245178063882">Šis mēnesis</translation>
<translation id="1637811476055996098">Izvēlēties failus</translation>
+<translation id="167575180612809735">aizņemtības indikators</translation>
<translation id="1729654308190250600">Lūdzu, ievadiet e-pasta adresi.</translation>
<translation id="1758486001363313524">Cits...</translation>
+<translation id="1806710327868736751">brīdinājuma dialoglodziņš</translation>
+<translation id="1821985195704844674">koka režģis</translation>
<translation id="1822429046913737220">priekšpusdienā/pēcpusdienā</translation>
<translation id="1832974991323546415">atskaņot attālinātā ierīcē</translation>
<translation id="1842960171412779397">Atlasiet</translation>
+<translation id="1880518467580572141">kontūra</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">statuss</translation>
<translation id="1938124657309484470">Vērtībai ir jābūt “<ph name="MAXIMUM_DATE_OR_TIME" />” vai agrākam datumam vai laikam.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Lūdzu, saīsiniet šo tekstu līdz <ph name="MAX_CHARACTERS" /> vai mazāk zīmēm (pašreiz tas ietver <ph name="CURRENT_LENGTH" /> rakstzīmes).</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. nedēļa, <ph name="YEAR" />. gads</translation>
<translation id="2291999235780842123">izvēles rūtiņa</translation>
+<translation id="2335594187091864976">datuma un laika atlasītājs</translation>
<translation id="248395913932153421">Diena</translation>
<translation id="2507943997699731163">Aizpildiet šo lauku.</translation>
+<translation id="2508569020611168319">ciļņu saraksts</translation>
<translation id="2548326553472216322">Nav nesenu meklējumu</translation>
<translation id="2572483411312390101">atskaņot</translation>
<translation id="2613802280814924224">Lūdzu, ievadiet derīgu vērtību. Tuvākā derīgā vērtība ir <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">kājene</translation>
<translation id="2723001399770238859">audio</translation>
<translation id="2746543609216772311">Vērtībai ir jābūt “<ph name="MINIMUM_DATE_OR_TIME" />” vai vēlākam datumam vai laikam.</translation>
+<translation id="2759744352195237655">uznirstoša poga</translation>
<translation id="2761667185364618470">Lai turpinātu, atzīmējiet šo izvēles rūtiņu.</translation>
<translation id="2846343701378493991">1024 (Vidēja Atzīme)</translation>
+<translation id="2896972712917208084">radiopogu grupa</translation>
<translation id="2901282870647571346">pašreizējais filmas statuss</translation>
<translation id="2908441821576996758">Lūdzu, ievadiet ar komatu atdalītu e-pasta adrešu sarakstu.</translation>
+<translation id="2931838996092594335">noklikšķināt</translation>
+<translation id="2940813599313844715">objekts</translation>
<translation id="2942448076852699108">iezīmētais saturs</translation>
<translation id="3040011195152428237">saite</translation>
<translation id="3075154866155599887">Lūdzu, ievadiet derīgu vērtību. Šis lauks nav pabeigts, vai tajā ir norādīts nederīgs datums.</translation>
+<translation id="3078740164268491126">tabula</translation>
+<translation id="3086746722712840547">piezīme</translation>
<translation id="310520048233152454">Ievadiet URL.</translation>
+<translation id="3175736971608411871">taimeris</translation>
+<translation id="3199563858620722075">kombinētais lodziņš</translation>
<translation id="3450233048674729344">Vērtībai ir jābūt mazākai vai vienādai ar <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">definīcija</translation>
+<translation id="3557673793733683882"><ph name="HEADING_LEVEL" />. virsraksts</translation>
<translation id="3632707345189162177">atlikušais filmas laiks sekundēs</translation>
<translation id="3706100364254443312">slēdzis</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">vārds</translation>
<translation id="3822383571486410024">Lūdzu, papildiniet šo tekstu līdz vismaz <ph name="MIN_CHARACTERS" /> rakstzīmēm (pašlaik tas ietver <ph name="CURRENT_LENGTH" /> rakstzīmes).</translation>
<translation id="383465348367842624">Daļā, kas atrodas pirms zīmes <ph name="ATSIGN" />, nedrīkst būt ietverts simbols <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="3924558731517983934">lietojumprogramma</translation>
+<translation id="3960700977367013758">ritjosla</translation>
<translation id="4103419683916926126">Milisekundes</translation>
+<translation id="4151657705144244502">grafiskais elements</translation>
<translation id="4201051445878709314">Rādīt iepriekšējo mēnesi</translation>
<translation id="4202807286478387388">lekt</translation>
+<translation id="421884353938374759">krāsu izvēle</translation>
+<translation id="4248100235867064564">izvēļņu josla</translation>
+<translation id="4254339807215791271">satura informācija</translation>
<translation id="4360991593054037559">Lūdzu, ievadiet derīgu vērtību. Divas tuvākās derīgās vērtības ir <ph name="VALID_VALUE_LOW" /> un <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">izvēlnes poga</translation>
<translation id="4522570452068850558">Informācija</translation>
<translation id="4597532268155981612">veidlapa</translation>
+<translation id="4661075872484491155">koks</translation>
<translation id="4664250907885839816">Daļā, kas atrodas aiz zīmes <ph name="ATSIGN" />, nedrīkst būt ietverts simbols <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="4757246831282535685">ciļņu panelis</translation>
<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">meklēt</translation>
<translation id="4812940957355064477">Lūdzu, ievadiet skaitli.</translation>
<translation id="4975562563186953947">Atlasīti <ph name="SELECTED_COUNT" /></translation>
<translation id="49969490063480558">Lūdzu, ievadiet daļu, kas atrodas aiz zīmes <ph name="ATSIGN" />. “<ph name="INVALIDADDRESS" />” ir nepilna adrese.</translation>
+<translation id="5034860022980953847">norises indikators</translation>
<translation id="5048533449481078685">sarakstu marķieris</translation>
<translation id="5117590920725113268">Rādīt nākamo mēnesi</translation>
+<translation id="512758898067543763">rindas virsraksts</translation>
<translation id="5164977714490026579">Vērtībai ir jābūt lielākai vai vienādai ar <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Lūdzu, ievadiet daļu, kas atrodas pirms zīmes <ph name="ATSIGN" />. “<ph name="INVALIDADDRESS" />” ir nepilna adrese.</translation>
+<translation id="5317780077021120954">Saglabāt</translation>
<translation id="5406322316791861025">cipars</translation>
+<translation id="5453733299334684579">koka vienums</translation>
<translation id="5466621249238537318">Lūdzu, atlasiet vienu vai vairākus failus.</translation>
<translation id="5468998798572797635">iziet no pilnekrāna režīma</translation>
<translation id="5476505524087279545">neprbaudt</translation>
+<translation id="5516424706154626233">datuma atlasītājs</translation>
<translation id="5546461542133609677">rādīt</translation>
+<translation id="561939826962581046">laiks</translation>
<translation id="5641012560118721995">pauzēt atskaņošanu</translation>
+<translation id="5643186887447432888">poga</translation>
<translation id="5843503607508392247">Cits...</translation>
<translation id="5939518447894949180">Atiestatīt</translation>
<translation id="5944544982112848342">2048 (Augsta Atzīme)</translation>
<translation id="5966707198760109579">Nedēļa</translation>
-<translation id="598301471034819706">adrese</translation>
+<translation id="5987525920412732405">skaitītājpoga</translation>
<translation id="6015796118275082299">Gads</translation>
+<translation id="6023896073578205740">sarakstlodziņš</translation>
<translation id="6101327004457443354">ieslēgt audio ieraksta skaņu</translation>
<translation id="6119846243427417423">aktivizt</translation>
+<translation id="6164829606128959761">mērītājs</translation>
<translation id="6270583010843788609">filmas laika skalas sīktēls</translation>
<translation id="6359256949422175976">filmas laika skalas slīdņa sīktēls</translation>
<translation id="6398862346408813489">Rādīt mēneša atlases paneli</translation>
<translation id="6404546809543547843">audio laika skalas slīdnis</translation>
+<translation id="648732519525291180">laika atlasītājs</translation>
<translation id="658823671542763450">atvērt pilnekrāna režīmā</translation>
+<translation id="6637586476836377253">žurnāls</translation>
<translation id="6643016212128521049">Notīrīt</translation>
<translation id="6663448176199120256">Neseni meklējumi</translation>
<translation id="668171684555832681">Cits</translation>
<translation id="6692633176391053278">pārslēdzējs</translation>
+<translation id="6739588121953935928">lineāls</translation>
+<translation id="6755330956360078551">rīka padoms</translation>
<translation id="6820355525329141109">Nevarēja ielādēt spraudni.</translation>
<translation id="6843725295806269523">izslēgt skaņu</translation>
<translation id="6845533974506654842">nospiest</translation>
<translation id="6853785296079745596">slēpt slēgtos parakstus</translation>
+<translation id="6885760532393684712">katalogs</translation>
+<translation id="6934078000481955284">citāta bloks</translation>
<translation id="7057186640035488495">filmas laiks</translation>
<translation id="709897737746224366">Pieskaņojiet vērtību prasītajam formātam.</translation>
<translation id="7223624360433298498">pagājušais laiks</translation>
<translation id="7263440858009898357">Atlasiet vienumu sarakstā.</translation>
+<translation id="727747134524199931">slejas virsraksts</translation>
<translation id="7364796246159120393">Izvēlēties failu</translation>
<translation id="739024184232394898">Cits...</translation>
+<translation id="7491962110804786152">cilne</translation>
<translation id="7673697353781729403">Stundas</translation>
<translation id="7720026100085573005">atlikušais laiks</translation>
<translation id="7740016676195725605">apturēt slēgto parakstu rādīšanu</translation>
<translation id="7740050170769002709">HTML saturs</translation>
<translation id="7789962463072032349">pauzēt</translation>
+<translation id="7802800022689234070">satura atklāšanas trijstūris</translation>
<translation id="7888071071722539607">E-pasta adresē ietveriet zīmi <ph name="ATSIGN" />. Adresē “<ph name="INVALIDADDRESS" />” trūkst zīmes <ph name="ATSIGN" />.</translation>
+<translation id="7891486169920085145">sadalītājs</translation>
<translation id="795667975304826397">Nav izvēlēts neviens fails</translation>
<translation id="8053789581856978548">meklēšanas teksta lauks</translation>
<translation id="8115662671911883373">sākt slēgto parakstu rādīšanu</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">attēlu karte</translation>
<translation id="835897206747267392">Nederīga vērtība.</translation>
<translation id="838869780401515933">prbaudt</translation>
+<translation id="8433900881053900389">rīkjosla</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> faili</translation>
<translation id="8451268428117625855">Lūdzu, atlasiet failu.</translation>
+<translation id="8461852803063341183">radiopoga</translation>
+<translation id="8511325616783751178">nolaižamās izvēlnes poga</translation>
<translation id="8534579021159131403">Minūtes</translation>
<translation id="8541249477527128034">multivides vadība</translation>
<translation id="8583702881314752957">definīciju saraksts</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">sākt atskaņošanu</translation>
<translation id="8851136666856101339">galvenais</translation>
<translation id="8987927404178983737">Mēnesis</translation>
+<translation id="9002566407876343676">atvērt</translation>
<translation id="901493112792887934">pašreizējais laiks sekundēs</translation>
<translation id="9048119486235211610">navigācija</translation>
<translation id="9050748414552849310">rādīt slēgtos parakstus</translation>
+<translation id="9062295712474918030">dokuments</translation>
<translation id="9108370397979208512">matemātiska izteiksme</translation>
<translation id="9132465097189459683">Cits...</translation>
+<translation id="9138385573473225930">brīdinājums</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, sākot no: <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">šūna</translation>
+<translation id="966787709310836684">izvēlne</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ml.xtb b/chromium/content/app/strings/translations/content_strings_ml.xtb
index 491d1ad7f85..a8800d4ca95 100644
--- a/chromium/content/app/strings/translations/content_strings_ml.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ml.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="ml">
<translation id="1014825444426747588">ശൂന്യം</translation>
+<translation id="1018939186200882850">മെനു ഇനം</translation>
<translation id="1020833440720551630">ഓഡിയോ ട്രാക്ക് നിശബ്‌ദമാക്കുക</translation>
<translation id="10623998915015855">ടോഗിൾ ബട്ടൺ</translation>
<translation id="1088086359088493902">സെക്കൻഡ്</translation>
<translation id="1171774979989969504">ദയവായി ഒരു ഇമെയില്‍ വിലാസം നല്‍കുക.</translation>
<translation id="1188858454923323853">കോംപ്ലിമെന്ററി</translation>
+<translation id="1206619573307042055">മാർക്യൂ</translation>
+<translation id="1206693055195146388">സ്ലൈഡർ</translation>
<translation id="1235745349614807883">അടുത്തിടെയുള്ള തിരയലുകള്‍ മായ്ക്കുക</translation>
+<translation id="1281252709823657822">ഡയലോഗ്</translation>
<translation id="1342835525016946179">ലേഖനം</translation>
<translation id="1359897965706325498">ബാനർ</translation>
<translation id="1589122976691792535">പ്രദേശം</translation>
<translation id="1591562245178063882">ഈ മാസം</translation>
<translation id="1637811476055996098">ഫയലുകൾ തിരഞ്ഞെടുക്കുക</translation>
+<translation id="167575180612809735">'ബിസി ഇൻഡിക്കേറ്റർ'</translation>
<translation id="1729654308190250600">ശൂന്യമായിടാതെ, ഇമെയിൽ വിലാസം നൽകുക.</translation>
<translation id="1758486001363313524">മറ്റുള്ളവ...</translation>
+<translation id="1806710327868736751">അലേർട്ട്_ഡയലോഗ്</translation>
+<translation id="1821985195704844674">ട്രീ ഗ്രിഡ്</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">വിദൂര ഉപകരണത്തിൽ പ്ലേ ചെയ്യുക</translation>
<translation id="1842960171412779397">തിരഞ്ഞെടുക്കൂ</translation>
+<translation id="1880518467580572141">ഔട്ട്‌ലൈൻ</translation>
<translation id="1921819250265091946">തീയതി</translation>
<translation id="1930711995431081526">നില</translation>
<translation id="1938124657309484470">മൂല്യം <ph name="MAXIMUM_DATE_OR_TIME" /> എന്നതോ അതിനുമുമ്പുള്ള തീയതിയോ ആയിരിക്കണം.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">ഈ വാചകത്തെ <ph name="MAX_CHARACTERS" /> അല്ലെങ്കില്‍ അതില്‍‌ക്കുറവ് പ്രതീകങ്ങളായി ദയവായി കുറയ്ക്കുക (നിങ്ങള്‍ നിലവില്‍ <ph name="CURRENT_LENGTH" /> പ്രതീകങ്ങള്‍ ഉപയോഗിക്കുകയാണ്).</translation>
<translation id="2247351761944213033">ആഴ്‌ച <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">ചെക്ക്‌ബോക്‌സ്</translation>
+<translation id="2335594187091864976">തീയതിയും സമയ പിക്കറും</translation>
<translation id="248395913932153421">ദിവസം</translation>
<translation id="2507943997699731163">ദയവായി ഈ ഫീല്‍ഡ് പൂരിപ്പിക്കുക.</translation>
+<translation id="2508569020611168319">ടാബ് ലിസ്റ്റ്</translation>
<translation id="2548326553472216322">സമീപകാല തിരയലുകള്‍ ഇല്ല</translation>
<translation id="2572483411312390101">പ്ലേ ചെയ്യുക</translation>
<translation id="2613802280814924224">സാധുവായ ഒരു മൂല്യം നൽകുക. ഏറ്റവുമടുത്ത സാധുവായ മൂല്യം <ph name="VALID_VALUE" /> ആണ്.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">അടിക്കുറിപ്പ്</translation>
<translation id="2723001399770238859">ഓഡിയോ</translation>
<translation id="2746543609216772311">മൂല്യം <ph name="MINIMUM_DATE_OR_TIME" /> എന്നതോ അതിനുശേഷമുള്ള തീയതിയോ ആയിരിക്കണം.</translation>
+<translation id="2759744352195237655">പോപ്പ് അപ്പ് ബട്ടൺ</translation>
<translation id="2761667185364618470">നിങ്ങള്‍ തുടരാന്‍ താല്‍പ്പര്യപ്പെടുന്നെങ്കില്‍ ഈ ബോക്സ് ദയവായി പരിശോധിക്കുക.</translation>
<translation id="2846343701378493991">1024 (മീഡിയം ഗ്രേഡ്)</translation>
+<translation id="2896972712917208084">റേഡിയോ ഗ്രൂപ്പ്</translation>
<translation id="2901282870647571346">നിലവിലെ മൂവി നില</translation>
<translation id="2908441821576996758">ഇമെയില്‍ വിലാസങ്ങളുടെ കോമയാല്‍ വേര്‍തിരിച്ച ഒരു പട്ടിക ദയവായി നല്‍കുക.</translation>
+<translation id="2931838996092594335">ക്ലിക്കുചെയ്യുക</translation>
+<translation id="2940813599313844715">ഒബ്‌ജക്‌റ്റ്</translation>
<translation id="2942448076852699108">ഹൈലൈറ്റുചെയ്‌തിരിക്കുന്ന ഉള്ളടക്കം</translation>
<translation id="3040011195152428237">ലിങ്ക്</translation>
<translation id="3075154866155599887">ഒരു സാധുതയുള്ള മൂല്യം നൽകുക. ഫീൽഡ് പൂർണ്ണമല്ല അല്ലെങ്കിൽ അസാധുവായ തീയതിയിലുള്ളതാണ്.</translation>
+<translation id="3078740164268491126">പട്ടിക</translation>
+<translation id="3086746722712840547">note</translation>
<translation id="310520048233152454">ദയവായി ഒരു URL നല്‍കുക.</translation>
+<translation id="3175736971608411871">ടൈമർ</translation>
+<translation id="3199563858620722075">കോമ്പോ ബോക്‌സ്</translation>
<translation id="3450233048674729344">മൂല്യം <ph name="MAXIMUM" /> എന്നതില്‍ കുറവോ സമമോ ആയിരിക്കണം.</translation>
<translation id="3486220673238053218">നിർവചനം</translation>
+<translation id="3557673793733683882">തലക്കെട്ട് <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">മൂവിയുടെ അവശേഷിക്കുന്ന നിമിഷങ്ങളുടെ എണ്ണം</translation>
<translation id="3706100364254443312">സ്വിച്ച്</translation>
<translation id="3732799496749320381">മാസം</translation>
@@ -52,72 +71,104 @@
<translation id="3808586225841795776">പദം</translation>
<translation id="3822383571486410024">ഈ ടെക്‌സ്റ്റിന്റെ ദൈർഘ്യം <ph name="MIN_CHARACTERS" /> അല്ലെങ്കിൽ അതിൽക്കൂടുതൽ പ്രതീകങ്ങൾ നൽകി കൂട്ടുക. (നിങ്ങൾ നിലവിൽ <ph name="CURRENT_LENGTH" /> പ്രതീകങ്ങളാണ് ഉപയോഗിക്കുന്നത്).</translation>
<translation id="383465348367842624">'<ph name="ATSIGN" />' എന്നതിനുശേഷം വരുന്ന ഒരു ഭാഗത്തിൽ '<ph name="INVALIDCHARACTER" />' ചിഹ്നം ഉണ്ടാകരുത്.</translation>
+<translation id="3924558731517983934">അപ്ലിക്കേഷൻ</translation>
+<translation id="3960700977367013758">സ്‌ക്രോൾ ബാർ</translation>
<translation id="4103419683916926126">മില്ലിസെക്കൻഡ്</translation>
+<translation id="4151657705144244502">ഗ്രാഫിക്</translation>
<translation id="4201051445878709314">മുൻ മാസം കാണിക്കുക</translation>
<translation id="4202807286478387388">jump</translation>
+<translation id="421884353938374759">വർണ്ണ പിക്കർ</translation>
+<translation id="4248100235867064564">മെനു ബാർ</translation>
+<translation id="4254339807215791271">ഉള്ളടക്ക വിവരം</translation>
<translation id="4360991593054037559">സാധുവായ മൂല്യം നൽകുക. സാധുവായ ഏറ്റവുമടുത്ത രണ്ട് മൂല്യങ്ങൾ <ph name="VALID_VALUE_LOW" />, <ph name="VALID_VALUE_HIGHER" /> എന്നിവയാണ്.</translation>
-<translation id="4522570452068850558">വിശദാംശങ്ങള്‍‌</translation>
+<translation id="4413860115965805769">മെനു ബട്ടൺ</translation>
+<translation id="4522570452068850558">വിശദാംശങ്ങൾ‌</translation>
<translation id="4597532268155981612">ഫോം</translation>
+<translation id="4661075872484491155">ട്രീ</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' എന്നതിനുശേഷം വരുന്ന ഭാഗത്തിൽ '<ph name="INVALIDCHARACTER" />' ചിഹ്നം ഉണ്ടാകരുത്.</translation>
+<translation id="4757246831282535685">ടാബ് പാനൽ</translation>
<translation id="4763480195061959176">വീഡിയോ</translation>
+<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">ഒരു നമ്പർ നൽകുക.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> തിരഞ്ഞെടുത്തു</translation>
<translation id="49969490063480558">'<ph name="ATSIGN" />' എന്നതിനുശേഷം ഒരു ഭാഗം നൽകുക.'<ph name="INVALIDADDRESS" />' അപൂർണ്ണമാണ്.</translation>
+<translation id="5034860022980953847">'പ്രോഗ്രസ്' ഇൻഡിക്കേറ്റർ</translation>
<translation id="5048533449481078685">പട്ടിക മാര്‍ക്കര്‍</translation>
<translation id="5117590920725113268">അടുത്ത മാസം കാണിക്കുക</translation>
+<translation id="512758898067543763">വരി ശീർഷകം</translation>
<translation id="5164977714490026579">മൂല്യം <ph name="MINIMUM" /> എന്നതില്‍ കൂടുതലോ സമമോ ആയിരിക്കണം.</translation>
<translation id="5307600278924710095">'<ph name="ATSIGN" />' എന്നതിനുശേഷം ഒരു ഭാഗം നൽകുക.'<ph name="INVALIDADDRESS" />' അപൂർണ്ണമാണ്.</translation>
+<translation id="5317780077021120954">സംരക്ഷിക്കുക</translation>
<translation id="5406322316791861025">ആകാരം</translation>
+<translation id="5453733299334684579">ട്രീ ഇനം</translation>
<translation id="5466621249238537318">ഒന്നോ അതില്‍ക്കൂടുതലോ ഫയലുകള്‍ ദയവായി തിരഞ്ഞെടുക്കുക.</translation>
<translation id="5468998798572797635">പൂർണ്ണ സ്‌ക്രീനിൽ നിന്ന് പുറത്തുകടക്കുക</translation>
<translation id="5476505524087279545">അണ്‍ചെക്ക് ചെയ്യുക</translation>
+<translation id="5516424706154626233">തീയതി പിക്കർ</translation>
<translation id="5546461542133609677">ശബ്‌ദമുള്ളതാക്കുക</translation>
+<translation id="561939826962581046">സമയം</translation>
<translation id="5641012560118721995">പ്ലേബാക്ക് താൽക്കാലികമായി നിർത്തുക</translation>
+<translation id="5643186887447432888">ബട്ടൺ</translation>
<translation id="5843503607508392247">മറ്റുള്ളവ...</translation>
<translation id="5939518447894949180">വീണ്ടും സജ്ജീകരിക്കുക</translation>
<translation id="5944544982112848342">2048 (High Grade)</translation>
<translation id="5966707198760109579">ആഴ്‌ച</translation>
-<translation id="598301471034819706">വിലാസം</translation>
+<translation id="5987525920412732405">സ്‌പിൻ ബട്ടൺ</translation>
<translation id="6015796118275082299">വര്‍ഷം</translation>
+<translation id="6023896073578205740">ലിസ്റ്റ് ബോക്‌സ്</translation>
<translation id="6101327004457443354">ഓഡിയോ ട്രാക്ക് ശബ്‌ദമുള്ളതാക്കുക</translation>
<translation id="6119846243427417423">ആക്റ്റിവേറ്റ് ചെയ്യുക</translation>
+<translation id="6164829606128959761">മീറ്റർ</translation>
<translation id="6270583010843788609">മൂവി ടൈംലൈൻ തമ്പ്</translation>
<translation id="6359256949422175976">മൂവി ടൈം സ്‌ക്രബ്ബർ തമ്പ്</translation>
<translation id="6398862346408813489">മാസം തിരഞ്ഞെടുക്കുന്ന പാനൽ കാണിക്കുക</translation>
<translation id="6404546809543547843">ഓഡിയോ സമയ സ്‌ക്രബർ</translation>
+<translation id="648732519525291180">സമയ പിക്കർ</translation>
<translation id="658823671542763450">പൂർണ്ണ സ്‌ക്രീനിലേക്ക് പോവുക</translation>
+<translation id="6637586476836377253">ലോഗ്</translation>
<translation id="6643016212128521049">മായ്‌ക്കുക</translation>
<translation id="6663448176199120256">സമീപകാല തിരയലുകള്‍</translation>
<translation id="668171684555832681">മറ്റുള്ളവ...</translation>
<translation id="6692633176391053278">സ്റ്റെപ്പർ</translation>
+<translation id="6739588121953935928">റൂളർ</translation>
+<translation id="6755330956360078551">ടൂൾടിപ്പ്</translation>
<translation id="6820355525329141109">പ്ലഗിൻ ലോഡുചെയ്യാനായില്ല.</translation>
<translation id="6843725295806269523">നിശബ്‌ദമാക്കുക</translation>
<translation id="6845533974506654842">അമര്‍ത്തുക</translation>
<translation id="6853785296079745596">അടച്ച അടിക്കുറിപ്പുകൾ മറയ്‌ക്കുക</translation>
+<translation id="6885760532393684712">ഡയറക്‌ടറി</translation>
+<translation id="6934078000481955284">ബ്ലോക്ക്‌കോട്ട്</translation>
<translation id="7057186640035488495">മൂവി ടൈം</translation>
<translation id="709897737746224366">അഭ്യര്‍ത്ഥി ച്ചഫോര്‍മാറ്റ് ദയവായി പൊരുത്തപ്പെടുത്തുക.</translation>
<translation id="7223624360433298498">കഴിഞ്ഞ സമയം</translation>
<translation id="7263440858009898357">പട്ടികയിലെ ഒരു ഇനം ദയവായി തിരഞ്ഞെടുക്കുക</translation>
+<translation id="727747134524199931">കോളം പേര്</translation>
<translation id="7364796246159120393">ഫയല്‍ തിരഞ്ഞെടുക്കൂ</translation>
<translation id="739024184232394898">മറ്റുള്ളവ...</translation>
+<translation id="7491962110804786152">ടാബ്</translation>
<translation id="7673697353781729403">മണിക്കൂര്‍‌</translation>
<translation id="7720026100085573005">അവശേഷിക്കുന്ന സമയം</translation>
<translation id="7740016676195725605">അടച്ച അടിക്കുറിപ്പുകൾ പ്രദർശിപ്പിക്കുന്നത് നിർത്തുക</translation>
<translation id="7740050170769002709">HTML ഉള്ളടക്കം</translation>
<translation id="7789962463072032349">താല്‍‌ക്കാലികമായി നിര്‍‌ത്തുക</translation>
+<translation id="7802800022689234070">ഡിസ്‌ക്ലോഷർ ത്രികോണം</translation>
<translation id="7888071071722539607">ഇമെയിൽ വിലാസത്തിൽ '<ph name="ATSIGN" />' ഉൾപ്പെടുത്തുക. '<ph name="INVALIDADDRESS" />' എന്നതിൽ ഒരു '<ph name="ATSIGN" />' കാണുന്നില്ല.</translation>
+<translation id="7891486169920085145">സ്‌പ്ലിറ്റർ</translation>
<translation id="795667975304826397">ഒരു ഫയലും തിരഞ്ഞെടുത്തിട്ടില്ല</translation>
<translation id="8053789581856978548">തിരയൽ ടെക്‌സ്റ്റ് ഫീൽഡ്</translation>
<translation id="8115662671911883373">അടച്ച അടിക്കുറിപ്പുകൾ പ്രദർശിപ്പിക്കുന്നത് ആരംഭിക്കുക</translation>
<translation id="8117451130807776954">ഈ ആഴ്‌ച</translation>
-<translation id="8141602879876242471">ഇത് തിരയാവുന്ന സൂചികയാണ്. തിരയല്‍ കീവേഡുകള്‍ നല്‍കുക:</translation>
+<translation id="8141602879876242471">ഇത് തിരയാവുന്ന സൂചികയാണ്. തിരയൽ കീവേഡുകള്‍ നല്‍കുക:</translation>
<translation id="819205353528511139">പൂർണ്ണ സ്‌ക്രീൻ മോഡിൽ മൂവി പ്ലേ ചെയ്യുക</translation>
<translation id="8199524924445686405">വർഷം</translation>
<translation id="8244226242650769279">ഇമേജ് മാപ്പ്</translation>
<translation id="835897206747267392">അസാധുവായ മൂല്യം.</translation>
<translation id="838869780401515933">പരിശോധിക്കൂ</translation>
+<translation id="8433900881053900389">ടൂൾബാർ</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ഫയലുകള്‍</translation>
<translation id="8451268428117625855">ദയവായി ഒരു ഫയല്‍ തരം തിരഞ്ഞെടുക്കുക.</translation>
+<translation id="8461852803063341183">റേഡിയോ ബട്ടൺ</translation>
+<translation id="8511325616783751178">ഡ്രോപ്പ് ഡൗൺ ബട്ടൺ</translation>
<translation id="8534579021159131403">മിനിറ്റ്</translation>
<translation id="8541249477527128034">മീഡിയ നിയന്ത്രണം</translation>
<translation id="8583702881314752957">നിർവചന ലിസ്റ്റ്</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">പ്ലേബാക്ക് ആരംഭിക്കുക</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8987927404178983737">മാസം</translation>
+<translation id="9002566407876343676">തുറക്കുക</translation>
<translation id="901493112792887934">നിലവിലെ സമയം നിമിഷങ്ങളിൽ</translation>
<translation id="9048119486235211610">നാവിഗേഷൻ</translation>
<translation id="9050748414552849310">അടച്ച അടിക്കുറിപ്പുകൾ കാണിക്കുക</translation>
+<translation id="9062295712474918030">പ്രമാണം</translation>
<translation id="9108370397979208512">മാത്ത്</translation>
<translation id="9132465097189459683">മറ്റുള്ളവ...</translation>
+<translation id="9138385573473225930">അലേർട്ട്</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, <ph name="WEEK_START_DATE" />-ന് ആരംഭിക്കുന്നു</translation>
+<translation id="947831847158436616">സെൽ</translation>
+<translation id="966787709310836684">മെനു</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_mr.xtb b/chromium/content/app/strings/translations/content_strings_mr.xtb
index fc986546d67..1ce9f37c917 100644
--- a/chromium/content/app/strings/translations/content_strings_mr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_mr.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="mr">
<translation id="1014825444426747588">रिक्त</translation>
+<translation id="1018939186200882850">मेनू आयटम</translation>
<translation id="1020833440720551630">ऑडिओ ट्रॅक निःशब्द करा</translation>
<translation id="10623998915015855">टॉगल बटण</translation>
<translation id="1088086359088493902">सेकंद</translation>
<translation id="1171774979989969504">कृपया एक ईमेल पत्ता प्रविष्ट करा.</translation>
<translation id="1188858454923323853">पूरक</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">स्लायडर</translation>
<translation id="1235745349614807883">अलीकडील शोध साफ करा</translation>
+<translation id="1281252709823657822">संवाद</translation>
<translation id="1342835525016946179">लेख</translation>
<translation id="1359897965706325498">बॅनर</translation>
<translation id="1589122976691792535">प्रदेश</translation>
<translation id="1591562245178063882">या महिन्यात</translation>
<translation id="1637811476055996098">फायली निवडा</translation>
+<translation id="167575180612809735">व्यस्त सूचक</translation>
<translation id="1729654308190250600">कृपया एक रिक्त-नसलेला ईमेल पत्ता प्रविष्ट करा.</translation>
<translation id="1758486001363313524">अन्य...</translation>
+<translation id="1806710327868736751">सूचना_संवाद</translation>
+<translation id="1821985195704844674">ट्री ग्रीड</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">दूरस्थ डिव्हाइसवर प्ले करा</translation>
<translation id="1842960171412779397">निवडा</translation>
+<translation id="1880518467580572141">बाह्यरेखा</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">स्थिती</translation>
<translation id="1938124657309484470">मूल्य <ph name="MAXIMUM_DATE_OR_TIME" /> किंवा आधीचे असणे आवश्यक आहे.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">कृपया हा मजकूर <ph name="MAX_CHARACTERS" /> वर्ण लहान किंवा कमी करा (आपण सध्या <ph name="CURRENT_LENGTH" /> वर्ण वापरत आहात).</translation>
<translation id="2247351761944213033">आठवडा <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">चेकबॉक्‍स</translation>
+<translation id="2335594187091864976">तारीख आणि वेळ निवडक</translation>
<translation id="248395913932153421">दिवस</translation>
<translation id="2507943997699731163">कृपया हे फील्ड भरा.</translation>
+<translation id="2508569020611168319">टॅब सूची</translation>
<translation id="2548326553472216322">अलीकडील शोध नाहीत</translation>
<translation id="2572483411312390101">प्ले करा</translation>
<translation id="2613802280814924224">कृपया एक वैध मूल्य प्रविष्ट करा. जवळील वैध मूल्य <ph name="VALID_VALUE" /> आहे.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">अधोलेख</translation>
<translation id="2723001399770238859">ऑडिओ</translation>
<translation id="2746543609216772311">मूल्य <ph name="MINIMUM_DATE_OR_TIME" /> किंवा नंतरचे असणे आवश्यक आहे.</translation>
+<translation id="2759744352195237655">पॉप अप बटण</translation>
<translation id="2761667185364618470">कृपया आपण पुढे चालू ठेवू इच्छित असल्यास हा बॉक्स पहा.</translation>
<translation id="2846343701378493991">1024 (मध्यम प्रत)</translation>
+<translation id="2896972712917208084">रेडिओ गट</translation>
<translation id="2901282870647571346">वर्तमान चित्रपट स्थिती</translation>
<translation id="2908441821576996758">कृपया ईमेल पत्त्यांची स्वल्पविरामाद्वारे विभक्त सूची प्रविष्ट करा.</translation>
+<translation id="2931838996092594335">क्लिक करा</translation>
+<translation id="2940813599313844715">ऑब्जेक्ट</translation>
<translation id="2942448076852699108">हायलाइट केलेली सामग्री</translation>
<translation id="3040011195152428237">दुवा</translation>
<translation id="3075154866155599887">कृपया एक वैध मूल्य प्रविष्ट करा. फील्ड अपूर्ण आहे किंवा अवैध तारीख आहे.</translation>
+<translation id="3078740164268491126">सारणी</translation>
+<translation id="3086746722712840547">टीप</translation>
<translation id="310520048233152454">कृपया एखादी URL प्रविष्ट करा.</translation>
+<translation id="3175736971608411871">टायमर</translation>
+<translation id="3199563858620722075">काँबो बॉक्स</translation>
<translation id="3450233048674729344">मूल्य <ph name="MAXIMUM" /> पेक्षा कमी किंवा समान असावे.</translation>
<translation id="3486220673238053218">परिभाषा</translation>
+<translation id="3557673793733683882">शीर्षक <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">चित्रपटाचे शिल्लक सेकंद</translation>
<translation id="3706100364254443312">स्विच करा</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">संज्ञा</translation>
<translation id="3822383571486410024">कृपया हा मजकूर <ph name="MIN_CHARACTERS" /> वर्ण किंवा त्यापेक्षा अधिक मोठा करा (आपण सध्‍या <ph name="CURRENT_LENGTH" /> वर्ण वापरत आहात).</translation>
<translation id="383465348367842624">'<ph name="ATSIGN" />' मागुन येणार्‍या भागामध्ये '<ph name="INVALIDCHARACTER" />' चिन्ह नसावे.</translation>
+<translation id="3924558731517983934">अनुप्रयोग</translation>
+<translation id="3960700977367013758">स्क्रोल बार</translation>
<translation id="4103419683916926126">मिलिसेकंद</translation>
+<translation id="4151657705144244502">ग्राफिक</translation>
<translation id="4201051445878709314">मागील महिना दर्शवा</translation>
<translation id="4202807286478387388">जंप करा</translation>
+<translation id="421884353938374759">रंग निवडक</translation>
+<translation id="4248100235867064564">मेनू बार</translation>
+<translation id="4254339807215791271">सामग्री माहिती</translation>
<translation id="4360991593054037559">कृपया एक वैध मूल्य प्रविष्ट करा. दोन जवळील वैध मूल्ये <ph name="VALID_VALUE_LOW" /> आणि <ph name="VALID_VALUE_HIGHER" /> आहेत.</translation>
+<translation id="4413860115965805769">मेनू बटण</translation>
<translation id="4522570452068850558">तपशील</translation>
<translation id="4597532268155981612">फॉर्म</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' चे अनुसरण करणार्‍या भागामध्ये '<ph name="INVALIDCHARACTER" />' चिन्ह नसावे.</translation>
+<translation id="4757246831282535685">टॅब पॅनेल</translation>
<translation id="4763480195061959176">व्हिडिओ</translation>
+<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">कृपया एक नंबर प्रविष्ट करा.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> निवडले</translation>
<translation id="49969490063480558">कृपया '<ph name="ATSIGN" />' चे अनुसरण करणारा भाग प्रविष्ट करा. '<ph name="INVALIDADDRESS" />' अपूर्ण आहे.</translation>
+<translation id="5034860022980953847">प्रगती सूचक</translation>
<translation id="5048533449481078685">सूची चिन्हक</translation>
<translation id="5117590920725113268">पुढील महिना दर्शवा</translation>
+<translation id="512758898067543763">पंक्ती शीर्षलेख</translation>
<translation id="5164977714490026579">मूल्य <ph name="MINIMUM" /> पेक्षा मोठे किंवा समान असावे.</translation>
<translation id="5307600278924710095">कृपया '<ph name="ATSIGN" />' मागुन येणारा भाग प्रविष्ट करा. '<ph name="INVALIDADDRESS" />' अपूर्ण आहे.</translation>
+<translation id="5317780077021120954">जतन करा</translation>
<translation id="5406322316791861025">आकृती</translation>
+<translation id="5453733299334684579">ट्री आयटम</translation>
<translation id="5466621249238537318">कृपया एक किंवा अधिक फायली निवडा.</translation>
<translation id="5468998798572797635">पूर्ण स्क्रीनमधून निर्गमन करा</translation>
<translation id="5476505524087279545">अनचेक</translation>
+<translation id="5516424706154626233">तारीख निवडक</translation>
<translation id="5546461542133609677">सशब्द करा</translation>
+<translation id="561939826962581046">time</translation>
<translation id="5641012560118721995">प्लेबॅकला विराम द्या</translation>
+<translation id="5643186887447432888">बटण</translation>
<translation id="5843503607508392247">अन्य...</translation>
<translation id="5939518447894949180">रीसेट करा</translation>
<translation id="5944544982112848342">2048 (उच्च ग्रेड)</translation>
<translation id="5966707198760109579">आठवडा</translation>
-<translation id="598301471034819706">पत्ता</translation>
+<translation id="5987525920412732405">स्पिन बटण</translation>
<translation id="6015796118275082299">वर्ष</translation>
+<translation id="6023896073578205740">सूची बॉक्स</translation>
<translation id="6101327004457443354">ऑडिओ ट्रॅक सशब्द करा</translation>
<translation id="6119846243427417423">सक्रिय करा</translation>
+<translation id="6164829606128959761">मीटर</translation>
<translation id="6270583010843788609">चित्रपट टाइमलाइन थंब</translation>
<translation id="6359256949422175976">चित्रपट वेळ स्क्रबर थंब</translation>
<translation id="6398862346408813489">महिना निवड पॅनेल दर्शवा</translation>
<translation id="6404546809543547843">ऑडिओ वेळ स्क्रबर</translation>
+<translation id="648732519525291180">वेळ निवडक</translation>
<translation id="658823671542763450">पूर्ण स्क्रीन प्रविष्ट करा</translation>
+<translation id="6637586476836377253">लॉग</translation>
<translation id="6643016212128521049">साफ करा</translation>
<translation id="6663448176199120256">अलीकडील शोध</translation>
<translation id="668171684555832681">अन्य...</translation>
<translation id="6692633176391053278">stepper</translation>
+<translation id="6739588121953935928">मोजपट्टी</translation>
+<translation id="6755330956360078551">टूलटिप</translation>
<translation id="6820355525329141109">प्लगिन लोड करणे शक्य झाले नाही.</translation>
<translation id="6843725295806269523">नि:शब्द करा</translation>
<translation id="6845533974506654842">दाबा</translation>
<translation id="6853785296079745596">बंद मथळा लपवा</translation>
+<translation id="6885760532393684712">निर्देशिका</translation>
+<translation id="6934078000481955284">ब्लॉककोट</translation>
<translation id="7057186640035488495">चित्रपटाची वेळ</translation>
<translation id="709897737746224366">कृपया विनंती केलेले स्वरूपन जुळवा.</translation>
<translation id="7223624360433298498">लोटलेला अवधी</translation>
<translation id="7263440858009898357">कृपया सूचीमधील आयटम निवडा.</translation>
+<translation id="727747134524199931">स्तंभ शीर्षलेख</translation>
<translation id="7364796246159120393">फाइल निवडा</translation>
<translation id="739024184232394898">अन्य...</translation>
+<translation id="7491962110804786152">टॅब</translation>
<translation id="7673697353781729403">तास</translation>
<translation id="7720026100085573005">शिल्लक वेळ</translation>
<translation id="7740016676195725605">बंद मथळा प्रदर्शित करणे थांबवा</translation>
<translation id="7740050170769002709">HTML सामुग्री</translation>
<translation id="7789962463072032349">विराम द्या</translation>
+<translation id="7802800022689234070">त्रिकोण प्रकटन</translation>
<translation id="7888071071722539607">कृपया ईमेल पत्त्यामध्ये '<ph name="ATSIGN" />' समाविष्ट करा. '<ph name="INVALIDADDRESS" />' '<ph name="ATSIGN" />' गमावत आहे.</translation>
+<translation id="7891486169920085145">विभाजक</translation>
<translation id="795667975304826397">कोणतीही फाइल निवडलेली नाही</translation>
<translation id="8053789581856978548">मजकूर फील्ड दर्शवा</translation>
<translation id="8115662671911883373">बंद मथळा प्रदर्शित करणे प्रारंभ करा</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">प्रतिमा नकाशा</translation>
<translation id="835897206747267392">अवैध मूल्य.</translation>
<translation id="838869780401515933">तपासा</translation>
+<translation id="8433900881053900389">टूलबार</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> फायली</translation>
<translation id="8451268428117625855">कृपया एखादी फाइल निवडा.</translation>
+<translation id="8461852803063341183">रेडिओ बटण</translation>
+<translation id="8511325616783751178">ड्रॉप डाउन बटण</translation>
<translation id="8534579021159131403">मिनिटे</translation>
<translation id="8541249477527128034">माध्यम नियंत्रण</translation>
<translation id="8583702881314752957">परिभाषा सूची</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">प्लेबॅक आरंभ करा</translation>
<translation id="8851136666856101339">मुख्य</translation>
<translation id="8987927404178983737">महिना</translation>
+<translation id="9002566407876343676">उघडा</translation>
<translation id="901493112792887934">वर्तमान वेळ सेकंदांमध्ये</translation>
<translation id="9048119486235211610">नेव्हिगेशन</translation>
<translation id="9050748414552849310">बंद मथळा दर्शवा</translation>
+<translation id="9062295712474918030">दस्तऐवज</translation>
<translation id="9108370397979208512">गणित</translation>
<translation id="9132465097189459683">अन्य...</translation>
+<translation id="9138385573473225930">सूचना</translation>
<translation id="9155987714137265666"><ph name="WEEK_START_DATE" /> रोजी प्रारंभ होणारा, <ph name="WEEK" /></translation>
+<translation id="947831847158436616">सेल</translation>
+<translation id="966787709310836684">मेनू</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ms.xtb b/chromium/content/app/strings/translations/content_strings_ms.xtb
index 03f0cac4110..53f551a6d9b 100644
--- a/chromium/content/app/strings/translations/content_strings_ms.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ms.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="ms">
<translation id="1014825444426747588">kosong</translation>
+<translation id="1018939186200882850">item menu</translation>
<translation id="1020833440720551630">redamkan runut audio</translation>
<translation id="10623998915015855">butang togol</translation>
<translation id="1088086359088493902">Saat</translation>
<translation id="1171774979989969504">Sila masukkan alamat e-mel.</translation>
<translation id="1188858454923323853">pelengkap</translation>
+<translation id="1206619573307042055">marki</translation>
+<translation id="1206693055195146388">peluncur</translation>
<translation id="1235745349614807883">Kosongkan Carian Baru-baru Ini</translation>
+<translation id="1281252709823657822">dialog</translation>
<translation id="1342835525016946179">artikel</translation>
<translation id="1359897965706325498">sepanduk</translation>
<translation id="1589122976691792535">wilayah</translation>
<translation id="1591562245178063882">Bulan ini</translation>
<translation id="1637811476055996098">Pilih Fail</translation>
+<translation id="167575180612809735">penunjuk sibuk</translation>
<translation id="1729654308190250600">Sila masukkan alamat e-mel bukan kosong.</translation>
<translation id="1758486001363313524">Lain-lain...</translation>
+<translation id="1806710327868736751">dialog_makluman</translation>
+<translation id="1821985195704844674">grid pohon</translation>
<translation id="1822429046913737220">PG / P/M</translation>
<translation id="1832974991323546415">main pada peranti jauh</translation>
<translation id="1842960171412779397">pilih</translation>
+<translation id="1880518467580572141">garis bentuk</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">status</translation>
<translation id="1938124657309484470">Nilai mestilah <ph name="MAXIMUM_DATE_OR_TIME" /> atau lebih awal.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Sila pendekkan teks ini menjadi <ph name="MAX_CHARACTERS" /> aksara atau kurang (anda kini menggunakan <ph name="CURRENT_LENGTH" /> aksara).</translation>
<translation id="2247351761944213033">Minggu <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">kotak pilihan</translation>
+<translation id="2335594187091864976">pemilih tarikh dan masa</translation>
<translation id="248395913932153421">Hari</translation>
<translation id="2507943997699731163">Sila isikan medan ini.</translation>
+<translation id="2508569020611168319">senarai tab</translation>
<translation id="2548326553472216322">Tiada carian baru-baru ini</translation>
<translation id="2572483411312390101">main</translation>
<translation id="2613802280814924224">Sila masukkan nilai yang sah. Nilai sah yang terdekat ialah <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">pembawah</translation>
<translation id="2723001399770238859">audio</translation>
<translation id="2746543609216772311">Nilai mestilah <ph name="MINIMUM_DATE_OR_TIME" /> atau kemudian.</translation>
+<translation id="2759744352195237655">butang timbul</translation>
<translation id="2761667185364618470">Sila tandakan kotak ini jika anda mahu teruskan.</translation>
<translation id="2846343701378493991">1024 (Gred Sederhana)</translation>
+<translation id="2896972712917208084">kumpulan radio</translation>
<translation id="2901282870647571346">status filem semasa</translation>
<translation id="2908441821576996758">Sila masukkan senarai alamat e-mel yang dipisahkan dengan koma.</translation>
+<translation id="2931838996092594335">klik</translation>
+<translation id="2940813599313844715">objek</translation>
<translation id="2942448076852699108">kandungan yang diserlahkan</translation>
<translation id="3040011195152428237">pautan</translation>
<translation id="3075154866155599887">Sila masukkan nilai yang sah. Medan tidak lengkap atau mengandungi tarikh yang tidak sah.</translation>
+<translation id="3078740164268491126">jadual</translation>
+<translation id="3086746722712840547">nota</translation>
<translation id="310520048233152454">Sila masukkan URL.</translation>
+<translation id="3175736971608411871">pemasa</translation>
+<translation id="3199563858620722075">kotak kombo</translation>
<translation id="3450233048674729344">Nilai mestilah kurang daripada atau sama dengan <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">takrif</translation>
+<translation id="3557673793733683882">pengepala <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">bilangan saat filem yang tinggal</translation>
<translation id="3706100364254443312">tukar</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">istilah</translation>
<translation id="3822383571486410024">Sila panjangkan teks ini kepada <ph name="MIN_CHARACTERS" /> aksara atau lebih (anda sedang menggunakan <ph name="CURRENT_LENGTH" /> aksara).</translation>
<translation id="383465348367842624">Bahagian yang diikuti oleh '<ph name="ATSIGN" />' tidak boleh mengandungi simbol '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="3924558731517983934">aplikasi</translation>
+<translation id="3960700977367013758">bar tatal</translation>
<translation id="4103419683916926126">Milisaat</translation>
+<translation id="4151657705144244502">grafik</translation>
<translation id="4201051445878709314">Tunjukkan bulan sebelumnya</translation>
<translation id="4202807286478387388">lompat</translation>
+<translation id="421884353938374759">pemilih warna</translation>
+<translation id="4248100235867064564">bar menu</translation>
+<translation id="4254339807215791271">maklumat kandungan</translation>
<translation id="4360991593054037559">Sila masukkan nilai yang sah. Dua nilai sah yang terdekat ialah <ph name="VALID_VALUE_LOW" /> dan <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">butang menu</translation>
<translation id="4522570452068850558">Butiran</translation>
<translation id="4597532268155981612">borang</translation>
+<translation id="4661075872484491155">pohon</translation>
<translation id="4664250907885839816">Bahagian selepas '<ph name="ATSIGN" />' tidak boleh mengandungi simbol '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="4757246831282535685">panel tab</translation>
<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Sila masukkan nombor.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> dipilih</translation>
<translation id="49969490063480558">Sila masukkan bahagian selepas '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' tidak lengkap.</translation>
+<translation id="5034860022980953847">penunjuk kemajuan</translation>
<translation id="5048533449481078685">penanda senarai</translation>
<translation id="5117590920725113268">Tunjukkan bulan seterusnya</translation>
+<translation id="512758898067543763">pengepala baris</translation>
<translation id="5164977714490026579">Nilai mesti lebih besar daripada atau sama dengan <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Sila masukkan bahagian diikuti oleh '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' tidak lengkap.</translation>
+<translation id="5317780077021120954">Simpan</translation>
<translation id="5406322316791861025">angka</translation>
+<translation id="5453733299334684579">item pohon</translation>
<translation id="5466621249238537318">Sila pilih satu fail atau lebih.</translation>
<translation id="5468998798572797635">keluar daripada skrin penuh</translation>
<translation id="5476505524087279545">nyahpilih</translation>
+<translation id="5516424706154626233">pemilih tarikh</translation>
<translation id="5546461542133609677">nyahredam</translation>
+<translation id="561939826962581046">masa</translation>
<translation id="5641012560118721995">jeda main balik</translation>
+<translation id="5643186887447432888">butang</translation>
<translation id="5843503607508392247">Lain-lain...</translation>
<translation id="5939518447894949180">Tetapkan semula</translation>
<translation id="5944544982112848342">2048 (Gred Tinggi)</translation>
<translation id="5966707198760109579">Minggu</translation>
-<translation id="598301471034819706">alamat</translation>
+<translation id="5987525920412732405">butang putar</translation>
<translation id="6015796118275082299">Tahun</translation>
+<translation id="6023896073578205740">kotak senarai</translation>
<translation id="6101327004457443354">nyahredam runut audio</translation>
<translation id="6119846243427417423">aktifkan</translation>
+<translation id="6164829606128959761">meter</translation>
<translation id="6270583010843788609">ibu jari garis masa filem</translation>
<translation id="6359256949422175976">ibu jari pembersih masa filem</translation>
<translation id="6398862346408813489">Tunjukkan panel pilihan bulan</translation>
<translation id="6404546809543547843">pembersih masa audio</translation>
+<translation id="648732519525291180">pemilih masa</translation>
<translation id="658823671542763450">memasuki skrin penuh</translation>
+<translation id="6637586476836377253">log</translation>
<translation id="6643016212128521049">Kosongkan</translation>
<translation id="6663448176199120256">Carian Baru-baru Ini</translation>
<translation id="668171684555832681">Lain-lain...</translation>
<translation id="6692633176391053278">pelangkah</translation>
+<translation id="6739588121953935928">pembaris</translation>
+<translation id="6755330956360078551">tip alat</translation>
<translation id="6820355525329141109">Tidak dapat memuatkan pemalam.</translation>
<translation id="6843725295806269523">redam</translation>
<translation id="6845533974506654842">tekan</translation>
<translation id="6853785296079745596">sembunyikan kapsyen tertutup</translation>
+<translation id="6885760532393684712">direktori</translation>
+<translation id="6934078000481955284">petikan blok</translation>
<translation id="7057186640035488495">masa filem</translation>
<translation id="709897737746224366">Sila padankan dengan format yang diminta.</translation>
<translation id="7223624360433298498">masa berlalu</translation>
<translation id="7263440858009898357">Sila pilih item dalam senarai.</translation>
+<translation id="727747134524199931">pengepala lajur</translation>
<translation id="7364796246159120393">Pilih Fail</translation>
<translation id="739024184232394898">Lain-lain...</translation>
+<translation id="7491962110804786152">tab</translation>
<translation id="7673697353781729403">Jam</translation>
<translation id="7720026100085573005">masa yang tinggal</translation>
<translation id="7740016676195725605">berhenti memaparkan kapsyen tertutup</translation>
<translation id="7740050170769002709">Kandungan HTML</translation>
<translation id="7789962463072032349">jeda</translation>
+<translation id="7802800022689234070">segi tiga pendedahan</translation>
<translation id="7888071071722539607">Sila masukkan '<ph name="ATSIGN" />' dalam alamat e-mel. '<ph name="INVALIDADDRESS" />' tiada '<ph name="ATSIGN" />'.</translation>
+<translation id="7891486169920085145">pemisah</translation>
<translation id="795667975304826397">Tiada fail dipilih</translation>
<translation id="8053789581856978548">medan teks carian</translation>
<translation id="8115662671911883373">mula memaparkan kapsyen tertutup</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">peta imej</translation>
<translation id="835897206747267392">Nilai tidak sah.</translation>
<translation id="838869780401515933">periksa</translation>
+<translation id="8433900881053900389">bar alat</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> fail</translation>
<translation id="8451268428117625855">Sila pilih fail.</translation>
+<translation id="8461852803063341183">butang radio</translation>
+<translation id="8511325616783751178">butang lungsur</translation>
<translation id="8534579021159131403">Minit</translation>
<translation id="8541249477527128034">kawalan media</translation>
<translation id="8583702881314752957">senarai takrif</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">mulakan main balik</translation>
<translation id="8851136666856101339">utama</translation>
<translation id="8987927404178983737">Bulan</translation>
+<translation id="9002566407876343676">buka</translation>
<translation id="901493112792887934">masa semasa dalam saat</translation>
<translation id="9048119486235211610">navigasi</translation>
<translation id="9050748414552849310">paparkan kapsyen tertutup</translation>
+<translation id="9062295712474918030">dokumen</translation>
<translation id="9108370397979208512">matematik</translation>
<translation id="9132465097189459683">Lain-lain...</translation>
+<translation id="9138385573473225930">makluman</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, bermula pada <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">sel</translation>
+<translation id="966787709310836684">menu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_nl.xtb b/chromium/content/app/strings/translations/content_strings_nl.xtb
index 405e94a5ec5..552abf6e840 100644
--- a/chromium/content/app/strings/translations/content_strings_nl.xtb
+++ b/chromium/content/app/strings/translations/content_strings_nl.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="nl">
<translation id="1014825444426747588">leeg</translation>
+<translation id="1018939186200882850">menu-item</translation>
<translation id="1020833440720551630">audiotrack dempen</translation>
<translation id="10623998915015855">schakelknop</translation>
<translation id="1088086359088493902">Seconden</translation>
<translation id="1171774979989969504">Geef een e-mailadres op.</translation>
<translation id="1188858454923323853">aanvullend</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">schuifregelaar</translation>
<translation id="1235745349614807883">Recente zoekopdrachten wissen</translation>
+<translation id="1281252709823657822">dialoogvenster</translation>
<translation id="1342835525016946179">artikel</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">regio</translation>
<translation id="1591562245178063882">Deze maand</translation>
<translation id="1637811476055996098">Bestanden kiezen</translation>
+<translation id="167575180612809735">bezetindicator</translation>
<translation id="1729654308190250600">Geef een e-mailadres op.</translation>
<translation id="1758486001363313524">Anders...</translation>
+<translation id="1806710327868736751">dialoogvenster voor meldingen</translation>
+<translation id="1821985195704844674">boomstructuur</translation>
<translation id="1822429046913737220">a.m./p.m.</translation>
<translation id="1832974991323546415">afspelen op extern apparaat</translation>
<translation id="1842960171412779397">Selecteren</translation>
+<translation id="1880518467580572141">overzicht</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">status</translation>
<translation id="1938124657309484470">Waarde moet <ph name="MAXIMUM_DATE_OR_TIME" /> of eerder zijn.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Kort deze tekst in tot <ph name="MAX_CHARACTERS" /> tekens of minder (je gebruikt momenteel <ph name="CURRENT_LENGTH" /> tekens).</translation>
<translation id="2247351761944213033">Week <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">selectievakje</translation>
+<translation id="2335594187091864976">datum- en tijdkiezer</translation>
<translation id="248395913932153421">Dag</translation>
<translation id="2507943997699731163">Vul dit veld in.</translation>
+<translation id="2508569020611168319">tabbladlijst</translation>
<translation id="2548326553472216322">Geen recente zoekopdrachten</translation>
<translation id="2572483411312390101">afspelen</translation>
<translation id="2613802280814924224">Geef een geldige waarde op. De dichtstbijzijnde geldige waarde is <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">voettekst</translation>
<translation id="2723001399770238859">audio</translation>
<translation id="2746543609216772311">Waarde moet <ph name="MINIMUM_DATE_OR_TIME" /> of later zijn.</translation>
+<translation id="2759744352195237655">pop-upknop</translation>
<translation id="2761667185364618470">Vink dit selectievakje aan als je wilt doorgaan.</translation>
<translation id="2846343701378493991">1024 (gemiddeld niveau)</translation>
+<translation id="2896972712917208084">groep met keuzerondjes</translation>
<translation id="2901282870647571346">huidige filmstatus</translation>
<translation id="2908441821576996758">Voer een door komma's gescheiden lijst met e-mailadressen in.</translation>
+<translation id="2931838996092594335">klikken</translation>
+<translation id="2940813599313844715">object</translation>
<translation id="2942448076852699108">gemarkeerde inhoud</translation>
<translation id="3040011195152428237">link</translation>
<translation id="3075154866155599887">Voer een geldige waarde in. Het veld is onvolledig of bevat een ongeldige datum.</translation>
+<translation id="3078740164268491126">tabel</translation>
+<translation id="3086746722712840547">opmerking</translation>
<translation id="310520048233152454">Geef een URL op.</translation>
+<translation id="3175736971608411871">timer</translation>
+<translation id="3199563858620722075">keuzelijst met invoervak</translation>
<translation id="3450233048674729344">Waarde moet kleiner dan of gelijk zijn aan <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">definitie</translation>
+<translation id="3557673793733683882">koptekst <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">aantal seconden van resterende film</translation>
<translation id="3706100364254443312">schakelaar</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">term</translation>
<translation id="3822383571486410024">Breid deze tekst uit tot <ph name="MIN_CHARACTERS" /> tekens of meer (je gebruikt momenteel <ph name="CURRENT_LENGTH" /> tekens).</translation>
<translation id="383465348367842624">Het naamgedeelte vóór '<ph name="ATSIGN" />' mag niet het teken '<ph name="INVALIDCHARACTER" />' bevatten.</translation>
+<translation id="3924558731517983934">app</translation>
+<translation id="3960700977367013758">schuifbalk</translation>
<translation id="4103419683916926126">Milliseconden</translation>
+<translation id="4151657705144244502">afbeelding</translation>
<translation id="4201051445878709314">Vorige maand weergeven</translation>
<translation id="4202807286478387388">Gaan naar</translation>
+<translation id="421884353938374759">kleurkiezer</translation>
+<translation id="4248100235867064564">menubalk</translation>
+<translation id="4254339807215791271">informatie over content</translation>
<translation id="4360991593054037559">Geef een geldige waarde op. De twee dichtstbijzijnde geldige waarden zijn <ph name="VALID_VALUE_LOW" /> en <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">menuknop</translation>
<translation id="4522570452068850558">Details</translation>
<translation id="4597532268155981612">formulier</translation>
+<translation id="4661075872484491155">structuur</translation>
<translation id="4664250907885839816">Het adresgedeelte na '<ph name="ATSIGN" />' mag niet het teken '<ph name="INVALIDCHARACTER" />' bevatten.</translation>
+<translation id="4757246831282535685">deelvenster met tabblad</translation>
<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">zoeken</translation>
<translation id="4812940957355064477">Voer een getal in.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> geselecteerd</translation>
<translation id="49969490063480558">Geef een adresgedeelte op na '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' is onvolledig.</translation>
+<translation id="5034860022980953847">voortgangsindicator</translation>
<translation id="5048533449481078685">lijstmarkering</translation>
<translation id="5117590920725113268">Volgende maand weergeven</translation>
+<translation id="512758898067543763">rijkop</translation>
<translation id="5164977714490026579">Waarde moet groter dan of gelijk zijn aan <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Geef een naamgedeelte op, gevolgd door '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' is onvolledig.</translation>
+<translation id="5317780077021120954">Opslaan</translation>
<translation id="5406322316791861025">figuur</translation>
+<translation id="5453733299334684579">item in boomstructuur</translation>
<translation id="5466621249238537318">Selecteer een of meer bestanden.</translation>
<translation id="5468998798572797635">volledig scherm sluiten</translation>
<translation id="5476505524087279545">Deselecteren</translation>
+<translation id="5516424706154626233">datumkiezer</translation>
<translation id="5546461542133609677">dempen opheffen</translation>
+<translation id="561939826962581046">tijd</translation>
<translation id="5641012560118721995">afspelen onderbreken</translation>
+<translation id="5643186887447432888">knop</translation>
<translation id="5843503607508392247">Anders...</translation>
<translation id="5939518447894949180">Terugzetten</translation>
<translation id="5944544982112848342">2048 (hoog niveau)</translation>
<translation id="5966707198760109579">Week</translation>
-<translation id="598301471034819706">adres</translation>
+<translation id="5987525920412732405">kringveld</translation>
<translation id="6015796118275082299">Jaar</translation>
+<translation id="6023896073578205740">keuzelijst</translation>
<translation id="6101327004457443354">dempen van audiotrack opheffen</translation>
<translation id="6119846243427417423">Activeren</translation>
+<translation id="6164829606128959761">meter</translation>
<translation id="6270583010843788609">miniatuur van tijdlijn van film</translation>
<translation id="6359256949422175976">miniatuur van schuifbalk met tijd van de film</translation>
<translation id="6398862346408813489">Deelvenster voor maandselectie weergeven</translation>
<translation id="6404546809543547843">schuifbalk met audiotijd</translation>
+<translation id="648732519525291180">tijdkiezer</translation>
<translation id="658823671542763450">volledig scherm openen</translation>
+<translation id="6637586476836377253">logboek</translation>
<translation id="6643016212128521049">Wissen</translation>
<translation id="6663448176199120256">Recente zoekopdrachten</translation>
<translation id="668171684555832681">Anders...</translation>
<translation id="6692633176391053278">stappenregelaar</translation>
+<translation id="6739588121953935928">liniaal</translation>
+<translation id="6755330956360078551">knopinfo</translation>
<translation id="6820355525329141109">Kan plug-in niet laden.</translation>
<translation id="6843725295806269523">dempen</translation>
<translation id="6845533974506654842">Indrukken</translation>
<translation id="6853785296079745596">ondertiteling verbergen</translation>
+<translation id="6885760532393684712">directory</translation>
+<translation id="6934078000481955284">blok met geciteerde tekst</translation>
<translation id="7057186640035488495">tijd van de film</translation>
<translation id="709897737746224366">Zorg dat de indeling voldoet aan de gevraagde indeling.</translation>
<translation id="7223624360433298498">verstreken tijd</translation>
<translation id="7263440858009898357">Selecteer een item in de lijst.</translation>
+<translation id="727747134524199931">kolomkop</translation>
<translation id="7364796246159120393">Bestand kiezen</translation>
<translation id="739024184232394898">Anders...</translation>
+<translation id="7491962110804786152">tab</translation>
<translation id="7673697353781729403">Uur</translation>
<translation id="7720026100085573005">resterende tijd</translation>
<translation id="7740016676195725605">het weergeven van ondertiteling stoppen</translation>
<translation id="7740050170769002709">HTML-inhoud</translation>
<translation id="7789962463072032349">onderbreken</translation>
+<translation id="7802800022689234070">driehoek voor samen-/uitvouwen</translation>
<translation id="7888071071722539607">Gebruik een '<ph name="ATSIGN" />' in thet e-mailadres. In '<ph name="INVALIDADDRESS" />' ontbreekt een '<ph name="ATSIGN" />'.</translation>
+<translation id="7891486169920085145">splitser</translation>
<translation id="795667975304826397">Geen bestand gekozen</translation>
<translation id="8053789581856978548">zoektekstveld</translation>
<translation id="8115662671911883373">het weergeven van ondertiteling starten</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">image map</translation>
<translation id="835897206747267392">Ongeldige waarde.</translation>
<translation id="838869780401515933">Selecteren</translation>
+<translation id="8433900881053900389">werkbalk</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> bestanden</translation>
<translation id="8451268428117625855">Selecteer een bestand.</translation>
+<translation id="8461852803063341183">keuzerondje</translation>
+<translation id="8511325616783751178">dropdown-knop</translation>
<translation id="8534579021159131403">Minuten</translation>
<translation id="8541249477527128034">mediacontrole</translation>
<translation id="8583702881314752957">definitielijst</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">afspelen starten</translation>
<translation id="8851136666856101339">hoofd</translation>
<translation id="8987927404178983737">Maand</translation>
+<translation id="9002566407876343676">openen</translation>
<translation id="901493112792887934">huidige tijd in seconden</translation>
<translation id="9048119486235211610">navigatie</translation>
<translation id="9050748414552849310">ondertiteling weergeven</translation>
+<translation id="9062295712474918030">document</translation>
<translation id="9108370397979208512">wiskunde</translation>
<translation id="9132465097189459683">Anders...</translation>
+<translation id="9138385573473225930">melding</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, die begint op <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">cel</translation>
+<translation id="966787709310836684">menu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_no.xtb b/chromium/content/app/strings/translations/content_strings_no.xtb
index da055713bed..4265becbb5b 100644
--- a/chromium/content/app/strings/translations/content_strings_no.xtb
+++ b/chromium/content/app/strings/translations/content_strings_no.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="no">
<translation id="1014825444426747588">tom</translation>
+<translation id="1018939186200882850">menyelement</translation>
<translation id="1020833440720551630">slå av lydsporet</translation>
<translation id="10623998915015855">av/på-knapp</translation>
<translation id="1088086359088493902">Sekunder</translation>
<translation id="1171774979989969504">Skriv inn en e-postadresse.</translation>
<translation id="1188858454923323853">komplementær</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">glidebryter</translation>
<translation id="1235745349614807883">Fjern nylige søk</translation>
+<translation id="1281252709823657822">dialog</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">område</translation>
<translation id="1591562245178063882">Denne måneden</translation>
<translation id="1637811476055996098">Velg filer</translation>
+<translation id="167575180612809735">opptatt-indikator</translation>
<translation id="1729654308190250600">Skriv inn en ikke-tom e-postadresse.</translation>
<translation id="1758486001363313524">Andre</translation>
+<translation id="1806710327868736751">varseldialog</translation>
+<translation id="1821985195704844674">trerutenett</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">spill på ekstern enhet</translation>
<translation id="1842960171412779397">velg</translation>
+<translation id="1880518467580572141">omriss</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">status</translation>
<translation id="1938124657309484470">Verdien må være <ph name="MAXIMUM_DATE_OR_TIME" /> eller før.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Forkort denne teksten til <ph name="MAX_CHARACTERS" /> tegn eller færre (for øyeblikket bruker du <ph name="CURRENT_LENGTH" /> tegn).</translation>
<translation id="2247351761944213033">Uke <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">avmerkingsboks</translation>
+<translation id="2335594187091864976">dato- og klokkeslettvelger</translation>
<translation id="248395913932153421">Dag</translation>
<translation id="2507943997699731163">Vennligst fyll ut dette feltet.</translation>
+<translation id="2508569020611168319">faneliste</translation>
<translation id="2548326553472216322">Ingen nylige søk</translation>
<translation id="2572483411312390101">spill av</translation>
<translation id="2613802280814924224">Skriv inn en gyldig verdi. Den nærmeste, gyldige verdien er <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">fotnote</translation>
<translation id="2723001399770238859">lyd</translation>
<translation id="2746543609216772311">Verdien må være <ph name="MINIMUM_DATE_OR_TIME" /> eller senere.</translation>
+<translation id="2759744352195237655">forgrunnsknapp</translation>
<translation id="2761667185364618470">Kryss av denne boksen hvis du vil fortsette.</translation>
<translation id="2846343701378493991">1024 (middels)</translation>
+<translation id="2896972712917208084">gruppe med alternativknapper</translation>
<translation id="2901282870647571346">gjeldende filmstatus</translation>
<translation id="2908441821576996758">Skriv inn en liste over e-postadresser atskilt med komma.</translation>
+<translation id="2931838996092594335">klikk</translation>
+<translation id="2940813599313844715">objekt</translation>
<translation id="2942448076852699108">merket innhold</translation>
<translation id="3040011195152428237">link</translation>
<translation id="3075154866155599887">Skriv inn en gyldig verdi. Feltet er ufullstendig, eller har en ugyldig dato.</translation>
+<translation id="3078740164268491126">tabell</translation>
+<translation id="3086746722712840547">note</translation>
<translation id="310520048233152454">Skriv inn en nettadresse.</translation>
+<translation id="3175736971608411871">tidtaker</translation>
+<translation id="3199563858620722075">kombinasjonsfelt</translation>
<translation id="3450233048674729344">Verdien må være mindre enn eller lik <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">definisjon</translation>
+<translation id="3557673793733683882">overskrift <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">antall sekunder som gjenstår av filmen</translation>
<translation id="3706100364254443312">bryter</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">term</translation>
<translation id="3822383571486410024">Du må forlenge denne teksten til <ph name="MIN_CHARACTERS" /> tegn eller mer (for øyeblikket bruker du <ph name="CURRENT_LENGTH" /> tegn).</translation>
<translation id="383465348367842624">En del etterfulgt av «<ph name="ATSIGN" />» kan ikke inneholde symbolet «<ph name="INVALIDCHARACTER" />».</translation>
+<translation id="3924558731517983934">program</translation>
+<translation id="3960700977367013758">rullefelt</translation>
<translation id="4103419683916926126">Millisekunder</translation>
+<translation id="4151657705144244502">grafikk</translation>
<translation id="4201051445878709314">Se forrige måned</translation>
<translation id="4202807286478387388">hopp</translation>
+<translation id="421884353938374759">fargevelger</translation>
+<translation id="4248100235867064564">menyrad</translation>
+<translation id="4254339807215791271">innholdsinformasjon</translation>
<translation id="4360991593054037559">Skriv inn en gyldig verdi. De to nærmeste, gyldige verdiene er <ph name="VALID_VALUE_LOW" /> og <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">menyknapp</translation>
<translation id="4522570452068850558">Detaljer</translation>
<translation id="4597532268155981612">skjema</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">En del etterfulgt av «<ph name="ATSIGN" />» kan ikke inneholde symbolet «<ph name="INVALIDCHARACTER" />».</translation>
+<translation id="4757246831282535685">fanepanel</translation>
<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">søk</translation>
<translation id="4812940957355064477">Skriv inn et tall.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> er valgt</translation>
<translation id="49969490063480558">Skriv inn en del etterfulgt av «<ph name="ATSIGN" />». «<ph name="INVALIDADDRESS" />» er ufullstendig.</translation>
+<translation id="5034860022980953847">fremdriftsindikator</translation>
<translation id="5048533449481078685">listemarkør</translation>
<translation id="5117590920725113268">Se neste måned</translation>
+<translation id="512758898067543763">radoverskrift</translation>
<translation id="5164977714490026579">Verdien må være større enn eller lik <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Skriv inn en del etterfulgt av «<ph name="ATSIGN" />». «<ph name="INVALIDADDRESS" />» er ufullstendig.</translation>
+<translation id="5317780077021120954">Lagre</translation>
<translation id="5406322316791861025">figur</translation>
+<translation id="5453733299334684579">treelement</translation>
<translation id="5466621249238537318">Velg én eller flere filer.</translation>
<translation id="5468998798572797635">avslutt fullskjerm</translation>
<translation id="5476505524087279545">fjern merke</translation>
+<translation id="5516424706154626233">datovelger</translation>
<translation id="5546461542133609677">slå på lyden</translation>
+<translation id="561939826962581046">time</translation>
<translation id="5641012560118721995">stopp avspillingen midlertidig</translation>
+<translation id="5643186887447432888">knapp</translation>
<translation id="5843503607508392247">Andre</translation>
<translation id="5939518447894949180">Tilbakestill</translation>
<translation id="5944544982112848342">2048 (sterk)</translation>
<translation id="5966707198760109579">Uke</translation>
-<translation id="598301471034819706">adresse</translation>
+<translation id="5987525920412732405">verdisettingsknapp</translation>
<translation id="6015796118275082299">År</translation>
+<translation id="6023896073578205740">listefelt</translation>
<translation id="6101327004457443354">slå på lydsporet</translation>
<translation id="6119846243427417423">aktiver</translation>
+<translation id="6164829606128959761">måler</translation>
<translation id="6270583010843788609">filmtidslinjemarkøren</translation>
<translation id="6359256949422175976">markøren for filmtidslinjen</translation>
<translation id="6398862346408813489">Se panelet for valg av måned</translation>
<translation id="6404546809543547843">lydtidslinje</translation>
+<translation id="648732519525291180">klokkeslettvelger</translation>
<translation id="658823671542763450">gå til fullskjermmodus</translation>
+<translation id="6637586476836377253">logg</translation>
<translation id="6643016212128521049">Tøm</translation>
<translation id="6663448176199120256">Nylige søk</translation>
<translation id="668171684555832681">Annen</translation>
<translation id="6692633176391053278">stepper</translation>
+<translation id="6739588121953935928">linjal</translation>
+<translation id="6755330956360078551">verktøytips</translation>
<translation id="6820355525329141109">Kunne ikke laste inn programtillegget.</translation>
<translation id="6843725295806269523">kutt lyd</translation>
<translation id="6845533974506654842">trykk</translation>
<translation id="6853785296079745596">skjul teksting</translation>
+<translation id="6885760532393684712">katalog</translation>
+<translation id="6934078000481955284">blokksitat</translation>
<translation id="7057186640035488495">gå til et annet tidspunkt</translation>
<translation id="709897737746224366">Sørg for samsvar med det forespurte formatet.</translation>
<translation id="7223624360433298498">brukt tid</translation>
<translation id="7263440858009898357">Velg en artikkel i listen.</translation>
+<translation id="727747134524199931">kolonneoverskrift</translation>
<translation id="7364796246159120393">Velg fil</translation>
<translation id="739024184232394898">Andre</translation>
+<translation id="7491962110804786152">tab</translation>
<translation id="7673697353781729403">Timer</translation>
<translation id="7720026100085573005">tid som gjenstår</translation>
<translation id="7740016676195725605">slå av tekstingen</translation>
<translation id="7740050170769002709">HTML-innhold</translation>
<translation id="7789962463072032349">stans midlertidig</translation>
+<translation id="7802800022689234070">trekant for ekstra innhold</translation>
<translation id="7888071071722539607">Inkluder en «<ph name="ATSIGN" />» i e-postadressen. «<ph name="INVALIDADDRESS" />» mangler en «<ph name="ATSIGN" />».</translation>
+<translation id="7891486169920085145">vindusdeler</translation>
<translation id="795667975304826397">Ingen fil valgt</translation>
<translation id="8053789581856978548">søketekstfelt</translation>
<translation id="8115662671911883373">slå på tekstingen</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">bildekart</translation>
<translation id="835897206747267392">Ugyldig verdi</translation>
<translation id="838869780401515933">merk av</translation>
+<translation id="8433900881053900389">verktøyrad</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> filer</translation>
<translation id="8451268428117625855">Velg en fil.</translation>
+<translation id="8461852803063341183">alternativknapp</translation>
+<translation id="8511325616783751178">rullegardinknapp</translation>
<translation id="8534579021159131403">Minutter</translation>
<translation id="8541249477527128034">mediekontroll</translation>
<translation id="8583702881314752957">definisjonsliste</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">start avspillingen</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8987927404178983737">Måned</translation>
+<translation id="9002566407876343676">åpne</translation>
<translation id="901493112792887934">gjeldende tid i sekunder</translation>
<translation id="9048119486235211610">navigasjon</translation>
<translation id="9050748414552849310">vis teksting</translation>
+<translation id="9062295712474918030">dokument</translation>
<translation id="9108370397979208512">math</translation>
<translation id="9132465097189459683">Andre</translation>
+<translation id="9138385573473225930">varsel</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, med start <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">celle</translation>
+<translation id="966787709310836684">meny</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_pl.xtb b/chromium/content/app/strings/translations/content_strings_pl.xtb
index 26543259dd5..6277f53a751 100644
--- a/chromium/content/app/strings/translations/content_strings_pl.xtb
+++ b/chromium/content/app/strings/translations/content_strings_pl.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="pl">
<translation id="1014825444426747588">puste</translation>
+<translation id="1018939186200882850">element menu</translation>
<translation id="1020833440720551630">wycisz ścieżkę dźwiękową</translation>
<translation id="10623998915015855">przycisk przełączania</translation>
<translation id="1088086359088493902">Sekundy</translation>
<translation id="1171774979989969504">Wprowadź adres e-mail.</translation>
<translation id="1188858454923323853">pomocniczy</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">suwak</translation>
<translation id="1235745349614807883">Wyczyść ostatnie wyszukiwania</translation>
+<translation id="1281252709823657822">okno dialogowe</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">baner</translation>
<translation id="1589122976691792535">region</translation>
<translation id="1591562245178063882">W tym miesiącu</translation>
<translation id="1637811476055996098">Wybierz pliki</translation>
+<translation id="167575180612809735">wskaźnik zajętości</translation>
<translation id="1729654308190250600">Podaj adres e-mail.</translation>
<translation id="1758486001363313524">Inny...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">siatka drzewa</translation>
<translation id="1822429046913737220">rano/po południu</translation>
<translation id="1832974991323546415">odtwarzanie na urządzeniu zdalnym</translation>
<translation id="1842960171412779397">wybierz</translation>
+<translation id="1880518467580572141">schemat</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">stan</translation>
<translation id="1938124657309484470">Musisz podać wartość <ph name="MAXIMUM_DATE_OR_TIME" /> lub wcześniejszą.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Skróć ten tekst do maksymalnie <ph name="MAX_CHARACTERS" /> znaków (w tej chwili korzystasz z <ph name="CURRENT_LENGTH" /> znaków).</translation>
<translation id="2247351761944213033">Tydzień <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">pole wyboru</translation>
+<translation id="2335594187091864976">selektor daty i godziny</translation>
<translation id="248395913932153421">Dzień</translation>
<translation id="2507943997699731163">Wypełnij to pole.</translation>
+<translation id="2508569020611168319">lista kart</translation>
<translation id="2548326553472216322">Brak ostatnich wyszukiwań</translation>
<translation id="2572483411312390101">odtwórz</translation>
<translation id="2613802280814924224">Podaj prawidłową wartość. Najbliższa prawidłowa wartość to <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">stopka</translation>
<translation id="2723001399770238859">dźwięk</translation>
<translation id="2746543609216772311">Musisz podać wartość <ph name="MINIMUM_DATE_OR_TIME" /> lub późniejszą.</translation>
+<translation id="2759744352195237655">przycisk wyskakującego okienka</translation>
<translation id="2761667185364618470">Zaznacz to pole, jeśli chcesz kontynuować.</translation>
<translation id="2846343701378493991">1024 (średni poziom)</translation>
+<translation id="2896972712917208084">grupa przycisków opcji</translation>
<translation id="2901282870647571346">bieżący stan filmu</translation>
<translation id="2908441821576996758">Podaj listę adresów e-mail rozdzielonych przecinkami.</translation>
+<translation id="2931838996092594335">kliknij</translation>
+<translation id="2940813599313844715">obiekt</translation>
<translation id="2942448076852699108">wyróżniona treść</translation>
<translation id="3040011195152428237">link</translation>
<translation id="3075154866155599887">Wpisz prawidłową wartość. Pole jest niekompletne lub zawiera nieprawidłową datę.</translation>
+<translation id="3078740164268491126">tabela</translation>
+<translation id="3086746722712840547">note</translation>
<translation id="310520048233152454">Wprowadź adres URL.</translation>
+<translation id="3175736971608411871">licznik czasu</translation>
+<translation id="3199563858620722075">pole złożone</translation>
<translation id="3450233048674729344">Wartość nie może być większa niż <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">definicja</translation>
+<translation id="3557673793733683882">nagłówek <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">pozostały czas filmu w sekundach</translation>
<translation id="3706100364254443312">przełącznik</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">termin</translation>
<translation id="3822383571486410024">Wydłuż ten tekst przynajmniej do <ph name="MIN_CHARACTERS" /> znaków (teraz używasz <ph name="CURRENT_LENGTH" /> znaków).</translation>
<translation id="383465348367842624">Część przed znakiem „<ph name="ATSIGN" />” nie może zawierać symbolu „<ph name="INVALIDCHARACTER" />”.</translation>
+<translation id="3924558731517983934">aplikacja</translation>
+<translation id="3960700977367013758">pasek przewijania</translation>
<translation id="4103419683916926126">Milisekundy</translation>
+<translation id="4151657705144244502">grafika</translation>
<translation id="4201051445878709314">Pokaż poprzedni miesiąc</translation>
<translation id="4202807286478387388">przejdź</translation>
+<translation id="421884353938374759">selektor kolorów</translation>
+<translation id="4248100235867064564">pasek menu</translation>
+<translation id="4254339807215791271">informacje o zawartości</translation>
<translation id="4360991593054037559">Podaj prawidłową wartość. Dwie najbliższe prawidłowe wartości to <ph name="VALID_VALUE_LOW" /> i <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">przycisk menu</translation>
<translation id="4522570452068850558">Szczegóły</translation>
<translation id="4597532268155981612">formularz</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Część po znaku „<ph name="ATSIGN" />” nie może zawierać symbolu „<ph name="INVALIDCHARACTER" />”.</translation>
+<translation id="4757246831282535685">panel karty</translation>
<translation id="4763480195061959176">film</translation>
+<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Wpisz liczbę.</translation>
<translation id="4975562563186953947">Wybrano: <ph name="SELECTED_COUNT" /></translation>
<translation id="49969490063480558">Podaj część po znaku „<ph name="ATSIGN" />”. Adres „<ph name="INVALIDADDRESS" />” jest niepełny.</translation>
+<translation id="5034860022980953847">wskaźnik postępu</translation>
<translation id="5048533449481078685">znacznik listy</translation>
<translation id="5117590920725113268">Pokaż przyszły miesiąc</translation>
+<translation id="512758898067543763">nagłówek wiersza</translation>
<translation id="5164977714490026579">Wartość nie może być mniejsza niż <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Podaj część przed znakiem „<ph name="ATSIGN" />”. Adres „<ph name="INVALIDADDRESS" />” jest niepełny.</translation>
+<translation id="5317780077021120954">Zapisz</translation>
<translation id="5406322316791861025">figura</translation>
+<translation id="5453733299334684579">element drzewa</translation>
<translation id="5466621249238537318">Wybierz jeden lub kilka plików.</translation>
<translation id="5468998798572797635">zamknij pełny ekran</translation>
<translation id="5476505524087279545">odznacz</translation>
+<translation id="5516424706154626233">selektor daty</translation>
<translation id="5546461542133609677">wyłącz wyciszenie</translation>
+<translation id="561939826962581046">time</translation>
<translation id="5641012560118721995">wstrzymaj odtwarzanie</translation>
+<translation id="5643186887447432888">przycisk</translation>
<translation id="5843503607508392247">Inny...</translation>
<translation id="5939518447894949180">Resetuj</translation>
<translation id="5944544982112848342">2048 (wysoki poziom)</translation>
<translation id="5966707198760109579">Tydzień</translation>
-<translation id="598301471034819706">adres</translation>
+<translation id="5987525920412732405">przycisk przewijany</translation>
<translation id="6015796118275082299">Rok</translation>
+<translation id="6023896073578205740">pole listy</translation>
<translation id="6101327004457443354">wyłącz wyciszenie ścieżki dźwiękowej</translation>
<translation id="6119846243427417423">aktywuj</translation>
+<translation id="6164829606128959761">miernik</translation>
<translation id="6270583010843788609">miniatura osi czasu filmu</translation>
<translation id="6359256949422175976">miniatura paska czasu odtwarzania filmu</translation>
<translation id="6398862346408813489">Pokaż panel wyboru miesiąca</translation>
<translation id="6404546809543547843">pasek czasu odtwarzania dźwięku</translation>
+<translation id="648732519525291180">selektor godziny</translation>
<translation id="658823671542763450">przejdź do pełnego ekranu</translation>
+<translation id="6637586476836377253">dziennik</translation>
<translation id="6643016212128521049">Wyczyść</translation>
<translation id="6663448176199120256">Ostatnie wyszukiwania</translation>
<translation id="668171684555832681">Inny...</translation>
<translation id="6692633176391053278">element kroczący</translation>
+<translation id="6739588121953935928">linijka</translation>
+<translation id="6755330956360078551">etykietka</translation>
<translation id="6820355525329141109">Nie można załadować wtyczki.</translation>
<translation id="6843725295806269523">wyciszenie</translation>
<translation id="6845533974506654842">naciśnij</translation>
<translation id="6853785296079745596">ukryj napisy</translation>
+<translation id="6885760532393684712">katalog</translation>
+<translation id="6934078000481955284">cytat blokowy</translation>
<translation id="7057186640035488495">czas filmu</translation>
<translation id="709897737746224366">Podaj wartość w wymaganym formacie.</translation>
<translation id="7223624360433298498">upłynęło czasu</translation>
<translation id="7263440858009898357">Wybierz element z listy.</translation>
+<translation id="727747134524199931">nagłówek kolumny</translation>
<translation id="7364796246159120393">Wybierz plik</translation>
<translation id="739024184232394898">Inny...</translation>
+<translation id="7491962110804786152">tab</translation>
<translation id="7673697353781729403">Godziny</translation>
<translation id="7720026100085573005">pozostały czas</translation>
<translation id="7740016676195725605">przestań pokazywać napisy</translation>
<translation id="7740050170769002709">Treść HTML</translation>
<translation id="7789962463072032349">wstrzymaj</translation>
+<translation id="7802800022689234070">trójkąt rozwinięcia</translation>
<translation id="7888071071722539607">Uwzględnij znak „<ph name="ATSIGN" />” w adresie e-mail. W adresie „<ph name="INVALIDADDRESS" />” brakuje znaku „<ph name="ATSIGN" />”.</translation>
+<translation id="7891486169920085145">podział</translation>
<translation id="795667975304826397">Nie wybrano pliku</translation>
<translation id="8053789581856978548">pole tekstowe wyszukiwania</translation>
<translation id="8115662671911883373">zacznij pokazywać napisy</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">mapa grafiki</translation>
<translation id="835897206747267392">Nieprawidłowa wartość.</translation>
<translation id="838869780401515933">zaznacz</translation>
+<translation id="8433900881053900389">pasek narzędzi</translation>
<translation id="8444882422881193423">Liczba plików: <ph name="NUMBER_OF_FILES" /></translation>
<translation id="8451268428117625855">Wybierz plik.</translation>
+<translation id="8461852803063341183">przycisk opcji</translation>
+<translation id="8511325616783751178">przycisk listy</translation>
<translation id="8534579021159131403">Minuty</translation>
<translation id="8541249477527128034">sterowanie multimediami</translation>
<translation id="8583702881314752957">lista definicji</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">rozpocznij odtwarzanie</translation>
<translation id="8851136666856101339">główny</translation>
<translation id="8987927404178983737">Miesiąc</translation>
+<translation id="9002566407876343676">otwórz</translation>
<translation id="901493112792887934">bieżący czas w sekundach</translation>
<translation id="9048119486235211610">nawigacja</translation>
<translation id="9050748414552849310">pokaż napisy</translation>
+<translation id="9062295712474918030">dokument</translation>
<translation id="9108370397979208512">matematyczny</translation>
<translation id="9132465097189459683">Inny...</translation>
+<translation id="9138385573473225930">alert</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, początek <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">komórka</translation>
+<translation id="966787709310836684">menu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_pt-BR.xtb b/chromium/content/app/strings/translations/content_strings_pt-BR.xtb
index 18f9742862b..99642d624d3 100644
--- a/chromium/content/app/strings/translations/content_strings_pt-BR.xtb
+++ b/chromium/content/app/strings/translations/content_strings_pt-BR.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="pt-BR">
<translation id="1014825444426747588">em branco</translation>
+<translation id="1018939186200882850">item de menu</translation>
<translation id="1020833440720551630">desativar som da faixa de áudio</translation>
<translation id="10623998915015855">botão "alternar"</translation>
<translation id="1088086359088493902">Segundos</translation>
<translation id="1171774979989969504">Insira um endereço de e-mail.</translation>
<translation id="1188858454923323853">complementar</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">controle deslizante</translation>
<translation id="1235745349614807883">Limpar pesquisas recentes</translation>
+<translation id="1281252709823657822">caixa de diálogo</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">região</translation>
<translation id="1591562245178063882">Este mês</translation>
<translation id="1637811476055996098">Escolher arquivos</translation>
+<translation id="167575180612809735">indicador de atividade</translation>
<translation id="1729654308190250600">Insira um endereço de e-mail que não esteja vazio.</translation>
<translation id="1758486001363313524">Outras...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">grade de árvore</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">reproduzir em dispositivo remoto</translation>
<translation id="1842960171412779397">selecione</translation>
+<translation id="1880518467580572141">contorno</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">status</translation>
<translation id="1938124657309484470">O valor deve ser <ph name="MAXIMUM_DATE_OR_TIME" /> ou anterior.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Reduza este texto para <ph name="MAX_CHARACTERS" /> caracteres ou menos (você está usando <ph name="CURRENT_LENGTH" /> caracteres).</translation>
<translation id="2247351761944213033">Semana <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">caixa de seleção</translation>
+<translation id="2335594187091864976">seletor de data e hora</translation>
<translation id="248395913932153421">Dia</translation>
<translation id="2507943997699731163">Preencha este campo.</translation>
+<translation id="2508569020611168319">lista de guias</translation>
<translation id="2548326553472216322">Nenhuma pesquisa recente</translation>
<translation id="2572483411312390101">reproduzir</translation>
<translation id="2613802280814924224">Insira um valor válido. O valor válido mais próximo é <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">rodapé</translation>
<translation id="2723001399770238859">áudio</translation>
<translation id="2746543609216772311">O valor deve ser <ph name="MINIMUM_DATE_OR_TIME" /> ou posterior.</translation>
+<translation id="2759744352195237655">botão pop-up</translation>
<translation id="2761667185364618470">Marque esta caixa se deseja continuar.</translation>
<translation id="2846343701378493991">1024 (Nível médio)</translation>
+<translation id="2896972712917208084">grupo de rádio</translation>
<translation id="2901282870647571346">status atual do filme</translation>
<translation id="2908441821576996758">Insira uma lista de endereços de e-mail separados por vírgula.</translation>
+<translation id="2931838996092594335">clicar</translation>
+<translation id="2940813599313844715">objeto</translation>
<translation id="2942448076852699108">conteúdo destacado</translation>
<translation id="3040011195152428237">link</translation>
<translation id="3075154866155599887">Insira um valor válido. O campo está incompleto ou tem uma data inválida.</translation>
+<translation id="3078740164268491126">tabela</translation>
+<translation id="3086746722712840547">note</translation>
<translation id="310520048233152454">Insira um URL.</translation>
+<translation id="3175736971608411871">temporizador</translation>
+<translation id="3199563858620722075">caixa de combinação</translation>
<translation id="3450233048674729344">O valor deve ser menor ou igual a <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">definição</translation>
+<translation id="3557673793733683882">cabeçalho <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">segundos restantes do filme</translation>
<translation id="3706100364254443312">alternar</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">termo</translation>
<translation id="3822383571486410024">Aumente este texto para <ph name="MIN_CHARACTERS" /> caracteres ou mais. No momento, você está usando <ph name="CURRENT_LENGTH" /> caracteres).</translation>
<translation id="383465348367842624">Uma parte seguida por "<ph name="ATSIGN" />" não deve conter o símbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3924558731517983934">app</translation>
+<translation id="3960700977367013758">barra de rolagem</translation>
<translation id="4103419683916926126">Milésimos de segundo</translation>
+<translation id="4151657705144244502">gráfico</translation>
<translation id="4201051445878709314">Mostrar mês anterior</translation>
<translation id="4202807286478387388">pular</translation>
+<translation id="421884353938374759">Seletor de cores</translation>
+<translation id="4248100235867064564">barra de menu</translation>
+<translation id="4254339807215791271">informações sobre o conteúdo</translation>
<translation id="4360991593054037559">Insira um valor válido. Os dois valores válidos mais próximos são <ph name="VALID_VALUE_LOW" /> e <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">botão de menu</translation>
<translation id="4522570452068850558">Detalhes</translation>
<translation id="4597532268155981612">formulário</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">A parte depois de "<ph name="ATSIGN" />" não deve conter o símbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4757246831282535685">painel da guia</translation>
<translation id="4763480195061959176">vídeo</translation>
+<translation id="479989351350248267">pesquisar</translation>
<translation id="4812940957355064477">Insira um número.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> selecionados</translation>
<translation id="49969490063480558">Insira uma parte depois de "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" está incompleto.</translation>
+<translation id="5034860022980953847">indicador de progresso</translation>
<translation id="5048533449481078685">marcador de lista</translation>
<translation id="5117590920725113268">Mostrar próximo mês</translation>
+<translation id="512758898067543763">cabeçalho de linha</translation>
<translation id="5164977714490026579">O valor deve ser maior ou igual a <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Insira uma parte seguida por "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" está incompleto.</translation>
+<translation id="5317780077021120954">Salvar</translation>
<translation id="5406322316791861025">figura</translation>
+<translation id="5453733299334684579">item de árvore</translation>
<translation id="5466621249238537318">Selecione um ou mais arquivos.</translation>
<translation id="5468998798572797635">sair do modo tela cheia</translation>
<translation id="5476505524087279545">desmarcar</translation>
+<translation id="5516424706154626233">seletor de data</translation>
<translation id="5546461542133609677">ativar som</translation>
+<translation id="561939826962581046">time</translation>
<translation id="5641012560118721995">pausar reprodução</translation>
+<translation id="5643186887447432888">botão</translation>
<translation id="5843503607508392247">Outras...</translation>
<translation id="5939518447894949180">Redefinir</translation>
<translation id="5944544982112848342">2048 (Nível alto)</translation>
<translation id="5966707198760109579">Semana</translation>
-<translation id="598301471034819706">endereço</translation>
+<translation id="5987525920412732405">botão de rotação</translation>
<translation id="6015796118275082299">Ano</translation>
+<translation id="6023896073578205740">caixa de listagem</translation>
<translation id="6101327004457443354">ativar som da faixa de áudio</translation>
<translation id="6119846243427417423">ativar</translation>
+<translation id="6164829606128959761">medidor</translation>
<translation id="6270583010843788609">miniatura da barra de progressão do filme</translation>
<translation id="6359256949422175976">miniatura da barra de progressão do filme</translation>
<translation id="6398862346408813489">Mostrar painel de seleção de mês</translation>
<translation id="6404546809543547843">barra de progressão do áudio</translation>
+<translation id="648732519525291180">seletor de hora</translation>
<translation id="658823671542763450">entrar no modo tela cheia</translation>
+<translation id="6637586476836377253">log</translation>
<translation id="6643016212128521049">Limpar</translation>
<translation id="6663448176199120256">Pesquisas recentes</translation>
<translation id="668171684555832681">Outro...</translation>
<translation id="6692633176391053278">stepper</translation>
+<translation id="6739588121953935928">régua</translation>
+<translation id="6755330956360078551">dica</translation>
<translation id="6820355525329141109">Não foi possível carregar o plug-in.</translation>
<translation id="6843725295806269523">sem som</translation>
<translation id="6845533974506654842">pressione</translation>
<translation id="6853785296079745596">ocultar legendas ocultas</translation>
+<translation id="6885760532393684712">diretório</translation>
+<translation id="6934078000481955284">bloco de texto</translation>
<translation id="7057186640035488495">tempo de filme</translation>
<translation id="709897737746224366">É preciso que o formato corresponda ao exigido.</translation>
<translation id="7223624360433298498">tempo decorrido</translation>
<translation id="7263440858009898357">Selecione um item da lista.</translation>
+<translation id="727747134524199931">cabeçalho da coluna</translation>
<translation id="7364796246159120393">Escolher arquivo</translation>
<translation id="739024184232394898">Outras...</translation>
+<translation id="7491962110804786152">tab</translation>
<translation id="7673697353781729403">Horas</translation>
<translation id="7720026100085573005">tempo restante</translation>
<translation id="7740016676195725605">parar de exibir legendas ocultas</translation>
<translation id="7740050170769002709">Conteúdo HTML</translation>
<translation id="7789962463072032349">pausar</translation>
+<translation id="7802800022689234070">triângulo de divulgação</translation>
<translation id="7888071071722539607">Inclua um "<ph name="ATSIGN" />" no endereço de e-mail. "<ph name="INVALIDADDRESS" />" está com um "<ph name="ATSIGN" />" faltando.</translation>
+<translation id="7891486169920085145">divisor</translation>
<translation id="795667975304826397">Nenhum arquivo selecionado</translation>
<translation id="8053789581856978548">campo de texto da pesquisa</translation>
<translation id="8115662671911883373">começar a exibir legendas ocultas</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">mapa de imagens</translation>
<translation id="835897206747267392">Valor inválido.</translation>
<translation id="838869780401515933">marcar</translation>
+<translation id="8433900881053900389">barra de ferramentas</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> arquivos</translation>
<translation id="8451268428117625855">Selecione um arquivo.</translation>
+<translation id="8461852803063341183">botão de opção</translation>
+<translation id="8511325616783751178">botão suspenso</translation>
<translation id="8534579021159131403">Minutos</translation>
<translation id="8541249477527128034">controle de mídia</translation>
<translation id="8583702881314752957">lista de definições</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">iniciar reprodução</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8987927404178983737">Mês</translation>
+<translation id="9002566407876343676">abrir</translation>
<translation id="901493112792887934">tempo atual em segundos</translation>
<translation id="9048119486235211610">navegação</translation>
<translation id="9050748414552849310">mostrar legendas ocultas</translation>
+<translation id="9062295712474918030">documento</translation>
<translation id="9108370397979208512">matemática</translation>
<translation id="9132465097189459683">Outras...</translation>
+<translation id="9138385573473225930">alerta</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, que começa em <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">célula</translation>
+<translation id="966787709310836684">menu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_pt-PT.xtb b/chromium/content/app/strings/translations/content_strings_pt-PT.xtb
index a0e5e1fb734..2398bd250e7 100644
--- a/chromium/content/app/strings/translations/content_strings_pt-PT.xtb
+++ b/chromium/content/app/strings/translations/content_strings_pt-PT.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="pt-PT">
<translation id="1014825444426747588">em branco</translation>
+<translation id="1018939186200882850">item de menu</translation>
<translation id="1020833440720551630">desativar a faixa de áudio</translation>
<translation id="10623998915015855">botão alternar</translation>
<translation id="1088086359088493902">Segundos</translation>
<translation id="1171774979989969504">Introduza um endereço de email.</translation>
<translation id="1188858454923323853">complementar</translation>
+<translation id="1206619573307042055">painel rolante</translation>
+<translation id="1206693055195146388">controlo de deslize</translation>
<translation id="1235745349614807883">Limpar pesquisas recentes</translation>
+<translation id="1281252709823657822">caixa de diálogo</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">região</translation>
<translation id="1591562245178063882">Este mês</translation>
<translation id="1637811476055996098">Escolher Ficheiros</translation>
+<translation id="167575180612809735">indicador de ocupado</translation>
<translation id="1729654308190250600">Introduza um endereço de email que não esteja vazio.</translation>
<translation id="1758486001363313524">Outra...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">grelha de árvore</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">reproduzir no dispositivo remoto</translation>
<translation id="1842960171412779397">seleccionar</translation>
+<translation id="1880518467580572141">contorno</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">estado</translation>
<translation id="1938124657309484470">O valor tem de ser <ph name="MAXIMUM_DATE_OR_TIME" /> ou anterior.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Encurte este texto para <ph name="MAX_CHARACTERS" /> caracteres ou menos (está atualmente a utilizar <ph name="CURRENT_LENGTH" /> caracteres).</translation>
<translation id="2247351761944213033">Semana <ph name="WEEKNUMBER" />, de <ph name="YEAR" /></translation>
<translation id="2291999235780842123">caixa de verificação</translation>
+<translation id="2335594187091864976">selecionador de data e hora</translation>
<translation id="248395913932153421">Dia</translation>
<translation id="2507943997699731163">Preencha este campo.</translation>
+<translation id="2508569020611168319">lista de separadores</translation>
<translation id="2548326553472216322">Nenhuma pesquisa recente</translation>
<translation id="2572483411312390101">reproduzir</translation>
<translation id="2613802280814924224">Introduza um valor válido. O valor válido mais próximo é <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">rodapé</translation>
<translation id="2723001399770238859">áudio</translation>
<translation id="2746543609216772311">O valor tem de ser <ph name="MINIMUM_DATE_OR_TIME" /> ou posterior.</translation>
+<translation id="2759744352195237655">botão pop-up</translation>
<translation id="2761667185364618470">Seleccione esta caixa se pretender continuar.</translation>
<translation id="2846343701378493991">1024 (Tamanho médio)</translation>
+<translation id="2896972712917208084">grupo de botões de opção</translation>
<translation id="2901282870647571346">estado atual do filme</translation>
<translation id="2908441821576996758">Introduza uma lista de endereços de email separados por vírgula.</translation>
+<translation id="2931838996092594335">clicar</translation>
+<translation id="2940813599313844715">objeto</translation>
<translation id="2942448076852699108">conteúdo realçado</translation>
<translation id="3040011195152428237">link</translation>
<translation id="3075154866155599887">Introduza um valor válido. O campo está incompleto ou tem uma data inválida.</translation>
+<translation id="3078740164268491126">tabela</translation>
+<translation id="3086746722712840547">note</translation>
<translation id="310520048233152454">Introduza um URL.</translation>
+<translation id="3175736971608411871">temporizador</translation>
+<translation id="3199563858620722075">caixa de combinação</translation>
<translation id="3450233048674729344">O valor tem de ser inferior ou igual a <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">definição</translation>
+<translation id="3557673793733683882">título <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">segundos que restam ao filme</translation>
<translation id="3706100364254443312">alternar</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">termo</translation>
<translation id="3822383571486410024">Aumente este texto para <ph name="MIN_CHARACTERS" /> carateres ou mais (está atualmente a utilizar <ph name="CURRENT_LENGTH" /> carateres).</translation>
<translation id="383465348367842624">Uma parte seguida de "<ph name="ATSIGN" />" não deve conter o símbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3924558731517983934">aplicação</translation>
+<translation id="3960700977367013758">barra de deslocamento</translation>
<translation id="4103419683916926126">Milissegundos</translation>
+<translation id="4151657705144244502">gráfico</translation>
<translation id="4201051445878709314">Mostrar mês anterior</translation>
<translation id="4202807286478387388">ir para</translation>
+<translation id="421884353938374759">seletor de cores</translation>
+<translation id="4248100235867064564">barra de menu</translation>
+<translation id="4254339807215791271">informações do conteúdo</translation>
<translation id="4360991593054037559">Introduza um valor válido. Os dois valores válidos mais próximos são <ph name="VALID_VALUE_LOW" /> e <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">botão de menu</translation>
<translation id="4522570452068850558">Detalhes</translation>
<translation id="4597532268155981612">formulário</translation>
+<translation id="4661075872484491155">árvore</translation>
<translation id="4664250907885839816">Uma parte a seguir a "<ph name="ATSIGN" />" não deve conter o símbolo "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4757246831282535685">painel de separadores</translation>
<translation id="4763480195061959176">vídeo</translation>
+<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Introduza um número.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> selecionados</translation>
<translation id="49969490063480558">Introduza uma parte a seguir a "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" está incompleto.</translation>
+<translation id="5034860022980953847">indicador de progresso</translation>
<translation id="5048533449481078685">marcador de lista</translation>
<translation id="5117590920725113268">Mostrar mês seguinte</translation>
+<translation id="512758898067543763">cabeçalho da linha</translation>
<translation id="5164977714490026579">O valor tem de ser superior ou igual a <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Introduza uma parte seguida de "<ph name="ATSIGN" />". "<ph name="INVALIDADDRESS" />" está incompleto.</translation>
+<translation id="5317780077021120954">Guardar</translation>
<translation id="5406322316791861025">figura</translation>
+<translation id="5453733299334684579">item de árvore</translation>
<translation id="5466621249238537318">Seleccione um ou mais ficheiros.</translation>
<translation id="5468998798572797635">sair do modo de ecrã inteiro</translation>
<translation id="5476505524087279545">desmarcar</translation>
+<translation id="5516424706154626233">selecionador de data</translation>
<translation id="5546461542133609677">reativar som</translation>
+<translation id="561939826962581046">hora</translation>
<translation id="5641012560118721995">interromper a reprodução</translation>
+<translation id="5643186887447432888">botão</translation>
<translation id="5843503607508392247">Outra...</translation>
<translation id="5939518447894949180">Repor</translation>
<translation id="5944544982112848342">2048 (Tamanho grande)</translation>
<translation id="5966707198760109579">Semana</translation>
-<translation id="598301471034819706">endereço</translation>
+<translation id="5987525920412732405">botão giratório</translation>
<translation id="6015796118275082299">Ano</translation>
+<translation id="6023896073578205740">caixa de lista</translation>
<translation id="6101327004457443354">reativar a faixa de áudio</translation>
<translation id="6119846243427417423">activar</translation>
+<translation id="6164829606128959761">contador</translation>
<translation id="6270583010843788609">botão da cronologia do filme</translation>
<translation id="6359256949422175976">botão do scrubber do tempo do filme</translation>
<translation id="6398862346408813489">Mostrar painel de seleção do mês</translation>
<translation id="6404546809543547843">controlo de arrasto do tempo do áudio</translation>
+<translation id="648732519525291180">selecionador de hora</translation>
<translation id="658823671542763450">entrar no modo de ecrã inteiro</translation>
+<translation id="6637586476836377253">log</translation>
<translation id="6643016212128521049">Limpar</translation>
<translation id="6663448176199120256">Pesquisas recentes</translation>
<translation id="668171684555832681">Outros...</translation>
<translation id="6692633176391053278">stepper</translation>
+<translation id="6739588121953935928">régua</translation>
+<translation id="6755330956360078551">sugestão</translation>
<translation id="6820355525329141109">Não foi possível carregar o plug-in.</translation>
<translation id="6843725295806269523">desativar som</translation>
<translation id="6845533974506654842">premir</translation>
<translation id="6853785296079745596">esconder legendas ocultas</translation>
+<translation id="6885760532393684712">diretório</translation>
+<translation id="6934078000481955284">blockquote</translation>
<translation id="7057186640035488495">tempo do filme</translation>
<translation id="709897737746224366">Faça corresponder o formato pedido.</translation>
<translation id="7223624360433298498">tempo decorrido</translation>
<translation id="7263440858009898357">Seleccione um item na lista.</translation>
+<translation id="727747134524199931">cabeçalho da coluna</translation>
<translation id="7364796246159120393">Escolher ficheiro</translation>
<translation id="739024184232394898">Outra...</translation>
+<translation id="7491962110804786152">tab</translation>
<translation id="7673697353781729403">Horas</translation>
<translation id="7720026100085573005">tempo restante</translation>
<translation id="7740016676195725605">parar de apresentar legendas ocultas</translation>
<translation id="7740050170769002709">Conteúdo HTML</translation>
<translation id="7789962463072032349">pausa</translation>
+<translation id="7802800022689234070">triângulo de divulgação</translation>
<translation id="7888071071722539607">Inclua um "<ph name="ATSIGN" />" no endereço de email. Falta um "<ph name="ATSIGN" />" em "<ph name="INVALIDADDRESS" />".</translation>
+<translation id="7891486169920085145">divisor</translation>
<translation id="795667975304826397">Nenhum ficheiro selecionado</translation>
<translation id="8053789581856978548">campo de texto de pesquisa</translation>
<translation id="8115662671911883373">apresentar legendas ocultas</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">mapa de imagem</translation>
<translation id="835897206747267392">Valor inválido.</translation>
<translation id="838869780401515933">verificar</translation>
+<translation id="8433900881053900389">barra de ferramentas</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ficheiros</translation>
<translation id="8451268428117625855">Seleccione um ficheiro.</translation>
+<translation id="8461852803063341183">botão de opção</translation>
+<translation id="8511325616783751178">botão pendente</translation>
<translation id="8534579021159131403">Minutos</translation>
<translation id="8541249477527128034">controlo multimédia</translation>
<translation id="8583702881314752957">lista de definições</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">iniciar reprodução</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8987927404178983737">Mês</translation>
+<translation id="9002566407876343676">abrir</translation>
<translation id="901493112792887934">tempo atual em segundos</translation>
<translation id="9048119486235211610">navegação</translation>
<translation id="9050748414552849310">apresentar legendas ocultas</translation>
+<translation id="9062295712474918030">documento</translation>
<translation id="9108370397979208512">math</translation>
<translation id="9132465097189459683">Outra...</translation>
+<translation id="9138385573473225930">alerta</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, a partir de <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">célula</translation>
+<translation id="966787709310836684">menu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ro.xtb b/chromium/content/app/strings/translations/content_strings_ro.xtb
index 8c60cf84b02..af8dbed9a30 100644
--- a/chromium/content/app/strings/translations/content_strings_ro.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ro.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="ro">
<translation id="1014825444426747588">necompletat</translation>
+<translation id="1018939186200882850">element de meniu</translation>
<translation id="1020833440720551630">dezactivați sunetul înregistrării audio</translation>
<translation id="10623998915015855">buton de comutare</translation>
<translation id="1088086359088493902">Secunde</translation>
<translation id="1171774979989969504">Introdu o adresă de e-mail.</translation>
<translation id="1188858454923323853">complementar</translation>
+<translation id="1206619573307042055">text derulant</translation>
+<translation id="1206693055195146388">glisor</translation>
<translation id="1235745349614807883">Șterge căutările recente</translation>
+<translation id="1281252709823657822">dialog</translation>
<translation id="1342835525016946179">articol</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">regiune</translation>
<translation id="1591562245178063882">Luna aceasta</translation>
<translation id="1637811476055996098">Alege fișierele</translation>
+<translation id="167575180612809735">indicator de procesare</translation>
<translation id="1729654308190250600">Introduceți o adresă de e-mail concretă.</translation>
<translation id="1758486001363313524">Altele...</translation>
+<translation id="1806710327868736751">dialog de alertă</translation>
+<translation id="1821985195704844674">grilă arbore</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">redă pe dispozitiv la distanță</translation>
<translation id="1842960171412779397">selectează</translation>
+<translation id="1880518467580572141">schemă</translation>
<translation id="1921819250265091946">zz</translation>
<translation id="1930711995431081526">stare</translation>
<translation id="1938124657309484470">Valoarea pentru dată/oră trebuie să fie <ph name="MAXIMUM_DATE_OR_TIME" /> sau una anterioară.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Micșorează acest text la cel mult <ph name="MAX_CHARACTERS" /> (de) caractere (în prezent utilizezi <ph name="CURRENT_LENGTH" /> (de) caractere).</translation>
<translation id="2247351761944213033">Săptămâna <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">casetă de selectare</translation>
+<translation id="2335594187091864976">selector pentru dată și oră</translation>
<translation id="248395913932153421">Zi</translation>
<translation id="2507943997699731163">Completează acest câmp.</translation>
+<translation id="2508569020611168319">listă de file</translation>
<translation id="2548326553472216322">Nicio căutare recentă</translation>
<translation id="2572483411312390101">redați</translation>
<translation id="2613802280814924224">Introduceți o valoare validă. Cea mai apropiată valoare validă este <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">notă de subsol</translation>
<translation id="2723001399770238859">audio</translation>
<translation id="2746543609216772311">Valoarea pentru dată/oră trebuie să fie <ph name="MINIMUM_DATE_OR_TIME" /> sau una ulterioară.</translation>
+<translation id="2759744352195237655">buton pop-up</translation>
<translation id="2761667185364618470">Bifeză caseta dacă vrei să continui.</translation>
<translation id="2846343701378493991">1024 (nivel mediu)</translation>
+<translation id="2896972712917208084">grup butoane radio</translation>
<translation id="2901282870647571346">starea actuală a filmului</translation>
<translation id="2908441821576996758">Introdu o listă de adrese de e-mail separate prin virgulă.</translation>
+<translation id="2931838996092594335">dă clic</translation>
+<translation id="2940813599313844715">obiect</translation>
<translation id="2942448076852699108">conținut evidențiat</translation>
<translation id="3040011195152428237">link</translation>
<translation id="3075154866155599887">Introduceți o valoare validă. Câmpul este incomplet sau conține o dată nevalidă.</translation>
+<translation id="3078740164268491126">tabel</translation>
+<translation id="3086746722712840547">notă</translation>
<translation id="310520048233152454">Introdu o adresă URL.</translation>
+<translation id="3175736971608411871">temporizator</translation>
+<translation id="3199563858620722075">casetă combo</translation>
<translation id="3450233048674729344">Valoarea trebuie să fie mai mică sau egală cu <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">definiție</translation>
+<translation id="3557673793733683882">titlu <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">numărul secundelor rămase din film</translation>
<translation id="3706100364254443312">comutator</translation>
<translation id="3732799496749320381">ll</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">termen</translation>
<translation id="3822383571486410024">Mărește acest text la cel puțin <ph name="MIN_CHARACTERS" /> (de) caractere (în prezent folosești <ph name="CURRENT_LENGTH" /> (de) caractere).</translation>
<translation id="383465348367842624">Valoarea urmată de semnul „<ph name="ATSIGN" />” nu trebuie să conțină simbolul „<ph name="INVALIDCHARACTER" />”.</translation>
+<translation id="3924558731517983934">aplicație</translation>
+<translation id="3960700977367013758">bară de derulare</translation>
<translation id="4103419683916926126">Milisecunde</translation>
+<translation id="4151657705144244502">element grafic</translation>
<translation id="4201051445878709314">Afișează luna anterioară</translation>
<translation id="4202807286478387388">accesează</translation>
+<translation id="421884353938374759">selector de culoare</translation>
+<translation id="4248100235867064564">bară de meniu</translation>
+<translation id="4254339807215791271">informații privind conținutul</translation>
<translation id="4360991593054037559">Introduceți o valoare validă. Cele mai apropiate valori valide sunt <ph name="VALID_VALUE_LOW" /> și <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">buton de meniu</translation>
<translation id="4522570452068850558">Detalii</translation>
<translation id="4597532268155981612">formular</translation>
+<translation id="4661075872484491155">arbore</translation>
<translation id="4664250907885839816">Valoarea care urmează după semnul „<ph name="ATSIGN" />” nu trebuie să conțină simbolul „<ph name="INVALIDCHARACTER" />”.</translation>
+<translation id="4757246831282535685">panou de file</translation>
<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">căutați</translation>
<translation id="4812940957355064477">Introduceți un număr.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> selectate</translation>
<translation id="49969490063480558">Introduceți o valoare după semnul „<ph name="ATSIGN" />”. Adresa „<ph name="INVALIDADDRESS" />” nu este completă.</translation>
+<translation id="5034860022980953847">indicator de progres</translation>
<translation id="5048533449481078685">marcator de listă</translation>
<translation id="5117590920725113268">Afișează luna următoare</translation>
+<translation id="512758898067543763">antet rând</translation>
<translation id="5164977714490026579">Valoarea trebuie să fie mai mare sau egală cu <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Introduceți o valoare urmată de semnul „<ph name="ATSIGN" />”. Adresa „<ph name="INVALIDADDRESS" />” nu este completă.</translation>
+<translation id="5317780077021120954">Salvează</translation>
<translation id="5406322316791861025">cifră</translation>
+<translation id="5453733299334684579">element arbore</translation>
<translation id="5466621249238537318">Selectează unul sau mai multe fișiere.</translation>
<translation id="5468998798572797635">ieșiți din ecranul complet</translation>
<translation id="5476505524087279545">debifează</translation>
+<translation id="5516424706154626233">selector dată</translation>
<translation id="5546461542133609677">activați sunetul</translation>
+<translation id="561939826962581046">oră</translation>
<translation id="5641012560118721995">întrerupeți redarea</translation>
+<translation id="5643186887447432888">buton</translation>
<translation id="5843503607508392247">Altele...</translation>
<translation id="5939518447894949180">Resetează</translation>
<translation id="5944544982112848342">2048 (nivel ridicat)</translation>
<translation id="5966707198760109579">Săptămână</translation>
-<translation id="598301471034819706">adresă</translation>
+<translation id="5987525920412732405">buton incrementare/decrementare</translation>
<translation id="6015796118275082299">An</translation>
+<translation id="6023896073578205740">casetă listă</translation>
<translation id="6101327004457443354">activați sunetul înregistrării audio</translation>
<translation id="6119846243427417423">activează</translation>
+<translation id="6164829606128959761">instrument de măsurare</translation>
<translation id="6270583010843788609">miniatură cronologie film</translation>
<translation id="6359256949422175976">miniatură glisor redare film</translation>
<translation id="6398862346408813489">Afișează panoul de selectare a lunii</translation>
<translation id="6404546809543547843">glisor redare audio</translation>
+<translation id="648732519525291180">selector oră</translation>
<translation id="658823671542763450">deschideți în ecran complet</translation>
+<translation id="6637586476836377253">jurnal</translation>
<translation id="6643016212128521049">Ștergeți</translation>
<translation id="6663448176199120256">Căutări recente</translation>
<translation id="668171684555832681">Altele...</translation>
<translation id="6692633176391053278">control numeric cu incrementare/decrementare</translation>
+<translation id="6739588121953935928">riglă</translation>
+<translation id="6755330956360078551">balon explicativ</translation>
<translation id="6820355525329141109">Nu s-a putut încărca pluginul.</translation>
<translation id="6843725295806269523">dezactivați sunetul</translation>
<translation id="6845533974506654842">apasă</translation>
<translation id="6853785296079745596">ascundeți subtitrările</translation>
+<translation id="6885760532393684712">director</translation>
+<translation id="6934078000481955284">blockquote</translation>
<translation id="7057186640035488495">durată film</translation>
<translation id="709897737746224366">Respectă formatul solicitat.</translation>
<translation id="7223624360433298498">timp scurs</translation>
<translation id="7263440858009898357">Selectează un articol din listă.</translation>
+<translation id="727747134524199931">antet coloană</translation>
<translation id="7364796246159120393">Alege fișierul</translation>
<translation id="739024184232394898">Altele...</translation>
+<translation id="7491962110804786152">filă</translation>
<translation id="7673697353781729403">Ore</translation>
<translation id="7720026100085573005">timp rămas</translation>
<translation id="7740016676195725605">nu mai afișați subtitrările</translation>
<translation id="7740050170769002709">Conținut HTML</translation>
<translation id="7789962463072032349">întrerupe</translation>
+<translation id="7802800022689234070">triunghi pentru afișare</translation>
<translation id="7888071071722539607">Includeți semnul „<ph name="ATSIGN" />” în adresa de e-mail. Din adresa „<ph name="INVALIDADDRESS" />” lipsește semnul „<ph name="ATSIGN" />”.</translation>
+<translation id="7891486169920085145">element de divizare</translation>
<translation id="795667975304826397">Nu ai ales niciun fișier</translation>
<translation id="8053789581856978548">câmp pentru căutarea textului</translation>
<translation id="8115662671911883373">începeți să afișați subtitrările</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">hartă imagine</translation>
<translation id="835897206747267392">Valoare nevalidă.</translation>
<translation id="838869780401515933">bifează</translation>
+<translation id="8433900881053900389">bară de instrumente</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> (de) fișiere</translation>
<translation id="8451268428117625855">Selectează un fișier.</translation>
+<translation id="8461852803063341183">buton radio</translation>
+<translation id="8511325616783751178">buton drop-down</translation>
<translation id="8534579021159131403">Minute</translation>
<translation id="8541249477527128034">comandă media</translation>
<translation id="8583702881314752957">listă de definiții</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">începeți redarea</translation>
<translation id="8851136666856101339">principal</translation>
<translation id="8987927404178983737">Lună</translation>
+<translation id="9002566407876343676">deschide</translation>
<translation id="901493112792887934">timp actual în secunde</translation>
<translation id="9048119486235211610">navigare</translation>
<translation id="9050748414552849310">afișați subtitrările</translation>
+<translation id="9062295712474918030">document</translation>
<translation id="9108370397979208512">matematică</translation>
<translation id="9132465097189459683">Altele...</translation>
+<translation id="9138385573473225930">alertă</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, începând de pe <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">celulă</translation>
+<translation id="966787709310836684">meniu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ru.xtb b/chromium/content/app/strings/translations/content_strings_ru.xtb
index fd0d08c5ac7..6e81a7ae063 100644
--- a/chromium/content/app/strings/translations/content_strings_ru.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ru.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="ru">
<translation id="1014825444426747588">нет данных</translation>
+<translation id="1018939186200882850">элемент меню</translation>
<translation id="1020833440720551630">отключение звуковой дорожки</translation>
<translation id="10623998915015855">кнопка-переключатель</translation>
<translation id="1088086359088493902">Секунды</translation>
<translation id="1171774979989969504">Введите адрес электронной почты.</translation>
<translation id="1188858454923323853">дополнительно</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">ползунок</translation>
<translation id="1235745349614807883">Очистить недавние поиски</translation>
+<translation id="1281252709823657822">диалоговое окно</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">баннер</translation>
<translation id="1589122976691792535">регион</translation>
<translation id="1591562245178063882">В этом месяце</translation>
<translation id="1637811476055996098">Выбрать файлы</translation>
+<translation id="167575180612809735">индикатор статуса занято</translation>
<translation id="1729654308190250600">Введите адрес электронной почты.</translation>
<translation id="1758486001363313524">Другое…</translation>
+<translation id="1806710327868736751">диалоговое окно оповещения</translation>
+<translation id="1821985195704844674">сетка в виде дерева</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">воспроизвести на удаленном устройстве</translation>
<translation id="1842960171412779397">выбрать</translation>
+<translation id="1880518467580572141">внешние границы</translation>
<translation id="1921819250265091946">дд</translation>
<translation id="1930711995431081526">статус</translation>
<translation id="1938124657309484470">Максимальное значение должно быть <ph name="MAXIMUM_DATE_OR_TIME" />.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Длина текста не должна превышать <ph name="MAX_CHARACTERS" /> симв. (сейчас <ph name="CURRENT_LENGTH" /> симв.).</translation>
<translation id="2247351761944213033">Неделя <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">флажок</translation>
+<translation id="2335594187091864976">окно выбора даты и времени</translation>
<translation id="248395913932153421">День</translation>
<translation id="2507943997699731163">Заполните это поле.</translation>
+<translation id="2508569020611168319">список вкладок</translation>
<translation id="2548326553472216322">Нет недавних поисков</translation>
<translation id="2572483411312390101">воспроизведение</translation>
<translation id="2613802280814924224">Введите допустимое значение. Ближайшее допустимое значение: <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">нижний колонтитул</translation>
<translation id="2723001399770238859">аудио</translation>
<translation id="2746543609216772311">Минимальное значение должно быть <ph name="MINIMUM_DATE_OR_TIME" />.</translation>
+<translation id="2759744352195237655">всплывающая кнопка</translation>
<translation id="2761667185364618470">Чтобы продолжить, установите этот флажок.</translation>
<translation id="2846343701378493991">1024 (Средний размер)</translation>
+<translation id="2896972712917208084">группа переключателей</translation>
<translation id="2901282870647571346">текущий статус ролика</translation>
<translation id="2908441821576996758">Введите адреса электронной почты через запятую.</translation>
+<translation id="2931838996092594335">нажать</translation>
+<translation id="2940813599313844715">объект</translation>
<translation id="2942448076852699108">выделенный контент</translation>
<translation id="3040011195152428237">ссылка</translation>
<translation id="3075154866155599887">Введите верное значение. Поле не заполнено или введена недействительная дата.</translation>
+<translation id="3078740164268491126">таблица</translation>
+<translation id="3086746722712840547">note</translation>
<translation id="310520048233152454">Введите URL.</translation>
+<translation id="3175736971608411871">таймер</translation>
+<translation id="3199563858620722075">поле со списком</translation>
<translation id="3450233048674729344">Значение должно быть меньше или равно <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">описание</translation>
+<translation id="3557673793733683882">заголовок <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">оставшееся время в секундах</translation>
<translation id="3706100364254443312">переключить</translation>
<translation id="3732799496749320381">мм</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">запрос</translation>
<translation id="3822383571486410024">Минимально допустимое количество символов: <ph name="MIN_CHARACTERS" />. Длина текста сейчас: <ph name="CURRENT_LENGTH" />.</translation>
<translation id="383465348367842624">Часть адреса до символа "<ph name="ATSIGN" />" не должна содержать символ "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3924558731517983934">приложение</translation>
+<translation id="3960700977367013758">полоса прокрутки</translation>
<translation id="4103419683916926126">Миллисекунды</translation>
+<translation id="4151657705144244502">изображение</translation>
<translation id="4201051445878709314">Показать предыдущий месяц</translation>
<translation id="4202807286478387388">перейти</translation>
+<translation id="421884353938374759">color picker</translation>
+<translation id="4248100235867064564">панель меню</translation>
+<translation id="4254339807215791271">сведения о контенте</translation>
<translation id="4360991593054037559">Введите допустимое значение. Ближайшие допустимые значения: <ph name="VALID_VALUE_LOW" /> и <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">кнопка меню</translation>
<translation id="4522570452068850558">Подробнее</translation>
<translation id="4597532268155981612">форма</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Часть адреса после символа "<ph name="ATSIGN" />" не должна содержать символ "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4757246831282535685">панель вкладок</translation>
<translation id="4763480195061959176">видео</translation>
+<translation id="479989351350248267">поиск</translation>
<translation id="4812940957355064477">Введите число.</translation>
<translation id="4975562563186953947">Выбрано: <ph name="SELECTED_COUNT" /></translation>
<translation id="49969490063480558">Введите часть адреса после символа "<ph name="ATSIGN" />". Адрес "<ph name="INVALIDADDRESS" />" неполный.</translation>
+<translation id="5034860022980953847">индикатор хода выполнения</translation>
<translation id="5048533449481078685">маркер списка</translation>
<translation id="5117590920725113268">Показать следующий месяц</translation>
+<translation id="512758898067543763">заголовок строки</translation>
<translation id="5164977714490026579">Значение должно быть больше или равно <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Введите часть адреса до символа "<ph name="ATSIGN" />". Адрес "<ph name="INVALIDADDRESS" />" неполный.</translation>
+<translation id="5317780077021120954">Сохранить</translation>
<translation id="5406322316791861025">фигура</translation>
+<translation id="5453733299334684579">элемент дерева</translation>
<translation id="5466621249238537318">Выберите один или несколько файлов.</translation>
<translation id="5468998798572797635">выход из полноэкранного режима</translation>
<translation id="5476505524087279545">снять галочку</translation>
+<translation id="5516424706154626233">окно выбора даты</translation>
<translation id="5546461542133609677">включение звука</translation>
+<translation id="561939826962581046">time</translation>
<translation id="5641012560118721995">пауза</translation>
+<translation id="5643186887447432888">кнопка</translation>
<translation id="5843503607508392247">Другое…</translation>
<translation id="5939518447894949180">Сбросить</translation>
<translation id="5944544982112848342">2048 (Крупный размер)</translation>
<translation id="5966707198760109579">Неделя</translation>
-<translation id="598301471034819706">адрес</translation>
+<translation id="5987525920412732405">кнопка счетчика</translation>
<translation id="6015796118275082299">Год</translation>
+<translation id="6023896073578205740">список</translation>
<translation id="6101327004457443354">включение звуковой дорожки</translation>
<translation id="6119846243427417423">активировать</translation>
+<translation id="6164829606128959761">счетчик</translation>
<translation id="6270583010843788609">бегунок временной шкалы</translation>
<translation id="6359256949422175976">бегунок полосы прокрутки</translation>
<translation id="6398862346408813489">Показать панель выбора месяца</translation>
<translation id="6404546809543547843">полоса воспроизведения</translation>
+<translation id="648732519525291180">окно выбора даты</translation>
<translation id="658823671542763450">полноэкранный режим</translation>
+<translation id="6637586476836377253">log</translation>
<translation id="6643016212128521049">Очистить</translation>
<translation id="6663448176199120256">Недавние поиски</translation>
<translation id="668171684555832681">Другой...</translation>
<translation id="6692633176391053278">счетчик</translation>
+<translation id="6739588121953935928">линейка</translation>
+<translation id="6755330956360078551">подсказка</translation>
<translation id="6820355525329141109">Не удалось загрузить плагин</translation>
<translation id="6843725295806269523">отключить звук</translation>
<translation id="6845533974506654842">нажать</translation>
<translation id="6853785296079745596">скрыть субтитры</translation>
+<translation id="6885760532393684712">каталог</translation>
+<translation id="6934078000481955284">цитата</translation>
<translation id="7057186640035488495">продолжительность ролика</translation>
<translation id="709897737746224366">Введите данные в указанном формате.</translation>
<translation id="7223624360433298498">прошедшее время</translation>
<translation id="7263440858009898357">Выберите один из пунктов списка.</translation>
+<translation id="727747134524199931">заголовок столбца</translation>
<translation id="7364796246159120393">Выберите файл</translation>
<translation id="739024184232394898">Другое…</translation>
+<translation id="7491962110804786152">tab</translation>
<translation id="7673697353781729403">Часы</translation>
<translation id="7720026100085573005">оставшееся время</translation>
<translation id="7740016676195725605">скрыть субтитры</translation>
<translation id="7740050170769002709">HTML-содержание</translation>
<translation id="7789962463072032349">Пауза</translation>
+<translation id="7802800022689234070">треугольник развертывания</translation>
<translation id="7888071071722539607">Адрес электронной почты должен содержать символ "<ph name="ATSIGN" />". В адресе "<ph name="INVALIDADDRESS" />" отсутствует символ "<ph name="ATSIGN" />".</translation>
+<translation id="7891486169920085145">разделитель</translation>
<translation id="795667975304826397">Файл не выбран</translation>
<translation id="8053789581856978548">поле поиска</translation>
<translation id="8115662671911883373">показать субтитры</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">графическая карта</translation>
<translation id="835897206747267392">Недопустимые данные.</translation>
<translation id="838869780401515933">поставить галочку</translation>
+<translation id="8433900881053900389">панель инструментов</translation>
<translation id="8444882422881193423">Число файлов: <ph name="NUMBER_OF_FILES" /></translation>
<translation id="8451268428117625855">Выберите файл.</translation>
+<translation id="8461852803063341183">переключатель</translation>
+<translation id="8511325616783751178">кнопка раскрывающегося меню</translation>
<translation id="8534579021159131403">Минуты</translation>
<translation id="8541249477527128034">управление мультимедиа</translation>
<translation id="8583702881314752957">список описаний</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">начать воспроизведение</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8987927404178983737">Месяц</translation>
+<translation id="9002566407876343676">открыть</translation>
<translation id="901493112792887934">текущее время в секундах</translation>
<translation id="9048119486235211610">навигация</translation>
<translation id="9050748414552849310">показать субтитры</translation>
+<translation id="9062295712474918030">документ</translation>
<translation id="9108370397979208512">math</translation>
<translation id="9132465097189459683">Другое…</translation>
+<translation id="9138385573473225930">оповещение</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, начинается <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">ячейка</translation>
+<translation id="966787709310836684">меню</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_sk.xtb b/chromium/content/app/strings/translations/content_strings_sk.xtb
index a647f5ade49..ca0376aaf70 100644
--- a/chromium/content/app/strings/translations/content_strings_sk.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sk.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="sk">
<translation id="1014825444426747588">prázdne</translation>
+<translation id="1018939186200882850">položka ponuky</translation>
<translation id="1020833440720551630">stlmiť zvukovú stopu</translation>
<translation id="10623998915015855">tlačidlo prepínania</translation>
<translation id="1088086359088493902">Sekundy</translation>
<translation id="1171774979989969504">Zadajte e-mailovú adresu.</translation>
<translation id="1188858454923323853">doplnkové</translation>
+<translation id="1206619573307042055">pohyblivý prvok</translation>
+<translation id="1206693055195146388">posúvač</translation>
<translation id="1235745349614807883">Vyčistiť posledné vyhľadávania</translation>
+<translation id="1281252709823657822">dialóg</translation>
<translation id="1342835525016946179">článok</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">oblasť</translation>
<translation id="1591562245178063882">Tento mesiac</translation>
<translation id="1637811476055996098">Vybrať súbory</translation>
+<translation id="167575180612809735">indikátor zaneprázdnenosti</translation>
<translation id="1729654308190250600">Zadajte e-mailovú adresu, ktorá nie je prázdna hodnota.</translation>
<translation id="1758486001363313524">Iné...</translation>
+<translation id="1806710327868736751">dialóg_upozornenia</translation>
+<translation id="1821985195704844674">stromová mriežka</translation>
<translation id="1822429046913737220">AM / PM</translation>
<translation id="1832974991323546415">prehrať na vzdialenom zariadení</translation>
<translation id="1842960171412779397">vybrať</translation>
+<translation id="1880518467580572141">osnova</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">stav</translation>
<translation id="1938124657309484470">Hodnota musí byť <ph name="MAXIMUM_DATE_OR_TIME" /> alebo skôr.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Tento text musíte skrátiť na <ph name="MAX_CHARACTERS" /> znakov alebo menej (súčasný počet znakov: <ph name="CURRENT_LENGTH" />).</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. týždeň, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">začiarkavacie políčko</translation>
+<translation id="2335594187091864976">výber dátumu a času</translation>
<translation id="248395913932153421">Deň</translation>
<translation id="2507943997699731163">Vyplňte toto pole.</translation>
+<translation id="2508569020611168319">zoznam kariet</translation>
<translation id="2548326553472216322">Žiadne posledné vyhľadávania</translation>
<translation id="2572483411312390101">prehrať</translation>
<translation id="2613802280814924224">Zadajte platnú hodnotu. Najbližšia platná hodnota je <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">päta</translation>
<translation id="2723001399770238859">zvuk</translation>
<translation id="2746543609216772311">Hodnota musí byť <ph name="MINIMUM_DATE_OR_TIME" /> alebo neskôr.</translation>
+<translation id="2759744352195237655">kontextové tlačidlo</translation>
<translation id="2761667185364618470">Ak chcete pokračovať, začiarknite toto políčko.</translation>
<translation id="2846343701378493991">1024 (stredný stupeň)</translation>
+<translation id="2896972712917208084">skupina prepínačov</translation>
<translation id="2901282870647571346">aktuálny stav filmu</translation>
<translation id="2908441821576996758">Zadajte zoznam e-mailových adries oddelených čiarkou.</translation>
+<translation id="2931838996092594335">kliknutie</translation>
+<translation id="2940813599313844715">objekt</translation>
<translation id="2942448076852699108">zvýraznený obsah</translation>
<translation id="3040011195152428237">odkaz</translation>
<translation id="3075154866155599887">Zadajte platnú hodnotu. Pole obsahuje neúplnú hodnotu alebo neplatný dátum.</translation>
+<translation id="3078740164268491126">tabuľka</translation>
+<translation id="3086746722712840547">poznámka</translation>
<translation id="310520048233152454">Zadajte webovú adresu.</translation>
+<translation id="3175736971608411871">časovač</translation>
+<translation id="3199563858620722075">pole s výberom</translation>
<translation id="3450233048674729344">Hodnota musí byť menšia alebo rovná hodnote <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">definícia</translation>
+<translation id="3557673793733683882">nadpis <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">zostávajúci čas do konca filmu v sekundách</translation>
<translation id="3706100364254443312">prepínač</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">výraz</translation>
<translation id="3822383571486410024">Predĺžte tento text aspoň na <ph name="MIN_CHARACTERS" /> alebo viac znakov (momentálny počet znakov je <ph name="CURRENT_LENGTH" />).</translation>
<translation id="383465348367842624">Časť pred znakom <ph name="ATSIGN" /> by nemala obsahovať symbol <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="3924558731517983934">aplikácia</translation>
+<translation id="3960700977367013758">posúvač</translation>
<translation id="4103419683916926126">Milisekundy</translation>
+<translation id="4151657705144244502">grafika</translation>
<translation id="4201051445878709314">Zobraziť predchádzajúci mesiac</translation>
<translation id="4202807286478387388">skok</translation>
+<translation id="421884353938374759">výber farieb</translation>
+<translation id="4248100235867064564">panel ponuky</translation>
+<translation id="4254339807215791271">informácie o obsahu</translation>
<translation id="4360991593054037559">Zadajte platnú hodnotu. Najbližšie platné hodnoty sú <ph name="VALID_VALUE_LOW" /> a <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">tlačidlo ponuky</translation>
<translation id="4522570452068850558">Podrobnosti</translation>
<translation id="4597532268155981612">formulár</translation>
+<translation id="4661075872484491155">strom</translation>
<translation id="4664250907885839816">Časť za znakom <ph name="ATSIGN" /> by nemala obsahovať symbol <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="4757246831282535685">panel karty</translation>
<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Zadajte číslo.</translation>
<translation id="4975562563186953947">Počet vybraných položiek: <ph name="SELECTED_COUNT" /></translation>
<translation id="49969490063480558">Zadajte časť za znakom <ph name="ATSIGN" />. Adresa <ph name="INVALIDADDRESS" /> je neúplná.</translation>
+<translation id="5034860022980953847">indikátor priebehu</translation>
<translation id="5048533449481078685">ukazovateľ v zozname</translation>
<translation id="5117590920725113268">Zobraziť ďalší mesiac</translation>
+<translation id="512758898067543763">hlavička riadka</translation>
<translation id="5164977714490026579">Hodnota musí byť väčšia alebo rovná hodnote <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Zadajte časť pred znakom <ph name="ATSIGN" />. Adresa <ph name="INVALIDADDRESS" /> je neúplná.</translation>
+<translation id="5317780077021120954">Uložiť</translation>
<translation id="5406322316791861025">hodnota</translation>
+<translation id="5453733299334684579">položka stromu</translation>
<translation id="5466621249238537318">Vyberte jeden alebo viac súborov.</translation>
<translation id="5468998798572797635">ukončiť režim celej obrazovky</translation>
<translation id="5476505524087279545">zrušiť označenie</translation>
+<translation id="5516424706154626233">výber dátumu</translation>
<translation id="5546461542133609677">obnoviť zvuk</translation>
+<translation id="561939826962581046">čas</translation>
<translation id="5641012560118721995">pozastaviť prehrávanie</translation>
+<translation id="5643186887447432888">tlačidlo</translation>
<translation id="5843503607508392247">Iné...</translation>
<translation id="5939518447894949180">Obnoviť</translation>
<translation id="5944544982112848342">2048 (vysoký stupeň)</translation>
<translation id="5966707198760109579">Týždeň</translation>
-<translation id="598301471034819706">adresa</translation>
+<translation id="5987525920412732405">tlačidlo otáčania</translation>
<translation id="6015796118275082299">Rok</translation>
+<translation id="6023896073578205740">pole s ponukou</translation>
<translation id="6101327004457443354">obnoviť zvukovú stopu</translation>
<translation id="6119846243427417423">aktivovať</translation>
+<translation id="6164829606128959761">meter</translation>
<translation id="6270583010843788609">časová os filmu</translation>
<translation id="6359256949422175976">posúvač času filmu</translation>
<translation id="6398862346408813489">Zobraziť panel na výber mesiaca</translation>
<translation id="6404546809543547843">posúvač časovej osi zvuku</translation>
+<translation id="648732519525291180">výber času</translation>
<translation id="658823671542763450">prejsť do režimu celej obrazovky</translation>
+<translation id="6637586476836377253">denník</translation>
<translation id="6643016212128521049">Vymazať</translation>
<translation id="6663448176199120256">Posledné vyhľadávania</translation>
<translation id="668171684555832681">Iný...</translation>
<translation id="6692633176391053278">stepper</translation>
+<translation id="6739588121953935928">pravítko</translation>
+<translation id="6755330956360078551">popis</translation>
<translation id="6820355525329141109">Doplnok sa nepodarilo načítať.</translation>
<translation id="6843725295806269523">stlmiť</translation>
<translation id="6845533974506654842">stlačiť</translation>
<translation id="6853785296079745596">skryť skryté titulky</translation>
+<translation id="6885760532393684712">adresár</translation>
+<translation id="6934078000481955284">značka blockquote</translation>
<translation id="7057186640035488495">čas filmu</translation>
<translation id="709897737746224366">Zadajte hodnotu zodpovedajúcu požadovanému formátu.</translation>
<translation id="7223624360433298498">uplynutý čas</translation>
<translation id="7263440858009898357">Vyberte položku zo zoznamu.</translation>
+<translation id="727747134524199931">hlavička stĺpca</translation>
<translation id="7364796246159120393">Vybrať súbor</translation>
<translation id="739024184232394898">Iné...</translation>
+<translation id="7491962110804786152">karta</translation>
<translation id="7673697353781729403">Hodiny</translation>
<translation id="7720026100085573005">zostávajúci čas</translation>
<translation id="7740016676195725605">ukončiť zobrazovanie skrytých titulkov</translation>
<translation id="7740050170769002709">Obsah HTML</translation>
<translation id="7789962463072032349">pozastaviť</translation>
+<translation id="7802800022689234070">trojuholníkové tlačidlo na zobrazenie skrytého obsahu</translation>
<translation id="7888071071722539607">Uveďte v e-mailovej adrese znak <ph name="ATSIGN" />. V adrese <ph name="INVALIDADDRESS" /> znak <ph name="ATSIGN" /> chýba.</translation>
+<translation id="7891486169920085145">rozdeľovač</translation>
<translation id="795667975304826397">Nie je vybratý žiadny súbor</translation>
<translation id="8053789581856978548">textové pole pre vyhľadávanie</translation>
<translation id="8115662671911883373">zobrazovať skryté titulky</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">mapa obrázka</translation>
<translation id="835897206747267392">Neplatná hodnota.</translation>
<translation id="838869780401515933">označiť</translation>
+<translation id="8433900881053900389">panel s nástrojmi</translation>
<translation id="8444882422881193423">Počet súborov: <ph name="NUMBER_OF_FILES" /></translation>
<translation id="8451268428117625855">Vyberte súbor.</translation>
+<translation id="8461852803063341183">prepínač</translation>
+<translation id="8511325616783751178">tlačidlo rozbaľovacej ponuky</translation>
<translation id="8534579021159131403">Minúty</translation>
<translation id="8541249477527128034">ovládanie médií</translation>
<translation id="8583702881314752957">zoznam definícií</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">začať prehrávanie</translation>
<translation id="8851136666856101339">hlavné</translation>
<translation id="8987927404178983737">Mesiac</translation>
+<translation id="9002566407876343676">otvorenie</translation>
<translation id="901493112792887934">aktuálny čas v sekundách</translation>
<translation id="9048119486235211610">navigácia</translation>
<translation id="9050748414552849310">zobraziť skryté titulky</translation>
+<translation id="9062295712474918030">dokument</translation>
<translation id="9108370397979208512">matematika</translation>
<translation id="9132465097189459683">Iné...</translation>
+<translation id="9138385573473225930">upozornenie</translation>
<translation id="9155987714137265666"><ph name="WEEK" /> začínajúci <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">bunka</translation>
+<translation id="966787709310836684">ponuka</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_sl.xtb b/chromium/content/app/strings/translations/content_strings_sl.xtb
index cbbae1fad79..310155830a2 100644
--- a/chromium/content/app/strings/translations/content_strings_sl.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sl.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="sl">
<translation id="1014825444426747588">prazno</translation>
+<translation id="1018939186200882850">menijski element</translation>
<translation id="1020833440720551630">izklop zvoka za zvočni posnetek</translation>
<translation id="10623998915015855">preklopni gumb</translation>
<translation id="1088086359088493902">Sekunde</translation>
<translation id="1171774979989969504">Vnesite e-poštni naslov</translation>
<translation id="1188858454923323853">dopolnilno</translation>
+<translation id="1206619573307042055">potujoči napis</translation>
+<translation id="1206693055195146388">drsnik</translation>
<translation id="1235745349614807883">Počisti zadnja iskanja</translation>
+<translation id="1281252709823657822">pogovorno okno</translation>
<translation id="1342835525016946179">člnk</translation>
<translation id="1359897965706325498">pasica</translation>
<translation id="1589122976691792535">območje</translation>
<translation id="1591562245178063882">Ta mesec</translation>
<translation id="1637811476055996098">Izberi datoteke</translation>
+<translation id="167575180612809735">kazalnik zasedenosti</translation>
<translation id="1729654308190250600">Vnesite e-poštni naslov (polje ne sme biti prazno).</translation>
<translation id="1758486001363313524">Drugo ...</translation>
+<translation id="1806710327868736751">pogovorno okno z opozorilom</translation>
+<translation id="1821985195704844674">drevesna mreža</translation>
<translation id="1822429046913737220">Dopoldne/popoldne</translation>
<translation id="1832974991323546415">predvajanje v oddaljeni napravi</translation>
<translation id="1842960171412779397">izberi</translation>
+<translation id="1880518467580572141">oris</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">stanje</translation>
<translation id="1938124657309484470">Vrednost mora biti <ph name="MAXIMUM_DATE_OR_TIME" /> ali prej.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Skrajšajte to besedilo na <ph name="MAX_CHARACTERS" /> znakov ali manj (trenutno uporabljate <ph name="CURRENT_LENGTH" /> znakov).</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. teden, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">potrditveno polje</translation>
+<translation id="2335594187091864976">izbirnik datuma in ure</translation>
<translation id="248395913932153421">Dan</translation>
<translation id="2507943997699731163">Izpolnite to polje</translation>
+<translation id="2508569020611168319">seznam zavihkov</translation>
<translation id="2548326553472216322">Ni zadnjih iskanj</translation>
<translation id="2572483411312390101">predvajanje</translation>
<translation id="2613802280814924224">Vnesite veljavno vrednost. Najbližja veljavna vrednost je <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">noga</translation>
<translation id="2723001399770238859">zvok</translation>
<translation id="2746543609216772311">Vrednost mora biti <ph name="MINIMUM_DATE_OR_TIME" /> ali pozneje.</translation>
+<translation id="2759744352195237655">pojavni gumb</translation>
<translation id="2761667185364618470">Potrdite to polje, če želite nadaljevati.</translation>
<translation id="2846343701378493991">1024 (srednja stopnja)</translation>
+<translation id="2896972712917208084">skupina izbirnih gumbov</translation>
<translation id="2901282870647571346">trenutno stanje filma</translation>
<translation id="2908441821576996758">Vnesite seznam e-poštnih naslovov, ločenih z vejicami</translation>
+<translation id="2931838996092594335">klikniti</translation>
+<translation id="2940813599313844715">predmet</translation>
<translation id="2942448076852699108">označena vsebina</translation>
<translation id="3040011195152428237">povezava</translation>
<translation id="3075154866155599887">Vnesite veljavno vrednost. Vnos v polje je nepopoln ali vsebuje neveljaven datum.</translation>
+<translation id="3078740164268491126">tabela</translation>
+<translation id="3086746722712840547">opmb</translation>
<translation id="310520048233152454">Vnesite URL.</translation>
+<translation id="3175736971608411871">merilnik časa</translation>
+<translation id="3199563858620722075">kombinirano polje</translation>
<translation id="3450233048674729344">Vrednost mora biti manjša od <ph name="MAXIMUM" /> ali enaka.</translation>
<translation id="3486220673238053218">opredelitev</translation>
+<translation id="3557673793733683882">naslov <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">preostale sekunde filma</translation>
<translation id="3706100364254443312">preklop</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">izraz</translation>
<translation id="3822383571486410024">Podaljšajte to besedilo na toliko znakov ali več: <ph name="MIN_CHARACTERS" /> (trenutno uporabljate toliko znakov: <ph name="CURRENT_LENGTH" />).</translation>
<translation id="383465348367842624">Del pred »<ph name="ATSIGN" />« ne sme vsebovati znaka »<ph name="INVALIDCHARACTER" />«.</translation>
+<translation id="3924558731517983934">aplikacija</translation>
+<translation id="3960700977367013758">drsni trak</translation>
<translation id="4103419683916926126">Milisekunde</translation>
+<translation id="4151657705144244502">grafični element</translation>
<translation id="4201051445878709314">Prikaz prejšnjega meseca</translation>
<translation id="4202807286478387388">skoči</translation>
+<translation id="421884353938374759">izbirnik barve</translation>
+<translation id="4248100235867064564">menijska vrstica</translation>
+<translation id="4254339807215791271">podatki o vsebini</translation>
<translation id="4360991593054037559">Vnesite veljavno vrednost. Najbližji veljavni vrednosti sta <ph name="VALID_VALUE_LOW" /> in <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">menijski gumb</translation>
<translation id="4522570452068850558">Podrobnosti</translation>
<translation id="4597532268155981612">obrazec</translation>
+<translation id="4661075872484491155">drevo</translation>
<translation id="4664250907885839816">Del po »<ph name="ATSIGN" />« ne sme vsebovati znaka »<ph name="INVALIDCHARACTER" />«.</translation>
+<translation id="4757246831282535685">podokno z zavihki</translation>
<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Vnesite številko.</translation>
<translation id="4975562563186953947">Št. izbranih: <ph name="SELECTED_COUNT" /></translation>
<translation id="49969490063480558">Vnesite nekaj po znaku »<ph name="ATSIGN" />«. Naslov »<ph name="INVALIDADDRESS" />« je nepopoln.</translation>
+<translation id="5034860022980953847">kazalnik poteka</translation>
<translation id="5048533449481078685">označevalnik seznama</translation>
<translation id="5117590920725113268">Prikaz naslednjega meseca</translation>
+<translation id="512758898067543763">glava vrstice</translation>
<translation id="5164977714490026579">Vrednost mora biti večja od <ph name="MINIMUM" /> ali enaka.</translation>
<translation id="5307600278924710095">Vnesite nekaj in nato <ph name="ATSIGN" />. Naslov »<ph name="INVALIDADDRESS" />« je nepopoln.</translation>
+<translation id="5317780077021120954">Shrani</translation>
<translation id="5406322316791861025">številka</translation>
+<translation id="5453733299334684579">element drevesa</translation>
<translation id="5466621249238537318">Izberite eno ali več datotek.</translation>
<translation id="5468998798572797635">izhod iz celozaslonskega načina</translation>
<translation id="5476505524087279545">počisti izbor</translation>
+<translation id="5516424706154626233">izbirnik datuma</translation>
<translation id="5546461542133609677">vklop zvoka</translation>
+<translation id="561939826962581046">čas</translation>
<translation id="5641012560118721995">začasna ustavitev predvajanja</translation>
+<translation id="5643186887447432888">gumb</translation>
<translation id="5843503607508392247">Drugo ...</translation>
<translation id="5939518447894949180">Ponastavi</translation>
<translation id="5944544982112848342">2048 (visoka stopnja)</translation>
<translation id="5966707198760109579">Teden</translation>
-<translation id="598301471034819706">naslov</translation>
+<translation id="5987525920412732405">pomikalnik</translation>
<translation id="6015796118275082299">Leto</translation>
+<translation id="6023896073578205740">polje s seznamom</translation>
<translation id="6101327004457443354">vklop zvoka za zvočni posnetek</translation>
<translation id="6119846243427417423">aktiviraj</translation>
+<translation id="6164829606128959761">merilnik</translation>
<translation id="6270583010843788609">sličica časovne premice filma</translation>
<translation id="6359256949422175976">sličica časovnega krmilnika za predvajanje filma</translation>
<translation id="6398862346408813489">Prikaz podokna za izbiro meseca</translation>
<translation id="6404546809543547843">časovni krmilnik za predvajanje zvoka</translation>
+<translation id="648732519525291180">izbirnik ure</translation>
<translation id="658823671542763450">prehod v celozaslonski način</translation>
+<translation id="6637586476836377253">dnevn</translation>
<translation id="6643016212128521049">Počisti</translation>
<translation id="6663448176199120256">Zadnja iskanja</translation>
<translation id="668171684555832681">Drugo ...</translation>
<translation id="6692633176391053278">kontrolnik</translation>
+<translation id="6739588121953935928">ravnilo</translation>
+<translation id="6755330956360078551">opis orodja</translation>
<translation id="6820355525329141109">Vtičnika ni bilo mogoče naložiti.</translation>
<translation id="6843725295806269523">nemo</translation>
<translation id="6845533974506654842">pritisni</translation>
<translation id="6853785296079745596">skrivanje podnapisov</translation>
+<translation id="6885760532393684712">imenik</translation>
+<translation id="6934078000481955284">daljši citat</translation>
<translation id="7057186640035488495">čas filma</translation>
<translation id="709897737746224366">Poskrbite za ujemanje z zahtevano obliko.</translation>
<translation id="7223624360433298498">pretečeni čas</translation>
<translation id="7263440858009898357">Izberite element s seznama.</translation>
+<translation id="727747134524199931">glava stolpca</translation>
<translation id="7364796246159120393">Izberite datoteko</translation>
<translation id="739024184232394898">Drugo ...</translation>
+<translation id="7491962110804786152">tabulatorka</translation>
<translation id="7673697353781729403">Ure</translation>
<translation id="7720026100085573005">preostali čas</translation>
<translation id="7740016676195725605">ustavitev prikazovanja podnapisov</translation>
<translation id="7740050170769002709">Vsebina HTML</translation>
<translation id="7789962463072032349">premor</translation>
+<translation id="7802800022689234070">trikotnik z dodatno vsebino</translation>
<translation id="7888071071722539607">V e-poštnem naslovu mora biti znak »<ph name="ATSIGN" />«. V naslovu »<ph name="INVALIDADDRESS" />« manjka »<ph name="ATSIGN" />«.</translation>
+<translation id="7891486169920085145">razdelilnik</translation>
<translation id="795667975304826397">Nobena datoteka ni izbrana</translation>
<translation id="8053789581856978548">besedilno polje za iskanje</translation>
<translation id="8115662671911883373">začetek predvajanja podnapisov</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">slikovni zemljevid</translation>
<translation id="835897206747267392">Neveljavna vrednost.</translation>
<translation id="838869780401515933">potrdi</translation>
+<translation id="8433900881053900389">orodna vrstica</translation>
<translation id="8444882422881193423">Število datotek: <ph name="NUMBER_OF_FILES" /></translation>
<translation id="8451268428117625855">Izberite datoteko.</translation>
+<translation id="8461852803063341183">izbirni gumb</translation>
+<translation id="8511325616783751178">spustni gumb</translation>
<translation id="8534579021159131403">Minute</translation>
<translation id="8541249477527128034">nadziranje predstavnosti</translation>
<translation id="8583702881314752957">seznam opredelitev</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">začetek predvajanja</translation>
<translation id="8851136666856101339">glavn</translation>
<translation id="8987927404178983737">Mesec</translation>
+<translation id="9002566407876343676">odpreti</translation>
<translation id="901493112792887934">trenutni čas v sekundah</translation>
<translation id="9048119486235211610">krmarjenje</translation>
<translation id="9050748414552849310">prikaz podnapisov</translation>
+<translation id="9062295712474918030">dokument</translation>
<translation id="9108370397979208512">matematika</translation>
<translation id="9132465097189459683">Drugo ...</translation>
+<translation id="9138385573473225930">opozorilo</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, začne se <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">celica</translation>
+<translation id="966787709310836684">meni</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_sr.xtb b/chromium/content/app/strings/translations/content_strings_sr.xtb
index 50a88407dec..f064fdc51ff 100644
--- a/chromium/content/app/strings/translations/content_strings_sr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sr.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="sr">
<translation id="1014825444426747588">празно</translation>
+<translation id="1018939186200882850">ставка менија</translation>
<translation id="1020833440720551630">искључите звук аудио снимка</translation>
<translation id="10623998915015855">дугме за укључивање/искључивање</translation>
<translation id="1088086359088493902">Секунде</translation>
<translation id="1171774979989969504">Унесите имејл адресу.</translation>
<translation id="1188858454923323853">комплементарно</translation>
+<translation id="1206619573307042055">покретни текст</translation>
+<translation id="1206693055195146388">клизач</translation>
<translation id="1235745349614807883">Обриши недавне претраге</translation>
+<translation id="1281252709823657822">дијалог</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">банер</translation>
<translation id="1589122976691792535">регион</translation>
<translation id="1591562245178063882">Овај месец</translation>
<translation id="1637811476055996098">Избор датотека</translation>
+<translation id="167575180612809735">индикатор да је заузето</translation>
<translation id="1729654308190250600">Унесите имејл адресу која није празна.</translation>
<translation id="1758486001363313524">Друго...</translation>
+<translation id="1806710327868736751">дијалог обавештења</translation>
+<translation id="1821985195704844674">мрежа стабла</translation>
<translation id="1822429046913737220">пре подне/по подне</translation>
<translation id="1832974991323546415">пуштајте на удаљеном уређају</translation>
<translation id="1842960171412779397">изабери</translation>
+<translation id="1880518467580572141">граница</translation>
<translation id="1921819250265091946">дд</translation>
<translation id="1930711995431081526">статус</translation>
<translation id="1938124657309484470">Вредност мора да буде <ph name="MAXIMUM_DATE_OR_TIME" /> или старија.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Скратите овај текст на <ph name="MAX_CHARACTERS" /> знак(ов)а или мање (тренутно користите <ph name="CURRENT_LENGTH" /> знак(ов)а).</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. недеља, <ph name="YEAR" />.</translation>
<translation id="2291999235780842123">поље за потврду</translation>
+<translation id="2335594187091864976">бирач датума и времена</translation>
<translation id="248395913932153421">Дан</translation>
<translation id="2507943997699731163">Попуните ово поље.</translation>
+<translation id="2508569020611168319">листа картица</translation>
<translation id="2548326553472216322">Нема недавних претрага</translation>
<translation id="2572483411312390101">пустите</translation>
<translation id="2613802280814924224">Унесите важећу вредност. Најближа важећа вредност је <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">подножје</translation>
<translation id="2723001399770238859">аудио</translation>
<translation id="2746543609216772311">Вредност мора да буде <ph name="MINIMUM_DATE_OR_TIME" /> или новија.</translation>
+<translation id="2759744352195237655">искачуће дугме</translation>
<translation id="2761667185364618470">Потврдите избор у овом пољу за потврду уколико желите да наставите.</translation>
<translation id="2846343701378493991">1024 (средњи степен)</translation>
+<translation id="2896972712917208084">група дугмади за избор</translation>
<translation id="2901282870647571346">актуелни статус филма</translation>
<translation id="2908441821576996758">Унесите листу имејл адреса раздвојених зарезима.</translation>
+<translation id="2931838996092594335">клик</translation>
+<translation id="2940813599313844715">објекат</translation>
<translation id="2942448076852699108">истакнути садржај</translation>
<translation id="3040011195152428237">веза</translation>
<translation id="3075154866155599887">Унесите важећу вредност. Поље није попуњено или садржи неважећи датум.</translation>
+<translation id="3078740164268491126">табела</translation>
+<translation id="3086746722712840547">белешка</translation>
<translation id="310520048233152454">Унесите URL адресу.</translation>
+<translation id="3175736971608411871">тајмер</translation>
+<translation id="3199563858620722075">комбиновани оквир</translation>
<translation id="3450233048674729344">Вредност сме да буде највише <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">дефиниција</translation>
+<translation id="3557673793733683882">заглавље <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">број преосталих секунди филма</translation>
<translation id="3706100364254443312">прекидач</translation>
<translation id="3732799496749320381">мм</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">термин</translation>
<translation id="3822383571486410024">Продужите овај текст на <ph name="MIN_CHARACTERS" /> знак(ов)а или више (тренутно користите <ph name="CURRENT_LENGTH" /> знак(ов)а).</translation>
<translation id="383465348367842624">Део пре „<ph name="ATSIGN" />“ не треба да садржи симбол „<ph name="INVALIDCHARACTER" />“.</translation>
+<translation id="3924558731517983934">апликација</translation>
+<translation id="3960700977367013758">трака за померање</translation>
<translation id="4103419683916926126">Милисекунде</translation>
+<translation id="4151657705144244502">графички елемент</translation>
<translation id="4201051445878709314">Прикажи претходни месец</translation>
<translation id="4202807286478387388">прескочи</translation>
+<translation id="421884353938374759">бирач боја</translation>
+<translation id="4248100235867064564">трака са менијима</translation>
+<translation id="4254339807215791271">информације о садржају</translation>
<translation id="4360991593054037559">Унесите важећу вредност. Две најближе важеће вредности су <ph name="VALID_VALUE_LOW" /> и <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">дугме менија</translation>
<translation id="4522570452068850558">Детаљи</translation>
<translation id="4597532268155981612">образац</translation>
+<translation id="4661075872484491155">стабло</translation>
<translation id="4664250907885839816">Део после „<ph name="ATSIGN" />“ не треба да садржи симбол „<ph name="INVALIDCHARACTER" />“.</translation>
+<translation id="4757246831282535685">табла са картицама</translation>
<translation id="4763480195061959176">видео</translation>
+<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Унесите број.</translation>
<translation id="4975562563186953947">Изабрано: <ph name="SELECTED_COUNT" /></translation>
<translation id="49969490063480558">Унесите неки део после „<ph name="ATSIGN" />“. Адреса „<ph name="INVALIDADDRESS" />“ је непотпуна.</translation>
+<translation id="5034860022980953847">индикатор напретка</translation>
<translation id="5048533449481078685">означивач листе</translation>
<translation id="5117590920725113268">Прикажи следећи месец</translation>
+<translation id="512758898067543763">заглавље реда</translation>
<translation id="5164977714490026579">Вредност сме да буде најмање <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Унесите неки део пре „<ph name="ATSIGN" />“. Адреса „<ph name="INVALIDADDRESS" />“ је непотпуна.</translation>
+<translation id="5317780077021120954">Сачувај</translation>
<translation id="5406322316791861025">цифра</translation>
+<translation id="5453733299334684579">ставка стабла</translation>
<translation id="5466621249238537318">Изаберите једну или више датотека.</translation>
<translation id="5468998798572797635">изађите из режима целог екрана</translation>
<translation id="5476505524087279545">опозови избор</translation>
+<translation id="5516424706154626233">бирач датума</translation>
<translation id="5546461542133609677">укључите звук</translation>
+<translation id="561939826962581046">време</translation>
<translation id="5641012560118721995">паузирајте репродукцију</translation>
+<translation id="5643186887447432888">дугме</translation>
<translation id="5843503607508392247">Друго...</translation>
<translation id="5939518447894949180">Ресетуј</translation>
<translation id="5944544982112848342">2048 (високи степен)</translation>
<translation id="5966707198760109579">Недеља</translation>
-<translation id="598301471034819706">адреса</translation>
+<translation id="5987525920412732405">дугме за промену вредности</translation>
<translation id="6015796118275082299">Година</translation>
+<translation id="6023896073578205740">оквир са листом</translation>
<translation id="6101327004457443354">укључите звук аудио снимка</translation>
<translation id="6119846243427417423">активирај</translation>
+<translation id="6164829606128959761">мерач</translation>
<translation id="6270583010843788609">клизач на временској траци филма</translation>
<translation id="6359256949422175976">клизач за трајање филма</translation>
<translation id="6398862346408813489">Прикажи таблу за избор месеца</translation>
<translation id="6404546809543547843">клизач за трајање аудио-садржаја</translation>
+<translation id="648732519525291180">бирач времена</translation>
<translation id="658823671542763450">пређите на режим целог екрана</translation>
+<translation id="6637586476836377253">log</translation>
<translation id="6643016212128521049">Обриши</translation>
<translation id="6663448176199120256">Недавне претраге</translation>
<translation id="668171684555832681">Друго...</translation>
<translation id="6692633176391053278">контрола за промене у корацима</translation>
+<translation id="6739588121953935928">лењир</translation>
+<translation id="6755330956360078551">објашњење</translation>
<translation id="6820355525329141109">Учитавање додатне компоненте није успело.</translation>
<translation id="6843725295806269523">искључи звук</translation>
<translation id="6845533974506654842">притисни</translation>
<translation id="6853785296079745596">сакријте опционални титл</translation>
+<translation id="6885760532393684712">каталог</translation>
+<translation id="6934078000481955284">издвојени цитат</translation>
<translation id="7057186640035488495">трајање филма</translation>
<translation id="709897737746224366">Изаберите захтевани формат.</translation>
<translation id="7223624360433298498">протекло време</translation>
<translation id="7263440858009898357">Изаберите ставку са листе.</translation>
+<translation id="727747134524199931">заглавље колоне</translation>
<translation id="7364796246159120393">Одабери датотеку</translation>
<translation id="739024184232394898">Друго...</translation>
+<translation id="7491962110804786152">tab</translation>
<translation id="7673697353781729403">Сати</translation>
<translation id="7720026100085573005">преостало време</translation>
<translation id="7740016676195725605">зауставите приказивање опционалног титла</translation>
<translation id="7740050170769002709">HTML садржај</translation>
<translation id="7789962463072032349">паузирај</translation>
+<translation id="7802800022689234070">троугао за откривање</translation>
<translation id="7888071071722539607">Уврстите „<ph name="ATSIGN" />“ у имејл адресу. У адреси е-поште „<ph name="INVALIDADDRESS" />“ недостаје „<ph name="ATSIGN" />“.</translation>
+<translation id="7891486169920085145">разделник</translation>
<translation id="795667975304826397">Није одабрано</translation>
<translation id="8053789581856978548">поље за текст претраге</translation>
<translation id="8115662671911883373">започните приказивање опционалног титла</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">мапа слике</translation>
<translation id="835897206747267392">Неважећа вредност.</translation>
<translation id="838869780401515933">изабери</translation>
+<translation id="8433900881053900389">трака с алаткама</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> датотеке(а)</translation>
<translation id="8451268428117625855">Изаберите датотеку.</translation>
+<translation id="8461852803063341183">дугме за избор</translation>
+<translation id="8511325616783751178">дугме за падајући мени</translation>
<translation id="8534579021159131403">Минути</translation>
<translation id="8541249477527128034">контрола за медије</translation>
<translation id="8583702881314752957">листа дефиниција</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">започните репродукцију</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8987927404178983737">Месец</translation>
+<translation id="9002566407876343676">отварање</translation>
<translation id="901493112792887934">актуелно време у секундама</translation>
<translation id="9048119486235211610">навигација</translation>
<translation id="9050748414552849310">приказивање опционалног титла</translation>
+<translation id="9062295712474918030">документ</translation>
<translation id="9108370397979208512">математички</translation>
<translation id="9132465097189459683">Друго...</translation>
+<translation id="9138385573473225930">обавештење</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, од <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">ћелија</translation>
+<translation id="966787709310836684">мени</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_sv.xtb b/chromium/content/app/strings/translations/content_strings_sv.xtb
index 22ec19c447e..8e6c8a4b857 100644
--- a/chromium/content/app/strings/translations/content_strings_sv.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sv.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="sv">
<translation id="1014825444426747588">tomt</translation>
+<translation id="1018939186200882850">menyalternativ</translation>
<translation id="1020833440720551630">stäng av ljudspår</translation>
<translation id="10623998915015855">växlingsknapp</translation>
<translation id="1088086359088493902">Sekunder</translation>
<translation id="1171774979989969504">Ange en e-postadress.</translation>
<translation id="1188858454923323853">kompletterande</translation>
+<translation id="1206619573307042055">markör</translation>
+<translation id="1206693055195146388">skjutreglage</translation>
<translation id="1235745349614807883">Rensa senaste sökningar</translation>
+<translation id="1281252709823657822">dialogruta</translation>
<translation id="1342835525016946179">artikel</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">område</translation>
<translation id="1591562245178063882">Den här månaden</translation>
<translation id="1637811476055996098">Välj filer</translation>
+<translation id="167575180612809735">upptaget-indikator</translation>
<translation id="1729654308190250600">Ange en e-postadress som inte är tom.</translation>
<translation id="1758486001363313524">Annat ...</translation>
+<translation id="1806710327868736751">varningsdialogruta</translation>
+<translation id="1821985195704844674">träddiagram</translation>
<translation id="1822429046913737220">FM/EM</translation>
<translation id="1832974991323546415">spela på en fjärrenhet</translation>
<translation id="1842960171412779397">välj</translation>
+<translation id="1880518467580572141">översikt</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">status</translation>
<translation id="1938124657309484470">Värdet måste vara <ph name="MAXIMUM_DATE_OR_TIME" /> eller tidigare.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Förkorta texten till <ph name="MAX_CHARACTERS" /> tecken eller mindre (nu är texten <ph name="CURRENT_LENGTH" /> tecken).</translation>
<translation id="2247351761944213033">Vecka <ph name="WEEKNUMBER" /> <ph name="YEAR" /></translation>
<translation id="2291999235780842123">kryssruta</translation>
+<translation id="2335594187091864976">datum- och tidsväljare</translation>
<translation id="248395913932153421">Dag</translation>
<translation id="2507943997699731163">Fyll i det här fältet.</translation>
+<translation id="2508569020611168319">fliklista</translation>
<translation id="2548326553472216322">Inga nya sökningar</translation>
<translation id="2572483411312390101">spela upp</translation>
<translation id="2613802280814924224">Ange ett giltigt värde. Det närmast giltiga värdet är <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">sidfot</translation>
<translation id="2723001399770238859">ljud</translation>
<translation id="2746543609216772311">Värdet måste vara <ph name="MINIMUM_DATE_OR_TIME" /> eller senare.</translation>
+<translation id="2759744352195237655">popup-knapp</translation>
<translation id="2761667185364618470">Markera den här kryssrutan om du vill fortsätta.</translation>
<translation id="2846343701378493991">1024 (medel)</translation>
+<translation id="2896972712917208084">alternativknappsgrupp</translation>
<translation id="2901282870647571346">aktuell filmstatus</translation>
<translation id="2908441821576996758">Ange en kommaavgränsad lista med e-postadresser.</translation>
+<translation id="2931838996092594335">klicka</translation>
+<translation id="2940813599313844715">objekt</translation>
<translation id="2942448076852699108">markerat innehåll</translation>
<translation id="3040011195152428237">länk</translation>
<translation id="3075154866155599887">Ange ett giltigt värde. Fältet är ofullständigt eller innehåller ett ogiltigt datum.</translation>
+<translation id="3078740164268491126">tabell</translation>
+<translation id="3086746722712840547">anm</translation>
<translation id="310520048233152454">Ange en webbadress.</translation>
+<translation id="3175736971608411871">timer</translation>
+<translation id="3199563858620722075">kombinationsruta</translation>
<translation id="3450233048674729344">Värdet måste vara mindre än eller lika med <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">definition</translation>
+<translation id="3557673793733683882">rubrik <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">antal sekunder kvar av filmen</translation>
<translation id="3706100364254443312">växel</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">term</translation>
<translation id="3822383571486410024">Lägg till minst <ph name="MIN_CHARACTERS" /> tecken (för närvarande har du angett <ph name="CURRENT_LENGTH" /> tecken).</translation>
<translation id="383465348367842624">En del följt av <ph name="ATSIGN" /> får inte innehålla symbolen <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="3924558731517983934">program</translation>
+<translation id="3960700977367013758">rullningslist</translation>
<translation id="4103419683916926126">Millisekunder</translation>
+<translation id="4151657705144244502">bild</translation>
<translation id="4201051445878709314">Visa föregående månad</translation>
<translation id="4202807286478387388">fortsätta</translation>
+<translation id="421884353938374759">färgval</translation>
+<translation id="4248100235867064564">menyfält</translation>
+<translation id="4254339807215791271">innehållsinformation</translation>
<translation id="4360991593054037559">Ange ett giltigt värde. De två närmaste giltiga värdena är <ph name="VALID_VALUE_LOW" /> och <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">menyknapp</translation>
<translation id="4522570452068850558">Info</translation>
<translation id="4597532268155981612">formulär</translation>
+<translation id="4661075872484491155">träd</translation>
<translation id="4664250907885839816">En del efter <ph name="ATSIGN" /> får inte innehålla symbolen <ph name="INVALIDCHARACTER" />.</translation>
+<translation id="4757246831282535685">flikpanel</translation>
<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">sök</translation>
<translation id="4812940957355064477">Ange ett nummer.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> valda</translation>
<translation id="49969490063480558">Ange en del följt av <ph name="ATSIGN" />. <ph name="INVALIDADDRESS" /> är ofullständig.</translation>
+<translation id="5034860022980953847">förloppsindikator</translation>
<translation id="5048533449481078685">listmarkör</translation>
<translation id="5117590920725113268">Visa nästa månad</translation>
+<translation id="512758898067543763">radrubrik</translation>
<translation id="5164977714490026579">Värdet måste vara större än eller lika med <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Ange en del följt av <ph name="ATSIGN" />. <ph name="INVALIDADDRESS" /> är ofullständig.</translation>
+<translation id="5317780077021120954">Spara</translation>
<translation id="5406322316791861025">figur</translation>
+<translation id="5453733299334684579">trädobjekt</translation>
<translation id="5466621249238537318">Välj en eller flera filer.</translation>
<translation id="5468998798572797635">avsluta helskärmsläge</translation>
<translation id="5476505524087279545">kryssa av</translation>
+<translation id="5516424706154626233">datumväljare</translation>
<translation id="5546461542133609677">visa</translation>
+<translation id="561939826962581046">tid</translation>
<translation id="5641012560118721995">pausa uppspelning</translation>
+<translation id="5643186887447432888">knapp</translation>
<translation id="5843503607508392247">Annat ...</translation>
<translation id="5939518447894949180">Återställ</translation>
<translation id="5944544982112848342">2048 (hög)</translation>
<translation id="5966707198760109579">Vecka</translation>
-<translation id="598301471034819706">adress</translation>
+<translation id="5987525920412732405">snurrknapp</translation>
<translation id="6015796118275082299">År</translation>
+<translation id="6023896073578205740">listruta</translation>
<translation id="6101327004457443354">spela upp ljudspåret</translation>
<translation id="6119846243427417423">aktivera</translation>
+<translation id="6164829606128959761">mätare</translation>
<translation id="6270583010843788609">miniatyr för filmtidslinje</translation>
<translation id="6359256949422175976">miniatyr för filmtidsreglage</translation>
<translation id="6398862346408813489">Visa panelen för val av månad</translation>
<translation id="6404546809543547843">tidsreglage för ljud</translation>
+<translation id="648732519525291180">tidsväljare</translation>
<translation id="658823671542763450">visa i helskärm</translation>
+<translation id="6637586476836377253">logg</translation>
<translation id="6643016212128521049">Rensa</translation>
<translation id="6663448176199120256">Senaste sökningar</translation>
<translation id="668171684555832681">Annan...</translation>
<translation id="6692633176391053278">knappreglage</translation>
+<translation id="6739588121953935928">linjal</translation>
+<translation id="6755330956360078551">beskrivning</translation>
<translation id="6820355525329141109">Det gick inte att läsa in plugin-programmet.</translation>
<translation id="6843725295806269523">ljud av</translation>
<translation id="6845533974506654842">tryck</translation>
<translation id="6853785296079745596">dölj textning</translation>
+<translation id="6885760532393684712">katalog</translation>
+<translation id="6934078000481955284">citatblock</translation>
<translation id="7057186640035488495">filmtid</translation>
<translation id="709897737746224366">Matcha det format som anges.</translation>
<translation id="7223624360433298498">förfluten tid</translation>
<translation id="7263440858009898357">Välj ett alternativ i listan.</translation>
+<translation id="727747134524199931">kolumnrubrik</translation>
<translation id="7364796246159120393">Välj fil</translation>
<translation id="739024184232394898">Annat ...</translation>
+<translation id="7491962110804786152">tabb</translation>
<translation id="7673697353781729403">Timmar</translation>
<translation id="7720026100085573005">återstående tid</translation>
<translation id="7740016676195725605">sluta visa textning</translation>
<translation id="7740050170769002709">HTML-innehåll</translation>
<translation id="7789962463072032349">paus</translation>
+<translation id="7802800022689234070">expanderingstriangel</translation>
<translation id="7888071071722539607">Inkludera ett <ph name="ATSIGN" /> i e-postadressen. <ph name="INVALIDADDRESS" /> saknar ett <ph name="ATSIGN" />.</translation>
+<translation id="7891486169920085145">delare</translation>
<translation id="795667975304826397">Ingen fil har valts</translation>
<translation id="8053789581856978548">fält för söktext</translation>
<translation id="8115662671911883373">börja visa textning</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">bildkarta</translation>
<translation id="835897206747267392">Ogiltigt värde.</translation>
<translation id="838869780401515933">kryssa för</translation>
+<translation id="8433900881053900389">verktygsfält</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> filer</translation>
<translation id="8451268428117625855">Välj en fil.</translation>
+<translation id="8461852803063341183">alternativknapp</translation>
+<translation id="8511325616783751178">rullgardinsknapp</translation>
<translation id="8534579021159131403">Minuter</translation>
<translation id="8541249477527128034">mediekontroll</translation>
<translation id="8583702881314752957">definitionslista</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">starta uppspelning</translation>
<translation id="8851136666856101339">huvud</translation>
<translation id="8987927404178983737">Månad</translation>
+<translation id="9002566407876343676">öppna</translation>
<translation id="901493112792887934">aktuell tid i sekunder</translation>
<translation id="9048119486235211610">navigering</translation>
<translation id="9050748414552849310">visa textning</translation>
+<translation id="9062295712474918030">dokument</translation>
<translation id="9108370397979208512">matte</translation>
<translation id="9132465097189459683">Annat ...</translation>
+<translation id="9138385573473225930">varning</translation>
<translation id="9155987714137265666"><ph name="WEEK" /> som börjar den <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">cell</translation>
+<translation id="966787709310836684">meny</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_sw.xtb b/chromium/content/app/strings/translations/content_strings_sw.xtb
index d18396819ac..8c0325a7f42 100644
--- a/chromium/content/app/strings/translations/content_strings_sw.xtb
+++ b/chromium/content/app/strings/translations/content_strings_sw.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="sw">
<translation id="1014825444426747588">tupu</translation>
+<translation id="1018939186200882850">kipengee cha menyu</translation>
<translation id="1020833440720551630">nyamazisha sauti ya wimbo</translation>
<translation id="10623998915015855">kitufe cha kugeuza</translation>
<translation id="1088086359088493902">Sekunde</translation>
<translation id="1171774979989969504">Tafadhali weka anwani ya barua pepe.</translation>
<translation id="1188858454923323853">nyongeza</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">kitelezi</translation>
<translation id="1235745349614807883">Futa Utafutaji wa Hivi Karibuni</translation>
+<translation id="1281252709823657822">kidirisha</translation>
<translation id="1342835525016946179">makala</translation>
<translation id="1359897965706325498">bango</translation>
<translation id="1589122976691792535">eneo</translation>
<translation id="1591562245178063882">Mwezi huu</translation>
<translation id="1637811476055996098">Chagua Faili</translation>
+<translation id="167575180612809735">kiashiria cha shughuli</translation>
<translation id="1729654308190250600">Tafadhali jaza sehemu ya anwani ya barua pepe.</translation>
<translation id="1758486001363313524">Nyingine...</translation>
+<translation id="1806710327868736751">kidirisha cha arifa</translation>
+<translation id="1821985195704844674">gridi ya mti</translation>
<translation id="1822429046913737220">AM / PM</translation>
<translation id="1832974991323546415">cheza kwenye kifaa cha mbali</translation>
<translation id="1842960171412779397">chagua</translation>
+<translation id="1880518467580572141">muhtasari</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">hali</translation>
<translation id="1938124657309484470">Thamani lazima iwe <ph name="MAXIMUM_DATE_OR_TIME" /> au mapema.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Tafadhali fupisha maandishi haya hadi vibambo <ph name="MAX_CHARACTERS" /> au chini (kwa sasa unatumia vibambo <ph name="CURRENT_LENGTH" /> ).</translation>
<translation id="2247351761944213033">Wiki <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">kisanduku cha kuteua</translation>
+<translation id="2335594187091864976">mchumaji tarehe na wakati</translation>
<translation id="248395913932153421">Siku</translation>
<translation id="2507943997699731163">Tafadhali jaza sehemu hii.</translation>
+<translation id="2508569020611168319">orodha ya vichupo</translation>
<translation id="2548326553472216322">Hakuna utafutaji wa hivi karibuni</translation>
<translation id="2572483411312390101">cheza</translation>
<translation id="2613802280814924224">Tafadhali ingiza thamani halali.Thamani halali ya karibu ni <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">kijachini</translation>
<translation id="2723001399770238859">sauti</translation>
<translation id="2746543609216772311">Thamani lazima iwe <ph name="MINIMUM_DATE_OR_TIME" /> au baadaye.</translation>
+<translation id="2759744352195237655">kitufe cha dirisha ibukizi</translation>
<translation id="2761667185364618470">Tafadhali angalia kikasha hiki iwapo unataka kuendelea.</translation>
<translation id="2846343701378493991">1024 (Gredi Wastani)</translation>
+<translation id="2896972712917208084">kikundi cha vitufe</translation>
<translation id="2901282870647571346">hali ya sasa ya filamu</translation>
<translation id="2908441821576996758">Tafadhali weka orodha ya anwani za barua pepe zilizotenganishwa kwa vikomo.</translation>
+<translation id="2931838996092594335">bofya</translation>
+<translation id="2940813599313844715">kitu</translation>
<translation id="2942448076852699108">maudhui yaliyoangaziwa</translation>
<translation id="3040011195152428237">kiungo</translation>
<translation id="3075154866155599887">Tafadhali ingiza thamani halali. Uga umekamilika au una tarehe batili.</translation>
+<translation id="3078740164268491126">jedwali</translation>
+<translation id="3086746722712840547">dokezo</translation>
<translation id="310520048233152454">Tafadhali ingiza URL.</translation>
+<translation id="3175736971608411871">kipima muda</translation>
+<translation id="3199563858620722075">kisanduku mseto</translation>
<translation id="3450233048674729344">Lazima thamani iwe chache kuliko au sawa na <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">ufafanuzi</translation>
+<translation id="3557673793733683882">kichwa cha <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">idadi ya sekunde zinazosalia za filamu</translation>
<translation id="3706100364254443312">badilisha</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">neno</translation>
<translation id="3822383571486410024">Tafadhali refusha maandishi haya hadi herufi <ph name="MIN_CHARACTERS" /> au zaidi (kwa sasa unatumia herufi <ph name="CURRENT_LENGTH" />).</translation>
<translation id="383465348367842624">Sehemu inayofuatwa na '<ph name="ATSIGN" />' haipaswi kuwa na alama ya '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="3924558731517983934">programu</translation>
+<translation id="3960700977367013758">sehemu ya kusogeza</translation>
<translation id="4103419683916926126">nukta</translation>
+<translation id="4151657705144244502">mchoro</translation>
<translation id="4201051445878709314">Onyesha mwezi uliotangulia</translation>
<translation id="4202807286478387388">ruka</translation>
+<translation id="421884353938374759">kiteua rangi</translation>
+<translation id="4248100235867064564">upau wa menyu</translation>
+<translation id="4254339807215791271">maelezo ya maudhui</translation>
<translation id="4360991593054037559">Tafadhali ingiza thamani halali. Thamani mbili halali za karibu ni <ph name="VALID_VALUE_LOW" /> na <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">kitufe cha menyu</translation>
<translation id="4522570452068850558">Maelezo</translation>
<translation id="4597532268155981612">fomu</translation>
+<translation id="4661075872484491155">mti</translation>
<translation id="4664250907885839816">Sehemu inayofuata '<ph name="ATSIGN" />' haipaswi kuwa na alama ya '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="4757246831282535685">kisanduku cha kichupo</translation>
<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">tafuta</translation>
<translation id="4812940957355064477">Tafadhali ingiza nambari.</translation>
<translation id="4975562563186953947">Vipengee <ph name="SELECTED_COUNT" /> vimechaguliwa</translation>
<translation id="49969490063480558">Tafadhali ingiza sehemu inayofuatia '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' haijakamilika.</translation>
+<translation id="5034860022980953847">kiashiria cha maendeleo</translation>
<translation id="5048533449481078685">kialamishi orodha</translation>
<translation id="5117590920725113268">Onyesha mwezi unaofuata</translation>
+<translation id="512758898067543763">kichwa cha safu mlalo</translation>
<translation id="5164977714490026579">Lazima thamani iwe kubwa kuliko au sawa na <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Tafadhali ingiza sehemu ikifuatiwa na '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' haijakamilika.</translation>
+<translation id="5317780077021120954">Hifadhi</translation>
<translation id="5406322316791861025">umbo</translation>
+<translation id="5453733299334684579">kipengee cha mti</translation>
<translation id="5466621249238537318">Tafadhali chagua faili moja au zaidi.</translation>
<translation id="5468998798572797635">Ondoka kwenye Skrini nzima</translation>
<translation id="5476505524087279545">toa tiki</translation>
+<translation id="5516424706154626233">kichagua tarehe</translation>
<translation id="5546461542133609677">washa sauti</translation>
+<translation id="561939826962581046">wakati</translation>
<translation id="5641012560118721995">sitisha kucheza</translation>
+<translation id="5643186887447432888">kitufe</translation>
<translation id="5843503607508392247">Nyingine...</translation>
<translation id="5939518447894949180">Weka upya</translation>
<translation id="5944544982112848342">2048 (Gredi ya Juu)</translation>
<translation id="5966707198760109579">Juma</translation>
-<translation id="598301471034819706">anwani</translation>
+<translation id="5987525920412732405">kitufe cha kubadilishia</translation>
<translation id="6015796118275082299">Mwaka</translation>
+<translation id="6023896073578205740">kikasha cha orodha</translation>
<translation id="6101327004457443354">washa sauti ya wimbo</translation>
<translation id="6119846243427417423">wezesha</translation>
+<translation id="6164829606128959761">mita</translation>
<translation id="6270583010843788609">kijipicha cha muda wa filamu</translation>
<translation id="6359256949422175976">kijipicha cha kitelezi cha muda wa filamu</translation>
<translation id="6398862346408813489">Onyesha kisanduku cha uchaguzi wa mwezi</translation>
<translation id="6404546809543547843">kitelezi cha muda cha sauti</translation>
+<translation id="648732519525291180">Kiteua wakati</translation>
<translation id="658823671542763450">ingia skrini kamili</translation>
+<translation id="6637586476836377253">kumbukumbu</translation>
<translation id="6643016212128521049">Futa</translation>
<translation id="6663448176199120256">Utafutaji wa hivi karibuni</translation>
<translation id="668171684555832681">Mengine...</translation>
<translation id="6692633176391053278">stepper</translation>
+<translation id="6739588121953935928">rula</translation>
+<translation id="6755330956360078551">kidirisha cha vidokezo</translation>
<translation id="6820355525329141109">Haikuweza kupakia programu-jalizi.</translation>
<translation id="6843725295806269523">nyamazisha</translation>
<translation id="6845533974506654842">bofya</translation>
<translation id="6853785296079745596">ficha manukuu yanayoweza kuonyeshwa</translation>
+<translation id="6885760532393684712">saraka</translation>
+<translation id="6934078000481955284">nukuu la msingi</translation>
<translation id="7057186640035488495">muda wa filamu</translation>
<translation id="709897737746224366">Tafadhali linganisha umbizo lililoombwa.</translation>
<translation id="7223624360433298498">muda uliokwisha</translation>
<translation id="7263440858009898357">Tafadhali chagua kipengee katika orodha.</translation>
+<translation id="727747134524199931">kijajuu cha safu wima</translation>
<translation id="7364796246159120393">Chagua Faili</translation>
<translation id="739024184232394898">Nyingine...</translation>
+<translation id="7491962110804786152">kichupo</translation>
<translation id="7673697353781729403">Saa</translation>
<translation id="7720026100085573005">muda unaosalia</translation>
<translation id="7740016676195725605">koma kuonyesha manukuu yanaweza kufichwa</translation>
<translation id="7740050170769002709">Maudhui ya HTML</translation>
<translation id="7789962463072032349">Sitisha</translation>
+<translation id="7802800022689234070">pembe tatu ya ufafanuzi</translation>
<translation id="7888071071722539607">Tafadhali jumuisha '<ph name="ATSIGN" />' katika anwani ya barua pepe. '<ph name="INVALIDADDRESS" />' inakosa '<ph name="ATSIGN" />'.</translation>
+<translation id="7891486169920085145">kitenganishi</translation>
<translation id="795667975304826397">Hakuna faili iliyochaguliwa</translation>
<translation id="8053789581856978548">sehemu ya maandishi ya utafutaji</translation>
<translation id="8115662671911883373">anza kuonyesha manukuu yaliyofungwa</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">ramani ya picha</translation>
<translation id="835897206747267392">Thamani batili.</translation>
<translation id="838869780401515933">chunguza</translation>
+<translation id="8433900881053900389">upau wa vidhibiti</translation>
<translation id="8444882422881193423">faili <ph name="NUMBER_OF_FILES" /></translation>
<translation id="8451268428117625855">Tafadhali chagua faili.</translation>
+<translation id="8461852803063341183">kitufe cha mviringo</translation>
+<translation id="8511325616783751178">kitufe kunjuzi</translation>
<translation id="8534579021159131403">Dakika</translation>
<translation id="8541249477527128034">udhibiti wa vyombo vya habari</translation>
<translation id="8583702881314752957">orodha ya ufafanuzi</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">anza kucheza</translation>
<translation id="8851136666856101339">kuu</translation>
<translation id="8987927404178983737">Mwezi</translation>
+<translation id="9002566407876343676">fungua</translation>
<translation id="901493112792887934">muda wa sasa kwa sekunde</translation>
<translation id="9048119486235211610">kuvinjari</translation>
<translation id="9050748414552849310">onyesha manakuu yaliyofichwa</translation>
+<translation id="9062295712474918030">hati</translation>
<translation id="9108370397979208512">hisabati</translation>
<translation id="9132465097189459683">Nyingine...</translation>
+<translation id="9138385573473225930">arifa</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, itaanza tarehe <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">kisanduku</translation>
+<translation id="966787709310836684">menyu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_ta.xtb b/chromium/content/app/strings/translations/content_strings_ta.xtb
index c77fc832f89..ce308d46fc5 100644
--- a/chromium/content/app/strings/translations/content_strings_ta.xtb
+++ b/chromium/content/app/strings/translations/content_strings_ta.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="ta">
<translation id="1014825444426747588">வெற்று</translation>
+<translation id="1018939186200882850">மெனு உருப்படி</translation>
<translation id="1020833440720551630">ஆடியோ டிராக்கை முடக்கு</translation>
<translation id="10623998915015855">நிலைமாற்றுதல் பொத்தான்</translation>
<translation id="1088086359088493902">வினாடிகள்</translation>
<translation id="1171774979989969504">ஒரு மின்னஞ்சல் முகவரியை உள்ளிடவும்.</translation>
<translation id="1188858454923323853">ஈடுசெய்யக்கூடியது</translation>
+<translation id="1206619573307042055">மார்கியூ</translation>
+<translation id="1206693055195146388">ஸ்லைடர்</translation>
<translation id="1235745349614807883">சமீபத்திய தேடல்களை சுத்தமாக்கு</translation>
+<translation id="1281252709823657822">உரையாடல்</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">பேனர்</translation>
<translation id="1589122976691792535">மண்டலம்</translation>
<translation id="1591562245178063882">இந்த மாதம்</translation>
<translation id="1637811476055996098">கோப்புகளைத் தேர்வுசெய்க</translation>
+<translation id="167575180612809735">பணிமிகுதி குறிப்பான்</translation>
<translation id="1729654308190250600">காலி அல்லாத மின்னஞ்சல் முகவரியை உள்ளிடவும்.</translation>
<translation id="1758486001363313524">மற்றவை…</translation>
+<translation id="1806710327868736751">விழிப்பூட்டல்_உரையாடல்</translation>
+<translation id="1821985195704844674">ட்ரீ கிரிட்</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">தொலைநிலைச் சாதனத்தில் இயக்கு</translation>
<translation id="1842960171412779397">தேர்ந்தெடு</translation>
+<translation id="1880518467580572141">சுற்றுவரி</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">நிலை</translation>
<translation id="1938124657309484470">மதிப்பு <ph name="MAXIMUM_DATE_OR_TIME" /> அல்லது அதற்கு முன்பு இருக்க வேண்டும்.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">இந்த உரையை <ph name="MAX_CHARACTERS" /> எழுத்துக்குறிகள் அல்லது அதற்கும் குறைவாக சுருக்கிடுங்கள் (நீங்கள் தற்போது <ph name="CURRENT_LENGTH" /> எழுத்துக்குறிகளைப் பயன்படுத்துகிறீர்கள்).</translation>
<translation id="2247351761944213033">வாரம் <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">செக்பாக்ஸ்</translation>
+<translation id="2335594187091864976">தேதி மற்றும் நேரம் தேர்ந்தெடுப்பான்</translation>
<translation id="248395913932153421">நாள்</translation>
<translation id="2507943997699731163">இந்தப் புலத்தை நிரப்புக.</translation>
+<translation id="2508569020611168319">தாவல் பட்டியல்</translation>
<translation id="2548326553472216322">சமீபத்திய தேடல்கள் எதுவுமில்லை</translation>
<translation id="2572483411312390101">இயக்கு</translation>
<translation id="2613802280814924224">சரியான மதிப்பை உள்ளிடவும். <ph name="VALID_VALUE" /> என்பது நெருக்கமாக உள்ள சரியான மதிப்பாகும்.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">அடிக்குறிப்பு</translation>
<translation id="2723001399770238859">ஆடியோ</translation>
<translation id="2746543609216772311">மதிப்பானது <ph name="MINIMUM_DATE_OR_TIME" /> அல்லது அதற்குப் பின்பு இருக்க வேண்டும்.</translation>
+<translation id="2759744352195237655">பாப்-அப் பொத்தான்</translation>
<translation id="2761667185364618470">தொடர விரும்பினால், இந்தப் பெட்டியைத் தேர்ந்தெடுங்கள்.</translation>
<translation id="2846343701378493991">1024 (இடைநிலைத் தரம்)</translation>
+<translation id="2896972712917208084">ரேடியோ குழு</translation>
<translation id="2901282870647571346">மூவியின் நடப்பு நிலை</translation>
<translation id="2908441821576996758">காற்புள்ளியால் பிரிக்கப்பட்ட மின்னஞ்சல் முகவரிகளின் பட்டியலை உள்ளிடுக.</translation>
+<translation id="2931838996092594335">கிளிக் செய்க</translation>
+<translation id="2940813599313844715">பொருள்</translation>
<translation id="2942448076852699108">தனிப்படுத்தப்பட்ட உள்ளடக்கம்</translation>
<translation id="3040011195152428237">இணைப்பு</translation>
<translation id="3075154866155599887">சரியான மதிப்பை உள்ளிடவும். இந்தப் புலம் முழுமையற்றதாக உள்ளது அல்லது தவறான தேதியைக் கொண்டுள்ளது.</translation>
+<translation id="3078740164268491126">அட்டவணை</translation>
+<translation id="3086746722712840547">குறிப்பு</translation>
<translation id="310520048233152454">URL ஐ உள்ளிடுக.</translation>
+<translation id="3175736971608411871">டைமர்</translation>
+<translation id="3199563858620722075">சேர்க்கைப் பெட்டி</translation>
<translation id="3450233048674729344">மதிப்பானது கண்டிப்பாக <ph name="MAXIMUM" /> ஐ விடக்குறைவாக அல்லது அதற்குச் சமமாக இருக்க வேண்டும்.</translation>
<translation id="3486220673238053218">விளக்கம்</translation>
+<translation id="3557673793733683882">தலைப்பு <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">மீதமுள்ள மூவியின் வினாடிகள்</translation>
<translation id="3706100364254443312">ஸ்விட்ச்</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">சொல்</translation>
<translation id="3822383571486410024">இந்த உரையை <ph name="MIN_CHARACTERS" /> எழுத்துக்குறிகள் அல்லது அதற்கும் அதிகமாக (தற்போது <ph name="CURRENT_LENGTH" /> எழுத்துக்குறிகளைப் பயன்படுத்துகிறீர்கள்) நீட்டிக்கவும்.</translation>
<translation id="383465348367842624">'<ph name="ATSIGN" />' ஐத் தொடர்ந்து வரும் பகுதியில் '<ph name="INVALIDCHARACTER" />' சின்னம் இருக்கக்கூடாது.</translation>
+<translation id="3924558731517983934">பயன்பாடு</translation>
+<translation id="3960700977367013758">உருட்டல் பட்டி</translation>
<translation id="4103419683916926126">மில்லிவினாடிகள்</translation>
+<translation id="4151657705144244502">கிராஃபிக்</translation>
<translation id="4201051445878709314">முந்தைய மாதத்தைக் காட்டு</translation>
<translation id="4202807286478387388">தாவு</translation>
+<translation id="421884353938374759">வண்ணத் தேர்வி</translation>
+<translation id="4248100235867064564">மெனுப் பட்டி</translation>
+<translation id="4254339807215791271">உள்ளடக்கத் தகவல்</translation>
<translation id="4360991593054037559">சரியான மதிப்பை உள்ளிடவும். <ph name="VALID_VALUE_LOW" /> மற்றும் <ph name="VALID_VALUE_HIGHER" /> ஆகியவை மிக நெருக்கமான சரியான இரண்டு மதிப்புகளாகும்.</translation>
+<translation id="4413860115965805769">மெனு பொத்தான்</translation>
<translation id="4522570452068850558">விவரங்கள்</translation>
<translation id="4597532268155981612">படிவம்</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />' ஐத் தொடரும் பகுதியில், '<ph name="INVALIDCHARACTER" />' சின்னம் இருக்கக்கூடாது.</translation>
+<translation id="4757246831282535685">தாவல் பலகம்</translation>
<translation id="4763480195061959176">வீடியோ</translation>
+<translation id="479989351350248267">Search</translation>
<translation id="4812940957355064477">எண்ணை உள்ளிடுக.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> தேர்ந்தெடுக்கப்பட்டன</translation>
<translation id="49969490063480558">'<ph name="ATSIGN" />' ஐத் தொடர்ந்து ஒரு பகுதியை உள்ளிடவும். '<ph name="INVALIDADDRESS" />' முழுமைப்பெறாமல் உள்ளது.</translation>
+<translation id="5034860022980953847">செயல்நிலை காட்டி</translation>
<translation id="5048533449481078685">பட்டியல் குறிப்பான்</translation>
<translation id="5117590920725113268">அடுத்த மாதத்தைக் காட்டு</translation>
+<translation id="512758898067543763">வரிசை மேற்தலைப்பு</translation>
<translation id="5164977714490026579">மதிப்பானது, கண்டிப்பாக <ph name="MINIMUM" /> ஐ விட அதிகமாக அல்லது அதற்குச் சமமாக இருக்க வேண்டும்.</translation>
<translation id="5307600278924710095">'<ph name="ATSIGN" />' ஐத் தொடர்ந்து ஒரு பகுதியை உள்ளிடவும். '<ph name="INVALIDADDRESS" />' முழுமைப் பெறாமல் உள்ளது.</translation>
+<translation id="5317780077021120954">சேமி</translation>
<translation id="5406322316791861025">உருவம்</translation>
+<translation id="5453733299334684579">ட்ரீ உருப்படி</translation>
<translation id="5466621249238537318">ஒன்று அல்லது அதற்குமேற்பட்ட கோப்புகளைத் தேர்ந்தெடுங்கள்.</translation>
<translation id="5468998798572797635">முழுத்திரையிலிருந்து வெளியேறு</translation>
<translation id="5476505524087279545">தேர்வு நீக்கு</translation>
+<translation id="5516424706154626233">தேதி தேர்ந்தெடுப்பான்</translation>
<translation id="5546461542133609677">ஒலி இயக்கு</translation>
+<translation id="561939826962581046">நேரம்</translation>
<translation id="5641012560118721995">மறுஇயக்கத்தை இடைநிறுத்து</translation>
+<translation id="5643186887447432888">பொத்தான்</translation>
<translation id="5843503607508392247">மற்றவை…</translation>
<translation id="5939518447894949180">மீட்டமை</translation>
<translation id="5944544982112848342">2048 (உயர் தரம்)</translation>
<translation id="5966707198760109579">வாரம்</translation>
-<translation id="598301471034819706">முகவரி</translation>
+<translation id="5987525920412732405">சுழல் பொத்தான்</translation>
<translation id="6015796118275082299">ஆண்டு</translation>
+<translation id="6023896073578205740">பட்டியல் பெட்டி</translation>
<translation id="6101327004457443354">ஆடியோ டிராக்கை இயக்கு</translation>
<translation id="6119846243427417423">செயல்படுத்து</translation>
+<translation id="6164829606128959761">மீட்டர்</translation>
<translation id="6270583010843788609">மூவி டைம்லைன் சிறுபடம்</translation>
<translation id="6359256949422175976">மூவி நேர ஸ்க்ரப்பர் சிறுபடம்</translation>
<translation id="6398862346408813489">மாதம் தேர்ந்தெடுப்புப் பலகத்தைக் காட்டு</translation>
<translation id="6404546809543547843">ஆடியோ நேர ஸ்கிரப்பர்</translation>
+<translation id="648732519525291180">நேரம் தேர்ந்தெடுப்பான்</translation>
<translation id="658823671542763450">முழுத்திரைக்குச் செல்</translation>
+<translation id="6637586476836377253">பதிவு</translation>
<translation id="6643016212128521049">அழி</translation>
<translation id="6663448176199120256">சமீபத்திய தேடல்கள்</translation>
<translation id="668171684555832681">மற்றவை…</translation>
<translation id="6692633176391053278">ஸ்டெப்பர்</translation>
+<translation id="6739588121953935928">அளவுகோல்</translation>
+<translation id="6755330956360078551">உதவிக்குறிப்பு</translation>
<translation id="6820355525329141109">செருகுநிரல் ஏற்றப்படவில்லை.</translation>
<translation id="6843725295806269523">ஒலியடக்கு</translation>
<translation id="6845533974506654842">அழுத்துக</translation>
<translation id="6853785296079745596">மூடப்பட்ட தலைப்புகளை மறை</translation>
+<translation id="6885760532393684712">கோப்பகம்</translation>
+<translation id="6934078000481955284">பிளாக்கோட்</translation>
<translation id="7057186640035488495">மூவி நேரம்</translation>
<translation id="709897737746224366">கோரிய வடிவமைப்பில் தருக.</translation>
<translation id="7223624360433298498">முடிவடைந்த நேரம்</translation>
<translation id="7263440858009898357">பட்டியலிலிருந்து ஒரு உருப்படியைத் தேர்ந்தெடுங்கள்.</translation>
+<translation id="727747134524199931">நெடுவரிசை மேற்தலைப்பு</translation>
<translation id="7364796246159120393">கோப்பைத் தேர்வு செய்க</translation>
<translation id="739024184232394898">மற்றவை…</translation>
+<translation id="7491962110804786152">tab</translation>
<translation id="7673697353781729403">மணிநேரம்</translation>
<translation id="7720026100085573005">மீதமுள்ள நேரம்</translation>
<translation id="7740016676195725605">மூடப்பட்ட தலைப்புகளைக் காட்டுவதை நிறுத்து</translation>
<translation id="7740050170769002709">HTML உள்ளடக்கம்</translation>
<translation id="7789962463072032349">இடைநிறுத்து</translation>
+<translation id="7802800022689234070">கூடுதல் உள்ளடக்க முக்கோணம்</translation>
<translation id="7888071071722539607">மின்னஞ்சல் முகவரியில் '<ph name="ATSIGN" />' ஐச் சேர்க்கவும். '<ph name="ATSIGN" />' இல் '<ph name="INVALIDADDRESS" />' இல்லை.</translation>
+<translation id="7891486169920085145">பிரிப்பான்</translation>
<translation id="795667975304826397">எந்த கோப்பும் தேர்ந்தெடுக்கப்படவில்லை</translation>
<translation id="8053789581856978548">தேடல் உரைப் புலம்</translation>
<translation id="8115662671911883373">மூடப்பட்ட தலைப்புகளைக் காட்டுவதைத் தொடங்கு</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">பட மேப்</translation>
<translation id="835897206747267392">செல்லாத மதிப்பு.</translation>
<translation id="838869780401515933">சரிபார்</translation>
+<translation id="8433900881053900389">கருவிப்பட்டி</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> கோப்புகள்</translation>
<translation id="8451268428117625855">ஒரு கோப்பை தேர்ந்தெடுக்கவும்.</translation>
+<translation id="8461852803063341183">ரேடியோ பொத்தான்</translation>
+<translation id="8511325616783751178">கீழ் தோன்றுதல் மெனு</translation>
<translation id="8534579021159131403">நிமிடங்கள்</translation>
<translation id="8541249477527128034">மீடியா கட்டுப்பாடு</translation>
<translation id="8583702881314752957">விளக்கப் பட்டியல்</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">மறுஇயக்கத்தைத் தொடங்கு</translation>
<translation id="8851136666856101339">முதன்மை</translation>
<translation id="8987927404178983737">மாதம்</translation>
+<translation id="9002566407876343676">திற</translation>
<translation id="901493112792887934">நடப்பு நேரம் வினாடிகளில்</translation>
<translation id="9048119486235211610">வழிசெலுத்தல்</translation>
<translation id="9050748414552849310">மூடப்பட்ட தலைப்புகளைக் காட்டு</translation>
+<translation id="9062295712474918030">ஆவணம்</translation>
<translation id="9108370397979208512">கணிதம்</translation>
<translation id="9132465097189459683">மற்றவை…</translation>
+<translation id="9138385573473225930">விழிப்பூட்டல்</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, <ph name="WEEK_START_DATE" /> அன்று தொடங்குவது</translation>
+<translation id="947831847158436616">கலம்</translation>
+<translation id="966787709310836684">மெனு</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_te.xtb b/chromium/content/app/strings/translations/content_strings_te.xtb
index 42506b219ff..866daee235c 100644
--- a/chromium/content/app/strings/translations/content_strings_te.xtb
+++ b/chromium/content/app/strings/translations/content_strings_te.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="te">
<translation id="1014825444426747588">ఖాళీ</translation>
+<translation id="1018939186200882850">మెను అంశం</translation>
<translation id="1020833440720551630">ఆడియో ట్రాక్‌ను మ్యూట్ చేయి</translation>
<translation id="10623998915015855">టోగుల్ బటన్</translation>
<translation id="1088086359088493902">సెకన్లు</translation>
<translation id="1171774979989969504">దయచేసి ఇమెయిల్ చిరునామాను ఎంటర్ చెయ్యండి.</translation>
<translation id="1188858454923323853">బహుమానపూర్వకం</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">స్లయిడర్</translation>
<translation id="1235745349614807883">ఇటీవల శోధనలను క్లియర్ చెయ్యి</translation>
+<translation id="1281252709823657822">డైలాగ్</translation>
<translation id="1342835525016946179">కథనం</translation>
<translation id="1359897965706325498">బ్యానర్</translation>
<translation id="1589122976691792535">ప్రాంతం</translation>
<translation id="1591562245178063882">ఈ నెల</translation>
<translation id="1637811476055996098">ఫైల్‌లను ఎంచుకోండి</translation>
+<translation id="167575180612809735">బిజీ సూచిక</translation>
<translation id="1729654308190250600">దయచేసి ఖాళీ-కాని ఇమెయిల్ చిరునామాని నమోదు చేయండి.</translation>
<translation id="1758486001363313524">ఇతర...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">వృక్షాంశ గ్రిడ్</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">రిమోట్ పరికరంలో ప్లే చేస్తుంది</translation>
<translation id="1842960171412779397">ఎంచుకోండి</translation>
+<translation id="1880518467580572141">చుట్టుగీత</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">స్థితి</translation>
<translation id="1938124657309484470">విలువ తప్పనిసరిగా <ph name="MAXIMUM_DATE_OR_TIME" /> లేదా అంతకంటే మునుపటిది అయి ఉండాలి.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">దయచేసి ఈ వచనాన్ని <ph name="MAX_CHARACTERS" /> అక్షరాలకు లేదా అంతకంటే తక్కువ (మీరు ప్రస్తుతం <ph name="CURRENT_LENGTH" /> అక్షరాలను ఉపయోగిస్తున్నారు)కు తగ్గించండి.</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />వ వారం, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">తనిఖీపెట్టె</translation>
+<translation id="2335594187091864976">తేదీ మరియు సమయం ఎంపిక</translation>
<translation id="248395913932153421">రోజు</translation>
<translation id="2507943997699731163">దయచేసి ఈ ఫీల్డ్‌ని పూర్తి చెయ్యండి.</translation>
+<translation id="2508569020611168319">ట్యాబ్ జాబితా</translation>
<translation id="2548326553472216322">ఇటీవల శోధనలు లేవు</translation>
<translation id="2572483411312390101">ప్లే చేయి</translation>
<translation id="2613802280814924224">దయచేసి చెల్లుబాటు అయ్యే విలువను నమోదు చేయండి. <ph name="VALID_VALUE" /> అనేది సమీప చెల్లుబాటు విలువ.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">ఫుటర్</translation>
<translation id="2723001399770238859">ఆడియో</translation>
<translation id="2746543609216772311">విలువ తప్పనిసరిగా <ph name="MINIMUM_DATE_OR_TIME" /> లేదా అంతకంటే తదుపరిది అయి ఉండాలి.</translation>
+<translation id="2759744352195237655">పాప్ అప్ బటన్</translation>
<translation id="2761667185364618470">దయచేసి మీరు కొనసాగాలనుకుంటే ఈ బాక్స్‌కి టిక్కు పెట్టండి.</translation>
<translation id="2846343701378493991">1024 (మధ్యస్థ గ్రేడ్)</translation>
+<translation id="2896972712917208084">రేడియో సమూహం</translation>
<translation id="2901282870647571346">ప్రస్తుతం చలనచిత్ర స్థితి</translation>
<translation id="2908441821576996758">దయచేసి కామాతో వేరు చేసిన ఇమెయిల్ చిరునామాల జాబితాను ఎంటర్ చెయ్యండి.</translation>
+<translation id="2931838996092594335">క్లిక్ చేయి</translation>
+<translation id="2940813599313844715">ఆబ్జెక్ట్</translation>
<translation id="2942448076852699108">ప్రముఖంగా చూపిన కంటెంట్</translation>
<translation id="3040011195152428237">లింక్</translation>
<translation id="3075154866155599887">దయచేసి చెల్లుబాటు అయ్యే విలువను నమోదు చేయండి. ఫీల్డ్ అసంపూర్ణంగా ఉంది లేదా చెల్లని తేదీని కలిగి ఉంది.</translation>
+<translation id="3078740164268491126">పట్టిక</translation>
+<translation id="3086746722712840547">note</translation>
<translation id="310520048233152454">దయచేసి ఒక URLని ఎంటర్ చెయ్యండి.</translation>
+<translation id="3175736971608411871">టైమర్</translation>
+<translation id="3199563858620722075">కాంబో పెట్టె</translation>
<translation id="3450233048674729344">విలువ ఖచ్చితంగా <ph name="MAXIMUM" /> కంటే తగ్గువగా లేదా సమానంగా ఉండాలి.</translation>
<translation id="3486220673238053218">నిర్వచనం</translation>
+<translation id="3557673793733683882">ముఖ్య శీర్షిక <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">చలనచిత్రంలో మిగిలి ఉన్న సెకన్లు</translation>
<translation id="3706100364254443312">మార్పు</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">పదం</translation>
<translation id="3822383571486410024">దయచేసి ఈ వచనాన్ని <ph name="MIN_CHARACTERS" /> లేదా అంతకంటే ఎక్కువ అక్షరాలకు పొడిగించండి (ప్రస్తుతం మీరు <ph name="CURRENT_LENGTH" /> అక్షరాలను ఉపయోగిస్తున్నారు).</translation>
<translation id="383465348367842624">'<ph name="ATSIGN" />'కి ముందు ఉన్న భాగంలో '<ph name="INVALIDCHARACTER" />' చిహ్నం ఉండకూడదు.</translation>
+<translation id="3924558731517983934">అనువర్తనం</translation>
+<translation id="3960700977367013758">స్క్రోల్ పట్టీ</translation>
<translation id="4103419683916926126">మిల్లీసెకన్లు</translation>
+<translation id="4151657705144244502">గ్రాఫిక్</translation>
<translation id="4201051445878709314">మునుపటి నెలను చూపుతుంది</translation>
<translation id="4202807286478387388">వెళ్ళు</translation>
+<translation id="421884353938374759">రంగు ఎంపిక</translation>
+<translation id="4248100235867064564">మెను పట్టీ</translation>
+<translation id="4254339807215791271">కంటెంట్ సమాచారం</translation>
<translation id="4360991593054037559">దయచేసి చెల్లుబాటు అయ్యే విలువను నమోదు చేయండి. <ph name="VALID_VALUE_LOW" /> మరియు <ph name="VALID_VALUE_HIGHER" /> అనేవి రెండు సమీప చెల్లుబాటు విలువలు.</translation>
+<translation id="4413860115965805769">మెను బటన్</translation>
<translation id="4522570452068850558">వివరాలు</translation>
<translation id="4597532268155981612">ఫారమ్</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">'<ph name="ATSIGN" />'కి తర్వాత ఉన్న భాగంలో '<ph name="INVALIDCHARACTER" />' చిహ్నం ఉండకూడదు.</translation>
+<translation id="4757246831282535685">ట్యాబ్ ప్యానెల్</translation>
<translation id="4763480195061959176">వీడియో</translation>
+<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">దయచేసి సంఖ్యను నమోదు చేయండి.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> ఎంచుకోబడ్డాయి</translation>
<translation id="49969490063480558">దయచేసి '<ph name="ATSIGN" />'కి తర్వాత ఉన్న భాగాన్ని నమోదు చేయండి. '<ph name="INVALIDADDRESS" />' అసంపూర్ణంగా ఉంది.</translation>
+<translation id="5034860022980953847">ప్రోగ్రెస్ సూచిక</translation>
<translation id="5048533449481078685">జాబితా మార్కర్</translation>
<translation id="5117590920725113268">తదుపరి నెలను చూపుతుంది</translation>
+<translation id="512758898067543763">అడ్డు వరుస శీర్షిక</translation>
<translation id="5164977714490026579">విలువ ఖచ్చితంగా <ph name="MINIMUM" /> కంటే ఎక్కువగా లేదా సమానంగా ఉండాలి.</translation>
<translation id="5307600278924710095">దయచేసి '<ph name="ATSIGN" />'కి ముందు ఉన్న భాగాన్ని నమోదు చేయండి. '<ph name="INVALIDADDRESS" />' అసంపూర్ణంగా ఉంది.</translation>
+<translation id="5317780077021120954">సేవ్ చేయి</translation>
<translation id="5406322316791861025">రూపం</translation>
+<translation id="5453733299334684579">వృక్షాంశం</translation>
<translation id="5466621249238537318">దయచేసి ఒకటి లేదా మరిన్ని ఫైళ్ళను ఎంచుకోండి.</translation>
<translation id="5468998798572797635">పూర్తి స్క్రీన్ నుండి నిష్క్రమించు</translation>
<translation id="5476505524087279545">ఎంపిక చెయ్యబడలేదు</translation>
+<translation id="5516424706154626233">తేదీ ఎంపిక</translation>
<translation id="5546461542133609677">అన్‌మ్యూట్ చేయి</translation>
+<translation id="561939826962581046">time</translation>
<translation id="5641012560118721995">ప్లేబ్యాక్‌ను పాజ్ చేయి</translation>
+<translation id="5643186887447432888">బటన్</translation>
<translation id="5843503607508392247">ఇతర...</translation>
<translation id="5939518447894949180">రీసెట్ చేయి</translation>
<translation id="5944544982112848342">2048 (ఉత్తమ గ్రేడ్)</translation>
<translation id="5966707198760109579">వారం</translation>
-<translation id="598301471034819706">చిరునామా</translation>
+<translation id="5987525920412732405">స్పిన్ బటన్</translation>
<translation id="6015796118275082299">సంవత్సరం</translation>
+<translation id="6023896073578205740">జాబితా పెట్టె</translation>
<translation id="6101327004457443354">ఆడియో ట్రాక్‌ను అన్‌మ్యూట్ చేయి</translation>
<translation id="6119846243427417423">ఆక్టివేట్ చెయ్యి</translation>
+<translation id="6164829606128959761">మీటర్</translation>
<translation id="6270583010843788609">చలనచిత్ర టైమ్‌లైన్ సూక్ష్మచిత్రం</translation>
<translation id="6359256949422175976">చలనచిత్ర సమయ స్క్రబ్బర్ సూక్ష్మచిత్రం</translation>
<translation id="6398862346408813489">నెల ఎంపిక ప్యానెల్‌ను చూపుతుంది</translation>
<translation id="6404546809543547843">ఆడియో సమయ స్క్రబ్బర్</translation>
+<translation id="648732519525291180">సమయం ఎంపిక</translation>
<translation id="658823671542763450">పూర్తి స్క్రీన్‌లోకి ప్రవేశించు</translation>
+<translation id="6637586476836377253">log</translation>
<translation id="6643016212128521049">క్లియర్ చేయి</translation>
<translation id="6663448176199120256">ఇటీవల శోధనలు</translation>
<translation id="668171684555832681">ఇతర...</translation>
<translation id="6692633176391053278">స్టెప్పర్</translation>
+<translation id="6739588121953935928">రూలర్</translation>
+<translation id="6755330956360078551">సాధన చిట్కా</translation>
<translation id="6820355525329141109">ప్లగిన్‌ను లోడ్ చేయడం సాధ్యపడలేదు.</translation>
<translation id="6843725295806269523">మ్యూట్ చేయి</translation>
<translation id="6845533974506654842">నొక్కండి</translation>
<translation id="6853785296079745596">సంవృత శీర్షికలను దాచు</translation>
+<translation id="6885760532393684712">డైరెక్టరీ</translation>
+<translation id="6934078000481955284">బ్లాక్‌కోట్</translation>
<translation id="7057186640035488495">చలనచిత్ర నిడివి</translation>
<translation id="709897737746224366">దయచేసి అభ్యర్థించిన ఆకృతీకరణను సరిపోల్చండి.</translation>
<translation id="7223624360433298498">గడిచిన సమయం</translation>
<translation id="7263440858009898357">దయచేసి జాబితాలోని ఒక అంశాన్ని ఎంచుకోండి.</translation>
+<translation id="727747134524199931">నిలువు వరుస శీర్షిక</translation>
<translation id="7364796246159120393">ఫైల్‌ను ఎంచుకోండి</translation>
<translation id="739024184232394898">ఇతర...</translation>
+<translation id="7491962110804786152">tab</translation>
<translation id="7673697353781729403">గంటలు</translation>
<translation id="7720026100085573005">మిగిలి ఉన్న సమయం</translation>
<translation id="7740016676195725605">సంవృత శీర్షికలను ప్రదర్శించడం ఆపివేయి</translation>
<translation id="7740050170769002709">HTML కంటెంట్</translation>
<translation id="7789962463072032349">నిలిపివేయి</translation>
+<translation id="7802800022689234070">కంటెంట్‌ను విస్తరింపజేసే లేదా కుదించే త్రిభుజం</translation>
<translation id="7888071071722539607">దయచేసి ఇమెయిల్ చిరునామాలో '<ph name="ATSIGN" />'ని చేర్చండి. '<ph name="INVALIDADDRESS" />'లో '<ph name="ATSIGN" />' లేదు.</translation>
+<translation id="7891486169920085145">విభజన</translation>
<translation id="795667975304826397">ఫైల్ ఏదీ ఎంచుకోలేదు</translation>
<translation id="8053789581856978548">శోధన వచనం ఫీల్డ్</translation>
<translation id="8115662671911883373">సంవృత శీర్షికలను ప్రదర్శించడం ప్రారంభించు</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">చిత్రం మ్యాప్‌</translation>
<translation id="835897206747267392">చెల్లని విలువ.</translation>
<translation id="838869780401515933">తనిఖీ చెయ్యి</translation>
+<translation id="8433900881053900389">సాధన పట్టీ</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ఫైళ్ళు</translation>
<translation id="8451268428117625855">దయచేసి ఒక ఫైల్‌ని ఎంచుకోండి.</translation>
+<translation id="8461852803063341183">రేడియో బటన్</translation>
+<translation id="8511325616783751178">డ్రాప్ డౌన్ బటన్</translation>
<translation id="8534579021159131403">నిమిషాలు</translation>
<translation id="8541249477527128034">మీడియా నియంత్రణ</translation>
<translation id="8583702881314752957">నిర్వచన జాబితా</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">ప్లేబ్యాక్‌ను ప్రారంభించు</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8987927404178983737">నెల</translation>
+<translation id="9002566407876343676">తెరువు</translation>
<translation id="901493112792887934">సెకన్లలో ప్రస్తుత సమయం</translation>
<translation id="9048119486235211610">నావిగేషన్</translation>
<translation id="9050748414552849310">సంవృత శీర్షికలను చూపు</translation>
+<translation id="9062295712474918030">పత్రం</translation>
<translation id="9108370397979208512">math</translation>
<translation id="9132465097189459683">ఇతర...</translation>
+<translation id="9138385573473225930">హెచ్చరిక</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, <ph name="WEEK_START_DATE" /> నుండి ప్రారంభమవుతుంది</translation>
+<translation id="947831847158436616">గడి</translation>
+<translation id="966787709310836684">మెను</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_th.xtb b/chromium/content/app/strings/translations/content_strings_th.xtb
index 946408959c6..34dedd0e0a4 100644
--- a/chromium/content/app/strings/translations/content_strings_th.xtb
+++ b/chromium/content/app/strings/translations/content_strings_th.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="th">
<translation id="1014825444426747588">ว่าง</translation>
+<translation id="1018939186200882850">รายการเมนู</translation>
<translation id="1020833440720551630">ปิดไฟล์เสียง</translation>
<translation id="10623998915015855">ปุ่มสลับ</translation>
<translation id="1088086359088493902">วินาที</translation>
<translation id="1171774979989969504">โปรดป้อนที่อยู่อีเมล</translation>
<translation id="1188858454923323853">ส่วนเสริม</translation>
+<translation id="1206619573307042055">ตัวอักษรวิ่ง</translation>
+<translation id="1206693055195146388">แถบเลื่อน</translation>
<translation id="1235745349614807883">ลบการค้นหาล่าสุด</translation>
+<translation id="1281252709823657822">กล่องโต้ตอบ</translation>
<translation id="1342835525016946179">บทความ</translation>
<translation id="1359897965706325498">แบนเนอร์</translation>
<translation id="1589122976691792535">ภูมิภาค</translation>
<translation id="1591562245178063882">เดือนนี้</translation>
<translation id="1637811476055996098">เลือกไฟล์</translation>
+<translation id="167575180612809735">สัญญาณบอกสถานะไม่ว่าง</translation>
<translation id="1729654308190250600">โปรดป้อนที่อยู่อีเมลที่ไม่ว่างเปล่า</translation>
<translation id="1758486001363313524">อื่นๆ...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">แผนผังต้นไม้</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">เล่นในอุปกรณ์ระยะไกล</translation>
<translation id="1842960171412779397">เลือก</translation>
+<translation id="1880518467580572141">เค้าโครง</translation>
<translation id="1921819250265091946">วว</translation>
<translation id="1930711995431081526">สถานะ</translation>
<translation id="1938124657309484470">ค่าต้องเป็น <ph name="MAXIMUM_DATE_OR_TIME" /> หรือก่อนหน้านั้น</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">โปรดย่อข้อความนี้ให้เหลือไม่เกิน <ph name="MAX_CHARACTERS" /> อักขระ (ขณะนี้ข้อความของคุณมี <ph name="CURRENT_LENGTH" /> อักขระ)</translation>
<translation id="2247351761944213033">สัปดาห์ที่ <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">ช่องทำเครื่องหมาย</translation>
+<translation id="2335594187091864976">เครื่องมือเลือกวันที่และเวลา</translation>
<translation id="248395913932153421">วัน</translation>
<translation id="2507943997699731163">โปรดกรอกฟิลด์นี้</translation>
+<translation id="2508569020611168319">รายการแท็บ</translation>
<translation id="2548326553472216322">ไม่พบการค้นหาล่าสุด</translation>
<translation id="2572483411312390101">เล่น</translation>
<translation id="2613802280814924224">โปรดป้อนค่าที่ถูกต้อง ค่าใกล้เคียงที่สุดที่ถูกต้องคือ <ph name="VALID_VALUE" /></translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">ส่วนท้าย</translation>
<translation id="2723001399770238859">เสียง</translation>
<translation id="2746543609216772311">ค่าต้องเป็น <ph name="MINIMUM_DATE_OR_TIME" /> หรือหลังจากนั้น</translation>
+<translation id="2759744352195237655">ปุ่มป๊อปอัป</translation>
<translation id="2761667185364618470">โปรดเลือกช่องนี้หากคุณต้องการดำเนินการต่อ</translation>
<translation id="2846343701378493991">1024 (เกรดปานกลาง)</translation>
+<translation id="2896972712917208084">กลุ่มตัวเลือก</translation>
<translation id="2901282870647571346">สถานะปัจจุบันของภาพยนตร์</translation>
<translation id="2908441821576996758">โปรดป้อนรายการที่อยู่อีเมลโดยคั่นด้วยเครื่องหมายจุลภาค</translation>
+<translation id="2931838996092594335">คลิก</translation>
+<translation id="2940813599313844715">ออบเจ็กต์</translation>
<translation id="2942448076852699108">เนื้อหาที่ไฮไลต์</translation>
<translation id="3040011195152428237">ลิงก์</translation>
<translation id="3075154866155599887">โปรดป้อนค่าที่ถูกต้อง ฟิลด์นี้ไม่สมบูรณ์หรือมีวันที่ที่ไม่ถูกต้อง</translation>
+<translation id="3078740164268491126">ตาราง</translation>
+<translation id="3086746722712840547">หมายเหตุ</translation>
<translation id="310520048233152454">โปรดป้อน URL</translation>
+<translation id="3175736971608411871">ตัวจับเวลา</translation>
+<translation id="3199563858620722075">ช่องตัวเลือกรวม</translation>
<translation id="3450233048674729344">ค่าต้องน้อยกว่าหรือเท่ากับ <ph name="MAXIMUM" /></translation>
<translation id="3486220673238053218">คำจำกัดความ</translation>
+<translation id="3557673793733683882">ส่วนหัว <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">จำนวนวินาทีที่เหลือของภาพยนตร์</translation>
<translation id="3706100364254443312">สวิตช์</translation>
<translation id="3732799496749320381">ดด</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">คำหลัก</translation>
<translation id="3822383571486410024">โปรดกรอกข้อความนี้ให้มีอักขระอย่างน้อย <ph name="MIN_CHARACTERS" /> ตัว (ตอนนี้คุณมี <ph name="CURRENT_LENGTH" /> ตัว)</translation>
<translation id="383465348367842624">ส่วนที่ตามด้วย "<ph name="ATSIGN" />" ต้องไม่มีสัญลักษณ์ "<ph name="INVALIDCHARACTER" />"</translation>
+<translation id="3924558731517983934">แอปพลิเคชัน</translation>
+<translation id="3960700977367013758">แถบเลื่อน</translation>
<translation id="4103419683916926126">มิลลิวินาที</translation>
+<translation id="4151657705144244502">กราฟิก</translation>
<translation id="4201051445878709314">แสดงเดือนที่ผ่านมา</translation>
<translation id="4202807286478387388">ข้าม</translation>
+<translation id="421884353938374759">ตัวเลือกสี</translation>
+<translation id="4248100235867064564">แถบเมนู</translation>
+<translation id="4254339807215791271">ข้อมูลเนื้อหา</translation>
<translation id="4360991593054037559">โปรดป้อนค่าที่ถูกต้อง ค่าใกล้เคียงที่สุดที่ถูกต้องสองรายการคือ <ph name="VALID_VALUE_LOW" /> และ <ph name="VALID_VALUE_HIGHER" /></translation>
+<translation id="4413860115965805769">ปุ่มเมนู</translation>
<translation id="4522570452068850558">รายละเอียด</translation>
<translation id="4597532268155981612">ฟอร์ม</translation>
+<translation id="4661075872484491155">แผนผัง</translation>
<translation id="4664250907885839816">ส่วนที่ต่อท้าย "<ph name="ATSIGN" />" ต้องไม่มีสัญลักษณ์ "<ph name="INVALIDCHARACTER" />"</translation>
+<translation id="4757246831282535685">แผงแท็บ</translation>
<translation id="4763480195061959176">วิดีโอ</translation>
+<translation id="479989351350248267">ค้นหา</translation>
<translation id="4812940957355064477">โปรดป้อนตัวเลข</translation>
<translation id="4975562563186953947">เลือกไว้ <ph name="SELECTED_COUNT" /> รายการ</translation>
<translation id="49969490063480558">โปรดป้อนส่วนที่ต่อท้าย "<ph name="ATSIGN" />" "<ph name="INVALIDADDRESS" />" นั้นไม่สมบูรณ์</translation>
+<translation id="5034860022980953847">ตัวบอกสถานะความคืบหน้า</translation>
<translation id="5048533449481078685">ผู้สร้างรายการ</translation>
<translation id="5117590920725113268">แสดงเดือนถัดไป</translation>
+<translation id="512758898067543763">ส่วนหัวของแถว</translation>
<translation id="5164977714490026579">ค่าต้องมากกว่าหรือเท่ากับ <ph name="MINIMUM" /></translation>
<translation id="5307600278924710095">โปรดป้อนส่วนหนึ่งโดยตามด้วย "<ph name="ATSIGN" />" "<ph name="INVALIDADDRESS" />" นั้นไม่สมบูรณ์</translation>
+<translation id="5317780077021120954">บันทึก</translation>
<translation id="5406322316791861025">ตัวเลข</translation>
+<translation id="5453733299334684579">รายการแบบต้นไม้</translation>
<translation id="5466621249238537318">โปรดเลือกอย่างน้อยหนึ่งไฟล์</translation>
<translation id="5468998798572797635">ออกจากการแสดงแบบเต็มหน้าจอ</translation>
<translation id="5476505524087279545">ยกเลิกการทำเครื่องหมาย</translation>
+<translation id="5516424706154626233">เครื่องมือเลือกวันที่</translation>
<translation id="5546461542133609677">เปิดเสียง</translation>
+<translation id="561939826962581046">เวลา</translation>
<translation id="5641012560118721995">หยุดเล่นชั่วคราว</translation>
+<translation id="5643186887447432888">ปุ่ม</translation>
<translation id="5843503607508392247">อื่นๆ...</translation>
<translation id="5939518447894949180">รีเซ็ต</translation>
<translation id="5944544982112848342">2048 (เกรดสูง)</translation>
<translation id="5966707198760109579">สัปดาห์</translation>
-<translation id="598301471034819706">ที่อยู่</translation>
+<translation id="5987525920412732405">ปุ่มหมุน</translation>
<translation id="6015796118275082299">ปี</translation>
+<translation id="6023896073578205740">ช่องรายการ</translation>
<translation id="6101327004457443354">เปิดไฟล์เสียง</translation>
<translation id="6119846243427417423">เปิดใช้งาน</translation>
+<translation id="6164829606128959761">เมตร</translation>
<translation id="6270583010843788609">เส้นเวลาขนาดย่อของภาพยนตร์</translation>
<translation id="6359256949422175976">ตัวควบคุมเวลาขนาดย่อของภาพยนตร์</translation>
<translation id="6398862346408813489">แสดงแผงการเลือกเดือน</translation>
<translation id="6404546809543547843">ตัวควบคุมเวลาของเสียง</translation>
+<translation id="648732519525291180">เครื่องมือเลือกเวลา</translation>
<translation id="658823671542763450">เข้าสู่โหมดเต็มหน้าจอ</translation>
+<translation id="6637586476836377253">บันทึก</translation>
<translation id="6643016212128521049">ล้าง</translation>
<translation id="6663448176199120256">การค้นหาล่าสุด</translation>
<translation id="668171684555832681">อื่นๆ...</translation>
<translation id="6692633176391053278">ตัวเพิ่ม/ลดระดับเสียง</translation>
+<translation id="6739588121953935928">ไม้บรรทัด</translation>
+<translation id="6755330956360078551">เคล็ดลับเครื่องมือ</translation>
<translation id="6820355525329141109">ไม่สามารถโหลดปลั๊กอิน</translation>
<translation id="6843725295806269523">ปิดเสียง</translation>
<translation id="6845533974506654842">กด</translation>
<translation id="6853785296079745596">ซ่อนคำอธิบายภาพ</translation>
+<translation id="6885760532393684712">ไดเรกทอรี</translation>
+<translation id="6934078000481955284">ข้อความที่ยกมา</translation>
<translation id="7057186640035488495">เวลาของภาพยนตร์</translation>
<translation id="709897737746224366">โปรดจับคู่รูปแบบที่ร้องขอ</translation>
<translation id="7223624360433298498">เวลาที่ผ่านไป</translation>
<translation id="7263440858009898357">โปรดเลือกรายการจากหน้ารายการ</translation>
+<translation id="727747134524199931">ส่วนหัวคอลัมน์</translation>
<translation id="7364796246159120393">เลือกไฟล์</translation>
<translation id="739024184232394898">อื่นๆ...</translation>
+<translation id="7491962110804786152">แท็บ</translation>
<translation id="7673697353781729403">ชั่วโมง</translation>
<translation id="7720026100085573005">เวลาที่เหลือ</translation>
<translation id="7740016676195725605">หยุดแสดงคำอธิบายภาพ</translation>
<translation id="7740050170769002709">เนื้อหา HTML</translation>
<translation id="7789962463072032349">หยุดชั่วคราว</translation>
+<translation id="7802800022689234070">สามเหลี่ยมซ่อนเนื้อหา</translation>
<translation id="7888071071722539607">โปรดใส่ "<ph name="ATSIGN" />" ในที่อยู่อีเมล "<ph name="INVALIDADDRESS" />" ขาด "<ph name="ATSIGN" />"</translation>
+<translation id="7891486169920085145">ตัวแยก</translation>
<translation id="795667975304826397">ไม่ได้เลือกไฟล์ใด</translation>
<translation id="8053789581856978548">ช่องข้อความค้นหา</translation>
<translation id="8115662671911883373">เริ่มแสดงคำอธิบายภาพ</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">แผนที่รูปภาพ</translation>
<translation id="835897206747267392">ค่าไม่ถูกต้อง</translation>
<translation id="838869780401515933">ทำเครื่องหมาย</translation>
+<translation id="8433900881053900389">แถบเครื่องมือ</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> ไฟล์</translation>
<translation id="8451268428117625855">โปรดเลือกไฟล์</translation>
+<translation id="8461852803063341183">ปุ่มตัวเลือก</translation>
+<translation id="8511325616783751178">ปุ่มแบบเลื่อนลง</translation>
<translation id="8534579021159131403">นาที</translation>
<translation id="8541249477527128034">การควบคุมสื่อ</translation>
<translation id="8583702881314752957">รายการคำจำกัดความ</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">เริ่มเล่น</translation>
<translation id="8851136666856101339">หลัก</translation>
<translation id="8987927404178983737">เดือน</translation>
+<translation id="9002566407876343676">เปิด</translation>
<translation id="901493112792887934">เวลาปัจจุบันเป็นวินาที</translation>
<translation id="9048119486235211610">การนำทาง</translation>
<translation id="9050748414552849310">แสดงคำอธิบายภาพ</translation>
+<translation id="9062295712474918030">เอกสาร</translation>
<translation id="9108370397979208512">คณิตศาสตร์</translation>
<translation id="9132465097189459683">อื่นๆ...</translation>
+<translation id="9138385573473225930">การแจ้งเตือน</translation>
<translation id="9155987714137265666"><ph name="WEEK" /> เริ่มวันที่ <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">เซลล์</translation>
+<translation id="966787709310836684">เมนู</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_tr.xtb b/chromium/content/app/strings/translations/content_strings_tr.xtb
index 2294a5e03d0..0c255c34bb0 100644
--- a/chromium/content/app/strings/translations/content_strings_tr.xtb
+++ b/chromium/content/app/strings/translations/content_strings_tr.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="tr">
<translation id="1014825444426747588">boş</translation>
+<translation id="1018939186200882850">menü öğesi</translation>
<translation id="1020833440720551630">ses kanalını kapat</translation>
<translation id="10623998915015855">geçiş düğmesi</translation>
<translation id="1088086359088493902">Saniye</translation>
<translation id="1171774979989969504">Lütfen e-posta adresi girin.</translation>
<translation id="1188858454923323853">tamamlayıcı</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">kaydırma çubuğu</translation>
<translation id="1235745349614807883">Son Aramaları Temizle</translation>
+<translation id="1281252709823657822">iletişim kutusu</translation>
<translation id="1342835525016946179">article</translation>
<translation id="1359897965706325498">banner</translation>
<translation id="1589122976691792535">bölge</translation>
<translation id="1591562245178063882">Bu ay</translation>
<translation id="1637811476055996098">Dosyaları Seç</translation>
+<translation id="167575180612809735">meşgul göstergesi</translation>
<translation id="1729654308190250600">Lütfen e-posta adresini boş bırakmayın.</translation>
<translation id="1758486001363313524">Diğer...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">ağaç tablo</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">uzaktan cihazda oynat</translation>
<translation id="1842960171412779397">seç</translation>
+<translation id="1880518467580572141">özet</translation>
<translation id="1921819250265091946">gg</translation>
<translation id="1930711995431081526">durum</translation>
<translation id="1938124657309484470">Değer <ph name="MAXIMUM_DATE_OR_TIME" /> veya daha geri olmalıdır.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Lütfen bu metni <ph name="MAX_CHARACTERS" /> veya daha az karakter olacak şekilde kısaltın (şu anda <ph name="CURRENT_LENGTH" /> karakter kullanıyorsunuz).</translation>
<translation id="2247351761944213033"><ph name="WEEKNUMBER" />. hafta, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">onay kutusu</translation>
+<translation id="2335594187091864976">tarih ve saat seçici</translation>
<translation id="248395913932153421">Gün</translation>
<translation id="2507943997699731163">Lütfen bu alanı doldurun.</translation>
+<translation id="2508569020611168319">sekme listesi</translation>
<translation id="2548326553472216322">Yeni arama yok</translation>
<translation id="2572483411312390101">oynat</translation>
<translation id="2613802280814924224">Lütfen geçerli bir değer girin. En yakın geçerli değer şudur: <ph name="VALID_VALUE" /></translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">altbilgi</translation>
<translation id="2723001399770238859">ses</translation>
<translation id="2746543609216772311">Değer <ph name="MINIMUM_DATE_OR_TIME" /> veya daha ileri olmalıdır.</translation>
+<translation id="2759744352195237655">pop-up düğmesi</translation>
<translation id="2761667185364618470">İlerlemek istiyorsanız lütfen bu kutuyu işaretleyin.</translation>
<translation id="2846343701378493991">1024 (Orta Düzey)</translation>
+<translation id="2896972712917208084">radyo düğmesi grubu</translation>
<translation id="2901282870647571346">filmin geçerli durumu</translation>
<translation id="2908441821576996758">Lütfen e-posta adreslerinin virgülle ayrılmış listesini girin.</translation>
+<translation id="2931838996092594335">tıklama</translation>
+<translation id="2940813599313844715">nesne</translation>
<translation id="2942448076852699108">vurgulanan içerik</translation>
<translation id="3040011195152428237">bağlantı</translation>
<translation id="3075154866155599887">Lütfen geçerli bir tarih girin. Alan tam doldurulmamış veya geçersiz bir tarih var.</translation>
+<translation id="3078740164268491126">tablo</translation>
+<translation id="3086746722712840547">note</translation>
<translation id="310520048233152454">Lütfen bir URL girin.</translation>
+<translation id="3175736971608411871">zamanlayıcı</translation>
+<translation id="3199563858620722075">birleşik kutu</translation>
<translation id="3450233048674729344">Değer <ph name="MAXIMUM" /> veya daha küçük olmalıdır.</translation>
<translation id="3486220673238053218">tanım</translation>
+<translation id="3557673793733683882">başlık <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">saniye olarak filmin kalan süresi</translation>
<translation id="3706100364254443312">anahtar</translation>
<translation id="3732799496749320381">aa</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">terim</translation>
<translation id="3822383571486410024">Lütfen bu metni <ph name="MIN_CHARACTERS" /> karakter veya daha fazla olacak şekilde uzatın (şu anda <ph name="CURRENT_LENGTH" /> karakter kullanıyorsunuz).</translation>
<translation id="383465348367842624">Başında "<ph name="ATSIGN" />" bulunan kısımda "<ph name="INVALIDCHARACTER" />" simgesi bulunmamalıdır.</translation>
+<translation id="3924558731517983934">uygulama</translation>
+<translation id="3960700977367013758">kaydırma çubuğu</translation>
<translation id="4103419683916926126">Milisaniye</translation>
+<translation id="4151657705144244502">grafik</translation>
<translation id="4201051445878709314">Önceki ayı göster</translation>
<translation id="4202807286478387388">git</translation>
+<translation id="421884353938374759">renk seçici</translation>
+<translation id="4248100235867064564">menü çubuğu</translation>
+<translation id="4254339807215791271">içerik bilgileri</translation>
<translation id="4360991593054037559">Lütfen geçerli bir değer girin. En yakın iki geçerli değer şunlardır: <ph name="VALID_VALUE_LOW" /> ve <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">menü düğmesi</translation>
<translation id="4522570452068850558">Ayrıntılar</translation>
<translation id="4597532268155981612">form</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">Başında "<ph name="ATSIGN" />" bulunan kısımda "<ph name="INVALIDCHARACTER" />" simgesi bulunmamalıdır.</translation>
+<translation id="4757246831282535685">sekme paneli</translation>
<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">ara</translation>
<translation id="4812940957355064477">Lütfen bir sayı girin.</translation>
<translation id="4975562563186953947"><ph name="SELECTED_COUNT" /> tane seçildi</translation>
<translation id="49969490063480558">Lütfen başına "<ph name="ATSIGN" />" ekleyin. "<ph name="INVALIDADDRESS" />" eksik.</translation>
+<translation id="5034860022980953847">ilerleme durumu göstergesi</translation>
<translation id="5048533449481078685">liste işaretçisi</translation>
<translation id="5117590920725113268">Sonraki ayı göster</translation>
+<translation id="512758898067543763">satır başlığı</translation>
<translation id="5164977714490026579">Değer <ph name="MINIMUM" /> veya daha büyük olmalıdır.</translation>
<translation id="5307600278924710095">Lütfen başına "<ph name="ATSIGN" />" ekleyin. "<ph name="INVALIDADDRESS" />" adresi eksik.</translation>
+<translation id="5317780077021120954">Kaydet</translation>
<translation id="5406322316791861025">figür</translation>
+<translation id="5453733299334684579">ağaç öğesi</translation>
<translation id="5466621249238537318">Lütfen bir veya daha fazla dosya seçin.</translation>
<translation id="5468998798572797635">tam ekrandan çık</translation>
<translation id="5476505524087279545">işareti kaldır</translation>
+<translation id="5516424706154626233">tarih seçici</translation>
<translation id="5546461542133609677">sesi aç</translation>
+<translation id="561939826962581046">time</translation>
<translation id="5641012560118721995">oynatmayı duraklat</translation>
+<translation id="5643186887447432888">düğme</translation>
<translation id="5843503607508392247">Diğer...</translation>
<translation id="5939518447894949180">Sıfırla</translation>
<translation id="5944544982112848342">2048 (Yüksek Düzey)</translation>
<translation id="5966707198760109579">Hafta</translation>
-<translation id="598301471034819706">adres 1</translation>
+<translation id="5987525920412732405">dönme düğmesi</translation>
<translation id="6015796118275082299">Yıl</translation>
+<translation id="6023896073578205740">liste kutusu</translation>
<translation id="6101327004457443354">ses kanalını aç</translation>
<translation id="6119846243427417423">etkinleştir</translation>
+<translation id="6164829606128959761">ölçüm aracı</translation>
<translation id="6270583010843788609">film zaman çizelgesi küçük resmi</translation>
<translation id="6359256949422175976">film süresi göstergesinin küçük resmi</translation>
<translation id="6398862346408813489">Ay seçim panelini göster</translation>
<translation id="6404546809543547843">ses zaman çizelgesi temizleyici</translation>
+<translation id="648732519525291180">zaman seçici</translation>
<translation id="658823671542763450">tam ekrana geç</translation>
+<translation id="6637586476836377253">log</translation>
<translation id="6643016212128521049">Temizle</translation>
<translation id="6663448176199120256">Son Aramalar</translation>
<translation id="668171684555832681">Diğer...</translation>
<translation id="6692633176391053278">stepper (adımlayıcı)</translation>
+<translation id="6739588121953935928">cetvel</translation>
+<translation id="6755330956360078551">ipucu</translation>
<translation id="6820355525329141109">Eklenti yüklenemedi.</translation>
<translation id="6843725295806269523">sesi kapat</translation>
<translation id="6845533974506654842">bas</translation>
<translation id="6853785296079745596">alt yazıları gizle</translation>
+<translation id="6885760532393684712">dizin</translation>
+<translation id="6934078000481955284">blok alıntı</translation>
<translation id="7057186640035488495">filmin süresi</translation>
<translation id="709897737746224366">Lütfen istenen biçimi eşleştirin.</translation>
<translation id="7223624360433298498">geçen süre</translation>
<translation id="7263440858009898357">Lütfen listeden bir öğe seçin.</translation>
+<translation id="727747134524199931">sütun başlığı</translation>
<translation id="7364796246159120393">Dosya Seç</translation>
<translation id="739024184232394898">Diğer...</translation>
+<translation id="7491962110804786152">tab</translation>
<translation id="7673697353781729403">Saat</translation>
<translation id="7720026100085573005">kalan süre</translation>
<translation id="7740016676195725605">altyazıların görüntülenmesini durdur</translation>
<translation id="7740050170769002709">HTML içeriği</translation>
<translation id="7789962463072032349">duraklat</translation>
+<translation id="7802800022689234070">açıklama üçgeni</translation>
<translation id="7888071071722539607">Lütfen e-posta adresine bir "<ph name="ATSIGN" />" işareti ekleyin. "<ph name="INVALIDADDRESS" />" adresinde "<ph name="ATSIGN" />" eksik.</translation>
+<translation id="7891486169920085145">ayırıcı</translation>
<translation id="795667975304826397">Dosya seçilmedi</translation>
<translation id="8053789581856978548">arama metni alanı</translation>
<translation id="8115662671911883373">altyazıları görüntülemeye başla</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">resim haritası</translation>
<translation id="835897206747267392">Geçersiz değer.</translation>
<translation id="838869780401515933">işaretle</translation>
+<translation id="8433900881053900389">araç çubuğu</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> dosya</translation>
<translation id="8451268428117625855">Lütfen bir dosya seçin.</translation>
+<translation id="8461852803063341183">radyo düğmesi</translation>
+<translation id="8511325616783751178">açılır liste düğmesi</translation>
<translation id="8534579021159131403">Dakika</translation>
<translation id="8541249477527128034">medya kontrolü</translation>
<translation id="8583702881314752957">tanım listesi</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">oynatmayı başlat</translation>
<translation id="8851136666856101339">main</translation>
<translation id="8987927404178983737">Ay</translation>
+<translation id="9002566407876343676">açma</translation>
<translation id="901493112792887934">saniye olarak geçerli süre</translation>
<translation id="9048119486235211610">gezinme</translation>
<translation id="9050748414552849310">alt yazıları göster</translation>
+<translation id="9062295712474918030">doküman</translation>
<translation id="9108370397979208512">math</translation>
<translation id="9132465097189459683">Diğer...</translation>
+<translation id="9138385573473225930">uyarı</translation>
<translation id="9155987714137265666"><ph name="WEEK_START_DATE" /> tarihinde başlayan <ph name="WEEK" /></translation>
+<translation id="947831847158436616">hücre</translation>
+<translation id="966787709310836684">menü</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_uk.xtb b/chromium/content/app/strings/translations/content_strings_uk.xtb
index 2de2adf0962..31e5c5b30db 100644
--- a/chromium/content/app/strings/translations/content_strings_uk.xtb
+++ b/chromium/content/app/strings/translations/content_strings_uk.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="uk">
<translation id="1014825444426747588">порожнє</translation>
+<translation id="1018939186200882850">пункт меню</translation>
<translation id="1020833440720551630">вимкнути звукову доріжку</translation>
<translation id="10623998915015855">перемикач</translation>
<translation id="1088086359088493902">Секунди</translation>
<translation id="1171774979989969504">Введіть електронну адресу.</translation>
<translation id="1188858454923323853">додатково</translation>
+<translation id="1206619573307042055">область виділення</translation>
+<translation id="1206693055195146388">повзунок</translation>
<translation id="1235745349614807883">Очистити останні пошуки</translation>
+<translation id="1281252709823657822">діалогове вікно</translation>
<translation id="1342835525016946179">стаття</translation>
<translation id="1359897965706325498">банер</translation>
<translation id="1589122976691792535">регіон</translation>
<translation id="1591562245178063882">Цей місяць</translation>
<translation id="1637811476055996098">Вибрати файли</translation>
+<translation id="167575180612809735">індикатор зайнятості</translation>
<translation id="1729654308190250600">Введіть електронну адресу.</translation>
<translation id="1758486001363313524">Інші...</translation>
+<translation id="1806710327868736751">вікно сповіщення</translation>
+<translation id="1821985195704844674">сітка дерева</translation>
<translation id="1822429046913737220">д.п./п.п.</translation>
<translation id="1832974991323546415">відтворити на віддаленому пристрої</translation>
<translation id="1842960171412779397">вибрати</translation>
+<translation id="1880518467580572141">структура</translation>
<translation id="1921819250265091946">дд</translation>
<translation id="1930711995431081526">статус</translation>
<translation id="1938124657309484470">Має бути <ph name="MAXIMUM_DATE_OR_TIME" /> або раніша дата.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Скоротіть текст до такої кількості символів або менше: <ph name="MAX_CHARACTERS" /> (наразі використано символів: <ph name="CURRENT_LENGTH" />).</translation>
<translation id="2247351761944213033">Тиждень <ph name="WEEKNUMBER" />, <ph name="YEAR" /> р.</translation>
<translation id="2291999235780842123">прапорець</translation>
+<translation id="2335594187091864976">засіб вибору дати й часу</translation>
<translation id="248395913932153421">День</translation>
<translation id="2507943997699731163">Заповніть це поле.</translation>
+<translation id="2508569020611168319">cписок вкладок</translation>
<translation id="2548326553472216322">Немає останніх пошуків</translation>
<translation id="2572483411312390101">відтворити</translation>
<translation id="2613802280814924224">Введіть дійсне значення. Найближче дійсне значення: <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">нижній колонтитул</translation>
<translation id="2723001399770238859">аудіо</translation>
<translation id="2746543609216772311">Має бути <ph name="MINIMUM_DATE_OR_TIME" /> або пізніша дата.</translation>
+<translation id="2759744352195237655">кнопка спливаючої підказки</translation>
<translation id="2761667185364618470">Поставте тут прапорець, якщо хочете продовжити.</translation>
<translation id="2846343701378493991">1024 (Середній рівень)</translation>
+<translation id="2896972712917208084">група перемикачів</translation>
<translation id="2901282870647571346">поточний статус фільму</translation>
<translation id="2908441821576996758">Введіть список електронних адрес, розділених комою.</translation>
+<translation id="2931838996092594335">натиснути</translation>
+<translation id="2940813599313844715">об’єкт</translation>
<translation id="2942448076852699108">виділений вміст</translation>
<translation id="3040011195152428237">посилання</translation>
<translation id="3075154866155599887">Введіть дійсне значення. Поле не заповнено або введено недійсну дату.</translation>
+<translation id="3078740164268491126">таблиця</translation>
+<translation id="3086746722712840547">примітка</translation>
<translation id="310520048233152454">Введіть URL-адресу.</translation>
+<translation id="3175736971608411871">таймер</translation>
+<translation id="3199563858620722075">поле зі списком</translation>
<translation id="3450233048674729344">Значення має бути меншим або дорівнювати <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">визначення</translation>
+<translation id="3557673793733683882">заголовок <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">кількість секунд до кінця фільму</translation>
<translation id="3706100364254443312">перемикач</translation>
<translation id="3732799496749320381">мм</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">термін</translation>
<translation id="3822383571486410024">У тексті має бути на менше <ph name="MIN_CHARACTERS" /> символів (ви ввели <ph name="CURRENT_LENGTH" /> символів).</translation>
<translation id="383465348367842624">Частина перед знаком "<ph name="ATSIGN" />" не може містити символ "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="3924558731517983934">додаток</translation>
+<translation id="3960700977367013758">смуга прокрутки</translation>
<translation id="4103419683916926126">Мілісекунди</translation>
+<translation id="4151657705144244502">зображення</translation>
<translation id="4201051445878709314">Показати попередній місяць</translation>
<translation id="4202807286478387388">перейти</translation>
+<translation id="421884353938374759">вибір кольору</translation>
+<translation id="4248100235867064564">панель меню</translation>
+<translation id="4254339807215791271">інформація про вміст</translation>
<translation id="4360991593054037559">Введіть дійсне значення. Два найближчі дійсні значення: <ph name="VALID_VALUE_LOW" /> і <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">кнопка меню</translation>
<translation id="4522570452068850558">Деталі</translation>
<translation id="4597532268155981612">форма</translation>
+<translation id="4661075872484491155">дерево</translation>
<translation id="4664250907885839816">Частина після знака "<ph name="ATSIGN" />" не може містити символ "<ph name="INVALIDCHARACTER" />".</translation>
+<translation id="4757246831282535685">панель вкладок</translation>
<translation id="4763480195061959176">відео</translation>
+<translation id="479989351350248267">пошук</translation>
<translation id="4812940957355064477">Введіть число.</translation>
<translation id="4975562563186953947">Вибрано <ph name="SELECTED_COUNT" /></translation>
<translation id="49969490063480558">Введіть частину електронної адреси після знака "<ph name="ATSIGN" />". Електронна адреса "<ph name="INVALIDADDRESS" />" неповна.</translation>
+<translation id="5034860022980953847">індикатор перебігу</translation>
<translation id="5048533449481078685">маркер списку</translation>
<translation id="5117590920725113268">Показати наступний місяць</translation>
+<translation id="512758898067543763">заголовок рядка</translation>
<translation id="5164977714490026579">Значення має бути більшим або дорівнювати <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Введіть частину електронної адреси до знака "<ph name="ATSIGN" />". Електронна адреса "<ph name="INVALIDADDRESS" />" неповна.</translation>
+<translation id="5317780077021120954">Зберегти</translation>
<translation id="5406322316791861025">фігура</translation>
+<translation id="5453733299334684579">елемент дерева</translation>
<translation id="5466621249238537318">Виберіть один або декілька файлів.</translation>
<translation id="5468998798572797635">вийти з повноекранного режиму</translation>
<translation id="5476505524087279545">зняти прапорець</translation>
+<translation id="5516424706154626233">засіб вибору дати</translation>
<translation id="5546461542133609677">увімкнути звук</translation>
+<translation id="561939826962581046">час</translation>
<translation id="5641012560118721995">призупинити відтворення</translation>
+<translation id="5643186887447432888">кнопка</translation>
<translation id="5843503607508392247">Інші...</translation>
<translation id="5939518447894949180">Скинути</translation>
<translation id="5944544982112848342">2048 (Високий рівень)</translation>
<translation id="5966707198760109579">Тиждень</translation>
-<translation id="598301471034819706">адреса</translation>
+<translation id="5987525920412732405">лічильник</translation>
<translation id="6015796118275082299">Рік</translation>
+<translation id="6023896073578205740">вікно списку</translation>
<translation id="6101327004457443354">увімкнути звукову доріжку</translation>
<translation id="6119846243427417423">активувати</translation>
+<translation id="6164829606128959761">вимірювач</translation>
<translation id="6270583010843788609">ескіз на часовій шкалі фільму</translation>
<translation id="6359256949422175976">ескіз на повзунку перебігу фільму</translation>
<translation id="6398862346408813489">Показати панель вибору місяців</translation>
<translation id="6404546809543547843">повзунок часу відтворення аудіо</translation>
+<translation id="648732519525291180">засіб вибору часу</translation>
<translation id="658823671542763450">увійти в повноекранний режим</translation>
+<translation id="6637586476836377253">журнал</translation>
<translation id="6643016212128521049">Очистити</translation>
<translation id="6663448176199120256">Останні пошуки</translation>
<translation id="668171684555832681">Інший...</translation>
<translation id="6692633176391053278">повторювач stepper</translation>
+<translation id="6739588121953935928">лінійка</translation>
+<translation id="6755330956360078551">підказка</translation>
<translation id="6820355525329141109">Не вдалося завантажити плагін.</translation>
<translation id="6843725295806269523">вимкнути звук</translation>
<translation id="6845533974506654842">натиснути</translation>
<translation id="6853785296079745596">сховати приховані субтирти</translation>
+<translation id="6885760532393684712">каталог</translation>
+<translation id="6934078000481955284">цитата</translation>
<translation id="7057186640035488495">тривалість фільму</translation>
<translation id="709897737746224366">Виберіть потрібний формат.</translation>
<translation id="7223624360433298498">минуло часу</translation>
<translation id="7263440858009898357">Виберіть елемент зі списку.</translation>
+<translation id="727747134524199931">заголовок стовпця</translation>
<translation id="7364796246159120393">Вибрати файл</translation>
<translation id="739024184232394898">Інші...</translation>
+<translation id="7491962110804786152">вкладка</translation>
<translation id="7673697353781729403">Години</translation>
<translation id="7720026100085573005">залишилось часу</translation>
<translation id="7740016676195725605">сховати приховані субтитри</translation>
<translation id="7740050170769002709">Вміст HTML</translation>
<translation id="7789962463072032349">призупинити</translation>
+<translation id="7802800022689234070">трикутник відкривання</translation>
<translation id="7888071071722539607">Електронна адреса має містити знак "<ph name="ATSIGN" />". В електронній адресі "<ph name="INVALIDADDRESS" />" знака "<ph name="ATSIGN" />" немає.</translation>
+<translation id="7891486169920085145">розділювач</translation>
<translation id="795667975304826397">Файл не вибрано</translation>
<translation id="8053789581856978548">текстове поле пошуку</translation>
<translation id="8115662671911883373">показати приховані субтитри</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">мапа зображення</translation>
<translation id="835897206747267392">Недійсне значення</translation>
<translation id="838869780401515933">установити прапорець</translation>
+<translation id="8433900881053900389">панель інструментів</translation>
<translation id="8444882422881193423">файлів: <ph name="NUMBER_OF_FILES" /></translation>
<translation id="8451268428117625855">Виберіть файл.</translation>
+<translation id="8461852803063341183">перемикач</translation>
+<translation id="8511325616783751178">кнопка спадного меню</translation>
<translation id="8534579021159131403">Хвилини</translation>
<translation id="8541249477527128034">елемент керування мультимедіа</translation>
<translation id="8583702881314752957">список визначень</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">розпочати відтворення</translation>
<translation id="8851136666856101339">головний</translation>
<translation id="8987927404178983737">Місяць</translation>
+<translation id="9002566407876343676">відкрити</translation>
<translation id="901493112792887934">поточний час у секундах</translation>
<translation id="9048119486235211610">навігація</translation>
<translation id="9050748414552849310">показати приховані субтитри</translation>
+<translation id="9062295712474918030">документ</translation>
<translation id="9108370397979208512">математика</translation>
<translation id="9132465097189459683">Інші...</translation>
+<translation id="9138385573473225930">сповіщення</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, починається <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">клітинка</translation>
+<translation id="966787709310836684">меню</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_vi.xtb b/chromium/content/app/strings/translations/content_strings_vi.xtb
index 813546bb357..ba271ad5801 100644
--- a/chromium/content/app/strings/translations/content_strings_vi.xtb
+++ b/chromium/content/app/strings/translations/content_strings_vi.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="vi">
<translation id="1014825444426747588">trống</translation>
+<translation id="1018939186200882850">mục menu</translation>
<translation id="1020833440720551630">tắt tiếng bản âm thanh</translation>
<translation id="10623998915015855">nút chuyển đổi</translation>
<translation id="1088086359088493902">Giây</translation>
<translation id="1171774979989969504">Vui lòng nhập địa chỉ email.</translation>
<translation id="1188858454923323853">bổ sung</translation>
+<translation id="1206619573307042055">bảng chữ chạy</translation>
+<translation id="1206693055195146388">thanh trượt</translation>
<translation id="1235745349614807883">Xóa Tìm kiếm Gần đây</translation>
+<translation id="1281252709823657822">hộp thoại</translation>
<translation id="1342835525016946179">bài viết</translation>
<translation id="1359897965706325498">biểu ngữ</translation>
<translation id="1589122976691792535">khu vực</translation>
<translation id="1591562245178063882">Tháng này</translation>
<translation id="1637811476055996098">Chọn tệp</translation>
+<translation id="167575180612809735">chỉ báo bận</translation>
<translation id="1729654308190250600">Vui lòng nhập địa chỉ email không trống.</translation>
<translation id="1758486001363313524">Khác...</translation>
+<translation id="1806710327868736751">alert_dialog</translation>
+<translation id="1821985195704844674">lưới dạng cây</translation>
<translation id="1822429046913737220">SA/CH</translation>
<translation id="1832974991323546415">phát trên thiết bị từ xa</translation>
<translation id="1842960171412779397">chọn</translation>
+<translation id="1880518467580572141">đường viền</translation>
<translation id="1921819250265091946">dd</translation>
<translation id="1930711995431081526">trạng thái</translation>
<translation id="1938124657309484470">Giá trị phải là <ph name="MAXIMUM_DATE_OR_TIME" /> hoặc sớm hơn.</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">Hãy cắt ngắn văn bản này thành <ph name="MAX_CHARACTERS" /> ký tự hoặc ít hơn (bạn hiện đang sử dụng <ph name="CURRENT_LENGTH" /> ký tự).</translation>
<translation id="2247351761944213033">Tuần <ph name="WEEKNUMBER" />, <ph name="YEAR" /></translation>
<translation id="2291999235780842123">hộp kiểm</translation>
+<translation id="2335594187091864976">bộ chọn ngày và giờ</translation>
<translation id="248395913932153421">Ngày</translation>
<translation id="2507943997699731163">Vui lòng điền vào trường này.</translation>
+<translation id="2508569020611168319">danh sách tab</translation>
<translation id="2548326553472216322">Không có tìm kiếm nào gần đây</translation>
<translation id="2572483411312390101">phát</translation>
<translation id="2613802280814924224">Vui lòng nhập giá trị hợp lệ. Giá trị hợp lệ gần nhất là <ph name="VALID_VALUE" />.</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">chân trang</translation>
<translation id="2723001399770238859">âm thanh</translation>
<translation id="2746543609216772311">Giá trị phải là <ph name="MINIMUM_DATE_OR_TIME" /> hoặc muộn hơn.</translation>
+<translation id="2759744352195237655">nút cửa sổ bật lên</translation>
<translation id="2761667185364618470">Vui lòng chọn hộp kiểm này nếu bạn muốn tiếp tục.</translation>
<translation id="2846343701378493991">1024 (Loại Trung bình)</translation>
+<translation id="2896972712917208084">nhóm radio</translation>
<translation id="2901282870647571346">trạng thái phim hiện tại</translation>
<translation id="2908441821576996758">Vui lòng nhập danh sách địa chỉ email được phân cách bằng dấu phẩy.</translation>
+<translation id="2931838996092594335">nhấp vào</translation>
+<translation id="2940813599313844715">đối tượng</translation>
<translation id="2942448076852699108">nội dung được đánh dấu</translation>
<translation id="3040011195152428237">liên kết</translation>
<translation id="3075154866155599887">Vui lòng nhập một giá trị hợp lệ. Trường không hoàn chỉnh hoặc có giá trị không hợp lệ.</translation>
+<translation id="3078740164268491126">bảng</translation>
+<translation id="3086746722712840547">ghi chú</translation>
<translation id="310520048233152454">Vui lòng nhập URL.</translation>
+<translation id="3175736971608411871">bộ tính giờ</translation>
+<translation id="3199563858620722075">hộp kết hợp</translation>
<translation id="3450233048674729344">Giá trị phải nhỏ hơn hoặc bằng <ph name="MAXIMUM" />.</translation>
<translation id="3486220673238053218">định nghĩa</translation>
+<translation id="3557673793733683882">tiêu đề <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">số giây còn lại của phim</translation>
<translation id="3706100364254443312">chuyển</translation>
<translation id="3732799496749320381">mm</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">cụm từ</translation>
<translation id="3822383571486410024">Hãy kéo dài văn bản này thành <ph name="MIN_CHARACTERS" /> ký tự trở lên (bạn hiện đang sử dụng <ph name="CURRENT_LENGTH" /> ký tự).</translation>
<translation id="383465348367842624">Phần đứng trước '<ph name="ATSIGN" />' không được chứa biểu tượng '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="3924558731517983934">ứng dụng</translation>
+<translation id="3960700977367013758">thanh cuộn</translation>
<translation id="4103419683916926126">Mili giây</translation>
+<translation id="4151657705144244502">hình ảnh</translation>
<translation id="4201051445878709314">Hiển thị tháng trước</translation>
<translation id="4202807286478387388">chuyển</translation>
+<translation id="421884353938374759">công cụ chọn màu</translation>
+<translation id="4248100235867064564">thanh menu</translation>
+<translation id="4254339807215791271">thông tin nội dung</translation>
<translation id="4360991593054037559">Vui lòng nhập giá trị hợp lệ. Hai giá trị hợp lệ gần nhất là <ph name="VALID_VALUE_LOW" /> và <ph name="VALID_VALUE_HIGHER" />.</translation>
+<translation id="4413860115965805769">nút menu</translation>
<translation id="4522570452068850558">Chi tiết</translation>
<translation id="4597532268155981612">biểu mẫu</translation>
+<translation id="4661075872484491155">cây</translation>
<translation id="4664250907885839816">Phần đứng sau '<ph name="ATSIGN" />' không được chứa biểu tượng '<ph name="INVALIDCHARACTER" />'.</translation>
+<translation id="4757246831282535685">bảng điều khiển tab</translation>
<translation id="4763480195061959176">video</translation>
+<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">Vui lòng nhập một số.</translation>
<translation id="4975562563186953947">Đã chọn <ph name="SELECTED_COUNT" /></translation>
<translation id="49969490063480558">Vui lòng nhập phần đứng sau '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' không hoàn chỉnh.</translation>
+<translation id="5034860022980953847">chỉ báo tiến trình</translation>
<translation id="5048533449481078685">đánh dấu danh sách</translation>
<translation id="5117590920725113268">Hiển thị tháng tiếp theo</translation>
+<translation id="512758898067543763">tiêu đề hàng</translation>
<translation id="5164977714490026579">Giá trị phải lớn hơn hoặc bằng <ph name="MINIMUM" />.</translation>
<translation id="5307600278924710095">Vui lòng nhập phần đứng trước '<ph name="ATSIGN" />'. '<ph name="INVALIDADDRESS" />' không hoàn chỉnh.</translation>
+<translation id="5317780077021120954">Lưu</translation>
<translation id="5406322316791861025">hình dáng</translation>
+<translation id="5453733299334684579">mục dạng cây</translation>
<translation id="5466621249238537318">Vui lòng chọn một hoặc nhiều tệp.</translation>
<translation id="5468998798572797635">thoát khỏi chế độ toàn màn hình</translation>
<translation id="5476505524087279545">bỏ chọn</translation>
+<translation id="5516424706154626233">bộ chọn ngày</translation>
<translation id="5546461542133609677">bật tiếng</translation>
+<translation id="561939826962581046">thời gian</translation>
<translation id="5641012560118721995">tạm dừng phát lại</translation>
+<translation id="5643186887447432888">nút</translation>
<translation id="5843503607508392247">Khác...</translation>
<translation id="5939518447894949180">Đặt lại</translation>
<translation id="5944544982112848342">2048 (Cấp độ cao)</translation>
<translation id="5966707198760109579">Tuần</translation>
-<translation id="598301471034819706">địa chỉ</translation>
+<translation id="5987525920412732405">nút quay tròn</translation>
<translation id="6015796118275082299">Năm</translation>
+<translation id="6023896073578205740">hộp danh sách</translation>
<translation id="6101327004457443354">bật tiếng bản âm thanh</translation>
<translation id="6119846243427417423">kích hoạt</translation>
+<translation id="6164829606128959761">thước đo</translation>
<translation id="6270583010843788609">núm dòng thời gian phim</translation>
<translation id="6359256949422175976">núm trình kiểm soát thời gian phim</translation>
<translation id="6398862346408813489">Hiển thị bảng lựa chọn tháng</translation>
<translation id="6404546809543547843">trình kiểm soát thời gian âm thanh</translation>
+<translation id="648732519525291180">bộ chọn giờ</translation>
<translation id="658823671542763450">vào chế độ toàn màn hình</translation>
+<translation id="6637586476836377253">nhật ký</translation>
<translation id="6643016212128521049">Xóa</translation>
<translation id="6663448176199120256">Tìm kiếm Gần đây</translation>
<translation id="668171684555832681">Khác...</translation>
<translation id="6692633176391053278">điều khiển tăng/giảm</translation>
+<translation id="6739588121953935928">thước</translation>
+<translation id="6755330956360078551">chú giải công cụ</translation>
<translation id="6820355525329141109">Không thể tải plugin.</translation>
<translation id="6843725295806269523">tắt tiếng</translation>
<translation id="6845533974506654842">nhấn</translation>
<translation id="6853785296079745596">ẩn phụ đề chi tiết</translation>
+<translation id="6885760532393684712">thư mục</translation>
+<translation id="6934078000481955284">khung trích dẫn</translation>
<translation id="7057186640035488495">thời gian phim</translation>
<translation id="709897737746224366">Vui lòng khớp với định dạng được yêu cầu.</translation>
<translation id="7223624360433298498">thời gian trôi qua</translation>
<translation id="7263440858009898357">Vui lòng chọn một mục trong danh sách.</translation>
+<translation id="727747134524199931">tiêu đề cột</translation>
<translation id="7364796246159120393">Chọn tệp</translation>
<translation id="739024184232394898">Khác...</translation>
+<translation id="7491962110804786152">tab</translation>
<translation id="7673697353781729403">Giờ</translation>
<translation id="7720026100085573005">thời gian còn lại</translation>
<translation id="7740016676195725605">ngừng hiển thị phụ đề chi tiết</translation>
<translation id="7740050170769002709">Nội dung HTML</translation>
<translation id="7789962463072032349">tạm dừng</translation>
+<translation id="7802800022689234070">tam giác hiển thị</translation>
<translation id="7888071071722539607">Vui lòng bao gồm '<ph name="ATSIGN" />' trong địa chỉ email. '<ph name="INVALIDADDRESS" />' bị thiếu '<ph name="ATSIGN" />'.</translation>
+<translation id="7891486169920085145">bộ chia</translation>
<translation id="795667975304826397">Không có tệp nào được chọn</translation>
<translation id="8053789581856978548">trường văn bản tìm kiếm</translation>
<translation id="8115662671911883373">bắt đầu hiển thị phụ đề chi tiết</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">bản đồ hình ảnh</translation>
<translation id="835897206747267392">Giá trị không hợp lệ.</translation>
<translation id="838869780401515933">chọn</translation>
+<translation id="8433900881053900389">thanh công cụ</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> tệp</translation>
<translation id="8451268428117625855">Vui lòng chọn một tệp.</translation>
+<translation id="8461852803063341183">nút radio</translation>
+<translation id="8511325616783751178">nút thả xuống</translation>
<translation id="8534579021159131403">Phút</translation>
<translation id="8541249477527128034">kiểm soát phương tiện</translation>
<translation id="8583702881314752957">danh sách định nghĩa</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">bắt đầu phát lại</translation>
<translation id="8851136666856101339">chính</translation>
<translation id="8987927404178983737">Tháng</translation>
+<translation id="9002566407876343676">mở</translation>
<translation id="901493112792887934">thời gian hiện tại bằng giây</translation>
<translation id="9048119486235211610">điều hướng</translation>
<translation id="9050748414552849310">hiển thị phụ đề chi tiết</translation>
+<translation id="9062295712474918030">tài liệu</translation>
<translation id="9108370397979208512">toán học</translation>
<translation id="9132465097189459683">Khác...</translation>
+<translation id="9138385573473225930">thông báo</translation>
<translation id="9155987714137265666"><ph name="WEEK" />, bắt đầu vào <ph name="WEEK_START_DATE" /></translation>
+<translation id="947831847158436616">ô</translation>
+<translation id="966787709310836684">menu</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_zh-CN.xtb b/chromium/content/app/strings/translations/content_strings_zh-CN.xtb
index a24fbb8c047..a556c73f52a 100644
--- a/chromium/content/app/strings/translations/content_strings_zh-CN.xtb
+++ b/chromium/content/app/strings/translations/content_strings_zh-CN.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="zh-CN">
<translation id="1014825444426747588">空白</translation>
+<translation id="1018939186200882850">菜单项</translation>
<translation id="1020833440720551630">将音轨设为静音</translation>
<translation id="10623998915015855">切换按钮</translation>
<translation id="1088086359088493902">秒</translation>
<translation id="1171774979989969504">请输入电子邮件地址。</translation>
<translation id="1188858454923323853">补充内容</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">滑块</translation>
<translation id="1235745349614807883">清除最近的搜索</translation>
+<translation id="1281252709823657822">对话框</translation>
<translation id="1342835525016946179">文章标记</translation>
<translation id="1359897965706325498">横幅</translation>
<translation id="1589122976691792535">区域</translation>
<translation id="1591562245178063882">本月</translation>
<translation id="1637811476055996098">选择文件</translation>
+<translation id="167575180612809735">忙碌状态指示</translation>
<translation id="1729654308190250600">请输入有效的电子邮件地址。</translation>
<translation id="1758486001363313524">其他...</translation>
+<translation id="1806710327868736751">提醒对话框</translation>
+<translation id="1821985195704844674">树状网格</translation>
<translation id="1822429046913737220">上午/下午</translation>
<translation id="1832974991323546415">在远程设备上播放</translation>
<translation id="1842960171412779397">选中</translation>
+<translation id="1880518467580572141">大纲</translation>
<translation id="1921819250265091946">日</translation>
<translation id="1930711995431081526">状态</translation>
<translation id="1938124657309484470">指定的值不得晚于<ph name="MAXIMUM_DATE_OR_TIME" />。</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">请将该文本减少为 <ph name="MAX_CHARACTERS" /> 个字符或更少(您当前使用了 <ph name="CURRENT_LENGTH" /> 个字符)。</translation>
<translation id="2247351761944213033"><ph name="YEAR" /> 年第 <ph name="WEEKNUMBER" /> 周</translation>
<translation id="2291999235780842123">复选框</translation>
+<translation id="2335594187091864976">日期和时间选择器</translation>
<translation id="248395913932153421">日</translation>
<translation id="2507943997699731163">请填写此字段。</translation>
+<translation id="2508569020611168319">标签列表</translation>
<translation id="2548326553472216322">最近未执行搜索</translation>
<translation id="2572483411312390101">播放</translation>
<translation id="2613802280814924224">请输入有效值。最接近的有效值为<ph name="VALID_VALUE" />。</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">页脚</translation>
<translation id="2723001399770238859">音频</translation>
<translation id="2746543609216772311">指定的值不得早于<ph name="MINIMUM_DATE_OR_TIME" />。</translation>
+<translation id="2759744352195237655">弹出式按钮</translation>
<translation id="2761667185364618470">如果要继续,请选中此框。</translation>
<translation id="2846343701378493991">1024(中等强度)</translation>
+<translation id="2896972712917208084">单选按钮组</translation>
<translation id="2901282870647571346">当前电影状态</translation>
<translation id="2908441821576996758">请输入用逗号分隔的电子邮件地址的列表。</translation>
+<translation id="2931838996092594335">点击</translation>
+<translation id="2940813599313844715">对象</translation>
<translation id="2942448076852699108">突出显示的内容</translation>
<translation id="3040011195152428237">链接</translation>
<translation id="3075154866155599887">请输入一个有效值。该字段不完整或存在无效日期。</translation>
+<translation id="3078740164268491126">表格</translation>
+<translation id="3086746722712840547">备注</translation>
<translation id="310520048233152454">请输入网址。</translation>
+<translation id="3175736971608411871">计时器</translation>
+<translation id="3199563858620722075">组合框</translation>
<translation id="3450233048674729344">值必须小于或等于 <ph name="MAXIMUM" />。</translation>
<translation id="3486220673238053218">定义</translation>
+<translation id="3557673793733683882">标题 <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">电影剩余时间(以秒为单位)</translation>
<translation id="3706100364254443312">切换</translation>
<translation id="3732799496749320381">月</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">字词</translation>
<translation id="3822383571486410024">请将该文本增加为 <ph name="MIN_CHARACTERS" /> 个字符或更多(您当前使用的是 <ph name="CURRENT_LENGTH" /> 个字符)。</translation>
<translation id="383465348367842624">“<ph name="ATSIGN" />”前面的内容不应包含符号“<ph name="INVALIDCHARACTER" />”。</translation>
+<translation id="3924558731517983934">应用</translation>
+<translation id="3960700977367013758">滚动条</translation>
<translation id="4103419683916926126">毫秒</translation>
+<translation id="4151657705144244502">图形</translation>
<translation id="4201051445878709314">显示上一个月</translation>
<translation id="4202807286478387388">略过</translation>
+<translation id="421884353938374759">颜色选择器</translation>
+<translation id="4248100235867064564">菜单栏</translation>
+<translation id="4254339807215791271">内容信息</translation>
<translation id="4360991593054037559">请输入有效值。两个最接近的有效值分别为<ph name="VALID_VALUE_LOW" />和<ph name="VALID_VALUE_HIGHER" />。</translation>
+<translation id="4413860115965805769">菜单按钮</translation>
<translation id="4522570452068850558">详细信息</translation>
<translation id="4597532268155981612">表单</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">“<ph name="ATSIGN" />”后面的内容不应包含符号“<ph name="INVALIDCHARACTER" />”。</translation>
+<translation id="4757246831282535685">标签面板</translation>
<translation id="4763480195061959176">视频</translation>
+<translation id="479989351350248267">搜索</translation>
<translation id="4812940957355064477">请输入一个数字。</translation>
<translation id="4975562563186953947">选择了<ph name="SELECTED_COUNT" />项</translation>
<translation id="49969490063480558">请在“<ph name="ATSIGN" />”后面输入内容。“<ph name="INVALIDADDRESS" />”不完整。</translation>
+<translation id="5034860022980953847">进度指示器</translation>
<translation id="5048533449481078685">列表标记</translation>
<translation id="5117590920725113268">显示下一个月</translation>
+<translation id="512758898067543763">行标题</translation>
<translation id="5164977714490026579">值必须大于或等于 <ph name="MINIMUM" />。</translation>
<translation id="5307600278924710095">请在“<ph name="ATSIGN" />”前面输入内容。“<ph name="INVALIDADDRESS" />”不完整。</translation>
+<translation id="5317780077021120954">保存</translation>
<translation id="5406322316791861025">图表</translation>
+<translation id="5453733299334684579">树状目录项</translation>
<translation id="5466621249238537318">请选择一个或多个文件。</translation>
<translation id="5468998798572797635">退出全屏模式</translation>
<translation id="5476505524087279545">取消选中</translation>
+<translation id="5516424706154626233">日期选择器</translation>
<translation id="5546461542133609677">取消静音</translation>
+<translation id="561939826962581046">time</translation>
<translation id="5641012560118721995">暂停播放</translation>
+<translation id="5643186887447432888">按钮</translation>
<translation id="5843503607508392247">其他...</translation>
<translation id="5939518447894949180">重置</translation>
<translation id="5944544982112848342">2048(高强度)</translation>
<translation id="5966707198760109579">周</translation>
-<translation id="598301471034819706">地址</translation>
+<translation id="5987525920412732405">微调按钮</translation>
<translation id="6015796118275082299">年</translation>
+<translation id="6023896073578205740">列表框</translation>
<translation id="6101327004457443354">取消对音轨静音</translation>
<translation id="6119846243427417423">激活</translation>
+<translation id="6164829606128959761">计量条</translation>
<translation id="6270583010843788609">电影时间轴缩略图</translation>
<translation id="6359256949422175976">电影时间进度条缩略图</translation>
<translation id="6398862346408813489">显示月份选择面板</translation>
<translation id="6404546809543547843">音频时间进度条</translation>
+<translation id="648732519525291180">时间选择器</translation>
<translation id="658823671542763450">进入全屏模式</translation>
+<translation id="6637586476836377253">日志</translation>
<translation id="6643016212128521049">清除</translation>
<translation id="6663448176199120256">近期搜索</translation>
<translation id="668171684555832681">其他...</translation>
<translation id="6692633176391053278">步进器</translation>
+<translation id="6739588121953935928">标尺</translation>
+<translation id="6755330956360078551">提示</translation>
<translation id="6820355525329141109">无法加载插件。</translation>
<translation id="6843725295806269523">静音</translation>
<translation id="6845533974506654842">按</translation>
<translation id="6853785296079745596">隐藏可选字幕</translation>
+<translation id="6885760532393684712">目录</translation>
+<translation id="6934078000481955284">引用标记</translation>
<translation id="7057186640035488495">电影时间</translation>
<translation id="709897737746224366">请与所请求的格式保持一致。</translation>
<translation id="7223624360433298498">已播放时间</translation>
<translation id="7263440858009898357">请在列表中选择一项。</translation>
+<translation id="727747134524199931">列标题</translation>
<translation id="7364796246159120393">选择文件</translation>
<translation id="739024184232394898">其他...</translation>
+<translation id="7491962110804786152">标签</translation>
<translation id="7673697353781729403">小时</translation>
<translation id="7720026100085573005">剩余时间</translation>
<translation id="7740016676195725605">停止显示可选字幕</translation>
<translation id="7740050170769002709">HTML 内容</translation>
<translation id="7789962463072032349">暂停</translation>
+<translation id="7802800022689234070">开合三角标记</translation>
<translation id="7888071071722539607">请在电子邮件地址中包括“<ph name="ATSIGN" />”。“<ph name="INVALIDADDRESS" />”中缺少“<ph name="ATSIGN" />”。</translation>
+<translation id="7891486169920085145">分离器</translation>
<translation id="795667975304826397">未选择任何文件</translation>
<translation id="8053789581856978548">搜索文本字段</translation>
<translation id="8115662671911883373">开始显示可选字幕</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">图片映射</translation>
<translation id="835897206747267392">值无效。</translation>
<translation id="838869780401515933">选中</translation>
+<translation id="8433900881053900389">工具栏</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> 个文件</translation>
<translation id="8451268428117625855">请选择一个文件。</translation>
+<translation id="8461852803063341183">单选按钮</translation>
+<translation id="8511325616783751178">下拉式按钮</translation>
<translation id="8534579021159131403">分钟</translation>
<translation id="8541249477527128034">媒体控件</translation>
<translation id="8583702881314752957">定义列表</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">开始播放</translation>
<translation id="8851136666856101339">主体内容</translation>
<translation id="8987927404178983737">月</translation>
+<translation id="9002566407876343676">打开</translation>
<translation id="901493112792887934">目前时间(以秒为单位)</translation>
<translation id="9048119486235211610">导航</translation>
<translation id="9050748414552849310">显示可选字幕</translation>
+<translation id="9062295712474918030">文档</translation>
<translation id="9108370397979208512">数学</translation>
<translation id="9132465097189459683">其他...</translation>
+<translation id="9138385573473225930">提醒</translation>
<translation id="9155987714137265666"><ph name="WEEK" />,从 <ph name="WEEK_START_DATE" />开始</translation>
+<translation id="947831847158436616">单元格</translation>
+<translation id="966787709310836684">菜单</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/app/strings/translations/content_strings_zh-TW.xtb b/chromium/content/app/strings/translations/content_strings_zh-TW.xtb
index 7b0b0ee069f..556872f3abd 100644
--- a/chromium/content/app/strings/translations/content_strings_zh-TW.xtb
+++ b/chromium/content/app/strings/translations/content_strings_zh-TW.xtb
@@ -2,22 +2,30 @@
<!DOCTYPE translationbundle>
<translationbundle lang="zh-TW">
<translation id="1014825444426747588">空白</translation>
+<translation id="1018939186200882850">選單項目</translation>
<translation id="1020833440720551630">將音軌設為靜音</translation>
<translation id="10623998915015855">切換按鈕</translation>
<translation id="1088086359088493902">秒</translation>
<translation id="1171774979989969504">請輸入電子郵件地址。</translation>
<translation id="1188858454923323853">補充</translation>
+<translation id="1206619573307042055">marquee</translation>
+<translation id="1206693055195146388">滑桿</translation>
<translation id="1235745349614807883">清除最近的搜尋紀錄</translation>
+<translation id="1281252709823657822">對話方塊</translation>
<translation id="1342835525016946179">文章</translation>
<translation id="1359897965706325498">橫幅</translation>
<translation id="1589122976691792535">區域</translation>
<translation id="1591562245178063882">本月</translation>
<translation id="1637811476055996098">選擇檔案</translation>
+<translation id="167575180612809735">忙碌狀態指標</translation>
<translation id="1729654308190250600">請輸入電子郵件地址。</translation>
<translation id="1758486001363313524">其他...</translation>
+<translation id="1806710327868736751">警示對話方塊</translation>
+<translation id="1821985195704844674">樹狀目錄網格</translation>
<translation id="1822429046913737220">AM/PM</translation>
<translation id="1832974991323546415">在遠端裝置上播放</translation>
<translation id="1842960171412779397">選取</translation>
+<translation id="1880518467580572141">大綱</translation>
<translation id="1921819250265091946">日</translation>
<translation id="1930711995431081526">狀態</translation>
<translation id="1938124657309484470">必須輸入 <ph name="MAXIMUM_DATE_OR_TIME" /> 或之前的值。</translation>
@@ -26,8 +34,10 @@
<translation id="2226276347425096477">請將這段文字刪減至 <ph name="MAX_CHARACTERS" /> 個字元以下 (目前的字元數為 <ph name="CURRENT_LENGTH" /> 個)。</translation>
<translation id="2247351761944213033"><ph name="YEAR" /> 年,第 <ph name="WEEKNUMBER" /> 週</translation>
<translation id="2291999235780842123">核取方塊</translation>
+<translation id="2335594187091864976">日期和時間選擇器</translation>
<translation id="248395913932153421">日</translation>
<translation id="2507943997699731163">請填寫這個欄位。</translation>
+<translation id="2508569020611168319">分頁清單</translation>
<translation id="2548326553472216322">沒有近期的搜尋</translation>
<translation id="2572483411312390101">播放</translation>
<translation id="2613802280814924224">請輸入有效值。最接近的有效值是 <ph name="VALID_VALUE" />。</translation>
@@ -35,16 +45,25 @@
<translation id="2674318244760992338">頁尾</translation>
<translation id="2723001399770238859">音訊</translation>
<translation id="2746543609216772311">必須輸入 <ph name="MINIMUM_DATE_OR_TIME" /> 或之後的值。</translation>
+<translation id="2759744352195237655">彈出式按鈕</translation>
<translation id="2761667185364618470">如果您要繼續執行,請勾選這個核取方塊。</translation>
<translation id="2846343701378493991">1024 (中等)</translation>
+<translation id="2896972712917208084">圓形按鈕群組</translation>
<translation id="2901282870647571346">目前電影狀態</translation>
<translation id="2908441821576996758">請輸入以逗號分隔的電子郵件地址清單。</translation>
+<translation id="2931838996092594335">點選</translation>
+<translation id="2940813599313844715">物件</translation>
<translation id="2942448076852699108">醒目顯示的內容</translation>
<translation id="3040011195152428237">連結</translation>
<translation id="3075154866155599887">欄位內容不完整或日期無效,請輸入有效的值。</translation>
+<translation id="3078740164268491126">表格</translation>
+<translation id="3086746722712840547">附註</translation>
<translation id="310520048233152454">請輸入網址。</translation>
+<translation id="3175736971608411871">計時器</translation>
+<translation id="3199563858620722075">下拉式方塊</translation>
<translation id="3450233048674729344">值必須小於或等於 <ph name="MAXIMUM" />。</translation>
<translation id="3486220673238053218">定義</translation>
+<translation id="3557673793733683882">標題 <ph name="HEADING_LEVEL" /></translation>
<translation id="3632707345189162177">電影剩餘秒數</translation>
<translation id="3706100364254443312">切換</translation>
<translation id="3732799496749320381">月</translation>
@@ -52,60 +71,89 @@
<translation id="3808586225841795776">字詞</translation>
<translation id="3822383571486410024">請將這段文字加長到 <ph name="MIN_CHARACTERS" /> 個字元以上 (目前使用字元數:<ph name="CURRENT_LENGTH" />)。</translation>
<translation id="383465348367842624">「<ph name="ATSIGN" />」後面的部分不應包含「<ph name="INVALIDCHARACTER" />」符號。</translation>
+<translation id="3924558731517983934">應用程式</translation>
+<translation id="3960700977367013758">捲軸</translation>
<translation id="4103419683916926126">毫秒</translation>
+<translation id="4151657705144244502">圖形</translation>
<translation id="4201051445878709314">顯示上一個月</translation>
<translation id="4202807286478387388">跳至另一頁</translation>
+<translation id="421884353938374759">顏色選擇器</translation>
+<translation id="4248100235867064564">選單列</translation>
+<translation id="4254339807215791271">內容資訊</translation>
<translation id="4360991593054037559">請輸入有效值。最接近的兩個有效值分別是 <ph name="VALID_VALUE_LOW" /> 和 <ph name="VALID_VALUE_HIGHER" />。</translation>
+<translation id="4413860115965805769">選單按鈕</translation>
<translation id="4522570452068850558">詳細資訊</translation>
<translation id="4597532268155981612">表單</translation>
+<translation id="4661075872484491155">tree</translation>
<translation id="4664250907885839816">「<ph name="ATSIGN" />」後面的部分不應包含「<ph name="INVALIDCHARACTER" />」符號。</translation>
+<translation id="4757246831282535685">分頁面板</translation>
<translation id="4763480195061959176">影片</translation>
+<translation id="479989351350248267">search</translation>
<translation id="4812940957355064477">請輸入一個數字。</translation>
<translation id="4975562563186953947">已選取 <ph name="SELECTED_COUNT" /> 個項目</translation>
<translation id="49969490063480558">請輸入「<ph name="ATSIGN" />」後面的部分。「<ph name="INVALIDADDRESS" />」不是完整值。</translation>
+<translation id="5034860022980953847">進度指標</translation>
<translation id="5048533449481078685">清單標記</translation>
<translation id="5117590920725113268">顯示下一個月</translation>
+<translation id="512758898067543763">列標題</translation>
<translation id="5164977714490026579">值必須大於或等於 <ph name="MINIMUM" />。</translation>
<translation id="5307600278924710095">請輸入「<ph name="ATSIGN" />」後面的部分。「<ph name="INVALIDADDRESS" />」不是完整值。</translation>
+<translation id="5317780077021120954">儲存</translation>
<translation id="5406322316791861025">圖表</translation>
+<translation id="5453733299334684579">樹狀目錄項目</translation>
<translation id="5466621249238537318">請選取一或多個檔案。</translation>
<translation id="5468998798572797635">退出全螢幕</translation>
<translation id="5476505524087279545">取消選取</translation>
+<translation id="5516424706154626233">日期選擇器</translation>
<translation id="5546461542133609677">取消靜音</translation>
+<translation id="561939826962581046">time</translation>
<translation id="5641012560118721995">暫停播放</translation>
+<translation id="5643186887447432888">按鈕</translation>
<translation id="5843503607508392247">其他...</translation>
<translation id="5939518447894949180">重設</translation>
<translation id="5944544982112848342">2048 (高級)</translation>
<translation id="5966707198760109579">週</translation>
-<translation id="598301471034819706">地址</translation>
+<translation id="5987525920412732405">微調按鈕</translation>
<translation id="6015796118275082299">年</translation>
+<translation id="6023896073578205740">清單方塊</translation>
<translation id="6101327004457443354">取消音軌靜音</translation>
<translation id="6119846243427417423">啟動</translation>
+<translation id="6164829606128959761">計量器</translation>
<translation id="6270583010843788609">電影時間軸捲動方塊</translation>
<translation id="6359256949422175976">影片時間拖曳工具捲動方塊</translation>
<translation id="6398862346408813489">顯示月份選取面板</translation>
<translation id="6404546809543547843">音訊時間點拖曳工具</translation>
+<translation id="648732519525291180">時間選擇器</translation>
<translation id="658823671542763450">進入全螢幕</translation>
+<translation id="6637586476836377253">紀錄</translation>
<translation id="6643016212128521049">清除</translation>
<translation id="6663448176199120256">最近的搜尋</translation>
<translation id="668171684555832681">其他...</translation>
<translation id="6692633176391053278">步進器</translation>
+<translation id="6739588121953935928">尺規</translation>
+<translation id="6755330956360078551">工具提示</translation>
<translation id="6820355525329141109">無法載入外掛程式。</translation>
<translation id="6843725295806269523">忽略的項目</translation>
<translation id="6845533974506654842">按下</translation>
<translation id="6853785296079745596">不顯示字幕</translation>
+<translation id="6885760532393684712">目錄</translation>
+<translation id="6934078000481955284">引用標記</translation>
<translation id="7057186640035488495">電影時間</translation>
<translation id="709897737746224366">請符合要求的格式。</translation>
<translation id="7223624360433298498">已播放時間</translation>
<translation id="7263440858009898357">請選取一個清單中的項目。</translation>
+<translation id="727747134524199931">欄標題</translation>
<translation id="7364796246159120393">選擇檔案</translation>
<translation id="739024184232394898">其他...</translation>
+<translation id="7491962110804786152">分頁</translation>
<translation id="7673697353781729403">小時</translation>
<translation id="7720026100085573005">剩餘時間</translation>
<translation id="7740016676195725605">停止顯示字幕</translation>
<translation id="7740050170769002709">HTML 內容</translation>
<translation id="7789962463072032349">暫停</translation>
+<translation id="7802800022689234070">顯示/隱藏三角標記</translation>
<translation id="7888071071722539607">請在電子郵件地址中包含「<ph name="ATSIGN" />」。「<ph name="INVALIDADDRESS" />」未包含「<ph name="ATSIGN" />」。</translation>
+<translation id="7891486169920085145">分割器</translation>
<translation id="795667975304826397">未選擇任何檔案</translation>
<translation id="8053789581856978548">搜尋文字欄位</translation>
<translation id="8115662671911883373">開始顯示字幕</translation>
@@ -116,8 +164,11 @@
<translation id="8244226242650769279">圖片點擊區</translation>
<translation id="835897206747267392">無效的值。</translation>
<translation id="838869780401515933">選取</translation>
+<translation id="8433900881053900389">工具列</translation>
<translation id="8444882422881193423"><ph name="NUMBER_OF_FILES" /> 個檔案</translation>
<translation id="8451268428117625855">請選取檔案。</translation>
+<translation id="8461852803063341183">圓形按鈕</translation>
+<translation id="8511325616783751178">下拉式清單按鈕</translation>
<translation id="8534579021159131403">分鐘</translation>
<translation id="8541249477527128034">媒體控制</translation>
<translation id="8583702881314752957">定義清單</translation>
@@ -127,10 +178,15 @@
<translation id="8785498733064193001">開始播放</translation>
<translation id="8851136666856101339">主要元素</translation>
<translation id="8987927404178983737">月</translation>
+<translation id="9002566407876343676">開啟</translation>
<translation id="901493112792887934">目前時間 (以秒為單位)</translation>
<translation id="9048119486235211610">導覽</translation>
<translation id="9050748414552849310">顯示字幕</translation>
+<translation id="9062295712474918030">文件</translation>
<translation id="9108370397979208512">數學</translation>
<translation id="9132465097189459683">其他...</translation>
+<translation id="9138385573473225930">警示</translation>
<translation id="9155987714137265666"><ph name="WEEK" />,從 <ph name="WEEK_START_DATE" />開始</translation>
+<translation id="947831847158436616">儲存格</translation>
+<translation id="966787709310836684">選單</translation>
</translationbundle> \ No newline at end of file
diff --git a/chromium/content/browser/BUILD.gn b/chromium/content/browser/BUILD.gn
index 4d66f86c09f..69f627a723b 100644
--- a/chromium/content/browser/BUILD.gn
+++ b/chromium/content/browser/BUILD.gn
@@ -10,150 +10,135 @@ import("//media/media_options.gni")
source_set("browser") {
# Only the public target should depend on this. All other targets (even
# internal content ones) should depend on the public one.
- visibility = [ "//content/public/browser:browser_sources" ]
+ visibility = [
+ ":for_content_tests", # See top of //content/BUILD.gn for why.
+ "//content/public/browser:browser_sources",
+ ]
configs += [
"//build/config:precompiled_headers",
+ "//content:content_implementation",
"//content/public/common:mojo_shell_client",
+ "//third_party/WebKit/public:debug_devtools",
+ "//v8:external_startup_data",
]
defines = []
libs = []
ldflags = []
- # Shared deps. See also non-iOS deps below.
deps = [
"//base",
"//base:base_static",
+ "//base/third_party/dynamic_annotations",
+ "//cc",
+ "//cc/surfaces",
+ "//components/filesystem:lib",
+ "//components/leveldb:lib",
"//components/mime_util",
+ "//components/profile_service:lib",
+ "//components/scheduler:common",
+ "//components/tracing",
+ "//components/tracing:startup_tracing",
"//components/url_formatter",
"//content:resources",
+ "//content/app/resources",
+ "//content/app/strings",
"//content/browser/background_sync:background_sync_proto",
"//content/browser/cache_storage:cache_storage_proto",
+ "//content/browser/devtools:gen_devtools_protocol_handler",
+ "//content/browser/devtools:resources",
"//content/browser/notifications:notification_proto",
"//content/browser/service_worker:service_worker_proto",
"//content/browser/speech/proto",
+ "//content/common",
"//content/public/common:common_sources",
"//content/public/common:mojo_bindings",
"//crypto",
"//device/battery",
+ "//device/bluetooth",
"//device/vibration",
+ "//gin",
"//google_apis",
+ "//gpu",
+ "//gpu/command_buffer/client:gles2_implementation",
+ "//ipc/mojo",
+ "//media",
+ "//media/midi",
"//mojo/common",
+ "//mojo/common:url_type_converters",
+ "//mojo/converters/geometry",
"//mojo/public/cpp/bindings",
+ "//mojo/public/js",
"//mojo/shell",
- "//mojo/shell/package_manager",
"//mojo/shell/public/cpp:cpp_for_chromium",
"//mojo/shell/public/interfaces",
+ "//mojo/shell/runner/common",
+ "//mojo/shell/runner/host:lib",
"//net",
"//net:extras",
"//skia",
+ "//skia/public",
"//sql",
+ "//storage/browser",
+ "//storage/common",
+
+ # TODO(brettw) bug 582206: Blink should not be used in the browser
+ # process. This is required by devtools' input_handler.cc which calls
+ # WebKeyboardEvent::setKeyIdentifierFromWindowsKeyCode
+ "//third_party/WebKit/public:blink",
"//third_party/WebKit/public:blink_headers",
+ "//third_party/WebKit/public:image_resources",
+ "//third_party/WebKit/public:resources",
+ "//third_party/angle:commit_id",
+ "//third_party/icu",
"//third_party/kasko:kasko_features",
- "//third_party/npapi",
+ "//third_party/leveldatabase",
+ "//third_party/libyuv",
"//third_party/re2",
+ "//third_party/webrtc",
+ "//third_party/webrtc/base:rtc_base",
+ "//third_party/webrtc/modules/desktop_capture:primitives",
"//third_party/zlib",
"//third_party/zlib:zip",
"//ui/accessibility",
"//ui/accessibility:ax_gen",
"//ui/base",
"//ui/base/ime",
+ "//ui/display",
"//ui/events",
"//ui/events:gesture_detection",
+ "//ui/events/blink",
"//ui/gfx",
"//ui/gfx/geometry",
"//ui/gl",
"//ui/native_theme",
"//ui/resources",
+ "//ui/shell_dialogs",
"//ui/snapshot",
+ "//ui/surface",
+ "//ui/touch_selection",
]
- if (is_ios) {
- # iOS doesn't get the normal file list and only takes these whitelisted
- # files.
- sources = [
- "browser_context.cc",
- "browser_main_loop.cc",
- "browser_main_runner.cc",
- "browser_process_sub_thread.cc",
- "browser_thread_impl.cc",
- "browser_url_handler_impl.cc",
- "cert_store_impl.cc",
- "download/download_create_info.cc",
- "notification_service_impl.cc",
- "signed_certificate_timestamp_store_impl.cc",
- "user_metrics.cc",
- "web_contents/navigation_entry_impl.cc",
- ]
- } else {
- # Normal non-iOS sources get everything.
- sources = rebase_path(content_browser_gypi_values.private_browser_sources,
- ".",
- "//content")
-
- # TODO(GYP) these generated files are listed as sources in content_browser.
- # This is a bit suspicious. The GN grit template will make a source set
- # containing the generated code so it should be sufficient to just depend
- # on the grit rule. But maybe some of these will need to be added?
- #
- # Need this annoying rebase_path call to match what happened with the
- # sources.
- sources -= rebase_path(
- [
- "$root_gen_dir/blink/grit/devtools_resources.h",
- "$root_gen_dir/blink/grit/devtools_resources_map.cc",
- "$root_gen_dir/blink/grit/devtools_resources_map.h",
- "$root_gen_dir/content/browser/tracing/grit/tracing_resources.h",
- "$root_gen_dir/ui/resources/grit/webui_resources_map.cc",
- ],
- ".")
-
- sources += [
- "mojo/mojo_shell_client_host.cc",
- "mojo/mojo_shell_client_host.h",
- "mojo/renderer_capability_filter.cc",
- ]
-
- # Non-iOS deps.
- deps += [
- "//cc",
- "//cc/surfaces",
- "//components/scheduler:common",
- "//content/app/resources",
- "//content/app/strings",
- "//content/browser/devtools:gen_devtools_protocol_handler",
- "//content/browser/devtools:resources",
- "//content/common:mojo_bindings",
- "//content/public/common:mojo_bindings",
- "//device/bluetooth",
- "//gin",
- "//mojo/common:url_type_converters",
- "//mojo/converters/geometry",
- "//mojo/public/cpp/bindings",
- "//mojo/public/js",
- "//mojo/shell/public/interfaces",
- "//skia/public",
- "//storage/browser",
- "//storage/common",
- "//third_party/WebKit/public:image_resources",
- "//third_party/WebKit/public:resources",
- "//third_party/angle:commit_id",
- "//third_party/icu",
- "//third_party/leveldatabase",
- "//third_party/libyuv",
- "//ui/events/blink",
- "//ui/resources",
- "//ui/surface",
- "//ui/touch_selection",
- ]
-
- configs += [ "//v8:external_startup_data" ]
- }
-
- configs += [
- "//content:content_implementation",
- "//third_party/WebKit/public:debug_devtools",
- ]
+ sources = rebase_path(content_browser_gypi_values.private_browser_sources,
+ ".",
+ "//content")
+
+ # TODO(GYP) these generated files are listed as sources in content_browser.
+ # This is a bit suspicious. The GN grit template will make a source set
+ # containing the generated code so it should be sufficient to just depend
+ # on the grit rule. But maybe some of these will need to be added?
+ #
+ # Need this annoying rebase_path call to match what happened with the
+ # sources.
+ sources -= rebase_path(
+ [
+ "$root_gen_dir/blink/grit/devtools_resources.h",
+ "$root_gen_dir/blink/grit/devtools_resources_map.cc",
+ "$root_gen_dir/blink/grit/devtools_resources_map.h",
+ "$root_gen_dir/content/browser/tracing/grit/tracing_resources.h",
+ "$root_gen_dir/ui/resources/grit/webui_resources_map.cc",
+ ],
+ ".")
if (toolkit_views) {
deps += [ "//ui/events" ]
@@ -176,32 +161,37 @@ source_set("browser") {
}
# TODO(GYP)
- # ['OS!="ios" and chrome_multiple_dll!=1', {
+ # [chrome_multiple_dll!=1', {
# 'dependencies': [
# '../third_party/WebKit/public/blink.gyp:blink',
# ],
# }],
- if (!is_mac && !is_ios) {
+ if (!is_mac) {
deps += [ "//sandbox" ]
}
- if (!is_android && !is_ios) {
+ if (!is_android) {
deps += [ "//content/browser/tracing:resources" ]
}
+ if ((use_udev && is_posix) || is_mac || is_win) {
+ deps += [ "//tools/battor_agent:battor_agent_lib" ]
+ sources += [
+ "tracing/power_tracing_agent.cc",
+ "tracing/power_tracing_agent.h",
+ ]
+ }
if (enable_webrtc) {
sources += rebase_path(content_browser_gypi_values.webrtc_browser_sources,
".",
"//content")
- deps += [ "//jingle:jingle_glue" ]
- if (is_linux) {
- deps += [ "//third_party/libjingle:libjingle_webrtc" ]
- }
+ deps += [
+ "//jingle:jingle_glue",
+ "//third_party/libjingle:libjingle_webrtc",
+ ]
if (is_linux || is_mac || is_win) {
sources += [
"media/capture/desktop_capture_device.cc",
"media/capture/desktop_capture_device.h",
- "media/capture/desktop_capture_device_uma_types.cc",
- "media/capture/desktop_capture_device_uma_types.h",
]
if (use_aura) {
sources += [
@@ -235,6 +225,7 @@ source_set("browser") {
"dinput8.lib",
"dwmapi.lib",
"dxguid.lib",
+ "imm32.lib",
"oleacc.lib",
"sensorsapi.lib",
"portabledeviceguids.lib",
@@ -251,20 +242,13 @@ source_set("browser") {
}
if (use_udev) {
- deps += [ "//device/udev_linux" ]
- } else {
- # Remove udev-specific sources.
- sources -= [
- "device_monitor_udev.cc",
- "device_monitor_udev.h",
+ deps += [
+ "//device/udev_linux",
+ "//media/capture",
]
+ } else {
if (is_linux) {
- # Already filtered out on non-Linux.
- sources -= [
- "gamepad/gamepad_platform_data_fetcher_linux.cc",
- "udev_linux.cc",
- "udev_linux.h",
- ]
+ sources -= [ "gamepad/gamepad_platform_data_fetcher_linux.cc" ]
}
}
@@ -305,6 +289,9 @@ source_set("browser") {
if (use_x11) {
configs += [ "//build/config/linux:x11" ]
+ if (!is_chromeos) {
+ configs += [ "//build/config/linux:xscrnsaver" ]
+ }
deps += [ "//ui/gfx/x" ]
}
@@ -338,6 +325,10 @@ source_set("browser") {
sources += rebase_path(content_browser_gypi_values.android_browser_sources,
".",
"//content")
+ sources += rebase_path(
+ content_browser_gypi_values.android_in_process_browser_sources,
+ ".",
+ "//content")
sources -= [
"browser_ipc_logging.cc",
"device_sensors/data_fetcher_shared_memory_default.cc",
@@ -345,8 +336,10 @@ source_set("browser") {
"geolocation/network_location_provider.h",
"geolocation/network_location_request.cc",
"geolocation/network_location_request.h",
+ "media/session/media_session_delegate_default.cc",
"power_usage_monitor_impl.cc",
"power_usage_monitor_impl.h",
+ "renderer_host/begin_frame_observer_proxy.cc",
"tracing/tracing_ui.cc",
"tracing/tracing_ui.h",
@@ -372,26 +365,13 @@ source_set("browser") {
"speech/speech_recognizer_impl.cc",
"speech/speech_recognizer_impl.h",
]
-
- if (!use_aura) {
- sources += rebase_path(
- content_browser_gypi_values.android_non_aura_browser_sources,
- ".",
- "//content")
- sources += rebase_path(
- content_browser_gypi_values.android_in_process_browser_sources,
- ".",
- "//content")
- sources -= [ "renderer_host/begin_frame_observer_proxy.cc" ]
- deps += [ "//ui/android" ]
- }
-
deps -= [ "//device/battery" ]
deps += [
"//content/public/android:jni",
"//media",
"//media/mojo/interfaces",
"//mojo/android:libsystem_java",
+ "//ui/android",
]
defines += [ "APPCACHE_USE_SIMPLE_CACHE" ]
libs += [ "jnigraphics" ]
@@ -409,18 +389,10 @@ source_set("browser") {
"//third_party/sudden_motion_sensor",
"//ui/accelerated_widget_mac",
]
- libs += [
- "bsm",
- "QTKit.framework",
- ]
}
if (is_chromeos) {
sources -= [ "device_sensors/data_fetcher_shared_memory_default.cc" ]
- sources += [
- "gpu/gpu_arc_video_service_host.cc",
- "gpu/gpu_arc_video_service_host.h",
- ]
deps += [
"//chromeos",
"//chromeos:power_manager_proto",
@@ -506,13 +478,6 @@ source_set("browser") {
deps += [ "//ui/compositor" ]
}
- if (!is_ios) {
- sources += [
- "compositor/surface_utils.cc",
- "compositor/surface_utils.h",
- ]
- }
-
if (enable_web_speech) {
deps += [ "//third_party/flac" ]
}
@@ -532,12 +497,8 @@ source_set("browser") {
deps += [ "//third_party/boringssl" ]
}
- if (enable_mojo_media != "none") {
- configs += [ "//media/mojo/services:enable_mojo_media_config" ]
- }
-
- if (enable_mojo_media == "browser") {
- deps += [ "//media/mojo/services:application" ]
+ if (enable_mojo_media) {
+ configs += [ "//media/mojo/services:mojo_media_config" ]
}
if (enable_webvr) {
@@ -559,3 +520,13 @@ source_set("browser") {
]
}
}
+
+# See comment at the top of //content/BUILD.gn for how this works.
+group("for_content_tests") {
+ visibility = [ "//content/test/*" ]
+ if (!is_component_build) {
+ public_deps = [
+ ":browser",
+ ]
+ }
+}
diff --git a/chromium/content/browser/DEPS b/chromium/content/browser/DEPS
index 5e33c93e2de..42e02ee046e 100644
--- a/chromium/content/browser/DEPS
+++ b/chromium/content/browser/DEPS
@@ -1,10 +1,12 @@
include_rules = [
# Allow inclusion of specific components that we depend on. We may only
# depend on components which we share with the mojo html_viewer.
- "+components/arc",
+ "+components/filesystem",
+ "+components/leveldb",
"+components/mime_util",
"+components/mus/public/interfaces",
"+components/mus/public",
+ "+components/profile_service",
"+components/scheduler/common",
"+components/tracing",
"+components/url_formatter",
@@ -16,11 +18,12 @@ include_rules = [
"+gin/v8_initializer.h",
"+media/media_features.h",
"+media/audio", # For audio input for speech input feature.
+ "+media/capture", # For Video Device monitoring in Mac.
"+media/base", # For Android JNI registration.
+ "+media/capture", # For Device Monitoring
"+media/filters", # For reporting GPU decoding UMA.
"+media/midi", # For Web MIDI API
"+media/mojo", # For mojo media services.
- "+media/capture/video", # For Video Device monitoring in Mac.
"+mojo",
"+sql",
"+ui/aura_extra",
@@ -49,6 +52,7 @@ include_rules = [
# No inclusion of WebKit from the browser, other than strictly enum/POD,
# header-only types, and some selected common code.
"-third_party/WebKit",
+ "+third_party/WebKit/public/platform/WebAddressSpace.h",
"+third_party/WebKit/public/platform/WebCircularGeofencingRegion.h",
"+third_party/WebKit/public/platform/WebCursorInfo.h",
"+third_party/WebKit/public/platform/WebDisplayMode.h",
@@ -61,9 +65,12 @@ include_rules = [
"+third_party/WebKit/public/platform/WebReferrerPolicy.h",
"+third_party/WebKit/public/platform/WebScreenInfo.h",
"+third_party/WebKit/public/platform/WebString.h",
+ "+third_party/WebKit/public/platform/modules/geolocation/geolocation.mojom.h",
"+third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseException.h",
"+third_party/WebKit/public/platform/modules/indexeddb/WebIDBTypes.h",
"+third_party/WebKit/public/platform/modules/notifications/WebNotificationPermission.h",
+ "+third_party/WebKit/public/platform/modules/permissions/permission.mojom.h",
+ "+third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h",
"+third_party/WebKit/public/platform/modules/push_messaging/WebPushPermissionStatus.h",
"+third_party/WebKit/public/platform/modules/screen_orientation/WebScreenOrientationLockType.h",
"+third_party/WebKit/public/platform/modules/screen_orientation/WebScreenOrientationType.h",
@@ -96,6 +103,10 @@ include_rules = [
"+third_party/WebKit/public/web/WebTreeScopeType.h",
"+third_party/WebKit/public/web/mac/WebScrollbarTheme.h",
+ # Until we define where mojo interfaces should live in blink we whitelist each
+ # one separately.
+ "+third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom.h"
+
# DO NOT ADD ANY CHROME OR COMPONENTS INCLUDES HERE!!!
# See https://sites.google.com/a/chromium.org/dev/developers/content-module
# for more information.
diff --git a/chromium/content/browser/accessibility/accessibility_event_recorder_win.cc b/chromium/content/browser/accessibility/accessibility_event_recorder_win.cc
index fa767494fb4..cb40bfbb850 100644
--- a/chromium/content/browser/accessibility/accessibility_event_recorder_win.cc
+++ b/chromium/content/browser/accessibility/accessibility_event_recorder_win.cc
@@ -287,7 +287,7 @@ HRESULT AccessibilityEventRecorderWin::AccessibleObjectFromWindowWrapper(
if (accessibility_hwnd != hwnd)
return E_FAIL;
- IAccessible* obj = manager_->GetRoot()->ToBrowserAccessibilityWin();
+ IAccessible* obj = ToBrowserAccessibilityWin(manager_->GetRoot());
obj->AddRef();
*ppv_object = obj;
return S_OK;
diff --git a/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc b/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
index a8bd5412df5..597631cc221 100644
--- a/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
+++ b/chromium/content/browser/accessibility/accessibility_ipc_error_browsertest.cc
@@ -132,7 +132,6 @@ IN_PROC_BROWSER_TEST_F(AccessibilityIpcErrorBrowserTest,
const ui::AXNode* button = button_container->ChildAtIndex(0);
EXPECT_EQ(ui::AX_ROLE_BUTTON, button->data().role);
- EXPECT_TRUE(button->data().state >> ui::AX_STATE_FOCUSED & 1);
}
#if defined(OS_ANDROID)
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc
index 12321df619d..24fce4d93ce 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_android.cc
@@ -127,6 +127,7 @@ void AccessibilityTreeFormatterAndroid::AddProperties(
// String attributes.
dict->SetString("name", android_node->GetText());
+ dict->SetString("role_description", android_node->GetRoleDescription());
// Int attributes.
dict->SetInteger("item_index", android_node->GetItemIndex());
@@ -171,6 +172,15 @@ base::string16 AccessibilityTreeFormatterAndroid::ToString(
dict.GetString("class", &class_value);
WriteAttribute(true, base::UTF16ToUTF8(class_value), &line);
+ std::string role_description;
+ dict.GetString("role_description", &role_description);
+ if (!role_description.empty()) {
+ WriteAttribute(
+ true,
+ StringPrintf("role_description='%s'", role_description.c_str()),
+ &line);
+ }
+
for (unsigned i = 0; i < arraysize(BOOL_ATTRIBUTES); i++) {
const char* attribute_name = BOOL_ATTRIBUTES[i];
bool value;
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
index 4ebb1c0e46d..ef954c9e26c 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_auralinux.cc
@@ -46,8 +46,7 @@ void AccessibilityTreeFormatterAuraLinux::AddProperties(
base::DictionaryValue* dict) {
dict->SetInteger("id", node.GetId());
BrowserAccessibilityAuraLinux* acc_obj =
- const_cast<BrowserAccessibility*>(&node)
- ->ToBrowserAccessibilityAuraLinux();
+ ToBrowserAccessibilityAuraLinux(const_cast<BrowserAccessibility*>(&node));
AtkObject* atk_object = acc_obj->GetAtkObject();
AtkRole role = acc_obj->atk_role();
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc
index 27b9c9fa1cd..6796770f2a5 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_blink.cc
@@ -7,6 +7,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "content/browser/accessibility/accessibility_tree_formatter_blink.h"
+#include "ui/gfx/transform.h"
namespace content {
@@ -19,13 +20,19 @@ AccessibilityTreeFormatterBlink::~AccessibilityTreeFormatterBlink() {
uint32_t AccessibilityTreeFormatterBlink::ChildCount(
const BrowserAccessibility& node) const {
- return node.InternalChildCount();
+ if (node.HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID))
+ return node.PlatformChildCount();
+ else
+ return node.InternalChildCount();
}
BrowserAccessibility* AccessibilityTreeFormatterBlink::GetChild(
const BrowserAccessibility& node,
uint32_t i) const {
- return node.InternalGetChild(i);
+ if (node.HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID))
+ return node.PlatformGetChild(i);
+ else
+ return node.InternalGetChild(i);
}
void AccessibilityTreeFormatterBlink::AddProperties(
@@ -33,12 +40,23 @@ void AccessibilityTreeFormatterBlink::AddProperties(
base::DictionaryValue* dict) {
dict->SetInteger("id", node.GetId());
- dict->SetString("role", ui::ToString(node.GetData().role));
+ dict->SetString("internalRole", ui::ToString(node.GetData().role));
- dict->SetInteger("boundsX", node.GetData().location.x());
- dict->SetInteger("boundsY", node.GetData().location.y());
- dict->SetInteger("boundsWidth", node.GetData().location.width());
- dict->SetInteger("boundsHeight", node.GetData().location.height());
+ gfx::Rect bounds = node.GetData().location;
+ dict->SetInteger("boundsX", bounds.x());
+ dict->SetInteger("boundsY", bounds.y());
+ dict->SetInteger("boundsWidth", bounds.width());
+ dict->SetInteger("boundsHeight", bounds.height());
+
+ gfx::Rect page_bounds = node.GetLocalBoundsRect();
+ dict->SetInteger("pageBoundsX", page_bounds.x());
+ dict->SetInteger("pageBoundsY", page_bounds.y());
+ dict->SetInteger("pageBoundsWidth", page_bounds.width());
+ dict->SetInteger("pageBoundsHeight", page_bounds.height());
+
+ dict->SetBoolean("transform",
+ node.GetData().transform &&
+ !node.GetData().transform->IsIdentity());
for (int state_index = ui::AX_STATE_NONE;
state_index <= ui::AX_STATE_LAST;
@@ -106,7 +124,7 @@ base::string16 AccessibilityTreeFormatterBlink::ToString(
}
base::string16 role_value;
- dict.GetString("role", &role_value);
+ dict.GetString("internalRole", &role_value);
WriteAttribute(true, base::UTF16ToUTF8(role_value), &line);
for (int state_index = ui::AX_STATE_NONE;
@@ -127,6 +145,19 @@ base::string16 AccessibilityTreeFormatterBlink::ToString(
FormatCoordinates("size", "boundsWidth", "boundsHeight", dict),
&line);
+ WriteAttribute(false,
+ FormatCoordinates("pageLocation",
+ "pageBoundsX", "pageBoundsY", dict),
+ &line);
+ WriteAttribute(false,
+ FormatCoordinates("pageSize",
+ "pageBoundsWidth", "pageBoundsHeight", dict),
+ &line);
+
+ bool transform;
+ if (dict.GetBoolean("transform", &transform) && transform)
+ WriteAttribute(false, "transform", &line);
+
for (int attr_index = ui::AX_STRING_ATTRIBUTE_NONE;
attr_index <= ui::AX_STRING_ATTRIBUTE_LAST;
++attr_index) {
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm b/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm
index 0721a9e991f..48b9d883167 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_mac.mm
@@ -41,15 +41,15 @@ scoped_ptr<base::DictionaryValue> PopulatePosition(
// based on the lower-left corner of the object. To make this easier and less
// confusing, convert it to local window coordinates using the top-left
// corner when dumping the position.
- BrowserAccessibility* root = node.manager()->GetRoot();
- BrowserAccessibilityCocoa* cocoa_root = root->ToBrowserAccessibilityCocoa();
+ BrowserAccessibility* root = node.manager()->GetRootManager()->GetRoot();
+ BrowserAccessibilityCocoa* cocoa_root = ToBrowserAccessibilityCocoa(root);
NSPoint root_position = [[cocoa_root position] pointValue];
NSSize root_size = [[cocoa_root size] sizeValue];
int root_top = -static_cast<int>(root_position.y + root_size.height);
int root_left = static_cast<int>(root_position.x);
BrowserAccessibilityCocoa* cocoa_node =
- const_cast<BrowserAccessibility*>(&node)->ToBrowserAccessibilityCocoa();
+ ToBrowserAccessibilityCocoa(const_cast<BrowserAccessibility*>(&node));
NSPoint node_position = [[cocoa_node position] pointValue];
NSSize node_size = [[cocoa_node size] sizeValue];
@@ -221,7 +221,7 @@ void AccessibilityTreeFormatterMac::AddProperties(
base::DictionaryValue* dict) {
dict->SetInteger("id", node.GetId());
BrowserAccessibilityCocoa* cocoa_node =
- const_cast<BrowserAccessibility*>(&node)->ToBrowserAccessibilityCocoa();
+ ToBrowserAccessibilityCocoa(const_cast<BrowserAccessibility*>(&node));
NSArray* supportedAttributes = [cocoa_node accessibilityAttributeNames];
string role = SysNSStringToUTF8(
diff --git a/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc b/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc
index cbece3a2553..eaf4fc8f4aa 100644
--- a/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc
+++ b/chromium/content/browser/accessibility/accessibility_tree_formatter_win.cc
@@ -54,36 +54,35 @@ AccessibilityTreeFormatterWin::AccessibilityTreeFormatterWin() {
AccessibilityTreeFormatterWin::~AccessibilityTreeFormatterWin() {
}
-const char* ALL_ATTRIBUTES[] = {
- "name",
- "value",
- "states",
- "attributes",
- "role_name",
- "ia2_hypertext",
- "currentValue",
- "minimumValue",
- "maximumValue",
- "description",
- "default_action",
- "keyboard_shortcut",
- "location",
- "size",
- "index_in_parent",
- "n_relations",
- "group_level",
- "similar_items_in_group",
- "position_in_group",
- "table_rows",
- "table_columns",
- "row_index",
- "column_index",
- "n_characters",
- "caret_offset",
- "n_selections",
- "selection_start",
- "selection_end"
-};
+const char* ALL_ATTRIBUTES[] = {"name",
+ "value",
+ "states",
+ "attributes",
+ "text_attributes",
+ "role_name",
+ "ia2_hypertext",
+ "currentValue",
+ "minimumValue",
+ "maximumValue",
+ "description",
+ "default_action",
+ "keyboard_shortcut",
+ "location",
+ "size",
+ "index_in_parent",
+ "n_relations",
+ "group_level",
+ "similar_items_in_group",
+ "position_in_group",
+ "table_rows",
+ "table_columns",
+ "row_index",
+ "column_index",
+ "n_characters",
+ "caret_offset",
+ "n_selections",
+ "selection_start",
+ "selection_end"};
namespace {
@@ -157,7 +156,7 @@ void AccessibilityTreeFormatterWin::AddProperties(
const BrowserAccessibility& node, base::DictionaryValue* dict) {
dict->SetInteger("id", node.GetId());
BrowserAccessibilityWin* ax_object =
- const_cast<BrowserAccessibility*>(&node)->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(const_cast<BrowserAccessibility*>(&node));
DCHECK(ax_object);
VARIANT variant_self;
@@ -167,8 +166,13 @@ void AccessibilityTreeFormatterWin::AddProperties(
dict->SetString("role", IAccessible2RoleToString(ax_object->ia2_role()));
base::win::ScopedBstr temp_bstr;
- if (SUCCEEDED(ax_object->get_accName(variant_self, temp_bstr.Receive())))
- dict->SetString("name", base::string16(temp_bstr, temp_bstr.Length()));
+ if (SUCCEEDED(ax_object->get_accName(variant_self, temp_bstr.Receive()))) {
+ base::string16 name = base::string16(temp_bstr, temp_bstr.Length());
+
+ // Ignore a JAWS workaround where the name of a document is " ".
+ if (name != L" " || ax_object->ia2_role() != ROLE_SYSTEM_DOCUMENT)
+ dict->SetString("name", name);
+ }
temp_bstr.Reset();
if (SUCCEEDED(ax_object->get_accValue(variant_self, temp_bstr.Receive())))
@@ -185,17 +189,29 @@ void AccessibilityTreeFormatterWin::AddProperties(
IAccessibleStateToStringVector(ia_state, &state_strings);
IAccessible2StateToStringVector(ax_object->ia2_state(), &state_strings);
- base::ListValue* states = new base::ListValue;
- for (const auto& state_string : state_strings)
+ scoped_ptr<base::ListValue> states(new base::ListValue());
+ for (const base::string16& state_string : state_strings)
states->AppendString(base::UTF16ToUTF8(state_string));
- dict->Set("states", states);
+ dict->Set("states", std::move(states));
const std::vector<base::string16>& ia2_attributes =
ax_object->ia2_attributes();
- base::ListValue* attributes = new base::ListValue;
- for (const auto& ia2_attribute : ia2_attributes)
+ scoped_ptr<base::ListValue> attributes(new base::ListValue());
+ for (const base::string16& ia2_attribute : ia2_attributes)
attributes->AppendString(base::UTF16ToUTF8(ia2_attribute));
- dict->Set("attributes", attributes);
+ dict->Set("attributes", std::move(attributes));
+
+ ax_object->ComputeStylesIfNeeded();
+ const std::map<int, std::vector<base::string16>>& ia2_text_attributes =
+ ax_object->offset_to_text_attributes();
+ scoped_ptr<base::ListValue> text_attributes(new base::ListValue());
+ for (const auto& style_span : ia2_text_attributes) {
+ int start_offset = style_span.first;
+ text_attributes->AppendString("offset:" + base::IntToString(start_offset));
+ for (const base::string16& text_attribute : style_span.second)
+ text_attributes->AppendString(base::UTF16ToUTF8(text_attribute));
+ }
+ dict->Set("text_attributes", std::move(text_attributes));
dict->SetString("role_name", ax_object->role_name());
dict->SetString("ia2_hypertext", GetIA2Hypertext(*ax_object));
@@ -237,12 +253,12 @@ void AccessibilityTreeFormatterWin::AddProperties(
dict->SetString("help", base::string16(temp_bstr, temp_bstr.Length()));
temp_bstr.Reset();
- BrowserAccessibility* root = node.manager()->GetRoot();
+ BrowserAccessibility* root = node.manager()->GetRootManager()->GetRoot();
LONG left, top, width, height;
LONG root_left, root_top, root_width, root_height;
if (SUCCEEDED(ax_object->accLocation(
&left, &top, &width, &height, variant_self)) &&
- SUCCEEDED(root->ToBrowserAccessibilityWin()->accLocation(
+ SUCCEEDED(ToBrowserAccessibilityWin(root)->accLocation(
&root_left, &root_top, &root_width, &root_height, variant_self))) {
base::DictionaryValue* location = new base::DictionaryValue;
location->SetInteger("x", left - root_left);
@@ -340,7 +356,7 @@ base::string16 AccessibilityTreeFormatterWin::ToString(
break;
}
case base::Value::TYPE_INTEGER: {
- int int_value;
+ int int_value = 0;
value->GetAsInteger(&int_value);
WriteAttribute(false,
base::StringPrintf(L"%ls=%d",
@@ -351,7 +367,7 @@ base::string16 AccessibilityTreeFormatterWin::ToString(
break;
}
case base::Value::TYPE_DOUBLE: {
- double double_value;
+ double double_value = 0.0;
value->GetAsDouble(&double_value);
WriteAttribute(false,
base::StringPrintf(L"%ls=%.2f",
diff --git a/chromium/content/browser/accessibility/android_hit_testing_browsertest.cc b/chromium/content/browser/accessibility/android_hit_testing_browsertest.cc
deleted file mode 100644
index 12817d10b0c..00000000000
--- a/chromium/content/browser/accessibility/android_hit_testing_browsertest.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/browser/accessibility/accessibility_tree_formatter.h"
-#include "content/browser/accessibility/browser_accessibility.h"
-#include "content/browser/accessibility/browser_accessibility_manager.h"
-#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/public/browser/web_contents.h"
-#include "content/public/common/content_paths.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/url_constants.h"
-#include "content/public/test/content_browser_test.h"
-#include "content/public/test/content_browser_test_utils.h"
-#include "content/shell/browser/shell.h"
-#include "content/test/accessibility_browser_test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-class AndroidHitTestingBrowserTest : public ContentBrowserTest {
- public:
- AndroidHitTestingBrowserTest() {}
- ~AndroidHitTestingBrowserTest() override {}
-};
-
-IN_PROC_BROWSER_TEST_F(AndroidHitTestingBrowserTest,
- HitTestOutsideDocumentBoundsReturnsRoot) {
- NavigateToURL(shell(), GURL(url::kAboutBlankURL));
-
- // Load the page.
- AccessibilityNotificationWaiter waiter(
- shell(), AccessibilityModeComplete,
- ui::AX_EVENT_LOAD_COMPLETE);
- const char url_str[] =
- "data:text/html,"
- "<!doctype html>"
- "<html><head><title>Accessibility Test</title></head>"
- "<body>"
- "<a href='#'>"
- "This is some text in a link"
- "</a>"
- "</body></html>";
- GURL url(url_str);
- NavigateToURL(shell(), url);
- waiter.WaitForNotification();
-
- // Get the BrowserAccessibilityManager.
- WebContentsImpl* web_contents =
- static_cast<WebContentsImpl*>(shell()->web_contents());
- BrowserAccessibilityManager* manager =
- web_contents->GetRootBrowserAccessibilityManager();
-
- // Send a hit test request, and wait for the hover event in response.
- AccessibilityNotificationWaiter hover_waiter(
- shell(), AccessibilityModeComplete,
- ui::AX_EVENT_HOVER);
- manager->delegate()->AccessibilityHitTest(gfx::Point(-1, -1));
- hover_waiter.WaitForNotification();
-
- // Assert that the hover event was fired on the root of the tree.
- int hover_target_id = hover_waiter.event_target_id();
- BrowserAccessibility* hovered_node = manager->GetFromID(hover_target_id);
- ASSERT_TRUE(hovered_node != NULL);
- ASSERT_EQ(ui::AX_ROLE_ROOT_WEB_AREA, hovered_node->GetRole());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility.cc b/chromium/content/browser/accessibility/browser_accessibility.cc
index 3c43e153fe6..fa606fc2bfe 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility.cc
@@ -15,9 +15,19 @@
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/common/accessibility_messages.h"
#include "ui/accessibility/ax_text_utils.h"
+#include "ui/accessibility/platform/ax_platform_node.h"
+#include "ui/gfx/geometry/rect_f.h"
namespace content {
+namespace {
+
+// Map from unique_id to BrowserAccessibility
+using UniqueIDMap = base::hash_map<int32_t, BrowserAccessibility*>;
+base::LazyInstance<UniqueIDMap> g_unique_id_map = LAZY_INSTANCE_INITIALIZER;
+
+}
+
#if !defined(PLATFORM_HAS_NATIVE_ACCESSIBILITY_IMPL)
// static
BrowserAccessibility* BrowserAccessibility::Create() {
@@ -27,10 +37,23 @@ BrowserAccessibility* BrowserAccessibility::Create() {
BrowserAccessibility::BrowserAccessibility()
: manager_(NULL),
- node_(NULL) {
+ node_(NULL),
+ unique_id_(ui::AXPlatformNode::GetNextUniqueId()) {
+ g_unique_id_map.Get()[unique_id_] = this;
}
BrowserAccessibility::~BrowserAccessibility() {
+ if (unique_id_)
+ g_unique_id_map.Get().erase(unique_id_);
+}
+
+// static
+BrowserAccessibility* BrowserAccessibility::GetFromUniqueID(int32_t unique_id) {
+ auto iter = g_unique_id_map.Get().find(unique_id);
+ if (iter == g_unique_id_map.Get().end())
+ return nullptr;
+
+ return iter->second;
}
void BrowserAccessibility::Init(BrowserAccessibilityManager* manager,
@@ -73,7 +96,7 @@ uint32_t BrowserAccessibility::PlatformChildCount() const {
BrowserAccessibilityManager* child_manager =
BrowserAccessibilityManager::FromID(
GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID));
- if (child_manager)
+ if (child_manager && child_manager->GetRoot()->GetParent() == this)
return 1;
return 0;
@@ -88,11 +111,14 @@ bool BrowserAccessibility::IsNative() const {
bool BrowserAccessibility::IsDescendantOf(
const BrowserAccessibility* ancestor) const {
- if (this == ancestor) {
+ if (!ancestor)
+ return false;
+
+ if (this == ancestor)
return true;
- } else if (GetParent()) {
+
+ if (GetParent())
return GetParent()->IsDescendantOf(ancestor);
- }
return false;
}
@@ -112,7 +138,7 @@ BrowserAccessibility* BrowserAccessibility::PlatformGetChild(
BrowserAccessibilityManager* child_manager =
BrowserAccessibilityManager::FromID(
GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID));
- if (child_manager)
+ if (child_manager && child_manager->GetRoot()->GetParent() == this)
result = child_manager->GetRoot();
} else {
result = InternalGetChild(child_index);
@@ -132,6 +158,16 @@ bool BrowserAccessibility::PlatformIsChildOfLeaf() const {
return false;
}
+BrowserAccessibility* BrowserAccessibility::GetClosestPlatformObject() const {
+ BrowserAccessibility* platform_object =
+ const_cast<BrowserAccessibility*>(this);
+ while (platform_object && platform_object->PlatformIsChildOfLeaf())
+ platform_object = platform_object->InternalGetParent();
+
+ DCHECK(platform_object);
+ return platform_object;
+}
+
BrowserAccessibility* BrowserAccessibility::GetPreviousSibling() const {
if (GetParent() && GetIndexInParent() > 0)
return GetParent()->InternalGetChild(GetIndexInParent() - 1);
@@ -154,7 +190,7 @@ BrowserAccessibility* BrowserAccessibility::PlatformDeepestFirstChild() const {
if (!PlatformChildCount())
return nullptr;
- auto deepest_child = PlatformGetChild(0);
+ BrowserAccessibility* deepest_child = PlatformGetChild(0);
while (deepest_child->PlatformChildCount())
deepest_child = deepest_child->PlatformGetChild(0);
@@ -165,7 +201,8 @@ BrowserAccessibility* BrowserAccessibility::PlatformDeepestLastChild() const {
if (!PlatformChildCount())
return nullptr;
- auto deepest_child = PlatformGetChild(PlatformChildCount() - 1);
+ BrowserAccessibility* deepest_child =
+ PlatformGetChild(PlatformChildCount() - 1);
while (deepest_child->PlatformChildCount()) {
deepest_child = deepest_child->PlatformGetChild(
deepest_child->PlatformChildCount() - 1);
@@ -174,6 +211,31 @@ BrowserAccessibility* BrowserAccessibility::PlatformDeepestLastChild() const {
return deepest_child;
}
+BrowserAccessibility* BrowserAccessibility::InternalDeepestFirstChild() const {
+ if (!InternalChildCount())
+ return nullptr;
+
+ BrowserAccessibility* deepest_child = InternalGetChild(0);
+ while (deepest_child->InternalChildCount())
+ deepest_child = deepest_child->InternalGetChild(0);
+
+ return deepest_child;
+}
+
+BrowserAccessibility* BrowserAccessibility::InternalDeepestLastChild() const {
+ if (!InternalChildCount())
+ return nullptr;
+
+ BrowserAccessibility* deepest_child =
+ InternalGetChild(InternalChildCount() - 1);
+ while (deepest_child->InternalChildCount()) {
+ deepest_child = deepest_child->InternalGetChild(
+ deepest_child->InternalChildCount() - 1);
+ }
+
+ return deepest_child;
+}
+
uint32_t BrowserAccessibility::InternalChildCount() const {
if (!node_ || !manager_)
return 0;
@@ -191,8 +253,9 @@ BrowserAccessibility* BrowserAccessibility::InternalGetChild(
}
BrowserAccessibility* BrowserAccessibility::GetParent() const {
- if (!node_ || !manager_)
- return NULL;
+ if (!instance_active())
+ return nullptr;
+
ui::AXNode* parent = node_->parent();
if (parent)
return manager_->GetFromAXNode(parent);
@@ -321,17 +384,25 @@ gfx::Rect BrowserAccessibility::GetLocalBoundsForRange(int start, int len)
int local_start = overlap_start - child_start;
int local_end = overlap_end - child_start;
+ // |local_end| and |local_start| may equal |child_length| when the caret is
+ // at the end of a text field.
+ DCHECK_GE(local_start, 0);
+ DCHECK_LE(local_start, child_length);
+ DCHECK_GE(local_end, 0);
+ DCHECK_LE(local_end, child_length);
- gfx::Rect child_rect = child->GetLocation();
- int text_direction = child->GetIntAttribute(
- ui::AX_ATTR_TEXT_DIRECTION);
const std::vector<int32_t>& character_offsets =
child->GetIntListAttribute(ui::AX_ATTR_CHARACTER_OFFSETS);
+ if (static_cast<int>(character_offsets.size()) != child_length)
+ continue;
int start_pixel_offset =
local_start > 0 ? character_offsets[local_start - 1] : 0;
int end_pixel_offset =
local_end > 0 ? character_offsets[local_end - 1] : 0;
+ gfx::Rect child_rect = child->GetLocation();
+ auto text_direction = static_cast<ui::AXTextDirection>(
+ child->GetIntAttribute(ui::AX_ATTR_TEXT_DIRECTION));
gfx::Rect child_overlap_rect;
switch (text_direction) {
case ui::AX_TEXT_DIRECTION_NONE:
@@ -389,7 +460,10 @@ gfx::Rect BrowserAccessibility::GetGlobalBoundsForRange(int start, int len)
base::string16 BrowserAccessibility::GetValue() const {
base::string16 value = GetString16Attribute(ui::AX_ATTR_VALUE);
- if (value.empty() && IsSimpleTextControl())
+ // Some screen readers like Jaws and older versions of VoiceOver require a
+ // value to be set in text fields with rich content, even though the same
+ // information is available on the children.
+ if (value.empty() && (IsSimpleTextControl() || IsRichTextControl()))
value = GetInnerText();
return value;
}
@@ -555,6 +629,10 @@ void BrowserAccessibility::Destroy() {
node_ = NULL;
manager_ = NULL;
+ if (unique_id_)
+ g_unique_id_map.Get().erase(unique_id_);
+ unique_id_ = 0;
+
NativeReleaseReference();
}
@@ -592,6 +670,72 @@ bool BrowserAccessibility::GetFloatAttribute(
return GetData().GetFloatAttribute(attribute, value);
}
+bool BrowserAccessibility::HasInheritedStringAttribute(
+ ui::AXStringAttribute attribute) const {
+ if (!instance_active())
+ return false;
+
+ if (GetData().HasStringAttribute(attribute))
+ return true;
+ return GetParent() && GetParent()->HasInheritedStringAttribute(attribute);
+}
+
+const std::string& BrowserAccessibility::GetInheritedStringAttribute(
+ ui::AXStringAttribute attribute) const {
+ if (!instance_active())
+ return base::EmptyString();
+
+ const BrowserAccessibility* current_object = this;
+ do {
+ if (current_object->GetData().HasStringAttribute(attribute))
+ return current_object->GetData().GetStringAttribute(attribute);
+ current_object = current_object->GetParent();
+ } while (current_object);
+ return base::EmptyString();
+}
+
+bool BrowserAccessibility::GetInheritedStringAttribute(
+ ui::AXStringAttribute attribute,
+ std::string* value) const {
+ if (!instance_active()) {
+ *value = std::string();
+ return false;
+ }
+
+ if (GetData().GetStringAttribute(attribute, value))
+ return true;
+ return GetParent() &&
+ GetParent()->GetData().GetStringAttribute(attribute, value);
+}
+
+base::string16 BrowserAccessibility::GetInheritedString16Attribute(
+ ui::AXStringAttribute attribute) const {
+ if (!instance_active())
+ return base::string16();
+
+ const BrowserAccessibility* current_object = this;
+ do {
+ if (current_object->GetData().HasStringAttribute(attribute))
+ return current_object->GetData().GetString16Attribute(attribute);
+ current_object = current_object->GetParent();
+ } while (current_object);
+ return base::string16();
+}
+
+bool BrowserAccessibility::GetInheritedString16Attribute(
+ ui::AXStringAttribute attribute,
+ base::string16* value) const {
+ if (!instance_active()) {
+ *value = base::string16();
+ return false;
+ }
+
+ if (GetData().GetString16Attribute(attribute, value))
+ return true;
+ return GetParent() &&
+ GetParent()->GetData().GetString16Attribute(attribute, value);
+}
+
bool BrowserAccessibility::HasIntAttribute(
ui::AXIntAttribute attribute) const {
return GetData().HasIntAttribute(attribute);
@@ -626,9 +770,8 @@ base::string16 BrowserAccessibility::GetString16Attribute(
return GetData().GetString16Attribute(attribute);
}
-bool BrowserAccessibility::GetString16Attribute(
- ui::AXStringAttribute attribute,
- base::string16* value) const {
+bool BrowserAccessibility::GetString16Attribute(ui::AXStringAttribute attribute,
+ base::string16* value) const {
return GetData().GetString16Attribute(attribute, value);
}
@@ -698,9 +841,7 @@ bool BrowserAccessibility::IsCellOrTableHeaderRole() const {
}
bool BrowserAccessibility::HasCaret() const {
- if (HasState(ui::AX_STATE_EDITABLE) &&
- !HasState(ui::AX_STATE_RICHLY_EDITABLE) &&
- HasIntAttribute(ui::AX_ATTR_TEXT_SEL_START) &&
+ if (IsSimpleTextControl() && HasIntAttribute(ui::AX_ATTR_TEXT_SEL_START) &&
HasIntAttribute(ui::AX_ATTR_TEXT_SEL_END)) {
return true;
}
@@ -724,28 +865,51 @@ bool BrowserAccessibility::IsWebAreaForPresentationalIframe() const {
if (!parent)
return false;
- BrowserAccessibility* grandparent = parent->GetParent();
- if (!grandparent)
- return false;
+ return parent->GetRole() == ui::AX_ROLE_IFRAME_PRESENTATIONAL;
+}
- return grandparent->GetRole() == ui::AX_ROLE_IFRAME_PRESENTATIONAL;
+bool BrowserAccessibility::IsClickable() const {
+ switch (GetRole()) {
+ case ui::AX_ROLE_BUTTON:
+ case ui::AX_ROLE_CHECK_BOX:
+ case ui::AX_ROLE_COLOR_WELL:
+ case ui::AX_ROLE_DISCLOSURE_TRIANGLE:
+ case ui::AX_ROLE_IMAGE_MAP_LINK:
+ case ui::AX_ROLE_LINK:
+ case ui::AX_ROLE_LIST_BOX_OPTION:
+ case ui::AX_ROLE_MENU_BUTTON:
+ case ui::AX_ROLE_MENU_ITEM:
+ case ui::AX_ROLE_MENU_ITEM_CHECK_BOX:
+ case ui::AX_ROLE_MENU_ITEM_RADIO:
+ case ui::AX_ROLE_MENU_LIST_OPTION:
+ case ui::AX_ROLE_MENU_LIST_POPUP:
+ case ui::AX_ROLE_POP_UP_BUTTON:
+ case ui::AX_ROLE_RADIO_BUTTON:
+ case ui::AX_ROLE_SWITCH:
+ case ui::AX_ROLE_TAB:
+ case ui::AX_ROLE_TOGGLE_BUTTON:
+ return true;
+ default:
+ return false;
+ }
}
bool BrowserAccessibility::IsControl() const {
switch (GetRole()) {
case ui::AX_ROLE_BUTTON:
- case ui::AX_ROLE_BUTTON_DROP_DOWN:
case ui::AX_ROLE_CHECK_BOX:
case ui::AX_ROLE_COLOR_WELL:
case ui::AX_ROLE_COMBO_BOX:
case ui::AX_ROLE_DISCLOSURE_TRIANGLE:
case ui::AX_ROLE_LIST_BOX:
+ case ui::AX_ROLE_MENU:
case ui::AX_ROLE_MENU_BAR:
case ui::AX_ROLE_MENU_BUTTON:
case ui::AX_ROLE_MENU_ITEM:
case ui::AX_ROLE_MENU_ITEM_CHECK_BOX:
case ui::AX_ROLE_MENU_ITEM_RADIO:
- case ui::AX_ROLE_MENU:
+ case ui::AX_ROLE_MENU_LIST_OPTION:
+ case ui::AX_ROLE_MENU_LIST_POPUP:
case ui::AX_ROLE_POP_UP_BUTTON:
case ui::AX_ROLE_RADIO_BUTTON:
case ui::AX_ROLE_SCROLL_BAR:
@@ -763,14 +927,31 @@ bool BrowserAccessibility::IsControl() const {
}
}
+bool BrowserAccessibility::IsMenuRelated() const {
+ switch (GetRole()) {
+ case ui::AX_ROLE_MENU:
+ case ui::AX_ROLE_MENU_BAR:
+ case ui::AX_ROLE_MENU_BUTTON:
+ case ui::AX_ROLE_MENU_ITEM:
+ case ui::AX_ROLE_MENU_ITEM_CHECK_BOX:
+ case ui::AX_ROLE_MENU_ITEM_RADIO:
+ case ui::AX_ROLE_MENU_LIST_OPTION:
+ case ui::AX_ROLE_MENU_LIST_POPUP:
+ return true;
+ default:
+ return false;
+ }
+}
+
bool BrowserAccessibility::IsSimpleTextControl() const {
// Time fields, color wells and spinner buttons might also use text fields as
// constituent parts, but they are not considered text fields as a whole.
switch (GetRole()) {
case ui::AX_ROLE_COMBO_BOX:
case ui::AX_ROLE_SEARCH_BOX:
- case ui::AX_ROLE_TEXT_FIELD:
return true;
+ case ui::AX_ROLE_TEXT_FIELD:
+ return !HasState(ui::AX_STATE_RICHLY_EDITABLE);
default:
return false;
}
@@ -842,39 +1023,49 @@ void BrowserAccessibility::FixEmptyBounds(gfx::Rect* bounds) const
gfx::Rect BrowserAccessibility::ElementBoundsToLocalBounds(gfx::Rect bounds)
const {
- // Walk up the parent chain. Every time we encounter a Web Area, offset
- // based on the scroll bars and then offset based on the origin of that
- // nested web area.
- BrowserAccessibility* parent = GetParent();
- bool need_to_offset_web_area =
- (GetRole() == ui::AX_ROLE_WEB_AREA ||
- GetRole() == ui::AX_ROLE_ROOT_WEB_AREA);
- while (parent) {
- if (need_to_offset_web_area &&
- parent->GetLocation().width() > 0 &&
- parent->GetLocation().height() > 0) {
- bounds.Offset(parent->GetLocation().x(), parent->GetLocation().y());
- need_to_offset_web_area = false;
- }
-
- // On some platforms, we don't want to take the root scroll offsets
- // into account.
- if (parent->GetRole() == ui::AX_ROLE_ROOT_WEB_AREA &&
- !manager()->UseRootScrollOffsetsWhenComputingBounds()) {
- break;
- }
-
- if (parent->GetRole() == ui::AX_ROLE_WEB_AREA ||
- parent->GetRole() == ui::AX_ROLE_ROOT_WEB_AREA) {
+ BrowserAccessibilityManager* manager = this->manager();
+ BrowserAccessibility* root = manager->GetRoot();
+ while (manager && root) {
+ // Apply scroll offsets.
+ if (root != this && (root->GetParent() ||
+ manager->UseRootScrollOffsetsWhenComputingBounds())) {
int sx = 0;
int sy = 0;
- if (parent->GetIntAttribute(ui::AX_ATTR_SCROLL_X, &sx) &&
- parent->GetIntAttribute(ui::AX_ATTR_SCROLL_Y, &sy)) {
+ if (root->GetIntAttribute(ui::AX_ATTR_SCROLL_X, &sx) &&
+ root->GetIntAttribute(ui::AX_ATTR_SCROLL_Y, &sy)) {
bounds.Offset(-sx, -sy);
}
- need_to_offset_web_area = true;
}
- parent = parent->GetParent();
+
+ // If the parent accessibility tree is in a different site instance,
+ // ask the delegate to transform our coordinates into the root
+ // coordinate space and then we're done.
+ if (manager->delegate() &&
+ root->GetParent() &&
+ root->GetParent()->manager()->delegate()) {
+ BrowserAccessibilityManager* parent_manager =
+ root->GetParent()->manager();
+ if (manager->delegate()->AccessibilityGetSiteInstance() !=
+ parent_manager->delegate()->AccessibilityGetSiteInstance()) {
+ return manager->delegate()->AccessibilityTransformToRootCoordSpace(
+ bounds);
+ }
+ }
+
+ // Otherwise, apply the transform from this frame into the coordinate
+ // space of its parent frame.
+ if (root->GetData().transform) {
+ gfx::RectF boundsf(bounds);
+ root->GetData().transform->TransformRect(&boundsf);
+ bounds = gfx::Rect(boundsf.x(), boundsf.y(),
+ boundsf.width(), boundsf.height());
+ }
+
+ if (!root->GetParent())
+ break;
+
+ manager = root->GetParent()->manager();
+ root = manager->GetRoot();
}
return bounds;
diff --git a/chromium/content/browser/accessibility/browser_accessibility.h b/chromium/content/browser/accessibility/browser_accessibility.h
index 9b1a3feb411..49120b9c396 100644
--- a/chromium/content/browser/accessibility/browser_accessibility.h
+++ b/chromium/content/browser/accessibility/browser_accessibility.h
@@ -75,6 +75,8 @@ class CONTENT_EXPORT BrowserAccessibility {
virtual ~BrowserAccessibility();
+ static BrowserAccessibility* GetFromUniqueID(int32_t unique_id);
+
// Called only once, immediately after construction. The constructor doesn't
// take any arguments because in the Windows subclass we use a special
// function to construct a COM object.
@@ -89,6 +91,11 @@ class CONTENT_EXPORT BrowserAccessibility {
// Called when the location changed.
virtual void OnLocationChanged() {}
+ // This is called when the platform-specific attributes for a node need
+ // to be recomputed, which may involve firing native events, due to a
+ // change other than an update from OnAccessibilityEvents.
+ virtual void UpdatePlatformAttributes() {}
+
// Return true if this object is equal to or a descendant of |ancestor|.
bool IsDescendantOf(const BrowserAccessibility* ancestor) const;
@@ -116,6 +123,10 @@ class CONTENT_EXPORT BrowserAccessibility {
// platform.
bool PlatformIsChildOfLeaf() const;
+ // If this object is exposed to the platform, returns this object. Otherwise,
+ // returns the platform leaf under which this object is found.
+ BrowserAccessibility* GetClosestPlatformObject() const;
+
BrowserAccessibility* GetPreviousSibling() const;
BrowserAccessibility* GetNextSibling() const;
@@ -124,6 +135,11 @@ class CONTENT_EXPORT BrowserAccessibility {
// Returns nullptr if there are no children.
BrowserAccessibility* PlatformDeepestLastChild() const;
+ // Returns nullptr if there are no children.
+ BrowserAccessibility* InternalDeepestFirstChild() const;
+ // Returns nullptr if there are no children.
+ BrowserAccessibility* InternalDeepestLastChild() const;
+
// Returns the bounds of this object in coordinates relative to the
// top-left corner of the overall web area.
gfx::Rect GetLocalBoundsRect() const;
@@ -183,8 +199,9 @@ class CONTENT_EXPORT BrowserAccessibility {
//
BrowserAccessibilityManager* manager() const { return manager_; }
- bool instance_active() const { return node_ != NULL; }
+ bool instance_active() const { return node_ && manager_; }
ui::AXNode* node() const { return node_; }
+ int32_t unique_id() const { return unique_id_; }
// These access the internal accessibility tree, which doesn't necessarily
// reflect the accessibility tree that should be exposed on each platform.
@@ -211,17 +228,6 @@ class CONTENT_EXPORT BrowserAccessibility {
// IsNative returns false.
virtual bool IsNative() const;
-#if defined(OS_MACOSX) && __OBJC__
- const BrowserAccessibilityCocoa* ToBrowserAccessibilityCocoa() const;
- BrowserAccessibilityCocoa* ToBrowserAccessibilityCocoa();
-#elif defined(OS_WIN)
- const BrowserAccessibilityWin* ToBrowserAccessibilityWin() const;
- BrowserAccessibilityWin* ToBrowserAccessibilityWin();
-#elif defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_X11)
- const BrowserAccessibilityAuraLinux* ToBrowserAccessibilityAuraLinux() const;
- BrowserAccessibilityAuraLinux* ToBrowserAccessibilityAuraLinux();
-#endif
-
// Accessing accessibility attributes:
//
// There are dozens of possible attributes for an accessibility node,
@@ -245,6 +251,17 @@ class CONTENT_EXPORT BrowserAccessibility {
float GetFloatAttribute(ui::AXFloatAttribute attr) const;
bool GetFloatAttribute(ui::AXFloatAttribute attr, float* value) const;
+ bool HasInheritedStringAttribute(ui::AXStringAttribute attribute) const;
+ const std::string& GetInheritedStringAttribute(
+ ui::AXStringAttribute attribute) const;
+ bool GetInheritedStringAttribute(ui::AXStringAttribute attribute,
+ std::string* value) const;
+
+ base::string16 GetInheritedString16Attribute(
+ ui::AXStringAttribute attribute) const;
+ bool GetInheritedString16Attribute(ui::AXStringAttribute attribute,
+ base::string16* value) const;
+
bool HasIntAttribute(ui::AXIntAttribute attribute) const;
int GetIntAttribute(ui::AXIntAttribute attribute) const;
bool GetIntAttribute(ui::AXIntAttribute attribute, int* value) const;
@@ -255,10 +272,10 @@ class CONTENT_EXPORT BrowserAccessibility {
bool GetStringAttribute(ui::AXStringAttribute attribute,
std::string* value) const;
- bool GetString16Attribute(ui::AXStringAttribute attribute,
- base::string16* value) const;
base::string16 GetString16Attribute(
ui::AXStringAttribute attribute) const;
+ bool GetString16Attribute(ui::AXStringAttribute attribute,
+ base::string16* value) const;
bool HasIntListAttribute(ui::AXIntListAttribute attribute) const;
const std::vector<int32_t>& GetIntListAttribute(
@@ -287,6 +304,8 @@ class CONTENT_EXPORT BrowserAccessibility {
bool* is_defined,
bool* is_mixed) const;
+ base::string16 GetFontFamily() const;
+ base::string16 GetLanguage() const;
virtual base::string16 GetText() const;
// Returns true if the bit corresponding to the given state enum is 1.
@@ -301,7 +320,10 @@ class CONTENT_EXPORT BrowserAccessibility {
// True if this is a web area, and its grandparent is a presentational iframe.
bool IsWebAreaForPresentationalIframe() const;
+ virtual bool IsClickable() const;
bool IsControl() const;
+ bool IsMenuRelated() const;
+ bool IsRangeControl() const;
bool IsSimpleTextControl() const;
// Indicates if this object is at the root of a rich edit text control.
bool IsRichTextControl() const;
@@ -319,6 +341,9 @@ class CONTENT_EXPORT BrowserAccessibility {
// The underlying node.
ui::AXNode* node_;
+ // A unique ID, since node IDs are frame-local.
+ int32_t unique_id_;
+
private:
// |GetInnerText| recursively includes all the text from descendants such as
// text found in any embedded object. In contrast, |GetText| might include a
diff --git a/chromium/content/browser/accessibility/browser_accessibility_android.cc b/chromium/content/browser/accessibility/browser_accessibility_android.cc
index 79a1f18a369..53df2492ce4 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_android.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_android.cc
@@ -5,11 +5,15 @@
#include "content/browser/accessibility/browser_accessibility_android.h"
#include "base/i18n/break_iterator.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/app/strings/grit/content_strings.h"
#include "content/browser/accessibility/browser_accessibility_manager_android.h"
#include "content/common/accessibility_messages.h"
+#include "content/public/common/content_client.h"
+#include "third_party/skia/include/core/SkColor.h"
namespace {
@@ -132,6 +136,8 @@ bool BrowserAccessibilityAndroid::IsClickable() const {
if (!PlatformIsLeaf())
return false;
+ // We are very aggressive about returning true with IsClickable on Android
+ // because there is no way to know for sure what might have a click handler.
return IsFocusable() || !GetText().empty();
}
@@ -181,7 +187,7 @@ bool BrowserAccessibilityAndroid::IsFocusable() const {
}
bool BrowserAccessibilityAndroid::IsFocused() const {
- return manager()->GetFocus(manager()->GetRoot()) == this;
+ return manager()->GetFocus() == this;
}
bool BrowserAccessibilityAndroid::IsHeading() const {
@@ -300,7 +306,10 @@ const char* BrowserAccessibilityAndroid::GetClassName() const {
class_name = "android.app.Dialog";
break;
case ui::AX_ROLE_ROOT_WEB_AREA:
- class_name = "android.webkit.WebView";
+ if (GetParent() == nullptr)
+ class_name = "android.webkit.WebView";
+ else
+ class_name = "android.view.View";
break;
case ui::AX_ROLE_MENU_ITEM:
case ui::AX_ROLE_MENU_ITEM_CHECK_BOX:
@@ -354,10 +363,11 @@ base::string16 BrowserAccessibilityAndroid::GetText() const {
// For color wells, the color is stored in separate attributes.
// Perhaps we could return color names in the future?
if (GetRole() == ui::AX_ROLE_COLOR_WELL) {
- int color = GetIntAttribute(ui::AX_ATTR_COLOR_VALUE);
- int red = (color >> 16) & 0xFF;
- int green = (color >> 8) & 0xFF;
- int blue = color & 0xFF;
+ unsigned int color =
+ static_cast<unsigned int>(GetIntAttribute(ui::AX_ATTR_COLOR_VALUE));
+ unsigned int red = SkColorGetR(color);
+ unsigned int green = SkColorGetG(color);
+ unsigned int blue = SkColorGetB(color);
return base::UTF8ToUTF16(
base::StringPrintf("#%02X%02X%02X", red, green, blue));
}
@@ -407,6 +417,412 @@ base::string16 BrowserAccessibilityAndroid::GetText() const {
return text;
}
+base::string16 BrowserAccessibilityAndroid::GetRoleDescription() const {
+ content::ContentClient* content_client = content::GetContentClient();
+
+ // As a special case, if we have a heading level return a string like
+ // "heading level 1", etc.
+ if (GetRole() == ui::AX_ROLE_HEADING) {
+ int level = GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL);
+ if (level >= 1 && level <= 6) {
+ std::vector<base::string16> values;
+ values.push_back(base::IntToString16(level));
+ return base::ReplaceStringPlaceholders(
+ content_client->GetLocalizedString(IDS_AX_ROLE_HEADING_WITH_LEVEL),
+ values, nullptr);
+ }
+ }
+
+ int message_id = -1;
+ switch (GetRole()) {
+ case ui::AX_ROLE_ABBR:
+ // No role description.
+ break;
+ case ui::AX_ROLE_ALERT_DIALOG:
+ message_id = IDS_AX_ROLE_ALERT_DIALOG;
+ break;
+ case ui::AX_ROLE_ALERT:
+ message_id = IDS_AX_ROLE_ALERT;
+ break;
+ case ui::AX_ROLE_ANNOTATION:
+ // No role description.
+ break;
+ case ui::AX_ROLE_APPLICATION:
+ message_id = IDS_AX_ROLE_APPLICATION;
+ break;
+ case ui::AX_ROLE_ARTICLE:
+ message_id = IDS_AX_ROLE_ARTICLE;
+ break;
+ case ui::AX_ROLE_BANNER:
+ message_id = IDS_AX_ROLE_BANNER;
+ break;
+ case ui::AX_ROLE_BLOCKQUOTE:
+ message_id = IDS_AX_ROLE_BLOCKQUOTE;
+ break;
+ case ui::AX_ROLE_BUSY_INDICATOR:
+ message_id = IDS_AX_ROLE_BUSY_INDICATOR;
+ break;
+ case ui::AX_ROLE_BUTTON:
+ message_id = IDS_AX_ROLE_BUTTON;
+ break;
+ case ui::AX_ROLE_BUTTON_DROP_DOWN:
+ message_id = IDS_AX_ROLE_BUTTON_DROP_DOWN;
+ break;
+ case ui::AX_ROLE_CANVAS:
+ // No role description.
+ break;
+ case ui::AX_ROLE_CAPTION:
+ // No role description.
+ break;
+ case ui::AX_ROLE_CELL:
+ message_id = IDS_AX_ROLE_CELL;
+ break;
+ case ui::AX_ROLE_CHECK_BOX:
+ message_id = IDS_AX_ROLE_CHECK_BOX;
+ break;
+ case ui::AX_ROLE_CLIENT:
+ // No role description.
+ break;
+ case ui::AX_ROLE_COLOR_WELL:
+ message_id = IDS_AX_ROLE_COLOR_WELL;
+ break;
+ case ui::AX_ROLE_COLUMN_HEADER:
+ message_id = IDS_AX_ROLE_COLUMN_HEADER;
+ break;
+ case ui::AX_ROLE_COLUMN:
+ // No role description.
+ break;
+ case ui::AX_ROLE_COMBO_BOX:
+ message_id = IDS_AX_ROLE_COMBO_BOX;
+ break;
+ case ui::AX_ROLE_COMPLEMENTARY:
+ message_id = IDS_AX_ROLE_COMPLEMENTARY;
+ break;
+ case ui::AX_ROLE_CONTENT_INFO:
+ message_id = IDS_AX_ROLE_CONTENT_INFO;
+ break;
+ case ui::AX_ROLE_DATE:
+ message_id = IDS_AX_ROLE_DATE;
+ break;
+ case ui::AX_ROLE_DATE_TIME:
+ message_id = IDS_AX_ROLE_DATE_TIME;
+ break;
+ case ui::AX_ROLE_DEFINITION:
+ message_id = IDS_AX_ROLE_DEFINITION;
+ break;
+ case ui::AX_ROLE_DESCRIPTION_LIST_DETAIL:
+ message_id = IDS_AX_ROLE_DEFINITION;
+ break;
+ case ui::AX_ROLE_DESCRIPTION_LIST:
+ // No role description.
+ break;
+ case ui::AX_ROLE_DESCRIPTION_LIST_TERM:
+ // No role description.
+ break;
+ case ui::AX_ROLE_DESKTOP:
+ // No role description.
+ break;
+ case ui::AX_ROLE_DETAILS:
+ // No role description.
+ break;
+ case ui::AX_ROLE_DIALOG:
+ message_id = IDS_AX_ROLE_DIALOG;
+ break;
+ case ui::AX_ROLE_DIRECTORY:
+ message_id = IDS_AX_ROLE_DIRECTORY;
+ break;
+ case ui::AX_ROLE_DISCLOSURE_TRIANGLE:
+ message_id = IDS_AX_ROLE_DISCLOSURE_TRIANGLE;
+ break;
+ case ui::AX_ROLE_DIV:
+ // No role description.
+ break;
+ case ui::AX_ROLE_DOCUMENT:
+ message_id = IDS_AX_ROLE_DOCUMENT;
+ break;
+ case ui::AX_ROLE_EMBEDDED_OBJECT:
+ message_id = IDS_AX_ROLE_EMBEDDED_OBJECT;
+ break;
+ case ui::AX_ROLE_FIGCAPTION:
+ // No role description.
+ break;
+ case ui::AX_ROLE_FIGURE:
+ message_id = IDS_AX_ROLE_GRAPHIC;
+ break;
+ case ui::AX_ROLE_FOOTER:
+ message_id = IDS_AX_ROLE_FOOTER;
+ break;
+ case ui::AX_ROLE_FORM:
+ // No role description.
+ break;
+ case ui::AX_ROLE_GRID:
+ message_id = IDS_AX_ROLE_TABLE;
+ break;
+ case ui::AX_ROLE_GROUP:
+ // No role description.
+ break;
+ case ui::AX_ROLE_HEADING:
+ // Note that code above this switch statement handles headings with
+ // a level, returning a string like "heading level 1", etc.
+ message_id = IDS_AX_ROLE_HEADING;
+ break;
+ case ui::AX_ROLE_IFRAME:
+ // No role description.
+ break;
+ case ui::AX_ROLE_IFRAME_PRESENTATIONAL:
+ // No role description.
+ break;
+ case ui::AX_ROLE_IGNORED:
+ // No role description.
+ break;
+ case ui::AX_ROLE_IMAGE_MAP_LINK:
+ message_id = IDS_AX_ROLE_LINK;
+ break;
+ case ui::AX_ROLE_IMAGE_MAP:
+ message_id = IDS_AX_ROLE_GRAPHIC;
+ break;
+ case ui::AX_ROLE_IMAGE:
+ message_id = IDS_AX_ROLE_GRAPHIC;
+ break;
+ case ui::AX_ROLE_INLINE_TEXT_BOX:
+ // No role description.
+ break;
+ case ui::AX_ROLE_INPUT_TIME:
+ message_id = IDS_AX_ROLE_INPUT_TIME;
+ break;
+ case ui::AX_ROLE_LABEL_TEXT:
+ // No role description.
+ break;
+ case ui::AX_ROLE_LEGEND:
+ // No role description.
+ break;
+ case ui::AX_ROLE_LINE_BREAK:
+ // No role description.
+ break;
+ case ui::AX_ROLE_LINK:
+ message_id = IDS_AX_ROLE_LINK;
+ break;
+ case ui::AX_ROLE_LIST_BOX_OPTION:
+ // No role description.
+ break;
+ case ui::AX_ROLE_LIST_BOX:
+ message_id = IDS_AX_ROLE_LIST_BOX;
+ break;
+ case ui::AX_ROLE_LIST_ITEM:
+ // No role description.
+ break;
+ case ui::AX_ROLE_LIST_MARKER:
+ // No role description.
+ break;
+ case ui::AX_ROLE_LIST:
+ // No role description.
+ break;
+ case ui::AX_ROLE_LOCATION_BAR:
+ // No role description.
+ break;
+ case ui::AX_ROLE_LOG:
+ message_id = IDS_AX_ROLE_LOG;
+ break;
+ case ui::AX_ROLE_MAIN:
+ message_id = IDS_AX_ROLE_MAIN_CONTENT;
+ break;
+ case ui::AX_ROLE_MARK:
+ message_id = IDS_AX_ROLE_MARK;
+ break;
+ case ui::AX_ROLE_MARQUEE:
+ message_id = IDS_AX_ROLE_MARQUEE;
+ break;
+ case ui::AX_ROLE_MATH:
+ message_id = IDS_AX_ROLE_MATH;
+ break;
+ case ui::AX_ROLE_MENU_BAR:
+ message_id = IDS_AX_ROLE_MENU_BAR;
+ break;
+ case ui::AX_ROLE_MENU_BUTTON:
+ message_id = IDS_AX_ROLE_MENU_BUTTON;
+ break;
+ case ui::AX_ROLE_MENU_ITEM:
+ message_id = IDS_AX_ROLE_MENU_ITEM;
+ break;
+ case ui::AX_ROLE_MENU_ITEM_CHECK_BOX:
+ message_id = IDS_AX_ROLE_CHECK_BOX;
+ break;
+ case ui::AX_ROLE_MENU_ITEM_RADIO:
+ message_id = IDS_AX_ROLE_RADIO;
+ break;
+ case ui::AX_ROLE_MENU_LIST_OPTION:
+ // No role description.
+ break;
+ case ui::AX_ROLE_MENU_LIST_POPUP:
+ // No role description.
+ break;
+ case ui::AX_ROLE_MENU:
+ message_id = IDS_AX_ROLE_MENU;
+ break;
+ case ui::AX_ROLE_METER:
+ message_id = IDS_AX_ROLE_METER;
+ break;
+ case ui::AX_ROLE_NAVIGATION:
+ message_id = IDS_AX_ROLE_NAVIGATIONAL_LINK;
+ break;
+ case ui::AX_ROLE_NOTE:
+ message_id = IDS_AX_ROLE_NOTE;
+ break;
+ case ui::AX_ROLE_OUTLINE:
+ message_id = IDS_AX_ROLE_OUTLINE;
+ break;
+ case ui::AX_ROLE_PANE:
+ // No role description.
+ break;
+ case ui::AX_ROLE_PARAGRAPH:
+ // No role description.
+ break;
+ case ui::AX_ROLE_POP_UP_BUTTON:
+ message_id = IDS_AX_ROLE_POP_UP_BUTTON;
+ break;
+ case ui::AX_ROLE_PRE:
+ // No role description.
+ break;
+ case ui::AX_ROLE_PRESENTATIONAL:
+ // No role description.
+ break;
+ case ui::AX_ROLE_PROGRESS_INDICATOR:
+ message_id = IDS_AX_ROLE_PROGRESS_INDICATOR;
+ break;
+ case ui::AX_ROLE_RADIO_BUTTON:
+ message_id = IDS_AX_ROLE_RADIO;
+ break;
+ case ui::AX_ROLE_RADIO_GROUP:
+ message_id = IDS_AX_ROLE_RADIO_GROUP;
+ break;
+ case ui::AX_ROLE_REGION:
+ message_id = IDS_AX_ROLE_REGION;
+ break;
+ case ui::AX_ROLE_ROOT_WEB_AREA:
+ // No role description.
+ break;
+ case ui::AX_ROLE_ROW_HEADER:
+ message_id = IDS_AX_ROLE_ROW_HEADER;
+ break;
+ case ui::AX_ROLE_ROW:
+ // No role description.
+ break;
+ case ui::AX_ROLE_RUBY:
+ // No role description.
+ break;
+ case ui::AX_ROLE_RULER:
+ message_id = IDS_AX_ROLE_RULER;
+ break;
+ case ui::AX_ROLE_SVG_ROOT:
+ message_id = IDS_AX_ROLE_GRAPHIC;
+ break;
+ case ui::AX_ROLE_SCROLL_AREA:
+ // No role description.
+ break;
+ case ui::AX_ROLE_SCROLL_BAR:
+ message_id = IDS_AX_ROLE_SCROLL_BAR;
+ break;
+ case ui::AX_ROLE_SEAMLESS_WEB_AREA:
+ // No role description.
+ break;
+ case ui::AX_ROLE_SEARCH:
+ message_id = IDS_AX_ROLE_SEARCH;
+ break;
+ case ui::AX_ROLE_SEARCH_BOX:
+ message_id = IDS_AX_ROLE_SEARCH_BOX;
+ break;
+ case ui::AX_ROLE_SLIDER:
+ message_id = IDS_AX_ROLE_SLIDER;
+ break;
+ case ui::AX_ROLE_SLIDER_THUMB:
+ // No role description.
+ break;
+ case ui::AX_ROLE_SPIN_BUTTON_PART:
+ // No role description.
+ break;
+ case ui::AX_ROLE_SPIN_BUTTON:
+ message_id = IDS_AX_ROLE_SPIN_BUTTON;
+ break;
+ case ui::AX_ROLE_SPLITTER:
+ message_id = IDS_AX_ROLE_SPLITTER;
+ break;
+ case ui::AX_ROLE_STATIC_TEXT:
+ // No role description.
+ break;
+ case ui::AX_ROLE_STATUS:
+ message_id = IDS_AX_ROLE_STATUS;
+ break;
+ case ui::AX_ROLE_SWITCH:
+ message_id = IDS_AX_ROLE_SWITCH;
+ break;
+ case ui::AX_ROLE_TAB_GROUP:
+ // No role description.
+ break;
+ case ui::AX_ROLE_TAB_LIST:
+ message_id = IDS_AX_ROLE_TAB_LIST;
+ break;
+ case ui::AX_ROLE_TAB_PANEL:
+ message_id = IDS_AX_ROLE_TAB_PANEL;
+ break;
+ case ui::AX_ROLE_TAB:
+ message_id = IDS_AX_ROLE_TAB;
+ break;
+ case ui::AX_ROLE_TABLE_HEADER_CONTAINER:
+ // No role description.
+ break;
+ case ui::AX_ROLE_TABLE:
+ message_id = IDS_AX_ROLE_TABLE;
+ break;
+ case ui::AX_ROLE_TEXT_FIELD:
+ // No role description.
+ break;
+ case ui::AX_ROLE_TIME:
+ message_id = IDS_AX_ROLE_TIME;
+ break;
+ case ui::AX_ROLE_TIMER:
+ message_id = IDS_AX_ROLE_TIMER;
+ break;
+ case ui::AX_ROLE_TITLE_BAR:
+ // No role description.
+ break;
+ case ui::AX_ROLE_TOGGLE_BUTTON:
+ message_id = IDS_AX_ROLE_TOGGLE_BUTTON;
+ break;
+ case ui::AX_ROLE_TOOLBAR:
+ message_id = IDS_AX_ROLE_TOOLBAR;
+ break;
+ case ui::AX_ROLE_TREE_GRID:
+ message_id = IDS_AX_ROLE_TREE_GRID;
+ break;
+ case ui::AX_ROLE_TREE_ITEM:
+ message_id = IDS_AX_ROLE_TREE_ITEM;
+ break;
+ case ui::AX_ROLE_TREE:
+ message_id = IDS_AX_ROLE_TREE;
+ break;
+ case ui::AX_ROLE_UNKNOWN:
+ // No role description.
+ break;
+ case ui::AX_ROLE_TOOLTIP:
+ message_id = IDS_AX_ROLE_TOOLTIP;
+ break;
+ case ui::AX_ROLE_WEB_AREA:
+ // No role description.
+ break;
+ case ui::AX_ROLE_WEB_VIEW:
+ // No role description.
+ break;
+ case ui::AX_ROLE_WINDOW:
+ // No role description.
+ break;
+ }
+
+ if (message_id != -1)
+ return content_client->GetLocalizedString(message_id);
+
+ return base::string16();
+}
+
int BrowserAccessibilityAndroid::GetItemIndex() const {
int index = 0;
switch (GetRole()) {
@@ -526,13 +942,13 @@ bool BrowserAccessibilityAndroid::Scroll(int direction) const {
// Figure out the bounding box of the visible portion of this scrollable
// view so we know how much to scroll by.
gfx::Rect bounds;
- if (GetRole() == ui::AX_ROLE_ROOT_WEB_AREA) {
+ if (GetRole() == ui::AX_ROLE_ROOT_WEB_AREA && !GetParent()) {
// If this is the root web area, use the bounds of the view to determine
// how big one page is.
if (!manager()->delegate())
return false;
bounds = manager()->delegate()->AccessibilityGetViewBounds();
- } else if (GetRole() == ui::AX_ROLE_WEB_AREA) {
+ } else if (GetRole() == ui::AX_ROLE_ROOT_WEB_AREA && GetParent()) {
// If this is a web area inside of an iframe, try to use the bounds of
// the containing element.
BrowserAccessibility* parent = GetParent();
@@ -924,9 +1340,8 @@ bool BrowserAccessibilityAndroid::HasOnlyTextAndImageChildren() const {
}
bool BrowserAccessibilityAndroid::IsIframe() const {
- base::string16 html_tag = GetString16Attribute(
- ui::AX_ATTR_HTML_TAG);
- return html_tag == base::ASCIIToUTF16("iframe");
+ return (GetRole() == ui::AX_ROLE_IFRAME ||
+ GetRole() == ui::AX_ROLE_IFRAME_PRESENTATIONAL);
}
void BrowserAccessibilityAndroid::OnDataChanged() {
diff --git a/chromium/content/browser/accessibility/browser_accessibility_android.h b/chromium/content/browser/accessibility/browser_accessibility_android.h
index 66055538087..56a5b63ea67 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_android.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_android.h
@@ -25,7 +25,7 @@ class CONTENT_EXPORT BrowserAccessibilityAndroid : public BrowserAccessibility {
bool IsCheckable() const;
bool IsChecked() const;
- bool IsClickable() const;
+ bool IsClickable() const override;
bool IsCollection() const;
bool IsCollectionItem() const;
bool IsContentInvalid() const;
@@ -52,6 +52,8 @@ class CONTENT_EXPORT BrowserAccessibilityAndroid : public BrowserAccessibility {
const char* GetClassName() const;
base::string16 GetText() const override;
+ base::string16 GetRoleDescription() const;
+
int GetItemIndex() const;
int GetItemCount() const;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_auralinux.cc b/chromium/content/browser/accessibility/browser_accessibility_auralinux.cc
index 880839e047a..231a3dd7cd4 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_auralinux.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_auralinux.cc
@@ -23,6 +23,18 @@ static BrowserAccessibilityAuraLinux* ToBrowserAccessibilityAuraLinux(
return atk_object->m_object;
}
+const BrowserAccessibilityAuraLinux* ToBrowserAccessibilityAuraLinux(
+ const BrowserAccessibility* obj) {
+ DCHECK(!obj || obj->IsNative());
+ return static_cast<const BrowserAccessibilityAuraLinux*>(obj);
+}
+
+BrowserAccessibilityAuraLinux* ToBrowserAccessibilityAuraLinux(
+ BrowserAccessibility* obj) {
+ DCHECK(!obj || obj->IsNative());
+ return static_cast<BrowserAccessibilityAuraLinux*>(obj);
+}
+
//
// AtkAction interface.
//
@@ -140,7 +152,7 @@ static AtkObject* browser_accessibility_accessible_at_point(
return NULL;
AtkObject* atk_result =
- result->ToBrowserAccessibilityAuraLinux()->GetAtkObject();
+ ToBrowserAccessibilityAuraLinux(result)->GetAtkObject();
g_object_ref(atk_result);
return atk_result;
}
@@ -177,7 +189,7 @@ static gboolean browser_accessibility_grab_focus(AtkComponent* atk_component) {
if (!obj)
return false;
- obj->manager()->SetFocus(obj, true);
+ obj->manager()->SetFocus(*obj);
return true;
}
@@ -474,7 +486,7 @@ static AtkObject* browser_accessibility_get_parent(AtkObject* atk_object) {
if (!obj)
return NULL;
if (obj->GetParent())
- return obj->GetParent()->ToBrowserAccessibilityAuraLinux()->GetAtkObject();
+ return ToBrowserAccessibilityAuraLinux(obj->GetParent())->GetAtkObject();
BrowserAccessibilityManagerAuraLinux* manager =
static_cast<BrowserAccessibilityManagerAuraLinux*>(obj->manager());
@@ -500,9 +512,8 @@ static AtkObject* browser_accessibility_ref_child(AtkObject* atk_object,
if (index < 0 || index >= static_cast<gint>(obj->PlatformChildCount()))
return NULL;
- AtkObject* result = obj->InternalGetChild(index)
- ->ToBrowserAccessibilityAuraLinux()
- ->GetAtkObject();
+ AtkObject* result = ToBrowserAccessibilityAuraLinux(
+ obj->InternalGetChild(index))->GetAtkObject();
g_object_ref(result);
return result;
}
@@ -539,7 +550,7 @@ static AtkStateSet* browser_accessibility_ref_state_set(AtkObject* atk_object) {
if (state & (1 << ui::AX_STATE_FOCUSABLE))
atk_state_set_add_state(state_set, ATK_STATE_FOCUSABLE);
- if (obj->manager()->GetFocus(NULL) == obj)
+ if (obj->manager()->GetFocus() == obj)
atk_state_set_add_state(state_set, ATK_STATE_FOCUSED);
if (state & (1 << ui::AX_STATE_ENABLED))
atk_state_set_add_state(state_set, ATK_STATE_ENABLED);
@@ -735,16 +746,6 @@ BrowserAccessibility* BrowserAccessibility::Create() {
return new BrowserAccessibilityAuraLinux();
}
-const BrowserAccessibilityAuraLinux*
-BrowserAccessibility::ToBrowserAccessibilityAuraLinux() const {
- return static_cast<const BrowserAccessibilityAuraLinux*>(this);
-}
-
-BrowserAccessibilityAuraLinux*
-BrowserAccessibility::ToBrowserAccessibilityAuraLinux() {
- return static_cast<BrowserAccessibilityAuraLinux*>(this);
-}
-
BrowserAccessibilityAuraLinux::BrowserAccessibilityAuraLinux()
: atk_object_(NULL) {
}
@@ -782,7 +783,7 @@ void BrowserAccessibilityAuraLinux::OnDataChanged() {
if (this->GetParent()) {
atk_object_set_parent(
atk_object_,
- this->GetParent()->ToBrowserAccessibilityAuraLinux()->GetAtkObject());
+ ToBrowserAccessibilityAuraLinux(this->GetParent())->GetAtkObject());
}
}
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_auralinux.h b/chromium/content/browser/accessibility/browser_accessibility_auralinux.h
index 43a9c3f16b0..773e79fbd31 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_auralinux.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_auralinux.h
@@ -10,6 +10,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "content/browser/accessibility/browser_accessibility.h"
+#include "content/common/content_export.h"
namespace content {
@@ -88,6 +89,12 @@ class BrowserAccessibilityAuraLinux : public BrowserAccessibility {
DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityAuraLinux);
};
+CONTENT_EXPORT const BrowserAccessibilityAuraLinux*
+ToBrowserAccessibilityAuraLinux(const BrowserAccessibility* obj);
+
+CONTENT_EXPORT BrowserAccessibilityAuraLinux* ToBrowserAccessibilityAuraLinux(
+ BrowserAccessibility* obj);
+
} // namespace content
#endif // CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_AURALINUX_H_
diff --git a/chromium/content/browser/accessibility/browser_accessibility_cocoa.h b/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
index 6c5a3e6f0c1..992373453e6 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_cocoa.h
@@ -22,8 +22,8 @@
}
// This creates a cocoa browser accessibility object around
-// the cross platform BrowserAccessibility object, which can't be null.
-- (id)initWithObject:(content::BrowserAccessibility*)accessibility;
+// the cross platform BrowserAccessibility object, which can't be nullptr.
+- (instancetype)initWithObject:(content::BrowserAccessibility*)accessibility;
// Clear this object's pointer to the wrapped BrowserAccessibility object
// because the wrapped object has been deleted, but this object may
@@ -39,7 +39,7 @@
// Convenience method to determine if this object should expose its
// accessible name in AXValue (as opposed to AXTitle/AXDescription).
-- (bool)shouldExposeNameInAXValue;
+- (BOOL)shouldExposeNameInAXValue;
// Convenience method to get the BrowserAccessibilityDelegate from
// the manager.
@@ -48,6 +48,9 @@
// Get the BrowserAccessibility that this object wraps.
- (content::BrowserAccessibility*)browserAccessibility;
+// Determines if this object is alive, i.e. it hasn't been detached.
+- (BOOL)instanceActive;
+
// Convert the local objet's origin to a global point.
- (NSPoint)pointInScreen:(NSPoint)origin
size:(NSSize)size;
@@ -61,16 +64,16 @@
// Returns the requested text range from this object's value attribute.
- (NSString*)valueForRange:(NSRange)range;
-// Internally-used method.
+// Internally-used property.
@property(nonatomic, readonly) NSPoint origin;
-// Children is an array of BrowserAccessibility objects, representing
-// the accessibility children of this object.
@property(nonatomic, readonly) NSString* accessKey;
@property(nonatomic, readonly) NSNumber* ariaAtomic;
@property(nonatomic, readonly) NSNumber* ariaBusy;
@property(nonatomic, readonly) NSString* ariaLive;
+@property(nonatomic, readonly) NSNumber* ariaPosInSet;
@property(nonatomic, readonly) NSString* ariaRelevant;
+@property(nonatomic, readonly) NSNumber* ariaSetSize;
@property(nonatomic, readonly) NSArray* children;
@property(nonatomic, readonly) NSArray* columns;
@property(nonatomic, readonly) NSArray* columnHeaders;
@@ -80,15 +83,24 @@
@property(nonatomic, readonly) id disclosedByRow;
@property(nonatomic, readonly) NSNumber* disclosureLevel;
@property(nonatomic, readonly) id disclosedRows;
+@property(nonatomic, readonly) NSString* dropEffects;
@property(nonatomic, readonly) NSNumber* enabled;
+// Returns a text marker that points to the last character in the document that
+// can be selected with Voiceover.
+@property(nonatomic, readonly) id endTextMarker;
+@property(nonatomic, readonly) NSNumber* expanded;
@property(nonatomic, readonly) NSNumber* focused;
+@property(nonatomic, readonly) NSNumber* grabbed;
+@property(nonatomic, readonly) id header;
@property(nonatomic, readonly) NSString* help;
// isIgnored returns whether or not the accessibility object
// should be ignored by the accessibility hierarchy.
@property(nonatomic, readonly, getter=isIgnored) BOOL ignored;
// Index of a row, column, or tree item.
@property(nonatomic, readonly) NSNumber* index;
+@property(nonatomic, readonly) NSNumber* insertionPointLineNumber;
@property(nonatomic, readonly) NSString* invalid;
+@property(nonatomic, readonly) NSNumber* isMultiSelectable;
@property(nonatomic, readonly) NSString* placeholderValue;
@property(nonatomic, readonly) NSNumber* loaded;
@property(nonatomic, readonly) NSNumber* loadingProgress;
@@ -106,9 +118,17 @@
@property(nonatomic, readonly) NSArray* rowHeaders;
@property(nonatomic, readonly) NSValue* rowIndexRange;
@property(nonatomic, readonly) NSArray* rows;
+// The object is selected as a whole.
+@property(nonatomic, readonly) NSNumber* selected;
@property(nonatomic, readonly) NSArray* selectedChildren;
-// The size of this object.
+@property(nonatomic, readonly) NSString* selectedText;
+@property(nonatomic, readonly) NSValue* selectedTextRange;
+@property(nonatomic, readonly) id selectedTextMarkerRange;
@property(nonatomic, readonly) NSValue* size;
+@property(nonatomic, readonly) NSString* sortDirection;
+// Returns a text marker that points to the first character in the document that
+// can be selected with Voiceover.
+@property(nonatomic, readonly) id startTextMarker;
// A string indicating the subrole of this object as far as accessibility
// is concerned.
@property(nonatomic, readonly) NSString* subrole;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
index 78c8c0150fb..1ae72bd2e30 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -10,22 +10,21 @@
#include <map>
+#include "base/mac/foundation_util.h"
+#include "base/mac/scoped_cftyperef.h"
#include "base/strings/string16.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "content/app/strings/grit/content_strings.h"
+#include "content/browser/accessibility/browser_accessibility_mac.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/accessibility/browser_accessibility_manager_mac.h"
#include "content/browser/accessibility/one_shot_accessibility_tree_search.h"
#include "content/public/common/content_client.h"
+#include "third_party/skia/include/core/SkColor.h"
#import "ui/accessibility/platform/ax_platform_node_mac.h"
-// See http://openradar.appspot.com/9896491. This SPI has been tested on 10.5,
-// 10.6, and 10.7. It allows accessibility clients to observe events posted on
-// this object.
-extern "C" void NSAccessibilityUnregisterUniqueIdForUIElement(id element);
-
-using ui::AXNodeData;
+using content::AXTreeIDRegistry;
using content::AccessibilityMatchPredicate;
using content::BrowserAccessibility;
using content::BrowserAccessibilityDelegate;
@@ -33,13 +32,186 @@ using content::BrowserAccessibilityManager;
using content::BrowserAccessibilityManagerMac;
using content::ContentClient;
using content::OneShotAccessibilityTreeSearch;
-typedef ui::AXStringAttribute StringAttribute;
+using ui::AXNodeData;
+using StringAttribute = ui::AXStringAttribute;
+using AXTextMarkerRef = CFTypeRef;
+using AXTextMarkerRangeRef = CFTypeRef;
namespace {
+// Private WebKit accessibility attributes.
+NSString* const NSAccessibilityARIAAtomicAttribute = @"AXARIAAtomic";
+NSString* const NSAccessibilityARIABusyAttribute = @"AXARIABusy";
+NSString* const NSAccessibilityARIALiveAttribute = @"AXARIALive";
+NSString* const NSAccessibilityARIAPosInSetAttribute = @"AXARIAPosInSet";
+NSString* const NSAccessibilityARIARelevantAttribute = @"AXARIARelevant";
+NSString* const NSAccessibilityARIASetSizeAttribute = @"AXARIASetSize";
+NSString* const NSAccessibilityAccessKeyAttribute = @"AXAccessKey";
+NSString* const NSAccessibilityDropEffectsAttribute = @"AXDropEffects";
+NSString* const NSAccessibilityGrabbedAttribute = @"AXGrabbed";
+NSString* const NSAccessibilityInvalidAttribute = @"AXInvalid";
+NSString* const NSAccessibilityIsMultiSelectableAttribute =
+ @"AXIsMultiSelectable";
+NSString* const NSAccessibilityLoadingProgressAttribute = @"AXLoadingProgress";
+NSString* const NSAccessibilityRequiredAttribute = @"AXRequired";
+NSString* const
+ NSAccessibilityUIElementCountForSearchPredicateParameterizedAttribute =
+ @"AXUIElementCountForSearchPredicate";
+NSString* const
+ NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute =
+ @"AXUIElementsForSearchPredicate";
+NSString* const NSAccessibilityVisitedAttribute = @"AXVisited";
+
+// Private attributes for text markers.
+NSString* const NSAccessibilityStartTextMarkerAttribute = @"AXStartTextMarker";
+NSString* const NSAccessibilityEndTextMarkerAttribute = @"AXEndTextMarker";
+NSString* const NSAccessibilitySelectedTextMarkerRangeAttribute =
+ @"AXSelectedTextMarkerRange";
+NSString* const NSAccessibilityTextMarkerIsValidParameterizedAttribute =
+ @"AXTextMarkerIsValid";
+NSString* const NSAccessibilityIndexForTextMarkerParameterizedAttribute =
+ @"AXIndexForTextMarker";
+NSString* const NSAccessibilityTextMarkerForIndexParameterizedAttribute =
+ @"AXTextMarkerForIndex";
+NSString* const NSAccessibilityEndTextMarkerForBoundsParameterizedAttribute =
+ @"AXEndTextMarkerForBounds";
+NSString* const NSAccessibilityStartTextMarkerForBoundsParameterizedAttribute =
+ @"AXStartTextMarkerForBounds";
+NSString* const
+ NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute =
+ @"AXLineTextMarkerRangeForTextMarker";
+NSString* const NSAccessibilitySelectTextWithCriteriaParameterizedAttribute =
+ @"AXSelectTextWithCriteria";
+
+// Actions.
+NSString* const NSAccessibilityScrollToVisibleAction = @"AXScrollToVisible";
+
+// A mapping from an accessibility attribute to its method name.
+NSDictionary* attributeToMethodNameMap = nil;
+
+struct AXTextMarkerData {
+ AXTreeIDRegistry::AXTreeID tree_id;
+ int32_t node_id;
+ int offset;
+};
+
// VoiceOver uses -1 to mean "no limit" for AXResultsLimit.
const int kAXResultsLimitNoLimit = -1;
+extern "C" {
+
+// See http://openradar.appspot.com/9896491. This SPI has been tested on 10.5,
+// 10.6, and 10.7. It allows accessibility clients to observe events posted on
+// this object.
+void NSAccessibilityUnregisterUniqueIdForUIElement(id element);
+
+// The following are private accessibility APIs required for cursor navigation
+// and text selection. VoiceOver started relying on them in Mac OS X 10.11.
+#if !defined(MAC_OS_X_VERSION_10_11) || \
+ MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_11
+
+AXTextMarkerRef AXTextMarkerCreate(CFAllocatorRef allocator,
+ const UInt8* bytes,
+ CFIndex length);
+
+const UInt8* AXTextMarkerGetBytePtr(AXTextMarkerRef text_marker);
+
+AXTextMarkerRangeRef AXTextMarkerRangeCreate(CFAllocatorRef allocator,
+ AXTextMarkerRef start_marker,
+ AXTextMarkerRef end_marker);
+
+AXTextMarkerRef AXTextMarkerRangeCopyStartMarker(
+ AXTextMarkerRangeRef text_marker_range);
+
+AXTextMarkerRef AXTextMarkerRangeCopyEndMarker(
+ AXTextMarkerRangeRef text_marker_range);
+
+#endif // MAC_OS_X_VERSION_10_11
+
+} // extern "C"
+
+id CreateTextMarker(const BrowserAccessibility& object, int offset) {
+ AXTextMarkerData marker_data;
+ marker_data.tree_id = object.manager() ? object.manager()->ax_tree_id() : -1;
+ marker_data.node_id = object.GetId();
+ marker_data.offset = offset;
+ return (id)base::mac::CFTypeRefToNSObjectAutorelease(AXTextMarkerCreate(
+ kCFAllocatorDefault, reinterpret_cast<const UInt8*>(&marker_data),
+ sizeof(marker_data)));
+}
+
+id CreateTextMarkerRange(const BrowserAccessibility& start_object,
+ int start_offset,
+ const BrowserAccessibility& end_object,
+ int end_offset) {
+ id start_marker = CreateTextMarker(start_object, start_offset);
+ id end_marker = CreateTextMarker(end_object, end_offset);
+ return (id)base::mac::CFTypeRefToNSObjectAutorelease(
+ AXTextMarkerRangeCreate(kCFAllocatorDefault, start_marker, end_marker));
+}
+
+bool GetTextMarkerData(AXTextMarkerRef text_marker,
+ BrowserAccessibility** object,
+ int* offset) {
+ DCHECK(text_marker);
+ DCHECK(object && offset);
+ auto marker_data = reinterpret_cast<const AXTextMarkerData*>(
+ AXTextMarkerGetBytePtr(text_marker));
+ if (!marker_data)
+ return false;
+
+ const BrowserAccessibilityManager* manager =
+ BrowserAccessibilityManager::FromID(marker_data->tree_id);
+ if (!manager)
+ return false;
+
+ *object = manager->GetFromID(marker_data->node_id);
+ if (!*object)
+ return false;
+
+ *offset = marker_data->offset;
+ if (*offset < 0)
+ return false;
+
+ return true;
+}
+
+bool GetTextMarkerRange(AXTextMarkerRangeRef marker_range,
+ BrowserAccessibility** start_object,
+ int* start_offset,
+ BrowserAccessibility** end_object,
+ int* end_offset) {
+ DCHECK(marker_range);
+ DCHECK(start_object && start_offset);
+ DCHECK(end_object && end_offset);
+
+ base::ScopedCFTypeRef<AXTextMarkerRef> start_marker(
+ AXTextMarkerRangeCopyStartMarker(marker_range));
+ base::ScopedCFTypeRef<AXTextMarkerRef> end_marker(
+ AXTextMarkerRangeCopyEndMarker(marker_range));
+ if (!start_marker.get() || !end_marker.get())
+ return false;
+
+ return GetTextMarkerData(start_marker.get(), start_object, start_offset) &&
+ GetTextMarkerData(end_marker.get(), end_object, end_offset);
+}
+
+NSString* GetTextForTextMarkerRange(AXTextMarkerRangeRef marker_range) {
+ BrowserAccessibility* start_object;
+ BrowserAccessibility* end_object;
+ int start_offset, end_offset;
+ if (!GetTextMarkerRange(marker_range, &start_object, &start_offset,
+ &end_object, &end_offset)) {
+ return nil;
+ }
+ DCHECK(start_object && end_object);
+ DCHECK_GE(start_offset, 0);
+ DCHECK_GE(end_offset, 0);
+
+ return base::SysUTF16ToNSString(BrowserAccessibilityManager::GetTextForRange(
+ *start_object, start_offset, *end_object, end_offset));
+}
+
// Returns an autoreleased copy of the AXNodeData's attribute.
NSString* NSStringForStringAttribute(
BrowserAccessibility* browserAccessibility,
@@ -54,9 +226,6 @@ bool GetState(BrowserAccessibility* accessibility, ui::AXState state) {
return ((accessibility->GetState() >> state) & 1);
}
-// A mapping from an accessibility attribute to its method name.
-NSDictionary* attributeToMethodNameMap = nil;
-
// Given a search key provided to AXUIElementCountForSearchPredicate or
// AXUIElementsForSearchPredicate, return a predicate that can be added
// to OneShotAccessibilityTreeSearch.
@@ -65,39 +234,19 @@ AccessibilityMatchPredicate PredicateForSearchKey(NSString* searchKey) {
return [](BrowserAccessibility* start, BrowserAccessibility* current) {
return true;
};
- } else if ([searchKey isEqualToString:@"AXBlockquoteSameLevelSearchKey"] ||
- [searchKey isEqualToString:@"AXBlockquoteSearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- // TODO(dmazzoni): implement the "same level" part.
- return current->GetRole() == ui::AX_ROLE_BLOCKQUOTE;
- };
+ } else if ([searchKey isEqualToString:@"AXBlockquoteSameLevelSearchKey"]) {
+ // TODO(dmazzoni): implement the "same level" part.
+ return content::AccessibilityBlockquotePredicate;
+ } else if ([searchKey isEqualToString:@"AXBlockquoteSearchKey"]) {
+ return content::AccessibilityBlockquotePredicate;
} else if ([searchKey isEqualToString:@"AXBoldFontSearchKey"]) {
- // TODO(dmazzoni): implement this.
- return nullptr;
+ return content::AccessibilityTextStyleBoldPredicate;
} else if ([searchKey isEqualToString:@"AXButtonSearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- return (current->GetRole() == ui::AX_ROLE_BUTTON ||
- current->GetRole() == ui::AX_ROLE_MENU_BUTTON ||
- current->GetRole() == ui::AX_ROLE_POP_UP_BUTTON ||
- current->GetRole() == ui::AX_ROLE_SWITCH ||
- current->GetRole() == ui::AX_ROLE_TOGGLE_BUTTON);
- };
+ return content::AccessibilityButtonPredicate;
} else if ([searchKey isEqualToString:@"AXCheckBoxSearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- return (current->GetRole() == ui::AX_ROLE_CHECK_BOX ||
- current->GetRole() == ui::AX_ROLE_MENU_ITEM_CHECK_BOX);
- };
+ return content::AccessibilityCheckboxPredicate;
} else if ([searchKey isEqualToString:@"AXControlSearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- if (current->IsControl())
- return true;
- if (current->HasState(ui::AX_STATE_FOCUSABLE) &&
- current->GetRole() != ui::AX_ROLE_IMAGE_MAP_LINK &&
- current->GetRole() != ui::AX_ROLE_LINK) {
- return true;
- }
- return false;
- };
+ return content::AccessibilityControlPredicate;
} else if ([searchKey isEqualToString:@"AXDifferentTypeSearchKey"]) {
return [](BrowserAccessibility* start, BrowserAccessibility* current) {
return current->GetRole() != start->GetRole();
@@ -109,102 +258,48 @@ AccessibilityMatchPredicate PredicateForSearchKey(NSString* searchKey) {
// TODO(dmazzoni): implement this.
return nullptr;
} else if ([searchKey isEqualToString:@"AXFrameSearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- if (current->IsWebAreaForPresentationalIframe())
- return false;
- if (!current->GetParent())
- return false;
- return (current->GetRole() == ui::AX_ROLE_WEB_AREA ||
- current->GetRole() == ui::AX_ROLE_ROOT_WEB_AREA);
- };
+ return content::AccessibilityFramePredicate;
} else if ([searchKey isEqualToString:@"AXGraphicSearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- return current->GetRole() == ui::AX_ROLE_IMAGE;
- };
+ return content::AccessibilityGraphicPredicate;
} else if ([searchKey isEqualToString:@"AXHeadingLevel1SearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- return (current->GetRole() == ui::AX_ROLE_HEADING &&
- current->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL) == 1);
- };
+ return content::AccessibilityH1Predicate;
} else if ([searchKey isEqualToString:@"AXHeadingLevel2SearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- return (current->GetRole() == ui::AX_ROLE_HEADING &&
- current->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL) == 2);
- };
+ return content::AccessibilityH2Predicate;
} else if ([searchKey isEqualToString:@"AXHeadingLevel3SearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- return (current->GetRole() == ui::AX_ROLE_HEADING &&
- current->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL) == 3);
- };
+ return content::AccessibilityH3Predicate;
} else if ([searchKey isEqualToString:@"AXHeadingLevel4SearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- return (current->GetRole() == ui::AX_ROLE_HEADING &&
- current->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL) == 4);
- };
+ return content::AccessibilityH4Predicate;
} else if ([searchKey isEqualToString:@"AXHeadingLevel5SearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- return (current->GetRole() == ui::AX_ROLE_HEADING &&
- current->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL) == 5);
- };
+ return content::AccessibilityH5Predicate;
} else if ([searchKey isEqualToString:@"AXHeadingLevel6SearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- return (current->GetRole() == ui::AX_ROLE_HEADING &&
- current->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL) == 6);
- };
+ return content::AccessibilityH6Predicate;
} else if ([searchKey isEqualToString:@"AXHeadingSameLevelSearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- return (current->GetRole() == ui::AX_ROLE_HEADING &&
- start->GetRole() == ui::AX_ROLE_HEADING &&
- (current->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL) ==
- start->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL)));
- };
+ return content::AccessibilityHeadingSameLevelPredicate;
} else if ([searchKey isEqualToString:@"AXHeadingSearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- return current->GetRole() == ui::AX_ROLE_HEADING;
- };
+ return content::AccessibilityHeadingPredicate;
} else if ([searchKey isEqualToString:@"AXHighlightedSearchKey"]) {
// TODO(dmazzoni): implement this.
return nullptr;
} else if ([searchKey isEqualToString:@"AXItalicFontSearchKey"]) {
- // TODO(dmazzoni): implement this.
- return nullptr;
+ return content::AccessibilityTextStyleItalicPredicate;
} else if ([searchKey isEqualToString:@"AXLandmarkSearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- return (current->GetRole() == ui::AX_ROLE_APPLICATION ||
- current->GetRole() == ui::AX_ROLE_BANNER ||
- current->GetRole() == ui::AX_ROLE_COMPLEMENTARY ||
- current->GetRole() == ui::AX_ROLE_CONTENT_INFO ||
- current->GetRole() == ui::AX_ROLE_FORM ||
- current->GetRole() == ui::AX_ROLE_MAIN ||
- current->GetRole() == ui::AX_ROLE_NAVIGATION ||
- current->GetRole() == ui::AX_ROLE_SEARCH);
- };
+ return content::AccessibilityLandmarkPredicate;
} else if ([searchKey isEqualToString:@"AXLinkSearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- return current->GetRole() == ui::AX_ROLE_LINK;
- };
+ return content::AccessibilityLinkPredicate;
} else if ([searchKey isEqualToString:@"AXListSearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- return current->GetRole() == ui::AX_ROLE_LIST;
- };
+ return content::AccessibilityListPredicate;
} else if ([searchKey isEqualToString:@"AXLiveRegionSearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- return current->HasStringAttribute(ui::AX_ATTR_LIVE_STATUS);
- };
+ return content::AccessibilityLiveRegionPredicate;
} else if ([searchKey isEqualToString:@"AXMisspelledWordSearchKey"]) {
// TODO(dmazzoni): implement this.
return nullptr;
} else if ([searchKey isEqualToString:@"AXOutlineSearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- return current->GetRole() == ui::AX_ROLE_TREE;
- };
+ return content::AccessibilityTreePredicate;
} else if ([searchKey isEqualToString:@"AXPlainTextSearchKey"]) {
// TODO(dmazzoni): implement this.
return nullptr;
} else if ([searchKey isEqualToString:@"AXRadioGroupSearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- return current->GetRole() == ui::AX_ROLE_RADIO_GROUP;
- };
+ return content::AccessibilityRadioGroupPredicate;
} else if ([searchKey isEqualToString:@"AXSameTypeSearchKey"]) {
return [](BrowserAccessibility* start, BrowserAccessibility* current) {
return current->GetRole() == start->GetRole();
@@ -217,33 +312,18 @@ AccessibilityMatchPredicate PredicateForSearchKey(NSString* searchKey) {
// TODO(dmazzoni): implement this.
return nullptr;
} else if ([searchKey isEqualToString:@"AXTableSameLevelSearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- // TODO(dmazzoni): implement the "same level" part.
- return current->GetRole() == ui::AX_ROLE_GRID ||
- current->GetRole() == ui::AX_ROLE_TABLE;
- };
+ // TODO(dmazzoni): implement the "same level" part.
+ return content::AccessibilityTablePredicate;
} else if ([searchKey isEqualToString:@"AXTableSearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- return current->GetRole() == ui::AX_ROLE_GRID ||
- current->GetRole() == ui::AX_ROLE_TABLE;
- };
+ return content::AccessibilityTablePredicate;
} else if ([searchKey isEqualToString:@"AXTextFieldSearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- return current->IsSimpleTextControl() || current->IsRichTextControl();
- };
+ return content::AccessibilityTextfieldPredicate;
} else if ([searchKey isEqualToString:@"AXUnderlineSearchKey"]) {
- // TODO(dmazzoni): implement this.
- return nullptr;
+ return content::AccessibilityTextStyleUnderlinePredicate;
} else if ([searchKey isEqualToString:@"AXUnvisitedLinkSearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- return (current->GetRole() == ui::AX_ROLE_LINK &&
- !current->HasState(ui::AX_STATE_VISITED));
- };
+ return content::AccessibilityUnvisitedLinkPredicate;
} else if ([searchKey isEqualToString:@"AXVisitedLinkSearchKey"]) {
- return [](BrowserAccessibility* start, BrowserAccessibility* current) {
- return (current->GetRole() == ui::AX_ROLE_LINK &&
- current->HasState(ui::AX_STATE_VISITED));
- };
+ return content::AccessibilityVisitedLinkPredicate;
}
return nullptr;
@@ -330,7 +410,7 @@ bool InitializeAccessibilityTreeSearch(
return true;
}
-} // namespace
+} // namespace
@implementation BrowserAccessibilityCocoa
@@ -339,67 +419,78 @@ bool InitializeAccessibilityTreeSearch(
NSString* attribute;
NSString* methodName;
} attributeToMethodNameContainer[] = {
- { NSAccessibilityChildrenAttribute, @"children" },
- { NSAccessibilityColumnsAttribute, @"columns" },
- { NSAccessibilityColumnHeaderUIElementsAttribute, @"columnHeaders" },
- { NSAccessibilityColumnIndexRangeAttribute, @"columnIndexRange" },
- { NSAccessibilityContentsAttribute, @"contents" },
- { NSAccessibilityDescriptionAttribute, @"description" },
- { NSAccessibilityDisclosingAttribute, @"disclosing" },
- { NSAccessibilityDisclosedByRowAttribute, @"disclosedByRow" },
- { NSAccessibilityDisclosureLevelAttribute, @"disclosureLevel" },
- { NSAccessibilityDisclosedRowsAttribute, @"disclosedRows" },
- { NSAccessibilityEnabledAttribute, @"enabled" },
- { NSAccessibilityExpandedAttribute, @"expanded" },
- { NSAccessibilityFocusedAttribute, @"focused" },
- { NSAccessibilityHeaderAttribute, @"header" },
- { NSAccessibilityHelpAttribute, @"help" },
- { NSAccessibilityIndexAttribute, @"index" },
- { NSAccessibilityLinkedUIElementsAttribute, @"linkedUIElements" },
- { NSAccessibilityMaxValueAttribute, @"maxValue" },
- { NSAccessibilityMinValueAttribute, @"minValue" },
- { NSAccessibilityNumberOfCharactersAttribute, @"numberOfCharacters" },
- { NSAccessibilityOrientationAttribute, @"orientation" },
- { NSAccessibilityParentAttribute, @"parent" },
- { NSAccessibilityPlaceholderValueAttribute, @"placeholderValue" },
- { NSAccessibilityPositionAttribute, @"position" },
- { NSAccessibilityRoleAttribute, @"role" },
- { NSAccessibilityRoleDescriptionAttribute, @"roleDescription" },
- { NSAccessibilityRowHeaderUIElementsAttribute, @"rowHeaders" },
- { NSAccessibilityRowIndexRangeAttribute, @"rowIndexRange" },
- { NSAccessibilityRowsAttribute, @"rows" },
- // TODO(aboxhall): expose NSAccessibilityServesAsTitleForUIElementsAttribute
- { NSAccessibilitySelectedChildrenAttribute, @"selectedChildren" },
- { NSAccessibilitySizeAttribute, @"size" },
- { NSAccessibilitySubroleAttribute, @"subrole" },
- { NSAccessibilityTabsAttribute, @"tabs" },
- { NSAccessibilityTitleAttribute, @"title" },
- { NSAccessibilityTitleUIElementAttribute, @"titleUIElement" },
- { NSAccessibilityTopLevelUIElementAttribute, @"window" },
- { NSAccessibilityURLAttribute, @"url" },
- { NSAccessibilityValueAttribute, @"value" },
- { NSAccessibilityValueDescriptionAttribute, @"valueDescription" },
- { NSAccessibilityVisibleCharacterRangeAttribute, @"visibleCharacterRange" },
- { NSAccessibilityVisibleCellsAttribute, @"visibleCells" },
- { NSAccessibilityVisibleChildrenAttribute, @"visibleChildren" },
- { NSAccessibilityVisibleColumnsAttribute, @"visibleColumns" },
- { NSAccessibilityVisibleRowsAttribute, @"visibleRows" },
- { NSAccessibilityWindowAttribute, @"window" },
- { @"AXAccessKey", @"accessKey" },
- { @"AXARIAAtomic", @"ariaAtomic" },
- { @"AXARIABusy", @"ariaBusy" },
- { @"AXARIALive", @"ariaLive" },
- { @"AXARIASetSize", @"ariaSetSize" },
- { @"AXARIAPosInSet", @"ariaPosInSet" },
- { @"AXARIARelevant", @"ariaRelevant" },
- { @"AXDropEffects", @"dropeffect" },
- { @"AXGrabbed", @"grabbed" },
- { @"AXInvalid", @"invalid" },
- { @"AXLoaded", @"loaded" },
- { @"AXLoadingProgress", @"loadingProgress" },
- { @"AXRequired", @"required" },
- { @"AXSortDirection", @"sortDirection" },
- { @"AXVisited", @"visited" },
+ {NSAccessibilityARIAAtomicAttribute, @"ariaAtomic"},
+ {NSAccessibilityARIABusyAttribute, @"ariaBusy"},
+ {NSAccessibilityARIALiveAttribute, @"ariaLive"},
+ {NSAccessibilityARIAPosInSetAttribute, @"ariaPosInSet"},
+ {NSAccessibilityARIARelevantAttribute, @"ariaRelevant"},
+ {NSAccessibilityARIASetSizeAttribute, @"ariaSetSize"},
+ {NSAccessibilityAccessKeyAttribute, @"accessKey"},
+ {NSAccessibilityChildrenAttribute, @"children"},
+ {NSAccessibilityColumnsAttribute, @"columns"},
+ {NSAccessibilityColumnHeaderUIElementsAttribute, @"columnHeaders"},
+ {NSAccessibilityColumnIndexRangeAttribute, @"columnIndexRange"},
+ {NSAccessibilityContentsAttribute, @"contents"},
+ {NSAccessibilityDescriptionAttribute, @"description"},
+ {NSAccessibilityDisclosingAttribute, @"disclosing"},
+ {NSAccessibilityDisclosedByRowAttribute, @"disclosedByRow"},
+ {NSAccessibilityDisclosureLevelAttribute, @"disclosureLevel"},
+ {NSAccessibilityDisclosedRowsAttribute, @"disclosedRows"},
+ {NSAccessibilityDropEffectsAttribute, @"dropEffects"},
+ {NSAccessibilityEnabledAttribute, @"enabled"},
+ {NSAccessibilityEndTextMarkerAttribute, @"endTextMarker"},
+ {NSAccessibilityExpandedAttribute, @"expanded"},
+ {NSAccessibilityFocusedAttribute, @"focused"},
+ {NSAccessibilityGrabbedAttribute, @"grabbed"},
+ {NSAccessibilityHeaderAttribute, @"header"},
+ {NSAccessibilityHelpAttribute, @"help"},
+ {NSAccessibilityIndexAttribute, @"index"},
+ {NSAccessibilityInsertionPointLineNumberAttribute,
+ @"insertionPointLineNumber"},
+ {NSAccessibilityInvalidAttribute, @"invalid"},
+ {NSAccessibilityIsMultiSelectableAttribute, @"isMultiSelectable"},
+ {NSAccessibilityLinkedUIElementsAttribute, @"linkedUIElements"},
+ {NSAccessibilityLoadingProgressAttribute, @"loadingProgress"},
+ {NSAccessibilityMaxValueAttribute, @"maxValue"},
+ {NSAccessibilityMinValueAttribute, @"minValue"},
+ {NSAccessibilityNumberOfCharactersAttribute, @"numberOfCharacters"},
+ {NSAccessibilityOrientationAttribute, @"orientation"},
+ {NSAccessibilityParentAttribute, @"parent"},
+ {NSAccessibilityPlaceholderValueAttribute, @"placeholderValue"},
+ {NSAccessibilityPositionAttribute, @"position"},
+ {NSAccessibilityRequiredAttribute, @"required"},
+ {NSAccessibilityRoleAttribute, @"role"},
+ {NSAccessibilityRoleDescriptionAttribute, @"roleDescription"},
+ {NSAccessibilityRowHeaderUIElementsAttribute, @"rowHeaders"},
+ {NSAccessibilityRowIndexRangeAttribute, @"rowIndexRange"},
+ {NSAccessibilityRowsAttribute, @"rows"},
+ // TODO(aboxhall): expose
+ // NSAccessibilityServesAsTitleForUIElementsAttribute
+ {NSAccessibilityStartTextMarkerAttribute, @"startTextMarker"},
+ {NSAccessibilitySelectedAttribute, @"selected"},
+ {NSAccessibilitySelectedChildrenAttribute, @"selectedChildren"},
+ {NSAccessibilitySelectedTextAttribute, @"selectedText"},
+ {NSAccessibilitySelectedTextRangeAttribute, @"selectedTextRange"},
+ {NSAccessibilitySelectedTextMarkerRangeAttribute,
+ @"selectedTextMarkerRange"},
+ {NSAccessibilitySizeAttribute, @"size"},
+ {NSAccessibilitySortDirectionAttribute, @"sortDirection"},
+ {NSAccessibilitySubroleAttribute, @"subrole"},
+ {NSAccessibilityTabsAttribute, @"tabs"},
+ {NSAccessibilityTitleAttribute, @"title"},
+ {NSAccessibilityTitleUIElementAttribute, @"titleUIElement"},
+ {NSAccessibilityTopLevelUIElementAttribute, @"window"},
+ {NSAccessibilityURLAttribute, @"url"},
+ {NSAccessibilityValueAttribute, @"value"},
+ {NSAccessibilityValueDescriptionAttribute, @"valueDescription"},
+ {NSAccessibilityVisibleCharacterRangeAttribute, @"visibleCharacterRange"},
+ {NSAccessibilityVisibleCellsAttribute, @"visibleCells"},
+ {NSAccessibilityVisibleChildrenAttribute, @"visibleChildren"},
+ {NSAccessibilityVisibleColumnsAttribute, @"visibleColumns"},
+ {NSAccessibilityVisibleRowsAttribute, @"visibleRows"},
+ {NSAccessibilityVisitedAttribute, @"visited"},
+ {NSAccessibilityWindowAttribute, @"window"},
+ {@"AXLoaded", @"loaded"},
};
NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
@@ -413,51 +504,64 @@ bool InitializeAccessibilityTreeSearch(
dict = nil;
}
-- (id)initWithObject:(BrowserAccessibility*)accessibility {
+- (instancetype)initWithObject:(BrowserAccessibility*)accessibility {
if ((self = [super init]))
browserAccessibility_ = accessibility;
return self;
}
- (void)detach {
- if (browserAccessibility_) {
+ if (browserAccessibility_)
NSAccessibilityUnregisterUniqueIdForUIElement(self);
- browserAccessibility_ = NULL;
- }
+ browserAccessibility_ = nullptr;
}
- (NSString*)accessKey {
+ if (![self instanceActive])
+ return nil;
return NSStringForStringAttribute(
browserAccessibility_, ui::AX_ATTR_ACCESS_KEY);
}
- (NSNumber*)ariaAtomic {
+ if (![self instanceActive])
+ return nil;
bool boolValue = browserAccessibility_->GetBoolAttribute(
ui::AX_ATTR_LIVE_ATOMIC);
return [NSNumber numberWithBool:boolValue];
}
- (NSNumber*)ariaBusy {
+ if (![self instanceActive])
+ return nil;
return [NSNumber numberWithBool:
GetState(browserAccessibility_, ui::AX_STATE_BUSY)];
}
- (NSString*)ariaLive {
+ if (![self instanceActive])
+ return nil;
return NSStringForStringAttribute(
browserAccessibility_, ui::AX_ATTR_LIVE_STATUS);
}
-- (NSString*)ariaRelevant {
- return NSStringForStringAttribute(
- browserAccessibility_, ui::AX_ATTR_LIVE_RELEVANT);
-}
-
- (NSNumber*)ariaPosInSet {
+ if (![self instanceActive])
+ return nil;
return [NSNumber numberWithInt:
browserAccessibility_->GetIntAttribute(ui::AX_ATTR_POS_IN_SET)];
}
+- (NSString*)ariaRelevant {
+ if (![self instanceActive])
+ return nil;
+ return NSStringForStringAttribute(browserAccessibility_,
+ ui::AX_ATTR_LIVE_RELEVANT);
+}
+
- (NSNumber*)ariaSetSize {
+ if (![self instanceActive])
+ return nil;
return [NSNumber numberWithInt:
browserAccessibility_->GetIntAttribute(ui::AX_ATTR_SET_SIZE)];
}
@@ -465,13 +569,15 @@ bool InitializeAccessibilityTreeSearch(
// Returns an array of BrowserAccessibilityCocoa objects, representing the
// accessibility children of this object.
- (NSArray*)children {
+ if (![self instanceActive])
+ return nil;
if (!children_) {
uint32_t childCount = browserAccessibility_->PlatformChildCount();
children_.reset([[NSMutableArray alloc] initWithCapacity:childCount]);
for (uint32_t index = 0; index < childCount; ++index) {
BrowserAccessibilityCocoa* child =
- browserAccessibility_->PlatformGetChild(index)->
- ToBrowserAccessibilityCocoa();
+ ToBrowserAccessibilityCocoa(
+ browserAccessibility_->PlatformGetChild(index));
if ([child isIgnored])
[children_ addObjectsFromArray:[child children]];
else
@@ -491,7 +597,7 @@ bool InitializeAccessibilityTreeSearch(
// a DCHECK in the future.
if (child) {
BrowserAccessibilityCocoa* child_cocoa =
- child->ToBrowserAccessibilityCocoa();
+ ToBrowserAccessibilityCocoa(child);
[children_ addObject:child_cocoa];
}
}
@@ -500,15 +606,19 @@ bool InitializeAccessibilityTreeSearch(
}
- (void)childrenChanged {
+ if (![self instanceActive])
+ return;
if (![self isIgnored]) {
children_.reset();
} else {
- [browserAccessibility_->GetParent()->ToBrowserAccessibilityCocoa()
- childrenChanged];
+ [ToBrowserAccessibilityCocoa(browserAccessibility_->GetParent())
+ childrenChanged];
}
}
- (NSArray*)columnHeaders {
+ if (![self instanceActive])
+ return nil;
if ([self internalRole] != ui::AX_ROLE_TABLE &&
[self internalRole] != ui::AX_ROLE_GRID) {
return nil;
@@ -522,12 +632,14 @@ bool InitializeAccessibilityTreeSearch(
BrowserAccessibility* cell =
browserAccessibility_->manager()->GetFromID(id);
if (cell && cell->GetRole() == ui::AX_ROLE_COLUMN_HEADER)
- [ret addObject:cell->ToBrowserAccessibilityCocoa()];
+ [ret addObject:ToBrowserAccessibilityCocoa(cell)];
}
return ret;
}
- (NSValue*)columnIndexRange {
+ if (![self instanceActive])
+ return nil;
if (!browserAccessibility_->IsCellOrTableHeaderRole())
return nil;
@@ -543,6 +655,8 @@ bool InitializeAccessibilityTreeSearch(
}
- (NSArray*)columns {
+ if (![self instanceActive])
+ return nil;
NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
for (BrowserAccessibilityCocoa* child in [self children]) {
if ([[child role] isEqualToString:NSAccessibilityColumnRole])
@@ -552,6 +666,9 @@ bool InitializeAccessibilityTreeSearch(
}
- (NSString*)description {
+ if (![self instanceActive])
+ return nil;
+
// Mac OS X wants static text exposed in AXValue.
if ([self shouldExposeNameInAXValue])
return @"";
@@ -562,14 +679,18 @@ bool InitializeAccessibilityTreeSearch(
browserAccessibility_->GetIntListAttribute(ui::AX_ATTR_LABELLEDBY_IDS);
ui::AXNameFrom nameFrom = static_cast<ui::AXNameFrom>(
browserAccessibility_->GetIntAttribute(ui::AX_ATTR_NAME_FROM));
+ std::string name = browserAccessibility_->GetStringAttribute(
+ ui::AX_ATTR_NAME);
+
+ // VoiceOver ignores titleUIElement on non-control AX nodes, so this special
+ // case expressly returns a nonempty text name for these nodes.
if (nameFrom == ui::AX_NAME_FROM_RELATED_ELEMENT &&
labelledby_ids.size() == 1 &&
- browserAccessibility_->manager()->GetFromID(labelledby_ids[0])) {
- return @"";
+ browserAccessibility_->manager()->GetFromID(labelledby_ids[0]) &&
+ !browserAccessibility_->IsControl()) {
+ return base::SysUTF8ToNSString(name);
}
- std::string name = browserAccessibility_->GetStringAttribute(
- ui::AX_ATTR_NAME);
if (!name.empty()) {
// On Mac OS X, the accessible name of an object is exposed as its
// title if it comes from visible text, and as its description
@@ -620,6 +741,8 @@ bool InitializeAccessibilityTreeSearch(
}
- (NSNumber*)disclosing {
+ if (![self instanceActive])
+ return nil;
if ([self internalRole] == ui::AX_ROLE_TREE_ITEM) {
return [NSNumber numberWithBool:
GetState(browserAccessibility_, ui::AX_STATE_EXPANDED)];
@@ -629,12 +752,17 @@ bool InitializeAccessibilityTreeSearch(
}
- (id)disclosedByRow {
+ if (![self instanceActive])
+ return nil;
+
// The row that contains this row.
// It should be the same as the first parent that is a treeitem.
return nil;
}
- (NSNumber*)disclosureLevel {
+ if (![self instanceActive])
+ return nil;
ui::AXRole role = [self internalRole];
if (role == ui::AX_ROLE_ROW ||
role == ui::AX_ROLE_TREE_ITEM) {
@@ -650,36 +778,78 @@ bool InitializeAccessibilityTreeSearch(
}
- (id)disclosedRows {
+ if (![self instanceActive])
+ return nil;
+
// The rows that are considered inside this row.
return nil;
}
-- (NSString*)dropeffect {
- std::string dropEffect;
- if (browserAccessibility_->GetHtmlAttribute("aria-dropeffect", &dropEffect))
- return base::SysUTF8ToNSString(dropEffect);
+- (NSString*)dropEffects {
+ if (![self instanceActive])
+ return nil;
+
+ std::string dropEffects;
+ if (browserAccessibility_->GetHtmlAttribute("aria-dropeffect", &dropEffects))
+ return base::SysUTF8ToNSString(dropEffects);
return nil;
}
- (NSNumber*)enabled {
+ if (![self instanceActive])
+ return nil;
return [NSNumber numberWithBool:
GetState(browserAccessibility_, ui::AX_STATE_ENABLED)];
}
+// Returns a text marker that points to the last character in the document that
+// can be selected with VoiceOver.
+- (id)endTextMarker {
+ if (![self instanceActive])
+ return nil;
+
+ const BrowserAccessibility* root =
+ browserAccessibility_->manager()->GetRoot();
+ if (!root)
+ return nil;
+
+ const BrowserAccessibility* last_text_object =
+ root->InternalDeepestLastChild();
+ if (last_text_object && !last_text_object->IsTextOnlyObject()) {
+ last_text_object =
+ BrowserAccessibilityManager::PreviousTextOnlyObject(last_text_object);
+ }
+ while (last_text_object) {
+ last_text_object =
+ BrowserAccessibilityManager::PreviousTextOnlyObject(last_text_object);
+ }
+ if (!last_text_object)
+ return nil;
+
+ return CreateTextMarker(*last_text_object,
+ last_text_object->GetText().length());
+}
+
- (NSNumber*)expanded {
+ if (![self instanceActive])
+ return nil;
return [NSNumber numberWithBool:
GetState(browserAccessibility_, ui::AX_STATE_EXPANDED)];
}
- (NSNumber*)focused {
+ if (![self instanceActive])
+ return nil;
BrowserAccessibilityManager* manager = browserAccessibility_->manager();
NSNumber* ret = [NSNumber numberWithBool:
- manager->GetFocus(NULL) == browserAccessibility_];
+ manager->GetFocus() == browserAccessibility_];
return ret;
}
- (NSNumber*)grabbed {
+ if (![self instanceActive])
+ return nil;
std::string grabbed;
if (browserAccessibility_->GetHtmlAttribute("aria-grabbed", &grabbed) &&
grabbed == "true")
@@ -689,6 +859,8 @@ bool InitializeAccessibilityTreeSearch(
}
- (id)header {
+ if (![self instanceActive])
+ return nil;
int headerElementId = -1;
if ([self internalRole] == ui::AX_ROLE_TABLE ||
[self internalRole] == ui::AX_ROLE_GRID) {
@@ -706,17 +878,21 @@ bool InitializeAccessibilityTreeSearch(
BrowserAccessibility* headerObject =
browserAccessibility_->manager()->GetFromID(headerElementId);
if (headerObject)
- return headerObject->ToBrowserAccessibilityCocoa();
+ return ToBrowserAccessibilityCocoa(headerObject);
}
return nil;
}
- (NSString*)help {
+ if (![self instanceActive])
+ return nil;
return NSStringForStringAttribute(
browserAccessibility_, ui::AX_ATTR_DESCRIPTION);
}
- (NSNumber*)index {
+ if (![self instanceActive])
+ return nil;
if ([self internalRole] == ui::AX_ROLE_COLUMN) {
int columnIndex = browserAccessibility_->GetIntAttribute(
ui::AX_ATTR_TABLE_COLUMN_INDEX);
@@ -730,13 +906,43 @@ bool InitializeAccessibilityTreeSearch(
return nil;
}
+- (NSNumber*)insertionPointLineNumber {
+ if (![self instanceActive])
+ return nil;
+
+ // TODO(nektar): Deprecate sel_start and sel_end attributes.
+ int selStart, selEnd;
+ if (!browserAccessibility_->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START,
+ &selStart) ||
+ !browserAccessibility_->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END,
+ &selEnd)) {
+ return nil;
+ }
+
+ if (selStart > selEnd)
+ std::swap(selStart, selEnd);
+
+ const std::vector<int32_t>& line_breaks =
+ browserAccessibility_->GetIntListAttribute(ui::AX_ATTR_LINE_BREAKS);
+ for (int i = 0; i < static_cast<int>(line_breaks.size()); ++i) {
+ if (line_breaks[i] > selStart)
+ return [NSNumber numberWithInt:i];
+ }
+
+ return [NSNumber numberWithInt:static_cast<int>(line_breaks.size())];
+}
+
// Returns whether or not this node should be ignored in the
// accessibility tree.
- (BOOL)isIgnored {
+ if (![self instanceActive])
+ return YES;
return [[self role] isEqualToString:NSAccessibilityUnknownRole];
}
- (NSString*)invalid {
+ if (![self instanceActive])
+ return nil;
int invalidState;
if (!browserAccessibility_->GetIntAttribute(
ui::AX_ATTR_INVALID_STATE, &invalidState))
@@ -768,7 +974,16 @@ bool InitializeAccessibilityTreeSearch(
return @"false";
}
+- (NSNumber*)isMultiSelectable {
+ if (![self instanceActive])
+ return nil;
+ return [NSNumber numberWithBool:GetState(browserAccessibility_,
+ ui::AX_STATE_MULTISELECTABLE)];
+}
+
- (NSString*)placeholderValue {
+ if (![self instanceActive])
+ return nil;
ui::AXNameFrom nameFrom = static_cast<ui::AXNameFrom>(
browserAccessibility_->GetIntAttribute(ui::AX_ATTR_NAME_FROM));
if (nameFrom == ui::AX_NAME_FROM_PLACEHOLDER) {
@@ -787,6 +1002,7 @@ bool InitializeAccessibilityTreeSearch(
browserAccessibility_, ui::AX_ATTR_PLACEHOLDER);
}
+// private
- (void)addLinkedUIElementsFromAttribute:(ui::AXIntListAttribute)attribute
addTo:(NSMutableArray*)outArray {
const std::vector<int32_t>& attributeValues =
@@ -795,10 +1011,11 @@ bool InitializeAccessibilityTreeSearch(
BrowserAccessibility* element =
browserAccessibility_->manager()->GetFromID(attributeValues[i]);
if (element)
- [outArray addObject:element->ToBrowserAccessibilityCocoa()];
+ [outArray addObject:ToBrowserAccessibilityCocoa(element)];
}
}
+// private
- (NSArray*)linkedUIElements {
NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
[self addLinkedUIElementsFromAttribute:ui::AX_ATTR_CONTROLS_IDS addTo:ret];
@@ -809,28 +1026,38 @@ bool InitializeAccessibilityTreeSearch(
}
- (NSNumber*)loaded {
+ if (![self instanceActive])
+ return nil;
return [NSNumber numberWithBool:YES];
}
- (NSNumber*)loadingProgress {
+ if (![self instanceActive])
+ return nil;
BrowserAccessibilityManager* manager = browserAccessibility_->manager();
float floatValue = manager->GetTreeData().loading_progress;
return [NSNumber numberWithFloat:floatValue];
}
- (NSNumber*)maxValue {
+ if (![self instanceActive])
+ return nil;
float floatValue = browserAccessibility_->GetFloatAttribute(
ui::AX_ATTR_MAX_VALUE_FOR_RANGE);
return [NSNumber numberWithFloat:floatValue];
}
- (NSNumber*)minValue {
+ if (![self instanceActive])
+ return nil;
float floatValue = browserAccessibility_->GetFloatAttribute(
ui::AX_ATTR_MIN_VALUE_FOR_RANGE);
return [NSNumber numberWithFloat:floatValue];
}
- (NSString*)orientation {
+ if (![self instanceActive])
+ return nil;
if (GetState(browserAccessibility_, ui::AX_STATE_VERTICAL))
return NSAccessibilityVerticalOrientationValue;
else if (GetState(browserAccessibility_, ui::AX_STATE_HORIZONTAL))
@@ -840,23 +1067,29 @@ bool InitializeAccessibilityTreeSearch(
}
- (NSNumber*)numberOfCharacters {
+ if (![self instanceActive])
+ return nil;
base::string16 value = browserAccessibility_->GetValue();
- return [NSNumber numberWithInt:value.size()];
+ return [NSNumber numberWithUnsignedInt:value.size()];
}
// The origin of this accessibility object in the page's document.
// This is relative to webkit's top-left origin, not Cocoa's
// bottom-left origin.
- (NSPoint)origin {
+ if (![self instanceActive])
+ return NSMakePoint(0, 0);
gfx::Rect bounds = browserAccessibility_->GetLocalBoundsRect();
return NSMakePoint(bounds.x(), bounds.y());
}
- (id)parent {
+ if (![self instanceActive])
+ return nil;
// A nil parent means we're the root.
if (browserAccessibility_->GetParent()) {
return NSAccessibilityUnignoredAncestor(
- browserAccessibility_->GetParent()->ToBrowserAccessibilityCocoa());
+ ToBrowserAccessibilityCocoa(browserAccessibility_->GetParent()));
} else {
// Hook back up to RenderWidgetHostViewCocoa.
BrowserAccessibilityManagerMac* manager =
@@ -867,6 +1100,8 @@ bool InitializeAccessibilityTreeSearch(
}
- (NSValue*)position {
+ if (![self instanceActive])
+ return nil;
NSPoint origin = [self origin];
NSSize size = [[self size] sizeValue];
NSPoint pointInScreen = [self pointInScreen:origin size:size];
@@ -874,17 +1109,21 @@ bool InitializeAccessibilityTreeSearch(
}
- (NSNumber*)required {
+ if (![self instanceActive])
+ return nil;
return [NSNumber numberWithBool:
GetState(browserAccessibility_, ui::AX_STATE_REQUIRED)];
}
// Returns an enum indicating the role from browserAccessibility_.
+// internal
- (ui::AXRole)internalRole {
return static_cast<ui::AXRole>(browserAccessibility_->GetRole());
}
// Returns true if this should expose its accessible name in AXValue.
-- (bool)shouldExposeNameInAXValue {
+// internal
+- (BOOL)shouldExposeNameInAXValue {
switch ([self internalRole]) {
case ui::AX_ROLE_LIST_BOX_OPTION:
case ui::AX_ROLE_LIST_MARKER:
@@ -896,19 +1135,24 @@ bool InitializeAccessibilityTreeSearch(
}
}
+// internal
- (content::BrowserAccessibilityDelegate*)delegate {
- return browserAccessibility_->manager() ?
- browserAccessibility_->manager()->delegate() :
- nil;
+ return [self instanceActive] ? browserAccessibility_->manager()->delegate()
+ : nil;
}
- (content::BrowserAccessibility*)browserAccessibility {
return browserAccessibility_;
}
+- (BOOL)instanceActive {
+ return browserAccessibility_ && browserAccessibility_->instance_active();
+}
+
+// internal
- (NSPoint)pointInScreen:(NSPoint)origin
size:(NSSize)size {
- if (!browserAccessibility_)
+ if (![self instanceActive])
return NSZeroPoint;
// Get the delegate for the topmost BrowserAccessibilityManager, because
@@ -926,7 +1170,7 @@ bool InitializeAccessibilityTreeSearch(
// Returns a string indicating the NSAccessibility role of this object.
- (NSString*)role {
- if (!browserAccessibility_)
+ if (![self instanceActive])
return nil;
ui::AXRole role = [self internalRole];
@@ -963,6 +1207,8 @@ bool InitializeAccessibilityTreeSearch(
// Returns a string indicating the role description of this object.
- (NSString*)roleDescription {
+ if (![self instanceActive])
+ return nil;
NSString* role = [self role];
ContentClient* content_client = content::GetContentClient();
@@ -1013,13 +1259,13 @@ bool InitializeAccessibilityTreeSearch(
IDS_AX_ROLE_COMPLEMENTARY));
case ui::AX_ROLE_CONTENT_INFO:
return base::SysUTF16ToNSString(content_client->GetLocalizedString(
- IDS_AX_ROLE_ADDRESS));
+ IDS_AX_ROLE_CONTENT_INFO));
case ui::AX_ROLE_DESCRIPTION_LIST:
return base::SysUTF16ToNSString(content_client->GetLocalizedString(
IDS_AX_ROLE_DESCRIPTION_LIST));
case ui::AX_ROLE_DESCRIPTION_LIST_DETAIL:
return base::SysUTF16ToNSString(content_client->GetLocalizedString(
- IDS_AX_ROLE_DESCRIPTION_DETAIL));
+ IDS_AX_ROLE_DEFINITION));
case ui::AX_ROLE_DESCRIPTION_LIST_TERM:
return base::SysUTF16ToNSString(content_client->GetLocalizedString(
IDS_AX_ROLE_DESCRIPTION_TERM));
@@ -1071,6 +1317,8 @@ bool InitializeAccessibilityTreeSearch(
}
- (NSArray*)rowHeaders {
+ if (![self instanceActive])
+ return nil;
if ([self internalRole] != ui::AX_ROLE_TABLE &&
[self internalRole] != ui::AX_ROLE_GRID) {
return nil;
@@ -1084,12 +1332,14 @@ bool InitializeAccessibilityTreeSearch(
BrowserAccessibility* cell =
browserAccessibility_->manager()->GetFromID(id);
if (cell && cell->GetRole() == ui::AX_ROLE_ROW_HEADER)
- [ret addObject:cell->ToBrowserAccessibilityCocoa()];
+ [ret addObject:ToBrowserAccessibilityCocoa(cell)];
}
return ret;
}
- (NSValue*)rowIndexRange {
+ if (![self instanceActive])
+ return nil;
if (!browserAccessibility_->IsCellOrTableHeaderRole())
return nil;
@@ -1105,6 +1355,8 @@ bool InitializeAccessibilityTreeSearch(
}
- (NSArray*)rows {
+ if (![self instanceActive])
+ return nil;
NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
if ([self internalRole] == ui::AX_ROLE_TABLE||
@@ -1122,24 +1374,35 @@ bool InitializeAccessibilityTreeSearch(
BrowserAccessibility* rowElement =
browserAccessibility_->manager()->GetFromID(id);
if (rowElement)
- [ret addObject:rowElement->ToBrowserAccessibilityCocoa()];
+ [ret addObject:ToBrowserAccessibilityCocoa(rowElement)];
}
}
return ret;
}
+- (NSNumber*)selected {
+ if (![self instanceActive])
+ return nil;
+ // TODO(nektar): Implement.
+ return [NSNumber numberWithBool:NO];
+}
+
- (NSArray*)selectedChildren {
+ if (![self instanceActive])
+ return nil;
NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
BrowserAccessibilityManager* manager = browserAccessibility_->manager();
- BrowserAccessibility* focusedChild = manager->GetFocus(browserAccessibility_);
+ BrowserAccessibility* focusedChild = manager->GetFocus();
+ if (!focusedChild->IsDescendantOf(browserAccessibility_))
+ focusedChild = nullptr;
// If it's not multiselectable, try to skip iterating over the
// children.
if (!GetState(browserAccessibility_, ui::AX_STATE_MULTISELECTABLE)) {
// First try the focused child.
if (focusedChild && focusedChild != browserAccessibility_) {
- [ret addObject:focusedChild->ToBrowserAccessibilityCocoa()];
+ [ret addObject:ToBrowserAccessibilityCocoa(focusedChild)];
return ret;
}
@@ -1150,7 +1413,7 @@ bool InitializeAccessibilityTreeSearch(
BrowserAccessibility* activeDescendant =
manager->GetFromID(activeDescendantId);
if (activeDescendant) {
- [ret addObject:activeDescendant->ToBrowserAccessibilityCocoa()];
+ [ret addObject:ToBrowserAccessibilityCocoa(activeDescendant)];
return ret;
}
}
@@ -1164,49 +1427,149 @@ bool InitializeAccessibilityTreeSearch(
BrowserAccessibility* child =
browserAccessibility_->PlatformGetChild(index);
if (child->HasState(ui::AX_STATE_SELECTED))
- [ret addObject:child->ToBrowserAccessibilityCocoa()];
+ [ret addObject:ToBrowserAccessibilityCocoa(child)];
}
// And if nothing's selected but one has focus, use the focused one.
if ([ret count] == 0 &&
focusedChild &&
focusedChild != browserAccessibility_) {
- [ret addObject:focusedChild->ToBrowserAccessibilityCocoa()];
+ [ret addObject:ToBrowserAccessibilityCocoa(focusedChild)];
}
return ret;
}
-// Returns the size of this object.
+- (NSString*)selectedText {
+ if (![self instanceActive])
+ return nil;
+
+ // TODO(nektar): Deprecate sel_start and sel_end attributes.
+ int selStart, selEnd;
+ if (!browserAccessibility_->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START,
+ &selStart) ||
+ !browserAccessibility_->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END,
+ &selEnd)) {
+ return nil;
+ }
+
+ if (selStart > selEnd)
+ std::swap(selStart, selEnd);
+
+ int selLength = selEnd - selStart;
+ base::string16 value = browserAccessibility_->GetValue();
+ return base::SysUTF16ToNSString(value.substr(selStart, selLength));
+}
+
+- (NSValue*)selectedTextRange {
+ if (![self instanceActive])
+ return nil;
+
+ // TODO(nektar): Deprecate sel_start and sel_end attributes.
+ int selStart, selEnd;
+ if (!browserAccessibility_->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START,
+ &selStart) ||
+ !browserAccessibility_->GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END,
+ &selEnd)) {
+ return nil;
+ }
+
+ if (selStart > selEnd)
+ std::swap(selStart, selEnd);
+
+ int selLength = selEnd - selStart;
+ return [NSValue valueWithRange:NSMakeRange(selStart, selLength)];
+}
+
+- (id)selectedTextMarkerRange {
+ if (![self instanceActive])
+ return nil;
+
+ BrowserAccessibilityManager* manager = browserAccessibility_->manager();
+ if (!manager)
+ return nil;
+
+ int32_t anchorId = manager->GetTreeData().sel_anchor_object_id;
+ const BrowserAccessibility* anchorObject = manager->GetFromID(anchorId);
+ if (!anchorObject)
+ return nil;
+
+ int32_t focusId = manager->GetTreeData().sel_focus_object_id;
+ const BrowserAccessibility* focusObject = manager->GetFromID(focusId);
+ if (!focusObject)
+ return nil;
+
+ int anchorOffset = manager->GetTreeData().sel_anchor_offset;
+ int focusOffset = manager->GetTreeData().sel_focus_offset;
+ if (anchorOffset < 0 || focusOffset < 0)
+ return nil;
+
+ return CreateTextMarkerRange(*anchorObject, anchorOffset, *focusObject,
+ focusOffset);
+}
+
- (NSValue*)size {
+ if (![self instanceActive])
+ return nil;
gfx::Rect bounds = browserAccessibility_->GetLocalBoundsRect();
return [NSValue valueWithSize:NSMakeSize(bounds.width(), bounds.height())];
}
- (NSString*)sortDirection {
+ if (![self instanceActive])
+ return nil;
int sortDirection;
if (!browserAccessibility_->GetIntAttribute(
ui::AX_ATTR_SORT_DIRECTION, &sortDirection))
- return @"";
+ return nil;
switch (sortDirection) {
case ui::AX_SORT_DIRECTION_UNSORTED:
- return @"";
+ return nil;
case ui::AX_SORT_DIRECTION_ASCENDING:
- return @"AXSortDirectionAscending";
+ return NSAccessibilityAscendingSortDirectionValue;
case ui::AX_SORT_DIRECTION_DESCENDING:
- return @"AXSortDirectionDescending";
+ return NSAccessibilityDescendingSortDirectionValue;
case ui::AX_SORT_DIRECTION_OTHER:
- return @"AXSortDirectionUnknown";
+ return NSAccessibilityUnknownSortDirectionValue;
default:
NOTREACHED();
}
- return @"";
+ return nil;
+}
+
+// Returns a text marker that points to the first character in the document that
+// can be selected with VoiceOver.
+- (id)startTextMarker {
+ if (![self instanceActive])
+ return nil;
+
+ const BrowserAccessibility* root =
+ browserAccessibility_->manager()->GetRoot();
+ if (!root)
+ return nil;
+
+ const BrowserAccessibility* first_text_object =
+ root->InternalDeepestFirstChild();
+ if (first_text_object && !first_text_object->IsTextOnlyObject()) {
+ first_text_object =
+ BrowserAccessibilityManager::NextTextOnlyObject(first_text_object);
+ }
+ while (first_text_object) {
+ first_text_object =
+ BrowserAccessibilityManager::NextTextOnlyObject(first_text_object);
+ }
+ if (!first_text_object)
+ return nil;
+
+ return CreateTextMarker(*first_text_object, 0);
}
// Returns a subrole based upon the role.
- (NSString*) subrole {
+ if (![self instanceActive])
+ return nil;
ui::AXRole browserAccessibilityRole = [self internalRole];
if (browserAccessibilityRole == ui::AX_ROLE_TEXT_FIELD &&
GetState(browserAccessibility_, ui::AX_STATE_PROTECTED)) {
@@ -1224,6 +1587,8 @@ bool InitializeAccessibilityTreeSearch(
// Returns all tabs in this subtree.
- (NSArray*)tabs {
+ if (![self instanceActive])
+ return nil;
NSMutableArray* tabSubtree = [[[NSMutableArray alloc] init] autorelease];
if ([self internalRole] == ui::AX_ROLE_TAB)
@@ -1239,6 +1604,8 @@ bool InitializeAccessibilityTreeSearch(
}
- (NSString*)title {
+ if (![self instanceActive])
+ return nil;
// Mac OS X wants static text exposed in AXValue.
if ([self shouldExposeNameInAXValue])
return @"";
@@ -1269,6 +1636,8 @@ bool InitializeAccessibilityTreeSearch(
}
- (id)titleUIElement {
+ if (![self instanceActive])
+ return nil;
std::vector<int32_t> labelledby_ids =
browserAccessibility_->GetIntListAttribute(ui::AX_ATTR_LABELLEDBY_IDS);
ui::AXNameFrom nameFrom = static_cast<ui::AXNameFrom>(
@@ -1278,13 +1647,15 @@ bool InitializeAccessibilityTreeSearch(
BrowserAccessibility* titleElement =
browserAccessibility_->manager()->GetFromID(labelledby_ids[0]);
if (titleElement)
- return titleElement->ToBrowserAccessibilityCocoa();
+ return ToBrowserAccessibilityCocoa(titleElement);
}
return nil;
}
- (NSURL*)url {
+ if (![self instanceActive])
+ return nil;
std::string url;
if ([[self role] isEqualToString:@"AXWebArea"])
url = browserAccessibility_->manager()->GetTreeData().url;
@@ -1298,6 +1669,8 @@ bool InitializeAccessibilityTreeSearch(
}
- (id)value {
+ if (![self instanceActive])
+ return nil;
NSString* role = [self role];
if ([self shouldExposeNameInAXValue]) {
return NSStringForStringAttribute(
@@ -1347,11 +1720,11 @@ bool InitializeAccessibilityTreeSearch(
return [NSNumber numberWithFloat:floatValue];
}
} else if ([role isEqualToString:NSAccessibilityColorWellRole]) {
- int color = browserAccessibility_->GetIntAttribute(
- ui::AX_ATTR_COLOR_VALUE);
- int red = (color >> 16) & 0xFF;
- int green = (color >> 8) & 0xFF;
- int blue = color & 0xFF;
+ unsigned int color = static_cast<unsigned int>(
+ browserAccessibility_->GetIntAttribute(ui::AX_ATTR_COLOR_VALUE));
+ unsigned int red = SkColorGetR(color);
+ unsigned int green = SkColorGetG(color);
+ unsigned int blue = SkColorGetB(color);
// This string matches the one returned by a native Mac color well.
return [NSString stringWithFormat:@"rgb %7.5f %7.5f %7.5f 1",
red / 255., green / 255., blue / 255.];
@@ -1361,17 +1734,23 @@ bool InitializeAccessibilityTreeSearch(
}
- (NSString*)valueDescription {
+ if (![self instanceActive])
+ return nil;
if (browserAccessibility_)
return base::SysUTF16ToNSString(browserAccessibility_->GetValue());
return nil;
}
- (NSValue*)visibleCharacterRange {
+ if (![self instanceActive])
+ return nil;
base::string16 value = browserAccessibility_->GetValue();
return [NSValue valueWithRange:NSMakeRange(0, value.size())];
}
- (NSArray*)visibleCells {
+ if (![self instanceActive])
+ return nil;
NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
const std::vector<int32_t>& uniqueCellIds =
browserAccessibility_->GetIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS);
@@ -1380,38 +1759,45 @@ bool InitializeAccessibilityTreeSearch(
BrowserAccessibility* cell =
browserAccessibility_->manager()->GetFromID(id);
if (cell)
- [ret addObject:cell->ToBrowserAccessibilityCocoa()];
+ [ret addObject:ToBrowserAccessibilityCocoa(cell)];
}
return ret;
}
- (NSArray*)visibleChildren {
+ if (![self instanceActive])
+ return nil;
NSMutableArray* ret = [[[NSMutableArray alloc] init] autorelease];
uint32_t childCount = browserAccessibility_->PlatformChildCount();
for (uint32_t index = 0; index < childCount; ++index) {
- BrowserAccessibilityCocoa* child =
- browserAccessibility_->PlatformGetChild(index)->
- ToBrowserAccessibilityCocoa();
+ BrowserAccessibilityCocoa* child = ToBrowserAccessibilityCocoa(
+ browserAccessibility_->PlatformGetChild(index));
[ret addObject:child];
}
return ret;
}
- (NSArray*)visibleColumns {
+ if (![self instanceActive])
+ return nil;
return [self columns];
}
- (NSArray*)visibleRows {
+ if (![self instanceActive])
+ return nil;
return [self rows];
}
- (NSNumber*)visited {
+ if (![self instanceActive])
+ return nil;
return [NSNumber numberWithBool:
GetState(browserAccessibility_, ui::AX_STATE_VISITED)];
}
- (id)window {
- if (!browserAccessibility_)
+ if (![self instanceActive])
return nil;
BrowserAccessibilityManagerMac* manager =
@@ -1433,7 +1819,7 @@ bool InitializeAccessibilityTreeSearch(
// Returns the requested text range from this object's value attribute.
- (NSString*)valueForRange:(NSRange)range {
- if (!browserAccessibility_)
+ if (![self instanceActive])
return nil;
base::string16 value = browserAccessibility_->GetValue();
@@ -1446,7 +1832,7 @@ bool InitializeAccessibilityTreeSearch(
// Returns the accessibility value for the given attribute. If the value isn't
// supported this will return nil.
- (id)accessibilityAttributeValue:(NSString*)attribute {
- if (!browserAccessibility_)
+ if (![self instanceActive])
return nil;
SEL selector =
@@ -1454,41 +1840,15 @@ bool InitializeAccessibilityTreeSearch(
if (selector)
return [self performSelector:selector];
- // TODO(dtseng): refactor remaining attributes.
- int selStart, selEnd;
- if (browserAccessibility_->GetIntAttribute(
- ui::AX_ATTR_TEXT_SEL_START, &selStart) &&
- browserAccessibility_->
- GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END, &selEnd)) {
- if (selStart > selEnd)
- std::swap(selStart, selEnd);
- int selLength = selEnd - selStart;
- if ([attribute isEqualToString:
- NSAccessibilityInsertionPointLineNumberAttribute]) {
- const std::vector<int32_t>& line_breaks =
- browserAccessibility_->GetIntListAttribute(ui::AX_ATTR_LINE_BREAKS);
- for (int i = 0; i < static_cast<int>(line_breaks.size()); ++i) {
- if (line_breaks[i] > selStart)
- return [NSNumber numberWithInt:i];
- }
- return [NSNumber numberWithInt:static_cast<int>(line_breaks.size())];
- }
- if ([attribute isEqualToString:NSAccessibilitySelectedTextAttribute]) {
- base::string16 value = browserAccessibility_->GetValue();
- return base::SysUTF16ToNSString(value.substr(selStart, selLength));
- }
- if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
- return [NSValue valueWithRange:NSMakeRange(selStart, selLength)];
- }
- }
return nil;
}
// Returns the accessibility value for the given attribute and parameter. If the
// value isn't supported this will return nil.
+// TODO(nektar): Implement all unimplemented attributes, e.g. text markers.
- (id)accessibilityAttributeValue:(NSString*)attribute
forParameter:(id)parameter {
- if (!browserAccessibility_)
+ if (![self instanceActive])
return nil;
const std::vector<int32_t>& line_breaks =
@@ -1577,7 +1937,7 @@ bool InitializeAccessibilityTreeSearch(
continue;
}
if (colIndex == column)
- return cell->ToBrowserAccessibilityCocoa();
+ return ToBrowserAccessibilityCocoa(cell);
if (colIndex > column)
break;
}
@@ -1585,6 +1945,96 @@ bool InitializeAccessibilityTreeSearch(
return nil;
}
+ if ([attribute isEqualToString:@"AXUIElementForTextMarker"]) {
+ BrowserAccessibility* object;
+ int offset;
+ if (GetTextMarkerData(parameter, &object, &offset))
+ return ToBrowserAccessibilityCocoa(object);
+
+ return nil;
+ }
+
+ if ([attribute isEqualToString:@"AXTextMarkerRangeForUIElement"]) {
+ return CreateTextMarkerRange(*browserAccessibility_, 0,
+ *browserAccessibility_,
+ browserAccessibility_->GetText().length());
+ }
+
+ if ([attribute isEqualToString:@"AXStringForTextMarkerRange"])
+ return GetTextForTextMarkerRange(parameter);
+
+ if ([attribute isEqualToString:@"AXAttributedStringForTextMarkerRange"]) {
+ NSString* text = GetTextForTextMarkerRange(parameter);
+ return [[[NSAttributedString alloc] initWithString:text] autorelease];
+ }
+
+ if ([attribute isEqualToString:@"AXNextTextMarkerForTextMarker"]) {
+ BrowserAccessibility* object;
+ int offset;
+ if (!GetTextMarkerData(parameter, &object, &offset))
+ return nil;
+
+ DCHECK(object);
+ if ((object->IsSimpleTextControl() || object->IsTextOnlyObject()) &&
+ offset < static_cast<int>(object->GetText().length())) {
+ ++offset;
+ } else {
+ do {
+ object = BrowserAccessibilityManager::NextTextOnlyObject(object);
+ } while (
+ object &&
+ !(object->IsTextOnlyObject() && object->GetText().length() == 0));
+ if (!object)
+ return nil;
+
+ offset = 0;
+ }
+
+ return CreateTextMarker(*object, offset);
+ }
+
+ if ([attribute isEqualToString:@"AXPreviousTextMarkerForTextMarker"]) {
+ BrowserAccessibility* object;
+ int offset;
+ if (!GetTextMarkerData(parameter, &object, &offset))
+ return nil;
+
+ DCHECK(object);
+ if ((object->IsSimpleTextControl() || object->IsTextOnlyObject()) &&
+ offset > 0) {
+ --offset;
+ } else {
+ do {
+ object = BrowserAccessibilityManager::PreviousTextOnlyObject(object);
+ } while (
+ object &&
+ !(object->IsTextOnlyObject() && object->GetText().length() == 0));
+ if (!object)
+ return nil;
+
+ offset = object->GetText().length() - 1;
+ }
+
+ return CreateTextMarker(*object, offset);
+ }
+
+ if ([attribute
+ isEqualToString:@"AXPreviousWordStartTextMarkerForTextMarker"]) {
+ BrowserAccessibility* object;
+ int offset;
+ if (!GetTextMarkerData(parameter, &object, &offset))
+ return nil;
+
+ DCHECK(object);
+ offset = object->GetWordStartBoundary(offset, ui::BACKWARDS_DIRECTION);
+ return CreateTextMarker(*object, offset);
+ }
+
+ if ([attribute isEqualToString:@"AXLengthForTextMarkerRange"]) {
+ NSString* text = GetTextForTextMarkerRange(parameter);
+ return [NSNumber numberWithInt:[text length]];
+ }
+
if ([attribute isEqualToString:
NSAccessibilityBoundsForRangeParameterizedAttribute]) {
if ([self internalRole] != ui::AX_ROLE_STATIC_TEXT)
@@ -1599,6 +2049,7 @@ bool InitializeAccessibilityTreeSearch(
pointInScreen.x, pointInScreen.y, rect.width(), rect.height());
return [NSValue valueWithRect:nsrect];
}
+
if ([attribute isEqualToString:@"AXUIElementCountForSearchPredicate"]) {
OneShotAccessibilityTreeSearch search(browserAccessibility_);
if (InitializeAccessibilityTreeSearch(&search, parameter))
@@ -1613,63 +2064,90 @@ bool InitializeAccessibilityTreeSearch(
NSMutableArray* result = [NSMutableArray arrayWithCapacity:count];
for (size_t i = 0; i < count; ++i) {
BrowserAccessibility* match = search.GetMatchAtIndex(i);
- [result addObject:match->ToBrowserAccessibilityCocoa()];
+ [result addObject:ToBrowserAccessibilityCocoa(match)];
}
return result;
}
return nil;
}
- // TODO(dtseng): support the following attributes.
- if ([attribute isEqualTo:
- NSAccessibilityRangeForPositionParameterizedAttribute] ||
- [attribute isEqualTo:
- NSAccessibilityRangeForIndexParameterizedAttribute] ||
- [attribute isEqualTo:NSAccessibilityRTFForRangeParameterizedAttribute] ||
- [attribute isEqualTo:
- NSAccessibilityStyleRangeForIndexParameterizedAttribute]) {
- return nil;
- }
return nil;
}
// Returns an array of parameterized attributes names that this object will
// respond to.
- (NSArray*)accessibilityParameterizedAttributeNames {
- if (!browserAccessibility_)
+ if (![self instanceActive])
return nil;
// General attributes.
- NSMutableArray* ret = [NSMutableArray arrayWithObjects:
- @"AXUIElementCountForSearchPredicate",
- @"AXUIElementsForSearchPredicate",
- nil];
+ NSMutableArray* ret = [NSMutableArray
+ arrayWithObjects:
+ @"AXUIElementForTextMarker", @"AXTextMarkerRangeForUIElement",
+ @"AXLineForTextMarker", @"AXTextMarkerRangeForLine",
+ @"AXStringForTextMarkerRange", @"AXTextMarkerForPosition",
+ @"AXBoundsForTextMarkerRange",
+ @"AXAttributedStringForTextMarkerRange",
+ @"AXTextMarkerRangeForUnorderedTextMarkers",
+ @"AXNextTextMarkerForTextMarker",
+ @"AXPreviousTextMarkerForTextMarker",
+ @"AXLeftWordTextMarkerRangeForTextMarker",
+ @"AXRightWordTextMarkerRangeForTextMarker",
+ @"AXLeftLineTextMarkerRangeForTextMarker",
+ @"AXRightLineTextMarkerRangeForTextMarker",
+ @"AXSentenceTextMarkerRangeForTextMarker",
+ @"AXParagraphTextMarkerRangeForTextMarker",
+ @"AXNextWordEndTextMarkerForTextMarker",
+ @"AXPreviousWordStartTextMarkerForTextMarker",
+ @"AXNextLineEndTextMarkerForTextMarker",
+ @"AXPreviousLineStartTextMarkerForTextMarker",
+ @"AXNextSentenceEndTextMarkerForTextMarker",
+ @"AXPreviousSentenceStartTextMarkerForTextMarker",
+ @"AXNextParagraphEndTextMarkerForTextMarker",
+ @"AXPreviousParagraphStartTextMarkerForTextMarker",
+ @"AXStyleTextMarkerRangeForTextMarker", @"AXLengthForTextMarkerRange",
+ NSAccessibilityBoundsForRangeParameterizedAttribute,
+ NSAccessibilityStringForRangeParameterizedAttribute,
+ NSAccessibilityUIElementCountForSearchPredicateParameterizedAttribute,
+ NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute,
+ NSAccessibilityEndTextMarkerForBoundsParameterizedAttribute,
+ NSAccessibilityStartTextMarkerForBoundsParameterizedAttribute,
+ NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute,
+ NSAccessibilitySelectTextWithCriteriaParameterizedAttribute, nil];
if ([[self role] isEqualToString:NSAccessibilityTableRole] ||
[[self role] isEqualToString:NSAccessibilityGridRole]) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- NSAccessibilityCellForColumnAndRowParameterizedAttribute,
- nil]];
+ [ret addObjectsFromArray:@[
+ NSAccessibilityCellForColumnAndRowParameterizedAttribute
+ ]];
}
if (browserAccessibility_->HasState(ui::AX_STATE_EDITABLE)) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- NSAccessibilityLineForIndexParameterizedAttribute,
- NSAccessibilityRangeForLineParameterizedAttribute,
- NSAccessibilityStringForRangeParameterizedAttribute,
- NSAccessibilityRangeForPositionParameterizedAttribute,
- NSAccessibilityRangeForIndexParameterizedAttribute,
- NSAccessibilityBoundsForRangeParameterizedAttribute,
- NSAccessibilityRTFForRangeParameterizedAttribute,
- NSAccessibilityAttributedStringForRangeParameterizedAttribute,
- NSAccessibilityStyleRangeForIndexParameterizedAttribute,
- nil]];
+ [ret addObjectsFromArray:@[
+ NSAccessibilityLineForIndexParameterizedAttribute,
+ NSAccessibilityRangeForLineParameterizedAttribute,
+ NSAccessibilityStringForRangeParameterizedAttribute,
+ NSAccessibilityRangeForPositionParameterizedAttribute,
+ NSAccessibilityRangeForIndexParameterizedAttribute,
+ NSAccessibilityBoundsForRangeParameterizedAttribute,
+ NSAccessibilityRTFForRangeParameterizedAttribute,
+ NSAccessibilityAttributedStringForRangeParameterizedAttribute,
+ NSAccessibilityStyleRangeForIndexParameterizedAttribute
+ ]];
}
if ([self internalRole] == ui::AX_ROLE_STATIC_TEXT) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- NSAccessibilityBoundsForRangeParameterizedAttribute,
- nil]];
+ [ret addObjectsFromArray:@[
+ NSAccessibilityBoundsForRangeParameterizedAttribute
+ ]];
+ }
+
+ if ([self internalRole] == ui::AX_ROLE_ROOT_WEB_AREA ||
+ [self internalRole] == ui::AX_ROLE_WEB_AREA) {
+ [ret addObjectsFromArray: @[
+ NSAccessibilityTextMarkerIsValidParameterizedAttribute,
+ NSAccessibilityIndexForTextMarkerParameterizedAttribute,
+ NSAccessibilityTextMarkerForIndexParameterizedAttribute]];
}
return ret;
@@ -1677,20 +2155,27 @@ bool InitializeAccessibilityTreeSearch(
// Returns an array of action names that this object will respond to.
- (NSArray*)accessibilityActionNames {
- if (!browserAccessibility_)
+ if (![self instanceActive])
return nil;
- NSMutableArray* ret =
- [NSMutableArray arrayWithObject:NSAccessibilityShowMenuAction];
- NSString* role = [self role];
- // TODO(dtseng): this should only get set when there's a default action.
- if (![role isEqualToString:NSAccessibilityStaticTextRole] &&
- ![role isEqualToString:NSAccessibilityTextFieldRole] &&
- ![role isEqualToString:NSAccessibilityTextAreaRole]) {
- [ret addObject:NSAccessibilityPressAction];
+ NSMutableArray* actions = [NSMutableArray
+ arrayWithObjects:NSAccessibilityShowMenuAction,
+ NSAccessibilityScrollToVisibleAction, nil];
+
+ // VoiceOver expects the "press" action to be first.
+ if (browserAccessibility_->IsClickable())
+ [actions insertObject:NSAccessibilityPressAction atIndex:0];
+
+ if (browserAccessibility_->IsMenuRelated())
+ [actions addObject:NSAccessibilityCancelAction];
+
+ if ([self internalRole] == ui::AX_ROLE_SLIDER) {
+ [actions addObjectsFromArray:@[
+ NSAccessibilityIncrementAction, NSAccessibilityDecrementAction
+ ]];
}
- return ret;
+ return actions;
}
// Returns a sub-array of values for the given attribute value, starting at
@@ -1702,7 +2187,7 @@ bool InitializeAccessibilityTreeSearch(
- (NSArray*)accessibilityArrayAttributeValues:(NSString*)attribute
index:(NSUInteger)index
maxCount:(NSUInteger)maxCount {
- if (!browserAccessibility_)
+ if (![self instanceActive])
return nil;
NSArray* fullArray = [self accessibilityAttributeValue:attribute];
@@ -1722,7 +2207,7 @@ bool InitializeAccessibilityTreeSearch(
// Returns the count of the specified accessibility array attribute.
- (NSUInteger)accessibilityArrayAttributeCount:(NSString*)attribute {
- if (!browserAccessibility_)
+ if (![self instanceActive])
return 0;
NSArray* fullArray = [self accessibilityAttributeValue:attribute];
@@ -1731,83 +2216,78 @@ bool InitializeAccessibilityTreeSearch(
// Returns the list of accessibility attributes that this object supports.
- (NSArray*)accessibilityAttributeNames {
- if (!browserAccessibility_)
+ if (![self instanceActive])
return nil;
// General attributes.
- NSMutableArray* ret = [NSMutableArray arrayWithObjects:
- NSAccessibilityChildrenAttribute,
- NSAccessibilityDescriptionAttribute,
- NSAccessibilityEnabledAttribute,
- NSAccessibilityFocusedAttribute,
- NSAccessibilityHelpAttribute,
- NSAccessibilityLinkedUIElementsAttribute,
- NSAccessibilityParentAttribute,
- NSAccessibilityPositionAttribute,
- NSAccessibilityRoleAttribute,
- NSAccessibilityRoleDescriptionAttribute,
- NSAccessibilitySizeAttribute,
- NSAccessibilitySubroleAttribute,
- NSAccessibilityTitleAttribute,
- NSAccessibilityTopLevelUIElementAttribute,
- NSAccessibilityValueAttribute,
- NSAccessibilityWindowAttribute,
- @"AXAccessKey",
- @"AXInvalid",
- @"AXVisited",
- nil];
+ NSMutableArray* ret = [NSMutableArray
+ arrayWithObjects:NSAccessibilityAccessKeyAttribute,
+ NSAccessibilityChildrenAttribute,
+ NSAccessibilityDescriptionAttribute,
+ NSAccessibilityEnabledAttribute,
+ NSAccessibilityEndTextMarkerAttribute,
+ NSAccessibilityFocusedAttribute,
+ NSAccessibilityHelpAttribute,
+ NSAccessibilityInvalidAttribute,
+ NSAccessibilityLinkedUIElementsAttribute,
+ NSAccessibilityParentAttribute,
+ NSAccessibilityPositionAttribute,
+ NSAccessibilityRoleAttribute,
+ NSAccessibilityRoleDescriptionAttribute,
+ NSAccessibilitySelectedTextMarkerRangeAttribute,
+ NSAccessibilitySizeAttribute,
+ NSAccessibilityStartTextMarkerAttribute,
+ NSAccessibilitySubroleAttribute,
+ NSAccessibilityTitleAttribute,
+ NSAccessibilityTitleUIElementAttribute,
+ NSAccessibilityTopLevelUIElementAttribute,
+ NSAccessibilityValueAttribute,
+ NSAccessibilityVisitedAttribute,
+ NSAccessibilityWindowAttribute, nil];
// Specific role attributes.
NSString* role = [self role];
NSString* subrole = [self subrole];
if ([role isEqualToString:NSAccessibilityTableRole] ||
[role isEqualToString:NSAccessibilityGridRole]) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- NSAccessibilityColumnsAttribute,
- NSAccessibilityVisibleColumnsAttribute,
- NSAccessibilityRowsAttribute,
- NSAccessibilityVisibleRowsAttribute,
- NSAccessibilityVisibleCellsAttribute,
- NSAccessibilityHeaderAttribute,
- NSAccessibilityColumnHeaderUIElementsAttribute,
- NSAccessibilityRowHeaderUIElementsAttribute,
- nil]];
+ [ret addObjectsFromArray:@[
+ NSAccessibilityColumnsAttribute, NSAccessibilityVisibleColumnsAttribute,
+ NSAccessibilityRowsAttribute, NSAccessibilityVisibleRowsAttribute,
+ NSAccessibilityVisibleCellsAttribute, NSAccessibilityHeaderAttribute,
+ NSAccessibilityColumnHeaderUIElementsAttribute,
+ NSAccessibilityRowHeaderUIElementsAttribute
+ ]];
} else if ([role isEqualToString:NSAccessibilityColumnRole]) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- NSAccessibilityIndexAttribute,
- NSAccessibilityHeaderAttribute,
- NSAccessibilityRowsAttribute,
- NSAccessibilityVisibleRowsAttribute,
- nil]];
+ [ret addObjectsFromArray:@[
+ NSAccessibilityIndexAttribute, NSAccessibilityHeaderAttribute,
+ NSAccessibilityRowsAttribute, NSAccessibilityVisibleRowsAttribute
+ ]];
} else if ([role isEqualToString:NSAccessibilityCellRole]) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- NSAccessibilityColumnIndexRangeAttribute,
- NSAccessibilityRowIndexRangeAttribute,
- @"AXSortDirection",
- nil]];
+ [ret addObjectsFromArray:@[
+ NSAccessibilityColumnIndexRangeAttribute,
+ NSAccessibilityRowIndexRangeAttribute, @"AXSortDirection"
+ ]];
} else if ([role isEqualToString:@"AXWebArea"]) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- @"AXLoaded",
- @"AXLoadingProgress",
- nil]];
+ [ret addObjectsFromArray:@[
+ @"AXLoaded", NSAccessibilityLoadingProgressAttribute
+ ]];
} else if ([role isEqualToString:NSAccessibilityTabGroupRole]) {
[ret addObject:NSAccessibilityTabsAttribute];
} else if ([role isEqualToString:NSAccessibilityProgressIndicatorRole] ||
[role isEqualToString:NSAccessibilitySliderRole] ||
[role isEqualToString:NSAccessibilityIncrementorRole] ||
[role isEqualToString:NSAccessibilityScrollBarRole]) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- NSAccessibilityMaxValueAttribute,
- NSAccessibilityMinValueAttribute,
- NSAccessibilityValueDescriptionAttribute,
- nil]];
+ [ret addObjectsFromArray:@[
+ NSAccessibilityMaxValueAttribute, NSAccessibilityMinValueAttribute,
+ NSAccessibilityValueDescriptionAttribute
+ ]];
} else if ([subrole isEqualToString:NSAccessibilityOutlineRowSubrole]) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- NSAccessibilityDisclosingAttribute,
- NSAccessibilityDisclosedByRowAttribute,
- NSAccessibilityDisclosureLevelAttribute,
- NSAccessibilityDisclosedRowsAttribute,
- nil]];
+ [ret addObjectsFromArray:@[
+ NSAccessibilityDisclosingAttribute,
+ NSAccessibilityDisclosedByRowAttribute,
+ NSAccessibilityDisclosureLevelAttribute,
+ NSAccessibilityDisclosedRowsAttribute
+ ]];
} else if ([role isEqualToString:NSAccessibilityRowRole]) {
if (browserAccessibility_->GetParent()) {
base::string16 parentRole;
@@ -1815,126 +2295,99 @@ bool InitializeAccessibilityTreeSearch(
"role", &parentRole);
const base::string16 treegridRole(base::ASCIIToUTF16("treegrid"));
if (parentRole == treegridRole) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- NSAccessibilityDisclosingAttribute,
- NSAccessibilityDisclosedByRowAttribute,
- NSAccessibilityDisclosureLevelAttribute,
- NSAccessibilityDisclosedRowsAttribute,
- nil]];
+ [ret addObjectsFromArray:@[
+ NSAccessibilityDisclosingAttribute,
+ NSAccessibilityDisclosedByRowAttribute,
+ NSAccessibilityDisclosureLevelAttribute,
+ NSAccessibilityDisclosedRowsAttribute
+ ]];
} else {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- NSAccessibilityIndexAttribute,
- nil]];
+ [ret addObjectsFromArray:@[ NSAccessibilityIndexAttribute ]];
}
}
} else if ([role isEqualToString:NSAccessibilityListRole]) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- NSAccessibilitySelectedChildrenAttribute,
- NSAccessibilityVisibleChildrenAttribute,
- nil]];
+ [ret addObjectsFromArray:@[
+ NSAccessibilitySelectedChildrenAttribute,
+ NSAccessibilityVisibleChildrenAttribute
+ ]];
}
// Caret navigation and text selection attributes.
if (browserAccessibility_->HasState(ui::AX_STATE_EDITABLE)) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- NSAccessibilityInsertionPointLineNumberAttribute,
- NSAccessibilityNumberOfCharactersAttribute,
- NSAccessibilitySelectedTextAttribute,
- NSAccessibilitySelectedTextRangeAttribute,
- NSAccessibilityVisibleCharacterRangeAttribute,
- nil]];
+ [ret addObjectsFromArray:@[
+ NSAccessibilityInsertionPointLineNumberAttribute,
+ NSAccessibilityNumberOfCharactersAttribute,
+ NSAccessibilitySelectedTextAttribute,
+ NSAccessibilitySelectedTextRangeAttribute,
+ NSAccessibilityVisibleCharacterRangeAttribute
+ ]];
}
// Add the url attribute only if it has a valid url.
if ([self url] != nil) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- NSAccessibilityURLAttribute,
- nil]];
+ [ret addObjectsFromArray:@[ NSAccessibilityURLAttribute ]];
}
// Position in set and Set size
if (browserAccessibility_->HasIntAttribute(ui::AX_ATTR_POS_IN_SET)) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- @"AXARIAPosInSet",
- nil]];
+ [ret addObjectsFromArray:@[ NSAccessibilityARIAPosInSetAttribute ]];
}
if (browserAccessibility_->HasIntAttribute(ui::AX_ATTR_SET_SIZE)) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- @"AXARIASetSize",
- nil]];
+ [ret addObjectsFromArray:@[ NSAccessibilityARIASetSizeAttribute ]];
}
// Live regions.
if (browserAccessibility_->HasStringAttribute(
ui::AX_ATTR_LIVE_STATUS)) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- @"AXARIALive",
- nil]];
+ [ret addObjectsFromArray:@[ NSAccessibilityARIALiveAttribute ]];
}
if (browserAccessibility_->HasStringAttribute(
ui::AX_ATTR_LIVE_RELEVANT)) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- @"AXARIARelevant",
- nil]];
+ [ret addObjectsFromArray:@[ NSAccessibilityARIARelevantAttribute ]];
}
if (browserAccessibility_->HasBoolAttribute(
ui::AX_ATTR_LIVE_ATOMIC)) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- @"AXARIAAtomic",
- nil]];
+ [ret addObjectsFromArray:@[ NSAccessibilityARIAAtomicAttribute ]];
}
if (browserAccessibility_->HasBoolAttribute(
ui::AX_ATTR_LIVE_BUSY)) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- @"AXARIABusy",
- nil]];
+ [ret addObjectsFromArray:@[ NSAccessibilityARIABusyAttribute ]];
}
std::string dropEffect;
if (browserAccessibility_->GetHtmlAttribute("aria-dropeffect", &dropEffect)) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- @"AXDropEffects",
- nil]];
+ [ret addObjectsFromArray:@[ NSAccessibilityDropEffectsAttribute ]];
}
std::string grabbed;
if (browserAccessibility_->GetHtmlAttribute("aria-grabbed", &grabbed)) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- @"AXGrabbed",
- nil]];
+ [ret addObjectsFromArray:@[ NSAccessibilityGrabbedAttribute ]];
}
// Add expanded attribute only if it has expanded or collapsed state.
if (GetState(browserAccessibility_, ui::AX_STATE_EXPANDED) ||
GetState(browserAccessibility_, ui::AX_STATE_COLLAPSED)) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- NSAccessibilityExpandedAttribute,
- nil]];
+ [ret addObjectsFromArray:@[ NSAccessibilityExpandedAttribute ]];
}
if (GetState(browserAccessibility_, ui::AX_STATE_VERTICAL)
|| GetState(browserAccessibility_, ui::AX_STATE_HORIZONTAL)) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- NSAccessibilityOrientationAttribute, nil]];
+ [ret addObjectsFromArray:@[ NSAccessibilityOrientationAttribute ]];
}
if (browserAccessibility_->HasStringAttribute(ui::AX_ATTR_PLACEHOLDER)) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- NSAccessibilityPlaceholderValueAttribute, nil]];
+ [ret addObjectsFromArray:@[ NSAccessibilityPlaceholderValueAttribute ]];
}
if (GetState(browserAccessibility_, ui::AX_STATE_REQUIRED)) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- @"AXRequired", nil]];
+ [ret addObjectsFromArray:@[ @"AXRequired" ]];
}
// Title UI Element.
if (browserAccessibility_->HasIntListAttribute(ui::AX_ATTR_LABELLEDBY_IDS) &&
browserAccessibility_->GetIntListAttribute(ui::AX_ATTR_LABELLEDBY_IDS)
.size() > 0) {
- [ret addObjectsFromArray:[NSArray arrayWithObjects:
- NSAccessibilityTitleUIElementAttribute,
- nil]];
+ [ret addObjectsFromArray:@[ NSAccessibilityTitleUIElementAttribute ]];
}
// TODO(aboxhall): expose NSAccessibilityServesAsTitleForUIElementsAttribute
// for elements which are referred to by labelledby or are labels
@@ -1944,7 +2397,7 @@ bool InitializeAccessibilityTreeSearch(
// Returns the index of the child in this objects array of children.
- (NSUInteger)accessibilityGetIndexOf:(id)child {
- if (!browserAccessibility_)
+ if (![self instanceActive])
return 0;
NSUInteger index = 0;
@@ -1959,7 +2412,7 @@ bool InitializeAccessibilityTreeSearch(
// Returns whether or not the specified attribute can be set by the
// accessibility API via |accessibilitySetValue:forAttribute:|.
- (BOOL)accessibilityIsAttributeSettable:(NSString*)attribute {
- if (!browserAccessibility_)
+ if (![self instanceActive])
return NO;
if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
@@ -1985,7 +2438,7 @@ bool InitializeAccessibilityTreeSearch(
// Returns whether or not this object should be ignored in the accessibility
// tree.
- (BOOL)accessibilityIsIgnored {
- if (!browserAccessibility_)
+ if (![self instanceActive])
return YES;
return [self isIgnored];
@@ -1994,7 +2447,7 @@ bool InitializeAccessibilityTreeSearch(
// Performs the given accessibility action on the webkit accessibility object
// that backs this object.
- (void)accessibilityPerformAction:(NSString*)action {
- if (!browserAccessibility_)
+ if (![self instanceActive])
return;
// TODO(dmazzoni): Support more actions.
@@ -2009,7 +2462,7 @@ bool InitializeAccessibilityTreeSearch(
// Returns the description of the given action.
- (NSString*)accessibilityActionDescription:(NSString*)action {
- if (!browserAccessibility_)
+ if (![self instanceActive])
return nil;
return NSAccessibilityActionDescription(action);
@@ -2019,12 +2472,14 @@ bool InitializeAccessibilityTreeSearch(
// This class does not support this.
- (BOOL)accessibilitySetOverrideValue:(id)value
forAttribute:(NSString*)attribute {
+ if (![self instanceActive])
+ return NO;
return NO;
}
// Sets the value for an accessibility attribute via the accessibility API.
- (void)accessibilitySetValue:(id)value forAttribute:(NSString*)attribute {
- if (!browserAccessibility_)
+ if (![self instanceActive])
return;
if ([attribute isEqualToString:NSAccessibilityFocusedAttribute]) {
@@ -2032,7 +2487,7 @@ bool InitializeAccessibilityTreeSearch(
NSNumber* focusedNumber = value;
BOOL focused = [focusedNumber intValue];
if (focused)
- manager->SetFocus(browserAccessibility_, true);
+ manager->SetFocus(*browserAccessibility_);
}
if ([attribute isEqualToString:NSAccessibilitySelectedTextRangeAttribute]) {
NSRange range = [(NSValue*)value rangeValue];
@@ -2047,7 +2502,7 @@ bool InitializeAccessibilityTreeSearch(
// or one of its children, so this will never return nil unless this
// object is invalid.
- (id)accessibilityHitTest:(NSPoint)point {
- if (!browserAccessibility_)
+ if (![self instanceActive])
return nil;
BrowserAccessibilityCocoa* hit = self;
@@ -2079,7 +2534,7 @@ bool InitializeAccessibilityTreeSearch(
- (NSUInteger)hash {
// Potentially called during dealloc.
- if (!browserAccessibility_)
+ if (![self instanceActive])
return [super hash];
return browserAccessibility_->GetId();
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_mac.h b/chromium/content/browser/accessibility/browser_accessibility_mac.h
index aed8fd49e08..d5160243274 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_mac.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_mac.h
@@ -11,11 +11,19 @@
#include "base/macros.h"
#include "content/browser/accessibility/browser_accessibility.h"
+#include "content/common/content_export.h"
@class BrowserAccessibilityCocoa;
namespace content {
+#if __OBJC__
+CONTENT_EXPORT const BrowserAccessibilityCocoa* ToBrowserAccessibilityCocoa(
+ const BrowserAccessibility* obj);
+CONTENT_EXPORT BrowserAccessibilityCocoa* ToBrowserAccessibilityCocoa(
+ BrowserAccessibility* obj);
+#endif
+
class BrowserAccessibilityMac : public BrowserAccessibility {
public:
// BrowserAccessibility overrides.
diff --git a/chromium/content/browser/accessibility/browser_accessibility_mac.mm b/chromium/content/browser/accessibility/browser_accessibility_mac.mm
index da1f55e9673..34475bdc309 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_mac.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_mac.mm
@@ -64,13 +64,17 @@ void BrowserAccessibilityMac::RecreateNativeObject() {
}
const BrowserAccessibilityCocoa*
-BrowserAccessibility::ToBrowserAccessibilityCocoa() const {
- return static_cast<const BrowserAccessibilityMac*>(this)->native_view();
+ToBrowserAccessibilityCocoa(const BrowserAccessibility* obj) {
+ DCHECK(obj);
+ DCHECK(obj->IsNative());
+ return static_cast<const BrowserAccessibilityMac*>(obj)->native_view();
}
-BrowserAccessibilityCocoa* BrowserAccessibility::ToBrowserAccessibilityCocoa() {
- return static_cast<BrowserAccessibilityMac*>(this)->
- native_view();
+BrowserAccessibilityCocoa* ToBrowserAccessibilityCocoa(
+ BrowserAccessibility* obj) {
+ DCHECK(obj);
+ DCHECK(obj->IsNative());
+ return static_cast<BrowserAccessibilityMac*>(obj)->native_view();
}
} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm b/chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm
index c85957fab59..0b2511dc09d 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_mac_unittest.mm
@@ -8,6 +8,7 @@
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/accessibility/browser_accessibility_cocoa.h"
+#include "content/browser/accessibility/browser_accessibility_mac.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/accessibility/browser_accessibility_manager_mac.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -53,7 +54,7 @@ class BrowserAccessibilityTest : public ui::CocoaTest {
nil,
MakeAXTreeUpdate(root, child1, child2),
NULL));
- accessibility_.reset([manager_->GetRoot()->ToBrowserAccessibilityCocoa()
+ accessibility_.reset([ToBrowserAccessibilityCocoa(manager_->GetRoot())
retain]);
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.cc b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
index 8979f10f0f0..f95f5085c33 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.cc
@@ -43,6 +43,10 @@ using AXTreeIDMap =
base::hash_map<AXTreeIDRegistry::AXTreeID, BrowserAccessibilityManager*>;
base::LazyInstance<AXTreeIDMap> g_ax_tree_id_map = LAZY_INSTANCE_INITIALIZER;
+// A function to call when focus changes, for testing only.
+base::LazyInstance<base::Closure> g_focus_change_callback_for_testing =
+ LAZY_INSTANCE_INITIALIZER;
+
ui::AXTreeUpdate MakeAXTreeUpdate(
const ui::AXNodeData& node1,
const ui::AXNodeData& node2 /* = ui::AXNodeData() */,
@@ -87,11 +91,7 @@ ui::AXTreeUpdate MakeAXTreeUpdate(
}
BrowserAccessibility* BrowserAccessibilityFactory::Create() {
-#if defined(OS_ANDROID) && defined(USE_AURA)
- return nullptr;
-#else
return BrowserAccessibility::Create();
-#endif
}
BrowserAccessibilityFindInPageInfo::BrowserAccessibilityFindInPageInfo()
@@ -127,9 +127,11 @@ BrowserAccessibilityManager::BrowserAccessibilityManager(
: delegate_(delegate),
factory_(factory),
tree_(new ui::AXSerializableTree()),
- focus_(NULL),
user_is_navigating_away_(false),
osk_state_(OSK_ALLOWED),
+ last_focused_node_(nullptr),
+ last_focused_manager_(nullptr),
+ connected_to_parent_tree_node_(false),
ax_tree_id_(AXTreeIDRegistry::kNoAXTreeID),
parent_node_id_from_parent_tree_(0) {
tree_->SetDelegate(this);
@@ -142,9 +144,10 @@ BrowserAccessibilityManager::BrowserAccessibilityManager(
: delegate_(delegate),
factory_(factory),
tree_(new ui::AXSerializableTree()),
- focus_(NULL),
user_is_navigating_away_(false),
osk_state_(OSK_ALLOWED),
+ last_focused_node_(nullptr),
+ last_focused_manager_(nullptr),
ax_tree_id_(AXTreeIDRegistry::kNoAXTreeID),
parent_node_id_from_parent_tree_(0) {
tree_->SetDelegate(this);
@@ -166,9 +169,6 @@ void BrowserAccessibilityManager::Initialize(
LOG(FATAL) << tree_->error();
}
}
-
- if (!focus_)
- SetFocus(tree_->root(), false);
}
// static
@@ -182,6 +182,49 @@ BrowserAccessibilityManager::GetEmptyDocument() {
return update;
}
+void BrowserAccessibilityManager::FireFocusEventsIfNeeded() {
+ BrowserAccessibility* focus = GetFocus();
+
+ // Don't fire focus events if the window itself doesn't have focus.
+ // Bypass this check if a global focus listener was set up for testing
+ // so that the test passes whether the window is active or not.
+ if (g_focus_change_callback_for_testing.Get().is_null()) {
+ if (delegate_ && !delegate_->AccessibilityViewHasFocus())
+ focus = nullptr;
+
+ if (!CanFireEvents())
+ focus = nullptr;
+ }
+
+ // Don't allow the document to be focused if it has no children and
+ // hasn't finished loading yet. Wait for at least a tiny bit of content,
+ // or for the document to actually finish loading.
+ if (focus &&
+ focus == focus->manager()->GetRoot() &&
+ focus->PlatformChildCount() == 0 &&
+ !focus->HasState(ui::AX_STATE_BUSY) &&
+ !focus->manager()->GetTreeData().loaded) {
+ focus = nullptr;
+ }
+
+ if (focus && focus != last_focused_node_)
+ FireFocusEvent(focus);
+
+ last_focused_node_ = focus;
+ last_focused_manager_ = focus ? focus->manager() : nullptr;
+}
+
+bool BrowserAccessibilityManager::CanFireEvents() {
+ return true;
+}
+
+void BrowserAccessibilityManager::FireFocusEvent(BrowserAccessibility* node) {
+ NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, node);
+
+ if (!g_focus_change_callback_for_testing.Get().is_null())
+ g_focus_change_callback_for_testing.Get().Run();
+}
+
BrowserAccessibility* BrowserAccessibilityManager::GetRoot() {
// tree_ can be null during destruction.
if (!tree_)
@@ -247,13 +290,15 @@ const ui::AXTreeData& BrowserAccessibilityManager::GetTreeData() {
}
void BrowserAccessibilityManager::OnWindowFocused() {
- if (focus_)
- NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, GetFromAXNode(focus_));
+ if (this == GetRootManager())
+ FireFocusEventsIfNeeded();
}
void BrowserAccessibilityManager::OnWindowBlurred() {
- if (focus_)
- NotifyAccessibilityEvent(ui::AX_EVENT_BLUR, GetFromAXNode(focus_));
+ if (this == GetRootManager()) {
+ last_focused_node_ = nullptr;
+ last_focused_manager_ = nullptr;
+ }
}
void BrowserAccessibilityManager::UserIsNavigatingAway() {
@@ -273,11 +318,12 @@ void BrowserAccessibilityManager::NavigationFailed() {
}
void BrowserAccessibilityManager::GotMouseDown() {
- if (!focus_)
+ BrowserAccessibility* focus = GetFocus();
+ if (!focus)
return;
osk_state_ = OSK_ALLOWED_WITHIN_FOCUSED_OBJECT;
- NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, GetFromAXNode(focus_));
+ NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, focus);
}
bool BrowserAccessibilityManager::UseRootScrollOffsetsWhenComputingBounds() {
@@ -286,8 +332,6 @@ bool BrowserAccessibilityManager::UseRootScrollOffsetsWhenComputingBounds() {
void BrowserAccessibilityManager::OnAccessibilityEvents(
const std::vector<AXEventNotificationDetails>& details) {
- bool should_send_initial_focus = false;
-
// Process all changes to the accessibility tree first.
for (uint32_t index = 0; index < details.size(); ++index) {
const AXEventNotificationDetails& detail = details[index];
@@ -300,18 +344,31 @@ void BrowserAccessibilityManager::OnAccessibilityEvents(
}
return;
}
+ }
- // Set focus to the root if it's not anywhere else.
- if (!focus_) {
- SetFocus(tree_->root(), false);
- should_send_initial_focus = true;
+ // If the root's parent is in another accessibility tree but it wasn't
+ // previously connected, post the proper notifications on the parent.
+ BrowserAccessibility* parent = GetParentNodeFromParentTree();
+ if (parent) {
+ if (!connected_to_parent_tree_node_) {
+ parent->OnDataChanged();
+ parent->UpdatePlatformAttributes();
+ parent->manager()->NotifyAccessibilityEvent(
+ ui::AX_EVENT_CHILDREN_CHANGED, parent);
+ connected_to_parent_tree_node_ = true;
}
+ } else {
+ connected_to_parent_tree_node_ = false;
}
- if (should_send_initial_focus && NativeViewHasFocus())
- NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, GetFromAXNode(focus_));
+ // Based on the changes to the tree, first fire focus events if needed.
+ // Screen readers might not do the right thing if they're not aware of what
+ // has focus, so always try that first. Nothing will be fired if the window
+ // itself isn't focused or if focus hasn't changed.
+ GetRootManager()->FireFocusEventsIfNeeded();
- // Now iterate over the events again and fire the events.
+ // Now iterate over the events again and fire the events other than focus
+ // events.
for (uint32_t index = 0; index < details.size(); index++) {
const AXEventNotificationDetails& detail = details[index];
@@ -324,19 +381,22 @@ void BrowserAccessibilityManager::OnAccessibilityEvents(
ui::AXEvent event_type = detail.event_type;
if (event_type == ui::AX_EVENT_FOCUS ||
event_type == ui::AX_EVENT_BLUR) {
- SetFocus(node, false);
-
if (osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_HIDDEN &&
osk_state_ != OSK_DISALLOWED_BECAUSE_TAB_JUST_APPEARED)
osk_state_ = OSK_ALLOWED;
- // Don't send a native focus event if the window itself doesn't
- // have focus.
- if (!NativeViewHasFocus())
+ bool is_menu_list_option =
+ node->data().role == ui::AX_ROLE_MENU_LIST_OPTION;
+
+ // Skip all focus events other than ones on menu list options;
+ // we've already handled them, above. Menu list options are a weird
+ // exception because the menu list itself has focus but we need to fire
+ // focus events on the individual options.
+ if (!is_menu_list_option)
continue;
}
- // Send the event event to the operating system.
+ // Fire the native event.
NotifyAccessibilityEvent(event_type, GetFromAXNode(node));
}
}
@@ -349,7 +409,16 @@ void BrowserAccessibilityManager::OnLocationChanges(
continue;
ui::AXNode* node = obj->node();
node->SetLocation(params[i].new_location);
- obj->OnLocationChanged();
+ }
+ SendLocationChangeEvents(params);
+}
+
+void BrowserAccessibilityManager::SendLocationChangeEvents(
+ const std::vector<AccessibilityHostMsg_LocationChangeParams>& params) {
+ for (size_t i = 0; i < params.size(); ++i) {
+ BrowserAccessibility* obj = GetFromID(params[i].id);
+ if (obj)
+ obj->OnLocationChanged();
}
}
@@ -367,6 +436,22 @@ void BrowserAccessibilityManager::OnFindInPageResult(
ActivateFindInPageResult(request_id);
}
+void BrowserAccessibilityManager::OnChildFrameHitTestResult(
+ const gfx::Point& point,
+ int hit_obj_id) {
+ BrowserAccessibility* obj = GetFromID(hit_obj_id);
+ if (!obj || !obj->HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID))
+ return;
+
+ BrowserAccessibilityManager* child_manager =
+ BrowserAccessibilityManager::FromID(
+ obj->GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID));
+ if (!child_manager || !child_manager->delegate())
+ return;
+
+ return child_manager->delegate()->AccessibilityHitTest(point);
+}
+
void BrowserAccessibilityManager::ActivateFindInPageResult(
int request_id) {
find_in_page_info_.active_request_id = request_id;
@@ -391,20 +476,19 @@ void BrowserAccessibilityManager::ActivateFindInPageResult(
}
BrowserAccessibility* BrowserAccessibilityManager::GetActiveDescendantFocus(
- BrowserAccessibility* root) {
- BrowserAccessibility* node = BrowserAccessibilityManager::GetFocus(root);
- if (!node)
+ BrowserAccessibility* focus) {
+ if (!focus)
return NULL;
int active_descendant_id;
- if (node->GetIntAttribute(ui::AX_ATTR_ACTIVEDESCENDANT_ID,
- &active_descendant_id)) {
+ if (focus->GetIntAttribute(ui::AX_ATTR_ACTIVEDESCENDANT_ID,
+ &active_descendant_id)) {
BrowserAccessibility* active_descendant =
- node->manager()->GetFromID(active_descendant_id);
+ focus->manager()->GetFromID(active_descendant_id);
if (active_descendant)
return active_descendant;
}
- return node;
+ return focus;
}
bool BrowserAccessibilityManager::NativeViewHasFocus() {
@@ -414,39 +498,55 @@ bool BrowserAccessibilityManager::NativeViewHasFocus() {
return false;
}
-BrowserAccessibility* BrowserAccessibilityManager::GetFocus(
- BrowserAccessibility* root) {
- if (!focus_)
- return nullptr;
+BrowserAccessibility* BrowserAccessibilityManager::GetFocus() {
+ BrowserAccessibilityManager* root_manager = GetRootManager();
+ if (!root_manager)
+ root_manager = this;
+ int32_t focused_tree_id = root_manager->GetTreeData().focused_tree_id;
- if (root && !focus_->IsDescendantOf(root->node()))
- return nullptr;
+ BrowserAccessibilityManager* focused_manager = nullptr;
+ if (focused_tree_id)
+ focused_manager =BrowserAccessibilityManager::FromID(focused_tree_id);
+ if (!focused_manager)
+ focused_manager = root_manager;
+
+ return focused_manager->GetFocusFromThisOrDescendantFrame();
+}
+
+BrowserAccessibility*
+BrowserAccessibilityManager::GetFocusFromThisOrDescendantFrame() {
+ int32_t focus_id = GetTreeData().focus_id;
+ BrowserAccessibility* obj = GetFromID(focus_id);
+ if (!obj)
+ return GetRoot();
- BrowserAccessibility* obj = GetFromAXNode(focus_);
- DCHECK(obj);
if (obj->HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)) {
BrowserAccessibilityManager* child_manager =
BrowserAccessibilityManager::FromID(
obj->GetIntAttribute(ui::AX_ATTR_CHILD_TREE_ID));
if (child_manager)
- return child_manager->GetFocus(child_manager->GetRoot());
+ return child_manager->GetFocusFromThisOrDescendantFrame();
}
return obj;
}
-void BrowserAccessibilityManager::SetFocus(ui::AXNode* node, bool notify) {
- if (focus_ != node)
- focus_ = node;
+void BrowserAccessibilityManager::SetFocus(const BrowserAccessibility& node) {
+ if (delegate_)
+ delegate_->AccessibilitySetFocus(node.GetId());
+}
- if (notify && node && delegate_)
- delegate_->AccessibilitySetFocus(node->id());
+void BrowserAccessibilityManager::SetFocusLocallyForTesting(
+ BrowserAccessibility* node) {
+ ui::AXTreeData data = GetTreeData();
+ data.focus_id = node->GetId();
+ tree_->UpdateData(data);
}
-void BrowserAccessibilityManager::SetFocus(
- BrowserAccessibility* obj, bool notify) {
- if (obj->node())
- SetFocus(obj->node(), notify);
+// static
+void BrowserAccessibilityManager::SetFocusChangeCallbackForTesting(
+ const base::Closure& callback) {
+ g_focus_change_callback_for_testing.Get() = callback;
}
void BrowserAccessibilityManager::DoDefaultAction(
@@ -500,33 +600,35 @@ gfx::Rect BrowserAccessibilityManager::GetViewBounds() {
return gfx::Rect();
}
+// static
BrowserAccessibility* BrowserAccessibilityManager::NextInTreeOrder(
- BrowserAccessibility* node) const {
- if (!node)
+ const BrowserAccessibility* object) {
+ if (!object)
return nullptr;
- if (node->PlatformChildCount())
- return node->PlatformGetChild(0);
+ if (object->PlatformChildCount())
+ return object->PlatformGetChild(0);
- while (node) {
- const auto sibling = node->GetNextSibling();
+ while (object) {
+ BrowserAccessibility* sibling = object->GetNextSibling();
if (sibling)
return sibling;
- node = node->GetParent();
+ object = object->GetParent();
}
return nullptr;
}
+// static
BrowserAccessibility* BrowserAccessibilityManager::PreviousInTreeOrder(
- BrowserAccessibility* node) const {
- if (!node)
+ const BrowserAccessibility* object) {
+ if (!object)
return nullptr;
- const auto sibling = node->GetPreviousSibling();
+ BrowserAccessibility* sibling = object->GetPreviousSibling();
if (!sibling)
- return node->GetParent();
+ return object->GetParent();
if (sibling->PlatformChildCount())
return sibling->PlatformDeepestLastChild();
@@ -534,36 +636,168 @@ BrowserAccessibility* BrowserAccessibilityManager::PreviousInTreeOrder(
return sibling;
}
+// static
BrowserAccessibility* BrowserAccessibilityManager::PreviousTextOnlyObject(
- BrowserAccessibility* node) const {
- BrowserAccessibility* previous_node = PreviousInTreeOrder(node);
- while (previous_node && !previous_node->IsTextOnlyObject())
- previous_node = PreviousInTreeOrder(previous_node);
+ const BrowserAccessibility* object) {
+ BrowserAccessibility* previous_object = PreviousInTreeOrder(object);
+ while (previous_object && !previous_object->IsTextOnlyObject())
+ previous_object = PreviousInTreeOrder(previous_object);
- return previous_node;
+ return previous_object;
}
+// static
BrowserAccessibility* BrowserAccessibilityManager::NextTextOnlyObject(
- BrowserAccessibility* node) const {
- BrowserAccessibility* next_node = NextInTreeOrder(node);
- while (next_node && !next_node->IsTextOnlyObject())
- next_node = NextInTreeOrder(next_node);
+ const BrowserAccessibility* object) {
+ BrowserAccessibility* next_object = NextInTreeOrder(object);
+ while (next_object && !next_object->IsTextOnlyObject())
+ next_object = NextInTreeOrder(next_object);
+
+ return next_object;
+}
+
+// static
+bool BrowserAccessibilityManager::FindIndicesInCommonParent(
+ const BrowserAccessibility& object1,
+ const BrowserAccessibility& object2,
+ BrowserAccessibility** common_parent,
+ int* child_index1,
+ int* child_index2) {
+ DCHECK(common_parent && child_index1 && child_index2);
+ auto ancestor1 = const_cast<BrowserAccessibility*>(&object1);
+ auto ancestor2 = const_cast<BrowserAccessibility*>(&object2);
+ do {
+ *child_index1 = ancestor1->GetIndexInParent();
+ ancestor1 = ancestor1->GetParent();
+ } while (
+ ancestor1 &&
+ // |BrowserAccessibility::IsAncestorOf| returns true if objects are equal.
+ (ancestor1 == ancestor2 || !ancestor2->IsDescendantOf(ancestor1)));
+
+ if (!ancestor1) {
+ *common_parent = nullptr;
+ *child_index1 = -1;
+ *child_index2 = -1;
+ return false;
+ }
+
+ do {
+ *child_index2 = ancestor2->GetIndexInParent();
+ ancestor2 = ancestor2->GetParent();
+ } while (ancestor1 != ancestor2);
+
+ *common_parent = ancestor1;
+ return true;
+}
+
+// static
+base::string16 BrowserAccessibilityManager::GetTextForRange(
+ const BrowserAccessibility& start_object,
+ int start_offset,
+ const BrowserAccessibility& end_object,
+ int end_offset) {
+ DCHECK_GE(start_offset, 0);
+ DCHECK_GE(end_offset, 0);
+
+ if (&start_object == &end_object && start_object.IsSimpleTextControl()) {
+ if (start_offset > end_offset)
+ std::swap(start_offset, end_offset);
+
+ if (start_offset >= static_cast<int>(start_object.GetValue().length()) ||
+ end_offset > static_cast<int>(start_object.GetValue().length())) {
+ return base::string16();
+ }
+
+ return start_object.GetValue().substr(start_offset,
+ end_offset - start_offset);
+ }
+
+ int child_index1 = -1;
+ int child_index2 = -1;
+ if (&start_object != &end_object) {
+ BrowserAccessibility* common_parent;
+ if (!FindIndicesInCommonParent(start_object, end_object, &common_parent,
+ &child_index1, &child_index2)) {
+ return base::string16();
+ }
- return next_node;
+ DCHECK(common_parent);
+ DCHECK_GE(child_index1, 0);
+ DCHECK_GE(child_index2, 0);
+ // If the child indices are equal, one object is a descendant of the other.
+ DCHECK(child_index1 != child_index2 ||
+ start_object.IsDescendantOf(&end_object) ||
+ end_object.IsDescendantOf(&start_object));
+ }
+
+ const BrowserAccessibility* start_text_object = nullptr;
+ const BrowserAccessibility* end_text_object = nullptr;
+ if (child_index1 <= child_index2 ||
+ end_object.IsDescendantOf(&start_object)) {
+ start_text_object = &start_object;
+ end_text_object = &end_object;
+ } else if (child_index1 > child_index2 ||
+ start_object.IsDescendantOf(&end_object)) {
+ start_text_object = &end_object;
+ end_text_object = &start_object;
+ }
+
+ if (!start_text_object->PlatformIsLeaf())
+ start_text_object = start_text_object->PlatformDeepestFirstChild();
+ if (!end_text_object->PlatformIsLeaf())
+ end_text_object = end_text_object->PlatformDeepestLastChild();
+
+ if (!start_text_object->IsTextOnlyObject())
+ start_text_object = NextTextOnlyObject(start_text_object);
+ if (!end_text_object->IsTextOnlyObject())
+ end_text_object = PreviousTextOnlyObject(end_text_object);
+
+ if (!start_text_object || !end_text_object)
+ return base::string16();
+
+ // Be a little permissive with the start and end offsets.
+ if (start_text_object == end_text_object) {
+ if (start_offset > end_offset)
+ std::swap(start_offset, end_offset);
+
+ if (start_offset <
+ static_cast<int>(start_text_object->GetText().length()) &&
+ end_offset <= static_cast<int>(end_text_object->GetText().length())) {
+ return start_text_object->GetText().substr(start_offset,
+ end_offset - start_offset);
+ }
+ return start_text_object->GetText();
+ }
+
+ base::string16 text;
+ if (start_offset < static_cast<int>(start_text_object->GetText().length()))
+ text += start_text_object->GetText().substr(start_offset);
+ else
+ text += start_text_object->GetText();
+ start_text_object = NextTextOnlyObject(start_text_object);
+ while (start_text_object && start_text_object != end_text_object) {
+ text += start_text_object->GetText();
+ start_text_object = NextTextOnlyObject(start_text_object);
+ }
+ if (end_offset <= static_cast<int>(end_text_object->GetText().length()))
+ text += end_text_object->GetText().substr(0, end_offset);
+ else
+ text += end_text_object->GetText();
+
+ return text;
}
+void BrowserAccessibilityManager::OnNodeDataWillChange(
+ ui::AXTree* tree,
+ const ui::AXNodeData& old_node_data,
+ const ui::AXNodeData& new_node_data) {}
+
void BrowserAccessibilityManager::OnTreeDataChanged(ui::AXTree* tree) {
}
void BrowserAccessibilityManager::OnNodeWillBeDeleted(ui::AXTree* tree,
ui::AXNode* node) {
DCHECK(node);
- if (node == focus_ && tree_) {
- if (node != tree_->root())
- SetFocus(tree_->root(), false);
- else
- focus_ = NULL;
- }
if (id_wrapper_map_.find(node->id()) == id_wrapper_map_.end())
return;
GetFromAXNode(node)->Destroy();
@@ -604,26 +838,34 @@ void BrowserAccessibilityManager::OnAtomicUpdateFinished(
ax_tree_id_changed = true;
}
- if (ax_tree_id_changed || root_changed) {
- BrowserAccessibility* parent = GetParentNodeFromParentTree();
- if (parent) {
- parent->OnDataChanged();
- parent->manager()->NotifyAccessibilityEvent(
- ui::AX_EVENT_CHILDREN_CHANGED, parent);
- }
+ // Whenever the tree ID or the root of this tree changes we may need to
+ // fire an event on our parent node in the parent tree to ensure that
+ // we're properly connected.
+ if (ax_tree_id_changed || root_changed)
+ connected_to_parent_tree_node_ = false;
+
+ // When the root changes and this is the root manager, we may need to
+ // fire a new focus event.
+ if (root_changed && last_focused_manager_ == this) {
+ last_focused_node_ = nullptr;
+ last_focused_manager_ = nullptr;
}
}
+BrowserAccessibilityManager* BrowserAccessibilityManager::GetRootManager() {
+ BrowserAccessibility* parent = GetParentNodeFromParentTree();
+ if (!parent)
+ return this;
+
+ return parent->manager()->GetRootManager();
+}
+
BrowserAccessibilityDelegate*
BrowserAccessibilityManager::GetDelegateFromRootManager() {
- if (!GetRoot())
- return nullptr;
- int parent_tree_id = GetTreeData().parent_tree_id;
- BrowserAccessibilityManager* parent_manager =
- BrowserAccessibilityManager::FromID(parent_tree_id);
- if (parent_manager)
- return parent_manager->GetDelegateFromRootManager();
- return delegate();
+ BrowserAccessibilityManager* root_manager = GetRootManager();
+ if (root_manager)
+ return root_manager->delegate();
+ return nullptr;
}
ui::AXTreeUpdate
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager.h b/chromium/content/browser/accessibility/browser_accessibility_manager.h
index 01dcf37a083..6d5a42f720e 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager.h
@@ -9,6 +9,7 @@
#include <vector>
+#include "base/callback_forward.h"
#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
@@ -35,6 +36,8 @@ class BrowserAccessibilityManagerWin;
class BrowserAccessibilityManagerAuraLinux;
#endif
+class SiteInstance;
+
// For testing.
CONTENT_EXPORT ui::AXTreeUpdate MakeAXTreeUpdate(
const ui::AXNodeData& node,
@@ -79,6 +82,9 @@ class CONTENT_EXPORT BrowserAccessibilityDelegate {
virtual gfx::Rect AccessibilityGetViewBounds() const = 0;
virtual gfx::Point AccessibilityOriginInScreen(
const gfx::Rect& bounds) const = 0;
+ virtual gfx::Rect AccessibilityTransformToRootCoordSpace(
+ const gfx::Rect& bounds) = 0;
+ virtual SiteInstance* AccessibilityGetSiteInstance() = 0;
virtual void AccessibilityHitTest(
const gfx::Point& point) = 0;
virtual void AccessibilitySetAccessibilityFocus(int acc_obj_id) = 0;
@@ -138,6 +144,18 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
virtual void NotifyAccessibilityEvent(
ui::AXEvent event_type, BrowserAccessibility* node) { }
+ // Checks whether focus has changed since the last time it was checked,
+ // taking into account whether the window has focus and which frame within
+ // the frame tree has focus. If focus has changed, calls FireFocusEvent.
+ void FireFocusEventsIfNeeded();
+
+ // Return whether or not we are currently able to fire events.
+ virtual bool CanFireEvents();
+
+ // Fire a focus event. Virtual so that some platforms can customize it,
+ // like firing a focus event on the root first, on Windows.
+ virtual void FireFocusEvent(BrowserAccessibility* node);
+
// Return a pointer to the root of the tree, does not make a new reference.
BrowserAccessibility* GetRoot();
@@ -172,11 +190,16 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
// occurred in the tab.
void GotMouseDown();
- // Update the focused node to |node|, which may be null.
- // If |notify| is true, send a message to the renderer to set focus
- // to this node.
- void SetFocus(ui::AXNode* node, bool notify);
- void SetFocus(BrowserAccessibility* node, bool notify);
+ // Send a message to the renderer to set focus to this node.
+ void SetFocus(const BrowserAccessibility& node);
+
+ // Pretend that the given node has focus, for testing only. Doesn't
+ // communicate with the renderer and doesn't fire any events.
+ void SetFocusLocallyForTesting(BrowserAccessibility* node);
+
+ // For testing only, register a function to be called when focus changes
+ // in any BrowserAccessibilityManager.
+ static void SetFocusChangeCallbackForTesting(const base::Closure& callback);
// Tell the renderer to do the default action for this node.
void DoDefaultAction(const BrowserAccessibility& node);
@@ -213,12 +236,12 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
void ActivateFindInPageResult(int request_id, int match_index);
// Called when the renderer process has notified us of about tree changes.
- void OnAccessibilityEvents(
+ virtual void OnAccessibilityEvents(
const std::vector<AXEventNotificationDetails>& details);
// Called when the renderer process updates the location of accessibility
- // objects.
- virtual void OnLocationChanges(
+ // objects. Calls SendLocationChangeEvents(), which can be overridden.
+ void OnLocationChanges(
const std::vector<AccessibilityHostMsg_LocationChangeParams>& params);
// Called when a new find in page result is received. We hold on to this
@@ -227,6 +250,11 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
int request_id, int match_index, int start_id, int start_offset,
int end_id, int end_offset);
+ // Called in response to a hit test, when the object hit has a child frame
+ // (like an iframe element or browser plugin), and we need to do another
+ // hit test recursively.
+ void OnChildFrameHitTestResult(const gfx::Point& point, int hit_obj_id);
+
// This is called when the user has committed to a find in page query,
// e.g. by pressing enter or tapping on the next / previous result buttons.
// If a match has already been received for this request id,
@@ -248,13 +276,16 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
ToBrowserAccessibilityManagerAuraLinux();
#endif
- // Return the object that has focus, if it's a descendant of the
- // given root (inclusive). Does not make a new reference.
- virtual BrowserAccessibility* GetFocus(BrowserAccessibility* root);
+ // Return the object that has focus, starting at the top of the frame tree.
+ virtual BrowserAccessibility* GetFocus();
- // Return the descentant of the given root that has focus, or that object's
- // active descendant if it has one.
- BrowserAccessibility* GetActiveDescendantFocus(BrowserAccessibility* root);
+ // Return the object that has focus, only considering this frame and
+ // descendants.
+ BrowserAccessibility* GetFocusFromThisOrDescendantFrame();
+
+ // Given a focused node |focus|, returns a descendant of that node if it
+ // has an active descendant, otherwise returns |focus|.
+ BrowserAccessibility* GetActiveDescendantFocus(BrowserAccessibility* focus);
// Returns true if native focus is anywhere in this WebContents or not.
bool NativeViewHasFocus();
@@ -264,13 +295,41 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
virtual bool UseRootScrollOffsetsWhenComputingBounds();
// Walk the tree.
- BrowserAccessibility* NextInTreeOrder(BrowserAccessibility* node) const;
- BrowserAccessibility* PreviousInTreeOrder(BrowserAccessibility* node) const;
- BrowserAccessibility* NextTextOnlyObject(BrowserAccessibility* node) const;
- BrowserAccessibility* PreviousTextOnlyObject(
- BrowserAccessibility* node) const;
+ static BrowserAccessibility* NextInTreeOrder(
+ const BrowserAccessibility* object);
+ static BrowserAccessibility* PreviousInTreeOrder(
+ const BrowserAccessibility* object);
+ static BrowserAccessibility* NextTextOnlyObject(
+ const BrowserAccessibility* object);
+ static BrowserAccessibility* PreviousTextOnlyObject(
+ const BrowserAccessibility* object);
+
+ // If the two objects provided have a common ancestor returns both the
+ // common ancestor and the child indices of the two subtrees in which the
+ // objects are located.
+ // Returns false if a common ancestor cannot be found.
+ static bool FindIndicesInCommonParent(const BrowserAccessibility& object1,
+ const BrowserAccessibility& object2,
+ BrowserAccessibility** common_parent,
+ int* child_index1,
+ int* child_index2);
+
+ // Returns all the text found between the given start and end locations.
+ // If start and end offsets are greater than the text's length, returns all
+ // the text until text length.
+ static base::string16 GetTextForRange(
+ const BrowserAccessibility& start_object,
+ int start_offset,
+ const BrowserAccessibility& end_object,
+ int end_offset);
+
+ // Accessors.
+ AXTreeIDRegistry::AXTreeID ax_tree_id() const { return ax_tree_id_; }
// AXTreeDelegate implementation.
+ void OnNodeDataWillChange(ui::AXTree* tree,
+ const ui::AXNodeData& old_node_data,
+ const ui::AXNodeData& new_node_data) override;
void OnTreeDataChanged(ui::AXTree* tree) override;
void OnNodeWillBeDeleted(ui::AXTree* tree, ui::AXNode* node) override;
void OnSubtreeWillBeDeleted(ui::AXTree* tree, ui::AXNode* node) override;
@@ -287,8 +346,11 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
}
// If this BrowserAccessibilityManager is a child frame or guest frame,
- // return the BrowserAccessibilityDelegate from the highest ancestor frame
+ // return the BrowserAccessibilityManager from the highest ancestor frame
// in the frame tree.
+ BrowserAccessibilityManager* GetRootManager();
+
+ // Returns the BrowserAccessibilityDelegate from |GetRootManager|, above.
BrowserAccessibilityDelegate* GetDelegateFromRootManager();
// Get a snapshot of the current tree as an AXTreeUpdate.
@@ -304,6 +366,12 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
BrowserAccessibilityDelegate* delegate,
BrowserAccessibilityFactory* factory);
+ // Send platform-specific notifications to each of these objects that
+ // their location has changed. This is called by OnLocationChanges
+ // after it's updated the internal data structure.
+ virtual void SendLocationChangeEvents(
+ const std::vector<AccessibilityHostMsg_LocationChangeParams>& params);
+
private:
// The following states keep track of whether or not the
// on-screen keyboard is allowed to be shown.
@@ -337,9 +405,6 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
// The underlying tree of accessibility objects.
scoped_ptr<ui::AXSerializableTree> tree_;
- // The node that currently has focus.
- ui::AXNode* focus_;
-
// A mapping from a node id to its wrapper of type BrowserAccessibility.
base::hash_map<int32_t, BrowserAccessibility*> id_wrapper_map_;
@@ -351,6 +416,21 @@ class CONTENT_EXPORT BrowserAccessibilityManager : public ui::AXTreeDelegate {
BrowserAccessibilityFindInPageInfo find_in_page_info_;
+ // These are only used by the root BrowserAccessibilityManager of a
+ // frame tree. Stores the last focused node and last focused manager so
+ // that when focus might have changed we can figure out whether we need
+ // to fire a focus event.
+ //
+ // NOTE: these pointers are not cleared, so they should never be
+ // dereferenced, only used for comparison.
+ BrowserAccessibility* last_focused_node_;
+ BrowserAccessibilityManager* last_focused_manager_;
+
+ // True if the root's parent is in another accessibility tree and that
+ // parent's child is the root. Ensures that the parent node is notified
+ // once when this subtree is first connected.
+ bool connected_to_parent_tree_node_;
+
// The global ID of this accessibility tree.
AXTreeIDRegistry::AXTreeID ax_tree_id_;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
index 42c2042c5c4..abfdcf7b558 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_android.cc
@@ -15,6 +15,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "content/browser/accessibility/browser_accessibility_android.h"
+#include "content/browser/accessibility/one_shot_accessibility_tree_search.h"
#include "content/common/accessibility_messages.h"
#include "jni/BrowserAccessibilityManager_jni.h"
#include "ui/accessibility/ax_text_utils.h"
@@ -22,32 +23,99 @@
using base::android::AttachCurrentThread;
using base::android::ScopedJavaLocalRef;
+namespace content {
+
namespace {
-enum AndroidHtmlElementType {
- HTML_ELEMENT_TYPE_SECTION,
- HTML_ELEMENT_TYPE_LIST,
- HTML_ELEMENT_TYPE_CONTROL,
- HTML_ELEMENT_TYPE_ANY
-};
+using SearchKeyToPredicateMap =
+ base::hash_map<base::string16, AccessibilityMatchPredicate>;
+base::LazyInstance<SearchKeyToPredicateMap> g_search_key_to_predicate_map =
+ LAZY_INSTANCE_INITIALIZER;
+base::LazyInstance<base::string16> g_all_search_keys =
+ LAZY_INSTANCE_INITIALIZER;
+
+bool SectionPredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ switch (node->GetRole()) {
+ case ui::AX_ROLE_ARTICLE:
+ case ui::AX_ROLE_APPLICATION:
+ case ui::AX_ROLE_BANNER:
+ case ui::AX_ROLE_COMPLEMENTARY:
+ case ui::AX_ROLE_CONTENT_INFO:
+ case ui::AX_ROLE_HEADING:
+ case ui::AX_ROLE_MAIN:
+ case ui::AX_ROLE_NAVIGATION:
+ case ui::AX_ROLE_SEARCH:
+ case ui::AX_ROLE_REGION:
+ return true;
+ default:
+ return false;
+ }
+}
+
+void AddToPredicateMap(const char* search_key_ascii,
+ AccessibilityMatchPredicate predicate) {
+ base::string16 search_key_utf16 = base::ASCIIToUTF16(search_key_ascii);
+ g_search_key_to_predicate_map.Get()[search_key_utf16] = predicate;
+ if (!g_all_search_keys.Get().empty())
+ g_all_search_keys.Get() += base::ASCIIToUTF16(",");
+ g_all_search_keys.Get() += search_key_utf16;
+}
// These are special unofficial strings sent from TalkBack/BrailleBack
// to jump to certain categories of web elements.
-AndroidHtmlElementType HtmlElementTypeFromString(base::string16 element_type) {
- if (element_type == base::ASCIIToUTF16("SECTION"))
- return HTML_ELEMENT_TYPE_SECTION;
- else if (element_type == base::ASCIIToUTF16("LIST"))
- return HTML_ELEMENT_TYPE_LIST;
- else if (element_type == base::ASCIIToUTF16("CONTROL"))
- return HTML_ELEMENT_TYPE_CONTROL;
- else
- return HTML_ELEMENT_TYPE_ANY;
+void InitSearchKeyToPredicateMapIfNeeded() {
+ if (!g_search_key_to_predicate_map.Get().empty())
+ return;
+
+ AddToPredicateMap("ARTICLE", AccessibilityArticlePredicate);
+ AddToPredicateMap("BUTTON", AccessibilityButtonPredicate);
+ AddToPredicateMap("CHECKBOX", AccessibilityCheckboxPredicate);
+ AddToPredicateMap("COMBOBOX", AccessibilityComboboxPredicate);
+ AddToPredicateMap("CONTROL", AccessibilityControlPredicate);
+ AddToPredicateMap("FOCUSABLE", AccessibilityFocusablePredicate);
+ AddToPredicateMap("FRAME", AccessibilityFramePredicate);
+ AddToPredicateMap("GRAPHIC", AccessibilityGraphicPredicate);
+ AddToPredicateMap("H1", AccessibilityH1Predicate);
+ AddToPredicateMap("H2", AccessibilityH2Predicate);
+ AddToPredicateMap("H3", AccessibilityH3Predicate);
+ AddToPredicateMap("H4", AccessibilityH4Predicate);
+ AddToPredicateMap("H5", AccessibilityH5Predicate);
+ AddToPredicateMap("H6", AccessibilityH6Predicate);
+ AddToPredicateMap("HEADING", AccessibilityHeadingPredicate);
+ AddToPredicateMap("LANDMARK", AccessibilityLandmarkPredicate);
+ AddToPredicateMap("LINK", AccessibilityLinkPredicate);
+ AddToPredicateMap("LIST", AccessibilityListPredicate);
+ AddToPredicateMap("LIST_ITEM", AccessibilityListItemPredicate);
+ AddToPredicateMap("MAIN", AccessibilityMainPredicate);
+ AddToPredicateMap("MEDIA", AccessibilityMediaPredicate);
+ AddToPredicateMap("RADIO", AccessibilityRadioButtonPredicate);
+ AddToPredicateMap("SECTION", SectionPredicate);
+ AddToPredicateMap("TABLE", AccessibilityTablePredicate);
+ AddToPredicateMap("TEXT_FIELD", AccessibilityTextfieldPredicate);
+ AddToPredicateMap("UNVISITED_LINK", AccessibilityUnvisitedLinkPredicate);
+ AddToPredicateMap("VISITED_LINK", AccessibilityVisitedLinkPredicate);
+}
+
+AccessibilityMatchPredicate PredicateForSearchKey(
+ const base::string16& element_type) {
+ InitSearchKeyToPredicateMapIfNeeded();
+ const auto& iter = g_search_key_to_predicate_map.Get().find(element_type);
+ if (iter != g_search_key_to_predicate_map.Get().end())
+ return iter->second;
+
+ // If we don't recognize the selector, return any element that's clickable.
+ // We mark all focusable nodes and leaf nodes as clickable because it's
+ // impossible to know whether a web node has a click handler or not, so
+ // to be safe we have to allow accessibility services to click on nearly
+ // anything that could possibly respond to a click.
+ return [](BrowserAccessibility* start, BrowserAccessibility* node) {
+ return static_cast<BrowserAccessibilityAndroid*>(node)->IsClickable();
+ };
}
} // anonymous namespace
-namespace content {
-
namespace aria_strings {
const char kAriaLivePolite[] = "polite";
const char kAriaLiveAssertive[] = "assertive";
@@ -80,11 +148,12 @@ BrowserAccessibilityManagerAndroid::BrowserAccessibilityManagerAndroid(
BrowserAccessibilityManagerAndroid::~BrowserAccessibilityManagerAndroid() {
JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+ ScopedJavaLocalRef<jobject> obj = GetJavaRefFromRootManager();
if (obj.is_null())
return;
- Java_BrowserAccessibilityManager_onNativeObjectDestroyed(env, obj.obj());
+ Java_BrowserAccessibilityManager_onNativeObjectDestroyed(
+ env, obj.obj(),reinterpret_cast<intptr_t>(this));
}
// static
@@ -116,7 +185,7 @@ void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent(
ui::AXEvent event_type,
BrowserAccessibility* node) {
JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+ ScopedJavaLocalRef<jobject> obj = GetJavaRefFromRootManager();
if (obj.is_null())
return;
@@ -129,7 +198,8 @@ void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent(
if (event_type == ui::AX_EVENT_TREE_CHANGED)
return;
- // Layout changes are handled in OnLocationChanges.
+ // Layout changes are handled in OnLocationChanges and
+ // SendLocationChangeEvents.
if (event_type == ui::AX_EVENT_LAYOUT_COMPLETE)
return;
@@ -142,28 +212,38 @@ void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent(
// the Android system that the accessibility hierarchy rooted at this
// node has changed.
Java_BrowserAccessibilityManager_handleContentChanged(
- env, obj.obj(), node->GetId());
+ env, obj.obj(), node->unique_id());
+
+ // Ignore load complete events on iframes.
+ if (event_type == ui::AX_EVENT_LOAD_COMPLETE &&
+ node->manager() != GetRootManager()) {
+ return;
+ }
switch (event_type) {
case ui::AX_EVENT_LOAD_COMPLETE:
Java_BrowserAccessibilityManager_handlePageLoaded(
- env, obj.obj(), focus_->id());
+ env, obj.obj(), GetFocus()->unique_id());
break;
case ui::AX_EVENT_FOCUS:
Java_BrowserAccessibilityManager_handleFocusChanged(
- env, obj.obj(), node->GetId());
+ env, obj.obj(), node->unique_id());
break;
case ui::AX_EVENT_CHECKED_STATE_CHANGED:
Java_BrowserAccessibilityManager_handleCheckStateChanged(
- env, obj.obj(), node->GetId());
+ env, obj.obj(), node->unique_id());
+ break;
+ case ui::AX_EVENT_CLICKED:
+ Java_BrowserAccessibilityManager_handleClicked(env, obj.obj(),
+ node->unique_id());
break;
case ui::AX_EVENT_SCROLL_POSITION_CHANGED:
Java_BrowserAccessibilityManager_handleScrollPositionChanged(
- env, obj.obj(), node->GetId());
+ env, obj.obj(), node->unique_id());
break;
case ui::AX_EVENT_SCROLLED_TO_ANCHOR:
Java_BrowserAccessibilityManager_handleScrolledToAnchor(
- env, obj.obj(), node->GetId());
+ env, obj.obj(), node->unique_id());
break;
case ui::AX_EVENT_ALERT:
// An alert is a special case of live region. Fall through to the
@@ -179,16 +259,16 @@ void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent(
}
case ui::AX_EVENT_TEXT_SELECTION_CHANGED:
Java_BrowserAccessibilityManager_handleTextSelectionChanged(
- env, obj.obj(), node->GetId());
+ env, obj.obj(), node->unique_id());
break;
case ui::AX_EVENT_TEXT_CHANGED:
case ui::AX_EVENT_VALUE_CHANGED:
- if (android_node->IsEditableText() && GetFocus(GetRoot()) == node) {
+ if (android_node->IsEditableText() && GetFocus() == node) {
Java_BrowserAccessibilityManager_handleEditableTextChanged(
- env, obj.obj(), node->GetId());
+ env, obj.obj(), node->unique_id());
} else if (android_node->IsSlider()) {
Java_BrowserAccessibilityManager_handleSliderChanged(
- env, obj.obj(), node->GetId());
+ env, obj.obj(), node->unique_id());
}
break;
default:
@@ -198,15 +278,15 @@ void BrowserAccessibilityManagerAndroid::NotifyAccessibilityEvent(
}
}
-void BrowserAccessibilityManagerAndroid::OnLocationChanges(
+void BrowserAccessibilityManagerAndroid::SendLocationChangeEvents(
const std::vector<AccessibilityHostMsg_LocationChangeParams>& params) {
// Android is not very efficient at handling notifications, and location
// changes in particular are frequent and not time-critical. If a lot of
// nodes changed location, just send a single notification after a short
// delay (to batch them), rather than lots of individual notifications.
if (params.size() > 3) {
+ ScopedJavaLocalRef<jobject> obj = GetJavaRefFromRootManager();
JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
if (obj.is_null())
return;
Java_BrowserAccessibilityManager_sendDelayedWindowContentChangedEvent(
@@ -214,14 +294,22 @@ void BrowserAccessibilityManagerAndroid::OnLocationChanges(
return;
}
- BrowserAccessibilityManager::OnLocationChanges(params);
+ BrowserAccessibilityManager::SendLocationChangeEvents(params);
+}
+
+base::android::ScopedJavaLocalRef<jstring>
+BrowserAccessibilityManagerAndroid::GetSupportedHtmlElementTypes(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& obj) {
+ InitSearchKeyToPredicateMapIfNeeded();
+ return base::android::ConvertUTF16ToJavaString(env, g_all_search_keys.Get());
}
jint BrowserAccessibilityManagerAndroid::GetRootId(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
if (GetRoot())
- return static_cast<jint>(GetRoot()->GetId());
+ return static_cast<jint>(GetRoot()->unique_id());
else
return -1;
}
@@ -230,7 +318,7 @@ jboolean BrowserAccessibilityManagerAndroid::IsNodeValid(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
jint id) {
- return GetFromID(id) != NULL;
+ return GetFromUniqueID(id) != NULL;
}
void BrowserAccessibilityManagerAndroid::HitTest(
@@ -246,8 +334,7 @@ jboolean BrowserAccessibilityManagerAndroid::IsEditableText(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
jint id) {
- BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
- GetFromID(id));
+ BrowserAccessibilityAndroid* node = GetFromUniqueID(id);
if (!node)
return false;
@@ -258,8 +345,7 @@ jint BrowserAccessibilityManagerAndroid::GetEditableTextSelectionStart(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
jint id) {
- BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
- GetFromID(id));
+ BrowserAccessibilityAndroid* node = GetFromUniqueID(id);
if (!node)
return false;
@@ -270,8 +356,7 @@ jint BrowserAccessibilityManagerAndroid::GetEditableTextSelectionEnd(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
jint id) {
- BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
- GetFromID(id));
+ BrowserAccessibilityAndroid* node = GetFromUniqueID(id);
if (!node)
return false;
@@ -283,18 +368,17 @@ jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityNodeInfo(
const JavaParamRef<jobject>& obj,
const JavaParamRef<jobject>& info,
jint id) {
- BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
- GetFromID(id));
+ BrowserAccessibilityAndroid* node = GetFromUniqueID(id);
if (!node)
return false;
if (node->GetParent()) {
Java_BrowserAccessibilityManager_setAccessibilityNodeInfoParent(
- env, obj, info, node->GetParent()->GetId());
+ env, obj, info, node->GetParent()->unique_id());
}
for (unsigned i = 0; i < node->PlatformChildCount(); ++i) {
Java_BrowserAccessibilityManager_addAccessibilityNodeInfoChild(
- env, obj, info, node->InternalGetChild(i)->GetId());
+ env, obj, info, node->PlatformGetChild(i)->unique_id());
}
Java_BrowserAccessibilityManager_setAccessibilityNodeInfoBooleanAttributes(
env, obj, info,
@@ -355,6 +439,12 @@ jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityNodeInfo(
absolute_rect.width(), absolute_rect.height(),
is_root);
+ Java_BrowserAccessibilityManager_setAccessibilityNodeInfoKitKatAttributes(
+ env, obj, info,
+ is_root,
+ base::android::ConvertUTF16ToJavaString(
+ env, node->GetRoleDescription()).obj());
+
Java_BrowserAccessibilityManager_setAccessibilityNodeInfoLollipopAttributes(
env, obj, info,
node->CanOpenPopup(),
@@ -397,8 +487,7 @@ jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityEvent(
const JavaParamRef<jobject>& event,
jint id,
jint event_type) {
- BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
- GetFromID(id));
+ BrowserAccessibilityAndroid* node = GetFromUniqueID(id);
if (!node)
return false;
@@ -500,7 +589,7 @@ jboolean BrowserAccessibilityManagerAndroid::PopulateAccessibilityEvent(
void BrowserAccessibilityManagerAndroid::Click(JNIEnv* env,
const JavaParamRef<jobject>& obj,
jint id) {
- BrowserAccessibility* node = GetFromID(id);
+ BrowserAccessibilityAndroid* node = GetFromUniqueID(id);
if (node)
DoDefaultAction(*node);
}
@@ -508,22 +597,22 @@ void BrowserAccessibilityManagerAndroid::Click(JNIEnv* env,
void BrowserAccessibilityManagerAndroid::Focus(JNIEnv* env,
const JavaParamRef<jobject>& obj,
jint id) {
- BrowserAccessibility* node = GetFromID(id);
+ BrowserAccessibilityAndroid* node = GetFromUniqueID(id);
if (node)
- SetFocus(node, true);
+ SetFocus(*node);
}
void BrowserAccessibilityManagerAndroid::Blur(
JNIEnv* env,
const JavaParamRef<jobject>& obj) {
- SetFocus(GetRoot(), true);
+ SetFocus(*GetRoot());
}
void BrowserAccessibilityManagerAndroid::ScrollToMakeNodeVisible(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
jint id) {
- BrowserAccessibility* node = GetFromID(id);
+ BrowserAccessibilityAndroid* node = GetFromUniqueID(id);
if (node)
ScrollToMakeVisible(*node, gfx::Rect(node->GetLocation().size()));
}
@@ -533,7 +622,7 @@ void BrowserAccessibilityManagerAndroid::SetTextFieldValue(
const JavaParamRef<jobject>& obj,
jint id,
const JavaParamRef<jstring>& value) {
- BrowserAccessibility* node = GetFromID(id);
+ BrowserAccessibilityAndroid* node = GetFromUniqueID(id);
if (node) {
BrowserAccessibilityManager::SetValue(
*node, base::android::ConvertJavaStringToUTF16(env, value));
@@ -546,7 +635,7 @@ void BrowserAccessibilityManagerAndroid::SetSelection(
jint id,
jint start,
jint end) {
- BrowserAccessibility* node = GetFromID(id);
+ BrowserAccessibilityAndroid* node = GetFromUniqueID(id);
if (node)
SetTextSelection(*node, start, end);
}
@@ -556,7 +645,7 @@ jboolean BrowserAccessibilityManagerAndroid::AdjustSlider(
const JavaParamRef<jobject>& obj,
jint id,
jboolean increment) {
- BrowserAccessibility* node = GetFromID(id);
+ BrowserAccessibilityAndroid* node = GetFromUniqueID(id);
if (!node)
return false;
@@ -589,7 +678,7 @@ jboolean BrowserAccessibilityManagerAndroid::AdjustSlider(
void BrowserAccessibilityManagerAndroid::HandleHoverEvent(
BrowserAccessibility* node) {
JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+ ScopedJavaLocalRef<jobject> obj = GetJavaRefFromRootManager();
if (obj.is_null())
return;
@@ -606,7 +695,7 @@ void BrowserAccessibilityManagerAndroid::HandleHoverEvent(
}
Java_BrowserAccessibilityManager_handleHover(
- env, obj.obj(), node->GetId());
+ env, obj.obj(), node->unique_id());
}
jint BrowserAccessibilityManagerAndroid::FindElementType(
@@ -615,58 +704,36 @@ jint BrowserAccessibilityManagerAndroid::FindElementType(
jint start_id,
const JavaParamRef<jstring>& element_type_str,
jboolean forwards) {
- BrowserAccessibility* node = GetFromID(start_id);
- if (!node)
+ BrowserAccessibilityAndroid* start_node = GetFromUniqueID(start_id);
+ if (!start_node)
return 0;
- AndroidHtmlElementType element_type = HtmlElementTypeFromString(
- base::android::ConvertJavaStringToUTF16(env, element_type_str));
+ BrowserAccessibilityManager* root_manager = GetRootManager();
+ if (!root_manager)
+ return 0;
- node = forwards ? NextInTreeOrder(node) : PreviousInTreeOrder(node);
- while (node) {
- switch(element_type) {
- case HTML_ELEMENT_TYPE_SECTION:
- if (node->GetRole() == ui::AX_ROLE_ARTICLE ||
- node->GetRole() == ui::AX_ROLE_APPLICATION ||
- node->GetRole() == ui::AX_ROLE_BANNER ||
- node->GetRole() == ui::AX_ROLE_COMPLEMENTARY ||
- node->GetRole() == ui::AX_ROLE_CONTENT_INFO ||
- node->GetRole() == ui::AX_ROLE_HEADING ||
- node->GetRole() == ui::AX_ROLE_MAIN ||
- node->GetRole() == ui::AX_ROLE_NAVIGATION ||
- node->GetRole() == ui::AX_ROLE_SEARCH ||
- node->GetRole() == ui::AX_ROLE_REGION) {
- return node->GetId();
- }
- break;
- case HTML_ELEMENT_TYPE_LIST:
- if (node->GetRole() == ui::AX_ROLE_LIST ||
- node->GetRole() == ui::AX_ROLE_GRID ||
- node->GetRole() == ui::AX_ROLE_TABLE ||
- node->GetRole() == ui::AX_ROLE_TREE) {
- return node->GetId();
- }
- break;
- case HTML_ELEMENT_TYPE_CONTROL:
- if (static_cast<BrowserAccessibilityAndroid*>(node)->IsFocusable())
- return node->GetId();
- break;
- case HTML_ELEMENT_TYPE_ANY:
- // In theory, the API says that an accessibility service could
- // jump to an element by element name, like 'H1' or 'P'. This isn't
- // currently used by any accessibility service, and we think it's
- // better to keep them high-level like 'SECTION' or 'CONTROL', so we
- // just fall back on linear navigation when we don't recognize the
- // element type.
- if (static_cast<BrowserAccessibilityAndroid*>(node)->IsClickable())
- return node->GetId();
- break;
- }
+ BrowserAccessibility* root = root_manager->GetRoot();
+ if (!root)
+ return 0;
- node = forwards ? NextInTreeOrder(node) : PreviousInTreeOrder(node);
- }
+ AccessibilityMatchPredicate predicate = PredicateForSearchKey(
+ base::android::ConvertJavaStringToUTF16(env, element_type_str));
- return 0;
+ OneShotAccessibilityTreeSearch tree_search(root);
+ tree_search.SetStartNode(start_node);
+ tree_search.SetDirection(
+ forwards ?
+ OneShotAccessibilityTreeSearch::FORWARDS :
+ OneShotAccessibilityTreeSearch::BACKWARDS);
+ tree_search.SetResultLimit(1);
+ tree_search.SetImmediateDescendantsOnly(false);
+ tree_search.SetVisibleOnly(false);
+ tree_search.AddPredicate(predicate);
+
+ if (tree_search.CountMatches() == 0)
+ return 0;
+
+ return tree_search.GetMatchAtIndex(0)->unique_id();
}
jboolean BrowserAccessibilityManagerAndroid::NextAtGranularity(
@@ -676,8 +743,7 @@ jboolean BrowserAccessibilityManagerAndroid::NextAtGranularity(
jboolean extend_selection,
jint id,
jint cursor_index) {
- BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
- GetFromID(id));
+ BrowserAccessibilityAndroid* node = GetFromUniqueID(id);
if (!node)
return false;
@@ -706,8 +772,7 @@ jboolean BrowserAccessibilityManagerAndroid::PreviousAtGranularity(
jboolean extend_selection,
jint id,
jint cursor_index) {
- BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
- GetFromID(id));
+ BrowserAccessibilityAndroid* node = GetFromUniqueID(id);
if (!node)
return false;
@@ -827,8 +892,7 @@ bool BrowserAccessibilityManagerAndroid::IsSlider(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
jint id) {
- BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
- GetFromID(id));
+ BrowserAccessibilityAndroid* node = GetFromUniqueID(id);
if (!node)
return false;
@@ -840,8 +904,7 @@ bool BrowserAccessibilityManagerAndroid::Scroll(
const JavaParamRef<jobject>& obj,
jint id,
int direction) {
- BrowserAccessibilityAndroid* node = static_cast<BrowserAccessibilityAndroid*>(
- GetFromID(id));
+ BrowserAccessibilityAndroid* node = GetFromUniqueID(id);
if (!node)
return false;
@@ -852,9 +915,12 @@ void BrowserAccessibilityManagerAndroid::OnAtomicUpdateFinished(
ui::AXTree* tree,
bool root_changed,
const std::vector<ui::AXTreeDelegate::Change>& changes) {
+ BrowserAccessibilityManager::OnAtomicUpdateFinished(
+ tree, root_changed, changes);
+
if (root_changed) {
JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
+ ScopedJavaLocalRef<jobject> obj = GetJavaRefFromRootManager();
if (obj.is_null())
return;
@@ -868,6 +934,24 @@ BrowserAccessibilityManagerAndroid::UseRootScrollOffsetsWhenComputingBounds() {
return false;
}
+BrowserAccessibilityAndroid*
+BrowserAccessibilityManagerAndroid::GetFromUniqueID(int32_t unique_id) {
+ return static_cast<BrowserAccessibilityAndroid*>(
+ BrowserAccessibility::GetFromUniqueID(unique_id));
+}
+
+ScopedJavaLocalRef<jobject>
+BrowserAccessibilityManagerAndroid::GetJavaRefFromRootManager() {
+ BrowserAccessibilityManagerAndroid* root_manager =
+ static_cast<BrowserAccessibilityManagerAndroid*>(
+ GetRootManager());
+ if (!root_manager)
+ return ScopedJavaLocalRef<jobject>();
+
+ JNIEnv* env = AttachCurrentThread();
+ return root_manager->java_ref().get(env);
+}
+
bool RegisterBrowserAccessibilityManager(JNIEnv* env) {
return RegisterNativesImpl(env);
}
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_android.h b/chromium/content/browser/accessibility/browser_accessibility_manager_android.h
index 4bc42b54be5..d74699db24a 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_android.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_android.h
@@ -77,7 +77,7 @@ class CONTENT_EXPORT BrowserAccessibilityManagerAndroid
// Implementation of BrowserAccessibilityManager.
void NotifyAccessibilityEvent(ui::AXEvent event_type,
BrowserAccessibility* node) override;
- void OnLocationChanges(
+ void SendLocationChangeEvents(
const std::vector<AccessibilityHostMsg_LocationChangeParams>& params)
override;
@@ -85,6 +85,10 @@ class CONTENT_EXPORT BrowserAccessibilityManagerAndroid
// Methods called from Java via JNI
// --------------------------------------------------------------------------
+ // Global methods.
+ base::android::ScopedJavaLocalRef<jstring> GetSupportedHtmlElementTypes(
+ JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+
// Tree methods.
jint GetRootId(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
jboolean IsNodeValid(JNIEnv* env,
@@ -214,6 +218,8 @@ class CONTENT_EXPORT BrowserAccessibilityManagerAndroid
jint id,
int direction);
+ JavaObjectWeakGlobalRef& java_ref() { return java_ref_; }
+
protected:
// AXTreeDelegate overrides.
void OnAtomicUpdateFinished(
@@ -224,6 +230,10 @@ class CONTENT_EXPORT BrowserAccessibilityManagerAndroid
bool UseRootScrollOffsetsWhenComputingBounds() override;
private:
+ BrowserAccessibilityAndroid* GetFromUniqueID(int32_t unique_id);
+
+ base::android::ScopedJavaLocalRef<jobject> GetJavaRefFromRootManager();
+
// This gives BrowserAccessibilityManager::Create access to the class
// constructor.
friend class BrowserAccessibilityManager;
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h
index 0cda76d2e93..715081920c4 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.h
@@ -6,9 +6,16 @@
#define CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_MANAGER_MAC_H_
#import <Cocoa/Cocoa.h>
+#include <stdint.h>
+
+#include <map>
+#include <vector>
#include "base/macros.h"
+#include "base/strings/string16.h"
+#import "content/browser/accessibility/browser_accessibility_cocoa.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "content/public/browser/ax_event_notification_details.h"
namespace content {
@@ -21,17 +28,26 @@ class CONTENT_EXPORT BrowserAccessibilityManagerMac
BrowserAccessibilityDelegate* delegate,
BrowserAccessibilityFactory* factory = new BrowserAccessibilityFactory());
+ ~BrowserAccessibilityManagerMac() override;
+
static ui::AXTreeUpdate GetEmptyDocument();
- BrowserAccessibility* GetFocus(BrowserAccessibility* root) override;
+ BrowserAccessibility* GetFocus() override;
// Implementation of BrowserAccessibilityManager.
void NotifyAccessibilityEvent(ui::AXEvent event_type,
BrowserAccessibility* node) override;
+ void OnAccessibilityEvents(
+ const std::vector<AXEventNotificationDetails>& details) override;
+
NSView* parent_view() { return parent_view_; }
private:
+ // AXTreeDelegate methods.
+ void OnNodeDataWillChange(ui::AXTree* tree,
+ const ui::AXNodeData& old_node_data,
+ const ui::AXNodeData& new_node_data) override;
void OnAtomicUpdateFinished(
ui::AXTree* tree,
bool root_changed,
@@ -40,12 +56,23 @@ class CONTENT_EXPORT BrowserAccessibilityManagerMac
// Returns an autoreleased object.
NSDictionary* GetUserInfoForSelectedTextChangedNotification();
+ // Returns an autoreleased object.
+ NSDictionary* GetUserInfoForValueChangedNotification(
+ const BrowserAccessibilityCocoa* native_node,
+ const base::string16& deleted_text,
+ const base::string16& inserted_text) const;
+
// This gives BrowserAccessibilityManager::Create access to the class
// constructor.
friend class BrowserAccessibilityManager;
NSView* parent_view_;
+ // Keeps track of any edits that have been made by the user during a tree
+ // update. Used by NSAccessibilityValueChangedNotification.
+ // Maps AXNode IDs to name or value attribute changes.
+ std::map<int32_t, base::string16> text_edits_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityManagerMac);
};
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
index 0937229b2aa..e43122e120b 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -4,19 +4,19 @@
#include "content/browser/accessibility/browser_accessibility_manager_mac.h"
-#include <stddef.h>
-
#import "base/mac/mac_util.h"
#import "base/mac/sdk_forward_declarations.h"
#include "base/logging.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/strings/utf_string_conversions.h"
#import "content/browser/accessibility/browser_accessibility_cocoa.h"
#import "content/browser/accessibility/browser_accessibility_mac.h"
#include "content/common/accessibility_messages.h"
-
namespace {
-// Declare accessibility constants and enums only present in WebKit.
+// Declare undocumented accessibility constants and enums only present in
+// WebKit.
enum AXTextStateChangeType {
AXTextStateChangeTypeUnknown,
@@ -46,6 +46,17 @@ enum AXTextSelectionGranularity {
AXTextSelectionGranularityAll
};
+enum AXTextEditType {
+ AXTextEditTypeUnknown,
+ AXTextEditTypeDelete,
+ AXTextEditTypeInsert,
+ AXTextEditTypeTyping,
+ AXTextEditTypeDictation,
+ AXTextEditTypeCut,
+ AXTextEditTypePaste,
+ AXTextEditTypeAttributesChange
+};
+
NSString* const NSAccessibilityAutocorrectionOccurredNotification =
@"AXAutocorrectionOccurred";
NSString* const NSAccessibilityLayoutCompleteNotification =
@@ -58,6 +69,9 @@ NSString* const NSAccessibilityLiveRegionChangedNotification =
@"AXLiveRegionChanged";
NSString* const NSAccessibilityMenuItemSelectedNotification =
@"AXMenuItemSelected";
+
+// Attributes used for NSAccessibilitySelectedTextChangedNotification and
+// NSAccessibilityValueChangedNotification.
NSString* const NSAccessibilityTextStateChangeTypeKey =
@"AXTextStateChangeType";
NSString* const NSAccessibilityTextStateSyncKey = @"AXTextStateSync";
@@ -67,8 +81,14 @@ NSString* const NSAccessibilityTextSelectionGranularity =
@"AXTextSelectionGranularity";
NSString* const NSAccessibilityTextSelectionChangedFocus =
@"AXTextSelectionChangedFocus";
-NSString* const NSAccessibilityTextChangeElement =
- @"AXAccessibilityTextChangeElement";
+NSString* const NSAccessibilitySelectedTextMarkerRangeAttribute =
+ @"AXSelectedTextMarkerRange";
+NSString* const NSAccessibilityTextChangeElement = @"AXTextChangeElement";
+NSString* const NSAccessibilityTextEditType = @"AXTextEditType";
+NSString* const NSAccessibilityTextChangeValue = @"AXTextChangeValue";
+NSString* const NSAccessibilityTextChangeValueLength =
+ @"AXTextChangeValueLength";
+NSString* const NSAccessibilityTextChangeValues = @"AXTextChangeValues";
} // namespace
@@ -93,6 +113,8 @@ BrowserAccessibilityManagerMac::BrowserAccessibilityManagerMac(
Initialize(initial_tree);
}
+BrowserAccessibilityManagerMac::~BrowserAccessibilityManagerMac() {}
+
// static
ui::AXTreeUpdate
BrowserAccessibilityManagerMac::GetEmptyDocument() {
@@ -106,16 +128,15 @@ ui::AXTreeUpdate
return update;
}
-BrowserAccessibility* BrowserAccessibilityManagerMac::GetFocus(
- BrowserAccessibility* root) {
+BrowserAccessibility* BrowserAccessibilityManagerMac::GetFocus() {
// On Mac, list boxes should always get focus on the whole list, otherwise
// information about the number of selected items will never be reported.
- BrowserAccessibility* node = BrowserAccessibilityManager::GetFocus(root);
+ BrowserAccessibility* node = BrowserAccessibilityManager::GetFocus();
if (node && node->GetRole() == ui::AX_ROLE_LIST_BOX)
return node;
// For other roles, follow the active descendant.
- return GetActiveDescendantFocus(root);
+ return GetActiveDescendantFocus(node);
}
void BrowserAccessibilityManagerMac::NotifyAccessibilityEvent(
@@ -125,8 +146,7 @@ void BrowserAccessibilityManagerMac::NotifyAccessibilityEvent(
return;
if (event_type == ui::AX_EVENT_FOCUS) {
- BrowserAccessibility* active_descendant = GetActiveDescendantFocus(
- GetRoot());
+ BrowserAccessibility* active_descendant = GetActiveDescendantFocus(node);
if (active_descendant)
node = active_descendant;
@@ -135,11 +155,11 @@ void BrowserAccessibilityManagerMac::NotifyAccessibilityEvent(
node->GetParent() &&
node->GetParent()->GetRole() == ui::AX_ROLE_LIST_BOX) {
node = node->GetParent();
- SetFocus(node, false);
+ SetFocus(*node);
}
}
- auto native_node = node->ToBrowserAccessibilityCocoa();
+ auto native_node = ToBrowserAccessibilityCocoa(node);
DCHECK(native_node);
// Refer to |AXObjectCache::postPlatformNotification| in WebKit source code.
@@ -182,6 +202,13 @@ void BrowserAccessibilityManagerMac::NotifyAccessibilityEvent(
break;
case ui::AX_EVENT_DOCUMENT_SELECTION_CHANGED: {
mac_notification = NSAccessibilitySelectedTextChangedNotification;
+ // WebKit fires a notification both on the focused object and the root.
+ BrowserAccessibility* focus = GetFocus();
+ if (!focus)
+ break; // Just fire a notification on the root.
+ NSAccessibilityPostNotification(ToBrowserAccessibilityCocoa(focus),
+ mac_notification);
+
if (base::mac::IsOSElCapitanOrLater()) {
// |NSAccessibilityPostNotificationWithUserInfo| should be used on OS X
// 10.11 or later to notify Voiceover about text selection changes. This
@@ -189,15 +216,46 @@ void BrowserAccessibilityManagerMac::NotifyAccessibilityEvent(
// appear to be needed by Voiceover before version 10.11.
NSDictionary* user_info =
GetUserInfoForSelectedTextChangedNotification();
+
+ BrowserAccessibility* root = GetRoot();
+ if (!root)
+ return;
+
NSAccessibilityPostNotificationWithUserInfo(
- native_node, mac_notification, user_info);
+ ToBrowserAccessibilityCocoa(focus), mac_notification, user_info);
+ NSAccessibilityPostNotificationWithUserInfo(
+ ToBrowserAccessibilityCocoa(root), mac_notification, user_info);
return;
}
break;
}
case ui::AX_EVENT_CHECKED_STATE_CHANGED:
+ mac_notification = NSAccessibilityValueChangedNotification;
+ break;
case ui::AX_EVENT_VALUE_CHANGED:
mac_notification = NSAccessibilityValueChangedNotification;
+ if (base::mac::IsOSElCapitanOrLater() && text_edits_.size()) {
+ // It seems that we don't need to distinguish between deleted and
+ // inserted text for now.
+ base::string16 deleted_text;
+ base::string16 inserted_text;
+ int32_t id = node->GetId();
+ const auto iterator = text_edits_.find(id);
+ if (iterator != text_edits_.end())
+ inserted_text = iterator->second;
+ NSDictionary* user_info = GetUserInfoForValueChangedNotification(
+ native_node, deleted_text, inserted_text);
+
+ BrowserAccessibility* root = GetRoot();
+ if (!root)
+ return;
+
+ NSAccessibilityPostNotificationWithUserInfo(
+ native_node, mac_notification, user_info);
+ NSAccessibilityPostNotificationWithUserInfo(
+ ToBrowserAccessibilityCocoa(root), mac_notification, user_info);
+ return;
+ }
break;
// TODO(nektar): Need to add an event for live region created.
case ui::AX_EVENT_LIVE_REGION_CHANGED:
@@ -244,6 +302,63 @@ void BrowserAccessibilityManagerMac::NotifyAccessibilityEvent(
NSAccessibilityPostNotification(native_node, mac_notification);
}
+void BrowserAccessibilityManagerMac::OnAccessibilityEvents(
+ const std::vector<AXEventNotificationDetails>& details) {
+ text_edits_.clear();
+ // Call the base method last as it might delete the tree if it receives an
+ // invalid message.
+ BrowserAccessibilityManager::OnAccessibilityEvents(details);
+}
+
+void BrowserAccessibilityManagerMac::OnNodeDataWillChange(
+ ui::AXTree* tree,
+ const ui::AXNodeData& old_node_data,
+ const ui::AXNodeData& new_node_data) {
+ BrowserAccessibilityManager::OnNodeDataWillChange(tree, old_node_data,
+ new_node_data);
+
+ // Starting from OS X 10.11, if the user has edited some text we need to
+ // dispatch the actual text that changed on the value changed notification.
+ // We run this code on all OS X versions to get the highest test coverage.
+ base::string16 old_text, new_text;
+ ui::AXRole role = new_node_data.role;
+ if (role == ui::AX_ROLE_COMBO_BOX || role == ui::AX_ROLE_SEARCH_BOX ||
+ role == ui::AX_ROLE_TEXT_FIELD) {
+ old_text = old_node_data.GetString16Attribute(ui::AX_ATTR_VALUE);
+ new_text = new_node_data.GetString16Attribute(ui::AX_ATTR_VALUE);
+ } else if (new_node_data.state & (1 << ui::AX_STATE_EDITABLE)) {
+ old_text = old_node_data.GetString16Attribute(ui::AX_ATTR_NAME);
+ new_text = new_node_data.GetString16Attribute(ui::AX_ATTR_NAME);
+ }
+
+ if ((old_text.empty() && new_text.empty()) ||
+ old_text.length() == new_text.length()) {
+ return;
+ }
+
+ if (old_text.length() < new_text.length()) {
+ // Insertion.
+ size_t i = 0;
+ while (i < old_text.length() && i < new_text.length() &&
+ old_text[i] == new_text[i]) {
+ ++i;
+ }
+ size_t length = (new_text.length() - i) - (old_text.length() - i);
+ base::string16 inserted_text = new_text.substr(i, length);
+ text_edits_[new_node_data.id] = inserted_text;
+ } else {
+ // Deletion.
+ size_t i = 0;
+ while (i < old_text.length() && i < new_text.length() &&
+ old_text[i] == new_text[i]) {
+ ++i;
+ }
+ size_t length = (old_text.length() - i) - (new_text.length() - i);
+ base::string16 deleted_text = old_text.substr(i, length);
+ text_edits_[new_node_data.id] = deleted_text;
+ }
+}
+
void BrowserAccessibilityManagerMac::OnAtomicUpdateFinished(
ui::AXTree* tree,
bool root_changed,
@@ -281,35 +396,65 @@ void BrowserAccessibilityManagerMac::OnAtomicUpdateFinished(
}
}
-// Returns an autoreleased object.
NSDictionary* BrowserAccessibilityManagerMac::
GetUserInfoForSelectedTextChangedNotification() {
NSMutableDictionary* user_info = [[[NSMutableDictionary alloc] init]
autorelease];
- [user_info setObject:[NSNumber numberWithBool:YES]
- forKey:NSAccessibilityTextStateSyncKey];
- [user_info setObject:[NSNumber numberWithInt:AXTextStateChangeTypeUnknown]
+ [user_info setObject:@YES forKey:NSAccessibilityTextStateSyncKey];
+ [user_info setObject:@(AXTextStateChangeTypeUnknown)
forKey:NSAccessibilityTextStateChangeTypeKey];
- [user_info
- setObject:[NSNumber numberWithInt:AXTextSelectionDirectionUnknown]
- forKey:NSAccessibilityTextSelectionDirection];
- [user_info
- setObject:[NSNumber numberWithInt:AXTextSelectionGranularityUnknown]
- forKey:NSAccessibilityTextSelectionGranularity];
- [user_info setObject:[NSNumber numberWithBool:YES]
- forKey:NSAccessibilityTextSelectionChangedFocus];
- // TODO(nektar): Set selected text marker range.
+ [user_info setObject:@(AXTextSelectionDirectionUnknown)
+ forKey:NSAccessibilityTextSelectionDirection];
+ [user_info setObject:@(AXTextSelectionGranularityUnknown)
+ forKey:NSAccessibilityTextSelectionGranularity];
+ [user_info setObject:@YES forKey:NSAccessibilityTextSelectionChangedFocus];
int32_t focus_id = GetTreeData().sel_focus_object_id;
BrowserAccessibility* focus_object = GetFromID(focus_id);
if (focus_object) {
- auto native_focus_object = focus_object->ToBrowserAccessibilityCocoa();
- if (native_focus_object)
+ focus_object = focus_object->GetClosestPlatformObject();
+ auto native_focus_object = ToBrowserAccessibilityCocoa(focus_object);
+ if (native_focus_object && [native_focus_object instanceActive]) {
+ [user_info setObject:[native_focus_object selectedTextMarkerRange]
+ forKey:NSAccessibilitySelectedTextMarkerRangeAttribute];
[user_info setObject:native_focus_object
forKey:NSAccessibilityTextChangeElement];
+ }
}
return user_info;
}
+NSDictionary*
+BrowserAccessibilityManagerMac::GetUserInfoForValueChangedNotification(
+ const BrowserAccessibilityCocoa* native_node,
+ const base::string16& deleted_text,
+ const base::string16& inserted_text) const {
+ DCHECK(native_node);
+ if (deleted_text.empty() && inserted_text.empty())
+ return nil;
+
+ NSMutableArray* changes = [[[NSMutableArray alloc] init] autorelease];
+ if (!deleted_text.empty()) {
+ [changes addObject:@{
+ NSAccessibilityTextEditType : @(AXTextEditTypeUnknown),
+ NSAccessibilityTextChangeValueLength : @(deleted_text.length()),
+ NSAccessibilityTextChangeValue : base::SysUTF16ToNSString(deleted_text)
+ }];
+ }
+ if (!inserted_text.empty()) {
+ [changes addObject:@{
+ NSAccessibilityTextEditType : @(AXTextEditTypeUnknown),
+ NSAccessibilityTextChangeValueLength : @(inserted_text.length()),
+ NSAccessibilityTextChangeValue : base::SysUTF16ToNSString(inserted_text)
+ }];
+ }
+
+ return @{
+ NSAccessibilityTextStateChangeTypeKey : @(AXTextStateChangeTypeEdit),
+ NSAccessibilityTextChangeValues : changes,
+ NSAccessibilityTextChangeElement : native_node
+ };
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
index c3a059652df..b13338f792e 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_unittest.cc
@@ -88,6 +88,9 @@ class TestBrowserAccessibilityDelegate
const gfx::Rect& bounds) const override {
return gfx::Point();
}
+ gfx::Rect AccessibilityTransformToRootCoordSpace(
+ const gfx::Rect& bounds) override { return gfx::Rect(); }
+ SiteInstance* AccessibilityGetSiteInstance() override { return nullptr; }
void AccessibilityHitTest(const gfx::Point& point) override {}
void AccessibilitySetAccessibilityFocus(int acc_obj_id) override {}
void AccessibilityFatalError() override { got_fatal_error_ = true; }
@@ -967,17 +970,18 @@ TEST(BrowserAccessibilityManagerTest, TestNextPreviousInTreeOrder) {
nullptr,
new CountedBrowserAccessibilityFactory()));
- auto root_accessible = manager->GetRoot();
+ BrowserAccessibility* root_accessible = manager->GetRoot();
ASSERT_NE(nullptr, root_accessible);
ASSERT_EQ(3U, root_accessible->PlatformChildCount());
- auto node2_accessible = root_accessible->PlatformGetChild(0);
+ BrowserAccessibility* node2_accessible = root_accessible->PlatformGetChild(0);
ASSERT_NE(nullptr, node2_accessible);
- auto node3_accessible = root_accessible->PlatformGetChild(1);
+ BrowserAccessibility* node3_accessible = root_accessible->PlatformGetChild(1);
ASSERT_NE(nullptr, node3_accessible);
ASSERT_EQ(1U, node3_accessible->PlatformChildCount());
- auto node4_accessible = node3_accessible->PlatformGetChild(0);
+ BrowserAccessibility* node4_accessible =
+ node3_accessible->PlatformGetChild(0);
ASSERT_NE(nullptr, node4_accessible);
- auto node5_accessible = root_accessible->PlatformGetChild(2);
+ BrowserAccessibility* node5_accessible = root_accessible->PlatformGetChild(2);
ASSERT_NE(nullptr, node5_accessible);
EXPECT_EQ(nullptr, manager->NextInTreeOrder(nullptr));
@@ -1042,26 +1046,30 @@ TEST(BrowserAccessibilityManagerTest, TestNextPreviousTextOnlyObject) {
nullptr,
new CountedBrowserAccessibilityFactory()));
- auto root_accessible = manager->GetRoot();
+ BrowserAccessibility* root_accessible = manager->GetRoot();
ASSERT_NE(nullptr, root_accessible);
ASSERT_EQ(4U, root_accessible->PlatformChildCount());
- auto node2_accessible = root_accessible->PlatformGetChild(0);
+ BrowserAccessibility* node2_accessible = root_accessible->PlatformGetChild(0);
ASSERT_NE(nullptr, node2_accessible);
- auto text1_accessible = root_accessible->PlatformGetChild(1);
+ BrowserAccessibility* text1_accessible = root_accessible->PlatformGetChild(1);
ASSERT_NE(nullptr, text1_accessible);
- auto node3_accessible = root_accessible->PlatformGetChild(2);
+ BrowserAccessibility* node3_accessible = root_accessible->PlatformGetChild(2);
ASSERT_NE(nullptr, node3_accessible);
ASSERT_EQ(3U, node3_accessible->PlatformChildCount());
- auto text2_accessible = node3_accessible->PlatformGetChild(0);
+ BrowserAccessibility* text2_accessible =
+ node3_accessible->PlatformGetChild(0);
ASSERT_NE(nullptr, text2_accessible);
- auto node4_accessible = node3_accessible->PlatformGetChild(1);
+ BrowserAccessibility* node4_accessible =
+ node3_accessible->PlatformGetChild(1);
ASSERT_NE(nullptr, node4_accessible);
- auto text3_accessible = node3_accessible->PlatformGetChild(2);
+ BrowserAccessibility* text3_accessible =
+ node3_accessible->PlatformGetChild(2);
ASSERT_NE(nullptr, text3_accessible);
- auto node5_accessible = root_accessible->PlatformGetChild(3);
+ BrowserAccessibility* node5_accessible = root_accessible->PlatformGetChild(3);
ASSERT_NE(nullptr, node5_accessible);
ASSERT_EQ(1U, node5_accessible->PlatformChildCount());
- auto text4_accessible = node5_accessible->PlatformGetChild(0);
+ BrowserAccessibility* text4_accessible =
+ node5_accessible->PlatformGetChild(0);
ASSERT_NE(nullptr, text4_accessible);
EXPECT_EQ(nullptr, manager->NextTextOnlyObject(nullptr));
@@ -1092,6 +1100,295 @@ TEST(BrowserAccessibilityManagerTest, TestNextPreviousTextOnlyObject) {
EXPECT_EQ(nullptr, manager->PreviousTextOnlyObject(root_accessible));
}
+TEST(BrowserAccessibilityManagerTest, TestFindIndicesInCommonParent) {
+ ui::AXNodeData root;
+ root.id = 1;
+ root.role = ui::AX_ROLE_ROOT_WEB_AREA;
+
+ ui::AXNodeData div;
+ div.id = 2;
+ div.role = ui::AX_ROLE_DIV;
+ root.child_ids.push_back(div.id);
+
+ ui::AXNodeData button;
+ button.id = 3;
+ button.role = ui::AX_ROLE_BUTTON;
+ div.child_ids.push_back(button.id);
+
+ ui::AXNodeData button_text;
+ button_text.id = 4;
+ button_text.role = ui::AX_ROLE_STATIC_TEXT;
+ button_text.SetName("Button");
+ button.child_ids.push_back(button_text.id);
+
+ ui::AXNodeData line_break;
+ line_break.id = 5;
+ line_break.role = ui::AX_ROLE_LINE_BREAK;
+ line_break.SetName("\n");
+ div.child_ids.push_back(line_break.id);
+
+ ui::AXNodeData paragraph;
+ paragraph.id = 6;
+ paragraph.role = ui::AX_ROLE_PARAGRAPH;
+ root.child_ids.push_back(paragraph.id);
+
+ ui::AXNodeData paragraph_text;
+ paragraph_text.id = 7;
+ paragraph_text.role = ui::AX_ROLE_STATIC_TEXT;
+ paragraph.child_ids.push_back(paragraph_text.id);
+
+ ui::AXNodeData paragraph_line1;
+ paragraph_line1.id = 8;
+ paragraph_line1.role = ui::AX_ROLE_INLINE_TEXT_BOX;
+ paragraph_line1.SetName("Hello ");
+ paragraph_text.child_ids.push_back(paragraph_line1.id);
+
+ ui::AXNodeData paragraph_line2;
+ paragraph_line2.id = 9;
+ paragraph_line2.role = ui::AX_ROLE_INLINE_TEXT_BOX;
+ paragraph_line2.SetName("world.");
+ paragraph_text.child_ids.push_back(paragraph_line2.id);
+
+ scoped_ptr<BrowserAccessibilityManager> manager(
+ BrowserAccessibilityManager::Create(
+ MakeAXTreeUpdate(root, div, button, button_text, line_break,
+ paragraph, paragraph_text, paragraph_line1,
+ paragraph_line2),
+ nullptr, new CountedBrowserAccessibilityFactory()));
+
+ BrowserAccessibility* root_accessible = manager->GetRoot();
+ ASSERT_NE(nullptr, root_accessible);
+ ASSERT_EQ(2U, root_accessible->PlatformChildCount());
+ BrowserAccessibility* div_accessible = root_accessible->PlatformGetChild(0);
+ ASSERT_NE(nullptr, div_accessible);
+ ASSERT_EQ(2U, div_accessible->PlatformChildCount());
+ BrowserAccessibility* button_accessible = div_accessible->PlatformGetChild(0);
+ ASSERT_NE(nullptr, button_accessible);
+ BrowserAccessibility* button_text_accessible =
+ button_accessible->PlatformGetChild(0);
+ ASSERT_NE(nullptr, button_text_accessible);
+ BrowserAccessibility* line_break_accessible =
+ div_accessible->PlatformGetChild(1);
+ ASSERT_NE(nullptr, line_break_accessible);
+ BrowserAccessibility* paragraph_accessible =
+ root_accessible->PlatformGetChild(1);
+ ASSERT_NE(nullptr, paragraph_accessible);
+ BrowserAccessibility* paragraph_text_accessible =
+ paragraph_accessible->PlatformGetChild(0);
+ ASSERT_NE(nullptr, paragraph_text_accessible);
+ ASSERT_EQ(2U, paragraph_text_accessible->InternalChildCount());
+ BrowserAccessibility* paragraph_line1_accessible =
+ paragraph_text_accessible->InternalGetChild(0);
+ ASSERT_NE(nullptr, paragraph_line1_accessible);
+ BrowserAccessibility* paragraph_line2_accessible =
+ paragraph_text_accessible->InternalGetChild(1);
+ ASSERT_NE(nullptr, paragraph_line2_accessible);
+
+ BrowserAccessibility* common_parent = nullptr;
+ int child_index1, child_index2;
+ EXPECT_FALSE(BrowserAccessibilityManager::FindIndicesInCommonParent(
+ *root_accessible, *root_accessible, &common_parent, &child_index1,
+ &child_index2));
+ EXPECT_EQ(nullptr, common_parent);
+ EXPECT_EQ(-1, child_index1);
+ EXPECT_EQ(-1, child_index2);
+
+ EXPECT_TRUE(BrowserAccessibilityManager::FindIndicesInCommonParent(
+ *div_accessible, *paragraph_accessible, &common_parent, &child_index1,
+ &child_index2));
+ EXPECT_EQ(root_accessible, common_parent);
+ EXPECT_EQ(0, child_index1);
+ EXPECT_EQ(1, child_index2);
+
+ EXPECT_TRUE(BrowserAccessibilityManager::FindIndicesInCommonParent(
+ *div_accessible, *paragraph_line1_accessible, &common_parent,
+ &child_index1, &child_index2));
+ EXPECT_EQ(root_accessible, common_parent);
+ EXPECT_EQ(0, child_index1);
+ EXPECT_EQ(1, child_index2);
+
+ EXPECT_TRUE(BrowserAccessibilityManager::FindIndicesInCommonParent(
+ *line_break_accessible, *paragraph_text_accessible, &common_parent,
+ &child_index1, &child_index2));
+ EXPECT_EQ(root_accessible, common_parent);
+ EXPECT_EQ(0, child_index1);
+ EXPECT_EQ(1, child_index2);
+
+ EXPECT_TRUE(BrowserAccessibilityManager::FindIndicesInCommonParent(
+ *button_text_accessible, *line_break_accessible, &common_parent,
+ &child_index1, &child_index2));
+ EXPECT_EQ(div_accessible, common_parent);
+ EXPECT_EQ(0, child_index1);
+ EXPECT_EQ(1, child_index2);
+
+ EXPECT_TRUE(BrowserAccessibilityManager::FindIndicesInCommonParent(
+ *paragraph_accessible, *paragraph_line2_accessible, &common_parent,
+ &child_index1, &child_index2));
+ EXPECT_EQ(root_accessible, common_parent);
+ EXPECT_EQ(1, child_index1);
+ EXPECT_EQ(1, child_index2);
+
+ EXPECT_TRUE(BrowserAccessibilityManager::FindIndicesInCommonParent(
+ *paragraph_text_accessible, *paragraph_line1_accessible, &common_parent,
+ &child_index1, &child_index2));
+ EXPECT_EQ(paragraph_accessible, common_parent);
+ EXPECT_EQ(0, child_index1);
+ EXPECT_EQ(0, child_index2);
+
+ EXPECT_TRUE(BrowserAccessibilityManager::FindIndicesInCommonParent(
+ *paragraph_line1_accessible, *paragraph_line2_accessible, &common_parent,
+ &child_index1, &child_index2));
+ EXPECT_EQ(paragraph_text_accessible, common_parent);
+ EXPECT_EQ(0, child_index1);
+ EXPECT_EQ(1, child_index2);
+}
+
+TEST(BrowserAccessibilityManagerTest, TestGetTextForRange) {
+ ui::AXNodeData root;
+ root.id = 1;
+ root.role = ui::AX_ROLE_ROOT_WEB_AREA;
+
+ ui::AXNodeData div;
+ div.id = 2;
+ div.role = ui::AX_ROLE_DIV;
+ root.child_ids.push_back(div.id);
+
+ ui::AXNodeData button;
+ button.id = 3;
+ button.role = ui::AX_ROLE_BUTTON;
+ div.child_ids.push_back(button.id);
+
+ ui::AXNodeData button_text;
+ button_text.id = 4;
+ button_text.role = ui::AX_ROLE_STATIC_TEXT;
+ button_text.SetName("Button");
+ button.child_ids.push_back(button_text.id);
+
+ ui::AXNodeData line_break;
+ line_break.id = 5;
+ line_break.role = ui::AX_ROLE_LINE_BREAK;
+ line_break.SetName("\n");
+ div.child_ids.push_back(line_break.id);
+
+ ui::AXNodeData paragraph;
+ paragraph.id = 6;
+ paragraph.role = ui::AX_ROLE_PARAGRAPH;
+ root.child_ids.push_back(paragraph.id);
+
+ ui::AXNodeData paragraph_text;
+ paragraph_text.id = 7;
+ paragraph_text.role = ui::AX_ROLE_STATIC_TEXT;
+ paragraph_text.SetName("Hello world.");
+ paragraph.child_ids.push_back(paragraph_text.id);
+
+ ui::AXNodeData paragraph_line1;
+ paragraph_line1.id = 8;
+ paragraph_line1.role = ui::AX_ROLE_INLINE_TEXT_BOX;
+ paragraph_line1.SetName("Hello ");
+ paragraph_text.child_ids.push_back(paragraph_line1.id);
+
+ ui::AXNodeData paragraph_line2;
+ paragraph_line2.id = 9;
+ paragraph_line2.role = ui::AX_ROLE_INLINE_TEXT_BOX;
+ paragraph_line2.SetName("world.");
+ paragraph_text.child_ids.push_back(paragraph_line2.id);
+
+ scoped_ptr<BrowserAccessibilityManager> manager(
+ BrowserAccessibilityManager::Create(
+ MakeAXTreeUpdate(root, div, button, button_text, line_break,
+ paragraph, paragraph_text, paragraph_line1,
+ paragraph_line2),
+ nullptr, new CountedBrowserAccessibilityFactory()));
+
+ BrowserAccessibility* root_accessible = manager->GetRoot();
+ ASSERT_NE(nullptr, root_accessible);
+ ASSERT_EQ(2U, root_accessible->PlatformChildCount());
+ BrowserAccessibility* div_accessible = root_accessible->PlatformGetChild(0);
+ ASSERT_NE(nullptr, div_accessible);
+ ASSERT_EQ(2U, div_accessible->PlatformChildCount());
+ BrowserAccessibility* button_accessible = div_accessible->PlatformGetChild(0);
+ ASSERT_NE(nullptr, button_accessible);
+ BrowserAccessibility* button_text_accessible =
+ button_accessible->PlatformGetChild(0);
+ ASSERT_NE(nullptr, button_text_accessible);
+ BrowserAccessibility* line_break_accessible =
+ div_accessible->PlatformGetChild(1);
+ ASSERT_NE(nullptr, line_break_accessible);
+ BrowserAccessibility* paragraph_accessible =
+ root_accessible->PlatformGetChild(1);
+ ASSERT_NE(nullptr, paragraph_accessible);
+ BrowserAccessibility* paragraph_text_accessible =
+ paragraph_accessible->PlatformGetChild(0);
+ ASSERT_NE(nullptr, paragraph_text_accessible);
+ ASSERT_EQ(2U, paragraph_text_accessible->InternalChildCount());
+ BrowserAccessibility* paragraph_line1_accessible =
+ paragraph_text_accessible->InternalGetChild(0);
+ ASSERT_NE(nullptr, paragraph_line1_accessible);
+ BrowserAccessibility* paragraph_line2_accessible =
+ paragraph_text_accessible->InternalGetChild(1);
+ ASSERT_NE(nullptr, paragraph_line2_accessible);
+
+ EXPECT_EQ(base::ASCIIToUTF16("Button\nHello world."),
+ BrowserAccessibilityManager::GetTextForRange(*root_accessible, 0,
+ *root_accessible, 19));
+ EXPECT_EQ(base::ASCIIToUTF16("ton\nHello world."),
+ BrowserAccessibilityManager::GetTextForRange(*root_accessible, 3,
+ *root_accessible, 19));
+ EXPECT_EQ(base::ASCIIToUTF16("Button\nHello world."),
+ BrowserAccessibilityManager::GetTextForRange(
+ *div_accessible, 0, *paragraph_accessible, 12));
+ EXPECT_EQ(base::ASCIIToUTF16("ton\nHello world."),
+ BrowserAccessibilityManager::GetTextForRange(
+ *div_accessible, 3, *paragraph_accessible, 12));
+
+ EXPECT_EQ(base::ASCIIToUTF16("Button\n"),
+ BrowserAccessibilityManager::GetTextForRange(*div_accessible, 0,
+ *div_accessible, 1));
+ EXPECT_EQ(base::ASCIIToUTF16("Button\n"),
+ BrowserAccessibilityManager::GetTextForRange(
+ *button_accessible, 0, *line_break_accessible, 1));
+
+ EXPECT_EQ(base::ASCIIToUTF16("Hello world."),
+ BrowserAccessibilityManager::GetTextForRange(
+ *paragraph_accessible, 0, *paragraph_accessible, 12));
+ EXPECT_EQ(base::ASCIIToUTF16("Hello wor"),
+ BrowserAccessibilityManager::GetTextForRange(
+ *paragraph_accessible, 0, *paragraph_accessible, 9));
+ EXPECT_EQ(base::ASCIIToUTF16("Hello world."),
+ BrowserAccessibilityManager::GetTextForRange(
+ *paragraph_text_accessible, 0, *paragraph_text_accessible, 12));
+ EXPECT_EQ(base::ASCIIToUTF16(" world."),
+ BrowserAccessibilityManager::GetTextForRange(
+ *paragraph_text_accessible, 5, *paragraph_text_accessible, 12));
+ EXPECT_EQ(base::ASCIIToUTF16("Hello world."),
+ BrowserAccessibilityManager::GetTextForRange(
+ *paragraph_accessible, 0, *paragraph_text_accessible, 12));
+ EXPECT_EQ(
+ base::ASCIIToUTF16("Hello "),
+ BrowserAccessibilityManager::GetTextForRange(
+ *paragraph_line1_accessible, 0, *paragraph_line1_accessible, 6));
+ EXPECT_EQ(
+ base::ASCIIToUTF16("Hello"),
+ BrowserAccessibilityManager::GetTextForRange(
+ *paragraph_line1_accessible, 0, *paragraph_line1_accessible, 5));
+ EXPECT_EQ(
+ base::ASCIIToUTF16("ello "),
+ BrowserAccessibilityManager::GetTextForRange(
+ *paragraph_line1_accessible, 1, *paragraph_line1_accessible, 6));
+ EXPECT_EQ(
+ base::ASCIIToUTF16("world."),
+ BrowserAccessibilityManager::GetTextForRange(
+ *paragraph_line2_accessible, 0, *paragraph_line2_accessible, 6));
+ EXPECT_EQ(
+ base::ASCIIToUTF16("orld"),
+ BrowserAccessibilityManager::GetTextForRange(
+ *paragraph_line2_accessible, 1, *paragraph_line2_accessible, 5));
+ EXPECT_EQ(
+ base::ASCIIToUTF16("Hello world."),
+ BrowserAccessibilityManager::GetTextForRange(
+ *paragraph_line1_accessible, 0, *paragraph_line2_accessible, 6));
+}
+
TEST(BrowserAccessibilityManagerTest, DeletingFocusedNodeDoesNotCrash) {
// Create a really simple tree with one root node and one focused child.
ui::AXNodeData root;
@@ -1102,27 +1399,18 @@ TEST(BrowserAccessibilityManagerTest, DeletingFocusedNodeDoesNotCrash) {
ui::AXNodeData node2;
node2.id = 2;
- node2.state = 1 << ui::AX_STATE_FOCUSED;
+ ui::AXTreeUpdate initial_state = MakeAXTreeUpdate(root, node2);
+ initial_state.has_tree_data = true;
+ initial_state.tree_data.focus_id = 2;
scoped_ptr<BrowserAccessibilityManager> manager(
BrowserAccessibilityManager::Create(
- MakeAXTreeUpdate(root, node2),
+ initial_state,
nullptr,
new CountedBrowserAccessibilityFactory()));
ASSERT_EQ(1, manager->GetRoot()->GetId());
- ASSERT_EQ(1, manager->GetFocus(manager->GetRoot())->GetId());
-
- // Send the focus event for node 2.
- std::vector<AXEventNotificationDetails> events;
- events.push_back(AXEventNotificationDetails());
- events[0].update = MakeAXTreeUpdate(node2);
- events[0].id = 2;
- events[0].event_type = ui::AX_EVENT_FOCUS;
- manager->OnAccessibilityEvents(events);
-
- ASSERT_EQ(1, manager->GetRoot()->GetId());
- ASSERT_EQ(2, manager->GetFocus(manager->GetRoot())->GetId());
+ ASSERT_EQ(2, manager->GetFocus()->GetId());
// Now replace the tree with a new tree consisting of a single root.
ui::AXNodeData root2;
@@ -1140,7 +1428,7 @@ TEST(BrowserAccessibilityManagerTest, DeletingFocusedNodeDoesNotCrash) {
// Make sure that the focused node was updated to the new root and
// that this doesn't crash.
ASSERT_EQ(3, manager->GetRoot()->GetId());
- ASSERT_EQ(3, manager->GetFocus(manager->GetRoot())->GetId());
+ ASSERT_EQ(3, manager->GetFocus()->GetId());
}
TEST(BrowserAccessibilityManagerTest, DeletingFocusedNodeDoesNotCrash2) {
@@ -1155,7 +1443,6 @@ TEST(BrowserAccessibilityManagerTest, DeletingFocusedNodeDoesNotCrash2) {
ui::AXNodeData node2;
node2.id = 2;
- node2.state = 1 << ui::AX_STATE_FOCUSED;
ui::AXNodeData node3;
node3.id = 3;
@@ -1165,25 +1452,17 @@ TEST(BrowserAccessibilityManagerTest, DeletingFocusedNodeDoesNotCrash2) {
node4.id = 4;
node4.state = 0;
+ ui::AXTreeUpdate initial_state = MakeAXTreeUpdate(root, node2, node3, node4);
+ initial_state.has_tree_data = true;
+ initial_state.tree_data.focus_id = 2;
scoped_ptr<BrowserAccessibilityManager> manager(
BrowserAccessibilityManager::Create(
- MakeAXTreeUpdate(root, node2, node3, node4),
+ initial_state,
nullptr,
new CountedBrowserAccessibilityFactory()));
ASSERT_EQ(1, manager->GetRoot()->GetId());
- ASSERT_EQ(1, manager->GetFocus(manager->GetRoot())->GetId());
-
- // Send the focus event for node 2.
- std::vector<AXEventNotificationDetails> events;
- events.push_back(AXEventNotificationDetails());
- events[0].update = MakeAXTreeUpdate(node2);
- events[0].id = 2;
- events[0].event_type = ui::AX_EVENT_FOCUS;
- manager->OnAccessibilityEvents(events);
-
- ASSERT_EQ(1, manager->GetRoot()->GetId());
- ASSERT_EQ(2, manager->GetFocus(manager->GetRoot())->GetId());
+ ASSERT_EQ(2, manager->GetFocus()->GetId());
// Now replace the tree with a new tree consisting of a single root.
ui::AXNodeData root2;
@@ -1203,7 +1482,7 @@ TEST(BrowserAccessibilityManagerTest, DeletingFocusedNodeDoesNotCrash2) {
// Make sure that the focused node was updated to the new root and
// that this doesn't crash.
ASSERT_EQ(3, manager->GetRoot()->GetId());
- ASSERT_EQ(3, manager->GetFocus(manager->GetRoot())->GetId());
+ ASSERT_EQ(3, manager->GetFocus()->GetId());
}
} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc b/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
index 4f963ebcb02..0595ea7d2fe 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_win.cc
@@ -20,10 +20,6 @@
namespace content {
-// Map from unique_id_win to BrowserAccessibility
-using UniqueIDWinMap = base::hash_map<LONG, BrowserAccessibility*>;
-base::LazyInstance<UniqueIDWinMap> g_unique_id_map = LAZY_INSTANCE_INITIALIZER;
-
// static
BrowserAccessibilityManager* BrowserAccessibilityManager::Create(
const ui::AXTreeUpdate& initial_tree,
@@ -42,11 +38,10 @@ BrowserAccessibilityManagerWin::BrowserAccessibilityManagerWin(
BrowserAccessibilityDelegate* delegate,
BrowserAccessibilityFactory* factory)
: BrowserAccessibilityManager(delegate, factory),
- tracked_scroll_object_(NULL),
- focus_event_on_root_needed_(false),
- inside_on_window_focused_(false) {
+ tracked_scroll_object_(NULL) {
ui::win::CreateATLModuleIfNeeded();
Initialize(initial_tree);
+ ui::GetIAccessible2UsageObserverList().AddObserver(this);
}
BrowserAccessibilityManagerWin::~BrowserAccessibilityManagerWin() {
@@ -59,6 +54,7 @@ BrowserAccessibilityManagerWin::~BrowserAccessibilityManagerWin() {
tracked_scroll_object_->Release();
tracked_scroll_object_ = NULL;
}
+ ui::GetIAccessible2UsageObserverList().RemoveObserver(this);
}
// static
@@ -93,7 +89,8 @@ IAccessible* BrowserAccessibilityManagerWin::GetParentIAccessible() {
void BrowserAccessibilityManagerWin::MaybeCallNotifyWinEvent(
DWORD event, BrowserAccessibility* node) {
- BrowserAccessibilityDelegate* delegate = GetDelegateFromRootManager();
+ BrowserAccessibilityDelegate* delegate =
+ node->manager()->GetDelegateFromRootManager();
if (!delegate) {
// This line and other LOG(WARNING) lines are temporary, to debug
// flaky failures in DumpAccessibilityEvent* tests.
@@ -118,65 +115,19 @@ void BrowserAccessibilityManagerWin::MaybeCallNotifyWinEvent(
// It doesn't make sense to fire a REORDER event on a leaf node; that
// happens when the node has internal children line inline text boxes.
- if (event == EVENT_OBJECT_REORDER && node->PlatformIsLeaf())
- return;
-
- // Don't fire focus, or load complete notifications if the
- // window isn't focused, because that can confuse screen readers into
- // entering their "browse" mode.
- if ((event == EVENT_OBJECT_FOCUS ||
- event == IA2_EVENT_DOCUMENT_LOAD_COMPLETE) &&
- !NativeViewHasFocus()) {
+ if (event == EVENT_OBJECT_REORDER && node->PlatformChildCount() == 0)
return;
- }
- // NVDA gets confused if we focus the main document element when it hasn't
- // finished loading and it has no children at all, so suppress that event.
- if (event == EVENT_OBJECT_FOCUS &&
- node == GetRoot() &&
- node->PlatformChildCount() == 0 &&
- !node->HasState(ui::AX_STATE_BUSY) &&
- !node->manager()->GetTreeData().loaded) {
- return;
- }
-
- // If a focus event is needed on the root, fire that first before
- // this event.
- if (event == EVENT_OBJECT_FOCUS && node == GetRoot())
- focus_event_on_root_needed_ = false;
- else if (focus_event_on_root_needed_)
- OnWindowFocused();
-
- LONG child_id = node->ToBrowserAccessibilityWin()->unique_id_win();
+ // Pass the negation of this node's unique id in the |child_id|
+ // argument to NotifyWinEvent; the AT client will then call get_accChild
+ // on the HWND's accessibility object and pass it that same id, which
+ // we can use to retrieve the IAccessible for this node.
+ LONG child_id = -node->unique_id();
::NotifyWinEvent(event, hwnd, OBJID_CLIENT, child_id);
}
-void BrowserAccessibilityManagerWin::OnWindowFocused() {
- // Make sure we don't call this recursively.
- if (inside_on_window_focused_)
- return;
- inside_on_window_focused_ = true;
-
- // This is called either when this web frame gets focused, or when
- // the root of the accessibility tree changes. In both cases, we need
- // to fire a focus event on the root and then on the focused element
- // within the page, if different.
-
- // Set this flag so that we'll keep trying to fire these focus events
- // if they're not successful this time.
- focus_event_on_root_needed_ = true;
-
- if (!NativeViewHasFocus()) {
- inside_on_window_focused_ = false;
- return;
- }
-
- // Try to fire a focus event on the root first and then the focused node.
- // This will clear focus_event_on_root_needed_ if successful.
- if (focus_ != tree_->root() && GetRoot())
- NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, GetRoot());
- BrowserAccessibilityManager::OnWindowFocused();
- inside_on_window_focused_ = false;
+void BrowserAccessibilityManagerWin::OnIAccessible2Used() {
+ BrowserAccessibilityStateImpl::GetInstance()->OnScreenReaderDetected();
}
void BrowserAccessibilityManagerWin::UserIsReloading() {
@@ -213,23 +164,6 @@ void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent(
return;
}
- // NVDA gets confused if we focus the main document element when it hasn't
- // finished loading and it has no children at all, so suppress that event.
- if (event_type == ui::AX_EVENT_FOCUS &&
- node == GetRoot() &&
- node->PlatformChildCount() == 0 &&
- !node->HasState(ui::AX_STATE_BUSY) &&
- !node->manager()->GetTreeData().loaded) {
- return;
- }
-
- // If a focus event is needed on the root, fire that first before
- // this event.
- if (event_type == ui::AX_EVENT_FOCUS && node == GetRoot())
- focus_event_on_root_needed_ = false;
- else if (focus_event_on_root_needed_)
- OnWindowFocused();
-
LONG event_id = EVENT_MIN;
switch (event_type) {
case ui::AX_EVENT_ACTIVEDESCENDANTCHANGED:
@@ -287,13 +221,9 @@ void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent(
if (!node)
return;
- if (event_id != EVENT_MIN) {
- // Pass the node's unique id in the |child_id| argument to NotifyWinEvent;
- // the AT client will then call get_accChild on the HWND's accessibility
- // object and pass it that same id, which we can use to retrieve the
- // IAccessible for this node.
+ if (event_id != EVENT_MIN)
MaybeCallNotifyWinEvent(event_id, node);
- }
+
// If this is a layout complete notification (sent when a container scrolls)
// and there is a descendant tracked object, send a notification on it.
@@ -308,6 +238,26 @@ void BrowserAccessibilityManagerWin::NotifyAccessibilityEvent(
}
}
+bool BrowserAccessibilityManagerWin::CanFireEvents() {
+ BrowserAccessibilityDelegate* root_delegate = GetDelegateFromRootManager();
+ if (!root_delegate)
+ return false;
+ HWND hwnd = root_delegate->AccessibilityGetAcceleratedWidget();
+ return hwnd != nullptr;
+}
+
+void BrowserAccessibilityManagerWin::FireFocusEvent(
+ BrowserAccessibility* node) {
+ // On Windows, we always fire a FOCUS event on the root of a frame before
+ // firing a focus event within that frame.
+ if (node->manager() != last_focused_manager_ &&
+ node != node->manager()->GetRoot()) {
+ NotifyAccessibilityEvent(ui::AX_EVENT_FOCUS, node->manager()->GetRoot());
+ }
+
+ BrowserAccessibilityManager::FireFocusEvent(node);
+}
+
void BrowserAccessibilityManagerWin::OnNodeCreated(ui::AXTree* tree,
ui::AXNode* node) {
DCHECK(node);
@@ -317,8 +267,6 @@ void BrowserAccessibilityManagerWin::OnNodeCreated(ui::AXTree* tree,
return;
if (!obj->IsNative())
return;
- LONG unique_id_win = obj->ToBrowserAccessibilityWin()->unique_id_win();
- g_unique_id_map.Get()[unique_id_win] = obj;
}
void BrowserAccessibilityManagerWin::OnNodeWillBeDeleted(ui::AXTree* tree,
@@ -326,8 +274,6 @@ void BrowserAccessibilityManagerWin::OnNodeWillBeDeleted(ui::AXTree* tree,
DCHECK(node);
BrowserAccessibility* obj = GetFromAXNode(node);
if (obj && obj->IsNative()) {
- g_unique_id_map.Get().erase(
- obj->ToBrowserAccessibilityWin()->unique_id_win());
if (obj == tracked_scroll_object_) {
tracked_scroll_object_->Release();
tracked_scroll_object_ = NULL;
@@ -346,12 +292,6 @@ void BrowserAccessibilityManagerWin::OnAtomicUpdateFinished(
BrowserAccessibilityManager::OnAtomicUpdateFinished(
tree, root_changed, changes);
- if (root_changed) {
- // In order to make screen readers aware of the new accessibility root,
- // we need to fire a focus event on it.
- OnWindowFocused();
- }
-
// Do a sequence of Windows-specific updates on each node. Each one is
// done in a single pass that must complete before the next step starts.
// The first step moves win_attributes_ to old_win_attributes_ and then
@@ -361,7 +301,7 @@ void BrowserAccessibilityManagerWin::OnAtomicUpdateFinished(
DCHECK(changed_node);
BrowserAccessibility* obj = GetFromAXNode(changed_node);
if (obj && obj->IsNative() && !obj->PlatformIsChildOfLeaf())
- obj->ToBrowserAccessibilityWin()->UpdateStep1ComputeWinAttributes();
+ ToBrowserAccessibilityWin(obj)->UpdateStep1ComputeWinAttributes();
}
// The next step updates the hypertext of each node, which is a
@@ -372,7 +312,7 @@ void BrowserAccessibilityManagerWin::OnAtomicUpdateFinished(
DCHECK(changed_node);
BrowserAccessibility* obj = GetFromAXNode(changed_node);
if (obj && obj->IsNative() && !obj->PlatformIsChildOfLeaf())
- obj->ToBrowserAccessibilityWin()->UpdateStep2ComputeHypertext();
+ ToBrowserAccessibilityWin(obj)->UpdateStep2ComputeHypertext();
}
// The third step fires events on nodes based on what's changed - like
@@ -388,7 +328,7 @@ void BrowserAccessibilityManagerWin::OnAtomicUpdateFinished(
DCHECK(changed_node);
BrowserAccessibility* obj = GetFromAXNode(changed_node);
if (obj && obj->IsNative() && !obj->PlatformIsChildOfLeaf()) {
- obj->ToBrowserAccessibilityWin()->UpdateStep3FireEvents(
+ ToBrowserAccessibilityWin(obj)->UpdateStep3FireEvents(
changes[i].type == AXTreeDelegate::SUBTREE_CREATED);
}
}
@@ -402,13 +342,4 @@ void BrowserAccessibilityManagerWin::TrackScrollingObject(
tracked_scroll_object_->AddRef();
}
-BrowserAccessibilityWin* BrowserAccessibilityManagerWin::GetFromUniqueIdWin(
- LONG unique_id_win) {
- auto iter = g_unique_id_map.Get().find(unique_id_win);
- if (iter == g_unique_id_map.Get().end())
- return nullptr;
-
- return iter->second->ToBrowserAccessibilityWin();
-}
-
} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility_manager_win.h b/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
index b9da9a12c6a..04b8aa241bb 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_manager_win.h
@@ -11,13 +11,15 @@
#include "base/memory/scoped_ptr.h"
#include "base/win/scoped_comptr.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "ui/accessibility/platform/ax_platform_node_win.h"
namespace content {
class BrowserAccessibilityWin;
// Manages a tree of BrowserAccessibilityWin objects.
class CONTENT_EXPORT BrowserAccessibilityManagerWin
- : public BrowserAccessibilityManager {
+ : public BrowserAccessibilityManager,
+ public ui::IAccessible2UsageObserver {
public:
BrowserAccessibilityManagerWin(
const ui::AXTreeUpdate& initial_tree,
@@ -37,26 +39,26 @@ class CONTENT_EXPORT BrowserAccessibilityManagerWin
// Calls NotifyWinEvent if the parent window's IAccessible pointer is known.
void MaybeCallNotifyWinEvent(DWORD event, BrowserAccessibility* node);
+ // IAccessible2UsageObserver
+ void OnIAccessible2Used() override;
+
// BrowserAccessibilityManager methods
- void OnWindowFocused() override;
void UserIsReloading() override;
void NotifyAccessibilityEvent(
ui::AXEvent event_type, BrowserAccessibility* node) override;
+ bool CanFireEvents() override;
+ void FireFocusEvent(BrowserAccessibility* node) override;
// Track this object and post a VISIBLE_DATA_CHANGED notification when
// its container scrolls.
// TODO(dmazzoni): remove once http://crbug.com/113483 is fixed.
void TrackScrollingObject(BrowserAccessibilityWin* node);
- // Return a pointer to the object corresponding to the given windows-specific
- // unique id, does not make a new reference.
- BrowserAccessibilityWin* GetFromUniqueIdWin(LONG unique_id_win);
-
// Called when |accessible_hwnd_| is deleted by its parent.
void OnAccessibleHwndDeleted();
protected:
- // AXTree methods.
+ // AXTreeDelegate methods.
void OnNodeWillBeDeleted(ui::AXTree* tree, ui::AXNode* node) override;
void OnNodeCreated(ui::AXTree* tree, ui::AXNode* node) override;
void OnAtomicUpdateFinished(
@@ -73,14 +75,6 @@ class CONTENT_EXPORT BrowserAccessibilityManagerWin
// TODO(dmazzoni): remove once http://crbug.com/113483 is fixed.
BrowserAccessibilityWin* tracked_scroll_object_;
- // Set to true if we need to fire a focus event on the root as soon as
- // possible.
- bool focus_event_on_root_needed_;
-
- // A flag to keep track of if we're inside the OnWindowFocused call stack
- // so we don't keep calling it recursively.
- bool inside_on_window_focused_;
-
DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityManagerWin);
};
diff --git a/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc b/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc
index 8fb3442d422..4038d66d063 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_state_impl.cc
@@ -122,7 +122,7 @@ void BrowserAccessibilityStateImpl::UpdateHistograms() {
switches::kForceRendererAccessibility));
}
-#if !defined(OS_WIN)
+#if !defined(OS_WIN) && !defined(OS_MACOSX)
void BrowserAccessibilityStateImpl::UpdatePlatformSpecificHistograms() {
}
#endif
diff --git a/chromium/content/browser/accessibility/browser_accessibility_state_impl_mac.mm b/chromium/content/browser/accessibility/browser_accessibility_state_impl_mac.mm
new file mode 100644
index 00000000000..863627f0f2e
--- /dev/null
+++ b/chromium/content/browser/accessibility/browser_accessibility_state_impl_mac.mm
@@ -0,0 +1,44 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/accessibility/browser_accessibility_state_impl.h"
+
+#import <Cocoa/Cocoa.h>
+
+#include "base/metrics/histogram.h"
+
+@interface NSWorkspace (Partials)
+
+@property(readonly) BOOL accessibilityDisplayShouldDifferentiateWithoutColor;
+@property(readonly) BOOL accessibilityDisplayShouldIncreaseContrast;
+@property(readonly) BOOL accessibilityDisplayShouldReduceTransparency;
+
+@end
+
+namespace content {
+
+void BrowserAccessibilityStateImpl::UpdatePlatformSpecificHistograms() {
+ // NOTE: This function is running on the file thread.
+ NSWorkspace* workspace = [NSWorkspace sharedWorkspace];
+
+ SEL sel = @selector(accessibilityDisplayShouldIncreaseContrast);
+ if (![workspace respondsToSelector:sel])
+ return;
+
+ UMA_HISTOGRAM_BOOLEAN(
+ "Accessibility.Mac.DifferentiateWithoutColor",
+ workspace.accessibilityDisplayShouldDifferentiateWithoutColor);
+ UMA_HISTOGRAM_BOOLEAN(
+ "Accessibility.Mac.IncreaseContrast",
+ workspace.accessibilityDisplayShouldIncreaseContrast);
+ UMA_HISTOGRAM_BOOLEAN(
+ "Accessibility.Mac.ReduceTransparency",
+ workspace.accessibilityDisplayShouldReduceTransparency);
+
+ UMA_HISTOGRAM_BOOLEAN(
+ "Accessibility.Mac.FullKeyboardAccessEnabled",
+ static_cast<NSApplication*>(NSApp).fullKeyboardAccessEnabled);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc b/chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc
index 1409b0f1ab5..1267770e9a2 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_state_impl_win.cc
@@ -10,6 +10,7 @@
#include "base/files/file_path.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/metrics/histogram.h"
#include "base/strings/string_util.h"
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win.cc b/chromium/content/browser/accessibility/browser_accessibility_win.cc
index 54165ed7323..98aeb77bc77 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_win.cc
@@ -20,6 +20,7 @@
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/common/accessibility_messages.h"
#include "content/public/common/content_client.h"
+#include "third_party/skia/include/core/SkColor.h"
#include "ui/accessibility/ax_text_utils.h"
#include "ui/base/win/accessibility_ids_win.h"
#include "ui/base/win/accessibility_misc_utils.h"
@@ -42,10 +43,6 @@ const GUID GUID_IAccessibleContentDocument = {
const base::char16 BrowserAccessibilityWin::kEmbeddedCharacter = L'\xfffc';
-// static
-LONG BrowserAccessibilityWin::next_unique_id_win_ =
- base::win::kFirstBrowserAccessibilityManagerAccessibilityId;
-
//
// BrowserAccessibilityRelation
//
@@ -119,9 +116,8 @@ STDMETHODIMP BrowserAccessibilityRelation::get_nTargets(long* n_targets) {
*n_targets = static_cast<long>(target_ids_.size());
- BrowserAccessibilityManager* manager = owner_->manager();
for (long i = *n_targets - 1; i >= 0; --i) {
- BrowserAccessibility* result = manager->GetFromID(target_ids_[i]);
+ BrowserAccessibilityWin* result = owner_->GetFromID(target_ids_[i]);
if (!result || !result->instance_active()) {
*n_targets = 0;
break;
@@ -143,14 +139,12 @@ STDMETHODIMP BrowserAccessibilityRelation::get_target(long target_index,
return E_INVALIDARG;
}
- BrowserAccessibilityManager* manager = owner_->manager();
- BrowserAccessibility* result =
- manager->GetFromID(target_ids_[target_index]);
+ BrowserAccessibility* result = owner_->GetFromID(target_ids_[target_index]);
if (!result || !result->instance_active())
return E_FAIL;
*target = static_cast<IAccessible*>(
- result->ToBrowserAccessibilityWin()->NewReference());
+ ToBrowserAccessibilityWin(result)->NewReference());
return S_OK;
}
@@ -207,29 +201,10 @@ BrowserAccessibility* BrowserAccessibility::Create() {
return instance->NewReference();
}
-const BrowserAccessibilityWin* BrowserAccessibility::ToBrowserAccessibilityWin()
- const {
- return static_cast<const BrowserAccessibilityWin*>(this);
-}
-
-BrowserAccessibilityWin* BrowserAccessibility::ToBrowserAccessibilityWin() {
- return static_cast<BrowserAccessibilityWin*>(this);
-}
-
BrowserAccessibilityWin::BrowserAccessibilityWin()
: win_attributes_(new WinAttributes()),
previous_scroll_x_(0),
previous_scroll_y_(0) {
- // Start unique IDs at -1 and decrement each time, because get_accChild
- // uses positive IDs to enumerate children, so we use negative IDs to
- // clearly distinguish between indices and unique IDs.
- unique_id_win_ = next_unique_id_win_;
- if (next_unique_id_win_ ==
- base::win::kLastBrowserAccessibilityManagerAccessibilityId) {
- next_unique_id_win_ =
- base::win::kFirstBrowserAccessibilityManagerAccessibilityId;
- }
- next_unique_id_win_--;
}
BrowserAccessibilityWin::~BrowserAccessibilityWin() {
@@ -254,6 +229,10 @@ HRESULT BrowserAccessibilityWin::accDoDefaultAction(VARIANT var_id) {
if (!target)
return E_INVALIDARG;
+ // Return an error if it's not clickable.
+ if (!target->HasStringAttribute(ui::AX_ATTR_ACTION))
+ return DISP_E_MEMBERNOTFOUND;
+
manager()->DoDefaultAction(*target);
return S_OK;
}
@@ -281,7 +260,7 @@ STDMETHODIMP BrowserAccessibilityWin::accHitTest(LONG x_left,
child->lVal = CHILDID_SELF;
} else {
child->vt = VT_DISPATCH;
- child->pdispVal = result->ToBrowserAccessibilityWin()->NewReference();
+ child->pdispVal = ToBrowserAccessibilityWin(result)->NewReference();
}
return S_OK;
}
@@ -355,7 +334,7 @@ STDMETHODIMP BrowserAccessibilityWin::accNavigate(LONG nav_dir,
}
end->vt = VT_DISPATCH;
- end->pdispVal = result->ToBrowserAccessibilityWin()->NewReference();
+ end->pdispVal = ToBrowserAccessibilityWin(result)->NewReference();
return S_OK;
}
@@ -435,7 +414,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accFocus(VARIANT* focus_child) {
return E_INVALIDARG;
BrowserAccessibilityWin* focus = static_cast<BrowserAccessibilityWin*>(
- manager()->GetFocus(this));
+ manager()->GetFocus());
if (focus == this) {
focus_child->vt = VT_I4;
focus_child->lVal = CHILDID_SELF;
@@ -487,8 +466,16 @@ STDMETHODIMP BrowserAccessibilityWin::get_accName(VARIANT var_id, BSTR* name) {
return E_INVALIDARG;
base::string16 name_str = target->name();
- if (name_str.empty())
- return S_FALSE;
+ if (name_str.empty()) {
+ if (target->ia2_role() == ROLE_SYSTEM_DOCUMENT && GetParent()) {
+ // Hack: Some versions of JAWS crash if they get an empty name on
+ // a document that's the child of an iframe, so always return a
+ // nonempty string for this role. https://crbug.com/583057
+ name_str = L" ";
+ } else {
+ return S_FALSE;
+ }
+ }
*name = SysAllocString(name_str.c_str());
@@ -503,7 +490,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accParent(IDispatch** disp_parent) {
if (!disp_parent)
return E_INVALIDARG;
- IAccessible* parent_obj = GetParent()->ToBrowserAccessibilityWin();
+ IAccessible* parent_obj = ToBrowserAccessibilityWin(GetParent());
if (parent_obj == NULL) {
// This happens if we're the root of the tree;
// return the IAccessible for the window.
@@ -562,7 +549,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accState(VARIANT var_id,
state->vt = VT_I4;
state->lVal = target->ia_state();
- if (manager()->GetFocus(NULL) == this)
+ if (manager()->GetFocus() == this)
state->lVal |= STATE_SYSTEM_FOCUSED;
return S_OK;
@@ -591,14 +578,15 @@ STDMETHODIMP BrowserAccessibilityWin::get_accValue(VARIANT var_id,
// Expose color well value.
if (target->ia2_role() == IA2_ROLE_COLOR_CHOOSER) {
- int color = target->GetIntAttribute(ui::AX_ATTR_COLOR_VALUE);
- int red = (color >> 16) & 0xFF;
- int green = (color >> 8) & 0xFF;
- int blue = color & 0xFF;
+ unsigned int color = static_cast<unsigned int>(
+ target->GetIntAttribute(ui::AX_ATTR_COLOR_VALUE));
+ unsigned int red = SkColorGetR(color);
+ unsigned int green = SkColorGetG(color);
+ unsigned int blue = SkColorGetB(color);
base::string16 value_text;
- value_text = base::IntToString16((red * 100) / 255) + L"% red " +
- base::IntToString16((green * 100) / 255) + L"% green " +
- base::IntToString16((blue * 100) / 255) + L"% blue";
+ value_text = base::UintToString16(red * 100 / 255) + L"% red " +
+ base::UintToString16(green * 100 / 255) + L"% green " +
+ base::UintToString16(blue * 100 / 255) + L"% blue";
*value = SysAllocString(value_text.c_str());
DCHECK(*value);
return S_OK;
@@ -638,7 +626,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accSelection(VARIANT* selected) {
if (InternalGetChild(i)->HasState(ui::AX_STATE_SELECTED)) {
selected->vt = VT_DISPATCH;
selected->pdispVal =
- InternalGetChild(i)->ToBrowserAccessibilityWin()->NewReference();
+ ToBrowserAccessibilityWin(InternalGetChild(i))->NewReference();
return S_OK;
}
}
@@ -653,7 +641,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_accSelection(VARIANT* selected) {
if (InternalGetChild(i)->HasState(ui::AX_STATE_SELECTED)) {
enum_variant->ItemAt(index)->vt = VT_DISPATCH;
enum_variant->ItemAt(index)->pdispVal =
- InternalGetChild(i)->ToBrowserAccessibilityWin()->NewReference();
+ ToBrowserAccessibilityWin(InternalGetChild(i))->NewReference();
++index;
}
}
@@ -669,7 +657,7 @@ STDMETHODIMP BrowserAccessibilityWin::accSelect(
return E_FAIL;
if (flags_sel & SELFLAG_TAKEFOCUS) {
- manager()->SetFocus(this, true);
+ manager()->SetFocus(*this);
return S_OK;
}
@@ -702,19 +690,16 @@ STDMETHODIMP BrowserAccessibilityWin::role(LONG* role) {
}
STDMETHODIMP BrowserAccessibilityWin::get_attributes(BSTR* attributes) {
- if (!instance_active())
- return E_FAIL;
-
if (!attributes)
return E_INVALIDARG;
+ *attributes = nullptr;
+
+ if (!instance_active())
+ return E_FAIL;
- // The iaccessible2 attributes are a set of key-value pairs
- // separated by semicolons, with a colon between the key and the value.
base::string16 str;
- const std::vector<base::string16>& attributes_list = ia2_attributes();
- for (unsigned int i = 0; i < attributes_list.size(); ++i) {
- str += attributes_list[i] + L';';
- }
+ for (const base::string16& attribute : ia2_attributes())
+ str += attribute + L';';
if (str.empty())
return S_FALSE;
@@ -743,7 +728,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_uniqueID(LONG* unique_id) {
if (!unique_id)
return E_INVALIDARG;
- *unique_id = unique_id_win_;
+ *unique_id = -unique_id_;
return S_OK;
}
@@ -862,7 +847,6 @@ STDMETHODIMP BrowserAccessibilityWin::scrollTo(IA2ScrollType scroll_type) {
}
manager()->ToBrowserAccessibilityManagerWin()->TrackScrollingObject(this);
-
return S_OK;
}
@@ -1196,8 +1180,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnDescription(long column,
GetIntListAttribute(ui::AX_ATTR_CELL_IDS);
for (int i = 0; i < rows; ++i) {
int cell_id = cell_ids[i * columns + column];
- BrowserAccessibilityWin* cell = static_cast<BrowserAccessibilityWin*>(
- manager()->GetFromID(cell_id));
+ BrowserAccessibilityWin* cell = GetFromID(cell_id);
if (cell && cell->GetRole() == ui::AX_ROLE_COLUMN_HEADER) {
base::string16 cell_name = cell->GetString16Attribute(
ui::AX_ATTR_NAME);
@@ -1242,8 +1225,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnExtentAt(
const std::vector<int32_t>& cell_ids =
GetIntListAttribute(ui::AX_ATTR_CELL_IDS);
int cell_id = cell_ids[row * columns + column];
- BrowserAccessibilityWin* cell = static_cast<BrowserAccessibilityWin*>(
- manager()->GetFromID(cell_id));
+ BrowserAccessibilityWin* cell = GetFromID(cell_id);
int colspan;
if (cell &&
cell->GetIntAttribute(
@@ -1280,8 +1262,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnIndex(long cell_index,
return S_FALSE;
int cell_id = unique_cell_ids[cell_index];
- BrowserAccessibilityWin* cell =
- manager()->GetFromID(cell_id)->ToBrowserAccessibilityWin();
+ BrowserAccessibilityWin* cell = GetFromID(cell_id);
int col_index;
if (cell &&
cell->GetIntAttribute(
@@ -1385,8 +1366,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowDescription(long row,
GetIntListAttribute(ui::AX_ATTR_CELL_IDS);
for (int i = 0; i < columns; ++i) {
int cell_id = cell_ids[row * columns + i];
- BrowserAccessibilityWin* cell =
- manager()->GetFromID(cell_id)->ToBrowserAccessibilityWin();
+ BrowserAccessibilityWin* cell = GetFromID(cell_id);
if (cell && cell->GetRole() == ui::AX_ROLE_ROW_HEADER) {
base::string16 cell_name = cell->GetString16Attribute(
ui::AX_ATTR_NAME);
@@ -1430,8 +1410,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowExtentAt(long row,
const std::vector<int32_t>& cell_ids =
GetIntListAttribute(ui::AX_ATTR_CELL_IDS);
int cell_id = cell_ids[row * columns + column];
- BrowserAccessibilityWin* cell =
- manager()->GetFromID(cell_id)->ToBrowserAccessibilityWin();
+ BrowserAccessibilityWin* cell = GetFromID(cell_id);
int rowspan;
if (cell &&
cell->GetIntAttribute(
@@ -1468,8 +1447,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowIndex(long cell_index,
return S_FALSE;
int cell_id = unique_cell_ids[cell_index];
- BrowserAccessibilityWin* cell =
- manager()->GetFromID(cell_id)->ToBrowserAccessibilityWin();
+ BrowserAccessibilityWin* cell = GetFromID(cell_id);
int cell_row_index;
if (cell &&
cell->GetIntAttribute(
@@ -1597,8 +1575,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowColumnExtentsAtIndex(
return S_FALSE;
int cell_id = unique_cell_ids[index];
- BrowserAccessibilityWin* cell =
- manager()->GetFromID(cell_id)->ToBrowserAccessibilityWin();
+ BrowserAccessibilityWin* cell = GetFromID(cell_id);
int rowspan;
int colspan;
if (cell &&
@@ -1756,8 +1733,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnHeaderCells(
for (int i = 0; i < rows; ++i) {
int cell_id = cell_ids[i * columns + column];
- BrowserAccessibilityWin* cell =
- manager()->GetFromID(cell_id)->ToBrowserAccessibilityWin();
+ BrowserAccessibilityWin* cell = GetFromID(cell_id);
if (cell && cell->GetRole() == ui::AX_ROLE_COLUMN_HEADER)
(*n_column_header_cells)++;
}
@@ -1770,7 +1746,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_columnHeaderCells(
BrowserAccessibility* cell = manager()->GetFromID(cell_id);
if (cell && cell->GetRole() == ui::AX_ROLE_COLUMN_HEADER) {
(*cell_accessibles)[index] = static_cast<IAccessible*>(
- cell->ToBrowserAccessibilityWin()->NewReference());
+ ToBrowserAccessibilityWin(cell)->NewReference());
++index;
}
}
@@ -1867,7 +1843,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_rowHeaderCells(
BrowserAccessibility* cell = manager()->GetFromID(cell_id);
if (cell && cell->GetRole() == ui::AX_ROLE_ROW_HEADER) {
(*cell_accessibles)[index] = static_cast<IAccessible*>(
- cell->ToBrowserAccessibilityWin()->NewReference());
+ ToBrowserAccessibilityWin(cell)->NewReference());
++index;
}
}
@@ -1962,7 +1938,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_table(IUnknown** table) {
}
*table = static_cast<IAccessibleTable*>(
- find_table->ToBrowserAccessibilityWin()->NewReference());
+ ToBrowserAccessibilityWin(find_table)->NewReference());
return S_OK;
}
@@ -2364,15 +2340,40 @@ STDMETHODIMP BrowserAccessibilityWin::setSelection(LONG selection_index,
return S_OK;
}
-//
-// IAccessibleText methods not implemented.
-//
-
STDMETHODIMP BrowserAccessibilityWin::get_attributes(LONG offset,
LONG* start_offset,
LONG* end_offset,
BSTR* text_attributes) {
- return E_NOTIMPL;
+ if (!start_offset || !end_offset || !text_attributes)
+ return E_INVALIDARG;
+
+ *start_offset = *end_offset = 0;
+ *text_attributes = nullptr;
+ if (!instance_active())
+ return E_FAIL;
+
+ const base::string16& text = GetText();
+ HandleSpecialTextOffset(text, &offset);
+ if (offset < 0 || offset > static_cast<LONG>(text.size()))
+ return E_INVALIDARG;
+
+ ComputeStylesIfNeeded();
+ *start_offset = FindStartOfStyle(offset, ui::BACKWARDS_DIRECTION);
+ *end_offset = FindStartOfStyle(offset, ui::FORWARDS_DIRECTION);
+
+ base::string16 attributes_str;
+ const std::vector<base::string16>& attributes =
+ offset_to_text_attributes().find(*start_offset)->second;
+ for (const base::string16& attribute : attributes) {
+ attributes_str += attribute + L';';
+ }
+
+ if (attributes.empty())
+ return S_FALSE;
+
+ *text_attributes = SysAllocString(attributes_str.c_str());
+ DCHECK(*text_attributes);
+ return S_OK;
}
//
@@ -2403,14 +2404,12 @@ STDMETHODIMP BrowserAccessibilityWin::get_hyperlink(
}
int32_t id = hyperlinks()[index];
- BrowserAccessibilityWin* child =
- manager()->GetFromID(id)->ToBrowserAccessibilityWin();
- if (child) {
- *hyperlink = static_cast<IAccessibleHyperlink*>(child->NewReference());
- return S_OK;
- }
+ BrowserAccessibilityWin* link = GetFromID(id);
+ if (!link)
+ return E_FAIL;
- return E_FAIL;
+ *hyperlink = static_cast<IAccessibleHyperlink*>(link->NewReference());
+ return S_OK;
}
STDMETHODIMP BrowserAccessibilityWin::get_hyperlinkIndex(
@@ -2502,7 +2501,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_startIndex(long* index) {
const auto parent = GetParent();
if (parent) {
hypertext_offset =
- parent->ToBrowserAccessibilityWin()->GetHypertextOffsetFromChild(*this);
+ ToBrowserAccessibilityWin(parent)->GetHypertextOffsetFromChild(*this);
}
*index = static_cast<LONG>(hypertext_offset);
return S_OK;
@@ -2743,7 +2742,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_nodeInfo(
*name_space_id = 0;
*node_value = SysAllocString(value().c_str());
*num_children = PlatformChildCount();
- *unique_id = unique_id_win_;
+ *unique_id = -unique_id_;
if (GetRole() == ui::AX_ROLE_ROOT_WEB_AREA ||
GetRole() == ui::AX_ROLE_WEB_AREA) {
@@ -2881,7 +2880,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_parentNode(ISimpleDOMNode** node) {
if (!node)
return E_INVALIDARG;
- *node = GetParent()->ToBrowserAccessibilityWin()->NewReference();
+ *node = ToBrowserAccessibilityWin(GetParent())->NewReference();
return S_OK;
}
@@ -2897,7 +2896,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_firstChild(ISimpleDOMNode** node) {
return S_FALSE;
}
- *node = PlatformGetChild(0)->ToBrowserAccessibilityWin()->NewReference();
+ *node = ToBrowserAccessibilityWin(PlatformGetChild(0))->NewReference();
return S_OK;
}
@@ -2913,8 +2912,8 @@ STDMETHODIMP BrowserAccessibilityWin::get_lastChild(ISimpleDOMNode** node) {
return S_FALSE;
}
- *node = PlatformGetChild(PlatformChildCount() - 1)
- ->ToBrowserAccessibilityWin()->NewReference();
+ *node = ToBrowserAccessibilityWin(
+ PlatformGetChild(PlatformChildCount() - 1))->NewReference();
return S_OK;
}
@@ -2931,8 +2930,8 @@ STDMETHODIMP BrowserAccessibilityWin::get_previousSibling(
return S_FALSE;
}
- *node = GetParent()->InternalGetChild(GetIndexInParent() - 1)->
- ToBrowserAccessibilityWin()->NewReference();
+ *node = ToBrowserAccessibilityWin(
+ GetParent()->InternalGetChild(GetIndexInParent() - 1))->NewReference();
return S_OK;
}
@@ -2951,8 +2950,8 @@ STDMETHODIMP BrowserAccessibilityWin::get_nextSibling(ISimpleDOMNode** node) {
return S_FALSE;
}
- *node = GetParent()->InternalGetChild(GetIndexInParent() + 1)->
- ToBrowserAccessibilityWin()->NewReference();
+ *node = ToBrowserAccessibilityWin(
+ GetParent()->InternalGetChild(GetIndexInParent() + 1))->NewReference();
return S_OK;
}
@@ -2974,7 +2973,7 @@ STDMETHODIMP BrowserAccessibilityWin::get_childAt(
return S_FALSE;
}
- *node = child->ToBrowserAccessibilityWin()->NewReference();
+ *node = ToBrowserAccessibilityWin(child)->NewReference();
return S_OK;
}
@@ -2988,7 +2987,20 @@ BrowserAccessibilityWin::get_localInterface(void** local_interface) {
}
STDMETHODIMP BrowserAccessibilityWin::get_language(BSTR* language) {
- return E_NOTIMPL;
+ if (!language)
+ return E_INVALIDARG;
+ *language = nullptr;
+
+ if (!instance_active())
+ return E_FAIL;
+
+ base::string16 lang = GetInheritedString16Attribute(ui::AX_ATTR_LANGUAGE);
+ if (lang.empty())
+ lang = L"en-US";
+
+ *language = SysAllocString(lang.c_str());
+ DCHECK(*language);
+ return S_OK;
}
//
@@ -3067,7 +3079,21 @@ STDMETHODIMP BrowserAccessibilityWin::scrollToSubstring(
}
STDMETHODIMP BrowserAccessibilityWin::get_fontFamily(BSTR* font_family) {
- return E_NOTIMPL;
+ if (!font_family)
+ return E_INVALIDARG;
+ *font_family = nullptr;
+
+ if (!instance_active())
+ return E_FAIL;
+
+ base::string16 family =
+ GetInheritedString16Attribute(ui::AX_ATTR_FONT_FAMILY);
+ if (family.empty())
+ return S_FALSE;
+
+ *font_family = SysAllocString(family.c_str());
+ DCHECK(*font_family);
+ return S_OK;
}
//
@@ -3093,7 +3119,7 @@ STDMETHODIMP BrowserAccessibilityWin::QueryService(REFGUID guid_service,
BrowserAccessibility* node = this;
while (node->GetParent())
node = node->GetParent()->manager()->GetRoot();
- return node->ToBrowserAccessibilityWin()->QueryInterface(
+ return ToBrowserAccessibilityWin(node)->QueryInterface(
IID_IAccessible2, object);
}
@@ -3248,6 +3274,45 @@ HRESULT WINAPI BrowserAccessibilityWin::InternalQueryInterface(
this_ptr, entries, iid, object);
}
+void BrowserAccessibilityWin::ComputeStylesIfNeeded() {
+ if (!offset_to_text_attributes().empty())
+ return;
+
+ std::map<int, std::vector<base::string16>> attributes_map;
+ if (PlatformIsLeaf()) {
+ attributes_map[0] = ComputeTextAttributes();
+ win_attributes_->offset_to_text_attributes.swap(attributes_map);
+ return;
+ }
+
+ int start_offset = 0;
+ for (size_t i = 0; i < PlatformChildCount(); ++i) {
+ const auto child = ToBrowserAccessibilityWin(PlatformGetChild(i));
+ DCHECK(child);
+ std::vector<base::string16> attributes(child->ComputeTextAttributes());
+
+ if (attributes_map.empty()) {
+ attributes_map[start_offset] = attributes;
+ } else {
+ // Only add the attributes for this child if we are at the start of a new
+ // style span.
+ std::vector<base::string16> previous_attributes =
+ attributes_map.rbegin()->second;
+ if (!std::equal(attributes.begin(), attributes.end(),
+ previous_attributes.begin())) {
+ attributes_map[start_offset] = attributes;
+ }
+ }
+
+ if (child->IsTextOnlyObject())
+ start_offset += child->GetText().length();
+ else
+ start_offset += 1;
+ }
+
+ win_attributes_->offset_to_text_attributes.swap(attributes_map);
+}
+
base::string16 BrowserAccessibilityWin::GetText() const {
if (PlatformIsChildOfLeaf())
return BrowserAccessibility::GetText();
@@ -3308,6 +3373,13 @@ void BrowserAccessibilityWin::UpdateStep1ComputeWinAttributes() {
BoolAttributeToIA2(ui::AX_ATTR_CONTAINER_LIVE_BUSY,
"container-busy");
+ // Expose the non-standard explicit-name IA2 attribute.
+ int name_from;
+ if (GetIntAttribute(ui::AX_ATTR_NAME_FROM, &name_from) &&
+ name_from != ui::AX_NAME_FROM_CONTENTS) {
+ win_attributes_->ia2_attributes.push_back(L"explicit-name:true");
+ }
+
// Expose table cell index.
if (IsCellOrTableHeaderRole()) {
BrowserAccessibility* table = GetParent();
@@ -3325,44 +3397,6 @@ void BrowserAccessibilityWin::UpdateStep1ComputeWinAttributes() {
}
}
- // Expose invalid state for form controls and elements with aria-invalid.
- int invalid_state;
- if (GetIntAttribute(ui::AX_ATTR_INVALID_STATE, &invalid_state)) {
- // TODO(nektar): Handle the possibility of having multiple aria-invalid
- // attributes defined, e.g., "invalid:spelling,grammar".
- switch (invalid_state) {
- case ui::AX_INVALID_STATE_FALSE:
- win_attributes_->ia2_attributes.push_back(L"invalid:false");
- break;
- case ui::AX_INVALID_STATE_TRUE:
- win_attributes_->ia2_attributes.push_back(L"invalid:true");
- break;
- case ui::AX_INVALID_STATE_SPELLING:
- win_attributes_->ia2_attributes.push_back(L"invalid:spelling");
- break;
- case ui::AX_INVALID_STATE_GRAMMAR:
- win_attributes_->ia2_attributes.push_back(L"invalid:grammar");
- break;
- case ui::AX_INVALID_STATE_OTHER:
- {
- base::string16 aria_invalid_value;
- if (GetString16Attribute(ui::AX_ATTR_ARIA_INVALID_VALUE,
- &aria_invalid_value)) {
- SanitizeStringAttributeForIA2(aria_invalid_value,
- &aria_invalid_value);
- win_attributes_->ia2_attributes.push_back(
- L"invalid:" + aria_invalid_value);
- } else {
- // Set the attribute to L"true", since we cannot be more specific.
- win_attributes_->ia2_attributes.push_back(L"invalid:true");
- }
- }
- break;
- default:
- NOTREACHED();
- }
- }
-
// Expose row or column header sort direction.
int32_t sort_direction;
if ((ia_role() == ROLE_SYSTEM_COLUMNHEADER ||
@@ -3442,8 +3476,7 @@ void BrowserAccessibilityWin::UpdateStep2ComputeHypertext() {
// the character index of each embedded object character to the id of the
// child object it points to.
for (unsigned int i = 0; i < PlatformChildCount(); ++i) {
- BrowserAccessibilityWin* child =
- PlatformGetChild(i)->ToBrowserAccessibilityWin();
+ const auto child = ToBrowserAccessibilityWin(PlatformGetChild(i));
DCHECK(child);
// Similar to Firefox, we don't expose text-only objects in IA2 hypertext.
if (child->IsTextOnlyObject()) {
@@ -3547,18 +3580,22 @@ void BrowserAccessibilityWin::UpdateStep3FireEvents(bool is_subtree_creation) {
// Changing a static text node can affect the IAccessibleText hypertext
// of the parent node, so force an update on the parent.
- BrowserAccessibilityWin* parent = GetParent()->ToBrowserAccessibilityWin();
+ BrowserAccessibilityWin* parent = ToBrowserAccessibilityWin(GetParent());
if (parent && IsTextOnlyObject() &&
name() != old_win_attributes_->name) {
- parent->UpdateStep1ComputeWinAttributes();
- parent->UpdateStep2ComputeHypertext();
- parent->UpdateStep3FireEvents(false);
+ parent->UpdatePlatformAttributes();
}
}
old_win_attributes_.reset(nullptr);
}
+void BrowserAccessibilityWin::UpdatePlatformAttributes() {
+ UpdateStep1ComputeWinAttributes();
+ UpdateStep2ComputeHypertext();
+ UpdateStep3FireEvents(false);
+}
+
void BrowserAccessibilityWin::OnSubtreeWillBeDeleted() {
manager()->ToBrowserAccessibilityManagerWin()->MaybeCallNotifyWinEvent(
EVENT_OBJECT_HIDE, this);
@@ -3581,6 +3618,182 @@ void BrowserAccessibilityWin::OnLocationChanged() {
EVENT_OBJECT_LOCATIONCHANGE, this);
}
+std::vector<base::string16> BrowserAccessibilityWin::ComputeTextAttributes()
+ const {
+ std::vector<base::string16> attributes;
+
+ // We include list markers for now, but there might be other objects that are
+ // auto generated.
+ // TODO(nektar): Compute what objects are auto-generated in Blink.
+ if (GetRole() == ui::AX_ROLE_LIST_MARKER)
+ attributes.push_back(L"auto-generated:true");
+ else
+ attributes.push_back(L"auto-generated:false");
+
+ int color;
+ base::string16 color_value(L"transparent");
+ if (GetIntAttribute(ui::AX_ATTR_BACKGROUND_COLOR, &color)) {
+ unsigned int alpha = SkColorGetA(color);
+ unsigned int red = SkColorGetR(color);
+ unsigned int green = SkColorGetG(color);
+ unsigned int blue = SkColorGetB(color);
+ if (alpha) {
+ color_value = L"rgb(" + base::UintToString16(red) + L',' +
+ base::UintToString16(green) + L',' +
+ base::UintToString16(blue) + L')';
+ }
+ }
+ SanitizeStringAttributeForIA2(color_value, &color_value);
+ attributes.push_back(L"background-color:" + color_value);
+
+ if (GetIntAttribute(ui::AX_ATTR_COLOR, &color)) {
+ unsigned int red = SkColorGetR(color);
+ unsigned int green = SkColorGetG(color);
+ unsigned int blue = SkColorGetB(color);
+ color_value = L"rgb(" + base::UintToString16(red) + L',' +
+ base::UintToString16(green) + L',' +
+ base::UintToString16(blue) + L')';
+ } else {
+ color_value = L"rgb(0,0,0)";
+ }
+ SanitizeStringAttributeForIA2(color_value, &color_value);
+ attributes.push_back(L"color:" + color_value);
+
+ base::string16 font_family(
+ GetInheritedString16Attribute(ui::AX_ATTR_FONT_FAMILY));
+ // Attribute has no default value.
+ if (!font_family.empty()) {
+ SanitizeStringAttributeForIA2(font_family, &font_family);
+ attributes.push_back(L"font-family:" + font_family);
+ }
+
+ float font_size;
+ // Attribute has no default value.
+ if (GetFloatAttribute(ui::AX_ATTR_FONT_SIZE, &font_size)) {
+ // The IA2 Spec requires the value to be in pt, not in pixels.
+ // There are 72 points per inch.
+ // We assume that there are 96 pixels per inch on a standard display.
+ // TODO(nektar): Figure out the current value of pixels per inch.
+ float points = font_size * 72.0 / 96.0;
+ attributes.push_back(L"font-size:" +
+ base::UTF8ToUTF16(base::DoubleToString(points)) +
+ L"pt");
+ }
+
+ auto text_style =
+ static_cast<ui::AXTextStyle>(GetIntAttribute(ui::AX_ATTR_TEXT_STYLE));
+ if (text_style == ui::AX_TEXT_STYLE_NONE) {
+ attributes.push_back(L"font-style:normal");
+ attributes.push_back(L"font-weight:normal");
+ } else {
+ if (text_style & ui::AX_TEXT_STYLE_BOLD)
+ attributes.push_back(L"font-weight:bold");
+
+ base::string16 font_style;
+ if (text_style & ui::AX_TEXT_STYLE_ITALIC)
+ font_style += L",italic";
+ if (text_style & ui::AX_TEXT_STYLE_UNDERLINE)
+ font_style += L",underline";
+ if (text_style & ui::AX_TEXT_STYLE_LINE_THROUGH)
+ font_style += L",line-through";
+ // TODO(nektar): Support more font style attributes in Blink.
+
+ if (font_style.empty()) {
+ font_style = L"normal";
+ } else {
+ // Remove the leading comma.
+ font_style.erase(0, 1);
+ }
+ attributes.push_back(L"font-style:" + font_style);
+ }
+
+ auto invalid_state = static_cast<ui::AXInvalidState>(
+ GetIntAttribute(ui::AX_ATTR_INVALID_STATE));
+ switch (invalid_state) {
+ case ui::AX_INVALID_STATE_NONE:
+ case ui::AX_INVALID_STATE_FALSE:
+ attributes.push_back(L"invalid:false");
+ break;
+ case ui::AX_INVALID_STATE_TRUE:
+ attributes.push_back(L"invalid:true");
+ break;
+ case ui::AX_INVALID_STATE_SPELLING:
+ case ui::AX_INVALID_STATE_GRAMMAR: {
+ base::string16 spelling_grammar_value;
+ if (invalid_state & ui::AX_INVALID_STATE_SPELLING)
+ spelling_grammar_value = L"spelling";
+ else if (invalid_state & ui::AX_INVALID_STATE_GRAMMAR)
+ spelling_grammar_value = L"grammar";
+ else
+ spelling_grammar_value = L"spelling,grammar";
+ attributes.push_back(L"invalid:" + spelling_grammar_value);
+ break;
+ }
+ case ui::AX_INVALID_STATE_OTHER: {
+ base::string16 aria_invalid_value;
+ if (GetString16Attribute(ui::AX_ATTR_ARIA_INVALID_VALUE,
+ &aria_invalid_value)) {
+ SanitizeStringAttributeForIA2(aria_invalid_value, &aria_invalid_value);
+ attributes.push_back(L"invalid:" + aria_invalid_value);
+ } else {
+ // Set the attribute to L"true", since we cannot be more specific.
+ attributes.push_back(L"invalid:true");
+ }
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+
+ base::string16 language(GetInheritedString16Attribute(ui::AX_ATTR_LANGUAGE));
+ // Default value should be L"en-US".
+ if (language.empty()) {
+ attributes.push_back(L"language:en-US");
+ } else {
+ SanitizeStringAttributeForIA2(language, &language);
+ attributes.push_back(L"language:" + language);
+ }
+
+ // TODO(nektar): Add Blink support for the following attributes.
+ // Currently set to their default values as dictated by the IA2 Spec.
+ attributes.push_back(L"text-line-through-mode:continuous");
+ attributes.push_back(L"text-line-through-style:none");
+ // Default value must be the empty string.
+ attributes.push_back(L"text-line-through-text:");
+ attributes.push_back(L"text-line-through-type:none");
+ attributes.push_back(L"text-line-through-width:auto");
+ attributes.push_back(L"text-outline:false");
+ attributes.push_back(L"text-position:baseline");
+ attributes.push_back(L"text-shadow:none");
+ attributes.push_back(L"text-underline-mode:continuous");
+ attributes.push_back(L"text-underline-style:none");
+ attributes.push_back(L"text-underline-type:none");
+ attributes.push_back(L"text-underline-width:auto");
+
+ auto text_direction = static_cast<ui::AXTextDirection>(
+ GetIntAttribute(ui::AX_ATTR_TEXT_DIRECTION));
+ switch (text_direction) {
+ case ui::AX_TEXT_DIRECTION_NONE:
+ case ui::AX_TEXT_DIRECTION_LTR:
+ attributes.push_back(L"writing-mode:lr");
+ break;
+ case ui::AX_TEXT_DIRECTION_RTL:
+ attributes.push_back(L"writing-mode:rl");
+ break;
+ case ui::AX_TEXT_DIRECTION_TTB:
+ attributes.push_back(L"writing-mode:tb");
+ break;
+ case ui::AX_TEXT_DIRECTION_BTT:
+ // Not listed in the IA2 Spec.
+ attributes.push_back(L"writing-mode:bt");
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ return attributes;
+}
+
BrowserAccessibilityWin* BrowserAccessibilityWin::NewReference() {
AddRef();
return this;
@@ -3589,17 +3802,21 @@ BrowserAccessibilityWin* BrowserAccessibilityWin::NewReference() {
BrowserAccessibilityWin* BrowserAccessibilityWin::GetTargetFromChildID(
const VARIANT& var_id) {
if (var_id.vt != VT_I4)
- return NULL;
+ return nullptr;
LONG child_id = var_id.lVal;
if (child_id == CHILDID_SELF)
return this;
if (child_id >= 1 && child_id <= static_cast<LONG>(PlatformChildCount()))
- return PlatformGetChild(child_id - 1)->ToBrowserAccessibilityWin();
+ return ToBrowserAccessibilityWin(PlatformGetChild(child_id - 1));
- return manager()->ToBrowserAccessibilityManagerWin()->
- GetFromUniqueIdWin(child_id);
+ BrowserAccessibilityWin* child = ToBrowserAccessibilityWin(
+ BrowserAccessibility::GetFromUniqueID(-child_id));
+ if (child && child->IsDescendantOf(this))
+ return child;
+
+ return nullptr;
}
HRESULT BrowserAccessibilityWin::GetStringAttributeAsBstr(
@@ -3672,7 +3889,7 @@ bool BrowserAccessibilityWin::IsHyperlink() const {
const auto parent = GetParent();
if (parent) {
hyperlink_index =
- parent->ToBrowserAccessibilityWin()->GetHyperlinkIndexFromChild(*this);
+ ToBrowserAccessibilityWin(parent)->GetHyperlinkIndexFromChild(*this);
}
if (hyperlink_index >= 0)
@@ -3680,6 +3897,23 @@ bool BrowserAccessibilityWin::IsHyperlink() const {
return false;
}
+BrowserAccessibilityWin*
+BrowserAccessibilityWin::GetHyperlinkFromHypertextOffset(int offset) const {
+ std::map<int32_t, int32_t>::iterator iterator =
+ hyperlink_offset_to_index().find(offset);
+ if (iterator == hyperlink_offset_to_index().end())
+ return nullptr;
+
+ int32_t index = iterator->second;
+ DCHECK_GE(index, 0);
+ DCHECK_LT(index, static_cast<int32_t>(hyperlinks().size()));
+ int32_t id = hyperlinks()[index];
+ BrowserAccessibilityWin* hyperlink = GetFromID(id);
+ if (!hyperlink)
+ return nullptr;
+ return hyperlink;
+}
+
int32_t BrowserAccessibilityWin::GetHyperlinkIndexFromChild(
const BrowserAccessibilityWin& child) const {
if (hyperlinks().empty())
@@ -3719,7 +3953,7 @@ int32_t BrowserAccessibilityWin::GetHypertextOffsetFromChild(
DCHECK_LT(index_in_parent, static_cast<int32_t>(InternalChildCount()));
for (uint32_t i = 0; i < static_cast<uint32_t>(index_in_parent); ++i) {
const BrowserAccessibilityWin* sibling =
- InternalGetChild(i)->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(InternalGetChild(i));
DCHECK(sibling);
if (sibling->IsTextOnlyObject())
hypertextOffset += sibling->GetText().size();
@@ -3738,11 +3972,11 @@ int32_t BrowserAccessibilityWin::GetHypertextOffsetFromChild(
int32_t BrowserAccessibilityWin::GetHypertextOffsetFromDescendant(
const BrowserAccessibilityWin& descendant) const {
- auto parent_object = descendant.GetParent()->ToBrowserAccessibilityWin();
+ auto parent_object = ToBrowserAccessibilityWin(descendant.GetParent());
auto current_object = const_cast<BrowserAccessibilityWin*>(&descendant);
while (parent_object && parent_object != this) {
current_object = parent_object;
- parent_object = current_object->GetParent()->ToBrowserAccessibilityWin();
+ parent_object = ToBrowserAccessibilityWin(current_object->GetParent());
}
if (!parent_object)
return -1;
@@ -3823,8 +4057,7 @@ int BrowserAccessibilityWin::GetHypertextOffsetFromEndpoint(
int BrowserAccessibilityWin::GetSelectionAnchor() const {
int32_t anchor_id = manager()->GetTreeData().sel_anchor_object_id;
- const auto anchor_object =
- manager()->GetFromID(anchor_id)->ToBrowserAccessibilityWin();
+ const BrowserAccessibilityWin* anchor_object = GetFromID(anchor_id);
if (!anchor_object)
return -1;
@@ -3834,8 +4067,7 @@ int BrowserAccessibilityWin::GetSelectionAnchor() const {
int BrowserAccessibilityWin::GetSelectionFocus() const {
int32_t focus_id = manager()->GetTreeData().sel_focus_object_id;
- const auto focus_object =
- manager()->GetFromID(focus_id)->ToBrowserAccessibilityWin();
+ const BrowserAccessibilityWin* focus_object = GetFromID(focus_id);
if (!focus_object)
return -1;
@@ -3847,8 +4079,7 @@ void BrowserAccessibilityWin::GetSelectionOffsets(
int* selection_start, int* selection_end) const {
DCHECK(selection_start && selection_end);
- if (HasState(ui::AX_STATE_EDITABLE) &&
- !HasState(ui::AX_STATE_RICHLY_EDITABLE) &&
+ if (IsSimpleTextControl() &&
GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START, selection_start) &&
GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END, selection_end)) {
return;
@@ -3885,22 +4116,13 @@ void BrowserAccessibilityWin::GetSelectionOffsets(
// the selection.
int* largest_offset =
(*selection_start <= *selection_end) ? selection_end : selection_start;
- auto current_object = const_cast<BrowserAccessibilityWin*>(this);
- LONG hyperlink_index;
- HRESULT hr =
- current_object->get_hyperlinkIndex(*largest_offset, &hyperlink_index);
- if (hr != S_OK)
+ BrowserAccessibilityWin* hyperlink =
+ GetHyperlinkFromHypertextOffset(*largest_offset);
+ if (!hyperlink)
return;
- DCHECK_GE(hyperlink_index, 0);
- base::win::ScopedComPtr<IAccessibleHyperlink> hyperlink;
- hr = current_object->get_hyperlink(hyperlink_index, hyperlink.Receive());
- DCHECK(SUCCEEDED(hr));
- base::win::ScopedComPtr<IAccessibleText> hyperlink_text;
- hr = hyperlink.QueryInterface(hyperlink_text.Receive());
- DCHECK(SUCCEEDED(hr));
LONG n_selections = 0;
- hr = hyperlink_text->get_nSelections(&n_selections);
+ HRESULT hr = hyperlink->get_nSelections(&n_selections);
DCHECK(SUCCEEDED(hr));
if (n_selections > 0)
++(*largest_offset);
@@ -4032,8 +4254,40 @@ LONG BrowserAccessibilityWin::FindBoundary(
text, line_breaks, boundary, start_offset, direction);
}
-BrowserAccessibilityWin* BrowserAccessibilityWin::GetFromID(int32_t id) {
- return manager()->GetFromID(id)->ToBrowserAccessibilityWin();
+LONG BrowserAccessibilityWin::FindStartOfStyle(
+ LONG start_offset,
+ ui::TextBoundaryDirection direction) const {
+ LONG text_length = static_cast<LONG>(GetText().length());
+ DCHECK_GE(start_offset, 0);
+ DCHECK_LE(start_offset, text_length);
+
+ switch (direction) {
+ case ui::BACKWARDS_DIRECTION: {
+ if (offset_to_text_attributes().empty())
+ return 0;
+
+ auto iterator = offset_to_text_attributes().upper_bound(start_offset);
+ --iterator;
+ return static_cast<LONG>(iterator->first);
+ }
+ case ui::FORWARDS_DIRECTION: {
+ const auto iterator =
+ offset_to_text_attributes().upper_bound(start_offset);
+ if (iterator == offset_to_text_attributes().end())
+ return text_length;
+ return static_cast<LONG>(iterator->first);
+ }
+ default:
+ NOTREACHED();
+ }
+
+ return start_offset;
+}
+
+BrowserAccessibilityWin* BrowserAccessibilityWin::GetFromID(int32_t id) const {
+ if (!instance_active())
+ return nullptr;
+ return ToBrowserAccessibilityWin(manager()->GetFromID(id));
}
bool BrowserAccessibilityWin::IsListBoxOptionOrMenuListOption() {
@@ -4056,6 +4310,25 @@ bool BrowserAccessibilityWin::IsListBoxOptionOrMenuListOption() {
return false;
}
+void BrowserAccessibilityWin::AddRelations(
+ ui::AXIntListAttribute src_attr,
+ const base::string16& iaccessiblerelation_type) {
+ if (!HasIntListAttribute(src_attr))
+ return;
+
+ const std::vector<int32_t>& ids = GetIntListAttribute(src_attr);
+ for (size_t i = 0; i < ids.size(); ++i) {
+ CComObject<BrowserAccessibilityRelation>* relation;
+ HRESULT hr =
+ CComObject<BrowserAccessibilityRelation>::CreateInstance(&relation);
+ DCHECK(SUCCEEDED(hr));
+ relation->AddRef();
+ relation->Initialize(this, iaccessiblerelation_type);
+ relation->AddTarget(ids[i]);
+ relations_.push_back(relation);
+ }
+}
+
void BrowserAccessibilityWin::UpdateRequiredAttributes() {
// Expose slider value.
if (ia_role() == ROLE_SYSTEM_PROGRESSBAR ||
@@ -4119,25 +4392,6 @@ void BrowserAccessibilityWin::UpdateRequiredAttributes() {
}
}
-void BrowserAccessibilityWin::AddRelations(
- ui::AXIntListAttribute src_attr,
- const base::string16& iaccessiblerelation_type) {
- if (!HasIntListAttribute(src_attr))
- return;
-
- const std::vector<int32_t>& ids = GetIntListAttribute(src_attr);
- for (size_t i = 0; i < ids.size(); ++i) {
- CComObject<BrowserAccessibilityRelation>* relation;
- HRESULT hr = CComObject<BrowserAccessibilityRelation>::CreateInstance(
- &relation);
- DCHECK(SUCCEEDED(hr));
- relation->AddRef();
- relation->Initialize(this, iaccessiblerelation_type);
- relation->AddTarget(ids[i]);
- relations_.push_back(relation);
- }
-}
-
void BrowserAccessibilityWin::InitRoleAndState() {
int32_t ia_role = 0;
int32_t ia_state = 0;
@@ -4332,8 +4586,15 @@ void BrowserAccessibilityWin::InitRoleAndState() {
ia_state |= STATE_SYSTEM_FOCUSABLE;
break;
case ui::AX_ROLE_EMBEDDED_OBJECT:
- ia_role = ROLE_SYSTEM_CLIENT;
- ia2_role = IA2_ROLE_EMBEDDED_OBJECT;
+ if (HasIntAttribute(ui::AX_ATTR_CHILD_TREE_ID)) {
+ // Windows screen readers assume that IA2_ROLE_EMBEDDED_OBJECT
+ // doesn't have any children, but it may be something like a
+ // browser plugin that has a document inside.
+ ia_role = ROLE_SYSTEM_GROUPING;
+ } else {
+ ia_role = ROLE_SYSTEM_CLIENT;
+ ia2_role = IA2_ROLE_EMBEDDED_OBJECT;
+ }
break;
case ui::AX_ROLE_FIGCAPTION:
role_name = html_tag;
@@ -4420,8 +4681,6 @@ void BrowserAccessibilityWin::InitRoleAndState() {
ia_role = ROLE_SYSTEM_LISTITEM;
if (ia_state & STATE_SYSTEM_SELECTABLE) {
ia_state |= STATE_SYSTEM_FOCUSABLE;
- if (HasState(ui::AX_STATE_FOCUSED))
- ia_state |= STATE_SYSTEM_FOCUSED;
}
break;
case ui::AX_ROLE_LIST_ITEM:
@@ -4470,8 +4729,6 @@ void BrowserAccessibilityWin::InitRoleAndState() {
ia2_state &= ~(IA2_STATE_EDITABLE);
if (ia_state & STATE_SYSTEM_SELECTABLE) {
ia_state |= STATE_SYSTEM_FOCUSABLE;
- if (HasState(ui::AX_STATE_FOCUSED))
- ia_state |= STATE_SYSTEM_FOCUSED;
}
break;
case ui::AX_ROLE_METER:
@@ -4616,6 +4873,7 @@ void BrowserAccessibilityWin::InitRoleAndState() {
ia2_state |= IA2_STATE_SINGLE_LINE;
ia2_state |= IA2_STATE_SELECTABLE_TEXT;
break;
+ case ui::AX_ROLE_ABBR:
case ui::AX_ROLE_TIME:
role_name = html_tag;
ia_role = ROLE_SYSTEM_TEXT;
@@ -4691,4 +4949,15 @@ void BrowserAccessibilityWin::InitRoleAndState() {
win_attributes_->ia2_state = ia2_state;
}
+BrowserAccessibilityWin* ToBrowserAccessibilityWin(BrowserAccessibility* obj) {
+ DCHECK(!obj || obj->IsNative());
+ return static_cast<BrowserAccessibilityWin*>(obj);
+}
+
+const BrowserAccessibilityWin*
+ToBrowserAccessibilityWin(const BrowserAccessibility* obj) {
+ DCHECK(!obj || obj->IsNative());
+ return static_cast<const BrowserAccessibilityWin*>(obj);
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win.h b/chromium/content/browser/accessibility/browser_accessibility_win.h
index adeb16b494b..0a4648379af 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win.h
+++ b/chromium/content/browser/accessibility/browser_accessibility_win.h
@@ -97,17 +97,17 @@ BrowserAccessibilityWin
CONTENT_EXPORT ~BrowserAccessibilityWin() override;
- // The Windows-specific unique ID, used as the child ID for MSAA methods
- // like NotifyWinEvent, and as the unique ID for IAccessible2 and ISimpleDOM.
- LONG unique_id_win() const { return unique_id_win_; }
-
// Called after an atomic tree update completes. See
// BrowserAccessibilityManagerWin::OnAtomicUpdateFinished for more
// details on what these do.
CONTENT_EXPORT void UpdateStep1ComputeWinAttributes();
CONTENT_EXPORT void UpdateStep2ComputeHypertext();
CONTENT_EXPORT void UpdateStep3FireEvents(bool is_subtree_creation);
- CONTENT_EXPORT void UpdateStep4DeleteOldWinAttributes();
+
+ // This is used to call UpdateStep1ComputeWinAttributes, ... above when
+ // a node needs to be updated for some other reason other than via
+ // OnAtomicUpdateFinished.
+ CONTENT_EXPORT void UpdatePlatformAttributes() override;
//
// BrowserAccessibility methods.
@@ -713,6 +713,10 @@ BrowserAccessibilityWin
REFIID iid,
void** object);
+ // Computes and caches the IA2 text style attributes for the text and other
+ // embedded child objects.
+ CONTENT_EXPORT void ComputeStylesIfNeeded();
+
CONTENT_EXPORT base::string16 GetText() const override;
// Accessors.
@@ -727,6 +731,10 @@ BrowserAccessibilityWin
base::string16 name() const { return win_attributes_->name; }
base::string16 description() const { return win_attributes_->description; }
base::string16 value() const { return win_attributes_->value; }
+ const std::map<int, std::vector<base::string16>>& offset_to_text_attributes()
+ const {
+ return win_attributes_->offset_to_text_attributes;
+ }
std::map<int32_t, int32_t>& hyperlink_offset_to_index() const {
return win_attributes_->hyperlink_offset_to_index;
}
@@ -735,6 +743,9 @@ BrowserAccessibilityWin
}
private:
+ // Returns the IA2 text attributes for this object.
+ std::vector<base::string16> ComputeTextAttributes() const;
+
// Add one to the reference count and return the same object. Always
// use this method when returning a BrowserAccessibilityWin object as
// an output parameter to a COM interface, never use it otherwise.
@@ -790,6 +801,9 @@ BrowserAccessibilityWin
// Returns true if the current object is an IA2 hyperlink.
bool IsHyperlink() const;
+ // Returns the hyperlink at the given text position, or nullptr if no
+ // hyperlink can be found.
+ BrowserAccessibilityWin* GetHyperlinkFromHypertextOffset(int offset) const;
// Functions for retrieving offsets for hyperlinks and hypertext.
// Return -1 in case of failure.
@@ -851,26 +865,31 @@ BrowserAccessibilityWin
LONG start_offset,
ui::TextBoundaryDirection direction);
- // Return a pointer to the object corresponding to the given id,
- // does not make a new reference.
- BrowserAccessibilityWin* GetFromID(int32_t id);
+ // Searches forward from the given offset until the start of the next style
+ // is found, or searches backward from the given offset until the start of the
+ // current style is found.
+ LONG FindStartOfStyle(LONG start_offset,
+ ui::TextBoundaryDirection direction) const;
+
+ // ID refers to the node ID in the current tree, not the globally unique ID.
+ // TODO(nektar): Could we use globally unique IDs everywhere?
+ // TODO(nektar): Rename this function to GetFromNodeID.
+ BrowserAccessibilityWin* GetFromID(int32_t id) const;
// Returns true if this is a list box option with a parent of type list box,
// or a menu list option with a parent of type menu list popup.
bool IsListBoxOptionOrMenuListOption();
- // Updates object attributes of IA2 with html attributes.
- void UpdateRequiredAttributes();
-
// Given an int list attribute containing the ids of related elements,
// add a new IAccessibleRelation for this object with the given type name.
void AddRelations(ui::AXIntListAttribute src_attr,
const base::string16& iaccessiblerelation_type);
- // Windows-specific unique ID (unique within the browser process),
- // used for get_accChild, NotifyWinEvent, and as the unique ID for
- // IAccessible2 and ISimpleDOM.
- LONG unique_id_win_;
+ // Updates object attributes of IA2 with html attributes.
+ void UpdateRequiredAttributes();
+
+ // Updates the IA2 text style attributes.
+ void UpdateTextAttributes();
struct WinAttributes {
WinAttributes();
@@ -896,6 +915,9 @@ BrowserAccessibilityWin
// Hypertext.
base::string16 hypertext;
+ // Maps each style span to its start offset in hypertext.
+ std::map<int, std::vector<base::string16>> offset_to_text_attributes;
+
// Maps the |hypertext_| embedded character offset to an index in
// |hyperlinks_|.
std::map<int32_t, int32_t> hyperlink_offset_to_index;
@@ -918,9 +940,6 @@ BrowserAccessibilityWin
int previous_scroll_x_;
int previous_scroll_y_;
- // The next unique id to use.
- static LONG next_unique_id_win_;
-
// Give BrowserAccessibility::Create access to our constructor.
friend class BrowserAccessibility;
friend class BrowserAccessibilityRelation;
@@ -928,6 +947,12 @@ BrowserAccessibilityWin
DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityWin);
};
+CONTENT_EXPORT BrowserAccessibilityWin*
+ToBrowserAccessibilityWin(BrowserAccessibility* obj);
+
+CONTENT_EXPORT const BrowserAccessibilityWin*
+ToBrowserAccessibilityWin(const BrowserAccessibility* obj);
+
} // namespace content
#endif // CONTENT_BROWSER_ACCESSIBILITY_BROWSER_ACCESSIBILITY_WIN_H_
diff --git a/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc b/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
index aac1961cb1d..e8c236a5195 100644
--- a/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
+++ b/chromium/content/browser/accessibility/browser_accessibility_win_unittest.cc
@@ -161,8 +161,7 @@ TEST_F(BrowserAccessibilityTest, TestNoLeaks) {
MakeAXTreeUpdate(root, button, checkbox),
NULL, new CountedBrowserAccessibilityFactory()));
ASSERT_EQ(3, CountedBrowserAccessibility::num_instances());
- IAccessible* root_accessible =
- manager->GetRoot()->ToBrowserAccessibilityWin();
+ IAccessible* root_accessible = ToBrowserAccessibilityWin(manager->GetRoot());
IDispatch* root_iaccessible = NULL;
IDispatch* child1_iaccessible = NULL;
base::win::ScopedVariant childid_self(CHILDID_SELF);
@@ -215,7 +214,7 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChange) {
// value.
base::win::ScopedVariant one(1);
base::win::ScopedComPtr<IDispatch> text_dispatch;
- HRESULT hr = manager->GetRoot()->ToBrowserAccessibilityWin()->get_accChild(
+ HRESULT hr = ToBrowserAccessibilityWin(manager->GetRoot())->get_accChild(
one, text_dispatch.Receive());
ASSERT_EQ(S_OK, hr);
@@ -249,7 +248,7 @@ TEST_F(BrowserAccessibilityTest, TestChildrenChange) {
// Query for the text IAccessible and verify that it now returns "new text"
// as its value.
- hr = manager->GetRoot()->ToBrowserAccessibilityWin()->get_accChild(
+ hr = ToBrowserAccessibilityWin(manager->GetRoot())->get_accChild(
one, text_dispatch.Receive());
ASSERT_EQ(S_OK, hr);
@@ -396,12 +395,12 @@ TEST_F(BrowserAccessibilityTest, TestTextBoundaries) {
ASSERT_EQ(7, CountedBrowserAccessibility::num_instances());
BrowserAccessibilityWin* root_obj =
- manager->GetRoot()->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(manager->GetRoot());
ASSERT_NE(nullptr, root_obj);
ASSERT_EQ(1U, root_obj->PlatformChildCount());
BrowserAccessibilityWin* text_field_obj =
- root_obj->PlatformGetChild(0)->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(root_obj->PlatformGetChild(0));
ASSERT_NE(nullptr, text_field_obj);
long text_len;
@@ -516,7 +515,7 @@ TEST_F(BrowserAccessibilityTest, TestSimpleHypertext) {
ASSERT_EQ(3, CountedBrowserAccessibility::num_instances());
BrowserAccessibilityWin* root_obj =
- manager->GetRoot()->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(manager->GetRoot());
long text_len;
EXPECT_EQ(S_OK, root_obj->get_nCharacters(&text_len));
@@ -637,7 +636,7 @@ TEST_F(BrowserAccessibilityTest, TestComplexHypertext) {
ASSERT_EQ(9, CountedBrowserAccessibility::num_instances());
BrowserAccessibilityWin* root_obj =
- manager->GetRoot()->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(manager->GetRoot());
long text_len;
EXPECT_EQ(S_OK, root_obj->get_nCharacters(&text_len));
@@ -821,8 +820,8 @@ TEST_F(BrowserAccessibilityTest, EmptyDocHasUniqueIdWin) {
1 << ui::AX_STATE_ENABLED,
root->GetState());
- LONG unique_id_win = root->ToBrowserAccessibilityWin()->unique_id_win();
- ASSERT_EQ(root, manager->GetFromUniqueIdWin(unique_id_win));
+ int32_t unique_id = ToBrowserAccessibilityWin(root)->unique_id();
+ ASSERT_EQ(root, BrowserAccessibility::GetFromUniqueID(unique_id));
}
TEST_F(BrowserAccessibilityTest, TestIA2Attributes) {
@@ -855,13 +854,13 @@ TEST_F(BrowserAccessibilityTest, TestIA2Attributes) {
ASSERT_NE(nullptr, manager->GetRoot());
BrowserAccessibilityWin* root_accessible =
- manager->GetRoot()->ToBrowserAccessibilityWin();
- ASSERT_NE(nullptr, root_accessible);
- ASSERT_EQ(2U, root_accessible->PlatformChildCount());
+ ToBrowserAccessibilityWin(manager->GetRoot());
+ ASSERT_NE(nullptr, root_accessible);
+ ASSERT_EQ(2U, root_accessible->PlatformChildCount());
- BrowserAccessibilityWin* pseudo_accessible =
- root_accessible->PlatformGetChild(0)->ToBrowserAccessibilityWin();
- ASSERT_NE(nullptr, pseudo_accessible);
+ BrowserAccessibilityWin* pseudo_accessible =
+ ToBrowserAccessibilityWin(root_accessible->PlatformGetChild(0));
+ ASSERT_NE(nullptr, pseudo_accessible);
base::win::ScopedBstr attributes;
HRESULT hr = pseudo_accessible->get_attributes(attributes.Receive());
@@ -871,7 +870,7 @@ TEST_F(BrowserAccessibilityTest, TestIA2Attributes) {
EXPECT_EQ(L"display:none;tag:<pseudo\\:before>;", attributes_str);
BrowserAccessibilityWin* checkbox_accessible =
- root_accessible->PlatformGetChild(1)->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(root_accessible->PlatformGetChild(1));
ASSERT_NE(nullptr, checkbox_accessible);
attributes.Reset();
@@ -899,7 +898,7 @@ TEST_F(BrowserAccessibilityTest, TestValueAttributeInTextControls) {
combo_box.role = ui::AX_ROLE_COMBO_BOX;
combo_box_text.role = ui::AX_ROLE_STATIC_TEXT;
combo_box.state = (1 << ui::AX_STATE_EDITABLE) |
- (1 << ui::AX_STATE_FOCUSABLE) | (1 << ui::AX_STATE_FOCUSED);
+ (1 << ui::AX_STATE_FOCUSABLE);
combo_box_text.state = 1 << ui::AX_STATE_EDITABLE;
combo_box.child_ids.push_back(combo_box_text.id);
@@ -914,8 +913,7 @@ TEST_F(BrowserAccessibilityTest, TestValueAttributeInTextControls) {
search_box_text.role = ui::AX_ROLE_STATIC_TEXT;
new_line.role = ui::AX_ROLE_LINE_BREAK;
search_box.state = (1 << ui::AX_STATE_EDITABLE) |
- (1 << ui::AX_STATE_FOCUSABLE) |
- (1 << ui::AX_STATE_FOCUSED);
+ (1 << ui::AX_STATE_FOCUSABLE);
search_box_text.state = new_line.state = 1 << ui::AX_STATE_EDITABLE;
search_box.child_ids.push_back(search_box_text.id);
search_box.child_ids.push_back(new_line.id);
@@ -943,7 +941,7 @@ TEST_F(BrowserAccessibilityTest, TestValueAttributeInTextControls) {
slider_text.SetName("Slider text");
slider.role = ui::AX_ROLE_SLIDER;
slider_text.role = ui::AX_ROLE_STATIC_TEXT;
- slider_text.state = 1 << ui::AX_STATE_READ_ONLY;
+ slider.state = slider_text.state = 1 << ui::AX_STATE_READ_ONLY;
slider.child_ids.push_back(slider_text.id);
root.child_ids.push_back(2); // Combo box.
@@ -963,27 +961,27 @@ TEST_F(BrowserAccessibilityTest, TestValueAttributeInTextControls) {
ASSERT_NE(nullptr, manager->GetRoot());
BrowserAccessibilityWin* root_accessible =
- manager->GetRoot()->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(manager->GetRoot());
ASSERT_NE(nullptr, root_accessible);
ASSERT_EQ(5U, root_accessible->PlatformChildCount());
BrowserAccessibilityWin* combo_box_accessible =
- root_accessible->PlatformGetChild(0)->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(root_accessible->PlatformGetChild(0));
ASSERT_NE(nullptr, combo_box_accessible);
- manager->SetFocus(combo_box_accessible, false /* notify */);
+ manager->SetFocusLocallyForTesting(combo_box_accessible);
ASSERT_EQ(combo_box_accessible,
- manager->GetFocus(root_accessible)->ToBrowserAccessibilityWin());
+ ToBrowserAccessibilityWin(manager->GetFocus()));
BrowserAccessibilityWin* search_box_accessible =
- root_accessible->PlatformGetChild(1)->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(root_accessible->PlatformGetChild(1));
ASSERT_NE(nullptr, search_box_accessible);
BrowserAccessibilityWin* text_field_accessible =
- root_accessible->PlatformGetChild(2)->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(root_accessible->PlatformGetChild(2));
ASSERT_NE(nullptr, text_field_accessible);
BrowserAccessibilityWin* link_accessible =
- root_accessible->PlatformGetChild(3)->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(root_accessible->PlatformGetChild(3));
ASSERT_NE(nullptr, link_accessible);
BrowserAccessibilityWin* slider_accessible =
- root_accessible->PlatformGetChild(4)->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(root_accessible->PlatformGetChild(4));
ASSERT_NE(nullptr, slider_accessible);
base::win::ScopedVariant childid_self(CHILDID_SELF);
@@ -1125,15 +1123,15 @@ TEST_F(BrowserAccessibilityTest, TestWordBoundariesInTextControls) {
ASSERT_NE(nullptr, manager->GetRoot());
BrowserAccessibilityWin* root_accessible =
- manager->GetRoot()->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(manager->GetRoot());
ASSERT_NE(nullptr, root_accessible);
ASSERT_EQ(2U, root_accessible->PlatformChildCount());
BrowserAccessibilityWin* textarea_accessible =
- root_accessible->PlatformGetChild(0)->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(root_accessible->PlatformGetChild(0));
ASSERT_NE(nullptr, textarea_accessible);
BrowserAccessibilityWin* text_field_accessible =
- root_accessible->PlatformGetChild(1)->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(root_accessible->PlatformGetChild(1));
ASSERT_NE(nullptr, text_field_accessible);
base::win::ScopedComPtr<IAccessibleText> textarea_object;
@@ -1196,7 +1194,7 @@ TEST_F(BrowserAccessibilityTest, TestCaretAndSelectionInSimpleFields) {
combo_box.id = 2;
combo_box.role = ui::AX_ROLE_COMBO_BOX;
combo_box.state = (1 << ui::AX_STATE_EDITABLE) |
- (1 << ui::AX_STATE_FOCUSABLE) | (1 << ui::AX_STATE_FOCUSED);
+ (1 << ui::AX_STATE_FOCUSABLE);
combo_box.SetValue("Test1");
// Place the caret between 't' and 'e'.
combo_box.AddIntAttribute(ui::AX_ATTR_TEXT_SEL_START, 1);
@@ -1224,18 +1222,18 @@ TEST_F(BrowserAccessibilityTest, TestCaretAndSelectionInSimpleFields) {
ASSERT_NE(nullptr, manager->GetRoot());
BrowserAccessibilityWin* root_accessible =
- manager->GetRoot()->ToBrowserAccessibilityWin();
- ASSERT_NE(nullptr, root_accessible);
- ASSERT_EQ(2U, root_accessible->PlatformChildCount());
+ ToBrowserAccessibilityWin(manager->GetRoot());
+ ASSERT_NE(nullptr, root_accessible);
+ ASSERT_EQ(2U, root_accessible->PlatformChildCount());
BrowserAccessibilityWin* combo_box_accessible =
- root_accessible->PlatformGetChild(0)->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(root_accessible->PlatformGetChild(0));
ASSERT_NE(nullptr, combo_box_accessible);
- manager->SetFocus(combo_box_accessible, false /* notify */);
+ manager->SetFocusLocallyForTesting(combo_box_accessible);
ASSERT_EQ(combo_box_accessible,
- manager->GetFocus(root_accessible)->ToBrowserAccessibilityWin());
+ ToBrowserAccessibilityWin(manager->GetFocus()));
BrowserAccessibilityWin* text_field_accessible =
- root_accessible->PlatformGetChild(1)->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(root_accessible->PlatformGetChild(1));
ASSERT_NE(nullptr, text_field_accessible);
// -2 is never a valid offset.
@@ -1254,11 +1252,9 @@ TEST_F(BrowserAccessibilityTest, TestCaretAndSelectionInSimpleFields) {
EXPECT_EQ(2L, caret_offset);
// Move the focus to the text field.
- combo_box.state &= ~(1 << ui::AX_STATE_FOCUSED);
- text_field.state |= 1 << ui::AX_STATE_FOCUSED;
- manager->SetFocus(text_field_accessible, false /* notify */);
+ manager->SetFocusLocallyForTesting(text_field_accessible);
ASSERT_EQ(text_field_accessible,
- manager->GetFocus(root_accessible)->ToBrowserAccessibilityWin());
+ ToBrowserAccessibilityWin(manager->GetFocus()));
// The caret should not have moved.
hr = text_field_accessible->get_caretOffset(&caret_offset);
@@ -1346,12 +1342,12 @@ TEST_F(BrowserAccessibilityTest, TestCaretInContentEditables) {
ASSERT_NE(nullptr, manager->GetRoot());
BrowserAccessibilityWin* root_accessible =
- manager->GetRoot()->ToBrowserAccessibilityWin();
- ASSERT_NE(nullptr, root_accessible);
- ASSERT_EQ(1U, root_accessible->PlatformChildCount());
+ ToBrowserAccessibilityWin(manager->GetRoot());
+ ASSERT_NE(nullptr, root_accessible);
+ ASSERT_EQ(1U, root_accessible->PlatformChildCount());
BrowserAccessibilityWin* div_editable_accessible =
- root_accessible->PlatformGetChild(0)->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(root_accessible->PlatformGetChild(0));
ASSERT_NE(nullptr, div_editable_accessible);
ASSERT_EQ(2U, div_editable_accessible->PlatformChildCount());
@@ -1370,21 +1366,20 @@ TEST_F(BrowserAccessibilityTest, TestCaretInContentEditables) {
EXPECT_EQ(6L, caret_offset);
// Move the focus to the content editable.
- div_editable.state |= 1 << ui::AX_STATE_FOCUSED;
- manager->SetFocus(div_editable_accessible, false /* notify */);
+ manager->SetFocusLocallyForTesting(div_editable_accessible);
ASSERT_EQ(div_editable_accessible,
- manager->GetFocus(root_accessible)->ToBrowserAccessibilityWin());
+ ToBrowserAccessibilityWin(manager->GetFocus()));
BrowserAccessibilityWin* text_accessible =
- div_editable_accessible->PlatformGetChild(0)->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(div_editable_accessible->PlatformGetChild(0));
ASSERT_NE(nullptr, text_accessible);
BrowserAccessibilityWin* link_accessible =
- div_editable_accessible->PlatformGetChild(1)->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(div_editable_accessible->PlatformGetChild(1));
ASSERT_NE(nullptr, link_accessible);
ASSERT_EQ(1U, link_accessible->PlatformChildCount());
BrowserAccessibilityWin* link_text_accessible =
- link_accessible->PlatformGetChild(0)->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(link_accessible->PlatformGetChild(0));
ASSERT_NE(nullptr, link_text_accessible);
// The caret should not have moved.
@@ -1465,12 +1460,12 @@ TEST_F(BrowserAccessibilityTest, TestSelectionInContentEditables) {
ASSERT_NE(nullptr, manager->GetRoot());
BrowserAccessibilityWin* root_accessible =
- manager->GetRoot()->ToBrowserAccessibilityWin();
- ASSERT_NE(nullptr, root_accessible);
- ASSERT_EQ(1U, root_accessible->PlatformChildCount());
+ ToBrowserAccessibilityWin(manager->GetRoot());
+ ASSERT_NE(nullptr, root_accessible);
+ ASSERT_EQ(1U, root_accessible->PlatformChildCount());
BrowserAccessibilityWin* div_editable_accessible =
- root_accessible->PlatformGetChild(0)->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(root_accessible->PlatformGetChild(0));
ASSERT_NE(nullptr, div_editable_accessible);
ASSERT_EQ(2U, div_editable_accessible->PlatformChildCount());
@@ -1481,15 +1476,15 @@ TEST_F(BrowserAccessibilityTest, TestSelectionInContentEditables) {
LONG selection_end = -2;
BrowserAccessibilityWin* text_accessible =
- div_editable_accessible->PlatformGetChild(0)->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(div_editable_accessible->PlatformGetChild(0));
ASSERT_NE(nullptr, text_accessible);
BrowserAccessibilityWin* link_accessible =
- div_editable_accessible->PlatformGetChild(1)->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(div_editable_accessible->PlatformGetChild(1));
ASSERT_NE(nullptr, link_accessible);
ASSERT_EQ(1U, link_accessible->PlatformChildCount());
BrowserAccessibilityWin* link_text_accessible =
- link_accessible->PlatformGetChild(0)->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(link_accessible->PlatformGetChild(0));
ASSERT_NE(nullptr, link_text_accessible);
// get_nSelections should work on all objects.
@@ -1537,10 +1532,9 @@ TEST_F(BrowserAccessibilityTest, TestSelectionInContentEditables) {
EXPECT_EQ(7L, caret_offset);
// Move the focus to the content editable.
- div_editable.state |= 1 << ui::AX_STATE_FOCUSED;
- manager->SetFocus(div_editable_accessible, false /* notify */);
+ manager->SetFocusLocallyForTesting(div_editable_accessible);
ASSERT_EQ(div_editable_accessible,
- manager->GetFocus(root_accessible)->ToBrowserAccessibilityWin());
+ ToBrowserAccessibilityWin(manager->GetFocus()));
// The caret should not have moved.
hr = div_editable_accessible->get_caretOffset(&caret_offset);
@@ -1602,20 +1596,20 @@ TEST_F(BrowserAccessibilityTest, TestIAccessibleHyperlink) {
ASSERT_NE(nullptr, manager->GetRoot());
BrowserAccessibilityWin* root_accessible =
- manager->GetRoot()->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(manager->GetRoot());
ASSERT_NE(nullptr, root_accessible);
ASSERT_EQ(1U, root_accessible->PlatformChildCount());
BrowserAccessibilityWin* div_accessible =
- root_accessible->PlatformGetChild(0)->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(root_accessible->PlatformGetChild(0));
ASSERT_NE(nullptr, div_accessible);
ASSERT_EQ(2U, div_accessible->PlatformChildCount());
BrowserAccessibilityWin* text_accessible =
- div_accessible->PlatformGetChild(0)->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(div_accessible->PlatformGetChild(0));
ASSERT_NE(nullptr, text_accessible);
BrowserAccessibilityWin* link_accessible =
- div_accessible->PlatformGetChild(1)->ToBrowserAccessibilityWin();
+ ToBrowserAccessibilityWin(div_accessible->PlatformGetChild(1));
ASSERT_NE(nullptr, link_accessible);
// -1 is never a valid value.
@@ -1720,25 +1714,29 @@ TEST_F(BrowserAccessibilityTest, TestIAccessibleHyperlink) {
EXPECT_EQ(7, end_index);
}
-TEST_F(BrowserAccessibilityTest, TestPlatformDeepestFirstLastChild) {
+TEST_F(BrowserAccessibilityTest, TestDeepestFirstLastChild) {
ui::AXNodeData root;
root.id = 1;
root.role = ui::AX_ROLE_ROOT_WEB_AREA;
ui::AXNodeData child1;
child1.id = 2;
+ child1.role = ui::AX_ROLE_STATIC_TEXT;
root.child_ids.push_back(2);
ui::AXNodeData child2;
child2.id = 3;
+ child2.role = ui::AX_ROLE_STATIC_TEXT;
root.child_ids.push_back(3);
ui::AXNodeData child2_child1;
child2_child1.id = 4;
+ child2_child1.role = ui::AX_ROLE_INLINE_TEXT_BOX;
child2.child_ids.push_back(4);
ui::AXNodeData child2_child2;
child2_child2.id = 5;
+ child2_child2.role = ui::AX_ROLE_INLINE_TEXT_BOX;
child2.child_ids.push_back(5);
scoped_ptr<BrowserAccessibilityManager> manager(
@@ -1746,32 +1744,168 @@ TEST_F(BrowserAccessibilityTest, TestPlatformDeepestFirstLastChild) {
MakeAXTreeUpdate(root, child1, child2, child2_child1, child2_child2),
nullptr, new CountedBrowserAccessibilityFactory()));
- auto root_accessible = manager->GetRoot();
+ BrowserAccessibility* root_accessible = manager->GetRoot();
ASSERT_NE(nullptr, root_accessible);
ASSERT_EQ(2U, root_accessible->PlatformChildCount());
- auto child1_accessible = root_accessible->PlatformGetChild(0);
+ BrowserAccessibility* child1_accessible =
+ root_accessible->PlatformGetChild(0);
ASSERT_NE(nullptr, child1_accessible);
- auto child2_accessible = root_accessible->PlatformGetChild(1);
+ BrowserAccessibility* child2_accessible =
+ root_accessible->PlatformGetChild(1);
ASSERT_NE(nullptr, child2_accessible);
- ASSERT_EQ(2U, child2_accessible->PlatformChildCount());
- auto child2_child1_accessible = child2_accessible->PlatformGetChild(0);
+ ASSERT_EQ(0U, child2_accessible->PlatformChildCount());
+ ASSERT_EQ(2U, child2_accessible->InternalChildCount());
+ BrowserAccessibility* child2_child1_accessible =
+ child2_accessible->InternalGetChild(0);
ASSERT_NE(nullptr, child2_child1_accessible);
- auto child2_child2_accessible = child2_accessible->PlatformGetChild(1);
+ BrowserAccessibility* child2_child2_accessible =
+ child2_accessible->InternalGetChild(1);
ASSERT_NE(nullptr, child2_child2_accessible);
EXPECT_EQ(child1_accessible, root_accessible->PlatformDeepestFirstChild());
+ EXPECT_EQ(child1_accessible, root_accessible->InternalDeepestFirstChild());
+
+ EXPECT_EQ(child2_accessible, root_accessible->PlatformDeepestLastChild());
EXPECT_EQ(child2_child2_accessible,
- root_accessible->PlatformDeepestLastChild());
+ root_accessible->InternalDeepestLastChild());
+
EXPECT_EQ(nullptr, child1_accessible->PlatformDeepestFirstChild());
+ EXPECT_EQ(nullptr, child1_accessible->InternalDeepestFirstChild());
+
EXPECT_EQ(nullptr, child1_accessible->PlatformDeepestLastChild());
+ EXPECT_EQ(nullptr, child1_accessible->InternalDeepestLastChild());
+
+ EXPECT_EQ(nullptr, child2_accessible->PlatformDeepestFirstChild());
EXPECT_EQ(child2_child1_accessible,
- child2_accessible->PlatformDeepestFirstChild());
+ child2_accessible->InternalDeepestFirstChild());
+
+ EXPECT_EQ(nullptr, child2_accessible->PlatformDeepestLastChild());
EXPECT_EQ(child2_child2_accessible,
- child2_accessible->PlatformDeepestLastChild());
+ child2_accessible->InternalDeepestLastChild());
+
EXPECT_EQ(nullptr, child2_child1_accessible->PlatformDeepestFirstChild());
+ EXPECT_EQ(nullptr, child2_child1_accessible->InternalDeepestFirstChild());
EXPECT_EQ(nullptr, child2_child1_accessible->PlatformDeepestLastChild());
+ EXPECT_EQ(nullptr, child2_child1_accessible->InternalDeepestLastChild());
EXPECT_EQ(nullptr, child2_child2_accessible->PlatformDeepestFirstChild());
+ EXPECT_EQ(nullptr, child2_child2_accessible->InternalDeepestFirstChild());
EXPECT_EQ(nullptr, child2_child2_accessible->PlatformDeepestLastChild());
+ EXPECT_EQ(nullptr, child2_child2_accessible->InternalDeepestLastChild());
+}
+
+TEST_F(BrowserAccessibilityTest, TestInheritedStringAttributes) {
+ ui::AXNodeData root;
+ root.id = 1;
+ root.role = ui::AX_ROLE_ROOT_WEB_AREA;
+ root.AddStringAttribute(ui::AX_ATTR_LANGUAGE, "en-US");
+ root.AddStringAttribute(ui::AX_ATTR_FONT_FAMILY, "Helvetica");
+
+ ui::AXNodeData child1;
+ child1.id = 2;
+ child1.role = ui::AX_ROLE_STATIC_TEXT;
+ root.child_ids.push_back(2);
+
+ ui::AXNodeData child2;
+ child2.id = 3;
+ child2.role = ui::AX_ROLE_STATIC_TEXT;
+ child2.AddStringAttribute(ui::AX_ATTR_LANGUAGE, "fr");
+ child2.AddStringAttribute(ui::AX_ATTR_FONT_FAMILY, "Arial");
+ root.child_ids.push_back(3);
+
+ ui::AXNodeData child2_child1;
+ child2_child1.id = 4;
+ child2_child1.role = ui::AX_ROLE_INLINE_TEXT_BOX;
+ child2.child_ids.push_back(4);
+
+ ui::AXNodeData child2_child2;
+ child2_child2.id = 5;
+ child2_child2.role = ui::AX_ROLE_INLINE_TEXT_BOX;
+ child2.child_ids.push_back(5);
+
+ scoped_ptr<BrowserAccessibilityManager> manager(
+ BrowserAccessibilityManager::Create(
+ MakeAXTreeUpdate(root, child1, child2, child2_child1, child2_child2),
+ nullptr, new CountedBrowserAccessibilityFactory()));
+
+ BrowserAccessibility* root_accessible = manager->GetRoot();
+ ASSERT_NE(nullptr, root_accessible);
+ BrowserAccessibility* child1_accessible =
+ root_accessible->PlatformGetChild(0);
+ ASSERT_NE(nullptr, child1_accessible);
+ BrowserAccessibility* child2_accessible =
+ root_accessible->PlatformGetChild(1);
+ ASSERT_NE(nullptr, child2_accessible);
+ BrowserAccessibility* child2_child1_accessible =
+ child2_accessible->InternalGetChild(0);
+ ASSERT_NE(nullptr, child2_child1_accessible);
+ BrowserAccessibility* child2_child2_accessible =
+ child2_accessible->InternalGetChild(1);
+ ASSERT_NE(nullptr, child2_child2_accessible);
+
+ // Test GetInheritedString16Attribute(attribute).
+ EXPECT_EQ(
+ base::UTF8ToUTF16("en-US"),
+ root_accessible->GetInheritedString16Attribute(ui::AX_ATTR_LANGUAGE));
+ EXPECT_EQ(
+ base::UTF8ToUTF16("en-US"),
+ child1_accessible->GetInheritedString16Attribute(ui::AX_ATTR_LANGUAGE));
+ EXPECT_EQ(
+ base::UTF8ToUTF16("fr"),
+ child2_accessible->GetInheritedString16Attribute(ui::AX_ATTR_LANGUAGE));
+ EXPECT_EQ(base::UTF8ToUTF16("fr"),
+ child2_child1_accessible->GetInheritedString16Attribute(
+ ui::AX_ATTR_LANGUAGE));
+ EXPECT_EQ(base::UTF8ToUTF16("fr"),
+ child2_child2_accessible->GetInheritedString16Attribute(
+ ui::AX_ATTR_LANGUAGE));
+
+ // Test GetInheritedString16Attribute(attribute, out_value).
+ base::string16 value16;
+ EXPECT_TRUE(root_accessible->GetInheritedString16Attribute(
+ ui::AX_ATTR_LANGUAGE, &value16));
+ EXPECT_EQ(base::UTF8ToUTF16("en-US"), value16);
+ EXPECT_TRUE(child1_accessible->GetInheritedString16Attribute(
+ ui::AX_ATTR_LANGUAGE, &value16));
+ EXPECT_EQ(base::UTF8ToUTF16("en-US"), value16);
+ EXPECT_TRUE(child2_accessible->GetInheritedString16Attribute(
+ ui::AX_ATTR_LANGUAGE, &value16));
+ EXPECT_EQ(base::UTF8ToUTF16("fr"), value16);
+ EXPECT_TRUE(child2_child1_accessible->GetInheritedString16Attribute(
+ ui::AX_ATTR_LANGUAGE, &value16));
+ EXPECT_EQ(base::UTF8ToUTF16("fr"), value16);
+ EXPECT_TRUE(child2_child2_accessible->GetInheritedString16Attribute(
+ ui::AX_ATTR_LANGUAGE, &value16));
+ EXPECT_EQ(base::UTF8ToUTF16("fr"), value16);
+
+ // Test GetInheritedStringAttribute(attribute).
+ EXPECT_EQ("Helvetica", root_accessible->GetInheritedStringAttribute(
+ ui::AX_ATTR_FONT_FAMILY));
+ EXPECT_EQ("Helvetica", child1_accessible->GetInheritedStringAttribute(
+ ui::AX_ATTR_FONT_FAMILY));
+ EXPECT_EQ("Arial", child2_accessible->GetInheritedStringAttribute(
+ ui::AX_ATTR_FONT_FAMILY));
+ EXPECT_EQ("Arial", child2_child1_accessible->GetInheritedStringAttribute(
+ ui::AX_ATTR_FONT_FAMILY));
+ EXPECT_EQ("Arial", child2_child2_accessible->GetInheritedStringAttribute(
+ ui::AX_ATTR_FONT_FAMILY));
+
+ // Test GetInheritedStringAttribute(attribute, out_value).
+ std::string value;
+ EXPECT_TRUE(root_accessible->GetInheritedStringAttribute(
+ ui::AX_ATTR_FONT_FAMILY, &value));
+ EXPECT_EQ("Helvetica", value);
+ EXPECT_TRUE(child1_accessible->GetInheritedStringAttribute(
+ ui::AX_ATTR_FONT_FAMILY, &value));
+ EXPECT_EQ("Helvetica", value);
+ EXPECT_TRUE(child2_accessible->GetInheritedStringAttribute(
+ ui::AX_ATTR_FONT_FAMILY, &value));
+ EXPECT_EQ("Arial", value);
+ EXPECT_TRUE(child2_child1_accessible->GetInheritedStringAttribute(
+ ui::AX_ATTR_FONT_FAMILY, &value));
+ EXPECT_EQ("Arial", value);
+ EXPECT_TRUE(child2_child2_accessible->GetInheritedStringAttribute(
+ ui::AX_ATTR_FONT_FAMILY, &value));
+ EXPECT_EQ("Arial", value);
}
TEST_F(BrowserAccessibilityTest, TestSanitizeStringAttributeForIA2) {
@@ -1797,9 +1931,9 @@ TEST_F(BrowserAccessibilityTest, UniqueIdWinInvalidAfterDeletingTree) {
new CountedBrowserAccessibilityFactory()));
BrowserAccessibility* root = manager->GetRoot();
- LONG root_unique_id = root->ToBrowserAccessibilityWin()->unique_id_win();
+ int32_t root_unique_id = root->unique_id();
BrowserAccessibility* child = root->PlatformGetChild(0);
- LONG child_unique_id = child->ToBrowserAccessibilityWin()->unique_id_win();
+ int32_t child_unique_id = child->unique_id();
// Now destroy that original tree and create a new tree.
manager.reset(
@@ -1808,39 +1942,67 @@ TEST_F(BrowserAccessibilityTest, UniqueIdWinInvalidAfterDeletingTree) {
nullptr,
new CountedBrowserAccessibilityFactory()));
root = manager->GetRoot();
- LONG root_unique_id_2 = root->ToBrowserAccessibilityWin()->unique_id_win();
+ int32_t root_unique_id_2 = root->unique_id();
child = root->PlatformGetChild(0);
- LONG child_unique_id_2 = child->ToBrowserAccessibilityWin()->unique_id_win();
+ int32_t child_unique_id_2 = child->unique_id();
// The nodes in the new tree should not have the same ids.
EXPECT_NE(root_unique_id, root_unique_id_2);
EXPECT_NE(child_unique_id, child_unique_id_2);
// Trying to access the unique IDs of the old, deleted objects should fail.
- base::win::ScopedVariant old_root_variant(root_unique_id);
+ base::win::ScopedVariant old_root_variant(-root_unique_id);
base::win::ScopedComPtr<IDispatch> old_root_dispatch;
- HRESULT hr = root->ToBrowserAccessibilityWin()->get_accChild(
+ HRESULT hr = ToBrowserAccessibilityWin(root)->get_accChild(
old_root_variant, old_root_dispatch.Receive());
EXPECT_EQ(E_INVALIDARG, hr);
- base::win::ScopedVariant old_child_variant(child_unique_id);
+ base::win::ScopedVariant old_child_variant(-child_unique_id);
base::win::ScopedComPtr<IDispatch> old_child_dispatch;
- hr = root->ToBrowserAccessibilityWin()->get_accChild(
+ hr = ToBrowserAccessibilityWin(root)->get_accChild(
old_child_variant, old_child_dispatch.Receive());
EXPECT_EQ(E_INVALIDARG, hr);
// Trying to access the unique IDs of the new objects should succeed.
- base::win::ScopedVariant new_root_variant(root_unique_id_2);
+ base::win::ScopedVariant new_root_variant(-root_unique_id_2);
base::win::ScopedComPtr<IDispatch> new_root_dispatch;
- hr = root->ToBrowserAccessibilityWin()->get_accChild(
+ hr = ToBrowserAccessibilityWin(root)->get_accChild(
new_root_variant, new_root_dispatch.Receive());
EXPECT_EQ(S_OK, hr);
- base::win::ScopedVariant new_child_variant(child_unique_id_2);
+ base::win::ScopedVariant new_child_variant(-child_unique_id_2);
base::win::ScopedComPtr<IDispatch> new_child_dispatch;
- hr = root->ToBrowserAccessibilityWin()->get_accChild(
+ hr = ToBrowserAccessibilityWin(root)->get_accChild(
new_child_variant, new_child_dispatch.Receive());
EXPECT_EQ(S_OK, hr);
}
+TEST_F(BrowserAccessibilityTest, AccChildOnlyReturnsDescendants) {
+ ui::AXNodeData root_node;
+ root_node.id = 1;
+ root_node.role = ui::AX_ROLE_ROOT_WEB_AREA;
+
+ ui::AXNodeData child_node;
+ child_node.id = 2;
+ root_node.child_ids.push_back(2);
+
+ scoped_ptr<BrowserAccessibilityManagerWin> manager(
+ new BrowserAccessibilityManagerWin(
+ MakeAXTreeUpdate(root_node, child_node),
+ nullptr,
+ new CountedBrowserAccessibilityFactory()));
+
+ BrowserAccessibility* root = manager->GetRoot();
+ BrowserAccessibility* child = root->PlatformGetChild(0);
+
+ base::win::ScopedVariant root_unique_id_variant(-root->unique_id());
+ base::win::ScopedComPtr<IDispatch> result;
+ EXPECT_EQ(E_INVALIDARG, ToBrowserAccessibilityWin(child)->get_accChild(
+ root_unique_id_variant, result.Receive()));
+
+ base::win::ScopedVariant child_unique_id_variant(-child->unique_id());
+ EXPECT_EQ(S_OK, ToBrowserAccessibilityWin(root)->get_accChild(
+ child_unique_id_variant, result.Receive()));
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc b/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc
index b5dd3296ef3..986fdc063bd 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.cc
@@ -15,21 +15,28 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "content/browser/accessibility/accessibility_tree_formatter.h"
#include "content/browser/accessibility/accessibility_tree_formatter_blink.h"
#include "content/browser/accessibility/browser_accessibility.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
+#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
+#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/accessibility_browser_test_utils.h"
+#include "content/test/content_browser_test_utils_internal.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
namespace content {
@@ -40,6 +47,29 @@ const char kMarkSkipFile[] = "#<skip";
const char kMarkEndOfFile[] = "<-- End-of-file -->";
const char kSignalDiff[] = "*";
+// Searches recursively and returns true if an accessibility node is found
+// that represents a fully loaded web document with the given url.
+bool AccessibilityTreeContainsLoadedDocWithUrl(BrowserAccessibility* node,
+ const std::string& url) {
+ if ((node->GetRole() == ui::AX_ROLE_WEB_AREA ||
+ node->GetRole() == ui::AX_ROLE_ROOT_WEB_AREA) &&
+ node->GetStringAttribute(ui::AX_ATTR_URL) == url) {
+ // If possible, ensure the doc has finished loading. That's currently
+ // not possible with same-process iframes until https://crbug.com/532249
+ // is fixed.
+ return (node->manager()->GetTreeData().url != url ||
+ node->manager()->GetTreeData().loaded);
+ }
+
+ for (unsigned i = 0; i < node->PlatformChildCount(); i++) {
+ if (AccessibilityTreeContainsLoadedDocWithUrl(
+ node->PlatformGetChild(i), url)) {
+ return true;
+ }
+ }
+ return false;
+}
+
} // namespace
typedef AccessibilityTreeFormatter::Filter Filter;
@@ -50,6 +80,17 @@ DumpAccessibilityTestBase::DumpAccessibilityTestBase() {
DumpAccessibilityTestBase::~DumpAccessibilityTestBase() {
}
+void DumpAccessibilityTestBase::SetUpCommandLine(
+ base::CommandLine* command_line) {
+ IsolateAllSitesForTesting(command_line);
+}
+
+void DumpAccessibilityTestBase::SetUpOnMainThread() {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(embedded_test_server()->Start());
+ SetupCrossSiteRedirector(embedded_test_server());
+}
+
base::string16
DumpAccessibilityTestBase::DumpUnfilteredAccessibilityTreeAsString() {
scoped_ptr<AccessibilityTreeFormatter> formatter(
@@ -95,7 +136,7 @@ std::vector<int> DumpAccessibilityTestBase::DiffLines(
void DumpAccessibilityTestBase::ParseHtmlForExtraDirectives(
const std::string& test_html,
std::vector<Filter>* filters,
- std::string* wait_for) {
+ std::vector<std::string>* wait_for) {
for (const std::string& line :
base::SplitString(test_html, "\n", base::TRIM_WHITESPACE,
base::SPLIT_WANT_ALL)) {
@@ -120,7 +161,7 @@ void DumpAccessibilityTestBase::ParseHtmlForExtraDirectives(
Filter::DENY));
} else if (base::StartsWith(line, wait_str,
base::CompareCase::SENSITIVE)) {
- *wait_for = line.substr(wait_str.size());
+ wait_for->push_back(line.substr(wait_str.size()));
}
}
}
@@ -193,42 +234,109 @@ void DumpAccessibilityTestBase::RunTestForPlatform(
}
// Parse filters and other directives in the test file.
- std::string wait_for;
+ std::vector<std::string> wait_for;
AddDefaultFilters(&filters_);
ParseHtmlForExtraDirectives(html_contents, &filters_, &wait_for);
- // Load the page.
- base::string16 html_contents16;
- html_contents16 = base::UTF8ToUTF16(html_contents);
- GURL url = GetTestUrl(file_dir, file_path.BaseName().MaybeAsASCII().c_str());
-
- // If there's a @WAIT-FOR directive, set up an accessibility notification
- // waiter that returns on any event; we'll stop when we get the text we're
- // waiting for, or time out. Otherwise just wait specifically for
- // the "load complete" event.
- scoped_ptr<AccessibilityNotificationWaiter> waiter;
- if (!wait_for.empty()) {
- waiter.reset(new AccessibilityNotificationWaiter(
- shell(), AccessibilityModeComplete, ui::AX_EVENT_NONE));
- } else {
- waiter.reset(new AccessibilityNotificationWaiter(
- shell(), AccessibilityModeComplete, ui::AX_EVENT_LOAD_COMPLETE));
+ // Load the test html and wait for the "load complete" AX event.
+ GURL url(embedded_test_server()->GetURL(
+ "/" + std::string(file_dir) + "/" + file_path.BaseName().MaybeAsASCII()));
+ AccessibilityNotificationWaiter accessibility_waiter(
+ shell(),
+ AccessibilityModeComplete,
+ ui::AX_EVENT_LOAD_COMPLETE);
+ NavigateToURL(shell(), url);
+ accessibility_waiter.WaitForNotification();
+
+ // Get the url of every frame in the frame tree.
+ WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
+ shell()->web_contents());
+ FrameTree* frame_tree = web_contents->GetFrameTree();
+ std::vector<std::string> all_frame_urls;
+ for (FrameTreeNode* node : frame_tree->Nodes()) {
+ // Ignore about:blank urls because of the case where a parent frame A
+ // has a child iframe B and it writes to the document using
+ // contentDocument.open() on the child frame B.
+ //
+ // In this scenario, B's contentWindow.location.href matches A's url,
+ // but B's url in the browser frame tree is still "about:blank".
+ std::string url = node->current_url().spec();
+ if (url != url::kAboutBlankURL)
+ all_frame_urls.push_back(url);
+
+ // We won't get the correct coordinate transformations for
+ // out-of-process iframes until each frame's surface is ready.
+ RenderFrameHostImpl* current_frame_host = node->current_frame_host();
+ if (!current_frame_host)
+ continue;
+ RenderWidgetHostImpl* rwh = current_frame_host->GetRenderWidgetHost();
+ if (!rwh)
+ continue;
+ RenderWidgetHostViewBase* rwhv = rwh->GetView();
+ if (rwhv && rwhv->IsChildFrameForTesting()) {
+ SurfaceHitTestReadyNotifier notifier(
+ static_cast<RenderWidgetHostViewChildFrame*>(rwhv));
+ notifier.WaitForSurfaceReady();
+ }
}
- // Load the test html.
- NavigateToURL(shell(), url);
+ // Wait for the accessibility tree to fully load for all frames,
+ // by searching for the WEB_AREA node in the accessibility tree
+ // with the url of each frame in our frame tree. Note that this
+ // doesn't support cases where there are two iframes with the
+ // exact same url. If all frames haven't loaded yet, set up a
+ // listener for accessibility events on any frame and block
+ // until the next one is received.
+ //
+ // If the original page has a @WAIT-FOR directive, don't break until
+ // the text we're waiting for appears in the full text dump of the
+ // accessibility tree, either.
+ for (;;) {
+ VLOG(1) << "Top of loop";
+ RenderFrameHostImpl* main_frame = static_cast<RenderFrameHostImpl*>(
+ web_contents->GetMainFrame());
+ BrowserAccessibilityManager* manager =
+ main_frame->browser_accessibility_manager();
+ if (manager) {
+ BrowserAccessibility* accessibility_root =
+ manager->GetRoot();
+
+ // Check to see if all frames have loaded.
+ bool all_frames_loaded = true;
+ for (const auto& url : all_frame_urls) {
+ if (!AccessibilityTreeContainsLoadedDocWithUrl(
+ accessibility_root, url)) {
+ VLOG(1) << "Still waiting on this frame to load: " << url;
+ all_frames_loaded = false;
+ break;
+ }
+ }
- // Wait for notifications. If there's a @WAIT-FOR directive, break when
- // the text we're waiting for appears in the dump, otherwise break after
- // the first notification, which will be a load complete.
- do {
- waiter->WaitForNotification();
- if (!wait_for.empty()) {
+ // Check to see if the @WAIT-FOR text has appeared yet.
+ bool all_wait_for_strings_found = true;
base::string16 tree_dump = DumpUnfilteredAccessibilityTreeAsString();
- if (base::UTF16ToUTF8(tree_dump).find(wait_for) != std::string::npos)
- wait_for.clear();
+ for (const auto& str : wait_for) {
+ if (base::UTF16ToUTF8(tree_dump).find(str) == std::string::npos) {
+ VLOG(1) << "Still waiting on this text to be found: " << str;
+ all_wait_for_strings_found = false;
+ break;
+ }
+ }
+
+ // If all frames have loaded and the @WAIT-FOR text has appeared,
+ // we're done.
+ if (all_frames_loaded && all_wait_for_strings_found)
+ break;
}
- } while (!wait_for.empty());
+
+ // Block until the next accessibility notification in any frame.
+ VLOG(1) << "Waiting until the next accessibility event";
+ AccessibilityNotificationWaiter accessibility_waiter(main_frame,
+ ui::AX_EVENT_NONE);
+ for (FrameTreeNode* node : frame_tree->Nodes())
+ accessibility_waiter.ListenToAdditionalFrame(node->current_frame_host());
+ accessibility_waiter.WaitForNotification();
+ }
// Call the subclass to dump the output.
std::vector<std::string> actual_lines = Dump();
diff --git a/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.h b/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.h
index 21ae32a1faf..5e93b9be562 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.h
+++ b/chromium/content/browser/accessibility/dump_accessibility_browsertest_base.h
@@ -31,6 +31,9 @@ class DumpAccessibilityTestBase : public ContentBrowserTest {
void RunTest(const base::FilePath file_path, const char* file_dir);
protected:
+ void SetUpCommandLine(base::CommandLine* command_line) override;
+ void SetUpOnMainThread() override;
+
//
// For subclasses to override:
//
@@ -79,11 +82,12 @@ class DumpAccessibilityTestBase : public ContentBrowserTest {
// until the given string (e.g., "text") appears in the resulting dump.
// A test can make some changes to the document, then append a magic string
// indicating that the test is done, and this framework will wait for that
- // string to appear before comparing the results.
+ // string to appear before comparing the results. There can be multiple
+ // @WAIT-FOR: directives.
void ParseHtmlForExtraDirectives(
const std::string& test_html,
std::vector<AccessibilityTreeFormatter::Filter>* filters,
- std::string* wait_for);
+ std::vector<std::string>* wait_for);
// Create the right AccessibilityTreeFormatter subclass.
AccessibilityTreeFormatter* CreateAccessibilityTreeFormatter();
diff --git a/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
index e4d2fc46dd6..40d33366e90 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -202,8 +202,16 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
RunEventTest(FILE_PATH_LITERAL("inner-html-change.html"));
}
+#if defined(OS_MACOSX)
+// Mac failures: http://crbug.com/598527.
+#define MAYBE_AccessibilityEventsInputTypeTextValueChanged \
+ DISABLED_AccessibilityEventsInputTypeTextValueChanged
+#else
+#define MAYBE_AccessibilityEventsInputTypeTextValueChanged \
+ AccessibilityEventsInputTypeTextValueChanged
+#endif
IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
- AccessibilityEventsInputTypeTextValueChanged) {
+ MAYBE_AccessibilityEventsInputTypeTextValueChanged) {
RunEventTest(FILE_PATH_LITERAL("input-type-text-value-changed.html"));
}
@@ -213,18 +221,9 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
}
// Flaky on Windows: http://crbug.com/486861
-#if defined(OS_WIN)
-#define MAYBE_AccessibilityEventsListboxNext \
- DISABLED_AccessibilityEventsListboxNext
-#define MAYBE_AccessibilityEventsMenuListPopup \
- DISABLED_AccessibilityEventsMenuListPopup
-#else
-#define MAYBE_AccessibilityEventsListboxNext AccessibilityEventsListboxNext
-#define MAYBE_AccessibilityEventsMenuListPopup AccessibilityEventsMenuListPopup
-#endif
-
+// Flaky on Mac: http://crbug.com/588271
IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
- MAYBE_AccessibilityEventsListboxNext) {
+ DISABLED_AccessibilityEventsListboxNext) {
RunEventTest(FILE_PATH_LITERAL("listbox-next.html"));
}
@@ -238,8 +237,9 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
RunEventTest(FILE_PATH_LITERAL("menulist-next.html"));
}
+// Flaky on Windows: http://crbug.com/486861
IN_PROC_BROWSER_TEST_F(DumpAccessibilityEventsTest,
- MAYBE_AccessibilityEventsMenuListPopup) {
+ DISABLED_AccessibilityEventsMenuListPopup) {
RunEventTest(FILE_PATH_LITERAL("menulist-popup.html"));
}
diff --git a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
index 9db7c77a84c..e1aa6a44d15 100644
--- a/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
+++ b/chromium/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -55,12 +55,14 @@ class DumpAccessibilityTreeTest : public DumpAccessibilityTestBase {
void AddDefaultFilters(std::vector<Filter>* filters) override {
filters->push_back(Filter(base::ASCIIToUTF16("FOCUSABLE"), Filter::ALLOW));
filters->push_back(Filter(base::ASCIIToUTF16("READONLY"), Filter::ALLOW));
- filters->push_back(Filter(base::ASCIIToUTF16("name*"), Filter::ALLOW));
+ filters->push_back(Filter(base::ASCIIToUTF16("name=*"), Filter::ALLOW));
+ filters->push_back(Filter(base::ASCIIToUTF16("roleDescription=*"),
+ Filter::ALLOW));
filters->push_back(Filter(base::ASCIIToUTF16("*=''"), Filter::DENY));
}
void SetUpCommandLine(base::CommandLine* command_line) override {
- ContentBrowserTest::SetUpCommandLine(command_line);
+ DumpAccessibilityTestBase::SetUpCommandLine(command_line);
// Enable <dialog>, which is used in some tests.
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableExperimentalWebPlatformFeatures);
@@ -77,6 +79,17 @@ class DumpAccessibilityTreeTest : public DumpAccessibilityTestBase {
RunTest(aria_file, "accessibility/aria");
}
+ void RunCSSTest(const base::FilePath::CharType* file_path) {
+ base::FilePath dir_test_data;
+ ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &dir_test_data));
+ base::FilePath test_path(
+ dir_test_data.AppendASCII("accessibility").AppendASCII("css"));
+ ASSERT_TRUE(base::PathExists(test_path)) << test_path.LossyDisplayName();
+
+ base::FilePath css_file = test_path.Append(base::FilePath(file_path));
+ RunTest(css_file, "accessibility/css");
+ }
+
void RunHtmlTest(const base::FilePath::CharType* file_path) {
base::FilePath dir_test_data;
ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &dir_test_data));
@@ -105,6 +118,18 @@ class DumpAccessibilityTreeTest : public DumpAccessibilityTestBase {
}
};
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityCSSColor) {
+ RunCSSTest(FILE_PATH_LITERAL("color.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityCSSFontStyle) {
+ RunCSSTest(FILE_PATH_LITERAL("font-style.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityCSSLanguage) {
+ RunCSSTest(FILE_PATH_LITERAL("language.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityA) {
RunHtmlTest(FILE_PATH_LITERAL("a.html"));
}
@@ -113,6 +138,10 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAbbr) {
RunHtmlTest(FILE_PATH_LITERAL("abbr.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityActionVerbs) {
+ RunHtmlTest(FILE_PATH_LITERAL("action-verbs.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAddress) {
RunHtmlTest(FILE_PATH_LITERAL("address.html"));
}
@@ -554,7 +583,12 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityAriaTextbox) {
}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
- AccessibilityAriaTextboxWithSelection) {
+ AccessibilityAriaTextboxWithRichText) {
+ RunAriaTest(FILE_PATH_LITERAL("aria-textbox-with-rich-text.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityAriaTextboxWithSelection) {
RunAriaTest(FILE_PATH_LITERAL("aria-textbox-with-selection.html"));
}
@@ -826,21 +860,59 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityIframe) {
RunHtmlTest(FILE_PATH_LITERAL("iframe.html"));
}
-// Flaky. See http://crbug.com/224659.
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
- DISABLED_AccessibilityIframeCoordinates) {
+ AccessibilityIframeCrossProcess) {
+ RunHtmlTest(FILE_PATH_LITERAL("iframe-cross-process.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityIframeCoordinates) {
RunHtmlTest(FILE_PATH_LITERAL("iframe-coordinates.html"));
}
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityIframeCoordinatesCrossProcess) {
+ RunHtmlTest(FILE_PATH_LITERAL("iframe-coordinates-cross-process.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
AccessibilityIframePresentational) {
RunHtmlTest(FILE_PATH_LITERAL("iframe-presentational.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityIframeTransform) {
+ RunHtmlTest(FILE_PATH_LITERAL("iframe-transform.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityIframeTransformCrossProcess) {
+ RunHtmlTest(FILE_PATH_LITERAL("iframe-transform-cross-process.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityIframeTransformNested) {
+ RunHtmlTest(FILE_PATH_LITERAL("iframe-transform-nested.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityIframeTransformNestedCrossProcess) {
+ RunHtmlTest(FILE_PATH_LITERAL("iframe-transform-nested-cross-process.html"));
+}
+
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
+ AccessibilityIframeTransformScrolled) {
+ RunHtmlTest(FILE_PATH_LITERAL("iframe-transform-scrolled.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityImg) {
RunHtmlTest(FILE_PATH_LITERAL("img.html"));
}
+IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityImgEmptyAlt) {
+ RunHtmlTest(FILE_PATH_LITERAL("img-empty-alt.html"));
+}
+
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest, AccessibilityInputButton) {
RunHtmlTest(FILE_PATH_LITERAL("input-button.html"));
}
@@ -1074,13 +1146,29 @@ IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
RunHtmlTest(FILE_PATH_LITERAL("modal-dialog-opened.html"));
}
+// Flaky on Windows and Mac: crbug.com/593846
+#if defined(OS_WIN) || defined(OS_MACOSX)
+#define MAYBE_AccessibilityModalDialogInIframeClosed \
+ DISABLED_AccessibilityModalDialogInIframeClosed
+#else
+#define MAYBE_AccessibilityModalDialogInIframeClosed \
+ AccessibilityModalDialogInIframeClosed
+#endif
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
- AccessibilityModalDialogInIframeClosed) {
+ MAYBE_AccessibilityModalDialogInIframeClosed) {
RunHtmlTest(FILE_PATH_LITERAL("modal-dialog-in-iframe-closed.html"));
}
+// Flaky on Windows and Mac: crbug.com/593846
+#if defined(OS_WIN) || defined(OS_MACOSX)
+#define MAYBE_AccessibilityModalDialogInIframeOpened \
+ DISABLED_AccessibilityModalDialogInIframeOpened
+#else
+#define MAYBE_AccessibilityModalDialogInIframeOpened \
+ AccessibilityModalDialogInIframeOpened
+#endif
IN_PROC_BROWSER_TEST_F(DumpAccessibilityTreeTest,
- AccessibilityModalDialogInIframeOpened) {
+ MAYBE_AccessibilityModalDialogInIframeOpened) {
RunHtmlTest(FILE_PATH_LITERAL("modal-dialog-in-iframe-opened.html"));
}
diff --git a/chromium/content/browser/accessibility/hit_testing_browsertest.cc b/chromium/content/browser/accessibility/hit_testing_browsertest.cc
new file mode 100644
index 00000000000..7610f73da1d
--- /dev/null
+++ b/chromium/content/browser/accessibility/hit_testing_browsertest.cc
@@ -0,0 +1,171 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/strings/string16.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/browser/accessibility/accessibility_tree_formatter.h"
+#include "content/browser/accessibility/browser_accessibility.h"
+#include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_paths.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/url_constants.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "content/test/accessibility_browser_test_utils.h"
+#include "net/dns/mock_host_resolver.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+bool AXTreeContainsNodeWithName(BrowserAccessibility* node,
+ const std::string& name) {
+ if (node->GetStringAttribute(ui::AX_ATTR_NAME) == name)
+ return true;
+
+ for (unsigned i = 0; i < node->PlatformChildCount(); i++) {
+ if (AXTreeContainsNodeWithName(node->PlatformGetChild(i), name))
+ return true;
+ }
+
+ return false;
+}
+
+} // namespace
+
+class AccessibilityHitTestingBrowserTest : public ContentBrowserTest {
+ public:
+ AccessibilityHitTestingBrowserTest() {}
+ ~AccessibilityHitTestingBrowserTest() override {}
+
+ protected:
+ BrowserAccessibility* HitTestAndWaitForResult(const gfx::Point& point) {
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ FrameTree* frame_tree = web_contents->GetFrameTree();
+ BrowserAccessibilityManager* manager =
+ web_contents->GetRootBrowserAccessibilityManager();
+
+ AccessibilityNotificationWaiter hover_waiter(
+ shell(), AccessibilityModeComplete, ui::AX_EVENT_HOVER);
+ for (FrameTreeNode* node : frame_tree->Nodes())
+ hover_waiter.ListenToAdditionalFrame(node->current_frame_host());
+ manager->delegate()->AccessibilityHitTest(point);
+ hover_waiter.WaitForNotification();
+
+ RenderFrameHostImpl* target_frame = hover_waiter.event_render_frame_host();
+ BrowserAccessibilityManager* target_manager =
+ target_frame->browser_accessibility_manager();
+ int hover_target_id = hover_waiter.event_target_id();
+ BrowserAccessibility* hovered_node =
+ target_manager->GetFromID(hover_target_id);
+ return hovered_node;
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(AccessibilityHitTestingBrowserTest,
+ HitTestOutsideDocumentBoundsReturnsRoot) {
+ NavigateToURL(shell(), GURL(url::kAboutBlankURL));
+
+ // Load the page.
+ AccessibilityNotificationWaiter waiter(shell(), AccessibilityModeComplete,
+ ui::AX_EVENT_LOAD_COMPLETE);
+ const char url_str[] =
+ "data:text/html,"
+ "<!doctype html>"
+ "<html><head><title>Accessibility Test</title></head>"
+ "<body>"
+ "<a href='#'>"
+ "This is some text in a link"
+ "</a>"
+ "</body></html>";
+ GURL url(url_str);
+ NavigateToURL(shell(), url);
+ waiter.WaitForNotification();
+
+ BrowserAccessibility* hovered_node =
+ HitTestAndWaitForResult(gfx::Point(-1, -1));
+ ASSERT_TRUE(hovered_node != NULL);
+ ASSERT_EQ(ui::AX_ROLE_ROOT_WEB_AREA, hovered_node->GetRole());
+}
+
+IN_PROC_BROWSER_TEST_F(AccessibilityHitTestingBrowserTest,
+ HitTestingInIframes) {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ NavigateToURL(shell(), GURL(url::kAboutBlankURL));
+
+ AccessibilityNotificationWaiter waiter(shell(), AccessibilityModeComplete,
+ ui::AX_EVENT_LOAD_COMPLETE);
+ GURL url(embedded_test_server()->GetURL(
+ "/accessibility/html/iframe-coordinates.html"));
+ NavigateToURL(shell(), url);
+ waiter.WaitForNotification();
+
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ FrameTree* frame_tree = web_contents->GetFrameTree();
+ BrowserAccessibilityManager* manager =
+ web_contents->GetRootBrowserAccessibilityManager();
+ BrowserAccessibility* root = manager->GetRoot();
+ while (!AXTreeContainsNodeWithName(root, "Ordinary Button") ||
+ !AXTreeContainsNodeWithName(root, "Scrolled Button")) {
+ AccessibilityNotificationWaiter waiter(shell(), AccessibilityModeComplete,
+ ui::AX_EVENT_NONE);
+ for (FrameTreeNode* node : frame_tree->Nodes())
+ waiter.ListenToAdditionalFrame(node->current_frame_host());
+ waiter.WaitForNotification();
+ }
+
+ // Send a series of hit test requests, and for each one
+ // wait for the hover event in response, verifying we hit the
+ // correct object.
+
+ // (50, 50) -> "Button"
+ BrowserAccessibility* hovered_node;
+ hovered_node = HitTestAndWaitForResult(gfx::Point(50, 50));
+ ASSERT_TRUE(hovered_node != NULL);
+ ASSERT_EQ(ui::AX_ROLE_BUTTON, hovered_node->GetRole());
+ ASSERT_EQ("Button", hovered_node->GetStringAttribute(ui::AX_ATTR_NAME));
+
+ // (50, 305) -> div in first iframe
+ hovered_node = HitTestAndWaitForResult(gfx::Point(50, 305));
+ ASSERT_TRUE(hovered_node != NULL);
+ ASSERT_EQ(ui::AX_ROLE_DIV, hovered_node->GetRole());
+
+ // (50, 350) -> "Ordinary Button"
+ hovered_node = HitTestAndWaitForResult(gfx::Point(50, 350));
+ ASSERT_TRUE(hovered_node != NULL);
+ ASSERT_EQ(ui::AX_ROLE_BUTTON, hovered_node->GetRole());
+ ASSERT_EQ("Ordinary Button",
+ hovered_node->GetStringAttribute(ui::AX_ATTR_NAME));
+
+ // (50, 455) -> "Scrolled Button"
+ hovered_node = HitTestAndWaitForResult(gfx::Point(50, 455));
+ ASSERT_TRUE(hovered_node != NULL);
+ ASSERT_EQ(ui::AX_ROLE_BUTTON, hovered_node->GetRole());
+ ASSERT_EQ("Scrolled Button",
+ hovered_node->GetStringAttribute(ui::AX_ATTR_NAME));
+
+ // (50, 505) -> div in second iframe
+ hovered_node = HitTestAndWaitForResult(gfx::Point(50, 505));
+ ASSERT_TRUE(hovered_node != NULL);
+ ASSERT_EQ(ui::AX_ROLE_DIV, hovered_node->GetRole());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc b/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc
index 8b17f2d9fd2..1a0239eb58b 100644
--- a/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc
+++ b/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.cc
@@ -11,6 +11,7 @@
#include "base/strings/utf_string_conversions.h"
#include "content/browser/accessibility/browser_accessibility.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "ui/accessibility/ax_enums.h"
namespace content {
@@ -210,4 +211,249 @@ bool OneShotAccessibilityTreeSearch::Matches(BrowserAccessibility* node) {
return true;
}
+//
+// Predicates
+//
+
+bool AccessibilityArticlePredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return node->GetRole() == ui::AX_ROLE_ARTICLE;
+}
+
+bool AccessibilityButtonPredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ switch (node->GetRole()) {
+ case ui::AX_ROLE_BUTTON:
+ case ui::AX_ROLE_MENU_BUTTON:
+ case ui::AX_ROLE_POP_UP_BUTTON:
+ case ui::AX_ROLE_SWITCH:
+ case ui::AX_ROLE_TOGGLE_BUTTON:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool AccessibilityBlockquotePredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return node->GetRole() == ui::AX_ROLE_BLOCKQUOTE;
+}
+
+bool AccessibilityCheckboxPredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return (node->GetRole() == ui::AX_ROLE_CHECK_BOX ||
+ node->GetRole() == ui::AX_ROLE_MENU_ITEM_CHECK_BOX);
+}
+
+bool AccessibilityComboboxPredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return (node->GetRole() == ui::AX_ROLE_COMBO_BOX ||
+ node->GetRole() == ui::AX_ROLE_POP_UP_BUTTON);
+}
+
+bool AccessibilityControlPredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ if (node->IsControl())
+ return true;
+ if (node->HasState(ui::AX_STATE_FOCUSABLE) &&
+ node->GetRole() != ui::AX_ROLE_IFRAME &&
+ node->GetRole() != ui::AX_ROLE_IFRAME_PRESENTATIONAL &&
+ node->GetRole() != ui::AX_ROLE_IMAGE_MAP_LINK &&
+ node->GetRole() != ui::AX_ROLE_LINK &&
+ node->GetRole() != ui::AX_ROLE_WEB_AREA &&
+ node->GetRole() != ui::AX_ROLE_ROOT_WEB_AREA) {
+ return true;
+ }
+ return false;
+}
+
+bool AccessibilityFocusablePredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ bool focusable = node->HasState(ui::AX_STATE_FOCUSABLE);
+ if (node->GetRole() == ui::AX_ROLE_IFRAME ||
+ node->GetRole() == ui::AX_ROLE_IFRAME_PRESENTATIONAL ||
+ node->GetRole() == ui::AX_ROLE_WEB_AREA ||
+ node->GetRole() == ui::AX_ROLE_ROOT_WEB_AREA) {
+ focusable = false;
+ }
+ return focusable;
+}
+
+bool AccessibilityGraphicPredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return node->GetRole() == ui::AX_ROLE_IMAGE;
+}
+
+bool AccessibilityHeadingPredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return (node->GetRole() == ui::AX_ROLE_HEADING);
+}
+
+bool AccessibilityH1Predicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return (node->GetRole() == ui::AX_ROLE_HEADING &&
+ node->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL) == 1);
+}
+
+bool AccessibilityH2Predicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return (node->GetRole() == ui::AX_ROLE_HEADING &&
+ node->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL) == 2);
+}
+
+bool AccessibilityH3Predicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return (node->GetRole() == ui::AX_ROLE_HEADING &&
+ node->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL) == 3);
+}
+
+bool AccessibilityH4Predicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return (node->GetRole() == ui::AX_ROLE_HEADING &&
+ node->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL) == 4);
+}
+
+bool AccessibilityH5Predicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return (node->GetRole() == ui::AX_ROLE_HEADING &&
+ node->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL) == 5);
+}
+
+bool AccessibilityH6Predicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return (node->GetRole() == ui::AX_ROLE_HEADING &&
+ node->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL) == 6);
+}
+
+bool AccessibilityHeadingSameLevelPredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return (node->GetRole() == ui::AX_ROLE_HEADING &&
+ start->GetRole() == ui::AX_ROLE_HEADING &&
+ (node->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL) ==
+ start->GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL)));
+}
+
+bool AccessibilityFramePredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ if (node->IsWebAreaForPresentationalIframe())
+ return false;
+ if (!node->GetParent())
+ return false;
+ return (node->GetRole() == ui::AX_ROLE_WEB_AREA ||
+ node->GetRole() == ui::AX_ROLE_ROOT_WEB_AREA);
+}
+
+bool AccessibilityLandmarkPredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ switch (node->GetRole()) {
+ case ui::AX_ROLE_APPLICATION:
+ case ui::AX_ROLE_ARTICLE:
+ case ui::AX_ROLE_BANNER:
+ case ui::AX_ROLE_COMPLEMENTARY:
+ case ui::AX_ROLE_CONTENT_INFO:
+ case ui::AX_ROLE_MAIN:
+ case ui::AX_ROLE_NAVIGATION:
+ case ui::AX_ROLE_SEARCH:
+ case ui::AX_ROLE_REGION:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool AccessibilityLinkPredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return (node->GetRole() == ui::AX_ROLE_LINK ||
+ node->GetRole() == ui::AX_ROLE_IMAGE_MAP_LINK);
+}
+
+bool AccessibilityListPredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return (node->GetRole() == ui::AX_ROLE_LIST_BOX ||
+ node->GetRole() == ui::AX_ROLE_LIST ||
+ node->GetRole() == ui::AX_ROLE_DESCRIPTION_LIST);
+}
+
+bool AccessibilityListItemPredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return (node->GetRole() == ui::AX_ROLE_LIST_ITEM ||
+ node->GetRole() == ui::AX_ROLE_DESCRIPTION_LIST_TERM ||
+ node->GetRole() == ui::AX_ROLE_LIST_BOX_OPTION);
+}
+
+bool AccessibilityLiveRegionPredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return node->HasStringAttribute(ui::AX_ATTR_LIVE_STATUS);
+}
+
+bool AccessibilityMainPredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return (node->GetRole() == ui::AX_ROLE_MAIN);
+}
+
+bool AccessibilityMediaPredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ const std::string& tag = node->GetStringAttribute(ui::AX_ATTR_HTML_TAG);
+ return tag == "audio" || tag == "video";
+}
+
+bool AccessibilityRadioButtonPredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return (node->GetRole() == ui::AX_ROLE_RADIO_BUTTON ||
+ node->GetRole() == ui::AX_ROLE_MENU_ITEM_RADIO);
+}
+
+bool AccessibilityRadioGroupPredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return node->GetRole() == ui::AX_ROLE_RADIO_GROUP;
+}
+
+bool AccessibilityTablePredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return (node->GetRole() == ui::AX_ROLE_TABLE ||
+ node->GetRole() == ui::AX_ROLE_GRID);
+}
+
+bool AccessibilityTextfieldPredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return (node->IsSimpleTextControl() || node->IsRichTextControl());
+}
+
+bool AccessibilityTextStyleBoldPredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ int32_t style = node->GetIntAttribute(ui::AX_ATTR_TEXT_STYLE);
+ return 0 != (style & ui::AX_TEXT_STYLE_BOLD);
+}
+
+bool AccessibilityTextStyleItalicPredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ int32_t style = node->GetIntAttribute(ui::AX_ATTR_TEXT_STYLE);
+ return 0 != (style & ui::AX_TEXT_STYLE_BOLD);
+}
+
+bool AccessibilityTextStyleUnderlinePredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ int32_t style = node->GetIntAttribute(ui::AX_ATTR_TEXT_STYLE);
+ return 0 != (style & ui::AX_TEXT_STYLE_UNDERLINE);
+}
+
+bool AccessibilityTreePredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return (node->IsSimpleTextControl() || node->IsRichTextControl());
+}
+
+bool AccessibilityUnvisitedLinkPredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return ((node->GetRole() == ui::AX_ROLE_LINK ||
+ node->GetRole() == ui::AX_ROLE_IMAGE_MAP_LINK) &&
+ !node->HasState(ui::AX_STATE_VISITED));
+}
+
+bool AccessibilityVisitedLinkPredicate(
+ BrowserAccessibility* start, BrowserAccessibility* node) {
+ return ((node->GetRole() == ui::AX_ROLE_LINK ||
+ node->GetRole() == ui::AX_ROLE_IMAGE_MAP_LINK) &&
+ node->HasState(ui::AX_STATE_VISITED));
+}
+
} // namespace content
diff --git a/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.h b/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.h
index 2538bb8aee0..df79eb94e02 100644
--- a/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.h
+++ b/chromium/content/browser/accessibility/one_shot_accessibility_tree_search.h
@@ -24,6 +24,47 @@ typedef bool (*AccessibilityMatchPredicate)(
BrowserAccessibility* start_element,
BrowserAccessibility* this_element);
+#define DECLARE_ACCESSIBILITY_PREDICATE(PredicateName) \
+ bool PredicateName(BrowserAccessibility* start_element, \
+ BrowserAccessibility* this_element);
+
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityArticlePredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityBlockquotePredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityButtonPredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityCheckboxPredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityComboboxPredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityControlPredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityFocusablePredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityGraphicPredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityHeadingPredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityH1Predicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityH2Predicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityH3Predicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityH4Predicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityH5Predicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityH6Predicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityHeadingSameLevelPredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityFramePredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityLandmarkPredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityLinkPredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityListPredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityListItemPredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityLiveRegionPredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityMainPredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityMediaPredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityRadioButtonPredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityRadioGroupPredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityTablePredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityTextfieldPredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityTextStyleBoldPredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityTextStyleItalicPredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityTextStyleUnderlinePredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityTreePredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityUnvisitedLinkPredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityVisitedLinkPredicate);
+DECLARE_ACCESSIBILITY_PREDICATE(AccessibilityTextStyleBoldPredicate);
+
+
// This class provides an interface for searching the accessibility tree from
// a given starting node, with a few built-in options and allowing an arbitrary
// number of predicates that can be used to restrict the search.
diff --git a/chromium/content/browser/accessibility/site_per_process_accessibility_browsertest.cc b/chromium/content/browser/accessibility/site_per_process_accessibility_browsertest.cc
index 37107702569..75833ff9aa8 100644
--- a/chromium/content/browser/accessibility/site_per_process_accessibility_browsertest.cc
+++ b/chromium/content/browser/accessibility/site_per_process_accessibility_browsertest.cc
@@ -58,15 +58,6 @@ bool AccessibilityTreeContainsText(BrowserAccessibility* node,
return false;
}
-// Helper function to be used with FrameTree::ForEach, so that
-// AccessibilityNotificationWaiter can listen for accessibility
-// events in all frames.
-bool ListenToFrame(AccessibilityNotificationWaiter* waiter,
- FrameTreeNode* frame_tree_node) {
- waiter->ListenToAdditionalFrame(frame_tree_node->current_frame_host());
- return true;
-}
-
} // namespace
class MAYBE_SitePerProcessAccessibilityBrowserTest
@@ -113,7 +104,10 @@ class MAYBE_SitePerProcessAccessibilityBrowserTest
main_frame_manager->GetRoot(), text)) {
AccessibilityNotificationWaiter accessibility_waiter(main_frame,
ui::AX_EVENT_NONE);
- frame_tree->ForEach(base::Bind(ListenToFrame, &accessibility_waiter));
+ for (FrameTreeNode* node : frame_tree->Nodes())
+ accessibility_waiter.ListenToAdditionalFrame(
+ node->current_frame_host());
+
accessibility_waiter.WaitForNotification();
}
}
diff --git a/chromium/content/browser/accessibility/snapshot_ax_tree_browsertest.cc b/chromium/content/browser/accessibility/snapshot_ax_tree_browsertest.cc
index da6201f5b6b..7dc177d8e5d 100644
--- a/chromium/content/browser/accessibility/snapshot_ax_tree_browsertest.cc
+++ b/chromium/content/browser/accessibility/snapshot_ax_tree_browsertest.cc
@@ -9,6 +9,9 @@
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
+#include "content/test/content_browser_test_utils_internal.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/accessibility/ax_node.h"
#include "ui/accessibility/ax_tree.h"
@@ -39,6 +42,19 @@ class AXTreeSnapshotWaiter {
DISALLOW_COPY_AND_ASSIGN(AXTreeSnapshotWaiter);
};
+void DumpRolesAndNamesAsText(const ui::AXNode* node,
+ int indent,
+ std::string* dst) {
+ for (int i = 0; i < indent; i++)
+ *dst += " ";
+ *dst += ui::ToString(node->data().role);
+ if (node->data().HasStringAttribute(ui::AX_ATTR_NAME))
+ *dst += " '" + node->data().GetStringAttribute(ui::AX_ATTR_NAME) + "'";
+ *dst += "\n";
+ for (int i = 0; i < node->child_count(); ++i)
+ DumpRolesAndNamesAsText(node->children()[i], indent + 1, dst);
+}
+
} // namespace
class SnapshotAXTreeBrowserTest : public ContentBrowserTest {
@@ -75,4 +91,54 @@ IN_PROC_BROWSER_TEST_F(SnapshotAXTreeBrowserTest,
ASSERT_EQ(ui::AX_ROLE_BUTTON, button->data().role);
}
+IN_PROC_BROWSER_TEST_F(SnapshotAXTreeBrowserTest,
+ SnapshotAccessibilityTreeFromMultipleFrames) {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ NavigateToURL(shell(), embedded_test_server()->GetURL(
+ "/accessibility/snapshot/outer.html"));
+
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ FrameTreeNode* root_frame = web_contents->GetFrameTree()->root();
+
+ NavigateFrameToURL(root_frame->child_at(0), GURL("data:text/plain,Alpha"));
+ NavigateFrameToURL(root_frame->child_at(1), embedded_test_server()->GetURL(
+ "/accessibility/snapshot/inner.html"));
+
+ AXTreeSnapshotWaiter waiter;
+ web_contents->RequestAXTreeSnapshot(
+ base::Bind(&AXTreeSnapshotWaiter::ReceiveSnapshot,
+ base::Unretained(&waiter)));
+ waiter.Wait();
+
+ // Dump the whole tree if one of the assertions below fails
+ // to aid in debugging why it failed.
+ SCOPED_TRACE(waiter.snapshot().ToString());
+
+ ui::AXTree tree(waiter.snapshot());
+ ui::AXNode* root = tree.root();
+ std::string dump;
+ DumpRolesAndNamesAsText(root, 0, &dump);
+ EXPECT_EQ(
+ "rootWebArea\n"
+ " group\n"
+ " button 'Before'\n"
+ " iframe\n"
+ " group\n"
+ " pre\n"
+ " staticText 'Alpha'\n"
+ " button 'Middle'\n"
+ " iframe\n"
+ " group\n"
+ " group\n"
+ " button 'Inside Before'\n"
+ " iframe\n"
+ " group\n"
+ " button 'Inside After'\n"
+ " button 'After'\n",
+ dump);
+}
+
} // namespace content
diff --git a/chromium/content/browser/android/browser_surface_texture_manager.h b/chromium/content/browser/android/browser_surface_texture_manager.h
index f9fb74cccb5..639ce28b0e5 100644
--- a/chromium/content/browser/android/browser_surface_texture_manager.h
+++ b/chromium/content/browser/android/browser_surface_texture_manager.h
@@ -5,18 +5,18 @@
#ifndef CONTENT_BROWSER_ANDROID_BROWSER_SURFACE_TEXTURE_MANAGER_H_
#define CONTENT_BROWSER_ANDROID_BROWSER_SURFACE_TEXTURE_MANAGER_H_
-#include "content/common/android/surface_texture_manager.h"
+#include "gpu/ipc/common/android/surface_texture_manager.h"
#include "base/macros.h"
#include "base/memory/singleton.h"
-#include "content/common/android/surface_texture_peer.h"
#include "content/common/content_export.h"
+#include "gpu/ipc/common/android/surface_texture_peer.h"
namespace content {
class CONTENT_EXPORT BrowserSurfaceTextureManager
- : public SurfaceTextureManager,
- public SurfaceTexturePeer {
+ : public gpu::SurfaceTextureManager,
+ public gpu::SurfaceTexturePeer {
public:
static BrowserSurfaceTextureManager* GetInstance();
diff --git a/chromium/content/browser/android/child_process_launcher_android.cc b/chromium/content/browser/android/child_process_launcher_android.cc
index 471ce31d91c..94765fbeeba 100644
--- a/chromium/content/browser/android/child_process_launcher_android.cc
+++ b/chromium/content/browser/android/child_process_launcher_android.cc
@@ -13,12 +13,16 @@
#include "base/android/jni_array.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "content/browser/file_descriptor_info_impl.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/media/android/browser_media_player_manager.h"
#include "content/browser/media/android/media_web_contents_observer_android.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/child_process_host_impl.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_process_host.h"
+#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "jni/ChildProcessLauncher_jni.h"
#include "media/base/android/media_player_android.h"
@@ -41,7 +45,6 @@ static void SetSurfacePeer(
base::ProcessHandle render_process_handle,
int render_frame_id,
int player_id) {
-#if !defined(USE_AURA)
int render_process_id = 0;
RenderProcessHost::iterator it = RenderProcessHost::AllHostsIterator();
while (!it.IsAtEnd()) {
@@ -83,9 +86,21 @@ static void SetSurfacePeer(
gfx::ScopedJavaSurface scoped_surface(surface);
player->SetVideoSurface(std::move(scoped_surface));
}
-#else
- NOTREACHED();
-#endif
+}
+
+void LaunchDownloadProcess(base::CommandLine* cmd_line) {
+ scoped_ptr<base::CommandLine> cmd_line_deleter(cmd_line);
+
+ JNIEnv* env = AttachCurrentThread();
+ DCHECK(env);
+
+ // Create the Command line String[]
+ ScopedJavaLocalRef<jobjectArray> j_argv =
+ ToJavaArrayOfStrings(env, cmd_line->argv());
+
+ // TODO(qinmin): pass download parameters here.
+ Java_ChildProcessLauncher_startDownloadProcessIfNecessary(
+ env, base::android::GetApplicationContext(), j_argv.obj());
}
} // anonymous namespace
@@ -107,6 +122,32 @@ static void OnChildProcessStarted(JNIEnv*,
delete callback;
}
+void StartDownloadProcessIfNecessary() {
+ base::FilePath exe_path = content::ChildProcessHost::GetChildPath(
+ content::ChildProcessHost::CHILD_NORMAL);
+ if (exe_path.empty()) {
+ NOTREACHED() << "Unable to get download process binary name.";
+ return;
+ }
+ base::CommandLine* cmd_line = new base::CommandLine(exe_path);
+ cmd_line->AppendSwitchASCII(switches::kProcessType,
+ switches::kDownloadProcess);
+ cmd_line->AppendSwitch(switches::kNoSandbox);
+
+ const base::CommandLine browser_command_line =
+ *base::CommandLine::ForCurrentProcess();
+ static const char* kForwardSwitches[] = {
+ switches::kDisableLogging,
+ switches::kEnableLogging,
+ switches::kLoggingLevel,
+ };
+ cmd_line->CopySwitchesFrom(browser_command_line, kForwardSwitches,
+ arraysize(kForwardSwitches));
+ CHECK(!cmd_line->HasSwitch(switches::kSingleProcess));
+ BrowserThread::PostTask(BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
+ base::Bind(&LaunchDownloadProcess, cmd_line));
+}
+
void StartChildProcess(
const base::CommandLine::StringVector& argv,
int child_process_id,
@@ -205,6 +246,13 @@ void UnregisterViewSurface(int surface_id) {
Java_ChildProcessLauncher_unregisterViewSurface(env, surface_id);
}
+gfx::ScopedJavaSurface GetViewSurface(int surface_id) {
+ JNIEnv* env = AttachCurrentThread();
+ DCHECK(env);
+ return gfx::ScopedJavaSurface::AcquireExternalSurface(
+ Java_ChildProcessLauncher_getViewSurface(env, surface_id).obj());
+}
+
void CreateSurfaceTextureSurface(int surface_texture_id,
int client_id,
gfx::SurfaceTexture* surface_texture) {
diff --git a/chromium/content/browser/android/child_process_launcher_android.h b/chromium/content/browser/android/child_process_launcher_android.h
index ea806ac5571..41cf4535704 100644
--- a/chromium/content/browser/android/child_process_launcher_android.h
+++ b/chromium/content/browser/android/child_process_launcher_android.h
@@ -6,11 +6,13 @@
#define CONTENT_BROWSER_ANDROID_CHILD_PROCESS_LAUNCHER_ANDROID_H_
#include <jni.h>
+
#include <map>
#include "base/callback.h"
#include "base/command_line.h"
#include "base/files/memory_mapped_file.h"
+#include "base/memory/scoped_ptr.h"
#include "base/process/process.h"
#include "content/public/browser/file_descriptor_info.h"
#include "ui/gl/android/scoped_java_surface.h"
@@ -29,6 +31,10 @@ void StartChildProcess(
const std::map<int, base::MemoryMappedFile::Region>& regions,
const StartChildProcessCallback& callback);
+// Starts the background download process if it hasn't been started.
+// TODO(qinmin): pass the download parameters here and pass it to java side.
+void StartDownloadProcessIfNecessary();
+
// Stops a child process based on the handle returned form
// StartChildProcess.
void StopChildProcess(base::ProcessHandle handle);
@@ -42,6 +48,8 @@ void RegisterViewSurface(int surface_id, jobject j_surface);
void UnregisterViewSurface(int surface_id);
+gfx::ScopedJavaSurface GetViewSurface(int surface_id);
+
void CreateSurfaceTextureSurface(int surface_texture_id,
int client_id,
gfx::SurfaceTexture* surface_texture);
diff --git a/chromium/content/browser/android/composited_touch_handle_drawable.cc b/chromium/content/browser/android/composited_touch_handle_drawable.cc
index 235e2eef3b4..16974e1afcc 100644
--- a/chromium/content/browser/android/composited_touch_handle_drawable.cc
+++ b/chromium/content/browser/android/composited_touch_handle_drawable.cc
@@ -96,7 +96,7 @@ CompositedTouchHandleDrawable::CompositedTouchHandleDrawable(
jobject context)
: dpi_scale_(dpi_scale),
orientation_(ui::TouchHandleOrientation::UNDEFINED),
- layer_(cc::UIResourceLayer::Create(Compositor::LayerSettings())) {
+ layer_(cc::UIResourceLayer::Create()) {
g_selection_resources.Get().LoadIfNecessary(context);
drawable_horizontal_padding_ratio_ =
g_selection_resources.Get().GetDrawableHorizontalPaddingRatio();
diff --git a/chromium/content/browser/android/content_startup_flags.cc b/chromium/content/browser/android/content_startup_flags.cc
index acda33ee494..b588deda0c9 100644
--- a/chromium/content/browser/android/content_startup_flags.cc
+++ b/chromium/content/browser/android/content_startup_flags.cc
@@ -10,7 +10,6 @@
#include "base/logging.h"
#include "base/sys_info.h"
#include "cc/base/switches.h"
-#include "cc/layers/layer_settings.h"
#include "content/public/browser/android/compositor.h"
#include "content/public/common/content_switches.h"
#include "gpu/command_buffer/service/gpu_switches.h"
@@ -79,14 +78,6 @@ void SetContentCommandLineFlags(bool single_process,
parsed_command_line->AppendSwitchASCII(
switches::kProfilerTiming, switches::kProfilerTimingDisabledValue);
}
-
-#if !defined(USE_AURA)
- cc::LayerSettings layer_settings;
- layer_settings.use_compositor_animation_timelines =
- !parsed_command_line->HasSwitch(
- switches::kDisableAndroidCompositorAnimationTimelines);
- Compositor::SetLayerSettings(layer_settings);
-#endif
}
} // namespace content
diff --git a/chromium/content/browser/android/content_video_view.cc b/chromium/content/browser/android/content_video_view.cc
index b107377c34c..4b14959ba5f 100644
--- a/chromium/content/browser/android/content_video_view.cc
+++ b/chromium/content/browser/android/content_video_view.cc
@@ -4,21 +4,15 @@
#include "content/browser/android/content_video_view.h"
-#include "base/command_line.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
+#include "content/browser/android/content_view_core_impl.h"
#include "content/browser/media/android/browser_media_player_manager.h"
-#include "content/browser/power_save_blocker_impl.h"
-#include "content/common/android/surface_texture_peer.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/common/content_switches.h"
#include "jni/ContentVideoView_jni.h"
-#if !defined(USE_AURA)
-#include "content/browser/android/content_view_core_impl.h"
-#endif
-
using base::android::AttachCurrentThread;
using base::android::CheckException;
using base::android::ScopedJavaGlobalRef;
@@ -51,12 +45,11 @@ ContentVideoView* ContentVideoView::GetInstance() {
return g_content_video_view;
}
-ContentVideoView::ContentVideoView(
- BrowserMediaPlayerManager* manager)
- : manager_(manager),
- weak_factory_(this) {
+ContentVideoView::ContentVideoView(Client* client,
+ ContentViewCore* content_view_core)
+ : client_(client), weak_factory_(this) {
DCHECK(!g_content_video_view);
- j_content_video_view_ = CreateJavaObject();
+ j_content_video_view_ = CreateJavaObject(content_view_core);
g_content_video_view = this;
}
@@ -85,7 +78,7 @@ void ContentVideoView::OnMediaPlayerError(int error_type) {
ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
if (!content_video_view.is_null()) {
Java_ContentVideoView_onMediaPlayerError(env, content_video_view.obj(),
- error_type);
+ error_type);
}
}
@@ -94,23 +87,35 @@ void ContentVideoView::OnVideoSizeChanged(int width, int height) {
ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
if (!content_video_view.is_null()) {
Java_ContentVideoView_onVideoSizeChanged(env, content_video_view.obj(),
- width, height);
+ width, height);
}
}
-void ContentVideoView::OnPlaybackComplete() {
+void ContentVideoView::ExitFullscreen() {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
- if (!content_video_view.is_null()) {
- Java_ContentVideoView_onPlaybackComplete(env, content_video_view.obj());
- }
+ bool release_media_player = false;
+ if (!content_video_view.is_null())
+ Java_ContentVideoView_exitFullscreen(env, content_video_view.obj(),
+ release_media_player);
}
-void ContentVideoView::OnExitFullscreen() {
- JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
- if (!content_video_view.is_null())
- Java_ContentVideoView_onExitFullscreen(env, content_video_view.obj());
+ScopedJavaLocalRef<jobject> ContentVideoView::GetJavaObject(JNIEnv* env) {
+ return j_content_video_view_.get(env);
+}
+
+void ContentVideoView::SetSurface(JNIEnv*,
+ const JavaParamRef<jobject>&,
+ const JavaParamRef<jobject>& surface) {
+ client_->SetVideoSurface(
+ gfx::ScopedJavaSurface::AcquireExternalSurface(surface));
+}
+
+void ContentVideoView::DidExitFullscreen(JNIEnv*,
+ const JavaParamRef<jobject>&,
+ jboolean release_media_player) {
+ j_content_video_view_.reset();
+ client_->DidExitFullscreen(release_media_player);
}
void ContentVideoView::RecordFullscreenPlayback(JNIEnv*,
@@ -151,63 +156,11 @@ void ContentVideoView::RecordExitFullscreenPlayback(
}
}
-void ContentVideoView::UpdateMediaMetadata() {
+JavaObjectWeakGlobalRef ContentVideoView::CreateJavaObject(
+ ContentViewCore* content_view_core) {
JNIEnv* env = AttachCurrentThread();
- ScopedJavaLocalRef<jobject> content_video_view = GetJavaObject(env);
- if (content_video_view.is_null())
- return;
-
- media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer();
- if (player && player->IsPlayerReady()) {
- Java_ContentVideoView_onUpdateMediaMetadata(
- env, content_video_view.obj(), player->GetVideoWidth(),
- player->GetVideoHeight(),
- static_cast<int>(player->GetDuration().InMilliseconds()),
- player->CanPause(),player->CanSeekForward(), player->CanSeekBackward());
- }
-}
-
-bool ContentVideoView::IsPlaying(JNIEnv*, const JavaParamRef<jobject>& obj) {
- media::MediaPlayerAndroid* player = manager_->GetFullscreenPlayer();
- return player ? player->IsPlaying() : false;
-}
-
-void ContentVideoView::ExitFullscreen(JNIEnv*,
- const JavaParamRef<jobject>&,
- jboolean release_media_player) {
- j_content_video_view_.reset();
- manager_->ExitFullscreen(release_media_player);
-}
-
-void ContentVideoView::SetSurface(JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- const JavaParamRef<jobject>& surface) {
- manager_->SetVideoSurface(
- gfx::ScopedJavaSurface::AcquireExternalSurface(surface));
-}
-
-void ContentVideoView::RequestMediaMetadata(JNIEnv* env,
- const JavaParamRef<jobject>& obj) {
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&ContentVideoView::UpdateMediaMetadata,
- weak_factory_.GetWeakPtr()));
-}
-
-ScopedJavaLocalRef<jobject> ContentVideoView::GetJavaObject(JNIEnv* env) {
- return j_content_video_view_.get(env);
-}
-
-JavaObjectWeakGlobalRef ContentVideoView::CreateJavaObject() {
-
- JNIEnv* env = AttachCurrentThread();
- base::android::ScopedJavaLocalRef<jobject> j_content_view_core;
-
-#if !defined(USE_AURA)
- ContentViewCore* content_view_core = manager_->GetContentViewCore();
- j_content_view_core = content_view_core->GetJavaObject();
-#endif
-
+ base::android::ScopedJavaLocalRef<jobject> j_content_view_core =
+ content_view_core->GetJavaObject();
if (j_content_view_core.is_null())
return JavaObjectWeakGlobalRef(env, nullptr);
diff --git a/chromium/content/browser/android/content_video_view.h b/chromium/content/browser/android/content_video_view.h
index 7959cd60880..292f818d927 100644
--- a/chromium/content/browser/android/content_video_view.h
+++ b/chromium/content/browser/android/content_video_view.h
@@ -10,60 +10,69 @@
#include "base/android/jni_weak_ref.h"
#include "base/android/scoped_java_ref.h"
#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
-#include "ui/gfx/native_widget_types.h"
+#include "content/public/browser/android/content_view_core.h"
+#include "ui/gl/android/scoped_java_surface.h"
namespace content {
-class BrowserMediaPlayerManager;
-
// Native mirror of ContentVideoView.java. This class is responsible for
-// creating the Java video view and pass all the player status change to
-// it. It accepts media control from Java class, and forwards it to
-// MediaPlayerManagerImpl.
+// creating the Java video view and passing changes in player status to it.
+// This class must be used on the UI thread.
class ContentVideoView {
public:
- // Construct a ContentVideoView object. The |manager| will handle all the
- // playback controls from the Java class.
- explicit ContentVideoView(BrowserMediaPlayerManager* manager);
+ static bool RegisterContentVideoView(JNIEnv* env);
+
+ // Returns the singleton object or NULL.
+ static ContentVideoView* GetInstance();
+
+ class Client {
+ public:
+ Client() {}
+ // For receiving notififcations when the SurfaceView surface is created and
+ // destroyed. When |surface.IsEmpty()| the surface was destroyed and
+ // the client should not hold any references to it once this returns.
+ virtual void SetVideoSurface(gfx::ScopedJavaSurface surface) = 0;
+ // Called after the ContentVideoView has been hidden because we're exiting
+ // fullscreen.
+ virtual void DidExitFullscreen(bool release_media_player) = 0;
+
+ protected:
+ ~Client() {}
+
+ DISALLOW_COPY_AND_ASSIGN(Client);
+ };
+
+ explicit ContentVideoView(Client* client, ContentViewCore* content_view_core);
~ContentVideoView();
// To open another video on existing ContentVideoView.
void OpenVideo();
- static bool RegisterContentVideoView(JNIEnv* env);
- static void KeepScreenOn(bool screen_on);
+ // Display an error dialog to the user.
+ void OnMediaPlayerError(int error_type);
- // Return the singleton object or NULL.
- static ContentVideoView* GetInstance();
+ // Update the video size. The video will not be visible until this is called.
+ void OnVideoSizeChanged(int width, int height);
- // Getter method called by the Java class to get the media information.
- bool IsPlaying(JNIEnv*, const base::android::JavaParamRef<jobject>& obj);
- void RequestMediaMetadata(JNIEnv*,
- const base::android::JavaParamRef<jobject>& obj);
+ // Exit fullscreen and notify |client_| with |DidExitFullscreen|.
+ void ExitFullscreen();
- // Called when the Java fullscreen view is destroyed. If
- // |release_media_player| is true, |manager_| needs to release the player
- // as we are quitting the app.
- void ExitFullscreen(JNIEnv*,
- const base::android::JavaParamRef<jobject>&,
- jboolean release_media_player);
+ // Returns the corresponding ContentVideoView Java object if any.
+ base::android::ScopedJavaLocalRef<jobject> GetJavaObject(JNIEnv* env);
- // Called by the Java class to pass the surface object to the player.
- void SetSurface(JNIEnv*,
+ // Called by the Java class when the surface changes.
+ void SetSurface(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
const base::android::JavaParamRef<jobject>& surface);
- // Method called by |manager_| to inform the Java class about player status
- // change.
- void UpdateMediaMetadata();
- void OnMediaPlayerError(int errorType);
- void OnVideoSizeChanged(int width, int height);
- void OnPlaybackComplete();
- void OnExitFullscreen();
+ // Called when the Java fullscreen view is destroyed. If
+ // |release_media_player| is true, |client_| needs to release the player
+ // as we are quitting the app.
+ void DidExitFullscreen(JNIEnv*,
+ const base::android::JavaParamRef<jobject>&,
+ jboolean release_media_player);
// Functions called to record fullscreen playback UMA metrics.
void RecordFullscreenPlayback(JNIEnv*,
@@ -77,18 +86,13 @@ class ContentVideoView {
long playback_duration_in_milliseconds_before_orientation_change,
long playback_duration_in_milliseconds_after_orientation_change);
- // Return the corresponing ContentVideoView Java object if any.
- base::android::ScopedJavaLocalRef<jobject> GetJavaObject(JNIEnv* env);
-
private:
// Creates the corresponding ContentVideoView Java object.
- JavaObjectWeakGlobalRef CreateJavaObject();
+ JavaObjectWeakGlobalRef CreateJavaObject(ContentViewCore* content_view_core);
- // Object that manages the fullscreen media player. It is responsible for
- // handling all the playback controls.
- BrowserMediaPlayerManager* manager_;
+ Client* client_;
- // Weak reference of corresponding Java object.
+ // Weak reference to corresponding Java object.
JavaObjectWeakGlobalRef j_content_video_view_;
// Weak pointer for posting tasks.
diff --git a/chromium/content/browser/android/content_view_core_impl.cc b/chromium/content/browser/android/content_view_core_impl.cc
index 965c21e95f0..2322e763408 100644
--- a/chromium/content/browser/android/content_view_core_impl.cc
+++ b/chromium/content/browser/android/content_view_core_impl.cc
@@ -19,6 +19,7 @@
#include "cc/layers/layer.h"
#include "cc/layers/solid_color_layer.h"
#include "cc/output/begin_frame_args.h"
+#include "cc/output/viewport_selection_bound.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/android/gesture_event_type.h"
#include "content/browser/android/interstitial_page_delegate_android.h"
@@ -55,6 +56,7 @@
#include "ui/android/view_android.h"
#include "ui/android/window_android.h"
#include "ui/events/android/motion_event_android.h"
+#include "ui/events/blink/blink_event_util.h"
#include "ui/gfx/android/java_bitmap.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
@@ -212,7 +214,7 @@ ContentViewCoreImpl::ContentViewCoreImpl(
: WebContentsObserver(web_contents),
java_ref_(env, obj),
web_contents_(static_cast<WebContentsImpl*>(web_contents)),
- root_layer_(cc::SolidColorLayer::Create(Compositor::LayerSettings())),
+ root_layer_(cc::SolidColorLayer::Create()),
page_scale_(1),
dpi_scale_(ui::GetScaleFactorForNativeView(this)),
window_android_(window_android),
@@ -247,8 +249,22 @@ ContentViewCoreImpl::ContentViewCoreImpl(
InitWebContents();
}
+void ContentViewCoreImpl::AddObserver(
+ ContentViewCoreImplObserver* observer) {
+ observer_list_.AddObserver(observer);
+}
+
+void ContentViewCoreImpl::RemoveObserver(
+ ContentViewCoreImplObserver* observer) {
+ observer_list_.RemoveObserver(observer);
+}
+
ContentViewCoreImpl::~ContentViewCoreImpl() {
root_layer_->RemoveFromParent();
+ FOR_EACH_OBSERVER(ContentViewCoreImplObserver,
+ observer_list_,
+ OnContentViewCoreDestroyed());
+ observer_list_.Clear();
JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
@@ -259,6 +275,24 @@ ContentViewCoreImpl::~ContentViewCoreImpl() {
}
}
+void ContentViewCoreImpl::UpdateWindowAndroid(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jlong window_android) {
+ if (window_android) {
+ DCHECK(!window_android_);
+ window_android_ = reinterpret_cast<ui::WindowAndroid*>(window_android);
+ FOR_EACH_OBSERVER(ContentViewCoreImplObserver,
+ observer_list_,
+ OnAttachedToWindow());
+ } else {
+ FOR_EACH_OBSERVER(ContentViewCoreImplObserver,
+ observer_list_,
+ OnDetachedFromWindow());
+ window_android_ = NULL;
+ }
+}
+
base::android::ScopedJavaLocalRef<jobject>
ContentViewCoreImpl::GetWebContentsAndroid(JNIEnv* env,
const JavaParamRef<jobject>& obj) {
@@ -387,10 +421,11 @@ void ContentViewCoreImpl::UpdateFrameInfo(
const gfx::SizeF& viewport_size,
const gfx::Vector2dF& controls_offset,
const gfx::Vector2dF& content_offset,
- bool is_mobile_optimized_hint) {
+ bool is_mobile_optimized_hint,
+ const cc::ViewportSelectionBound& selection_start) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj = java_ref_.get(env);
- if (obj.is_null())
+ if (obj.is_null() || !window_android_)
return;
window_android_->set_content_offset(
@@ -398,6 +433,18 @@ void ContentViewCoreImpl::UpdateFrameInfo(
page_scale_ = page_scale_factor;
+ // The CursorAnchorInfo API in Android only supports zero width selection
+ // bounds.
+ const jboolean has_insertion_marker =
+ selection_start.type == cc::SELECTION_BOUND_CENTER;
+ const jboolean is_insertion_marker_visible = selection_start.visible;
+ const jfloat insertion_marker_horizontal =
+ has_insertion_marker ? selection_start.edge_top.x() : 0.0f;
+ const jfloat insertion_marker_top =
+ has_insertion_marker ? selection_start.edge_top.y() : 0.0f;
+ const jfloat insertion_marker_bottom =
+ has_insertion_marker ? selection_start.edge_bottom.y() : 0.0f;
+
Java_ContentViewCore_updateFrameInfo(
env, obj.obj(),
scroll_offset.x(),
@@ -411,7 +458,12 @@ void ContentViewCoreImpl::UpdateFrameInfo(
viewport_size.height(),
controls_offset.y(),
content_offset.y(),
- is_mobile_optimized_hint);
+ is_mobile_optimized_hint,
+ has_insertion_marker,
+ is_insertion_marker_visible,
+ insertion_marker_horizontal,
+ insertion_marker_top,
+ insertion_marker_bottom);
}
void ContentViewCoreImpl::SetTitle(const base::string16& title) {
@@ -718,6 +770,22 @@ ScopedJavaLocalRef<jobject> ContentViewCoreImpl::GetContext() const {
return Java_ContentViewCore_getContext(env, obj.obj());
}
+gfx::Size ContentViewCoreImpl::GetViewSizeWithOSKHidden() const {
+ gfx::Size size_pix;
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> j_obj = java_ref_.get(env);
+ if (j_obj.is_null())
+ return size_pix = gfx::Size();
+ size_pix = gfx::Size(
+ Java_ContentViewCore_getViewportWidthPix(env, j_obj.obj()),
+ Java_ContentViewCore_getViewportHeightWithOSKHiddenPix(env, j_obj.obj()));
+
+ gfx::Size size_dip = gfx::ScaleToCeiledSize(size_pix, 1.0f / dpi_scale());
+ if (DoTopControlsShrinkBlinkSize())
+ size_dip.Enlarge(0, -GetTopControlsHeightDip());
+ return size_dip;
+}
+
gfx::Size ContentViewCoreImpl::GetViewSize() const {
gfx::Size size = GetViewportSizeDip();
if (DoTopControlsShrinkBlinkSize())
@@ -949,7 +1017,8 @@ jboolean ContentViewCoreImpl::SendMouseMoveEvent(
const JavaParamRef<jobject>& obj,
jlong time_ms,
jfloat x,
- jfloat y) {
+ jfloat y,
+ jint tool_type) {
RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
if (!rwhv)
return false;
@@ -957,7 +1026,8 @@ jboolean ContentViewCoreImpl::SendMouseMoveEvent(
blink::WebMouseEvent event = WebMouseEventBuilder::Build(
WebInputEvent::MouseMove,
blink::WebMouseEvent::ButtonNone,
- time_ms / 1000.0, x / dpi_scale(), y / dpi_scale(), 0, 1);
+ time_ms / 1000.0, x / dpi_scale(), y / dpi_scale(), 0, 1,
+ ui::ToWebPointerType(static_cast<ui::MotionEvent::ToolType>(tool_type)));
rwhv->SendMouseEvent(event);
return true;
@@ -1154,15 +1224,6 @@ void ContentViewCoreImpl::SelectBetweenCoordinates(
gfx::PointF(x2 / dpi_scale(), y2 / dpi_scale()));
}
-void ContentViewCoreImpl::MoveCaret(JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- jfloat x,
- jfloat y) {
- RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
- if (rwhv)
- rwhv->MoveCaret(gfx::Point(x / dpi_scale_, y / dpi_scale_));
-}
-
void ContentViewCoreImpl::DismissTextHandles(JNIEnv* env,
const JavaParamRef<jobject>& obj) {
RenderWidgetHostViewAndroid* rwhv = GetRenderWidgetHostViewAndroid();
@@ -1239,9 +1300,7 @@ void ContentViewCoreImpl::WasResized(JNIEnv* env,
root_layer_->SetBounds(physical_size);
if (view) {
- RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
- view->GetRenderWidgetHost());
- host->SendScreenRects();
+ web_contents_->SendScreenRects();
view->WasResized();
}
}
@@ -1431,10 +1490,6 @@ void ContentViewCoreImpl::OnShowUnhandledTapUIIfNeeded(int x_dip, int y_dip) {
static_cast<jint>(y_dip * dpi_scale()));
}
-float ContentViewCoreImpl::GetScaleFactor() const {
- return page_scale_ * dpi_scale_;
-}
-
void ContentViewCoreImpl::OnSmartClipDataExtracted(
const base::string16& text,
const base::string16& html,
diff --git a/chromium/content/browser/android/content_view_core_impl.h b/chromium/content/browser/android/content_view_core_impl.h
index 2e0b22694ee..31635faca33 100644
--- a/chromium/content/browser/android/content_view_core_impl.h
+++ b/chromium/content/browser/android/content_view_core_impl.h
@@ -16,6 +16,7 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/process/process.h"
+#include "content/browser/android/content_view_core_impl_observer.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/android/content_view_core.h"
@@ -27,6 +28,10 @@
#include "ui/gfx/geometry/rect_f.h"
#include "url/gurl.h"
+namespace cc {
+struct ViewportSelectionBound;
+}
+
namespace ui {
class WindowAndroid;
}
@@ -69,6 +74,9 @@ class ContentViewCoreImpl : public ContentViewCore,
int start_offset,
int end_offset)>& callback) override;
+ void AddObserver(ContentViewCoreImplObserver* observer);
+ void RemoveObserver(ContentViewCoreImplObserver* observer);
+
// ViewAndroid implementation
base::android::ScopedJavaLocalRef<jobject> GetViewAndroidDelegate()
const override;
@@ -84,6 +92,9 @@ class ContentViewCoreImpl : public ContentViewCore,
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
+ void UpdateWindowAndroid(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jlong window_android);
void OnJavaContentViewCoreDestroyed(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
@@ -134,7 +145,8 @@ class ContentViewCoreImpl : public ContentViewCore,
const base::android::JavaParamRef<jobject>& obj,
jlong time_ms,
jfloat x,
- jfloat y);
+ jfloat y,
+ jint tool_type);
jboolean SendMouseWheelEvent(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jlong time_ms,
@@ -207,10 +219,6 @@ class ContentViewCoreImpl : public ContentViewCore,
jfloat y1,
jfloat x2,
jfloat y2);
- void MoveCaret(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
- jfloat x,
- jfloat y);
void DismissTextHandles(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
void SetTextHandlesTemporarilyHidden(
@@ -236,7 +244,6 @@ class ContentViewCoreImpl : public ContentViewCore,
jboolean focused);
jint GetBackgroundColor(JNIEnv* env, jobject obj);
- void SetBackgroundColor(JNIEnv* env, jobject obj, jint color);
void SetAllowJavascriptInterfacesInspection(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
@@ -313,7 +320,8 @@ class ContentViewCoreImpl : public ContentViewCore,
const gfx::SizeF& viewport_size,
const gfx::Vector2dF& controls_offset,
const gfx::Vector2dF& content_offset,
- bool is_mobile_optimized_hint);
+ bool is_mobile_optimized_hint,
+ const cc::ViewportSelectionBound& selection_start);
void ForceUpdateImeAdapter(long native_ime_adapter);
void UpdateImeAdapter(long native_ime_adapter,
@@ -363,6 +371,8 @@ class ContentViewCoreImpl : public ContentViewCore,
// Returns the viewport size after accounting for the viewport offset.
gfx::Size GetViewSize() const;
+ gfx::Size GetViewSizeWithOSKHidden() const;
+
void SetAccessibilityEnabledInternal(bool enabled);
bool IsFullscreenRequiredForOrientationLock() const;
@@ -386,8 +396,6 @@ class ContentViewCoreImpl : public ContentViewCore,
void OnShowUnhandledTapUIIfNeeded(int x_dip, int y_dip);
- // returns page density (dpi) X page scale
- float GetScaleFactor() const;
private:
class ContentViewUserData;
@@ -454,6 +462,9 @@ class ContentViewCoreImpl : public ContentViewCore,
// The owning window that has a hold of main application activity.
ui::WindowAndroid* window_android_;
+ // Observer to notify of lifecyle changes.
+ base::ObserverList<ContentViewCoreImplObserver> observer_list_;
+
// The cache of device's current orientation set from Java side, this value
// will be sent to Renderer once it is ready.
int device_orientation_;
diff --git a/chromium/content/browser/android/content_view_core_impl_observer.h b/chromium/content/browser/android/content_view_core_impl_observer.h
new file mode 100644
index 00000000000..d27735e9dc0
--- /dev/null
+++ b/chromium/content/browser/android/content_view_core_impl_observer.h
@@ -0,0 +1,22 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_ANDROID_CONTENT_VIEW_CORE_IMPL_OBSERVER_H
+#define CONTENT_BROWSER_ANDROID_CONTENT_VIEW_CORE_IMPL_OBSERVER_H
+
+namespace content {
+
+class ContentViewCoreImplObserver {
+ public:
+ virtual void OnContentViewCoreDestroyed() = 0;
+ virtual void OnAttachedToWindow() = 0;
+ virtual void OnDetachedFromWindow() = 0;
+
+ protected:
+ virtual ~ContentViewCoreImplObserver() {}
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_CONTENT_VIEW_CORE_IMPL_OBSERVER_H
diff --git a/chromium/content/browser/android/content_view_render_view.cc b/chromium/content/browser/android/content_view_render_view.cc
index 24fdbc2f020..be3064e05eb 100644
--- a/chromium/content/browser/android/content_view_render_view.cc
+++ b/chromium/content/browser/android/content_view_render_view.cc
@@ -99,14 +99,7 @@ void ContentViewRenderView::SetOverlayVideoMode(
const JavaParamRef<jobject>& obj,
bool enabled) {
compositor_->SetHasTransparentBackground(enabled);
- SetNeedsComposite(env, obj);
-}
-
-void ContentViewRenderView::SetNeedsComposite(
- JNIEnv* env,
- const JavaParamRef<jobject>& obj) {
- if (compositor_)
- compositor_->SetNeedsComposite();
+ compositor_->SetNeedsComposite();
}
void ContentViewRenderView::UpdateLayerTreeHost() {
@@ -124,11 +117,4 @@ void ContentViewRenderView::InitCompositor() {
compositor_.reset(Compositor::Create(this, root_window_));
}
-jlong ContentViewRenderView::GetUIResourceProvider(
- JNIEnv* env,
- const JavaParamRef<jobject>& obj) {
- if (!compositor_)
- return 0;
- return reinterpret_cast<intptr_t>(&compositor_->GetUIResourceProvider());
-}
} // 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 c571de0fd4e..50f3b9c4f83 100644
--- a/chromium/content/browser/android/content_view_render_view.h
+++ b/chromium/content/browser/android/content_view_render_view.h
@@ -48,13 +48,6 @@ class ContentViewRenderView : public CompositorClient {
void SetOverlayVideoMode(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
bool enabled);
- void SetNeedsComposite(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj);
-
- // TODO(yusufo): Remove this once the compositor code is
- // refactored to use a unified system.
- jlong GetUIResourceProvider(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj);
// CompositorClient implementation
void UpdateLayerTreeHost() override;
diff --git a/chromium/content/browser/android/download_controller_android_impl.cc b/chromium/content/browser/android/download_controller_android_impl.cc
index feb8de30152..768a599f6bd 100644
--- a/chromium/content/browser/android/download_controller_android_impl.cc
+++ b/chromium/content/browser/android/download_controller_android_impl.cc
@@ -32,6 +32,7 @@
#include "content/public/common/content_client.h"
#include "content/public/common/referrer.h"
#include "jni/DownloadController_jni.h"
+#include "net/base/filename_util.h"
#include "net/cookies/cookie_options.h"
#include "net/cookies/cookie_store.h"
#include "net/http/http_content_disposition.h"
@@ -97,6 +98,17 @@ void CreateContextMenuDownload(int render_process_id,
dlm->DownloadUrl(std::move(dl_params));
}
+// Check if an interrupted download item can be auto resumed.
+bool IsInterruptedDownloadAutoResumable(content::DownloadItem* download_item) {
+ int interrupt_reason = download_item->GetLastReason();
+ DCHECK_NE(interrupt_reason, content::DOWNLOAD_INTERRUPT_REASON_NONE);
+ return
+ interrupt_reason == content::DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT ||
+ interrupt_reason == content::DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED ||
+ interrupt_reason ==
+ content::DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED;
+}
+
} // namespace
namespace content {
@@ -211,6 +223,11 @@ void DownloadControllerAndroidImpl::AcquireFileAccessPermission(
env, GetJavaObject()->Controller(env).obj(), view.obj(), callback_id);
}
+void DownloadControllerAndroidImpl::SetDefaultDownloadFileName(
+ const std::string& file_name) {
+ default_file_name_ = file_name;
+}
+
bool DownloadControllerAndroidImpl::HasFileAccessPermission(
ScopedJavaLocalRef<jobject> j_content_view_core) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -222,7 +239,8 @@ bool DownloadControllerAndroidImpl::HasFileAccessPermission(
}
void DownloadControllerAndroidImpl::CreateGETDownload(
- int render_process_id, int render_view_id, int request_id) {
+ int render_process_id, int render_view_id, int request_id,
+ bool must_download) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
GlobalRequestID global_id(render_process_id, request_id);
@@ -232,7 +250,7 @@ void DownloadControllerAndroidImpl::CreateGETDownload(
GetDownloadInfoCB cb = base::Bind(
&DownloadControllerAndroidImpl::StartAndroidDownload,
base::Unretained(this), render_process_id,
- render_view_id);
+ render_view_id, must_download);
PrepareDownloadInfo(
global_id,
@@ -326,7 +344,7 @@ void DownloadControllerAndroidImpl::StartDownloadOnUIThread(
}
void DownloadControllerAndroidImpl::StartAndroidDownload(
- int render_process_id, int render_view_id,
+ int render_process_id, int render_view_id, bool must_download,
const DownloadInfoAndroid& info) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -346,7 +364,7 @@ void DownloadControllerAndroidImpl::StartAndroidDownload(
web_contents,
base::Bind(&DownloadControllerAndroidImpl::StartAndroidDownload,
base::Unretained(this), render_process_id, render_view_id,
- info)));
+ must_download, info)));
return;
}
@@ -354,11 +372,11 @@ void DownloadControllerAndroidImpl::StartAndroidDownload(
web_contents,
base::Bind(&DownloadControllerAndroidImpl::StartAndroidDownloadInternal,
base::Unretained(this), render_process_id, render_view_id,
- info));
+ must_download, info));
}
void DownloadControllerAndroidImpl::StartAndroidDownloadInternal(
- int render_process_id, int render_view_id,
+ int render_process_id, int render_view_id, bool must_download,
const DownloadInfoAndroid& info, bool allowed) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!allowed)
@@ -388,17 +406,20 @@ void DownloadControllerAndroidImpl::StartAndroidDownloadInternal(
ScopedJavaLocalRef<jstring> jreferer =
ConvertUTF8ToJavaString(env, info.referer);
- // Try parsing the content disposition header to get a
- // explicitly specified filename if available.
- net::HttpContentDisposition header(info.content_disposition, "");
+ // net::GetSuggestedFilename will fallback to "download" as filename.
ScopedJavaLocalRef<jstring> jfilename =
- ConvertUTF8ToJavaString(env, header.filename());
+ base::android::ConvertUTF16ToJavaString(
+ env, net::GetSuggestedFilename(info.url, info.content_disposition,
+ std::string(), // referrer_charset
+ std::string(), // suggested_name
+ info.original_mime_type,
+ default_file_name_));
Java_DownloadController_newHttpGetDownload(
env, GetJavaObject()->Controller(env).obj(), view.obj(), jurl.obj(),
juser_agent.obj(), jcontent_disposition.obj(), jmime_type.obj(),
jcookie.obj(), jreferer.obj(), info.has_user_gesture, jfilename.obj(),
- info.total_bytes);
+ info.total_bytes, must_download);
}
void DownloadControllerAndroidImpl::OnDownloadStarted(
@@ -433,6 +454,8 @@ void DownloadControllerAndroidImpl::OnDownloadUpdated(DownloadItem* item) {
OnDangerousDownload(item);
JNIEnv* env = base::android::AttachCurrentThread();
+ ScopedJavaLocalRef<jstring> jguid =
+ ConvertUTF8ToJavaString(env, item->GetGuid());
ScopedJavaLocalRef<jstring> jurl =
ConvertUTF8ToJavaString(env, item->GetURL().spec());
ScopedJavaLocalRef<jstring> jmime_type =
@@ -441,17 +464,22 @@ void DownloadControllerAndroidImpl::OnDownloadUpdated(DownloadItem* item) {
ConvertUTF8ToJavaString(env, item->GetTargetFilePath().value());
ScopedJavaLocalRef<jstring> jfilename = ConvertUTF8ToJavaString(
env, item->GetTargetFilePath().BaseName().value());
+ ScopedJavaLocalRef<jstring> joriginal_url =
+ ConvertUTF8ToJavaString(env, item->GetOriginalUrl().spec());
+ ScopedJavaLocalRef<jstring> jreferrer_url =
+ ConvertUTF8ToJavaString(env, item->GetReferrerUrl().spec());
switch (item->GetState()) {
case DownloadItem::IN_PROGRESS: {
base::TimeDelta time_delta;
item->TimeRemaining(&time_delta);
Java_DownloadController_onDownloadUpdated(
- env, GetJavaObject()->Controller(env).obj(),
- base::android::GetApplicationContext(), jurl.obj(), jmime_type.obj(),
- jfilename.obj(), jpath.obj(), item->GetReceivedBytes(), true,
- item->GetId(), item->PercentComplete(), time_delta.InMilliseconds(),
- item->HasUserGesture());
+ env, GetJavaObject()->Controller(env).obj(), jurl.obj(),
+ jmime_type.obj(), jfilename.obj(), jpath.obj(),
+ item->GetReceivedBytes(), item->GetId(), jguid.obj(),
+ item->PercentComplete(), time_delta.InMilliseconds(),
+ item->HasUserGesture(), item->IsPaused(),
+ item->GetBrowserContext()->IsOffTheRecord());
break;
}
case DownloadItem::COMPLETE:
@@ -461,22 +489,27 @@ void DownloadControllerAndroidImpl::OnDownloadUpdated(DownloadItem* item) {
// Call onDownloadCompleted
Java_DownloadController_onDownloadCompleted(
- env, GetJavaObject()->Controller(env).obj(),
- base::android::GetApplicationContext(), jurl.obj(), jmime_type.obj(),
- jfilename.obj(), jpath.obj(), item->GetReceivedBytes(), true,
- item->GetId(), item->HasUserGesture());
+ env, GetJavaObject()->Controller(env).obj(), jurl.obj(),
+ jmime_type.obj(), jfilename.obj(), jpath.obj(),
+ item->GetReceivedBytes(), item->GetId(), jguid.obj(),
+ joriginal_url.obj(), jreferrer_url.obj(), item->HasUserGesture());
break;
case DownloadItem::CANCELLED:
- // TODO(shashishekhar): An interrupted download can be resumed. Android
- // currently does not support resumable downloads. Add handling for
- // interrupted case based on item->CanResume().
+ Java_DownloadController_onDownloadCancelled(
+ env, GetJavaObject()->Controller(env).obj(), item->GetId(),
+ jguid.obj());
+ break;
case DownloadItem::INTERRUPTED:
- // Call onDownloadCompleted with success = false.
- Java_DownloadController_onDownloadCompleted(
- env, GetJavaObject()->Controller(env).obj(),
- base::android::GetApplicationContext(), jurl.obj(), jmime_type.obj(),
- jfilename.obj(), jpath.obj(), item->GetReceivedBytes(), false,
- item->GetId(), item->HasUserGesture());
+ // When device loses/changes network, we get a NETWORK_TIMEOUT,
+ // NETWORK_FAILED or NETWORK_DISCONNECTED error. Download should auto
+ // resume in this case.
+ Java_DownloadController_onDownloadInterrupted(
+ env, GetJavaObject()->Controller(env).obj(), jurl.obj(),
+ jmime_type.obj(), jfilename.obj(), jpath.obj(),
+ item->GetReceivedBytes(), item->GetId(), jguid.obj(),
+ item->CanResume(), IsInterruptedDownloadAutoResumable(item),
+ item->GetBrowserContext()->IsOffTheRecord());
+ item->RemoveObserver(this);
break;
case DownloadItem::MAX_DOWNLOAD_STATE:
NOTREACHED();
@@ -487,12 +520,14 @@ void DownloadControllerAndroidImpl::OnDangerousDownload(DownloadItem* item) {
JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jstring> jfilename = ConvertUTF8ToJavaString(
env, item->GetTargetFilePath().BaseName().value());
+ ScopedJavaLocalRef<jstring> jguid =
+ ConvertUTF8ToJavaString(env, item->GetGuid());
ScopedJavaLocalRef<jobject> view_core = GetContentViewCoreFromWebContents(
item->GetWebContents());
if (!view_core.is_null()) {
Java_DownloadController_onDangerousDownload(
env, GetJavaObject()->Controller(env).obj(), view_core.obj(),
- jfilename.obj(), item->GetId());
+ jfilename.obj(), jguid.obj());
}
}
@@ -532,12 +567,14 @@ void DownloadControllerAndroidImpl::StartContextMenuDownload(
}
void DownloadControllerAndroidImpl::DangerousDownloadValidated(
- WebContents* web_contents, int download_id, bool accept) {
+ WebContents* web_contents,
+ const std::string& download_guid,
+ bool accept) {
if (!web_contents)
return;
DownloadManagerImpl* dlm = static_cast<DownloadManagerImpl*>(
BrowserContext::GetDownloadManager(web_contents->GetBrowserContext()));
- DownloadItem* item = dlm->GetDownload(download_id);
+ DownloadItem* item = dlm->GetDownloadByGuid(download_guid);
if (!item)
return;
if (accept)
diff --git a/chromium/content/browser/android/download_controller_android_impl.h b/chromium/content/browser/android/download_controller_android_impl.h
index 36c108e349d..157f306300d 100644
--- a/chromium/content/browser/android/download_controller_android_impl.h
+++ b/chromium/content/browser/android/download_controller_android_impl.h
@@ -30,7 +30,6 @@
#include "base/memory/scoped_vector.h"
#include "base/memory/singleton.h"
#include "content/public/browser/android/download_controller_android.h"
-#include "content/public/browser/download_item.h"
#include "net/cookies/cookie_monster.h"
#include "url/gurl.h"
@@ -44,8 +43,7 @@ class DeferredDownloadObserver;
class RenderViewHost;
class WebContents;
-class DownloadControllerAndroidImpl : public DownloadControllerAndroid,
- public DownloadItem::Observer {
+class DownloadControllerAndroidImpl : public DownloadControllerAndroid {
public:
static DownloadControllerAndroidImpl* GetInstance();
@@ -61,6 +59,7 @@ class DownloadControllerAndroidImpl : public DownloadControllerAndroid,
void AcquireFileAccessPermission(
WebContents* web_contents,
const AcquireFileAccessPermissionCallback& callback) override;
+ void SetDefaultDownloadFileName(const std::string& file_name) override;
private:
// Used to store all the information about an Android download.
@@ -96,14 +95,15 @@ class DownloadControllerAndroidImpl : public DownloadControllerAndroid,
// DownloadControllerAndroid implementation.
void CreateGETDownload(int render_process_id,
int render_view_id,
- int request_id) override;
+ int request_id,
+ bool must_download) override;
void OnDownloadStarted(DownloadItem* download_item) override;
void StartContextMenuDownload(const ContextMenuParams& params,
WebContents* web_contents,
bool is_link,
const std::string& extra_headers) override;
void DangerousDownloadValidated(WebContents* web_contents,
- int download_id,
+ const std::string& download_guid,
bool accept) override;
// DownloadItem::Observer interface.
@@ -127,9 +127,11 @@ class DownloadControllerAndroidImpl : public DownloadControllerAndroid,
const DownloadInfoAndroid& info);
void StartAndroidDownload(int render_process_id,
int render_view_id,
+ bool must_download,
const DownloadInfoAndroid& info);
void StartAndroidDownloadInternal(int render_process_id,
int render_view_id,
+ bool must_download,
const DownloadInfoAndroid& info,
bool allowed);
@@ -144,6 +146,8 @@ class DownloadControllerAndroidImpl : public DownloadControllerAndroid,
JavaObject* java_object_;
+ std::string default_file_name_;
+
ScopedVector<DeferredDownloadObserver> deferred_downloads_;
DISALLOW_COPY_AND_ASSIGN(DownloadControllerAndroidImpl);
diff --git a/chromium/content/browser/android/in_process/context_provider_in_process.cc b/chromium/content/browser/android/in_process/context_provider_in_process.cc
index 9f4fbc2d827..e7cbb65e0f2 100644
--- a/chromium/content/browser/android/in_process/context_provider_in_process.cc
+++ b/chromium/content/browser/android/in_process/context_provider_in_process.cc
@@ -11,7 +11,7 @@
#include "base/callback_helpers.h"
#include "base/strings/stringprintf.h"
#include "cc/output/managed_memory_policy.h"
-#include "content/common/gpu/client/grcontext_for_webgraphicscontext3d.h"
+#include "content/common/gpu/client/grcontext_for_gles2_interface.h"
#include "gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "third_party/skia/include/gpu/GrContext.h"
@@ -25,11 +25,11 @@ class ContextProviderInProcess::LostContextCallbackProxy
public:
explicit LostContextCallbackProxy(ContextProviderInProcess* provider)
: provider_(provider) {
- provider_->WebContext3DImpl()->setContextLostCallback(this);
+ provider_->context3d_->setContextLostCallback(this);
}
~LostContextCallbackProxy() override {
- provider_->WebContext3DImpl()->setContextLostCallback(NULL);
+ provider_->context3d_->setContextLostCallback(nullptr);
}
void onContextLost() override {
@@ -45,19 +45,16 @@ scoped_refptr<ContextProviderInProcess> ContextProviderInProcess::Create(
scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> context3d,
const std::string& debug_name) {
if (!context3d)
- return NULL;
+ return nullptr;
return new ContextProviderInProcess(std::move(context3d), debug_name);
}
ContextProviderInProcess::ContextProviderInProcess(
scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> context3d,
const std::string& debug_name)
- : debug_name_(debug_name) {
+ : context3d_(std::move(context3d)), debug_name_(debug_name) {
DCHECK(main_thread_checker_.CalledOnValidThread());
- DCHECK(context3d);
- gr_interface_ = skia::AdoptRef(
- new GrGLInterfaceForWebGraphicsContext3D(std::move(context3d)));
- DCHECK(gr_interface_->WebContext3D());
+ DCHECK(context3d_);
context_thread_checker_.DetachFromThread();
}
@@ -70,20 +67,11 @@ blink::WebGraphicsContext3D* ContextProviderInProcess::WebContext3D() {
DCHECK(lost_context_callback_proxy_); // Is bound to thread.
DCHECK(context_thread_checker_.CalledOnValidThread());
- return WebContext3DImpl();
-}
-
-gpu_blink::WebGraphicsContext3DInProcessCommandBufferImpl*
- ContextProviderInProcess::WebContext3DImpl() {
- DCHECK(gr_interface_->WebContext3D());
-
- return
- static_cast<gpu_blink::WebGraphicsContext3DInProcessCommandBufferImpl*>(
- gr_interface_->WebContext3D());
+ return context3d_.get();
}
bool ContextProviderInProcess::BindToCurrentThread() {
- DCHECK(WebContext3DImpl());
+ DCHECK(context3d_);
// This is called on the thread the context will be used.
DCHECK(context_thread_checker_.CalledOnValidThread());
@@ -91,16 +79,14 @@ bool ContextProviderInProcess::BindToCurrentThread() {
if (lost_context_callback_proxy_)
return true;
- if (!WebContext3DImpl()->InitializeOnCurrentThread())
+ if (!context3d_->InitializeOnCurrentThread())
return false;
- gr_interface_->BindToCurrentThread();
InitializeCapabilities();
const std::string unique_context_name =
- base::StringPrintf("%s-%p", debug_name_.c_str(), WebContext3DImpl());
- WebContext3DImpl()->traceBeginCHROMIUM("gpu_toplevel",
- unique_context_name.c_str());
+ base::StringPrintf("%s-%p", debug_name_.c_str(), context3d_.get());
+ ContextGL()->TraceBeginCHROMIUM("gpu_toplevel", unique_context_name.c_str());
lost_context_callback_proxy_.reset(new LostContextCallbackProxy(this));
return true;
@@ -111,9 +97,9 @@ void ContextProviderInProcess::DetachFromThread() {
}
void ContextProviderInProcess::InitializeCapabilities() {
- capabilities_.gpu = WebContext3DImpl()->GetImplementation()->capabilities();
+ capabilities_.gpu = context3d_->GetImplementation()->capabilities();
- size_t mapped_memory_limit = WebContext3DImpl()->GetMappedMemoryLimit();
+ size_t mapped_memory_limit = context3d_->GetMappedMemoryLimit();
capabilities_.max_transfer_buffer_usage_bytes =
mapped_memory_limit ==
WebGraphicsContext3DInProcessCommandBufferImpl::kNoLimit
@@ -129,21 +115,21 @@ ContextProviderInProcess::ContextCapabilities() {
}
::gpu::gles2::GLES2Interface* ContextProviderInProcess::ContextGL() {
- DCHECK(WebContext3DImpl());
+ DCHECK(context3d_);
DCHECK(lost_context_callback_proxy_); // Is bound to thread.
DCHECK(context_thread_checker_.CalledOnValidThread());
- return WebContext3DImpl()->GetGLInterface();
+ return context3d_->GetGLInterface();
}
::gpu::ContextSupport* ContextProviderInProcess::ContextSupport() {
- DCHECK(WebContext3DImpl());
+ DCHECK(context3d_);
if (!lost_context_callback_proxy_)
return NULL; // Not bound to anything.
DCHECK(context_thread_checker_.CalledOnValidThread());
- return WebContext3DImpl()->GetContextSupport();
+ return context3d_->GetContextSupport();
}
class GrContext* ContextProviderInProcess::GrContext() {
@@ -153,7 +139,8 @@ class GrContext* ContextProviderInProcess::GrContext() {
if (gr_context_)
return gr_context_->get();
- gr_context_.reset(new GrContextForWebGraphicsContext3D(gr_interface_));
+ gr_context_.reset(
+ new GrContextForGLES2Interface(context3d_->GetGLInterface()));
return gr_context_->get();
}
@@ -166,7 +153,7 @@ void ContextProviderInProcess::InvalidateGrContext(uint32_t state) {
}
void ContextProviderInProcess::SetupLock() {
- WebContext3DImpl()->SetLock(&context_lock_);
+ context3d_->SetLock(&context_lock_);
}
base::Lock* ContextProviderInProcess::GetLock() {
diff --git a/chromium/content/browser/android/in_process/context_provider_in_process.h b/chromium/content/browser/android/in_process/context_provider_in_process.h
index fe24f945003..37f494afcb1 100644
--- a/chromium/content/browser/android/in_process/context_provider_in_process.h
+++ b/chromium/content/browser/android/in_process/context_provider_in_process.h
@@ -14,7 +14,6 @@
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
#include "cc/blink/context_provider_web_context.h"
-#include "skia/ext/refptr.h"
namespace blink { class WebGraphicsContext3D; }
@@ -24,8 +23,7 @@ class WebGraphicsContext3DInProcessCommandBufferImpl;
namespace content {
-class GrContextForWebGraphicsContext3D;
-class GrGLInterfaceForWebGraphicsContext3D;
+class GrContextForGLES2Interface;
class ContextProviderInProcess
: NON_EXPORTED_BASE(public cc_blink::ContextProviderWebContext) {
@@ -45,8 +43,6 @@ class ContextProviderInProcess
// cc_blink::ContextProviderWebContext:
blink::WebGraphicsContext3D* WebContext3D() override;
- gpu_blink::WebGraphicsContext3DInProcessCommandBufferImpl* WebContext3DImpl();
-
// cc::ContextProvider:
bool BindToCurrentThread() override;
void DetachFromThread() override;
@@ -67,8 +63,9 @@ class ContextProviderInProcess
base::ThreadChecker main_thread_checker_;
base::ThreadChecker context_thread_checker_;
- skia::RefPtr<GrGLInterfaceForWebGraphicsContext3D> gr_interface_;
- scoped_ptr<GrContextForWebGraphicsContext3D> gr_context_;
+ scoped_ptr<gpu_blink::WebGraphicsContext3DInProcessCommandBufferImpl>
+ context3d_;
+ scoped_ptr<GrContextForGLES2Interface> gr_context_;
LostContextCallback lost_context_callback_;
diff --git a/chromium/content/browser/android/in_process/synchronous_compositor_factory_impl.cc b/chromium/content/browser/android/in_process/synchronous_compositor_factory_impl.cc
index 628bfccf6a2..4e5f3f132ea 100644
--- a/chromium/content/browser/android/in_process/synchronous_compositor_factory_impl.cc
+++ b/chromium/content/browser/android/in_process/synchronous_compositor_factory_impl.cc
@@ -17,7 +17,6 @@
#include "content/browser/android/in_process/synchronous_compositor_registry_in_proc.h"
#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
-#include "content/common/gpu/client/gpu_channel_host.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
@@ -29,6 +28,7 @@
#include "gpu/command_buffer/client/gl_in_process_context.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/ipc/client/gpu_channel_host.h"
#include "ui/gl/android/surface_texture.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/gl_surface_stub.h"
@@ -46,30 +46,15 @@ struct ContextHolder {
gpu::GLInProcessContext* gl_in_process_context;
};
-blink::WebGraphicsContext3D::Attributes GetDefaultAttribs() {
- blink::WebGraphicsContext3D::Attributes attributes;
- attributes.antialias = false;
- attributes.depth = false;
- attributes.stencil = false;
- attributes.shareResources = true;
- attributes.noAutomaticFlushes = true;
-
- return attributes;
-}
-
ContextHolder CreateContextHolder(
- const blink::WebGraphicsContext3D::Attributes& attributes,
+ const gpu::gles2::ContextCreationAttribHelper& attributes,
scoped_refptr<gpu::InProcessCommandBuffer::Service> service,
- const gpu::GLInProcessContextSharedMemoryLimits& mem_limits,
- bool is_offscreen) {
- gpu::gles2::ContextCreationAttribHelper in_process_attribs;
- WebGraphicsContext3DImpl::ConvertAttributes(attributes, &in_process_attribs);
- in_process_attribs.lose_context_when_out_of_memory = true;
-
+ const gpu::GLInProcessContextSharedMemoryLimits& mem_limits) {
+ bool is_offscreen = true;
scoped_ptr<gpu::GLInProcessContext> context(gpu::GLInProcessContext::Create(
- service, NULL /* surface */, is_offscreen, gfx::kNullAcceleratedWidget,
- gfx::Size(1, 1), NULL /* share_context */, attributes.shareResources,
- in_process_attribs, gfx::PreferDiscreteGpu, mem_limits,
+ service, nullptr /* surface */, is_offscreen, gfx::kNullAcceleratedWidget,
+ gfx::Size(1, 1), nullptr /* share_context */, attributes,
+ gfx::PreferDiscreteGpu, mem_limits,
BrowserGpuMemoryBufferManager::current(), nullptr));
gpu::GLInProcessContext* context_ptr = context.get();
@@ -86,12 +71,58 @@ ContextHolder CreateContextHolder(
} // namespace
-class SynchronousCompositorFactoryImpl::VideoContextProvider
+SynchronousCompositorFactoryImpl::SynchronousCompositorFactoryImpl() {
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSingleProcess)) {
+ // TODO(boliu): Figure out how to deal with this more nicely.
+ SynchronousCompositorFactory::SetInstance(this);
+ }
+}
+
+SynchronousCompositorFactoryImpl::~SynchronousCompositorFactoryImpl() {}
+
+scoped_refptr<base::SingleThreadTaskRunner>
+SynchronousCompositorFactoryImpl::GetCompositorTaskRunner() {
+ return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
+}
+
+scoped_ptr<cc::OutputSurface>
+SynchronousCompositorFactoryImpl::CreateOutputSurface(
+ int routing_id,
+ uint32_t output_surface_id,
+ const scoped_refptr<FrameSwapMessageQueue>& frame_swap_message_queue,
+ const scoped_refptr<cc::ContextProvider>& onscreen_context,
+ const scoped_refptr<cc::ContextProvider>& worker_context) {
+ return make_scoped_ptr(new SynchronousCompositorOutputSurface(
+ onscreen_context, worker_context, routing_id, output_surface_id,
+ SynchronousCompositorRegistryInProc::GetInstance(),
+ frame_swap_message_queue));
+}
+
+InputHandlerManagerClient*
+SynchronousCompositorFactoryImpl::GetInputHandlerManagerClient() {
+ return synchronous_input_event_filter();
+}
+
+SynchronousInputHandlerProxyClient*
+SynchronousCompositorFactoryImpl::GetSynchronousInputHandlerProxyClient() {
+ return synchronous_input_event_filter();
+}
+
+scoped_ptr<cc::BeginFrameSource>
+SynchronousCompositorFactoryImpl::CreateExternalBeginFrameSource(
+ int routing_id) {
+ return make_scoped_ptr(new SynchronousCompositorExternalBeginFrameSource(
+ routing_id, SynchronousCompositorRegistryInProc::GetInstance()));
+}
+
+// SynchronousCompositorStreamTextureFactoryImpl.
+
+class SynchronousCompositorStreamTextureFactoryImpl::VideoContextProvider
: public StreamTextureFactorySynchronousImpl::ContextProvider {
public:
- VideoContextProvider(
- scoped_refptr<cc::ContextProvider> context_provider,
- gpu::GLInProcessContext* gl_in_process_context)
+ VideoContextProvider(scoped_refptr<cc::ContextProvider> context_provider,
+ gpu::GLInProcessContext* gl_in_process_context)
: context_provider_(context_provider),
gl_in_process_context_(gl_in_process_context) {
context_provider_->BindToCurrentThread();
@@ -119,8 +150,7 @@ class SynchronousCompositorFactoryImpl::VideoContextProvider
}
void RestoreContext() {
- FOR_EACH_OBSERVER(StreamTextureFactoryContextObserver,
- observer_list_,
+ FOR_EACH_OBSERVER(StreamTextureFactoryContextObserver, observer_list_,
ResetStreamTextureProxy());
}
@@ -135,87 +165,62 @@ class SynchronousCompositorFactoryImpl::VideoContextProvider
DISALLOW_COPY_AND_ASSIGN(VideoContextProvider);
};
-SynchronousCompositorFactoryImpl::SynchronousCompositorFactoryImpl()
- : num_hardware_compositors_(0) {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kSingleProcess)) {
- // TODO(boliu): Figure out how to deal with this more nicely.
- SynchronousCompositorFactory::SetInstance(this);
- }
-}
-
-SynchronousCompositorFactoryImpl::~SynchronousCompositorFactoryImpl() {}
-
-scoped_refptr<base::SingleThreadTaskRunner>
-SynchronousCompositorFactoryImpl::GetCompositorTaskRunner() {
- return BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI);
-}
-
-scoped_ptr<cc::OutputSurface>
-SynchronousCompositorFactoryImpl::CreateOutputSurface(
- int routing_id,
- const scoped_refptr<FrameSwapMessageQueue>& frame_swap_message_queue,
- const scoped_refptr<cc::ContextProvider>& onscreen_context,
- const scoped_refptr<cc::ContextProvider>& worker_context) {
- return make_scoped_ptr(new SynchronousCompositorOutputSurface(
- onscreen_context, worker_context, routing_id,
- SynchronousCompositorRegistryInProc::GetInstance(),
- frame_swap_message_queue));
-}
+namespace {
+base::LazyInstance<SynchronousCompositorStreamTextureFactoryImpl>::Leaky
+ g_stream_texture_factory = LAZY_INSTANCE_INITIALIZER;
+} // namespace
-InputHandlerManagerClient*
-SynchronousCompositorFactoryImpl::GetInputHandlerManagerClient() {
- return synchronous_input_event_filter();
+// static
+SynchronousCompositorStreamTextureFactoryImpl*
+SynchronousCompositorStreamTextureFactoryImpl::GetInstance() {
+ return g_stream_texture_factory.Pointer();
}
-scoped_ptr<cc::BeginFrameSource>
-SynchronousCompositorFactoryImpl::CreateExternalBeginFrameSource(
- int routing_id) {
- return make_scoped_ptr(new SynchronousCompositorExternalBeginFrameSource(
- routing_id, SynchronousCompositorRegistryInProc::GetInstance()));
-}
+SynchronousCompositorStreamTextureFactoryImpl::
+ SynchronousCompositorStreamTextureFactoryImpl()
+ : num_hardware_compositors_(0) {}
scoped_refptr<StreamTextureFactory>
-SynchronousCompositorFactoryImpl::CreateStreamTextureFactory(int frame_id) {
- scoped_refptr<StreamTextureFactorySynchronousImpl> factory(
- StreamTextureFactorySynchronousImpl::Create(
- base::Bind(
- &SynchronousCompositorFactoryImpl::TryCreateStreamTextureFactory,
- base::Unretained(this)),
- frame_id));
- return factory;
+SynchronousCompositorStreamTextureFactoryImpl::CreateStreamTextureFactory() {
+ return StreamTextureFactorySynchronousImpl::Create(
+ base::Bind(&SynchronousCompositorStreamTextureFactoryImpl::
+ TryCreateStreamTextureFactory,
+ base::Unretained(this)));
}
-void SynchronousCompositorFactoryImpl::CompositorInitializedHardwareDraw() {
+void SynchronousCompositorStreamTextureFactoryImpl::
+ CompositorInitializedHardwareDraw() {
base::AutoLock lock(num_hardware_compositor_lock_);
num_hardware_compositors_++;
if (num_hardware_compositors_ == 1 && main_thread_task_runner_.get()) {
main_thread_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(
- &SynchronousCompositorFactoryImpl::RestoreContextOnMainThread,
- base::Unretained(this)));
+ FROM_HERE, base::Bind(&SynchronousCompositorStreamTextureFactoryImpl::
+ RestoreContextOnMainThread,
+ base::Unretained(this)));
}
}
-void SynchronousCompositorFactoryImpl::CompositorReleasedHardwareDraw() {
+void SynchronousCompositorStreamTextureFactoryImpl::
+ CompositorReleasedHardwareDraw() {
base::AutoLock lock(num_hardware_compositor_lock_);
DCHECK_GT(num_hardware_compositors_, 0u);
num_hardware_compositors_--;
}
-void SynchronousCompositorFactoryImpl::RestoreContextOnMainThread() {
+void SynchronousCompositorStreamTextureFactoryImpl::
+ RestoreContextOnMainThread() {
if (CanCreateMainThreadContext() && video_context_provider_.get())
video_context_provider_->RestoreContext();
}
-bool SynchronousCompositorFactoryImpl::CanCreateMainThreadContext() {
+bool SynchronousCompositorStreamTextureFactoryImpl::
+ CanCreateMainThreadContext() {
base::AutoLock lock(num_hardware_compositor_lock_);
return num_hardware_compositors_ > 0;
}
scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
-SynchronousCompositorFactoryImpl::TryCreateStreamTextureFactory() {
+SynchronousCompositorStreamTextureFactoryImpl::TryCreateStreamTextureFactory() {
{
base::AutoLock lock(num_hardware_compositor_lock_);
main_thread_task_runner_ = base::ThreadTaskRunnerHandle::Get();
@@ -226,20 +231,29 @@ SynchronousCompositorFactoryImpl::TryCreateStreamTextureFactory() {
// |video_context_provider_| to null is also not safe since it makes
// synchronous destruction uncontrolled and possibly deadlock.
if (!CanCreateMainThreadContext()) {
- return
- scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>();
+ return scoped_refptr<
+ StreamTextureFactorySynchronousImpl::ContextProvider>();
}
if (!video_context_provider_.get()) {
DCHECK(android_view_service_.get());
- blink::WebGraphicsContext3D::Attributes attributes = GetDefaultAttribs();
- attributes.shareResources = false;
+ // This is for an offscreen context, so the default framebuffer doesn't need
+ // any alpha, depth, stencil, antialiasing.
+ gpu::gles2::ContextCreationAttribHelper attributes;
+ attributes.alpha_size = -1;
+ attributes.depth_size = 0;
+ attributes.stencil_size = 0;
+ attributes.samples = 0;
+ attributes.sample_buffers = 0;
+ attributes.bind_generates_resource = false;
+ attributes.lose_context_when_out_of_memory = true;
+
// This needs to run in on-screen |android_view_service_| context due to
// SurfaceTexture limitations.
ContextHolder holder =
CreateContextHolder(attributes, android_view_service_,
- gpu::GLInProcessContextSharedMemoryLimits(), false);
+ gpu::GLInProcessContextSharedMemoryLimits());
video_context_provider_ = new VideoContextProvider(
ContextProviderInProcess::Create(std::move(holder.command_buffer),
"Video-Offscreen-main-thread"),
@@ -248,10 +262,15 @@ SynchronousCompositorFactoryImpl::TryCreateStreamTextureFactory() {
return video_context_provider_;
}
-void SynchronousCompositorFactoryImpl::SetDeferredGpuService(
+void SynchronousCompositorStreamTextureFactoryImpl::SetDeferredGpuService(
scoped_refptr<gpu::InProcessCommandBuffer::Service> service) {
DCHECK(!android_view_service_.get());
android_view_service_ = service;
+
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSingleProcess)) {
+ RenderThreadImpl::SetStreamTextureFactory(CreateStreamTextureFactory());
+ }
}
} // namespace content
diff --git a/chromium/content/browser/android/in_process/synchronous_compositor_factory_impl.h b/chromium/content/browser/android/in_process/synchronous_compositor_factory_impl.h
index 03533444a3e..4842e85f30e 100644
--- a/chromium/content/browser/android/in_process/synchronous_compositor_factory_impl.h
+++ b/chromium/content/browser/android/in_process/synchronous_compositor_factory_impl.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_COMPOSITOR_FACTORY_IMPL_H_
#define CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_COMPOSITOR_FACTORY_IMPL_H_
+#include "base/lazy_instance.h"
#include "base/synchronization/lock.h"
#include "cc/blink/context_provider_web_context.h"
#include "content/browser/android/in_process/synchronous_input_event_filter.h"
@@ -40,34 +41,46 @@ class SynchronousCompositorFactoryImpl : public SynchronousCompositorFactory {
override;
scoped_ptr<cc::OutputSurface> CreateOutputSurface(
int routing_id,
+ uint32_t output_surface_id,
const scoped_refptr<FrameSwapMessageQueue>& frame_swap_message_queue,
const scoped_refptr<cc::ContextProvider>& onscreen_context,
const scoped_refptr<cc::ContextProvider>& worker_context) override;
InputHandlerManagerClient* GetInputHandlerManagerClient() override;
+ SynchronousInputHandlerProxyClient* GetSynchronousInputHandlerProxyClient()
+ override;
scoped_ptr<cc::BeginFrameSource> CreateExternalBeginFrameSource(
int routing_id) override;
- scoped_refptr<StreamTextureFactory> CreateStreamTextureFactory(
- int frame_id) override;
SynchronousInputEventFilter* synchronous_input_event_filter() {
return &synchronous_input_event_filter_;
}
+ private:
+ SynchronousInputEventFilter synchronous_input_event_filter_;
+};
+
+class SynchronousCompositorStreamTextureFactoryImpl {
+ public:
+ static SynchronousCompositorStreamTextureFactoryImpl* GetInstance();
+
+ scoped_refptr<StreamTextureFactory> CreateStreamTextureFactory();
void SetDeferredGpuService(
scoped_refptr<gpu::InProcessCommandBuffer::Service> service);
void CompositorInitializedHardwareDraw();
void CompositorReleasedHardwareDraw();
-
private:
- scoped_refptr<cc::ContextProvider> GetSharedWorkerContextProvider();
+ friend struct base::DefaultLazyInstanceTraits<
+ SynchronousCompositorStreamTextureFactoryImpl>;
+
+ SynchronousCompositorStreamTextureFactoryImpl();
+ ~SynchronousCompositorStreamTextureFactoryImpl();
+
bool CanCreateMainThreadContext();
scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
TryCreateStreamTextureFactory();
void RestoreContextOnMainThread();
- SynchronousInputEventFilter synchronous_input_event_filter_;
-
scoped_refptr<gpu::InProcessCommandBuffer::Service> android_view_service_;
class VideoContextProvider;
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 e1791374ed2..f1829890a09 100644
--- a/chromium/content/browser/android/in_process/synchronous_compositor_impl.cc
+++ b/chromium/content/browser/android/in_process/synchronous_compositor_impl.cc
@@ -108,12 +108,6 @@ void SynchronousCompositorImpl::RegisterWithClient() {
synchronous_input_handler_proxy_->SetOnlySynchronouslyAnimateRootFlings(this);
}
-// static
-void SynchronousCompositorImpl::SetGpuServiceInProc(
- scoped_refptr<gpu::InProcessCommandBuffer::Service> service) {
- g_factory.Get().SetDeferredGpuService(service);
-}
-
void SynchronousCompositorImpl::DidInitializeRendererObjects(
SynchronousCompositorOutputSurface* output_surface,
SynchronousCompositorExternalBeginFrameSource* begin_frame_source,
@@ -156,7 +150,7 @@ void SynchronousCompositorImpl::DidDestroyRendererObjects() {
need_animate_input_ = false;
}
-scoped_ptr<cc::CompositorFrame> SynchronousCompositorImpl::DemandDrawHw(
+SynchronousCompositor::Frame SynchronousCompositorImpl::DemandDrawHw(
const gfx::Size& surface_size,
const gfx::Transform& transform,
const gfx::Rect& viewport,
@@ -166,45 +160,48 @@ scoped_ptr<cc::CompositorFrame> SynchronousCompositorImpl::DemandDrawHw(
DCHECK(CalledOnValidThread());
DCHECK(output_surface_);
DCHECK(begin_frame_source_);
- DCHECK(!frame_holder_);
+ DCHECK(!frame_holder_.frame);
output_surface_->DemandDrawHw(surface_size, transform, viewport, clip,
viewport_rect_for_tile_priority,
transform_for_tile_priority);
- if (frame_holder_)
- UpdateFrameMetaData(frame_holder_->metadata);
+ if (frame_holder_.frame)
+ UpdateFrameMetaData(frame_holder_.frame->metadata);
return std::move(frame_holder_);
}
void SynchronousCompositorImpl::ReturnResources(
+ uint32_t output_surface_id,
const cc::CompositorFrameAck& frame_ack) {
DCHECK(CalledOnValidThread());
- output_surface_->ReturnResources(frame_ack);
+ output_surface_->ReturnResources(output_surface_id, frame_ack);
}
bool SynchronousCompositorImpl::DemandDrawSw(SkCanvas* canvas) {
DCHECK(CalledOnValidThread());
DCHECK(output_surface_);
DCHECK(begin_frame_source_);
- DCHECK(!frame_holder_);
+ DCHECK(!frame_holder_.frame);
output_surface_->DemandDrawSw(canvas);
- bool success = !!frame_holder_;
- if (frame_holder_) {
- UpdateFrameMetaData(frame_holder_->metadata);
- frame_holder_.reset();
+ bool success = !!frame_holder_.frame;
+ if (frame_holder_.frame) {
+ UpdateFrameMetaData(frame_holder_.frame->metadata);
+ frame_holder_.frame.reset();
}
return success;
}
-void SynchronousCompositorImpl::SwapBuffers(cc::CompositorFrame* frame) {
- DCHECK(!frame_holder_);
- frame_holder_.reset(new cc::CompositorFrame);
- frame->AssignTo(frame_holder_.get());
+void SynchronousCompositorImpl::SwapBuffers(uint32_t output_surface_id,
+ cc::CompositorFrame* frame) {
+ DCHECK(!frame_holder_.frame);
+ frame_holder_.output_surface_id = output_surface_id;
+ frame_holder_.frame.reset(new cc::CompositorFrame);
+ frame->AssignTo(frame_holder_.frame.get());
}
void SynchronousCompositorImpl::UpdateFrameMetaData(
@@ -221,9 +218,11 @@ void SynchronousCompositorImpl::SetMemoryPolicy(size_t bytes_limit) {
output_surface_->SetMemoryPolicy(bytes_limit);
if (bytes_limit && !current_bytes_limit) {
- g_factory.Get().CompositorInitializedHardwareDraw();
+ SynchronousCompositorStreamTextureFactoryImpl::GetInstance()
+ ->CompositorInitializedHardwareDraw();
} else if (!bytes_limit && current_bytes_limit) {
- g_factory.Get().CompositorReleasedHardwareDraw();
+ SynchronousCompositorStreamTextureFactoryImpl::GetInstance()
+ ->CompositorReleasedHardwareDraw();
}
}
@@ -242,6 +241,14 @@ void SynchronousCompositorImpl::DidChangeRootLayerScrollOffset(
root_offset);
}
+void SynchronousCompositorImpl::SynchronouslyZoomBy(float zoom_delta,
+ const gfx::Point& anchor) {
+ DCHECK(CalledOnValidThread());
+ if (!synchronous_input_handler_proxy_)
+ return;
+ synchronous_input_handler_proxy_->SynchronouslyZoomBy(zoom_delta, anchor);
+}
+
void SynchronousCompositorImpl::SetIsActive(bool is_active) {
TRACE_EVENT1("cc", "SynchronousCompositorImpl::SetIsActive", "is_active",
is_active);
@@ -283,7 +290,7 @@ void SynchronousCompositorImpl::UpdateNeedsBeginFrames() {
rwhva_->OnSetNeedsBeginFrames(is_active_ && renderer_needs_begin_frames_);
}
-void SynchronousCompositorImpl::DidOverscroll(
+void SynchronousCompositorImpl::DidOverscrollInProcess(
const DidOverscrollParams& params) {
if (registered_with_client_) {
compositor_client_->DidOverscroll(params.accumulated_overscroll,
@@ -307,6 +314,13 @@ InputEventAckState SynchronousCompositorImpl::HandleInputEvent(
routing_id_, input_event);
}
+void SynchronousCompositorImpl::DidOverscroll(
+ const DidOverscrollParams& params) {
+ // SynchronousCompositorImpl uses synchronous DidOverscrollInProcess for
+ // overscroll instead of this async path.
+ NOTREACHED();
+}
+
bool SynchronousCompositorImpl::OnMessageReceived(const IPC::Message& message) {
NOTREACHED();
return false;
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 e5a14611d8c..29f48d2a707 100644
--- a/chromium/content/browser/android/in_process/synchronous_compositor_impl.h
+++ b/chromium/content/browser/android/in_process/synchronous_compositor_impl.h
@@ -43,9 +43,6 @@ class SynchronousCompositorImpl
// is implicitly that of the in-process renderer.
static SynchronousCompositorImpl* FromRoutingID(int routing_id);
- static void SetGpuServiceInProc(
- scoped_refptr<gpu::InProcessCommandBuffer::Service> service);
-
~SynchronousCompositorImpl() override;
// Called by SynchronousCompositorRegistry.
@@ -60,10 +57,11 @@ class SynchronousCompositorImpl
// SynchronousCompositorOutputSurfaceClient overrides.
void Invalidate() override;
- void SwapBuffers(cc::CompositorFrame* frame) override;
+ void SwapBuffers(uint32_t output_surface_id,
+ cc::CompositorFrame* frame) override;
// SynchronousCompositor overrides.
- scoped_ptr<cc::CompositorFrame> DemandDrawHw(
+ SynchronousCompositor::Frame DemandDrawHw(
const gfx::Size& surface_size,
const gfx::Transform& transform,
const gfx::Rect& viewport,
@@ -71,10 +69,12 @@ class SynchronousCompositorImpl
const gfx::Rect& viewport_rect_for_tile_priority,
const gfx::Transform& transform_for_tile_priority) override;
bool DemandDrawSw(SkCanvas* canvas) override;
- void ReturnResources(const cc::CompositorFrameAck& frame_ack) override;
+ void ReturnResources(uint32_t output_surface_id,
+ const cc::CompositorFrameAck& frame_ack) override;
void SetMemoryPolicy(size_t bytes_limit) override;
void DidChangeRootLayerScrollOffset(
const gfx::ScrollOffset& root_offset) override;
+ void SynchronouslyZoomBy(float zoom_delta, const gfx::Point& anchor) override;
void SetIsActive(bool is_active) override;
void OnComputeScroll(base::TimeTicks animation_time) override;
@@ -82,6 +82,7 @@ class SynchronousCompositorImpl
void BeginFrame(const cc::BeginFrameArgs& args) override;
InputEventAckState HandleInputEvent(
const blink::WebInputEvent& input_event) override;
+ void DidOverscroll(const DidOverscrollParams& params) override;
bool OnMessageReceived(const IPC::Message& message) override;
void DidBecomeCurrent() override;
@@ -94,7 +95,7 @@ class SynchronousCompositorImpl
float min_page_scale_factor,
float max_page_scale_factor) override;
- void DidOverscroll(const DidOverscrollParams& params);
+ void DidOverscrollInProcess(const DidOverscrollParams& params);
void DidStopFlinging();
private:
@@ -118,7 +119,7 @@ class SynchronousCompositorImpl
bool is_active_;
bool renderer_needs_begin_frames_;
bool need_animate_input_;
- scoped_ptr<cc::CompositorFrame> frame_holder_;
+ SynchronousCompositor::Frame frame_holder_;
base::WeakPtrFactory<SynchronousCompositorImpl> weak_ptr_factory_;
diff --git a/chromium/content/browser/android/in_process/synchronous_compositor_renderer_statics.cc b/chromium/content/browser/android/in_process/synchronous_compositor_renderer_statics.cc
new file mode 100644
index 00000000000..38056fbd7ac
--- /dev/null
+++ b/chromium/content/browser/android/in_process/synchronous_compositor_renderer_statics.cc
@@ -0,0 +1,15 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/android/in_process/synchronous_compositor_renderer_statics.h"
+
+#include "content/renderer/android/synchronous_compositor_proxy.h"
+
+namespace content {
+
+void SynchronousCompositorSetSkCanvas(SkCanvas* canvas) {
+ SynchronousCompositorProxy::SetSkCanvasForDraw(canvas);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/android/in_process/synchronous_compositor_renderer_statics.h b/chromium/content/browser/android/in_process/synchronous_compositor_renderer_statics.h
new file mode 100644
index 00000000000..80823671758
--- /dev/null
+++ b/chromium/content/browser/android/in_process/synchronous_compositor_renderer_statics.h
@@ -0,0 +1,16 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_COMPOSITOR_RENDERER_STATICS_H_
+#define CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_COMPOSITOR_RENDERER_STATICS_H_
+
+class SkCanvas;
+
+namespace content {
+
+void SynchronousCompositorSetSkCanvas(SkCanvas* canvas);
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_IN_PROCESS_SYNCHRONOUS_COMPOSITOR_RENDERER_STATICS_H_
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 3ce1c61eb4f..b4d9f7fa82b 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
@@ -40,26 +40,15 @@ void SynchronousInputEventFilter::SetBoundHandler(const Handler& handler) {
base::Unretained(this), handler));
}
+void SynchronousInputEventFilter::DidAddInputHandler(int routing_id) {}
+void SynchronousInputEventFilter::DidRemoveInputHandler(int routing_id) {}
+
void SynchronousInputEventFilter::SetBoundHandlerOnUIThread(
const Handler& handler) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
handler_ = handler;
}
-void SynchronousInputEventFilter::DidAddInputHandler(
- int routing_id,
- ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- SynchronousCompositorRegistryInProc::GetInstance()->RegisterInputHandler(
- routing_id, synchronous_input_handler_proxy);
-}
-
-void SynchronousInputEventFilter::DidRemoveInputHandler(int routing_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- SynchronousCompositorRegistryInProc::GetInstance()->UnregisterInputHandler(
- routing_id);
-}
-
void SynchronousInputEventFilter::DidOverscroll(
int routing_id,
const DidOverscrollParams& params) {
@@ -68,7 +57,7 @@ void SynchronousInputEventFilter::DidOverscroll(
SynchronousCompositorImpl* compositor =
SynchronousCompositorImpl::FromRoutingID(routing_id);
if (compositor)
- compositor->DidOverscroll(params);
+ compositor->DidOverscrollInProcess(params);
}
void SynchronousInputEventFilter::DidStopFlinging(int routing_id) {
@@ -80,4 +69,23 @@ void SynchronousInputEventFilter::DidStopFlinging(int routing_id) {
compositor->DidStopFlinging();
}
+void SynchronousInputEventFilter::NotifyInputEventHandled(
+ int routing_id,
+ blink::WebInputEvent::Type type) {}
+
+void SynchronousInputEventFilter::DidAddSynchronousHandlerProxy(
+ int routing_id,
+ ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ SynchronousCompositorRegistryInProc::GetInstance()->RegisterInputHandler(
+ routing_id, synchronous_input_handler_proxy);
+}
+
+void SynchronousInputEventFilter::DidRemoveSynchronousHandlerProxy(
+ int routing_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ SynchronousCompositorRegistryInProc::GetInstance()->UnregisterInputHandler(
+ routing_id);
+}
+
} // namespace content
diff --git a/chromium/content/browser/android/in_process/synchronous_input_event_filter.h b/chromium/content/browser/android/in_process/synchronous_input_event_filter.h
index 98375d73bf8..9ecb400ff02 100644
--- a/chromium/content/browser/android/in_process/synchronous_input_event_filter.h
+++ b/chromium/content/browser/android/in_process/synchronous_input_event_filter.h
@@ -26,7 +26,9 @@ namespace content {
// The provided |handler| process WebInputEvents synchronously on the merged
// UI and compositing thread. If the event goes unhandled, that is reflected in
// the InputEventAckState; no forwarding is performed.
-class SynchronousInputEventFilter : public InputHandlerManagerClient {
+class SynchronousInputEventFilter
+ : public InputHandlerManagerClient,
+ public SynchronousInputHandlerProxyClient {
public:
SynchronousInputEventFilter();
~SynchronousInputEventFilter() override;
@@ -36,14 +38,20 @@ class SynchronousInputEventFilter : public InputHandlerManagerClient {
// InputHandlerManagerClient implementation.
void SetBoundHandler(const Handler& handler) override;
- void DidAddInputHandler(
- int routing_id,
- ui::SynchronousInputHandlerProxy*
- synchronous_input_handler_proxy) override;
+ void DidAddInputHandler(int routing_id) override;
void DidRemoveInputHandler(int routing_id) override;
void DidOverscroll(int routing_id,
const DidOverscrollParams& params) override;
void DidStopFlinging(int routing_id) override;
+ void NotifyInputEventHandled(int routing_id,
+ blink::WebInputEvent::Type type) override;
+
+ // SynchronousInputHandlerProxyClient overrides.
+ void DidAddSynchronousHandlerProxy(
+ int routing_id,
+ ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy)
+ override;
+ void DidRemoveSynchronousHandlerProxy(int routing_id) override;
private:
void SetBoundHandlerOnUIThread(const Handler& handler);
diff --git a/chromium/content/browser/android/in_process_surface_texture_manager.h b/chromium/content/browser/android/in_process_surface_texture_manager.h
index 24e951c7b2f..8cf4d2eebdd 100644
--- a/chromium/content/browser/android/in_process_surface_texture_manager.h
+++ b/chromium/content/browser/android/in_process_surface_texture_manager.h
@@ -5,22 +5,22 @@
#ifndef CONTENT_BROWSER_ANDROID_IN_PROCESS_SURFACE_TEXTURE_MANAGER_H_
#define CONTENT_BROWSER_ANDROID_IN_PROCESS_SURFACE_TEXTURE_MANAGER_H_
-#include "content/common/android/surface_texture_manager.h"
+#include "gpu/ipc/common/android/surface_texture_manager.h"
#include "base/containers/scoped_ptr_hash_map.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
#include "base/synchronization/lock.h"
-#include "content/common/android/surface_texture_peer.h"
#include "content/common/content_export.h"
+#include "gpu/ipc/common/android/surface_texture_peer.h"
#include "ui/gl/android/scoped_java_surface.h"
namespace content {
class CONTENT_EXPORT InProcessSurfaceTextureManager
- : public SurfaceTextureManager,
- public SurfaceTexturePeer {
+ : public gpu::SurfaceTextureManager,
+ public gpu::SurfaceTexturePeer {
public:
static InProcessSurfaceTextureManager* GetInstance();
diff --git a/chromium/content/browser/android/java/OWNERS b/chromium/content/browser/android/java/OWNERS
index 0cebb68c10c..ce79cad30e2 100644
--- a/chromium/content/browser/android/java/OWNERS
+++ b/chromium/content/browser/android/java/OWNERS
@@ -1,2 +1,2 @@
-mnaganov@chromium.org
+michaelbai@chromium.org
torne@chromium.org
diff --git a/chromium/content/browser/mojo/service_registry_android.cc b/chromium/content/browser/android/service_registry_android_impl.cc
index 0e80e0842b5..e54c3610a29 100644
--- a/chromium/content/browser/mojo/service_registry_android.cc
+++ b/chromium/content/browser/android/service_registry_android_impl.cc
@@ -1,16 +1,18 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
+// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/mojo/service_registry_android.h"
+#include "content/browser/android/service_registry_android_impl.h"
#include <utility>
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/callback.h"
-#include "content/common/mojo/service_registry_impl.h"
+#include "base/memory/ptr_util.h"
+#include "content/public/common/service_registry.h"
#include "jni/ServiceRegistry_jni.h"
+#include "mojo/public/cpp/system/message_pipe.h"
using base::android::AttachCurrentThread;
using base::android::ConvertJavaStringToUTF8;
@@ -28,23 +30,31 @@ void CreateImplAndAttach(
const ScopedJavaGlobalRef<jobject>& j_scoped_factory,
mojo::ScopedMessagePipeHandle handle) {
JNIEnv* env = AttachCurrentThread();
- Java_ServiceRegistry_createImplAndAttach(env,
- j_scoped_service_registry.obj(),
- handle.release().value(),
- j_scoped_manager.obj(),
- j_scoped_factory.obj());
+ Java_ServiceRegistry_createImplAndAttach(
+ env, j_scoped_service_registry.obj(), handle.release().value(),
+ j_scoped_manager.obj(), j_scoped_factory.obj());
}
} // namespace
// static
-bool ServiceRegistryAndroid::Register(JNIEnv* env) {
+std::unique_ptr<ServiceRegistryAndroid> ServiceRegistryAndroid::Create(
+ ServiceRegistry* registry) {
+ return base::WrapUnique(new ServiceRegistryAndroidImpl(registry));
+}
+
+// static
+bool ServiceRegistryAndroidImpl::Register(JNIEnv* env) {
return RegisterNativesImpl(env);
}
+ServiceRegistryAndroidImpl::~ServiceRegistryAndroidImpl() {
+ Java_ServiceRegistry_destroy(AttachCurrentThread(), obj_.obj());
+}
+
// Constructor and destructor call into Java.
-ServiceRegistryAndroid::ServiceRegistryAndroid(
- ServiceRegistryImpl* service_registry)
+ServiceRegistryAndroidImpl::ServiceRegistryAndroidImpl(
+ ServiceRegistry* service_registry)
: service_registry_(service_registry) {
JNIEnv* env = AttachCurrentThread();
obj_.Reset(
@@ -52,12 +62,13 @@ ServiceRegistryAndroid::ServiceRegistryAndroid(
Java_ServiceRegistry_create(env, reinterpret_cast<intptr_t>(this)).obj());
}
-ServiceRegistryAndroid::~ServiceRegistryAndroid() {
- Java_ServiceRegistry_destroy(AttachCurrentThread(), obj_.obj());
+const base::android::ScopedJavaGlobalRef<jobject>&
+ServiceRegistryAndroidImpl::GetObj() {
+ return obj_;
}
// Methods called from Java.
-void ServiceRegistryAndroid::AddService(
+void ServiceRegistryAndroidImpl::AddService(
JNIEnv* env,
const JavaParamRef<jobject>& j_service_registry,
const JavaParamRef<jobject>& j_manager,
@@ -74,14 +85,12 @@ void ServiceRegistryAndroid::AddService(
ScopedJavaGlobalRef<jobject> j_scoped_factory;
j_scoped_factory.Reset(env, j_factory);
- service_registry_->AddService(name,
- base::Bind(&CreateImplAndAttach,
- j_scoped_service_registry,
- j_scoped_manager,
- j_scoped_factory));
+ service_registry_->AddService(
+ name, base::Bind(&CreateImplAndAttach, j_scoped_service_registry,
+ j_scoped_manager, j_scoped_factory));
}
-void ServiceRegistryAndroid::RemoveService(
+void ServiceRegistryAndroidImpl::RemoveService(
JNIEnv* env,
const JavaParamRef<jobject>& j_service_registry,
const JavaParamRef<jstring>& j_name) {
@@ -89,7 +98,7 @@ void ServiceRegistryAndroid::RemoveService(
service_registry_->RemoveService(name);
}
-void ServiceRegistryAndroid::ConnectToRemoteService(
+void ServiceRegistryAndroidImpl::ConnectToRemoteService(
JNIEnv* env,
const JavaParamRef<jobject>& j_service_registry,
const JavaParamRef<jstring>& j_name,
diff --git a/chromium/content/browser/android/service_registry_android_impl.h b/chromium/content/browser/android/service_registry_android_impl.h
new file mode 100644
index 00000000000..2620313c801
--- /dev/null
+++ b/chromium/content/browser/android/service_registry_android_impl.h
@@ -0,0 +1,53 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_ANDROID_SERVICE_REGISTRY_ANDROID_IMPL_H_
+#define CONTENT_BROWSER_ANDROID_SERVICE_REGISTRY_ANDROID_IMPL_H_
+
+#include <jni.h>
+
+#include "base/macros.h"
+#include "content/public/browser/android/service_registry_android.h"
+
+namespace content {
+
+class ServiceRegistryAndroidImpl : public ServiceRegistryAndroid {
+ public:
+ static bool Register(JNIEnv* env);
+
+ ~ServiceRegistryAndroidImpl() override;
+
+ private:
+ friend class ServiceRegistryAndroid;
+
+ // Use ServiceRegistryAndroid::Create() to create an instance.
+ explicit ServiceRegistryAndroidImpl(ServiceRegistry* service_registry);
+
+ // ServiceRegistryAndroid implementation:
+ void AddService(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& j_service_registry,
+ const base::android::JavaParamRef<jobject>& j_manager,
+ const base::android::JavaParamRef<jobject>& j_factory,
+ const base::android::JavaParamRef<jstring>& j_name) override;
+ void RemoveService(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& j_service_registry,
+ const base::android::JavaParamRef<jstring>& j_name) override;
+ void ConnectToRemoteService(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& j_service_registry,
+ const base::android::JavaParamRef<jstring>& j_name,
+ jint handle) override;
+ const base::android::ScopedJavaGlobalRef<jobject>& GetObj() override;
+
+ ServiceRegistry* service_registry_;
+ base::android::ScopedJavaGlobalRef<jobject> obj_;
+
+ DISALLOW_COPY_AND_ASSIGN(ServiceRegistryAndroidImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ANDROID_SERVICE_REGISTRY_ANDROID_IMPL_H_
diff --git a/chromium/content/browser/android/synchronous_compositor_base.cc b/chromium/content/browser/android/synchronous_compositor_base.cc
index acc5e349f99..0d085095b91 100644
--- a/chromium/content/browser/android/synchronous_compositor_base.cc
+++ b/chromium/content/browser/android/synchronous_compositor_base.cc
@@ -6,6 +6,7 @@
#include "base/command_line.h"
#include "base/supports_user_data.h"
+#include "content/browser/android/in_process/synchronous_compositor_factory_impl.h"
#include "content/browser/android/in_process/synchronous_compositor_impl.h"
#include "content/browser/android/synchronous_compositor_host.h"
#include "content/browser/gpu/gpu_process_host.h"
@@ -20,27 +21,25 @@ class SynchronousCompositorClient;
namespace {
-gpu::SyncPointManager* g_sync_point_manager = nullptr;
+base::LazyInstance<scoped_refptr<gpu::InProcessCommandBuffer::Service>>
+ g_gpu_service = LAZY_INSTANCE_INITIALIZER;
base::Thread* CreateInProcessGpuThreadForSynchronousCompositor(
- const InProcessChildThreadParams& params) {
- DCHECK(g_sync_point_manager);
- return new InProcessGpuThread(params, g_sync_point_manager);
+ const InProcessChildThreadParams& params,
+ const gpu::GpuPreferences& gpu_preferences) {
+ DCHECK(g_gpu_service.Get());
+ return new InProcessGpuThread(params, gpu_preferences,
+ g_gpu_service.Get()->sync_point_manager());
}
} // namespace
void SynchronousCompositor::SetGpuService(
scoped_refptr<gpu::InProcessCommandBuffer::Service> service) {
- DCHECK(!g_sync_point_manager);
- g_sync_point_manager = service->sync_point_manager();
+ DCHECK(!g_gpu_service.Get());
+ g_gpu_service.Get() = service;
GpuProcessHost::RegisterGpuMainThreadFactory(
CreateInProcessGpuThreadForSynchronousCompositor);
-
- if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kIPCSyncCompositing)) {
- SynchronousCompositorImpl::SetGpuServiceInProc(service);
- }
}
// static
@@ -65,10 +64,15 @@ scoped_ptr<SynchronousCompositorBase> SynchronousCompositorBase::Create(
if (!web_contents_android->synchronous_compositor_client())
return nullptr; // Not using sync compositing.
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kIPCSyncCompositing)) {
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kIPCSyncCompositing)) {
+ bool async_input =
+ !command_line->HasSwitch(switches::kSyncInputForSyncCompositor);
+ bool use_in_proc_software_draw =
+ command_line->HasSwitch(switches::kSingleProcess);
return make_scoped_ptr(new SynchronousCompositorHost(
- rwhva, web_contents_android->synchronous_compositor_client()));
+ rwhva, web_contents_android->synchronous_compositor_client(),
+ async_input, use_in_proc_software_draw));
}
return make_scoped_ptr(new SynchronousCompositorImpl(
rwhva, web_contents_android->synchronous_compositor_client()));
diff --git a/chromium/content/browser/android/synchronous_compositor_base.h b/chromium/content/browser/android/synchronous_compositor_base.h
index 6bd41bb24d4..218e82199da 100644
--- a/chromium/content/browser/android/synchronous_compositor_base.h
+++ b/chromium/content/browser/android/synchronous_compositor_base.h
@@ -24,7 +24,9 @@ struct BeginFrameArgs;
namespace content {
class RenderWidgetHostViewAndroid;
+class SynchronousCompositorStreamTextureFactoryImpl;
class WebContents;
+struct DidOverscrollParams;
class SynchronousCompositorBase : public SynchronousCompositor {
public:
@@ -37,6 +39,7 @@ class SynchronousCompositorBase : public SynchronousCompositor {
virtual void BeginFrame(const cc::BeginFrameArgs& args) = 0;
virtual InputEventAckState HandleInputEvent(
const blink::WebInputEvent& input_event) = 0;
+ virtual void DidOverscroll(const DidOverscrollParams& over_scroll_params) = 0;
virtual bool OnMessageReceived(const IPC::Message& message) = 0;
virtual void DidBecomeCurrent() = 0;
diff --git a/chromium/content/browser/android/synchronous_compositor_host.cc b/chromium/content/browser/android/synchronous_compositor_host.cc
index 83dd85fead4..7f6cdfc5fb3 100644
--- a/chromium/content/browser/android/synchronous_compositor_host.cc
+++ b/chromium/content/browser/android/synchronous_compositor_host.cc
@@ -10,6 +10,8 @@
#include "base/memory/shared_memory.h"
#include "base/trace_event/trace_event_argument.h"
#include "cc/output/compositor_frame_ack.h"
+#include "content/browser/android/in_process/synchronous_compositor_factory_impl.h"
+#include "content/browser/android/in_process/synchronous_compositor_renderer_statics.h"
#include "content/browser/renderer_host/render_widget_host_view_android.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/android/sync_compositor_messages.h"
@@ -27,21 +29,26 @@ namespace content {
SynchronousCompositorHost::SynchronousCompositorHost(
RenderWidgetHostViewAndroid* rwhva,
- SynchronousCompositorClient* client)
+ SynchronousCompositorClient* client,
+ bool async_input,
+ bool use_in_proc_software_draw)
: rwhva_(rwhva),
client_(client),
ui_task_runner_(
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI)),
routing_id_(rwhva_->GetRenderWidgetHost()->GetRoutingID()),
sender_(rwhva_->GetRenderWidgetHost()),
+ async_input_(async_input),
+ use_in_process_zero_copy_software_draw_(use_in_proc_software_draw),
is_active_(false),
bytes_limit_(0u),
+ output_surface_id_from_last_draw_(0u),
root_scroll_offset_updated_by_browser_(false),
renderer_param_version_(0u),
need_animate_scroll_(false),
- need_invalidate_(false),
+ need_invalidate_count_(0u),
need_begin_frame_(false),
- did_activate_pending_tree_(false),
+ did_activate_pending_tree_count_(0u),
weak_ptr_factory_(this) {
client_->DidInitializeCompositor(this);
}
@@ -66,7 +73,7 @@ void SynchronousCompositorHost::DidBecomeCurrent() {
client_->DidBecomeCurrent(this);
}
-scoped_ptr<cc::CompositorFrame> SynchronousCompositorHost::DemandDrawHw(
+SynchronousCompositor::Frame SynchronousCompositorHost::DemandDrawHw(
const gfx::Size& surface_size,
const gfx::Transform& transform,
const gfx::Rect& viewport,
@@ -76,22 +83,27 @@ scoped_ptr<cc::CompositorFrame> SynchronousCompositorHost::DemandDrawHw(
SyncCompositorDemandDrawHwParams params(surface_size, transform, viewport,
clip, viewport_rect_for_tile_priority,
transform_for_tile_priority);
- scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
+ SynchronousCompositor::Frame frame;
+ frame.frame.reset(new cc::CompositorFrame);
SyncCompositorCommonBrowserParams common_browser_params;
PopulateCommonParams(&common_browser_params);
SyncCompositorCommonRendererParams common_renderer_params;
if (!sender_->Send(new SyncCompositorMsg_DemandDrawHw(
routing_id_, common_browser_params, params, &common_renderer_params,
- frame.get()))) {
- return nullptr;
+ &frame.output_surface_id, frame.frame.get()))) {
+ return SynchronousCompositor::Frame();
}
ProcessCommonParams(common_renderer_params);
- if (!frame->delegated_frame_data) {
+ if (!frame.frame->delegated_frame_data) {
// This can happen if compositor did not swap in this draw.
- frame.reset();
+ frame.frame.reset();
+ }
+ if (frame.frame) {
+ UpdateFrameMetaData(frame.frame->metadata);
+ if (output_surface_id_from_last_draw_ != frame.output_surface_id)
+ returned_resources_.clear();
+ output_surface_id_from_last_draw_ = frame.output_surface_id;
}
- if (frame)
- UpdateFrameMetaData(frame->metadata);
return frame;
}
@@ -100,6 +112,44 @@ void SynchronousCompositorHost::UpdateFrameMetaData(
rwhva_->SynchronousFrameMetadata(frame_metadata);
}
+namespace {
+
+class ScopedSetSkCanvas {
+ public:
+ explicit ScopedSetSkCanvas(SkCanvas* canvas) {
+ SynchronousCompositorSetSkCanvas(canvas);
+ }
+
+ ~ScopedSetSkCanvas() {
+ SynchronousCompositorSetSkCanvas(nullptr);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ScopedSetSkCanvas);
+};
+
+}
+
+bool SynchronousCompositorHost::DemandDrawSwInProc(SkCanvas* canvas) {
+ SyncCompositorCommonBrowserParams common_browser_params;
+ PopulateCommonParams(&common_browser_params);
+ SyncCompositorCommonRendererParams common_renderer_params;
+ bool success = false;
+ scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
+ ScopedSetSkCanvas set_sk_canvas(canvas);
+ SyncCompositorDemandDrawSwParams params; // Unused.
+ if (!sender_->Send(new SyncCompositorMsg_DemandDrawSw(
+ routing_id_, common_browser_params, params, &success,
+ &common_renderer_params, frame.get()))) {
+ return false;
+ }
+ if (!success)
+ return false;
+ ProcessCommonParams(common_renderer_params);
+ UpdateFrameMetaData(frame->metadata);
+ return true;
+}
+
class SynchronousCompositorHost::ScopedSendZeroMemory {
public:
ScopedSendZeroMemory(SynchronousCompositorHost* host) : host_(host) {}
@@ -124,6 +174,9 @@ struct SynchronousCompositorHost::SharedMemoryWithSize {
};
bool SynchronousCompositorHost::DemandDrawSw(SkCanvas* canvas) {
+ if (use_in_process_zero_copy_software_draw_)
+ return DemandDrawSwInProc(canvas);
+
SyncCompositorDemandDrawSwParams params;
params.size = gfx::Size(canvas->getBaseLayerSize().width(),
canvas->getBaseLayerSize().height());
@@ -222,7 +275,13 @@ void SynchronousCompositorHost::SendZeroMemory() {
}
void SynchronousCompositorHost::ReturnResources(
+ uint32_t output_surface_id,
const cc::CompositorFrameAck& frame_ack) {
+ // If output_surface_id does not match, then renderer side has switched
+ // to a new OutputSurface, so dropping resources for old OutputSurface
+ // is allowed.
+ if (output_surface_id_from_last_draw_ != output_surface_id)
+ return;
returned_resources_.insert(returned_resources_.end(),
frame_ack.resources.begin(),
frame_ack.resources.end());
@@ -231,8 +290,17 @@ void SynchronousCompositorHost::ReturnResources(
void SynchronousCompositorHost::SetMemoryPolicy(size_t bytes_limit) {
if (bytes_limit_ == bytes_limit)
return;
+ size_t current_bytes_limit = bytes_limit_;
bytes_limit_ = bytes_limit;
SendAsyncCompositorStateIfNeeded();
+
+ if (bytes_limit && !current_bytes_limit) {
+ SynchronousCompositorStreamTextureFactoryImpl::GetInstance()
+ ->CompositorInitializedHardwareDraw();
+ } else if (!bytes_limit && current_bytes_limit) {
+ SynchronousCompositorStreamTextureFactoryImpl::GetInstance()
+ ->CompositorReleasedHardwareDraw();
+ }
}
void SynchronousCompositorHost::DidChangeRootLayerScrollOffset(
@@ -261,6 +329,19 @@ void SynchronousCompositorHost::UpdateStateTask() {
DCHECK(!weak_ptr_factory_.HasWeakPtrs());
}
+void SynchronousCompositorHost::SynchronouslyZoomBy(float zoom_delta,
+ const gfx::Point& anchor) {
+ SyncCompositorCommonBrowserParams common_browser_params;
+ PopulateCommonParams(&common_browser_params);
+ SyncCompositorCommonRendererParams common_renderer_params;
+ if (!sender_->Send(new SyncCompositorMsg_ZoomBy(
+ routing_id_, common_browser_params, zoom_delta, anchor,
+ &common_renderer_params))) {
+ return;
+ }
+ ProcessCommonParams(common_renderer_params);
+}
+
void SynchronousCompositorHost::SetIsActive(bool is_active) {
if (is_active_ == is_active)
return;
@@ -278,16 +359,14 @@ void SynchronousCompositorHost::OnComputeScroll(
SyncCompositorCommonBrowserParams common_browser_params;
PopulateCommonParams(&common_browser_params);
SyncCompositorCommonRendererParams common_renderer_params;
- if (!sender_->Send(new SyncCompositorMsg_ComputeScroll(
- routing_id_, common_browser_params, animation_time,
- &common_renderer_params))) {
- return;
- }
- ProcessCommonParams(common_renderer_params);
+ sender_->Send(new SyncCompositorMsg_ComputeScroll(
+ routing_id_, common_browser_params, animation_time));
}
InputEventAckState SynchronousCompositorHost::HandleInputEvent(
const blink::WebInputEvent& input_event) {
+ if (async_input_)
+ return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
SyncCompositorCommonBrowserParams common_browser_params;
PopulateCommonParams(&common_browser_params);
SyncCompositorCommonRendererParams common_renderer_params;
@@ -301,8 +380,15 @@ InputEventAckState SynchronousCompositorHost::HandleInputEvent(
return ack;
}
+void SynchronousCompositorHost::DidOverscroll(
+ const DidOverscrollParams& over_scroll_params) {
+ client_->DidOverscroll(over_scroll_params.accumulated_overscroll,
+ over_scroll_params.latest_overscroll_delta,
+ over_scroll_params.current_fling_velocity);
+}
+
void SynchronousCompositorHost::BeginFrame(const cc::BeginFrameArgs& args) {
- if (!is_active_ || !need_begin_frame_)
+ if (!is_active_)
return;
SyncCompositorCommonBrowserParams common_browser_params;
@@ -320,9 +406,7 @@ void SynchronousCompositorHost::OnOverScroll(
const SyncCompositorCommonRendererParams& params,
const DidOverscrollParams& over_scroll_params) {
ProcessCommonParams(params);
- client_->DidOverscroll(over_scroll_params.accumulated_overscroll,
- over_scroll_params.latest_overscroll_delta,
- over_scroll_params.current_fling_velocity);
+ DidOverscroll(over_scroll_params);
}
void SynchronousCompositorHost::PopulateCommonParams(
@@ -330,6 +414,8 @@ void SynchronousCompositorHost::PopulateCommonParams(
DCHECK(params);
DCHECK(params->ack.resources.empty());
params->bytes_limit = bytes_limit_;
+ params->output_surface_id_for_returned_resources =
+ output_surface_id_from_last_draw_;
params->ack.resources.swap(returned_resources_);
if (root_scroll_offset_updated_by_browser_) {
params->root_scroll_offset = root_scroll_offset_;
@@ -354,18 +440,16 @@ void SynchronousCompositorHost::ProcessCommonParams(
need_begin_frame_ = params.need_begin_frame;
UpdateNeedsBeginFrames();
}
- need_invalidate_ = need_invalidate_ || params.need_invalidate;
- did_activate_pending_tree_ =
- did_activate_pending_tree_ || params.did_activate_pending_tree;
root_scroll_offset_ = params.total_scroll_offset;
- if (need_invalidate_) {
- need_invalidate_ = false;
+ if (need_invalidate_count_ != params.need_invalidate_count) {
+ need_invalidate_count_ = params.need_invalidate_count;
client_->PostInvalidate();
}
- if (did_activate_pending_tree_) {
- did_activate_pending_tree_ = false;
+ if (did_activate_pending_tree_count_ !=
+ params.did_activate_pending_tree_count) {
+ did_activate_pending_tree_count_ = params.did_activate_pending_tree_count;
client_->DidUpdateContent();
}
diff --git a/chromium/content/browser/android/synchronous_compositor_host.h b/chromium/content/browser/android/synchronous_compositor_host.h
index 8c60071db59..b9b1598602f 100644
--- a/chromium/content/browser/android/synchronous_compositor_host.h
+++ b/chromium/content/browser/android/synchronous_compositor_host.h
@@ -33,7 +33,7 @@ class SynchronousCompositorHost : public SynchronousCompositorBase {
~SynchronousCompositorHost() override;
// SynchronousCompositor overrides.
- scoped_ptr<cc::CompositorFrame> DemandDrawHw(
+ SynchronousCompositor::Frame DemandDrawHw(
const gfx::Size& surface_size,
const gfx::Transform& transform,
const gfx::Rect& viewport,
@@ -41,16 +41,19 @@ class SynchronousCompositorHost : public SynchronousCompositorBase {
const gfx::Rect& viewport_rect_for_tile_priority,
const gfx::Transform& transform_for_tile_priority) override;
bool DemandDrawSw(SkCanvas* canvas) override;
- void ReturnResources(const cc::CompositorFrameAck& frame_ack) override;
+ void ReturnResources(uint32_t output_surface_id,
+ const cc::CompositorFrameAck& frame_ack) override;
void SetMemoryPolicy(size_t bytes_limit) override;
void DidChangeRootLayerScrollOffset(
const gfx::ScrollOffset& root_offset) override;
+ void SynchronouslyZoomBy(float zoom_delta, const gfx::Point& anchor) override;
void SetIsActive(bool is_active) override;
void OnComputeScroll(base::TimeTicks animation_time) override;
// SynchronousCompositorBase overrides.
InputEventAckState HandleInputEvent(
const blink::WebInputEvent& input_event) override;
+ void DidOverscroll(const DidOverscrollParams& over_scroll_params) override;
void BeginFrame(const cc::BeginFrameArgs& args) override;
bool OnMessageReceived(const IPC::Message& message) override;
void DidBecomeCurrent() override;
@@ -62,7 +65,9 @@ class SynchronousCompositorHost : public SynchronousCompositorBase {
friend class SynchronousCompositorBase;
SynchronousCompositorHost(RenderWidgetHostViewAndroid* rwhva,
- SynchronousCompositorClient* client);
+ SynchronousCompositorClient* client,
+ bool async_input,
+ bool use_in_proc_software_draw);
void PopulateCommonParams(SyncCompositorCommonBrowserParams* params);
void ProcessCommonParams(const SyncCompositorCommonRendererParams& params);
void UpdateNeedsBeginFrames();
@@ -71,6 +76,7 @@ class SynchronousCompositorHost : public SynchronousCompositorBase {
const DidOverscrollParams& over_scroll_params);
void SendAsyncCompositorStateIfNeeded();
void UpdateStateTask();
+ bool DemandDrawSwInProc(SkCanvas* canvas);
void SetSoftwareDrawSharedMemoryIfNeeded(size_t stride, size_t buffer_size);
void SendZeroMemory();
@@ -79,9 +85,12 @@ class SynchronousCompositorHost : public SynchronousCompositorBase {
const scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
const int routing_id_;
IPC::Sender* const sender_;
+ const bool async_input_;
+ const bool use_in_process_zero_copy_software_draw_;
bool is_active_;
size_t bytes_limit_;
+ uint32_t output_surface_id_from_last_draw_;
cc::ReturnedResourceArray returned_resources_;
scoped_ptr<SharedMemoryWithSize> software_draw_shm_;
@@ -92,9 +101,9 @@ class SynchronousCompositorHost : public SynchronousCompositorBase {
// From renderer.
uint32_t renderer_param_version_;
bool need_animate_scroll_;
- bool need_invalidate_;
+ uint32_t need_invalidate_count_;
bool need_begin_frame_;
- bool did_activate_pending_tree_;
+ uint32_t did_activate_pending_tree_count_;
base::WeakPtrFactory<SynchronousCompositorHost> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorHost);
diff --git a/chromium/content/browser/android/web_contents_observer_proxy.cc b/chromium/content/browser/android/web_contents_observer_proxy.cc
index d176f61f21b..dfa52cfb211 100644
--- a/chromium/content/browser/android/web_contents_observer_proxy.cc
+++ b/chromium/content/browser/android/web_contents_observer_proxy.cc
@@ -11,8 +11,10 @@
#include "base/android/scoped_java_ref.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/android/media_metadata_android.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/navigation_handle.h"
#include "jni/WebContentsObserverProxy_jni.h"
using base::android::AttachCurrentThread;
@@ -76,6 +78,17 @@ void WebContentsObserverProxy::RenderProcessGone(
was_oom_protected);
}
+void WebContentsObserverProxy::DidFinishNavigation(
+ NavigationHandle* navigation_handle) {
+ JNIEnv* env = AttachCurrentThread();
+ ScopedJavaLocalRef<jobject> obj(java_observer_);
+ ScopedJavaLocalRef<jstring> jstring_url(
+ ConvertUTF8ToJavaString(env, web_contents()->GetVisibleURL().spec()));
+ Java_WebContentsObserverProxy_didFinishNavigation(
+ env, obj.obj(), navigation_handle->IsInMainFrame(),
+ navigation_handle->IsErrorPage(), navigation_handle->HasCommitted());
+}
+
void WebContentsObserverProxy::DidStartLoading() {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj(java_observer_);
@@ -144,6 +157,7 @@ void WebContentsObserverProxy::DidNavigateMainFrame(
// that would also be valid for a fragment navigation.
bool is_fragment_navigation =
urls_same_ignoring_fragment && details.is_in_page;
+
Java_WebContentsObserverProxy_didNavigateMainFrame(
env, obj.obj(), jstring_url.obj(), jstring_base_url.obj(),
details.is_navigation_to_different_page(), is_fragment_navigation,
@@ -294,14 +308,18 @@ void WebContentsObserverProxy::DidStartNavigationToPendingEntry(
env, obj.obj(), jstring_url.obj());
}
-void WebContentsObserverProxy::MediaSessionStateChanged(bool is_controllable,
- bool is_suspended) {
+void WebContentsObserverProxy::MediaSessionStateChanged(
+ bool is_controllable,
+ bool is_suspended,
+ const MediaMetadata& metadata) {
JNIEnv* env = AttachCurrentThread();
ScopedJavaLocalRef<jobject> obj(java_observer_);
+ ScopedJavaLocalRef<jobject> j_metadata =
+ MediaMetadataAndroid::CreateJavaObject(env, metadata);
Java_WebContentsObserverProxy_mediaSessionStateChanged(
- env, obj.obj(), is_controllable, is_suspended);
+ env, obj.obj(), is_controllable, is_suspended, j_metadata.obj());
}
void WebContentsObserverProxy::SetToBaseURLForDataURLIfNeeded(
diff --git a/chromium/content/browser/android/web_contents_observer_proxy.h b/chromium/content/browser/android/web_contents_observer_proxy.h
index e22edbbdf84..af0895dc669 100644
--- a/chromium/content/browser/android/web_contents_observer_proxy.h
+++ b/chromium/content/browser/android/web_contents_observer_proxy.h
@@ -32,6 +32,7 @@ class WebContentsObserverProxy : public WebContentsObserver {
private:
void RenderViewReady() override;
void RenderProcessGone(base::TerminationStatus termination_status) override;
+ void DidFinishNavigation(NavigationHandle* navigation_handle) override;
void DidStartLoading() override;
void DidStopLoading() override;
void DidFailProvisionalLoad(RenderFrameHost* render_frame_host,
@@ -72,7 +73,8 @@ class WebContentsObserverProxy : public WebContentsObserver {
const GURL& url,
NavigationController::ReloadType reload_type) override;
void MediaSessionStateChanged(bool is_controllable,
- bool is_suspended) override;
+ bool is_suspended,
+ const MediaMetadata& metadata) override;
void SetToBaseURLForDataURLIfNeeded(std::string* url);
void DidFailLoadInternal(bool is_provisional_load,
diff --git a/chromium/content/browser/appcache/appcache_database.cc b/chromium/content/browser/appcache/appcache_database.cc
index f9e83ac91b7..f3053c7d258 100644
--- a/chromium/content/browser/appcache/appcache_database.cc
+++ b/chromium/content/browser/appcache/appcache_database.cc
@@ -191,6 +191,8 @@ AppCacheDatabase::GroupRecord::GroupRecord()
: group_id(0) {
}
+AppCacheDatabase::GroupRecord::GroupRecord(const GroupRecord& other) = default;
+
AppCacheDatabase::GroupRecord::~GroupRecord() {
}
diff --git a/chromium/content/browser/appcache/appcache_database.h b/chromium/content/browser/appcache/appcache_database.h
index a6f017e48d0..e2b265d56f1 100644
--- a/chromium/content/browser/appcache/appcache_database.h
+++ b/chromium/content/browser/appcache/appcache_database.h
@@ -51,6 +51,7 @@ class CONTENT_EXPORT AppCacheDatabase {
public:
struct CONTENT_EXPORT GroupRecord {
GroupRecord();
+ GroupRecord(const GroupRecord& other);
~GroupRecord();
int64_t group_id;
diff --git a/chromium/content/browser/appcache/appcache_disk_cache.cc b/chromium/content/browser/appcache/appcache_disk_cache.cc
index 49030f000a9..da5475d03d2 100644
--- a/chromium/content/browser/appcache/appcache_disk_cache.cc
+++ b/chromium/content/browser/appcache/appcache_disk_cache.cc
@@ -336,6 +336,8 @@ AppCacheDiskCache::PendingCall::PendingCall(
const net::CompletionCallback& callback)
: call_type(call_type), key(key), entry(entry), callback(callback) {}
+AppCacheDiskCache::PendingCall::PendingCall(const PendingCall& other) = default;
+
AppCacheDiskCache::PendingCall::~PendingCall() {}
int AppCacheDiskCache::Init(
diff --git a/chromium/content/browser/appcache/appcache_disk_cache.h b/chromium/content/browser/appcache/appcache_disk_cache.h
index 2b8c29993b4..d06bcf50f5b 100644
--- a/chromium/content/browser/appcache/appcache_disk_cache.h
+++ b/chromium/content/browser/appcache/appcache_disk_cache.h
@@ -89,6 +89,8 @@ class CONTENT_EXPORT AppCacheDiskCache
Entry** entry,
const net::CompletionCallback& callback);
+ PendingCall(const PendingCall& other);
+
~PendingCall();
};
typedef std::vector<PendingCall> PendingCalls;
diff --git a/chromium/content/browser/appcache/appcache_interceptor.cc b/chromium/content/browser/appcache/appcache_interceptor.cc
index 81985fe704a..050e66aee18 100644
--- a/chromium/content/browser/appcache/appcache_interceptor.cc
+++ b/chromium/content/browser/appcache/appcache_interceptor.cc
@@ -9,6 +9,9 @@
#include "content/browser/appcache/appcache_request_handler.h"
#include "content/browser/appcache/appcache_service_impl.h"
#include "content/browser/appcache/appcache_url_request_job.h"
+#include "content/browser/appcache/chrome_appcache_service.h"
+#include "content/browser/bad_message.h"
+#include "content/browser/loader/resource_message_filter.h"
#include "content/common/appcache_interfaces.h"
#include "net/url_request/url_request.h"
@@ -76,10 +79,16 @@ void AppCacheInterceptor::PrepareForCrossSiteTransfer(
void AppCacheInterceptor::CompleteCrossSiteTransfer(
net::URLRequest* request,
int new_process_id,
- int new_host_id) {
+ int new_host_id,
+ ResourceMessageFilter* filter) {
AppCacheRequestHandler* handler = GetHandler(request);
if (!handler)
return;
+ if (!handler->SanityCheckIsSameService(filter->appcache_service())) {
+ bad_message::ReceivedBadMessage(filter,
+ bad_message::ACI_WRONG_STORAGE_PARTITION);
+ return;
+ }
DCHECK_NE(kAppCacheNoHostId, new_host_id);
handler->CompleteCrossSiteTransfer(new_process_id,
new_host_id);
diff --git a/chromium/content/browser/appcache/appcache_interceptor.h b/chromium/content/browser/appcache/appcache_interceptor.h
index 0e50983ba21..9d1abc31b6a 100644
--- a/chromium/content/browser/appcache/appcache_interceptor.h
+++ b/chromium/content/browser/appcache/appcache_interceptor.h
@@ -21,6 +21,7 @@ class URLRequest;
namespace content {
class AppCacheRequestHandler;
class AppCacheServiceImpl;
+class ResourceMessageFilter;
// An interceptor to hijack requests and potentially service them out of
// the appcache.
@@ -45,7 +46,8 @@ class CONTENT_EXPORT AppCacheInterceptor : public net::URLRequestInterceptor {
int old_process_id);
static void CompleteCrossSiteTransfer(net::URLRequest* request,
int new_process_id,
- int new_host_id);
+ int new_host_id,
+ ResourceMessageFilter* filter);
static void MaybeCompleteCrossSiteTransferInOldProcess(
net::URLRequest* request,
int old_process_id);
diff --git a/chromium/content/browser/appcache/appcache_internals_ui.cc b/chromium/content/browser/appcache/appcache_internals_ui.cc
index 3abd692603a..0c402129b60 100644
--- a/chromium/content/browser/appcache/appcache_internals_ui.cc
+++ b/chromium/content/browser/appcache/appcache_internals_ui.cc
@@ -462,7 +462,7 @@ void AppCacheInternalsUI::OnFileDetailsReady(
response_info->http_response_info()->headers->GetStatusLine()));
headers.push_back('\n');
- void* iter = nullptr;
+ size_t iter = 0;
std::string name, value;
while (response_info->http_response_info()->headers->EnumerateHeaderLines(
&iter, &name, &value)) {
diff --git a/chromium/content/browser/appcache/appcache_request_handler.cc b/chromium/content/browser/appcache/appcache_request_handler.cc
index c02223752af..0a00878df3c 100644
--- a/chromium/content/browser/appcache/appcache_request_handler.cc
+++ b/chromium/content/browser/appcache/appcache_request_handler.cc
@@ -187,6 +187,7 @@ void AppCacheRequestHandler::PrepareForCrossSiteTransfer(int old_process_id) {
if (!host_)
return;
AppCacheBackendImpl* backend = host_->service()->GetBackend(old_process_id);
+ DCHECK(backend) << "appcache detected likely storage partition mismatch";
old_process_id_ = old_process_id;
old_host_id_ = host_->host_id();
host_for_cross_site_transfer_ = backend->TransferHostOut(host_->host_id());
@@ -199,6 +200,7 @@ void AppCacheRequestHandler::CompleteCrossSiteTransfer(
return;
DCHECK_EQ(host_, host_for_cross_site_transfer_.get());
AppCacheBackendImpl* backend = host_->service()->GetBackend(new_process_id);
+ DCHECK(backend) << "appcache detected likely storage partition mismatch";
backend->TransferHostIn(new_host_id,
std::move(host_for_cross_site_transfer_));
}
diff --git a/chromium/content/browser/appcache/appcache_request_handler.h b/chromium/content/browser/appcache/appcache_request_handler.h
index d7b55e5a96b..7665d10e0b8 100644
--- a/chromium/content/browser/appcache/appcache_request_handler.h
+++ b/chromium/content/browser/appcache/appcache_request_handler.h
@@ -25,6 +25,7 @@ class URLRequestJob;
namespace content {
class AppCacheRequestHandlerTest;
+class AppCacheService;
class AppCacheURLRequestJob;
// An instance is created for each net::URLRequest. The instance survives all
@@ -58,6 +59,12 @@ class CONTENT_EXPORT AppCacheRequestHandler
void CompleteCrossSiteTransfer(int new_process_id, int new_host_id);
void MaybeCompleteCrossSiteTransferInOldProcess(int old_process_id);
+ // Useful for detecting storage partition mismatches in the context
+ // of cross site transfer navigations.
+ bool SanityCheckIsSameService(AppCacheService* service) {
+ return !host_ || (host_->service() == service);
+ }
+
static bool IsMainResourceType(ResourceType type) {
return IsResourceTypeFrame(type) ||
type == RESOURCE_TYPE_SHARED_WORKER;
diff --git a/chromium/content/browser/appcache/appcache_response.cc b/chromium/content/browser/appcache/appcache_response.cc
index 20a8b8a36d0..b5df22dea85 100644
--- a/chromium/content/browser/appcache/appcache_response.cc
+++ b/chromium/content/browser/appcache/appcache_response.cc
@@ -78,11 +78,24 @@ HttpResponseInfoIOBuffer::HttpResponseInfoIOBuffer(net::HttpResponseInfo* info)
HttpResponseInfoIOBuffer::~HttpResponseInfoIOBuffer() {}
+// AppCacheDiskCacheInterface ----------------------------------------
+
+AppCacheDiskCacheInterface::AppCacheDiskCacheInterface()
+ : weak_factory_(this) {}
+
+base::WeakPtr<AppCacheDiskCacheInterface>
+AppCacheDiskCacheInterface::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
+AppCacheDiskCacheInterface::~AppCacheDiskCacheInterface() {}
+
// AppCacheResponseIO ----------------------------------------------
-AppCacheResponseIO::AppCacheResponseIO(int64_t response_id,
- int64_t group_id,
- AppCacheDiskCacheInterface* disk_cache)
+AppCacheResponseIO::AppCacheResponseIO(
+ int64_t response_id,
+ int64_t group_id,
+ const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache)
: response_id_(response_id),
group_id_(group_id),
disk_cache_(disk_cache),
@@ -177,7 +190,7 @@ void AppCacheResponseIO::OpenEntryCallback(
AppCacheResponseReader::AppCacheResponseReader(
int64_t response_id,
int64_t group_id,
- AppCacheDiskCacheInterface* disk_cache)
+ const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache)
: AppCacheResponseIO(response_id, group_id, disk_cache),
range_offset_(0),
range_length_(std::numeric_limits<int32_t>::max()),
@@ -302,7 +315,7 @@ void AppCacheResponseReader::OnOpenEntryComplete() {
AppCacheResponseWriter::AppCacheResponseWriter(
int64_t response_id,
int64_t group_id,
- AppCacheDiskCacheInterface* disk_cache)
+ const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache)
: AppCacheResponseIO(response_id, group_id, disk_cache),
info_size_(0),
write_position_(0),
@@ -404,7 +417,10 @@ void AppCacheResponseWriter::OnCreateEntryComplete(
AppCacheDiskCacheInterface::Entry** entry, int rv) {
DCHECK(info_buffer_.get() || buffer_.get());
- if (creation_phase_ == INITIAL_ATTEMPT) {
+ if (!disk_cache_) {
+ ScheduleIOCompletionCallback(net::ERR_FAILED);
+ return;
+ } else if (creation_phase_ == INITIAL_ATTEMPT) {
if (rv != net::OK) {
// We may try to overwrite existing entries.
creation_phase_ = DOOM_EXISTING;
@@ -444,7 +460,7 @@ void AppCacheResponseWriter::OnCreateEntryComplete(
AppCacheResponseMetadataWriter::AppCacheResponseMetadataWriter(
int64_t response_id,
int64_t group_id,
- AppCacheDiskCacheInterface* disk_cache)
+ const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache)
: AppCacheResponseIO(response_id, group_id, disk_cache),
write_amount_(0),
weak_factory_(this) {}
diff --git a/chromium/content/browser/appcache/appcache_response.h b/chromium/content/browser/appcache/appcache_response.h
index 8543b2b902f..0b709b91068 100644
--- a/chromium/content/browser/appcache/appcache_response.h
+++ b/chromium/content/browser/appcache/appcache_response.h
@@ -93,6 +93,8 @@ class CONTENT_EXPORT AppCacheDiskCacheInterface {
virtual ~Entry() {}
};
+ AppCacheDiskCacheInterface();
+
virtual int CreateEntry(int64_t key,
Entry** entry,
const net::CompletionCallback& callback) = 0;
@@ -102,9 +104,12 @@ class CONTENT_EXPORT AppCacheDiskCacheInterface {
virtual int DoomEntry(int64_t key,
const net::CompletionCallback& callback) = 0;
+ base::WeakPtr<AppCacheDiskCacheInterface> GetWeakPtr();
+
protected:
- friend class base::RefCounted<AppCacheDiskCacheInterface>;
- virtual ~AppCacheDiskCacheInterface() {}
+ virtual ~AppCacheDiskCacheInterface();
+
+ base::WeakPtrFactory<AppCacheDiskCacheInterface> weak_factory_;
};
// Common base class for response reader and writer.
@@ -114,9 +119,10 @@ class CONTENT_EXPORT AppCacheResponseIO {
int64_t response_id() const { return response_id_; }
protected:
- AppCacheResponseIO(int64_t response_id,
- int64_t group_id,
- AppCacheDiskCacheInterface* disk_cache);
+ AppCacheResponseIO(
+ int64_t response_id,
+ int64_t group_id,
+ const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache);
virtual void OnIOComplete(int result) = 0;
virtual void OnOpenEntryComplete() {}
@@ -130,7 +136,7 @@ class CONTENT_EXPORT AppCacheResponseIO {
const int64_t response_id_;
const int64_t group_id_;
- AppCacheDiskCacheInterface* disk_cache_;
+ base::WeakPtr<AppCacheDiskCacheInterface> disk_cache_;
AppCacheDiskCacheInterface::Entry* entry_;
scoped_refptr<HttpResponseInfoIOBuffer> info_buffer_;
scoped_refptr<net::IOBuffer> buffer_;
@@ -190,9 +196,10 @@ class CONTENT_EXPORT AppCacheResponseReader
friend class content::MockAppCacheStorage;
// Should only be constructed by the storage class and derivatives.
- AppCacheResponseReader(int64_t response_id,
- int64_t group_id,
- AppCacheDiskCacheInterface* disk_cache);
+ AppCacheResponseReader(
+ int64_t response_id,
+ int64_t group_id,
+ const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache);
void OnIOComplete(int result) override;
void OnOpenEntryComplete() override;
@@ -247,9 +254,10 @@ class CONTENT_EXPORT AppCacheResponseWriter
protected:
// Should only be constructed by the storage class and derivatives.
- AppCacheResponseWriter(int64_t response_id,
- int64_t group_id,
- AppCacheDiskCacheInterface* disk_cache);
+ AppCacheResponseWriter(
+ int64_t response_id,
+ int64_t group_id,
+ const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache);
private:
friend class AppCacheStorageImpl;
@@ -304,10 +312,12 @@ class CONTENT_EXPORT AppCacheResponseMetadataWriter
protected:
friend class AppCacheStorageImpl;
friend class content::MockAppCacheStorage;
+
// Should only be constructed by the storage class and derivatives.
- AppCacheResponseMetadataWriter(int64_t response_id,
- int64_t group_id,
- AppCacheDiskCacheInterface* disk_cache);
+ AppCacheResponseMetadataWriter(
+ int64_t response_id,
+ int64_t group_id,
+ const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache);
private:
void OnIOComplete(int result) override;
diff --git a/chromium/content/browser/appcache/appcache_service_impl.cc b/chromium/content/browser/appcache/appcache_service_impl.cc
index 2fc5d949d2e..537ca8e81e6 100644
--- a/chromium/content/browser/appcache/appcache_service_impl.cc
+++ b/chromium/content/browser/appcache/appcache_service_impl.cc
@@ -412,9 +412,8 @@ AppCacheServiceImpl::AppCacheServiceImpl(
AppCacheServiceImpl::~AppCacheServiceImpl() {
DCHECK(backends_.empty());
- std::for_each(pending_helpers_.begin(),
- pending_helpers_.end(),
- std::mem_fun(&AsyncHelper::Cancel));
+ for (auto* helper : pending_helpers_)
+ helper->Cancel();
STLDeleteElements(&pending_helpers_);
if (quota_client_)
quota_client_->NotifyAppCacheDestroyed();
diff --git a/chromium/content/browser/appcache/appcache_service_unittest.cc b/chromium/content/browser/appcache/appcache_service_unittest.cc
index 79febf7675a..5c29d50ee5f 100644
--- a/chromium/content/browser/appcache/appcache_service_unittest.cc
+++ b/chromium/content/browser/appcache/appcache_service_unittest.cc
@@ -42,7 +42,9 @@ class MockResponseReader : public AppCacheResponseReader {
int info_size,
const char* data,
int data_size)
- : AppCacheResponseReader(response_id, 0, NULL),
+ : AppCacheResponseReader(response_id,
+ 0,
+ base::WeakPtr<AppCacheDiskCacheInterface>()),
info_(info),
info_size_(info_size),
data_(data),
diff --git a/chromium/content/browser/appcache/appcache_storage_impl.cc b/chromium/content/browser/appcache/appcache_storage_impl.cc
index b144eb69f51..ceb52271fd8 100644
--- a/chromium/content/browser/appcache/appcache_storage_impl.cc
+++ b/chromium/content/browser/appcache/appcache_storage_impl.cc
@@ -837,11 +837,7 @@ void AppCacheStorageImpl::StoreGroupAndCacheTask::CancelCompletion() {
// Helpers for FindMainResponseTask::Run()
namespace {
-class SortByCachePreference
- : public std::binary_function<
- AppCacheDatabase::EntryRecord,
- AppCacheDatabase::EntryRecord,
- bool> {
+class SortByCachePreference {
public:
SortByCachePreference(int64_t preferred_id,
const std::set<int64_t>& in_use_ids)
@@ -1423,12 +1419,10 @@ AppCacheStorageImpl::AppCacheStorageImpl(AppCacheServiceImpl* service)
}
AppCacheStorageImpl::~AppCacheStorageImpl() {
- std::for_each(pending_quota_queries_.begin(),
- pending_quota_queries_.end(),
- std::mem_fun(&DatabaseTask::CancelCompletion));
- std::for_each(scheduled_database_tasks_.begin(),
- scheduled_database_tasks_.end(),
- std::mem_fun(&DatabaseTask::CancelCompletion));
+ for (auto* task : pending_quota_queries_)
+ task->CancelCompletion();
+ for (auto* task : scheduled_database_tasks_)
+ task->CancelCompletion();
if (database_ &&
!db_thread_->PostTask(
@@ -1742,20 +1736,22 @@ AppCacheResponseReader* AppCacheStorageImpl::CreateResponseReader(
const GURL& manifest_url,
int64_t group_id,
int64_t response_id) {
- return new AppCacheResponseReader(response_id, group_id, disk_cache());
+ return new AppCacheResponseReader(response_id, group_id,
+ disk_cache()->GetWeakPtr());
}
AppCacheResponseWriter* AppCacheStorageImpl::CreateResponseWriter(
const GURL& manifest_url,
int64_t group_id) {
- return new AppCacheResponseWriter(NewResponseId(), group_id, disk_cache());
+ return new AppCacheResponseWriter(NewResponseId(), group_id,
+ disk_cache()->GetWeakPtr());
}
AppCacheResponseMetadataWriter*
AppCacheStorageImpl::CreateResponseMetadataWriter(int64_t group_id,
int64_t response_id) {
return new AppCacheResponseMetadataWriter(response_id, group_id,
- disk_cache());
+ disk_cache()->GetWeakPtr());
}
void AppCacheStorageImpl::DoomResponses(
diff --git a/chromium/content/browser/appcache/appcache_update_job.cc b/chromium/content/browser/appcache/appcache_update_job.cc
index b6ab3fb7318..7c922f868a7 100644
--- a/chromium/content/browser/appcache/appcache_update_job.cc
+++ b/chromium/content/browser/appcache/appcache_update_job.cc
@@ -140,6 +140,8 @@ AppCacheUpdateJob::UrlToFetch::UrlToFetch(const GURL& url,
existing_response_info(info) {
}
+AppCacheUpdateJob::UrlToFetch::UrlToFetch(const UrlToFetch& other) = default;
+
AppCacheUpdateJob::UrlToFetch::~UrlToFetch() {
}
@@ -279,7 +281,7 @@ void AppCacheUpdateJob::URLFetcher::AddConditionalHeaders(
// Add If-Modified-Since header if response info has Last-Modified header.
const std::string last_modified = "Last-Modified";
std::string last_modified_value;
- headers->EnumerateHeader(NULL, last_modified, &last_modified_value);
+ headers->EnumerateHeader(nullptr, last_modified, &last_modified_value);
if (!last_modified_value.empty()) {
extra_headers.SetHeader(net::HttpRequestHeaders::kIfModifiedSince,
last_modified_value);
@@ -288,7 +290,7 @@ void AppCacheUpdateJob::URLFetcher::AddConditionalHeaders(
// Add If-None-Match header if response info has ETag header.
const std::string etag = "ETag";
std::string etag_value;
- headers->EnumerateHeader(NULL, etag, &etag_value);
+ headers->EnumerateHeader(nullptr, etag, &etag_value);
if (!etag_value.empty()) {
extra_headers.SetHeader(net::HttpRequestHeaders::kIfNoneMatch,
etag_value);
@@ -1474,7 +1476,7 @@ void AppCacheUpdateJob::OnResponseInfoLoaded(
// Responses with a "vary" header get treated as expired.
const std::string name = "vary";
std::string value;
- void* iter = NULL;
+ size_t iter = 0;
if (!http_info->headers.get() ||
http_info->headers->RequiresValidation(http_info->request_time,
http_info->response_time,
diff --git a/chromium/content/browser/appcache/appcache_update_job.h b/chromium/content/browser/appcache/appcache_update_job.h
index f1c7af03bd5..4fa15885c88 100644
--- a/chromium/content/browser/appcache/appcache_update_job.h
+++ b/chromium/content/browser/appcache/appcache_update_job.h
@@ -101,6 +101,7 @@ class CONTENT_EXPORT AppCacheUpdateJob
struct UrlToFetch {
UrlToFetch(const GURL& url, bool checked, AppCacheResponseInfo* info);
+ UrlToFetch(const UrlToFetch& other);
~UrlToFetch();
GURL url;
diff --git a/chromium/content/browser/appcache/appcache_url_request_job.cc b/chromium/content/browser/appcache/appcache_url_request_job.cc
index 05fe008b54e..35728e66de5 100644
--- a/chromium/content/browser/appcache/appcache_url_request_job.cc
+++ b/chromium/content/browser/appcache/appcache_url_request_job.cc
@@ -433,6 +433,12 @@ int AppCacheURLRequestJob::ReadRawData(net::IOBuffer* buf, int buf_size) {
return net::ERR_IO_PENDING;
}
+net::HostPortPair AppCacheURLRequestJob::GetSocketAddress() const {
+ if (!http_info())
+ return net::HostPortPair();
+ return http_info()->socket_address;
+}
+
void AppCacheURLRequestJob::SetExtraRequestHeaders(
const net::HttpRequestHeaders& headers) {
std::string value;
diff --git a/chromium/content/browser/appcache/appcache_url_request_job.h b/chromium/content/browser/appcache/appcache_url_request_job.h
index 057c13b98e4..5b8723761a5 100644
--- a/chromium/content/browser/appcache/appcache_url_request_job.h
+++ b/chromium/content/browser/appcache/appcache_url_request_job.h
@@ -152,6 +152,7 @@ class CONTENT_EXPORT AppCacheURLRequestJob
bool GetCharset(std::string* charset) override;
void GetResponseInfo(net::HttpResponseInfo* info) override;
int ReadRawData(net::IOBuffer* buf, int buf_size) override;
+ net::HostPortPair GetSocketAddress() const override;
// Sets extra request headers for Job types that support request headers.
// This is how we get informed of range-requests.
diff --git a/chromium/content/browser/appcache/chrome_appcache_service_unittest.cc b/chromium/content/browser/appcache/chrome_appcache_service_unittest.cc
index 0eca5fe0cfb..a23bde6f0e5 100644
--- a/chromium/content/browser/appcache/chrome_appcache_service_unittest.cc
+++ b/chromium/content/browser/appcache/chrome_appcache_service_unittest.cc
@@ -102,14 +102,11 @@ ChromeAppCacheServiceTest::CreateAppCacheServiceImpl(
browser_context_.GetResourceContext()->GetRequestContext(),
message_loop_.task_runner().get());
BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
+ BrowserThread::IO, FROM_HERE,
base::Bind(&ChromeAppCacheService::InitializeOnIOThread,
- appcache_service.get(),
- appcache_path,
+ appcache_service.get(), appcache_path,
browser_context_.GetResourceContext(),
- mock_request_context_getter,
- mock_policy));
+ base::RetainedRef(mock_request_context_getter), mock_policy));
// Steps needed to initialize the storage of AppCache data.
message_loop_.RunUntilIdle();
if (init_storage) {
diff --git a/chromium/content/browser/appcache/mock_appcache_storage.cc b/chromium/content/browser/appcache/mock_appcache_storage.cc
index 09bdf03c2ac..5d7cd8d19d9 100644
--- a/chromium/content/browser/appcache/mock_appcache_storage.cc
+++ b/chromium/content/browser/appcache/mock_appcache_storage.cc
@@ -169,20 +169,22 @@ AppCacheResponseReader* MockAppCacheStorage::CreateResponseReader(
int64_t response_id) {
if (simulated_reader_)
return simulated_reader_.release();
- return new AppCacheResponseReader(response_id, group_id, disk_cache());
+ return new AppCacheResponseReader(response_id, group_id,
+ disk_cache()->GetWeakPtr());
}
AppCacheResponseWriter* MockAppCacheStorage::CreateResponseWriter(
const GURL& manifest_url,
int64_t group_id) {
- return new AppCacheResponseWriter(NewResponseId(), group_id, disk_cache());
+ return new AppCacheResponseWriter(NewResponseId(), group_id,
+ disk_cache()->GetWeakPtr());
}
AppCacheResponseMetadataWriter*
MockAppCacheStorage::CreateResponseMetadataWriter(int64_t group_id,
int64_t response_id) {
return new AppCacheResponseMetadataWriter(response_id, group_id,
- disk_cache());
+ disk_cache()->GetWeakPtr());
}
void MockAppCacheStorage::DoomResponses(
diff --git a/chromium/content/browser/background_sync/background_sync.proto b/chromium/content/browser/background_sync/background_sync.proto
index 11adc3133c3..62dbe72b359 100644
--- a/chromium/content/browser/background_sync/background_sync.proto
+++ b/chromium/content/browser/background_sync/background_sync.proto
@@ -14,23 +14,13 @@ enum SyncNetworkState {
NETWORK_STATE_ONLINE = 2;
}
-enum SyncPowerState {
- POWER_STATE_AUTO = 0;
- POWER_STATE_AVOID_DRAINING = 1;
-}
-
-enum SyncPeriodicity {
- SYNC_PERIODIC = 0;
- SYNC_ONE_SHOT = 1;
-}
-
message BackgroundSyncRegistrationProto {
required int64 id = 1;
required string tag = 2;
- required SyncPeriodicity periodicity = 3;
- required int64 min_period = 4;
+ // required SyncPeriodicity periodicity = 3;
+ // required int64 min_period = 4;
required SyncNetworkState network_state = 5;
- required SyncPowerState power_state = 6;
+ // required SyncPowerState power_state = 6;
required int32 num_attempts = 7;
required int64 delay_until = 8;
}
diff --git a/chromium/content/browser/background_sync/background_sync_browsertest.cc b/chromium/content/browser/background_sync/background_sync_browsertest.cc
index a5de6ada408..4113137ef62 100644
--- a/chromium/content/browser/background_sync/background_sync_browsertest.cc
+++ b/chromium/content/browser/background_sync/background_sync_browsertest.cc
@@ -15,7 +15,6 @@
#include "base/task_runner_util.h"
#include "content/browser/background_sync/background_sync_manager.h"
#include "content/browser/background_sync/background_sync_network_observer.h"
-#include "content/browser/background_sync/background_sync_registration_handle.h"
#include "content/browser/background_sync/background_sync_status.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_registration.h"
@@ -42,7 +41,10 @@ namespace {
const char kDefaultTestURL[] = "/background_sync/test.html";
const char kEmptyURL[] = "/background_sync/empty.html";
-const char kRegisterSyncURL[] = "/background_sync/register_sync.html";
+const char kRegisterSyncFromIFrameURL[] =
+ "/background_sync/register_sync_from_iframe.html";
+const char kRegisterSyncFromSWURL[] =
+ "/background_sync/register_sync_from_sw.html";
const char kSuccessfulOperationPrefix[] = "ok - ";
@@ -57,7 +59,7 @@ std::string BuildExpectedResult(const std::string& tag,
action.c_str());
}
-void OneShotPendingCallback(
+void RegistrationPendingCallback(
const base::Closure& quit,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
bool* result_out,
@@ -66,16 +68,24 @@ void OneShotPendingCallback(
task_runner->PostTask(FROM_HERE, quit);
}
-void OneShotPendingDidGetSyncRegistration(
+void RegistrationPendingDidGetSyncRegistration(
+ const std::string& tag,
const base::Callback<void(bool)>& callback,
BackgroundSyncStatus error_type,
- scoped_ptr<BackgroundSyncRegistrationHandle> registration_handle) {
+ scoped_ptr<ScopedVector<BackgroundSyncRegistration>> registrations) {
ASSERT_EQ(BACKGROUND_SYNC_STATUS_OK, error_type);
- callback.Run(registration_handle->sync_state() ==
- BACKGROUND_SYNC_STATE_PENDING);
+ // Find the right registration in the list and check its status.
+ for (const BackgroundSyncRegistration* registration : *registrations) {
+ if (registration->options()->tag == tag) {
+ callback.Run(registration->sync_state() ==
+ mojom::BackgroundSyncState::PENDING);
+ return;
+ }
+ }
+ ADD_FAILURE() << "Registration should exist";
}
-void OneShotPendingDidGetSWRegistration(
+void RegistrationPendingDidGetSWRegistration(
const scoped_refptr<BackgroundSyncContext> sync_context,
const std::string& tag,
const base::Callback<void(bool)>& callback,
@@ -84,20 +94,20 @@ void OneShotPendingDidGetSWRegistration(
ASSERT_EQ(SERVICE_WORKER_OK, status);
int64_t service_worker_id = registration->id();
BackgroundSyncManager* sync_manager = sync_context->background_sync_manager();
- sync_manager->GetRegistration(
- service_worker_id, tag, SYNC_ONE_SHOT,
- base::Bind(&OneShotPendingDidGetSyncRegistration, callback));
+ sync_manager->GetRegistrations(
+ service_worker_id,
+ base::Bind(&RegistrationPendingDidGetSyncRegistration, tag, callback));
}
-void OneShotPendingOnIOThread(
+void RegistrationPendingOnIOThread(
const scoped_refptr<BackgroundSyncContext> sync_context,
const scoped_refptr<ServiceWorkerContextWrapper> sw_context,
const std::string& tag,
const GURL& url,
const base::Callback<void(bool)>& callback) {
sw_context->FindReadyRegistrationForDocument(
- url, base::Bind(&OneShotPendingDidGetSWRegistration, sync_context, tag,
- callback));
+ url, base::Bind(&RegistrationPendingDidGetSWRegistration, sync_context,
+ tag, callback));
}
void SetMaxSyncAttemptsOnIOThread(
@@ -169,9 +179,9 @@ class BackgroundSyncBrowserTest : public ContentBrowserTest {
result);
}
- // Returns true if the one-shot sync with tag is currently pending. Fails
+ // Returns true if the registration with tag |tag| is currently pending. Fails
// (assertion failure) if the tag isn't registered.
- bool OneShotPending(const std::string& tag);
+ bool RegistrationPending(const std::string& tag);
// Sets the BackgroundSyncManager's max sync attempts per registration.
void SetMaxSyncAttempts(int max_sync_attempts);
@@ -181,17 +191,18 @@ class BackgroundSyncBrowserTest : public ContentBrowserTest {
std::string PopConsoleString();
bool PopConsole(const std::string& expected_msg);
bool RegisterServiceWorker();
- bool RegisterOneShot(const std::string& tag);
- bool RegisterOneShotFromServiceWorker(const std::string& tag);
- bool GetRegistrationOneShot(const std::string& tag);
- bool GetRegistrationOneShotFromServiceWorker(const std::string& tag);
- bool MatchRegistrations(const std::string& script_result,
- const std::vector<std::string>& expected_tags);
- bool GetRegistrationsOneShot(const std::vector<std::string>& expected_tags);
- bool GetRegistrationsOneShotFromServiceWorker(
- const std::vector<std::string>& expected_tags);
- bool CompleteDelayedOneShot();
- bool RejectDelayedOneShot();
+ bool Register(const std::string& tag);
+ bool RegisterFromServiceWorker(const std::string& tag);
+ bool RegisterFromCrossOriginFrame(const std::string& frame_url,
+ std::string* script_result);
+ bool HasTag(const std::string& tag);
+ bool HasTagFromServiceWorker(const std::string& tag);
+ bool MatchTags(const std::string& script_result,
+ const std::vector<std::string>& expected_tags);
+ bool GetTags(const std::vector<std::string>& expected_tags);
+ bool GetTagsFromServiceWorker(const std::vector<std::string>& expected_tags);
+ bool CompleteDelayedSyncEvent();
+ bool RejectDelayedSyncEvent();
net::EmbeddedTestServer* https_server() { return https_server_.get(); }
@@ -202,7 +213,7 @@ class BackgroundSyncBrowserTest : public ContentBrowserTest {
DISALLOW_COPY_AND_ASSIGN(BackgroundSyncBrowserTest);
};
-bool BackgroundSyncBrowserTest::OneShotPending(const std::string& tag) {
+bool BackgroundSyncBrowserTest::RegistrationPending(const std::string& tag) {
bool is_pending;
base::RunLoop run_loop;
@@ -213,12 +224,13 @@ bool BackgroundSyncBrowserTest::OneShotPending(const std::string& tag) {
storage->GetServiceWorkerContext());
base::Callback<void(bool)> callback =
- base::Bind(&OneShotPendingCallback, run_loop.QuitClosure(),
+ base::Bind(&RegistrationPendingCallback, run_loop.QuitClosure(),
base::ThreadTaskRunnerHandle::Get(), &is_pending);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&OneShotPendingOnIOThread, make_scoped_refptr(sync_context),
+ base::Bind(&RegistrationPendingOnIOThread,
+ make_scoped_refptr(sync_context),
make_scoped_refptr(service_worker_context), tag,
https_server_->GetURL(kDefaultTestURL), callback));
@@ -281,41 +293,51 @@ bool BackgroundSyncBrowserTest::RegisterServiceWorker() {
return script_result == BuildExpectedResult("service worker", "registered");
}
-bool BackgroundSyncBrowserTest::RegisterOneShot(const std::string& tag) {
+bool BackgroundSyncBrowserTest::Register(const std::string& tag) {
std::string script_result;
- EXPECT_TRUE(
- RunScript(BuildScriptString("registerOneShot", tag), &script_result));
+ EXPECT_TRUE(RunScript(BuildScriptString("register", tag), &script_result));
return script_result == BuildExpectedResult(tag, "registered");
}
-bool BackgroundSyncBrowserTest::RegisterOneShotFromServiceWorker(
+bool BackgroundSyncBrowserTest::RegisterFromServiceWorker(
const std::string& tag) {
std::string script_result;
- EXPECT_TRUE(
- RunScript(BuildScriptString("registerOneShotFromServiceWorker", tag),
- &script_result));
+ EXPECT_TRUE(RunScript(BuildScriptString("registerFromServiceWorker", tag),
+ &script_result));
return script_result == BuildExpectedResult(tag, "register sent to SW");
}
-bool BackgroundSyncBrowserTest::GetRegistrationOneShot(const std::string& tag) {
+bool BackgroundSyncBrowserTest::RegisterFromCrossOriginFrame(
+ const std::string& frame_url,
+ std::string* script_result) {
+ // Start a second https server to use as a second origin.
+ net::EmbeddedTestServer alt_server(net::EmbeddedTestServer::TYPE_HTTPS);
+ alt_server.ServeFilesFromSourceDirectory("content/test/data");
+ EXPECT_TRUE(alt_server.Start());
+
+ GURL url = alt_server.GetURL(frame_url);
+ return RunScript(
+ BuildScriptString("registerFromCrossOriginFrame", url.spec()),
+ script_result);
+}
+
+bool BackgroundSyncBrowserTest::HasTag(const std::string& tag) {
std::string script_result;
- EXPECT_TRUE(RunScript(BuildScriptString("getRegistrationOneShot", tag),
- &script_result));
+ EXPECT_TRUE(RunScript(BuildScriptString("hasTag", tag), &script_result));
return script_result == BuildExpectedResult(tag, "found");
}
-bool BackgroundSyncBrowserTest::GetRegistrationOneShotFromServiceWorker(
+bool BackgroundSyncBrowserTest::HasTagFromServiceWorker(
const std::string& tag) {
std::string script_result;
- EXPECT_TRUE(RunScript(
- BuildScriptString("getRegistrationOneShotFromServiceWorker", tag),
- &script_result));
- EXPECT_TRUE(script_result == "ok - getRegistration sent to SW");
+ EXPECT_TRUE(RunScript(BuildScriptString("hasTagFromServiceWorker", tag),
+ &script_result));
+ EXPECT_TRUE(script_result == "ok - hasTag sent to SW");
return PopConsole(BuildExpectedResult(tag, "found"));
}
-bool BackgroundSyncBrowserTest::MatchRegistrations(
+bool BackgroundSyncBrowserTest::MatchTags(
const std::string& script_result,
const std::vector<std::string>& expected_tags) {
EXPECT_TRUE(base::StartsWith(script_result, kSuccessfulOperationPrefix,
@@ -329,79 +351,80 @@ bool BackgroundSyncBrowserTest::MatchRegistrations(
std::set<std::string>(result_tags.begin(), result_tags.end());
}
-bool BackgroundSyncBrowserTest::GetRegistrationsOneShot(
+bool BackgroundSyncBrowserTest::GetTags(
const std::vector<std::string>& expected_tags) {
std::string script_result;
- EXPECT_TRUE(RunScript("getRegistrationsOneShot()", &script_result));
+ EXPECT_TRUE(RunScript("getTags()", &script_result));
- return MatchRegistrations(script_result, expected_tags);
+ return MatchTags(script_result, expected_tags);
}
-bool BackgroundSyncBrowserTest::GetRegistrationsOneShotFromServiceWorker(
+bool BackgroundSyncBrowserTest::GetTagsFromServiceWorker(
const std::vector<std::string>& expected_tags) {
std::string script_result;
- EXPECT_TRUE(
- RunScript("getRegistrationsOneShotFromServiceWorker()", &script_result));
- EXPECT_TRUE(script_result == "ok - getRegistrations sent to SW");
+ EXPECT_TRUE(RunScript("getTagsFromServiceWorker()", &script_result));
+ EXPECT_TRUE(script_result == "ok - getTags sent to SW");
- return MatchRegistrations(PopConsoleString(), expected_tags);
+ return MatchTags(PopConsoleString(), expected_tags);
}
-bool BackgroundSyncBrowserTest::CompleteDelayedOneShot() {
+bool BackgroundSyncBrowserTest::CompleteDelayedSyncEvent() {
std::string script_result;
- EXPECT_TRUE(RunScript("completeDelayedOneShot()", &script_result));
+ EXPECT_TRUE(RunScript("completeDelayedSyncEvent()", &script_result));
return script_result == BuildExpectedResult("delay", "completing");
}
-bool BackgroundSyncBrowserTest::RejectDelayedOneShot() {
+bool BackgroundSyncBrowserTest::RejectDelayedSyncEvent() {
std::string script_result;
- EXPECT_TRUE(RunScript("rejectDelayedOneShot()", &script_result));
+ EXPECT_TRUE(RunScript("rejectDelayedSyncEvent()", &script_result));
return script_result == BuildExpectedResult("delay", "rejecting");
}
-IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, OneShotFiresControlled) {
+IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest,
+ RegisterFromControlledDocument) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
- EXPECT_TRUE(RegisterOneShot("foo"));
+ EXPECT_TRUE(Register("foo"));
EXPECT_TRUE(PopConsole("foo fired"));
- EXPECT_FALSE(GetRegistrationOneShot("foo"));
+ EXPECT_FALSE(HasTag("foo"));
}
-IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, OneShotFiresUncontrolled) {
+IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest,
+ RegisterFromUncontrolledDocument) {
EXPECT_TRUE(RegisterServiceWorker());
- EXPECT_TRUE(RegisterOneShot("foo"));
+ EXPECT_TRUE(Register("foo"));
EXPECT_TRUE(PopConsole("foo fired"));
- EXPECT_FALSE(GetRegistrationOneShot("foo"));
+ EXPECT_FALSE(HasTag("foo"));
}
// Verify that Register works in a service worker
-IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest,
- OneShotFromServiceWorkerFires) {
+IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, RegisterFromServiceWorker) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
- EXPECT_TRUE(RegisterOneShotFromServiceWorker("foo_sw"));
+ EXPECT_TRUE(RegisterFromServiceWorker("foo_sw"));
EXPECT_TRUE(PopConsole("ok - foo_sw registered in SW"));
EXPECT_TRUE(PopConsole("foo_sw fired"));
- EXPECT_FALSE(GetRegistrationOneShot("foo_sw"));
+ EXPECT_FALSE(HasTag("foo_sw"));
}
-IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, OneShotDelaysForNetwork) {
+IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest,
+ RegistrationDelaysForNetwork) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
// Prevent firing by going offline.
background_sync_test_util::SetOnline(web_contents(), false);
- EXPECT_TRUE(RegisterOneShot("foo"));
- EXPECT_TRUE(GetRegistrationOneShot("foo"));
- EXPECT_TRUE(OneShotPending("foo"));
+ EXPECT_TRUE(Register("foo"));
+ EXPECT_TRUE(HasTag("foo"));
+ EXPECT_TRUE(RegistrationPending("foo"));
// Resume firing by going online.
background_sync_test_util::SetOnline(web_contents(), true);
EXPECT_TRUE(PopConsole("foo fired"));
- EXPECT_FALSE(GetRegistrationOneShot("foo"));
+ EXPECT_FALSE(HasTag("foo"));
}
IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, WaitUntil) {
@@ -409,18 +432,18 @@ IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, WaitUntil) {
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
background_sync_test_util::SetOnline(web_contents(), true);
- EXPECT_TRUE(RegisterOneShot("delay"));
+ EXPECT_TRUE(Register("delay"));
// Verify that it is firing.
- EXPECT_TRUE(GetRegistrationOneShot("delay"));
- EXPECT_FALSE(OneShotPending("delay"));
+ EXPECT_TRUE(HasTag("delay"));
+ EXPECT_FALSE(RegistrationPending("delay"));
// Complete the task.
- EXPECT_TRUE(CompleteDelayedOneShot());
+ EXPECT_TRUE(CompleteDelayedSyncEvent());
EXPECT_TRUE(PopConsole("ok - delay completed"));
// Verify that it finished firing.
- EXPECT_FALSE(GetRegistrationOneShot("delay"));
+ EXPECT_FALSE(HasTag("delay"));
}
IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, WaitUntilReject) {
@@ -428,16 +451,16 @@ IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, WaitUntilReject) {
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
background_sync_test_util::SetOnline(web_contents(), true);
- EXPECT_TRUE(RegisterOneShot("delay"));
+ EXPECT_TRUE(Register("delay"));
// Verify that it is firing.
- EXPECT_TRUE(GetRegistrationOneShot("delay"));
- EXPECT_FALSE(OneShotPending("delay"));
+ EXPECT_TRUE(HasTag("delay"));
+ EXPECT_FALSE(RegistrationPending("delay"));
// Complete the task.
- EXPECT_TRUE(RejectDelayedOneShot());
+ EXPECT_TRUE(RejectDelayedSyncEvent());
EXPECT_TRUE(PopConsole("ok - delay rejected"));
- EXPECT_FALSE(GetRegistrationOneShot("delay"));
+ EXPECT_FALSE(HasTag("delay"));
}
IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, Incognito) {
@@ -445,8 +468,8 @@ IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, Incognito) {
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
background_sync_test_util::SetOnline(web_contents(), false);
- EXPECT_TRUE(RegisterOneShot("normal"));
- EXPECT_TRUE(OneShotPending("normal"));
+ EXPECT_TRUE(Register("normal"));
+ EXPECT_TRUE(RegistrationPending("normal"));
// Go incognito and verify that incognito doesn't see the registration.
SetIncognitoMode(true);
@@ -459,34 +482,34 @@ IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, Incognito) {
EXPECT_TRUE(LoadTestPage(kDefaultTestURL));
EXPECT_TRUE(RegisterServiceWorker());
- EXPECT_FALSE(GetRegistrationOneShot("normal"));
+ EXPECT_FALSE(HasTag("normal"));
- EXPECT_TRUE(RegisterOneShot("incognito"));
- EXPECT_TRUE(OneShotPending("incognito"));
+ EXPECT_TRUE(Register("incognito"));
+ EXPECT_TRUE(RegistrationPending("incognito"));
// Switch back and make sure the registration is still there.
SetIncognitoMode(false);
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Should be controlled.
- EXPECT_TRUE(GetRegistrationOneShot("normal"));
- EXPECT_FALSE(GetRegistrationOneShot("incognito"));
+ EXPECT_TRUE(HasTag("normal"));
+ EXPECT_FALSE(HasTag("incognito"));
}
-IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, GetRegistrations) {
+IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, GetTags) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
std::vector<std::string> registered_tags;
- EXPECT_TRUE(GetRegistrationsOneShot(registered_tags));
+ EXPECT_TRUE(GetTags(registered_tags));
background_sync_test_util::SetOnline(web_contents(), false);
registered_tags.push_back("foo");
registered_tags.push_back("bar");
for (const std::string& tag : registered_tags)
- EXPECT_TRUE(RegisterOneShot(tag));
+ EXPECT_TRUE(Register(tag));
- EXPECT_TRUE(GetRegistrationsOneShot(registered_tags));
+ EXPECT_TRUE(GetTags(registered_tags));
}
// Verify that GetRegistrations works in a service worker
@@ -496,34 +519,33 @@ IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest,
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
std::vector<std::string> registered_tags;
- EXPECT_TRUE(GetRegistrationsOneShot(registered_tags));
+ EXPECT_TRUE(GetTags(registered_tags));
background_sync_test_util::SetOnline(web_contents(), false);
registered_tags.push_back("foo_sw");
registered_tags.push_back("bar_sw");
for (const std::string& tag : registered_tags) {
- EXPECT_TRUE(RegisterOneShotFromServiceWorker(tag));
+ EXPECT_TRUE(RegisterFromServiceWorker(tag));
EXPECT_TRUE(PopConsole(BuildExpectedResult(tag, "registered in SW")));
}
- EXPECT_TRUE(GetRegistrationsOneShotFromServiceWorker(registered_tags));
+ EXPECT_TRUE(GetTagsFromServiceWorker(registered_tags));
}
// Verify that GetRegistration works in a service worker
-IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest,
- GetRegistrationFromServiceWorker) {
+IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, HasTagFromServiceWorker) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
std::vector<std::string> registered_tags;
- EXPECT_TRUE(GetRegistrationsOneShot(registered_tags));
+ EXPECT_TRUE(GetTags(registered_tags));
background_sync_test_util::SetOnline(web_contents(), false);
- EXPECT_TRUE(RegisterOneShotFromServiceWorker("foo_sw"));
+ EXPECT_TRUE(RegisterFromServiceWorker("foo_sw"));
EXPECT_TRUE(PopConsole("ok - foo_sw registered in SW"));
- EXPECT_TRUE(GetRegistrationOneShotFromServiceWorker("foo_sw"));
+ EXPECT_TRUE(HasTagFromServiceWorker("foo_sw"));
}
// Verify that a background sync registration is deleted when site data is
@@ -535,15 +557,15 @@ IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest,
// Prevent firing by going offline.
background_sync_test_util::SetOnline(web_contents(), false);
- EXPECT_TRUE(RegisterOneShot("foo"));
- EXPECT_TRUE(GetRegistrationOneShot("foo"));
- EXPECT_TRUE(OneShotPending("foo"));
+ EXPECT_TRUE(Register("foo"));
+ EXPECT_TRUE(HasTag("foo"));
+ EXPECT_TRUE(RegistrationPending("foo"));
// Simulate a user clearing site data (including Service Workers, crucially),
// by clearing data from the storage partition.
ClearStoragePartitionData();
- EXPECT_FALSE(GetRegistrationOneShot("foo"));
+ EXPECT_FALSE(HasTag("foo"));
}
// Verify that a background sync registration, from a service worker, is deleted
@@ -554,19 +576,19 @@ IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest,
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
std::vector<std::string> registered_tags;
- EXPECT_TRUE(GetRegistrationsOneShot(registered_tags));
+ EXPECT_TRUE(GetTags(registered_tags));
background_sync_test_util::SetOnline(web_contents(), false);
- EXPECT_TRUE(RegisterOneShotFromServiceWorker("foo_sw"));
+ EXPECT_TRUE(RegisterFromServiceWorker("foo_sw"));
EXPECT_TRUE(PopConsole("ok - foo_sw registered in SW"));
- EXPECT_TRUE(GetRegistrationOneShotFromServiceWorker("foo_sw"));
+ EXPECT_TRUE(HasTagFromServiceWorker("foo_sw"));
// Simulate a user clearing site data (including Service Workers, crucially),
// by clearing data from the storage partition.
ClearStoragePartitionData();
- EXPECT_FALSE(GetRegistrationOneShotFromServiceWorker("foo"));
+ EXPECT_FALSE(HasTagFromServiceWorker("foo"));
}
// Verify that multiple background sync registrations are deleted when site
@@ -577,26 +599,26 @@ IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest,
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
std::vector<std::string> registered_tags;
- EXPECT_TRUE(GetRegistrationsOneShot(registered_tags));
+ EXPECT_TRUE(GetTags(registered_tags));
background_sync_test_util::SetOnline(web_contents(), false);
registered_tags.push_back("foo");
registered_tags.push_back("bar");
for (const std::string& tag : registered_tags)
- EXPECT_TRUE(RegisterOneShot(tag));
+ EXPECT_TRUE(Register(tag));
- EXPECT_TRUE(GetRegistrationsOneShot(registered_tags));
+ EXPECT_TRUE(GetTags(registered_tags));
for (const std::string& tag : registered_tags)
- EXPECT_TRUE(OneShotPending(tag));
+ EXPECT_TRUE(RegistrationPending(tag));
// Simulate a user clearing site data (including Service Workers, crucially),
// by clearing data from the storage partition.
ClearStoragePartitionData();
for (const std::string& tag : registered_tags)
- EXPECT_FALSE(GetRegistrationOneShot(tag));
+ EXPECT_FALSE(HasTag(tag));
}
// Verify that a sync event that is currently firing is deleted when site
@@ -607,58 +629,59 @@ IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest,
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
background_sync_test_util::SetOnline(web_contents(), true);
- EXPECT_TRUE(RegisterOneShot("delay"));
+ EXPECT_TRUE(Register("delay"));
// Verify that it is firing.
- EXPECT_TRUE(GetRegistrationOneShot("delay"));
- EXPECT_FALSE(OneShotPending("delay"));
+ EXPECT_TRUE(HasTag("delay"));
+ EXPECT_FALSE(RegistrationPending("delay"));
// Simulate a user clearing site data (including Service Workers, crucially),
// by clearing data from the storage partition.
ClearStoragePartitionData();
// Verify that it was deleted.
- EXPECT_FALSE(GetRegistrationOneShot("delay"));
+ EXPECT_FALSE(HasTag("delay"));
}
-IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, VerifyRetry) {
+// Disabled due to flakiness. See https://crbug.com/578952.
+IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, DISABLED_VerifyRetry) {
EXPECT_TRUE(RegisterServiceWorker());
EXPECT_TRUE(LoadTestPage(kDefaultTestURL)); // Control the page.
SetMaxSyncAttempts(2);
- EXPECT_TRUE(RegisterOneShot("delay"));
- EXPECT_TRUE(RejectDelayedOneShot());
+ EXPECT_TRUE(Register("delay"));
+ EXPECT_TRUE(RejectDelayedSyncEvent());
EXPECT_TRUE(PopConsole("ok - delay rejected"));
- // Verify that the oneshot is still around and waiting to try again.
- EXPECT_TRUE(OneShotPending("delay"));
+ // Verify that the registration is still around and waiting to try again.
+ EXPECT_TRUE(RegistrationPending("delay"));
}
-IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest, RegisterFromNonMainFrame) {
+IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest,
+ RegisterFromIFrameWithMainFrameHost) {
std::string script_result;
GURL url = https_server()->GetURL(kEmptyURL);
+ EXPECT_TRUE(RunScript(BuildScriptString("registerFromLocalFrame", url.spec()),
+ &script_result));
+ EXPECT_EQ(BuildExpectedResult("iframe", "registered sync"), script_result);
+}
+
+IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest,
+ RegisterFromIFrameWithoutMainFrameHost) {
+ std::string script_result;
EXPECT_TRUE(
- RunScript(BuildScriptString("registerOneShotFromLocalFrame", url.spec()),
- &script_result));
- EXPECT_EQ(BuildExpectedResult("iframe", "failed to register sync"),
+ RegisterFromCrossOriginFrame(kRegisterSyncFromIFrameURL, &script_result));
+ EXPECT_EQ(BuildExpectedResult("frame", "failed to register sync"),
script_result);
}
IN_PROC_BROWSER_TEST_F(BackgroundSyncBrowserTest,
RegisterFromServiceWorkerWithoutMainFrameHost) {
- // Start a second https server to use as a second origin.
- net::EmbeddedTestServer alt_server(net::EmbeddedTestServer::TYPE_HTTPS);
- alt_server.ServeFilesFromSourceDirectory("content/test/data");
- ASSERT_TRUE(alt_server.Start());
-
std::string script_result;
- GURL url = alt_server.GetURL(kRegisterSyncURL);
EXPECT_TRUE(
- RunScript(BuildScriptString("registerOneShotFromCrossOriginServiceWorker",
- url.spec()),
- &script_result));
- EXPECT_EQ(BuildExpectedResult("worker", "failed to register sync"),
+ RegisterFromCrossOriginFrame(kRegisterSyncFromSWURL, &script_result));
+ EXPECT_EQ(BuildExpectedResult("frame", "failed to register sync"),
script_result);
}
diff --git a/chromium/content/browser/background_sync/background_sync_context_impl.cc b/chromium/content/browser/background_sync/background_sync_context_impl.cc
index 009e8864b6f..bd92edb8650 100644
--- a/chromium/content/browser/background_sync/background_sync_context_impl.cc
+++ b/chromium/content/browser/background_sync/background_sync_context_impl.cc
@@ -43,7 +43,7 @@ void BackgroundSyncContextImpl::Shutdown() {
}
void BackgroundSyncContextImpl::CreateService(
- mojo::InterfaceRequest<BackgroundSyncService> request) {
+ mojo::InterfaceRequest<mojom::BackgroundSyncService> request) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BrowserThread::PostTask(
@@ -68,8 +68,15 @@ BackgroundSyncManager* BackgroundSyncContextImpl::background_sync_manager()
return background_sync_manager_.get();
}
+void BackgroundSyncContextImpl::set_background_sync_manager_for_testing(
+ scoped_ptr<BackgroundSyncManager> manager) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ background_sync_manager_ = std::move(manager);
+}
+
void BackgroundSyncContextImpl::CreateBackgroundSyncManager(
- const scoped_refptr<ServiceWorkerContextWrapper>& context) {
+ scoped_refptr<ServiceWorkerContextWrapper> context) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!background_sync_manager_);
@@ -77,7 +84,7 @@ void BackgroundSyncContextImpl::CreateBackgroundSyncManager(
}
void BackgroundSyncContextImpl::CreateServiceOnIOThread(
- mojo::InterfaceRequest<BackgroundSyncService> request) {
+ mojo::InterfaceRequest<mojom::BackgroundSyncService> request) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(background_sync_manager_);
services_.insert(new BackgroundSyncServiceImpl(this, std::move(request)));
diff --git a/chromium/content/browser/background_sync/background_sync_context_impl.h b/chromium/content/browser/background_sync/background_sync_context_impl.h
index f30a6392728..1eebe700256 100644
--- a/chromium/content/browser/background_sync/background_sync_context_impl.h
+++ b/chromium/content/browser/background_sync/background_sync_context_impl.h
@@ -37,7 +37,8 @@ class CONTENT_EXPORT BackgroundSyncContextImpl : public BackgroundSyncContext {
// Create a BackgroundSyncServiceImpl that is owned by this. Call on the UI
// thread.
- void CreateService(mojo::InterfaceRequest<BackgroundSyncService> request);
+ void CreateService(
+ mojo::InterfaceRequest<mojom::BackgroundSyncService> request);
// Called by BackgroundSyncServiceImpl objects so that they can
// be deleted. Call on the IO thread.
@@ -49,14 +50,17 @@ class CONTENT_EXPORT BackgroundSyncContextImpl : public BackgroundSyncContext {
protected:
~BackgroundSyncContextImpl() override;
+ void set_background_sync_manager_for_testing(
+ scoped_ptr<BackgroundSyncManager> manager);
+
private:
friend class BackgroundSyncServiceImplTest;
- void CreateBackgroundSyncManager(
- const scoped_refptr<ServiceWorkerContextWrapper>& context);
+ virtual void CreateBackgroundSyncManager(
+ scoped_refptr<ServiceWorkerContextWrapper> context);
void CreateServiceOnIOThread(
- mojo::InterfaceRequest<BackgroundSyncService> request);
+ mojo::InterfaceRequest<mojom::BackgroundSyncService> request);
void ShutdownOnIO();
diff --git a/chromium/content/browser/background_sync/background_sync_manager.cc b/chromium/content/browser/background_sync/background_sync_manager.cc
index 926dbca6dc8..343dd05a4a4 100644
--- a/chromium/content/browser/background_sync/background_sync_manager.cc
+++ b/chromium/content/browser/background_sync/background_sync_manager.cc
@@ -15,8 +15,6 @@
#include "build/build_config.h"
#include "content/browser/background_sync/background_sync_metrics.h"
#include "content/browser/background_sync/background_sync_network_observer.h"
-#include "content/browser/background_sync/background_sync_power_observer.h"
-#include "content/browser/background_sync/background_sync_registration_handle.h"
#include "content/browser/background_sync/background_sync_registration_options.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_storage.h"
@@ -25,6 +23,8 @@
#include "content/public/browser/background_sync_controller.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/permission_manager.h"
+#include "content/public/browser/permission_type.h"
#include "content/public/common/background_sync.mojom.h"
#if defined(OS_ANDROID)
@@ -33,35 +33,24 @@
namespace content {
-class BackgroundSyncManager::RefCountedRegistration
- : public base::RefCounted<RefCountedRegistration> {
- public:
- BackgroundSyncRegistration* value() { return &registration_; }
- const BackgroundSyncRegistration* value() const { return &registration_; }
-
- private:
- friend class base::RefCounted<RefCountedRegistration>;
- ~RefCountedRegistration() = default;
-
- BackgroundSyncRegistration registration_;
-};
-
namespace {
// The key used to index the background sync data in ServiceWorkerStorage.
const char kBackgroundSyncUserDataKey[] = "BackgroundSyncUserData";
-void PostErrorResponse(
+void RecordFailureAndPostError(
BackgroundSyncStatus status,
const BackgroundSyncManager::StatusAndRegistrationCallback& callback) {
+ BackgroundSyncMetrics::CountRegisterFailure(status);
+
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::Bind(callback, status,
- base::Passed(scoped_ptr<BackgroundSyncRegistrationHandle>())));
+ base::Passed(scoped_ptr<BackgroundSyncRegistration>())));
}
-// Returns nullptr if the controller cannot be accessed for any reason.
-BackgroundSyncController* GetBackgroundSyncControllerOnUIThread(
+// Returns nullptr if the browser context cannot be accessed for any reason.
+BrowserContext* GetBrowserContextOnUIThread(
const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -72,8 +61,42 @@ BackgroundSyncController* GetBackgroundSyncControllerOnUIThread(
if (!storage_partition_impl) // may be null in tests
return nullptr;
- return storage_partition_impl->browser_context()
- ->GetBackgroundSyncController();
+ return storage_partition_impl->browser_context();
+}
+
+// Returns nullptr if the controller cannot be accessed for any reason.
+BackgroundSyncController* GetBackgroundSyncControllerOnUIThread(
+ const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ BrowserContext* browser_context =
+ GetBrowserContextOnUIThread(service_worker_context);
+ if (!browser_context)
+ return nullptr;
+
+ return browser_context->GetBackgroundSyncController();
+}
+
+// Returns PermissionStatus::DENIED if the permission manager cannot be
+// accessed for any reason.
+blink::mojom::PermissionStatus GetBackgroundSyncPermissionOnUIThread(
+ const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context,
+ const GURL& origin) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ BrowserContext* browser_context =
+ GetBrowserContextOnUIThread(service_worker_context);
+ if (!browser_context)
+ return blink::mojom::PermissionStatus::DENIED;
+
+ PermissionManager* permission_manager =
+ browser_context->GetPermissionManager();
+ if (!permission_manager)
+ return blink::mojom::PermissionStatus::DENIED;
+
+ // The requesting origin always matches the embedding origin.
+ return permission_manager->GetPermissionStatus(
+ PermissionType::BACKGROUND_SYNC, origin, origin);
}
void NotifyBackgroundSyncRegisteredOnUIThread(
@@ -126,11 +149,12 @@ void OnSyncEventFinished(
const scoped_refptr<ServiceWorkerVersion>& active_version,
int request_id,
const ServiceWorkerVersion::StatusCallback& callback,
- ServiceWorkerEventStatus status) {
- TRACE_EVENT1("ServiceWorker", "BackgroundSyncManager::OnSyncEventFinished",
- "Request id", request_id);
- if (!active_version->FinishRequest(request_id))
+ mojom::ServiceWorkerEventStatus status) {
+ if (!active_version->FinishRequest(
+ request_id,
+ status == content::mojom::ServiceWorkerEventStatus::COMPLETED)) {
return;
+ }
callback.Run(mojo::ConvertTo<ServiceWorkerStatusCode>(status));
}
@@ -141,6 +165,9 @@ BackgroundSyncManager::BackgroundSyncRegistrations::
: next_id(BackgroundSyncRegistration::kInitialId) {
}
+BackgroundSyncManager::BackgroundSyncRegistrations::BackgroundSyncRegistrations(
+ const BackgroundSyncRegistrations& other) = default;
+
BackgroundSyncManager::BackgroundSyncRegistrations::
~BackgroundSyncRegistrations() {
}
@@ -162,74 +189,25 @@ BackgroundSyncManager::~BackgroundSyncManager() {
service_worker_context_->RemoveObserver(this);
}
-BackgroundSyncManager::RegistrationKey::RegistrationKey(
- const BackgroundSyncRegistration& registration)
- : RegistrationKey(registration.options()->tag,
- registration.options()->periodicity) {
-}
-
-BackgroundSyncManager::RegistrationKey::RegistrationKey(
- const BackgroundSyncRegistrationOptions& options)
- : RegistrationKey(options.tag, options.periodicity) {
-}
-
-BackgroundSyncManager::RegistrationKey::RegistrationKey(
- const std::string& tag,
- SyncPeriodicity periodicity)
- : value_(periodicity == SYNC_ONE_SHOT ? "o_" + tag : "p_" + tag) {
-}
-
void BackgroundSyncManager::Register(
int64_t sw_registration_id,
const BackgroundSyncRegistrationOptions& options,
- bool requested_from_service_worker,
const StatusAndRegistrationCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (disabled_) {
- BackgroundSyncMetrics::CountRegisterFailure(
- options.periodicity, BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
- PostErrorResponse(BACKGROUND_SYNC_STATUS_STORAGE_ERROR, callback);
- return;
- }
-
- if (requested_from_service_worker) {
- op_scheduler_.ScheduleOperation(
- base::Bind(&BackgroundSyncManager::RegisterCheckIfHasMainFrame,
- weak_ptr_factory_.GetWeakPtr(), sw_registration_id, options,
- MakeStatusAndRegistrationCompletion(callback)));
+ RecordFailureAndPostError(BACKGROUND_SYNC_STATUS_STORAGE_ERROR, callback);
return;
}
op_scheduler_.ScheduleOperation(
- base::Bind(&BackgroundSyncManager::RegisterImpl,
+ base::Bind(&BackgroundSyncManager::RegisterCheckIfHasMainFrame,
weak_ptr_factory_.GetWeakPtr(), sw_registration_id, options,
MakeStatusAndRegistrationCompletion(callback)));
}
-void BackgroundSyncManager::GetRegistration(
- int64_t sw_registration_id,
- const std::string& sync_registration_tag,
- SyncPeriodicity periodicity,
- const StatusAndRegistrationCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (disabled_) {
- PostErrorResponse(BACKGROUND_SYNC_STATUS_STORAGE_ERROR, callback);
- return;
- }
-
- RegistrationKey registration_key(sync_registration_tag, periodicity);
-
- op_scheduler_.ScheduleOperation(base::Bind(
- &BackgroundSyncManager::GetRegistrationImpl,
- weak_ptr_factory_.GetWeakPtr(), sw_registration_id, registration_key,
- MakeStatusAndRegistrationCompletion(callback)));
-}
-
void BackgroundSyncManager::GetRegistrations(
int64_t sw_registration_id,
- SyncPeriodicity periodicity,
const StatusAndRegistrationsCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -238,30 +216,15 @@ void BackgroundSyncManager::GetRegistrations(
FROM_HERE,
base::Bind(
callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
- base::Passed(
- scoped_ptr<ScopedVector<BackgroundSyncRegistrationHandle>>(
- new ScopedVector<BackgroundSyncRegistrationHandle>()))));
+ base::Passed(scoped_ptr<ScopedVector<BackgroundSyncRegistration>>(
+ new ScopedVector<BackgroundSyncRegistration>()))));
return;
}
op_scheduler_.ScheduleOperation(
base::Bind(&BackgroundSyncManager::GetRegistrationsImpl,
weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
- periodicity, MakeStatusAndRegistrationsCompletion(callback)));
-}
-
-// Given a HandleId |handle_id|, return a new handle for the same
-// registration.
-scoped_ptr<BackgroundSyncRegistrationHandle>
-BackgroundSyncManager::DuplicateRegistrationHandle(
- BackgroundSyncRegistrationHandle::HandleId handle_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- scoped_refptr<RefCountedRegistration>* ref_registration =
- registration_handle_ids_.Lookup(handle_id);
- if (!ref_registration)
- return scoped_ptr<BackgroundSyncRegistrationHandle>();
- return CreateRegistrationHandle(ref_registration->get());
+ MakeStatusAndRegistrationsCompletion(callback)));
}
void BackgroundSyncManager::OnRegistrationDeleted(int64_t sw_registration_id,
@@ -316,8 +279,6 @@ BackgroundSyncManager::BackgroundSyncManager(
base::Bind(&BackgroundSyncManager::OnNetworkChanged,
weak_ptr_factory_.GetWeakPtr())));
#endif
- power_observer_.reset(new BackgroundSyncPowerObserver(base::Bind(
- &BackgroundSyncManager::OnPowerChanged, weak_ptr_factory_.GetWeakPtr())));
}
void BackgroundSyncManager::Init() {
@@ -400,20 +361,12 @@ void BackgroundSyncManager::InitDidGetDataFromBackend(
break;
}
- RegistrationKey registration_key(registration_proto.tag(),
- registration_proto.periodicity());
-
- scoped_refptr<RefCountedRegistration> ref_registration(
- new RefCountedRegistration());
- registrations->registration_map[registration_key] = ref_registration;
- BackgroundSyncRegistration* registration = ref_registration->value();
+ BackgroundSyncRegistration* registration =
+ &registrations->registration_map[registration_proto.tag()];
BackgroundSyncRegistrationOptions* options = registration->options();
options->tag = registration_proto.tag();
- options->periodicity = registration_proto.periodicity();
- options->min_period = registration_proto.min_period();
options->network_state = registration_proto.network_state();
- options->power_state = registration_proto.power_state();
registration->set_id(registration_proto.id());
registration->set_num_attempts(registration_proto.num_attempts());
@@ -447,9 +400,8 @@ void BackgroundSyncManager::RegisterCheckIfHasMainFrame(
ServiceWorkerRegistration* sw_registration =
service_worker_context_->GetLiveRegistration(sw_registration_id);
if (!sw_registration || !sw_registration->active_version()) {
- BackgroundSyncMetrics::CountRegisterFailure(
- options.periodicity, BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER);
- PostErrorResponse(BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER, callback);
+ RecordFailureAndPostError(BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER,
+ callback);
return;
}
@@ -468,9 +420,7 @@ void BackgroundSyncManager::RegisterDidCheckIfMainFrame(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!has_main_frame_client) {
- BackgroundSyncMetrics::CountRegisterFailure(
- options.periodicity, BACKGROUND_SYNC_STATUS_NOT_ALLOWED);
- PostErrorResponse(BACKGROUND_SYNC_STATUS_NOT_ALLOWED, callback);
+ RecordFailureAndPostError(BACKGROUND_SYNC_STATUS_NOT_ALLOWED, callback);
return;
}
RegisterImpl(sw_registration_id, options, callback);
@@ -483,25 +433,53 @@ void BackgroundSyncManager::RegisterImpl(
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (disabled_) {
- BackgroundSyncMetrics::CountRegisterFailure(
- options.periodicity, BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
- PostErrorResponse(BACKGROUND_SYNC_STATUS_STORAGE_ERROR, callback);
+ RecordFailureAndPostError(BACKGROUND_SYNC_STATUS_STORAGE_ERROR, callback);
return;
}
if (options.tag.length() > kMaxTagLength) {
- BackgroundSyncMetrics::CountRegisterFailure(
- options.periodicity, BACKGROUND_SYNC_STATUS_NOT_ALLOWED);
- PostErrorResponse(BACKGROUND_SYNC_STATUS_NOT_ALLOWED, callback);
+ RecordFailureAndPostError(BACKGROUND_SYNC_STATUS_NOT_ALLOWED, callback);
return;
}
ServiceWorkerRegistration* sw_registration =
service_worker_context_->GetLiveRegistration(sw_registration_id);
if (!sw_registration || !sw_registration->active_version()) {
- BackgroundSyncMetrics::CountRegisterFailure(
- options.periodicity, BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER);
- PostErrorResponse(BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER, callback);
+ RecordFailureAndPostError(BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER,
+ callback);
+ return;
+ }
+
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&GetBackgroundSyncPermissionOnUIThread,
+ service_worker_context_,
+ sw_registration->pattern().GetOrigin()),
+ base::Bind(&BackgroundSyncManager::RegisterDidAskForPermission,
+ weak_ptr_factory_.GetWeakPtr(), sw_registration_id, options,
+ callback));
+}
+
+void BackgroundSyncManager::RegisterDidAskForPermission(
+ int64_t sw_registration_id,
+ const BackgroundSyncRegistrationOptions& options,
+ const StatusAndRegistrationCallback& callback,
+ blink::mojom::PermissionStatus permission_status) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (permission_status == blink::mojom::PermissionStatus::DENIED) {
+ RecordFailureAndPostError(BACKGROUND_SYNC_STATUS_PERMISSION_DENIED,
+ callback);
+ return;
+ }
+ DCHECK(permission_status == blink::mojom::PermissionStatus::GRANTED);
+
+ ServiceWorkerRegistration* sw_registration =
+ service_worker_context_->GetLiveRegistration(sw_registration_id);
+ if (!sw_registration || !sw_registration->active_version()) {
+ // The service worker was shut down in the interim.
+ RecordFailureAndPostError(BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER,
+ callback);
return;
}
@@ -510,57 +488,49 @@ void BackgroundSyncManager::RegisterImpl(
service_worker_context_,
sw_registration->pattern().GetOrigin()));
- RefCountedRegistration* existing_registration_ref =
- LookupActiveRegistration(sw_registration_id, RegistrationKey(options));
- if (existing_registration_ref) {
- if (existing_registration_ref->value()->options()->Equals(options)) {
- BackgroundSyncRegistration* existing_registration =
- existing_registration_ref->value();
-
- BackgroundSyncMetrics::RegistrationCouldFire registration_could_fire =
- AreOptionConditionsMet(options)
- ? BackgroundSyncMetrics::REGISTRATION_COULD_FIRE
- : BackgroundSyncMetrics::REGISTRATION_COULD_NOT_FIRE;
- BackgroundSyncMetrics::CountRegisterSuccess(
- existing_registration->options()->periodicity,
- registration_could_fire,
- BackgroundSyncMetrics::REGISTRATION_IS_DUPLICATE);
+ BackgroundSyncRegistration* existing_registration =
+ LookupActiveRegistration(sw_registration_id, options.tag);
+ if (existing_registration) {
+ DCHECK(existing_registration->options()->Equals(options));
+
+ BackgroundSyncMetrics::RegistrationCouldFire registration_could_fire =
+ AreOptionConditionsMet(options)
+ ? BackgroundSyncMetrics::REGISTRATION_COULD_FIRE
+ : BackgroundSyncMetrics::REGISTRATION_COULD_NOT_FIRE;
+ BackgroundSyncMetrics::CountRegisterSuccess(
+ registration_could_fire,
+ BackgroundSyncMetrics::REGISTRATION_IS_DUPLICATE);
if (existing_registration->IsFiring()) {
existing_registration->set_sync_state(
- BACKGROUND_SYNC_STATE_REREGISTERED_WHILE_FIRING);
+ mojom::BackgroundSyncState::REREGISTERED_WHILE_FIRING);
}
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(
- callback, BACKGROUND_SYNC_STATUS_OK,
- base::Passed(CreateRegistrationHandle(existing_registration_ref))));
+ base::Bind(callback, BACKGROUND_SYNC_STATUS_OK,
+ base::Passed(make_scoped_ptr(new BackgroundSyncRegistration(
+ *existing_registration)))));
return;
- } else {
- existing_registration_ref->value()->SetUnregisteredState();
- }
}
- scoped_refptr<RefCountedRegistration> new_ref_registration(
- new RefCountedRegistration());
- BackgroundSyncRegistration* new_registration = new_ref_registration->value();
+ BackgroundSyncRegistration new_registration;
- *new_registration->options() = options;
+ *new_registration.options() = options;
BackgroundSyncRegistrations* registrations =
&active_registrations_[sw_registration_id];
- new_registration->set_id(registrations->next_id++);
+ new_registration.set_id(registrations->next_id++);
AddActiveRegistration(sw_registration_id,
sw_registration->pattern().GetOrigin(),
- new_ref_registration);
+ new_registration);
StoreRegistrations(
sw_registration_id,
base::Bind(&BackgroundSyncManager::RegisterDidStore,
weak_ptr_factory_.GetWeakPtr(), sw_registration_id,
- new_ref_registration, callback));
+ new_registration, callback));
}
void BackgroundSyncManager::DisableAndClearManager(
@@ -575,15 +545,6 @@ void BackgroundSyncManager::DisableAndClearManager(
disabled_ = true;
- for (auto& sw_id_and_registrations : active_registrations_) {
- for (auto& key_and_registration :
- sw_id_and_registrations.second.registration_map) {
- BackgroundSyncRegistration* registration =
- key_and_registration.second->value();
- registration->SetUnregisteredState();
- }
- }
-
active_registrations_.clear();
// Delete all backend entries. The memory representation of registered syncs
@@ -628,10 +589,9 @@ void BackgroundSyncManager::DisableAndClearManagerClearedOne(
base::Bind(barrier_closure));
}
-BackgroundSyncManager::RefCountedRegistration*
-BackgroundSyncManager::LookupActiveRegistration(
+BackgroundSyncRegistration* BackgroundSyncManager::LookupActiveRegistration(
int64_t sw_registration_id,
- const RegistrationKey& registration_key) {
+ const std::string& tag) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
SWIdToRegistrationsMap::iterator it =
@@ -643,12 +603,11 @@ BackgroundSyncManager::LookupActiveRegistration(
DCHECK_LE(BackgroundSyncRegistration::kInitialId, registrations.next_id);
DCHECK(!registrations.origin.is_empty());
- auto key_and_registration_iter =
- registrations.registration_map.find(registration_key);
+ auto key_and_registration_iter = registrations.registration_map.find(tag);
if (key_and_registration_iter == registrations.registration_map.end())
return nullptr;
- return key_and_registration_iter->second.get();
+ return &key_and_registration_iter->second;
}
void BackgroundSyncManager::StoreRegistrations(
@@ -665,16 +624,13 @@ void BackgroundSyncManager::StoreRegistrations(
for (const auto& key_and_registration : registrations.registration_map) {
const BackgroundSyncRegistration& registration =
- *key_and_registration.second->value();
+ key_and_registration.second;
BackgroundSyncRegistrationProto* registration_proto =
registrations_proto.add_registration();
registration_proto->set_id(registration.id());
registration_proto->set_tag(registration.options()->tag);
- registration_proto->set_periodicity(registration.options()->periodicity);
- registration_proto->set_min_period(registration.options()->min_period);
registration_proto->set_network_state(
registration.options()->network_state);
- registration_proto->set_power_state(registration.options()->power_state);
registration_proto->set_num_attempts(registration.num_attempts());
registration_proto->set_delay_until(
registration.delay_until().ToInternalValue());
@@ -689,21 +645,15 @@ void BackgroundSyncManager::StoreRegistrations(
void BackgroundSyncManager::RegisterDidStore(
int64_t sw_registration_id,
- const scoped_refptr<RefCountedRegistration>& new_registration_ref,
+ const BackgroundSyncRegistration& new_registration,
const StatusAndRegistrationCallback& callback,
ServiceWorkerStatusCode status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- const BackgroundSyncRegistration* new_registration =
- new_registration_ref->value();
-
if (status == SERVICE_WORKER_ERROR_NOT_FOUND) {
// The service worker registration is gone.
- BackgroundSyncMetrics::CountRegisterFailure(
- new_registration->options()->periodicity,
- BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
active_registrations_.erase(sw_registration_id);
- PostErrorResponse(BACKGROUND_SYNC_STATUS_STORAGE_ERROR, callback);
+ RecordFailureAndPostError(BACKGROUND_SYNC_STATUS_STORAGE_ERROR, callback);
return;
}
@@ -711,55 +661,54 @@ void BackgroundSyncManager::RegisterDidStore(
LOG(ERROR) << "BackgroundSync failed to store registration due to backend "
"failure.";
BackgroundSyncMetrics::CountRegisterFailure(
- new_registration->options()->periodicity,
BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
- DisableAndClearManager(base::Bind(
- callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
- base::Passed(scoped_ptr<BackgroundSyncRegistrationHandle>())));
+ DisableAndClearManager(
+ base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
+ base::Passed(scoped_ptr<BackgroundSyncRegistration>())));
return;
}
BackgroundSyncMetrics::RegistrationCouldFire registration_could_fire =
- AreOptionConditionsMet(*new_registration->options())
+ AreOptionConditionsMet(*new_registration.options())
? BackgroundSyncMetrics::REGISTRATION_COULD_FIRE
: BackgroundSyncMetrics::REGISTRATION_COULD_NOT_FIRE;
BackgroundSyncMetrics::CountRegisterSuccess(
- new_registration->options()->periodicity, registration_could_fire,
+ registration_could_fire,
BackgroundSyncMetrics::REGISTRATION_IS_NOT_DUPLICATE);
FireReadyEvents();
+
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(
- callback, BACKGROUND_SYNC_STATUS_OK,
- base::Passed(CreateRegistrationHandle(new_registration_ref.get()))));
+ base::Bind(callback, BACKGROUND_SYNC_STATUS_OK,
+ base::Passed(make_scoped_ptr(
+ new BackgroundSyncRegistration(new_registration)))));
}
-void BackgroundSyncManager::RemoveActiveRegistration(
- int64_t sw_registration_id,
- const RegistrationKey& registration_key) {
+void BackgroundSyncManager::RemoveActiveRegistration(int64_t sw_registration_id,
+ const std::string& tag) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(LookupActiveRegistration(sw_registration_id, registration_key));
+ DCHECK(LookupActiveRegistration(sw_registration_id, tag));
BackgroundSyncRegistrations* registrations =
&active_registrations_[sw_registration_id];
- registrations->registration_map.erase(registration_key);
+ registrations->registration_map.erase(tag);
}
void BackgroundSyncManager::AddActiveRegistration(
int64_t sw_registration_id,
const GURL& origin,
- const scoped_refptr<RefCountedRegistration>& sync_registration) {
+ const BackgroundSyncRegistration& sync_registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(sync_registration->value()->IsValid());
+ DCHECK(sync_registration.IsValid());
BackgroundSyncRegistrations* registrations =
&active_registrations_[sw_registration_id];
registrations->origin = origin;
- RegistrationKey registration_key(*sync_registration->value());
- registrations->registration_map[registration_key] = sync_registration;
+ registrations->registration_map[sync_registration.options()->tag] =
+ sync_registration;
}
void BackgroundSyncManager::StoreDataInBackend(
@@ -784,19 +733,21 @@ void BackgroundSyncManager::GetDataFromBackend(
callback);
}
-void BackgroundSyncManager::FireOneShotSync(
- BackgroundSyncRegistrationHandle::HandleId handle_id,
+void BackgroundSyncManager::DispatchSyncEvent(
+ const std::string& tag,
const scoped_refptr<ServiceWorkerVersion>& active_version,
- BackgroundSyncEventLastChance last_chance,
+ mojom::BackgroundSyncEventLastChance last_chance,
const ServiceWorkerVersion::StatusCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(active_version);
if (active_version->running_status() != ServiceWorkerVersion::RUNNING) {
active_version->RunAfterStartWorker(
- callback, base::Bind(&BackgroundSyncManager::FireOneShotSync,
- weak_ptr_factory_.GetWeakPtr(), handle_id,
- active_version, last_chance, callback));
+ ServiceWorkerMetrics::EventType::SYNC,
+ base::Bind(&BackgroundSyncManager::DispatchSyncEvent,
+ weak_ptr_factory_.GetWeakPtr(), tag, active_version,
+ last_chance, callback),
+ callback);
return;
}
@@ -804,16 +755,13 @@ void BackgroundSyncManager::FireOneShotSync(
ServiceWorkerMetrics::EventType::SYNC, callback,
parameters_->max_sync_event_duration,
ServiceWorkerVersion::CONTINUE_ON_TIMEOUT);
- base::WeakPtr<BackgroundSyncServiceClient> client =
- active_version->GetMojoServiceForRequest<BackgroundSyncServiceClient>(
- request_id);
-
- // The ServiceWorkerVersion doesn't know when the client (javascript) is done
- // with the registration so don't give it a BackgroundSyncRegistrationHandle.
- // Once the render process gets the handle_id it can create its own handle
- // (with a new unique handle id).
+ base::WeakPtr<mojom::BackgroundSyncServiceClient> client =
+ active_version
+ ->GetMojoServiceForRequest<mojom::BackgroundSyncServiceClient>(
+ request_id);
+
client->Sync(
- handle_id, last_chance,
+ tag, last_chance,
base::Bind(&OnSyncEventFinished, active_version, request_id, callback));
}
@@ -829,221 +777,13 @@ void BackgroundSyncManager::HasMainFrameProviderHost(
service_worker_context_->HasMainFrameProviderHost(origin, callback);
}
-scoped_ptr<BackgroundSyncRegistrationHandle>
-BackgroundSyncManager::CreateRegistrationHandle(
- const scoped_refptr<RefCountedRegistration>& registration) {
- scoped_refptr<RefCountedRegistration>* ptr =
- new scoped_refptr<RefCountedRegistration>(registration);
-
- // Registration handles have unique handle ids. The handle id maps to an
- // internal RefCountedRegistration (which has the persistent registration id)
- // via
- // registration_reference_ids_.
- BackgroundSyncRegistrationHandle::HandleId handle_id =
- registration_handle_ids_.Add(ptr);
-
- return make_scoped_ptr(new BackgroundSyncRegistrationHandle(
- weak_ptr_factory_.GetWeakPtr(), handle_id));
-}
-
-BackgroundSyncRegistration* BackgroundSyncManager::GetRegistrationForHandle(
- BackgroundSyncRegistrationHandle::HandleId handle_id) const {
- scoped_refptr<RefCountedRegistration>* ref_registration =
- registration_handle_ids_.Lookup(handle_id);
- if (!ref_registration)
- return nullptr;
- return (*ref_registration)->value();
-}
-
-void BackgroundSyncManager::ReleaseRegistrationHandle(
- BackgroundSyncRegistrationHandle::HandleId handle_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(registration_handle_ids_.Lookup(handle_id));
- registration_handle_ids_.Remove(handle_id);
-}
-
-void BackgroundSyncManager::Unregister(
- int64_t sw_registration_id,
- BackgroundSyncRegistrationHandle::HandleId handle_id,
- const StatusCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- BackgroundSyncRegistration* registration =
- GetRegistrationForHandle(handle_id);
- DCHECK(registration);
-
- if (disabled_) {
- BackgroundSyncMetrics::CountUnregister(
- registration->options()->periodicity,
- BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR));
- return;
- }
-
- op_scheduler_.ScheduleOperation(base::Bind(
- &BackgroundSyncManager::UnregisterImpl, weak_ptr_factory_.GetWeakPtr(),
- sw_registration_id, RegistrationKey(*registration), registration->id(),
- registration->options()->periodicity, MakeStatusCompletion(callback)));
-}
-
-void BackgroundSyncManager::UnregisterImpl(
- int64_t sw_registration_id,
- const RegistrationKey& registration_key,
- BackgroundSyncRegistration::RegistrationId sync_registration_id,
- SyncPeriodicity periodicity,
- const StatusCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (disabled_) {
- BackgroundSyncMetrics::CountUnregister(
- periodicity, BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR));
- return;
- }
-
- RefCountedRegistration* existing_registration =
- LookupActiveRegistration(sw_registration_id, registration_key);
-
- if (!existing_registration ||
- existing_registration->value()->id() != sync_registration_id) {
- BackgroundSyncMetrics::CountUnregister(periodicity,
- BACKGROUND_SYNC_STATUS_NOT_FOUND);
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_NOT_FOUND));
- return;
- }
-
- existing_registration->value()->SetUnregisteredState();
-
- RemoveActiveRegistration(sw_registration_id, registration_key);
-
- StoreRegistrations(sw_registration_id,
- base::Bind(&BackgroundSyncManager::UnregisterDidStore,
- weak_ptr_factory_.GetWeakPtr(),
- sw_registration_id, periodicity, callback));
-}
-
-void BackgroundSyncManager::UnregisterDidStore(int64_t sw_registration_id,
- SyncPeriodicity periodicity,
- const StatusCallback& callback,
- ServiceWorkerStatusCode status) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (status == SERVICE_WORKER_ERROR_NOT_FOUND) {
- // ServiceWorker was unregistered.
- BackgroundSyncMetrics::CountUnregister(
- periodicity, BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
- active_registrations_.erase(sw_registration_id);
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR));
- return;
- }
-
- if (status != SERVICE_WORKER_OK) {
- LOG(ERROR) << "BackgroundSync failed to unregister due to backend failure.";
- BackgroundSyncMetrics::CountUnregister(
- periodicity, BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
- DisableAndClearManager(
- base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR));
- return;
- }
-
- BackgroundSyncMetrics::CountUnregister(periodicity,
- BACKGROUND_SYNC_STATUS_OK);
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_OK));
-}
-
-void BackgroundSyncManager::NotifyWhenFinished(
- BackgroundSyncRegistrationHandle::HandleId handle_id,
- const StatusAndStateCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (disabled_) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
- BACKGROUND_SYNC_STATE_FAILED));
- return;
- }
-
- scoped_ptr<BackgroundSyncRegistrationHandle> registration_handle =
- DuplicateRegistrationHandle(handle_id);
-
- op_scheduler_.ScheduleOperation(
- base::Bind(&BackgroundSyncManager::NotifyWhenFinishedImpl,
- weak_ptr_factory_.GetWeakPtr(),
- base::Passed(std::move(registration_handle)), callback));
-}
-
-void BackgroundSyncManager::NotifyWhenFinishedImpl(
- scoped_ptr<BackgroundSyncRegistrationHandle> registration_handle,
- const StatusAndStateCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK_EQ(SYNC_ONE_SHOT, registration_handle->options()->periodicity);
-
- if (disabled_) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_STORAGE_ERROR,
- BACKGROUND_SYNC_STATE_FAILED));
- return;
- }
-
- if (!registration_handle->registration()->HasCompleted()) {
- registration_handle->registration()->AddFinishedCallback(
- base::Bind(&BackgroundSyncManager::NotifyWhenFinishedInvokeCallback,
- weak_ptr_factory_.GetWeakPtr(), callback));
- op_scheduler_.CompleteOperationAndRunNext();
- return;
- }
-
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(callback, BACKGROUND_SYNC_STATUS_OK,
- registration_handle->sync_state()));
- op_scheduler_.CompleteOperationAndRunNext();
-}
-
-void BackgroundSyncManager::NotifyWhenFinishedInvokeCallback(
- const StatusAndStateCallback& callback,
- BackgroundSyncState sync_state) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- callback.Run(BACKGROUND_SYNC_STATUS_OK, sync_state);
-}
-
-void BackgroundSyncManager::GetRegistrationImpl(
- int64_t sw_registration_id,
- const RegistrationKey& registration_key,
- const StatusAndRegistrationCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (disabled_) {
- PostErrorResponse(BACKGROUND_SYNC_STATUS_STORAGE_ERROR, callback);
- return;
- }
-
- RefCountedRegistration* registration =
- LookupActiveRegistration(sw_registration_id, registration_key);
- if (!registration) {
- PostErrorResponse(BACKGROUND_SYNC_STATUS_NOT_FOUND, callback);
- return;
- }
-
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(callback, BACKGROUND_SYNC_STATUS_OK,
- base::Passed(CreateRegistrationHandle(registration))));
-}
-
void BackgroundSyncManager::GetRegistrationsImpl(
int64_t sw_registration_id,
- SyncPeriodicity periodicity,
const StatusAndRegistrationsCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- scoped_ptr<ScopedVector<BackgroundSyncRegistrationHandle>> out_registrations(
- new ScopedVector<BackgroundSyncRegistrationHandle>());
+ scoped_ptr<ScopedVector<BackgroundSyncRegistration>> out_registrations(
+ new ScopedVector<BackgroundSyncRegistration>());
if (disabled_) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -1058,11 +798,11 @@ void BackgroundSyncManager::GetRegistrationsImpl(
if (it != active_registrations_.end()) {
const BackgroundSyncRegistrations& registrations = it->second;
for (const auto& tag_and_registration : registrations.registration_map) {
- RefCountedRegistration* registration = tag_and_registration.second.get();
- if (registration->value()->options()->periodicity == periodicity) {
- out_registrations->push_back(
- CreateRegistrationHandle(registration).release());
- }
+ const BackgroundSyncRegistration& registration =
+ tag_and_registration.second;
+ BackgroundSyncRegistration* out_registration =
+ new BackgroundSyncRegistration(registration);
+ out_registrations->push_back(out_registration);
}
}
@@ -1074,26 +814,19 @@ void BackgroundSyncManager::GetRegistrationsImpl(
bool BackgroundSyncManager::AreOptionConditionsMet(
const BackgroundSyncRegistrationOptions& options) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- return network_observer_->NetworkSufficient(options.network_state) &&
- power_observer_->PowerSufficient(options.power_state);
+ return network_observer_->NetworkSufficient(options.network_state);
}
bool BackgroundSyncManager::IsRegistrationReadyToFire(
const BackgroundSyncRegistration& registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // TODO(jkarlin): Add support for firing periodic registrations.
- if (registration.options()->periodicity == SYNC_PERIODIC)
- return false;
-
- if (registration.sync_state() != BACKGROUND_SYNC_STATE_PENDING)
+ if (registration.sync_state() != mojom::BackgroundSyncState::PENDING)
return false;
if (clock_->Now() < registration.delay_until())
return false;
- DCHECK_EQ(SYNC_ONE_SHOT, registration.options()->periodicity);
-
return AreOptionConditionsMet(*registration.options());
}
@@ -1105,20 +838,15 @@ void BackgroundSyncManager::RunInBackgroundIfNecessary() {
for (const auto& key_and_registration :
sw_id_and_registrations.second.registration_map) {
const BackgroundSyncRegistration& registration =
- *key_and_registration.second->value();
- if (registration.sync_state() == BACKGROUND_SYNC_STATE_PENDING) {
- if (registration.options()->periodicity == SYNC_ONE_SHOT) {
- if (clock_->Now() >= registration.delay_until()) {
- soonest_wakeup_delta = base::TimeDelta();
- } else {
- base::TimeDelta delay_delta =
- registration.delay_until() - clock_->Now();
- if (delay_delta < soonest_wakeup_delta)
- soonest_wakeup_delta = delay_delta;
- }
+ key_and_registration.second;
+ if (registration.sync_state() == mojom::BackgroundSyncState::PENDING) {
+ if (clock_->Now() >= registration.delay_until()) {
+ soonest_wakeup_delta = base::TimeDelta();
} else {
- // TODO(jkarlin): Support keeping the browser alive for periodic
- // syncs.
+ base::TimeDelta delay_delta =
+ registration.delay_until() - clock_->Now();
+ if (delay_delta < soonest_wakeup_delta)
+ soonest_wakeup_delta = delay_delta;
}
}
}
@@ -1170,26 +898,25 @@ void BackgroundSyncManager::FireReadyEventsImpl(const base::Closure& callback) {
}
// Find the registrations that are ready to run.
- std::vector<std::pair<int64_t, RegistrationKey>> sw_id_and_keys_to_fire;
+ std::vector<std::pair<int64_t, std::string>> sw_id_and_tags_to_fire;
for (auto& sw_id_and_registrations : active_registrations_) {
const int64_t service_worker_id = sw_id_and_registrations.first;
for (auto& key_and_registration :
sw_id_and_registrations.second.registration_map) {
- BackgroundSyncRegistration* registration =
- key_and_registration.second->value();
+ BackgroundSyncRegistration* registration = &key_and_registration.second;
if (IsRegistrationReadyToFire(*registration)) {
- sw_id_and_keys_to_fire.push_back(
+ sw_id_and_tags_to_fire.push_back(
std::make_pair(service_worker_id, key_and_registration.first));
// The state change is not saved to persistent storage because
// if the sync event is killed mid-sync then it should return to
// SYNC_STATE_PENDING.
- registration->set_sync_state(BACKGROUND_SYNC_STATE_FIRING);
+ registration->set_sync_state(mojom::BackgroundSyncState::FIRING);
}
}
}
- if (sw_id_and_keys_to_fire.empty()) {
+ if (sw_id_and_tags_to_fire.empty()) {
RunInBackgroundIfNecessary();
base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
base::Bind(callback));
@@ -1201,33 +928,33 @@ void BackgroundSyncManager::FireReadyEventsImpl(const base::Closure& callback) {
// Fire the sync event of the ready registrations and run |callback| once
// they're all done.
base::Closure events_fired_barrier_closure = base::BarrierClosure(
- sw_id_and_keys_to_fire.size(),
+ sw_id_and_tags_to_fire.size(),
base::Bind(&BackgroundSyncManager::FireReadyEventsAllEventsFiring,
weak_ptr_factory_.GetWeakPtr(), callback));
// Record the total time taken after all events have run to completion.
base::Closure events_completed_barrier_closure =
- base::BarrierClosure(sw_id_and_keys_to_fire.size(),
+ base::BarrierClosure(sw_id_and_tags_to_fire.size(),
base::Bind(&OnAllSyncEventsCompleted, start_time,
- sw_id_and_keys_to_fire.size()));
+ sw_id_and_tags_to_fire.size()));
- for (const auto& sw_id_and_key : sw_id_and_keys_to_fire) {
- int64_t service_worker_id = sw_id_and_key.first;
- const RefCountedRegistration* registration =
- LookupActiveRegistration(service_worker_id, sw_id_and_key.second);
+ for (const auto& sw_id_and_tag : sw_id_and_tags_to_fire) {
+ int64_t service_worker_id = sw_id_and_tag.first;
+ const BackgroundSyncRegistration* registration =
+ LookupActiveRegistration(service_worker_id, sw_id_and_tag.second);
DCHECK(registration);
service_worker_context_->FindReadyRegistrationForId(
service_worker_id, active_registrations_[service_worker_id].origin,
base::Bind(&BackgroundSyncManager::FireReadyEventsDidFindRegistration,
- weak_ptr_factory_.GetWeakPtr(), sw_id_and_key.second,
- registration->value()->id(), events_fired_barrier_closure,
+ weak_ptr_factory_.GetWeakPtr(), sw_id_and_tag.second,
+ registration->id(), events_fired_barrier_closure,
events_completed_barrier_closure));
}
}
void BackgroundSyncManager::FireReadyEventsDidFindRegistration(
- const RegistrationKey& registration_key,
+ const std::string& tag,
BackgroundSyncRegistration::RegistrationId registration_id,
const base::Closure& event_fired_callback,
const base::Closure& event_completed_callback,
@@ -1243,37 +970,27 @@ void BackgroundSyncManager::FireReadyEventsDidFindRegistration(
return;
}
- RefCountedRegistration* registration = LookupActiveRegistration(
- service_worker_registration->id(), registration_key);
+ BackgroundSyncRegistration* registration =
+ LookupActiveRegistration(service_worker_registration->id(), tag);
DCHECK(registration);
- // Create a handle and keep it until the sync event completes. The client can
- // acquire its own handle for longer-term use.
- scoped_ptr<BackgroundSyncRegistrationHandle> registration_handle =
- CreateRegistrationHandle(registration);
-
num_firing_registrations_ += 1;
- BackgroundSyncRegistrationHandle::HandleId handle_id =
- registration_handle->handle_id();
-
- BackgroundSyncEventLastChance last_chance =
- registration->value()->num_attempts() ==
- parameters_->max_sync_attempts - 1
- ? BACKGROUND_SYNC_EVENT_LAST_CHANCE_IS_LAST_CHANCE
- : BACKGROUND_SYNC_EVENT_LAST_CHANCE_IS_NOT_LAST_CHANCE;
+ mojom::BackgroundSyncEventLastChance last_chance =
+ registration->num_attempts() == parameters_->max_sync_attempts - 1
+ ? mojom::BackgroundSyncEventLastChance::IS_LAST_CHANCE
+ : mojom::BackgroundSyncEventLastChance::IS_NOT_LAST_CHANCE;
HasMainFrameProviderHost(
service_worker_registration->pattern().GetOrigin(),
- base::Bind(&BackgroundSyncMetrics::RecordEventStarted,
- registration->value()->options()->periodicity));
+ base::Bind(&BackgroundSyncMetrics::RecordEventStarted));
- FireOneShotSync(
- handle_id, service_worker_registration->active_version(), last_chance,
+ DispatchSyncEvent(
+ registration->options()->tag,
+ service_worker_registration->active_version(), last_chance,
base::Bind(&BackgroundSyncManager::EventComplete,
weak_ptr_factory_.GetWeakPtr(), service_worker_registration,
- service_worker_registration->id(),
- base::Passed(std::move(registration_handle)),
+ service_worker_registration->id(), tag,
event_completed_callback));
base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -1294,34 +1011,48 @@ void BackgroundSyncManager::FireReadyEventsAllEventsFiring(
void BackgroundSyncManager::EventComplete(
const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration,
int64_t service_worker_id,
- scoped_ptr<BackgroundSyncRegistrationHandle> registration_handle,
+ const std::string& tag,
const base::Closure& callback,
ServiceWorkerStatusCode status_code) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // Do not check for disabled as events that were firing when disabled should
- // be allowed to complete (for NotifyWhenFinished).
+ if (disabled_) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ base::Bind(callback));
+ return;
+ }
+
op_scheduler_.ScheduleOperation(base::Bind(
&BackgroundSyncManager::EventCompleteImpl, weak_ptr_factory_.GetWeakPtr(),
- service_worker_id, base::Passed(std::move(registration_handle)),
- status_code, MakeClosureCompletion(callback)));
+ service_worker_id, tag, status_code, MakeClosureCompletion(callback)));
}
void BackgroundSyncManager::EventCompleteImpl(
int64_t service_worker_id,
- scoped_ptr<BackgroundSyncRegistrationHandle> registration_handle,
+ const std::string& tag,
ServiceWorkerStatusCode status_code,
const base::Closure& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (disabled_) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ base::Bind(callback));
+ return;
+ }
+
+ num_firing_registrations_ -= 1;
+
BackgroundSyncRegistration* registration =
- registration_handle->registration();
- DCHECK(registration);
- DCHECK(!registration->HasCompleted());
+ LookupActiveRegistration(service_worker_id, tag);
+ if (!registration) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ base::Bind(callback));
+ return;
+ }
- registration->set_num_attempts(registration->num_attempts() + 1);
+ DCHECK_NE(mojom::BackgroundSyncState::PENDING, registration->sync_state());
- num_firing_registrations_ -= 1;
+ registration->set_num_attempts(registration->num_attempts() + 1);
// The event ran to completion, we should count it, no matter what happens
// from here.
@@ -1331,58 +1062,36 @@ void BackgroundSyncManager::EventCompleteImpl(
HasMainFrameProviderHost(
sw_registration->pattern().GetOrigin(),
base::Bind(&BackgroundSyncMetrics::RecordEventResult,
- registration->options()->periodicity,
status_code == SERVICE_WORKER_OK));
}
- if (registration->options()->periodicity == SYNC_ONE_SHOT) {
- if (registration->sync_state() ==
- BACKGROUND_SYNC_STATE_REREGISTERED_WHILE_FIRING) {
- registration->set_sync_state(BACKGROUND_SYNC_STATE_PENDING);
- registration->set_num_attempts(0);
- } else if (status_code != SERVICE_WORKER_OK) { // Sync failed
- bool can_retry =
- registration->num_attempts() < parameters_->max_sync_attempts;
- if (registration->sync_state() ==
- BACKGROUND_SYNC_STATE_UNREGISTERED_WHILE_FIRING) {
- registration->set_sync_state(can_retry
- ? BACKGROUND_SYNC_STATE_UNREGISTERED
- : BACKGROUND_SYNC_STATE_FAILED);
- registration->RunFinishedCallbacks();
- } else if (can_retry) {
- registration->set_sync_state(BACKGROUND_SYNC_STATE_PENDING);
- registration->set_delay_until(
- clock_->Now() +
- parameters_->initial_retry_delay *
- pow(parameters_->retry_delay_factor,
- registration->num_attempts() - 1));
- } else {
- registration->set_sync_state(BACKGROUND_SYNC_STATE_FAILED);
- registration->RunFinishedCallbacks();
- }
- } else { // Sync succeeded
- registration->set_sync_state(BACKGROUND_SYNC_STATE_SUCCESS);
- registration->RunFinishedCallbacks();
- }
-
- if (registration->HasCompleted()) {
- RegistrationKey key(*registration);
- RefCountedRegistration* active_registration =
- LookupActiveRegistration(service_worker_id, key);
- if (active_registration &&
- active_registration->value()->id() == registration->id()) {
- RemoveActiveRegistration(service_worker_id, key);
- }
- }
- } else { // !SYNC_ONE_SHOT
- // TODO(jkarlin): Add support for running periodic syncs. (crbug.com/479674)
- NOTREACHED();
+ bool registration_completed = true;
+ bool can_retry =
+ registration->num_attempts() < parameters_->max_sync_attempts;
+
+ if (registration->sync_state() ==
+ mojom::BackgroundSyncState::REREGISTERED_WHILE_FIRING) {
+ registration->set_sync_state(mojom::BackgroundSyncState::PENDING);
+ registration->set_num_attempts(0);
+ registration_completed = false;
+ } else if (status_code != SERVICE_WORKER_OK &&
+ can_retry) { // Sync failed but can retry
+ registration->set_sync_state(mojom::BackgroundSyncState::PENDING);
+ registration->set_delay_until(clock_->Now() +
+ parameters_->initial_retry_delay *
+ pow(parameters_->retry_delay_factor,
+ registration->num_attempts() - 1));
+ registration_completed = false;
}
- if (disabled_) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- base::Bind(callback));
- return;
+ if (registration_completed) {
+ const std::string& tag = registration->options()->tag;
+ BackgroundSyncRegistration* active_registration =
+ LookupActiveRegistration(service_worker_id, tag);
+ if (active_registration &&
+ active_registration->id() == registration->id()) {
+ RemoveActiveRegistration(service_worker_id, tag);
+ }
}
StoreRegistrations(
@@ -1454,12 +1163,6 @@ void BackgroundSyncManager::OnNetworkChanged() {
FireReadyEvents();
}
-void BackgroundSyncManager::OnPowerChanged() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- FireReadyEvents();
-}
-
void BackgroundSyncManager::SetMaxSyncAttemptsImpl(
int max_attempts,
const base::Closure& callback) {
@@ -1482,21 +1185,20 @@ void BackgroundSyncManager::CompleteOperationCallback(const CallbackT& callback,
void BackgroundSyncManager::CompleteStatusAndRegistrationCallback(
StatusAndRegistrationCallback callback,
BackgroundSyncStatus status,
- scoped_ptr<BackgroundSyncRegistrationHandle> registration_handle) {
+ scoped_ptr<BackgroundSyncRegistration> registration) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- callback.Run(status, std::move(registration_handle));
+ callback.Run(status, std::move(registration));
op_scheduler_.CompleteOperationAndRunNext();
}
void BackgroundSyncManager::CompleteStatusAndRegistrationsCallback(
StatusAndRegistrationsCallback callback,
BackgroundSyncStatus status,
- scoped_ptr<ScopedVector<BackgroundSyncRegistrationHandle>>
- registration_handles) {
+ scoped_ptr<ScopedVector<BackgroundSyncRegistration>> registrations) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- callback.Run(status, std::move(registration_handles));
+ callback.Run(status, std::move(registrations));
op_scheduler_.CompleteOperationAndRunNext();
}
diff --git a/chromium/content/browser/background_sync/background_sync_manager.h b/chromium/content/browser/background_sync/background_sync_manager.h
index 42a69ea8989..e80ee0a485c 100644
--- a/chromium/content/browser/background_sync/background_sync_manager.h
+++ b/chromium/content/browser/background_sync/background_sync_manager.h
@@ -22,7 +22,6 @@
#include "base/time/clock.h"
#include "content/browser/background_sync/background_sync.pb.h"
#include "content/browser/background_sync/background_sync_registration.h"
-#include "content/browser/background_sync/background_sync_registration_handle.h"
#include "content/browser/background_sync/background_sync_status.h"
#include "content/browser/cache_storage/cache_storage_scheduler.h"
#include "content/browser/service_worker/service_worker_context_observer.h"
@@ -32,12 +31,18 @@
#include "content/common/service_worker/service_worker_status_code.h"
#include "content/public/browser/background_sync_parameters.h"
#include "content/public/browser/browser_thread.h"
+#include "third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h"
#include "url/gurl.h"
+namespace blink {
+namespace mojom {
+enum class PermissionStatus;
+}
+}
+
namespace content {
class BackgroundSyncNetworkObserver;
-class BackgroundSyncPowerObserver;
class ServiceWorkerContextWrapper;
// BackgroundSyncManager manages and stores the set of background sync
@@ -53,53 +58,32 @@ class CONTENT_EXPORT BackgroundSyncManager
using StatusCallback = base::Callback<void(BackgroundSyncStatus)>;
using StatusAndRegistrationCallback =
base::Callback<void(BackgroundSyncStatus,
- scoped_ptr<BackgroundSyncRegistrationHandle>)>;
- using StatusAndStateCallback =
- base::Callback<void(BackgroundSyncStatus, BackgroundSyncState)>;
+ scoped_ptr<BackgroundSyncRegistration>)>;
using StatusAndRegistrationsCallback = base::Callback<void(
BackgroundSyncStatus,
- scoped_ptr<ScopedVector<BackgroundSyncRegistrationHandle>>)>;
+ scoped_ptr<ScopedVector<BackgroundSyncRegistration>>)>;
static scoped_ptr<BackgroundSyncManager> Create(
const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context);
~BackgroundSyncManager() override;
// Stores the given background sync registration and adds it to the scheduling
- // queue. It will overwrite an existing registration with the same tag and
- // periodicity unless they're identical (save for the id). Calls |callback|
- // with BACKGROUND_SYNC_STATUS_OK and the accepted registration on success.
+ // queue. It will overwrite an existing registration with the same tag unless
+ // they're identical (save for the id). Calls |callback| with
+ // BACKGROUND_SYNC_STATUS_OK and the accepted registration on success.
// The accepted registration will have a unique id. It may also have altered
// parameters if the user or UA chose different parameters than those
// supplied.
void Register(int64_t sw_registration_id,
const BackgroundSyncRegistrationOptions& options,
- bool requested_from_service_worker,
const StatusAndRegistrationCallback& callback);
- // Finds the background sync registration associated with
- // |sw_registration_id|, periodicity |periodicity|, and tag
- // |sync_registration_tag|. Calls |callback| with
- // BACKGROUND_SYNC_STATUS_NOT_FOUND if it doesn't exist. Calls |callback| with
- // BACKGROUND_SYNC_STATUS_OK on success. If the callback's status
- // is not BACKGROUND_SYNC_STATUS_OK then the callback's RegistrationHandle
- // will be nullptr.
- void GetRegistration(int64_t sw_registration_id,
- const std::string& sync_registration_tag,
- SyncPeriodicity periodicity,
- const StatusAndRegistrationCallback& callback);
-
// Finds the background sync registrations associated with
- // |sw_registration_id| and periodicity |periodicity|. Calls
- // |callback| with BACKGROUND_SYNC_STATUS_OK on success.
+ // |sw_registration_id|. Calls |callback| with BACKGROUND_SYNC_STATUS_OK on
+ // success.
void GetRegistrations(int64_t sw_registration_id,
- SyncPeriodicity periodicity,
const StatusAndRegistrationsCallback& callback);
- // Given a HandleId |handle_id|, return a new handle for the same
- // registration.
- scoped_ptr<BackgroundSyncRegistrationHandle> DuplicateRegistrationHandle(
- BackgroundSyncRegistrationHandle::HandleId handle_id);
-
// ServiceWorkerContextObserver overrides.
void OnRegistrationDeleted(int64_t sw_registration_id,
const GURL& pattern) override;
@@ -119,14 +103,6 @@ class CONTENT_EXPORT BackgroundSyncManager
}
protected:
- // A registration might be referenced by the client longer than
- // the BackgroundSyncManager needs to keep track of it (e.g., the event has
- // finished firing). The BackgroundSyncManager reference counts its
- // registrations internally and every BackgroundSyncRegistrationHandle has a
- // unique handle id which maps to a locally maintained (in
- // client_registration_ids_) scoped_refptr.
- class RefCountedRegistration;
-
explicit BackgroundSyncManager(
const scoped_refptr<ServiceWorkerContextWrapper>& context);
@@ -144,10 +120,10 @@ class CONTENT_EXPORT BackgroundSyncManager
const std::string& backend_key,
const ServiceWorkerStorage::GetUserDataForAllRegistrationsCallback&
callback);
- virtual void FireOneShotSync(
- BackgroundSyncRegistrationHandle::HandleId handle_id,
+ virtual void DispatchSyncEvent(
+ const std::string& tag,
const scoped_refptr<ServiceWorkerVersion>& active_version,
- BackgroundSyncEventLastChance last_chance,
+ mojom::BackgroundSyncEventLastChance last_chance,
const ServiceWorkerVersion::StatusCallback& callback);
virtual void ScheduleDelayedTask(const base::Closure& callback,
base::TimeDelta delay);
@@ -157,29 +133,12 @@ class CONTENT_EXPORT BackgroundSyncManager
private:
friend class TestBackgroundSyncManager;
friend class BackgroundSyncManagerTest;
- friend class BackgroundSyncRegistrationHandle;
-
- class RegistrationKey {
- public:
- explicit RegistrationKey(const BackgroundSyncRegistration& registration);
- explicit RegistrationKey(const BackgroundSyncRegistrationOptions& options);
- RegistrationKey(const std::string& tag, SyncPeriodicity periodicity);
- RegistrationKey(const RegistrationKey& other) = default;
- RegistrationKey& operator=(const RegistrationKey& other) = default;
-
- bool operator<(const RegistrationKey& rhs) const {
- return value_ < rhs.value_;
- }
-
- private:
- std::string value_;
- };
struct BackgroundSyncRegistrations {
- using RegistrationMap =
- std::map<RegistrationKey, scoped_refptr<RefCountedRegistration>>;
+ using RegistrationMap = std::map<std::string, BackgroundSyncRegistration>;
BackgroundSyncRegistrations();
+ BackgroundSyncRegistrations(const BackgroundSyncRegistrations& other);
~BackgroundSyncRegistrations();
RegistrationMap registration_map;
@@ -192,23 +151,8 @@ class CONTENT_EXPORT BackgroundSyncManager
static const size_t kMaxTagLength = 10240;
- scoped_ptr<BackgroundSyncRegistrationHandle> CreateRegistrationHandle(
- const scoped_refptr<RefCountedRegistration>& registration);
-
- // Returns the BackgroundSyncRegistration corresponding to |handle_id|.
- // Returns nullptr if the registration is not found.
- BackgroundSyncRegistration* GetRegistrationForHandle(
- BackgroundSyncRegistrationHandle::HandleId handle_id) const;
-
- // The BackgroundSyncManager holds references to registrations that have
- // active Handles. The handles must call this on destruction.
- void ReleaseRegistrationHandle(
- BackgroundSyncRegistrationHandle::HandleId handle_id);
-
// Disable the manager. Already queued operations will abort once they start
- // to run (in their impl methods). Future operations will not queue. The one
- // exception is already firing events -- their responses will be processed in
- // order to notify their final state.
+ // to run (in their impl methods). Future operations will not queue.
// The list of active registrations is cleared and the backend is also cleared
// (if it's still functioning). The manager will reenable itself once it
// receives the OnStorageWiped message or on browser restart.
@@ -221,9 +165,9 @@ class CONTENT_EXPORT BackgroundSyncManager
ServiceWorkerStatusCode status);
// Returns the existing registration or nullptr if it cannot be found.
- RefCountedRegistration* LookupActiveRegistration(
+ BackgroundSyncRegistration* LookupActiveRegistration(
int64_t sw_registration_id,
- const RegistrationKey& registration_key);
+ const std::string& tag);
// Write all registrations for a given |sw_registration_id| to persistent
// storage.
@@ -232,12 +176,12 @@ class CONTENT_EXPORT BackgroundSyncManager
// Removes the active registration if it is in the map.
void RemoveActiveRegistration(int64_t sw_registration_id,
- const RegistrationKey& registration_key);
+ const std::string& tag);
void AddActiveRegistration(
int64_t sw_registration_id,
const GURL& origin,
- const scoped_refptr<RefCountedRegistration>& sync_registration);
+ const BackgroundSyncRegistration& sync_registration);
void InitImpl(const base::Closure& callback);
void InitDidGetControllerParameters(
@@ -261,49 +205,18 @@ class CONTENT_EXPORT BackgroundSyncManager
void RegisterImpl(int64_t sw_registration_id,
const BackgroundSyncRegistrationOptions& options,
const StatusAndRegistrationCallback& callback);
- void RegisterDidStore(
+ void RegisterDidAskForPermission(
int64_t sw_registration_id,
- const scoped_refptr<RefCountedRegistration>& new_registration_ref,
+ const BackgroundSyncRegistrationOptions& options,
const StatusAndRegistrationCallback& callback,
- ServiceWorkerStatusCode status);
-
- // Removes the background sync with periodicity |periodicity| and id
- // |sync_registration_id|. Calls |callback| with
- // BACKGROUND_SYNC_STATUS_NOT_FOUND if no match is found. Calls |callback|
- // with BACKGROUND_SYNC_STATUS_OK on success.
- void Unregister(int64_t sw_registration_id,
- BackgroundSyncRegistrationHandle::HandleId handle_id,
- const StatusCallback& callback);
- void UnregisterImpl(
- int64_t sw_registration_id,
- const RegistrationKey& key,
- BackgroundSyncRegistration::RegistrationId sync_registration_id,
- SyncPeriodicity periodicity,
- const StatusCallback& callback);
- void UnregisterDidStore(int64_t sw_registration_id,
- SyncPeriodicity periodicity,
- const StatusCallback& callback,
- ServiceWorkerStatusCode status);
-
- // NotifyWhenFinished and its callbacks. See
- // BackgroundSyncRegistrationHandle::NotifyWhenFinished for detailed
- // documentation.
- void NotifyWhenFinished(BackgroundSyncRegistrationHandle::HandleId handle_id,
- const StatusAndStateCallback& callback);
- void NotifyWhenFinishedImpl(
- scoped_ptr<BackgroundSyncRegistrationHandle> registration_handle,
- const StatusAndStateCallback& callback);
- void NotifyWhenFinishedInvokeCallback(const StatusAndStateCallback& callback,
- BackgroundSyncState status);
-
- // GetRegistration callbacks
- void GetRegistrationImpl(int64_t sw_registration_id,
- const RegistrationKey& registration_key,
- const StatusAndRegistrationCallback& callback);
+ blink::mojom::PermissionStatus permission_status);
+ void RegisterDidStore(int64_t sw_registration_id,
+ const BackgroundSyncRegistration& new_registration,
+ const StatusAndRegistrationCallback& callback,
+ ServiceWorkerStatusCode status);
// GetRegistrations callbacks
void GetRegistrationsImpl(int64_t sw_registration_id,
- SyncPeriodicity periodicity,
const StatusAndRegistrationsCallback& callback);
bool AreOptionConditionsMet(const BackgroundSyncRegistrationOptions& options);
@@ -324,7 +237,7 @@ class CONTENT_EXPORT BackgroundSyncManager
void FireReadyEvents();
void FireReadyEventsImpl(const base::Closure& callback);
void FireReadyEventsDidFindRegistration(
- const RegistrationKey& registration_key,
+ const std::string& tag,
BackgroundSyncRegistration::RegistrationId registration_id,
const base::Closure& event_fired_callback,
const base::Closure& event_completed_callback,
@@ -334,18 +247,16 @@ class CONTENT_EXPORT BackgroundSyncManager
void FireReadyEventsAllEventsFiring(const base::Closure& callback);
// Called when a sync event has completed.
- void EventComplete(
- const scoped_refptr<ServiceWorkerRegistration>&
- service_worker_registration,
- int64_t service_worker_id,
- scoped_ptr<BackgroundSyncRegistrationHandle> registration_handle,
- const base::Closure& callback,
- ServiceWorkerStatusCode status_code);
- void EventCompleteImpl(
- int64_t service_worker_id,
- scoped_ptr<BackgroundSyncRegistrationHandle> registration_handle,
- ServiceWorkerStatusCode status_code,
- const base::Closure& callback);
+ void EventComplete(const scoped_refptr<ServiceWorkerRegistration>&
+ service_worker_registration,
+ int64_t service_worker_id,
+ const std::string& tag,
+ const base::Closure& callback,
+ ServiceWorkerStatusCode status_code);
+ void EventCompleteImpl(int64_t service_worker_id,
+ const std::string& tag,
+ ServiceWorkerStatusCode status_code,
+ const base::Closure& callback);
void EventCompleteDidStore(int64_t service_worker_id,
const base::Closure& callback,
ServiceWorkerStatusCode status_code);
@@ -362,7 +273,6 @@ class CONTENT_EXPORT BackgroundSyncManager
void OnStorageWipedImpl(const base::Closure& callback);
void OnNetworkChanged();
- void OnPowerChanged();
// SetMaxSyncAttempts callback
void SetMaxSyncAttemptsImpl(int max_sync_attempts,
@@ -375,11 +285,11 @@ class CONTENT_EXPORT BackgroundSyncManager
void CompleteStatusAndRegistrationCallback(
StatusAndRegistrationCallback callback,
BackgroundSyncStatus status,
- scoped_ptr<BackgroundSyncRegistrationHandle> result);
+ scoped_ptr<BackgroundSyncRegistration> registration);
void CompleteStatusAndRegistrationsCallback(
StatusAndRegistrationsCallback callback,
BackgroundSyncStatus status,
- scoped_ptr<ScopedVector<BackgroundSyncRegistrationHandle>> results);
+ scoped_ptr<ScopedVector<BackgroundSyncRegistration>> registrations);
base::Closure MakeEmptyCompletion();
base::Closure MakeClosureCompletion(const base::Closure& callback);
StatusAndRegistrationCallback MakeStatusAndRegistrationCompletion(
@@ -404,12 +314,6 @@ class CONTENT_EXPORT BackgroundSyncManager
base::CancelableCallback<void()> delayed_sync_task_;
scoped_ptr<BackgroundSyncNetworkObserver> network_observer_;
- scoped_ptr<BackgroundSyncPowerObserver> power_observer_;
-
- // The registrations that clients have handles to.
- IDMap<scoped_refptr<RefCountedRegistration>,
- IDMapOwnPointer,
- BackgroundSyncRegistrationHandle::HandleId> registration_handle_ids_;
scoped_ptr<base::Clock> clock_;
diff --git a/chromium/content/browser/background_sync/background_sync_manager_unittest.cc b/chromium/content/browser/background_sync/background_sync_manager_unittest.cc
index bf0670df243..dbe81cdfec8 100644
--- a/chromium/content/browser/background_sync/background_sync_manager_unittest.cc
+++ b/chromium/content/browser/background_sync/background_sync_manager_unittest.cc
@@ -11,16 +11,14 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/metrics/field_trial.h"
-#include "base/power_monitor/power_monitor.h"
-#include "base/power_monitor/power_monitor_source.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/test/mock_entropy_provider.h"
#include "base/test/simple_test_clock.h"
#include "base/thread_task_runner_handle.h"
#include "content/browser/background_sync/background_sync_network_observer.h"
-#include "content/browser/background_sync/background_sync_registration_handle.h"
#include "content/browser/background_sync/background_sync_status.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
@@ -28,18 +26,26 @@
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_storage.h"
#include "content/browser/storage_partition_impl.h"
-#include "content/public/browser/background_sync_controller.h"
#include "content/public/browser/background_sync_parameters.h"
+#include "content/public/browser/permission_type.h"
#include "content/public/test/background_sync_test_util.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/test/mock_background_sync_controller.h"
+#include "content/test/mock_permission_manager.h"
+#include "content/test/test_background_sync_manager.h"
#include "net/base/network_change_notifier.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h"
namespace content {
namespace {
+using ::testing::Return;
+using ::testing::_;
+
const char kPattern1[] = "https://example.com/a";
const char kPattern2[] = "https://example.com/b";
const char kScript1[] = "https://example.com/a/script.js";
@@ -69,7 +75,7 @@ void UnregisterServiceWorkerCallback(bool* called,
*called = true;
}
-void OneShotSuccessfulCallback(
+void DispatchSyncSuccessfulCallback(
int* count,
const scoped_refptr<ServiceWorkerVersion>& active_version,
const ServiceWorkerVersion::StatusCallback& callback) {
@@ -77,7 +83,7 @@ void OneShotSuccessfulCallback(
callback.Run(SERVICE_WORKER_OK);
}
-void OneShotFailedCallback(
+void DispatchSyncFailedCallback(
int* count,
const scoped_refptr<ServiceWorkerVersion>& active_version,
const ServiceWorkerVersion::StatusCallback& callback) {
@@ -85,7 +91,7 @@ void OneShotFailedCallback(
callback.Run(SERVICE_WORKER_ERROR_FAILED);
}
-void OneShotDelayedCallback(
+void DispatchSyncDelayedCallback(
int* count,
ServiceWorkerVersion::StatusCallback* out_callback,
const scoped_refptr<ServiceWorkerVersion>& active_version,
@@ -94,222 +100,18 @@ void OneShotDelayedCallback(
*out_callback = callback;
}
-void NotifyWhenFinishedCallback(bool* was_called,
- BackgroundSyncStatus* out_status,
- BackgroundSyncState* out_state,
- BackgroundSyncStatus status,
- BackgroundSyncState state) {
- *was_called = true;
- *out_status = status;
- *out_state = state;
-}
-
-class TestPowerSource : public base::PowerMonitorSource {
- public:
- void GeneratePowerStateEvent(bool on_battery_power) {
- test_on_battery_power_ = on_battery_power;
- ProcessPowerEvent(POWER_STATE_EVENT);
- }
-
- private:
- bool IsOnBatteryPowerImpl() final { return test_on_battery_power_; }
- bool test_on_battery_power_ = false;
-};
-
-class TestBackgroundSyncController : public BackgroundSyncController {
- public:
- TestBackgroundSyncController() = default;
-
- // BackgroundSyncController Overrides
- void NotifyBackgroundSyncRegistered(const GURL& origin) override {
- registration_count_ += 1;
- registration_origin_ = origin;
- }
- void RunInBackground(bool enabled, int64_t min_ms) override {
- run_in_background_count_ += 1;
- run_in_background_enabled_ = enabled;
- run_in_background_min_ms_ = min_ms;
- }
- void GetParameterOverrides(
- BackgroundSyncParameters* parameters) const override {
- *parameters = background_sync_parameters_;
- }
-
- int registration_count() const { return registration_count_; }
- GURL registration_origin() const { return registration_origin_; }
- int run_in_background_count() const { return run_in_background_count_; }
- bool run_in_background_enabled() const { return run_in_background_enabled_; }
- int64_t run_in_background_min_ms() const { return run_in_background_min_ms_; }
- BackgroundSyncParameters* background_sync_parameters() {
- return &background_sync_parameters_;
- }
-
- private:
- int registration_count_ = 0;
- GURL registration_origin_;
-
- int run_in_background_count_ = 0;
- bool run_in_background_enabled_ = true;
- int64_t run_in_background_min_ms_ = 0;
- BackgroundSyncParameters background_sync_parameters_;
-
- DISALLOW_COPY_AND_ASSIGN(TestBackgroundSyncController);
-};
-
} // namespace
-// A BackgroundSyncManager that can simulate delaying and corrupting the backend
-// storage and service worker onsync events.
-class TestBackgroundSyncManager : public BackgroundSyncManager {
- public:
- using OneShotCallback =
- base::Callback<void(const scoped_refptr<ServiceWorkerVersion>&,
- const ServiceWorkerVersion::StatusCallback&)>;
-
- explicit TestBackgroundSyncManager(
- const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context)
- : BackgroundSyncManager(service_worker_context) {
- }
-
- void DoInit() { Init(); }
-
- void StoreDataInBackendContinue(
- int64_t sw_registration_id,
- const GURL& origin,
- const std::string& key,
- const std::string& data,
- const ServiceWorkerStorage::StatusCallback& callback) {
- BackgroundSyncManager::StoreDataInBackend(sw_registration_id, origin, key,
- data, callback);
- }
-
- void GetDataFromBackendContinue(
- const std::string& key,
- const ServiceWorkerStorage::GetUserDataForAllRegistrationsCallback&
- callback) {
- BackgroundSyncManager::GetDataFromBackend(key, callback);
- }
-
- void Continue() {
- ASSERT_FALSE(continuation_.is_null());
- continuation_.Run();
- continuation_.Reset();
- }
-
- void ClearDelayedTask() { delayed_task_.Reset(); }
-
- void set_corrupt_backend(bool corrupt_backend) {
- corrupt_backend_ = corrupt_backend;
- }
- void set_delay_backend(bool delay_backend) { delay_backend_ = delay_backend; }
- void set_one_shot_callback(const OneShotCallback& callback) {
- one_shot_callback_ = callback;
- }
-
- base::Closure delayed_task() const { return delayed_task_; }
- base::TimeDelta delayed_task_delta() const { return delayed_task_delta_; }
-
- BackgroundSyncEventLastChance last_chance() const { return last_chance_; }
-
- void set_has_main_frame_provider_host(bool value) {
- has_main_frame_provider_host_ = value;
- }
-
- const BackgroundSyncParameters* background_sync_parameters() const {
- return parameters_.get();
- }
-
- protected:
- void StoreDataInBackend(
- int64_t sw_registration_id,
- const GURL& origin,
- const std::string& key,
- const std::string& data,
- const ServiceWorkerStorage::StatusCallback& callback) override {
- EXPECT_TRUE(continuation_.is_null());
- if (corrupt_backend_) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(callback, SERVICE_WORKER_ERROR_FAILED));
- return;
- }
- continuation_ =
- base::Bind(&TestBackgroundSyncManager::StoreDataInBackendContinue,
- base::Unretained(this), sw_registration_id, origin, key,
- data, callback);
- if (delay_backend_)
- return;
-
- Continue();
- }
-
- void GetDataFromBackend(
- const std::string& key,
- const ServiceWorkerStorage::GetUserDataForAllRegistrationsCallback&
- callback) override {
- EXPECT_TRUE(continuation_.is_null());
- if (corrupt_backend_) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(callback, std::vector<std::pair<int64_t, std::string>>(),
- SERVICE_WORKER_ERROR_FAILED));
- return;
- }
- continuation_ =
- base::Bind(&TestBackgroundSyncManager::GetDataFromBackendContinue,
- base::Unretained(this), key, callback);
- if (delay_backend_)
- return;
-
- Continue();
- }
-
- void FireOneShotSync(
- BackgroundSyncRegistrationHandle::HandleId handle_id,
- const scoped_refptr<ServiceWorkerVersion>& active_version,
- BackgroundSyncEventLastChance last_chance,
- const ServiceWorkerVersion::StatusCallback& callback) override {
- ASSERT_FALSE(one_shot_callback_.is_null());
- last_chance_ = last_chance;
- one_shot_callback_.Run(active_version, callback);
- }
-
- void ScheduleDelayedTask(const base::Closure& callback,
- base::TimeDelta delay) override {
- delayed_task_ = callback;
- delayed_task_delta_ = delay;
- }
-
- void HasMainFrameProviderHost(const GURL& origin,
- const BoolCallback& callback) override {
- callback.Run(has_main_frame_provider_host_);
- }
-
- private:
- bool corrupt_backend_ = false;
- bool delay_backend_ = false;
- bool has_main_frame_provider_host_ = true;
- BackgroundSyncEventLastChance last_chance_ =
- BACKGROUND_SYNC_EVENT_LAST_CHANCE_IS_NOT_LAST_CHANCE;
- base::Closure continuation_;
- OneShotCallback one_shot_callback_;
- base::Closure delayed_task_;
- base::TimeDelta delayed_task_delta_;
-};
-
class BackgroundSyncManagerTest : public testing::Test {
public:
BackgroundSyncManagerTest()
: browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
network_change_notifier_(net::NetworkChangeNotifier::CreateMock()) {
sync_options_1_.tag = "foo";
- sync_options_1_.periodicity = SYNC_ONE_SHOT;
sync_options_1_.network_state = NETWORK_STATE_ONLINE;
- sync_options_1_.power_state = POWER_STATE_AUTO;
sync_options_2_.tag = "bar";
- sync_options_2_.periodicity = SYNC_ONE_SHOT;
sync_options_2_.network_state = NETWORK_STATE_ONLINE;
- sync_options_2_.power_state = POWER_STATE_AUTO;
}
void SetUp() override {
@@ -321,28 +123,23 @@ class BackgroundSyncManagerTest : public testing::Test {
// extra SW stuff.
helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
+ scoped_ptr<MockPermissionManager> mock_permission_manager(
+ new testing::NiceMock<MockPermissionManager>());
+ ON_CALL(*mock_permission_manager,
+ GetPermissionStatus(PermissionType::BACKGROUND_SYNC, _, _))
+ .WillByDefault(Return(blink::mojom::PermissionStatus::GRANTED));
+ helper_->browser_context()->SetPermissionManager(
+ std::move(mock_permission_manager));
+
// Create a StoragePartition with the correct BrowserContext so that the
// BackgroundSyncManager can find the BrowserContext through it.
storage_partition_impl_.reset(new StoragePartitionImpl(
helper_->browser_context(), base::FilePath(), nullptr, nullptr, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr));
+ nullptr, nullptr, nullptr));
helper_->context_wrapper()->set_storage_partition(
storage_partition_impl_.get());
- power_monitor_source_ = new TestPowerSource();
- // power_monitor_ takes ownership of power_monitor_source.
- power_monitor_.reset(new base::PowerMonitor(
- scoped_ptr<base::PowerMonitorSource>(power_monitor_source_)));
-
- SetOnBatteryPower(false);
-
- scoped_ptr<TestBackgroundSyncController> background_sync_controller(
- new TestBackgroundSyncController());
- test_controller_ = background_sync_controller.get();
- helper_->browser_context()->SetBackgroundSyncController(
- std::move(background_sync_controller));
-
SetMaxSyncAttemptsAndRestartManager(1);
// Wait for storage to finish initializing before registering service
@@ -398,28 +195,22 @@ class BackgroundSyncManagerTest : public testing::Test {
}
}
- void SetOnBatteryPower(bool on_battery_power) {
- power_monitor_source_->GeneratePowerStateEvent(on_battery_power);
- base::RunLoop().RunUntilIdle();
- }
-
void StatusAndRegistrationCallback(
bool* was_called,
BackgroundSyncStatus status,
- scoped_ptr<BackgroundSyncRegistrationHandle> registration_handle) {
+ scoped_ptr<BackgroundSyncRegistration> registration) {
*was_called = true;
callback_status_ = status;
- callback_registration_handle_ = std::move(registration_handle);
+ callback_registration_ = std::move(registration);
}
void StatusAndRegistrationsCallback(
bool* was_called,
BackgroundSyncStatus status,
- scoped_ptr<ScopedVector<BackgroundSyncRegistrationHandle>>
- registration_handles) {
+ scoped_ptr<ScopedVector<BackgroundSyncRegistration>> registrations) {
*was_called = true;
callback_status_ = status;
- callback_registration_handles_ = std::move(registration_handles);
+ callback_registrations_ = std::move(registrations);
}
void StatusCallback(bool* was_called, BackgroundSyncStatus status) {
@@ -429,8 +220,6 @@ class BackgroundSyncManagerTest : public testing::Test {
protected:
void CreateBackgroundSyncManager() {
- ClearRegistrationHandles();
-
test_background_sync_manager_ =
new TestBackgroundSyncManager(helper_->context_wrapper());
background_sync_manager_.reset(test_background_sync_manager_);
@@ -451,12 +240,6 @@ class BackgroundSyncManagerTest : public testing::Test {
base::RunLoop().RunUntilIdle();
}
- // Clear the registrations so that the BackgroundSyncManager can release them.
- void ClearRegistrationHandles() {
- callback_registration_handle_.reset();
- callback_registration_handles_.reset();
- }
-
void SetupBackgroundSyncManager() {
CreateBackgroundSyncManager();
InitBackgroundSyncManager();
@@ -475,7 +258,6 @@ class BackgroundSyncManagerTest : public testing::Test {
}
void DeleteBackgroundSyncManager() {
- ClearRegistrationHandles();
background_sync_manager_.reset();
test_background_sync_manager_ = nullptr;
test_clock_ = nullptr;
@@ -490,7 +272,7 @@ class BackgroundSyncManagerTest : public testing::Test {
const BackgroundSyncRegistrationOptions& options) {
bool was_called = false;
background_sync_manager_->Register(
- sw_registration_id, options, true /* requested_from_service_worker */,
+ sw_registration_id, options,
base::Bind(&BackgroundSyncManagerTest::StatusAndRegistrationCallback,
base::Unretained(this), &was_called));
base::RunLoop().RunUntilIdle();
@@ -498,58 +280,9 @@ class BackgroundSyncManagerTest : public testing::Test {
return callback_status_ == BACKGROUND_SYNC_STATUS_OK;
}
- bool RegisterFromDocumentWithServiceWorkerId(
- int64_t sw_registration_id,
- const BackgroundSyncRegistrationOptions& options) {
- bool was_called = false;
- background_sync_manager_->Register(
- sw_registration_id, options, false /* requested_from_service_worker */,
- base::Bind(&BackgroundSyncManagerTest::StatusAndRegistrationCallback,
- base::Unretained(this), &was_called));
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(was_called);
- return callback_status_ == BACKGROUND_SYNC_STATUS_OK;
- }
-
- bool Unregister(BackgroundSyncRegistrationHandle* registration_handle) {
- return UnregisterWithServiceWorkerId(sw_registration_id_1_,
- registration_handle);
- }
-
- bool UnregisterWithServiceWorkerId(
- int64_t sw_registration_id,
- BackgroundSyncRegistrationHandle* registration_handle) {
- bool was_called = false;
- registration_handle->Unregister(
- sw_registration_id,
- base::Bind(&BackgroundSyncManagerTest::StatusCallback,
- base::Unretained(this), &was_called));
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(was_called);
- return callback_status_ == BACKGROUND_SYNC_STATUS_OK;
- }
-
- bool NotifyWhenFinished(
- BackgroundSyncRegistrationHandle* registration_handle) {
- callback_finished_called_ = false;
- callback_finished_status_ = BACKGROUND_SYNC_STATUS_NOT_FOUND;
- callback_finished_state_ = BACKGROUND_SYNC_STATE_FAILED;
-
- registration_handle->NotifyWhenFinished(
- base::Bind(&NotifyWhenFinishedCallback, &callback_finished_called_,
- &callback_finished_status_, &callback_finished_state_));
- base::RunLoop().RunUntilIdle();
-
- if (callback_finished_called_)
- EXPECT_EQ(BACKGROUND_SYNC_STATUS_OK, callback_finished_status_);
-
- return callback_finished_called_;
- }
-
- BackgroundSyncState FinishedState() {
- EXPECT_TRUE(callback_finished_called_);
- EXPECT_EQ(BACKGROUND_SYNC_STATUS_OK, callback_finished_status_);
- return callback_finished_state_;
+ MockPermissionManager* GetPermissionManager() {
+ return static_cast<MockPermissionManager*>(
+ helper_->browser_context()->GetPermissionManager());
}
bool GetRegistration(
@@ -562,32 +295,36 @@ class BackgroundSyncManagerTest : public testing::Test {
int64_t sw_registration_id,
const BackgroundSyncRegistrationOptions& registration_options) {
bool was_called = false;
- background_sync_manager_->GetRegistration(
- sw_registration_id, registration_options.tag,
- registration_options.periodicity,
- base::Bind(&BackgroundSyncManagerTest::StatusAndRegistrationCallback,
+ background_sync_manager_->GetRegistrations(
+ sw_registration_id,
+ base::Bind(&BackgroundSyncManagerTest::StatusAndRegistrationsCallback,
base::Unretained(this), &was_called));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
if (callback_status_ == BACKGROUND_SYNC_STATUS_OK) {
- EXPECT_STREQ(registration_options.tag.c_str(),
- callback_registration_handle_->options()->tag.c_str());
+ for (auto iter = callback_registrations_->begin();
+ iter < callback_registrations_->end(); ++iter) {
+ if ((*iter)->options()->tag == registration_options.tag) {
+ // Transfer the matching registration out of the vector into
+ // callback_registration_ for testing.
+ callback_registration_.reset(*iter);
+ callback_registrations_->weak_erase(iter);
+ return true;
+ }
+ }
}
-
- return callback_status_ == BACKGROUND_SYNC_STATUS_OK;
+ return false;
}
- bool GetRegistrations(SyncPeriodicity periodicity) {
- return GetRegistrationWithServiceWorkerId(sw_registration_id_1_,
- periodicity);
+ bool GetRegistrations() {
+ return GetRegistrationsWithServiceWorkerId(sw_registration_id_1_);
}
- bool GetRegistrationWithServiceWorkerId(int64_t sw_registration_id,
- SyncPeriodicity periodicity) {
+ bool GetRegistrationsWithServiceWorkerId(int64_t sw_registration_id) {
bool was_called = false;
background_sync_manager_->GetRegistrations(
- sw_registration_id, periodicity,
+ sw_registration_id,
base::Bind(&BackgroundSyncManagerTest::StatusAndRegistrationsCallback,
base::Unretained(this), &was_called));
base::RunLoop().RunUntilIdle();
@@ -596,6 +333,11 @@ class BackgroundSyncManagerTest : public testing::Test {
return callback_status_ == BACKGROUND_SYNC_STATUS_OK;
}
+ MockBackgroundSyncController* GetController() {
+ return static_cast<MockBackgroundSyncController*>(
+ helper_->browser_context()->GetBackgroundSyncController());
+ }
+
void StorageRegistrationCallback(ServiceWorkerStatusCode result) {
callback_sw_status_code_ = result;
}
@@ -616,23 +358,24 @@ class BackgroundSyncManagerTest : public testing::Test {
}
void SetupForSyncEvent(
- const TestBackgroundSyncManager::OneShotCallback& callback) {
- test_background_sync_manager_->set_one_shot_callback(callback);
+ const TestBackgroundSyncManager::DispatchSyncCallback& callback) {
+ test_background_sync_manager_->set_dispatch_sync_callback(callback);
SetNetwork(net::NetworkChangeNotifier::CONNECTION_WIFI);
}
void InitSyncEventTest() {
SetupForSyncEvent(
- base::Bind(OneShotSuccessfulCallback, &sync_events_called_));
+ base::Bind(DispatchSyncSuccessfulCallback, &sync_events_called_));
}
void InitFailedSyncEventTest() {
- SetupForSyncEvent(base::Bind(OneShotFailedCallback, &sync_events_called_));
+ SetupForSyncEvent(
+ base::Bind(DispatchSyncFailedCallback, &sync_events_called_));
}
void InitDelayedSyncEventTest() {
- SetupForSyncEvent(base::Bind(OneShotDelayedCallback, &sync_events_called_,
- &sync_fired_callback_));
+ SetupForSyncEvent(base::Bind(DispatchSyncDelayedCallback,
+ &sync_events_called_, &sync_fired_callback_));
}
void RegisterAndVerifySyncEventDelayed(
@@ -656,7 +399,7 @@ class BackgroundSyncManagerTest : public testing::Test {
void SetMaxSyncAttemptsAndRestartManager(int max_sync_attempts) {
BackgroundSyncParameters* parameters =
- test_controller_->background_sync_parameters();
+ GetController()->background_sync_parameters();
parameters->max_sync_attempts = max_sync_attempts;
// Restart the BackgroundSyncManager so that it updates its parameters.
@@ -665,13 +408,10 @@ class BackgroundSyncManagerTest : public testing::Test {
TestBrowserThreadBundle browser_thread_bundle_;
scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_;
- TestPowerSource* power_monitor_source_ = nullptr; // owned by power_monitor_
- scoped_ptr<base::PowerMonitor> power_monitor_;
scoped_ptr<EmbeddedWorkerTestHelper> helper_;
scoped_ptr<BackgroundSyncManager> background_sync_manager_;
scoped_ptr<StoragePartitionImpl> storage_partition_impl_;
TestBackgroundSyncManager* test_background_sync_manager_ = nullptr;
- TestBackgroundSyncController* test_controller_;
base::SimpleTestClock* test_clock_ = nullptr;
int64_t sw_registration_id_1_;
@@ -684,14 +424,9 @@ class BackgroundSyncManagerTest : public testing::Test {
// Callback values.
BackgroundSyncStatus callback_status_ = BACKGROUND_SYNC_STATUS_OK;
- scoped_ptr<BackgroundSyncRegistrationHandle> callback_registration_handle_;
- scoped_ptr<ScopedVector<BackgroundSyncRegistrationHandle>>
- callback_registration_handles_;
+ scoped_ptr<BackgroundSyncRegistration> callback_registration_;
+ scoped_ptr<ScopedVector<BackgroundSyncRegistration>> callback_registrations_;
ServiceWorkerStatusCode callback_sw_status_code_ = SERVICE_WORKER_OK;
- bool callback_finished_called_ = false;
- BackgroundSyncStatus callback_finished_status_ =
- BACKGROUND_SYNC_STATUS_NOT_FOUND;
- BackgroundSyncState callback_finished_state_ = BACKGROUND_SYNC_STATE_FAILED;
int sync_events_called_ = 0;
ServiceWorkerVersion::StatusCallback sync_fired_callback_;
};
@@ -700,11 +435,11 @@ TEST_F(BackgroundSyncManagerTest, Register) {
EXPECT_TRUE(Register(sync_options_1_));
}
-TEST_F(BackgroundSyncManagerTest, RegistractionIntact) {
+TEST_F(BackgroundSyncManagerTest, RegistrationIntact) {
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_STREQ(sync_options_1_.tag.c_str(),
- callback_registration_handle_->options()->tag.c_str());
- EXPECT_TRUE(callback_registration_handle_->IsValid());
+ callback_registration_->options()->tag.c_str());
+ EXPECT_TRUE(callback_registration_->IsValid());
}
TEST_F(BackgroundSyncManagerTest, RegisterWithoutLiveSWRegistration) {
@@ -719,36 +454,6 @@ TEST_F(BackgroundSyncManagerTest, RegisterWithoutActiveSWRegistration) {
EXPECT_EQ(BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER, callback_status_);
}
-TEST_F(BackgroundSyncManagerTest, RegisterOverwrites) {
- EXPECT_TRUE(Register(sync_options_1_));
- scoped_ptr<BackgroundSyncRegistrationHandle> first_registration_handle =
- std::move(callback_registration_handle_);
-
- sync_options_1_.min_period = 100;
- EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_LT(first_registration_handle->handle_id(),
- callback_registration_handle_->handle_id());
- EXPECT_FALSE(first_registration_handle->options()->Equals(
- *callback_registration_handle_->options()));
-}
-
-TEST_F(BackgroundSyncManagerTest, RegisterOverlappingPeriodicAndOneShotTags) {
- // Registrations with the same tags but different periodicities should not
- // collide.
- sync_options_1_.tag = "";
- sync_options_2_.tag = "";
- sync_options_1_.periodicity = SYNC_PERIODIC;
- sync_options_2_.periodicity = SYNC_ONE_SHOT;
- EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_TRUE(Register(sync_options_2_));
- EXPECT_TRUE(GetRegistration(sync_options_1_));
- EXPECT_EQ(SYNC_PERIODIC,
- callback_registration_handle_->options()->periodicity);
- EXPECT_TRUE(GetRegistration(sync_options_2_));
- EXPECT_EQ(SYNC_ONE_SHOT,
- callback_registration_handle_->options()->periodicity);
-}
-
TEST_F(BackgroundSyncManagerTest, RegisterBadBackend) {
test_background_sync_manager_->set_corrupt_backend(true);
EXPECT_FALSE(Register(sync_options_1_));
@@ -757,18 +462,26 @@ TEST_F(BackgroundSyncManagerTest, RegisterBadBackend) {
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
-TEST_F(BackgroundSyncManagerTest, DuplicateRegistrationHandle) {
- EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_TRUE(
- sync_options_1_.Equals(*callback_registration_handle_->options()));
+TEST_F(BackgroundSyncManagerTest, RegisterPermissionDenied) {
+ GURL expected_origin = GURL(kPattern1).GetOrigin();
+ MockPermissionManager* mock_permission_manager = GetPermissionManager();
- scoped_ptr<BackgroundSyncRegistrationHandle> dup_handle =
- background_sync_manager_->DuplicateRegistrationHandle(
- callback_registration_handle_->handle_id());
+ EXPECT_CALL(*mock_permission_manager,
+ GetPermissionStatus(PermissionType::BACKGROUND_SYNC,
+ expected_origin, expected_origin))
+ .WillOnce(testing::Return(blink::mojom::PermissionStatus::DENIED));
+ EXPECT_FALSE(Register(sync_options_1_));
+}
+
+TEST_F(BackgroundSyncManagerTest, RegisterPermissionGranted) {
+ GURL expected_origin = GURL(kPattern1).GetOrigin();
+ MockPermissionManager* mock_permission_manager = GetPermissionManager();
- EXPECT_TRUE(sync_options_1_.Equals(*dup_handle->options()));
- EXPECT_NE(callback_registration_handle_->handle_id(),
- dup_handle->handle_id());
+ EXPECT_CALL(*mock_permission_manager,
+ GetPermissionStatus(PermissionType::BACKGROUND_SYNC,
+ expected_origin, expected_origin))
+ .WillOnce(testing::Return(blink::mojom::PermissionStatus::GRANTED));
+ EXPECT_TRUE(Register(sync_options_1_));
}
TEST_F(BackgroundSyncManagerTest, TwoRegistrations) {
@@ -799,115 +512,70 @@ TEST_F(BackgroundSyncManagerTest, GetRegistrationBadBackend) {
}
TEST_F(BackgroundSyncManagerTest, GetRegistrationsZero) {
- EXPECT_TRUE(GetRegistrations(SYNC_ONE_SHOT));
- EXPECT_EQ(0u, callback_registration_handles_->size());
+ EXPECT_TRUE(GetRegistrations());
+ EXPECT_EQ(0u, callback_registrations_->size());
}
TEST_F(BackgroundSyncManagerTest, GetRegistrationsOne) {
EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_TRUE(GetRegistrations(sync_options_1_.periodicity));
+ EXPECT_TRUE(GetRegistrations());
- EXPECT_EQ(1u, callback_registration_handles_->size());
- sync_options_1_.Equals(*(*callback_registration_handles_)[0]->options());
+ EXPECT_EQ(1u, callback_registrations_->size());
+ sync_options_1_.Equals(*(*callback_registrations_)[0]->options());
}
TEST_F(BackgroundSyncManagerTest, GetRegistrationsTwo) {
- EXPECT_EQ(sync_options_1_.periodicity, sync_options_2_.periodicity);
-
- EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_TRUE(Register(sync_options_2_));
- EXPECT_TRUE(GetRegistrations(sync_options_1_.periodicity));
-
- EXPECT_EQ(2u, callback_registration_handles_->size());
- sync_options_1_.Equals(*(*callback_registration_handles_)[0]->options());
- sync_options_2_.Equals(*(*callback_registration_handles_)[1]->options());
-}
-
-TEST_F(BackgroundSyncManagerTest, GetRegistrationsPeriodicity) {
- sync_options_1_.periodicity = SYNC_ONE_SHOT;
- sync_options_2_.periodicity = SYNC_PERIODIC;
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(Register(sync_options_2_));
+ EXPECT_TRUE(GetRegistrations());
- EXPECT_TRUE(GetRegistrations(SYNC_ONE_SHOT));
- EXPECT_EQ(1u, callback_registration_handles_->size());
- sync_options_1_.Equals(*(*callback_registration_handles_)[0]->options());
-
- EXPECT_TRUE(GetRegistrations(SYNC_PERIODIC));
- EXPECT_EQ(1u, callback_registration_handles_->size());
- sync_options_2_.Equals(*(*callback_registration_handles_)[0]->options());
+ EXPECT_EQ(2u, callback_registrations_->size());
+ sync_options_1_.Equals(*(*callback_registrations_)[0]->options());
+ sync_options_2_.Equals(*(*callback_registrations_)[1]->options());
}
TEST_F(BackgroundSyncManagerTest, GetRegistrationsBadBackend) {
EXPECT_TRUE(Register(sync_options_1_));
test_background_sync_manager_->set_corrupt_backend(true);
- EXPECT_TRUE(GetRegistrations(sync_options_1_.periodicity));
+ EXPECT_TRUE(GetRegistrations());
EXPECT_FALSE(Register(sync_options_2_));
// Registration should have discovered the bad backend and disabled the
// BackgroundSyncManager.
- EXPECT_FALSE(GetRegistrations(sync_options_1_.periodicity));
+ EXPECT_FALSE(GetRegistrations());
test_background_sync_manager_->set_corrupt_backend(false);
- EXPECT_FALSE(GetRegistrations(sync_options_1_.periodicity));
+ EXPECT_FALSE(GetRegistrations());
}
-TEST_F(BackgroundSyncManagerTest, Unregister) {
- EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_TRUE(Unregister(callback_registration_handle_.get()));
- EXPECT_FALSE(GetRegistration(sync_options_1_));
-}
TEST_F(BackgroundSyncManagerTest, Reregister) {
EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_TRUE(Unregister(callback_registration_handle_.get()));
- EXPECT_TRUE(Register(sync_options_1_));
-}
-
-TEST_F(BackgroundSyncManagerTest, UnregisterSecond) {
EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_TRUE(Register(sync_options_2_));
- EXPECT_TRUE(Unregister(callback_registration_handle_.get()));
EXPECT_TRUE(GetRegistration(sync_options_1_));
- EXPECT_TRUE(Register(sync_options_2_));
}
-TEST_F(BackgroundSyncManagerTest, UnregisterBadBackend) {
- sync_options_1_.min_period += 1;
+TEST_F(BackgroundSyncManagerTest, ReregisterSecond) {
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(Register(sync_options_2_));
- test_background_sync_manager_->set_corrupt_backend(true);
- EXPECT_FALSE(Unregister(callback_registration_handle_.get()));
- // Unregister should have discovered the bad backend and disabled the
- // BackgroundSyncManager.
- test_background_sync_manager_->set_corrupt_backend(false);
- EXPECT_FALSE(GetRegistration(sync_options_1_));
- EXPECT_FALSE(GetRegistration(sync_options_2_));
+ EXPECT_TRUE(Register(sync_options_2_));
}
TEST_F(BackgroundSyncManagerTest, RegisterMaxTagLength) {
sync_options_1_.tag = std::string(MaxTagLength(), 'a');
EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_TRUE(Unregister(callback_registration_handle_.get()));
- sync_options_1_.tag = std::string(MaxTagLength() + 1, 'a');
- EXPECT_FALSE(Register(sync_options_1_));
+ sync_options_2_.tag = std::string(MaxTagLength() + 1, 'b');
+ EXPECT_FALSE(Register(sync_options_2_));
EXPECT_EQ(BACKGROUND_SYNC_STATUS_NOT_ALLOWED, callback_status_);
}
TEST_F(BackgroundSyncManagerTest, RegistrationIncreasesId) {
EXPECT_TRUE(Register(sync_options_1_));
- scoped_ptr<BackgroundSyncRegistrationHandle> registered_handle =
- std::move(callback_registration_handle_);
BackgroundSyncRegistration::RegistrationId cur_id =
- registered_handle->handle_id();
+ callback_registration_->id();
EXPECT_TRUE(GetRegistration(sync_options_1_));
EXPECT_TRUE(Register(sync_options_2_));
- EXPECT_LT(cur_id, callback_registration_handle_->handle_id());
- cur_id = callback_registration_handle_->handle_id();
-
- EXPECT_TRUE(Unregister(registered_handle.get()));
- EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_LT(cur_id, callback_registration_handle_->handle_id());
+ EXPECT_LT(cur_id, callback_registration_->id());
}
TEST_F(BackgroundSyncManagerTest, RebootRecovery) {
@@ -960,34 +628,33 @@ TEST_F(BackgroundSyncManagerTest, SequentialOperations) {
SetupDelayedBackgroundSyncManager();
bool register_called = false;
- bool get_registration_called = false;
+ bool get_registrations_called = false;
test_background_sync_manager_->Register(
sw_registration_id_1_, sync_options_1_,
- true /* requested_from_service_worker */,
base::Bind(&BackgroundSyncManagerTest::StatusAndRegistrationCallback,
base::Unretained(this), &register_called));
- test_background_sync_manager_->GetRegistration(
- sw_registration_id_1_, sync_options_1_.tag, sync_options_1_.periodicity,
- base::Bind(&BackgroundSyncManagerTest::StatusAndRegistrationCallback,
- base::Unretained(this), &get_registration_called));
+ test_background_sync_manager_->GetRegistrations(
+ sw_registration_id_1_,
+ base::Bind(&BackgroundSyncManagerTest::StatusAndRegistrationsCallback,
+ base::Unretained(this), &get_registrations_called));
base::RunLoop().RunUntilIdle();
// Init should be blocked while loading from the backend.
EXPECT_FALSE(register_called);
- EXPECT_FALSE(get_registration_called);
+ EXPECT_FALSE(get_registrations_called);
- test_background_sync_manager_->Continue();
+ test_background_sync_manager_->ResumeBackendOperation();
base::RunLoop().RunUntilIdle();
// Register should be blocked while storing to the backend.
EXPECT_FALSE(register_called);
- EXPECT_FALSE(get_registration_called);
+ EXPECT_FALSE(get_registrations_called);
- test_background_sync_manager_->Continue();
+ test_background_sync_manager_->ResumeBackendOperation();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(register_called);
EXPECT_EQ(BACKGROUND_SYNC_STATUS_OK, callback_status_);
- // GetRegistration should run immediately as it doesn't write to disk.
- EXPECT_TRUE(get_registration_called);
+ // GetRegistrations should run immediately as it doesn't write to disk.
+ EXPECT_TRUE(get_registrations_called);
}
TEST_F(BackgroundSyncManagerTest, UnregisterServiceWorker) {
@@ -1004,7 +671,6 @@ TEST_F(BackgroundSyncManagerTest,
bool callback_called = false;
test_background_sync_manager_->Register(
sw_registration_id_1_, sync_options_2_,
- true /* requested_from_service_worker */,
base::Bind(&BackgroundSyncManagerTest::StatusAndRegistrationCallback,
base::Unretained(this), &callback_called));
@@ -1012,7 +678,7 @@ TEST_F(BackgroundSyncManagerTest,
EXPECT_FALSE(callback_called);
UnregisterServiceWorker(sw_registration_id_1_);
- test_background_sync_manager_->Continue();
+ test_background_sync_manager_->ResumeBackendOperation();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(callback_called);
EXPECT_EQ(BACKGROUND_SYNC_STATUS_STORAGE_ERROR, callback_status_);
@@ -1078,23 +744,6 @@ TEST_F(BackgroundSyncManagerTest, RegistrationEqualsTag) {
EXPECT_FALSE(reg_1.Equals(reg_2));
}
-TEST_F(BackgroundSyncManagerTest, RegistrationEqualsPeriodicity) {
- BackgroundSyncRegistration reg_1;
- BackgroundSyncRegistration reg_2;
- EXPECT_TRUE(reg_1.Equals(reg_2));
- reg_1.options()->periodicity = SYNC_PERIODIC;
- reg_2.options()->periodicity = SYNC_ONE_SHOT;
- EXPECT_FALSE(reg_1.Equals(reg_2));
-}
-
-TEST_F(BackgroundSyncManagerTest, RegistrationEqualsMinPeriod) {
- BackgroundSyncRegistration reg_1;
- BackgroundSyncRegistration reg_2;
- EXPECT_TRUE(reg_1.Equals(reg_2));
- reg_2.options()->min_period = reg_1.options()->min_period + 1;
- EXPECT_FALSE(reg_1.Equals(reg_2));
-}
-
TEST_F(BackgroundSyncManagerTest, RegistrationEqualsNetworkState) {
BackgroundSyncRegistration reg_1;
BackgroundSyncRegistration reg_2;
@@ -1104,26 +753,14 @@ TEST_F(BackgroundSyncManagerTest, RegistrationEqualsNetworkState) {
EXPECT_FALSE(reg_1.Equals(reg_2));
}
-TEST_F(BackgroundSyncManagerTest, RegistrationEqualsPowerState) {
- BackgroundSyncRegistration reg_1;
- BackgroundSyncRegistration reg_2;
- EXPECT_TRUE(reg_1.Equals(reg_2));
- reg_1.options()->power_state = POWER_STATE_AUTO;
- reg_2.options()->power_state = POWER_STATE_AVOID_DRAINING;
- EXPECT_FALSE(reg_1.Equals(reg_2));
-}
-
TEST_F(BackgroundSyncManagerTest, StoreAndRetrievePreservesValues) {
+ InitDelayedSyncEventTest();
BackgroundSyncRegistrationOptions options;
+
// Set non-default values for each field.
options.tag = "foo";
- EXPECT_NE(SYNC_PERIODIC, options.periodicity);
- options.periodicity = SYNC_PERIODIC;
- options.min_period += 1;
- EXPECT_NE(NETWORK_STATE_ANY, options.network_state);
- options.network_state = NETWORK_STATE_ANY;
- EXPECT_NE(POWER_STATE_AUTO, options.power_state);
- options.power_state = POWER_STATE_AUTO;
+ EXPECT_NE(NETWORK_STATE_AVOID_CELLULAR, options.network_state);
+ options.network_state = NETWORK_STATE_AVOID_CELLULAR;
// Store the registration.
EXPECT_TRUE(Register(options));
@@ -1133,49 +770,17 @@ TEST_F(BackgroundSyncManagerTest, StoreAndRetrievePreservesValues) {
SetupBackgroundSyncManager();
EXPECT_TRUE(GetRegistration(options));
- EXPECT_TRUE(options.Equals(*callback_registration_handle_->options()));
+ EXPECT_TRUE(options.Equals(*callback_registration_->options()));
}
TEST_F(BackgroundSyncManagerTest, EmptyTagSupported) {
- sync_options_1_.tag = "a";
- EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_TRUE(GetRegistration(sync_options_1_));
- EXPECT_TRUE(
- sync_options_1_.Equals(*callback_registration_handle_->options()));
- EXPECT_TRUE(Unregister(callback_registration_handle_.get()));
- EXPECT_FALSE(GetRegistration(sync_options_1_));
-}
-
-TEST_F(BackgroundSyncManagerTest, OverlappingPeriodicAndOneShotTags) {
- // Registrations with the same tags but different periodicities should not
- // collide.
sync_options_1_.tag = "";
- sync_options_2_.tag = "";
- sync_options_1_.periodicity = SYNC_PERIODIC;
- sync_options_2_.periodicity = SYNC_ONE_SHOT;
-
EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_TRUE(Register(sync_options_2_));
-
- EXPECT_TRUE(GetRegistration(sync_options_1_));
- EXPECT_EQ(SYNC_PERIODIC,
- callback_registration_handle_->options()->periodicity);
- EXPECT_TRUE(GetRegistration(sync_options_2_));
- EXPECT_EQ(SYNC_ONE_SHOT,
- callback_registration_handle_->options()->periodicity);
-
EXPECT_TRUE(GetRegistration(sync_options_1_));
- EXPECT_TRUE(Unregister(callback_registration_handle_.get()));
- EXPECT_FALSE(GetRegistration(sync_options_1_));
- EXPECT_TRUE(GetRegistration(sync_options_2_));
- EXPECT_EQ(SYNC_ONE_SHOT,
- callback_registration_handle_->options()->periodicity);
-
- EXPECT_TRUE(Unregister(callback_registration_handle_.get()));
- EXPECT_FALSE(GetRegistration(sync_options_2_));
+ EXPECT_TRUE(sync_options_1_.Equals(*callback_registration_->options()));
}
-TEST_F(BackgroundSyncManagerTest, OneShotFiresOnRegistration) {
+TEST_F(BackgroundSyncManagerTest, FiresOnRegistration) {
InitSyncEventTest();
EXPECT_TRUE(Register(sync_options_1_));
@@ -1183,139 +788,9 @@ TEST_F(BackgroundSyncManagerTest, OneShotFiresOnRegistration) {
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
-TEST_F(BackgroundSyncManagerTest, NotifyWhenFinishedAfterEventSuccess) {
- InitSyncEventTest();
-
- EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_EQ(1, sync_events_called_);
-
- EXPECT_TRUE(NotifyWhenFinished(callback_registration_handle_.get()));
- EXPECT_EQ(BACKGROUND_SYNC_STATE_SUCCESS, FinishedState());
-}
-
-TEST_F(BackgroundSyncManagerTest, NotifyWhenFinishedBeforeEventSuccess) {
- InitDelayedSyncEventTest();
-
- RegisterAndVerifySyncEventDelayed(sync_options_1_);
-
- EXPECT_FALSE(NotifyWhenFinished(callback_registration_handle_.get()));
-
- // Finish firing the event.
- sync_fired_callback_.Run(SERVICE_WORKER_OK);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, sync_events_called_);
- EXPECT_EQ(BACKGROUND_SYNC_STATE_SUCCESS, FinishedState());
-}
-
-TEST_F(BackgroundSyncManagerTest,
- NotifyWhenFinishedBeforeUnregisteredEventSuccess) {
- InitDelayedSyncEventTest();
-
- RegisterAndVerifySyncEventDelayed(sync_options_1_);
- EXPECT_FALSE(NotifyWhenFinished(callback_registration_handle_.get()));
-
- // Unregistering should set the state to UNREGISTERED but finished shouldn't
- // be called until the event finishes firing, at which point its state should
- // be SUCCESS.
- EXPECT_TRUE(Unregister(callback_registration_handle_.get()));
- EXPECT_FALSE(GetRegistration(sync_options_1_));
-
- // Finish firing the event.
- sync_fired_callback_.Run(SERVICE_WORKER_OK);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(BACKGROUND_SYNC_STATE_SUCCESS, FinishedState());
-}
-
-TEST_F(BackgroundSyncManagerTest,
- NotifyWhenFinishedBeforeUnregisteredEventFailure) {
- InitDelayedSyncEventTest();
-
- RegisterAndVerifySyncEventDelayed(sync_options_1_);
- EXPECT_FALSE(NotifyWhenFinished(callback_registration_handle_.get()));
-
- // Unregistering should set the state to UNREGISTERED but finished shouldn't
- // be called until the event finishes firing, at which point its state should
- // be FAILED.
- EXPECT_TRUE(Unregister(callback_registration_handle_.get()));
- EXPECT_FALSE(GetRegistration(sync_options_1_));
-
- // Finish firing the event.
- sync_fired_callback_.Run(SERVICE_WORKER_ERROR_FAILED);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, sync_events_called_);
- EXPECT_EQ(BACKGROUND_SYNC_STATE_FAILED, FinishedState());
-}
-
-TEST_F(BackgroundSyncManagerTest,
- NotifyWhenFinishedBeforeUnregisteredEventFires) {
- InitSyncEventTest();
-
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE);
- EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_TRUE(Unregister(callback_registration_handle_.get()));
- EXPECT_TRUE(NotifyWhenFinished(callback_registration_handle_.get()));
- EXPECT_EQ(BACKGROUND_SYNC_STATE_UNREGISTERED, FinishedState());
-}
-
-TEST_F(BackgroundSyncManagerTest,
- NotifyWhenFinishedBeforeEventSuccessDroppedHandle) {
- InitDelayedSyncEventTest();
-
- RegisterAndVerifySyncEventDelayed(sync_options_1_);
- EXPECT_FALSE(NotifyWhenFinished(callback_registration_handle_.get()));
-
- // Drop the client's handle to the registration before the event fires, ensure
- // that the finished callback is still run.
- callback_registration_handle_ = nullptr;
-
- // Finish firing the event.
- sync_fired_callback_.Run(SERVICE_WORKER_OK);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, sync_events_called_);
- EXPECT_EQ(BACKGROUND_SYNC_STATE_SUCCESS, FinishedState());
-}
-
-TEST_F(BackgroundSyncManagerTest, NotifyWhenFinishedAfterEventFailure) {
- InitFailedSyncEventTest();
-
- EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_EQ(1, sync_events_called_);
-
- EXPECT_TRUE(NotifyWhenFinished(callback_registration_handle_.get()));
- EXPECT_EQ(BACKGROUND_SYNC_STATE_FAILED, FinishedState());
-}
-
-TEST_F(BackgroundSyncManagerTest, NotifyWhenFinishedBeforeEventFailure) {
- InitDelayedSyncEventTest();
-
- RegisterAndVerifySyncEventDelayed(sync_options_1_);
- EXPECT_FALSE(NotifyWhenFinished(callback_registration_handle_.get()));
-
- // Finish firing the event.
- sync_fired_callback_.Run(SERVICE_WORKER_ERROR_FAILED);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(BACKGROUND_SYNC_STATE_FAILED, FinishedState());
-}
-
-TEST_F(BackgroundSyncManagerTest, NotifyWhenFinishedAfterUnregistered) {
- EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_TRUE(Unregister(callback_registration_handle_.get()));
-
- EXPECT_TRUE(NotifyWhenFinished(callback_registration_handle_.get()));
- EXPECT_EQ(BACKGROUND_SYNC_STATE_UNREGISTERED, FinishedState());
-}
-
-TEST_F(BackgroundSyncManagerTest, NotifyWhenFinishedBeforeUnregistered) {
- Register(sync_options_1_);
- EXPECT_FALSE(NotifyWhenFinished(callback_registration_handle_.get()));
- EXPECT_TRUE(Unregister(callback_registration_handle_.get()));
- EXPECT_EQ(BACKGROUND_SYNC_STATE_UNREGISTERED, FinishedState());
-}
-
TEST_F(BackgroundSyncManagerTest, ReregisterMidSyncFirstAttemptFails) {
InitDelayedSyncEventTest();
RegisterAndVerifySyncEventDelayed(sync_options_1_);
- EXPECT_FALSE(NotifyWhenFinished(callback_registration_handle_.get()));
// Reregister the event mid-sync
EXPECT_TRUE(Register(sync_options_1_));
@@ -1323,19 +798,16 @@ TEST_F(BackgroundSyncManagerTest, ReregisterMidSyncFirstAttemptFails) {
// The first sync attempt fails.
sync_fired_callback_.Run(SERVICE_WORKER_ERROR_FAILED);
base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(callback_finished_called_);
// It should fire again since it was reregistered mid-sync.
EXPECT_TRUE(GetRegistration(sync_options_1_));
sync_fired_callback_.Run(SERVICE_WORKER_OK);
EXPECT_FALSE(GetRegistration(sync_options_1_));
- EXPECT_EQ(BACKGROUND_SYNC_STATE_SUCCESS, FinishedState());
}
TEST_F(BackgroundSyncManagerTest, ReregisterMidSyncFirstAttemptSucceeds) {
InitDelayedSyncEventTest();
RegisterAndVerifySyncEventDelayed(sync_options_1_);
- EXPECT_FALSE(NotifyWhenFinished(callback_registration_handle_.get()));
// Reregister the event mid-sync
EXPECT_TRUE(Register(sync_options_1_));
@@ -1343,198 +815,67 @@ TEST_F(BackgroundSyncManagerTest, ReregisterMidSyncFirstAttemptSucceeds) {
// The first sync event succeeds.
sync_fired_callback_.Run(SERVICE_WORKER_OK);
base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(callback_finished_called_);
// It should fire again since it was reregistered mid-sync.
EXPECT_TRUE(GetRegistration(sync_options_1_));
sync_fired_callback_.Run(SERVICE_WORKER_OK);
EXPECT_FALSE(GetRegistration(sync_options_1_));
- EXPECT_EQ(BACKGROUND_SYNC_STATE_SUCCESS, FinishedState());
-}
-
-TEST_F(BackgroundSyncManagerTest,
- NotifyUnregisteredMidSyncNoRetryAttemptsLeft) {
- InitDelayedSyncEventTest();
-
- RegisterAndVerifySyncEventDelayed(sync_options_1_);
- EXPECT_FALSE(NotifyWhenFinished(callback_registration_handle_.get()));
-
- // Unregister the event mid-sync.
- EXPECT_TRUE(Unregister(callback_registration_handle_.get()));
-
- // Finish firing the event.
- sync_fired_callback_.Run(SERVICE_WORKER_ERROR_FAILED);
- base::RunLoop().RunUntilIdle();
-
- // Since there were no retry attempts left, the sync ultimately failed.
- EXPECT_EQ(BACKGROUND_SYNC_STATE_FAILED, FinishedState());
-}
-
-TEST_F(BackgroundSyncManagerTest,
- NotifyUnregisteredMidSyncWithRetryAttemptsLeft) {
- SetMaxSyncAttemptsAndRestartManager(2);
- InitDelayedSyncEventTest();
-
- RegisterAndVerifySyncEventDelayed(sync_options_1_);
- EXPECT_FALSE(NotifyWhenFinished(callback_registration_handle_.get()));
-
- // Unregister the event mid-sync.
- EXPECT_TRUE(Unregister(callback_registration_handle_.get()));
-
- // Finish firing the event.
- sync_fired_callback_.Run(SERVICE_WORKER_ERROR_FAILED);
- base::RunLoop().RunUntilIdle();
- // Since there was one retry attempt left, the sync didn't completely fail
- // before it was unregistered.
- EXPECT_EQ(BACKGROUND_SYNC_STATE_UNREGISTERED, FinishedState());
}
TEST_F(BackgroundSyncManagerTest, OverwritePendingRegistration) {
- // An overwritten pending registration should complete with
- // BACKGROUND_SYNC_STATE_UNREGISTERED.
- sync_options_1_.power_state = POWER_STATE_AVOID_DRAINING;
- EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_TRUE(GetRegistration(sync_options_1_));
- EXPECT_EQ(POWER_STATE_AVOID_DRAINING,
- callback_registration_handle_->options()->power_state);
- scoped_ptr<BackgroundSyncRegistrationHandle> original_handle =
- std::move(callback_registration_handle_);
+ InitFailedSyncEventTest();
- // Overwrite the pending registration.
- sync_options_1_.power_state = POWER_STATE_AUTO;
+ // Prevent the first sync from running so that it stays in a pending state.
+ SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE);
EXPECT_TRUE(Register(sync_options_1_));
EXPECT_TRUE(GetRegistration(sync_options_1_));
- EXPECT_EQ(POWER_STATE_AUTO,
- callback_registration_handle_->options()->power_state);
- EXPECT_TRUE(NotifyWhenFinished(original_handle.get()));
- EXPECT_EQ(BACKGROUND_SYNC_STATE_UNREGISTERED, FinishedState());
- EXPECT_EQ(0, sync_events_called_);
-}
-
-TEST_F(BackgroundSyncManagerTest, OverwriteFiringRegistrationWhichSucceeds) {
- // An overwritten pending registration should complete with
- // BACKGROUND_SYNC_STATE_SUCCESS if firing completes successfully.
- InitDelayedSyncEventTest();
-
- sync_options_1_.power_state = POWER_STATE_AVOID_DRAINING;
- RegisterAndVerifySyncEventDelayed(sync_options_1_);
- scoped_ptr<BackgroundSyncRegistrationHandle> original_handle =
- std::move(callback_registration_handle_);
-
- // The next registration won't block.
- InitSyncEventTest();
-
- // Overwrite the firing registration.
- sync_options_1_.power_state = POWER_STATE_AUTO;
+ // Overwrite the first sync. It should still be pending.
EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_FALSE(NotifyWhenFinished(original_handle.get()));
+ EXPECT_TRUE(GetRegistration(sync_options_1_));
- // Successfully finish the first event.
- sync_fired_callback_.Run(SERVICE_WORKER_OK);
+ // Verify that it only gets to run once.
+ SetNetwork(net::NetworkChangeNotifier::CONNECTION_WIFI);
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(BACKGROUND_SYNC_STATE_SUCCESS, FinishedState());
+ EXPECT_EQ(1, sync_events_called_);
+ EXPECT_FALSE(GetRegistration(sync_options_1_));
}
-TEST_F(BackgroundSyncManagerTest, OverwriteFiringRegistrationWhichFails) {
- // An overwritten pending registration should complete with
- // BACKGROUND_SYNC_STATE_FAILED if firing fails.
+TEST_F(BackgroundSyncManagerTest, DisableWhilePending) {
InitDelayedSyncEventTest();
-
- sync_options_1_.power_state = POWER_STATE_AVOID_DRAINING;
- RegisterAndVerifySyncEventDelayed(sync_options_1_);
- scoped_ptr<BackgroundSyncRegistrationHandle> original_handle =
- std::move(callback_registration_handle_);
-
- // The next registration won't block.
- InitSyncEventTest();
-
- // Overwrite the firing registration.
- sync_options_1_.power_state = POWER_STATE_AUTO;
- EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_FALSE(NotifyWhenFinished(original_handle.get()));
-
- // Fail the first event.
- sync_fired_callback_.Run(SERVICE_WORKER_ERROR_FAILED);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(BACKGROUND_SYNC_STATE_FAILED, FinishedState());
-}
-
-TEST_F(BackgroundSyncManagerTest, DisableWhilePendingNotifiesFinished) {
- InitSyncEventTest();
-
- // Register a one-shot that must wait for network connectivity before it
- // can fire.
SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE);
EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_FALSE(NotifyWhenFinished(callback_registration_handle_.get()));
// Corrupting the backend should result in the manager disabling itself on the
- // next operation. While disabling, it should finalize any pending
- // registrations.
+ // next operation.
test_background_sync_manager_->set_corrupt_backend(true);
EXPECT_FALSE(Register(sync_options_2_));
- EXPECT_EQ(BACKGROUND_SYNC_STATE_UNREGISTERED, FinishedState());
+
+ test_background_sync_manager_->set_corrupt_backend(false);
+ SetNetwork(net::NetworkChangeNotifier::CONNECTION_WIFI);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0, sync_events_called_);
}
-TEST_F(BackgroundSyncManagerTest, DisableWhileFiringNotifiesFinished) {
+TEST_F(BackgroundSyncManagerTest, DisableWhileFiring) {
InitDelayedSyncEventTest();
// Register a one-shot that pauses mid-fire.
RegisterAndVerifySyncEventDelayed(sync_options_1_);
- EXPECT_FALSE(NotifyWhenFinished(callback_registration_handle_.get()));
// Corrupting the backend should result in the manager disabling itself on the
- // next operation. Even though the manager is disabled, the firing sync event
- // should still be able to complete successfully and notify as much.
+ // next operation.
test_background_sync_manager_->set_corrupt_backend(true);
EXPECT_FALSE(Register(sync_options_2_));
- EXPECT_FALSE(callback_finished_called_);
test_background_sync_manager_->set_corrupt_backend(false);
- // Successfully complete the firing event.
+ // Successfully complete the firing event. We can't verify that it actually
+ // completed but at least we can test that it doesn't crash.
sync_fired_callback_.Run(SERVICE_WORKER_OK);
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(BACKGROUND_SYNC_STATE_SUCCESS, FinishedState());
-}
-
-// TODO(jkarlin): Change this to a periodic test as one-shots can't be power
-// dependent according to spec.
-TEST_F(BackgroundSyncManagerTest, OneShotFiresOnPowerChange) {
- InitSyncEventTest();
- sync_options_1_.power_state = POWER_STATE_AVOID_DRAINING;
-
- SetOnBatteryPower(true);
- EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_EQ(0, sync_events_called_);
- EXPECT_TRUE(GetRegistration(sync_options_1_));
-
- SetOnBatteryPower(false);
- EXPECT_EQ(1, sync_events_called_);
- EXPECT_FALSE(GetRegistration(sync_options_1_));
}
-// TODO(jkarlin): Change this to a periodic test as one-shots can't be power
-// dependent according to spec.
-TEST_F(BackgroundSyncManagerTest, MultipleOneShotsFireOnPowerChange) {
- InitSyncEventTest();
- sync_options_1_.power_state = POWER_STATE_AVOID_DRAINING;
- sync_options_2_.power_state = POWER_STATE_AVOID_DRAINING;
-
- SetOnBatteryPower(true);
- EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_TRUE(Register(sync_options_2_));
- EXPECT_EQ(0, sync_events_called_);
- EXPECT_TRUE(GetRegistration(sync_options_1_));
- EXPECT_TRUE(GetRegistration(sync_options_2_));
-
- SetOnBatteryPower(false);
- EXPECT_EQ(2, sync_events_called_);
- EXPECT_FALSE(GetRegistration(sync_options_1_));
- EXPECT_FALSE(GetRegistration(sync_options_2_));
-}
-
-TEST_F(BackgroundSyncManagerTest, OneShotFiresOnNetworkChange) {
+TEST_F(BackgroundSyncManagerTest, FiresOnNetworkChange) {
InitSyncEventTest();
SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE);
@@ -1548,7 +889,7 @@ TEST_F(BackgroundSyncManagerTest, OneShotFiresOnNetworkChange) {
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
-TEST_F(BackgroundSyncManagerTest, MultipleOneShotsFireOnNetworkChange) {
+TEST_F(BackgroundSyncManagerTest, MultipleRegistrationsFireOnNetworkChange) {
InitSyncEventTest();
SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE);
@@ -1565,7 +906,7 @@ TEST_F(BackgroundSyncManagerTest, MultipleOneShotsFireOnNetworkChange) {
EXPECT_FALSE(GetRegistration(sync_options_2_));
}
-TEST_F(BackgroundSyncManagerTest, OneShotFiresOnManagerRestart) {
+TEST_F(BackgroundSyncManagerTest, FiresOnManagerRestart) {
InitSyncEventTest();
// Initially the event won't run because there is no network.
@@ -1587,7 +928,7 @@ TEST_F(BackgroundSyncManagerTest, OneShotFiresOnManagerRestart) {
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
-TEST_F(BackgroundSyncManagerTest, FailedOneShotShouldBeRemoved) {
+TEST_F(BackgroundSyncManagerTest, FailedRegistrationShouldBeRemoved) {
InitFailedSyncEventTest();
EXPECT_TRUE(Register(sync_options_1_));
@@ -1595,7 +936,7 @@ TEST_F(BackgroundSyncManagerTest, FailedOneShotShouldBeRemoved) {
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
-TEST_F(BackgroundSyncManagerTest, FailedOneShotReregisteredAndFires) {
+TEST_F(BackgroundSyncManagerTest, FailedRegistrationReregisteredAndFires) {
InitFailedSyncEventTest();
// The initial sync event fails.
@@ -1612,7 +953,7 @@ TEST_F(BackgroundSyncManagerTest, FailedOneShotReregisteredAndFires) {
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
-TEST_F(BackgroundSyncManagerTest, DelayOneShotMidSync) {
+TEST_F(BackgroundSyncManagerTest, DelayMidSync) {
InitDelayedSyncEventTest();
RegisterAndVerifySyncEventDelayed(sync_options_1_);
@@ -1624,50 +965,6 @@ TEST_F(BackgroundSyncManagerTest, DelayOneShotMidSync) {
EXPECT_FALSE(GetRegistration(sync_options_1_));
}
-TEST_F(BackgroundSyncManagerTest, OverwriteRegistrationMidSync) {
- InitDelayedSyncEventTest();
-
- sync_options_1_.network_state = NETWORK_STATE_ANY;
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE);
-
- RegisterAndVerifySyncEventDelayed(sync_options_1_);
-
- // Don't delay the next sync.
- test_background_sync_manager_->set_one_shot_callback(
- base::Bind(OneShotSuccessfulCallback, &sync_events_called_));
-
- // Register a different sync event with the same tag, overwriting the first.
- sync_options_1_.network_state = NETWORK_STATE_ONLINE;
- EXPECT_TRUE(Register(sync_options_1_));
-
- // The new sync event won't run as the network requirements aren't met.
- EXPECT_EQ(1, sync_events_called_);
- EXPECT_TRUE(GetRegistration(sync_options_1_));
-
- // Finish the first event, note that the second is still registered.
- sync_fired_callback_.Run(SERVICE_WORKER_OK);
- EXPECT_EQ(1, sync_events_called_);
- EXPECT_TRUE(GetRegistration(sync_options_1_));
-
- // Change the network and the second should run.
- SetNetwork(net::NetworkChangeNotifier::CONNECTION_WIFI);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(2, sync_events_called_);
- EXPECT_FALSE(GetRegistration(sync_options_1_));
-}
-
-TEST_F(BackgroundSyncManagerTest, UnregisterOneShotMidSync) {
- InitDelayedSyncEventTest();
-
- RegisterAndVerifySyncEventDelayed(sync_options_1_);
-
- EXPECT_TRUE(Unregister(callback_registration_handle_.get()));
- EXPECT_FALSE(GetRegistration(sync_options_1_));
-
- sync_fired_callback_.Run(SERVICE_WORKER_OK);
- EXPECT_FALSE(GetRegistration(sync_options_1_));
-}
-
TEST_F(BackgroundSyncManagerTest, BadBackendMidSync) {
InitDelayedSyncEventTest();
@@ -1712,34 +1009,19 @@ TEST_F(BackgroundSyncManagerTest, KillManagerMidSync) {
EXPECT_EQ(2, sync_events_called_);
}
-TEST_F(BackgroundSyncManagerTest, RegisterFromServiceWorkerWithoutMainFrame) {
+TEST_F(BackgroundSyncManagerTest, RegisterWithoutMainFrame) {
test_background_sync_manager_->set_has_main_frame_provider_host(false);
EXPECT_FALSE(Register(sync_options_1_));
}
-TEST_F(BackgroundSyncManagerTest,
- RegisterFromDocumentWithoutMainFrameProviderHost) {
- test_background_sync_manager_->set_has_main_frame_provider_host(false);
- EXPECT_TRUE(RegisterFromDocumentWithServiceWorkerId(sw_registration_id_1_,
- sync_options_1_));
-}
-
-TEST_F(BackgroundSyncManagerTest,
- RegisterExistingFromServiceWorkerWithoutMainFrame) {
+TEST_F(BackgroundSyncManagerTest, RegisterExistingWithoutMainFrame) {
EXPECT_TRUE(Register(sync_options_1_));
test_background_sync_manager_->set_has_main_frame_provider_host(false);
EXPECT_FALSE(Register(sync_options_1_));
}
-TEST_F(BackgroundSyncManagerTest, UnregisterSucceedsWithoutMainFrame) {
- EXPECT_TRUE(Register(sync_options_1_));
- test_background_sync_manager_->set_has_main_frame_provider_host(false);
- EXPECT_TRUE(Unregister(callback_registration_handle_.get()));
- EXPECT_FALSE(GetRegistration(sync_options_1_));
-}
-
TEST_F(BackgroundSyncManagerTest, DefaultParameters) {
- *test_controller_->background_sync_parameters() = BackgroundSyncParameters();
+ *GetController()->background_sync_parameters() = BackgroundSyncParameters();
// Restart the BackgroundSyncManager so that it updates its parameters.
SetupBackgroundSyncManager();
@@ -1749,7 +1031,7 @@ TEST_F(BackgroundSyncManagerTest, DefaultParameters) {
TEST_F(BackgroundSyncManagerTest, OverrideParameters) {
BackgroundSyncParameters* parameters =
- test_controller_->background_sync_parameters();
+ GetController()->background_sync_parameters();
parameters->disable = true;
parameters->max_sync_attempts = 100;
parameters->initial_retry_delay = base::TimeDelta::FromMinutes(200);
@@ -1773,7 +1055,7 @@ TEST_F(BackgroundSyncManagerTest, DisablingFromControllerKeepsRegistrations) {
EXPECT_TRUE(Register(sync_options_1_));
BackgroundSyncParameters* parameters =
- test_controller_->background_sync_parameters();
+ GetController()->background_sync_parameters();
parameters->disable = true;
// Restart the BackgroundSyncManager so that it updates its parameters.
@@ -1790,7 +1072,7 @@ TEST_F(BackgroundSyncManagerTest, DisablingFromControllerKeepsRegistrations) {
TEST_F(BackgroundSyncManagerTest, DisabledPermanently) {
BackgroundSyncParameters* parameters =
- test_controller_->background_sync_parameters();
+ GetController()->background_sync_parameters();
parameters->disable = true;
// Restart the BackgroundSyncManager so that it updates its parameters.
@@ -1810,11 +1092,11 @@ TEST_F(BackgroundSyncManagerTest, DisabledPermanently) {
TEST_F(BackgroundSyncManagerTest, NotifyBackgroundSyncRegistered) {
// Verify that the BackgroundSyncController is informed of registrations.
- EXPECT_EQ(0, test_controller_->registration_count());
+ EXPECT_EQ(0, GetController()->registration_count());
EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_EQ(1, test_controller_->registration_count());
+ EXPECT_EQ(1, GetController()->registration_count());
EXPECT_EQ(GURL(kPattern1).GetOrigin().spec(),
- test_controller_->registration_origin().spec());
+ GetController()->registration_origin().spec());
}
TEST_F(BackgroundSyncManagerTest, WakeBrowserCalled) {
@@ -1822,30 +1104,30 @@ TEST_F(BackgroundSyncManagerTest, WakeBrowserCalled) {
// The BackgroundSyncManager should declare in initialization
// that it doesn't need to be woken up since it has no registrations.
- EXPECT_LT(0, test_controller_->run_in_background_count());
- EXPECT_FALSE(test_controller_->run_in_background_enabled());
+ EXPECT_LT(0, GetController()->run_in_background_count());
+ EXPECT_FALSE(GetController()->run_in_background_enabled());
SetNetwork(net::NetworkChangeNotifier::CONNECTION_NONE);
- EXPECT_FALSE(test_controller_->run_in_background_enabled());
+ EXPECT_FALSE(GetController()->run_in_background_enabled());
// Register a one-shot but it can't fire due to lack of network, wake up is
// required.
Register(sync_options_1_);
- EXPECT_TRUE(test_controller_->run_in_background_enabled());
+ EXPECT_TRUE(GetController()->run_in_background_enabled());
// Start the event but it will pause mid-sync due to
// InitDelayedSyncEventTest() above.
SetNetwork(net::NetworkChangeNotifier::CONNECTION_WIFI);
- EXPECT_TRUE(test_controller_->run_in_background_enabled());
+ EXPECT_TRUE(GetController()->run_in_background_enabled());
EXPECT_EQ(test_background_sync_manager_->background_sync_parameters()
->min_sync_recovery_time,
base::TimeDelta::FromMilliseconds(
- test_controller_->run_in_background_min_ms()));
+ GetController()->run_in_background_min_ms()));
// Finish the sync.
sync_fired_callback_.Run(SERVICE_WORKER_OK);
base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(test_controller_->run_in_background_enabled());
+ EXPECT_FALSE(GetController()->run_in_background_enabled());
}
TEST_F(BackgroundSyncManagerTest, OneAttempt) {
@@ -2022,7 +1304,7 @@ TEST_F(BackgroundSyncManagerTest, LastChance) {
InitFailedSyncEventTest();
EXPECT_TRUE(Register(sync_options_1_));
- EXPECT_EQ(BACKGROUND_SYNC_EVENT_LAST_CHANCE_IS_NOT_LAST_CHANCE,
+ EXPECT_EQ(mojom::BackgroundSyncEventLastChance::IS_NOT_LAST_CHANCE,
test_background_sync_manager_->last_chance());
EXPECT_TRUE(GetRegistration(sync_options_1_));
@@ -2031,7 +1313,7 @@ TEST_F(BackgroundSyncManagerTest, LastChance) {
test_background_sync_manager_->delayed_task().Run();
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(GetRegistration(sync_options_1_));
- EXPECT_EQ(BACKGROUND_SYNC_EVENT_LAST_CHANCE_IS_LAST_CHANCE,
+ EXPECT_EQ(mojom::BackgroundSyncEventLastChance::IS_LAST_CHANCE,
test_background_sync_manager_->last_chance());
}
diff --git a/chromium/content/browser/background_sync/background_sync_metrics.cc b/chromium/content/browser/background_sync/background_sync_metrics.cc
index 20b3a6651a3..8ae07b74eb6 100644
--- a/chromium/content/browser/background_sync/background_sync_metrics.cc
+++ b/chromium/content/browser/background_sync/background_sync_metrics.cc
@@ -33,40 +33,18 @@ ResultPattern EventResultToResultPattern(bool success,
namespace content {
// static
-void BackgroundSyncMetrics::RecordEventStarted(SyncPeriodicity periodicity,
- bool started_in_foreground) {
- switch (periodicity) {
- case SYNC_ONE_SHOT:
- UMA_HISTOGRAM_BOOLEAN("BackgroundSync.Event.OneShotStartedInForeground",
- started_in_foreground);
- return;
- case SYNC_PERIODIC:
- UMA_HISTOGRAM_BOOLEAN("BackgroundSync.Event.PeriodicStartedInForeground",
- started_in_foreground);
- return;
- }
- NOTREACHED();
+void BackgroundSyncMetrics::RecordEventStarted(bool started_in_foreground) {
+ UMA_HISTOGRAM_BOOLEAN("BackgroundSync.Event.OneShotStartedInForeground",
+ started_in_foreground);
}
// static
-void BackgroundSyncMetrics::RecordEventResult(SyncPeriodicity periodicity,
- bool success,
+void BackgroundSyncMetrics::RecordEventResult(bool success,
bool finished_in_foreground) {
- switch (periodicity) {
- case SYNC_ONE_SHOT:
- UMA_HISTOGRAM_ENUMERATION(
- "BackgroundSync.Event.OneShotResultPattern",
- EventResultToResultPattern(success, finished_in_foreground),
- RESULT_PATTERN_MAX + 1);
- return;
- case SYNC_PERIODIC:
- UMA_HISTOGRAM_ENUMERATION(
- "BackgroundSync.Event.PeriodicResultPattern",
- EventResultToResultPattern(success, finished_in_foreground),
- RESULT_PATTERN_MAX + 1);
- return;
- }
- NOTREACHED();
+ UMA_HISTOGRAM_ENUMERATION(
+ "BackgroundSync.Event.OneShotResultPattern",
+ EventResultToResultPattern(success, finished_in_foreground),
+ RESULT_PATTERN_MAX + 1);
}
// static
@@ -84,62 +62,23 @@ void BackgroundSyncMetrics::RecordBatchSyncEventComplete(
// static
void BackgroundSyncMetrics::CountRegisterSuccess(
- SyncPeriodicity periodicity,
RegistrationCouldFire registration_could_fire,
RegistrationIsDuplicate registration_is_duplicate) {
- switch (periodicity) {
- case SYNC_ONE_SHOT:
- UMA_HISTOGRAM_ENUMERATION("BackgroundSync.Registration.OneShot",
- BACKGROUND_SYNC_STATUS_OK,
- BACKGROUND_SYNC_STATUS_MAX + 1);
- UMA_HISTOGRAM_BOOLEAN("BackgroundSync.Registration.OneShot.CouldFire",
- registration_could_fire == REGISTRATION_COULD_FIRE);
- UMA_HISTOGRAM_BOOLEAN(
- "BackgroundSync.Registration.OneShot.IsDuplicate",
- registration_is_duplicate == REGISTRATION_IS_DUPLICATE);
- return;
- case SYNC_PERIODIC:
- UMA_HISTOGRAM_ENUMERATION("BackgroundSync.Registration.Periodic",
- BACKGROUND_SYNC_STATUS_OK,
- BACKGROUND_SYNC_STATUS_MAX + 1);
- UMA_HISTOGRAM_BOOLEAN(
- "BackgroundSync.Registration.Periodic.IsDuplicate",
- registration_is_duplicate == REGISTRATION_IS_DUPLICATE);
- return;
- }
- NOTREACHED();
-}
-
-// static
-void BackgroundSyncMetrics::CountRegisterFailure(SyncPeriodicity periodicity,
- BackgroundSyncStatus result) {
- switch (periodicity) {
- case SYNC_ONE_SHOT:
- UMA_HISTOGRAM_ENUMERATION("BackgroundSync.Registration.OneShot", result,
- BACKGROUND_SYNC_STATUS_MAX + 1);
- return;
- case SYNC_PERIODIC:
- UMA_HISTOGRAM_ENUMERATION("BackgroundSync.Registration.Periodic", result,
- BACKGROUND_SYNC_STATUS_MAX + 1);
- return;
- }
- NOTREACHED();
+ UMA_HISTOGRAM_ENUMERATION("BackgroundSync.Registration.OneShot",
+ BACKGROUND_SYNC_STATUS_OK,
+ BACKGROUND_SYNC_STATUS_MAX + 1);
+ UMA_HISTOGRAM_BOOLEAN("BackgroundSync.Registration.OneShot.CouldFire",
+ registration_could_fire == REGISTRATION_COULD_FIRE);
+ UMA_HISTOGRAM_BOOLEAN("BackgroundSync.Registration.OneShot.IsDuplicate",
+ registration_is_duplicate == REGISTRATION_IS_DUPLICATE);
+ return;
}
// static
-void BackgroundSyncMetrics::CountUnregister(SyncPeriodicity periodicity,
- BackgroundSyncStatus result) {
- switch (periodicity) {
- case SYNC_ONE_SHOT:
- UMA_HISTOGRAM_ENUMERATION("BackgroundSync.Unregistration.OneShot", result,
- BACKGROUND_SYNC_STATUS_MAX + 1);
- return;
- case SYNC_PERIODIC:
- UMA_HISTOGRAM_ENUMERATION("BackgroundSync.Unregistration.Periodic",
- result, BACKGROUND_SYNC_STATUS_MAX + 1);
- return;
- }
- NOTREACHED();
+void BackgroundSyncMetrics::CountRegisterFailure(BackgroundSyncStatus result) {
+ UMA_HISTOGRAM_ENUMERATION("BackgroundSync.Registration.OneShot", result,
+ BACKGROUND_SYNC_STATUS_MAX + 1);
+ return;
}
} // namespace content
diff --git a/chromium/content/browser/background_sync/background_sync_metrics.h b/chromium/content/browser/background_sync/background_sync_metrics.h
index f92a7c5b7a3..3280896f671 100644
--- a/chromium/content/browser/background_sync/background_sync_metrics.h
+++ b/chromium/content/browser/background_sync/background_sync_metrics.h
@@ -29,13 +29,10 @@ class BackgroundSyncMetrics {
};
// Records the start of a sync event.
- static void RecordEventStarted(SyncPeriodicity periodicity,
- bool startedin_foreground);
+ static void RecordEventStarted(bool startedin_foreground);
// Records the result of a single sync event firing.
- static void RecordEventResult(SyncPeriodicity periodicity,
- bool result,
- bool finished_in_foreground);
+ static void RecordEventResult(bool result, bool finished_in_foreground);
// Records the result of running a batch of sync events, including the total
// time spent, and the batch size.
@@ -46,17 +43,11 @@ class BackgroundSyncMetrics {
// indicates whether the conditions were sufficient for the sync to fire
// immediately at the time it was registered.
static void CountRegisterSuccess(
- SyncPeriodicity periodicity,
RegistrationCouldFire could_fire,
RegistrationIsDuplicate registration_is_duplicate);
// Records the status of a failed sync registration.
- static void CountRegisterFailure(SyncPeriodicity periodicity,
- BackgroundSyncStatus status);
-
- // Records the result of trying to unregister a sync.
- static void CountUnregister(SyncPeriodicity periodicity,
- BackgroundSyncStatus result);
+ static void CountRegisterFailure(BackgroundSyncStatus status);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(BackgroundSyncMetrics);
diff --git a/chromium/content/browser/background_sync/background_sync_power_observer.cc b/chromium/content/browser/background_sync/background_sync_power_observer.cc
deleted file mode 100644
index 087fe21e37d..00000000000
--- a/chromium/content/browser/background_sync/background_sync_power_observer.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/background_sync/background_sync_power_observer.h"
-
-#include "base/power_monitor/power_monitor.h"
-#include "base/thread_task_runner_handle.h"
-
-namespace content {
-
-BackgroundSyncPowerObserver::BackgroundSyncPowerObserver(
- const base::Closure& power_callback)
- : observing_power_monitor_(false),
- on_battery_(true),
- power_changed_callback_(power_callback) {
- base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
- if (power_monitor) {
- observing_power_monitor_ = true;
- on_battery_ = power_monitor->IsOnBatteryPower();
- power_monitor->AddObserver(this);
- }
-}
-
-BackgroundSyncPowerObserver::~BackgroundSyncPowerObserver() {
- base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
-
- if (power_monitor)
- power_monitor->RemoveObserver(this);
-}
-
-bool BackgroundSyncPowerObserver::PowerSufficient(
- SyncPowerState power_state) const {
- DCHECK(observing_power_monitor_);
- DCHECK(base::PowerMonitor::Get());
-
- switch (power_state) {
- case POWER_STATE_AUTO:
- // TODO(jkarlin): Also check for device status, such as power saving mode
- // or user preferences. crbug.com/482088.
- return true;
- case POWER_STATE_AVOID_DRAINING:
- return !on_battery_;
- }
-
- NOTREACHED();
- return false;
-}
-
-void BackgroundSyncPowerObserver::OnPowerStateChange(bool on_battery_power) {
- DCHECK(observing_power_monitor_);
- DCHECK(base::PowerMonitor::Get());
-
- if (on_battery_ == on_battery_power)
- return;
-
- on_battery_ = on_battery_power;
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- power_changed_callback_);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/background_sync/background_sync_power_observer.h b/chromium/content/browser/background_sync/background_sync_power_observer.h
deleted file mode 100644
index b0da8f9facc..00000000000
--- a/chromium/content/browser/background_sync/background_sync_power_observer.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_POWER_OBSERVER_H_
-#define CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_POWER_OBSERVER_H_
-
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/power_monitor/power_observer.h"
-#include "content/browser/background_sync/background_sync.pb.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-// BackgroundSyncPowerObserver monitors the charging status of the device and
-// determines if the power conditions of BackgroundSyncRegistrations are met.
-class CONTENT_EXPORT BackgroundSyncPowerObserver : public base::PowerObserver {
- public:
- // Creates a BackgroundSyncPowerObserver. |power_callback| is run when the
- // battery states changes asynchronously via PostMessage.
- explicit BackgroundSyncPowerObserver(const base::Closure& power_callback);
-
- ~BackgroundSyncPowerObserver() override;
-
- // Returns true if the state of the battery (charging or not) meets the needs
- // of |power_state|.
- bool PowerSufficient(SyncPowerState power_state) const;
-
- private:
- friend class BackgroundSyncPowerObserverTest;
-
- // PowerObserver overrides
- void OnPowerStateChange(bool on_battery_power) override;
-
- // |observing_power_monitor_| is true when the constructor is able to find and
- // register an observer with the base::PowerMonitor. This should always be
- // true except for tests in which the browser initialization isn't done.
- bool observing_power_monitor_;
-
- bool on_battery_;
-
- // The callback to run when the battery state changes.
- base::Closure power_changed_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(BackgroundSyncPowerObserver);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_POWER_OBSERVER_H_
diff --git a/chromium/content/browser/background_sync/background_sync_power_observer_unittest.cc b/chromium/content/browser/background_sync/background_sync_power_observer_unittest.cc
deleted file mode 100644
index 857ac069192..00000000000
--- a/chromium/content/browser/background_sync/background_sync_power_observer_unittest.cc
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <content/browser/background_sync/background_sync_power_observer.h>
-
-#include "base/macros.h"
-#include "base/run_loop.h"
-#include "base/test/power_monitor_test_base.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-namespace {
-
-class BackgroundSyncPowerObserverTest : public testing::Test {
- protected:
- BackgroundSyncPowerObserverTest() : power_changed_count_(0) {
- power_monitor_source_ = new base::PowerMonitorTestSource();
- power_monitor_.reset(new base::PowerMonitor(
- scoped_ptr<base::PowerMonitorSource>(power_monitor_source_)));
- power_observer_.reset(new BackgroundSyncPowerObserver(
- base::Bind(&BackgroundSyncPowerObserverTest::OnPowerChanged,
- base::Unretained(this))));
- }
-
- void SetOnBatteryPower(bool on_battery_power) {
- power_monitor_source_->GeneratePowerStateEvent(on_battery_power);
- }
-
- void OnPowerChanged() { power_changed_count_++; }
-
- // power_monitor_source_ is owned by power_monitor_
- base::PowerMonitorTestSource* power_monitor_source_;
- scoped_ptr<base::PowerMonitor> power_monitor_;
- scoped_ptr<BackgroundSyncPowerObserver> power_observer_;
- int power_changed_count_;
-
- DISALLOW_COPY_AND_ASSIGN(BackgroundSyncPowerObserverTest);
-};
-
-TEST_F(BackgroundSyncPowerObserverTest, PowerChangeInvokesCallback) {
- SetOnBatteryPower(true);
- power_changed_count_ = 0;
-
- SetOnBatteryPower(false);
- EXPECT_EQ(1, power_changed_count_);
- SetOnBatteryPower(true);
- EXPECT_EQ(2, power_changed_count_);
- SetOnBatteryPower(true);
- EXPECT_EQ(2, power_changed_count_);
-}
-
-TEST_F(BackgroundSyncPowerObserverTest, PowerSufficientAuto) {
- SetOnBatteryPower(false);
- EXPECT_TRUE(power_observer_->PowerSufficient(POWER_STATE_AUTO));
-
- SetOnBatteryPower(true);
- EXPECT_TRUE(power_observer_->PowerSufficient(POWER_STATE_AUTO));
-}
-
-TEST_F(BackgroundSyncPowerObserverTest, PowerSufficientAvoidDraining) {
- SetOnBatteryPower(false);
- EXPECT_TRUE(power_observer_->PowerSufficient(POWER_STATE_AVOID_DRAINING));
-
- SetOnBatteryPower(true);
- EXPECT_FALSE(power_observer_->PowerSufficient(POWER_STATE_AVOID_DRAINING));
-}
-
-} // namespace
-
-} // namespace content
diff --git a/chromium/content/browser/background_sync/background_sync_registration.cc b/chromium/content/browser/background_sync/background_sync_registration.cc
index b20e2ef744f..d835e67d4cb 100644
--- a/chromium/content/browser/background_sync/background_sync_registration.cc
+++ b/chromium/content/browser/background_sync/background_sync_registration.cc
@@ -18,9 +18,6 @@ const BackgroundSyncRegistration::RegistrationId
const BackgroundSyncRegistration::RegistrationId
BackgroundSyncRegistration::kInitialId = 0;
-BackgroundSyncRegistration::BackgroundSyncRegistration() = default;
-BackgroundSyncRegistration::~BackgroundSyncRegistration() = default;
-
bool BackgroundSyncRegistration::Equals(
const BackgroundSyncRegistration& other) const {
return options_.Equals(other.options_);
@@ -30,69 +27,16 @@ bool BackgroundSyncRegistration::IsValid() const {
return id_ != kInvalidRegistrationId;
}
-void BackgroundSyncRegistration::AddFinishedCallback(
- const StateCallback& callback) {
- DCHECK(!HasCompleted());
- notify_finished_callbacks_.push_back(callback);
-}
-
-void BackgroundSyncRegistration::RunFinishedCallbacks() {
- DCHECK(HasCompleted());
-
- for (auto& callback : notify_finished_callbacks_) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(callback, sync_state_));
- }
-
- notify_finished_callbacks_.clear();
-}
-
-bool BackgroundSyncRegistration::HasCompleted() const {
- switch (sync_state_) {
- case BACKGROUND_SYNC_STATE_PENDING:
- case BACKGROUND_SYNC_STATE_FIRING:
- case BACKGROUND_SYNC_STATE_REREGISTERED_WHILE_FIRING:
- case BACKGROUND_SYNC_STATE_UNREGISTERED_WHILE_FIRING:
- return false;
- case BACKGROUND_SYNC_STATE_FAILED:
- case BACKGROUND_SYNC_STATE_SUCCESS:
- case BACKGROUND_SYNC_STATE_UNREGISTERED:
- return true;
- }
- NOTREACHED();
- return false;
-}
-
bool BackgroundSyncRegistration::IsFiring() const {
switch (sync_state_) {
- case BACKGROUND_SYNC_STATE_FIRING:
- case BACKGROUND_SYNC_STATE_REREGISTERED_WHILE_FIRING:
- case BACKGROUND_SYNC_STATE_UNREGISTERED_WHILE_FIRING:
+ case mojom::BackgroundSyncState::FIRING:
+ case mojom::BackgroundSyncState::REREGISTERED_WHILE_FIRING:
return true;
- case BACKGROUND_SYNC_STATE_PENDING:
- case BACKGROUND_SYNC_STATE_FAILED:
- case BACKGROUND_SYNC_STATE_SUCCESS:
- case BACKGROUND_SYNC_STATE_UNREGISTERED:
+ case mojom::BackgroundSyncState::PENDING:
return false;
}
NOTREACHED();
return false;
}
-void BackgroundSyncRegistration::SetUnregisteredState() {
- DCHECK(!HasCompleted());
-
- bool is_firing = IsFiring();
-
- sync_state_ = is_firing ? BACKGROUND_SYNC_STATE_UNREGISTERED_WHILE_FIRING
- : BACKGROUND_SYNC_STATE_UNREGISTERED;
-
- if (!is_firing) {
- // If the registration is currently firing then wait to run
- // RunFinishedCallbacks until after it has finished as it might
- // change state to SUCCESS first.
- RunFinishedCallbacks();
- }
-}
-
} // namespace content
diff --git a/chromium/content/browser/background_sync/background_sync_registration.h b/chromium/content/browser/background_sync/background_sync_registration.h
index 4e4f1cd3f33..924540f65ac 100644
--- a/chromium/content/browser/background_sync/background_sync_registration.h
+++ b/chromium/content/browser/background_sync/background_sync_registration.h
@@ -24,34 +24,27 @@ namespace content {
class CONTENT_EXPORT BackgroundSyncRegistration {
public:
using RegistrationId = int64_t;
- using StateCallback = base::Callback<void(BackgroundSyncState)>;
static const RegistrationId kInitialId;
- BackgroundSyncRegistration();
- ~BackgroundSyncRegistration();
+ BackgroundSyncRegistration() = default;
+ BackgroundSyncRegistration(const BackgroundSyncRegistration& other) = default;
+ BackgroundSyncRegistration& operator=(
+ const BackgroundSyncRegistration& other) = default;
+ ~BackgroundSyncRegistration() = default;
bool Equals(const BackgroundSyncRegistration& other) const;
bool IsValid() const;
- void AddFinishedCallback(const StateCallback& callback);
- void RunFinishedCallbacks();
- bool HasCompleted() const;
bool IsFiring() const;
- // If the registration is currently firing, sets its state to
- // BACKGROUND_SYNC_STATE_UNREGISTERED_WHILE_FIRING. If it is firing, it sets
- // the state to BACKGROUND_SYNC_STATE_UNREGISTERED and calls
- // RunFinishedCallbacks.
- void SetUnregisteredState();
-
const BackgroundSyncRegistrationOptions* options() const { return &options_; }
BackgroundSyncRegistrationOptions* options() { return &options_; }
RegistrationId id() const { return id_; }
void set_id(RegistrationId id) { id_ = id; }
- BackgroundSyncState sync_state() const { return sync_state_; }
- void set_sync_state(BackgroundSyncState state) { sync_state_ = state; }
+ mojom::BackgroundSyncState sync_state() const { return sync_state_; }
+ void set_sync_state(mojom::BackgroundSyncState state) { sync_state_ = state; }
int num_attempts() const { return num_attempts_; }
void set_num_attempts(int num_attempts) { num_attempts_ = num_attempts; }
@@ -64,13 +57,9 @@ class CONTENT_EXPORT BackgroundSyncRegistration {
BackgroundSyncRegistrationOptions options_;
RegistrationId id_ = kInvalidRegistrationId;
- BackgroundSyncState sync_state_ = BACKGROUND_SYNC_STATE_PENDING;
+ mojom::BackgroundSyncState sync_state_ = mojom::BackgroundSyncState::PENDING;
int num_attempts_ = 0;
base::Time delay_until_;
-
- std::list<StateCallback> notify_finished_callbacks_;
-
- DISALLOW_COPY_AND_ASSIGN(BackgroundSyncRegistration);
};
} // namespace content
@@ -80,15 +69,15 @@ namespace mojo {
template <>
struct CONTENT_EXPORT
TypeConverter<scoped_ptr<content::BackgroundSyncRegistration>,
- content::SyncRegistrationPtr> {
+ content::mojom::SyncRegistrationPtr> {
static scoped_ptr<content::BackgroundSyncRegistration> Convert(
- const content::SyncRegistrationPtr& input);
+ const content::mojom::SyncRegistrationPtr& input);
};
template <>
-struct CONTENT_EXPORT TypeConverter<content::SyncRegistrationPtr,
+struct CONTENT_EXPORT TypeConverter<content::mojom::SyncRegistrationPtr,
content::BackgroundSyncRegistration> {
- static content::SyncRegistrationPtr Convert(
+ static content::mojom::SyncRegistrationPtr Convert(
const content::BackgroundSyncRegistration& input);
};
diff --git a/chromium/content/browser/background_sync/background_sync_registration_handle.cc b/chromium/content/browser/background_sync/background_sync_registration_handle.cc
deleted file mode 100644
index eca0abbb693..00000000000
--- a/chromium/content/browser/background_sync/background_sync_registration_handle.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/background_sync/background_sync_registration_handle.h"
-
-#include "content/browser/background_sync/background_sync_manager.h"
-#include "content/public/browser/browser_thread.h"
-
-namespace content {
-
-BackgroundSyncRegistrationHandle::~BackgroundSyncRegistrationHandle() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (IsValid() && background_sync_manager_)
- background_sync_manager_->ReleaseRegistrationHandle(handle_id_);
-}
-
-void BackgroundSyncRegistrationHandle::Unregister(
- int64_t sw_registration_id,
- const StatusCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(IsValid());
- DCHECK(background_sync_manager_);
-
- background_sync_manager_->Unregister(sw_registration_id, handle_id_,
- callback);
-}
-
-void BackgroundSyncRegistrationHandle::NotifyWhenFinished(
- const StatusAndStateCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(IsValid());
- DCHECK(background_sync_manager_);
-
- background_sync_manager_->NotifyWhenFinished(handle_id_, callback);
-}
-
-bool BackgroundSyncRegistrationHandle::IsValid() const {
- return registration_ != nullptr;
-}
-
-BackgroundSyncRegistrationHandle::BackgroundSyncRegistrationHandle(
- base::WeakPtr<BackgroundSyncManager> background_sync_manager,
- HandleId handle_id)
- : background_sync_manager_(background_sync_manager),
- handle_id_(handle_id),
- registration_(
- background_sync_manager_->GetRegistrationForHandle(handle_id_)) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(background_sync_manager_);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/background_sync/background_sync_registration_handle.h b/chromium/content/browser/background_sync/background_sync_registration_handle.h
deleted file mode 100644
index 8b2b5a92bb9..00000000000
--- a/chromium/content/browser/background_sync/background_sync_registration_handle.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_REGISTRATION_HANDLE_H_
-#define CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_REGISTRATION_HANDLE_H_
-
-#include <stdint.h>
-
-#include "base/callback.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "content/browser/background_sync/background_sync_registration.h"
-#include "content/browser/background_sync/background_sync_status.h"
-#include "content/common/background_sync_service.mojom.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-class BackgroundSyncManager;
-
-// Handle to BackgroundSyncRegistration that is exposed to clients. Each
-// BackgroundSyncRegistrationHandle is given a unique handle id (by the
-// BackgroundSyncManager) which is released at destruction.
-// BackgroundSyncRegistrationHandle objects must not be used (but may be
-// destroyed) after the BackgroundSyncManager has been deleted.
-class CONTENT_EXPORT BackgroundSyncRegistrationHandle {
- public:
- using HandleId = int64_t;
- using StatusCallback = base::Callback<void(BackgroundSyncStatus)>;
- using StatusAndStateCallback =
- base::Callback<void(BackgroundSyncStatus, BackgroundSyncState)>;
-
- ~BackgroundSyncRegistrationHandle();
-
- const BackgroundSyncRegistrationOptions* options() const {
- DCHECK(background_sync_manager_);
- return registration_->options();
- }
-
- BackgroundSyncState sync_state() const {
- DCHECK(background_sync_manager_);
- return registration_->sync_state();
- }
-
- // Unregisters the background sync registration. Calls |callback|
- // with BACKGROUND_SYNC_STATUS_OK if it succeeds.
- void Unregister(int64_t service_worker_id, const StatusCallback& callback);
-
- // Runs |callback| when the registration associated with |handle_id|
- // completes.The provided status is BACKGROUND_SYNC_STATUS_OK if the operation
- // succeeded. The provided state is BACKGROUND_SYNC_STATE_SUCCESS on success,
- // BACKGRUOND_SYNC_STATE_FAILED on final failure, and
- // BACKGROUND_SYNC_STATE_UNREGISTERED if the registration was unregistered
- // before it could complete. NotifyWhenFinished should only be called for
- // SYNC_ONE_SHOT registrations.
- void NotifyWhenFinished(const StatusAndStateCallback& callback);
-
- // Returns true if the handle is backed by a BackgroundSyncRegistration in the
- // BackgroundSyncManager.
- bool IsValid() const;
-
- HandleId handle_id() const { return handle_id_; }
-
- private:
- friend class BackgroundSyncManager;
-
- BackgroundSyncRegistrationHandle(
- base::WeakPtr<BackgroundSyncManager> background_sync_manager,
- HandleId handle_id);
-
- BackgroundSyncRegistration* registration() {
- DCHECK(background_sync_manager_);
- return registration_;
- }
-
- // The BackgroundSyncManager is expected to remain alive for all operations
- // except for possibly at destruction.
- base::WeakPtr<BackgroundSyncManager> background_sync_manager_;
-
- // Each BackgroundSyncRegistrationHandle is assigned a unique handle id.
- // The BackgroundSyncManager maps the id to an internal pointer.
- HandleId handle_id_;
-
- // This is owned by background_sync_manager_ and is valid until handle_id_ is
- // released in the destructor or background_sync_manager_ has been destroyed.
- BackgroundSyncRegistration* registration_;
-
- DISALLOW_COPY_AND_ASSIGN(BackgroundSyncRegistrationHandle);
-};
-
-} // namespace
-
-#endif // CONTENT_BROWSER_BACKGROUND_SYNC_BACKGROUND_SYNC_REGISTRATION_HANDLE_H_
diff --git a/chromium/content/browser/background_sync/background_sync_registration_options.cc b/chromium/content/browser/background_sync/background_sync_registration_options.cc
index 74b8bac8ef7..7b8e1e7e7bc 100644
--- a/chromium/content/browser/background_sync/background_sync_registration_options.cc
+++ b/chromium/content/browser/background_sync/background_sync_registration_options.cc
@@ -8,9 +8,7 @@ namespace content {
bool BackgroundSyncRegistrationOptions::Equals(
const BackgroundSyncRegistrationOptions& other) const {
- return tag == other.tag && min_period == other.min_period &&
- network_state == other.network_state &&
- power_state == other.power_state && periodicity == other.periodicity;
+ return tag == other.tag && network_state == other.network_state;
}
} // namespace content
diff --git a/chromium/content/browser/background_sync/background_sync_registration_options.h b/chromium/content/browser/background_sync/background_sync_registration_options.h
index 0429f2a90cc..5c81e308846 100644
--- a/chromium/content/browser/background_sync/background_sync_registration_options.h
+++ b/chromium/content/browser/background_sync/background_sync_registration_options.h
@@ -19,10 +19,7 @@ struct CONTENT_EXPORT BackgroundSyncRegistrationOptions {
bool Equals(const BackgroundSyncRegistrationOptions& other) const;
std::string tag;
- int64_t min_period = 0;
SyncNetworkState network_state = NETWORK_STATE_ONLINE;
- SyncPowerState power_state = POWER_STATE_AVOID_DRAINING;
- SyncPeriodicity periodicity = SYNC_ONE_SHOT;
};
} // namespace content
diff --git a/chromium/content/browser/background_sync/background_sync_service_impl.cc b/chromium/content/browser/background_sync/background_sync_service_impl.cc
index ffab6abc995..a5b51bd2edf 100644
--- a/chromium/content/browser/background_sync/background_sync_service_impl.cc
+++ b/chromium/content/browser/background_sync/background_sync_service_impl.cc
@@ -6,7 +6,6 @@
#include <utility>
-#include "background_sync_registration_handle.h"
#include "base/memory/weak_ptr.h"
#include "base/stl_util.h"
#include "content/browser/background_sync/background_sync_context_impl.h"
@@ -20,28 +19,20 @@ namespace {
// specializations.
BackgroundSyncRegistrationOptions ToBackgroundSyncRegistrationOptions(
- const SyncRegistrationPtr& in) {
+ const mojom::SyncRegistrationPtr& in) {
BackgroundSyncRegistrationOptions out;
out.tag = in->tag;
- out.min_period = in->min_period_ms;
- out.power_state = static_cast<SyncPowerState>(in->power_state);
out.network_state = static_cast<SyncNetworkState>(in->network_state);
- out.periodicity = static_cast<SyncPeriodicity>(in->periodicity);
return out;
}
-SyncRegistrationPtr ToMojoRegistration(
- const BackgroundSyncRegistrationHandle& in) {
- SyncRegistrationPtr out(content::SyncRegistration::New());
- out->handle_id = in.handle_id();
+mojom::SyncRegistrationPtr ToMojoRegistration(
+ const BackgroundSyncRegistration& in) {
+ mojom::SyncRegistrationPtr out(content::mojom::SyncRegistration::New());
+ out->id = in.id();
out->tag = in.options()->tag;
- out->min_period_ms = in.options()->min_period;
- out->periodicity = static_cast<content::BackgroundSyncPeriodicity>(
- in.options()->periodicity);
- out->power_state =
- static_cast<content::BackgroundSyncPowerState>(in.options()->power_state);
- out->network_state = static_cast<content::BackgroundSyncNetworkState>(
+ out->network_state = static_cast<content::mojom::BackgroundSyncNetworkState>(
in.options()->network_state);
return out;
}
@@ -54,42 +45,30 @@ SyncRegistrationPtr ToMojoRegistration(
"mojo and manager enums must match")
// TODO(iclelland): Move these tests somewhere else
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_ERROR_NONE,
+COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::NONE,
BACKGROUND_SYNC_STATUS_OK);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_ERROR_STORAGE,
+COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::STORAGE,
BACKGROUND_SYNC_STATUS_STORAGE_ERROR);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_ERROR_NOT_FOUND,
+COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::NOT_FOUND,
BACKGROUND_SYNC_STATUS_NOT_FOUND);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_ERROR_NO_SERVICE_WORKER,
+COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::NO_SERVICE_WORKER,
BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_ERROR_NOT_ALLOWED,
- BACKGROUND_SYNC_STATUS_NOT_ALLOWED);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_ERROR_MAX,
+COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::NOT_ALLOWED,
BACKGROUND_SYNC_STATUS_NOT_ALLOWED);
+COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::PERMISSION_DENIED,
+ BACKGROUND_SYNC_STATUS_PERMISSION_DENIED);
+COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncError::MAX,
+ BACKGROUND_SYNC_STATUS_PERMISSION_DENIED);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_NETWORK_STATE_ANY,
+COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncNetworkState::ANY,
SyncNetworkState::NETWORK_STATE_ANY);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_NETWORK_STATE_AVOID_CELLULAR,
+COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncNetworkState::AVOID_CELLULAR,
SyncNetworkState::NETWORK_STATE_AVOID_CELLULAR);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_NETWORK_STATE_ONLINE,
+COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncNetworkState::ONLINE,
SyncNetworkState::NETWORK_STATE_ONLINE);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_NETWORK_STATE_MAX,
+COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncNetworkState::MAX,
SyncNetworkState::NETWORK_STATE_ONLINE);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_POWER_STATE_AUTO,
- SyncPowerState::POWER_STATE_AUTO);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_POWER_STATE_AVOID_DRAINING,
- SyncPowerState::POWER_STATE_AVOID_DRAINING);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_POWER_STATE_MAX,
- SyncPowerState::POWER_STATE_AVOID_DRAINING);
-
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_PERIODICITY_PERIODIC,
- SyncPeriodicity::SYNC_PERIODIC);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_PERIODICITY_ONE_SHOT,
- SyncPeriodicity::SYNC_ONE_SHOT);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_PERIODICITY_MAX,
- SyncPeriodicity::SYNC_ONE_SHOT);
-
BackgroundSyncServiceImpl::~BackgroundSyncServiceImpl() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(background_sync_context_->background_sync_manager());
@@ -97,7 +76,7 @@ BackgroundSyncServiceImpl::~BackgroundSyncServiceImpl() {
BackgroundSyncServiceImpl::BackgroundSyncServiceImpl(
BackgroundSyncContextImpl* background_sync_context,
- mojo::InterfaceRequest<BackgroundSyncService> request)
+ mojo::InterfaceRequest<mojom::BackgroundSyncService> request)
: background_sync_context_(background_sync_context),
binding_(this, std::move(request)),
weak_ptr_factory_(this) {
@@ -114,60 +93,25 @@ void BackgroundSyncServiceImpl::OnConnectionError() {
// |this| is now deleted.
}
-void BackgroundSyncServiceImpl::Register(content::SyncRegistrationPtr options,
- int64_t sw_registration_id,
- bool requested_from_service_worker,
- const RegisterCallback& callback) {
+void BackgroundSyncServiceImpl::Register(
+ content::mojom::SyncRegistrationPtr options,
+ int64_t sw_registration_id,
+ const RegisterCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BackgroundSyncRegistrationOptions mgr_options =
+ BackgroundSyncRegistrationOptions manager_options =
ToBackgroundSyncRegistrationOptions(options);
BackgroundSyncManager* background_sync_manager =
background_sync_context_->background_sync_manager();
DCHECK(background_sync_manager);
background_sync_manager->Register(
- sw_registration_id, mgr_options, requested_from_service_worker,
- base::Bind(&BackgroundSyncServiceImpl::OnRegisterResult,
- weak_ptr_factory_.GetWeakPtr(), callback));
-}
-
-void BackgroundSyncServiceImpl::Unregister(
- BackgroundSyncRegistrationHandle::HandleId handle_id,
- int64_t sw_registration_id,
- const UnregisterCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- BackgroundSyncRegistrationHandle* registration =
- active_handles_.Lookup(handle_id);
- if (!registration) {
- callback.Run(BACKGROUND_SYNC_ERROR_NOT_ALLOWED);
- return;
- }
-
- registration->Unregister(
- sw_registration_id,
- base::Bind(&BackgroundSyncServiceImpl::OnUnregisterResult,
- weak_ptr_factory_.GetWeakPtr(), callback));
-}
-
-void BackgroundSyncServiceImpl::GetRegistration(
- BackgroundSyncPeriodicity periodicity,
- const mojo::String& tag,
- int64_t sw_registration_id,
- const GetRegistrationCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BackgroundSyncManager* background_sync_manager =
- background_sync_context_->background_sync_manager();
- DCHECK(background_sync_manager);
- background_sync_manager->GetRegistration(
- sw_registration_id, tag.get(), static_cast<SyncPeriodicity>(periodicity),
+ sw_registration_id, manager_options,
base::Bind(&BackgroundSyncServiceImpl::OnRegisterResult,
weak_ptr_factory_.GetWeakPtr(), callback));
}
void BackgroundSyncServiceImpl::GetRegistrations(
- BackgroundSyncPeriodicity periodicity,
int64_t sw_registration_id,
const GetRegistrationsCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -175,129 +119,43 @@ void BackgroundSyncServiceImpl::GetRegistrations(
background_sync_context_->background_sync_manager();
DCHECK(background_sync_manager);
background_sync_manager->GetRegistrations(
- sw_registration_id, static_cast<SyncPeriodicity>(periodicity),
+ sw_registration_id,
base::Bind(&BackgroundSyncServiceImpl::OnGetRegistrationsResult,
weak_ptr_factory_.GetWeakPtr(), callback));
}
-void BackgroundSyncServiceImpl::GetPermissionStatus(
- BackgroundSyncPeriodicity periodicity,
- int64_t sw_registration_id,
- const GetPermissionStatusCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // TODO(iclelland): Implement a real policy. This is a stub implementation.
- // OneShot: crbug.com/482091
- // Periodic: crbug.com/482093
- callback.Run(BACKGROUND_SYNC_ERROR_NONE, PERMISSION_STATUS_GRANTED);
-}
-
-void BackgroundSyncServiceImpl::DuplicateRegistrationHandle(
- BackgroundSyncRegistrationHandle::HandleId handle_id,
- const DuplicateRegistrationHandleCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BackgroundSyncManager* background_sync_manager =
- background_sync_context_->background_sync_manager();
- DCHECK(background_sync_manager);
-
- scoped_ptr<BackgroundSyncRegistrationHandle> registration_handle =
- background_sync_manager->DuplicateRegistrationHandle(handle_id);
-
- BackgroundSyncRegistrationHandle* handle_ptr = registration_handle.get();
-
- if (!registration_handle) {
- callback.Run(BACKGROUND_SYNC_ERROR_NOT_FOUND,
- SyncRegistrationPtr(content::SyncRegistration::New()));
- return;
- }
-
- active_handles_.AddWithID(registration_handle.release(),
- handle_ptr->handle_id());
- SyncRegistrationPtr mojoResult = ToMojoRegistration(*handle_ptr);
- callback.Run(BACKGROUND_SYNC_ERROR_NONE, std::move(mojoResult));
-}
-
-void BackgroundSyncServiceImpl::ReleaseRegistration(
- BackgroundSyncRegistrationHandle::HandleId handle_id) {
- if (!active_handles_.Lookup(handle_id)) {
- // TODO(jkarlin): Abort client.
- LOG(WARNING) << "Client attempted to release non-existing registration";
- return;
- }
-
- active_handles_.Remove(handle_id);
-}
-
-void BackgroundSyncServiceImpl::NotifyWhenFinished(
- BackgroundSyncRegistrationHandle::HandleId handle_id,
- const NotifyWhenFinishedCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BackgroundSyncRegistrationHandle* registration =
- active_handles_.Lookup(handle_id);
- if (!registration) {
- callback.Run(BACKGROUND_SYNC_ERROR_NOT_ALLOWED,
- BACKGROUND_SYNC_STATE_FAILED);
- return;
- }
-
- registration->NotifyWhenFinished(
- base::Bind(&BackgroundSyncServiceImpl::OnNotifyWhenFinishedResult,
- weak_ptr_factory_.GetWeakPtr(), callback));
-}
-
void BackgroundSyncServiceImpl::OnRegisterResult(
const RegisterCallback& callback,
BackgroundSyncStatus status,
- scoped_ptr<BackgroundSyncRegistrationHandle> result) {
+ scoped_ptr<BackgroundSyncRegistration> result) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- BackgroundSyncRegistrationHandle* result_ptr = result.get();
if (status != BACKGROUND_SYNC_STATUS_OK) {
- callback.Run(static_cast<content::BackgroundSyncError>(status),
- SyncRegistrationPtr(content::SyncRegistration::New()));
+ callback.Run(
+ static_cast<content::mojom::BackgroundSyncError>(status),
+ mojom::SyncRegistrationPtr(content::mojom::SyncRegistration::New()));
return;
}
DCHECK(result);
- active_handles_.AddWithID(result.release(), result_ptr->handle_id());
- SyncRegistrationPtr mojoResult = ToMojoRegistration(*result_ptr);
- callback.Run(static_cast<content::BackgroundSyncError>(status),
+ mojom::SyncRegistrationPtr mojoResult = ToMojoRegistration(*result);
+ callback.Run(static_cast<content::mojom::BackgroundSyncError>(status),
std::move(mojoResult));
}
-void BackgroundSyncServiceImpl::OnUnregisterResult(
- const UnregisterCallback& callback,
- BackgroundSyncStatus status) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- callback.Run(static_cast<content::BackgroundSyncError>(status));
-}
-
void BackgroundSyncServiceImpl::OnGetRegistrationsResult(
const GetRegistrationsCallback& callback,
BackgroundSyncStatus status,
- scoped_ptr<ScopedVector<BackgroundSyncRegistrationHandle>>
- result_registrations) {
+ scoped_ptr<ScopedVector<BackgroundSyncRegistration>> result_registrations) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(result_registrations);
- mojo::Array<content::SyncRegistrationPtr> mojo_registrations(0);
- for (BackgroundSyncRegistrationHandle* registration : *result_registrations) {
- active_handles_.AddWithID(registration, registration->handle_id());
+ mojo::Array<content::mojom::SyncRegistrationPtr> mojo_registrations;
+ for (const BackgroundSyncRegistration* registration : *result_registrations)
mojo_registrations.push_back(ToMojoRegistration(*registration));
- }
- result_registrations->weak_clear();
-
- callback.Run(static_cast<content::BackgroundSyncError>(status),
+ callback.Run(static_cast<content::mojom::BackgroundSyncError>(status),
std::move(mojo_registrations));
}
-void BackgroundSyncServiceImpl::OnNotifyWhenFinishedResult(
- const NotifyWhenFinishedCallback& callback,
- BackgroundSyncStatus status,
- BackgroundSyncState sync_state) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- callback.Run(static_cast<content::BackgroundSyncError>(status), sync_state);
-}
-
} // namespace content
diff --git a/chromium/content/browser/background_sync/background_sync_service_impl.h b/chromium/content/browser/background_sync/background_sync_service_impl.h
index a5b6d184e06..1851b90579a 100644
--- a/chromium/content/browser/background_sync/background_sync_service_impl.h
+++ b/chromium/content/browser/background_sync/background_sync_service_impl.h
@@ -20,56 +20,31 @@ namespace content {
class BackgroundSyncContextImpl;
class CONTENT_EXPORT BackgroundSyncServiceImpl
- : public NON_EXPORTED_BASE(BackgroundSyncService) {
+ : public NON_EXPORTED_BASE(mojom::BackgroundSyncService) {
public:
BackgroundSyncServiceImpl(
BackgroundSyncContextImpl* background_sync_context,
- mojo::InterfaceRequest<BackgroundSyncService> request);
+ mojo::InterfaceRequest<mojom::BackgroundSyncService> request);
~BackgroundSyncServiceImpl() override;
private:
friend class BackgroundSyncServiceImplTest;
- // BackgroundSyncService methods:
- void Register(content::SyncRegistrationPtr options,
+ // mojom::BackgroundSyncService methods:
+ void Register(content::mojom::SyncRegistrationPtr options,
int64_t sw_registration_id,
- bool requested_from_service_worker,
const RegisterCallback& callback) override;
- void Unregister(BackgroundSyncRegistrationHandle::HandleId handle_id,
- int64_t sw_registration_id,
- const UnregisterCallback& callback) override;
- void GetRegistration(BackgroundSyncPeriodicity periodicity,
- const mojo::String& tag,
- int64_t sw_registration_id,
- const GetRegistrationCallback& callback) override;
- void GetRegistrations(BackgroundSyncPeriodicity periodicity,
- int64_t sw_registration_id,
+ void GetRegistrations(int64_t sw_registration_id,
const GetRegistrationsCallback& callback) override;
- void GetPermissionStatus(
- BackgroundSyncPeriodicity periodicity,
- int64_t sw_registration_id,
- const GetPermissionStatusCallback& callback) override;
- void DuplicateRegistrationHandle(
- BackgroundSyncRegistrationHandle::HandleId handle_id,
- const DuplicateRegistrationHandleCallback& callback) override;
- void ReleaseRegistration(
- BackgroundSyncRegistrationHandle::HandleId handle_id) override;
- void NotifyWhenFinished(BackgroundSyncRegistrationHandle::HandleId handle_id,
- const NotifyWhenFinishedCallback& callback) override;
void OnRegisterResult(const RegisterCallback& callback,
BackgroundSyncStatus status,
- scoped_ptr<BackgroundSyncRegistrationHandle> result);
- void OnUnregisterResult(const UnregisterCallback& callback,
- BackgroundSyncStatus status);
+ scoped_ptr<BackgroundSyncRegistration> result);
void OnGetRegistrationsResult(
const GetRegistrationsCallback& callback,
BackgroundSyncStatus status,
- scoped_ptr<ScopedVector<BackgroundSyncRegistrationHandle>> result);
- void OnNotifyWhenFinishedResult(const NotifyWhenFinishedCallback& callback,
- BackgroundSyncStatus status,
- BackgroundSyncState sync_state);
+ scoped_ptr<ScopedVector<BackgroundSyncRegistration>> result);
// Called when an error is detected on binding_.
void OnConnectionError();
@@ -77,12 +52,7 @@ class CONTENT_EXPORT BackgroundSyncServiceImpl
// background_sync_context_ owns this.
BackgroundSyncContextImpl* background_sync_context_;
- mojo::Binding<BackgroundSyncService> binding_;
-
- // The registrations that the client might reference.
- IDMap<BackgroundSyncRegistrationHandle,
- IDMapOwnPointer,
- BackgroundSyncRegistrationHandle::HandleId> active_handles_;
+ mojo::Binding<mojom::BackgroundSyncService> binding_;
base::WeakPtrFactory<BackgroundSyncServiceImpl> weak_ptr_factory_;
diff --git a/chromium/content/browser/background_sync/background_sync_service_impl_unittest.cc b/chromium/content/browser/background_sync/background_sync_service_impl_unittest.cc
index a9f8307c04a..8f413508481 100644
--- a/chromium/content/browser/background_sync/background_sync_service_impl_unittest.cc
+++ b/chromium/content/browser/background_sync/background_sync_service_impl_unittest.cc
@@ -10,8 +10,6 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/memory/scoped_ptr.h"
-#include "base/power_monitor/power_monitor.h"
-#include "base/power_monitor/power_monitor_source.h"
#include "base/run_loop.h"
#include "content/browser/background_sync/background_sync_context_impl.h"
#include "content/browser/background_sync/background_sync_network_observer.h"
@@ -19,9 +17,12 @@
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/storage_partition_impl.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/permission_type.h"
#include "content/public/test/background_sync_test_util.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/test/mock_permission_manager.h"
+#include "content/test/test_background_sync_context_impl.h"
#include "mojo/public/cpp/bindings/interface_ptr.h"
#include "net/base/network_change_notifier.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -30,6 +31,8 @@ namespace content {
namespace {
+using ::testing::_;
+
const char kServiceWorkerPattern[] = "https://example.com/a";
const char kServiceWorkerScript[] = "https://example.com/a/script.js";
@@ -54,51 +57,29 @@ void FindServiceWorkerRegistrationCallback(
// Callbacks from BackgroundSyncServiceImpl methods
-void ErrorAndRegistrationCallback(bool* called,
- BackgroundSyncError* out_error,
- SyncRegistrationPtr* out_registration,
- BackgroundSyncError error,
- const SyncRegistrationPtr& registration) {
+void ErrorAndRegistrationCallback(
+ bool* called,
+ mojom::BackgroundSyncError* out_error,
+ mojom::SyncRegistrationPtr* out_registration,
+ mojom::BackgroundSyncError error,
+ const mojom::SyncRegistrationPtr& registration) {
*called = true;
*out_error = error;
*out_registration = registration.Clone();
}
-void ErrorAndStateCallback(bool* called,
- BackgroundSyncError* out_error,
- BackgroundSyncState* out_state,
- BackgroundSyncError error,
- BackgroundSyncState state) {
- *called = true;
- *out_error = error;
- *out_state = state;
-}
-
-void ErrorCallback(bool* called,
- BackgroundSyncError* out_error,
- BackgroundSyncError error) {
- *called = true;
- *out_error = error;
-}
-
void ErrorAndRegistrationListCallback(
bool* called,
- BackgroundSyncError* out_error,
+ mojom::BackgroundSyncError* out_error,
unsigned long* out_array_size,
- BackgroundSyncError error,
- mojo::Array<content::SyncRegistrationPtr> registrations) {
+ mojom::BackgroundSyncError error,
+ mojo::Array<content::mojom::SyncRegistrationPtr> registrations) {
*called = true;
*out_error = error;
- if (error == BackgroundSyncError::BACKGROUND_SYNC_ERROR_NONE)
+ if (error == mojom::BackgroundSyncError::NONE)
*out_array_size = registrations.size();
}
-class MockPowerMonitorSource : public base::PowerMonitorSource {
- private:
- // PowerMonitorSource overrides.
- bool IsOnBatteryPowerImpl() final { return false; }
-};
-
} // namespace
class BackgroundSyncServiceImplTest : public testing::Test {
@@ -107,7 +88,7 @@ class BackgroundSyncServiceImplTest : public testing::Test {
: thread_bundle_(
new TestBrowserThreadBundle(TestBrowserThreadBundle::IO_MAINLOOP)),
network_change_notifier_(net::NetworkChangeNotifier::CreateMock()) {
- default_sync_registration_ = SyncRegistration::New();
+ default_sync_registration_ = mojom::SyncRegistration::New();
}
void SetUp() override {
@@ -137,6 +118,14 @@ class BackgroundSyncServiceImplTest : public testing::Test {
void CreateTestHelper() {
embedded_worker_helper_.reset(
new EmbeddedWorkerTestHelper(base::FilePath()));
+ scoped_ptr<MockPermissionManager> mock_permission_manager(
+ new testing::NiceMock<MockPermissionManager>());
+ ON_CALL(*mock_permission_manager,
+ GetPermissionStatus(PermissionType::BACKGROUND_SYNC, _, _))
+ .WillByDefault(
+ testing::Return(blink::mojom::PermissionStatus::GRANTED));
+ embedded_worker_helper_->browser_context()->SetPermissionManager(
+ std::move(mock_permission_manager));
}
void CreateStoragePartition() {
@@ -145,16 +134,15 @@ class BackgroundSyncServiceImplTest : public testing::Test {
storage_partition_impl_.reset(new StoragePartitionImpl(
embedded_worker_helper_->browser_context(), base::FilePath(), nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr));
+ nullptr, nullptr, nullptr, nullptr, nullptr));
embedded_worker_helper_->context_wrapper()->set_storage_partition(
storage_partition_impl_.get());
}
void CreateBackgroundSyncContext() {
- power_monitor_.reset(
- new base::PowerMonitor(make_scoped_ptr(new MockPowerMonitorSource())));
-
- background_sync_context_ = new BackgroundSyncContextImpl();
+ // Registering for background sync includes a check for having a same-origin
+ // main frame. Use a test context that allows control over that check.
+ background_sync_context_ = new TestBackgroundSyncContextImpl();
background_sync_context_->Init(embedded_worker_helper_->context_wrapper());
// Tests do not expect the sync event to fire immediately after
@@ -190,10 +178,10 @@ class BackgroundSyncServiceImplTest : public testing::Test {
void CreateBackgroundSyncServiceImpl() {
// Create a dummy mojo channel so that the BackgroundSyncServiceImpl can be
- // instantiated
- mojo::InterfaceRequest<BackgroundSyncService> service_request =
+ // instantiated.
+ mojo::InterfaceRequest<mojom::BackgroundSyncService> service_request =
mojo::GetProxy(&service_ptr_);
- // Create a new BackgroundSyncServiceImpl bound to the dummy channel
+ // Create a new BackgroundSyncServiceImpl bound to the dummy channel.
background_sync_context_->CreateService(std::move(service_request));
base::RunLoop().RunUntilIdle();
@@ -202,44 +190,16 @@ class BackgroundSyncServiceImplTest : public testing::Test {
}
// Helpers for testing BackgroundSyncServiceImpl methods
- void RegisterOneShot(
- SyncRegistrationPtr sync,
- const BackgroundSyncService::RegisterCallback& callback) {
- service_impl_->Register(std::move(sync), sw_registration_id_,
- false /* requested_from_service_worker */,
- callback);
- base::RunLoop().RunUntilIdle();
- }
-
- void UnregisterOneShot(
- int32_t handle_id,
- const BackgroundSyncService::UnregisterCallback& callback) {
- service_impl_->Unregister(
- handle_id, sw_registration_id_, callback);
- base::RunLoop().RunUntilIdle();
- }
-
- void GetRegistrationOneShot(
- const mojo::String& tag,
- const BackgroundSyncService::RegisterCallback& callback) {
- service_impl_->GetRegistration(
- BackgroundSyncPeriodicity::BACKGROUND_SYNC_PERIODICITY_ONE_SHOT, tag,
- sw_registration_id_, callback);
- base::RunLoop().RunUntilIdle();
- }
-
- void GetRegistrationsOneShot(
- const BackgroundSyncService::GetRegistrationsCallback& callback) {
- service_impl_->GetRegistrations(
- BackgroundSyncPeriodicity::BACKGROUND_SYNC_PERIODICITY_ONE_SHOT,
- sw_registration_id_, callback);
+ void Register(
+ mojom::SyncRegistrationPtr sync,
+ const mojom::BackgroundSyncService::RegisterCallback& callback) {
+ service_impl_->Register(std::move(sync), sw_registration_id_, callback);
base::RunLoop().RunUntilIdle();
}
- void NotifyWhenDone(
- int32_t handle_id,
- const BackgroundSyncService::NotifyWhenFinishedCallback& callback) {
- service_impl_->NotifyWhenFinished(handle_id, callback);
+ void GetRegistrations(
+ const mojom::BackgroundSyncService::GetRegistrationsCallback& callback) {
+ service_impl_->GetRegistrations(sw_registration_id_, callback);
base::RunLoop().RunUntilIdle();
}
@@ -247,154 +207,57 @@ class BackgroundSyncServiceImplTest : public testing::Test {
scoped_ptr<net::NetworkChangeNotifier> network_change_notifier_;
scoped_ptr<EmbeddedWorkerTestHelper> embedded_worker_helper_;
scoped_ptr<StoragePartitionImpl> storage_partition_impl_;
- scoped_ptr<base::PowerMonitor> power_monitor_;
scoped_refptr<BackgroundSyncContextImpl> background_sync_context_;
int64_t sw_registration_id_;
scoped_refptr<ServiceWorkerRegistration> sw_registration_;
- BackgroundSyncServicePtr service_ptr_;
+ mojom::BackgroundSyncServicePtr service_ptr_;
BackgroundSyncServiceImpl*
service_impl_; // Owned by background_sync_context_
- SyncRegistrationPtr default_sync_registration_;
+ mojom::SyncRegistrationPtr default_sync_registration_;
};
// Tests
TEST_F(BackgroundSyncServiceImplTest, Register) {
bool called = false;
- BackgroundSyncError error;
- SyncRegistrationPtr reg;
- RegisterOneShot(
- default_sync_registration_.Clone(),
- base::Bind(&ErrorAndRegistrationCallback, &called, &error, &reg));
+ mojom::BackgroundSyncError error;
+ mojom::SyncRegistrationPtr reg;
+ Register(default_sync_registration_.Clone(),
+ base::Bind(&ErrorAndRegistrationCallback, &called, &error, &reg));
EXPECT_TRUE(called);
- EXPECT_EQ(BackgroundSyncError::BACKGROUND_SYNC_ERROR_NONE, error);
+ EXPECT_EQ(mojom::BackgroundSyncError::NONE, error);
EXPECT_EQ("", reg->tag);
}
-TEST_F(BackgroundSyncServiceImplTest, Unregister) {
- bool unregister_called = false;
- BackgroundSyncError unregister_error;
- SyncRegistrationPtr reg;
- UnregisterOneShot(
- default_sync_registration_->handle_id,
- base::Bind(&ErrorCallback, &unregister_called, &unregister_error));
- EXPECT_TRUE(unregister_called);
- EXPECT_EQ(BackgroundSyncError::BACKGROUND_SYNC_ERROR_NOT_ALLOWED,
- unregister_error);
-}
-
-TEST_F(BackgroundSyncServiceImplTest, UnregisterWithRegisteredSync) {
- bool register_called = false;
- bool unregister_called = false;
- BackgroundSyncError register_error;
- BackgroundSyncError unregister_error;
- SyncRegistrationPtr reg;
- RegisterOneShot(default_sync_registration_.Clone(),
- base::Bind(&ErrorAndRegistrationCallback, &register_called,
- &register_error, &reg));
- EXPECT_TRUE(register_called);
- EXPECT_EQ(BackgroundSyncError::BACKGROUND_SYNC_ERROR_NONE, register_error);
- UnregisterOneShot(
- reg->handle_id,
- base::Bind(&ErrorCallback, &unregister_called, &unregister_error));
- EXPECT_TRUE(unregister_called);
- EXPECT_EQ(BackgroundSyncError::BACKGROUND_SYNC_ERROR_NONE, unregister_error);
-}
-
-TEST_F(BackgroundSyncServiceImplTest, GetRegistration) {
- bool called = false;
- BackgroundSyncError error;
- SyncRegistrationPtr reg;
- GetRegistrationOneShot(
- "", base::Bind(&ErrorAndRegistrationCallback, &called, &error, &reg));
- EXPECT_TRUE(called);
- EXPECT_EQ(BackgroundSyncError::BACKGROUND_SYNC_ERROR_NOT_FOUND, error);
-}
-
-TEST_F(BackgroundSyncServiceImplTest, GetRegistrationWithRegisteredSync) {
- bool register_called = false;
- bool getregistration_called = false;
- BackgroundSyncError register_error;
- BackgroundSyncError getregistration_error;
- SyncRegistrationPtr register_reg;
- SyncRegistrationPtr getregistration_reg;
- RegisterOneShot(default_sync_registration_.Clone(),
- base::Bind(&ErrorAndRegistrationCallback, &register_called,
- &register_error, &register_reg));
- EXPECT_TRUE(register_called);
- EXPECT_EQ(BackgroundSyncError::BACKGROUND_SYNC_ERROR_NONE, register_error);
- GetRegistrationOneShot(
- register_reg->tag,
- base::Bind(&ErrorAndRegistrationCallback, &getregistration_called,
- &getregistration_error, &getregistration_reg));
- EXPECT_TRUE(getregistration_called);
- EXPECT_EQ(BackgroundSyncError::BACKGROUND_SYNC_ERROR_NONE,
- getregistration_error);
-}
-
TEST_F(BackgroundSyncServiceImplTest, GetRegistrations) {
bool called = false;
- BackgroundSyncError error;
+ mojom::BackgroundSyncError error;
unsigned long array_size = 0UL;
- GetRegistrationsOneShot(base::Bind(&ErrorAndRegistrationListCallback, &called,
- &error, &array_size));
+ GetRegistrations(base::Bind(&ErrorAndRegistrationListCallback, &called,
+ &error, &array_size));
EXPECT_TRUE(called);
- EXPECT_EQ(BackgroundSyncError::BACKGROUND_SYNC_ERROR_NONE, error);
+ EXPECT_EQ(mojom::BackgroundSyncError::NONE, error);
EXPECT_EQ(0UL, array_size);
}
TEST_F(BackgroundSyncServiceImplTest, GetRegistrationsWithRegisteredSync) {
bool register_called = false;
bool getregistrations_called = false;
- BackgroundSyncError register_error;
- BackgroundSyncError getregistrations_error;
- SyncRegistrationPtr register_reg;
+ mojom::BackgroundSyncError register_error;
+ mojom::BackgroundSyncError getregistrations_error;
+ mojom::SyncRegistrationPtr register_reg;
unsigned long array_size = 0UL;
- RegisterOneShot(default_sync_registration_.Clone(),
- base::Bind(&ErrorAndRegistrationCallback, &register_called,
- &register_error, &register_reg));
+ Register(default_sync_registration_.Clone(),
+ base::Bind(&ErrorAndRegistrationCallback, &register_called,
+ &register_error, &register_reg));
EXPECT_TRUE(register_called);
- EXPECT_EQ(BackgroundSyncError::BACKGROUND_SYNC_ERROR_NONE, register_error);
- GetRegistrationsOneShot(base::Bind(&ErrorAndRegistrationListCallback,
- &getregistrations_called,
- &getregistrations_error, &array_size));
+ EXPECT_EQ(mojom::BackgroundSyncError::NONE, register_error);
+ GetRegistrations(base::Bind(&ErrorAndRegistrationListCallback,
+ &getregistrations_called, &getregistrations_error,
+ &array_size));
EXPECT_TRUE(getregistrations_called);
- EXPECT_EQ(BackgroundSyncError::BACKGROUND_SYNC_ERROR_NONE,
- getregistrations_error);
+ EXPECT_EQ(mojom::BackgroundSyncError::NONE, getregistrations_error);
EXPECT_EQ(1UL, array_size);
}
-TEST_F(BackgroundSyncServiceImplTest, NotifyWhenFinished) {
- // Register a sync event.
- bool register_called = false;
- BackgroundSyncError register_error;
- SyncRegistrationPtr reg;
- RegisterOneShot(default_sync_registration_.Clone(),
- base::Bind(&ErrorAndRegistrationCallback, &register_called,
- &register_error, &reg));
- EXPECT_TRUE(register_called);
- EXPECT_EQ(BACKGROUND_SYNC_ERROR_NONE, register_error);
-
- // Unregister it.
- bool unregister_called = false;
- BackgroundSyncError unregister_error;
- UnregisterOneShot(
- reg->handle_id,
- base::Bind(&ErrorCallback, &unregister_called, &unregister_error));
- EXPECT_TRUE(unregister_called);
- EXPECT_EQ(BACKGROUND_SYNC_ERROR_NONE, unregister_error);
-
- // Call NotifyWhenDone and verify that it calls back with unregistered.
- bool notify_done_called = false;
- BackgroundSyncError notify_done_error = BACKGROUND_SYNC_ERROR_NONE;
- BackgroundSyncState notify_done_sync_state = BACKGROUND_SYNC_STATE_SUCCESS;
-
- NotifyWhenDone(reg->handle_id,
- base::Bind(&ErrorAndStateCallback, &notify_done_called,
- &notify_done_error, &notify_done_sync_state));
- EXPECT_TRUE(notify_done_called);
- EXPECT_EQ(BACKGROUND_SYNC_ERROR_NONE, notify_done_error);
- EXPECT_EQ(BACKGROUND_SYNC_STATE_UNREGISTERED, notify_done_sync_state);
-}
-
} // namespace content
diff --git a/chromium/content/browser/background_sync/background_sync_status.h b/chromium/content/browser/background_sync/background_sync_status.h
index 3faee998377..27a8805325c 100644
--- a/chromium/content/browser/background_sync/background_sync_status.h
+++ b/chromium/content/browser/background_sync/background_sync_status.h
@@ -16,7 +16,8 @@ enum BackgroundSyncStatus {
BACKGROUND_SYNC_STATUS_NOT_FOUND,
BACKGROUND_SYNC_STATUS_NO_SERVICE_WORKER,
BACKGROUND_SYNC_STATUS_NOT_ALLOWED,
- BACKGROUND_SYNC_STATUS_MAX = BACKGROUND_SYNC_STATUS_NOT_ALLOWED
+ BACKGROUND_SYNC_STATUS_PERMISSION_DENIED,
+ BACKGROUND_SYNC_STATUS_MAX = BACKGROUND_SYNC_STATUS_PERMISSION_DENIED
};
} // namespace content
diff --git a/chromium/content/browser/bad_message.h b/chromium/content/browser/bad_message.h
index 1a8c80abb4e..441b903e350 100644
--- a/chromium/content/browser/bad_message.h
+++ b/chromium/content/browser/bad_message.h
@@ -127,6 +127,19 @@ enum BadMessageReason {
DWNLD_INVALID_SAVABLE_RESOURCE_LINKS_RESPONSE = 103,
DWNLD_INVALID_SERIALIZE_AS_MHTML_RESPONSE = 104,
BDH_DEVICE_NOT_ALLOWED_FOR_ORIGIN = 105,
+ ACI_WRONG_STORAGE_PARTITION = 106,
+ RDHI_WRONG_STORAGE_PARTITION = 107,
+ RDH_INVALID_REQUEST_ID = 108,
+ BDH_SERVICE_NOT_ALLOWED_FOR_ORIGIN = 109,
+ WSH_SEND_BLOB_DURING_BLOB_SEND = 110,
+ WSH_SEND_FRAME_DURING_BLOB_SEND = 111,
+ RFH_UNEXPECTED_LOAD_START = 112,
+ NMF_INVALID_ARGUMENT = 113,
+ RFH_INVALID_ORIGIN_ON_COMMIT = 114,
+ BDH_UUID_REGISTERED = 115,
+ BDH_CONSTRUCTION_FAILED = 116,
+ BDH_INVALID_REFCOUNT_OPERATION = 117,
+ BDH_INVALID_URL_OPERATION = 118,
// Please add new elements here. The naming convention is abbreviated class
// name (e.g. RenderFrameHost becomes RFH) plus a unique description of the
diff --git a/chromium/content/browser/battery_status/battery_monitor_integration_browsertest.cc b/chromium/content/browser/battery_status/battery_monitor_integration_browsertest.cc
index 468126f3d39..1aee295891b 100644
--- a/chromium/content/browser/battery_status/battery_monitor_integration_browsertest.cc
+++ b/chromium/content/browser/battery_status/battery_monitor_integration_browsertest.cc
@@ -95,6 +95,13 @@ class TestContentBrowserClient : public ContentBrowserClient {
registry->AddService(base::Bind(&FakeBatteryMonitor::Create));
}
+ void AppendExtraCommandLineSwitches(base::CommandLine* command_line,
+ int child_process_id) override {
+ // Necessary for passing kIsolateSitesForTesting flag to the renderer.
+ ShellContentBrowserClient::Get()->AppendExtraCommandLineSwitches(
+ command_line, child_process_id);
+ }
+
#if defined(OS_ANDROID)
void GetAdditionalMappedFilesForChildProcess(
const base::CommandLine& command_line,
diff --git a/chromium/content/browser/blob_storage/blob_async_builder_host_unittest.cc b/chromium/content/browser/blob_storage/blob_async_builder_host_unittest.cc
index 934e0db887b..d40cc7cbc0c 100644
--- a/chromium/content/browser/blob_storage/blob_async_builder_host_unittest.cc
+++ b/chromium/content/browser/blob_storage/blob_async_builder_host_unittest.cc
@@ -11,14 +11,21 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/shared_memory.h"
+#include "base/run_loop.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "storage/browser/blob/blob_data_builder.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_storage_context.h"
#include "storage/common/blob_storage/blob_storage_constants.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace storage {
namespace {
const std::string kBlobUUID = "blobUUIDYAY";
-const std::string kFakeBlobUUID = "fakeBlob";
-const std::string kBlobType = "blobtypeYAY";
+const std::string kContentType = "content_type";
+const std::string kContentDisposition = "content_disposition";
+const std::string kCompletedBlobUUID = "completedBlob";
+const std::string kCompletedBlobData = "completedBlobData";
const size_t kTestBlobStorageIPCThresholdBytes = 5;
const size_t kTestBlobStorageMaxSharedMemoryBytes = 20;
@@ -52,87 +59,81 @@ void AddShortcutMemoryItem(size_t length, BlobDataBuilder* out) {
void AddBlobItem(std::vector<DataElement>* out) {
DataElement blob;
- blob.SetToBlob(kFakeBlobUUID);
+ blob.SetToBlob(kCompletedBlobUUID);
out->push_back(blob);
}
+} // namespace
class BlobAsyncBuilderHostTest : public testing::Test {
- protected:
+ public:
BlobAsyncBuilderHostTest()
- : matching_builder_(nullptr),
- done_called_(false),
- cancel_called_(false),
- cancel_code_(IPCBlobCreationCancelCode::UNKNOWN),
+ : cancel_code_(IPCBlobCreationCancelCode::UNKNOWN),
request_called_(false) {}
~BlobAsyncBuilderHostTest() override {}
void SetUp() override {
- matching_builder_ = nullptr;
- done_called_ = false;
- cancel_called_ = false;
cancel_code_ = IPCBlobCreationCancelCode::UNKNOWN;
request_called_ = false;
requests_.clear();
memory_handles_.clear();
- file_handles_.clear();
host_.SetMemoryConstantsForTesting(kTestBlobStorageIPCThresholdBytes,
kTestBlobStorageMaxSharedMemoryBytes,
kTestBlobStorageMaxFileSizeBytes);
- }
-
- void SetMatchingBuilder(BlobDataBuilder* builder) {
- matching_builder_ = builder;
- }
-
- void CancelCallback(IPCBlobCreationCancelCode code) {
- cancel_called_ = true;
- cancel_code_ = code;
- }
-
- void DoneCallback(const BlobDataBuilder& builder) {
- // This does a deep comparison, including internal data items.
- if (matching_builder_)
- EXPECT_EQ(*matching_builder_, builder);
- done_called_ = true;
+ BlobDataBuilder builder(kCompletedBlobUUID);
+ builder.AppendData(kCompletedBlobData);
+ completed_blob_handle_ = context_.AddFinishedBlob(builder);
+ completed_blob_uuid_set_ = {kCompletedBlobUUID};
}
void RequestMemoryCallback(
- const std::vector<storage::BlobItemBytesRequest>& requests,
- const std::vector<base::SharedMemoryHandle>& shared_memory_handles,
- const std::vector<uint64_t>& file_sizes) {
- this->requests_ = requests;
- memory_handles_ = shared_memory_handles;
- file_handles_ = file_sizes;
+ scoped_ptr<std::vector<storage::BlobItemBytesRequest>> requests,
+ scoped_ptr<std::vector<base::SharedMemoryHandle>> shared_memory_handles,
+ scoped_ptr<std::vector<base::File>> files) {
+ requests_ = std::move(*requests);
+ memory_handles_ = std::move(*shared_memory_handles);
request_called_ = true;
}
- bool BuildBlobAsync(const std::vector<DataElement>& descriptions,
- size_t memory_available) {
- done_called_ = false;
- cancel_called_ = false;
+ BlobTransportResult BuildBlobAsync(
+ const std::vector<DataElement>& descriptions,
+ const std::set<std::string>& referenced_blob_uuids,
+ size_t memory_available) {
request_called_ = false;
+ BlobTransportResult register_result =
+ host_.RegisterBlobUUID(kBlobUUID, kContentType, kContentDisposition,
+ referenced_blob_uuids, &context_);
+ if (register_result != BlobTransportResult::DONE) {
+ return register_result;
+ }
return host_.StartBuildingBlob(
- kBlobUUID, kBlobType, descriptions, memory_available,
+ kBlobUUID, descriptions, memory_available, &context_,
base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
- base::Unretained(this)),
- base::Bind(&BlobAsyncBuilderHostTest::DoneCallback,
- base::Unretained(this)),
- base::Bind(&BlobAsyncBuilderHostTest::CancelCallback,
base::Unretained(this)));
}
- BlobDataBuilder* matching_builder_;
+ void DecrementBlobRefCount(const std::string& uuid) {
+ context_.DecrementBlobRefCount(uuid);
+ }
+
+ bool IsBeingBuiltInContext(const std::string& uuid) {
+ return context_.IsBeingBuilt(uuid);
+ }
+
+ content::TestBrowserThreadBundle browser_thread_bundle_;
+ BlobStorageContext context_;
BlobAsyncBuilderHost host_;
- bool done_called_;
- bool cancel_called_;
IPCBlobCreationCancelCode cancel_code_;
bool request_called_;
std::vector<storage::BlobItemBytesRequest> requests_;
std::vector<base::SharedMemoryHandle> memory_handles_;
- std::vector<uint64_t> file_handles_;
+ std::set<std::string> completed_blob_uuid_set_;
+
+ scoped_ptr<BlobDataHandle> completed_blob_handle_;
};
+// The 'shortcut' method is when the data is included in the initial IPCs and
+// the browser uses that instead of requesting the memory.
TEST_F(BlobAsyncBuilderHostTest, TestShortcut) {
std::vector<DataElement> descriptions;
@@ -141,16 +142,37 @@ TEST_F(BlobAsyncBuilderHostTest, TestShortcut) {
AddShortcutMemoryItem(5000, &descriptions);
BlobDataBuilder expected(kBlobUUID);
- expected.set_content_type(kBlobType);
+ expected.set_content_type(kContentType);
+ expected.set_content_disposition(kContentDisposition);
AddShortcutMemoryItem(10, &expected);
- expected.AppendBlob(kFakeBlobUUID);
+ expected.AppendData(kCompletedBlobData);
AddShortcutMemoryItem(5000, &expected);
- SetMatchingBuilder(&expected);
- EXPECT_TRUE(BuildBlobAsync(descriptions, 5010));
+ EXPECT_EQ(BlobTransportResult::DONE,
+ BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
+
+ EXPECT_FALSE(request_called_);
+ EXPECT_EQ(0u, host_.blob_building_count());
+ scoped_ptr<BlobDataHandle> handle = context_.GetBlobDataFromUUID(kBlobUUID);
+ EXPECT_FALSE(handle->IsBeingBuilt());
+ EXPECT_FALSE(handle->IsBroken());
+ scoped_ptr<BlobDataSnapshot> data = handle->CreateSnapshot();
+ EXPECT_EQ(expected, *data);
+ data.reset();
+ handle.reset();
+ base::RunLoop().RunUntilIdle();
+};
+
+TEST_F(BlobAsyncBuilderHostTest, TestShortcutNoRoom) {
+ std::vector<DataElement> descriptions;
+
+ AddShortcutMemoryItem(10, &descriptions);
+ AddBlobItem(&descriptions);
+ AddShortcutMemoryItem(5000, &descriptions);
+
+ EXPECT_EQ(BlobTransportResult::CANCEL_MEMORY_FULL,
+ BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5000));
- EXPECT_TRUE(done_called_);
- EXPECT_FALSE(cancel_called_);
EXPECT_FALSE(request_called_);
EXPECT_EQ(0u, host_.blob_building_count());
};
@@ -160,11 +182,10 @@ TEST_F(BlobAsyncBuilderHostTest, TestSingleSharedMemRequest) {
const size_t kSize = kTestBlobStorageIPCThresholdBytes + 1;
AddMemoryItem(kSize, &descriptions);
- EXPECT_TRUE(
- BuildBlobAsync(descriptions, kTestBlobStorageIPCThresholdBytes + 1));
+ EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
+ BuildBlobAsync(descriptions, std::set<std::string>(),
+ kTestBlobStorageIPCThresholdBytes + 1));
- EXPECT_FALSE(done_called_);
- EXPECT_FALSE(cancel_called_);
EXPECT_TRUE(request_called_);
EXPECT_EQ(1u, host_.blob_building_count());
ASSERT_EQ(1u, requests_.size());
@@ -183,18 +204,17 @@ TEST_F(BlobAsyncBuilderHostTest, TestMultipleSharedMemRequests) {
AddMemoryItem(kSize, &descriptions);
BlobDataBuilder expected(kBlobUUID);
- expected.set_content_type(kBlobType);
+ expected.set_content_type(kContentType);
+ expected.set_content_disposition(kContentDisposition);
char data[kSize];
memset(data, kFirstBlockByte, kTestBlobStorageMaxSharedMemoryBytes);
expected.AppendData(data, kTestBlobStorageMaxSharedMemoryBytes);
expected.AppendData(&kSecondBlockByte, 1);
- SetMatchingBuilder(&expected);
- EXPECT_TRUE(
- BuildBlobAsync(descriptions, kTestBlobStorageMaxSharedMemoryBytes + 1));
+ EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
+ BuildBlobAsync(descriptions, std::set<std::string>(),
+ kTestBlobStorageMaxSharedMemoryBytes + 1));
- EXPECT_FALSE(done_called_);
- EXPECT_FALSE(cancel_called_);
EXPECT_TRUE(request_called_);
EXPECT_EQ(1u, host_.blob_building_count());
ASSERT_EQ(1u, requests_.size());
@@ -217,10 +237,9 @@ TEST_F(BlobAsyncBuilderHostTest, TestMultipleSharedMemRequests) {
BlobItemBytesResponse response(0);
std::vector<BlobItemBytesResponse> responses = {response};
- EXPECT_TRUE(host_.OnMemoryResponses(kBlobUUID, responses));
+ EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
+ host_.OnMemoryResponses(kBlobUUID, responses, &context_));
- EXPECT_FALSE(done_called_);
- EXPECT_FALSE(cancel_called_);
EXPECT_TRUE(request_called_);
EXPECT_EQ(1u, host_.blob_building_count());
ASSERT_EQ(1u, requests_.size());
@@ -234,11 +253,16 @@ TEST_F(BlobAsyncBuilderHostTest, TestMultipleSharedMemRequests) {
response.request_number = 1;
responses[0] = response;
- EXPECT_TRUE(host_.OnMemoryResponses(kBlobUUID, responses));
- EXPECT_TRUE(done_called_);
- EXPECT_FALSE(cancel_called_);
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.OnMemoryResponses(kBlobUUID, responses, &context_));
EXPECT_FALSE(request_called_);
EXPECT_EQ(0u, host_.blob_building_count());
+ scoped_ptr<BlobDataHandle> blob_handle =
+ context_.GetBlobDataFromUUID(kBlobUUID);
+ EXPECT_FALSE(blob_handle->IsBeingBuilt());
+ EXPECT_FALSE(blob_handle->IsBroken());
+ scoped_ptr<BlobDataSnapshot> blob_data = blob_handle->CreateSnapshot();
+ EXPECT_EQ(expected, *blob_data);
};
TEST_F(BlobAsyncBuilderHostTest, TestBasicIPCAndStopBuilding) {
@@ -249,18 +273,32 @@ TEST_F(BlobAsyncBuilderHostTest, TestBasicIPCAndStopBuilding) {
AddMemoryItem(2, &descriptions);
BlobDataBuilder expected(kBlobUUID);
- expected.set_content_type(kBlobType);
+ expected.set_content_type(kContentType);
+ expected.set_content_disposition(kContentDisposition);
AddShortcutMemoryItem(2, &expected);
- expected.AppendBlob(kFakeBlobUUID);
+ expected.AppendData(kCompletedBlobData);
AddShortcutMemoryItem(2, &expected);
- SetMatchingBuilder(&expected);
- EXPECT_TRUE(BuildBlobAsync(descriptions, 5010));
- host_.StopBuildingBlob(kBlobUUID);
- EXPECT_TRUE(BuildBlobAsync(descriptions, 5010));
+ EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
+ BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
+ host_.CancelBuildingBlob(kBlobUUID, IPCBlobCreationCancelCode::UNKNOWN,
+ &context_);
+
+ // Check that we're broken, and then remove the blob.
+ scoped_ptr<BlobDataHandle> blob_handle =
+ context_.GetBlobDataFromUUID(kBlobUUID);
+ EXPECT_FALSE(blob_handle->IsBeingBuilt());
+ EXPECT_TRUE(blob_handle->IsBroken());
+ blob_handle.reset();
+ DecrementBlobRefCount(kBlobUUID);
+ base::RunLoop().RunUntilIdle();
+ blob_handle = context_.GetBlobDataFromUUID(kBlobUUID);
+ EXPECT_FALSE(blob_handle.get());
+
+ // This should succeed because we've removed all references to the blob.
+ EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
+ BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
- EXPECT_FALSE(done_called_);
- EXPECT_FALSE(cancel_called_);
EXPECT_TRUE(request_called_);
EXPECT_EQ(1u, host_.blob_building_count());
request_called_ = false;
@@ -270,58 +308,308 @@ TEST_F(BlobAsyncBuilderHostTest, TestBasicIPCAndStopBuilding) {
BlobItemBytesResponse response2(1);
PopulateBytes(response2.allocate_mutable_data(2), 2);
std::vector<BlobItemBytesResponse> responses = {response1, response2};
- EXPECT_TRUE(host_.OnMemoryResponses(kBlobUUID, responses));
- EXPECT_TRUE(done_called_);
- EXPECT_FALSE(cancel_called_);
+
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.OnMemoryResponses(kBlobUUID, responses, &context_));
EXPECT_FALSE(request_called_);
EXPECT_EQ(0u, host_.blob_building_count());
+ blob_handle = context_.GetBlobDataFromUUID(kBlobUUID);
+ EXPECT_FALSE(blob_handle->IsBeingBuilt());
+ EXPECT_FALSE(blob_handle->IsBroken());
+ scoped_ptr<BlobDataSnapshot> blob_data = blob_handle->CreateSnapshot();
+ EXPECT_EQ(expected, *blob_data);
+};
+
+TEST_F(BlobAsyncBuilderHostTest, TestBreakingAllBuilding) {
+ const std::string& kBlob1 = "blob1";
+ const std::string& kBlob2 = "blob2";
+ const std::string& kBlob3 = "blob3";
+
+ // Register blobs.
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
+ std::set<std::string>(), &context_));
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
+ std::set<std::string>(), &context_));
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.RegisterBlobUUID(kBlob3, kContentType, kContentDisposition,
+ std::set<std::string>(), &context_));
+
+ // Start building one of them.
+ std::vector<DataElement> descriptions;
+ AddMemoryItem(2, &descriptions);
+ EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
+ host_.StartBuildingBlob(
+ kBlob1, descriptions, 2, &context_,
+ base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
+ base::Unretained(this))));
+ EXPECT_TRUE(request_called_);
+
+ scoped_ptr<BlobDataHandle> blob_handle1 =
+ context_.GetBlobDataFromUUID(kBlob1);
+ scoped_ptr<BlobDataHandle> blob_handle2 =
+ context_.GetBlobDataFromUUID(kBlob2);
+ scoped_ptr<BlobDataHandle> blob_handle3 =
+ context_.GetBlobDataFromUUID(kBlob2);
+ EXPECT_TRUE(blob_handle1->IsBeingBuilt() && blob_handle2->IsBeingBuilt() &&
+ blob_handle3->IsBeingBuilt());
+ EXPECT_FALSE(blob_handle1->IsBroken() || blob_handle2->IsBroken() ||
+ blob_handle3->IsBroken());
+
+ host_.CancelAll(&context_);
+
+ EXPECT_FALSE(blob_handle1->IsBeingBuilt() || blob_handle2->IsBeingBuilt() ||
+ blob_handle3->IsBeingBuilt());
+ EXPECT_TRUE(blob_handle1->IsBroken() && blob_handle2->IsBroken() &&
+ blob_handle3->IsBroken());
+ blob_handle1.reset();
+ blob_handle2.reset();
+ blob_handle3.reset();
+ base::RunLoop().RunUntilIdle();
};
TEST_F(BlobAsyncBuilderHostTest, TestBadIPCs) {
std::vector<DataElement> descriptions;
// Test reusing same blob uuid.
- SetMatchingBuilder(nullptr);
AddMemoryItem(10, &descriptions);
AddBlobItem(&descriptions);
AddMemoryItem(5000, &descriptions);
- EXPECT_TRUE(BuildBlobAsync(descriptions, 5010));
- EXPECT_FALSE(BuildBlobAsync(descriptions, 5010));
- EXPECT_FALSE(done_called_);
- EXPECT_FALSE(cancel_called_);
+ EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
+ BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
+ EXPECT_EQ(BlobTransportResult::BAD_IPC,
+ BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
EXPECT_FALSE(request_called_);
- host_.StopBuildingBlob(kBlobUUID);
+ host_.CancelBuildingBlob(kBlobUUID, IPCBlobCreationCancelCode::UNKNOWN,
+ &context_);
+ base::RunLoop().RunUntilIdle();
+ DecrementBlobRefCount(kBlobUUID);
+ EXPECT_FALSE(context_.GetBlobDataFromUUID(kBlobUUID).get());
- // Test we're _not_ an error if we get a bad uuid for responses.
+ // Test we're an error if we get a bad uuid for responses.
BlobItemBytesResponse response(0);
std::vector<BlobItemBytesResponse> responses = {response};
- EXPECT_TRUE(host_.OnMemoryResponses(kBlobUUID, responses));
+ EXPECT_EQ(BlobTransportResult::BAD_IPC,
+ host_.OnMemoryResponses(kBlobUUID, responses, &context_));
// Test empty responses.
responses.clear();
- EXPECT_FALSE(host_.OnMemoryResponses(kBlobUUID, responses));
+ EXPECT_EQ(BlobTransportResult::BAD_IPC,
+ host_.OnMemoryResponses(kBlobUUID, responses, &context_));
// Test response problems below here.
descriptions.clear();
AddMemoryItem(2, &descriptions);
AddBlobItem(&descriptions);
AddMemoryItem(2, &descriptions);
- EXPECT_TRUE(BuildBlobAsync(descriptions, 5010));
+ EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
+ BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
// Invalid request number.
BlobItemBytesResponse response1(3);
PopulateBytes(response1.allocate_mutable_data(2), 2);
responses = {response1};
- EXPECT_FALSE(host_.OnMemoryResponses(kBlobUUID, responses));
+ EXPECT_EQ(BlobTransportResult::BAD_IPC,
+ host_.OnMemoryResponses(kBlobUUID, responses, &context_));
+ EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlobUUID)->IsBroken());
+ DecrementBlobRefCount(kBlobUUID);
+ base::RunLoop().RunUntilIdle();
// Duplicate request number responses.
- EXPECT_TRUE(BuildBlobAsync(descriptions, 5010));
+ EXPECT_EQ(BlobTransportResult::PENDING_RESPONSES,
+ BuildBlobAsync(descriptions, completed_blob_uuid_set_, 5010));
response1.request_number = 0;
BlobItemBytesResponse response2(0);
PopulateBytes(response2.allocate_mutable_data(2), 2);
responses = {response1, response2};
- EXPECT_FALSE(host_.OnMemoryResponses(kBlobUUID, responses));
+ EXPECT_EQ(BlobTransportResult::BAD_IPC,
+ host_.OnMemoryResponses(kBlobUUID, responses, &context_));
+ EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlobUUID)->IsBroken());
+ DecrementBlobRefCount(kBlobUUID);
+ base::RunLoop().RunUntilIdle();
+};
+
+TEST_F(BlobAsyncBuilderHostTest, WaitOnReferencedBlob) {
+ const std::string& kBlob1 = "blob1";
+ const std::string& kBlob2 = "blob2";
+ const std::string& kBlob3 = "blob3";
+
+ // Register blobs.
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
+ std::set<std::string>(), &context_));
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
+ std::set<std::string>(), &context_));
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.RegisterBlobUUID(kBlob3, kContentType, kContentDisposition,
+ {kBlob1, kBlob2}, &context_));
+
+ // Finish the third one, with a reference to the first and second blob.
+ std::vector<DataElement> descriptions;
+ AddShortcutMemoryItem(2, &descriptions);
+ DataElement element;
+ element.SetToBlob(kBlob1);
+ descriptions.push_back(element);
+ element.SetToBlob(kBlob2);
+ descriptions.push_back(element);
+
+ // Finish the third, but we should still be 'building' it.
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.StartBuildingBlob(
+ kBlob3, descriptions, 2, &context_,
+ base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
+ base::Unretained(this))));
+ EXPECT_FALSE(request_called_);
+ EXPECT_TRUE(host_.IsBeingBuilt(kBlob3));
+ EXPECT_TRUE(IsBeingBuiltInContext(kBlob3));
+
+ // Finish the first.
+ descriptions.clear();
+ AddShortcutMemoryItem(2, &descriptions);
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.StartBuildingBlob(
+ kBlob1, descriptions, 2, &context_,
+ base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
+ base::Unretained(this))));
+ EXPECT_FALSE(request_called_);
+ EXPECT_FALSE(host_.IsBeingBuilt(kBlob1));
+ EXPECT_FALSE(IsBeingBuiltInContext(kBlob1));
+ EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob1));
+
+ // Run the message loop so we propogate the construction complete callbacks.
+ base::RunLoop().RunUntilIdle();
+ // Verify we're not done.
+ EXPECT_TRUE(host_.IsBeingBuilt(kBlob3));
+ EXPECT_TRUE(IsBeingBuiltInContext(kBlob3));
+
+ // Finish the second.
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.StartBuildingBlob(
+ kBlob2, descriptions, 2, &context_,
+ base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
+ base::Unretained(this))));
+ EXPECT_FALSE(request_called_);
+ EXPECT_FALSE(host_.IsBeingBuilt(kBlob2));
+ EXPECT_FALSE(IsBeingBuiltInContext(kBlob2));
+ EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob2));
+
+ // Run the message loop so we propogate the construction complete callbacks.
+ base::RunLoop().RunUntilIdle();
+ // Finally, we should be finished with third blob.
+ EXPECT_FALSE(host_.IsBeingBuilt(kBlob3));
+ EXPECT_FALSE(IsBeingBuiltInContext(kBlob3));
+ EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob3));
+};
+
+TEST_F(BlobAsyncBuilderHostTest, IncorrectBlobDependencies) {
+ const std::string& kGoodBlob = "goodBlob";
+ const std::string& kBlob1 = "blob1";
+ const std::string& kBlob2 = "blob2";
+ const std::string& kBlob3 = "blob3";
+
+ // Register blobs. Blob 1 has a reference to itself, Blob 2 has a reference
+ // but doesn't use it, and blob 3 doesn't list it's reference.
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.RegisterBlobUUID(kGoodBlob, kContentType, kContentDisposition,
+ std::set<std::string>(), &context_));
+ EXPECT_EQ(BlobTransportResult::BAD_IPC,
+ host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
+ {kBlob1}, &context_));
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
+ {kGoodBlob}, &context_));
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.RegisterBlobUUID(kBlob3, kContentType, kContentDisposition,
+ std::set<std::string>(), &context_));
+
+ // The first blob shouldn't be building anymore.
+ EXPECT_FALSE(host_.IsBeingBuilt(kBlob1));
+
+ // Try to finish the second one, without a reference to the first.
+ std::vector<DataElement> descriptions;
+ AddShortcutMemoryItem(2, &descriptions);
+ EXPECT_EQ(BlobTransportResult::BAD_IPC,
+ host_.StartBuildingBlob(
+ kBlob2, descriptions, 2, &context_,
+ base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
+ base::Unretained(this))));
+ EXPECT_FALSE(host_.IsBeingBuilt(kBlob2));
+
+ // Try to finish the third one with the reference we didn't declare earlier.
+ descriptions.clear();
+ AddShortcutMemoryItem(2, &descriptions);
+ DataElement element;
+ element.SetToBlob(kGoodBlob);
+ descriptions.push_back(element);
+ EXPECT_EQ(BlobTransportResult::BAD_IPC,
+ host_.StartBuildingBlob(
+ kBlob3, descriptions, 2, &context_,
+ base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
+ base::Unretained(this))));
+ EXPECT_FALSE(host_.IsBeingBuilt(kBlob3));
+};
+
+TEST_F(BlobAsyncBuilderHostTest, BlobBreaksWhenReferenceBreaks) {
+ const std::string& kBlob1 = "blob1";
+ const std::string& kBlob2 = "blob2";
+
+ // Register blobs.
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
+ std::set<std::string>(), &context_));
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
+ {kBlob1}, &context_));
+
+ // Finish the second one, with a reference to the first.
+ std::vector<DataElement> descriptions;
+ AddShortcutMemoryItem(2, &descriptions);
+ DataElement element;
+ element.SetToBlob(kBlob1);
+ descriptions.push_back(element);
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.StartBuildingBlob(
+ kBlob2, descriptions, 2, &context_,
+ base::Bind(&BlobAsyncBuilderHostTest::RequestMemoryCallback,
+ base::Unretained(this))));
+ EXPECT_FALSE(request_called_);
+ EXPECT_TRUE(host_.IsBeingBuilt(kBlob2));
+ EXPECT_TRUE(IsBeingBuiltInContext(kBlob2));
+
+ // Break the first.
+ descriptions.clear();
+ host_.CancelBuildingBlob(kBlob1, IPCBlobCreationCancelCode::UNKNOWN,
+ &context_);
+ EXPECT_FALSE(host_.IsBeingBuilt(kBlob1));
+ EXPECT_FALSE(IsBeingBuiltInContext(kBlob1));
+ EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob1)->IsBroken());
+
+ // Run the message loop so we propogate the construction complete callbacks.
+ base::RunLoop().RunUntilIdle();
+ // We should be finished with third blob, and it should be broken.
+ EXPECT_FALSE(host_.IsBeingBuilt(kBlob2));
+ EXPECT_FALSE(IsBeingBuiltInContext(kBlob2));
+ EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob2)->IsBroken());
+};
+
+TEST_F(BlobAsyncBuilderHostTest, BlobBreaksWhenReferenceBroken) {
+ const std::string& kBlob1 = "blob1";
+ const std::string& kBlob2 = "blob2";
+
+ // Register blobs.
+ EXPECT_EQ(BlobTransportResult::DONE,
+ host_.RegisterBlobUUID(kBlob1, kContentType, kContentDisposition,
+ std::set<std::string>(), &context_));
+ host_.CancelBuildingBlob(kBlob1, IPCBlobCreationCancelCode::UNKNOWN,
+ &context_);
+ EXPECT_EQ(BlobTransportResult::CANCEL_REFERENCED_BLOB_BROKEN,
+ host_.RegisterBlobUUID(kBlob2, kContentType, kContentDisposition,
+ {kBlob1}, &context_));
+ EXPECT_FALSE(host_.IsBeingBuilt(kBlob2));
+ EXPECT_FALSE(IsBeingBuiltInContext(kBlob2));
+ EXPECT_TRUE(context_.GetBlobDataFromUUID(kBlob2)->IsBroken());
};
-} // namespace
} // namespace storage
diff --git a/chromium/content/browser/blob_storage/blob_async_transport_request_builder_unittest.cc b/chromium/content/browser/blob_storage/blob_async_transport_request_builder_unittest.cc
new file mode 100644
index 00000000000..071a06bb23f
--- /dev/null
+++ b/chromium/content/browser/blob_storage/blob_async_transport_request_builder_unittest.cc
@@ -0,0 +1,356 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <string>
+
+#include "base/logging.h"
+#include "storage/browser/blob/blob_async_transport_request_builder.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace storage {
+namespace {
+
+const char kNewUUID[] = "newUUID";
+const base::FilePath kFuturePopulatingFilePath = base::FilePath::FromUTF8Unsafe(
+ std::string(BlobDataBuilder::kAppendFutureFileTemporaryFileName));
+const char kFakeBlobUUID[] = "fakeBlob";
+
+void AddMemoryItem(size_t length, std::vector<DataElement>* out) {
+ DataElement bytes;
+ bytes.SetToBytesDescription(length);
+ out->push_back(bytes);
+}
+
+void AddShortcutMemoryItem(size_t length, std::vector<DataElement>* out) {
+ DataElement bytes;
+ bytes.SetToAllocatedBytes(length);
+ for (size_t i = 0; i < length; i++) {
+ bytes.mutable_bytes()[i] = static_cast<char>(i);
+ }
+ out->push_back(bytes);
+}
+
+void AddBlobItem(std::vector<DataElement>* out) {
+ DataElement blob;
+ blob.SetToBlob(kFakeBlobUUID);
+ out->push_back(blob);
+}
+
+TEST(BlobAsyncTransportRequestBuilderTest, TestNoMemoryItems) {
+ BlobAsyncTransportRequestBuilder strategy;
+ BlobDataBuilder builder(kNewUUID);
+ std::vector<DataElement> infos;
+
+ // Here we test that we don't do any requests when there are no memory items.
+ AddBlobItem(&infos);
+ AddBlobItem(&infos);
+ AddBlobItem(&infos);
+ strategy.InitializeForIPCRequests(100, // max_ipc_memory_size
+ 0, // blob_total_size
+ infos, &builder);
+
+ EXPECT_EQ(0u, strategy.shared_memory_sizes().size());
+ EXPECT_EQ(0u, strategy.file_sizes().size());
+ EXPECT_EQ(0u, strategy.requests().size());
+
+ BlobDataBuilder expected_builder(kNewUUID);
+ expected_builder.AppendBlob(kFakeBlobUUID);
+ expected_builder.AppendBlob(kFakeBlobUUID);
+ expected_builder.AppendBlob(kFakeBlobUUID);
+ EXPECT_EQ(expected_builder, builder);
+}
+
+TEST(BlobAsyncTransportRequestBuilderTest, TestLargeBlockToFile) {
+ BlobAsyncTransportRequestBuilder strategy;
+ BlobDataBuilder builder(kNewUUID);
+ std::vector<DataElement> infos;
+
+ AddMemoryItem(305, &infos);
+ strategy.InitializeForFileRequests(400, // max_file_size
+ 305, // blob_total_size
+ infos, &builder);
+
+ EXPECT_EQ(0u, strategy.shared_memory_sizes().size());
+ EXPECT_EQ(1u, strategy.file_sizes().size());
+ EXPECT_EQ(305ul, strategy.file_sizes().at(0));
+ EXPECT_EQ(1u, strategy.requests().size());
+
+ auto& memory_item_request = strategy.requests().at(0);
+ EXPECT_EQ(0u, memory_item_request.browser_item_index);
+ EXPECT_EQ(0u, memory_item_request.browser_item_offset);
+ EXPECT_EQ(
+ BlobItemBytesRequest::CreateFileRequest(0u, 0u, 0ull, 305ull, 0u, 0ull),
+ memory_item_request.message);
+
+ BlobDataBuilder expected_builder(kNewUUID);
+ expected_builder.AppendFile(kFuturePopulatingFilePath, 0, 305,
+ base::Time::FromDoubleT(0));
+ EXPECT_EQ(expected_builder, builder);
+}
+
+TEST(BlobAsyncTransportRequestBuilderTest, TestLargeBlockToFiles) {
+ BlobAsyncTransportRequestBuilder strategy;
+ BlobDataBuilder builder(kNewUUID);
+ std::vector<DataElement> infos;
+
+ AddMemoryItem(1000, &infos);
+ strategy.InitializeForFileRequests(400, // max_file_size
+ 1000, // blob_total_size
+ infos, &builder);
+
+ EXPECT_EQ(0u, strategy.shared_memory_sizes().size());
+ EXPECT_EQ(3u, strategy.file_sizes().size());
+ EXPECT_EQ(400ul, strategy.file_sizes().at(0));
+ EXPECT_EQ(400ul, strategy.file_sizes().at(1));
+ EXPECT_EQ(200ul, strategy.file_sizes().at(2));
+ EXPECT_EQ(3u, strategy.requests().size());
+
+ auto memory_item_request = strategy.requests().at(0);
+ EXPECT_EQ(0u, memory_item_request.browser_item_index);
+ EXPECT_EQ(0u, memory_item_request.browser_item_offset);
+ EXPECT_EQ(
+ BlobItemBytesRequest::CreateFileRequest(0u, 0u, 0ull, 400ull, 0u, 0ull),
+ memory_item_request.message);
+
+ memory_item_request = strategy.requests().at(1);
+ EXPECT_EQ(1u, memory_item_request.browser_item_index);
+ EXPECT_EQ(0u, memory_item_request.browser_item_offset);
+ EXPECT_EQ(
+ BlobItemBytesRequest::CreateFileRequest(1u, 0u, 400ull, 400ull, 1u, 0ull),
+ memory_item_request.message);
+
+ memory_item_request = strategy.requests().at(2);
+ EXPECT_EQ(2u, memory_item_request.browser_item_index);
+ EXPECT_EQ(0u, memory_item_request.browser_item_offset);
+ EXPECT_EQ(
+ BlobItemBytesRequest::CreateFileRequest(2u, 0u, 800ull, 200ull, 2u, 0ull),
+ memory_item_request.message);
+
+ BlobDataBuilder expected_builder(kNewUUID);
+ expected_builder.AppendFile(kFuturePopulatingFilePath, 0, 400,
+ base::Time::FromDoubleT(0));
+ expected_builder.AppendFile(kFuturePopulatingFilePath, 0, 400,
+ base::Time::FromDoubleT(0));
+ expected_builder.AppendFile(kFuturePopulatingFilePath, 0, 200,
+ base::Time::FromDoubleT(0));
+ EXPECT_EQ(expected_builder, builder);
+}
+
+TEST(BlobAsyncTransportRequestBuilderTest,
+ TestLargeBlocksConsolidatingInFiles) {
+ BlobAsyncTransportRequestBuilder strategy;
+ BlobDataBuilder builder(kNewUUID);
+ std::vector<DataElement> infos;
+
+ // We should have 3 storage items for the memory, two files, 400 each.
+ // We end up with storage items:
+ // 1: File A, 300MB
+ // 2: Blob
+ // 3: File A, 100MB (300MB offset)
+ // 4: File B, 400MB
+ AddMemoryItem(300, &infos);
+ AddBlobItem(&infos);
+ AddMemoryItem(500, &infos);
+
+ strategy.InitializeForFileRequests(400, // max_file_size
+ 800, // blob_total_size
+ infos, &builder);
+
+ EXPECT_EQ(0u, strategy.shared_memory_sizes().size());
+ EXPECT_EQ(2u, strategy.file_sizes().size());
+ EXPECT_EQ(400ul, strategy.file_sizes().at(0));
+ EXPECT_EQ(400ul, strategy.file_sizes().at(1));
+ EXPECT_EQ(3u, strategy.requests().size());
+
+ auto memory_item_request = strategy.requests().at(0);
+ EXPECT_EQ(0u, memory_item_request.browser_item_index);
+ EXPECT_EQ(0u, memory_item_request.browser_item_offset);
+ EXPECT_EQ(
+ BlobItemBytesRequest::CreateFileRequest(0u, 0u, 0ull, 300ull, 0u, 0ull),
+ memory_item_request.message);
+
+ memory_item_request = strategy.requests().at(1);
+ EXPECT_EQ(2u, memory_item_request.browser_item_index);
+ EXPECT_EQ(0u, memory_item_request.browser_item_offset);
+ EXPECT_EQ(
+ BlobItemBytesRequest::CreateFileRequest(1u, 2u, 0ull, 100ull, 0u, 300ull),
+ memory_item_request.message);
+
+ memory_item_request = strategy.requests().at(2);
+ EXPECT_EQ(3u, memory_item_request.browser_item_index);
+ EXPECT_EQ(0u, memory_item_request.browser_item_offset);
+ EXPECT_EQ(
+ BlobItemBytesRequest::CreateFileRequest(2u, 2u, 100ull, 400ull, 1u, 0ull),
+ memory_item_request.message);
+}
+
+TEST(BlobAsyncTransportRequestBuilderTest, TestSharedMemorySegmentation) {
+ BlobAsyncTransportRequestBuilder strategy;
+ BlobDataBuilder builder(kNewUUID);
+ std::vector<DataElement> infos;
+
+ // For transport we should have 3 shared memories, and then storage in 3
+ // browser items.
+ AddMemoryItem(500, &infos);
+ strategy.InitializeForSharedMemoryRequests(200, // max_shared_memory_size
+ 500, // total_blob_size
+ infos, &builder);
+
+ EXPECT_EQ(0u, strategy.file_sizes().size());
+ EXPECT_EQ(3u, strategy.shared_memory_sizes().size());
+ EXPECT_EQ(200u, strategy.shared_memory_sizes().at(0));
+ EXPECT_EQ(200u, strategy.shared_memory_sizes().at(1));
+ EXPECT_EQ(100u, strategy.shared_memory_sizes().at(2));
+ EXPECT_EQ(3u, strategy.requests().size());
+
+ auto memory_item_request = strategy.requests().at(0);
+ EXPECT_EQ(0u, memory_item_request.browser_item_index);
+ EXPECT_EQ(0u, memory_item_request.browser_item_offset);
+ EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest(0u, 0u, 0ull,
+ 200ull, 0u, 0ull),
+ memory_item_request.message);
+
+ memory_item_request = strategy.requests().at(1);
+ EXPECT_EQ(1u, memory_item_request.browser_item_index);
+ EXPECT_EQ(0u, memory_item_request.browser_item_offset);
+ EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest(1u, 0u, 200ull,
+ 200ull, 1u, 0ull),
+ memory_item_request.message);
+
+ memory_item_request = strategy.requests().at(2);
+ EXPECT_EQ(2u, memory_item_request.browser_item_index);
+ EXPECT_EQ(0u, memory_item_request.browser_item_offset);
+ EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest(2u, 0u, 400ull,
+ 100ull, 2u, 0ull),
+ memory_item_request.message);
+
+ BlobDataBuilder expected_builder(kNewUUID);
+ expected_builder.AppendFutureData(200);
+ expected_builder.AppendFutureData(200);
+ expected_builder.AppendFutureData(100);
+ EXPECT_EQ(expected_builder, builder);
+}
+
+TEST(BlobAsyncTransportRequestBuilderTest,
+ TestSharedMemorySegmentationAndStorage) {
+ BlobAsyncTransportRequestBuilder strategy;
+ BlobDataBuilder builder(kNewUUID);
+ std::vector<DataElement> infos;
+
+ // For transport, we should have 2 shared memories, where the first one
+ // have half 0 and half 3, and then the last one has half 3.
+ //
+ // For storage, we should have 3 browser items that match the pre-transport
+ // version:
+ // 1: Bytes 100MB
+ // 2: Blob
+ // 3: Bytes 200MB
+ AddShortcutMemoryItem(100, &infos); // should have no behavior change
+ AddBlobItem(&infos);
+ AddMemoryItem(200, &infos);
+
+ strategy.InitializeForSharedMemoryRequests(200, // max_shared_memory_size
+ 300, // total_blob_size
+ infos, &builder);
+
+ EXPECT_EQ(0u, strategy.file_sizes().size());
+ EXPECT_EQ(2u, strategy.shared_memory_sizes().size());
+ EXPECT_EQ(200u, strategy.shared_memory_sizes().at(0));
+ EXPECT_EQ(100u, strategy.shared_memory_sizes().at(1));
+ EXPECT_EQ(3u, strategy.requests().size());
+
+ auto memory_item_request = strategy.requests().at(0);
+ EXPECT_EQ(0u, memory_item_request.browser_item_index);
+ EXPECT_EQ(0u, memory_item_request.browser_item_offset);
+ EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest(0u, 0u, 0ull,
+ 100ull, 0u, 0ull),
+ memory_item_request.message);
+
+ memory_item_request = strategy.requests().at(1);
+ EXPECT_EQ(2u, memory_item_request.browser_item_index);
+ EXPECT_EQ(0u, memory_item_request.browser_item_offset);
+ EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest(1u, 2u, 0ull,
+ 100ull, 0u, 100ull),
+ memory_item_request.message);
+
+ memory_item_request = strategy.requests().at(2);
+ EXPECT_EQ(2u, memory_item_request.browser_item_index);
+ EXPECT_EQ(100u, memory_item_request.browser_item_offset);
+ EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest(2u, 2u, 100ull,
+ 100ull, 1u, 0ull),
+ memory_item_request.message);
+
+ BlobDataBuilder expected_builder(kNewUUID);
+ expected_builder.AppendFutureData(100);
+ expected_builder.AppendBlob(kFakeBlobUUID);
+ expected_builder.AppendFutureData(200);
+ EXPECT_EQ(expected_builder, builder);
+}
+
+TEST(BlobAsyncTransportRequestBuilderTest, TestSimpleIPC) {
+ // Test simple IPC strategy, where size < max_ipc_memory_size and we have
+ // just one item.
+ std::vector<DataElement> infos;
+ BlobAsyncTransportRequestBuilder strategy;
+ BlobDataBuilder builder(kNewUUID);
+ AddMemoryItem(10, &infos);
+ AddBlobItem(&infos);
+
+ strategy.InitializeForIPCRequests(100, // max_ipc_memory_size
+ 10, // total_blob_size
+ infos, &builder);
+
+ EXPECT_EQ(0u, strategy.file_sizes().size());
+ EXPECT_EQ(0u, strategy.shared_memory_sizes().size());
+ ASSERT_EQ(1u, strategy.requests().size());
+
+ auto memory_item_request = strategy.requests().at(0);
+ EXPECT_EQ(0u, memory_item_request.browser_item_index);
+ EXPECT_EQ(0u, memory_item_request.browser_item_offset);
+ EXPECT_EQ(BlobItemBytesRequest::CreateIPCRequest(0u, 0u, 0ull, 10ull),
+ memory_item_request.message);
+}
+
+TEST(BlobAsyncTransportRequestBuilderTest, TestMultipleIPC) {
+ // Same as above, but with 2 items and a blob in-between.
+ std::vector<DataElement> infos;
+ BlobAsyncTransportRequestBuilder strategy;
+ BlobDataBuilder builder(kNewUUID);
+ AddShortcutMemoryItem(10, &infos); // should have no behavior change
+ AddBlobItem(&infos);
+ AddMemoryItem(80, &infos);
+
+ strategy.InitializeForIPCRequests(100, // max_ipc_memory_size
+ 90, // total_blob_size
+ infos, &builder);
+
+ EXPECT_EQ(0u, strategy.file_sizes().size());
+ EXPECT_EQ(0u, strategy.shared_memory_sizes().size());
+ ASSERT_EQ(2u, strategy.requests().size());
+
+ auto memory_item_request = strategy.requests().at(0);
+ EXPECT_EQ(0u, memory_item_request.browser_item_index);
+ EXPECT_EQ(0u, memory_item_request.browser_item_offset);
+ EXPECT_EQ(BlobItemBytesRequest::CreateIPCRequest(0u, 0u, 0ull, 10ull),
+ memory_item_request.message);
+
+ memory_item_request = strategy.requests().at(1);
+ EXPECT_EQ(2u, memory_item_request.browser_item_index);
+ EXPECT_EQ(0u, memory_item_request.browser_item_offset);
+ EXPECT_EQ(BlobItemBytesRequest::CreateIPCRequest(1u, 2u, 0ull, 80ull),
+ memory_item_request.message);
+
+ // We still populate future data, as the strategy assumes we will be
+ // requesting the data.
+ BlobDataBuilder expected_builder(kNewUUID);
+ expected_builder.AppendFutureData(10);
+ expected_builder.AppendBlob(kFakeBlobUUID);
+ expected_builder.AppendFutureData(80);
+ EXPECT_EQ(expected_builder, builder);
+}
+} // namespace
+} // namespace storage
diff --git a/chromium/content/browser/blob_storage/blob_async_transport_strategy_unittest.cc b/chromium/content/browser/blob_storage/blob_async_transport_strategy_unittest.cc
deleted file mode 100644
index 6318439e916..00000000000
--- a/chromium/content/browser/blob_storage/blob_async_transport_strategy_unittest.cc
+++ /dev/null
@@ -1,458 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "storage/browser/blob/blob_async_transport_strategy.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <string>
-
-#include "base/logging.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace storage {
-namespace {
-
-const char kNewUUID[] = "newUUID";
-const base::FilePath kFuturePopulatingFilePath = base::FilePath::FromUTF8Unsafe(
- std::string(BlobDataBuilder::kAppendFutureFileTemporaryFileName));
-const char kFakeBlobUUID[] = "fakeBlob";
-
-void AddMemoryItem(size_t length, std::vector<DataElement>* out) {
- DataElement bytes;
- bytes.SetToBytesDescription(length);
- out->push_back(bytes);
-}
-
-void AddShortcutMemoryItem(size_t length, std::vector<DataElement>* out) {
- DataElement bytes;
- bytes.SetToAllocatedBytes(length);
- for (size_t i = 0; i < length; i++) {
- bytes.mutable_bytes()[i] = static_cast<char>(i);
- }
- out->push_back(bytes);
-}
-
-void AddBlobItem(std::vector<DataElement>* out) {
- DataElement blob;
- blob.SetToBlob(kFakeBlobUUID);
- out->push_back(blob);
-}
-
-TEST(BlobAsyncTransportStrategyTest, TestNoMemoryItems) {
- BlobAsyncTransportStrategy strategy;
- std::vector<DataElement> infos;
-
- // Here we test that we don't do any requests when there are no memory items.
- AddBlobItem(&infos);
- AddBlobItem(&infos);
- AddBlobItem(&infos);
- strategy.Initialize(100, // max_ipc_memory_size
- 200, // max_shared_memory_size
- 400, // max_file_size
- 5000, // disk_space_left
- 100, // memory_available
- kNewUUID, infos);
-
- EXPECT_EQ(BlobAsyncTransportStrategy::ERROR_NONE, strategy.error());
-
- EXPECT_EQ(0u, strategy.handle_sizes().size());
- EXPECT_EQ(0u, strategy.requests().size());
-
- BlobDataBuilder builder(kNewUUID);
- builder.AppendBlob(kFakeBlobUUID);
- builder.AppendBlob(kFakeBlobUUID);
- builder.AppendBlob(kFakeBlobUUID);
- EXPECT_EQ(builder, *strategy.blob_builder());
-}
-
-TEST(BlobAsyncTransportStrategyTest, TestLargeBlockToFile) {
- BlobAsyncTransportStrategy strategy;
- std::vector<DataElement> infos;
-
- // Here we test our size > max_blob_in_memory_size (100),
- // and we save to one file. (size < max_file_size)
- AddMemoryItem(305, &infos);
- strategy.Initialize(100, // max_ipc_memory_size
- 200, // max_shared_memory_size
- 400, // max_file_size
- 5000, // disk_space_left
- 100, // memory_available
- kNewUUID, infos);
-
- EXPECT_EQ(BlobAsyncTransportStrategy::ERROR_NONE, strategy.error());
-
- EXPECT_EQ(1u, strategy.handle_sizes().size());
- EXPECT_EQ(305ul, strategy.handle_sizes().at(0));
- EXPECT_EQ(1u, strategy.requests().size());
-
- auto& memory_item_request = strategy.requests().at(0);
- EXPECT_EQ(0u, memory_item_request.browser_item_index);
- EXPECT_EQ(0u, memory_item_request.browser_item_offset);
- EXPECT_EQ(
- BlobItemBytesRequest::CreateFileRequest(0u, 0u, 0ull, 305ull, 0u, 0ull),
- memory_item_request.message);
-
- BlobDataBuilder builder(kNewUUID);
- builder.AppendFile(kFuturePopulatingFilePath, 0, 305,
- base::Time::FromDoubleT(0));
- EXPECT_EQ(builder, *strategy.blob_builder());
-}
-
-TEST(BlobAsyncTransportStrategyTest, TestLargeBlockToFiles) {
- BlobAsyncTransportStrategy strategy;
- std::vector<DataElement> infos;
-
- // Here we test our size > max_blob_in_memory_size (300),
- // and we save 3 files. (size > max_file_size)
- AddMemoryItem(1000, &infos);
- strategy.Initialize(100, // max_ipc_memory_size
- 200, // max_shared_memory_size
- 400, // max_file_size
- 5000, // disk_space_left
- 100, // memory_available
- kNewUUID, infos);
- EXPECT_EQ(BlobAsyncTransportStrategy::ERROR_NONE, strategy.error());
-
- EXPECT_EQ(3u, strategy.handle_sizes().size());
- EXPECT_EQ(400ul, strategy.handle_sizes().at(0));
- EXPECT_EQ(400ul, strategy.handle_sizes().at(1));
- EXPECT_EQ(200ul, strategy.handle_sizes().at(2));
- EXPECT_EQ(3u, strategy.requests().size());
-
- auto memory_item_request = strategy.requests().at(0);
- EXPECT_EQ(0u, memory_item_request.browser_item_index);
- EXPECT_EQ(0u, memory_item_request.browser_item_offset);
- EXPECT_EQ(
- BlobItemBytesRequest::CreateFileRequest(0u, 0u, 0ull, 400ull, 0u, 0ull),
- memory_item_request.message);
-
- memory_item_request = strategy.requests().at(1);
- EXPECT_EQ(1u, memory_item_request.browser_item_index);
- EXPECT_EQ(0u, memory_item_request.browser_item_offset);
- EXPECT_EQ(
- BlobItemBytesRequest::CreateFileRequest(1u, 0u, 400ull, 400ull, 1u, 0ull),
- memory_item_request.message);
-
- memory_item_request = strategy.requests().at(2);
- EXPECT_EQ(2u, memory_item_request.browser_item_index);
- EXPECT_EQ(0u, memory_item_request.browser_item_offset);
- EXPECT_EQ(
- BlobItemBytesRequest::CreateFileRequest(2u, 0u, 800ull, 200ull, 2u, 0ull),
- memory_item_request.message);
-
- BlobDataBuilder builder(kNewUUID);
- builder.AppendFile(kFuturePopulatingFilePath, 0, 400,
- base::Time::FromDoubleT(0));
- builder.AppendFile(kFuturePopulatingFilePath, 0, 400,
- base::Time::FromDoubleT(0));
- builder.AppendFile(kFuturePopulatingFilePath, 0, 200,
- base::Time::FromDoubleT(0));
- EXPECT_EQ(builder, *strategy.blob_builder());
-}
-
-TEST(BlobAsyncTransportStrategyTest, TestLargeBlocksConsolidatingInFiles) {
- BlobAsyncTransportStrategy strategy;
- std::vector<DataElement> infos;
-
- // We should have 3 storage items for the memory, two files, 400 each.
- // We end up with storage items:
- // 1: File A, 300MB
- // 2: Blob
- // 3: File A, 100MB (300MB offset)
- // 4: File B, 400MB
- AddMemoryItem(300, &infos);
- AddBlobItem(&infos);
- AddMemoryItem(500, &infos);
-
- strategy.Initialize(100, // max_ipc_memory_size
- 200, // max_shared_memory_size
- 400, // max_file_size
- 5000, // disk_space_left
- 100, // memory_available
- kNewUUID, infos);
- EXPECT_EQ(BlobAsyncTransportStrategy::ERROR_NONE, strategy.error());
-
- EXPECT_EQ(2u, strategy.handle_sizes().size());
- EXPECT_EQ(400ul, strategy.handle_sizes().at(0));
- EXPECT_EQ(400ul, strategy.handle_sizes().at(1));
- EXPECT_EQ(3u, strategy.requests().size());
-
- auto memory_item_request = strategy.requests().at(0);
- EXPECT_EQ(0u, memory_item_request.browser_item_index);
- EXPECT_EQ(0u, memory_item_request.browser_item_offset);
- EXPECT_EQ(
- BlobItemBytesRequest::CreateFileRequest(0u, 0u, 0ull, 300ull, 0u, 0ull),
- memory_item_request.message);
-
- memory_item_request = strategy.requests().at(1);
- EXPECT_EQ(2u, memory_item_request.browser_item_index);
- EXPECT_EQ(0u, memory_item_request.browser_item_offset);
- EXPECT_EQ(
- BlobItemBytesRequest::CreateFileRequest(1u, 2u, 0ull, 100ull, 0u, 300ull),
- memory_item_request.message);
-
- memory_item_request = strategy.requests().at(2);
- EXPECT_EQ(3u, memory_item_request.browser_item_index);
- EXPECT_EQ(0u, memory_item_request.browser_item_offset);
- EXPECT_EQ(
- BlobItemBytesRequest::CreateFileRequest(2u, 2u, 100ull, 400ull, 1u, 0ull),
- memory_item_request.message);
-}
-
-TEST(BlobAsyncTransportStrategyTest, TestSharedMemorySegmentation) {
- BlobAsyncTransportStrategy strategy;
- std::vector<DataElement> infos;
-
- // For transport we should have 3 shared memories, and then storage in 3
- // browser items.
- // (size > max_shared_memory_size and size < max_blob_in_memory_size
- AddMemoryItem(500, &infos);
- strategy.Initialize(100, // max_ipc_memory_size
- 200, // max_shared_memory_size
- 300, // max_file_size
- 5000, // disk_space_left
- 500, // memory_available
- kNewUUID, infos);
- EXPECT_EQ(BlobAsyncTransportStrategy::ERROR_NONE, strategy.error());
-
- EXPECT_EQ(3u, strategy.handle_sizes().size());
- EXPECT_EQ(200u, strategy.handle_sizes().at(0));
- EXPECT_EQ(200u, strategy.handle_sizes().at(1));
- EXPECT_EQ(100u, strategy.handle_sizes().at(2));
- EXPECT_EQ(3u, strategy.requests().size());
-
- auto memory_item_request = strategy.requests().at(0);
- EXPECT_EQ(0u, memory_item_request.browser_item_index);
- EXPECT_EQ(0u, memory_item_request.browser_item_offset);
- EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest(0u, 0u, 0ull,
- 200ull, 0u, 0ull),
- memory_item_request.message);
-
- memory_item_request = strategy.requests().at(1);
- EXPECT_EQ(1u, memory_item_request.browser_item_index);
- EXPECT_EQ(0u, memory_item_request.browser_item_offset);
- EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest(1u, 0u, 200ull,
- 200ull, 1u, 0ull),
- memory_item_request.message);
-
- memory_item_request = strategy.requests().at(2);
- EXPECT_EQ(2u, memory_item_request.browser_item_index);
- EXPECT_EQ(0u, memory_item_request.browser_item_offset);
- EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest(2u, 0u, 400ull,
- 100ull, 2u, 0ull),
- memory_item_request.message);
-
- BlobDataBuilder builder(kNewUUID);
- builder.AppendFutureData(200);
- builder.AppendFutureData(200);
- builder.AppendFutureData(100);
-
- EXPECT_EQ(builder, *strategy.blob_builder());
-}
-
-TEST(BlobAsyncTransportStrategyTest, TestSharedMemorySegmentationAndStorage) {
- BlobAsyncTransportStrategy strategy;
- std::vector<DataElement> infos;
-
- // For transport, we should have 2 shared memories, where the first one
- // have half 0 and half 3, and then the last one has half 3.
- //
- // For storage, we should have 3 browser items that match the pre-transport
- // version:
- // 1: Bytes 100MB
- // 2: Blob
- // 3: Bytes 200MB
- AddShortcutMemoryItem(100, &infos); // should have no behavior change
- AddBlobItem(&infos);
- AddMemoryItem(200, &infos);
-
- strategy.Initialize(100, // max_ipc_memory_size
- 200, // max_shared_memory_size
- 300, // max_file_size
- 5000, // disk_space_left
- 300, // memory_available
- kNewUUID, infos);
- EXPECT_EQ(BlobAsyncTransportStrategy::ERROR_NONE, strategy.error());
-
- EXPECT_EQ(2u, strategy.handle_sizes().size());
- EXPECT_EQ(200u, strategy.handle_sizes().at(0));
- EXPECT_EQ(100u, strategy.handle_sizes().at(1));
- EXPECT_EQ(3u, strategy.requests().size());
-
- auto memory_item_request = strategy.requests().at(0);
- EXPECT_EQ(0u, memory_item_request.browser_item_index);
- EXPECT_EQ(0u, memory_item_request.browser_item_offset);
- EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest(0u, 0u, 0ull,
- 100ull, 0u, 0ull),
- memory_item_request.message);
-
- memory_item_request = strategy.requests().at(1);
- EXPECT_EQ(2u, memory_item_request.browser_item_index);
- EXPECT_EQ(0u, memory_item_request.browser_item_offset);
- EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest(1u, 2u, 0ull,
- 100ull, 0u, 100ull),
- memory_item_request.message);
-
- memory_item_request = strategy.requests().at(2);
- EXPECT_EQ(2u, memory_item_request.browser_item_index);
- EXPECT_EQ(100u, memory_item_request.browser_item_offset);
- EXPECT_EQ(BlobItemBytesRequest::CreateSharedMemoryRequest(2u, 2u, 100ull,
- 100ull, 1u, 0ull),
- memory_item_request.message);
-
- BlobDataBuilder builder(kNewUUID);
- builder.AppendFutureData(100);
- builder.AppendBlob(kFakeBlobUUID);
- builder.AppendFutureData(200);
-
- EXPECT_EQ(builder, *strategy.blob_builder());
-}
-
-TEST(BlobAsyncTransportStrategyTest, TestTooLarge) {
- BlobAsyncTransportStrategy strategy;
- std::vector<DataElement> infos;
-
- // Our item is too large for disk, so error out.
- AddMemoryItem(5001, &infos);
-
- strategy.Initialize(100, // max_ipc_memory_size
- 200, // max_shared_memory_size
- 400, // max_file_size
- 5000, // disk_space_left
- 100, // memory_left
- kNewUUID, infos);
-
- EXPECT_EQ(0u, strategy.handle_sizes().size());
- EXPECT_EQ(0u, strategy.handle_sizes().size());
- EXPECT_EQ(0u, strategy.requests().size());
- EXPECT_EQ(BlobAsyncTransportStrategy::ERROR_TOO_LARGE, strategy.error());
-}
-
-TEST(BlobAsyncTransportStrategyTest, TestNoDisk) {
- BlobAsyncTransportStrategy strategy;
- std::vector<DataElement> infos;
-
- // Our item is too large for memory, and we are in no_disk mode (incognito)
- AddMemoryItem(301, &infos);
-
- strategy.Initialize(100, // max_ipc_memory_size
- 200, // max_shared_memory_size
- 400, // max_file_size
- 0, // disk_space_left
- 300, // memory_available
- kNewUUID, infos);
-
- EXPECT_EQ(0u, strategy.handle_sizes().size());
- EXPECT_EQ(0u, strategy.handle_sizes().size());
- EXPECT_EQ(0u, strategy.requests().size());
- EXPECT_EQ(BlobAsyncTransportStrategy::ERROR_TOO_LARGE, strategy.error());
-}
-
-TEST(BlobAsyncTransportStrategyTest, TestSimpleIPC) {
- // Test simple IPC strategy, where size < max_ipc_memory_size and we have
- // just one item.
- std::vector<DataElement> infos;
- BlobAsyncTransportStrategy strategy;
- AddMemoryItem(10, &infos);
- AddBlobItem(&infos);
-
- strategy.Initialize(100, // max_ipc_memory_size
- 200, // max_shared_memory_size
- 400, // max_file_size
- 5000, // disk_space_left
- 100, // memory_left
- kNewUUID, infos);
- EXPECT_EQ(BlobAsyncTransportStrategy::ERROR_NONE, strategy.error());
-
- ASSERT_EQ(1u, strategy.requests().size());
-
- auto memory_item_request = strategy.requests().at(0);
- EXPECT_EQ(0u, memory_item_request.browser_item_index);
- EXPECT_EQ(0u, memory_item_request.browser_item_offset);
- EXPECT_EQ(BlobItemBytesRequest::CreateIPCRequest(0u, 0u, 0ull, 10ull),
- memory_item_request.message);
-}
-
-TEST(BlobAsyncTransportStrategyTest, TestMultipleIPC) {
- // Same as above, but with 2 items and a blob in-between.
- std::vector<DataElement> infos;
- BlobAsyncTransportStrategy strategy;
- infos.clear();
- AddShortcutMemoryItem(10, &infos); // should have no behavior change
- AddBlobItem(&infos);
- AddMemoryItem(80, &infos);
-
- strategy.Initialize(100, // max_ipc_memory_size
- 200, // max_shared_memory_size
- 400, // max_file_size
- 5000, // disk_space_left
- 100, // memory_left
- kNewUUID, infos);
- EXPECT_EQ(BlobAsyncTransportStrategy::ERROR_NONE, strategy.error());
-
- ASSERT_EQ(2u, strategy.requests().size());
-
- auto memory_item_request = strategy.requests().at(0);
- EXPECT_EQ(0u, memory_item_request.browser_item_index);
- EXPECT_EQ(0u, memory_item_request.browser_item_offset);
- EXPECT_EQ(BlobItemBytesRequest::CreateIPCRequest(0u, 0u, 0ull, 10ull),
- memory_item_request.message);
-
- memory_item_request = strategy.requests().at(1);
- EXPECT_EQ(2u, memory_item_request.browser_item_index);
- EXPECT_EQ(0u, memory_item_request.browser_item_offset);
- EXPECT_EQ(BlobItemBytesRequest::CreateIPCRequest(1u, 2u, 0ull, 80ull),
- memory_item_request.message);
-
- // We still populate future data, as the strategy assumes we will be
- // requesting the data.
- BlobDataBuilder builder(kNewUUID);
- builder.AppendFutureData(10);
- builder.AppendBlob(kFakeBlobUUID);
- builder.AppendFutureData(80);
-
- EXPECT_EQ(builder, *strategy.blob_builder());
-}
-
-TEST(BlobAsyncTransportStrategyTest, Shortcut) {
- std::vector<DataElement> infos;
- AddMemoryItem(100, &infos);
- AddBlobItem(&infos);
- EXPECT_FALSE(BlobAsyncTransportStrategy::ShouldBeShortcut(infos, 200));
-
- infos.clear();
- AddShortcutMemoryItem(100, &infos);
- AddBlobItem(&infos);
- EXPECT_TRUE(BlobAsyncTransportStrategy::ShouldBeShortcut(infos, 200));
-
- infos.clear();
- AddShortcutMemoryItem(100, &infos);
- EXPECT_FALSE(BlobAsyncTransportStrategy::ShouldBeShortcut(infos, 99));
-}
-} // namespace
-
-TEST(BlobAsyncTransportStrategyTest, TestInvalidParams) {
- std::vector<DataElement> infos;
- // In order to test uin64_t overflow, we would need to have an array with more
- // than size_t entries (for 32 byte stuff). So this would only happen if the
- // IPC was malformed. We instead have to friend this test from DataElement so
- // we can modify the length to be > size_t.
-
- // Test uint64_t overflow.
- BlobAsyncTransportStrategy strategy;
- AddMemoryItem(1, &infos);
- AddMemoryItem(1, &infos);
- infos.back().length_ = std::numeric_limits<uint64_t>::max();
- strategy.Initialize(100, // max_ipc_memory_size
- 200, // max_shared_memory_size
- 400, // max_file_size
- 5000, // disk_space_left
- 100, // memory_left
- kNewUUID, infos);
- EXPECT_EQ(BlobAsyncTransportStrategy::ERROR_INVALID_PARAMS,
- strategy.error());
-}
-} // namespace storage
diff --git a/chromium/content/browser/blob_storage/blob_dispatcher_host.cc b/chromium/content/browser/blob_storage/blob_dispatcher_host.cc
new file mode 100644
index 00000000000..d61653cdaf5
--- /dev/null
+++ b/chromium/content/browser/blob_storage/blob_dispatcher_host.cc
@@ -0,0 +1,370 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/blob_storage/blob_dispatcher_host.h"
+
+#include <algorithm>
+
+#include "base/bind.h"
+#include "base/metrics/histogram_macros.h"
+#include "content/browser/bad_message.h"
+#include "content/browser/fileapi/chrome_blob_storage_context.h"
+#include "content/common/fileapi/webblob_messages.h"
+#include "ipc/ipc_platform_file.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "storage/browser/blob/blob_transport_result.h"
+#include "storage/common/blob_storage/blob_item_bytes_request.h"
+#include "storage/common/blob_storage/blob_item_bytes_response.h"
+#include "storage/common/data_element.h"
+#include "url/gurl.h"
+
+using storage::BlobStorageContext;
+using storage::BlobStorageRegistry;
+using storage::BlobTransportResult;
+using storage::IPCBlobCreationCancelCode;
+
+namespace content {
+namespace {
+
+// These are used for UMA stats, don't change.
+enum RefcountOperation {
+ BDH_DECREMENT = 0,
+ BDH_INCREMENT,
+ BDH_TRACING_ENUM_LAST
+};
+
+} // namespace
+
+BlobDispatcherHost::BlobDispatcherHost(
+ ChromeBlobStorageContext* blob_storage_context)
+ : BrowserMessageFilter(BlobMsgStart),
+ blob_storage_context_(blob_storage_context) {}
+
+BlobDispatcherHost::~BlobDispatcherHost() {
+ ClearHostFromBlobStorageContext();
+}
+
+void BlobDispatcherHost::OnChannelClosing() {
+ ClearHostFromBlobStorageContext();
+ public_blob_urls_.clear();
+ blobs_inuse_map_.clear();
+}
+
+bool BlobDispatcherHost::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(BlobDispatcherHost, message)
+ IPC_MESSAGE_HANDLER(BlobStorageMsg_RegisterBlobUUID, OnRegisterBlobUUID)
+ IPC_MESSAGE_HANDLER(BlobStorageMsg_StartBuildingBlob, OnStartBuildingBlob)
+ IPC_MESSAGE_HANDLER(BlobStorageMsg_MemoryItemResponse, OnMemoryItemResponse)
+ IPC_MESSAGE_HANDLER(BlobStorageMsg_CancelBuildingBlob, OnCancelBuildingBlob)
+ 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_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void BlobDispatcherHost::OnRegisterBlobUUID(
+ const std::string& uuid,
+ const std::string& content_type,
+ const std::string& content_disposition,
+ const std::set<std::string>& referenced_blob_uuids) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ BlobStorageContext* context = this->context();
+ if (uuid.empty() || context->registry().HasEntry(uuid) ||
+ async_builder_.IsBeingBuilt(uuid)) {
+ bad_message::ReceivedBadMessage(this, bad_message::BDH_UUID_REGISTERED);
+ return;
+ }
+ blobs_inuse_map_[uuid] = 1;
+ BlobTransportResult result = async_builder_.RegisterBlobUUID(
+ uuid, content_type, content_disposition, referenced_blob_uuids, context);
+ switch (result) {
+ case BlobTransportResult::BAD_IPC:
+ blobs_inuse_map_.erase(uuid);
+ bad_message::ReceivedBadMessage(this,
+ bad_message::BDH_CONSTRUCTION_FAILED);
+ break;
+ case BlobTransportResult::CANCEL_REFERENCED_BLOB_BROKEN:
+ // The async builder builds the blob as broken, and we just need to send
+ // the cancel message back to the renderer.
+ Send(new BlobStorageMsg_CancelBuildingBlob(
+ uuid, IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN));
+ break;
+ case BlobTransportResult::DONE:
+ break;
+ case BlobTransportResult::CANCEL_MEMORY_FULL:
+ case BlobTransportResult::CANCEL_FILE_ERROR:
+ case BlobTransportResult::CANCEL_UNKNOWN:
+ case BlobTransportResult::PENDING_RESPONSES:
+ NOTREACHED();
+ break;
+ }
+}
+
+void BlobDispatcherHost::OnStartBuildingBlob(
+ const std::string& uuid,
+ const std::vector<storage::DataElement>& descriptions) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (uuid.empty()) {
+ SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
+ return;
+ }
+ BlobStorageContext* context = this->context();
+ const BlobStorageRegistry::Entry* entry = context->registry().GetEntry(uuid);
+ if (!entry || entry->state == BlobStorageRegistry::BlobState::BROKEN) {
+ // We ignore messages for blobs that don't exist to handle the case where
+ // the renderer de-refs a blob that we're still constructing, and there are
+ // no references to that blob. We ignore broken as well, in the case where
+ // we decided to break a blob after RegisterBlobUUID is called.
+ // Second, if the last dereference of the blob happened on a different host,
+ // then we still haven't gotten rid of the 'building' state in the original
+ // host. So we call cancel, and send the message just in case that happens.
+ if (async_builder_.IsBeingBuilt(uuid)) {
+ async_builder_.CancelBuildingBlob(
+ uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING,
+ context);
+ Send(new BlobStorageMsg_CancelBuildingBlob(
+ uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING));
+ }
+ return;
+ }
+ if (!async_builder_.IsBeingBuilt(uuid)) {
+ SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
+ return;
+ }
+ // |this| owns async_builder_ so using base::Unretained(this) is safe.
+ BlobTransportResult result = async_builder_.StartBuildingBlob(
+ uuid, descriptions, context->memory_available(), context,
+ base::Bind(&BlobDispatcherHost::SendMemoryRequest, base::Unretained(this),
+ uuid));
+ SendIPCResponse(uuid, result);
+}
+
+void BlobDispatcherHost::OnMemoryItemResponse(
+ const std::string& uuid,
+ const std::vector<storage::BlobItemBytesResponse>& responses) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (uuid.empty()) {
+ SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
+ return;
+ }
+ BlobStorageContext* context = this->context();
+ const BlobStorageRegistry::Entry* entry = context->registry().GetEntry(uuid);
+ if (!entry || entry->state == BlobStorageRegistry::BlobState::BROKEN) {
+ // We ignore messages for blobs that don't exist to handle the case where
+ // the renderer de-refs a blob that we're still constructing, and there are
+ // no references to that blob. We ignore broken as well, in the case where
+ // we decided to break a blob after sending the memory request.
+ // Note: if a blob is broken, then it can't be in the async_builder.
+ // Second, if the last dereference of the blob happened on a different host,
+ // then we still haven't gotten rid of the 'building' state in the original
+ // host. So we call cancel, and send the message just in case that happens.
+ if (async_builder_.IsBeingBuilt(uuid)) {
+ async_builder_.CancelBuildingBlob(
+ uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING,
+ context);
+ Send(new BlobStorageMsg_CancelBuildingBlob(
+ uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING));
+ }
+ return;
+ }
+ if (!async_builder_.IsBeingBuilt(uuid)) {
+ SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
+ return;
+ }
+ BlobTransportResult result =
+ async_builder_.OnMemoryResponses(uuid, responses, context);
+ SendIPCResponse(uuid, result);
+}
+
+void BlobDispatcherHost::OnCancelBuildingBlob(
+ const std::string& uuid,
+ const storage::IPCBlobCreationCancelCode code) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (uuid.empty()) {
+ SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
+ return;
+ }
+ BlobStorageContext* context = this->context();
+ const BlobStorageRegistry::Entry* entry = context->registry().GetEntry(uuid);
+ if (!entry || entry->state == BlobStorageRegistry::BlobState::BROKEN) {
+ // We ignore messages for blobs that don't exist to handle the case where
+ // the renderer de-refs a blob that we're still constructing, and there are
+ // no references to that blob. We ignore broken as well, in the case where
+ // we decided to break a blob and the renderer also decided to cancel.
+ // Note: if a blob is broken, then it can't be in the async_builder.
+ // Second, if the last dereference of the blob happened on a different host,
+ // then we still haven't gotten rid of the 'building' state in the original
+ // host. So we call cancel just in case this happens.
+ if (async_builder_.IsBeingBuilt(uuid)) {
+ async_builder_.CancelBuildingBlob(
+ uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING,
+ context);
+ }
+ return;
+ }
+ if (!async_builder_.IsBeingBuilt(uuid)) {
+ SendIPCResponse(uuid, BlobTransportResult::BAD_IPC);
+ return;
+ }
+ VLOG(1) << "Blob construction of " << uuid << " cancelled by renderer. "
+ << " Reason: " << static_cast<int>(code) << ".";
+ async_builder_.CancelBuildingBlob(uuid, code, context);
+}
+
+void BlobDispatcherHost::OnIncrementBlobRefCount(const std::string& uuid) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ BlobStorageContext* context = this->context();
+ if (uuid.empty()) {
+ bad_message::ReceivedBadMessage(
+ this, bad_message::BDH_INVALID_REFCOUNT_OPERATION);
+ return;
+ }
+ if (!context->registry().HasEntry(uuid)) {
+ UMA_HISTOGRAM_ENUMERATION("Storage.Blob.InvalidReference", BDH_INCREMENT,
+ BDH_TRACING_ENUM_LAST);
+ return;
+ }
+ context->IncrementBlobRefCount(uuid);
+ blobs_inuse_map_[uuid] += 1;
+}
+
+void BlobDispatcherHost::OnDecrementBlobRefCount(const std::string& uuid) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (uuid.empty()) {
+ bad_message::ReceivedBadMessage(
+ this, bad_message::BDH_INVALID_REFCOUNT_OPERATION);
+ return;
+ }
+ if (!IsInUseInHost(uuid)) {
+ UMA_HISTOGRAM_ENUMERATION("Storage.Blob.InvalidReference", BDH_DECREMENT,
+ BDH_TRACING_ENUM_LAST);
+ return;
+ }
+ BlobStorageContext* context = this->context();
+ context->DecrementBlobRefCount(uuid);
+ blobs_inuse_map_[uuid] -= 1;
+ if (blobs_inuse_map_[uuid] == 0) {
+ blobs_inuse_map_.erase(uuid);
+ // If the blob has been deleted in the context and we're still building it,
+ // this means we have no references waiting to read it. Clear the building
+ // state and send a cancel message to the renderer.
+ if (async_builder_.IsBeingBuilt(uuid) &&
+ !context->registry().HasEntry(uuid)) {
+ async_builder_.CancelBuildingBlob(
+ uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING,
+ context);
+ Send(new BlobStorageMsg_CancelBuildingBlob(
+ uuid, IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING));
+ }
+ }
+}
+
+void BlobDispatcherHost::OnRegisterPublicBlobURL(const GURL& public_url,
+ const std::string& uuid) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ BlobStorageContext* context = this->context();
+ if (uuid.empty()) {
+ bad_message::ReceivedBadMessage(this,
+ bad_message::BDH_INVALID_URL_OPERATION);
+ return;
+ }
+ if (!IsInUseInHost(uuid) || context->registry().IsURLMapped(public_url)) {
+ UMA_HISTOGRAM_ENUMERATION("Storage.Blob.InvalidURLRegister", BDH_INCREMENT,
+ BDH_TRACING_ENUM_LAST);
+ return;
+ }
+ context->RegisterPublicBlobURL(public_url, uuid);
+ public_blob_urls_.insert(public_url);
+}
+
+void BlobDispatcherHost::OnRevokePublicBlobURL(const GURL& public_url) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (!public_url.is_valid()) {
+ bad_message::ReceivedBadMessage(this,
+ bad_message::BDH_INVALID_URL_OPERATION);
+ return;
+ }
+ if (!IsUrlRegisteredInHost(public_url)) {
+ UMA_HISTOGRAM_ENUMERATION("Storage.Blob.InvalidURLRegister", BDH_DECREMENT,
+ BDH_TRACING_ENUM_LAST);
+ return;
+ }
+ context()->RevokePublicBlobURL(public_url);
+ public_blob_urls_.erase(public_url);
+}
+
+storage::BlobStorageContext* BlobDispatcherHost::context() {
+ return blob_storage_context_->context();
+}
+
+void BlobDispatcherHost::SendMemoryRequest(
+ const std::string& uuid,
+ scoped_ptr<std::vector<storage::BlobItemBytesRequest>> requests,
+ scoped_ptr<std::vector<base::SharedMemoryHandle>> memory_handles,
+ scoped_ptr<std::vector<base::File>> files) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ std::vector<IPC::PlatformFileForTransit> file_handles;
+ // TODO(dmurph): Support file-backed blob transportation.
+ DCHECK(files->empty());
+ Send(new BlobStorageMsg_RequestMemoryItem(uuid, *requests, *memory_handles,
+ file_handles));
+}
+
+void BlobDispatcherHost::SendIPCResponse(const std::string& uuid,
+ storage::BlobTransportResult result) {
+ switch (result) {
+ case BlobTransportResult::BAD_IPC:
+ bad_message::ReceivedBadMessage(this,
+ bad_message::BDH_CONSTRUCTION_FAILED);
+ return;
+ case BlobTransportResult::CANCEL_MEMORY_FULL:
+ Send(new BlobStorageMsg_CancelBuildingBlob(
+ uuid, IPCBlobCreationCancelCode::OUT_OF_MEMORY));
+ return;
+ case BlobTransportResult::CANCEL_FILE_ERROR:
+ Send(new BlobStorageMsg_CancelBuildingBlob(
+ uuid, IPCBlobCreationCancelCode::FILE_WRITE_FAILED));
+ return;
+ case BlobTransportResult::CANCEL_REFERENCED_BLOB_BROKEN:
+ Send(new BlobStorageMsg_CancelBuildingBlob(
+ uuid, IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN));
+ return;
+ case BlobTransportResult::CANCEL_UNKNOWN:
+ Send(new BlobStorageMsg_CancelBuildingBlob(
+ uuid, IPCBlobCreationCancelCode::UNKNOWN));
+ return;
+ case BlobTransportResult::PENDING_RESPONSES:
+ return;
+ case BlobTransportResult::DONE:
+ Send(new BlobStorageMsg_DoneBuildingBlob(uuid));
+ return;
+ }
+ NOTREACHED();
+}
+
+bool BlobDispatcherHost::IsInUseInHost(const std::string& uuid) {
+ return blobs_inuse_map_.find(uuid) != blobs_inuse_map_.end();
+}
+
+bool BlobDispatcherHost::IsUrlRegisteredInHost(const GURL& blob_url) {
+ return public_blob_urls_.find(blob_url) != public_blob_urls_.end();
+}
+
+void BlobDispatcherHost::ClearHostFromBlobStorageContext() {
+ BlobStorageContext* context = this->context();
+ for (const auto& url : public_blob_urls_) {
+ context->RevokePublicBlobURL(url);
+ }
+ for (const auto& uuid_refnum_pair : blobs_inuse_map_) {
+ for (int i = 0; i < uuid_refnum_pair.second; ++i)
+ context->DecrementBlobRefCount(uuid_refnum_pair.first);
+ }
+ async_builder_.CancelAll(context);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/blob_storage/blob_dispatcher_host.h b/chromium/content/browser/blob_storage/blob_dispatcher_host.h
new file mode 100644
index 00000000000..bf1a03cf8fb
--- /dev/null
+++ b/chromium/content/browser/blob_storage/blob_dispatcher_host.h
@@ -0,0 +1,148 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_BLOB_STORAGE_BLOB_DISPATCHER_HOST_H_
+#define CONTENT_BROWSER_BLOB_STORAGE_BLOB_DISPATCHER_HOST_H_
+
+#include <set>
+#include <string>
+#include <vector>
+
+#include "base/files/file.h"
+#include "base/gtest_prod_util.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/shared_memory_handle.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/browser_message_filter.h"
+#include "storage/browser/blob/blob_async_builder_host.h"
+#include "storage/browser/blob/blob_transport_result.h"
+#include "storage/common/blob_storage/blob_storage_constants.h"
+
+class GURL;
+
+namespace IPC {
+class Sender;
+}
+
+namespace storage {
+class DataElement;
+class BlobDataBuilder;
+struct BlobItemBytesRequest;
+struct BlobItemBytesResponse;
+class BlobStorageContext;
+}
+
+namespace content {
+class ChromeBlobStorageContext;
+
+// This class's responsibility is to listen for and dispatch blob storage
+// messages and handle logistics of blob storage for a single child process.
+// When the child process terminates all blob references attributable to
+// that process go away upon destruction of the instance.
+// This lives in the browser process, is single threaded (IO thread), and there
+// is one per child process.
+class CONTENT_EXPORT BlobDispatcherHost : public BrowserMessageFilter {
+ public:
+ explicit BlobDispatcherHost(ChromeBlobStorageContext* blob_storage_context);
+
+ // BrowserMessageFilter implementation.
+ void OnChannelClosing() override;
+ bool OnMessageReceived(const IPC::Message& message) override;
+
+ protected:
+ ~BlobDispatcherHost() override;
+
+ // For testing use only.
+ void SetMemoryConstantsForTesting(size_t max_ipc_memory_size,
+ size_t max_shared_memory_size,
+ uint64_t max_file_size) {
+ async_builder_.SetMemoryConstantsForTesting(
+ max_ipc_memory_size, max_shared_memory_size, max_file_size);
+ }
+
+ private:
+ friend class base::RefCountedThreadSafe<BlobDispatcherHost>;
+ friend class BlobDispatcherHostTest;
+ FRIEND_TEST_ALL_PREFIXES(BlobDispatcherHostTest, EmptyUUIDs);
+ FRIEND_TEST_ALL_PREFIXES(BlobDispatcherHostTest, MultipleTransfers);
+ FRIEND_TEST_ALL_PREFIXES(BlobDispatcherHostTest, SharedMemoryTransfer);
+ FRIEND_TEST_ALL_PREFIXES(BlobDispatcherHostTest, OnCancelBuildingBlob);
+ FRIEND_TEST_ALL_PREFIXES(BlobDispatcherHostTest,
+ BlobReferenceWhileConstructing);
+ FRIEND_TEST_ALL_PREFIXES(BlobDispatcherHostTest,
+ BlobReferenceWhileShortcutConstructing);
+ FRIEND_TEST_ALL_PREFIXES(BlobDispatcherHostTest,
+ BlobReferenceWhileConstructingCancelled);
+ FRIEND_TEST_ALL_PREFIXES(BlobDispatcherHostTest, DecrementRefAfterRegister);
+ FRIEND_TEST_ALL_PREFIXES(BlobDispatcherHostTest, DecrementRefAfterOnStart);
+ FRIEND_TEST_ALL_PREFIXES(BlobDispatcherHostTest,
+ DecrementRefAfterOnStartWithHandle);
+ FRIEND_TEST_ALL_PREFIXES(BlobDispatcherHostTest,
+ HostDisconnectAfterRegisterWithHandle);
+ FRIEND_TEST_ALL_PREFIXES(BlobDispatcherHostTest, HostDisconnectAfterOnStart);
+ FRIEND_TEST_ALL_PREFIXES(BlobDispatcherHostTest,
+ HostDisconnectAfterOnMemoryResponse);
+ FRIEND_TEST_ALL_PREFIXES(BlobDispatcherHostTest,
+ CreateBlobWithBrokenReference);
+ FRIEND_TEST_ALL_PREFIXES(BlobDispatcherHostTest,
+ DeferenceBlobOnDifferentHost);
+ FRIEND_TEST_ALL_PREFIXES(BlobDispatcherHostTest, BuildingReferenceChain);
+ FRIEND_TEST_ALL_PREFIXES(BlobDispatcherHostTest,
+ BuildingReferenceChainWithCancel);
+ FRIEND_TEST_ALL_PREFIXES(BlobDispatcherHostTest,
+ BuildingReferenceChainWithSourceDeath);
+
+ typedef std::map<std::string, int> BlobReferenceMap;
+
+ void OnRegisterBlobUUID(const std::string& uuid,
+ const std::string& content_type,
+ const std::string& content_disposition,
+ const std::set<std::string>& referenced_blob_uuids);
+ void OnStartBuildingBlob(
+ const std::string& uuid,
+ const std::vector<storage::DataElement>& descriptions);
+ void OnMemoryItemResponse(
+ const std::string& uuid,
+ const std::vector<storage::BlobItemBytesResponse>& response);
+ void OnCancelBuildingBlob(const std::string& uuid,
+ const storage::IPCBlobCreationCancelCode code);
+
+ 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);
+
+ storage::BlobStorageContext* context();
+
+ void SendMemoryRequest(
+ const std::string& uuid,
+ scoped_ptr<std::vector<storage::BlobItemBytesRequest>> requests,
+ scoped_ptr<std::vector<base::SharedMemoryHandle>> memory_handles,
+ scoped_ptr<std::vector<base::File>> files);
+
+ // Send the appropriate IPC response to the renderer for the given result.
+ void SendIPCResponse(const std::string& uuid,
+ storage::BlobTransportResult result);
+
+ bool IsInUseInHost(const std::string& uuid);
+ bool IsUrlRegisteredInHost(const GURL& blob_url);
+
+ // Unregisters all blobs and urls that were registered in this host.
+ void ClearHostFromBlobStorageContext();
+
+ // Collection of blob ids and a count of how many usages
+ // of that id are attributable to this consumer.
+ BlobReferenceMap blobs_inuse_map_;
+
+ // The set of public blob urls coined by this consumer.
+ std::set<GURL> public_blob_urls_;
+
+ scoped_refptr<ChromeBlobStorageContext> blob_storage_context_;
+ storage::BlobAsyncBuilderHost async_builder_;
+
+ DISALLOW_COPY_AND_ASSIGN(BlobDispatcherHost);
+};
+} // namespace content
+#endif // CONTENT_BROWSER_BLOB_STORAGE_BLOB_DISPATCHER_HOST_H_
diff --git a/chromium/content/browser/blob_storage/blob_dispatcher_host_unittest.cc b/chromium/content/browser/blob_storage/blob_dispatcher_host_unittest.cc
new file mode 100644
index 00000000000..43cdf8ad373
--- /dev/null
+++ b/chromium/content/browser/blob_storage/blob_dispatcher_host_unittest.cc
@@ -0,0 +1,1199 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/blob_storage/blob_dispatcher_host.h"
+
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/memory/shared_memory.h"
+#include "base/run_loop.h"
+#include "base/tuple.h"
+#include "content/browser/fileapi/chrome_blob_storage_context.h"
+#include "content/common/fileapi/webblob_messages.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "ipc/ipc_sender.h"
+#include "ipc/ipc_test_sink.h"
+#include "ipc/message_filter.h"
+#include "storage/browser/blob/blob_data_builder.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_storage_context.h"
+#include "storage/common/blob_storage/blob_item_bytes_request.h"
+#include "storage/common/blob_storage/blob_item_bytes_response.h"
+#include "storage/common/data_element.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using storage::BlobDataBuilder;
+using storage::BlobDataHandle;
+using storage::BlobItemBytesRequest;
+using storage::BlobItemBytesResponse;
+using storage::BlobStorageContext;
+using storage::BlobTransportResult;
+using storage::DataElement;
+using storage::IPCBlobCreationCancelCode;
+using RequestMemoryCallback =
+ storage::BlobAsyncBuilderHost::RequestMemoryCallback;
+
+namespace content {
+namespace {
+
+const char kContentType[] = "text/plain";
+const char kContentDisposition[] = "content_disposition";
+const char kData[] = "data!!";
+const size_t kDataSize = 6;
+
+const size_t kTestBlobStorageIPCThresholdBytes = 20;
+const size_t kTestBlobStorageMaxSharedMemoryBytes = 50;
+const uint64_t kTestBlobStorageMaxFileSizeBytes = 100;
+
+void ConstructionCompletePopulator(bool* succeeded_pointer,
+ IPCBlobCreationCancelCode* reason_pointer,
+ bool succeeded,
+ IPCBlobCreationCancelCode reason) {
+ *succeeded_pointer = succeeded;
+ *reason_pointer = reason;
+}
+
+class TestableBlobDispatcherHost : public BlobDispatcherHost {
+ public:
+ TestableBlobDispatcherHost(ChromeBlobStorageContext* blob_storage_context,
+ IPC::TestSink* sink)
+ : BlobDispatcherHost(blob_storage_context), sink_(sink) {
+ this->SetMemoryConstantsForTesting(kTestBlobStorageIPCThresholdBytes,
+ kTestBlobStorageMaxSharedMemoryBytes,
+ kTestBlobStorageMaxFileSizeBytes);
+ }
+
+ bool Send(IPC::Message* message) override { return sink_->Send(message); }
+
+ void ShutdownForBadMessage() override { shutdown_for_bad_message_ = true; }
+
+ bool shutdown_for_bad_message_ = false;
+
+ protected:
+ ~TestableBlobDispatcherHost() override {}
+
+ private:
+ friend class base::RefCountedThreadSafe<TestableBlobDispatcherHost>;
+
+ IPC::TestSink* sink_;
+};
+
+} // namespace
+
+class BlobDispatcherHostTest : public testing::Test {
+ protected:
+ BlobDispatcherHostTest()
+ : chrome_blob_storage_context_(
+ ChromeBlobStorageContext::GetFor(&browser_context_)) {
+ host_ =
+ new TestableBlobDispatcherHost(chrome_blob_storage_context_, &sink_);
+ }
+ ~BlobDispatcherHostTest() override {}
+
+ void SetUp() override {
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ if (!command_line->HasSwitch(switches::kDisableKillAfterBadIPC)) {
+ command_line->AppendSwitch(switches::kDisableKillAfterBadIPC);
+ }
+ // We run the run loop to initialize the chrome blob storage context.
+ base::RunLoop().RunUntilIdle();
+ context_ = chrome_blob_storage_context_->context();
+ DCHECK(context_);
+ }
+
+ void ExpectBlobNotExist(const std::string& id) {
+ EXPECT_FALSE(context_->registry().HasEntry(id));
+ EXPECT_FALSE(host_->IsInUseInHost(id));
+ EXPECT_FALSE(IsBeingBuiltInHost(id));
+ }
+
+ void AsyncShortcutBlobTransfer(const std::string& id) {
+ sink_.ClearMessages();
+ ExpectBlobNotExist(id);
+ host_->OnRegisterBlobUUID(id, std::string(kContentType),
+ std::string(kContentDisposition),
+ std::set<std::string>());
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+ DataElement element;
+ element.SetToBytes(kData, kDataSize);
+ std::vector<DataElement> elements = {element};
+ host_->OnStartBuildingBlob(id, elements);
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+ ExpectDone(id);
+ sink_.ClearMessages();
+ }
+
+ void AsyncBlobTransfer(const std::string& id) {
+ sink_.ClearMessages();
+ ExpectBlobNotExist(id);
+ host_->OnRegisterBlobUUID(id, std::string(kContentType),
+ std::string(kContentDisposition),
+ std::set<std::string>());
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+ DataElement element;
+ element.SetToBytesDescription(kDataSize);
+ std::vector<DataElement> elements = {element};
+ host_->OnStartBuildingBlob(id, elements);
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+
+ // Expect our request.
+ std::vector<BlobItemBytesRequest> expected_requests = {
+ BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize)};
+ ExpectRequest(id, expected_requests);
+ sink_.ClearMessages();
+
+ // Send results;
+ BlobItemBytesResponse response(0);
+ std::memcpy(response.allocate_mutable_data(kDataSize), kData, kDataSize);
+ std::vector<BlobItemBytesResponse> responses = {response};
+ host_->OnMemoryItemResponse(id, responses);
+ ExpectDone(id);
+ sink_.ClearMessages();
+ }
+
+ void ExpectAndResetBadMessage() {
+ EXPECT_TRUE(host_->shutdown_for_bad_message_);
+ host_->shutdown_for_bad_message_ = false;
+ }
+
+ void ExpectHandleEqualsData(BlobDataHandle* handle,
+ const std::vector<DataElement>& data) {
+ scoped_ptr<storage::BlobDataSnapshot> snapshot = handle->CreateSnapshot();
+ EXPECT_FALSE(handle->IsBeingBuilt());
+ for (size_t i = 0; i < data.size(); i++) {
+ const DataElement& expected = data[i];
+ const DataElement& actual = snapshot->items()[i]->data_element();
+ EXPECT_EQ(expected, actual);
+ }
+ EXPECT_EQ(data.size(), snapshot->items().size());
+ }
+
+ void ExpectRequest(
+ const std::string& expected_uuid,
+ const std::vector<BlobItemBytesRequest>& expected_requests) {
+ EXPECT_FALSE(
+ sink_.GetFirstMessageMatching(BlobStorageMsg_DoneBuildingBlob::ID));
+ EXPECT_FALSE(
+ sink_.GetFirstMessageMatching(BlobStorageMsg_CancelBuildingBlob::ID));
+ const IPC::Message* message =
+ sink_.GetUniqueMessageMatching(BlobStorageMsg_RequestMemoryItem::ID);
+ ASSERT_TRUE(message);
+ base::Tuple<std::string, std::vector<storage::BlobItemBytesRequest>,
+ std::vector<base::SharedMemoryHandle>,
+ std::vector<IPC::PlatformFileForTransit>>
+ args;
+ BlobStorageMsg_RequestMemoryItem::Read(message, &args);
+ EXPECT_EQ(expected_uuid, base::get<0>(args));
+ std::vector<BlobItemBytesRequest> requests = base::get<1>(args);
+ ASSERT_EQ(requests.size(), expected_requests.size());
+ for (size_t i = 0; i < expected_requests.size(); ++i) {
+ EXPECT_EQ(expected_requests[i], requests[i]);
+ }
+ }
+
+ void ExpectRequestWithSharedMemoryHandles(
+ const std::string& expected_uuid,
+ const std::vector<BlobItemBytesRequest>& expected_requests,
+ std::vector<base::SharedMemoryHandle>* shared_memory_handles) {
+ EXPECT_FALSE(
+ sink_.GetFirstMessageMatching(BlobStorageMsg_DoneBuildingBlob::ID));
+ EXPECT_FALSE(
+ sink_.GetFirstMessageMatching(BlobStorageMsg_CancelBuildingBlob::ID));
+ const IPC::Message* message =
+ sink_.GetUniqueMessageMatching(BlobStorageMsg_RequestMemoryItem::ID);
+ ASSERT_TRUE(message);
+ base::Tuple<std::string, std::vector<storage::BlobItemBytesRequest>,
+ std::vector<base::SharedMemoryHandle>,
+ std::vector<IPC::PlatformFileForTransit>>
+ args;
+ BlobStorageMsg_RequestMemoryItem::Read(message, &args);
+ EXPECT_EQ(expected_uuid, base::get<0>(args));
+ std::vector<BlobItemBytesRequest> requests = base::get<1>(args);
+ ASSERT_EQ(requests.size(), expected_requests.size());
+ for (size_t i = 0; i < expected_requests.size(); ++i) {
+ EXPECT_EQ(expected_requests[i], requests[i]);
+ }
+ *shared_memory_handles = std::move(base::get<2>(args));
+ }
+
+ void ExpectCancel(const std::string& expected_uuid,
+ IPCBlobCreationCancelCode code) {
+ EXPECT_FALSE(
+ sink_.GetFirstMessageMatching(BlobStorageMsg_RequestMemoryItem::ID));
+ EXPECT_FALSE(
+ sink_.GetFirstMessageMatching(BlobStorageMsg_DoneBuildingBlob::ID));
+ const IPC::Message* message =
+ sink_.GetUniqueMessageMatching(BlobStorageMsg_CancelBuildingBlob::ID);
+ ASSERT_TRUE(message);
+ base::Tuple<std::string, IPCBlobCreationCancelCode> args;
+ BlobStorageMsg_CancelBuildingBlob::Read(message, &args);
+ EXPECT_EQ(expected_uuid, base::get<0>(args));
+ EXPECT_EQ(code, base::get<1>(args));
+ }
+
+ void ExpectDone(const std::string& expected_uuid) {
+ EXPECT_FALSE(
+ sink_.GetFirstMessageMatching(BlobStorageMsg_RequestMemoryItem::ID));
+ EXPECT_FALSE(
+ sink_.GetFirstMessageMatching(BlobStorageMsg_CancelBuildingBlob::ID));
+ const IPC::Message* message =
+ sink_.GetUniqueMessageMatching(BlobStorageMsg_DoneBuildingBlob::ID);
+ base::Tuple<std::string> args;
+ BlobStorageMsg_DoneBuildingBlob::Read(message, &args);
+ EXPECT_EQ(expected_uuid, base::get<0>(args));
+ }
+
+ bool IsBeingBuiltInHost(const std::string& uuid) {
+ return host_->async_builder_.IsBeingBuilt(uuid);
+ }
+
+ IPC::TestSink sink_;
+ TestBrowserThreadBundle browser_thread_bundle_;
+ TestBrowserContext browser_context_;
+ ChromeBlobStorageContext* chrome_blob_storage_context_;
+ BlobStorageContext* context_ = nullptr;
+ scoped_refptr<TestableBlobDispatcherHost> host_;
+};
+
+TEST_F(BlobDispatcherHostTest, EmptyUUIDs) {
+ host_->OnRegisterBlobUUID("", "", "", std::set<std::string>());
+ ExpectAndResetBadMessage();
+ host_->OnStartBuildingBlob("", std::vector<DataElement>());
+ ExpectAndResetBadMessage();
+ host_->OnMemoryItemResponse("", std::vector<BlobItemBytesResponse>());
+ ExpectAndResetBadMessage();
+ host_->OnCancelBuildingBlob("", IPCBlobCreationCancelCode::UNKNOWN);
+ ExpectAndResetBadMessage();
+}
+
+TEST_F(BlobDispatcherHostTest, Shortcut) {
+ const std::string kId = "uuid1";
+ AsyncShortcutBlobTransfer(kId);
+ EXPECT_TRUE(context_->registry().HasEntry(kId));
+ scoped_ptr<BlobDataHandle> handle = context_->GetBlobDataFromUUID(kId);
+ EXPECT_TRUE(handle);
+
+ DataElement expected;
+ expected.SetToBytes(kData, kDataSize);
+ std::vector<DataElement> elements = {expected};
+ ExpectHandleEqualsData(handle.get(), elements);
+}
+
+TEST_F(BlobDispatcherHostTest, RegularTransfer) {
+ const std::string kId = "uuid1";
+ AsyncBlobTransfer(kId);
+ EXPECT_TRUE(context_->registry().HasEntry(kId));
+ scoped_ptr<BlobDataHandle> handle = context_->GetBlobDataFromUUID(kId);
+ EXPECT_TRUE(handle);
+
+ DataElement expected;
+ expected.SetToBytes(kData, kDataSize);
+ std::vector<DataElement> elements = {expected};
+ ExpectHandleEqualsData(handle.get(), elements);
+}
+
+TEST_F(BlobDispatcherHostTest, MultipleTransfers) {
+ const std::string kId = "uuid";
+ const int kNumIters = 10;
+ for (int i = 0; i < kNumIters; i++) {
+ std::string id = kId;
+ id += ('0' + i);
+ ExpectBlobNotExist(id);
+ host_->OnRegisterBlobUUID(id, std::string(kContentType),
+ std::string(kContentDisposition),
+ std::set<std::string>());
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+ }
+ sink_.ClearMessages();
+ for (int i = 0; i < kNumIters; i++) {
+ std::string id = kId;
+ id += ('0' + i);
+ DataElement element;
+ element.SetToBytesDescription(kDataSize);
+ std::vector<DataElement> elements = {element};
+ host_->OnStartBuildingBlob(id, elements);
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+ // Expect our request.
+ std::vector<BlobItemBytesRequest> expected_requests = {
+ BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize)};
+ ExpectRequest(id, expected_requests);
+ sink_.ClearMessages();
+ }
+ for (int i = 0; i < kNumIters; i++) {
+ std::string id = kId;
+ id += ('0' + i);
+ // Send results;
+ BlobItemBytesResponse response(0);
+ std::memcpy(response.allocate_mutable_data(kDataSize), kData, kDataSize);
+ std::vector<BlobItemBytesResponse> responses = {response};
+ host_->OnMemoryItemResponse(id, responses);
+ ExpectDone(id);
+ sink_.ClearMessages();
+ }
+}
+
+TEST_F(BlobDispatcherHostTest, SharedMemoryTransfer) {
+ const std::string kId = "uuid1";
+ const size_t kLargeSize = kTestBlobStorageMaxSharedMemoryBytes * 2;
+ std::vector<base::SharedMemoryHandle> shared_memory_handles;
+
+ ExpectBlobNotExist(kId);
+ host_->OnRegisterBlobUUID(kId, std::string(kContentType),
+ std::string(kContentDisposition),
+ std::set<std::string>());
+
+ // Grab the handle.
+ scoped_ptr<BlobDataHandle> blob_data_handle =
+ context_->GetBlobDataFromUUID(kId);
+ bool built = false;
+ IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN;
+ blob_data_handle->RunOnConstructionComplete(
+ base::Bind(&ConstructionCompletePopulator, &built, &error_code));
+ EXPECT_FALSE(built);
+
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+ DataElement element;
+ element.SetToBytesDescription(kLargeSize);
+ std::vector<DataElement> elements = {element};
+ host_->OnStartBuildingBlob(kId, elements);
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+
+ // Expect our first request.
+ std::vector<BlobItemBytesRequest> expected_requests = {
+ BlobItemBytesRequest::CreateSharedMemoryRequest(
+ 0 /* request_number */, 0 /* renderer_item_index */,
+ 0 /* renderer_item_offset */,
+ static_cast<uint64_t>(
+ kTestBlobStorageMaxSharedMemoryBytes) /* size */,
+ 0 /* handle_index */, 0 /* handle_offset */)};
+ ExpectRequestWithSharedMemoryHandles(kId, expected_requests,
+ &shared_memory_handles);
+ sink_.ClearMessages();
+
+ // Populate the shared memory.
+ EXPECT_EQ(1u, shared_memory_handles.size());
+ EXPECT_TRUE(base::SharedMemory::IsHandleValid(shared_memory_handles[0]));
+ {
+ base::SharedMemory memory(
+ base::SharedMemory::DuplicateHandle(shared_memory_handles[0]), false);
+ memory.Map(kTestBlobStorageMaxSharedMemoryBytes);
+ std::memset(memory.memory(), 'X', kTestBlobStorageMaxSharedMemoryBytes);
+ memory.Close();
+ }
+
+ // Send the confirmation.
+ std::vector<BlobItemBytesResponse> responses = {BlobItemBytesResponse(0)};
+ host_->OnMemoryItemResponse(kId, responses);
+
+ // Expect our second request.
+ expected_requests = {BlobItemBytesRequest::CreateSharedMemoryRequest(
+ 1 /* request_number */, 0 /* renderer_item_index */,
+ static_cast<uint64_t>(
+ kTestBlobStorageMaxSharedMemoryBytes) /* renderer_item_offset */,
+ static_cast<uint64_t>(kTestBlobStorageMaxSharedMemoryBytes) /* size */,
+ 0 /* handle_index */, 0 /* handle_offset */)};
+ ExpectRequestWithSharedMemoryHandles(kId, expected_requests,
+ &shared_memory_handles);
+ sink_.ClearMessages();
+
+ // Populate the shared memory.
+ EXPECT_EQ(1u, shared_memory_handles.size());
+ EXPECT_TRUE(base::SharedMemory::IsHandleValid(shared_memory_handles[0]));
+ {
+ base::SharedMemory memory(
+ base::SharedMemory::DuplicateHandle(shared_memory_handles[0]), false);
+ memory.Map(kTestBlobStorageMaxSharedMemoryBytes);
+ std::memset(memory.memory(), 'Z', kTestBlobStorageMaxSharedMemoryBytes);
+ memory.Close();
+ }
+ // Send the confirmation.
+ responses = {BlobItemBytesResponse(1)};
+ host_->OnMemoryItemResponse(kId, responses);
+
+ ExpectDone(kId);
+ sink_.ClearMessages();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(built) << "Error code: " << static_cast<int>(error_code);
+ EXPECT_TRUE(context_->registry().HasEntry(kId));
+ scoped_ptr<BlobDataHandle> handle = context_->GetBlobDataFromUUID(kId);
+ EXPECT_TRUE(handle);
+
+ DataElement expected;
+ expected.SetToAllocatedBytes(kLargeSize / 2);
+ std::memset(expected.mutable_bytes(), 'X', kLargeSize / 2);
+ elements = {expected};
+ std::memset(expected.mutable_bytes(), 'Z', kLargeSize / 2);
+ elements.push_back(expected);
+ ExpectHandleEqualsData(handle.get(), elements);
+}
+
+TEST_F(BlobDispatcherHostTest, OnCancelBuildingBlob) {
+ const std::string kId("id");
+ // We ignore blobs that are unknown, as it could have been cancelled earlier
+ // and the renderer didn't know about it yet.
+ host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN);
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+
+ // Start building blob.
+ host_->OnRegisterBlobUUID(kId, std::string(kContentType),
+ std::string(kContentDisposition),
+ std::set<std::string>());
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+ DataElement element;
+ element.SetToBytesDescription(kDataSize);
+ std::vector<DataElement> elements = {element};
+ host_->OnStartBuildingBlob(kId, elements);
+ // It should have requested memory here.
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+ sink_.ClearMessages();
+
+ // Cancel in middle of construction.
+ host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN);
+ EXPECT_TRUE(context_->registry().HasEntry(kId));
+ EXPECT_TRUE(host_->IsInUseInHost(kId));
+ EXPECT_FALSE(IsBeingBuiltInHost(kId));
+ // Check that's it's broken.
+ scoped_ptr<BlobDataHandle> handle = context_->GetBlobDataFromUUID(kId);
+ EXPECT_TRUE(handle->IsBroken());
+ handle.reset();
+ base::RunLoop().RunUntilIdle();
+
+ // Get rid of it in the host.
+ host_->OnDecrementBlobRefCount(kId);
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+ ExpectBlobNotExist(kId);
+
+ // Create blob again to verify we don't have any old construction state lying
+ // around.
+ AsyncBlobTransfer(kId);
+
+ // Check data.
+ handle = context_->GetBlobDataFromUUID(kId);
+ EXPECT_TRUE(handle);
+ DataElement expected;
+ expected.SetToBytes(kData, kDataSize);
+ std::vector<DataElement> expecteds = {expected};
+ ExpectHandleEqualsData(handle.get(), expecteds);
+
+ // Verify we can't cancel after the fact.
+ host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN);
+ ExpectAndResetBadMessage();
+}
+
+TEST_F(BlobDispatcherHostTest, BlobDataWithHostDeletion) {
+ // Build up a basic blob.
+ const std::string kId("id");
+ AsyncShortcutBlobTransfer(kId);
+ scoped_ptr<BlobDataHandle> handle = context_->GetBlobDataFromUUID(kId);
+ EXPECT_TRUE(handle);
+
+ // Kill the host.
+ host_ = nullptr;
+ base::RunLoop().RunUntilIdle();
+ // Should still be there due to the handle.
+ scoped_ptr<BlobDataHandle> another_handle =
+ context_->GetBlobDataFromUUID(kId);
+ EXPECT_TRUE(another_handle);
+
+ // Should disappear after dropping both handles.
+ handle.reset();
+ another_handle.reset();
+ base::RunLoop().RunUntilIdle();
+
+ handle = context_->GetBlobDataFromUUID(kId);
+ EXPECT_FALSE(handle);
+}
+
+TEST_F(BlobDispatcherHostTest, BlobReferenceWhileConstructing) {
+ const std::string kId("id");
+
+ // Start building blob.
+ host_->OnRegisterBlobUUID(kId, std::string(kContentType),
+ std::string(kContentDisposition),
+ std::set<std::string>());
+
+ // Grab the handle.
+ scoped_ptr<BlobDataHandle> blob_data_handle =
+ context_->GetBlobDataFromUUID(kId);
+ EXPECT_TRUE(blob_data_handle);
+ EXPECT_TRUE(blob_data_handle->IsBeingBuilt());
+ bool built = false;
+ IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN;
+ blob_data_handle->RunOnConstructionComplete(
+ base::Bind(&ConstructionCompletePopulator, &built, &error_code));
+
+ // Continue building.
+ DataElement element;
+ element.SetToBytesDescription(kDataSize);
+ std::vector<DataElement> elements = {element};
+ host_->OnStartBuildingBlob(kId, elements);
+ sink_.ClearMessages();
+
+ // Send data.
+ BlobItemBytesResponse response(0);
+ std::memcpy(response.allocate_mutable_data(kDataSize), kData, kDataSize);
+ std::vector<BlobItemBytesResponse> responses = {response};
+ sink_.ClearMessages();
+ host_->OnMemoryItemResponse(kId, responses);
+
+ ExpectDone(kId);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(built) << "Error code: " << static_cast<int>(error_code);
+}
+
+TEST_F(BlobDispatcherHostTest, BlobReferenceWhileShortcutConstructing) {
+ const std::string kId("id");
+
+ // Start building blob.
+ host_->OnRegisterBlobUUID(kId, std::string(kContentType),
+ std::string(kContentDisposition),
+ std::set<std::string>());
+
+ // Grab the handle.
+ scoped_ptr<BlobDataHandle> blob_data_handle =
+ context_->GetBlobDataFromUUID(kId);
+ EXPECT_TRUE(blob_data_handle);
+ EXPECT_TRUE(blob_data_handle->IsBeingBuilt());
+ bool built = false;
+ IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN;
+ blob_data_handle->RunOnConstructionComplete(
+ base::Bind(&ConstructionCompletePopulator, &built, &error_code));
+
+ // Continue building.
+ DataElement element;
+ element.SetToBytes(kData, kDataSize);
+ std::vector<DataElement> elements = {element};
+ host_->OnStartBuildingBlob(kId, elements);
+ ExpectDone(kId);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(built) << "Error code: " << static_cast<int>(error_code);
+}
+
+TEST_F(BlobDispatcherHostTest, BlobReferenceWhileConstructingCancelled) {
+ const std::string kId("id");
+
+ // Start building blob.
+ host_->OnRegisterBlobUUID(kId, std::string(kContentType),
+ std::string(kContentDisposition),
+ std::set<std::string>());
+
+ // Grab the handle.
+ scoped_ptr<BlobDataHandle> blob_data_handle =
+ context_->GetBlobDataFromUUID(kId);
+ EXPECT_TRUE(blob_data_handle);
+ EXPECT_TRUE(blob_data_handle->IsBeingBuilt());
+ bool built = true;
+ IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN;
+ blob_data_handle->RunOnConstructionComplete(
+ base::Bind(&ConstructionCompletePopulator, &built, &error_code));
+
+ // Cancel in middle of construction.
+ host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(context_->registry().HasEntry(kId));
+ EXPECT_TRUE(host_->IsInUseInHost(kId));
+ EXPECT_FALSE(IsBeingBuiltInHost(kId));
+ EXPECT_TRUE(blob_data_handle->IsBroken());
+ EXPECT_FALSE(built);
+ EXPECT_EQ(IPCBlobCreationCancelCode::UNKNOWN, error_code);
+ error_code = IPCBlobCreationCancelCode::UNKNOWN;
+ built = true;
+ blob_data_handle->RunOnConstructionComplete(
+ base::Bind(&ConstructionCompletePopulator, &built, &error_code));
+ EXPECT_FALSE(built);
+ EXPECT_EQ(IPCBlobCreationCancelCode::UNKNOWN, error_code);
+
+ // Remove it.
+ blob_data_handle.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(context_->registry().HasEntry(kId));
+ host_->OnDecrementBlobRefCount(kId);
+ ExpectBlobNotExist(kId);
+}
+
+TEST_F(BlobDispatcherHostTest, DecrementRefAfterRegister) {
+ const std::string kId("id");
+ // Decrement the refcount while building (renderer blob gc'd before
+ // construction was completed).
+ host_->OnRegisterBlobUUID(kId, std::string(kContentType),
+ std::string(kContentDisposition),
+ std::set<std::string>());
+ EXPECT_TRUE(context_->registry().HasEntry(kId));
+ host_->OnDecrementBlobRefCount(kId);
+ EXPECT_FALSE(context_->registry().HasEntry(kId));
+ EXPECT_FALSE(IsBeingBuiltInHost(kId));
+ ExpectCancel(kId,
+ IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING);
+ sink_.ClearMessages();
+
+ // Do the same, but this time grab a handle before we decrement.
+ host_->OnRegisterBlobUUID(kId, std::string(kContentType),
+ std::string(kContentDisposition),
+ std::set<std::string>());
+ scoped_ptr<BlobDataHandle> blob_data_handle =
+ context_->GetBlobDataFromUUID(kId);
+ host_->OnDecrementBlobRefCount(kId);
+ EXPECT_TRUE(context_->registry().HasEntry(kId));
+ EXPECT_TRUE(IsBeingBuiltInHost(kId));
+
+ // Finish up the blob, and verify we got the done message.
+ DataElement element;
+ element.SetToBytes(kData, kDataSize);
+ std::vector<DataElement> elements = {element};
+ host_->OnStartBuildingBlob(kId, elements);
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+ ExpectDone(kId);
+ sink_.ClearMessages();
+ // Get rid of the handle, and verify it's gone.
+ blob_data_handle.reset();
+ base::RunLoop().RunUntilIdle();
+ // Check that it's no longer around.
+ EXPECT_FALSE(context_->registry().HasEntry(kId));
+ EXPECT_FALSE(IsBeingBuiltInHost(kId));
+}
+
+TEST_F(BlobDispatcherHostTest, DecrementRefAfterOnStart) {
+ const std::string kId("id");
+
+ // Decrement the refcount while building, after we call OnStartBuildlingBlob.
+ host_->OnRegisterBlobUUID(kId, std::string(kContentType),
+ std::string(kContentDisposition),
+ std::set<std::string>());
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+ DataElement element;
+ element.SetToBytesDescription(kDataSize);
+ std::vector<DataElement> elements = {element};
+ host_->OnStartBuildingBlob(kId, elements);
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+
+ std::vector<BlobItemBytesRequest> expected_requests = {
+ BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize)};
+ ExpectRequest(kId, expected_requests);
+ sink_.ClearMessages();
+ EXPECT_TRUE(context_->registry().HasEntry(kId));
+ host_->OnDecrementBlobRefCount(kId);
+ EXPECT_FALSE(context_->registry().HasEntry(kId));
+ EXPECT_FALSE(IsBeingBuiltInHost(kId));
+ ExpectCancel(kId,
+ IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING);
+ sink_.ClearMessages();
+
+ // Do the same, but this time grab a handle to keep it alive.
+ host_->OnRegisterBlobUUID(kId, std::string(kContentType),
+ std::string(kContentDisposition),
+ std::set<std::string>());
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+ host_->OnStartBuildingBlob(kId, elements);
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+ ExpectRequest(kId, expected_requests);
+ sink_.ClearMessages();
+ EXPECT_TRUE(context_->registry().HasEntry(kId));
+ // Grab the handle before decrementing.
+ scoped_ptr<BlobDataHandle> blob_data_handle =
+ context_->GetBlobDataFromUUID(kId);
+ host_->OnDecrementBlobRefCount(kId);
+ EXPECT_TRUE(context_->registry().HasEntry(kId));
+ EXPECT_TRUE(IsBeingBuiltInHost(kId));
+
+ // We finish the blob, and verify that we send 'Done' back to the renderer.
+ BlobItemBytesResponse response(0);
+ std::memcpy(response.allocate_mutable_data(kDataSize), kData, kDataSize);
+ std::vector<BlobItemBytesResponse> responses = {response};
+ host_->OnMemoryItemResponse(kId, responses);
+ ExpectDone(kId);
+ sink_.ClearMessages();
+ // Check that it's still around.
+ EXPECT_TRUE(context_->registry().HasEntry(kId));
+ EXPECT_FALSE(IsBeingBuiltInHost(kId));
+
+ // Get rid of the handle, and verify it's gone.
+ blob_data_handle.reset();
+ base::RunLoop().RunUntilIdle();
+ // Check that it's no longer around.
+ EXPECT_FALSE(context_->registry().HasEntry(kId));
+ EXPECT_FALSE(IsBeingBuiltInHost(kId));
+}
+
+TEST_F(BlobDispatcherHostTest, DecrementRefAfterOnStartWithHandle) {
+ const std::string kId("id");
+ // Decrement the refcount while building, after we call
+ // OnStartBuildlingBlob, except we have another handle.
+ host_->OnRegisterBlobUUID(kId, std::string(kContentType),
+ std::string(kContentDisposition),
+ std::set<std::string>());
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+
+ scoped_ptr<BlobDataHandle> blob_data_handle =
+ context_->GetBlobDataFromUUID(kId);
+ EXPECT_TRUE(blob_data_handle->IsBeingBuilt());
+ bool built = true;
+ IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN;
+ blob_data_handle->RunOnConstructionComplete(
+ base::Bind(&ConstructionCompletePopulator, &built, &error_code));
+
+ DataElement element;
+ element.SetToBytesDescription(kDataSize);
+ std::vector<DataElement> elements = {element};
+ host_->OnStartBuildingBlob(kId, elements);
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+
+ // Check that we got the expected request.
+ std::vector<BlobItemBytesRequest> expected_requests = {
+ BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize)};
+ ExpectRequest(kId, expected_requests);
+ sink_.ClearMessages();
+ EXPECT_TRUE(context_->registry().HasEntry(kId));
+ EXPECT_TRUE(IsBeingBuiltInHost(kId));
+ // Decrement, simulating where the ref goes out of scope in renderer.
+ host_->OnDecrementBlobRefCount(kId);
+ // We still have the blob as it's not done.
+ EXPECT_TRUE(context_->registry().HasEntry(kId));
+ EXPECT_TRUE(blob_data_handle->IsBeingBuilt());
+ EXPECT_TRUE(IsBeingBuiltInHost(kId));
+ // Cancel to clean up.
+ host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN);
+ // Run loop to propagate the handle decrement in the host.
+ base::RunLoop().RunUntilIdle();
+ // We still have the entry because of our earlier handle.
+ EXPECT_TRUE(context_->registry().HasEntry(kId));
+ EXPECT_FALSE(IsBeingBuiltInHost(kId));
+ EXPECT_FALSE(built);
+ EXPECT_EQ(IPCBlobCreationCancelCode::UNKNOWN, error_code);
+ sink_.ClearMessages();
+
+ // Should disappear after dropping the handle.
+ EXPECT_TRUE(blob_data_handle->IsBroken());
+ blob_data_handle.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(context_->registry().HasEntry(kId));
+}
+
+TEST_F(BlobDispatcherHostTest, HostDisconnectAfterRegisterWithHandle) {
+ const std::string kId("id");
+
+ // Delete host with a handle to the blob.
+ host_->OnRegisterBlobUUID(kId, std::string(kContentType),
+ std::string(kContentDisposition),
+ std::set<std::string>());
+
+ scoped_ptr<BlobDataHandle> blob_data_handle =
+ context_->GetBlobDataFromUUID(kId);
+ EXPECT_TRUE(blob_data_handle->IsBeingBuilt());
+ bool built = true;
+ IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN;
+ blob_data_handle->RunOnConstructionComplete(
+ base::Bind(&ConstructionCompletePopulator, &built, &error_code));
+ // Get rid of host, which was doing the constructing.
+ host_ = nullptr;
+ EXPECT_FALSE(blob_data_handle->IsBeingBuilt());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(built);
+ EXPECT_EQ(IPCBlobCreationCancelCode::SOURCE_DIED_IN_TRANSIT, error_code);
+
+ // Should still be there due to the handle.
+ scoped_ptr<BlobDataHandle> another_handle =
+ context_->GetBlobDataFromUUID(kId);
+ EXPECT_TRUE(another_handle);
+
+ // Should disappear after dropping both handles.
+ blob_data_handle.reset();
+ another_handle.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(context_->registry().HasEntry(kId));
+}
+
+TEST_F(BlobDispatcherHostTest, HostDisconnectAfterOnStart) {
+ const std::string kId("id");
+
+ // Host deleted after OnStartBuilding.
+ host_->OnRegisterBlobUUID(kId, std::string(kContentType),
+ std::string(kContentDisposition),
+ std::set<std::string>());
+
+ DataElement element;
+ element.SetToBytesDescription(kDataSize);
+ std::vector<DataElement> elements = {element};
+ host_->OnStartBuildingBlob(kId, elements);
+
+ std::vector<BlobItemBytesRequest> expected_requests = {
+ BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize)};
+ ExpectRequest(kId, expected_requests);
+ sink_.ClearMessages();
+ host_ = nullptr;
+ // We need to run the message loop because of the handle in the async builder.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(context_->registry().HasEntry(kId));
+}
+
+TEST_F(BlobDispatcherHostTest, HostDisconnectAfterOnMemoryResponse) {
+ const std::string kId("id");
+
+ // Host deleted after OnMemoryItemResponse.
+ host_->OnRegisterBlobUUID(kId, std::string(kContentType),
+ std::string(kContentDisposition),
+ std::set<std::string>());
+
+ // Create list of two items.
+ DataElement element;
+ element.SetToBytesDescription(kDataSize);
+ std::vector<DataElement> elements = {element, element};
+ host_->OnStartBuildingBlob(kId, elements);
+ std::vector<BlobItemBytesRequest> expected_requests = {
+ BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize),
+ BlobItemBytesRequest::CreateIPCRequest(1, 1, 0, kDataSize)};
+ ExpectRequest(kId, expected_requests);
+ sink_.ClearMessages();
+
+ // Send just one response so the blob isn't 'done' yet.
+ BlobItemBytesResponse response(0);
+ std::memcpy(response.allocate_mutable_data(kDataSize), kData, kDataSize);
+ std::vector<BlobItemBytesResponse> responses = {response};
+ host_->OnMemoryItemResponse(kId, responses);
+ EXPECT_EQ(0u, sink_.message_count());
+
+ host_ = nullptr;
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(context_->registry().HasEntry(kId));
+}
+
+TEST_F(BlobDispatcherHostTest, CreateBlobWithBrokenReference) {
+ const std::string kBrokenId("id1");
+ const std::string kReferencingId("id2");
+
+ // First, let's test a circular reference.
+ const std::string kCircularId("id1");
+ host_->OnRegisterBlobUUID(kCircularId, std::string(kContentType),
+ std::string(kContentDisposition), {kCircularId});
+ ExpectAndResetBadMessage();
+
+ // Next, test a blob that references a broken blob.
+ host_->OnRegisterBlobUUID(kBrokenId, std::string(kContentType),
+ std::string(kContentDisposition),
+ std::set<std::string>());
+ host_->OnCancelBuildingBlob(kBrokenId, IPCBlobCreationCancelCode::UNKNOWN);
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+ EXPECT_TRUE(context_->GetBlobDataFromUUID(kBrokenId)->IsBroken());
+
+ // Create referencing blob. We should be broken right away, but also ignore
+ // the subsequent OnStart message.
+ host_->OnRegisterBlobUUID(kReferencingId, std::string(kContentType),
+ std::string(kContentDisposition), {kBrokenId});
+ EXPECT_TRUE(context_->GetBlobDataFromUUID(kReferencingId)->IsBroken());
+ EXPECT_FALSE(IsBeingBuiltInHost(kReferencingId));
+ EXPECT_TRUE(context_->registry().HasEntry(kReferencingId));
+ ExpectCancel(kReferencingId,
+ IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN);
+ sink_.ClearMessages();
+
+ DataElement element;
+ element.SetToBytesDescription(kDataSize);
+ std::vector<DataElement> elements = {element};
+ element.SetToBlob(kBrokenId);
+ elements.push_back(element);
+ host_->OnStartBuildingBlob(kReferencingId, elements);
+ EXPECT_EQ(0u, sink_.message_count());
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(BlobDispatcherHostTest, DeferenceBlobOnDifferentHost) {
+ const std::string kId("id");
+ // Data elements for our transfer & checking messages.
+ DataElement element;
+ element.SetToBytesDescription(kDataSize);
+ std::vector<DataElement> elements = {element};
+ std::vector<BlobItemBytesRequest> expected_requests = {
+ BlobItemBytesRequest::CreateIPCRequest(0, 0, 0, kDataSize)};
+ BlobItemBytesResponse response(0);
+ std::memcpy(response.allocate_mutable_data(kDataSize), kData, kDataSize);
+ std::vector<BlobItemBytesResponse> responses = {response};
+
+ scoped_refptr<TestableBlobDispatcherHost> host2(
+ new TestableBlobDispatcherHost(chrome_blob_storage_context_, &sink_));
+
+ // Delete host with another host having a referencing, then dereference on
+ // second host. Verify we're still building it on first host, and then
+ // verify that a building message from the renderer will kill it.
+
+ // Test OnStartBuilding after double dereference.
+ host_->OnRegisterBlobUUID(kId, std::string(kContentType),
+ std::string(kContentDisposition),
+ std::set<std::string>());
+ host2->OnIncrementBlobRefCount(kId);
+ host_->OnDecrementBlobRefCount(kId);
+ EXPECT_FALSE(host_->IsInUseInHost(kId));
+ host2->OnDecrementBlobRefCount(kId);
+ // So no more blob in the context, but we're still being built in host 1.
+ EXPECT_FALSE(context_->registry().HasEntry(kId));
+ EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kId));
+ host_->OnStartBuildingBlob(kId, elements);
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+ // We should be cleaned up.
+ EXPECT_FALSE(host_->async_builder_.IsBeingBuilt(kId));
+ ExpectCancel(kId,
+ IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING);
+ sink_.ClearMessages();
+
+ // Same as above, but test OnMemoryItemResponse after double dereference.
+ host_->OnRegisterBlobUUID(kId, std::string(kContentType),
+ std::string(kContentDisposition),
+ std::set<std::string>());
+ host2->OnIncrementBlobRefCount(kId);
+ host_->OnDecrementBlobRefCount(kId);
+ EXPECT_FALSE(host_->IsInUseInHost(kId));
+ host_->OnStartBuildingBlob(kId, elements);
+ ExpectRequest(kId, expected_requests);
+ sink_.ClearMessages();
+
+ host2->OnDecrementBlobRefCount(kId);
+ // So no more blob in the context, but we're still being built in host 1.
+ EXPECT_FALSE(context_->registry().HasEntry(kId));
+ EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kId));
+ host_->OnMemoryItemResponse(kId, responses);
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+ // We should be cleaned up.
+ EXPECT_FALSE(host_->async_builder_.IsBeingBuilt(kId));
+ ExpectCancel(kId,
+ IPCBlobCreationCancelCode::BLOB_DEREFERENCED_WHILE_BUILDING);
+ sink_.ClearMessages();
+
+ // Same, but now for OnCancel.
+ host_->OnRegisterBlobUUID(kId, std::string(kContentType),
+ std::string(kContentDisposition),
+ std::set<std::string>());
+ host2->OnIncrementBlobRefCount(kId);
+ host_->OnDecrementBlobRefCount(kId);
+ EXPECT_FALSE(host_->IsInUseInHost(kId));
+ host_->OnStartBuildingBlob(kId, elements);
+ ExpectRequest(kId, expected_requests);
+ sink_.ClearMessages();
+
+ host2->OnDecrementBlobRefCount(kId);
+ // So no more blob in the context, but we're still being built in host 1.
+ EXPECT_FALSE(context_->registry().HasEntry(kId));
+ EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kId));
+ host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN);
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+ // We should be cleaned up.
+ EXPECT_FALSE(host_->async_builder_.IsBeingBuilt(kId));
+}
+
+TEST_F(BlobDispatcherHostTest, BuildingReferenceChain) {
+ const std::string kId("id");
+ const std::string kSameHostReferencingId("id2");
+ const std::string kDifferentHostReferencingId("id3");
+ // Data elements for our transfer & checking messages.
+ DataElement element;
+ element.SetToBytes(kData, kDataSize);
+ std::vector<DataElement> elements = {element};
+ DataElement referencing_element;
+ referencing_element.SetToBlob(kId);
+ std::vector<DataElement> referencing_elements = {referencing_element};
+ std::set<std::string> referenced_blobs_set = {kId};
+
+ scoped_refptr<TestableBlobDispatcherHost> host2(
+ new TestableBlobDispatcherHost(chrome_blob_storage_context_, &sink_));
+
+ // We want to have a blob referencing another blob that is building, both on
+ // the same host and a different host. We should successfully build all blobs
+ // after the referenced blob is finished.
+
+ // First we start the referenced blob.
+ host_->OnRegisterBlobUUID(kId, std::string(kContentType),
+ std::string(kContentDisposition),
+ std::set<std::string>());
+ EXPECT_TRUE(host_->IsInUseInHost(kId));
+
+ // Next we start the referencing blobs in both the same and different host.
+ host_->OnRegisterBlobUUID(kSameHostReferencingId, std::string(kContentType),
+ std::string(kContentDisposition),
+ referenced_blobs_set);
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+ host_->OnStartBuildingBlob(kSameHostReferencingId, referencing_elements);
+ EXPECT_FALSE(host_->shutdown_for_bad_message_);
+ ExpectDone(kSameHostReferencingId);
+ EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId));
+ sink_.ClearMessages();
+ // Now the other host.
+ host2->OnRegisterBlobUUID(
+ kDifferentHostReferencingId, std::string(kContentType),
+ std::string(kContentDisposition), referenced_blobs_set);
+ EXPECT_FALSE(host2->shutdown_for_bad_message_);
+ host2->OnStartBuildingBlob(kDifferentHostReferencingId, referencing_elements);
+ EXPECT_FALSE(host2->shutdown_for_bad_message_);
+ ExpectDone(kDifferentHostReferencingId);
+ EXPECT_TRUE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId));
+ sink_.ClearMessages();
+
+ // Now we finish the first blob, and we expect all blobs to finish.
+ host_->OnStartBuildingBlob(kId, elements);
+ ExpectDone(kId);
+ // We need to run the message loop to propagate the construction callbacks.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId));
+ EXPECT_FALSE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId));
+ EXPECT_FALSE(
+ context_->GetBlobDataFromUUID(kSameHostReferencingId)->IsBroken());
+ EXPECT_FALSE(
+ context_->GetBlobDataFromUUID(kDifferentHostReferencingId)->IsBroken());
+ sink_.ClearMessages();
+
+ // Finally check that our data is correct in the child elements.
+ scoped_ptr<BlobDataHandle> handle =
+ context_->GetBlobDataFromUUID(kDifferentHostReferencingId);
+ ExpectHandleEqualsData(handle.get(), elements);
+}
+
+TEST_F(BlobDispatcherHostTest, BuildingReferenceChainWithCancel) {
+ const std::string kId("id");
+ const std::string kSameHostReferencingId("id2");
+ const std::string kDifferentHostReferencingId("id3");
+ // Data elements for our transfer & checking messages.
+ DataElement referencing_element;
+ referencing_element.SetToBlob(kId);
+ std::vector<DataElement> referencing_elements = {referencing_element};
+ std::set<std::string> referenced_blobs_set = {kId};
+
+ scoped_refptr<TestableBlobDispatcherHost> host2(
+ new TestableBlobDispatcherHost(chrome_blob_storage_context_, &sink_));
+
+ // We want to have a blob referencing another blob that is building, both on
+ // the same host and a different host. After we cancel the first blob, the
+ // others should cancel as well.
+
+ // First we start the referenced blob.
+ host_->OnRegisterBlobUUID(kId, std::string(kContentType),
+ std::string(kContentDisposition),
+ std::set<std::string>());
+ EXPECT_TRUE(host_->IsInUseInHost(kId));
+
+ // Next we start the referencing blobs in both the same and different host.
+ host_->OnRegisterBlobUUID(kSameHostReferencingId, std::string(kContentType),
+ std::string(kContentDisposition),
+ referenced_blobs_set);
+ host_->OnStartBuildingBlob(kSameHostReferencingId, referencing_elements);
+ ExpectDone(kSameHostReferencingId);
+ EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId));
+ sink_.ClearMessages();
+ // Now the other host.
+ host2->OnRegisterBlobUUID(
+ kDifferentHostReferencingId, std::string(kContentType),
+ std::string(kContentDisposition), referenced_blobs_set);
+ host2->OnStartBuildingBlob(kDifferentHostReferencingId, referencing_elements);
+ ExpectDone(kDifferentHostReferencingId);
+ EXPECT_TRUE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId));
+ sink_.ClearMessages();
+ bool built = false;
+ IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN;
+ context_->GetBlobDataFromUUID(kDifferentHostReferencingId)
+ ->RunOnConstructionComplete(
+ base::Bind(&ConstructionCompletePopulator, &built, &error_code));
+
+ // Now we cancel the first blob, and we expect all blobs to cancel.
+ host_->OnCancelBuildingBlob(kId, IPCBlobCreationCancelCode::UNKNOWN);
+ // We need to run the message loop to propagate the construction callbacks.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId));
+ EXPECT_FALSE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId));
+ EXPECT_TRUE(
+ context_->GetBlobDataFromUUID(kSameHostReferencingId)->IsBroken());
+ EXPECT_TRUE(
+ context_->GetBlobDataFromUUID(kDifferentHostReferencingId)->IsBroken());
+ EXPECT_FALSE(built);
+ EXPECT_EQ(IPCBlobCreationCancelCode::REFERENCED_BLOB_BROKEN, error_code);
+ sink_.ClearMessages();
+}
+
+TEST_F(BlobDispatcherHostTest, BuildingReferenceChainWithSourceDeath) {
+ const std::string kId("id");
+ const std::string kSameHostReferencingId("id2");
+ const std::string kDifferentHostReferencingId("id3");
+ // Data elements for our transfer & checking messages.
+ DataElement referencing_element;
+ referencing_element.SetToBlob(kId);
+ std::vector<DataElement> referencing_elements = {referencing_element};
+ std::set<std::string> referenced_blobs_set = {kId};
+
+ scoped_refptr<TestableBlobDispatcherHost> host2(
+ new TestableBlobDispatcherHost(chrome_blob_storage_context_, &sink_));
+
+ // We want to have a blob referencing another blob that is building, both on
+ // the same host and a different host. When we destroy the host, the other
+ // blob should cancel, as well as the blob on the other host.
+
+ // First we start the referenced blob.
+ host_->OnRegisterBlobUUID(kId, std::string(kContentType),
+ std::string(kContentDisposition),
+ std::set<std::string>());
+ EXPECT_TRUE(host_->IsInUseInHost(kId));
+
+ // Next we start the referencing blobs in both the same and different host.
+ host_->OnRegisterBlobUUID(kSameHostReferencingId, std::string(kContentType),
+ std::string(kContentDisposition),
+ referenced_blobs_set);
+ host_->OnStartBuildingBlob(kSameHostReferencingId, referencing_elements);
+ ExpectDone(kSameHostReferencingId);
+ EXPECT_TRUE(host_->async_builder_.IsBeingBuilt(kSameHostReferencingId));
+ sink_.ClearMessages();
+ // Now the other host.
+ host2->OnRegisterBlobUUID(
+ kDifferentHostReferencingId, std::string(kContentType),
+ std::string(kContentDisposition), referenced_blobs_set);
+ host2->OnStartBuildingBlob(kDifferentHostReferencingId, referencing_elements);
+ ExpectDone(kDifferentHostReferencingId);
+ EXPECT_TRUE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId));
+ sink_.ClearMessages();
+
+ // Grab handles & add listeners.
+ bool built = true;
+ IPCBlobCreationCancelCode error_code = IPCBlobCreationCancelCode::UNKNOWN;
+ scoped_ptr<BlobDataHandle> blob_handle = context_->GetBlobDataFromUUID(kId);
+ blob_handle->RunOnConstructionComplete(
+ base::Bind(&ConstructionCompletePopulator, &built, &error_code));
+
+ bool same_host_built = true;
+ IPCBlobCreationCancelCode same_host_error_code =
+ IPCBlobCreationCancelCode::UNKNOWN;
+ scoped_ptr<BlobDataHandle> same_host_blob_handle =
+ context_->GetBlobDataFromUUID(kSameHostReferencingId);
+ same_host_blob_handle->RunOnConstructionComplete(base::Bind(
+ &ConstructionCompletePopulator, &same_host_built, &same_host_error_code));
+
+ bool other_host_built = true;
+ IPCBlobCreationCancelCode other_host_error_code =
+ IPCBlobCreationCancelCode::UNKNOWN;
+ scoped_ptr<BlobDataHandle> other_host_blob_handle =
+ context_->GetBlobDataFromUUID(kDifferentHostReferencingId);
+ other_host_blob_handle->RunOnConstructionComplete(
+ base::Bind(&ConstructionCompletePopulator, &other_host_built,
+ &other_host_error_code));
+
+ // Now we kill the host.
+ host_ = nullptr;
+ // We need to run the message loop to propagate the construction callbacks.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(host2->async_builder_.IsBeingBuilt(kDifferentHostReferencingId));
+ EXPECT_TRUE(
+ context_->GetBlobDataFromUUID(kSameHostReferencingId)->IsBroken());
+ EXPECT_TRUE(
+ context_->GetBlobDataFromUUID(kDifferentHostReferencingId)->IsBroken());
+
+ // Check our callbacks
+ EXPECT_FALSE(built);
+ EXPECT_EQ(IPCBlobCreationCancelCode::SOURCE_DIED_IN_TRANSIT, error_code);
+ EXPECT_FALSE(same_host_built);
+ EXPECT_EQ(IPCBlobCreationCancelCode::SOURCE_DIED_IN_TRANSIT,
+ same_host_error_code);
+ EXPECT_FALSE(other_host_built);
+ EXPECT_EQ(IPCBlobCreationCancelCode::SOURCE_DIED_IN_TRANSIT,
+ other_host_error_code);
+
+ sink_.ClearMessages();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/blob_storage/blob_storage_registry_unittest.cc b/chromium/content/browser/blob_storage/blob_storage_registry_unittest.cc
index 9ff10d69700..918554202b0 100644
--- a/chromium/content/browser/blob_storage/blob_storage_registry_unittest.cc
+++ b/chromium/content/browser/blob_storage/blob_storage_registry_unittest.cc
@@ -15,36 +15,33 @@ using BlobState = BlobStorageRegistry::BlobState;
TEST(BlobStorageRegistry, UUIDRegistration) {
const std::string kBlob1 = "Blob1";
+ const std::string kType = "type1";
+ const std::string kDisposition = "disp1";
BlobStorageRegistry registry;
EXPECT_FALSE(registry.DeleteEntry(kBlob1));
EXPECT_EQ(0u, registry.blob_count());
- Entry* entry = registry.CreateEntry(kBlob1);
+ Entry* entry = registry.CreateEntry(kBlob1, kType, kDisposition);
ASSERT_NE(nullptr, entry);
- EXPECT_EQ(BlobState::RESERVED, entry->state);
+ EXPECT_EQ(BlobState::PENDING, entry->state);
+ EXPECT_EQ(kType, entry->content_type);
+ EXPECT_EQ(kDisposition, entry->content_disposition);
EXPECT_EQ(1u, entry->refcount);
- EXPECT_FALSE(entry->exceeded_memory);
EXPECT_FALSE(entry->data.get() || entry->data_builder.get());
- EXPECT_EQ(0u, entry->construction_complete_callbacks.size());
+ EXPECT_EQ(0u, entry->build_completion_callbacks.size());
EXPECT_EQ(entry, registry.GetEntry(kBlob1));
EXPECT_TRUE(registry.DeleteEntry(kBlob1));
- entry = registry.CreateEntry(kBlob1);
+ entry = registry.CreateEntry(kBlob1, kType, kDisposition);
- EXPECT_TRUE(entry->TestAndSetState(BlobState::RESERVED,
- BlobState::ASYNC_TRANSPORTATION));
- EXPECT_FALSE(
- entry->TestAndSetState(BlobState::CONSTRUCTION, BlobState::RESERVED));
- EXPECT_FALSE(entry->TestAndSetState(BlobState::ACTIVE, BlobState::RESERVED));
- EXPECT_TRUE(entry->TestAndSetState(BlobState::ASYNC_TRANSPORTATION,
- BlobState::CONSTRUCTION));
- EXPECT_EQ(BlobState::CONSTRUCTION, entry->state);
EXPECT_EQ(1u, registry.blob_count());
}
TEST(BlobStorageRegistry, URLRegistration) {
const std::string kBlob = "Blob1";
+ const std::string kType = "type1";
+ const std::string kDisposition = "disp1";
const std::string kBlob2 = "Blob2";
const GURL kURL = GURL("blob://Blob1");
const GURL kURL2 = GURL("blob://Blob2");
@@ -55,7 +52,7 @@ TEST(BlobStorageRegistry, URLRegistration) {
EXPECT_FALSE(registry.DeleteURLMapping(kURL, nullptr));
EXPECT_FALSE(registry.CreateUrlMapping(kURL, kBlob));
EXPECT_EQ(0u, registry.url_count());
- Entry* entry = registry.CreateEntry(kBlob);
+ Entry* entry = registry.CreateEntry(kBlob, kType, kDisposition);
EXPECT_FALSE(registry.IsURLMapped(kURL));
EXPECT_TRUE(registry.CreateUrlMapping(kURL, kBlob));
@@ -68,7 +65,7 @@ TEST(BlobStorageRegistry, URLRegistration) {
EXPECT_EQ(kBlob, uuid);
EXPECT_EQ(1u, registry.url_count());
- registry.CreateEntry(kBlob2);
+ registry.CreateEntry(kBlob2, kType, kDisposition);
EXPECT_TRUE(registry.CreateUrlMapping(kURL2, kBlob2));
EXPECT_EQ(2u, registry.url_count());
EXPECT_TRUE(registry.DeleteURLMapping(kURL2, &uuid));
diff --git a/chromium/content/browser/bluetooth/README.md b/chromium/content/browser/bluetooth/README.md
new file mode 100644
index 00000000000..6e55bcd73b3
--- /dev/null
+++ b/chromium/content/browser/bluetooth/README.md
@@ -0,0 +1,24 @@
+Bluetooth in Content
+====================
+
+`content/*/bluetooth` implements [Web Bluetooth][WB] using the
+`device/bluetooth` code module.
+
+[WB]: https://webbluetoothcg.github.io/web-bluetooth/
+
+Testing
+--------------------------------------------------------------------------------
+
+Bluetooth layout tests in `third_party/WebKit/LayoutTests/bluetooth/` rely on
+fake Bluetooth implementation classes constructed in
+`content/shell/browser/layout_test/layout_test_bluetooth_adapter_provider`.
+These tests span JavaScript binding to the `device/bluetooth` API layer.
+
+
+Design Documents
+--------------------------------------------------------------------------------
+
+See: [Class Diagram of Web Bluetooth through Bluetooth Android][Class]
+
+[Class]: https://sites.google.com/a/chromium.org/dev/developers/design-documents/bluetooth-design-docs/web-bluetooth-through-bluetooth-android-class-diagram
+
diff --git a/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.cc b/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.cc
index 9075fe82bb3..cd2e78929a3 100644
--- a/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.cc
+++ b/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.cc
@@ -10,6 +10,7 @@
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
+#include "content/browser/bluetooth/bluetooth_blacklist.h"
#include "content/common/bluetooth/bluetooth_scan_filter.h"
#include "crypto/random.h"
#include "device/bluetooth/bluetooth_uuid.h"
@@ -55,18 +56,28 @@ const std::string& BluetoothAllowedDevicesMap::AddDevice(
// https://w3c.github.io/webappsec-secure-contexts/
CHECK(!origin.unique());
- if (ContainsKey(origin_to_device_address_to_id_map_[origin],
- device_address)) {
+ auto device_address_to_id_map = origin_to_device_address_to_id_map_[origin];
+ auto id_iter = device_address_to_id_map.find(device_address);
+ if (id_iter != device_address_to_id_map.end()) {
VLOG(1) << "Device already in map of allowed devices.";
+ const auto& device_id = id_iter->second;
+
+ AddUnionOfServicesTo(
+ filters, optional_services,
+ &origin_to_device_id_to_services_map_[origin][device_id]);
+
return origin_to_device_address_to_id_map_[origin][device_address];
}
- const std::string device_id = GenerateDeviceId(origin);
+ const std::string device_id = GenerateDeviceId();
VLOG(1) << "Id generated for device: " << device_id;
origin_to_device_address_to_id_map_[origin][device_address] = device_id;
origin_to_device_id_to_address_map_[origin][device_id] = device_address;
- origin_to_device_id_to_services_map_[origin][device_id] =
- UnionOfServices(filters, optional_services);
+ AddUnionOfServicesTo(
+ filters, optional_services,
+ &origin_to_device_id_to_services_map_[origin][device_id]);
+
+ CHECK(device_id_set_.insert(device_id).second);
return origin_to_device_address_to_id_map_[origin][device_address];
}
@@ -88,6 +99,9 @@ void BluetoothAllowedDevicesMap::RemoveDevice(
CHECK(origin_to_device_id_to_address_map_.erase(origin));
CHECK(origin_to_device_id_to_services_map_.erase(origin));
}
+
+ // 3. Remove from set of ids.
+ CHECK(device_id_set_.erase(device_id));
}
const std::string& BluetoothAllowedDevicesMap::GetDeviceId(
@@ -123,33 +137,48 @@ const std::string& BluetoothAllowedDevicesMap::GetDeviceAddress(
: id_iter->second;
}
-std::string BluetoothAllowedDevicesMap::GenerateDeviceId(
- const url::Origin& origin) {
- std::string device_id = GetBase64Id();
- auto id_map_iter = origin_to_device_id_to_address_map_.find(origin);
- if (id_map_iter == origin_to_device_id_to_address_map_.end()) {
- return device_id;
+bool BluetoothAllowedDevicesMap::IsOriginAllowedToAccessService(
+ const url::Origin& origin,
+ const std::string& device_id,
+ const std::string& service_uuid) const {
+ if (BluetoothBlacklist::Get().IsExcluded(BluetoothUUID(service_uuid)))
+ return false;
+
+ auto id_map_iter = origin_to_device_id_to_services_map_.find(origin);
+ if (id_map_iter == origin_to_device_id_to_services_map_.end()) {
+ return false;
}
- while (ContainsKey(id_map_iter->second, device_id)) {
+
+ const auto& device_id_to_services_map = id_map_iter->second;
+
+ auto id_iter = device_id_to_services_map.find(device_id);
+
+ return id_iter == device_id_to_services_map.end()
+ ? false
+ : ContainsKey(id_iter->second, service_uuid);
+}
+
+std::string BluetoothAllowedDevicesMap::GenerateDeviceId() {
+ std::string device_id = GetBase64Id();
+ while (ContainsKey(device_id_set_, device_id)) {
LOG(WARNING) << "Generated repeated id.";
device_id = GetBase64Id();
}
return device_id;
}
-std::set<std::string> BluetoothAllowedDevicesMap::UnionOfServices(
+void BluetoothAllowedDevicesMap::AddUnionOfServicesTo(
const std::vector<BluetoothScanFilter>& filters,
- const std::vector<BluetoothUUID>& optional_services) {
- std::set<std::string> unionOfServices;
+ const std::vector<device::BluetoothUUID>& optional_services,
+ std::set<std::string>* unionOfServices) {
for (const auto& filter : filters) {
for (const BluetoothUUID& uuid : filter.services) {
- unionOfServices.insert(uuid.canonical_value());
+ unionOfServices->insert(uuid.canonical_value());
}
}
for (const BluetoothUUID& uuid : optional_services) {
- unionOfServices.insert(uuid.canonical_value());
+ unionOfServices->insert(uuid.canonical_value());
}
- return unionOfServices;
}
} // namespace content
diff --git a/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.h b/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.h
index d8672979eeb..32823593a37 100644
--- a/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.h
+++ b/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map.h
@@ -25,15 +25,14 @@ struct BluetoothScanFilter;
// their services.
//
// |AddDevice| generates device ids, which are random strings that are unique
-// for each (origin, device address) pair.
+// in the map.
class CONTENT_EXPORT BluetoothAllowedDevicesMap final {
public:
BluetoothAllowedDevicesMap();
~BluetoothAllowedDevicesMap();
// Adds the Bluetooth Device with |device_address| to the map of allowed
- // devices for that origin. Generates and returns a device id for the
- // (|origin|, |device_address|) pair.
+ // devices for that origin. Generates and returns a device id.
const std::string& AddDevice(
const url::Origin& origin,
const std::string& device_address,
@@ -45,12 +44,8 @@ class CONTENT_EXPORT BluetoothAllowedDevicesMap final {
void RemoveDevice(const url::Origin& origin,
const std::string& device_address);
- // TODO(ortuno): Add function to check if origin is allowed to access
- // a device's service and add tests for that function.
- // https://crbug.com/493460
-
// Returns the Bluetooth Device's id for |origin|. Returns an empty string
- // if the origin is not allowed to access the device.
+ // if |origin| is not allowed to access the device.
const std::string& GetDeviceId(const url::Origin& origin,
const std::string& device_address);
@@ -59,17 +54,24 @@ class CONTENT_EXPORT BluetoothAllowedDevicesMap final {
const std::string& GetDeviceAddress(const url::Origin& origin,
const std::string& device_id);
+ // Returns true if the origin has previously been granted access to
+ // the service.
+ bool IsOriginAllowedToAccessService(const url::Origin& origin,
+ const std::string& device_id,
+ const std::string& service_uuid) const;
+
private:
typedef std::map<std::string, std::string> DeviceAddressToIdMap;
typedef std::map<std::string, std::string> DeviceIdToAddressMap;
typedef std::map<std::string, std::set<std::string>> DeviceIdToServicesMap;
- // Returns an id guaranteed to be unique for the origin. The id is randomly
+ // Returns an id guaranteed to be unique for the map. The id is randomly
// generated so that an origin can't guess the id used in another origin.
- std::string GenerateDeviceId(const url::Origin& origin);
- std::set<std::string> UnionOfServices(
+ std::string GenerateDeviceId();
+ void AddUnionOfServicesTo(
const std::vector<BluetoothScanFilter>& filters,
- const std::vector<device::BluetoothUUID>& optional_services);
+ const std::vector<device::BluetoothUUID>& optional_services,
+ std::set<std::string>* unionOfServices);
std::map<url::Origin, DeviceAddressToIdMap>
origin_to_device_address_to_id_map_;
@@ -77,6 +79,9 @@ class CONTENT_EXPORT BluetoothAllowedDevicesMap final {
origin_to_device_id_to_address_map_;
std::map<url::Origin, DeviceIdToServicesMap>
origin_to_device_id_to_services_map_;
+
+ // Keep track of all device_ids in the map.
+ std::set<std::string> device_id_set_;
};
} // namespace content
diff --git a/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map_unittest.cc b/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map_unittest.cc
index 2d5243a1d5f..925d1a1393f 100644
--- a/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map_unittest.cc
+++ b/chromium/content/browser/bluetooth/bluetooth_allowed_devices_map_unittest.cc
@@ -10,153 +10,390 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
+using device::BluetoothUUID;
+
namespace content {
namespace {
-const url::Origin test_origin1(GURL("https://www.example1.com"));
-const url::Origin test_origin2(GURL("https://www.example2.com"));
-
-const std::string device_address1 = "00:00:00";
-const std::string device_address2 = "11:11:11";
-
-const std::vector<content::BluetoothScanFilter> filters =
+const url::Origin kTestOrigin1(GURL("https://www.example1.com"));
+const url::Origin kTestOrigin2(GURL("https://www.example2.com"));
+
+const std::string kDeviceAddress1 = "00:00:00";
+const std::string kDeviceAddress2 = "11:11:11";
+
+const char kGlucoseUUIDString[] = "00001808-0000-1000-8000-00805f9b34fb";
+const char kHeartRateUUIDString[] = "0000180d-0000-1000-8000-00805f9b34fb";
+const char kBatteryServiceUUIDString[] = "0000180f-0000-1000-8000-00805f9b34fb";
+const char kBloodPressureUUIDString[] = "00001813-0000-1000-8000-00805f9b34fb";
+const char kCyclingPowerUUIDString[] = "00001818-0000-1000-8000-00805f9b34fb";
+const BluetoothUUID kGlucoseUUID(kGlucoseUUIDString);
+const BluetoothUUID kHeartRateUUID(kHeartRateUUIDString);
+const BluetoothUUID kBatteryServiceUUID(kBatteryServiceUUIDString);
+const BluetoothUUID kBloodPressureUUID(kBloodPressureUUIDString);
+const BluetoothUUID kCyclingPowerUUID(kCyclingPowerUUIDString);
+
+const std::vector<content::BluetoothScanFilter> kEmptyFilters =
std::vector<BluetoothScanFilter>();
-const std::vector<device::BluetoothUUID> optional_services =
+const std::vector<device::BluetoothUUID> kEmptyOptionalServices =
std::vector<device::BluetoothUUID>();
} // namespace
-class BluetoothAllowedDevicesMapTest : public testing::Test {};
-
-TEST_F(BluetoothAllowedDevicesMapTest, AddDeviceToMap) {
+TEST(BluetoothAllowedDevicesMapTest, AddDeviceToMap) {
BluetoothAllowedDevicesMap allowed_devices_map;
const std::string& device_id = allowed_devices_map.AddDevice(
- test_origin1, device_address1, filters, optional_services);
+ kTestOrigin1, kDeviceAddress1, kEmptyFilters, kEmptyOptionalServices);
// Test that we can retrieve the device address/id.
EXPECT_EQ(device_id,
- allowed_devices_map.GetDeviceId(test_origin1, device_address1));
- EXPECT_EQ(device_address1,
- allowed_devices_map.GetDeviceAddress(test_origin1, device_id));
+ allowed_devices_map.GetDeviceId(kTestOrigin1, kDeviceAddress1));
+ EXPECT_EQ(kDeviceAddress1,
+ allowed_devices_map.GetDeviceAddress(kTestOrigin1, device_id));
}
-TEST_F(BluetoothAllowedDevicesMapTest, AddDeviceToMapTwice) {
+TEST(BluetoothAllowedDevicesMapTest, AddDeviceToMapTwice) {
BluetoothAllowedDevicesMap allowed_devices_map;
const std::string& device_id1 = allowed_devices_map.AddDevice(
- test_origin1, device_address1, filters, optional_services);
+ kTestOrigin1, kDeviceAddress1, kEmptyFilters, kEmptyOptionalServices);
const std::string& device_id2 = allowed_devices_map.AddDevice(
- test_origin1, device_address1, filters, optional_services);
+ kTestOrigin1, kDeviceAddress1, kEmptyFilters, kEmptyOptionalServices);
EXPECT_EQ(device_id1, device_id2);
// Test that we can retrieve the device address/id.
EXPECT_EQ(device_id1,
- allowed_devices_map.GetDeviceId(test_origin1, device_address1));
- EXPECT_EQ(device_address1,
- allowed_devices_map.GetDeviceAddress(test_origin1, device_id1));
+ allowed_devices_map.GetDeviceId(kTestOrigin1, kDeviceAddress1));
+ EXPECT_EQ(kDeviceAddress1,
+ allowed_devices_map.GetDeviceAddress(kTestOrigin1, device_id1));
}
-TEST_F(BluetoothAllowedDevicesMapTest, AddTwoDevicesFromSameOriginToMap) {
+TEST(BluetoothAllowedDevicesMapTest, AddTwoDevicesFromSameOriginToMap) {
BluetoothAllowedDevicesMap allowed_devices_map;
const std::string& device_id1 = allowed_devices_map.AddDevice(
- test_origin1, device_address1, filters, optional_services);
+ kTestOrigin1, kDeviceAddress1, kEmptyFilters, kEmptyOptionalServices);
const std::string& device_id2 = allowed_devices_map.AddDevice(
- test_origin1, device_address2, filters, optional_services);
+ kTestOrigin1, kDeviceAddress2, kEmptyFilters, kEmptyOptionalServices);
EXPECT_NE(device_id1, device_id2);
// Test that we can retrieve the device address/id.
EXPECT_EQ(device_id1,
- allowed_devices_map.GetDeviceId(test_origin1, device_address1));
+ allowed_devices_map.GetDeviceId(kTestOrigin1, kDeviceAddress1));
EXPECT_EQ(device_id2,
- allowed_devices_map.GetDeviceId(test_origin1, device_address2));
+ allowed_devices_map.GetDeviceId(kTestOrigin1, kDeviceAddress2));
- EXPECT_EQ(device_address1,
- allowed_devices_map.GetDeviceAddress(test_origin1, device_id1));
- EXPECT_EQ(device_address2,
- allowed_devices_map.GetDeviceAddress(test_origin1, device_id2));
+ EXPECT_EQ(kDeviceAddress1,
+ allowed_devices_map.GetDeviceAddress(kTestOrigin1, device_id1));
+ EXPECT_EQ(kDeviceAddress2,
+ allowed_devices_map.GetDeviceAddress(kTestOrigin1, device_id2));
}
-TEST_F(BluetoothAllowedDevicesMapTest, AddTwoDevicesFromTwoOriginsToMap) {
+TEST(BluetoothAllowedDevicesMapTest, AddTwoDevicesFromTwoOriginsToMap) {
BluetoothAllowedDevicesMap allowed_devices_map;
const std::string& device_id1 = allowed_devices_map.AddDevice(
- test_origin1, device_address1, filters, optional_services);
+ kTestOrigin1, kDeviceAddress1, kEmptyFilters, kEmptyOptionalServices);
const std::string& device_id2 = allowed_devices_map.AddDevice(
- test_origin2, device_address2, filters, optional_services);
+ kTestOrigin2, kDeviceAddress2, kEmptyFilters, kEmptyOptionalServices);
EXPECT_NE(device_id1, device_id2);
// Test that the wrong origin doesn't have access to the device.
EXPECT_EQ(base::EmptyString(),
- allowed_devices_map.GetDeviceId(test_origin1, device_address2));
+ allowed_devices_map.GetDeviceId(kTestOrigin1, kDeviceAddress2));
EXPECT_EQ(base::EmptyString(),
- allowed_devices_map.GetDeviceId(test_origin2, device_address1));
+ allowed_devices_map.GetDeviceId(kTestOrigin2, kDeviceAddress1));
EXPECT_EQ(base::EmptyString(),
- allowed_devices_map.GetDeviceAddress(test_origin1, device_id2));
+ allowed_devices_map.GetDeviceAddress(kTestOrigin1, device_id2));
EXPECT_EQ(base::EmptyString(),
- allowed_devices_map.GetDeviceAddress(test_origin2, device_id1));
+ allowed_devices_map.GetDeviceAddress(kTestOrigin2, device_id1));
// Test that we can retrieve the device address/id.
EXPECT_EQ(device_id1,
- allowed_devices_map.GetDeviceId(test_origin1, device_address1));
+ allowed_devices_map.GetDeviceId(kTestOrigin1, kDeviceAddress1));
EXPECT_EQ(device_id2,
- allowed_devices_map.GetDeviceId(test_origin2, device_address2));
+ allowed_devices_map.GetDeviceId(kTestOrigin2, kDeviceAddress2));
- EXPECT_EQ(device_address1,
- allowed_devices_map.GetDeviceAddress(test_origin1, device_id1));
- EXPECT_EQ(device_address2,
- allowed_devices_map.GetDeviceAddress(test_origin2, device_id2));
+ EXPECT_EQ(kDeviceAddress1,
+ allowed_devices_map.GetDeviceAddress(kTestOrigin1, device_id1));
+ EXPECT_EQ(kDeviceAddress2,
+ allowed_devices_map.GetDeviceAddress(kTestOrigin2, device_id2));
}
-TEST_F(BluetoothAllowedDevicesMapTest, AddDeviceFromTwoOriginsToMap) {
+TEST(BluetoothAllowedDevicesMapTest, AddDeviceFromTwoOriginsToMap) {
BluetoothAllowedDevicesMap allowed_devices_map;
const std::string& device_id1 = allowed_devices_map.AddDevice(
- test_origin1, device_address1, filters, optional_services);
+ kTestOrigin1, kDeviceAddress1, kEmptyFilters, kEmptyOptionalServices);
const std::string& device_id2 = allowed_devices_map.AddDevice(
- test_origin2, device_address1, filters, optional_services);
+ kTestOrigin2, kDeviceAddress1, kEmptyFilters, kEmptyOptionalServices);
EXPECT_NE(device_id1, device_id2);
// Test that the wrong origin doesn't have access to the device.
EXPECT_EQ(base::EmptyString(),
- allowed_devices_map.GetDeviceAddress(test_origin1, device_id2));
+ allowed_devices_map.GetDeviceAddress(kTestOrigin1, device_id2));
EXPECT_EQ(base::EmptyString(),
- allowed_devices_map.GetDeviceAddress(test_origin2, device_id1));
+ allowed_devices_map.GetDeviceAddress(kTestOrigin2, device_id1));
}
-TEST_F(BluetoothAllowedDevicesMapTest, AddRemoveAddDeviceToMap) {
+TEST(BluetoothAllowedDevicesMapTest, AddRemoveAddDeviceToMap) {
BluetoothAllowedDevicesMap allowed_devices_map;
const std::string device_id_first_time = allowed_devices_map.AddDevice(
- test_origin1, device_address1, filters, optional_services);
+ kTestOrigin1, kDeviceAddress1, kEmptyFilters, kEmptyOptionalServices);
- allowed_devices_map.RemoveDevice(test_origin1, device_address1);
+ allowed_devices_map.RemoveDevice(kTestOrigin1, kDeviceAddress1);
const std::string device_id_second_time = allowed_devices_map.AddDevice(
- test_origin1, device_address1, filters, optional_services);
+ kTestOrigin1, kDeviceAddress1, kEmptyFilters, kEmptyOptionalServices);
EXPECT_NE(device_id_first_time, device_id_second_time);
}
-TEST_F(BluetoothAllowedDevicesMapTest, RemoveDeviceFromMap) {
+TEST(BluetoothAllowedDevicesMapTest, RemoveDeviceFromMap) {
BluetoothAllowedDevicesMap allowed_devices_map;
const std::string& device_id = allowed_devices_map.AddDevice(
- test_origin1, device_address1, filters, optional_services);
+ kTestOrigin1, kDeviceAddress1, kEmptyFilters, kEmptyOptionalServices);
- allowed_devices_map.RemoveDevice(test_origin1, device_address1);
+ allowed_devices_map.RemoveDevice(kTestOrigin1, kDeviceAddress1);
EXPECT_EQ(base::EmptyString(),
- allowed_devices_map.GetDeviceId(test_origin1, device_id));
+ allowed_devices_map.GetDeviceId(kTestOrigin1, device_id));
EXPECT_EQ(base::EmptyString(), allowed_devices_map.GetDeviceAddress(
- test_origin1, device_address1));
+ kTestOrigin1, kDeviceAddress1));
+}
+
+TEST(BluetoothAllowedDevicesMapTest, AllowedServices_OneOriginOneDevice) {
+ BluetoothAllowedDevicesMap allowed_devices_map;
+
+ // Setup device.
+ BluetoothScanFilter scanFilter1;
+ scanFilter1.services.push_back(kGlucoseUUID);
+ BluetoothScanFilter scanFilter2;
+ scanFilter2.services.push_back(kHeartRateUUID);
+
+ std::vector<BluetoothScanFilter> filters;
+ filters.push_back(scanFilter1);
+ filters.push_back(scanFilter2);
+
+ std::vector<BluetoothUUID> optional_services;
+ optional_services.push_back(kBatteryServiceUUID);
+ optional_services.push_back(kHeartRateUUID);
+
+ // Add to map.
+ const std::string device_id1 = allowed_devices_map.AddDevice(
+ kTestOrigin1, kDeviceAddress1, filters, optional_services);
+
+ // Access allowed services.
+ EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id1, kGlucoseUUIDString));
+ EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id1, kHeartRateUUIDString));
+ EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id1, kBatteryServiceUUIDString));
+
+ // Try to access a non-allowed service.
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id1, kBloodPressureUUIDString));
+
+ // Try to access allowed services after removing device.
+ allowed_devices_map.RemoveDevice(kTestOrigin1, kDeviceAddress1);
+
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id1, kGlucoseUUIDString));
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id1, kHeartRateUUIDString));
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id1, kBatteryServiceUUIDString));
+
+ // Add device back.
+ const std::string device_id2 = allowed_devices_map.AddDevice(
+ kTestOrigin1, kDeviceAddress1, filters, kEmptyOptionalServices);
+
+ // Access allowed services.
+ EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id2, kGlucoseUUIDString));
+ EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id2, kHeartRateUUIDString));
+
+ // Try to access a non-allowed service.
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id2, kBatteryServiceUUIDString));
+
+ // Try to access services from old device.
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id1, kGlucoseUUIDString));
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id1, kHeartRateUUIDString));
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id1, kBatteryServiceUUIDString));
+}
+
+TEST(BluetoothAllowedDevicesMapTest, AllowedServices_OneOriginTwoDevices) {
+ BluetoothAllowedDevicesMap allowed_devices_map;
+
+ // Setup request for device #1.
+ BluetoothScanFilter scanFilter1;
+ scanFilter1.services.push_back(kGlucoseUUID);
+ std::vector<BluetoothScanFilter> filters1;
+ filters1.push_back(scanFilter1);
+
+ std::vector<BluetoothUUID> optional_services1;
+ optional_services1.push_back(kHeartRateUUID);
+
+ // Setup request for device #2.
+ BluetoothScanFilter scanFilter2;
+ scanFilter2.services.push_back(kBatteryServiceUUID);
+ std::vector<BluetoothScanFilter> filters2;
+ filters2.push_back(scanFilter2);
+
+ std::vector<BluetoothUUID> optional_services2;
+ optional_services2.push_back(kBloodPressureUUID);
+
+ // Add devices to map.
+ const std::string& device_id1 = allowed_devices_map.AddDevice(
+ kTestOrigin1, kDeviceAddress1, filters1, optional_services1);
+ const std::string& device_id2 = allowed_devices_map.AddDevice(
+ kTestOrigin1, kDeviceAddress2, filters2, optional_services2);
+
+ // Access allowed services.
+ EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id1, kGlucoseUUIDString));
+ EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id1, kHeartRateUUIDString));
+
+ EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id2, kBatteryServiceUUIDString));
+ EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id2, kBloodPressureUUIDString));
+
+ // Try to access non-allowed services.
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id1, kBatteryServiceUUIDString));
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id1, kBloodPressureUUIDString));
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id1, kCyclingPowerUUIDString));
+
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id2, kGlucoseUUIDString));
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id2, kHeartRateUUIDString));
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id2, kCyclingPowerUUIDString));
+}
+
+TEST(BluetoothAllowedDevicesMapTest, AllowedServices_TwoOriginsOneDevice) {
+ BluetoothAllowedDevicesMap allowed_devices_map;
+ // Setup request #1 for device.
+ BluetoothScanFilter scanFilter1;
+ scanFilter1.services.push_back(kGlucoseUUID);
+ std::vector<BluetoothScanFilter> filters1;
+ filters1.push_back(scanFilter1);
+
+ std::vector<BluetoothUUID> optional_services1;
+ optional_services1.push_back(kHeartRateUUID);
+
+ // Setup request #2 for device.
+ BluetoothScanFilter scanFilter2;
+ scanFilter2.services.push_back(kBatteryServiceUUID);
+ std::vector<BluetoothScanFilter> filters2;
+ filters2.push_back(scanFilter2);
+
+ std::vector<BluetoothUUID> optional_services2;
+ optional_services2.push_back(kBloodPressureUUID);
+
+ // Add devices to map.
+ const std::string& device_id1 = allowed_devices_map.AddDevice(
+ kTestOrigin1, kDeviceAddress1, filters1, optional_services1);
+ const std::string& device_id2 = allowed_devices_map.AddDevice(
+ kTestOrigin2, kDeviceAddress1, filters2, optional_services2);
+
+ // Access allowed services.
+ EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id1, kGlucoseUUIDString));
+ EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id1, kHeartRateUUIDString));
+
+ EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin2, device_id2, kBatteryServiceUUIDString));
+ EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin2, device_id2, kBloodPressureUUIDString));
+
+ // Try to access non-allowed services.
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id1, kBatteryServiceUUIDString));
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id1, kBloodPressureUUIDString));
+
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id2, kGlucoseUUIDString));
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id2, kHeartRateUUIDString));
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id2, kBatteryServiceUUIDString));
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id2, kBloodPressureUUIDString));
+
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin2, device_id2, kGlucoseUUIDString));
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin2, device_id2, kHeartRateUUIDString));
+
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin2, device_id1, kGlucoseUUIDString));
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin2, device_id1, kHeartRateUUIDString));
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin2, device_id1, kBatteryServiceUUIDString));
+ EXPECT_FALSE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin2, device_id1, kBloodPressureUUIDString));
+}
+
+TEST(BluetoothAllowedDevicesMapTest, MergeServices) {
+ BluetoothAllowedDevicesMap allowed_devices_map;
+
+ // Setup first request.
+ BluetoothScanFilter scanFilter1;
+ scanFilter1.services.push_back(kGlucoseUUID);
+ std::vector<BluetoothScanFilter> filters1;
+ filters1.push_back(scanFilter1);
+ std::vector<BluetoothUUID> optional_services1;
+ optional_services1.push_back(kBatteryServiceUUID);
+
+ // Add to map.
+ const std::string device_id1 = allowed_devices_map.AddDevice(
+ kTestOrigin1, kDeviceAddress1, filters1, optional_services1);
+
+ // Setup second request.
+ BluetoothScanFilter scanFilter2;
+ scanFilter2.services.push_back(kHeartRateUUID);
+ std::vector<BluetoothScanFilter> filters2;
+ filters2.push_back(scanFilter2);
+ std::vector<BluetoothUUID> optional_services2;
+ optional_services2.push_back(kBloodPressureUUID);
+
+ // Add to map again.
+ const std::string device_id2 = allowed_devices_map.AddDevice(
+ kTestOrigin1, kDeviceAddress1, filters2, optional_services2);
+
+ EXPECT_EQ(device_id1, device_id2);
+
+ EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id1, kGlucoseUUIDString));
+ EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id1, kBatteryServiceUUIDString));
+ EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id1, kHeartRateUUIDString));
+ EXPECT_TRUE(allowed_devices_map.IsOriginAllowedToAccessService(
+ kTestOrigin1, device_id1, kBloodPressureUUIDString));
}
-TEST_F(BluetoothAllowedDevicesMapTest, CorrectIdFormat) {
+TEST(BluetoothAllowedDevicesMapTest, CorrectIdFormat) {
BluetoothAllowedDevicesMap allowed_devices_map;
const std::string& device_id = allowed_devices_map.AddDevice(
- test_origin1, device_address1, filters, optional_services);
+ kTestOrigin1, kDeviceAddress1, kEmptyFilters, kEmptyOptionalServices);
EXPECT_TRUE(device_id.size() == 24)
<< "Expected Lenghth of a 128bit string encoded to Base64.";
diff --git a/chromium/content/browser/bluetooth/bluetooth_blacklist.cc b/chromium/content/browser/bluetooth/bluetooth_blacklist.cc
new file mode 100644
index 00000000000..c9edc5e3806
--- /dev/null
+++ b/chromium/content/browser/bluetooth/bluetooth_blacklist.cc
@@ -0,0 +1,185 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/bluetooth/bluetooth_blacklist.h"
+
+#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/strings/string_split.h"
+#include "content/common/bluetooth/bluetooth_scan_filter.h"
+#include "content/public/browser/content_browser_client.h"
+
+using device::BluetoothUUID;
+
+namespace {
+
+static base::LazyInstance<content::BluetoothBlacklist>::Leaky g_singleton =
+ LAZY_INSTANCE_INITIALIZER;
+
+void RecordUMAParsedNonEmptyString(bool success) {
+ UMA_HISTOGRAM_BOOLEAN("Bluetooth.Web.Blacklist.ParsedNonEmptyString",
+ success);
+}
+
+} // namespace
+
+namespace content {
+
+BluetoothBlacklist::~BluetoothBlacklist() {}
+
+// static
+BluetoothBlacklist& BluetoothBlacklist::Get() {
+ return g_singleton.Get();
+}
+
+void BluetoothBlacklist::Add(const device::BluetoothUUID& uuid, Value value) {
+ CHECK(uuid.IsValid());
+ auto insert_result = blacklisted_uuids_.insert(std::make_pair(uuid, value));
+ bool inserted = insert_result.second;
+ if (!inserted) {
+ Value& stored = insert_result.first->second;
+ if (stored != value)
+ stored = Value::EXCLUDE;
+ }
+}
+
+void BluetoothBlacklist::Add(base::StringPiece blacklist_string) {
+ if (blacklist_string.empty())
+ return;
+ base::StringPairs kv_pairs;
+ bool parsed_values = false;
+ bool invalid_values = false;
+ SplitStringIntoKeyValuePairs(blacklist_string,
+ ':', // Key-value delimiter
+ ',', // Key-value pair delimiter
+ &kv_pairs);
+ for (const auto& pair : kv_pairs) {
+ BluetoothUUID uuid(pair.first);
+ if (uuid.IsValid() && pair.second.size() == 1u) {
+ switch (pair.second[0]) {
+ case 'e':
+ Add(uuid, Value::EXCLUDE);
+ parsed_values = true;
+ continue;
+ case 'r':
+ Add(uuid, Value::EXCLUDE_READS);
+ parsed_values = true;
+ continue;
+ case 'w':
+ Add(uuid, Value::EXCLUDE_WRITES);
+ parsed_values = true;
+ continue;
+ }
+ }
+ invalid_values = true;
+ }
+ RecordUMAParsedNonEmptyString(parsed_values && !invalid_values);
+}
+
+bool BluetoothBlacklist::IsExcluded(const BluetoothUUID& uuid) const {
+ CHECK(uuid.IsValid());
+ const auto& it = blacklisted_uuids_.find(uuid);
+ if (it == blacklisted_uuids_.end())
+ return false;
+ return it->second == Value::EXCLUDE;
+}
+
+bool BluetoothBlacklist::IsExcluded(
+ const std::vector<content::BluetoothScanFilter>& filters) {
+ for (const BluetoothScanFilter& filter : filters) {
+ for (const BluetoothUUID& service : filter.services) {
+ if (IsExcluded(service)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool BluetoothBlacklist::IsExcludedFromReads(const BluetoothUUID& uuid) const {
+ CHECK(uuid.IsValid());
+ const auto& it = blacklisted_uuids_.find(uuid);
+ if (it == blacklisted_uuids_.end())
+ return false;
+ return it->second == Value::EXCLUDE || it->second == Value::EXCLUDE_READS;
+}
+
+bool BluetoothBlacklist::IsExcludedFromWrites(const BluetoothUUID& uuid) const {
+ CHECK(uuid.IsValid());
+ const auto& it = blacklisted_uuids_.find(uuid);
+ if (it == blacklisted_uuids_.end())
+ return false;
+ return it->second == Value::EXCLUDE || it->second == Value::EXCLUDE_WRITES;
+}
+
+void BluetoothBlacklist::RemoveExcludedUuids(
+ std::vector<device::BluetoothUUID>* uuids) {
+ auto it = uuids->begin();
+ while (it != uuids->end()) {
+ if (IsExcluded(*it)) {
+ it = uuids->erase(it);
+ } else {
+ it++;
+ }
+ }
+}
+
+void BluetoothBlacklist::ResetToDefaultValuesForTest() {
+ blacklisted_uuids_.clear();
+ PopulateWithDefaultValues();
+ PopulateWithServerProvidedValues();
+}
+
+BluetoothBlacklist::BluetoothBlacklist() {
+ PopulateWithDefaultValues();
+ PopulateWithServerProvidedValues();
+}
+
+void BluetoothBlacklist::PopulateWithDefaultValues() {
+ blacklisted_uuids_.clear();
+
+ // Testing from Layout Tests Note:
+ //
+ // Random UUIDs for object & exclude permutations that do not exist in the
+ // standard blacklist are included to facilitate integration testing from
+ // Layout Tests. Unit tests can dynamically modify the blacklist, but don't
+ // offer the full integration test to the Web Bluetooth Javascript bindings.
+ //
+ // This is done for simplicity as opposed to exposing a testing API that can
+ // add to the blacklist over time, which would be over engineered.
+ //
+ // Remove testing UUIDs if the specified blacklist is updated to include UUIDs
+ // that match the specific permutations.
+ DCHECK(BluetoothUUID("00001800-0000-1000-8000-00805f9b34fb") ==
+ BluetoothUUID("1800"));
+
+ // Blacklist UUIDs updated 2016-04-07 from:
+ // https://github.com/WebBluetoothCG/registries/blob/master/gatt_blacklist.txt
+ // Short UUIDs are used for readability of this list.
+ //
+ // Services:
+ Add(BluetoothUUID("1812"), Value::EXCLUDE);
+ Add(BluetoothUUID("00001530-1212-efde-1523-785feabcd123"), Value::EXCLUDE);
+ Add(BluetoothUUID("f000ffc0-0451-4000-b000-000000000000"), Value::EXCLUDE);
+ // Characteristics:
+ Add(BluetoothUUID("2a02"), Value::EXCLUDE_WRITES);
+ Add(BluetoothUUID("2a03"), Value::EXCLUDE);
+ Add(BluetoothUUID("2a25"), Value::EXCLUDE);
+ // Characteristics for Layout Tests:
+ Add(BluetoothUUID("bad1c9a2-9a5b-4015-8b60-1579bbbf2135"),
+ Value::EXCLUDE_READS);
+ // Descriptors:
+ Add(BluetoothUUID("2902"), Value::EXCLUDE_WRITES);
+ Add(BluetoothUUID("2903"), Value::EXCLUDE_WRITES);
+ // Descriptors for Layout Tests:
+ Add(BluetoothUUID("bad2ddcf-60db-45cd-bef9-fd72b153cf7c"), Value::EXCLUDE);
+ Add(BluetoothUUID("bad3ec61-3cc3-4954-9702-7977df514114"),
+ Value::EXCLUDE_READS);
+}
+
+void BluetoothBlacklist::PopulateWithServerProvidedValues() {
+ Add(GetContentClient()->browser()->GetWebBluetoothBlacklist());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/bluetooth/bluetooth_blacklist.h b/chromium/content/browser/bluetooth/bluetooth_blacklist.h
new file mode 100644
index 00000000000..d363d86cfb9
--- /dev/null
+++ b/chromium/content/browser/bluetooth/bluetooth_blacklist.h
@@ -0,0 +1,104 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_BLACKLIST_H_
+#define CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_BLACKLIST_H_
+
+#include <map>
+#include <vector>
+
+#include "base/lazy_instance.h"
+#include "base/macros.h"
+#include "base/strings/string_piece.h"
+#include "content/common/content_export.h"
+#include "device/bluetooth/bluetooth_uuid.h"
+
+namespace content {
+
+struct BluetoothScanFilter;
+
+// Implements the Web Bluetooth Blacklist policy as defined in the Web Bluetooth
+// specification:
+// https://webbluetoothcg.github.io/web-bluetooth/#the-gatt-blacklist
+//
+// Client code may query UUIDs to determine if they are excluded from use by the
+// blacklist.
+//
+// Singleton access via Get() enforces only one copy of blacklist.
+class CONTENT_EXPORT BluetoothBlacklist final {
+ public:
+ // Blacklist value terminology from Web Bluetooth specification:
+ // https://webbluetoothcg.github.io/web-bluetooth/#the-gatt-blacklist
+ enum class Value {
+ EXCLUDE, // Implies EXCLUDE_READS and EXCLUDE_WRITES.
+ EXCLUDE_READS, // Excluded from read operations.
+ EXCLUDE_WRITES // Excluded from write operations.
+ };
+
+ ~BluetoothBlacklist();
+
+ // Returns a singleton instance of the blacklist.
+ static BluetoothBlacklist& Get();
+
+ // Adds a UUID to the blacklist to be excluded from operations, merging with
+ // any previous value and resulting in the strictest exclusion rule from the
+ // combination of the two, E.G.:
+ // Add(uuid, EXCLUDE_READS);
+ // Add(uuid, EXCLUDE_WRITES);
+ // IsExcluded(uuid); // true.
+ // Requires UUID to be valid.
+ void Add(const device::BluetoothUUID&, Value);
+
+ // Adds UUIDs to the blacklist by parsing a blacklist string and calling
+ // Add(uuid, value).
+ //
+ // The blacklist string format is defined at
+ // ContentBrowserClient::GetWebBluetoothBlacklist().
+ //
+ // Malformed pairs in the string are ignored, including invalid UUID or
+ // exclusion values. Duplicate UUIDs follow Add()'s merging rule.
+ void Add(base::StringPiece blacklist_string);
+
+ // Returns if a UUID is excluded from all operations. UUID must be valid.
+ bool IsExcluded(const device::BluetoothUUID&) const;
+
+ // Returns if any UUID in a set of filters is excluded from all operations.
+ // UUID must be valid.
+ bool IsExcluded(const std::vector<content::BluetoothScanFilter>&);
+
+ // Returns if a UUID is excluded from read operations. UUID must be valid.
+ bool IsExcludedFromReads(const device::BluetoothUUID&) const;
+
+ // Returns if a UUID is excluded from write operations. UUID must be valid.
+ bool IsExcludedFromWrites(const device::BluetoothUUID&) const;
+
+ // Modifies a list of UUIDs, removing any UUIDs with Value::EXCLUDE.
+ void RemoveExcludedUuids(std::vector<device::BluetoothUUID>*);
+
+ // Size of blacklist.
+ size_t size() { return blacklisted_uuids_.size(); }
+
+ void ResetToDefaultValuesForTest();
+
+ private:
+ // friend LazyInstance to permit access to private constructor.
+ friend base::DefaultLazyInstanceTraits<BluetoothBlacklist>;
+
+ BluetoothBlacklist();
+
+ void PopulateWithDefaultValues();
+
+ // Populates blacklist with values obtained dynamically from a server, able
+ // to be updated without shipping new executable versions.
+ void PopulateWithServerProvidedValues();
+
+ // Map of UUID to blacklisted value.
+ std::map<device::BluetoothUUID, Value> blacklisted_uuids_;
+
+ DISALLOW_COPY_AND_ASSIGN(BluetoothBlacklist);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_BLUETOOTH_BLUETOOTH_BLACKLIST_H_
diff --git a/chromium/content/browser/bluetooth/bluetooth_blacklist_unittest.cc b/chromium/content/browser/bluetooth/bluetooth_blacklist_unittest.cc
new file mode 100644
index 00000000000..b0ed9c2c6a1
--- /dev/null
+++ b/chromium/content/browser/bluetooth/bluetooth_blacklist_unittest.cc
@@ -0,0 +1,398 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/bluetooth/bluetooth_blacklist.h"
+
+#include "content/common/bluetooth/bluetooth_scan_filter.h"
+#include "device/bluetooth/bluetooth_uuid.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using device::BluetoothUUID;
+
+namespace content {
+
+class BluetoothBlacklistTest : public ::testing::Test {
+ public:
+ BluetoothBlacklistTest() : list_(BluetoothBlacklist::Get()) {
+ // Because BluetoothBlacklist is used via a singleton instance, the data
+ // must be reset for each test.
+ list_.ResetToDefaultValuesForTest();
+ }
+ BluetoothBlacklist& list_;
+};
+
+TEST_F(BluetoothBlacklistTest, NonExcludedUUID) {
+ BluetoothUUID non_excluded_uuid("00000000-0000-0000-0000-000000000000");
+ EXPECT_FALSE(list_.IsExcluded(non_excluded_uuid));
+ EXPECT_FALSE(list_.IsExcludedFromReads(non_excluded_uuid));
+ EXPECT_FALSE(list_.IsExcludedFromWrites(non_excluded_uuid));
+}
+
+TEST_F(BluetoothBlacklistTest, ExcludeUUID) {
+ BluetoothUUID excluded_uuid("eeee");
+ list_.Add(excluded_uuid, BluetoothBlacklist::Value::EXCLUDE);
+ EXPECT_TRUE(list_.IsExcluded(excluded_uuid));
+ EXPECT_TRUE(list_.IsExcludedFromReads(excluded_uuid));
+ EXPECT_TRUE(list_.IsExcludedFromWrites(excluded_uuid));
+}
+
+TEST_F(BluetoothBlacklistTest, ExcludeReadsUUID) {
+ BluetoothUUID exclude_reads_uuid("eeee");
+ list_.Add(exclude_reads_uuid, BluetoothBlacklist::Value::EXCLUDE_READS);
+ EXPECT_FALSE(list_.IsExcluded(exclude_reads_uuid));
+ EXPECT_TRUE(list_.IsExcludedFromReads(exclude_reads_uuid));
+ EXPECT_FALSE(list_.IsExcludedFromWrites(exclude_reads_uuid));
+}
+
+TEST_F(BluetoothBlacklistTest, ExcludeWritesUUID) {
+ BluetoothUUID exclude_writes_uuid("eeee");
+ list_.Add(exclude_writes_uuid, BluetoothBlacklist::Value::EXCLUDE_WRITES);
+ EXPECT_FALSE(list_.IsExcluded(exclude_writes_uuid));
+ EXPECT_FALSE(list_.IsExcludedFromReads(exclude_writes_uuid));
+ EXPECT_TRUE(list_.IsExcludedFromWrites(exclude_writes_uuid));
+}
+
+TEST_F(BluetoothBlacklistTest, InvalidUUID) {
+ BluetoothUUID empty_string_uuid("");
+ EXPECT_DEATH_IF_SUPPORTED(
+ list_.Add(empty_string_uuid, BluetoothBlacklist::Value::EXCLUDE), "");
+ EXPECT_DEATH_IF_SUPPORTED(list_.IsExcluded(empty_string_uuid), "");
+ EXPECT_DEATH_IF_SUPPORTED(list_.IsExcludedFromReads(empty_string_uuid), "");
+ EXPECT_DEATH_IF_SUPPORTED(list_.IsExcludedFromWrites(empty_string_uuid), "");
+
+ BluetoothUUID invalid_string_uuid("Not a valid UUID string.");
+ EXPECT_DEATH_IF_SUPPORTED(
+ list_.Add(invalid_string_uuid, BluetoothBlacklist::Value::EXCLUDE), "");
+ EXPECT_DEATH_IF_SUPPORTED(list_.IsExcluded(invalid_string_uuid), "");
+ EXPECT_DEATH_IF_SUPPORTED(list_.IsExcludedFromReads(invalid_string_uuid), "");
+ EXPECT_DEATH_IF_SUPPORTED(list_.IsExcludedFromWrites(invalid_string_uuid),
+ "");
+}
+
+// Abreviated UUIDs used to create, or test against, the blacklist work
+// correctly compared to full UUIDs.
+TEST_F(BluetoothBlacklistTest, AbreviatedUUIDs) {
+ list_.Add(BluetoothUUID("aaaa"), BluetoothBlacklist::Value::EXCLUDE);
+ EXPECT_TRUE(
+ list_.IsExcluded(BluetoothUUID("0000aaaa-0000-1000-8000-00805f9b34fb")));
+
+ list_.Add(BluetoothUUID("0000bbbb-0000-1000-8000-00805f9b34fb"),
+ BluetoothBlacklist::Value::EXCLUDE);
+ EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("bbbb")));
+}
+
+// Tests permutations of previous values and then Add() with a new value,
+// requiring result to be strictest result of the combination.
+TEST_F(BluetoothBlacklistTest, Add_MergingExcludeValues) {
+ list_.Add(BluetoothUUID("ee01"), BluetoothBlacklist::Value::EXCLUDE);
+ list_.Add(BluetoothUUID("ee01"), BluetoothBlacklist::Value::EXCLUDE);
+ EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("ee01")));
+
+ list_.Add(BluetoothUUID("ee02"), BluetoothBlacklist::Value::EXCLUDE);
+ list_.Add(BluetoothUUID("ee02"), BluetoothBlacklist::Value::EXCLUDE_READS);
+ EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("ee02")));
+
+ list_.Add(BluetoothUUID("ee03"), BluetoothBlacklist::Value::EXCLUDE);
+ list_.Add(BluetoothUUID("ee03"), BluetoothBlacklist::Value::EXCLUDE_WRITES);
+ EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("ee03")));
+
+ list_.Add(BluetoothUUID("ee04"), BluetoothBlacklist::Value::EXCLUDE_READS);
+ list_.Add(BluetoothUUID("ee04"), BluetoothBlacklist::Value::EXCLUDE);
+ EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("ee04")));
+
+ list_.Add(BluetoothUUID("ee05"), BluetoothBlacklist::Value::EXCLUDE_READS);
+ list_.Add(BluetoothUUID("ee05"), BluetoothBlacklist::Value::EXCLUDE_READS);
+ EXPECT_FALSE(list_.IsExcluded(BluetoothUUID("ee05")));
+ EXPECT_TRUE(list_.IsExcludedFromReads(BluetoothUUID("ee05")));
+
+ list_.Add(BluetoothUUID("ee06"), BluetoothBlacklist::Value::EXCLUDE_READS);
+ list_.Add(BluetoothUUID("ee06"), BluetoothBlacklist::Value::EXCLUDE_WRITES);
+ EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("ee06")));
+
+ list_.Add(BluetoothUUID("ee07"), BluetoothBlacklist::Value::EXCLUDE_WRITES);
+ list_.Add(BluetoothUUID("ee07"), BluetoothBlacklist::Value::EXCLUDE);
+ EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("ee07")));
+
+ list_.Add(BluetoothUUID("ee08"), BluetoothBlacklist::Value::EXCLUDE_WRITES);
+ list_.Add(BluetoothUUID("ee08"), BluetoothBlacklist::Value::EXCLUDE_READS);
+ EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("ee08")));
+
+ list_.Add(BluetoothUUID("ee09"), BluetoothBlacklist::Value::EXCLUDE_WRITES);
+ list_.Add(BluetoothUUID("ee09"), BluetoothBlacklist::Value::EXCLUDE_WRITES);
+ EXPECT_FALSE(list_.IsExcluded(BluetoothUUID("ee09")));
+ EXPECT_TRUE(list_.IsExcludedFromWrites(BluetoothUUID("ee09")));
+}
+
+// Tests Add() with string that contains many UUID:exclusion value pairs,
+// checking that the correct blacklist entries are created for them.
+TEST_F(BluetoothBlacklistTest, Add_StringWithValidEntries) {
+ list_.Add(
+ "0001:e,0002:r,0003:w, " // Single items.
+ "0004:r,0004:r, " // Duplicate items.
+ "0005:r,0005:w, " // Items that merge.
+ "00000006:e, " // 8 char UUID.
+ "00000007-0000-1000-8000-00805f9b34fb:e");
+
+ EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("0001")));
+
+ EXPECT_FALSE(list_.IsExcluded(BluetoothUUID("0002")));
+ EXPECT_TRUE(list_.IsExcludedFromReads(BluetoothUUID("0002")));
+
+ EXPECT_FALSE(list_.IsExcluded(BluetoothUUID("0003")));
+ EXPECT_TRUE(list_.IsExcludedFromWrites(BluetoothUUID("0003")));
+
+ EXPECT_FALSE(list_.IsExcluded(BluetoothUUID("0004")));
+ EXPECT_TRUE(list_.IsExcludedFromReads(BluetoothUUID("0004")));
+
+ EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("0005")));
+ EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("0006")));
+ EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("0007")));
+}
+
+// Tests Add() with strings that contain no valid UUID:exclusion value.
+TEST_F(BluetoothBlacklistTest, Add_StringsWithNoValidEntries) {
+ size_t previous_list_size = list_.size();
+ list_.Add("");
+ list_.Add("~!@#$%^&*()-_=+[]{}/*-");
+ list_.Add(":");
+ list_.Add(",");
+ list_.Add(",,");
+ list_.Add(",:,");
+ list_.Add("1234:");
+ list_.Add("1234:q");
+ list_.Add("1234:E");
+ list_.Add("1234:R");
+ list_.Add("1234:W");
+ list_.Add("1234:ee");
+ list_.Add("1234 :e");
+ list_.Add("1234: e");
+ list_.Add("1:e");
+ list_.Add("1:r");
+ list_.Add("1:w");
+ list_.Add("00001800-0000-1000-8000-00805f9b34fb:ee");
+ list_.Add("z0001800-0000-1000-8000-00805f9b34fb:e");
+ list_.Add("☯");
+ EXPECT_EQ(previous_list_size, list_.size());
+}
+
+// Tests Add() with strings that contain exactly one valid UUID:exclusion value
+// pair, and optionally other issues in the string that are ignored.
+TEST_F(BluetoothBlacklistTest, Add_StringsWithOneValidEntry) {
+ size_t previous_list_size = list_.size();
+ list_.Add("0001:e");
+ EXPECT_EQ(++previous_list_size, list_.size());
+ EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("0001")));
+
+ list_.Add("00000002:e");
+ EXPECT_EQ(++previous_list_size, list_.size());
+ EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("0002")));
+
+ list_.Add("00000003-0000-1000-8000-00805f9b34fb:e");
+ EXPECT_EQ(++previous_list_size, list_.size());
+ EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("0003")));
+
+ list_.Add(" 0004:e ");
+ EXPECT_EQ(++previous_list_size, list_.size());
+ EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("0004")));
+
+ list_.Add(", 0005:e ,");
+ EXPECT_EQ(++previous_list_size, list_.size());
+ EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("0005")));
+
+ list_.Add(":, 0006:e ,,no");
+ EXPECT_EQ(++previous_list_size, list_.size());
+ EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("0006")));
+
+ list_.Add("0007:, 0008:e");
+ EXPECT_EQ(++previous_list_size, list_.size());
+ EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("0008")));
+
+ list_.Add("\r\n0009:e\n\r");
+ EXPECT_EQ(++previous_list_size, list_.size());
+ EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("0009")));
+}
+
+TEST_F(BluetoothBlacklistTest, IsExcluded_BluetoothScanFilter_ReturnsFalse) {
+ list_.Add(BluetoothUUID("eeee"), BluetoothBlacklist::Value::EXCLUDE);
+ list_.Add(BluetoothUUID("ee01"), BluetoothBlacklist::Value::EXCLUDE_READS);
+ list_.Add(BluetoothUUID("ee02"), BluetoothBlacklist::Value::EXCLUDE_WRITES);
+ {
+ std::vector<BluetoothScanFilter> empty_filters;
+ EXPECT_FALSE(list_.IsExcluded(empty_filters));
+ }
+ {
+ std::vector<BluetoothScanFilter> single_empty_filter(1);
+ EXPECT_EQ(0u, single_empty_filter[0].services.size());
+ EXPECT_FALSE(list_.IsExcluded(single_empty_filter));
+ }
+ {
+ std::vector<BluetoothScanFilter> single_non_matching_filter(1);
+ single_non_matching_filter[0].services.push_back(BluetoothUUID("0000"));
+ EXPECT_FALSE(list_.IsExcluded(single_non_matching_filter));
+ }
+ {
+ std::vector<BluetoothScanFilter> multiple_non_matching_filter(2);
+ multiple_non_matching_filter[0].services.push_back(BluetoothUUID("0000"));
+ multiple_non_matching_filter[0].services.push_back(BluetoothUUID("ee01"));
+ multiple_non_matching_filter[1].services.push_back(BluetoothUUID("ee02"));
+ multiple_non_matching_filter[1].services.push_back(BluetoothUUID("0003"));
+ EXPECT_FALSE(list_.IsExcluded(multiple_non_matching_filter));
+ }
+}
+
+TEST_F(BluetoothBlacklistTest, IsExcluded_BluetoothScanFilter_ReturnsTrue) {
+ list_.Add(BluetoothUUID("eeee"), BluetoothBlacklist::Value::EXCLUDE);
+ {
+ std::vector<BluetoothScanFilter> single_matching_filter(1);
+ single_matching_filter[0].services.push_back(BluetoothUUID("eeee"));
+ EXPECT_TRUE(list_.IsExcluded(single_matching_filter));
+ }
+ {
+ std::vector<BluetoothScanFilter> first_matching_filter(2);
+ first_matching_filter[0].services.push_back(BluetoothUUID("eeee"));
+ first_matching_filter[0].services.push_back(BluetoothUUID("0001"));
+ first_matching_filter[1].services.push_back(BluetoothUUID("0002"));
+ first_matching_filter[1].services.push_back(BluetoothUUID("0003"));
+ EXPECT_TRUE(list_.IsExcluded(first_matching_filter));
+ }
+ {
+ std::vector<BluetoothScanFilter> last_matching_filter(2);
+ last_matching_filter[0].services.push_back(BluetoothUUID("0001"));
+ last_matching_filter[0].services.push_back(BluetoothUUID("0001"));
+ last_matching_filter[1].services.push_back(BluetoothUUID("0002"));
+ last_matching_filter[1].services.push_back(BluetoothUUID("eeee"));
+ EXPECT_TRUE(list_.IsExcluded(last_matching_filter));
+ }
+ {
+ std::vector<BluetoothScanFilter> multiple_matching_filter(2);
+ multiple_matching_filter[0].services.push_back(BluetoothUUID("eeee"));
+ multiple_matching_filter[0].services.push_back(BluetoothUUID("eeee"));
+ multiple_matching_filter[1].services.push_back(BluetoothUUID("eeee"));
+ multiple_matching_filter[1].services.push_back(BluetoothUUID("eeee"));
+ EXPECT_TRUE(list_.IsExcluded(multiple_matching_filter));
+ }
+}
+
+TEST_F(BluetoothBlacklistTest, RemoveExcludedUuids_NonMatching) {
+ list_.Add(BluetoothUUID("eeee"), BluetoothBlacklist::Value::EXCLUDE);
+ list_.Add(BluetoothUUID("ee01"), BluetoothBlacklist::Value::EXCLUDE_READS);
+ list_.Add(BluetoothUUID("ee02"), BluetoothBlacklist::Value::EXCLUDE_WRITES);
+ {
+ std::vector<BluetoothUUID> empty;
+ std::vector<BluetoothUUID> expected_empty;
+ list_.RemoveExcludedUuids(&empty);
+ EXPECT_EQ(expected_empty, empty);
+ }
+ {
+ std::vector<BluetoothUUID> single_non_matching;
+ single_non_matching.push_back(BluetoothUUID("0000"));
+
+ std::vector<BluetoothUUID> expected_copy(single_non_matching);
+
+ list_.RemoveExcludedUuids(&single_non_matching);
+ EXPECT_EQ(expected_copy, single_non_matching);
+ }
+ {
+ std::vector<BluetoothUUID> multiple_non_matching;
+ multiple_non_matching.push_back(BluetoothUUID("0000"));
+ multiple_non_matching.push_back(BluetoothUUID("ee01"));
+ multiple_non_matching.push_back(BluetoothUUID("ee02"));
+ multiple_non_matching.push_back(BluetoothUUID("0003"));
+
+ std::vector<BluetoothUUID> expected_copy(multiple_non_matching);
+
+ list_.RemoveExcludedUuids(&multiple_non_matching);
+ EXPECT_EQ(expected_copy, multiple_non_matching);
+ }
+}
+
+TEST_F(BluetoothBlacklistTest, RemoveExcludedUuids_Matching) {
+ list_.Add(BluetoothUUID("eeee"), BluetoothBlacklist::Value::EXCLUDE);
+ list_.Add(BluetoothUUID("eee2"), BluetoothBlacklist::Value::EXCLUDE);
+ list_.Add(BluetoothUUID("eee3"), BluetoothBlacklist::Value::EXCLUDE);
+ list_.Add(BluetoothUUID("eee4"), BluetoothBlacklist::Value::EXCLUDE);
+ {
+ std::vector<BluetoothUUID> single_matching;
+ single_matching.push_back(BluetoothUUID("eeee"));
+
+ std::vector<BluetoothUUID> expected_empty;
+
+ list_.RemoveExcludedUuids(&single_matching);
+ EXPECT_EQ(expected_empty, single_matching);
+ }
+ {
+ std::vector<BluetoothUUID> single_matching_of_many;
+ single_matching_of_many.push_back(BluetoothUUID("0000"));
+ single_matching_of_many.push_back(BluetoothUUID("eeee"));
+ single_matching_of_many.push_back(BluetoothUUID("0001"));
+
+ std::vector<BluetoothUUID> expected;
+ expected.push_back(BluetoothUUID("0000"));
+ expected.push_back(BluetoothUUID("0001"));
+
+ list_.RemoveExcludedUuids(&single_matching_of_many);
+ EXPECT_EQ(expected, single_matching_of_many);
+ }
+ {
+ std::vector<BluetoothUUID> all_matching_of_many;
+ all_matching_of_many.push_back(BluetoothUUID("eee2"));
+ all_matching_of_many.push_back(BluetoothUUID("eee4"));
+ all_matching_of_many.push_back(BluetoothUUID("eee3"));
+ all_matching_of_many.push_back(BluetoothUUID("eeee"));
+
+ std::vector<BluetoothUUID> expected_empty;
+
+ list_.RemoveExcludedUuids(&all_matching_of_many);
+ EXPECT_EQ(expected_empty, all_matching_of_many);
+ }
+}
+
+TEST_F(BluetoothBlacklistTest, VerifyDefaultBlacklistSize) {
+ // When adding items to the blacklist the new values should be added in the
+ // tests below for each exclusion type.
+ EXPECT_EQ(11u, list_.size());
+}
+
+TEST_F(BluetoothBlacklistTest, VerifyDefaultExcludeList) {
+ EXPECT_FALSE(list_.IsExcluded(BluetoothUUID("1800")));
+ EXPECT_FALSE(list_.IsExcluded(BluetoothUUID("1801")));
+ EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("1812")));
+ EXPECT_TRUE(
+ list_.IsExcluded(BluetoothUUID("00001530-1212-efde-1523-785feabcd123")));
+ EXPECT_TRUE(
+ list_.IsExcluded(BluetoothUUID("f000ffc0-0451-4000-b000-000000000000")));
+ EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("2a03")));
+ EXPECT_TRUE(list_.IsExcluded(BluetoothUUID("2a25")));
+ EXPECT_TRUE(
+ list_.IsExcluded(BluetoothUUID("bad2ddcf-60db-45cd-bef9-fd72b153cf7c")));
+}
+
+TEST_F(BluetoothBlacklistTest, VerifyDefaultExcludeReadList) {
+ EXPECT_FALSE(list_.IsExcludedFromReads(BluetoothUUID("1800")));
+ EXPECT_FALSE(list_.IsExcludedFromReads(BluetoothUUID("1801")));
+ EXPECT_TRUE(list_.IsExcludedFromReads(BluetoothUUID("1812")));
+ EXPECT_TRUE(list_.IsExcludedFromReads(BluetoothUUID("2a03")));
+ EXPECT_TRUE(list_.IsExcludedFromReads(BluetoothUUID("2a25")));
+ EXPECT_TRUE(list_.IsExcludedFromReads(
+ BluetoothUUID("bad1c9a2-9a5b-4015-8b60-1579bbbf2135")));
+ EXPECT_TRUE(list_.IsExcludedFromReads(
+ BluetoothUUID("bad2ddcf-60db-45cd-bef9-fd72b153cf7c")));
+ EXPECT_TRUE(list_.IsExcludedFromReads(
+ BluetoothUUID("bad3ec61-3cc3-4954-9702-7977df514114")));
+}
+
+TEST_F(BluetoothBlacklistTest, VerifyDefaultExcludeWriteList) {
+ EXPECT_FALSE(list_.IsExcludedFromWrites(BluetoothUUID("1800")));
+ EXPECT_FALSE(list_.IsExcludedFromWrites(BluetoothUUID("1801")));
+ EXPECT_TRUE(list_.IsExcludedFromWrites(BluetoothUUID("1812")));
+ EXPECT_TRUE(list_.IsExcludedFromWrites(BluetoothUUID("2a02")));
+ EXPECT_TRUE(list_.IsExcludedFromWrites(BluetoothUUID("2a03")));
+ EXPECT_TRUE(list_.IsExcludedFromWrites(BluetoothUUID("2a25")));
+ EXPECT_TRUE(list_.IsExcludedFromWrites(BluetoothUUID("2902")));
+ EXPECT_TRUE(list_.IsExcludedFromWrites(BluetoothUUID("2903")));
+ EXPECT_TRUE(list_.IsExcludedFromWrites(
+ BluetoothUUID("bad2ddcf-60db-45cd-bef9-fd72b153cf7c")));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/bluetooth/bluetooth_dispatcher_host.cc b/chromium/content/browser/bluetooth/bluetooth_dispatcher_host.cc
index 85bf81e0003..f8444caec79 100644
--- a/chromium/content/browser/bluetooth/bluetooth_dispatcher_host.cc
+++ b/chromium/content/browser/bluetooth/bluetooth_dispatcher_host.cc
@@ -20,10 +20,11 @@
#include "base/strings/utf_string_conversions.h"
#include "base/thread_task_runner_handle.h"
#include "content/browser/bad_message.h"
-#include "content/browser/bluetooth/bluetooth_metrics.h"
+#include "content/browser/bluetooth/bluetooth_blacklist.h"
#include "content/browser/bluetooth/first_device_bluetooth_chooser.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
-#include "content/common/bluetooth/bluetooth_messages.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "device/bluetooth/bluetooth_adapter.h"
@@ -116,94 +117,94 @@ WebBluetoothError TranslateConnectError(
switch (error_code) {
case device::BluetoothDevice::ERROR_UNKNOWN:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::UNKNOWN);
- return WebBluetoothError::ConnectUnknownError;
+ return WebBluetoothError::CONNECT_UNKNOWN_ERROR;
case device::BluetoothDevice::ERROR_INPROGRESS:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::IN_PROGRESS);
- return WebBluetoothError::ConnectAlreadyInProgress;
+ return WebBluetoothError::CONNECT_ALREADY_IN_PROGRESS;
case device::BluetoothDevice::ERROR_FAILED:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::FAILED);
- return WebBluetoothError::ConnectUnknownFailure;
+ return WebBluetoothError::CONNECT_UNKNOWN_FAILURE;
case device::BluetoothDevice::ERROR_AUTH_FAILED:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::AUTH_FAILED);
- return WebBluetoothError::ConnectAuthFailed;
+ return WebBluetoothError::CONNECT_AUTH_FAILED;
case device::BluetoothDevice::ERROR_AUTH_CANCELED:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::AUTH_CANCELED);
- return WebBluetoothError::ConnectAuthCanceled;
+ return WebBluetoothError::CONNECT_AUTH_CANCELED;
case device::BluetoothDevice::ERROR_AUTH_REJECTED:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::AUTH_REJECTED);
- return WebBluetoothError::ConnectAuthRejected;
+ return WebBluetoothError::CONNECT_AUTH_REJECTED;
case device::BluetoothDevice::ERROR_AUTH_TIMEOUT:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::AUTH_TIMEOUT);
- return WebBluetoothError::ConnectAuthTimeout;
+ return WebBluetoothError::CONNECT_AUTH_TIMEOUT;
case device::BluetoothDevice::ERROR_UNSUPPORTED_DEVICE:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::UNSUPPORTED_DEVICE);
- return WebBluetoothError::ConnectUnsupportedDevice;
+ return WebBluetoothError::CONNECT_UNSUPPORTED_DEVICE;
case device::BluetoothDevice::ERROR_ATTRIBUTE_LENGTH_INVALID:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::ATTRIBUTE_LENGTH_INVALID);
- return WebBluetoothError::ConnectAttributeLengthInvalid;
+ return WebBluetoothError::CONNECT_ATTRIBUTE_LENGTH_INVALID;
case device::BluetoothDevice::ERROR_CONNECTION_CONGESTED:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::CONNECTION_CONGESTED);
- return WebBluetoothError::ConnectConnectionCongested;
+ return WebBluetoothError::CONNECT_CONNECTION_CONGESTED;
case device::BluetoothDevice::ERROR_INSUFFICIENT_ENCRYPTION:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::INSUFFICIENT_ENCRYPTION);
- return WebBluetoothError::ConnectInsufficientEncryption;
+ return WebBluetoothError::CONNECT_INSUFFICIENT_ENCRYPTION;
case device::BluetoothDevice::ERROR_OFFSET_INVALID:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::OFFSET_INVALID);
- return WebBluetoothError::ConnectOffsetInvalid;
+ return WebBluetoothError::CONNECT_OFFSET_INVALID;
case device::BluetoothDevice::ERROR_READ_NOT_PERMITTED:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::READ_NOT_PERMITTED);
- return WebBluetoothError::ConnectReadNotPermitted;
+ return WebBluetoothError::CONNECT_READ_NOT_PERMITTED;
case device::BluetoothDevice::ERROR_REQUEST_NOT_SUPPORTED:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::REQUEST_NOT_SUPPORTED);
- return WebBluetoothError::ConnectRequestNotSupported;
+ return WebBluetoothError::CONNECT_REQUEST_NOT_SUPPORTED;
case device::BluetoothDevice::ERROR_WRITE_NOT_PERMITTED:
RecordConnectGATTOutcome(UMAConnectGATTOutcome::WRITE_NOT_PERMITTED);
- return WebBluetoothError::ConnectWriteNotPermitted;
+ return WebBluetoothError::CONNECT_WRITE_NOT_PERMITTED;
case device::BluetoothDevice::NUM_CONNECT_ERROR_CODES:
NOTREACHED();
- return WebBluetoothError::UntranslatedConnectErrorCode;
+ return WebBluetoothError::UNTRANSLATED_CONNECT_ERROR_CODE;
}
NOTREACHED();
- return WebBluetoothError::UntranslatedConnectErrorCode;
+ return WebBluetoothError::UNTRANSLATED_CONNECT_ERROR_CODE;
}
-blink::WebBluetoothError TranslateGATTError(
+WebBluetoothError TranslateGATTError(
BluetoothGattService::GattErrorCode error_code,
UMAGATTOperation operation) {
switch (error_code) {
case BluetoothGattService::GATT_ERROR_UNKNOWN:
RecordGATTOperationOutcome(operation, UMAGATTOperationOutcome::UNKNOWN);
- return blink::WebBluetoothError::GATTUnknownError;
+ return blink::WebBluetoothError::GATT_UNKNOWN_ERROR;
case BluetoothGattService::GATT_ERROR_FAILED:
RecordGATTOperationOutcome(operation, UMAGATTOperationOutcome::FAILED);
- return blink::WebBluetoothError::GATTUnknownFailure;
+ return blink::WebBluetoothError::GATT_UNKNOWN_FAILURE;
case BluetoothGattService::GATT_ERROR_IN_PROGRESS:
RecordGATTOperationOutcome(operation,
UMAGATTOperationOutcome::IN_PROGRESS);
- return blink::WebBluetoothError::GATTOperationInProgress;
+ return blink::WebBluetoothError::GATT_OPERATION_IN_PROGRESS;
case BluetoothGattService::GATT_ERROR_INVALID_LENGTH:
RecordGATTOperationOutcome(operation,
UMAGATTOperationOutcome::INVALID_LENGTH);
- return blink::WebBluetoothError::GATTInvalidAttributeLength;
+ return blink::WebBluetoothError::GATT_INVALID_ATTRIBUTE_LENGTH;
case BluetoothGattService::GATT_ERROR_NOT_PERMITTED:
RecordGATTOperationOutcome(operation,
UMAGATTOperationOutcome::NOT_PERMITTED);
- return blink::WebBluetoothError::GATTNotPermitted;
+ return blink::WebBluetoothError::GATT_NOT_PERMITTED;
case BluetoothGattService::GATT_ERROR_NOT_AUTHORIZED:
RecordGATTOperationOutcome(operation,
UMAGATTOperationOutcome::NOT_AUTHORIZED);
- return blink::WebBluetoothError::GATTNotAuthorized;
+ return blink::WebBluetoothError::GATT_NOT_AUTHORIZED;
case BluetoothGattService::GATT_ERROR_NOT_PAIRED:
RecordGATTOperationOutcome(operation,
UMAGATTOperationOutcome::NOT_PAIRED);
- return blink::WebBluetoothError::GATTNotPaired;
+ return blink::WebBluetoothError::GATT_NOT_PAIRED;
case BluetoothGattService::GATT_ERROR_NOT_SUPPORTED:
RecordGATTOperationOutcome(operation,
UMAGATTOperationOutcome::NOT_SUPPORTED);
- return blink::WebBluetoothError::GATTNotSupported;
+ return blink::WebBluetoothError::GATT_NOT_SUPPORTED;
}
NOTREACHED();
- return blink::WebBluetoothError::GATTUntranslatedErrorCode;
+ return blink::WebBluetoothError::GATT_UNTRANSLATED_ERROR_CODE;
}
void StopDiscoverySession(
@@ -232,6 +233,34 @@ std::vector<BluetoothGattService*> GetPrimaryServicesByUUID(
return services;
}
+UMARequestDeviceOutcome OutcomeFromChooserEvent(BluetoothChooser::Event event) {
+ switch (event) {
+ case BluetoothChooser::Event::DENIED_PERMISSION:
+ return UMARequestDeviceOutcome::BLUETOOTH_CHOOSER_DENIED_PERMISSION;
+ case BluetoothChooser::Event::CANCELLED:
+ return UMARequestDeviceOutcome::BLUETOOTH_CHOOSER_CANCELLED;
+ case BluetoothChooser::Event::SHOW_OVERVIEW_HELP:
+ return UMARequestDeviceOutcome::BLUETOOTH_OVERVIEW_HELP_LINK_PRESSED;
+ case BluetoothChooser::Event::SHOW_ADAPTER_OFF_HELP:
+ return UMARequestDeviceOutcome::ADAPTER_OFF_HELP_LINK_PRESSED;
+ case BluetoothChooser::Event::SHOW_NEED_LOCATION_HELP:
+ return UMARequestDeviceOutcome::NEED_LOCATION_HELP_LINK_PRESSED;
+ case BluetoothChooser::Event::SELECTED:
+ // We can't know if we are going to send a success message yet because
+ // the device could have vanished. This event should be histogramed
+ // manually after checking if the device is still around.
+ NOTREACHED();
+ return UMARequestDeviceOutcome::SUCCESS;
+ case BluetoothChooser::Event::RESCAN:
+ // Rescanning doesn't result in a IPC message for the request being sent
+ // so no need to histogram it.
+ NOTREACHED();
+ return UMARequestDeviceOutcome::SUCCESS;
+ }
+ NOTREACHED();
+ return UMARequestDeviceOutcome::SUCCESS;
+}
+
} // namespace
BluetoothDispatcherHost::BluetoothDispatcherHost(int render_process_id)
@@ -251,14 +280,11 @@ BluetoothDispatcherHost::BluetoothDispatcherHost(int render_process_id)
weak_ptr_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ connected_devices_map_.reset(new ConnectedDevicesMap(render_process_id));
+
// Bind all future weak pointers to the UI thread.
weak_ptr_on_ui_thread_ = weak_ptr_factory_.GetWeakPtr();
weak_ptr_on_ui_thread_.get(); // Associates with UI thread.
-
- if (BluetoothAdapterFactory::IsBluetoothAdapterAvailable())
- BluetoothAdapterFactory::GetAdapter(
- base::Bind(&BluetoothDispatcherHost::set_adapter,
- weak_ptr_factory_.GetWeakPtr()));
}
void BluetoothDispatcherHost::OnDestruct() const {
@@ -278,11 +304,13 @@ bool BluetoothDispatcherHost::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(BluetoothDispatcherHost, message)
IPC_MESSAGE_HANDLER(BluetoothHostMsg_RequestDevice, OnRequestDevice)
- IPC_MESSAGE_HANDLER(BluetoothHostMsg_ConnectGATT, OnConnectGATT)
+ IPC_MESSAGE_HANDLER(BluetoothHostMsg_GATTServerConnect, OnGATTServerConnect)
+ IPC_MESSAGE_HANDLER(BluetoothHostMsg_GATTServerDisconnect,
+ OnGATTServerDisconnect)
IPC_MESSAGE_HANDLER(BluetoothHostMsg_GetPrimaryService, OnGetPrimaryService)
IPC_MESSAGE_HANDLER(BluetoothHostMsg_GetCharacteristic, OnGetCharacteristic)
+ IPC_MESSAGE_HANDLER(BluetoothHostMsg_GetCharacteristics, OnGetCharacteristics)
IPC_MESSAGE_HANDLER(BluetoothHostMsg_ReadValue, OnReadValue)
- IPC_MESSAGE_HANDLER(BluetoothHostMsg_WriteValue, OnWriteValue)
IPC_MESSAGE_HANDLER(BluetoothHostMsg_StartNotifications, OnStartNotifications)
IPC_MESSAGE_HANDLER(BluetoothHostMsg_StopNotifications, OnStopNotifications)
IPC_MESSAGE_HANDLER(BluetoothHostMsg_RegisterCharacteristic,
@@ -321,7 +349,8 @@ void BluetoothDispatcherHost::SetBluetoothAdapterForTesting(
characteristic_to_service_.clear();
characteristic_id_to_notify_session_.clear();
active_characteristic_threads_.clear();
- connections_.clear();
+ connected_devices_map_.reset(new ConnectedDevicesMap(render_process_id_));
+ allowed_devices_map_ = BluetoothAllowedDevicesMap();
}
set_adapter(std::move(mock_adapter));
@@ -339,11 +368,13 @@ struct BluetoothDispatcherHost::RequestDeviceSession {
public:
RequestDeviceSession(int thread_id,
int request_id,
+ int frame_routing_id,
url::Origin origin,
const std::vector<BluetoothScanFilter>& filters,
const std::vector<BluetoothUUID>& optional_services)
: thread_id(thread_id),
request_id(request_id),
+ frame_routing_id(frame_routing_id),
origin(origin),
filters(filters),
optional_services(optional_services) {}
@@ -370,6 +401,7 @@ struct BluetoothDispatcherHost::RequestDeviceSession {
const int thread_id;
const int request_id;
+ const int frame_routing_id;
const url::Origin origin;
const std::vector<BluetoothScanFilter> filters;
const std::vector<BluetoothUUID> optional_services;
@@ -377,40 +409,31 @@ struct BluetoothDispatcherHost::RequestDeviceSession {
scoped_ptr<device::BluetoothDiscoverySession> discovery_session;
};
-struct BluetoothDispatcherHost::CacheQueryResult {
- CacheQueryResult()
- : device(nullptr),
- service(nullptr),
- characteristic(nullptr),
- outcome(CacheQueryOutcome::SUCCESS) {}
- CacheQueryResult(CacheQueryOutcome outcome)
- : device(nullptr),
- service(nullptr),
- characteristic(nullptr),
- outcome(outcome) {}
- ~CacheQueryResult() {}
- WebBluetoothError GetWebError() const {
- switch (outcome) {
- case CacheQueryOutcome::SUCCESS:
- case CacheQueryOutcome::BAD_RENDERER:
- NOTREACHED();
- return WebBluetoothError::DeviceNoLongerInRange;
- case CacheQueryOutcome::NO_DEVICE:
- return WebBluetoothError::DeviceNoLongerInRange;
- case CacheQueryOutcome::NO_SERVICE:
- return WebBluetoothError::ServiceNoLongerExists;
- case CacheQueryOutcome::NO_CHARACTERISTIC:
- return WebBluetoothError::CharacteristicNoLongerExists;
- }
- NOTREACHED();
- return WebBluetoothError::DeviceNoLongerInRange;
- }
+BluetoothDispatcherHost::CacheQueryResult::CacheQueryResult() {}
- device::BluetoothDevice* device;
- device::BluetoothGattService* service;
- device::BluetoothGattCharacteristic* characteristic;
- CacheQueryOutcome outcome;
-};
+BluetoothDispatcherHost::CacheQueryResult::CacheQueryResult(
+ CacheQueryOutcome outcome)
+ : outcome(outcome) {}
+
+BluetoothDispatcherHost::CacheQueryResult::~CacheQueryResult() {}
+
+WebBluetoothError BluetoothDispatcherHost::CacheQueryResult::GetWebError()
+ const {
+ switch (outcome) {
+ case CacheQueryOutcome::SUCCESS:
+ case CacheQueryOutcome::BAD_RENDERER:
+ NOTREACHED();
+ return WebBluetoothError::DEVICE_NO_LONGER_IN_RANGE;
+ case CacheQueryOutcome::NO_DEVICE:
+ return WebBluetoothError::DEVICE_NO_LONGER_IN_RANGE;
+ case CacheQueryOutcome::NO_SERVICE:
+ return WebBluetoothError::SERVICE_NO_LONGER_EXISTS;
+ case CacheQueryOutcome::NO_CHARACTERISTIC:
+ return WebBluetoothError::CHARACTERISTIC_NO_LONGER_EXISTS;
+ }
+ NOTREACHED();
+ return WebBluetoothError::DEVICE_NO_LONGER_IN_RANGE;
+}
struct BluetoothDispatcherHost::PrimaryServicesRequest {
enum CallingFunction { GET_PRIMARY_SERVICE, GET_PRIMARY_SERVICES };
@@ -431,10 +454,74 @@ struct BluetoothDispatcherHost::PrimaryServicesRequest {
CallingFunction func;
};
+BluetoothDispatcherHost::ConnectedDevicesMap::ConnectedDevicesMap(
+ int render_process_id)
+ : render_process_id_(render_process_id) {}
+
+BluetoothDispatcherHost::ConnectedDevicesMap::~ConnectedDevicesMap() {
+ for (auto frame_id_device_id : frame_ids_device_ids_) {
+ DecrementBluetoothConnectedDeviceCount(frame_id_device_id.first);
+ }
+}
+
+bool BluetoothDispatcherHost::ConnectedDevicesMap::HasActiveConnection(
+ const std::string& device_id) {
+ auto connection_iter = device_id_to_connection_map_.find(device_id);
+ if (connection_iter != device_id_to_connection_map_.end()) {
+ return connection_iter->second->IsConnected();
+ }
+ return false;
+}
+
+void BluetoothDispatcherHost::ConnectedDevicesMap::InsertOrReplace(
+ int frame_routing_id,
+ const std::string& device_id,
+ scoped_ptr<device::BluetoothGattConnection> connection) {
+ auto connection_iter = device_id_to_connection_map_.find(device_id);
+ if (connection_iter == device_id_to_connection_map_.end()) {
+ IncrementBluetoothConnectedDeviceCount(frame_routing_id);
+ frame_ids_device_ids_.insert(std::make_pair(frame_routing_id, device_id));
+ } else {
+ device_id_to_connection_map_.erase(connection_iter);
+ }
+ device_id_to_connection_map_[device_id] = std::move(connection);
+}
+
+void BluetoothDispatcherHost::ConnectedDevicesMap::Remove(
+ int frame_routing_id,
+ const std::string& device_id) {
+ if (device_id_to_connection_map_.erase(device_id)) {
+ VLOG(1) << "Disconnecting device: " << device_id;
+ DecrementBluetoothConnectedDeviceCount(frame_routing_id);
+ frame_ids_device_ids_.erase(std::make_pair(frame_routing_id, device_id));
+ }
+}
+
+void BluetoothDispatcherHost::ConnectedDevicesMap::
+ IncrementBluetoothConnectedDeviceCount(int frame_routing_id) {
+ RenderFrameHostImpl* render_frame_host =
+ RenderFrameHostImpl::FromID(render_process_id_, frame_routing_id);
+ WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
+ WebContents::FromRenderFrameHost(render_frame_host));
+ if (web_contents) {
+ web_contents->IncrementBluetoothConnectedDeviceCount();
+ }
+}
+
+void BluetoothDispatcherHost::ConnectedDevicesMap::
+ DecrementBluetoothConnectedDeviceCount(int frame_routing_id) {
+ RenderFrameHostImpl* render_frame_host =
+ RenderFrameHostImpl::FromID(render_process_id_, frame_routing_id);
+ WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
+ WebContents::FromRenderFrameHost(render_frame_host));
+ if (web_contents) {
+ web_contents->DecrementBluetoothConnectedDeviceCount();
+ }
+}
+
void BluetoothDispatcherHost::set_adapter(
scoped_refptr<device::BluetoothAdapter> adapter) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- connections_.clear();
if (adapter_.get())
adapter_->RemoveObserver(this);
adapter_ = adapter;
@@ -488,9 +575,21 @@ void BluetoothDispatcherHost::AdapterPoweredChanged(
&request_device_sessions_);
!iter.IsAtEnd(); iter.Advance()) {
RequestDeviceSession* session = iter.GetCurrentValue();
+
+ // Stop ongoing discovery session if power is off.
+ if (!powered && session->discovery_session) {
+ StopDiscoverySession(std::move(session->discovery_session));
+ }
+
if (session->chooser)
session->chooser->SetAdapterPresence(presence);
}
+
+ // Stop the timer so that we don't change the state of the chooser
+ // when timer expires.
+ if (!powered) {
+ discovery_session_timer_.Stop();
+ }
}
void BluetoothDispatcherHost::DeviceAdded(device::BluetoothAdapter* adapter,
@@ -548,7 +647,7 @@ void BluetoothDispatcherHost::GattServicesDiscovered(
UMAGetPrimaryServiceOutcome::NOT_FOUND);
Send(new BluetoothMsg_GetPrimaryServiceError(
request.thread_id, request.request_id,
- WebBluetoothError::ServiceNotFound));
+ WebBluetoothError::SERVICE_NOT_FOUND));
}
break;
case PrimaryServicesRequest::GET_PRIMARY_SERVICES:
@@ -606,118 +705,29 @@ void BluetoothDispatcherHost::OnRequestDevice(
RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::REQUEST_DEVICE);
RecordRequestDeviceArguments(filters, optional_services);
- VLOG(1) << "requestDevice called with the following filters: ";
- for (const BluetoothScanFilter& filter : filters) {
- VLOG(1) << "Name: " << filter.name;
- VLOG(1) << "Name Prefix: " << filter.namePrefix;
- VLOG(1) << "Services:";
- VLOG(1) << "\t[";
- for (const BluetoothUUID& service : filter.services)
- VLOG(1) << "\t\t" << service.value();
- VLOG(1) << "\t]";
- }
-
- VLOG(1) << "requestDevice called with the following optional services: ";
- for (const BluetoothUUID& service : optional_services)
- VLOG(1) << "\t" << service.value();
-
- RenderFrameHostImpl* render_frame_host =
- RenderFrameHostImpl::FromID(render_process_id_, frame_routing_id);
-
- if (!render_frame_host) {
- DLOG(WARNING)
- << "Got a requestDevice IPC without a matching RenderFrameHost: "
- << render_process_id_ << ", " << frame_routing_id;
- RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_RENDER_FRAME);
- Send(new BluetoothMsg_RequestDeviceError(
- thread_id, request_id, WebBluetoothError::RequestDeviceWithoutFrame));
- return;
- }
-
- if (!adapter_) {
- VLOG(1) << "No BluetoothAdapter. Can't serve requestDevice.";
+ if (!adapter_.get()) {
+ if (BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) {
+ BluetoothAdapterFactory::GetAdapter(base::Bind(
+ &BluetoothDispatcherHost::OnGetAdapter, weak_ptr_on_ui_thread_,
+ base::Bind(&BluetoothDispatcherHost::OnRequestDeviceImpl,
+ weak_ptr_on_ui_thread_, thread_id, request_id,
+ frame_routing_id, filters, optional_services)));
+ return;
+ }
RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_BLUETOOTH_ADAPTER);
Send(new BluetoothMsg_RequestDeviceError(
- thread_id, request_id, WebBluetoothError::NoBluetoothAdapter));
- return;
- }
-
- if (!adapter_->IsPresent()) {
- VLOG(1) << "Bluetooth Adapter not present. Can't serve requestDevice.";
- RecordRequestDeviceOutcome(
- UMARequestDeviceOutcome::BLUETOOTH_ADAPTER_NOT_PRESENT);
- Send(new BluetoothMsg_RequestDeviceError(
- thread_id, request_id, WebBluetoothError::NoBluetoothAdapter));
+ thread_id, request_id, WebBluetoothError::NO_BLUETOOTH_ADAPTER));
return;
}
-
- // The renderer should never send empty filters.
- if (HasEmptyOrInvalidFilter(filters)) {
- bad_message::ReceivedBadMessage(this,
- bad_message::BDH_EMPTY_OR_INVALID_FILTERS);
- return;
- }
-
- // Create storage for the information that backs the chooser, and show the
- // chooser.
- RequestDeviceSession* const session = new RequestDeviceSession(
- thread_id, request_id, render_frame_host->GetLastCommittedOrigin(),
- filters, optional_services);
- int chooser_id = request_device_sessions_.Add(session);
-
- BluetoothChooser::EventHandler chooser_event_handler =
- base::Bind(&BluetoothDispatcherHost::OnBluetoothChooserEvent,
- weak_ptr_on_ui_thread_, chooser_id);
- if (WebContents* web_contents =
- WebContents::FromRenderFrameHost(render_frame_host)) {
- if (WebContentsDelegate* delegate = web_contents->GetDelegate()) {
- session->chooser = delegate->RunBluetoothChooser(
- web_contents, chooser_event_handler,
- // TODO(ortuno): Replace with GetLastCommittedOrigin.
- // http://crbug.com/577451
- render_frame_host->GetLastCommittedURL().GetOrigin());
- }
- }
- if (!session->chooser) {
- LOG(WARNING)
- << "No Bluetooth chooser implementation; falling back to first device.";
- session->chooser.reset(
- new FirstDeviceBluetoothChooser(chooser_event_handler));
- }
-
- if (!session->chooser->CanAskForScanningPermission()) {
- VLOG(1) << "Closing immediately because Chooser cannot obtain permission.";
- OnBluetoothChooserEvent(chooser_id,
- BluetoothChooser::Event::DENIED_PERMISSION, "");
- return;
- }
-
- // Populate the initial list of devices.
- VLOG(1) << "Populating " << adapter_->GetDevices().size()
- << " devices in chooser " << chooser_id;
- for (const device::BluetoothDevice* device : adapter_->GetDevices()) {
- VLOG(1) << "\t" << device->GetAddress();
- session->AddFilteredDevice(*device);
- }
-
- if (!session->chooser) {
- // If the dialog's closing, no need to do any of the rest of this.
- return;
- }
-
- if (!adapter_->IsPowered()) {
- session->chooser->SetAdapterPresence(
- BluetoothChooser::AdapterPresence::POWERED_OFF);
- return;
- }
-
- StartDeviceDiscovery(session, chooser_id);
+ OnRequestDeviceImpl(thread_id, request_id, frame_routing_id, filters,
+ optional_services);
}
-void BluetoothDispatcherHost::OnConnectGATT(int thread_id,
- int request_id,
- int frame_routing_id,
- const std::string& device_id) {
+void BluetoothDispatcherHost::OnGATTServerConnect(
+ int thread_id,
+ int request_id,
+ int frame_routing_id,
+ const std::string& device_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::CONNECT_GATT);
const base::TimeTicks start_time = base::TimeTicks::Now();
@@ -727,20 +737,53 @@ void BluetoothDispatcherHost::OnConnectGATT(int thread_id,
if (query_result.outcome != CacheQueryOutcome::SUCCESS) {
RecordConnectGATTOutcome(query_result.outcome);
- Send(new BluetoothMsg_ConnectGATTError(thread_id, request_id,
- query_result.GetWebError()));
+ Send(new BluetoothMsg_GATTServerConnectError(thread_id, request_id,
+ query_result.GetWebError()));
+ return;
+ }
+
+ // If we are already connected no need to connect again.
+ if (connected_devices_map_->HasActiveConnection(device_id)) {
+ VLOG(1) << "Already connected.";
+ Send(new BluetoothMsg_GATTServerConnectSuccess(thread_id, request_id));
return;
}
query_result.device->CreateGattConnection(
base::Bind(&BluetoothDispatcherHost::OnGATTConnectionCreated,
- weak_ptr_on_ui_thread_, thread_id, request_id, device_id,
- start_time),
+ weak_ptr_on_ui_thread_, thread_id, request_id,
+ frame_routing_id, device_id, start_time),
base::Bind(&BluetoothDispatcherHost::OnCreateGATTConnectionError,
weak_ptr_on_ui_thread_, thread_id, request_id, device_id,
start_time));
}
+void BluetoothDispatcherHost::OnGATTServerDisconnect(
+ int thread_id,
+ int frame_routing_id,
+ const std::string& device_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ RecordWebBluetoothFunctionCall(
+ UMAWebBluetoothFunction::REMOTE_GATT_SERVER_DISCONNECT);
+
+ // Frames can send a disconnect request after they've started navigating,
+ // making calls to GetLastCommitted origin invalid. Because we still need
+ // to disconnect the device, otherwise we would leave users with no other
+ // option to disconnect than closing the tab, we purposefully don't
+ // check if the frame has permission to interact with the device.
+
+ // The last BluetoothGattConnection for a device closes the connection when
+ // it's destroyed.
+
+ // This only catches disconnections from the renderer. If the device
+ // disconnects by itself, or the renderer frame has been deleted
+ // due to navigation, we will not hide the indicator.
+ // TODO(ortuno): Once we move to Frame and Mojo we will be able
+ // to observe the frame's lifetime and hide the indicator when necessary.
+ // http://crbug.com/508771
+ connected_devices_map_->Remove(frame_routing_id, device_id);
+}
+
void BluetoothDispatcherHost::OnGetPrimaryService(
int thread_id,
int request_id,
@@ -751,8 +794,13 @@ void BluetoothDispatcherHost::OnGetPrimaryService(
RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::GET_PRIMARY_SERVICE);
RecordGetPrimaryServiceService(BluetoothUUID(service_uuid));
- // TODO(ortuno): Check if service_uuid is in "allowed services"
- // https://crbug.com/493460
+ if (!allowed_devices_map_.IsOriginAllowedToAccessService(
+ GetOrigin(frame_routing_id), device_id, service_uuid)) {
+ Send(new BluetoothMsg_GetPrimaryServiceError(
+ thread_id, request_id,
+ WebBluetoothError::NOT_ALLOWED_TO_ACCESS_SERVICE));
+ return;
+ }
const CacheQueryResult query_result =
QueryCacheForDevice(GetOrigin(frame_routing_id), device_id);
@@ -792,7 +840,7 @@ void BluetoothDispatcherHost::OnGetPrimaryService(
VLOG(1) << "Service not found in device.";
RecordGetPrimaryServiceOutcome(UMAGetPrimaryServiceOutcome::NOT_FOUND);
Send(new BluetoothMsg_GetPrimaryServiceError(
- thread_id, request_id, WebBluetoothError::ServiceNotFound));
+ thread_id, request_id, WebBluetoothError::SERVICE_NOT_FOUND));
return;
}
@@ -814,6 +862,16 @@ void BluetoothDispatcherHost::OnGetCharacteristic(
RecordWebBluetoothFunctionCall(UMAWebBluetoothFunction::GET_CHARACTERISTIC);
RecordGetCharacteristicCharacteristic(characteristic_uuid);
+ // Check Blacklist for characteristic_uuid.
+ if (BluetoothBlacklist::Get().IsExcluded(
+ BluetoothUUID(characteristic_uuid))) {
+ RecordGetCharacteristicOutcome(UMAGetCharacteristicOutcome::BLACKLISTED);
+ Send(new BluetoothMsg_GetCharacteristicError(
+ thread_id, request_id,
+ WebBluetoothError::BLACKLISTED_CHARACTERISTIC_UUID));
+ return;
+ }
+
const CacheQueryResult query_result =
QueryCacheForService(GetOrigin(frame_routing_id), service_instance_id);
@@ -852,59 +910,98 @@ void BluetoothDispatcherHost::OnGetCharacteristic(
}
RecordGetCharacteristicOutcome(UMAGetCharacteristicOutcome::NOT_FOUND);
Send(new BluetoothMsg_GetCharacteristicError(
- thread_id, request_id, WebBluetoothError::CharacteristicNotFound));
+ thread_id, request_id, WebBluetoothError::CHARACTERISTIC_NOT_FOUND));
}
-void BluetoothDispatcherHost::OnReadValue(
+void BluetoothDispatcherHost::OnGetCharacteristics(
int thread_id,
int request_id,
int frame_routing_id,
- const std::string& characteristic_instance_id) {
+ const std::string& service_instance_id,
+ const std::string& characteristics_uuid) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RecordWebBluetoothFunctionCall(
- UMAWebBluetoothFunction::CHARACTERISTIC_READ_VALUE);
+ UMAWebBluetoothFunction::SERVICE_GET_CHARACTERISTICS);
+ RecordGetCharacteristicsCharacteristic(characteristics_uuid);
+
+ // Check Blacklist for characteristics_uuid.
+ if (!characteristics_uuid.empty() &&
+ BluetoothBlacklist::Get().IsExcluded(
+ BluetoothUUID(characteristics_uuid))) {
+ RecordGetCharacteristicsOutcome(UMAGetCharacteristicOutcome::BLACKLISTED);
+ Send(new BluetoothMsg_GetCharacteristicsError(
+ thread_id, request_id,
+ WebBluetoothError::BLACKLISTED_CHARACTERISTIC_UUID));
+ return;
+ }
- const CacheQueryResult query_result = QueryCacheForCharacteristic(
- GetOrigin(frame_routing_id), characteristic_instance_id);
+ const CacheQueryResult query_result =
+ QueryCacheForService(GetOrigin(frame_routing_id), service_instance_id);
if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) {
return;
}
if (query_result.outcome != CacheQueryOutcome::SUCCESS) {
- RecordCharacteristicReadValueOutcome(query_result.outcome);
- Send(new BluetoothMsg_ReadCharacteristicValueError(
- thread_id, request_id, query_result.GetWebError()));
+ RecordGetCharacteristicsOutcome(query_result.outcome);
+ Send(new BluetoothMsg_GetCharacteristicsError(thread_id, request_id,
+ query_result.GetWebError()));
return;
}
- query_result.characteristic->ReadRemoteCharacteristic(
- base::Bind(&BluetoothDispatcherHost::OnCharacteristicValueRead,
- weak_ptr_on_ui_thread_, thread_id, request_id),
- base::Bind(&BluetoothDispatcherHost::OnCharacteristicReadValueError,
- weak_ptr_on_ui_thread_, thread_id, request_id));
+ std::vector<std::string> characteristics_instance_ids;
+ std::vector<std::string> characteristics_uuids;
+ std::vector<uint32_t> characteristics_properties;
+
+ for (BluetoothGattCharacteristic* characteristic :
+ query_result.service->GetCharacteristics()) {
+ if (!BluetoothBlacklist::Get().IsExcluded(characteristic->GetUUID()) &&
+ (characteristics_uuid.empty() ||
+ characteristics_uuid == characteristic->GetUUID().canonical_value())) {
+ const std::string& characteristic_instance_id =
+ characteristic->GetIdentifier();
+
+ characteristics_instance_ids.push_back(characteristic_instance_id);
+ characteristics_uuids.push_back(
+ characteristic->GetUUID().canonical_value());
+ characteristics_properties.push_back(
+ static_cast<uint32_t>(characteristic->GetProperties()));
+
+ auto insert_result = characteristic_to_service_.insert(
+ make_pair(characteristic_instance_id, service_instance_id));
+
+ // If value is already in map, DCHECK it's valid.
+ if (!insert_result.second)
+ DCHECK(insert_result.first->second == service_instance_id);
+ }
+ }
+
+ if (!characteristics_instance_ids.empty()) {
+ RecordGetCharacteristicsOutcome(UMAGetCharacteristicOutcome::SUCCESS);
+ Send(new BluetoothMsg_GetCharacteristicsSuccess(
+ thread_id, request_id, characteristics_instance_ids,
+ characteristics_uuids, characteristics_properties));
+ return;
+ }
+ RecordGetCharacteristicsOutcome(
+ characteristics_uuid.empty()
+ ? UMAGetCharacteristicOutcome::NO_CHARACTERISTICS
+ : UMAGetCharacteristicOutcome::NOT_FOUND);
+ Send(new BluetoothMsg_GetCharacteristicsError(
+ thread_id, request_id,
+ characteristics_uuid.empty()
+ ? WebBluetoothError::NO_CHARACTERISTICS_FOUND
+ : WebBluetoothError::CHARACTERISTIC_NOT_FOUND));
}
-void BluetoothDispatcherHost::OnWriteValue(
+void BluetoothDispatcherHost::OnReadValue(
int thread_id,
int request_id,
int frame_routing_id,
- const std::string& characteristic_instance_id,
- const std::vector<uint8_t>& value) {
+ const std::string& characteristic_instance_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RecordWebBluetoothFunctionCall(
- UMAWebBluetoothFunction::CHARACTERISTIC_WRITE_VALUE);
-
- // Length check per step 3 of writeValue algorithm:
- // https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothgattcharacteristic-writevalue
- // We perform the length check on the renderer side. So if we
- // get a value with length > 512, we can assume it's a hostile
- // renderer and kill it.
- if (value.size() > 512) {
- bad_message::ReceivedBadMessage(
- this, bad_message::BDH_INVALID_WRITE_VALUE_LENGTH);
- return;
- }
+ UMAWebBluetoothFunction::CHARACTERISTIC_READ_VALUE);
const CacheQueryResult query_result = QueryCacheForCharacteristic(
GetOrigin(frame_routing_id), characteristic_instance_id);
@@ -914,16 +1011,24 @@ void BluetoothDispatcherHost::OnWriteValue(
}
if (query_result.outcome != CacheQueryOutcome::SUCCESS) {
- RecordCharacteristicWriteValueOutcome(query_result.outcome);
- Send(new BluetoothMsg_WriteCharacteristicValueError(
+ RecordCharacteristicReadValueOutcome(query_result.outcome);
+ Send(new BluetoothMsg_ReadCharacteristicValueError(
thread_id, request_id, query_result.GetWebError()));
return;
}
- query_result.characteristic->WriteRemoteCharacteristic(
- value, base::Bind(&BluetoothDispatcherHost::OnWriteValueSuccess,
- weak_ptr_on_ui_thread_, thread_id, request_id),
- base::Bind(&BluetoothDispatcherHost::OnWriteValueFailed,
+ if (BluetoothBlacklist::Get().IsExcludedFromReads(
+ query_result.characteristic->GetUUID())) {
+ RecordCharacteristicReadValueOutcome(UMAGATTOperationOutcome::BLACKLISTED);
+ Send(new BluetoothMsg_ReadCharacteristicValueError(
+ thread_id, request_id, WebBluetoothError::BLACKLISTED_READ));
+ return;
+ }
+
+ query_result.characteristic->ReadRemoteCharacteristic(
+ base::Bind(&BluetoothDispatcherHost::OnCharacteristicValueRead,
+ weak_ptr_on_ui_thread_, thread_id, request_id),
+ base::Bind(&BluetoothDispatcherHost::OnCharacteristicReadValueError,
weak_ptr_on_ui_thread_, thread_id, request_id));
}
@@ -1028,6 +1133,181 @@ void BluetoothDispatcherHost::OnUnregisterCharacteristicObject(
}
}
+void BluetoothDispatcherHost::OnGetAdapter(
+ base::Closure continuation,
+ scoped_refptr<device::BluetoothAdapter> adapter) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ set_adapter(adapter);
+ continuation.Run();
+}
+
+void BluetoothDispatcherHost::OnRequestDeviceImpl(
+ int thread_id,
+ int request_id,
+ int frame_routing_id,
+ const std::vector<BluetoothScanFilter>& filters,
+ const std::vector<BluetoothUUID>& optional_services) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+
+ VLOG(1) << "requestDevice called with the following filters: ";
+ for (const BluetoothScanFilter& filter : filters) {
+ VLOG(1) << "Name: " << filter.name;
+ VLOG(1) << "Name Prefix: " << filter.namePrefix;
+ VLOG(1) << "Services:";
+ VLOG(1) << "\t[";
+ for (const BluetoothUUID& service : filter.services)
+ VLOG(1) << "\t\t" << service.value();
+ VLOG(1) << "\t]";
+ }
+
+ VLOG(1) << "requestDevice called with the following optional services: ";
+ for (const BluetoothUUID& service : optional_services)
+ VLOG(1) << "\t" << service.value();
+
+ // Check blacklist to reject invalid filters and adjust optional_services.
+ if (BluetoothBlacklist::Get().IsExcluded(filters)) {
+ RecordRequestDeviceOutcome(
+ UMARequestDeviceOutcome::BLACKLISTED_SERVICE_IN_FILTER);
+ Send(new BluetoothMsg_RequestDeviceError(
+ thread_id, request_id,
+ WebBluetoothError::REQUEST_DEVICE_WITH_BLACKLISTED_UUID));
+ return;
+ }
+ std::vector<BluetoothUUID> optional_services_blacklist_filtered(
+ optional_services);
+ BluetoothBlacklist::Get().RemoveExcludedUuids(
+ &optional_services_blacklist_filtered);
+
+ RenderFrameHostImpl* render_frame_host =
+ RenderFrameHostImpl::FromID(render_process_id_, frame_routing_id);
+ WebContents* web_contents =
+ WebContents::FromRenderFrameHost(render_frame_host);
+
+ if (!render_frame_host || !web_contents) {
+ DLOG(WARNING) << "Got a requestDevice IPC without a matching "
+ << "RenderFrameHost or WebContents: " << render_process_id_
+ << ", " << frame_routing_id;
+ RecordRequestDeviceOutcome(UMARequestDeviceOutcome::NO_RENDER_FRAME);
+ Send(new BluetoothMsg_RequestDeviceError(
+ thread_id, request_id,
+ WebBluetoothError::REQUEST_DEVICE_WITHOUT_FRAME));
+ return;
+ }
+
+ const url::Origin requesting_origin =
+ render_frame_host->GetLastCommittedOrigin();
+ const url::Origin embedding_origin =
+ web_contents->GetMainFrame()->GetLastCommittedOrigin();
+
+ // TODO(crbug.com/518042): Enforce correctly-delegated permissions instead of
+ // matching origins. When relaxing this, take care to handle non-sandboxed
+ // unique origins.
+ if (!embedding_origin.IsSameOriginWith(requesting_origin)) {
+ Send(new BluetoothMsg_RequestDeviceError(
+ thread_id, request_id,
+ WebBluetoothError::REQUEST_DEVICE_FROM_CROSS_ORIGIN_IFRAME));
+ return;
+ }
+ // The above also excludes unique origins, which are not even same-origin with
+ // themselves.
+ DCHECK(!requesting_origin.unique());
+
+ DCHECK(adapter_.get());
+
+ if (!adapter_->IsPresent()) {
+ VLOG(1) << "Bluetooth Adapter not present. Can't serve requestDevice.";
+ RecordRequestDeviceOutcome(
+ UMARequestDeviceOutcome::BLUETOOTH_ADAPTER_NOT_PRESENT);
+ Send(new BluetoothMsg_RequestDeviceError(
+ thread_id, request_id, WebBluetoothError::NO_BLUETOOTH_ADAPTER));
+ return;
+ }
+
+ // The renderer should never send empty filters.
+ if (HasEmptyOrInvalidFilter(filters)) {
+ bad_message::ReceivedBadMessage(this,
+ bad_message::BDH_EMPTY_OR_INVALID_FILTERS);
+ return;
+ }
+
+ switch (GetContentClient()->browser()->AllowWebBluetooth(
+ web_contents->GetBrowserContext(), requesting_origin, embedding_origin)) {
+ case ContentBrowserClient::AllowWebBluetoothResult::BLOCK_POLICY: {
+ RecordRequestDeviceOutcome(
+ UMARequestDeviceOutcome::BLUETOOTH_CHOOSER_POLICY_DISABLED);
+ Send(new BluetoothMsg_RequestDeviceError(
+ thread_id, request_id,
+ WebBluetoothError::CHOOSER_NOT_SHOWN_API_LOCALLY_DISABLED));
+ return;
+ }
+ case ContentBrowserClient::AllowWebBluetoothResult::
+ BLOCK_GLOBALLY_DISABLED: {
+ // Log to the developer console.
+ web_contents->GetMainFrame()->AddMessageToConsole(
+ content::CONSOLE_MESSAGE_LEVEL_LOG,
+ "Bluetooth permission has been blocked.");
+ // Block requests.
+ RecordRequestDeviceOutcome(
+ UMARequestDeviceOutcome::BLUETOOTH_GLOBALLY_DISABLED);
+ Send(new BluetoothMsg_RequestDeviceError(
+ thread_id, request_id,
+ WebBluetoothError::CHOOSER_NOT_SHOWN_API_GLOBALLY_DISABLED));
+ return;
+ }
+ case ContentBrowserClient::AllowWebBluetoothResult::ALLOW:
+ break;
+ }
+
+ // Create storage for the information that backs the chooser, and show the
+ // chooser.
+ RequestDeviceSession* const session = new RequestDeviceSession(
+ thread_id, request_id, frame_routing_id, requesting_origin, filters,
+ optional_services_blacklist_filtered);
+ int chooser_id = request_device_sessions_.Add(session);
+
+ BluetoothChooser::EventHandler chooser_event_handler =
+ base::Bind(&BluetoothDispatcherHost::OnBluetoothChooserEvent,
+ weak_ptr_on_ui_thread_, chooser_id);
+ if (WebContentsDelegate* delegate = web_contents->GetDelegate()) {
+ session->chooser =
+ delegate->RunBluetoothChooser(render_frame_host, chooser_event_handler);
+ }
+ if (!session->chooser) {
+ LOG(WARNING)
+ << "No Bluetooth chooser implementation; falling back to first device.";
+ session->chooser.reset(
+ new FirstDeviceBluetoothChooser(chooser_event_handler));
+ }
+
+ if (!session->chooser->CanAskForScanningPermission()) {
+ VLOG(1) << "Closing immediately because Chooser cannot obtain permission.";
+ OnBluetoothChooserEvent(chooser_id,
+ BluetoothChooser::Event::DENIED_PERMISSION, "");
+ return;
+ }
+
+ // Populate the initial list of devices.
+ VLOG(1) << "Populating " << adapter_->GetDevices().size()
+ << " devices in chooser " << chooser_id;
+ for (const device::BluetoothDevice* device : adapter_->GetDevices()) {
+ VLOG(1) << "\t" << device->GetAddress();
+ session->AddFilteredDevice(*device);
+ }
+
+ if (!session->chooser) {
+ // If the dialog's closing, no need to do any of the rest of this.
+ return;
+ }
+
+ if (!adapter_->IsPowered()) {
+ session->chooser->SetAdapterPresence(
+ BluetoothChooser::AdapterPresence::POWERED_OFF);
+ return;
+ }
+
+ StartDeviceDiscovery(session, chooser_id);
+}
+
void BluetoothDispatcherHost::OnDiscoverySessionStarted(
int chooser_id,
scoped_ptr<device::BluetoothDiscoverySession> discovery_session) {
@@ -1074,38 +1354,35 @@ void BluetoothDispatcherHost::OnBluetoothChooserEvent(
switch (event) {
case BluetoothChooser::Event::RESCAN:
StartDeviceDiscovery(session, chooser_id);
- break;
+ // No need to close the chooser so we return.
+ return;
case BluetoothChooser::Event::DENIED_PERMISSION:
case BluetoothChooser::Event::CANCELLED:
- case BluetoothChooser::Event::SELECTED: {
- // Synchronously ensure nothing else calls into the chooser after it has
- // asked to be closed.
- session->chooser.reset();
-
- // Yield to the event loop to make sure we don't destroy the session
- // within a BluetoothDispatcherHost stack frame.
- if (!base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&BluetoothDispatcherHost::FinishClosingChooser,
- weak_ptr_on_ui_thread_, chooser_id, event,
- device_id))) {
- LOG(WARNING) << "No TaskRunner; not closing requestDevice dialog.";
- }
+ case BluetoothChooser::Event::SELECTED:
break;
- }
case BluetoothChooser::Event::SHOW_OVERVIEW_HELP:
- ShowBluetoothOverviewLink();
- break;
- case BluetoothChooser::Event::SHOW_PAIRING_HELP:
- ShowBluetoothPairingLink();
+ VLOG(1) << "Overview Help link pressed.";
break;
case BluetoothChooser::Event::SHOW_ADAPTER_OFF_HELP:
- ShowBluetoothAdapterOffLink();
+ VLOG(1) << "Adapter Off Help link pressed.";
break;
case BluetoothChooser::Event::SHOW_NEED_LOCATION_HELP:
- ShowNeedLocationLink();
+ VLOG(1) << "Need Location Help link pressed.";
break;
}
+
+ // Synchronously ensure nothing else calls into the chooser after it has
+ // asked to be closed.
+ session->chooser.reset();
+
+ // Yield to the event loop to make sure we don't destroy the session
+ // within a BluetoothDispatcherHost stack frame.
+ if (!base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(&BluetoothDispatcherHost::FinishClosingChooser,
+ weak_ptr_on_ui_thread_, chooser_id, event, device_id))) {
+ LOG(WARNING) << "No TaskRunner; not closing requestDevice dialog.";
+ }
}
void BluetoothDispatcherHost::FinishClosingChooser(
@@ -1116,13 +1393,12 @@ void BluetoothDispatcherHost::FinishClosingChooser(
RequestDeviceSession* session = request_device_sessions_.Lookup(chooser_id);
DCHECK(session) << "Session removed unexpectedly.";
- if (event == BluetoothChooser::Event::CANCELLED) {
- RecordRequestDeviceOutcome(
- UMARequestDeviceOutcome::BLUETOOTH_CHOOSER_CANCELLED);
- VLOG(1) << "Bluetooth chooser cancelled";
+ if ((event != BluetoothChooser::Event::DENIED_PERMISSION) &&
+ (event != BluetoothChooser::Event::SELECTED)) {
+ RecordRequestDeviceOutcome(OutcomeFromChooserEvent(event));
Send(new BluetoothMsg_RequestDeviceError(
session->thread_id, session->request_id,
- WebBluetoothError::ChooserCancelled));
+ WebBluetoothError::CHOOSER_CANCELLED));
request_device_sessions_.Remove(chooser_id);
return;
}
@@ -1132,7 +1408,7 @@ void BluetoothDispatcherHost::FinishClosingChooser(
VLOG(1) << "Bluetooth chooser denied permission";
Send(new BluetoothMsg_RequestDeviceError(
session->thread_id, session->request_id,
- WebBluetoothError::ChooserDeniedPermission));
+ WebBluetoothError::CHOOSER_NOT_SHOWN_USER_DENIED_PERMISSION_TO_SCAN));
request_device_sessions_.Remove(chooser_id);
return;
}
@@ -1147,20 +1423,29 @@ void BluetoothDispatcherHost::FinishClosingChooser(
RecordRequestDeviceOutcome(UMARequestDeviceOutcome::CHOSEN_DEVICE_VANISHED);
Send(new BluetoothMsg_RequestDeviceError(
session->thread_id, session->request_id,
- WebBluetoothError::ChosenDeviceVanished));
+ WebBluetoothError::CHOSEN_DEVICE_VANISHED));
request_device_sessions_.Remove(chooser_id);
return;
}
- VLOG(1) << "Device: " << device->GetName();
- VLOG(1) << "UUIDs: ";
- for (BluetoothUUID uuid : device->GetUUIDs())
- VLOG(1) << "\t" << uuid.canonical_value();
-
const std::string& device_id_for_origin = allowed_devices_map_.AddDevice(
session->origin, device->GetAddress(), session->filters,
session->optional_services);
+ VLOG(1) << "Device: " << device->GetName();
+ VLOG(1) << "UUIDs: ";
+
+ device::BluetoothDevice::UUIDList filtered_uuids;
+ for (BluetoothUUID uuid : device->GetUUIDs()) {
+ if (allowed_devices_map_.IsOriginAllowedToAccessService(
+ session->origin, device_id_for_origin, uuid.canonical_value())) {
+ VLOG(1) << "\t Allowed: " << uuid.canonical_value();
+ filtered_uuids.push_back(uuid);
+ } else {
+ VLOG(1) << "\t Not Allowed: " << uuid.canonical_value();
+ }
+ }
+
content::BluetoothDevice device_ipc(
device_id_for_origin, // id
device->GetName(), // name
@@ -1174,7 +1459,7 @@ void BluetoothDispatcherHost::FinishClosingChooser(
device->GetProductID(), // product_id
device->GetDeviceID(), // product_version
content::BluetoothDevice::UUIDsFromBluetoothUUIDs(
- device->GetUUIDs())); // uuids
+ filtered_uuids)); // uuids
RecordRequestDeviceOutcome(UMARequestDeviceOutcome::SUCCESS);
Send(new BluetoothMsg_RequestDeviceSuccess(session->thread_id,
session->request_id, device_ipc));
@@ -1184,14 +1469,16 @@ void BluetoothDispatcherHost::FinishClosingChooser(
void BluetoothDispatcherHost::OnGATTConnectionCreated(
int thread_id,
int request_id,
+ int frame_routing_id,
const std::string& device_id,
base::TimeTicks start_time,
scoped_ptr<device::BluetoothGattConnection> connection) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- connections_.push_back(std::move(connection));
RecordConnectGATTTimeSuccess(base::TimeTicks::Now() - start_time);
RecordConnectGATTOutcome(UMAConnectGATTOutcome::SUCCESS);
- Send(new BluetoothMsg_ConnectGATTSuccess(thread_id, request_id, device_id));
+ connected_devices_map_->InsertOrReplace(frame_routing_id, device_id,
+ std::move(connection));
+ Send(new BluetoothMsg_GATTServerConnectSuccess(thread_id, request_id));
}
void BluetoothDispatcherHost::OnCreateGATTConnectionError(
@@ -1206,8 +1493,8 @@ void BluetoothDispatcherHost::OnCreateGATTConnectionError(
// https://webbluetoothchrome.github.io/web-bluetooth/#dom-bluetoothdevice-connectgatt
RecordConnectGATTTimeFailed(base::TimeTicks::Now() - start_time);
// RecordConnectGATTOutcome is called by TranslateConnectError.
- Send(new BluetoothMsg_ConnectGATTError(thread_id, request_id,
- TranslateConnectError(error_code)));
+ Send(new BluetoothMsg_GATTServerConnectError(
+ thread_id, request_id, TranslateConnectError(error_code)));
}
void BluetoothDispatcherHost::AddToServicesMapAndSendGetPrimaryServiceSuccess(
@@ -1249,24 +1536,6 @@ void BluetoothDispatcherHost::OnCharacteristicReadValueError(
TranslateGATTError(error_code, UMAGATTOperation::CHARACTERISTIC_READ)));
}
-void BluetoothDispatcherHost::OnWriteValueSuccess(int thread_id,
- int request_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- RecordCharacteristicWriteValueOutcome(UMAGATTOperationOutcome::SUCCESS);
- Send(new BluetoothMsg_WriteCharacteristicValueSuccess(thread_id, request_id));
-}
-
-void BluetoothDispatcherHost::OnWriteValueFailed(
- int thread_id,
- int request_id,
- device::BluetoothGattService::GattErrorCode error_code) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- // TranslateGATTError calls RecordGATTOperationOutcome.
- Send(new BluetoothMsg_WriteCharacteristicValueError(
- thread_id, request_id,
- TranslateGATTError(error_code, UMAGATTOperation::CHARACTERISTIC_WRITE)));
-}
-
void BluetoothDispatcherHost::OnStartNotifySessionSuccess(
int thread_id,
int request_id,
@@ -1355,6 +1624,12 @@ BluetoothDispatcherHost::QueryCacheForService(
result.service = result.device->GetGattService(service_instance_id);
if (result.service == nullptr) {
result.outcome = CacheQueryOutcome::NO_SERVICE;
+ } else if (!allowed_devices_map_.IsOriginAllowedToAccessService(
+ origin, device_id,
+ result.service->GetUUID().canonical_value())) {
+ bad_message::ReceivedBadMessage(
+ this, bad_message::BDH_SERVICE_NOT_ALLOWED_FOR_ORIGIN);
+ return CacheQueryResult(CacheQueryOutcome::BAD_RENDERER);
}
return result;
}
@@ -1408,24 +1683,4 @@ bool BluetoothDispatcherHost::CanFrameAccessCharacteristicInstance(
.outcome != CacheQueryOutcome::BAD_RENDERER;
}
-void BluetoothDispatcherHost::ShowBluetoothOverviewLink() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- NOTIMPLEMENTED();
-}
-
-void BluetoothDispatcherHost::ShowBluetoothPairingLink() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- NOTIMPLEMENTED();
-}
-
-void BluetoothDispatcherHost::ShowBluetoothAdapterOffLink() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- NOTIMPLEMENTED();
-}
-
-void BluetoothDispatcherHost::ShowNeedLocationLink() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- NOTIMPLEMENTED();
-}
-
} // namespace content
diff --git a/chromium/content/browser/bluetooth/bluetooth_dispatcher_host.h b/chromium/content/browser/bluetooth/bluetooth_dispatcher_host.h
index 7bae29ca931..e3a4d6178bd 100644
--- a/chromium/content/browser/bluetooth/bluetooth_dispatcher_host.h
+++ b/chromium/content/browser/bluetooth/bluetooth_dispatcher_host.h
@@ -14,6 +14,8 @@
#include "base/memory/scoped_vector.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/bluetooth/bluetooth_allowed_devices_map.h"
+#include "content/browser/bluetooth/bluetooth_metrics.h"
+#include "content/common/bluetooth/bluetooth_messages.h"
#include "content/public/browser/bluetooth_chooser.h"
#include "content/public/browser/browser_message_filter.h"
#include "device/bluetooth/bluetooth_adapter.h"
@@ -53,6 +55,29 @@ class CONTENT_EXPORT BluetoothDispatcherHost final
void SetBluetoothAdapterForTesting(
scoped_refptr<device::BluetoothAdapter> mock_adapter);
+ // TODO(ortuno): We temporarily make this a public struct so that
+ // both BluetoothDispatcherHost and WebBluetoothServiceImpl can use it,
+ // while we move functions from BluetoothDispatcherHost to
+ // WebBluetoothServiceImpl.
+ // https://crbug.com/508771
+ struct CacheQueryResult {
+ CacheQueryResult();
+ CacheQueryResult(CacheQueryOutcome outcome);
+ ~CacheQueryResult();
+ blink::WebBluetoothError GetWebError() const;
+ device::BluetoothDevice* device = nullptr;
+ device::BluetoothGattService* service = nullptr;
+ device::BluetoothGattCharacteristic* characteristic = nullptr;
+ CacheQueryOutcome outcome = CacheQueryOutcome::SUCCESS;
+ };
+
+ // Queries the platform cache for a characteristic with
+ // |characteristic_instance_id|. Fills in the |outcome| field, and |device|,
+ // |service| and |characteristic| fields if successful.
+ CacheQueryResult QueryCacheForCharacteristic(
+ const url::Origin& origin,
+ const std::string& characteristic_instance_id);
+
protected:
~BluetoothDispatcherHost() override;
@@ -60,10 +85,32 @@ class CONTENT_EXPORT BluetoothDispatcherHost final
friend class base::DeleteHelper<BluetoothDispatcherHost>;
friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
- struct CacheQueryResult;
struct RequestDeviceSession;
struct PrimaryServicesRequest;
+ // Map to keep track of connections. Inserting and removing connections
+ // will update the Web Contents for the frame. Upon destruction
+ // the map will clear Web Contents of Bluetooth connections.
+ struct ConnectedDevicesMap {
+ ConnectedDevicesMap(int render_process_id);
+ ~ConnectedDevicesMap();
+ bool HasActiveConnection(const std::string& device_id);
+ void InsertOrReplace(
+ int frame_routing_id,
+ const std::string& device_id,
+ scoped_ptr<device::BluetoothGattConnection> connection);
+ void Remove(int frame_routing_id, const std::string& device_id);
+ void IncrementBluetoothConnectedDeviceCount(int frame_routing_id);
+ void DecrementBluetoothConnectedDeviceCount(int frame_routing_id);
+
+ int render_process_id_;
+ std::unordered_map<std::string, scoped_ptr<device::BluetoothGattConnection>>
+ device_id_to_connection_map_;
+ // Keeps track of which frame is connected to which device so that
+ // we can clean up the WebContents in our destructor.
+ std::set<std::pair<int, std::string>> frame_ids_device_ids_;
+ };
+
// Set |adapter_| to a BluetoothAdapter instance and register observers,
// releasing references to previous |adapter_|.
void set_adapter(scoped_refptr<device::BluetoothAdapter> adapter);
@@ -103,10 +150,13 @@ class CONTENT_EXPORT BluetoothDispatcherHost final
int frame_routing_id,
const std::vector<content::BluetoothScanFilter>& filters,
const std::vector<device::BluetoothUUID>& optional_services);
- void OnConnectGATT(int thread_id,
- int request_id,
- int frame_routing_id,
- const std::string& device_id);
+ void OnGATTServerConnect(int thread_id,
+ int request_id,
+ int frame_routing_id,
+ const std::string& device_id);
+ void OnGATTServerDisconnect(int thread_id,
+ int frame_routing_id,
+ const std::string& device_id);
void OnGetPrimaryService(int thread_id,
int request_id,
int frame_routing_id,
@@ -117,15 +167,15 @@ class CONTENT_EXPORT BluetoothDispatcherHost final
int frame_routing_id,
const std::string& service_instance_id,
const std::string& characteristic_uuid);
+ void OnGetCharacteristics(int thread_id,
+ int request_id,
+ int frame_routing_id,
+ const std::string& service_instance_id,
+ const std::string& characteristics_uuid);
void OnReadValue(int thread_id,
int request_id,
int frame_routing_id,
const std::string& characteristic_instance_id);
- void OnWriteValue(int thread_id,
- int request_id,
- int frame_routing_id,
- const std::string& characteristic_instance_id,
- const std::vector<uint8_t>& value);
void OnStartNotifications(int thread_id,
int request_id,
int frame_routing_id,
@@ -143,6 +193,17 @@ class CONTENT_EXPORT BluetoothDispatcherHost final
int frame_routing_id,
const std::string& characteristic_instance_id);
+ // Callbacks for BluetoothDevice::OnRequestDevice.
+ // If necessary, the adapter must be obtained before continuing to Impl.
+ void OnGetAdapter(base::Closure continuation,
+ scoped_refptr<device::BluetoothAdapter> adapter);
+ void OnRequestDeviceImpl(
+ int thread_id,
+ int request_id,
+ int frame_routing_id,
+ const std::vector<content::BluetoothScanFilter>& filters,
+ const std::vector<device::BluetoothUUID>& optional_services);
+
// Callbacks for BluetoothAdapter::StartDiscoverySession.
void OnDiscoverySessionStarted(
int chooser_id,
@@ -165,6 +226,7 @@ class CONTENT_EXPORT BluetoothDispatcherHost final
void OnGATTConnectionCreated(
int thread_id,
int request_id,
+ int frame_routing_id,
const std::string& device_id,
base::TimeTicks start_time,
scoped_ptr<device::BluetoothGattConnection> connection);
@@ -191,12 +253,6 @@ class CONTENT_EXPORT BluetoothDispatcherHost final
int request_id,
device::BluetoothGattService::GattErrorCode);
- // Callbacks for BluetoothGattCharacteristic::WriteRemoteCharacteristic.
- void OnWriteValueSuccess(int thread_id, int request_id);
- void OnWriteValueFailed(int thread_id,
- int request_id,
- device::BluetoothGattService::GattErrorCode);
-
// Callbacks for BluetoothGattCharacteristic::StartNotifySession.
void OnStartNotifySessionSuccess(
int thread_id,
@@ -228,12 +284,6 @@ class CONTENT_EXPORT BluetoothDispatcherHost final
// in the |outcome| field, and |device| and |service| fields if successful.
CacheQueryResult QueryCacheForService(const url::Origin& origin,
const std::string& service_instance_id);
- // Queries the platform cache for a characteristic with
- // |characteristic_instance_id|. Fills in the |outcome| field, and |device|,
- // |service| and |characteristic| fields if successful.
- CacheQueryResult QueryCacheForCharacteristic(
- const url::Origin& origin,
- const std::string& characteristic_instance_id);
// Adds the PrimaryServicesRequest to the vector of pending services requests
// for that device.
@@ -251,12 +301,6 @@ class CONTENT_EXPORT BluetoothDispatcherHost final
int frame_routing_id,
const std::string& characteristic_instance_id);
- // Show help pages from the chooser dialog.
- void ShowBluetoothOverviewLink();
- void ShowBluetoothPairingLink();
- void ShowBluetoothAdapterOffLink();
- void ShowNeedLocationLink();
-
int render_process_id_;
// Maps a (thread_id,request_id) to information about its requestDevice call,
@@ -297,9 +341,8 @@ class CONTENT_EXPORT BluetoothDispatcherHost final
// sessions when other sessions are active.
base::Timer discovery_session_timer_;
- // Retain BluetoothGattConnection objects to keep connections open.
- // TODO(scheib): Destroy as connections are closed. http://crbug.com/539643
- ScopedVector<device::BluetoothGattConnection> connections_;
+ // Retains BluetoothGattConnection objects to keep connections open.
+ scoped_ptr<ConnectedDevicesMap> connected_devices_map_;
// Map of device_address's to primary-services requests that need responses
// when that device's service discovery completes.
diff --git a/chromium/content/browser/bluetooth/bluetooth_metrics.cc b/chromium/content/browser/bluetooth/bluetooth_metrics.cc
index ef829203bba..32f7c73dfa7 100644
--- a/chromium/content/browser/bluetooth/bluetooth_metrics.cc
+++ b/chromium/content/browser/bluetooth/bluetooth_metrics.cc
@@ -97,7 +97,7 @@ void RecordRequestDeviceArguments(
RecordUnionOfServices(filters, optional_services);
}
-// connectGATT
+// GATTServer.Connect
void RecordConnectGATTOutcome(UMAConnectGATTOutcome outcome) {
UMA_HISTOGRAM_ENUMERATION("Bluetooth.Web.ConnectGATT.Outcome",
@@ -150,7 +150,8 @@ void RecordGetCharacteristicOutcome(CacheQueryOutcome outcome) {
switch (outcome) {
case CacheQueryOutcome::SUCCESS:
case CacheQueryOutcome::BAD_RENDERER:
- NOTREACHED() << "No need to record a success or renderer crash";
+ // No need to record a success or renderer crash.
+ NOTREACHED();
return;
case CacheQueryOutcome::NO_DEVICE:
RecordGetCharacteristicOutcome(UMAGetCharacteristicOutcome::NO_DEVICE);
@@ -169,6 +170,38 @@ void RecordGetCharacteristicCharacteristic(const std::string& characteristic) {
HashUUID(characteristic));
}
+// getCharacteristics
+
+void RecordGetCharacteristicsOutcome(UMAGetCharacteristicOutcome outcome) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Bluetooth.Web.GetCharacteristics.Outcome", static_cast<int>(outcome),
+ static_cast<int>(UMAGetCharacteristicOutcome::COUNT));
+}
+
+void RecordGetCharacteristicsOutcome(CacheQueryOutcome outcome) {
+ switch (outcome) {
+ case CacheQueryOutcome::SUCCESS:
+ case CacheQueryOutcome::BAD_RENDERER:
+ // No need to record a success or renderer crash.
+ NOTREACHED();
+ return;
+ case CacheQueryOutcome::NO_DEVICE:
+ RecordGetCharacteristicsOutcome(UMAGetCharacteristicOutcome::NO_DEVICE);
+ return;
+ case CacheQueryOutcome::NO_SERVICE:
+ RecordGetCharacteristicsOutcome(UMAGetCharacteristicOutcome::NO_SERVICE);
+ return;
+ case CacheQueryOutcome::NO_CHARACTERISTIC:
+ NOTREACHED();
+ return;
+ }
+}
+
+void RecordGetCharacteristicsCharacteristic(const std::string& characteristic) {
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Bluetooth.Web.GetCharacteristics.Characteristic",
+ HashUUID(characteristic));
+}
+
// GATT Operations
void RecordGATTOperationOutcome(UMAGATTOperation operation,
@@ -195,7 +228,8 @@ static UMAGATTOperationOutcome TranslateCacheQueryOutcomeToGATTOperationOutcome(
switch (outcome) {
case CacheQueryOutcome::SUCCESS:
case CacheQueryOutcome::BAD_RENDERER:
- NOTREACHED() << "No need to record success or renderer crash";
+ // No need to record a success or renderer crash.
+ NOTREACHED();
return UMAGATTOperationOutcome::NOT_SUPPORTED;
case CacheQueryOutcome::NO_DEVICE:
return UMAGATTOperationOutcome::NO_DEVICE;
diff --git a/chromium/content/browser/bluetooth/bluetooth_metrics.h b/chromium/content/browser/bluetooth/bluetooth_metrics.h
index fa508590177..872008b8513 100644
--- a/chromium/content/browser/bluetooth/bluetooth_metrics.h
+++ b/chromium/content/browser/bluetooth/bluetooth_metrics.h
@@ -31,6 +31,8 @@ enum class UMAWebBluetoothFunction {
CHARACTERISTIC_WRITE_VALUE = 5,
CHARACTERISTIC_START_NOTIFICATIONS = 6,
CHARACTERISTIC_STOP_NOTIFICATIONS = 7,
+ REMOTE_GATT_SERVER_DISCONNECT = 8,
+ SERVICE_GET_CHARACTERISTICS = 9,
// NOTE: Add new actions immediately above this line. Make sure to update
// the enum list in tools/metrics/histograms/histograms.xml accordingly.
COUNT
@@ -62,6 +64,12 @@ enum class UMARequestDeviceOutcome {
CHOSEN_DEVICE_VANISHED = 8,
BLUETOOTH_CHOOSER_CANCELLED = 9,
BLUETOOTH_CHOOSER_DENIED_PERMISSION = 10,
+ BLACKLISTED_SERVICE_IN_FILTER = 11,
+ BLUETOOTH_OVERVIEW_HELP_LINK_PRESSED = 12,
+ ADAPTER_OFF_HELP_LINK_PRESSED = 13,
+ NEED_LOCATION_HELP_LINK_PRESSED = 14,
+ BLUETOOTH_CHOOSER_POLICY_DISABLED = 15,
+ BLUETOOTH_GLOBALLY_DISABLED = 16,
// NOTE: Add new requestDevice() outcomes immediately above this line. Make
// sure to update the enum list in
// tools/metrics/histograms/histograms.xml accordingly.
@@ -145,6 +153,8 @@ enum class UMAGetCharacteristicOutcome {
NO_DEVICE = 1,
NO_SERVICE = 2,
NOT_FOUND = 3,
+ BLACKLISTED = 4,
+ NO_CHARACTERISTICS = 5,
// Note: Add new outcomes immediately above this line.
// Make sure to update the enum list in
// tools/metrisc/histogram/histograms.xml accordingly.
@@ -160,6 +170,17 @@ void RecordGetCharacteristicOutcome(CacheQueryOutcome outcome);
// Records the UUID of the characteristic used when calling getCharacteristic.
void RecordGetCharacteristicCharacteristic(const std::string& characteristic);
+// getCharacteristics() Metrics
+// There should be a call to this function for every call to
+// Send(BluetoothMsg_GetCharacteristicsSuccess) and
+// Send(BluetoothMsg_GetCharacteristicsError).
+void RecordGetCharacteristicsOutcome(UMAGetCharacteristicOutcome outcome);
+// Records the outcome of the cache query for getCharacteristics. Should only be
+// called if QueryCacheForService fails.
+void RecordGetCharacteristicsOutcome(CacheQueryOutcome outcome);
+// Records the UUID of the characteristic used when calling getCharacteristic.
+void RecordGetCharacteristicsCharacteristic(const std::string& characteristic);
+
// GATT Operations Metrics
// These are the possible outcomes when performing GATT operations i.e.
@@ -178,6 +199,7 @@ enum UMAGATTOperationOutcome {
NOT_AUTHORIZED = 10,
NOT_PAIRED = 11,
NOT_SUPPORTED = 12,
+ BLACKLISTED = 13,
// Note: Add new GATT Outcomes immediately above this line.
// Make sure to update the enum list in
// tools/metrics/histograms/histograms.xml accordingly.
diff --git a/chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc b/chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc
new file mode 100644
index 00000000000..ea627d222e0
--- /dev/null
+++ b/chromium/content/browser/bluetooth/web_bluetooth_service_impl.cc
@@ -0,0 +1,156 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/bluetooth/web_bluetooth_service_impl.h"
+
+#include <vector>
+
+#include "content/browser/bluetooth/bluetooth_blacklist.h"
+#include "content/browser/bluetooth/bluetooth_dispatcher_host.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/public/browser/render_frame_host.h"
+#include "device/bluetooth/bluetooth_gatt_characteristic.h"
+
+using device::BluetoothGattService;
+
+namespace content {
+
+namespace {
+
+blink::mojom::WebBluetoothError TranslateGATTErrorAndRecord(
+ BluetoothGattService::GattErrorCode error_code,
+ UMAGATTOperation operation) {
+ switch (error_code) {
+ case BluetoothGattService::GATT_ERROR_UNKNOWN:
+ RecordGATTOperationOutcome(operation, UMAGATTOperationOutcome::UNKNOWN);
+ return blink::mojom::WebBluetoothError::GATT_UNKNOWN_ERROR;
+ case BluetoothGattService::GATT_ERROR_FAILED:
+ RecordGATTOperationOutcome(operation, UMAGATTOperationOutcome::FAILED);
+ return blink::mojom::WebBluetoothError::GATT_UNKNOWN_FAILURE;
+ case BluetoothGattService::GATT_ERROR_IN_PROGRESS:
+ RecordGATTOperationOutcome(operation,
+ UMAGATTOperationOutcome::IN_PROGRESS);
+ return blink::mojom::WebBluetoothError::GATT_OPERATION_IN_PROGRESS;
+ case BluetoothGattService::GATT_ERROR_INVALID_LENGTH:
+ RecordGATTOperationOutcome(operation,
+ UMAGATTOperationOutcome::INVALID_LENGTH);
+ return blink::mojom::WebBluetoothError::GATT_INVALID_ATTRIBUTE_LENGTH;
+ case BluetoothGattService::GATT_ERROR_NOT_PERMITTED:
+ RecordGATTOperationOutcome(operation,
+ UMAGATTOperationOutcome::NOT_PERMITTED);
+ return blink::mojom::WebBluetoothError::GATT_NOT_PERMITTED;
+ case BluetoothGattService::GATT_ERROR_NOT_AUTHORIZED:
+ RecordGATTOperationOutcome(operation,
+ UMAGATTOperationOutcome::NOT_AUTHORIZED);
+ return blink::mojom::WebBluetoothError::GATT_NOT_AUTHORIZED;
+ case BluetoothGattService::GATT_ERROR_NOT_PAIRED:
+ RecordGATTOperationOutcome(operation,
+ UMAGATTOperationOutcome::NOT_PAIRED);
+ return blink::mojom::WebBluetoothError::GATT_NOT_PAIRED;
+ case BluetoothGattService::GATT_ERROR_NOT_SUPPORTED:
+ RecordGATTOperationOutcome(operation,
+ UMAGATTOperationOutcome::NOT_SUPPORTED);
+ return blink::mojom::WebBluetoothError::GATT_NOT_SUPPORTED;
+ }
+ NOTREACHED();
+ return blink::mojom::WebBluetoothError::GATT_UNTRANSLATED_ERROR_CODE;
+}
+
+} // namespace
+
+using CacheQueryResult = BluetoothDispatcherHost::CacheQueryResult;
+
+WebBluetoothServiceImpl::WebBluetoothServiceImpl(
+ RenderFrameHost* render_frame_host,
+ blink::mojom::WebBluetoothServiceRequest request)
+ : render_frame_host_(render_frame_host),
+ binding_(this, std::move(request)),
+ weak_ptr_factory_(this) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+}
+
+WebBluetoothServiceImpl::~WebBluetoothServiceImpl() {}
+
+void WebBluetoothServiceImpl::RemoteCharacteristicWriteValue(
+ const mojo::String& characteristic_instance_id,
+ mojo::Array<uint8_t> value,
+ const RemoteCharacteristicWriteValueCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ RecordWebBluetoothFunctionCall(
+ UMAWebBluetoothFunction::CHARACTERISTIC_WRITE_VALUE);
+
+ // We perform the length check on the renderer side. So if we
+ // get a value with length > 512, we can assume it's a hostile
+ // renderer and kill it.
+ if (value.size() > 512) {
+ CrashRendererAndClosePipe(bad_message::BDH_INVALID_WRITE_VALUE_LENGTH);
+ return;
+ }
+
+ const CacheQueryResult query_result =
+ GetBluetoothDispatcherHost()->QueryCacheForCharacteristic(
+ GetOrigin(), characteristic_instance_id);
+
+ if (query_result.outcome == CacheQueryOutcome::BAD_RENDERER) {
+ binding_.Close();
+ return;
+ }
+
+ if (query_result.outcome != CacheQueryOutcome::SUCCESS) {
+ RecordCharacteristicWriteValueOutcome(query_result.outcome);
+ callback.Run(query_result.GetWebError());
+ return;
+ }
+
+ if (BluetoothBlacklist::Get().IsExcludedFromWrites(
+ query_result.characteristic->GetUUID())) {
+ RecordCharacteristicWriteValueOutcome(UMAGATTOperationOutcome::BLACKLISTED);
+ callback.Run(blink::mojom::WebBluetoothError::BLACKLISTED_WRITE);
+ return;
+ }
+
+ query_result.characteristic->WriteRemoteCharacteristic(
+ value.To<std::vector<uint8_t>>(),
+ base::Bind(&WebBluetoothServiceImpl::OnWriteValueSuccess,
+ weak_ptr_factory_.GetWeakPtr(), callback),
+ base::Bind(&WebBluetoothServiceImpl::OnWriteValueFailed,
+ weak_ptr_factory_.GetWeakPtr(), callback));
+}
+
+void WebBluetoothServiceImpl::OnWriteValueSuccess(
+ const RemoteCharacteristicWriteValueCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ RecordCharacteristicWriteValueOutcome(UMAGATTOperationOutcome::SUCCESS);
+ callback.Run(blink::mojom::WebBluetoothError::SUCCESS);
+}
+
+void WebBluetoothServiceImpl::OnWriteValueFailed(
+ const RemoteCharacteristicWriteValueCallback& callback,
+ device::BluetoothGattService::GattErrorCode error_code) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ callback.Run(TranslateGATTErrorAndRecord(
+ error_code, UMAGATTOperation::CHARACTERISTIC_WRITE));
+}
+
+RenderProcessHost* WebBluetoothServiceImpl::GetRenderProcessHost() {
+ return render_frame_host_->GetProcess();
+}
+
+BluetoothDispatcherHost* WebBluetoothServiceImpl::GetBluetoothDispatcherHost() {
+ RenderProcessHostImpl* render_process_host_impl =
+ static_cast<RenderProcessHostImpl*>(GetRenderProcessHost());
+ return render_process_host_impl->GetBluetoothDispatcherHost();
+}
+
+void WebBluetoothServiceImpl::CrashRendererAndClosePipe(
+ bad_message::BadMessageReason reason) {
+ bad_message::ReceivedBadMessage(GetRenderProcessHost(), reason);
+ binding_.Close();
+}
+
+url::Origin WebBluetoothServiceImpl::GetOrigin() {
+ return render_frame_host_->GetLastCommittedOrigin();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/bluetooth/web_bluetooth_service_impl.h b/chromium/content/browser/bluetooth/web_bluetooth_service_impl.h
new file mode 100644
index 00000000000..45f9e8c65bd
--- /dev/null
+++ b/chromium/content/browser/bluetooth/web_bluetooth_service_impl.h
@@ -0,0 +1,77 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_BLUETOOTH_WEB_BLUETOOTH_SERVICE_IMPL_H_
+#define CONTENT_BROWSER_BLUETOOTH_WEB_BLUETOOTH_SERVICE_IMPL_H_
+
+#include "base/macros.h"
+#include "content/browser/bad_message.h"
+#include "content/common/content_export.h"
+#include "device/bluetooth/bluetooth_gatt_service.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom.h"
+
+namespace url {
+class Origin;
+} // namespace url
+
+namespace content {
+
+class BluetoothDispatcherHost;
+class RenderFrameHost;
+class RenderProcessHost;
+
+// Implementation of Mojo WebBluetoothService located in
+// third_party/WebKit/public/platform/modules/bluetooth.
+// It handles Web Bluetooth API requests coming from Blink / renderer
+// process and uses the platform abstraction of device/bluetooth.
+// WebBluetoothServiceImpl is not thread-safe and should be created on the
+// UI thread as required by device/bluetooth.
+// This class is instantiated on-demand via Mojo's ConnectToRemoteService
+// from the renderer when the first Web Bluetooth API request is handled.
+// RenderFrameHostImpl will create an instance of this class and keep
+// ownership of it.
+class WebBluetoothServiceImpl : public blink::mojom::WebBluetoothService {
+ public:
+ // |render_frame_host|: The RFH that owns this instance.
+ // |request|: The instance will be bound to this request's pipe.
+ WebBluetoothServiceImpl(RenderFrameHost* render_frame_host,
+ blink::mojom::WebBluetoothServiceRequest request);
+ ~WebBluetoothServiceImpl() override;
+
+ private:
+ // WebBluetoothService methods:
+ void RemoteCharacteristicWriteValue(
+ const mojo::String& characteristic_instance_id,
+ mojo::Array<uint8_t> value,
+ const RemoteCharacteristicWriteValueCallback& callback) override;
+
+ // Callbacks for BluetoothGattCharacteristic::WriteRemoteCharacteristic.
+ void OnWriteValueSuccess(
+ const RemoteCharacteristicWriteValueCallback& callback);
+ void OnWriteValueFailed(
+ const RemoteCharacteristicWriteValueCallback& callback,
+ device::BluetoothGattService::GattErrorCode error_code);
+
+ RenderProcessHost* GetRenderProcessHost();
+ BluetoothDispatcherHost* GetBluetoothDispatcherHost();
+ void CrashRendererAndClosePipe(bad_message::BadMessageReason reason);
+ url::Origin GetOrigin();
+
+ // The RFH that owns this instance.
+ RenderFrameHost* render_frame_host_;
+
+ // The lifetime of this instance is exclusively managed by the RFH that
+ // owns it so we use a "Binding" as opposed to a "StrongBinding" which deletes
+ // the service on pipe connection errors.
+ mojo::Binding<blink::mojom::WebBluetoothService> binding_;
+
+ base::WeakPtrFactory<WebBluetoothServiceImpl> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebBluetoothServiceImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_BLUETOOTH_WEB_BLUETOOTH_SERVICE_IMPL_H_
diff --git a/chromium/content/browser/browser_child_process_host_impl.cc b/chromium/content/browser/browser_child_process_host_impl.cc
index 9461b624195..64b81eeb361 100644
--- a/chromium/content/browser/browser_child_process_host_impl.cc
+++ b/chromium/content/browser/browser_child_process_host_impl.cc
@@ -8,10 +8,12 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/debug/dump_without_crashing.h"
+#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
@@ -35,18 +37,12 @@
#include "content/public/common/result_codes.h"
#include "ipc/attachment_broker.h"
#include "ipc/attachment_broker_privileged.h"
-#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
+#include "mojo/edk/embedder/embedder.h"
#if defined(OS_MACOSX)
#include "content/browser/mach_broker_mac.h"
#endif
-
-#if defined(MOJO_SHELL_CLIENT)
-#include "content/browser/mojo/mojo_shell_client_host.h"
-#include "content/common/mojo/mojo_shell_connection_impl.h"
-#endif
-
namespace content {
namespace {
@@ -132,7 +128,8 @@ BrowserChildProcessHostImpl::BrowserChildProcessHostImpl(
: data_(process_type),
delegate_(delegate),
power_monitor_message_broadcaster_(this),
- is_channel_connected_(false) {
+ is_channel_connected_(false),
+ notify_child_disconnected_(false) {
data_.id = ChildProcessHostImpl::GenerateChildProcessUniqueId();
#if USE_ATTACHMENT_BROKER
@@ -140,12 +137,12 @@ BrowserChildProcessHostImpl::BrowserChildProcessHostImpl(
// child process. This ensures that when a test is being run in one of the
// single process modes, the global attachment broker is the privileged
// attachment broker, rather than an unprivileged attachment broker.
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MACOSX)
IPC::AttachmentBrokerPrivileged::CreateBrokerIfNeeded(
MachBroker::GetInstance());
#else
IPC::AttachmentBrokerPrivileged::CreateBrokerIfNeeded();
-#endif // defined(OS_MACOSX) && !defined(OS_IOS)
+#endif // defined(OS_MACOSX)
#endif // USE_ATTACHMENT_BROKER
child_process_host_.reset(ChildProcessHost::Create(this));
@@ -162,6 +159,11 @@ BrowserChildProcessHostImpl::BrowserChildProcessHostImpl(
BrowserChildProcessHostImpl::~BrowserChildProcessHostImpl() {
g_child_process_list.Get().remove(this);
+
+ if (notify_child_disconnected_) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&NotifyProcessHostDisconnected, data_));
+ }
}
// static
@@ -176,6 +178,28 @@ void BrowserChildProcessHostImpl::TerminateAll() {
}
}
+// static
+void BrowserChildProcessHostImpl::CopyFeatureAndFieldTrialFlags(
+ base::CommandLine* cmd_line) {
+ std::string enabled_features;
+ std::string disabled_features;
+ base::FeatureList::GetInstance()->GetFeatureOverrides(&enabled_features,
+ &disabled_features);
+ if (!enabled_features.empty())
+ cmd_line->AppendSwitchASCII(switches::kEnableFeatures, enabled_features);
+ if (!disabled_features.empty())
+ cmd_line->AppendSwitchASCII(switches::kDisableFeatures, disabled_features);
+
+ // If we run base::FieldTrials, we want to pass to their state to the
+ // child process so that it can act in accordance with each state.
+ std::string field_trial_states;
+ base::FieldTrialList::AllStatesToString(&field_trial_states);
+ if (!field_trial_states.empty()) {
+ cmd_line->AppendSwitchASCII(switches::kForceFieldTrials,
+ field_trial_states);
+ }
+}
+
void BrowserChildProcessHostImpl::Launch(
SandboxedProcessLauncherDelegate* delegate,
base::CommandLine* cmd_line,
@@ -195,11 +219,11 @@ void BrowserChildProcessHostImpl::Launch(
switches::kTraceToConsole,
switches::kV,
switches::kVModule,
- "use-new-edk", // TODO(use_chrome_edk): temporary.
};
cmd_line->CopySwitchesFrom(browser_command_line, kForwardSwitches,
arraysize(kForwardSwitches));
+ notify_child_disconnected_ = true;
child_process_.reset(new ChildProcessLauncher(
delegate,
cmd_line,
@@ -256,13 +280,6 @@ void BrowserChildProcessHostImpl::AddFilter(BrowserMessageFilter* filter) {
child_process_host_->AddFilter(filter->GetFilter());
}
-void BrowserChildProcessHostImpl::NotifyProcessInstanceCreated(
- const ChildProcessData& data) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- FOR_EACH_OBSERVER(BrowserChildProcessObserver, g_observers.Get(),
- BrowserChildProcessInstanceCreated(data));
-}
-
void BrowserChildProcessHostImpl::HistogramBadMessageTerminated(
int process_type) {
UMA_HISTOGRAM_ENUMERATION("ChildProcess.BadMessgeTerminated", process_type,
@@ -287,6 +304,7 @@ void BrowserChildProcessHostImpl::OnChannelConnected(int32_t peer_pid) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
is_channel_connected_ = true;
+ notify_child_disconnected_ = true;
#if defined(OS_WIN)
// From this point onward, the exit of the child process is detected by an
@@ -394,8 +412,6 @@ void BrowserChildProcessHostImpl::OnChildDisconnected() {
}
#endif
}
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&NotifyProcessHostDisconnected, data_));
delete delegate_; // Will delete us
}
@@ -405,6 +421,7 @@ bool BrowserChildProcessHostImpl::Send(IPC::Message* message) {
void BrowserChildProcessHostImpl::OnProcessLaunchFailed() {
delegate_->OnProcessLaunchFailed();
+ notify_child_disconnected_ = false;
delete delegate_; // Will delete us
}
@@ -414,25 +431,10 @@ void BrowserChildProcessHostImpl::OnProcessLaunched() {
const base::Process& process = child_process_->GetProcess();
DCHECK(process.IsValid());
- if (base::CommandLine::ForCurrentProcess()->HasSwitch("use-new-edk")) {
- mojo::embedder::ScopedPlatformHandle client_pipe;
-#if defined(MOJO_SHELL_CLIENT)
- if (IsRunningInMojoShell()) {
- client_pipe = RegisterProcessWithBroker(process.Pid());
- } else
-#endif
- {
- client_pipe = mojo::embedder::ChildProcessLaunched(process.Handle());
- }
- Send(new ChildProcessMsg_SetMojoParentPipeHandle(
- IPC::GetFileHandleForProcess(
-#if defined(OS_WIN)
- client_pipe.release().handle,
-#else
- client_pipe.release().fd,
-#endif
- process.Handle(), true)));
- }
+ mojo::edk::ScopedPlatformHandle client_pipe =
+ mojo::edk::ChildProcessLaunched(process.Handle());
+ Send(new ChildProcessMsg_SetMojoParentPipeHandle(
+ IPC::GetPlatformFileForTransit(client_pipe.release().handle, true)));
#if defined(OS_WIN)
// Start a WaitableEventWatcher that will invoke OnProcessExitedEarly if the
diff --git a/chromium/content/browser/browser_child_process_host_impl.h b/chromium/content/browser/browser_child_process_host_impl.h
index a5f3b6d528b..ce551a5da86 100644
--- a/chromium/content/browser/browser_child_process_host_impl.h
+++ b/chromium/content/browser/browser_child_process_host_impl.h
@@ -54,6 +54,11 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
// instance.
static void TerminateAll();
+ // Copies kEnableFeatures and kDisableFeatures to the command line. Generates
+ // them from the FeatureList override state, to take into account overrides
+ // from FieldTrials.
+ static void CopyFeatureAndFieldTrialFlags(base::CommandLine* cmd_line);
+
// BrowserChildProcessHost implementation:
bool Send(IPC::Message* message) override;
void Launch(SandboxedProcessLauncherDelegate* delegate,
@@ -89,9 +94,6 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
// Adds an IPC message filter.
void AddFilter(BrowserMessageFilter* filter);
- // Called when an instance of a particular child is created in a page.
- static void NotifyProcessInstanceCreated(const ChildProcessData& data);
-
static void HistogramBadMessageTerminated(int process_type);
BrowserChildProcessHostDelegate* delegate() const { return delegate_; }
@@ -135,6 +137,7 @@ class CONTENT_EXPORT BrowserChildProcessHostImpl
#endif
bool is_channel_connected_;
+ bool notify_child_disconnected_;
};
} // namespace content
diff --git a/chromium/content/browser/browser_context.cc b/chromium/content/browser/browser_context.cc
index fc3f644fba2..4b8396ed03e 100644
--- a/chromium/content/browser/browser_context.cc
+++ b/chromium/content/browser/browser_context.cc
@@ -6,11 +6,15 @@
#include <stddef.h>
#include <stdint.h>
+#include <algorithm>
+#include <limits>
#include <utility>
+#include "base/guid.h"
+#include "base/lazy_instance.h"
+#include "base/rand_util.h"
#include "build/build_config.h"
-
-#if !defined(OS_IOS)
+#include "components/profile_service/user_id_map.h"
#include "content/browser/download/download_manager_impl.h"
#include "content/browser/fileapi/chrome_blob_storage_context.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
@@ -22,7 +26,6 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/site_instance.h"
-#include "net/cookies/cookie_monster.h"
#include "net/cookies/cookie_store.h"
#include "net/ssl/channel_id_service.h"
#include "net/ssl/channel_id_store.h"
@@ -30,20 +33,24 @@
#include "net/url_request/url_request_context_getter.h"
#include "storage/browser/database/database_tracker.h"
#include "storage/browser/fileapi/external_mount_points.h"
-#endif // !OS_IOS
using base::UserDataAdapter;
namespace content {
-// Only ~BrowserContext() is needed on iOS.
-#if !defined(OS_IOS)
namespace {
+base::LazyInstance<std::set<std::string>> g_used_user_ids =
+ LAZY_INSTANCE_INITIALIZER;
+base::LazyInstance<std::vector<std::pair<BrowserContext*, std::string>>>
+g_context_to_user_id = LAZY_INSTANCE_INITIALIZER;
+
// Key names on BrowserContext.
const char kDownloadManagerKeyName[] = "download_manager";
const char kStoragePartitionMapKeyName[] = "content_storage_partition_map";
+const char kMojoWasInitialized[] = "mojo-was-initialized";
+
#if defined(OS_CHROMEOS)
const char kMountPointsKey[] = "mount_points";
#endif // defined(OS_CHROMEOS)
@@ -78,8 +85,7 @@ void SaveSessionStateOnIOThread(
const scoped_refptr<net::URLRequestContextGetter>& context_getter,
AppCacheServiceImpl* appcache_service) {
net::URLRequestContext* context = context_getter->GetURLRequestContext();
- context->cookie_store()->GetCookieMonster()->
- SetForceKeepSessionState();
+ context->cookie_store()->SetForceKeepSessionState();
context->channel_id_service()->GetChannelIDStore()->
SetForceKeepSessionState();
appcache_service->set_force_keep_session_state();
@@ -255,11 +261,12 @@ void BrowserContext::DeliverPushMessage(
BrowserContext* browser_context,
const GURL& origin,
int64_t service_worker_registration_id,
- const std::string& data,
+ const PushEventPayload& payload,
const base::Callback<void(PushDeliveryStatus)>& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- PushMessagingRouter::DeliverMessage(
- browser_context, origin, service_worker_registration_id, data, callback);
+ PushMessagingRouter::DeliverMessage(browser_context, origin,
+ service_worker_registration_id, payload,
+ callback);
}
// static
@@ -322,13 +329,44 @@ void BrowserContext::SetDownloadManagerForTesting(
SetDownloadManager(browser_context, download_manager);
}
-#endif // !OS_IOS
+void BrowserContext::Initialize(
+ BrowserContext* browser_context,
+ const base::FilePath& path) {
+ // Generate a GUID for |browser_context| to use as the Mojo user id.
+ std::string new_id = base::GenerateGUID();
+ while (g_used_user_ids.Get().find(new_id) != g_used_user_ids.Get().end())
+ new_id = base::GenerateGUID();
+
+ g_used_user_ids.Get().insert(new_id);
+ g_context_to_user_id.Get().push_back(std::make_pair(browser_context, new_id));
+
+ profile::AssociateMojoUserIDWithProfileDir(new_id, path);
+ browser_context->SetUserData(kMojoWasInitialized,
+ new base::SupportsUserData::Data);
+}
+
+const std::string& BrowserContext::GetMojoUserIdFor(
+ BrowserContext* browser_context) {
+ CHECK(browser_context->GetUserData(kMojoWasInitialized))
+ << "Attempting to get the mojo user id for a BrowserContext that was "
+ << "never Initialize()ed.";
+
+ auto it = std::find_if(
+ g_context_to_user_id.Get().begin(),
+ g_context_to_user_id.Get().end(),
+ [&browser_context](const std::pair<BrowserContext*, std::string>& p) {
+ return p.first == browser_context; });
+ CHECK(it != g_context_to_user_id.Get().end());
+ return it->second;
+}
BrowserContext::~BrowserContext() {
-#if !defined(OS_IOS)
+ CHECK(GetUserData(kMojoWasInitialized))
+ << "Attempting to destroy a BrowserContext that never called "
+ << "Initialize()";
+
if (GetUserData(kDownloadManagerKeyName))
GetDownloadManager(this)->Shutdown();
-#endif
}
} // namespace content
diff --git a/chromium/content/browser/browser_main.cc b/chromium/content/browser/browser_main.cc
index d0897f1d650..459bde05a4d 100644
--- a/chromium/content/browser/browser_main.cc
+++ b/chromium/content/browser/browser_main.cc
@@ -4,6 +4,7 @@
#include "content/browser/browser_main.h"
+#include "base/memory/scoped_ptr.h"
#include "base/trace_event/trace_event.h"
#include "content/common/content_constants_internal.h"
#include "content/public/browser/browser_main_runner.h"
diff --git a/chromium/content/browser/browser_main_loop.cc b/chromium/content/browser/browser_main_loop.cc
index 63ee2cca5d9..175e9d69f7e 100644
--- a/chromium/content/browser/browser_main_loop.cc
+++ b/chromium/content/browser/browser_main_loop.cc
@@ -32,6 +32,7 @@
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
+#include "components/tracing/process_metrics_memory_dump_provider.h"
#include "components/tracing/trace_config_file.h"
#include "components/tracing/trace_to_console.h"
#include "components/tracing/tracing_switches.h"
@@ -52,14 +53,17 @@
#include "content/browser/mojo/mojo_shell_context.h"
#include "content/browser/net/browser_online_state_observer.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/speech/speech_recognition_manager_impl.h"
#include "content/browser/startup_task_runner.h"
#include "content/browser/time_zone_monitor.h"
+#include "content/browser/utility_process_host_impl.h"
#include "content/browser/webui/content_web_ui_controller_factory.h"
#include "content/browser/webui/url_data_manager.h"
#include "content/common/content_switches_internal.h"
#include "content/common/host_discardable_shared_memory_manager.h"
#include "content/common/host_shared_bitmap_manager.h"
+#include "content/common/mojo/mojo_shell_connection_impl.h"
#include "content/public/browser/browser_main_parts.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_process_host.h"
@@ -73,6 +77,8 @@
#include "media/base/media.h"
#include "media/base/user_input_monitor.h"
#include "media/midi/midi_manager.h"
+#include "mojo/edk/embedder/embedder.h"
+#include "mojo/shell/public/cpp/shell.h"
#include "net/base/network_change_notifier.h"
#include "net/socket/client_socket_factory.h"
#include "net/ssl/ssl_config_service.h"
@@ -81,7 +87,7 @@
#include "sql/sql_memory_dump_provider.h"
#include "ui/base/clipboard/clipboard.h"
-#if defined(USE_AURA) || (defined(OS_MACOSX) && !defined(OS_IOS))
+#if defined(USE_AURA) || defined(OS_MACOSX)
#include "content/browser/compositor/image_transport_factory.h"
#endif
@@ -90,10 +96,6 @@
#include "ui/aura/env.h"
#endif
-#if !defined(OS_IOS)
-#include "content/browser/renderer_host/render_process_host_impl.h"
-#endif
-
#if defined(OS_ANDROID)
#include "base/android/jni_android.h"
#include "components/tracing/graphics_memory_dump_provider_android.h"
@@ -106,18 +108,18 @@
#include "ui/gl/gl_surface.h"
#endif
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MACOSX)
#include "base/memory/memory_pressure_monitor_mac.h"
#include "content/browser/bootstrap_sandbox_manager_mac.h"
#include "content/browser/cocoa/system_hotkey_helper_mac.h"
-#include "content/browser/compositor/browser_compositor_view_mac.h"
+#include "content/browser/mach_broker_mac.h"
+#include "content/browser/renderer_host/browser_compositor_view_mac.h"
#include "content/browser/theme_helper_mac.h"
#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
#endif
#if defined(USE_OZONE)
#include "ui/ozone/public/client_native_pixmap_factory.h"
-#include "ui/ozone/public/ozone_platform.h"
#endif
#if defined(OS_WIN)
@@ -126,7 +128,8 @@
#include <shellapi.h>
#include "base/memory/memory_pressure_monitor_win.h"
-#include "content/browser/system_message_window_win.h"
+#include "base/win/windows_version.h"
+#include "content/browser/screen_orientation/screen_orientation_delegate_win.h"
#include "content/common/sandbox_win.h"
#include "net/base/winsock_init.h"
#include "ui/base/l10n/l10n_util_win.h"
@@ -141,26 +144,29 @@
#include <glib-object.h>
#endif
-#if defined(OS_LINUX) && defined(USE_UDEV)
-#include "content/browser/device_monitor_udev.h"
-#elif defined(OS_MACOSX) && !defined(OS_IOS)
-#include "content/browser/device_monitor_mac.h"
+#if defined(OS_WIN)
+#include "media/capture/system_message_window_win.h"
+#elif defined(OS_LINUX) && defined(USE_UDEV)
+#include "media/capture/device_monitor_udev.h"
+#elif defined(OS_MACOSX)
+#include "media/capture/device_monitor_mac.h"
#endif
#if defined(OS_POSIX) && !defined(OS_MACOSX)
#include "content/browser/renderer_host/render_sandbox_host_linux.h"
#include "content/browser/zygote_host/zygote_host_impl_linux.h"
#include "sandbox/linux/suid/client/setuid_sandbox_host.h"
-#endif
+
+#if !defined(OS_ANDROID)
+#include "content/public/browser/zygote_handle_linux.h"
+#endif // !defined(OS_ANDROID)
+#endif // defined(OS_POSIX) && !defined(OS_MACOSX)
+
#if defined(ENABLE_PLUGINS)
#include "content/browser/plugin_service_impl.h"
#endif
-#if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED)
-#include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
-#endif
-
#if defined(USE_X11)
#include "ui/base/x/x11_util_internal.h"
#include "ui/gfx/x/x11_connection.h"
@@ -173,11 +179,7 @@
#endif
#if defined(MOJO_SHELL_CLIENT)
-#include "components/mus/public/interfaces/window_manager.mojom.h"
-#include "content/common/mojo/mojo_shell_connection_impl.h"
-#include "mojo/converters/network/network_type_converters.h"
-#include "mojo/shell/public/cpp/application_impl.h"
-#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
+#include "mojo/shell/public/cpp/connector.h"
#include "ui/views/mus/window_manager_connection.h"
#endif
@@ -220,6 +222,8 @@ void SetupSandbox(const base::CommandLine& parsed_command_line) {
// Tickle the sandbox host and zygote host so they fork now.
RenderSandboxHostLinux::GetInstance()->Init();
ZygoteHostImpl::GetInstance()->Init(sandbox_binary.value());
+ *GetGenericZygote() = CreateZygote();
+ RenderProcessHostImpl::EarlyZygoteLaunch();
}
#endif
@@ -332,13 +336,11 @@ NOINLINE void ResetThread_IO(scoped_ptr<BrowserProcessSubThread> thread) {
thread.reset();
}
-#if !defined(OS_IOS)
NOINLINE void ResetThread_IndexedDb(scoped_ptr<base::Thread> thread) {
volatile int inhibit_comdat = __LINE__;
ALLOW_UNUSED_LOCAL(inhibit_comdat);
thread.reset();
}
-#endif
MSVC_POP_WARNING()
MSVC_ENABLE_OPTIMIZE();
@@ -383,13 +385,11 @@ class BrowserMainLoop::MemoryObserver : public base::MessageLoop::TaskObserver {
void WillProcessTask(const base::PendingTask& pending_task) override {}
void DidProcessTask(const base::PendingTask& pending_task) override {
-#if !defined(OS_IOS) // No ProcessMetrics on IOS.
scoped_ptr<base::ProcessMetrics> process_metrics(
base::ProcessMetrics::CreateCurrentProcessMetrics());
size_t private_bytes;
process_metrics->GetMemoryBytes(&private_bytes, NULL);
LOCAL_HISTOGRAM_MEMORY_KB("Memory.BrowserUsed", private_bytes >> 10);
-#endif
}
private:
DISALLOW_COPY_AND_ASSIGN(MemoryObserver);
@@ -420,9 +420,7 @@ BrowserMainLoop::BrowserMainLoop(const MainFunctionParams& parameters)
BrowserMainLoop::~BrowserMainLoop() {
DCHECK_EQ(this, g_current_browser_main_loop);
-#if !defined(OS_IOS)
ui::Clipboard::DestroyClipboardForCurrentThread();
-#endif // !defined(OS_IOS)
g_current_browser_main_loop = NULL;
}
@@ -497,7 +495,6 @@ void BrowserMainLoop::EarlyInitialization() {
crypto::EnsureNSPRInit();
#endif
-#if !defined(OS_IOS)
if (parsed_command_line_.HasSwitch(switches::kRendererProcessLimit)) {
std::string limit_string = parsed_command_line_.GetSwitchValueASCII(
switches::kRendererProcessLimit);
@@ -506,7 +503,6 @@ void BrowserMainLoop::EarlyInitialization() {
RenderProcessHost::SetMaxRendererProcessCount(process_limit);
}
}
-#endif // !defined(OS_IOS)
if (parts_)
parts_->PostEarlyInitialization();
@@ -563,8 +559,6 @@ void BrowserMainLoop::PostMainMessageLoopStart() {
TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:NetworkChangeNotifier");
network_change_notifier_.reset(net::NetworkChangeNotifier::Create());
}
-
-#if !defined(OS_IOS)
{
TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:MediaFeatures");
media::InitializeMediaLibrary();
@@ -586,10 +580,10 @@ void BrowserMainLoop::PostMainMessageLoopStart() {
new base::trace_event::TraceEventSystemStatsMonitor(
base::ThreadTaskRunnerHandle::Get()));
}
-#endif // !defined(OS_IOS)
#if defined(OS_WIN)
- system_message_window_.reset(new SystemMessageWindowWin);
+ if (base::win::GetVersion() >= base::win::VERSION_WIN8)
+ screen_orientation_delegate_.reset(new ScreenOrientationDelegateWin());
#endif
// TODO(boliu): kSingleProcess check is a temporary workaround for
@@ -622,7 +616,6 @@ void BrowserMainLoop::PostMainMessageLoopStart() {
tracing::TraceConfigFile::GetInstance()->GetTraceConfig(),
TracingController::StartTracingDoneCallback());
}
-#if !defined(OS_IOS)
// Start tracing to a file for certain duration if needed. Only do this after
// starting the main message loop to avoid calling
// MessagePumpForUI::ScheduleWork() before MessagePumpForUI::Start() as it
@@ -631,20 +624,19 @@ void BrowserMainLoop::PostMainMessageLoopStart() {
TRACE_EVENT0("startup", "BrowserMainLoop::InitStartupTracingForDuration");
InitStartupTracingForDuration(parsed_command_line_);
}
-#endif // !defined(OS_IOS)
#if defined(OS_ANDROID)
{
TRACE_EVENT0("startup", "BrowserMainLoop::Subsystem:SurfaceTextureManager");
if (parsed_command_line_.HasSwitch(switches::kSingleProcess)) {
- SurfaceTextureManager::SetInstance(
+ gpu::SurfaceTextureManager::SetInstance(
InProcessSurfaceTextureManager::GetInstance());
} else {
- SurfaceTextureManager::SetInstance(
+ gpu::SurfaceTextureManager::SetInstance(
BrowserSurfaceTextureManager::GetInstance());
}
}
-#if !defined(USE_AURA)
+
if (!parsed_command_line_.HasSwitch(
switches::kDisableScreenOrientationLock)) {
TRACE_EVENT0("startup",
@@ -654,9 +646,8 @@ void BrowserMainLoop::PostMainMessageLoopStart() {
ScreenOrientationProvider::SetDelegate(screen_orientation_delegate_.get());
}
#endif
-#endif
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MACOSX)
if (BootstrapSandboxManager::ShouldEnable()) {
TRACE_EVENT0("startup",
"BrowserMainLoop::Subsystem:BootstrapSandbox");
@@ -668,8 +659,6 @@ void BrowserMainLoop::PostMainMessageLoopStart() {
client_native_pixmap_factory_ = ui::ClientNativePixmapFactory::Create();
ui::ClientNativePixmapFactory::SetInstance(
client_native_pixmap_factory_.get());
- ui::ClientNativePixmapFactory::GetInstance()->Initialize(
- ui::OzonePlatform::GetInstance()->OpenClientNativePixmapDevice());
#endif
if (parsed_command_line_.HasSwitch(switches::kMemoryMetrics)) {
@@ -687,6 +676,8 @@ void BrowserMainLoop::PostMainMessageLoopStart() {
// Enable memory-infra dump providers.
InitSkiaEventTracer();
+ tracing::ProcessMetricsMemoryDumpProvider::RegisterForProcess(
+ base::kNullProcessId);
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
HostSharedBitmapManager::current(), "HostSharedBitmapManager", nullptr);
base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
@@ -704,9 +695,13 @@ int BrowserMainLoop::PreCreateThreads() {
result_code_ = parts_->PreCreateThreads();
}
- // Initialize an instance of FeatureList. This will be a no-op if an instance
- // was already set up by the embedder.
- base::FeatureList::InitializeInstance();
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
+ // Note that we do not initialize a new FeatureList when calling this for
+ // the second time.
+ base::FeatureList::InitializeInstance(
+ command_line->GetSwitchValueASCII(switches::kEnableFeatures),
+ command_line->GetSwitchValueASCII(switches::kDisableFeatures));
// TODO(chrisha): Abstract away this construction mess to a helper function,
// once MemoryPressureMonitor is made a concrete class.
@@ -715,7 +710,7 @@ int BrowserMainLoop::PreCreateThreads() {
memory_pressure_monitor_.reset(new base::chromeos::MemoryPressureMonitor(
chromeos::switches::GetMemoryPressureThresholds()));
}
-#elif defined(OS_MACOSX) && !defined(OS_IOS)
+#elif defined(OS_MACOSX)
memory_pressure_monitor_.reset(new base::mac::MemoryPressureMonitor());
#elif defined(OS_WIN)
memory_pressure_monitor_.reset(CreateWinMemoryPressureMonitor(
@@ -733,7 +728,7 @@ int BrowserMainLoop::PreCreateThreads() {
}
#endif
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MACOSX)
// The WindowResizeHelper allows the UI thread to wait on specific renderer
// and GPU messages from the IO thread. Initializing it before the IO thread
// starts ensures the affected IO thread messages always have somewhere to go.
@@ -746,7 +741,7 @@ int BrowserMainLoop::PreCreateThreads() {
// 2) Must be after parts_->PreCreateThreads to pick up chrome://flags.
GpuDataManagerImpl::GetInstance()->Initialize();
-#if !defined(OS_IOS) && (!defined(GOOGLE_CHROME_BUILD) || defined(OS_ANDROID))
+#if !defined(GOOGLE_CHROME_BUILD) || defined(OS_ANDROID)
// Single-process is an unsupported and not fully tested mode, so
// don't enable it for official Chrome builds (except on Android).
if (parsed_command_line_.HasSwitch(switches::kSingleProcess))
@@ -868,7 +863,9 @@ int BrowserMainLoop::CreateThreads() {
"BrowserMainLoop::CreateThreads:start",
"Thread", "BrowserThread::CACHE");
thread_to_start = &cache_thread_;
+#if defined(OS_WIN)
options = io_message_loop_options;
+#endif // defined(OS_WIN)
options.timer_slack = base::TIMER_SLACK_MAXIMUM;
break;
case BrowserThread::IO:
@@ -877,7 +874,7 @@ int BrowserMainLoop::CreateThreads() {
"Thread", "BrowserThread::IO");
thread_to_start = &io_thread_;
options = io_message_loop_options;
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
// Up the priority of the |io_thread_| as some of its IPCs relate to
// display tasks.
options.priority = base::ThreadPriority::DISPLAY;
@@ -908,17 +905,19 @@ int BrowserMainLoop::CreateThreads() {
}
int BrowserMainLoop::PreMainMessageLoopRun() {
-#if defined(MOJO_SHELL_CLIENT)
if (IsRunningInMojoShell()) {
- mojo::embedder::PreInitializeChildProcess();
- MojoShellConnectionImpl::Create();
- MojoShellConnectionImpl::Get()->BindToCommandLinePlatformChannel();
-#if defined(USE_AURA)
- views::WindowManagerConnection::Create(
- MojoShellConnection::Get()->GetApplication());
+ if (!MojoShellConnectionImpl::CreateUsingFactory()) {
+ mojo::edk::SetParentPipeHandleFromCommandLine();
+ MojoShellConnectionImpl::Create();
+ MojoShellConnectionImpl::Get()->BindToRequestFromCommandLine();
+ }
+#if defined(MOJO_SHELL_CLIENT) && defined(USE_AURA)
+ if (MojoShellConnection::Get()) {
+ views::WindowManagerConnection::Create(
+ MojoShellConnection::Get()->GetConnector());
+ }
#endif
}
-#endif
if (parts_) {
TRACE_EVENT0("startup",
@@ -966,16 +965,11 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
base::Bind(base::IgnoreResult(&base::ThreadRestrictions::SetIOAllowed),
true));
-#if defined(MOJO_SHELL_CLIENT)
- MojoShellConnection::Destroy();
-#endif
- mojo_ipc_support_.reset();
- mojo_shell_context_.reset();
+ if (IsRunningInMojoShell())
+ MojoShellConnection::Destroy();
-#if !defined(OS_IOS)
if (RenderProcessHost::run_renderer_in_process())
RenderProcessHostImpl::ShutDownInProcessRenderer();
-#endif
if (parts_) {
TRACE_EVENT0("shutdown",
@@ -989,7 +983,6 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
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
@@ -1034,7 +1027,10 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
#elif defined(OS_MACOSX)
device_monitor_mac_.reset();
#endif
-#endif // !defined(OS_IOS)
+
+ // Shutdown Mojo shell and IPC.
+ mojo_shell_context_.reset();
+ mojo_ipc_support_.reset();
// Must be size_t so we can subtract from it.
for (size_t thread_id = BrowserThread::ID_COUNT - 1;
@@ -1065,12 +1061,10 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
}
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();
-#endif // !defined(OS_IOS)
ResetThread_FILE(std::move(file_thread_));
break;
}
@@ -1102,13 +1096,10 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
break;
}
}
-
-#if !defined(OS_IOS)
{
TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:IndexedDBThread");
ResetThread_IndexedDb(std::move(indexed_db_thread_));
}
-#endif
// Close the blocking I/O pool after the other threads. Other threads such
// as the I/O thread may need to schedule work like closing files or flushing
@@ -1120,8 +1111,6 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
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.
{
@@ -1150,7 +1139,6 @@ void BrowserMainLoop::ShutdownThreadsAndCleanUp() {
TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:DeleteDataSources");
URLDataManager::DeleteDataSources();
}
-#endif // !defined(OS_IOS)
if (parts_) {
TRACE_EVENT0("shutdown", "BrowserMainLoop::Subsystem:PostDestroyThreads");
@@ -1177,21 +1165,28 @@ void BrowserMainLoop::InitializeMainThread() {
int BrowserMainLoop::BrowserThreadsStarted() {
TRACE_EVENT0("startup", "BrowserMainLoop::BrowserThreadsStarted");
-#if !defined(OS_IOS)
+ // Bring up Mojo IPC and shell as early as possible.
+ mojo_ipc_support_.reset(new IPC::ScopedIPCSupport(
+ BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO)
+ ->task_runner()));
+ mojo_shell_context_.reset(new MojoShellContext(file_thread_->task_runner(),
+ db_thread_->task_runner()));
+#if defined(OS_MACOSX)
+ mojo::edk::SetMachPortProvider(MachBroker::GetInstance());
+#endif // defined(OS_MACOSX)
+
indexed_db_thread_.reset(new base::Thread("IndexedDB"));
indexed_db_thread_->Start();
-#endif
-#if !defined(OS_IOS)
HistogramSynchronizer::GetInstance();
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
// Up the priority of the UI thread.
base::PlatformThread::SetCurrentThreadPriority(base::ThreadPriority::DISPLAY);
#endif
bool always_uses_gpu = true;
bool established_gpu_channel = false;
-#if defined(OS_ANDROID) && !defined(USE_AURA)
+#if defined(OS_ANDROID)
// TODO(crbug.com/439322): This should be set to |true|.
established_gpu_channel = false;
BrowserGpuChannelHostFactory::Initialize(established_gpu_channel);
@@ -1238,10 +1233,13 @@ int BrowserMainLoop::BrowserThreadsStarted() {
midi_manager_.reset(media::midi::MidiManager::Create());
}
-#if defined(OS_LINUX) && defined(USE_UDEV)
- device_monitor_linux_.reset(new DeviceMonitorLinux());
+#if defined(OS_WIN)
+ system_message_window_.reset(new media::SystemMessageWindowWin);
+#elif defined(OS_LINUX) && defined(USE_UDEV)
+ device_monitor_linux_.reset(
+ new media::DeviceMonitorLinux(io_thread_->task_runner()));
#elif defined(OS_MACOSX)
- device_monitor_mac_.reset(new DeviceMonitorMac());
+ device_monitor_mac_.reset(new media::DeviceMonitorMac());
#endif
#if defined(OS_WIN)
@@ -1316,13 +1314,6 @@ int BrowserMainLoop::BrowserThreadsStarted() {
SystemHotkeyHelperMac::GetInstance()->DeferredLoadSystemHotkeys();
#endif // defined(OS_MACOSX)
-#endif // !defined(OS_IOS)
-
- mojo_shell_context_.reset(new MojoShellContext);
- mojo_ipc_support_.reset(new IPC::ScopedIPCSupport(
- BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO)
- ->task_runner()));
-
return result_code_;
}
@@ -1409,7 +1400,7 @@ base::FilePath BrowserMainLoop::GetStartupTraceFileName(
return trace_file;
if (trace_file.empty()) {
-#if defined(OS_ANDROID) && !defined(USE_AURA)
+#if defined(OS_ANDROID)
TracingControllerAndroid::GenerateTracingFilePath(&trace_file);
#else
// Default to saving the startup trace into the current dir.
@@ -1417,7 +1408,7 @@ base::FilePath BrowserMainLoop::GetStartupTraceFileName(
#endif
}
} else {
-#if defined(OS_ANDROID) && !defined(USE_AURA)
+#if defined(OS_ANDROID)
TracingControllerAndroid::GenerateTracingFilePath(&trace_file);
#else
trace_file = tracing::TraceConfigFile::GetInstance()->GetResultFile();
diff --git a/chromium/content/browser/browser_main_loop.h b/chromium/content/browser/browser_main_loop.h
index ae07f764237..e8a13a03881 100644
--- a/chromium/content/browser/browser_main_loop.h
+++ b/chromium/content/browser/browser_main_loop.h
@@ -33,7 +33,15 @@ class ScopedIPCSupport;
namespace media {
class AudioManager;
+#if defined(OS_WIN)
+class SystemMessageWindowWin;
+#elif defined(OS_LINUX) && defined(USE_UDEV)
+class DeviceMonitorLinux;
+#endif
class UserInputMonitor;
+#if defined(OS_MACOSX)
+class DeviceMonitorMac;
+#endif
namespace midi {
class MidiManager;
} // namespace midi
@@ -63,12 +71,8 @@ struct MainFunctionParams;
#if defined(OS_ANDROID)
class ScreenOrientationDelegate;
-#elif defined(OS_LINUX)
-class DeviceMonitorLinux;
-#elif defined(OS_MACOSX)
-class DeviceMonitorMac;
#elif defined(OS_WIN)
-class SystemMessageWindowWin;
+class ScreenOrientationDelegate;
#endif
// Implements the main browser loop stages called from BrowserMainRunner.
@@ -130,7 +134,7 @@ class CONTENT_EXPORT BrowserMainLoop {
void StopStartupTracingTimer();
#if defined(OS_MACOSX) && !defined(OS_IOS)
- DeviceMonitorMac* device_monitor_mac() const {
+ media::DeviceMonitorMac* device_monitor_mac() const {
return device_monitor_mac_.get();
}
#endif
@@ -198,7 +202,7 @@ class CONTENT_EXPORT BrowserMainLoop {
system_stats_monitor_;
#if defined(OS_WIN)
- scoped_ptr<SystemMessageWindowWin> system_message_window_;
+ scoped_ptr<ScreenOrientationDelegate> screen_orientation_delegate_;
#endif
#if defined(OS_ANDROID)
@@ -249,10 +253,12 @@ class CONTENT_EXPORT BrowserMainLoop {
scoped_ptr<media::midi::MidiManager> midi_manager_;
-#if defined(USE_UDEV)
- scoped_ptr<DeviceMonitorLinux> device_monitor_linux_;
+#if defined(OS_WIN)
+ scoped_ptr<media::SystemMessageWindowWin> system_message_window_;
+#elif defined(OS_LINUX) && defined(USE_UDEV)
+ scoped_ptr<media::DeviceMonitorLinux> device_monitor_linux_;
#elif defined(OS_MACOSX) && !defined(OS_IOS)
- scoped_ptr<DeviceMonitorMac> device_monitor_mac_;
+ scoped_ptr<media::DeviceMonitorMac> device_monitor_mac_;
#endif
#if defined(USE_OZONE)
scoped_ptr<ui::ClientNativePixmapFactory> client_native_pixmap_factory_;
diff --git a/chromium/content/browser/browser_main_runner.cc b/chromium/content/browser/browser_main_runner.cc
index 2585c8dd870..de130940eff 100644
--- a/chromium/content/browser/browser_main_runner.cc
+++ b/chromium/content/browser/browser_main_runner.cc
@@ -15,6 +15,7 @@
#include "base/profiler/scoped_profile.h"
#include "base/profiler/scoped_tracker.h"
#include "base/time/time.h"
+#include "base/trace_event/heap_profiler_allocation_context_tracker.h"
#include "base/trace_event/trace_event.h"
#include "base/tracked_objects.h"
#include "build/build_config.h"
@@ -34,12 +35,8 @@
#endif
#if defined(OS_WIN)
-#include "base/win/win_util.h"
#include "base/win/windows_version.h"
-#include "net/cert/sha256_legacy_support_win.h"
-#include "sandbox/win/src/sidestep/preamble_patcher.h"
#include "ui/base/win/scoped_ole_initializer.h"
-#include "ui/gfx/switches.h"
#include "ui/gfx/win/direct_write.h"
#endif
@@ -48,86 +45,7 @@ namespace content {
namespace {
bool g_exited_main_message_loop = false;
-
-#if defined(OS_WIN)
-#if !defined(_WIN64)
-// Pointer to the original CryptVerifyCertificateSignatureEx function.
-net::sha256_interception::CryptVerifyCertificateSignatureExFunc
- g_real_crypt_verify_signature_stub = NULL;
-
-// Stub function that is called whenever the Crypt32 function
-// CryptVerifyCertificateSignatureEx is called. It just defers to net to perform
-// the actual verification.
-BOOL WINAPI CryptVerifyCertificateSignatureExStub(
- HCRYPTPROV_LEGACY provider,
- DWORD encoding_type,
- DWORD subject_type,
- void* subject_data,
- DWORD issuer_type,
- void* issuer_data,
- DWORD flags,
- void* extra) {
- return net::sha256_interception::CryptVerifyCertificateSignatureExHook(
- g_real_crypt_verify_signature_stub, provider, encoding_type, subject_type,
- subject_data, issuer_type, issuer_data, flags, extra);
-}
-#endif // !defined(_WIN64)
-
-// If necessary, install an interception
-void InstallSha256LegacyHooks() {
-#if defined(_WIN64)
- // Interception on x64 is not supported.
- return;
-#else
- if (base::win::MaybeHasSHA256Support())
- return;
-
- net::sha256_interception::CryptVerifyCertificateSignatureExFunc
- cert_verify_signature_ptr = reinterpret_cast<
- net::sha256_interception::CryptVerifyCertificateSignatureExFunc>(
- ::GetProcAddress(::GetModuleHandle(L"crypt32.dll"),
- "CryptVerifyCertificateSignatureEx"));
- CHECK(cert_verify_signature_ptr);
-
- DWORD old_protect = 0;
- if (!::VirtualProtect(cert_verify_signature_ptr, 5, PAGE_EXECUTE_READWRITE,
- &old_protect)) {
- return;
- }
-
- g_real_crypt_verify_signature_stub =
- reinterpret_cast<
- net::sha256_interception::CryptVerifyCertificateSignatureExFunc>(
- VirtualAllocEx(::GetCurrentProcess(), NULL,
- sidestep::kMaxPreambleStubSize, MEM_COMMIT,
- PAGE_EXECUTE_READWRITE));
- if (g_real_crypt_verify_signature_stub == NULL) {
- CHECK(::VirtualProtect(cert_verify_signature_ptr, 5, old_protect,
- &old_protect));
- return;
- }
-
- sidestep::SideStepError patch_result =
- sidestep::PreamblePatcher::Patch(
- cert_verify_signature_ptr, CryptVerifyCertificateSignatureExStub,
- g_real_crypt_verify_signature_stub, sidestep::kMaxPreambleStubSize);
- if (patch_result != sidestep::SIDESTEP_SUCCESS) {
- CHECK(::VirtualFreeEx(::GetCurrentProcess(),
- g_real_crypt_verify_signature_stub, 0,
- MEM_RELEASE));
- CHECK(::VirtualProtect(cert_verify_signature_ptr, 5, old_protect,
- &old_protect));
- return;
- }
-
- DWORD dummy = 0;
- CHECK(::VirtualProtect(cert_verify_signature_ptr, 5, old_protect, &dummy));
- CHECK(::VirtualProtect(g_real_crypt_verify_signature_stub,
- sidestep::kMaxPreambleStubSize, old_protect,
- &old_protect));
-#endif // _WIN64
-}
-#endif // OS_WIN
+const char kMainThreadName[] = "CrBrowserMain";
} // namespace
@@ -147,7 +65,9 @@ class BrowserMainRunnerImpl : public BrowserMainRunner {
// TODO(vadimt, yiyaoliu): Remove all tracked_objects references below once
// crbug.com/453640 is fixed.
- tracked_objects::ThreadData::InitializeThreadContext("CrBrowserMain");
+ tracked_objects::ThreadData::InitializeThreadContext(kMainThreadName);
+ base::trace_event::AllocationContextTracker::SetCurrentThreadName(
+ kMainThreadName);
TRACK_SCOPED_REGION(
"Startup", "BrowserMainRunnerImpl::Initialize");
TRACE_EVENT0("startup", "BrowserMainRunnerImpl::Initialize");
@@ -163,10 +83,8 @@ class BrowserMainRunnerImpl : public BrowserMainRunner {
SkGraphics::Init();
-#if !defined(OS_IOS)
if (parameters.command_line.HasSwitch(switches::kWaitForDebugger))
base::debug::WaitForDebugger(60, true);
-#endif
#if defined(OS_WIN)
if (base::win::GetVersion() < base::win::VERSION_VISTA) {
@@ -180,7 +98,6 @@ class BrowserMainRunnerImpl : public BrowserMainRunner {
// Win32 API here directly.
ImmDisableTextFrameService(static_cast<DWORD>(-1));
}
- InstallSha256LegacyHooks();
#endif // OS_WIN
base::StatisticsRecorder::Initialize();
@@ -266,7 +183,7 @@ class BrowserMainRunnerImpl : public BrowserMainRunner {
} else if (tracing::TraceConfigFile::GetInstance()->IsEnabled() &&
TracingController::GetInstance()->IsTracing()) {
base::FilePath result_file;
-#if defined(OS_ANDROID) && !defined(USE_AURA)
+#if defined(OS_ANDROID)
TracingControllerAndroid::GenerateTracingFilePath(&result_file);
#else
result_file = tracing::TraceConfigFile::GetInstance()->GetResultFile();
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc b/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc
index 68899faf82a..274315ecd3b 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc
+++ b/chromium/content/browser/browser_plugin/browser_plugin_embedder.cc
@@ -105,9 +105,7 @@ void BrowserPluginEmbedder::ClearGuestDragStateIfApplicable() {
// static
bool BrowserPluginEmbedder::DidSendScreenRectsCallback(
WebContents* guest_web_contents) {
- RenderWidgetHostImpl::From(
- guest_web_contents->GetRenderViewHost()->GetWidget())
- ->SendScreenRects();
+ static_cast<WebContentsImpl*>(guest_web_contents)->SendScreenRects();
// Not handled => Iterate over all guests.
return false;
}
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
index 33262a832e5..fd0c173ed0b 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.cc
@@ -21,6 +21,7 @@
#include "content/browser/compositor/surface_utils.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/frame_host/render_frame_proxy_host.h"
+#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
#include "content/browser/frame_host/render_widget_host_view_guest.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
@@ -119,9 +120,9 @@ int BrowserPluginGuest::GetGuestProxyRoutingID() {
if (guest_proxy_routing_id_ != MSG_ROUTING_NONE)
return guest_proxy_routing_id_;
- // Create a swapped out RenderView for the guest in the embedder renderer
+ // Create a RenderFrameProxyHost for the guest in the embedder renderer
// process, so that the embedder can access the guest's window object.
- // On reattachment, we can reuse the same swapped out RenderView because
+ // On reattachment, we can reuse the same RenderFrameProxyHost because
// the embedder process will always be the same even if the embedder
// WebContents changes.
//
@@ -130,17 +131,12 @@ int BrowserPluginGuest::GetGuestProxyRoutingID() {
// |guest_proxy_routing_id_| and perform any necessary cleanup on Detach
// to enable this.
SiteInstance* owner_site_instance = owner_web_contents_->GetSiteInstance();
- if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- int proxy_routing_id =
- GetWebContents()->GetFrameTree()->root()->render_manager()->
- CreateRenderFrameProxy(owner_site_instance);
- guest_proxy_routing_id_ = RenderFrameProxyHost::FromID(
- owner_site_instance->GetProcess()->GetID(), proxy_routing_id)
- ->GetRenderViewHost()->GetRoutingID();
- } else {
- guest_proxy_routing_id_ =
- GetWebContents()->CreateSwappedOutRenderView(owner_site_instance);
- }
+ int proxy_routing_id =
+ GetWebContents()->GetFrameTree()->root()->render_manager()->
+ CreateRenderFrameProxy(owner_site_instance);
+ guest_proxy_routing_id_ = RenderFrameProxyHost::FromID(
+ owner_site_instance->GetProcess()->GetID(), proxy_routing_id)
+ ->GetRenderViewHost()->GetRoutingID();
return guest_proxy_routing_id_;
}
@@ -250,8 +246,6 @@ bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(BrowserPluginGuest, message)
- IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_CompositorFrameSwappedACK,
- OnCompositorFrameSwappedACK)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_Detach, OnDetach)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_DragStatusUpdate,
OnDragStatusUpdate)
@@ -264,8 +258,6 @@ bool BrowserPluginGuest::OnMessageReceivedFromEmbedder(
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ImeSetComposition,
OnImeSetComposition)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_LockMouse_ACK, OnLockMouseAck)
- IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_ReclaimCompositorResources,
- OnReclaimCompositorResources)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetEditCommandsForNextKeyEvent,
OnSetEditCommandsForNextKeyEvent)
IPC_MESSAGE_HANDLER(BrowserPluginHostMsg_SetFocus, OnSetFocus)
@@ -397,24 +389,6 @@ void BrowserPluginGuest::PointerLockPermissionResponse(bool allow) {
new BrowserPluginMsg_SetMouseLock(browser_plugin_instance_id(), allow));
}
-// TODO(wjmaclean): Remove this once any remaining users of this pathway
-// are gone.
-void BrowserPluginGuest::SwapCompositorFrame(
- uint32_t output_surface_id,
- int host_process_id,
- int host_routing_id,
- scoped_ptr<cc::CompositorFrame> frame) {
- last_pending_frame_.reset(new FrameMsg_CompositorFrameSwapped_Params());
- frame->AssignTo(&last_pending_frame_->frame);
- last_pending_frame_->output_surface_id = output_surface_id;
- last_pending_frame_->producing_route_id = host_routing_id;
- last_pending_frame_->producing_host_id = host_process_id;
-
- SendMessageToEmbedder(
- new BrowserPluginMsg_CompositorFrameSwapped(
- browser_plugin_instance_id(), *last_pending_frame_));
-}
-
void BrowserPluginGuest::SetChildFrameSurface(
const cc::SurfaceId& surface_id,
const gfx::Size& frame_size,
@@ -752,21 +726,6 @@ void BrowserPluginGuest::Attach(
WebContentsImpl* embedder_web_contents,
const BrowserPluginHostMsg_Attach_Params& params) {
browser_plugin_instance_id_ = browser_plugin_instance_id;
- // If a guest is detaching from one container and attaching to another
- // container, then late arriving ACKs may be lost if the mapping from
- // |browser_plugin_instance_id| to |guest_instance_id| changes. Thus we
- // ensure that we always get new frames on attachment by ACKing the pending
- // frame if it's still waiting on the ACK.
- if (last_pending_frame_) {
- cc::CompositorFrameAck ack;
- RenderWidgetHostImpl::SendSwapCompositorFrameAck(
- last_pending_frame_->producing_route_id,
- last_pending_frame_->output_surface_id,
- last_pending_frame_->producing_host_id,
- ack);
- last_pending_frame_.reset();
- }
-
// The guest is owned by the embedder. Attach is queued up so we cannot
// change embedders before attach completes. If the embedder goes away,
// so does the guest and so we will never call WillAttachComplete because
@@ -781,16 +740,15 @@ void BrowserPluginGuest::Attach(
void BrowserPluginGuest::OnWillAttachComplete(
WebContentsImpl* embedder_web_contents,
const BrowserPluginHostMsg_Attach_Params& params) {
- bool use_cross_process_frames =
- BrowserPluginGuestMode::UseCrossProcessFramesForGuests();
// If a RenderView has already been created for this new window, then we need
// to initialize the browser-side state now so that the RenderFrameHostManager
// does not create a new RenderView on navigation.
- if (!use_cross_process_frames && has_render_view_) {
+ if (has_render_view_) {
// This will trigger a callback to RenderViewReady after a round-trip IPC.
static_cast<RenderViewHostImpl*>(GetWebContents()->GetRenderViewHost())
->GetWidget()
->Init();
+ GetWebContents()->GetMainFrame()->Init();
WebContentsViewGuest* web_contents_view =
static_cast<WebContentsViewGuest*>(GetWebContents()->GetView());
if (!web_contents()->GetRenderViewHost()->GetWidget()->GetView()) {
@@ -809,23 +767,11 @@ void BrowserPluginGuest::OnWillAttachComplete(
RenderWidgetHostViewGuest* rwhv = static_cast<RenderWidgetHostViewGuest*>(
web_contents()->GetRenderWidgetHostView());
rwhv->RegisterSurfaceNamespaceId();
-
- if (!use_cross_process_frames)
- has_render_view_ = true;
+ has_render_view_ = true;
RecordAction(base::UserMetricsAction("BrowserPlugin.Guest.Attached"));
}
-void BrowserPluginGuest::OnCompositorFrameSwappedACK(
- int browser_plugin_instance_id,
- const FrameHostMsg_CompositorFrameSwappedACK_Params& params) {
- RenderWidgetHostImpl::SendSwapCompositorFrameAck(params.producing_route_id,
- params.output_surface_id,
- params.producing_host_id,
- params.ack);
- last_pending_frame_.reset();
-}
-
void BrowserPluginGuest::OnDetach(int browser_plugin_instance_id) {
if (!attached())
return;
@@ -834,8 +780,9 @@ void BrowserPluginGuest::OnDetach(int browser_plugin_instance_id) {
// it's attached again.
attached_ = false;
- RenderWidgetHostViewGuest* rwhv = static_cast<RenderWidgetHostViewGuest*>(
- web_contents()->GetRenderWidgetHostView());
+ RenderWidgetHostViewChildFrame* rwhv =
+ static_cast<RenderWidgetHostViewChildFrame*>(
+ web_contents()->GetRenderWidgetHostView());
// If the guest is terminated, our host may already be gone.
if (rwhv)
rwhv->UnregisterSurfaceNamespaceId();
@@ -897,6 +844,7 @@ void BrowserPluginGuest::OnImeSetComposition(
int selection_end) {
Send(new InputMsg_ImeSetComposition(routing_id(),
base::UTF8ToUTF16(text), underlines,
+ gfx::Range::InvalidRange(),
selection_start, selection_end));
}
@@ -920,15 +868,6 @@ void BrowserPluginGuest::OnExtendSelectionAndDelete(
rfh->ExtendSelectionAndDelete(before, after);
}
-void BrowserPluginGuest::OnReclaimCompositorResources(
- int browser_plugin_instance_id,
- const FrameHostMsg_ReclaimCompositorResources_Params& params) {
- RenderWidgetHostImpl::SendReclaimCompositorResources(params.route_id,
- params.output_surface_id,
- params.renderer_host_id,
- params.ack);
-}
-
void BrowserPluginGuest::OnLockMouse(bool user_gesture,
bool last_unlocked_by_target,
bool privileged) {
@@ -973,6 +912,10 @@ void BrowserPluginGuest::OnSetEditCommandsForNextKeyEvent(
void BrowserPluginGuest::OnSetVisibility(int browser_plugin_instance_id,
bool visible) {
+ // For OOPIF-<webivew>, the remote frame will handle visibility state.
+ if (BrowserPluginGuestMode::UseCrossProcessFramesForGuests())
+ return;
+
guest_visible_ = visible;
if (embedder_visible_ && guest_visible_)
GetWebContents()->WasShown();
@@ -999,10 +942,7 @@ void BrowserPluginGuest::OnUpdateGeometry(int browser_plugin_instance_id,
// The plugin has moved within the embedder without resizing or the
// embedder/container's view rect changing.
guest_window_rect_ = view_rect;
- RenderWidgetHostImpl* rwh = RenderWidgetHostImpl::From(
- GetWebContents()->GetRenderViewHost()->GetWidget());
- if (rwh)
- rwh->SendScreenRects();
+ GetWebContents()->SendScreenRects();
}
void BrowserPluginGuest::OnHasTouchEventHandlers(bool accept) {
diff --git a/chromium/content/browser/browser_plugin/browser_plugin_guest.h b/chromium/content/browser/browser_plugin/browser_plugin_guest.h
index 9cdc85e96d2..e6676f74d6d 100644
--- a/chromium/content/browser/browser_plugin/browser_plugin_guest.h
+++ b/chromium/content/browser/browser_plugin/browser_plugin_guest.h
@@ -45,9 +45,6 @@
#include "ui/gfx/geometry/rect.h"
struct BrowserPluginHostMsg_Attach_Params;
-struct FrameHostMsg_CompositorFrameSwappedACK_Params;
-struct FrameHostMsg_ReclaimCompositorResources_Params;
-struct FrameMsg_CompositorFrameSwapped_Params;
struct ViewHostMsg_TextInputState_Params;
#if defined(OS_MACOSX)
@@ -241,11 +238,7 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
void PointerLockPermissionResponse(bool allow);
- // The next two functions are virtual for test purposes.
- virtual void SwapCompositorFrame(uint32_t output_surface_id,
- int host_process_id,
- int host_routing_id,
- scoped_ptr<cc::CompositorFrame> frame);
+ // The next function is virtual for test purposes.
virtual void SetChildFrameSurface(const cc::SurfaceId& surface_id,
const gfx::Size& frame_size,
float scale_factor,
@@ -289,9 +282,6 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
const cc::SurfaceId& id,
const cc::SurfaceSequence& sequence);
// Message handlers for messages from embedder.
- void OnCompositorFrameSwappedACK(
- int instance_id,
- const FrameHostMsg_CompositorFrameSwappedACK_Params& params);
void OnDetach(int instance_id);
// Handles drag events from the embedder.
// When dragging, the drag events go to the embedder first, and if the drag
@@ -307,11 +297,6 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
void OnExecuteEditCommand(int instance_id,
const std::string& command);
- // Returns compositor resources reclaimed in the embedder to the guest.
- void OnReclaimCompositorResources(
- int instance_id,
- const FrameHostMsg_ReclaimCompositorResources_Params& params);
-
void OnLockMouse(bool user_gesture,
bool last_unlocked_by_target,
bool privileged);
@@ -456,15 +441,6 @@ class CONTENT_EXPORT BrowserPluginGuest : public GuestHost,
// Indicates the URL dragged into the guest if any.
GURL dragged_url_;
- // Guests generate frames and send a CompositorFrameSwapped (CFS) message
- // indicating the next frame is ready to be positioned and composited.
- // Subsequent frames are not generated until the IPC is ACKed. We would like
- // to ensure that the guest generates frames on attachment so we directly ACK
- // an unACKed CFS. ACKs could get lost between the time a guest is detached
- // from a container and the time it is attached elsewhere. This mitigates this
- // race by ensuring the guest is ACKed on attachment.
- scoped_ptr<FrameMsg_CompositorFrameSwapped_Params> last_pending_frame_;
-
// This is a queue of messages that are destined to be sent to the embedder
// once the guest is attached to a particular embedder.
std::deque<linked_ptr<IPC::Message> > pending_messages_;
diff --git a/chromium/content/browser/browser_process_sub_thread.cc b/chromium/content/browser/browser_process_sub_thread.cc
index b1904e10971..5aadda5ad1e 100644
--- a/chromium/content/browser/browser_process_sub_thread.cc
+++ b/chromium/content/browser/browser_process_sub_thread.cc
@@ -66,12 +66,10 @@ void BrowserProcessSubThread::IOThreadPreCleanUp() {
// Destroy all URLRequests started by URLFetchers.
net::URLFetcher::CancelAll();
-#if !defined(OS_IOS)
// If any child processes are still running, terminate them and
// and delete the BrowserChildProcessHost instances to release whatever
// IO thread only resources they are referencing.
BrowserChildProcessHostImpl::TerminateAll();
-#endif // !defined(OS_IOS)
// Unregister GpuMemoryBuffer dump provider before IO thread is shut down.
base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
diff --git a/chromium/content/browser/browser_process_sub_thread.h b/chromium/content/browser/browser_process_sub_thread.h
index 2276d6dca46..aded0cb883f 100644
--- a/chromium/content/browser/browser_process_sub_thread.h
+++ b/chromium/content/browser/browser_process_sub_thread.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_BROWSER_PROCESS_SUB_THREAD_H_
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "build/build_config.h"
#include "content/browser/browser_thread_impl.h"
#include "content/common/content_export.h"
diff --git a/chromium/content/browser/browser_side_navigation_browsertest.cc b/chromium/content/browser/browser_side_navigation_browsertest.cc
index 3ffef7d88d2..599f3cc5b71 100644
--- a/chromium/content/browser/browser_side_navigation_browsertest.cc
+++ b/chromium/content/browser/browser_side_navigation_browsertest.cc
@@ -6,7 +6,9 @@
#include "base/command_line.h"
#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/site_isolation_policy.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
@@ -156,9 +158,21 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest,
EXPECT_TRUE(observer.last_navigation_succeeded());
}
- // The RenderFrameHost should not have changed.
- EXPECT_EQ(initial_rfh, static_cast<WebContentsImpl*>(shell()->web_contents())
- ->GetFrameTree()->root()->current_frame_host());
+ // The RenderFrameHost should not have changed unless site-per-process is
+ // enabled.
+ if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
+ EXPECT_NE(initial_rfh,
+ static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root()
+ ->current_frame_host());
+ } else {
+ EXPECT_EQ(initial_rfh,
+ static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root()
+ ->current_frame_host());
+ }
}
// Ensure that browser side navigation handles navigation failures.
@@ -188,4 +202,30 @@ IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest, FailedNavigation) {
}
}
+// Ensure that browser side navigation handles POST navigations correctly.
+IN_PROC_BROWSER_TEST_F(BrowserSideNavigationBrowserTest, POSTNavigation) {
+ GURL url(embedded_test_server()->GetURL("/session_history/form.html"));
+ GURL post_url = embedded_test_server()->GetURL("/echotitle");
+
+ // Navigate to a page with a form.
+ TestNavigationObserver observer(shell()->web_contents());
+ NavigateToURL(shell(), url);
+ EXPECT_EQ(url, observer.last_navigation_url());
+ EXPECT_TRUE(observer.last_navigation_succeeded());
+
+ // Submit the form.
+ GURL submit_url("javascript:submitForm('isubmit')");
+ NavigateToURL(shell(), submit_url);
+
+ // Check that a proper POST navigation was done.
+ EXPECT_EQ("text=&select=a",
+ base::UTF16ToASCII(shell()->web_contents()->GetTitle()));
+ EXPECT_EQ(post_url, shell()->web_contents()->GetLastCommittedURL());
+ EXPECT_TRUE(shell()
+ ->web_contents()
+ ->GetController()
+ .GetActiveEntry()
+ ->GetHasPostData());
+}
+
} // namespace content
diff --git a/chromium/content/browser/browser_thread_impl.cc b/chromium/content/browser/browser_thread_impl.cc
index b86643970e5..dd77c8dac04 100644
--- a/chromium/content/browser/browser_thread_impl.cc
+++ b/chromium/content/browser/browser_thread_impl.cc
@@ -13,9 +13,9 @@
#include "base/compiler_specific.h"
#include "base/lazy_instance.h"
#include "base/macros.h"
+#include "base/profiler/scoped_tracker.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/sequenced_worker_pool.h"
-#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#include "content/public/browser/browser_thread_delegate.h"
#include "content/public/browser/content_browser_client.h"
@@ -230,10 +230,11 @@ void BrowserThreadImpl::Run(base::MessageLoop* message_loop) {
#endif
BrowserThread::ID thread_id = ID_COUNT;
- if (!GetCurrentThreadIdentifier(&thread_id))
- return Thread::Run(message_loop);
+ CHECK(GetCurrentThreadIdentifier(&thread_id));
+ CHECK_EQ(identifier_, thread_id);
+ CHECK_EQ(Thread::message_loop(), message_loop);
- switch (thread_id) {
+ switch (identifier_) {
case BrowserThread::UI:
return UIThreadRun(message_loop);
case BrowserThread::DB:
@@ -252,7 +253,10 @@ void BrowserThreadImpl::Run(base::MessageLoop* message_loop) {
CHECK(false); // This shouldn't actually be reached!
break;
}
- Thread::Run(message_loop);
+
+ // |identifier_| must be set to a valid enum value in the constructor, so it
+ // should be impossible to reach here.
+ CHECK(false);
}
void BrowserThreadImpl::CleanUp() {
@@ -267,6 +271,13 @@ void BrowserThreadImpl::CleanUp() {
if (delegate)
delegate->CleanUp();
+
+ // PostTaskHelper() accesses the message loop while holding this lock.
+ // However, the message loop will soon be destructed without any locking. So
+ // to prevent a race with accessing the message loop in PostTaskHelper(),
+ // remove this thread from the global array now.
+ base::AutoLock lock(globals.lock);
+ globals.threads[identifier_] = NULL;
}
void BrowserThreadImpl::Initialize() {
@@ -398,11 +409,6 @@ bool BrowserThread::IsThreadInitialized(ID identifier) {
// static
bool BrowserThread::CurrentlyOn(ID identifier) {
- // We shouldn't use MessageLoop::current() since it uses LazyInstance which
- // may be deleted by ~AtExitManager when a WorkerPool thread calls this
- // function.
- // http://crbug.com/63678
- base::ThreadRestrictions::ScopedAllowSingleton allow_singleton;
BrowserThreadGlobals& globals = g_globals.Get();
base::AutoLock lock(globals.lock);
DCHECK(identifier >= 0 && identifier < ID_COUNT);
@@ -501,13 +507,13 @@ bool BrowserThread::GetCurrentThreadIdentifier(ID* identifier) {
if (g_globals == NULL)
return false;
- // We shouldn't use MessageLoop::current() since it uses LazyInstance which
- // may be deleted by ~AtExitManager when a WorkerPool thread calls this
- // function.
- // http://crbug.com/63678
- base::ThreadRestrictions::ScopedAllowSingleton allow_singleton;
base::MessageLoop* cur_message_loop = base::MessageLoop::current();
BrowserThreadGlobals& globals = g_globals.Get();
+ // Profiler to track potential contention on |globals.lock|. This only does
+ // real work on canary and local dev builds, so the cost of having this here
+ // should be minimal.
+ tracked_objects::ScopedTracker tracking_profile(FROM_HERE);
+ base::AutoLock lock(globals.lock);
for (int i = 0; i < ID_COUNT; ++i) {
if (globals.threads[i] &&
globals.threads[i]->message_loop() == cur_message_loop) {
diff --git a/chromium/content/browser/browsing_instance.cc b/chromium/content/browser/browsing_instance.cc
index 1d5f8953769..5dd0ca4191f 100644
--- a/chromium/content/browser/browsing_instance.cc
+++ b/chromium/content/browser/browsing_instance.cc
@@ -7,6 +7,7 @@
#include "base/command_line.h"
#include "base/logging.h"
#include "content/browser/site_instance_impl.h"
+#include "content/common/site_isolation_policy.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_switches.h"
@@ -27,29 +28,49 @@ bool BrowsingInstance::HasSiteInstance(const GURL& url) {
return site_instance_map_.find(site) != site_instance_map_.end();
}
-SiteInstance* BrowsingInstance::GetSiteInstanceForURL(const GURL& url) {
- std::string site =
- SiteInstanceImpl::GetSiteForURL(browser_context_, url)
- .possibly_invalid_spec();
+scoped_refptr<SiteInstanceImpl> BrowsingInstance::GetSiteInstanceForURL(
+ const GURL& url) {
+ std::string site = SiteInstanceImpl::GetSiteForURL(browser_context_, url)
+ .possibly_invalid_spec();
SiteInstanceMap::iterator i = site_instance_map_.find(site);
if (i != site_instance_map_.end())
return i->second;
-
// No current SiteInstance for this site, so let's create one.
- SiteInstanceImpl* instance = new SiteInstanceImpl(this);
+ scoped_refptr<SiteInstanceImpl> instance = new SiteInstanceImpl(this);
// Set the site of this new SiteInstance, which will register it with us.
instance->SetSite(url);
return instance;
}
-void BrowsingInstance::RegisterSiteInstance(SiteInstance* site_instance) {
- DCHECK(static_cast<SiteInstanceImpl*>(site_instance)
- ->browsing_instance_.get() ==
- this);
- DCHECK(static_cast<SiteInstanceImpl*>(site_instance)->HasSite());
+scoped_refptr<SiteInstanceImpl>
+BrowsingInstance::GetDefaultSubframeSiteInstance() {
+ // This should only be used for --top-document-isolation mode.
+ CHECK(SiteIsolationPolicy::IsTopDocumentIsolationEnabled());
+ if (!default_subframe_site_instance_) {
+ SiteInstanceImpl* instance = new SiteInstanceImpl(this);
+ instance->set_is_default_subframe_site_instance();
+
+ // TODO(nick): This is a hack for now.
+ instance->SetSite(GURL("http://web-subframes.invalid"));
+
+ default_subframe_site_instance_ = instance;
+ }
+
+ return make_scoped_refptr(default_subframe_site_instance_);
+}
+
+void BrowsingInstance::RegisterSiteInstance(SiteInstanceImpl* site_instance) {
+ DCHECK(site_instance->browsing_instance_.get() == this);
+ DCHECK(site_instance->HasSite());
+
+ // Don't register the default subframe SiteInstance, to prevent it from being
+ // returned by GetSiteInstanceForURL.
+ if (default_subframe_site_instance_ == site_instance)
+ return;
+
std::string site = site_instance->GetSiteURL().possibly_invalid_spec();
// Only register if we don't have a SiteInstance for this site already.
@@ -64,11 +85,9 @@ void BrowsingInstance::RegisterSiteInstance(SiteInstance* site_instance) {
}
}
-void BrowsingInstance::UnregisterSiteInstance(SiteInstance* site_instance) {
- DCHECK(static_cast<SiteInstanceImpl*>(site_instance)
- ->browsing_instance_.get() ==
- this);
- DCHECK(static_cast<SiteInstanceImpl*>(site_instance)->HasSite());
+void BrowsingInstance::UnregisterSiteInstance(SiteInstanceImpl* site_instance) {
+ DCHECK(site_instance->browsing_instance_.get() == this);
+ DCHECK(site_instance->HasSite());
std::string site = site_instance->GetSiteURL().possibly_invalid_spec();
// Only unregister the SiteInstance if it is the same one that is registered
@@ -79,6 +98,8 @@ void BrowsingInstance::UnregisterSiteInstance(SiteInstance* site_instance) {
// Matches, so erase it.
site_instance_map_.erase(i);
}
+ if (default_subframe_site_instance_ == site_instance)
+ default_subframe_site_instance_ = nullptr;
}
BrowsingInstance::~BrowsingInstance() {
diff --git a/chromium/content/browser/browsing_instance.h b/chromium/content/browser/browsing_instance.h
index 0cb80ac80a9..34c1f073bbd 100644
--- a/chromium/content/browser/browsing_instance.h
+++ b/chromium/content/browser/browsing_instance.h
@@ -8,6 +8,7 @@
#include <stddef.h>
#include "base/containers/hash_tables.h"
+#include "base/gtest_prod_util.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/macros.h"
@@ -18,7 +19,6 @@
class GURL;
namespace content {
-class SiteInstance;
class SiteInstanceImpl;
///////////////////////////////////////////////////////////////////////////////
@@ -55,12 +55,20 @@ class SiteInstanceImpl;
// site_instance_unittest.cc.
//
///////////////////////////////////////////////////////////////////////////////
-class CONTENT_EXPORT BrowsingInstance
+class CONTENT_EXPORT BrowsingInstance final
: public base::RefCounted<BrowsingInstance> {
- protected:
+ private:
+ friend class base::RefCounted<BrowsingInstance>;
+ friend class SiteInstanceImpl;
+ FRIEND_TEST_ALL_PREFIXES(SiteInstanceTest, OneSiteInstancePerSite);
+ FRIEND_TEST_ALL_PREFIXES(SiteInstanceTest,
+ OneSiteInstancePerSiteInBrowserContext);
+
// Create a new BrowsingInstance.
explicit BrowsingInstance(BrowserContext* context);
+ ~BrowsingInstance();
+
// Get the browser context to which this BrowsingInstance belongs.
BrowserContext* browser_context() const { return browser_context_; }
@@ -71,17 +79,23 @@ class CONTENT_EXPORT BrowsingInstance
// Get the SiteInstance responsible for rendering the given URL. Should
// create a new one if necessary, but should not create more than one
// SiteInstance per site.
- SiteInstance* GetSiteInstanceForURL(const GURL& url);
+ scoped_refptr<SiteInstanceImpl> GetSiteInstanceForURL(const GURL& url);
+
+ // Returns a SiteInstance that should be used for subframes when an oopif is
+ // required, but a dedicated process is not. This SiteInstance will be created
+ // if it doesn't already exist. There is at most one of these per
+ // BrowsingInstance.
+ scoped_refptr<SiteInstanceImpl> GetDefaultSubframeSiteInstance();
// Adds the given SiteInstance to our map, to ensure that we do not create
// another SiteInstance for the same site.
- void RegisterSiteInstance(SiteInstance* site_instance);
+ void RegisterSiteInstance(SiteInstanceImpl* site_instance);
// Removes the given SiteInstance from our map, after all references to it
// have been deleted. This means it is safe to create a new SiteInstance
// if the user later visits a page from this site, within this
// BrowsingInstance.
- void UnregisterSiteInstance(SiteInstance* site_instance);
+ void UnregisterSiteInstance(SiteInstanceImpl* site_instance);
// Tracks the number of WebContents currently in this BrowsingInstance.
size_t active_contents_count() const { return active_contents_count_; }
@@ -91,18 +105,9 @@ class CONTENT_EXPORT BrowsingInstance
active_contents_count_--;
}
- friend class SiteInstanceImpl;
- friend class SiteInstance;
-
- friend class base::RefCounted<BrowsingInstance>;
-
- // Virtual to allow tests to extend it.
- virtual ~BrowsingInstance();
-
- private:
// Map of site to SiteInstance, to ensure we only have one SiteInstance per
// site.
- typedef base::hash_map<std::string, SiteInstance*> SiteInstanceMap;
+ typedef base::hash_map<std::string, SiteInstanceImpl*> SiteInstanceMap;
// Common browser context to which all SiteInstances in this BrowsingInstance
// must belong.
@@ -120,6 +125,8 @@ class CONTENT_EXPORT BrowsingInstance
// Number of WebContentses currently using this BrowsingInstance.
size_t active_contents_count_;
+ SiteInstanceImpl* default_subframe_site_instance_ = nullptr;
+
DISALLOW_COPY_AND_ASSIGN(BrowsingInstance);
};
diff --git a/chromium/content/browser/cache_storage/cache_storage.cc b/chromium/content/browser/cache_storage/cache_storage.cc
index 362af37e58c..c5a7b1eff63 100644
--- a/chromium/content/browser/cache_storage/cache_storage.cc
+++ b/chromium/content/browser/cache_storage/cache_storage.cc
@@ -46,28 +46,45 @@ std::string HexedHash(const std::string& value) {
return valued_hexed_hash;
}
-void CloseAllCachesDidCloseCache(const scoped_refptr<CacheStorageCache>& cache,
- const base::Closure& barrier_closure) {
- barrier_closure.Run();
+void SizeRetrievedFromCache(const scoped_refptr<CacheStorageCache>& cache,
+ const base::Closure& closure,
+ int64_t* accumulator,
+ int64_t size) {
+ *accumulator += size;
+ closure.Run();
+}
+
+void SizeRetrievedFromAllCaches(scoped_ptr<int64_t> accumulator,
+ const CacheStorage::SizeCallback& callback) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(callback, *accumulator));
}
} // namespace
const char CacheStorage::kIndexFileName[] = "index.txt";
+struct CacheStorage::CacheMatchResponse {
+ CacheMatchResponse() = default;
+ ~CacheMatchResponse() = default;
+
+ CacheStorageError error;
+ scoped_ptr<ServiceWorkerResponse> service_worker_response;
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle;
+};
+
// Handles the loading and clean up of CacheStorageCache objects.
class CacheStorage::CacheLoader {
public:
- typedef base::Callback<void(const scoped_refptr<CacheStorageCache>&)>
- CacheCallback;
+ typedef base::Callback<void(scoped_refptr<CacheStorageCache>)> CacheCallback;
typedef base::Callback<void(bool)> BoolCallback;
typedef base::Callback<void(scoped_ptr<std::vector<std::string>>)>
StringVectorCallback;
CacheLoader(
base::SequencedTaskRunner* cache_task_runner,
- const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
- const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter,
+ storage::QuotaManagerProxy* quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
const GURL& origin)
: cache_task_runner_(cache_task_runner),
@@ -105,7 +122,10 @@ class CacheStorage::CacheLoader {
protected:
scoped_refptr<base::SequencedTaskRunner> cache_task_runner_;
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
- scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
+
+ // Owned by CacheStorage which owns this.
+ storage::QuotaManagerProxy* quota_manager_proxy_;
+
base::WeakPtr<storage::BlobStorageContext> blob_context_;
GURL origin_;
};
@@ -116,12 +136,11 @@ class CacheStorage::CacheLoader {
// cache is deleted.
class CacheStorage::MemoryLoader : public CacheStorage::CacheLoader {
public:
- MemoryLoader(
- base::SequencedTaskRunner* cache_task_runner,
- const scoped_refptr<net::URLRequestContextGetter>& request_context,
- const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
- base::WeakPtr<storage::BlobStorageContext> blob_context,
- const GURL& origin)
+ MemoryLoader(base::SequencedTaskRunner* cache_task_runner,
+ scoped_refptr<net::URLRequestContextGetter> request_context,
+ storage::QuotaManagerProxy* quota_manager_proxy,
+ base::WeakPtr<storage::BlobStorageContext> blob_context,
+ const GURL& origin)
: CacheLoader(cache_task_runner,
request_context,
quota_manager_proxy,
@@ -131,14 +150,15 @@ class CacheStorage::MemoryLoader : public CacheStorage::CacheLoader {
scoped_refptr<CacheStorageCache> CreateCache(
const std::string& cache_name) override {
return CacheStorageCache::CreateMemoryCache(
- origin_, request_context_getter_, quota_manager_proxy_, blob_context_);
+ origin_, cache_name, request_context_getter_, quota_manager_proxy_,
+ blob_context_);
}
void PrepareNewCacheDestination(const std::string& cache_name,
const CacheCallback& callback) override {
scoped_refptr<CacheStorageCache> cache = CreateCache(cache_name);
cache_refs_.insert(std::make_pair(cache_name, cache));
- callback.Run(cache);
+ callback.Run(std::move(cache));
}
void CleanUpDeletedCache(const std::string& cache_name,
@@ -171,13 +191,12 @@ class CacheStorage::MemoryLoader : public CacheStorage::CacheLoader {
class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader {
public:
- SimpleCacheLoader(
- const base::FilePath& origin_path,
- base::SequencedTaskRunner* cache_task_runner,
- const scoped_refptr<net::URLRequestContextGetter>& request_context,
- const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
- base::WeakPtr<storage::BlobStorageContext> blob_context,
- const GURL& origin)
+ SimpleCacheLoader(const base::FilePath& origin_path,
+ base::SequencedTaskRunner* cache_task_runner,
+ scoped_refptr<net::URLRequestContextGetter> request_context,
+ storage::QuotaManagerProxy* quota_manager_proxy,
+ base::WeakPtr<storage::BlobStorageContext> blob_context,
+ const GURL& origin)
: CacheLoader(cache_task_runner,
request_context,
quota_manager_proxy,
@@ -194,8 +213,8 @@ class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader {
std::string cache_dir = cache_name_to_cache_dir_[cache_name];
base::FilePath cache_path = origin_path_.AppendASCII(cache_dir);
return CacheStorageCache::CreatePersistentCache(
- origin_, cache_path, request_context_getter_, quota_manager_proxy_,
- blob_context_);
+ origin_, cache_name, cache_path, request_context_getter_,
+ quota_manager_proxy_, blob_context_);
}
void PrepareNewCacheDestination(const std::string& cache_name,
@@ -253,7 +272,7 @@ class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader {
static void CleanUpDeleteCacheDirInPool(
const base::FilePath& cache_path,
const BoolCallback& callback,
- const scoped_refptr<base::SingleThreadTaskRunner>& original_task_runner) {
+ scoped_refptr<base::SingleThreadTaskRunner> original_task_runner) {
bool rv = base::DeleteFile(cache_path, true);
original_task_runner->PostTask(FROM_HERE, base::Bind(callback, rv));
}
@@ -284,27 +303,24 @@ class CacheStorage::SimpleCacheLoader : public CacheStorage::CacheLoader {
base::FilePath index_path =
origin_path_.AppendASCII(CacheStorage::kIndexFileName);
- cache_task_runner_->PostTask(
- FROM_HERE, base::Bind(&SimpleCacheLoader::WriteIndexWriteToFileInPool,
- tmp_path, index_path, serialized, callback,
- base::ThreadTaskRunnerHandle::Get()));
+ PostTaskAndReplyWithResult(
+ cache_task_runner_.get(), FROM_HERE,
+ base::Bind(&SimpleCacheLoader::WriteIndexWriteToFileInPool, tmp_path,
+ index_path, serialized),
+ callback);
}
- static void WriteIndexWriteToFileInPool(
- const base::FilePath& tmp_path,
- const base::FilePath& index_path,
- const std::string& data,
- const BoolCallback& callback,
- const scoped_refptr<base::SingleThreadTaskRunner>& original_task_runner) {
+ static bool WriteIndexWriteToFileInPool(const base::FilePath& tmp_path,
+ const base::FilePath& index_path,
+ const std::string& data) {
int bytes_written = base::WriteFile(tmp_path, data.c_str(), data.size());
if (bytes_written != base::checked_cast<int>(data.size())) {
base::DeleteFile(tmp_path, /* recursive */ false);
- original_task_runner->PostTask(FROM_HERE, base::Bind(callback, false));
+ return false;
}
// Atomically rename the temporary index file to become the real one.
- bool rv = base::ReplaceFile(tmp_path, index_path, NULL);
- original_task_runner->PostTask(FROM_HERE, base::Bind(callback, rv));
+ return base::ReplaceFile(tmp_path, index_path, NULL);
}
void LoadIndex(scoped_ptr<std::vector<std::string>> names,
@@ -442,8 +458,8 @@ CacheStorage::CacheStorage(
const base::FilePath& path,
bool memory_only,
base::SequencedTaskRunner* cache_task_runner,
- const scoped_refptr<net::URLRequestContextGetter>& request_context,
- const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
+ scoped_refptr<net::URLRequestContextGetter> request_context,
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
const GURL& origin)
: initialized_(false),
@@ -452,15 +468,17 @@ CacheStorage::CacheStorage(
origin_path_(path),
cache_task_runner_(cache_task_runner),
memory_only_(memory_only),
+ quota_manager_proxy_(quota_manager_proxy),
+ origin_(origin),
weak_factory_(this) {
if (memory_only)
- cache_loader_.reset(new MemoryLoader(cache_task_runner_.get(),
- request_context, quota_manager_proxy,
- blob_context, origin));
+ cache_loader_.reset(
+ new MemoryLoader(cache_task_runner_.get(), std::move(request_context),
+ quota_manager_proxy.get(), blob_context, origin));
else
cache_loader_.reset(new SimpleCacheLoader(
- origin_path_, cache_task_runner_.get(), request_context,
- quota_manager_proxy, blob_context, origin));
+ origin_path_, cache_task_runner_.get(), std::move(request_context),
+ quota_manager_proxy.get(), blob_context, origin));
}
CacheStorage::~CacheStorage() {
@@ -473,6 +491,10 @@ void CacheStorage::OpenCache(const std::string& cache_name,
if (!initialized_)
LazyInit();
+ quota_manager_proxy_->NotifyStorageAccessed(
+ storage::QuotaClient::kServiceWorkerCache, origin_,
+ storage::kStorageTypeTemporary);
+
CacheAndErrorCallback pending_callback =
base::Bind(&CacheStorage::PendingCacheAndErrorCallback,
weak_factory_.GetWeakPtr(), callback);
@@ -488,6 +510,10 @@ void CacheStorage::HasCache(const std::string& cache_name,
if (!initialized_)
LazyInit();
+ quota_manager_proxy_->NotifyStorageAccessed(
+ storage::QuotaClient::kServiceWorkerCache, origin_,
+ storage::kStorageTypeTemporary);
+
BoolAndErrorCallback pending_callback =
base::Bind(&CacheStorage::PendingBoolAndErrorCallback,
weak_factory_.GetWeakPtr(), callback);
@@ -503,6 +529,10 @@ void CacheStorage::DeleteCache(const std::string& cache_name,
if (!initialized_)
LazyInit();
+ quota_manager_proxy_->NotifyStorageAccessed(
+ storage::QuotaClient::kServiceWorkerCache, origin_,
+ storage::kStorageTypeTemporary);
+
BoolAndErrorCallback pending_callback =
base::Bind(&CacheStorage::PendingBoolAndErrorCallback,
weak_factory_.GetWeakPtr(), callback);
@@ -517,6 +547,10 @@ void CacheStorage::EnumerateCaches(const StringsAndErrorCallback& callback) {
if (!initialized_)
LazyInit();
+ quota_manager_proxy_->NotifyStorageAccessed(
+ storage::QuotaClient::kServiceWorkerCache, origin_,
+ storage::kStorageTypeTemporary);
+
StringsAndErrorCallback pending_callback =
base::Bind(&CacheStorage::PendingStringsAndErrorCallback,
weak_factory_.GetWeakPtr(), callback);
@@ -534,6 +568,10 @@ void CacheStorage::MatchCache(
if (!initialized_)
LazyInit();
+ quota_manager_proxy_->NotifyStorageAccessed(
+ storage::QuotaClient::kServiceWorkerCache, origin_,
+ storage::kStorageTypeTemporary);
+
CacheStorageCache::ResponseCallback pending_callback =
base::Bind(&CacheStorage::PendingResponseCallback,
weak_factory_.GetWeakPtr(), callback);
@@ -550,6 +588,10 @@ void CacheStorage::MatchAllCaches(
if (!initialized_)
LazyInit();
+ quota_manager_proxy_->NotifyStorageAccessed(
+ storage::QuotaClient::kServiceWorkerCache, origin_,
+ storage::kStorageTypeTemporary);
+
CacheStorageCache::ResponseCallback pending_callback =
base::Bind(&CacheStorage::PendingResponseCallback,
weak_factory_.GetWeakPtr(), callback);
@@ -558,33 +600,31 @@ void CacheStorage::MatchAllCaches(
base::Passed(std::move(request)), pending_callback));
}
-void CacheStorage::CloseAllCaches(const base::Closure& callback) {
+void CacheStorage::GetSizeThenCloseAllCaches(const SizeCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!initialized_) {
- callback.Run();
- return;
- }
+ if (!initialized_)
+ LazyInit();
- base::Closure pending_callback = base::Bind(
- &CacheStorage::PendingClosure, weak_factory_.GetWeakPtr(), callback);
- scheduler_->ScheduleOperation(base::Bind(&CacheStorage::CloseAllCachesImpl,
- weak_factory_.GetWeakPtr(),
- pending_callback));
+ CacheStorageCache::SizeCallback pending_callback = base::Bind(
+ &CacheStorage::PendingSizeCallback, weak_factory_.GetWeakPtr(), callback);
+
+ scheduler_->ScheduleOperation(
+ base::Bind(&CacheStorage::GetSizeThenCloseAllCachesImpl,
+ weak_factory_.GetWeakPtr(), pending_callback));
}
-int64_t CacheStorage::MemoryBackedSize() const {
+void CacheStorage::Size(const CacheStorage::SizeCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!initialized_ || !memory_only_)
- return 0;
+ if (!initialized_)
+ LazyInit();
+
+ CacheStorageCache::SizeCallback pending_callback = base::Bind(
+ &CacheStorage::PendingSizeCallback, weak_factory_.GetWeakPtr(), callback);
- int64_t sum = 0;
- for (auto& key_value : cache_map_) {
- if (key_value.second)
- sum += key_value.second->MemoryBackedSize();
- }
- return sum;
+ scheduler_->ScheduleOperation(base::Bind(
+ &CacheStorage::SizeImpl, weak_factory_.GetWeakPtr(), pending_callback));
}
void CacheStorage::StartAsyncOperationForTesting() {
@@ -648,7 +688,7 @@ void CacheStorage::OpenCacheImpl(const std::string& cache_name,
const CacheAndErrorCallback& callback) {
scoped_refptr<CacheStorageCache> cache = GetLoadedCache(cache_name);
if (cache.get()) {
- callback.Run(cache, CACHE_STORAGE_OK);
+ callback.Run(std::move(cache), CACHE_STORAGE_OK);
return;
}
@@ -660,7 +700,7 @@ void CacheStorage::OpenCacheImpl(const std::string& cache_name,
void CacheStorage::CreateCacheDidCreateCache(
const std::string& cache_name,
const CacheAndErrorCallback& callback,
- const scoped_refptr<CacheStorageCache>& cache) {
+ scoped_refptr<CacheStorageCache> cache) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
UMA_HISTOGRAM_BOOLEAN("ServiceWorkerCache.CreateCacheStorageResult",
@@ -680,19 +720,19 @@ void CacheStorage::CreateCacheDidCreateCache(
cache_loader_->WriteIndex(
ordered_cache_names_,
base::Bind(&CacheStorage::CreateCacheDidWriteIndex,
- weak_factory_.GetWeakPtr(), callback, cache));
+ weak_factory_.GetWeakPtr(), callback, std::move(cache)));
}
void CacheStorage::CreateCacheDidWriteIndex(
const CacheAndErrorCallback& callback,
- const scoped_refptr<CacheStorageCache>& cache,
+ scoped_refptr<CacheStorageCache> cache,
bool success) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(cache.get());
// TODO(jkarlin): Handle !success.
- callback.Run(cache, CACHE_STORAGE_OK);
+ callback.Run(std::move(cache), CACHE_STORAGE_OK);
}
void CacheStorage::HasCacheImpl(const std::string& cache_name,
@@ -703,14 +743,15 @@ void CacheStorage::HasCacheImpl(const std::string& cache_name,
void CacheStorage::DeleteCacheImpl(const std::string& cache_name,
const BoolAndErrorCallback& callback) {
- CacheMap::iterator it = cache_map_.find(cache_name);
- if (it == cache_map_.end()) {
- callback.Run(false, CACHE_STORAGE_ERROR_NOT_FOUND);
+ scoped_refptr<CacheStorageCache> cache = GetLoadedCache(cache_name);
+ if (!cache.get()) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(callback, false, CACHE_STORAGE_ERROR_NOT_FOUND));
return;
}
- base::WeakPtr<CacheStorageCache> cache = it->second;
- cache_map_.erase(it);
+ CacheMap::iterator map_iter = cache_map_.find(cache_name);
+ cache_map_.erase(map_iter);
// Delete the name from ordered_cache_names_.
StringVector::iterator iter = std::find(
@@ -718,36 +759,33 @@ void CacheStorage::DeleteCacheImpl(const std::string& cache_name,
DCHECK(iter != ordered_cache_names_.end());
ordered_cache_names_.erase(iter);
- base::Closure closure =
- base::Bind(&CacheStorage::DeleteCacheDidClose, weak_factory_.GetWeakPtr(),
- cache_name, callback, ordered_cache_names_,
- make_scoped_refptr(cache.get()));
-
- if (cache) {
- cache->Close(closure);
- return;
- }
-
- closure.Run();
+ cache->GetSizeThenClose(base::Bind(&CacheStorage::DeleteCacheDidClose,
+ weak_factory_.GetWeakPtr(), cache_name,
+ callback, ordered_cache_names_, cache));
}
-void CacheStorage::DeleteCacheDidClose(
- const std::string& cache_name,
- const BoolAndErrorCallback& callback,
- const StringVector& ordered_cache_names,
- const scoped_refptr<CacheStorageCache>& cache /* might be null */) {
+void CacheStorage::DeleteCacheDidClose(const std::string& cache_name,
+ const BoolAndErrorCallback& callback,
+ const StringVector& ordered_cache_names,
+ scoped_refptr<CacheStorageCache> cache,
+ int64_t cache_size) {
cache_loader_->WriteIndex(
ordered_cache_names,
base::Bind(&CacheStorage::DeleteCacheDidWriteIndex,
- weak_factory_.GetWeakPtr(), cache_name, callback));
+ weak_factory_.GetWeakPtr(), cache_name, callback, cache_size));
}
void CacheStorage::DeleteCacheDidWriteIndex(
const std::string& cache_name,
const BoolAndErrorCallback& callback,
+ int cache_size,
bool success) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ quota_manager_proxy_->NotifyStorageModified(
+ storage::QuotaClient::kServiceWorkerCache, origin_,
+ storage::kStorageTypeTemporary, -1 * cache_size);
+
cache_loader_->CleanUpDeletedCache(
cache_name, base::Bind(&CacheStorage::DeleteCacheDidCleanUp,
weak_factory_.GetWeakPtr(), callback));
@@ -772,7 +810,7 @@ void CacheStorage::MatchCacheImpl(
scoped_refptr<CacheStorageCache> cache = GetLoadedCache(cache_name);
if (!cache.get()) {
- callback.Run(CACHE_STORAGE_ERROR_NOT_FOUND,
+ callback.Run(CACHE_STORAGE_ERROR_CACHE_NAME_NOT_FOUND,
scoped_ptr<ServiceWorkerResponse>(),
scoped_ptr<storage::BlobDataHandle>());
return;
@@ -786,7 +824,7 @@ void CacheStorage::MatchCacheImpl(
}
void CacheStorage::MatchCacheDidMatch(
- const scoped_refptr<CacheStorageCache>& cache,
+ scoped_refptr<CacheStorageCache> cache,
const CacheStorageCache::ResponseCallback& callback,
CacheStorageError error,
scoped_ptr<ServiceWorkerResponse> response,
@@ -797,51 +835,55 @@ void CacheStorage::MatchCacheDidMatch(
void CacheStorage::MatchAllCachesImpl(
scoped_ptr<ServiceWorkerFetchRequest> request,
const CacheStorageCache::ResponseCallback& callback) {
- scoped_ptr<CacheStorageCache::ResponseCallback> callback_copy(
- new CacheStorageCache::ResponseCallback(callback));
-
- CacheStorageCache::ResponseCallback* callback_ptr = callback_copy.get();
- base::Closure barrier_closure =
- base::BarrierClosure(ordered_cache_names_.size(),
- base::Bind(&CacheStorage::MatchAllCachesDidMatchAll,
- weak_factory_.GetWeakPtr(),
- base::Passed(std::move(callback_copy))));
-
- for (const std::string& cache_name : ordered_cache_names_) {
- scoped_refptr<CacheStorageCache> cache = GetLoadedCache(cache_name);
+ std::vector<CacheMatchResponse>* match_responses =
+ new std::vector<CacheMatchResponse>(ordered_cache_names_.size());
+
+ base::Closure barrier_closure = base::BarrierClosure(
+ ordered_cache_names_.size(),
+ base::Bind(&CacheStorage::MatchAllCachesDidMatchAll,
+ weak_factory_.GetWeakPtr(),
+ base::Passed(make_scoped_ptr(match_responses)), callback));
+
+ for (size_t i = 0, max = ordered_cache_names_.size(); i < max; ++i) {
+ scoped_refptr<CacheStorageCache> cache =
+ GetLoadedCache(ordered_cache_names_[i]);
DCHECK(cache.get());
cache->Match(make_scoped_ptr(new ServiceWorkerFetchRequest(*request)),
base::Bind(&CacheStorage::MatchAllCachesDidMatch,
- weak_factory_.GetWeakPtr(), cache, barrier_closure,
- callback_ptr));
+ weak_factory_.GetWeakPtr(), cache,
+ &match_responses->at(i), barrier_closure));
}
}
void CacheStorage::MatchAllCachesDidMatch(
scoped_refptr<CacheStorageCache> cache,
+ CacheMatchResponse* out_match_response,
const base::Closure& barrier_closure,
- CacheStorageCache::ResponseCallback* callback,
CacheStorageError error,
- scoped_ptr<ServiceWorkerResponse> response,
+ scoped_ptr<ServiceWorkerResponse> service_worker_response,
scoped_ptr<storage::BlobDataHandle> handle) {
- if (callback->is_null() || error == CACHE_STORAGE_ERROR_NOT_FOUND) {
- barrier_closure.Run();
- return;
- }
- callback->Run(error, std::move(response), std::move(handle));
- callback->Reset(); // Only call the callback once.
-
+ out_match_response->error = error;
+ out_match_response->service_worker_response =
+ std::move(service_worker_response);
+ out_match_response->blob_data_handle = std::move(handle);
barrier_closure.Run();
}
void CacheStorage::MatchAllCachesDidMatchAll(
- scoped_ptr<CacheStorageCache::ResponseCallback> callback) {
- if (!callback->is_null()) {
- callback->Run(CACHE_STORAGE_ERROR_NOT_FOUND,
- scoped_ptr<ServiceWorkerResponse>(),
- scoped_ptr<storage::BlobDataHandle>());
+ scoped_ptr<std::vector<CacheMatchResponse>> match_responses,
+ const CacheStorageCache::ResponseCallback& callback) {
+ for (CacheMatchResponse& match_response : *match_responses) {
+ if (match_response.error == CACHE_STORAGE_ERROR_NOT_FOUND)
+ continue;
+ callback.Run(match_response.error,
+ std::move(match_response.service_worker_response),
+ std::move(match_response.blob_data_handle));
+ return;
}
+ callback.Run(CACHE_STORAGE_ERROR_NOT_FOUND,
+ scoped_ptr<ServiceWorkerResponse>(),
+ scoped_ptr<storage::BlobDataHandle>());
}
scoped_refptr<CacheStorageCache> CacheStorage::GetLoadedCache(
@@ -868,7 +910,7 @@ scoped_refptr<CacheStorageCache> CacheStorage::GetLoadedCache(
}
void CacheStorage::TemporarilyPreserveCache(
- const scoped_refptr<CacheStorageCache>& cache) {
+ scoped_refptr<CacheStorageCache> cache) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!ContainsKey(preserved_caches_, cache.get()));
@@ -894,32 +936,42 @@ void CacheStorage::RemovePreservedCache(const CacheStorageCache* cache) {
preserved_caches_.erase(cache);
}
-void CacheStorage::CloseAllCachesImpl(const base::Closure& callback) {
- int live_cache_count = 0;
- for (const auto& key_value : cache_map_) {
- if (key_value.second)
- live_cache_count += 1;
- }
+void CacheStorage::GetSizeThenCloseAllCachesImpl(const SizeCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(initialized_);
- if (live_cache_count == 0) {
- callback.Run();
- return;
- }
+ scoped_ptr<int64_t> accumulator(new int64_t(0));
+ int64_t* accumulator_ptr = accumulator.get();
- // The closure might modify this object so delay calling it until after
- // iterating through cache_map_ by adding one to the barrier.
- base::Closure barrier_closure =
- base::BarrierClosure(live_cache_count + 1, base::Bind(callback));
+ base::Closure barrier_closure = base::BarrierClosure(
+ ordered_cache_names_.size(),
+ base::Bind(&SizeRetrievedFromAllCaches,
+ base::Passed(std::move(accumulator)), callback));
- for (auto& key_value : cache_map_) {
- if (key_value.second) {
- key_value.second->Close(base::Bind(
- CloseAllCachesDidCloseCache,
- make_scoped_refptr(key_value.second.get()), barrier_closure));
- }
+ for (const std::string& cache_name : ordered_cache_names_) {
+ scoped_refptr<CacheStorageCache> cache = GetLoadedCache(cache_name);
+ cache->GetSizeThenClose(base::Bind(&SizeRetrievedFromCache, cache,
+ barrier_closure, accumulator_ptr));
}
+}
- barrier_closure.Run();
+void CacheStorage::SizeImpl(const SizeCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(initialized_);
+
+ scoped_ptr<int64_t> accumulator(new int64_t(0));
+ int64_t* accumulator_ptr = accumulator.get();
+
+ base::Closure barrier_closure = base::BarrierClosure(
+ ordered_cache_names_.size(),
+ base::Bind(&SizeRetrievedFromAllCaches,
+ base::Passed(std::move(accumulator)), callback));
+
+ for (const std::string& cache_name : ordered_cache_names_) {
+ scoped_refptr<CacheStorageCache> cache = GetLoadedCache(cache_name);
+ cache->Size(base::Bind(&SizeRetrievedFromCache, cache, barrier_closure,
+ accumulator_ptr));
+ }
}
void CacheStorage::PendingClosure(const base::Closure& callback) {
@@ -943,11 +995,11 @@ void CacheStorage::PendingBoolAndErrorCallback(
void CacheStorage::PendingCacheAndErrorCallback(
const CacheAndErrorCallback& callback,
- const scoped_refptr<CacheStorageCache>& cache,
+ scoped_refptr<CacheStorageCache> cache,
CacheStorageError error) {
base::WeakPtr<CacheStorage> cache_storage = weak_factory_.GetWeakPtr();
- callback.Run(cache, error);
+ callback.Run(std::move(cache), error);
if (cache_storage)
scheduler_->CompleteOperationAndRunNext();
}
@@ -975,4 +1027,13 @@ void CacheStorage::PendingResponseCallback(
scheduler_->CompleteOperationAndRunNext();
}
+void CacheStorage::PendingSizeCallback(const SizeCallback& callback,
+ int64_t size) {
+ base::WeakPtr<CacheStorage> cache_storage = weak_factory_.GetWeakPtr();
+
+ callback.Run(size);
+ if (cache_storage)
+ scheduler_->CompleteOperationAndRunNext();
+}
+
} // namespace content
diff --git a/chromium/content/browser/cache_storage/cache_storage.h b/chromium/content/browser/cache_storage/cache_storage.h
index b1bf67e75d6..e81dd2f1441 100644
--- a/chromium/content/browser/cache_storage/cache_storage.h
+++ b/chromium/content/browser/cache_storage/cache_storage.h
@@ -41,10 +41,12 @@ class CONTENT_EXPORT CacheStorage {
public:
typedef std::vector<std::string> StringVector;
typedef base::Callback<void(bool, CacheStorageError)> BoolAndErrorCallback;
- typedef base::Callback<void(const scoped_refptr<CacheStorageCache>&,
- CacheStorageError)> CacheAndErrorCallback;
+ typedef base::Callback<void(scoped_refptr<CacheStorageCache>,
+ CacheStorageError)>
+ CacheAndErrorCallback;
typedef base::Callback<void(const StringVector&, CacheStorageError)>
StringsAndErrorCallback;
+ using SizeCallback = base::Callback<void(int64_t)>;
static const char kIndexFileName[];
@@ -52,8 +54,8 @@ class CONTENT_EXPORT CacheStorage {
const base::FilePath& origin_path,
bool memory_only,
base::SequencedTaskRunner* cache_task_runner,
- const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
- const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter,
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context,
const GURL& origin);
@@ -84,20 +86,19 @@ class CONTENT_EXPORT CacheStorage {
const CacheStorageCache::ResponseCallback& callback);
// Calls match on all of the caches in parallel, calling |callback| with the
- // first response found. Note that if multiple caches have the same
- // request/response then it is not defined which cache's response will be
- // returned. If no response is found then |callback| is called with
+ // response from the first cache (in order of cache creation) to have the
+ // entry. If no response is found then |callback| is called with
// CACHE_STORAGE_ERROR_NOT_FOUND.
void MatchAllCaches(scoped_ptr<ServiceWorkerFetchRequest> request,
const CacheStorageCache::ResponseCallback& callback);
- // Calls close on each cache and runs the callback after all of them have
- // closed.
- void CloseAllCaches(const base::Closure& callback);
+ // Sums the sizes of each cache and closes them. Runs |callback| with the
+ // size.
+ void GetSizeThenCloseAllCaches(const SizeCallback& callback);
- // The size of all of the origin's contents in memory. Returns 0 if the cache
- // backend is not a memory backend. Runs synchronously.
- int64_t MemoryBackedSize() const;
+ // The size of all of the origin's contents. This value should be used as an
+ // estimate only since the cache may be modified at any time.
+ void Size(const SizeCallback& callback);
// The functions below are for tests to verify that the operations run
// serially.
@@ -106,10 +107,10 @@ class CONTENT_EXPORT CacheStorage {
private:
friend class TestCacheStorage;
-
+ class CacheLoader;
class MemoryLoader;
class SimpleCacheLoader;
- class CacheLoader;
+ struct CacheMatchResponse;
typedef std::map<std::string, base::WeakPtr<CacheStorageCache>> CacheMap;
@@ -119,7 +120,7 @@ class CONTENT_EXPORT CacheStorage {
const std::string& cache_name);
// Holds a reference to a cache for thirty seconds.
- void TemporarilyPreserveCache(const scoped_refptr<CacheStorageCache>& cache);
+ void TemporarilyPreserveCache(scoped_refptr<CacheStorageCache> cache);
virtual void SchedulePreservedCacheRemoval(
const base::Closure& callback); // Virtual for testing.
void RemovePreservedCache(const CacheStorageCache* cache);
@@ -135,9 +136,9 @@ class CONTENT_EXPORT CacheStorage {
const CacheAndErrorCallback& callback);
void CreateCacheDidCreateCache(const std::string& cache_name,
const CacheAndErrorCallback& callback,
- const scoped_refptr<CacheStorageCache>& cache);
+ scoped_refptr<CacheStorageCache> cache);
void CreateCacheDidWriteIndex(const CacheAndErrorCallback& callback,
- const scoped_refptr<CacheStorageCache>& cache,
+ scoped_refptr<CacheStorageCache> cache,
bool success);
// The HasCache callbacks are below.
@@ -151,9 +152,11 @@ class CONTENT_EXPORT CacheStorage {
void DeleteCacheDidClose(const std::string& cache_name,
const BoolAndErrorCallback& callback,
const StringVector& ordered_cache_names,
- const scoped_refptr<CacheStorageCache>& cache);
+ scoped_refptr<CacheStorageCache> cache,
+ int64_t cache_size);
void DeleteCacheDidWriteIndex(const std::string& cache_name,
const BoolAndErrorCallback& callback,
+ int cache_size,
bool success);
void DeleteCacheDidCleanUp(const BoolAndErrorCallback& callback,
bool success);
@@ -165,7 +168,7 @@ class CONTENT_EXPORT CacheStorage {
void MatchCacheImpl(const std::string& cache_name,
scoped_ptr<ServiceWorkerFetchRequest> request,
const CacheStorageCache::ResponseCallback& callback);
- void MatchCacheDidMatch(const scoped_refptr<CacheStorageCache>& cache,
+ void MatchCacheDidMatch(scoped_refptr<CacheStorageCache> cache,
const CacheStorageCache::ResponseCallback& callback,
CacheStorageError error,
scoped_ptr<ServiceWorkerResponse> response,
@@ -174,26 +177,28 @@ class CONTENT_EXPORT CacheStorage {
// The MatchAllCaches callbacks are below.
void MatchAllCachesImpl(scoped_ptr<ServiceWorkerFetchRequest> request,
const CacheStorageCache::ResponseCallback& callback);
- void MatchAllCachesDidMatch(scoped_refptr<CacheStorageCache> cache,
- const base::Closure& barrier_closure,
- CacheStorageCache::ResponseCallback* callback,
- CacheStorageError error,
- scoped_ptr<ServiceWorkerResponse> response,
- scoped_ptr<storage::BlobDataHandle> handle);
+ void MatchAllCachesDidMatch(
+ scoped_refptr<CacheStorageCache> cache,
+ CacheMatchResponse* out_match_response,
+ const base::Closure& barrier_closure,
+ CacheStorageError error,
+ scoped_ptr<ServiceWorkerResponse> service_worker_response,
+ scoped_ptr<storage::BlobDataHandle> handle);
void MatchAllCachesDidMatchAll(
- scoped_ptr<CacheStorageCache::ResponseCallback> callback);
+ scoped_ptr<std::vector<CacheMatchResponse>> match_responses,
+ const CacheStorageCache::ResponseCallback& callback);
- // The CloseAllCaches callbacks are below.
- void CloseAllCachesImpl(const base::Closure& callback);
+ void GetSizeThenCloseAllCachesImpl(const SizeCallback& callback);
+
+ void SizeImpl(const SizeCallback& callback);
void PendingClosure(const base::Closure& callback);
void PendingBoolAndErrorCallback(const BoolAndErrorCallback& callback,
bool found,
CacheStorageError error);
- void PendingCacheAndErrorCallback(
- const CacheAndErrorCallback& callback,
- const scoped_refptr<CacheStorageCache>& cache,
- CacheStorageError error);
+ void PendingCacheAndErrorCallback(const CacheAndErrorCallback& callback,
+ scoped_refptr<CacheStorageCache> cache,
+ CacheStorageError error);
void PendingStringsAndErrorCallback(const StringsAndErrorCallback& callback,
const StringVector& strings,
CacheStorageError error);
@@ -203,6 +208,8 @@ class CONTENT_EXPORT CacheStorage {
scoped_ptr<ServiceWorkerResponse> response,
scoped_ptr<storage::BlobDataHandle> blob_data_handle);
+ void PendingSizeCallback(const SizeCallback& callback, int64_t size);
+
// Whether or not we've loaded the list of cache names into memory.
bool initialized_;
bool initializing_;
@@ -233,6 +240,12 @@ class CONTENT_EXPORT CacheStorage {
std::map<const CacheStorageCache*, scoped_refptr<CacheStorageCache>>
preserved_caches_;
+ // The quota manager.
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
+
+ // The origin that this CacheStorage is associated with.
+ GURL origin_;
+
base::WeakPtrFactory<CacheStorage> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(CacheStorage);
diff --git a/chromium/content/browser/cache_storage/cache_storage.proto b/chromium/content/browser/cache_storage/cache_storage.proto
index 807c1e548c4..07a61700cff 100644
--- a/chromium/content/browser/cache_storage/cache_storage.proto
+++ b/chromium/content/browser/cache_storage/cache_storage.proto
@@ -42,6 +42,7 @@ message CacheResponse {
required ResponseType response_type = 3;
repeated CacheHeaderMap headers = 4;
optional string url = 5;
+ optional int64 response_time = 6;
}
message CacheMetadata {
diff --git a/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.cc b/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.cc
index 08dffc32323..bc58008ae29 100644
--- a/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.cc
@@ -32,13 +32,14 @@ CacheStorageBlobToDiskCache::~CacheStorageBlobToDiskCache() {
void CacheStorageBlobToDiskCache::StreamBlobToCache(
disk_cache::ScopedEntryPtr entry,
int disk_cache_body_index,
- const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
+ net::URLRequestContextGetter* request_context_getter,
scoped_ptr<storage::BlobDataHandle> blob_data_handle,
const EntryAndBoolCallback& callback) {
DCHECK(entry);
DCHECK_LE(0, disk_cache_body_index);
DCHECK(blob_data_handle);
DCHECK(!blob_request_);
+ DCHECK(request_context_getter);
if (!request_context_getter->GetURLRequestContext()) {
callback.Run(std::move(entry), false /* success */);
diff --git a/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.h b/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.h
index 18e6fd9730f..3f73f255a6b 100644
--- a/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.h
+++ b/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache.h
@@ -43,12 +43,11 @@ class CONTENT_EXPORT CacheStorageBlobToDiskCache
// Writes the body of |blob_data_handle| to |entry| with index
// |disk_cache_body_index|. |entry| is passed to the callback once complete.
// Only call this once per instantiation of CacheStorageBlobToDiskCache.
- void StreamBlobToCache(
- disk_cache::ScopedEntryPtr entry,
- int disk_cache_body_index,
- const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
- scoped_ptr<storage::BlobDataHandle> blob_data_handle,
- const EntryAndBoolCallback& callback);
+ void StreamBlobToCache(disk_cache::ScopedEntryPtr entry,
+ int disk_cache_body_index,
+ net::URLRequestContextGetter* request_context_getter,
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle,
+ const EntryAndBoolCallback& callback);
// net::URLRequest::Delegate overrides for reading blobs.
void OnResponseStarted(net::URLRequest* request) override;
@@ -80,7 +79,10 @@ class CONTENT_EXPORT CacheStorageBlobToDiskCache
int cache_entry_offset_;
disk_cache::ScopedEntryPtr entry_;
- scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
+
+ // Owned by CacheStorageCache which owns this.
+ net::URLRequestContextGetter* request_context_getter_;
+
int disk_cache_body_index_;
scoped_ptr<net::URLRequest> blob_request_;
EntryAndBoolCallback callback_;
diff --git a/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc b/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc
index 28e6c0c18b4..5734e0d8a31 100644
--- a/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_blob_to_disk_cache_unittest.cc
@@ -172,7 +172,7 @@ class CacheStorageBlobToDiskCacheTest : public testing::Test {
cache_storage_blob_to_disk_cache_->StreamBlobToCache(
std::move(disk_cache_entry_), kCacheEntryIndex,
- url_request_context_getter_, std::move(new_data_handle),
+ url_request_context_getter_.get(), std::move(new_data_handle),
base::Bind(&CacheStorageBlobToDiskCacheTest::StreamCallback,
base::Unretained(this)));
diff --git a/chromium/content/browser/cache_storage/cache_storage_cache.cc b/chromium/content/browser/cache_storage/cache_storage_cache.cc
index 2fc74110e7e..cbe1889d4e6 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_cache.cc
@@ -15,6 +15,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
+#include "base/thread_task_runner_handle.h"
#include "content/browser/cache_storage/cache_storage.pb.h"
#include "content/browser/cache_storage/cache_storage_blob_to_disk_cache.h"
#include "content/browser/cache_storage/cache_storage_scheduler.h"
@@ -41,7 +42,7 @@ namespace {
class CacheStorageCacheDataHandle
: public storage::BlobDataBuilder::DataHandle {
public:
- CacheStorageCacheDataHandle(const scoped_refptr<CacheStorageCache>& cache,
+ CacheStorageCacheDataHandle(scoped_refptr<CacheStorageCache> cache,
disk_cache::ScopedEntryPtr entry)
: cache_(cache), entry_(std::move(entry)) {}
@@ -58,13 +59,9 @@ typedef base::Callback<void(scoped_ptr<CacheMetadata>)> MetadataCallback;
enum EntryIndex { INDEX_HEADERS = 0, INDEX_RESPONSE_BODY };
-// The maximum size of an individual cache. Ultimately cache size is controlled
-// per-origin.
-const int kMaxCacheBytes = 512 * 1024 * 1024;
-
-void NotReachedCompletionCallback(int rv) {
- NOTREACHED();
-}
+// The maximum size of each cache. Ultimately, cache size
+// is controlled per-origin by the QuotaManager.
+const int kMaxCacheBytes = std::numeric_limits<int>::max();
blink::WebServiceWorkerResponseType ProtoResponseTypeToWebResponseType(
CacheResponse::ResponseType response_type) {
@@ -109,11 +106,10 @@ CacheResponse::ResponseType WebResponseTypeToProtoResponseType(
// Copy headers out of a cache entry and into a protobuf. The callback is
// guaranteed to be run.
void ReadMetadata(disk_cache::Entry* entry, const MetadataCallback& callback);
-void ReadMetadataDidReadMetadata(
- disk_cache::Entry* entry,
- const MetadataCallback& callback,
- const scoped_refptr<net::IOBufferWithSize>& buffer,
- int rv);
+void ReadMetadataDidReadMetadata(disk_cache::Entry* entry,
+ const MetadataCallback& callback,
+ scoped_refptr<net::IOBufferWithSize> buffer,
+ int rv);
bool VaryMatches(const ServiceWorkerHeaderMap& request,
const ServiceWorkerHeaderMap& cached_request,
@@ -147,6 +143,12 @@ bool VaryMatches(const ServiceWorkerHeaderMap& request,
return true;
}
+GURL RemoveQueryParam(const GURL& url) {
+ url::Replacements<char> replacements;
+ replacements.ClearQuery();
+ return url.ReplaceComponents(replacements);
+}
+
void ReadMetadata(disk_cache::Entry* entry, const MetadataCallback& callback) {
DCHECK(entry);
@@ -163,11 +165,10 @@ void ReadMetadata(disk_cache::Entry* entry, const MetadataCallback& callback) {
read_header_callback.Run(read_rv);
}
-void ReadMetadataDidReadMetadata(
- disk_cache::Entry* entry,
- const MetadataCallback& callback,
- const scoped_refptr<net::IOBufferWithSize>& buffer,
- int rv) {
+void ReadMetadataDidReadMetadata(disk_cache::Entry* entry,
+ const MetadataCallback& callback,
+ scoped_refptr<net::IOBufferWithSize> buffer,
+ int rv) {
if (rv != buffer->size()) {
callback.Run(scoped_ptr<CacheMetadata>());
return;
@@ -210,12 +211,20 @@ struct CacheStorageCache::OpenAllEntriesContext {
// The state needed to pass between CacheStorageCache::MatchAll callbacks.
struct CacheStorageCache::MatchAllContext {
- explicit MatchAllContext(const CacheStorageCache::ResponsesCallback& callback)
- : original_callback(callback),
+ MatchAllContext(scoped_ptr<ServiceWorkerFetchRequest> request,
+ const CacheStorageCacheQueryParams& match_params,
+ const ResponsesCallback& callback)
+ : request(std::move(request)),
+ options(match_params),
+ original_callback(callback),
out_responses(new Responses),
out_blob_data_handles(new BlobDataHandles) {}
~MatchAllContext() {}
+ scoped_ptr<ServiceWorkerFetchRequest> request;
+
+ CacheStorageCacheQueryParams options;
+
// The callback passed to the MatchAll() function.
ResponsesCallback original_callback;
@@ -251,31 +260,22 @@ struct CacheStorageCache::KeysContext {
// The state needed to pass between CacheStorageCache::Put callbacks.
struct CacheStorageCache::PutContext {
- PutContext(
- const GURL& origin,
- scoped_ptr<ServiceWorkerFetchRequest> request,
- scoped_ptr<ServiceWorkerResponse> response,
- scoped_ptr<storage::BlobDataHandle> blob_data_handle,
- const CacheStorageCache::ErrorCallback& callback,
- const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
- const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy)
- : origin(origin),
- request(std::move(request)),
+ PutContext(scoped_ptr<ServiceWorkerFetchRequest> request,
+ scoped_ptr<ServiceWorkerResponse> response,
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle,
+ const CacheStorageCache::ErrorCallback& callback)
+ : request(std::move(request)),
response(std::move(response)),
blob_data_handle(std::move(blob_data_handle)),
- callback(callback),
- request_context_getter(request_context_getter),
- quota_manager_proxy(quota_manager_proxy) {}
+ callback(callback) {}
// Input parameters to the Put function.
- GURL origin;
scoped_ptr<ServiceWorkerFetchRequest> request;
scoped_ptr<ServiceWorkerResponse> response;
scoped_ptr<storage::BlobDataHandle> blob_data_handle;
CacheStorageCache::ErrorCallback callback;
- scoped_refptr<net::URLRequestContextGetter> request_context_getter;
- scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy;
disk_cache::ScopedEntryPtr cache_entry;
+ int64_t available_bytes = 0;
private:
DISALLOW_COPY_AND_ASSIGN(PutContext);
@@ -284,26 +284,30 @@ struct CacheStorageCache::PutContext {
// static
scoped_refptr<CacheStorageCache> CacheStorageCache::CreateMemoryCache(
const GURL& origin,
- const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
- const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
+ const std::string& cache_name,
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter,
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context) {
- return make_scoped_refptr(
- new CacheStorageCache(origin, base::FilePath(), request_context_getter,
- quota_manager_proxy, blob_context));
+ return make_scoped_refptr(new CacheStorageCache(
+ origin, cache_name, base::FilePath(), std::move(request_context_getter),
+ std::move(quota_manager_proxy), blob_context));
}
// static
scoped_refptr<CacheStorageCache> CacheStorageCache::CreatePersistentCache(
const GURL& origin,
+ const std::string& cache_name,
const base::FilePath& path,
- const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
- const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter,
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context) {
return make_scoped_refptr(new CacheStorageCache(
- origin, path, request_context_getter, quota_manager_proxy, blob_context));
+ origin, cache_name, path, std::move(request_context_getter),
+ std::move(quota_manager_proxy), blob_context));
}
CacheStorageCache::~CacheStorageCache() {
+ quota_manager_proxy_->NotifyOriginNoLongerInUse(origin_);
}
base::WeakPtr<CacheStorageCache> CacheStorageCache::AsWeakPtr() {
@@ -327,7 +331,10 @@ void CacheStorageCache::Match(scoped_ptr<ServiceWorkerFetchRequest> request,
base::Passed(std::move(request)), pending_callback));
}
-void CacheStorageCache::MatchAll(const ResponsesCallback& callback) {
+void CacheStorageCache::MatchAll(
+ scoped_ptr<ServiceWorkerFetchRequest> request,
+ const CacheStorageCacheQueryParams& match_params,
+ const ResponsesCallback& callback) {
if (!LazyInitialize()) {
callback.Run(CACHE_STORAGE_ERROR_STORAGE, scoped_ptr<Responses>(),
scoped_ptr<BlobDataHandles>());
@@ -337,9 +344,12 @@ void CacheStorageCache::MatchAll(const ResponsesCallback& callback) {
ResponsesCallback pending_callback =
base::Bind(&CacheStorageCache::PendingResponsesCallback,
weak_ptr_factory_.GetWeakPtr(), callback);
+
+ scoped_ptr<MatchAllContext> context(
+ new MatchAllContext(std::move(request), match_params, pending_callback));
scheduler_->ScheduleOperation(base::Bind(&CacheStorageCache::MatchAllImpl,
weak_ptr_factory_.GetWeakPtr(),
- pending_callback));
+ base::Passed(std::move(context))));
}
void CacheStorageCache::BatchOperation(
@@ -427,50 +437,63 @@ void CacheStorageCache::Close(const base::Closure& callback) {
pending_callback));
}
-int64_t CacheStorageCache::MemoryBackedSize() const {
- if (backend_state_ != BACKEND_OPEN || !memory_only_)
- return 0;
+void CacheStorageCache::Size(const SizeCallback& callback) {
+ if (!LazyInitialize()) {
+ // TODO(jkarlin): Delete caches that can't be initialized.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ base::Bind(callback, 0));
+ return;
+ }
- scoped_ptr<disk_cache::Backend::Iterator> backend_iter =
- backend_->CreateIterator();
- disk_cache::Entry* entry = nullptr;
+ if (initializing_) {
+ // Note that Size doesn't use the scheduler, see header comments for why.
+ pending_size_callbacks_.push_back(callback);
+ return;
+ }
- int64_t sum = 0;
+ // Run immediately so that we don't deadlock on
+ // CacheStorageCache::PutDidDelete's call to
+ // quota_manager_proxy_->GetUsageAndQuota.
+ SizeImpl(callback);
+}
- std::vector<disk_cache::Entry*> entries;
- int rv = net::OK;
- while ((rv = backend_iter->OpenNextEntry(
- &entry, base::Bind(NotReachedCompletionCallback))) == net::OK) {
- entries.push_back(entry); // Open the entries without mutating them.
+void CacheStorageCache::GetSizeThenClose(const SizeCallback& callback) {
+ if (!LazyInitialize()) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ base::Bind(callback, 0));
+ return;
}
- DCHECK_NE(net::ERR_IO_PENDING, rv)
- << "Memory cache operations should be synchronous.";
- for (disk_cache::Entry* entry : entries) {
- sum += entry->GetDataSize(INDEX_HEADERS) +
- entry->GetDataSize(INDEX_RESPONSE_BODY);
- entry->Close();
- }
+ SizeCallback pending_callback =
+ base::Bind(&CacheStorageCache::PendingSizeCallback,
+ weak_ptr_factory_.GetWeakPtr(), callback);
- return sum;
+ scheduler_->ScheduleOperation(
+ base::Bind(&CacheStorageCache::SizeImpl, weak_ptr_factory_.GetWeakPtr(),
+ base::Bind(&CacheStorageCache::GetSizeThenCloseDidGetSize,
+ weak_ptr_factory_.GetWeakPtr(), pending_callback)));
}
CacheStorageCache::CacheStorageCache(
const GURL& origin,
+ const std::string& cache_name,
const base::FilePath& path,
- const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
- const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter,
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context)
: origin_(origin),
+ cache_name_(cache_name),
path_(path),
- request_context_getter_(request_context_getter),
- quota_manager_proxy_(quota_manager_proxy),
+ request_context_getter_(std::move(request_context_getter)),
+ quota_manager_proxy_(std::move(quota_manager_proxy)),
blob_storage_context_(blob_context),
- backend_state_(BACKEND_UNINITIALIZED),
scheduler_(new CacheStorageScheduler()),
- initializing_(false),
memory_only_(path.empty()),
weak_ptr_factory_(this) {
+ DCHECK(!origin_.is_empty());
+ DCHECK(quota_manager_proxy_.get());
+
+ quota_manager_proxy_->NotifyOriginInUse(origin_);
}
bool CacheStorageCache::LazyInitialize() {
@@ -638,28 +661,30 @@ void CacheStorageCache::MatchDidReadMetadata(
std::move(blob_data_handle));
}
-void CacheStorageCache::MatchAllImpl(const ResponsesCallback& callback) {
+void CacheStorageCache::MatchAllImpl(scoped_ptr<MatchAllContext> context) {
DCHECK_NE(BACKEND_UNINITIALIZED, backend_state_);
if (backend_state_ != BACKEND_OPEN) {
- callback.Run(CACHE_STORAGE_ERROR_STORAGE, scoped_ptr<Responses>(),
- scoped_ptr<BlobDataHandles>());
+ context->original_callback.Run(CACHE_STORAGE_ERROR_STORAGE,
+ scoped_ptr<Responses>(),
+ scoped_ptr<BlobDataHandles>());
return;
}
OpenAllEntries(base::Bind(&CacheStorageCache::MatchAllDidOpenAllEntries,
- weak_ptr_factory_.GetWeakPtr(), callback));
+ weak_ptr_factory_.GetWeakPtr(),
+ base::Passed(std::move(context))));
}
void CacheStorageCache::MatchAllDidOpenAllEntries(
- const ResponsesCallback& callback,
+ scoped_ptr<MatchAllContext> context,
scoped_ptr<OpenAllEntriesContext> entries_context,
CacheStorageError error) {
if (error != CACHE_STORAGE_OK) {
- callback.Run(error, scoped_ptr<Responses>(), scoped_ptr<BlobDataHandles>());
+ context->original_callback.Run(error, scoped_ptr<Responses>(),
+ scoped_ptr<BlobDataHandles>());
return;
}
- scoped_ptr<MatchAllContext> context(new MatchAllContext(callback));
context->entries_context.swap(entries_context);
Entries::iterator iter = context->entries_context->entries.begin();
MatchAllProcessNextEntry(std::move(context), iter);
@@ -676,6 +701,17 @@ void CacheStorageCache::MatchAllProcessNextEntry(
return;
}
+ if (context->options.ignore_search) {
+ DCHECK(context->request);
+ disk_cache::Entry* entry(*iter);
+ if (RemoveQueryParam(context->request->url) !=
+ RemoveQueryParam(GURL(entry->GetKey()))) {
+ // In this case, we don't need to read data.
+ MatchAllProcessNextEntry(std::move(context), iter + 1);
+ return;
+ }
+ }
+
ReadMetadata(*iter, base::Bind(&CacheStorageCache::MatchAllDidReadMetadata,
weak_ptr_factory_.GetWeakPtr(),
base::Passed(std::move(context)), iter));
@@ -740,7 +776,9 @@ void CacheStorageCache::Put(const CacheStorageBatchOperation& operation,
operation.response.status_text, operation.response.response_type,
operation.response.headers, operation.response.blob_uuid,
operation.response.blob_size, operation.response.stream_url,
- operation.response.error));
+ operation.response.error, operation.response.response_time,
+ false /* is_in_cache_storage */,
+ std::string() /* cache_storage_cache_name */));
scoped_ptr<storage::BlobDataHandle> blob_data_handle;
@@ -762,9 +800,8 @@ void CacheStorageCache::Put(const CacheStorageBatchOperation& operation,
weak_ptr_factory_.GetWeakPtr(), callback);
scoped_ptr<PutContext> put_context(
- new PutContext(origin_, std::move(request), std::move(response),
- std::move(blob_data_handle), pending_callback,
- request_context_getter_, quota_manager_proxy_));
+ new PutContext(std::move(request), std::move(response),
+ std::move(blob_data_handle), pending_callback));
scheduler_->ScheduleOperation(
base::Bind(&CacheStorageCache::PutImpl, weak_ptr_factory_.GetWeakPtr(),
@@ -781,7 +818,7 @@ void CacheStorageCache::PutImpl(scoped_ptr<PutContext> put_context) {
scoped_ptr<ServiceWorkerFetchRequest> request_copy(
new ServiceWorkerFetchRequest(*put_context->request));
- DeleteImpl(std::move(request_copy),
+ DeleteImpl(std::move(request_copy), CacheStorageCacheQueryParams(),
base::Bind(&CacheStorageCache::PutDidDelete,
weak_ptr_factory_.GetWeakPtr(),
base::Passed(std::move(put_context))));
@@ -794,6 +831,31 @@ void CacheStorageCache::PutDidDelete(scoped_ptr<PutContext> put_context,
return;
}
+ quota_manager_proxy_->GetUsageAndQuota(
+ base::ThreadTaskRunnerHandle::Get().get(), origin_,
+ storage::kStorageTypeTemporary,
+ base::Bind(&CacheStorageCache::PutDidGetUsageAndQuota,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::Passed(std::move(put_context))));
+}
+
+void CacheStorageCache::PutDidGetUsageAndQuota(
+ scoped_ptr<PutContext> put_context,
+ storage::QuotaStatusCode status_code,
+ int64_t usage,
+ int64_t quota) {
+ if (backend_state_ != BACKEND_OPEN) {
+ put_context->callback.Run(CACHE_STORAGE_ERROR_STORAGE);
+ return;
+ }
+
+ if (status_code != storage::kQuotaStatusOk) {
+ put_context->callback.Run(CACHE_STORAGE_ERROR_QUOTA_EXCEEDED);
+ return;
+ }
+
+ put_context->available_bytes = quota - usage;
+
scoped_ptr<disk_cache::Entry*> scoped_entry_ptr(new disk_cache::Entry*());
disk_cache::Entry** entry_ptr = scoped_entry_ptr.get();
ServiceWorkerFetchRequest* request_ptr = put_context->request.get();
@@ -841,6 +903,8 @@ void CacheStorageCache::PutDidCreateEntry(
response_metadata->set_response_type(
WebResponseTypeToProtoResponseType(put_context->response->response_type));
response_metadata->set_url(put_context->response->url.spec());
+ response_metadata->set_response_time(
+ put_context->response->response_time.ToInternalValue());
for (ServiceWorkerHeaderMap::const_iterator it =
put_context->response->headers.begin();
it != put_context->response->headers.end(); ++it) {
@@ -860,6 +924,12 @@ void CacheStorageCache::PutDidCreateEntry(
scoped_refptr<net::StringIOBuffer> buffer(
new net::StringIOBuffer(std::move(serialized)));
+ int64_t bytes_to_write = buffer->size() + put_context->response->blob_size;
+ if (put_context->available_bytes < bytes_to_write) {
+ put_context->callback.Run(CACHE_STORAGE_ERROR_QUOTA_EXCEEDED);
+ return;
+ }
+
// Get a temporary copy of the entry pointer before passing it in base::Bind.
disk_cache::Entry* temp_entry_ptr = put_context->cache_entry.get();
@@ -888,13 +958,7 @@ void CacheStorageCache::PutDidWriteHeaders(scoped_ptr<PutContext> put_context,
// from the blob into the cache entry.
if (put_context->response->blob_uuid.empty()) {
- if (put_context->quota_manager_proxy.get()) {
- put_context->quota_manager_proxy->NotifyStorageModified(
- storage::QuotaClient::kServiceWorkerCache, put_context->origin,
- storage::kStorageTypeTemporary,
- put_context->cache_entry->GetDataSize(INDEX_HEADERS));
- }
-
+ UpdateCacheSize();
put_context->callback.Run(CACHE_STORAGE_OK);
return;
}
@@ -909,14 +973,11 @@ void CacheStorageCache::PutDidWriteHeaders(scoped_ptr<PutContext> put_context,
BlobToDiskCacheIDMap::KeyType blob_to_cache_key =
active_blob_to_disk_cache_writers_.Add(blob_to_cache);
- // Grab some pointers before passing put_context in Bind.
- scoped_refptr<net::URLRequestContextGetter> request_context_getter =
- put_context->request_context_getter;
scoped_ptr<storage::BlobDataHandle> blob_data_handle =
std::move(put_context->blob_data_handle);
blob_to_cache->StreamBlobToCache(
- std::move(entry), INDEX_RESPONSE_BODY, request_context_getter,
+ std::move(entry), INDEX_RESPONSE_BODY, request_context_getter_.get(),
std::move(blob_data_handle),
base::Bind(&CacheStorageCache::PutDidWriteBlobToCache,
weak_ptr_factory_.GetWeakPtr(),
@@ -939,17 +1000,32 @@ void CacheStorageCache::PutDidWriteBlobToCache(
return;
}
- if (put_context->quota_manager_proxy.get()) {
- put_context->quota_manager_proxy->NotifyStorageModified(
- storage::QuotaClient::kServiceWorkerCache, put_context->origin,
- storage::kStorageTypeTemporary,
- put_context->cache_entry->GetDataSize(INDEX_HEADERS) +
- put_context->cache_entry->GetDataSize(INDEX_RESPONSE_BODY));
- }
-
+ UpdateCacheSize();
put_context->callback.Run(CACHE_STORAGE_OK);
}
+void CacheStorageCache::UpdateCacheSize() {
+ if (backend_state_ != BACKEND_OPEN)
+ return;
+
+ // Note that the callback holds a refptr to |this| since UpdateCacheSize is
+ // often called after an operation completes and the cache might be freed.
+ int rv = backend_->CalculateSizeOfAllEntries(
+ base::Bind(&CacheStorageCache::UpdateCacheSizeGotSize, this));
+
+ if (rv != net::ERR_IO_PENDING)
+ UpdateCacheSizeGotSize(rv);
+}
+
+void CacheStorageCache::UpdateCacheSizeGotSize(int current_cache_size) {
+ int64_t old_cache_size = cache_size_;
+ cache_size_ = current_cache_size;
+
+ quota_manager_proxy_->NotifyStorageModified(
+ storage::QuotaClient::kServiceWorkerCache, origin_,
+ storage::kStorageTypeTemporary, current_cache_size - old_cache_size);
+}
+
void CacheStorageCache::Delete(const CacheStorageBatchOperation& operation,
const ErrorCallback& callback) {
DCHECK(BACKEND_OPEN == backend_state_ || initializing_);
@@ -966,17 +1042,27 @@ void CacheStorageCache::Delete(const CacheStorageBatchOperation& operation,
weak_ptr_factory_.GetWeakPtr(), callback);
scheduler_->ScheduleOperation(
base::Bind(&CacheStorageCache::DeleteImpl, weak_ptr_factory_.GetWeakPtr(),
- base::Passed(std::move(request)), pending_callback));
+ base::Passed(std::move(request)), operation.match_params,
+ pending_callback));
}
void CacheStorageCache::DeleteImpl(
scoped_ptr<ServiceWorkerFetchRequest> request,
+ const CacheStorageCacheQueryParams& match_params,
const ErrorCallback& callback) {
DCHECK_NE(BACKEND_UNINITIALIZED, backend_state_);
if (backend_state_ != BACKEND_OPEN) {
callback.Run(CACHE_STORAGE_ERROR_STORAGE);
return;
}
+
+ if (match_params.ignore_search) {
+ OpenAllEntries(base::Bind(&CacheStorageCache::DeleteDidOpenAllEntries,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::Passed(std::move(request)), callback));
+ return;
+ }
+
scoped_ptr<disk_cache::Entry*> entry(new disk_cache::Entry*);
disk_cache::Entry** entry_ptr = entry.get();
@@ -986,7 +1072,7 @@ void CacheStorageCache::DeleteImpl(
net::CompletionCallback open_entry_callback = base::Bind(
&CacheStorageCache::DeleteDidOpenEntry, weak_ptr_factory_.GetWeakPtr(),
origin_, base::Passed(std::move(request)), callback,
- base::Passed(std::move(entry)), quota_manager_proxy_);
+ base::Passed(std::move(entry)));
int rv = backend_->OpenEntry(request_ptr->url.spec(), entry_ptr,
open_entry_callback);
@@ -994,12 +1080,35 @@ void CacheStorageCache::DeleteImpl(
open_entry_callback.Run(rv);
}
+void CacheStorageCache::DeleteDidOpenAllEntries(
+ scoped_ptr<ServiceWorkerFetchRequest> request,
+ const ErrorCallback& callback,
+ scoped_ptr<OpenAllEntriesContext> entries_context,
+ CacheStorageError error) {
+ if (error != CACHE_STORAGE_OK) {
+ callback.Run(error);
+ return;
+ }
+
+ GURL request_url_without_query = RemoveQueryParam(request->url);
+ for (Entries::iterator iter = entries_context->entries.begin();
+ iter != entries_context->entries.end(); iter++) {
+ disk_cache::Entry* entry(*iter);
+ if (request_url_without_query == RemoveQueryParam(GURL(entry->GetKey())))
+ entry->Doom();
+ }
+
+ entries_context.reset();
+
+ UpdateCacheSize();
+ callback.Run(CACHE_STORAGE_OK);
+}
+
void CacheStorageCache::DeleteDidOpenEntry(
const GURL& origin,
scoped_ptr<ServiceWorkerFetchRequest> request,
const CacheStorageCache::ErrorCallback& callback,
scoped_ptr<disk_cache::Entry*> entry_ptr,
- const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
int rv) {
if (rv != net::OK) {
callback.Run(CACHE_STORAGE_ERROR_NOT_FOUND);
@@ -1009,15 +1118,10 @@ void CacheStorageCache::DeleteDidOpenEntry(
DCHECK(entry_ptr);
disk_cache::ScopedEntryPtr entry(*entry_ptr);
- if (quota_manager_proxy.get()) {
- quota_manager_proxy->NotifyStorageModified(
- storage::QuotaClient::kServiceWorkerCache, origin,
- storage::kStorageTypeTemporary,
- -1 * (entry->GetDataSize(INDEX_HEADERS) +
- entry->GetDataSize(INDEX_RESPONSE_BODY)));
- }
-
entry->Doom();
+ entry.reset();
+
+ UpdateCacheSize();
callback.Run(CACHE_STORAGE_OK);
}
@@ -1107,6 +1211,19 @@ void CacheStorageCache::CloseImpl(const base::Closure& callback) {
callback.Run();
}
+void CacheStorageCache::SizeImpl(const SizeCallback& callback) {
+ DCHECK_NE(BACKEND_UNINITIALIZED, backend_state_);
+
+ int64_t size = backend_state_ == BACKEND_OPEN ? cache_size_ : 0;
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ base::Bind(callback, size));
+}
+
+void CacheStorageCache::GetSizeThenCloseDidGetSize(const SizeCallback& callback,
+ int64_t cache_size) {
+ CloseImpl(base::Bind(callback, cache_size));
+}
+
void CacheStorageCache::CreateBackend(const ErrorCallback& callback) {
DCHECK(!backend_);
@@ -1158,19 +1275,40 @@ void CacheStorageCache::InitBackend() {
scheduler_->ScheduleOperation(base::Bind(
&CacheStorageCache::CreateBackend, weak_ptr_factory_.GetWeakPtr(),
- base::Bind(&CacheStorageCache::InitDone,
+ base::Bind(&CacheStorageCache::InitDidCreateBackend,
weak_ptr_factory_.GetWeakPtr())));
}
-void CacheStorageCache::InitDone(CacheStorageError error) {
+void CacheStorageCache::InitDidCreateBackend(
+ CacheStorageError cache_create_error) {
+ if (cache_create_error != CACHE_STORAGE_OK) {
+ InitGotCacheSize(cache_create_error, 0);
+ return;
+ }
+
+ int rv = backend_->CalculateSizeOfAllEntries(
+ base::Bind(&CacheStorageCache::InitGotCacheSize,
+ weak_ptr_factory_.GetWeakPtr(), cache_create_error));
+
+ if (rv != net::ERR_IO_PENDING)
+ InitGotCacheSize(cache_create_error, rv);
+}
+
+void CacheStorageCache::InitGotCacheSize(CacheStorageError cache_create_error,
+ int cache_size) {
+ cache_size_ = cache_size;
initializing_ = false;
- backend_state_ = (error == CACHE_STORAGE_OK && backend_ &&
+ backend_state_ = (cache_create_error == CACHE_STORAGE_OK && backend_ &&
backend_state_ == BACKEND_UNINITIALIZED)
? BACKEND_OPEN
: BACKEND_CLOSED;
- UMA_HISTOGRAM_ENUMERATION("ServiceWorkerCache.InitBackendResult", error,
- CACHE_STORAGE_ERROR_LAST + 1);
+ for (const SizeCallback& callback : pending_size_callbacks_)
+ SizeImpl(callback);
+ pending_size_callbacks_.clear();
+
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorkerCache.InitBackendResult",
+ cache_create_error, CACHE_STORAGE_ERROR_LAST + 1);
scheduler_->CompleteOperationAndRunNext();
}
@@ -1227,6 +1365,15 @@ void CacheStorageCache::PendingRequestsCallback(
scheduler_->CompleteOperationAndRunNext();
}
+void CacheStorageCache::PendingSizeCallback(const SizeCallback& callback,
+ int64_t size) {
+ base::WeakPtr<CacheStorageCache> cache = weak_ptr_factory_.GetWeakPtr();
+
+ callback.Run(size);
+ if (cache)
+ scheduler_->CompleteOperationAndRunNext();
+}
+
void CacheStorageCache::PopulateResponseMetadata(
const CacheMetadata& metadata,
ServiceWorkerResponse* response) {
@@ -1235,7 +1382,9 @@ void CacheStorageCache::PopulateResponseMetadata(
metadata.response().status_text(),
ProtoResponseTypeToWebResponseType(metadata.response().response_type()),
ServiceWorkerHeaderMap(), "", 0, GURL(),
- blink::WebServiceWorkerResponseErrorUnknown);
+ blink::WebServiceWorkerResponseErrorUnknown,
+ base::Time::FromInternalValue(metadata.response().response_time()),
+ true /* is_in_cache_storage */, cache_name_);
for (int i = 0; i < metadata.response().headers_size(); ++i) {
const CacheHeaderMap header = metadata.response().headers(i);
diff --git a/chromium/content/browser/cache_storage/cache_storage_cache.h b/chromium/content/browser/cache_storage/cache_storage_cache.h
index a9dcd4cccaf..4cb77ddb70a 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache.h
+++ b/chromium/content/browser/cache_storage/cache_storage_cache.h
@@ -18,6 +18,7 @@
#include "content/common/cache_storage/cache_storage_types.h"
#include "content/common/service_worker/service_worker_types.h"
#include "net/disk_cache/disk_cache.h"
+#include "storage/common/quota/quota_status_code.h"
namespace net {
class URLRequestContextGetter;
@@ -38,9 +39,9 @@ class CacheStorageScheduler;
class TestCacheStorageCache;
// Represents a ServiceWorker Cache as seen in
-// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/
-// The asynchronous methods are executed serially. Callbacks to the
-// public functions will be called so long as the cache object lives.
+// https://slightlyoff.github.io/ServiceWorker/spec/service_worker/ The
+// asynchronous methods are executed serially (except for Size). Callbacks to
+// the public functions will be called so long as the cache object lives.
class CONTENT_EXPORT CacheStorageCache
: public base::RefCounted<CacheStorageCache> {
public:
@@ -57,26 +58,31 @@ class CONTENT_EXPORT CacheStorageCache
using Requests = std::vector<ServiceWorkerFetchRequest>;
using RequestsCallback =
base::Callback<void(CacheStorageError, scoped_ptr<Requests>)>;
+ using SizeCallback = base::Callback<void(int64_t)>;
static scoped_refptr<CacheStorageCache> CreateMemoryCache(
const GURL& origin,
- const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
- const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
+ const std::string& cache_name,
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter,
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context);
static scoped_refptr<CacheStorageCache> CreatePersistentCache(
const GURL& origin,
+ const std::string& cache_name,
const base::FilePath& path,
- const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
- const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter,
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context);
// Returns ERROR_TYPE_NOT_FOUND if not found.
void Match(scoped_ptr<ServiceWorkerFetchRequest> request,
const ResponseCallback& callback);
- // Returns CACHE_STORAGE_OK and all responses in this cache. If there are no
- // responses, returns CACHE_STORAGE_OK and an empty vector.
- void MatchAll(const ResponsesCallback& callback);
+ // Returns CACHE_STORAGE_OK and matched responses in this cache. If there are
+ // no responses, returns CACHE_STORAGE_OK and an empty vector.
+ void MatchAll(scoped_ptr<ServiceWorkerFetchRequest> request,
+ const CacheStorageCacheQueryParams& match_params,
+ const ResponsesCallback& callback);
// Runs given batch operations. This corresponds to the Batch Cache Operations
// algorithm in the spec.
@@ -106,9 +112,16 @@ class CONTENT_EXPORT CacheStorageCache
// will exit early. Close should only be called once per CacheStorageCache.
void Close(const base::Closure& callback);
- // The size of the cache contents in memory. Returns 0 if the cache backend is
- // not a memory cache backend.
- int64_t MemoryBackedSize() const;
+ // The size of the cache's contents. This runs in parallel with other Cache
+ // operations. This is because QuotaManager is a dependency of the Put
+ // operation and QuotaManager calls Size. If the cache isn't yet initialized,
+ // runs immediately after initialization, before any pending operations in the
+ // scheduler are run.
+ void Size(const SizeCallback& callback);
+
+ // Gets the cache's size, closes the backend, and then runs |callback| with
+ // the cache's size.
+ void GetSizeThenClose(const SizeCallback& callback);
base::FilePath path() const { return path_; }
@@ -141,9 +154,10 @@ class CONTENT_EXPORT CacheStorageCache
CacheStorageCache(
const GURL& origin,
+ const std::string& cache_name,
const base::FilePath& path,
- const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
- const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter,
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context);
// Async operations in progress will cancel and not run their callbacks.
@@ -171,9 +185,9 @@ class CONTENT_EXPORT CacheStorageCache
scoped_ptr<CacheMetadata> headers);
// MatchAll callbacks
- void MatchAllImpl(const ResponsesCallback& callback);
+ void MatchAllImpl(scoped_ptr<MatchAllContext> context);
void MatchAllDidOpenAllEntries(
- const ResponsesCallback& callback,
+ scoped_ptr<MatchAllContext> context,
scoped_ptr<OpenAllEntriesContext> entries_context,
CacheStorageError error);
void MatchAllProcessNextEntry(scoped_ptr<MatchAllContext> context,
@@ -190,6 +204,10 @@ class CONTENT_EXPORT CacheStorageCache
void PutImpl(scoped_ptr<PutContext> put_context);
void PutDidDelete(scoped_ptr<PutContext> put_context,
CacheStorageError delete_error);
+ void PutDidGetUsageAndQuota(scoped_ptr<PutContext> put_context,
+ storage::QuotaStatusCode status_code,
+ int64_t usage,
+ int64_t quota);
void PutDidCreateEntry(scoped_ptr<disk_cache::Entry*> entry_ptr,
scoped_ptr<PutContext> put_context,
int rv);
@@ -201,18 +219,28 @@ class CONTENT_EXPORT CacheStorageCache
disk_cache::ScopedEntryPtr entry,
bool success);
+ // Asynchronously calculates the current cache size, notifies the quota
+ // manager of any change from the last report, and sets cache_size_ to the new
+ // size. Runs |callback| once complete.
+ void UpdateCacheSize();
+ void UpdateCacheSizeGotSize(int current_cache_size);
+
// Returns ERROR_NOT_FOUND if not found. Otherwise deletes and returns OK.
void Delete(const CacheStorageBatchOperation& operation,
const ErrorCallback& callback);
void DeleteImpl(scoped_ptr<ServiceWorkerFetchRequest> request,
+ const CacheStorageCacheQueryParams& match_params,
const ErrorCallback& callback);
- void DeleteDidOpenEntry(
- const GURL& origin,
+ void DeleteDidOpenAllEntries(
scoped_ptr<ServiceWorkerFetchRequest> request,
- const CacheStorageCache::ErrorCallback& callback,
- scoped_ptr<disk_cache::Entry*> entryptr,
- const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
- int rv);
+ const ErrorCallback& callback,
+ scoped_ptr<OpenAllEntriesContext> entries_context,
+ CacheStorageError error);
+ void DeleteDidOpenEntry(const GURL& origin,
+ scoped_ptr<ServiceWorkerFetchRequest> request,
+ const CacheStorageCache::ErrorCallback& callback,
+ scoped_ptr<disk_cache::Entry*> entryptr,
+ int rv);
// Keys callbacks.
void KeysImpl(const RequestsCallback& callback);
@@ -227,6 +255,11 @@ class CONTENT_EXPORT CacheStorageCache
void CloseImpl(const base::Closure& callback);
+ void SizeImpl(const SizeCallback& callback);
+
+ void GetSizeThenCloseDidGetSize(const SizeCallback& callback,
+ int64_t cache_size);
+
// Loads the backend and calls the callback with the result (true for
// success). The callback will always be called. Virtual for tests.
virtual void CreateBackend(const ErrorCallback& callback);
@@ -235,7 +268,8 @@ class CONTENT_EXPORT CacheStorageCache
int rv);
void InitBackend();
- void InitDone(CacheStorageError error);
+ void InitDidCreateBackend(CacheStorageError cache_create_error);
+ void InitGotCacheSize(CacheStorageError cache_create_error, int cache_size);
void PendingClosure(const base::Closure& callback);
void PendingErrorCallback(const ErrorCallback& callback,
@@ -252,6 +286,7 @@ class CONTENT_EXPORT CacheStorageCache
void PendingRequestsCallback(const RequestsCallback& callback,
CacheStorageError error,
scoped_ptr<Requests> requests);
+ void PendingSizeCallback(const SizeCallback& callback, int64_t size);
void PopulateResponseMetadata(const CacheMetadata& metadata,
ServiceWorkerResponse* response);
@@ -263,13 +298,16 @@ class CONTENT_EXPORT CacheStorageCache
scoped_ptr<disk_cache::Backend> backend_;
GURL origin_;
+ const std::string cache_name_;
base::FilePath path_;
scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy_;
base::WeakPtr<storage::BlobStorageContext> blob_storage_context_;
- BackendState backend_state_;
+ BackendState backend_state_ = BACKEND_UNINITIALIZED;
scoped_ptr<CacheStorageScheduler> scheduler_;
- bool initializing_;
+ std::vector<SizeCallback> pending_size_callbacks_;
+ bool initializing_ = false;
+ int64_t cache_size_ = 0;
// Owns the elements of the list
BlobToDiskCacheIDMap active_blob_to_disk_cache_writers_;
diff --git a/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc b/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc
index b440758990e..a8200769fb2 100644
--- a/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_cache_unittest.cc
@@ -23,6 +23,7 @@
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/referrer.h"
+#include "content/public/test/mock_special_storage_policy.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/base/test_completion_callback.h"
@@ -41,6 +42,8 @@ namespace content {
namespace {
const char kTestData[] = "Hello World";
+const char kOrigin[] = "http://example.com";
+const char kCacheName[] = "test_cache";
// Returns a BlobProtocolHandler that uses |blob_storage_context|. Caller owns
// the memory.
@@ -188,6 +191,14 @@ bool ResponseMetadataEqual(const ServiceWorkerResponse& expected,
return false;
}
+ EXPECT_EQ(expected.response_time, actual.response_time);
+ if (expected.response_time != actual.response_time)
+ return false;
+
+ EXPECT_EQ(expected.cache_storage_cache_name, actual.cache_storage_cache_name);
+ if (expected.cache_storage_cache_name != actual.cache_storage_cache_name)
+ return false;
+
return true;
}
@@ -198,6 +209,14 @@ bool ResponseBodiesEqual(const std::string& expected_body,
return expected_body == actual_body;
}
+ServiceWorkerResponse SetCacheName(const ServiceWorkerResponse& original) {
+ return ServiceWorkerResponse(
+ original.url, original.status_code, original.status_text,
+ original.response_type, original.headers, original.blob_uuid,
+ original.blob_size, original.stream_url, original.error,
+ original.response_time, true, kCacheName);
+}
+
} // namespace
// A CacheStorageCache that can optionally delay during backend creation.
@@ -205,11 +224,13 @@ class TestCacheStorageCache : public CacheStorageCache {
public:
TestCacheStorageCache(
const GURL& origin,
+ const std::string& cache_name,
const base::FilePath& path,
const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext> blob_context)
: CacheStorageCache(origin,
+ cache_name,
path,
request_context_getter,
quota_manager_proxy,
@@ -253,9 +274,7 @@ class TestCacheStorageCache : public CacheStorageCache {
class CacheStorageCacheTest : public testing::Test {
public:
CacheStorageCacheTest()
- : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
- callback_error_(CACHE_STORAGE_OK),
- callback_closed_(false) {}
+ : browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
void SetUp() override {
ChromeBlobStorageContext* blob_storage_context =
@@ -264,8 +283,19 @@ class CacheStorageCacheTest : public testing::Test {
base::RunLoop().RunUntilIdle();
blob_storage_context_ = blob_storage_context->context();
+ if (!MemoryOnly())
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+
+ quota_policy_ = new MockSpecialStoragePolicy;
+ mock_quota_manager_ = new MockQuotaManager(
+ MemoryOnly() /* is incognito */, temp_dir_.path(),
+ base::ThreadTaskRunnerHandle::Get().get(),
+ base::ThreadTaskRunnerHandle::Get().get(), quota_policy_.get());
+ mock_quota_manager_->SetQuota(GURL(kOrigin), storage::kStorageTypeTemporary,
+ 1024 * 1024 * 100);
+
quota_manager_proxy_ = new MockQuotaManagerProxy(
- nullptr, base::ThreadTaskRunnerHandle::Get().get());
+ mock_quota_manager_.get(), base::ThreadTaskRunnerHandle::Get().get());
url_request_job_factory_.reset(new net::URLRequestJobFactoryImpl);
url_request_job_factory_->SetProtocolHandler(
@@ -278,13 +308,10 @@ class CacheStorageCacheTest : public testing::Test {
CreateRequests(blob_storage_context);
- if (!MemoryOnly())
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- base::FilePath path = MemoryOnly() ? base::FilePath() : temp_dir_.path();
-
cache_ = make_scoped_refptr(new TestCacheStorageCache(
- GURL("http://example.com"), path, browser_context_.GetRequestContext(),
- quota_manager_proxy_, blob_storage_context->context()->AsWeakPtr()));
+ GURL(kOrigin), kCacheName, temp_dir_.path(),
+ browser_context_.GetRequestContext(), quota_manager_proxy_,
+ blob_storage_context->context()->AsWeakPtr()));
}
void TearDown() override {
@@ -299,6 +326,9 @@ class CacheStorageCacheTest : public testing::Test {
body_request_ =
ServiceWorkerFetchRequest(GURL("http://example.com/body.html"), "GET",
headers, Referrer(), false);
+ body_request_with_query_ = ServiceWorkerFetchRequest(
+ GURL("http://example.com/body.html?query=test"), "GET", headers,
+ Referrer(), false);
no_body_request_ =
ServiceWorkerFetchRequest(GURL("http://example.com/no_body.html"),
"GET", headers, Referrer(), false);
@@ -318,12 +348,24 @@ class CacheStorageCacheTest : public testing::Test {
GURL("http://example.com/body.html"), 200, "OK",
blink::WebServiceWorkerResponseTypeDefault, headers,
blob_handle_->uuid(), expected_blob_data_.size(), GURL(),
- blink::WebServiceWorkerResponseErrorUnknown);
+ blink::WebServiceWorkerResponseErrorUnknown, base::Time::Now(),
+ false /* is_in_cache_storage */,
+ std::string() /* cache_storage_cache_name */);
+
+ body_response_with_query_ = ServiceWorkerResponse(
+ GURL("http://example.com/body.html?query=test"), 200, "OK",
+ blink::WebServiceWorkerResponseTypeDefault, headers,
+ blob_handle_->uuid(), expected_blob_data_.size(), GURL(),
+ blink::WebServiceWorkerResponseErrorUnknown, base::Time::Now(),
+ false /* is_in_cache_storage */,
+ std::string() /* cache_storage_cache_name */);
no_body_response_ = ServiceWorkerResponse(
GURL("http://example.com/no_body.html"), 200, "OK",
blink::WebServiceWorkerResponseTypeDefault, headers, "", 0, GURL(),
- blink::WebServiceWorkerResponseErrorUnknown);
+ blink::WebServiceWorkerResponseErrorUnknown, base::Time::Now(),
+ false /* is_in_cache_storage */,
+ std::string() /* cache_storage_cache_name */);
}
scoped_ptr<ServiceWorkerFetchRequest> CopyFetchRequest(
@@ -372,20 +414,33 @@ class CacheStorageCacheTest : public testing::Test {
return callback_error_ == CACHE_STORAGE_OK;
}
- bool MatchAll(scoped_ptr<CacheStorageCache::Responses>* responses,
+ bool MatchAll(const ServiceWorkerFetchRequest& request,
+ const CacheStorageCacheQueryParams& match_params,
+ scoped_ptr<CacheStorageCache::Responses>* responses,
scoped_ptr<CacheStorageCache::BlobDataHandles>* body_handles) {
base::RunLoop loop;
- cache_->MatchAll(base::Bind(
- &CacheStorageCacheTest::ResponsesAndErrorCallback,
- base::Unretained(this), loop.QuitClosure(), responses, body_handles));
+ cache_->MatchAll(
+ CopyFetchRequest(request), match_params,
+ base::Bind(&CacheStorageCacheTest::ResponsesAndErrorCallback,
+ base::Unretained(this), loop.QuitClosure(), responses,
+ body_handles));
loop.Run();
return callback_error_ == CACHE_STORAGE_OK;
}
- bool Delete(const ServiceWorkerFetchRequest& request) {
+ bool MatchAll(scoped_ptr<CacheStorageCache::Responses>* responses,
+ scoped_ptr<CacheStorageCache::BlobDataHandles>* body_handles) {
+ return MatchAll(ServiceWorkerFetchRequest(), CacheStorageCacheQueryParams(),
+ responses, body_handles);
+ }
+
+ bool Delete(const ServiceWorkerFetchRequest& request,
+ const CacheStorageCacheQueryParams& match_params =
+ CacheStorageCacheQueryParams()) {
CacheStorageBatchOperation operation;
operation.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_DELETE;
operation.request = request;
+ operation.match_params = match_params;
CacheStorageError error =
BatchOperation(std::vector<CacheStorageBatchOperation>(1, operation));
@@ -413,6 +468,32 @@ class CacheStorageCacheTest : public testing::Test {
return callback_closed_;
}
+ int64_t Size() {
+ // Storage notification happens after an operation completes. Let the any
+ // notifications complete before calling Size.
+ base::RunLoop().RunUntilIdle();
+
+ base::RunLoop run_loop;
+ bool callback_called = false;
+ cache_->Size(base::Bind(&CacheStorageCacheTest::SizeCallback,
+ base::Unretained(this), &run_loop,
+ &callback_called));
+ run_loop.Run();
+ EXPECT_TRUE(callback_called);
+ return callback_size_;
+ }
+
+ int64_t GetSizeThenClose() {
+ base::RunLoop run_loop;
+ bool callback_called = false;
+ cache_->GetSizeThenClose(base::Bind(&CacheStorageCacheTest::SizeCallback,
+ base::Unretained(this), &run_loop,
+ &callback_called));
+ run_loop.Run();
+ EXPECT_TRUE(callback_called);
+ return callback_size_;
+ }
+
void RequestsCallback(base::RunLoop* run_loop,
CacheStorageError error,
scoped_ptr<CacheStorageCache::Requests> requests) {
@@ -477,6 +558,15 @@ class CacheStorageCacheTest : public testing::Test {
run_loop->Quit();
}
+ void SizeCallback(base::RunLoop* run_loop,
+ bool* callback_called,
+ int64_t size) {
+ *callback_called = true;
+ callback_size_ = size;
+ if (run_loop)
+ run_loop->Quit();
+ }
+
bool VerifyKeys(const std::vector<std::string>& expected_keys) {
if (expected_keys.size() != callback_strings_.size())
return false;
@@ -514,6 +604,8 @@ class CacheStorageCacheTest : public testing::Test {
TestBrowserContext browser_context_;
TestBrowserThreadBundle browser_thread_bundle_;
scoped_ptr<net::URLRequestJobFactoryImpl> url_request_job_factory_;
+ scoped_refptr<MockSpecialStoragePolicy> quota_policy_;
+ scoped_refptr<MockQuotaManager> mock_quota_manager_;
scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
storage::BlobStorageContext* blob_storage_context_;
@@ -521,16 +613,19 @@ class CacheStorageCacheTest : public testing::Test {
ServiceWorkerFetchRequest body_request_;
ServiceWorkerResponse body_response_;
+ ServiceWorkerFetchRequest body_request_with_query_;
+ ServiceWorkerResponse body_response_with_query_;
ServiceWorkerFetchRequest no_body_request_;
ServiceWorkerResponse no_body_response_;
scoped_ptr<storage::BlobDataHandle> blob_handle_;
std::string expected_blob_data_;
- CacheStorageError callback_error_;
+ CacheStorageError callback_error_ = CACHE_STORAGE_OK;
scoped_ptr<ServiceWorkerResponse> callback_response_;
scoped_ptr<storage::BlobDataHandle> callback_response_data_;
std::vector<std::string> callback_strings_;
- bool callback_closed_;
+ bool callback_closed_ = false;
+ int64_t callback_size_ = 0;
};
class CacheStorageCacheTestP : public CacheStorageCacheTest,
@@ -538,12 +633,6 @@ class CacheStorageCacheTestP : public CacheStorageCacheTest,
bool MemoryOnly() override { return !GetParam(); }
};
-class CacheStorageCacheMemoryOnlyTest
- : public CacheStorageCacheTest,
- public testing::WithParamInterface<bool> {
- bool MemoryOnly() override { return true; }
-};
-
TEST_P(CacheStorageCacheTestP, PutNoBody) {
EXPECT_TRUE(Put(no_body_request_, no_body_response_));
}
@@ -666,14 +755,16 @@ TEST_P(CacheStorageCacheTestP, PutReplcaceInBatch) {
TEST_P(CacheStorageCacheTestP, MatchNoBody) {
EXPECT_TRUE(Put(no_body_request_, no_body_response_));
EXPECT_TRUE(Match(no_body_request_));
- EXPECT_TRUE(ResponseMetadataEqual(no_body_response_, *callback_response_));
+ EXPECT_TRUE(ResponseMetadataEqual(SetCacheName(no_body_response_),
+ *callback_response_));
EXPECT_FALSE(callback_response_data_);
}
TEST_P(CacheStorageCacheTestP, MatchBody) {
EXPECT_TRUE(Put(body_request_, body_response_));
EXPECT_TRUE(Match(body_request_));
- EXPECT_TRUE(ResponseMetadataEqual(body_response_, *callback_response_));
+ EXPECT_TRUE(
+ ResponseMetadataEqual(SetCacheName(body_response_), *callback_response_));
EXPECT_TRUE(
ResponseBodiesEqual(expected_blob_data_, *callback_response_data_));
}
@@ -694,7 +785,8 @@ TEST_P(CacheStorageCacheTestP, MatchAll_NoBody) {
EXPECT_TRUE(MatchAll(&responses, &body_handles));
ASSERT_EQ(1u, responses->size());
- EXPECT_TRUE(ResponseMetadataEqual(no_body_response_, responses->at(0)));
+ EXPECT_TRUE(
+ ResponseMetadataEqual(SetCacheName(no_body_response_), responses->at(0)));
EXPECT_TRUE(body_handles->empty());
}
@@ -707,7 +799,8 @@ TEST_P(CacheStorageCacheTestP, MatchAll_Body) {
ASSERT_EQ(1u, responses->size());
ASSERT_EQ(1u, body_handles->size());
- EXPECT_TRUE(ResponseMetadataEqual(body_response_, responses->at(0)));
+ EXPECT_TRUE(
+ ResponseMetadataEqual(SetCacheName(body_response_), responses->at(0)));
EXPECT_TRUE(ResponseBodiesEqual(expected_blob_data_, body_handles->at(0)));
}
@@ -725,10 +818,12 @@ TEST_P(CacheStorageCacheTestP, MatchAll_TwoResponsesThenOne) {
std::set<std::string> matched_set;
for (const ServiceWorkerResponse& response : *responses) {
if (response.url.spec() == "http://example.com/no_body.html") {
- EXPECT_TRUE(ResponseMetadataEqual(no_body_response_, response));
+ EXPECT_TRUE(
+ ResponseMetadataEqual(SetCacheName(no_body_response_), response));
matched_set.insert(response.url.spec());
} else if (response.url.spec() == "http://example.com/body.html") {
- EXPECT_TRUE(ResponseMetadataEqual(body_response_, response));
+ EXPECT_TRUE(
+ ResponseMetadataEqual(SetCacheName(body_response_), response));
EXPECT_TRUE(
ResponseBodiesEqual(expected_blob_data_, body_handles->at(0)));
matched_set.insert(response.url.spec());
@@ -743,10 +838,41 @@ TEST_P(CacheStorageCacheTestP, MatchAll_TwoResponsesThenOne) {
EXPECT_TRUE(MatchAll(&responses, &body_handles));
ASSERT_EQ(1u, responses->size());
- EXPECT_TRUE(ResponseMetadataEqual(no_body_response_, responses->at(0)));
+ EXPECT_TRUE(
+ ResponseMetadataEqual(SetCacheName(no_body_response_), responses->at(0)));
EXPECT_TRUE(body_handles->empty());
}
+TEST_P(CacheStorageCacheTestP, MatchAll_IgnoreSearch) {
+ EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(body_request_with_query_, body_response_with_query_));
+ EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+
+ scoped_ptr<CacheStorageCache::Responses> responses;
+ scoped_ptr<CacheStorageCache::BlobDataHandles> body_handles;
+ CacheStorageCacheQueryParams match_params;
+ match_params.ignore_search = true;
+ EXPECT_TRUE(MatchAll(body_request_, match_params, &responses, &body_handles));
+
+ ASSERT_EQ(2u, responses->size());
+ ASSERT_EQ(2u, body_handles->size());
+
+ // Order of returned responses is not guaranteed.
+ std::set<std::string> matched_set;
+ for (const ServiceWorkerResponse& response : *responses) {
+ if (response.url.spec() == "http://example.com/body.html?query=test") {
+ EXPECT_TRUE(ResponseMetadataEqual(SetCacheName(body_response_with_query_),
+ response));
+ matched_set.insert(response.url.spec());
+ } else if (response.url.spec() == "http://example.com/body.html") {
+ EXPECT_TRUE(
+ ResponseMetadataEqual(SetCacheName(body_response_), response));
+ matched_set.insert(response.url.spec());
+ }
+ }
+ EXPECT_EQ(2u, matched_set.size());
+}
+
TEST_P(CacheStorageCacheTestP, Vary) {
body_request_.headers["vary_foo"] = "foo";
body_response_.headers["vary"] = "vary_foo";
@@ -863,6 +989,61 @@ TEST_P(CacheStorageCacheTestP, DeleteBody) {
EXPECT_TRUE(Delete(body_request_));
}
+TEST_P(CacheStorageCacheTestP, DeleteWithIgnoreSearchTrue) {
+ EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(body_request_with_query_, body_response_with_query_));
+
+ EXPECT_TRUE(Keys());
+ EXPECT_EQ(3u, callback_strings_.size());
+ std::vector<std::string> expected_keys;
+ expected_keys.push_back(no_body_request_.url.spec());
+ expected_keys.push_back(body_request_.url.spec());
+ expected_keys.push_back(body_request_with_query_.url.spec());
+ EXPECT_TRUE(VerifyKeys(expected_keys));
+
+ // The following delete operation will remove both of body_request_ and
+ // body_request_with_query_ from cache storage.
+ CacheStorageCacheQueryParams match_params;
+ match_params.ignore_search = true;
+ EXPECT_TRUE(Delete(body_request_with_query_, match_params));
+
+ EXPECT_TRUE(Keys());
+ EXPECT_EQ(1u, callback_strings_.size());
+ expected_keys.clear();
+ expected_keys.push_back(no_body_request_.url.spec());
+ EXPECT_TRUE(VerifyKeys(expected_keys));
+}
+
+TEST_P(CacheStorageCacheTestP, DeleteWithIgnoreSearchFalse) {
+ EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ EXPECT_TRUE(Put(body_request_, body_response_));
+ EXPECT_TRUE(Put(body_request_with_query_, body_response_with_query_));
+
+ EXPECT_TRUE(Keys());
+ EXPECT_EQ(3u, callback_strings_.size());
+ std::vector<std::string> expected_keys;
+ expected_keys.push_back(no_body_request_.url.spec());
+ expected_keys.push_back(body_request_.url.spec());
+ expected_keys.push_back(body_request_with_query_.url.spec());
+ EXPECT_TRUE(VerifyKeys(expected_keys));
+
+ // Default value of ignore_search is false.
+ CacheStorageCacheQueryParams match_params;
+ match_params.ignore_search = false;
+ EXPECT_EQ(match_params.ignore_search,
+ CacheStorageCacheQueryParams().ignore_search);
+
+ EXPECT_TRUE(Delete(body_request_with_query_, match_params));
+
+ EXPECT_TRUE(Keys());
+ EXPECT_EQ(2u, callback_strings_.size());
+ expected_keys.clear();
+ expected_keys.push_back(no_body_request_.url.spec());
+ expected_keys.push_back(body_request_.url.spec());
+ EXPECT_TRUE(VerifyKeys(expected_keys));
+}
+
TEST_P(CacheStorageCacheTestP, QuickStressNoBody) {
for (int i = 0; i < 100; ++i) {
EXPECT_FALSE(Match(no_body_request_));
@@ -895,7 +1076,9 @@ TEST_F(CacheStorageCacheTest, CaselessServiceWorkerResponseHeaders) {
ServiceWorkerResponse response(GURL("http://www.example.com"), 200, "OK",
blink::WebServiceWorkerResponseTypeDefault,
ServiceWorkerHeaderMap(), "", 0, GURL(),
- blink::WebServiceWorkerResponseErrorUnknown);
+ blink::WebServiceWorkerResponseErrorUnknown,
+ base::Time(), false /* is_in_cache_storage */,
+ std::string() /* cache_storage_cache_name */);
response.headers["content-type"] = "foo";
response.headers["Content-Type"] = "bar";
EXPECT_EQ("bar", response.headers["content-type"]);
@@ -916,46 +1099,95 @@ TEST_P(CacheStorageCacheTestP, QuotaManagerModified) {
EXPECT_EQ(0, quota_manager_proxy_->notify_storage_modified_count());
EXPECT_TRUE(Put(no_body_request_, no_body_response_));
+ // Storage notification happens after the operation returns, so continue the
+ // event loop.
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, quota_manager_proxy_->notify_storage_modified_count());
EXPECT_LT(0, quota_manager_proxy_->last_notified_delta());
int64_t sum_delta = quota_manager_proxy_->last_notified_delta();
EXPECT_TRUE(Put(body_request_, body_response_));
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(2, quota_manager_proxy_->notify_storage_modified_count());
EXPECT_LT(sum_delta, quota_manager_proxy_->last_notified_delta());
sum_delta += quota_manager_proxy_->last_notified_delta();
EXPECT_TRUE(Delete(body_request_));
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(3, quota_manager_proxy_->notify_storage_modified_count());
sum_delta += quota_manager_proxy_->last_notified_delta();
EXPECT_TRUE(Delete(no_body_request_));
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(4, quota_manager_proxy_->notify_storage_modified_count());
sum_delta += quota_manager_proxy_->last_notified_delta();
EXPECT_EQ(0, sum_delta);
}
-TEST_F(CacheStorageCacheMemoryOnlyTest, MemoryBackedSize) {
- EXPECT_EQ(0, cache_->MemoryBackedSize());
+TEST_P(CacheStorageCacheTestP, PutObeysQuotaLimits) {
+ mock_quota_manager_->SetQuota(GURL(kOrigin), storage::kStorageTypeTemporary,
+ 0);
+ EXPECT_FALSE(Put(no_body_request_, no_body_response_));
+ EXPECT_EQ(CACHE_STORAGE_ERROR_QUOTA_EXCEEDED, callback_error_);
+}
+
+TEST_P(CacheStorageCacheTestP, Size) {
+ EXPECT_EQ(0, Size());
EXPECT_TRUE(Put(no_body_request_, no_body_response_));
- EXPECT_LT(0, cache_->MemoryBackedSize());
- int64_t no_body_size = cache_->MemoryBackedSize();
+ EXPECT_LT(0, Size());
+ int64_t no_body_size = Size();
EXPECT_TRUE(Delete(no_body_request_));
- EXPECT_EQ(0, cache_->MemoryBackedSize());
+ EXPECT_EQ(0, Size());
EXPECT_TRUE(Put(body_request_, body_response_));
- EXPECT_LT(no_body_size, cache_->MemoryBackedSize());
+ EXPECT_LT(no_body_size, Size());
EXPECT_TRUE(Delete(body_request_));
- EXPECT_EQ(0, cache_->MemoryBackedSize());
+ EXPECT_EQ(0, Size());
}
-TEST_F(CacheStorageCacheTest, MemoryBackedSizePersistent) {
- EXPECT_EQ(0, cache_->MemoryBackedSize());
- EXPECT_TRUE(Put(no_body_request_, no_body_response_));
- EXPECT_EQ(0, cache_->MemoryBackedSize());
+TEST_P(CacheStorageCacheTestP, SizeOperationsArePrioritized) {
+ // Test that pending size operations (those waiting for initialization) run
+ // before other scheduler operations.
+ cache_->set_delay_backend_creation(true); // Delay cache initialization
+
+ CacheStorageBatchOperation operation;
+ operation.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
+ operation.request = body_request_;
+ operation.response = body_response_;
+
+ callback_error_ = CACHE_STORAGE_ERROR_NOT_FOUND;
+ base::RunLoop run_loop;
+ // Start a put operation that blocks on initialization.
+ cache_->BatchOperation(std::vector<CacheStorageBatchOperation>(1, operation),
+ base::Bind(&CacheStorageCacheTest::ErrorTypeCallback,
+ base::Unretained(this), &run_loop));
+
+ // Next start a size operation that also blocks on initialization.
+ bool size_callback_called = false;
+ cache_->Size(base::Bind(&CacheStorageCacheTest::SizeCallback,
+ base::Unretained(this), nullptr,
+ &size_callback_called));
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(size_callback_called);
+ EXPECT_EQ(CACHE_STORAGE_ERROR_NOT_FOUND, callback_error_);
+
+ // Finish initialization. The Size operation should complete before Put gets
+ // to run as Size has priority. See crbug.com/605663.
+ cache_->ContinueCreateBackend();
+ run_loop.Run();
+ EXPECT_TRUE(size_callback_called);
+ EXPECT_EQ(CACHE_STORAGE_OK, callback_error_);
+}
+
+TEST_P(CacheStorageCacheTestP, GetSizeThenClose) {
+ EXPECT_TRUE(Put(body_request_, body_response_));
+ int64_t cache_size = Size();
+ EXPECT_EQ(cache_size, GetSizeThenClose());
+ VerifyAllOpsFail();
}
TEST_P(CacheStorageCacheTestP, OpsFailOnClosedBackendNeverCreated) {
diff --git a/chromium/content/browser/cache_storage/cache_storage_context_impl.cc b/chromium/content/browser/cache_storage/cache_storage_context_impl.cc
index 83aa12d6cdc..e58d790939c 100644
--- a/chromium/content/browser/cache_storage/cache_storage_context_impl.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_context_impl.cc
@@ -28,8 +28,7 @@ CacheStorageContextImpl::~CacheStorageContextImpl() {
void CacheStorageContextImpl::Init(
const base::FilePath& user_data_directory,
- storage::QuotaManagerProxy* quota_manager_proxy,
- storage::SpecialStoragePolicy* special_storage_policy) {
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
is_incognito_ = user_data_directory.empty();
@@ -45,7 +44,7 @@ void CacheStorageContextImpl::Init(
// TODO: Fix the tests to let the quota manager initialize normally.
if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
CreateCacheStorageManager(user_data_directory, cache_task_runner,
- quota_manager_proxy, special_storage_policy);
+ std::move(quota_manager_proxy));
return;
}
@@ -53,8 +52,7 @@ void CacheStorageContextImpl::Init(
BrowserThread::IO, FROM_HERE,
base::Bind(&CacheStorageContextImpl::CreateCacheStorageManager, this,
user_data_directory, cache_task_runner,
- make_scoped_refptr(quota_manager_proxy),
- make_scoped_refptr(special_storage_policy)));
+ std::move(quota_manager_proxy)));
}
void CacheStorageContextImpl::Shutdown() {
@@ -103,15 +101,13 @@ void CacheStorageContextImpl::DeleteForOrigin(const GURL& origin) {
void CacheStorageContextImpl::CreateCacheStorageManager(
const base::FilePath& user_data_directory,
- const scoped_refptr<base::SequencedTaskRunner>& cache_task_runner,
- storage::QuotaManagerProxy* quota_manager_proxy,
- storage::SpecialStoragePolicy* special_storage_policy) {
+ scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!cache_manager_);
- cache_manager_ =
- CacheStorageManager::Create(user_data_directory, cache_task_runner.get(),
- make_scoped_refptr(quota_manager_proxy));
+ cache_manager_ = CacheStorageManager::Create(
+ user_data_directory, cache_task_runner, std::move(quota_manager_proxy));
}
void CacheStorageContextImpl::ShutdownOnIO() {
diff --git a/chromium/content/browser/cache_storage/cache_storage_context_impl.h b/chromium/content/browser/cache_storage/cache_storage_context_impl.h
index d72babf1d37..f404fa86d31 100644
--- a/chromium/content/browser/cache_storage/cache_storage_context_impl.h
+++ b/chromium/content/browser/cache_storage/cache_storage_context_impl.h
@@ -44,8 +44,7 @@ class CONTENT_EXPORT CacheStorageContextImpl
// Init and Shutdown are for use on the UI thread when the profile,
// storagepartition is being setup and torn down.
void Init(const base::FilePath& user_data_directory,
- storage::QuotaManagerProxy* quota_manager_proxy,
- storage::SpecialStoragePolicy* special_storage_policy);
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy);
void Shutdown();
// Only callable on the IO thread.
@@ -73,9 +72,8 @@ class CONTENT_EXPORT CacheStorageContextImpl
private:
void CreateCacheStorageManager(
const base::FilePath& user_data_directory,
- const scoped_refptr<base::SequencedTaskRunner>& cache_task_runner,
- storage::QuotaManagerProxy* quota_manager_proxy,
- storage::SpecialStoragePolicy* special_storage_policy);
+ scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy);
void ShutdownOnIO();
diff --git a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc
index 073f57d8027..f371be943dc 100644
--- a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.cc
@@ -22,6 +22,8 @@
#include "content/public/common/origin_util.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerCacheError.h"
+#include "url/gurl.h"
+#include "url/origin.h"
namespace content {
@@ -43,13 +45,17 @@ blink::WebServiceWorkerCacheError ToWebServiceWorkerCacheError(
return blink::WebServiceWorkerCacheErrorNotFound;
case CACHE_STORAGE_ERROR_NOT_FOUND:
return blink::WebServiceWorkerCacheErrorNotFound;
+ case CACHE_STORAGE_ERROR_QUOTA_EXCEEDED:
+ return blink::WebServiceWorkerCacheErrorQuotaExceeded;
+ case CACHE_STORAGE_ERROR_CACHE_NAME_NOT_FOUND:
+ return blink::WebServiceWorkerCacheErrorCacheNameNotFound;
}
NOTREACHED();
return blink::WebServiceWorkerCacheErrorNotImplemented;
}
-bool OriginCanAccessCacheStorage(const GURL& url) {
- return IsOriginSecure(url);
+bool OriginCanAccessCacheStorage(const url::Origin& origin) {
+ return !origin.unique() && IsOriginSecure(GURL(origin.Serialize()));
}
} // namespace
@@ -67,7 +73,7 @@ void CacheStorageDispatcherHost::Init(CacheStorageContextImpl* context) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&CacheStorageDispatcherHost::CreateCacheListener, this,
- make_scoped_refptr(context)));
+ base::RetainedRef(context)));
}
void CacheStorageDispatcherHost::OnDestruct() const {
@@ -110,7 +116,7 @@ void CacheStorageDispatcherHost::CreateCacheListener(
void CacheStorageDispatcherHost::OnCacheStorageHas(
int thread_id,
int request_id,
- const GURL& origin,
+ const url::Origin& origin,
const base::string16& cache_name) {
TRACE_EVENT0("CacheStorage", "CacheStorageDispatcherHost::OnCacheStorageHas");
if (!OriginCanAccessCacheStorage(origin)) {
@@ -118,7 +124,7 @@ void CacheStorageDispatcherHost::OnCacheStorageHas(
return;
}
context_->cache_manager()->HasCache(
- origin, base::UTF16ToUTF8(cache_name),
+ GURL(origin.Serialize()), base::UTF16ToUTF8(cache_name),
base::Bind(&CacheStorageDispatcherHost::OnCacheStorageHasCallback, this,
thread_id, request_id));
}
@@ -126,7 +132,7 @@ void CacheStorageDispatcherHost::OnCacheStorageHas(
void CacheStorageDispatcherHost::OnCacheStorageOpen(
int thread_id,
int request_id,
- const GURL& origin,
+ const url::Origin& origin,
const base::string16& cache_name) {
TRACE_EVENT0("CacheStorage",
"CacheStorageDispatcherHost::OnCacheStorageOpen");
@@ -135,7 +141,7 @@ void CacheStorageDispatcherHost::OnCacheStorageOpen(
return;
}
context_->cache_manager()->OpenCache(
- origin, base::UTF16ToUTF8(cache_name),
+ GURL(origin.Serialize()), base::UTF16ToUTF8(cache_name),
base::Bind(&CacheStorageDispatcherHost::OnCacheStorageOpenCallback, this,
thread_id, request_id));
}
@@ -143,7 +149,7 @@ void CacheStorageDispatcherHost::OnCacheStorageOpen(
void CacheStorageDispatcherHost::OnCacheStorageDelete(
int thread_id,
int request_id,
- const GURL& origin,
+ const url::Origin& origin,
const base::string16& cache_name) {
TRACE_EVENT0("CacheStorage",
"CacheStorageDispatcherHost::OnCacheStorageDelete");
@@ -152,14 +158,14 @@ void CacheStorageDispatcherHost::OnCacheStorageDelete(
return;
}
context_->cache_manager()->DeleteCache(
- origin, base::UTF16ToUTF8(cache_name),
+ GURL(origin.Serialize()), base::UTF16ToUTF8(cache_name),
base::Bind(&CacheStorageDispatcherHost::OnCacheStorageDeleteCallback,
this, thread_id, request_id));
}
void CacheStorageDispatcherHost::OnCacheStorageKeys(int thread_id,
int request_id,
- const GURL& origin) {
+ const url::Origin& origin) {
TRACE_EVENT0("CacheStorage",
"CacheStorageDispatcherHost::OnCacheStorageKeys");
if (!OriginCanAccessCacheStorage(origin)) {
@@ -167,7 +173,7 @@ void CacheStorageDispatcherHost::OnCacheStorageKeys(int thread_id,
return;
}
context_->cache_manager()->EnumerateCaches(
- origin,
+ GURL(origin.Serialize()),
base::Bind(&CacheStorageDispatcherHost::OnCacheStorageKeysCallback, this,
thread_id, request_id));
}
@@ -175,7 +181,7 @@ void CacheStorageDispatcherHost::OnCacheStorageKeys(int thread_id,
void CacheStorageDispatcherHost::OnCacheStorageMatch(
int thread_id,
int request_id,
- const GURL& origin,
+ const url::Origin& origin,
const ServiceWorkerFetchRequest& request,
const CacheStorageCacheQueryParams& match_params) {
TRACE_EVENT0("CacheStorage",
@@ -191,13 +197,13 @@ void CacheStorageDispatcherHost::OnCacheStorageMatch(
if (match_params.cache_name.empty()) {
context_->cache_manager()->MatchAllCaches(
- origin, std::move(scoped_request),
+ GURL(origin.Serialize()), std::move(scoped_request),
base::Bind(&CacheStorageDispatcherHost::OnCacheStorageMatchCallback,
this, thread_id, request_id));
return;
}
context_->cache_manager()->MatchCache(
- origin, base::UTF16ToUTF8(match_params.cache_name),
+ GURL(origin.Serialize()), base::UTF16ToUTF8(match_params.cache_name),
std::move(scoped_request),
base::Bind(&CacheStorageDispatcherHost::OnCacheStorageMatchCallback, this,
thread_id, request_id));
@@ -242,6 +248,7 @@ void CacheStorageDispatcherHost::OnCacheMatchAll(
scoped_refptr<CacheStorageCache> cache = it->second;
if (request.url.is_empty()) {
cache->MatchAll(
+ scoped_ptr<ServiceWorkerFetchRequest>(), match_params,
base::Bind(&CacheStorageDispatcherHost::OnCacheMatchAllCallback, this,
thread_id, request_id, cache));
return;
@@ -251,6 +258,13 @@ void CacheStorageDispatcherHost::OnCacheMatchAll(
new ServiceWorkerFetchRequest(request.url, request.method,
request.headers, request.referrer,
request.is_reload));
+ if (match_params.ignore_search) {
+ cache->MatchAll(
+ std::move(scoped_request), match_params,
+ base::Bind(&CacheStorageDispatcherHost::OnCacheMatchAllCallback, this,
+ thread_id, request_id, cache));
+ return;
+ }
cache->Match(
std::move(scoped_request),
base::Bind(&CacheStorageDispatcherHost::OnCacheMatchAllCallbackAdapter,
@@ -322,14 +336,14 @@ void CacheStorageDispatcherHost::OnCacheStorageHasCallback(
void CacheStorageDispatcherHost::OnCacheStorageOpenCallback(
int thread_id,
int request_id,
- const scoped_refptr<CacheStorageCache>& cache,
+ scoped_refptr<CacheStorageCache> cache,
CacheStorageError error) {
if (error != CACHE_STORAGE_OK) {
Send(new CacheStorageMsg_CacheStorageOpenError(
thread_id, request_id, ToWebServiceWorkerCacheError(error)));
return;
}
- CacheID cache_id = StoreCacheReference(cache);
+ CacheID cache_id = StoreCacheReference(std::move(cache));
Send(new CacheStorageMsg_CacheStorageOpenSuccess(thread_id, request_id,
cache_id));
}
@@ -388,7 +402,7 @@ void CacheStorageDispatcherHost::OnCacheStorageMatchCallback(
void CacheStorageDispatcherHost::OnCacheMatchCallback(
int thread_id,
int request_id,
- const scoped_refptr<CacheStorageCache>& cache,
+ scoped_refptr<CacheStorageCache> cache,
CacheStorageError error,
scoped_ptr<ServiceWorkerResponse> response,
scoped_ptr<storage::BlobDataHandle> blob_data_handle) {
@@ -407,7 +421,7 @@ void CacheStorageDispatcherHost::OnCacheMatchCallback(
void CacheStorageDispatcherHost::OnCacheMatchAllCallbackAdapter(
int thread_id,
int request_id,
- const scoped_refptr<CacheStorageCache>& cache,
+ scoped_refptr<CacheStorageCache> cache,
CacheStorageError error,
scoped_ptr<ServiceWorkerResponse> response,
scoped_ptr<storage::BlobDataHandle> blob_data_handle) {
@@ -421,14 +435,14 @@ void CacheStorageDispatcherHost::OnCacheMatchAllCallbackAdapter(
if (blob_data_handle)
blob_data_handles->push_back(*blob_data_handle);
}
- OnCacheMatchAllCallback(thread_id, request_id, cache, error,
+ OnCacheMatchAllCallback(thread_id, request_id, std::move(cache), error,
std::move(responses), std::move(blob_data_handles));
}
void CacheStorageDispatcherHost::OnCacheMatchAllCallback(
int thread_id,
int request_id,
- const scoped_refptr<CacheStorageCache>& cache,
+ scoped_refptr<CacheStorageCache> cache,
CacheStorageError error,
scoped_ptr<CacheStorageCache::Responses> responses,
scoped_ptr<CacheStorageCache::BlobDataHandles> blob_data_handles) {
@@ -448,7 +462,7 @@ void CacheStorageDispatcherHost::OnCacheMatchAllCallback(
void CacheStorageDispatcherHost::OnCacheKeysCallback(
int thread_id,
int request_id,
- const scoped_refptr<CacheStorageCache>& cache,
+ scoped_refptr<CacheStorageCache> cache,
CacheStorageError error,
scoped_ptr<CacheStorageCache::Requests> requests) {
if (error != CACHE_STORAGE_OK) {
@@ -472,7 +486,7 @@ void CacheStorageDispatcherHost::OnCacheKeysCallback(
void CacheStorageDispatcherHost::OnCacheBatchCallback(
int thread_id,
int request_id,
- const scoped_refptr<CacheStorageCache>& cache,
+ scoped_refptr<CacheStorageCache> cache,
CacheStorageError error) {
if (error != CACHE_STORAGE_OK) {
Send(new CacheStorageMsg_CacheBatchError(
@@ -485,9 +499,9 @@ void CacheStorageDispatcherHost::OnCacheBatchCallback(
CacheStorageDispatcherHost::CacheID
CacheStorageDispatcherHost::StoreCacheReference(
- const scoped_refptr<CacheStorageCache>& cache) {
+ scoped_refptr<CacheStorageCache> cache) {
int cache_id = next_cache_id_++;
- id_to_cache_map_[cache_id] = cache;
+ id_to_cache_map_[cache_id] = std::move(cache);
return cache_id;
}
diff --git a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h
index 77435096db2..14cfe301efb 100644
--- a/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h
+++ b/chromium/content/browser/cache_storage/cache_storage_dispatcher_host.h
@@ -13,6 +13,10 @@
#include "content/browser/cache_storage/cache_storage.h"
#include "content/public/browser/browser_message_filter.h"
+namespace url {
+class Origin;
+}
+
namespace content {
class CacheStorageContextImpl;
@@ -49,20 +53,22 @@ class CONTENT_EXPORT CacheStorageDispatcherHost : public BrowserMessageFilter {
// The message receiver functions for the CacheStorage API:
void OnCacheStorageHas(int thread_id,
int request_id,
- const GURL& origin,
+ const url::Origin& origin,
const base::string16& cache_name);
void OnCacheStorageOpen(int thread_id,
int request_id,
- const GURL& origin,
+ const url::Origin& origin,
const base::string16& cache_name);
void OnCacheStorageDelete(int thread_id,
int request_id,
- const GURL& origin,
+ const url::Origin& origin,
const base::string16& cache_name);
- void OnCacheStorageKeys(int thread_id, int request_id, const GURL& origin);
+ void OnCacheStorageKeys(int thread_id,
+ int request_id,
+ const url::Origin& origin);
void OnCacheStorageMatch(int thread_id,
int request_id,
- const GURL& origin,
+ const url::Origin& origin,
const ServiceWorkerFetchRequest& request,
const CacheStorageCacheQueryParams& match_params);
@@ -91,7 +97,7 @@ class CONTENT_EXPORT CacheStorageDispatcherHost : public BrowserMessageFilter {
CacheStorageError error);
void OnCacheStorageOpenCallback(int thread_id,
int request_id,
- const scoped_refptr<CacheStorageCache>& cache,
+ scoped_refptr<CacheStorageCache> cache,
CacheStorageError error);
void OnCacheStorageDeleteCallback(int thread_id,
int request_id,
@@ -112,21 +118,21 @@ class CONTENT_EXPORT CacheStorageDispatcherHost : public BrowserMessageFilter {
void OnCacheMatchCallback(
int thread_id,
int request_id,
- const scoped_refptr<CacheStorageCache>& cache,
+ scoped_refptr<CacheStorageCache> cache,
CacheStorageError error,
scoped_ptr<ServiceWorkerResponse> response,
scoped_ptr<storage::BlobDataHandle> blob_data_handle);
void OnCacheMatchAllCallbackAdapter(
int thread_id,
int request_id,
- const scoped_refptr<CacheStorageCache>& cache,
+ scoped_refptr<CacheStorageCache> cache,
CacheStorageError error,
scoped_ptr<ServiceWorkerResponse> response,
scoped_ptr<storage::BlobDataHandle> blob_data_handle);
void OnCacheMatchAllCallback(
int thread_id,
int request_id,
- const scoped_refptr<CacheStorageCache>& cache,
+ scoped_refptr<CacheStorageCache> cache,
CacheStorageError error,
scoped_ptr<std::vector<ServiceWorkerResponse>> responses,
scoped_ptr<CacheStorageCache::BlobDataHandles> blob_data_handles);
@@ -137,18 +143,18 @@ class CONTENT_EXPORT CacheStorageDispatcherHost : public BrowserMessageFilter {
const CacheStorageCacheQueryParams& match_params);
void OnCacheKeysCallback(int thread_id,
int request_id,
- const scoped_refptr<CacheStorageCache>& cache,
+ scoped_refptr<CacheStorageCache> cache,
CacheStorageError error,
scoped_ptr<CacheStorageCache::Requests> requests);
void OnCacheBatchCallback(int thread_id,
int request_id,
- const scoped_refptr<CacheStorageCache>& cache,
+ scoped_refptr<CacheStorageCache> cache,
CacheStorageError error);
// Hangs onto a scoped_refptr for the cache if it isn't already doing so.
// Returns a unique cache_id. Call DropCacheReference when the client is done
// with this cache.
- CacheID StoreCacheReference(const scoped_refptr<CacheStorageCache>& cache);
+ CacheID StoreCacheReference(scoped_refptr<CacheStorageCache> cache);
void DropCacheReference(CacheID cache_id);
// Stores blob handles while waiting for acknowledgement of receipt from the
diff --git a/chromium/content/browser/cache_storage/cache_storage_manager.cc b/chromium/content/browser/cache_storage/cache_storage_manager.cc
index cd02deb0a0f..be2c6d7c5b1 100644
--- a/chromium/content/browser/cache_storage/cache_storage_manager.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_manager.cc
@@ -9,6 +9,7 @@
#include <string>
#include <utility>
+#include "base/barrier_closure.h"
#include "base/bind.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
@@ -23,7 +24,7 @@
#include "content/browser/cache_storage/cache_storage_quota_client.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/public/browser/browser_thread.h"
-#include "net/base/net_util.h"
+#include "net/base/url_util.h"
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/common/database/database_identifier.h"
#include "storage/common/quota/quota_status_code.h"
@@ -42,11 +43,16 @@ void DeleteOriginDidDeleteDir(
bool rv) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- callback.Run(rv ? storage::kQuotaStatusOk : storage::kQuotaErrorAbort);
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(callback, rv ? storage::kQuotaStatusOk
+ : storage::kQuotaErrorAbort));
}
-std::set<GURL> ListOriginsOnDisk(base::FilePath root_path) {
- std::set<GURL> origins;
+// Open the various cache directories' index files and extract their origins and
+// last modified times.
+void ListOriginsAndLastModifiedOnTaskRunner(
+ std::vector<CacheStorageUsageInfo>* usages,
+ base::FilePath root_path) {
base::FileEnumerator file_enum(root_path, false /* recursive */,
base::FileEnumerator::DIRECTORIES);
@@ -55,33 +61,28 @@ std::set<GURL> ListOriginsOnDisk(base::FilePath root_path) {
std::string protobuf;
base::ReadFileToString(path.AppendASCII(CacheStorage::kIndexFileName),
&protobuf);
-
CacheStorageIndex index;
if (index.ParseFromString(protobuf)) {
- if (index.has_origin())
- origins.insert(GURL(index.origin()));
+ if (index.has_origin()) {
+ base::File::Info file_info;
+ if (base::GetFileInfo(path, &file_info)) {
+ usages->push_back(CacheStorageUsageInfo(
+ GURL(index.origin()), 0 /* size */, file_info.last_modified));
+ }
+ }
}
}
-
- return origins;
}
-std::vector<CacheStorageUsageInfo> GetAllOriginsUsageOnTaskRunner(
- const base::FilePath root_path) {
- std::vector<CacheStorageUsageInfo> entries;
- const std::set<GURL> origins = ListOriginsOnDisk(root_path);
- entries.reserve(origins.size());
- for (const GURL& origin : origins) {
- base::FilePath path =
- CacheStorageManager::ConstructOriginPath(root_path, origin);
- int64_t size = base::ComputeDirectorySize(path);
- base::File::Info file_info;
- base::Time last_modified;
- if (base::GetFileInfo(path, &file_info))
- last_modified = file_info.last_modified;
- entries.push_back(CacheStorageUsageInfo(origin, size, last_modified));
- }
- return entries;
+std::set<GURL> ListOriginsOnTaskRunner(base::FilePath root_path) {
+ std::vector<CacheStorageUsageInfo> usages;
+ ListOriginsAndLastModifiedOnTaskRunner(&usages, root_path);
+
+ std::set<GURL> out_origins;
+ for (const CacheStorageUsageInfo& usage : usages)
+ out_origins.insert(usage.origin);
+
+ return out_origins;
}
void GetOriginsForHostDidListOrigins(
@@ -93,26 +94,45 @@ void GetOriginsForHostDidListOrigins(
if (host == net::GetHostOrSpecFromURL(origin))
out_origins.insert(origin);
}
- callback.Run(out_origins);
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(callback, out_origins));
}
void EmptyQuotaStatusCallback(storage::QuotaStatusCode code) {}
+void AllOriginSizesReported(
+ scoped_ptr<std::vector<CacheStorageUsageInfo>> usages,
+ const CacheStorageContext::GetUsageInfoCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ base::Bind(callback, *usages));
+}
+
+void OneOriginSizeReported(const base::Closure& callback,
+ CacheStorageUsageInfo* usage,
+ int64_t size) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ usage->total_size_bytes = size;
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
+}
+
} // namespace
// static
scoped_ptr<CacheStorageManager> CacheStorageManager::Create(
const base::FilePath& path,
- const scoped_refptr<base::SequencedTaskRunner>& cache_task_runner,
- const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy) {
+ scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy) {
base::FilePath root_path = path;
if (!path.empty()) {
root_path = path.Append(ServiceWorkerContextCore::kServiceWorkerDirectory)
.AppendASCII("CacheStorage");
}
- return make_scoped_ptr(new CacheStorageManager(root_path, cache_task_runner,
- quota_manager_proxy));
+ return make_scoped_ptr(new CacheStorageManager(
+ root_path, std::move(cache_task_runner), std::move(quota_manager_proxy)));
}
// static
@@ -191,14 +211,14 @@ void CacheStorageManager::MatchAllCaches(
}
void CacheStorageManager::SetBlobParametersForCache(
- const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter,
base::WeakPtr<storage::BlobStorageContext> blob_storage_context) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(cache_storage_map_.empty());
DCHECK(!request_context_getter_ ||
request_context_getter_.get() == request_context_getter.get());
DCHECK(!blob_context_ || blob_context_.get() == blob_storage_context.get());
- request_context_getter_ = request_context_getter;
+ request_context_getter_ = std::move(request_context_getter);
blob_context_ = blob_storage_context;
}
@@ -206,23 +226,54 @@ void CacheStorageManager::GetAllOriginsUsage(
const CacheStorageContext::GetUsageInfoCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ scoped_ptr<std::vector<CacheStorageUsageInfo>> usages(
+ new std::vector<CacheStorageUsageInfo>());
+
if (IsMemoryBacked()) {
- std::vector<CacheStorageUsageInfo> entries;
- entries.reserve(cache_storage_map_.size());
for (const auto& origin_details : cache_storage_map_) {
- entries.push_back(CacheStorageUsageInfo(
- origin_details.first, origin_details.second->MemoryBackedSize(),
- base::Time()));
+ usages->push_back(
+ CacheStorageUsageInfo(origin_details.first, 0 /* size */,
+ base::Time() /* last modified */));
}
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(callback, entries));
+ GetAllOriginsUsageGetSizes(std::move(usages), callback);
return;
}
- PostTaskAndReplyWithResult(
- cache_task_runner_.get(), FROM_HERE,
- base::Bind(&GetAllOriginsUsageOnTaskRunner, root_path_),
- base::Bind(callback));
+ std::vector<CacheStorageUsageInfo>* usages_ptr = usages.get();
+ cache_task_runner_->PostTaskAndReply(
+ FROM_HERE, base::Bind(&ListOriginsAndLastModifiedOnTaskRunner, usages_ptr,
+ root_path_),
+ base::Bind(&CacheStorageManager::GetAllOriginsUsageGetSizes,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::Passed(std::move(usages)), callback));
+}
+
+void CacheStorageManager::GetAllOriginsUsageGetSizes(
+ scoped_ptr<std::vector<CacheStorageUsageInfo>> usages,
+ const CacheStorageContext::GetUsageInfoCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(usages);
+
+ // The origin GURL and last modified times are set in |usages| but not the
+ // size in bytes. Call each CacheStorage's Size() function to fill that out.
+ std::vector<CacheStorageUsageInfo>* usages_ptr = usages.get();
+
+ if (usages->empty()) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(callback, *usages));
+ return;
+ }
+
+ base::Closure barrier_closure = base::BarrierClosure(
+ usages_ptr->size(),
+ base::Bind(&AllOriginSizesReported, base::Passed(std::move(usages)),
+ callback));
+
+ for (CacheStorageUsageInfo& usage : *usages_ptr) {
+ CacheStorage* cache_storage = FindOrCreateCacheStorage(usage.origin);
+ cache_storage->Size(
+ base::Bind(&OneOriginSizeReported, barrier_closure, &usage));
+ }
}
void CacheStorageManager::GetOriginUsage(
@@ -230,20 +281,9 @@ void CacheStorageManager::GetOriginUsage(
const storage::QuotaClient::GetUsageCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (IsMemoryBacked()) {
- int64_t usage = 0;
- if (ContainsKey(cache_storage_map_, origin_url))
- usage = cache_storage_map_[origin_url]->MemoryBackedSize();
- callback.Run(usage);
- return;
- }
+ CacheStorage* cache_storage = FindOrCreateCacheStorage(origin_url);
- MigrateOrigin(origin_url);
- PostTaskAndReplyWithResult(
- cache_task_runner_.get(), FROM_HERE,
- base::Bind(base::ComputeDirectorySize,
- ConstructOriginPath(root_path_, origin_url)),
- base::Bind(callback));
+ cache_storage->Size(callback);
}
void CacheStorageManager::GetOrigins(
@@ -255,12 +295,13 @@ void CacheStorageManager::GetOrigins(
for (const auto& key_value : cache_storage_map_)
origins.insert(key_value.first);
- callback.Run(origins);
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(callback, origins));
return;
}
PostTaskAndReplyWithResult(cache_task_runner_.get(), FROM_HERE,
- base::Bind(&ListOriginsOnDisk, root_path_),
+ base::Bind(&ListOriginsOnTaskRunner, root_path_),
base::Bind(callback));
}
@@ -275,13 +316,14 @@ void CacheStorageManager::GetOriginsForHost(
if (host == net::GetHostOrSpecFromURL(key_value.first))
origins.insert(key_value.first);
}
- callback.Run(origins);
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(callback, origins));
return;
}
PostTaskAndReplyWithResult(
cache_task_runner_.get(), FROM_HERE,
- base::Bind(&ListOriginsOnDisk, root_path_),
+ base::Bind(&ListOriginsOnTaskRunner, root_path_),
base::Bind(&GetOriginsForHostDidListOrigins, host, callback));
}
@@ -290,18 +332,18 @@ void CacheStorageManager::DeleteOriginData(
const storage::QuotaClient::DeletionCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ // Create the CacheStorage for the origin if it hasn't been loaded yet.
+ FindOrCreateCacheStorage(origin);
+
CacheStorageMap::iterator it = cache_storage_map_.find(origin);
- if (it == cache_storage_map_.end()) {
- callback.Run(storage::kQuotaStatusOk);
- return;
- }
+ DCHECK(it != cache_storage_map_.end());
CacheStorage* cache_storage = it->second.release();
cache_storage_map_.erase(origin);
- cache_storage->CloseAllCaches(
- base::Bind(&CacheStorageManager::DeleteOriginDidClose, origin, callback,
- base::Passed(make_scoped_ptr(cache_storage)),
- weak_ptr_factory_.GetWeakPtr()));
+ cache_storage->GetSizeThenCloseAllCaches(
+ base::Bind(&CacheStorageManager::DeleteOriginDidClose,
+ weak_ptr_factory_.GetWeakPtr(), origin, callback,
+ base::Passed(make_scoped_ptr(cache_storage))));
}
void CacheStorageManager::DeleteOriginData(const GURL& origin) {
@@ -309,42 +351,40 @@ void CacheStorageManager::DeleteOriginData(const GURL& origin) {
DeleteOriginData(origin, base::Bind(&EmptyQuotaStatusCallback));
}
-// static
void CacheStorageManager::DeleteOriginDidClose(
const GURL& origin,
const storage::QuotaClient::DeletionCallback& callback,
scoped_ptr<CacheStorage> cache_storage,
- base::WeakPtr<CacheStorageManager> cache_manager) {
+ int64_t origin_size) {
// TODO(jkarlin): Deleting the storage leaves any unfinished operations
- // hanging, resulting in unresolved promises. Fix this by guaranteeing that
- // callbacks are called in ServiceWorkerStorage.
+ // hanging, resulting in unresolved promises. Fix this by returning early from
+ // CacheStorage operations posted after GetSizeThenCloseAllCaches is called.
cache_storage.reset();
- if (!cache_manager) {
- callback.Run(storage::kQuotaErrorAbort);
- return;
- }
+ quota_manager_proxy_->NotifyStorageModified(
+ storage::QuotaClient::kServiceWorkerCache, origin,
+ storage::kStorageTypeTemporary, -1 * origin_size);
- if (cache_manager->IsMemoryBacked()) {
- callback.Run(storage::kQuotaStatusOk);
+ if (IsMemoryBacked()) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(callback, storage::kQuotaStatusOk));
return;
}
- cache_manager->MigrateOrigin(origin);
+ MigrateOrigin(origin);
PostTaskAndReplyWithResult(
- cache_manager->cache_task_runner_.get(), FROM_HERE,
- base::Bind(&DeleteDir,
- ConstructOriginPath(cache_manager->root_path_, origin)),
+ cache_task_runner_.get(), FROM_HERE,
+ base::Bind(&DeleteDir, ConstructOriginPath(root_path_, origin)),
base::Bind(&DeleteOriginDidDeleteDir, callback));
}
CacheStorageManager::CacheStorageManager(
const base::FilePath& path,
- const scoped_refptr<base::SequencedTaskRunner>& cache_task_runner,
- const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy)
+ scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy)
: root_path_(path),
- cache_task_runner_(cache_task_runner),
- quota_manager_proxy_(quota_manager_proxy),
+ cache_task_runner_(std::move(cache_task_runner)),
+ quota_manager_proxy_(std::move(quota_manager_proxy)),
weak_ptr_factory_(this) {
if (quota_manager_proxy_.get()) {
quota_manager_proxy_->RegisterClient(
diff --git a/chromium/content/browser/cache_storage/cache_storage_manager.h b/chromium/content/browser/cache_storage/cache_storage_manager.h
index 121a25228d3..ded3703e924 100644
--- a/chromium/content/browser/cache_storage/cache_storage_manager.h
+++ b/chromium/content/browser/cache_storage/cache_storage_manager.h
@@ -40,8 +40,8 @@ class CONTENT_EXPORT CacheStorageManager {
public:
static scoped_ptr<CacheStorageManager> Create(
const base::FilePath& path,
- const scoped_refptr<base::SequencedTaskRunner>& cache_task_runner,
- const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy);
+ scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy);
static scoped_ptr<CacheStorageManager> Create(
CacheStorageManager* old_manager);
@@ -76,7 +76,7 @@ class CONTENT_EXPORT CacheStorageManager {
// This must be called before creating any of the public *Cache functions
// above.
void SetBlobParametersForCache(
- const scoped_refptr<net::URLRequestContextGetter>& request_context_getter,
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter,
base::WeakPtr<storage::BlobStorageContext> blob_storage_context);
base::WeakPtr<CacheStorageManager> AsWeakPtr() {
@@ -95,8 +95,8 @@ class CONTENT_EXPORT CacheStorageManager {
CacheStorageManager(
const base::FilePath& path,
- const scoped_refptr<base::SequencedTaskRunner>& cache_task_runner,
- const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy);
+ scoped_refptr<base::SequencedTaskRunner> cache_task_runner,
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy);
// The returned CacheStorage* is owned by this manager.
CacheStorage* FindOrCreateCacheStorage(const GURL& origin);
@@ -104,6 +104,10 @@ class CONTENT_EXPORT CacheStorageManager {
// QuotaClient and Browsing Data Deletion support
void GetAllOriginsUsage(
const CacheStorageContext::GetUsageInfoCallback& callback);
+ void GetAllOriginsUsageGetSizes(
+ scoped_ptr<std::vector<CacheStorageUsageInfo>> usage_info,
+ const CacheStorageContext::GetUsageInfoCallback& callback);
+
void GetOriginUsage(const GURL& origin_url,
const storage::QuotaClient::GetUsageCallback& callback);
void GetOrigins(const storage::QuotaClient::GetOriginsCallback& callback);
@@ -113,11 +117,11 @@ class CONTENT_EXPORT CacheStorageManager {
void DeleteOriginData(const GURL& origin,
const storage::QuotaClient::DeletionCallback& callback);
void DeleteOriginData(const GURL& origin);
- static void DeleteOriginDidClose(
+ void DeleteOriginDidClose(
const GURL& origin,
const storage::QuotaClient::DeletionCallback& callback,
scoped_ptr<CacheStorage> cache_storage,
- base::WeakPtr<CacheStorageManager> cache_manager);
+ int64_t origin_size);
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter()
const {
@@ -128,7 +132,7 @@ class CONTENT_EXPORT CacheStorageManager {
return blob_context_;
}
- const scoped_refptr<base::SequencedTaskRunner>& cache_task_runner() const {
+ scoped_refptr<base::SequencedTaskRunner> cache_task_runner() const {
return cache_task_runner_;
}
diff --git a/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc b/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc
index f8d94976e2b..dec8cfa953f 100644
--- a/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_manager_unittest.cc
@@ -24,6 +24,7 @@
#include "content/browser/quota/mock_quota_manager_proxy.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/cache_storage_usage_info.h"
+#include "content/public/test/mock_special_storage_policy.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/url_request/url_request_context.h"
@@ -75,19 +76,25 @@ class CacheStorageManagerTest : public testing::Test {
url_request_context->set_job_factory(url_request_job_factory_.get());
+ if (!MemoryOnly())
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+
+ quota_policy_ = new MockSpecialStoragePolicy;
+ mock_quota_manager_ = new MockQuotaManager(
+ MemoryOnly() /* is incognito */, temp_dir_.path(),
+ base::ThreadTaskRunnerHandle::Get().get(),
+ base::ThreadTaskRunnerHandle::Get().get(), quota_policy_.get());
+ mock_quota_manager_->SetQuota(
+ GURL(origin1_), storage::kStorageTypeTemporary, 1024 * 1024 * 100);
+ mock_quota_manager_->SetQuota(
+ GURL(origin2_), storage::kStorageTypeTemporary, 1024 * 1024 * 100);
+
quota_manager_proxy_ = new MockQuotaManagerProxy(
- nullptr, base::ThreadTaskRunnerHandle::Get().get());
+ mock_quota_manager_.get(), base::ThreadTaskRunnerHandle::Get().get());
- if (MemoryOnly()) {
- cache_manager_ = CacheStorageManager::Create(
- base::FilePath(), base::ThreadTaskRunnerHandle::Get(),
- quota_manager_proxy_);
- } else {
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- cache_manager_ = CacheStorageManager::Create(
- temp_dir_.path(), base::ThreadTaskRunnerHandle::Get(),
- quota_manager_proxy_);
- }
+ cache_manager_ = CacheStorageManager::Create(
+ temp_dir_.path(), base::ThreadTaskRunnerHandle::Get(),
+ quota_manager_proxy_);
cache_manager_->SetBlobParametersForCache(
browser_context_.GetRequestContext(),
@@ -110,9 +117,9 @@ class CacheStorageManagerTest : public testing::Test {
}
void CacheAndErrorCallback(base::RunLoop* run_loop,
- const scoped_refptr<CacheStorageCache>& cache,
+ scoped_refptr<CacheStorageCache> cache,
CacheStorageError error) {
- callback_cache_ = cache;
+ callback_cache_ = std::move(cache);
callback_error_ = error;
run_loop->Quit();
}
@@ -219,8 +226,13 @@ class CacheStorageManagerTest : public testing::Test {
return callback_error_ == CACHE_STORAGE_OK;
}
- bool CachePut(const scoped_refptr<CacheStorageCache>& cache,
- const GURL& url) {
+ bool CachePut(CacheStorageCache* cache, const GURL& url) {
+ return CachePutWithStatusCode(cache, url, 200);
+ }
+
+ bool CachePutWithStatusCode(CacheStorageCache* cache,
+ const GURL& url,
+ int status_code) {
ServiceWorkerFetchRequest request;
request.url = url;
@@ -231,9 +243,11 @@ class CacheStorageManagerTest : public testing::Test {
scoped_ptr<storage::BlobDataHandle> blob_handle =
blob_storage_context_->AddFinishedBlob(blob_data.get());
ServiceWorkerResponse response(
- url, 200, "OK", blink::WebServiceWorkerResponseTypeDefault,
+ url, status_code, "OK", blink::WebServiceWorkerResponseTypeDefault,
ServiceWorkerHeaderMap(), blob_handle->uuid(), url.spec().size(),
- GURL(), blink::WebServiceWorkerResponseErrorUnknown);
+ GURL(), blink::WebServiceWorkerResponseErrorUnknown, base::Time(),
+ false /* is_in_cache_storage */,
+ std::string() /* cache_storage_cache_name */);
CacheStorageBatchOperation operation;
operation.operation_type = CACHE_STORAGE_CACHE_OPERATION_TYPE_PUT;
@@ -250,8 +264,7 @@ class CacheStorageManagerTest : public testing::Test {
return callback_error_ == CACHE_STORAGE_OK;
}
- bool CacheMatch(const scoped_refptr<CacheStorageCache>& cache,
- const GURL& url) {
+ bool CacheMatch(CacheStorageCache* cache, const GURL& url) {
scoped_ptr<ServiceWorkerFetchRequest> request(
new ServiceWorkerFetchRequest());
request->url = url;
@@ -298,6 +311,25 @@ class CacheStorageManagerTest : public testing::Test {
run_loop->Quit();
}
+ int64_t GetSizeThenCloseAllCaches(const GURL& origin) {
+ base::RunLoop loop;
+ CacheStorage* cache_storage = CacheStorageForOrigin(origin);
+ cache_storage->GetSizeThenCloseAllCaches(
+ base::Bind(&CacheStorageManagerTest::UsageCallback,
+ base::Unretained(this), &loop));
+ loop.Run();
+ return callback_usage_;
+ }
+
+ int64_t Size(const GURL& origin) {
+ base::RunLoop loop;
+ CacheStorage* cache_storage = CacheStorageForOrigin(origin);
+ cache_storage->Size(base::Bind(&CacheStorageManagerTest::UsageCallback,
+ base::Unretained(this), &loop));
+ loop.Run();
+ return callback_usage_;
+ }
+
protected:
// Temporary directory must be allocated first so as to be destroyed last.
base::ScopedTempDir temp_dir_;
@@ -307,6 +339,8 @@ class CacheStorageManagerTest : public testing::Test {
scoped_ptr<net::URLRequestJobFactoryImpl> url_request_job_factory_;
storage::BlobStorageContext* blob_storage_context_;
+ scoped_refptr<MockSpecialStoragePolicy> quota_policy_;
+ scoped_refptr<MockQuotaManager> mock_quota_manager_;
scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
scoped_ptr<CacheStorageManager> cache_manager_;
@@ -395,6 +429,18 @@ TEST_P(CacheStorageManagerTestP, DeleteTwice) {
EXPECT_EQ(CACHE_STORAGE_ERROR_NOT_FOUND, callback_error_);
}
+TEST_P(CacheStorageManagerTestP, DeleteCacheReducesOriginSize) {
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
+ // The quota manager gets updated after the put operation runs its callback so
+ // run the event loop.
+ base::RunLoop().RunUntilIdle();
+ int64_t put_delta = quota_manager_proxy_->last_notified_delta();
+ EXPECT_LT(0, put_delta);
+ EXPECT_TRUE(Delete(origin1_, "foo"));
+ EXPECT_EQ(put_delta, -1 * quota_manager_proxy_->last_notified_delta());
+}
+
TEST_P(CacheStorageManagerTestP, EmptyKeys) {
EXPECT_TRUE(Keys(origin1_));
EXPECT_TRUE(callback_strings_.empty());
@@ -427,33 +473,33 @@ TEST_P(CacheStorageManagerTestP, DeletedKeysGone) {
TEST_P(CacheStorageManagerTestP, StorageMatchEntryExists) {
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_, GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
EXPECT_TRUE(StorageMatch(origin1_, "foo", GURL("http://example.com/foo")));
}
TEST_P(CacheStorageManagerTestP, StorageMatchNoEntry) {
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_, GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
EXPECT_FALSE(StorageMatch(origin1_, "foo", GURL("http://example.com/bar")));
EXPECT_EQ(CACHE_STORAGE_ERROR_NOT_FOUND, callback_error_);
}
TEST_P(CacheStorageManagerTestP, StorageMatchNoCache) {
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_, GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
EXPECT_FALSE(StorageMatch(origin1_, "bar", GURL("http://example.com/foo")));
- EXPECT_EQ(CACHE_STORAGE_ERROR_NOT_FOUND, callback_error_);
+ EXPECT_EQ(CACHE_STORAGE_ERROR_CACHE_NAME_NOT_FOUND, callback_error_);
}
TEST_P(CacheStorageManagerTestP, StorageMatchAllEntryExists) {
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_, GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
EXPECT_TRUE(StorageMatchAll(origin1_, GURL("http://example.com/foo")));
}
TEST_P(CacheStorageManagerTestP, StorageMatchAllNoEntry) {
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_, GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
EXPECT_FALSE(StorageMatchAll(origin1_, GURL("http://example.com/bar")));
EXPECT_EQ(CACHE_STORAGE_ERROR_NOT_FOUND, callback_error_);
}
@@ -468,8 +514,8 @@ TEST_F(CacheStorageManagerTest, StorageReuseCacheName) {
// with the same URL should work. (see crbug.com/542668)
const GURL kTestURL = GURL("http://example.com/foo");
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_, kTestURL));
- EXPECT_TRUE(CacheMatch(callback_cache_, kTestURL));
+ EXPECT_TRUE(CachePut(callback_cache_.get(), kTestURL));
+ EXPECT_TRUE(CacheMatch(callback_cache_.get(), kTestURL));
scoped_ptr<storage::BlobDataHandle> data_handle =
std::move(callback_data_handle_);
@@ -477,22 +523,28 @@ TEST_F(CacheStorageManagerTest, StorageReuseCacheName) {
// The cache is deleted but the handle to one of its entries is still
// open. Creating a new cache in the same directory would fail on Windows.
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_, kTestURL));
+ EXPECT_TRUE(CachePut(callback_cache_.get(), kTestURL));
}
TEST_P(CacheStorageManagerTestP, StorageMatchAllEntryExistsTwice) {
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_, GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePutWithStatusCode(callback_cache_.get(),
+ GURL("http://example.com/foo"), 200));
EXPECT_TRUE(Open(origin1_, "bar"));
- EXPECT_TRUE(CachePut(callback_cache_, GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePutWithStatusCode(callback_cache_.get(),
+ GURL("http://example.com/foo"), 201));
EXPECT_TRUE(StorageMatchAll(origin1_, GURL("http://example.com/foo")));
+
+ // The caches need to be searched in order of creation, so verify that the
+ // response came from the first cache.
+ EXPECT_EQ(200, callback_cache_response_->status_code);
}
TEST_P(CacheStorageManagerTestP, StorageMatchInOneOfMany) {
EXPECT_TRUE(Open(origin1_, "foo"));
EXPECT_TRUE(Open(origin1_, "bar"));
- EXPECT_TRUE(CachePut(callback_cache_, GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
EXPECT_TRUE(Open(origin1_, "baz"));
EXPECT_TRUE(StorageMatchAll(origin1_, GURL("http://example.com/foo")));
@@ -595,56 +647,67 @@ TEST_P(CacheStorageManagerTestP, OpenRunsSerially) {
TEST_P(CacheStorageManagerTestP, GetOriginUsage) {
EXPECT_EQ(0, GetOriginUsage(origin1_));
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_, GURL("http://example.com/foo")));
+ EXPECT_EQ(0, GetOriginUsage(origin1_));
+ EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
+ int64_t foo_size = GetOriginUsage(origin1_);
EXPECT_LT(0, GetOriginUsage(origin1_));
EXPECT_EQ(0, GetOriginUsage(origin2_));
+
+ // Add the same entry into a second cache, the size should double.
+ EXPECT_TRUE(Open(origin1_, "bar"));
+ EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
+ EXPECT_EQ(2 * foo_size, GetOriginUsage(origin1_));
}
TEST_P(CacheStorageManagerTestP, GetAllOriginsUsage) {
EXPECT_EQ(0ULL, GetAllOriginsUsage().size());
+ // Put one entry in a cache on origin 1.
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_, GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
+
+ // Put two entries (of identical size) in a cache on origin 2.
+ EXPECT_TRUE(Open(origin2_, "foo"));
+ EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/bar")));
+
std::vector<CacheStorageUsageInfo> usage = GetAllOriginsUsage();
- EXPECT_EQ(1ULL, usage.size());
- const CacheStorageUsageInfo& info = usage[0];
- EXPECT_EQ(origin1_, info.origin);
- EXPECT_LT(0, info.total_size_bytes);
- if (MemoryOnly())
- EXPECT_TRUE(info.last_modified.is_null());
- else
- EXPECT_FALSE(info.last_modified.is_null());
+ EXPECT_EQ(2ULL, usage.size());
+
+ int origin1_index = usage[0].origin == origin1_ ? 0 : 1;
+ int origin2_index = usage[1].origin == origin2_ ? 1 : 0;
+ EXPECT_NE(origin1_index, origin2_index);
+
+ int64_t origin1_size = usage[origin1_index].total_size_bytes;
+ int64_t origin2_size = usage[origin2_index].total_size_bytes;
+ EXPECT_EQ(2 * origin1_size, origin2_size);
+
+ if (MemoryOnly()) {
+ EXPECT_TRUE(usage[origin1_index].last_modified.is_null());
+ EXPECT_TRUE(usage[origin2_index].last_modified.is_null());
+ } else {
+ EXPECT_FALSE(usage[origin1_index].last_modified.is_null());
+ EXPECT_FALSE(usage[origin2_index].last_modified.is_null());
+ }
}
-TEST_F(CacheStorageManagerMemoryOnlyTest, MemoryBackedSize) {
- CacheStorage* cache_storage = CacheStorageForOrigin(origin1_);
- EXPECT_EQ(0, cache_storage->MemoryBackedSize());
-
+TEST_P(CacheStorageManagerTestP, GetSizeThenCloseAllCaches) {
EXPECT_TRUE(Open(origin1_, "foo"));
- scoped_refptr<CacheStorageCache> foo_cache = callback_cache_;
+ EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo2")));
EXPECT_TRUE(Open(origin1_, "bar"));
- scoped_refptr<CacheStorageCache> bar_cache = callback_cache_;
- EXPECT_EQ(0, cache_storage->MemoryBackedSize());
+ EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/bar")));
- EXPECT_TRUE(CachePut(foo_cache, GURL("http://example.com/foo")));
- EXPECT_LT(0, cache_storage->MemoryBackedSize());
- int64_t foo_size = cache_storage->MemoryBackedSize();
+ int64_t origin_size = GetOriginUsage(origin1_);
+ EXPECT_LT(0, origin_size);
- EXPECT_TRUE(CachePut(bar_cache, GURL("http://example.com/foo")));
- EXPECT_EQ(foo_size * 2, cache_storage->MemoryBackedSize());
-}
-
-TEST_F(CacheStorageManagerTest, MemoryBackedSizePersistent) {
- CacheStorage* cache_storage = CacheStorageForOrigin(origin1_);
- EXPECT_EQ(0, cache_storage->MemoryBackedSize());
- EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_, GURL("http://example.com/foo")));
- EXPECT_EQ(0, cache_storage->MemoryBackedSize());
+ EXPECT_EQ(origin_size, GetSizeThenCloseAllCaches(origin1_));
+ EXPECT_FALSE(CachePut(callback_cache_.get(), GURL("http://example.com/baz")));
}
TEST_F(CacheStorageManagerTest, DeleteUnreferencedCacheDirectories) {
// Create a referenced cache.
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_, GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
// Create an unreferenced directory next to the referenced one.
base::FilePath origin_path = CacheStorageManager::ConstructOriginPath(
@@ -660,12 +723,63 @@ TEST_F(CacheStorageManagerTest, DeleteUnreferencedCacheDirectories) {
// Verify that the referenced cache still works.
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CacheMatch(callback_cache_, GURL("http://example.com/foo")));
+ EXPECT_TRUE(
+ CacheMatch(callback_cache_.get(), GURL("http://example.com/foo")));
// Verify that the unreferenced cache is gone.
EXPECT_FALSE(base::DirectoryExists(unreferenced_path));
}
+TEST_P(CacheStorageManagerTestP, OpenCacheStorageAccessed) {
+ EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count());
+}
+
+TEST_P(CacheStorageManagerTestP, HasStorageAccessed) {
+ EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
+ EXPECT_FALSE(Has(origin1_, "foo"));
+ EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count());
+}
+
+TEST_P(CacheStorageManagerTestP, DeleteStorageAccessed) {
+ EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
+ EXPECT_FALSE(Delete(origin1_, "foo"));
+ EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count());
+}
+
+TEST_P(CacheStorageManagerTestP, KeysStorageAccessed) {
+ EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
+ EXPECT_TRUE(Keys(origin1_));
+ EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count());
+}
+
+TEST_P(CacheStorageManagerTestP, MatchCacheStorageAccessed) {
+ EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
+ EXPECT_FALSE(StorageMatch(origin1_, "foo", GURL("http://example.com/foo")));
+ EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count());
+}
+
+TEST_P(CacheStorageManagerTestP, MatchAllCachesStorageAccessed) {
+ EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
+ EXPECT_FALSE(StorageMatchAll(origin1_, GURL("http://example.com/foo")));
+ EXPECT_EQ(1, quota_manager_proxy_->notify_storage_accessed_count());
+}
+
+TEST_P(CacheStorageManagerTestP, SizeStorageAccessed) {
+ EXPECT_EQ(0, Size(origin1_));
+ // Size is not part of the web API and should not notify the quota manager of
+ // an access.
+ EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
+}
+
+TEST_P(CacheStorageManagerTestP, SizeThenCloseStorageAccessed) {
+ EXPECT_EQ(0, GetSizeThenCloseAllCaches(origin1_));
+ // GetSizeThenCloseAllCaches is not part of the web API and should not notify
+ // the quota manager of an access.
+ EXPECT_EQ(0, quota_manager_proxy_->notify_storage_accessed_count());
+}
+
class CacheStorageMigrationTest : public CacheStorageManagerTest {
protected:
CacheStorageMigrationTest() : cache1_("foo"), cache2_("bar") {}
@@ -729,7 +843,7 @@ TEST_F(CacheStorageMigrationTest, DeleteCache) {
}
TEST_F(CacheStorageMigrationTest, GetOriginUsage) {
- EXPECT_GT(GetOriginUsage(origin1_), 0);
+ EXPECT_EQ(0, GetOriginUsage(origin1_));
EXPECT_FALSE(base::DirectoryExists(legacy_path_));
EXPECT_TRUE(base::DirectoryExists(new_path_));
}
@@ -774,7 +888,7 @@ class MigratedLegacyCacheDirectoryNameTest : public CacheStorageManagerTest {
// Populate a legacy cache.
ASSERT_TRUE(Open(origin1_, legacy_cache_name_));
- EXPECT_TRUE(CachePut(callback_cache_, stored_url_));
+ EXPECT_TRUE(CachePut(callback_cache_.get(), stored_url_));
base::FilePath new_path = callback_cache_->path();
// Close the cache's backend so that the files can be moved.
@@ -827,27 +941,29 @@ TEST_F(MigratedLegacyCacheDirectoryNameTest, LegacyCacheMigrated) {
ASSERT_FALSE(base::DirectoryExists(legacy_path_));
// Verify that the existing entry still works.
- EXPECT_TRUE(CacheMatch(callback_cache_, stored_url_));
+ EXPECT_TRUE(CacheMatch(callback_cache_.get(), stored_url_));
// Verify that adding new entries works.
- EXPECT_TRUE(CachePut(callback_cache_, GURL("http://example.com/foo2")));
- EXPECT_TRUE(CacheMatch(callback_cache_, GURL("http://example.com/foo2")));
+ EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo2")));
+ EXPECT_TRUE(
+ CacheMatch(callback_cache_.get(), GURL("http://example.com/foo2")));
}
TEST_F(MigratedLegacyCacheDirectoryNameTest,
RandomDirectoryCacheSideBySideWithLegacy) {
EXPECT_TRUE(Open(origin1_, legacy_cache_name_));
EXPECT_TRUE(Open(origin1_, "bar"));
- EXPECT_TRUE(CachePut(callback_cache_, stored_url_));
- EXPECT_TRUE(CacheMatch(callback_cache_, stored_url_));
+ EXPECT_TRUE(CachePut(callback_cache_.get(), stored_url_));
+ EXPECT_TRUE(CacheMatch(callback_cache_.get(), stored_url_));
}
TEST_F(MigratedLegacyCacheDirectoryNameTest, DeleteLegacyCacheAndRecreateNew) {
EXPECT_TRUE(Delete(origin1_, legacy_cache_name_));
EXPECT_TRUE(Open(origin1_, legacy_cache_name_));
- EXPECT_FALSE(CacheMatch(callback_cache_, stored_url_));
- EXPECT_TRUE(CachePut(callback_cache_, GURL("http://example.com/foo2")));
- EXPECT_TRUE(CacheMatch(callback_cache_, GURL("http://example.com/foo2")));
+ EXPECT_FALSE(CacheMatch(callback_cache_.get(), stored_url_));
+ EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo2")));
+ EXPECT_TRUE(
+ CacheMatch(callback_cache_.get(), GURL("http://example.com/foo2")));
}
class CacheStorageQuotaClientTest : public CacheStorageManagerTest {
@@ -929,6 +1045,11 @@ class CacheStorageQuotaClientTest : public CacheStorageManagerTest {
DISALLOW_COPY_AND_ASSIGN(CacheStorageQuotaClientTest);
};
+class CacheStorageQuotaClientDiskOnlyTest : public CacheStorageQuotaClientTest {
+ public:
+ bool MemoryOnly() override { return false; }
+};
+
class CacheStorageQuotaClientTestP : public CacheStorageQuotaClientTest,
public testing::WithParamInterface<bool> {
bool MemoryOnly() override { return !GetParam(); }
@@ -941,7 +1062,7 @@ TEST_P(CacheStorageQuotaClientTestP, QuotaID) {
TEST_P(CacheStorageQuotaClientTestP, QuotaGetOriginUsage) {
EXPECT_EQ(0, QuotaGetOriginUsage(origin1_));
EXPECT_TRUE(Open(origin1_, "foo"));
- EXPECT_TRUE(CachePut(callback_cache_, GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
EXPECT_LT(0, QuotaGetOriginUsage(origin1_));
}
@@ -967,14 +1088,20 @@ TEST_P(CacheStorageQuotaClientTestP, QuotaGetOriginsForHost) {
}
TEST_P(CacheStorageQuotaClientTestP, QuotaDeleteOriginData) {
+ EXPECT_EQ(0, QuotaGetOriginUsage(origin1_));
EXPECT_TRUE(Open(origin1_, "foo"));
// Call put to test that initialized caches are properly deleted too.
- EXPECT_TRUE(CachePut(callback_cache_, GURL("http://example.com/foo")));
+ EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
EXPECT_TRUE(Open(origin1_, "bar"));
EXPECT_TRUE(Open(origin2_, "baz"));
+ int64_t origin1_size = QuotaGetOriginUsage(origin1_);
+ EXPECT_LT(0, origin1_size);
+
EXPECT_TRUE(QuotaDeleteOriginData(origin1_));
+ EXPECT_EQ(-1 * origin1_size, quota_manager_proxy_->last_notified_delta());
+ EXPECT_EQ(0, QuotaGetOriginUsage(origin1_));
EXPECT_FALSE(Has(origin1_, "foo"));
EXPECT_FALSE(Has(origin1_, "bar"));
EXPECT_TRUE(Has(origin2_, "baz"));
@@ -985,6 +1112,25 @@ TEST_P(CacheStorageQuotaClientTestP, QuotaDeleteEmptyOrigin) {
EXPECT_TRUE(QuotaDeleteOriginData(origin1_));
}
+TEST_F(CacheStorageQuotaClientDiskOnlyTest, QuotaDeleteUnloadedOriginData) {
+ EXPECT_TRUE(Open(origin1_, "foo"));
+ // Call put to test that initialized caches are properly deleted too.
+ EXPECT_TRUE(CachePut(callback_cache_.get(), GURL("http://example.com/foo")));
+
+ // Close the cache backend so that it writes out its index to disk.
+ base::RunLoop run_loop;
+ callback_cache_->Close(run_loop.QuitClosure());
+ run_loop.Run();
+
+ // Create a new CacheStorageManager that hasn't yet loaded the origin.
+ quota_manager_proxy_->SimulateQuotaManagerDestroyed();
+ cache_manager_ = CacheStorageManager::Create(cache_manager_.get());
+ quota_client_.reset(new CacheStorageQuotaClient(cache_manager_->AsWeakPtr()));
+
+ EXPECT_TRUE(QuotaDeleteOriginData(origin1_));
+ EXPECT_EQ(0, QuotaGetOriginUsage(origin1_));
+}
+
TEST_P(CacheStorageQuotaClientTestP, QuotaDoesSupport) {
EXPECT_TRUE(QuotaDoesSupport(storage::kStorageTypeTemporary));
EXPECT_FALSE(QuotaDoesSupport(storage::kStorageTypePersistent));
diff --git a/chromium/content/browser/cache_storage/cache_storage_unittest.cc b/chromium/content/browser/cache_storage/cache_storage_unittest.cc
index faf0eb10635..9c0081ba087 100644
--- a/chromium/content/browser/cache_storage/cache_storage_unittest.cc
+++ b/chromium/content/browser/cache_storage/cache_storage_unittest.cc
@@ -7,9 +7,12 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/files/scoped_temp_dir.h"
+#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/thread_task_runner_handle.h"
+#include "content/browser/quota/mock_quota_manager_proxy.h"
+#include "content/public/test/mock_special_storage_policy.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/url_request/url_request_context_getter.h"
#include "storage/browser/quota/quota_manager_proxy.h"
@@ -23,12 +26,14 @@ const char kOrigin[] = "http://example.com/";
class TestCacheStorage : public CacheStorage {
public:
- explicit TestCacheStorage(const base::FilePath& file_path)
+ TestCacheStorage(
+ const base::FilePath& file_path,
+ scoped_refptr<storage::QuotaManagerProxy> quota_manager_proxy)
: CacheStorage(file_path,
false /* memory_only */,
base::ThreadTaskRunnerHandle::Get().get(),
scoped_refptr<net::URLRequestContextGetter>(),
- scoped_refptr<storage::QuotaManagerProxy>(),
+ quota_manager_proxy,
base::WeakPtr<storage::BlobStorageContext>(),
GURL(kOrigin)),
delay_preserved_cache_callback_(false) {}
@@ -67,7 +72,17 @@ class CacheStorageTest : public testing::Test {
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- test_cache_storage_.reset(new TestCacheStorage(temp_dir_.path()));
+
+ quota_policy_ = new MockSpecialStoragePolicy;
+ mock_quota_manager_ = new MockQuotaManager(
+ false /* is incognito */, temp_dir_.path(),
+ base::ThreadTaskRunnerHandle::Get().get(),
+ base::ThreadTaskRunnerHandle::Get().get(), quota_policy_.get());
+ quota_manager_proxy_ = new MockQuotaManagerProxy(
+ mock_quota_manager_.get(), base::ThreadTaskRunnerHandle::Get().get());
+
+ test_cache_storage_.reset(
+ new TestCacheStorage(temp_dir_.path(), quota_manager_proxy_));
}
bool OpenCache(const std::string& cache_name) {
@@ -81,7 +96,7 @@ class CacheStorageTest : public testing::Test {
}
void OpenCacheCallback(bool* callback_called,
- const scoped_refptr<CacheStorageCache>& cache,
+ scoped_refptr<CacheStorageCache> cache,
CacheStorageError error) {
*callback_called = true;
callback_cache_ = cache;
@@ -90,6 +105,9 @@ class CacheStorageTest : public testing::Test {
base::ScopedTempDir temp_dir_;
TestBrowserThreadBundle browser_thread_bundle_;
+ scoped_refptr<MockSpecialStoragePolicy> quota_policy_;
+ scoped_refptr<MockQuotaManager> mock_quota_manager_;
+ scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
scoped_ptr<TestCacheStorage> test_cache_storage_;
scoped_refptr<CacheStorageCache> callback_cache_;
diff --git a/chromium/content/browser/child_process_launcher.cc b/chromium/content/browser/child_process_launcher.cc
index 57a6368cb7d..47205b630c1 100644
--- a/chromium/content/browser/child_process_launcher.cc
+++ b/chromium/content/browser/child_process_launcher.cc
@@ -13,6 +13,7 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/metrics/histogram.h"
+#include "base/process/launch.h"
#include "base/process/process.h"
#include "base/strings/string_number_conversions.h"
#include "base/synchronization/lock.h"
@@ -23,9 +24,13 @@
#include "content/public/common/content_switches.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
+#include "mojo/edk/embedder/embedder.h"
+#include "mojo/edk/embedder/scoped_platform_handle.h"
#if defined(OS_WIN)
#include "base/files/file_path.h"
+#include "base/win/scoped_handle.h"
+#include "base/win/win_util.h"
#include "content/common/sandbox_win.h"
#include "content/public/common/sandbox_init.h"
#elif defined(OS_MACOSX)
@@ -39,8 +44,10 @@
#elif defined(OS_POSIX)
#include "base/memory/singleton.h"
#include "content/browser/renderer_host/render_sandbox_host_linux.h"
+#include "content/browser/zygote_host/zygote_communication_linux.h"
#include "content/browser/zygote_host/zygote_host_impl_linux.h"
#include "content/common/child_process_sandbox_support_impl_linux.h"
+#include "content/public/browser/zygote_handle_linux.h"
#endif
#if defined(OS_POSIX)
@@ -53,9 +60,10 @@ namespace content {
namespace {
-typedef base::Callback<void(bool,
+typedef base::Callback<void(ZygoteHandle,
#if defined(OS_ANDROID)
base::ScopedFD,
+ base::ScopedFD,
#endif
base::Process)> NotifyCallback;
@@ -79,6 +87,7 @@ void OnChildProcessStartedAndroid(const NotifyCallback& callback,
BrowserThread::ID client_thread_id,
const base::TimeTicks begin_launch_time,
base::ScopedFD ipcfd,
+ base::ScopedFD mojo_fd,
base::ProcessHandle handle) {
// This can be called on the launcher thread or UI thread.
base::TimeDelta launch_time = base::TimeTicks::Now() - begin_launch_time;
@@ -87,8 +96,8 @@ void OnChildProcessStartedAndroid(const NotifyCallback& callback,
base::Bind(&RecordHistogramsOnLauncherThread, launch_time));
base::Closure callback_on_client_thread(
- base::Bind(callback, false, base::Passed(&ipcfd),
- base::Passed(base::Process(handle))));
+ base::Bind(callback, nullptr, base::Passed(&ipcfd),
+ base::Passed(&mojo_fd), base::Passed(base::Process(handle))));
if (BrowserThread::CurrentlyOn(client_thread_id)) {
callback_on_client_thread.Run();
} else {
@@ -105,18 +114,19 @@ void LaunchOnLauncherThread(const NotifyCallback& callback,
#if defined(OS_ANDROID)
base::ScopedFD ipcfd,
#endif
+ mojo::edk::ScopedPlatformHandle client_handle,
base::CommandLine* cmd_line) {
DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
scoped_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate);
+#if !defined(OS_ANDROID)
+ ZygoteHandle zygote = nullptr;
+#endif
#if defined(OS_WIN)
- bool use_zygote = false;
bool launch_elevated = delegate->ShouldLaunchElevated();
#elif defined(OS_MACOSX)
- bool use_zygote = false;
base::EnvironmentMap env = delegate->GetEnvironment();
base::ScopedFD ipcfd = delegate->TakeIpcFd();
#elif defined(OS_POSIX) && !defined(OS_ANDROID)
- bool use_zygote = delegate->ShouldUseZygote();
base::EnvironmentMap env = delegate->GetEnvironment();
base::ScopedFD ipcfd = delegate->TakeIpcFd();
#endif
@@ -126,11 +136,19 @@ void LaunchOnLauncherThread(const NotifyCallback& callback,
base::Process process;
#if defined(OS_WIN)
if (launch_elevated) {
+ // TODO(rockot): We may want to support Mojo IPC to elevated processes as
+ // well, but this isn't currently feasible without sharing a pipe path on
+ // the command line as elevated process launch goes through ShellExecuteEx.
base::LaunchOptions options;
options.start_hidden = true;
process = base::LaunchElevatedProcess(*cmd_line, options);
} else {
- process = StartSandboxedProcess(delegate, cmd_line);
+ base::HandlesToInheritVector handles;
+ handles.push_back(client_handle.get().handle);
+ cmd_line->AppendSwitchASCII(
+ mojo::edk::PlatformChannelPair::kMojoPlatformChannelHandleSwitch,
+ base::UintToString(base::win::HandleToUint32(handles[0])));
+ process = StartSandboxedProcess(delegate, cmd_line, handles);
}
#elif defined(OS_POSIX)
std::string process_type =
@@ -138,10 +156,17 @@ void LaunchOnLauncherThread(const NotifyCallback& callback,
scoped_ptr<FileDescriptorInfo> files_to_register(
FileDescriptorInfoImpl::Create());
+ base::ScopedFD mojo_fd(client_handle.release().handle);
+ DCHECK(mojo_fd.is_valid());
+
#if defined(OS_ANDROID)
- files_to_register->Share(kPrimaryIPCChannel, ipcfd.get());
+ if (ipcfd.get() != -1)
+ files_to_register->Share(kPrimaryIPCChannel, ipcfd.get());
+ files_to_register->Share(kMojoIPCChannel, mojo_fd.get());
#else
- files_to_register->Transfer(kPrimaryIPCChannel, std::move(ipcfd));
+ if (ipcfd.get() != -1)
+ files_to_register->Transfer(kPrimaryIPCChannel, std::move(ipcfd));
+ files_to_register->Transfer(kMojoIPCChannel, std::move(mojo_fd));
#endif
#endif
@@ -154,6 +179,31 @@ void LaunchOnLauncherThread(const NotifyCallback& callback,
#endif
);
#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
+ bool snapshot_loaded = false;
+#if defined(OS_ANDROID)
+ base::MemoryMappedFile::Region region;
+ auto maybe_register = [&region, &regions, &files_to_register](int key,
+ int fd) {
+ if (fd != -1) {
+ files_to_register->Share(key, fd);
+ regions.insert(std::make_pair(key, region));
+ }
+ };
+ maybe_register(
+ kV8NativesDataDescriptor32,
+ gin::V8Initializer::GetOpenNativesFileForChildProcesses(&region, true));
+ maybe_register(
+ kV8NativesDataDescriptor64,
+ gin::V8Initializer::GetOpenNativesFileForChildProcesses(&region, false));
+ maybe_register(
+ kV8SnapshotDataDescriptor32,
+ gin::V8Initializer::GetOpenSnapshotFileForChildProcesses(&region, true));
+ maybe_register(
+ kV8SnapshotDataDescriptor64,
+ gin::V8Initializer::GetOpenSnapshotFileForChildProcesses(&region, false));
+
+ snapshot_loaded = true;
+#else
base::PlatformFile natives_pf =
gin::V8Initializer::GetOpenNativesFileForChildProcesses(
&regions[kV8NativesDataDescriptor]);
@@ -167,13 +217,15 @@ void LaunchOnLauncherThread(const NotifyCallback& callback,
// Failure to load the V8 snapshot is not necessarily an error. V8 can start
// up (slower) without the snapshot.
if (snapshot_pf != -1) {
+ snapshot_loaded = true;
files_to_register->Share(kV8SnapshotDataDescriptor, snapshot_pf);
regions.insert(std::make_pair(kV8SnapshotDataDescriptor, snapshot_region));
}
+#endif
if (process_type != switches::kZygoteProcess) {
cmd_line->AppendSwitch(::switches::kV8NativesPassedByFD);
- if (snapshot_pf != -1) {
+ if (snapshot_loaded) {
cmd_line->AppendSwitch(::switches::kV8SnapshotPassedByFD);
}
}
@@ -192,15 +244,24 @@ void LaunchOnLauncherThread(const NotifyCallback& callback,
StartChildProcess(
cmd_line->argv(), child_process_id, std::move(files_to_register), regions,
base::Bind(&OnChildProcessStartedAndroid, callback, client_thread_id,
- begin_launch_time, base::Passed(&ipcfd)));
+ begin_launch_time, base::Passed(&ipcfd),
+ base::Passed(&mojo_fd)));
#elif defined(OS_POSIX)
// We need to close the client end of the IPC channel to reliably detect
// child termination.
#if !defined(OS_MACOSX)
- if (use_zygote) {
- base::ProcessHandle handle = ZygoteHostImpl::GetInstance()->ForkRequest(
+ ZygoteHandle* zygote_handle = delegate->GetZygote();
+ // If |zygote_handle| is null, a zygote should not be used.
+ if (zygote_handle) {
+ // This code runs on the PROCESS_LAUNCHER thread so race conditions are not
+ // an issue with the lazy initialization.
+ if (*zygote_handle == nullptr) {
+ *zygote_handle = CreateZygote();
+ }
+ zygote = *zygote_handle;
+ base::ProcessHandle handle = zygote->ForkRequest(
cmd_line->argv(), std::move(files_to_register), process_type);
process = base::Process(handle);
} else
@@ -278,13 +339,11 @@ void LaunchOnLauncherThread(const NotifyCallback& callback,
begin_launch_time);
}
BrowserThread::PostTask(client_thread_id, FROM_HERE,
- base::Bind(callback,
- use_zygote,
- base::Passed(&process)));
+ base::Bind(callback, zygote, base::Passed(&process)));
#endif // !defined(OS_ANDROID)
}
-void TerminateOnLauncherThread(bool zygote, base::Process process) {
+void TerminateOnLauncherThread(ZygoteHandle zygote, base::Process process) {
DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
#if defined(OS_ANDROID)
VLOG(1) << "ChromeProcess: Stopping process with handle "
@@ -300,7 +359,7 @@ void TerminateOnLauncherThread(bool zygote, base::Process process) {
if (zygote) {
// If the renderer was created via a zygote, we have to proxy the reaping
// through the zygote process.
- ZygoteHostImpl::GetInstance()->EnsureProcessTerminated(process.Handle());
+ zygote->EnsureProcessTerminated(process.Handle());
} else
#endif // !OS_MACOSX
base::EnsureProcessTerminated(std::move(process));
@@ -330,7 +389,7 @@ ChildProcessLauncher::ChildProcessLauncher(
: client_(client),
termination_status_(base::TERMINATION_STATUS_NORMAL_TERMINATION),
exit_code_(RESULT_CODE_NORMAL_EXIT),
- zygote_(false),
+ zygote_(nullptr),
starting_(true),
#if defined(ADDRESS_SANITIZER) || defined(LEAK_SANITIZER) || \
defined(MEMORY_SANITIZER) || defined(THREAD_SANITIZER) || \
@@ -386,6 +445,8 @@ void ChildProcessLauncher::Launch(
NotifyCallback reply_callback(base::Bind(&ChildProcessLauncher::DidLaunch,
weak_factory_.GetWeakPtr(),
terminate_child_on_shutdown_));
+ mojo::edk::ScopedPlatformHandle client_handle =
+ mojo_platform_channel_.PassClientHandle();
BrowserThread::PostTask(
BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
base::Bind(&LaunchOnLauncherThread, reply_callback, client_thread_id_,
@@ -393,15 +454,15 @@ void ChildProcessLauncher::Launch(
#if defined(OS_ANDROID)
base::Passed(&ipcfd),
#endif
- cmd_line));
+ base::Passed(&client_handle), cmd_line));
}
void ChildProcessLauncher::UpdateTerminationStatus(bool known_dead) {
DCHECK(CalledOnValidThread());
#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
if (zygote_) {
- termination_status_ = ZygoteHostImpl::GetInstance()->
- GetTerminationStatus(process_.Handle(), known_dead, &exit_code_);
+ termination_status_ = zygote_->GetTerminationStatus(
+ process_.Handle(), known_dead, &exit_code_);
} else if (known_dead) {
termination_status_ =
base::GetKnownDeadTerminationStatus(process_.Handle(), &exit_code_);
@@ -434,9 +495,10 @@ void ChildProcessLauncher::SetProcessBackgrounded(bool background) {
void ChildProcessLauncher::DidLaunch(
base::WeakPtr<ChildProcessLauncher> instance,
bool terminate_on_shutdown,
- bool zygote,
+ ZygoteHandle zygote,
#if defined(OS_ANDROID)
base::ScopedFD ipcfd,
+ base::ScopedFD mojo_fd,
#endif
base::Process process) {
if (!process.IsValid())
@@ -459,16 +521,21 @@ void ChildProcessLauncher::DidLaunch(
}
}
-void ChildProcessLauncher::Notify(
- bool zygote,
+void ChildProcessLauncher::Notify(ZygoteHandle zygote,
#if defined(OS_ANDROID)
- base::ScopedFD ipcfd,
+ base::ScopedFD ipcfd,
#endif
- base::Process process) {
+ base::Process process) {
DCHECK(CalledOnValidThread());
starting_ = false;
process_ = std::move(process);
+ if (process_.IsValid()) {
+ // Set up Mojo IPC to the new process.
+ mojo::edk::ChildProcessLaunched(process_.Handle(),
+ mojo_platform_channel_.PassServerHandle());
+ }
+
#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
zygote_ = zygote;
#endif
diff --git a/chromium/content/browser/child_process_launcher.h b/chromium/content/browser/child_process_launcher.h
index c4f63210af1..710247778bb 100644
--- a/chromium/content/browser/child_process_launcher.h
+++ b/chromium/content/browser/child_process_launcher.h
@@ -15,13 +15,14 @@
#include "build/build_config.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/common/sandboxed_process_launcher_delegate.h"
+#include "mojo/edk/embedder/platform_channel_pair.h"
namespace base {
class CommandLine;
}
namespace content {
-class SandboxedProcessLauncherDelegate;
// Launches a process asynchronously and notifies the client of the process
// handle when it's available. It's used to avoid blocking the calling thread
@@ -95,14 +96,15 @@ class CONTENT_EXPORT ChildProcessLauncher : public base::NonThreadSafe {
// client went away.
static void DidLaunch(base::WeakPtr<ChildProcessLauncher> instance,
bool terminate_on_shutdown,
- bool zygote,
+ ZygoteHandle zygote,
#if defined(OS_ANDROID)
base::ScopedFD ipcfd,
+ base::ScopedFD mojo_fd,
#endif
base::Process process);
// Notifies the client about the result of the operation.
- void Notify(bool zygote,
+ void Notify(ZygoteHandle zygote,
#if defined(OS_ANDROID)
base::ScopedFD ipcfd,
#endif
@@ -122,12 +124,15 @@ class CONTENT_EXPORT ChildProcessLauncher : public base::NonThreadSafe {
base::Process process_;
base::TerminationStatus termination_status_;
int exit_code_;
- bool zygote_;
+ ZygoteHandle zygote_;
bool starting_;
// Controls whether the child process should be terminated on browser
// shutdown. Default behavior is to terminate the child.
const bool terminate_child_on_shutdown_;
+ // Platform channel used to establish Mojo IPC.
+ mojo::edk::PlatformChannelPair mojo_platform_channel_;
+
base::WeakPtrFactory<ChildProcessLauncher> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ChildProcessLauncher);
diff --git a/chromium/content/browser/child_process_security_policy_impl.cc b/chromium/content/browser/child_process_security_policy_impl.cc
index 639401fc731..bd84239b04f 100644
--- a/chromium/content/browser/child_process_security_policy_impl.cc
+++ b/chromium/content/browser/child_process_security_policy_impl.cc
@@ -14,7 +14,6 @@
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "build/build_config.h"
-#include "content/browser/plugin_process_host.h"
#include "content/browser/site_instance_impl.h"
#include "content/common/site_isolation_policy.h"
#include "content/public/browser/child_process_data.h"
@@ -602,7 +601,7 @@ bool ChildProcessSecurityPolicyImpl::CanRequestURL(
if (base::LowerCaseEqualsASCII(url.spec(), url::kAboutBlankURL))
return true; // Every child process can request <about:blank>.
- // URLs like <about:memory> and <about:crash> shouldn't be requestable by
+ // URLs like <about:version> and <about:crash> shouldn't be requestable by
// any child process. Also, this case covers <javascript:...>, which should
// be handled internally by the process and not kicked up to the browser.
return false;
@@ -818,8 +817,11 @@ bool ChildProcessSecurityPolicyImpl::CanAccessDataForOrigin(int child_id,
const GURL& gurl) {
base::AutoLock lock(lock_);
SecurityStateMap::iterator state = security_state_.find(child_id);
- if (state == security_state_.end())
- return false;
+ if (state == security_state_.end()) {
+ // TODO(nick): Returning true instead of false here is a temporary
+ // workaround for https://crbug.com/600441
+ return true;
+ }
return state->second->CanAccessDataForOrigin(gurl);
}
diff --git a/chromium/content/browser/child_process_security_policy_unittest.cc b/chromium/content/browser/child_process_security_policy_unittest.cc
index 23604683ad3..455da447dd3 100644
--- a/chromium/content/browser/child_process_security_policy_unittest.cc
+++ b/chromium/content/browser/child_process_security_policy_unittest.cc
@@ -203,21 +203,22 @@ TEST_F(ChildProcessSecurityPolicyTest, AboutTest) {
EXPECT_TRUE(p->CanCommitURL(kRendererID, GURL("aBouT:BlAnK")));
EXPECT_TRUE(p->CanCommitURL(kRendererID, GURL("aBouT:blank")));
- EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:memory")));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:crash")));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:cache")));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:hang")));
- EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("about:memory")));
+ EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:version")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("about:crash")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("about:cache")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("about:hang")));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("about:version")));
- EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("aBoUt:memory")));
+ EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("aBoUt:version")));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("about:CrASh")));
EXPECT_FALSE(p->CanRequestURL(kRendererID, GURL("abOuT:cAChe")));
- EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("aBoUt:memory")));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("aBoUt:version")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("about:CrASh")));
EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("abOuT:cAChe")));
+ EXPECT_FALSE(p->CanCommitURL(kRendererID, GURL("aBoUt:version")));
// Requests for about: pages should be denied.
p->GrantRequestURL(kRendererID, GURL("about:crash"));
diff --git a/chromium/content/browser/cocoa/system_hotkey_helper_mac.h b/chromium/content/browser/cocoa/system_hotkey_helper_mac.h
index d8e0153fd63..004b2087c78 100644
--- a/chromium/content/browser/cocoa/system_hotkey_helper_mac.h
+++ b/chromium/content/browser/cocoa/system_hotkey_helper_mac.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_COCOA_SYSTEM_HOTKEY_HELPER_MAC_H_
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
#include "base/memory/weak_ptr.h"
diff --git a/chromium/content/browser/cocoa/system_hotkey_map.mm b/chromium/content/browser/cocoa/system_hotkey_map.mm
index da04fa8b844..6ee40574420 100644
--- a/chromium/content/browser/cocoa/system_hotkey_map.mm
+++ b/chromium/content/browser/cocoa/system_hotkey_map.mm
@@ -4,6 +4,10 @@
#import "content/browser/cocoa/system_hotkey_map.h"
+#import <Carbon/Carbon.h>
+
+#include "base/mac/scoped_nsobject.h"
+
#pragma mark - NSDictionary Helper Functions
namespace {
@@ -75,11 +79,32 @@ bool SystemHotkeyMap::ParseDictionary(NSDictionary* dictionary) {
if (!dictionary)
return false;
- NSDictionary* hotkey_dictionaries =
+ NSDictionary* user_hotkey_dictionaries =
DictionaryForKey(dictionary, @"AppleSymbolicHotKeys");
- if (!hotkey_dictionaries)
+ if (!user_hotkey_dictionaries)
return false;
+ // Start with a dictionary of default OS X hotkeys that are not necessarily
+ // listed in com.apple.symbolichotkeys.plist, but should still be handled as
+ // reserved.
+ // If the user has overridden or disabled any of these hotkeys,
+ // -NSMutableDictionary addEntriesFromDictionary:] will ensure that the new
+ // values are used.
+ // See https://crbug.com/145062#c8
+ base::scoped_nsobject<NSMutableDictionary> hotkey_dictionaries([@{
+ // Default Window switch key binding: Command + `
+ // Note: The first parameter @96 is not used by |SystemHotkeyMap|.
+ @"27" : @{
+ @"enabled" : @YES,
+ @"value" : @{
+ @"type" : @"standard",
+ @"parameters" :
+ @[ @96 /* unused */, @(kVK_ANSI_Grave), @(NSCommandKeyMask) ],
+ }
+ }
+ } mutableCopy]);
+ [hotkey_dictionaries addEntriesFromDictionary:user_hotkey_dictionaries];
+
for (NSString* hotkey_system_effect in [hotkey_dictionaries allKeys]) {
if (![hotkey_system_effect isKindOfClass:[NSString class]])
continue;
diff --git a/chromium/content/browser/cocoa/system_hotkey_map_unittest.mm b/chromium/content/browser/cocoa/system_hotkey_map_unittest.mm
index 37638d472ac..a0798bec241 100644
--- a/chromium/content/browser/cocoa/system_hotkey_map_unittest.mm
+++ b/chromium/content/browser/cocoa/system_hotkey_map_unittest.mm
@@ -134,13 +134,13 @@ TEST_F(SystemHotkeyMapTest, ParseMouse) {
bool result = map.ParseDictionary(dictionary);
EXPECT_TRUE(result);
- // Command + ` is a common key binding. It is missing.
- // TODO(erikchen): OSX uses the default value when the keybinding is missing,
- // so the hotkey should still be reserved.
- // http://crbug.com/383558
+ // Command + ` is a common key binding. It is missing, but since OS X uses the
+ // default value the hotkey should still be reserved.
+ // https://crbug.com/383558
+ // https://crbug.com/145062
unsigned short key_code = kVK_ANSI_Grave;
NSUInteger modifiers = NSCommandKeyMask;
- EXPECT_FALSE(map.IsHotkeyReserved(key_code, modifiers));
+ EXPECT_TRUE(map.IsHotkeyReserved(key_code, modifiers));
// There is a mouse keybinding for 0x08. It should not apply to keyboard
// hotkeys.
diff --git a/chromium/content/browser/compositor/browser_compositor_output_surface.h b/chromium/content/browser/compositor/browser_compositor_output_surface.h
index 6e5ac7796b2..b3b9a4bd7a7 100644
--- a/chromium/content/browser/compositor/browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/browser_compositor_output_surface.h
@@ -36,7 +36,7 @@ class CONTENT_EXPORT BrowserCompositorOutputSurface
bool BindToClient(cc::OutputSurfaceClient* client) override;
cc::OverlayCandidateValidator* GetOverlayCandidateValidator() const override;
- // ui::CompositorOutputSurface::Observer implementation.
+ // ui::CompositorVSyncManager::Observer implementation.
void OnUpdateVSyncParameters(base::TimeTicks timebase,
base::TimeDelta interval) override;
diff --git a/chromium/content/browser/compositor/browser_compositor_overlay_candidate_validator_mac.mm b/chromium/content/browser/compositor/browser_compositor_overlay_candidate_validator_mac.mm
index 2b1c3eca645..3e9886b0fc9 100644
--- a/chromium/content/browser/compositor/browser_compositor_overlay_candidate_validator_mac.mm
+++ b/chromium/content/browser/compositor/browser_compositor_overlay_candidate_validator_mac.mm
@@ -6,9 +6,10 @@
#include <stddef.h>
-#include "cc/output/overlay_strategy_sandwich.h"
+#include "base/command_line.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "gpu/config/gpu_driver_bug_workaround_type.h"
+#include "ui/base/ui_base_switches.h"
namespace content {
@@ -31,7 +32,11 @@ void BrowserCompositorOverlayCandidateValidatorMac::GetStrategies(
}
bool BrowserCompositorOverlayCandidateValidatorMac::AllowCALayerOverlays() {
- if (software_mirror_active_ || ca_layers_disabled_)
+ static bool overlays_disabled_at_command_line =
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableMacOverlays);
+ if (software_mirror_active_ || ca_layers_disabled_ ||
+ overlays_disabled_at_command_line)
return false;
return true;
}
diff --git a/chromium/content/browser/compositor/buffer_queue.cc b/chromium/content/browser/compositor/buffer_queue.cc
index dbe2ee24b7c..cafb6d96a18 100644
--- a/chromium/content/browser/compositor/buffer_queue.cc
+++ b/chromium/content/browser/compositor/buffer_queue.cc
@@ -6,12 +6,13 @@
#include "base/containers/adapters.h"
#include "build/build_config.h"
+#include "content/browser/compositor/gl_helper.h"
#include "content/browser/compositor/image_transport_factory.h"
-#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
-#include "content/common/gpu/client/gl_helper.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
+#include "gpu/command_buffer/common/gpu_memory_buffer_support.h"
#include "gpu/command_buffer/service/image_factory.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/core/SkRegion.h"
@@ -20,13 +21,12 @@
namespace content {
-BufferQueue::BufferQueue(
- scoped_refptr<cc::ContextProvider> context_provider,
- unsigned int texture_target,
- unsigned int internalformat,
- GLHelper* gl_helper,
- BrowserGpuMemoryBufferManager* gpu_memory_buffer_manager,
- int surface_id)
+BufferQueue::BufferQueue(scoped_refptr<cc::ContextProvider> context_provider,
+ unsigned int texture_target,
+ unsigned int internalformat,
+ GLHelper* gl_helper,
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
+ int surface_id)
: context_provider_(context_provider),
fbo_(0),
allocated_count_(0),
@@ -222,10 +222,9 @@ scoped_ptr<BufferQueue::AllocatedSurface> BufferQueue::GetNextSurface() {
DCHECK_LT(allocated_count_, 4U);
scoped_ptr<gfx::GpuMemoryBuffer> buffer(
- gpu_memory_buffer_manager_->AllocateGpuMemoryBufferForScanout(
- size_, gpu::ImageFactory::DefaultBufferFormatForImageFormat(
- internal_format_),
- surface_id_));
+ gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer(
+ size_, gpu::DefaultBufferFormatForImageFormat(internal_format_),
+ gfx::BufferUsage::SCANOUT, surface_id_));
if (!buffer.get()) {
gl->DeleteTextures(1, &texture);
DLOG(ERROR) << "Failed to allocate GPU memory buffer";
diff --git a/chromium/content/browser/compositor/buffer_queue.h b/chromium/content/browser/compositor/buffer_queue.h
index 4c7d9439f9d..47b4a7dd00a 100644
--- a/chromium/content/browser/compositor/buffer_queue.h
+++ b/chromium/content/browser/compositor/buffer_queue.h
@@ -25,9 +25,12 @@ namespace gfx {
class GpuMemoryBuffer;
}
+namespace gpu {
+class GpuMemoryBufferManager;
+}
+
namespace content {
-class BrowserGpuMemoryBufferManager;
class GLHelper;
// Provides a surface that manages its own buffers, backed by GpuMemoryBuffers
@@ -40,7 +43,7 @@ class CONTENT_EXPORT BufferQueue {
unsigned int texture_target,
unsigned int internalformat,
GLHelper* gl_helper,
- BrowserGpuMemoryBufferManager* gpu_memory_buffer_manager,
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager,
int surface_id);
virtual ~BufferQueue();
@@ -112,7 +115,7 @@ class CONTENT_EXPORT BufferQueue {
// may be nullptr, if they represent frames that have been destroyed.
std::deque<scoped_ptr<AllocatedSurface>> in_flight_surfaces_;
GLHelper* gl_helper_;
- BrowserGpuMemoryBufferManager* gpu_memory_buffer_manager_;
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_;
int surface_id_;
DISALLOW_COPY_AND_ASSIGN(BufferQueue);
diff --git a/chromium/content/browser/compositor/buffer_queue_unittest.cc b/chromium/content/browser/compositor/buffer_queue_unittest.cc
index 323d7ae8fd2..6e1dc9f05af 100644
--- a/chromium/content/browser/compositor/buffer_queue_unittest.cc
+++ b/chromium/content/browser/compositor/buffer_queue_unittest.cc
@@ -11,9 +11,9 @@
#include "cc/test/test_context_provider.h"
#include "cc/test/test_web_graphics_context_3d.h"
+#include "content/browser/compositor/gl_helper.h"
#include "content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h"
#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
-#include "content/common/gpu/client/gl_helper.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -57,10 +57,15 @@ class StubBrowserGpuMemoryBufferManager : public BrowserGpuMemoryBufferManager {
void set_allocate_succeeds(bool value) { allocate_succeeds_ = value; }
- scoped_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBufferForScanout(
+ scoped_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer(
const gfx::Size& size,
gfx::BufferFormat format,
+ gfx::BufferUsage usage,
int32_t surface_id) override {
+ if (!surface_id) {
+ return BrowserGpuMemoryBufferManager::AllocateGpuMemoryBuffer(
+ size, format, usage, surface_id);
+ }
if (allocate_succeeds_)
return make_scoped_ptr<gfx::GpuMemoryBuffer>(new StubGpuMemoryBufferImpl);
return nullptr;
diff --git a/chromium/content/common/gpu/client/gl_helper.cc b/chromium/content/browser/compositor/gl_helper.cc
index 5549caaacb8..55493e90068 100644
--- a/chromium/content/common/gpu/client/gl_helper.cc
+++ b/chromium/content/browser/compositor/gl_helper.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/common/gpu/client/gl_helper.h"
+#include "content/browser/compositor/gl_helper.h"
#include <stddef.h>
#include <stdint.h>
@@ -19,8 +19,8 @@
#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
-#include "content/common/gpu/client/gl_helper_readback_support.h"
-#include "content/common/gpu/client/gl_helper_scaling.h"
+#include "content/browser/compositor/gl_helper_readback_support.h"
+#include "content/browser/compositor/gl_helper_scaling.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/common/mailbox.h"
@@ -55,19 +55,12 @@ class TextureFrameBufferPair {
TextureFrameBufferPair(GLES2Interface* gl, gfx::Size size)
: texture_(gl), framebuffer_(gl), size_(size) {
content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl, texture_);
- gl->TexImage2D(GL_TEXTURE_2D,
- 0,
- GL_RGBA,
- size.width(),
- size.height(),
- 0,
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- NULL);
+ gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
content::ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(
gl, framebuffer_);
- gl->FramebufferTexture2D(
- GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture_, 0);
+ gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_TEXTURE_2D, texture_, 0);
}
GLuint texture() const { return texture_.id(); }
@@ -255,9 +248,8 @@ class GLHelper::CopyTextureToImpl
delete request;
}
}
- void Add(Request* r) {
- requests_.push(r);
- }
+ void Add(Request* r) { requests_.push(r); }
+
private:
std::queue<Request*> requests_;
DISALLOW_COPY_AND_ASSIGN(FinishRequestHelper);
@@ -370,7 +362,7 @@ class GLHelper::CopyTextureToImpl
bool swizzle);
static void nullcallback(bool success) {}
- void ReadbackDone(Request *request, int bytes_per_pixel);
+ void ReadbackDone(Request* request, int bytes_per_pixel);
void FinishRequest(Request* request,
bool result,
FinishRequestHelper* helper);
@@ -400,12 +392,8 @@ GLHelper::ScalerInterface* GLHelper::CreateScaler(ScalerQuality quality,
bool vertically_flip_texture,
bool swizzle) {
InitScalerImpl();
- return scaler_impl_->CreateScaler(quality,
- src_size,
- src_subrect,
- dst_size,
- vertically_flip_texture,
- swizzle);
+ return scaler_impl_->CreateScaler(quality, src_size, src_subrect, dst_size,
+ vertically_flip_texture, swizzle);
}
GLuint GLHelper::CopyTextureToImpl::ScaleTexture(
@@ -430,23 +418,12 @@ GLuint GLHelper::CopyTextureToImpl::ScaleTexture(
type = GL_UNSIGNED_SHORT_5_6_5;
}
- gl_->TexImage2D(GL_TEXTURE_2D,
- 0,
- format,
- dst_size.width(),
- dst_size.height(),
- 0,
- format,
- type,
- NULL);
+ gl_->TexImage2D(GL_TEXTURE_2D, 0, format, dst_size.width(),
+ dst_size.height(), 0, format, type, NULL);
}
scoped_ptr<ScalerInterface> scaler(
- helper_->CreateScaler(quality,
- src_size,
- src_subrect,
- dst_size,
- vertically_flip_texture,
- swizzle));
+ helper_->CreateScaler(quality, src_size, src_subrect, dst_size,
+ vertically_flip_texture, swizzle));
scaler->Scale(src_texture, dst_texture);
return dst_texture;
}
@@ -464,15 +441,9 @@ GLuint GLHelper::CopyTextureToImpl::EncodeTextureAsGrayscale(
gfx::Size((src_size.width() + 3) / 4, src_size.height());
{
ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, dst_texture);
- gl_->TexImage2D(GL_TEXTURE_2D,
- 0,
- GL_RGBA,
- encoded_texture_size->width(),
- encoded_texture_size->height(),
- 0,
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- NULL);
+ gl_->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, encoded_texture_size->width(),
+ encoded_texture_size->height(), 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, NULL);
}
helper_->InitScalerImpl();
@@ -480,9 +451,7 @@ GLuint GLHelper::CopyTextureToImpl::EncodeTextureAsGrayscale(
helper_->scaler_impl_.get()->CreatePlanarScaler(
src_size,
gfx::Rect(0, 0, (src_size.width() + 3) & ~3, src_size.height()),
- *encoded_texture_size,
- vertically_flip_texture,
- swizzle,
+ *encoded_texture_size, vertically_flip_texture, swizzle,
kRGBtoGrayscaleColorWeights));
grayscale_scaler->Scale(src_texture, dst_texture);
return dst_texture;
@@ -506,26 +475,18 @@ void GLHelper::CopyTextureToImpl::ReadbackAsync(
gl_->GenBuffers(1, &request->buffer);
gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, request->buffer);
gl_->BufferData(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM,
- bytes_per_pixel * dst_size.GetArea(),
- NULL,
- GL_STREAM_READ);
+ bytes_per_pixel * dst_size.GetArea(), NULL, GL_STREAM_READ);
request->query = 0u;
gl_->GenQueriesEXT(1, &request->query);
gl_->BeginQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM, request->query);
- gl_->ReadPixels(0,
- 0,
- dst_size.width(),
- dst_size.height(),
- format,
- type,
+ gl_->ReadPixels(0, 0, dst_size.width(), dst_size.height(), format, type,
NULL);
gl_->EndQueryEXT(GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM);
gl_->BindBuffer(GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM, 0);
context_support_->SignalQuery(
- request->query,
- base::Bind(&CopyTextureToImpl::ReadbackDone, AsWeakPtr(),
- request, bytes_per_pixel));
+ request->query, base::Bind(&CopyTextureToImpl::ReadbackDone, AsWeakPtr(),
+ request, bytes_per_pixel));
}
void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture(
@@ -548,8 +509,8 @@ void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture(
readback_color_type = kRGBA_8888_SkColorType;
}
- FormatSupport supported = GetReadbackConfig(
- readback_color_type, true, &format, &type, &bytes_per_pixel);
+ FormatSupport supported = GetReadbackConfig(readback_color_type, true,
+ &format, &type, &bytes_per_pixel);
if (supported == GLHelperReadbackSupport::NOT_SUPPORTED) {
callback.Run(false);
@@ -571,16 +532,11 @@ void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture(
bool scale_swizzle = out_color_type == kAlpha_8_SkColorType
? false
: supported == GLHelperReadbackSupport::SWIZZLE;
- texture =
- ScaleTexture(src_texture,
- src_size,
- src_subrect,
- dst_size,
- true,
- scale_swizzle,
- out_color_type == kAlpha_8_SkColorType ? kN32_SkColorType
- : out_color_type,
- quality);
+ texture = ScaleTexture(src_texture, src_size, src_subrect, dst_size, true,
+ scale_swizzle, out_color_type == kAlpha_8_SkColorType
+ ? kN32_SkColorType
+ : out_color_type,
+ quality);
DCHECK(texture);
}
@@ -593,12 +549,9 @@ void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture(
// EncodeTextureAsGrayscale by default creates a texture which should be
// read back as RGBA, so need to swizzle if the readback format is BGRA.
bool encode_as_grayscale_swizzle = format == GL_BGRA_EXT;
- GLuint tmp_texture =
- EncodeTextureAsGrayscale(texture,
- dst_size,
- &readback_texture_size,
- encode_as_grayscale_vertical_flip,
- encode_as_grayscale_swizzle);
+ GLuint tmp_texture = EncodeTextureAsGrayscale(
+ texture, dst_size, &readback_texture_size,
+ encode_as_grayscale_vertical_flip, encode_as_grayscale_swizzle);
// If the scaled texture was created - delete it
if (scale_texture)
gl_->DeleteTextures(1, &texture);
@@ -611,32 +564,22 @@ void GLHelper::CopyTextureToImpl::CropScaleReadbackAndCleanTexture(
ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
dst_framebuffer);
ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
- gl_->FramebufferTexture2D(GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D,
- texture,
- 0);
+ gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ texture, 0);
int32_t bytes_per_row = out_color_type == kAlpha_8_SkColorType
? dst_size.width()
: dst_size.width() * bytes_per_pixel;
- ReadbackAsync(readback_texture_size,
- bytes_per_row,
- bytes_per_row,
- out,
- format,
- type,
- bytes_per_pixel,
- callback);
+ ReadbackAsync(readback_texture_size, bytes_per_row, bytes_per_row, out,
+ format, type, bytes_per_pixel, callback);
gl_->DeleteTextures(1, &texture);
}
-void GLHelper::CopyTextureToImpl::ReadbackTextureSync(
- GLuint texture,
- const gfx::Rect& src_rect,
- unsigned char* out,
- SkColorType color_type) {
+void GLHelper::CopyTextureToImpl::ReadbackTextureSync(GLuint texture,
+ const gfx::Rect& src_rect,
+ unsigned char* out,
+ SkColorType color_type) {
GLenum format, type;
size_t bytes_per_pixel;
FormatSupport supported =
@@ -649,15 +592,10 @@ void GLHelper::CopyTextureToImpl::ReadbackTextureSync(
ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
dst_framebuffer);
ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
- gl_->FramebufferTexture2D(
- GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
- gl_->ReadPixels(src_rect.x(),
- src_rect.y(),
- src_rect.width(),
- src_rect.height(),
- format,
- type,
- out);
+ gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ texture, 0);
+ gl_->ReadPixels(src_rect.x(), src_rect.y(), src_rect.width(),
+ src_rect.height(), format, type, out);
}
void GLHelper::CopyTextureToImpl::ReadbackTextureAsync(
@@ -679,19 +617,11 @@ void GLHelper::CopyTextureToImpl::ReadbackTextureAsync(
ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
dst_framebuffer);
ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
- gl_->FramebufferTexture2D(GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D,
- texture,
- 0);
- ReadbackAsync(dst_size,
- dst_size.width() * bytes_per_pixel,
- dst_size.width() * bytes_per_pixel,
- out,
- format,
- type,
- bytes_per_pixel,
- callback);
+ gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ texture, 0);
+ ReadbackAsync(dst_size, dst_size.width() * bytes_per_pixel,
+ dst_size.width() * bytes_per_pixel, out, format, type,
+ bytes_per_pixel, callback);
}
GLuint GLHelper::CopyTextureToImpl::CopyAndScaleTexture(
@@ -700,12 +630,8 @@ GLuint GLHelper::CopyTextureToImpl::CopyAndScaleTexture(
const gfx::Size& dst_size,
bool vertically_flip_texture,
GLHelper::ScalerQuality quality) {
- return ScaleTexture(src_texture,
- src_size,
- gfx::Rect(src_size),
- dst_size,
- vertically_flip_texture,
- false,
+ return ScaleTexture(src_texture, src_size, gfx::Rect(src_size), dst_size,
+ vertically_flip_texture, false,
kRGBA_8888_SkColorType, // GL_RGBA
quality);
}
@@ -808,14 +734,9 @@ void GLHelper::CropScaleReadbackAndCleanTexture(
const base::Callback<void(bool)>& callback,
GLHelper::ScalerQuality quality) {
InitCopyTextToImpl();
- copy_texture_to_impl_->CropScaleReadbackAndCleanTexture(src_texture,
- src_size,
- src_subrect,
- dst_size,
- out,
- out_color_type,
- callback,
- quality);
+ copy_texture_to_impl_->CropScaleReadbackAndCleanTexture(
+ src_texture, src_size, src_subrect, dst_size, out, out_color_type,
+ callback, quality);
}
void GLHelper::CropScaleReadbackAndCleanMailbox(
@@ -829,13 +750,8 @@ void GLHelper::CropScaleReadbackAndCleanMailbox(
const base::Callback<void(bool)>& callback,
GLHelper::ScalerQuality quality) {
GLuint mailbox_texture = ConsumeMailboxToTexture(src_mailbox, sync_token);
- CropScaleReadbackAndCleanTexture(mailbox_texture,
- src_size,
- src_subrect,
- dst_size,
- out,
- out_color_type,
- callback,
+ CropScaleReadbackAndCleanTexture(mailbox_texture, src_size, src_subrect,
+ dst_size, out, out_color_type, callback,
quality);
gl_->DeleteTextures(1, &mailbox_texture);
}
@@ -855,11 +771,8 @@ void GLHelper::ReadbackTextureAsync(
SkColorType color_type,
const base::Callback<void(bool)>& callback) {
InitCopyTextToImpl();
- copy_texture_to_impl_->ReadbackTextureAsync(texture,
- dst_size,
- out,
- color_type,
- callback);
+ copy_texture_to_impl_->ReadbackTextureAsync(texture, dst_size, out,
+ color_type, callback);
}
GLuint GLHelper::CopyTexture(GLuint texture, const gfx::Size& size) {
@@ -891,8 +804,8 @@ GLuint GLHelper::CompileShaderFromSource(const GLchar* source, GLenum type) {
if (log_length) {
scoped_ptr<GLchar[]> log(new GLchar[log_length]);
GLsizei returned_log_length = 0;
- gl_->GetShaderInfoLog(
- shader, log_length, &returned_log_length, log.get());
+ gl_->GetShaderInfoLog(shader, log_length, &returned_log_length,
+ log.get());
LOG(ERROR) << std::string(log.get(), returned_log_length);
}
gl_->DeleteShader(shader);
@@ -992,33 +905,20 @@ GLuint GLHelper::ConsumeMailboxToTexture(const gpu::Mailbox& mailbox,
void GLHelper::ResizeTexture(GLuint texture, const gfx::Size& size) {
content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
- gl_->TexImage2D(GL_TEXTURE_2D,
- 0,
- GL_RGB,
- size.width(),
- size.height(),
- 0,
- GL_RGB,
- GL_UNSIGNED_BYTE,
- NULL);
+ gl_->TexImage2D(GL_TEXTURE_2D, 0, GL_RGB, size.width(), size.height(), 0,
+ GL_RGB, GL_UNSIGNED_BYTE, NULL);
}
void GLHelper::CopyTextureSubImage(GLuint texture, const gfx::Rect& rect) {
content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
- gl_->CopyTexSubImage2D(GL_TEXTURE_2D,
- 0,
- rect.x(),
- rect.y(),
- rect.x(),
- rect.y(),
- rect.width(),
- rect.height());
+ gl_->CopyTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.x(),
+ rect.y(), rect.width(), rect.height());
}
void GLHelper::CopyTextureFullImage(GLuint texture, const gfx::Size& size) {
content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, texture);
- gl_->CopyTexImage2D(
- GL_TEXTURE_2D, 0, GL_RGB, 0, 0, size.width(), size.height(), 0);
+ gl_->CopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 0, 0, size.width(),
+ size.height(), 0);
}
void GLHelper::Flush() {
@@ -1039,15 +939,11 @@ void GLHelper::CopyTextureToImpl::ReadbackPlane(
const base::Callback<void(bool)>& callback) {
gl_->BindFramebuffer(GL_FRAMEBUFFER, source->framebuffer());
const size_t offset = target->stride(plane) * (paste_rect.y() >> size_shift) +
- (paste_rect.x() >> size_shift);
- ReadbackAsync(source->size(),
- paste_rect.width() >> size_shift,
- target->stride(plane),
- target->data(plane) + offset,
+ (paste_rect.x() >> size_shift);
+ ReadbackAsync(source->size(), paste_rect.width() >> size_shift,
+ target->stride(plane), target->data(plane) + offset,
(swizzle == kSwizzleBGRA) ? GL_BGRA_EXT : GL_RGBA,
- GL_UNSIGNED_BYTE,
- 4,
- callback);
+ GL_UNSIGNED_BYTE, 4, callback);
}
const float GLHelper::CopyTextureToImpl::kRGBtoYColorWeights[] = {
@@ -1085,10 +981,7 @@ GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUVImpl(
y_(gl,
scaler_impl->CreatePlanarScaler(
dst_size,
- gfx::Rect(0,
- 0,
- (dst_size.width() + 3) & ~3,
- dst_size.height()),
+ gfx::Rect(0, 0, (dst_size.width() + 3) & ~3, dst_size.height()),
gfx::Size((dst_size.width() + 3) / 4, dst_size.height()),
false,
(swizzle == kSwizzleBGRA),
@@ -1100,8 +993,7 @@ GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUVImpl(
0,
(dst_size.width() + 7) & ~7,
(dst_size.height() + 1) & ~1),
- gfx::Size((dst_size.width() + 7) / 8,
- (dst_size.height() + 1) / 2),
+ gfx::Size((dst_size.width() + 7) / 8, (dst_size.height() + 1) / 2),
false,
(swizzle == kSwizzleBGRA),
kRGBtoUColorWeights)),
@@ -1112,8 +1004,7 @@ GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUVImpl(
0,
(dst_size.width() + 7) & ~7,
(dst_size.height() + 1) & ~1),
- gfx::Size((dst_size.width() + 7) / 8,
- (dst_size.height() + 1) / 2),
+ gfx::Size((dst_size.width() + 7) / 8, (dst_size.height() + 1) / 2),
false,
(swizzle == kSwizzleBGRA),
kRGBtoVColorWeights)) {
@@ -1158,27 +1049,15 @@ void GLHelper::CopyTextureToImpl::ReadbackYUVImpl::ReadbackYUV(
// Read back planes, one at a time. Keep the video frame alive while doing the
// readback.
- copy_impl_->ReadbackPlane(y_.texture_and_framebuffer(),
- target,
- media::VideoFrame::kYPlane,
- 0,
- paste_rect,
- swizzle_,
+ copy_impl_->ReadbackPlane(y_.texture_and_framebuffer(), target,
+ media::VideoFrame::kYPlane, 0, paste_rect, swizzle_,
base::Bind(&nullcallback));
- copy_impl_->ReadbackPlane(u_.texture_and_framebuffer(),
- target,
- media::VideoFrame::kUPlane,
- 1,
- paste_rect,
- swizzle_,
+ copy_impl_->ReadbackPlane(u_.texture_and_framebuffer(), target,
+ media::VideoFrame::kUPlane, 1, paste_rect, swizzle_,
base::Bind(&nullcallback));
copy_impl_->ReadbackPlane(
- v_.texture_and_framebuffer(),
- target,
- media::VideoFrame::kVPlane,
- 1,
- paste_rect,
- swizzle_,
+ v_.texture_and_framebuffer(), target, media::VideoFrame::kVPlane, 1,
+ paste_rect, swizzle_,
base::Bind(&CallbackKeepingVideoFrameAlive, target, callback));
gl_->BindFramebuffer(GL_FRAMEBUFFER, 0);
media::LetterboxYUV(target.get(), paste_rect);
@@ -1217,36 +1096,23 @@ GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV_MRT(
GLHelperScaling::SHADER_YUV_MRT_PASS1)),
pass2_shader_(scaler_impl->CreateYuvMrtShader(
gfx::Size((dst_size.width() + 3) / 4, dst_size.height()),
- gfx::Rect(0,
- 0,
- (dst_size.width() + 7) / 8 * 2,
- dst_size.height()),
- gfx::Size((dst_size.width() + 7) / 8,
- (dst_size.height() + 1) / 2),
+ gfx::Rect(0, 0, (dst_size.width() + 7) / 8 * 2, dst_size.height()),
+ gfx::Size((dst_size.width() + 7) / 8, (dst_size.height() + 1) / 2),
false,
(swizzle == kSwizzleBGRA),
GLHelperScaling::SHADER_YUV_MRT_PASS2)),
y_(gl, gfx::Size((dst_size.width() + 3) / 4, dst_size.height())),
uv_(gl),
u_(gl,
- gfx::Size((dst_size.width() + 7) / 8,
- (dst_size.height() + 1) / 2)),
+ gfx::Size((dst_size.width() + 7) / 8, (dst_size.height() + 1) / 2)),
v_(gl,
- gfx::Size((dst_size.width() + 7) / 8,
- (dst_size.height() + 1) / 2)) {
+ gfx::Size((dst_size.width() + 7) / 8, (dst_size.height() + 1) / 2)) {
DCHECK(!(dst_size.width() & 1));
DCHECK(!(dst_size.height() & 1));
content::ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl, uv_);
- gl->TexImage2D(GL_TEXTURE_2D,
- 0,
- GL_RGBA,
- (dst_size.width() + 3) / 4,
- dst_size.height(),
- 0,
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- NULL);
+ gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (dst_size.width() + 3) / 4,
+ dst_size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
}
void GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV(
@@ -1293,27 +1159,12 @@ void GLHelper::CopyTextureToImpl::ReadbackYUV_MRT::ReadbackYUV(
}
// Read back planes, one at a time.
- copy_impl_->ReadbackPlane(&y_,
- target,
- media::VideoFrame::kYPlane,
- 0,
- paste_rect,
- swizzle_,
- base::Bind(&nullcallback));
- copy_impl_->ReadbackPlane(&u_,
- target,
- media::VideoFrame::kUPlane,
- 1,
- paste_rect,
- swizzle_,
- base::Bind(&nullcallback));
+ copy_impl_->ReadbackPlane(&y_, target, media::VideoFrame::kYPlane, 0,
+ paste_rect, swizzle_, base::Bind(&nullcallback));
+ copy_impl_->ReadbackPlane(&u_, target, media::VideoFrame::kUPlane, 1,
+ paste_rect, swizzle_, base::Bind(&nullcallback));
copy_impl_->ReadbackPlane(
- &v_,
- target,
- media::VideoFrame::kVPlane,
- 1,
- paste_rect,
- swizzle_,
+ &v_, target, media::VideoFrame::kVPlane, 1, paste_rect, swizzle_,
base::Bind(&CallbackKeepingVideoFrameAlive, target, callback));
gl_->BindFramebuffer(GL_FRAMEBUFFER, 0);
media::LetterboxYUV(target.get(), paste_rect);
@@ -1341,8 +1192,8 @@ ReadbackYUVInterface* GLHelper::CopyTextureToImpl::CreateReadbackPipelineYUV(
// ReadbackPlane() we will choose GL_RGBA/GL_BGRA_EXT based on swizzle
GLenum format, type;
size_t bytes_per_pixel;
- FormatSupport supported = GetReadbackConfig(
- kRGBA_8888_SkColorType, true, &format, &type, &bytes_per_pixel);
+ FormatSupport supported = GetReadbackConfig(kRGBA_8888_SkColorType, true,
+ &format, &type, &bytes_per_pixel);
DCHECK((format == GL_RGBA || format == GL_BGRA_EXT) &&
type == GL_UNSIGNED_BYTE);
@@ -1351,24 +1202,12 @@ ReadbackYUVInterface* GLHelper::CopyTextureToImpl::CreateReadbackPipelineYUV(
swizzle = kSwizzleBGRA;
if (max_draw_buffers_ >= 2 && use_mrt) {
- return new ReadbackYUV_MRT(gl_,
- this,
- helper_->scaler_impl_.get(),
- quality,
- src_size,
- src_subrect,
- dst_size,
- flip_vertically,
+ return new ReadbackYUV_MRT(gl_, this, helper_->scaler_impl_.get(), quality,
+ src_size, src_subrect, dst_size, flip_vertically,
swizzle);
}
- return new ReadbackYUVImpl(gl_,
- this,
- helper_->scaler_impl_.get(),
- quality,
- src_size,
- src_subrect,
- dst_size,
- flip_vertically,
+ return new ReadbackYUVImpl(gl_, this, helper_->scaler_impl_.get(), quality,
+ src_size, src_subrect, dst_size, flip_vertically,
swizzle);
}
@@ -1380,12 +1219,8 @@ ReadbackYUVInterface* GLHelper::CreateReadbackPipelineYUV(
bool flip_vertically,
bool use_mrt) {
InitCopyTextToImpl();
- return copy_texture_to_impl_->CreateReadbackPipelineYUV(quality,
- src_size,
- src_subrect,
- dst_size,
- flip_vertically,
- use_mrt);
+ return copy_texture_to_impl_->CreateReadbackPipelineYUV(
+ quality, src_size, src_subrect, dst_size, flip_vertically, use_mrt);
}
} // namespace content
diff --git a/chromium/content/common/gpu/client/gl_helper.h b/chromium/content/browser/compositor/gl_helper.h
index 2be3f5ae210..ebfc1a33c0b 100644
--- a/chromium/content/common/gpu/client/gl_helper.h
+++ b/chromium/content/browser/compositor/gl_helper.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_COMMON_GPU_CLIENT_GL_HELPER_H_
-#define CONTENT_COMMON_GPU_CLIENT_GL_HELPER_H_
+#ifndef CONTENT_BROWSER_COMPOSITOR_GL_HELPER_H_
+#define CONTENT_BROWSER_COMPOSITOR_GL_HELPER_H_
#include "base/atomicops.h"
#include "base/callback.h"
@@ -338,10 +338,7 @@ class CONTENT_EXPORT GLHelper {
// Creates |scaler_impl_| if NULL.
void InitScalerImpl();
- enum ReadbackSwizzle {
- kSwizzleNone = 0,
- kSwizzleBGRA
- };
+ enum ReadbackSwizzle { kSwizzleNone = 0, kSwizzleBGRA };
gpu::gles2::GLES2Interface* gl_;
gpu::ContextSupport* context_support_;
@@ -379,4 +376,4 @@ class CONTENT_EXPORT ReadbackYUVInterface {
} // namespace content
-#endif // CONTENT_COMMON_GPU_CLIENT_GL_HELPER_H_
+#endif // CONTENT_BROWSER_COMPOSITOR_GL_HELPER_H_
diff --git a/chromium/content/browser/compositor/gl_helper_benchmark.cc b/chromium/content/browser/compositor/gl_helper_benchmark.cc
new file mode 100644
index 00000000000..845d82a4264
--- /dev/null
+++ b/chromium/content/browser/compositor/gl_helper_benchmark.cc
@@ -0,0 +1,247 @@
+// 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 looks like a unit test, but it contains benchmarks and test
+// utilities intended for manual evaluation of the scalers in
+// gl_helper*. These tests produce output in the form of files and printouts,
+// but cannot really "fail". There is no point in making these tests part
+// of any test automation run.
+
+#include <stddef.h>
+#include <stdio.h>
+#include <cmath>
+#include <string>
+#include <vector>
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <GLES2/gl2extchromium.h>
+
+#include "base/at_exit.h"
+#include "base/command_line.h"
+#include "base/files/file_util.h"
+#include "base/macros.h"
+#include "base/strings/stringprintf.h"
+#include "base/time/time.h"
+#include "content/browser/compositor/gl_helper.h"
+#include "content/browser/compositor/gl_helper_scaling.h"
+#include "gpu/command_buffer/client/gl_in_process_context.h"
+#include "gpu/command_buffer/client/gles2_implementation.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkTypes.h"
+#include "ui/gfx/codec/png_codec.h"
+#include "ui/gl/gl_surface.h"
+
+namespace content {
+
+content::GLHelper::ScalerQuality kQualities[] = {
+ content::GLHelper::SCALER_QUALITY_BEST,
+ content::GLHelper::SCALER_QUALITY_GOOD,
+ content::GLHelper::SCALER_QUALITY_FAST,
+};
+
+const char* kQualityNames[] = {
+ "best", "good", "fast",
+};
+
+class GLHelperTest : public testing::Test {
+ protected:
+ void SetUp() override {
+ gpu::gles2::ContextCreationAttribHelper attributes;
+ attributes.alpha_size = 8;
+ attributes.depth_size = 24;
+ attributes.red_size = 8;
+ attributes.green_size = 8;
+ attributes.blue_size = 8;
+ attributes.stencil_size = 8;
+ attributes.samples = 4;
+ attributes.sample_buffers = 1;
+ attributes.bind_generates_resource = false;
+
+ context_.reset(gpu::GLInProcessContext::Create(
+ nullptr, /* service */
+ nullptr, /* surface */
+ true, /* offscreen */
+ gfx::kNullAcceleratedWidget, /* window */
+ gfx::Size(1, 1), /* size */
+ nullptr, /* share_context */
+ attributes, gfx::PreferDiscreteGpu,
+ ::gpu::GLInProcessContextSharedMemoryLimits(),
+ nullptr, /* gpu_memory_buffer_manager */
+ nullptr /* image_factory */));
+ gl_ = context_->GetImplementation();
+ gpu::ContextSupport* support = context_->GetImplementation();
+
+ helper_.reset(new content::GLHelper(gl_, support));
+ helper_scaling_.reset(new content::GLHelperScaling(gl_, helper_.get()));
+ }
+
+ void TearDown() override {
+ helper_scaling_.reset(NULL);
+ helper_.reset(NULL);
+ context_.reset(NULL);
+ }
+
+ void LoadPngFileToSkBitmap(const base::FilePath& filename, SkBitmap* bitmap) {
+ std::string compressed;
+ base::ReadFileToString(base::MakeAbsoluteFilePath(filename), &compressed);
+ ASSERT_TRUE(compressed.size());
+ ASSERT_TRUE(gfx::PNGCodec::Decode(
+ reinterpret_cast<const unsigned char*>(compressed.data()),
+ compressed.size(), bitmap));
+ }
+
+ // Save the image to a png file. Used to create the initial test files.
+ void SaveToFile(SkBitmap* bitmap, const base::FilePath& filename) {
+ std::vector<unsigned char> compressed;
+ ASSERT_TRUE(gfx::PNGCodec::Encode(
+ static_cast<unsigned char*>(bitmap->getPixels()),
+ gfx::PNGCodec::FORMAT_BGRA,
+ gfx::Size(bitmap->width(), bitmap->height()),
+ static_cast<int>(bitmap->rowBytes()), true,
+ std::vector<gfx::PNGCodec::Comment>(), &compressed));
+ ASSERT_TRUE(compressed.size());
+ FILE* f = base::OpenFile(filename, "wb");
+ ASSERT_TRUE(f);
+ ASSERT_EQ(fwrite(&*compressed.begin(), 1, compressed.size(), f),
+ compressed.size());
+ base::CloseFile(f);
+ }
+
+ scoped_ptr<gpu::GLInProcessContext> context_;
+ gpu::gles2::GLES2Interface* gl_;
+ scoped_ptr<content::GLHelper> helper_;
+ scoped_ptr<content::GLHelperScaling> helper_scaling_;
+ std::deque<GLHelperScaling::ScaleOp> x_ops_, y_ops_;
+};
+
+TEST_F(GLHelperTest, ScaleBenchmark) {
+ int output_sizes[] = {1920, 1080, 1249, 720, // Output size on pixel
+ 256, 144};
+ int input_sizes[] = {3200, 2040, 2560, 1476, // Pixel tab size
+ 1920, 1080, 1280, 720, 800, 480, 256, 144};
+
+ for (size_t q = 0; q < arraysize(kQualities); q++) {
+ for (size_t outsize = 0; outsize < arraysize(output_sizes); outsize += 2) {
+ for (size_t insize = 0; insize < arraysize(input_sizes); insize += 2) {
+ uint32_t src_texture;
+ gl_->GenTextures(1, &src_texture);
+ uint32_t dst_texture;
+ gl_->GenTextures(1, &dst_texture);
+ uint32_t framebuffer;
+ gl_->GenFramebuffers(1, &framebuffer);
+ const gfx::Size src_size(input_sizes[insize], input_sizes[insize + 1]);
+ const gfx::Size dst_size(output_sizes[outsize],
+ output_sizes[outsize + 1]);
+ SkBitmap input;
+ input.allocN32Pixels(src_size.width(), src_size.height());
+
+ SkBitmap output_pixels;
+ output_pixels.allocN32Pixels(dst_size.width(), dst_size.height());
+
+ gl_->BindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+ gl_->BindTexture(GL_TEXTURE_2D, dst_texture);
+ gl_->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dst_size.width(),
+ dst_size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ gl_->BindTexture(GL_TEXTURE_2D, src_texture);
+ gl_->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, src_size.width(),
+ src_size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ input.getPixels());
+
+ gfx::Rect src_subrect(0, 0, src_size.width(), src_size.height());
+ scoped_ptr<content::GLHelper::ScalerInterface> scaler(
+ helper_->CreateScaler(kQualities[q], src_size, src_subrect,
+ dst_size, false, false));
+ // Scale once beforehand before we start measuring.
+ scaler->Scale(src_texture, dst_texture);
+ gl_->Finish();
+
+ base::TimeTicks start_time = base::TimeTicks::Now();
+ int iterations = 0;
+ base::TimeTicks end_time;
+ while (true) {
+ for (int i = 0; i < 50; i++) {
+ iterations++;
+ scaler->Scale(src_texture, dst_texture);
+ gl_->Flush();
+ }
+ gl_->Finish();
+ end_time = base::TimeTicks::Now();
+ if (iterations > 2000) {
+ break;
+ }
+ if ((end_time - start_time).InMillisecondsF() > 1000) {
+ break;
+ }
+ }
+ gl_->DeleteTextures(1, &dst_texture);
+ gl_->DeleteTextures(1, &src_texture);
+ gl_->DeleteFramebuffers(1, &framebuffer);
+
+ std::string name;
+ name = base::StringPrintf("scale_%dx%d_to_%dx%d_%s", src_size.width(),
+ src_size.height(), dst_size.width(),
+ dst_size.height(), kQualityNames[q]);
+
+ float ms = (end_time - start_time).InMillisecondsF() / iterations;
+ VLOG(0) << base::StringPrintf("*RESULT gpu_scale_time: %s=%.2f ms\n",
+ name.c_str(), ms);
+ }
+ }
+ }
+}
+
+// This is more of a test utility than a test.
+// Put an PNG image called "testimage.png" in your
+// current directory, then run this test. It will
+// create testoutput_Q_P.png, where Q is the scaling
+// mode and P is the scaling percentage taken from
+// the table below.
+TEST_F(GLHelperTest, DISABLED_ScaleTestImage) {
+ int percents[] = {
+ 230, 180, 150, 110, 90, 70, 50, 49, 40, 20, 10,
+ };
+
+ SkBitmap input;
+ LoadPngFileToSkBitmap(base::FilePath(FILE_PATH_LITERAL("testimage.png")),
+ &input);
+
+ uint32_t framebuffer;
+ gl_->GenFramebuffers(1, &framebuffer);
+ uint32_t src_texture;
+ gl_->GenTextures(1, &src_texture);
+ const gfx::Size src_size(input.width(), input.height());
+ gl_->BindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+ gl_->BindTexture(GL_TEXTURE_2D, src_texture);
+ gl_->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, src_size.width(),
+ src_size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
+ input.getPixels());
+
+ for (size_t q = 0; q < arraysize(kQualities); q++) {
+ for (size_t p = 0; p < arraysize(percents); p++) {
+ const gfx::Size dst_size(input.width() * percents[p] / 100,
+ input.height() * percents[p] / 100);
+ uint32_t dst_texture = helper_->CopyAndScaleTexture(
+ src_texture, src_size, dst_size, false, kQualities[q]);
+
+ SkBitmap output_pixels;
+ output_pixels.allocN32Pixels(dst_size.width(), dst_size.height());
+
+ helper_->ReadbackTextureSync(
+ dst_texture, gfx::Rect(0, 0, dst_size.width(), dst_size.height()),
+ static_cast<unsigned char*>(output_pixels.getPixels()),
+ kN32_SkColorType);
+ gl_->DeleteTextures(1, &dst_texture);
+ std::string filename = base::StringPrintf("testoutput_%s_%d.ppm",
+ kQualityNames[q], percents[p]);
+ VLOG(0) << "Writing " << filename;
+ SaveToFile(&output_pixels, base::FilePath::FromUTF8Unsafe(filename));
+ }
+ }
+ gl_->DeleteTextures(1, &src_texture);
+ gl_->DeleteFramebuffers(1, &framebuffer);
+}
+
+} // namespace
diff --git a/chromium/content/common/gpu/client/gl_helper_readback_support.cc b/chromium/content/browser/compositor/gl_helper_readback_support.cc
index e773ca90782..c389eda6ba5 100644
--- a/chromium/content/common/gpu/client/gl_helper_readback_support.cc
+++ b/chromium/content/browser/compositor/gl_helper_readback_support.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/common/gpu/client/gl_helper_readback_support.h"
+#include "content/browser/compositor/gl_helper_readback_support.h"
#include "base/logging.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "third_party/skia/include/core/SkImageInfo.h"
@@ -81,20 +81,20 @@ void GLHelperReadbackSupport::GetAdditionalFormat(GLenum format,
gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
gl_->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- gl_->TexImage2D(
- GL_TEXTURE_2D, 0, format, kTestSize, kTestSize, 0, format, type, NULL);
+ gl_->TexImage2D(GL_TEXTURE_2D, 0, format, kTestSize, kTestSize, 0, format,
+ type, NULL);
ScopedFramebuffer dst_framebuffer(gl_);
ScopedFramebufferBinder<GL_FRAMEBUFFER> framebuffer_binder(gl_,
dst_framebuffer);
- gl_->FramebufferTexture2D(
- GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst_texture, 0);
+ gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ dst_texture, 0);
GLint format_tmp = 0, type_tmp = 0;
gl_->GetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &format_tmp);
gl_->GetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &type_tmp);
*format_out = format_tmp;
*type_out = type_tmp;
- struct FormatCacheEntry entry = { format, type, *format_out, *type_out };
+ struct FormatCacheEntry entry = {format, type, *format_out, *type_out};
format_cache_.push_back(entry);
}
@@ -104,17 +104,6 @@ bool GLHelperReadbackSupport::SupportsFormat(GLenum format, GLenum type) {
if (format == GL_RGBA && type == GL_UNSIGNED_BYTE)
return true;
- if (format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE) {
- const GLubyte* tmp = gl_->GetString(GL_EXTENSIONS);
- if (tmp) {
- std::string extensions =
- " " + std::string(reinterpret_cast<const char*>(tmp)) + " ";
- if (extensions.find(" GL_EXT_read_format_bgra ") != std::string::npos) {
- return true;
- }
- }
- }
-
bool supports_format = false;
GLenum ext_format = 0, ext_type = 0;
GetAdditionalFormat(format, type, &ext_format, &ext_type);
diff --git a/chromium/content/common/gpu/client/gl_helper_readback_support.h b/chromium/content/browser/compositor/gl_helper_readback_support.h
index f9329e9912c..8f83a1fbc6b 100644
--- a/chromium/content/common/gpu/client/gl_helper_readback_support.h
+++ b/chromium/content/browser/compositor/gl_helper_readback_support.h
@@ -2,14 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_COMMON_GPU_CLIENT_GL_HELPER_READBACK_SUPPORT_H_
-#define CONTENT_COMMON_GPU_CLIENT_GL_HELPER_READBACK_SUPPORT_H_
+#ifndef CONTENT_BROWSER_COMPOSITOR_GL_HELPER_READBACK_SUPPORT_H_
+#define CONTENT_BROWSER_COMPOSITOR_GL_HELPER_READBACK_SUPPORT_H_
#include <stddef.h>
#include <vector>
-#include "content/common/gpu/client/gl_helper.h"
+#include "content/browser/compositor/gl_helper.h"
namespace content {
@@ -36,8 +36,11 @@ class CONTENT_EXPORT GLHelperReadbackSupport {
size_t* bytes_per_pixel);
// Provides the additional readback format/type pairing for a render target
// of a given format/type pairing
- void GetAdditionalFormat(GLenum format, GLenum type, GLenum *format_out,
- GLenum *type_out);
+ void GetAdditionalFormat(GLenum format,
+ GLenum type,
+ GLenum* format_out,
+ GLenum* type_out);
+
private:
struct FormatCacheEntry {
GLenum format;
@@ -69,4 +72,4 @@ class CONTENT_EXPORT GLHelperReadbackSupport {
} // namespace content
-#endif // CONTENT_COMMON_GPU_CLIENT_GL_HELPER_READBACK_SUPPORT_H_
+#endif // CONTENT_BROWSER_COMPOSITOR_GL_HELPER_READBACK_SUPPORT_H_
diff --git a/chromium/content/common/gpu/client/gl_helper_scaling.cc b/chromium/content/browser/compositor/gl_helper_scaling.cc
index f4cd6b3eb52..0c7d9775f35 100644
--- a/chromium/content/common/gpu/client/gl_helper_scaling.cc
+++ b/chromium/content/browser/compositor/gl_helper_scaling.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/common/gpu/client/gl_helper_scaling.h"
+#include "content/browser/compositor/gl_helper_scaling.h"
#include <stddef.h>
@@ -146,14 +146,8 @@ class ScalerImpl : public GLHelper::ScalerInterface,
gl_->GenTextures(1, &intermediate_texture_);
ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_,
intermediate_texture_);
- gl_->TexImage2D(GL_TEXTURE_2D,
- 0,
- GL_RGBA,
- spec_.src_size.width(),
- spec_.src_size.height(),
- 0,
- GL_RGBA,
- GL_UNSIGNED_BYTE,
+ gl_->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, spec_.src_size.width(),
+ spec_.src_size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE,
NULL);
}
}
@@ -178,11 +172,8 @@ class ScalerImpl : public GLHelper::ScalerInterface,
scoped_ptr<GLenum[]> buffers(new GLenum[dest_textures.size()]);
for (size_t t = 0; t < dest_textures.size(); t++) {
ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, dest_textures[t]);
- gl_->FramebufferTexture2D(GL_FRAMEBUFFER,
- GL_COLOR_ATTACHMENT0 + t,
- GL_TEXTURE_2D,
- dest_textures[t],
- 0);
+ gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + t,
+ GL_TEXTURE_2D, dest_textures[t], 0);
buffers[t] = GL_COLOR_ATTACHMENT0 + t;
}
ScopedTextureBinder<GL_TEXTURE_2D> texture_binder(gl_, source_texture);
@@ -194,12 +185,9 @@ class ScalerImpl : public GLHelper::ScalerInterface,
ScopedBufferBinder<GL_ARRAY_BUFFER> buffer_binder(
gl_, scaler_helper_->vertex_attributes_buffer_);
- shader_program_->UseProgram(spec_.src_size,
- spec_.src_subrect,
- spec_.dst_size,
- spec_.scale_x,
- spec_.vertically_flip_texture,
- color_weights_);
+ shader_program_->UseProgram(spec_.src_size, spec_.src_subrect,
+ spec_.dst_size, spec_.scale_x,
+ spec_.vertically_flip_texture, color_weights_);
gl_->Viewport(0, 0, spec_.dst_size.width(), spec_.dst_size.height());
if (dest_textures.size() > 1) {
@@ -262,6 +250,8 @@ GLHelperScaling::ScalerStage::ScalerStage(ShaderType shader_,
vertically_flip_texture(vertically_flip_texture_),
swizzle(swizzle_) {}
+GLHelperScaling::ScalerStage::ScalerStage(const ScalerStage& other) = default;
+
// The important inputs for this function is |x_ops| and
// |y_ops|. They represent scaling operations to be done
// on an imag of size |src_size|. If |quality| is SCALER_QUALITY_BEST,
@@ -380,13 +370,9 @@ void GLHelperScaling::ConvertScalerOpsToScalerStages(
}
}
- scaler_stages->push_back(ScalerStage(current_shader,
- src_size,
- src_subrect,
- intermediate_size,
- scale_x,
- vertically_flip_texture,
- swizzle));
+ scaler_stages->push_back(ScalerStage(current_shader, src_size, src_subrect,
+ intermediate_size, scale_x,
+ vertically_flip_texture, swizzle));
src_size = intermediate_size;
src_subrect = gfx::Rect(intermediate_size);
vertically_flip_texture = false;
@@ -404,37 +390,23 @@ void GLHelperScaling::ComputeScalerStages(
std::vector<ScalerStage>* scaler_stages) {
if (quality == GLHelper::SCALER_QUALITY_FAST ||
src_subrect.size() == dst_size) {
- scaler_stages->push_back(ScalerStage(SHADER_BILINEAR,
- src_size,
- src_subrect,
- dst_size,
- false,
- vertically_flip_texture,
- swizzle));
+ scaler_stages->push_back(ScalerStage(SHADER_BILINEAR, src_size, src_subrect,
+ dst_size, false,
+ vertically_flip_texture, swizzle));
return;
}
std::deque<GLHelperScaling::ScaleOp> x_ops, y_ops;
- GLHelperScaling::ScaleOp::AddOps(src_subrect.width(),
- dst_size.width(),
- true,
+ GLHelperScaling::ScaleOp::AddOps(src_subrect.width(), dst_size.width(), true,
quality == GLHelper::SCALER_QUALITY_GOOD,
&x_ops);
- GLHelperScaling::ScaleOp::AddOps(src_subrect.height(),
- dst_size.height(),
- false,
- quality == GLHelper::SCALER_QUALITY_GOOD,
- &y_ops);
-
- ConvertScalerOpsToScalerStages(quality,
- src_size,
- src_subrect,
- dst_size,
- vertically_flip_texture,
- swizzle,
- &x_ops,
- &y_ops,
- scaler_stages);
+ GLHelperScaling::ScaleOp::AddOps(
+ src_subrect.height(), dst_size.height(), false,
+ quality == GLHelper::SCALER_QUALITY_GOOD, &y_ops);
+
+ ConvertScalerOpsToScalerStages(quality, src_size, src_subrect, dst_size,
+ vertically_flip_texture, swizzle, &x_ops,
+ &y_ops, scaler_stages);
}
GLHelper::ScalerInterface* GLHelperScaling::CreateScaler(
@@ -445,13 +417,8 @@ GLHelper::ScalerInterface* GLHelperScaling::CreateScaler(
bool vertically_flip_texture,
bool swizzle) {
std::vector<ScalerStage> scaler_stages;
- ComputeScalerStages(quality,
- src_size,
- src_subrect,
- dst_size,
- vertically_flip_texture,
- swizzle,
- &scaler_stages);
+ ComputeScalerStages(quality, src_size, src_subrect, dst_size,
+ vertically_flip_texture, swizzle, &scaler_stages);
ScalerImpl* ret = NULL;
for (unsigned int i = 0; i < scaler_stages.size(); i++) {
@@ -467,13 +434,8 @@ GLHelper::ScalerInterface* GLHelperScaling::CreatePlanarScaler(
bool vertically_flip_texture,
bool swizzle,
const float color_weights[4]) {
- ScalerStage stage(SHADER_PLANAR,
- src_size,
- src_subrect,
- dst_size,
- true,
- vertically_flip_texture,
- swizzle);
+ ScalerStage stage(SHADER_PLANAR, src_size, src_subrect, dst_size, true,
+ vertically_flip_texture, swizzle);
return new ScalerImpl(gl_, this, stage, NULL, color_weights);
}
@@ -485,28 +447,22 @@ GLHelperScaling::ShaderInterface* GLHelperScaling::CreateYuvMrtShader(
bool swizzle,
ShaderType shader) {
DCHECK(shader == SHADER_YUV_MRT_PASS1 || shader == SHADER_YUV_MRT_PASS2);
- ScalerStage stage(shader,
- src_size,
- src_subrect,
- dst_size,
- true,
- vertically_flip_texture,
- swizzle);
+ ScalerStage stage(shader, src_size, src_subrect, dst_size, true,
+ vertically_flip_texture, swizzle);
return new ScalerImpl(gl_, this, stage, NULL, NULL);
}
const GLfloat GLHelperScaling::kVertexAttributes[] = {
- -1.0f, -1.0f, 0.0f, 0.0f, // vertex 0
- 1.0f, -1.0f, 1.0f, 0.0f, // vertex 1
- -1.0f, 1.0f, 0.0f, 1.0f, // vertex 2
- 1.0f, 1.0f, 1.0f, 1.0f, }; // vertex 3
+ -1.0f, -1.0f, 0.0f, 0.0f, // vertex 0
+ 1.0f, -1.0f, 1.0f, 0.0f, // vertex 1
+ -1.0f, 1.0f, 0.0f, 1.0f, // vertex 2
+ 1.0f, 1.0f, 1.0f, 1.0f,
+}; // vertex 3
void GLHelperScaling::InitBuffer() {
ScopedBufferBinder<GL_ARRAY_BUFFER> buffer_binder(gl_,
vertex_attributes_buffer_);
- gl_->BufferData(GL_ARRAY_BUFFER,
- sizeof(kVertexAttributes),
- kVertexAttributes,
+ gl_->BufferData(GL_ARRAY_BUFFER, sizeof(kVertexAttributes), kVertexAttributes,
GL_STATIC_DRAW);
}
@@ -810,7 +766,7 @@ scoped_refptr<ShaderProgram> GLHelperScaling::GetShaderProgram(ShaderType type,
break;
}
if (swizzle) {
- switch(type) {
+ switch (type) {
case SHADER_YUV_MRT_PASS1:
fragment_program.append(" gl_FragData[0] = gl_FragData[0].bgra;\n");
break;
@@ -887,24 +843,15 @@ void ShaderProgram::UseProgram(const gfx::Size& src_size,
// OpenGL defines the last parameter to VertexAttribPointer as type
// "const GLvoid*" even though it is actually an offset into the buffer
// object's data store and not a pointer to the client's address space.
- const void* offsets[2] = {
- 0, reinterpret_cast<const void*>(2 * sizeof(GLfloat))
- };
+ const void* offsets[2] = {0,
+ reinterpret_cast<const void*>(2 * sizeof(GLfloat))};
- gl_->VertexAttribPointer(position_location_,
- 2,
- GL_FLOAT,
- GL_FALSE,
- 4 * sizeof(GLfloat),
- offsets[0]);
+ gl_->VertexAttribPointer(position_location_, 2, GL_FLOAT, GL_FALSE,
+ 4 * sizeof(GLfloat), offsets[0]);
gl_->EnableVertexAttribArray(position_location_);
- gl_->VertexAttribPointer(texcoord_location_,
- 2,
- GL_FLOAT,
- GL_FALSE,
- 4 * sizeof(GLfloat),
- offsets[1]);
+ gl_->VertexAttribPointer(texcoord_location_, 2, GL_FLOAT, GL_FALSE,
+ 4 * sizeof(GLfloat), offsets[1]);
gl_->EnableVertexAttribArray(texcoord_location_);
gl_->Uniform1i(texture_location_, 0);
@@ -914,7 +861,8 @@ void ShaderProgram::UseProgram(const gfx::Size& src_size,
static_cast<float>(src_subrect.x()) / src_size.width(),
static_cast<float>(src_subrect.y()) / src_size.height(),
static_cast<float>(src_subrect.width()) / src_size.width(),
- static_cast<float>(src_subrect.height()) / src_size.height(), };
+ static_cast<float>(src_subrect.height()) / src_size.height(),
+ };
if (flip_y) {
src_subrect_texcoord[1] += src_subrect_texcoord[3];
src_subrect_texcoord[3] *= -1.0;
@@ -922,12 +870,11 @@ void ShaderProgram::UseProgram(const gfx::Size& src_size,
gl_->Uniform4fv(src_subrect_location_, 1, src_subrect_texcoord);
gl_->Uniform2f(src_pixelsize_location_, src_size.width(), src_size.height());
- gl_->Uniform2f(dst_pixelsize_location_,
- static_cast<float>(dst_size.width()),
+ gl_->Uniform2f(dst_pixelsize_location_, static_cast<float>(dst_size.width()),
static_cast<float>(dst_size.height()));
- gl_->Uniform2f(
- scaling_vector_location_, scale_x ? 1.0 : 0.0, scale_x ? 0.0 : 1.0);
+ gl_->Uniform2f(scaling_vector_location_, scale_x ? 1.0 : 0.0,
+ scale_x ? 0.0 : 1.0);
gl_->Uniform4fv(color_weights_location_, 1, color_weights);
}
diff --git a/chromium/content/common/gpu/client/gl_helper_scaling.h b/chromium/content/browser/compositor/gl_helper_scaling.h
index 6157d8e0d9b..6fbc03342ad 100644
--- a/chromium/content/common/gpu/client/gl_helper_scaling.h
+++ b/chromium/content/browser/compositor/gl_helper_scaling.h
@@ -2,15 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_COMMON_GPU_CLIENT_GL_HELPER_SCALING_H_
-#define CONTENT_COMMON_GPU_CLIENT_GL_HELPER_SCALING_H_
+#ifndef CONTENT_BROWSER_COMPOSITOR_GL_HELPER_SCALING_H_
+#define CONTENT_BROWSER_COMPOSITOR_GL_HELPER_SCALING_H_
#include <deque>
#include <map>
#include <vector>
#include "base/macros.h"
-#include "content/common/gpu/client/gl_helper.h"
+#include "content/browser/compositor/gl_helper.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
@@ -52,34 +52,30 @@ class CONTENT_EXPORT GLHelperScaling {
typedef std::pair<ShaderType, bool> ShaderProgramKeyType;
- GLHelperScaling(gpu::gles2::GLES2Interface* gl,
- GLHelper* helper);
+ GLHelperScaling(gpu::gles2::GLES2Interface* gl, GLHelper* helper);
~GLHelperScaling();
void InitBuffer();
- GLHelper::ScalerInterface* CreateScaler(
- GLHelper::ScalerQuality quality,
- gfx::Size src_size,
- gfx::Rect src_subrect,
- const gfx::Size& dst_size,
- bool vertically_flip_texture,
- bool swizzle);
-
- GLHelper::ScalerInterface* CreatePlanarScaler(
- const gfx::Size& src_size,
- const gfx::Rect& src_subrect,
- const gfx::Size& dst_size,
- bool vertically_flip_texture,
- bool swizzle,
- const float color_weights[4]);
-
- ShaderInterface* CreateYuvMrtShader(
- const gfx::Size& src_size,
- const gfx::Rect& src_subrect,
- const gfx::Size& dst_size,
- bool vertically_flip_texture,
- bool swizzle,
- ShaderType shader);
+ GLHelper::ScalerInterface* CreateScaler(GLHelper::ScalerQuality quality,
+ gfx::Size src_size,
+ gfx::Rect src_subrect,
+ const gfx::Size& dst_size,
+ bool vertically_flip_texture,
+ bool swizzle);
+
+ GLHelper::ScalerInterface* CreatePlanarScaler(const gfx::Size& src_size,
+ const gfx::Rect& src_subrect,
+ const gfx::Size& dst_size,
+ bool vertically_flip_texture,
+ bool swizzle,
+ const float color_weights[4]);
+
+ ShaderInterface* CreateYuvMrtShader(const gfx::Size& src_size,
+ const gfx::Rect& src_subrect,
+ const gfx::Size& dst_size,
+ bool vertically_flip_texture,
+ bool swizzle,
+ ShaderType shader);
private:
// A ScaleOp represents a pass in a scaler pipeline, in one dimension.
@@ -88,8 +84,7 @@ class CONTENT_EXPORT GLHelperScaling {
// Exposed in the header file for testing purposes.
struct ScaleOp {
ScaleOp(int factor, bool x, int size)
- : scale_factor(factor), scale_x(x), scale_size(size) {
- }
+ : scale_factor(factor), scale_x(x), scale_size(size) {}
// Calculate a set of ScaleOp needed to convert an image of size
// |src| into an image of size |dst|. If |scale_x| is true, then
@@ -138,7 +133,7 @@ class CONTENT_EXPORT GLHelperScaling {
// 2 means 50% scale
// 3 means 33% scale, etc.
int scale_factor;
- bool scale_x; // Otherwise y
+ bool scale_x; // Otherwise y
int scale_size; // Size to scale to.
};
@@ -151,6 +146,7 @@ class CONTENT_EXPORT GLHelperScaling {
bool scale_x_,
bool vertically_flip_texture_,
bool swizzle_);
+ ScalerStage(const ScalerStage& other);
ShaderType shader;
gfx::Size src_size;
gfx::Rect src_subrect;
@@ -168,7 +164,7 @@ class CONTENT_EXPORT GLHelperScaling {
const gfx::Size& dst_size,
bool vertically_flip_texture,
bool swizzle,
- std::vector<ScalerStage> *scaler_stages);
+ std::vector<ScalerStage>* scaler_stages);
// Take two queues of ScaleOp structs and generate a
// vector of scaler stages. This is the second half of
@@ -182,8 +178,7 @@ class CONTENT_EXPORT GLHelperScaling {
bool swizzle,
std::deque<GLHelperScaling::ScaleOp>* x_ops,
std::deque<GLHelperScaling::ScaleOp>* y_ops,
- std::vector<ScalerStage> *scaler_stages);
-
+ std::vector<ScalerStage>* scaler_stages);
scoped_refptr<ShaderProgram> GetShaderProgram(ShaderType type, bool swizzle);
@@ -198,8 +193,7 @@ class CONTENT_EXPORT GLHelperScaling {
// drawing a quad.
ScopedBuffer vertex_attributes_buffer_;
- std::map<ShaderProgramKeyType,
- scoped_refptr<ShaderProgram> > shader_programs_;
+ std::map<ShaderProgramKeyType, scoped_refptr<ShaderProgram>> shader_programs_;
friend class ShaderProgram;
friend class ScalerImpl;
@@ -207,7 +201,6 @@ class CONTENT_EXPORT GLHelperScaling {
DISALLOW_COPY_AND_ASSIGN(GLHelperScaling);
};
-
} // namespace content
-#endif // CONTENT_COMMON_GPU_CLIENT_GL_HELPER_SCALING_H_
+#endif // CONTENT_BROWSER_COMPOSITOR_GL_HELPER_SCALING_H_
diff --git a/chromium/content/common/gpu/client/gl_helper_unittest.cc b/chromium/content/browser/compositor/gl_helper_unittest.cc
index 57022351c51..697c68ba47a 100644
--- a/chromium/content/common/gpu/client/gl_helper_unittest.cc
+++ b/chromium/content/browser/compositor/gl_helper_unittest.cc
@@ -20,6 +20,7 @@
#include "base/files/file_util.h"
#include "base/json/json_reader.h"
#include "base/macros.h"
+#include "base/memory/ref_counted_memory.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
@@ -28,50 +29,59 @@
#include "base/test/test_suite.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
-#include "build/build_config.h"
-#include "content/common/gpu/client/gl_helper.h"
-#include "content/common/gpu/client/gl_helper_readback_support.h"
-#include "content/common/gpu/client/gl_helper_scaling.h"
-#include "content/public/test/unittest_test_suite.h"
-#include "content/test/content_test_suite.h"
-#include "gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h"
+#include "content/browser/compositor/gl_helper.h"
+#include "content/browser/compositor/gl_helper_readback_support.h"
+#include "content/browser/compositor/gl_helper_scaling.h"
+#include "gpu/command_buffer/client/gl_in_process_context.h"
+#include "gpu/command_buffer/client/gles2_implementation.h"
#include "media/base/video_frame.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkTypes.h"
#include "ui/gl/gl_implementation.h"
-#if defined(OS_MACOSX)
-#include "base/mac/scoped_nsautorelease_pool.h"
-#endif
-
namespace content {
-using blink::WebGLId;
-using blink::WebGraphicsContext3D;
-using gpu_blink::WebGraphicsContext3DInProcessCommandBufferImpl;
-
content::GLHelper::ScalerQuality kQualities[] = {
content::GLHelper::SCALER_QUALITY_BEST,
content::GLHelper::SCALER_QUALITY_GOOD,
- content::GLHelper::SCALER_QUALITY_FAST, };
+ content::GLHelper::SCALER_QUALITY_FAST,
+};
-const char* kQualityNames[] = {"best", "good", "fast", };
+const char* kQualityNames[] = {
+ "best", "good", "fast",
+};
class GLHelperTest : public testing::Test {
protected:
void SetUp() override {
- WebGraphicsContext3D::Attributes attributes;
- bool lose_context_when_out_of_memory = false;
- context_ =
- WebGraphicsContext3DInProcessCommandBufferImpl::CreateOffscreenContext(
- attributes, lose_context_when_out_of_memory);
- context_->InitializeOnCurrentThread();
- context_support_ = context_->GetContextSupport();
- helper_.reset(
- new content::GLHelper(context_->GetGLInterface(), context_support_));
- helper_scaling_.reset(new content::GLHelperScaling(
- context_->GetGLInterface(), helper_.get()));
+ gpu::gles2::ContextCreationAttribHelper attributes;
+ attributes.alpha_size = 8;
+ attributes.depth_size = 24;
+ attributes.red_size = 8;
+ attributes.green_size = 8;
+ attributes.blue_size = 8;
+ attributes.stencil_size = 8;
+ attributes.samples = 4;
+ attributes.sample_buffers = 1;
+ attributes.bind_generates_resource = false;
+
+ context_.reset(gpu::GLInProcessContext::Create(
+ nullptr, /* service */
+ nullptr, /* surface */
+ true, /* offscreen */
+ gfx::kNullAcceleratedWidget, /* window */
+ gfx::Size(1, 1), /* size */
+ nullptr, /* share_context */
+ attributes, gfx::PreferDiscreteGpu,
+ ::gpu::GLInProcessContextSharedMemoryLimits(),
+ nullptr, /* gpu_memory_buffer_manager */
+ nullptr /* image_factory */));
+ gl_ = context_->GetImplementation();
+ gpu::ContextSupport* support = context_->GetImplementation();
+
+ helper_.reset(new content::GLHelper(gl_, support));
+ helper_scaling_.reset(new content::GLHelperScaling(gl_, helper_.get()));
}
void TearDown() override {
@@ -108,8 +118,7 @@ class GLHelperTest : public testing::Test {
base::trace_event::TraceLog::GetInstance()->SetDisabled();
base::RunLoop run_loop;
base::trace_event::TraceLog::GetInstance()->Flush(
- base::Bind(&GLHelperTest::TraceDataCB,
- run_loop.QuitClosure(),
+ base::Bind(&GLHelperTest::TraceDataCB, run_loop.QuitClosure(),
base::Unretained(&json_data)));
run_loop.Run();
json_data.append("]");
@@ -117,9 +126,9 @@ class GLHelperTest : public testing::Test {
std::string error_msg;
scoped_ptr<base::Value> trace_data =
base::JSONReader::ReadAndReturnError(json_data, 0, NULL, &error_msg);
- CHECK(trace_data)
- << "JSON parsing failed (" << error_msg << ") JSON data:" << std::endl
- << json_data;
+ CHECK(trace_data) << "JSON parsing failed (" << error_msg
+ << ") JSON data:" << std::endl
+ << json_data;
base::ListValue* list;
CHECK(trace_data->GetAsList(&list));
@@ -208,11 +217,10 @@ class GLHelperTest : public testing::Test {
const std::vector<GLHelperScaling::ScalerStage>& scaler_stages) {
std::string ret;
for (size_t i = 0; i < scaler_stages.size(); i++) {
- ret.append(base::StringPrintf("%dx%d -> %dx%d ",
- scaler_stages[i].src_size.width(),
- scaler_stages[i].src_size.height(),
- scaler_stages[i].dst_size.width(),
- scaler_stages[i].dst_size.height()));
+ ret.append(base::StringPrintf(
+ "%dx%d -> %dx%d ", scaler_stages[i].src_size.width(),
+ scaler_stages[i].src_size.height(), scaler_stages[i].dst_size.width(),
+ scaler_stages[i].dst_size.height()));
bool xy_matters = false;
switch (scaler_stages[i].shader) {
case GLHelperScaling::SHADER_BILINEAR:
@@ -387,12 +395,12 @@ class GLHelperTest : public testing::Test {
}
if (x_samples) {
- EXPECT_TRUE(CheckScale(x_scale, x_samples, scaled_x))
- << "x_scale = " << x_scale;
+ EXPECT_TRUE(CheckScale(x_scale, x_samples, scaled_x)) << "x_scale = "
+ << x_scale;
}
if (y_samples) {
- EXPECT_TRUE(CheckScale(y_scale, y_samples, scaled_y))
- << "y_scale = " << y_scale;
+ EXPECT_TRUE(CheckScale(y_scale, y_samples, scaled_y)) << "y_scale = "
+ << y_scale;
}
if (x_scale != 1.0) {
@@ -502,8 +510,8 @@ class GLHelperTest : public testing::Test {
float value = c0 * kRGBtoGrayscaleColorWeights[0] +
c1 * kRGBtoGrayscaleColorWeights[1] +
c2 * kRGBtoGrayscaleColorWeights[2];
- SetChannel(
- output, dst_x, dst_y, 0, static_cast<int>(value * 255.0f + 0.5f));
+ SetChannel(output, dst_x, dst_y, 0,
+ static_cast<int>(value * 255.0f + 0.5f));
}
}
}
@@ -564,10 +572,9 @@ class GLHelperTest : public testing::Test {
}
for (int x = 0; x < xmag; x++) {
for (int y = 0; y < ymag; y++) {
- value += Bilinear(input,
- (dst_x * xmag + x + 0.5) * xscale / xmag,
- (dst_y * ymag + y + 0.5) * yscale / ymag,
- channel);
+ value += Bilinear(
+ input, (dst_x * xmag + x + 0.5) * xscale / xmag,
+ (dst_y * ymag + y + 0.5) * yscale / ymag, channel);
sum += 1.0;
}
}
@@ -579,10 +586,7 @@ class GLHelperTest : public testing::Test {
sum = 1.0;
}
value /= sum;
- SetChannel(output,
- dst_x,
- dst_y,
- channel,
+ SetChannel(output, dst_x, dst_y, channel,
static_cast<int>(value * 255.0f + 0.5f));
}
}
@@ -674,8 +678,8 @@ class GLHelperTest : public testing::Test {
int height,
int test_pattern) {
scoped_ptr<SkBitmap> bitmap(new SkBitmap);
- bitmap->allocPixels(SkImageInfo::Make(
- width, height, kRGBA_8888_SkColorType, kPremul_SkAlphaType));
+ bitmap->allocPixels(SkImageInfo::Make(width, height, kRGBA_8888_SkColorType,
+ kPremul_SkAlphaType));
for (int x = 0; x < width; ++x) {
for (int y = 0; y < height; ++y) {
@@ -706,22 +710,15 @@ class GLHelperTest : public testing::Test {
}
// Binds texture and framebuffer and loads the bitmap pixels into the texture.
- void BindTextureAndFrameBuffer(WebGLId texture,
- WebGLId framebuffer,
+ void BindTextureAndFrameBuffer(GLuint texture,
+ GLuint framebuffer,
SkBitmap* bitmap,
int width,
int height) {
- context_->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
- context_->bindTexture(GL_TEXTURE_2D, texture);
- context_->texImage2D(GL_TEXTURE_2D,
- 0,
- GL_RGBA,
- width,
- height,
- 0,
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- bitmap->getPixels());
+ gl_->BindFramebuffer(GL_FRAMEBUFFER, framebuffer);
+ gl_->BindTexture(GL_TEXTURE_2D, texture);
+ gl_->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, bitmap->getPixels());
}
// Create a test image, transform it using
@@ -738,25 +735,22 @@ class GLHelperTest : public testing::Test {
DCHECK(out_color_type == kAlpha_8_SkColorType ||
out_color_type == kRGBA_8888_SkColorType ||
out_color_type == kBGRA_8888_SkColorType);
- WebGLId src_texture = context_->createTexture();
- WebGLId framebuffer = context_->createFramebuffer();
+ GLuint src_texture;
+ gl_->GenTextures(1, &src_texture);
+ GLuint framebuffer;
+ gl_->GenFramebuffers(1, &framebuffer);
scoped_ptr<SkBitmap> input_pixels =
CreateTestBitmap(xsize, ysize, test_pattern);
- BindTextureAndFrameBuffer(
- src_texture, framebuffer, input_pixels.get(), xsize, ysize);
+ BindTextureAndFrameBuffer(src_texture, framebuffer, input_pixels.get(),
+ xsize, ysize);
std::string message = base::StringPrintf(
"input size: %dx%d "
"output size: %dx%d "
"pattern: %d , quality: %s, "
"out_color_type: %d",
- xsize,
- ysize,
- scaled_xsize,
- scaled_ysize,
- test_pattern,
- kQualityNames[quality_index],
- out_color_type);
+ xsize, ysize, scaled_xsize, scaled_ysize, test_pattern,
+ kQualityNames[quality_index], out_color_type);
// Transform the bitmap using GLHelper::CropScaleReadbackAndCleanTexture.
SkBitmap output_pixels;
@@ -765,12 +759,9 @@ class GLHelperTest : public testing::Test {
base::RunLoop run_loop;
gfx::Size encoded_texture_size;
helper_->CropScaleReadbackAndCleanTexture(
- src_texture,
- gfx::Size(xsize, ysize),
- gfx::Rect(xsize, ysize),
+ src_texture, gfx::Size(xsize, ysize), gfx::Rect(xsize, ysize),
gfx::Size(scaled_xsize, scaled_ysize),
- static_cast<unsigned char*>(output_pixels.getPixels()),
- out_color_type,
+ static_cast<unsigned char*>(output_pixels.getPixels()), out_color_type,
base::Bind(&callcallback, run_loop.QuitClosure()),
kQualities[quality_index]);
run_loop.Run();
@@ -781,25 +772,20 @@ class GLHelperTest : public testing::Test {
if (xsize == scaled_xsize && ysize == scaled_ysize &&
out_color_type != kAlpha_8_SkColorType) {
const std::vector<GLHelperScaling::ScalerStage> dummy_stages;
- Compare(input_pixels.get(),
- &output_pixels,
- 0,
- NULL,
- dummy_stages,
+ Compare(input_pixels.get(), &output_pixels, 0, NULL, dummy_stages,
message + " comparing against input");
return;
}
// Now transform the bitmap using the reference implementation.
SkBitmap scaled_pixels;
- scaled_pixels.allocPixels(SkImageInfo::Make(scaled_xsize,
- scaled_ysize,
+ scaled_pixels.allocPixels(SkImageInfo::Make(scaled_xsize, scaled_ysize,
kRGBA_8888_SkColorType,
kPremul_SkAlphaType));
SkBitmap truth_pixels;
// Step 1: Scale
- ScaleSlowRecursive(
- input_pixels.get(), &scaled_pixels, kQualities[quality_index]);
+ ScaleSlowRecursive(input_pixels.get(), &scaled_pixels,
+ kQualities[quality_index]);
// Step 2: Encode to grayscale if needed.
if (out_color_type == kAlpha_8_SkColorType) {
truth_pixels.allocPixels(SkImageInfo::Make(
@@ -812,15 +798,11 @@ class GLHelperTest : public testing::Test {
// Now compare the results.
SkAutoLockPixels lock_input(truth_pixels);
const std::vector<GLHelperScaling::ScalerStage> dummy_stages;
- Compare(&truth_pixels,
- &output_pixels,
- 2,
- input_pixels.get(),
- dummy_stages,
+ Compare(&truth_pixels, &output_pixels, 2, input_pixels.get(), dummy_stages,
message + " comparing against transformed/scaled");
- context_->deleteTexture(src_texture);
- context_->deleteFramebuffer(framebuffer);
+ gl_->DeleteTextures(1, &src_texture);
+ gl_->DeleteFramebuffers(1, &framebuffer);
}
// Scaling test: Create a test image, scale it using GLHelperScaling
@@ -832,22 +814,20 @@ class GLHelperTest : public testing::Test {
int test_pattern,
size_t quality_index,
bool flip) {
- WebGLId src_texture = context_->createTexture();
- WebGLId framebuffer = context_->createFramebuffer();
+ GLuint src_texture;
+ gl_->GenTextures(1, &src_texture);
+ GLuint framebuffer;
+ gl_->GenFramebuffers(1, &framebuffer);
scoped_ptr<SkBitmap> input_pixels =
CreateTestBitmap(xsize, ysize, test_pattern);
- BindTextureAndFrameBuffer(
- src_texture, framebuffer, input_pixels.get(), xsize, ysize);
+ BindTextureAndFrameBuffer(src_texture, framebuffer, input_pixels.get(),
+ xsize, ysize);
std::string message = base::StringPrintf(
"input size: %dx%d "
"output size: %dx%d "
"pattern: %d quality: %s",
- xsize,
- ysize,
- scaled_xsize,
- scaled_ysize,
- test_pattern,
+ xsize, ysize, scaled_xsize, scaled_ysize, test_pattern,
kQualityNames[quality_index]);
std::vector<GLHelperScaling::ScalerStage> stages;
@@ -863,22 +843,17 @@ class GLHelperTest : public testing::Test {
gfx::Size(scaled_xsize, scaled_ysize),
message);
- WebGLId dst_texture =
- helper_->CopyAndScaleTexture(src_texture,
- gfx::Size(xsize, ysize),
- gfx::Size(scaled_xsize, scaled_ysize),
- flip,
- kQualities[quality_index]);
+ GLuint dst_texture = helper_->CopyAndScaleTexture(
+ src_texture, gfx::Size(xsize, ysize),
+ gfx::Size(scaled_xsize, scaled_ysize), flip, kQualities[quality_index]);
SkBitmap output_pixels;
- output_pixels.allocPixels(SkImageInfo::Make(scaled_xsize,
- scaled_ysize,
+ output_pixels.allocPixels(SkImageInfo::Make(scaled_xsize, scaled_ysize,
kRGBA_8888_SkColorType,
kPremul_SkAlphaType));
helper_->ReadbackTextureSync(
- dst_texture,
- gfx::Rect(0, 0, scaled_xsize, scaled_ysize),
+ dst_texture, gfx::Rect(0, 0, scaled_xsize, scaled_ysize),
static_cast<unsigned char*>(output_pixels.getPixels()),
kRGBA_8888_SkColorType);
if (flip) {
@@ -888,33 +863,24 @@ class GLHelperTest : public testing::Test {
// If the bitmap shouldn't have changed - compare against input.
if (xsize == scaled_xsize && ysize == scaled_ysize) {
- Compare(input_pixels.get(),
- &output_pixels,
- 0,
- NULL,
- stages,
+ Compare(input_pixels.get(), &output_pixels, 0, NULL, stages,
message + " comparing against input");
return;
}
// Now scale the bitmap using the reference implementation.
SkBitmap truth_pixels;
- truth_pixels.allocPixels(SkImageInfo::Make(scaled_xsize,
- scaled_ysize,
+ truth_pixels.allocPixels(SkImageInfo::Make(scaled_xsize, scaled_ysize,
kRGBA_8888_SkColorType,
kPremul_SkAlphaType));
- ScaleSlowRecursive(
- input_pixels.get(), &truth_pixels, kQualities[quality_index]);
- Compare(&truth_pixels,
- &output_pixels,
- 2,
- input_pixels.get(),
- stages,
+ ScaleSlowRecursive(input_pixels.get(), &truth_pixels,
+ kQualities[quality_index]);
+ Compare(&truth_pixels, &output_pixels, 2, input_pixels.get(), stages,
message + " comparing against scaled");
- context_->deleteTexture(src_texture);
- context_->deleteTexture(dst_texture);
- context_->deleteFramebuffer(framebuffer);
+ gl_->DeleteTextures(1, &src_texture);
+ gl_->DeleteTextures(1, &dst_texture);
+ gl_->DeleteFramebuffers(1, &framebuffer);
}
// Create a scaling pipeline and check that it is made up of
@@ -925,25 +891,17 @@ class GLHelperTest : public testing::Test {
int dst_xsize,
int dst_ysize) {
std::vector<GLHelperScaling::ScalerStage> stages;
- helper_scaling_->ComputeScalerStages(kQualities[quality],
- gfx::Size(xsize, ysize),
- gfx::Rect(0, 0, xsize, ysize),
- gfx::Size(dst_xsize, dst_ysize),
- false,
- false,
- &stages);
- ValidateScalerStages(kQualities[quality],
- stages,
+ helper_scaling_->ComputeScalerStages(
+ kQualities[quality], gfx::Size(xsize, ysize),
+ gfx::Rect(0, 0, xsize, ysize), gfx::Size(dst_xsize, dst_ysize), false,
+ false, &stages);
+ ValidateScalerStages(kQualities[quality], stages,
gfx::Size(dst_xsize, dst_ysize),
- base::StringPrintf(
- "input size: %dx%d "
- "output size: %dx%d "
- "quality: %s",
- xsize,
- ysize,
- dst_xsize,
- dst_ysize,
- kQualityNames[quality]));
+ base::StringPrintf("input size: %dx%d "
+ "output size: %dx%d "
+ "quality: %s",
+ xsize, ysize, dst_xsize, dst_ysize,
+ kQualityNames[quality]));
}
// Create a scaling pipeline and make sure that the steps
@@ -955,17 +913,11 @@ class GLHelperTest : public testing::Test {
int dst_ysize,
const std::string& description) {
std::vector<GLHelperScaling::ScalerStage> stages;
- helper_scaling_->ComputeScalerStages(quality,
- gfx::Size(xsize, ysize),
- gfx::Rect(0, 0, xsize, ysize),
- gfx::Size(dst_xsize, dst_ysize),
- false,
- false,
- &stages);
- ValidateScalerStages(content::GLHelper::SCALER_QUALITY_GOOD,
- stages,
- gfx::Size(dst_xsize, dst_ysize),
- "");
+ helper_scaling_->ComputeScalerStages(
+ quality, gfx::Size(xsize, ysize), gfx::Rect(0, 0, xsize, ysize),
+ gfx::Size(dst_xsize, dst_ysize), false, false, &stages);
+ ValidateScalerStages(content::GLHelper::SCALER_QUALITY_GOOD, stages,
+ gfx::Size(dst_xsize, dst_ysize), "");
EXPECT_EQ(PrintStages(stages), description);
}
@@ -1068,7 +1020,8 @@ class GLHelperTest : public testing::Test {
}
}
- void DrawGridToBitmap(int w, int h,
+ void DrawGridToBitmap(int w,
+ int h,
SkColor background_color,
SkColor grid_color,
int grid_pitch,
@@ -1094,9 +1047,12 @@ class GLHelperTest : public testing::Test {
}
}
- void DrawCheckerToBitmap(int w, int h,
- SkColor color1, SkColor color2,
- int rect_w, int rect_h,
+ void DrawCheckerToBitmap(int w,
+ int h,
+ SkColor color1,
+ SkColor color2,
+ int rect_w,
+ int rect_h,
SkBitmap& bmp) {
ASSERT_GT(rect_w, 0);
ASSERT_GT(rect_h, 0);
@@ -1140,14 +1096,14 @@ class GLHelperTest : public testing::Test {
}
bool ColorsClose(SkColor color1, SkColor color2, SkColorType color_type) {
- bool red = ColorComponentsClose(SkColorGetR(color1),
- SkColorGetR(color2), color_type);
- bool green = ColorComponentsClose(SkColorGetG(color1),
- SkColorGetG(color2), color_type);
- bool blue = ColorComponentsClose(SkColorGetB(color1),
- SkColorGetB(color2), color_type);
- bool alpha = ColorComponentsClose(SkColorGetA(color1),
- SkColorGetA(color2), color_type);
+ bool red = ColorComponentsClose(SkColorGetR(color1), SkColorGetR(color2),
+ color_type);
+ bool green = ColorComponentsClose(SkColorGetG(color1), SkColorGetG(color2),
+ color_type);
+ bool blue = ColorComponentsClose(SkColorGetB(color1), SkColorGetB(color2),
+ color_type);
+ bool alpha = ColorComponentsClose(SkColorGetA(color1), SkColorGetA(color2),
+ color_type);
if (color_type == kRGB_565_SkColorType) {
return red && blue && green;
}
@@ -1157,10 +1113,9 @@ class GLHelperTest : public testing::Test {
bool IsEqual(const SkBitmap& bmp1, const SkBitmap& bmp2) {
if (bmp1.isNull() && bmp2.isNull())
return true;
- if (bmp1.width() != bmp2.width() ||
- bmp1.height() != bmp2.height()) {
- LOG(ERROR) << "Bitmap geometry check failure";
- return false;
+ if (bmp1.width() != bmp2.width() || bmp1.height() != bmp2.height()) {
+ LOG(ERROR) << "Bitmap geometry check failure";
+ return false;
}
if (bmp1.colorType() != bmp2.colorType())
return false;
@@ -1173,8 +1128,7 @@ class GLHelperTest : public testing::Test {
}
for (int y = 0; y < bmp1.height(); ++y) {
for (int x = 0; x < bmp1.width(); ++x) {
- if (!ColorsClose(bmp1.getColor(x,y),
- bmp2.getColor(x,y),
+ if (!ColorsClose(bmp1.getColor(x, y), bmp2.getColor(x, y),
bmp1.colorType())) {
LOG(ERROR) << "Bitmap color comparision failure";
return false;
@@ -1188,7 +1142,7 @@ class GLHelperTest : public testing::Test {
SkColorType color_type,
const gfx::Size& src_size,
const SkBitmap& input_pixels) {
- context_->bindTexture(GL_TEXTURE_2D, src_texture);
+ gl_->BindTexture(GL_TEXTURE_2D, src_texture);
GLenum format = 0;
switch (color_type) {
case kBGRA_8888_SkColorType:
@@ -1205,15 +1159,9 @@ class GLHelperTest : public testing::Test {
}
GLenum type = (color_type == kRGB_565_SkColorType) ?
GL_UNSIGNED_SHORT_5_6_5 : GL_UNSIGNED_BYTE;
- context_->texImage2D(GL_TEXTURE_2D,
- 0,
- format,
- src_size.width(),
- src_size.height(),
- 0,
- format,
- type,
- input_pixels.getPixels());
+ gl_->TexImage2D(GL_TEXTURE_2D, 0, format, src_size.width(),
+ src_size.height(), 0, format, type,
+ input_pixels.getPixels());
}
void ReadBackTexture(GLuint src_texture,
@@ -1223,42 +1171,33 @@ class GLHelperTest : public testing::Test {
bool async) {
if (async) {
base::RunLoop run_loop;
- helper_->ReadbackTextureAsync(src_texture,
- src_size,
- pixels,
- color_type,
- base::Bind(&callcallback,
- run_loop.QuitClosure()));
+ helper_->ReadbackTextureAsync(
+ src_texture, src_size, pixels, color_type,
+ base::Bind(&callcallback, run_loop.QuitClosure()));
run_loop.Run();
} else {
- helper_->ReadbackTextureSync(src_texture,
- gfx::Rect(src_size),
- pixels,
+ helper_->ReadbackTextureSync(src_texture, gfx::Rect(src_size), pixels,
color_type);
}
}
// Test basic format readback.
bool TestTextureFormatReadback(const gfx::Size& src_size,
- SkColorType color_type,
- bool async) {
- SkImageInfo info =
- SkImageInfo::Make(src_size.width(),
- src_size.height(),
- color_type,
- kPremul_SkAlphaType);
+ SkColorType color_type,
+ bool async) {
+ SkImageInfo info = SkImageInfo::Make(src_size.width(), src_size.height(),
+ color_type, kPremul_SkAlphaType);
if (!helper_->IsReadbackConfigSupported(color_type)) {
LOG(INFO) << "Skipping test format not supported" << color_type;
return true;
}
- WebGLId src_texture = context_->createTexture();
+ GLuint src_texture;
+ gl_->GenTextures(1, &src_texture);
SkBitmap input_pixels;
input_pixels.allocPixels(info);
// Test Pattern-1, Fill with Plain color pattern.
// Erase the input bitmap with red color.
input_pixels.eraseColor(SK_ColorRED);
- BindAndAttachTextureWithPixels(src_texture,
- color_type,
- src_size,
+ BindAndAttachTextureWithPixels(src_texture, color_type, src_size,
input_pixels);
SkBitmap output_pixels;
output_pixels.allocPixels(info);
@@ -1275,13 +1214,9 @@ class GLHelperTest : public testing::Test {
const int rect_w = 10, rect_h = 4, src_grid_pitch = 10, src_grid_width = 4;
const SkColor color1 = SK_ColorRED, color2 = SK_ColorBLUE;
// Test Pattern-2, Fill with Grid Pattern.
- DrawGridToBitmap(src_size.width(), src_size.height(),
- color2, color1,
- src_grid_pitch, src_grid_width,
- input_pixels);
- BindAndAttachTextureWithPixels(src_texture,
- color_type,
- src_size,
+ DrawGridToBitmap(src_size.width(), src_size.height(), color2, color1,
+ src_grid_pitch, src_grid_width, input_pixels);
+ BindAndAttachTextureWithPixels(src_texture, color_type, src_size,
input_pixels);
ReadBackTexture(src_texture, src_size, pixels, color_type, async);
result = IsEqual(input_pixels, output_pixels);
@@ -1290,13 +1225,9 @@ class GLHelperTest : public testing::Test {
return false;
}
// Test Pattern-3, Fill with CheckerBoard Pattern.
- DrawCheckerToBitmap(src_size.width(),
- src_size.height(),
- color1,
- color2, rect_w, rect_h, input_pixels);
- BindAndAttachTextureWithPixels(src_texture,
- color_type,
- src_size,
+ DrawCheckerToBitmap(src_size.width(), src_size.height(), color1, color2,
+ rect_w, rect_h, input_pixels);
+ BindAndAttachTextureWithPixels(src_texture, color_type, src_size,
input_pixels);
ReadBackTexture(src_texture, src_size, pixels, color_type, async);
result = IsEqual(input_pixels, output_pixels);
@@ -1304,7 +1235,7 @@ class GLHelperTest : public testing::Test {
LOG(ERROR) << "Bitmap comparision failure Pattern-3";
return false;
}
- context_->deleteTexture(src_texture);
+ gl_->DeleteTextures(1, &src_texture);
if (HasFailure()) {
return false;
}
@@ -1324,7 +1255,8 @@ class GLHelperTest : public testing::Test {
bool flip,
bool use_mrt,
content::GLHelper::ScalerQuality quality) {
- WebGLId src_texture = context_->createTexture();
+ GLuint src_texture;
+ gl_->GenTextures(1, &src_texture);
SkBitmap input_pixels;
input_pixels.allocN32Pixels(xsize, ysize);
@@ -1353,50 +1285,31 @@ class GLHelperTest : public testing::Test {
}
}
- context_->bindTexture(GL_TEXTURE_2D, src_texture);
- context_->texImage2D(GL_TEXTURE_2D,
- 0,
- GL_RGBA,
- xsize,
- ysize,
- 0,
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- input_pixels.getPixels());
+ gl_->BindTexture(GL_TEXTURE_2D, src_texture);
+ gl_->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, xsize, ysize, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, input_pixels.getPixels());
gpu::Mailbox mailbox;
- context_->genMailboxCHROMIUM(mailbox.name);
+ gl_->GenMailboxCHROMIUM(mailbox.name);
EXPECT_FALSE(mailbox.IsZero());
- context_->produceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
- const blink::WGC3Duint64 fence_sync = context_->insertFenceSyncCHROMIUM();
- context_->shallowFlushCHROMIUM();
+ gl_->ProduceTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name);
+ const GLuint64 fence_sync = gl_->InsertFenceSyncCHROMIUM();
+ gl_->ShallowFlushCHROMIUM();
gpu::SyncToken sync_token;
- ASSERT_TRUE(context_->genSyncTokenCHROMIUM(fence_sync,
- sync_token.GetData()));
+ gl_->GenSyncTokenCHROMIUM(fence_sync, sync_token.GetData());
std::string message = base::StringPrintf(
"input size: %dx%d "
"output size: %dx%d "
"margin: %dx%d "
"pattern: %d %s %s",
- xsize,
- ysize,
- output_xsize,
- output_ysize,
- xmargin,
- ymargin,
- test_pattern,
- flip ? "flip" : "noflip",
- flip ? "mrt" : "nomrt");
+ xsize, ysize, output_xsize, output_ysize, xmargin, ymargin,
+ test_pattern, flip ? "flip" : "noflip", flip ? "mrt" : "nomrt");
scoped_ptr<ReadbackYUVInterface> yuv_reader(
helper_->CreateReadbackPipelineYUV(
- quality,
- gfx::Size(xsize, ysize),
- gfx::Rect(0, 0, xsize, ysize),
- gfx::Size(xsize, ysize),
- flip,
- use_mrt));
+ quality, gfx::Size(xsize, ysize), gfx::Rect(0, 0, xsize, ysize),
+ gfx::Size(xsize, ysize), flip, use_mrt));
scoped_refptr<media::VideoFrame> output_frame =
media::VideoFrame::CreateFrame(
@@ -1471,35 +1384,20 @@ class GLHelperTest : public testing::Test {
}
}
- ComparePlane(Y,
- y_stride,
- output_frame->visible_data(media::VideoFrame::kYPlane),
- output_frame->stride(media::VideoFrame::kYPlane),
- 2,
- output_xsize,
- output_ysize,
- &input_pixels,
- message + " Y plane");
- ComparePlane(U,
- u_stride,
- output_frame->visible_data(media::VideoFrame::kUPlane),
- output_frame->stride(media::VideoFrame::kUPlane),
- 2,
- output_xsize / 2,
- output_ysize / 2,
- &input_pixels,
- message + " U plane");
- ComparePlane(V,
- v_stride,
- output_frame->visible_data(media::VideoFrame::kVPlane),
- output_frame->stride(media::VideoFrame::kVPlane),
- 2,
- output_xsize / 2,
- output_ysize / 2,
- &input_pixels,
- message + " V plane");
-
- context_->deleteTexture(src_texture);
+ ComparePlane(
+ Y, y_stride, output_frame->visible_data(media::VideoFrame::kYPlane),
+ output_frame->stride(media::VideoFrame::kYPlane), 2, output_xsize,
+ output_ysize, &input_pixels, message + " Y plane");
+ ComparePlane(
+ U, u_stride, output_frame->visible_data(media::VideoFrame::kUPlane),
+ output_frame->stride(media::VideoFrame::kUPlane), 2, output_xsize / 2,
+ output_ysize / 2, &input_pixels, message + " U plane");
+ ComparePlane(
+ V, v_stride, output_frame->visible_data(media::VideoFrame::kVPlane),
+ output_frame->stride(media::VideoFrame::kVPlane), 2, output_xsize / 2,
+ output_ysize / 2, &input_pixels, message + " V plane");
+
+ gl_->DeleteTextures(1, &src_texture);
}
void TestAddOps(int src, int dst, bool scale_x, bool allow3) {
@@ -1548,21 +1446,13 @@ class GLHelperTest : public testing::Test {
const std::string& description) {
std::vector<GLHelperScaling::ScalerStage> stages;
helper_scaling_->ConvertScalerOpsToScalerStages(
- content::GLHelper::SCALER_QUALITY_GOOD,
- gfx::Size(xsize, ysize),
- gfx::Rect(0, 0, xsize, ysize),
- gfx::Size(dst_xsize, dst_ysize),
- false,
- false,
- &x_ops_,
- &y_ops_,
- &stages);
+ content::GLHelper::SCALER_QUALITY_GOOD, gfx::Size(xsize, ysize),
+ gfx::Rect(0, 0, xsize, ysize), gfx::Size(dst_xsize, dst_ysize), false,
+ false, &x_ops_, &y_ops_, &stages);
EXPECT_EQ(x_ops_.size(), 0U);
EXPECT_EQ(y_ops_.size(), 0U);
- ValidateScalerStages(content::GLHelper::SCALER_QUALITY_GOOD,
- stages,
- gfx::Size(dst_xsize, dst_ysize),
- "");
+ ValidateScalerStages(content::GLHelper::SCALER_QUALITY_GOOD, stages,
+ gfx::Size(dst_xsize, dst_ysize), "");
EXPECT_EQ(PrintStages(stages), description);
}
@@ -1609,10 +1499,7 @@ class GLHelperTest : public testing::Test {
// X scaled to 40%, Y scaled 40%, two bilinear3 passes.
x_ops_.push_back(GLHelperScaling::ScaleOp(3, true, 40));
y_ops_.push_back(GLHelperScaling::ScaleOp(3, false, 40));
- CheckPipeline2(100,
- 100,
- 40,
- 40,
+ CheckPipeline2(100, 100, 40, 40,
"100x100 -> 100x40 bilinear3 Y\n"
"100x40 -> 40x40 bilinear3 X\n");
@@ -1620,10 +1507,7 @@ class GLHelperTest : public testing::Test {
x_ops_.push_back(GLHelperScaling::ScaleOp(0, true, 120));
x_ops_.push_back(GLHelperScaling::ScaleOp(2, true, 60));
y_ops_.push_back(GLHelperScaling::ScaleOp(3, false, 40));
- CheckPipeline2(100,
- 100,
- 60,
- 40,
+ CheckPipeline2(100, 100, 60, 40,
"100x100 -> 100x40 bilinear3 Y\n"
"100x40 -> 60x40 bilinear2 X\n");
@@ -1631,10 +1515,7 @@ class GLHelperTest : public testing::Test {
x_ops_.push_back(GLHelperScaling::ScaleOp(3, true, 40));
y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 120));
y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 60));
- CheckPipeline2(100,
- 100,
- 40,
- 60,
+ CheckPipeline2(100, 100, 40, 60,
"100x100 -> 100x60 bilinear2 Y\n"
"100x60 -> 40x60 bilinear3 X\n");
@@ -1645,10 +1526,7 @@ class GLHelperTest : public testing::Test {
y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 120));
y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 60));
y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 30));
- CheckPipeline2(100,
- 100,
- 30,
- 30,
+ CheckPipeline2(100, 100, 30, 30,
"100x100 -> 100x30 bilinear4 Y\n"
"100x30 -> 30x30 bilinear4 X\n");
@@ -1666,10 +1544,7 @@ class GLHelperTest : public testing::Test {
y_ops_.push_back(GLHelperScaling::ScaleOp(0, false, 120));
y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 60));
y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 30));
- CheckPipeline2(100,
- 100,
- 150,
- 30,
+ CheckPipeline2(100, 100, 150, 30,
"100x100 -> 100x30 bilinear4 Y\n"
"100x30 -> 150x30 bilinear\n");
@@ -1690,10 +1565,7 @@ class GLHelperTest : public testing::Test {
y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 4));
y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 2));
y_ops_.push_back(GLHelperScaling::ScaleOp(2, false, 1));
- CheckPipeline2(100,
- 100,
- 1,
- 1,
+ CheckPipeline2(100, 100, 1, 1,
"100x100 -> 100x32 bilinear4 Y\n"
"100x32 -> 100x4 bilinear4 Y\n"
"100x4 -> 64x1 bilinear2x2\n"
@@ -1701,8 +1573,8 @@ class GLHelperTest : public testing::Test {
"8x1 -> 1x1 bilinear4 X\n");
}
- scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> context_;
- gpu::ContextSupport* context_support_;
+ scoped_ptr<gpu::GLInProcessContext> context_;
+ gpu::gles2::GLES2Interface* gl_;
scoped_ptr<content::GLHelper> helper_;
scoped_ptr<content::GLHelperScaling> helper_scaling_;
std::deque<GLHelperScaling::ScaleOp> x_ops_, y_ops_;
@@ -1715,68 +1587,53 @@ class GLHelperPixelTest : public GLHelperTest {
TEST_F(GLHelperTest, RGBASyncReadbackTest) {
const int kTestSize = 64;
- bool result = TestTextureFormatReadback(gfx::Size(kTestSize,kTestSize),
- kRGBA_8888_SkColorType,
- false);
+ bool result = TestTextureFormatReadback(gfx::Size(kTestSize, kTestSize),
+ kRGBA_8888_SkColorType, false);
EXPECT_EQ(result, true);
}
-
TEST_F(GLHelperTest, BGRASyncReadbackTest) {
const int kTestSize = 64;
- bool result = TestTextureFormatReadback(gfx::Size(kTestSize,kTestSize),
- kBGRA_8888_SkColorType,
- false);
+ bool result = TestTextureFormatReadback(gfx::Size(kTestSize, kTestSize),
+ kBGRA_8888_SkColorType, false);
EXPECT_EQ(result, true);
}
TEST_F(GLHelperTest, RGB565SyncReadbackTest) {
const int kTestSize = 64;
- bool result = TestTextureFormatReadback(gfx::Size(kTestSize,kTestSize),
- kRGB_565_SkColorType,
- false);
+ bool result = TestTextureFormatReadback(gfx::Size(kTestSize, kTestSize),
+ kRGB_565_SkColorType, false);
EXPECT_EQ(result, true);
}
TEST_F(GLHelperTest, RGBAASyncReadbackTest) {
const int kTestSize = 64;
- bool result = TestTextureFormatReadback(gfx::Size(kTestSize,kTestSize),
- kRGBA_8888_SkColorType,
- true);
+ bool result = TestTextureFormatReadback(gfx::Size(kTestSize, kTestSize),
+ kRGBA_8888_SkColorType, true);
EXPECT_EQ(result, true);
}
TEST_F(GLHelperTest, BGRAASyncReadbackTest) {
const int kTestSize = 64;
- bool result = TestTextureFormatReadback(gfx::Size(kTestSize,kTestSize),
- kBGRA_8888_SkColorType,
- true);
+ bool result = TestTextureFormatReadback(gfx::Size(kTestSize, kTestSize),
+ kBGRA_8888_SkColorType, true);
EXPECT_EQ(result, true);
}
TEST_F(GLHelperTest, RGB565ASyncReadbackTest) {
const int kTestSize = 64;
- bool result = TestTextureFormatReadback(gfx::Size(kTestSize,kTestSize),
- kRGB_565_SkColorType,
- true);
+ bool result = TestTextureFormatReadback(gfx::Size(kTestSize, kTestSize),
+ kRGB_565_SkColorType, true);
EXPECT_EQ(result, true);
}
TEST_F(GLHelperPixelTest, YUVReadbackOptTest) {
// This test uses the gpu.service/gpu_decoder tracing events to detect how
// many scaling passes are actually performed by the YUV readback pipeline.
- StartTracing(TRACE_DISABLED_BY_DEFAULT("gpu.service") ","
- TRACE_DISABLED_BY_DEFAULT("gpu_decoder"));
-
- TestYUVReadback(800,
- 400,
- 800,
- 400,
- 0,
- 0,
- 1,
- false,
- true,
+ StartTracing(TRACE_DISABLED_BY_DEFAULT(
+ "gpu.service") "," TRACE_DISABLED_BY_DEFAULT("gpu_decoder"));
+
+ TestYUVReadback(800, 400, 800, 400, 0, 0, 1, false, true,
content::GLHelper::SCALER_QUALITY_FAST);
std::map<std::string, int> event_counts;
@@ -1799,10 +1656,10 @@ TEST_F(GLHelperPixelTest, YUVReadbackOptTest) {
}
}
-class GLHelperPixelYuvReadback :
- public GLHelperPixelTest,
- public ::testing::WithParamInterface<
- std::tr1::tuple<bool, bool, unsigned int, unsigned int>> {};
+class GLHelperPixelYuvReadback
+ : public GLHelperPixelTest,
+ public ::testing::WithParamInterface<
+ std::tr1::tuple<bool, bool, unsigned int, unsigned int>> {};
int kYUVReadBackSizes[] = {2, 4, 14};
@@ -1816,25 +1673,17 @@ TEST_P(GLHelperPixelYuvReadback, Test) {
for (unsigned int oy = y; oy < arraysize(kYUVReadBackSizes); oy++) {
// If output is a subsection of the destination frame, (letterbox)
// then try different variations of where the subsection goes.
- for (Margin xm = x < ox ? MarginLeft : MarginRight;
- xm <= MarginRight;
+ for (Margin xm = x < ox ? MarginLeft : MarginRight; xm <= MarginRight;
xm = NextMargin(xm)) {
- for (Margin ym = y < oy ? MarginLeft : MarginRight;
- ym <= MarginRight;
+ for (Margin ym = y < oy ? MarginLeft : MarginRight; ym <= MarginRight;
ym = NextMargin(ym)) {
for (int pattern = 0; pattern < 3; pattern++) {
- TestYUVReadback(kYUVReadBackSizes[x],
- kYUVReadBackSizes[y],
- kYUVReadBackSizes[ox],
- kYUVReadBackSizes[oy],
- compute_margin(kYUVReadBackSizes[x],
- kYUVReadBackSizes[ox], xm),
- compute_margin(kYUVReadBackSizes[y],
- kYUVReadBackSizes[oy], ym),
- pattern,
- flip,
- use_mrt,
- content::GLHelper::SCALER_QUALITY_GOOD);
+ TestYUVReadback(
+ kYUVReadBackSizes[x], kYUVReadBackSizes[y],
+ kYUVReadBackSizes[ox], kYUVReadBackSizes[oy],
+ compute_margin(kYUVReadBackSizes[x], kYUVReadBackSizes[ox], xm),
+ compute_margin(kYUVReadBackSizes[y], kYUVReadBackSizes[oy], ym),
+ pattern, flip, use_mrt, content::GLHelper::SCALER_QUALITY_GOOD);
if (HasFailure()) {
return;
}
@@ -1850,37 +1699,37 @@ INSTANTIATE_TEST_CASE_P(
,
GLHelperPixelYuvReadback,
::testing::Combine(
- ::testing::Bool(),
- ::testing::Bool(),
- ::testing::Range<unsigned int>(0, arraysize(kYUVReadBackSizes)),
- ::testing::Range<unsigned int>(0, arraysize(kYUVReadBackSizes))));
+ ::testing::Bool(),
+ ::testing::Bool(),
+ ::testing::Range<unsigned int>(0, arraysize(kYUVReadBackSizes)),
+ ::testing::Range<unsigned int>(0, arraysize(kYUVReadBackSizes))));
+int kRGBReadBackSizes[] = {3, 6, 16};
+
+class GLHelperPixelReadbackTest
+ : public GLHelperPixelTest,
+ public ::testing::WithParamInterface<std::tr1::tuple<unsigned int,
+ unsigned int,
+ unsigned int,
+ unsigned int,
+ unsigned int>> {};
// Per pixel tests, all sizes are small so that we can print
// out the generated bitmaps.
-TEST_F(GLHelperPixelTest, ScaleTest) {
- int sizes[] = {3, 6, 16};
+TEST_P(GLHelperPixelReadbackTest, ScaleTest) {
+ unsigned int q_index = std::tr1::get<0>(GetParam());
+ unsigned int x = std::tr1::get<1>(GetParam());
+ unsigned int y = std::tr1::get<2>(GetParam());
+ unsigned int dst_x = std::tr1::get<3>(GetParam());
+ unsigned int dst_y = std::tr1::get<4>(GetParam());
+
for (int flip = 0; flip <= 1; flip++) {
- for (size_t q_index = 0; q_index < arraysize(kQualities); q_index++) {
- for (int x = 0; x < 3; x++) {
- for (int y = 0; y < 3; y++) {
- for (int dst_x = 0; dst_x < 3; dst_x++) {
- for (int dst_y = 0; dst_y < 3; dst_y++) {
- for (int pattern = 0; pattern < 3; pattern++) {
- TestScale(sizes[x],
- sizes[y],
- sizes[dst_x],
- sizes[dst_y],
- pattern,
- q_index,
- flip == 1);
- if (HasFailure()) {
- return;
- }
- }
- }
- }
- }
+ for (int pattern = 0; pattern < 3; pattern++) {
+ TestScale(kRGBReadBackSizes[x], kRGBReadBackSizes[y],
+ kRGBReadBackSizes[dst_x], kRGBReadBackSizes[dst_y], pattern,
+ q_index, flip == 1);
+ if (HasFailure()) {
+ return;
}
}
}
@@ -1888,38 +1737,38 @@ TEST_F(GLHelperPixelTest, ScaleTest) {
// Per pixel tests, all sizes are small so that we can print
// out the generated bitmaps.
-TEST_F(GLHelperPixelTest, CropScaleReadbackAndCleanTextureTest) {
- const int kSizes[] = {3, 6, 16};
+TEST_P(GLHelperPixelReadbackTest, CropScaleReadbackAndCleanTextureTest) {
+ unsigned int q_index = std::tr1::get<0>(GetParam());
+ unsigned int x = std::tr1::get<1>(GetParam());
+ unsigned int y = std::tr1::get<2>(GetParam());
+ unsigned int dst_x = std::tr1::get<3>(GetParam());
+ unsigned int dst_y = std::tr1::get<4>(GetParam());
+
const SkColorType kColorTypes[] = {
kAlpha_8_SkColorType, kRGBA_8888_SkColorType, kBGRA_8888_SkColorType};
for (size_t color_type = 0; color_type < arraysize(kColorTypes);
color_type++) {
- // Test BEST and FAST qualities, skip GOOD
- for (size_t q_index = 0; q_index < arraysize(kQualities); q_index += 2) {
- for (size_t x = 0; x < arraysize(kSizes); x++) {
- for (size_t y = 0; y < arraysize(kSizes); y++) {
- for (size_t dst_x = 0; dst_x < arraysize(kSizes); dst_x++) {
- for (size_t dst_y = 0; dst_y < arraysize(kSizes); dst_y++) {
- for (int pattern = 0; pattern < 3; pattern++) {
- TestCropScaleReadbackAndCleanTexture(kSizes[x],
- kSizes[y],
- kSizes[dst_x],
- kSizes[dst_y],
- pattern,
- kColorTypes[color_type],
- false,
- q_index);
- if (HasFailure())
- return;
- }
- }
- }
- }
- }
+ for (int pattern = 0; pattern < 3; pattern++) {
+ TestCropScaleReadbackAndCleanTexture(
+ kRGBReadBackSizes[x], kRGBReadBackSizes[y], kRGBReadBackSizes[dst_x],
+ kRGBReadBackSizes[dst_y], pattern, kColorTypes[color_type], false,
+ q_index);
+ if (HasFailure())
+ return;
}
}
}
+INSTANTIATE_TEST_CASE_P(
+ ,
+ GLHelperPixelReadbackTest,
+ ::testing::Combine(
+ ::testing::Range<unsigned int>(0, arraysize(kQualities)),
+ ::testing::Range<unsigned int>(0, arraysize(kRGBReadBackSizes)),
+ ::testing::Range<unsigned int>(0, arraysize(kRGBReadBackSizes)),
+ ::testing::Range<unsigned int>(0, arraysize(kRGBReadBackSizes)),
+ ::testing::Range<unsigned int>(0, arraysize(kRGBReadBackSizes))));
+
// Validate that all scaling generates valid pipelines.
TEST_F(GLHelperTest, ValidateScalerPipelines) {
int sizes[] = {7, 99, 128, 256, 512, 719, 720, 721, 1920, 2011, 3217, 4096};
@@ -1928,8 +1777,8 @@ TEST_F(GLHelperTest, ValidateScalerPipelines) {
for (size_t y = 0; y < arraysize(sizes); y++) {
for (size_t dst_x = 0; dst_x < arraysize(sizes); dst_x++) {
for (size_t dst_y = 0; dst_y < arraysize(sizes); dst_y++) {
- TestScalerPipeline(
- q, sizes[x], sizes[y], sizes[dst_x], sizes[dst_y]);
+ TestScalerPipeline(q, sizes[x], sizes[y], sizes[dst_x],
+ sizes[dst_y]);
if (HasFailure()) {
return;
}
@@ -1944,26 +1793,14 @@ TEST_F(GLHelperTest, ValidateScalerPipelines) {
// for a few common use cases.
TEST_F(GLHelperTest, CheckSpecificPipelines) {
// Upscale should be single pass.
- CheckPipeline(content::GLHelper::SCALER_QUALITY_GOOD,
- 1024,
- 700,
- 1280,
- 720,
+ CheckPipeline(content::GLHelper::SCALER_QUALITY_GOOD, 1024, 700, 1280, 720,
"1024x700 -> 1280x720 bilinear\n");
// Slight downscale should use BILINEAR2X2.
- CheckPipeline(content::GLHelper::SCALER_QUALITY_GOOD,
- 1280,
- 720,
- 1024,
- 700,
+ CheckPipeline(content::GLHelper::SCALER_QUALITY_GOOD, 1280, 720, 1024, 700,
"1280x720 -> 1024x700 bilinear2x2\n");
// Most common tab capture pipeline on the Pixel.
// Should be using two BILINEAR3 passes.
- CheckPipeline(content::GLHelper::SCALER_QUALITY_GOOD,
- 2560,
- 1476,
- 1249,
- 720,
+ CheckPipeline(content::GLHelper::SCALER_QUALITY_GOOD, 2560, 1476, 1249, 720,
"2560x1476 -> 2560x720 bilinear3 Y\n"
"2560x720 -> 1249x720 bilinear3 X\n");
}
@@ -1989,28 +1826,3 @@ TEST_F(GLHelperTest, CheckOptimizations) {
}
} // namespace content
-
-namespace {
-
-int RunHelper(base::TestSuite* test_suite) {
- content::UnitTestTestSuite runner(test_suite);
- base::MessageLoopForIO message_loop;
- return runner.Run();
-}
-
-} // namespace
-
-// These tests needs to run against a proper GL environment, so we
-// need to set it up before we can run the tests.
-int main(int argc, char** argv) {
- base::CommandLine::Init(argc, argv);
- base::TestSuite* suite = new content::ContentTestSuite(argc, argv);
-#if defined(OS_MACOSX)
- base::mac::ScopedNSAutoreleasePool pool;
-#endif
-
- return base::LaunchUnitTestsSerially(
- argc,
- argv,
- base::Bind(&RunHelper, base::Unretained(suite)));
-}
diff --git a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc
index adf0764c65a..f3eb5f5aa20 100644
--- a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.cc
@@ -41,12 +41,12 @@ GpuBrowserCompositorOutputSurface::GpuBrowserCompositorOutputSurface(
GpuBrowserCompositorOutputSurface::~GpuBrowserCompositorOutputSurface() {}
-CommandBufferProxyImpl*
+gpu::CommandBufferProxyImpl*
GpuBrowserCompositorOutputSurface::GetCommandBufferProxy() {
ContextProviderCommandBuffer* provider_command_buffer =
static_cast<content::ContextProviderCommandBuffer*>(
context_provider_.get());
- CommandBufferProxyImpl* command_buffer_proxy =
+ gpu::CommandBufferProxyImpl* command_buffer_proxy =
provider_command_buffer->GetCommandBufferProxy();
DCHECK(command_buffer_proxy);
return command_buffer_proxy;
diff --git a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h
index ae08e8d1a2d..4133bc36951 100644
--- a/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/gpu_browser_compositor_output_surface.h
@@ -11,12 +11,15 @@
#include "content/browser/compositor/browser_compositor_output_surface.h"
#include "ui/gfx/swap_result.h"
+namespace gpu {
+class CommandBufferProxyImpl;
+}
+
namespace ui {
class CompositorVSyncManager;
}
namespace content {
-class CommandBufferProxyImpl;
class BrowserCompositorOverlayCandidateValidator;
class ReflectorTexture;
@@ -64,7 +67,7 @@ class GpuBrowserCompositorOutputSurface
ShouldShowFramesState should_show_frames_state_;
#endif
- CommandBufferProxyImpl* GetCommandBufferProxy();
+ gpu::CommandBufferProxyImpl* GetCommandBufferProxy();
base::CancelableCallback<void(const std::vector<ui::LatencyInfo>&,
gfx::SwapResult)>
diff --git a/chromium/content/browser/compositor/gpu_process_transport_factory.cc b/chromium/content/browser/compositor/gpu_process_transport_factory.cc
index 874debf5f1e..9a4ad655d5b 100644
--- a/chromium/content/browser/compositor/gpu_process_transport_factory.cc
+++ b/chromium/content/browser/compositor/gpu_process_transport_factory.cc
@@ -26,6 +26,7 @@
#include "cc/surfaces/surface_manager.h"
#include "content/browser/compositor/browser_compositor_output_surface.h"
#include "content/browser/compositor/browser_compositor_overlay_candidate_validator.h"
+#include "content/browser/compositor/gl_helper.h"
#include "content/browser/compositor/gpu_browser_compositor_output_surface.h"
#include "content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h"
#include "content/browser/compositor/offscreen_browser_compositor_output_surface.h"
@@ -34,27 +35,24 @@
#include "content/browser/compositor/software_output_device_mus.h"
#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
-#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_surface_tracker.h"
#include "content/browser/renderer_host/render_widget_host_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"
-#include "content/common/gpu/gpu_process_launch_causes.h"
+#include "content/common/gpu_process_launch_causes.h"
#include "content/common/host_shared_bitmap_manager.h"
#include "content/public/common/content_switches.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/mailbox.h"
+#include "gpu/ipc/client/gpu_channel_host.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/compositor_constants.h"
#include "ui/compositor/compositor_switches.h"
#include "ui/compositor/layer.h"
#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/native_widget_types.h"
#if defined(MOJO_RUNNER_CLIENT)
#include "content/common/mojo/mojo_shell_connection_impl.h"
@@ -62,6 +60,7 @@
#if defined(OS_WIN)
#include "content/browser/compositor/software_output_device_win.h"
+#include "ui/gfx/win/rendering_window_manager.h"
#elif defined(USE_OZONE)
#include "content/browser/compositor/browser_compositor_overlay_candidate_validator_ozone.h"
#include "content/browser/compositor/software_output_device_ozone.h"
@@ -99,11 +98,9 @@ GpuProcessTransportFactory::GpuProcessTransportFactory()
: next_surface_id_namespace_(1u),
task_graph_runner_(new cc::SingleThreadTaskGraphRunner),
callback_factory_(this) {
- ui::Layer::InitializeUILayerSettings();
cc::SetClientNameForMetrics("Browser");
- if (UseSurfacesEnabled())
- surface_manager_ = make_scoped_ptr(new cc::SurfaceManager);
+ surface_manager_ = make_scoped_ptr(new cc::SurfaceManager);
task_graph_runner_->Start("CompositorTileWorker1",
base::SimpleThread::Options());
@@ -123,15 +120,11 @@ GpuProcessTransportFactory::~GpuProcessTransportFactory() {
scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
GpuProcessTransportFactory::CreateOffscreenCommandBufferContext() {
-#if defined(OS_ANDROID)
- return CreateContextCommon(scoped_refptr<GpuChannelHost>(nullptr), 0);
-#else
CauseForGpuLaunch cause =
CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
- scoped_refptr<GpuChannelHost> gpu_channel_host(
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel_host(
BrowserGpuChannelHostFactory::instance()->EstablishGpuChannelSync(cause));
- return CreateContextCommon(gpu_channel_host, 0);
-#endif // OS_ANDROID
+ return CreateContextCommon(gpu_channel_host, gpu::kNullSurfaceHandle);
}
scoped_ptr<cc::SoftwareOutputDevice>
@@ -224,6 +217,11 @@ void GpuProcessTransportFactory::CreateOutputSurface(
data->surface = nullptr;
}
+#if defined(OS_WIN)
+ gfx::RenderingWindowManager::GetInstance()->UnregisterParent(
+ compositor->widget());
+#endif
+
bool create_gpu_output_surface =
ShouldCreateGpuOutputSurface(compositor.get());
if (create_gpu_output_surface) {
@@ -262,6 +260,11 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
create_gpu_output_surface = false;
}
+#if defined(OS_WIN)
+ gfx::RenderingWindowManager::GetInstance()->RegisterParent(
+ compositor->widget());
+#endif
+
scoped_refptr<ContextProviderCommandBuffer> context_provider;
if (create_gpu_output_surface) {
// Try to reuse existing worker context provider.
@@ -274,20 +277,26 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
shared_worker_context_provider_lost = true;
}
}
- scoped_refptr<GpuChannelHost> gpu_channel_host =
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel_host =
BrowserGpuChannelHostFactory::instance()->GetGpuChannel();
if (gpu_channel_host.get()) {
+ GpuSurfaceTracker* tracker = GpuSurfaceTracker::Get();
+ gpu::SurfaceHandle surface_handle =
+ data->surface_id ? tracker->GetSurfaceHandle(data->surface_id)
+ : gpu::kNullSurfaceHandle;
+ // This context is used for both the browser compositor and the display
+ // compositor.
context_provider = ContextProviderCommandBuffer::Create(
GpuProcessTransportFactory::CreateContextCommon(gpu_channel_host,
- data->surface_id),
- BROWSER_COMPOSITOR_ONSCREEN_CONTEXT);
+ surface_handle),
+ DISPLAY_COMPOSITOR_ONSCREEN_CONTEXT);
if (context_provider && !context_provider->BindToCurrentThread())
context_provider = nullptr;
if (!shared_worker_context_provider_ ||
shared_worker_context_provider_lost) {
shared_worker_context_provider_ = ContextProviderCommandBuffer::Create(
- GpuProcessTransportFactory::CreateContextCommon(gpu_channel_host,
- 0),
+ GpuProcessTransportFactory::CreateContextCommon(
+ gpu_channel_host, gpu::kNullSurfaceHandle),
BROWSER_WORKER_CONTEXT);
if (shared_worker_context_provider_ &&
!shared_worker_context_provider_->BindToCurrentThread())
@@ -334,7 +343,7 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
GLenum format = GL_RGB;
#if defined(OS_MACOSX)
target = GL_TEXTURE_RECTANGLE_ARB;
- format = GL_BGRA_EXT;
+ format = GL_RGBA;
#endif
surface =
make_scoped_ptr(new GpuSurfacelessBrowserCompositorOutputSurface(
@@ -361,10 +370,10 @@ void GpuProcessTransportFactory::EstablishedGpuChannel(
if (data->reflector)
data->reflector->OnSourceSurfaceReady(data->surface);
- if (!UseSurfacesEnabled()) {
- compositor->SetOutputSurface(std::move(surface));
- return;
- }
+#if defined(OS_WIN)
+ gfx::RenderingWindowManager::GetInstance()->DoSetParentOnChild(
+ compositor->widget());
+#endif
// This gets a bit confusing. Here we have a ContextProvider in the |surface|
// configured to render directly to this widget. We need to make an
@@ -442,6 +451,10 @@ void GpuProcessTransportFactory::RemoveCompositor(ui::Compositor* compositor) {
DCHECK(!gl_helper_) << "Destroying the GLHelper should not cause a new "
"GLHelper to be created.";
}
+#if defined(OS_WIN)
+ gfx::RenderingWindowManager::GetInstance()->UnregisterParent(
+ compositor->widget());
+#endif
}
bool GpuProcessTransportFactory::DoesCreateTestContexts() { return false; }
@@ -579,24 +592,13 @@ GpuProcessTransportFactory::CreatePerCompositorData(
DCHECK(!per_compositor_data_[compositor]);
gfx::AcceleratedWidget widget = compositor->widget();
- GpuSurfaceTracker* tracker = GpuSurfaceTracker::Get();
PerCompositorData* data = new PerCompositorData;
if (compositor->widget() == gfx::kNullAcceleratedWidget) {
data->surface_id = 0;
} else {
+ GpuSurfaceTracker* tracker = GpuSurfaceTracker::Get();
data->surface_id = tracker->AddSurfaceForNativeWidget(widget);
-#if defined(OS_MACOSX) || defined(OS_ANDROID)
- // On Mac and Android, we can't pass the AcceleratedWidget, which is
- // process-local, so instead we pass the surface_id, so that we can look up
- // the AcceleratedWidget on the GPU side or when we receive
- // GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params.
- gfx::PluginWindowHandle handle = data->surface_id;
-#else
- gfx::PluginWindowHandle handle = widget;
-#endif
- tracker->SetSurfaceHandle(data->surface_id,
- gfx::GLSurfaceHandle(handle, gfx::NATIVE_DIRECT));
}
per_compositor_data_[compositor] = data;
@@ -606,31 +608,46 @@ GpuProcessTransportFactory::CreatePerCompositorData(
scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
GpuProcessTransportFactory::CreateContextCommon(
- scoped_refptr<GpuChannelHost> gpu_channel_host,
- int surface_id) {
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel_host,
+ gpu::SurfaceHandle surface_handle) {
if (!GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor())
- return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
- blink::WebGraphicsContext3D::Attributes attrs;
- attrs.shareResources = true;
- attrs.depth = false;
- attrs.stencil = false;
- attrs.antialias = false;
- attrs.noAutomaticFlushes = true;
- bool lose_context_when_out_of_memory = true;
- if (!gpu_channel_host.get()) {
+ return nullptr;
+ if (!gpu_channel_host) {
LOG(ERROR) << "Failed to establish GPU channel.";
- return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
+ return nullptr;
}
+
+ // This is called from a few places to create different contexts:
+ // - The shared main thread context (offscreen).
+ // - The compositor context, which is used by the browser compositor
+ // (offscreen) for synchronization mostly, and by the display compositor
+ // (onscreen) for actual GL drawing.
+ // - The compositor worker context (offscreen) used for GPU raster.
+ // So ask for capabilities needed by any of these cases (we can optimize by
+ // branching on |surface_handle| being null if these needs diverge).
+ //
+ // The default framebuffer for an offscreen context is not used, so it does
+ // not need alpha, stencil, depth, antialiasing. The display compositor does
+ // not use these things either, so we can request nothing here.
+ gpu::gles2::ContextCreationAttribHelper attributes;
+ attributes.alpha_size = -1;
+ attributes.depth_size = 0;
+ attributes.stencil_size = 0;
+ attributes.samples = 0;
+ attributes.sample_buffers = 0;
+ attributes.bind_generates_resource = false;
+ attributes.lose_context_when_out_of_memory = true;
+
+ bool share_resources = true;
+ bool automatic_flushes = false;
+
GURL url("chrome://gpu/GpuProcessTransportFactory::CreateContextCommon");
scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
new WebGraphicsContext3DCommandBufferImpl(
- surface_id,
- url,
- gpu_channel_host.get(),
- attrs,
- lose_context_when_out_of_memory,
+ surface_handle, url, gpu_channel_host.get(), attributes,
+ gfx::PreferIntegratedGpu, share_resources, automatic_flushes,
WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits(),
- NULL));
+ nullptr));
return context;
}
diff --git a/chromium/content/browser/compositor/gpu_process_transport_factory.h b/chromium/content/browser/compositor/gpu_process_transport_factory.h
index ee8d60e9ac9..f4e007aa188 100644
--- a/chromium/content/browser/compositor/gpu_process_transport_factory.h
+++ b/chromium/content/browser/compositor/gpu_process_transport_factory.h
@@ -17,7 +17,8 @@
#include "base/observer_list.h"
#include "build/build_config.h"
#include "content/browser/compositor/image_transport_factory.h"
-#include "content/common/gpu/client/gpu_channel_host.h"
+#include "gpu/ipc/client/gpu_channel_host.h"
+#include "gpu/ipc/common/surface_handle.h"
#include "ui/compositor/compositor.h"
namespace base {
@@ -94,8 +95,8 @@ class GpuProcessTransportFactory
bool create_gpu_output_surface,
int num_attempts);
scoped_ptr<WebGraphicsContext3DCommandBufferImpl> CreateContextCommon(
- scoped_refptr<GpuChannelHost> gpu_channel_host,
- int surface_id);
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel_host,
+ gpu::SurfaceHandle surface_handle);
void OnLostMainThreadSharedContextInsideCallback();
void OnLostMainThreadSharedContext();
diff --git a/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc b/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc
index 0913548f2fa..5e85a4e315d 100644
--- a/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc
+++ b/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.cc
@@ -10,10 +10,10 @@
#include "cc/output/output_surface_client.h"
#include "content/browser/compositor/browser_compositor_overlay_candidate_validator.h"
#include "content/browser/compositor/buffer_queue.h"
+#include "content/browser/compositor/gl_helper.h"
#include "content/browser/compositor/reflector_impl.h"
#include "content/browser/gpu/gpu_surface_tracker.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
-#include "content/common/gpu/client/gl_helper.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h"
@@ -29,7 +29,7 @@ GpuSurfacelessBrowserCompositorOutputSurface::
overlay_candidate_validator,
unsigned int target,
unsigned int internalformat,
- BrowserGpuMemoryBufferManager* gpu_memory_buffer_manager)
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager)
: GpuBrowserCompositorOutputSurface(context,
worker_context,
vsync_manager,
diff --git a/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h b/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h
index a869fccd8cf..23412198d0e 100644
--- a/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h
+++ b/chromium/content/browser/compositor/gpu_surfaceless_browser_compositor_output_surface.h
@@ -7,9 +7,12 @@
#include "content/browser/compositor/gpu_browser_compositor_output_surface.h"
+namespace gpu {
+class GpuMemoryBufferManager;
+}
+
namespace content {
-class BrowserGpuMemoryBufferManager;
class BufferQueue;
class GLHelper;
@@ -25,7 +28,7 @@ class GpuSurfacelessBrowserCompositorOutputSurface
overlay_candidate_validator,
unsigned int target,
unsigned int internalformat,
- BrowserGpuMemoryBufferManager* gpu_memory_buffer_manager);
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager);
~GpuSurfacelessBrowserCompositorOutputSurface() override;
private:
@@ -45,7 +48,7 @@ class GpuSurfacelessBrowserCompositorOutputSurface
unsigned int internalformat_;
scoped_ptr<GLHelper> gl_helper_;
scoped_ptr<BufferQueue> output_surface_;
- BrowserGpuMemoryBufferManager* gpu_memory_buffer_manager_;
+ gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_;
};
} // namespace content
diff --git a/chromium/content/browser/compositor/owned_mailbox.cc b/chromium/content/browser/compositor/owned_mailbox.cc
index 912d4d569b7..8e0558212a6 100644
--- a/chromium/content/browser/compositor/owned_mailbox.cc
+++ b/chromium/content/browser/compositor/owned_mailbox.cc
@@ -5,8 +5,8 @@
#include "content/browser/compositor/owned_mailbox.h"
#include "base/logging.h"
+#include "content/browser/compositor/gl_helper.h"
#include "content/browser/compositor/image_transport_factory.h"
-#include "content/common/gpu/client/gl_helper.h"
namespace content {
diff --git a/chromium/content/browser/compositor/reflector_texture.cc b/chromium/content/browser/compositor/reflector_texture.cc
index 231066275d9..c9b742d425f 100644
--- a/chromium/content/browser/compositor/reflector_texture.cc
+++ b/chromium/content/browser/compositor/reflector_texture.cc
@@ -4,9 +4,9 @@
#include "content/browser/compositor/reflector_texture.h"
+#include "content/browser/compositor/gl_helper.h"
#include "content/browser/compositor/owned_mailbox.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
-#include "content/common/gpu/client/gl_helper.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
diff --git a/chromium/content/browser/compositor/software_output_device_mac.h b/chromium/content/browser/compositor/software_output_device_mac.h
index a613ab4b1d8..84e09873597 100644
--- a/chromium/content/browser/compositor/software_output_device_mac.h
+++ b/chromium/content/browser/compositor/software_output_device_mac.h
@@ -10,6 +10,8 @@
#include "base/mac/scoped_cftyperef.h"
#include "base/macros.h"
#include "cc/output/software_output_device.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "ui/gfx/vsync_provider.h"
@@ -63,7 +65,7 @@ class SoftwareOutputDeviceMac :
// The SkCanvas wrapps the mapped current IOSurface. It is valid only between
// BeginPaint and EndPaint.
- skia::RefPtr<SkCanvas> canvas_;
+ sk_sp<SkCanvas> canvas_;
gfx::VSyncProvider::UpdateVSyncCallback update_vsync_callback_;
diff --git a/chromium/content/browser/compositor/software_output_device_mac.mm b/chromium/content/browser/compositor/software_output_device_mac.mm
index e71f6782878..9c9c3931480 100644
--- a/chromium/content/browser/compositor/software_output_device_mac.mm
+++ b/chromium/content/browser/compositor/software_output_device_mac.mm
@@ -123,7 +123,7 @@ SkCanvas* SoftwareOutputDeviceMac::BeginPaint(
IOSurfaceGetBaseAddress(io_surfaces_[current_index_]));
size_t stride = IOSurfaceGetBytesPerRow(io_surfaces_[current_index_]);
- canvas_ = skia::AdoptRef(SkCanvas::NewRasterDirectN32(
+ canvas_ = sk_sp<SkCanvas>(SkCanvas::NewRasterDirectN32(
pixel_size_.width(), pixel_size_.height(), pixels, stride));
CopyPreviousBufferDamage(SkRegion(gfx::RectToSkIRect(new_damage_rect)));
@@ -141,7 +141,7 @@ void SoftwareOutputDeviceMac::EndPaint() {
DLOG(ERROR) << "Failed to unlock IOSurface " << io_result;
}
- canvas_ = nullptr;
+ canvas_.reset();
base::TimeTicks vsync_timebase;
base::TimeDelta vsync_interval;
ui::AcceleratedWidgetMacGotFrame(
diff --git a/chromium/content/browser/compositor/software_output_device_win.cc b/chromium/content/browser/compositor/software_output_device_win.cc
index a712def1911..3ab7677a543 100644
--- a/chromium/content/browser/compositor/software_output_device_win.cc
+++ b/chromium/content/browser/compositor/software_output_device_win.cc
@@ -122,7 +122,7 @@ void SoftwareOutputDeviceWin::Resize(const gfx::Size& viewport_pixel_size,
viewport_pixel_size_ = viewport_pixel_size;
if (backing_)
backing_->Resized();
- contents_.clear();
+ contents_.reset();
}
SkCanvas* SoftwareOutputDeviceWin::BeginPaint(const gfx::Rect& damage_rect) {
@@ -141,7 +141,7 @@ SkCanvas* SoftwareOutputDeviceWin::BeginPaint(const gfx::Rect& damage_rect) {
}
}
if (can_create_contents) {
- contents_ = skia::AdoptRef(skia::CreatePlatformCanvas(
+ contents_ = sk_sp<SkCanvas>(skia::CreatePlatformCanvas(
viewport_pixel_size_.width(), viewport_pixel_size_.height(), true,
shared_section, skia::CRASH_ON_FAILURE));
}
@@ -180,10 +180,10 @@ void SoftwareOutputDeviceWin::EndPaint() {
style |= WS_EX_LAYERED;
SetWindowLong(hwnd_, GWL_EXSTYLE, style);
- HDC dib_dc = skia::BeginPlatformPaint(contents_.get());
+ skia::ScopedPlatformPaint spp(contents_.get());
+ HDC dib_dc = spp.GetPlatformSurface();
::UpdateLayeredWindow(hwnd_, NULL, &position, &size, dib_dc, &zero,
RGB(0xFF, 0xFF, 0xFF), &blend, ULW_ALPHA);
- skia::EndPlatformPaint(contents_.get());
} else {
HDC hdc = ::GetDC(hwnd_);
RECT src_rect = rect.ToRECT();
@@ -196,7 +196,7 @@ void SoftwareOutputDeviceWin::EndPaint() {
void SoftwareOutputDeviceWin::ReleaseContents() {
DCHECK(!contents_ || contents_->unique());
DCHECK(!in_paint_);
- contents_.clear();
+ contents_.reset();
}
} // namespace content
diff --git a/chromium/content/browser/compositor/software_output_device_win.h b/chromium/content/browser/compositor/software_output_device_win.h
index 1cc267dd55b..5c80340808c 100644
--- a/chromium/content/browser/compositor/software_output_device_win.h
+++ b/chromium/content/browser/compositor/software_output_device_win.h
@@ -13,6 +13,8 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "cc/output/software_output_device.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
namespace base {
class SharedMemory;
@@ -61,7 +63,7 @@ class SoftwareOutputDeviceWin : public cc::SoftwareOutputDevice {
private:
HWND hwnd_;
- skia::RefPtr<SkCanvas> contents_;
+ sk_sp<SkCanvas> contents_;
bool is_hwnd_composited_;
OutputDeviceBacking* backing_;
bool in_paint_;
diff --git a/chromium/content/browser/compositor/surface_utils.cc b/chromium/content/browser/compositor/surface_utils.cc
index 7ae05912a65..4f4b3bad88c 100644
--- a/chromium/content/browser/compositor/surface_utils.cc
+++ b/chromium/content/browser/compositor/surface_utils.cc
@@ -4,20 +4,162 @@
#include "content/browser/compositor/surface_utils.h"
+#include "base/callback_helpers.h"
+#include "base/memory/ref_counted.h"
#include "build/build_config.h"
+#include "cc/output/copy_output_result.h"
+#include "cc/resources/single_release_callback.h"
#include "cc/surfaces/surface_id_allocator.h"
+#include "content/browser/compositor/gl_helper.h"
+#include "skia/ext/image_operations.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkColorFilter.h"
+#include "third_party/skia/include/core/SkPaint.h"
+#include "third_party/skia/include/effects/SkLumaColorFilter.h"
+#include "ui/gfx/geometry/rect.h"
-#if defined(OS_ANDROID) && !defined(USE_AURA)
+#if defined(OS_ANDROID)
#include "content/browser/renderer_host/compositor_impl_android.h"
#else
#include "content/browser/compositor/image_transport_factory.h"
#include "ui/compositor/compositor.h"
#endif
+namespace {
+
+#if !defined(OS_ANDROID) || defined(USE_AURA)
+void CopyFromCompositingSurfaceFinished(
+ const content::ReadbackRequestCallback& callback,
+ scoped_ptr<cc::SingleReleaseCallback> release_callback,
+ scoped_ptr<SkBitmap> bitmap,
+ scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
+ bool result) {
+ bitmap_pixels_lock.reset();
+
+ gpu::SyncToken sync_token;
+ if (result) {
+ content::GLHelper* gl_helper =
+ content::ImageTransportFactory::GetInstance()->GetGLHelper();
+ if (gl_helper)
+ gl_helper->GenerateSyncToken(&sync_token);
+ }
+ const bool lost_resource = !sync_token.HasData();
+ release_callback->Run(sync_token, lost_resource);
+
+ callback.Run(*bitmap,
+ result ? content::READBACK_SUCCESS : content::READBACK_FAILED);
+}
+#endif
+
+// TODO(wjmaclean): There is significant overlap between
+// PrepareTextureCopyOutputResult and CopyFromCompositingSurfaceFinished in
+// this file, and the versions in RenderWidgetHostViewAndroid. They should
+// be merged. See https://crbug.com/582955
+void PrepareTextureCopyOutputResult(
+ const gfx::Size& dst_size_in_pixel,
+ const SkColorType color_type,
+ const content::ReadbackRequestCallback& callback,
+ scoped_ptr<cc::CopyOutputResult> result) {
+#if defined(OS_ANDROID) && !defined(USE_AURA)
+ // TODO(wjmaclean): See if there's an equivalent pathway for Android and
+ // implement it here.
+ callback.Run(SkBitmap(), content::READBACK_FAILED);
+#else
+ DCHECK(result->HasTexture());
+ base::ScopedClosureRunner scoped_callback_runner(
+ base::Bind(callback, SkBitmap(), content::READBACK_FAILED));
+
+ // TODO(siva.gunturi): We should be able to validate the format here using
+ // GLHelper::IsReadbackConfigSupported before we processs the result.
+ // See crbug.com/415682 and crbug.com/415131.
+ scoped_ptr<SkBitmap> bitmap(new SkBitmap);
+ if (!bitmap->tryAllocPixels(SkImageInfo::Make(
+ dst_size_in_pixel.width(), dst_size_in_pixel.height(), color_type,
+ kOpaque_SkAlphaType))) {
+ scoped_callback_runner.Reset(base::Bind(
+ callback, SkBitmap(), content::READBACK_BITMAP_ALLOCATION_FAILURE));
+ return;
+ }
+
+ content::ImageTransportFactory* factory =
+ content::ImageTransportFactory::GetInstance();
+ content::GLHelper* gl_helper = factory->GetGLHelper();
+ if (!gl_helper)
+ return;
+
+ scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock(
+ new SkAutoLockPixels(*bitmap));
+ uint8_t* pixels = static_cast<uint8_t*>(bitmap->getPixels());
+
+ cc::TextureMailbox texture_mailbox;
+ scoped_ptr<cc::SingleReleaseCallback> release_callback;
+ result->TakeTexture(&texture_mailbox, &release_callback);
+ DCHECK(texture_mailbox.IsTexture());
+
+ ignore_result(scoped_callback_runner.Release());
+
+ gl_helper->CropScaleReadbackAndCleanMailbox(
+ texture_mailbox.mailbox(), texture_mailbox.sync_token(), result->size(),
+ gfx::Rect(result->size()), dst_size_in_pixel, pixels, color_type,
+ base::Bind(&CopyFromCompositingSurfaceFinished, callback,
+ base::Passed(&release_callback), base::Passed(&bitmap),
+ base::Passed(&bitmap_pixels_lock)),
+ content::GLHelper::SCALER_QUALITY_GOOD);
+#endif
+}
+
+void PrepareBitmapCopyOutputResult(
+ const gfx::Size& dst_size_in_pixel,
+ const SkColorType preferred_color_type,
+ const content::ReadbackRequestCallback& callback,
+ scoped_ptr<cc::CopyOutputResult> result) {
+ SkColorType color_type = preferred_color_type;
+ if (color_type != kN32_SkColorType && color_type != kAlpha_8_SkColorType) {
+ // Switch back to default colortype if format not supported.
+ color_type = kN32_SkColorType;
+ }
+ DCHECK(result->HasBitmap());
+ scoped_ptr<SkBitmap> source = result->TakeBitmap();
+ DCHECK(source);
+ SkBitmap scaled_bitmap;
+ if (source->width() != dst_size_in_pixel.width() ||
+ source->height() != dst_size_in_pixel.height()) {
+ scaled_bitmap = skia::ImageOperations::Resize(
+ *source, skia::ImageOperations::RESIZE_BEST, dst_size_in_pixel.width(),
+ dst_size_in_pixel.height());
+ } else {
+ scaled_bitmap = *source;
+ }
+ if (color_type == kN32_SkColorType) {
+ DCHECK_EQ(scaled_bitmap.colorType(), kN32_SkColorType);
+ callback.Run(scaled_bitmap, content::READBACK_SUCCESS);
+ return;
+ }
+ DCHECK_EQ(color_type, kAlpha_8_SkColorType);
+ // The software path currently always returns N32 bitmap regardless of the
+ // |color_type| we ask for.
+ DCHECK_EQ(scaled_bitmap.colorType(), kN32_SkColorType);
+ // Paint |scaledBitmap| to alpha-only |grayscale_bitmap|.
+ SkBitmap grayscale_bitmap;
+ bool success = grayscale_bitmap.tryAllocPixels(
+ SkImageInfo::MakeA8(scaled_bitmap.width(), scaled_bitmap.height()));
+ if (!success) {
+ callback.Run(SkBitmap(), content::READBACK_BITMAP_ALLOCATION_FAILURE);
+ return;
+ }
+ SkCanvas canvas(grayscale_bitmap);
+ SkPaint paint;
+ paint.setColorFilter(SkLumaColorFilter::Make());
+ canvas.drawBitmap(scaled_bitmap, SkIntToScalar(0), SkIntToScalar(0), &paint);
+ callback.Run(grayscale_bitmap, content::READBACK_SUCCESS);
+}
+
+} // namespace
+
namespace content {
scoped_ptr<cc::SurfaceIdAllocator> CreateSurfaceIdAllocator() {
-#if defined(OS_ANDROID) && !defined(USE_AURA)
+#if defined(OS_ANDROID)
return CompositorImpl::CreateSurfaceIdAllocator();
#else
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
@@ -26,7 +168,7 @@ scoped_ptr<cc::SurfaceIdAllocator> CreateSurfaceIdAllocator() {
}
cc::SurfaceManager* GetSurfaceManager() {
-#if defined(OS_ANDROID) && !defined(USE_AURA)
+#if defined(OS_ANDROID)
return CompositorImpl::GetSurfaceManager();
#else
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
@@ -34,4 +176,33 @@ cc::SurfaceManager* GetSurfaceManager() {
#endif
}
+void CopyFromCompositingSurfaceHasResult(
+ const gfx::Size& dst_size_in_pixel,
+ const SkColorType color_type,
+ const ReadbackRequestCallback& callback,
+ scoped_ptr<cc::CopyOutputResult> result) {
+ if (result->IsEmpty() || result->size().IsEmpty()) {
+ callback.Run(SkBitmap(), READBACK_FAILED);
+ return;
+ }
+
+ gfx::Size output_size_in_pixel;
+ if (dst_size_in_pixel.IsEmpty())
+ output_size_in_pixel = result->size();
+ else
+ output_size_in_pixel = dst_size_in_pixel;
+
+ if (result->HasTexture()) {
+ // GPU-accelerated path
+ PrepareTextureCopyOutputResult(output_size_in_pixel, color_type, callback,
+ std::move(result));
+ return;
+ }
+
+ DCHECK(result->HasBitmap());
+ // Software path
+ PrepareBitmapCopyOutputResult(output_size_in_pixel, color_type, callback,
+ std::move(result));
+}
+
} // namespace content
diff --git a/chromium/content/browser/compositor/surface_utils.h b/chromium/content/browser/compositor/surface_utils.h
index b56fef27170..6d986a9c8ca 100644
--- a/chromium/content/browser/compositor/surface_utils.h
+++ b/chromium/content/browser/compositor/surface_utils.h
@@ -6,8 +6,13 @@
#define CONTENT_BROWSER_COMPOSITOR_SURFACE_UTILS_H_
#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/readback_types.h"
+#include "third_party/skia/include/core/SkImageInfo.h"
+#include "ui/gfx/geometry/size.h"
namespace cc {
+class CopyOutputResult;
class SurfaceIdAllocator;
class SurfaceManager;
} // namespace cc
@@ -16,8 +21,15 @@ namespace content {
scoped_ptr<cc::SurfaceIdAllocator> CreateSurfaceIdAllocator();
+CONTENT_EXPORT
cc::SurfaceManager* GetSurfaceManager();
+void CopyFromCompositingSurfaceHasResult(
+ const gfx::Size& dst_size_in_pixel,
+ const SkColorType color_type,
+ const ReadbackRequestCallback& callback,
+ scoped_ptr<cc::CopyOutputResult> result);
+
} // namespace content
#endif // CONTENT_BROWSER_COMPOSITOR_SURFACE_UTILS_H_
diff --git a/chromium/content/browser/cross_site_transfer_browsertest.cc b/chromium/content/browser/cross_site_transfer_browsertest.cc
index fbe720d9e11..1b7c099e455 100644
--- a/chromium/content/browser/cross_site_transfer_browsertest.cc
+++ b/chromium/content/browser/cross_site_transfer_browsertest.cc
@@ -293,7 +293,7 @@ IN_PROC_BROWSER_TEST_F(CrossSiteTransferTest,
// navigation. This test is the same as the test above, except transfering from
// in-process.
IN_PROC_BROWSER_TEST_F(CrossSiteTransferTest,
- ReplaceEntryInProcessThenTranfers) {
+ ReplaceEntryInProcessThenTransfer) {
const NavigationController& controller =
shell()->web_contents()->GetController();
@@ -367,8 +367,8 @@ IN_PROC_BROWSER_TEST_F(CrossSiteTransferTest,
"A.com", "/cross-site/" + url3b.host() + url3b.PathForRequest());
NavigateToURLContentInitiated(shell(), url3a, false, true);
- // There should be two history entries. url2b should have replaced url1. url2b
- // should not have replaced url3b.
+ // There should be two history entries. url2b should have replaced url1. url3b
+ // should not have replaced url2b.
EXPECT_TRUE(controller.GetPendingEntry() == nullptr);
EXPECT_EQ(2, controller.GetEntryCount());
EXPECT_EQ(1, controller.GetCurrentEntryIndex());
diff --git a/chromium/content/browser/database_util_unittest.cc b/chromium/content/browser/database_util_unittest.cc
index 50d68952b4a..9534cb98488 100644
--- a/chromium/content/browser/database_util_unittest.cc
+++ b/chromium/content/browser/database_util_unittest.cc
@@ -29,17 +29,6 @@ static void TestVfsFilePath(bool expected_result,
EXPECT_EQ(ASCIIToUTF16(expected_sqlite_suffix), sqlite_suffix);
}
-static GURL ToAndFromOriginIdentifier(const GURL origin_url) {
- std::string id = storage::GetIdentifierFromOrigin(origin_url);
- return storage::GetOriginFromIdentifier(id);
-}
-
-static void TestValidOriginIdentifier(bool expected_result,
- const std::string& id) {
- EXPECT_EQ(expected_result,
- DatabaseUtil::IsValidOriginIdentifier(id));
-}
-
namespace content {
// Test DatabaseUtil::CrackVfsFilePath on various inputs.
@@ -59,21 +48,5 @@ TEST(DatabaseUtilTest, CrackVfsFilePathTest) {
TestVfsFilePath(false, "/db_name#suffix");
}
-TEST(DatabaseUtilTest, OriginIdentifiers) {
- const GURL kFileOrigin(GURL("file:///").GetOrigin());
- const GURL kHttpOrigin(GURL("http://bar/").GetOrigin());
- EXPECT_EQ(kFileOrigin, ToAndFromOriginIdentifier(kFileOrigin));
- EXPECT_EQ(kHttpOrigin, ToAndFromOriginIdentifier(kHttpOrigin));
-}
-
-TEST(DatabaseUtilTest, IsValidOriginIdentifier) {
- TestValidOriginIdentifier(true, "http_bar_0");
- TestValidOriginIdentifier(false, "");
- TestValidOriginIdentifier(false, "bad..id");
- TestValidOriginIdentifier(false, "bad/id");
- TestValidOriginIdentifier(false, "bad\\id");
- TestValidOriginIdentifier(false, "http_bad:0_2");
- TestValidOriginIdentifier(false, std::string("bad\0id", 6));
-}
} // namespace content
diff --git a/chromium/content/browser/device_monitor_mac.h b/chromium/content/browser/device_monitor_mac.h
deleted file mode 100644
index 05eab158db8..00000000000
--- a/chromium/content/browser/device_monitor_mac.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_DEVICE_MONITOR_MAC_H_
-#define CONTENT_BROWSER_DEVICE_MONITOR_MAC_H_
-
-#include "base/macros.h"
-#include "base/system_monitor/system_monitor.h"
-#include "base/threading/thread_checker.h"
-
-namespace {
-class DeviceMonitorMacImpl;
-}
-
-namespace content {
-
-// Class to track audio/video devices removal or addition via callback to
-// base::SystemMonitor ProcessDevicesChanged(). A single object of this class
-// is created from the browser main process and lives as long as this one.
-class DeviceMonitorMac {
- public:
- DeviceMonitorMac();
- ~DeviceMonitorMac();
-
- // Registers the observers for the audio/video device removal, connection and
- // suspension. The AVFoundation library is also loaded and initialised if the
- // OS supports it. The |device_task_runner| argument represents the thread on
- // which device enumeration will occur.
- void StartMonitoring(
- const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner);
-
- // Method called by the internal DeviceMonitorMacImpl object
- // |device_monitor_impl_| when a device of type |type| has been added to or
- // removed from the system. This code executes in the notification thread
- // (QTKit or AVFoundation).
- void NotifyDeviceChanged(base::SystemMonitor::DeviceType type);
-
- private:
- scoped_ptr<DeviceMonitorMacImpl> device_monitor_impl_;
-
- // |thread_checker_| is used to check that constructor and StartMonitoring()
- // are called in the correct thread, the UI thread, that also owns the object.
- base::ThreadChecker thread_checker_;
-
- DISALLOW_COPY_AND_ASSIGN(DeviceMonitorMac);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_DEVICE_MONITOR_MAC_H_
diff --git a/chromium/content/browser/device_monitor_mac.mm b/chromium/content/browser/device_monitor_mac.mm
deleted file mode 100644
index 248b99dceda..00000000000
--- a/chromium/content/browser/device_monitor_mac.mm
+++ /dev/null
@@ -1,568 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/device_monitor_mac.h"
-
-#import <QTKit/QTKit.h>
-
-#include <set>
-
-#include "base/bind_helpers.h"
-#include "base/logging.h"
-#include "base/mac/bind_objc_block.h"
-#include "base/mac/scoped_nsobject.h"
-#include "base/macros.h"
-#include "base/profiler/scoped_tracker.h"
-#include "base/threading/thread_checker.h"
-#include "content/public/browser/browser_thread.h"
-#import "media/base/mac/avfoundation_glue.h"
-
-using content::BrowserThread;
-
-namespace {
-
-// This class is used to keep track of system devices names and their types.
-class DeviceInfo {
- public:
- enum DeviceType {
- kAudio,
- kVideo,
- kMuxed,
- kUnknown,
- kInvalid
- };
-
- DeviceInfo(const std::string& unique_id, DeviceType type)
- : unique_id_(unique_id), type_(type) {}
-
- // Operator== is needed here to use this class in a std::find. A given
- // |unique_id_| always has the same |type_| so for comparison purposes the
- // latter can be safely ignored.
- bool operator==(const DeviceInfo& device) const {
- return unique_id_ == device.unique_id_;
- }
-
- const std::string& unique_id() const { return unique_id_; }
- DeviceType type() const { return type_; }
-
- private:
- std::string unique_id_;
- DeviceType type_;
- // Allow generated copy constructor and assignment.
-};
-
-// Base abstract class used by DeviceMonitorMac to interact with either a QTKit
-// or an AVFoundation implementation of events and notifications.
-class DeviceMonitorMacImpl {
- public:
- explicit DeviceMonitorMacImpl(content::DeviceMonitorMac* monitor)
- : monitor_(monitor),
- cached_devices_(),
- device_arrival_(nil),
- device_removal_(nil) {
- DCHECK(monitor);
- // Initialise the devices_cache_ with a not-valid entry. For the case in
- // which there is one single device in the system and we get notified when
- // it gets removed, this will prevent the system from thinking that no
- // devices were added nor removed and not notifying the |monitor_|.
- cached_devices_.push_back(DeviceInfo("invalid", DeviceInfo::kInvalid));
- }
- virtual ~DeviceMonitorMacImpl() {}
-
- virtual void OnDeviceChanged() = 0;
-
- // Method called by the default notification center when a device is removed
- // or added to the system. It will compare the |cached_devices_| with the
- // current situation, update it, and, if there's an update, signal to
- // |monitor_| with the appropriate device type.
- void ConsolidateDevicesListAndNotify(
- const std::vector<DeviceInfo>& snapshot_devices);
-
- protected:
- content::DeviceMonitorMac* monitor_;
- std::vector<DeviceInfo> cached_devices_;
-
- // Handles to NSNotificationCenter block observers.
- id device_arrival_;
- id device_removal_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DeviceMonitorMacImpl);
-};
-
-void DeviceMonitorMacImpl::ConsolidateDevicesListAndNotify(
- const std::vector<DeviceInfo>& snapshot_devices) {
- bool video_device_added = false;
- bool audio_device_added = false;
- bool video_device_removed = false;
- bool audio_device_removed = false;
-
- // Compare the current system devices snapshot with the ones cached to detect
- // additions, present in the former but not in the latter. If we find a device
- // in snapshot_devices entry also present in cached_devices, we remove it from
- // the latter vector.
- std::vector<DeviceInfo>::const_iterator it;
- for (it = snapshot_devices.begin(); it != snapshot_devices.end(); ++it) {
- std::vector<DeviceInfo>::iterator cached_devices_iterator =
- std::find(cached_devices_.begin(), cached_devices_.end(), *it);
- if (cached_devices_iterator == cached_devices_.end()) {
- video_device_added |= ((it->type() == DeviceInfo::kVideo) ||
- (it->type() == DeviceInfo::kMuxed));
- audio_device_added |= ((it->type() == DeviceInfo::kAudio) ||
- (it->type() == DeviceInfo::kMuxed));
- DVLOG(1) << "Device has been added, id: " << it->unique_id();
- } else {
- cached_devices_.erase(cached_devices_iterator);
- }
- }
- // All the remaining entries in cached_devices are removed devices.
- for (it = cached_devices_.begin(); it != cached_devices_.end(); ++it) {
- video_device_removed |= ((it->type() == DeviceInfo::kVideo) ||
- (it->type() == DeviceInfo::kMuxed) ||
- (it->type() == DeviceInfo::kInvalid));
- audio_device_removed |= ((it->type() == DeviceInfo::kAudio) ||
- (it->type() == DeviceInfo::kMuxed) ||
- (it->type() == DeviceInfo::kInvalid));
- DVLOG(1) << "Device has been removed, id: " << it->unique_id();
- }
- // Update the cached devices with the current system snapshot.
- cached_devices_ = snapshot_devices;
-
- if (video_device_added || video_device_removed)
- monitor_->NotifyDeviceChanged(base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE);
- if (audio_device_added || audio_device_removed)
- monitor_->NotifyDeviceChanged(base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE);
-}
-
-class QTKitMonitorImpl : public DeviceMonitorMacImpl {
- public:
- explicit QTKitMonitorImpl(content::DeviceMonitorMac* monitor);
- ~QTKitMonitorImpl() override;
-
- void OnDeviceChanged() override;
-
- private:
- void CountDevices();
- void OnAttributeChanged(NSNotification* notification);
-
- id device_change_;
-};
-
-QTKitMonitorImpl::QTKitMonitorImpl(content::DeviceMonitorMac* monitor)
- : DeviceMonitorMacImpl(monitor) {
- NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
- device_arrival_ =
- [nc addObserverForName:QTCaptureDeviceWasConnectedNotification
- object:nil
- queue:nil
- usingBlock:^(NSNotification* notification) {
- OnDeviceChanged();}];
- device_removal_ =
- [nc addObserverForName:QTCaptureDeviceWasDisconnectedNotification
- object:nil
- queue:nil
- usingBlock:^(NSNotification* notification) {
- OnDeviceChanged();}];
- device_change_ =
- [nc addObserverForName:QTCaptureDeviceAttributeDidChangeNotification
- object:nil
- queue:nil
- usingBlock:^(NSNotification* notification) {
- OnAttributeChanged(notification);}];
-}
-
-QTKitMonitorImpl::~QTKitMonitorImpl() {
- NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
- [nc removeObserver:device_arrival_];
- [nc removeObserver:device_removal_];
- [nc removeObserver:device_change_];
-}
-
-void QTKitMonitorImpl::OnAttributeChanged(
- NSNotification* notification) {
- if ([[[notification userInfo]
- objectForKey:QTCaptureDeviceChangedAttributeKey]
- isEqualToString:QTCaptureDeviceSuspendedAttribute]) {
- OnDeviceChanged();
- }
-}
-
-void QTKitMonitorImpl::OnDeviceChanged() {
- std::vector<DeviceInfo> snapshot_devices;
-
- NSArray* devices = [QTCaptureDevice inputDevices];
- for (QTCaptureDevice* device in devices) {
- DeviceInfo::DeviceType device_type = DeviceInfo::kUnknown;
- // Act as if suspended video capture devices are not attached. For
- // example, a laptop's internal webcam is suspended when the lid is closed.
- if ([device hasMediaType:QTMediaTypeVideo] &&
- ![[device attributeForKey:QTCaptureDeviceSuspendedAttribute]
- boolValue]) {
- device_type = DeviceInfo::kVideo;
- } else if ([device hasMediaType:QTMediaTypeMuxed] &&
- ![[device attributeForKey:QTCaptureDeviceSuspendedAttribute]
- boolValue]) {
- device_type = DeviceInfo::kMuxed;
- } else if ([device hasMediaType:QTMediaTypeSound] &&
- ![[device attributeForKey:QTCaptureDeviceSuspendedAttribute]
- boolValue]) {
- device_type = DeviceInfo::kAudio;
- }
- snapshot_devices.push_back(
- DeviceInfo([[device uniqueID] UTF8String], device_type));
- }
- ConsolidateDevicesListAndNotify(snapshot_devices);
-}
-
-// Forward declaration for use by CrAVFoundationDeviceObserver.
-class SuspendObserverDelegate;
-
-} // namespace
-
-// This class is a Key-Value Observer (KVO) shim. It is needed because C++
-// classes cannot observe Key-Values directly. Created, manipulated, and
-// destroyed on the UI Thread by SuspendObserverDelegate.
-@interface CrAVFoundationDeviceObserver : NSObject {
- @private
- // Callback for device changed, has to run on Device Thread.
- base::Closure onDeviceChangedCallback_;
-
- // Member to keep track of the devices we are already monitoring.
- std::set<base::scoped_nsobject<CrAVCaptureDevice> > monitoredDevices_;
-}
-
-- (id)initWithOnChangedCallback:(const base::Closure&)callback;
-- (void)startObserving:(base::scoped_nsobject<CrAVCaptureDevice>)device;
-- (void)stopObserving:(CrAVCaptureDevice*)device;
-- (void)clearOnDeviceChangedCallback;
-
-@end
-
-namespace {
-
-// This class owns and manages the lifetime of a CrAVFoundationDeviceObserver.
-// It is created and destroyed in UI thread by AVFoundationMonitorImpl, and it
-// operates on this thread except for the expensive device enumerations which
-// are run on Device Thread.
-class SuspendObserverDelegate :
- public base::RefCountedThreadSafe<SuspendObserverDelegate> {
- public:
- explicit SuspendObserverDelegate(DeviceMonitorMacImpl* monitor);
-
- // Create |suspend_observer_| for all devices and register OnDeviceChanged()
- // as its change callback. Schedule bottom half in DoStartObserver().
- void StartObserver(
- const scoped_refptr<base::SingleThreadTaskRunner>& device_thread);
- // Enumerate devices in |device_thread| and run the bottom half in
- // DoOnDeviceChange(). |suspend_observer_| calls back here on suspend event,
- // and our parent AVFoundationMonitorImpl calls on connect/disconnect device.
- void OnDeviceChanged(
- const scoped_refptr<base::SingleThreadTaskRunner>& device_thread);
- // Remove the device monitor's weak reference. Remove ourselves as suspend
- // notification observer from |suspend_observer_|.
- void ResetDeviceMonitor();
-
- private:
- friend class base::RefCountedThreadSafe<SuspendObserverDelegate>;
-
- virtual ~SuspendObserverDelegate();
-
- // Bottom half of StartObserver(), starts |suspend_observer_| for all devices.
- // Assumes that |devices| has been retained prior to being called, and
- // releases it internally.
- void DoStartObserver(NSArray* devices);
- // Bottom half of OnDeviceChanged(), starts |suspend_observer_| for current
- // devices and composes a snapshot of them to send it to
- // |avfoundation_monitor_impl_|. Assumes that |devices| has been retained
- // prior to being called, and releases it internally.
- void DoOnDeviceChanged(NSArray* devices);
-
- base::scoped_nsobject<CrAVFoundationDeviceObserver> suspend_observer_;
- DeviceMonitorMacImpl* avfoundation_monitor_impl_;
-};
-
-SuspendObserverDelegate::SuspendObserverDelegate(DeviceMonitorMacImpl* monitor)
- : avfoundation_monitor_impl_(monitor) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-}
-
-void SuspendObserverDelegate::StartObserver(
- const scoped_refptr<base::SingleThreadTaskRunner>& device_thread) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- base::Closure on_device_changed_callback =
- base::Bind(&SuspendObserverDelegate::OnDeviceChanged,
- this, device_thread);
- suspend_observer_.reset([[CrAVFoundationDeviceObserver alloc]
- initWithOnChangedCallback:on_device_changed_callback]);
-
- // Enumerate the devices in Device thread and post the observers start to be
- // done on UI thread. The devices array is retained in |device_thread| and
- // released in DoStartObserver().
- base::PostTaskAndReplyWithResult(
- device_thread.get(),
- FROM_HERE,
- base::BindBlock(^{ return [[AVCaptureDeviceGlue devices] retain]; }),
- base::Bind(&SuspendObserverDelegate::DoStartObserver, this));
-}
-
-void SuspendObserverDelegate::OnDeviceChanged(
- const scoped_refptr<base::SingleThreadTaskRunner>& device_thread) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- // Enumerate the devices in Device thread and post the consolidation of the
- // new devices and the old ones to be done on UI thread. The devices array
- // is retained in |device_thread| and released in DoOnDeviceChanged().
- PostTaskAndReplyWithResult(
- device_thread.get(),
- FROM_HERE,
- base::BindBlock(^{ return [[AVCaptureDeviceGlue devices] retain]; }),
- base::Bind(&SuspendObserverDelegate::DoOnDeviceChanged, this));
-}
-
-void SuspendObserverDelegate::ResetDeviceMonitor() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- avfoundation_monitor_impl_ = NULL;
- [suspend_observer_ clearOnDeviceChangedCallback];
-}
-
-SuspendObserverDelegate::~SuspendObserverDelegate() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-}
-
-void SuspendObserverDelegate::DoStartObserver(NSArray* devices) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- base::scoped_nsobject<NSArray> auto_release(devices);
- for (CrAVCaptureDevice* device in devices) {
- base::scoped_nsobject<CrAVCaptureDevice> device_ptr([device retain]);
- [suspend_observer_ startObserving:device_ptr];
- }
-}
-
-void SuspendObserverDelegate::DoOnDeviceChanged(NSArray* devices) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- base::scoped_nsobject<NSArray> auto_release(devices);
- std::vector<DeviceInfo> snapshot_devices;
- for (CrAVCaptureDevice* device in devices) {
- base::scoped_nsobject<CrAVCaptureDevice> device_ptr([device retain]);
- [suspend_observer_ startObserving:device_ptr];
-
- BOOL suspended = [device respondsToSelector:@selector(isSuspended)] &&
- [device isSuspended];
- DeviceInfo::DeviceType device_type = DeviceInfo::kUnknown;
- if ([device hasMediaType:AVFoundationGlue::AVMediaTypeVideo()]) {
- if (suspended)
- continue;
- device_type = DeviceInfo::kVideo;
- } else if ([device hasMediaType:AVFoundationGlue::AVMediaTypeMuxed()]) {
- device_type = suspended ? DeviceInfo::kAudio : DeviceInfo::kMuxed;
- } else if ([device hasMediaType:AVFoundationGlue::AVMediaTypeAudio()]) {
- device_type = DeviceInfo::kAudio;
- }
- snapshot_devices.push_back(DeviceInfo([[device uniqueID] UTF8String],
- device_type));
- }
- // Make sure no references are held to |devices| when
- // ConsolidateDevicesListAndNotify is called since the VideoCaptureManager
- // and AudioCaptureManagers also enumerates the available devices but on
- // another thread.
- auto_release.reset();
- // |avfoundation_monitor_impl_| might have been NULLed asynchronously before
- // arriving at this line.
- if (avfoundation_monitor_impl_) {
- avfoundation_monitor_impl_->ConsolidateDevicesListAndNotify(
- snapshot_devices);
- }
-}
-
-// AVFoundation implementation of the Mac Device Monitor, registers as a global
-// device connect/disconnect observer and plugs suspend/wake up device observers
-// per device. This class is created and lives in UI thread. Owns a
-// SuspendObserverDelegate that notifies when a device is suspended/resumed.
-class AVFoundationMonitorImpl : public DeviceMonitorMacImpl {
- public:
- AVFoundationMonitorImpl(
- content::DeviceMonitorMac* monitor,
- const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner);
- ~AVFoundationMonitorImpl() override;
-
- void OnDeviceChanged() override;
-
- private:
- // {Video,AudioInput}DeviceManager's "Device" thread task runner used for
- // posting tasks to |suspend_observer_delegate_|; valid after
- // MediaStreamManager calls StartMonitoring().
- const scoped_refptr<base::SingleThreadTaskRunner> device_task_runner_;
-
- scoped_refptr<SuspendObserverDelegate> suspend_observer_delegate_;
-
- DISALLOW_COPY_AND_ASSIGN(AVFoundationMonitorImpl);
-};
-
-AVFoundationMonitorImpl::AVFoundationMonitorImpl(
- content::DeviceMonitorMac* monitor,
- const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner)
- : DeviceMonitorMacImpl(monitor),
- device_task_runner_(device_task_runner),
- suspend_observer_delegate_(new SuspendObserverDelegate(this)) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
- device_arrival_ =
- [nc addObserverForName:AVFoundationGlue::
- AVCaptureDeviceWasConnectedNotification()
- object:nil
- queue:nil
- usingBlock:^(NSNotification* notification) {
- OnDeviceChanged();}];
- device_removal_ =
- [nc addObserverForName:AVFoundationGlue::
- AVCaptureDeviceWasDisconnectedNotification()
- object:nil
- queue:nil
- usingBlock:^(NSNotification* notification) {
- OnDeviceChanged();}];
- suspend_observer_delegate_->StartObserver(device_task_runner_);
-}
-
-AVFoundationMonitorImpl::~AVFoundationMonitorImpl() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- suspend_observer_delegate_->ResetDeviceMonitor();
- NSNotificationCenter* nc = [NSNotificationCenter defaultCenter];
- [nc removeObserver:device_arrival_];
- [nc removeObserver:device_removal_];
-}
-
-void AVFoundationMonitorImpl::OnDeviceChanged() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- suspend_observer_delegate_->OnDeviceChanged(device_task_runner_);
-}
-
-} // namespace
-
-@implementation CrAVFoundationDeviceObserver
-
-- (id)initWithOnChangedCallback:(const base::Closure&)callback {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if ((self = [super init])) {
- DCHECK(!callback.is_null());
- onDeviceChangedCallback_ = callback;
- }
- return self;
-}
-
-- (void)dealloc {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- std::set<base::scoped_nsobject<CrAVCaptureDevice> >::iterator it =
- monitoredDevices_.begin();
- while (it != monitoredDevices_.end())
- [self removeObservers:*(it++)];
- [super dealloc];
-}
-
-- (void)startObserving:(base::scoped_nsobject<CrAVCaptureDevice>)device {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(device != nil);
- // Skip this device if there are already observers connected to it.
- if (std::find(monitoredDevices_.begin(), monitoredDevices_.end(), device) !=
- monitoredDevices_.end()) {
- return;
- }
- [device addObserver:self
- forKeyPath:@"suspended"
- options:0
- context:device.get()];
- [device addObserver:self
- forKeyPath:@"connected"
- options:0
- context:device.get()];
- monitoredDevices_.insert(device);
-}
-
-- (void)stopObserving:(CrAVCaptureDevice*)device {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(device != nil);
-
- std::set<base::scoped_nsobject<CrAVCaptureDevice> >::iterator found =
- std::find(monitoredDevices_.begin(), monitoredDevices_.end(), device);
- DCHECK(found != monitoredDevices_.end());
- [self removeObservers:*found];
- monitoredDevices_.erase(found);
-}
-
-- (void)clearOnDeviceChangedCallback {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- onDeviceChangedCallback_.Reset();
-}
-
-- (void)removeObservers:(CrAVCaptureDevice*)device {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- // Check sanity of |device| via its -observationInfo. http://crbug.com/371271.
- if ([device observationInfo]) {
- [device removeObserver:self
- forKeyPath:@"suspended"];
- [device removeObserver:self
- forKeyPath:@"connected"];
- }
-}
-
-- (void)observeValueForKeyPath:(NSString*)keyPath
- ofObject:(id)object
- change:(NSDictionary*)change
- context:(void*)context {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if ([keyPath isEqual:@"suspended"])
- onDeviceChangedCallback_.Run();
- if ([keyPath isEqual:@"connected"])
- [self stopObserving:static_cast<CrAVCaptureDevice*>(context)];
-}
-
-@end // @implementation CrAVFoundationDeviceObserver
-
-namespace content {
-
-DeviceMonitorMac::DeviceMonitorMac() {
- // Both QTKit and AVFoundation do not need to be fired up until the user
- // exercises a GetUserMedia. Bringing up either library and enumerating the
- // devices in the system is an operation taking in the range of hundred of ms,
- // so it is triggered explicitly from MediaStreamManager::StartMonitoring().
-}
-
-DeviceMonitorMac::~DeviceMonitorMac() {}
-
-void DeviceMonitorMac::StartMonitoring(
- const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- // We're on the UI thread so let's try to initialize AVFoundation and then
- // see if it's supported. IsAVFoundationSupported can't implicitly initialize
- // the library since it can be called on different threads.
- AVFoundationGlue::InitializeAVFoundation();
-
- if (AVFoundationGlue::IsAVFoundationSupported()) {
- // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/458404
- // is fixed.
- tracked_objects::ScopedTracker tracking_profile(
- FROM_HERE_WITH_EXPLICIT_FUNCTION(
- "458404 DeviceMonitorMac::StartMonitoring::AVFoundation"));
- DVLOG(1) << "Monitoring via AVFoundation";
- device_monitor_impl_.reset(new AVFoundationMonitorImpl(this,
- device_task_runner));
- } else {
- // TODO(erikchen): Remove ScopedTracker below once http://crbug.com/458404
- // is fixed.
- tracked_objects::ScopedTracker tracking_profile(
- FROM_HERE_WITH_EXPLICIT_FUNCTION(
- "458404 DeviceMonitorMac::StartMonitoring::QTKit"));
- DVLOG(1) << "Monitoring via QTKit";
- device_monitor_impl_.reset(new QTKitMonitorImpl(this));
- }
-}
-
-void DeviceMonitorMac::NotifyDeviceChanged(
- base::SystemMonitor::DeviceType type) {
- DCHECK(thread_checker_.CalledOnValidThread());
- // TODO(xians): Remove the global variable for SystemMonitor.
- base::SystemMonitor::Get()->ProcessDevicesChanged(type);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/device_monitor_udev.cc b/chromium/content/browser/device_monitor_udev.cc
deleted file mode 100644
index 822e995f47c..00000000000
--- a/chromium/content/browser/device_monitor_udev.cc
+++ /dev/null
@@ -1,89 +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.
-
-// libudev is used for monitoring device changes.
-
-#include "content/browser/device_monitor_udev.h"
-
-#include <stddef.h>
-
-#include <string>
-
-#include "base/macros.h"
-#include "base/system_monitor/system_monitor.h"
-#include "content/browser/udev_linux.h"
-#include "content/public/browser/browser_thread.h"
-#include "device/udev_linux/udev.h"
-
-namespace {
-
-struct SubsystemMap {
- base::SystemMonitor::DeviceType device_type;
- const char* subsystem;
- const char* devtype;
-};
-
-const char kAudioSubsystem[] = "sound";
-const char kVideoSubsystem[] = "video4linux";
-
-// Add more subsystems here for monitoring.
-const SubsystemMap kSubsystemMap[] = {
- { base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE, kAudioSubsystem, NULL },
- { base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE, kVideoSubsystem, NULL },
-};
-
-} // namespace
-
-namespace content {
-
-DeviceMonitorLinux::DeviceMonitorLinux() {
- DCHECK(BrowserThread::IsMessageLoopValid(BrowserThread::IO));
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(&DeviceMonitorLinux::Initialize, base::Unretained(this)));
-}
-
-DeviceMonitorLinux::~DeviceMonitorLinux() {
-}
-
-void DeviceMonitorLinux::Initialize() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // We want to be notified of IO message loop destruction to delete |udev_|.
- base::MessageLoop::current()->AddDestructionObserver(this);
-
- std::vector<UdevLinux::UdevMonitorFilter> filters;
- for (size_t i = 0; i < arraysize(kSubsystemMap); ++i) {
- filters.push_back(UdevLinux::UdevMonitorFilter(
- kSubsystemMap[i].subsystem, kSubsystemMap[i].devtype));
- }
- udev_.reset(new UdevLinux(filters,
- base::Bind(&DeviceMonitorLinux::OnDevicesChanged,
- base::Unretained(this))));
-}
-
-void DeviceMonitorLinux::WillDestroyCurrentMessageLoop() {
- // Called on IO thread.
- udev_.reset();
-}
-
-void DeviceMonitorLinux::OnDevicesChanged(udev_device* device) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(device);
-
- base::SystemMonitor::DeviceType device_type =
- base::SystemMonitor::DEVTYPE_UNKNOWN;
- std::string subsystem(device::udev_device_get_subsystem(device));
- for (size_t i = 0; i < arraysize(kSubsystemMap); ++i) {
- if (subsystem == kSubsystemMap[i].subsystem) {
- device_type = kSubsystemMap[i].device_type;
- break;
- }
- }
- DCHECK_NE(device_type, base::SystemMonitor::DEVTYPE_UNKNOWN);
-
- base::SystemMonitor::Get()->ProcessDevicesChanged(device_type);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/device_monitor_udev.h b/chromium/content/browser/device_monitor_udev.h
deleted file mode 100644
index 965055d93b2..00000000000
--- a/chromium/content/browser/device_monitor_udev.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This class is used to detect device change and notify base::SystemMonitor
-// on Linux.
-
-#ifndef CONTENT_BROWSER_DEVICE_MONITOR_UDEV_H_
-#define CONTENT_BROWSER_DEVICE_MONITOR_UDEV_H_
-
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-
-extern "C" {
-struct udev_device;
-}
-
-namespace content {
-
-class UdevLinux;
-
-class DeviceMonitorLinux : public base::MessageLoop::DestructionObserver {
- public:
- DeviceMonitorLinux();
- ~DeviceMonitorLinux() override;
-
- private:
- // This object is deleted on the UI thread after the IO thread has been
- // destroyed. Need to know when IO thread is being destroyed so that
- // we can delete udev_.
- void WillDestroyCurrentMessageLoop() override;
-
- void Initialize();
- void OnDevicesChanged(udev_device* device);
-
- scoped_ptr<UdevLinux> udev_;
-
- DISALLOW_COPY_AND_ASSIGN(DeviceMonitorLinux);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_DEVICE_MONITOR_UDEV_H_
diff --git a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_mac.cc b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_mac.cc
index a9ab2ff1dc2..c8b37986c7d 100644
--- a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_mac.cc
+++ b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_mac.cc
@@ -194,7 +194,6 @@ bool DataFetcherSharedMemory::Start(ConsumerType consumer_type, void* buffer) {
// On Mac we cannot provide absolute orientation.
orientation_buffer_->seqlock.WriteBegin();
orientation_buffer_->data.absolute = false;
- orientation_buffer_->data.hasAbsolute = true;
orientation_buffer_->seqlock.WriteEnd();
} else {
// No motion sensor available, fire an all-null event.
diff --git a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_win.cc b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_win.cc
index 709c25b595c..40471ca0a3b 100644
--- a/chromium/content/browser/device_sensors/data_fetcher_shared_memory_win.cc
+++ b/chromium/content/browser/device_sensors/data_fetcher_shared_memory_win.cc
@@ -129,8 +129,7 @@ class DataFetcherSharedMemory::SensorEventSinkOrientation
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.absolute = has_alpha || has_beta || has_gamma;
buffer_->data.allAvailableSensorsAreActive = true;
buffer_->seqlock.WriteEnd();
}
diff --git a/chromium/content/browser/device_sensors/device_light_message_filter.cc b/chromium/content/browser/device_sensors/device_light_message_filter.cc
index 797b3eade2c..dda05a86aa8 100644
--- a/chromium/content/browser/device_sensors/device_light_message_filter.cc
+++ b/chromium/content/browser/device_sensors/device_light_message_filter.cc
@@ -4,57 +4,28 @@
#include "content/browser/device_sensors/device_light_message_filter.h"
-#include "content/browser/device_sensors/device_inertial_sensor_service.h"
#include "content/common/device_sensors/device_light_messages.h"
namespace content {
DeviceLightMessageFilter::DeviceLightMessageFilter()
- : BrowserMessageFilter(DeviceLightMsgStart), is_started_(false) {
-}
+ : DeviceSensorMessageFilter(CONSUMER_TYPE_LIGHT, DeviceLightMsgStart) {}
-DeviceLightMessageFilter::~DeviceLightMessageFilter() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (is_started_) {
- DeviceInertialSensorService::GetInstance()->RemoveConsumer(
- CONSUMER_TYPE_LIGHT);
- }
-}
+DeviceLightMessageFilter::~DeviceLightMessageFilter() {}
bool DeviceLightMessageFilter::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(DeviceLightMessageFilter, message)
- IPC_MESSAGE_HANDLER(DeviceLightHostMsg_StartPolling,
- OnDeviceLightStartPolling)
- IPC_MESSAGE_HANDLER(DeviceLightHostMsg_StopPolling, OnDeviceLightStopPolling)
+ IPC_MESSAGE_HANDLER(DeviceLightHostMsg_StartPolling, OnStartPolling)
+ IPC_MESSAGE_HANDLER(DeviceLightHostMsg_StopPolling, OnStopPolling)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
-void DeviceLightMessageFilter::OnDeviceLightStartPolling() {
- DCHECK(!is_started_);
- if (is_started_)
- return;
- is_started_ = true;
- DeviceInertialSensorService::GetInstance()->AddConsumer(CONSUMER_TYPE_LIGHT);
- DidStartDeviceLightPolling();
-}
-
-void DeviceLightMessageFilter::OnDeviceLightStopPolling() {
- DCHECK(is_started_);
- if (!is_started_)
- return;
- is_started_ = false;
- DeviceInertialSensorService::GetInstance()->RemoveConsumer(
- CONSUMER_TYPE_LIGHT);
-}
-
-void DeviceLightMessageFilter::DidStartDeviceLightPolling() {
- Send(new DeviceLightMsg_DidStartPolling(
- DeviceInertialSensorService::GetInstance()
- ->GetSharedMemoryHandleForProcess(CONSUMER_TYPE_LIGHT,
- PeerHandle())));
+void DeviceLightMessageFilter::DidStartPolling(
+ base::SharedMemoryHandle handle) {
+ Send(new DeviceLightMsg_DidStartPolling(handle));
}
} // namespace content
diff --git a/chromium/content/browser/device_sensors/device_light_message_filter.h b/chromium/content/browser/device_sensors/device_light_message_filter.h
index 58246935a7e..bf302b7dd5a 100644
--- a/chromium/content/browser/device_sensors/device_light_message_filter.h
+++ b/chromium/content/browser/device_sensors/device_light_message_filter.h
@@ -5,12 +5,11 @@
#ifndef CONTENT_BROWSER_DEVICE_SENSORS_DEVICE_LIGHT_MESSAGE_FILTER_H_
#define CONTENT_BROWSER_DEVICE_SENSORS_DEVICE_LIGHT_MESSAGE_FILTER_H_
-#include "base/macros.h"
-#include "content/public/browser/browser_message_filter.h"
+#include "content/browser/device_sensors/device_sensor_message_filter.h"
namespace content {
-class DeviceLightMessageFilter : public BrowserMessageFilter {
+class DeviceLightMessageFilter : public DeviceSensorMessageFilter {
public:
DeviceLightMessageFilter();
@@ -20,11 +19,8 @@ class DeviceLightMessageFilter : public BrowserMessageFilter {
private:
~DeviceLightMessageFilter() override;
- void OnDeviceLightStartPolling();
- void OnDeviceLightStopPolling();
- void DidStartDeviceLightPolling();
-
- bool is_started_;
+ // DeviceSensorMessageFilter implementation.
+ void DidStartPolling(base::SharedMemoryHandle handle) override;
DISALLOW_COPY_AND_ASSIGN(DeviceLightMessageFilter);
};
diff --git a/chromium/content/browser/device_sensors/device_motion_message_filter.cc b/chromium/content/browser/device_sensors/device_motion_message_filter.cc
index f874ea493a4..58a2b514b5b 100644
--- a/chromium/content/browser/device_sensors/device_motion_message_filter.cc
+++ b/chromium/content/browser/device_sensors/device_motion_message_filter.cc
@@ -4,59 +4,28 @@
#include "content/browser/device_sensors/device_motion_message_filter.h"
-#include "content/browser/device_sensors/device_inertial_sensor_service.h"
#include "content/common/device_sensors/device_motion_messages.h"
namespace content {
DeviceMotionMessageFilter::DeviceMotionMessageFilter()
- : BrowserMessageFilter(DeviceMotionMsgStart),
- is_started_(false) {
-}
+ : DeviceSensorMessageFilter(CONSUMER_TYPE_MOTION, DeviceMotionMsgStart) {}
-DeviceMotionMessageFilter::~DeviceMotionMessageFilter() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (is_started_)
- DeviceInertialSensorService::GetInstance()->RemoveConsumer(
- CONSUMER_TYPE_MOTION);
-}
+DeviceMotionMessageFilter::~DeviceMotionMessageFilter() {}
bool DeviceMotionMessageFilter::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(DeviceMotionMessageFilter, message)
- IPC_MESSAGE_HANDLER(DeviceMotionHostMsg_StartPolling,
- OnDeviceMotionStartPolling)
- IPC_MESSAGE_HANDLER(DeviceMotionHostMsg_StopPolling,
- OnDeviceMotionStopPolling)
+ IPC_MESSAGE_HANDLER(DeviceMotionHostMsg_StartPolling, OnStartPolling)
+ IPC_MESSAGE_HANDLER(DeviceMotionHostMsg_StopPolling, OnStopPolling)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
-void DeviceMotionMessageFilter::OnDeviceMotionStartPolling() {
- DCHECK(!is_started_);
- if (is_started_)
- return;
- is_started_ = true;
- DeviceInertialSensorService::GetInstance()->AddConsumer(
- CONSUMER_TYPE_MOTION);
- DidStartDeviceMotionPolling();
-}
-
-void DeviceMotionMessageFilter::OnDeviceMotionStopPolling() {
- DCHECK(is_started_);
- if (!is_started_)
- return;
- is_started_ = false;
- DeviceInertialSensorService::GetInstance()->RemoveConsumer(
- CONSUMER_TYPE_MOTION);
-}
-
-void DeviceMotionMessageFilter::DidStartDeviceMotionPolling() {
- Send(new DeviceMotionMsg_DidStartPolling(
- DeviceInertialSensorService::GetInstance()->
- GetSharedMemoryHandleForProcess(
- CONSUMER_TYPE_MOTION, PeerHandle())));
+void DeviceMotionMessageFilter::DidStartPolling(
+ base::SharedMemoryHandle handle) {
+ Send(new DeviceMotionMsg_DidStartPolling(handle));
}
} // namespace content
diff --git a/chromium/content/browser/device_sensors/device_motion_message_filter.h b/chromium/content/browser/device_sensors/device_motion_message_filter.h
index 36eb42aa127..3b0587d15da 100644
--- a/chromium/content/browser/device_sensors/device_motion_message_filter.h
+++ b/chromium/content/browser/device_sensors/device_motion_message_filter.h
@@ -5,12 +5,11 @@
#ifndef CONTENT_BROWSER_DEVICE_SENSORS_DEVICE_MOTION_MESSAGE_FILTER_H_
#define CONTENT_BROWSER_DEVICE_SENSORS_DEVICE_MOTION_MESSAGE_FILTER_H_
-#include "base/macros.h"
-#include "content/public/browser/browser_message_filter.h"
+#include "content/browser/device_sensors/device_sensor_message_filter.h"
namespace content {
-class DeviceMotionMessageFilter : public BrowserMessageFilter {
+class DeviceMotionMessageFilter : public DeviceSensorMessageFilter {
public:
DeviceMotionMessageFilter();
@@ -20,11 +19,8 @@ class DeviceMotionMessageFilter : public BrowserMessageFilter {
private:
~DeviceMotionMessageFilter() override;
- void OnDeviceMotionStartPolling();
- void OnDeviceMotionStopPolling();
- void DidStartDeviceMotionPolling();
-
- bool is_started_;
+ // DeviceSensorMessageFilter implementation.
+ void DidStartPolling(base::SharedMemoryHandle handle) override;
DISALLOW_COPY_AND_ASSIGN(DeviceMotionMessageFilter);
};
diff --git a/chromium/content/browser/device_sensors/device_orientation_absolute_message_filter.cc b/chromium/content/browser/device_sensors/device_orientation_absolute_message_filter.cc
index 572952cea11..3aa6042e429 100644
--- a/chromium/content/browser/device_sensors/device_orientation_absolute_message_filter.cc
+++ b/chromium/content/browser/device_sensors/device_orientation_absolute_message_filter.cc
@@ -4,24 +4,16 @@
#include "content/browser/device_sensors/device_orientation_absolute_message_filter.h"
-#include "content/browser/device_sensors/device_inertial_sensor_service.h"
#include "content/common/device_sensors/device_orientation_messages.h"
namespace content {
DeviceOrientationAbsoluteMessageFilter::DeviceOrientationAbsoluteMessageFilter()
- : BrowserMessageFilter(DeviceOrientationMsgStart),
- is_started_(false) {
-}
+ : DeviceSensorMessageFilter(CONSUMER_TYPE_ORIENTATION_ABSOLUTE,
+ DeviceOrientationMsgStart) {}
DeviceOrientationAbsoluteMessageFilter::
- ~DeviceOrientationAbsoluteMessageFilter() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (is_started_) {
- DeviceInertialSensorService::GetInstance()->RemoveConsumer(
- CONSUMER_TYPE_ORIENTATION_ABSOLUTE);
- }
-}
+ ~DeviceOrientationAbsoluteMessageFilter() {}
bool DeviceOrientationAbsoluteMessageFilter::OnMessageReceived(
const IPC::Message& message) {
@@ -36,31 +28,9 @@ bool DeviceOrientationAbsoluteMessageFilter::OnMessageReceived(
return handled;
}
-void DeviceOrientationAbsoluteMessageFilter::OnStartPolling() {
- DCHECK(!is_started_);
- if (is_started_)
- return;
- is_started_ = true;
- DeviceInertialSensorService::GetInstance()->AddConsumer(
- CONSUMER_TYPE_ORIENTATION_ABSOLUTE);
- DidStartPolling();
-}
-
-void DeviceOrientationAbsoluteMessageFilter::OnStopPolling() {
- DCHECK(is_started_);
- if (!is_started_)
- return;
- is_started_ = false;
- DeviceInertialSensorService::GetInstance()->RemoveConsumer(
- CONSUMER_TYPE_ORIENTATION_ABSOLUTE);
-}
-
-void DeviceOrientationAbsoluteMessageFilter::DidStartPolling() {
- Send(new DeviceOrientationAbsoluteMsg_DidStartPolling(
- DeviceInertialSensorService::GetInstance()->
- GetSharedMemoryHandleForProcess(
- CONSUMER_TYPE_ORIENTATION_ABSOLUTE,
- PeerHandle())));
+void DeviceOrientationAbsoluteMessageFilter::DidStartPolling(
+ base::SharedMemoryHandle handle) {
+ Send(new DeviceOrientationAbsoluteMsg_DidStartPolling(handle));
}
} // namespace content
diff --git a/chromium/content/browser/device_sensors/device_orientation_absolute_message_filter.h b/chromium/content/browser/device_sensors/device_orientation_absolute_message_filter.h
index 5ed5ac5467e..5e64bf8fe73 100644
--- a/chromium/content/browser/device_sensors/device_orientation_absolute_message_filter.h
+++ b/chromium/content/browser/device_sensors/device_orientation_absolute_message_filter.h
@@ -5,12 +5,12 @@
#ifndef CONTENT_BROWSER_DEVICE_SENSORS_DEVICE_ORIENTATION_ABSOLUTE_MESSAGE_FILTER_H_
#define CONTENT_BROWSER_DEVICE_SENSORS_DEVICE_ORIENTATION_ABSOLUTE_MESSAGE_FILTER_H_
-#include "base/macros.h"
-#include "content/public/browser/browser_message_filter.h"
+#include "content/browser/device_sensors/device_sensor_message_filter.h"
namespace content {
-class DeviceOrientationAbsoluteMessageFilter : public BrowserMessageFilter {
+class DeviceOrientationAbsoluteMessageFilter
+ : public DeviceSensorMessageFilter {
public:
DeviceOrientationAbsoluteMessageFilter();
@@ -20,11 +20,8 @@ class DeviceOrientationAbsoluteMessageFilter : public BrowserMessageFilter {
private:
~DeviceOrientationAbsoluteMessageFilter() override;
- void OnStartPolling();
- void OnStopPolling();
- void DidStartPolling();
-
- bool is_started_;
+ // DeviceSensorMessageFilter implementation.
+ void DidStartPolling(base::SharedMemoryHandle handle) override;
DISALLOW_COPY_AND_ASSIGN(DeviceOrientationAbsoluteMessageFilter);
};
diff --git a/chromium/content/browser/device_sensors/device_orientation_message_filter.cc b/chromium/content/browser/device_sensors/device_orientation_message_filter.cc
index 63a9d6230f4..9b0aeb8b13a 100644
--- a/chromium/content/browser/device_sensors/device_orientation_message_filter.cc
+++ b/chromium/content/browser/device_sensors/device_orientation_message_filter.cc
@@ -4,61 +4,30 @@
#include "content/browser/device_sensors/device_orientation_message_filter.h"
-#include "content/browser/device_sensors/device_inertial_sensor_service.h"
#include "content/common/device_sensors/device_orientation_messages.h"
namespace content {
DeviceOrientationMessageFilter::DeviceOrientationMessageFilter()
- : BrowserMessageFilter(DeviceOrientationMsgStart),
- is_started_(false) {
-}
+ : DeviceSensorMessageFilter(CONSUMER_TYPE_ORIENTATION,
+ DeviceOrientationMsgStart) {}
-DeviceOrientationMessageFilter::~DeviceOrientationMessageFilter() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (is_started_)
- DeviceInertialSensorService::GetInstance()->RemoveConsumer(
- CONSUMER_TYPE_ORIENTATION);
-}
+DeviceOrientationMessageFilter::~DeviceOrientationMessageFilter() {}
bool DeviceOrientationMessageFilter::OnMessageReceived(
const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(DeviceOrientationMessageFilter, message)
- IPC_MESSAGE_HANDLER(DeviceOrientationHostMsg_StartPolling,
- OnDeviceOrientationStartPolling)
- IPC_MESSAGE_HANDLER(DeviceOrientationHostMsg_StopPolling,
- OnDeviceOrientationStopPolling)
+ IPC_MESSAGE_HANDLER(DeviceOrientationHostMsg_StartPolling, OnStartPolling)
+ IPC_MESSAGE_HANDLER(DeviceOrientationHostMsg_StopPolling, OnStopPolling)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
-void DeviceOrientationMessageFilter::OnDeviceOrientationStartPolling() {
- DCHECK(!is_started_);
- if (is_started_)
- return;
- is_started_ = true;
- DeviceInertialSensorService::GetInstance()->AddConsumer(
- CONSUMER_TYPE_ORIENTATION);
- DidStartDeviceOrientationPolling();
-}
-
-void DeviceOrientationMessageFilter::OnDeviceOrientationStopPolling() {
- DCHECK(is_started_);
- if (!is_started_)
- return;
- is_started_ = false;
- DeviceInertialSensorService::GetInstance()->RemoveConsumer(
- CONSUMER_TYPE_ORIENTATION);
-}
-
-void DeviceOrientationMessageFilter::DidStartDeviceOrientationPolling() {
- Send(new DeviceOrientationMsg_DidStartPolling(
- DeviceInertialSensorService::GetInstance()->
- GetSharedMemoryHandleForProcess(
- CONSUMER_TYPE_ORIENTATION,
- PeerHandle())));
+void DeviceOrientationMessageFilter::DidStartPolling(
+ base::SharedMemoryHandle handle) {
+ Send(new DeviceOrientationMsg_DidStartPolling(handle));
}
} // namespace content
diff --git a/chromium/content/browser/device_sensors/device_orientation_message_filter.h b/chromium/content/browser/device_sensors/device_orientation_message_filter.h
index fb375d99439..21e445347a7 100644
--- a/chromium/content/browser/device_sensors/device_orientation_message_filter.h
+++ b/chromium/content/browser/device_sensors/device_orientation_message_filter.h
@@ -5,12 +5,11 @@
#ifndef CONTENT_BROWSER_DEVICE_SENSORS_DEVICE_ORIENTATION_MESSAGE_FILTER_H_
#define CONTENT_BROWSER_DEVICE_SENSORS_DEVICE_ORIENTATION_MESSAGE_FILTER_H_
-#include "base/macros.h"
-#include "content/public/browser/browser_message_filter.h"
+#include "content/browser/device_sensors/device_sensor_message_filter.h"
namespace content {
-class DeviceOrientationMessageFilter : public BrowserMessageFilter {
+class DeviceOrientationMessageFilter : public DeviceSensorMessageFilter {
public:
DeviceOrientationMessageFilter();
@@ -20,11 +19,8 @@ class DeviceOrientationMessageFilter : public BrowserMessageFilter {
private:
~DeviceOrientationMessageFilter() override;
- void OnDeviceOrientationStartPolling();
- void OnDeviceOrientationStopPolling();
- void DidStartDeviceOrientationPolling();
-
- bool is_started_;
+ // DeviceSensorMessageFilter implementation.
+ void DidStartPolling(base::SharedMemoryHandle handle) override;
DISALLOW_COPY_AND_ASSIGN(DeviceOrientationMessageFilter);
};
diff --git a/chromium/content/browser/device_sensors/device_sensor_message_filter.cc b/chromium/content/browser/device_sensors/device_sensor_message_filter.cc
new file mode 100644
index 00000000000..cb9e9e592a4
--- /dev/null
+++ b/chromium/content/browser/device_sensors/device_sensor_message_filter.cc
@@ -0,0 +1,44 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/device_sensors/device_sensor_message_filter.h"
+
+#include "content/browser/device_sensors/device_inertial_sensor_service.h"
+
+namespace content {
+
+DeviceSensorMessageFilter::DeviceSensorMessageFilter(
+ ConsumerType consumer_type, uint32_t message_class_to_filter)
+ : BrowserMessageFilter(message_class_to_filter),
+ consumer_type_(consumer_type),
+ is_started_(false) {
+}
+
+DeviceSensorMessageFilter::~DeviceSensorMessageFilter() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (is_started_)
+ DeviceInertialSensorService::GetInstance()->RemoveConsumer(consumer_type_);
+}
+
+void DeviceSensorMessageFilter::OnStartPolling() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(!is_started_);
+ if (is_started_)
+ return;
+ is_started_ = true;
+ DeviceInertialSensorService::GetInstance()->AddConsumer(consumer_type_);
+ DidStartPolling(DeviceInertialSensorService::GetInstance()->
+ GetSharedMemoryHandleForProcess(consumer_type_, PeerHandle()));
+}
+
+void DeviceSensorMessageFilter::OnStopPolling() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(is_started_);
+ if (!is_started_)
+ return;
+ is_started_ = false;
+ DeviceInertialSensorService::GetInstance()->RemoveConsumer(consumer_type_);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/device_sensors/device_sensor_message_filter.h b/chromium/content/browser/device_sensors/device_sensor_message_filter.h
new file mode 100644
index 00000000000..13d0b0ac3ea
--- /dev/null
+++ b/chromium/content/browser/device_sensors/device_sensor_message_filter.h
@@ -0,0 +1,40 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_DEVICE_SENSORS_DEVICE_SENSOR_MESSAGE_FILTER_H_
+#define CONTENT_BROWSER_DEVICE_SENSORS_DEVICE_SENSOR_MESSAGE_FILTER_H_
+
+#include "base/macros.h"
+#include "base/memory/shared_memory.h"
+#include "content/browser/device_sensors/device_sensors_consts.h"
+#include "content/public/browser/browser_message_filter.h"
+
+namespace content {
+
+// A base class for device sensor related message filters.
+class DeviceSensorMessageFilter : public BrowserMessageFilter {
+ public:
+ DeviceSensorMessageFilter(ConsumerType consumer_type,
+ uint32_t message_class_to_filter);
+
+ protected:
+ // All methods below to be called on the IO thread.
+ ~DeviceSensorMessageFilter() override;
+
+ virtual void OnStartPolling();
+ virtual void OnStopPolling();
+ // To be overriden by the subclass in order to send the appropriate message
+ // to the renderer with a handle to shared memory.
+ virtual void DidStartPolling(base::SharedMemoryHandle handle) = 0;
+
+ private:
+ ConsumerType consumer_type_;
+ bool is_started_;
+
+ DISALLOW_COPY_AND_ASSIGN(DeviceSensorMessageFilter);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_DEVICE_SENSORS_DEVICE_SENSOR_MESSAGE_FILTER_H_
diff --git a/chromium/content/browser/device_sensors/sensor_manager_android.cc b/chromium/content/browser/device_sensors/sensor_manager_android.cc
index e821fb445a4..5fffdd90720 100644
--- a/chromium/content/browser/device_sensors/sensor_manager_android.cc
+++ b/chromium/content/browser/device_sensors/sensor_manager_android.cc
@@ -41,7 +41,6 @@ void SetOrientationBufferStatus(
bool ready, bool absolute) {
buffer->seqlock.WriteBegin();
buffer->data.absolute = absolute;
- buffer->data.hasAbsolute = ready;
buffer->data.allAvailableSensorsAreActive = ready;
buffer->seqlock.WriteEnd();
}
diff --git a/chromium/content/browser/device_sensors/sensor_manager_chromeos.cc b/chromium/content/browser/device_sensors/sensor_manager_chromeos.cc
index 97dc8fbcbc6..3544749d6e4 100644
--- a/chromium/content/browser/device_sensors/sensor_manager_chromeos.cc
+++ b/chromium/content/browser/device_sensors/sensor_manager_chromeos.cc
@@ -69,7 +69,6 @@ void SensorManagerChromeOS::StartFetchingDeviceOrientationData(
// No compass information, so we cannot provide absolute orientation.
orientation_buffer_->seqlock.WriteBegin();
orientation_buffer_->data.absolute = false;
- orientation_buffer_->data.hasAbsolute = true;
orientation_buffer_->seqlock.WriteEnd();
if (!motion_buffer_)
diff --git a/chromium/content/browser/device_sensors/sensor_manager_chromeos_unittest.cc b/chromium/content/browser/device_sensors/sensor_manager_chromeos_unittest.cc
index 6d9f77644f7..7693e4d81b4 100644
--- a/chromium/content/browser/device_sensors/sensor_manager_chromeos_unittest.cc
+++ b/chromium/content/browser/device_sensors/sensor_manager_chromeos_unittest.cc
@@ -116,7 +116,6 @@ TEST_F(SensorManagerChromeOSTest, MotionBuffer) {
// buffer.
TEST_F(SensorManagerChromeOSTest, OrientationBuffer) {
DeviceOrientationHardwareBuffer* buffer = orientation_buffer();
- EXPECT_TRUE(buffer->data.hasAbsolute);
EXPECT_FALSE(buffer->data.hasAlpha);
EXPECT_FALSE(buffer->data.hasBeta);
EXPECT_FALSE(buffer->data.hasGamma);
diff --git a/chromium/content/browser/devtools/browser_devtools_agent_host.cc b/chromium/content/browser/devtools/browser_devtools_agent_host.cc
index d7c342307db..dbc28a60092 100644
--- a/chromium/content/browser/devtools/browser_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/browser_devtools_agent_host.cc
@@ -11,6 +11,7 @@
#include "content/browser/devtools/protocol/system_info_handler.h"
#include "content/browser/devtools/protocol/tethering_handler.h"
#include "content/browser/devtools/protocol/tracing_handler.h"
+#include "content/browser/frame_host/frame_tree_node.h"
namespace content {
@@ -30,7 +31,9 @@ BrowserDevToolsAgentHost::BrowserDevToolsAgentHost(
new devtools::tethering::TetheringHandler(socket_callback,
tethering_task_runner)),
tracing_handler_(new devtools::tracing::TracingHandler(
- devtools::tracing::TracingHandler::Browser, GetIOContext())),
+ devtools::tracing::TracingHandler::Browser,
+ FrameTreeNode::kFrameTreeNodeInvalidId,
+ GetIOContext())),
protocol_handler_(new DevToolsProtocolHandler(this)) {
DevToolsProtocolDispatcher* dispatcher = protocol_handler_->dispatcher();
dispatcher->SetIOHandler(io_handler_.get());
diff --git a/chromium/content/browser/devtools/devtools_agent_host_impl.cc b/chromium/content/browser/devtools/devtools_agent_host_impl.cc
index df27d124201..033f2f18bd9 100644
--- a/chromium/content/browser/devtools/devtools_agent_host_impl.cc
+++ b/chromium/content/browser/devtools/devtools_agent_host_impl.cc
@@ -235,10 +235,13 @@ void DevToolsAgentHostImpl::NotifyCallbacks(
(*it)->Run(agent_host, attached);
}
-void DevToolsAgentHostImpl::Inspect(BrowserContext* browser_context) {
+bool DevToolsAgentHostImpl::Inspect(BrowserContext* browser_context) {
DevToolsManager* manager = DevToolsManager::GetInstance();
- if (manager->delegate())
+ if (manager->delegate()) {
manager->delegate()->Inspect(browser_context, this);
+ return true;
+ }
+ return false;
}
// DevToolsMessageChunkProcessor -----------------------------------------------
diff --git a/chromium/content/browser/devtools/devtools_agent_host_impl.h b/chromium/content/browser/devtools/devtools_agent_host_impl.h
index f3b06246816..f70ebc5fc97 100644
--- a/chromium/content/browser/devtools/devtools_agent_host_impl.h
+++ b/chromium/content/browser/devtools/devtools_agent_host_impl.h
@@ -35,7 +35,7 @@ class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost,
virtual void Detach() = 0;
// Opens the inspector for this host.
- void Inspect(BrowserContext* browser_context);
+ bool Inspect(BrowserContext* browser_context);
// DevToolsAgentHost implementation.
void AttachClient(DevToolsAgentHostClient* client) override;
diff --git a/chromium/content/browser/devtools/devtools_frame_trace_recorder.cc b/chromium/content/browser/devtools/devtools_frame_trace_recorder.cc
index 618bbf8517c..d5756385810 100644
--- a/chromium/content/browser/devtools/devtools_frame_trace_recorder.cc
+++ b/chromium/content/browser/devtools/devtools_frame_trace_recorder.cc
@@ -78,7 +78,7 @@ void FrameCaptured(base::TimeTicks timestamp, const SkBitmap& bitmap,
TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID_AND_TIMESTAMP(
TRACE_DISABLED_BY_DEFAULT("devtools.screenshot"), "Screenshot", 1,
timestamp.ToInternalValue(),
- scoped_refptr<base::trace_event::ConvertableToTraceFormat>(
+ scoped_ptr<base::trace_event::ConvertableToTraceFormat>(
new TraceableDevToolsScreenshot(bitmap)));
}
diff --git a/chromium/content/browser/devtools/devtools_frame_trace_recorder.h b/chromium/content/browser/devtools/devtools_frame_trace_recorder.h
index 1d026676cf8..79c6f16145c 100644
--- a/chromium/content/browser/devtools/devtools_frame_trace_recorder.h
+++ b/chromium/content/browser/devtools/devtools_frame_trace_recorder.h
@@ -7,6 +7,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
namespace cc {
diff --git a/chromium/content/browser/devtools/devtools_manager.h b/chromium/content/browser/devtools/devtools_manager.h
index 57b9ea022b3..f803c1331d7 100644
--- a/chromium/content/browser/devtools/devtools_manager.h
+++ b/chromium/content/browser/devtools/devtools_manager.h
@@ -7,6 +7,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
#include "content/common/content_export.h"
#include "content/public/browser/devtools_manager_delegate.h"
diff --git a/chromium/content/browser/devtools/devtools_netlog_observer.cc b/chromium/content/browser/devtools/devtools_netlog_observer.cc
index 24448e330cf..6a2a3c45be0 100644
--- a/chromium/content/browser/devtools/devtools_netlog_observer.cc
+++ b/chromium/content/browser/devtools/devtools_netlog_observer.cc
@@ -138,8 +138,8 @@ void DevToolsNetLogObserver::OnAddURLRequestEntry(
// several http requests (e.g. see http://crbug.com/80157).
info->response_headers.clear();
- for (void* it = NULL;
- response_headers->EnumerateHeaderLines(&it, &name, &value); ) {
+ for (size_t it = 0;
+ response_headers->EnumerateHeaderLines(&it, &name, &value);) {
info->response_headers.push_back(std::make_pair(name, value));
}
diff --git a/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
index 62f7a35aade..3f471114c64 100644
--- a/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
+++ b/chromium/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -282,7 +282,7 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, DISABLED_SynthesizePinchGesture) {
ASSERT_DOUBLE_EQ(2.0, static_cast<double>(old_height) / new_height);
}
-IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, SynthesizeScrollGesture) {
+IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, DISABLED_SynthesizeScrollGesture) {
GURL test_url = GetTestUrl("devtools", "synthetic_gesture_tests.html");
NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
Attach();
@@ -306,7 +306,7 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, SynthesizeScrollGesture) {
ASSERT_EQ(100, scroll_top);
}
-IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, SynthesizeTapGesture) {
+IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, DISABLED_SynthesizeTapGesture) {
GURL test_url = GetTestUrl("devtools", "synthetic_gesture_tests.html");
NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
Attach();
@@ -344,7 +344,9 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, NavigationPreservesMessages) {
scoped_ptr<base::DictionaryValue> params(new base::DictionaryValue());
test_url = GetTestUrl("devtools", "navigation.html");
params->SetString("url", test_url.spec());
+ TestNavigationObserver navigation_observer(shell()->web_contents());
SendCommand("Page.navigate", std::move(params), true);
+ navigation_observer.Wait();
bool enough_results = result_ids_.size() >= 2u;
EXPECT_TRUE(enough_results);
@@ -486,4 +488,30 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, ReloadBlankPage) {
// Should not crash at this point.
}
+IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, EvaluateInBlankPage) {
+ NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
+ Attach();
+ scoped_ptr<base::DictionaryValue> params(new base::DictionaryValue());
+ params->SetString("expression", "window");
+ SendCommand("Runtime.evaluate", std::move(params), true);
+ bool wasThrown = true;
+ EXPECT_TRUE(result_->GetBoolean("wasThrown", &wasThrown));
+ EXPECT_FALSE(wasThrown);
+}
+
+IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest,
+ EvaluateInBlankPageAfterNavigation) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ GURL test_url = embedded_test_server()->GetURL("/devtools/navigation.html");
+ NavigateToURLBlockUntilNavigationsComplete(shell(), test_url, 1);
+ Attach();
+ NavigateToURLBlockUntilNavigationsComplete(shell(), GURL("about:blank"), 1);
+ scoped_ptr<base::DictionaryValue> params(new base::DictionaryValue());
+ params->SetString("expression", "window");
+ SendCommand("Runtime.evaluate", std::move(params), true);
+ bool wasThrown = true;
+ EXPECT_TRUE(result_->GetBoolean("wasThrown", &wasThrown));
+ EXPECT_FALSE(wasThrown);
+}
+
} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/devtools_protocol_client.h b/chromium/content/browser/devtools/protocol/devtools_protocol_client.h
index fe17c995f77..ba1a0d79c53 100644
--- a/chromium/content/browser/devtools/protocol/devtools_protocol_client.h
+++ b/chromium/content/browser/devtools/protocol/devtools_protocol_client.h
@@ -7,6 +7,7 @@
#include "base/callback.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/values.h"
namespace content {
diff --git a/chromium/content/browser/devtools/protocol/devtools_protocol_handler_generator.py b/chromium/content/browser/devtools/protocol/devtools_protocol_handler_generator.py
index df56ffe8a5c..2f244625c3a 100755
--- a/chromium/content/browser/devtools/protocol/devtools_protocol_handler_generator.py
+++ b/chromium/content/browser/devtools/protocol/devtools_protocol_handler_generator.py
@@ -568,6 +568,7 @@ def ResolveObject(json, mapping):
mapping["storage_type"] = "scoped_ptr<base::DictionaryValue>"
mapping["raw_type"] = "base::DictionaryValue*"
mapping["pass_template"] = tmpl_object_pass
+ mapping["init"] = " = nullptr"
if "properties" in json:
if not "declared_name" in mapping:
mapping["declared_name"] = ("%s%s" %
diff --git a/chromium/content/browser/devtools/protocol/emulation_handler.cc b/chromium/content/browser/devtools/protocol/emulation_handler.cc
index f5945d71321..6b124e37131 100644
--- a/chromium/content/browser/devtools/protocol/emulation_handler.cc
+++ b/chromium/content/browser/devtools/protocol/emulation_handler.cc
@@ -23,6 +23,19 @@ using Response = DevToolsProtocolClient::Response;
namespace {
+blink::WebScreenOrientationType WebScreenOrientationTypeFromString(
+ const std::string& type) {
+ if (type == screen_orientation::kTypePortraitPrimary)
+ return blink::WebScreenOrientationPortraitPrimary;
+ if (type == screen_orientation::kTypePortraitSecondary)
+ return blink::WebScreenOrientationPortraitSecondary;
+ if (type == screen_orientation::kTypeLandscapePrimary)
+ return blink::WebScreenOrientationLandscapePrimary;
+ if (type == screen_orientation::kTypeLandscapeSecondary)
+ return blink::WebScreenOrientationLandscapeSecondary;
+ return blink::WebScreenOrientationUndefined;
+}
+
ui::GestureProviderConfigType TouchEmulationConfigurationToType(
const std::string& protocol_value) {
ui::GestureProviderConfigType result =
@@ -132,9 +145,11 @@ Response EmulationHandler::SetDeviceMetricsOverride(
const int* screen_width,
const int* screen_height,
const int* position_x,
- const int* position_y) {
+ const int* position_y,
+ const scoped_ptr<base::DictionaryValue>& screen_orientation) {
const static int max_size = 10000000;
const static double max_scale = 10;
+ const static int max_orientation_angle = 360;
if (!host_)
return Response::InternalError("Could not connect to view");
@@ -168,6 +183,30 @@ Response EmulationHandler::SetDeviceMetricsOverride(
base::DoubleToString(max_scale));
}
+ blink::WebScreenOrientationType orientationType =
+ blink::WebScreenOrientationUndefined;
+ int orientationAngle = 0;
+ if (screen_orientation) {
+ std::string orientationTypeString;
+ if (!screen_orientation->GetString("type", &orientationTypeString)) {
+ return Response::InvalidParams(
+ "Screen orientation type must be a string");
+ }
+ orientationType = WebScreenOrientationTypeFromString(orientationTypeString);
+ if (orientationType == blink::WebScreenOrientationUndefined)
+ return Response::InvalidParams("Invalid screen orientation type value");
+
+ if (!screen_orientation->GetInteger("angle", &orientationAngle)) {
+ return Response::InvalidParams(
+ "Screen orientation angle must be a number");
+ }
+ if (orientationAngle < 0 || orientationAngle >= max_orientation_angle) {
+ return Response::InvalidParams(
+ "Screen orientation angle must be non-negative, less than " +
+ base::IntToString(max_orientation_angle));
+ }
+ }
+
blink::WebDeviceEmulationParams params;
params.screenPosition = mobile ? blink::WebDeviceEmulationParams::Mobile :
blink::WebDeviceEmulationParams::Desktop;
@@ -182,6 +221,8 @@ Response EmulationHandler::SetDeviceMetricsOverride(
params.offset = blink::WebFloatPoint(
optional_offset_x ? *optional_offset_x : 0.f,
optional_offset_y ? *optional_offset_y : 0.f);
+ params.screenOrientationType = orientationType;
+ params.screenOrientationAngle = orientationAngle;
if (device_emulation_enabled_ && params == device_emulation_params_)
return Response::OK();
diff --git a/chromium/content/browser/devtools/protocol/emulation_handler.h b/chromium/content/browser/devtools/protocol/emulation_handler.h
index bcaeb0d0410..a5aec635500 100644
--- a/chromium/content/browser/devtools/protocol/emulation_handler.h
+++ b/chromium/content/browser/devtools/protocol/emulation_handler.h
@@ -39,18 +39,20 @@ class EmulationHandler {
const std::string* configuration);
Response CanEmulate(bool* result);
- Response SetDeviceMetricsOverride(int width,
- int height,
- double device_scale_factor,
- bool mobile,
- bool fit_window,
- const double* optional_scale,
- const double* optional_offset_x,
- const double* optional_offset_y,
- const int* screen_widget,
- const int* screen_height,
- const int* position_x,
- const int* position_y);
+ Response SetDeviceMetricsOverride(
+ int width,
+ int height,
+ double device_scale_factor,
+ bool mobile,
+ bool fit_window,
+ const double* optional_scale,
+ const double* optional_offset_x,
+ const double* optional_offset_y,
+ const int* screen_widget,
+ const int* screen_height,
+ const int* position_x,
+ const int* position_y,
+ const scoped_ptr<base::DictionaryValue>& screen_orientation);
Response ClearDeviceMetricsOverride();
private:
diff --git a/chromium/content/browser/devtools/protocol/input_handler.cc b/chromium/content/browser/devtools/protocol/input_handler.cc
index d9c17f3ee0e..08c3cf2cd36 100644
--- a/chromium/content/browser/devtools/protocol/input_handler.cc
+++ b/chromium/content/browser/devtools/protocol/input_handler.cc
@@ -69,8 +69,13 @@ void SetEventModifiers(blink::WebInputEvent* event, const int* modifiers) {
}
void SetEventTimestamp(blink::WebInputEvent* event, const double* timestamp) {
- event->timeStampSeconds =
- timestamp ? *timestamp : base::Time::Now().ToDoubleT();
+ // Convert timestamp, in seconds since unix epoch, to an event timestamp
+ // which is time ticks since platform start time.
+ base::TimeTicks ticks = timestamp
+ ? base::TimeDelta::FromSecondsD(*timestamp) +
+ base::TimeTicks::UnixEpoch()
+ : base::TimeTicks::Now();
+ event->timeStampSeconds = (ticks - base::TimeTicks()).InSecondsF();
}
bool SetKeyboardEventText(blink::WebUChar* to, const std::string* from) {
@@ -248,6 +253,7 @@ Response InputHandler::DispatchMouseEvent(
event.globalX = x * page_scale_factor_;
event.globalY = y * page_scale_factor_;
event.clickCount = click_count ? *click_count : 0;
+ event.pointerType = blink::WebPointerProperties::PointerType::Mouse;
if (!host_)
return Response::ServerError("Could not connect to view");
@@ -296,6 +302,7 @@ Response InputHandler::EmulateTouchFromMouseEvent(const std::string& type,
event->globalX = x;
event->globalY = y;
event->clickCount = click_count ? *click_count : 0;
+ event->pointerType = blink::WebPointerProperties::PointerType::Touch;
if (!host_)
return Response::ServerError("Could not connect to view");
diff --git a/chromium/content/browser/devtools/protocol/inspector_handler.cc b/chromium/content/browser/devtools/protocol/inspector_handler.cc
index 31e9d1bf9c6..8e018a8477e 100644
--- a/chromium/content/browser/devtools/protocol/inspector_handler.cc
+++ b/chromium/content/browser/devtools/protocol/inspector_handler.cc
@@ -38,9 +38,12 @@ void InspectorHandler::TargetDetached(const std::string& reason) {
Response InspectorHandler::Enable() {
if (host_ && !host_->IsRenderFrameLive())
client_->TargetCrashed(TargetCrashedParams::Create());
- return Response::FallThrough();
+ return Response::OK();
}
+Response InspectorHandler::Disable() {
+ return Response::OK();
+}
} // namespace inspector
} // namespace devtools
diff --git a/chromium/content/browser/devtools/protocol/inspector_handler.h b/chromium/content/browser/devtools/protocol/inspector_handler.h
index 08c1e5e3efb..52325c48a69 100644
--- a/chromium/content/browser/devtools/protocol/inspector_handler.h
+++ b/chromium/content/browser/devtools/protocol/inspector_handler.h
@@ -29,6 +29,7 @@ class InspectorHandler {
void TargetDetached(const std::string& reason);
Response Enable();
+ Response Disable();
private:
scoped_ptr<Client> client_;
diff --git a/chromium/content/browser/devtools/protocol/memory_handler.cc b/chromium/content/browser/devtools/protocol/memory_handler.cc
index ef5cda2703a..9107fa93a4f 100644
--- a/chromium/content/browser/devtools/protocol/memory_handler.cc
+++ b/chromium/content/browser/devtools/protocol/memory_handler.cc
@@ -6,7 +6,7 @@
#include "base/memory/memory_pressure_listener.h"
#include "base/strings/stringprintf.h"
-#include "content/browser/memory/memory_pressure_controller.h"
+#include "content/browser/memory/memory_pressure_controller_impl.h"
namespace content {
namespace devtools {
@@ -18,7 +18,7 @@ MemoryHandler::~MemoryHandler() {}
MemoryHandler::Response MemoryHandler::SetPressureNotificationsSuppressed(
bool suppressed) {
- content::MemoryPressureController::GetInstance()
+ content::MemoryPressureControllerImpl::GetInstance()
->SetPressureNotificationsSuppressedInAllProcesses(suppressed);
return Response::OK();
}
@@ -35,7 +35,7 @@ MemoryHandler::Response MemoryHandler::SimulatePressureNotification(
"Invalid memory pressure level '%s'", level.c_str()));
}
- MemoryPressureController::GetInstance()
+ MemoryPressureControllerImpl::GetInstance()
->SimulatePressureNotificationInAllProcesses(parsed_level);
return Response::OK();
}
diff --git a/chromium/content/browser/devtools/protocol/network_handler.cc b/chromium/content/browser/devtools/protocol/network_handler.cc
index d18d87a6b96..5163f19b853 100644
--- a/chromium/content/browser/devtools/protocol/network_handler.cc
+++ b/chromium/content/browser/devtools/protocol/network_handler.cc
@@ -15,8 +15,10 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/cert_store.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/render_process_host.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/site_instance.h"
+#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/common/content_client.h"
@@ -133,8 +135,6 @@ class GetCookiesCommand {
request_count_(0) {
CookieListCallback got_cookies_callback = base::Bind(
&GetCookiesCommand::GotCookiesForURL, base::Unretained(this));
- BrowserContext* browser_context =
- frame_host->GetSiteInstance()->GetBrowserContext();
std::queue<FrameTreeNode*> queue;
queue.push(frame_host->frame_tree_node());
@@ -145,11 +145,12 @@ class GetCookiesCommand {
// Only traverse nodes with the same local root.
if (node->current_frame_host()->IsCrossProcessSubframe())
continue;
- int process_id = node->current_frame_host()->GetProcess()->GetID();
++request_count_;
GetCookiesForURLOnUI(
- browser_context->GetResourceContext(),
- browser_context->GetRequestContextForRenderProcess(process_id),
+ frame_host->GetSiteInstance()->GetBrowserContext()->
+ GetResourceContext(),
+ frame_host->GetProcess()->GetStoragePartition()->
+ GetURLRequestContext(),
node->current_url(),
got_cookies_callback);
@@ -233,7 +234,7 @@ void NetworkHandler::SendGetCookiesResponse(
std::vector<scoped_refptr<Cookie>> cookies;
for (size_t i = 0; i < cookie_list.size(); ++i) {
const net::CanonicalCookie& cookie = cookie_list[i];
- cookies.push_back(Cookie::Create()
+ scoped_refptr<Cookie> devtools_cookie = Cookie::Create()
->set_name(cookie.Name())
->set_value(cookie.Value())
->set_domain(cookie.Domain())
@@ -242,7 +243,19 @@ void NetworkHandler::SendGetCookiesResponse(
->set_size(cookie.Name().length() + cookie.Value().length())
->set_http_only(cookie.IsHttpOnly())
->set_secure(cookie.IsSecure())
- ->set_session(!cookie.IsPersistent()));
+ ->set_session(!cookie.IsPersistent());
+
+ switch (cookie.SameSite()) {
+ case net::CookieSameSite::STRICT_MODE:
+ devtools_cookie->set_same_site(cookie::kSameSiteStrict);
+ break;
+ case net::CookieSameSite::LAX_MODE:
+ devtools_cookie->set_same_site(cookie::kSameSiteLax);
+ break;
+ case net::CookieSameSite::NO_RESTRICTION:
+ break;
+ }
+ cookies.push_back(devtools_cookie);
}
client_->SendGetCookiesResponse(command_id,
GetCookiesResponse::Create()->set_cookies(cookies));
@@ -254,12 +267,9 @@ Response NetworkHandler::DeleteCookie(
const std::string& url) {
if (!host_)
return Response::InternalError("Could not connect to view");
- BrowserContext* browser_context =
- host_->GetSiteInstance()->GetBrowserContext();
- int process_id = host_->GetProcess()->GetID();
DeleteCookieOnUI(
- browser_context->GetResourceContext(),
- browser_context->GetRequestContextForRenderProcess(process_id),
+ host_->GetSiteInstance()->GetBrowserContext()->GetResourceContext(),
+ host_->GetProcess()->GetStoragePartition()->GetURLRequestContext(),
GURL(url),
cookie_name,
base::Bind(&NetworkHandler::SendDeleteCookieResponse,
diff --git a/chromium/content/browser/devtools/protocol/page_handler.cc b/chromium/content/browser/devtools/protocol/page_handler.cc
index 7e79a7200cf..d4f6c3976f4 100644
--- a/chromium/content/browser/devtools/protocol/page_handler.cc
+++ b/chromium/content/browser/devtools/protocol/page_handler.cc
@@ -200,7 +200,7 @@ Response PageHandler::Disable() {
return Response::FallThrough();
}
-Response PageHandler::Reload(const bool* ignoreCache,
+Response PageHandler::Reload(const bool* bypassCache,
const std::string* script_to_evaluate_on_load,
const std::string* script_preprocessor) {
WebContentsImpl* web_contents = GetWebContents();
@@ -210,7 +210,10 @@ Response PageHandler::Reload(const bool* ignoreCache,
if (web_contents->IsCrashed() ||
(web_contents->GetController().GetVisibleEntry() &&
web_contents->GetController().GetVisibleEntry()->IsViewSourceMode())) {
- web_contents->GetController().Reload(false);
+ if (bypassCache && *bypassCache)
+ web_contents->GetController().ReloadBypassingCache(false);
+ else
+ web_contents->GetController().Reload(false);
return Response::OK();
} else {
// Handle reload in renderer except for crashed and view source mode.
@@ -357,6 +360,14 @@ Response PageHandler::SetColorPickerEnabled(bool enabled) {
return Response::OK();
}
+Response PageHandler::RequestAppBanner() {
+ WebContentsImpl* web_contents = GetWebContents();
+ if (!web_contents)
+ return Response::InternalError("Could not connect to view");
+ web_contents->GetDelegate()->RequestAppBannerFromDevTools(web_contents);
+ return Response::OK();
+}
+
WebContentsImpl* PageHandler::GetWebContents() {
return host_ ?
static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(host_)) :
diff --git a/chromium/content/browser/devtools/protocol/page_handler.h b/chromium/content/browser/devtools/protocol/page_handler.h
index 02b685a50d1..067d9587b32 100644
--- a/chromium/content/browser/devtools/protocol/page_handler.h
+++ b/chromium/content/browser/devtools/protocol/page_handler.h
@@ -49,7 +49,7 @@ class PageHandler : public NotificationObserver {
Response Enable();
Response Disable();
- Response Reload(const bool* ignoreCache,
+ Response Reload(const bool* bypassCache,
const std::string* script_to_evaluate_on_load,
const std::string* script_preprocessor = NULL);
@@ -77,6 +77,7 @@ class PageHandler : public NotificationObserver {
const std::string& security_origin);
Response SetColorPickerEnabled(bool enabled);
+ Response RequestAppBanner();
private:
WebContentsImpl* GetWebContents();
diff --git a/chromium/content/browser/devtools/protocol/service_worker_handler.cc b/chromium/content/browser/devtools/protocol/service_worker_handler.cc
index a84091c276b..b2f5c2572b7 100644
--- a/chromium/content/browser/devtools/protocol/service_worker_handler.cc
+++ b/chromium/content/browser/devtools/protocol/service_worker_handler.cc
@@ -16,6 +16,7 @@
#include "content/browser/service_worker/service_worker_context_watcher.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_version.h"
+#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/devtools_agent_host.h"
@@ -23,6 +24,7 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/common/push_event_payload.h"
#include "content/public/common/push_messaging_status.h"
#include "url/gurl.h"
@@ -131,10 +133,7 @@ scoped_refptr<ServiceWorkerRegistration> CreateRegistrationDictionaryValue(
base::Int64ToString(registration_info.registration_id))
->set_scope_url(registration_info.pattern.spec())
->set_is_deleted(registration_info.delete_flag ==
- ServiceWorkerRegistrationInfo::IS_DELETED)
- ->set_force_update_on_page_load(
- registration_info.force_update_on_page_load ==
- ServiceWorkerRegistrationInfo::IS_FORCED));
+ ServiceWorkerRegistrationInfo::IS_DELETED));
return registration;
}
@@ -142,17 +141,27 @@ scoped_refptr<ServiceWorkerDevToolsAgentHost> GetMatchingServiceWorker(
const ServiceWorkerDevToolsAgentHost::List& agent_hosts,
const GURL& url) {
scoped_refptr<ServiceWorkerDevToolsAgentHost> best_host;
- std::string best_scope;
+ bool best_host_scope_matched = false;
+ int best_host_scope_length = 0;
+
for (auto host : agent_hosts) {
if (host->GetURL().host_piece() != url.host_piece())
continue;
- std::string path = host->GetURL().path();
- std::string file = host->GetURL().ExtractFileName();
- std::string scope = path.substr(0, path.length() - file.length());
- // Choose the latest, longest scope match worker.
- if (scope.length() >= best_scope.length()) {
+ const bool scope_matched =
+ ServiceWorkerUtils::ScopeMatches(host->scope(), url);
+ const int scope_length = host->scope().spec().length();
+ bool replace = false;
+ if (!best_host)
+ replace = true;
+ else if (best_host_scope_matched)
+ replace = scope_matched && scope_length >= best_host_scope_length;
+ else
+ replace = scope_matched || scope_length >= best_host_scope_length;
+
+ if (replace) {
best_host = host;
- best_scope = scope;
+ best_host_scope_matched = scope_matched;
+ best_host_scope_length = scope_length;
}
}
return best_host;
@@ -176,11 +185,6 @@ ServiceWorkerDevToolsAgentHost::Map GetMatchingServiceWorkers(
return result;
}
-bool CollectURLs(std::set<GURL>* urls, FrameTreeNode* tree_node) {
- urls->insert(tree_node->current_url());
- return false;
-}
-
void StopServiceWorkerOnIO(scoped_refptr<ServiceWorkerContextWrapper> context,
int64_t version_id) {
if (content::ServiceWorkerVersion* version =
@@ -246,6 +250,7 @@ void ServiceWorkerHandler::SetRenderFrameHost(
render_frame_host_ = render_frame_host;
// Do not call UpdateHosts yet, wait for load to commit.
if (!render_frame_host) {
+ ClearForceUpdate();
context_ = nullptr;
return;
}
@@ -268,8 +273,10 @@ void ServiceWorkerHandler::UpdateHosts() {
urls_.clear();
BrowserContext* browser_context = nullptr;
if (render_frame_host_) {
- render_frame_host_->frame_tree_node()->frame_tree()->ForEach(
- base::Bind(&CollectURLs, &urls_));
+ for (FrameTreeNode* node :
+ render_frame_host_->frame_tree_node()->frame_tree()->Nodes())
+ urls_.insert(node->current_url());
+
browser_context = render_frame_host_->GetProcess()->GetBrowserContext();
}
@@ -277,12 +284,12 @@ void ServiceWorkerHandler::UpdateHosts() {
ServiceWorkerDevToolsAgentHost::Map new_hosts =
GetMatchingServiceWorkers(browser_context, urls_);
- for (auto pair : old_hosts) {
+ for (const auto& pair : old_hosts) {
if (new_hosts.find(pair.first) == new_hosts.end())
ReportWorkerTerminated(pair.second.get());
}
- for (auto pair : new_hosts) {
+ for (const auto& pair : new_hosts) {
if (old_hosts.find(pair.first) == old_hosts.end())
ReportWorkerCreated(pair.second.get());
}
@@ -301,11 +308,6 @@ Response ServiceWorkerHandler::Enable() {
ServiceWorkerDevToolsManager::GetInstance()->AddObserver(this);
- client_->DebugOnStartUpdated(
- DebugOnStartUpdatedParams::Create()->set_debug_on_start(
- ServiceWorkerDevToolsManager::GetInstance()
- ->debug_service_worker_on_start()));
-
context_watcher_ = new ServiceWorkerContextWatcher(
context_, base::Bind(&ServiceWorkerHandler::OnWorkerRegistrationUpdated,
weak_factory_.GetWeakPtr()),
@@ -325,6 +327,7 @@ Response ServiceWorkerHandler::Disable() {
enabled_ = false;
ServiceWorkerDevToolsManager::GetInstance()->RemoveObserver(this);
+ ClearForceUpdate();
for (const auto& pair : attached_hosts_)
pair.second->DetachClient();
attached_hosts_.clear();
@@ -411,21 +414,11 @@ Response ServiceWorkerHandler::InspectWorker(const std::string& version_id) {
return Response::OK();
}
-Response ServiceWorkerHandler::SetDebugOnStart(bool debug_on_start) {
- ServiceWorkerDevToolsManager::GetInstance()
- ->set_debug_service_worker_on_start(debug_on_start);
- return Response::OK();
-}
-
Response ServiceWorkerHandler::SetForceUpdateOnPageLoad(
- const std::string& registration_id,
bool force_update_on_page_load) {
if (!context_)
return CreateContextErrorResponse();
- int64_t id = kInvalidServiceWorkerRegistrationId;
- if (!base::StringToInt64(registration_id, &id))
- return CreateInvalidVersionIdErrorResponse();
- context_->SetForceUpdateOnPageLoad(id, force_update_on_page_load);
+ context_->SetForceUpdateOnPageLoad(force_update_on_page_load);
return Response::OK();
}
@@ -440,9 +433,12 @@ Response ServiceWorkerHandler::DeliverPushMessage(
int64_t id = 0;
if (!base::StringToInt64(registration_id, &id))
return CreateInvalidVersionIdErrorResponse();
+ PushEventPayload payload;
+ if (data.size() > 0)
+ payload.setData(data);
BrowserContext::DeliverPushMessage(
render_frame_host_->GetProcess()->GetBrowserContext(), GURL(origin), id,
- data, base::Bind(&PushDeliveryNoOp));
+ payload, base::Bind(&PushDeliveryNoOp));
return Response::OK();
}
@@ -568,11 +564,6 @@ void ServiceWorkerHandler::WorkerDestroyed(
UpdateHosts();
}
-void ServiceWorkerHandler::DebugOnStartUpdated(bool debug_on_start) {
- client_->DebugOnStartUpdated(
- DebugOnStartUpdatedParams::Create()->set_debug_on_start(debug_on_start));
-}
-
void ServiceWorkerHandler::ReportWorkerCreated(
ServiceWorkerDevToolsAgentHost* host) {
if (host->IsAttached())
@@ -597,6 +588,11 @@ void ServiceWorkerHandler::ReportWorkerTerminated(
attached_hosts_.erase(it);
}
+void ServiceWorkerHandler::ClearForceUpdate() {
+ if (context_)
+ context_->SetForceUpdateOnPageLoad(false);
+}
+
} // namespace service_worker
} // namespace devtools
} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/service_worker_handler.h b/chromium/content/browser/devtools/protocol/service_worker_handler.h
index 1508f5d375f..02dcd8c43f5 100644
--- a/chromium/content/browser/devtools/protocol/service_worker_handler.h
+++ b/chromium/content/browser/devtools/protocol/service_worker_handler.h
@@ -57,9 +57,7 @@ class ServiceWorkerHandler : public DevToolsAgentHostClient,
Response StopWorker(const std::string& version_id);
Response UpdateRegistration(const std::string& scope_url);
Response InspectWorker(const std::string& version_id);
- Response SetDebugOnStart(bool debug_on_start);
- Response SetForceUpdateOnPageLoad(const std::string& registration_id,
- bool force_update_on_page_load);
+ Response SetForceUpdateOnPageLoad(bool force_update_on_page_load);
Response DeliverPushMessage(const std::string& origin,
const std::string& registration_id,
const std::string& data);
@@ -71,7 +69,6 @@ class ServiceWorkerHandler : public DevToolsAgentHostClient,
void WorkerCreated(ServiceWorkerDevToolsAgentHost* host) override;
void WorkerReadyForInspection(ServiceWorkerDevToolsAgentHost* host) override;
void WorkerDestroyed(ServiceWorkerDevToolsAgentHost* host) override;
- void DebugOnStartUpdated(bool debug_on_start) override;
private:
// DevToolsAgentHostClient overrides.
@@ -92,6 +89,7 @@ class ServiceWorkerHandler : public DevToolsAgentHostClient,
const ServiceWorkerContextObserver::ErrorInfo& info);
void OpenNewDevToolsWindow(int process_id, int devtools_agent_route_id);
+ void ClearForceUpdate();
scoped_refptr<ServiceWorkerContextWrapper> context_;
scoped_ptr<Client> client_;
diff --git a/chromium/content/browser/devtools/protocol/system_info_handler.cc b/chromium/content/browser/devtools/protocol/system_info_handler.cc
index 27877b0bd98..5a9d53ad1e9 100644
--- a/chromium/content/browser/devtools/protocol/system_info_handler.cc
+++ b/chromium/content/browser/devtools/protocol/system_info_handler.cc
@@ -8,9 +8,12 @@
#include <utility>
#include "base/bind.h"
+#include "base/command_line.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/public/browser/gpu_data_manager.h"
+#include "gpu/config/gpu_feature_type.h"
#include "gpu/config/gpu_info.h"
+#include "gpu/config/gpu_switches.h"
namespace content {
namespace devtools {
@@ -149,7 +152,9 @@ void SystemInfoHandler::SetClient(scoped_ptr<Client> client) {
Response SystemInfoHandler::GetInfo(DevToolsCommandId command_id) {
std::string reason;
if (!GpuDataManager::GetInstance()->GpuAccessAllowed(&reason) ||
- GpuDataManager::GetInstance()->IsEssentialGpuInfoAvailable()) {
+ GpuDataManager::GetInstance()->IsEssentialGpuInfoAvailable() ||
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kGpuTestingNoCompleteInfoCollection)) {
// The GpuDataManager already has all of the information needed to make
// GPU-based blacklisting decisions. Post a task to give it to the
// client asynchronously.
diff --git a/chromium/content/browser/devtools/protocol/tethering_handler.cc b/chromium/content/browser/devtools/protocol/tethering_handler.cc
index a58b534c368..1718261c355 100644
--- a/chromium/content/browser/devtools/protocol/tethering_handler.cc
+++ b/chromium/content/browser/devtools/protocol/tethering_handler.cc
@@ -7,6 +7,7 @@
#include "base/stl_util.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/io_buffer.h"
+#include "net/base/ip_address.h"
#include "net/base/net_errors.h"
#include "net/socket/server_socket.h"
#include "net/socket/stream_socket.h"
@@ -18,8 +19,6 @@ namespace tethering {
namespace {
-const char kLocalhost[] = "127.0.0.1";
-
const int kListenBacklog = 5;
const int kBufferSize = 16 * 1024;
@@ -171,11 +170,7 @@ class BoundSocket {
bool Listen(uint16_t port) {
port_ = port;
- net::IPAddressNumber ip_number;
- if (!net::ParseIPLiteralToNumber(kLocalhost, &ip_number))
- return false;
-
- net::IPEndPoint end_point(ip_number, port);
+ net::IPEndPoint end_point(net::IPAddress::IPv4Localhost(), port);
int result = socket_->Listen(end_point, kListenBacklog);
if (result < 0)
return false;
diff --git a/chromium/content/browser/devtools/protocol/tracing_handler.cc b/chromium/content/browser/devtools/protocol/tracing_handler.cc
index 11cc18844ae..e7de4c753ce 100644
--- a/chromium/content/browser/devtools/protocol/tracing_handler.cc
+++ b/chromium/content/browser/devtools/protocol/tracing_handler.cc
@@ -8,14 +8,18 @@
#include "base/bind.h"
#include "base/format_macros.h"
+#include "base/json/json_writer.h"
+#include "base/memory/ref_counted_memory.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event_impl.h"
+#include "base/trace_event/tracing_agent.h"
#include "components/tracing/trace_config_file.h"
#include "content/browser/devtools/devtools_io_context.h"
+#include "content/browser/tracing/tracing_controller_impl.h"
namespace content {
namespace devtools {
@@ -27,6 +31,46 @@ namespace {
const double kMinimumReportingInterval = 250.0;
+const char kRecordModeParam[] = "record_mode";
+
+// Convert from camel case to separator + lowercase.
+std::string ConvertFromCamelCase(const std::string& in_str, char separator) {
+ std::string out_str;
+ out_str.reserve(in_str.size());
+ for (const char& c : in_str) {
+ if (isupper(c)) {
+ out_str.push_back(separator);
+ out_str.push_back(tolower(c));
+ } else {
+ out_str.push_back(c);
+ }
+ }
+ return out_str;
+}
+
+scoped_ptr<base::Value> ConvertDictKeyStyle(const base::Value& value) {
+ const base::DictionaryValue* dict = nullptr;
+ if (value.GetAsDictionary(&dict)) {
+ scoped_ptr<base::DictionaryValue> out_dict(new base::DictionaryValue());
+ for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd();
+ it.Advance()) {
+ out_dict->Set(ConvertFromCamelCase(it.key(), '_'),
+ ConvertDictKeyStyle(it.value()));
+ }
+ return std::move(out_dict);
+ }
+
+ const base::ListValue* list = nullptr;
+ if (value.GetAsList(&list)) {
+ scoped_ptr<base::ListValue> out_list(new base::ListValue());
+ for (const auto& value : *list)
+ out_list->Append(ConvertDictKeyStyle(*value));
+ return std::move(out_list);
+ }
+
+ return value.CreateDeepCopy();
+}
+
class DevToolsTraceSinkProxy : public TracingController::TraceDataSink {
public:
explicit DevToolsTraceSinkProxy(base::WeakPtr<TracingHandler> handler)
@@ -85,9 +129,11 @@ class DevToolsStreamTraceSink : public TracingController::TraceDataSink {
} // namespace
TracingHandler::TracingHandler(TracingHandler::Target target,
+ int frame_tree_node_id,
DevToolsIOContext* io_context)
: target_(target),
io_context_(io_context),
+ frame_tree_node_id_(frame_tree_node_id),
did_initiate_recording_(false),
return_as_stream_(false),
weak_factory_(this) {}
@@ -125,38 +171,46 @@ void TracingHandler::OnTraceToStreamComplete(const std::string& stream_handle) {
TracingCompleteParams::Create()->set_stream(stream_handle));
}
-Response TracingHandler::Start(DevToolsCommandId command_id,
- const std::string* categories,
- const std::string* options,
- const double* buffer_usage_reporting_interval,
- const std::string* transfer_mode) {
+Response TracingHandler::Start(
+ DevToolsCommandId command_id,
+ const std::string* categories,
+ const std::string* options,
+ const double* buffer_usage_reporting_interval,
+ const std::string* transfer_mode,
+ const scoped_ptr<base::DictionaryValue>& config) {
if (IsTracing())
return Response::InternalError("Tracing is already started");
+ if (config && (categories || options)) {
+ return Response::InternalError(
+ "Either trace config (preferred), or categories+options should be "
+ "specified, but not both.");
+ }
+
did_initiate_recording_ = true;
return_as_stream_ =
transfer_mode && *transfer_mode == start::kTransferModeReturnAsStream;
- base::trace_event::TraceConfig trace_config(
- categories ? *categories : std::string(),
- options ? *options : std::string());
if (buffer_usage_reporting_interval)
SetupTimer(*buffer_usage_reporting_interval);
- // If inspected target is a render process Tracing.start will be handled by
- // tracing agent in the renderer.
- if (target_ == Renderer) {
- TracingController::GetInstance()->StartTracing(
- trace_config,
- TracingController::StartTracingDoneCallback());
- return Response::FallThrough();
+ base::trace_event::TraceConfig trace_config;
+ if (config) {
+ trace_config = GetTraceConfigFromDevToolsConfig(*config);
+ } else if (categories || options) {
+ trace_config = base::trace_event::TraceConfig(
+ categories ? *categories : std::string(),
+ options ? *options : std::string());
}
+ // If inspected target is a render process Tracing.start will be handled by
+ // tracing agent in the renderer.
TracingController::GetInstance()->StartTracing(
trace_config,
base::Bind(&TracingHandler::OnRecordingEnabled,
weak_factory_.GetWeakPtr(),
command_id));
- return Response::OK();
+
+ return target_ == Renderer ? Response::FallThrough() : Response::OK();
}
Response TracingHandler::End(DevToolsCommandId command_id) {
@@ -188,7 +242,11 @@ Response TracingHandler::GetCategories(DevToolsCommandId command_id) {
}
void TracingHandler::OnRecordingEnabled(DevToolsCommandId command_id) {
- client_->SendStartResponse(command_id, StartResponse::Create());
+ TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
+ "TracingStartedInBrowser", TRACE_EVENT_SCOPE_THREAD,
+ "frameTreeNodeId", frame_tree_node_id_);
+ if (target_ != Renderer)
+ client_->SendStartResponse(command_id, StartResponse::Create());
}
void TracingHandler::OnBufferUsage(float percent_full,
@@ -233,6 +291,17 @@ void TracingHandler::OnMemoryDumpFinished(DevToolsCommandId command_id,
->set_success(success));
}
+Response TracingHandler::RecordClockSyncMarker(const std::string& sync_id) {
+ if (!IsTracing())
+ return Response::InternalError("Tracing is not started");
+
+ TracingControllerImpl::GetInstance()->RecordClockSyncMarker(
+ sync_id,
+ base::trace_event::TracingAgent::RecordClockSyncMarkerCallback());
+
+ return Response::OK();
+}
+
void TracingHandler::SetupTimer(double usage_reporting_interval) {
if (usage_reporting_interval == 0) return;
@@ -267,6 +336,21 @@ bool TracingHandler::IsStartupTracingActive() {
TracingController::GetInstance()->IsTracing();
}
+// static
+base::trace_event::TraceConfig TracingHandler::GetTraceConfigFromDevToolsConfig(
+ const base::DictionaryValue& devtools_config) {
+ scoped_ptr<base::Value> value = ConvertDictKeyStyle(devtools_config);
+ DCHECK(value && value->IsType(base::Value::TYPE_DICTIONARY));
+ scoped_ptr<base::DictionaryValue> tracing_dict(
+ static_cast<base::DictionaryValue*>(value.release()));
+
+ std::string mode;
+ if (tracing_dict->GetString(kRecordModeParam, &mode))
+ tracing_dict->SetString(kRecordModeParam, ConvertFromCamelCase(mode, '-'));
+
+ return base::trace_event::TraceConfig(*tracing_dict);
+}
+
} // namespace tracing
} // namespace devtools
} // namespace content
diff --git a/chromium/content/browser/devtools/protocol/tracing_handler.h b/chromium/content/browser/devtools/protocol/tracing_handler.h
index f45d7e97c2e..be3e6e412ed 100644
--- a/chromium/content/browser/devtools/protocol/tracing_handler.h
+++ b/chromium/content/browser/devtools/protocol/tracing_handler.h
@@ -11,10 +11,12 @@
#include <set>
#include <string>
+#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/devtools/protocol/devtools_protocol_dispatcher.h"
+#include "content/common/content_export.h"
#include "content/public/browser/tracing_controller.h"
namespace base {
@@ -34,7 +36,9 @@ class TracingHandler {
typedef DevToolsProtocolClient::Response Response;
enum Target { Browser, Renderer };
- TracingHandler(Target target, DevToolsIOContext* io_context);
+ TracingHandler(Target target,
+ int frame_tree_node_id,
+ DevToolsIOContext* io_context);
virtual ~TracingHandler();
void SetClient(scoped_ptr<Client> client);
@@ -49,10 +53,12 @@ class TracingHandler {
const std::string* categories,
const std::string* options,
const double* buffer_usage_reporting_interval,
- const std::string* transfer_mode);
+ const std::string* transfer_mode,
+ const scoped_ptr<base::DictionaryValue>& config);
Response End(DevToolsCommandId command_id);
Response GetCategories(DevToolsCommandId command);
Response RequestMemoryDump(DevToolsCommandId command_id);
+ Response RecordClockSyncMarker(const std::string& sync_id);
bool did_initiate_recording() { return did_initiate_recording_; }
@@ -70,16 +76,22 @@ class TracingHandler {
const scoped_refptr<TracingController::TraceDataSink>& trace_data_sink);
bool IsTracing() const;
static bool IsStartupTracingActive();
+ CONTENT_EXPORT static base::trace_event::TraceConfig
+ GetTraceConfigFromDevToolsConfig(
+ const base::DictionaryValue& devtools_config);
scoped_ptr<base::Timer> buffer_usage_poll_timer_;
Target target_;
scoped_ptr<Client> client_;
DevToolsIOContext* io_context_;
+ int frame_tree_node_id_;
bool did_initiate_recording_;
bool return_as_stream_;
base::WeakPtrFactory<TracingHandler> weak_factory_;
+ FRIEND_TEST_ALL_PREFIXES(TracingHandlerTest,
+ GetTraceConfigFromDevToolsConfig);
DISALLOW_COPY_AND_ASSIGN(TracingHandler);
};
diff --git a/chromium/content/browser/devtools/protocol/tracing_handler_unittest.cc b/chromium/content/browser/devtools/protocol/tracing_handler_unittest.cc
new file mode 100644
index 00000000000..8182f45826f
--- /dev/null
+++ b/chromium/content/browser/devtools/protocol/tracing_handler_unittest.cc
@@ -0,0 +1,73 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/json/json_reader.h"
+#include "base/trace_event/trace_config.h"
+#include "base/values.h"
+#include "content/browser/devtools/protocol/tracing_handler.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace devtools {
+namespace tracing {
+
+namespace {
+
+const char kCustomTraceConfigString[] =
+ "{"
+ "\"enable_argument_filter\":true,"
+ "\"enable_sampling\":true,"
+ "\"enable_systrace\":true,"
+ "\"excluded_categories\":[\"excluded\",\"exc_pattern*\"],"
+ "\"included_categories\":[\"included\","
+ "\"inc_pattern*\","
+ "\"disabled-by-default-cc\","
+ "\"disabled-by-default-memory-infra\"],"
+ "\"memory_dump_config\":{"
+ "\"triggers\":["
+ "{\"mode\":\"light\",\"periodic_interval_ms\":50},"
+ "{\"mode\":\"detailed\",\"periodic_interval_ms\":1000}"
+ "]"
+ "},"
+ "\"record_mode\":\"record-continuously\","
+ "\"synthetic_delays\":[\"test.Delay1;16\",\"test.Delay2;32\"]"
+ "}";
+
+const char kCustomTraceConfigStringDevToolsStyle[] =
+ "{"
+ "\"enableArgumentFilter\":true,"
+ "\"enableSampling\":true,"
+ "\"enableSystrace\":true,"
+ "\"excludedCategories\":[\"excluded\",\"exc_pattern*\"],"
+ "\"includedCategories\":[\"included\","
+ "\"inc_pattern*\","
+ "\"disabled-by-default-cc\","
+ "\"disabled-by-default-memory-infra\"],"
+ "\"memoryDumpConfig\":{"
+ "\"triggers\":["
+ "{\"mode\":\"light\",\"periodicIntervalMs\":50},"
+ "{\"mode\":\"detailed\",\"periodicIntervalMs\":1000}"
+ "]"
+ "},"
+ "\"recordMode\":\"recordContinuously\","
+ "\"synthetic_delays\":[\"test.Delay1;16\",\"test.Delay2;32\"]"
+ "}";
+
+}
+
+TEST(TracingHandlerTest, GetTraceConfigFromDevToolsConfig) {
+ scoped_ptr<base::Value> value = base::JSONReader::Read(
+ kCustomTraceConfigStringDevToolsStyle);
+ scoped_ptr<base::DictionaryValue> devtools_style_dict(
+ static_cast<base::DictionaryValue*>(value.release()));
+
+ base::trace_event::TraceConfig trace_config =
+ TracingHandler::GetTraceConfigFromDevToolsConfig(*devtools_style_dict);
+
+ EXPECT_STREQ(kCustomTraceConfigString, trace_config.ToString().c_str());
+}
+
+} // namespace tracing
+} // namespace devtools
+} // namespace content
diff --git a/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc b/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc
index cb1be38ea98..d9a1a1c0b0d 100644
--- a/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/render_frame_devtools_agent_host.cc
@@ -24,6 +24,7 @@
#include "content/browser/devtools/protocol/tracing_handler.h"
#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/renderer_host/input/input_router_impl.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/site_instance_impl.h"
@@ -47,8 +48,6 @@ typedef std::vector<RenderFrameDevToolsAgentHost*> Instances;
namespace {
base::LazyInstance<Instances>::Leaky g_instances = LAZY_INSTANCE_INITIALIZER;
-bool browser_side_navigation = false;
-
static RenderFrameDevToolsAgentHost* FindAgentHost(RenderFrameHost* host) {
if (g_instances == NULL)
return NULL;
@@ -60,19 +59,24 @@ static RenderFrameDevToolsAgentHost* FindAgentHost(RenderFrameHost* host) {
return NULL;
}
-// Returns RenderFrameDevToolsAgentHost attached to any of RenderFrameHost
-// instances associated with |web_contents|
-static RenderFrameDevToolsAgentHost* FindAgentHost(WebContents* web_contents) {
+static RenderFrameDevToolsAgentHost* FindAgentHost(
+ FrameTreeNode* frame_tree_node) {
if (g_instances == NULL)
return NULL;
for (Instances::iterator it = g_instances.Get().begin();
it != g_instances.Get().end(); ++it) {
- if ((*it)->GetWebContents() == web_contents)
+ if ((*it)->frame_tree_node() == frame_tree_node)
return *it;
}
return NULL;
}
+static RenderFrameDevToolsAgentHost* FindAgentHost(WebContents* web_contents) {
+ if (!web_contents->GetMainFrame())
+ return nullptr;
+ return FindAgentHost(web_contents->GetMainFrame());
+}
+
bool ShouldCreateDevToolsFor(RenderFrameHost* rfh) {
return rfh->IsCrossProcessSubframe() || !rfh->GetParent();
}
@@ -254,16 +258,11 @@ DevToolsAgentHost::GetOrCreateFor(RenderFrameHost* frame_host) {
// static
scoped_refptr<DevToolsAgentHost>
DevToolsAgentHost::GetOrCreateFor(WebContents* web_contents) {
- RenderFrameDevToolsAgentHost* result = FindAgentHost(web_contents);
- if (!result) {
- // TODO(dgozman): this check should not be necessary. See
- // http://crbug.com/489664.
- if (!web_contents->GetMainFrame())
- return nullptr;
- result = new RenderFrameDevToolsAgentHost(
- static_cast<RenderFrameHostImpl*>(web_contents->GetMainFrame()));
- }
- return result;
+ // TODO(dgozman): this check should not be necessary. See
+ // http://crbug.com/489664.
+ if (!web_contents->GetMainFrame())
+ return nullptr;
+ return DevToolsAgentHost::GetOrCreateFor(web_contents->GetMainFrame());
}
// static
@@ -311,7 +310,7 @@ void RenderFrameDevToolsAgentHost::AddAllAgentHosts(
void RenderFrameDevToolsAgentHost::OnCancelPendingNavigation(
RenderFrameHost* pending,
RenderFrameHost* current) {
- if (browser_side_navigation)
+ if (IsBrowserSideNavigationEnabled())
return;
RenderFrameDevToolsAgentHost* agent_host = FindAgentHost(pending);
@@ -331,6 +330,16 @@ void RenderFrameDevToolsAgentHost::OnBeforeNavigation(
agent_host->AboutToNavigateRenderFrame(current, pending);
}
+// static
+void RenderFrameDevToolsAgentHost::OnBeforeNavigation(
+ NavigationHandle* navigation_handle) {
+ FrameTreeNode* frame_tree_node =
+ static_cast<NavigationHandleImpl*>(navigation_handle)->frame_tree_node();
+ RenderFrameDevToolsAgentHost* agent_host = FindAgentHost(frame_tree_node);
+ if (agent_host)
+ agent_host->AboutToNavigate(navigation_handle);
+}
+
RenderFrameDevToolsAgentHost::RenderFrameDevToolsAgentHost(
RenderFrameHostImpl* host)
: dom_handler_(new devtools::dom::DOMHandler()),
@@ -344,15 +353,14 @@ RenderFrameDevToolsAgentHost::RenderFrameDevToolsAgentHost(
new devtools::service_worker::ServiceWorkerHandler()),
tracing_handler_(new devtools::tracing::TracingHandler(
devtools::tracing::TracingHandler::Renderer,
+ host->GetFrameTreeNodeId(),
GetIOContext())),
emulation_handler_(nullptr),
frame_trace_recorder_(nullptr),
protocol_handler_(new DevToolsProtocolHandler(this)),
current_frame_crashed_(false),
pending_handle_(nullptr),
- in_navigation_(0),
frame_tree_node_(host->frame_tree_node()) {
- browser_side_navigation = IsBrowserSideNavigationEnabled();
DevToolsProtocolDispatcher* dispatcher = protocol_handler_->dispatcher();
dispatcher->SetDOMHandler(dom_handler_.get());
dispatcher->SetInputHandler(input_handler_.get());
@@ -454,8 +462,8 @@ bool RenderFrameDevToolsAgentHost::DispatchProtocolMessage(
if (protocol_handler_->HandleOptionalMessage(session_id(), message, &call_id))
return true;
- if (in_navigation_ > 0) {
- DCHECK(browser_side_navigation);
+ if (!navigating_handles_.empty()) {
+ DCHECK(IsBrowserSideNavigationEnabled());
in_navigation_protocol_message_buffer_[call_id] =
std::make_pair(session_id(), message);
return true;
@@ -480,8 +488,7 @@ void RenderFrameDevToolsAgentHost::OnClientAttached() {
return;
frame_trace_recorder_.reset(new DevToolsFrameTraceRecorder());
-
-#if defined(OS_ANDROID) && !defined(USE_AURA)
+#if defined(OS_ANDROID)
power_save_blocker_.reset(static_cast<PowerSaveBlockerImpl*>(
PowerSaveBlocker::Create(
PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
@@ -520,54 +527,49 @@ RenderFrameDevToolsAgentHost::~RenderFrameDevToolsAgentHost() {
g_instances.Get().erase(it);
}
-void RenderFrameDevToolsAgentHost::DidStartNavigation(
- NavigationHandle* navigation_handle) {
- if (!browser_side_navigation)
- return;
- if (!MatchesMyTreeNode(navigation_handle))
- return;
- DCHECK(current_);
- DCHECK(in_navigation_ >= 0);
- ++in_navigation_;
-}
-
void RenderFrameDevToolsAgentHost::ReadyToCommitNavigation(
NavigationHandle* navigation_handle) {
// ReadyToCommitNavigation should only be called in PlzNavigate.
- DCHECK(browser_side_navigation);
-
- if (MatchesMyTreeNode(navigation_handle) && in_navigation_ != 0) {
- RenderFrameHostImpl* render_frame_host_impl =
- static_cast<RenderFrameHostImpl*>(
- navigation_handle->GetRenderFrameHost());
- if (current_->host() != render_frame_host_impl || current_frame_crashed_) {
- SetPending(render_frame_host_impl);
- pending_handle_ = navigation_handle;
- }
+ DCHECK(IsBrowserSideNavigationEnabled());
+
+ // If the navigation is not tracked, return;
+ if (navigating_handles_.count(navigation_handle) == 0)
+ return;
+
+ RenderFrameHostImpl* render_frame_host_impl =
+ static_cast<RenderFrameHostImpl*>(
+ navigation_handle->GetRenderFrameHost());
+ if (current_->host() != render_frame_host_impl || current_frame_crashed_) {
+ SetPending(render_frame_host_impl);
+ pending_handle_ = navigation_handle;
}
}
void RenderFrameDevToolsAgentHost::DidFinishNavigation(
NavigationHandle* navigation_handle) {
- if (!browser_side_navigation)
+ if (!IsBrowserSideNavigationEnabled())
+ return;
+
+ // If the navigation is not tracked, return;
+ if (navigating_handles_.count(navigation_handle) == 0)
return;
- if (MatchesMyTreeNode(navigation_handle) && in_navigation_ != 0) {
- --in_navigation_;
- DCHECK(in_navigation_ >= 0);
- if (pending_handle_ == navigation_handle) {
- // This navigation handle did set the pending FrameHostHolder.
- DCHECK(pending_);
- if (navigation_handle->HasCommitted()) {
- DCHECK(pending_->host() == navigation_handle->GetRenderFrameHost());
- CommitPending();
- } else {
- DiscardPending();
- }
- pending_handle_ = nullptr;
+ // Now that the navigation is finished, remove the handle from the list of
+ // navigating handles.
+ navigating_handles_.erase(navigation_handle);
+
+ if (pending_handle_ == navigation_handle) {
+ // This navigation handle did set the pending FrameHostHolder.
+ DCHECK(pending_);
+ if (navigation_handle->HasCommitted()) {
+ DCHECK(pending_->host() == navigation_handle->GetRenderFrameHost());
+ CommitPending();
+ } else {
+ DiscardPending();
}
- DispatchBufferedProtocolMessagesIfNecessary();
+ pending_handle_ = nullptr;
}
+ DispatchBufferedProtocolMessagesIfNecessary();
if (navigation_handle->HasCommitted())
service_worker_handler_->UpdateHosts();
@@ -576,7 +578,7 @@ void RenderFrameDevToolsAgentHost::DidFinishNavigation(
void RenderFrameDevToolsAgentHost::AboutToNavigateRenderFrame(
RenderFrameHost* old_host,
RenderFrameHost* new_host) {
- if (browser_side_navigation)
+ if (IsBrowserSideNavigationEnabled())
return;
DCHECK(!pending_ || pending_->host() != old_host);
@@ -588,10 +590,18 @@ void RenderFrameDevToolsAgentHost::AboutToNavigateRenderFrame(
SetPending(static_cast<RenderFrameHostImpl*>(new_host));
}
+void RenderFrameDevToolsAgentHost::AboutToNavigate(
+ NavigationHandle* navigation_handle) {
+ if (!IsBrowserSideNavigationEnabled())
+ return;
+ DCHECK(current_);
+ navigating_handles_.insert(navigation_handle);
+}
+
void RenderFrameDevToolsAgentHost::RenderFrameHostChanged(
RenderFrameHost* old_host,
RenderFrameHost* new_host) {
- if (browser_side_navigation)
+ if (IsBrowserSideNavigationEnabled())
return;
DCHECK(!pending_ || pending_->host() != old_host);
@@ -608,7 +618,7 @@ void RenderFrameDevToolsAgentHost::RenderFrameHostChanged(
void RenderFrameDevToolsAgentHost::FrameDeleted(RenderFrameHost* rfh) {
if (pending_ && pending_->host() == rfh) {
- if (!browser_side_navigation)
+ if (!IsBrowserSideNavigationEnabled())
DiscardPending();
return;
}
@@ -671,24 +681,22 @@ bool RenderFrameDevToolsAgentHost::OnMessageReceived(
bool RenderFrameDevToolsAgentHost::OnMessageReceived(
const IPC::Message& message,
RenderFrameHost* render_frame_host) {
- if (message.type() != DevToolsClientMsg_DispatchOnInspectorFrontend::ID)
+ bool is_current = current_ && current_->host() == render_frame_host;
+ bool is_pending = pending_ && pending_->host() == render_frame_host;
+ if (!is_current && !is_pending)
return false;
if (!IsAttached())
return false;
-
- FrameHostHolder* holder = nullptr;
- if (current_ && current_->host() == render_frame_host)
- holder = current_.get();
- if (pending_ && pending_->host() == render_frame_host)
- holder = pending_.get();
- if (!holder)
- return false;
-
- DevToolsClientMsg_DispatchOnInspectorFrontend::Param param;
- if (!DevToolsClientMsg_DispatchOnInspectorFrontend::Read(&message, &param))
- return false;
- holder->ProcessChunkedMessageFromAgent(base::get<0>(param));
- return true;
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(RenderFrameDevToolsAgentHost, message,
+ render_frame_host)
+ IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend,
+ OnDispatchOnInspectorFrontend)
+ IPC_MESSAGE_HANDLER(DevToolsAgentHostMsg_RequestNewWindow,
+ OnRequestNewWindow)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
}
void RenderFrameDevToolsAgentHost::DidAttachInterstitialPage() {
@@ -713,7 +721,7 @@ void RenderFrameDevToolsAgentHost::DidCommitProvisionalLoadForFrame(
RenderFrameHost* render_frame_host,
const GURL& url,
ui::PageTransition transition_type) {
- if (browser_side_navigation)
+ if (IsBrowserSideNavigationEnabled())
return;
if (pending_ && pending_->host() == render_frame_host)
CommitPending();
@@ -726,7 +734,7 @@ void RenderFrameDevToolsAgentHost::DidFailProvisionalLoad(
int error_code,
const base::string16& error_description,
bool was_ignored_by_handler) {
- if (browser_side_navigation)
+ if (IsBrowserSideNavigationEnabled())
return;
if (pending_ && pending_->host() == render_frame_host)
DiscardPending();
@@ -734,7 +742,8 @@ void RenderFrameDevToolsAgentHost::DidFailProvisionalLoad(
void RenderFrameDevToolsAgentHost::
DispatchBufferedProtocolMessagesIfNecessary() {
- if (in_navigation_ == 0 && in_navigation_protocol_message_buffer_.size()) {
+ if (navigating_handles_.empty() &&
+ in_navigation_protocol_message_buffer_.size()) {
DCHECK(current_);
for (const auto& pair : in_navigation_protocol_message_buffer_) {
current_->DispatchProtocolMessage(pair.second.first, pair.first,
@@ -768,7 +777,7 @@ void RenderFrameDevToolsAgentHost::DisconnectWebContents() {
disconnected_->Detach();
frame_tree_node_ = nullptr;
in_navigation_protocol_message_buffer_.clear();
- in_navigation_ = 0;
+ navigating_handles_.clear();
pending_handle_ = nullptr;
WebContentsObserver::Observe(nullptr);
}
@@ -856,6 +865,33 @@ void RenderFrameDevToolsAgentHost::SynchronousSwapCompositorFrame(
}
}
+void RenderFrameDevToolsAgentHost::OnDispatchOnInspectorFrontend(
+ RenderFrameHost* sender,
+ const DevToolsMessageChunk& message) {
+ if (current_ && current_->host() == sender)
+ current_->ProcessChunkedMessageFromAgent(message);
+ else if (pending_ && pending_->host() == sender)
+ pending_->ProcessChunkedMessageFromAgent(message);
+}
+
+void RenderFrameDevToolsAgentHost::OnRequestNewWindow(
+ RenderFrameHost* sender,
+ int new_routing_id) {
+ RenderFrameHostImpl* frame_host = RenderFrameHostImpl::FromID(
+ sender->GetProcess()->GetID(), new_routing_id);
+
+ bool success = false;
+ if (IsAttached() && sender->GetRoutingID() != new_routing_id && frame_host) {
+ scoped_refptr<DevToolsAgentHost> agent =
+ DevToolsAgentHost::GetOrCreateFor(frame_host);
+ success = static_cast<DevToolsAgentHostImpl*>(agent.get())->
+ Inspect(agent->GetBrowserContext());
+ }
+
+ sender->Send(new DevToolsAgentMsg_RequestNewWindow_ACK(
+ sender->GetRoutingID(), success));
+}
+
bool RenderFrameDevToolsAgentHost::HasRenderFrameHost(
RenderFrameHost* host) {
return (current_ && current_->host() == host) ||
@@ -866,11 +902,4 @@ bool RenderFrameDevToolsAgentHost::IsChildFrame() {
return current_ && current_->host()->GetParent();
}
-bool RenderFrameDevToolsAgentHost::MatchesMyTreeNode(
- NavigationHandle* navigation_handle) {
- return frame_tree_node_ ==
- static_cast<NavigationHandleImpl*>(navigation_handle)
- ->frame_tree_node();
-}
-
} // namespace content
diff --git a/chromium/content/browser/devtools/render_frame_devtools_agent_host.h b/chromium/content/browser/devtools/render_frame_devtools_agent_host.h
index 68409344de8..24d05358ad9 100644
--- a/chromium/content/browser/devtools/render_frame_devtools_agent_host.h
+++ b/chromium/content/browser/devtools/render_frame_devtools_agent_host.h
@@ -55,12 +55,15 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
RenderFrameHost* current);
static void OnBeforeNavigation(RenderFrameHost* current,
RenderFrameHost* pending);
+ static void OnBeforeNavigation(NavigationHandle* navigation_handle);
void SynchronousSwapCompositorFrame(
const cc::CompositorFrameMetadata& frame_metadata);
bool HasRenderFrameHost(RenderFrameHost* host);
+ FrameTreeNode* frame_tree_node() { return frame_tree_node_; }
+
// DevTooolsAgentHost overrides.
void DisconnectWebContents() override;
void ConnectWebContents(WebContents* web_contents) override;
@@ -90,7 +93,6 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
void InspectElement(int x, int y) override;
// WebContentsObserver overrides.
- void DidStartNavigation(NavigationHandle* navigation_handle) override;
void ReadyToCommitNavigation(NavigationHandle* navigation_handle) override;
void DidFinishNavigation(NavigationHandle* navigation_handle) override;
void RenderFrameHostChanged(RenderFrameHost* old_host,
@@ -116,6 +118,7 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
void AboutToNavigateRenderFrame(RenderFrameHost* old_host,
RenderFrameHost* new_host);
+ void AboutToNavigate(NavigationHandle* navigation_handle);
void DispatchBufferedProtocolMessagesIfNecessary();
@@ -131,10 +134,12 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
void RenderFrameCrashed();
void OnSwapCompositorFrame(const IPC::Message& message);
+ void OnDispatchOnInspectorFrontend(
+ RenderFrameHost* sender,
+ const DevToolsMessageChunk& message);
+ void OnRequestNewWindow(RenderFrameHost* sender, int new_routing_id);
void DestroyOnRenderFrameGone();
- bool MatchesMyTreeNode(NavigationHandle* navigation_handle);
-
class FrameHostHolder;
scoped_ptr<FrameHostHolder> current_;
@@ -166,9 +171,8 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
// Handle that caused the setting of pending_.
NavigationHandle* pending_handle_;
- // Navigation counter and queue for buffering protocol messages during a
- // navigation.
- int in_navigation_;
+ // List of handles currently navigating.
+ std::set<NavigationHandle*> navigating_handles_;
// <call_id> -> <session_id, message>
std::map<int, std::pair<int, std::string>>
diff --git a/chromium/content/browser/devtools/service_worker_devtools_agent_host.cc b/chromium/content/browser/devtools/service_worker_devtools_agent_host.cc
index 3755d15c51e..33293d52e5b 100644
--- a/chromium/content/browser/devtools/service_worker_devtools_agent_host.cc
+++ b/chromium/content/browser/devtools/service_worker_devtools_agent_host.cc
@@ -109,6 +109,10 @@ int64_t ServiceWorkerDevToolsAgentHost::service_worker_version_id() const {
return service_worker_->version_id();
}
+GURL ServiceWorkerDevToolsAgentHost::scope() const {
+ return service_worker_->scope();
+}
+
bool ServiceWorkerDevToolsAgentHost::Matches(
const ServiceWorkerIdentifier& other) {
return service_worker_->Matches(other);
diff --git a/chromium/content/browser/devtools/service_worker_devtools_agent_host.h b/chromium/content/browser/devtools/service_worker_devtools_agent_host.h
index 89b48b13b1f..a5f15ee7dc8 100644
--- a/chromium/content/browser/devtools/service_worker_devtools_agent_host.h
+++ b/chromium/content/browser/devtools/service_worker_devtools_agent_host.h
@@ -40,6 +40,7 @@ class ServiceWorkerDevToolsAgentHost : public WorkerDevToolsAgentHost {
void OnAttachedStateChanged(bool attached) override;
int64_t service_worker_version_id() const;
+ GURL scope() const;
bool Matches(const ServiceWorkerIdentifier& other);
diff --git a/chromium/content/browser/devtools/service_worker_devtools_manager.cc b/chromium/content/browser/devtools/service_worker_devtools_manager.cc
index b94f1a9e3c2..6796b71db69 100644
--- a/chromium/content/browser/devtools/service_worker_devtools_manager.cc
+++ b/chromium/content/browser/devtools/service_worker_devtools_manager.cc
@@ -16,19 +16,21 @@ ServiceWorkerDevToolsManager::ServiceWorkerIdentifier::ServiceWorkerIdentifier(
const ServiceWorkerContextCore* context,
base::WeakPtr<ServiceWorkerContextCore> context_weak,
int64_t version_id,
- const GURL& url)
+ const GURL& url,
+ const GURL& scope)
: context_(context),
context_weak_(context_weak),
version_id_(version_id),
- url_(url) {}
+ url_(url),
+ scope_(scope) {}
ServiceWorkerDevToolsManager::ServiceWorkerIdentifier::ServiceWorkerIdentifier(
const ServiceWorkerIdentifier& other)
: context_(other.context_),
context_weak_(other.context_weak_),
version_id_(other.version_id_),
- url_(other.url_) {
-}
+ url_(other.url_),
+ scope_(other.scope_) {}
ServiceWorkerDevToolsManager::
ServiceWorkerIdentifier::~ServiceWorkerIdentifier() {
@@ -155,8 +157,6 @@ void ServiceWorkerDevToolsManager::RemoveObserver(Observer* observer) {
void ServiceWorkerDevToolsManager::set_debug_service_worker_on_start(
bool debug_on_start) {
debug_service_worker_on_start_ = debug_on_start;
- FOR_EACH_OBSERVER(Observer, observer_list_,
- DebugOnStartUpdated(debug_on_start));
}
ServiceWorkerDevToolsManager::ServiceWorkerDevToolsManager()
diff --git a/chromium/content/browser/devtools/service_worker_devtools_manager.h b/chromium/content/browser/devtools/service_worker_devtools_manager.h
index 306edd7d3f5..c2cd08e11cc 100644
--- a/chromium/content/browser/devtools/service_worker_devtools_manager.h
+++ b/chromium/content/browser/devtools/service_worker_devtools_manager.h
@@ -35,7 +35,6 @@ class CONTENT_EXPORT ServiceWorkerDevToolsManager {
virtual void WorkerReadyForInspection(
ServiceWorkerDevToolsAgentHost* host) {}
virtual void WorkerDestroyed(ServiceWorkerDevToolsAgentHost* host) {}
- virtual void DebugOnStartUpdated(bool debug_on_start) {}
protected:
virtual ~Observer() {}
@@ -47,7 +46,8 @@ class CONTENT_EXPORT ServiceWorkerDevToolsManager {
const ServiceWorkerContextCore* context,
base::WeakPtr<ServiceWorkerContextCore> context_weak,
int64_t version_id,
- const GURL& url);
+ const GURL& url,
+ const GURL& scope);
ServiceWorkerIdentifier(const ServiceWorkerIdentifier& other);
~ServiceWorkerIdentifier();
@@ -59,12 +59,14 @@ class CONTENT_EXPORT ServiceWorkerDevToolsManager {
}
int64_t version_id() const { return version_id_; }
GURL url() const { return url_; }
+ GURL scope() const { return scope_; }
private:
const ServiceWorkerContextCore* const context_;
const base::WeakPtr<ServiceWorkerContextCore> context_weak_;
const int64_t version_id_;
const GURL url_;
+ const GURL scope_;
};
// Returns the ServiceWorkerDevToolsManager singleton.
diff --git a/chromium/content/browser/devtools/shared_worker_devtools_manager_unittest.cc b/chromium/content/browser/devtools/shared_worker_devtools_manager_unittest.cc
index 98a715220b0..c6f86d5fc23 100644
--- a/chromium/content/browser/devtools/shared_worker_devtools_manager_unittest.cc
+++ b/chromium/content/browser/devtools/shared_worker_devtools_manager_unittest.cc
@@ -102,7 +102,7 @@ TEST_F(SharedWorkerDevToolsManagerTest, BasicTest) {
SharedWorkerInstance instance1(
GURL("http://example.com/w.js"), base::string16(), base::string16(),
- blink::WebContentSecurityPolicyTypeReport,
+ blink::WebContentSecurityPolicyTypeReport, blink::WebAddressSpacePublic,
browser_context_->GetResourceContext(), partition_id_,
blink::WebSharedWorkerCreationContextTypeNonsecure);
@@ -184,12 +184,12 @@ TEST_F(SharedWorkerDevToolsManagerTest, AttachTest) {
SharedWorkerInstance instance1(
GURL("http://example.com/w1.js"), base::string16(), base::string16(),
- blink::WebContentSecurityPolicyTypeReport,
+ blink::WebContentSecurityPolicyTypeReport, blink::WebAddressSpacePublic,
browser_context_->GetResourceContext(), partition_id_,
blink::WebSharedWorkerCreationContextTypeNonsecure);
SharedWorkerInstance instance2(
GURL("http://example.com/w2.js"), base::string16(), base::string16(),
- blink::WebContentSecurityPolicyTypeReport,
+ blink::WebContentSecurityPolicyTypeReport, blink::WebAddressSpacePublic,
browser_context_->GetResourceContext(), partition_id_,
blink::WebSharedWorkerCreationContextTypeNonsecure);
@@ -267,7 +267,7 @@ TEST_F(SharedWorkerDevToolsManagerTest, AttachTest) {
TEST_F(SharedWorkerDevToolsManagerTest, ReattachTest) {
SharedWorkerInstance instance(
GURL("http://example.com/w3.js"), base::string16(), base::string16(),
- blink::WebContentSecurityPolicyTypeReport,
+ blink::WebContentSecurityPolicyTypeReport, blink::WebAddressSpacePublic,
browser_context_->GetResourceContext(), partition_id_,
blink::WebSharedWorkerCreationContextTypeNonsecure);
scoped_ptr<TestDevToolsClientHost> client_host(new TestDevToolsClientHost());
diff --git a/chromium/content/browser/devtools/site_per_process_devtools_browsertest.cc b/chromium/content/browser/devtools/site_per_process_devtools_browsertest.cc
index cfa2b4a1042..e3c3cf222bc 100644
--- a/chromium/content/browser/devtools/site_per_process_devtools_browsertest.cc
+++ b/chromium/content/browser/devtools/site_per_process_devtools_browsertest.cc
@@ -23,7 +23,7 @@ class SitePerProcessDevToolsBrowserTest
class TestClient: public DevToolsAgentHostClient {
public:
- TestClient() : closed_(false) {}
+ TestClient() : closed_(false), waiting_for_reply_(false) {}
~TestClient() override {}
bool closed() { return closed_; }
@@ -31,6 +31,10 @@ class TestClient: public DevToolsAgentHostClient {
void DispatchProtocolMessage(
DevToolsAgentHost* agent_host,
const std::string& message) override {
+ if (waiting_for_reply_) {
+ waiting_for_reply_ = false;
+ base::MessageLoop::current()->QuitNow();
+ }
}
void AgentHostClosed(
@@ -39,8 +43,14 @@ class TestClient: public DevToolsAgentHostClient {
closed_ = true;
}
+ void WaitForReply() {
+ waiting_for_reply_ = true;
+ base::MessageLoop::current()->Run();
+ }
+
private:
bool closed_;
+ bool waiting_for_reply_;
};
// Fails on Android, http://crbug.com/464993.
@@ -90,10 +100,20 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsBrowserTest,
EXPECT_EQ(DevToolsAgentHost::TYPE_FRAME, list[1]->GetType());
EXPECT_EQ(cross_site_url.spec(), list[1]->GetURL().spec());
- // Attaching to child frame.
+ // Attaching to both agent hosts.
scoped_refptr<DevToolsAgentHost> child_host = list[1];
- TestClient client;
- child_host->AttachClient(&client);
+ TestClient child_client;
+ child_host->AttachClient(&child_client);
+ scoped_refptr<DevToolsAgentHost> parent_host = list[0];
+ TestClient parent_client;
+ parent_host->AttachClient(&parent_client);
+
+ // Send message to parent and child frames and get result back.
+ char message[] = "{\"id\": 0, \"method\": \"incorrect.method\"}";
+ child_host->DispatchProtocolMessage(message);
+ child_client.WaitForReply();
+ parent_host->DispatchProtocolMessage(message);
+ parent_client.WaitForReply();
// Load back same-site page into iframe.
NavigateFrameToURL(root->child_at(0), http_url);
@@ -102,9 +122,12 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsBrowserTest,
EXPECT_EQ(1U, list.size());
EXPECT_EQ(DevToolsAgentHost::TYPE_WEB_CONTENTS, list[0]->GetType());
EXPECT_EQ(main_url.spec(), list[0]->GetURL().spec());
- EXPECT_TRUE(client.closed());
+ EXPECT_TRUE(child_client.closed());
child_host->DetachClient();
child_host = nullptr;
+ EXPECT_FALSE(parent_client.closed());
+ parent_host->DetachClient();
+ parent_host = nullptr;
}
IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsBrowserTest, AgentHostForFrames) {
@@ -145,4 +168,36 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsBrowserTest, AgentHostForFrames) {
EXPECT_NE(page_agent.get(), child_frame_agent.get());
}
+IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsBrowserTest,
+ AgentHostForPageEqualsOneForMainFrame) {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html"));
+ NavigateToURL(shell(), main_url);
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root =
+ static_cast<WebContentsImpl*>(shell()->web_contents())->
+ GetFrameTree()->root();
+ FrameTreeNode* child = root->child_at(0);
+
+ // Load cross-site page into iframe.
+ GURL::Replacements replace_host;
+ GURL cross_site_url(embedded_test_server()->GetURL("/title2.html"));
+ replace_host.SetHostStr("foo.com");
+ cross_site_url = cross_site_url.ReplaceComponents(replace_host);
+ NavigateFrameToURL(child, cross_site_url);
+
+ // First ask for child frame, then for main frame.
+ scoped_refptr<DevToolsAgentHost> child_frame_agent =
+ DevToolsAgentHost::GetOrCreateFor(child->current_frame_host());
+ scoped_refptr<DevToolsAgentHost> main_frame_agent =
+ DevToolsAgentHost::GetOrCreateFor(root->current_frame_host());
+ EXPECT_NE(main_frame_agent.get(), child_frame_agent.get());
+
+ // Agent for web contents should be the the main frame's one.
+ scoped_refptr<DevToolsAgentHost> page_agent =
+ DevToolsAgentHost::GetOrCreateFor(shell()->web_contents());
+ EXPECT_EQ(page_agent.get(), main_frame_agent.get());
+}
+
} // namespace content
diff --git a/chromium/content/browser/dom_storage/dom_storage_browsertest.cc b/chromium/content/browser/dom_storage/dom_storage_browsertest.cc
index b0c1c63d65f..9fc8c417dc9 100644
--- a/chromium/content/browser/dom_storage/dom_storage_browsertest.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_browsertest.cc
@@ -9,7 +9,6 @@
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
-#include "net/base/net_util.h"
namespace content {
diff --git a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc
index db486f35e36..b0ec4d5ab65 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.cc
@@ -11,15 +11,23 @@
#include "base/bind_helpers.h"
#include "base/files/file_path.h"
#include "base/location.h"
+#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/thread_task_runner_handle.h"
+#include "components/filesystem/public/interfaces/directory.mojom.h"
+#include "components/leveldb/public/interfaces/leveldb.mojom.h"
+#include "components/profile_service/public/interfaces/profile.mojom.h"
#include "content/browser/dom_storage/dom_storage_area.h"
#include "content/browser/dom_storage/dom_storage_context_impl.h"
#include "content/browser/dom_storage/dom_storage_task_runner.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
+#include "content/browser/leveldb_wrapper_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/local_storage_usage_info.h"
+#include "content/public/browser/mojo_app_connection.h"
#include "content/public/browser/session_storage_usage_info.h"
+#include "mojo/common/common_type_converters.h"
namespace content {
namespace {
@@ -65,9 +73,175 @@ void GetSessionStorageUsageHelper(
} // namespace
+// Used for mojo-based LocalStorage implementation (behind --mojo-local-storage
+// for now).
+class DOMStorageContextWrapper::MojoState {
+ public:
+ MojoState(const std::string& mojo_user_id, const base::FilePath& subdirectory)
+ : mojo_user_id_(mojo_user_id),
+ subdirectory_(subdirectory),
+ connection_state_(NO_CONNECTION),
+ weak_ptr_factory_(this) {}
+
+ void OpenLocalStorage(const url::Origin& origin,
+ mojom::LevelDBObserverPtr observer,
+ mojom::LevelDBWrapperRequest request);
+
+ private:
+ void OnLevelDDWrapperHasNoBindings(const url::Origin& origin) {
+ DCHECK(level_db_wrappers_.find(origin) != level_db_wrappers_.end());
+ level_db_wrappers_.erase(origin);
+ }
+
+ // Part of our asynchronous directory opening called from OpenLocalStorage().
+ void OnDirectoryOpened(filesystem::FileError err);
+ void OnDatabaseOpened(leveldb::DatabaseError status);
+
+ // The (possibly delayed) implementation of OpenLocalStorage(). Can be called
+ // directly from that function, or through |on_database_open_callbacks_|.
+ void BindLocalStorage(const url::Origin& origin,
+ mojom::LevelDBObserverPtr observer,
+ mojom::LevelDBWrapperRequest request);
+
+ // Maps between an origin and its prefixed LevelDB view.
+ std::map<url::Origin, scoped_ptr<LevelDBWrapperImpl>> level_db_wrappers_;
+
+ std::string mojo_user_id_;
+ base::FilePath subdirectory_;
+
+ enum ConnectionState {
+ NO_CONNECTION,
+ CONNECTION_IN_PROGRESS,
+ CONNECTION_FINISHED
+ } connection_state_;
+
+ scoped_ptr<MojoAppConnection> profile_app_connection_;
+ profile::ProfileServicePtr profile_service_;
+ filesystem::DirectoryPtr directory_;
+
+ leveldb::LevelDBServicePtr leveldb_service_;
+ leveldb::LevelDBDatabasePtr database_;
+
+ std::vector<base::Closure> on_database_opened_callbacks_;
+
+ base::WeakPtrFactory<MojoState> weak_ptr_factory_;
+};
+
+void DOMStorageContextWrapper::MojoState::OpenLocalStorage(
+ const url::Origin& origin,
+ mojom::LevelDBObserverPtr observer,
+ mojom::LevelDBWrapperRequest request) {
+ // If we don't have a filesystem_connection_, we'll need to establish one.
+ if (connection_state_ == NO_CONNECTION) {
+ profile_app_connection_ = MojoAppConnection::Create(
+ mojo_user_id_, "mojo:profile", kBrowserMojoAppUrl);
+
+ connection_state_ = CONNECTION_IN_PROGRESS;
+
+ if (!subdirectory_.empty()) {
+ // We were given a subdirectory to write to. Get it and use a disk backed
+ // database.
+ profile_app_connection_->GetInterface(&profile_service_);
+ profile_service_->GetSubDirectory(
+ mojo::String::From(subdirectory_.AsUTF8Unsafe()),
+ GetProxy(&directory_),
+ base::Bind(&MojoState::OnDirectoryOpened,
+ weak_ptr_factory_.GetWeakPtr()));
+ } else {
+ // We were not given a subdirectory. Use a memory backed database.
+ profile_app_connection_->GetInterface(&leveldb_service_);
+ leveldb_service_->OpenInMemory(
+ GetProxy(&database_),
+ base::Bind(&MojoState::OnDatabaseOpened,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+ }
+
+ if (connection_state_ == CONNECTION_IN_PROGRESS) {
+ // Queue this OpenLocalStorage call for when we have a level db pointer.
+ on_database_opened_callbacks_.push_back(
+ base::Bind(&MojoState::BindLocalStorage, weak_ptr_factory_.GetWeakPtr(),
+ origin, base::Passed(&observer), base::Passed(&request)));
+ return;
+ }
+
+ BindLocalStorage(origin, std::move(observer), std::move(request));
+}
+
+void DOMStorageContextWrapper::MojoState::OnDirectoryOpened(
+ filesystem::FileError err) {
+ if (err != filesystem::FileError::OK) {
+ // We failed to open the directory; continue with startup so that we create
+ // the |level_db_wrappers_|.
+ OnDatabaseOpened(leveldb::DatabaseError::IO_ERROR);
+ return;
+ }
+
+ // Now that we have a directory, connect to the LevelDB service and get our
+ // database.
+ profile_app_connection_->GetInterface(&leveldb_service_);
+
+ leveldb_service_->Open(
+ std::move(directory_), "leveldb", GetProxy(&database_),
+ base::Bind(&MojoState::OnDatabaseOpened, weak_ptr_factory_.GetWeakPtr()));
+}
+
+void DOMStorageContextWrapper::MojoState::OnDatabaseOpened(
+ leveldb::DatabaseError status) {
+ if (status != leveldb::DatabaseError::OK) {
+ // If we failed to open the database, reset the service object so we pass
+ // null pointers to our wrappers.
+ database_.reset();
+ leveldb_service_.reset();
+ }
+
+ // We no longer need the profile service; we've either transferred
+ // |directory_| to the leveldb service, or we got a file error and no more is
+ // possible.
+ directory_.reset();
+ profile_service_.reset();
+
+ // |leveldb_| should be known to either be valid or invalid by now. Run our
+ // delayed bindings.
+ connection_state_ = CONNECTION_FINISHED;
+ for (size_t i = 0; i < on_database_opened_callbacks_.size(); ++i)
+ on_database_opened_callbacks_[i].Run();
+ on_database_opened_callbacks_.clear();
+}
+
+void DOMStorageContextWrapper::MojoState::BindLocalStorage(
+ const url::Origin& origin,
+ mojom::LevelDBObserverPtr observer,
+ mojom::LevelDBWrapperRequest request) {
+ auto found = level_db_wrappers_.find(origin);
+ if (found == level_db_wrappers_.end()) {
+ level_db_wrappers_[origin] = make_scoped_ptr(new LevelDBWrapperImpl(
+ database_.get(),
+ origin.Serialize(),
+ kPerStorageAreaQuota + kPerStorageAreaOverQuotaAllowance,
+ base::Bind(&MojoState::OnLevelDDWrapperHasNoBindings,
+ base::Unretained(this),
+ origin)));
+ found = level_db_wrappers_.find(origin);
+ }
+
+ found->second->Bind(std::move(request));
+ found->second->AddObserver(std::move(observer));
+}
+
DOMStorageContextWrapper::DOMStorageContextWrapper(
- const base::FilePath& data_path,
+ const std::string& mojo_user_id,
+ const base::FilePath& profile_path,
+ const base::FilePath& local_partition_path,
storage::SpecialStoragePolicy* special_storage_policy) {
+ base::FilePath storage_dir;
+ if (!profile_path.empty())
+ storage_dir = local_partition_path.AppendASCII(kLocalStorageDirectory);
+ mojo_state_.reset(new MojoState(mojo_user_id, storage_dir));
+
+ base::FilePath data_path;
+ if (!profile_path.empty())
+ data_path = profile_path.Append(local_partition_path);
base::SequencedWorkerPool* worker_pool = BrowserThread::GetBlockingPool();
context_ = new DOMStorageContextImpl(
data_path.empty() ? data_path
@@ -83,8 +257,7 @@ DOMStorageContextWrapper::DOMStorageContextWrapper(
.get()));
}
-DOMStorageContextWrapper::~DOMStorageContextWrapper() {
-}
+DOMStorageContextWrapper::~DOMStorageContextWrapper() {}
void DOMStorageContextWrapper::GetLocalStorageUsage(
const GetLocalStorageUsageCallback& callback) {
@@ -92,7 +265,8 @@ void DOMStorageContextWrapper::GetLocalStorageUsage(
context_->task_runner()->PostShutdownBlockingTask(
FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
base::Bind(&GetLocalStorageUsageHelper,
- base::ThreadTaskRunnerHandle::Get(), context_, callback));
+ base::RetainedRef(base::ThreadTaskRunnerHandle::Get()),
+ base::RetainedRef(context_), callback));
}
void DOMStorageContextWrapper::GetSessionStorageUsage(
@@ -101,7 +275,8 @@ void DOMStorageContextWrapper::GetSessionStorageUsage(
context_->task_runner()->PostShutdownBlockingTask(
FROM_HERE, DOMStorageTaskRunner::PRIMARY_SEQUENCE,
base::Bind(&GetSessionStorageUsageHelper,
- base::ThreadTaskRunnerHandle::Get(), context_, callback));
+ base::RetainedRef(base::ThreadTaskRunnerHandle::Get()),
+ base::RetainedRef(context_), callback));
}
void DOMStorageContextWrapper::DeleteLocalStorage(const GURL& origin) {
@@ -153,6 +328,7 @@ void DOMStorageContextWrapper::SetForceKeepSessionState() {
void DOMStorageContextWrapper::Shutdown() {
DCHECK(context_.get());
+ mojo_state_.reset();
context_->task_runner()->PostShutdownBlockingTask(
FROM_HERE,
DOMStorageTaskRunner::PRIMARY_SEQUENCE,
@@ -166,4 +342,12 @@ void DOMStorageContextWrapper::Flush() {
base::Bind(&DOMStorageContextImpl::Flush, context_));
}
+void DOMStorageContextWrapper::OpenLocalStorage(
+ const url::Origin& origin,
+ mojom::LevelDBObserverPtr observer,
+ mojom::LevelDBWrapperRequest request) {
+ mojo_state_->OpenLocalStorage(
+ origin, std::move(observer), std::move(request));
+}
+
} // namespace content
diff --git a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.h b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.h
index 53033447ca1..56196a1f997 100644
--- a/chromium/content/browser/dom_storage/dom_storage_context_wrapper.h
+++ b/chromium/content/browser/dom_storage/dom_storage_context_wrapper.h
@@ -5,12 +5,15 @@
#ifndef CONTENT_BROWSER_DOM_STORAGE_DOM_STORAGE_CONTEXT_WRAPPER_H_
#define CONTENT_BROWSER_DOM_STORAGE_DOM_STORAGE_CONTEXT_WRAPPER_H_
+#include <map>
#include <string>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
+#include "content/common/storage_partition_service.mojom.h"
#include "content/public/browser/dom_storage_context.h"
+#include "url/origin.h"
namespace base {
class FilePath;
@@ -23,16 +26,19 @@ class SpecialStoragePolicy;
namespace content {
class DOMStorageContextImpl;
+class LevelDBWrapperImpl;
-// This is owned by BrowserContext (aka Profile) and encapsulates all
-// per-profile dom storage state.
+// This is owned by Storage Partition and encapsulates all its dom storage
+// state.
class CONTENT_EXPORT DOMStorageContextWrapper :
NON_EXPORTED_BASE(public DOMStorageContext),
public base::RefCountedThreadSafe<DOMStorageContextWrapper> {
public:
// If |data_path| is empty, nothing will be saved to disk.
DOMStorageContextWrapper(
+ const std::string& mojo_user_id,
const base::FilePath& data_path,
+ const base::FilePath& local_partition_path,
storage::SpecialStoragePolicy* special_storage_policy);
// DOMStorageContext implementation.
@@ -58,6 +64,11 @@ class CONTENT_EXPORT DOMStorageContextWrapper :
void Flush();
+ // See mojom::StoragePartitionService interface.
+ void OpenLocalStorage(const url::Origin& origin,
+ mojom::LevelDBObserverPtr observer,
+ mojom::LevelDBWrapperRequest request);
+
private:
friend class DOMStorageMessageFilter; // for access to context()
friend class SessionStorageNamespaceImpl; // ditto
@@ -66,6 +77,11 @@ class CONTENT_EXPORT DOMStorageContextWrapper :
~DOMStorageContextWrapper() override;
DOMStorageContextImpl* context() const { return context_.get(); }
+ // An inner class to keep all mojo-ish details together and not bleed them
+ // through the public interface.
+ class MojoState;
+ scoped_ptr<MojoState> mojo_state_;
+
scoped_refptr<DOMStorageContextImpl> context_;
DISALLOW_IMPLICIT_CONSTRUCTORS(DOMStorageContextWrapper);
diff --git a/chromium/content/browser/dom_storage/dom_storage_host.cc b/chromium/content/browser/dom_storage/dom_storage_host.cc
index 14d288d8653..3db7d5a15ec 100644
--- a/chromium/content/browser/dom_storage/dom_storage_host.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_host.cc
@@ -153,6 +153,8 @@ DOMStorageNamespace* DOMStorageHost::GetNamespace(int connection_id) {
// NamespaceAndArea
DOMStorageHost::NamespaceAndArea::NamespaceAndArea() {}
+DOMStorageHost::NamespaceAndArea::NamespaceAndArea(
+ const NamespaceAndArea& other) = default;
DOMStorageHost::NamespaceAndArea::~NamespaceAndArea() {}
} // namespace content
diff --git a/chromium/content/browser/dom_storage/dom_storage_host.h b/chromium/content/browser/dom_storage/dom_storage_host.h
index 9b79406cbd2..d53bd154eec 100644
--- a/chromium/content/browser/dom_storage/dom_storage_host.h
+++ b/chromium/content/browser/dom_storage/dom_storage_host.h
@@ -57,6 +57,7 @@ class CONTENT_EXPORT DOMStorageHost {
scoped_refptr<DOMStorageNamespace> namespace_;
scoped_refptr<DOMStorageArea> area_;
NamespaceAndArea();
+ NamespaceAndArea(const NamespaceAndArea& other);
~NamespaceAndArea();
};
typedef std::map<int, NamespaceAndArea > AreaMap;
diff --git a/chromium/content/browser/dom_storage/dom_storage_namespace.cc b/chromium/content/browser/dom_storage/dom_storage_namespace.cc
index 25e44e53e3f..a8681b6e6c2 100644
--- a/chromium/content/browser/dom_storage/dom_storage_namespace.cc
+++ b/chromium/content/browser/dom_storage/dom_storage_namespace.cc
@@ -195,6 +195,8 @@ DOMStorageNamespace::AreaHolder::AreaHolder(
: area_(area), open_count_(count) {
}
+DOMStorageNamespace::AreaHolder::AreaHolder(const AreaHolder& other) = default;
+
DOMStorageNamespace::AreaHolder::~AreaHolder() {
}
diff --git a/chromium/content/browser/dom_storage/dom_storage_namespace.h b/chromium/content/browser/dom_storage/dom_storage_namespace.h
index a9f65693fe8..238b7ca554e 100644
--- a/chromium/content/browser/dom_storage/dom_storage_namespace.h
+++ b/chromium/content/browser/dom_storage/dom_storage_namespace.h
@@ -86,6 +86,7 @@ class CONTENT_EXPORT DOMStorageNamespace
int open_count_;
AreaHolder();
AreaHolder(DOMStorageArea* area, int count);
+ AreaHolder(const AreaHolder& other);
~AreaHolder();
};
typedef std::map<GURL, AreaHolder> AreaMap;
diff --git a/chromium/content/browser/dom_storage/session_storage_database.cc b/chromium/content/browser/dom_storage/session_storage_database.cc
index ec246164e34..0aea7c7cc34 100644
--- a/chromium/content/browser/dom_storage/session_storage_database.cc
+++ b/chromium/content/browser/dom_storage/session_storage_database.cc
@@ -383,6 +383,9 @@ leveldb::Status SessionStorageDatabase::TryToOpen(leveldb::DB** db) {
options.max_open_files = 0; // Use minimum.
options.create_if_missing = true;
options.reuse_logs = leveldb_env::kDefaultLogReuseOptionValue;
+ // Default write_buffer_size is 4 MB but that might leave a 3.999
+ // memory allocation in RAM from a log file recovery.
+ options.write_buffer_size = 64 * 1024;
return leveldb::DB::Open(options, file_path_.AsUTF8Unsafe(), db);
}
diff --git a/chromium/content/browser/download/OWNERS b/chromium/content/browser/download/OWNERS
index 9e1fc0676f3..27f3217e697 100644
--- a/chromium/content/browser/download/OWNERS
+++ b/chromium/content/browser/download/OWNERS
@@ -1,4 +1,2 @@
-ahendrickson@chromium.org
asanka@chromium.org
-phajdan.jr@chromium.org
rdsmith@chromium.org
diff --git a/chromium/content/browser/download/base_file.cc b/chromium/content/browser/download/base_file.cc
index 8fda8de6a5c..74072bb1f72 100644
--- a/chromium/content/browser/download/base_file.cc
+++ b/chromium/content/browser/download/base_file.cc
@@ -25,38 +25,8 @@
namespace content {
-// This will initialize the entire array to zero.
-const unsigned char BaseFile::kEmptySha256Hash[] = { 0 };
-
-BaseFile::BaseFile(const base::FilePath& full_path,
- const GURL& source_url,
- const GURL& referrer_url,
- int64_t received_bytes,
- bool calculate_hash,
- const std::string& hash_state_bytes,
- base::File file,
- const net::BoundNetLog& bound_net_log)
- : full_path_(full_path),
- source_url_(source_url),
- referrer_url_(referrer_url),
- file_(std::move(file)),
- bytes_so_far_(received_bytes),
- start_tick_(base::TimeTicks::Now()),
- calculate_hash_(calculate_hash),
- detached_(false),
- bound_net_log_(bound_net_log) {
- memcpy(sha256_hash_, kEmptySha256Hash, crypto::kSHA256Length);
- if (calculate_hash_) {
- secure_hash_.reset(crypto::SecureHash::Create(crypto::SecureHash::SHA256));
- if ((bytes_so_far_ > 0) && // Not starting at the beginning.
- (!IsEmptyHash(hash_state_bytes))) {
- base::Pickle hash_state(hash_state_bytes.c_str(),
- hash_state_bytes.size());
- base::PickleIterator data_iterator(hash_state);
- secure_hash_->Deserialize(&data_iterator);
- }
- }
-}
+BaseFile::BaseFile(const net::BoundNetLog& bound_net_log)
+ : bound_net_log_(bound_net_log) {}
BaseFile::~BaseFile() {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
@@ -67,11 +37,16 @@ BaseFile::~BaseFile() {
}
DownloadInterruptReason BaseFile::Initialize(
- const base::FilePath& default_directory) {
+ const base::FilePath& full_path,
+ const base::FilePath& default_directory,
+ base::File file,
+ int64_t bytes_so_far,
+ const std::string& hash_so_far,
+ scoped_ptr<crypto::SecureHash> hash_state) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
DCHECK(!detached_);
- if (full_path_.empty()) {
+ if (full_path.empty()) {
base::FilePath initial_directory(default_directory);
base::FilePath temp_file;
if (initial_directory.empty()) {
@@ -87,9 +62,15 @@ DownloadInterruptReason BaseFile::Initialize(
DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
}
full_path_ = temp_file;
+ } else {
+ full_path_ = full_path;
}
- return Open();
+ bytes_so_far_ = bytes_so_far;
+ secure_hash_ = std::move(hash_state);
+ file_ = std::move(file);
+
+ return Open(hash_so_far);
}
DownloadInterruptReason BaseFile::AppendDataToFile(const char* data,
@@ -134,7 +115,7 @@ DownloadInterruptReason BaseFile::AppendDataToFile(const char* data,
RecordDownloadWriteSize(data_len);
RecordDownloadWriteLoopCount(write_count);
- if (calculate_hash_)
+ if (secure_hash_)
secure_hash_->Update(data, data_len);
return DOWNLOAD_INTERRUPT_REASON_NONE;
@@ -170,7 +151,7 @@ DownloadInterruptReason BaseFile::Rename(const base::FilePath& new_path) {
// reason.
DownloadInterruptReason open_result = DOWNLOAD_INTERRUPT_REASON_NONE;
if (was_in_progress)
- open_result = Open();
+ open_result = Open(std::string());
bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_FILE_RENAMED);
return rename_result == DOWNLOAD_INTERRUPT_REASON_NONE ? open_result
@@ -198,92 +179,127 @@ void BaseFile::Cancel() {
Detach();
}
-void BaseFile::Finish() {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
-
- if (calculate_hash_)
- secure_hash_->Finish(sha256_hash_, crypto::kSHA256Length);
- Close();
-}
-
-void BaseFile::FinishWithError() {
+scoped_ptr<crypto::SecureHash> BaseFile::Finish() {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
Close();
-}
-
-void BaseFile::SetClientGuid(const std::string& guid) {
- client_guid_ = guid;
+ return std::move(secure_hash_);
}
// OS_WIN, OS_MACOSX and OS_LINUX have specialized implementations.
#if !defined(OS_WIN) && !defined(OS_MACOSX) && !defined(OS_LINUX)
-DownloadInterruptReason BaseFile::AnnotateWithSourceInformation() {
+DownloadInterruptReason BaseFile::AnnotateWithSourceInformation(
+ const std::string& client_guid,
+ const GURL& source_url,
+ const GURL& referrer_url) {
return DOWNLOAD_INTERRUPT_REASON_NONE;
}
#endif
-bool BaseFile::GetHash(std::string* hash) {
- DCHECK(!detached_);
- hash->assign(reinterpret_cast<const char*>(sha256_hash_),
- sizeof(sha256_hash_));
- return (calculate_hash_ && !in_progress());
+std::string BaseFile::DebugString() const {
+ return base::StringPrintf(
+ "{ "
+ " full_path_ = \"%" PRFilePath
+ "\""
+ " bytes_so_far_ = %" PRId64 " detached_ = %c }",
+ full_path_.value().c_str(),
+ bytes_so_far_,
+ detached_ ? 'T' : 'F');
}
-std::string BaseFile::GetHashState() {
- if (!calculate_hash_)
- return std::string();
+DownloadInterruptReason BaseFile::CalculatePartialHash(
+ const std::string& hash_to_expect) {
+ secure_hash_.reset(crypto::SecureHash::Create(crypto::SecureHash::SHA256));
- base::Pickle hash_state;
- if (!secure_hash_->Serialize(&hash_state))
- return std::string();
+ if (bytes_so_far_ == 0)
+ return DOWNLOAD_INTERRUPT_REASON_NONE;
- return std::string(reinterpret_cast<const char*>(hash_state.data()),
- hash_state.size());
-}
+ if (file_.Seek(base::File::FROM_BEGIN, 0) != 0)
+ return LogSystemError("Seek partial file",
+ logging::GetLastSystemErrorCode());
+
+ const size_t kMinBufferSize = secure_hash_->GetHashLength();
+ const size_t kMaxBufferSize = 1024 * 512;
+
+ // The size of the buffer is:
+ // - at least kMinBufferSize so that we can use it to hold the hash as well.
+ // - at most kMaxBufferSize so that there's a reasonable bound.
+ // - not larger than |bytes_so_far_| unless bytes_so_far_ is less than the
+ // hash size.
+ std::vector<char> buffer(std::max(
+ kMinBufferSize, std::min<size_t>(kMaxBufferSize, bytes_so_far_)));
+
+ int64_t current_position = 0;
+ while (current_position < bytes_so_far_) {
+ int length = file_.ReadAtCurrentPos(&buffer.front(), buffer.size());
+ if (length == -1) {
+ return LogInterruptReason("Reading partial file",
+ logging::GetLastSystemErrorCode(),
+ DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT);
+ }
-// static
-bool BaseFile::IsEmptyHash(const std::string& hash) {
- return (hash.size() == crypto::kSHA256Length &&
- 0 == memcmp(hash.data(), kEmptySha256Hash, crypto::kSHA256Length));
-}
+ if (length == 0)
+ break;
-std::string BaseFile::DebugString() const {
- return base::StringPrintf("{ source_url_ = \"%s\""
- " full_path_ = \"%" PRFilePath "\""
- " bytes_so_far_ = %" PRId64
- " detached_ = %c }",
- source_url_.spec().c_str(),
- full_path_.value().c_str(),
- bytes_so_far_,
- detached_ ? 'T' : 'F');
+ secure_hash_->Update(&buffer.front(), length);
+ current_position += length;
+ }
+
+ if (current_position != bytes_so_far_) {
+ return LogInterruptReason(
+ "Verifying prefix hash", 0, DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT);
+ }
+
+ if (!hash_to_expect.empty()) {
+ DCHECK_EQ(secure_hash_->GetHashLength(), hash_to_expect.size());
+ DCHECK(buffer.size() >= secure_hash_->GetHashLength());
+ scoped_ptr<crypto::SecureHash> partial_hash(secure_hash_->Clone());
+ partial_hash->Finish(&buffer.front(), buffer.size());
+
+ if (memcmp(&buffer.front(),
+ hash_to_expect.c_str(),
+ partial_hash->GetHashLength())) {
+ return LogInterruptReason("Verifying prefix hash",
+ 0,
+ DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH);
+ }
+ }
+
+ return DOWNLOAD_INTERRUPT_REASON_NONE;
}
-DownloadInterruptReason BaseFile::Open() {
+DownloadInterruptReason BaseFile::Open(const std::string& hash_so_far) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
DCHECK(!detached_);
DCHECK(!full_path_.empty());
- bound_net_log_.BeginEvent(
- net::NetLog::TYPE_DOWNLOAD_FILE_OPENED,
- base::Bind(&FileOpenedNetLogCallback, &full_path_, bytes_so_far_));
-
// Create a new file if it is not provided.
if (!file_.IsValid()) {
- file_.Initialize(
- full_path_, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE);
+ file_.Initialize(full_path_,
+ base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE |
+ base::File::FLAG_READ);
if (!file_.IsValid()) {
- return LogNetError("Open",
+ return LogNetError("Open/Initialize File",
net::FileErrorToNetError(file_.error_details()));
}
}
- // We may be re-opening the file after rename. Always make sure we're
- // writing at the end of the file.
+ bound_net_log_.BeginEvent(
+ net::NetLog::TYPE_DOWNLOAD_FILE_OPENED,
+ base::Bind(&FileOpenedNetLogCallback, &full_path_, bytes_so_far_));
+
+ if (!secure_hash_) {
+ DownloadInterruptReason reason = CalculatePartialHash(hash_so_far);
+ if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) {
+ ClearFile();
+ return reason;
+ }
+ }
+
int64_t file_size = file_.Seek(base::File::FROM_END, 0);
if (file_size < 0) {
logging::SystemErrorCode error = logging::GetLastSystemErrorCode();
ClearFile();
- return LogSystemError("Seek", error);
+ return LogSystemError("Seeking to end", error);
} else if (file_size > bytes_so_far_) {
// The file is larger than we expected.
// This is OK, as long as we don't use the extra.
@@ -292,7 +308,7 @@ DownloadInterruptReason BaseFile::Open() {
file_.Seek(base::File::FROM_BEGIN, bytes_so_far_) != bytes_so_far_) {
logging::SystemErrorCode error = logging::GetLastSystemErrorCode();
ClearFile();
- return LogSystemError("Truncate", error);
+ return LogSystemError("Truncating to last known offset", error);
}
} else if (file_size < bytes_so_far_) {
// The file is shorter than we expected. Our hashes won't be valid.
@@ -347,6 +363,9 @@ DownloadInterruptReason BaseFile::LogInterruptReason(
const char* operation,
int os_error,
DownloadInterruptReason reason) {
+ DVLOG(1) << __FUNCTION__ << "() operation:" << operation
+ << " os_error:" << os_error
+ << " reason:" << DownloadInterruptReasonToString(reason);
bound_net_log_.AddEvent(
net::NetLog::TYPE_DOWNLOAD_FILE_ERROR,
base::Bind(&FileInterruptedNetLogCallback, operation, os_error, reason));
diff --git a/chromium/content/browser/download/base_file.h b/chromium/content/browser/download/base_file.h
index cc87ae6ce67..139d43b9bb5 100644
--- a/chromium/content/browser/download/base_file.h
+++ b/chromium/content/browser/download/base_file.h
@@ -20,40 +20,72 @@
#include "base/time/time.h"
#include "content/common/content_export.h"
#include "content/public/browser/download_interrupt_reasons.h"
-#include "crypto/sha2.h"
+#include "crypto/secure_hash.h"
#include "net/base/net_errors.h"
#include "net/log/net_log.h"
#include "url/gurl.h"
-namespace crypto {
-class SecureHash;
-}
-
namespace content {
// File being downloaded and saved to disk. This is a base class
-// for DownloadFile and SaveFile, which keep more state information.
+// for DownloadFile and SaveFile, which keep more state information. BaseFile
+// considers itself the owner of the physical file and will delete it when the
+// BaseFile object is destroyed unless the ownership is revoked via a call to
+// Detach().
class CONTENT_EXPORT BaseFile {
public:
// May be constructed on any thread. All other routines (including
// destruction) must occur on the FILE thread.
- BaseFile(const base::FilePath& full_path,
- const GURL& source_url,
- const GURL& referrer_url,
- int64_t received_bytes,
- bool calculate_hash,
- const std::string& hash_state,
- base::File file,
- const net::BoundNetLog& bound_net_log);
- virtual ~BaseFile();
+ BaseFile(const net::BoundNetLog& bound_net_log);
+ ~BaseFile();
// Returns DOWNLOAD_INTERRUPT_REASON_NONE on success, or a
- // DownloadInterruptReason on failure. |default_directory| specifies the
- // directory to create the temporary file in if |full_path()| is empty. If
- // |default_directory| and |full_path()| are empty, then a temporary file will
- // be created in the default download location as determined by
- // ContentBrowserClient.
- DownloadInterruptReason Initialize(const base::FilePath& default_directory);
+ // DownloadInterruptReason on failure. Upon success, the file at |full_path()|
+ // is assumed to be owned by the BaseFile. It will be deleted when the
+ // BaseFile object is destroyed unless Detach() is called before destroying
+ // the BaseFile instance.
+ //
+ // |full_path|: Full path to the download file. Can be empty, in which case
+ // the rules described in |default_directory| will be used to generate a
+ // temporary filename.
+ //
+ // |default_directory|: specifies the directory to create the temporary file
+ // in if |full_path| is empty. If |default_directory| and |full_path| are
+ // empty, then a temporary file will be created in the default download
+ // location as determined by ContentBrowserClient.
+ //
+ // |file|: The base::File handle to use. If specified, BaseFile will not open
+ // a file and will use this handle. The file should be opened for both
+ // read and write. Only makes sense if |full_path| is non-empty since it
+ // implies that the caller already knows the path to the file. There's no
+ // perfect way to come up with a canonical path for a file. So BaseFile
+ // will not attempt to determine the |full_path|.
+ //
+ // |bytes_so_far|: If a file is provided (via |full_path| or |file|), then
+ // this argument specifies the size of the file to expect. It is legal for
+ // the file to be larger, in which case the file will be truncated down to
+ // this size. However, if the file is shorter, then the operation will
+ // fail with DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT.
+ //
+ // |hash_so_far|: If |bytes_so_far| is non-zero, this specifies the SHA-256
+ // hash of the first |bytes_so_far| bytes of the target file. If
+ // specified, BaseFile will read the first |bytes_so_far| of the target
+ // file in order to calculate the hash and verify that the file matches.
+ // If there's a mismatch, then the operation fails with
+ // DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH. Not used if |hash_state|
+ // is also specified.
+ //
+ // |hash_state|: The partial hash object to use. Only meaningful if there's a
+ // preexisting target file and it is non-empty (i.e. bytes_so_far is
+ // non-zero). If specified, BaseFile will assume that the bytes up to
+ // |bytes_so_far| has been accurately hashed into |hash_state| and will
+ // ignore |hash_so_far|.
+ DownloadInterruptReason Initialize(const base::FilePath& full_path,
+ const base::FilePath& default_directory,
+ base::File file,
+ int64_t bytes_so_far,
+ const std::string& hash_so_far,
+ scoped_ptr<crypto::SecureHash> hash_state);
// Write a new chunk of data to the file. Returns a DownloadInterruptReason
// indicating the result of the operation.
@@ -63,33 +95,39 @@ class CONTENT_EXPORT BaseFile {
// result of the operation. A return code of NONE indicates that the rename
// was successful. After a failure, the full_path() and in_progress() can be
// used to determine the last known filename and whether the file is available
- // for writing or retrying the rename.
- virtual DownloadInterruptReason Rename(const base::FilePath& full_path);
-
- // Detach the file so it is not deleted on destruction.
- virtual void Detach();
-
- // Abort the download and automatically close the file.
+ // for writing or retrying the rename. Call Finish() to obtain the last known
+ // hash state.
+ DownloadInterruptReason Rename(const base::FilePath& full_path);
+
+ // Mark the file as detached. Up until this method is called, BaseFile assumes
+ // ownership of the file and hence will delete the file if the BaseFile object
+ // is destroyed. Calling Detach() causes BaseFile to assume that it no longer
+ // owns the file. Detach() can be called at any time. Close() must still be
+ // called to close the file if it is open.
+ void Detach();
+
+ // Abort the download and automatically close and delete the file.
void Cancel();
// Indicate that the download has finished. No new data will be received.
- void Finish();
-
- // Indicate that the download is being aborted due to an error. This is
- // identical to Finish() with the exception that the hash state will not be
- // finalized.
- void FinishWithError();
-
- // Set the client guid which will be used to identify the app to the
- // system AV scanning function. Should be called before
- // AnnotateWithSourceInformation() to take effect.
- void SetClientGuid(const std::string& guid);
+ // Returns the SecureHash object representing the state of the hash function
+ // at the end of the operation.
+ scoped_ptr<crypto::SecureHash> Finish();
// Informs the OS that this file came from the internet. Returns a
// DownloadInterruptReason indicating the result of the operation.
- // Note: SetClientGuid() should be called before this function on
- // Windows to ensure the correct app client ID is available.
- DownloadInterruptReason AnnotateWithSourceInformation();
+ //
+ // |client_guid|: The client GUID which will be used to identify the caller to
+ // the system AV scanning function.
+ //
+ // |source_url| / |referrer_url|: Source and referrer for the network request
+ // that originated this download. Will be used to annotate source
+ // information and also to determine the relative danger level of the
+ // file.
+ DownloadInterruptReason AnnotateWithSourceInformation(
+ const std::string& client_guid,
+ const GURL& source_url,
+ const GURL& referrer_url);
// Returns the last known path to the download file. Can be empty if there's
// no file.
@@ -102,26 +140,27 @@ class CONTENT_EXPORT BaseFile {
// Returns the number of bytes in the file pointed to by full_path().
int64_t bytes_so_far() const { return bytes_so_far_; }
- // Fills |hash| with the hash digest for the file.
- // Returns true if digest is successfully calculated.
- virtual bool GetHash(std::string* hash);
-
- // Returns the current (intermediate) state of the hash as a byte string.
- virtual std::string GetHashState();
-
- // Returns true if the given hash is considered empty. An empty hash is
- // a string of size crypto::kSHA256Length that contains only zeros (initial
- // value for the hash).
- static bool IsEmptyHash(const std::string& hash);
-
- virtual std::string DebugString() const;
+ std::string DebugString() const;
private:
friend class BaseFileTest;
FRIEND_TEST_ALL_PREFIXES(BaseFileTest, IsEmptyHash);
- // Creates and opens the file_ if it is NULL.
- DownloadInterruptReason Open();
+ // Creates and opens the file_ if it is invalid.
+ //
+ // If |hash_so_far| is not empty, then it must match the SHA-256 hash of the
+ // first |bytes_so_far_| bytes of |file_|. If there's a hash mismatch, Open()
+ // fails with DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH.
+ //
+ // If the opened file is shorter than |bytes_so_far_| bytes, then Open() fails
+ // with DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT. If the opened file is
+ // longer, then the file is truncated to |bytes_so_far_|.
+ //
+ // Open() can fail for other reasons as well. In that case, it returns a
+ // relevant interrupt reason. Unless Open() return
+ // DOWNLOAD_INTERRUPT_REASON_NONE, it should be assumed that |file_| is not
+ // valid.
+ DownloadInterruptReason Open(const std::string& hash_so_far);
// Closes and resets file_.
void Close();
@@ -138,6 +177,17 @@ class CONTENT_EXPORT BaseFile {
// Split out from CurrentSpeed to enable testing.
int64_t CurrentSpeedAtTime(base::TimeTicks current_time) const;
+ // Verifies that:
+ // * Size of the file represented by |file_| is at least |bytes_so_far_|.
+ //
+ // * If |hash_to_expect| is not empty, then the result of hashing the first
+ // |bytes_so_far_| bytes of |file_| matches |hash_to_expect|.
+ //
+ // If the result is REASON_NONE, then on return |secure_hash_| is valid and
+ // is ready to hash bytes from offset |bytes_so_far_| + 1.
+ DownloadInterruptReason CalculatePartialHash(
+ const std::string& hash_to_expect);
+
// Log a TYPE_DOWNLOAD_FILE_ERROR NetLog event with |error| and passes error
// on through, converting to a |DownloadInterruptReason|.
DownloadInterruptReason LogNetError(const char* operation, net::Error error);
@@ -153,40 +203,24 @@ class CONTENT_EXPORT BaseFile {
const char* operation, int os_error,
DownloadInterruptReason reason);
- static const unsigned char kEmptySha256Hash[crypto::kSHA256Length];
-
// Full path to the file including the file name.
base::FilePath full_path_;
- // Source URL for the file being downloaded.
- GURL source_url_;
-
- // The URL where the download was initiated.
- GURL referrer_url_;
-
- std::string client_guid_;
-
// OS file for writing
base::File file_;
// Amount of data received up so far, in bytes.
- int64_t bytes_so_far_;
+ int64_t bytes_so_far_ = 0;
- // Start time for calculating speed.
- base::TimeTicks start_tick_;
-
- // Indicates if hash should be calculated for the file.
- bool calculate_hash_;
-
- // Used to calculate hash for the file when calculate_hash_
- // is set.
+ // Used to calculate hash for the file when calculate_hash_ is set.
scoped_ptr<crypto::SecureHash> secure_hash_;
- unsigned char sha256_hash_[crypto::kSHA256Length];
+ // Start time for calculating speed.
+ base::TimeTicks start_tick_;
// Indicates that this class no longer owns the associated file, and so
// won't delete it on destruction.
- bool detached_;
+ bool detached_ = false;
net::BoundNetLog bound_net_log_;
diff --git a/chromium/content/browser/download/base_file_linux.cc b/chromium/content/browser/download/base_file_linux.cc
index 721cd602694..6c62be32302 100644
--- a/chromium/content/browser/download/base_file_linux.cc
+++ b/chromium/content/browser/download/base_file_linux.cc
@@ -9,11 +9,14 @@
namespace content {
-DownloadInterruptReason BaseFile::AnnotateWithSourceInformation() {
+DownloadInterruptReason BaseFile::AnnotateWithSourceInformation(
+ const std::string& client_guid,
+ const GURL& source_url,
+ const GURL& referrer_url) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
DCHECK(!detached_);
- AddOriginMetadataToFile(full_path_, source_url_, referrer_url_);
+ AddOriginMetadataToFile(full_path_, source_url, referrer_url);
return DOWNLOAD_INTERRUPT_REASON_NONE;
}
diff --git a/chromium/content/browser/download/base_file_mac.cc b/chromium/content/browser/download/base_file_mac.cc
index f3edf12d094..4ece61b90d7 100644
--- a/chromium/content/browser/download/base_file_mac.cc
+++ b/chromium/content/browser/download/base_file_mac.cc
@@ -9,12 +9,15 @@
namespace content {
-DownloadInterruptReason BaseFile::AnnotateWithSourceInformation() {
+DownloadInterruptReason BaseFile::AnnotateWithSourceInformation(
+ const std::string& client_guid,
+ const GURL& source_url,
+ const GURL& referrer_url) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
DCHECK(!detached_);
- AddQuarantineMetadataToFile(full_path_, source_url_, referrer_url_);
- AddOriginMetadataToFile(full_path_, source_url_, referrer_url_);
+ AddQuarantineMetadataToFile(full_path_, source_url, referrer_url);
+ AddOriginMetadataToFile(full_path_, source_url, referrer_url);
return DOWNLOAD_INTERRUPT_REASON_NONE;
}
diff --git a/chromium/content/browser/download/base_file_unittest.cc b/chromium/content/browser/download/base_file_unittest.cc
index a6ce347c189..8f2412b17d9 100644
--- a/chromium/content/browser/download/base_file_unittest.cc
+++ b/chromium/content/browser/download/base_file_unittest.cc
@@ -32,12 +32,24 @@ const char kTestData3[] = "Final line.";
const char kTestData4[] = "supercalifragilisticexpialidocious";
const int kTestDataLength1 = arraysize(kTestData1) - 1;
const int kTestDataLength2 = arraysize(kTestData2) - 1;
-const int kTestDataLength3 = arraysize(kTestData3) - 1;
const int kTestDataLength4 = arraysize(kTestData4) - 1;
const int kElapsedTimeSeconds = 5;
const base::TimeDelta kElapsedTimeDelta = base::TimeDelta::FromSeconds(
kElapsedTimeSeconds);
+// SHA-256 hash of kTestData1 (excluding terminating NUL).
+const uint8_t kHashOfTestData1[] = {
+ 0x0b, 0x2d, 0x3f, 0x3f, 0x79, 0x43, 0xad, 0x64, 0xb8, 0x60, 0xdf,
+ 0x94, 0xd0, 0x5c, 0xb5, 0x6a, 0x8a, 0x97, 0xc6, 0xec, 0x57, 0x68,
+ 0xb5, 0xb7, 0x0b, 0x93, 0x0c, 0x5a, 0xa7, 0xfa, 0x9a, 0xde};
+
+// SHA-256 hash of kTestData1 ++ kTestData2 ++ kTestData3 (excluding terminating
+// NUL).
+const uint8_t kHashOfTestData1To3[] = {
+ 0xcb, 0xf6, 0x8b, 0xf1, 0x0f, 0x80, 0x03, 0xdb, 0x86, 0xb3, 0x13,
+ 0x43, 0xaf, 0xac, 0x8c, 0x71, 0x75, 0xbd, 0x03, 0xfb, 0x5f, 0xc9,
+ 0x05, 0x65, 0x0f, 0x8c, 0x80, 0xaf, 0x08, 0x74, 0x43, 0xa8};
+
} // namespace
class BaseFileTest : public testing::Test {
@@ -52,16 +64,8 @@ class BaseFileTest : public testing::Test {
}
void SetUp() override {
- ResetHash();
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- base_file_.reset(new BaseFile(base::FilePath(),
- GURL(),
- GURL(),
- 0,
- false,
- std::string(),
- base::File(),
- net::BoundNetLog()));
+ base_file_.reset(new BaseFile(net::BoundNetLog()));
}
void TearDown() override {
@@ -87,36 +91,14 @@ class BaseFileTest : public testing::Test {
EXPECT_EQ(expect_file_survives_, base::PathExists(full_path));
}
- void ResetHash() {
- secure_hash_.reset(crypto::SecureHash::Create(crypto::SecureHash::SHA256));
- memcpy(sha256_hash_, kEmptySha256Hash, crypto::kSHA256Length);
- }
-
- void UpdateHash(const char* data, size_t length) {
- secure_hash_->Update(data, length);
- }
-
- std::string GetFinalHash() {
- std::string hash;
- secure_hash_->Finish(sha256_hash_, crypto::kSHA256Length);
- hash.assign(reinterpret_cast<const char*>(sha256_hash_),
- sizeof(sha256_hash_));
- return hash;
- }
-
- void MakeFileWithHash() {
- base_file_.reset(new BaseFile(base::FilePath(),
- GURL(),
- GURL(),
- 0,
- true,
- std::string(),
- base::File(),
- net::BoundNetLog()));
- }
-
bool InitializeFile() {
- DownloadInterruptReason result = base_file_->Initialize(temp_dir_.path());
+ DownloadInterruptReason result =
+ base_file_->Initialize(base::FilePath(),
+ temp_dir_.path(),
+ base::File(),
+ 0,
+ std::string(),
+ scoped_ptr<crypto::SecureHash>());
EXPECT_EQ(expected_error_, result);
return result == DOWNLOAD_INTERRUPT_REASON_NONE;
}
@@ -145,17 +127,15 @@ class BaseFileTest : public testing::Test {
// Create a file. Returns the complete file path.
base::FilePath CreateTestFile() {
base::FilePath file_name;
- BaseFile file(base::FilePath(),
- GURL(),
- GURL(),
- 0,
- false,
- std::string(),
- base::File(),
- net::BoundNetLog());
+ BaseFile file((net::BoundNetLog()));
EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
- file.Initialize(temp_dir_.path()));
+ file.Initialize(base::FilePath(),
+ temp_dir_.path(),
+ base::File(),
+ 0,
+ std::string(),
+ scoped_ptr<crypto::SecureHash>()));
file_name = file.full_path();
EXPECT_NE(base::FilePath::StringType(), file_name.value());
@@ -171,16 +151,14 @@ class BaseFileTest : public testing::Test {
// Create a file with the specified file name.
void CreateFileWithName(const base::FilePath& file_name) {
EXPECT_NE(base::FilePath::StringType(), file_name.value());
- BaseFile duplicate_file(file_name,
- GURL(),
- GURL(),
- 0,
- false,
- std::string(),
- base::File(),
- net::BoundNetLog());
+ BaseFile duplicate_file((net::BoundNetLog()));
EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
- duplicate_file.Initialize(temp_dir_.path()));
+ duplicate_file.Initialize(file_name,
+ temp_dir_.path(),
+ base::File(),
+ 0,
+ std::string(),
+ scoped_ptr<crypto::SecureHash>()));
// Write something into it.
duplicate_file.AppendDataToFile(kTestData4, kTestDataLength4);
// Detach the file so it isn't deleted on destruction of |duplicate_file|.
@@ -207,6 +185,15 @@ class BaseFileTest : public testing::Test {
<< "Interrupt reason = " << err;
}
+ template <size_t SZ>
+ static void ExpectHashValue(const uint8_t (&expected_hash)[SZ],
+ scoped_ptr<crypto::SecureHash> hash_state) {
+ std::vector<uint8_t> hash_value(hash_state->GetHashLength());
+ hash_state->Finish(&hash_value.front(), hash_value.size());
+ ASSERT_EQ(SZ, hash_value.size());
+ EXPECT_EQ(0, memcmp(expected_hash, &hash_value.front(), hash_value.size()));
+ }
+
protected:
// BaseClass instance we are testing.
scoped_ptr<BaseFile> base_file_;
@@ -220,11 +207,6 @@ class BaseFileTest : public testing::Test {
// Expect the file to be in progress.
bool expect_in_progress_;
- // Hash calculator.
- scoped_ptr<crypto::SecureHash> secure_hash_;
-
- unsigned char sha256_hash_[crypto::kSHA256Length];
-
private:
// Keep track of what data should be saved to the disk file.
std::string expected_data_;
@@ -266,24 +248,9 @@ TEST_F(BaseFileTest, WriteAndDetach) {
// Write data to the file and detach it, and calculate its sha256 hash.
TEST_F(BaseFileTest, WriteWithHashAndDetach) {
- // Calculate the final hash.
- ResetHash();
- UpdateHash(kTestData1, kTestDataLength1);
- std::string expected_hash = GetFinalHash();
- std::string expected_hash_hex =
- base::HexEncode(expected_hash.data(), expected_hash.size());
-
- MakeFileWithHash();
ASSERT_TRUE(InitializeFile());
ASSERT_TRUE(AppendDataToFile(kTestData1));
- base_file_->Finish();
-
- std::string hash;
- base_file_->GetHash(&hash);
- EXPECT_EQ("0B2D3F3F7943AD64B860DF94D05CB56A8A97C6EC5768B5B70B930C5AA7FA9ADE",
- expected_hash_hex);
- EXPECT_EQ(expected_hash_hex, base::HexEncode(hash.data(), hash.size()));
-
+ ExpectHashValue(kHashOfTestData1, base_file_->Finish());
base_file_->Detach();
expect_file_survives_ = true;
}
@@ -303,7 +270,7 @@ TEST_F(BaseFileTest, WriteThenRenameAndDetach) {
EXPECT_FALSE(base::PathExists(initial_path));
EXPECT_TRUE(base::PathExists(new_path));
- base_file_->Finish();
+ ExpectHashValue(kHashOfTestData1, base_file_->Finish());
base_file_->Detach();
expect_file_survives_ = true;
}
@@ -312,7 +279,7 @@ TEST_F(BaseFileTest, WriteThenRenameAndDetach) {
TEST_F(BaseFileTest, SingleWrite) {
ASSERT_TRUE(InitializeFile());
ASSERT_TRUE(AppendDataToFile(kTestData1));
- base_file_->Finish();
+ ExpectHashValue(kHashOfTestData1, base_file_->Finish());
}
// Write data to the file multiple times.
@@ -321,82 +288,18 @@ TEST_F(BaseFileTest, MultipleWrites) {
ASSERT_TRUE(AppendDataToFile(kTestData1));
ASSERT_TRUE(AppendDataToFile(kTestData2));
ASSERT_TRUE(AppendDataToFile(kTestData3));
- std::string hash;
- EXPECT_FALSE(base_file_->GetHash(&hash));
- base_file_->Finish();
-}
-
-// Write data to the file once and calculate its sha256 hash.
-TEST_F(BaseFileTest, SingleWriteWithHash) {
- // Calculate the final hash.
- ResetHash();
- UpdateHash(kTestData1, kTestDataLength1);
- std::string expected_hash = GetFinalHash();
- std::string expected_hash_hex =
- base::HexEncode(expected_hash.data(), expected_hash.size());
-
- MakeFileWithHash();
- ASSERT_TRUE(InitializeFile());
- // Can get partial hash states before Finish() is called.
- EXPECT_STRNE(std::string().c_str(), base_file_->GetHashState().c_str());
- ASSERT_TRUE(AppendDataToFile(kTestData1));
- EXPECT_STRNE(std::string().c_str(), base_file_->GetHashState().c_str());
- base_file_->Finish();
-
- std::string hash;
- base_file_->GetHash(&hash);
- EXPECT_EQ(expected_hash_hex, base::HexEncode(hash.data(), hash.size()));
-}
-
-// Write data to the file multiple times and calculate its sha256 hash.
-TEST_F(BaseFileTest, MultipleWritesWithHash) {
- // Calculate the final hash.
- ResetHash();
- UpdateHash(kTestData1, kTestDataLength1);
- UpdateHash(kTestData2, kTestDataLength2);
- UpdateHash(kTestData3, kTestDataLength3);
- std::string expected_hash = GetFinalHash();
- std::string expected_hash_hex =
- base::HexEncode(expected_hash.data(), expected_hash.size());
-
- std::string hash;
- MakeFileWithHash();
- ASSERT_TRUE(InitializeFile());
- ASSERT_TRUE(AppendDataToFile(kTestData1));
- ASSERT_TRUE(AppendDataToFile(kTestData2));
- ASSERT_TRUE(AppendDataToFile(kTestData3));
- // No hash before Finish() is called.
- EXPECT_FALSE(base_file_->GetHash(&hash));
- base_file_->Finish();
-
- EXPECT_TRUE(base_file_->GetHash(&hash));
- EXPECT_EQ("CBF68BF10F8003DB86B31343AFAC8C7175BD03FB5FC905650F8C80AF087443A8",
- expected_hash_hex);
- EXPECT_EQ(expected_hash_hex, base::HexEncode(hash.data(), hash.size()));
+ ExpectHashValue(kHashOfTestData1To3, base_file_->Finish());
}
// Write data to the file multiple times, interrupt it, and continue using
// another file. Calculate the resulting combined sha256 hash.
TEST_F(BaseFileTest, MultipleWritesInterruptedWithHash) {
- // Calculate the final hash.
- ResetHash();
- UpdateHash(kTestData1, kTestDataLength1);
- UpdateHash(kTestData2, kTestDataLength2);
- UpdateHash(kTestData3, kTestDataLength3);
- std::string expected_hash = GetFinalHash();
- std::string expected_hash_hex =
- base::HexEncode(expected_hash.data(), expected_hash.size());
-
- MakeFileWithHash();
ASSERT_TRUE(InitializeFile());
// Write some data
ASSERT_TRUE(AppendDataToFile(kTestData1));
ASSERT_TRUE(AppendDataToFile(kTestData2));
// Get the hash state and file name.
- std::string hash_state;
- hash_state = base_file_->GetHashState();
- // Finish the file.
- base_file_->Finish();
+ scoped_ptr<crypto::SecureHash> hash_state = base_file_->Finish();
base::FilePath new_file_path(temp_dir_.path().Append(
base::FilePath(FILE_PATH_LITERAL("second_file"))));
@@ -404,26 +307,18 @@ TEST_F(BaseFileTest, MultipleWritesInterruptedWithHash) {
ASSERT_TRUE(base::CopyFile(base_file_->full_path(), new_file_path));
// Create another file
- BaseFile second_file(new_file_path,
- GURL(),
- GURL(),
- base_file_->bytes_so_far(),
- true,
- hash_state,
- base::File(),
- net::BoundNetLog());
+ BaseFile second_file((net::BoundNetLog()));
ASSERT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
- second_file.Initialize(base::FilePath()));
+ second_file.Initialize(new_file_path,
+ base::FilePath(),
+ base::File(),
+ base_file_->bytes_so_far(),
+ std::string(),
+ std::move(hash_state)));
std::string data(kTestData3);
EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
second_file.AppendDataToFile(data.data(), data.size()));
- second_file.Finish();
-
- std::string hash;
- EXPECT_TRUE(second_file.GetHash(&hash));
- // This will fail until getting the hash state is supported in SecureHash.
- EXPECT_STREQ(expected_hash_hex.c_str(),
- base::HexEncode(hash.data(), hash.size()).c_str());
+ ExpectHashValue(kHashOfTestData1To3, second_file.Finish());
}
// Rename the file after all writes to it.
@@ -442,7 +337,7 @@ TEST_F(BaseFileTest, WriteThenRename) {
EXPECT_FALSE(base::PathExists(initial_path));
EXPECT_TRUE(base::PathExists(new_path));
- base_file_->Finish();
+ ExpectHashValue(kHashOfTestData1, base_file_->Finish());
}
// Rename the file while the download is still in progress.
@@ -462,8 +357,9 @@ TEST_F(BaseFileTest, RenameWhileInProgress) {
EXPECT_TRUE(base::PathExists(new_path));
ASSERT_TRUE(AppendDataToFile(kTestData2));
+ ASSERT_TRUE(AppendDataToFile(kTestData3));
- base_file_->Finish();
+ ExpectHashValue(kHashOfTestData1To3, base_file_->Finish());
}
// Test that a failed rename reports the correct error.
@@ -525,15 +421,7 @@ TEST_F(BaseFileTest, RenameWithErrorInProgress) {
ASSERT_EQ(new_path.value(), base_file_->full_path().value());
ASSERT_TRUE(AppendDataToFile(kTestData3));
- base_file_->Finish();
-
- // The contents of the file should be intact.
- std::string file_contents;
- std::string expected_contents(kTestData1);
- expected_contents += kTestData2;
- expected_contents += kTestData3;
- ASSERT_TRUE(base::ReadFileToString(new_path, &file_contents));
- EXPECT_EQ(expected_contents, file_contents);
+ ExpectHashValue(kHashOfTestData1To3, base_file_->Finish());
}
// Test that a failed write reports an error.
@@ -544,9 +432,14 @@ TEST_F(BaseFileTest, WriteWithError) {
// Pass a file handle which was opened without the WRITE flag.
// This should result in an error when writing.
base::File file(path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ);
- base_file_.reset(new BaseFile(path, GURL(), GURL(), 0, false, std::string(),
- std::move(file), net::BoundNetLog()));
- ASSERT_TRUE(InitializeFile());
+ base_file_.reset(new BaseFile(net::BoundNetLog()));
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
+ base_file_->Initialize(path,
+ base::FilePath(),
+ std::move(file),
+ 0,
+ std::string(),
+ scoped_ptr<crypto::SecureHash>()));
#if defined(OS_WIN)
set_expected_error(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED);
#elif defined (OS_POSIX)
@@ -580,20 +473,17 @@ TEST_F(BaseFileTest, DuplicateBaseFile) {
TEST_F(BaseFileTest, AppendToBaseFile) {
// Create a new file.
base::FilePath existing_file_name = CreateTestFile();
-
set_expected_data(kTestData4);
// Use the file we've just created.
- base_file_.reset(new BaseFile(existing_file_name,
- GURL(),
- GURL(),
- kTestDataLength4,
- false,
- std::string(),
- base::File(),
- net::BoundNetLog()));
-
- ASSERT_TRUE(InitializeFile());
+ base_file_.reset(new BaseFile(net::BoundNetLog()));
+ ASSERT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
+ base_file_->Initialize(existing_file_name,
+ base::FilePath(),
+ base::File(),
+ kTestDataLength4,
+ std::string(),
+ scoped_ptr<crypto::SecureHash>()));
const base::FilePath file_name = base_file_->full_path();
EXPECT_NE(base::FilePath::StringType(), file_name.value());
@@ -618,18 +508,16 @@ TEST_F(BaseFileTest, ReadonlyBaseFile) {
EXPECT_TRUE(base::MakeFileUnwritable(readonly_file_name));
// Try to overwrite it.
- base_file_.reset(new BaseFile(readonly_file_name,
- GURL(),
- GURL(),
- 0,
- false,
- std::string(),
- base::File(),
- net::BoundNetLog()));
+ base_file_.reset(new BaseFile(net::BoundNetLog()));
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED,
+ base_file_->Initialize(readonly_file_name,
+ base::FilePath(),
+ base::File(),
+ 0,
+ std::string(),
+ scoped_ptr<crypto::SecureHash>()));
expect_in_progress_ = false;
- set_expected_error(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED);
- EXPECT_FALSE(InitializeFile());
const base::FilePath file_name = base_file_->full_path();
EXPECT_NE(base::FilePath::StringType(), file_name.value());
@@ -643,16 +531,175 @@ TEST_F(BaseFileTest, ReadonlyBaseFile) {
expect_file_survives_ = true;
}
-TEST_F(BaseFileTest, IsEmptyHash) {
- std::string empty(crypto::kSHA256Length, '\x00');
- EXPECT_TRUE(BaseFile::IsEmptyHash(empty));
- std::string not_empty(crypto::kSHA256Length, '\x01');
- EXPECT_FALSE(BaseFile::IsEmptyHash(not_empty));
- EXPECT_FALSE(BaseFile::IsEmptyHash(std::string()));
+// Open an existing file and continue writing to it. The hash of the partial
+// file is known and matches the existing contents.
+TEST_F(BaseFileTest, ExistingBaseFileKnownHash) {
+ base::FilePath file_path = temp_dir_.path().AppendASCII("existing");
+ ASSERT_TRUE(base::WriteFile(file_path, kTestData1, kTestDataLength1));
+
+ std::string hash_so_far(std::begin(kHashOfTestData1),
+ std::end(kHashOfTestData1));
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
+ base_file_->Initialize(file_path,
+ base::FilePath(),
+ base::File(),
+ kTestDataLength1,
+ hash_so_far,
+ scoped_ptr<crypto::SecureHash>()));
+ set_expected_data(kTestData1);
+ ASSERT_TRUE(AppendDataToFile(kTestData2));
+ ASSERT_TRUE(AppendDataToFile(kTestData3));
+ ExpectHashValue(kHashOfTestData1To3, base_file_->Finish());
+}
+
+// Open an existing file and continue writing to it. The hash of the partial
+// file is unknown.
+TEST_F(BaseFileTest, ExistingBaseFileUnknownHash) {
+ base::FilePath file_path = temp_dir_.path().AppendASCII("existing");
+ ASSERT_TRUE(base::WriteFile(file_path, kTestData1, kTestDataLength1));
+
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
+ base_file_->Initialize(file_path,
+ base::FilePath(),
+ base::File(),
+ kTestDataLength1,
+ std::string(),
+ scoped_ptr<crypto::SecureHash>()));
+ set_expected_data(kTestData1);
+ ASSERT_TRUE(AppendDataToFile(kTestData2));
+ ASSERT_TRUE(AppendDataToFile(kTestData3));
+ ExpectHashValue(kHashOfTestData1To3, base_file_->Finish());
+}
+
+// Open an existing file. The contentsof the file doesn't match the known hash.
+TEST_F(BaseFileTest, ExistingBaseFileIncorrectHash) {
+ base::FilePath file_path = temp_dir_.path().AppendASCII("existing");
+ ASSERT_TRUE(base::WriteFile(file_path, kTestData2, kTestDataLength2));
+
+ std::string hash_so_far(std::begin(kHashOfTestData1),
+ std::end(kHashOfTestData1));
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH,
+ base_file_->Initialize(file_path,
+ base::FilePath(),
+ base::File(),
+ kTestDataLength2,
+ hash_so_far,
+ scoped_ptr<crypto::SecureHash>()));
+ set_expected_error(DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH);
+}
- std::string also_not_empty = empty;
- also_not_empty[crypto::kSHA256Length - 1] = '\x01';
- EXPECT_FALSE(BaseFile::IsEmptyHash(also_not_empty));
+// Open a large existing file with a known hash and continue writing to it.
+TEST_F(BaseFileTest, ExistingBaseFileLargeSizeKnownHash) {
+ base::FilePath file_path = temp_dir_.path().AppendASCII("existing");
+ std::string big_buffer(1024 * 200, 'a');
+ ASSERT_TRUE(base::WriteFile(file_path, big_buffer.data(), big_buffer.size()));
+
+ // Hash of partial file (1024*200 * 'a')
+ const uint8_t kExpectedPartialHash[] = {
+ 0x4b, 0x4f, 0x0f, 0x46, 0xac, 0x02, 0xd1, 0x77, 0xde, 0xa0, 0xab,
+ 0x36, 0xa6, 0x6a, 0x65, 0x78, 0x40, 0xe2, 0xfb, 0x98, 0xb2, 0x0b,
+ 0xb2, 0x7a, 0x68, 0x8d, 0xb4, 0xd8, 0xea, 0x9c, 0xd2, 0x2c};
+
+ // Hash of entire file (1024*400 * 'a')
+ const uint8_t kExpectedFullHash[] = {
+ 0x0c, 0xe9, 0xf6, 0x78, 0x6b, 0x0f, 0x58, 0x49, 0x36, 0xe8, 0x83,
+ 0xc5, 0x09, 0x16, 0xbc, 0x5e, 0x2d, 0x07, 0x95, 0xb9, 0x42, 0x20,
+ 0x41, 0x7c, 0xb3, 0x38, 0xd3, 0xf4, 0xe0, 0x78, 0x89, 0x46};
+
+ ASSERT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
+ base_file_->Initialize(file_path,
+ base::FilePath(),
+ base::File(),
+ big_buffer.size(),
+ std::string(std::begin(kExpectedPartialHash),
+ std::end(kExpectedPartialHash)),
+ scoped_ptr<crypto::SecureHash>()));
+ set_expected_data(big_buffer); // Contents of the file on Open.
+ ASSERT_TRUE(AppendDataToFile(big_buffer));
+ ExpectHashValue(kExpectedFullHash, base_file_->Finish());
+}
+
+// Open a large existing file. The contents doesn't match the known hash.
+TEST_F(BaseFileTest, ExistingBaseFileLargeSizeIncorrectHash) {
+ base::FilePath file_path = temp_dir_.path().AppendASCII("existing");
+ std::string big_buffer(1024 * 200, 'a');
+ ASSERT_TRUE(base::WriteFile(file_path, big_buffer.data(), big_buffer.size()));
+
+ // Incorrect hash of partial file (1024*200 * 'a')
+ const uint8_t kExpectedPartialHash[] = {
+ 0xc2, 0xa9, 0x08, 0xd9, 0x8f, 0x5d, 0xf9, 0x87, 0xad, 0xe4, 0x1b,
+ 0x5f, 0xce, 0x21, 0x30, 0x67, 0xef, 0x6c, 0xc2, 0x1e, 0xf2, 0x24,
+ 0x02, 0x12, 0xa4, 0x1e, 0x54, 0xb5, 0xe7, 0xc2, 0x8a, 0xe5};
+
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH,
+ base_file_->Initialize(file_path,
+ base::FilePath(),
+ base::File(),
+ big_buffer.size(),
+ std::string(std::begin(kExpectedPartialHash),
+ std::end(kExpectedPartialHash)),
+ scoped_ptr<crypto::SecureHash>()));
+ set_expected_error(DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH);
+}
+
+// Open an existing file. The size of the file is too short.
+TEST_F(BaseFileTest, ExistingBaseFileTooShort) {
+ base::FilePath file_path = temp_dir_.path().AppendASCII("existing");
+ ASSERT_TRUE(base::WriteFile(file_path, kTestData1, kTestDataLength1));
+
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT,
+ base_file_->Initialize(file_path,
+ base::FilePath(),
+ base::File(),
+ kTestDataLength1 + 1,
+ std::string(),
+ scoped_ptr<crypto::SecureHash>()));
+ set_expected_error(DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT);
+}
+
+// Open an existing file. The size is larger than expected.
+TEST_F(BaseFileTest, ExistingBaseFileKnownHashTooLong) {
+ base::FilePath file_path = temp_dir_.path().AppendASCII("existing");
+ std::string contents;
+ contents.append(kTestData1);
+ contents.append("Something extra");
+ ASSERT_TRUE(base::WriteFile(file_path, contents.data(), contents.size()));
+
+ std::string hash_so_far(std::begin(kHashOfTestData1),
+ std::end(kHashOfTestData1));
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
+ base_file_->Initialize(file_path,
+ base::FilePath(),
+ base::File(),
+ kTestDataLength1,
+ hash_so_far,
+ scoped_ptr<crypto::SecureHash>()));
+ set_expected_data(kTestData1); // Our starting position.
+ ASSERT_TRUE(AppendDataToFile(kTestData2));
+ ASSERT_TRUE(AppendDataToFile(kTestData3));
+ ExpectHashValue(kHashOfTestData1To3, base_file_->Finish());
+}
+
+// Open an existing file. The size is large than expected and the hash is
+// unknown.
+TEST_F(BaseFileTest, ExistingBaseFileUnknownHashTooLong) {
+ base::FilePath file_path = temp_dir_.path().AppendASCII("existing");
+ std::string contents;
+ contents.append(kTestData1);
+ contents.append("Something extra");
+ ASSERT_TRUE(base::WriteFile(file_path, contents.data(), contents.size()));
+
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE,
+ base_file_->Initialize(file_path,
+ base::FilePath(),
+ base::File(),
+ kTestDataLength1,
+ std::string(),
+ scoped_ptr<crypto::SecureHash>()));
+ set_expected_data(kTestData1);
+ ASSERT_TRUE(AppendDataToFile(kTestData2));
+ ASSERT_TRUE(AppendDataToFile(kTestData3));
+ ExpectHashValue(kHashOfTestData1To3, base_file_->Finish());
}
// Test that a temporary file is created in the default download directory.
diff --git a/chromium/content/browser/download/base_file_win.cc b/chromium/content/browser/download/base_file_win.cc
index bfdf3aa9da6..5fa373a43ec 100644
--- a/chromium/content/browser/download/base_file_win.cc
+++ b/chromium/content/browser/download/base_file_win.cc
@@ -352,22 +352,25 @@ DownloadInterruptReason BaseFile::MoveFileAndAdjustPermissions(
return interrupt_reason;
}
-DownloadInterruptReason BaseFile::AnnotateWithSourceInformation() {
+DownloadInterruptReason BaseFile::AnnotateWithSourceInformation(
+ const std::string& client_guid,
+ const GURL& source_url,
+ const GURL& referrer_url) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
DCHECK(!detached_);
bound_net_log_.BeginEvent(net::NetLog::TYPE_DOWNLOAD_FILE_ANNOTATED);
DownloadInterruptReason result = DOWNLOAD_INTERRUPT_REASON_NONE;
- std::string braces_guid = "{" + client_guid_ + "}";
+ std::string braces_guid = "{" + client_guid + "}";
GUID guid = GUID_NULL;
- if (base::IsValidGUID(client_guid_)) {
+ if (base::IsValidGUID(client_guid)) {
HRESULT hr = CLSIDFromString(
base::UTF8ToUTF16(braces_guid).c_str(), &guid);
if (FAILED(hr))
guid = GUID_NULL;
}
- HRESULT hr = AVScanFile(full_path_, source_url_.spec(), guid);
+ HRESULT hr = AVScanFile(full_path_, source_url.spec(), guid);
// If the download file is missing after the call, then treat this as an
// interrupted download.
diff --git a/chromium/content/browser/download/docs/save-page-as.md b/chromium/content/browser/download/docs/save-page-as.md
new file mode 100644
index 00000000000..2661289b375
--- /dev/null
+++ b/chromium/content/browser/download/docs/save-page-as.md
@@ -0,0 +1,137 @@
+# High-level overview of Save-Page-As code
+
+This document describes code under `//content/browser/downloads`
+restricting the scope only to code handling Save-Page-As functionality
+(i.e. leaving out other downloads-related code).
+This document focuses on high-level overview and aspects of the code that
+span multiple compilation units (hoping that individual compilation units
+are described by their code comments or by their code structure).
+
+## Classes overview
+
+* SavePackage class
+ * coordinates overall save-page-as request
+ * created and owned by `WebContents`
+ (ref-counted today, but it is unnecessary - see https://crbug.com/596953)
+ * UI-thread object
+
+* SaveFileCreateInfo::SaveFileSource enum
+ * classifies `SaveItem` and `SaveFile` processing into 3 flavours:
+ * `SAVE_FILE_FROM_NET` (see `SaveFileResourceHandler`)
+ * `SAVE_FILE_FROM_DOM` (see "Complete HTML" section below)
+ * `SAVE_FILE_FROM_FILE` (see `SaveFileManager::SaveLocalFile`)
+
+* SaveItem class
+ * tracks saving a single file
+ * created and owned by `SavePackage`
+ * UI-thread object
+
+* SaveFileManager class
+ * coordinates between FILE and UI threads
+ * Gets requests from `SavePackage` and communicates results back to
+ `SavePackage` on the UI thread.
+ * Shephards data (received from the network OR from DOM) into
+ FILE thread - via `SaveFileManager::UpdateSaveProgress`
+ * created and owned by `ResourceDispatchedHostImpl`
+ (ref-counted today, but it is unnecessary - see https://crbug.com/596953)
+
+* SaveFile class
+ * tracks saving a single file
+ * created and owned by `SaveFileManager`
+ * FILE-thread object
+
+* SaveFileResourceHandler class
+ * tracks network downloads + forwards their status into `SaveFileManager`
+ (onto FILE-thread)
+ * created by `ResourceDispatcherHostImpl::BeginSaveFile`
+ * IO-thread object
+
+* SaveFileCreateInfo POD struct
+ * short-lived object holding data passed to callbacks handling start of
+ saving a file.
+
+* MHTMLGenerationManager class
+ * singleton that manages progress of jobs responsible for saving individual
+ MHTML files (represented by `MHTMLGenerationManager::Job`).
+
+
+## Overview of the processing flow
+
+Save-Page-As flow starts with `WebContents::OnSavePage`.
+The flow is different depending on the save format chosen by the user
+(each flow is described in a separate section below).
+
+### Complete HTML
+
+Very high-level flow of saving a page as "Complete HTML":
+
+* Step 1: `SavePackage` asks all frames for "savable resources"
+ and creates `SaveItem` for each of files that need to be saved
+
+* Step 2: `SavePackage` first processes `SAVE_FILE_FROM_NET` and
+ `SAVE_FILE_FROM_FILE` `SaveItem`s and asks `SaveFileManager` to save
+ them.
+
+* Step 3: `SavePackage` handles remaining `SAVE_FILE_FROM_DOM` `SaveItem`s and
+ asks each frame to serialize its DOM/HTML (each frame gets from
+ `SavePackage` a map covering local paths that need to be referenced by
+ the frame). Responses from frames get forwarded to `SaveFileManager`
+ to be written to disk.
+
+
+### MHTML
+
+Very high-level flow of saving a page as MHTML:
+
+* Step 1: `WebContents::GenerateMHTML` is called by either `SavePackage` (for
+ Save-Page-As UI) or Extensions (via `chrome.pageCapture` extensions
+ API) or by an embedder of `WebContents` (since this is public API of
+ //content).
+
+* Step 2: `MHTMLGenerationManager` coordinates generation of the MHTML file
+ by sequentially (one-at-a-time) asking each frame to write its portion
+ of MHTML to a file handle. Other classes (i.e. `SavePackage` and/or
+ `SaveFileManager`) are not used at this step at all.
+
+* Step 3: When done `MHTMLGenerationManager` calls a completion callback
+ which in case of Save-Page-As will end up in
+ `SavePackage::OnMHTMLGenerated`.
+
+Note: MHTML format is by default disabled in Save-Page-As UI on Windows, MacOS
+and Linux (it is the default on ChromeOS), but for testing this can be easily
+changed using `--save-page-as-mhtml` command line switch.
+
+
+### HTML Only
+
+Very high-level flow of saving a page as "HTML Only":
+
+* `SavePackage` creates only a single `SaveItem` (either `SAVE_FILE_FROM_NET` or
+ `SAVE_FILE_FROM_FILE`) and asks `SaveFileManager` to process it
+ (as in the Complete HTML individual SaveItem handling above.).
+
+
+## Other relevant code
+
+Pointers to related code outside of `//content/browser/download`:
+
+* End-to-end tests:
+ * `//chrome/browser/downloads/save_page_browsertest.cc`
+ * `//chrome/test/data/save_page/...`
+
+* Other tests:
+ * `//content/browser/downloads/*test*.cc`
+ * `//content/renderer/dom_serializer_browsertest.cc` - single process... :-/
+
+* Elsewhere in `//content`:
+ * `//content/renderer/savable_resources...`
+
+* Blink:
+ * `//third_party/WebKit/public/web/WebFrameSerializer...`
+ * `//third_party/WebKit/Source/web/WebFrameSerializerImpl...`
+ (used for Complete HTML today; should use `FrameSerializer` instead in
+ the long-term - see https://crbug.com/328354).
+ * `//third_party/WebKit/Source/core/frame/FrameSerializer...`
+ (used for MHTML today)
+ * `//third_party/WebKit/Source/platform/mhtml/MHTMLArchive...`
+
diff --git a/chromium/content/browser/download/download_browsertest.cc b/chromium/content/browser/download/download_browsertest.cc
index dc965d41646..19a05a2d6a0 100644
--- a/chromium/content/browser/download/download_browsertest.cc
+++ b/chromium/content/browser/download/download_browsertest.cc
@@ -29,8 +29,12 @@
#include "content/browser/download/download_item_impl.h"
#include "content/browser/download/download_manager_impl.h"
#include "content/browser/download/download_resource_handler.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/download_danger_type.h"
#include "content/public/browser/power_save_blocker.h"
+#include "content/public/browser/resource_dispatcher_host_delegate.h"
+#include "content/public/browser/resource_throttle.h"
#include "content/public/common/content_features.h"
#include "content/public/common/webplugininfo.h"
#include "content/public/test/browser_test_utils.h"
@@ -118,17 +122,13 @@ static DownloadManagerImpl* DownloadManagerForShell(Shell* shell) {
class DownloadFileWithDelay : public DownloadFileImpl {
public:
- DownloadFileWithDelay(
- scoped_ptr<DownloadSaveInfo> save_info,
- const base::FilePath& default_download_directory,
- const GURL& url,
- const GURL& referrer_url,
- bool calculate_hash,
- scoped_ptr<ByteStreamReader> stream,
- const net::BoundNetLog& bound_net_log,
- scoped_ptr<PowerSaveBlocker> power_save_blocker,
- base::WeakPtr<DownloadDestinationObserver> observer,
- base::WeakPtr<DownloadFileWithDelayFactory> owner);
+ DownloadFileWithDelay(scoped_ptr<DownloadSaveInfo> save_info,
+ const base::FilePath& default_download_directory,
+ scoped_ptr<ByteStreamReader> stream,
+ const net::BoundNetLog& bound_net_log,
+ scoped_ptr<PowerSaveBlocker> power_save_blocker,
+ base::WeakPtr<DownloadDestinationObserver> observer,
+ base::WeakPtr<DownloadFileWithDelayFactory> owner);
~DownloadFileWithDelay() override;
@@ -138,6 +138,9 @@ class DownloadFileWithDelay : public DownloadFileImpl {
void RenameAndUniquify(const base::FilePath& full_path,
const RenameCompletionCallback& callback) override;
void RenameAndAnnotate(const base::FilePath& full_path,
+ const std::string& client_guid,
+ const GURL& source_url,
+ const GURL& referrer_url,
const RenameCompletionCallback& callback) override;
private:
@@ -167,9 +170,6 @@ class DownloadFileWithDelayFactory : public DownloadFileFactory {
DownloadFile* CreateFile(
scoped_ptr<DownloadSaveInfo> save_info,
const base::FilePath& default_download_directory,
- const GURL& url,
- const GURL& referrer_url,
- bool calculate_hash,
scoped_ptr<ByteStreamReader> stream,
const net::BoundNetLog& bound_net_log,
base::WeakPtr<DownloadDestinationObserver> observer) override;
@@ -191,9 +191,6 @@ class DownloadFileWithDelayFactory : public DownloadFileFactory {
DownloadFileWithDelay::DownloadFileWithDelay(
scoped_ptr<DownloadSaveInfo> save_info,
const base::FilePath& default_download_directory,
- const GURL& url,
- const GURL& referrer_url,
- bool calculate_hash,
scoped_ptr<ByteStreamReader> stream,
const net::BoundNetLog& bound_net_log,
scoped_ptr<PowerSaveBlocker> power_save_blocker,
@@ -201,9 +198,6 @@ DownloadFileWithDelay::DownloadFileWithDelay(
base::WeakPtr<DownloadFileWithDelayFactory> owner)
: DownloadFileImpl(std::move(save_info),
default_download_directory,
- url,
- referrer_url,
- calculate_hash,
std::move(stream),
bound_net_log,
observer),
@@ -221,11 +215,19 @@ void DownloadFileWithDelay::RenameAndUniquify(
}
void DownloadFileWithDelay::RenameAndAnnotate(
- const base::FilePath& full_path, const RenameCompletionCallback& callback) {
+ const base::FilePath& full_path,
+ const std::string& client_guid,
+ const GURL& source_url,
+ const GURL& referrer_url,
+ const RenameCompletionCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
DownloadFileImpl::RenameAndAnnotate(
- full_path, base::Bind(DownloadFileWithDelay::RenameCallbackWrapper,
- owner_, callback));
+ full_path,
+ client_guid,
+ source_url,
+ referrer_url,
+ base::Bind(
+ DownloadFileWithDelay::RenameCallbackWrapper, owner_, callback));
}
// static
@@ -249,19 +251,19 @@ DownloadFileWithDelayFactory::~DownloadFileWithDelayFactory() {}
DownloadFile* DownloadFileWithDelayFactory::CreateFile(
scoped_ptr<DownloadSaveInfo> save_info,
const base::FilePath& default_download_directory,
- const GURL& url,
- const GURL& referrer_url,
- bool calculate_hash,
scoped_ptr<ByteStreamReader> stream,
const net::BoundNetLog& bound_net_log,
base::WeakPtr<DownloadDestinationObserver> observer) {
scoped_ptr<PowerSaveBlocker> psb(PowerSaveBlocker::Create(
PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
PowerSaveBlocker::kReasonOther, "Download in progress"));
- return new DownloadFileWithDelay(
- std::move(save_info), default_download_directory, url, referrer_url,
- calculate_hash, std::move(stream), bound_net_log, std::move(psb),
- observer, weak_ptr_factory_.GetWeakPtr());
+ return new DownloadFileWithDelay(std::move(save_info),
+ default_download_directory,
+ std::move(stream),
+ bound_net_log,
+ std::move(psb),
+ observer,
+ weak_ptr_factory_.GetWeakPtr());
}
void DownloadFileWithDelayFactory::AddRenameCallback(base::Closure callback) {
@@ -291,18 +293,12 @@ class CountingDownloadFile : public DownloadFileImpl {
public:
CountingDownloadFile(scoped_ptr<DownloadSaveInfo> save_info,
const base::FilePath& default_downloads_directory,
- const GURL& url,
- const GURL& referrer_url,
- bool calculate_hash,
scoped_ptr<ByteStreamReader> stream,
const net::BoundNetLog& bound_net_log,
scoped_ptr<PowerSaveBlocker> power_save_blocker,
base::WeakPtr<DownloadDestinationObserver> observer)
: DownloadFileImpl(std::move(save_info),
default_downloads_directory,
- url,
- referrer_url,
- calculate_hash,
std::move(stream),
bound_net_log,
observer) {}
@@ -351,19 +347,18 @@ class CountingDownloadFileFactory : public DownloadFileFactory {
DownloadFile* CreateFile(
scoped_ptr<DownloadSaveInfo> save_info,
const base::FilePath& default_downloads_directory,
- const GURL& url,
- const GURL& referrer_url,
- bool calculate_hash,
scoped_ptr<ByteStreamReader> stream,
const net::BoundNetLog& bound_net_log,
base::WeakPtr<DownloadDestinationObserver> observer) override {
scoped_ptr<PowerSaveBlocker> psb(PowerSaveBlocker::Create(
PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
PowerSaveBlocker::kReasonOther, "Download in progress"));
- return new CountingDownloadFile(
- std::move(save_info), default_downloads_directory, url, referrer_url,
- calculate_hash, std::move(stream), bound_net_log, std::move(psb),
- observer);
+ return new CountingDownloadFile(std::move(save_info),
+ default_downloads_directory,
+ std::move(stream),
+ bound_net_log,
+ std::move(psb),
+ observer);
}
};
@@ -551,6 +546,13 @@ class TestRequestStartHandler {
class DownloadContentTest : public ContentBrowserTest {
protected:
void SetUpOnMainThread() override {
+ // Enable downloads resumption.
+ base::FeatureList::ClearInstanceForTesting();
+ scoped_ptr<base::FeatureList> feature_list(new base::FeatureList);
+ feature_list->InitializeFromCommandLine(features::kDownloadResumption.name,
+ std::string());
+ base::FeatureList::SetInstance(std::move(feature_list));
+
ASSERT_TRUE(downloads_directory_.CreateUniqueTempDir());
test_delegate_.reset(new TestShellDownloadManagerDelegate());
@@ -575,6 +577,10 @@ class DownloadContentTest : public ContentBrowserTest {
return test_delegate_.get();
}
+ const base::FilePath& GetDownloadDirectory() const {
+ return downloads_directory_.path();
+ }
+
// Create a DownloadTestObserverTerminal that will wait for the
// specified number of downloads to finish.
DownloadTestObserver* CreateWaiter(
@@ -602,6 +608,12 @@ class DownloadContentTest : public ContentBrowserTest {
.WaitForEvent();
}
+ void WaitForCancel(DownloadItem* download) {
+ DownloadUpdatedObserver(
+ download, base::Bind(&IsDownloadInState, DownloadItem::CANCELLED))
+ .WaitForEvent();
+ }
+
// Note: Cannot be used with other alternative DownloadFileFactorys
void SetupEnsureNoPendingDownloads() {
DownloadManagerForShell(shell())->SetDownloadFileFactoryForTesting(
@@ -705,71 +717,6 @@ class DownloadContentTest : public ContentBrowserTest {
scoped_ptr<TestShellDownloadManagerDelegate> test_delegate_;
};
-// Parameters for DownloadResumptionContentTest.
-enum class DownloadResumptionTestType {
- RESUME_WITH_RENDERER, // Resume() is called while the originating WebContents
- // is still alive.
- RESUME_WITHOUT_RENDERER // Resume() is called after the originating
- // WebContents has been deleted.
-};
-
-// Parameterized test for download resumption. Tests using this fixure will be
-// run once with RESUME_WITH_RENDERER and once with RESUME_WITHOUT_RENDERER.
-// Use initiator_shell_for_resumption() to retrieve the Shell object that should
-// be used as the originator for the initial download. Prior to calling
-// Resume(), call PrepareToResume() which will cause the originating Shell to be
-// deleted if the test parameter is RESUME_WITHOUT_RENDERER.
-class DownloadResumptionContentTest
- : public DownloadContentTest,
- public ::testing::WithParamInterface<DownloadResumptionTestType> {
- public:
- void SetUpOnMainThread() override {
- base::FeatureList::ClearInstanceForTesting();
- scoped_ptr<base::FeatureList> feature_list(new base::FeatureList);
- feature_list->InitializeFromCommandLine(
- features::kDownloadResumption.name, std::string());
- base::FeatureList::SetInstance(std::move(feature_list));
-
- DownloadContentTest::SetUpOnMainThread();
-
- if (GetParam() == DownloadResumptionTestType::RESUME_WITHOUT_RENDERER)
- initiator_shell_for_resumption_ = CreateBrowser();
- else
- initiator_shell_for_resumption_ = shell();
-
- ASSERT_EQ(DownloadManagerForShell(shell()),
- DownloadManagerForShell(initiator_shell_for_resumption()));
- }
-
- // Shell to use for initiating a download. Only valid *before*
- // PrepareToResume() is called.
- Shell* initiator_shell_for_resumption() const {
- DCHECK(initiator_shell_for_resumption_);
- return initiator_shell_for_resumption_;
- }
-
- // Should be called once before calling DownloadItem::Resume() on an
- // interrupted download. This may cause initiator_shell_for_resumption() to
- // become invalidated.
- void PrepareToResume() {
- if (GetParam() == DownloadResumptionTestType::RESUME_WITH_RENDERER)
- return;
- DCHECK_NE(initiator_shell_for_resumption(), shell());
- DCHECK(initiator_shell_for_resumption());
- initiator_shell_for_resumption_->Close();
- initiator_shell_for_resumption_ = nullptr;
- }
-
- private:
- Shell* initiator_shell_for_resumption_ = nullptr;
-};
-
-INSTANTIATE_TEST_CASE_P(
- _,
- DownloadResumptionContentTest,
- ::testing::Values(DownloadResumptionTestType::RESUME_WITH_RENDERER,
- DownloadResumptionTestType::RESUME_WITHOUT_RENDERER));
-
} // namespace
IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadCancelled) {
@@ -1070,7 +1017,7 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, ShutdownAtRelease) {
}
// Test resumption with a response that contains strong validators.
-IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, StrongValidators) {
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, StrongValidators) {
TestDownloadRequestHandler request_handler;
TestDownloadRequestHandler::Parameters parameters =
TestDownloadRequestHandler::Parameters::WithSingleInterruption();
@@ -1078,14 +1025,13 @@ IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, StrongValidators) {
parameters.injected_errors.front();
request_handler.StartServing(parameters);
- DownloadItem* download = StartDownloadAndReturnItem(
- initiator_shell_for_resumption(), request_handler.url());
+ DownloadItem* download =
+ StartDownloadAndReturnItem(shell(), request_handler.url());
WaitForInterrupt(download);
ASSERT_EQ(interruption.offset, download->GetReceivedBytes());
ASSERT_EQ(parameters.size, download->GetTotalBytes());
- PrepareToResume();
download->Resume();
WaitForCompletion(download);
@@ -1123,13 +1069,200 @@ IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, StrongValidators) {
value);
}
+// Resumption should only attempt to contact the final URL if the download has a
+// URL chain.
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, RedirectBeforeResume) {
+ TestDownloadRequestHandler request_handler_1(
+ GURL("http://example.com/first-url"));
+ request_handler_1.StartServingStaticResponse(
+ "HTTP/1.1 302 Redirect\r\n"
+ "Location: http://example.com/second-url\r\n"
+ "\r\n");
+
+ TestDownloadRequestHandler request_handler_2(
+ GURL("http://example.com/second-url"));
+ request_handler_2.StartServingStaticResponse(
+ "HTTP/1.1 302 Redirect\r\n"
+ "Location: http://example.com/third-url\r\n"
+ "\r\n");
+
+ TestDownloadRequestHandler request_handler_3(
+ GURL("http://example.com/third-url"));
+ request_handler_3.StartServingStaticResponse(
+ "HTTP/1.1 302 Redirect\r\n"
+ "Location: http://example.com/download\r\n"
+ "\r\n");
+
+ TestDownloadRequestHandler resumable_request_handler(
+ GURL("http://example.com/download"));
+ TestDownloadRequestHandler::Parameters parameters =
+ TestDownloadRequestHandler::Parameters::WithSingleInterruption();
+ resumable_request_handler.StartServing(parameters);
+
+ DownloadItem* download =
+ StartDownloadAndReturnItem(shell(), request_handler_1.url());
+ WaitForInterrupt(download);
+
+ EXPECT_EQ(4u, download->GetUrlChain().size());
+ EXPECT_EQ(request_handler_1.url(), download->GetOriginalUrl());
+ EXPECT_EQ(resumable_request_handler.url(), download->GetURL());
+
+ // Now that the download is interrupted, make all intermediate servers return
+ // a 404. The only way a resumption request would succeed if the resumption
+ // request is sent to the final server in the chain.
+ const char k404Response[] = "HTTP/1.1 404 Not found\r\n\r\n";
+ request_handler_1.StartServingStaticResponse(k404Response);
+ request_handler_2.StartServingStaticResponse(k404Response);
+ request_handler_3.StartServingStaticResponse(k404Response);
+
+ download->Resume();
+ WaitForCompletion(download);
+
+ ASSERT_NO_FATAL_FAILURE(ReadAndVerifyFileContents(
+ parameters.pattern_generator_seed, parameters.size,
+ download->GetTargetFilePath()));
+}
+
+// If a resumption request results in a redirect, the response should be ignored
+// and the download should be marked as interrupted again.
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, RedirectWhileResume) {
+ TestDownloadRequestHandler request_handler(
+ GURL("http://example.com/first-url"));
+ TestDownloadRequestHandler::Parameters parameters =
+ TestDownloadRequestHandler::Parameters::WithSingleInterruption();
+ ++parameters.pattern_generator_seed;
+ request_handler.StartServing(parameters);
+
+ // We should never send a request to the decoy. If we do, the request will
+ // always succeed, which results in behavior that diverges from what we want,
+ // which is for the download to return to being interrupted.
+ TestDownloadRequestHandler decoy_request_handler(
+ GURL("http://example.com/decoy"));
+ decoy_request_handler.StartServing(TestDownloadRequestHandler::Parameters());
+
+ DownloadItem* download =
+ StartDownloadAndReturnItem(shell(), request_handler.url());
+ WaitForInterrupt(download);
+
+ // Upon resumption, the server starts responding with a redirect. This
+ // response should not be accepted.
+ request_handler.StartServingStaticResponse(
+ "HTTP/1.1 302 Redirect\r\n"
+ "Location: http://example.com/decoy\r\n"
+ "\r\n");
+ download->Resume();
+ WaitForInterrupt(download);
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_SERVER_UNREACHABLE,
+ download->GetLastReason());
+
+ // Back to the original request handler. Resumption should now succeed, and
+ // use the partial data it had prior to the first interruption.
+ request_handler.StartServing(parameters);
+ download->Resume();
+ WaitForCompletion(download);
+
+ ASSERT_EQ(parameters.size, download->GetReceivedBytes());
+ ASSERT_EQ(parameters.size, download->GetTotalBytes());
+ ASSERT_NO_FATAL_FAILURE(ReadAndVerifyFileContents(
+ parameters.pattern_generator_seed, parameters.size,
+ download->GetTargetFilePath()));
+
+ // Characterization risk: The next portion of the test examines the requests
+ // that were sent out while downloading our resource. These requests
+ // correspond to the requests that were generated by the browser and the
+ // downloads system and may change as implementation details change.
+ TestDownloadRequestHandler::CompletedRequests requests;
+ request_handler.GetCompletedRequestInfo(&requests);
+
+ ASSERT_EQ(3u, requests.size());
+
+ // None of the request should have transferred the entire resource. The
+ // redirect response shows up as a response with 0 bytes transferred.
+ EXPECT_GT(parameters.size, requests[0].transferred_byte_count);
+ EXPECT_EQ(0, requests[1].transferred_byte_count);
+ EXPECT_GT(parameters.size, requests[2].transferred_byte_count);
+}
+
+// If the server response for the resumption request specifies a bad range (i.e.
+// not the range that was requested or an invalid or missing Content-Range
+// header), then the download should be marked as interrupted again without
+// discarding the partial state.
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, BadRangeHeader) {
+ TestDownloadRequestHandler request_handler;
+ TestDownloadRequestHandler::Parameters parameters =
+ TestDownloadRequestHandler::Parameters::WithSingleInterruption();
+ request_handler.StartServing(parameters);
+
+ DownloadItem* download =
+ StartDownloadAndReturnItem(shell(), request_handler.url());
+ WaitForInterrupt(download);
+
+ // Upon resumption, the server starts responding with a bad range header.
+ request_handler.StartServingStaticResponse(
+ "HTTP/1.1 206 Partial Content\r\n"
+ "Content-Range: bytes 1000000-2000000/3000000\r\n"
+ "\r\n");
+ download->Resume();
+ WaitForInterrupt(download);
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT,
+ download->GetLastReason());
+
+ // Or this time, the server sends a response with an invalid Content-Range
+ // header.
+ request_handler.StartServingStaticResponse(
+ "HTTP/1.1 206 Partial Content\r\n"
+ "Content-Range: ooga-booga-booga-booga\r\n"
+ "\r\n");
+ download->Resume();
+ WaitForInterrupt(download);
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT,
+ download->GetLastReason());
+
+ // Or no Content-Range header at all.
+ request_handler.StartServingStaticResponse(
+ "HTTP/1.1 206 Partial Content\r\n"
+ "Some-Headers: ooga-booga-booga-booga\r\n"
+ "\r\n");
+ download->Resume();
+ WaitForInterrupt(download);
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT,
+ download->GetLastReason());
+
+ // Back to the original request handler. Resumption should now succeed, and
+ // use the partial data it had prior to the first interruption.
+ request_handler.StartServing(parameters);
+ download->Resume();
+ WaitForCompletion(download);
+
+ ASSERT_EQ(parameters.size, download->GetReceivedBytes());
+ ASSERT_EQ(parameters.size, download->GetTotalBytes());
+ ASSERT_NO_FATAL_FAILURE(ReadAndVerifyFileContents(
+ parameters.pattern_generator_seed, parameters.size,
+ download->GetTargetFilePath()));
+
+ // Characterization risk: The next portion of the test examines the requests
+ // that were sent out while downloading our resource. These requests
+ // correspond to the requests that were generated by the browser and the
+ // downloads system and may change as implementation details change.
+ TestDownloadRequestHandler::CompletedRequests requests;
+ request_handler.GetCompletedRequestInfo(&requests);
+
+ ASSERT_EQ(5u, requests.size());
+
+ // None of the request should have transferred the entire resource.
+ EXPECT_GT(parameters.size, requests[0].transferred_byte_count);
+ EXPECT_EQ(0, requests[1].transferred_byte_count);
+ EXPECT_EQ(0, requests[2].transferred_byte_count);
+ EXPECT_EQ(0, requests[3].transferred_byte_count);
+ EXPECT_GT(parameters.size, requests[4].transferred_byte_count);
+}
+
// A partial resumption results in an HTTP 200 response. I.e. the server ignored
// the range request and sent the entire resource instead. For If-Range requests
// (as opposed to If-Match), the behavior for a precondition failure is also to
// respond with a 200. So this test case covers both validation failure and
// ignoring the range request.
-IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest,
- RestartIfNotPartialResponse) {
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, RestartIfNotPartialResponse) {
const int kOriginalPatternGeneratorSeed = 1;
const int kNewPatternGeneratorSeed = 2;
@@ -1142,8 +1275,8 @@ IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest,
TestDownloadRequestHandler request_handler;
request_handler.StartServing(parameters);
- DownloadItem* download = StartDownloadAndReturnItem(
- initiator_shell_for_resumption(), request_handler.url());
+ DownloadItem* download =
+ StartDownloadAndReturnItem(shell(), request_handler.url());
WaitForInterrupt(download);
ASSERT_EQ(interruption.offset, download->GetReceivedBytes());
@@ -1154,7 +1287,6 @@ IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest,
parameters.pattern_generator_seed = kNewPatternGeneratorSeed;
request_handler.StartServing(parameters);
- PrepareToResume();
download->Resume();
WaitForCompletion(download);
@@ -1192,7 +1324,7 @@ IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest,
}
// Confirm we restart if we don't have a verifier.
-IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, RestartIfNoETag) {
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, RestartIfNoETag) {
const int kOriginalPatternGeneratorSeed = 1;
const int kNewPatternGeneratorSeed = 2;
@@ -1204,15 +1336,14 @@ IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, RestartIfNoETag) {
TestDownloadRequestHandler request_handler;
request_handler.StartServing(parameters);
- DownloadItem* download = StartDownloadAndReturnItem(
- initiator_shell_for_resumption(), request_handler.url());
+ DownloadItem* download =
+ StartDownloadAndReturnItem(shell(), request_handler.url());
WaitForInterrupt(download);
parameters.pattern_generator_seed = kNewPatternGeneratorSeed;
parameters.ClearInjectedErrors();
request_handler.StartServing(parameters);
- PrepareToResume();
download->Resume();
WaitForCompletion(download);
@@ -1236,14 +1367,14 @@ IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, RestartIfNoETag) {
// Partial file goes missing before the download is resumed. The download should
// restart.
-IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, RestartIfNoPartialFile) {
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, RestartIfNoPartialFile) {
TestDownloadRequestHandler::Parameters parameters =
TestDownloadRequestHandler::Parameters::WithSingleInterruption();
TestDownloadRequestHandler request_handler;
request_handler.StartServing(parameters);
- DownloadItem* download = StartDownloadAndReturnItem(
- initiator_shell_for_resumption(), request_handler.url());
+ DownloadItem* download =
+ StartDownloadAndReturnItem(shell(), request_handler.url());
WaitForInterrupt(download);
// Delete the intermediate file.
@@ -1253,7 +1384,6 @@ IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, RestartIfNoPartialFile) {
parameters.ClearInjectedErrors();
request_handler.StartServing(parameters);
- PrepareToResume();
download->Resume();
WaitForCompletion(download);
@@ -1264,32 +1394,29 @@ IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, RestartIfNoPartialFile) {
download->GetTargetFilePath()));
}
-IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest,
- RecoverFromInitFileError) {
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, RecoverFromInitFileError) {
TestDownloadRequestHandler request_handler;
request_handler.StartServing(TestDownloadRequestHandler::Parameters());
// Setup the error injector.
- scoped_refptr<TestFileErrorInjector> injector(TestFileErrorInjector::Create(
- DownloadManagerForShell(initiator_shell_for_resumption())));
+ scoped_refptr<TestFileErrorInjector> injector(
+ TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
const TestFileErrorInjector::FileErrorInfo err = {
- request_handler.url().spec(),
TestFileErrorInjector::FILE_OPERATION_INITIALIZE, 0,
DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE};
- injector->AddError(err);
- injector->InjectErrors();
+ injector->InjectError(err);
// Start and watch for interrupt.
- DownloadItem* download(StartDownloadAndReturnItem(
- initiator_shell_for_resumption(), request_handler.url()));
+ DownloadItem* download(
+ StartDownloadAndReturnItem(shell(), request_handler.url()));
WaitForInterrupt(download);
ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState());
EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE,
download->GetLastReason());
EXPECT_EQ(0, download->GetReceivedBytes());
EXPECT_TRUE(download->GetFullPath().empty());
- EXPECT_TRUE(download->GetTargetFilePath().empty());
+ EXPECT_FALSE(download->GetTargetFilePath().empty());
// We need to make sure that any cross-thread downloads communication has
// quiesced before clearing and injecting the new errors, as the
@@ -1299,35 +1426,31 @@ IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest,
RunAllPendingInMessageLoop();
// Clear the old errors list.
- injector->ClearErrors();
- injector->InjectErrors();
+ injector->ClearError();
// Resume and watch completion.
- PrepareToResume();
download->Resume();
WaitForCompletion(download);
EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE);
}
-IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest,
+IN_PROC_BROWSER_TEST_F(DownloadContentTest,
RecoverFromIntermediateFileRenameError) {
TestDownloadRequestHandler request_handler;
request_handler.StartServing(TestDownloadRequestHandler::Parameters());
// Setup the error injector.
- scoped_refptr<TestFileErrorInjector> injector(TestFileErrorInjector::Create(
- DownloadManagerForShell(initiator_shell_for_resumption())));
+ scoped_refptr<TestFileErrorInjector> injector(
+ TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
const TestFileErrorInjector::FileErrorInfo err = {
- request_handler.url().spec(),
TestFileErrorInjector::FILE_OPERATION_RENAME_UNIQUIFY, 0,
DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE};
- injector->AddError(err);
- injector->InjectErrors();
+ injector->InjectError(err);
// Start and watch for interrupt.
- DownloadItem* download(StartDownloadAndReturnItem(
- initiator_shell_for_resumption(), request_handler.url()));
+ DownloadItem* download(
+ StartDownloadAndReturnItem(shell(), request_handler.url()));
WaitForInterrupt(download);
ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState());
EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE,
@@ -1346,40 +1469,33 @@ IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest,
RunAllPendingInMessageLoop();
// Clear the old errors list.
- injector->ClearErrors();
- injector->InjectErrors();
+ injector->ClearError();
- PrepareToResume();
download->Resume();
WaitForCompletion(download);
EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE);
}
-IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest,
- RecoverFromFinalRenameError) {
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, RecoverFromFinalRenameError) {
TestDownloadRequestHandler request_handler;
request_handler.StartServing(TestDownloadRequestHandler::Parameters());
// Setup the error injector.
- scoped_refptr<TestFileErrorInjector> injector(TestFileErrorInjector::Create(
- DownloadManagerForShell(initiator_shell_for_resumption())));
+ scoped_refptr<TestFileErrorInjector> injector(
+ TestFileErrorInjector::Create(DownloadManagerForShell(shell())));
- DownloadManagerForShell(initiator_shell_for_resumption())
- ->RemoveAllDownloads();
+ DownloadManagerForShell(shell())->RemoveAllDownloads();
TestFileErrorInjector::FileErrorInfo err = {
- request_handler.url().spec(),
TestFileErrorInjector::FILE_OPERATION_RENAME_ANNOTATE, 0,
- DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE};
- injector->AddError(err);
- injector->InjectErrors();
+ DOWNLOAD_INTERRUPT_REASON_FILE_FAILED};
+ injector->InjectError(err);
// Start and watch for interrupt.
- DownloadItem* download(StartDownloadAndReturnItem(
- initiator_shell_for_resumption(), request_handler.url()));
+ DownloadItem* download(
+ StartDownloadAndReturnItem(shell(), request_handler.url()));
WaitForInterrupt(download);
ASSERT_EQ(DownloadItem::INTERRUPTED, download->GetState());
- EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE,
- download->GetLastReason());
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED, download->GetLastReason());
EXPECT_TRUE(download->GetFullPath().empty());
// Target path should still be intact.
EXPECT_FALSE(download->GetTargetFilePath().empty());
@@ -1392,16 +1508,14 @@ IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest,
RunAllPendingInMessageLoop();
// Clear the old errors list.
- injector->ClearErrors();
- injector->InjectErrors();
+ injector->ClearError();
- PrepareToResume();
download->Resume();
WaitForCompletion(download);
EXPECT_EQ(download->GetState(), DownloadItem::COMPLETE);
}
-IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, Resume_Hash) {
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, Resume_Hash) {
using InjectedError = TestDownloadRequestHandler::InjectedError;
const char kExpectedHash[] =
"\xa7\x44\x49\x86\x24\xc6\x84\x6c\x89\xdf\xd8\xec\xa0\xe0\x61\x12\xdc\x80"
@@ -1412,8 +1526,8 @@ IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, Resume_Hash) {
// As a control, let's try GetHash() on an uninterrupted download.
request_handler.StartServing(parameters);
- DownloadItem* uninterrupted_download(StartDownloadAndReturnItem(
- initiator_shell_for_resumption(), request_handler.url()));
+ DownloadItem* uninterrupted_download(
+ StartDownloadAndReturnItem(shell(), request_handler.url()));
WaitForCompletion(uninterrupted_download);
EXPECT_EQ(expected_hash, uninterrupted_download->GetHash());
@@ -1431,11 +1545,10 @@ IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, Resume_Hash) {
request_handler.StartServing(parameters);
// Start and watch for interrupt.
- DownloadItem* download(StartDownloadAndReturnItem(
- initiator_shell_for_resumption(), request_handler.url()));
+ DownloadItem* download(
+ StartDownloadAndReturnItem(shell(), request_handler.url()));
WaitForInterrupt(download);
- PrepareToResume();
download->Resume();
WaitForInterrupt(download);
@@ -1456,14 +1569,13 @@ IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, Resume_Hash) {
// An interrupted download should remove the intermediate file when it is
// cancelled.
-IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest,
- CancelInterruptedDownload) {
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelInterruptedDownload) {
TestDownloadRequestHandler request_handler;
request_handler.StartServing(
TestDownloadRequestHandler::Parameters::WithSingleInterruption());
- DownloadItem* download = StartDownloadAndReturnItem(
- initiator_shell_for_resumption(), request_handler.url());
+ DownloadItem* download =
+ StartDownloadAndReturnItem(shell(), request_handler.url());
WaitForInterrupt(download);
base::FilePath intermediate_path = download->GetFullPath();
@@ -1479,14 +1591,13 @@ IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest,
EXPECT_TRUE(download->GetFullPath().empty());
}
-IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest,
- RemoveInterruptedDownload) {
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveInterruptedDownload) {
TestDownloadRequestHandler request_handler;
request_handler.StartServing(
TestDownloadRequestHandler::Parameters::WithSingleInterruption());
- DownloadItem* download = StartDownloadAndReturnItem(
- initiator_shell_for_resumption(), request_handler.url());
+ DownloadItem* download =
+ StartDownloadAndReturnItem(shell(), request_handler.url());
WaitForInterrupt(download);
base::FilePath intermediate_path = download->GetFullPath();
@@ -1523,14 +1634,14 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveCompletedDownload) {
EXPECT_TRUE(base::PathExists(target_path));
}
-IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, RemoveResumingDownload) {
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveResumingDownload) {
TestDownloadRequestHandler::Parameters parameters =
TestDownloadRequestHandler::Parameters::WithSingleInterruption();
TestDownloadRequestHandler request_handler;
request_handler.StartServing(parameters);
- DownloadItem* download = StartDownloadAndReturnItem(
- initiator_shell_for_resumption(), request_handler.url());
+ DownloadItem* download =
+ StartDownloadAndReturnItem(shell(), request_handler.url());
WaitForInterrupt(download);
base::FilePath intermediate_path(download->GetFullPath());
@@ -1539,15 +1650,13 @@ IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, RemoveResumingDownload) {
// Resume and remove download. We expect only a single OnDownloadCreated()
// call, and that's for the second download created below.
- MockDownloadManagerObserver dm_observer(
- DownloadManagerForShell(initiator_shell_for_resumption()));
+ MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell()));
EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
TestRequestStartHandler request_start_handler;
parameters.on_start_handler = request_start_handler.GetOnStartHandler();
request_handler.StartServing(parameters);
- PrepareToResume();
download->Resume();
request_start_handler.WaitForCallback();
@@ -1575,14 +1684,14 @@ IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, RemoveResumingDownload) {
EXPECT_TRUE(EnsureNoPendingDownloads());
}
-IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, CancelResumingDownload) {
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelResumingDownload) {
TestDownloadRequestHandler::Parameters parameters =
TestDownloadRequestHandler::Parameters::WithSingleInterruption();
TestDownloadRequestHandler request_handler;
request_handler.StartServing(parameters);
- DownloadItem* download = StartDownloadAndReturnItem(
- initiator_shell_for_resumption(), request_handler.url());
+ DownloadItem* download =
+ StartDownloadAndReturnItem(shell(), request_handler.url());
WaitForInterrupt(download);
base::FilePath intermediate_path(download->GetFullPath());
@@ -1591,15 +1700,13 @@ IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, CancelResumingDownload) {
// Resume and cancel download. We expect only a single OnDownloadCreated()
// call, and that's for the second download created below.
- MockDownloadManagerObserver dm_observer(
- DownloadManagerForShell(initiator_shell_for_resumption()));
+ MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell()));
EXPECT_CALL(dm_observer, OnDownloadCreated(_,_)).Times(1);
TestRequestStartHandler request_start_handler;
parameters.on_start_handler = request_start_handler.GetOnStartHandler();
request_handler.StartServing(parameters);
- PrepareToResume();
download->Resume();
request_start_handler.WaitForCallback();
@@ -1628,14 +1735,14 @@ IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, CancelResumingDownload) {
EXPECT_TRUE(EnsureNoPendingDownloads());
}
-IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, RemoveResumedDownload) {
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, RemoveResumedDownload) {
TestDownloadRequestHandler::Parameters parameters =
TestDownloadRequestHandler::Parameters::WithSingleInterruption();
TestDownloadRequestHandler request_handler;
request_handler.StartServing(parameters);
- DownloadItem* download = StartDownloadAndReturnItem(
- initiator_shell_for_resumption(), request_handler.url());
+ DownloadItem* download =
+ StartDownloadAndReturnItem(shell(), request_handler.url());
WaitForInterrupt(download);
base::FilePath intermediate_path(download->GetFullPath());
@@ -1645,11 +1752,9 @@ IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, RemoveResumedDownload) {
EXPECT_FALSE(base::PathExists(target_path));
// Resume and remove download. We don't expect OnDownloadCreated() calls.
- MockDownloadManagerObserver dm_observer(
- DownloadManagerForShell(initiator_shell_for_resumption()));
+ MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell()));
EXPECT_CALL(dm_observer, OnDownloadCreated(_, _)).Times(0);
- PrepareToResume();
download->Resume();
WaitForInProgress(download);
@@ -1663,14 +1768,14 @@ IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, RemoveResumedDownload) {
EXPECT_TRUE(EnsureNoPendingDownloads());
}
-IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, CancelResumedDownload) {
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, CancelResumedDownload) {
TestDownloadRequestHandler::Parameters parameters =
TestDownloadRequestHandler::Parameters::WithSingleInterruption();
TestDownloadRequestHandler request_handler;
request_handler.StartServing(parameters);
- DownloadItem* download = StartDownloadAndReturnItem(
- initiator_shell_for_resumption(), request_handler.url());
+ DownloadItem* download =
+ StartDownloadAndReturnItem(shell(), request_handler.url());
WaitForInterrupt(download);
base::FilePath intermediate_path(download->GetFullPath());
@@ -1680,11 +1785,9 @@ IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, CancelResumedDownload) {
EXPECT_FALSE(base::PathExists(target_path));
// Resume and remove download. We don't expect OnDownloadCreated() calls.
- MockDownloadManagerObserver dm_observer(
- DownloadManagerForShell(initiator_shell_for_resumption()));
+ MockDownloadManagerObserver dm_observer(DownloadManagerForShell(shell()));
EXPECT_CALL(dm_observer, OnDownloadCreated(_, _)).Times(0);
- PrepareToResume();
download->Resume();
WaitForInProgress(download);
@@ -1698,6 +1801,415 @@ IN_PROC_BROWSER_TEST_P(DownloadResumptionContentTest, CancelResumedDownload) {
EXPECT_TRUE(EnsureNoPendingDownloads());
}
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeRestoredDownload_NoFile) {
+ TestDownloadRequestHandler request_handler;
+ TestDownloadRequestHandler::Parameters parameters;
+ request_handler.StartServing(parameters);
+
+ base::FilePath intermediate_file_path =
+ GetDownloadDirectory().AppendASCII("intermediate");
+ std::vector<GURL> url_chain;
+
+ const int kIntermediateSize = 1331;
+ url_chain.push_back(request_handler.url());
+
+ DownloadItem* download = DownloadManagerForShell(shell())->CreateDownloadItem(
+ "F7FB1F59-7DE1-4845-AFDB-8A688F70F583",
+ 1,
+ intermediate_file_path,
+ base::FilePath(),
+ url_chain,
+ GURL(),
+ "application/octet-stream",
+ "application/octet-stream",
+ base::Time::Now(),
+ base::Time(),
+ parameters.etag,
+ std::string(),
+ kIntermediateSize,
+ parameters.size,
+ std::string(),
+ DownloadItem::INTERRUPTED,
+ DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+ DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED,
+ false);
+
+ download->Resume();
+ WaitForCompletion(download);
+
+ EXPECT_FALSE(base::PathExists(intermediate_file_path));
+ ReadAndVerifyFileContents(parameters.pattern_generator_seed,
+ parameters.size,
+ download->GetTargetFilePath());
+
+ TestDownloadRequestHandler::CompletedRequests completed_requests;
+ request_handler.GetCompletedRequestInfo(&completed_requests);
+
+ // There will be two requests. The first one is issued optimistically assuming
+ // that the intermediate file exists and matches the size expectations set
+ // forth in the download metadata (i.e. assuming that a 1331 byte file exists
+ // at |intermediate_file_path|.
+ //
+ // However, once the response is received, DownloadFile will report that the
+ // intermediate file doesn't exist and hence the download is marked
+ // interrupted again.
+ //
+ // The second request reads the entire entity.
+ //
+ // N.b. we can't make any assumptions about how many bytes are transferred by
+ // the first request since response data will be bufferred until DownloadFile
+ // is done initializing.
+ //
+ // TODO(asanka): Ideally we'll check that the intermediate file matches
+ // expectations prior to issuing the first resumption request.
+ ASSERT_EQ(2u, completed_requests.size());
+ EXPECT_EQ(parameters.size, completed_requests[1].transferred_byte_count);
+}
+
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeRestoredDownload_NoHash) {
+ TestDownloadRequestHandler request_handler;
+ TestDownloadRequestHandler::Parameters parameters;
+ request_handler.StartServing(parameters);
+
+ base::FilePath intermediate_file_path =
+ GetDownloadDirectory().AppendASCII("intermediate");
+ std::vector<GURL> url_chain;
+
+ const int kIntermediateSize = 1331;
+ std::vector<char> buffer(kIntermediateSize);
+ request_handler.GetPatternBytes(
+ parameters.pattern_generator_seed, 0, buffer.size(), buffer.data());
+ ASSERT_EQ(
+ kIntermediateSize,
+ base::WriteFile(intermediate_file_path, buffer.data(), buffer.size()));
+
+ url_chain.push_back(request_handler.url());
+
+ DownloadItem* download = DownloadManagerForShell(shell())->CreateDownloadItem(
+ "F7FB1F59-7DE1-4845-AFDB-8A688F70F583",
+ 1,
+ intermediate_file_path,
+ base::FilePath(),
+ url_chain,
+ GURL(),
+ "application/octet-stream",
+ "application/octet-stream",
+ base::Time::Now(),
+ base::Time(),
+ parameters.etag,
+ std::string(),
+ kIntermediateSize,
+ parameters.size,
+ std::string(),
+ DownloadItem::INTERRUPTED,
+ DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+ DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED,
+ false);
+
+ download->Resume();
+ WaitForCompletion(download);
+
+ EXPECT_FALSE(base::PathExists(intermediate_file_path));
+ ReadAndVerifyFileContents(parameters.pattern_generator_seed,
+ parameters.size,
+ download->GetTargetFilePath());
+
+ TestDownloadRequestHandler::CompletedRequests completed_requests;
+ request_handler.GetCompletedRequestInfo(&completed_requests);
+
+ // There's only one network request issued, and that is for the remainder of
+ // the file.
+ ASSERT_EQ(1u, completed_requests.size());
+ EXPECT_EQ(parameters.size - kIntermediateSize,
+ completed_requests[0].transferred_byte_count);
+}
+
+IN_PROC_BROWSER_TEST_F(DownloadContentTest,
+ ResumeRestoredDownload_EtagMismatch) {
+ TestDownloadRequestHandler request_handler;
+ TestDownloadRequestHandler::Parameters parameters;
+ request_handler.StartServing(parameters);
+
+ base::FilePath intermediate_file_path =
+ GetDownloadDirectory().AppendASCII("intermediate");
+ std::vector<GURL> url_chain;
+
+ const int kIntermediateSize = 1331;
+ std::vector<char> buffer(kIntermediateSize);
+ request_handler.GetPatternBytes(
+ parameters.pattern_generator_seed + 1, 0, buffer.size(), buffer.data());
+ ASSERT_EQ(
+ kIntermediateSize,
+ base::WriteFile(intermediate_file_path, buffer.data(), buffer.size()));
+
+ url_chain.push_back(request_handler.url());
+
+ DownloadItem* download = DownloadManagerForShell(shell())->CreateDownloadItem(
+ "F7FB1F59-7DE1-4845-AFDB-8A688F70F583",
+ 1,
+ intermediate_file_path,
+ base::FilePath(),
+ url_chain,
+ GURL(),
+ "application/octet-stream",
+ "application/octet-stream",
+ base::Time::Now(),
+ base::Time(),
+ "fake-etag",
+ std::string(),
+ kIntermediateSize,
+ parameters.size,
+ std::string(),
+ DownloadItem::INTERRUPTED,
+ DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+ DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED,
+ false);
+
+ download->Resume();
+ WaitForCompletion(download);
+
+ EXPECT_FALSE(base::PathExists(intermediate_file_path));
+ ReadAndVerifyFileContents(parameters.pattern_generator_seed,
+ parameters.size,
+ download->GetTargetFilePath());
+
+ TestDownloadRequestHandler::CompletedRequests completed_requests;
+ request_handler.GetCompletedRequestInfo(&completed_requests);
+
+ // There's only one network request issued. The If-Range header allows the
+ // server to respond with the entire entity in one go. The existing contents
+ // of the file should be discarded, and overwritten by the new contents.
+ ASSERT_EQ(1u, completed_requests.size());
+ EXPECT_EQ(parameters.size, completed_requests[0].transferred_byte_count);
+}
+
+IN_PROC_BROWSER_TEST_F(DownloadContentTest,
+ ResumeRestoredDownload_CorrectHash) {
+ TestDownloadRequestHandler request_handler;
+ TestDownloadRequestHandler::Parameters parameters;
+ request_handler.StartServing(parameters);
+
+ base::FilePath intermediate_file_path =
+ GetDownloadDirectory().AppendASCII("intermediate");
+ std::vector<GURL> url_chain;
+
+ const int kIntermediateSize = 1331;
+ std::vector<char> buffer(kIntermediateSize);
+ request_handler.GetPatternBytes(
+ parameters.pattern_generator_seed, 0, buffer.size(), buffer.data());
+ ASSERT_EQ(
+ kIntermediateSize,
+ base::WriteFile(intermediate_file_path, buffer.data(), buffer.size()));
+ // SHA-256 hash of the pattern bytes in buffer.
+ static const uint8_t kPartialHash[] = {
+ 0x77, 0x14, 0xfd, 0x83, 0x06, 0x15, 0x10, 0x7a, 0x47, 0x15, 0xd3,
+ 0xcf, 0xdd, 0x46, 0xa2, 0x61, 0x96, 0xff, 0xc3, 0xbb, 0x49, 0x30,
+ 0xaf, 0x31, 0x3a, 0x64, 0x0b, 0xd5, 0xfa, 0xb1, 0xe3, 0x81};
+
+ url_chain.push_back(request_handler.url());
+
+ DownloadItem* download = DownloadManagerForShell(shell())->CreateDownloadItem(
+ "F7FB1F59-7DE1-4845-AFDB-8A688F70F583",
+ 1,
+ intermediate_file_path,
+ base::FilePath(),
+ url_chain,
+ GURL(),
+ "application/octet-stream",
+ "application/octet-stream",
+ base::Time::Now(),
+ base::Time(),
+ parameters.etag,
+ std::string(),
+ kIntermediateSize,
+ parameters.size,
+ std::string(std::begin(kPartialHash), std::end(kPartialHash)),
+ DownloadItem::INTERRUPTED,
+ DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+ DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED,
+ false);
+
+ download->Resume();
+ WaitForCompletion(download);
+
+ EXPECT_FALSE(base::PathExists(intermediate_file_path));
+ ReadAndVerifyFileContents(parameters.pattern_generator_seed,
+ parameters.size,
+ download->GetTargetFilePath());
+
+ TestDownloadRequestHandler::CompletedRequests completed_requests;
+ request_handler.GetCompletedRequestInfo(&completed_requests);
+
+ // There's only one network request issued, and that is for the remainder of
+ // the file.
+ ASSERT_EQ(1u, completed_requests.size());
+ EXPECT_EQ(parameters.size - kIntermediateSize,
+ completed_requests[0].transferred_byte_count);
+
+ // SHA-256 hash of the entire 102400 bytes in the target file.
+ static const uint8_t kFullHash[] = {
+ 0xa7, 0x44, 0x49, 0x86, 0x24, 0xc6, 0x84, 0x6c, 0x89, 0xdf, 0xd8,
+ 0xec, 0xa0, 0xe0, 0x61, 0x12, 0xdc, 0x80, 0x13, 0xf2, 0x83, 0x49,
+ 0xa9, 0x14, 0x52, 0x32, 0xf0, 0x95, 0x20, 0xca, 0x5b, 0x30};
+ EXPECT_EQ(std::string(std::begin(kFullHash), std::end(kFullHash)),
+ download->GetHash());
+}
+
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeRestoredDownload_WrongHash) {
+ TestDownloadRequestHandler request_handler;
+ TestDownloadRequestHandler::Parameters parameters;
+ request_handler.StartServing(parameters);
+
+ base::FilePath intermediate_file_path =
+ GetDownloadDirectory().AppendASCII("intermediate");
+ std::vector<GURL> url_chain;
+
+ const int kIntermediateSize = 1331;
+ std::vector<char> buffer(kIntermediateSize);
+ ASSERT_EQ(
+ kIntermediateSize,
+ base::WriteFile(intermediate_file_path, buffer.data(), buffer.size()));
+ // SHA-256 hash of the expected pattern bytes in buffer. This doesn't match
+ // the current contents of the intermediate file which should all be 0.
+ static const uint8_t kPartialHash[] = {
+ 0x77, 0x14, 0xfd, 0x83, 0x06, 0x15, 0x10, 0x7a, 0x47, 0x15, 0xd3,
+ 0xcf, 0xdd, 0x46, 0xa2, 0x61, 0x96, 0xff, 0xc3, 0xbb, 0x49, 0x30,
+ 0xaf, 0x31, 0x3a, 0x64, 0x0b, 0xd5, 0xfa, 0xb1, 0xe3, 0x81};
+
+ url_chain.push_back(request_handler.url());
+
+ DownloadItem* download = DownloadManagerForShell(shell())->CreateDownloadItem(
+ "F7FB1F59-7DE1-4845-AFDB-8A688F70F583",
+ 1,
+ intermediate_file_path,
+ base::FilePath(),
+ url_chain,
+ GURL(),
+ "application/octet-stream",
+ "application/octet-stream",
+ base::Time::Now(),
+ base::Time(),
+ parameters.etag,
+ std::string(),
+ kIntermediateSize,
+ parameters.size,
+ std::string(std::begin(kPartialHash), std::end(kPartialHash)),
+ DownloadItem::INTERRUPTED,
+ DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+ DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED,
+ false);
+
+ download->Resume();
+ WaitForCompletion(download);
+
+ EXPECT_FALSE(base::PathExists(intermediate_file_path));
+ ReadAndVerifyFileContents(parameters.pattern_generator_seed,
+ parameters.size,
+ download->GetTargetFilePath());
+
+ TestDownloadRequestHandler::CompletedRequests completed_requests;
+ request_handler.GetCompletedRequestInfo(&completed_requests);
+
+ // There will be two requests. The first one is issued optimistically assuming
+ // that the intermediate file exists and matches the size expectations set
+ // forth in the download metadata (i.e. assuming that a 1331 byte file exists
+ // at |intermediate_file_path|.
+ //
+ // However, once the response is received, DownloadFile will report that the
+ // intermediate file doesn't match the expected hash.
+ //
+ // The second request reads the entire entity.
+ //
+ // N.b. we can't make any assumptions about how many bytes are transferred by
+ // the first request since response data will be bufferred until DownloadFile
+ // is done initializing.
+ //
+ // TODO(asanka): Ideally we'll check that the intermediate file matches
+ // expectations prior to issuing the first resumption request.
+ ASSERT_EQ(2u, completed_requests.size());
+ EXPECT_EQ(parameters.size, completed_requests[1].transferred_byte_count);
+
+ // SHA-256 hash of the entire 102400 bytes in the target file.
+ static const uint8_t kFullHash[] = {
+ 0xa7, 0x44, 0x49, 0x86, 0x24, 0xc6, 0x84, 0x6c, 0x89, 0xdf, 0xd8,
+ 0xec, 0xa0, 0xe0, 0x61, 0x12, 0xdc, 0x80, 0x13, 0xf2, 0x83, 0x49,
+ 0xa9, 0x14, 0x52, 0x32, 0xf0, 0x95, 0x20, 0xca, 0x5b, 0x30};
+ EXPECT_EQ(std::string(std::begin(kFullHash), std::end(kFullHash)),
+ download->GetHash());
+}
+
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, ResumeRestoredDownload_ShortFile) {
+ TestDownloadRequestHandler request_handler;
+ TestDownloadRequestHandler::Parameters parameters;
+ request_handler.StartServing(parameters);
+
+ base::FilePath intermediate_file_path =
+ GetDownloadDirectory().AppendASCII("intermediate");
+ std::vector<GURL> url_chain;
+
+ const int kIntermediateSize = 1331;
+ // Size of file is slightly shorter than the size known to DownloadItem.
+ std::vector<char> buffer(kIntermediateSize - 100);
+ request_handler.GetPatternBytes(
+ parameters.pattern_generator_seed, 0, buffer.size(), buffer.data());
+ ASSERT_EQ(
+ kIntermediateSize - 100,
+ base::WriteFile(intermediate_file_path, buffer.data(), buffer.size()));
+ url_chain.push_back(request_handler.url());
+
+ DownloadItem* download = DownloadManagerForShell(shell())->CreateDownloadItem(
+ "F7FB1F59-7DE1-4845-AFDB-8A688F70F583",
+ 1,
+ intermediate_file_path,
+ base::FilePath(),
+ url_chain,
+ GURL(),
+ "application/octet-stream",
+ "application/octet-stream",
+ base::Time::Now(),
+ base::Time(),
+ parameters.etag,
+ std::string(),
+ kIntermediateSize,
+ parameters.size,
+ std::string(),
+ DownloadItem::INTERRUPTED,
+ DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+ DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED,
+ false);
+
+ download->Resume();
+ WaitForCompletion(download);
+
+ EXPECT_FALSE(base::PathExists(intermediate_file_path));
+ ReadAndVerifyFileContents(parameters.pattern_generator_seed,
+ parameters.size,
+ download->GetTargetFilePath());
+
+ TestDownloadRequestHandler::CompletedRequests completed_requests;
+ request_handler.GetCompletedRequestInfo(&completed_requests);
+
+ // There will be two requests. The first one is issued optimistically assuming
+ // that the intermediate file exists and matches the size expectations set
+ // forth in the download metadata (i.e. assuming that a 1331 byte file exists
+ // at |intermediate_file_path|.
+ //
+ // However, once the response is received, DownloadFile will report that the
+ // intermediate file is too short and hence the download is marked interrupted
+ // again.
+ //
+ // The second request reads the entire entity.
+ //
+ // N.b. we can't make any assumptions about how many bytes are transferred by
+ // the first request since response data will be bufferred until DownloadFile
+ // is done initializing.
+ //
+ // TODO(asanka): Ideally we'll check that the intermediate file matches
+ // expectations prior to issuing the first resumption request.
+ ASSERT_EQ(2u, completed_requests.size());
+ EXPECT_EQ(parameters.size, completed_requests[1].transferred_byte_count);
+}
+
// Check that the cookie policy is correctly updated when downloading a file
// that redirects cross origin.
IN_PROC_BROWSER_TEST_F(DownloadContentTest, CookiePolicy) {
@@ -1834,6 +2346,81 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest,
ASSERT_TRUE(origin_two.ShutdownAndWaitUntilComplete());
}
+// A request for a non-existent resource should still result in a DownloadItem
+// that's created in an interrupted state.
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeServerError) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ GURL download_url =
+ embedded_test_server()->GetURL("/download/does-not-exist");
+ GURL document_url = embedded_test_server()->GetURL(
+ std::string("/download/download-attribute.html?target=") +
+ download_url.spec());
+
+ DownloadItem* download = StartDownloadAndReturnItem(shell(), document_url);
+ WaitForInterrupt(download);
+
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT,
+ download->GetLastReason());
+}
+
+namespace {
+
+void ErrorReturningRequestHandler(
+ const net::HttpRequestHeaders& headers,
+ const TestDownloadRequestHandler::OnStartResponseCallback& callback) {
+ callback.Run(std::string(), net::ERR_INTERNET_DISCONNECTED);
+}
+
+} // namespace
+
+// A request that fails before it gets a response from the server should also
+// result in a DownloadItem that's created in an interrupted state.
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeNetworkError) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ TestDownloadRequestHandler request_handler;
+ TestDownloadRequestHandler::Parameters parameters;
+
+ parameters.on_start_handler = base::Bind(&ErrorReturningRequestHandler);
+ request_handler.StartServing(parameters);
+
+ GURL document_url = embedded_test_server()->GetURL(
+ std::string("/download/download-attribute.html?target=") +
+ request_handler.url().spec());
+ DownloadItem* download = StartDownloadAndReturnItem(shell(), document_url);
+ WaitForInterrupt(download);
+
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED,
+ download->GetLastReason());
+}
+
+// A request that fails due to it being rejected by policy should result in a
+// DownloadItem that's marked as interrupted.
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeInvalidURL) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ GURL document_url = embedded_test_server()->GetURL(
+ "/download/download-attribute.html?target=about:version");
+ DownloadItem* download = StartDownloadAndReturnItem(shell(), document_url);
+ WaitForInterrupt(download);
+
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST,
+ download->GetLastReason());
+ EXPECT_FALSE(download->CanResume());
+}
+
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, DownloadAttributeBlobURL) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ GURL document_url =
+ embedded_test_server()->GetURL("/download/download-attribute-blob.html");
+ DownloadItem* download = StartDownloadAndReturnItem(shell(), document_url);
+ WaitForCompletion(download);
+
+ EXPECT_STREQ(FILE_PATH_LITERAL("suggested-filename.txt"),
+ download->GetTargetFilePath().BaseName().value().c_str());
+}
+
// The file empty.bin is served with a MIME type of application/octet-stream.
// The content body is empty. Make sure this case is handled properly and we
// don't regress on http://crbug.com/320394.
@@ -1854,9 +2441,11 @@ IN_PROC_BROWSER_TEST_F(DownloadContentTest, SniffedMimeType) {
EXPECT_TRUE(item->GetOriginalMimeType().empty());
}
-IN_PROC_BROWSER_TEST_F(DownloadContentTest, Spam) {
+IN_PROC_BROWSER_TEST_F(DownloadContentTest, DuplicateContentDisposition) {
ASSERT_TRUE(embedded_test_server()->Start());
+ // double-content-disposition.txt is served with two Content-Disposition
+ // headers, both of which are identical.
NavigateToURLAndWaitForDownload(
shell(),
embedded_test_server()->GetURL(
diff --git a/chromium/content/browser/download/download_create_info.cc b/chromium/content/browser/download/download_create_info.cc
index c09d713aa97..92b15849b37 100644
--- a/chromium/content/browser/download/download_create_info.cc
+++ b/chromium/content/browser/download/download_create_info.cc
@@ -5,7 +5,6 @@
#include "content/browser/download/download_create_info.h"
#include <string>
-#include <utility>
#include "base/format_macros.h"
#include "base/strings/stringprintf.h"
@@ -13,36 +12,24 @@
namespace content {
DownloadCreateInfo::DownloadCreateInfo(const base::Time& start_time,
- int64_t total_bytes,
const net::BoundNetLog& bound_net_log,
scoped_ptr<DownloadSaveInfo> save_info)
- : start_time(start_time),
- total_bytes(total_bytes),
- download_id(DownloadItem::kInvalidId),
+ : download_id(DownloadItem::kInvalidId),
+ start_time(start_time),
+ total_bytes(0),
has_user_gesture(false),
transition_type(ui::PAGE_TRANSITION_LINK),
+ result(DOWNLOAD_INTERRUPT_REASON_NONE),
save_info(std::move(save_info)),
request_bound_net_log(bound_net_log) {}
DownloadCreateInfo::DownloadCreateInfo()
: DownloadCreateInfo(base::Time(),
- 0,
net::BoundNetLog(),
make_scoped_ptr(new DownloadSaveInfo)) {}
DownloadCreateInfo::~DownloadCreateInfo() {}
-std::string DownloadCreateInfo::DebugString() const {
- return base::StringPrintf(
- "{"
- " download_id = %u"
- " url = \"%s\""
- " request_handle = %s"
- " total_bytes = %" PRId64 " }",
- download_id, url().spec().c_str(), request_handle->DebugString().c_str(),
- total_bytes);
-}
-
const GURL& DownloadCreateInfo::url() const {
return url_chain.empty() ? GURL::EmptyGURL() : url_chain.back();
}
diff --git a/chromium/content/browser/download/download_create_info.h b/chromium/content/browser/download/download_create_info.h
index 1767e45eebc..01e1ad5f014 100644
--- a/chromium/content/browser/download/download_create_info.h
+++ b/chromium/content/browser/download/download_create_info.h
@@ -16,6 +16,7 @@
#include "content/browser/download/download_file.h"
#include "content/browser/download/download_request_handle.h"
#include "content/common/content_export.h"
+#include "content/public/browser/download_interrupt_reasons.h"
#include "content/public/browser/download_save_info.h"
#include "net/log/net_log.h"
#include "ui/base/page_transition_types.h"
@@ -27,18 +28,18 @@ namespace content {
// want to pass |DownloadItem|s between threads.
struct CONTENT_EXPORT DownloadCreateInfo {
DownloadCreateInfo(const base::Time& start_time,
- int64_t total_bytes,
const net::BoundNetLog& bound_net_log,
scoped_ptr<DownloadSaveInfo> save_info);
DownloadCreateInfo();
~DownloadCreateInfo();
- std::string DebugString() const;
-
// The URL from which we are downloading. This is the final URL after any
// redirection by the server for |url_chain|.
const GURL& url() const;
+ // The ID of the download.
+ uint32_t download_id;
+
// The chain of redirects that leading up to and including the final URL.
std::vector<GURL> url_chain;
@@ -57,14 +58,35 @@ struct CONTENT_EXPORT DownloadCreateInfo {
// The total download size.
int64_t total_bytes;
- // The ID of the download.
- uint32_t download_id;
-
// True if the download was initiated by user action.
bool has_user_gesture;
ui::PageTransition transition_type;
+ // The remote IP address where the download was fetched from. Copied from
+ // UrlRequest::GetSocketAddress().
+ std::string remote_address;
+
+ // If the download is initially created in an interrupted state (because the
+ // response was in error), then |result| would be something other than
+ // INTERRUPT_REASON_NONE.
+ DownloadInterruptReason result;
+
+ // The download file save info.
+ scoped_ptr<DownloadSaveInfo> save_info;
+
+ // The handle to the URLRequest sourcing this download.
+ scoped_ptr<DownloadRequestHandleInterface> request_handle;
+
+ // The request's |BoundNetLog|, for "source_dependency" linking with the
+ // download item's.
+ const net::BoundNetLog request_bound_net_log;
+
+ // ---------------------------------------------------------------------------
+ // The remaining fields are Entity-body properties. These are only set if
+ // |result| is DOWNLOAD_INTERRUPT_REASON_NONE.
+ // ---------------------------------------------------------------------------
+
// The content-disposition string from the response header.
std::string content_disposition;
@@ -81,23 +103,9 @@ struct CONTENT_EXPORT DownloadCreateInfo {
// "If-Unmodified-Since" comparison.
std::string last_modified;
- // For continuing a download, the ETAG of the file.
+ // For continuing a download, the ETag of the file.
std::string etag;
- // The download file save info.
- scoped_ptr<DownloadSaveInfo> save_info;
-
- // The remote IP address where the download was fetched from. Copied from
- // UrlRequest::GetSocketAddress().
- std::string remote_address;
-
- // The handle to the URLRequest sourcing this download.
- scoped_ptr<DownloadRequestHandleInterface> request_handle;
-
- // The request's |BoundNetLog|, for "source_dependency" linking with the
- // download item's.
- const net::BoundNetLog request_bound_net_log;
-
private:
DISALLOW_COPY_AND_ASSIGN(DownloadCreateInfo);
};
diff --git a/chromium/content/public/browser/download_destination_observer.h b/chromium/content/browser/download/download_destination_observer.h
index b7b5e6282fb..6f76391ecf9 100644
--- a/chromium/content/public/browser/download_destination_observer.h
+++ b/chromium/content/browser/download/download_destination_observer.h
@@ -2,14 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_PUBLIC_BROWSER_DOWNLOAD_DESTINATION_OBSERVER_H_
-#define CONTENT_PUBLIC_BROWSER_DOWNLOAD_DESTINATION_OBSERVER_H_
+#ifndef CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_DESTINATION_OBSERVER_H_
+#define CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_DESTINATION_OBSERVER_H_
#include <stdint.h>
#include <string>
+#include "base/memory/scoped_ptr.h"
#include "content/public/browser/download_interrupt_reasons.h"
+#include "crypto/secure_hash.h"
namespace content {
@@ -26,14 +28,17 @@ namespace content {
class DownloadDestinationObserver {
public:
virtual void DestinationUpdate(int64_t bytes_so_far,
- int64_t bytes_per_sec,
- const std::string& hash_state) = 0;
+ int64_t bytes_per_sec) = 0;
- virtual void DestinationError(DownloadInterruptReason reason) = 0;
+ virtual void DestinationError(DownloadInterruptReason reason,
+ int64_t bytes_so_far,
+ scoped_ptr<crypto::SecureHash> hash_state) = 0;
- virtual void DestinationCompleted(const std::string& final_hash) = 0;
+ virtual void DestinationCompleted(
+ int64_t total_bytes,
+ scoped_ptr<crypto::SecureHash> hash_state) = 0;
};
} // namespace content
-#endif // CONTENT_PUBLIC_BROWSER_DOWNLOAD_DESTINATION_OBSERVER_H_
+#endif // CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_DESTINATION_OBSERVER_H_
diff --git a/chromium/content/browser/download/download_file.h b/chromium/content/browser/download/download_file.h
index 2514df15519..c30cab9fe30 100644
--- a/chromium/content/browser/download/download_file.h
+++ b/chromium/content/browser/download/download_file.h
@@ -14,6 +14,8 @@
#include "content/common/content_export.h"
#include "content/public/browser/download_interrupt_reasons.h"
+class GURL;
+
namespace content {
class DownloadManager;
@@ -55,6 +57,9 @@ class CONTENT_EXPORT DownloadFile {
// "Mark of the Web" information about its source. No uniquification
// will be performed.
virtual void RenameAndAnnotate(const base::FilePath& full_path,
+ const std::string& client_guid,
+ const GURL& source_url,
+ const GURL& referrer_url,
const RenameCompletionCallback& callback) = 0;
// Detach the file so it is not deleted on destruction.
@@ -63,30 +68,8 @@ class CONTENT_EXPORT DownloadFile {
// Abort the download and automatically close the file.
virtual void Cancel() = 0;
- virtual base::FilePath FullPath() const = 0;
+ virtual const base::FilePath& FullPath() const = 0;
virtual bool InProgress() const = 0;
- virtual int64_t CurrentSpeed() const = 0;
-
- // Set |hash| with sha256 digest for the file.
- // Returns true if digest is successfully calculated.
- virtual bool GetHash(std::string* hash) = 0;
-
- // Returns the current (intermediate) state of the hash as a byte string.
- virtual std::string GetHashState() = 0;
-
- // Set the application GUID to be used to identify the app to the
- // system AV function when scanning downloaded files. Should be called
- // before RenameAndAnnotate() to take effect.
- virtual void SetClientGuid(const std::string& guid) = 0;
-
- // For testing. Must be called on FILE thread.
- // TODO(rdsmith): Replace use of EnsureNoPendingDownloads()
- // on the DownloadManager with a test-specific DownloadFileFactory
- // which keeps track of the number of DownloadFiles.
- static int GetNumberOfDownloadFiles();
-
- protected:
- static int number_active_objects_;
};
} // namespace content
diff --git a/chromium/content/browser/download/download_file_factory.cc b/chromium/content/browser/download/download_file_factory.cc
index bae88bef34e..55e03469c89 100644
--- a/chromium/content/browser/download/download_file_factory.cc
+++ b/chromium/content/browser/download/download_file_factory.cc
@@ -15,15 +15,14 @@ DownloadFileFactory::~DownloadFileFactory() {}
DownloadFile* DownloadFileFactory::CreateFile(
scoped_ptr<DownloadSaveInfo> save_info,
const base::FilePath& default_downloads_directory,
- const GURL& url,
- const GURL& referrer_url,
- bool calculate_hash,
- scoped_ptr<ByteStreamReader> stream,
+ scoped_ptr<ByteStreamReader> byte_stream,
const net::BoundNetLog& bound_net_log,
base::WeakPtr<DownloadDestinationObserver> observer) {
- return new DownloadFileImpl(std::move(save_info), default_downloads_directory,
- url, referrer_url, calculate_hash,
- std::move(stream), bound_net_log, observer);
+ return new DownloadFileImpl(std::move(save_info),
+ default_downloads_directory,
+ std::move(byte_stream),
+ bound_net_log,
+ observer);
}
} // namespace content
diff --git a/chromium/content/browser/download/download_file_factory.h b/chromium/content/browser/download/download_file_factory.h
index 2600e3f8455..d29384dde08 100644
--- a/chromium/content/browser/download/download_file_factory.h
+++ b/chromium/content/browser/download/download_file_factory.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_FILE_FACTORY_H_
#define CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_FILE_FACTORY_H_
+#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
@@ -12,6 +13,10 @@
#include "content/common/content_export.h"
#include "url/gurl.h"
+namespace crypto {
+class SecureHash;
+}
+
namespace net {
class BoundNetLog;
}
@@ -31,10 +36,7 @@ class CONTENT_EXPORT DownloadFileFactory {
virtual DownloadFile* CreateFile(
scoped_ptr<DownloadSaveInfo> save_info,
const base::FilePath& default_downloads_directory,
- const GURL& url,
- const GURL& referrer_url,
- bool calculate_hash,
- scoped_ptr<ByteStreamReader> stream,
+ scoped_ptr<ByteStreamReader> byte_stream,
const net::BoundNetLog& bound_net_log,
base::WeakPtr<DownloadDestinationObserver> observer);
};
diff --git a/chromium/content/browser/download/download_file_impl.cc b/chromium/content/browser/download/download_file_impl.cc
index e8e31cee7be..6378b9c8d3b 100644
--- a/chromium/content/browser/download/download_file_impl.cc
+++ b/chromium/content/browser/download/download_file_impl.cc
@@ -14,11 +14,13 @@
#include "base/values.h"
#include "content/browser/byte_stream.h"
#include "content/browser/download/download_create_info.h"
+#include "content/browser/download/download_destination_observer.h"
#include "content/browser/download/download_interrupt_reasons_impl.h"
#include "content/browser/download/download_net_log_parameters.h"
#include "content/browser/download/download_stats.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/download_destination_observer.h"
+#include "crypto/secure_hash.h"
+#include "crypto/sha2.h"
#include "net/base/io_buffer.h"
namespace content {
@@ -29,28 +31,19 @@ const int kMaxTimeBlockingFileThreadMs = 1000;
// These constants control the default retry behavior for failing renames. Each
// retry is performed after a delay that is twice the previous delay. The
// initial delay is specified by kInitialRenameRetryDelayMs.
-const int kMaxRenameRetries = 3;
const int kInitialRenameRetryDelayMs = 200;
-int DownloadFile::number_active_objects_ = 0;
+// Number of times a failing rename is retried before giving up.
+const int kMaxRenameRetries = 3;
DownloadFileImpl::DownloadFileImpl(
scoped_ptr<DownloadSaveInfo> save_info,
const base::FilePath& default_download_directory,
- const GURL& url,
- const GURL& referrer_url,
- bool calculate_hash,
scoped_ptr<ByteStreamReader> stream,
const net::BoundNetLog& bound_net_log,
base::WeakPtr<DownloadDestinationObserver> observer)
- : file_(save_info->file_path,
- url,
- referrer_url,
- save_info->offset,
- calculate_hash,
- save_info->hash_state,
- std::move(save_info->file),
- bound_net_log),
+ : file_(bound_net_log),
+ save_info_(std::move(save_info)),
default_download_directory_(default_download_directory),
stream_reader_(std::move(stream)),
bytes_seen_(0),
@@ -60,7 +53,6 @@ DownloadFileImpl::DownloadFileImpl(
DownloadFileImpl::~DownloadFileImpl() {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- --number_active_objects_;
}
void DownloadFileImpl::Initialize(const InitializeCallback& callback) {
@@ -68,7 +60,12 @@ void DownloadFileImpl::Initialize(const InitializeCallback& callback) {
update_timer_.reset(new base::RepeatingTimer());
DownloadInterruptReason result =
- file_.Initialize(default_download_directory_);
+ file_.Initialize(save_info_->file_path,
+ default_download_directory_,
+ std::move(save_info_->file),
+ save_info_->offset,
+ save_info_->hash_of_partial_file,
+ std::move(save_info_->hash_state));
if (result != DOWNLOAD_INTERRUPT_REASON_NONE) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE, base::Bind(callback, result));
@@ -89,8 +86,6 @@ void DownloadFileImpl::Initialize(const InitializeCallback& callback) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE, base::Bind(
callback, DOWNLOAD_INTERRUPT_REASON_NONE));
-
- ++number_active_objects_;
}
DownloadInterruptReason DownloadFileImpl::AppendDataToFile(
@@ -109,18 +104,23 @@ DownloadInterruptReason DownloadFileImpl::AppendDataToFile(
void DownloadFileImpl::RenameAndUniquify(
const base::FilePath& full_path,
const RenameCompletionCallback& callback) {
- RenameWithRetryInternal(
- full_path, UNIQUIFY, kMaxRenameRetries, base::TimeTicks(), callback);
+ scoped_ptr<RenameParameters> parameters(
+ new RenameParameters(UNIQUIFY, full_path, callback));
+ RenameWithRetryInternal(std::move(parameters));
}
void DownloadFileImpl::RenameAndAnnotate(
const base::FilePath& full_path,
+ const std::string& client_guid,
+ const GURL& source_url,
+ const GURL& referrer_url,
const RenameCompletionCallback& callback) {
- RenameWithRetryInternal(full_path,
- ANNOTATE_WITH_SOURCE_INFORMATION,
- kMaxRenameRetries,
- base::TimeTicks(),
- callback);
+ scoped_ptr<RenameParameters> parameters(new RenameParameters(
+ ANNOTATE_WITH_SOURCE_INFORMATION, full_path, callback));
+ parameters->client_guid = client_guid;
+ parameters->source_url = source_url;
+ parameters->referrer_url = referrer_url;
+ RenameWithRetryInternal(std::move(parameters));
}
base::TimeDelta DownloadFileImpl::GetRetryDelayForFailedRename(
@@ -139,16 +139,12 @@ bool DownloadFileImpl::ShouldRetryFailedRename(DownloadInterruptReason reason) {
}
void DownloadFileImpl::RenameWithRetryInternal(
- const base::FilePath& full_path,
- RenameOption option,
- int retries_left,
- base::TimeTicks time_of_first_failure,
- const RenameCompletionCallback& callback) {
+ scoped_ptr<RenameParameters> parameters) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- base::FilePath new_path(full_path);
+ base::FilePath new_path = parameters->new_path;
- if ((option & UNIQUIFY) && full_path != file_.full_path()) {
+ if ((parameters->option & UNIQUIFY) && new_path != file_.full_path()) {
int uniquifier =
base::GetUniquePathNumber(new_path, base::FilePath::StringType());
if (uniquifier > 0)
@@ -164,36 +160,36 @@ void DownloadFileImpl::RenameWithRetryInternal(
// have less assurance that the file at file_.full_path() was the one we were
// working with.
if (ShouldRetryFailedRename(reason) && file_.in_progress() &&
- retries_left > 0) {
- int attempt_number = kMaxRenameRetries - retries_left;
+ parameters->retries_left > 0) {
+ int attempt_number = kMaxRenameRetries - parameters->retries_left;
+ --parameters->retries_left;
+ if (parameters->time_of_first_failure.is_null())
+ parameters->time_of_first_failure = base::TimeTicks::Now();
BrowserThread::PostDelayedTask(
BrowserThread::FILE,
FROM_HERE,
base::Bind(&DownloadFileImpl::RenameWithRetryInternal,
weak_factory_.GetWeakPtr(),
- full_path,
- option,
- --retries_left,
- time_of_first_failure.is_null() ? base::TimeTicks::Now()
- : time_of_first_failure,
- callback),
+ base::Passed(std::move(parameters))),
GetRetryDelayForFailedRename(attempt_number));
return;
}
- if (!time_of_first_failure.is_null())
+ if (!parameters->time_of_first_failure.is_null())
RecordDownloadFileRenameResultAfterRetry(
- base::TimeTicks::Now() - time_of_first_failure, reason);
+ base::TimeTicks::Now() - parameters->time_of_first_failure, reason);
if (reason == DOWNLOAD_INTERRUPT_REASON_NONE &&
- (option & ANNOTATE_WITH_SOURCE_INFORMATION)) {
+ (parameters->option & ANNOTATE_WITH_SOURCE_INFORMATION)) {
// Doing the annotation after the rename rather than before leaves
// a very small window during which the file has the final name but
// hasn't been marked with the Mark Of The Web. However, it allows
// anti-virus scanners on Windows to actually see the data
// (http://crbug.com/127999) under the correct name (which is information
// it uses).
- reason = file_.AnnotateWithSourceInformation();
+ reason = file_.AnnotateWithSourceInformation(parameters->client_guid,
+ parameters->source_url,
+ parameters->referrer_url);
}
if (reason != DOWNLOAD_INTERRUPT_REASON_NONE) {
@@ -208,8 +204,9 @@ void DownloadFileImpl::RenameWithRetryInternal(
}
BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(callback, reason, new_path));
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(parameters->completion_callback, reason, new_path));
}
void DownloadFileImpl::Detach() {
@@ -220,7 +217,7 @@ void DownloadFileImpl::Cancel() {
file_.Cancel();
}
-base::FilePath DownloadFileImpl::FullPath() const {
+const base::FilePath& DownloadFileImpl::FullPath() const {
return file_.full_path();
}
@@ -228,22 +225,6 @@ bool DownloadFileImpl::InProgress() const {
return file_.in_progress();
}
-int64_t DownloadFileImpl::CurrentSpeed() const {
- return rate_estimator_.GetCountPerSecond();
-}
-
-bool DownloadFileImpl::GetHash(std::string* hash) {
- return file_.GetHash(hash);
-}
-
-std::string DownloadFileImpl::GetHashState() {
- return file_.GetHashState();
-}
-
-void DownloadFileImpl::SetClientGuid(const std::string& guid) {
- file_.SetClientGuid(guid);
-}
-
void DownloadFileImpl::StreamActive() {
base::TimeTicks start(base::TimeTicks::Now());
base::TimeTicks now;
@@ -280,10 +261,6 @@ void DownloadFileImpl::StreamActive() {
stream_reader_->GetStatus());
SendUpdate();
base::TimeTicks close_start(base::TimeTicks::Now());
- if (reason == DOWNLOAD_INTERRUPT_REASON_NONE)
- file_.Finish();
- else
- file_.FinishWithError();
base::TimeTicks now(base::TimeTicks::Now());
disk_writes_time_ += (now - close_start);
RecordFileBandwidth(
@@ -321,24 +298,29 @@ void DownloadFileImpl::StreamActive() {
// Our observer will clean us up.
stream_reader_->RegisterCallback(base::Closure());
weak_factory_.InvalidateWeakPtrs();
- SendUpdate(); // Make info up to date before error.
+ SendUpdate(); // Make info up to date before error.
+ scoped_ptr<crypto::SecureHash> hash_state = file_.Finish();
BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ BrowserThread::UI,
+ FROM_HERE,
base::Bind(&DownloadDestinationObserver::DestinationError,
- observer_, reason));
+ observer_,
+ reason,
+ file_.bytes_so_far(),
+ base::Passed(&hash_state)));
} else if (state == ByteStreamReader::STREAM_COMPLETE) {
// Signal successful completion and shut down processing.
stream_reader_->RegisterCallback(base::Closure());
weak_factory_.InvalidateWeakPtrs();
- std::string hash;
- if (!GetHash(&hash) || file_.IsEmptyHash(hash))
- hash.clear();
SendUpdate();
+ scoped_ptr<crypto::SecureHash> hash_state = file_.Finish();
BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(
- &DownloadDestinationObserver::DestinationCompleted,
- observer_, hash));
+ BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(&DownloadDestinationObserver::DestinationCompleted,
+ observer_,
+ file_.bytes_so_far(),
+ base::Passed(&hash_state)));
}
if (bound_net_log_.IsCapturing()) {
bound_net_log_.AddEvent(
@@ -350,15 +332,23 @@ void DownloadFileImpl::StreamActive() {
void DownloadFileImpl::SendUpdate() {
BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
+ BrowserThread::UI,
+ FROM_HERE,
base::Bind(&DownloadDestinationObserver::DestinationUpdate,
- observer_, file_.bytes_so_far(), CurrentSpeed(),
- GetHashState()));
+ observer_,
+ file_.bytes_so_far(),
+ rate_estimator_.GetCountPerSecond()));
}
-// static
-int DownloadFile::GetNumberOfDownloadFiles() {
- return number_active_objects_;
-}
+DownloadFileImpl::RenameParameters::RenameParameters(
+ RenameOption option,
+ const base::FilePath& new_path,
+ const RenameCompletionCallback& completion_callback)
+ : option(option),
+ new_path(new_path),
+ retries_left(kMaxRenameRetries),
+ completion_callback(completion_callback) {}
+
+DownloadFileImpl::RenameParameters::~RenameParameters() {}
} // namespace content
diff --git a/chromium/content/browser/download/download_file_impl.h b/chromium/content/browser/download/download_file_impl.h
index 98381128505..93b1e551703 100644
--- a/chromium/content/browser/download/download_file_impl.h
+++ b/chromium/content/browser/download/download_file_impl.h
@@ -10,6 +10,7 @@
#include <stddef.h>
#include <stdint.h>
+#include "base/files/file.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
@@ -38,15 +39,11 @@ class CONTENT_EXPORT DownloadFileImpl : public DownloadFile {
// Note that the DownloadFileImpl automatically reads from the passed in
// stream, and sends updates and status of those reads to the
// DownloadDestinationObserver.
- DownloadFileImpl(
- scoped_ptr<DownloadSaveInfo> save_info,
- const base::FilePath& default_downloads_directory,
- const GURL& url,
- const GURL& referrer_url,
- bool calculate_hash,
- scoped_ptr<ByteStreamReader> stream,
- const net::BoundNetLog& bound_net_log,
- base::WeakPtr<DownloadDestinationObserver> observer);
+ DownloadFileImpl(scoped_ptr<DownloadSaveInfo> save_info,
+ const base::FilePath& default_downloads_directory,
+ scoped_ptr<ByteStreamReader> byte_stream,
+ const net::BoundNetLog& bound_net_log,
+ base::WeakPtr<DownloadDestinationObserver> observer);
~DownloadFileImpl() override;
@@ -55,15 +52,14 @@ class CONTENT_EXPORT DownloadFileImpl : public DownloadFile {
void RenameAndUniquify(const base::FilePath& full_path,
const RenameCompletionCallback& callback) override;
void RenameAndAnnotate(const base::FilePath& full_path,
+ const std::string& client_guid,
+ const GURL& source_url,
+ const GURL& referrer_url,
const RenameCompletionCallback& callback) override;
void Detach() override;
void Cancel() override;
- base::FilePath FullPath() const override;
+ const base::FilePath& FullPath() const override;
bool InProgress() const override;
- int64_t CurrentSpeed() const override;
- bool GetHash(std::string* hash) override;
- std::string GetHashState() override;
- void SetClientGuid(const std::string& guid) override;
protected:
// For test class overrides.
@@ -85,20 +81,29 @@ class CONTENT_EXPORT DownloadFileImpl : public DownloadFile {
ANNOTATE_WITH_SOURCE_INFORMATION = 1 << 1
};
- // Rename file_ to |new_path|.
- // |option| specifies additional operations to be performed during the rename.
- // See RenameOption above.
- // |retries_left| indicates how many times to retry the operation if the
- // rename fails with a transient error.
- // |time_of_first_failure| Set to an empty base::TimeTicks during the first
- // call. Once the first failure is seen, subsequent calls of
- // RenameWithRetryInternal will have a non-empty value keeping track of
- // the time of first observed failure. Used for UMA.
- void RenameWithRetryInternal(const base::FilePath& new_path,
- RenameOption option,
- int retries_left,
- base::TimeTicks time_of_first_failure,
- const RenameCompletionCallback& callback);
+ struct RenameParameters {
+ RenameParameters(RenameOption option,
+ const base::FilePath& new_path,
+ const RenameCompletionCallback& completion_callback);
+ ~RenameParameters();
+
+ RenameOption option;
+ base::FilePath new_path;
+ std::string client_guid; // See BaseFile::AnnotateWithSourceInformation()
+ GURL source_url; // See BaseFile::AnnotateWithSourceInformation()
+ GURL referrer_url; // See BaseFile::AnnotateWithSourceInformation()
+ int retries_left; // RenameWithRetryInternal() will
+ // automatically retry until this
+ // count reaches 0. Each attempt
+ // decrements this counter.
+ base::TimeTicks time_of_first_failure; // Set to empty at first, but is set
+ // when a failure is first
+ // encountered. Used for UMA.
+ RenameCompletionCallback completion_callback;
+ };
+
+ // Rename file_ based on |parameters|.
+ void RenameWithRetryInternal(scoped_ptr<RenameParameters> parameters);
// Send an update on our progress.
void SendUpdate();
@@ -110,6 +115,11 @@ class CONTENT_EXPORT DownloadFileImpl : public DownloadFile {
// The base file instance.
BaseFile file_;
+ // DownloadSaveInfo provided during construction. Since the DownloadFileImpl
+ // can be created on any thread, this holds the save_info_ until it can be
+ // used to initialize file_ on the FILE thread.
+ scoped_ptr<DownloadSaveInfo> save_info_;
+
// The default directory for creating the download file.
base::FilePath default_download_directory_;
diff --git a/chromium/content/browser/download/download_file_unittest.cc b/chromium/content/browser/download/download_file_unittest.cc
index 9630a49b066..d24eeb81392 100644
--- a/chromium/content/browser/download/download_file_unittest.cc
+++ b/chromium/content/browser/download/download_file_unittest.cc
@@ -4,7 +4,9 @@
#include <stddef.h>
#include <stdint.h>
+
#include <utility>
+#include <vector>
#include "base/files/file.h"
#include "base/files/file_util.h"
@@ -18,9 +20,9 @@
#include "content/browser/browser_thread_impl.h"
#include "content/browser/byte_stream.h"
#include "content/browser/download/download_create_info.h"
+#include "content/browser/download/download_destination_observer.h"
#include "content/browser/download/download_file_impl.h"
#include "content/browser/download/download_request_handle.h"
-#include "content/public/browser/download_destination_observer.h"
#include "content/public/browser/download_interrupt_reasons.h"
#include "content/public/browser/download_manager.h"
#include "content/public/test/mock_download_manager.h"
@@ -41,6 +43,14 @@ using ::testing::StrictMock;
namespace content {
namespace {
+std::string GetHexEncodedHashValue(crypto::SecureHash* hash_state) {
+ if (!hash_state)
+ return std::string();
+ std::vector<char> hash_value(hash_state->GetHashLength());
+ hash_state->Finish(&hash_value.front(), hash_value.size());
+ return base::HexEncode(&hash_value.front(), hash_value.size());
+}
+
class MockByteStreamReader : public ByteStreamReader {
public:
MockByteStreamReader() {}
@@ -55,21 +65,33 @@ class MockByteStreamReader : public ByteStreamReader {
class MockDownloadDestinationObserver : public DownloadDestinationObserver {
public:
- MOCK_METHOD3(DestinationUpdate, void(int64_t, int64_t, const std::string&));
- MOCK_METHOD1(DestinationError, void(DownloadInterruptReason));
- MOCK_METHOD1(DestinationCompleted, void(const std::string&));
+ MOCK_METHOD2(DestinationUpdate, void(int64_t, int64_t));
+ void DestinationError(DownloadInterruptReason reason,
+ int64_t bytes_so_far,
+ scoped_ptr<crypto::SecureHash> hash_state) override {
+ MockDestinationError(
+ reason, bytes_so_far, GetHexEncodedHashValue(hash_state.get()));
+ }
+ void DestinationCompleted(
+ int64_t total_bytes,
+ scoped_ptr<crypto::SecureHash> hash_state) override {
+ MockDestinationCompleted(total_bytes,
+ GetHexEncodedHashValue(hash_state.get()));
+ }
+
+ MOCK_METHOD3(MockDestinationError,
+ void(DownloadInterruptReason, int64_t, const std::string&));
+ MOCK_METHOD2(MockDestinationCompleted, void(int64_t, const std::string&));
// Doesn't override any methods in the base class. Used to make sure
// that the last DestinationUpdate before a Destination{Completed,Error}
// had the right values.
- MOCK_METHOD3(CurrentUpdateStatus, void(int64_t, int64_t, const std::string&));
+ MOCK_METHOD2(CurrentUpdateStatus, void(int64_t, int64_t));
};
MATCHER(IsNullCallback, "") { return (arg.is_null()); }
-typedef void (DownloadFile::*DownloadFileRenameMethodType)(
- const base::FilePath&,
- const DownloadFile::RenameCompletionCallback&);
+enum DownloadFileRenameMethodType { RENAME_AND_UNIQUIFY, RENAME_AND_ANNOTATE };
// This is a test DownloadFileImpl that has no retry delay and, on Posix,
// retries renames failed due to ACCESS_DENIED.
@@ -77,17 +99,11 @@ class TestDownloadFileImpl : public DownloadFileImpl {
public:
TestDownloadFileImpl(scoped_ptr<DownloadSaveInfo> save_info,
const base::FilePath& default_downloads_directory,
- const GURL& url,
- const GURL& referrer_url,
- bool calculate_hash,
scoped_ptr<ByteStreamReader> stream,
const net::BoundNetLog& bound_net_log,
base::WeakPtr<DownloadDestinationObserver> observer)
: DownloadFileImpl(std::move(save_info),
default_downloads_directory,
- url,
- referrer_url,
- calculate_hash,
std::move(stream),
bound_net_log,
observer) {}
@@ -111,11 +127,11 @@ class TestDownloadFileImpl : public DownloadFileImpl {
class DownloadFileTest : public testing::Test {
public:
-
- static const char* kTestData1;
- static const char* kTestData2;
- static const char* kTestData3;
- static const char* kDataHash;
+ static const char kTestData1[];
+ static const char kTestData2[];
+ static const char kTestData3[];
+ static const char kDataHash[];
+ static const char kEmptyHash[];
static const uint32_t kDummyDownloadId;
static const int kDummyChildId;
static const int kDummyRequestId;
@@ -126,27 +142,23 @@ class DownloadFileTest : public testing::Test {
input_stream_(NULL),
bytes_(-1),
bytes_per_sec_(-1),
- hash_state_("xyzzy"),
ui_thread_(BrowserThread::UI, &loop_),
file_thread_(BrowserThread::FILE, &loop_) {
}
~DownloadFileTest() override {}
- void SetUpdateDownloadInfo(int64_t bytes,
- int64_t bytes_per_sec,
- const std::string& hash_state) {
+ void SetUpdateDownloadInfo(int64_t bytes, int64_t bytes_per_sec) {
bytes_ = bytes;
bytes_per_sec_ = bytes_per_sec;
- hash_state_ = hash_state;
}
void ConfirmUpdateDownloadInfo() {
- observer_->CurrentUpdateStatus(bytes_, bytes_per_sec_, hash_state_);
+ observer_->CurrentUpdateStatus(bytes_, bytes_per_sec_);
}
void SetUp() override {
- EXPECT_CALL(*(observer_.get()), DestinationUpdate(_, _, _))
+ EXPECT_CALL(*(observer_.get()), DestinationUpdate(_, _))
.Times(AnyNumber())
.WillRepeatedly(Invoke(this, &DownloadFileTest::SetUpdateDownloadInfo));
}
@@ -176,15 +188,12 @@ class DownloadFileTest : public testing::Test {
.RetiresOnSaturation();
scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo());
- scoped_ptr<TestDownloadFileImpl> download_file_impl(
- new TestDownloadFileImpl(
- std::move(save_info), base::FilePath(),
- GURL(), // Source
- GURL(), // Referrer
- calculate_hash, scoped_ptr<ByteStreamReader>(input_stream_),
- net::BoundNetLog(), observer_factory_.GetWeakPtr()));
- download_file_impl->SetClientGuid("12345678-ABCD-1234-DCBA-123456789ABC");
- download_file_ = std::move(download_file_impl);
+ download_file_.reset(
+ new TestDownloadFileImpl(std::move(save_info),
+ base::FilePath(),
+ scoped_ptr<ByteStreamReader>(input_stream_),
+ net::BoundNetLog(),
+ observer_factory_.GetWeakPtr()));
EXPECT_CALL(*input_stream_, Read(_, _))
.WillOnce(Return(ByteStreamReader::STREAM_EMPTY))
@@ -269,19 +278,21 @@ class DownloadFileTest : public testing::Test {
}
void FinishStream(DownloadInterruptReason interrupt_reason,
- bool check_observer) {
+ bool check_observer,
+ const std::string& expected_hash) {
::testing::Sequence s1;
SetupFinishStream(interrupt_reason, s1);
sink_callback_.Run();
VerifyStreamAndSize();
if (check_observer) {
- EXPECT_CALL(*(observer_.get()), DestinationCompleted(_));
+ EXPECT_CALL(*(observer_.get()),
+ MockDestinationCompleted(_, expected_hash));
loop_.RunUntilIdle();
::testing::Mock::VerifyAndClearExpectations(observer_.get());
- EXPECT_CALL(*(observer_.get()), DestinationUpdate(_, _, _))
+ EXPECT_CALL(*(observer_.get()), DestinationUpdate(_, _))
.Times(AnyNumber())
- .WillRepeatedly(Invoke(this,
- &DownloadFileTest::SetUpdateDownloadInfo));
+ .WillRepeatedly(
+ Invoke(this, &DownloadFileTest::SetUpdateDownloadInfo));
}
}
@@ -289,14 +300,14 @@ class DownloadFileTest : public testing::Test {
const base::FilePath& full_path,
base::FilePath* result_path_p) {
return InvokeRenameMethodAndWaitForCallback(
- &DownloadFile::RenameAndUniquify, full_path, result_path_p);
+ RENAME_AND_UNIQUIFY, full_path, result_path_p);
}
DownloadInterruptReason RenameAndAnnotate(
const base::FilePath& full_path,
base::FilePath* result_path_p) {
return InvokeRenameMethodAndWaitForCallback(
- &DownloadFile::RenameAndAnnotate, full_path, result_path_p);
+ RENAME_AND_ANNOTATE, full_path, result_path_p);
}
void ExpectPermissionError(DownloadInterruptReason err) {
@@ -306,20 +317,40 @@ class DownloadFileTest : public testing::Test {
}
protected:
+ void InvokeRenameMethod(
+ DownloadFileRenameMethodType method,
+ const base::FilePath& full_path,
+ const DownloadFile::RenameCompletionCallback& completion_callback) {
+ switch (method) {
+ case RENAME_AND_UNIQUIFY:
+ download_file_->RenameAndUniquify(full_path, completion_callback);
+ break;
+
+ case RENAME_AND_ANNOTATE:
+ download_file_->RenameAndAnnotate(
+ full_path,
+ "12345678-ABCD-1234-DCBA-123456789ABC",
+ GURL(),
+ GURL(),
+ completion_callback);
+ break;
+ }
+ }
+
DownloadInterruptReason InvokeRenameMethodAndWaitForCallback(
DownloadFileRenameMethodType method,
const base::FilePath& full_path,
base::FilePath* result_path_p) {
DownloadInterruptReason result_reason(DOWNLOAD_INTERRUPT_REASON_NONE);
base::FilePath result_path;
-
base::RunLoop loop_runner;
- ((*download_file_).*method)(full_path,
- base::Bind(&DownloadFileTest::SetRenameResult,
- base::Unretained(this),
- loop_runner.QuitClosure(),
- &result_reason,
- result_path_p));
+ DownloadFile::RenameCompletionCallback completion_callback =
+ base::Bind(&DownloadFileTest::SetRenameResult,
+ base::Unretained(this),
+ loop_runner.QuitClosure(),
+ &result_reason,
+ result_path_p);
+ InvokeRenameMethod(method, full_path, completion_callback);
loop_runner.Run();
return result_reason;
}
@@ -340,7 +371,6 @@ class DownloadFileTest : public testing::Test {
// Latest update sent to the observer.
int64_t bytes_;
int64_t bytes_per_sec_;
- std::string hash_state_;
base::MessageLoop loop_;
@@ -390,15 +420,17 @@ class DownloadFileTestWithRename
// the value parameter.
INSTANTIATE_TEST_CASE_P(DownloadFile,
DownloadFileTestWithRename,
- ::testing::Values(&DownloadFile::RenameAndAnnotate,
- &DownloadFile::RenameAndUniquify));
+ ::testing::Values(RENAME_AND_ANNOTATE,
+ RENAME_AND_UNIQUIFY));
-const char* DownloadFileTest::kTestData1 =
+const char DownloadFileTest::kTestData1[] =
"Let's write some data to the file!\n";
-const char* DownloadFileTest::kTestData2 = "Writing more data.\n";
-const char* DownloadFileTest::kTestData3 = "Final line.";
-const char* DownloadFileTest::kDataHash =
+const char DownloadFileTest::kTestData2[] = "Writing more data.\n";
+const char DownloadFileTest::kTestData3[] = "Final line.";
+const char DownloadFileTest::kDataHash[] =
"CBF68BF10F8003DB86B31343AFAC8C7175BD03FB5FC905650F8C80AF087443A8";
+const char DownloadFileTest::kEmptyHash[] =
+ "E3B0C44298FC1C149AFBF4C8996FB92427AE41E4649B934CA495991B7852B855";
const uint32_t DownloadFileTest::kDummyDownloadId = 23;
const int DownloadFileTest::kDummyChildId = 3;
@@ -456,10 +488,7 @@ TEST_P(DownloadFileTestWithRename, RenameFileFinal) {
EXPECT_FALSE(base::PathExists(path_2));
EXPECT_TRUE(base::PathExists(path_3));
- // Should not be able to get the hash until the file is closed.
- std::string hash;
- EXPECT_FALSE(download_file_->GetHash(&hash));
- FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true);
+ FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true, kDataHash);
loop_.RunUntilIdle();
// Rename the file after downloading all the data and closing the file.
@@ -473,10 +502,6 @@ TEST_P(DownloadFileTestWithRename, RenameFileFinal) {
EXPECT_FALSE(base::PathExists(path_3));
EXPECT_TRUE(base::PathExists(path_4));
- // Check the hash.
- EXPECT_TRUE(download_file_->GetHash(&hash));
- EXPECT_EQ(kDataHash, base::HexEncode(hash.data(), hash.size()));
-
DestroyDownloadFile(0);
}
@@ -504,7 +529,7 @@ TEST_F(DownloadFileTest, RenameOverwrites) {
ASSERT_TRUE(base::ReadFileToString(new_path, &file_contents));
EXPECT_NE(std::string(file_data), file_contents);
- FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true);
+ FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true, kEmptyHash);
loop_.RunUntilIdle();
DestroyDownloadFile(0);
}
@@ -529,7 +554,7 @@ TEST_F(DownloadFileTest, RenameUniquifies) {
EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, RenameAndUniquify(path_1, NULL));
EXPECT_TRUE(base::PathExists(path_1_suffixed));
- FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true);
+ FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true, kEmptyHash);
loop_.RunUntilIdle();
DestroyDownloadFile(0);
}
@@ -546,7 +571,7 @@ TEST_F(DownloadFileTest, RenameRecognizesSelfConflict) {
RenameAndUniquify(initial_path, &new_path));
EXPECT_TRUE(base::PathExists(initial_path));
- FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true);
+ FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true, kEmptyHash);
loop_.RunUntilIdle();
DestroyDownloadFile(0);
EXPECT_EQ(initial_path.value(), new_path.value());
@@ -581,7 +606,7 @@ TEST_P(DownloadFileTestWithRename, RenameError) {
EXPECT_FALSE(base::PathExists(target_path_suffixed));
}
- FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true);
+ FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true, kEmptyHash);
loop_.RunUntilIdle();
DestroyDownloadFile(0);
}
@@ -644,10 +669,11 @@ TEST_P(DownloadFileTestWithRename, RenameWithErrorRetry) {
// The Rename() should fail here and enqueue a retry task without invoking
// the completion callback.
- ((*download_file_).*GetParam())(target_path,
- base::Bind(&TestRenameCompletionCallback,
- succeeding_run.QuitClosure(),
- &did_run_callback));
+ InvokeRenameMethod(GetParam(),
+ target_path,
+ base::Bind(&TestRenameCompletionCallback,
+ succeeding_run.QuitClosure(),
+ &did_run_callback));
EXPECT_FALSE(did_run_callback);
base::RunLoop first_failing_run;
@@ -673,7 +699,7 @@ TEST_P(DownloadFileTestWithRename, RenameWithErrorRetry) {
succeeding_run.Run();
EXPECT_TRUE(did_run_callback);
- FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true);
+ FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true, kEmptyHash);
loop_.RunUntilIdle();
DestroyDownloadFile(0);
}
@@ -688,10 +714,8 @@ TEST_F(DownloadFileTest, StreamEmptySuccess) {
// do anything.
AppendDataToFile(NULL, 0);
- // Finish the download this way and make sure we see it on the
- // observer.
- EXPECT_CALL(*(observer_.get()), DestinationCompleted(_));
- FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, false);
+ // Finish the download this way and make sure we see it on the observer.
+ FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true, kEmptyHash);
loop_.RunUntilIdle();
DestroyDownloadFile(0);
@@ -704,9 +728,10 @@ TEST_F(DownloadFileTest, StreamEmptyError) {
// Finish the download in error and make sure we see it on the
// observer.
- EXPECT_CALL(*(observer_.get()),
- DestinationError(
- DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED))
+ EXPECT_CALL(
+ *(observer_.get()),
+ MockDestinationError(
+ DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, 0, kEmptyHash))
.WillOnce(InvokeWithoutArgs(
this, &DownloadFileTest::ConfirmUpdateDownloadInfo));
@@ -715,9 +740,10 @@ TEST_F(DownloadFileTest, StreamEmptyError) {
// the last one may have the correct information even if the failure
// doesn't produce an update, as the timer update may have triggered at the
// same time.
- EXPECT_CALL(*(observer_.get()), CurrentUpdateStatus(0, _, _));
+ EXPECT_CALL(*(observer_.get()), CurrentUpdateStatus(0, _));
- FinishStream(DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, false);
+ FinishStream(
+ DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, false, kEmptyHash);
loop_.RunUntilIdle();
@@ -733,7 +759,7 @@ TEST_F(DownloadFileTest, StreamNonEmptySuccess) {
::testing::Sequence s1;
SetupDataAppend(chunks1, 2, s1);
SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, s1);
- EXPECT_CALL(*(observer_.get()), DestinationCompleted(_));
+ EXPECT_CALL(*(observer_.get()), MockDestinationCompleted(_, _));
sink_callback_.Run();
VerifyStreamAndSize();
loop_.RunUntilIdle();
@@ -751,8 +777,8 @@ TEST_F(DownloadFileTest, StreamNonEmptyError) {
SetupFinishStream(DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, s1);
EXPECT_CALL(*(observer_.get()),
- DestinationError(
- DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED))
+ MockDestinationError(
+ DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED, _, _))
.WillOnce(InvokeWithoutArgs(
this, &DownloadFileTest::ConfirmUpdateDownloadInfo));
@@ -762,8 +788,7 @@ TEST_F(DownloadFileTest, StreamNonEmptyError) {
// doesn't produce an update, as the timer update may have triggered at the
// same time.
EXPECT_CALL(*(observer_.get()),
- CurrentUpdateStatus(strlen(kTestData1) + strlen(kTestData2),
- _, _));
+ CurrentUpdateStatus(strlen(kTestData1) + strlen(kTestData2), _));
sink_callback_.Run();
loop_.RunUntilIdle();
@@ -771,26 +796,4 @@ TEST_F(DownloadFileTest, StreamNonEmptyError) {
DestroyDownloadFile(0);
}
-// Send some data, wait 3/4s of a second, run the message loop, and
-// confirm the values the observer received are correct.
-TEST_F(DownloadFileTest, ConfirmUpdate) {
- CreateDownloadFile(0, true);
-
- const char* chunks1[] = { kTestData1, kTestData2 };
- AppendDataToFile(chunks1, 2);
-
- // Run the message loops for 750ms and check for results.
- loop_.task_runner()->PostDelayedTask(FROM_HERE,
- base::MessageLoop::QuitWhenIdleClosure(),
- base::TimeDelta::FromMilliseconds(750));
- loop_.Run();
-
- EXPECT_EQ(static_cast<int64_t>(strlen(kTestData1) + strlen(kTestData2)),
- bytes_);
- EXPECT_EQ(download_file_->GetHashState(), hash_state_);
-
- FinishStream(DOWNLOAD_INTERRUPT_REASON_NONE, true);
- DestroyDownloadFile(0);
-}
-
} // namespace content
diff --git a/chromium/content/browser/download/download_interrupt_reasons_impl.cc b/chromium/content/browser/download/download_interrupt_reasons_impl.cc
index 2ed8f147ee0..406c4e9d33a 100644
--- a/chromium/content/browser/download/download_interrupt_reasons_impl.cc
+++ b/chromium/content/browser/download/download_interrupt_reasons_impl.cc
@@ -83,7 +83,8 @@ DownloadInterruptReason ConvertNetErrorToInterruptReason(
case net::ERR_TIMED_OUT:
return DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT;
- // The network connection has been lost.
+ // The network connection was lost or changed.
+ case net::ERR_NETWORK_CHANGED:
case net::ERR_INTERNET_DISCONNECTED:
return DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED;
diff --git a/chromium/content/browser/download/download_item_factory.h b/chromium/content/browser/download/download_item_factory.h
index 0069e43422e..caf8ef8ce4b 100644
--- a/chromium/content/browser/download/download_item_factory.h
+++ b/chromium/content/browser/download/download_item_factory.h
@@ -41,6 +41,7 @@ public:
virtual DownloadItemImpl* CreatePersistedItem(
DownloadItemImplDelegate* delegate,
+ const std::string& guid,
uint32_t download_id,
const base::FilePath& current_path,
const base::FilePath& target_path,
@@ -54,6 +55,7 @@ public:
const std::string& last_modified,
int64_t received_bytes,
int64_t total_bytes,
+ const std::string& hash,
DownloadItem::DownloadState state,
DownloadDangerType danger_type,
DownloadInterruptReason interrupt_reason,
diff --git a/chromium/content/browser/download/download_item_impl.cc b/chromium/content/browser/download/download_item_impl.cc
index cef57731792..08d90390a60 100644
--- a/chromium/content/browser/download/download_item_impl.cc
+++ b/chromium/content/browser/download/download_item_impl.cc
@@ -29,15 +29,18 @@
#include "base/bind.h"
#include "base/files/file_util.h"
#include "base/format_macros.h"
+#include "base/guid.h"
#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/stl_util.h"
+#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/download/download_create_info.h"
#include "content/browser/download/download_file.h"
#include "content/browser/download/download_interrupt_reasons_impl.h"
#include "content/browser/download/download_item_impl_delegate.h"
+#include "content/browser/download/download_net_log_parameters.h"
#include "content/browser/download/download_request_handle.h"
#include "content/browser/download/download_stats.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
@@ -50,7 +53,6 @@
#include "content/public/browser/download_url_parameters.h"
#include "content/public/common/content_features.h"
#include "content/public/common/referrer.h"
-#include "net/base/net_util.h"
namespace content {
@@ -99,13 +101,12 @@ bool IsDownloadResumptionEnabled() {
const uint32_t DownloadItem::kInvalidId = 0;
-const char DownloadItem::kEmptyFileHash[] = "";
-
// The maximum number of attempts we will make to resume automatically.
const int DownloadItemImpl::kMaxAutoResumeAttempts = 5;
// Constructor for reading from the history service.
DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate,
+ const std::string& guid,
uint32_t download_id,
const base::FilePath& current_path,
const base::FilePath& target_path,
@@ -119,27 +120,20 @@ DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate,
const std::string& last_modified,
int64_t received_bytes,
int64_t total_bytes,
+ const std::string& hash,
DownloadItem::DownloadState state,
DownloadDangerType danger_type,
DownloadInterruptReason interrupt_reason,
bool opened,
const net::BoundNetLog& bound_net_log)
- : is_save_package_download_(false),
+ : guid_(base::ToUpperASCII(guid)),
download_id_(download_id),
- current_path_(current_path),
target_path_(target_path),
- target_disposition_(TARGET_DISPOSITION_OVERWRITE),
url_chain_(url_chain),
referrer_url_(referrer_url),
- transition_type_(ui::PAGE_TRANSITION_LINK),
- has_user_gesture_(false),
mime_type_(mime_type),
original_mime_type_(original_mime_type),
total_bytes_(total_bytes),
- received_bytes_(received_bytes),
- bytes_per_sec_(0),
- last_modified_time_(last_modified),
- etag_(etag),
last_reason_(interrupt_reason),
start_tick_(base::TimeTicks()),
state_(ExternalToInternalState(state)),
@@ -147,20 +141,19 @@ DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate,
start_time_(start_time),
end_time_(end_time),
delegate_(delegate),
- is_paused_(false),
- auto_resume_count_(0),
- open_when_complete_(false),
- file_externally_removed_(false),
- auto_opened_(false),
- is_temporary_(false),
- all_data_saved_(state == COMPLETE),
- destination_error_(content::DOWNLOAD_INTERRUPT_REASON_NONE),
opened_(opened),
- delegate_delayed_complete_(false),
+ current_path_(current_path),
+ received_bytes_(received_bytes),
+ all_data_saved_(state == COMPLETE),
+ hash_(hash),
+ last_modified_time_(last_modified),
+ etag_(etag),
bound_net_log_(bound_net_log),
weak_ptr_factory_(this) {
delegate_->Attach();
- DCHECK_NE(IN_PROGRESS_INTERNAL, state_);
+ DCHECK(state_ == COMPLETE_INTERNAL || state_ == INTERRUPTED_INTERNAL ||
+ state_ == CANCELLED_INTERNAL);
+ DCHECK(base::IsValidGUID(guid_));
Init(false /* not actively downloading */, SRC_HISTORY_IMPORT);
}
@@ -169,7 +162,7 @@ DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate,
uint32_t download_id,
const DownloadCreateInfo& info,
const net::BoundNetLog& bound_net_log)
- : is_save_package_download_(false),
+ : guid_(base::ToUpperASCII(base::GenerateGUID())),
download_id_(download_id),
target_disposition_((info.save_info->prompt_for_save_location)
? TARGET_DISPOSITION_PROMPT
@@ -187,26 +180,14 @@ DownloadItemImpl::DownloadItemImpl(DownloadItemImplDelegate* delegate,
original_mime_type_(info.original_mime_type),
remote_address_(info.remote_address),
total_bytes_(info.total_bytes),
- received_bytes_(0),
- bytes_per_sec_(0),
- last_modified_time_(info.last_modified),
- etag_(info.etag),
- last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE),
+ last_reason_(info.result),
start_tick_(base::TimeTicks::Now()),
- state_(IN_PROGRESS_INTERNAL),
- danger_type_(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS),
+ state_(INITIAL_INTERNAL),
start_time_(info.start_time),
delegate_(delegate),
- is_paused_(false),
- auto_resume_count_(0),
- open_when_complete_(false),
- file_externally_removed_(false),
- auto_opened_(false),
is_temporary_(!info.save_info->file_path.empty()),
- all_data_saved_(false),
- destination_error_(content::DOWNLOAD_INTERRUPT_REASON_NONE),
- opened_(false),
- delegate_delayed_complete_(false),
+ last_modified_time_(info.last_modified),
+ etag_(info.etag),
bound_net_log_(bound_net_log),
weak_ptr_factory_(this) {
delegate_->Attach();
@@ -233,35 +214,17 @@ DownloadItemImpl::DownloadItemImpl(
const net::BoundNetLog& bound_net_log)
: is_save_package_download_(true),
request_handle_(std::move(request_handle)),
+ guid_(base::ToUpperASCII(base::GenerateGUID())),
download_id_(download_id),
- current_path_(path),
target_path_(path),
- target_disposition_(TARGET_DISPOSITION_OVERWRITE),
url_chain_(1, url),
- referrer_url_(GURL()),
- transition_type_(ui::PAGE_TRANSITION_LINK),
- has_user_gesture_(false),
mime_type_(mime_type),
original_mime_type_(mime_type),
- total_bytes_(0),
- received_bytes_(0),
- bytes_per_sec_(0),
- last_reason_(DOWNLOAD_INTERRUPT_REASON_NONE),
start_tick_(base::TimeTicks::Now()),
state_(IN_PROGRESS_INTERNAL),
- danger_type_(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS),
start_time_(base::Time::Now()),
delegate_(delegate),
- is_paused_(false),
- auto_resume_count_(0),
- open_when_complete_(false),
- file_externally_removed_(false),
- auto_opened_(false),
- is_temporary_(false),
- all_data_saved_(false),
- destination_error_(content::DOWNLOAD_INTERRUPT_REASON_NONE),
- opened_(false),
- delegate_delayed_complete_(false),
+ current_path_(path),
bound_net_log_(bound_net_log),
weak_ptr_factory_(this) {
delegate_->Attach();
@@ -294,6 +257,7 @@ void DownloadItemImpl::RemoveObserver(Observer* observer) {
void DownloadItemImpl::UpdateObservers() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DVLOG(20) << __FUNCTION__ << "()";
FOR_EACH_OBSERVER(Observer, observers_, OnDownloadUpdated(this));
}
@@ -317,7 +281,9 @@ void DownloadItemImpl::ValidateDangerousDownload() {
net::NetLog::TYPE_DOWNLOAD_ITEM_SAFETY_STATE_UPDATED,
base::Bind(&ItemCheckedNetLogCallback, GetDangerType()));
- UpdateObservers();
+ UpdateObservers(); // TODO(asanka): This is potentially unsafe. The download
+ // may not be in a consistent state or around at all after
+ // invoking observers. http://crbug.com/586610
MaybeCompleteDownload();
}
@@ -327,6 +293,7 @@ void DownloadItemImpl::StealDangerousDownload(
DVLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(IsDangerous());
+
if (download_file_) {
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::FILE,
@@ -345,17 +312,50 @@ void DownloadItemImpl::Pause() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Ignore irrelevant states.
- if (state_ != IN_PROGRESS_INTERNAL || is_paused_)
+ if (is_paused_)
return;
- request_handle_->PauseRequest();
- is_paused_ = true;
- UpdateObservers();
+ switch (state_) {
+ case CANCELLED_INTERNAL:
+ case COMPLETE_INTERNAL:
+ case COMPLETING_INTERNAL:
+ case INITIAL_INTERNAL:
+ case INTERRUPTED_INTERNAL:
+ case INTERRUPTED_TARGET_PENDING_INTERNAL:
+ case RESUMING_INTERNAL:
+ // No active request.
+ // TODO(asanka): In the case of RESUMING_INTERNAL, consider setting
+ // is_paused_ even if there's no request currently associated with this
+ // DII. When a request is assigned (due to a resumption, for example) we
+ // can honor the is_paused_ setting.
+ return;
+
+ case IN_PROGRESS_INTERNAL:
+ case TARGET_PENDING_INTERNAL:
+ request_handle_->PauseRequest();
+ is_paused_ = true;
+ UpdateObservers();
+ return;
+
+ case MAX_DOWNLOAD_INTERNAL_STATE:
+ case TARGET_RESOLVED_INTERNAL:
+ NOTREACHED();
+ }
}
void DownloadItemImpl::Resume() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DVLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
switch (state_) {
+ case CANCELLED_INTERNAL: // Nothing to resume.
+ case COMPLETE_INTERNAL:
+ case COMPLETING_INTERNAL:
+ case INITIAL_INTERNAL:
+ case INTERRUPTED_TARGET_PENDING_INTERNAL:
+ case RESUMING_INTERNAL: // Resumption in progress.
+ return;
+
+ case TARGET_PENDING_INTERNAL:
case IN_PROGRESS_INTERNAL:
if (!is_paused_)
return;
@@ -364,70 +364,25 @@ void DownloadItemImpl::Resume() {
UpdateObservers();
return;
- case COMPLETING_INTERNAL:
- case COMPLETE_INTERNAL:
- case CANCELLED_INTERNAL:
- case RESUMING_INTERNAL:
- return;
-
case INTERRUPTED_INTERNAL:
auto_resume_count_ = 0; // User input resets the counter.
ResumeInterruptedDownload();
+ UpdateObservers();
return;
case MAX_DOWNLOAD_INTERNAL_STATE:
+ case TARGET_RESOLVED_INTERNAL:
NOTREACHED();
}
}
void DownloadItemImpl::Cancel(bool user_cancel) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
DVLOG(20) << __FUNCTION__ << "() download = " << DebugString(true);
- if (state_ != IN_PROGRESS_INTERNAL &&
- state_ != INTERRUPTED_INTERNAL &&
- state_ != RESUMING_INTERNAL) {
- // Small downloads might be complete before this method has a chance to run.
- return;
- }
-
- if (IsDangerous()) {
- RecordDangerousDownloadDiscard(
- user_cancel ? DOWNLOAD_DISCARD_DUE_TO_USER_ACTION
- : DOWNLOAD_DISCARD_DUE_TO_SHUTDOWN,
- GetDangerType(),
- GetTargetFilePath());
- }
-
- last_reason_ = user_cancel ? DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
- : DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN;
-
- RecordDownloadCount(CANCELLED_COUNT);
-
- // TODO(rdsmith/benjhayden): Remove condition as part of
- // |SavePackage| integration.
- // |download_file_| can be NULL if Interrupt() is called after the
- // download file has been released.
- if (!is_save_package_download_ && download_file_)
- ReleaseDownloadFile(true);
-
- if (state_ == IN_PROGRESS_INTERNAL) {
- // Cancel the originating URL request unless it's already been cancelled
- // by interrupt.
- request_handle_->CancelRequest();
- }
-
- // Remove the intermediate file if we are cancelling an interrupted download.
- // Continuable interruptions leave the intermediate file around.
- if ((state_ == INTERRUPTED_INTERNAL || state_ == RESUMING_INTERNAL) &&
- !current_path_.empty()) {
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(base::IgnoreResult(&DeleteDownloadedFile), current_path_));
- current_path_.clear();
- }
-
- TransitionTo(CANCELLED_INTERNAL, UPDATE_OBSERVERS);
+ InterruptAndDiscardPartialState(
+ user_cancel ? DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
+ : DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN);
+ UpdateObservers();
}
void DownloadItemImpl::Remove() {
@@ -435,7 +390,8 @@ void DownloadItemImpl::Remove() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
delegate_->AssertStateConsistent(this);
- Cancel(true);
+ InterruptAndDiscardPartialState(DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
+ UpdateObservers();
delegate_->AssertStateConsistent(this);
NotifyRemoved();
@@ -478,6 +434,10 @@ uint32_t DownloadItemImpl::GetId() const {
return download_id_;
}
+const std::string& DownloadItemImpl::GetGuid() const {
+ return guid_;
+}
+
DownloadItem::DownloadState DownloadItemImpl::GetState() const {
return InternalToExternalState(state_);
}
@@ -495,26 +455,45 @@ bool DownloadItemImpl::IsTemporary() const {
}
bool DownloadItemImpl::CanResume() const {
- if ((GetState() == IN_PROGRESS) && IsPaused())
- return true;
-
- if (state_ != INTERRUPTED_INTERNAL)
- return false;
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ switch (state_) {
+ case INITIAL_INTERNAL:
+ case COMPLETING_INTERNAL:
+ case COMPLETE_INTERNAL:
+ case CANCELLED_INTERNAL:
+ case RESUMING_INTERNAL:
+ case INTERRUPTED_TARGET_PENDING_INTERNAL:
+ return false;
- // We currently only support HTTP(S) requests for download resumption.
- if (!GetURL().SchemeIsHTTPOrHTTPS())
- return false;
+ case TARGET_PENDING_INTERNAL:
+ case TARGET_RESOLVED_INTERNAL:
+ case IN_PROGRESS_INTERNAL:
+ return is_paused_;
+
+ case INTERRUPTED_INTERNAL: {
+ ResumeMode resume_mode = GetResumeMode();
+ // Only allow Resume() calls if the resumption mode requires a user
+ // action.
+ return IsDownloadResumptionEnabled() &&
+ (resume_mode == RESUME_MODE_USER_RESTART ||
+ resume_mode == RESUME_MODE_USER_CONTINUE);
+ }
- ResumeMode resume_mode = GetResumeMode();
- return IsDownloadResumptionEnabled() &&
- (resume_mode == RESUME_MODE_USER_RESTART ||
- resume_mode == RESUME_MODE_USER_CONTINUE);
+ case MAX_DOWNLOAD_INTERNAL_STATE:
+ NOTREACHED();
+ }
+ return false;
}
bool DownloadItemImpl::IsDone() const {
switch (state_) {
- case IN_PROGRESS_INTERNAL:
+ case INITIAL_INTERNAL:
case COMPLETING_INTERNAL:
+ case RESUMING_INTERNAL:
+ case TARGET_PENDING_INTERNAL:
+ case INTERRUPTED_TARGET_PENDING_INTERNAL:
+ case TARGET_RESOLVED_INTERNAL:
+ case IN_PROGRESS_INTERNAL:
return false;
case COMPLETE_INTERNAL:
@@ -524,14 +503,10 @@ bool DownloadItemImpl::IsDone() const {
case INTERRUPTED_INTERNAL:
return !CanResume();
- case RESUMING_INTERNAL:
- return false;
-
case MAX_DOWNLOAD_INTERNAL_STATE:
- break;
+ NOTREACHED();
}
- NOTREACHED();
- return true;
+ return false;
}
const GURL& DownloadItemImpl::GetURL() const {
@@ -628,10 +603,6 @@ const std::string& DownloadItemImpl::GetHash() const {
return hash_;
}
-const std::string& DownloadItemImpl::GetHashState() const {
- return hash_state_;
-}
-
bool DownloadItemImpl::GetFileExternallyRemoved() const {
return file_externally_removed_;
}
@@ -770,6 +741,14 @@ WebContents* DownloadItemImpl::GetWebContents() const {
void DownloadItemImpl::OnContentCheckCompleted(DownloadDangerType danger_type) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(AllDataSaved());
+
+ // Danger type is only allowed to be set on an active download after all data
+ // has been saved. This excludes all other states. In particular,
+ // OnContentCheckCompleted() isn't allowed on an INTERRUPTED download since
+ // such an interruption would need to happen between OnAllDataSaved() and
+ // OnContentCheckCompleted() during which no disk or network activity
+ // should've taken place.
+ DCHECK_EQ(state_, IN_PROGRESS_INTERNAL);
DVLOG(20) << __FUNCTION__ << " danger_type=" << danger_type
<< " download=" << DebugString(true);
SetDangerType(danger_type);
@@ -815,8 +794,7 @@ std::string DownloadItemImpl::DebugString(bool verbose) const {
if (verbose) {
description += base::StringPrintf(
- " total = %" PRId64
- " received = %" PRId64
+ " total = %" PRId64 " received = %" PRId64
" reason = %s"
" paused = %c"
" resume_mode = %s"
@@ -827,7 +805,8 @@ std::string DownloadItemImpl::DebugString(bool verbose) const {
" etag = '%s'"
" has_download_file = %s"
" url_chain = \n\t\"%s\"\n\t"
- " full_path = \"%" PRFilePath "\"\n\t"
+ " current_path = \"%" PRFilePath
+ "\"\n\t"
" target_path = \"%" PRFilePath "\"",
GetTotalBytes(),
GetReceivedBytes(),
@@ -854,62 +833,78 @@ std::string DownloadItemImpl::DebugString(bool verbose) const {
DownloadItemImpl::ResumeMode DownloadItemImpl::GetResumeMode() const {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ if (!IsDownloadResumptionEnabled())
+ return RESUME_MODE_INVALID;
+
+ // Only support resumption for HTTP(S).
+ if (!GetURL().SchemeIsHTTPOrHTTPS())
+ return RESUME_MODE_INVALID;
+
// We can't continue without a handle on the intermediate file.
// We also can't continue if we don't have some verifier to make sure
// we're getting the same file.
- const bool force_restart =
+ bool restart_required =
(current_path_.empty() || (etag_.empty() && last_modified_time_.empty()));
// We won't auto-restart if we've used up our attempts or the
// download has been paused by user action.
- const bool force_user =
+ bool user_action_required =
(auto_resume_count_ >= kMaxAutoResumeAttempts || is_paused_);
- ResumeMode mode = RESUME_MODE_INVALID;
-
switch(last_reason_) {
case DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR:
case DOWNLOAD_INTERRUPT_REASON_NETWORK_TIMEOUT:
- if (force_restart && force_user)
- mode = RESUME_MODE_USER_RESTART;
- else if (force_restart)
- mode = RESUME_MODE_IMMEDIATE_RESTART;
- else if (force_user)
- mode = RESUME_MODE_USER_CONTINUE;
- else
- mode = RESUME_MODE_IMMEDIATE_CONTINUE;
break;
case DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE:
+ // The server disagreed with the file offset that we sent.
+
+ case DOWNLOAD_INTERRUPT_REASON_FILE_HASH_MISMATCH:
+ // The file on disk was found to not match the expected hash. Discard and
+ // start from beginning.
+
case DOWNLOAD_INTERRUPT_REASON_FILE_TOO_SHORT:
- if (force_user)
- mode = RESUME_MODE_USER_RESTART;
- else
- mode = RESUME_MODE_IMMEDIATE_RESTART;
+ // The [possibly persisted] file offset disagreed with the file on disk.
+
+ // The intermediate stub is not usable and the server is responding. Hence
+ // retrying the request from the beginning is likely to work.
+ restart_required = true;
break;
case DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED:
case DOWNLOAD_INTERRUPT_REASON_NETWORK_DISCONNECTED:
case DOWNLOAD_INTERRUPT_REASON_NETWORK_SERVER_DOWN:
- case DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST:
case DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED:
+ case DOWNLOAD_INTERRUPT_REASON_SERVER_UNREACHABLE:
case DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN:
case DOWNLOAD_INTERRUPT_REASON_CRASH:
- if (force_restart)
- mode = RESUME_MODE_USER_RESTART;
- else
- mode = RESUME_MODE_USER_CONTINUE;
+ // It is not clear whether attempting a resumption is acceptable at this
+ // time or whether it would work at all. Hence allow the user to retry the
+ // download manually.
+ user_action_required = true;
+ break;
+
+ case DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE:
+ // There was no space. Require user interaction so that the user may, for
+ // example, choose a different location to store the file. Or they may
+ // free up some space on the targret device and retry. But try to reuse
+ // the partial stub.
+ user_action_required = true;
break;
case DOWNLOAD_INTERRUPT_REASON_FILE_FAILED:
case DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED:
- case DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE:
case DOWNLOAD_INTERRUPT_REASON_FILE_NAME_TOO_LONG:
case DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE:
- mode = RESUME_MODE_USER_RESTART;
+ // Assume the partial stub is unusable. Also it may not be possible to
+ // restart immediately.
+ user_action_required = true;
+ restart_required = true;
break;
case DOWNLOAD_INTERRUPT_REASON_NONE:
+ case DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST:
case DOWNLOAD_INTERRUPT_REASON_FILE_VIRUS_INFECTED:
case DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT:
case DOWNLOAD_INTERRUPT_REASON_USER_CANCELED:
@@ -918,14 +913,23 @@ DownloadItemImpl::ResumeMode DownloadItemImpl::GetResumeMode() const {
case DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED:
case DOWNLOAD_INTERRUPT_REASON_SERVER_CERT_PROBLEM:
case DOWNLOAD_INTERRUPT_REASON_SERVER_FORBIDDEN:
- mode = RESUME_MODE_INVALID;
- break;
+ // Unhandled.
+ return RESUME_MODE_INVALID;
}
- return mode;
+ if (user_action_required && restart_required)
+ return RESUME_MODE_USER_RESTART;
+
+ if (restart_required)
+ return RESUME_MODE_IMMEDIATE_RESTART;
+
+ if (user_action_required)
+ return RESUME_MODE_USER_CONTINUE;
+
+ return RESUME_MODE_IMMEDIATE_CONTINUE;
}
-void DownloadItemImpl::MergeOriginInfoOnResume(
+void DownloadItemImpl::UpdateValidatorsOnResumption(
const DownloadCreateInfo& new_create_info) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK_EQ(RESUMING_INTERNAL, state_);
@@ -955,8 +959,7 @@ void DownloadItemImpl::MergeOriginInfoOnResume(
origin_state |= ORIGIN_STATE_ON_RESUMPTION_VALIDATORS_CHANGED;
if (content_disposition_ != new_create_info.content_disposition)
origin_state |= ORIGIN_STATE_ON_RESUMPTION_CONTENT_DISPOSITION_CHANGED;
- RecordOriginStateOnResumption(new_create_info.save_info->offset != 0,
- origin_state);
+ RecordOriginStateOnResumption(received_bytes_ != 0, origin_state);
url_chain_.insert(
url_chain_.end(), chain_iter, new_create_info.url_chain.end());
@@ -992,18 +995,20 @@ void DownloadItemImpl::SetTotalBytes(int64_t total_bytes) {
total_bytes_ = total_bytes;
}
-void DownloadItemImpl::OnAllDataSaved(const std::string& final_hash) {
+void DownloadItemImpl::OnAllDataSaved(
+ int64_t total_bytes,
+ scoped_ptr<crypto::SecureHash> hash_state) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- DCHECK_EQ(IN_PROGRESS_INTERNAL, state_);
DCHECK(!all_data_saved_);
all_data_saved_ = true;
- DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true);
-
- // Store final hash and null out intermediate serialized hash state.
- hash_ = final_hash;
- hash_state_ = "";
+ SetTotalBytes(total_bytes);
+ UpdateProgress(total_bytes, 0);
+ SetHashState(std::move(hash_state));
+ hash_state_.reset(); // No need to retain hash_state_ since we are done with
+ // the download and don't expect to receive any more
+ // data.
+ DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true);
UpdateObservers();
}
@@ -1012,38 +1017,28 @@ void DownloadItemImpl::MarkAsComplete() {
DCHECK(all_data_saved_);
end_time_ = base::Time::Now();
- TransitionTo(COMPLETE_INTERNAL, UPDATE_OBSERVERS);
+ TransitionTo(COMPLETE_INTERNAL);
+ UpdateObservers();
}
void DownloadItemImpl::DestinationUpdate(int64_t bytes_so_far,
- int64_t bytes_per_sec,
- const std::string& hash_state) {
+ int64_t bytes_per_sec) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DVLOG(20) << __FUNCTION__ << " so_far=" << bytes_so_far
- << " per_sec=" << bytes_per_sec << " download="
- << DebugString(true);
-
- if (GetState() != IN_PROGRESS) {
- // Ignore if we're no longer in-progress. This can happen if we race a
- // Cancel on the UI thread with an update on the FILE thread.
- //
- // TODO(rdsmith): Arguably we should let this go through, as this means
- // the download really did get further than we know before it was
- // cancelled. But the gain isn't very large, and the code is more
- // fragile if it has to support in progress updates in a non-in-progress
- // state. This issue should be readdressed when we revamp performance
- // reporting.
- return;
- }
- bytes_per_sec_ = bytes_per_sec;
- hash_state_ = hash_state;
- received_bytes_ = bytes_so_far;
+ // If the download is in any other state we don't expect any
+ // DownloadDestinationObserver callbacks. An interruption or a cancellation
+ // results in a call to ReleaseDownloadFile which invalidates the weak
+ // reference held by the DownloadFile and hence cuts off any pending
+ // callbacks.
+ DCHECK(state_ == TARGET_PENDING_INTERNAL || state_ == IN_PROGRESS_INTERNAL);
- // If we've received more data than we were expecting (bad server info?),
- // revert to 'unknown size mode'.
- if (received_bytes_ > total_bytes_)
- total_bytes_ = 0;
+ // There must be no pending destination_error_.
+ DCHECK_EQ(destination_error_, DOWNLOAD_INTERRUPT_REASON_NONE);
+ DVLOG(20) << __FUNCTION__ << " so_far=" << bytes_so_far
+ << " per_sec=" << bytes_per_sec
+ << " download=" << DebugString(true);
+
+ UpdateProgress(bytes_so_far, bytes_per_sec);
if (bound_net_log_.IsCapturing()) {
bound_net_log_.AddEvent(
net::NetLog::TYPE_DOWNLOAD_ITEM_UPDATED,
@@ -1053,21 +1048,47 @@ void DownloadItemImpl::DestinationUpdate(int64_t bytes_so_far,
UpdateObservers();
}
-void DownloadItemImpl::DestinationError(DownloadInterruptReason reason) {
+void DownloadItemImpl::DestinationError(
+ DownloadInterruptReason reason,
+ int64_t bytes_so_far,
+ scoped_ptr<crypto::SecureHash> secure_hash) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ // If the download is in any other state we don't expect any
+ // DownloadDestinationObserver callbacks. An interruption or a cancellation
+ // results in a call to ReleaseDownloadFile which invalidates the weak
+ // reference held by the DownloadFile and hence cuts off any pending
+ // callbacks.
+ DCHECK(state_ == TARGET_PENDING_INTERNAL || state_ == IN_PROGRESS_INTERNAL);
+ DVLOG(20) << __FUNCTION__
+ << "() reason:" << DownloadInterruptReasonToString(reason);
+
// Postpone recognition of this error until after file name determination
// has completed and the intermediate file has been renamed to simplify
// resumption conditions.
- if (current_path_.empty() || target_path_.empty())
+ if (state_ == TARGET_PENDING_INTERNAL) {
+ received_bytes_ = bytes_so_far;
+ hash_state_ = std::move(secure_hash);
+ hash_.clear();
destination_error_ = reason;
- else
- Interrupt(reason);
+ return;
+ }
+ InterruptWithPartialState(bytes_so_far, std::move(secure_hash), reason);
+ UpdateObservers();
}
-void DownloadItemImpl::DestinationCompleted(const std::string& final_hash) {
+void DownloadItemImpl::DestinationCompleted(
+ int64_t total_bytes,
+ scoped_ptr<crypto::SecureHash> secure_hash) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ // If the download is in any other state we don't expect any
+ // DownloadDestinationObserver callbacks. An interruption or a cancellation
+ // results in a call to ReleaseDownloadFile which invalidates the weak
+ // reference held by the DownloadFile and hence cuts off any pending
+ // callbacks.
+ DCHECK(state_ == TARGET_PENDING_INTERNAL || state_ == IN_PROGRESS_INTERNAL);
DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true);
- if (GetState() != IN_PROGRESS)
- return;
- OnAllDataSaved(final_hash);
+
+ OnAllDataSaved(total_bytes, std::move(secure_hash));
MaybeCompleteDownload();
}
@@ -1111,24 +1132,79 @@ void DownloadItemImpl::Init(bool active,
// We're starting the download.
void DownloadItemImpl::Start(
scoped_ptr<DownloadFile> file,
- scoped_ptr<DownloadRequestHandleInterface> req_handle) {
+ scoped_ptr<DownloadRequestHandleInterface> req_handle,
+ const DownloadCreateInfo& new_create_info) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(!download_file_.get());
- DCHECK(file.get());
- DCHECK(req_handle.get());
+ DVLOG(20) << __FUNCTION__ << "() this=" << DebugString(true);
download_file_ = std::move(file);
request_handle_ = std::move(req_handle);
+ destination_error_ = DOWNLOAD_INTERRUPT_REASON_NONE;
- if (GetState() == CANCELLED) {
+ if (state_ == CANCELLED_INTERNAL) {
// The download was in the process of resuming when it was cancelled. Don't
// proceed.
ReleaseDownloadFile(true);
- request_handle_->CancelRequest();
+ if (request_handle_)
+ request_handle_->CancelRequest();
+ return;
+ }
+
+ // The state could be one of the following:
+ //
+ // INITIAL_INTERNAL: A normal download attempt.
+ //
+ // RESUMING_INTERNAL: A resumption attempt. May or may not have been
+ // successful.
+ DCHECK(state_ == INITIAL_INTERNAL || state_ == RESUMING_INTERNAL);
+
+ // If the state_ is INITIAL_INTERNAL, then the target path must be empty.
+ DCHECK(state_ != INITIAL_INTERNAL || target_path_.empty());
+
+ // If a resumption attempted failed, or if the download was DOA, then the
+ // download should go back to being interrupted.
+ if (new_create_info.result != DOWNLOAD_INTERRUPT_REASON_NONE) {
+ DCHECK(!download_file_.get());
+
+ // Download requests that are interrupted by Start() should result in a
+ // DownloadCreateInfo with an intact DownloadSaveInfo.
+ DCHECK(new_create_info.save_info);
+
+ int64_t offset = new_create_info.save_info->offset;
+ scoped_ptr<crypto::SecureHash> hash_state =
+ make_scoped_ptr(new_create_info.save_info->hash_state
+ ? new_create_info.save_info->hash_state->Clone()
+ : nullptr);
+
+ // Interrupted downloads also need a target path.
+ if (target_path_.empty()) {
+ received_bytes_ = offset;
+ hash_state_ = std::move(hash_state);
+ hash_.clear();
+ destination_error_ = new_create_info.result;
+ TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL);
+ DetermineDownloadTarget();
+ return;
+ }
+
+ // Otherwise, this was a resumption attempt which ended with an
+ // interruption. Continue with current target path.
+ TransitionTo(TARGET_RESOLVED_INTERNAL);
+ InterruptWithPartialState(
+ offset, std::move(hash_state), new_create_info.result);
+ UpdateObservers();
return;
}
- TransitionTo(IN_PROGRESS_INTERNAL, UPDATE_OBSERVERS);
+ // Successful download start.
+ DCHECK(download_file_.get());
+ DCHECK(request_handle_.get());
+
+ if (state_ == RESUMING_INTERNAL)
+ UpdateValidatorsOnResumption(new_create_info);
+
+ TransitionTo(TARGET_PENDING_INTERNAL);
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
@@ -1142,32 +1218,41 @@ void DownloadItemImpl::Start(
void DownloadItemImpl::OnDownloadFileInitialized(
DownloadInterruptReason result) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_EQ(state_, TARGET_PENDING_INTERNAL);
+ DVLOG(20) << __FUNCTION__
+ << "() result:" << DownloadInterruptReasonToString(result);
if (result != DOWNLOAD_INTERRUPT_REASON_NONE) {
- Interrupt(result);
- // TODO(rdsmith/asanka): Arguably we should show this in the UI, but
- // it's not at all clear what to show--we haven't done filename
- // determination, so we don't know what name to display. OTOH,
- // the failure mode of not showing the DI if the file initialization
- // fails isn't a good one. Can we hack up a name based on the
- // URLRequest? We'll need to make sure that initialization happens
- // properly. Possibly the right thing is to have the UI handle
- // this case specially.
- return;
+ // Whoops. That didn't work. Proceed as an interrupted download, but reset
+ // the partial state. Currently, the partial stub cannot be recovered if the
+ // download file initialization fails.
+ received_bytes_ = 0;
+ hash_state_.reset();
+ hash_.clear();
+ destination_error_ = result;
+ TransitionTo(INTERRUPTED_TARGET_PENDING_INTERNAL);
}
+ DetermineDownloadTarget();
+}
+
+void DownloadItemImpl::DetermineDownloadTarget() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DVLOG(20) << __FUNCTION__ << "() " << DebugString(true);
+
delegate_->DetermineDownloadTarget(
this, base::Bind(&DownloadItemImpl::OnDownloadTargetDetermined,
weak_ptr_factory_.GetWeakPtr()));
}
-// Called by delegate_ when the download target path has been
-// determined.
+// Called by delegate_ when the download target path has been determined.
void DownloadItemImpl::OnDownloadTargetDetermined(
const base::FilePath& target_path,
TargetDisposition disposition,
DownloadDangerType danger_type,
const base::FilePath& intermediate_path) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK(state_ == TARGET_PENDING_INTERNAL ||
+ state_ == INTERRUPTED_TARGET_PENDING_INTERNAL);
// If the |target_path| is empty, then we consider this download to be
// canceled.
@@ -1176,21 +1261,24 @@ void DownloadItemImpl::OnDownloadTargetDetermined(
return;
}
- // TODO(rdsmith,asanka): We are ignoring the possibility that the download
- // has been interrupted at this point until we finish the intermediate
- // rename and set the full path. That's dangerous, because we might race
- // with resumption, either manual (because the interrupt is visible to the
- // UI) or automatic. If we keep the "ignore an error on download until file
- // name determination complete" semantics, we need to make sure that the
- // error is kept completely invisible until that point.
-
- DVLOG(20) << __FUNCTION__ << " " << target_path.value() << " " << disposition
- << " " << danger_type << " " << DebugString(true);
+ DVLOG(20) << __FUNCTION__ << "() target_path:" << target_path.value()
+ << " disposition:" << disposition << " danger_type:" << danger_type
+ << " this:" << DebugString(true);
target_path_ = target_path;
target_disposition_ = disposition;
SetDangerType(danger_type);
+ // This was an interrupted download that was looking for a filename. Now that
+ // it has one, transition to interrupted.
+ if (state_ == INTERRUPTED_TARGET_PENDING_INTERNAL) {
+ InterruptWithPartialState(
+ received_bytes_, std::move(hash_state_), destination_error_);
+ destination_error_ = DOWNLOAD_INTERRUPT_REASON_NONE;
+ UpdateObservers();
+ return;
+ }
+
// We want the intermediate and target paths to refer to the same directory so
// that they are both on the same device and subject to same
// space/permission/availability constraints.
@@ -1231,27 +1319,38 @@ void DownloadItemImpl::OnDownloadRenamedToIntermediateName(
DownloadInterruptReason reason,
const base::FilePath& full_path) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DCHECK_EQ(state_, TARGET_PENDING_INTERNAL);
DVLOG(20) << __FUNCTION__ << " download=" << DebugString(true);
+ TransitionTo(TARGET_RESOLVED_INTERNAL);
+
+ // If the intermediate rename fails while there's also a destination_error_,
+ // then the former is considered the critical error since it requires
+ // discarding the partial state.
+ if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) {
+ // TODO(asanka): Even though the rename failed, it may still be possible to
+ // recover the partial state from the 'before' name.
+ InterruptAndDiscardPartialState(reason);
+ UpdateObservers();
+ return;
+ }
+
if (DOWNLOAD_INTERRUPT_REASON_NONE != destination_error_) {
- // Process destination error. If both |reason| and |destination_error_|
- // refer to actual errors, we want to use the |destination_error_| as the
- // argument to the Interrupt() routine, as it happened first.
- if (reason == DOWNLOAD_INTERRUPT_REASON_NONE)
- SetFullPath(full_path);
- Interrupt(destination_error_);
- destination_error_ = DOWNLOAD_INTERRUPT_REASON_NONE;
- } else if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) {
- Interrupt(reason);
- // All file errors result in file deletion above; no need to cleanup. The
- // current_path_ should be empty. Resuming this download will force a
- // restart and a re-doing of filename determination.
- DCHECK(current_path_.empty());
- } else {
SetFullPath(full_path);
+ InterruptWithPartialState(
+ received_bytes_, std::move(hash_state_), destination_error_);
+ destination_error_ = DOWNLOAD_INTERRUPT_REASON_NONE;
UpdateObservers();
- MaybeCompleteDownload();
+ return;
}
+
+ SetFullPath(full_path);
+ TransitionTo(IN_PROGRESS_INTERNAL);
+ // TODO(asanka): Calling UpdateObservers() prior to MaybeCompleteDownload() is
+ // not safe. The download could be in an underminate state after invoking
+ // observers. http://crbug.com/586610
+ UpdateObservers();
+ MaybeCompleteDownload();
}
// When SavePackage downloads MHTML to GData (see
@@ -1272,12 +1371,8 @@ void DownloadItemImpl::MaybeCompleteDownload() {
weak_ptr_factory_.GetWeakPtr())))
return;
- // TODO(rdsmith): DCHECK that we only pass through this point
- // once per download. The natural way to do this is by a state
- // transition on the DownloadItem.
-
- // Confirm we're in the proper set of states to be here;
- // have all data, have a history handle, (validated or safe).
+ // Confirm we're in the proper set of states to be here; have all data, have a
+ // history handle, (validated or safe).
DCHECK_EQ(IN_PROGRESS_INTERNAL, state_);
DCHECK(!IsDangerous());
DCHECK(all_data_saved_);
@@ -1301,9 +1396,8 @@ void DownloadItemImpl::OnDownloadCompleting() {
// TODO(rdsmith/benjhayden): Remove as part of SavePackage integration.
if (is_save_package_download_) {
// Avoid doing anything on the file thread; there's nothing we control
- // there.
- // Strictly speaking, this skips giving the embedder a chance to open
- // the download. But on a save package download, there's no real
+ // there. Strictly speaking, this skips giving the embedder a chance to
+ // open the download. But on a save package download, there's no real
// concept of opening.
Completed();
return;
@@ -1316,10 +1410,15 @@ void DownloadItemImpl::OnDownloadCompleting() {
base::Bind(&DownloadItemImpl::OnDownloadRenamedToFinalName,
weak_ptr_factory_.GetWeakPtr());
BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
+ BrowserThread::FILE,
+ FROM_HERE,
base::Bind(&DownloadFile::RenameAndAnnotate,
base::Unretained(download_file_.get()),
- GetTargetFilePath(), callback));
+ GetTargetFilePath(),
+ delegate_->GetApplicationClientIdForFileScanning(),
+ GetURL(),
+ GetReferrerUrl(),
+ callback));
}
void DownloadItemImpl::OnDownloadRenamedToFinalName(
@@ -1339,11 +1438,11 @@ void DownloadItemImpl::OnDownloadRenamedToFinalName(
<< " " << DebugString(false);
if (DOWNLOAD_INTERRUPT_REASON_NONE != reason) {
- Interrupt(reason);
-
- // All file errors should have resulted in in file deletion above. On
- // resumption we will need to re-do filename determination.
- DCHECK(current_path_.empty());
+ // Failure to perform the final rename is considered fatal. TODO(asanka): It
+ // may not be, in which case we should figure out whether we can recover the
+ // state.
+ InterruptAndDiscardPartialState(reason);
+ UpdateObservers();
return;
}
@@ -1356,14 +1455,14 @@ void DownloadItemImpl::OnDownloadRenamedToFinalName(
}
// Complete the download and release the DownloadFile.
- DCHECK(download_file_.get());
+ DCHECK(download_file_);
ReleaseDownloadFile(false);
// We're not completely done with the download item yet, but at this
// point we're committed to complete the download. Cancels (or Interrupts,
// though it's not clear how they could happen) after this point will be
// ignored.
- TransitionTo(COMPLETING_INTERNAL, DONT_UPDATE_OBSERVERS);
+ TransitionTo(COMPLETING_INTERNAL);
if (delegate_->ShouldOpenDownload(
this, base::Bind(&DownloadItemImpl::DelayedDownloadOpened,
@@ -1389,7 +1488,7 @@ void DownloadItemImpl::Completed() {
DCHECK(all_data_saved_);
end_time_ = base::Time::Now();
- TransitionTo(COMPLETE_INTERNAL, UPDATE_OBSERVERS);
+ TransitionTo(COMPLETE_INTERNAL);
RecordDownloadCompleted(start_tick_, received_bytes_);
if (auto_opened_) {
@@ -1404,32 +1503,28 @@ void DownloadItemImpl::Completed() {
OpenDownload();
auto_opened_ = true;
- UpdateObservers();
}
-}
-
-void DownloadItemImpl::OnResumeRequestStarted(
- DownloadItem* item,
- DownloadInterruptReason interrupt_reason) {
- // If |item| is not NULL, then Start() has been called already, and nothing
- // more needs to be done here.
- if (item) {
- DCHECK_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, interrupt_reason);
- DCHECK_EQ(static_cast<DownloadItem*>(this), item);
- return;
- }
- // Otherwise, the request failed without passing through
- // DownloadResourceHandler::OnResponseStarted.
- DCHECK_NE(DOWNLOAD_INTERRUPT_REASON_NONE, interrupt_reason);
- Interrupt(interrupt_reason);
+ UpdateObservers();
}
// **** End of Download progression cascade
-// An error occurred somewhere.
-void DownloadItemImpl::Interrupt(DownloadInterruptReason reason) {
+void DownloadItemImpl::InterruptAndDiscardPartialState(
+ DownloadInterruptReason reason) {
+ InterruptWithPartialState(0, scoped_ptr<crypto::SecureHash>(), reason);
+}
+
+void DownloadItemImpl::InterruptWithPartialState(
+ int64_t bytes_so_far,
+ scoped_ptr<crypto::SecureHash> hash_state,
+ DownloadInterruptReason reason) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK_NE(DOWNLOAD_INTERRUPT_REASON_NONE, reason);
+ DVLOG(20) << __FUNCTION__
+ << "() reason:" << DownloadInterruptReasonToString(reason)
+ << " bytes_so_far:" << bytes_so_far
+ << " hash_state:" << (hash_state ? "Valid" : "Invalid")
+ << " this=" << DebugString(true);
// Somewhat counter-intuitively, it is possible for us to receive an
// interrupt after we've already been interrupted. The generation of
@@ -1439,56 +1534,130 @@ void DownloadItemImpl::Interrupt(DownloadInterruptReason reason) {
// respectively), and since we choose not to keep state on the File thread,
// this is the place where the races collide. It's also possible for
// interrupts to race with cancels.
+ switch (state_) {
+ case CANCELLED_INTERNAL:
+ // If the download is already cancelled, then there's no point in
+ // transitioning out to interrupted.
+ case COMPLETING_INTERNAL:
+ case COMPLETE_INTERNAL:
+ // Already complete.
+ return;
- // Whatever happens, the first one to hit the UI thread wins.
- if (state_ != IN_PROGRESS_INTERNAL && state_ != RESUMING_INTERNAL)
- return;
+ case INITIAL_INTERNAL:
+ case MAX_DOWNLOAD_INTERNAL_STATE:
+ NOTREACHED();
+ return;
- last_reason_ = reason;
+ case INTERRUPTED_TARGET_PENDING_INTERNAL:
+ case IN_PROGRESS_INTERNAL:
+ case TARGET_PENDING_INTERNAL:
+ case TARGET_RESOLVED_INTERNAL:
+ // last_reason_ needs to be set for GetResumeMode() to work.
+ last_reason_ = reason;
+
+ if (download_file_) {
+ ResumeMode resume_mode = GetResumeMode();
+ ReleaseDownloadFile(resume_mode != RESUME_MODE_IMMEDIATE_CONTINUE &&
+ resume_mode != RESUME_MODE_USER_CONTINUE);
+ }
+ break;
- ResumeMode resume_mode = GetResumeMode();
+ case RESUMING_INTERNAL:
+ case INTERRUPTED_INTERNAL:
+ DCHECK(!download_file_);
+ // The first non-cancel interrupt reason wins in cases where multiple
+ // things go wrong.
+ if (reason != DOWNLOAD_INTERRUPT_REASON_USER_CANCELED &&
+ reason != DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN)
+ return;
- if (state_ == IN_PROGRESS_INTERNAL) {
- // Cancel (delete file) if:
- // 1) we're going to restart.
- // 2) Resumption isn't possible (download was cancelled or blocked due to
- // security restrictions).
- // 3) Resumption isn't enabled.
- // No point in leaving data around we aren't going to use.
- ReleaseDownloadFile(resume_mode == RESUME_MODE_IMMEDIATE_RESTART ||
- resume_mode == RESUME_MODE_USER_RESTART ||
- resume_mode == RESUME_MODE_INVALID ||
- !IsDownloadResumptionEnabled());
+ last_reason_ = reason;
+ if (!current_path_.empty()) {
+ // There is no download file and this is transitioning from INTERRUPTED
+ // to CANCELLED. The intermediate file is no longer usable, and should
+ // be deleted.
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(base::IgnoreResult(&DeleteDownloadedFile),
+ current_path_));
+ current_path_.clear();
+ }
+ break;
+ }
- // Cancel the originating URL request.
- request_handle_->CancelRequest();
+ // Reset all data saved, as even if we did save all the data we're going to go
+ // through another round of downloading when we resume. There's a potential
+ // problem here in the abstract, as if we did download all the data and then
+ // run into a continuable error, on resumption we won't download any more
+ // data. However, a) there are currently no continuable errors that can occur
+ // after we download all the data, and b) if there were, that would probably
+ // simply result in a null range request, which would generate a
+ // DestinationCompleted() notification from the DownloadFile, which would
+ // behave properly with setting all_data_saved_ to false here.
+ all_data_saved_ = false;
+
+ if (current_path_.empty()) {
+ hash_state_.reset();
+ hash_.clear();
+ received_bytes_ = 0;
} else {
- DCHECK(!download_file_.get());
+ UpdateProgress(bytes_so_far, 0);
+ SetHashState(std::move(hash_state));
}
- // Reset all data saved, as even if we did save all the data we're going
- // to go through another round of downloading when we resume.
- // There's a potential problem here in the abstract, as if we did download
- // all the data and then run into a continuable error, on resumption we
- // won't download any more data. However, a) there are currently no
- // continuable errors that can occur after we download all the data, and
- // b) if there were, that would probably simply result in a null range
- // request, which would generate a DestinationCompleted() notification
- // from the DownloadFile, which would behave properly with setting
- // all_data_saved_ to false here.
- all_data_saved_ = false;
+ if (request_handle_)
+ request_handle_->CancelRequest();
+
+ if (reason == DOWNLOAD_INTERRUPT_REASON_USER_CANCELED ||
+ reason == DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN) {
+ if (IsDangerous()) {
+ RecordDangerousDownloadDiscard(
+ reason == DOWNLOAD_INTERRUPT_REASON_USER_CANCELED
+ ? DOWNLOAD_DISCARD_DUE_TO_USER_ACTION
+ : DOWNLOAD_DISCARD_DUE_TO_SHUTDOWN,
+ GetDangerType(), GetTargetFilePath());
+ }
+
+ RecordDownloadCount(CANCELLED_COUNT);
+ TransitionTo(CANCELLED_INTERNAL);
+ return;
+ }
- TransitionTo(INTERRUPTED_INTERNAL, DONT_UPDATE_OBSERVERS);
RecordDownloadInterrupted(reason, received_bytes_, total_bytes_);
if (!GetWebContents())
RecordDownloadCount(INTERRUPTED_WITHOUT_WEBCONTENTS);
+ TransitionTo(INTERRUPTED_INTERNAL);
AutoResumeIfValid();
- UpdateObservers();
+}
+
+void DownloadItemImpl::UpdateProgress(int64_t bytes_so_far,
+ int64_t bytes_per_sec) {
+ received_bytes_ = bytes_so_far;
+ bytes_per_sec_ = bytes_per_sec;
+
+ // If we've received more data than we were expecting (bad server info?),
+ // revert to 'unknown size mode'.
+ if (received_bytes_ > total_bytes_)
+ total_bytes_ = 0;
+}
+
+void DownloadItemImpl::SetHashState(scoped_ptr<crypto::SecureHash> hash_state) {
+ hash_state_ = std::move(hash_state);
+ if (!hash_state_) {
+ hash_.clear();
+ return;
+ }
+
+ scoped_ptr<crypto::SecureHash> clone_of_hash_state(hash_state_->Clone());
+ std::vector<char> hash_value(clone_of_hash_state->GetHashLength());
+ clone_of_hash_state->Finish(&hash_value.front(), hash_value.size());
+ hash_.assign(hash_value.begin(), hash_value.end());
}
void DownloadItemImpl::ReleaseDownloadFile(bool destroy_file) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ DVLOG(20) << __FUNCTION__ << "() destroy_file:" << destroy_file;
if (destroy_file) {
BrowserThread::PostTask(
@@ -1514,6 +1683,11 @@ void DownloadItemImpl::ReleaseDownloadFile(bool destroy_file) {
bool DownloadItemImpl::IsDownloadReadyForCompletion(
const base::Closure& state_change_notification) {
+ // If the download hasn't progressed to the IN_PROGRESS state, then it's not
+ // ready for completion.
+ if (state_ != IN_PROGRESS_INTERNAL)
+ return false;
+
// If we don't have all the data, the download is not ready for
// completion.
if (!AllDataSaved())
@@ -1524,20 +1698,13 @@ bool DownloadItemImpl::IsDownloadReadyForCompletion(
if (IsDangerous())
return false;
- // If the download isn't active (e.g. has been cancelled) it's not
- // ready for completion.
- if (state_ != IN_PROGRESS_INTERNAL)
- return false;
-
- // If the target filename hasn't been determined, then it's not ready for
- // completion. This is checked in ReadyForDownloadCompletionDone().
- if (GetTargetFilePath().empty())
- return false;
-
- // This is checked in NeedsRename(). Without this conditional,
- // browser_tests:DownloadTest.DownloadMimeType fails the DCHECK.
- if (target_path_.DirName() != current_path_.DirName())
- return false;
+ // Check for consistency before invoking delegate. Since there are no pending
+ // target determination calls and the download is in progress, both the target
+ // and current paths should be non-empty and they should point to the same
+ // directory.
+ DCHECK(!target_path_.empty());
+ DCHECK(!current_path_.empty());
+ DCHECK(target_path_.DirName() == current_path_.DirName());
// Give the delegate a chance to hold up a stop sign. It'll call
// use back through the passed callback if it does and that state changes.
@@ -1547,8 +1714,7 @@ bool DownloadItemImpl::IsDownloadReadyForCompletion(
return true;
}
-void DownloadItemImpl::TransitionTo(DownloadInternalState new_state,
- ShouldUpdateObservers notify_action) {
+void DownloadItemImpl::TransitionTo(DownloadInternalState new_state) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (state_ == new_state)
@@ -1557,49 +1723,89 @@ void DownloadItemImpl::TransitionTo(DownloadInternalState new_state,
DownloadInternalState old_state = state_;
state_ = new_state;
+ DCHECK(is_save_package_download_
+ ? IsValidSavePackageStateTransition(old_state, new_state)
+ : IsValidStateTransition(old_state, new_state))
+ << "Invalid state transition from:" << DebugDownloadStateString(old_state)
+ << " to:" << DebugDownloadStateString(new_state);
+
switch (state_) {
+ case INITIAL_INTERNAL:
+ NOTREACHED();
+ break;
+
+ case TARGET_PENDING_INTERNAL:
+ case TARGET_RESOLVED_INTERNAL:
+ case INTERRUPTED_TARGET_PENDING_INTERNAL:
+ break;
+
+ case IN_PROGRESS_INTERNAL:
+ DCHECK(!current_path_.empty()) << "Current output path must be known.";
+ DCHECK(!target_path_.empty()) << "Target path must be known.";
+ DCHECK(current_path_.DirName() == target_path_.DirName())
+ << "Current output directory must match target directory.";
+ DCHECK(download_file_) << "Output file must be owned by download item.";
+ DCHECK(request_handle_) << "Download source must be active.";
+ DCHECK(!is_paused_) << "At the time a download enters IN_PROGRESS state, "
+ "it must not be paused.";
+ break;
+
case COMPLETING_INTERNAL:
+ DCHECK(all_data_saved_) << "All data must be saved prior to completion.";
+ DCHECK(!download_file_)
+ << "Download file must be released prior to completion.";
+ DCHECK(!target_path_.empty()) << "Target path must be known.";
+ DCHECK(current_path_ == target_path_)
+ << "Current output path must match target path.";
+
bound_net_log_.AddEvent(
net::NetLog::TYPE_DOWNLOAD_ITEM_COMPLETING,
base::Bind(&ItemCompletingNetLogCallback, received_bytes_, &hash_));
break;
+
case COMPLETE_INTERNAL:
bound_net_log_.AddEvent(
net::NetLog::TYPE_DOWNLOAD_ITEM_FINISHED,
base::Bind(&ItemFinishedNetLogCallback, auto_opened_));
break;
+
case INTERRUPTED_INTERNAL:
bound_net_log_.AddEvent(
net::NetLog::TYPE_DOWNLOAD_ITEM_INTERRUPTED,
- base::Bind(&ItemInterruptedNetLogCallback, last_reason_,
- received_bytes_, &hash_state_));
+ base::Bind(
+ &ItemInterruptedNetLogCallback, last_reason_, received_bytes_));
break;
- case IN_PROGRESS_INTERNAL:
- if (old_state == INTERRUPTED_INTERNAL) {
- bound_net_log_.AddEvent(
- net::NetLog::TYPE_DOWNLOAD_ITEM_RESUMED,
- base::Bind(&ItemResumingNetLogCallback,
- false, last_reason_, received_bytes_, &hash_state_));
- }
+
+ case RESUMING_INTERNAL:
+ bound_net_log_.AddEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_RESUMED,
+ base::Bind(&ItemResumingNetLogCallback,
+ false,
+ last_reason_,
+ received_bytes_));
break;
+
case CANCELLED_INTERNAL:
bound_net_log_.AddEvent(
net::NetLog::TYPE_DOWNLOAD_ITEM_CANCELED,
- base::Bind(&ItemCanceledNetLogCallback, received_bytes_,
- &hash_state_));
+ base::Bind(&ItemCanceledNetLogCallback, received_bytes_));
break;
- default:
+
+ case MAX_DOWNLOAD_INTERNAL_STATE:
+ NOTREACHED();
break;
}
- DVLOG(20) << " " << __FUNCTION__ << "()" << " this = " << DebugString(true)
- << " " << InternalToExternalState(old_state)
- << " " << InternalToExternalState(state_);
+ DVLOG(20) << " " << __FUNCTION__ << "()"
+ << " from:" << DebugDownloadStateString(old_state)
+ << " to:" << DebugDownloadStateString(state_)
+ << " this = " << DebugString(true);
+ bool is_done =
+ (state_ == COMPLETE_INTERNAL || state_ == INTERRUPTED_INTERNAL ||
+ state_ == RESUMING_INTERNAL || state_ == CANCELLED_INTERNAL);
+ bool was_done =
+ (old_state == COMPLETE_INTERNAL || old_state == INTERRUPTED_INTERNAL ||
+ old_state == RESUMING_INTERNAL || old_state == CANCELLED_INTERNAL);
- bool is_done = (state_ != IN_PROGRESS_INTERNAL &&
- state_ != COMPLETING_INTERNAL);
- bool was_done = (old_state != IN_PROGRESS_INTERNAL &&
- old_state != COMPLETING_INTERNAL);
// Termination
if (is_done && !was_done)
bound_net_log_.EndEvent(net::NetLog::TYPE_DOWNLOAD_ITEM_ACTIVE);
@@ -1612,9 +1818,6 @@ void DownloadItemImpl::TransitionTo(DownloadInternalState new_state,
this, SRC_ACTIVE_DOWNLOAD,
&file_name));
}
-
- if (notify_action == UPDATE_OBSERVERS)
- UpdateObservers();
}
void DownloadItemImpl::SetDangerType(DownloadDangerType danger_type) {
@@ -1676,45 +1879,52 @@ void DownloadItemImpl::ResumeInterruptedDownload() {
if (state_ != INTERRUPTED_INTERNAL)
return;
+ // We are starting a new request. Shake off all pending operations.
+ DCHECK(!download_file_);
+ weak_ptr_factory_.InvalidateWeakPtrs();
+
// Reset the appropriate state if restarting.
ResumeMode mode = GetResumeMode();
if (mode == RESUME_MODE_IMMEDIATE_RESTART ||
mode == RESUME_MODE_USER_RESTART) {
received_bytes_ = 0;
- hash_state_ = "";
- last_modified_time_ = "";
- etag_ = "";
- }
-
- scoped_ptr<DownloadUrlParameters> download_params;
- if (GetWebContents()) {
- download_params =
- DownloadUrlParameters::FromWebContents(GetWebContents(), GetURL());
- } else {
- download_params = make_scoped_ptr(new DownloadUrlParameters(
- GetURL(), -1, -1, -1, GetBrowserContext()->GetResourceContext()));
+ last_modified_time_.clear();
+ etag_.clear();
+ hash_.clear();
+ hash_state_.reset();
}
+ // Avoid using the WebContents even if it's still around. Resumption requests
+ // are consistently routed through the no-renderer code paths so that the
+ // request will not be dropped if the WebContents (and by extension, the
+ // associated renderer) goes away before a response is received.
+ scoped_ptr<DownloadUrlParameters> download_params(new DownloadUrlParameters(
+ GetURL(), -1, -1, -1, GetBrowserContext()->GetResourceContext()));
download_params->set_file_path(GetFullPath());
download_params->set_offset(GetReceivedBytes());
- download_params->set_hash_state(GetHashState());
download_params->set_last_modified(GetLastModifiedTime());
download_params->set_etag(GetETag());
- download_params->set_callback(
- base::Bind(&DownloadItemImpl::OnResumeRequestStarted,
- weak_ptr_factory_.GetWeakPtr()));
+ download_params->set_hash_of_partial_file(hash_);
+ download_params->set_hash_state(std::move(hash_state_));
+ TransitionTo(RESUMING_INTERNAL);
delegate_->ResumeInterruptedDownload(std::move(download_params), GetId());
// Just in case we were interrupted while paused.
is_paused_ = false;
-
- TransitionTo(RESUMING_INTERNAL, DONT_UPDATE_OBSERVERS);
}
// static
DownloadItem::DownloadState DownloadItemImpl::InternalToExternalState(
DownloadInternalState internal_state) {
switch (internal_state) {
+ case INITIAL_INTERNAL:
+ case TARGET_PENDING_INTERNAL:
+ case TARGET_RESOLVED_INTERNAL:
+ case INTERRUPTED_TARGET_PENDING_INTERNAL:
+ // TODO(asanka): Introduce an externally visible state to distinguish
+ // between the above states and IN_PROGRESS_INTERNAL. The latter (the
+ // state where the download is active and has a known target) is the state
+ // that most external users are interested in.
case IN_PROGRESS_INTERNAL:
return IN_PROGRESS;
case COMPLETING_INTERNAL:
@@ -1753,9 +1963,96 @@ DownloadItemImpl::ExternalToInternalState(
return MAX_DOWNLOAD_INTERNAL_STATE;
}
+// static
+bool DownloadItemImpl::IsValidSavePackageStateTransition(
+ DownloadInternalState from,
+ DownloadInternalState to) {
+#if DCHECK_IS_ON()
+ switch (from) {
+ case INITIAL_INTERNAL:
+ case TARGET_PENDING_INTERNAL:
+ case INTERRUPTED_TARGET_PENDING_INTERNAL:
+ case TARGET_RESOLVED_INTERNAL:
+ case COMPLETING_INTERNAL:
+ case COMPLETE_INTERNAL:
+ case INTERRUPTED_INTERNAL:
+ case RESUMING_INTERNAL:
+ case CANCELLED_INTERNAL:
+ return false;
+
+ case IN_PROGRESS_INTERNAL:
+ return to == CANCELLED_INTERNAL || to == COMPLETE_INTERNAL;
+
+ case MAX_DOWNLOAD_INTERNAL_STATE:
+ NOTREACHED();
+ }
+ return false;
+#else
+ return true;
+#endif
+}
+
+// static
+bool DownloadItemImpl::IsValidStateTransition(DownloadInternalState from,
+ DownloadInternalState to) {
+#if DCHECK_IS_ON()
+ switch (from) {
+ case INITIAL_INTERNAL:
+ return to == TARGET_PENDING_INTERNAL ||
+ to == INTERRUPTED_TARGET_PENDING_INTERNAL;
+
+ case TARGET_PENDING_INTERNAL:
+ return to == INTERRUPTED_TARGET_PENDING_INTERNAL ||
+ to == TARGET_RESOLVED_INTERNAL || to == CANCELLED_INTERNAL;
+
+ case INTERRUPTED_TARGET_PENDING_INTERNAL:
+ return to == INTERRUPTED_INTERNAL || to == CANCELLED_INTERNAL;
+
+ case TARGET_RESOLVED_INTERNAL:
+ return to == IN_PROGRESS_INTERNAL || to == INTERRUPTED_INTERNAL ||
+ to == CANCELLED_INTERNAL;
+
+ case IN_PROGRESS_INTERNAL:
+ return to == COMPLETING_INTERNAL || to == CANCELLED_INTERNAL ||
+ to == INTERRUPTED_INTERNAL;
+
+ case COMPLETING_INTERNAL:
+ return to == COMPLETE_INTERNAL;
+
+ case COMPLETE_INTERNAL:
+ return false;
+
+ case INTERRUPTED_INTERNAL:
+ return to == RESUMING_INTERNAL || to == CANCELLED_INTERNAL;
+
+ case RESUMING_INTERNAL:
+ return to == TARGET_PENDING_INTERNAL ||
+ to == INTERRUPTED_TARGET_PENDING_INTERNAL ||
+ to == TARGET_RESOLVED_INTERNAL || to == CANCELLED_INTERNAL;
+
+ case CANCELLED_INTERNAL:
+ return false;
+
+ case MAX_DOWNLOAD_INTERNAL_STATE:
+ NOTREACHED();
+ }
+ return false;
+#else
+ return true;
+#endif // DCHECK_IS_ON()
+}
+
const char* DownloadItemImpl::DebugDownloadStateString(
DownloadInternalState state) {
switch (state) {
+ case INITIAL_INTERNAL:
+ return "INITIAL";
+ case TARGET_PENDING_INTERNAL:
+ return "TARGET_PENDING";
+ case INTERRUPTED_TARGET_PENDING_INTERNAL:
+ return "INTERRUPTED_TARGET_PENDING";
+ case TARGET_RESOLVED_INTERNAL:
+ return "TARGET_RESOLVED";
case IN_PROGRESS_INTERNAL:
return "IN_PROGRESS";
case COMPLETING_INTERNAL:
diff --git a/chromium/content/browser/download/download_item_impl.h b/chromium/content/browser/download/download_item_impl.h
index c527861287f..a6afdd86779 100644
--- a/chromium/content/browser/download/download_item_impl.h
+++ b/chromium/content/browser/download/download_item_impl.h
@@ -16,10 +16,10 @@
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/time/time.h"
+#include "content/browser/download/download_destination_observer.h"
#include "content/browser/download/download_net_log_parameters.h"
#include "content/browser/download/download_request_handle.h"
#include "content/common/content_export.h"
-#include "content/public/browser/download_destination_observer.h"
#include "content/public/browser/download_interrupt_reasons.h"
#include "content/public/browser/download_item.h"
#include "net/log/net_log.h"
@@ -52,6 +52,7 @@ class CONTENT_EXPORT DownloadItemImpl
// Constructing from persistent store:
// |bound_net_log| is constructed externally for our use.
DownloadItemImpl(DownloadItemImplDelegate* delegate,
+ const std::string& guid,
uint32_t id,
const base::FilePath& current_path,
const base::FilePath& target_path,
@@ -65,6 +66,7 @@ class CONTENT_EXPORT DownloadItemImpl
const std::string& last_modified,
int64_t received_bytes,
int64_t total_bytes,
+ const std::string& hash,
DownloadItem::DownloadState state,
DownloadDangerType danger_type,
DownloadInterruptReason interrupt_reason,
@@ -73,6 +75,8 @@ class CONTENT_EXPORT DownloadItemImpl
// Constructing for a regular download.
// |bound_net_log| is constructed externally for our use.
+ // TODO(asanka): Get rid of the DownloadCreateInfo parameter since active
+ // downloads end up at Start() immediately after creation.
DownloadItemImpl(DownloadItemImplDelegate* delegate,
uint32_t id,
const DownloadCreateInfo& info,
@@ -103,6 +107,7 @@ class CONTENT_EXPORT DownloadItemImpl
void OpenDownload() override;
void ShowDownloadInShell() override;
uint32_t GetId() const override;
+ const std::string& GetGuid() const override;
DownloadState GetState() const override;
DownloadInterruptReason GetLastReason() const override;
bool IsPaused() const override;
@@ -131,7 +136,6 @@ class CONTENT_EXPORT DownloadItemImpl
base::FilePath GetFileNameToReportUser() const override;
TargetDisposition GetTargetDisposition() const override;
const std::string& GetHash() const override;
- const std::string& GetHashState() const override;
bool GetFileExternallyRemoved() const override;
void DeleteFile(const base::Callback<void(bool)>& callback) override;
bool IsDangerous() const override;
@@ -167,18 +171,18 @@ class CONTENT_EXPORT DownloadItemImpl
// INTERRUPTED state.
virtual ResumeMode GetResumeMode() const;
- // Notify the download item that new origin information is available due to a
- // resumption request receiving a response.
- virtual void MergeOriginInfoOnResume(
- const DownloadCreateInfo& new_create_info);
-
// State transition operations on regular downloads --------------------------
// Start the download.
// |download_file| is the associated file on the storage medium.
// |req_handle| is the new request handle associated with the download.
+ // |new_create_info| is a DownloadCreateInfo containing the new response
+ // parameters. It may be different from the DownloadCreateInfo used to create
+ // the DownloadItem if Start() is being called in response for a download
+ // resumption request.
virtual void Start(scoped_ptr<DownloadFile> download_file,
- scoped_ptr<DownloadRequestHandleInterface> req_handle);
+ scoped_ptr<DownloadRequestHandleInterface> req_handle,
+ const DownloadCreateInfo& new_create_info);
// Needed because of intertwining with DownloadManagerImpl -------------------
@@ -203,94 +207,171 @@ class CONTENT_EXPORT DownloadItemImpl
// Called by SavePackage to set the total number of bytes on the item.
virtual void SetTotalBytes(int64_t total_bytes);
- virtual void OnAllDataSaved(const std::string& final_hash);
+ virtual void OnAllDataSaved(int64_t total_bytes,
+ scoped_ptr<crypto::SecureHash> hash_state);
// Called by SavePackage to display progress when the DownloadItem
// should be considered complete.
virtual void MarkAsComplete();
// DownloadDestinationObserver
- void DestinationUpdate(int64_t bytes_so_far,
- int64_t bytes_per_sec,
- const std::string& hash_state) override;
- void DestinationError(DownloadInterruptReason reason) override;
- void DestinationCompleted(const std::string& final_hash) override;
+ void DestinationUpdate(int64_t bytes_so_far, int64_t bytes_per_sec) override;
+ void DestinationError(DownloadInterruptReason reason,
+ int64_t bytes_so_far,
+ scoped_ptr<crypto::SecureHash> hash_state) override;
+ void DestinationCompleted(int64_t total_bytes,
+ scoped_ptr<crypto::SecureHash> hash_state) override;
private:
- // Fine grained states of a download. Note that active downloads are created
- // in IN_PROGRESS_INTERNAL state. However, downloads creates via history can
- // be created in COMPLETE_INTERNAL, CANCELLED_INTERNAL and
- // INTERRUPTED_INTERNAL.
-
+ // Fine grained states of a download.
+ //
+ // New downloads can be created in the following states:
+ //
+ // INITIAL_INTERNAL: All active new downloads.
+ //
+ // COMPLETE_INTERNAL: Downloads restored from persisted state.
+ // CANCELLED_INTERNAL: - do -
+ // INTERRUPTED_INTERNAL: - do -
+ //
+ // IN_PROGRESS_INTERNAL: SavePackage downloads.
+ //
+ // On debug builds, state transitions can be verified via
+ // IsValidStateTransition() and IsValidSavePackageStateTransition(). Allowed
+ // state transitions are described below, both for normal downloads and
+ // SavePackage downloads.
enum DownloadInternalState {
- // Includes both before and after file name determination, and paused
- // downloads.
- // TODO(rdsmith): Put in state variable for file name determination.
- // Transitions from:
- // <Initial creation> Active downloads are created in this state.
- // RESUMING_INTERNAL
- // Transitions to:
- // COMPLETING_INTERNAL On final rename completion.
- // CANCELLED_INTERNAL On cancel.
- // INTERRUPTED_INTERNAL On interrupt.
- // COMPLETE_INTERNAL On SavePackage download completion.
+ // Initial state. Regular downloads are created in this state until the
+ // Start() call is received.
+ //
+ // Transitions to (regular):
+ // TARGET_PENDING_INTERNAL: After a successful Start() call.
+ // INTERRUPTED_TARGET_PENDING_INTERNAL: After a failed Start() call.
+ //
+ // Transitions to (SavePackage):
+ // <n/a> SavePackage downloads never reach this state.
+ INITIAL_INTERNAL,
+
+ // Embedder is in the process of determining the target of the download.
+ // Since the embedder is sensitive to state transitions during this time,
+ // any DestinationError/DestinationCompleted events are deferred until
+ // TARGET_RESOLVED_INTERNAL.
+ //
+ // Transitions to (regular):
+ // TARGET_RESOLVED_INTERNAL: Once the embedder invokes the callback.
+ // INTERRUPTED_TARGET_PENDING_INTERNAL: An error occurred prior to target
+ // determination.
+ // CANCELLED_INTERNAL: Cancelled.
+ //
+ // Transitions to (SavePackage):
+ // <n/a> SavePackage downloads never reach this state.
+ TARGET_PENDING_INTERNAL,
+
+ // Embedder is in the process of determining the target of the download, and
+ // the download is in an interrupted state. The interrupted state is not
+ // exposed to the emedder until target determination is complete.
+ //
+ // Transitions to (regular):
+ // INTERRUPTED_INTERNAL: Once the target is determined, the download
+ // is marked as interrupted.
+ // CANCELLED_INTERNAL: Cancelled.
+ //
+ // Transitions to (SavePackage):
+ // <n/a> SavePackage downloads never reach this state.
+ INTERRUPTED_TARGET_PENDING_INTERNAL,
+
+ // Embedder has completed target determination. It is now safe to resolve
+ // the download target as well as process deferred DestinationError events.
+ // This state is differs from TARGET_PENDING_INTERNAL due to it being
+ // allowed to transition to INTERRUPTED_INTERNAL, and it's different from
+ // IN_PROGRESS_INTERNAL in that entering this state doesn't require having
+ // a valid target. This state is transient (i.e. DownloadItemImpl will
+ // transition out of it before yielding execution). It's only purpose in
+ // life is to ensure the integrity of state transitions.
+ //
+ // Transitions to (regular):
+ // IN_PROGRESS_INTERNAL: Target successfully determined. The incoming
+ // data stream can now be written to the target.
+ // INTERRUPTED_INTERNAL: Either the target determination or one of the
+ // deferred signals indicated that the download
+ // should be interrupted.
+ // CANCELLED_INTERNAL: User cancelled the download or there was a
+ // deferred Cancel() call.
+ //
+ // Transitions to (SavePackage):
+ // <n/a> SavePackage downloads never reach this state.
+ TARGET_RESOLVED_INTERNAL,
+
+ // Download target is known and the data can be transferred from our source
+ // to our sink.
+ //
+ // Transitions to (regular):
+ // COMPLETING_INTERNAL: On final rename completion.
+ // CANCELLED_INTERNAL: On cancel.
+ // INTERRUPTED_INTERNAL: On interrupt.
+ //
+ // Transitions to (SavePackage):
+ // COMPLETE_INTERNAL: On completion.
+ // CANCELLED_INTERNAL: On cancel.
IN_PROGRESS_INTERNAL,
// Between commit point (dispatch of download file release) and completed.
// Embedder may be opening the file in this state.
- // Transitions from:
- // IN_PROGRESS_INTERNAL
- // Transitions to:
- // COMPLETE_INTERNAL On successful completion.
+ //
+ // Transitions to (regular):
+ // COMPLETE_INTERNAL: On successful completion.
+ //
+ // Transitions to (SavePackage):
+ // <n/a> SavePackage downloads never reach this state.
COMPLETING_INTERNAL,
// After embedder has had a chance to auto-open. User may now open
// or auto-open based on extension.
- // Transitions from:
- // COMPLETING_INTERNAL
- // IN_PROGRESS_INTERNAL SavePackage only.
- // <Initial creation> Completed persisted downloads.
- // Transitions to:
- // <none> Terminal state.
+ //
+ // Transitions to (regular):
+ // <none> Terminal state.
+ //
+ // Transitions to (SavePackage):
+ // <none> Terminal state.
COMPLETE_INTERNAL,
- // User has cancelled the download.
- // Transitions from:
- // IN_PROGRESS_INTERNAL
- // INTERRUPTED_INTERNAL
- // RESUMING_INTERNAL
- // <Initial creation> Canceleld persisted downloads.
- // Transitions to:
- // <none> Terminal state.
- CANCELLED_INTERNAL,
-
// An error has interrupted the download.
- // Transitions from:
- // IN_PROGRESS_INTERNAL
- // RESUMING_INTERNAL
- // <Initial creation> Interrupted persisted downloads.
- // Transitions to:
- // RESUMING_INTERNAL On resumption.
+ //
+ // Transitions to (regular):
+ // RESUMING_INTERNAL: On resumption.
+ // CANCELLED_INTERNAL: On cancel.
+ //
+ // Transitions to (SavePackage):
+ // <n/a> SavePackage downloads never reach this state.
INTERRUPTED_INTERNAL,
// A request to resume this interrupted download is in progress.
- // Transitions from:
- // INTERRUPTED_INTERNAL
- // Transitions to:
- // IN_PROGRESS_INTERNAL Once a server response is received from a
- // resumption.
- // INTERRUPTED_INTERNAL If the resumption request fails.
- // CANCELLED_INTERNAL On cancel.
+ //
+ // Transitions to (regular):
+ // TARGET_PENDING_INTERNAL: Once a server response is received from a
+ // resumption.
+ // INTERRUPTED_TARGET_PENDING_INTERNAL: A server response was received,
+ // but it indicated an error, and the download
+ // needs to go through target determination.
+ // TARGET_RESOLVED_INTERNAL: A resumption attempt received an error
+ // but it was not necessary to go through target
+ // determination.
+ // CANCELLED_INTERNAL: On cancel.
+ //
+ // Transitions to (SavePackage):
+ // <n/a> SavePackage downloads never reach this state.
RESUMING_INTERNAL,
- MAX_DOWNLOAD_INTERNAL_STATE,
- };
+ // User has cancelled the download.
+ // TODO(asanka): Merge interrupted and cancelled states.
+ //
+ // Transitions to (regular):
+ // <none> Terminal state.
+ //
+ // Transitions to (SavePackage):
+ // <none> Terminal state.
+ CANCELLED_INTERNAL,
- // Used with TransitionTo() to indicate whether or not to call
- // UpdateObservers() after the state transition.
- enum ShouldUpdateObservers {
- UPDATE_OBSERVERS,
- DONT_UPDATE_OBSERVERS
+ MAX_DOWNLOAD_INTERNAL_STATE,
};
// Normal progression of a download ------------------------------------------
@@ -305,6 +386,13 @@ class CONTENT_EXPORT DownloadItemImpl
// this is.
void Init(bool active, DownloadType download_type);
+ // Callback from file thread when we initialize the DownloadFile.
+ void OnDownloadFileInitialized(DownloadInterruptReason result);
+
+ // Called to determine the target path. Will cause OnDownloadTargetDetermined
+ // to be called when the target information is available.
+ void DetermineDownloadTarget();
+
// Called when the target path has been determined. |target_path| is the
// suggested target path. |disposition| indicates how the target path should
// be used (see TargetDisposition). |danger_type| is the danger level of
@@ -316,9 +404,6 @@ class CONTENT_EXPORT DownloadItemImpl
DownloadDangerType danger_type,
const base::FilePath& intermediate_path);
- // Callback from file thread when we initialize the DownloadFile.
- void OnDownloadFileInitialized(DownloadInterruptReason result);
-
void OnDownloadRenamedToIntermediateName(
DownloadInterruptReason reason, const base::FilePath& full_path);
@@ -339,18 +424,29 @@ class CONTENT_EXPORT DownloadItemImpl
// the download has been opened.
void DelayedDownloadOpened(bool auto_opened);
- // Called when the entire download operation (including renaming etc)
+ // Called when the entire download operation (including renaming etc.)
// is completed.
void Completed();
- // Callback invoked when the URLRequest for a download resumption has started.
- void OnResumeRequestStarted(DownloadItem* item,
- DownloadInterruptReason interrupt_reason);
-
// Helper routines -----------------------------------------------------------
- // Indicate that an error has occurred on the download.
- void Interrupt(DownloadInterruptReason reason);
+ // Indicate that an error has occurred on the download. Discards partial
+ // state. The interrupted download will not be considered continuable, but may
+ // be restarted.
+ void InterruptAndDiscardPartialState(DownloadInterruptReason reason);
+
+ // Indiates that an error has occurred on the download. The |bytes_so_far| and
+ // |hash_state| should correspond to the state of the DownloadFile. If the
+ // interrupt reason allows, this partial state may be allowed to continue the
+ // interrupted download upon resumption.
+ void InterruptWithPartialState(int64_t bytes_so_far,
+ scoped_ptr<crypto::SecureHash> hash_state,
+ DownloadInterruptReason reason);
+
+ void UpdateProgress(int64_t bytes_so_far, int64_t bytes_per_sec);
+
+ // Set |hash_| and |hash_state_| based on |hash_state|.
+ void SetHashState(scoped_ptr<crypto::SecureHash> hash_state);
// Destroy the DownloadFile object. If |destroy_file| is true, the file is
// destroyed with it. Otherwise, DownloadFile::Detach() is called before
@@ -366,10 +462,9 @@ class CONTENT_EXPORT DownloadItemImpl
// Call to transition state; all state transitions should go through this.
// |notify_action| specifies whether or not to call UpdateObservers() after
// the state transition.
- void TransitionTo(DownloadInternalState new_state,
- ShouldUpdateObservers notify_action);
+ void TransitionTo(DownloadInternalState new_state);
- // Set the |danger_type_| and invoke obserers if necessary.
+ // Set the |danger_type_| and invoke observers if necessary.
void SetDangerType(DownloadDangerType danger_type);
void SetFullPath(const base::FilePath& new_path);
@@ -378,6 +473,11 @@ class CONTENT_EXPORT DownloadItemImpl
void ResumeInterruptedDownload();
+ // Update origin information based on the response to a download resumption
+ // request. Should only be called if the resumption request was successful.
+ virtual void UpdateValidatorsOnResumption(
+ const DownloadCreateInfo& new_create_info);
+
static DownloadState InternalToExternalState(
DownloadInternalState internal_state);
static DownloadInternalState ExternalToInternalState(
@@ -386,34 +486,34 @@ class CONTENT_EXPORT DownloadItemImpl
// Debugging routines --------------------------------------------------------
static const char* DebugDownloadStateString(DownloadInternalState state);
static const char* DebugResumeModeString(ResumeMode mode);
+ static bool IsValidSavePackageStateTransition(DownloadInternalState from,
+ DownloadInternalState to);
+ static bool IsValidStateTransition(DownloadInternalState from,
+ DownloadInternalState to);
// Will be false for save package downloads retrieved from the history.
// TODO(rdsmith): Replace with a generalized enum for "download source".
- const bool is_save_package_download_;
+ const bool is_save_package_download_ = false;
// The handle to the request information. Used for operations outside the
// download system.
scoped_ptr<DownloadRequestHandleInterface> request_handle_;
- uint32_t download_id_;
+ std::string guid_;
+
+ uint32_t download_id_ = kInvalidId;
// Display name for the download. If this is empty, then the display name is
// considered to be |target_path_.BaseName()|.
base::FilePath display_name_;
- // Full path to the downloaded or downloading file. This is the path to the
- // physical file, if one exists. The final target path is specified by
- // |target_path_|. |current_path_| can be empty if the in-progress path hasn't
- // been determined.
- base::FilePath current_path_;
-
// Target path of an in-progress download. We may be downloading to a
// temporary or intermediate file (specified by |current_path_|. Once the
// download completes, we will rename the file to |target_path_|.
base::FilePath target_path_;
// Whether the target should be overwritten, uniquified or prompted for.
- TargetDisposition target_disposition_;
+ TargetDisposition target_disposition_ = TARGET_DISPOSITION_OVERWRITE;
// The chain of redirects that leading up to and including the final URL.
std::vector<GURL> url_chain_;
@@ -437,10 +537,10 @@ class CONTENT_EXPORT DownloadItemImpl
base::FilePath forced_file_path_;
// Page transition that triggerred the download.
- ui::PageTransition transition_type_;
+ ui::PageTransition transition_type_ = ui::PAGE_TRANSITION_LINK;
// Whether the download was triggered with a user gesture.
- bool has_user_gesture_;
+ bool has_user_gesture_ = false;
// Information from the request.
// Content-disposition field from the header.
@@ -459,40 +559,19 @@ class CONTENT_EXPORT DownloadItemImpl
std::string remote_address_;
// Total bytes expected.
- int64_t total_bytes_;
-
- // Current received bytes.
- int64_t received_bytes_;
-
- // Current speed. Calculated by the DownloadFile.
- int64_t bytes_per_sec_;
-
- // Sha256 hash of the content. This might be empty either because
- // the download isn't done yet or because the hash isn't needed
- // (ChromeDownloadManagerDelegate::GenerateFileHash() returned false).
- std::string hash_;
-
- // A blob containing the state of the hash algorithm. Only valid while the
- // download is in progress.
- std::string hash_state_;
-
- // Server's time stamp for the file.
- std::string last_modified_time_;
-
- // Server's ETAG for the file.
- std::string etag_;
+ int64_t total_bytes_ = 0;
// Last reason.
- DownloadInterruptReason last_reason_;
+ DownloadInterruptReason last_reason_ = DOWNLOAD_INTERRUPT_REASON_NONE;
// Start time for recording statistics.
base::TimeTicks start_tick_;
// The current state of this download.
- DownloadInternalState state_;
+ DownloadInternalState state_ = INITIAL_INTERNAL;
// Current danger type for the download.
- DownloadDangerType danger_type_;
+ DownloadDangerType danger_type_ = DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS;
// The views of this item in the download shelf and download contents.
base::ObserverList<Observer> observers_;
@@ -504,44 +583,40 @@ class CONTENT_EXPORT DownloadItemImpl
base::Time end_time_;
// Our delegate.
- DownloadItemImplDelegate* delegate_;
+ DownloadItemImplDelegate* delegate_ = nullptr;
// In progress downloads may be paused by the user, we note it here.
- bool is_paused_;
-
- // The number of times this download has been resumed automatically.
- int auto_resume_count_;
+ bool is_paused_ = false;
// A flag for indicating if the download should be opened at completion.
- bool open_when_complete_;
+ bool open_when_complete_ = false;
// A flag for indicating if the downloaded file is externally removed.
- bool file_externally_removed_;
+ bool file_externally_removed_ = false;
// True if the download was auto-opened. We set this rather than using
// an observer as it's frequently possible for the download to be auto opened
// before the observer is added.
- bool auto_opened_;
+ bool auto_opened_ = false;
// True if the item was downloaded temporarily.
- bool is_temporary_;
-
- // True if we've saved all the data for the download.
- bool all_data_saved_;
-
- // Error return from DestinationError. Stored separately from
- // last_reason_ so that we can avoid handling destination errors until
- // after file name determination has occurred.
- DownloadInterruptReason destination_error_;
+ bool is_temporary_ = false;
// Did the user open the item either directly or indirectly (such as by
// setting always open files of this type)? The shelf also sets this field
// when the user closes the shelf before the item has been opened but should
// be treated as though the user opened it.
- bool opened_;
+ bool opened_ = false;
// Did the delegate delay calling Complete on this download?
- bool delegate_delayed_complete_;
+ bool delegate_delayed_complete_ = false;
+
+ // Error return from DestinationError. Stored separately from
+ // last_reason_ so that we can avoid handling destination errors until
+ // after file name determination has occurred.
+ DownloadInterruptReason destination_error_ = DOWNLOAD_INTERRUPT_REASON_NONE;
+
+ // The following fields describe the current state of the download file.
// DownloadFile associated with this download. Note that this
// pointer may only be used or destroyed on the FILE thread.
@@ -549,6 +624,47 @@ class CONTENT_EXPORT DownloadItemImpl
// the IN_PROGRESS state.
scoped_ptr<DownloadFile> download_file_;
+ // Full path to the downloaded or downloading file. This is the path to the
+ // physical file, if one exists. The final target path is specified by
+ // |target_path_|. |current_path_| can be empty if the in-progress path hasn't
+ // been determined.
+ base::FilePath current_path_;
+
+ // Current received bytes.
+ int64_t received_bytes_ = 0;
+
+ // Current speed. Calculated by the DownloadFile.
+ int64_t bytes_per_sec_ = 0;
+
+ // True if we've saved all the data for the download. If true, then the file
+ // at |current_path_| contains |received_bytes_|, which constitute the
+ // entirety of what we expect to save there. A digest of its contents can be
+ // found at |hash_|.
+ bool all_data_saved_ = false;
+
+ // The number of times this download has been resumed automatically. Will be
+ // reset to 0 if a resumption is performed in response to a Resume() call.
+ int auto_resume_count_ = 0;
+
+ // SHA256 hash of the possibly partial content. The hash is updated each time
+ // the download is interrupted, and when the all the data has been
+ // transferred. |hash_| contains the raw binary hash and is not hex encoded.
+ //
+ // While the download is in progress, and while resuming, |hash_| will be
+ // empty.
+ std::string hash_;
+
+ // In the event of an interruption, the DownloadDestinationObserver interface
+ // exposes the partial hash state. This state can be held by the download item
+ // in case it's needed for resumption.
+ scoped_ptr<crypto::SecureHash> hash_state_;
+
+ // Contents of the Last-Modified header for the most recent server response.
+ std::string last_modified_time_;
+
+ // Server's ETAG for the file.
+ std::string etag_;
+
// Net log to use for this download.
const net::BoundNetLog bound_net_log_;
diff --git a/chromium/content/browser/download/download_item_impl_delegate.cc b/chromium/content/browser/download/download_item_impl_delegate.cc
index c1ed48cd124..be7432599e1 100644
--- a/chromium/content/browser/download/download_item_impl_delegate.cc
+++ b/chromium/content/browser/download/download_item_impl_delegate.cc
@@ -56,6 +56,11 @@ bool DownloadItemImplDelegate::ShouldOpenFileBasedOnExtension(
void DownloadItemImplDelegate::CheckForFileRemoval(
DownloadItemImpl* download_item) {}
+std::string DownloadItemImplDelegate::GetApplicationClientIdForFileScanning()
+ const {
+ return std::string();
+}
+
void DownloadItemImplDelegate::ResumeInterruptedDownload(
scoped_ptr<DownloadUrlParameters> params,
uint32_t id) {}
diff --git a/chromium/content/browser/download/download_item_impl_delegate.h b/chromium/content/browser/download/download_item_impl_delegate.h
index 1925963f0a2..8dd9d8cb740 100644
--- a/chromium/content/browser/download/download_item_impl_delegate.h
+++ b/chromium/content/browser/download/download_item_impl_delegate.h
@@ -69,6 +69,11 @@ class CONTENT_EXPORT DownloadItemImplDelegate {
// to OnDownloadedFileRemoved().
virtual void CheckForFileRemoval(DownloadItemImpl* download_item);
+ // Return a GUID string used for identifying the application to the system AV
+ // function for scanning downloaded files. If an empty or invalid GUID string
+ // is returned, no client identification will be given to the AV function.
+ virtual std::string GetApplicationClientIdForFileScanning() const;
+
// Called when an interrupted download is resumed.
virtual void ResumeInterruptedDownload(
scoped_ptr<content::DownloadUrlParameters> params,
diff --git a/chromium/content/browser/download/download_item_impl_unittest.cc b/chromium/content/browser/download/download_item_impl_unittest.cc
index 0afad1bfca2..45c822cfc55 100644
--- a/chromium/content/browser/download/download_item_impl_unittest.cc
+++ b/chromium/content/browser/download/download_item_impl_unittest.cc
@@ -5,39 +5,54 @@
#include "content/browser/download/download_item_impl.h"
#include <stdint.h>
+
+#include <iterator>
+#include <queue>
#include <utility>
#include "base/callback.h"
#include "base/feature_list.h"
#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/threading/thread.h"
#include "content/browser/byte_stream.h"
#include "content/browser/download/download_create_info.h"
+#include "content/browser/download/download_destination_observer.h"
#include "content/browser/download/download_file_factory.h"
#include "content/browser/download/download_item_impl_delegate.h"
#include "content/browser/download/download_request_handle.h"
#include "content/browser/download/mock_download_file.h"
-#include "content/public/browser/download_destination_observer.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_interrupt_reasons.h"
#include "content/public/browser/download_url_parameters.h"
#include "content/public/common/content_features.h"
#include "content/public/test/mock_download_item.h"
+#include "content/public/test/mock_download_item.h"
#include "content/public/test/test_browser_context.h"
-#include "content/public/test/test_browser_thread.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "content/public/test/web_contents_tester.h"
+#include "crypto/secure_hash.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-using ::testing::_;
+using ::testing::DoAll;
using ::testing::NiceMock;
using ::testing::Property;
using ::testing::Return;
+using ::testing::ReturnRefOfCopy;
using ::testing::SaveArg;
using ::testing::StrictMock;
+using ::testing::WithArg;
+using ::testing::_;
const int kDownloadChunkSize = 1000;
const int kDownloadSpeed = 1000;
-const base::FilePath::CharType kDummyPath[] = FILE_PATH_LITERAL("/testpath");
+const base::FilePath::CharType kDummyTargetPath[] =
+ FILE_PATH_LITERAL("/testpath");
+const base::FilePath::CharType kDummyIntermediatePath[] =
+ FILE_PATH_LITERAL("/testpathx");
namespace content {
@@ -66,7 +81,6 @@ class MockDelegate : public DownloadItemImplDelegate {
void(DownloadUrlParameters* params, uint32_t id));
MOCK_CONST_METHOD0(GetBrowserContext, BrowserContext*());
- MOCK_METHOD1(UpdatePersistence, void(DownloadItemImpl*));
MOCK_METHOD1(DownloadOpened, void(DownloadItemImpl*));
MOCK_METHOD1(DownloadRemoved, void(DownloadItemImpl*));
MOCK_CONST_METHOD1(AssertStateConsistent, void(DownloadItemImpl*));
@@ -128,8 +142,8 @@ class TestDownloadItemObserver : public DownloadItem::Observer {
private:
void OnDownloadRemoved(DownloadItem* download) override {
- DVLOG(20) << " " << __FUNCTION__
- << " download = " << download->DebugString(false);
+ SCOPED_TRACE(::testing::Message() << " " << __FUNCTION__ << " download = "
+ << download->DebugString(false));
removed_ = true;
}
@@ -159,7 +173,7 @@ class TestDownloadItemObserver : public DownloadItem::Observer {
<< " download = " << download->DebugString(false);
destroyed_ = true;
item_->RemoveObserver(this);
- item_ = NULL;
+ item_ = nullptr;
}
DownloadItem* item_;
@@ -173,54 +187,82 @@ class TestDownloadItemObserver : public DownloadItem::Observer {
// Schedules a task to invoke the RenameCompletionCallback with |new_path| on
// the UI thread. Should only be used as the action for
-// MockDownloadFile::Rename as follows:
-// EXPECT_CALL(download_file, Rename*(_,_))
-// .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
-// new_path));
-ACTION_P2(ScheduleRenameCallback, interrupt_reason, new_path) {
+// MockDownloadFile::RenameAndUniquify as follows:
+// EXPECT_CALL(download_file, RenameAndUniquify(_,_))
+// .WillOnce(ScheduleRenameAndUniquifyCallback(
+// DOWNLOAD_INTERRUPT_REASON_NONE, new_path));
+ACTION_P2(ScheduleRenameAndUniquifyCallback, interrupt_reason, new_path) {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(arg1, interrupt_reason, new_path));
}
+// Schedules a task to invoke the RenameCompletionCallback with |new_path| on
+// the UI thread. Should only be used as the action for
+// MockDownloadFile::RenameAndAnnotate as follows:
+// EXPECT_CALL(download_file, RenameAndAnnotate(_,_,_,_,_))
+// .WillOnce(ScheduleRenameAndAnnotateCallback(
+// DOWNLOAD_INTERRUPT_REASON_NONE, new_path));
+ACTION_P2(ScheduleRenameAndAnnotateCallback, interrupt_reason, new_path) {
+ BrowserThread::PostTask(BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(arg4, interrupt_reason, new_path));
+}
+
+// Schedules a task to invoke a callback that's bound to the specified
+// parameter.
+// E.g.:
+//
+// EXPECT_CALL(foo, Bar(1, _))
+// .WithArg<1>(ScheduleCallbackWithParam(0));
+//
+// .. will invoke the second argument to Bar with 0 as the parameter.
+ACTION_P(ScheduleCallbackWithParam, param) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(arg0, param));
+}
+
+// Schedules a task to invoke a closure.
+// E.g.:
+//
+// EXPECT_CALL(foo, Bar(1, _))
+// .WillOnce(ScheduleClosure(some_closure));
+ACTION_P(ScheduleClosure, closure) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, closure);
+}
+
+const char kTestData1[] = {'M', 'a', 'r', 'y', ' ', 'h', 'a', 'd',
+ ' ', 'a', ' ', 'l', 'i', 't', 't', 'l',
+ 'e', ' ', 'l', 'a', 'm', 'b', '.'};
+
+// SHA256 hash of TestData1
+const uint8_t kHashOfTestData1[] = {
+ 0xd2, 0xfc, 0x16, 0xa1, 0xf5, 0x1a, 0x65, 0x3a, 0xa0, 0x19, 0x64,
+ 0xef, 0x9c, 0x92, 0x33, 0x36, 0xe1, 0x06, 0x53, 0xfe, 0xc1, 0x95,
+ 0xf4, 0x93, 0x45, 0x8b, 0x3b, 0x21, 0x89, 0x0e, 0x1b, 0x97};
+
} // namespace
class DownloadItemTest : public testing::Test {
public:
DownloadItemTest()
- : ui_thread_(BrowserThread::UI, &loop_),
- file_thread_(BrowserThread::FILE, &loop_),
- delegate_() {
- }
-
- ~DownloadItemTest() {
- }
-
- virtual void SetUp() {
+ : delegate_(), next_download_id_(DownloadItem::kInvalidId + 1) {
base::FeatureList::ClearInstanceForTesting();
scoped_ptr<base::FeatureList> feature_list(new base::FeatureList);
feature_list->InitializeFromCommandLine(features::kDownloadResumption.name,
std::string());
base::FeatureList::SetInstance(std::move(feature_list));
- }
- virtual void TearDown() {
- ui_thread_.DeprecatedGetThreadObject()->message_loop()->RunUntilIdle();
- STLDeleteElements(&allocated_downloads_);
+ create_info_.reset(new DownloadCreateInfo());
+ create_info_->save_info =
+ scoped_ptr<DownloadSaveInfo>(new DownloadSaveInfo());
+ create_info_->save_info->prompt_for_save_location = false;
+ create_info_->url_chain.push_back(GURL("http://example.com/download"));
+ create_info_->etag = "SomethingToSatisfyResumption";
}
- // This class keeps ownership of the created download item; it will
- // be torn down at the end of the test unless DestroyDownloadItem is
- // called.
- DownloadItemImpl* CreateDownloadItem() {
- scoped_ptr<DownloadCreateInfo> info;
-
- info.reset(new DownloadCreateInfo());
- info->save_info = scoped_ptr<DownloadSaveInfo>(new DownloadSaveInfo());
- info->save_info->prompt_for_save_location = false;
- info->url_chain.push_back(GURL());
- info->etag = "SomethingToSatisfyResumption";
-
- return CreateDownloadItemWithCreateInfo(std::move(info));
+ ~DownloadItemTest() {
+ RunAllPendingInMessageLoops();
+ STLDeleteElements(&allocated_downloads_);
}
DownloadItemImpl* CreateDownloadItemWithCreateInfo(
@@ -231,26 +273,47 @@ class DownloadItemTest : public testing::Test {
return download;
}
- // Add DownloadFile to DownloadItem
- MockDownloadFile* AddDownloadFileToDownloadItem(
+ // This class keeps ownership of the created download item; it will
+ // be torn down at the end of the test unless DestroyDownloadItem is
+ // called.
+ DownloadItemImpl* CreateDownloadItem() {
+ create_info_->download_id = ++next_download_id_;
+ DownloadItemImpl* download =
+ new DownloadItemImpl(&delegate_, create_info_->download_id,
+ *create_info_, net::BoundNetLog());
+ allocated_downloads_.insert(download);
+ return download;
+ }
+
+ // Add DownloadFile to DownloadItem. Set |callback| to nullptr if a download
+ // target determination is not expected.
+ MockDownloadFile* CallDownloadItemStart(
DownloadItemImpl* item,
- DownloadItemImplDelegate::DownloadTargetCallback *callback) {
- MockDownloadFile* mock_download_file(new StrictMock<MockDownloadFile>);
- scoped_ptr<DownloadFile> download_file(mock_download_file);
- EXPECT_CALL(*mock_download_file, Initialize(_));
+ DownloadItemImplDelegate::DownloadTargetCallback* callback) {
+ MockDownloadFile* mock_download_file = nullptr;
+ scoped_ptr<DownloadFile> download_file;
if (callback) {
- // Save the callback.
EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _))
.WillOnce(SaveArg<1>(callback));
} else {
- // Drop it on the floor.
- EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _));
+ EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _)).Times(0);
+ }
+
+ // Only create a DownloadFile if the request was successful.
+ if (create_info_->result == DOWNLOAD_INTERRUPT_REASON_NONE) {
+ mock_download_file = new StrictMock<MockDownloadFile>;
+ download_file.reset(mock_download_file);
+ EXPECT_CALL(*mock_download_file, Initialize(_))
+ .WillOnce(ScheduleCallbackWithParam(DOWNLOAD_INTERRUPT_REASON_NONE));
+ EXPECT_CALL(*mock_download_file, FullPath())
+ .WillRepeatedly(ReturnRefOfCopy(base::FilePath()));
}
- scoped_ptr<DownloadRequestHandleInterface> request_handle(
+ scoped_ptr<MockRequestHandle> request_handle(
new NiceMock<MockRequestHandle>);
- item->Start(std::move(download_file), std::move(request_handle));
- loop_.RunUntilIdle();
+ item->Start(std::move(download_file), std::move(request_handle),
+ *create_info_);
+ RunAllPendingInMessageLoops();
// So that we don't have a function writing to a stack variable
// lying around if the above failed.
@@ -266,27 +329,42 @@ class DownloadItemTest : public testing::Test {
}
// Perform the intermediate rename for |item|. The target path for the
- // download will be set to kDummyPath. Returns the MockDownloadFile* that was
- // added to the DownloadItem.
+ // download will be set to kDummyTargetPath. Returns the MockDownloadFile*
+ // that was added to the DownloadItem.
MockDownloadFile* DoIntermediateRename(DownloadItemImpl* item,
DownloadDangerType danger_type) {
EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
EXPECT_TRUE(item->GetTargetFilePath().empty());
DownloadItemImplDelegate::DownloadTargetCallback callback;
- MockDownloadFile* download_file =
- AddDownloadFileToDownloadItem(item, &callback);
- base::FilePath target_path(kDummyPath);
- base::FilePath intermediate_path(
- target_path.InsertBeforeExtensionASCII("x"));
+ MockDownloadFile* download_file = CallDownloadItemStart(item, &callback);
+ base::FilePath target_path(kDummyTargetPath);
+ base::FilePath intermediate_path(kDummyIntermediatePath);
EXPECT_CALL(*download_file, RenameAndUniquify(intermediate_path, _))
- .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
- intermediate_path));
+ .WillOnce(ScheduleRenameAndUniquifyCallback(
+ DOWNLOAD_INTERRUPT_REASON_NONE, intermediate_path));
callback.Run(target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
danger_type, intermediate_path);
RunAllPendingInMessageLoops();
return download_file;
}
+ void DoDestinationComplete(DownloadItemImpl* item,
+ MockDownloadFile* download_file) {
+ EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(_, _))
+ .WillOnce(Return(true));
+ base::FilePath final_path(kDummyTargetPath);
+ EXPECT_CALL(*download_file, RenameAndAnnotate(_, _, _, _, _))
+ .WillOnce(ScheduleRenameAndAnnotateCallback(
+ DOWNLOAD_INTERRUPT_REASON_NONE, final_path));
+ EXPECT_CALL(*download_file, FullPath())
+ .WillRepeatedly(ReturnRefOfCopy(base::FilePath(kDummyTargetPath)));
+ EXPECT_CALL(*download_file, Detach());
+
+ item->DestinationObserverAsWeakPtr()->DestinationCompleted(
+ 0, scoped_ptr<crypto::SecureHash>());
+ RunAllPendingInMessageLoops();
+ }
+
// Cleanup a download item (specifically get rid of the DownloadFile on it).
// The item must be in the expected state.
void CleanupItem(DownloadItemImpl* item,
@@ -298,7 +376,7 @@ class DownloadItemTest : public testing::Test {
if (download_file)
EXPECT_CALL(*download_file, Cancel());
item->Cancel(true);
- loop_.RunUntilIdle();
+ RunAllPendingInMessageLoops();
}
}
@@ -308,9 +386,7 @@ class DownloadItemTest : public testing::Test {
delete item;
}
- void RunAllPendingInMessageLoops() {
- loop_.RunUntilIdle();
- }
+ void RunAllPendingInMessageLoops() { base::RunLoop().RunUntilIdle(); }
MockDelegate* mock_delegate() {
return &delegate_;
@@ -321,13 +397,17 @@ class DownloadItemTest : public testing::Test {
*return_path = path;
}
+ DownloadCreateInfo* create_info() { return create_info_.get(); }
+
+ BrowserContext* browser_context() { return &browser_context_; }
+
private:
- int next_download_id_ = DownloadItem::kInvalidId + 1;
- base::MessageLoopForUI loop_;
- TestBrowserThread ui_thread_; // UI thread
- TestBrowserThread file_thread_; // FILE thread
StrictMock<MockDelegate> delegate_;
std::set<DownloadItem*> allocated_downloads_;
+ scoped_ptr<DownloadCreateInfo> create_info_;
+ uint32_t next_download_id_ = DownloadItem::kInvalidId + 1;
+ TestBrowserContext browser_context_;
+ TestBrowserThreadBundle thread_bundle_;
};
// Tests to ensure calls that change a DownloadItem generate an update to
@@ -340,28 +420,33 @@ class DownloadItemTest : public testing::Test {
TEST_F(DownloadItemTest, NotificationAfterUpdate) {
DownloadItemImpl* item = CreateDownloadItem();
+ MockDownloadFile* file =
+ DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
+ ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
TestDownloadItemObserver observer(item);
- item->DestinationUpdate(kDownloadChunkSize, kDownloadSpeed, std::string());
+ item->DestinationUpdate(kDownloadChunkSize, kDownloadSpeed);
ASSERT_TRUE(observer.CheckAndResetDownloadUpdated());
EXPECT_EQ(kDownloadSpeed, item->CurrentSpeed());
+ CleanupItem(item, file, DownloadItem::IN_PROGRESS);
}
TEST_F(DownloadItemTest, NotificationAfterCancel) {
DownloadItemImpl* user_cancel = CreateDownloadItem();
+ DownloadItemImplDelegate::DownloadTargetCallback target_callback;
MockDownloadFile* download_file =
- AddDownloadFileToDownloadItem(user_cancel, NULL);
+ CallDownloadItemStart(user_cancel, &target_callback);
EXPECT_CALL(*download_file, Cancel());
- TestDownloadItemObserver observer1(user_cancel);
+ TestDownloadItemObserver observer1(user_cancel);
user_cancel->Cancel(true);
ASSERT_TRUE(observer1.CheckAndResetDownloadUpdated());
DownloadItemImpl* system_cancel = CreateDownloadItem();
- download_file = AddDownloadFileToDownloadItem(system_cancel, NULL);
+ download_file = CallDownloadItemStart(system_cancel, &target_callback);
EXPECT_CALL(*download_file, Cancel());
- TestDownloadItemObserver observer2(system_cancel);
+ TestDownloadItemObserver observer2(system_cancel);
system_cancel->Cancel(false);
ASSERT_TRUE(observer2.CheckAndResetDownloadUpdated());
}
@@ -369,11 +454,10 @@ TEST_F(DownloadItemTest, NotificationAfterCancel) {
TEST_F(DownloadItemTest, NotificationAfterComplete) {
DownloadItemImpl* item = CreateDownloadItem();
TestDownloadItemObserver observer(item);
-
- item->OnAllDataSaved(DownloadItem::kEmptyFileHash);
+ MockDownloadFile* download_file =
+ DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
ASSERT_TRUE(observer.CheckAndResetDownloadUpdated());
-
- item->MarkAsComplete();
+ DoDestinationComplete(item, download_file);
ASSERT_TRUE(observer.CheckAndResetDownloadUpdated());
}
@@ -396,7 +480,9 @@ TEST_F(DownloadItemTest, NotificationAfterInterrupted) {
.Times(0);
item->DestinationObserverAsWeakPtr()->DestinationError(
- DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
+ DOWNLOAD_INTERRUPT_REASON_FILE_FAILED,
+ 0,
+ scoped_ptr<crypto::SecureHash>());
ASSERT_TRUE(observer.CheckAndResetDownloadUpdated());
}
@@ -408,8 +494,8 @@ TEST_F(DownloadItemTest, NotificationAfterDestroyed) {
ASSERT_TRUE(observer.download_destroyed());
}
+// Test that a download is resumed automatcially after a continuable interrupt.
TEST_F(DownloadItemTest, ContinueAfterInterrupted) {
- TestBrowserContext test_browser_context;
DownloadItemImpl* item = CreateDownloadItem();
TestDownloadItemObserver observer(item);
MockDownloadFile* download_file =
@@ -417,13 +503,15 @@ TEST_F(DownloadItemTest, ContinueAfterInterrupted) {
// Interrupt the download, using a continuable interrupt.
EXPECT_CALL(*download_file, FullPath())
- .WillOnce(Return(base::FilePath()));
+ .WillOnce(ReturnRefOfCopy(base::FilePath()));
EXPECT_CALL(*download_file, Detach());
EXPECT_CALL(*mock_delegate(), GetBrowserContext())
- .WillRepeatedly(Return(&test_browser_context));
+ .WillRepeatedly(Return(browser_context()));
EXPECT_CALL(*mock_delegate(), MockResumeInterruptedDownload(_, _)).Times(1);
item->DestinationObserverAsWeakPtr()->DestinationError(
- DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR);
+ DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR,
+ 0,
+ scoped_ptr<crypto::SecureHash>());
ASSERT_TRUE(observer.CheckAndResetDownloadUpdated());
// Since the download is resumed automatically, the interrupt count doesn't
// increase.
@@ -441,7 +529,8 @@ TEST_F(DownloadItemTest, ContinueAfterInterrupted) {
CleanupItem(item, nullptr, DownloadItem::IN_PROGRESS);
}
-// Same as above, but with a non-continuable interrupt.
+// Test that automatic resumption doesn't happen after a non-continuable
+// interrupt.
TEST_F(DownloadItemTest, RestartAfterInterrupted) {
DownloadItemImpl* item = CreateDownloadItem();
TestDownloadItemObserver observer(item);
@@ -451,7 +540,9 @@ TEST_F(DownloadItemTest, RestartAfterInterrupted) {
// Interrupt the download, using a restartable interrupt.
EXPECT_CALL(*download_file, Cancel());
item->DestinationObserverAsWeakPtr()->DestinationError(
- DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
+ DOWNLOAD_INTERRUPT_REASON_FILE_FAILED,
+ 0,
+ scoped_ptr<crypto::SecureHash>());
ASSERT_TRUE(observer.CheckAndResetDownloadUpdated());
// Should not try to auto-resume.
ASSERT_EQ(1, observer.interrupt_count());
@@ -471,13 +562,15 @@ TEST_F(DownloadItemTest, UnresumableInterrupt) {
// Fail final rename with unresumable reason.
EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
.WillOnce(Return(true));
- EXPECT_CALL(*download_file, RenameAndAnnotate(base::FilePath(kDummyPath), _))
- .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED,
- base::FilePath(kDummyPath)));
+ EXPECT_CALL(*download_file,
+ RenameAndAnnotate(base::FilePath(kDummyTargetPath), _, _, _, _))
+ .WillOnce(ScheduleRenameAndAnnotateCallback(
+ DOWNLOAD_INTERRUPT_REASON_FILE_BLOCKED, base::FilePath()));
EXPECT_CALL(*download_file, Cancel());
// Complete download to trigger final rename.
- item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
+ item->DestinationObserverAsWeakPtr()->DestinationCompleted(
+ 0, scoped_ptr<crypto::SecureHash>());
RunAllPendingInMessageLoops();
ASSERT_TRUE(observer.CheckAndResetDownloadUpdated());
@@ -489,25 +582,24 @@ TEST_F(DownloadItemTest, UnresumableInterrupt) {
}
TEST_F(DownloadItemTest, LimitRestartsAfterInterrupted) {
- TestBrowserContext test_browser_context;
DownloadItemImpl* item = CreateDownloadItem();
base::WeakPtr<DownloadDestinationObserver> as_observer(
item->DestinationObserverAsWeakPtr());
TestDownloadItemObserver observer(item);
- MockDownloadFile* mock_download_file(NULL);
+ MockDownloadFile* mock_download_file(nullptr);
scoped_ptr<DownloadFile> download_file;
- MockRequestHandle* mock_request_handle(NULL);
+ MockRequestHandle* mock_request_handle(nullptr);
scoped_ptr<DownloadRequestHandleInterface> request_handle;
DownloadItemImplDelegate::DownloadTargetCallback callback;
EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _))
.WillRepeatedly(SaveArg<1>(&callback));
EXPECT_CALL(*mock_delegate(), GetBrowserContext())
- .WillRepeatedly(Return(&test_browser_context));
+ .WillRepeatedly(Return(browser_context()));
EXPECT_CALL(*mock_delegate(), MockResumeInterruptedDownload(_, _))
.Times(DownloadItemImpl::kMaxAutoResumeAttempts);
for (int i = 0; i < (DownloadItemImpl::kMaxAutoResumeAttempts + 1); ++i) {
- DVLOG(20) << "Loop iteration " << i;
+ SCOPED_TRACE(::testing::Message() << "Iteration " << i);
mock_download_file = new NiceMock<MockDownloadFile>;
download_file.reset(mock_download_file);
@@ -515,65 +607,128 @@ TEST_F(DownloadItemTest, LimitRestartsAfterInterrupted) {
request_handle.reset(mock_request_handle);
ON_CALL(*mock_download_file, FullPath())
- .WillByDefault(Return(base::FilePath()));
+ .WillByDefault(ReturnRefOfCopy(base::FilePath()));
- // Copied key parts of DoIntermediateRename & AddDownloadFileToDownloadItem
+ // Copied key parts of DoIntermediateRename & CallDownloadItemStart
// to allow for holding onto the request handle.
- item->Start(std::move(download_file), std::move(request_handle));
+ item->Start(std::move(download_file), std::move(request_handle),
+ *create_info());
RunAllPendingInMessageLoops();
+
+ base::FilePath target_path(kDummyTargetPath);
+ base::FilePath intermediate_path(kDummyIntermediatePath);
if (i == 0) {
- // Target determination is only done the first time through.
- base::FilePath target_path(kDummyPath);
- base::FilePath intermediate_path(
- target_path.InsertBeforeExtensionASCII("x"));
+ // RenameAndUniquify is only called the first time. In all the subsequent
+ // iterations, the intermediate file already has the correct name, hence
+ // no rename is necessary.
EXPECT_CALL(*mock_download_file, RenameAndUniquify(intermediate_path, _))
- .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
- intermediate_path));
- callback.Run(target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
- DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path);
- RunAllPendingInMessageLoops();
+ .WillOnce(ScheduleRenameAndUniquifyCallback(
+ DOWNLOAD_INTERRUPT_REASON_NONE, intermediate_path));
}
+ callback.Run(target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+ DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path);
+ RunAllPendingInMessageLoops();
// Use a continuable interrupt.
item->DestinationObserverAsWeakPtr()->DestinationError(
- DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR);
+ DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR,
+ 0,
+ scoped_ptr<crypto::SecureHash>());
+ RunAllPendingInMessageLoops();
::testing::Mock::VerifyAndClearExpectations(mock_download_file);
}
+ EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState());
EXPECT_EQ(1, observer.interrupt_count());
CleanupItem(item, nullptr, DownloadItem::INTERRUPTED);
}
+// If the download attempts to resume and the resumption request fails, the
+// subsequent Start() call shouldn't update the origin state (URL redirect
+// chains, Content-Disposition, download URL, etc..)
+TEST_F(DownloadItemTest, FailedResumptionDoesntUpdateOriginState) {
+ const char kContentDisposition[] = "attachment; filename=foo";
+ const char kFirstETag[] = "ABC";
+ const char kFirstLastModified[] = "Yesterday";
+ const char kFirstURL[] = "http://www.example.com/download";
+ create_info()->content_disposition = kContentDisposition;
+ create_info()->etag = kFirstETag;
+ create_info()->last_modified = kFirstLastModified;
+ create_info()->url_chain.push_back(GURL(kFirstURL));
+
+ DownloadItemImpl* item = CreateDownloadItem();
+ MockDownloadFile* download_file =
+ DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
+ EXPECT_EQ(kContentDisposition, item->GetContentDisposition());
+ EXPECT_EQ(kFirstETag, item->GetETag());
+ EXPECT_EQ(kFirstLastModified, item->GetLastModifiedTime());
+ EXPECT_EQ(kFirstURL, item->GetURL().spec());
+
+ EXPECT_CALL(*mock_delegate(), MockResumeInterruptedDownload(_, _));
+ EXPECT_CALL(*mock_delegate(), GetBrowserContext())
+ .WillRepeatedly(Return(browser_context()));
+ EXPECT_CALL(*download_file, Detach());
+ item->DestinationObserverAsWeakPtr()->DestinationError(
+ DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR,
+ 0,
+ scoped_ptr<crypto::SecureHash>());
+ RunAllPendingInMessageLoops();
+ EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
+
+ // Now change the create info. The changes should not cause the DownloadItem
+ // to be updated.
+ const char kSecondContentDisposition[] = "attachment; filename=bar";
+ const char kSecondETag[] = "123";
+ const char kSecondLastModified[] = "Today";
+ const char kSecondURL[] = "http://example.com/another-download";
+ create_info()->content_disposition = kSecondContentDisposition;
+ create_info()->etag = kSecondETag;
+ create_info()->last_modified = kSecondLastModified;
+ create_info()->url_chain.clear();
+ create_info()->url_chain.push_back(GURL(kSecondURL));
+ create_info()->result = DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED;
+
+ // The following ends up calling DownloadItem::Start(), but shouldn't result
+ // in an origin update.
+ download_file = CallDownloadItemStart(item, nullptr);
+
+ EXPECT_EQ(kContentDisposition, item->GetContentDisposition());
+ EXPECT_EQ(kFirstETag, item->GetETag());
+ EXPECT_EQ(kFirstLastModified, item->GetLastModifiedTime());
+ EXPECT_EQ(kFirstURL, item->GetURL().spec());
+ EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState());
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED, item->GetLastReason());
+}
+
// Test that resumption uses the final URL in a URL chain when resuming.
TEST_F(DownloadItemTest, ResumeUsingFinalURL) {
- TestBrowserContext test_browser_context;
- scoped_ptr<DownloadCreateInfo> create_info(new DownloadCreateInfo);
- create_info->save_info = scoped_ptr<DownloadSaveInfo>(new DownloadSaveInfo());
- create_info->save_info->prompt_for_save_location = false;
- create_info->etag = "SomethingToSatisfyResumption";
- create_info->url_chain.push_back(GURL("http://example.com/a"));
- create_info->url_chain.push_back(GURL("http://example.com/b"));
- create_info->url_chain.push_back(GURL("http://example.com/c"));
-
- DownloadItemImpl* item =
- CreateDownloadItemWithCreateInfo(std::move(create_info));
+ create_info()->save_info->prompt_for_save_location = false;
+ create_info()->url_chain.clear();
+ create_info()->url_chain.push_back(GURL("http://example.com/a"));
+ create_info()->url_chain.push_back(GURL("http://example.com/b"));
+ create_info()->url_chain.push_back(GURL("http://example.com/c"));
+
+ DownloadItemImpl* item = CreateDownloadItem();
TestDownloadItemObserver observer(item);
MockDownloadFile* download_file =
DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
// Interrupt the download, using a continuable interrupt.
- EXPECT_CALL(*download_file, FullPath()).WillOnce(Return(base::FilePath()));
+ EXPECT_CALL(*download_file, FullPath())
+ .WillOnce(ReturnRefOfCopy(base::FilePath()));
EXPECT_CALL(*download_file, Detach());
EXPECT_CALL(*mock_delegate(), GetBrowserContext())
- .WillRepeatedly(Return(&test_browser_context));
+ .WillRepeatedly(Return(browser_context()));
EXPECT_CALL(*mock_delegate(), MockResumeInterruptedDownload(
Property(&DownloadUrlParameters::url,
GURL("http://example.com/c")),
_))
.Times(1);
item->DestinationObserverAsWeakPtr()->DestinationError(
- DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR);
+ DOWNLOAD_INTERRUPT_REASON_FILE_TRANSIENT_ERROR,
+ 0,
+ scoped_ptr<crypto::SecureHash>());
// Test expectations verify that ResumeInterruptedDownload() is called (by way
// of MockResumeInterruptedDownload) after the download is interrupted. But
@@ -588,7 +743,9 @@ TEST_F(DownloadItemTest, ResumeUsingFinalURL) {
TEST_F(DownloadItemTest, NotificationAfterRemove) {
DownloadItemImpl* item = CreateDownloadItem();
- MockDownloadFile* download_file = AddDownloadFileToDownloadItem(item, NULL);
+ DownloadItemImplDelegate::DownloadTargetCallback target_callback;
+ MockDownloadFile* download_file =
+ CallDownloadItemStart(item, &target_callback);
EXPECT_CALL(*download_file, Cancel());
EXPECT_CALL(*mock_delegate(), DownloadRemoved(_));
TestDownloadItemObserver observer(item);
@@ -601,37 +758,52 @@ TEST_F(DownloadItemTest, NotificationAfterRemove) {
TEST_F(DownloadItemTest, NotificationAfterOnContentCheckCompleted) {
// Setting to NOT_DANGEROUS does not trigger a notification.
DownloadItemImpl* safe_item = CreateDownloadItem();
+ MockDownloadFile* download_file =
+ DoIntermediateRename(safe_item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
TestDownloadItemObserver safe_observer(safe_item);
- safe_item->OnAllDataSaved(std::string());
+ safe_item->OnAllDataSaved(0, scoped_ptr<crypto::SecureHash>());
EXPECT_TRUE(safe_observer.CheckAndResetDownloadUpdated());
safe_item->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
EXPECT_TRUE(safe_observer.CheckAndResetDownloadUpdated());
+ CleanupItem(safe_item, download_file, DownloadItem::IN_PROGRESS);
// Setting to unsafe url or unsafe file should trigger a notification.
DownloadItemImpl* unsafeurl_item =
CreateDownloadItem();
+ download_file =
+ DoIntermediateRename(unsafeurl_item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
TestDownloadItemObserver unsafeurl_observer(unsafeurl_item);
- unsafeurl_item->OnAllDataSaved(std::string());
+ unsafeurl_item->OnAllDataSaved(0, scoped_ptr<crypto::SecureHash>());
EXPECT_TRUE(unsafeurl_observer.CheckAndResetDownloadUpdated());
unsafeurl_item->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_DANGEROUS_URL);
EXPECT_TRUE(unsafeurl_observer.CheckAndResetDownloadUpdated());
+ EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(_, _))
+ .WillOnce(Return(true));
+ EXPECT_CALL(*download_file, RenameAndAnnotate(_, _, _, _, _));
unsafeurl_item->ValidateDangerousDownload();
EXPECT_TRUE(unsafeurl_observer.CheckAndResetDownloadUpdated());
+ CleanupItem(unsafeurl_item, download_file, DownloadItem::IN_PROGRESS);
DownloadItemImpl* unsafefile_item =
CreateDownloadItem();
+ download_file =
+ DoIntermediateRename(unsafefile_item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
TestDownloadItemObserver unsafefile_observer(unsafefile_item);
- unsafefile_item->OnAllDataSaved(std::string());
+ unsafefile_item->OnAllDataSaved(0, scoped_ptr<crypto::SecureHash>());
EXPECT_TRUE(unsafefile_observer.CheckAndResetDownloadUpdated());
unsafefile_item->OnContentCheckCompleted(DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE);
EXPECT_TRUE(unsafefile_observer.CheckAndResetDownloadUpdated());
+ EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(_, _))
+ .WillOnce(Return(true));
+ EXPECT_CALL(*download_file, RenameAndAnnotate(_, _, _, _, _));
unsafefile_item->ValidateDangerousDownload();
EXPECT_TRUE(unsafefile_observer.CheckAndResetDownloadUpdated());
+ CleanupItem(unsafefile_item, download_file, DownloadItem::IN_PROGRESS);
}
// DownloadItemImpl::OnDownloadTargetDetermined will schedule a task to run
@@ -642,16 +814,15 @@ TEST_F(DownloadItemTest, NotificationAfterOnContentCheckCompleted) {
TEST_F(DownloadItemTest, NotificationAfterOnDownloadTargetDetermined) {
DownloadItemImpl* item = CreateDownloadItem();
DownloadItemImplDelegate::DownloadTargetCallback callback;
- MockDownloadFile* download_file =
- AddDownloadFileToDownloadItem(item, &callback);
+ MockDownloadFile* download_file = CallDownloadItemStart(item, &callback);
TestDownloadItemObserver observer(item);
- base::FilePath target_path(kDummyPath);
+ base::FilePath target_path(kDummyTargetPath);
base::FilePath intermediate_path(target_path.InsertBeforeExtensionASCII("x"));
base::FilePath new_intermediate_path(
target_path.InsertBeforeExtensionASCII("y"));
EXPECT_CALL(*download_file, RenameAndUniquify(intermediate_path, _))
- .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
- new_intermediate_path));
+ .WillOnce(ScheduleRenameAndUniquifyCallback(
+ DOWNLOAD_INTERRUPT_REASON_NONE, new_intermediate_path));
// Currently, a notification would be generated if the danger type is anything
// other than NOT_DANGEROUS.
@@ -675,7 +846,8 @@ TEST_F(DownloadItemTest, NotificationAfterTogglePause) {
EXPECT_CALL(*mock_download_file, Initialize(_));
EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(_, _));
- item->Start(std::move(download_file), std::move(request_handle));
+ item->Start(std::move(download_file), std::move(request_handle),
+ *create_info());
item->Pause();
ASSERT_TRUE(observer.CheckAndResetDownloadUpdated());
@@ -693,15 +865,15 @@ TEST_F(DownloadItemTest, NotificationAfterTogglePause) {
TEST_F(DownloadItemTest, DisplayName) {
DownloadItemImpl* item = CreateDownloadItem();
DownloadItemImplDelegate::DownloadTargetCallback callback;
- MockDownloadFile* download_file =
- AddDownloadFileToDownloadItem(item, &callback);
- base::FilePath target_path(base::FilePath(kDummyPath).AppendASCII("foo.bar"));
+ MockDownloadFile* download_file = CallDownloadItemStart(item, &callback);
+ base::FilePath target_path(
+ base::FilePath(kDummyTargetPath).AppendASCII("foo.bar"));
base::FilePath intermediate_path(target_path.InsertBeforeExtensionASCII("x"));
EXPECT_EQ(FILE_PATH_LITERAL(""),
item->GetFileNameToReportUser().value());
EXPECT_CALL(*download_file, RenameAndUniquify(_, _))
- .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
- intermediate_path));
+ .WillOnce(ScheduleRenameAndUniquifyCallback(
+ DOWNLOAD_INTERRUPT_REASON_NONE, intermediate_path));
callback.Run(target_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path);
RunAllPendingInMessageLoops();
@@ -722,25 +894,90 @@ TEST_F(DownloadItemTest, Start) {
scoped_ptr<DownloadRequestHandleInterface> request_handle(
new NiceMock<MockRequestHandle>);
EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _));
- item->Start(std::move(download_file), std::move(request_handle));
+ item->Start(std::move(download_file), std::move(request_handle),
+ *create_info());
RunAllPendingInMessageLoops();
CleanupItem(item, mock_download_file, DownloadItem::IN_PROGRESS);
}
+// Download file and the request should be cancelled as a result of download
+// file initialization failing.
+TEST_F(DownloadItemTest, InitDownloadFileFails) {
+ DownloadItemImpl* item = CreateDownloadItem();
+ scoped_ptr<MockDownloadFile> file(new MockDownloadFile());
+ scoped_ptr<MockRequestHandle> request_handle(new MockRequestHandle());
+ EXPECT_CALL(*file, Cancel());
+ EXPECT_CALL(*request_handle, CancelRequest());
+ EXPECT_CALL(*file, Initialize(_))
+ .WillOnce(ScheduleCallbackWithParam(
+ DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED));
+
+ base::RunLoop start_download_loop;
+ DownloadItemImplDelegate::DownloadTargetCallback download_target_callback;
+ EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _))
+ .WillOnce(DoAll(SaveArg<1>(&download_target_callback),
+ ScheduleClosure(start_download_loop.QuitClosure())));
+
+ item->Start(std::move(file), std::move(request_handle), *create_info());
+ start_download_loop.Run();
+
+ download_target_callback.Run(base::FilePath(kDummyTargetPath),
+ DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+ DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+ base::FilePath(kDummyIntermediatePath));
+ RunAllPendingInMessageLoops();
+
+ EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState());
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED,
+ item->GetLastReason());
+}
+
+// Handling of downloads initiated via a failed request. In this case, Start()
+// will get called with a DownloadCreateInfo with a non-zero interrupt_reason.
+TEST_F(DownloadItemTest, StartFailedDownload) {
+ create_info()->result = DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED;
+ DownloadItemImpl* item = CreateDownloadItem();
+
+ // DownloadFile and DownloadRequestHandleInterface objects aren't created for
+ // failed downloads.
+ scoped_ptr<DownloadFile> null_download_file;
+ scoped_ptr<DownloadRequestHandleInterface> null_request_handle;
+ DownloadItemImplDelegate::DownloadTargetCallback download_target_callback;
+ EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(item, _))
+ .WillOnce(SaveArg<1>(&download_target_callback));
+ item->Start(std::move(null_download_file), std::move(null_request_handle),
+ *create_info());
+ EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
+ RunAllPendingInMessageLoops();
+
+ // The DownloadItemImpl should attempt to determine a target path even if the
+ // download was interrupted.
+ ASSERT_FALSE(download_target_callback.is_null());
+ ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
+ base::FilePath target_path(FILE_PATH_LITERAL("foo"));
+ download_target_callback.Run(target_path,
+ DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+ DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, target_path);
+ RunAllPendingInMessageLoops();
+
+ EXPECT_EQ(target_path, item->GetTargetFilePath());
+ CleanupItem(item, NULL, DownloadItem::INTERRUPTED);
+}
+
// Test that the delegate is invoked after the download file is renamed.
TEST_F(DownloadItemTest, CallbackAfterRename) {
DownloadItemImpl* item = CreateDownloadItem();
DownloadItemImplDelegate::DownloadTargetCallback callback;
- MockDownloadFile* download_file =
- AddDownloadFileToDownloadItem(item, &callback);
- base::FilePath final_path(base::FilePath(kDummyPath).AppendASCII("foo.bar"));
+ MockDownloadFile* download_file = CallDownloadItemStart(item, &callback);
+ base::FilePath final_path(
+ base::FilePath(kDummyTargetPath).AppendASCII("foo.bar"));
base::FilePath intermediate_path(final_path.InsertBeforeExtensionASCII("x"));
base::FilePath new_intermediate_path(
final_path.InsertBeforeExtensionASCII("y"));
EXPECT_CALL(*download_file, RenameAndUniquify(intermediate_path, _))
- .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
- new_intermediate_path));
+ .WillOnce(ScheduleRenameAndUniquifyCallback(
+ DOWNLOAD_INTERRUPT_REASON_NONE, new_intermediate_path));
callback.Run(final_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, intermediate_path);
@@ -751,13 +988,14 @@ TEST_F(DownloadItemTest, CallbackAfterRename) {
EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
.WillOnce(Return(true));
- EXPECT_CALL(*download_file, RenameAndAnnotate(final_path, _))
- .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
- final_path));
+ EXPECT_CALL(*download_file, RenameAndAnnotate(final_path, _, _, _, _))
+ .WillOnce(ScheduleRenameAndAnnotateCallback(
+ DOWNLOAD_INTERRUPT_REASON_NONE, final_path));
EXPECT_CALL(*download_file, FullPath())
- .WillOnce(Return(base::FilePath()));
+ .WillOnce(ReturnRefOfCopy(base::FilePath()));
EXPECT_CALL(*download_file, Detach());
- item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
+ item->DestinationObserverAsWeakPtr()->DestinationCompleted(
+ 0, scoped_ptr<crypto::SecureHash>());
RunAllPendingInMessageLoops();
::testing::Mock::VerifyAndClearExpectations(download_file);
mock_delegate()->VerifyAndClearExpectations();
@@ -768,15 +1006,15 @@ TEST_F(DownloadItemTest, CallbackAfterRename) {
TEST_F(DownloadItemTest, CallbackAfterInterruptedRename) {
DownloadItemImpl* item = CreateDownloadItem();
DownloadItemImplDelegate::DownloadTargetCallback callback;
- MockDownloadFile* download_file =
- AddDownloadFileToDownloadItem(item, &callback);
- base::FilePath final_path(base::FilePath(kDummyPath).AppendASCII("foo.bar"));
+ MockDownloadFile* download_file = CallDownloadItemStart(item, &callback);
+ base::FilePath final_path(
+ base::FilePath(kDummyTargetPath).AppendASCII("foo.bar"));
base::FilePath intermediate_path(final_path.InsertBeforeExtensionASCII("x"));
base::FilePath new_intermediate_path(
final_path.InsertBeforeExtensionASCII("y"));
EXPECT_CALL(*download_file, RenameAndUniquify(intermediate_path, _))
- .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED,
- new_intermediate_path));
+ .WillOnce(ScheduleRenameAndUniquifyCallback(
+ DOWNLOAD_INTERRUPT_REASON_FILE_FAILED, new_intermediate_path));
EXPECT_CALL(*download_file, Cancel())
.Times(1);
@@ -798,7 +1036,8 @@ TEST_F(DownloadItemTest, Interrupted) {
// Confirm interrupt sets state properly.
EXPECT_CALL(*download_file, Cancel());
- item->DestinationObserverAsWeakPtr()->DestinationError(reason);
+ item->DestinationObserverAsWeakPtr()->DestinationError(
+ reason, 0, scoped_ptr<crypto::SecureHash>());
RunAllPendingInMessageLoops();
EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState());
EXPECT_EQ(reason, item->GetLastReason());
@@ -814,19 +1053,21 @@ TEST_F(DownloadItemTest, Interrupted) {
TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Restart) {
DownloadItemImpl* item = CreateDownloadItem();
DownloadItemImplDelegate::DownloadTargetCallback callback;
- MockDownloadFile* download_file =
- AddDownloadFileToDownloadItem(item, &callback);
+ MockDownloadFile* download_file = CallDownloadItemStart(item, &callback);
item->DestinationObserverAsWeakPtr()->DestinationError(
- DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
+ DOWNLOAD_INTERRUPT_REASON_FILE_FAILED,
+ 0,
+ scoped_ptr<crypto::SecureHash>());
ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
- base::FilePath final_path(base::FilePath(kDummyPath).AppendASCII("foo.bar"));
+ base::FilePath final_path(
+ base::FilePath(kDummyTargetPath).AppendASCII("foo.bar"));
base::FilePath intermediate_path(final_path.InsertBeforeExtensionASCII("x"));
base::FilePath new_intermediate_path(
final_path.InsertBeforeExtensionASCII("y"));
EXPECT_CALL(*download_file, RenameAndUniquify(intermediate_path, _))
- .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
- new_intermediate_path));
+ .WillOnce(ScheduleRenameAndUniquifyCallback(
+ DOWNLOAD_INTERRUPT_REASON_NONE, new_intermediate_path));
EXPECT_CALL(*download_file, Cancel())
.Times(1);
@@ -847,21 +1088,23 @@ TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Restart) {
TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Continue) {
DownloadItemImpl* item = CreateDownloadItem();
DownloadItemImplDelegate::DownloadTargetCallback callback;
- MockDownloadFile* download_file =
- AddDownloadFileToDownloadItem(item, &callback);
+ MockDownloadFile* download_file = CallDownloadItemStart(item, &callback);
item->DestinationObserverAsWeakPtr()->DestinationError(
- DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED);
+ DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED,
+ 0,
+ scoped_ptr<crypto::SecureHash>());
ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
- base::FilePath final_path(base::FilePath(kDummyPath).AppendASCII("foo.bar"));
+ base::FilePath final_path(
+ base::FilePath(kDummyTargetPath).AppendASCII("foo.bar"));
base::FilePath intermediate_path(final_path.InsertBeforeExtensionASCII("x"));
base::FilePath new_intermediate_path(
final_path.InsertBeforeExtensionASCII("y"));
EXPECT_CALL(*download_file, RenameAndUniquify(intermediate_path, _))
- .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
- new_intermediate_path));
+ .WillOnce(ScheduleRenameAndUniquifyCallback(
+ DOWNLOAD_INTERRUPT_REASON_NONE, new_intermediate_path));
EXPECT_CALL(*download_file, FullPath())
- .WillOnce(Return(base::FilePath(new_intermediate_path)));
+ .WillOnce(ReturnRefOfCopy(base::FilePath(new_intermediate_path)));
EXPECT_CALL(*download_file, Detach());
callback.Run(final_path, DownloadItem::TARGET_DISPOSITION_OVERWRITE,
@@ -876,23 +1119,25 @@ TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Continue) {
}
// As above. If the intermediate rename fails, then the interrupt reason should
-// be set to the destination error and the intermediate path should be empty.
+// be set to the file error and the intermediate path should be empty.
TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Failed) {
DownloadItemImpl* item = CreateDownloadItem();
DownloadItemImplDelegate::DownloadTargetCallback callback;
- MockDownloadFile* download_file =
- AddDownloadFileToDownloadItem(item, &callback);
+ MockDownloadFile* download_file = CallDownloadItemStart(item, &callback);
item->DestinationObserverAsWeakPtr()->DestinationError(
- DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED);
+ DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED,
+ 0,
+ scoped_ptr<crypto::SecureHash>());
ASSERT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
- base::FilePath final_path(base::FilePath(kDummyPath).AppendASCII("foo.bar"));
+ base::FilePath final_path(
+ base::FilePath(kDummyTargetPath).AppendASCII("foo.bar"));
base::FilePath intermediate_path(final_path.InsertBeforeExtensionASCII("x"));
base::FilePath new_intermediate_path(
final_path.InsertBeforeExtensionASCII("y"));
EXPECT_CALL(*download_file, RenameAndUniquify(intermediate_path, _))
- .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED,
- new_intermediate_path));
+ .WillOnce(ScheduleRenameAndUniquifyCallback(
+ DOWNLOAD_INTERRUPT_REASON_FILE_FAILED, new_intermediate_path));
EXPECT_CALL(*download_file, Cancel())
.Times(1);
@@ -903,14 +1148,16 @@ TEST_F(DownloadItemTest, InterruptedBeforeIntermediateRename_Failed) {
::testing::Mock::VerifyAndClearExpectations(download_file);
mock_delegate()->VerifyAndClearExpectations();
EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState());
- EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED, item->GetLastReason());
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED, item->GetLastReason());
EXPECT_TRUE(item->GetFullPath().empty());
EXPECT_EQ(final_path, item->GetTargetFilePath());
}
TEST_F(DownloadItemTest, Canceled) {
DownloadItemImpl* item = CreateDownloadItem();
- MockDownloadFile* download_file = AddDownloadFileToDownloadItem(item, NULL);
+ DownloadItemImplDelegate::DownloadTargetCallback target_callback;
+ MockDownloadFile* download_file =
+ CallDownloadItemStart(item, &target_callback);
// Confirm cancel sets state properly.
EXPECT_CALL(*download_file, Cancel());
@@ -928,34 +1175,62 @@ TEST_F(DownloadItemTest, FileRemoved) {
TEST_F(DownloadItemTest, DestinationUpdate) {
DownloadItemImpl* item = CreateDownloadItem();
+ MockDownloadFile* file =
+ DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
base::WeakPtr<DownloadDestinationObserver> as_observer(
item->DestinationObserverAsWeakPtr());
TestDownloadItemObserver observer(item);
EXPECT_EQ(0l, item->CurrentSpeed());
- EXPECT_EQ("", item->GetHashState());
EXPECT_EQ(0l, item->GetReceivedBytes());
EXPECT_EQ(0l, item->GetTotalBytes());
EXPECT_FALSE(observer.CheckAndResetDownloadUpdated());
item->SetTotalBytes(100l);
EXPECT_EQ(100l, item->GetTotalBytes());
- as_observer->DestinationUpdate(10, 20, "deadbeef");
+ as_observer->DestinationUpdate(10, 20);
EXPECT_EQ(20l, item->CurrentSpeed());
- EXPECT_EQ("deadbeef", item->GetHashState());
EXPECT_EQ(10l, item->GetReceivedBytes());
EXPECT_EQ(100l, item->GetTotalBytes());
EXPECT_TRUE(observer.CheckAndResetDownloadUpdated());
- as_observer->DestinationUpdate(200, 20, "livebeef");
+ as_observer->DestinationUpdate(200, 20);
EXPECT_EQ(20l, item->CurrentSpeed());
- EXPECT_EQ("livebeef", item->GetHashState());
EXPECT_EQ(200l, item->GetReceivedBytes());
EXPECT_EQ(0l, item->GetTotalBytes());
EXPECT_TRUE(observer.CheckAndResetDownloadUpdated());
+
+ CleanupItem(item, file, DownloadItem::IN_PROGRESS);
}
-TEST_F(DownloadItemTest, DestinationError) {
+TEST_F(DownloadItemTest, DestinationError_NoRestartRequired) {
+ DownloadItemImpl* item = CreateDownloadItem();
+ MockDownloadFile* download_file =
+ DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
+ base::WeakPtr<DownloadDestinationObserver> as_observer(
+ item->DestinationObserverAsWeakPtr());
+ TestDownloadItemObserver observer(item);
+
+ EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, item->GetLastReason());
+ EXPECT_FALSE(observer.CheckAndResetDownloadUpdated());
+
+ scoped_ptr<crypto::SecureHash> hash(
+ crypto::SecureHash::Create(crypto::SecureHash::SHA256));
+ hash->Update(kTestData1, sizeof(kTestData1));
+
+ EXPECT_CALL(*download_file, Detach());
+ as_observer->DestinationError(
+ DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED, 0, std::move(hash));
+ mock_delegate()->VerifyAndClearExpectations();
+ EXPECT_TRUE(observer.CheckAndResetDownloadUpdated());
+ EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState());
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED, item->GetLastReason());
+ EXPECT_EQ(
+ std::string(std::begin(kHashOfTestData1), std::end(kHashOfTestData1)),
+ item->GetHash());
+}
+TEST_F(DownloadItemTest, DestinationError_RestartRequired) {
DownloadItemImpl* item = CreateDownloadItem();
MockDownloadFile* download_file =
DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
@@ -967,43 +1242,58 @@ TEST_F(DownloadItemTest, DestinationError) {
EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NONE, item->GetLastReason());
EXPECT_FALSE(observer.CheckAndResetDownloadUpdated());
+ scoped_ptr<crypto::SecureHash> hash(
+ crypto::SecureHash::Create(crypto::SecureHash::SHA256));
+ hash->Update(kTestData1, sizeof(kTestData1));
+
EXPECT_CALL(*download_file, Cancel());
as_observer->DestinationError(
- DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED);
+ DOWNLOAD_INTERRUPT_REASON_FILE_FAILED, 0, std::move(hash));
mock_delegate()->VerifyAndClearExpectations();
EXPECT_TRUE(observer.CheckAndResetDownloadUpdated());
EXPECT_EQ(DownloadItem::INTERRUPTED, item->GetState());
- EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED,
- item->GetLastReason());
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED, item->GetLastReason());
+ EXPECT_EQ(std::string(), item->GetHash());
}
TEST_F(DownloadItemTest, DestinationCompleted) {
DownloadItemImpl* item = CreateDownloadItem();
+ MockDownloadFile* download_file =
+ DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS);
base::WeakPtr<DownloadDestinationObserver> as_observer(
item->DestinationObserverAsWeakPtr());
TestDownloadItemObserver observer(item);
EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
EXPECT_EQ("", item->GetHash());
- EXPECT_EQ("", item->GetHashState());
EXPECT_FALSE(item->AllDataSaved());
EXPECT_FALSE(observer.CheckAndResetDownloadUpdated());
- as_observer->DestinationUpdate(10, 20, "deadbeef");
+ as_observer->DestinationUpdate(10, 20);
EXPECT_TRUE(observer.CheckAndResetDownloadUpdated());
EXPECT_FALSE(observer.CheckAndResetDownloadUpdated()); // Confirm reset.
EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
EXPECT_EQ("", item->GetHash());
- EXPECT_EQ("deadbeef", item->GetHashState());
EXPECT_FALSE(item->AllDataSaved());
- as_observer->DestinationCompleted("livebeef");
+ scoped_ptr<crypto::SecureHash> hash(
+ crypto::SecureHash::Create(crypto::SecureHash::SHA256));
+ hash->Update(kTestData1, sizeof(kTestData1));
+
+ EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(_, _));
+ as_observer->DestinationCompleted(10, std::move(hash));
mock_delegate()->VerifyAndClearExpectations();
EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
EXPECT_TRUE(observer.CheckAndResetDownloadUpdated());
- EXPECT_EQ("livebeef", item->GetHash());
- EXPECT_EQ("", item->GetHashState());
+ EXPECT_EQ(
+ std::string(std::begin(kHashOfTestData1), std::end(kHashOfTestData1)),
+ item->GetHash());
EXPECT_TRUE(item->AllDataSaved());
+
+ // Even though the DownloadItem receives a DestinationCompleted() event,
+ // target determination hasn't completed, hence the download item is stuck in
+ // TARGET_PENDING.
+ CleanupItem(item, download_file, DownloadItem::IN_PROGRESS);
}
TEST_F(DownloadItemTest, EnabledActionsForNormalDownload) {
@@ -1018,15 +1308,16 @@ TEST_F(DownloadItemTest, EnabledActionsForNormalDownload) {
EXPECT_TRUE(item->CanOpenDownload());
// Complete
- EXPECT_CALL(*download_file, RenameAndAnnotate(_, _))
- .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
- base::FilePath(kDummyPath)));
+ EXPECT_CALL(*download_file, RenameAndAnnotate(_, _, _, _, _))
+ .WillOnce(ScheduleRenameAndAnnotateCallback(
+ DOWNLOAD_INTERRUPT_REASON_NONE, base::FilePath(kDummyTargetPath)));
EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
.WillOnce(Return(true));
EXPECT_CALL(*download_file, FullPath())
- .WillOnce(Return(base::FilePath()));
+ .WillOnce(ReturnRefOfCopy(base::FilePath()));
EXPECT_CALL(*download_file, Detach());
- item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
+ item->DestinationObserverAsWeakPtr()->DestinationCompleted(
+ 0, scoped_ptr<crypto::SecureHash>());
RunAllPendingInMessageLoops();
ASSERT_EQ(DownloadItem::COMPLETE, item->GetState());
@@ -1050,13 +1341,14 @@ TEST_F(DownloadItemTest, EnabledActionsForTemporaryDownload) {
// Complete Temporary
EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
.WillOnce(Return(true));
- EXPECT_CALL(*download_file, RenameAndAnnotate(_, _))
- .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
- base::FilePath(kDummyPath)));
+ EXPECT_CALL(*download_file, RenameAndAnnotate(_, _, _, _, _))
+ .WillOnce(ScheduleRenameAndAnnotateCallback(
+ DOWNLOAD_INTERRUPT_REASON_NONE, base::FilePath(kDummyTargetPath)));
EXPECT_CALL(*download_file, FullPath())
- .WillOnce(Return(base::FilePath()));
+ .WillOnce(ReturnRefOfCopy(base::FilePath()));
EXPECT_CALL(*download_file, Detach());
- item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
+ item->DestinationObserverAsWeakPtr()->DestinationCompleted(
+ 0, scoped_ptr<crypto::SecureHash>());
RunAllPendingInMessageLoops();
ASSERT_EQ(DownloadItem::COMPLETE, item->GetState());
@@ -1071,13 +1363,15 @@ TEST_F(DownloadItemTest, EnabledActionsForInterruptedDownload) {
EXPECT_CALL(*download_file, Cancel());
item->DestinationObserverAsWeakPtr()->DestinationError(
- DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
+ DOWNLOAD_INTERRUPT_REASON_FILE_FAILED,
+ 0,
+ scoped_ptr<crypto::SecureHash>());
RunAllPendingInMessageLoops();
ASSERT_EQ(DownloadItem::INTERRUPTED, item->GetState());
ASSERT_FALSE(item->GetTargetFilePath().empty());
EXPECT_FALSE(item->CanShowInFolder());
- EXPECT_FALSE(item->CanOpenDownload());
+ EXPECT_TRUE(item->CanOpenDownload());
}
TEST_F(DownloadItemTest, EnabledActionsForCancelledDownload) {
@@ -1107,18 +1401,20 @@ TEST_F(DownloadItemTest, CompleteDelegate_ReturnTrue) {
// Drive the delegate interaction.
EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(item, _))
.WillOnce(Return(true));
- item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
+ item->DestinationObserverAsWeakPtr()->DestinationCompleted(
+ 0, scoped_ptr<crypto::SecureHash>());
EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
EXPECT_FALSE(item->IsDangerous());
// Make sure the download can complete.
- EXPECT_CALL(*download_file, RenameAndAnnotate(base::FilePath(kDummyPath), _))
- .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
- base::FilePath(kDummyPath)));
+ EXPECT_CALL(*download_file,
+ RenameAndAnnotate(base::FilePath(kDummyTargetPath), _, _, _, _))
+ .WillOnce(ScheduleRenameAndAnnotateCallback(
+ DOWNLOAD_INTERRUPT_REASON_NONE, base::FilePath(kDummyTargetPath)));
EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item, _))
.WillOnce(Return(true));
EXPECT_CALL(*download_file, FullPath())
- .WillOnce(Return(base::FilePath()));
+ .WillOnce(ReturnRefOfCopy(base::FilePath()));
EXPECT_CALL(*download_file, Detach());
RunAllPendingInMessageLoops();
EXPECT_EQ(DownloadItem::COMPLETE, item->GetState());
@@ -1139,7 +1435,8 @@ TEST_F(DownloadItemTest, CompleteDelegate_BlockOnce) {
.WillOnce(DoAll(SaveArg<1>(&delegate_callback),
Return(false)))
.WillOnce(Return(true));
- item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
+ item->DestinationObserverAsWeakPtr()->DestinationCompleted(
+ 0, scoped_ptr<crypto::SecureHash>());
ASSERT_FALSE(delegate_callback.is_null());
copy_delegate_callback = delegate_callback;
delegate_callback.Reset();
@@ -1150,13 +1447,14 @@ TEST_F(DownloadItemTest, CompleteDelegate_BlockOnce) {
EXPECT_FALSE(item->IsDangerous());
// Make sure the download can complete.
- EXPECT_CALL(*download_file, RenameAndAnnotate(base::FilePath(kDummyPath), _))
- .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
- base::FilePath(kDummyPath)));
+ EXPECT_CALL(*download_file,
+ RenameAndAnnotate(base::FilePath(kDummyTargetPath), _, _, _, _))
+ .WillOnce(ScheduleRenameAndAnnotateCallback(
+ DOWNLOAD_INTERRUPT_REASON_NONE, base::FilePath(kDummyTargetPath)));
EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item, _))
.WillOnce(Return(true));
EXPECT_CALL(*download_file, FullPath())
- .WillOnce(Return(base::FilePath()));
+ .WillOnce(ReturnRefOfCopy(base::FilePath()));
EXPECT_CALL(*download_file, Detach());
RunAllPendingInMessageLoops();
EXPECT_EQ(DownloadItem::COMPLETE, item->GetState());
@@ -1177,7 +1475,8 @@ TEST_F(DownloadItemTest, CompleteDelegate_SetDanger) {
.WillOnce(DoAll(SaveArg<1>(&delegate_callback),
Return(false)))
.WillOnce(Return(true));
- item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
+ item->DestinationObserverAsWeakPtr()->DestinationCompleted(
+ 0, scoped_ptr<crypto::SecureHash>());
ASSERT_FALSE(delegate_callback.is_null());
copy_delegate_callback = delegate_callback;
delegate_callback.Reset();
@@ -1191,13 +1490,14 @@ TEST_F(DownloadItemTest, CompleteDelegate_SetDanger) {
EXPECT_TRUE(item->IsDangerous());
// Make sure the download doesn't complete until we've validated it.
- EXPECT_CALL(*download_file, RenameAndAnnotate(base::FilePath(kDummyPath), _))
- .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
- base::FilePath(kDummyPath)));
+ EXPECT_CALL(*download_file,
+ RenameAndAnnotate(base::FilePath(kDummyTargetPath), _, _, _, _))
+ .WillOnce(ScheduleRenameAndAnnotateCallback(
+ DOWNLOAD_INTERRUPT_REASON_NONE, base::FilePath(kDummyTargetPath)));
EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item, _))
.WillOnce(Return(true));
EXPECT_CALL(*download_file, FullPath())
- .WillOnce(Return(base::FilePath()));
+ .WillOnce(ReturnRefOfCopy(base::FilePath()));
EXPECT_CALL(*download_file, Detach());
RunAllPendingInMessageLoops();
EXPECT_EQ(DownloadItem::IN_PROGRESS, item->GetState());
@@ -1226,7 +1526,8 @@ TEST_F(DownloadItemTest, CompleteDelegate_BlockTwice) {
.WillOnce(DoAll(SaveArg<1>(&delegate_callback),
Return(false)))
.WillOnce(Return(true));
- item->DestinationObserverAsWeakPtr()->DestinationCompleted(std::string());
+ item->DestinationObserverAsWeakPtr()->DestinationCompleted(
+ 0, scoped_ptr<crypto::SecureHash>());
ASSERT_FALSE(delegate_callback.is_null());
copy_delegate_callback = delegate_callback;
delegate_callback.Reset();
@@ -1242,13 +1543,14 @@ TEST_F(DownloadItemTest, CompleteDelegate_BlockTwice) {
EXPECT_FALSE(item->IsDangerous());
// Make sure the download can complete.
- EXPECT_CALL(*download_file, RenameAndAnnotate(base::FilePath(kDummyPath), _))
- .WillOnce(ScheduleRenameCallback(DOWNLOAD_INTERRUPT_REASON_NONE,
- base::FilePath(kDummyPath)));
+ EXPECT_CALL(*download_file,
+ RenameAndAnnotate(base::FilePath(kDummyTargetPath), _, _, _, _))
+ .WillOnce(ScheduleRenameAndAnnotateCallback(
+ DOWNLOAD_INTERRUPT_REASON_NONE, base::FilePath(kDummyTargetPath)));
EXPECT_CALL(*mock_delegate(), ShouldOpenDownload(item, _))
.WillOnce(Return(true));
EXPECT_CALL(*download_file, FullPath())
- .WillOnce(Return(base::FilePath()));
+ .WillOnce(ReturnRefOfCopy(base::FilePath()));
EXPECT_CALL(*download_file, Detach());
RunAllPendingInMessageLoops();
EXPECT_EQ(DownloadItem::COMPLETE, item->GetState());
@@ -1262,8 +1564,7 @@ TEST_F(DownloadItemTest, StealDangerousDownload) {
base::FilePath full_path(FILE_PATH_LITERAL("foo.txt"));
base::FilePath returned_path;
- EXPECT_CALL(*download_file, FullPath())
- .WillOnce(Return(full_path));
+ EXPECT_CALL(*download_file, FullPath()).WillOnce(ReturnRefOfCopy(full_path));
EXPECT_CALL(*download_file, Detach());
EXPECT_CALL(*mock_delegate(), DownloadRemoved(_));
base::WeakPtrFactory<DownloadItemTest> weak_ptr_factory(this);
@@ -1282,11 +1583,12 @@ TEST_F(DownloadItemTest, StealInterruptedDangerousDownload) {
DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE);
base::FilePath full_path = item->GetFullPath();
EXPECT_FALSE(full_path.empty());
- EXPECT_CALL(*download_file, FullPath())
- .WillOnce(Return(full_path));
+ EXPECT_CALL(*download_file, FullPath()).WillOnce(ReturnRefOfCopy(full_path));
EXPECT_CALL(*download_file, Detach());
item->DestinationObserverAsWeakPtr()->DestinationError(
- DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED);
+ DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED,
+ 0,
+ scoped_ptr<crypto::SecureHash>());
ASSERT_TRUE(item->IsDangerous());
EXPECT_CALL(*mock_delegate(), DownloadRemoved(_));
@@ -1306,7 +1608,9 @@ TEST_F(DownloadItemTest, StealInterruptedNonResumableDangerousDownload) {
DoIntermediateRename(item, DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE);
EXPECT_CALL(*download_file, Cancel());
item->DestinationObserverAsWeakPtr()->DestinationError(
- DOWNLOAD_INTERRUPT_REASON_FILE_FAILED);
+ DOWNLOAD_INTERRUPT_REASON_FILE_FAILED,
+ 0,
+ scoped_ptr<crypto::SecureHash>());
ASSERT_TRUE(item->IsDangerous());
EXPECT_CALL(*mock_delegate(), DownloadRemoved(_));
@@ -1319,6 +1623,428 @@ TEST_F(DownloadItemTest, StealInterruptedNonResumableDangerousDownload) {
EXPECT_TRUE(returned_path.empty());
}
+namespace {
+
+// The DownloadItemDestinationUpdateRaceTest fixture (defined below) is used to
+// test for race conditions between download destination events received via the
+// DownloadDestinationObserver interface, and the target determination logic.
+//
+// The general control flow for DownloadItemImpl looks like this:
+//
+// * Start() called, which in turn calls DownloadFile::Initialize().
+//
+// Even though OnDownloadFileInitialized hasn't been called, there could now
+// be destination observer calls queued prior to the task that calls
+// OnDownloadFileInitialized. Let's call this point in the workflow "A".
+//
+// * DownloadItemImpl::OnDownloadFileInitialized() called.
+//
+// * Assuming the result is successful, DII now invokes the delegate's
+// DetermineDownloadTarget method.
+//
+// At this point DonwnloadFile acts as the source of
+// DownloadDestinationObserver events, and may invoke callbacks. Let's call
+// this point in the workflow "B".
+//
+// * DII::OnDownloadTargetDetermined() invoked after delegate is done with
+// target determination.
+//
+// * DII attempts to rename the DownloadFile to its intermediate name.
+//
+// More DownloadDestinationObserver events can happen here. Let's call this
+// point in the workflow "C".
+//
+// * DII::OnDownloadRenamedToIntermediateName() invoked. Assuming all went well,
+// DII is now in IN_PROGRESS state.
+//
+// More DownloadDestinationObserver events can happen here. Let's call this
+// point in the workflow "D".
+//
+// The DownloadItemDestinationUpdateRaceTest works by generating various
+// combinations of DownloadDestinationObserver events that might occur at the
+// points "A", "B", "C", and "D" above. Each test in this suite cranks a
+// DownloadItemImpl through the states listed above and invokes the events
+// assigned to each position.
+
+// This type of callback represents a call to a DownloadDestinationObserver
+// method that's missing the DownloadDestinationObserver object. Currying this
+// way allows us to bind a call prior to constructing the object on which the
+// method would be invoked. This is necessary since we are going to construct
+// various permutations of observer calls that will then be applied to a
+// DownloadItem in a state as yet undetermined.
+using CurriedObservation =
+ base::Callback<void(base::WeakPtr<DownloadDestinationObserver>)>;
+
+// A list of observations that are to be made during some event in the
+// DownloadItemImpl control flow. Ordering of the observations is significant.
+using ObservationList = std::deque<CurriedObservation>;
+
+// An ordered list of events.
+//
+// An "event" in this context refers to some stage in the DownloadItemImpl's
+// workflow described as "A", "B", "C", or "D" above. An EventList is expected
+// to always contains kEventCount events.
+using EventList = std::deque<ObservationList>;
+
+// Number of events in an EventList. This is always 4 for now as described
+// above.
+const int kEventCount = 4;
+
+// The following functions help us with currying the calls to
+// DownloadDestinationObserver. If std::bind was allowed along with
+// std::placeholders, it is possible to avoid these functions, but currently
+// Chromium doesn't allow using std::bind for good reasons.
+void DestinationUpdateInvoker(
+ int64_t bytes_so_far,
+ int64_t bytes_per_sec,
+ base::WeakPtr<DownloadDestinationObserver> observer) {
+ DVLOG(20) << "DestinationUpdate(bytes_so_far:" << bytes_so_far
+ << ", bytes_per_sec:" << bytes_per_sec
+ << ") observer:" << !!observer;
+ if (observer)
+ observer->DestinationUpdate(bytes_so_far, bytes_per_sec);
+}
+
+void DestinationErrorInvoker(
+ DownloadInterruptReason reason,
+ int64_t bytes_so_far,
+ base::WeakPtr<DownloadDestinationObserver> observer) {
+ DVLOG(20) << "DestinationError(reason:"
+ << DownloadInterruptReasonToString(reason)
+ << ", bytes_so_far:" << bytes_so_far << ") observer:" << !!observer;
+ if (observer)
+ observer->DestinationError(
+ reason, bytes_so_far, scoped_ptr<crypto::SecureHash>());
+}
+
+void DestinationCompletedInvoker(
+ int64_t total_bytes,
+ base::WeakPtr<DownloadDestinationObserver> observer) {
+ DVLOG(20) << "DestinationComplete(total_bytes:" << total_bytes
+ << ") observer:" << !!observer;
+ if (observer)
+ observer->DestinationCompleted(total_bytes,
+ scoped_ptr<crypto::SecureHash>());
+}
+
+// Given a set of observations (via the range |begin|..|end|), constructs a list
+// of EventLists such that:
+//
+// * There are exactly |event_count| ObservationSets in each EventList.
+//
+// * Each ObservationList in each EventList contains a subrange (possibly empty)
+// of observations from the input range, in the same order as the input range.
+//
+// * The ordering of the ObservationList in each EventList is such that all
+// observations in one ObservationList occur earlier than all observations in
+// an ObservationList that follows it.
+//
+// * The list of EventLists together describe all the possible ways in which the
+// list of observations can be distributed into |event_count| events.
+std::vector<EventList> DistributeObservationsIntoEvents(
+ const std::vector<CurriedObservation>::iterator begin,
+ const std::vector<CurriedObservation>::iterator end,
+ int event_count) {
+ std::vector<EventList> all_event_lists;
+ for (auto partition = begin;; ++partition) {
+ ObservationList first_group_of_observations(begin, partition);
+ if (event_count > 1) {
+ std::vector<EventList> list_of_subsequent_events =
+ DistributeObservationsIntoEvents(partition, end, event_count - 1);
+ for (const auto& subsequent_events : list_of_subsequent_events) {
+ EventList event_list;
+ event_list = subsequent_events;
+ event_list.push_front(first_group_of_observations);
+ all_event_lists.push_back(event_list);
+ }
+ } else {
+ EventList event_list;
+ event_list.push_front(first_group_of_observations);
+ all_event_lists.push_back(event_list);
+ }
+ if (partition == end)
+ break;
+ }
+ return all_event_lists;
+}
+
+// For the purpose of this tests, we are only concerned with 3 events:
+//
+// 1. Immediately after the DownloadFile is initialized.
+// 2. Immediately after the DownloadTargetCallback is invoked.
+// 3. Immediately after the intermediate file is renamed.
+//
+// We are going to take a couple of sets of DownloadDestinationObserver events
+// and distribute them into the three events described above. And then we are
+// going to invoke the observations while a DownloadItemImpl is carefully
+// stepped through its stages.
+
+std::vector<EventList> GenerateSuccessfulEventLists() {
+ std::vector<CurriedObservation> all_observations;
+ all_observations.push_back(base::Bind(&DestinationUpdateInvoker, 100, 100));
+ all_observations.push_back(base::Bind(&DestinationUpdateInvoker, 200, 100));
+ all_observations.push_back(base::Bind(&DestinationCompletedInvoker, 200));
+ return DistributeObservationsIntoEvents(all_observations.begin(),
+ all_observations.end(), kEventCount);
+}
+
+std::vector<EventList> GenerateFailingEventLists() {
+ std::vector<CurriedObservation> all_observations;
+ all_observations.push_back(base::Bind(&DestinationUpdateInvoker, 100, 100));
+ all_observations.push_back(base::Bind(
+ &DestinationErrorInvoker, DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED, 100));
+ return DistributeObservationsIntoEvents(all_observations.begin(),
+ all_observations.end(), kEventCount);
+}
+
+class DownloadItemDestinationUpdateRaceTest
+ : public DownloadItemTest,
+ public ::testing::WithParamInterface<EventList> {
+ public:
+ DownloadItemDestinationUpdateRaceTest()
+ : DownloadItemTest(),
+ item_(CreateDownloadItem()),
+ file_(new ::testing::StrictMock<MockDownloadFile>()),
+ request_handle_(new ::testing::StrictMock<MockRequestHandle>()) {
+ DCHECK_EQ(GetParam().size(), static_cast<unsigned>(kEventCount));
+ EXPECT_CALL(*request_handle_, GetWebContents())
+ .WillRepeatedly(Return(nullptr));
+ }
+
+ protected:
+ const ObservationList& PreInitializeFileObservations() {
+ return GetParam().front();
+ }
+ const ObservationList& PostInitializeFileObservations() {
+ return *(GetParam().begin() + 1);
+ }
+ const ObservationList& PostTargetDeterminationObservations() {
+ return *(GetParam().begin() + 2);
+ }
+ const ObservationList& PostIntermediateRenameObservations() {
+ return *(GetParam().begin() + 3);
+ }
+
+ // Apply all the observations in |observations| to |observer|, but do so
+ // asynchronously so that the events are applied in order behind any tasks
+ // that are already scheduled.
+ void ScheduleObservations(
+ const ObservationList& observations,
+ base::WeakPtr<DownloadDestinationObserver> observer) {
+ for (const auto action : observations)
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(action, observer));
+ }
+
+ DownloadItemImpl* item_;
+ scoped_ptr<MockDownloadFile> file_;
+ scoped_ptr<MockRequestHandle> request_handle_;
+
+ std::queue<base::Closure> successful_update_events_;
+ std::queue<base::Closure> failing_update_events_;
+};
+
+INSTANTIATE_TEST_CASE_P(Success,
+ DownloadItemDestinationUpdateRaceTest,
+ ::testing::ValuesIn(GenerateSuccessfulEventLists()));
+
+INSTANTIATE_TEST_CASE_P(Failure,
+ DownloadItemDestinationUpdateRaceTest,
+ ::testing::ValuesIn(GenerateFailingEventLists()));
+
+} // namespace
+
+// Run through the DII workflow but the embedder cancels the download at target
+// determination.
+TEST_P(DownloadItemDestinationUpdateRaceTest, DownloadCancelledByUser) {
+ // Expect that the download file and the request will be cancelled as a
+ // result.
+ EXPECT_CALL(*file_, Cancel());
+ EXPECT_CALL(*request_handle_, CancelRequest());
+
+ base::RunLoop download_start_loop;
+ DownloadFile::InitializeCallback initialize_callback;
+ EXPECT_CALL(*file_, Initialize(_))
+ .WillOnce(DoAll(SaveArg<0>(&initialize_callback),
+ ScheduleClosure(download_start_loop.QuitClosure())));
+ item_->Start(std::move(file_), std::move(request_handle_), *create_info());
+ download_start_loop.Run();
+
+ base::WeakPtr<DownloadDestinationObserver> destination_observer =
+ item_->DestinationObserverAsWeakPtr();
+
+ ScheduleObservations(PreInitializeFileObservations(), destination_observer);
+ RunAllPendingInMessageLoops();
+
+ base::RunLoop initialize_completion_loop;
+ DownloadItemImplDelegate::DownloadTargetCallback target_callback;
+ EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(_, _))
+ .WillOnce(
+ DoAll(SaveArg<1>(&target_callback),
+ ScheduleClosure(initialize_completion_loop.QuitClosure())));
+ ScheduleObservations(PostInitializeFileObservations(), destination_observer);
+ initialize_callback.Run(DOWNLOAD_INTERRUPT_REASON_NONE);
+ initialize_completion_loop.Run();
+
+ RunAllPendingInMessageLoops();
+
+ ASSERT_FALSE(target_callback.is_null());
+ ScheduleObservations(PostTargetDeterminationObservations(),
+ destination_observer);
+ target_callback.Run(base::FilePath(),
+ DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+ DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS, base::FilePath());
+ EXPECT_EQ(DownloadItem::CANCELLED, item_->GetState());
+ RunAllPendingInMessageLoops();
+}
+
+// Run through the DII workflow, but the intermediate rename fails.
+TEST_P(DownloadItemDestinationUpdateRaceTest, IntermediateRenameFails) {
+ // Expect that the download file and the request will be cancelled as a
+ // result.
+ EXPECT_CALL(*file_, Cancel());
+ EXPECT_CALL(*request_handle_, CancelRequest());
+
+ // Intermediate rename loop is not used immediately, but let's set up the
+ // DownloadFile expectations since we are about to transfer its ownership to
+ // the DownloadItem.
+ base::RunLoop intermediate_rename_loop;
+ DownloadFile::RenameCompletionCallback intermediate_rename_callback;
+ EXPECT_CALL(*file_, RenameAndUniquify(_, _))
+ .WillOnce(DoAll(SaveArg<1>(&intermediate_rename_callback),
+ ScheduleClosure(intermediate_rename_loop.QuitClosure())));
+
+ base::RunLoop download_start_loop;
+ DownloadFile::InitializeCallback initialize_callback;
+ EXPECT_CALL(*file_, Initialize(_))
+ .WillOnce(DoAll(SaveArg<0>(&initialize_callback),
+ ScheduleClosure(download_start_loop.QuitClosure())));
+
+ item_->Start(std::move(file_), std::move(request_handle_), *create_info());
+ download_start_loop.Run();
+ base::WeakPtr<DownloadDestinationObserver> destination_observer =
+ item_->DestinationObserverAsWeakPtr();
+
+ ScheduleObservations(PreInitializeFileObservations(), destination_observer);
+ RunAllPendingInMessageLoops();
+
+ base::RunLoop initialize_completion_loop;
+ DownloadItemImplDelegate::DownloadTargetCallback target_callback;
+ EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(_, _))
+ .WillOnce(
+ DoAll(SaveArg<1>(&target_callback),
+ ScheduleClosure(initialize_completion_loop.QuitClosure())));
+ ScheduleObservations(PostInitializeFileObservations(), destination_observer);
+ initialize_callback.Run(DOWNLOAD_INTERRUPT_REASON_NONE);
+ initialize_completion_loop.Run();
+
+ RunAllPendingInMessageLoops();
+ ASSERT_FALSE(target_callback.is_null());
+
+ ScheduleObservations(PostTargetDeterminationObservations(),
+ destination_observer);
+ target_callback.Run(base::FilePath(kDummyTargetPath),
+ DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+ DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+ base::FilePath(kDummyIntermediatePath));
+
+ intermediate_rename_loop.Run();
+ ASSERT_FALSE(intermediate_rename_callback.is_null());
+
+ ScheduleObservations(PostIntermediateRenameObservations(),
+ destination_observer);
+ intermediate_rename_callback.Run(DOWNLOAD_INTERRUPT_REASON_FILE_FAILED,
+ base::FilePath());
+ RunAllPendingInMessageLoops();
+
+ EXPECT_EQ(DownloadItem::INTERRUPTED, item_->GetState());
+}
+
+// Run through the DII workflow. Download file initialization, target
+// determination and intermediate rename all succeed.
+TEST_P(DownloadItemDestinationUpdateRaceTest, IntermediateRenameSucceeds) {
+ // We expect either that the download will fail (in which case the request and
+ // the download file will be cancelled), or it will succeed (in which case the
+ // DownloadFile will Detach()). It depends on the list of observations that
+ // are given to us.
+ EXPECT_CALL(*file_, Cancel()).Times(::testing::AnyNumber());
+ EXPECT_CALL(*request_handle_, CancelRequest()).Times(::testing::AnyNumber());
+ EXPECT_CALL(*file_, Detach()).Times(::testing::AnyNumber());
+
+ EXPECT_CALL(*file_, FullPath())
+ .WillRepeatedly(ReturnRefOfCopy(base::FilePath(kDummyIntermediatePath)));
+
+ // Intermediate rename loop is not used immediately, but let's set up the
+ // DownloadFile expectations since we are about to transfer its ownership to
+ // the DownloadItem.
+ base::RunLoop intermediate_rename_loop;
+ DownloadFile::RenameCompletionCallback intermediate_rename_callback;
+ EXPECT_CALL(*file_, RenameAndUniquify(_, _))
+ .WillOnce(DoAll(SaveArg<1>(&intermediate_rename_callback),
+ ScheduleClosure(intermediate_rename_loop.QuitClosure())));
+
+ base::RunLoop download_start_loop;
+ DownloadFile::InitializeCallback initialize_callback;
+ EXPECT_CALL(*file_, Initialize(_))
+ .WillOnce(DoAll(SaveArg<0>(&initialize_callback),
+ ScheduleClosure(download_start_loop.QuitClosure())));
+
+ item_->Start(std::move(file_), std::move(request_handle_), *create_info());
+ download_start_loop.Run();
+ base::WeakPtr<DownloadDestinationObserver> destination_observer =
+ item_->DestinationObserverAsWeakPtr();
+
+ ScheduleObservations(PreInitializeFileObservations(), destination_observer);
+ RunAllPendingInMessageLoops();
+
+ base::RunLoop initialize_completion_loop;
+ DownloadItemImplDelegate::DownloadTargetCallback target_callback;
+ EXPECT_CALL(*mock_delegate(), DetermineDownloadTarget(_, _))
+ .WillOnce(
+ DoAll(SaveArg<1>(&target_callback),
+ ScheduleClosure(initialize_completion_loop.QuitClosure())));
+ ScheduleObservations(PostInitializeFileObservations(), destination_observer);
+ initialize_callback.Run(DOWNLOAD_INTERRUPT_REASON_NONE);
+ initialize_completion_loop.Run();
+
+ RunAllPendingInMessageLoops();
+ ASSERT_FALSE(target_callback.is_null());
+
+ ScheduleObservations(PostTargetDeterminationObservations(),
+ destination_observer);
+ target_callback.Run(base::FilePath(kDummyTargetPath),
+ DownloadItem::TARGET_DISPOSITION_OVERWRITE,
+ DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+ base::FilePath(kDummyIntermediatePath));
+
+ intermediate_rename_loop.Run();
+ ASSERT_FALSE(intermediate_rename_callback.is_null());
+
+ // This may or may not be called, depending on whether there are any errors in
+ // our action list.
+ EXPECT_CALL(*mock_delegate(), ShouldCompleteDownload(_, _))
+ .Times(::testing::AnyNumber());
+
+ ScheduleObservations(PostIntermediateRenameObservations(),
+ destination_observer);
+ intermediate_rename_callback.Run(DOWNLOAD_INTERRUPT_REASON_NONE,
+ base::FilePath(kDummyIntermediatePath));
+ RunAllPendingInMessageLoops();
+
+ // The state of the download depends on the observer events that were played
+ // back to the DownloadItemImpl. Hence we can't establish a single expectation
+ // here. On Debug builds, the DCHECKs will verify that the state transitions
+ // were correct. On Release builds, tests are expected to run to completion
+ // without crashing on success.
+ EXPECT_TRUE(item_->GetState() == DownloadItem::IN_PROGRESS ||
+ item_->GetState() == DownloadItem::INTERRUPTED);
+ if (item_->GetState() == DownloadItem::INTERRUPTED)
+ EXPECT_EQ(DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED, item_->GetLastReason());
+
+ item_->Cancel(true);
+ RunAllPendingInMessageLoops();
+}
+
TEST(MockDownloadItem, Compiles) {
MockDownloadItem mock_item;
}
diff --git a/chromium/content/browser/download/download_manager_impl.cc b/chromium/content/browser/download/download_manager_impl.cc
index 97c0a85e714..28f1c3fca65 100644
--- a/chromium/content/browser/download/download_manager_impl.cc
+++ b/chromium/content/browser/download/download_manager_impl.cc
@@ -45,6 +45,7 @@
#include "net/base/request_priority.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/url_request/url_request_context.h"
+#include "storage/browser/blob/blob_url_request_job_factory.h"
#include "url/origin.h"
namespace content {
@@ -55,90 +56,53 @@ scoped_ptr<UrlDownloader, BrowserThread::DeleteOnIOThread> BeginDownload(
uint32_t download_id,
base::WeakPtr<DownloadManagerImpl> download_manager) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and
- // DownloadUrlParameters can-not include resource_dispatcher_host_impl.h, so
- // we must down cast. RDHI is the only subclass of RDH as of 2012 May 4.
- scoped_ptr<net::URLRequest> request(
- params->resource_context()->GetRequestContext()->CreateRequest(
- params->url(), net::DEFAULT_PRIORITY, NULL));
- request->set_method(params->method());
- if (!params->post_body().empty()) {
- const std::string& body = params->post_body();
- scoped_ptr<net::UploadElementReader> reader(
- net::UploadOwnedBytesElementReader::CreateWithString(body));
- request->set_upload(
- net::ElementsUploadDataStream::CreateWithReader(std::move(reader), 0));
- }
- if (params->post_id() >= 0) {
- // The POST in this case does not have an actual body, and only works
- // when retrieving data from cache. This is done because we don't want
- // to do a re-POST without user consent, and currently don't have a good
- // plan on how to display the UI for that.
- DCHECK(params->prefer_cache());
- DCHECK_EQ("POST", params->method());
- std::vector<scoped_ptr<net::UploadElementReader>> element_readers;
- request->set_upload(make_scoped_ptr(new net::ElementsUploadDataStream(
- std::move(element_readers), params->post_id())));
- }
- // If we're not at the beginning of the file, retrieve only the remaining
- // portion.
- bool has_last_modified = !params->last_modified().empty();
- bool has_etag = !params->etag().empty();
-
- // If we've asked for a range, we want to make sure that we only
- // get that range if our current copy of the information is good.
- // We shouldn't be asked to continue if we don't have a verifier.
- DCHECK(params->offset() == 0 || has_etag || has_last_modified);
-
- if (params->offset() > 0 && (has_etag || has_last_modified)) {
- request->SetExtraRequestHeaderByName(
- "Range",
- base::StringPrintf("bytes=%" PRId64 "-", params->offset()),
- true);
-
- // In accordance with RFC 2616 Section 14.27, use If-Range to specify that
- // the server return the entire entity if the validator doesn't match.
- // Last-Modified can be used in the absence of ETag as a validator if the
- // response headers satisfied the HttpUtil::HasStrongValidators() predicate.
- //
- // This function assumes that HasStrongValidators() was true and that the
- // ETag and Last-Modified header values supplied are valid.
- request->SetExtraRequestHeaderByName(
- "If-Range", has_etag ? params->etag() : params->last_modified(), true);
+ scoped_ptr<net::URLRequest> url_request =
+ DownloadRequestCore::CreateRequestOnIOThread(download_id, params.get());
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle =
+ params->GetBlobDataHandle();
+ if (blob_data_handle) {
+ storage::BlobProtocolHandler::SetRequestedBlobDataHandle(
+ url_request.get(), std::move(blob_data_handle));
}
- for (DownloadUrlParameters::RequestHeadersType::const_iterator iter
- = params->request_headers_begin();
- iter != params->request_headers_end();
- ++iter) {
- request->SetExtraRequestHeaderByName(
- iter->first, iter->second, false /*overwrite*/);
- }
-
- scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo());
- save_info->file_path = params->file_path();
- save_info->suggested_name = params->suggested_name();
- save_info->offset = params->offset();
- save_info->hash_state = params->hash_state();
- save_info->prompt_for_save_location = params->prompt();
- save_info->file = params->GetFile();
-
+ // If there's a valid renderer process associated with the request, then the
+ // request should be driven by the ResourceLoader. Pass it over to the
+ // ResourceDispatcherHostImpl which will in turn pass it along to the
+ // ResourceLoader.
if (params->render_process_host_id() != -1) {
- ResourceDispatcherHost::Get()->BeginDownload(
- std::move(request), params->referrer(), params->content_initiated(),
- params->resource_context(), params->render_process_host_id(),
- params->render_view_host_routing_id(),
- params->render_frame_host_routing_id(), params->prefer_cache(),
- params->do_not_prompt_for_login(), std::move(save_info), download_id,
- params->callback());
+ DownloadInterruptReason reason =
+ ResourceDispatcherHostImpl::Get()->BeginDownload(
+ std::move(url_request), params->referrer(),
+ params->content_initiated(), params->resource_context(),
+ params->render_process_host_id(),
+ params->render_view_host_routing_id(),
+ params->render_frame_host_routing_id(),
+ params->do_not_prompt_for_login());
+
+ // If the download was accepted, the DownloadResourceHandler is now
+ // responsible for driving the request to completion.
+ if (reason == DOWNLOAD_INTERRUPT_REASON_NONE)
+ return nullptr;
+
+ // Otherwise, create an interrupted download.
+ scoped_ptr<DownloadCreateInfo> failed_created_info(
+ new DownloadCreateInfo(base::Time::Now(), net::BoundNetLog(),
+ make_scoped_ptr(new DownloadSaveInfo)));
+ failed_created_info->url_chain.push_back(params->url());
+ failed_created_info->result = reason;
+ scoped_ptr<ByteStreamReader> empty_byte_stream;
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&DownloadManager::StartDownload, download_manager,
+ base::Passed(&failed_created_info),
+ base::Passed(&empty_byte_stream), params->callback()));
return nullptr;
}
+
return scoped_ptr<UrlDownloader, BrowserThread::DeleteOnIOThread>(
- UrlDownloader::BeginDownload(download_manager, std::move(request),
- params->referrer(), params->prefer_cache(),
- std::move(save_info), download_id,
- params->callback())
+ UrlDownloader::BeginDownload(download_manager, std::move(url_request),
+ params->referrer())
.release());
}
@@ -149,6 +113,7 @@ class DownloadItemFactoryImpl : public DownloadItemFactory {
DownloadItemImpl* CreatePersistedItem(
DownloadItemImplDelegate* delegate,
+ const std::string& guid,
uint32_t download_id,
const base::FilePath& current_path,
const base::FilePath& target_path,
@@ -162,31 +127,33 @@ class DownloadItemFactoryImpl : public DownloadItemFactory {
const std::string& last_modified,
int64_t received_bytes,
int64_t total_bytes,
+ const std::string& hash,
DownloadItem::DownloadState state,
DownloadDangerType danger_type,
DownloadInterruptReason interrupt_reason,
bool opened,
const net::BoundNetLog& bound_net_log) override {
- return new DownloadItemImpl(
- delegate,
- download_id,
- current_path,
- target_path,
- url_chain,
- referrer_url,
- mime_type,
- original_mime_type,
- start_time,
- end_time,
- etag,
- last_modified,
- received_bytes,
- total_bytes,
- state,
- danger_type,
- interrupt_reason,
- opened,
- bound_net_log);
+ return new DownloadItemImpl(delegate,
+ guid,
+ download_id,
+ current_path,
+ target_path,
+ url_chain,
+ referrer_url,
+ mime_type,
+ original_mime_type,
+ start_time,
+ end_time,
+ etag,
+ last_modified,
+ received_bytes,
+ total_bytes,
+ hash,
+ state,
+ danger_type,
+ interrupt_reason,
+ opened,
+ bound_net_log);
}
DownloadItemImpl* CreateActiveItem(
@@ -240,6 +207,7 @@ DownloadItemImpl* DownloadManagerImpl::CreateActiveItem(
DownloadItemImpl* download =
item_factory_->CreateActiveItem(this, id, info, bound_net_log);
downloads_[id] = download;
+ downloads_by_guid_[download->GetGuid()] = download;
return download;
}
@@ -322,13 +290,13 @@ void DownloadManagerImpl::Shutdown() {
// dangerous downloads which will remain in history if they aren't explicitly
// accepted or discarded. Canceling will remove the intermediate download
// file.
- for (DownloadMap::iterator it = downloads_.begin(); it != downloads_.end();
- ++it) {
- DownloadItemImpl* download = it->second;
+ for (const auto& it : downloads_) {
+ DownloadItemImpl* download = it.second;
if (download->GetState() == DownloadItem::IN_PROGRESS)
download->Cancel(false);
}
STLDeleteValues(&downloads_);
+ downloads_by_guid_.clear();
url_downloaders_.clear();
// We'll have nothing more to report to the observers after this point.
@@ -345,6 +313,11 @@ void DownloadManagerImpl::StartDownload(
const DownloadUrlParameters::OnStartedCallback& on_started) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(info);
+ // |stream| is only non-nil if the download request was successful.
+ DCHECK((info->result == DOWNLOAD_INTERRUPT_REASON_NONE && stream.get()) ||
+ (info->result != DOWNLOAD_INTERRUPT_REASON_NONE && !stream.get()));
+ DVLOG(20) << __FUNCTION__ << "()"
+ << " result=" << DownloadInterruptReasonToString(info->result);
uint32_t download_id = info->download_id;
const bool new_download = (download_id == content::DownloadItem::kInvalidId);
base::Callback<void(uint32_t)> got_id(base::Bind(
@@ -380,13 +353,12 @@ void DownloadManagerImpl::StartDownloadWithId(
if (!on_started.is_null())
on_started.Run(NULL, DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
// The ByteStreamReader lives and dies on the FILE thread.
- BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE,
- stream.release());
+ if (info->result == DOWNLOAD_INTERRUPT_REASON_NONE)
+ BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE,
+ stream.release());
return;
}
download = item_iterator->second;
- DCHECK_EQ(download->GetState(), DownloadItem::IN_PROGRESS);
- download->MergeOriginInfoOnResume(*info);
}
base::FilePath default_download_directory;
@@ -397,20 +369,23 @@ void DownloadManagerImpl::StartDownloadWithId(
&default_download_directory, &skip_dir_check);
}
- // Create the download file and start the download.
- scoped_ptr<DownloadFile> download_file(file_factory_->CreateFile(
- std::move(info->save_info), default_download_directory, info->url(),
- info->referrer_url, delegate_ && delegate_->GenerateFileHash(),
- std::move(stream), download->GetBoundNetLog(),
- download->DestinationObserverAsWeakPtr()));
-
- // Attach the client ID identifying the app to the AV system.
- if (download_file.get() && delegate_) {
- download_file->SetClientGuid(
- delegate_->ApplicationClientIdForFileScanning());
+ scoped_ptr<DownloadFile> download_file;
+
+ if (info->result == DOWNLOAD_INTERRUPT_REASON_NONE) {
+ DCHECK(stream.get());
+ download_file.reset(
+ file_factory_->CreateFile(std::move(info->save_info),
+ default_download_directory,
+ std::move(stream),
+ download->GetBoundNetLog(),
+ download->DestinationObserverAsWeakPtr()));
}
+ // It is important to leave info->save_info intact in the case of an interrupt
+ // so that the DownloadItem can salvage what it can out of a failed resumption
+ // attempt.
- download->Start(std::move(download_file), std::move(info->request_handle));
+ download->Start(std::move(download_file), std::move(info->request_handle),
+ *info);
// For interrupted downloads, Start() will transition the state to
// IN_PROGRESS and consumers will be notified via OnDownloadUpdated().
@@ -426,9 +401,8 @@ void DownloadManagerImpl::StartDownloadWithId(
void DownloadManagerImpl::CheckForHistoryFilesRemoval() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- for (DownloadMap::iterator it = downloads_.begin();
- it != downloads_.end(); ++it) {
- DownloadItemImpl* item = it->second;
+ for (const auto& it : downloads_) {
+ DownloadItemImpl* item = it.second;
CheckForFileRemoval(item);
}
}
@@ -487,6 +461,8 @@ void DownloadManagerImpl::CreateSavePackageDownloadItemWithId(
this, id, main_file_path, page_url, mime_type, std::move(request_handle),
bound_net_log);
downloads_[download_item->GetId()] = download_item;
+ DCHECK(!ContainsKey(downloads_by_guid_, download_item->GetGuid()));
+ downloads_by_guid_[download_item->GetGuid()] = download_item;
FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(
this, download_item));
if (!item_created.is_null())
@@ -532,6 +508,8 @@ void DownloadManagerImpl::DownloadRemoved(DownloadItemImpl* download) {
if (!download)
return;
+ downloads_by_guid_.erase(download->GetGuid());
+
uint32_t download_id = download->GetId();
if (downloads_.erase(download_id) == 0)
return;
@@ -556,19 +534,18 @@ void DownloadManagerImpl::RemoveUrlDownloader(UrlDownloader* downloader) {
namespace {
-bool RemoveDownloadBetween(base::Time remove_begin,
- base::Time remove_end,
- const DownloadItemImpl* download_item) {
- return download_item->GetStartTime() >= remove_begin &&
- (remove_end.is_null() || download_item->GetStartTime() < remove_end);
+bool EmptyFilter(const GURL& url) {
+ return true;
}
-bool RemoveDownloadByOriginAndTime(const url::Origin& origin,
- base::Time remove_begin,
- base::Time remove_end,
- const DownloadItemImpl* download_item) {
- return origin.IsSameOriginWith(url::Origin(download_item->GetURL())) &&
- RemoveDownloadBetween(remove_begin, remove_end, download_item);
+bool RemoveDownloadByURLAndTime(
+ const base::Callback<bool(const GURL&)>& url_filter,
+ base::Time remove_begin,
+ base::Time remove_end,
+ const DownloadItemImpl* download_item) {
+ return url_filter.Run(download_item->GetURL()) &&
+ download_item->GetStartTime() >= remove_begin &&
+ (remove_end.is_null() || download_item->GetStartTime() < remove_end);
}
} // namespace
@@ -591,28 +568,21 @@ int DownloadManagerImpl::RemoveDownloads(const DownloadRemover& remover) {
return count;
}
-int DownloadManagerImpl::RemoveDownloadsByOriginAndTime(
- const url::Origin& origin,
+int DownloadManagerImpl::RemoveDownloadsByURLAndTime(
+ const base::Callback<bool(const GURL&)>& url_filter,
base::Time remove_begin,
base::Time remove_end) {
- return RemoveDownloads(base::Bind(&RemoveDownloadByOriginAndTime,
- base::ConstRef(origin), remove_begin,
- remove_end));
-}
-
-int DownloadManagerImpl::RemoveDownloadsBetween(base::Time remove_begin,
- base::Time remove_end) {
- return RemoveDownloads(
- base::Bind(&RemoveDownloadBetween, remove_begin, remove_end));
-}
-
-int DownloadManagerImpl::RemoveDownloads(base::Time remove_begin) {
- return RemoveDownloadsBetween(remove_begin, base::Time());
+ return RemoveDownloads(base::Bind(&RemoveDownloadByURLAndTime,
+ url_filter,
+ remove_begin, remove_end));
}
int DownloadManagerImpl::RemoveAllDownloads() {
+ const base::Callback<bool(const GURL&)> empty_filter =
+ base::Bind(&EmptyFilter);
// The null times make the date range unbounded.
- int num_deleted = RemoveDownloadsBetween(base::Time(), base::Time());
+ int num_deleted = RemoveDownloadsByURLAndTime(
+ empty_filter, base::Time(), base::Time());
RecordClearAllSize(num_deleted);
return num_deleted;
}
@@ -641,6 +611,7 @@ void DownloadManagerImpl::RemoveObserver(Observer* observer) {
}
DownloadItem* DownloadManagerImpl::CreateDownloadItem(
+ const std::string& guid,
uint32_t id,
const base::FilePath& current_path,
const base::FilePath& target_path,
@@ -654,6 +625,7 @@ DownloadItem* DownloadManagerImpl::CreateDownloadItem(
const std::string& last_modified,
int64_t received_bytes,
int64_t total_bytes,
+ const std::string& hash,
DownloadItem::DownloadState state,
DownloadDangerType danger_type,
DownloadInterruptReason interrupt_reason,
@@ -662,8 +634,10 @@ DownloadItem* DownloadManagerImpl::CreateDownloadItem(
NOTREACHED();
return NULL;
}
+ DCHECK(!ContainsKey(downloads_by_guid_, guid));
DownloadItemImpl* item = item_factory_->CreatePersistedItem(
this,
+ guid,
id,
current_path,
target_path,
@@ -677,12 +651,14 @@ DownloadItem* DownloadManagerImpl::CreateDownloadItem(
last_modified,
received_bytes,
total_bytes,
+ hash,
state,
danger_type,
interrupt_reason,
opened,
net::BoundNetLog::Make(net_log_, net::NetLog::SOURCE_DOWNLOAD));
downloads_[id] = item;
+ downloads_by_guid_[guid] = item;
FOR_EACH_OBSERVER(Observer, observers_, OnDownloadCreated(this, item));
DVLOG(20) << __FUNCTION__ << "() download = " << item->DebugString(true);
return item;
@@ -690,9 +666,8 @@ DownloadItem* DownloadManagerImpl::CreateDownloadItem(
int DownloadManagerImpl::InProgressCount() const {
int count = 0;
- for (DownloadMap::const_iterator it = downloads_.begin();
- it != downloads_.end(); ++it) {
- if (it->second->GetState() == DownloadItem::IN_PROGRESS)
+ for (const auto& it : downloads_) {
+ if (it.second->GetState() == DownloadItem::IN_PROGRESS)
++count;
}
return count;
@@ -700,13 +675,12 @@ int DownloadManagerImpl::InProgressCount() const {
int DownloadManagerImpl::NonMaliciousInProgressCount() const {
int count = 0;
- for (DownloadMap::const_iterator it = downloads_.begin();
- it != downloads_.end(); ++it) {
- if (it->second->GetState() == DownloadItem::IN_PROGRESS &&
- it->second->GetDangerType() != DOWNLOAD_DANGER_TYPE_DANGEROUS_URL &&
- it->second->GetDangerType() != DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT &&
- it->second->GetDangerType() != DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST &&
- it->second->GetDangerType() !=
+ for (const auto& it : downloads_) {
+ if (it.second->GetState() == DownloadItem::IN_PROGRESS &&
+ it.second->GetDangerType() != DOWNLOAD_DANGER_TYPE_DANGEROUS_URL &&
+ it.second->GetDangerType() != DOWNLOAD_DANGER_TYPE_DANGEROUS_CONTENT &&
+ it.second->GetDangerType() != DOWNLOAD_DANGER_TYPE_DANGEROUS_HOST &&
+ it.second->GetDangerType() !=
DOWNLOAD_DANGER_TYPE_POTENTIALLY_UNWANTED) {
++count;
}
@@ -715,21 +689,26 @@ int DownloadManagerImpl::NonMaliciousInProgressCount() const {
}
DownloadItem* DownloadManagerImpl::GetDownload(uint32_t download_id) {
- return ContainsKey(downloads_, download_id) ? downloads_[download_id] : NULL;
+ return ContainsKey(downloads_, download_id) ? downloads_[download_id]
+ : nullptr;
+}
+
+DownloadItem* DownloadManagerImpl::GetDownloadByGuid(const std::string& guid) {
+ DCHECK(guid == base::ToUpperASCII(guid));
+ return ContainsKey(downloads_by_guid_, guid) ? downloads_by_guid_[guid]
+ : nullptr;
}
void DownloadManagerImpl::GetAllDownloads(DownloadVector* downloads) {
- for (DownloadMap::iterator it = downloads_.begin();
- it != downloads_.end(); ++it) {
- downloads->push_back(it->second);
+ for (const auto& it : downloads_) {
+ downloads->push_back(it.second);
}
}
void DownloadManagerImpl::OpenDownload(DownloadItemImpl* download) {
int num_unopened = 0;
- for (DownloadMap::iterator it = downloads_.begin();
- it != downloads_.end(); ++it) {
- DownloadItemImpl* item = it->second;
+ for (const auto& it : downloads_) {
+ DownloadItemImpl* item = it.second;
if ((item->GetState() == DownloadItem::COMPLETE) &&
!item->GetOpened())
++num_unopened;
diff --git a/chromium/content/browser/download/download_manager_impl.h b/chromium/content/browser/download/download_manager_impl.h
index ebac07ab081..610b76408fc 100644
--- a/chromium/content/browser/download/download_manager_impl.h
+++ b/chromium/content/browser/download/download_manager_impl.h
@@ -7,13 +7,12 @@
#include <stdint.h>
-#include <map>
#include <set>
#include <string>
+#include <unordered_map>
#include <vector>
#include "base/callback_forward.h"
-#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
@@ -42,7 +41,7 @@ class DownloadRequestHandleInterface;
class CONTENT_EXPORT DownloadManagerImpl : public DownloadManager,
private DownloadItemImplDelegate {
public:
- typedef base::Callback<void(DownloadItemImpl*)> DownloadItemImplCreated;
+ using DownloadItemImplCreated = base::Callback<void(DownloadItemImpl*)>;
// Caller guarantees that |net_log| will remain valid
// for the lifetime of DownloadManagerImpl (until Shutdown() is called).
@@ -74,17 +73,16 @@ class CONTENT_EXPORT DownloadManagerImpl : public DownloadManager,
scoped_ptr<ByteStreamReader> stream,
const DownloadUrlParameters::OnStartedCallback& on_started) override;
- int RemoveDownloadsByOriginAndTime(const url::Origin& origin,
- base::Time remove_begin,
- base::Time remove_end) override;
- int RemoveDownloadsBetween(base::Time remove_begin,
- base::Time remove_end) override;
- int RemoveDownloads(base::Time remove_begin) override;
+ int RemoveDownloadsByURLAndTime(
+ const base::Callback<bool(const GURL&)>& url_filter,
+ base::Time remove_begin,
+ base::Time remove_end) override;
int RemoveAllDownloads() override;
void DownloadUrl(scoped_ptr<DownloadUrlParameters> params) override;
void AddObserver(Observer* observer) override;
void RemoveObserver(Observer* observer) override;
content::DownloadItem* CreateDownloadItem(
+ const std::string& guid,
uint32_t id,
const base::FilePath& current_path,
const base::FilePath& target_path,
@@ -98,6 +96,7 @@ class CONTENT_EXPORT DownloadManagerImpl : public DownloadManager,
const std::string& last_modified,
int64_t received_bytes,
int64_t total_bytes,
+ const std::string& hash,
content::DownloadItem::DownloadState state,
DownloadDangerType danger_type,
DownloadInterruptReason interrupt_reason,
@@ -107,6 +106,7 @@ class CONTENT_EXPORT DownloadManagerImpl : public DownloadManager,
BrowserContext* GetBrowserContext() const override;
void CheckForHistoryFilesRemoval() override;
DownloadItem* GetDownload(uint32_t id) override;
+ DownloadItem* GetDownloadByGuid(const std::string& guid) override;
// For testing; specifically, accessed from TestFileErrorInjector.
void SetDownloadItemFactoryForTesting(
@@ -118,10 +118,11 @@ class CONTENT_EXPORT DownloadManagerImpl : public DownloadManager,
void RemoveUrlDownloader(UrlDownloader* downloader);
private:
- typedef std::set<DownloadItem*> DownloadSet;
- typedef base::hash_map<uint32_t, DownloadItemImpl*> DownloadMap;
- typedef std::vector<DownloadItemImpl*> DownloadItemImplVector;
- typedef base::Callback<bool(const DownloadItemImpl*)> DownloadRemover;
+ using DownloadSet = std::set<DownloadItem*>;
+ using DownloadMap = std::unordered_map<uint32_t, DownloadItemImpl*>;
+ using DownloadGuidMap = std::unordered_map<std::string, DownloadItemImpl*>;
+ using DownloadItemImplVector = std::vector<DownloadItemImpl*>;
+ using DownloadRemover = base::Callback<bool(const DownloadItemImpl*)>;
// For testing.
friend class DownloadManagerTest;
@@ -189,8 +190,16 @@ class CONTENT_EXPORT DownloadManagerImpl : public DownloadManager,
// DownloadManager. This includes downloads started by the user in
// this session, downloads initialized from the history system, and
// "save page as" downloads.
+ // TODO(asanka): Remove this container in favor of downloads_by_guid_ as a
+ // part of http://crbug.com/593020.
DownloadMap downloads_;
+ // Same as the above, but maps from GUID to download item. Note that the
+ // container is case sensitive. Hence the key needs to be normalized to
+ // upper-case when inserting new elements here. Fortunately for us,
+ // DownloadItemImpl already normalizes the string GUID.
+ DownloadGuidMap downloads_by_guid_;
+
int history_size_;
// True if the download manager has been initialized and requires a shutdown.
diff --git a/chromium/content/browser/download/download_manager_impl_unittest.cc b/chromium/content/browser/download/download_manager_impl_unittest.cc
index 78d13863470..c72a1d07a82 100644
--- a/chromium/content/browser/download/download_manager_impl_unittest.cc
+++ b/chromium/content/browser/download/download_manager_impl_unittest.cc
@@ -6,12 +6,14 @@
#include <stddef.h>
#include <stdint.h>
+
#include <set>
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/files/scoped_temp_dir.h"
+#include "base/guid.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
@@ -37,7 +39,6 @@
#include "content/public/test/mock_download_item.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread.h"
-#include "net/base/net_util.h"
#include "net/log/net_log.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gmock_mutant.h"
@@ -50,6 +51,7 @@ using ::testing::Eq;
using ::testing::Ref;
using ::testing::Return;
using ::testing::ReturnRef;
+using ::testing::ReturnRefOfCopy;
using ::testing::SetArgPointee;
using ::testing::StrictMock;
using ::testing::_;
@@ -76,26 +78,27 @@ class MockDownloadItemImpl : public DownloadItemImpl {
public:
// Use history constructor for minimal base object.
explicit MockDownloadItemImpl(DownloadItemImplDelegate* delegate)
- : DownloadItemImpl(
- delegate,
- content::DownloadItem::kInvalidId,
- base::FilePath(),
- base::FilePath(),
- std::vector<GURL>(),
- GURL(),
- "application/octet-stream",
- "application/octet-stream",
- base::Time(),
- base::Time(),
- std::string(),
- std::string(),
- 0,
- 0,
- DownloadItem::COMPLETE,
- DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
- DOWNLOAD_INTERRUPT_REASON_NONE,
- false,
- net::BoundNetLog()) {}
+ : DownloadItemImpl(delegate,
+ std::string("7d122682-55b5-4a47-a253-36cadc3e5bee"),
+ content::DownloadItem::kInvalidId,
+ base::FilePath(),
+ base::FilePath(),
+ std::vector<GURL>(),
+ GURL(),
+ "application/octet-stream",
+ "application/octet-stream",
+ base::Time(),
+ base::Time(),
+ std::string(),
+ std::string(),
+ 0,
+ 0,
+ std::string(),
+ DownloadItem::COMPLETE,
+ DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+ DOWNLOAD_INTERRUPT_REASON_NONE,
+ false,
+ net::BoundNetLog()) {}
virtual ~MockDownloadItemImpl() {}
MOCK_METHOD4(OnDownloadTargetDetermined,
@@ -114,10 +117,13 @@ class MockDownloadItemImpl : public DownloadItemImpl {
MOCK_METHOD3(UpdateProgress, void(int64_t, int64_t, const std::string&));
MOCK_METHOD1(Cancel, void(bool));
MOCK_METHOD0(MarkAsComplete, void());
- MOCK_METHOD1(OnAllDataSaved, void(const std::string&));
+ void OnAllDataSaved(int64_t, scoped_ptr<crypto::SecureHash>) override {
+ NOTREACHED();
+ }
MOCK_METHOD0(OnDownloadedFileRemoved, void());
void Start(scoped_ptr<DownloadFile> download_file,
- scoped_ptr<DownloadRequestHandleInterface> req_handle) override {
+ scoped_ptr<DownloadRequestHandleInterface> req_handle,
+ const DownloadCreateInfo& create_info) override {
MockStart(download_file.get(), req_handle.get());
}
@@ -153,6 +159,7 @@ class MockDownloadItemImpl : public DownloadItemImpl {
MOCK_CONST_METHOD0(GetHashState, const std::string&());
MOCK_CONST_METHOD0(GetHash, const std::string&());
MOCK_CONST_METHOD0(GetId, uint32_t());
+ MOCK_CONST_METHOD0(GetGuid, const std::string&());
MOCK_CONST_METHOD0(GetStartTime, base::Time());
MOCK_CONST_METHOD0(GetEndTime, base::Time());
MOCK_METHOD0(GetDownloadManager, DownloadManager*());
@@ -199,7 +206,6 @@ class MockDownloadManagerDelegate : public DownloadManagerDelegate {
bool(DownloadItem*, const base::Closure&));
MOCK_METHOD2(ShouldOpenDownload,
bool(DownloadItem*, const DownloadOpenDelayedCallback&));
- MOCK_METHOD0(GenerateFileHash, bool());
MOCK_METHOD4(GetSaveDir, void(BrowserContext*,
base::FilePath*, base::FilePath*, bool*));
MOCK_METHOD5(ChooseSavePath, void(
@@ -237,6 +243,7 @@ class MockDownloadItemFactory
// Overridden methods from DownloadItemFactory.
DownloadItemImpl* CreatePersistedItem(
DownloadItemImplDelegate* delegate,
+ const std::string& guid,
uint32_t download_id,
const base::FilePath& current_path,
const base::FilePath& target_path,
@@ -250,6 +257,7 @@ class MockDownloadItemFactory
const std::string& last_modofied,
int64_t received_bytes,
int64_t total_bytes,
+ const std::string& hash,
DownloadItem::DownloadState state,
DownloadDangerType danger_type,
DownloadInterruptReason interrupt_reason,
@@ -304,6 +312,7 @@ void MockDownloadItemFactory::RemoveItem(int id) {
DownloadItemImpl* MockDownloadItemFactory::CreatePersistedItem(
DownloadItemImplDelegate* delegate,
+ const std::string& guid,
uint32_t download_id,
const base::FilePath& current_path,
const base::FilePath& target_path,
@@ -317,6 +326,7 @@ DownloadItemImpl* MockDownloadItemFactory::CreatePersistedItem(
const std::string& last_modified,
int64_t received_bytes,
int64_t total_bytes,
+ const std::string& hash,
DownloadItem::DownloadState state,
DownloadDangerType danger_type,
DownloadInterruptReason interrupt_reason,
@@ -327,6 +337,7 @@ DownloadItemImpl* MockDownloadItemFactory::CreatePersistedItem(
new StrictMock<MockDownloadItemImpl>(&item_delegate_);
EXPECT_CALL(*result, GetId())
.WillRepeatedly(Return(download_id));
+ EXPECT_CALL(*result, GetGuid()).WillRepeatedly(ReturnRefOfCopy(guid));
items_[download_id] = result;
return result;
}
@@ -342,6 +353,9 @@ DownloadItemImpl* MockDownloadItemFactory::CreateActiveItem(
new StrictMock<MockDownloadItemImpl>(&item_delegate_);
EXPECT_CALL(*result, GetId())
.WillRepeatedly(Return(download_id));
+ EXPECT_CALL(*result, GetGuid())
+ .WillRepeatedly(
+ ReturnRefOfCopy(base::ToUpperASCII(base::GenerateGUID())));
items_[download_id] = result;
// Active items are created and then immediately are called to start
@@ -378,32 +392,24 @@ class MockDownloadFileFactory
virtual ~MockDownloadFileFactory() {}
// Overridden method from DownloadFileFactory
- MOCK_METHOD8(MockCreateFile, MockDownloadFile*(
- const DownloadSaveInfo&,
- const base::FilePath&,
- const GURL&, const GURL&, bool,
- ByteStreamReader*,
- const net::BoundNetLog&,
- base::WeakPtr<DownloadDestinationObserver>));
+ MOCK_METHOD2(MockCreateFile,
+ MockDownloadFile*(const DownloadSaveInfo&, ByteStreamReader*));
virtual DownloadFile* CreateFile(
scoped_ptr<DownloadSaveInfo> save_info,
const base::FilePath& default_download_directory,
- const GURL& url,
- const GURL& referrer_url,
- bool calculate_hash,
- scoped_ptr<ByteStreamReader> stream,
+ scoped_ptr<ByteStreamReader> byte_stream,
const net::BoundNetLog& bound_net_log,
- base::WeakPtr<DownloadDestinationObserver> observer) {
- return MockCreateFile(*save_info.get(), default_download_directory, url,
- referrer_url, calculate_hash,
- stream.get(), bound_net_log, observer);
+ base::WeakPtr<DownloadDestinationObserver> observer) override {
+ return MockCreateFile(*save_info, byte_stream.get());
}
};
class MockBrowserContext : public BrowserContext {
public:
- MockBrowserContext() {}
+ MockBrowserContext() {
+ content::BrowserContext::Initialize(this, base::FilePath());
+ }
~MockBrowserContext() {}
MOCK_CONST_METHOD0(GetPath, base::FilePath());
@@ -411,8 +417,6 @@ class MockBrowserContext : public BrowserContext {
ZoomLevelDelegate*(const base::FilePath&));
MOCK_CONST_METHOD0(IsOffTheRecord, bool());
MOCK_METHOD0(GetRequestContext, net::URLRequestContextGetter*());
- MOCK_METHOD1(GetRequestContextForRenderProcess,
- net::URLRequestContextGetter*(int renderer_child_id));
MOCK_METHOD0(GetMediaRequestContext,
net::URLRequestContextGetter*());
MOCK_METHOD1(GetMediaRequestContextForRenderProcess,
@@ -429,6 +433,23 @@ class MockBrowserContext : public BrowserContext {
MOCK_METHOD0(GetPermissionManager, PermissionManager*());
MOCK_METHOD0(GetBackgroundSyncController, BackgroundSyncController*());
+ // Define these two methods to avoid a
+ // cannot access private member declared in class 'ScopedVector<net::URLRequestInterceptor>'
+ // build error if they're put in MOCK_METHOD.
+ net::URLRequestContextGetter* CreateRequestContext(
+ ProtocolHandlerMap* protocol_handlers,
+ URLRequestInterceptorScopedVector request_interceptors) override {
+ return nullptr;
+ }
+
+ net::URLRequestContextGetter* CreateRequestContextForStoragePartition(
+ const base::FilePath& partition_path,
+ bool in_memory,
+ ProtocolHandlerMap* protocol_handlers,
+ URLRequestInterceptorScopedVector request_interceptors) override {
+ return nullptr;
+ }
+
scoped_ptr<ZoomLevelDelegate> CreateZoomLevelDelegate(
const base::FilePath& path) override {
return scoped_ptr<ZoomLevelDelegate>(CreateZoomLevelDelegateMock(path));
@@ -445,6 +466,14 @@ class MockDownloadManagerObserver : public DownloadManager::Observer {
MOCK_METHOD2(SelectFileDialogDisplayed, void(DownloadManager*, int32_t));
};
+class MockByteStreamReader : public ByteStreamReader {
+ public:
+ virtual ~MockByteStreamReader() {}
+ MOCK_METHOD2(Read, StreamState(scoped_refptr<net::IOBuffer>*, size_t*));
+ MOCK_CONST_METHOD0(GetStatus, int());
+ MOCK_METHOD1(RegisterCallback, void(const base::Closure&));
+};
+
} // namespace
class DownloadManagerTest : public testing::Test {
@@ -529,7 +558,7 @@ class DownloadManagerTest : public testing::Test {
// we call Start on it immediately, so we need to set that expectation
// in the factory.
scoped_ptr<DownloadRequestHandleInterface> req_handle;
- item.Start(scoped_ptr<DownloadFile>(), std::move(req_handle));
+ item.Start(scoped_ptr<DownloadFile>(), std::move(req_handle), info);
DCHECK(id < download_urls_.size());
EXPECT_CALL(item, GetURL()).WillRepeatedly(ReturnRef(download_urls_[id]));
@@ -605,7 +634,7 @@ class DownloadManagerTest : public testing::Test {
// Confirm the appropriate invocations occur when you start a download.
TEST_F(DownloadManagerTest, StartDownload) {
scoped_ptr<DownloadCreateInfo> info(new DownloadCreateInfo);
- scoped_ptr<ByteStreamReader> stream;
+ scoped_ptr<ByteStreamReader> stream(new MockByteStreamReader);
uint32_t local_id(5); // Random value
base::FilePath download_path(FILE_PATH_LITERAL("download/path"));
@@ -618,16 +647,12 @@ TEST_F(DownloadManagerTest, StartDownload) {
// Doing nothing will set the default download directory to null.
EXPECT_CALL(GetMockDownloadManagerDelegate(), GetSaveDir(_, _, _, _));
- EXPECT_CALL(GetMockDownloadManagerDelegate(), GenerateFileHash())
- .WillOnce(Return(true));
EXPECT_CALL(GetMockDownloadManagerDelegate(),
ApplicationClientIdForFileScanning())
.WillRepeatedly(Return("client-id"));
MockDownloadFile* mock_file = new MockDownloadFile;
- EXPECT_CALL(*mock_file, SetClientGuid("client-id"));
EXPECT_CALL(*mock_download_file_factory_.get(),
- MockCreateFile(Ref(*info->save_info.get()), _, _, _, true,
- stream.get(), _, _))
+ MockCreateFile(Ref(*info->save_info.get()), stream.get()))
.WillOnce(Return(mock_file));
download_manager_->StartDownload(std::move(info), std::move(stream),
@@ -707,8 +732,53 @@ TEST_F(DownloadManagerTest, RemoveAllDownloads) {
// result in them being removed from the DownloadManager list.
}
-// Confirm that only downloads with same origin are removed.
-TEST_F(DownloadManagerTest, RemoveSameOriginDownloads) {
+TEST_F(DownloadManagerTest, GetDownloadByGuid) {
+ for (uint32_t i = 0; i < 4; ++i)
+ AddItemToManager();
+
+ MockDownloadItemImpl& item = GetMockDownloadItem(0);
+ DownloadItem* result = download_manager_->GetDownloadByGuid(item.GetGuid());
+ ASSERT_TRUE(result);
+ ASSERT_EQ(static_cast<DownloadItem*>(&item), result);
+
+ ASSERT_FALSE(download_manager_->GetDownloadByGuid(""));
+
+ const char kGuid[] = "8DF158E8-C980-4618-BB03-EBA3242EB48B";
+ DownloadItem* persisted_item = download_manager_->CreateDownloadItem(
+ kGuid,
+ 10,
+ base::FilePath(),
+ base::FilePath(),
+ std::vector<GURL>(),
+ GURL("http://example.com/a"),
+ "application/octet-stream",
+ "application/octet-stream",
+ base::Time::Now(),
+ base::Time::Now(),
+ std::string(),
+ std::string(),
+ 10,
+ 10,
+ std::string(),
+ DownloadItem::INTERRUPTED,
+ DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
+ DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED,
+ false);
+ ASSERT_TRUE(persisted_item);
+
+ ASSERT_EQ(persisted_item, download_manager_->GetDownloadByGuid(kGuid));
+}
+
+namespace {
+
+base::Callback<bool(const GURL&)> GetSingleURLFilter(const GURL& url) {
+ return base::Bind(&GURL::operator==, base::Owned(new GURL(url)));
+}
+
+} // namespace
+
+// Confirm that only downloads with the specified URL are removed.
+TEST_F(DownloadManagerTest, RemoveDownloadsByURL) {
base::Time now(base::Time::Now());
for (uint32_t i = 0; i < 2; ++i) {
MockDownloadItemImpl& item(AddItemToManager());
@@ -720,9 +790,10 @@ TEST_F(DownloadManagerTest, RemoveSameOriginDownloads) {
EXPECT_CALL(GetMockDownloadItem(0), Remove());
EXPECT_CALL(GetMockDownloadItem(1), Remove()).Times(0);
- url::Origin origin_to_clear(download_urls_[0]);
- int remove_count = download_manager_->RemoveDownloadsByOriginAndTime(
- origin_to_clear, base::Time(), base::Time::Max());
+ base::Callback<bool(const GURL&)> url_filter =
+ GetSingleURLFilter(download_urls_[0]);
+ int remove_count = download_manager_->RemoveDownloadsByURLAndTime(
+ url_filter, base::Time(), base::Time::Max());
EXPECT_EQ(remove_count, 1);
}
diff --git a/chromium/content/browser/download/download_net_log_parameters.cc b/chromium/content/browser/download/download_net_log_parameters.cc
index e81c813af2f..110bc98c3b0 100644
--- a/chromium/content/browser/download/download_net_log_parameters.cc
+++ b/chromium/content/browser/download/download_net_log_parameters.cc
@@ -89,14 +89,11 @@ scoped_ptr<base::Value> ItemRenamedNetLogCallback(
scoped_ptr<base::Value> ItemInterruptedNetLogCallback(
DownloadInterruptReason reason,
int64_t bytes_so_far,
- const std::string* hash_state,
net::NetLogCaptureMode capture_mode) {
scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
dict->SetString("interrupt_reason", DownloadInterruptReasonToString(reason));
dict->SetString("bytes_so_far", base::Int64ToString(bytes_so_far));
- dict->SetString("hash_state",
- base::HexEncode(hash_state->data(), hash_state->size()));
return std::move(dict);
}
@@ -105,15 +102,12 @@ scoped_ptr<base::Value> ItemResumingNetLogCallback(
bool user_initiated,
DownloadInterruptReason reason,
int64_t bytes_so_far,
- const std::string* hash_state,
net::NetLogCaptureMode capture_mode) {
scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
dict->SetString("user_initiated", user_initiated ? "true" : "false");
dict->SetString("interrupt_reason", DownloadInterruptReasonToString(reason));
dict->SetString("bytes_so_far", base::Int64ToString(bytes_so_far));
- dict->SetString("hash_state",
- base::HexEncode(hash_state->data(), hash_state->size()));
return std::move(dict);
}
@@ -143,13 +137,10 @@ scoped_ptr<base::Value> ItemFinishedNetLogCallback(
scoped_ptr<base::Value> ItemCanceledNetLogCallback(
int64_t bytes_so_far,
- const std::string* hash_state,
net::NetLogCaptureMode capture_mode) {
scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
dict->SetString("bytes_so_far", base::Int64ToString(bytes_so_far));
- dict->SetString("hash_state",
- base::HexEncode(hash_state->data(), hash_state->size()));
return std::move(dict);
}
diff --git a/chromium/content/browser/download/download_net_log_parameters.h b/chromium/content/browser/download/download_net_log_parameters.h
index 2f4b6a006e5..b10a345ed33 100644
--- a/chromium/content/browser/download/download_net_log_parameters.h
+++ b/chromium/content/browser/download/download_net_log_parameters.h
@@ -50,7 +50,6 @@ scoped_ptr<base::Value> ItemRenamedNetLogCallback(
scoped_ptr<base::Value> ItemInterruptedNetLogCallback(
DownloadInterruptReason reason,
int64_t bytes_so_far,
- const std::string* hash_state,
net::NetLogCaptureMode capture_mode);
// Returns NetLog parameters when a DownloadItem is resumed.
@@ -58,7 +57,6 @@ scoped_ptr<base::Value> ItemResumingNetLogCallback(
bool user_initiated,
DownloadInterruptReason reason,
int64_t bytes_so_far,
- const std::string* hash_state,
net::NetLogCaptureMode capture_mode);
// Returns NetLog parameters when a DownloadItem is completing.
@@ -75,7 +73,6 @@ scoped_ptr<base::Value> ItemFinishedNetLogCallback(
// Returns NetLog parameters when a DownloadItem is canceled.
scoped_ptr<base::Value> ItemCanceledNetLogCallback(
int64_t bytes_so_far,
- const std::string* hash_state,
net::NetLogCaptureMode capture_mode);
// Returns NetLog parameters when a DownloadFile is opened.
diff --git a/chromium/content/browser/download/download_request_core.cc b/chromium/content/browser/download/download_request_core.cc
index 072ba7b0b55..3f70e956baa 100644
--- a/chromium/content/browser/download/download_request_core.cc
+++ b/chromium/content/browser/download/download_request_core.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/format_macros.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
@@ -21,41 +22,197 @@
#include "content/browser/download/download_manager_impl.h"
#include "content/browser/download/download_request_handle.h"
#include "content/browser/download/download_stats.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/download_interrupt_reasons.h"
#include "content/public/browser/download_item.h"
#include "content/public/browser/download_manager_delegate.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/power_save_blocker.h"
+#include "content/public/browser/resource_context.h"
#include "content/public/browser/web_contents.h"
+#include "net/base/elements_upload_data_stream.h"
#include "net/base/io_buffer.h"
+#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
+#include "net/base/upload_bytes_element_reader.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
#include "net/url_request/url_request_context.h"
namespace content {
+namespace {
+
+// This is a UserData::Data that will be attached to a URLRequest as a
+// side-channel for passing download parameters.
+class DownloadRequestData : public base::SupportsUserData::Data {
+ public:
+ ~DownloadRequestData() override {}
+
+ static void Attach(net::URLRequest* request,
+ DownloadUrlParameters* download_parameters,
+ uint32_t download_id);
+ static DownloadRequestData* Get(net::URLRequest* request);
+ static void Detach(net::URLRequest* request);
+
+ scoped_ptr<DownloadSaveInfo> TakeSaveInfo() { return std::move(save_info_); }
+ uint32_t download_id() const { return download_id_; }
+ const DownloadUrlParameters::OnStartedCallback& callback() const {
+ return on_started_callback_;
+ }
+
+ private:
+ static const int kKey;
+
+ scoped_ptr<DownloadSaveInfo> save_info_;
+ uint32_t download_id_ = DownloadItem::kInvalidId;
+ DownloadUrlParameters::OnStartedCallback on_started_callback_;
+};
+
+// static
+const int DownloadRequestData::kKey = 0;
+
+// static
+void DownloadRequestData::Attach(net::URLRequest* request,
+ DownloadUrlParameters* parameters,
+ uint32_t download_id) {
+ DownloadRequestData* request_data = new DownloadRequestData;
+ request_data->save_info_.reset(
+ new DownloadSaveInfo(parameters->GetSaveInfo()));
+ request_data->download_id_ = download_id;
+ request_data->on_started_callback_ = parameters->callback();
+ request->SetUserData(&kKey, request_data);
+}
+
+// static
+DownloadRequestData* DownloadRequestData::Get(net::URLRequest* request) {
+ return static_cast<DownloadRequestData*>(request->GetUserData(&kKey));
+}
+
+// static
+void DownloadRequestData::Detach(net::URLRequest* request) {
+ request->RemoveUserData(&kKey);
+}
+
+} // namespace
+
const int DownloadRequestCore::kDownloadByteStreamSize = 100 * 1024;
-DownloadRequestCore::DownloadRequestCore(
- net::URLRequest* request,
- scoped_ptr<DownloadSaveInfo> save_info,
- const base::Closure& on_ready_to_read_callback)
- : on_ready_to_read_callback_(on_ready_to_read_callback),
+// static
+scoped_ptr<net::URLRequest> DownloadRequestCore::CreateRequestOnIOThread(
+ uint32_t download_id,
+ DownloadUrlParameters* params) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(download_id == DownloadItem::kInvalidId ||
+ !params->content_initiated())
+ << "Content initiated downloads shouldn't specify a download ID";
+
+ // ResourceDispatcherHost{Base} is-not-a URLRequest::Delegate, and
+ // DownloadUrlParameters can-not include resource_dispatcher_host_impl.h, so
+ // we must down cast. RDHI is the only subclass of RDH as of 2012 May 4.
+ scoped_ptr<net::URLRequest> request(
+ params->resource_context()->GetRequestContext()->CreateRequest(
+ params->url(), net::DEFAULT_PRIORITY, nullptr));
+ request->set_method(params->method());
+
+ if (!params->post_body().empty()) {
+ const std::string& body = params->post_body();
+ scoped_ptr<net::UploadElementReader> reader(
+ net::UploadOwnedBytesElementReader::CreateWithString(body));
+ request->set_upload(
+ net::ElementsUploadDataStream::CreateWithReader(std::move(reader), 0));
+ }
+
+ if (params->post_id() >= 0) {
+ // The POST in this case does not have an actual body, and only works
+ // when retrieving data from cache. This is done because we don't want
+ // to do a re-POST without user consent, and currently don't have a good
+ // plan on how to display the UI for that.
+ DCHECK(params->prefer_cache());
+ DCHECK_EQ("POST", params->method());
+ std::vector<scoped_ptr<net::UploadElementReader>> element_readers;
+ request->set_upload(make_scoped_ptr(new net::ElementsUploadDataStream(
+ std::move(element_readers), params->post_id())));
+ }
+
+ int load_flags = request->load_flags();
+ if (params->prefer_cache()) {
+ // If there is upload data attached, only retrieve from cache because there
+ // is no current mechanism to prompt the user for their consent for a
+ // re-post. For GETs, try to retrieve data from the cache and skip
+ // validating the entry if present.
+ if (request->get_upload())
+ load_flags |= net::LOAD_ONLY_FROM_CACHE;
+ else
+ load_flags |= net::LOAD_PREFERRING_CACHE;
+ } else {
+ load_flags |= net::LOAD_DISABLE_CACHE;
+ }
+ request->SetLoadFlags(load_flags);
+
+ bool has_last_modified = !params->last_modified().empty();
+ bool has_etag = !params->etag().empty();
+
+ // If we've asked for a range, we want to make sure that we only get that
+ // range if our current copy of the information is good. We shouldn't be
+ // asked to continue if we don't have a verifier.
+ DCHECK(params->offset() == 0 || has_etag || has_last_modified);
+
+ // If we're not at the beginning of the file, retrieve only the remaining
+ // portion.
+ if (params->offset() > 0 && (has_etag || has_last_modified)) {
+ request->SetExtraRequestHeaderByName(
+ "Range", base::StringPrintf("bytes=%" PRId64 "-", params->offset()),
+ true);
+
+ // In accordance with RFC 2616 Section 14.27, use If-Range to specify that
+ // the server return the entire entity if the validator doesn't match.
+ // Last-Modified can be used in the absence of ETag as a validator if the
+ // response headers satisfied the HttpUtil::HasStrongValidators() predicate.
+ //
+ // This function assumes that HasStrongValidators() was true and that the
+ // ETag and Last-Modified header values supplied are valid.
+ request->SetExtraRequestHeaderByName(
+ "If-Range", has_etag ? params->etag() : params->last_modified(), true);
+ }
+
+ for (const auto& header : params->request_headers())
+ request->SetExtraRequestHeaderByName(header.first, header.second,
+ false /*overwrite*/);
+
+ DownloadRequestData::Attach(request.get(), std::move(params), download_id);
+ return request;
+}
+
+DownloadRequestCore::DownloadRequestCore(net::URLRequest* request,
+ Delegate* delegate)
+ : delegate_(delegate),
request_(request),
- save_info_(std::move(save_info)),
+ download_id_(DownloadItem::kInvalidId),
last_buffer_size_(0),
bytes_read_(0),
pause_count_(0),
- was_deferred_(false) {
+ was_deferred_(false),
+ is_partial_request_(false),
+ started_(false),
+ abort_reason_(DOWNLOAD_INTERRUPT_REASON_NONE) {
DCHECK(request_);
- DCHECK(save_info_);
- DCHECK(!on_ready_to_read_callback_.is_null());
+ DCHECK(delegate_);
RecordDownloadCount(UNTHROTTLED_COUNT);
power_save_blocker_ = PowerSaveBlocker::Create(
PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension,
PowerSaveBlocker::kReasonOther, "Download in progress");
+ DownloadRequestData* request_data = DownloadRequestData::Get(request_);
+ if (request_data) {
+ save_info_ = request_data->TakeSaveInfo();
+ download_id_ = request_data->download_id();
+ on_started_callback_ = request_data->callback();
+ DownloadRequestData::Detach(request_);
+ is_partial_request_ = save_info_->offset > 0;
+ } else {
+ save_info_.reset(new DownloadSaveInfo);
+ }
}
DownloadRequestCore::~DownloadRequestCore() {
@@ -68,15 +225,41 @@ DownloadRequestCore::~DownloadRequestCore() {
base::TimeTicks::Now() - download_start_time_);
}
-// Send the download creation information to the download thread.
-void DownloadRequestCore::OnResponseStarted(
- scoped_ptr<DownloadCreateInfo>* create_info,
- scoped_ptr<ByteStreamReader>* stream_reader) {
+scoped_ptr<DownloadCreateInfo> DownloadRequestCore::CreateDownloadCreateInfo(
+ DownloadInterruptReason result) {
+ DCHECK(!started_);
+ started_ = true;
+ scoped_ptr<DownloadCreateInfo> create_info(new DownloadCreateInfo(
+ base::Time::Now(), request()->net_log(), std::move(save_info_)));
+
+ if (result == DOWNLOAD_INTERRUPT_REASON_NONE)
+ create_info->remote_address = request()->GetSocketAddress().host();
+ create_info->url_chain = request()->url_chain();
+ create_info->referrer_url = GURL(request()->referrer());
+ create_info->result = result;
+ create_info->download_id = download_id_;
+ return create_info;
+}
+
+bool DownloadRequestCore::OnResponseStarted(
+ const std::string& override_mime_type) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(save_info_);
DVLOG(20) << __FUNCTION__ << "()" << DebugString();
download_start_time_ = base::TimeTicks::Now();
+ DownloadInterruptReason result =
+ request()->response_headers()
+ ? HandleSuccessfulServerResponse(*request()->response_headers(),
+ save_info_.get())
+ : DOWNLOAD_INTERRUPT_REASON_NONE;
+
+ scoped_ptr<DownloadCreateInfo> create_info = CreateDownloadCreateInfo(result);
+ if (result != DOWNLOAD_INTERRUPT_REASON_NONE) {
+ delegate_->OnStart(std::move(create_info), scoped_ptr<ByteStreamReader>(),
+ base::ResetAndReturn(&on_started_callback_));
+ return false;
+ }
+
// If it's a download, we don't want to poison the cache with it.
request()->StopCaching();
@@ -90,35 +273,21 @@ void DownloadRequestCore::OnResponseStarted(
int64_t content_length = request()->GetExpectedContentSize() > 0
? request()->GetExpectedContentSize()
: 0;
-
- // Deleted in DownloadManager.
- scoped_ptr<DownloadCreateInfo> info(
- new DownloadCreateInfo(base::Time::Now(), content_length,
- request()->net_log(), std::move(save_info_)));
+ create_info->total_bytes = content_length;
// Create the ByteStream for sending data to the download sink.
+ scoped_ptr<ByteStreamReader> stream_reader;
CreateByteStream(
base::ThreadTaskRunnerHandle::Get(),
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
- kDownloadByteStreamSize, &stream_writer_, stream_reader);
+ kDownloadByteStreamSize, &stream_writer_, &stream_reader);
stream_writer_->RegisterCallback(
base::Bind(&DownloadRequestCore::ResumeRequest, AsWeakPtr()));
- info->url_chain = request()->url_chain();
- info->referrer_url = GURL(request()->referrer());
- string mime_type;
- request()->GetMimeType(&mime_type);
- info->mime_type = mime_type;
- info->remote_address = request()->GetSocketAddress().host();
- if (request()->response_headers()) {
- // Grab the first content-disposition header. There may be more than one,
- // though as of this writing, the network stack ensures if there are, they
- // are all duplicates.
- request()->response_headers()->EnumerateHeader(
- nullptr, "Content-Disposition", &info->content_disposition);
- }
- RecordDownloadMimeType(info->mime_type);
- RecordDownloadContentDisposition(info->content_disposition);
+ if (!override_mime_type.empty())
+ create_info->mime_type = override_mime_type;
+ else
+ request()->GetMimeType(&create_info->mime_type);
// Get the last modified time and etag.
const net::HttpResponseHeaders* headers = request()->response_headers();
@@ -127,33 +296,49 @@ void DownloadRequestCore::OnResponseStarted(
// If we don't have strong validators as per RFC 2616 section 13.3.3, then
// we neither store nor use them for range requests.
if (!headers->EnumerateHeader(nullptr, "Last-Modified",
- &info->last_modified))
- info->last_modified.clear();
- if (!headers->EnumerateHeader(nullptr, "ETag", &info->etag))
- info->etag.clear();
+ &create_info->last_modified))
+ create_info->last_modified.clear();
+ if (!headers->EnumerateHeader(nullptr, "ETag", &create_info->etag))
+ create_info->etag.clear();
}
- int status = headers->response_code();
- if (2 == status / 100 && status != net::HTTP_PARTIAL_CONTENT) {
- // Success & not range response; if we asked for a range, we didn't
- // get it--reset the file pointers to reflect that.
- info->save_info->offset = 0;
- info->save_info->hash_state = "";
- }
+ // Grab the first content-disposition header. There may be more than one,
+ // though as of this writing, the network stack ensures if there are, they
+ // are all duplicates.
+ headers->EnumerateHeader(nullptr, "Content-Disposition",
+ &create_info->content_disposition);
- if (!headers->GetMimeType(&info->original_mime_type))
- info->original_mime_type.clear();
+ if (!headers->GetMimeType(&create_info->original_mime_type))
+ create_info->original_mime_type.clear();
}
// Blink verifies that the requester of this download is allowed to set a
- // suggested name for the security origin of the downlaod URL. However, this
+ // suggested name for the security origin of the download URL. However, this
// assumption doesn't hold if there were cross origin redirects. Therefore,
// clear the suggested_name for such requests.
- if (info->url_chain.size() > 1 &&
- info->url_chain.front().GetOrigin() != info->url_chain.back().GetOrigin())
- info->save_info->suggested_name.clear();
+ if (create_info->url_chain.size() > 1 &&
+ create_info->url_chain.front().GetOrigin() !=
+ create_info->url_chain.back().GetOrigin())
+ create_info->save_info->suggested_name.clear();
+
+ RecordDownloadMimeType(create_info->mime_type);
+ RecordDownloadContentDisposition(create_info->content_disposition);
+
+ delegate_->OnStart(std::move(create_info), std::move(stream_reader),
+ base::ResetAndReturn(&on_started_callback_));
+ return true;
+}
- info.swap(*create_info);
+bool DownloadRequestCore::OnRequestRedirected() {
+ DVLOG(20) << __FUNCTION__ << "() " << DebugString();
+ if (is_partial_request_) {
+ // A redirect while attempting a partial resumption indicates a potential
+ // middle box. Trigger another interruption so that the DownloadItem can
+ // retry.
+ abort_reason_ = DOWNLOAD_INTERRUPT_REASON_SERVER_UNREACHABLE;
+ return false;
+ }
+ return true;
}
// Create a new buffer, which will be handed to the download thread for file
@@ -212,7 +397,13 @@ bool DownloadRequestCore::OnReadCompleted(int bytes_read, bool* defer) {
return true;
}
-DownloadInterruptReason DownloadRequestCore::OnResponseCompleted(
+void DownloadRequestCore::OnWillAbort(DownloadInterruptReason reason) {
+ DVLOG(20) << __FUNCTION__ << "() reason=" << reason << " " << DebugString();
+ DCHECK(!started_);
+ abort_reason_ = reason;
+}
+
+void DownloadRequestCore::OnResponseCompleted(
const net::URLRequestStatus& status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
int response_code = status.is_success() ? request()->GetResponseCode() : 0;
@@ -221,80 +412,27 @@ DownloadInterruptReason DownloadRequestCore::OnResponseCompleted(
<< " status.error() = " << status.error()
<< " response_code = " << response_code;
- net::Error error_code = net::OK;
- if (status.status() == net::URLRequestStatus::FAILED ||
- // Note cancels as failures too.
- status.status() == net::URLRequestStatus::CANCELED) {
- error_code = static_cast<net::Error>(status.error()); // Normal case.
- // Make sure that at least the fact of failure comes through.
- if (error_code == net::OK)
- error_code = net::ERR_FAILED;
- }
-
- // ERR_CONTENT_LENGTH_MISMATCH and ERR_INCOMPLETE_CHUNKED_ENCODING are
- // allowed since a number of servers in the wild close the connection too
- // early by mistake. Other browsers - IE9, Firefox 11.0, and Safari 5.1.4 -
- // treat downloads as complete in both cases, so we follow their lead.
- if (error_code == net::ERR_CONTENT_LENGTH_MISMATCH ||
- error_code == net::ERR_INCOMPLETE_CHUNKED_ENCODING) {
- error_code = net::OK;
- }
- DownloadInterruptReason reason = ConvertNetErrorToInterruptReason(
- error_code, DOWNLOAD_INTERRUPT_FROM_NETWORK);
-
- if (status.status() == net::URLRequestStatus::CANCELED &&
- status.error() == net::ERR_ABORTED) {
- // CANCELED + ERR_ABORTED == something outside of the network
- // stack cancelled the request. There aren't that many things that
- // could do this to a download request (whose lifetime is separated from
- // the tab from which it came). We map this to USER_CANCELLED as the
- // case we know about (system suspend because of laptop close) corresponds
- // to a user action.
- // TODO(ahendrickson) -- Find a better set of codes to use here, as
- // CANCELED/ERR_ABORTED can occur for reasons other than user cancel.
- if (net::IsCertStatusError(request()->ssl_info().cert_status))
- reason = DOWNLOAD_INTERRUPT_REASON_SERVER_CERT_PROBLEM;
- else
- reason = DOWNLOAD_INTERRUPT_REASON_USER_CANCELED;
- }
-
- if (status.is_success() && reason == DOWNLOAD_INTERRUPT_REASON_NONE &&
- request()->response_headers()) {
- // Handle server's response codes.
- switch (response_code) {
- case -1: // Non-HTTP request.
- case net::HTTP_OK:
- case net::HTTP_CREATED:
- case net::HTTP_ACCEPTED:
- case net::HTTP_NON_AUTHORITATIVE_INFORMATION:
- case net::HTTP_RESET_CONTENT:
- case net::HTTP_PARTIAL_CONTENT:
- // Expected successful codes.
- break;
- case net::HTTP_NO_CONTENT:
- case net::HTTP_NOT_FOUND:
- reason = DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT;
- break;
- case net::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE:
- // Retry by downloading from the start automatically:
- // If we haven't received data when we get this error, we won't.
- reason = DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE;
- break;
- case net::HTTP_UNAUTHORIZED:
- // Server didn't authorize this request.
- reason = DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED;
- break;
- case net::HTTP_FORBIDDEN:
- // Server forbids access to this resource.
- reason = DOWNLOAD_INTERRUPT_REASON_SERVER_FORBIDDEN;
- break;
- default: // All other errors.
- // Redirection and informational codes should have been handled earlier
- // in the stack.
- DCHECK_NE(3, response_code / 100);
- DCHECK_NE(1, response_code / 100);
- reason = DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED;
- break;
+ DownloadInterruptReason reason = HandleRequestStatus(status);
+
+ if (status.status() == net::URLRequestStatus::CANCELED) {
+ if (abort_reason_ != DOWNLOAD_INTERRUPT_REASON_NONE) {
+ // If a more specific interrupt reason was specified before the request
+ // was explicitly cancelled, then use it.
+ reason = abort_reason_;
+ } else if (status.error() == net::ERR_ABORTED) {
+ // CANCELED + ERR_ABORTED == something outside of the network
+ // stack cancelled the request. There aren't that many things that
+ // could do this to a download request (whose lifetime is separated from
+ // the tab from which it came). We map this to USER_CANCELLED as the
+ // case we know about (system suspend because of laptop close) corresponds
+ // to a user action.
+ // TODO(asanka): A lid close or other power event should result in an
+ // interruption that doesn't discard the partial state, unlike
+ // USER_CANCELLED. (https://crbug.com/166179)
+ if (net::IsCertStatusError(request()->ssl_info().cert_status))
+ reason = DOWNLOAD_INTERRUPT_REASON_SERVER_CERT_PROBLEM;
+ else
+ reason = DOWNLOAD_INTERRUPT_REASON_USER_CANCELED;
}
}
@@ -325,7 +463,16 @@ DownloadInterruptReason DownloadRequestCore::OnResponseCompleted(
stream_writer_.reset(); // We no longer need the stream.
read_buffer_ = nullptr;
- return reason;
+ if (started_)
+ return;
+
+ // OnResponseCompleted() called without OnResponseStarted(). This should only
+ // happen when the request was aborted.
+ DCHECK_NE(reason, DOWNLOAD_INTERRUPT_REASON_NONE);
+ scoped_ptr<DownloadCreateInfo> create_info = CreateDownloadCreateInfo(reason);
+ scoped_ptr<ByteStreamReader> empty_byte_stream;
+ delegate_->OnStart(std::move(create_info), std::move(empty_byte_stream),
+ base::ResetAndReturn(&on_started_callback_));
}
void DownloadRequestCore::PauseRequest() {
@@ -351,16 +498,136 @@ void DownloadRequestCore::ResumeRequest() {
last_stream_pause_time_ = base::TimeTicks();
}
- on_ready_to_read_callback_.Run();
+ delegate_->OnReadyToRead();
}
std::string DownloadRequestCore::DebugString() const {
return base::StringPrintf(
"{"
+ " this=%p "
" url_ = "
"\"%s\""
" }",
+ reinterpret_cast<const void*>(this),
request() ? request()->url().spec().c_str() : "<NULL request>");
}
+// static
+DownloadInterruptReason DownloadRequestCore::HandleRequestStatus(
+ const net::URLRequestStatus& status) {
+ net::Error error_code = net::OK;
+ if (status.status() == net::URLRequestStatus::FAILED ||
+ // Note cancels as failures too.
+ status.status() == net::URLRequestStatus::CANCELED) {
+ error_code = static_cast<net::Error>(status.error()); // Normal case.
+ // Make sure that at least the fact of failure comes through.
+ if (error_code == net::OK)
+ error_code = net::ERR_FAILED;
+ }
+
+ // ERR_CONTENT_LENGTH_MISMATCH and ERR_INCOMPLETE_CHUNKED_ENCODING are
+ // allowed since a number of servers in the wild close the connection too
+ // early by mistake. Other browsers - IE9, Firefox 11.0, and Safari 5.1.4 -
+ // treat downloads as complete in both cases, so we follow their lead.
+ if (error_code == net::ERR_CONTENT_LENGTH_MISMATCH ||
+ error_code == net::ERR_INCOMPLETE_CHUNKED_ENCODING) {
+ error_code = net::OK;
+ }
+ DownloadInterruptReason reason = ConvertNetErrorToInterruptReason(
+ error_code, DOWNLOAD_INTERRUPT_FROM_NETWORK);
+
+ return reason;
+}
+
+// static
+DownloadInterruptReason DownloadRequestCore::HandleSuccessfulServerResponse(
+ const net::HttpResponseHeaders& http_headers,
+ DownloadSaveInfo* save_info) {
+ switch (http_headers.response_code()) {
+ case -1: // Non-HTTP request.
+ case net::HTTP_OK:
+ case net::HTTP_NON_AUTHORITATIVE_INFORMATION:
+ case net::HTTP_PARTIAL_CONTENT:
+ // Expected successful codes.
+ break;
+
+ case net::HTTP_CREATED:
+ case net::HTTP_ACCEPTED:
+ // Per RFC 2616 the entity being transferred is metadata about the
+ // resource at the target URL and not the resource at that URL (or the
+ // resource that would be at the URL once processing is completed in the
+ // case of HTTP_ACCEPTED). However, we currently don't have special
+ // handling for these response and they are downloaded the same as a
+ // regular response.
+ break;
+
+ case net::HTTP_NO_CONTENT:
+ case net::HTTP_RESET_CONTENT:
+ // These two status codes don't have an entity (or rather RFC 2616
+ // requires that there be no entity). They are treated the same as the
+ // resource not being found since there is no entity to download.
+
+ case net::HTTP_NOT_FOUND:
+ return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT;
+ break;
+
+ case net::HTTP_REQUESTED_RANGE_NOT_SATISFIABLE:
+ // Retry by downloading from the start automatically:
+ // If we haven't received data when we get this error, we won't.
+ return DOWNLOAD_INTERRUPT_REASON_SERVER_NO_RANGE;
+ break;
+ case net::HTTP_UNAUTHORIZED:
+ case net::HTTP_PROXY_AUTHENTICATION_REQUIRED:
+ // Server didn't authorize this request.
+ return DOWNLOAD_INTERRUPT_REASON_SERVER_UNAUTHORIZED;
+ break;
+ case net::HTTP_FORBIDDEN:
+ // Server forbids access to this resource.
+ return DOWNLOAD_INTERRUPT_REASON_SERVER_FORBIDDEN;
+ break;
+ default: // All other errors.
+ // Redirection and informational codes should have been handled earlier
+ // in the stack.
+ DCHECK_NE(3, http_headers.response_code() / 100);
+ DCHECK_NE(1, http_headers.response_code() / 100);
+ return DOWNLOAD_INTERRUPT_REASON_SERVER_FAILED;
+ }
+
+ if (save_info && save_info->offset > 0) {
+ // The caller is expecting a partial response.
+
+ if (http_headers.response_code() != net::HTTP_PARTIAL_CONTENT) {
+ // Requested a partial range, but received the entire response.
+ save_info->offset = 0;
+ save_info->hash_of_partial_file.clear();
+ save_info->hash_state.reset();
+ return DOWNLOAD_INTERRUPT_REASON_NONE;
+ }
+
+ int64_t first_byte = -1;
+ int64_t last_byte = -1;
+ int64_t length = -1;
+ if (!http_headers.GetContentRange(&first_byte, &last_byte, &length))
+ return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT;
+ DCHECK_GE(first_byte, 0);
+
+ if (first_byte != save_info->offset) {
+ // The server returned a different range than the one we requested. Assume
+ // the response is bad.
+ //
+ // In the future we should consider allowing offsets that are less than
+ // the offset we've requested, since in theory we can truncate the partial
+ // file at the offset and continue.
+ return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT;
+ }
+
+ return DOWNLOAD_INTERRUPT_REASON_NONE;
+ }
+
+ if (http_headers.response_code() == net::HTTP_PARTIAL_CONTENT)
+ return DOWNLOAD_INTERRUPT_REASON_SERVER_BAD_CONTENT;
+
+ return DOWNLOAD_INTERRUPT_REASON_NONE;
+}
+
} // namespace content
diff --git a/chromium/content/browser/download/download_request_core.h b/chromium/content/browser/download/download_request_core.h
index 22ca862ef85..ac9e9b6cd86 100644
--- a/chromium/content/browser/download/download_request_core.h
+++ b/chromium/content/browser/download/download_request_core.h
@@ -20,7 +20,9 @@
#include "content/public/browser/download_url_parameters.h"
namespace net {
+class HttpResponseHeaders;
class URLRequest;
+class URLRequestStatus;
} // namespace net
namespace content {
@@ -38,29 +40,29 @@ struct DownloadCreateInfo;
class CONTENT_EXPORT DownloadRequestCore
: public base::SupportsWeakPtr<DownloadRequestCore> {
public:
- // Size of the buffer used between the DownloadRequestCore and the
- // downstream receiver of its output.
- static const int kDownloadByteStreamSize;
-
- // |request| *must* outlive the DownloadRequestCore. |save_info| must be
- // valid.
- //
- // Invokes |on_ready_to_read_callback| if a previous call to OnReadCompleted()
- // resulted in |defer| being set to true, and DownloadRequestCore is now ready
- // to commence reading.
- DownloadRequestCore(net::URLRequest* request,
- scoped_ptr<DownloadSaveInfo> save_info,
- const base::Closure& on_ready_to_read_callback);
+ class Delegate {
+ public:
+ virtual void OnReadyToRead() = 0;
+ virtual void OnStart(
+ scoped_ptr<DownloadCreateInfo> download_create_info,
+ scoped_ptr<ByteStreamReader> stream_reader,
+ const DownloadUrlParameters::OnStartedCallback& callback) = 0;
+ };
+
+ // All parameters are required. |request| and |delegate| must outlive
+ // DownloadRequestCore.
+ DownloadRequestCore(net::URLRequest* request, Delegate* delegate);
~DownloadRequestCore();
// Should be called when the URLRequest::Delegate receives OnResponseStarted.
- // Constructs a DownloadCreateInfo and a ByteStreamReader that should be
- // passed into DownloadManagerImpl::StartDownload().
- //
- // Only populates the response derived fields of DownloadCreateInfo, with the
- // exception of |save_info|.
- void OnResponseStarted(scoped_ptr<DownloadCreateInfo>* info,
- scoped_ptr<ByteStreamReader>* stream_reader);
+ // Invokes Delegate::OnStart() with download start parameters. The
+ // |override_mime_type| is used as the MIME type for the download when
+ // constructing a DownloadCreateInfo object.
+ bool OnResponseStarted(const std::string& override_mime_type);
+
+ // Should be called to handle a redirect. The caller should only allow the
+ // redirect to be followed if the return value is true.
+ bool OnRequestRedirected();
// Starts a read cycle. Creates a new IOBuffer which can be passed into
// URLRequest::Read(). Call OnReadCompleted() when the Read operation
@@ -69,20 +71,22 @@ class CONTENT_EXPORT DownloadRequestCore
int* buf_size,
int min_size);
+ // Used to notify DownloadRequestCore that the caller is about to abort the
+ // outer request. |reason| will be used as the final interrupt reason when
+ // OnResponseCompleted() is called.
+ void OnWillAbort(DownloadInterruptReason reason);
+
// Should be called when the Read() operation completes. |defer| will be set
// to true if reading is to be suspended. In the latter case, once more data
// can be read, invokes the |on_ready_to_read_callback|.
bool OnReadCompleted(int bytes_read, bool* defer);
- // Called to signal that the response is complete. If the return value is
- // something other than DOWNLOAD_INTERRUPT_REASON_NONE, then the download
- // should be considered interrupted.
+ // Called to signal that the response is complete.
//
// It is expected that once this method is invoked, the DownloadRequestCore
// object will be destroyed in short order without invoking any other methods
// other than the destructor.
- DownloadInterruptReason OnResponseCompleted(
- const net::URLRequestStatus& status);
+ void OnResponseCompleted(const net::URLRequestStatus& status);
// Called if the request should suspend reading. A subsequent
// OnReadCompleted() will result in |defer| being set to true.
@@ -98,13 +102,36 @@ class CONTENT_EXPORT DownloadRequestCore
std::string DebugString() const;
+ static scoped_ptr<net::URLRequest> CreateRequestOnIOThread(
+ uint32_t download_id,
+ DownloadUrlParameters* params);
+
+ // Size of the buffer used between the DownloadRequestCore and the
+ // downstream receiver of its output.
+ static const int kDownloadByteStreamSize;
+
protected:
net::URLRequest* request() const { return request_; }
private:
- base::Closure on_ready_to_read_callback_;
+ static DownloadInterruptReason HandleRequestStatus(
+ const net::URLRequestStatus& status);
+
+ static DownloadInterruptReason HandleSuccessfulServerResponse(
+ const net::HttpResponseHeaders& http_headers,
+ DownloadSaveInfo* save_info);
+
+ scoped_ptr<DownloadCreateInfo> CreateDownloadCreateInfo(
+ DownloadInterruptReason result);
+
+ Delegate* delegate_;
net::URLRequest* request_;
+
+ // "Passthrough" fields. These are only kept here so that they can be used to
+ // populate the DownloadCreateInfo when the time comes.
scoped_ptr<DownloadSaveInfo> save_info_;
+ uint32_t download_id_;
+ DownloadUrlParameters::OnStartedCallback on_started_callback_;
// Data flow
scoped_refptr<net::IOBuffer> read_buffer_; // From URLRequest.
@@ -125,6 +152,15 @@ class CONTENT_EXPORT DownloadRequestCore
int pause_count_;
bool was_deferred_;
+ bool is_partial_request_;
+ bool started_;
+
+ // When DownloadRequestCore initiates an abort (by blocking a redirect, for
+ // example) it expects to eventually receive a OnResponseCompleted() with a
+ // status indicating that the request was aborted. When this happens, the
+ // interrupt reason in |abort_reason_| will be used instead of USER_CANCELED
+ // which is vague.
+ DownloadInterruptReason abort_reason_;
// Each successful OnWillRead will yield a buffer of this size.
static const int kReadBufSize = 32768; // bytes
diff --git a/chromium/content/browser/download/download_request_handle.cc b/chromium/content/browser/download/download_request_handle.cc
index 67dda4f5029..f5979b945ad 100644
--- a/chromium/content/browser/download/download_request_handle.cc
+++ b/chromium/content/browser/download/download_request_handle.cc
@@ -6,88 +6,39 @@
#include "base/bind.h"
#include "base/strings/stringprintf.h"
-#include "content/browser/frame_host/navigator.h"
-#include "content/browser/frame_host/render_frame_host_impl.h"
-#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/common/browser_side_navigation_policy.h"
namespace content {
DownloadRequestHandleInterface::~DownloadRequestHandleInterface() {}
+DownloadRequestHandle::DownloadRequestHandle(
+ const DownloadRequestHandle& other) = default;
+
DownloadRequestHandle::~DownloadRequestHandle() {}
-DownloadRequestHandle::DownloadRequestHandle()
- : child_id_(-1),
- render_view_id_(-1),
- request_id_(-1),
- frame_tree_node_id_(-1) {
-}
+DownloadRequestHandle::DownloadRequestHandle() {}
DownloadRequestHandle::DownloadRequestHandle(
const base::WeakPtr<DownloadResourceHandler>& handler,
- int child_id,
- int render_view_id,
- int request_id,
- int frame_tree_node_id)
- : handler_(handler),
- child_id_(child_id),
- render_view_id_(render_view_id),
- request_id_(request_id),
- frame_tree_node_id_(frame_tree_node_id) {
+ const content::ResourceRequestInfo::WebContentsGetter& web_contents_getter)
+ : handler_(handler), web_contents_getter_(web_contents_getter) {
DCHECK(handler_.get());
}
WebContents* DownloadRequestHandle::GetWebContents() const {
- // PlzNavigate: if a FrameTreeNodeId was provided, use it to return the
- // WebContents.
- // TODO(davidben): This logic should be abstracted within the ResourceLoader
- // stack. https://crbug.com/376003
- if (IsBrowserSideNavigationEnabled()) {
- FrameTreeNode* frame_tree_node =
- FrameTreeNode::GloballyFindByID(frame_tree_node_id_);
- if (frame_tree_node) {
- return WebContentsImpl::FromFrameTreeNode(frame_tree_node);
- }
- }
-
- RenderViewHostImpl* render_view_host =
- RenderViewHostImpl::FromID(child_id_, render_view_id_);
- if (!render_view_host)
- return nullptr;
-
- return render_view_host->GetDelegate()->GetAsWebContents();
+ return web_contents_getter_.is_null() ? nullptr : web_contents_getter_.Run();
}
DownloadManager* DownloadRequestHandle::GetDownloadManager() const {
- // PlzNavigate: if a FrameTreeNodeId was provided, use it to return the
- // DownloadManager.
- // TODO(davidben): This logic should be abstracted within the ResourceLoader
- // stack. https://crbug.com/376003
- if (IsBrowserSideNavigationEnabled()) {
- FrameTreeNode* frame_tree_node =
- FrameTreeNode::GloballyFindByID(frame_tree_node_id_);
- if (frame_tree_node) {
- BrowserContext* context =
- frame_tree_node->navigator()->GetController()->GetBrowserContext();
- if (context)
- return BrowserContext::GetDownloadManager(context);
- }
- }
-
- RenderViewHostImpl* rvh = RenderViewHostImpl::FromID(
- child_id_, render_view_id_);
- if (rvh == NULL)
- return NULL;
- RenderProcessHost* rph = rvh->GetProcess();
- if (rph == NULL)
- return NULL;
- BrowserContext* context = rph->GetBrowserContext();
- if (context == NULL)
- return NULL;
+ WebContents* web_contents = GetWebContents();
+ if (web_contents == nullptr)
+ return nullptr;
+ BrowserContext* context = web_contents->GetBrowserContext();
+ if (context == nullptr)
+ return nullptr;
return BrowserContext::GetDownloadManager(context);
}
@@ -109,15 +60,4 @@ void DownloadRequestHandle::CancelRequest() const {
base::Bind(&DownloadResourceHandler::CancelRequest, handler_));
}
-std::string DownloadRequestHandle::DebugString() const {
- return base::StringPrintf("{"
- " child_id = %d"
- " render_view_id = %d"
- " request_id = %d"
- "}",
- child_id_,
- render_view_id_,
- request_id_);
-}
-
} // namespace content
diff --git a/chromium/content/browser/download/download_request_handle.h b/chromium/content/browser/download/download_request_handle.h
index 5d047c75910..090a25bb5a6 100644
--- a/chromium/content/browser/download/download_request_handle.h
+++ b/chromium/content/browser/download/download_request_handle.h
@@ -5,12 +5,11 @@
#ifndef CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_REQUEST_HANDLE_H_
#define CONTENT_BROWSER_DOWNLOAD_DOWNLOAD_REQUEST_HANDLE_H_
-#include <string>
-
#include "base/compiler_specific.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/download/download_resource_handler.h"
#include "content/common/content_export.h"
+#include "content/public/browser/resource_request_info.h"
namespace content {
class DownloadManager;
@@ -36,15 +35,13 @@ class CONTENT_EXPORT DownloadRequestHandleInterface {
// Cancels the request.
virtual void CancelRequest() const = 0;
-
- // Describes the object.
- virtual std::string DebugString() const = 0;
};
class CONTENT_EXPORT DownloadRequestHandle
: public DownloadRequestHandleInterface {
public:
+ DownloadRequestHandle(const DownloadRequestHandle& other);
~DownloadRequestHandle() override;
// Create a null DownloadRequestHandle: getters will return null, and
@@ -56,12 +53,9 @@ class CONTENT_EXPORT DownloadRequestHandle
// allowing mocking of ResourceDispatcherHost in unit tests.
DownloadRequestHandle();
- // Note that |rdh| is required to be non-null.
DownloadRequestHandle(const base::WeakPtr<DownloadResourceHandler>& handler,
- int child_id,
- int render_view_id,
- int request_id,
- int frame_tree_node_id);
+ const content::ResourceRequestInfo::WebContentsGetter&
+ web_contents_getter);
// Implement DownloadRequestHandleInterface interface.
WebContents* GetWebContents() const override;
@@ -69,23 +63,10 @@ class CONTENT_EXPORT DownloadRequestHandle
void PauseRequest() const override;
void ResumeRequest() const override;
void CancelRequest() const override;
- std::string DebugString() const override;
private:
base::WeakPtr<DownloadResourceHandler> handler_;
-
- // The ID of the child process that started the download.
- int child_id_;
-
- // The ID of the render view that started the download.
- int render_view_id_;
-
- // The ID associated with the request used for the download.
- int request_id_;
-
- // PlzNavigate
- // The ID of the FrameTreeNode that started the download.
- int frame_tree_node_id_;
+ content::ResourceRequestInfo::WebContentsGetter web_contents_getter_;
};
} // namespace content
diff --git a/chromium/content/browser/download/download_resource_handler.cc b/chromium/content/browser/download/download_resource_handler.cc
index e06b3095e99..30a7c8cf029 100644
--- a/chromium/content/browser/download/download_resource_handler.cc
+++ b/chromium/content/browser/download/download_resource_handler.cc
@@ -48,11 +48,11 @@ static void StartOnUIThread(
// NULL in unittests or if the page closed right after starting the
// download.
if (!started_cb.is_null())
- started_cb.Run(NULL, DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
-
- // |stream| gets deleted on non-FILE thread, but it's ok since
- // we're not using stream_writer_ yet.
+ started_cb.Run(nullptr, DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
+ if (stream)
+ BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE,
+ stream.release());
return;
}
@@ -83,19 +83,10 @@ void DeleteOnUIThread(
} // namespace
-DownloadResourceHandler::DownloadResourceHandler(
- uint32_t id,
- net::URLRequest* request,
- const DownloadUrlParameters::OnStartedCallback& started_cb,
- scoped_ptr<DownloadSaveInfo> save_info)
+DownloadResourceHandler::DownloadResourceHandler(net::URLRequest* request)
: ResourceHandler(request),
- download_id_(id),
- started_cb_(started_cb),
tab_info_(new DownloadTabInfo()),
- core_(request,
- std::move(save_info),
- base::Bind(&DownloadResourceHandler::OnCoreReadyToRead,
- base::Unretained(this))) {
+ core_(request, this) {
// Do UI thread initialization for tab_info_ asap after
// DownloadResourceHandler creation since the tab could be navigated
// before StartOnUIThread gets called. This is safe because deletion
@@ -104,20 +95,14 @@ DownloadResourceHandler::DownloadResourceHandler(
const ResourceRequestInfoImpl* request_info = GetRequestInfo();
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&InitializeDownloadTabInfoOnUIThread,
- DownloadRequestHandle(AsWeakPtr(), request_info->GetChildID(),
- request_info->GetRouteID(),
- request_info->GetRequestID(),
- request_info->frame_tree_node_id()),
- tab_info_.get()));
+ base::Bind(
+ &InitializeDownloadTabInfoOnUIThread,
+ DownloadRequestHandle(AsWeakPtr(),
+ request_info->GetWebContentsGetterForRequest()),
+ tab_info_.get()));
}
DownloadResourceHandler::~DownloadResourceHandler() {
- // This won't do anything if the callback was called before.
- // If it goes through, it will likely be because OnWillStart() returned
- // false somewhere in the chain of resource handlers.
- CallStartedCB(DOWNLOAD_INTERRUPT_REASON_NETWORK_FAILED);
-
if (tab_info_) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
@@ -129,46 +114,16 @@ bool DownloadResourceHandler::OnRequestRedirected(
const net::RedirectInfo& redirect_info,
ResourceResponse* response,
bool* defer) {
- return true;
+ return core_.OnRequestRedirected();
}
// Send the download creation information to the download thread.
bool DownloadResourceHandler::OnResponseStarted(
ResourceResponse* response,
bool* defer) {
- scoped_ptr<DownloadCreateInfo> create_info;
- scoped_ptr<ByteStreamReader> stream_reader;
-
- core_.OnResponseStarted(&create_info, &stream_reader);
-
- const ResourceRequestInfoImpl* request_info = GetRequestInfo();
- create_info->download_id = download_id_;
- create_info->has_user_gesture = request_info->HasUserGesture();
- create_info->transition_type = request_info->GetPageTransition();
- create_info->request_handle.reset(new DownloadRequestHandle(
- AsWeakPtr(), request_info->GetChildID(), request_info->GetRouteID(),
- request_info->GetRequestID(), request_info->frame_tree_node_id()));
-
// The MIME type in ResourceResponse is the product of
// MimeTypeResourceHandler.
- create_info->mime_type = response->head.mime_type;
-
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&StartOnUIThread, base::Passed(&create_info),
- base::Passed(&tab_info_), base::Passed(&stream_reader),
- base::ResetAndReturn(&started_cb_)));
- return true;
-}
-
-void DownloadResourceHandler::CallStartedCB(
- DownloadInterruptReason interrupt_reason) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (started_cb_.is_null())
- return;
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(base::ResetAndReturn(&started_cb_),
- nullptr, interrupt_reason));
+ return core_.OnResponseStarted(response->head.mime_type);
}
bool DownloadResourceHandler::OnWillStart(const GURL& url, bool* defer) {
@@ -197,8 +152,7 @@ void DownloadResourceHandler::OnResponseCompleted(
const net::URLRequestStatus& status,
const std::string& security_info,
bool* defer) {
- DownloadInterruptReason result = core_.OnResponseCompleted(status);
- CallStartedCB(result);
+ core_.OnResponseCompleted(status);
}
void DownloadResourceHandler::OnDataDownloaded(int bytes_downloaded) {
@@ -213,7 +167,36 @@ void DownloadResourceHandler::ResumeRequest() {
core_.ResumeRequest();
}
-void DownloadResourceHandler::OnCoreReadyToRead() {
+void DownloadResourceHandler::OnStart(
+ scoped_ptr<DownloadCreateInfo> create_info,
+ scoped_ptr<ByteStreamReader> stream_reader,
+ const DownloadUrlParameters::OnStartedCallback& callback) {
+ // If the user cancels the download, then don't call start. Instead ignore the
+ // download entirely.
+ if (create_info->result == DOWNLOAD_INTERRUPT_REASON_USER_CANCELED &&
+ create_info->download_id == DownloadItem::kInvalidId) {
+ if (!callback.is_null())
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(callback, nullptr, create_info->result));
+ return;
+ }
+
+ const ResourceRequestInfoImpl* request_info = GetRequestInfo();
+ create_info->has_user_gesture = request_info->HasUserGesture();
+ create_info->transition_type = request_info->GetPageTransition();
+
+ create_info->request_handle.reset(new DownloadRequestHandle(
+ AsWeakPtr(), request_info->GetWebContentsGetterForRequest()));
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&StartOnUIThread, base::Passed(&create_info),
+ base::Passed(&tab_info_), base::Passed(&stream_reader),
+ callback));
+}
+
+void DownloadResourceHandler::OnReadyToRead() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
controller()->Resume();
}
diff --git a/chromium/content/browser/download/download_resource_handler.h b/chromium/content/browser/download/download_resource_handler.h
index 22a10a8a049..b874b9a43bb 100644
--- a/chromium/content/browser/download/download_resource_handler.h
+++ b/chromium/content/browser/download/download_resource_handler.h
@@ -33,17 +33,14 @@ struct DownloadCreateInfo;
// Forwards data to the download thread.
class CONTENT_EXPORT DownloadResourceHandler
: public ResourceHandler,
+ public DownloadRequestCore::Delegate,
public base::SupportsWeakPtr<DownloadResourceHandler> {
public:
struct DownloadTabInfo;
// started_cb will be called exactly once on the UI thread.
// |id| should be invalid if the id should be automatically assigned.
- DownloadResourceHandler(
- uint32_t id,
- net::URLRequest* request,
- const DownloadUrlParameters::OnStartedCallback& started_cb,
- scoped_ptr<DownloadSaveInfo> save_info);
+ DownloadResourceHandler(net::URLRequest* request);
bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
ResourceResponse* response,
@@ -84,18 +81,12 @@ class CONTENT_EXPORT DownloadResourceHandler
private:
~DownloadResourceHandler() override;
- // Arrange for started_cb_ to be called on the UI thread with the
- // below values, nulling out started_cb_. Should only be called
- // on the IO thread.
- void CallStartedCB(DownloadInterruptReason interrupt_reason);
-
- void OnCoreReadyToRead();
-
- uint32_t download_id_;
-
- // This is read only on the IO thread, but may only
- // be called on the UI thread.
- DownloadUrlParameters::OnStartedCallback started_cb_;
+ // DownloadRequestCore::Delegate
+ void OnStart(
+ scoped_ptr<DownloadCreateInfo> download_create_info,
+ scoped_ptr<ByteStreamReader> stream_reader,
+ const DownloadUrlParameters::OnStartedCallback& callback) override;
+ void OnReadyToRead() override;
// Stores information about the download that must be acquired on the UI
// thread before StartOnUIThread is called.
diff --git a/chromium/content/browser/download/drag_download_file.cc b/chromium/content/browser/download/drag_download_file.cc
index afb533a56bf..dc6b89c8b8f 100644
--- a/chromium/content/browser/download/drag_download_file.cc
+++ b/chromium/content/browser/download/drag_download_file.cc
@@ -97,8 +97,8 @@ class DragDownloadFile::DragDownloadFileUI : public DownloadItem::Observer {
void OnDownloadStarted(DownloadItem* item,
DownloadInterruptReason interrupt_reason) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (!item) {
- DCHECK_NE(DOWNLOAD_INTERRUPT_REASON_NONE, interrupt_reason);
+ if (!item || item->GetState() != DownloadItem::IN_PROGRESS) {
+ DCHECK(!item || item->GetLastReason() != DOWNLOAD_INTERRUPT_REASON_NONE);
on_completed_loop_->task_runner()->PostTask(
FROM_HERE, base::Bind(on_completed_, false));
return;
diff --git a/chromium/content/browser/download/mhtml_generation_manager.cc b/chromium/content/browser/download/mhtml_generation_manager.cc
index ef9202330d2..623ab53546e 100644
--- a/chromium/content/browser/download/mhtml_generation_manager.cc
+++ b/chromium/content/browser/download/mhtml_generation_manager.cc
@@ -188,9 +188,8 @@ bool MHTMLGenerationManager::Job::SendToNextRenderFrame() {
ipc_params.salt = salt_;
ipc_params.digests_of_uris_to_skip = digests_of_already_serialized_uris_;
- ipc_params.destination_file = IPC::GetFileHandleForProcess(
- browser_file_.GetPlatformFile(), rfh->GetProcess()->GetHandle(),
- false); // |close_source_handle|.
+ ipc_params.destination_file = IPC::GetPlatformFileForTransit(
+ browser_file_.GetPlatformFile(), false); // |close_source_handle|.
ipc_params.frame_routing_id_to_content_id =
CreateFrameRoutingIdToContentId(rfh->GetSiteInstance());
diff --git a/chromium/content/browser/download/mock_download_file.h b/chromium/content/browser/download/mock_download_file.h
index a0020b686c9..7109c44c157 100644
--- a/chromium/content/browser/download/mock_download_file.h
+++ b/chromium/content/browser/download/mock_download_file.h
@@ -35,23 +35,24 @@ class MockDownloadFile : public DownloadFile {
MOCK_METHOD2(RenameAndUniquify,
void(const base::FilePath& full_path,
const RenameCompletionCallback& callback));
- MOCK_METHOD2(RenameAndAnnotate,
+ MOCK_METHOD5(RenameAndAnnotate,
void(const base::FilePath& full_path,
+ const std::string& client_guid,
+ const GURL& source_url,
+ const GURL& referrer_url,
const RenameCompletionCallback& callback));
MOCK_METHOD0(Detach, void());
MOCK_METHOD0(Cancel, void());
MOCK_METHOD0(Finish, void());
- MOCK_CONST_METHOD0(FullPath, base::FilePath());
+ MOCK_CONST_METHOD0(FullPath, const base::FilePath&());
MOCK_CONST_METHOD0(InProgress, bool());
MOCK_CONST_METHOD0(BytesSoFar, int64_t());
MOCK_CONST_METHOD0(CurrentSpeed, int64_t());
MOCK_METHOD1(GetHash, bool(std::string* hash));
- MOCK_METHOD0(GetHashState, std::string());
MOCK_METHOD0(SendUpdate, void());
MOCK_CONST_METHOD0(Id, int());
MOCK_METHOD0(GetDownloadManager, DownloadManager*());
MOCK_CONST_METHOD0(DebugString, std::string());
- MOCK_METHOD1(SetClientGuid, void(const std::string&));
};
} // namespace content
diff --git a/chromium/content/browser/download/save_file.cc b/chromium/content/browser/download/save_file.cc
index 5085e477c15..2eab52b0451 100644
--- a/chromium/content/browser/download/save_file.cc
+++ b/chromium/content/browser/download/save_file.cc
@@ -14,15 +14,7 @@ namespace content {
// Unfortunately, as it is, constructors of SaveFile don't always
// have access to the SavePackage at this point.
SaveFile::SaveFile(const SaveFileCreateInfo* info, bool calculate_hash)
- : file_(base::FilePath(),
- info->url,
- GURL(),
- 0,
- calculate_hash,
- std::string(),
- base::File(),
- net::BoundNetLog()),
- info_(info) {
+ : file_(net::BoundNetLog()), info_(info) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
DCHECK(info);
@@ -34,7 +26,12 @@ SaveFile::~SaveFile() {
}
DownloadInterruptReason SaveFile::Initialize() {
- return file_.Initialize(base::FilePath());
+ return file_.Initialize(base::FilePath(),
+ base::FilePath(),
+ base::File(),
+ 0,
+ std::string(),
+ scoped_ptr<crypto::SecureHash>());
}
DownloadInterruptReason SaveFile::AppendDataToFile(const char* data,
@@ -61,7 +58,7 @@ void SaveFile::Finish() {
void SaveFile::AnnotateWithSourceInformation() {
// TODO(gbillock): If this method is called, it should set the
// file_.SetClientGuid() method first.
- file_.AnnotateWithSourceInformation();
+ NOTREACHED();
}
base::FilePath SaveFile::FullPath() const {
@@ -76,10 +73,6 @@ int64_t SaveFile::BytesSoFar() const {
return file_.bytes_so_far();
}
-bool SaveFile::GetHash(std::string* hash) {
- return file_.GetHash(hash);
-}
-
std::string SaveFile::DebugString() const {
return file_.DebugString();
}
diff --git a/chromium/content/browser/download/save_file.h b/chromium/content/browser/download/save_file.h
index 1dc82170ad0..69add3279da 100644
--- a/chromium/content/browser/download/save_file.h
+++ b/chromium/content/browser/download/save_file.h
@@ -38,7 +38,6 @@ class SaveFile {
base::FilePath FullPath() const;
bool InProgress() const;
int64_t BytesSoFar() const;
- bool GetHash(std::string* hash);
std::string DebugString() const;
// Accessors.
diff --git a/chromium/content/browser/download/save_file_manager.cc b/chromium/content/browser/download/save_file_manager.cc
index cf2e59ce3f1..527a7a18fbb 100644
--- a/chromium/content/browser/download/save_file_manager.cc
+++ b/chromium/content/browser/download/save_file_manager.cc
@@ -74,6 +74,10 @@ void SaveFileManager::SaveURL(SaveItemId save_item_id,
SavePackage* save_package) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ // Insert started saving job to tracking list.
+ DCHECK(packages_.find(save_item_id) == packages_.end());
+ packages_[save_item_id] = save_package;
+
// Register a saving job.
if (save_source == SaveFileCreateInfo::SAVE_FILE_FROM_NET) {
DCHECK(url.is_valid());
@@ -201,19 +205,27 @@ void SaveFileManager::SaveFinished(SaveItemId save_item_id,
<< " save_package_id = " << save_package_id
<< " is_success = " << is_success;
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+
+ int64_t bytes_so_far = 0;
SaveFile* save_file = LookupSaveFile(save_item_id);
if (save_file != nullptr) {
DCHECK(save_file->InProgress());
DVLOG(20) << " " << __FUNCTION__ << "()"
<< " save_file = " << save_file->DebugString();
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&SaveFileManager::OnSaveFinished, this, save_item_id,
- save_file->BytesSoFar(), is_success));
-
+ bytes_so_far = save_file->BytesSoFar();
save_file->Finish();
save_file->Detach();
+ } else {
+ // We got called before StartSave - this should only happen if
+ // ResourceHandler failed before it got a chance to parse headers
+ // and metadata.
+ DCHECK(!is_success);
}
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&SaveFileManager::OnSaveFinished, this, save_item_id,
+ bytes_so_far, is_success));
}
// Notifications sent from the file thread and run on the UI thread.
@@ -228,10 +240,6 @@ void SaveFileManager::OnStartSave(const SaveFileCreateInfo& info) {
return;
}
- // Insert started saving job to tracking list.
- DCHECK(packages_.find(info.save_item_id) == packages_.end());
- packages_[info.save_item_id] = save_package;
-
// Forward this message to SavePackage.
save_package->StartSave(&info);
}
diff --git a/chromium/content/browser/download/save_file_manager.h b/chromium/content/browser/download/save_file_manager.h
index 3f36206f43c..e99c2a23b8a 100644
--- a/chromium/content/browser/download/save_file_manager.h
+++ b/chromium/content/browser/download/save_file_manager.h
@@ -60,8 +60,8 @@
#include <stdint.h>
#include <string>
+#include <unordered_map>
-#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "content/browser/download/save_types.h"
@@ -90,8 +90,10 @@ class SaveFileManager : public base::RefCountedThreadSafe<SaveFileManager> {
// Lifetime management.
CONTENT_EXPORT void Shutdown();
- // Save the specified URL. Called on the UI thread and forwarded to the
- // ResourceDispatcherHostImpl on the IO thread.
+ // Save the specified URL. Caller has to guarantee that |save_package| will
+ // be alive until the call to RemoveSaveFile. Called on the UI thread (and in
+ // case of network downloads forwarded to the ResourceDispatcherHostImpl on
+ // the IO thread).
void SaveURL(SaveItemId save_item_id,
const GURL& url,
const Referrer& referrer,
@@ -204,12 +206,14 @@ class SaveFileManager : public base::RefCountedThreadSafe<SaveFileManager> {
void ExecuteCancelSaveRequest(int render_process_id, int request_id);
// A map from save_item_id into SaveFiles.
- typedef base::hash_map<SaveItemId, SaveFile*> SaveFileMap;
+ using SaveFileMap =
+ std::unordered_map<SaveItemId, SaveFile*, SaveItemId::Hasher>;
SaveFileMap save_file_map_;
// Tracks which SavePackage to send data to, called only on UI thread.
// SavePackageMap maps save item ids to their SavePackage.
- typedef base::hash_map<SaveItemId, SavePackage*> SavePackageMap;
+ using SavePackageMap =
+ std::unordered_map<SaveItemId, SavePackage*, SaveItemId::Hasher>;
SavePackageMap packages_;
DISALLOW_COPY_AND_ASSIGN(SaveFileManager);
diff --git a/chromium/content/browser/download/save_file_resource_handler.cc b/chromium/content/browser/download/save_file_resource_handler.cc
index faf5605710a..7cba445aad5 100644
--- a/chromium/content/browser/download/save_file_resource_handler.cc
+++ b/chromium/content/browser/download/save_file_resource_handler.cc
@@ -85,7 +85,7 @@ bool SaveFileResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
base::Bind(&SaveFileManager::UpdateSaveProgress, save_manager_,
- save_item_id_, buffer, bytes_read));
+ save_item_id_, base::RetainedRef(buffer), bytes_read));
return true;
}
diff --git a/chromium/content/browser/download/save_item.cc b/chromium/content/browser/download/save_item.cc
index edea2632804..5fa262778e8 100644
--- a/chromium/content/browser/download/save_item.cc
+++ b/chromium/content/browser/download/save_item.cc
@@ -27,10 +27,12 @@ SaveItemId GetNextSaveItemId() {
SaveItem::SaveItem(const GURL& url,
const Referrer& referrer,
SavePackage* package,
- SaveFileCreateInfo::SaveFileSource save_source)
+ SaveFileCreateInfo::SaveFileSource save_source,
+ int frame_tree_node_id)
: save_item_id_(GetNextSaveItemId()),
url_(url),
referrer_(referrer),
+ frame_tree_node_id_(frame_tree_node_id),
total_bytes_(0),
received_bytes_(0),
state_(WAIT_START),
diff --git a/chromium/content/browser/download/save_item.h b/chromium/content/browser/download/save_item.h
index b0e655da71e..ef463953bf7 100644
--- a/chromium/content/browser/download/save_item.h
+++ b/chromium/content/browser/download/save_item.h
@@ -30,7 +30,8 @@ class SaveItem {
SaveItem(const GURL& url,
const Referrer& referrer,
SavePackage* package,
- SaveFileCreateInfo::SaveFileSource save_source);
+ SaveFileCreateInfo::SaveFileSource save_source,
+ int frame_tree_node_id);
~SaveItem();
@@ -61,6 +62,7 @@ class SaveItem {
const base::FilePath& file_name() const { return file_name_; }
const GURL& url() const { return url_; }
const Referrer& referrer() const { return referrer_; }
+ int frame_tree_node_id() const { return frame_tree_node_id_; }
int64_t total_bytes() const { return total_bytes_; }
int64_t received_bytes() const { return received_bytes_; }
bool has_final_name() const { return has_final_name_; }
@@ -87,6 +89,10 @@ class SaveItem {
GURL url_;
Referrer referrer_;
+ // Frame tree node id, if this save item represents a frame
+ // (otherwise FrameTreeNode::kFrameTreeNodeInvalidID).
+ int frame_tree_node_id_;
+
// Total bytes expected.
int64_t total_bytes_;
diff --git a/chromium/content/browser/download/save_package.cc b/chromium/content/browser/download/save_package.cc
index 5b7d6a6ead1..7c989856f6b 100644
--- a/chromium/content/browser/download/save_package.cc
+++ b/chromium/content/browser/download/save_package.cc
@@ -131,9 +131,6 @@ class SavePackageRequestHandle : public DownloadRequestHandleInterface {
void PauseRequest() const override {}
void ResumeRequest() const override {}
void CancelRequest() const override {}
- std::string DebugString() const override {
- return "SavePackage DownloadRequestHandle";
- }
private:
base::WeakPtr<SavePackage> save_package_;
@@ -354,10 +351,8 @@ void SavePackage::InitWithDownloadItem(
SaveFileCreateInfo::SaveFileSource save_source = page_url_.SchemeIsFile() ?
SaveFileCreateInfo::SAVE_FILE_FROM_FILE :
SaveFileCreateInfo::SAVE_FILE_FROM_NET;
- SaveItem* save_item = new SaveItem(page_url_,
- Referrer(),
- this,
- save_source);
+ SaveItem* save_item = new SaveItem(page_url_, Referrer(), this, save_source,
+ FrameTreeNode::kFrameTreeNodeInvalidId);
// Add this item to waiting list.
waiting_item_queue_.push_back(save_item);
all_save_items_count_ = 1;
@@ -378,12 +373,10 @@ void SavePackage::OnMHTMLGenerated(int64_t size) {
// TODO(rdsmith/benjhayden): Integrate canceling on DownloadItem
// with SavePackage flow.
if (download_->GetState() == DownloadItem::IN_PROGRESS) {
- download_->SetTotalBytes(size);
- download_->DestinationUpdate(size, 0, std::string());
// Must call OnAllDataSaved here in order for
// GDataDownloadObserver::ShouldUpload() to return true.
// ShouldCompleteDownload() may depend on the gdata uploader to finish.
- download_->OnAllDataSaved(DownloadItem::kEmptyFileHash);
+ download_->OnAllDataSaved(size, scoped_ptr<crypto::SecureHash>());
}
if (!download_manager_->GetDelegate()) {
@@ -555,7 +548,7 @@ bool SavePackage::GenerateFileName(const std::string& disposition,
// We have received a message from SaveFileManager about a new saving job. We
// find a SaveItem and store it in our in_progress list.
void SavePackage::StartSave(const SaveFileCreateInfo* info) {
- DCHECK(info && !info->url.is_empty());
+ DCHECK(info);
SaveItemIdMap::iterator it = in_progress_items_.find(info->save_item_id);
if (it == in_progress_items_.end()) {
@@ -788,9 +781,9 @@ void SavePackage::Finish() {
// with SavePackage flow.
if (download_->GetState() == DownloadItem::IN_PROGRESS) {
if (save_type_ != SAVE_PAGE_TYPE_AS_MHTML) {
- download_->DestinationUpdate(
- all_save_items_count_, CurrentSpeed(), std::string());
- download_->OnAllDataSaved(DownloadItem::kEmptyFileHash);
+ download_->DestinationUpdate(all_save_items_count_, CurrentSpeed());
+ download_->OnAllDataSaved(all_save_items_count_,
+ scoped_ptr<crypto::SecureHash>());
}
download_->MarkAsComplete();
}
@@ -821,8 +814,7 @@ void SavePackage::SaveFinished(SaveItemId save_item_id,
// TODO(rdsmith/benjhayden): Integrate canceling on DownloadItem
// with SavePackage flow.
if (download_ && (download_->GetState() == DownloadItem::IN_PROGRESS)) {
- download_->DestinationUpdate(
- completed_count(), CurrentSpeed(), std::string());
+ download_->DestinationUpdate(completed_count(), CurrentSpeed());
}
if (save_item->save_source() == SaveFileCreateInfo::SAVE_FILE_FROM_DOM &&
@@ -974,18 +966,28 @@ void SavePackage::GetSerializedHtmlWithLocalLinks() {
if (successful_started_items_count != in_process_count())
return;
- // Ask all frames for their serialized data.
+ // Try to serialize all the frames gathered during GetSavableResourceLinks.
DCHECK_EQ(0, number_of_frames_pending_response_);
FrameTree* frame_tree =
static_cast<RenderFrameHostImpl*>(web_contents()->GetMainFrame())
->frame_tree_node()->frame_tree();
for (const auto& item : frame_tree_node_id_to_save_item_) {
- DCHECK(item.second); // SaveItem* != nullptr.
int frame_tree_node_id = item.first;
+ SaveItem* save_item = item.second;
+ DCHECK(save_item);
+
FrameTreeNode* frame_tree_node = frame_tree->FindByID(frame_tree_node_id);
- if (frame_tree_node) {
+ if (frame_tree_node &&
+ frame_tree_node->current_frame_host()->IsRenderFrameLive()) {
+ // Ask the frame for HTML to be written to the associated SaveItem.
GetSerializedHtmlWithLocalLinksForFrame(frame_tree_node);
number_of_frames_pending_response_++;
+ } else {
+ // Notify SaveFileManager about the failure to save this SaveItem.
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&SaveFileManager::SaveFinished, file_manager_,
+ save_item->id(), id(), false));
}
}
if (number_of_frames_pending_response_ == 0) {
@@ -999,30 +1001,59 @@ void SavePackage::GetSerializedHtmlWithLocalLinksForFrame(
FrameTreeNode* target_tree_node) {
DCHECK(target_tree_node);
int target_frame_tree_node_id = target_tree_node->frame_tree_node_id();
+ RenderFrameHostImpl* target = target_tree_node->current_frame_host();
// Collect all saved success items.
// SECURITY NOTE: We don't send *all* urls / local paths, but only
// those that the given frame had access to already (because it contained
// the savable resources / subframes associated with save items).
std::map<GURL, base::FilePath> url_to_local_path;
+ std::map<int, base::FilePath> routing_id_to_local_path;
auto it = frame_tree_node_id_to_contained_save_items_.find(
target_frame_tree_node_id);
if (it != frame_tree_node_id_to_contained_save_items_.end()) {
for (SaveItem* save_item : it->second) {
- DCHECK(save_item->has_final_name());
+ // Skip items that failed to save.
+ if (!save_item->has_final_name()) {
+ DCHECK_EQ(SaveItem::SaveState::COMPLETE, save_item->state());
+ DCHECK(!save_item->success());
+ continue;
+ }
+
+ // Calculate the relative path for referring to the |save_item|.
base::FilePath local_path(base::FilePath::kCurrentDirectory);
if (target_tree_node->IsMainFrame()) {
local_path = local_path.Append(saved_main_directory_path_.BaseName());
}
local_path = local_path.Append(save_item->file_name());
- url_to_local_path[save_item->url()] = local_path;
+
+ // Insert the link into |url_to_local_path| or |routing_id_to_local_path|.
+ if (save_item->save_source() != SaveFileCreateInfo::SAVE_FILE_FROM_DOM) {
+ DCHECK_EQ(FrameTreeNode::kFrameTreeNodeInvalidId,
+ save_item->frame_tree_node_id());
+ url_to_local_path[save_item->url()] = local_path;
+ } else {
+ FrameTreeNode* save_item_frame_tree_node =
+ target_tree_node->frame_tree()->FindByID(
+ save_item->frame_tree_node_id());
+ if (!save_item_frame_tree_node) {
+ // crbug.com/541354: Raciness when saving a dynamically changing page.
+ continue;
+ }
+
+ int routing_id =
+ save_item_frame_tree_node->render_manager()
+ ->GetRoutingIdForSiteInstance(target->GetSiteInstance());
+ DCHECK_NE(MSG_ROUTING_NONE, routing_id);
+
+ routing_id_to_local_path[routing_id] = local_path;
+ }
}
}
// Ask target frame to serialize itself.
- RenderFrameHostImpl* target = target_tree_node->current_frame_host();
target->Send(new FrameMsg_GetSerializedHtmlWithLocalLinks(
- target->GetRoutingID(), url_to_local_path));
+ target->GetRoutingID(), url_to_local_path, routing_id_to_local_path));
}
// Process the serialized HTML content data of a specified frame
@@ -1069,7 +1100,8 @@ void SavePackage::OnSerializedHtmlWithLocalLinksResponse(
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
base::Bind(&SaveFileManager::UpdateSaveProgress, file_manager_,
- save_item->id(), new_data, static_cast<int>(data.size())));
+ save_item->id(), base::RetainedRef(new_data),
+ static_cast<int>(data.size())));
}
// Current frame is completed saving, call finish in file thread.
@@ -1150,14 +1182,14 @@ void SavePackage::OnSavableResourceLinksResponse(
SaveItem* SavePackage::CreatePendingSaveItem(
int container_frame_tree_node_id,
+ int save_item_frame_tree_node_id,
const GURL& url,
const Referrer& referrer,
SaveFileCreateInfo::SaveFileSource save_source) {
- DCHECK(url.is_valid()); // |url| should be validated by the callers.
-
SaveItem* save_item;
Referrer sanitized_referrer = Referrer::SanitizeForRequest(url, referrer);
- save_item = new SaveItem(url, sanitized_referrer, this, save_source);
+ save_item = new SaveItem(url, sanitized_referrer, this, save_source,
+ save_item_frame_tree_node_id);
waiting_item_queue_.push_back(save_item);
frame_tree_node_id_to_contained_save_items_[container_frame_tree_node_id]
@@ -1167,6 +1199,7 @@ SaveItem* SavePackage::CreatePendingSaveItem(
SaveItem* SavePackage::CreatePendingSaveItemDeduplicatingByUrl(
int container_frame_tree_node_id,
+ int save_item_frame_tree_node_id,
const GURL& url,
const Referrer& referrer,
SaveFileCreateInfo::SaveFileSource save_source) {
@@ -1182,7 +1215,8 @@ SaveItem* SavePackage::CreatePendingSaveItemDeduplicatingByUrl(
frame_tree_node_id_to_contained_save_items_[container_frame_tree_node_id]
.push_back(save_item);
} else {
- save_item = CreatePendingSaveItem(container_frame_tree_node_id, url,
+ save_item = CreatePendingSaveItem(container_frame_tree_node_id,
+ save_item_frame_tree_node_id, url,
referrer, save_source);
url_to_save_item_[url] = save_item;
}
@@ -1199,19 +1233,17 @@ void SavePackage::EnqueueSavableResource(int container_frame_tree_node_id,
SaveFileCreateInfo::SaveFileSource save_source =
url.SchemeIsFile() ? SaveFileCreateInfo::SAVE_FILE_FROM_FILE
: SaveFileCreateInfo::SAVE_FILE_FROM_NET;
- CreatePendingSaveItemDeduplicatingByUrl(container_frame_tree_node_id, url,
- referrer, save_source);
+ CreatePendingSaveItemDeduplicatingByUrl(
+ container_frame_tree_node_id, FrameTreeNode::kFrameTreeNodeInvalidId, url,
+ referrer, save_source);
}
void SavePackage::EnqueueFrame(int container_frame_tree_node_id,
int frame_tree_node_id,
const GURL& frame_original_url) {
- if (!frame_original_url.is_valid())
- return;
-
- SaveItem* save_item =
- CreatePendingSaveItem(container_frame_tree_node_id, frame_original_url,
- Referrer(), SaveFileCreateInfo::SAVE_FILE_FROM_DOM);
+ SaveItem* save_item = CreatePendingSaveItem(
+ container_frame_tree_node_id, frame_tree_node_id, frame_original_url,
+ Referrer(), SaveFileCreateInfo::SAVE_FILE_FROM_DOM);
DCHECK(save_item);
frame_tree_node_id_to_save_item_[frame_tree_node_id] = save_item;
}
@@ -1261,8 +1293,7 @@ void SavePackage::CompleteSavableResourceLinksResponse() {
base::FilePath SavePackage::GetSuggestedNameForSaveAs(
bool can_save_as_complete,
- const std::string& contents_mime_type,
- const std::string& accept_langs) {
+ const std::string& contents_mime_type) {
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
@@ -1274,7 +1305,7 @@ base::FilePath SavePackage::GetSuggestedNameForSaveAs(
// back to a URL, and if it matches the original page URL, we know the page
// had no title (or had a title equal to its URL, which is fine to treat
// similarly).
- if (title_ == url_formatter::FormatUrl(page_url_, accept_langs)) {
+ if (title_ == url_formatter::FormatUrl(page_url_)) {
std::string url_path;
if (!page_url_.SchemeIs(url::kDataScheme)) {
std::vector<std::string> url_parts = base::SplitString(
@@ -1374,23 +1405,17 @@ void SavePackage::GetSaveInfo() {
&download_save_dir, &skip_dir_check);
}
std::string mime_type = web_contents()->GetContentsMimeType();
- std::string accept_languages =
- GetContentClient()->browser()->GetAcceptLangs(
- web_contents()->GetBrowserContext());
-
BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
base::Bind(&SavePackage::CreateDirectoryOnFileThread, this,
- website_save_dir, download_save_dir, skip_dir_check,
- mime_type, accept_languages));
+ website_save_dir, download_save_dir, skip_dir_check, mime_type));
}
void SavePackage::CreateDirectoryOnFileThread(
const base::FilePath& website_save_dir,
const base::FilePath& download_save_dir,
bool skip_dir_check,
- const std::string& mime_type,
- const std::string& accept_langs) {
+ const std::string& mime_type) {
base::FilePath save_dir;
// If the default html/websites save folder doesn't exist...
// We skip the directory check for gdata directories on ChromeOS.
@@ -1408,7 +1433,7 @@ void SavePackage::CreateDirectoryOnFileThread(
bool can_save_as_complete = CanSaveAsComplete(mime_type);
base::FilePath suggested_filename = GetSuggestedNameForSaveAs(
- can_save_as_complete, mime_type, accept_langs);
+ can_save_as_complete, mime_type);
base::FilePath::StringType pure_file_name =
suggested_filename.RemoveExtension().BaseName().value();
base::FilePath::StringType file_name_ext = suggested_filename.Extension();
diff --git a/chromium/content/browser/download/save_package.h b/chromium/content/browser/download/save_package.h
index eabf65717a0..5b0e958c3a0 100644
--- a/chromium/content/browser/download/save_package.h
+++ b/chromium/content/browser/download/save_package.h
@@ -12,9 +12,9 @@
#include <map>
#include <set>
#include <string>
+#include <unordered_map>
#include <vector>
-#include "base/containers/hash_tables.h"
#include "base/files/file_path.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
@@ -206,6 +206,7 @@ class CONTENT_EXPORT SavePackage
// Helper for finding or creating a SaveItem with the given parameters.
SaveItem* CreatePendingSaveItem(
int container_frame_tree_node_id,
+ int save_item_frame_tree_node_id,
const GURL& url,
const Referrer& referrer,
SaveFileCreateInfo::SaveFileSource save_source);
@@ -214,6 +215,7 @@ class CONTENT_EXPORT SavePackage
// creating a SaveItem with the given parameters.
SaveItem* CreatePendingSaveItemDeduplicatingByUrl(
int container_frame_tree_node_id,
+ int save_item_frame_tree_node_id,
const GURL& url,
const Referrer& referrer,
SaveFileCreateInfo::SaveFileSource save_source);
@@ -263,8 +265,7 @@ class CONTENT_EXPORT SavePackage
void CreateDirectoryOnFileThread(const base::FilePath& website_save_dir,
const base::FilePath& download_save_dir,
bool skip_dir_check,
- const std::string& mime_type,
- const std::string& accept_langs);
+ const std::string& mime_type);
void ContinueGetSaveInfo(const base::FilePath& suggested_path,
bool can_save_as_complete);
void OnPathPicked(
@@ -273,7 +274,8 @@ class CONTENT_EXPORT SavePackage
const SavePackageDownloadCreatedCallback& cb);
// Map from SaveItem::id() (aka save_item_id) into a SaveItem.
- typedef base::hash_map<SaveItemId, SaveItem*> SaveItemIdMap;
+ using SaveItemIdMap =
+ std::unordered_map<SaveItemId, SaveItem*, SaveItemId::Hasher>;
// in_progress_items_ is map of all saving job in in-progress state.
SaveItemIdMap in_progress_items_;
// saved_failed_items_ is map of all saving job which are failed.
@@ -302,8 +304,7 @@ class CONTENT_EXPORT SavePackage
// suggested name is determined by the web document's title.
base::FilePath GetSuggestedNameForSaveAs(
bool can_save_as_complete,
- const std::string& contents_mime_type,
- const std::string& accept_langs);
+ const std::string& contents_mime_type);
// Ensures that the file name has a proper extension for HTML by adding ".htm"
// if necessary.
@@ -319,7 +320,7 @@ class CONTENT_EXPORT SavePackage
static const base::FilePath::CharType* ExtensionForMimeType(
const std::string& contents_mime_type);
- typedef std::deque<SaveItem*> SaveItemQueue;
+ using SaveItemQueue = std::deque<SaveItem*>;
// A queue for items we are about to start saving.
SaveItemQueue waiting_item_queue_;
@@ -333,21 +334,22 @@ class CONTENT_EXPORT SavePackage
// OnSerializedHtmlWithLocalLinksResponse) to the right SaveItem.
// Note that |frame_tree_node_id_to_save_item_| does NOT own SaveItems - they
// remain owned by waiting_item_queue_, in_progress_items_, etc.
- base::hash_map<int, SaveItem*> frame_tree_node_id_to_save_item_;
+ std::unordered_map<int, SaveItem*> frame_tree_node_id_to_save_item_;
// Used to limit which local paths get exposed to which frames
// (i.e. to prevent information disclosure to oop frames).
// Note that |frame_tree_node_id_to_contained_save_items_| does NOT own
// SaveItems - they remain owned by waiting_item_queue_, in_progress_items_,
// etc.
- base::hash_map<int, std::vector<SaveItem*>>
+ std::unordered_map<int, std::vector<SaveItem*>>
frame_tree_node_id_to_contained_save_items_;
// Number of frames that we still need to get a response from.
int number_of_frames_pending_response_;
// saved_success_items_ is map of all saving job which are successfully saved.
- base::hash_map<SaveItemId, SaveItem*> saved_success_items_;
+ std::unordered_map<SaveItemId, SaveItem*, SaveItemId::Hasher>
+ saved_success_items_;
// Non-owning pointer for handling file writing on the file thread.
SaveFileManager* file_manager_;
@@ -392,7 +394,8 @@ class CONTENT_EXPORT SavePackage
// This set is used to eliminate duplicated file names in saving directory.
FileNameSet file_name_set_;
- typedef base::hash_map<base::FilePath::StringType, uint32_t> FileNameCountMap;
+ using FileNameCountMap =
+ std::unordered_map<base::FilePath::StringType, uint32_t>;
// This map is used to track serial number for specified filename.
FileNameCountMap file_name_count_map_;
diff --git a/chromium/content/browser/download/save_package_unittest.cc b/chromium/content/browser/download/save_package_unittest.cc
index fc89b6d1806..c426772a820 100644
--- a/chromium/content/browser/download/save_package_unittest.cc
+++ b/chromium/content/browser/download/save_package_unittest.cc
@@ -406,8 +406,7 @@ TEST_F(SavePackageTest, MAYBE_TestSuggestedSaveNames) {
save_package->title_ = kSuggestedSaveNames[i].page_title;
base::FilePath save_name = save_package->GetSuggestedNameForSaveAs(
- kSuggestedSaveNames[i].ensure_html_extension,
- std::string(), std::string());
+ kSuggestedSaveNames[i].ensure_html_extension, std::string());
EXPECT_EQ(kSuggestedSaveNames[i].expected_name, save_name.value()) <<
"Test case " << i;
}
diff --git a/chromium/content/browser/download/save_types.cc b/chromium/content/browser/download/save_types.cc
index 9c4972a8854..0dd760562c1 100644
--- a/chromium/content/browser/download/save_types.cc
+++ b/chromium/content/browser/download/save_types.cc
@@ -45,6 +45,9 @@ SaveFileCreateInfo::SaveFileCreateInfo(const GURL& url,
total_bytes(total_bytes),
save_source(SaveFileCreateInfo::SAVE_FILE_FROM_NET) {}
+SaveFileCreateInfo::SaveFileCreateInfo(const SaveFileCreateInfo& other) =
+ default;
+
SaveFileCreateInfo::~SaveFileCreateInfo() {}
} // namespace content
diff --git a/chromium/content/browser/download/save_types.h b/chromium/content/browser/download/save_types.h
index 83d890b8dc9..9d61a9a70a0 100644
--- a/chromium/content/browser/download/save_types.h
+++ b/chromium/content/browser/download/save_types.h
@@ -13,16 +13,16 @@
#include <vector>
#include "base/files/file_path.h"
-#include "content/common/id_type.h"
+#include "gpu/command_buffer/common/id_type.h"
#include "url/gurl.h"
namespace content {
class SavePackage;
-using SavePackageId = IdType32<SavePackage>;
+using SavePackageId = gpu::IdType32<SavePackage>;
class SaveItem;
-using SaveItemId = IdType32<SaveItem>;
+using SaveItemId = gpu::IdType32<SaveItem>;
// Map from save_item_id into final file path.
using FinalNamesMap = std::map<SaveItemId, base::FilePath>;
@@ -63,6 +63,8 @@ struct SaveFileCreateInfo {
const std::string& content_disposition,
int64_t total_bytes);
+ SaveFileCreateInfo(const SaveFileCreateInfo& other);
+
~SaveFileCreateInfo();
// SaveItem fields.
diff --git a/chromium/content/browser/download/url_downloader.cc b/chromium/content/browser/download/url_downloader.cc
index b178a1d4b26..274de905d8c 100644
--- a/chromium/content/browser/download/url_downloader.cc
+++ b/chromium/content/browser/download/url_downloader.cc
@@ -60,7 +60,6 @@ class UrlDownloader::RequestHandle : public DownloadRequestHandleInterface {
downloader_task_runner_->PostTask(
FROM_HERE, base::Bind(&UrlDownloader::CancelRequest, downloader_));
}
- std::string DebugString() const override { return std::string(); }
private:
base::WeakPtr<UrlDownloader> downloader_;
@@ -74,62 +73,32 @@ class UrlDownloader::RequestHandle : public DownloadRequestHandleInterface {
scoped_ptr<UrlDownloader> UrlDownloader::BeginDownload(
base::WeakPtr<DownloadManagerImpl> download_manager,
scoped_ptr<net::URLRequest> request,
- const Referrer& referrer,
- bool prefer_cache,
- scoped_ptr<DownloadSaveInfo> save_info,
- uint32_t download_id,
- const DownloadUrlParameters::OnStartedCallback& started_callback) {
+ const Referrer& referrer) {
if (!referrer.url.is_valid())
request->SetReferrer(std::string());
else
request->SetReferrer(referrer.url.spec());
- int extra_load_flags = net::LOAD_NORMAL;
- if (prefer_cache) {
- // If there is upload data attached, only retrieve from cache because there
- // is no current mechanism to prompt the user for their consent for a
- // re-post. For GETs, try to retrieve data from the cache and skip
- // validating the entry if present.
- if (request->get_upload() != NULL)
- extra_load_flags |= net::LOAD_ONLY_FROM_CACHE;
- else
- extra_load_flags |= net::LOAD_PREFERRING_CACHE;
- } else {
- extra_load_flags |= net::LOAD_DISABLE_CACHE;
- }
- request->SetLoadFlags(request->load_flags() | extra_load_flags);
-
if (request->url().SchemeIs(url::kBlobScheme))
return nullptr;
// From this point forward, the |UrlDownloader| is responsible for
// |started_callback|.
scoped_ptr<UrlDownloader> downloader(
- new UrlDownloader(std::move(request), download_manager,
- std::move(save_info), download_id, started_callback));
+ new UrlDownloader(std::move(request), download_manager));
downloader->Start();
return downloader;
}
-UrlDownloader::UrlDownloader(
- scoped_ptr<net::URLRequest> request,
- base::WeakPtr<DownloadManagerImpl> manager,
- scoped_ptr<DownloadSaveInfo> save_info,
- uint32_t download_id,
- const DownloadUrlParameters::OnStartedCallback& on_started_callback)
+UrlDownloader::UrlDownloader(scoped_ptr<net::URLRequest> request,
+ base::WeakPtr<DownloadManagerImpl> manager)
: request_(std::move(request)),
manager_(manager),
- download_id_(download_id),
- on_started_callback_(on_started_callback),
- handler_(
- request_.get(),
- std::move(save_info),
- base::Bind(&UrlDownloader::ResumeReading, base::Unretained(this))),
+ core_(request_.get(), this),
weak_ptr_factory_(this) {}
UrlDownloader::~UrlDownloader() {
- CallStartedCallbackOnFailure(DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
}
void UrlDownloader::Start() {
@@ -146,7 +115,15 @@ void UrlDownloader::OnReceivedRedirect(net::URLRequest* request,
const net::RedirectInfo& redirect_info,
bool* defer_redirect) {
DVLOG(1) << "OnReceivedRedirect: " << request_->url().spec();
- request_->CancelWithError(net::ERR_ABORTED);
+
+ // We are going to block redirects even if DownloadRequestCore allows it. No
+ // redirects are expected for download requests that are made without a
+ // renderer, which are currently exclusively resumption requests. Since there
+ // is no security policy being applied here, it's safer to block redirects and
+ // revisit if some previously unknown legitimate use case arises for redirects
+ // while resuming.
+ core_.OnWillAbort(DOWNLOAD_INTERRUPT_REASON_SERVER_UNREACHABLE);
+ request_->CancelWithError(net::ERR_UNSAFE_REDIRECT);
}
void UrlDownloader::OnResponseStarted(net::URLRequest* request) {
@@ -157,22 +134,7 @@ void UrlDownloader::OnResponseStarted(net::URLRequest* request) {
return;
}
- scoped_ptr<DownloadCreateInfo> create_info;
- scoped_ptr<ByteStreamReader> stream_reader;
-
- handler_.OnResponseStarted(&create_info, &stream_reader);
-
- create_info->download_id = download_id_;
- create_info->request_handle.reset(
- new RequestHandle(weak_ptr_factory_.GetWeakPtr(), manager_,
- base::SequencedTaskRunnerHandle::Get()));
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&DownloadManagerImpl::StartDownload, manager_,
- base::Passed(&create_info), base::Passed(&stream_reader),
- base::ResetAndReturn(&on_started_callback_)));
-
- if (request_->status().is_success())
+ if (core_.OnResponseStarted(std::string()))
StartReading(false); // Read the first chunk.
else
ResponseCompleted();
@@ -186,7 +148,7 @@ void UrlDownloader::StartReading(bool is_continuation) {
// doesn't use the buffer.
scoped_refptr<net::IOBuffer> buf;
int buf_size;
- if (!handler_.OnWillRead(&buf, &buf_size, -1)) {
+ if (!core_.OnWillRead(&buf, &buf_size, -1)) {
request_->CancelWithError(net::ERR_ABORTED);
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(&UrlDownloader::ResponseCompleted,
@@ -229,7 +191,7 @@ void UrlDownloader::OnReadCompleted(net::URLRequest* request, int bytes_read) {
DCHECK(request_->status().is_success());
bool defer = false;
- if (!handler_.OnReadCompleted(bytes_read, &defer)) {
+ if (!core_.OnReadCompleted(bytes_read, &defer)) {
request_->CancelWithError(net::ERR_ABORTED);
return;
} else if (defer) {
@@ -251,38 +213,43 @@ void UrlDownloader::OnReadCompleted(net::URLRequest* request, int bytes_read) {
void UrlDownloader::ResponseCompleted() {
DVLOG(1) << "ResponseCompleted: " << request_->url().spec();
- handler_.OnResponseCompleted(request_->status());
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&DownloadManagerImpl::RemoveUrlDownloader, manager_, this));
+ core_.OnResponseCompleted(request_->status());
+ Destroy();
}
-void UrlDownloader::ResumeReading() {
- if (request_->status().is_success()) {
- StartReading(false); // Read the next chunk (OK to complete synchronously).
- } else {
- ResponseCompleted();
- }
+void UrlDownloader::OnStart(
+ scoped_ptr<DownloadCreateInfo> create_info,
+ scoped_ptr<ByteStreamReader> stream_reader,
+ const DownloadUrlParameters::OnStartedCallback& callback) {
+ create_info->request_handle.reset(
+ new RequestHandle(weak_ptr_factory_.GetWeakPtr(), manager_,
+ base::SequencedTaskRunnerHandle::Get()));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&DownloadManagerImpl::StartDownload,
+ manager_, base::Passed(&create_info),
+ base::Passed(&stream_reader), callback));
}
-void UrlDownloader::CallStartedCallbackOnFailure(
- DownloadInterruptReason result) {
- if (on_started_callback_.is_null())
- return;
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(base::ResetAndReturn(&on_started_callback_), nullptr, result));
+void UrlDownloader::OnReadyToRead() {
+ if (request_->status().is_success())
+ StartReading(false); // Read the next chunk (OK to complete synchronously).
+ else
+ ResponseCompleted();
}
void UrlDownloader::PauseRequest() {
- handler_.PauseRequest();
+ core_.PauseRequest();
}
void UrlDownloader::ResumeRequest() {
- handler_.ResumeRequest();
+ core_.ResumeRequest();
}
void UrlDownloader::CancelRequest() {
+ Destroy();
+}
+
+void UrlDownloader::Destroy() {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&DownloadManagerImpl::RemoveUrlDownloader, manager_, this));
diff --git a/chromium/content/browser/download/url_downloader.h b/chromium/content/browser/download/url_downloader.h
index 787feb4c91b..475d97bfbc6 100644
--- a/chromium/content/browser/download/url_downloader.h
+++ b/chromium/content/browser/download/url_downloader.h
@@ -10,6 +10,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/download/download_request_core.h"
+#include "content/public/browser/download_interrupt_reasons.h"
#include "content/public/browser/download_save_info.h"
#include "content/public/browser/download_url_parameters.h"
#include "content/public/common/referrer.h"
@@ -17,26 +18,26 @@
#include "net/url_request/url_request.h"
namespace content {
+class ByteStreamReader;
+struct DownloadCreateInfo;
class DownloadManagerImpl;
-class UrlDownloader : public net::URLRequest::Delegate {
+class UrlDownloader : public net::URLRequest::Delegate,
+ public DownloadRequestCore::Delegate {
public:
- UrlDownloader(
- scoped_ptr<net::URLRequest> request,
- base::WeakPtr<DownloadManagerImpl> manager,
- scoped_ptr<DownloadSaveInfo> save_info,
- uint32_t download_id,
- const DownloadUrlParameters::OnStartedCallback& on_started_callback);
+ UrlDownloader(scoped_ptr<net::URLRequest> request,
+ base::WeakPtr<DownloadManagerImpl> manager);
~UrlDownloader() override;
static scoped_ptr<UrlDownloader> BeginDownload(
base::WeakPtr<DownloadManagerImpl> download_manager,
scoped_ptr<net::URLRequest> request,
- const Referrer& referrer,
- bool prefer_cache,
- scoped_ptr<DownloadSaveInfo> save_info,
- uint32_t download_id,
- const DownloadUrlParameters::OnStartedCallback& started_callback);
+ const Referrer& referrer);
+
+ private:
+ class RequestHandle;
+
+ void Start();
// URLRequest::Delegate:
void OnReceivedRedirect(net::URLRequest* request,
@@ -48,24 +49,25 @@ class UrlDownloader : public net::URLRequest::Delegate {
void StartReading(bool is_continuation);
void ResponseCompleted();
- void Start();
- void ResumeReading();
-
- void CallStartedCallbackOnFailure(DownloadInterruptReason result);
-
- private:
- class RequestHandle;
+ // DownloadRequestCore::Delegate
+ void OnStart(
+ scoped_ptr<DownloadCreateInfo> download_create_info,
+ scoped_ptr<ByteStreamReader> stream_reader,
+ const DownloadUrlParameters::OnStartedCallback& callback) override;
+ void OnReadyToRead() override;
void PauseRequest();
void ResumeRequest();
void CancelRequest();
+ // Called when the UrlDownloader is done with the request. Posts a task to
+ // remove itself from its download manager, which in turn would cause the
+ // UrlDownloader to be freed.
+ void Destroy();
+
scoped_ptr<net::URLRequest> request_;
base::WeakPtr<DownloadManagerImpl> manager_;
- uint32_t download_id_;
- DownloadUrlParameters::OnStartedCallback on_started_callback_;
-
- DownloadRequestCore handler_;
+ DownloadRequestCore core_;
base::WeakPtrFactory<UrlDownloader> weak_ptr_factory_;
};
diff --git a/chromium/content/browser/fileapi/blob_reader_unittest.cc b/chromium/content/browser/fileapi/blob_reader_unittest.cc
index d16b552d392..1c0ae10a593 100644
--- a/chromium/content/browser/fileapi/blob_reader_unittest.cc
+++ b/chromium/content/browser/fileapi/blob_reader_unittest.cc
@@ -327,8 +327,7 @@ class BlobReaderTest : public ::testing::Test {
void InitializeReader(BlobDataBuilder* builder) {
blob_handle_ = builder ? context_.AddFinishedBlob(builder) : nullptr;
provider_ = new MockFileStreamReaderProvider();
- scoped_ptr<BlobReader::FileStreamReaderProvider> temp_ptr(provider_);
- reader_.reset(new BlobReader(blob_handle_.get(), std::move(temp_ptr),
+ reader_.reset(new BlobReader(blob_handle_.get(), make_scoped_ptr(provider_),
message_loop_.task_runner().get()));
}
@@ -395,8 +394,6 @@ class BlobReaderTest : public ::testing::Test {
DISALLOW_COPY_AND_ASSIGN(BlobReaderTest);
};
-namespace {
-
TEST_F(BlobReaderTest, BasicMemory) {
BlobDataBuilder b("uuid");
const std::string kData("Hello!!!");
@@ -1113,5 +1110,52 @@ TEST_F(BlobReaderTest, RangeError) {
EXPECT_EQ(net::ERR_FILE_NOT_FOUND, reader_->net_error());
}
-} // namespace
+TEST_F(BlobReaderTest, HandleBeforeAsyncCancel) {
+ const std::string kUuid("uuid1");
+
+ context_.CreatePendingBlob(kUuid, "", "");
+ blob_handle_ = context_.GetBlobDataFromUUID(kUuid);
+ provider_ = new MockFileStreamReaderProvider();
+ reader_.reset(new BlobReader(blob_handle_.get(), make_scoped_ptr(provider_),
+ message_loop_.task_runner().get()));
+ int size_result = -1;
+ EXPECT_EQ(BlobReader::Status::IO_PENDING,
+ reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+ context_.CancelPendingBlob(kUuid, IPCBlobCreationCancelCode::UNKNOWN);
+ message_loop_.RunUntilIdle();
+ EXPECT_EQ(net::ERR_FAILED, size_result);
+}
+
+TEST_F(BlobReaderTest, ReadFromIncompleteBlob) {
+ const std::string kUuid("uuid1");
+ const std::string kData("Hello!!!");
+ const size_t kDataSize = 8ul;
+
+ BlobDataBuilder b(kUuid);
+ b.AppendData(kData);
+ context_.CreatePendingBlob(kUuid, "", "");
+ blob_handle_ = context_.GetBlobDataFromUUID(kUuid);
+ provider_ = new MockFileStreamReaderProvider();
+ reader_.reset(new BlobReader(blob_handle_.get(), make_scoped_ptr(provider_),
+ message_loop_.task_runner().get()));
+ int size_result = -1;
+ EXPECT_EQ(BlobReader::Status::IO_PENDING,
+ reader_->CalculateSize(base::Bind(&SetValue<int>, &size_result)));
+ context_.CompletePendingBlob(b);
+ message_loop_.RunUntilIdle();
+ CheckSizeCalculatedAsynchronously(kDataSize, size_result);
+ scoped_refptr<net::IOBuffer> buffer(new net::IOBuffer(kDataSize));
+
+ int bytes_read = 0;
+ int async_bytes_read = 0;
+ EXPECT_EQ(BlobReader::Status::DONE,
+ reader_->Read(buffer.get(), kDataSize, &bytes_read,
+ base::Bind(&SetValue<int>, &async_bytes_read)));
+ EXPECT_EQ(net::OK, reader_->net_error());
+ EXPECT_EQ(kDataSize, static_cast<size_t>(bytes_read));
+ EXPECT_EQ(0, async_bytes_read);
+ EXPECT_EQ(kData, std::string(buffer->data(), kDataSize));
+ EXPECT_EQ(net::OK, size_result);
+}
+
} // namespace storage
diff --git a/chromium/content/browser/fileapi/blob_storage_context_unittest.cc b/chromium/content/browser/fileapi/blob_storage_context_unittest.cc
index 72df9841708..74e10d0493a 100644
--- a/chromium/content/browser/fileapi/blob_storage_context_unittest.cc
+++ b/chromium/content/browser/fileapi/blob_storage_context_unittest.cc
@@ -9,32 +9,37 @@
#include <limits>
#include <string>
+#include "base/files/file.h"
#include "base/files/file_path.h"
#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 "base/time/time.h"
-#include "content/browser/fileapi/blob_storage_host.h"
+#include "content/browser/blob_storage/blob_dispatcher_host.h"
+#include "content/browser/fileapi/chrome_blob_storage_context.h"
+#include "content/public/test/test_browser_context.h"
#include "net/base/io_buffer.h"
#include "net/base/test_completion_callback.h"
#include "net/disk_cache/disk_cache.h"
+#include "storage/browser/blob/blob_async_builder_host.h"
#include "storage/browser/blob/blob_data_builder.h"
#include "storage/browser/blob/blob_data_handle.h"
#include "storage/browser/blob/blob_data_item.h"
#include "storage/browser/blob/blob_data_snapshot.h"
+#include "storage/browser/blob/blob_transport_result.h"
+#include "storage/common/blob_storage/blob_item_bytes_request.h"
+#include "storage/common/blob_storage/blob_item_bytes_response.h"
#include "testing/gtest/include/gtest/gtest.h"
-using storage::BlobDataBuilder;
-using storage::BlobDataHandle;
-using storage::BlobDataItem;
-using storage::BlobDataSnapshot;
-using storage::BlobStorageContext;
-using storage::DataElement;
+using RequestMemoryCallback =
+ storage::BlobAsyncBuilderHost::RequestMemoryCallback;
-namespace content {
+namespace storage {
namespace {
+const char kContentType[] = "text/plain";
+const char kContentDisposition[] = "content_disposition";
const int kTestDiskCacheStreamIndex = 0;
// Our disk cache tests don't need a real data handle since the tests themselves
@@ -74,97 +79,89 @@ disk_cache::ScopedEntryPtr CreateDiskCacheEntry(disk_cache::Backend* cache,
return entry;
}
-void SetupBasicBlob(BlobStorageHost* host, const std::string& id) {
- EXPECT_TRUE(host->StartBuildingBlob(id));
- DataElement item;
- item.SetToBytes("1", 1);
- EXPECT_TRUE(host->AppendBlobDataItem(id, item));
- EXPECT_TRUE(host->FinishBuildingBlob(id, "text/plain"));
- EXPECT_FALSE(host->StartBuildingBlob(id));
-}
} // namespace
-TEST(BlobStorageContextTest, IncrementDecrementRef) {
- BlobStorageContext context;
- BlobStorageHost host(&context);
+class BlobStorageContextTest : public testing::Test {
+ protected:
+ BlobStorageContextTest() {}
+ ~BlobStorageContextTest() override {}
+
+ scoped_ptr<BlobDataHandle> SetupBasicBlob(const std::string& id) {
+ BlobDataBuilder builder(id);
+ builder.AppendData("1", 1);
+ builder.set_content_type("text/plain");
+ return context_.AddFinishedBlob(builder);
+ }
+
+ BlobStorageContext context_;
+};
+
+TEST_F(BlobStorageContextTest, IncrementDecrementRef) {
base::MessageLoop fake_io_message_loop;
// Build up a basic blob.
const std::string kId("id");
- SetupBasicBlob(&host, kId);
+ scoped_ptr<BlobDataHandle> blob_data_handle = SetupBasicBlob(kId);
- // Make sure it's there, finish building implies a ref of one.
- scoped_ptr<BlobDataHandle> blob_data_handle;
- blob_data_handle = context.GetBlobDataFromUUID(kId);
+ // Do an extra increment to keep it around after we kill the handle.
+ context_.IncrementBlobRefCount(kId);
+ context_.IncrementBlobRefCount(kId);
+ context_.DecrementBlobRefCount(kId);
+ blob_data_handle = context_.GetBlobDataFromUUID(kId);
EXPECT_TRUE(blob_data_handle);
blob_data_handle.reset();
base::RunLoop().RunUntilIdle();
- // Make sure its still there after inc/dec.
- EXPECT_TRUE(host.IncrementBlobRefCount(kId));
- EXPECT_TRUE(host.DecrementBlobRefCount(kId));
- blob_data_handle = context.GetBlobDataFromUUID(kId);
- EXPECT_TRUE(blob_data_handle);
- blob_data_handle.reset();
- base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(context_.registry().HasEntry(kId));
+ context_.DecrementBlobRefCount(kId);
+ EXPECT_FALSE(context_.registry().HasEntry(kId));
// Make sure it goes away in the end.
- EXPECT_TRUE(host.DecrementBlobRefCount(kId));
- blob_data_handle = context.GetBlobDataFromUUID(kId);
+ blob_data_handle = context_.GetBlobDataFromUUID(kId);
EXPECT_FALSE(blob_data_handle);
- EXPECT_FALSE(host.DecrementBlobRefCount(kId));
- EXPECT_FALSE(host.IncrementBlobRefCount(kId));
}
-TEST(BlobStorageContextTest, CancelBuildingBlob) {
- BlobStorageContext context;
- BlobStorageHost host(&context);
+TEST_F(BlobStorageContextTest, OnCancelBuildingBlob) {
base::MessageLoop fake_io_message_loop;
// Build up a basic blob.
const std::string kId("id");
- EXPECT_TRUE(host.StartBuildingBlob(kId));
- DataElement item;
- item.SetToBytes("1", 1);
- EXPECT_TRUE(host.AppendBlobDataItem(kId, item));
- EXPECT_TRUE(host.CancelBuildingBlob(kId));
- EXPECT_FALSE(host.FinishBuildingBlob(kId, "text/plain"));
- EXPECT_TRUE(host.StartBuildingBlob(kId));
+ context_.CreatePendingBlob(kId, std::string(kContentType),
+ std::string(kContentDisposition));
+ EXPECT_TRUE(context_.IsBeingBuilt(kId));
+ context_.CancelPendingBlob(kId, IPCBlobCreationCancelCode::OUT_OF_MEMORY);
+ EXPECT_TRUE(context_.registry().HasEntry(kId));
+ EXPECT_FALSE(context_.IsBeingBuilt(kId));
+ EXPECT_TRUE(context_.IsBroken(kId));
}
-TEST(BlobStorageContextTest, BlobDataHandle) {
- BlobStorageContext context;
- BlobStorageHost host(&context);
+TEST_F(BlobStorageContextTest, BlobDataHandle) {
base::MessageLoop fake_io_message_loop;
// Build up a basic blob.
const std::string kId("id");
- SetupBasicBlob(&host, kId);
-
- // Get a handle to it.
- scoped_ptr<BlobDataHandle> blob_data_handle =
- context.GetBlobDataFromUUID(kId);
+ scoped_ptr<BlobDataHandle> blob_data_handle = SetupBasicBlob(kId);
EXPECT_TRUE(blob_data_handle);
- // Drop the host's ref to it.
- EXPECT_TRUE(host.DecrementBlobRefCount(kId));
-
- // Should still be there due to the handle.
- scoped_ptr<BlobDataHandle> another_handle =
- context.GetBlobDataFromUUID(kId);
+ // Get another handle
+ scoped_ptr<BlobDataHandle> another_handle = context_.GetBlobDataFromUUID(kId);
EXPECT_TRUE(another_handle);
// Should disappear after dropping both handles.
blob_data_handle.reset();
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(context_.registry().HasEntry(kId));
+
another_handle.reset();
base::RunLoop().RunUntilIdle();
- blob_data_handle = context.GetBlobDataFromUUID(kId);
+ blob_data_handle = context_.GetBlobDataFromUUID(kId);
EXPECT_FALSE(blob_data_handle);
}
-TEST(BlobStorageContextTest, MemoryUsage) {
+TEST_F(BlobStorageContextTest, MemoryUsage) {
const std::string kId1("id1");
const std::string kId2("id2");
@@ -181,27 +178,30 @@ TEST(BlobStorageContextTest, MemoryUsage) {
builder2.AppendBlob(kId1);
builder2.AppendBlob(kId1);
- BlobStorageContext context;
- EXPECT_EQ(0lu, context.memory_usage());
+ EXPECT_EQ(0lu, context_.memory_usage());
scoped_ptr<BlobDataHandle> blob_data_handle =
- context.AddFinishedBlob(&builder1);
- EXPECT_EQ(10lu, context.memory_usage());
+ context_.AddFinishedBlob(&builder1);
+ EXPECT_EQ(10lu, context_.memory_usage());
scoped_ptr<BlobDataHandle> blob_data_handle2 =
- context.AddFinishedBlob(&builder2);
- EXPECT_EQ(10lu, context.memory_usage());
+ context_.AddFinishedBlob(&builder2);
+ EXPECT_EQ(10lu, context_.memory_usage());
+
+ EXPECT_EQ(2u, context_.registry().blob_count());
blob_data_handle.reset();
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(10lu, context.memory_usage());
+ EXPECT_EQ(10lu, context_.memory_usage());
+ EXPECT_EQ(1u, context_.registry().blob_count());
blob_data_handle2.reset();
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(0lu, context.memory_usage());
+ EXPECT_EQ(0lu, context_.memory_usage());
+ EXPECT_EQ(0u, context_.registry().blob_count());
}
-TEST(BlobStorageContextTest, AddFinishedBlob) {
+TEST_F(BlobStorageContextTest, AddFinishedBlob) {
const std::string kId1("id1");
const std::string kId2("id12");
const std::string kId2Prime("id2.prime");
@@ -222,9 +222,9 @@ TEST(BlobStorageContextTest, AddFinishedBlob) {
BlobStorageContext context;
scoped_ptr<BlobDataHandle> blob_data_handle =
- context.AddFinishedBlob(&builder1);
+ context_.AddFinishedBlob(&builder1);
scoped_ptr<BlobDataHandle> blob_data_handle2 =
- context.AddFinishedBlob(&builder2);
+ context_.AddFinishedBlob(&builder2);
ASSERT_TRUE(blob_data_handle);
ASSERT_TRUE(blob_data_handle2);
@@ -237,7 +237,7 @@ TEST(BlobStorageContextTest, AddFinishedBlob) {
base::RunLoop().RunUntilIdle();
- blob_data_handle = context.GetBlobDataFromUUID(kId1);
+ blob_data_handle = context_.GetBlobDataFromUUID(kId1);
EXPECT_FALSE(blob_data_handle);
EXPECT_TRUE(blob_data_handle2);
data2 = blob_data_handle2->CreateSnapshot();
@@ -248,11 +248,11 @@ TEST(BlobStorageContextTest, AddFinishedBlob) {
builder3.AppendBlob(kId2);
builder3.AppendBlob(kId2);
scoped_ptr<BlobDataHandle> blob_data_handle3 =
- context.AddFinishedBlob(&builder3);
+ context_.AddFinishedBlob(&builder3);
blob_data_handle2.reset();
base::RunLoop().RunUntilIdle();
- blob_data_handle2 = context.GetBlobDataFromUUID(kId2);
+ blob_data_handle2 = context_.GetBlobDataFromUUID(kId2);
EXPECT_FALSE(blob_data_handle2);
EXPECT_TRUE(blob_data_handle3);
scoped_ptr<BlobDataSnapshot> data3 = blob_data_handle3->CreateSnapshot();
@@ -270,7 +270,7 @@ TEST(BlobStorageContextTest, AddFinishedBlob) {
base::RunLoop().RunUntilIdle();
}
-TEST(BlobStorageContextTest, AddFinishedBlob_LargeOffset) {
+TEST_F(BlobStorageContextTest, AddFinishedBlob_LargeOffset) {
// A value which does not fit in a 4-byte data type. Used to confirm that
// large values are supported on 32-bit Chromium builds. Regression test for:
// crbug.com/458122.
@@ -287,11 +287,10 @@ TEST(BlobStorageContextTest, AddFinishedBlob_LargeOffset) {
BlobDataBuilder builder2(kId2);
builder2.AppendBlob(kId1, kLargeSize - kBlobLength, kBlobLength);
- BlobStorageContext context;
scoped_ptr<BlobDataHandle> blob_data_handle1 =
- context.AddFinishedBlob(&builder1);
+ context_.AddFinishedBlob(&builder1);
scoped_ptr<BlobDataHandle> blob_data_handle2 =
- context.AddFinishedBlob(&builder2);
+ context_.AddFinishedBlob(&builder2);
ASSERT_TRUE(blob_data_handle1);
ASSERT_TRUE(blob_data_handle2);
@@ -306,14 +305,13 @@ TEST(BlobStorageContextTest, AddFinishedBlob_LargeOffset) {
base::RunLoop().RunUntilIdle();
}
-TEST(BlobStorageContextTest, BuildDiskCacheBlob) {
+TEST_F(BlobStorageContextTest, BuildDiskCacheBlob) {
base::MessageLoop fake_io_message_loop;
scoped_refptr<BlobDataBuilder::DataHandle>
data_handle = new EmptyDataHandle();
{
- scoped_ptr<BlobStorageContext> context(new BlobStorageContext);
- BlobStorageHost host(context.get());
+ BlobStorageContext context;
scoped_ptr<disk_cache::Backend> cache = CreateInMemoryDiskCache();
ASSERT_TRUE(cache);
@@ -333,7 +331,7 @@ TEST(BlobStorageContextTest, BuildDiskCacheBlob) {
data_handle, entry.get(), kTestDiskCacheStreamIndex);
scoped_ptr<BlobDataHandle> blob_data_handle =
- context->AddFinishedBlob(&builder);
+ context.AddFinishedBlob(&builder);
scoped_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot();
EXPECT_EQ(*data, builder);
EXPECT_FALSE(data_handle->HasOneRef())
@@ -344,7 +342,7 @@ TEST(BlobStorageContextTest, BuildDiskCacheBlob) {
base::RunLoop().RunUntilIdle();
}
-TEST(BlobStorageContextTest, CompoundBlobs) {
+TEST_F(BlobStorageContextTest, CompoundBlobs) {
const std::string kId1("id1");
const std::string kId2("id2");
const std::string kId3("id3");
@@ -390,7 +388,7 @@ TEST(BlobStorageContextTest, CompoundBlobs) {
scoped_ptr<BlobDataHandle> blob_data_handle;
// Test a blob referring to only data and a file.
- blob_data_handle = context.AddFinishedBlob(&blob_data1);
+ blob_data_handle = context_.AddFinishedBlob(&blob_data1);
ASSERT_TRUE(blob_data_handle);
scoped_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot();
@@ -398,14 +396,14 @@ TEST(BlobStorageContextTest, CompoundBlobs) {
EXPECT_EQ(*data, blob_data1);
// Test a blob composed in part with another blob.
- blob_data_handle = context.AddFinishedBlob(&blob_data2);
+ blob_data_handle = context_.AddFinishedBlob(&blob_data2);
data = blob_data_handle->CreateSnapshot();
ASSERT_TRUE(blob_data_handle);
ASSERT_TRUE(data);
EXPECT_EQ(*data, canonicalized_blob_data2);
// Test a blob referring to only data and a disk cache entry.
- blob_data_handle = context.AddFinishedBlob(&blob_data3);
+ blob_data_handle = context_.AddFinishedBlob(&blob_data3);
data = blob_data_handle->CreateSnapshot();
ASSERT_TRUE(blob_data_handle);
EXPECT_EQ(*data, blob_data3);
@@ -414,79 +412,85 @@ TEST(BlobStorageContextTest, CompoundBlobs) {
base::RunLoop().RunUntilIdle();
}
-TEST(BlobStorageContextTest, PublicBlobUrls) {
- BlobStorageContext context;
- BlobStorageHost host(&context);
+TEST_F(BlobStorageContextTest, PublicBlobUrls) {
base::MessageLoop fake_io_message_loop;
// Build up a basic blob.
const std::string kId("id");
- SetupBasicBlob(&host, kId);
+ scoped_ptr<BlobDataHandle> first_handle = SetupBasicBlob(kId);
// Now register a url for that blob.
GURL kUrl("blob:id");
- EXPECT_TRUE(host.RegisterPublicBlobURL(kUrl, kId));
+ context_.RegisterPublicBlobURL(kUrl, kId);
scoped_ptr<BlobDataHandle> blob_data_handle =
- context.GetBlobDataFromPublicURL(kUrl);
+ context_.GetBlobDataFromPublicURL(kUrl);
ASSERT_TRUE(blob_data_handle.get());
EXPECT_EQ(kId, blob_data_handle->uuid());
scoped_ptr<BlobDataSnapshot> data = blob_data_handle->CreateSnapshot();
blob_data_handle.reset();
+ first_handle.reset();
base::RunLoop().RunUntilIdle();
// The url registration should keep the blob alive even after
// explicit references are dropped.
- EXPECT_TRUE(host.DecrementBlobRefCount(kId));
- blob_data_handle = context.GetBlobDataFromPublicURL(kUrl);
+ blob_data_handle = context_.GetBlobDataFromPublicURL(kUrl);
EXPECT_TRUE(blob_data_handle);
blob_data_handle.reset();
base::RunLoop().RunUntilIdle();
// Finally get rid of the url registration and the blob.
- EXPECT_TRUE(host.RevokePublicBlobURL(kUrl));
- blob_data_handle = context.GetBlobDataFromPublicURL(kUrl);
- EXPECT_TRUE(!blob_data_handle.get());
- EXPECT_FALSE(host.RevokePublicBlobURL(kUrl));
-}
-
-TEST(BlobStorageContextTest, HostCleanup) {
- BlobStorageContext context;
- scoped_ptr<BlobStorageHost> host(new BlobStorageHost(&context));
- base::MessageLoop fake_io_message_loop;
-
- // Build up a basic blob and register a url
- const std::string kId("id");
- GURL kUrl("blob:id");
- SetupBasicBlob(host.get(), kId);
- EXPECT_TRUE(host->RegisterPublicBlobURL(kUrl, kId));
-
- // All should disappear upon host deletion.
- host.reset();
- scoped_ptr<BlobDataHandle> handle = context.GetBlobDataFromPublicURL(kUrl);
- EXPECT_TRUE(!handle.get());
- handle = context.GetBlobDataFromUUID(kId);
- EXPECT_TRUE(!handle.get());
+ context_.RevokePublicBlobURL(kUrl);
+ blob_data_handle = context_.GetBlobDataFromPublicURL(kUrl);
+ EXPECT_FALSE(blob_data_handle.get());
+ EXPECT_FALSE(context_.registry().HasEntry(kId));
}
-TEST(BlobStorageContextTest, EarlyContextDeletion) {
- scoped_ptr<BlobStorageContext> context(new BlobStorageContext);
- BlobStorageHost host(context.get());
+TEST_F(BlobStorageContextTest, TestUnknownBrokenAndBuildingBlobReference) {
base::MessageLoop fake_io_message_loop;
-
- // Deleting the context should not induce crashes.
- context.reset();
-
- const std::string kId("id");
- GURL kUrl("blob:id");
- EXPECT_FALSE(host.StartBuildingBlob(kId));
- DataElement item;
- item.SetToBytes("1", 1);
- EXPECT_FALSE(host.AppendBlobDataItem(kId, item));
- EXPECT_FALSE(host.FinishBuildingBlob(kId, "text/plain"));
- EXPECT_FALSE(host.RegisterPublicBlobURL(kUrl, kId));
- EXPECT_FALSE(host.IncrementBlobRefCount(kId));
- EXPECT_FALSE(host.DecrementBlobRefCount(kId));
- EXPECT_FALSE(host.RevokePublicBlobURL(kUrl));
+ const std::string kBrokenId("broken_id");
+ const std::string kBuildingId("building_id");
+ const std::string kReferencingId("referencing_id");
+ const std::string kUnknownId("unknown_id");
+
+ // Create a broken blob and a building blob.
+ context_.CreatePendingBlob(kBuildingId, "", "");
+ context_.CreatePendingBlob(kBrokenId, "", "");
+ context_.CancelPendingBlob(kBrokenId, IPCBlobCreationCancelCode::UNKNOWN);
+ EXPECT_TRUE(context_.IsBroken(kBrokenId));
+ EXPECT_TRUE(context_.registry().HasEntry(kBrokenId));
+
+ // Try to create a blob with a reference to an unknown blob.
+ BlobDataBuilder builder(kReferencingId);
+ builder.AppendData("data");
+ builder.AppendBlob(kUnknownId);
+ scoped_ptr<BlobDataHandle> handle = context_.AddFinishedBlob(builder);
+ EXPECT_TRUE(handle->IsBroken());
+ EXPECT_TRUE(context_.registry().HasEntry(kReferencingId));
+ handle.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(context_.registry().HasEntry(kReferencingId));
+
+ // Try to create a blob with a reference to the broken blob.
+ BlobDataBuilder builder2(kReferencingId);
+ builder2.AppendData("data");
+ builder2.AppendBlob(kBrokenId);
+ handle = context_.AddFinishedBlob(builder2);
+ EXPECT_TRUE(handle->IsBroken());
+ EXPECT_TRUE(context_.registry().HasEntry(kReferencingId));
+ handle.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(context_.registry().HasEntry(kReferencingId));
+
+ // Try to create a blob with a reference to the building blob.
+ BlobDataBuilder builder3(kReferencingId);
+ builder3.AppendData("data");
+ builder3.AppendBlob(kBuildingId);
+ handle = context_.AddFinishedBlob(builder3);
+ EXPECT_TRUE(handle->IsBroken());
+ EXPECT_TRUE(context_.registry().HasEntry(kReferencingId));
+ handle.reset();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(context_.registry().HasEntry(kReferencingId));
}
// TODO(michaeln): tests for the depcrecated url stuff
diff --git a/chromium/content/browser/fileapi/blob_storage_host.cc b/chromium/content/browser/fileapi/blob_storage_host.cc
deleted file mode 100644
index faf81010dd3..00000000000
--- a/chromium/content/browser/fileapi/blob_storage_host.cc
+++ /dev/null
@@ -1,116 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/fileapi/blob_storage_host.h"
-
-#include "base/sequenced_task_runner.h"
-#include "base/strings/string_util.h"
-#include "storage/browser/blob/blob_storage_context.h"
-#include "url/gurl.h"
-
-using storage::BlobStorageContext;
-
-namespace content {
-
-BlobStorageHost::BlobStorageHost(BlobStorageContext* context)
- : context_(context->AsWeakPtr()) {
-}
-
-BlobStorageHost::~BlobStorageHost() {
- if (!context_.get())
- return;
- for (std::set<GURL>::iterator iter = public_blob_urls_.begin();
- iter != public_blob_urls_.end(); ++iter) {
- context_->RevokePublicBlobURL(*iter);
- }
- for (BlobReferenceMap::iterator iter = blobs_inuse_map_.begin();
- iter != blobs_inuse_map_.end(); ++iter) {
- for (int i = 0; i < iter->second; ++i)
- context_->DecrementBlobRefCount(iter->first);
- }
-}
-
-bool BlobStorageHost::StartBuildingBlob(const std::string& uuid) {
- if (!context_.get() || uuid.empty() || context_->IsInUse(uuid))
- return false;
- context_->StartBuildingBlob(uuid);
- blobs_inuse_map_[uuid] = 1;
- return true;
-}
-
-bool BlobStorageHost::AppendBlobDataItem(
- const std::string& uuid,
- const storage::DataElement& data_item) {
- if (!context_.get() || !IsBeingBuiltInHost(uuid))
- return false;
- context_->AppendBlobDataItem(uuid, data_item);
- return true;
-}
-
-bool BlobStorageHost::CancelBuildingBlob(const std::string& uuid) {
- if (!context_.get() || !IsBeingBuiltInHost(uuid))
- return false;
- blobs_inuse_map_.erase(uuid);
- context_->CancelBuildingBlob(uuid);
- return true;
-}
-
-bool BlobStorageHost::FinishBuildingBlob(
- const std::string& uuid, const std::string& content_type) {
- if (!context_.get() || !IsBeingBuiltInHost(uuid))
- return false;
- context_->FinishBuildingBlob(uuid, content_type);
- return true;
-}
-
-bool BlobStorageHost::IncrementBlobRefCount(const std::string& uuid) {
- if (!context_.get() || !context_->IsInUse(uuid) ||
- context_->IsBeingBuilt(uuid))
- return false;
- context_->IncrementBlobRefCount(uuid);
- blobs_inuse_map_[uuid] += 1;
- return true;
-}
-
-bool BlobStorageHost::DecrementBlobRefCount(const std::string& uuid) {
- if (!context_.get() || !IsInUseInHost(uuid))
- return false;
- context_->DecrementBlobRefCount(uuid);
- blobs_inuse_map_[uuid] -= 1;
- if (blobs_inuse_map_[uuid] == 0)
- blobs_inuse_map_.erase(uuid);
- return true;
-}
-
-bool BlobStorageHost::RegisterPublicBlobURL(
- const GURL& blob_url, const std::string& uuid) {
- if (!context_.get() || !IsInUseInHost(uuid) ||
- context_->IsUrlRegistered(blob_url))
- return false;
- context_->RegisterPublicBlobURL(blob_url, uuid);
- public_blob_urls_.insert(blob_url);
- return true;
-}
-
-bool BlobStorageHost::RevokePublicBlobURL(const GURL& blob_url) {
- if (!context_.get() || !IsUrlRegisteredInHost(blob_url))
- return false;
- context_->RevokePublicBlobURL(blob_url);
- public_blob_urls_.erase(blob_url);
- return true;
-}
-
-bool BlobStorageHost::IsInUseInHost(const std::string& uuid) {
- return blobs_inuse_map_.find(uuid) != blobs_inuse_map_.end();
-}
-
-bool BlobStorageHost::IsBeingBuiltInHost(const std::string& uuid) {
- return IsInUseInHost(uuid) && context_->IsBeingBuilt(uuid);
-}
-
-bool BlobStorageHost::IsUrlRegisteredInHost(const GURL& blob_url) {
- return public_blob_urls_.find(blob_url) != public_blob_urls_.end();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/fileapi/blob_storage_host.h b/chromium/content/browser/fileapi/blob_storage_host.h
deleted file mode 100644
index ecfbc569262..00000000000
--- a/chromium/content/browser/fileapi/blob_storage_host.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_FILEAPI_BLOB_STORAGE_HOST_H_
-#define CONTENT_BROWSER_FILEAPI_BLOB_STORAGE_HOST_H_
-
-#include <map>
-#include <set>
-#include <string>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "content/common/content_export.h"
-#include "storage/common/data_element.h"
-
-class GURL;
-
-namespace storage {
-class BlobDataHandle;
-class BlobStorageHost;
-class BlobStorageContext;
-}
-
-namespace content {
-
-// This class handles the logistics of blob storage for a single child process.
-// There is one instance per child process. When the child process
-// terminates all blob references attibutable to that process go away upon
-// destruction of the instance. The class is single threaded and should
-// only be used on the IO thread.
-class CONTENT_EXPORT BlobStorageHost {
- public:
- explicit BlobStorageHost(storage::BlobStorageContext* context);
- ~BlobStorageHost();
-
- // Methods to support the IPC message protocol.
- // A false return indicates a problem with the inputs
- // like a non-existent or pre-existent uuid or url.
- bool StartBuildingBlob(const std::string& uuid) WARN_UNUSED_RESULT;
- bool AppendBlobDataItem(const std::string& uuid,
- const storage::DataElement& data_item)
- WARN_UNUSED_RESULT;
- bool CancelBuildingBlob(const std::string& uuid) WARN_UNUSED_RESULT;
- bool FinishBuildingBlob(const std::string& uuid,
- const std::string& type) WARN_UNUSED_RESULT;
- bool IncrementBlobRefCount(const std::string& uuid) WARN_UNUSED_RESULT;
- bool DecrementBlobRefCount(const std::string& uuid) WARN_UNUSED_RESULT;
- bool RegisterPublicBlobURL(const GURL& blob_url,
- const std::string& uuid) WARN_UNUSED_RESULT;
- bool RevokePublicBlobURL(const GURL& blob_url) WARN_UNUSED_RESULT;
-
- private:
- typedef std::map<std::string, int> BlobReferenceMap;
-
- bool IsInUseInHost(const std::string& uuid);
- bool IsBeingBuiltInHost(const std::string& uuid);
- bool IsUrlRegisteredInHost(const GURL& blob_url);
-
- // Collection of blob ids and a count of how many usages
- // of that id are attributable to this consumer.
- BlobReferenceMap blobs_inuse_map_;
-
- // The set of public blob urls coined by this consumer.
- std::set<GURL> public_blob_urls_;
-
- base::WeakPtr<storage::BlobStorageContext> context_;
-
- DISALLOW_COPY_AND_ASSIGN(BlobStorageHost);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_FILEAPI_BLOB_STORAGE_HOST_H_
diff --git a/chromium/content/browser/fileapi/blob_url_request_job_unittest.cc b/chromium/content/browser/fileapi/blob_url_request_job_unittest.cc
index 782a1e581db..bdb430fe14a 100644
--- a/chromium/content/browser/fileapi/blob_url_request_job_unittest.cc
+++ b/chromium/content/browser/fileapi/blob_url_request_job_unittest.cc
@@ -534,7 +534,7 @@ TEST_F(BlobURLRequestJobTest, TestExtraHeaders) {
std::string content_type;
EXPECT_TRUE(request_->response_headers()->GetMimeType(&content_type));
EXPECT_EQ(kTestContentType, content_type);
- void* iter = NULL;
+ size_t iter = 0;
std::string content_disposition;
EXPECT_TRUE(request_->response_headers()->EnumerateHeader(
&iter, "Content-Disposition", &content_disposition));
diff --git a/chromium/content/browser/fileapi/copy_or_move_operation_delegate_unittest.cc b/chromium/content/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
index 055b8f2c97f..6e2fcca758c 100644
--- a/chromium/content/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
+++ b/chromium/content/browser/fileapi/copy_or_move_operation_delegate_unittest.cc
@@ -619,8 +619,10 @@ TEST(LocalFileSystemCopyOrMoveOperationTest,
ASSERT_TRUE(helper.DirectoryExists(src));
ASSERT_TRUE(helper.DirectoryExists(dest));
+ // In the move operation, [file 0, file 2, file 3] are processed as LIFO.
+ // After file 3 is processed, file 2 is rejected by the validator and the
+ // operation fails. That is, only file 3 should be in dest.
FileSystemTestCaseRecord kMoveDirResultCases[] = {
- {false, FILE_PATH_LITERAL("file 0"), 38},
{false, FILE_PATH_LITERAL("file 3"), 0},
};
diff --git a/chromium/content/browser/fileapi/dragged_file_util_unittest.cc b/chromium/content/browser/fileapi/dragged_file_util_unittest.cc
index 07c983bad4a..63ba54abae4 100644
--- a/chromium/content/browser/fileapi/dragged_file_util_unittest.cc
+++ b/chromium/content/browser/fileapi/dragged_file_util_unittest.cc
@@ -15,6 +15,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/time/time.h"
#include "build/build_config.h"
diff --git a/chromium/content/browser/fileapi/file_system_dir_url_request_job_unittest.cc b/chromium/content/browser/fileapi/file_system_dir_url_request_job_unittest.cc
index 15f376ce44b..8a535bbdd06 100644
--- a/chromium/content/browser/fileapi/file_system_dir_url_request_job_unittest.cc
+++ b/chromium/content/browser/fileapi/file_system_dir_url_request_job_unittest.cc
@@ -22,7 +22,6 @@
#include "content/public/test/test_file_system_backend.h"
#include "content/public/test/test_file_system_context.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/base/request_priority.h"
#include "net/http/http_request_headers.h"
#include "net/url_request/url_request.h"
@@ -252,9 +251,11 @@ class FileSystemDirURLRequestJobTest : public testing::Test {
const std::string& url,
bool is_directory,
int64_t size) {
+#define NUMBER "([0-9-]*)"
#define STR "([^\"]*)"
icu::UnicodeString pattern("^<script>addRow\\(\"" STR "\",\"" STR
- "\",(0|1),\"" STR "\",\"" STR "\"\\);</script>");
+ "\",(0|1)," NUMBER ",\"" STR "\"," NUMBER ",\"" STR "\"\\);</script>");
+#undef NUMBER
#undef STR
icu::UnicodeString input(entry_line.c_str());
@@ -262,7 +263,7 @@ class FileSystemDirURLRequestJobTest : public testing::Test {
icu::RegexMatcher match(pattern, input, 0, status);
EXPECT_TRUE(match.find());
- EXPECT_EQ(5, match.groupCount());
+ EXPECT_EQ(7, match.groupCount());
EXPECT_EQ(icu::UnicodeString(name.c_str()), match.group(1, status));
EXPECT_EQ(icu::UnicodeString(url.c_str()), match.group(2, status));
EXPECT_EQ(icu::UnicodeString(is_directory ? "1" : "0"),
@@ -270,10 +271,10 @@ class FileSystemDirURLRequestJobTest : public testing::Test {
if (size >= 0) {
icu::UnicodeString size_string(
base::FormatBytesUnlocalized(size).c_str());
- EXPECT_EQ(size_string, match.group(4, status));
+ EXPECT_EQ(size_string, match.group(5, status));
}
- icu::UnicodeString date_ustr(match.group(5, status));
+ icu::UnicodeString date_ustr(match.group(7, status));
scoped_ptr<icu::DateFormat> formatter(
icu::DateFormat::createDateTimeInstance(icu::DateFormat::kShort));
UErrorCode parse_status = U_ZERO_ERROR;
diff --git a/chromium/content/browser/fileapi/file_system_quota_client_unittest.cc b/chromium/content/browser/fileapi/file_system_quota_client_unittest.cc
index e3a24c20151..a1e4f8d05bb 100644
--- a/chromium/content/browser/fileapi/file_system_quota_client_unittest.cc
+++ b/chromium/content/browser/fileapi/file_system_quota_client_unittest.cc
@@ -8,6 +8,7 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "content/public/test/async_file_test_helper.h"
#include "content/public/test/test_file_system_context.h"
diff --git a/chromium/content/browser/fileapi/file_system_url_request_job_unittest.cc b/chromium/content/browser/fileapi/file_system_url_request_job_unittest.cc
index 4b2715c29ab..58ab33b6ea4 100644
--- a/chromium/content/browser/fileapi/file_system_url_request_job_unittest.cc
+++ b/chromium/content/browser/fileapi/file_system_url_request_job_unittest.cc
@@ -27,7 +27,6 @@
#include "net/base/load_flags.h"
#include "net/base/mime_util.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/base/request_priority.h"
#include "net/http/http_byte_range.h"
#include "net/http/http_request_headers.h"
diff --git a/chromium/content/browser/fileapi/fileapi_message_filter.cc b/chromium/content/browser/fileapi/fileapi_message_filter.cc
index 8594aef48bd..318d9566448 100644
--- a/chromium/content/browser/fileapi/fileapi_message_filter.cc
+++ b/chromium/content/browser/fileapi/fileapi_message_filter.cc
@@ -20,7 +20,6 @@
#include "build/build_config.h"
#include "content/browser/bad_message.h"
#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/fileapi/blob_storage_host.h"
#include "content/browser/fileapi/browser_file_system_helper.h"
#include "content/browser/fileapi/chrome_blob_storage_context.h"
#include "content/browser/streams/stream_registry.h"
@@ -56,9 +55,7 @@ namespace content {
namespace {
-const uint32_t kFilteredMessageClasses[] = {
- BlobMsgStart, FileSystemMsgStart,
-};
+const uint32_t kFilteredMessageClasses[] = {FileSystemMsgStart, BlobMsgStart};
void RevokeFilePermission(int child_id, const base::FilePath& path) {
ChildProcessSecurityPolicyImpl::GetInstance()->RevokeAllPermissionsForFile(
@@ -118,18 +115,13 @@ void FileAPIMessageFilter::OnChannelConnected(int32_t peer_pid) {
DCHECK(request_context_);
}
- blob_storage_host_.reset(
- new BlobStorageHost(blob_storage_context_->context()));
-
operation_runner_ = context_->CreateFileSystemOperationRunner();
}
void FileAPIMessageFilter::OnChannelClosing() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // Unregister all the blob and stream URLs that are previously registered in
- // this process.
- blob_storage_host_.reset();
+ // Unregister all stream URLs that are previously registered in this process.
for (base::hash_set<std::string>::const_iterator iter = stream_urls_.begin();
iter != stream_urls_.end(); ++iter) {
stream_context_->registry()->UnregisterStream(GURL(*iter));
@@ -171,19 +163,6 @@ bool FileAPIMessageFilter::OnMessageReceived(const IPC::Message& message) {
OnDidReceiveSnapshotFile)
IPC_MESSAGE_HANDLER(FileSystemHostMsg_SyncGetPlatformPath,
OnSyncGetPlatformPath)
- IPC_MESSAGE_HANDLER(BlobHostMsg_StartBuilding, OnStartBuildingBlob)
- IPC_MESSAGE_HANDLER(BlobHostMsg_AppendBlobDataItem,
- OnAppendBlobDataItemToBlob)
- IPC_MESSAGE_HANDLER(BlobHostMsg_SyncAppendSharedMemory,
- OnAppendSharedMemoryToBlob)
- IPC_MESSAGE_HANDLER(BlobHostMsg_FinishBuilding, OnFinishBuildingBlob)
- 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(StreamHostMsg_StartBuilding, OnStartBuildingStream)
IPC_MESSAGE_HANDLER(StreamHostMsg_AppendBlobDataItem,
OnAppendBlobDataItemToStream)
@@ -514,90 +493,6 @@ void FileAPIMessageFilter::OnDidReceiveSnapshotFile(int request_id) {
in_transit_snapshot_files_.erase(request_id);
}
-void FileAPIMessageFilter::OnStartBuildingBlob(const std::string& uuid) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- ignore_result(blob_storage_host_->StartBuildingBlob(uuid));
-}
-
-void FileAPIMessageFilter::OnAppendBlobDataItemToBlob(
- const std::string& uuid,
- const storage::DataElement& item) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (item.type() == storage::DataElement::TYPE_FILE_FILESYSTEM) {
- 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() == storage::DataElement::TYPE_FILE &&
- !security_policy_->CanReadFile(process_id_, item.path())) {
- ignore_result(blob_storage_host_->CancelBuildingBlob(uuid));
- return;
- }
- if (item.length() == 0) {
- bad_message::ReceivedBadMessage(this,
- bad_message::FAMF_APPEND_ITEM_TO_BLOB);
- return;
- }
- ignore_result(blob_storage_host_->AppendBlobDataItem(uuid, item));
-}
-
-void FileAPIMessageFilter::OnAppendSharedMemoryToBlob(
- const std::string& uuid,
- base::SharedMemoryHandle handle,
- size_t buffer_size) {
- DCHECK(base::SharedMemory::IsHandleValid(handle));
- if (!buffer_size) {
- bad_message::ReceivedBadMessage(
- this, bad_message::FAMF_APPEND_SHARED_MEMORY_TO_BLOB);
- return;
- }
-#if defined(OS_WIN)
- base::SharedMemory shared_memory(handle, true, PeerHandle());
-#else
- base::SharedMemory shared_memory(handle, true);
-#endif
- if (!shared_memory.Map(buffer_size)) {
- ignore_result(blob_storage_host_->CancelBuildingBlob(uuid));
- return;
- }
-
- storage::DataElement item;
- item.SetToSharedBytes(static_cast<char*>(shared_memory.memory()),
- buffer_size);
- ignore_result(blob_storage_host_->AppendBlobDataItem(uuid, item));
-}
-
-void FileAPIMessageFilter::OnFinishBuildingBlob(
- const std::string& uuid, const std::string& content_type) {
- DCHECK_CURRENTLY_ON(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_CURRENTLY_ON(BrowserThread::IO);
- ignore_result(blob_storage_host_->IncrementBlobRefCount(uuid));
-}
-
-void FileAPIMessageFilter::OnDecrementBlobRefCount(const std::string& uuid) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- ignore_result(blob_storage_host_->DecrementBlobRefCount(uuid));
-}
-
-void FileAPIMessageFilter::OnRegisterPublicBlobURL(
- const GURL& public_url, const std::string& uuid) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- ignore_result(blob_storage_host_->RegisterPublicBlobURL(public_url, uuid));
-}
-
-void FileAPIMessageFilter::OnRevokePublicBlobURL(const GURL& public_url) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- ignore_result(blob_storage_host_->RevokePublicBlobURL(public_url));
-}
-
void FileAPIMessageFilter::OnStartBuildingStream(
const GURL& url, const std::string& content_type) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -638,18 +533,15 @@ void FileAPIMessageFilter::OnAppendBlobDataItemToStream(
}
void FileAPIMessageFilter::OnAppendSharedMemoryToStream(
- const GURL& url, base::SharedMemoryHandle handle, size_t buffer_size) {
+ const GURL& url, base::SharedMemoryHandle handle,
+ uint32_t buffer_size) {
DCHECK(base::SharedMemory::IsHandleValid(handle));
if (!buffer_size) {
bad_message::ReceivedBadMessage(
this, bad_message::FAMF_APPEND_SHARED_MEMORY_TO_STREAM);
return;
}
-#if defined(OS_WIN)
- base::SharedMemory shared_memory(handle, true, PeerHandle());
-#else
base::SharedMemory shared_memory(handle, true);
-#endif
if (!shared_memory.Map(buffer_size)) {
OnRemoveStream(url);
return;
diff --git a/chromium/content/browser/fileapi/fileapi_message_filter.h b/chromium/content/browser/fileapi/fileapi_message_filter.h
index 74d056fef8e..7f0a20f340f 100644
--- a/chromium/content/browser/fileapi/fileapi_message_filter.h
+++ b/chromium/content/browser/fileapi/fileapi_message_filter.h
@@ -46,10 +46,6 @@ class URLRequestContext;
class URLRequestContextGetter;
} // namespace net
-namespace content {
-class BlobStorageHost;
-}
-
namespace storage {
class ShareableFileReference;
class DataElement;
@@ -128,21 +124,6 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
const GURL& path);
void OnDidReceiveSnapshotFile(int request_id);
- // Handlers for BlobHostMsg_ family messages.
-
- void OnStartBuildingBlob(const std::string& uuid);
- void OnAppendBlobDataItemToBlob(const std::string& uuid,
- const storage::DataElement& 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 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);
-
// Handlers for StreamHostMsg_ family messages.
//
// TODO(tyoshino): Consider renaming BlobData to more generic one as it's now
@@ -155,7 +136,7 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
void OnAppendBlobDataItemToStream(const GURL& url,
const storage::DataElement& item);
void OnAppendSharedMemoryToStream(
- const GURL& url, base::SharedMemoryHandle handle, size_t buffer_size);
+ const GURL& url, base::SharedMemoryHandle handle, uint32_t buffer_size);
void OnFlushStream(const GURL& url);
void OnFinishBuildingStream(const GURL& url);
void OnAbortBuildingStream(const GURL& url);
@@ -229,10 +210,6 @@ class CONTENT_EXPORT FileAPIMessageFilter : public BrowserMessageFilter {
scoped_ptr<storage::FileSystemOperationRunner> operation_runner_;
- // Keeps track of blobs used in this process and cleans up
- // when the renderer process dies.
- scoped_ptr<BlobStorageHost> blob_storage_host_;
-
// Keep track of stream URLs registered in this process. Need to unregister
// all of them when the renderer process dies.
base::hash_set<std::string> stream_urls_;
diff --git a/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc b/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc
index 1fe224e38ec..b7d61e389d7 100644
--- a/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc
+++ b/chromium/content/browser/fileapi/fileapi_message_filter_unittest.cc
@@ -249,7 +249,7 @@ TEST_F(FileAPIMessageFilterTest, BuildStreamWithSharedMemory) {
ASSERT_TRUE(shared_memory->CreateAndMapAnonymous(kFakeData.size()));
memcpy(shared_memory->memory(), kFakeData.data(), kFakeData.size());
StreamHostMsg_SyncAppendSharedMemory append_message(
- kUrl, shared_memory->handle(), kFakeData.size());
+ kUrl, shared_memory->handle(), static_cast<uint32_t>(kFakeData.size()));
EXPECT_TRUE(filter_->OnMessageReceived(append_message));
StreamHostMsg_FinishBuilding finish_message(kUrl);
diff --git a/chromium/content/browser/fileapi/local_file_util_unittest.cc b/chromium/content/browser/fileapi/local_file_util_unittest.cc
index 28ff6b3ba9d..071a122279a 100644
--- a/chromium/content/browser/fileapi/local_file_util_unittest.cc
+++ b/chromium/content/browser/fileapi/local_file_util_unittest.cc
@@ -11,6 +11,7 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
diff --git a/chromium/content/browser/fileapi/native_file_util_unittest.cc b/chromium/content/browser/fileapi/native_file_util_unittest.cc
index 210f8b9cca5..5a91454bbfc 100644
--- a/chromium/content/browser/fileapi/native_file_util_unittest.cc
+++ b/chromium/content/browser/fileapi/native_file_util_unittest.cc
@@ -11,6 +11,7 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "storage/browser/fileapi/native_file_util.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/content/browser/fileapi/recursive_operation_delegate_unittest.cc b/chromium/content/browser/fileapi/recursive_operation_delegate_unittest.cc
index abcdf54e65b..8c00f0c7c31 100644
--- a/chromium/content/browser/fileapi/recursive_operation_delegate_unittest.cc
+++ b/chromium/content/browser/fileapi/recursive_operation_delegate_unittest.cc
@@ -11,6 +11,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/location.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
diff --git a/chromium/content/browser/fileapi/sandbox_origin_database_unittest.cc b/chromium/content/browser/fileapi/sandbox_origin_database_unittest.cc
index 8338304e6a6..ce89ae6b8e7 100644
--- a/chromium/content/browser/fileapi/sandbox_origin_database_unittest.cc
+++ b/chromium/content/browser/fileapi/sandbox_origin_database_unittest.cc
@@ -15,6 +15,7 @@
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
#include "content/browser/fileapi/sandbox_database_test_helper.h"
#include "storage/browser/fileapi/sandbox_origin_database.h"
diff --git a/chromium/content/browser/fileapi/upload_file_system_file_element_reader.h b/chromium/content/browser/fileapi/upload_file_system_file_element_reader.h
index 5510ce540b6..cba9fa795d8 100644
--- a/chromium/content/browser/fileapi/upload_file_system_file_element_reader.h
+++ b/chromium/content/browser/fileapi/upload_file_system_file_element_reader.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
diff --git a/chromium/content/browser/frame_host/OWNERS b/chromium/content/browser/frame_host/OWNERS
index 2d5011da465..cb3028c329e 100644
--- a/chromium/content/browser/frame_host/OWNERS
+++ b/chromium/content/browser/frame_host/OWNERS
@@ -1 +1,2 @@
+alexmos@chromium.org
clamy@chromium.org
diff --git a/chromium/content/browser/frame_host/PRESUBMIT.py b/chromium/content/browser/frame_host/PRESUBMIT.py
new file mode 100644
index 00000000000..d3afe71d89e
--- /dev/null
+++ b/chromium/content/browser/frame_host/PRESUBMIT.py
@@ -0,0 +1,53 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Presubmit script for //content/browser/frame_host.
+
+See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
+for more details about the presubmit API built into depot_tools.
+"""
+
+import re
+
+
+def _GetTryMasters(project, change):
+ return {
+ 'tryserver.chromium.linux': {
+ 'linux_site_isolation': [],
+ },
+ }
+
+
+def GetPreferredTryMasters(project, change):
+ # TODO(nick, dcheng): Using the value of _GetTryMasters() instead of an empty
+ # value here would cause 'git cl try' to include the site isolation trybots,
+ # which would be nice. But it has the side effect of replacing, rather than
+ # augmenting, the default set of try servers. Re-enable this when we figure
+ # out a way to augment the default set.
+ return {}
+
+
+def PostUploadHook(cl, change, output_api):
+ """git cl upload will call this hook after the issue is created/modified.
+
+ This hook adds extra try bots to the CL description in order to run site
+ isolation tests in addition to CQ try bots.
+ """
+ rietveld_obj = cl.RpcServer()
+ issue = cl.issue
+ description = rietveld_obj.get_description(issue)
+ if re.search(r'^CQ_INCLUDE_TRYBOTS=.*', description, re.M | re.I):
+ return []
+
+ masters = _GetTryMasters(None, change)
+ results = []
+ new_description = description
+ new_description += '\nCQ_INCLUDE_TRYBOTS=%s' % ';'.join(
+ '%s:%s' % (master, ','.join(bots))
+ for master, bots in masters.iteritems())
+ results.append(output_api.PresubmitNotifyResult(
+ 'Automatically added site isolation trybots to run tests on CQ.'))
+
+ rietveld_obj.update_description(issue, new_description)
+
+ return results
diff --git a/chromium/content/browser/frame_host/cross_process_frame_connector.cc b/chromium/content/browser/frame_host/cross_process_frame_connector.cc
index 1d8b23c0411..b5e415ced16 100644
--- a/chromium/content/browser/frame_host/cross_process_frame_connector.cc
+++ b/chromium/content/browser/frame_host/cross_process_frame_connector.cc
@@ -17,7 +17,7 @@
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/common/frame_messages.h"
-#include "content/common/gpu/gpu_messages.h"
+#include "gpu/ipc/common/gpu_messages.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
namespace content {
@@ -38,10 +38,6 @@ bool CrossProcessFrameConnector::OnMessageReceived(const IPC::Message& msg) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(CrossProcessFrameConnector, msg)
- IPC_MESSAGE_HANDLER(FrameHostMsg_CompositorFrameSwappedACK,
- OnCompositorFrameSwappedACK)
- IPC_MESSAGE_HANDLER(FrameHostMsg_ReclaimCompositorResources,
- OnReclaimCompositorResources)
IPC_MESSAGE_HANDLER(FrameHostMsg_ForwardInputEvent, OnForwardInputEvent)
IPC_MESSAGE_HANDLER(FrameHostMsg_FrameRectChanged, OnFrameRectChanged)
IPC_MESSAGE_HANDLER(FrameHostMsg_VisibilityChanged, OnVisibilityChanged)
@@ -67,7 +63,7 @@ void CrossProcessFrameConnector::set_view(
if (view_) {
view_->set_cross_process_frame_connector(this);
SetDeviceScaleFactor(device_scale_factor_);
- SetSize(child_frame_rect_);
+ SetRect(child_frame_rect_);
}
}
@@ -76,20 +72,6 @@ void CrossProcessFrameConnector::RenderProcessGone() {
frame_proxy_in_parent_renderer_->GetRoutingID()));
}
-void CrossProcessFrameConnector::ChildFrameCompositorFrameSwapped(
- uint32_t output_surface_id,
- int host_id,
- int route_id,
- scoped_ptr<cc::CompositorFrame> frame) {
- FrameMsg_CompositorFrameSwapped_Params params;
- frame->AssignTo(&params.frame);
- params.output_surface_id = output_surface_id;
- params.producing_route_id = route_id;
- params.producing_host_id = host_id;
- frame_proxy_in_parent_renderer_->Send(new FrameMsg_CompositorFrameSwapped(
- frame_proxy_in_parent_renderer_->GetRoutingID(), params));
-}
-
void CrossProcessFrameConnector::SetChildFrameSurface(
const cc::SurfaceId& surface_id,
const gfx::Size& frame_size,
@@ -120,29 +102,13 @@ void CrossProcessFrameConnector::OnRequireSequence(
surface->AddDestructionDependency(sequence);
}
-void CrossProcessFrameConnector::OnCompositorFrameSwappedACK(
- const FrameHostMsg_CompositorFrameSwappedACK_Params& params) {
- RenderWidgetHostImpl::SendSwapCompositorFrameAck(params.producing_route_id,
- params.output_surface_id,
- params.producing_host_id,
- params.ack);
-}
-
-void CrossProcessFrameConnector::OnReclaimCompositorResources(
- const FrameHostMsg_ReclaimCompositorResources_Params& params) {
- RenderWidgetHostImpl::SendReclaimCompositorResources(params.route_id,
- params.output_surface_id,
- params.renderer_host_id,
- params.ack);
-}
-
void CrossProcessFrameConnector::OnInitializeChildFrame(gfx::Rect frame_rect,
float scale_factor) {
if (scale_factor != device_scale_factor_)
SetDeviceScaleFactor(scale_factor);
if (!frame_rect.size().IsEmpty())
- SetSize(frame_rect);
+ SetRect(frame_rect);
}
gfx::Rect CrossProcessFrameConnector::ChildFrameRect() {
@@ -150,20 +116,10 @@ gfx::Rect CrossProcessFrameConnector::ChildFrameRect() {
}
void CrossProcessFrameConnector::GetScreenInfo(blink::WebScreenInfo* results) {
- // Inner WebContents's root FrameTreeNode does not have a parent(), so
- // GetRenderWidgetHostView() call below will fail.
- // TODO(lazyboy): Fix this.
- if (frame_proxy_in_parent_renderer_->frame_tree_node()
- ->render_manager()
- ->ForInnerDelegate()) {
- DCHECK(frame_proxy_in_parent_renderer_->frame_tree_node()->IsMainFrame());
- return;
+ auto parent_view = GetParentRenderWidgetHostView();
+ if (parent_view) {
+ parent_view->GetScreenInfo(results);
}
-
- RenderWidgetHostView* rwhv =
- frame_proxy_in_parent_renderer_->GetRenderWidgetHostView();
- if (rwhv)
- static_cast<RenderWidgetHostViewBase*>(rwhv)->GetScreenInfo(results);
}
void CrossProcessFrameConnector::UpdateCursor(const WebCursor& cursor) {
@@ -172,15 +128,23 @@ void CrossProcessFrameConnector::UpdateCursor(const WebCursor& cursor) {
root_view->UpdateCursor(cursor);
}
-void CrossProcessFrameConnector::TransformPointToRootCoordSpace(
+gfx::Point CrossProcessFrameConnector::TransformPointToRootCoordSpace(
const gfx::Point& point,
- cc::SurfaceId surface_id,
- gfx::Point* transformed_point) {
+ cc::SurfaceId surface_id) {
+ gfx::Point transformed_point = point;
RenderWidgetHostViewBase* root_view = GetRootRenderWidgetHostView();
- *transformed_point = point;
if (root_view)
root_view->TransformPointToLocalCoordSpace(point, surface_id,
- transformed_point);
+ &transformed_point);
+ return transformed_point;
+}
+
+void CrossProcessFrameConnector::ForwardProcessAckedTouchEvent(
+ const TouchEventWithLatencyInfo& touch,
+ InputEventAckState ack_result) {
+ auto main_view = GetRootRenderWidgetHostView();
+ if (main_view)
+ main_view->ProcessAckedTouchEvent(touch, ack_result);
}
bool CrossProcessFrameConnector::HasFocus() {
@@ -190,6 +154,12 @@ bool CrossProcessFrameConnector::HasFocus() {
return false;
}
+void CrossProcessFrameConnector::FocusRootView() {
+ RenderWidgetHostViewBase* root_view = GetRootRenderWidgetHostView();
+ if (root_view)
+ root_view->Focus();
+}
+
void CrossProcessFrameConnector::OnForwardInputEvent(
const blink::WebInputEvent* event) {
if (!view_)
@@ -202,6 +172,10 @@ void CrossProcessFrameConnector::OnForwardInputEvent(
? manager->GetOuterRenderWidgetHostForKeyboardInput()
: frame_proxy_in_parent_renderer_->GetRenderViewHost()->GetWidget();
+ // TODO(wjmaclean): We should remove these forwarding functions, since they
+ // are directly target using RenderWidgetHostInputEventRouter. But neither
+ // pathway is currently handling gesture events, so that needs to be fixed
+ // in a subsequent CL.
if (blink::WebInputEvent::isKeyboardEventType(event->type)) {
if (!parent_widget->GetLastKeyboardEvent())
return;
@@ -226,13 +200,26 @@ void CrossProcessFrameConnector::OnForwardInputEvent(
void CrossProcessFrameConnector::OnFrameRectChanged(
const gfx::Rect& frame_rect) {
if (!frame_rect.size().IsEmpty())
- SetSize(frame_rect);
+ SetRect(frame_rect);
}
void CrossProcessFrameConnector::OnVisibilityChanged(bool visible) {
if (!view_)
return;
+ // If there is an inner WebContents, it should be notified of the change in
+ // the visibility. The Show/Hide methods will not be called if an inner
+ // WebContents exists since the corresponding WebContents will itself call
+ // Show/Hide on all the RenderWidgetHostViews (including this) one.
+ if (frame_proxy_in_parent_renderer_->frame_tree_node()
+ ->render_manager()
+ ->ForInnerDelegate()) {
+ RenderWidgetHostImpl::From(view_->GetRenderWidgetHost())
+ ->delegate()
+ ->OnRenderFrameProxyVisibilityChanged(visible);
+ return;
+ }
+
if (visible)
view_->Show();
else
@@ -249,10 +236,27 @@ void CrossProcessFrameConnector::SetDeviceScaleFactor(float scale_factor) {
}
}
-void CrossProcessFrameConnector::SetSize(gfx::Rect frame_rect) {
+void CrossProcessFrameConnector::SetRect(const gfx::Rect& frame_rect) {
+ gfx::Rect old_rect = child_frame_rect_;
child_frame_rect_ = frame_rect;
- if (view_)
- view_->SetSize(frame_rect.size());
+ if (view_) {
+ view_->SetBounds(frame_rect);
+
+ // Out-of-process iframes nested underneath this one implicitly have their
+ // view rects changed when their ancestor is repositioned, and therefore
+ // need to have their screen rects updated.
+ FrameTreeNode* proxy_node =
+ frame_proxy_in_parent_renderer_->frame_tree_node();
+ if (old_rect.x() != child_frame_rect_.x() ||
+ old_rect.y() != child_frame_rect_.y()) {
+ for (FrameTreeNode* node :
+ proxy_node->frame_tree()->SubtreeNodes(proxy_node)) {
+ if (node != proxy_node &&
+ node->current_frame_host()->GetRenderWidgetHost())
+ node->current_frame_host()->GetRenderWidgetHost()->SendScreenRects();
+ }
+ }
+ }
}
RenderWidgetHostViewBase*
@@ -270,4 +274,27 @@ CrossProcessFrameConnector::GetRootRenderWidgetHostView() {
return static_cast<RenderWidgetHostViewBase*>(top_host->GetView());
}
+RenderWidgetHostViewBase*
+CrossProcessFrameConnector::GetParentRenderWidgetHostView() {
+ FrameTreeNode* parent =
+ frame_proxy_in_parent_renderer_->frame_tree_node()->parent();
+
+ if (!parent &&
+ frame_proxy_in_parent_renderer_->frame_tree_node()
+ ->render_manager()
+ ->GetOuterDelegateNode()) {
+ parent = frame_proxy_in_parent_renderer_->frame_tree_node()
+ ->render_manager()
+ ->GetOuterDelegateNode()
+ ->parent();
+ }
+
+ if (parent) {
+ return static_cast<RenderWidgetHostViewBase*>(
+ parent->current_frame_host()->GetView());
+ }
+
+ return nullptr;
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/cross_process_frame_connector.h b/chromium/content/browser/frame_host/cross_process_frame_connector.h
index 6f31ec606fa..0eebdbb5158 100644
--- a/chromium/content/browser/frame_host/cross_process_frame_connector.h
+++ b/chromium/content/browser/frame_host/cross_process_frame_connector.h
@@ -8,7 +8,9 @@
#include <stdint.h>
#include "cc/output/compositor_frame.h"
+#include "content/browser/renderer_host/event_with_latency_info.h"
#include "content/common/content_export.h"
+#include "content/common/input/input_event_ack_state.h"
#include "ui/gfx/geometry/rect.h"
namespace blink {
@@ -25,9 +27,6 @@ namespace IPC {
class Message;
}
-struct FrameHostMsg_CompositorFrameSwappedACK_Params;
-struct FrameHostMsg_ReclaimCompositorResources_Params;
-
namespace content {
class RenderFrameProxyHost;
class RenderWidgetHostImpl;
@@ -87,11 +86,6 @@ class CONTENT_EXPORT CrossProcessFrameConnector {
void RenderProcessGone();
- virtual void ChildFrameCompositorFrameSwapped(
- uint32_t output_surface_id,
- int host_id,
- int route_id,
- scoped_ptr<cc::CompositorFrame> frame);
virtual void SetChildFrameSurface(const cc::SurfaceId& surface_id,
const gfx::Size& frame_size,
float scale_factor,
@@ -101,20 +95,31 @@ class CONTENT_EXPORT CrossProcessFrameConnector {
float device_scale_factor() const { return device_scale_factor_; }
void GetScreenInfo(blink::WebScreenInfo* results);
void UpdateCursor(const WebCursor& cursor);
- void TransformPointToRootCoordSpace(const gfx::Point& point,
- cc::SurfaceId surface_id,
- gfx::Point* transformed_point);
+ gfx::Point TransformPointToRootCoordSpace(const gfx::Point& point,
+ cc::SurfaceId surface_id);
+ // Pass acked touch events to the root view for gesture processing.
+ void ForwardProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
+ InputEventAckState ack_result);
// Determines whether the root RenderWidgetHostView (and thus the current
// page) has focus.
bool HasFocus();
+ // Focuses the root RenderWidgetHostView.
+ void FocusRootView();
+
+ // Returns the parent RenderWidgetHostView or nullptr it it doesn't have one.
+ RenderWidgetHostViewBase* GetParentRenderWidgetHostView();
+
+ // Returns the view for the top-level frame under the same WebContents.
+ RenderWidgetHostViewBase* GetRootRenderWidgetHostView();
+
+ // Exposed for tests.
+ RenderWidgetHostViewBase* GetRootRenderWidgetHostViewForTesting() {
+ return GetRootRenderWidgetHostView();
+ }
private:
// Handlers for messages received from the parent frame.
- void OnCompositorFrameSwappedACK(
- const FrameHostMsg_CompositorFrameSwappedACK_Params& params);
- void OnReclaimCompositorResources(
- const FrameHostMsg_ReclaimCompositorResources_Params& params);
void OnForwardInputEvent(const blink::WebInputEvent* event);
void OnFrameRectChanged(const gfx::Rect& frame_rect);
void OnVisibilityChanged(bool visible);
@@ -124,10 +129,7 @@ class CONTENT_EXPORT CrossProcessFrameConnector {
const cc::SurfaceSequence& sequence);
void SetDeviceScaleFactor(float scale_factor);
- void SetSize(gfx::Rect frame_rect);
-
- // Retrieve the view for the top-level frame under the same WebContents.
- RenderWidgetHostViewBase* GetRootRenderWidgetHostView();
+ void SetRect(const gfx::Rect& frame_rect);
// The RenderFrameProxyHost that routes messages to the parent frame's
// renderer process.
diff --git a/chromium/content/browser/frame_host/debug_urls.cc b/chromium/content/browser/frame_host/debug_urls.cc
index f3190a74acb..833b0063ab4 100644
--- a/chromium/content/browser/frame_host/debug_urls.cc
+++ b/chromium/content/browser/frame_host/debug_urls.cc
@@ -31,6 +31,11 @@
namespace content {
+class ScopedAllowWaitForDebugURL {
+ private:
+ base::ThreadRestrictions::ScopedAllowWait wait;
+};
+
namespace {
// Define the Asan debug URLs.
@@ -164,14 +169,13 @@ bool HandleAsanDebugURL(const GURL& url) {
return true;
}
+void HangCurrentThread() {
+ ScopedAllowWaitForDebugURL allow_wait;
+ base::WaitableEvent(false, false).Wait();
+}
} // namespace
-class ScopedAllowWaitForDebugURL {
- private:
- base::ThreadRestrictions::ScopedAllowWait wait;
-};
-
bool HandleDebugURL(const GURL& url, ui::PageTransition transition) {
// Ensure that the user explicitly navigated to this URL, unless
// kEnableGpuBenchmarking is enabled by Telemetry.
@@ -199,8 +203,16 @@ bool HandleDebugURL(const GURL& url, ui::PageTransition transition) {
}
if (url == GURL(kChromeUIBrowserUIHang)) {
- ScopedAllowWaitForDebugURL allow_wait;
- base::WaitableEvent(false, false).Wait();
+ HangCurrentThread();
+ return true;
+ }
+
+ if (url == GURL(kChromeUIDelayedBrowserUIHang)) {
+ // Webdriver-safe url to hang the ui thread. Webdriver waits for the onload
+ // event in javascript which needs a little more time to fire.
+ BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&HangCurrentThread),
+ base::TimeDelta::FromSeconds(2));
return true;
}
diff --git a/chromium/content/browser/frame_host/frame_mojo_shell.cc b/chromium/content/browser/frame_host/frame_mojo_shell.cc
index ece035648f4..556bfc9152f 100644
--- a/chromium/content/browser/frame_host/frame_mojo_shell.cc
+++ b/chromium/content/browser/frame_host/frame_mojo_shell.cc
@@ -9,12 +9,15 @@
#include "build/build_config.h"
#include "content/browser/mojo/mojo_shell_context.h"
#include "content/common/mojo/service_registry_impl.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
#include "content/public/browser/site_instance.h"
#include "content/public/common/content_client.h"
+#include "mojo/common/url_type_converters.h"
-#if defined(OS_ANDROID) && defined(ENABLE_MOJO_MEDIA)
+#if defined(OS_ANDROID) && defined(ENABLE_MOJO_CDM)
#include "content/browser/media/android/provision_fetcher_impl.h"
#endif
@@ -24,7 +27,7 @@ namespace {
void RegisterFrameMojoShellServices(ServiceRegistry* registry,
RenderFrameHost* render_frame_host) {
-#if defined(OS_ANDROID) && defined(ENABLE_MOJO_MEDIA)
+#if defined(OS_ANDROID) && defined(ENABLE_MOJO_CDM)
registry->AddService(
base::Bind(&ProvisionFetcherImpl::Create, render_frame_host));
#endif
@@ -39,35 +42,32 @@ FrameMojoShell::FrameMojoShell(RenderFrameHost* frame_host)
FrameMojoShell::~FrameMojoShell() {
}
-void FrameMojoShell::BindRequest(
- mojo::InterfaceRequest<mojo::Shell> shell_request) {
- bindings_.AddBinding(this, std::move(shell_request));
+void FrameMojoShell::BindRequest(mojo::shell::mojom::ConnectorRequest request) {
+ connectors_.AddBinding(this, std::move(request));
}
// TODO(xhwang): Currently no callers are exposing |exposed_services|. So we
// drop it and replace it with services we provide in the browser. In the
// future we may need to support both.
-void FrameMojoShell::ConnectToApplication(
- mojo::URLRequestPtr application_url,
- mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr /* exposed_services */,
- mojo::CapabilityFilterPtr filter,
- const ConnectToApplicationCallback& callback) {
- mojo::ServiceProviderPtr frame_services;
+void FrameMojoShell::Connect(
+ mojo::shell::mojom::IdentityPtr target,
+ mojo::shell::mojom::InterfaceProviderRequest services,
+ mojo::shell::mojom::InterfaceProviderPtr /* exposed_services */,
+ mojo::shell::mojom::ClientProcessConnectionPtr client_process_connection,
+ const mojo::shell::mojom::Connector::ConnectCallback& callback) {
+ mojo::shell::mojom::InterfaceProviderPtr frame_services;
service_provider_bindings_.AddBinding(GetServiceRegistry(),
GetProxy(&frame_services));
-
- mojo::shell::CapabilityFilter capability_filter =
- mojo::shell::GetPermissiveCapabilityFilter();
- if (!filter.is_null())
- capability_filter = filter->filter.To<mojo::shell::CapabilityFilter>();
+ std::string mojo_user_id = BrowserContext::GetMojoUserIdFor(
+ frame_host_->GetProcess()->GetBrowserContext());
MojoShellContext::ConnectToApplication(
- GURL(application_url->url), frame_host_->GetSiteInstance()->GetSiteURL(),
- std::move(services), std::move(frame_services), capability_filter,
- callback);
+ mojo_user_id, target->name,
+ frame_host_->GetSiteInstance()->GetSiteURL().spec(), std::move(services),
+ std::move(frame_services), callback);
}
-void FrameMojoShell::QuitApplication() {
+void FrameMojoShell::Clone(mojo::shell::mojom::ConnectorRequest request) {
+ connectors_.AddBinding(this, std::move(request));
}
ServiceRegistryImpl* FrameMojoShell::GetServiceRegistry() {
diff --git a/chromium/content/browser/frame_host/frame_mojo_shell.h b/chromium/content/browser/frame_host/frame_mojo_shell.h
index 08a60e9b831..893ade427f4 100644
--- a/chromium/content/browser/frame_host/frame_mojo_shell.h
+++ b/chromium/content/browser/frame_host/frame_mojo_shell.h
@@ -7,42 +7,44 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
-#include "mojo/common/weak_binding_set.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
#include "mojo/public/cpp/bindings/interface_request.h"
-#include "mojo/shell/public/interfaces/shell.mojom.h"
+#include "mojo/shell/public/interfaces/connector.mojom.h"
namespace content {
class RenderFrameHost;
class ServiceRegistryImpl;
-// This provides the |mojo::Shell| service interface to each frame's
-// ServiceRegistry, giving frames the ability to connect to Mojo applications.
-class FrameMojoShell : public mojo::Shell {
+// This provides the |mojo::shell::mojom::Shell| service interface to each
+// frame's ServiceRegistry, giving frames the ability to connect to Mojo
+// applications.
+class FrameMojoShell : public mojo::shell::mojom::Connector {
public:
explicit FrameMojoShell(RenderFrameHost* frame_host);
~FrameMojoShell() override;
- void BindRequest(mojo::InterfaceRequest<mojo::Shell> shell_request);
+ void BindRequest(mojo::shell::mojom::ConnectorRequest request);
private:
- // mojo::Shell:
- void ConnectToApplication(
- mojo::URLRequestPtr application_url,
- mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services,
- mojo::CapabilityFilterPtr filter,
- const ConnectToApplicationCallback& callback) override;
- void QuitApplication() override;
+ // mojo::Connector:
+ void Connect(
+ mojo::shell::mojom::IdentityPtr target,
+ mojo::shell::mojom::InterfaceProviderRequest services,
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services,
+ mojo::shell::mojom::ClientProcessConnectionPtr client_process_connection,
+ const mojo::shell::mojom::Connector::ConnectCallback& callback) override;
+ void Clone(mojo::shell::mojom::ConnectorRequest request) override;
ServiceRegistryImpl* GetServiceRegistry();
RenderFrameHost* frame_host_;
- mojo::WeakBindingSet<mojo::Shell> bindings_;
+ mojo::BindingSet<mojo::shell::mojom::Connector> connectors_;
// ServiceRegistry providing browser services to connected applications.
scoped_ptr<ServiceRegistryImpl> service_registry_;
- mojo::WeakBindingSet<mojo::ServiceProvider> service_provider_bindings_;
+ mojo::BindingSet<mojo::shell::mojom::InterfaceProvider>
+ service_provider_bindings_;
DISALLOW_COPY_AND_ASSIGN(FrameMojoShell);
};
diff --git a/chromium/content/browser/frame_host/frame_navigation_entry.cc b/chromium/content/browser/frame_host/frame_navigation_entry.cc
index a7a414e85a3..fe8809c8fc6 100644
--- a/chromium/content/browser/frame_host/frame_navigation_entry.cc
+++ b/chromium/content/browser/frame_host/frame_navigation_entry.cc
@@ -4,6 +4,8 @@
#include "content/browser/frame_host/frame_navigation_entry.h"
+#include <utility>
+
namespace content {
FrameNavigationEntry::FrameNavigationEntry(int frame_tree_node_id)
@@ -12,18 +14,19 @@ FrameNavigationEntry::FrameNavigationEntry(int frame_tree_node_id)
document_sequence_number_(-1) {
}
-FrameNavigationEntry::FrameNavigationEntry(int frame_tree_node_id,
- const std::string& frame_unique_name,
- int64_t item_sequence_number,
- int64_t document_sequence_number,
- SiteInstanceImpl* site_instance,
- const GURL& url,
- const Referrer& referrer)
+FrameNavigationEntry::FrameNavigationEntry(
+ int frame_tree_node_id,
+ const std::string& frame_unique_name,
+ int64_t item_sequence_number,
+ int64_t document_sequence_number,
+ scoped_refptr<SiteInstanceImpl> site_instance,
+ const GURL& url,
+ const Referrer& referrer)
: frame_tree_node_id_(frame_tree_node_id),
frame_unique_name_(frame_unique_name),
item_sequence_number_(item_sequence_number),
document_sequence_number_(document_sequence_number),
- site_instance_(site_instance),
+ site_instance_(std::move(site_instance)),
url_(url),
referrer_(referrer) {}
diff --git a/chromium/content/browser/frame_host/frame_navigation_entry.h b/chromium/content/browser/frame_host/frame_navigation_entry.h
index 67a27063700..8527c4aed41 100644
--- a/chromium/content/browser/frame_host/frame_navigation_entry.h
+++ b/chromium/content/browser/frame_host/frame_navigation_entry.h
@@ -33,7 +33,7 @@ class CONTENT_EXPORT FrameNavigationEntry
const std::string& frame_unique_name,
int64_t item_sequence_number,
int64_t document_sequence_number,
- SiteInstanceImpl* site_instance,
+ scoped_refptr<SiteInstanceImpl> site_instance,
const GURL& url,
const Referrer& referrer);
@@ -88,8 +88,8 @@ class CONTENT_EXPORT FrameNavigationEntry
// a SiteInstance must live in the same process. This is a refcounted pointer
// that keeps the SiteInstance (not necessarily the process) alive as long as
// this object remains in the session history.
- void set_site_instance(SiteInstanceImpl* site_instance) {
- site_instance_ = site_instance;
+ void set_site_instance(scoped_refptr<SiteInstanceImpl> site_instance) {
+ site_instance_ = std::move(site_instance);
}
SiteInstanceImpl* site_instance() const { return site_instance_.get(); }
diff --git a/chromium/content/browser/frame_host/frame_tree.cc b/chromium/content/browser/frame_host/frame_tree.cc
index e92d28f80be..388c878ba3b 100644
--- a/chromium/content/browser/frame_host/frame_tree.cc
+++ b/chromium/content/browser/frame_host/frame_tree.cc
@@ -28,84 +28,60 @@ namespace content {
namespace {
-// Used with FrameTree::ForEach() to search for the FrameTreeNode
-// corresponding to |frame_tree_node_id| within a specific FrameTree.
-bool FrameTreeNodeForId(int frame_tree_node_id,
- FrameTreeNode** out_node,
- FrameTreeNode* node) {
- if (node->frame_tree_node_id() == frame_tree_node_id) {
- *out_node = node;
- // Terminate iteration once the node has been found.
- return false;
- }
- return true;
+// Helper function to collect SiteInstances involved in rendering a single
+// FrameTree (which is a subset of SiteInstances in main frame's proxy_hosts_
+// because of openers).
+std::set<SiteInstance*> CollectSiteInstances(FrameTree* tree) {
+ std::set<SiteInstance*> instances;
+ for (FrameTreeNode* node : tree->Nodes())
+ instances.insert(node->current_frame_host()->GetSiteInstance());
+ return instances;
}
-// Used with FrameTree::ForEach() to search for the FrameTreeNode with the given
-// |name| within a specific FrameTree.
-bool FrameTreeNodeForName(const std::string& name,
- FrameTreeNode** out_node,
- FrameTreeNode* node) {
- if (node->frame_name() == name) {
- *out_node = node;
- // Terminate iteration once the node has been found.
- return false;
+} // namespace
+
+FrameTree::NodeIterator::NodeIterator(const NodeIterator& other) = default;
+
+FrameTree::NodeIterator::~NodeIterator() {}
+
+FrameTree::NodeIterator& FrameTree::NodeIterator::operator++() {
+ for (size_t i = 0; i < current_node_->child_count(); ++i) {
+ FrameTreeNode* child = current_node_->child_at(i);
+ if (child == node_to_skip_)
+ continue;
+ queue_.push(child);
}
- return true;
-}
-bool CreateProxyForSiteInstance(const scoped_refptr<SiteInstance>& instance,
- FrameTreeNode* node) {
- // If a new frame is created in the current SiteInstance, other frames in
- // that SiteInstance don't need a proxy for the new frame.
- SiteInstance* current_instance =
- node->render_manager()->current_frame_host()->GetSiteInstance();
- if (current_instance != instance.get())
- node->render_manager()->CreateRenderFrameProxy(instance.get());
- return true;
-}
+ if (!queue_.empty()) {
+ current_node_ = queue_.front();
+ queue_.pop();
+ } else {
+ current_node_ = nullptr;
+ }
-// Helper function used with FrameTree::ForEach() for retrieving the total
-// loading progress and number of frames in a frame tree.
-bool CollectLoadProgress(double* progress,
- int* frame_count,
- FrameTreeNode* node) {
- // Ignore the current frame if it has not started loading.
- if (!node->has_started_loading())
- return true;
-
- // Collect progress.
- *progress += node->loading_progress();
- (*frame_count)++;
- return true;
+ return *this;
}
-// Helper function used with FrameTree::ForEach() to reset the load progress.
-bool ResetNodeLoadProgress(FrameTreeNode* node) {
- node->reset_loading_progress();
- return true;
+bool FrameTree::NodeIterator::operator==(const NodeIterator& rhs) const {
+ return current_node_ == rhs.current_node_;
}
-// Helper function used with FrameTree::ForEach() to check if at least one of
-// the nodes is loading.
-bool IsNodeLoading(bool* is_loading, FrameTreeNode* node) {
- if (node->IsLoading()) {
- // There is at least one node loading, so abort traversal.
- *is_loading = true;
- return false;
- }
- return true;
+FrameTree::NodeIterator::NodeIterator(FrameTreeNode* starting_node,
+ FrameTreeNode* node_to_skip)
+ : current_node_(starting_node != node_to_skip ? starting_node : nullptr),
+ node_to_skip_(node_to_skip) {}
+
+FrameTree::NodeIterator FrameTree::NodeRange::begin() {
+ return NodeIterator(root_, node_to_skip_);
}
-// Helper function used with FrameTree::ForEach to collect SiteInstances
-// involved in rendering a single FrameTree (which is a subset of SiteInstances
-// in main frame's proxy_hosts_ because of openers).
-bool CollectSiteInstances(std::set<SiteInstance*>* set, FrameTreeNode* node) {
- set->insert(node->current_frame_host()->GetSiteInstance());
- return true;
+FrameTree::NodeIterator FrameTree::NodeRange::end() {
+ return NodeIterator(nullptr, nullptr);
}
-} // namespace
+FrameTree::NodeRange::NodeRange(FrameTreeNode* root,
+ FrameTreeNode* node_to_skip)
+ : root_(root), node_to_skip_(node_to_skip) {}
FrameTree::FrameTree(Navigator* navigator,
RenderFrameHostDelegate* render_frame_delegate,
@@ -126,7 +102,7 @@ FrameTree::FrameTree(Navigator* navigator,
// document scope.
blink::WebTreeScopeType::Document,
std::string(),
- blink::WebSandboxFlags::None,
+ std::string(),
blink::WebFrameOwnerProperties())),
focused_frame_tree_node_id_(-1),
load_progress_(0.0) {}
@@ -137,9 +113,11 @@ FrameTree::~FrameTree() {
}
FrameTreeNode* FrameTree::FindByID(int frame_tree_node_id) {
- FrameTreeNode* node = nullptr;
- ForEach(base::Bind(&FrameTreeNodeForId, frame_tree_node_id, &node));
- return node;
+ for (FrameTreeNode* node : Nodes()) {
+ if (node->frame_tree_node_id() == frame_tree_node_id)
+ return node;
+ }
+ return nullptr;
}
FrameTreeNode* FrameTree::FindByRoutingID(int process_id, int routing_id) {
@@ -166,34 +144,24 @@ FrameTreeNode* FrameTree::FindByName(const std::string& name) {
if (name.empty())
return root_;
- FrameTreeNode* node = nullptr;
- ForEach(base::Bind(&FrameTreeNodeForName, name, &node));
- return node;
-}
+ for (FrameTreeNode* node : Nodes()) {
+ if (node->frame_name() == name)
+ return node;
+ }
-void FrameTree::ForEach(
- const base::Callback<bool(FrameTreeNode*)>& on_node) const {
- ForEach(on_node, nullptr);
+ return nullptr;
}
-void FrameTree::ForEach(
- const base::Callback<bool(FrameTreeNode*)>& on_node,
- FrameTreeNode* skip_this_subtree) const {
- std::queue<FrameTreeNode*> queue;
- queue.push(root_);
-
- while (!queue.empty()) {
- FrameTreeNode* node = queue.front();
- queue.pop();
- if (skip_this_subtree == node)
- continue;
+FrameTree::NodeRange FrameTree::Nodes() {
+ return NodesExcept(nullptr);
+}
- if (!on_node.Run(node))
- break;
+FrameTree::NodeRange FrameTree::SubtreeNodes(FrameTreeNode* subtree_root) {
+ return NodeRange(subtree_root, nullptr);
+}
- for (size_t i = 0; i < node->child_count(); ++i)
- queue.push(node->child_at(i));
- }
+FrameTree::NodeRange FrameTree::NodesExcept(FrameTreeNode* node_to_skip) {
+ return NodeRange(root_, node_to_skip);
}
bool FrameTree::AddFrame(
@@ -202,6 +170,7 @@ bool FrameTree::AddFrame(
int new_routing_id,
blink::WebTreeScopeType scope,
const std::string& frame_name,
+ const std::string& frame_unique_name,
blink::WebSandboxFlags sandbox_flags,
const blink::WebFrameOwnerProperties& frame_owner_properties) {
CHECK_NE(new_routing_id, MSG_ROUTING_NONE);
@@ -218,9 +187,14 @@ bool FrameTree::AddFrame(
make_scoped_ptr(new FrameTreeNode(
this, parent->navigator(), render_frame_delegate_,
render_view_delegate_, render_widget_delegate_, manager_delegate_,
- scope, frame_name, sandbox_flags, frame_owner_properties)),
+ scope, frame_name, frame_unique_name, frame_owner_properties)),
process_id, new_routing_id);
+ // Set sandbox flags and make them effective immediately, since initial
+ // sandbox flags should apply to the initial empty document in the frame.
+ added_node->SetPendingSandboxFlags(sandbox_flags);
+ added_node->CommitPendingSandboxFlags();
+
// Now that the new node is part of the FrameTree and has a RenderFrameHost,
// we can announce the creation of the initial RenderFrame which already
// exists in the renderer process.
@@ -241,30 +215,28 @@ void FrameTree::RemoveFrame(FrameTreeNode* child) {
void FrameTree::CreateProxiesForSiteInstance(
FrameTreeNode* source,
SiteInstance* site_instance) {
- // Create the swapped out RVH for the new SiteInstance. This will create
- // a top-level swapped out RFH as well, which will then be wrapped by a
- // RenderFrameProxyHost.
+ // Create the RenderFrameProxyHost for the new SiteInstance.
if (!source || !source->IsMainFrame()) {
RenderViewHostImpl* render_view_host = GetRenderViewHost(site_instance);
if (!render_view_host) {
- if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- root()->render_manager()->CreateRenderFrameProxy(site_instance);
- } else {
- root()->render_manager()->CreateRenderFrame(
- site_instance, CREATE_RF_SWAPPED_OUT | CREATE_RF_HIDDEN, nullptr);
- }
+ root()->render_manager()->CreateRenderFrameProxy(site_instance);
} else {
root()->render_manager()->EnsureRenderViewInitialized(render_view_host,
site_instance);
}
}
- scoped_refptr<SiteInstance> instance(site_instance);
-
// Proxies are created in the FrameTree in response to a node navigating to a
// new SiteInstance. Since |source|'s navigation will replace the currently
// loaded document, the entire subtree under |source| will be removed.
- ForEach(base::Bind(&CreateProxyForSiteInstance, instance), source);
+ for (FrameTreeNode* node : NodesExcept(source)) {
+ // If a new frame is created in the current SiteInstance, other frames in
+ // that SiteInstance don't need a proxy for the new frame.
+ SiteInstance* current_instance =
+ node->render_manager()->current_frame_host()->GetSiteInstance();
+ if (current_instance != site_instance)
+ node->render_manager()->CreateRenderFrameProxy(site_instance);
+ }
}
RenderFrameHostImpl* FrameTree::GetMainFrame() const {
@@ -279,8 +251,8 @@ void FrameTree::SetFocusedFrame(FrameTreeNode* node, SiteInstance* source) {
if (node == GetFocusedFrame())
return;
- std::set<SiteInstance*> frame_tree_site_instances;
- ForEach(base::Bind(&CollectSiteInstances, &frame_tree_site_instances));
+ std::set<SiteInstance*> frame_tree_site_instances =
+ CollectSiteInstances(this);
SiteInstance* current_instance =
node->current_frame_host()->GetSiteInstance();
@@ -311,6 +283,11 @@ void FrameTree::SetFocusedFrame(FrameTreeNode* node, SiteInstance* source) {
focused_frame_tree_node_id_ = node->frame_tree_node_id();
node->DidFocus();
+
+ // The accessibility tree data for the root of the frame tree keeps
+ // track of the focused frame too, so update that every time the
+ // focused frame changes.
+ root()->current_frame_host()->UpdateAXTreeData();
}
void FrameTree::SetFrameRemoveListener(
@@ -333,7 +310,7 @@ RenderViewHostImpl* FrameTree::CreateRenderViewHost(
// SiteInstance. Note that if swapped-out is forbidden, the
// RenderViewHost's main frame has already been cleared, so we cannot rely
// on checking whether the main frame is pending deletion.
- if (iter->second->is_pending_deletion()) {
+ if (root_->render_manager()->IsViewPendingDeletion(iter->second)) {
render_view_host_pending_shutdown_map_.insert(
std::make_pair(site_instance->GetId(), iter->second));
render_view_host_map_.erase(iter);
@@ -353,9 +330,12 @@ RenderViewHostImpl* FrameTree::CreateRenderViewHost(
RenderViewHostImpl* FrameTree::GetRenderViewHost(SiteInstance* site_instance) {
RenderViewHostMap::iterator iter =
render_view_host_map_.find(site_instance->GetId());
- if (iter == render_view_host_map_.end())
- return nullptr;
- return iter->second;
+ // Don't return the RVH if it is pending deletion.
+ if (iter != render_view_host_map_.end() &&
+ !root_->render_manager()->IsViewPendingDeletion(iter->second)) {
+ return iter->second;
+ }
+ return nullptr;
}
void FrameTree::AddRenderViewHostRef(RenderViewHostImpl* render_view_host) {
@@ -428,7 +408,16 @@ void FrameTree::UpdateLoadProgress() {
double progress = 0.0;
int frame_count = 0;
- ForEach(base::Bind(&CollectLoadProgress, &progress, &frame_count));
+ for (FrameTreeNode* node : Nodes()) {
+ // Ignore the current frame if it has not started loading.
+ if (!node->has_started_loading())
+ continue;
+
+ // Collect progress.
+ progress += node->loading_progress();
+ frame_count++;
+ }
+
if (frame_count != 0)
progress /= frame_count;
@@ -441,19 +430,22 @@ void FrameTree::UpdateLoadProgress() {
}
void FrameTree::ResetLoadProgress() {
- ForEach(base::Bind(&ResetNodeLoadProgress));
+ for (FrameTreeNode* node : Nodes())
+ node->reset_loading_progress();
load_progress_ = 0.0;
}
-bool FrameTree::IsLoading() {
- bool is_loading = false;
- ForEach(base::Bind(&IsNodeLoading, &is_loading));
- return is_loading;
+bool FrameTree::IsLoading() const {
+ for (const FrameTreeNode* node : const_cast<FrameTree*>(this)->Nodes()) {
+ if (node->IsLoading())
+ return true;
+ }
+ return false;
}
void FrameTree::ReplicatePageFocus(bool is_focused) {
- std::set<SiteInstance*> frame_tree_site_instances;
- ForEach(base::Bind(&CollectSiteInstances, &frame_tree_site_instances));
+ std::set<SiteInstance*> frame_tree_site_instances =
+ CollectSiteInstances(this);
// Send the focus update to main frame's proxies in all SiteInstances of
// other frames in this FrameTree. Note that the main frame might also know
diff --git a/chromium/content/browser/frame_host/frame_tree.h b/chromium/content/browser/frame_host/frame_tree.h
index 6fc21f61cb0..840228d412d 100644
--- a/chromium/content/browser/frame_host/frame_tree.h
+++ b/chromium/content/browser/frame_host/frame_tree.h
@@ -7,6 +7,7 @@
#include <stdint.h>
+#include <iterator>
#include <string>
#include "base/callback.h"
@@ -18,7 +19,6 @@
namespace content {
-class FrameTreeNode;
class Navigator;
class RenderFrameHostDelegate;
class RenderProcessHost;
@@ -41,6 +41,45 @@ class RenderWidgetHostDelegate;
// This object is only used on the UI thread.
class CONTENT_EXPORT FrameTree {
public:
+ class NodeRange;
+
+ class CONTENT_EXPORT NodeIterator
+ : public std::iterator<std::forward_iterator_tag, FrameTreeNode> {
+ public:
+ NodeIterator(const NodeIterator& other);
+ ~NodeIterator();
+
+ NodeIterator& operator++();
+
+ bool operator==(const NodeIterator& rhs) const;
+ bool operator!=(const NodeIterator& rhs) const { return !(*this == rhs); }
+
+ FrameTreeNode* operator*() { return current_node_; }
+
+ private:
+ friend class NodeRange;
+
+ NodeIterator(FrameTreeNode* starting_node, FrameTreeNode* node_to_skip);
+
+ FrameTreeNode* current_node_;
+ FrameTreeNode* const node_to_skip_;
+ std::queue<FrameTreeNode*> queue_;
+ };
+
+ class CONTENT_EXPORT NodeRange {
+ public:
+ NodeIterator begin();
+ NodeIterator end();
+
+ private:
+ friend class FrameTree;
+
+ NodeRange(FrameTreeNode* root, FrameTreeNode* node_to_skip);
+
+ FrameTreeNode* const root_;
+ FrameTreeNode* const node_to_skip_;
+ };
+
// Each FrameTreeNode will default to using the given |navigator| for
// navigation tasks in the frame.
// A set of delegates are remembered here so that we can create
@@ -69,12 +108,13 @@ class CONTENT_EXPORT FrameTree {
// nor searching other FrameTrees (unlike blink::WebView::findFrameByName).
FrameTreeNode* FindByName(const std::string& name);
- // Executes |on_node| on each node in the frame tree. If |on_node| returns
- // false, terminates the iteration immediately. Returning false is useful
- // if |on_node| is just doing a search over the tree. The iteration proceeds
- // top-down and visits a node before adding its children to the queue, making
- // it safe to remove children during the callback.
- void ForEach(const base::Callback<bool(FrameTreeNode*)>& on_node) const;
+ // Returns a range to iterate over all FrameTreeNodes in the frame tree in
+ // breadth-first traversal order.
+ NodeRange Nodes();
+
+ // Returns a range to iterate over all FrameTreeNodes in a subtree of the
+ // frame tree, starting from |subtree_root|.
+ NodeRange SubtreeNodes(FrameTreeNode* subtree_root);
// Adds a new child frame to the frame tree. |process_id| is required to
// disambiguate |new_routing_id|, and it must match the process of the
@@ -84,6 +124,7 @@ class CONTENT_EXPORT FrameTree {
int new_routing_id,
blink::WebTreeScopeType scope,
const std::string& frame_name,
+ const std::string& frame_unique_name,
blink::WebSandboxFlags sandbox_flags,
const blink::WebFrameOwnerProperties& frame_owner_properties);
@@ -154,7 +195,7 @@ class CONTENT_EXPORT FrameTree {
void ResetLoadProgress();
// Returns true if at least one of the nodes in this FrameTree is loading.
- bool IsLoading();
+ bool IsLoading() const;
// Set page-level focus in all SiteInstances involved in rendering
// this FrameTree, not including the current main frame's
@@ -167,14 +208,15 @@ class CONTENT_EXPORT FrameTree {
void SetPageFocus(SiteInstance* instance, bool is_focused);
private:
+ friend class FrameTreeTest;
FRIEND_TEST_ALL_PREFIXES(RenderFrameHostImplBrowserTest, RemoveFocusedFrame);
typedef base::hash_map<int, RenderViewHostImpl*> RenderViewHostMap;
typedef std::multimap<int, RenderViewHostImpl*> RenderViewHostMultiMap;
- // A variation to the public ForEach method with a difference that the subtree
- // starting at |skip_this_subtree| will not be recursed into.
- void ForEach(const base::Callback<bool(FrameTreeNode*)>& on_node,
- FrameTreeNode* skip_this_subtree) const;
+ // Returns a range to iterate over all FrameTreeNodes in the frame tree in
+ // breadth-first traversal order, skipping the subtree rooted at
+ // |node_to_skip|.
+ NodeRange NodesExcept(FrameTreeNode* node_to_skip);
// These delegates are installed into all the RenderViewHosts and
// RenderFrameHosts that we create.
diff --git a/chromium/content/browser/frame_host/frame_tree_browsertest.cc b/chromium/content/browser/frame_host/frame_tree_browsertest.cc
index 1ffdd0a21d2..782234f5a02 100644
--- a/chromium/content/browser/frame_host/frame_tree_browsertest.cc
+++ b/chromium/content/browser/frame_host/frame_tree_browsertest.cc
@@ -464,30 +464,29 @@ IN_PROC_BROWSER_TEST_F(FrameTreeBrowserTest, SandboxFlagsSetForChildFrames) {
// which resets both SandboxFlags::Scripts and
// SandboxFlags::AutomaticFeatures bits per blink::parseSandboxPolicy(), and
// third frame has "allow-scripts allow-same-origin".
- EXPECT_EQ(root->current_replication_state().sandbox_flags,
- blink::WebSandboxFlags::None);
- EXPECT_EQ(root->child_at(0)->current_replication_state().sandbox_flags,
- blink::WebSandboxFlags::All);
- EXPECT_EQ(root->child_at(1)->current_replication_state().sandbox_flags,
- blink::WebSandboxFlags::All & ~blink::WebSandboxFlags::Scripts &
- ~blink::WebSandboxFlags::AutomaticFeatures);
- EXPECT_EQ(root->child_at(2)->current_replication_state().sandbox_flags,
- blink::WebSandboxFlags::All & ~blink::WebSandboxFlags::Scripts &
+ EXPECT_EQ(blink::WebSandboxFlags::None, root->effective_sandbox_flags());
+ EXPECT_EQ(blink::WebSandboxFlags::All,
+ root->child_at(0)->effective_sandbox_flags());
+ EXPECT_EQ(blink::WebSandboxFlags::All & ~blink::WebSandboxFlags::Scripts &
+ ~blink::WebSandboxFlags::AutomaticFeatures,
+ root->child_at(1)->effective_sandbox_flags());
+ EXPECT_EQ(blink::WebSandboxFlags::All & ~blink::WebSandboxFlags::Scripts &
~blink::WebSandboxFlags::AutomaticFeatures &
- ~blink::WebSandboxFlags::Origin);
+ ~blink::WebSandboxFlags::Origin,
+ root->child_at(2)->effective_sandbox_flags());
// Sandboxed frames should set a unique origin unless they have the
// "allow-same-origin" directive.
- EXPECT_EQ(root->child_at(0)->current_origin().Serialize(), "null");
- EXPECT_EQ(root->child_at(1)->current_origin().Serialize(), "null");
- EXPECT_EQ(root->child_at(2)->current_origin().Serialize() + "/",
- main_url.GetOrigin().spec());
+ EXPECT_EQ("null", root->child_at(0)->current_origin().Serialize());
+ EXPECT_EQ("null", root->child_at(1)->current_origin().Serialize());
+ EXPECT_EQ(main_url.GetOrigin().spec(),
+ root->child_at(2)->current_origin().Serialize() + "/");
// Navigating to a different URL should not clear sandbox flags.
GURL frame_url(embedded_test_server()->GetURL("/title1.html"));
NavigateFrameToURL(root->child_at(0), frame_url);
- EXPECT_EQ(root->child_at(0)->current_replication_state().sandbox_flags,
- blink::WebSandboxFlags::All);
+ EXPECT_EQ(blink::WebSandboxFlags::All,
+ root->child_at(0)->effective_sandbox_flags());
}
// Ensure that a popup opened from a subframe sets its opener to the subframe's
diff --git a/chromium/content/browser/frame_host/frame_tree_node.cc b/chromium/content/browser/frame_host/frame_tree_node.cc
index b975a051106..7f1d2f57ad9 100644
--- a/chromium/content/browser/frame_host/frame_tree_node.cc
+++ b/chromium/content/browser/frame_host/frame_tree_node.cc
@@ -14,11 +14,13 @@
#include "content/browser/frame_host/navigation_request.h"
#include "content/browser/frame_host/navigator.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/frame_host/traced_frame_tree_node.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/common/frame_messages.h"
#include "content/common/site_isolation_policy.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/browser_side_navigation_policy.h"
+#include "third_party/WebKit/public/web/WebSandboxFlags.h"
namespace content {
@@ -77,7 +79,7 @@ FrameTreeNode::FrameTreeNode(
RenderFrameHostManager::Delegate* manager_delegate,
blink::WebTreeScopeType scope,
const std::string& name,
- blink::WebSandboxFlags sandbox_flags,
+ const std::string& unique_name,
const blink::WebFrameOwnerProperties& frame_owner_properties)
: frame_tree_(frame_tree),
navigator_(navigator),
@@ -94,17 +96,23 @@ FrameTreeNode::FrameTreeNode(
replication_state_(
scope,
name,
- sandbox_flags,
- false /* should enforce strict mixed content checking */),
- // Effective sandbox flags also need to be set, since initial sandbox
- // flags should apply to the initial empty document in the frame.
- effective_sandbox_flags_(sandbox_flags),
+ unique_name,
+ blink::WebSandboxFlags::None,
+ false /* should enforce strict mixed content checking */,
+ false /* is a potentially trustworthy unique origin */),
+ pending_sandbox_flags_(blink::WebSandboxFlags::None),
frame_owner_properties_(frame_owner_properties),
loading_progress_(kLoadingProgressNotStarted) {
std::pair<FrameTreeNodeIdMap::iterator, bool> result =
g_frame_tree_node_id_map.Get().insert(
std::make_pair(frame_tree_node_id_, this));
CHECK(result.second);
+
+ TRACE_EVENT_OBJECT_CREATED_WITH_ID(
+ "navigation", "FrameTreeNode",
+ TRACE_ID_WITH_SCOPE("FrameTreeNode", frame_tree_node_id_));
+ // Don't TraceSnapshot() until the RenderFrameHostManager is initialized and
+ // calls SetCurrentURL().
}
FrameTreeNode::~FrameTreeNode() {
@@ -116,6 +124,10 @@ FrameTreeNode::~FrameTreeNode() {
opener_->RemoveObserver(opener_observer_.get());
g_frame_tree_node_id_map.Get().erase(frame_tree_node_id_);
+
+ TRACE_EVENT_OBJECT_DELETED_WITH_ID(
+ "navigation", "FrameTreeNode",
+ TRACE_ID_WITH_SCOPE("FrameTreeNode", frame_tree_node_id_));
}
void FrameTreeNode::AddObserver(Observer* observer) {
@@ -171,7 +183,8 @@ void FrameTreeNode::RemoveChild(FrameTreeNode* child) {
}
void FrameTreeNode::ResetForNewProcess() {
- current_url_ = GURL();
+ current_frame_host()->set_last_committed_url(GURL());
+ TraceSnapshot();
// Remove child nodes from the tree, then delete them. This destruction
// operation will notify observers.
@@ -196,19 +209,34 @@ void FrameTreeNode::SetOpener(FrameTreeNode* opener) {
void FrameTreeNode::SetCurrentURL(const GURL& url) {
if (!has_committed_real_load_ && url != GURL(url::kAboutBlankURL))
has_committed_real_load_ = true;
- current_url_ = url;
+ current_frame_host()->set_last_committed_url(url);
+ TraceSnapshot();
}
-void FrameTreeNode::SetCurrentOrigin(const url::Origin& origin) {
- if (!origin.IsSameOriginWith(replication_state_.origin))
- render_manager_.OnDidUpdateOrigin(origin);
+void FrameTreeNode::SetCurrentOrigin(
+ const url::Origin& origin,
+ bool is_potentially_trustworthy_unique_origin) {
+ if (!origin.IsSameOriginWith(replication_state_.origin) ||
+ replication_state_.has_potentially_trustworthy_unique_origin !=
+ is_potentially_trustworthy_unique_origin) {
+ render_manager_.OnDidUpdateOrigin(origin,
+ is_potentially_trustworthy_unique_origin);
+ }
replication_state_.origin = origin;
+ replication_state_.has_potentially_trustworthy_unique_origin =
+ is_potentially_trustworthy_unique_origin;
}
-void FrameTreeNode::SetFrameName(const std::string& name) {
- if (name != replication_state_.name)
- render_manager_.OnDidUpdateName(name);
+void FrameTreeNode::SetFrameName(const std::string& name,
+ const std::string& unique_name) {
+ if (name == replication_state_.name) {
+ // |unique_name| shouldn't change unless |name| changes.
+ DCHECK_EQ(unique_name, replication_state_.unique_name);
+ return;
+ }
+ render_manager_.OnDidUpdateName(name, unique_name);
replication_state_.name = name;
+ replication_state_.unique_name = unique_name;
}
void FrameTreeNode::SetEnforceStrictMixedContentChecking(bool should_enforce) {
@@ -221,6 +249,15 @@ void FrameTreeNode::SetEnforceStrictMixedContentChecking(bool should_enforce) {
should_enforce;
}
+void FrameTreeNode::SetPendingSandboxFlags(
+ blink::WebSandboxFlags sandbox_flags) {
+ pending_sandbox_flags_ = sandbox_flags;
+
+ // Subframes should always inherit their parent's sandbox flags.
+ if (parent())
+ pending_sandbox_flags_ |= parent()->effective_sandbox_flags();
+}
+
bool FrameTreeNode::IsDescendantOf(FrameTreeNode* other) const {
if (!other || !other->child_count())
return false;
@@ -271,48 +308,68 @@ bool FrameTreeNode::IsLoading() const {
bool FrameTreeNode::CommitPendingSandboxFlags() {
bool did_change_flags =
- effective_sandbox_flags_ != replication_state_.sandbox_flags;
- effective_sandbox_flags_ = replication_state_.sandbox_flags;
+ pending_sandbox_flags_ != replication_state_.sandbox_flags;
+ replication_state_.sandbox_flags = pending_sandbox_flags_;
return did_change_flags;
}
void FrameTreeNode::CreatedNavigationRequest(
scoped_ptr<NavigationRequest> navigation_request) {
CHECK(IsBrowserSideNavigationEnabled());
- ResetNavigationRequest(false);
+
+ bool was_previously_loading = frame_tree()->IsLoading();
+
+ // There's no need to reset the state: there's still an ongoing load, and the
+ // RenderFrameHostManager will take care of updates to the speculative
+ // RenderFrameHost in DidCreateNavigationRequest below.
+ if (was_previously_loading)
+ ResetNavigationRequest(true);
+
+ navigation_request_ = std::move(navigation_request);
+ render_manager()->DidCreateNavigationRequest(navigation_request_.get());
// Force the throbber to start to keep it in sync with what is happening in
// the UI. Blink doesn't send throb notifications for JavaScript URLs, so it
// is not done here either.
- if (!navigation_request->common_params().url.SchemeIs(
+ if (!navigation_request_->common_params().url.SchemeIs(
url::kJavaScriptScheme)) {
// TODO(fdegans): Check if this is a same-document navigation and set the
// proper argument.
- DidStartLoading(true);
+ DidStartLoading(true, was_previously_loading);
}
-
- navigation_request_ = std::move(navigation_request);
-
- render_manager()->DidCreateNavigationRequest(*navigation_request_);
}
-void FrameTreeNode::ResetNavigationRequest(bool is_commit) {
+void FrameTreeNode::ResetNavigationRequest(bool keep_state) {
CHECK(IsBrowserSideNavigationEnabled());
if (!navigation_request_)
return;
+ bool was_renderer_initiated = !navigation_request_->browser_initiated();
+ NavigationRequest::AssociatedSiteInstanceType site_instance_type =
+ navigation_request_->associated_site_instance_type();
navigation_request_.reset();
- // During commit, the clean up of a speculative RenderFrameHost is done in
- // RenderFrameHostManager::DidNavigateFrame. The load is also still being
- // tracked.
- if (is_commit)
+ if (keep_state)
return;
- // If the reset corresponds to a cancelation, the RenderFrameHostManager
- // should clean up any speculative RenderFrameHost it created for the
- // navigation.
+ // The RenderFrameHostManager should clean up any speculative RenderFrameHost
+ // it created for the navigation. Also register that the load stopped.
DidStopLoading();
render_manager_.CleanUpNavigation();
+
+ // When reusing the same SiteInstance, a pending WebUI may have been created
+ // on behalf of the navigation in the current RenderFrameHost. Clear it.
+ if (site_instance_type ==
+ NavigationRequest::AssociatedSiteInstanceType::CURRENT) {
+ current_frame_host()->ClearPendingWebUI();
+ }
+
+ // If the navigation is renderer-initiated, the renderer should also be
+ // informed that the navigation stopped.
+ if (was_renderer_initiated) {
+ current_frame_host()->Send(
+ new FrameMsg_Stop(current_frame_host()->GetRoutingID()));
+ }
+
}
bool FrameTreeNode::has_started_loading() const {
@@ -323,7 +380,8 @@ void FrameTreeNode::reset_loading_progress() {
loading_progress_ = kLoadingProgressNotStarted;
}
-void FrameTreeNode::DidStartLoading(bool to_different_document) {
+void FrameTreeNode::DidStartLoading(bool to_different_document,
+ bool was_previously_loading) {
// Any main frame load to a new document should reset the load progress since
// it will replace the current page and any frames. The WebContents will
// be notified when DidChangeLoadProgress is called.
@@ -331,7 +389,7 @@ void FrameTreeNode::DidStartLoading(bool to_different_document) {
frame_tree_->ResetLoadProgress();
// Notify the WebContents.
- if (!frame_tree_->IsLoading())
+ if (!was_previously_loading)
navigator()->GetDelegate()->DidStartLoading(this, to_different_document);
// Set initial load progress and update overall progress. This will notify
@@ -398,4 +456,36 @@ void FrameTreeNode::DidFocus() {
FOR_EACH_OBSERVER(Observer, observers_, OnFrameTreeNodeFocused(this));
}
+void FrameTreeNode::BeforeUnloadCanceled() {
+ // TODO(clamy): Support BeforeUnload in subframes.
+ if (!IsMainFrame())
+ return;
+
+ RenderFrameHostImpl* current_frame_host =
+ render_manager_.current_frame_host();
+ DCHECK(current_frame_host);
+ current_frame_host->ResetLoadingState();
+
+ if (IsBrowserSideNavigationEnabled()) {
+ RenderFrameHostImpl* speculative_frame_host =
+ render_manager_.speculative_frame_host();
+ if (speculative_frame_host)
+ speculative_frame_host->ResetLoadingState();
+ } else {
+ RenderFrameHostImpl* pending_frame_host =
+ render_manager_.pending_frame_host();
+ if (pending_frame_host)
+ pending_frame_host->ResetLoadingState();
+ }
+}
+
+void FrameTreeNode::TraceSnapshot() const {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
+ "navigation", "FrameTreeNode",
+ TRACE_ID_WITH_SCOPE("FrameTreeNode", frame_tree_node_id_),
+ scoped_ptr<base::trace_event::ConvertableToTraceFormat>(
+ new TracedFrameTreeNode(*this)));
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/frame_tree_node.h b/chromium/content/browser/frame_host/frame_tree_node.h
index 9103b63aa70..044764b9144 100644
--- a/chromium/content/browser/frame_host/frame_tree_node.h
+++ b/chromium/content/browser/frame_host/frame_tree_node.h
@@ -51,6 +51,8 @@ class CONTENT_EXPORT FrameTreeNode {
// regardless of which FrameTree it is in.
static FrameTreeNode* GloballyFindByID(int frame_tree_node_id);
+ // Callers are are expected to initialize sandbox flags separately after
+ // calling the constructor.
FrameTreeNode(FrameTree* frame_tree,
Navigator* navigator,
RenderFrameHostDelegate* render_frame_delegate,
@@ -59,7 +61,7 @@ class CONTENT_EXPORT FrameTreeNode {
RenderFrameHostManager::Delegate* manager_delegate,
blink::WebTreeScopeType scope,
const std::string& name,
- blink::WebSandboxFlags sandbox_flags,
+ const std::string& unique_name,
const blink::WebFrameOwnerProperties& frame_owner_properties);
~FrameTreeNode();
@@ -97,8 +99,6 @@ class CONTENT_EXPORT FrameTreeNode {
return replication_state_.name;
}
- const url::Origin& frame_origin() const { return replication_state_.origin; }
-
size_t child_count() const {
return children_.size();
}
@@ -116,9 +116,9 @@ class CONTENT_EXPORT FrameTreeNode {
return children_[index].get();
}
- // Returns the URL of the last committed page in this frame.
+ // Returns the URL of the last committed page in the current frame.
const GURL& current_url() const {
- return current_url_;
+ return current_frame_host()->last_committed_url();
}
// Sets the last committed URL for this frame and updates
@@ -136,25 +136,43 @@ class CONTENT_EXPORT FrameTreeNode {
}
// Set the current origin and notify proxies about the update.
- void SetCurrentOrigin(const url::Origin& origin);
+ void SetCurrentOrigin(const url::Origin& origin,
+ bool is_potentially_trustworthy_unique_origin);
// Set the current name and notify proxies about the update.
- void SetFrameName(const std::string& name);
+ void SetFrameName(const std::string& name, const std::string& unique_name);
// Sets the current enforcement of strict mixed content checking and
// notifies proxies about the update.
void SetEnforceStrictMixedContentChecking(bool should_enforce);
- blink::WebSandboxFlags effective_sandbox_flags() {
- return effective_sandbox_flags_;
+ // Returns the currently active sandbox flags for this frame. This includes
+ // flags inherited from parent frames and the currently active flags from the
+ // <iframe> element hosting this frame. This does not include flags that
+ // have been updated in an <iframe> element but have not taken effect yet;
+ // use pending_sandbox_flags() for those.
+ blink::WebSandboxFlags effective_sandbox_flags() const {
+ return replication_state_.sandbox_flags;
}
- void set_sandbox_flags(blink::WebSandboxFlags sandbox_flags) {
- replication_state_.sandbox_flags = sandbox_flags;
+ // Returns the latest sandbox flags for this frame. This includes flags
+ // inherited from parent frames and the latest flags from the <iframe>
+ // element hosting this frame. The returned flags may not yet have taken
+ // effect, since sandbox flag updates in an <iframe> element take effect on
+ // next navigation. To retrieve the currently active sandbox flags for this
+ // frame, use effective_sandbox_flags().
+ blink::WebSandboxFlags pending_sandbox_flags() const {
+ return pending_sandbox_flags_;
}
- // Transfer any pending sandbox flags into |effective_sandbox_flags_|, and
- // return true if the sandbox flags were changed.
+ // Update this frame's sandbox flags. This is used when a parent frame
+ // updates sandbox flags in the <iframe> element for this frame. These flags
+ // won't take effect until next navigation. If this frame's parent is itself
+ // sandboxed, the parent's sandbox flags are combined with |sandbox_flags|.
+ void SetPendingSandboxFlags(blink::WebSandboxFlags sandbox_flags);
+
+ // Set any pending sandbox flags as active, and return true if the sandbox
+ // flags were changed.
bool CommitPendingSandboxFlags();
const blink::WebFrameOwnerProperties& frame_owner_properties() {
@@ -202,9 +220,10 @@ class CONTENT_EXPORT FrameTreeNode {
scoped_ptr<NavigationRequest> navigation_request);
// PlzNavigate
- // Resets the current navigation request. |is_commit| is true if the reset is
- // due to the commit of the navigation.
- void ResetNavigationRequest(bool is_commit);
+ // Resets the current navigation request. If |keep_state| is true, any state
+ // created by the NavigationRequest (e.g. speculative RenderFrameHost,
+ // loading state) will not be reset by the function.
+ void ResetNavigationRequest(bool keep_state);
// Returns true if this node is in a state where the loading progress is being
// tracked.
@@ -216,7 +235,11 @@ class CONTENT_EXPORT FrameTreeNode {
// A RenderFrameHost in this node started loading.
// |to_different_document| will be true unless the load is a fragment
// navigation, or triggered by history.pushState/replaceState.
- void DidStartLoading(bool to_different_document);
+ // |was_previously_loading| is false if the FrameTree was not loading before.
+ // The caller is required to provide this boolean as the delegate should only
+ // be notified if the FrameTree went from non-loading to loading state.
+ // However, when it is called, the FrameTree should be in a loading state.
+ void DidStartLoading(bool to_different_document, bool was_previously_loading);
// A RenderFrameHost in this node stopped loading.
void DidStopLoading();
@@ -238,11 +261,18 @@ class CONTENT_EXPORT FrameTreeNode {
// time and notifies observers.
void DidFocus();
+ // Called when the user closed the modal dialogue for BeforeUnload and
+ // cancelled the navigation. This should stop any load happening in the
+ // FrameTreeNode.
+ void BeforeUnloadCanceled();
+
private:
class OpenerDestroyedObserver;
void set_parent(FrameTreeNode* parent) { parent_ = parent; }
+ void TraceSnapshot() const;
+
// The next available browser-global FrameTreeNode ID.
static int next_frame_tree_node_id_;
@@ -282,11 +312,6 @@ class CONTENT_EXPORT FrameTreeNode {
// The immediate children of this specific frame.
std::vector<scoped_ptr<FrameTreeNode>> children_;
- // Track the current frame's last committed URL.
- // TODO(creis): Consider storing a reference to the last committed
- // FrameNavigationEntry here once those are created in all modes.
- GURL current_url_;
-
// Whether this frame has committed any real load, replacing its initial
// about:blank page.
bool has_committed_real_load_;
@@ -295,15 +320,12 @@ class CONTENT_EXPORT FrameTreeNode {
// proxies for this frame.
FrameReplicationState replication_state_;
- // Track the effective sandbox flags for this frame. When a parent frame
- // dynamically updates sandbox flags for a child frame, the child's updated
- // sandbox flags are stored in replication_state_.sandbox_flags. However, the
- // update only takes effect on the next frame navigation, so the effective
- // sandbox flags are tracked separately here. When enforcing sandbox flags
- // directives in the browser process, |effective_sandbox_flags_| should be
- // used. |effective_sandbox_flags_| is updated with any pending sandbox
- // flags when a navigation for this frame commits.
- blink::WebSandboxFlags effective_sandbox_flags_;
+ // Track the pending sandbox flags for this frame. When a parent frame
+ // dynamically updates sandbox flags in the <iframe> element for a child
+ // frame, these updated flags are stored here and are transferred into
+ // replication_state_.sandbox_flags when they take effect on the next frame
+ // navigation.
+ blink::WebSandboxFlags pending_sandbox_flags_;
// Tracks the scrolling and margin properties for this frame. These
// properties affect the child renderer but are stored on its parent's
diff --git a/chromium/content/browser/frame_host/frame_tree_unittest.cc b/chromium/content/browser/frame_host/frame_tree_unittest.cc
index 93d481684fd..73861575da4 100644
--- a/chromium/content/browser/frame_host/frame_tree_unittest.cc
+++ b/chromium/content/browser/frame_host/frame_tree_unittest.cc
@@ -120,6 +120,17 @@ class FrameTreeTest : public RenderViewHostImplTestHarness {
AppendTreeNodeState(frame_tree->root(), &result);
return result;
}
+
+ std::string GetTraversalOrder(FrameTree* frame_tree,
+ FrameTreeNode* node_to_skip) {
+ std::string result;
+ for (FrameTreeNode* node : frame_tree->NodesExcept(node_to_skip)) {
+ if (!result.empty())
+ result += " ";
+ result += base::Int64ToString(node->current_frame_host()->GetRoutingID());
+ }
+ return result;
+ }
};
// Exercise tree manipulation routines.
@@ -145,26 +156,29 @@ TEST_F(FrameTreeTest, Shape) {
// Simulate attaching a series of frames to build the frame tree.
frame_tree->AddFrame(root, process_id, 14, blink::WebTreeScopeType::Document,
- std::string(), blink::WebSandboxFlags::None,
+ std::string(), "uniqueName0",
+ blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
frame_tree->AddFrame(root, process_id, 15, blink::WebTreeScopeType::Document,
- std::string(), blink::WebSandboxFlags::None,
+ std::string(), "uniqueName1",
+ blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
frame_tree->AddFrame(root, process_id, 16, blink::WebTreeScopeType::Document,
- std::string(), blink::WebSandboxFlags::None,
+ std::string(), "uniqueName2",
+ blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
frame_tree->AddFrame(root->child_at(0), process_id, 244,
blink::WebTreeScopeType::Document, std::string(),
- blink::WebSandboxFlags::None,
+ "uniqueName3", blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
frame_tree->AddFrame(root->child_at(1), process_id, 255,
blink::WebTreeScopeType::Document, no_children_node,
- blink::WebSandboxFlags::None,
+ "uniqueName4", blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
frame_tree->AddFrame(root->child_at(0), process_id, 245,
blink::WebTreeScopeType::Document, std::string(),
- blink::WebSandboxFlags::None,
+ "uniqueName5", blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
EXPECT_EQ(
@@ -176,42 +190,42 @@ TEST_F(FrameTreeTest, Shape) {
FrameTreeNode* child_16 = root->child_at(2);
frame_tree->AddFrame(child_16, process_id, 264,
blink::WebTreeScopeType::Document, std::string(),
- blink::WebSandboxFlags::None,
+ "uniqueName6", blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
frame_tree->AddFrame(child_16, process_id, 265,
blink::WebTreeScopeType::Document, std::string(),
- blink::WebSandboxFlags::None,
+ "uniqueName7", blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
frame_tree->AddFrame(child_16, process_id, 266,
blink::WebTreeScopeType::Document, std::string(),
- blink::WebSandboxFlags::None,
+ "uniqueName8", blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
frame_tree->AddFrame(child_16, process_id, 267,
blink::WebTreeScopeType::Document, deep_subtree,
- blink::WebSandboxFlags::None,
+ "uniqueName9", blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
frame_tree->AddFrame(child_16, process_id, 268,
blink::WebTreeScopeType::Document, std::string(),
- blink::WebSandboxFlags::None,
+ "uniqueName10", blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
FrameTreeNode* child_267 = child_16->child_at(3);
frame_tree->AddFrame(child_267, process_id, 365,
blink::WebTreeScopeType::Document, std::string(),
- blink::WebSandboxFlags::None,
+ "uniqueName11", blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
frame_tree->AddFrame(child_267->child_at(0), process_id, 455,
blink::WebTreeScopeType::Document, std::string(),
- blink::WebSandboxFlags::None,
+ "uniqueName12", blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
frame_tree->AddFrame(child_267->child_at(0)->child_at(0), process_id, 555,
blink::WebTreeScopeType::Document, std::string(),
- blink::WebSandboxFlags::None,
- blink::WebFrameOwnerProperties());
- frame_tree->AddFrame(child_267->child_at(0)->child_at(0)->child_at(0),
- process_id, 655, blink::WebTreeScopeType::Document,
- std::string(), blink::WebSandboxFlags::None,
+ "uniqueName13", blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
+ frame_tree->AddFrame(
+ child_267->child_at(0)->child_at(0)->child_at(0), process_id, 655,
+ blink::WebTreeScopeType::Document, std::string(), "uniqueName14",
+ blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
// Now that's it's fully built, verify the tree structure is as expected.
EXPECT_EQ(
@@ -222,7 +236,31 @@ TEST_F(FrameTreeTest, Shape) {
"[365: [455: [555: [655: []]]]], 268: []]]",
GetTreeState(frame_tree));
+ // Verify that traversal order is breadth first, even if we skip a subtree.
+ FrameTreeNode* child_14 = root->child_at(0);
+ FrameTreeNode* child_15 = root->child_at(1);
+ FrameTreeNode* child_244 = child_14->child_at(0);
+ FrameTreeNode* child_245 = child_14->child_at(1);
FrameTreeNode* child_555 = child_267->child_at(0)->child_at(0)->child_at(0);
+ FrameTreeNode* child_655 = child_555->child_at(0);
+ EXPECT_EQ("2 14 15 16 244 245 255 264 265 266 267 268 365 455 555 655",
+ GetTraversalOrder(frame_tree, nullptr));
+ EXPECT_EQ("", GetTraversalOrder(frame_tree, root));
+ EXPECT_EQ("2 15 16 255 264 265 266 267 268 365 455 555 655",
+ GetTraversalOrder(frame_tree, child_14));
+ EXPECT_EQ("2 14 15 16 245 255 264 265 266 267 268 365 455 555 655",
+ GetTraversalOrder(frame_tree, child_244));
+ EXPECT_EQ("2 14 15 16 244 255 264 265 266 267 268 365 455 555 655",
+ GetTraversalOrder(frame_tree, child_245));
+ EXPECT_EQ("2 14 16 244 245 264 265 266 267 268 365 455 555 655",
+ GetTraversalOrder(frame_tree, child_15));
+ EXPECT_EQ("2 14 15 16 244 245 255 264 265 266 268",
+ GetTraversalOrder(frame_tree, child_267));
+ EXPECT_EQ("2 14 15 16 244 245 255 264 265 266 267 268 365 455",
+ GetTraversalOrder(frame_tree, child_555));
+ EXPECT_EQ("2 14 15 16 244 245 255 264 265 266 267 268 365 455 555",
+ GetTraversalOrder(frame_tree, child_655));
+
frame_tree->RemoveFrame(child_555);
EXPECT_EQ(
"2: [14: [244: [], 245: []], "
@@ -258,16 +296,15 @@ TEST_F(FrameTreeTest, FindFrames) {
FrameTree* frame_tree = contents()->GetFrameTree();
FrameTreeNode* root = frame_tree->root();
- main_test_rfh()->OnCreateChildFrame(22, blink::WebTreeScopeType::Document,
- "child0", blink::WebSandboxFlags::None,
- blink::WebFrameOwnerProperties());
- main_test_rfh()->OnCreateChildFrame(23, blink::WebTreeScopeType::Document,
- "child1", blink::WebSandboxFlags::None,
- blink::WebFrameOwnerProperties());
- main_test_rfh()->OnCreateChildFrame(24, blink::WebTreeScopeType::Document,
- std::string(),
- blink::WebSandboxFlags::None,
- blink::WebFrameOwnerProperties());
+ main_test_rfh()->OnCreateChildFrame(
+ 22, blink::WebTreeScopeType::Document, "child0", "uniqueName0",
+ blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
+ main_test_rfh()->OnCreateChildFrame(
+ 23, blink::WebTreeScopeType::Document, "child1", "uniqueName1",
+ blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
+ main_test_rfh()->OnCreateChildFrame(
+ 24, blink::WebTreeScopeType::Document, std::string(), "uniqueName2",
+ blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
FrameTreeNode* child0 = root->child_at(0);
FrameTreeNode* child1 = root->child_at(1);
@@ -275,7 +312,7 @@ TEST_F(FrameTreeTest, FindFrames) {
// Add one grandchild frame.
child1->current_frame_host()->OnCreateChildFrame(
- 33, blink::WebTreeScopeType::Document, "grandchild",
+ 33, blink::WebTreeScopeType::Document, "grandchild", "uniqueName3",
blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
FrameTreeNode* grandchild = child1->child_at(0);
@@ -312,22 +349,22 @@ TEST_F(FrameTreeTest, PreviousSibling) {
// Add a few child frames to the main frame.
FrameTree* frame_tree = contents()->GetFrameTree();
FrameTreeNode* root = frame_tree->root();
- main_test_rfh()->OnCreateChildFrame(22, blink::WebTreeScopeType::Document,
- "child0", blink::WebSandboxFlags::None,
- blink::WebFrameOwnerProperties());
- main_test_rfh()->OnCreateChildFrame(23, blink::WebTreeScopeType::Document,
- "child1", blink::WebSandboxFlags::None,
- blink::WebFrameOwnerProperties());
- main_test_rfh()->OnCreateChildFrame(24, blink::WebTreeScopeType::Document,
- "child2", blink::WebSandboxFlags::None,
- blink::WebFrameOwnerProperties());
+ main_test_rfh()->OnCreateChildFrame(
+ 22, blink::WebTreeScopeType::Document, "child0", "uniqueName0",
+ blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
+ main_test_rfh()->OnCreateChildFrame(
+ 23, blink::WebTreeScopeType::Document, "child1", "uniqueName1",
+ blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
+ main_test_rfh()->OnCreateChildFrame(
+ 24, blink::WebTreeScopeType::Document, "child2", "uniqueName2",
+ blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
FrameTreeNode* child0 = root->child_at(0);
FrameTreeNode* child1 = root->child_at(1);
FrameTreeNode* child2 = root->child_at(2);
// Add one grandchild frame.
child1->current_frame_host()->OnCreateChildFrame(
- 33, blink::WebTreeScopeType::Document, "grandchild",
+ 33, blink::WebTreeScopeType::Document, "grandchild", "uniqueName3",
blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
FrameTreeNode* grandchild = child1->child_at(0);
@@ -349,18 +386,16 @@ TEST_F(FrameTreeTest, ObserverWalksTreeDuringFrameCreation) {
FrameTreeNode* root = frame_tree->root();
// Simulate attaching a series of frames to build the frame tree.
- main_test_rfh()->OnCreateChildFrame(14, blink::WebTreeScopeType::Document,
- std::string(),
- blink::WebSandboxFlags::None,
- blink::WebFrameOwnerProperties());
+ main_test_rfh()->OnCreateChildFrame(
+ 14, blink::WebTreeScopeType::Document, std::string(), "uniqueName0",
+ blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
EXPECT_EQ(
"RenderFrameHostChanged(new)(14) -> 2: []\n"
"RenderFrameCreated(14) -> 2: [14: []]",
activity.GetLog());
- main_test_rfh()->OnCreateChildFrame(18, blink::WebTreeScopeType::Document,
- std::string(),
- blink::WebSandboxFlags::None,
- blink::WebFrameOwnerProperties());
+ main_test_rfh()->OnCreateChildFrame(
+ 18, blink::WebTreeScopeType::Document, std::string(), "uniqueName1",
+ blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
EXPECT_EQ(
"RenderFrameHostChanged(new)(18) -> 2: [14: []]\n"
"RenderFrameCreated(18) -> 2: [14: [], 18: []]",
@@ -378,18 +413,16 @@ TEST_F(FrameTreeTest, ObserverWalksTreeAfterCrash) {
contents()->NavigateAndCommit(GURL("http://www.google.com"));
EXPECT_EQ("RenderFrameCreated(2) -> 2: []", activity.GetLog());
- main_test_rfh()->OnCreateChildFrame(22, blink::WebTreeScopeType::Document,
- std::string(),
- blink::WebSandboxFlags::None,
- blink::WebFrameOwnerProperties());
+ main_test_rfh()->OnCreateChildFrame(
+ 22, blink::WebTreeScopeType::Document, std::string(), "uniqueName0",
+ blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
EXPECT_EQ(
"RenderFrameHostChanged(new)(22) -> 2: []\n"
"RenderFrameCreated(22) -> 2: [22: []]",
activity.GetLog());
- main_test_rfh()->OnCreateChildFrame(23, blink::WebTreeScopeType::Document,
- std::string(),
- blink::WebSandboxFlags::None,
- blink::WebFrameOwnerProperties());
+ main_test_rfh()->OnCreateChildFrame(
+ 23, blink::WebTreeScopeType::Document, std::string(), "uniqueName1",
+ blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
EXPECT_EQ(
"RenderFrameHostChanged(new)(23) -> 2: [22: []]\n"
"RenderFrameCreated(23) -> 2: [22: [], 23: []]",
@@ -418,7 +451,8 @@ TEST_F(FrameTreeTest, FailAddFrameWithWrongProcessId) {
// Simulate attaching a frame from mismatched process id.
ASSERT_FALSE(frame_tree->AddFrame(
root, process_id + 1, 1, blink::WebTreeScopeType::Document, std::string(),
- blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties()));
+ "uniqueName0", blink::WebSandboxFlags::None,
+ blink::WebFrameOwnerProperties()));
ASSERT_EQ("2: []", GetTreeState(frame_tree));
}
@@ -430,20 +464,18 @@ TEST_F(FrameTreeTest, ProcessCrashClearsGlobalMap) {
// Add a couple child frames to the main frame.
FrameTreeNode* root = contents()->GetFrameTree()->root();
- main_test_rfh()->OnCreateChildFrame(22, blink::WebTreeScopeType::Document,
- std::string(),
- blink::WebSandboxFlags::None,
- blink::WebFrameOwnerProperties());
- main_test_rfh()->OnCreateChildFrame(23, blink::WebTreeScopeType::Document,
- std::string(),
- blink::WebSandboxFlags::None,
- blink::WebFrameOwnerProperties());
+ main_test_rfh()->OnCreateChildFrame(
+ 22, blink::WebTreeScopeType::Document, std::string(), "uniqueName0",
+ blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
+ main_test_rfh()->OnCreateChildFrame(
+ 23, blink::WebTreeScopeType::Document, std::string(), "uniqueName1",
+ blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
// Add one grandchild frame.
RenderFrameHostImpl* child1_rfh = root->child_at(0)->current_frame_host();
- child1_rfh->OnCreateChildFrame(33, blink::WebTreeScopeType::Document,
- std::string(), blink::WebSandboxFlags::None,
- blink::WebFrameOwnerProperties());
+ child1_rfh->OnCreateChildFrame(
+ 33, blink::WebTreeScopeType::Document, std::string(), "uniqueName2",
+ blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
// Ensure they can be found by id.
int id1 = root->child_at(0)->frame_tree_node_id();
diff --git a/chromium/content/browser/frame_host/interstitial_page_impl.cc b/chromium/content/browser/frame_host/interstitial_page_impl.cc
index 251e3bc642f..784c9b481d5 100644
--- a/chromium/content/browser/frame_host/interstitial_page_impl.cc
+++ b/chromium/content/browser/frame_host/interstitial_page_impl.cc
@@ -53,28 +53,6 @@ using blink::WebDragOperation;
using blink::WebDragOperationsMask;
namespace content {
-namespace {
-
-void ResourceRequestHelper(ResourceDispatcherHostImpl* rdh,
- int process_id,
- int render_view_host_id,
- ResourceRequestAction action) {
- switch (action) {
- case BLOCK:
- rdh->BlockRequestsForRoute(process_id, render_view_host_id);
- break;
- case RESUME:
- rdh->ResumeBlockedRequestsForRoute(process_id, render_view_host_id);
- break;
- case CANCEL:
- rdh->CancelBlockedRequestsForRoute(process_id, render_view_host_id);
- break;
- default:
- NOTREACHED();
- }
-}
-
-} // namespace
class InterstitialPageImpl::InterstitialPageRVHDelegateView
: public RenderViewHostDelegateView {
@@ -181,15 +159,17 @@ InterstitialPageImpl::InterstitialPageImpl(
// TODO(creis): We will also need to pass delegates for the RVHM as we
// start to use it.
frame_tree_(new InterstitialPageNavigatorImpl(this, controller_),
- this, this, this,
+ this,
+ this,
+ this,
static_cast<WebContentsImpl*>(web_contents)),
original_child_id_(web_contents->GetRenderProcessHost()->GetID()),
original_rvh_id_(web_contents->GetRenderViewHost()->GetRoutingID()),
should_revert_web_contents_title_(false),
- web_contents_was_loading_(false),
resource_dispatcher_host_notified_(false),
rvh_delegate_view_(new InterstitialPageRVHDelegateView(this)),
create_view_(true),
+ pause_throbber_(false),
delegate_(delegate),
weak_ptr_factory_(this) {
InitInterstitialPageMap();
@@ -523,6 +503,9 @@ void InterstitialPageImpl::DidNavigate(
return;
}
+ // The interstitial is not loading anymore so stop the throbber.
+ pause_throbber_ = true;
+
// The RenderViewHost has loaded its contents, we can show it now.
if (!controller_->delegate()->IsHidden())
render_view_host_->GetWidget()->GetView()->Show();
@@ -540,14 +523,6 @@ void InterstitialPageImpl::DidNavigate(
// Hide the original RVH since we're showing the interstitial instead.
rwh_view->Hide();
}
-
- // Notify the tab we are not loading so the throbber is stopped. It also
- // causes a WebContentsObserver::DidStopLoading callback that the
- // AutomationProvider (used by the UI tests) expects to consider a navigation
- // as complete. Without this, navigating in a UI test to a URL that triggers
- // an interstitial would hang.
- web_contents_was_loading_ = controller_->delegate()->IsLoading();
- controller_->delegate()->SetIsLoading(false, true, NULL);
}
RendererPreferences InterstitialPageImpl::GetRendererPrefs(
@@ -577,17 +552,6 @@ void InterstitialPageImpl::HandleKeyboardEvent(
render_widget_host_delegate_->HandleKeyboardEvent(event);
}
-#if defined(OS_WIN)
-gfx::NativeViewAccessible
-InterstitialPageImpl::GetParentNativeViewAccessible() {
- if (web_contents_) {
- WebContentsImpl* wci = static_cast<WebContentsImpl*>(web_contents_);
- return wci->GetParentNativeViewAccessible();
- }
- return NULL;
-}
-#endif
-
WebContents* InterstitialPageImpl::web_contents() const {
return web_contents_;
}
@@ -657,8 +621,8 @@ void InterstitialPageImpl::Proceed() {
action_taken_ = PROCEED_ACTION;
// Resumes the throbber, if applicable.
- if (web_contents_was_loading_)
- controller_->delegate()->SetIsLoading(true, true, NULL);
+ pause_throbber_ = false;
+ controller_->delegate()->DidProceedOnInterstitial();
// If this is a new navigation, the old page is going away, so we cancel any
// blocked requests for it. If it is not a new navigation, then it means the
@@ -855,22 +819,25 @@ void InterstitialPageImpl::TakeActionOnResourceDispatcher(
// The tab might not have a render_view_host if it was closed (in which case,
// we have taken care of the blocked requests when processing
// NOTIFY_RENDER_WIDGET_HOST_DESTROYED.
- // Also we need to test there is a ResourceDispatcherHostImpl, as when unit-
- // tests we don't have one.
RenderViewHostImpl* rvh = RenderViewHostImpl::FromID(original_child_id_,
original_rvh_id_);
- if (!rvh || !ResourceDispatcherHostImpl::Get())
+ if (!rvh)
return;
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(
- &ResourceRequestHelper,
- ResourceDispatcherHostImpl::Get(),
- original_child_id_,
- original_rvh_id_,
- action));
+ RenderFrameHostImpl* rfh =
+ static_cast<RenderFrameHostImpl*>(rvh->GetMainFrame());
+ switch (action) {
+ case BLOCK:
+ ResourceDispatcherHost::BlockRequestsForFrameFromUI(rfh);
+ break;
+ case RESUME:
+ ResourceDispatcherHost::ResumeBlockedRequestsForFrameFromUI(rfh);
+ break;
+ default:
+ DCHECK_EQ(action, CANCEL);
+ ResourceDispatcherHostImpl::CancelBlockedRequestsForFrameFromUI(rfh);
+ break;
+ }
}
void InterstitialPageImpl::OnDomOperationResponse(
diff --git a/chromium/content/browser/frame_host/interstitial_page_impl.h b/chromium/content/browser/frame_host/interstitial_page_impl.h
index 32361e881e3..f619d050d24 100644
--- a/chromium/content/browser/frame_host/interstitial_page_impl.h
+++ b/chromium/content/browser/frame_host/interstitial_page_impl.h
@@ -88,6 +88,8 @@ class CONTENT_EXPORT InterstitialPageImpl
}
bool reload_on_dont_proceed() const { return reload_on_dont_proceed_; }
+ bool pause_throbber() const { return pause_throbber_; }
+
// TODO(nasko): This should move to InterstitialPageNavigatorImpl, but in
// the meantime make it public, so it can be called directly.
void DidNavigate(
@@ -154,9 +156,6 @@ class CONTENT_EXPORT InterstitialPageImpl
bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
bool* is_keyboard_shortcut) override;
void HandleKeyboardEvent(const NativeWebKeyboardEvent& event) override;
-#if defined(OS_WIN)
- gfx::NativeViewAccessible GetParentNativeViewAccessible() override;
-#endif
bool enabled() const { return enabled_; }
WebContents* web_contents() const;
@@ -271,10 +270,6 @@ class CONTENT_EXPORT InterstitialPageImpl
// revert it to its original value).
bool should_revert_web_contents_title_;
- // Whether or not the contents was loading resources when the interstitial was
- // shown. We restore this state if the user proceeds from the interstitial.
- bool web_contents_was_loading_;
-
// Whether the ResourceDispatcherHost has been notified to cancel/resume the
// resource requests blocked for the RenderViewHost.
bool resource_dispatcher_host_notified_;
@@ -283,7 +278,7 @@ class CONTENT_EXPORT InterstitialPageImpl
// interstitial is hidden.
base::string16 original_web_contents_title_;
- // Our RenderViewHostViewDelegate, necessary for accelerators to work.
+ // Our RenderViewHostDelegateView, necessary for accelerators to work.
scoped_ptr<InterstitialPageRVHDelegateView> rvh_delegate_view_;
// Settings passed to the renderer.
@@ -291,6 +286,11 @@ class CONTENT_EXPORT InterstitialPageImpl
bool create_view_;
+ // Whether the throbber should be paused. This is true from the moment the
+ // interstitial is shown until the moment the interstitial goes away or the
+ // user chooses to proceed.
+ bool pause_throbber_;
+
scoped_ptr<InterstitialPageDelegate> delegate_;
scoped_refptr<SessionStorageNamespace> session_storage_namespace_;
diff --git a/chromium/content/browser/frame_host/navigation_controller_android.cc b/chromium/content/browser/frame_host/navigation_controller_android.cc
index 81745177fb9..96aceacc070 100644
--- a/chromium/content/browser/frame_host/navigation_controller_android.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_android.cc
@@ -159,11 +159,11 @@ void NavigationControllerAndroid::ReloadToRefreshContent(
navigation_controller_->ReloadToRefreshContent(check_for_repost);
}
-void NavigationControllerAndroid::ReloadIgnoringCache(
+void NavigationControllerAndroid::ReloadBypassingCache(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
jboolean check_for_repost) {
- navigation_controller_->ReloadIgnoringCache(check_for_repost);
+ navigation_controller_->ReloadBypassingCache(check_for_repost);
}
void NavigationControllerAndroid::ReloadDisableLoFi(
diff --git a/chromium/content/browser/frame_host/navigation_controller_android.h b/chromium/content/browser/frame_host/navigation_controller_android.h
index e22eb882a82..f2ec9058d95 100644
--- a/chromium/content/browser/frame_host/navigation_controller_android.h
+++ b/chromium/content/browser/frame_host/navigation_controller_android.h
@@ -57,9 +57,9 @@ class CONTENT_EXPORT NavigationControllerAndroid {
void ReloadToRefreshContent(JNIEnv* env,
jobject obj,
jboolean check_for_repost);
- void ReloadIgnoringCache(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
- jboolean check_for_repost);
+ void ReloadBypassingCache(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jboolean check_for_repost);
void ReloadDisableLoFi(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
jboolean check_for_repost);
diff --git a/chromium/content/browser/frame_host/navigation_controller_delegate.h b/chromium/content/browser/frame_host/navigation_controller_delegate.h
index 9922ac59817..8a20e2bcd01 100644
--- a/chromium/content/browser/frame_host/navigation_controller_delegate.h
+++ b/chromium/content/browser/frame_host/navigation_controller_delegate.h
@@ -42,7 +42,6 @@ class NavigationControllerDelegate {
virtual void Stop() = 0;
virtual int32_t GetMaxPageID() = 0;
virtual int32_t GetMaxPageIDForSiteInstance(SiteInstance* site_instance) = 0;
- virtual bool IsLoading() const = 0;
virtual bool IsBeingDestroyed() const = 0;
virtual bool CanOverscrollContent() const = 0;
@@ -71,10 +70,8 @@ class NavigationControllerDelegate {
RenderFrameHost* render_frame_host) = 0;
virtual void AttachInterstitialPage(
InterstitialPageImpl* interstitial_page) = 0;
+ virtual void DidProceedOnInterstitial() = 0;
virtual void DetachInterstitialPage() = 0;
- virtual void SetIsLoading(bool is_loading,
- bool to_different_document,
- LoadNotificationDetails* details) = 0;
};
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl.cc b/chromium/content/browser/frame_host/navigation_controller_impl.cc
index 071cec8e4bb..ac57709fb7e 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl.cc
@@ -57,6 +57,7 @@
#include "content/browser/frame_host/interstitial_page_impl.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
#include "content/browser/frame_host/navigation_entry_screenshot_manager.h"
+#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/browser/frame_host/navigator.h"
#include "content/browser/renderer_host/render_view_host_impl.h" // Temporary
#include "content/browser/site_instance_impl.h"
@@ -76,10 +77,9 @@
#include "content/public/browser/user_metrics.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_constants.h"
-#include "content/public/common/content_switches.h"
+#include "content/public/common/content_features.h"
#include "media/base/mime_util.h"
#include "net/base/escape.h"
-#include "net/base/net_util.h"
#include "skia/ext/platform_canvas.h"
#include "url/url_constants.h"
@@ -148,13 +148,6 @@ bool ShouldKeepOverride(const NavigationEntry* last_entry) {
return last_entry && last_entry->GetIsOverridingUserAgent();
}
-// Helper method for FrameTree::ForEach to set the nav_entry_id on each current
-// RenderFrameHost in the tree.
-bool SetFrameNavEntryID(int nav_entry_id, FrameTreeNode* node) {
- node->current_frame_host()->set_nav_entry_id(nav_entry_id);
- return true;
-}
-
} // namespace
// NavigationControllerImpl ----------------------------------------------------
@@ -235,7 +228,6 @@ NavigationControllerImpl::NavigationControllerImpl(
: browser_context_(browser_context),
pending_entry_(NULL),
failed_pending_entry_id_(0),
- failed_pending_entry_should_replace_(false),
last_committed_entry_index_(-1),
pending_entry_index_(-1),
transient_entry_index_(-1),
@@ -295,15 +287,30 @@ void NavigationControllerImpl::Reload(bool check_for_repost) {
ReloadInternal(check_for_repost, RELOAD);
}
void NavigationControllerImpl::ReloadToRefreshContent(bool check_for_repost) {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableNonValidatingReloadOnRefreshContent)) {
- ReloadInternal(check_for_repost, NO_RELOAD);
- } else {
- ReloadInternal(check_for_repost, RELOAD);
+ if (base::FeatureList::IsEnabled(
+ features::kNonValidatingReloadOnRefreshContent)) {
+ // Cause this reload to behave like NAVIGATION_TYPE_SAME_PAGE (e.g., enter
+ // in the omnibox), so that the main resource is cache-validated but all
+ // other resources use the cache as much as possible. This requires
+ // navigating to the current URL in a new pending entry.
+ // TODO(toyoshim): Introduce a new ReloadType for this behavior if it
+ // becomes the default.
+ NavigationEntryImpl* last_committed = GetLastCommittedEntry();
+
+ // If the last committed entry does not exist, or a repost check dialog is
+ // really needed, use a standard reload instead.
+ if (last_committed &&
+ !(check_for_repost && last_committed->GetHasPostData())) {
+ LoadURL(last_committed->GetURL(), last_committed->GetReferrer(),
+ last_committed->GetTransitionType(),
+ last_committed->extra_headers());
+ return;
+ }
}
+ ReloadInternal(check_for_repost, RELOAD);
}
-void NavigationControllerImpl::ReloadIgnoringCache(bool check_for_repost) {
- ReloadInternal(check_for_repost, RELOAD_IGNORING_CACHE);
+void NavigationControllerImpl::ReloadBypassingCache(bool check_for_repost) {
+ ReloadInternal(check_for_repost, RELOAD_BYPASSING_CACHE);
}
void NavigationControllerImpl::ReloadOriginalRequestURL(bool check_for_repost) {
ReloadInternal(check_for_repost, RELOAD_ORIGINAL_REQUEST_URL);
@@ -581,48 +588,13 @@ bool NavigationControllerImpl::CanGoToOffset(int offset) const {
}
void NavigationControllerImpl::GoBack() {
- if (!CanGoBack()) {
- NOTREACHED();
- return;
- }
-
- // Base the navigation on where we are now...
- int current_index = GetCurrentEntryIndex();
-
- DiscardNonCommittedEntries();
-
- pending_entry_index_ = current_index - 1;
- entries_[pending_entry_index_]->SetTransitionType(
- ui::PageTransitionFromInt(
- entries_[pending_entry_index_]->GetTransitionType() |
- ui::PAGE_TRANSITION_FORWARD_BACK));
- NavigateToPendingEntry(NO_RELOAD);
+ // Call GoToIndex rather than GoToOffset to get the NOTREACHED() check.
+ GoToIndex(GetIndexForOffset(-1));
}
void NavigationControllerImpl::GoForward() {
- if (!CanGoForward()) {
- NOTREACHED();
- return;
- }
-
- bool transient = (transient_entry_index_ != -1);
-
- // Base the navigation on where we are now...
- int current_index = GetCurrentEntryIndex();
-
- DiscardNonCommittedEntries();
-
- pending_entry_index_ = current_index;
- // If there was a transient entry, we removed it making the current index
- // the next page.
- if (!transient)
- pending_entry_index_++;
-
- entries_[pending_entry_index_]->SetTransitionType(
- ui::PageTransitionFromInt(
- entries_[pending_entry_index_]->GetTransitionType() |
- ui::PAGE_TRANSITION_FORWARD_BACK));
- NavigateToPendingEntry(NO_RELOAD);
+ // Call GoToIndex rather than GoToOffset to get the NOTREACHED() check.
+ GoToIndex(GetIndexForOffset(1));
}
void NavigationControllerImpl::GoToIndex(int index) {
@@ -653,6 +625,7 @@ void NavigationControllerImpl::GoToIndex(int index) {
}
void NavigationControllerImpl::GoToOffset(int offset) {
+ // Note: This is actually reached in unit tests.
if (!CanGoToOffset(offset))
return;
@@ -822,6 +795,12 @@ void NavigationControllerImpl::LoadURLWithParams(const LoadURLParams& params) {
LoadEntry(std::move(entry));
}
+bool NavigationControllerImpl::PendingEntryMatchesHandle(
+ NavigationHandleImpl* handle) const {
+ return pending_entry_ &&
+ pending_entry_->GetUniqueID() == handle->pending_nav_entry_id();
+}
+
bool NavigationControllerImpl::RendererDidNavigate(
RenderFrameHostImpl* rfh,
const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
@@ -846,20 +825,8 @@ bool NavigationControllerImpl::RendererDidNavigate(
pending_entry_->restore_type() != NavigationEntryImpl::RESTORE_NONE)
pending_entry_->set_restore_type(NavigationEntryImpl::RESTORE_NONE);
- // If we are doing a cross-site reload, we need to replace the existing
- // navigation entry, not add another entry to the history. This has the side
- // effect of removing forward browsing history, if such existed. Or if we are
- // doing a cross-site redirect navigation, we will do a similar thing.
- //
- // If this is an error load, we may have already removed the pending entry
- // when we got the notice of the load failure. If so, look at the copy of the
- // pending parameters that were saved.
- if (params.url_is_unreachable && failed_pending_entry_id_ != 0) {
- details->did_replace_entry = failed_pending_entry_should_replace_;
- } else {
- details->did_replace_entry = pending_entry_ &&
- pending_entry_->should_replace_entry();
- }
+ // The renderer tells us whether the navigation replaces the current entry.
+ details->did_replace_entry = params.should_replace_current_entry;
// Do navigation-type specific actions. These will make and commit an entry.
details->type = ClassifyNavigation(rfh, params);
@@ -880,7 +847,7 @@ bool NavigationControllerImpl::RendererDidNavigate(
RendererDidNavigateToSamePage(rfh, params);
break;
case NAVIGATION_TYPE_NEW_SUBFRAME:
- RendererDidNavigateNewSubframe(rfh, params);
+ RendererDidNavigateNewSubframe(rfh, params, details->did_replace_entry);
break;
case NAVIGATION_TYPE_AUTO_SUBFRAME:
if (!RendererDidNavigateAutoSubframe(rfh, params))
@@ -976,8 +943,9 @@ bool NavigationControllerImpl::RendererDidNavigate(
// committed anything in this navigation or not). This allows things like
// state and title updates from RenderFrames to apply to the latest relevant
// NavigationEntry.
- delegate_->GetFrameTree()->ForEach(
- base::Bind(&SetFrameNavEntryID, active_entry->GetUniqueID()));
+ int nav_entry_id = active_entry->GetUniqueID();
+ for (FrameTreeNode* node : delegate_->GetFrameTree()->Nodes())
+ node->current_frame_host()->set_nav_entry_id(nav_entry_id);
return true;
}
@@ -1003,6 +971,18 @@ NavigationType NavigationControllerImpl::ClassifyNavigation(
return NAVIGATION_TYPE_NEW_SUBFRAME;
}
+ // Cross-process location.replace navigations should be classified as New with
+ // replacement rather than ExistingPage, since it is not safe to reuse the
+ // NavigationEntry.
+ // TODO(creis): Have the renderer classify location.replace as
+ // did_create_new_entry for all cases and eliminate this special case. This
+ // requires updating several test expectations. See https://crbug.com/317872.
+ if (!rfh->GetParent() && GetLastCommittedEntry() &&
+ GetLastCommittedEntry()->site_instance() != rfh->GetSiteInstance() &&
+ params.should_replace_current_entry) {
+ return NAVIGATION_TYPE_NEW_PAGE;
+ }
+
// We only clear the session history when navigating to a new page.
DCHECK(!params.history_list_was_cleared);
@@ -1090,12 +1070,18 @@ void NavigationControllerImpl::RendererDidNavigateToNewPage(
scoped_ptr<NavigationEntryImpl> new_entry;
bool update_virtual_url;
// Only make a copy of the pending entry if it is appropriate for the new page
- // that was just loaded. We verify this at a coarse grain by checking that
- // the SiteInstance hasn't been assigned to something else, and by making sure
- // that the pending entry was intended as a new entry (rather than being a
- // history navigation that was interrupted by an unrelated, renderer-initiated
- // navigation).
- if (pending_entry_ && pending_entry_index_ == -1 &&
+ // that was just loaded. Verify this by checking if the entry corresponds
+ // to the current navigation handle. Note that in some tests the render frame
+ // host does not have a valid handle. Additionally, coarsely check that:
+ // 1. The SiteInstance hasn't been assigned to something else.
+ // 2. The pending entry was intended as a new entry, rather than being a
+ // history navigation that was interrupted by an unrelated,
+ // renderer-initiated navigation.
+ // TODO(csharrison): Investigate whether we can remove some of the coarser
+ // checks.
+ NavigationHandleImpl* handle = rfh->navigation_handle();
+ DCHECK(handle);
+ if (PendingEntryMatchesHandle(handle) && pending_entry_index_ == -1 &&
(!pending_entry_->site_instance() ||
pending_entry_->site_instance() == rfh->GetSiteInstance())) {
new_entry = pending_entry_->Clone();
@@ -1262,7 +1248,8 @@ void NavigationControllerImpl::RendererDidNavigateToSamePage(
void NavigationControllerImpl::RendererDidNavigateNewSubframe(
RenderFrameHostImpl* rfh,
- const FrameHostMsg_DidCommitProvisionalLoad_Params& params) {
+ const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
+ bool replace_entry) {
DCHECK(ui::PageTransitionCoreTypeIs(params.transition,
ui::PAGE_TRANSITION_MANUAL_SUBFRAME));
@@ -1292,7 +1279,7 @@ void NavigationControllerImpl::RendererDidNavigateNewSubframe(
}
new_entry->SetPageID(params.page_id);
- InsertOrReplaceEntry(std::move(new_entry), false);
+ InsertOrReplaceEntry(std::move(new_entry), replace_entry);
}
bool NavigationControllerImpl::RendererDidNavigateAutoSubframe(
@@ -1592,21 +1579,25 @@ NavigationControllerImpl::GetSessionStorageNamespace(SiteInstance* instance) {
browser_context_, instance->GetSiteURL());
}
+ // TODO(ajwong): Should this use the |partition_id| directly rather than
+ // re-lookup via |instance|? http://crbug.com/142685
+ StoragePartition* partition =
+ BrowserContext::GetStoragePartition(browser_context_, instance);
+ DOMStorageContextWrapper* context_wrapper =
+ static_cast<DOMStorageContextWrapper*>(partition->GetDOMStorageContext());
+
SessionStorageNamespaceMap::const_iterator it =
session_storage_namespace_map_.find(partition_id);
- if (it != session_storage_namespace_map_.end())
+ if (it != session_storage_namespace_map_.end()) {
+ // Ensure that this namespace actually belongs to this partition.
+ DCHECK(static_cast<SessionStorageNamespaceImpl*>(it->second.get())->
+ IsFromContext(context_wrapper));
return it->second.get();
+ }
// Create one if no one has accessed session storage for this partition yet.
- //
- // TODO(ajwong): Should this use the |partition_id| directly rather than
- // re-lookup via |instance|? http://crbug.com/142685
- StoragePartition* partition =
- BrowserContext::GetStoragePartition(browser_context_, instance);
SessionStorageNamespaceImpl* session_storage_namespace =
- new SessionStorageNamespaceImpl(
- static_cast<DOMStorageContextWrapper*>(
- partition->GetDOMStorageContext()));
+ new SessionStorageNamespaceImpl(context_wrapper);
session_storage_namespace_map_[partition_id] = session_storage_namespace;
return session_storage_namespace;
@@ -1875,8 +1866,10 @@ void NavigationControllerImpl::FindFramesToNavigate(
same_document_loads->push_back(std::make_pair(frame, new_item));
} else {
different_document_loads->push_back(std::make_pair(frame, new_item));
+ // For a different document, the subframes will be destroyed, so there's
+ // no need to consider them.
+ return;
}
- return;
}
for (size_t i = 0; i < frame->child_count(); i++) {
@@ -1973,8 +1966,6 @@ void NavigationControllerImpl::DiscardPendingEntry(bool was_failure) {
if (was_failure && pending_entry_) {
failed_pending_entry_id_ = pending_entry_->GetUniqueID();
- failed_pending_entry_should_replace_ =
- pending_entry_->should_replace_entry();
} else {
failed_pending_entry_id_ = 0;
}
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl.h b/chromium/content/browser/frame_host/navigation_controller_impl.h
index 72b76d7464a..a0067f49051 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl.h
+++ b/chromium/content/browser/frame_host/navigation_controller_impl.h
@@ -87,7 +87,7 @@ class CONTENT_EXPORT NavigationControllerImpl
bool IsInitialBlankNavigation() const override;
void Reload(bool check_for_repost) override;
void ReloadToRefreshContent(bool check_for_repost) override;
- void ReloadIgnoringCache(bool check_for_repost) override;
+ void ReloadBypassingCache(bool check_for_repost) override;
void ReloadOriginalRequestURL(bool check_for_repost) override;
void ReloadDisableLoFi(bool check_for_repost) override;
void NotifyEntryChanged(const NavigationEntry* entry) override;
@@ -258,6 +258,10 @@ class CONTENT_EXPORT NavigationControllerImpl
FrameLoadVector* sameDocumentLoads,
FrameLoadVector* differentDocumentLoads);
+ // Returns whether there is a pending NavigationEntry whose unique ID matches
+ // the given NavigationHandle's pending_nav_entry_id.
+ bool PendingEntryMatchesHandle(NavigationHandleImpl* handle) const;
+
// Classifies the given renderer navigation (see the NavigationType enum).
NavigationType ClassifyNavigation(
RenderFrameHostImpl* rfh,
@@ -272,9 +276,11 @@ class CONTENT_EXPORT NavigationControllerImpl
// anything if some random subframe is loaded. It will return true if anything
// changed, or false if not.
//
- // The functions taking |did_replace_entry| will fill into the given variable
- // whether the last entry has been replaced or not.
- // See LoadCommittedDetails.did_replace_entry.
+ // The NewPage and NewSubframe functions take in |replace_entry| to pass to
+ // InsertOrReplaceEntry, in case the newly created NavigationEntry is meant to
+ // replace the current one (e.g., for location.replace or successful loads
+ // after net errors), in contrast to updating a NavigationEntry in place
+ // (e.g., for history.replaceState).
void RendererDidNavigateToNewPage(
RenderFrameHostImpl* rfh,
const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
@@ -287,12 +293,14 @@ class CONTENT_EXPORT NavigationControllerImpl
const FrameHostMsg_DidCommitProvisionalLoad_Params& params);
void RendererDidNavigateNewSubframe(
RenderFrameHostImpl* rfh,
- const FrameHostMsg_DidCommitProvisionalLoad_Params& params);
+ const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
+ bool replace_entry);
bool RendererDidNavigateAutoSubframe(
RenderFrameHostImpl* rfh,
const FrameHostMsg_DidCommitProvisionalLoad_Params& params);
- // Helper function for code shared between Reload() and ReloadIgnoringCache().
+ // Helper function for code shared between Reload() and
+ // ReloadBypassingCache().
void ReloadInternal(bool check_for_repost, ReloadType reload_type);
// Actually issues the navigation held in pending_entry.
@@ -369,8 +377,7 @@ class CONTENT_EXPORT NavigationControllerImpl
NavigationEntryImpl* pending_entry_;
// If a new entry fails loading, details about it are temporarily held here
- // until the error page is shown. These variables are only valid if
- // |failed_pending_entry_id_| is not 0.
+ // until the error page is shown (or 0 otherwise).
//
// TODO(avi): We need a better way to handle the connection between failed
// loads and the subsequent load of the error page. This current approach has
@@ -378,7 +385,6 @@ class CONTENT_EXPORT NavigationControllerImpl
// error page loaded, and 2. This doesn't work very well for frames.
// http://crbug.com/474261
int failed_pending_entry_id_;
- bool failed_pending_entry_should_replace_;
// The index of the currently visible entry.
int last_committed_entry_index_;
@@ -428,7 +434,7 @@ class CONTENT_EXPORT NavigationControllerImpl
// The maximum number of entries that a navigation controller can store.
static size_t max_entry_count_for_testing_;
- // If a repost is pending, its type (RELOAD or RELOAD_IGNORING_CACHE),
+ // If a repost is pending, its type (RELOAD or RELOAD_BYPASSING_CACHE),
// NO_RELOAD otherwise.
ReloadType pending_reload_;
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc
index 5ead3764296..561f84ccc0f 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl_browsertest.cc
@@ -15,8 +15,11 @@
#include "content/browser/frame_host/frame_navigation_entry.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/page_state_serialization.h"
#include "content/common/site_isolation_policy.h"
+#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/resource_controller.h"
#include "content/public/browser/resource_dispatcher_host.h"
@@ -25,6 +28,7 @@
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/bindings_policy.h"
+#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
@@ -34,6 +38,7 @@
#include "content/shell/browser/shell.h"
#include "content/shell/common/shell_switches.h"
#include "content/test/content_browser_test_utils_internal.h"
+#include "content/test/test_frame_navigation_observer.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/url_request/url_request_failed_job.h"
@@ -631,7 +636,7 @@ class LoadCommittedCapturer : public WebContentsObserver {
// Don't pay attention to swapped out RenderFrameHosts in the main frame.
// TODO(nasko): Remove once swappedout:// is gone.
// See https://crbug.com/357747.
- if (!RenderFrameHostImpl::IsRFHStateActive(rfh->rfh_state())) {
+ if (!rfh->is_active()) {
DLOG(INFO) << "Skipping swapped out RFH: "
<< rfh->GetSiteInstance()->GetSiteURL();
return;
@@ -721,15 +726,15 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
NavigateToURL(shell(), GURL(url::kAboutBlankURL));
EXPECT_EQ(3, controller.GetEntryCount());
- // ... and replace it with a failed load. (Note that when you set the
- // should_replace_current_entry flag, the navigation is classified as NEW_PAGE
- // because that is a classification of the renderer's behavior, and the flag
- // is a browser-side flag.)
+ // ... and replace it with a failed load.
+ // TODO(creis): Make this be NEW_PAGE along with the other location.replace
+ // cases. There isn't much impact to having this be EXISTING_PAGE for now.
+ // See https://crbug.com/317872.
{
FrameNavigateParamsCapturer capturer(root);
NavigateToURLAndReplace(shell(), error_url);
capturer.Wait();
- EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
+ EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, capturer.details().type);
NavigationEntry* entry = controller.GetLastCommittedEntry();
EXPECT_EQ(PAGE_TYPE_ERROR, entry->GetPageType());
EXPECT_EQ(3, controller.GetEntryCount());
@@ -829,6 +834,20 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
EXPECT_TRUE(capturer.details().is_in_page);
}
+
+ if (AreAllSitesIsolatedForTesting()) {
+ // Cross-process location.replace().
+ FrameNavigateParamsCapturer capturer(root);
+ GURL frame_url(embedded_test_server()->GetURL(
+ "foo.com", "/navigation_controller/simple_page_1.html"));
+ std::string script = "location.replace('" + frame_url.spec() + "')";
+ EXPECT_TRUE(content::ExecuteScript(root->current_frame_host(), script));
+ capturer.Wait();
+ EXPECT_EQ(ui::PAGE_TRANSITION_LINK | ui::PAGE_TRANSITION_CLIENT_REDIRECT,
+ capturer.params().transition);
+ EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
+ EXPECT_FALSE(capturer.details().is_in_page);
+ }
}
// Verify that navigations for NAVIGATION_TYPE_EXISTING_PAGE are correctly
@@ -952,6 +971,8 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
{
// location.replace().
+ // TODO(creis): Change this to be NEW_PAGE with replacement in
+ // https://crbug.com/317872.
FrameNavigateParamsCapturer capturer(root);
GURL frame_url(embedded_test_server()->GetURL(
"/navigation_controller/simple_page_1.html"));
@@ -2673,8 +2694,18 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"bar.com", "/navigation_controller/simple_page_1.html"));
NavigateFrameToURL(foo_subframe, bar_url);
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
- EXPECT_NE(main_site_instance,
- foo_subframe->current_frame_host()->GetSiteInstance());
+
+ // When run just with subframe navigation entries enabled and not in
+ // site-per-process-mode the subframe should be in the same SiteInstance as
+ // its parent.
+ if (!AreAllSitesIsolatedForTesting()) {
+ EXPECT_EQ(main_site_instance,
+ foo_subframe->current_frame_host()->GetSiteInstance());
+ } else {
+ EXPECT_NE(main_site_instance,
+ foo_subframe->current_frame_host()->GetSiteInstance());
+ }
+
foo_subframe_entry =
controller.GetLastCommittedEntry()->GetFrameEntry(foo_subframe);
EXPECT_EQ(named_subframe_name, foo_subframe_entry->frame_unique_name());
@@ -2940,6 +2971,63 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
DoReplaceStateWhilePending(shell(), url, url, "simple_page_1.html");
}
+// Ensure that a pending NavigationEntry for a different navigation doesn't
+// cause a commit to be incorrectly treated as a replacement.
+// See https://crbug.com/593153.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+ OtherCommitDuringPendingEntryWithReplacement) {
+ NavigationControllerImpl& controller = static_cast<NavigationControllerImpl&>(
+ shell()->web_contents()->GetController());
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // Load an initial page.
+ GURL start_url(embedded_test_server()->GetURL(
+ "/navigation_controller/simple_page_1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), start_url));
+ int entry_count = controller.GetEntryCount();
+ EXPECT_EQ(1, controller.GetEntryCount());
+ EXPECT_EQ(start_url, controller.GetLastCommittedEntry()->GetURL());
+
+ // Start a cross-process navigation with replacement, which never completes.
+ GURL foo_url(embedded_test_server()->GetURL(
+ "foo.com", "/navigation_controller/page_with_links.html"));
+ NavigationStallDelegate stall_delegate(foo_url);
+ ResourceDispatcherHost::Get()->SetDelegate(&stall_delegate);
+ NavigationController::LoadURLParams params(foo_url);
+ params.should_replace_current_entry = true;
+ controller.LoadURLWithParams(params);
+
+ // That should be the pending entry.
+ NavigationEntryImpl* entry = controller.GetPendingEntry();
+ ASSERT_NE(nullptr, entry);
+ EXPECT_EQ(foo_url, entry->GetURL());
+ EXPECT_EQ(entry_count, controller.GetEntryCount());
+
+ {
+ // Now the existing page uses history.pushState() while the pending entry
+ // for the other navigation still exists.
+ FrameNavigateParamsCapturer capturer(root);
+ capturer.set_wait_for_load(false);
+ std::string script = "history.pushState({}, '', 'pushed')";
+ EXPECT_TRUE(content::ExecuteScript(root->current_frame_host(), script));
+ capturer.Wait();
+ EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, capturer.details().type);
+ EXPECT_TRUE(capturer.details().is_in_page);
+ }
+
+ // The in-page navigation should not have replaced the previous entry.
+ GURL push_state_url(
+ embedded_test_server()->GetURL("/navigation_controller/pushed"));
+ EXPECT_EQ(entry_count + 1, controller.GetEntryCount());
+ EXPECT_EQ(push_state_url, controller.GetLastCommittedEntry()->GetURL());
+ EXPECT_EQ(start_url, controller.GetEntryAtIndex(0)->GetURL());
+
+ ResourceDispatcherHost::Get()->SetDelegate(nullptr);
+}
+
// Ensure the renderer process does not get confused about the current entry
// due to subframes and replaced entries. See https://crbug.com/480201.
// TODO(creis): Re-enable for Site Isolation FYI bots: https://crbug.com/502317.
@@ -3136,6 +3224,15 @@ class FailureWatcher : public WebContentsObserver {
message_loop_runner_->Quit();
}
+ void DidFinishNavigation(NavigationHandle* handle) override {
+ if (handle->GetFrameTreeNodeId() != frame_tree_node_id_)
+ return;
+ if (handle->HasCommitted())
+ return;
+
+ message_loop_runner_->Quit();
+ }
+
// The id of the FrameTreeNode whose navigations to observe.
int frame_tree_node_id_;
@@ -3146,7 +3243,7 @@ class FailureWatcher : public WebContentsObserver {
} // namespace
IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
- StopCausesFailureDespiteJavaScriptURL) {
+ DISABLED_StopCausesFailureDespiteJavaScriptURL) {
NavigationControllerImpl& controller =
static_cast<NavigationControllerImpl&>(
shell()->web_contents()->GetController());
@@ -3160,7 +3257,7 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
"/navigation_controller/simple_page_1.html"));
EXPECT_TRUE(NavigateToURL(shell(), url1));
- // Have the user decide to go to a different page which is very slow.
+ // Have the user decide to go to a different page which will not commit.
GURL url2(embedded_test_server()->GetURL(
"/navigation_controller/simple_page_2.html"));
NavigationStallDelegate stall_delegate(url2);
@@ -3180,8 +3277,10 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
// This LoadURL ends up purging the pending entry, which is why this is
// tricky.
EXPECT_EQ(nullptr, controller.GetPendingEntry());
+ EXPECT_TRUE(shell()->web_contents()->IsLoading());
shell()->web_contents()->Stop();
watcher.Wait();
+ EXPECT_FALSE(shell()->web_contents()->IsLoading());
}
ResourceDispatcherHost::Get()->SetDelegate(nullptr);
@@ -3262,4 +3361,309 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, ReloadOriginalRequest) {
ExecuteScript(shell()->web_contents(), "console.log('Success');"));
}
+// This tests that 1) the initial "about:blank" URL is elided from the
+// navigation history of a subframe when it is loaded, and 2) that that initial
+// "about:blank" returns if it is navigated to as part of a history navigation.
+// See http://crbug.com/542299 and https://github.com/whatwg/html/issues/546 .
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+ BackToAboutBlankIframe) {
+ GURL original_url(embedded_test_server()->GetURL(
+ "/navigation_controller/simple_page_1.html"));
+ NavigateToURL(shell(), original_url);
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ NavigationController& controller = shell()->web_contents()->GetController();
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ EXPECT_EQ(1, controller.GetEntryCount());
+ EXPECT_EQ(1, RendererHistoryLength(shell()));
+
+ // Add an iframe with no 'src'.
+
+ std::string script =
+ "var iframe = document.createElement('iframe');"
+ "iframe.id = 'frame';"
+ "document.body.appendChild(iframe);";
+ EXPECT_TRUE(content::ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ EXPECT_EQ(1, controller.GetEntryCount());
+ EXPECT_EQ(1, RendererHistoryLength(shell()));
+ EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
+
+ ASSERT_EQ(1U, root->child_count());
+ FrameTreeNode* frame = root->child_at(0);
+ ASSERT_NE(nullptr, frame);
+
+ EXPECT_EQ(GURL(url::kAboutBlankURL), frame->current_url());
+
+ // Now create a new navigation entry. Note that the old navigation entry has
+ // "about:blank" as the URL in the iframe.
+
+ script = "history.pushState({}, '', 'notarealurl.html')";
+ EXPECT_TRUE(content::ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ EXPECT_EQ(2, controller.GetEntryCount());
+ EXPECT_EQ(2, RendererHistoryLength(shell()));
+ EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+
+ // Load the iframe; the initial "about:blank" URL should be elided and thus we
+ // shouldn't get a new navigation entry.
+
+ GURL frame_url = embedded_test_server()->GetURL(
+ "/navigation_controller/simple_page_2.html");
+ NavigateFrameToURL(frame, frame_url);
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ EXPECT_EQ(2, controller.GetEntryCount());
+ EXPECT_EQ(2, RendererHistoryLength(shell()));
+ EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+
+ EXPECT_EQ(frame_url, frame->current_url());
+
+ // Go back. Because the old state had an empty frame, that should be restored
+ // even though it was replaced in the second navigation entry.
+
+ TestFrameNavigationObserver observer(frame);
+ ASSERT_TRUE(controller.CanGoBack());
+ controller.GoBack();
+ observer.Wait();
+
+ EXPECT_EQ(2, controller.GetEntryCount());
+ EXPECT_EQ(2, RendererHistoryLength(shell()));
+ EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
+
+ EXPECT_EQ(GURL(url::kAboutBlankURL), frame->current_url());
+}
+
+// This test is similar to "BackToAboutBlankIframe" above, except that a
+// fragment navigation is used rather than pushState (both create an in-page
+// navigation, so we need to test both), and an initial 'src' is given to the
+// iframe to test proper restoration in that case.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+ BackToIframeWithContent) {
+ GURL links_url(embedded_test_server()->GetURL(
+ "/navigation_controller/page_with_links.html"));
+ NavigateToURL(shell(), links_url);
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ NavigationController& controller = shell()->web_contents()->GetController();
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ EXPECT_EQ(1, controller.GetEntryCount());
+ EXPECT_EQ(1, RendererHistoryLength(shell()));
+
+ // Add an iframe with a 'src'.
+
+ GURL frame_url_1 = embedded_test_server()->GetURL(
+ "/navigation_controller/simple_page_1.html");
+ std::string script =
+ "var iframe = document.createElement('iframe');"
+ "iframe.src = '" + frame_url_1.spec() + "';"
+ "iframe.id = 'frame';"
+ "document.body.appendChild(iframe);";
+ EXPECT_TRUE(content::ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ EXPECT_EQ(1, controller.GetEntryCount());
+ EXPECT_EQ(1, RendererHistoryLength(shell()));
+ EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
+
+ ASSERT_EQ(1U, root->child_count());
+ FrameTreeNode* frame = root->child_at(0);
+ ASSERT_NE(nullptr, frame);
+
+ EXPECT_EQ(frame_url_1, frame->current_url());
+
+ // Do a fragment navigation, creating a new navigation entry. Note that the
+ // old navigation entry has frame_url_1 as the URL in the iframe.
+
+ script = "document.getElementById('fraglink').click()";
+ EXPECT_TRUE(content::ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ EXPECT_EQ(2, controller.GetEntryCount());
+ EXPECT_EQ(2, RendererHistoryLength(shell()));
+ EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+
+ EXPECT_EQ(frame_url_1, frame->current_url());
+
+ // Navigate the iframe; unlike the test "BackToAboutBlankIframe" above, this
+ // _will_ create a new navigation entry.
+
+ GURL frame_url_2 = embedded_test_server()->GetURL(
+ "/navigation_controller/simple_page_2.html");
+ NavigateFrameToURL(frame, frame_url_2);
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ EXPECT_EQ(3, controller.GetEntryCount());
+ EXPECT_EQ(3, RendererHistoryLength(shell()));
+ EXPECT_EQ(2, controller.GetLastCommittedEntryIndex());
+
+ EXPECT_EQ(frame_url_2, frame->current_url());
+
+ // Go back two entries. The original frame URL should be back.
+
+ TestFrameNavigationObserver observer(frame);
+ ASSERT_TRUE(controller.CanGoToOffset(-2));
+ controller.GoToOffset(-2);
+ observer.Wait();
+
+ EXPECT_EQ(3, controller.GetEntryCount());
+ EXPECT_EQ(3, RendererHistoryLength(shell()));
+ EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
+
+ EXPECT_EQ(frame_url_1, frame->current_url());
+}
+
+// Ensure that we do not corrupt a NavigationEntry's PageState if a subframe
+// forward navigation commits after we've already started another forward
+// navigation in the main frame. See https://crbug.com/597322.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+ ForwardInSubframeWithPendingForward) {
+ // Navigate to a page with an iframe.
+ GURL url_a(embedded_test_server()->GetURL(
+ "/navigation_controller/page_with_data_iframe.html"));
+ GURL frame_url_a1("data:text/html,Subframe");
+ EXPECT_TRUE(NavigateToURL(shell(), url_a));
+
+ NavigationController& controller = shell()->web_contents()->GetController();
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ ASSERT_EQ(1U, root->child_count());
+ EXPECT_EQ(url_a, root->current_url());
+ FrameTreeNode* frame = root->child_at(0);
+ EXPECT_EQ(frame_url_a1, frame->current_url());
+
+ // Navigate the iframe to a second page.
+ GURL frame_url_a2 = embedded_test_server()->GetURL(
+ "/navigation_controller/simple_page_1.html");
+ NavigateFrameToURL(frame, frame_url_a2);
+
+ EXPECT_EQ(2, controller.GetEntryCount());
+ EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+ EXPECT_EQ(url_a, root->current_url());
+ EXPECT_EQ(frame_url_a2, frame->current_url());
+
+ // Navigate the top-level frame to another page with an iframe.
+ GURL url_b(embedded_test_server()->GetURL(
+ "/navigation_controller/page_with_iframe.html"));
+ GURL frame_url_b1(url::kAboutBlankURL);
+ EXPECT_TRUE(NavigateToURL(shell(), url_b));
+ EXPECT_EQ(3, controller.GetEntryCount());
+ EXPECT_EQ(url_b, root->current_url());
+ EXPECT_EQ(frame_url_b1, root->child_at(0)->current_url());
+
+ // Go back two entries. The original frame URL should be back.
+ ASSERT_TRUE(controller.CanGoToOffset(-2));
+ controller.GoToOffset(-2);
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
+ EXPECT_EQ(url_a, root->current_url());
+ EXPECT_EQ(frame_url_a1, root->child_at(0)->current_url());
+
+ // Go forward two times in a row, being careful that the subframe commits
+ // after the second forward navigation begins but before the main frame
+ // commits.
+ TestNavigationManager subframe_delayer(shell()->web_contents(), frame_url_a2);
+ TestNavigationManager mainframe_delayer(shell()->web_contents(), url_b);
+ controller.GoForward();
+ subframe_delayer.WaitForWillStartRequest();
+ controller.GoForward();
+ mainframe_delayer.WaitForWillStartRequest();
+ EXPECT_EQ(2, controller.GetPendingEntryIndex());
+
+ // Let the subframe commit.
+ subframe_delayer.ResumeNavigation();
+ subframe_delayer.WaitForNavigationFinished();
+ EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+ EXPECT_EQ(url_a, root->current_url());
+ EXPECT_EQ(frame_url_a2, root->child_at(0)->current_url());
+
+ // Let the main frame commit.
+ mainframe_delayer.ResumeNavigation();
+ mainframe_delayer.WaitForNavigationFinished();
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+ EXPECT_EQ(2, controller.GetLastCommittedEntryIndex());
+ EXPECT_EQ(url_b, root->current_url());
+ EXPECT_EQ(frame_url_b1, root->child_at(0)->current_url());
+
+ // Check the PageState of the previous entry to ensure it isn't corrupted.
+ NavigationEntry* entry = controller.GetEntryAtIndex(1);
+ EXPECT_EQ(url_a, entry->GetURL());
+ ExplodedPageState exploded_state;
+ EXPECT_TRUE(
+ DecodePageState(entry->GetPageState().ToEncodedData(), &exploded_state));
+ EXPECT_EQ(url_a, GURL(exploded_state.top.url_string.string()));
+ EXPECT_EQ(frame_url_a2,
+ GURL(exploded_state.top.children.at(0).url_string.string()));
+}
+
+// Ensure that forward navigations in cloned tabs can commit if they redirect to
+// a different site than before. This causes the navigation's item sequence
+// number to change, meaning that we can't use it for determining whether the
+// commit matches the history item. See https://crbug.com/600238.
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest,
+ ForwardRedirectWithNoCommittedEntry) {
+ NavigationController& controller = shell()->web_contents()->GetController();
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // Put 2 pages in history.
+ GURL url_1(embedded_test_server()->GetURL(
+ "/navigation_controller/simple_page_1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), url_1));
+
+ GURL url_2(embedded_test_server()->GetURL(
+ "/navigation_controller/simple_page_2.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), url_2));
+
+ EXPECT_EQ(url_2, root->current_url());
+ EXPECT_EQ(2, controller.GetEntryCount());
+ EXPECT_EQ(1, controller.GetLastCommittedEntryIndex());
+
+ // Do a replaceState to a URL that will redirect when we come back to it via
+ // session history.
+ GURL url_3(embedded_test_server()->GetURL(
+ "foo.com", "/navigation_controller/page_with_links.html"));
+ {
+ TestNavigationObserver observer(shell()->web_contents());
+ std::string script =
+ "history.replaceState({}, '', '/server-redirect?" + url_3.spec() + "')";
+ EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+ observer.Wait();
+ }
+
+ // Go back.
+ controller.GoBack();
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+ EXPECT_EQ(0, controller.GetLastCommittedEntryIndex());
+ EXPECT_EQ(url_1, root->current_url());
+
+ // Clone the tab without navigating it.
+ std::unique_ptr<WebContentsImpl> new_tab(
+ static_cast<WebContentsImpl*>(shell()->web_contents()->Clone()));
+ NavigationController& new_controller = new_tab->GetController();
+ FrameTreeNode* new_root = new_tab->GetFrameTree()->root();
+ EXPECT_TRUE(new_controller.IsInitialNavigation());
+ EXPECT_TRUE(new_controller.NeedsReload());
+
+ // Go forward in the new tab.
+ {
+ TestNavigationObserver observer(new_tab.get());
+ new_controller.GoForward();
+ observer.Wait();
+ }
+ EXPECT_TRUE(new_root->current_frame_host()->IsRenderFrameLive());
+ EXPECT_EQ(url_3, new_root->current_url());
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc b/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc
index 775feb3debf..e86f1fdba6f 100644
--- a/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigation_controller_impl_unittest.cc
@@ -46,7 +46,6 @@
#include "content/test/test_render_frame_host.h"
#include "content/test/test_render_view_host.h"
#include "content/test/test_web_contents.h"
-#include "net/base/net_util.h"
#include "skia/ext/platform_canvas.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/web/WebFrameOwnerProperties.h"
@@ -296,6 +295,25 @@ class TestWebContentsDelegate : public WebContentsDelegate {
int repost_form_warning_count_;
};
+// Observer that records the LoadCommittedDetails from the most recent commit.
+class LoadCommittedDetailsObserver : public WebContentsObserver {
+ public:
+ // Observes navigation for the specified |web_contents|.
+ explicit LoadCommittedDetailsObserver(WebContents* web_contents)
+ : WebContentsObserver(web_contents) {}
+
+ const LoadCommittedDetails& details() { return details_; }
+
+ private:
+ void DidNavigateAnyFrame(RenderFrameHost* render_frame_host,
+ const LoadCommittedDetails& details,
+ const FrameNavigateParams& params) override {
+ details_ = details;
+ }
+
+ LoadCommittedDetails details_;
+};
+
// -----------------------------------------------------------------------------
TEST_F(NavigationControllerTest, Defaults) {
@@ -384,6 +402,50 @@ TEST_F(NavigationControllerTest, GoToOffset) {
}
}
+// This test case was added to reproduce crbug.com/513742. The repro steps are
+// as follows:
+// 1. Pending entry for A is created.
+// 2. DidStartProvisionalLoad message for A arrives.
+// 3. Pending entry for B is created.
+// 4. DidFailProvisionalLoad message for A arrives. The logic here discards.
+// 5. DidStartProvisionalLoad message for B arrives.
+//
+// At step (4), the pending entry for B is discarded, when A is the one that
+// is being aborted. This caused the last committed entry to be displayed in
+// the omnibox, which is the entry before A was created.
+TEST_F(NavigationControllerTest, DontDiscardWrongPendingEntry) {
+ NavigationControllerImpl& controller = controller_impl();
+ GURL initial_url("http://www.google.com");
+ GURL url_1("http://foo.com");
+ GURL url_2("http://foo2.com");
+
+ // Navigate inititally. This is the url that could erroneously be the visible
+ // entry when url_1 fails.
+ NavigateAndCommit(initial_url);
+
+ // Set the pending entry as url_1 and receive the DidStartProvisionalLoad
+ // message, creating the NavigationHandle.
+ controller.LoadURL(url_1, Referrer(), ui::PAGE_TRANSITION_TYPED,
+ std::string());
+ EXPECT_EQ(url_1, controller.GetVisibleEntry()->GetURL());
+ main_test_rfh()->SimulateNavigationStart(url_1);
+ EXPECT_EQ(url_1, controller.GetVisibleEntry()->GetURL());
+
+ // Navigate to url_2, aborting url_1 before the DidStartProvisionalLoad
+ // message is received for url_2. Do not discard the pending entry for url_2
+ // here.
+ controller.LoadURL(url_2, Referrer(), ui::PAGE_TRANSITION_TYPED,
+ std::string());
+ EXPECT_EQ(url_2, controller.GetVisibleEntry()->GetURL());
+ main_test_rfh()->SimulateNavigationError(url_1, net::ERR_ABORTED);
+ EXPECT_EQ(url_2, controller.GetVisibleEntry()->GetURL());
+
+ // Get the DidStartProvisionalLoad message for url_2.
+ main_test_rfh()->SimulateNavigationStart(url_2);
+
+ EXPECT_EQ(url_2, controller.GetVisibleEntry()->GetURL());
+}
+
TEST_F(NavigationControllerTest, LoadURL) {
NavigationControllerImpl& controller = controller_impl();
TestNotificationTracker notifications;
@@ -1048,10 +1110,7 @@ TEST_F(NavigationControllerTest, LoadURL_IgnorePreemptsPending) {
EXPECT_EQ(-1, controller.GetPendingEntryIndex());
EXPECT_FALSE(controller.GetPendingEntry());
EXPECT_EQ(-1, controller.GetLastCommittedEntryIndex());
- if (IsBrowserSideNavigationEnabled())
- EXPECT_EQ(4, delegate->navigation_state_change_count());
- else
- EXPECT_EQ(2, delegate->navigation_state_change_count());
+ EXPECT_EQ(2, delegate->navigation_state_change_count());
contents()->SetDelegate(NULL);
}
@@ -1469,7 +1528,7 @@ TEST_F(NavigationControllerTest, ResetEntryValuesAfterCommit) {
// Fake a commit response.
main_test_rfh()->PrepareForCommit();
- main_test_rfh()->SendNavigate(1, entry_id, true, url1);
+ main_test_rfh()->SendNavigateWithReplacement(1, entry_id, true, url1);
// Certain values that are only used for pending entries get reset after
// commit.
@@ -1824,10 +1883,8 @@ TEST_F(NavigationControllerTest, Redirect) {
params.is_post = false;
params.page_state = PageState::CreateFromURL(url2);
- LoadCommittedDetails details;
-
- EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), params,
- &details));
+ main_test_rfh()->PrepareForCommit();
+ main_test_rfh()->SendNavigateWithParams(&params);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1844,12 +1901,13 @@ TEST_F(NavigationControllerTest, Redirect) {
params.did_create_new_entry = false;
EXPECT_EQ(0U, notifications.size());
- EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), params,
- &details));
+ LoadCommittedDetailsObserver observer(contents());
+ main_test_rfh()->PrepareForCommit();
+ main_test_rfh()->SendNavigateWithParams(&params);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
- EXPECT_TRUE(details.type == NAVIGATION_TYPE_SAME_PAGE);
+ EXPECT_EQ(NAVIGATION_TYPE_SAME_PAGE, observer.details().type);
EXPECT_EQ(controller.GetEntryCount(), 1);
EXPECT_EQ(controller.GetLastCommittedEntryIndex(), 0);
EXPECT_TRUE(controller.GetLastCommittedEntry());
@@ -1893,10 +1951,8 @@ TEST_F(NavigationControllerTest, PostThenRedirect) {
params.is_post = true;
params.page_state = PageState::CreateFromURL(url2);
- LoadCommittedDetails details;
-
- EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), params,
- &details));
+ main_test_rfh()->PrepareForCommit();
+ main_test_rfh()->SendNavigateWithParams(&params);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -1914,12 +1970,13 @@ TEST_F(NavigationControllerTest, PostThenRedirect) {
params.is_post = false;
EXPECT_EQ(0U, notifications.size());
- EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), params,
- &details));
+ LoadCommittedDetailsObserver observer(contents());
+ main_test_rfh()->PrepareForCommit();
+ main_test_rfh()->SendNavigateWithParams(&params);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
- EXPECT_TRUE(details.type == NAVIGATION_TYPE_SAME_PAGE);
+ EXPECT_EQ(NAVIGATION_TYPE_SAME_PAGE, observer.details().type);
EXPECT_EQ(controller.GetEntryCount(), 1);
EXPECT_EQ(controller.GetLastCommittedEntryIndex(), 0);
EXPECT_TRUE(controller.GetLastCommittedEntry());
@@ -1963,15 +2020,15 @@ TEST_F(NavigationControllerTest, ImmediateRedirect) {
params.is_post = false;
params.page_state = PageState::CreateFromURL(url2);
- LoadCommittedDetails details;
+ LoadCommittedDetailsObserver observer(contents());
EXPECT_EQ(0U, notifications.size());
- EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), params,
- &details));
+ main_test_rfh()->PrepareForCommit();
+ main_test_rfh()->SendNavigateWithParams(&params);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
- EXPECT_TRUE(details.type == NAVIGATION_TYPE_NEW_PAGE);
+ EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, observer.details().type);
EXPECT_EQ(controller.GetEntryCount(), 1);
EXPECT_EQ(controller.GetLastCommittedEntryIndex(), 0);
EXPECT_TRUE(controller.GetLastCommittedEntry());
@@ -2028,12 +2085,11 @@ TEST_F(NavigationControllerTest,
params.transition = ui::PAGE_TRANSITION_TYPED;
params.page_state = PageState::CreateFromURL(url1);
- LoadCommittedDetails details;
+ LoadCommittedDetailsObserver observer(contents());
main_test_rfh()->PrepareForCommit();
- EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), params,
- &details));
- EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, details.type);
+ main_test_rfh()->SendNavigateWithParams(&params);
+ EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, observer.details().type);
}
// Tests navigation via link click within a subframe. A new navigation entry
@@ -2051,10 +2107,10 @@ TEST_F(NavigationControllerTest, NewSubframe) {
// Prereq: add a subframe with an initial auto-subframe navigation.
main_test_rfh()->OnCreateChildFrame(
process()->GetNextRoutingID(), blink::WebTreeScopeType::Document,
- std::string(), blink::WebSandboxFlags::None,
+ std::string(), "uniqueName0", blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
- RenderFrameHostImpl* subframe =
- contents()->GetFrameTree()->root()->child_at(0)->current_frame_host();
+ TestRenderFrameHost* subframe = static_cast<TestRenderFrameHost*>(
+ contents()->GetFrameTree()->root()->child_at(0)->current_frame_host());
const GURL subframe_url("http://foo1/subframe");
{
FrameHostMsg_DidCommitProvisionalLoad_Params params;
@@ -2069,8 +2125,9 @@ TEST_F(NavigationControllerTest, NewSubframe) {
params.page_state = PageState::CreateFromURL(subframe_url);
// Navigating should do nothing.
- LoadCommittedDetails details;
- EXPECT_FALSE(controller.RendererDidNavigate(subframe, params, &details));
+ subframe->SendRendererInitiatedNavigationRequest(subframe_url, false);
+ subframe->PrepareForCommit();
+ subframe->SendNavigateWithParams(&params);
EXPECT_EQ(0U, notifications.size());
}
@@ -2087,18 +2144,20 @@ TEST_F(NavigationControllerTest, NewSubframe) {
params.is_post = false;
params.page_state = PageState::CreateFromURL(url2);
- LoadCommittedDetails details;
- EXPECT_TRUE(controller.RendererDidNavigate(subframe, params, &details));
+ LoadCommittedDetailsObserver observer(contents());
+ subframe->SendRendererInitiatedNavigationRequest(url2, true);
+ subframe->PrepareForCommit();
+ subframe->SendNavigateWithParams(&params);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
- EXPECT_EQ(url1, details.previous_url);
- EXPECT_FALSE(details.is_in_page);
- EXPECT_FALSE(details.is_main_frame);
+ EXPECT_EQ(url1, observer.details().previous_url);
+ EXPECT_FALSE(observer.details().is_in_page);
+ EXPECT_FALSE(observer.details().is_main_frame);
// The new entry should be appended.
NavigationEntryImpl* entry = controller.GetLastCommittedEntry();
EXPECT_EQ(2, controller.GetEntryCount());
- EXPECT_EQ(entry, details.entry);
+ EXPECT_EQ(entry, observer.details().entry);
// New entry should refer to the new page, but the old URL (entries only
// reflect the toplevel URL).
@@ -2132,10 +2191,10 @@ TEST_F(NavigationControllerTest, AutoSubframe) {
// Add a subframe and navigate it.
main_test_rfh()->OnCreateChildFrame(
process()->GetNextRoutingID(), blink::WebTreeScopeType::Document,
- std::string(), blink::WebSandboxFlags::None,
+ std::string(), "uniqueName0", blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
- RenderFrameHostImpl* subframe =
- contents()->GetFrameTree()->root()->child_at(0)->current_frame_host();
+ TestRenderFrameHost* subframe = static_cast<TestRenderFrameHost*>(
+ contents()->GetFrameTree()->root()->child_at(0)->current_frame_host());
const GURL url2("http://foo/2");
{
FrameHostMsg_DidCommitProvisionalLoad_Params params;
@@ -2150,8 +2209,9 @@ TEST_F(NavigationControllerTest, AutoSubframe) {
params.page_state = PageState::CreateFromURL(url2);
// Navigating should do nothing.
- LoadCommittedDetails details;
- EXPECT_FALSE(controller.RendererDidNavigate(subframe, params, &details));
+ subframe->SendRendererInitiatedNavigationRequest(url2, false);
+ subframe->PrepareForCommit();
+ subframe->SendNavigateWithParams(&params);
EXPECT_EQ(0U, notifications.size());
}
@@ -2178,10 +2238,10 @@ TEST_F(NavigationControllerTest, AutoSubframe) {
// Add a second subframe and navigate.
main_test_rfh()->OnCreateChildFrame(
process()->GetNextRoutingID(), blink::WebTreeScopeType::Document,
- std::string(), blink::WebSandboxFlags::None,
+ std::string(), "uniqueName1", blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
- RenderFrameHostImpl* subframe2 =
- contents()->GetFrameTree()->root()->child_at(1)->current_frame_host();
+ TestRenderFrameHost* subframe2 = static_cast<TestRenderFrameHost*>(
+ contents()->GetFrameTree()->root()->child_at(1)->current_frame_host());
const GURL url3("http://foo/3");
{
FrameHostMsg_DidCommitProvisionalLoad_Params params;
@@ -2196,8 +2256,9 @@ TEST_F(NavigationControllerTest, AutoSubframe) {
params.page_state = PageState::CreateFromURL(url3);
// Navigating should do nothing.
- LoadCommittedDetails details;
- EXPECT_FALSE(controller.RendererDidNavigate(subframe2, params, &details));
+ subframe2->SendRendererInitiatedNavigationRequest(url3, false);
+ subframe2->PrepareForCommit();
+ subframe2->SendNavigateWithParams(&params);
EXPECT_EQ(0U, notifications.size());
}
@@ -2224,14 +2285,15 @@ TEST_F(NavigationControllerTest, AutoSubframe) {
// Add a nested subframe and navigate.
subframe->OnCreateChildFrame(process()->GetNextRoutingID(),
blink::WebTreeScopeType::Document, std::string(),
- blink::WebSandboxFlags::None,
+ "uniqueName2", blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
- RenderFrameHostImpl* subframe3 = contents()
- ->GetFrameTree()
- ->root()
- ->child_at(0)
- ->child_at(0)
- ->current_frame_host();
+ TestRenderFrameHost* subframe3 =
+ static_cast<TestRenderFrameHost*>(contents()
+ ->GetFrameTree()
+ ->root()
+ ->child_at(0)
+ ->child_at(0)
+ ->current_frame_host());
const GURL url4("http://foo/4");
{
FrameHostMsg_DidCommitProvisionalLoad_Params params;
@@ -2246,8 +2308,9 @@ TEST_F(NavigationControllerTest, AutoSubframe) {
params.page_state = PageState::CreateFromURL(url4);
// Navigating should do nothing.
- LoadCommittedDetails details;
- EXPECT_FALSE(controller.RendererDidNavigate(subframe3, params, &details));
+ subframe3->SendRendererInitiatedNavigationRequest(url4, false);
+ subframe3->PrepareForCommit();
+ subframe3->SendNavigateWithParams(&params);
EXPECT_EQ(0U, notifications.size());
}
@@ -2289,10 +2352,10 @@ TEST_F(NavigationControllerTest, BackSubframe) {
// Prereq: add a subframe with an initial auto-subframe navigation.
main_test_rfh()->OnCreateChildFrame(
process()->GetNextRoutingID(), blink::WebTreeScopeType::Document,
- std::string(), blink::WebSandboxFlags::None,
+ std::string(), "uniqueName0", blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
- RenderFrameHostImpl* subframe =
- contents()->GetFrameTree()->root()->child_at(0)->current_frame_host();
+ TestRenderFrameHost* subframe = static_cast<TestRenderFrameHost*>(
+ contents()->GetFrameTree()->root()->child_at(0)->current_frame_host());
const GURL subframe_url("http://foo1/subframe");
{
FrameHostMsg_DidCommitProvisionalLoad_Params params;
@@ -2307,8 +2370,9 @@ TEST_F(NavigationControllerTest, BackSubframe) {
params.page_state = PageState::CreateFromURL(subframe_url);
// Navigating should do nothing.
- LoadCommittedDetails details;
- EXPECT_FALSE(controller.RendererDidNavigate(subframe, params, &details));
+ subframe->SendRendererInitiatedNavigationRequest(subframe_url, false);
+ subframe->PrepareForCommit();
+ subframe->SendNavigateWithParams(&params);
EXPECT_EQ(0U, notifications.size());
}
@@ -2326,8 +2390,9 @@ TEST_F(NavigationControllerTest, BackSubframe) {
params.page_state = PageState::CreateFromURL(url2);
// This should generate a new entry.
- LoadCommittedDetails details;
- EXPECT_TRUE(controller.RendererDidNavigate(subframe, params, &details));
+ subframe->SendRendererInitiatedNavigationRequest(url2, false);
+ subframe->PrepareForCommit();
+ subframe->SendNavigateWithParams(&params);
NavigationEntryImpl* entry2 = controller.GetLastCommittedEntry();
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
@@ -2351,7 +2416,9 @@ TEST_F(NavigationControllerTest, BackSubframe) {
params.url = url3;
params.transition = ui::PAGE_TRANSITION_MANUAL_SUBFRAME;
params.page_state = PageState::CreateFromURL(url3);
- EXPECT_TRUE(controller.RendererDidNavigate(subframe, params, &details));
+ subframe->SendRendererInitiatedNavigationRequest(url3, false);
+ subframe->PrepareForCommit();
+ subframe->SendNavigateWithParams(&params);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
NavigationEntryImpl* entry3 = controller.GetLastCommittedEntry();
@@ -2376,7 +2443,8 @@ TEST_F(NavigationControllerTest, BackSubframe) {
params.url = url2;
params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME;
params.page_state = PageState::CreateFromURL(url2);
- EXPECT_TRUE(controller.RendererDidNavigate(subframe, params, &details));
+ subframe->PrepareForCommit();
+ subframe->SendNavigateWithParams(&params);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
EXPECT_EQ(entry2, controller.GetLastCommittedEntry());
@@ -2393,7 +2461,8 @@ TEST_F(NavigationControllerTest, BackSubframe) {
params.url = subframe_url;
params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME;
params.page_state = PageState::CreateFromURL(subframe_url);
- EXPECT_TRUE(controller.RendererDidNavigate(subframe, params, &details));
+ subframe->PrepareForCommit();
+ subframe->SendNavigateWithParams(&params);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
EXPECT_EQ(entry1, controller.GetLastCommittedEntry());
@@ -2454,14 +2523,15 @@ TEST_F(NavigationControllerTest, InPage) {
self_params.page_state = PageState::CreateFromURL(url1);
self_params.was_within_same_page = true;
- LoadCommittedDetails details;
- EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), self_params,
- &details));
+ LoadCommittedDetailsObserver observer(contents());
+ main_test_rfh()->SendRendererInitiatedNavigationRequest(url1, false);
+ main_test_rfh()->PrepareForCommit();
+ main_test_rfh()->SendNavigateWithParams(&self_params);
NavigationEntry* entry1 = controller.GetLastCommittedEntry();
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
- EXPECT_TRUE(details.is_in_page);
- EXPECT_TRUE(details.did_replace_entry);
+ EXPECT_TRUE(observer.details().is_in_page);
+ EXPECT_TRUE(observer.details().did_replace_entry);
EXPECT_EQ(1, controller.GetEntryCount());
// Fragment navigation to a new page_id.
@@ -2479,13 +2549,14 @@ TEST_F(NavigationControllerTest, InPage) {
params.was_within_same_page = true;
// This should generate a new entry.
- EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), params,
- &details));
+ main_test_rfh()->SendRendererInitiatedNavigationRequest(url2, false);
+ main_test_rfh()->PrepareForCommit();
+ main_test_rfh()->SendNavigateWithParams(&params);
NavigationEntry* entry2 = controller.GetLastCommittedEntry();
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
- EXPECT_TRUE(details.is_in_page);
- EXPECT_FALSE(details.did_replace_entry);
+ EXPECT_TRUE(observer.details().is_in_page);
+ EXPECT_FALSE(observer.details().did_replace_entry);
EXPECT_EQ(2, controller.GetEntryCount());
// Go back one.
@@ -2495,11 +2566,11 @@ TEST_F(NavigationControllerTest, InPage) {
back_params.page_id = 0;
back_params.nav_entry_id = entry1->GetUniqueID();
back_params.did_create_new_entry = false;
- EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), back_params,
- &details));
+ main_test_rfh()->PrepareForCommit();
+ main_test_rfh()->SendNavigateWithParams(&back_params);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
- EXPECT_TRUE(details.is_in_page);
+ EXPECT_TRUE(observer.details().is_in_page);
EXPECT_EQ(2, controller.GetEntryCount());
EXPECT_EQ(0, controller.GetCurrentEntryIndex());
EXPECT_EQ(back_params.url, controller.GetVisibleEntry()->GetURL());
@@ -2511,11 +2582,11 @@ TEST_F(NavigationControllerTest, InPage) {
forward_params.page_id = 1;
forward_params.nav_entry_id = entry2->GetUniqueID();
forward_params.did_create_new_entry = false;
- EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), forward_params,
- &details));
+ main_test_rfh()->PrepareForCommit();
+ main_test_rfh()->SendNavigateWithParams(&forward_params);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
- EXPECT_TRUE(details.is_in_page);
+ EXPECT_TRUE(observer.details().is_in_page);
EXPECT_EQ(2, controller.GetEntryCount());
EXPECT_EQ(1, controller.GetCurrentEntryIndex());
EXPECT_EQ(forward_params.url,
@@ -2526,11 +2597,11 @@ TEST_F(NavigationControllerTest, InPage) {
// one identified by an existing page ID. This would result in the second URL
// losing the reference fragment when you navigate away from it and then back.
controller.GoBack();
- EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), back_params,
- &details));
+ main_test_rfh()->PrepareForCommit();
+ main_test_rfh()->SendNavigateWithParams(&back_params);
controller.GoForward();
- EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), forward_params,
- &details));
+ main_test_rfh()->PrepareForCommit();
+ main_test_rfh()->SendNavigateWithParams(&forward_params);
EXPECT_EQ(forward_params.url,
controller.GetVisibleEntry()->GetURL());
@@ -2541,11 +2612,12 @@ TEST_F(NavigationControllerTest, InPage) {
params.did_create_new_entry = true;
params.url = url3;
navigation_entry_committed_counter_ = 0;
- EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), params,
- &details));
+ main_test_rfh()->SendRendererInitiatedNavigationRequest(url3, false);
+ main_test_rfh()->PrepareForCommit();
+ main_test_rfh()->SendNavigateWithParams(&params);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
- EXPECT_FALSE(details.is_in_page);
+ EXPECT_FALSE(observer.details().is_in_page);
EXPECT_EQ(3, controller.GetEntryCount());
EXPECT_EQ(2, controller.GetCurrentEntryIndex());
}
@@ -2576,13 +2648,14 @@ TEST_F(NavigationControllerTest, InPage_Replace) {
params.was_within_same_page = true;
// This should NOT generate a new entry, nor prune the list.
- LoadCommittedDetails details;
- EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), params,
- &details));
+ LoadCommittedDetailsObserver observer(contents());
+ main_test_rfh()->SendRendererInitiatedNavigationRequest(url2, false);
+ main_test_rfh()->PrepareForCommit();
+ main_test_rfh()->SendNavigateWithParams(&params);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
- EXPECT_TRUE(details.is_in_page);
- EXPECT_TRUE(details.did_replace_entry);
+ EXPECT_TRUE(observer.details().is_in_page);
+ EXPECT_TRUE(observer.details().did_replace_entry);
EXPECT_EQ(1, controller.GetEntryCount());
}
@@ -2630,13 +2703,14 @@ TEST_F(NavigationControllerTest, ClientRedirectAfterInPageNavigation) {
params.was_within_same_page = true;
// This should NOT generate a new entry, nor prune the list.
- LoadCommittedDetails details;
- EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), params,
- &details));
+ LoadCommittedDetailsObserver observer(contents());
+ main_test_rfh()->SendRendererInitiatedNavigationRequest(url, false);
+ main_test_rfh()->PrepareForCommit();
+ main_test_rfh()->SendNavigateWithParams(&params);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
- EXPECT_TRUE(details.is_in_page);
- EXPECT_TRUE(details.did_replace_entry);
+ EXPECT_TRUE(observer.details().is_in_page);
+ EXPECT_TRUE(observer.details().did_replace_entry);
EXPECT_EQ(2, controller.GetEntryCount());
}
@@ -2657,12 +2731,13 @@ TEST_F(NavigationControllerTest, ClientRedirectAfterInPageNavigation) {
params.page_state = PageState::CreateFromURL(url);
// This SHOULD generate a new entry.
- LoadCommittedDetails details;
- EXPECT_TRUE(controller.RendererDidNavigate(main_test_rfh(), params,
- &details));
+ LoadCommittedDetailsObserver observer(contents());
+ main_test_rfh()->SendRendererInitiatedNavigationRequest(url, false);
+ main_test_rfh()->PrepareForCommit();
+ main_test_rfh()->SendNavigateWithParams(&params);
EXPECT_EQ(1U, navigation_entry_committed_counter_);
navigation_entry_committed_counter_ = 0;
- EXPECT_FALSE(details.is_in_page);
+ EXPECT_FALSE(observer.details().is_in_page);
EXPECT_EQ(3, controller.GetEntryCount());
}
@@ -2841,9 +2916,10 @@ TEST_F(NavigationControllerTest, RestoreNavigate) {
params.gesture = NavigationGestureUser;
params.is_post = false;
params.page_state = PageState::CreateFromURL(url);
- LoadCommittedDetails details;
- our_controller.RendererDidNavigate(our_contents->GetMainFrame(), params,
- &details);
+ TestRenderFrameHost* main_rfh =
+ static_cast<TestRenderFrameHost*>(our_contents->GetMainFrame());
+ main_rfh->PrepareForCommit();
+ main_rfh->SendNavigateWithParams(&params);
// There should be no longer any pending entry and one committed one. This
// means that we were able to locate the entry, assign its site instance, and
@@ -2923,9 +2999,10 @@ TEST_F(NavigationControllerTest, RestoreNavigateAfterFailure) {
params.gesture = NavigationGestureUser;
params.is_post = false;
params.page_state = PageState::CreateFromURL(url);
- LoadCommittedDetails details;
- our_controller.RendererDidNavigate(our_contents->GetMainFrame(), params,
- &details);
+ TestRenderFrameHost* main_rfh =
+ static_cast<TestRenderFrameHost*>(our_contents->GetMainFrame());
+ main_rfh->PrepareForCommit();
+ main_rfh->SendNavigateWithParams(&params);
// There should be no pending entry and one committed one.
EXPECT_EQ(1, our_controller.GetEntryCount());
@@ -3357,7 +3434,7 @@ TEST_F(NavigationControllerTest, RendererInitiatedPendingEntries) {
navigator->DidStartProvisionalLoad(main_test_rfh(), url2,
base::TimeTicks::Now());
EXPECT_TRUE(controller.GetPendingEntry()->should_replace_entry());
- main_test_rfh()->SendNavigate(0, 0, false, url2);
+ main_test_rfh()->SendNavigateWithReplacement(0, 0, false, url2);
EXPECT_EQ(url2, controller.GetLastCommittedEntry()->GetURL());
}
@@ -3470,14 +3547,19 @@ TEST_F(NavigationControllerTest, ShowBrowserURLAfterFailUntilModified) {
// Suppose it aborts before committing, if it's a 204 or download or due to a
// stop or a new navigation from the user. The URL should remain visible.
- FrameHostMsg_DidFailProvisionalLoadWithError_Params params;
- params.error_code = net::ERR_ABORTED;
- params.error_description = base::string16();
- params.url = url;
- params.showing_repost_interstitial = false;
- main_test_rfh()->OnMessageReceived(
- FrameHostMsg_DidFailProvisionalLoadWithError(0, params));
- contents()->SetIsLoading(false, true, NULL);
+ if (IsBrowserSideNavigationEnabled()) {
+ static_cast<NavigatorImpl*>(main_test_rfh()->frame_tree_node()->navigator())
+ ->CancelNavigation(main_test_rfh()->frame_tree_node());
+ } else {
+ FrameHostMsg_DidFailProvisionalLoadWithError_Params params;
+ params.error_code = net::ERR_ABORTED;
+ params.error_description = base::string16();
+ params.url = url;
+ params.showing_repost_interstitial = false;
+ main_test_rfh()->OnMessageReceived(
+ FrameHostMsg_DidFailProvisionalLoadWithError(0, params));
+ main_test_rfh()->OnMessageReceived(FrameHostMsg_DidStopLoading(0));
+ }
EXPECT_EQ(url, controller.GetVisibleEntry()->GetURL());
// If something else later modifies the contents of the about:blank page, then
@@ -3723,10 +3805,10 @@ TEST_F(NavigationControllerTest, SameSubframe) {
// Add and navigate a subframe that would normally count as in-page.
main_test_rfh()->OnCreateChildFrame(
process()->GetNextRoutingID(), blink::WebTreeScopeType::Document,
- std::string(), blink::WebSandboxFlags::None,
+ std::string(), "uniqueName0", blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
- RenderFrameHostImpl* subframe =
- contents()->GetFrameTree()->root()->child_at(0)->current_frame_host();
+ TestRenderFrameHost* subframe = static_cast<TestRenderFrameHost*>(
+ contents()->GetFrameTree()->root()->child_at(0)->current_frame_host());
const GURL subframe_url("http://www.google.com/#");
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.page_id = 0;
@@ -3738,8 +3820,9 @@ TEST_F(NavigationControllerTest, SameSubframe) {
params.gesture = NavigationGestureAuto;
params.is_post = false;
params.page_state = PageState::CreateFromURL(subframe_url);
- LoadCommittedDetails details;
- EXPECT_FALSE(controller.RendererDidNavigate(subframe, params, &details));
+ subframe->SendRendererInitiatedNavigationRequest(subframe_url, false);
+ subframe->PrepareForCommit();
+ subframe->SendNavigateWithParams(&params);
// Nothing should have changed.
EXPECT_EQ(controller.GetEntryCount(), 1);
@@ -3890,10 +3973,10 @@ TEST_F(NavigationControllerTest, SubframeWhilePending) {
// automatically loaded. Auto subframes don't increment the page ID.
main_test_rfh()->OnCreateChildFrame(
process()->GetNextRoutingID(), blink::WebTreeScopeType::Document,
- std::string(), blink::WebSandboxFlags::None,
+ std::string(), "uniqueName0", blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
- RenderFrameHostImpl* subframe =
- contents()->GetFrameTree()->root()->child_at(0)->current_frame_host();
+ TestRenderFrameHost* subframe = static_cast<TestRenderFrameHost*>(
+ contents()->GetFrameTree()->root()->child_at(0)->current_frame_host());
const GURL url1_sub("http://foo/subframe");
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.page_id = controller.GetLastCommittedEntry()->GetPageID();
@@ -3905,10 +3988,11 @@ TEST_F(NavigationControllerTest, SubframeWhilePending) {
params.gesture = NavigationGestureAuto;
params.is_post = false;
params.page_state = PageState::CreateFromURL(url1_sub);
- LoadCommittedDetails details;
// This should return false meaning that nothing was actually updated.
- EXPECT_FALSE(controller.RendererDidNavigate(subframe, params, &details));
+ subframe->SendRendererInitiatedNavigationRequest(url1_sub, false);
+ subframe->PrepareForCommit();
+ subframe->SendNavigateWithParams(&params);
// The notification should have updated the last committed one, and not
// the pending load.
@@ -4863,7 +4947,7 @@ TEST_F(NavigationControllerTest, PushStateUpdatesTitleAndFavicon) {
// The title should immediately be visible on the new NavigationEntry.
base::string16 new_title =
- controller().GetLastCommittedEntry()->GetTitleForDisplay(std::string());
+ controller().GetLastCommittedEntry()->GetTitleForDisplay();
EXPECT_EQ(title, new_title);
FaviconStatus new_favicon =
controller().GetLastCommittedEntry()->GetFavicon();
@@ -4967,6 +5051,8 @@ TEST_F(NavigationControllerTest, PostThenReplaceStateThenReload) {
TEST_F(NavigationControllerTest, UnreachableURLGivesErrorPage) {
GURL url("http://foo");
+ controller().LoadURL(url, Referrer(), ui::PAGE_TRANSITION_TYPED,
+ std::string());
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.page_id = 1;
params.nav_entry_id = 0;
@@ -4982,21 +5068,25 @@ TEST_F(NavigationControllerTest, UnreachableURLGivesErrorPage) {
// Navigate to new page.
{
- LoadCommittedDetails details;
- controller_impl().RendererDidNavigate(main_test_rfh(), params, &details);
+ LoadCommittedDetailsObserver observer(contents());
+ main_test_rfh()->SendRendererInitiatedNavigationRequest(url, false);
+ main_test_rfh()->PrepareForCommit();
+ main_test_rfh()->SendNavigateWithParams(&params);
EXPECT_EQ(PAGE_TYPE_ERROR,
controller_impl().GetLastCommittedEntry()->GetPageType());
- EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, details.type);
+ EXPECT_EQ(NAVIGATION_TYPE_NEW_PAGE, observer.details().type);
}
// Navigate to existing page.
{
params.did_create_new_entry = false;
- LoadCommittedDetails details;
- controller_impl().RendererDidNavigate(main_test_rfh(), params, &details);
+ LoadCommittedDetailsObserver observer(contents());
+ main_test_rfh()->SendRendererInitiatedNavigationRequest(url, false);
+ main_test_rfh()->PrepareForCommit();
+ main_test_rfh()->SendNavigateWithParams(&params);
EXPECT_EQ(PAGE_TYPE_ERROR,
controller_impl().GetLastCommittedEntry()->GetPageType());
- EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, details.type);
+ EXPECT_EQ(NAVIGATION_TYPE_EXISTING_PAGE, observer.details().type);
}
// Navigate to same page.
@@ -5007,11 +5097,12 @@ TEST_F(NavigationControllerTest, UnreachableURLGivesErrorPage) {
params.nav_entry_id = controller_impl().GetPendingEntry()->GetUniqueID();
params.transition = ui::PAGE_TRANSITION_TYPED;
{
- LoadCommittedDetails details;
- controller_impl().RendererDidNavigate(main_test_rfh(), params, &details);
+ LoadCommittedDetailsObserver observer(contents());
+ main_test_rfh()->PrepareForCommit();
+ main_test_rfh()->SendNavigateWithParams(&params);
EXPECT_EQ(PAGE_TYPE_ERROR,
controller_impl().GetLastCommittedEntry()->GetPageType());
- EXPECT_EQ(NAVIGATION_TYPE_SAME_PAGE, details.type);
+ EXPECT_EQ(NAVIGATION_TYPE_SAME_PAGE, observer.details().type);
}
// Navigate in page.
@@ -5019,11 +5110,13 @@ TEST_F(NavigationControllerTest, UnreachableURLGivesErrorPage) {
params.transition = ui::PAGE_TRANSITION_LINK;
params.was_within_same_page = true;
{
- LoadCommittedDetails details;
- controller_impl().RendererDidNavigate(main_test_rfh(), params, &details);
+ LoadCommittedDetailsObserver observer(contents());
+ main_test_rfh()->SendRendererInitiatedNavigationRequest(params.url, false);
+ main_test_rfh()->PrepareForCommit();
+ main_test_rfh()->SendNavigateWithParams(&params);
EXPECT_EQ(PAGE_TYPE_ERROR,
controller_impl().GetLastCommittedEntry()->GetPageType());
- EXPECT_TRUE(details.is_in_page);
+ EXPECT_TRUE(observer.details().is_in_page);
}
}
@@ -5094,6 +5187,8 @@ TEST_F(NavigationControllerTest, StaleNavigationsResurrected) {
// killed.
TEST_F(NavigationControllerTest, RendererNavigateBogusSecurityInfo) {
GURL url("http://foo.test");
+ controller().LoadURL(url, Referrer(), ui::PAGE_TRANSITION_TYPED,
+ std::string());
FrameHostMsg_DidCommitProvisionalLoad_Params params;
params.page_id = 0;
params.nav_entry_id = 0;
@@ -5107,22 +5202,26 @@ TEST_F(NavigationControllerTest, RendererNavigateBogusSecurityInfo) {
params.was_within_same_page = false;
params.security_info = "bogus security info!";
- LoadCommittedDetails details;
+ LoadCommittedDetailsObserver observer(contents());
EXPECT_EQ(0, main_test_rfh()->GetProcess()->bad_msg_count());
- EXPECT_TRUE(
- controller_impl().RendererDidNavigate(main_test_rfh(), params, &details));
+ main_test_rfh()->PrepareForCommit();
+ main_test_rfh()->SendNavigateWithParams(&params);
SSLStatus default_ssl_status;
EXPECT_EQ(default_ssl_status.security_style,
- details.ssl_status.security_style);
- EXPECT_EQ(default_ssl_status.cert_id, details.ssl_status.cert_id);
- EXPECT_EQ(default_ssl_status.cert_status, details.ssl_status.cert_status);
- EXPECT_EQ(default_ssl_status.security_bits, details.ssl_status.security_bits);
+ observer.details().ssl_status.security_style);
+ EXPECT_EQ(default_ssl_status.cert_id, observer.details().ssl_status.cert_id);
+ EXPECT_EQ(default_ssl_status.cert_status,
+ observer.details().ssl_status.cert_status);
+ EXPECT_EQ(default_ssl_status.security_bits,
+ observer.details().ssl_status.security_bits);
EXPECT_EQ(default_ssl_status.connection_status,
- details.ssl_status.connection_status);
+ observer.details().ssl_status.connection_status);
EXPECT_EQ(default_ssl_status.content_status,
- details.ssl_status.content_status);
- EXPECT_EQ(0u, details.ssl_status.signed_certificate_timestamp_ids.size());
+ observer.details().ssl_status.content_status);
+ EXPECT_EQ(
+ 0u,
+ observer.details().ssl_status.signed_certificate_timestamp_ids.size());
EXPECT_EQ(1, main_test_rfh()->GetProcess()->bad_msg_count());
}
diff --git a/chromium/content/browser/frame_host/navigation_entry_impl.cc b/chromium/content/browser/frame_host/navigation_entry_impl.cc
index 258429a90b1..ecf43c456e6 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_entry_impl.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include <queue>
+#include <utility>
#include "base/metrics/histogram.h"
#include "base/strings/string_util.h"
@@ -156,15 +157,21 @@ NavigationEntryImpl::NavigationEntryImpl()
ui::PAGE_TRANSITION_LINK, false) {
}
-NavigationEntryImpl::NavigationEntryImpl(SiteInstanceImpl* instance,
- int page_id,
- const GURL& url,
- const Referrer& referrer,
- const base::string16& title,
- ui::PageTransition transition_type,
- bool is_renderer_initiated)
- : frame_tree_(new TreeNode(
- new FrameNavigationEntry(-1, "", -1, -1, instance, url, referrer))),
+NavigationEntryImpl::NavigationEntryImpl(
+ scoped_refptr<SiteInstanceImpl> instance,
+ int page_id,
+ const GURL& url,
+ const Referrer& referrer,
+ const base::string16& title,
+ ui::PageTransition transition_type,
+ bool is_renderer_initiated)
+ : frame_tree_(new TreeNode(new FrameNavigationEntry(-1,
+ "",
+ -1,
+ -1,
+ std::move(instance),
+ url,
+ referrer))),
unique_id_(GetUniqueIDInConstructor()),
bindings_(kInvalidBindings),
page_type_(PAGE_TYPE_NORMAL),
@@ -264,9 +271,17 @@ void NavigationEntryImpl::SetPageState(const PageState& state) {
return;
}
- // This should only be called when restoring a NavigationEntry, so there
- // should be no subframe FrameNavigationEntries yet.
- DCHECK_EQ(0U, frame_tree_->children.size());
+ // SetPageState should only be called before the NavigationEntry has been
+ // loaded, such as for restore (when there are no subframe
+ // FrameNavigationEntries yet). However, some callers expect to call this
+ // after a Clone but before loading the page. Clone will copy over the
+ // subframe entries, and we should reset them before setting the state again.
+ //
+ // TODO(creis): It would be good to verify that this NavigationEntry hasn't
+ // been loaded yet in cases that SetPageState is called while subframe
+ // entries exist, but there's currently no way to check that.
+ if (!frame_tree_->children.empty())
+ frame_tree_->children.clear();
// If the PageState can't be parsed or has no children, just store it on the
// main frame's FrameNavigationEntry without recursively creating subframe
@@ -310,9 +325,10 @@ int32_t NavigationEntryImpl::GetPageID() const {
return page_id_;
}
-void NavigationEntryImpl::set_site_instance(SiteInstanceImpl* site_instance) {
+void NavigationEntryImpl::set_site_instance(
+ scoped_refptr<SiteInstanceImpl> site_instance) {
// TODO(creis): Update all callers and remove this method.
- frame_tree_->frame_entry->set_site_instance(site_instance);
+ frame_tree_->frame_entry->set_site_instance(std::move(site_instance));
}
void NavigationEntryImpl::set_source_site_instance(
@@ -327,8 +343,7 @@ void NavigationEntryImpl::SetBindings(int bindings) {
bindings_ = bindings;
}
-const base::string16& NavigationEntryImpl::GetTitleForDisplay(
- const std::string& languages) const {
+const base::string16& NavigationEntryImpl::GetTitleForDisplay() const {
// Most pages have real titles. Don't even bother caching anything if this is
// the case.
if (!title_.empty())
@@ -342,9 +357,9 @@ const base::string16& NavigationEntryImpl::GetTitleForDisplay(
// Use the virtual URL first if any, and fall back on using the real URL.
base::string16 title;
if (!virtual_url_.is_empty()) {
- title = url_formatter::FormatUrl(virtual_url_, languages);
+ title = url_formatter::FormatUrl(virtual_url_);
} else if (!GetURL().is_empty()) {
- title = url_formatter::FormatUrl(GetURL(), languages);
+ title = url_formatter::FormatUrl(GetURL());
}
// For file:// URLs use the filename as the title, not the full path.
@@ -576,7 +591,7 @@ CommonNavigationParams NavigationEntryImpl::ConstructCommonNavigationParams(
dest_url, dest_referrer, GetTransitionType(), navigation_type,
!IsViewSourceMode(), should_replace_entry(), ui_timestamp, report_type,
GetBaseURLForDataURL(), GetHistoryURLForDataURL(), lofi_state,
- navigation_start);
+ navigation_start, GetHasPostData() ? "POST" : "GET");
}
StartNavigationParams NavigationEntryImpl::ConstructStartNavigationParams()
@@ -589,8 +604,7 @@ StartNavigationParams NavigationEntryImpl::ConstructStartNavigationParams()
GetBrowserInitiatedPostData()->size());
}
- return StartNavigationParams(GetHasPostData(), extra_headers(),
- browser_initiated_post_data,
+ return StartNavigationParams(extra_headers(), browser_initiated_post_data,
#if defined(OS_ANDROID)
has_user_gesture(),
#endif
diff --git a/chromium/content/browser/frame_host/navigation_entry_impl.h b/chromium/content/browser/frame_host/navigation_entry_impl.h
index ac5a3f2f593..ff840331a1f 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl.h
+++ b/chromium/content/browser/frame_host/navigation_entry_impl.h
@@ -69,7 +69,7 @@ class CONTENT_EXPORT NavigationEntryImpl
static int kInvalidBindings;
NavigationEntryImpl();
- NavigationEntryImpl(SiteInstanceImpl* instance,
+ NavigationEntryImpl(scoped_refptr<SiteInstanceImpl> instance,
int page_id,
const GURL& url,
const Referrer& referrer,
@@ -101,8 +101,7 @@ class CONTENT_EXPORT NavigationEntryImpl
PageState GetPageState() const override;
void SetPageID(int page_id) override;
int32_t GetPageID() const override;
- const base::string16& GetTitleForDisplay(
- const std::string& languages) const override;
+ const base::string16& GetTitleForDisplay() const override;
bool IsViewSourceMode() const override;
void SetTransitionType(ui::PageTransition transition_type) override;
ui::PageTransition GetTransitionType() const override;
@@ -219,7 +218,7 @@ class CONTENT_EXPORT NavigationEntryImpl
// Note that the SiteInstance should usually not be changed after it is set,
// but this may happen if the NavigationEntry was cloned and needs to use a
// different SiteInstance.
- void set_site_instance(SiteInstanceImpl* site_instance);
+ void set_site_instance(scoped_refptr<SiteInstanceImpl> site_instance);
SiteInstanceImpl* site_instance() const {
return frame_tree_->frame_entry->site_instance();
}
diff --git a/chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc b/chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc
index 7319b5347c6..ccea60b0158 100644
--- a/chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigation_entry_impl_unittest.cc
@@ -24,9 +24,7 @@ class NavigationEntryTest : public testing::Test {
void SetUp() override {
entry1_.reset(new NavigationEntryImpl);
-#if !defined(OS_IOS)
- instance_ = static_cast<SiteInstanceImpl*>(SiteInstance::Create(NULL));
-#endif
+ instance_ = SiteInstanceImpl::Create(NULL);
entry2_.reset(new NavigationEntryImpl(
instance_, 3,
GURL("test:url"),
@@ -42,7 +40,7 @@ class NavigationEntryTest : public testing::Test {
scoped_ptr<NavigationEntryImpl> entry1_;
scoped_ptr<NavigationEntryImpl> entry2_;
// SiteInstances are deleted when their NavigationEntries are gone.
- SiteInstanceImpl* instance_;
+ scoped_refptr<SiteInstanceImpl> instance_;
};
// Test unique ID accessors
@@ -63,44 +61,42 @@ TEST_F(NavigationEntryTest, NavigationEntryURLs) {
EXPECT_EQ(GURL(), entry1_->GetURL());
EXPECT_EQ(GURL(), entry1_->GetVirtualURL());
- EXPECT_TRUE(entry1_->GetTitleForDisplay(std::string()).empty());
+ EXPECT_TRUE(entry1_->GetTitleForDisplay().empty());
// Setting URL affects virtual_url and GetTitleForDisplay
entry1_->SetURL(GURL("http://www.google.com"));
EXPECT_EQ(GURL("http://www.google.com"), entry1_->GetURL());
EXPECT_EQ(GURL("http://www.google.com"), entry1_->GetVirtualURL());
EXPECT_EQ(ASCIIToUTF16("www.google.com"),
- entry1_->GetTitleForDisplay(std::string()));
+ entry1_->GetTitleForDisplay());
// file:/// URLs should only show the filename.
entry1_->SetURL(GURL("file:///foo/bar baz.txt"));
- EXPECT_EQ(ASCIIToUTF16("bar baz.txt"),
- entry1_->GetTitleForDisplay(std::string()));
+ EXPECT_EQ(ASCIIToUTF16("bar baz.txt"), entry1_->GetTitleForDisplay());
// For file:/// URLs, make sure that slashes after the filename are ignored.
// Regression test for https://crbug.com/503003.
entry1_->SetURL(GURL("file:///foo/bar baz.txt#foo/bar"));
- EXPECT_EQ(ASCIIToUTF16("bar baz.txt#foo/bar"),
- entry1_->GetTitleForDisplay(std::string()));
+ EXPECT_EQ(ASCIIToUTF16("bar baz.txt#foo/bar"), entry1_->GetTitleForDisplay());
entry1_->SetURL(GURL("file:///foo/bar baz.txt?x=foo/bar"));
EXPECT_EQ(ASCIIToUTF16("bar baz.txt?x=foo/bar"),
- entry1_->GetTitleForDisplay(std::string()));
+ entry1_->GetTitleForDisplay());
entry1_->SetURL(GURL("file:///foo/bar baz.txt#baz/boo?x=foo/bar"));
EXPECT_EQ(ASCIIToUTF16("bar baz.txt#baz/boo?x=foo/bar"),
- entry1_->GetTitleForDisplay(std::string()));
+ entry1_->GetTitleForDisplay());
entry1_->SetURL(GURL("file:///foo/bar baz.txt?x=foo/bar#baz/boo"));
EXPECT_EQ(ASCIIToUTF16("bar baz.txt?x=foo/bar#baz/boo"),
- entry1_->GetTitleForDisplay(std::string()));
+ entry1_->GetTitleForDisplay());
entry1_->SetURL(GURL("file:///foo/bar baz.txt#foo/bar#baz/boo"));
EXPECT_EQ(ASCIIToUTF16("bar baz.txt#foo/bar#baz/boo"),
- entry1_->GetTitleForDisplay(std::string()));
+ entry1_->GetTitleForDisplay());
entry1_->SetURL(GURL("file:///foo/bar baz.txt?x=foo/bar?y=baz/boo"));
EXPECT_EQ(ASCIIToUTF16("bar baz.txt?x=foo/bar?y=baz/boo"),
- entry1_->GetTitleForDisplay(std::string()));
+ entry1_->GetTitleForDisplay());
// Title affects GetTitleForDisplay
entry1_->SetTitle(ASCIIToUTF16("Google"));
- EXPECT_EQ(ASCIIToUTF16("Google"), entry1_->GetTitleForDisplay(std::string()));
+ EXPECT_EQ(ASCIIToUTF16("Google"), entry1_->GetTitleForDisplay());
// Setting virtual_url doesn't affect URL
entry2_->SetVirtualURL(GURL("display:url"));
@@ -109,7 +105,7 @@ TEST_F(NavigationEntryTest, NavigationEntryURLs) {
EXPECT_EQ(GURL("display:url"), entry2_->GetVirtualURL());
// Having a title set in constructor overrides virtual URL
- EXPECT_EQ(ASCIIToUTF16("title"), entry2_->GetTitleForDisplay(std::string()));
+ EXPECT_EQ(ASCIIToUTF16("title"), entry2_->GetTitleForDisplay());
// User typed URL is independent of the others
EXPECT_EQ(GURL(), entry1_->GetUserTypedURL());
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl.cc b/chromium/content/browser/frame_host/navigation_handle_impl.cc
index a8d32e911e2..dde5fa77087 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl.cc
+++ b/chromium/content/browser/frame_host/navigation_handle_impl.cc
@@ -11,6 +11,7 @@
#include "content/browser/frame_host/navigator_delegate.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_navigation_handle.h"
+#include "content/common/frame_messages.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_client.h"
@@ -32,15 +33,22 @@ void UpdateThrottleCheckResult(
scoped_ptr<NavigationHandleImpl> NavigationHandleImpl::Create(
const GURL& url,
FrameTreeNode* frame_tree_node,
- const base::TimeTicks& navigation_start) {
+ bool is_synchronous,
+ bool is_srcdoc,
+ const base::TimeTicks& navigation_start,
+ int pending_nav_entry_id) {
return scoped_ptr<NavigationHandleImpl>(
- new NavigationHandleImpl(url, frame_tree_node, navigation_start));
+ new NavigationHandleImpl(url, frame_tree_node, is_synchronous, is_srcdoc,
+ navigation_start, pending_nav_entry_id));
}
NavigationHandleImpl::NavigationHandleImpl(
const GURL& url,
FrameTreeNode* frame_tree_node,
- const base::TimeTicks& navigation_start)
+ bool is_synchronous,
+ bool is_srcdoc,
+ const base::TimeTicks& navigation_start,
+ int pending_nav_entry_id)
: url_(url),
is_post_(false),
has_user_gesture_(false),
@@ -49,11 +57,15 @@ NavigationHandleImpl::NavigationHandleImpl(
net_error_code_(net::OK),
render_frame_host_(nullptr),
is_same_page_(false),
+ is_synchronous_(is_synchronous),
+ is_srcdoc_(is_srcdoc),
+ was_redirected_(false),
state_(INITIAL),
is_transferring_(false),
frame_tree_node_(frame_tree_node),
next_index_(0),
- navigation_start_(navigation_start) {
+ navigation_start_(navigation_start),
+ pending_nav_entry_id_(pending_nav_entry_id) {
DCHECK(!navigation_start.is_null());
GetDelegate()->DidStartNavigation(this);
}
@@ -79,6 +91,36 @@ bool NavigationHandleImpl::IsInMainFrame() {
return frame_tree_node_->IsMainFrame();
}
+bool NavigationHandleImpl::IsParentMainFrame() {
+ if (frame_tree_node_->parent())
+ return frame_tree_node_->parent()->IsMainFrame();
+
+ return false;
+}
+
+bool NavigationHandleImpl::IsSynchronousNavigation() {
+ return is_synchronous_;
+}
+
+bool NavigationHandleImpl::IsSrcdoc() {
+ return is_srcdoc_;
+}
+
+bool NavigationHandleImpl::WasServerRedirect() {
+ return was_redirected_;
+}
+
+int NavigationHandleImpl::GetFrameTreeNodeId() {
+ return frame_tree_node_->frame_tree_node_id();
+}
+
+int NavigationHandleImpl::GetParentFrameTreeNodeId() {
+ if (frame_tree_node_->IsMainFrame())
+ return FrameTreeNode::kFrameTreeNodeInvalidId;
+
+ return frame_tree_node_->parent()->frame_tree_node_id();
+}
+
const base::TimeTicks& NavigationHandleImpl::NavigationStart() {
return navigation_start_;
}
@@ -132,9 +174,6 @@ bool NavigationHandleImpl::IsSamePage() {
}
const net::HttpResponseHeaders* NavigationHandleImpl::GetResponseHeaders() {
- DCHECK(state_ >= WILL_REDIRECT_REQUEST)
- << "This accessor should only be called when the request encountered a "
- "redirect or received a response";
return response_headers_.get();
}
@@ -147,14 +186,23 @@ bool NavigationHandleImpl::IsErrorPage() {
}
void NavigationHandleImpl::Resume() {
- if (state_ != DEFERRING_START && state_ != DEFERRING_REDIRECT)
+ if (state_ != DEFERRING_START && state_ != DEFERRING_REDIRECT &&
+ state_ != DEFERRING_RESPONSE) {
return;
+ }
NavigationThrottle::ThrottleCheckResult result = NavigationThrottle::DEFER;
if (state_ == DEFERRING_START) {
result = CheckWillStartRequest();
- } else {
+ } else if (state_ == DEFERRING_REDIRECT) {
result = CheckWillRedirectRequest();
+ } else {
+ result = CheckWillProcessResponse();
+
+ // If the navigation is about to proceed after processing the response, then
+ // it's ready to commit.
+ if (result == NavigationThrottle::PROCEED)
+ ReadyToCommitNavigation(render_frame_host_);
}
if (result != NavigationThrottle::DEFER)
@@ -267,6 +315,7 @@ void NavigationHandleImpl::WillRedirectRequest(
sanitized_referrer_ = Referrer::SanitizeForRequest(url_, sanitized_referrer_);
is_external_protocol_ = new_is_external_protocol;
response_headers_ = response_headers;
+ was_redirected_ = true;
state_ = WILL_REDIRECT_REQUEST;
complete_callback_ = callback;
@@ -279,17 +328,32 @@ void NavigationHandleImpl::WillRedirectRequest(
RunCompleteCallback(result);
}
-void NavigationHandleImpl::DidRedirectNavigation(const GURL& new_url) {
- url_ = new_url;
- GetDelegate()->DidRedirectNavigation(this);
+void NavigationHandleImpl::WillProcessResponse(
+ RenderFrameHostImpl* render_frame_host,
+ scoped_refptr<net::HttpResponseHeaders> response_headers,
+ const ThrottleChecksFinishedCallback& callback) {
+ DCHECK(!render_frame_host_ || render_frame_host_ == render_frame_host);
+ render_frame_host_ = render_frame_host;
+ response_headers_ = response_headers;
+ state_ = WILL_PROCESS_RESPONSE;
+ complete_callback_ = callback;
+
+ // Notify each throttle of the response.
+ NavigationThrottle::ThrottleCheckResult result = CheckWillProcessResponse();
+
+ // If the navigation is about to proceed, then it's ready to commit.
+ if (result == NavigationThrottle::PROCEED)
+ ReadyToCommitNavigation(render_frame_host);
+
+ // If the navigation is not deferred, run the callback.
+ if (result != NavigationThrottle::DEFER)
+ RunCompleteCallback(result);
}
void NavigationHandleImpl::ReadyToCommitNavigation(
- RenderFrameHostImpl* render_frame_host,
- scoped_refptr<net::HttpResponseHeaders> response_headers) {
+ RenderFrameHostImpl* render_frame_host) {
DCHECK(!render_frame_host_ || render_frame_host_ == render_frame_host);
render_frame_host_ = render_frame_host;
- response_headers_ = response_headers;
state_ = READY_TO_COMMIT;
// Only notify the WebContentsObservers when PlzNavigate is enabled, as
@@ -299,11 +363,19 @@ void NavigationHandleImpl::ReadyToCommitNavigation(
}
void NavigationHandleImpl::DidCommitNavigation(
+ const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
bool same_page,
RenderFrameHostImpl* render_frame_host) {
DCHECK(!render_frame_host_ || render_frame_host_ == render_frame_host);
- is_same_page_ = same_page;
+ DCHECK_EQ(frame_tree_node_, render_frame_host->frame_tree_node());
+ CHECK_EQ(url_, params.url);
+
+ is_post_ = params.is_post;
+ has_user_gesture_ = (params.gesture == NavigationGestureUser);
+ transition_ = params.transition;
render_frame_host_ = render_frame_host;
+ is_same_page_ = same_page;
+
state_ = net_error_code_ == net::OK ? DID_COMMIT : DID_COMMIT_ERROR_PAGE;
}
@@ -366,16 +438,54 @@ NavigationHandleImpl::CheckWillRedirectRequest() {
}
next_index_ = 0;
state_ = WILL_REDIRECT_REQUEST;
+
+ // Notify the delegate that a redirect was encountered and will be followed.
+ if (GetDelegate())
+ GetDelegate()->DidRedirectNavigation(this);
+
+ return NavigationThrottle::PROCEED;
+}
+
+NavigationThrottle::ThrottleCheckResult
+NavigationHandleImpl::CheckWillProcessResponse() {
+ DCHECK(state_ == WILL_PROCESS_RESPONSE || state_ == DEFERRING_RESPONSE);
+ DCHECK(state_ != WILL_PROCESS_RESPONSE || next_index_ == 0);
+ DCHECK(state_ != DEFERRING_RESPONSE || next_index_ != 0);
+ for (size_t i = next_index_; i < throttles_.size(); ++i) {
+ NavigationThrottle::ThrottleCheckResult result =
+ throttles_[i]->WillProcessResponse();
+ switch (result) {
+ case NavigationThrottle::PROCEED:
+ continue;
+
+ case NavigationThrottle::CANCEL:
+ case NavigationThrottle::CANCEL_AND_IGNORE:
+ state_ = CANCELING;
+ return result;
+
+ case NavigationThrottle::DEFER:
+ state_ = DEFERRING_RESPONSE;
+ next_index_ = i + 1;
+ return result;
+ }
+ }
+ next_index_ = 0;
+ state_ = WILL_PROCESS_RESPONSE;
return NavigationThrottle::PROCEED;
}
void NavigationHandleImpl::RunCompleteCallback(
NavigationThrottle::ThrottleCheckResult result) {
DCHECK(result != NavigationThrottle::DEFER);
- if (!complete_callback_.is_null())
- complete_callback_.Run(result);
+ ThrottleChecksFinishedCallback callback = complete_callback_;
complete_callback_.Reset();
+
+ if (!callback.is_null())
+ callback.Run(result);
+
+ // No code after running the callback, as it might have resulted in our
+ // destruction.
}
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl.h b/chromium/content/browser/frame_host/navigation_handle_impl.h
index 192cdab3348..252a2e03d39 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl.h
+++ b/chromium/content/browser/frame_host/navigation_handle_impl.h
@@ -11,7 +11,6 @@
#include "base/callback.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
@@ -19,6 +18,8 @@
#include "content/public/browser/navigation_throttle.h"
#include "url/gurl.h"
+struct FrameHostMsg_DidCommitProvisionalLoad_Params;
+
namespace content {
class NavigatorDelegate;
@@ -68,12 +69,21 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
static scoped_ptr<NavigationHandleImpl> Create(
const GURL& url,
FrameTreeNode* frame_tree_node,
- const base::TimeTicks& navigation_start);
+ bool is_synchronous,
+ bool is_srcdoc,
+ const base::TimeTicks& navigation_start,
+ int pending_nav_entry_id);
~NavigationHandleImpl() override;
// NavigationHandle implementation:
const GURL& GetURL() override;
bool IsInMainFrame() override;
+ bool IsParentMainFrame() override;
+ bool IsSynchronousNavigation() override;
+ bool IsSrcdoc() override;
+ bool WasServerRedirect() override;
+ int GetFrameTreeNodeId() override;
+ int GetParentFrameTreeNodeId() override;
const base::TimeTicks& NavigationStart() override;
bool IsPost() override;
const Referrer& GetReferrer() override;
@@ -104,12 +114,25 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
NavigatorDelegate* GetDelegate() const;
- // Returns the response headers for the request. This can only be accessed
- // after a redirect was encountered or after the the navigation is ready to
- // commit. It should not be modified, as modifications will not be reflected
- // in the network stack.
+ // Returns the response headers for the request or nullptr if there are none.
+ // This should only be accessed after a redirect was encountered or after the
+ // navigation is ready to commit. The headers returned should not be modified,
+ // as modifications will not be reflected in the network stack.
const net::HttpResponseHeaders* GetResponseHeaders();
+ // Get the unique id from the NavigationEntry associated with this
+ // NavigationHandle. Note that a synchronous, renderer-initiated navigation
+ // will not have a NavigationEntry associated with it, and this will return 0.
+ int pending_nav_entry_id() const { return pending_nav_entry_id_; }
+
+ // Changes the pending NavigationEntry ID for this handle. This is currently
+ // required during transfer navigations.
+ // TODO(creis): Remove this when transfer navigations do not require pending
+ // entries. See https://crbug.com/495161.
+ void update_entry_id_for_transfer(int nav_entry_id) {
+ pending_nav_entry_id_ = nav_entry_id;
+ }
+
void set_net_error_code(net::Error net_error_code) {
net_error_code_ = net_error_code;
}
@@ -152,6 +175,7 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
// Called when the URLRequest will be redirected in the network stack.
// |callback| will be called when all throttles check have completed. This
// will allow the caller to cancel the navigation or let it proceed.
+ // This will also inform the delegate that the request was redirected.
void WillRedirectRequest(
const GURL& new_url,
bool new_method_is_post,
@@ -160,24 +184,32 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
scoped_refptr<net::HttpResponseHeaders> response_headers,
const ThrottleChecksFinishedCallback& callback);
+ // Called when the URLRequest has delivered response headers and metadata.
+ // |callback| will be called when all throttle checks have completed,
+ // allowing the caller to cancel the navigation or let it proceed.
+ // NavigationHandle will not call |callback| with a result of DEFER.
+ // If the result is PROCEED, then 'ReadyToCommitNavigation' will be called
+ // with |render_frame_host| and |response_headers| just before calling
+ // |callback|.
+ void WillProcessResponse(
+ RenderFrameHostImpl* render_frame_host,
+ scoped_refptr<net::HttpResponseHeaders> response_headers,
+ const ThrottleChecksFinishedCallback& callback);
+
// Returns the FrameTreeNode this navigation is happening in.
FrameTreeNode* frame_tree_node() { return frame_tree_node_; }
- // Called when the navigation was redirected. This will update the |url_| and
- // inform the delegate.
- void DidRedirectNavigation(const GURL& new_url);
-
// Called when the navigation is ready to be committed in
// |render_frame_host|. This will update the |state_| and inform the
// delegate.
- void ReadyToCommitNavigation(
- RenderFrameHostImpl* render_frame_host,
- scoped_refptr<net::HttpResponseHeaders> response_headers);
+ void ReadyToCommitNavigation(RenderFrameHostImpl* render_frame_host);
// Called when the navigation was committed in |render_frame_host|. This will
// update the |state_|.
- void DidCommitNavigation(bool same_page,
- RenderFrameHostImpl* render_frame_host);
+ void DidCommitNavigation(
+ const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
+ bool same_page,
+ RenderFrameHostImpl* render_frame_host);
private:
friend class NavigationHandleImplTest;
@@ -190,6 +222,8 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
WILL_REDIRECT_REQUEST,
DEFERRING_REDIRECT,
CANCELING,
+ WILL_PROCESS_RESPONSE,
+ DEFERRING_RESPONSE,
READY_TO_COMMIT,
DID_COMMIT,
DID_COMMIT_ERROR_PAGE,
@@ -197,10 +231,14 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
NavigationHandleImpl(const GURL& url,
FrameTreeNode* frame_tree_node,
- const base::TimeTicks& navigation_start);
+ bool is_synchronous,
+ bool is_srcdoc,
+ const base::TimeTicks& navigation_start,
+ int pending_nav_entry_id);
NavigationThrottle::ThrottleCheckResult CheckWillStartRequest();
NavigationThrottle::ThrottleCheckResult CheckWillRedirectRequest();
+ NavigationThrottle::ThrottleCheckResult CheckWillProcessResponse();
// Helper function to run and reset the |complete_callback_|. This marks the
// end of a round of NavigationThrottleChecks.
@@ -219,6 +257,9 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
net::Error net_error_code_;
RenderFrameHostImpl* render_frame_host_;
bool is_same_page_;
+ const bool is_synchronous_;
+ const bool is_srcdoc_;
+ bool was_redirected_;
scoped_refptr<net::HttpResponseHeaders> response_headers_;
// The state the navigation is in.
@@ -240,6 +281,9 @@ class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle {
// The time this navigation started.
const base::TimeTicks navigation_start_;
+ // The unique id of the corresponding NavigationEntry.
+ int pending_nav_entry_id_;
+
// This callback will be run when all throttle checks have been performed.
ThrottleChecksFinishedCallback complete_callback_;
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc b/chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc
new file mode 100644
index 00000000000..7630a743531
--- /dev/null
+++ b/chromium/content/browser/frame_host/navigation_handle_impl_browsertest.cc
@@ -0,0 +1,560 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/frame_host/navigation_handle_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "net/dns/mock_host_resolver.h"
+#include "ui/base/page_transition_types.h"
+#include "url/url_constants.h"
+
+namespace content {
+
+namespace {
+
+class NavigationHandleObserver : public WebContentsObserver {
+ public:
+ NavigationHandleObserver(WebContents* web_contents, const GURL& expected_url)
+ : WebContentsObserver(web_contents),
+ handle_(nullptr),
+ has_committed_(false),
+ is_error_(false),
+ is_main_frame_(false),
+ is_parent_main_frame_(false),
+ is_synchronous_(false),
+ is_srcdoc_(false),
+ was_redirected_(false),
+ frame_tree_node_id_(-1),
+ page_transition_(ui::PAGE_TRANSITION_LINK),
+ expected_url_(expected_url) {}
+
+ void DidStartNavigation(NavigationHandle* navigation_handle) override {
+ if (handle_ || navigation_handle->GetURL() != expected_url_)
+ return;
+
+ handle_ = navigation_handle;
+ has_committed_ = false;
+ is_error_ = false;
+ page_transition_ = ui::PAGE_TRANSITION_LINK;
+ last_committed_url_ = GURL();
+
+ is_main_frame_ = navigation_handle->IsInMainFrame();
+ is_parent_main_frame_ = navigation_handle->IsParentMainFrame();
+ is_synchronous_ = navigation_handle->IsSynchronousNavigation();
+ is_srcdoc_ = navigation_handle->IsSrcdoc();
+ was_redirected_ = navigation_handle->WasServerRedirect();
+ frame_tree_node_id_ = navigation_handle->GetFrameTreeNodeId();
+ }
+
+ void DidFinishNavigation(NavigationHandle* navigation_handle) override {
+ if (navigation_handle != handle_)
+ return;
+
+ DCHECK_EQ(is_main_frame_, navigation_handle->IsInMainFrame());
+ DCHECK_EQ(is_parent_main_frame_, navigation_handle->IsParentMainFrame());
+ DCHECK_EQ(is_synchronous_, navigation_handle->IsSynchronousNavigation());
+ DCHECK_EQ(is_srcdoc_, navigation_handle->IsSrcdoc());
+ DCHECK_EQ(frame_tree_node_id_, navigation_handle->GetFrameTreeNodeId());
+
+ was_redirected_ = navigation_handle->WasServerRedirect();
+
+ if (navigation_handle->HasCommitted()) {
+ has_committed_ = true;
+ if (!navigation_handle->IsErrorPage()) {
+ page_transition_ = navigation_handle->GetPageTransition();
+ last_committed_url_ = navigation_handle->GetURL();
+ } else {
+ is_error_ = true;
+ }
+ } else {
+ has_committed_ = false;
+ is_error_ = true;
+ }
+
+ handle_ = nullptr;
+ }
+
+ bool has_committed() { return has_committed_; }
+ bool is_error() { return is_error_; }
+ bool is_main_frame() { return is_main_frame_; }
+ bool is_parent_main_frame() { return is_parent_main_frame_; }
+ bool is_synchronous() { return is_synchronous_; }
+ bool is_srcdoc() { return is_srcdoc_; }
+ bool was_redirected() { return was_redirected_; }
+ int frame_tree_node_id() { return frame_tree_node_id_; }
+
+ const GURL& last_committed_url() { return last_committed_url_; }
+
+ ui::PageTransition page_transition() { return page_transition_; }
+
+ private:
+ // A reference to the NavigationHandle so this class will track only
+ // one navigation at a time. It is set at DidStartNavigation and cleared
+ // at DidFinishNavigation before the NavigationHandle is destroyed.
+ NavigationHandle* handle_;
+ bool has_committed_;
+ bool is_error_;
+ bool is_main_frame_;
+ bool is_parent_main_frame_;
+ bool is_synchronous_;
+ bool is_srcdoc_;
+ bool was_redirected_;
+ int frame_tree_node_id_;
+ ui::PageTransition page_transition_;
+ GURL expected_url_;
+ GURL last_committed_url_;
+};
+
+// A test NavigationThrottle that will return pre-determined checks and run
+// callbacks when the various NavigationThrottle methods are called.
+class TestNavigationThrottle : public NavigationThrottle {
+ public:
+ TestNavigationThrottle(
+ NavigationHandle* handle,
+ NavigationThrottle::ThrottleCheckResult will_start_result,
+ NavigationThrottle::ThrottleCheckResult will_redirect_result,
+ NavigationThrottle::ThrottleCheckResult will_process_result,
+ base::Closure did_call_will_start,
+ base::Closure did_call_will_redirect,
+ base::Closure did_call_will_process)
+ : NavigationThrottle(handle),
+ will_start_result_(will_start_result),
+ will_redirect_result_(will_redirect_result),
+ will_process_result_(will_process_result),
+ did_call_will_start_(did_call_will_start),
+ did_call_will_redirect_(did_call_will_redirect),
+ did_call_will_process_(did_call_will_process) {}
+ ~TestNavigationThrottle() override {}
+
+ void Resume() { navigation_handle()->Resume(); }
+
+ private:
+ // NavigationThrottle implementation.
+ NavigationThrottle::ThrottleCheckResult WillStartRequest() override {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, did_call_will_start_);
+ return will_start_result_;
+ }
+
+ NavigationThrottle::ThrottleCheckResult WillRedirectRequest() override {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ did_call_will_redirect_);
+ return will_redirect_result_;
+ }
+
+ NavigationThrottle::ThrottleCheckResult WillProcessResponse() override {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ did_call_will_process_);
+ return will_process_result_;
+ }
+
+ NavigationThrottle::ThrottleCheckResult will_start_result_;
+ NavigationThrottle::ThrottleCheckResult will_redirect_result_;
+ NavigationThrottle::ThrottleCheckResult will_process_result_;
+ base::Closure did_call_will_start_;
+ base::Closure did_call_will_redirect_;
+ base::Closure did_call_will_process_;
+};
+
+// Install a TestNavigationThrottle on all requests and allows waiting for
+// various NavigationThrottle related events.
+class TestNavigationThrottleInstaller : public WebContentsObserver {
+ public:
+ TestNavigationThrottleInstaller(
+ WebContents* web_contents,
+ NavigationThrottle::ThrottleCheckResult will_start_result,
+ NavigationThrottle::ThrottleCheckResult will_redirect_result,
+ NavigationThrottle::ThrottleCheckResult will_process_result)
+ : WebContentsObserver(web_contents),
+ will_start_result_(will_start_result),
+ will_redirect_result_(will_redirect_result),
+ will_process_result_(will_process_result),
+ will_start_called_(0),
+ will_redirect_called_(0),
+ will_process_called_(0),
+ navigation_throttle_(nullptr) {}
+ ~TestNavigationThrottleInstaller() override{};
+
+ TestNavigationThrottle* navigation_throttle() { return navigation_throttle_; }
+
+ void WaitForThrottleWillStart() {
+ if (will_start_called_)
+ return;
+ will_start_loop_runner_ = new MessageLoopRunner();
+ will_start_loop_runner_->Run();
+ will_start_loop_runner_ = nullptr;
+ }
+
+ void WaitForThrottleWillRedirect() {
+ if (will_redirect_called_)
+ return;
+ will_redirect_loop_runner_ = new MessageLoopRunner();
+ will_redirect_loop_runner_->Run();
+ will_redirect_loop_runner_ = nullptr;
+ }
+
+ void WaitForThrottleWillProcess() {
+ if (will_process_called_)
+ return;
+ will_process_loop_runner_ = new MessageLoopRunner();
+ will_process_loop_runner_->Run();
+ will_process_loop_runner_ = nullptr;
+ }
+
+ int will_start_called() { return will_start_called_; }
+ int will_redirect_called() { return will_redirect_called_; }
+ int will_process_called() { return will_process_called_; }
+
+ private:
+ void DidStartNavigation(NavigationHandle* handle) override {
+ scoped_ptr<NavigationThrottle> throttle(new TestNavigationThrottle(
+ handle, will_start_result_, will_redirect_result_, will_process_result_,
+ base::Bind(&TestNavigationThrottleInstaller::DidCallWillStartRequest,
+ base::Unretained(this)),
+ base::Bind(&TestNavigationThrottleInstaller::DidCallWillRedirectRequest,
+ base::Unretained(this)),
+ base::Bind(&TestNavigationThrottleInstaller::DidCallWillProcessResponse,
+ base::Unretained(this))));
+ navigation_throttle_ = static_cast<TestNavigationThrottle*>(throttle.get());
+ handle->RegisterThrottleForTesting(std::move(throttle));
+ }
+
+ void DidFinishNavigation(NavigationHandle* handle) override {
+ if (!navigation_throttle_)
+ return;
+
+ if (handle == navigation_throttle_->navigation_handle())
+ navigation_throttle_ = nullptr;
+ }
+
+ void DidCallWillStartRequest() {
+ will_start_called_++;
+ if (will_start_loop_runner_)
+ will_start_loop_runner_->Quit();
+ }
+
+ void DidCallWillRedirectRequest() {
+ will_redirect_called_++;
+ if (will_redirect_loop_runner_)
+ will_redirect_loop_runner_->Quit();
+ }
+
+ void DidCallWillProcessResponse() {
+ will_process_called_++;
+ if (will_process_loop_runner_)
+ will_process_loop_runner_->Quit();
+ }
+
+ NavigationThrottle::ThrottleCheckResult will_start_result_;
+ NavigationThrottle::ThrottleCheckResult will_redirect_result_;
+ NavigationThrottle::ThrottleCheckResult will_process_result_;
+ int will_start_called_;
+ int will_redirect_called_;
+ int will_process_called_;
+ TestNavigationThrottle* navigation_throttle_;
+ scoped_refptr<MessageLoopRunner> will_start_loop_runner_;
+ scoped_refptr<MessageLoopRunner> will_redirect_loop_runner_;
+ scoped_refptr<MessageLoopRunner> will_process_loop_runner_;
+};
+
+} // namespace
+
+class NavigationHandleImplBrowserTest : public ContentBrowserTest {
+ protected:
+ void SetUpOnMainThread() override {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(embedded_test_server()->Start());
+ SetupCrossSiteRedirector(embedded_test_server());
+ }
+};
+
+// Ensure that PageTransition is properly set on the NavigationHandle.
+IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, VerifyPageTransition) {
+ {
+ // Test browser initiated navigation, which should have a PageTransition as
+ // if it came from the omnibox.
+ GURL url(embedded_test_server()->GetURL("/title1.html"));
+ NavigationHandleObserver observer(shell()->web_contents(), url);
+ ui::PageTransition expected_transition = ui::PageTransitionFromInt(
+ ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
+
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+
+ EXPECT_TRUE(observer.has_committed());
+ EXPECT_FALSE(observer.is_error());
+ EXPECT_EQ(url, observer.last_committed_url());
+ EXPECT_EQ(expected_transition, observer.page_transition());
+ }
+
+ {
+ // Test navigating to a page with subframe. The subframe will have
+ // PageTransition of type AUTO_SUBFRAME.
+ GURL url(
+ embedded_test_server()->GetURL("/frame_tree/page_with_one_frame.html"));
+ NavigationHandleObserver observer(
+ shell()->web_contents(),
+ embedded_test_server()->GetURL("/cross-site/baz.com/title1.html"));
+ ui::PageTransition expected_transition =
+ ui::PageTransitionFromInt(ui::PAGE_TRANSITION_AUTO_SUBFRAME);
+
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+
+ EXPECT_TRUE(observer.has_committed());
+ EXPECT_FALSE(observer.is_error());
+ EXPECT_EQ(embedded_test_server()->GetURL("baz.com", "/title1.html"),
+ observer.last_committed_url());
+ EXPECT_EQ(expected_transition, observer.page_transition());
+ EXPECT_FALSE(observer.is_main_frame());
+ }
+}
+
+// Ensure that the following methods on NavigationHandle behave correctly:
+// * IsInMainFrame
+// * IsParentMainFrame
+IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, VerifyFrameTree) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b(c))"));
+ GURL b_url(embedded_test_server()->GetURL(
+ "b.com", "/cross_site_iframe_factory.html?b(c())"));
+ GURL c_url(embedded_test_server()->GetURL(
+ "c.com", "/cross_site_iframe_factory.html?c()"));
+
+ NavigationHandleObserver main_observer(shell()->web_contents(), main_url);
+ NavigationHandleObserver b_observer(shell()->web_contents(), b_url);
+ NavigationHandleObserver c_observer(shell()->web_contents(), c_url);
+
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // Verify the main frame.
+ EXPECT_TRUE(main_observer.has_committed());
+ EXPECT_FALSE(main_observer.is_error());
+ EXPECT_EQ(main_url, main_observer.last_committed_url());
+ EXPECT_TRUE(main_observer.is_main_frame());
+ EXPECT_EQ(root->frame_tree_node_id(), main_observer.frame_tree_node_id());
+
+ // Verify the b.com frame.
+ EXPECT_TRUE(b_observer.has_committed());
+ EXPECT_FALSE(b_observer.is_error());
+ EXPECT_EQ(b_url, b_observer.last_committed_url());
+ EXPECT_FALSE(b_observer.is_main_frame());
+ EXPECT_TRUE(b_observer.is_parent_main_frame());
+ EXPECT_EQ(root->child_at(0)->frame_tree_node_id(),
+ b_observer.frame_tree_node_id());
+
+ // Verify the c.com frame.
+ EXPECT_TRUE(c_observer.has_committed());
+ EXPECT_FALSE(c_observer.is_error());
+ EXPECT_EQ(c_url, c_observer.last_committed_url());
+ EXPECT_FALSE(c_observer.is_main_frame());
+ EXPECT_FALSE(c_observer.is_parent_main_frame());
+ EXPECT_EQ(root->child_at(0)->child_at(0)->frame_tree_node_id(),
+ c_observer.frame_tree_node_id());
+}
+
+// Ensure that the WasRedirected() method on NavigationHandle behaves correctly.
+IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, VerifyRedirect) {
+ {
+ GURL url(embedded_test_server()->GetURL("/title1.html"));
+ NavigationHandleObserver observer(shell()->web_contents(), url);
+
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+
+ EXPECT_TRUE(observer.has_committed());
+ EXPECT_FALSE(observer.is_error());
+ EXPECT_FALSE(observer.was_redirected());
+ }
+
+ {
+ GURL url(embedded_test_server()->GetURL("/cross-site/baz.com/title1.html"));
+ NavigationHandleObserver observer(shell()->web_contents(), url);
+
+ NavigateToURL(shell(), url);
+
+ EXPECT_TRUE(observer.has_committed());
+ EXPECT_FALSE(observer.is_error());
+ EXPECT_TRUE(observer.was_redirected());
+ }
+}
+
+// Ensure that the IsSrcdoc() method on NavigationHandle behaves correctly.
+IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, VerifySrcdoc) {
+ GURL url(embedded_test_server()->GetURL(
+ "/frame_tree/page_with_srcdoc_frame.html"));
+ NavigationHandleObserver observer(shell()->web_contents(),
+ GURL(url::kAboutBlankURL));
+
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+
+ EXPECT_TRUE(observer.has_committed());
+ EXPECT_FALSE(observer.is_error());
+ EXPECT_TRUE(observer.is_srcdoc());
+}
+
+// Ensure that the IsSynchronousNavigation() method on NavigationHandle behaves
+// correctly.
+IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, VerifySynchronous) {
+ GURL url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(a())"));
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ NavigationHandleObserver observer(
+ shell()->web_contents(), embedded_test_server()->GetURL("a.com", "/bar"));
+ EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(),
+ "window.history.pushState({}, '', 'bar');"));
+
+ EXPECT_TRUE(observer.has_committed());
+ EXPECT_FALSE(observer.is_error());
+ EXPECT_TRUE(observer.is_synchronous());
+}
+
+// Ensure that a NavigationThrottle can cancel the navigation at navigation
+// start.
+IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, ThrottleCancelStart) {
+ GURL start_url(embedded_test_server()->GetURL("/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), start_url));
+
+ GURL redirect_url(
+ embedded_test_server()->GetURL("/cross-site/bar.com/title2.html"));
+ NavigationHandleObserver observer(shell()->web_contents(), redirect_url);
+ TestNavigationThrottleInstaller installer(
+ shell()->web_contents(), NavigationThrottle::CANCEL,
+ NavigationThrottle::PROCEED, NavigationThrottle::PROCEED);
+
+ EXPECT_FALSE(NavigateToURL(shell(), redirect_url));
+
+ EXPECT_FALSE(observer.has_committed());
+ EXPECT_TRUE(observer.is_error());
+
+ // The navigation should have been canceled before being redirected.
+ EXPECT_FALSE(observer.was_redirected());
+ EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), start_url);
+}
+
+// Ensure that a NavigationThrottle can cancel the navigation when a navigation
+// is redirected.
+IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest,
+ ThrottleCancelRedirect) {
+ GURL start_url(embedded_test_server()->GetURL("/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), start_url));
+
+ // A navigation with a redirect should be canceled.
+ {
+ GURL redirect_url(
+ embedded_test_server()->GetURL("/cross-site/bar.com/title2.html"));
+ NavigationHandleObserver observer(shell()->web_contents(), redirect_url);
+ TestNavigationThrottleInstaller installer(
+ shell()->web_contents(), NavigationThrottle::PROCEED,
+ NavigationThrottle::CANCEL, NavigationThrottle::PROCEED);
+
+ EXPECT_FALSE(NavigateToURL(shell(), redirect_url));
+
+ EXPECT_FALSE(observer.has_committed());
+ EXPECT_TRUE(observer.is_error());
+ EXPECT_TRUE(observer.was_redirected());
+ EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), start_url);
+ }
+
+ // A navigation without redirects should be successful.
+ {
+ GURL no_redirect_url(embedded_test_server()->GetURL("/title2.html"));
+ NavigationHandleObserver observer(shell()->web_contents(), no_redirect_url);
+ TestNavigationThrottleInstaller installer(
+ shell()->web_contents(), NavigationThrottle::PROCEED,
+ NavigationThrottle::CANCEL, NavigationThrottle::PROCEED);
+
+ EXPECT_TRUE(NavigateToURL(shell(), no_redirect_url));
+
+ EXPECT_TRUE(observer.has_committed());
+ EXPECT_FALSE(observer.is_error());
+ EXPECT_FALSE(observer.was_redirected());
+ EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), no_redirect_url);
+ }
+}
+
+// Ensure that a NavigationThrottle can cancel the navigation when the response
+// is received.
+IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest,
+ ThrottleCancelResponse) {
+ GURL start_url(embedded_test_server()->GetURL("/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), start_url));
+
+ GURL redirect_url(
+ embedded_test_server()->GetURL("/cross-site/bar.com/title2.html"));
+ NavigationHandleObserver observer(shell()->web_contents(), redirect_url);
+ TestNavigationThrottleInstaller installer(
+ shell()->web_contents(), NavigationThrottle::PROCEED,
+ NavigationThrottle::PROCEED, NavigationThrottle::CANCEL);
+
+ EXPECT_FALSE(NavigateToURL(shell(), redirect_url));
+
+ EXPECT_FALSE(observer.has_committed());
+ EXPECT_TRUE(observer.is_error());
+ // The navigation should have been redirected first, and then canceled when
+ // the response arrived.
+ EXPECT_TRUE(observer.was_redirected());
+ EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), start_url);
+}
+
+// Ensure that a NavigationThrottle can defer and resume the navigation at
+// navigation start, navigation redirect and response received.
+IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, ThrottleDefer) {
+ GURL start_url(embedded_test_server()->GetURL("/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), start_url));
+
+ GURL redirect_url(
+ embedded_test_server()->GetURL("/cross-site/bar.com/title2.html"));
+ TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
+ NavigationHandleObserver observer(shell()->web_contents(), redirect_url);
+ TestNavigationThrottleInstaller installer(
+ shell()->web_contents(), NavigationThrottle::DEFER,
+ NavigationThrottle::DEFER, NavigationThrottle::DEFER);
+
+ shell()->LoadURL(redirect_url);
+
+ // Wait for WillStartRequest.
+ installer.WaitForThrottleWillStart();
+ EXPECT_EQ(1, installer.will_start_called());
+ EXPECT_EQ(0, installer.will_redirect_called());
+ EXPECT_EQ(0, installer.will_process_called());
+ installer.navigation_throttle()->Resume();
+
+ // Wait for WillRedirectRequest.
+ installer.WaitForThrottleWillRedirect();
+ EXPECT_EQ(1, installer.will_start_called());
+ EXPECT_EQ(1, installer.will_redirect_called());
+ EXPECT_EQ(0, installer.will_process_called());
+ installer.navigation_throttle()->Resume();
+
+ // Wait for WillProcessResponse.
+ installer.WaitForThrottleWillProcess();
+ EXPECT_EQ(1, installer.will_start_called());
+ EXPECT_EQ(1, installer.will_redirect_called());
+ EXPECT_EQ(1, installer.will_process_called());
+ installer.navigation_throttle()->Resume();
+
+ // Wait for the end of the navigation.
+ navigation_observer.Wait();
+
+ EXPECT_TRUE(observer.has_committed());
+ EXPECT_TRUE(observer.was_redirected());
+ EXPECT_FALSE(observer.is_error());
+ EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(),
+ GURL(embedded_test_server()->GetURL("bar.com", "/title2.html")));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc b/chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc
index ee999cb31b0..65adc6b494e 100644
--- a/chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigation_handle_impl_unittest.cc
@@ -9,9 +9,10 @@
namespace content {
-// Test version of a NavigationThrottle. It will always return the same
+// Test version of a NavigationThrottle. It will always return the current
// NavigationThrottle::ThrottleCheckResult |result_|, It also monitors the
-// number of times WillStartRequest and WillRedirectRequest were called.
+// number of times WillStartRequest, WillRedirectRequest, and
+// WillProcessResponse were called.
class TestNavigationThrottle : public NavigationThrottle {
public:
TestNavigationThrottle(NavigationHandle* handle,
@@ -19,7 +20,8 @@ class TestNavigationThrottle : public NavigationThrottle {
: NavigationThrottle(handle),
result_(result),
will_start_calls_(0),
- will_redirect_calls_(0) {}
+ will_redirect_calls_(0),
+ will_process_response_calls_(0) {}
~TestNavigationThrottle() override {}
@@ -33,16 +35,25 @@ class TestNavigationThrottle : public NavigationThrottle {
return result_;
}
+ NavigationThrottle::ThrottleCheckResult WillProcessResponse() override {
+ ++will_process_response_calls_;
+ return result_;
+ }
+
int will_start_calls() const { return will_start_calls_; }
int will_redirect_calls() const { return will_redirect_calls_; }
+ int will_process_response_calls() const {
+ return will_process_response_calls_;
+ }
private:
// The result returned by the TestNavigationThrottle.
NavigationThrottle::ThrottleCheckResult result_;
- // The number of times WillStartRequest and WillRedirectRequest were called.
+ // The number of times each handler was called.
int will_start_calls_;
int will_redirect_calls_;
+ int will_process_response_calls_;
};
class NavigationHandleImplTest : public RenderViewHostImplTestHarness {
@@ -53,8 +64,9 @@ class NavigationHandleImplTest : public RenderViewHostImplTestHarness {
void SetUp() override {
RenderViewHostImplTestHarness::SetUp();
- test_handle_ = NavigationHandleImpl::Create(
- GURL(), main_test_rfh()->frame_tree_node(), base::TimeTicks::Now());
+ test_handle_ =
+ NavigationHandleImpl::Create(GURL(), main_test_rfh()->frame_tree_node(),
+ false, false, base::TimeTicks::Now(), 0);
}
void TearDown() override {
@@ -72,6 +84,10 @@ class NavigationHandleImplTest : public RenderViewHostImplTestHarness {
return test_handle_->state() == NavigationHandleImpl::DEFERRING_REDIRECT;
}
+ bool IsDeferringResponse() {
+ return test_handle_->state() == NavigationHandleImpl::DEFERRING_RESPONSE;
+ }
+
bool IsCanceling() {
return test_handle_->state() == NavigationHandleImpl::CANCELING;
}
@@ -108,6 +124,24 @@ class NavigationHandleImplTest : public RenderViewHostImplTestHarness {
base::Unretained(this)));
}
+ // Helper function to call WillProcessResponse on |handle|. If this function
+ // returns DEFER, |callback_result_| will be set to the actual result of the
+ // throttle checks when they are finished.
+ // TODO(clamy): this should also simulate that WillStartRequest was called if
+ // it has not been called before.
+ void SimulateWillProcessResponse() {
+ was_callback_called_ = false;
+ callback_result_ = NavigationThrottle::DEFER;
+
+ // It's safe to use base::Unretained since the NavigationHandle is owned by
+ // the NavigationHandleImplTest.
+ test_handle_->WillProcessResponse(
+ main_test_rfh(),
+ scoped_refptr<net::HttpResponseHeaders>(),
+ base::Bind(&NavigationHandleImplTest::UpdateThrottleCheckResult,
+ base::Unretained(this)));
+ }
+
// Returns the handle used in tests.
NavigationHandleImpl* test_handle() const { return test_handle_.get(); }
@@ -150,46 +184,80 @@ TEST_F(NavigationHandleImplTest, ResumeDeferred) {
CreateTestNavigationThrottle(NavigationThrottle::DEFER);
EXPECT_FALSE(IsDeferringStart());
EXPECT_FALSE(IsDeferringRedirect());
+ EXPECT_FALSE(IsDeferringResponse());
EXPECT_EQ(0, test_throttle->will_start_calls());
EXPECT_EQ(0, test_throttle->will_redirect_calls());
+ EXPECT_EQ(0, test_throttle->will_process_response_calls());
// Simulate WillStartRequest. The request should be deferred. The callback
// should not have been called.
SimulateWillStartRequest();
EXPECT_TRUE(IsDeferringStart());
EXPECT_FALSE(IsDeferringRedirect());
+ EXPECT_FALSE(IsDeferringResponse());
EXPECT_FALSE(was_callback_called());
EXPECT_EQ(1, test_throttle->will_start_calls());
EXPECT_EQ(0, test_throttle->will_redirect_calls());
+ EXPECT_EQ(0, test_throttle->will_process_response_calls());
// Resume the request. It should no longer be deferred and the callback
// should have been called.
test_handle()->Resume();
EXPECT_FALSE(IsDeferringStart());
EXPECT_FALSE(IsDeferringRedirect());
+ EXPECT_FALSE(IsDeferringResponse());
EXPECT_TRUE(was_callback_called());
EXPECT_EQ(NavigationThrottle::PROCEED, callback_result());
EXPECT_EQ(1, test_throttle->will_start_calls());
EXPECT_EQ(0, test_throttle->will_redirect_calls());
+ EXPECT_EQ(0, test_throttle->will_process_response_calls());
// Simulate WillRedirectRequest. The request should be deferred. The callback
// should not have been called.
SimulateWillRedirectRequest();
EXPECT_FALSE(IsDeferringStart());
EXPECT_TRUE(IsDeferringRedirect());
+ EXPECT_FALSE(IsDeferringResponse());
EXPECT_FALSE(was_callback_called());
EXPECT_EQ(1, test_throttle->will_start_calls());
EXPECT_EQ(1, test_throttle->will_redirect_calls());
+ EXPECT_EQ(0, test_throttle->will_process_response_calls());
// Resume the request. It should no longer be deferred and the callback
// should have been called.
test_handle()->Resume();
EXPECT_FALSE(IsDeferringStart());
EXPECT_FALSE(IsDeferringRedirect());
+ EXPECT_FALSE(IsDeferringResponse());
EXPECT_TRUE(was_callback_called());
EXPECT_EQ(NavigationThrottle::PROCEED, callback_result());
EXPECT_EQ(1, test_throttle->will_start_calls());
EXPECT_EQ(1, test_throttle->will_redirect_calls());
+ EXPECT_EQ(0, test_throttle->will_process_response_calls());
+
+ // Simulate WillProcessResponse. It will be deferred. The callback should not
+ // have been called.
+ SimulateWillProcessResponse();
+ EXPECT_FALSE(IsDeferringStart());
+ EXPECT_FALSE(IsDeferringRedirect());
+ EXPECT_TRUE(IsDeferringResponse());
+ EXPECT_FALSE(was_callback_called());
+ EXPECT_EQ(1, test_throttle->will_start_calls());
+ EXPECT_EQ(1, test_throttle->will_redirect_calls());
+ EXPECT_EQ(1, test_throttle->will_process_response_calls());
+
+ // Resume the request. It should no longer be deferred and the callback should
+ // have been called.
+ test_handle()->Resume();
+ EXPECT_FALSE(IsDeferringStart());
+ EXPECT_FALSE(IsDeferringRedirect());
+ EXPECT_FALSE(IsDeferringResponse());
+ EXPECT_TRUE(was_callback_called());
+ EXPECT_EQ(NavigationThrottle::PROCEED, callback_result());
+ EXPECT_EQ(1, test_throttle->will_start_calls());
+ EXPECT_EQ(1, test_throttle->will_redirect_calls());
+ EXPECT_EQ(1, test_throttle->will_process_response_calls());
+ EXPECT_TRUE(test_handle()->GetRenderFrameHost());
}
// Checks that a navigation deferred during WillStartRequest can be properly
@@ -201,6 +269,7 @@ TEST_F(NavigationHandleImplTest, CancelDeferredWillStart) {
EXPECT_FALSE(IsDeferringRedirect());
EXPECT_EQ(0, test_throttle->will_start_calls());
EXPECT_EQ(0, test_throttle->will_redirect_calls());
+ EXPECT_EQ(0, test_throttle->will_process_response_calls());
// Simulate WillStartRequest. The request should be deferred. The callback
// should not have been called.
@@ -210,6 +279,7 @@ TEST_F(NavigationHandleImplTest, CancelDeferredWillStart) {
EXPECT_FALSE(was_callback_called());
EXPECT_EQ(1, test_throttle->will_start_calls());
EXPECT_EQ(0, test_throttle->will_redirect_calls());
+ EXPECT_EQ(0, test_throttle->will_process_response_calls());
// Cancel the request. The callback should have been called.
test_handle()->CancelDeferredNavigation(
@@ -221,6 +291,7 @@ TEST_F(NavigationHandleImplTest, CancelDeferredWillStart) {
EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, callback_result());
EXPECT_EQ(1, test_throttle->will_start_calls());
EXPECT_EQ(0, test_throttle->will_redirect_calls());
+ EXPECT_EQ(0, test_throttle->will_process_response_calls());
}
// Checks that a navigation deferred during WillRedirectRequest can be properly
@@ -232,6 +303,7 @@ TEST_F(NavigationHandleImplTest, CancelDeferredWillRedirect) {
EXPECT_FALSE(IsDeferringRedirect());
EXPECT_EQ(0, test_throttle->will_start_calls());
EXPECT_EQ(0, test_throttle->will_redirect_calls());
+ EXPECT_EQ(0, test_throttle->will_process_response_calls());
// Simulate WillRedirectRequest. The request should be deferred. The callback
// should not have been called.
@@ -241,6 +313,7 @@ TEST_F(NavigationHandleImplTest, CancelDeferredWillRedirect) {
EXPECT_FALSE(was_callback_called());
EXPECT_EQ(0, test_throttle->will_start_calls());
EXPECT_EQ(1, test_throttle->will_redirect_calls());
+ EXPECT_EQ(0, test_throttle->will_process_response_calls());
// Cancel the request. The callback should have been called.
test_handle()->CancelDeferredNavigation(
@@ -252,6 +325,7 @@ TEST_F(NavigationHandleImplTest, CancelDeferredWillRedirect) {
EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, callback_result());
EXPECT_EQ(0, test_throttle->will_start_calls());
EXPECT_EQ(1, test_throttle->will_redirect_calls());
+ EXPECT_EQ(0, test_throttle->will_process_response_calls());
}
// Checks that a navigation deferred can be canceled and not ignored.
@@ -262,6 +336,7 @@ TEST_F(NavigationHandleImplTest, CancelDeferredNoIgnore) {
EXPECT_FALSE(IsDeferringRedirect());
EXPECT_EQ(0, test_throttle->will_start_calls());
EXPECT_EQ(0, test_throttle->will_redirect_calls());
+ EXPECT_EQ(0, test_throttle->will_process_response_calls());
// Simulate WillRedirectRequest. The request should be deferred. The callback
// should not have been called.
@@ -271,6 +346,7 @@ TEST_F(NavigationHandleImplTest, CancelDeferredNoIgnore) {
EXPECT_FALSE(was_callback_called());
EXPECT_EQ(1, test_throttle->will_start_calls());
EXPECT_EQ(0, test_throttle->will_redirect_calls());
+ EXPECT_EQ(0, test_throttle->will_process_response_calls());
// Cancel the request. The callback should have been called with CANCEL, and
// not CANCEL_AND_IGNORE.
@@ -282,6 +358,7 @@ TEST_F(NavigationHandleImplTest, CancelDeferredNoIgnore) {
EXPECT_EQ(NavigationThrottle::CANCEL, callback_result());
EXPECT_EQ(1, test_throttle->will_start_calls());
EXPECT_EQ(0, test_throttle->will_redirect_calls());
+ EXPECT_EQ(0, test_throttle->will_process_response_calls());
}
// Checks that a NavigationThrottle asking to defer followed by a
@@ -295,8 +372,10 @@ TEST_F(NavigationHandleImplTest, DeferThenProceed) {
EXPECT_FALSE(IsDeferringRedirect());
EXPECT_EQ(0, defer_throttle->will_start_calls());
EXPECT_EQ(0, defer_throttle->will_redirect_calls());
+ EXPECT_EQ(0, defer_throttle->will_process_response_calls());
EXPECT_EQ(0, proceed_throttle->will_start_calls());
EXPECT_EQ(0, proceed_throttle->will_redirect_calls());
+ EXPECT_EQ(0, proceed_throttle->will_process_response_calls());
// Simulate WillStartRequest. The request should be deferred. The callback
// should not have been called. The second throttle should not have been
@@ -307,6 +386,7 @@ TEST_F(NavigationHandleImplTest, DeferThenProceed) {
EXPECT_FALSE(was_callback_called());
EXPECT_EQ(1, defer_throttle->will_start_calls());
EXPECT_EQ(0, defer_throttle->will_redirect_calls());
+ EXPECT_EQ(0, defer_throttle->will_process_response_calls());
EXPECT_EQ(0, proceed_throttle->will_start_calls());
EXPECT_EQ(0, proceed_throttle->will_redirect_calls());
@@ -319,6 +399,7 @@ TEST_F(NavigationHandleImplTest, DeferThenProceed) {
EXPECT_EQ(NavigationThrottle::PROCEED, callback_result());
EXPECT_EQ(1, defer_throttle->will_start_calls());
EXPECT_EQ(0, defer_throttle->will_redirect_calls());
+ EXPECT_EQ(0, defer_throttle->will_process_response_calls());
EXPECT_EQ(1, proceed_throttle->will_start_calls());
EXPECT_EQ(0, proceed_throttle->will_redirect_calls());
@@ -331,6 +412,7 @@ TEST_F(NavigationHandleImplTest, DeferThenProceed) {
EXPECT_FALSE(was_callback_called());
EXPECT_EQ(1, defer_throttle->will_start_calls());
EXPECT_EQ(1, defer_throttle->will_redirect_calls());
+ EXPECT_EQ(0, defer_throttle->will_process_response_calls());
EXPECT_EQ(1, proceed_throttle->will_start_calls());
EXPECT_EQ(0, proceed_throttle->will_redirect_calls());
@@ -343,6 +425,7 @@ TEST_F(NavigationHandleImplTest, DeferThenProceed) {
EXPECT_EQ(NavigationThrottle::PROCEED, callback_result());
EXPECT_EQ(1, defer_throttle->will_start_calls());
EXPECT_EQ(1, defer_throttle->will_redirect_calls());
+ EXPECT_EQ(0, defer_throttle->will_process_response_calls());
EXPECT_EQ(1, proceed_throttle->will_start_calls());
EXPECT_EQ(1, proceed_throttle->will_redirect_calls());
}
@@ -358,6 +441,7 @@ TEST_F(NavigationHandleImplTest, DeferThenCancelWillStartRequest) {
EXPECT_FALSE(IsDeferringRedirect());
EXPECT_EQ(0, defer_throttle->will_start_calls());
EXPECT_EQ(0, defer_throttle->will_redirect_calls());
+ EXPECT_EQ(0, defer_throttle->will_process_response_calls());
EXPECT_EQ(0, cancel_throttle->will_start_calls());
EXPECT_EQ(0, cancel_throttle->will_redirect_calls());
@@ -370,6 +454,7 @@ TEST_F(NavigationHandleImplTest, DeferThenCancelWillStartRequest) {
EXPECT_FALSE(was_callback_called());
EXPECT_EQ(1, defer_throttle->will_start_calls());
EXPECT_EQ(0, defer_throttle->will_redirect_calls());
+ EXPECT_EQ(0, defer_throttle->will_process_response_calls());
EXPECT_EQ(0, cancel_throttle->will_start_calls());
EXPECT_EQ(0, cancel_throttle->will_redirect_calls());
@@ -383,6 +468,7 @@ TEST_F(NavigationHandleImplTest, DeferThenCancelWillStartRequest) {
EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, callback_result());
EXPECT_EQ(1, defer_throttle->will_start_calls());
EXPECT_EQ(0, defer_throttle->will_redirect_calls());
+ EXPECT_EQ(0, defer_throttle->will_process_response_calls());
EXPECT_EQ(1, cancel_throttle->will_start_calls());
EXPECT_EQ(0, cancel_throttle->will_redirect_calls());
}
@@ -398,6 +484,7 @@ TEST_F(NavigationHandleImplTest, DeferThenCancelWillRedirectRequest) {
EXPECT_FALSE(IsDeferringRedirect());
EXPECT_EQ(0, defer_throttle->will_start_calls());
EXPECT_EQ(0, defer_throttle->will_redirect_calls());
+ EXPECT_EQ(0, defer_throttle->will_process_response_calls());
EXPECT_EQ(0, cancel_throttle->will_start_calls());
EXPECT_EQ(0, cancel_throttle->will_redirect_calls());
@@ -410,6 +497,7 @@ TEST_F(NavigationHandleImplTest, DeferThenCancelWillRedirectRequest) {
EXPECT_FALSE(was_callback_called());
EXPECT_EQ(0, defer_throttle->will_start_calls());
EXPECT_EQ(1, defer_throttle->will_redirect_calls());
+ EXPECT_EQ(0, defer_throttle->will_process_response_calls());
EXPECT_EQ(0, cancel_throttle->will_start_calls());
EXPECT_EQ(0, cancel_throttle->will_redirect_calls());
@@ -423,6 +511,7 @@ TEST_F(NavigationHandleImplTest, DeferThenCancelWillRedirectRequest) {
EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, callback_result());
EXPECT_EQ(0, defer_throttle->will_start_calls());
EXPECT_EQ(1, defer_throttle->will_redirect_calls());
+ EXPECT_EQ(0, defer_throttle->will_process_response_calls());
EXPECT_EQ(0, cancel_throttle->will_start_calls());
EXPECT_EQ(1, cancel_throttle->will_redirect_calls());
}
@@ -440,6 +529,7 @@ TEST_F(NavigationHandleImplTest, CancelThenProceedWillStartRequest) {
EXPECT_FALSE(IsDeferringRedirect());
EXPECT_EQ(0, cancel_throttle->will_start_calls());
EXPECT_EQ(0, cancel_throttle->will_redirect_calls());
+ EXPECT_EQ(0, cancel_throttle->will_process_response_calls());
EXPECT_EQ(0, proceed_throttle->will_start_calls());
EXPECT_EQ(0, proceed_throttle->will_redirect_calls());
@@ -453,6 +543,7 @@ TEST_F(NavigationHandleImplTest, CancelThenProceedWillStartRequest) {
EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, callback_result());
EXPECT_EQ(1, cancel_throttle->will_start_calls());
EXPECT_EQ(0, cancel_throttle->will_redirect_calls());
+ EXPECT_EQ(0, cancel_throttle->will_process_response_calls());
EXPECT_EQ(0, proceed_throttle->will_start_calls());
EXPECT_EQ(0, proceed_throttle->will_redirect_calls());
}
@@ -470,6 +561,7 @@ TEST_F(NavigationHandleImplTest, CancelThenProceedWillRedirectRequest) {
EXPECT_FALSE(IsDeferringRedirect());
EXPECT_EQ(0, cancel_throttle->will_start_calls());
EXPECT_EQ(0, cancel_throttle->will_redirect_calls());
+ EXPECT_EQ(0, cancel_throttle->will_process_response_calls());
EXPECT_EQ(0, proceed_throttle->will_start_calls());
EXPECT_EQ(0, proceed_throttle->will_redirect_calls());
@@ -483,8 +575,74 @@ TEST_F(NavigationHandleImplTest, CancelThenProceedWillRedirectRequest) {
EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, callback_result());
EXPECT_EQ(0, cancel_throttle->will_start_calls());
EXPECT_EQ(1, cancel_throttle->will_redirect_calls());
+ EXPECT_EQ(0, cancel_throttle->will_process_response_calls());
+ EXPECT_EQ(0, proceed_throttle->will_start_calls());
+ EXPECT_EQ(0, proceed_throttle->will_redirect_calls());
+}
+
+// Checks that a NavigationThrottle asking to proceed followed by a
+// NavigationThrottle asking to cancel behave correctly in WillProcessResponse.
+// Both throttles will be called, and the request will be cancelled.
+TEST_F(NavigationHandleImplTest, ProceedThenCancelWillProcessResponse) {
+ TestNavigationThrottle* proceed_throttle =
+ CreateTestNavigationThrottle(NavigationThrottle::PROCEED);
+ TestNavigationThrottle* cancel_throttle =
+ CreateTestNavigationThrottle(NavigationThrottle::CANCEL_AND_IGNORE);
+ EXPECT_FALSE(IsDeferringStart());
+ EXPECT_FALSE(IsDeferringRedirect());
+ EXPECT_EQ(0, cancel_throttle->will_start_calls());
+ EXPECT_EQ(0, cancel_throttle->will_redirect_calls());
+ EXPECT_EQ(0, cancel_throttle->will_process_response_calls());
+ EXPECT_EQ(0, proceed_throttle->will_start_calls());
+ EXPECT_EQ(0, proceed_throttle->will_redirect_calls());
+ EXPECT_EQ(0, proceed_throttle->will_process_response_calls());
+
+ // Simulate WillRedirectRequest. The request should not be deferred. The
+ // callback should have been called.
+ SimulateWillProcessResponse();
+ EXPECT_FALSE(IsDeferringStart());
+ EXPECT_FALSE(IsDeferringRedirect());
+ EXPECT_TRUE(was_callback_called());
+ EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, callback_result());
+ EXPECT_EQ(0, cancel_throttle->will_start_calls());
+ EXPECT_EQ(0, cancel_throttle->will_redirect_calls());
+ EXPECT_EQ(1, cancel_throttle->will_process_response_calls());
+ EXPECT_EQ(0, proceed_throttle->will_start_calls());
+ EXPECT_EQ(0, proceed_throttle->will_redirect_calls());
+ EXPECT_EQ(1, proceed_throttle->will_process_response_calls());
+}
+
+// Checks that a NavigationThrottle asking to cancel followed by a
+// NavigationThrottle asking to proceed behave correctly in WillProcessResponse.
+// The navigation will be canceled directly, and the second throttle will not
+// be called.
+TEST_F(NavigationHandleImplTest, CancelThenProceedWillProcessResponse) {
+ TestNavigationThrottle* cancel_throttle =
+ CreateTestNavigationThrottle(NavigationThrottle::CANCEL_AND_IGNORE);
+ TestNavigationThrottle* proceed_throttle =
+ CreateTestNavigationThrottle(NavigationThrottle::PROCEED);
+ EXPECT_FALSE(IsDeferringStart());
+ EXPECT_FALSE(IsDeferringRedirect());
+ EXPECT_EQ(0, cancel_throttle->will_start_calls());
+ EXPECT_EQ(0, cancel_throttle->will_redirect_calls());
+ EXPECT_EQ(0, cancel_throttle->will_process_response_calls());
+ EXPECT_EQ(0, proceed_throttle->will_start_calls());
+ EXPECT_EQ(0, proceed_throttle->will_redirect_calls());
+
+ // Simulate WillRedirectRequest. The request should not be deferred. The
+ // callback should have been called. The second throttle should not have
+ // been notified.
+ SimulateWillProcessResponse();
+ EXPECT_FALSE(IsDeferringStart());
+ EXPECT_FALSE(IsDeferringRedirect());
+ EXPECT_TRUE(was_callback_called());
+ EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, callback_result());
+ EXPECT_EQ(0, cancel_throttle->will_start_calls());
+ EXPECT_EQ(0, cancel_throttle->will_redirect_calls());
+ EXPECT_EQ(1, cancel_throttle->will_process_response_calls());
EXPECT_EQ(0, proceed_throttle->will_start_calls());
EXPECT_EQ(0, proceed_throttle->will_redirect_calls());
+ EXPECT_EQ(0, proceed_throttle->will_process_response_calls());
}
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigation_request.cc b/chromium/content/browser/frame_host/navigation_request.cc
index 582a6803dfb..617fc26dc41 100644
--- a/chromium/content/browser/frame_host/navigation_request.cc
+++ b/chromium/content/browser/frame_host/navigation_request.cc
@@ -6,12 +6,14 @@
#include <utility>
+#include "content/browser/devtools/render_frame_devtools_agent_host.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/navigation_controller_impl.h"
#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/browser/frame_host/navigation_request_info.h"
#include "content/browser/frame_host/navigator.h"
+#include "content/browser/frame_host/navigator_impl.h"
#include "content/browser/loader/navigation_url_loader.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_navigation_handle.h"
@@ -41,7 +43,7 @@ int LoadFlagFromNavigationType(FrameMsg_Navigate_Type::Value navigation_type) {
case FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL:
load_flags |= net::LOAD_VALIDATE_CACHE;
break;
- case FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE:
+ case FrameMsg_Navigate_Type::RELOAD_BYPASSING_CACHE:
load_flags |= net::LOAD_BYPASS_CACHE;
break;
case FrameMsg_Navigate_Type::RESTORE:
@@ -67,19 +69,16 @@ scoped_ptr<NavigationRequest> NavigationRequest::CreateBrowserInitiated(
const FrameNavigationEntry& frame_entry,
const NavigationEntryImpl& entry,
FrameMsg_Navigate_Type::Value navigation_type,
+ LoFiState lofi_state,
bool is_same_document_history_load,
const base::TimeTicks& navigation_start,
NavigationControllerImpl* controller) {
- std::string method = entry.GetHasPostData() ? "POST" : "GET";
-
// Copy existing headers and add necessary headers that may not be present
// in the RequestNavigationParams.
net::HttpRequestHeaders headers;
headers.AddHeadersFromString(entry.extra_headers());
headers.SetHeaderIfMissing(net::HttpRequestHeaders::kUserAgent,
GetContentClient()->GetUserAgent());
- // TODO(clamy): match what blink is doing with accept headers.
- headers.SetHeaderIfMissing("Accept", "*/*");
// Fill POST data from the browser in the request body.
scoped_refptr<ResourceRequestBody> request_body;
@@ -93,9 +92,9 @@ scoped_ptr<NavigationRequest> NavigationRequest::CreateBrowserInitiated(
scoped_ptr<NavigationRequest> navigation_request(new NavigationRequest(
frame_tree_node, entry.ConstructCommonNavigationParams(
- dest_url, dest_referrer, navigation_type,
- LOFI_UNSPECIFIED, navigation_start),
- BeginNavigationParams(method, headers.ToString(),
+ dest_url, dest_referrer, navigation_type, lofi_state,
+ navigation_start),
+ BeginNavigationParams(headers.ToString(),
LoadFlagFromNavigationType(navigation_type),
false, // has_user_gestures
false, // skip_service_worker
@@ -125,7 +124,6 @@ scoped_ptr<NavigationRequest> NavigationRequest::CreateRendererInitiated(
// TODO(clamy): See if the navigation start time should be measured in the
// renderer and sent to the browser instead of being measured here.
// TODO(clamy): The pending history list offset should be properly set.
- // TODO(clamy): Set has_committed_real_load.
RequestNavigationParams request_params(
false, // is_overriding_user_agent
std::vector<GURL>(), // redirects
@@ -135,7 +133,7 @@ scoped_ptr<NavigationRequest> NavigationRequest::CreateRendererInitiated(
-1, // page_id
0, // nav_entry_id
false, // is_same_document_history_load
- false, // has_committed_real_load
+ frame_tree_node->has_committed_real_load(),
false, // intended_as_new_entry
-1, // pending_history_list_offset
current_history_list_offset, current_history_list_length,
@@ -164,7 +162,8 @@ NavigationRequest::NavigationRequest(
state_(NOT_STARTED),
restore_type_(NavigationEntryImpl::RESTORE_NONE),
is_view_source_(false),
- bindings_(NavigationEntryImpl::kInvalidBindings) {
+ bindings_(NavigationEntryImpl::kInvalidBindings),
+ associated_site_instance_type_(AssociatedSiteInstanceType::NONE) {
DCHECK(!browser_initiated || (entry != nullptr && frame_entry != nullptr));
if (browser_initiated) {
// TODO(clamy): use the FrameNavigationEntry for the source SiteInstance
@@ -193,7 +192,7 @@ NavigationRequest::NavigationRequest(
false : frame_tree_node->parent()->IsMainFrame();
info_.reset(new NavigationRequestInfo(
common_params, begin_params, first_party_for_cookies,
- frame_tree_node->frame_origin(), frame_tree_node->IsMainFrame(),
+ frame_tree_node->current_origin(), frame_tree_node->IsMainFrame(),
parent_is_main_frame, frame_tree_node->frame_tree_node_id(), body));
}
@@ -204,13 +203,16 @@ void NavigationRequest::BeginNavigation() {
DCHECK(!loader_);
DCHECK(state_ == NOT_STARTED || state_ == WAITING_FOR_RENDERER_RESPONSE);
state_ = STARTED;
+ RenderFrameDevToolsAgentHost::OnBeforeNavigation(navigation_handle_.get());
if (ShouldMakeNetworkRequestForURL(common_params_.url)) {
// It's safe to use base::Unretained because this NavigationRequest owns
// the NavigationHandle where the callback will be stored.
// TODO(clamy): pass the real value for |is_external_protocol| if needed.
+ // TODO(clamy): pass the method to the NavigationHandle instead of a
+ // boolean.
navigation_handle_->WillStartRequest(
- begin_params_.method == "POST",
+ common_params_.method == "POST",
Referrer::SanitizeForRequest(common_params_.url,
common_params_.referrer),
begin_params_.has_user_gesture, common_params_.transition, false,
@@ -222,13 +224,27 @@ void NavigationRequest::BeginNavigation() {
// There is no need to make a network request for this navigation, so commit
// it immediately.
state_ = RESPONSE_STARTED;
- frame_tree_node_->navigator()->CommitNavigation(
- frame_tree_node_, nullptr, scoped_ptr<StreamHandle>());
+
+ // Select an appropriate RenderFrameHost.
+ RenderFrameHostImpl* render_frame_host =
+ frame_tree_node_->render_manager()->GetFrameHostForNavigation(*this);
+ NavigatorImpl::CheckWebUIRendererDoesNotDisplayNormalURL(render_frame_host,
+ common_params_.url);
+
+ // Inform the NavigationHandle that the navigation will commit.
+ navigation_handle_->ReadyToCommitNavigation(render_frame_host);
+
+ CommitNavigation();
}
-void NavigationRequest::CreateNavigationHandle() {
+void NavigationRequest::CreateNavigationHandle(int pending_nav_entry_id) {
+ // TODO(nasko): Update the NavigationHandle creation to ensure that the
+ // proper values are specified for is_synchronous and is_srcdoc.
navigation_handle_ = NavigationHandleImpl::Create(
- common_params_.url, frame_tree_node_, common_params_.navigation_start);
+ common_params_.url, frame_tree_node_,
+ false, // is_synchronous
+ false, // is_srcdoc
+ common_params_.navigation_start, pending_nav_entry_id);
}
void NavigationRequest::TransferNavigationHandleOwnership(
@@ -240,7 +256,7 @@ void NavigationRequest::OnRequestRedirected(
const net::RedirectInfo& redirect_info,
const scoped_refptr<ResourceResponse>& response) {
common_params_.url = redirect_info.new_url;
- begin_params_.method = redirect_info.new_method;
+ common_params_.method = redirect_info.new_method;
common_params_.referrer.url = GURL(redirect_info.new_referrer);
// TODO(clamy): Have CSP + security upgrade checks here.
@@ -250,7 +266,7 @@ void NavigationRequest::OnRequestRedirected(
// NavigationHandle where the callback will be stored.
// TODO(clamy): pass the real value for |is_external_protocol| if needed.
navigation_handle_->WillRedirectRequest(
- common_params_.url, begin_params_.method == "POST",
+ common_params_.url, common_params_.method == "POST",
common_params_.referrer.url, false, response->head.headers,
base::Bind(&NavigationRequest::OnRedirectChecksComplete,
base::Unretained(this)));
@@ -262,9 +278,19 @@ void NavigationRequest::OnResponseStarted(
DCHECK(state_ == STARTED);
state_ = RESPONSE_STARTED;
+ // HTTP 204 (No Content) and HTTP 205 (Reset Content) responses should not
+ // commit; they leave the frame showing the previous page.
+ DCHECK(response);
+ if (response->head.headers.get() &&
+ (response->head.headers->response_code() == 204 ||
+ response->head.headers->response_code() == 205)) {
+ frame_tree_node_->ResetNavigationRequest(false);
+ return;
+ }
+
// Update the service worker params of the request params.
request_params_.should_create_service_worker =
- (frame_tree_node_->current_replication_state().sandbox_flags &
+ (frame_tree_node_->pending_sandbox_flags() &
blink::WebSandboxFlags::Origin) != blink::WebSandboxFlags::Origin;
if (navigation_handle_->service_worker_handle()) {
request_params_.service_worker_provider_id =
@@ -272,8 +298,38 @@ void NavigationRequest::OnResponseStarted(
->service_worker_provider_host_id();
}
- frame_tree_node_->navigator()->CommitNavigation(
- frame_tree_node_, response.get(), std::move(body));
+ // Update the lofi state of the request.
+ if (response->head.is_using_lofi)
+ common_params_.lofi_state = LOFI_ON;
+ else
+ common_params_.lofi_state = LOFI_OFF;
+
+ // Select an appropriate renderer to commit the navigation.
+ RenderFrameHostImpl* render_frame_host =
+ frame_tree_node_->render_manager()->GetFrameHostForNavigation(*this);
+ NavigatorImpl::CheckWebUIRendererDoesNotDisplayNormalURL(render_frame_host,
+ common_params_.url);
+
+ // For renderer-initiated navigations that are set to commit in a different
+ // renderer, allow the embedder to cancel the transfer.
+ if (!browser_initiated_ &&
+ render_frame_host != frame_tree_node_->current_frame_host() &&
+ !frame_tree_node_->navigator()
+ ->GetDelegate()
+ ->ShouldTransferNavigation()) {
+ frame_tree_node_->ResetNavigationRequest(false);
+ return;
+ }
+
+ // Store the response and the StreamHandle until checks have been processed.
+ response_ = response;
+ body_ = std::move(body);
+
+ // Check if the navigation should be allowed to proceed.
+ navigation_handle_->WillProcessResponse(
+ render_frame_host, response->head.headers.get(),
+ base::Bind(&NavigationRequest::OnWillProcessResponseChecksComplete,
+ base::Unretained(this)));
}
void NavigationRequest::OnRequestFailed(bool has_stale_copy_in_cache,
@@ -327,14 +383,57 @@ void NavigationRequest::OnRedirectChecksComplete(
}
loader_->FollowRedirect();
- navigation_handle_->DidRedirectNavigation(common_params_.url);
+}
+
+void NavigationRequest::OnWillProcessResponseChecksComplete(
+ NavigationThrottle::ThrottleCheckResult result) {
+ CHECK(result != NavigationThrottle::DEFER);
+
+ // Abort the request if needed. This will destroy the NavigationRequest.
+ if (result == NavigationThrottle::CANCEL_AND_IGNORE ||
+ result == NavigationThrottle::CANCEL) {
+ // TODO(clamy): distinguish between CANCEL and CANCEL_AND_IGNORE.
+ frame_tree_node_->ResetNavigationRequest(false);
+ return;
+ }
+
+ // Have the processing of the response resume in the network stack.
+ loader_->ProceedWithResponse();
+
+ CommitNavigation();
+
+ // DO NOT ADD CODE after this. The previous call to CommitNavigation caused
+ // the destruction of the NavigationRequest.
+}
+
+void NavigationRequest::CommitNavigation() {
+ DCHECK(response_ || !ShouldMakeNetworkRequestForURL(common_params_.url));
+
+ // Retrieve the RenderFrameHost that needs to commit the navigation.
+ RenderFrameHostImpl* render_frame_host =
+ navigation_handle_->GetRenderFrameHost();
+ DCHECK(render_frame_host ==
+ frame_tree_node_->render_manager()->current_frame_host() ||
+ render_frame_host ==
+ frame_tree_node_->render_manager()->speculative_frame_host());
+
+ TransferNavigationHandleOwnership(render_frame_host);
+ render_frame_host->CommitNavigation(response_.get(), std::move(body_),
+ common_params_, request_params_,
+ is_view_source_);
+
+ // When navigating to a Javascript url, the NavigationRequest is not stored
+ // in the FrameTreeNode. Therefore do not reset it, as this could cancel an
+ // existing pending navigation.
+ if (!common_params_.url.SchemeIs(url::kJavaScriptScheme))
+ frame_tree_node_->ResetNavigationRequest(true);
}
void NavigationRequest::InitializeServiceWorkerHandleIfNeeded() {
// Only initialize the ServiceWorkerNavigationHandle if it can be created for
// this frame.
bool can_create_service_worker =
- (frame_tree_node_->current_replication_state().sandbox_flags &
+ (frame_tree_node_->pending_sandbox_flags() &
blink::WebSandboxFlags::Origin) != blink::WebSandboxFlags::Origin;
if (!can_create_service_worker)
return;
diff --git a/chromium/content/browser/frame_host/navigation_request.h b/chromium/content/browser/frame_host/navigation_request.h
index fb418c54d11..da8f9d7b81e 100644
--- a/chromium/content/browser/frame_host/navigation_request.h
+++ b/chromium/content/browser/frame_host/navigation_request.h
@@ -57,6 +57,16 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
FAILED,
};
+ // The SiteInstance currently associated with the navigation. Note that the
+ // final value will only be known when the response is received, or the
+ // navigation fails, as server redirects can modify the SiteInstance to use
+ // for the navigation.
+ enum class AssociatedSiteInstanceType {
+ NONE = 0,
+ CURRENT,
+ SPECULATIVE,
+ };
+
// Creates a request for a browser-intiated navigation.
static scoped_ptr<NavigationRequest> CreateBrowserInitiated(
FrameTreeNode* frame_tree_node,
@@ -65,6 +75,7 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
const FrameNavigationEntry& frame_entry,
const NavigationEntryImpl& entry,
FrameMsg_Navigate_Type::Value navigation_type,
+ LoFiState lofi_state,
bool is_same_document_history_load,
const base::TimeTicks& navigation_start,
NavigationControllerImpl* controller);
@@ -99,6 +110,8 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
NavigationState state() const { return state_; }
+ FrameTreeNode* frame_tree_node() const { return frame_tree_node_; }
+
SiteInstanceImpl* source_site_instance() const {
return source_site_instance_.get();
}
@@ -122,13 +135,20 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
state_ = WAITING_FOR_RENDERER_RESPONSE;
}
+ AssociatedSiteInstanceType associated_site_instance_type() const {
+ return associated_site_instance_type_;
+ }
+ void set_associated_site_instance_type(AssociatedSiteInstanceType type) {
+ associated_site_instance_type_ = type;
+ }
+
NavigationHandleImpl* navigation_handle() const {
return navigation_handle_.get();
}
// Creates a NavigationHandle. This should be called after any previous
// NavigationRequest for the FrameTreeNode has been destroyed.
- void CreateNavigationHandle();
+ void CreateNavigationHandle(int pending_nav_entry_id);
// Transfers the ownership of the NavigationHandle to |render_frame_host|.
// This should be called when the navigation is ready to commit, because the
@@ -161,6 +181,12 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
// NavigationHandle.
void OnStartChecksComplete(NavigationThrottle::ThrottleCheckResult result);
void OnRedirectChecksComplete(NavigationThrottle::ThrottleCheckResult result);
+ void OnWillProcessResponseChecksComplete(
+ NavigationThrottle::ThrottleCheckResult result);
+
+ // Have a RenderFrameHost commit the navigation. The NavigationRequest will
+ // be destroyed after this call.
+ void CommitNavigation();
// Called when the navigation is about to be sent to the IO thread.
void InitializeServiceWorkerHandleIfNeeded();
@@ -199,8 +225,16 @@ class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate {
bool is_view_source_;
int bindings_;
+ // The type of SiteInstance associated with this navigation.
+ AssociatedSiteInstanceType associated_site_instance_type_;
+
scoped_ptr<NavigationHandleImpl> navigation_handle_;
+ // Holds the ResourceResponse and the StreamHandle for the navigation while
+ // the WillProcessResponse checks are performed by the NavigationHandle.
+ scoped_refptr<ResourceResponse> response_;
+ scoped_ptr<StreamHandle> body_;
+
DISALLOW_COPY_AND_ASSIGN(NavigationRequest);
};
diff --git a/chromium/content/browser/frame_host/navigator.cc b/chromium/content/browser/frame_host/navigator.cc
index 333d1033374..ac6c248cae6 100644
--- a/chromium/content/browser/frame_host/navigator.cc
+++ b/chromium/content/browser/frame_host/navigator.cc
@@ -42,9 +42,4 @@ void Navigator::OnBeginNavigation(
scoped_refptr<ResourceRequestBody> body) {
}
-void Navigator::CommitNavigation(FrameTreeNode* frame_tree_node,
- ResourceResponse* response,
- scoped_ptr<StreamHandle> body) {
-}
-
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigator.h b/chromium/content/browser/frame_host/navigator.h
index b5e0e84a538..ce1c97dec99 100644
--- a/chromium/content/browser/frame_host/navigator.h
+++ b/chromium/content/browser/frame_host/navigator.h
@@ -124,6 +124,7 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
virtual void RequestTransferURL(
RenderFrameHostImpl* render_frame_host,
const GURL& url,
+ SiteInstance* source_site_instance,
const std::vector<GURL>& redirect_chain,
const Referrer& referrer,
ui::PageTransition page_transition,
@@ -148,13 +149,6 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
scoped_refptr<ResourceRequestBody> body);
// PlzNavigate
- // Signal |render_frame_host| that a navigation is ready to commit (the
- // response to the navigation request has been received).
- virtual void CommitNavigation(FrameTreeNode* frame_tree_node,
- ResourceResponse* response,
- scoped_ptr<StreamHandle> body);
-
- // PlzNavigate
// Called when a NavigationRequest for |frame_tree_node| failed. An
// appropriate RenderFrameHost should be selected and asked to show an error
// page. |has_stale_copy_in_cache| is true if there is a stale copy of the
diff --git a/chromium/content/browser/frame_host/navigator_impl.cc b/chromium/content/browser/frame_host/navigator_impl.cc
index 2acedd76a19..35ee34045fe 100644
--- a/chromium/content/browser/frame_host/navigator_impl.cc
+++ b/chromium/content/browser/frame_host/navigator_impl.cc
@@ -42,6 +42,7 @@
#include "content/public/common/resource_response.h"
#include "content/public/common/url_constants.h"
#include "net/base/net_errors.h"
+#include "url/url_constants.h"
namespace content {
@@ -53,9 +54,9 @@ FrameMsg_Navigate_Type::Value GetNavigationType(
switch (reload_type) {
case NavigationControllerImpl::RELOAD:
return FrameMsg_Navigate_Type::RELOAD;
- case NavigationControllerImpl::RELOAD_IGNORING_CACHE:
+ case NavigationControllerImpl::RELOAD_BYPASSING_CACHE:
case NavigationControllerImpl::RELOAD_DISABLE_LOFI_MODE:
- return FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE;
+ return FrameMsg_Navigate_Type::RELOAD_BYPASSING_CACHE;
case NavigationControllerImpl::RELOAD_ORIGINAL_REQUEST_URL:
return FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL;
case NavigationControllerImpl::NO_RELOAD:
@@ -103,6 +104,27 @@ NavigatorImpl::NavigatorImpl(
NavigatorImpl::~NavigatorImpl() {}
+// static
+void NavigatorImpl::CheckWebUIRendererDoesNotDisplayNormalURL(
+ RenderFrameHostImpl* render_frame_host,
+ const GURL& url) {
+ int enabled_bindings =
+ render_frame_host->render_view_host()->GetEnabledBindings();
+ bool is_allowed_in_web_ui_renderer =
+ WebUIControllerFactoryRegistry::GetInstance()->IsURLAcceptableForWebUI(
+ render_frame_host->frame_tree_node()
+ ->navigator()
+ ->GetController()
+ ->GetBrowserContext(),
+ url);
+ if ((enabled_bindings & BINDINGS_POLICY_WEB_UI) &&
+ !is_allowed_in_web_ui_renderer) {
+ // Log the URL to help us diagnose any future failures of this CHECK.
+ GetContentClient()->SetActiveURL(url);
+ CHECK(0);
+ }
+}
+
NavigatorDelegate* NavigatorImpl::GetDelegate() {
return delegate_;
}
@@ -124,7 +146,8 @@ void NavigatorImpl::DidStartProvisionalLoad(
if (is_main_frame && !is_error_page) {
DidStartMainFrameNavigation(validated_url,
- render_frame_host->GetSiteInstance());
+ render_frame_host->GetSiteInstance(),
+ render_frame_host->navigation_handle());
}
if (delegate_) {
@@ -151,8 +174,12 @@ void NavigatorImpl::DidStartProvisionalLoad(
render_frame_host->SetNavigationHandle(scoped_ptr<NavigationHandleImpl>());
}
+ NavigationEntry* pending_entry = controller_->GetPendingEntry();
render_frame_host->SetNavigationHandle(NavigationHandleImpl::Create(
- validated_url, render_frame_host->frame_tree_node(), navigation_start));
+ validated_url, render_frame_host->frame_tree_node(),
+ false, // is_synchronous
+ is_iframe_srcdoc, // is_srcdoc
+ navigation_start, pending_entry ? pending_entry->GetUniqueID() : 0));
}
void NavigatorImpl::DidFailProvisionalLoadWithError(
@@ -192,37 +219,14 @@ void NavigatorImpl::DidFailProvisionalLoadWithError(
// We used to cancel the pending renderer here for cross-site downloads.
// However, it's not safe to do that because the download logic repeatedly
- // looks for this WebContents based on a render ID. Instead, we just
+ // looks for this WebContents based on a render ID. Instead, we just
// leave the pending renderer around until the next navigation event
// (Navigate, DidNavigate, etc), which will clean it up properly.
//
// TODO(creis): Find a way to cancel any pending RFH here.
}
- // We usually clear the pending entry when it fails, so that an arbitrary URL
- // isn't left visible above a committed page. This must be enforced when
- // the pending entry isn't visible (e.g., renderer-initiated navigations) to
- // prevent URL spoofs for in-page navigations that don't go through
- // DidStartProvisionalLoadForFrame.
- //
- // However, we do preserve the pending entry in some cases, such as on the
- // initial navigation of an unmodified blank tab. We also allow the delegate
- // to say when it's safe to leave aborted URLs in the omnibox, to let the user
- // edit the URL and try again. This may be useful in cases that the committed
- // page cannot be attacker-controlled. In these cases, we still allow the
- // view to clear the pending entry and typed URL if the user requests
- // (e.g., hitting Escape with focus in the address bar).
- //
- // Note: don't touch the transient entry, since an interstitial may exist.
- bool should_preserve_entry = controller_->IsUnmodifiedBlankTab() ||
- delegate_->ShouldPreserveAbortedURLs();
- if (controller_->GetPendingEntry() != controller_->GetVisibleEntry() ||
- !should_preserve_entry) {
- controller_->DiscardPendingEntry(true);
-
- // Also force the UI to refresh.
- controller_->delegate()->NotifyNavigationStateChanged(INVALIDATE_TYPE_URL);
- }
+ DiscardPendingEntryOnFailureIfNeeded(render_frame_host->navigation_handle());
if (delegate_)
delegate_->DidFailProvisionalLoadWithError(render_frame_host, params);
@@ -272,8 +276,8 @@ bool NavigatorImpl::NavigateToEntry(
// The renderer will reject IPC messages with URLs longer than
// this limit, so don't attempt to navigate with a longer URL.
- if (dest_url.spec().size() > kMaxURLChars) {
- LOG(WARNING) << "Refusing to load URL as it exceeds " << kMaxURLChars
+ if (dest_url.spec().size() > url::kMaxURLChars) {
+ LOG(WARNING) << "Refusing to load URL as it exceeds " << url::kMaxURLChars
<< " characters.";
return false;
}
@@ -287,13 +291,27 @@ bool NavigatorImpl::NavigateToEntry(
"navigation", "NavigationTiming navigationStart",
TRACE_EVENT_SCOPE_GLOBAL, navigation_start.ToInternalValue());
+ // Determine if LoFi should be used for the navigation.
+ LoFiState lofi_state = LOFI_UNSPECIFIED;
+ if (!frame_tree_node->IsMainFrame()) {
+ // For subframes, use the state of the top-level frame.
+ lofi_state = frame_tree_node->frame_tree()
+ ->root()
+ ->current_frame_host()
+ ->last_navigation_lofi_state();
+ } else if (reload_type ==
+ NavigationController::ReloadType::RELOAD_DISABLE_LOFI_MODE) {
+ // Disable LoFi when asked for it explicitly.
+ lofi_state = LOFI_OFF;
+ }
+
// PlzNavigate: the RenderFrameHosts are no longer asked to navigate.
if (IsBrowserSideNavigationEnabled()) {
navigation_data_.reset(new NavigationMetricsData(navigation_start, dest_url,
entry.restore_type()));
RequestNavigation(frame_tree_node, dest_url, dest_referrer, frame_entry,
- entry, reload_type, is_same_document_history_load,
- navigation_start);
+ entry, reload_type, lofi_state,
+ is_same_document_history_load, navigation_start);
if (frame_tree_node->IsMainFrame() &&
frame_tree_node->navigation_request()) {
// TODO(carlosk): extend these traces to support subframes and
@@ -315,61 +333,63 @@ bool NavigatorImpl::NavigateToEntry(
"FrameTreeNode id", frame_tree_node->frame_tree_node_id());
}
- // Notify observers about navigation if this is for the pending entry.
- if (delegate_ && is_pending_entry)
- delegate_->DidStartNavigationToPendingEntry(dest_url, reload_type);
-
- return true;
- }
-
- RenderFrameHostImpl* dest_render_frame_host =
- frame_tree_node->render_manager()->Navigate(dest_url, frame_entry, entry);
- if (!dest_render_frame_host)
- return false; // Unable to create the desired RenderFrameHost.
-
- // Make sure no code called via RFHM::Navigate clears the pending entry.
- if (is_pending_entry)
- CHECK_EQ(controller_->GetPendingEntry(), &entry);
-
- // For security, we should never send non-Web-UI URLs to a Web UI renderer.
- // Double check that here.
- CheckWebUIRendererDoesNotDisplayNormalURL(dest_render_frame_host, dest_url);
-
- // Navigate in the desired RenderFrameHost.
- // We can skip this step in the rare case that this is a transfer navigation
- // which began in the chosen RenderFrameHost, since the request has already
- // been issued. In that case, simply resume the response.
- bool is_transfer_to_same =
- entry.transferred_global_request_id().child_id != -1 &&
- entry.transferred_global_request_id().child_id ==
- dest_render_frame_host->GetProcess()->GetID();
- if (!is_transfer_to_same) {
- navigation_data_.reset(new NavigationMetricsData(navigation_start, dest_url,
- entry.restore_type()));
- // Create the navigation parameters.
- FrameMsg_Navigate_Type::Value navigation_type =
- GetNavigationType(controller_->GetBrowserContext(), entry, reload_type);
- LoFiState lofi_state =
- (reload_type ==
- NavigationController::ReloadType::RELOAD_DISABLE_LOFI_MODE
- ? LOFI_OFF
- : LOFI_UNSPECIFIED);
- dest_render_frame_host->Navigate(
- entry.ConstructCommonNavigationParams(dest_url, dest_referrer,
- navigation_type, lofi_state,
- navigation_start),
- entry.ConstructStartNavigationParams(),
- entry.ConstructRequestNavigationParams(
- frame_entry, is_same_document_history_load,
- frame_tree_node->has_committed_real_load(),
- controller_->GetPendingEntryIndex() == -1,
- controller_->GetIndexOfEntry(&entry),
- controller_->GetLastCommittedEntryIndex(),
- controller_->GetEntryCount()));
} else {
- // No need to navigate again. Just resume the deferred request.
- dest_render_frame_host->GetProcess()->ResumeDeferredNavigation(
- entry.transferred_global_request_id());
+ RenderFrameHostImpl* dest_render_frame_host =
+ frame_tree_node->render_manager()->Navigate(dest_url, frame_entry,
+ entry);
+ if (!dest_render_frame_host)
+ return false; // Unable to create the desired RenderFrameHost.
+
+ // Make sure no code called via RFHM::Navigate clears the pending entry.
+ if (is_pending_entry)
+ CHECK_EQ(controller_->GetPendingEntry(), &entry);
+
+ // For security, we should never send non-Web-UI URLs to a Web UI renderer.
+ // Double check that here.
+ CheckWebUIRendererDoesNotDisplayNormalURL(dest_render_frame_host, dest_url);
+
+ // In the case of a transfer navigation, set the destination
+ // RenderFrameHost as loading. This ensures that the RenderFrameHost gets
+ // in a loading state without emitting a spurious DidStartLoading
+ // notification at the FrameTreeNode level (since the FrameTreeNode was
+ // already loading). Note that this works both for a transfer to a
+ // different RenderFrameHost and in the rare case where the navigation is
+ // transferred back to the same RenderFrameHost.
+ bool is_transfer = entry.transferred_global_request_id().child_id != -1;
+ if (is_transfer)
+ dest_render_frame_host->set_is_loading(true);
+
+ // Navigate in the desired RenderFrameHost.
+ // We can skip this step in the rare case that this is a transfer navigation
+ // which began in the chosen RenderFrameHost, since the request has already
+ // been issued. In that case, simply resume the response.
+ bool is_transfer_to_same =
+ is_transfer &&
+ entry.transferred_global_request_id().child_id ==
+ dest_render_frame_host->GetProcess()->GetID();
+ if (!is_transfer_to_same) {
+ navigation_data_.reset(new NavigationMetricsData(
+ navigation_start, dest_url, entry.restore_type()));
+ // Create the navigation parameters.
+ FrameMsg_Navigate_Type::Value navigation_type = GetNavigationType(
+ controller_->GetBrowserContext(), entry, reload_type);
+ dest_render_frame_host->Navigate(
+ entry.ConstructCommonNavigationParams(dest_url, dest_referrer,
+ navigation_type, lofi_state,
+ navigation_start),
+ entry.ConstructStartNavigationParams(),
+ entry.ConstructRequestNavigationParams(
+ frame_entry, is_same_document_history_load,
+ frame_tree_node->has_committed_real_load(),
+ controller_->GetPendingEntryIndex() == -1,
+ controller_->GetIndexOfEntry(&entry),
+ controller_->GetLastCommittedEntryIndex(),
+ controller_->GetEntryCount()));
+ } else {
+ // No need to navigate again. Just resume the deferred request.
+ dest_render_frame_host->GetProcess()->ResumeDeferredNavigation(
+ entry.transferred_global_request_id());
+ }
}
// Make sure no code called via RFH::Navigate clears the pending entry.
@@ -436,6 +456,11 @@ void NavigatorImpl::DidNavigate(
FrameTree* frame_tree = render_frame_host->frame_tree_node()->frame_tree();
bool oopifs_possible = SiteIsolationPolicy::AreCrossProcessFramesPossible();
+ bool has_embedded_credentials =
+ params.url.has_username() || params.url.has_password();
+ UMA_HISTOGRAM_BOOLEAN("Navigation.FrameHasEmbeddedCredentials",
+ has_embedded_credentials);
+
bool is_navigation_within_page = controller_->IsURLInPageNavigation(
params.url, params.was_within_same_page, render_frame_host);
@@ -470,6 +495,9 @@ void NavigatorImpl::DidNavigate(
// Run tasks that must execute just before the commit.
delegate_->DidNavigateMainFramePreCommit(is_navigation_within_page);
+
+ UMA_HISTOGRAM_BOOLEAN("Navigation.MainFrameHasEmbeddedCredentials",
+ has_embedded_credentials);
}
if (!oopifs_possible)
@@ -483,7 +511,8 @@ void NavigatorImpl::DidNavigate(
// origin because it creates a RenderFrameProxy that needs this to initialize
// its security context. This origin will also be sent to RenderFrameProxies
// created via ViewMsg_New and FrameMsg_NewFrameProxy.
- render_frame_host->frame_tree_node()->SetCurrentOrigin(params.origin);
+ render_frame_host->frame_tree_node()->SetCurrentOrigin(
+ params.origin, params.has_potentially_trustworthy_unique_origin);
render_frame_host->frame_tree_node()->SetEnforceStrictMixedContentChecking(
params.should_enforce_strict_mixed_content_checking);
@@ -524,9 +553,21 @@ void NavigatorImpl::DidNavigate(
bool did_navigate = controller_->RendererDidNavigate(render_frame_host,
params, &details);
- // Keep track of each frame's URL in its FrameTreeNode.
+ // Keep track of each frame's URL in its FrameTreeNode, whether it's for a net
+ // error or not.
+ // TODO(creis): Move the last committed URL to RenderFrameHostImpl.
render_frame_host->frame_tree_node()->SetCurrentURL(params.url);
+ // Separately, update the frame's last successful URL except for net error
+ // pages, since those do not end up in the correct process after transfers
+ // (see https://crbug.com/560511). Instead, the next cross-process navigation
+ // or transfer should decide whether to swap as if the net error had not
+ // occurred.
+ // TODO(creis): Remove this block and always set the URL once transfers handle
+ // network errors or PlzNavigate is enabled. See https://crbug.com/588314.
+ if (!params.url_is_unreachable)
+ render_frame_host->set_last_successful_url(params.url);
+
if (did_navigate && render_frame_host->frame_tree_node()->IsMainFrame() &&
IsBrowserSideNavigationEnabled()) {
TRACE_EVENT_ASYNC_END0("navigation", "Navigation timeToCommit",
@@ -554,7 +595,7 @@ void NavigatorImpl::DidNavigate(
params.url,
transition_type);
render_frame_host->navigation_handle()->DidCommitNavigation(
- is_navigation_within_page, render_frame_host);
+ params, is_navigation_within_page, render_frame_host);
render_frame_host->SetNavigationHandle(nullptr);
}
@@ -604,17 +645,9 @@ void NavigatorImpl::RequestOpenURL(RenderFrameHostImpl* render_frame_host,
DCHECK(!render_frame_host->GetParent() ||
SiteIsolationPolicy::AreCrossProcessFramesPossible());
- // If this came from a swapped out RenderFrameHost, we only allow the request
- // if we are still in the same BrowsingInstance.
- // TODO(creis): Move this to RenderFrameProxyHost::OpenURL.
SiteInstance* current_site_instance = render_frame_host->frame_tree_node()
->current_frame_host()
->GetSiteInstance();
- if (render_frame_host->is_swapped_out() &&
- !render_frame_host->GetSiteInstance()->IsRelatedSiteInstance(
- current_site_instance)) {
- return;
- }
// TODO(creis): Pass the redirect_chain into this method to support client
// redirects. http://crbug.com/311721.
@@ -672,6 +705,7 @@ void NavigatorImpl::RequestOpenURL(RenderFrameHostImpl* render_frame_host,
void NavigatorImpl::RequestTransferURL(
RenderFrameHostImpl* render_frame_host,
const GURL& url,
+ SiteInstance* source_site_instance,
const std::vector<GURL>& redirect_chain,
const Referrer& referrer,
ui::PageTransition page_transition,
@@ -716,9 +750,8 @@ void NavigatorImpl::RequestTransferURL(
}
NavigationController::LoadURLParams load_url_params(dest_url);
- // The source_site_instance only matters for navigations via RenderFrameProxy,
- // which go through RequestOpenURL.
- load_url_params.source_site_instance = nullptr;
+ // The source_site_instance may matter for navigations via RenderFrameProxy.
+ load_url_params.source_site_instance = source_site_instance;
load_url_params.transition_type = page_transition;
load_url_params.frame_tree_node_id = node->frame_tree_node_id();
load_url_params.referrer = referrer_to_use;
@@ -775,6 +808,10 @@ void NavigatorImpl::OnBeginNavigation(
(ongoing_navigation_request->browser_initiated() ||
ongoing_navigation_request->begin_params().has_user_gesture) &&
!begin_params.has_user_gesture) {
+ RenderFrameHost* current_frame_host =
+ frame_tree_node->render_manager()->current_frame_host();
+ current_frame_host->Send(
+ new FrameMsg_Stop(current_frame_host->GetRoutingID()));
return;
}
@@ -786,8 +823,6 @@ void NavigatorImpl::OnBeginNavigation(
controller_->GetLastCommittedEntryIndex(),
controller_->GetEntryCount()));
NavigationRequest* navigation_request = frame_tree_node->navigation_request();
- navigation_request->CreateNavigationHandle();
-
if (frame_tree_node->IsMainFrame()) {
// Renderer-initiated main-frame navigations that need to swap processes
// will go to the browser via a OpenURL call, and then be handled by the
@@ -798,62 +833,20 @@ void NavigatorImpl::OnBeginNavigation(
// RenderFrameHost.
DidStartMainFrameNavigation(
common_params.url,
- frame_tree_node->current_frame_host()->GetSiteInstance());
+ frame_tree_node->current_frame_host()->GetSiteInstance(), nullptr);
navigation_data_.reset();
}
+ // For main frames, NavigationHandle will be created after the call to
+ // |DidStartMainFrameNavigation|, so it receives the most up to date pending
+ // entry from the NavigationController.
+ NavigationEntry* pending_entry = controller_->GetPendingEntry();
+ navigation_request->CreateNavigationHandle(
+ pending_entry ? pending_entry->GetUniqueID() : 0);
navigation_request->BeginNavigation();
}
// PlzNavigate
-void NavigatorImpl::CommitNavigation(FrameTreeNode* frame_tree_node,
- ResourceResponse* response,
- scoped_ptr<StreamHandle> body) {
- CHECK(IsBrowserSideNavigationEnabled());
-
- NavigationRequest* navigation_request = frame_tree_node->navigation_request();
- DCHECK(navigation_request);
- DCHECK(response ||
- !ShouldMakeNetworkRequestForURL(
- navigation_request->common_params().url));
-
- // HTTP 204 (No Content) and HTTP 205 (Reset Content) responses should not
- // commit; they leave the frame showing the previous page.
- if (response && response->head.headers.get() &&
- (response->head.headers->response_code() == 204 ||
- response->head.headers->response_code() == 205)) {
- CancelNavigation(frame_tree_node);
- return;
- }
-
- // Select an appropriate renderer to commit the navigation.
- RenderFrameHostImpl* render_frame_host =
- frame_tree_node->render_manager()->GetFrameHostForNavigation(
- *navigation_request);
-
- // The renderer can exit view source mode when any error or cancellation
- // happen. When reusing the same renderer, overwrite to recover the mode.
- if (navigation_request->is_view_source() &&
- render_frame_host ==
- frame_tree_node->render_manager()->current_frame_host()) {
- DCHECK(!render_frame_host->GetParent());
- render_frame_host->render_view_host()->Send(
- new ViewMsg_EnableViewSourceMode(
- render_frame_host->render_view_host()->GetRoutingID()));
- }
-
- CheckWebUIRendererDoesNotDisplayNormalURL(
- render_frame_host, navigation_request->common_params().url);
-
- navigation_request->TransferNavigationHandleOwnership(render_frame_host);
- render_frame_host->navigation_handle()->ReadyToCommitNavigation(
- render_frame_host, response ? response->head.headers : nullptr);
- render_frame_host->CommitNavigation(response, std::move(body),
- navigation_request->common_params(),
- navigation_request->request_params());
-}
-
-// PlzNavigate
void NavigatorImpl::FailedNavigation(FrameTreeNode* frame_tree_node,
bool has_stale_copy_in_cache,
int error_code) {
@@ -862,6 +855,8 @@ void NavigatorImpl::FailedNavigation(FrameTreeNode* frame_tree_node,
NavigationRequest* navigation_request = frame_tree_node->navigation_request();
DCHECK(navigation_request);
+ DiscardPendingEntryOnFailureIfNeeded(navigation_request->navigation_handle());
+
// If the request was canceled by the user do not show an error page.
if (error_code == net::ERR_ABORTED) {
frame_tree_node->ResetNavigationRequest(false);
@@ -877,7 +872,7 @@ void NavigatorImpl::FailedNavigation(FrameTreeNode* frame_tree_node,
navigation_request->TransferNavigationHandleOwnership(render_frame_host);
render_frame_host->navigation_handle()->ReadyToCommitNavigation(
- render_frame_host, scoped_refptr<net::HttpResponseHeaders>());
+ render_frame_host);
render_frame_host->FailedNavigation(navigation_request->common_params(),
navigation_request->request_params(),
has_stale_copy_in_cache, error_code);
@@ -913,22 +908,6 @@ void NavigatorImpl::LogBeforeUnloadTime(
}
}
-void NavigatorImpl::CheckWebUIRendererDoesNotDisplayNormalURL(
- RenderFrameHostImpl* render_frame_host,
- const GURL& url) {
- int enabled_bindings =
- render_frame_host->render_view_host()->GetEnabledBindings();
- bool is_allowed_in_web_ui_renderer =
- WebUIControllerFactoryRegistry::GetInstance()->IsURLAcceptableForWebUI(
- controller_->GetBrowserContext(), url);
- if ((enabled_bindings & BINDINGS_POLICY_WEB_UI) &&
- !is_allowed_in_web_ui_renderer) {
- // Log the URL to help us diagnose any future failures of this CHECK.
- GetContentClient()->SetActiveURL(url);
- CHECK(0);
- }
-}
-
// PlzNavigate
void NavigatorImpl::RequestNavigation(
FrameTreeNode* frame_tree_node,
@@ -937,6 +916,7 @@ void NavigatorImpl::RequestNavigation(
const FrameNavigationEntry& frame_entry,
const NavigationEntryImpl& entry,
NavigationController::ReloadType reload_type,
+ LoFiState lofi_state,
bool is_same_document_history_load,
base::TimeTicks navigation_start) {
CHECK(IsBrowserSideNavigationEnabled());
@@ -948,13 +928,21 @@ void NavigatorImpl::RequestNavigation(
frame_tree_node->current_frame_host()->ShouldDispatchBeforeUnload();
FrameMsg_Navigate_Type::Value navigation_type =
GetNavigationType(controller_->GetBrowserContext(), entry, reload_type);
- frame_tree_node->CreatedNavigationRequest(
+ scoped_ptr<NavigationRequest> scoped_request =
NavigationRequest::CreateBrowserInitiated(
frame_tree_node, dest_url, dest_referrer, frame_entry, entry,
- navigation_type, is_same_document_history_load, navigation_start,
- controller_));
- NavigationRequest* navigation_request = frame_tree_node->navigation_request();
- navigation_request->CreateNavigationHandle();
+ navigation_type, lofi_state, is_same_document_history_load,
+ navigation_start, controller_);
+ NavigationRequest* navigation_request = scoped_request.get();
+
+ // For Javascript navigations, do not assign the NavigationRequest to the
+ // FrameTreeNode, as navigating to a Javascript URL should not interrupt a
+ // previous navigation. BeginNavigation will have it commit, and the
+ // scoped_request will be destroyed at the end of this function.
+ if (!dest_url.SchemeIs(url::kJavaScriptScheme))
+ frame_tree_node->CreatedNavigationRequest(std::move(scoped_request));
+
+ navigation_request->CreateNavigationHandle(entry.GetUniqueID());
// Have the current renderer execute its beforeunload event if needed. If it
// is not needed (when beforeunload dispatch is not needed or this navigation
@@ -1026,7 +1014,8 @@ void NavigatorImpl::RecordNavigationMetrics(
void NavigatorImpl::DidStartMainFrameNavigation(
const GURL& url,
- SiteInstanceImpl* site_instance) {
+ SiteInstanceImpl* site_instance,
+ NavigationHandleImpl* navigation_handle) {
// If there is no browser-initiated pending entry for this navigation and it
// is not for the error URL, create a pending entry using the current
// SiteInstance, and ensure the address bar updates accordingly. We don't
@@ -1035,7 +1024,12 @@ void NavigatorImpl::DidStartMainFrameNavigation(
NavigationEntryImpl* pending_entry = controller_->GetPendingEntry();
bool has_browser_initiated_pending_entry =
pending_entry && !pending_entry->is_renderer_initiated();
- if (!has_browser_initiated_pending_entry) {
+
+ // If there is a transient entry, creating a new pending entry will result
+ // in deleting it, which leads to inconsistent state.
+ bool has_transient_entry = !!controller_->GetTransientEntry();
+
+ if (!has_browser_initiated_pending_entry && !has_transient_entry) {
scoped_ptr<NavigationEntryImpl> entry =
NavigationEntryImpl::FromNavigationEntry(
controller_->CreateNavigationEntry(
@@ -1045,16 +1039,65 @@ void NavigatorImpl::DidStartMainFrameNavigation(
entry->set_site_instance(site_instance);
// 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.
+ // That will allow us to skip the NavigationHandle update below as well.
if (pending_entry) {
entry->set_transferred_global_request_id(
pending_entry->transferred_global_request_id());
entry->set_should_replace_entry(pending_entry->should_replace_entry());
entry->SetRedirectChain(pending_entry->GetRedirectChain());
}
+
+ // If there's a current NavigationHandle, update its pending NavEntry ID.
+ // This is necessary for transfer navigations. The handle may be null in
+ // PlzNavigate.
+ if (navigation_handle)
+ navigation_handle->update_entry_id_for_transfer(entry->GetUniqueID());
+
controller_->SetPendingEntry(std::move(entry));
if (delegate_)
delegate_->NotifyChangedNavigationState(content::INVALIDATE_TYPE_URL);
}
}
+void NavigatorImpl::DiscardPendingEntryOnFailureIfNeeded(
+ NavigationHandleImpl* handle) {
+ // Racy conditions can cause a fail message to arrive after its corresponding
+ // pending entry has been replaced by another navigation. If
+ // |DiscardPendingEntry| is called in this case, then the completely valid
+ // entry for the new navigation would be discarded. See crbug.com/513742. To
+ // catch this case, the current pending entry is compared against the current
+ // navigation handle's entry id, which should correspond to the failed load.
+ NavigationEntry* pending_entry = controller_->GetPendingEntry();
+ bool pending_matches_fail_msg =
+ handle && pending_entry &&
+ handle->pending_nav_entry_id() == pending_entry->GetUniqueID();
+ if (!pending_matches_fail_msg)
+ return;
+
+ // We usually clear the pending entry when it fails, so that an arbitrary URL
+ // isn't left visible above a committed page. This must be enforced when the
+ // pending entry isn't visible (e.g., renderer-initiated navigations) to
+ // prevent URL spoofs for in-page navigations that don't go through
+ // DidStartProvisionalLoadForFrame.
+ //
+ // However, we do preserve the pending entry in some cases, such as on the
+ // initial navigation of an unmodified blank tab. We also allow the delegate
+ // to say when it's safe to leave aborted URLs in the omnibox, to let the
+ // user edit the URL and try again. This may be useful in cases that the
+ // committed page cannot be attacker-controlled. In these cases, we still
+ // allow the view to clear the pending entry and typed URL if the user
+ // requests (e.g., hitting Escape with focus in the address bar).
+ //
+ // Note: don't touch the transient entry, since an interstitial may exist.
+ bool should_preserve_entry = controller_->IsUnmodifiedBlankTab() ||
+ delegate_->ShouldPreserveAbortedURLs();
+ if (pending_entry != controller_->GetVisibleEntry() ||
+ !should_preserve_entry) {
+ controller_->DiscardPendingEntry(true);
+
+ // Also force the UI to refresh.
+ controller_->delegate()->NotifyNavigationStateChanged(INVALIDATE_TYPE_URL);
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/navigator_impl.h b/chromium/content/browser/frame_host/navigator_impl.h
index a8907689a6c..da3762fd555 100644
--- a/chromium/content/browser/frame_host/navigator_impl.h
+++ b/chromium/content/browser/frame_host/navigator_impl.h
@@ -13,6 +13,7 @@
#include "content/browser/frame_host/navigation_controller_impl.h"
#include "content/browser/frame_host/navigator.h"
#include "content/common/content_export.h"
+#include "content/common/navigation_params.h"
#include "url/gurl.h"
class GURL;
@@ -23,9 +24,6 @@ class NavigationControllerImpl;
class NavigatorDelegate;
class NavigatorTest;
struct LoadCommittedDetails;
-struct CommitNavigationParams;
-struct CommonNavigationParams;
-struct RequestNavigationParams;
// This class is an implementation of Navigator, responsible for managing
// navigations in regular browser tabs.
@@ -34,6 +32,10 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
NavigatorImpl(NavigationControllerImpl* navigation_controller,
NavigatorDelegate* delegate);
+ static void CheckWebUIRendererDoesNotDisplayNormalURL(
+ RenderFrameHostImpl* render_frame_host,
+ const GURL& url);
+
// Navigator implementation.
NavigatorDelegate* GetDelegate() override;
NavigationController* GetController() override;
@@ -68,6 +70,7 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
bool user_gesture) override;
void RequestTransferURL(RenderFrameHostImpl* render_frame_host,
const GURL& url,
+ SiteInstance* source_site_instance,
const std::vector<GURL>& redirect_chain,
const Referrer& referrer,
ui::PageTransition page_transition,
@@ -78,9 +81,6 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
const CommonNavigationParams& common_params,
const BeginNavigationParams& begin_params,
scoped_refptr<ResourceRequestBody> body) override;
- void CommitNavigation(FrameTreeNode* frame_tree_node,
- ResourceResponse* response,
- scoped_ptr<StreamHandle> body) override;
void FailedNavigation(FrameTreeNode* frame_tree_node,
bool has_stale_copy_in_cache,
int error_code) override;
@@ -110,10 +110,6 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
bool ShouldAssignSiteForURL(const GURL& url);
- void CheckWebUIRendererDoesNotDisplayNormalURL(
- RenderFrameHostImpl* render_frame_host,
- const GURL& url);
-
// PlzNavigate: if needed, sends a BeforeUnload IPC to the renderer to ask it
// to execute the beforeUnload event. Otherwise, the navigation request will
// be started.
@@ -123,6 +119,7 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
const FrameNavigationEntry& frame_entry,
const NavigationEntryImpl& entry,
NavigationController::ReloadType reload_type,
+ LoFiState lofi_state,
bool is_same_document_history_load,
base::TimeTicks navigation_start);
@@ -135,7 +132,12 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
// NavigationEntry if the controller does not currently have a
// browser-initiated one.
void DidStartMainFrameNavigation(const GURL& url,
- SiteInstanceImpl* site_instance);
+ SiteInstanceImpl* site_instance,
+ NavigationHandleImpl* navigation_handle);
+
+ // Called when a navigation has failed to discard the pending entry in order
+ // to avoid url spoofs.
+ void DiscardPendingEntryOnFailureIfNeeded(NavigationHandleImpl* handle);
// The NavigationController that will keep track of session history for all
// RenderFrameHost objects using this NavigatorImpl.
diff --git a/chromium/content/browser/frame_host/navigator_impl_unittest.cc b/chromium/content/browser/frame_host/navigator_impl_unittest.cc
index 28cce0799b7..a8ff15d9df5 100644
--- a/chromium/content/browser/frame_host/navigator_impl_unittest.cc
+++ b/chromium/content/browser/frame_host/navigator_impl_unittest.cc
@@ -43,9 +43,8 @@ namespace content {
class NavigatorTestWithBrowserSideNavigation
: public RenderViewHostImplTestHarness {
public:
- // Re-defines the private RenderFrameHostManager::SiteInstanceDescriptor here
- // to allow access to it from tests.
- typedef RenderFrameHostManager::SiteInstanceDescriptor SiteInstanceDescriptor;
+ using SiteInstanceDescriptor = RenderFrameHostManager::SiteInstanceDescriptor;
+ using SiteInstanceRelation = RenderFrameHostManager::SiteInstanceRelation;
void SetUp() override {
#if !defined(OS_ANDROID)
@@ -110,9 +109,10 @@ class NavigatorTestWithBrowserSideNavigation
return message && rfh->GetRoutingID() == message->routing_id();
}
- SiteInstance* ConvertToSiteInstance(RenderFrameHostManager* rfhm,
- const SiteInstanceDescriptor& descriptor,
- SiteInstance* candidate_instance) {
+ scoped_refptr<SiteInstance> ConvertToSiteInstance(
+ RenderFrameHostManager* rfhm,
+ const SiteInstanceDescriptor& descriptor,
+ SiteInstance* candidate_instance) {
return rfhm->ConvertToSiteInstance(descriptor, candidate_instance);
}
};
@@ -151,7 +151,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// Commit the navigation.
main_test_rfh()->SendNavigate(0, entry_id, true, kUrl);
- EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, main_test_rfh()->rfh_state());
+ EXPECT_TRUE(main_test_rfh()->is_active());
EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl),
main_test_rfh()->GetSiteInstance()->GetSiteURL());
EXPECT_EQ(kUrl, contents()->GetLastCommittedURL());
@@ -204,7 +204,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// Commit the navigation.
main_test_rfh()->SendNavigate(1, 0, true, kUrl2);
- EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, main_test_rfh()->rfh_state());
+ EXPECT_TRUE(main_test_rfh()->is_active());
EXPECT_EQ(SiteInstanceImpl::GetSiteForURL(browser_context(), kUrl2),
main_test_rfh()->GetSiteInstance()->GetSiteURL());
EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
@@ -237,19 +237,28 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_FALSE(request->begin_params().has_user_gesture);
EXPECT_EQ(kUrl2, request->common_params().url);
EXPECT_FALSE(request->browser_initiated());
- EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
+ if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
+ EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
+ } else {
+ EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
+ }
// Have the current RenderFrameHost commit the navigation.
scoped_refptr<ResourceResponse> response(new ResourceResponse);
GetLoaderForNavigationRequest(request)
->CallOnResponseStarted(response, MakeEmptyStream());
- EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
+ if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
+ EXPECT_TRUE(
+ DidRenderFrameHostRequestCommit(GetSpeculativeRenderFrameHost(node)));
+ } else {
+ EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
+ }
EXPECT_TRUE(main_test_rfh()->is_loading());
EXPECT_FALSE(node->navigation_request());
// Commit the navigation.
main_test_rfh()->SendNavigate(1, 0, true, kUrl2);
- EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, main_test_rfh()->rfh_state());
+ EXPECT_TRUE(main_test_rfh()->is_active());
EXPECT_EQ(kUrl2, contents()->GetLastCommittedURL());
EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
EXPECT_FALSE(node->render_manager()->pending_frame_host());
@@ -447,7 +456,6 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, CrossSiteNavigation) {
// Receive the beforeUnload ACK.
main_test_rfh()->SendBeforeUnloadACK(true);
EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
- EXPECT_FALSE(contents()->CrossProcessNavigationPending());
scoped_refptr<ResourceResponse> response(new ResourceResponse);
GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted(
@@ -455,7 +463,6 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, CrossSiteNavigation) {
EXPECT_EQ(speculative_rfh, GetSpeculativeRenderFrameHost(node));
EXPECT_TRUE(DidRenderFrameHostRequestCommit(speculative_rfh));
EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
- EXPECT_TRUE(contents()->CrossProcessNavigationPending());
speculative_rfh->SendNavigate(0, entry_id, true, kUrl2);
@@ -622,14 +629,24 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// Confirm that the first loader got destroyed.
EXPECT_FALSE(loader1);
- // Confirm that the speculative RenderFrameHost was destroyed.
- EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
+ // Confirm that the speculative RenderFrameHost was destroyed in the non
+ // SitePerProcess case.
+ if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
+ EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
+ } else {
+ EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
+ }
// Have the RenderFrameHost commit the navigation.
scoped_refptr<ResourceResponse> response(new ResourceResponse);
GetLoaderForNavigationRequest(request2)
->CallOnResponseStarted(response, MakeEmptyStream());
- EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
+ if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
+ EXPECT_TRUE(
+ DidRenderFrameHostRequestCommit(GetSpeculativeRenderFrameHost(node)));
+ } else {
+ EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
+ }
// Commit the navigation.
main_test_rfh()->SendNavigate(1, 0, true, kUrl2);
@@ -660,7 +677,11 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_EQ(kUrl1, request1->common_params().url);
EXPECT_FALSE(request1->browser_initiated());
EXPECT_TRUE(request1->begin_params().has_user_gesture);
- EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
+ if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
+ EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
+ } else {
+ EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
+ }
// Now receive a renderer-initiated non-user-initiated request. Nothing should
// change.
@@ -671,13 +692,22 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_EQ(kUrl1, request2->common_params().url);
EXPECT_FALSE(request2->browser_initiated());
EXPECT_TRUE(request2->begin_params().has_user_gesture);
- EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
+ if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
+ EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
+ } else {
+ EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
+ }
// Have the RenderFrameHost commit the navigation.
scoped_refptr<ResourceResponse> response(new ResourceResponse);
GetLoaderForNavigationRequest(request2)
->CallOnResponseStarted(response, MakeEmptyStream());
- EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
+ if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
+ EXPECT_TRUE(
+ DidRenderFrameHostRequestCommit(GetSpeculativeRenderFrameHost(node)));
+ } else {
+ EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
+ }
// Commit the navigation.
main_test_rfh()->SendNavigate(1, 0, true, kUrl1);
@@ -753,7 +783,11 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_EQ(kUrl1, request1->common_params().url);
EXPECT_FALSE(request1->browser_initiated());
EXPECT_FALSE(request1->begin_params().has_user_gesture);
- EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
+ if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
+ EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
+ } else {
+ EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
+ }
base::WeakPtr<TestNavigationURLLoader> loader1 =
GetLoaderForNavigationRequest(request1)->AsWeakPtr();
EXPECT_TRUE(loader1);
@@ -764,7 +798,11 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_EQ(kUrl2, request2->common_params().url);
EXPECT_FALSE(request2->browser_initiated());
EXPECT_FALSE(request2->begin_params().has_user_gesture);
- EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
+ if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
+ EXPECT_TRUE(GetSpeculativeRenderFrameHost(node));
+ } else {
+ EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
+ }
// Confirm that the first loader got destroyed.
EXPECT_FALSE(loader1);
@@ -773,7 +811,12 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
scoped_refptr<ResourceResponse> response(new ResourceResponse);
GetLoaderForNavigationRequest(request2)
->CallOnResponseStarted(response, MakeEmptyStream());
- EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
+ if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
+ EXPECT_TRUE(
+ DidRenderFrameHostRequestCommit(GetSpeculativeRenderFrameHost(node)));
+ } else {
+ EXPECT_TRUE(DidRenderFrameHostRequestCommit(main_test_rfh()));
+ }
// Commit the navigation.
main_test_rfh()->SendNavigate(1, 0, true, kUrl2);
@@ -805,11 +848,11 @@ TEST_F(NavigatorTestWithBrowserSideNavigation, Reload) {
EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
// Now do a shift+reload.
- controller().ReloadIgnoringCache(false);
+ controller().ReloadBypassingCache(false);
// A NavigationRequest should have been generated.
main_request = node->navigation_request();
ASSERT_TRUE(main_request != NULL);
- EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE,
+ EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD_BYPASSING_CACHE,
main_request->common_params().navigation_type);
main_test_rfh()->PrepareForCommit();
EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
@@ -930,62 +973,6 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_FALSE(GetSpeculativeRenderFrameHost(node));
}
-// PlzNavigate: Verify that a previously swapped out RenderFrameHost is
-// correctly reused when spawning a speculative RenderFrameHost in a navigation
-// using the same SiteInstance.
-TEST_F(NavigatorTestWithBrowserSideNavigation,
- SpeculativeRendererReuseSwappedOutRFH) {
- // This test doesn't make sense in --site-per-process where swapped out
- // RenderFrameHost is no longer used.
- if (SiteIsolationPolicy::IsSwappedOutStateForbidden())
- return;
-
- // Navigate to an initial site.
- const GURL kUrl1("http://wikipedia.org/");
- contents()->NavigateAndCommit(kUrl1);
- TestRenderFrameHost* rfh1 = main_test_rfh();
- FrameTreeNode* node = rfh1->frame_tree_node();
- RenderFrameHostManager* rfhm = node->render_manager();
-
- // Increment active frame count to cause the RenderFrameHost to be swapped out
- // (instead of immediately destroyed).
- rfh1->GetSiteInstance()->IncrementActiveFrameCount();
-
- // Navigate to another site to swap out the initial RenderFrameHost.
- const GURL kUrl2("http://chromium.org/");
- contents()->NavigateAndCommit(kUrl2);
- ASSERT_NE(rfh1, main_test_rfh());
- EXPECT_NE(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state());
- EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, main_test_rfh()->rfh_state());
- EXPECT_TRUE(rfhm->IsOnSwappedOutList(rfh1));
-
- // Now go back to the initial site so that the swapped out RenderFrameHost
- // should be reused.
- process()->sink().ClearMessages();
- rfh1->GetProcess()->sink().ClearMessages();
- int entry_id = RequestNavigation(node, kUrl1);
- EXPECT_EQ(rfh1, GetSpeculativeRenderFrameHost(node));
-
- main_test_rfh()->SendBeforeUnloadACK(true);
- EXPECT_EQ(rfh1, GetSpeculativeRenderFrameHost(node));
- EXPECT_NE(RenderFrameHostImpl::STATE_DEFAULT,
- GetSpeculativeRenderFrameHost(node)->rfh_state());
-
- scoped_refptr<ResourceResponse> response(new ResourceResponse);
- GetLoaderForNavigationRequest(node->navigation_request())
- ->CallOnResponseStarted(response, MakeEmptyStream());
- EXPECT_EQ(rfh1, GetSpeculativeRenderFrameHost(node));
- EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT,
- GetSpeculativeRenderFrameHost(node)->rfh_state());
- EXPECT_TRUE(DidRenderFrameHostRequestCommit(rfh1));
- EXPECT_FALSE(DidRenderFrameHostRequestCommit(main_test_rfh()));
-
- rfh1->SendNavigate(1, entry_id, true, kUrl1);
- EXPECT_EQ(rfh1, main_test_rfh());
- EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state());
- EXPECT_FALSE(rfhm->IsOnSwappedOutList(rfh1));
-}
-
// PlzNavigate: Verify that data urls are properly handled.
TEST_F(NavigatorTestWithBrowserSideNavigation, DataUrls) {
const GURL kUrl1("http://wikipedia.org/");
@@ -1038,7 +1025,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
main_test_rfh()->frame_tree_node()->render_manager();
{
SiteInstanceDescriptor descriptor(current_instance);
- SiteInstance* converted_instance =
+ scoped_refptr<SiteInstance> converted_instance =
ConvertToSiteInstance(rfhm, descriptor, nullptr);
EXPECT_EQ(current_instance, converted_instance);
}
@@ -1052,7 +1039,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
current_instance->IsRelatedSiteInstance(unrelated_instance.get()));
{
SiteInstanceDescriptor descriptor(unrelated_instance.get());
- SiteInstance* converted_instance =
+ scoped_refptr<SiteInstance> converted_instance =
ConvertToSiteInstance(rfhm, descriptor, nullptr);
EXPECT_EQ(unrelated_instance.get(), converted_instance);
}
@@ -1061,8 +1048,9 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// current one.
GURL kUrlSameSiteAs1("http://www.a.com/foo");
{
- SiteInstanceDescriptor descriptor(browser_context(), kUrlSameSiteAs1, true);
- SiteInstance* converted_instance =
+ SiteInstanceDescriptor descriptor(browser_context(), kUrlSameSiteAs1,
+ SiteInstanceRelation::RELATED);
+ scoped_refptr<SiteInstance> converted_instance =
ConvertToSiteInstance(rfhm, descriptor, nullptr);
EXPECT_EQ(current_instance, converted_instance);
}
@@ -1072,7 +1060,8 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
GURL kUrlSameSiteAs2("http://www.b.com/foo");
scoped_refptr<SiteInstance> related_instance;
{
- SiteInstanceDescriptor descriptor(browser_context(), kUrlSameSiteAs2, true);
+ SiteInstanceDescriptor descriptor(browser_context(), kUrlSameSiteAs2,
+ SiteInstanceRelation::RELATED);
related_instance = ConvertToSiteInstance(rfhm, descriptor, nullptr);
// Should return a new instance, related to the current, set to the new site
// URL.
@@ -1088,7 +1077,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// current one, several times, with and without candidate sites.
{
SiteInstanceDescriptor descriptor(browser_context(), kUrlSameSiteAs1,
- false);
+ SiteInstanceRelation::UNRELATED);
scoped_refptr<SiteInstance> converted_instance_1 =
ConvertToSiteInstance(rfhm, descriptor, nullptr);
// Should return a new instance, unrelated to the current one, set to the
@@ -1115,7 +1104,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
converted_instance_2->GetSiteURL());
// Converts once more but with |converted_instance_1| as a candidate.
- SiteInstance* converted_instance_3 =
+ scoped_refptr<SiteInstance> converted_instance_3 =
ConvertToSiteInstance(rfhm, descriptor, converted_instance_1.get());
// Should return |converted_instance_1| because its site matches and it is
// unrelated to the current SiteInstance.
@@ -1126,7 +1115,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
// related_instance and using it as a candidate.
{
SiteInstanceDescriptor descriptor(browser_context(), kUrlSameSiteAs2,
- false);
+ SiteInstanceRelation::UNRELATED);
scoped_refptr<SiteInstance> converted_instance_1 =
ConvertToSiteInstance(rfhm, descriptor, related_instance.get());
// Should return a new instance, unrelated to the current, set to the
@@ -1138,7 +1127,7 @@ TEST_F(NavigatorTestWithBrowserSideNavigation,
EXPECT_EQ(SiteInstance::GetSiteForURL(browser_context(), kUrlSameSiteAs2),
converted_instance_1->GetSiteURL());
- SiteInstance* converted_instance_2 =
+ scoped_refptr<SiteInstance> converted_instance_2 =
ConvertToSiteInstance(rfhm, descriptor, unrelated_instance.get());
// Should return |unrelated_instance| because its site matches and it is
// unrelated to the current SiteInstance.
@@ -1151,6 +1140,7 @@ void SetWithinPage(const GURL& url,
FrameHostMsg_DidCommitProvisionalLoad_Params* params) {
params->was_within_same_page = true;
params->url = url;
+ params->origin = url::Origin(url);
}
}
diff --git a/chromium/content/browser/frame_host/render_frame_host_delegate.cc b/chromium/content/browser/frame_host/render_frame_host_delegate.cc
index 03d9729cac2..b9dca1db897 100644
--- a/chromium/content/browser/frame_host/render_frame_host_delegate.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_delegate.cc
@@ -88,11 +88,4 @@ scoped_ptr<WebUIImpl> RenderFrameHostDelegate::CreateWebUIForRenderFrameHost(
return nullptr;
}
-#if defined(OS_WIN)
-gfx::NativeViewAccessible
- RenderFrameHostDelegate::GetParentNativeViewAccessible() {
- return NULL;
-}
-#endif // defined(OS_WIN)
-
} // namespace content
diff --git a/chromium/content/browser/frame_host/render_frame_host_delegate.h b/chromium/content/browser/frame_host/render_frame_host_delegate.h
index a2a4c599c3a..1cec9c701ab 100644
--- a/chromium/content/browser/frame_host/render_frame_host_delegate.h
+++ b/chromium/content/browser/frame_host/render_frame_host_delegate.h
@@ -81,7 +81,6 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
IPC::Message* reply_msg) {}
virtual void RunBeforeUnloadConfirm(RenderFrameHost* render_frame_host,
- const base::string16& message,
bool is_reload,
IPC::Message* reply_msg) {}
@@ -158,7 +157,10 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
virtual void EnterFullscreenMode(const GURL& origin) {}
// Notification that the frame wants to go out of fullscreen mode.
- virtual void ExitFullscreenMode() {}
+ // |will_cause_resize| indicates whether the fullscreen change causes a
+ // view resize. e.g. This will be false when going from tab fullscreen to
+ // browser fullscreen.
+ virtual void ExitFullscreenMode(bool will_cause_resize) {}
// Let the delegate decide whether postMessage should be delivered to
// |target_rfh| from a source frame in the given SiteInstance. This defaults
@@ -184,11 +186,6 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
// applies, returns null.
virtual scoped_ptr<WebUIImpl> CreateWebUIForRenderFrameHost(const GURL& url);
-#if defined(OS_WIN)
- // Returns the frame's parent's NativeViewAccessible.
- virtual gfx::NativeViewAccessible GetParentNativeViewAccessible();
-#endif
-
protected:
virtual ~RenderFrameHostDelegate() {}
};
diff --git a/chromium/content/browser/frame_host/render_frame_host_factory.cc b/chromium/content/browser/frame_host/render_frame_host_factory.cc
index d91354bfe33..92a449fa787 100644
--- a/chromium/content/browser/frame_host/render_frame_host_factory.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_factory.cc
@@ -23,15 +23,15 @@ scoped_ptr<RenderFrameHostImpl> RenderFrameHostFactory::Create(
FrameTreeNode* frame_tree_node,
int32_t routing_id,
int32_t widget_routing_id,
- int flags) {
+ bool hidden) {
if (factory_) {
return factory_->CreateRenderFrameHost(
site_instance, render_view_host, delegate, rwh_delegate, frame_tree,
- frame_tree_node, routing_id, widget_routing_id, flags);
+ frame_tree_node, routing_id, widget_routing_id, hidden);
}
return make_scoped_ptr(new RenderFrameHostImpl(
site_instance, render_view_host, delegate, rwh_delegate, frame_tree,
- frame_tree_node, routing_id, widget_routing_id, flags));
+ frame_tree_node, routing_id, widget_routing_id, hidden));
}
// static
diff --git a/chromium/content/browser/frame_host/render_frame_host_factory.h b/chromium/content/browser/frame_host/render_frame_host_factory.h
index 1b2fdc3aa4b..d6eb4908e16 100644
--- a/chromium/content/browser/frame_host/render_frame_host_factory.h
+++ b/chromium/content/browser/frame_host/render_frame_host_factory.h
@@ -37,7 +37,7 @@ class CONTENT_EXPORT RenderFrameHostFactory {
FrameTreeNode* frame_tree_node,
int32_t routing_id,
int32_t widget_routing_id,
- int flags);
+ bool hidden);
// Returns true if there is currently a globally-registered factory.
static bool has_factory() { return !!factory_; }
@@ -57,7 +57,7 @@ class CONTENT_EXPORT RenderFrameHostFactory {
FrameTreeNode* frame_tree_node,
int32_t routing_id,
int32_t widget_routing_id,
- int flags) = 0;
+ bool hidden) = 0;
// Registers a factory to be called when new RenderFrameHostImpls are created.
// We have only one global factory, so there must be no factory registered
diff --git a/chromium/content/browser/frame_host/render_frame_host_impl.cc b/chromium/content/browser/frame_host/render_frame_host_impl.cc
index f0de4ccf8e7..9eb6eaf828a 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_impl.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/command_line.h"
#include "base/containers/hash_tables.h"
#include "base/lazy_instance.h"
#include "base/metrics/histogram.h"
@@ -17,6 +18,7 @@
#include "content/browser/accessibility/ax_tree_id_registry.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
+#include "content/browser/bluetooth/web_bluetooth_service_impl.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
@@ -34,10 +36,11 @@
#include "content/browser/frame_host/render_frame_proxy_host.h"
#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
#include "content/browser/geolocation/geolocation_service_context.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/permissions/permission_service_context.h"
#include "content/browser/permissions/permission_service_impl.h"
#include "content/browser/presentation/presentation_service_impl.h"
-#include "content/browser/renderer_host/input/input_router.h"
+#include "content/browser/renderer_host/input/input_router_impl.h"
#include "content/browser/renderer_host/input/timeout_monitor.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
@@ -70,11 +73,13 @@
#include "content/public/browser/user_metrics.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_constants.h"
+#include "content/public/common/content_switches.h"
#include "content/public/common/isolated_world_ids.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "ui/accessibility/ax_tree.h"
#include "ui/accessibility/ax_tree_update.h"
+#include "ui/gfx/geometry/quad_f.h"
#include "url/gurl.h"
#if defined(OS_ANDROID)
@@ -131,11 +136,6 @@ base::i18n::TextDirection WebTextDirectionToChromeTextDirection(
} // namespace
// static
-bool RenderFrameHostImpl::IsRFHStateActive(RenderFrameHostImplState rfh_state) {
- return rfh_state == STATE_DEFAULT;
-}
-
-// static
RenderFrameHost* RenderFrameHost::FromID(int render_process_id,
int render_frame_id) {
return RenderFrameHostImpl::FromID(render_process_id, render_frame_id);
@@ -181,7 +181,7 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
FrameTreeNode* frame_tree_node,
int32_t routing_id,
int32_t widget_routing_id,
- int flags)
+ bool hidden)
: render_view_host_(render_view_host),
delegate_(delegate),
site_instance_(static_cast<SiteInstanceImpl*>(site_instance)),
@@ -192,6 +192,7 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
frame_tree_node_(frame_tree_node),
render_widget_host_(nullptr),
routing_id_(routing_id),
+ is_waiting_for_swapout_ack_(false),
render_frame_created_(false),
navigations_suspended_(false),
is_waiting_for_beforeunload_ack_(false),
@@ -201,25 +202,20 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
nav_entry_id_(0),
accessibility_reset_token_(0),
accessibility_reset_count_(0),
+ browser_plugin_embedder_ax_tree_id_(AXTreeIDRegistry::kNoAXTreeID),
no_create_browser_accessibility_manager_for_testing_(false),
web_ui_type_(WebUI::kNoWebUI),
pending_web_ui_type_(WebUI::kNoWebUI),
should_reuse_web_ui_(false),
+ last_navigation_lofi_state_(LOFI_UNSPECIFIED),
weak_ptr_factory_(this) {
- bool is_swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT);
- bool hidden = !!(flags & CREATE_RF_HIDDEN);
frame_tree_->AddRenderViewHostRef(render_view_host_);
GetProcess()->AddRoute(routing_id_, this);
g_routing_id_frame_map.Get().insert(std::make_pair(
RenderFrameHostID(GetProcess()->GetID(), routing_id_),
this));
-
- if (is_swapped_out) {
- rfh_state_ = STATE_SWAPPED_OUT;
- } else {
- rfh_state_ = STATE_DEFAULT;
- GetSiteInstance()->IncrementActiveFrameCount();
- }
+ site_instance_->AddObserver(this);
+ GetSiteInstance()->IncrementActiveFrameCount();
// New child frames should inherit the nav_entry_id of their parent.
if (frame_tree_node_->parent()) {
@@ -246,6 +242,9 @@ RenderFrameHostImpl::RenderFrameHostImpl(SiteInstance* site_instance,
} else {
DCHECK(!render_widget_host_->owned_by_render_frame_host());
}
+ InputRouterImpl* ir =
+ static_cast<InputRouterImpl*>(render_widget_host_->input_router());
+ ir->SetFrameTreeNodeId(frame_tree_node_->frame_tree_node_id());
}
}
@@ -258,21 +257,21 @@ RenderFrameHostImpl::~RenderFrameHostImpl() {
g_routing_id_frame_map.Get().erase(
RenderFrameHostID(GetProcess()->GetID(), routing_id_));
+ site_instance_->RemoveObserver(this);
+
if (delegate_ && render_frame_created_)
delegate_->RenderFrameDeleted(this);
- bool is_active = IsRFHStateActive(rfh_state_);
-
// If this RenderFrameHost is swapped out, it already decremented the active
// frame count of the SiteInstance it belongs to.
- if (is_active)
+ if (is_active())
GetSiteInstance()->DecrementActiveFrameCount();
// If this RenderFrameHost is swapping with a RenderFrameProxyHost, the
// RenderFrame will already be deleted in the renderer process. Main frame
// RenderFrames will be cleaned up as part of deleting its RenderView. In all
// other cases, the RenderFrame should be cleaned up (if it exists).
- if (is_active && !frame_tree_node_->IsMainFrame() && render_frame_created_)
+ if (is_active() && !frame_tree_node_->IsMainFrame() && render_frame_created_)
Send(new FrameMsg_Delete(routing_id_));
// NULL out the swapout timer; in crash dumps this member will be null only if
@@ -311,7 +310,7 @@ RenderProcessHost* RenderFrameHostImpl::GetProcess() {
return process_;
}
-RenderFrameHost* RenderFrameHostImpl::GetParent() {
+RenderFrameHostImpl* RenderFrameHostImpl::GetParent() {
FrameTreeNode* parent_node = frame_tree_node_->parent();
if (!parent_node)
return NULL;
@@ -334,8 +333,8 @@ bool RenderFrameHostImpl::IsCrossProcessSubframe() {
parent_node->current_frame_host()->GetSiteInstance();
}
-GURL RenderFrameHostImpl::GetLastCommittedURL() {
- return frame_tree_node_->current_url();
+const GURL& RenderFrameHostImpl::GetLastCommittedURL() {
+ return last_committed_url();
}
url::Origin RenderFrameHostImpl::GetLastCommittedOrigin() {
@@ -459,22 +458,9 @@ bool RenderFrameHostImpl::Send(IPC::Message* message) {
}
bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
- // Filter out most IPC messages if this frame is swapped out.
- // We still want to handle certain ACKs to keep our state consistent.
- if (is_swapped_out()) {
- if (!SwappedOutMessages::CanHandleWhileSwappedOut(msg)) {
- // If this is a synchronous message and we decided not to handle it,
- // we must send an error reply, or else the renderer will be stuck
- // and won't respond to future requests.
- if (msg.is_sync()) {
- IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg);
- reply->set_reply_error();
- Send(reply);
- }
- // Don't continue looking for someone to handle it.
- return true;
- }
- }
+ // Only process messages if the RenderFrame is alive.
+ if (!render_frame_created_)
+ return false;
// This message map is for handling internal IPC messages which should not
// be dispatched to other objects.
@@ -513,7 +499,6 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
OnDidFailLoadWithError)
IPC_MESSAGE_HANDLER_GENERIC(FrameHostMsg_DidCommitProvisionalLoad,
OnDidCommitProvisionalLoad(msg))
- IPC_MESSAGE_HANDLER(FrameHostMsg_DidDropNavigation, OnDidDropNavigation)
IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateState, OnUpdateState)
IPC_MESSAGE_HANDLER(FrameHostMsg_OpenURL, OnOpenURL)
IPC_MESSAGE_HANDLER(FrameHostMsg_DocumentOnLoadCompleted,
@@ -535,6 +520,8 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeName, OnDidChangeName)
IPC_MESSAGE_HANDLER(FrameHostMsg_EnforceStrictMixedContentChecking,
OnEnforceStrictMixedContentChecking)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateToUniqueOrigin,
+ OnUpdateToUniqueOrigin)
IPC_MESSAGE_HANDLER(FrameHostMsg_DidAssignPageId, OnDidAssignPageId)
IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeSandboxFlags,
OnDidChangeSandboxFlags)
@@ -552,6 +539,8 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
OnAccessibilityLocationChanges)
IPC_MESSAGE_HANDLER(AccessibilityHostMsg_FindInPageResult,
OnAccessibilityFindInPageResult)
+ IPC_MESSAGE_HANDLER(AccessibilityHostMsg_ChildFrameHitTestResult,
+ OnAccessibilityChildFrameHitTestResult)
IPC_MESSAGE_HANDLER(AccessibilityHostMsg_SnapshotResponse,
OnAccessibilitySnapshotResponse)
IPC_MESSAGE_HANDLER(FrameHostMsg_ToggleFullscreen, OnToggleFullscreen)
@@ -606,7 +595,7 @@ void RenderFrameHostImpl::AccessibilitySetSelection(int anchor_object_id,
int focus_object_id,
int focus_offset) {
Send(new AccessibilityMsg_SetSelection(routing_id_,
- focus_object_id,
+ anchor_object_id,
anchor_offset,
focus_object_id,
focus_offset));
@@ -640,6 +629,25 @@ gfx::Point RenderFrameHostImpl::AccessibilityOriginInScreen(
return gfx::Point();
}
+gfx::Rect RenderFrameHostImpl::AccessibilityTransformToRootCoordSpace(
+ const gfx::Rect& bounds) {
+ RenderWidgetHostViewBase* view =
+ static_cast<RenderWidgetHostViewBase*>(GetView());
+ gfx::Point p1 = view->TransformPointToRootCoordSpace(bounds.origin());
+ gfx::Point p2 = view->TransformPointToRootCoordSpace(bounds.top_right());
+ gfx::Point p3 = view->TransformPointToRootCoordSpace(bounds.bottom_right());
+ gfx::Point p4 = view->TransformPointToRootCoordSpace(bounds.bottom_left());
+ gfx::QuadF transformed_quad = gfx::QuadF(
+ gfx::PointF(p1), gfx::PointF(p2), gfx::PointF(p3), gfx::PointF(p4));
+ gfx::RectF new_bounds = transformed_quad.BoundingBox();
+ return gfx::Rect(new_bounds.x(), new_bounds.y(),
+ new_bounds.width(), new_bounds.height());
+}
+
+SiteInstance* RenderFrameHostImpl::AccessibilityGetSiteInstance() {
+ return GetSiteInstance();
+}
+
void RenderFrameHostImpl::AccessibilityHitTest(const gfx::Point& point) {
Send(new AccessibilityMsg_HitTest(routing_id_, point));
}
@@ -670,6 +678,14 @@ void RenderFrameHostImpl::AccessibilityFatalError() {
gfx::AcceleratedWidget
RenderFrameHostImpl::AccessibilityGetAcceleratedWidget() {
+ // Only the main frame's current frame host is connected to the native
+ // widget tree for accessibility, so return null if this is queried on
+ // any other frame.
+ if (frame_tree_node()->parent() ||
+ frame_tree_node()->current_frame_host() != this) {
+ return gfx::kNullAcceleratedWidget;
+ }
+
RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
render_view_host_->GetWidget()->GetView());
if (view)
@@ -686,6 +702,13 @@ gfx::NativeViewAccessible
return NULL;
}
+void RenderFrameHostImpl::RenderProcessGone(SiteInstanceImpl* site_instance) {
+ DCHECK_EQ(site_instance_.get(), site_instance);
+
+ // The renderer process is gone, so this frame can no longer be loading.
+ ResetLoadingState();
+}
+
bool RenderFrameHostImpl::CreateRenderFrame(int proxy_routing_id,
int opener_routing_id,
int parent_routing_id,
@@ -709,6 +732,16 @@ bool RenderFrameHostImpl::CreateRenderFrame(int proxy_routing_id,
params.parent_routing_id = parent_routing_id;
params.previous_sibling_routing_id = previous_sibling_routing_id;
params.replication_state = frame_tree_node()->current_replication_state();
+
+ // Normally, the replication state contains effective sandbox flags,
+ // excluding flags that were updated but have not taken effect. However, a
+ // new RenderFrame should use the pending sandbox flags, since it is being
+ // created as part of the navigation that will commit these flags. (I.e., the
+ // RenderFrame needs to know the flags to use when initializing the new
+ // document once it commits).
+ params.replication_state.sandbox_flags =
+ frame_tree_node()->pending_sandbox_flags();
+
params.frame_owner_properties = frame_tree_node()->frame_owner_properties();
if (render_widget_host_) {
@@ -769,9 +802,7 @@ void RenderFrameHostImpl::SetRenderFrameCreated(bool created) {
}
void RenderFrameHostImpl::Init() {
- // TODO(csharrison): Call GetProcess()->ResumeRequestsForFrame(routing_id_)
- // once ResourceDispatcherHostImpl is keyed on render frame routing ids
- // instead of render view routing ids.
+ ResourceDispatcherHost::ResumeBlockedRequestsForFrameFromUI(this);
}
void RenderFrameHostImpl::OnAddMessageToConsole(
@@ -804,18 +835,21 @@ void RenderFrameHostImpl::OnCreateChildFrame(
int new_routing_id,
blink::WebTreeScopeType scope,
const std::string& frame_name,
+ const std::string& frame_unique_name,
blink::WebSandboxFlags sandbox_flags,
const blink::WebFrameOwnerProperties& frame_owner_properties) {
+ // TODO(lukasza): Call ReceivedBadMessage when |frame_unique_name| is empty.
+ DCHECK(!frame_unique_name.empty());
+
// It is possible that while a new RenderFrameHost was committed, the
// RenderFrame corresponding to this host sent an IPC message to create a
// frame and it is delivered after this host is swapped out.
// Ignore such messages, as we know this RenderFrameHost is going away.
- if (rfh_state_ != RenderFrameHostImpl::STATE_DEFAULT ||
- frame_tree_node_->current_frame_host() != this)
+ if (!is_active() || frame_tree_node_->current_frame_host() != this)
return;
frame_tree_->AddFrame(frame_tree_node_, GetProcess()->GetID(), new_routing_id,
- scope, frame_name, sandbox_flags,
+ scope, frame_name, frame_unique_name, sandbox_flags,
frame_owner_properties);
}
@@ -963,6 +997,15 @@ void RenderFrameHostImpl::OnDidCommitProvisionalLoad(const IPC::Message& msg) {
// Kills the process.
bad_message::ReceivedBadMessage(process,
bad_message::RFH_CAN_COMMIT_URL_BLOCKED);
+ return;
+ }
+
+ // Verify that the origin passed from the renderer process is valid and can
+ // be allowed to commit in this RenderFrameHost.
+ if (!CanCommitOrigin(validated_params.origin, validated_params.url)) {
+ bad_message::ReceivedBadMessage(GetProcess(),
+ bad_message::RFH_INVALID_ORIGIN_ON_COMMIT);
+ return;
}
// Without this check, an evil renderer can trick the browser into creating
@@ -993,8 +1036,30 @@ void RenderFrameHostImpl::OnDidCommitProvisionalLoad(const IPC::Message& msg) {
// commit as a new navigation. This can happen if an ongoing slow
// same-process navigation is interrupted by a synchronous renderer-initiated
// navigation.
+ // TODO(csharrison): Data navigations loaded with LoadDataWithBaseURL get
+ // reset here, because the NavigationHandle tracks the URL but the
+ // validated_params.url tracks the data. The trick of saving the old entry ids
+ // for these navigations should go away when this is properly handled. See
+ // crbug.com/588317.
+ int entry_id_for_data_nav = 0;
if (navigation_handle_ &&
- navigation_handle_->GetURL() != validated_params.url) {
+ (navigation_handle_->GetURL() != validated_params.url)) {
+ // Make sure that the pending entry was really loaded via
+ // LoadDataWithBaseURL and that it matches this handle.
+ NavigationEntry* pending_entry =
+ frame_tree_node()->navigator()->GetController()->GetPendingEntry();
+ bool pending_entry_matches_handle =
+ pending_entry &&
+ pending_entry->GetUniqueID() ==
+ navigation_handle_->pending_nav_entry_id();
+ // TODO(csharrison): The pending entry's base url should equal
+ // |validated_params.base_url|. This is not the case for loads with invalid
+ // base urls.
+ if (navigation_handle_->GetURL() == validated_params.base_url &&
+ pending_entry_matches_handle &&
+ !pending_entry->GetBaseURLForDataURL().is_empty()) {
+ entry_id_for_data_nav = navigation_handle_->pending_nav_entry_id();
+ }
navigation_handle_.reset();
}
@@ -1002,8 +1067,25 @@ void RenderFrameHostImpl::OnDidCommitProvisionalLoad(const IPC::Message& msg) {
// DidCommitProvisionalLoad IPC without a prior DidStartProvisionalLoad
// message.
if (!navigation_handle_) {
+ // There is no pending NavigationEntry in these cases, so pass 0 as the
+ // nav_id. If the previous handle was a prematurely aborted navigation
+ // loaded via LoadDataWithBaseURL, propogate the entry id.
navigation_handle_ = NavigationHandleImpl::Create(
- validated_params.url, frame_tree_node_, base::TimeTicks::Now());
+ validated_params.url, frame_tree_node_,
+ true, // is_synchronous
+ validated_params.is_srcdoc, base::TimeTicks::Now(),
+ entry_id_for_data_nav);
+ // PlzNavigate
+ if (IsBrowserSideNavigationEnabled()) {
+ // PlzNavigate: synchronous loads happen in the renderer, and the browser
+ // has not been notified about the start of the load yet. Do it now.
+ if (!is_loading()) {
+ bool was_loading = frame_tree_node()->frame_tree()->IsLoading();
+ is_loading_ = true;
+ frame_tree_node()->DidStartLoading(true, was_loading);
+ }
+ pending_commit_ = false;
+ }
}
accessibility_reset_count_ = 0;
@@ -1021,19 +1103,6 @@ void RenderFrameHostImpl::OnDidCommitProvisionalLoad(const IPC::Message& msg) {
RenderWidgetHostImpl::From(GetView()->GetRenderWidgetHost())
->StartNewContentRenderingTimeout();
}
-
- // PlzNavigate
- if (IsBrowserSideNavigationEnabled())
- pending_commit_ = false;
-}
-
-void RenderFrameHostImpl::OnDidDropNavigation() {
- // At the end of Navigate(), the FrameTreeNode's DidStartLoading is called to
- // force the spinner to start, even if the renderer didn't yet begin the load.
- // If it turns out that the renderer dropped the navigation, the spinner needs
- // to be turned off.
- frame_tree_node_->DidStopLoading();
- navigation_handle_.reset();
}
void RenderFrameHostImpl::OnUpdateState(const PageState& state) {
@@ -1067,6 +1136,10 @@ RenderWidgetHostView* RenderFrameHostImpl::GetView() {
return nullptr;
}
+GlobalFrameRoutingId RenderFrameHostImpl::GetGlobalFrameRoutingId() {
+ return GlobalFrameRoutingId(GetProcess()->GetID(), GetRoutingID());
+}
+
int RenderFrameHostImpl::GetEnabledBindings() {
return render_view_host_->GetEnabledBindings();
}
@@ -1107,9 +1180,9 @@ void RenderFrameHostImpl::SwapOut(
// to be fixed when RenderViewHostImpl::OnSwapOut moves to RenderFrameHost.
TRACE_EVENT_ASYNC_BEGIN0("navigation", "RenderFrameHostImpl::SwapOut", this);
- // If this RenderFrameHost is not in the default state, it must have already
+ // If this RenderFrameHost is already pending deletion, it must have already
// gone through this, therefore just return.
- if (rfh_state_ != RenderFrameHostImpl::STATE_DEFAULT) {
+ if (!is_active()) {
NOTREACHED() << "RFH should be in default state when calling SwapOut.";
return;
}
@@ -1131,9 +1204,16 @@ void RenderFrameHostImpl::SwapOut(
replication_state));
}
- // If this is the last active frame in the SiteInstance, the SetState call
- // below will trigger the deletion of the SiteInstance's proxies.
- SetState(RenderFrameHostImpl::STATE_PENDING_SWAP_OUT);
+ // TODO(nasko): If the frame is not live, the RFH should just be deleted by
+ // simulating the receipt of swap out ack.
+ is_waiting_for_swapout_ack_ = true;
+ if (frame_tree_node_->IsMainFrame())
+ render_view_host_->set_is_active(false);
+
+ // If this is the last active frame in the SiteInstance, the
+ // DecrementActiveFrameCount call will trigger the deletion of the
+ // SiteInstance's proxies.
+ GetSiteInstance()->DecrementActiveFrameCount();
if (!GetParent())
delegate_->SwappedOut(this);
@@ -1233,7 +1313,7 @@ void RenderFrameHostImpl::OnBeforeUnloadACK(
bool RenderFrameHostImpl::IsWaitingForUnloadACK() const {
return render_view_host_->is_waiting_for_close_ack_ ||
- rfh_state_ == STATE_PENDING_SWAP_OUT;
+ is_waiting_for_swapout_ack_;
}
void RenderFrameHostImpl::OnSwapOutACK() {
@@ -1251,11 +1331,7 @@ void RenderFrameHostImpl::OnRenderProcessGone(int status, int exit_code) {
// Reset frame tree state associated with this process. This must happen
// before RenderViewTerminated because observers expect the subframes of any
// affected frames to be cleared first.
- // Note: When a RenderFrameHost is swapped out there is a different one
- // which is the current host. In this case, the FrameTreeNode state must
- // not be reset.
- if (!is_swapped_out())
- frame_tree_node_->ResetForNewProcess();
+ frame_tree_node_->ResetForNewProcess();
// Reset state for the current RenderFrameHost once the FrameTreeNode has been
// reset.
@@ -1268,6 +1344,12 @@ void RenderFrameHostImpl::OnRenderProcessGone(int status, int exit_code) {
iter.second.Run(ui::AXTreeUpdate());
ax_tree_snapshot_callbacks_.clear();
+ // If the process has died, we don't need to wait for the swap out ack from
+ // this RenderFrame if it is pending deletion. Complete the swap out to
+ // destroy it.
+ if (!is_active())
+ OnSwappedOut();
+
// Note: don't add any more code at this point in the function because
// |this| may be deleted. Any additional cleanup should happen before
// the last block of code here.
@@ -1275,7 +1357,7 @@ void RenderFrameHostImpl::OnRenderProcessGone(int status, int exit_code) {
void RenderFrameHostImpl::OnSwappedOut() {
// Ignore spurious swap out ack.
- if (rfh_state_ != STATE_PENDING_SWAP_OUT)
+ if (!is_waiting_for_swapout_ack_)
return;
TRACE_EVENT_ASYNC_END0("navigation", "RenderFrameHostImpl::SwapOut", this);
@@ -1284,21 +1366,19 @@ void RenderFrameHostImpl::OnSwappedOut() {
ClearAllWebUI();
// If this is a main frame RFH that's about to be deleted, update its RVH's
- // swapped-out state here, since SetState won't be called once this RFH is
- // deleted below. https://crbug.com/505887
- if (frame_tree_node_->IsMainFrame() &&
- frame_tree_node_->render_manager()->IsPendingDeletion(this)) {
+ // swapped-out state here. https://crbug.com/505887
+ if (frame_tree_node_->IsMainFrame()) {
render_view_host_->set_is_active(false);
render_view_host_->set_is_swapped_out(true);
}
- if (frame_tree_node_->render_manager()->DeleteFromPendingList(this)) {
- // We are now deleted.
- return;
- }
+ bool deleted =
+ frame_tree_node_->render_manager()->DeleteFromPendingList(this);
+ CHECK(deleted);
+}
- // If this RFH wasn't pending deletion, then it is now swapped out.
- SetState(RenderFrameHostImpl::STATE_SWAPPED_OUT);
+void RenderFrameHostImpl::ResetSwapOutTimerForTesting() {
+ swapout_event_monitor_timeout_->Stop();
}
void RenderFrameHostImpl::OnContextMenu(const ContextMenuParams& params) {
@@ -1317,9 +1397,9 @@ void RenderFrameHostImpl::OnContextMenu(const ContextMenuParams& params) {
// It is necessary to transform the coordinates to account for nested
// RenderWidgetHosts, such as with out-of-process iframes.
gfx::Point original_point(validated_params.x, validated_params.y);
- gfx::Point transformed_point = original_point;
- static_cast<RenderWidgetHostViewBase*>(GetView())
- ->TransformPointToRootCoordSpace(original_point, &transformed_point);
+ gfx::Point transformed_point =
+ static_cast<RenderWidgetHostViewBase*>(GetView())
+ ->TransformPointToRootCoordSpace(original_point);
validated_params.x = transformed_point.x();
validated_params.y = transformed_point.y();
@@ -1371,20 +1451,19 @@ void RenderFrameHostImpl::OnRunJavaScriptMessage(
void RenderFrameHostImpl::OnRunBeforeUnloadConfirm(
const GURL& frame_url,
- const base::string16& message,
bool is_reload,
IPC::Message* reply_msg) {
// While a JS beforeunload dialog is showing, tabs in the same process
// shouldn't process input events.
GetProcess()->SetIgnoreInputEvents(true);
render_view_host_->GetWidget()->StopHangMonitorTimeout();
- delegate_->RunBeforeUnloadConfirm(this, message, is_reload, reply_msg);
+ delegate_->RunBeforeUnloadConfirm(this, is_reload, reply_msg);
}
void RenderFrameHostImpl::OnTextSurroundingSelectionResponse(
const base::string16& content,
- size_t start_offset,
- size_t end_offset) {
+ uint32_t start_offset,
+ uint32_t end_offset) {
render_view_host_->OnTextSurroundingSelectionResponse(
content, start_offset, end_offset);
}
@@ -1398,9 +1477,15 @@ void RenderFrameHostImpl::OnDidChangeOpener(int32_t opener_routing_id) {
GetSiteInstance());
}
-void RenderFrameHostImpl::OnDidChangeName(const std::string& name) {
+void RenderFrameHostImpl::OnDidChangeName(const std::string& name,
+ const std::string& unique_name) {
+ if (GetParent() != nullptr) {
+ // TODO(lukasza): Call ReceivedBadMessage when |unique_name| is empty.
+ DCHECK(!unique_name.empty());
+ }
+
std::string old_name = frame_tree_node()->frame_name();
- frame_tree_node()->SetFrameName(name);
+ frame_tree_node()->SetFrameName(name, unique_name);
if (old_name.empty() && !name.empty())
frame_tree_node_->render_manager()->CreateProxiesForNewNamedFrame();
delegate_->DidChangeName(this, name);
@@ -1410,6 +1495,14 @@ void RenderFrameHostImpl::OnEnforceStrictMixedContentChecking() {
frame_tree_node()->SetEnforceStrictMixedContentChecking(true);
}
+void RenderFrameHostImpl::OnUpdateToUniqueOrigin(
+ bool is_potentially_trustworthy_unique_origin) {
+ url::Origin origin;
+ DCHECK(origin.unique());
+ frame_tree_node()->SetCurrentOrigin(origin,
+ is_potentially_trustworthy_unique_origin);
+}
+
void RenderFrameHostImpl::OnDidAssignPageId(int32_t page_id) {
// Update the RVH's current page ID so that future IPCs from the renderer
// correspond to the new page.
@@ -1441,7 +1534,7 @@ void RenderFrameHostImpl::OnDidChangeSandboxFlags(
if (!child)
return;
- child->set_sandbox_flags(flags);
+ child->SetPendingSandboxFlags(flags);
// Notify the RenderFrame if it lives in a different process from its
// parent. The frame's proxies in other processes also need to learn about
@@ -1550,8 +1643,7 @@ void RenderFrameHostImpl::OnAccessibilityEvents(
RenderWidgetHostViewBase* view = GetViewForAccessibility();
AccessibilityMode accessibility_mode = delegate_->GetAccessibilityMode();
- if ((accessibility_mode != AccessibilityModeOff) && view &&
- RenderFrameHostImpl::IsRFHStateActive(rfh_state())) {
+ if ((accessibility_mode != AccessibilityModeOff) && view && is_active()) {
if (accessibility_mode & AccessibilityModeFlagPlatform)
GetOrCreateBrowserAccessibilityManager();
@@ -1565,8 +1657,8 @@ void RenderFrameHostImpl::OnAccessibilityEvents(
detail.ax_tree_id = GetAXTreeID();
if (param.update.has_tree_data) {
detail.update.has_tree_data = true;
- AXContentTreeDataToAXTreeData(param.update.tree_data,
- &detail.update.tree_data);
+ ax_content_tree_data_ = param.update.tree_data;
+ AXContentTreeDataToAXTreeData(&detail.update.tree_data);
}
detail.update.node_id_to_clear = param.update.node_id_to_clear;
detail.update.nodes.resize(param.update.nodes.size());
@@ -1605,7 +1697,7 @@ void RenderFrameHostImpl::OnAccessibilityEvents(
CHECK(ax_tree_for_testing_->Unserialize(detail.update))
<< ax_tree_for_testing_->error();
}
- accessibility_testing_callback_.Run(detail.event_type, detail.id);
+ accessibility_testing_callback_.Run(this, detail.event_type, detail.id);
}
}
}
@@ -1621,7 +1713,7 @@ void RenderFrameHostImpl::OnAccessibilityLocationChanges(
RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
render_view_host_->GetWidget()->GetView());
- if (view && RenderFrameHostImpl::IsRFHStateActive(rfh_state())) {
+ if (view && is_active()) {
AccessibilityMode accessibility_mode = delegate_->GetAccessibilityMode();
if (accessibility_mode & AccessibilityModeFlagPlatform) {
BrowserAccessibilityManager* manager =
@@ -1647,6 +1739,15 @@ void RenderFrameHostImpl::OnAccessibilityFindInPageResult(
}
}
+void RenderFrameHostImpl::OnAccessibilityChildFrameHitTestResult(
+ const gfx::Point& point,
+ int hit_obj_id) {
+ if (browser_accessibility_manager_) {
+ browser_accessibility_manager_->OnChildFrameHitTestResult(point,
+ hit_obj_id);
+ }
+}
+
void RenderFrameHostImpl::OnAccessibilitySnapshotResponse(
int callback_id,
const AXContentTreeUpdate& snapshot) {
@@ -1659,8 +1760,8 @@ void RenderFrameHostImpl::OnAccessibilitySnapshotResponse(
&dst_snapshot.nodes[i]);
}
if (snapshot.has_tree_data) {
- AXContentTreeDataToAXTreeData(snapshot.tree_data,
- &dst_snapshot.tree_data);
+ ax_content_tree_data_ = snapshot.tree_data;
+ AXContentTreeDataToAXTreeData(&dst_snapshot.tree_data);
dst_snapshot.has_tree_data = true;
}
it->second.Run(dst_snapshot);
@@ -1672,9 +1773,9 @@ void RenderFrameHostImpl::OnAccessibilitySnapshotResponse(
void RenderFrameHostImpl::OnToggleFullscreen(bool enter_fullscreen) {
if (enter_fullscreen)
- delegate_->EnterFullscreenMode(GetLastCommittedURL().GetOrigin());
+ delegate_->EnterFullscreenMode(last_committed_url().GetOrigin());
else
- delegate_->ExitFullscreenMode();
+ delegate_->ExitFullscreenMode(/* will_cause_resize */ true);
// The previous call might change the fullscreen state. We need to make sure
// the renderer is aware of that, which is done via the resize message.
@@ -1682,23 +1783,20 @@ void RenderFrameHostImpl::OnToggleFullscreen(bool enter_fullscreen) {
}
void RenderFrameHostImpl::OnDidStartLoading(bool to_different_document) {
- // Any main frame load to a new document should reset the load since it will
- // replace the current page and any frames.
- if (to_different_document && !GetParent())
- is_loading_ = false;
-
- // This method should never be called when the frame is loading.
- // Unfortunately, it can happen if a history navigation happens during a
- // BeforeUnload or Unload event.
- // TODO(fdegans): Change this to a DCHECK after LoadEventProgress has been
- // refactored in Blink. See crbug.com/466089
- if (is_loading_) {
- LOG(WARNING) << "OnDidStartLoading was called twice.";
+ if (IsBrowserSideNavigationEnabled() && to_different_document) {
+ bad_message::ReceivedBadMessage(GetProcess(),
+ bad_message::RFH_UNEXPECTED_LOAD_START);
return;
}
-
- frame_tree_node_->DidStartLoading(to_different_document);
+ bool was_previously_loading = frame_tree_node_->frame_tree()->IsLoading();
is_loading_ = true;
+
+ // Only inform the FrameTreeNode of a change in load state if the load state
+ // of this RenderFrameHost is being tracked.
+ if (is_active()) {
+ frame_tree_node_->DidStartLoading(to_different_document,
+ was_previously_loading);
+ }
}
void RenderFrameHostImpl::OnDidStopLoading() {
@@ -1713,8 +1811,12 @@ void RenderFrameHostImpl::OnDidStopLoading() {
}
is_loading_ = false;
- frame_tree_node_->DidStopLoading();
navigation_handle_.reset();
+
+ // Only inform the FrameTreeNode of a change in load state if the load state
+ // of this RenderFrameHost is being tracked.
+ if (is_active())
+ frame_tree_node_->DidStopLoading();
}
void RenderFrameHostImpl::OnDidChangeLoadProgress(double load_progress) {
@@ -1735,13 +1837,15 @@ void RenderFrameHostImpl::OnShowPopup(
RenderViewHostDelegateView* view =
render_view_host_->delegate_->GetDelegateView();
if (view) {
- view->ShowPopupMenu(this,
- params.bounds,
- params.item_height,
- params.item_font_size,
- params.selected_item,
- params.popup_items,
- params.right_aligned,
+ gfx::Point original_point(params.bounds.x(), params.bounds.y());
+ gfx::Point transformed_point =
+ static_cast<RenderWidgetHostViewBase*>(GetView())
+ ->TransformPointToRootCoordSpace(original_point);
+ gfx::Rect transformed_bounds(transformed_point.x(), transformed_point.y(),
+ params.bounds.width(), params.bounds.height());
+ view->ShowPopupMenu(this, transformed_bounds, params.item_height,
+ params.item_font_size, params.selected_item,
+ params.popup_items, params.right_aligned,
params.allow_multiple_selection);
}
}
@@ -1761,11 +1865,17 @@ void RenderFrameHostImpl::RegisterMojoServices() {
// TODO(creis): Bind process ID here so that GeolocationServiceImpl
// can perform permissions checks once site isolation is complete.
// crbug.com/426384
- GetServiceRegistry()->AddService<GeolocationService>(
+ // NOTE: At shutdown, there is no guaranteed ordering between destruction of
+ // this object and destruction of any GeolocationServicesImpls created via
+ // the below service registry, the reason being that the destruction of the
+ // latter is triggered by receiving a message that the pipe was closed from
+ // the renderer side. Hence, supply the reference to this object as a weak
+ // pointer.
+ GetServiceRegistry()->AddService(
base::Bind(&GeolocationServiceContext::CreateService,
base::Unretained(geolocation_service_context),
base::Bind(&RenderFrameHostImpl::DidUseGeolocationPermission,
- base::Unretained(this))));
+ weak_ptr_factory_.GetWeakPtr())));
}
WakeLockServiceContext* wake_lock_service_context =
@@ -1774,7 +1884,7 @@ void RenderFrameHostImpl::RegisterMojoServices() {
// WakeLockServiceContext is owned by WebContentsImpl so it will outlive
// this RenderFrameHostImpl, hence a raw pointer can be bound to service
// factory callback.
- GetServiceRegistry()->AddService<WakeLockService>(
+ GetServiceRegistry()->AddService<mojom::WakeLockService>(
base::Bind(&WakeLockServiceContext::CreateService,
base::Unretained(wake_lock_service_context),
GetProcess()->GetID(), GetRoutingID()));
@@ -1783,18 +1893,29 @@ void RenderFrameHostImpl::RegisterMojoServices() {
if (!permission_service_context_)
permission_service_context_.reset(new PermissionServiceContext(this));
- GetServiceRegistry()->AddService<PermissionService>(
+ GetServiceRegistry()->AddService(
base::Bind(&PermissionServiceContext::CreateService,
base::Unretained(permission_service_context_.get())));
- GetServiceRegistry()->AddService<presentation::PresentationService>(
- base::Bind(&PresentationServiceImpl::CreateMojoService,
- base::Unretained(this)));
+ GetServiceRegistry()->AddService(base::Bind(
+ &PresentationServiceImpl::CreateMojoService, base::Unretained(this)));
+
+ bool enable_web_bluetooth = base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableWebBluetooth);
+#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
+ enable_web_bluetooth = true;
+#endif
+
+ if (enable_web_bluetooth) {
+ GetServiceRegistry()->AddService(
+ base::Bind(&RenderFrameHostImpl::CreateWebBluetoothService,
+ base::Unretained(this)));
+ }
if (!frame_mojo_shell_)
frame_mojo_shell_.reset(new FrameMojoShell(this));
- GetServiceRegistry()->AddService<mojo::Shell>(base::Bind(
+ GetServiceRegistry()->AddService<mojo::shell::mojom::Connector>(base::Bind(
&FrameMojoShell::BindRequest, base::Unretained(frame_mojo_shell_.get())));
#if defined(ENABLE_WEBVR)
@@ -1802,8 +1923,7 @@ void RenderFrameHostImpl::RegisterMojoServices() {
*base::CommandLine::ForCurrentProcess();
if (browser_command_line.HasSwitch(switches::kEnableWebVR)) {
- GetServiceRegistry()->AddService<VRService>(
- base::Bind(&VRDeviceManager::BindRequest));
+ GetServiceRegistry()->AddService(base::Bind(&VRDeviceManager::BindRequest));
}
#endif
@@ -1811,43 +1931,26 @@ void RenderFrameHostImpl::RegisterMojoServices() {
GetServiceRegistry(), this);
}
-void RenderFrameHostImpl::SetState(RenderFrameHostImplState rfh_state) {
- // Only main frames should be swapped out and retained inside a proxy host.
- if (rfh_state == STATE_SWAPPED_OUT)
- CHECK(!GetParent());
+void RenderFrameHostImpl::ResetWaitingState() {
+ DCHECK(is_active());
- // We update the number of RenderFrameHosts in a SiteInstance when the swapped
- // out status of a RenderFrameHost gets flipped to/from active.
- if (!IsRFHStateActive(rfh_state_) && IsRFHStateActive(rfh_state))
- GetSiteInstance()->IncrementActiveFrameCount();
- else if (IsRFHStateActive(rfh_state_) && !IsRFHStateActive(rfh_state))
- GetSiteInstance()->DecrementActiveFrameCount();
-
- // The active and swapped out state of the RVH is determined by its main
- // frame, since subframes should have their own widgets.
+ // The active state of the RVH is determined by its main frame, since
+ // subframes should have their own widgets.
if (frame_tree_node_->IsMainFrame()) {
- render_view_host_->set_is_active(IsRFHStateActive(rfh_state));
- render_view_host_->set_is_swapped_out(rfh_state == STATE_SWAPPED_OUT);
- }
-
- // Whenever we change the RFH state to and from active or swapped out state,
- // we should not be waiting for beforeunload or close acks. We clear them
- // here to be safe, since they can cause navigations to be ignored in
- // OnDidCommitProvisionalLoad.
- // TODO(creis): Move is_waiting_for_beforeunload_ack_ into the state machine.
- if (rfh_state == STATE_DEFAULT ||
- rfh_state == STATE_SWAPPED_OUT ||
- rfh_state_ == STATE_DEFAULT ||
- rfh_state_ == STATE_SWAPPED_OUT) {
- if (is_waiting_for_beforeunload_ack_) {
- is_waiting_for_beforeunload_ack_ = false;
- render_view_host_->GetWidget()->decrement_in_flight_event_count();
- render_view_host_->GetWidget()->StopHangMonitorTimeout();
- }
- send_before_unload_start_time_ = base::TimeTicks();
- render_view_host_->is_waiting_for_close_ack_ = false;
+ render_view_host_->set_is_active(true);
+ render_view_host_->set_is_swapped_out(false);
}
- rfh_state_ = rfh_state;
+
+ // Whenever we reset the RFH state, we should not be waiting for beforeunload
+ // or close acks. We clear them here to be safe, since they can cause
+ // navigations to be ignored in OnDidCommitProvisionalLoad.
+ if (is_waiting_for_beforeunload_ack_) {
+ is_waiting_for_beforeunload_ack_ = false;
+ render_view_host_->GetWidget()->decrement_in_flight_event_count();
+ render_view_host_->GetWidget()->StopHangMonitorTimeout();
+ }
+ send_before_unload_start_time_ = base::TimeTicks();
+ render_view_host_->is_waiting_for_close_ack_ = false;
}
bool RenderFrameHostImpl::CanCommitURL(const GURL& url) {
@@ -1859,6 +1962,42 @@ bool RenderFrameHostImpl::CanCommitURL(const GURL& url) {
return GetContentClient()->browser()->CanCommitURL(GetProcess(), url);
}
+bool RenderFrameHostImpl::CanCommitOrigin(
+ const url::Origin& origin,
+ const GURL& url) {
+ // If the --disable-web-security flag is specified, all bets are off and the
+ // renderer process can send any origin it wishes.
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableWebSecurity)) {
+ return true;
+ }
+
+ // file: URLs can be allowed to access any other origin, based on settings.
+ if (origin.scheme() == url::kFileScheme) {
+ WebPreferences prefs = render_view_host_->GetWebkitPreferences();
+ if (prefs.allow_universal_access_from_file_urls)
+ return true;
+ }
+
+ // It is safe to commit into a unique origin, regardless of the URL, as it is
+ // restricted from accessing other origins.
+ if (origin.unique())
+ return true;
+
+ // Standard URLs must match the reported origin.
+ if (url.IsStandard() && !origin.IsSameOriginWith(url::Origin(url)))
+ return false;
+
+ // A non-unique origin must be a valid URL, which allows us to safely do a
+ // conversion to GURL.
+ GURL origin_url(origin.Serialize());
+
+ // Verify that the origin is allowed to commit in this process.
+ // Note: This also handles non-standard cases for |url|, such as
+ // about:blank, data, and blob URLs.
+ return CanCommitURL(origin_url);
+}
+
void RenderFrameHostImpl::Navigate(
const CommonNavigationParams& common_params,
const StartNavigationParams& start_params,
@@ -1877,8 +2016,8 @@ void RenderFrameHostImpl::Navigate(
new NavigationParams(common_params, start_params, request_params));
} else {
// Get back to a clean state, in case we start a new navigation without
- // completing a RFH swap or unload handler.
- SetState(RenderFrameHostImpl::STATE_DEFAULT);
+ // completing an unload handler.
+ ResetWaitingState();
SendNavigateMessage(common_params, start_params, request_params);
}
@@ -1894,7 +2033,7 @@ void RenderFrameHostImpl::Navigate(
// Blink doesn't send throb notifications for JavaScript URLs, so it is not
// done here either.
if (!common_params.url.SchemeIs(url::kJavaScriptScheme))
- frame_tree_node_->DidStartLoading(true);
+ OnDidStartLoading(true);
}
void RenderFrameHostImpl::NavigateToInterstitialURL(const GURL& data_url) {
@@ -1903,10 +2042,10 @@ void RenderFrameHostImpl::NavigateToInterstitialURL(const GURL& data_url) {
data_url, Referrer(), ui::PAGE_TRANSITION_LINK,
FrameMsg_Navigate_Type::NORMAL, false, false, base::TimeTicks::Now(),
FrameMsg_UILoadMetricsReportType::NO_REPORT, GURL(), GURL(), LOFI_OFF,
- base::TimeTicks::Now());
+ base::TimeTicks::Now(), "GET");
if (IsBrowserSideNavigationEnabled()) {
- CommitNavigation(nullptr, nullptr, common_params,
- RequestNavigationParams());
+ CommitNavigation(nullptr, nullptr, common_params, RequestNavigationParams(),
+ false);
} else {
Navigate(common_params, StartNavigationParams(), RequestNavigationParams());
}
@@ -2036,34 +2175,46 @@ void RenderFrameHostImpl::CommitNavigation(
ResourceResponse* response,
scoped_ptr<StreamHandle> body,
const CommonNavigationParams& common_params,
- const RequestNavigationParams& request_params) {
+ const RequestNavigationParams& request_params,
+ bool is_view_source) {
DCHECK((response && body.get()) ||
!ShouldMakeNetworkRequestForURL(common_params.url));
UpdatePermissionsForNavigation(common_params, request_params);
// Get back to a clean state, in case we start a new navigation without
- // completing a RFH swap or unload handler.
- SetState(RenderFrameHostImpl::STATE_DEFAULT);
+ // completing an unload handler.
+ ResetWaitingState();
+
+ // The renderer can exit view source mode when any error or cancellation
+ // happen. When reusing the same renderer, overwrite to recover the mode.
+ if (is_view_source &&
+ this == frame_tree_node_->render_manager()->current_frame_host()) {
+ DCHECK(!GetParent());
+ render_view_host()->Send(new FrameMsg_EnableViewSourceMode(routing_id_));
+ }
const GURL body_url = body.get() ? body->GetURL() : GURL();
const ResourceResponseHead head = response ?
response->head : ResourceResponseHead();
Send(new FrameMsg_CommitNavigation(routing_id_, head, body_url, common_params,
request_params));
- // TODO(clamy): Check if we should start the throbber for non javascript urls
- // here.
+
+ // If a network request was made, update the LoFi state.
+ if (ShouldMakeNetworkRequestForURL(common_params.url))
+ last_navigation_lofi_state_ = common_params.lofi_state;
// TODO(clamy): Release the stream handle once the renderer has finished
// reading it.
stream_handle_ = std::move(body);
// When navigating to a Javascript url, no commit is expected from the
- // RenderFrameHost, nor should the throbber start.
+ // RenderFrameHost, nor should the throbber start. The NavigationRequest is
+ // also not stored in the FrameTreeNode. Therefore do not reset it, as this
+ // could cancel an existing pending navigation.
if (!common_params.url.SchemeIs(url::kJavaScriptScheme)) {
pending_commit_ = true;
is_loading_ = true;
}
- frame_tree_node_->ResetNavigationRequest(true);
}
void RenderFrameHostImpl::FailedNavigation(
@@ -2072,8 +2223,8 @@ void RenderFrameHostImpl::FailedNavigation(
bool has_stale_copy_in_cache,
int error_code) {
// Get back to a clean state, in case a new navigation started without
- // completing a RFH swap or unload handler.
- SetState(RenderFrameHostImpl::STATE_DEFAULT);
+ // completing an unload handler.
+ ResetWaitingState();
Send(new FrameMsg_FailedNavigation(routing_id_, common_params, request_params,
has_stale_copy_in_cache, error_code));
@@ -2092,21 +2243,21 @@ void RenderFrameHostImpl::SetUpMojoIfNeeded() {
return;
RegisterMojoServices();
- RenderFrameSetupPtr setup;
+ mojom::RenderFrameSetupPtr setup;
GetProcess()->GetServiceRegistry()->ConnectToRemoteService(
mojo::GetProxy(&setup));
- mojo::ServiceProviderPtr exposed_services;
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services;
service_registry_->Bind(GetProxy(&exposed_services));
- mojo::ServiceProviderPtr services;
- setup->ExchangeServiceProviders(routing_id_, GetProxy(&services),
- std::move(exposed_services));
+ mojo::shell::mojom::InterfaceProviderPtr services;
+ setup->ExchangeInterfaceProviders(routing_id_, GetProxy(&services),
+ std::move(exposed_services));
service_registry_->BindRemoteServiceProvider(std::move(services));
#if defined(OS_ANDROID)
- service_registry_android_.reset(
- new ServiceRegistryAndroid(service_registry_.get()));
+ service_registry_android_ =
+ ServiceRegistryAndroid::Create(service_registry_.get());
ServiceRegistrarAndroid::RegisterFrameHostServices(
service_registry_android_.get());
#endif
@@ -2226,7 +2377,7 @@ void RenderFrameHostImpl::ClearAllWebUI() {
web_ui_.reset();
}
-const image_downloader::ImageDownloaderPtr&
+const content::mojom::ImageDownloaderPtr&
RenderFrameHostImpl::GetMojoImageDownloader() {
if (!mojo_image_downloader_.get() && GetServiceRegistry()) {
GetServiceRegistry()->ConnectToRemoteService(
@@ -2235,6 +2386,22 @@ RenderFrameHostImpl::GetMojoImageDownloader() {
return mojo_image_downloader_;
}
+void RenderFrameHostImpl::ResetLoadingState() {
+ if (is_loading()) {
+ // When pending deletion, just set the loading state to not loading.
+ // Otherwise, OnDidStopLoading will take care of that, as well as sending
+ // notification to the FrameTreeNode about the change in loading state.
+ if (!is_active())
+ is_loading_ = false;
+ else
+ OnDidStopLoading();
+ }
+}
+
+void RenderFrameHostImpl::SuppressFurtherDialogs() {
+ Send(new FrameMsg_SuppressFurtherDialogs(GetRoutingID()));
+}
+
bool RenderFrameHostImpl::IsSameSiteInstance(
RenderFrameHostImpl* other_render_frame_host) {
// As a sanity check, make sure the frame belongs to the same BrowserContext.
@@ -2256,10 +2423,31 @@ void RenderFrameHostImpl::RequestAXTreeSnapshot(
}
void RenderFrameHostImpl::SetAccessibilityCallbackForTesting(
- const base::Callback<void(ui::AXEvent, int)>& callback) {
+ const base::Callback<void(RenderFrameHostImpl*, ui::AXEvent, int)>&
+ callback) {
accessibility_testing_callback_ = callback;
}
+void RenderFrameHostImpl::UpdateAXTreeData() {
+ AccessibilityMode accessibility_mode = delegate_->GetAccessibilityMode();
+ if (accessibility_mode == AccessibilityModeOff || !is_active()) {
+ return;
+ }
+
+ std::vector<AXEventNotificationDetails> details;
+ details.reserve(1U);
+ AXEventNotificationDetails detail;
+ detail.ax_tree_id = GetAXTreeID();
+ detail.update.has_tree_data = true;
+ AXContentTreeDataToAXTreeData(&detail.update.tree_data);
+ details.push_back(detail);
+
+ if (browser_accessibility_manager_)
+ browser_accessibility_manager_->OnAccessibilityEvents(details);
+
+ delegate_->AccessibilityEventReceived(details);
+}
+
void RenderFrameHostImpl::SetTextTrackSettings(
const FrameMsg_TextTrackSettings_Params& params) {
DCHECK(!GetParent());
@@ -2276,8 +2464,9 @@ BrowserAccessibilityManager*
if (view &&
!browser_accessibility_manager_ &&
!no_create_browser_accessibility_manager_for_testing_) {
+ bool is_root_frame = !frame_tree_node()->parent();
browser_accessibility_manager_.reset(
- view->CreateBrowserAccessibilityManager(this));
+ view->CreateBrowserAccessibilityManager(this, is_root_frame));
if (browser_accessibility_manager_)
UMA_HISTOGRAM_COUNTS("Accessibility.FrameEnabledCount", 1);
else
@@ -2314,22 +2503,13 @@ bool RenderFrameHostImpl::IsRenderFrameLive() {
return is_live;
}
-#if defined(OS_WIN)
-
-void RenderFrameHostImpl::SetParentNativeViewAccessible(
- gfx::NativeViewAccessible accessible_parent) {
- RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
- render_view_host_->GetWidget()->GetView());
- if (view)
- view->SetParentNativeViewAccessible(accessible_parent);
+int RenderFrameHostImpl::GetProxyCount() {
+ if (this != frame_tree_node_->current_frame_host())
+ return 0;
+ return frame_tree_node_->render_manager()->GetProxyCount();
}
-gfx::NativeViewAccessible
-RenderFrameHostImpl::GetParentNativeViewAccessible() const {
- return delegate_->GetParentNativeViewAccessible();
-}
-
-#elif defined(OS_MACOSX)
+#if defined(OS_MACOSX)
void RenderFrameHostImpl::DidSelectPopupMenuItem(int selected_index) {
Send(new FrameMsg_SelectPopupMenuItem(routing_id_, selected_index));
@@ -2341,6 +2521,17 @@ void RenderFrameHostImpl::DidCancelPopupMenu() {
#elif defined(OS_ANDROID)
+void RenderFrameHostImpl::ActivateNearestFindResult(int request_id,
+ float x,
+ float y) {
+ Send(
+ new InputMsg_ActivateNearestFindResult(GetRoutingID(), request_id, x, y));
+}
+
+void RenderFrameHostImpl::RequestFindMatchRects(int current_version) {
+ Send(new FrameMsg_FindMatchRects(GetRoutingID(), current_version));
+}
+
void RenderFrameHostImpl::DidSelectPopupMenuItems(
const std::vector<int>& selected_indices) {
Send(new FrameMsg_SelectPopupMenuItems(routing_id_, false, selected_indices));
@@ -2370,9 +2561,8 @@ void RenderFrameHostImpl::SetNavigationsSuspended(
if (!suspend && suspended_nav_params_) {
// There's navigation message params waiting to be sent. Now that we're not
- // suspended anymore, resume navigation by sending them. If we were swapped
- // out, we should also stop filtering out the IPC messages now.
- SetState(RenderFrameHostImpl::STATE_DEFAULT);
+ // suspended anymore, resume navigation by sending them.
+ ResetWaitingState();
DCHECK(!proceed_time.is_null());
// TODO(csharrison): Make sure that PlzNavigate and the current architecture
@@ -2414,9 +2604,9 @@ void RenderFrameHostImpl::DidUseGeolocationPermission() {
permission_manager->RegisterPermissionUsage(
PermissionType::GEOLOCATION,
- GetLastCommittedURL().GetOrigin(),
+ last_committed_url().GetOrigin(),
frame_tree_node()->frame_tree()->GetMainFrame()
- ->GetLastCommittedURL().GetOrigin());
+ ->last_committed_url().GetOrigin());
}
void RenderFrameHostImpl::UpdatePermissionsForNavigation(
@@ -2488,11 +2678,13 @@ AXTreeIDRegistry::AXTreeID RenderFrameHostImpl::RoutingIDToAXTreeID(
AXTreeIDRegistry::AXTreeID
RenderFrameHostImpl::BrowserPluginInstanceIDToAXTreeID(
int instance_id) {
- RenderFrameHost* guest = delegate()->GetGuestByInstanceID(
- this, instance_id);
+ RenderFrameHostImpl* guest = static_cast<RenderFrameHostImpl*>(
+ delegate()->GetGuestByInstanceID(this, instance_id));
if (!guest)
return AXTreeIDRegistry::kNoAXTreeID;
+ guest->set_browser_plugin_embedder_ax_tree_id(GetAXTreeID());
+
return guest->GetAXTreeID();
}
@@ -2525,8 +2717,9 @@ void RenderFrameHostImpl::AXContentNodeDataToAXNodeData(
}
void RenderFrameHostImpl::AXContentTreeDataToAXTreeData(
- const AXContentTreeData& src,
ui::AXTreeData* dst) {
+ const AXContentTreeData& src = ax_content_tree_data_;
+
// Copy the common fields.
*dst = src;
@@ -2535,6 +2728,29 @@ void RenderFrameHostImpl::AXContentTreeDataToAXTreeData(
if (src.parent_routing_id != -1)
dst->parent_tree_id = RoutingIDToAXTreeID(src.parent_routing_id);
+
+ if (browser_plugin_embedder_ax_tree_id_ != AXTreeIDRegistry::kNoAXTreeID)
+ dst->parent_tree_id = browser_plugin_embedder_ax_tree_id_;
+
+ // If this is not the root frame tree node, we're done.
+ if (frame_tree_node()->parent())
+ return;
+
+ // For the root frame tree node, also store the AXTreeID of the focused frame.
+ FrameTreeNode* focused_frame_tree_node = frame_tree_->GetFocusedFrame();
+ if (!focused_frame_tree_node)
+ return;
+ RenderFrameHostImpl* focused_frame =
+ focused_frame_tree_node->current_frame_host();
+ DCHECK(focused_frame);
+ dst->focused_tree_id = focused_frame->GetAXTreeID();
+}
+
+void RenderFrameHostImpl::CreateWebBluetoothService(
+ blink::mojom::WebBluetoothServiceRequest request) {
+ DCHECK(!web_bluetooth_service_);
+ web_bluetooth_service_.reset(
+ new WebBluetoothServiceImpl(this, std::move(request)));
}
} // namespace content
diff --git a/chromium/content/browser/frame_host/render_frame_host_impl.h b/chromium/content/browser/frame_host/render_frame_host_impl.h
index b457a076e55..7376f298f58 100644
--- a/chromium/content/browser/frame_host/render_frame_host_impl.h
+++ b/chromium/content/browser/frame_host/render_frame_host_impl.h
@@ -23,6 +23,7 @@
#include "build/build_config.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/bad_message.h"
+#include "content/browser/loader/global_routing_id.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/webui/web_ui_impl.h"
#include "content/common/accessibility_mode_enums.h"
@@ -43,7 +44,7 @@
#include "ui/base/page_transition_types.h"
#if defined(OS_ANDROID)
-#include "content/browser/mojo/service_registry_android.h"
+#include "content/public/browser/android/service_registry_android.h"
#endif
class GURL;
@@ -62,6 +63,12 @@ class FilePath;
class ListValue;
}
+namespace blink {
+namespace mojom {
+class WebBluetoothService;
+}
+}
+
namespace content {
class CrossProcessFrameConnector;
@@ -82,47 +89,20 @@ class RenderWidgetHostViewBase;
class ResourceRequestBody;
class StreamHandle;
class TimeoutMonitor;
+class WebBluetoothServiceImpl;
struct ContextMenuParams;
struct GlobalRequestID;
struct Referrer;
struct ResourceResponse;
-// Flag arguments for RenderFrameHost creation.
-enum CreateRenderFrameFlags {
- // The RFH will be initially placed on the swapped out hosts list.
- CREATE_RF_SWAPPED_OUT = 1 << 0,
- // The RenderFrame is initially hidden.
- CREATE_RF_HIDDEN = 1 << 1,
-};
-
-class CONTENT_EXPORT RenderFrameHostImpl
- : public RenderFrameHost,
- public BrowserAccessibilityDelegate {
+class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost,
+ public BrowserAccessibilityDelegate,
+ public SiteInstanceImpl::Observer {
public:
using AXTreeSnapshotCallback =
base::Callback<void(
const ui::AXTreeUpdate&)>;
- // Keeps track of the state of the RenderFrameHostImpl, particularly with
- // respect to swap out.
- enum RenderFrameHostImplState {
- // The standard state for a RFH handling the communication with an active
- // RenderFrame.
- STATE_DEFAULT = 0,
- // The RFH has not received the SwapOutACK yet, but the new page has
- // committed in a different RFH. Upon reception of the SwapOutACK, the RFH
- // will either enter STATE_SWAPPED_OUT (if it is a main frame and there are
- // other active frames in its SiteInstance) or it will be deleted.
- STATE_PENDING_SWAP_OUT,
- // The RFH is swapped out and stored inside a RenderFrameProxyHost, being
- // used as a placeholder to allow cross-process communication. Only main
- // frames can enter this state.
- STATE_SWAPPED_OUT,
- };
- // Helper function to determine whether the RFH state should contribute to the
- // number of active frames of a SiteInstance or not.
- static bool IsRFHStateActive(RenderFrameHostImplState rfh_state);
-
// An accessibility reset is only allowed to prevent very rare corner cases
// or race conditions where the browser and renderer get out of sync. If
// this happens more than this many times, kill the renderer.
@@ -139,11 +119,12 @@ class CONTENT_EXPORT RenderFrameHostImpl
AXTreeIDRegistry::AXTreeID GetAXTreeID() override;
SiteInstanceImpl* GetSiteInstance() override;
RenderProcessHost* GetProcess() override;
- RenderFrameHost* GetParent() override;
+ RenderWidgetHostView* GetView() override;
+ RenderFrameHostImpl* GetParent() override;
int GetFrameTreeNodeId() override;
const std::string& GetFrameName() override;
bool IsCrossProcessSubframe() override;
- GURL GetLastCommittedURL() override;
+ const GURL& GetLastCommittedURL() override;
url::Origin GetLastCommittedOrigin() override;
gfx::NativeView GetNativeView() override;
void AddMessageToConsole(ConsoleMessageLevel level,
@@ -151,23 +132,27 @@ class CONTENT_EXPORT RenderFrameHostImpl
void ExecuteJavaScript(const base::string16& javascript) override;
void ExecuteJavaScript(const base::string16& javascript,
const JavaScriptResultCallback& callback) override;
+ void ExecuteJavaScriptInIsolatedWorld(
+ const base::string16& javascript,
+ const JavaScriptResultCallback& callback,
+ int world_id) override;
void ExecuteJavaScriptForTests(const base::string16& javascript) override;
void ExecuteJavaScriptForTests(
const base::string16& javascript,
const JavaScriptResultCallback& callback) override;
void ExecuteJavaScriptWithUserGestureForTests(
const base::string16& javascript) override;
- void ExecuteJavaScriptInIsolatedWorld(
- const base::string16& javascript,
- const JavaScriptResultCallback& callback,
- int world_id) override;
void ActivateFindInPageResultForAccessibility(int request_id) override;
+ void InsertVisualStateCallback(const VisualStateCallback& callback) override;
RenderViewHost* GetRenderViewHost() override;
ServiceRegistry* GetServiceRegistry() override;
blink::WebPageVisibilityState GetVisibilityState() override;
- void InsertVisualStateCallback(
- const VisualStateCallback& callback) override;
bool IsRenderFrameLive() override;
+ int GetProxyCount() override;
+#if defined(OS_ANDROID)
+ void ActivateNearestFindResult(int request_id, float x, float y) override;
+ void RequestFindMatchRects(int current_version) override;
+#endif
// IPC::Sender
bool Send(IPC::Message* msg) override;
@@ -195,12 +180,18 @@ class CONTENT_EXPORT RenderFrameHostImpl
gfx::Rect AccessibilityGetViewBounds() const override;
gfx::Point AccessibilityOriginInScreen(
const gfx::Rect& bounds) const override;
+ gfx::Rect AccessibilityTransformToRootCoordSpace(
+ const gfx::Rect& bounds) override;
+ SiteInstance* AccessibilityGetSiteInstance() override;
void AccessibilityHitTest(const gfx::Point& point) override;
void AccessibilitySetAccessibilityFocus(int acc_obj_id) override;
void AccessibilityFatalError() override;
gfx::AcceleratedWidget AccessibilityGetAcceleratedWidget() override;
gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible() override;
+ // SiteInstanceImpl::Observer
+ void RenderProcessGone(SiteInstanceImpl* site_instance) override;
+
// Creates a RenderFrame in the renderer process.
bool CreateRenderFrame(int proxy_routing_id,
int opener_routing_id,
@@ -221,6 +212,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
int new_routing_id,
blink::WebTreeScopeType scope,
const std::string& frame_name,
+ const std::string& frame_unique_name,
blink::WebSandboxFlags sandbox_flags,
const blink::WebFrameOwnerProperties& frame_owner_properties);
@@ -228,6 +220,22 @@ class CONTENT_EXPORT RenderFrameHostImpl
RenderFrameHostDelegate* delegate() { return delegate_; }
FrameTreeNode* frame_tree_node() { return frame_tree_node_; }
+ const GURL& last_committed_url() const { return last_committed_url_; }
+
+ // Allows FrameTreeNode::SetCurrentURL to update this frame's last committed
+ // URL. Do not call this directly, since we rely on SetCurrentURL to track
+ // whether a real load has committed or not.
+ void set_last_committed_url(const GURL& url) {
+ last_committed_url_ = url;
+ }
+
+ // The most recent non-net-error URL to commit in this frame. In almost all
+ // cases, use GetLastCommittedURL instead.
+ const GURL& last_successful_url() { return last_successful_url_; }
+ void set_last_successful_url(const GURL& url) {
+ last_successful_url_ = url;
+ }
+
// Returns the associated WebUI or null if none applies.
WebUIImpl* web_ui() const { return web_ui_.get(); }
@@ -241,15 +249,19 @@ class CONTENT_EXPORT RenderFrameHostImpl
// call FrameTreeNode::IsLoading.
bool is_loading() const { return is_loading_; }
+ // Sets this RenderFrameHost loading state. This is only used in the case of
+ // transfer navigations, where no DidStart/DidStopLoading notifications
+ // should be sent during the transfer.
+ // TODO(clamy): Remove this once PlzNavigate ships.
+ void set_is_loading(bool is_loading) { is_loading_ = is_loading; }
+
// This returns the RenderFrameHost's owned RenderWidgetHost if it has one,
// or else it returns nullptr.
// If the RenderFrameHost is the page's main frame, this returns instead a
// pointer to the RenderViewHost (which inherits RenderWidgetHost).
RenderWidgetHostImpl* GetRenderWidgetHost();
- // This returns the RenderWidgetHostView that can be used to control
- // focus and visibility for this frame.
- RenderWidgetHostView* GetView();
+ GlobalFrameRoutingId GetGlobalFrameRoutingId();
// This function is called when this is a swapped out RenderFrameHost that
// lives in the same process as the parent frame. The
@@ -332,12 +344,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
// out.
void OnSwappedOut();
- // Whether this RenderFrameHost has been swapped out, such that the frame is
- // now rendered by a RenderFrameHost in a different process.
- bool is_swapped_out() const { return rfh_state_ == STATE_SWAPPED_OUT; }
-
- // The current state of this RFH.
- RenderFrameHostImplState rfh_state() const { return rfh_state_; }
+ // This method returns true from the time this RenderFrameHost is created
+ // until SwapOut is called, at which point it is pending deletion.
+ bool is_active() { return !is_waiting_for_swapout_ack_; }
// Sends the given navigation message. Use this rather than sending it
// yourself since this does the internal bookkeeping described below. This
@@ -435,7 +444,19 @@ class CONTENT_EXPORT RenderFrameHostImpl
// renderer process, and the accessibility tree it sent can be
// retrieved using GetAXTreeForTesting().
void SetAccessibilityCallbackForTesting(
- const base::Callback<void(ui::AXEvent, int)>& callback);
+ const base::Callback<void(RenderFrameHostImpl*, ui::AXEvent, int)>&
+ callback);
+
+ // Called when the metadata about the accessibility tree for this frame
+ // changes due to a browser-side change, as opposed to due to an IPC from
+ // a renderer.
+ void UpdateAXTreeData();
+
+ // Set the AX tree ID of the embedder RFHI, if this is a browser plugin guest.
+ void set_browser_plugin_embedder_ax_tree_id(
+ AXTreeIDRegistry::AXTreeID ax_tree_id) {
+ browser_plugin_embedder_ax_tree_id_ = ax_tree_id;
+ }
// Send a message to the render process to change text track style settings.
void SetTextTrackSettings(const FrameMsg_TextTrackSettings_Params& params);
@@ -459,11 +480,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
no_create_browser_accessibility_manager_for_testing_ = flag;
}
-#if defined(OS_WIN)
- void SetParentNativeViewAccessible(
- gfx::NativeViewAccessible accessible_parent);
- gfx::NativeViewAccessible GetParentNativeViewAccessible() const;
-#elif defined(OS_MACOSX)
+#if defined(OS_MACOSX)
// Select popup menu related methods (for external popup menus).
void DidSelectPopupMenuItem(int selected_index);
void DidCancelPopupMenu();
@@ -477,7 +494,8 @@ class CONTENT_EXPORT RenderFrameHostImpl
void CommitNavigation(ResourceResponse* response,
scoped_ptr<StreamHandle> body,
const CommonNavigationParams& common_params,
- const RequestNavigationParams& request_params);
+ const RequestNavigationParams& request_params,
+ bool is_view_source);
// PlzNavigate
// Indicates that a navigation failed and that this RenderFrame should display
@@ -521,7 +539,23 @@ class CONTENT_EXPORT RenderFrameHostImpl
void ClearAllWebUI();
// Returns the Mojo ImageDownloader service.
- const image_downloader::ImageDownloaderPtr& GetMojoImageDownloader();
+ const content::mojom::ImageDownloaderPtr& GetMojoImageDownloader();
+
+ // Resets the loading state. Following this call, the RenderFrameHost will be
+ // in a non-loading state.
+ void ResetLoadingState();
+
+ // Tells the renderer that this RenderFrame will soon be swapped out, and thus
+ // not to create any new modal dialogs until it happens. This must be done
+ // separately so that the ScopedPageLoadDeferrers of any current dialogs are
+ // no longer on the stack when we attempt to swap it out.
+ void SuppressFurtherDialogs();
+
+ // PlzNavigate: returns the LoFi state of the last successful navigation that
+ // made a network request.
+ LoFiState last_navigation_lofi_state() const {
+ return last_navigation_lofi_state_;
+ }
protected:
friend class RenderFrameHostFactory;
@@ -538,13 +572,19 @@ class CONTENT_EXPORT RenderFrameHostImpl
FrameTreeNode* frame_tree_node,
int32_t routing_id,
int32_t widget_routing_id,
- int flags);
+ bool hidden);
private:
friend class TestRenderFrameHost;
friend class TestRenderViewHost;
+ FRIEND_TEST_ALL_PREFIXES(RenderFrameHostManagerTest,
+ CreateRenderViewAfterProcessKillAndClosedProxy);
+ FRIEND_TEST_ALL_PREFIXES(RenderFrameHostManagerTest,
+ RenderViewInitAfterNewProxyAndProcessKill);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest, CrashSubframe);
+ FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
+ RenderViewHostPendingDeletionIsNotReused);
// IPC Message handlers.
void OnAddMessageToConsole(int32_t level,
@@ -568,7 +608,6 @@ class CONTENT_EXPORT RenderFrameHostImpl
const base::string16& error_description,
bool was_ignored_by_handler);
void OnDidCommitProvisionalLoad(const IPC::Message& msg);
- void OnDidDropNavigation();
void OnUpdateState(const PageState& state);
void OnBeforeUnloadACK(
bool proceed,
@@ -585,16 +624,16 @@ class CONTENT_EXPORT RenderFrameHostImpl
JavaScriptMessageType type,
IPC::Message* reply_msg);
void OnRunBeforeUnloadConfirm(const GURL& frame_url,
- const base::string16& message,
bool is_reload,
IPC::Message* reply_msg);
void OnTextSurroundingSelectionResponse(const base::string16& content,
- size_t start_offset,
- size_t end_offset);
+ uint32_t start_offset,
+ uint32_t end_offset);
void OnDidAccessInitialDocument();
void OnDidChangeOpener(int32_t opener_routing_id);
- void OnDidChangeName(const std::string& name);
+ void OnDidChangeName(const std::string& name, const std::string& unique_name);
void OnEnforceStrictMixedContentChecking();
+ void OnUpdateToUniqueOrigin(bool is_potentially_trustworthy_unique_origin);
void OnDidAssignPageId(int32_t page_id);
void OnDidChangeSandboxFlags(int32_t frame_routing_id,
blink::WebSandboxFlags flags);
@@ -615,6 +654,8 @@ class CONTENT_EXPORT RenderFrameHostImpl
const std::vector<AccessibilityHostMsg_LocationChangeParams>& params);
void OnAccessibilityFindInPageResult(
const AccessibilityHostMsg_FindInPageResultParams& params);
+ void OnAccessibilityChildFrameHitTestResult(const gfx::Point& point,
+ int hit_obj_id);
void OnAccessibilitySnapshotResponse(
int callback_id,
const AXContentTreeUpdate& snapshot);
@@ -635,15 +676,22 @@ class CONTENT_EXPORT RenderFrameHostImpl
// Registers Mojo services that this frame host makes available.
void RegisterMojoServices();
- // Updates the state of this RenderFrameHost and clears any waiting state
- // that is no longer relevant.
- void SetState(RenderFrameHostImplState rfh_state);
+ // Resets any waiting state of this RenderFrameHost that is no longer
+ // relevant.
+ void ResetWaitingState();
// Returns whether the given URL is allowed to commit in the current process.
// This is a more conservative check than RenderProcessHost::FilterURL, since
// it will be used to kill processes that commit unauthorized URLs.
bool CanCommitURL(const GURL& url);
+ // Returns whether the given origin is allowed to commit in the current
+ // RenderFrameHost. The |url| is used to ensure it matches the origin in cases
+ // where it is applicable. This is a more conservative check than
+ // RenderProcessHost::FilterURL, since it will be used to kill processes that
+ // commit unauthorized origins.
+ bool CanCommitOrigin(const url::Origin& origin, const GURL& url);
+
// Asserts that the given RenderFrameHostImpl is part of the same browser
// context (and crashes if not), then returns whether the given frame is
// part of the same site instance.
@@ -674,8 +722,7 @@ class CONTENT_EXPORT RenderFrameHostImpl
// Convert the content-layer-specific AXContentTreeData to a general-purpose
// AXTreeData structure.
- void AXContentTreeDataToAXTreeData(const AXContentTreeData& src,
- ui::AXTreeData* dst);
+ void AXContentTreeDataToAXTreeData(ui::AXTreeData* dst);
// Returns the RenderWidgetHostView used for accessibility. For subframes,
// this function will return the platform view on the main frame; for main
@@ -697,6 +744,14 @@ class CONTENT_EXPORT RenderFrameHostImpl
FrameTreeNode* FindAndVerifyChild(int32_t child_frame_routing_id,
bad_message::BadMessageReason reason);
+ // Creates a Web Bluetooth Service owned by the frame.
+ void CreateWebBluetoothService(
+ mojo::InterfaceRequest<blink::mojom::WebBluetoothService> request);
+
+ // Allows tests to disable the swapout event timer to simulate bugs that
+ // happen before it fires (to avoid flakiness).
+ void ResetSwapOutTimerForTesting();
+
// For now, RenderFrameHosts indirectly keep RenderViewHosts alive via a
// refcount that calls Shutdown when it reaches zero. This allows each
// RenderFrameHostManager to just care about RenderFrameHosts, while ensuring
@@ -744,6 +799,14 @@ class CONTENT_EXPORT RenderFrameHostImpl
// The FrameTreeNode which this RenderFrameHostImpl is hosted in.
FrameTreeNode* frame_tree_node_;
+ // Track this frame's last committed URL.
+ GURL last_committed_url_;
+
+ // The most recent non-error URL to commit in this frame. Remove this in
+ // favor of GetLastCommittedURL() once PlzNavigate is enabled or cross-process
+ // transfers work for net errors. See https://crbug.com/588314.
+ GURL last_successful_url_;
+
// The mapping of pending JavaScript calls created by
// ExecuteJavaScript and their corresponding callbacks.
std::map<int, JavaScriptResultCallback> javascript_callbacks_;
@@ -759,8 +822,9 @@ class CONTENT_EXPORT RenderFrameHostImpl
int routing_id_;
- // The current state of this RenderFrameHost.
- RenderFrameHostImplState rfh_state_;
+ // Boolean indicating whether this RenderFrameHost is being actively used or
+ // is waiting for FrameHostMsg_SwapOut_ACK and thus pending deletion.
+ bool is_waiting_for_swapout_ack_;
// Tracks whether the RenderFrame for this RenderFrameHost has been created in
// the renderer process. Currently only used for subframes.
@@ -828,6 +892,8 @@ class CONTENT_EXPORT RenderFrameHostImpl
scoped_ptr<ServiceRegistryAndroid> service_registry_android_;
#endif
+ scoped_ptr<WebBluetoothServiceImpl> web_bluetooth_service_;
+
// The object managing the accessibility tree for this frame.
scoped_ptr<BrowserAccessibilityManager> browser_accessibility_manager_;
@@ -840,12 +906,19 @@ class CONTENT_EXPORT RenderFrameHostImpl
// we don't keep trying to reset forever.
int accessibility_reset_count_;
+ // The last AXContentTreeData for this frame received from the RenderFrame.
+ AXContentTreeData ax_content_tree_data_;
+
+ // The AX tree ID of the embedder, if this is a browser plugin guest.
+ AXTreeIDRegistry::AXTreeID browser_plugin_embedder_ax_tree_id_;
+
// The mapping from callback id to corresponding callback for pending
// accessibility tree snapshot calls created by RequestAXTreeSnapshot.
std::map<int, AXTreeSnapshotCallback> ax_tree_snapshot_callbacks_;
// Callback when an event is received, for testing.
- base::Callback<void(ui::AXEvent, int)> accessibility_testing_callback_;
+ base::Callback<void(RenderFrameHostImpl*, ui::AXEvent, int)>
+ accessibility_testing_callback_;
// The most recently received accessibility tree - for testing only.
scoped_ptr<ui::AXTree> ax_tree_for_testing_;
// Flag to not create a BrowserAccessibilityManager, for testing. If one
@@ -856,14 +929,15 @@ class CONTENT_EXPORT RenderFrameHostImpl
// response once it has started.
scoped_ptr<StreamHandle> stream_handle_;
- // Context shared for each PermissionService instance created for this RFH.
+ // Context shared for each mojom::PermissionService instance created for this
+ // RFH.
scoped_ptr<PermissionServiceContext> permission_service_context_;
// The frame's Mojo Shell service.
scoped_ptr<FrameMojoShell> frame_mojo_shell_;
// Holder of Mojo connection with ImageDownloader service in RenderFrame.
- image_downloader::ImageDownloaderPtr mojo_image_downloader_;
+ content::mojom::ImageDownloaderPtr mojo_image_downloader_;
// Tracks a navigation happening in this frame. Note that while there can be
// two navigations in the same FrameTreeNode, there can only be one
@@ -888,6 +962,11 @@ class CONTENT_EXPORT RenderFrameHostImpl
// called (no pending instance should be set).
bool should_reuse_web_ui_;
+ // PlzNavigate: The LoFi state of the last navigation. This is used during
+ // history navigation of subframes to ensure that subframes navigate with the
+ // same LoFi status as the top-level frame.
+ LoFiState last_navigation_lofi_state_;
+
// NOTE: This must be the last member.
base::WeakPtrFactory<RenderFrameHostImpl> weak_ptr_factory_;
diff --git a/chromium/content/browser/frame_host/render_frame_host_manager.cc b/chromium/content/browser/frame_host/render_frame_host_manager.cc
index 093dd4a5fa8..4358082af22 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_manager.cc
@@ -10,6 +10,8 @@
#include <utility>
#include "base/command_line.h"
+#include "base/debug/crash_logging.h"
+#include "base/debug/dump_without_crashing.h"
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/trace_event/trace_event.h"
@@ -48,61 +50,6 @@
namespace content {
-namespace {
-
-// Helper function to add the FrameTree of the given node's opener to the list
-// of |opener_trees|, if it doesn't exist there already. |visited_index|
-// indicates which FrameTrees in |opener_trees| have already been visited
-// (i.e., those at indices less than |visited_index|). |nodes_with_back_links|
-// collects FrameTreeNodes with openers in FrameTrees that have already been
-// visited (such as those with cycles). This function is intended to be used
-// with FrameTree::ForEach, so it always returns true to visit all nodes in the
-// tree.
-bool OpenerForFrameTreeNode(
- size_t visited_index,
- std::vector<FrameTree*>* opener_trees,
- base::hash_set<FrameTreeNode*>* nodes_with_back_links,
- FrameTreeNode* node) {
- if (!node->opener())
- return true;
-
- FrameTree* opener_tree = node->opener()->frame_tree();
-
- const auto& existing_tree_it =
- std::find(opener_trees->begin(), opener_trees->end(), opener_tree);
- if (existing_tree_it == opener_trees->end()) {
- // This is a new opener tree that we will need to process.
- opener_trees->push_back(opener_tree);
- } else {
- // If this tree is already on our processing list *and* we have visited it,
- // then this node's opener is a back link. This means the node will need
- // special treatment to process its opener.
- size_t position = std::distance(opener_trees->begin(), existing_tree_it);
- if (position < visited_index)
- nodes_with_back_links->insert(node);
- }
- return true;
-}
-
-} // namespace
-
-// static
-bool RenderFrameHostManager::ClearRFHsPendingShutdown(FrameTreeNode* node) {
- node->render_manager()->pending_delete_hosts_.clear();
- return true;
-}
-
-// static
-bool RenderFrameHostManager::ClearWebUIInstances(FrameTreeNode* node) {
- node->current_frame_host()->ClearAllWebUI();
- if (node->render_manager()->pending_render_frame_host_)
- node->render_manager()->pending_render_frame_host_->ClearAllWebUI();
- // PlzNavigate
- if (node->render_manager()->speculative_render_frame_host_)
- node->render_manager()->speculative_render_frame_host_->ClearAllWebUI();
- return true;
-}
-
RenderFrameHostManager::RenderFrameHostManager(
FrameTreeNode* frame_tree_node,
RenderFrameHostDelegate* render_frame_delegate,
@@ -147,10 +94,9 @@ void RenderFrameHostManager::Init(SiteInstance* site_instance,
// https://crbug.com/545684
DCHECK(!frame_tree_node_->IsMainFrame() ||
view_routing_id == widget_routing_id);
- int flags = delegate_->IsHidden() ? CREATE_RF_HIDDEN : 0;
SetRenderFrameHost(CreateRenderFrameHost(site_instance, view_routing_id,
frame_routing_id, widget_routing_id,
- flags));
+ delegate_->IsHidden()));
// Notify the delegate of the creation of the current RenderFrameHost.
// Do this only for subframes, as the main frame case is taken care of by
@@ -346,9 +292,16 @@ RenderFrameHostImpl* RenderFrameHostManager::Navigate(
entry.transferred_global_request_id()) {
cross_site_transferring_request_->ReleaseRequest();
+ DCHECK(transfer_navigation_handle_);
+
+ // Update the pending NavigationEntry ID on the transferring handle.
+ // TODO(creis): Make this line unnecessary by avoiding having a pending
+ // entry for transfer navigations. See https://crbug.com/495161.
+ transfer_navigation_handle_->update_entry_id_for_transfer(
+ entry.GetUniqueID());
+
// The navigating RenderFrameHost should take ownership of the
// NavigationHandle that came from the transferring RenderFrameHost.
- DCHECK(transfer_navigation_handle_);
dest_render_frame_host->SetNavigationHandle(
std::move(transfer_navigation_handle_));
}
@@ -472,7 +425,7 @@ void RenderFrameHostManager::OnBeforeUnloadACK(
}
void RenderFrameHostManager::OnCrossSiteResponse(
- RenderFrameHostImpl* pending_render_frame_host,
+ RenderFrameHostImpl* transferring_render_frame_host,
const GlobalRequestID& global_request_id,
scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request,
const std::vector<GURL>& transfer_url_chain,
@@ -484,12 +437,27 @@ void RenderFrameHostManager::OnCrossSiteResponse(
// swapping out) when the new navigation commits.
CHECK(cross_site_transferring_request);
- // A transfer should only have come from our pending or current RFH.
+ // A transfer should only have come from our pending or current RFH. If it
+ // started as a cross-process navigation via OpenURL, this is the pending
+ // one. If it wasn't cross-process until the transfer, this is the current
+ // one.
+ //
+ // Note that having a pending RFH does not imply that it was the one that
+ // made the request. Suppose that during a pending cross-site navigation,
+ // the frame performs a different same-site navigation which redirects
+ // cross-site. In this case, there will be a pending RFH, but this request
+ // is made by the current RFH. Later, this will create a new pending RFH and
+ // clean up the old one.
+ //
// TODO(creis): We need to handle the case that the pending RFH has changed
// in the mean time, while this was being posted from the IO thread. We
// should probably cancel the request in that case.
- DCHECK(pending_render_frame_host == pending_render_frame_host_.get() ||
- pending_render_frame_host == render_frame_host_.get());
+ DCHECK(transferring_render_frame_host == pending_render_frame_host_.get() ||
+ transferring_render_frame_host == render_frame_host_.get());
+
+ // Check if the FrameTreeNode is loading. This will be used later to notify
+ // the FrameTreeNode that the load stop if the transfer fails.
+ bool frame_tree_node_was_loading = frame_tree_node_->IsLoading();
// Store the transferring request so that we can release it if the transfer
// navigation matches.
@@ -498,22 +466,13 @@ void RenderFrameHostManager::OnCrossSiteResponse(
// Store the NavigationHandle to give it to the appropriate RenderFrameHost
// after it started navigating.
transfer_navigation_handle_ =
- pending_render_frame_host->PassNavigationHandleOwnership();
+ transferring_render_frame_host->PassNavigationHandleOwnership();
DCHECK(transfer_navigation_handle_);
- // Sanity check that the params are for the correct frame and process.
- // These should match the RenderFrameHost that made the request.
- // If it started as a cross-process navigation via OpenURL, this is the
- // pending one. If it wasn't cross-process until the transfer, this is
- // the current one.
- int render_frame_id = pending_render_frame_host_
- ? pending_render_frame_host_->GetRoutingID()
- : render_frame_host_->GetRoutingID();
- DCHECK_EQ(render_frame_id, pending_render_frame_host->GetRoutingID());
- int process_id = pending_render_frame_host_ ?
- pending_render_frame_host_->GetProcess()->GetID() :
- render_frame_host_->GetProcess()->GetID();
- DCHECK_EQ(process_id, global_request_id.child_id);
+ // Set the transferring RenderFrameHost as not loading, so that it does not
+ // emit a DidStopLoading notification if it is destroyed when creating the
+ // new navigating RenderFrameHost.
+ transferring_render_frame_host->set_is_loading(false);
// Treat the last URL in the chain as the destination and the remainder as
// the redirect chain.
@@ -522,9 +481,11 @@ void RenderFrameHostManager::OnCrossSiteResponse(
std::vector<GURL> rest_of_chain = transfer_url_chain;
rest_of_chain.pop_back();
- pending_render_frame_host->frame_tree_node()->navigator()->RequestTransferURL(
- pending_render_frame_host, transfer_url, rest_of_chain, referrer,
- page_transition, global_request_id, should_replace_current_entry);
+ transferring_render_frame_host->frame_tree_node()
+ ->navigator()
+ ->RequestTransferURL(transferring_render_frame_host, transfer_url,
+ nullptr, rest_of_chain, referrer, page_transition,
+ global_request_id, should_replace_current_entry);
// The transferring request was only needed during the RequestTransferURL
// call, so it is safe to clear at this point.
@@ -533,6 +494,11 @@ void RenderFrameHostManager::OnCrossSiteResponse(
// If the navigation continued, the NavigationHandle should have been
// transfered to a RenderFrameHost. In the other cases, it should be cleared.
transfer_navigation_handle_.reset();
+
+ // If the navigation in the new renderer did not start, inform the
+ // FrameTreeNode that it stopped loading.
+ if (!frame_tree_node_->IsLoading() && frame_tree_node_was_loading)
+ frame_tree_node_->DidStopLoading();
}
void RenderFrameHostManager::DidNavigateFrame(
@@ -579,15 +545,14 @@ void RenderFrameHostManager::CommitPendingIfNecessary(
if (render_frame_host_->pending_web_ui())
CommitPendingWebUI();
- // Decide on canceling the ongoing cross-process navigation.
- if (IsBrowserSideNavigationEnabled()) {
- CleanUpNavigation();
- } else {
- if (was_caused_by_user_gesture) {
- // A navigation in the original page has taken place. Cancel the
- // pending one. Only do it for user gesture originated navigations to
- // prevent page doing any shenanigans to prevent user from navigating.
- // See https://code.google.com/p/chromium/issues/detail?id=75195
+ // A navigation in the original page has taken place. Cancel the pending
+ // one. Only do it for user gesture originated navigations to prevent page
+ // doing any shenanigans to prevent user from navigating. See
+ // https://code.google.com/p/chromium/issues/detail?id=75195
+ if (was_caused_by_user_gesture) {
+ if (IsBrowserSideNavigationEnabled()) {
+ CleanUpNavigation();
+ } else {
CancelPending();
}
}
@@ -668,11 +633,10 @@ void RenderFrameHostManager::SwapOutOldFrame(
// Tell the renderer to suppress any further modal dialogs so that we can swap
// it out. This must be done before canceling any current dialog, in case
// there is a loop creating additional dialogs.
- // TODO(creis): Handle modal dialogs in subframe processes.
- old_render_frame_host->render_view_host()->SuppressDialogsUntilSwapOut();
+ old_render_frame_host->SuppressFurtherDialogs();
// Now close any modal dialogs that would prevent us from swapping out. This
- // must be done separately from SwapOut, so that the PageGroupLoadDeferrer is
+ // must be done separately from SwapOut, so that the ScopedPageLoadDeferrer is
// no longer on the stack when we send the SwapOut message.
delegate_->CancelModalDialogsForRenderManager();
@@ -703,20 +667,7 @@ void RenderFrameHostManager::SwapOutOldFrame(
// SwapOut creates a RenderFrameProxy, so set the proxy to be initialized.
proxy->set_render_frame_proxy_created(true);
- if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- // In --site-per-process, frames delete their RFH rather than storing it
- // in the proxy. Schedule it for deletion once the SwapOutACK comes in.
- // TODO(creis): This will be the default when we remove swappedout://.
- MoveToPendingDeleteHosts(std::move(old_render_frame_host));
- } else {
- // We shouldn't get here for subframes, since we only swap subframes when
- // --site-per-process is used.
- DCHECK(frame_tree_node_->IsMainFrame());
-
- // The old RenderFrameHost will stay alive inside the proxy so that existing
- // JavaScript window references to it stay valid.
- proxy->TakeFrameHostOwnership(std::move(old_render_frame_host));
- }
+ MoveToPendingDeleteHosts(std::move(old_render_frame_host));
}
void RenderFrameHostManager::DiscardUnusedFrame(
@@ -743,20 +694,6 @@ void RenderFrameHostManager::DiscardUnusedFrame(
proxy = CreateRenderFrameProxyHost(site_instance,
render_frame_host->render_view_host());
}
-
- if (!SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- DCHECK(frame_tree_node_->IsMainFrame());
-
- // When using swapped out RenderFrameHosts, it is possible for the pending
- // RenderFrameHost to be an existing one in swapped out state. Since it
- // has been used to start a navigation, it could have committed a
- // document. Check if |render_frame_host| is already swapped out, to avoid
- // swapping it out again.
- if (!render_frame_host->is_swapped_out())
- render_frame_host->SwapOut(proxy, false);
-
- proxy->TakeFrameHostOwnership(std::move(render_frame_host));
- }
}
render_frame_host.reset();
@@ -764,25 +701,26 @@ void RenderFrameHostManager::DiscardUnusedFrame(
void RenderFrameHostManager::MoveToPendingDeleteHosts(
scoped_ptr<RenderFrameHostImpl> render_frame_host) {
- // If this is the main frame going away and there are no more references to
- // its RenderViewHost, mark it for deletion as well so that we don't try to
- // reuse it.
- if (render_frame_host->frame_tree_node()->IsMainFrame() &&
- render_frame_host->render_view_host()->ref_count() <= 1) {
- render_frame_host->render_view_host()->set_pending_deletion();
- }
-
// |render_frame_host| will be deleted when its SwapOut ACK is received, or
// when the timer times out, or when the RFHM itself is deleted (whichever
// comes first).
- pending_delete_hosts_.push_back(
- linked_ptr<RenderFrameHostImpl>(render_frame_host.release()));
+ pending_delete_hosts_.push_back(std::move(render_frame_host));
}
-bool RenderFrameHostManager::IsPendingDeletion(
- RenderFrameHostImpl* render_frame_host) {
+bool RenderFrameHostManager::IsViewPendingDeletion(
+ RenderViewHostImpl* render_view_host) {
+ // Only safe to call this on the main frame.
+ CHECK(frame_tree_node_->IsMainFrame());
+
+ // The view is not pending deletion if more than one frame or proxy references
+ // it.
+ if (render_view_host->ref_count() > 1)
+ return false;
+
+ // If the only thing referencing it is a frame on the pending deletion list,
+ // then this view will go away when the frame goes away.
for (const auto& rfh : pending_delete_hosts_) {
- if (rfh == render_frame_host)
+ if (rfh->GetRenderViewHost() == render_view_host)
return true;
}
return false;
@@ -793,7 +731,7 @@ bool RenderFrameHostManager::DeleteFromPendingList(
for (RFHPendingDeleteList::iterator iter = pending_delete_hosts_.begin();
iter != pending_delete_hosts_.end();
iter++) {
- if (*iter == render_frame_host) {
+ if (iter->get() == render_frame_host) {
pending_delete_hosts_.erase(iter);
return true;
}
@@ -802,24 +740,36 @@ bool RenderFrameHostManager::DeleteFromPendingList(
}
void RenderFrameHostManager::ResetProxyHosts() {
- for (auto& pair : proxy_hosts_) {
+ for (const auto& pair : proxy_hosts_) {
static_cast<SiteInstanceImpl*>(pair.second->GetSiteInstance())
->RemoveObserver(this);
}
proxy_hosts_.clear();
}
+void RenderFrameHostManager::ClearRFHsPendingShutdown() {
+ pending_delete_hosts_.clear();
+}
+
+void RenderFrameHostManager::ClearWebUIInstances() {
+ current_frame_host()->ClearAllWebUI();
+ if (pending_render_frame_host_)
+ pending_render_frame_host_->ClearAllWebUI();
+ // PlzNavigate
+ if (speculative_render_frame_host_)
+ speculative_render_frame_host_->ClearAllWebUI();
+}
+
// PlzNavigate
void RenderFrameHostManager::DidCreateNavigationRequest(
- const NavigationRequest& request) {
+ NavigationRequest* request) {
CHECK(IsBrowserSideNavigationEnabled());
- // Clean up any state in case there's an ongoing navigation.
- // TODO(carlosk): remove this cleanup here once we properly cancel ongoing
- // navigations.
- CleanUpNavigation();
-
- RenderFrameHostImpl* dest_rfh = GetFrameHostForNavigation(request);
+ RenderFrameHostImpl* dest_rfh = GetFrameHostForNavigation(*request);
DCHECK(dest_rfh);
+ request->set_associated_site_instance_type(
+ dest_rfh == render_frame_host_.get()
+ ? NavigationRequest::AssociatedSiteInstanceType::CURRENT
+ : NavigationRequest::AssociatedSiteInstanceType::SPECULATIVE);
}
// PlzNavigate
@@ -844,27 +794,35 @@ RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
// The appropriate RenderFrameHost to commit the navigation.
RenderFrameHostImpl* navigation_rfh = nullptr;
- // Renderer-initiated main frame navigations that may require a SiteInstance
- // swap are sent to the browser via the OpenURL IPC and are afterwards treated
- // as browser-initiated navigations. NavigationRequests marked as
- // renderer-initiated are created by receiving a BeginNavigation IPC, and will
- // then proceed in the same renderer that sent the IPC due to the condition
- // below.
- // Subframe navigations will use the current renderer, unless
- // --site-per-process is enabled.
- // TODO(carlosk): Have renderer-initated main frame navigations swap processes
- // if needed when it no longer breaks OAuth popups (see
- // https://crbug.com/440266).
- bool is_main_frame = frame_tree_node_->IsMainFrame();
bool notify_webui_of_rv_creation = false;
- if (current_site_instance == dest_site_instance.get() ||
- (!request.browser_initiated() && is_main_frame) ||
- (!is_main_frame && !dest_site_instance->RequiresDedicatedProcess() &&
- !current_site_instance->RequiresDedicatedProcess())) {
- // Reuse the current RenderFrameHost if its SiteInstance matches the
- // navigation's or if this is a subframe navigation. We only swap
- // RenderFrameHosts for subframes when --site-per-process is enabled.
+ // Reuse the current RenderFrameHost if its SiteInstance matches the
+ // navigation's.
+ bool no_renderer_swap = current_site_instance == dest_site_instance.get();
+ if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
+ // Check if the current renderer should be changed for the navigation.
+ no_renderer_swap |=
+ render_frame_host_->IsRenderFrameLive() &&
+ ShouldMakeNetworkRequestForURL(request.common_params().url) &&
+ !IsRendererTransferNeededForNavigation(render_frame_host_.get(),
+ request.common_params().url);
+ } else {
+ // Subframe navigations will use the current renderer.
+ no_renderer_swap |= !frame_tree_node_->IsMainFrame();
+
+ // Renderer-initiated main frame navigations that may require a
+ // SiteInstance swap are sent to the browser via the OpenURL IPC and are
+ // afterwards treated as browser-initiated navigations. NavigationRequests
+ // marked as renderer-initiated are created by receiving a BeginNavigation
+ // IPC, and will then proceed in the same renderer that sent the IPC due to
+ // the condition below.
+ // TODO(carlosk): Have renderer-initated main frame navigations swap
+ // processes if needed when it no longer breaks OAuth popups (see
+ // https://crbug.com/440266).
+ no_renderer_swap |= !request.browser_initiated();
+ }
+
+ if (no_renderer_swap) {
// GetFrameHostForNavigation will be called more than once during a
// navigation (currently twice, on request and when it's about to commit in
// the renderer). In the follow up calls an existing pending WebUI should
@@ -917,6 +875,15 @@ RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
// (Note that we don't care about on{before}unload handlers if the current
// RFH isn't live.)
CommitPending();
+
+ // Notify the WebUI of the creation of the RenderView if needed (the
+ // newly created WebUI has just been committed by CommitPending, so
+ // GetNavigatingWebUI() below will return false).
+ if (notify_webui_of_rv_creation && render_frame_host_->web_ui()) {
+ render_frame_host_->web_ui()->RenderViewCreated(
+ render_frame_host_->render_view_host());
+ notify_webui_of_rv_creation = false;
+ }
}
}
DCHECK(navigation_rfh &&
@@ -957,9 +924,12 @@ RenderFrameHostImpl* RenderFrameHostManager::GetFrameHostForNavigation(
// PlzNavigate
void RenderFrameHostManager::CleanUpNavigation() {
CHECK(IsBrowserSideNavigationEnabled());
- render_frame_host_->ClearPendingWebUI();
- if (speculative_render_frame_host_)
+ if (speculative_render_frame_host_) {
+ bool was_loading = speculative_render_frame_host_->is_loading();
DiscardUnusedFrame(UnsetSpeculativeRenderFrameHost());
+ if (was_loading)
+ frame_tree_node_->DidStopLoading();
+ }
}
// PlzNavigate
@@ -983,18 +953,17 @@ void RenderFrameHostManager::OnDidStopLoading() {
}
}
-void RenderFrameHostManager::OnDidUpdateName(const std::string& name) {
+void RenderFrameHostManager::OnDidUpdateName(const std::string& name,
+ const std::string& unique_name) {
// The window.name message may be sent outside of --site-per-process when
// report_frame_name_changes renderer preference is set (used by
// WebView). Don't send the update to proxies in those cases.
- // TODO(nick,nasko): Should this be IsSwappedOutStateForbidden, to match
- // OnDidUpdateOrigin?
if (!SiteIsolationPolicy::AreCrossProcessFramesPossible())
return;
for (const auto& pair : proxy_hosts_) {
- pair.second->Send(
- new FrameMsg_DidUpdateName(pair.second->GetRoutingID(), name));
+ pair.second->Send(new FrameMsg_DidUpdateName(pair.second->GetRoutingID(),
+ name, unique_name));
}
}
@@ -1009,22 +978,21 @@ void RenderFrameHostManager::OnEnforceStrictMixedContentChecking(
}
}
-void RenderFrameHostManager::OnDidUpdateOrigin(const url::Origin& origin) {
- if (!SiteIsolationPolicy::IsSwappedOutStateForbidden())
- return;
-
+void RenderFrameHostManager::OnDidUpdateOrigin(
+ const url::Origin& origin,
+ bool is_potentially_trustworthy_unique_origin) {
for (const auto& pair : proxy_hosts_) {
pair.second->Send(
- new FrameMsg_DidUpdateOrigin(pair.second->GetRoutingID(), origin));
+ new FrameMsg_DidUpdateOrigin(pair.second->GetRoutingID(), origin,
+ is_potentially_trustworthy_unique_origin));
}
}
RenderFrameHostManager::SiteInstanceDescriptor::SiteInstanceDescriptor(
BrowserContext* browser_context,
GURL dest_url,
- bool related_to_current)
- : existing_site_instance(nullptr),
- new_is_related_to_current(related_to_current) {
+ SiteInstanceRelation relation_to_current)
+ : existing_site_instance(nullptr), relation(relation_to_current) {
new_site_url = SiteInstance::GetSiteForURL(browser_context, dest_url);
}
@@ -1039,30 +1007,20 @@ void RenderFrameHostManager::ActiveFrameCountIsZero(
RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(site_instance);
CHECK(proxy);
- // Delete the proxy. If it is for a main frame (and the RFH is stored
- // in the proxy) and it was still pending swap out, move the RFH to the
- // pending deletion list first.
- if (frame_tree_node_->IsMainFrame() && proxy->render_frame_host() &&
- proxy->render_frame_host()->rfh_state() ==
- RenderFrameHostImpl::STATE_PENDING_SWAP_OUT) {
- DCHECK(!SiteIsolationPolicy::IsSwappedOutStateForbidden());
- scoped_ptr<RenderFrameHostImpl> swapped_out_rfh =
- proxy->PassFrameHostOwnership();
- MoveToPendingDeleteHosts(std::move(swapped_out_rfh));
- }
-
DeleteRenderFrameProxyHost(site_instance);
}
RenderFrameProxyHost* RenderFrameHostManager::CreateRenderFrameProxyHost(
SiteInstance* site_instance,
RenderViewHostImpl* rvh) {
- auto result = proxy_hosts_.add(site_instance->GetId(),
- make_scoped_ptr(new RenderFrameProxyHost(
- site_instance, rvh, frame_tree_node_)));
- CHECK(result.second) << "A proxy already existed for this SiteInstance.";
+ int site_instance_id = site_instance->GetId();
+ CHECK(proxy_hosts_.find(site_instance_id) == proxy_hosts_.end())
+ << "A proxy already existed for this SiteInstance.";
+ RenderFrameProxyHost* proxy_host =
+ new RenderFrameProxyHost(site_instance, rvh, frame_tree_node_);
+ proxy_hosts_[site_instance_id] = make_scoped_ptr(proxy_host);
static_cast<SiteInstanceImpl*>(site_instance)->AddObserver(this);
- return result.first->second;
+ return proxy_host;
}
void RenderFrameHostManager::DeleteRenderFrameProxyHost(
@@ -1173,7 +1131,8 @@ bool RenderFrameHostManager::ShouldSwapBrowsingInstancesForNavigation(
return false;
}
-SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation(
+scoped_refptr<SiteInstance>
+RenderFrameHostManager::GetSiteInstanceForNavigation(
const GURL& dest_url,
SiteInstance* source_instance,
SiteInstance* dest_instance,
@@ -1217,15 +1176,15 @@ SiteInstance* RenderFrameHostManager::GetSiteInstanceForNavigation(
dest_is_restore, dest_is_view_source_mode, force_swap);
}
- SiteInstance* new_instance =
+ scoped_refptr<SiteInstance> new_instance =
ConvertToSiteInstance(new_instance_descriptor, candidate_instance);
-
// If |force_swap| is true, we must use a different SiteInstance than the
// current one. If we didn't, we would have two RenderFrameHosts in the same
// SiteInstance and the same frame, resulting in page_id conflicts for their
// NavigationEntries.
if (force_swap)
CHECK_NE(new_instance, current_instance);
+
return new_instance;
}
@@ -1258,7 +1217,8 @@ RenderFrameHostManager::DetermineSiteInstanceForURL(
// If a swap is required, we need to force the SiteInstance AND
// BrowsingInstance to be different ones, using CreateForURL.
if (force_browsing_instance_swap)
- return SiteInstanceDescriptor(browser_context, dest_url, false);
+ return SiteInstanceDescriptor(browser_context, dest_url,
+ SiteInstanceRelation::UNRELATED);
// (UGLY) HEURISTIC, process-per-site only:
//
@@ -1297,7 +1257,8 @@ RenderFrameHostManager::DetermineSiteInstanceForURL(
RenderProcessHostImpl::GetProcessHostForSite(browser_context, dest_url);
if (current_instance_impl->HasRelatedSiteInstance(dest_url) ||
use_process_per_site) {
- return SiteInstanceDescriptor(browser_context, dest_url, true);
+ return SiteInstanceDescriptor(browser_context, dest_url,
+ SiteInstanceRelation::RELATED);
}
// For extensions, Web UI URLs (such as the new tab page), and apps we do
@@ -1305,20 +1266,23 @@ RenderFrameHostManager::DetermineSiteInstanceForURL(
// will have a RenderProcessHost of PRIV_NORMAL. Create a new SiteInstance
// for this URL instead (with the correct process type).
if (current_instance_impl->HasWrongProcessForURL(dest_url))
- return SiteInstanceDescriptor(browser_context, dest_url, true);
+ return SiteInstanceDescriptor(browser_context, dest_url,
+ SiteInstanceRelation::RELATED);
// View-source URLs must use a new SiteInstance and BrowsingInstance.
// TODO(nasko): This is the same condition as later in the function. This
// should be taken into account when refactoring this method as part of
// http://crbug.com/123007.
if (dest_is_view_source_mode)
- return SiteInstanceDescriptor(browser_context, dest_url, false);
+ return SiteInstanceDescriptor(browser_context, dest_url,
+ SiteInstanceRelation::UNRELATED);
// If we are navigating from a blank SiteInstance to a WebUI, make sure we
// create a new SiteInstance.
if (WebUIControllerFactoryRegistry::GetInstance()->UseWebUIForURL(
browser_context, dest_url)) {
- return SiteInstanceDescriptor(browser_context, dest_url, false);
+ return SiteInstanceDescriptor(browser_context, dest_url,
+ SiteInstanceRelation::UNRELATED);
}
// Normally the "site" on the SiteInstance is set lazily when the load
@@ -1368,7 +1332,8 @@ RenderFrameHostManager::DetermineSiteInstanceForURL(
if (current_entry &&
current_entry->IsViewSourceMode() != dest_is_view_source_mode &&
!IsRendererDebugURL(dest_url)) {
- return SiteInstanceDescriptor(browser_context, dest_url, false);
+ return SiteInstanceDescriptor(browser_context, dest_url,
+ SiteInstanceRelation::UNRELATED);
}
// Use the source SiteInstance in case of data URLs or about:blank pages,
@@ -1380,22 +1345,43 @@ RenderFrameHostManager::DetermineSiteInstanceForURL(
return SiteInstanceDescriptor(source_instance);
}
- // Use the current SiteInstance for same site navigations, as long as the
- // process type is correct. (The URL may have been installed as an app since
- // the last time we visited it.)
- const GURL& current_url =
- GetCurrentURLForSiteInstance(current_instance_impl, current_entry);
- if (SiteInstance::IsSameWebSite(browser_context, current_url, dest_url) &&
- !current_instance_impl->HasWrongProcessForURL(dest_url)) {
- return SiteInstanceDescriptor(current_instance_impl);
+ // Use the current SiteInstance for same site navigations.
+ if (IsCurrentlySameSite(render_frame_host_.get(), dest_url))
+ return SiteInstanceDescriptor(render_frame_host_->GetSiteInstance());
+
+ if (SiteIsolationPolicy::IsTopDocumentIsolationEnabled()) {
+ // TODO(nick): Looking at the main frame and openers is required for TDI
+ // mode, but should be safe to enable unconditionally.
+ if (!frame_tree_node_->IsMainFrame()) {
+ RenderFrameHostImpl* main_frame =
+ frame_tree_node_->frame_tree()->root()->current_frame_host();
+ if (IsCurrentlySameSite(main_frame, dest_url))
+ return SiteInstanceDescriptor(main_frame->GetSiteInstance());
+ }
+
+ if (frame_tree_node_->opener()) {
+ RenderFrameHostImpl* opener_frame =
+ frame_tree_node_->opener()->current_frame_host();
+ if (IsCurrentlySameSite(opener_frame, dest_url))
+ return SiteInstanceDescriptor(opener_frame->GetSiteInstance());
+ }
+ }
+
+ if (!frame_tree_node_->IsMainFrame() &&
+ SiteIsolationPolicy::IsTopDocumentIsolationEnabled() &&
+ !SiteInstanceImpl::DoesSiteRequireDedicatedProcess(browser_context,
+ dest_url)) {
+ // This is a cross-site subframe of a non-isolated origin, so place this
+ // frame in the default subframe site instance.
+ return SiteInstanceDescriptor(
+ browser_context, dest_url,
+ SiteInstanceRelation::RELATED_DEFAULT_SUBFRAME);
}
// Start the new renderer in a new SiteInstance, but in the current
- // BrowsingInstance. It is important to immediately give this new
- // SiteInstance to a RenderViewHost (if it is different than our current
- // SiteInstance), so that it is ref counted. This will happen in
- // CreateRenderView.
- return SiteInstanceDescriptor(browser_context, dest_url, true);
+ // BrowsingInstance.
+ return SiteInstanceDescriptor(browser_context, dest_url,
+ SiteInstanceRelation::RELATED);
}
bool RenderFrameHostManager::IsRendererTransferNeededForNavigation(
@@ -1424,23 +1410,34 @@ bool RenderFrameHostManager::IsRendererTransferNeededForNavigation(
// TODO(nasko, nick): These following --site-per-process checks are
// overly simplistic. Update them to match all the cases
// considered by DetermineSiteInstanceForURL.
- if (SiteInstance::IsSameWebSite(rfh->GetSiteInstance()->GetBrowserContext(),
- rfh->GetSiteInstance()->GetSiteURL(),
- dest_url)) {
- return false; // The same site, no transition needed.
+ if (IsCurrentlySameSite(rfh, dest_url)) {
+ // The same site, no transition needed for security purposes, and we must
+ // keep the same SiteInstance for correctness of synchronous scripting.
+ return false;
}
// The sites differ. If either one requires a dedicated process,
// then a transfer is needed.
- return rfh->GetSiteInstance()->RequiresDedicatedProcess() ||
- SiteInstanceImpl::DoesSiteRequireDedicatedProcess(context,
- effective_url);
+ if (rfh->GetSiteInstance()->RequiresDedicatedProcess() ||
+ SiteInstanceImpl::DoesSiteRequireDedicatedProcess(context,
+ effective_url)) {
+ return true;
+ }
+
+ if (SiteIsolationPolicy::IsTopDocumentIsolationEnabled() &&
+ (!frame_tree_node_->IsMainFrame() ||
+ rfh->GetSiteInstance()->is_default_subframe_site_instance())) {
+ // Always attempt a transfer in these cases.
+ return true;
+ }
+
+ return false;
}
-SiteInstance* RenderFrameHostManager::ConvertToSiteInstance(
+scoped_refptr<SiteInstance> RenderFrameHostManager::ConvertToSiteInstance(
const SiteInstanceDescriptor& descriptor,
SiteInstance* candidate_instance) {
- SiteInstance* current_instance = render_frame_host_->GetSiteInstance();
+ SiteInstanceImpl* current_instance = render_frame_host_->GetSiteInstance();
// Note: If the |candidate_instance| matches the descriptor, it will already
// be set to |descriptor.existing_site_instance|.
@@ -1449,9 +1446,12 @@ SiteInstance* RenderFrameHostManager::ConvertToSiteInstance(
// Note: If the |candidate_instance| matches the descriptor,
// GetRelatedSiteInstance will return it.
- if (descriptor.new_is_related_to_current)
+ if (descriptor.relation == SiteInstanceRelation::RELATED)
return current_instance->GetRelatedSiteInstance(descriptor.new_site_url);
+ if (descriptor.relation == SiteInstanceRelation::RELATED_DEFAULT_SUBFRAME)
+ return current_instance->GetDefaultSubframeSiteInstance();
+
// At this point we know an unrelated site instance must be returned. First
// check if the candidate matches.
if (candidate_instance &&
@@ -1466,40 +1466,54 @@ SiteInstance* RenderFrameHostManager::ConvertToSiteInstance(
descriptor.new_site_url);
}
-const GURL& RenderFrameHostManager::GetCurrentURLForSiteInstance(
- SiteInstance* current_instance, NavigationEntry* current_entry) {
- // If this is a subframe that is potentially out of process from its parent,
- // don't consider using current_entry's url for SiteInstance selection, since
- // current_entry's url is for the main frame and may be in a different site
- // than this frame.
- // TODO(creis): Remove this when we can check the FrameNavigationEntry's url.
- // See http://crbug.com/369654
- if (!frame_tree_node_->IsMainFrame() &&
- SiteIsolationPolicy::AreCrossProcessFramesPossible())
- return frame_tree_node_->current_url();
-
- // If there is no last non-interstitial entry (and current_instance already
- // has a site), then we must have been opened from another tab. We want
- // to compare against the URL of the page that opened us, but we can't
- // get to it directly. The best we can do is check against the site of
- // the SiteInstance. This will be correct when we intercept links and
- // script-based navigations, but for now, it could place some pages in a
- // new process unnecessarily. We should only hit this case if a page tries
- // to open a new tab to an interstitial-inducing URL, and then navigates
- // the page to a different same-site URL. (This seems very unlikely in
- // practice.)
- if (current_entry)
- return current_entry->GetURL();
- return current_instance->GetSiteURL();
+bool RenderFrameHostManager::IsCurrentlySameSite(RenderFrameHostImpl* candidate,
+ const GURL& dest_url) {
+ BrowserContext* browser_context =
+ delegate_->GetControllerForRenderManager().GetBrowserContext();
+
+ // If the process type is incorrect, reject the candidate even if |dest_url|
+ // is same-site. (The URL may have been installed as an app since
+ // the last time we visited it.)
+ if (candidate->GetSiteInstance()->HasWrongProcessForURL(dest_url))
+ return false;
+
+ // If we don't have a last successful URL, we can't trust the origin or URL
+ // stored on the frame, so we fall back to GetSiteURL(). This case occurs
+ // after commits of net errors, since net errors do not currently swap
+ // processes for transfer navigations. Note: browser-initiated net errors do
+ // swap processes, but the frame's last successful URL will still be empty in
+ // that case.
+ if (candidate->last_successful_url().is_empty()) {
+ // TODO(creis): GetSiteURL() is not 100% accurate. Eliminate this fallback.
+ return SiteInstance::IsSameWebSite(
+ browser_context, candidate->GetSiteInstance()->GetSiteURL(), dest_url);
+ }
+
+ // In the common case, we use the RenderFrameHost's last successful URL. Thus,
+ // we compare against the last successful commit when deciding whether to swap
+ // this time.
+ if (SiteInstance::IsSameWebSite(browser_context,
+ candidate->last_successful_url(), dest_url)) {
+ return true;
+ }
+
+ // It is possible that last_successful_url() was a nonstandard scheme (for
+ // example, "about:blank"). If so, examine the replicated origin to determine
+ // the site.
+ if (!candidate->GetLastCommittedOrigin().unique() &&
+ SiteInstance::IsSameWebSite(
+ browser_context,
+ GURL(candidate->GetLastCommittedOrigin().Serialize()), dest_url)) {
+ return true;
+ }
+
+ // Not same-site.
+ return false;
}
void RenderFrameHostManager::CreatePendingRenderFrameHost(
SiteInstance* old_instance,
SiteInstance* new_instance) {
- int create_render_frame_flags = 0;
- if (delegate_->IsHidden())
- create_render_frame_flags |= CREATE_RF_HIDDEN;
-
if (pending_render_frame_host_)
CancelPending();
@@ -1514,7 +1528,7 @@ void RenderFrameHostManager::CreatePendingRenderFrameHost(
// Create a non-swapped-out RFH with the given opener.
pending_render_frame_host_ =
- CreateRenderFrame(new_instance, create_render_frame_flags, nullptr);
+ CreateRenderFrame(new_instance, delegate_->IsHidden(), nullptr);
}
void RenderFrameHostManager::CreateProxiesForNewRenderFrameHost(
@@ -1570,19 +1584,16 @@ scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrameHost(
int32_t view_routing_id,
int32_t frame_routing_id,
int32_t widget_routing_id,
- int flags) {
+ bool hidden) {
if (frame_routing_id == MSG_ROUTING_NONE)
frame_routing_id = site_instance->GetProcess()->GetNextRoutingID();
- bool swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT);
- bool hidden = !!(flags & CREATE_RF_HIDDEN);
-
// Create a RVH for main frames, or find the existing one for subframes.
FrameTree* frame_tree = frame_tree_node_->frame_tree();
RenderViewHostImpl* render_view_host = nullptr;
if (frame_tree_node_->IsMainFrame()) {
render_view_host = frame_tree->CreateRenderViewHost(
- site_instance, view_routing_id, frame_routing_id, swapped_out, hidden);
+ site_instance, view_routing_id, frame_routing_id, false, hidden);
// TODO(avi): It's a bit bizarre that this logic lives here instead of in
// CreateRenderFrame(). It turns out that FrameTree::CreateRenderViewHost
// doesn't /always/ create a new RenderViewHost. It first tries to find an
@@ -1605,7 +1616,7 @@ scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrameHost(
return RenderFrameHostFactory::Create(
site_instance, render_view_host, render_frame_delegate_,
render_widget_delegate_, frame_tree, frame_tree_node_, frame_routing_id,
- widget_routing_id, flags);
+ widget_routing_id, hidden);
}
// PlzNavigate
@@ -1624,31 +1635,23 @@ bool RenderFrameHostManager::CreateSpeculativeRenderFrameHost(
CreateProxiesForNewRenderFrameHost(old_instance, new_instance);
- int create_render_frame_flags = 0;
- if (delegate_->IsHidden())
- create_render_frame_flags |= CREATE_RF_HIDDEN;
speculative_render_frame_host_ =
- CreateRenderFrame(new_instance, create_render_frame_flags, nullptr);
+ CreateRenderFrame(new_instance, delegate_->IsHidden(), nullptr);
return !!speculative_render_frame_host_;
}
scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame(
SiteInstance* instance,
- int flags,
+ bool hidden,
int* view_routing_id_ptr) {
- bool swapped_out = !!(flags & CREATE_RF_SWAPPED_OUT);
- bool swapped_out_forbidden =
- SiteIsolationPolicy::IsSwappedOutStateForbidden();
+ int32_t widget_routing_id = MSG_ROUTING_NONE;
+ RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(instance);
CHECK(instance);
- CHECK(!swapped_out_forbidden || !swapped_out);
CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible() ||
frame_tree_node_->IsMainFrame());
- // Swapped out views should always be hidden.
- DCHECK(!swapped_out || (flags & CREATE_RF_HIDDEN));
-
scoped_ptr<RenderFrameHostImpl> new_render_frame_host;
bool success = true;
if (view_routing_id_ptr)
@@ -1658,101 +1661,58 @@ scoped_ptr<RenderFrameHostImpl> RenderFrameHostManager::CreateRenderFrame(
// never create it in the same SiteInstance as our current RFH.
CHECK_NE(render_frame_host_->GetSiteInstance(), instance);
- // Check if we've already created an RFH for this SiteInstance. If so, try
- // to re-use the existing one, which has already been initialized. We'll
- // remove it from the list of proxy hosts below if it will be active.
- RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(instance);
- if (proxy && proxy->render_frame_host()) {
- RenderViewHost* render_view_host = proxy->GetRenderViewHost();
- CHECK(!swapped_out_forbidden);
- if (view_routing_id_ptr)
- *view_routing_id_ptr = proxy->GetRenderViewHost()->GetRoutingID();
- // Delete the existing RenderFrameProxyHost, but reuse the RenderFrameHost.
- // Prevent the process from exiting while we're trying to use it.
- if (!swapped_out) {
- new_render_frame_host = proxy->PassFrameHostOwnership();
- new_render_frame_host->GetProcess()->AddPendingView();
-
- DeleteRenderFrameProxyHost(instance);
- // NB |proxy| is deleted at this point.
-
- // If we are reusing the RenderViewHost and it doesn't already have a
- // RenderWidgetHostView, we need to create one if this is the main frame.
- if (render_view_host->IsRenderViewLive() &&
- !render_view_host->GetWidget()->GetView() &&
- frame_tree_node_->IsMainFrame()) {
- delegate_->CreateRenderWidgetHostViewForRenderManager(render_view_host);
- }
- }
- } else {
- // Create a new RenderFrameHost if we don't find an existing one.
+ // A RenderFrame in a different process from its parent RenderFrame
+ // requires a RenderWidget for input/layout/painting.
+ if (frame_tree_node_->parent() &&
+ frame_tree_node_->parent()->current_frame_host()->GetSiteInstance() !=
+ instance) {
+ CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible());
+ widget_routing_id = instance->GetProcess()->GetNextRoutingID();
+ }
- int32_t widget_routing_id = MSG_ROUTING_NONE;
+ new_render_frame_host = CreateRenderFrameHost(
+ instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE, widget_routing_id, hidden);
+ RenderViewHostImpl* render_view_host =
+ new_render_frame_host->render_view_host();
- // A RenderFrame in a different process from its parent RenderFrame
- // requires a RenderWidget for input/layout/painting.
- if (frame_tree_node_->parent() &&
- frame_tree_node_->parent()->current_frame_host()->GetSiteInstance() !=
- instance) {
- CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible());
- widget_routing_id = instance->GetProcess()->GetNextRoutingID();
- }
+ // Prevent the process from exiting while we're trying to navigate in it.
+ new_render_frame_host->GetProcess()->AddPendingView();
- new_render_frame_host = CreateRenderFrameHost(
- instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE, widget_routing_id, flags);
- RenderViewHostImpl* render_view_host =
- new_render_frame_host->render_view_host();
+ if (frame_tree_node_->IsMainFrame()) {
+ success = InitRenderView(render_view_host, proxy);
- // Prevent the process from exiting while we're trying to navigate in it.
- // Otherwise, if the new RFH is swapped out already, store it.
- if (!swapped_out) {
- new_render_frame_host->GetProcess()->AddPendingView();
- } else {
- proxy =
- CreateRenderFrameProxyHost(new_render_frame_host->GetSiteInstance(),
- new_render_frame_host->render_view_host());
- proxy->TakeFrameHostOwnership(std::move(new_render_frame_host));
- }
+ // If we are reusing the RenderViewHost and it doesn't already have a
+ // RenderWidgetHostView, we need to create one if this is the main frame.
+ if (!render_view_host->GetWidget()->GetView())
+ delegate_->CreateRenderWidgetHostViewForRenderManager(render_view_host);
+ } else {
+ DCHECK(render_view_host->IsRenderViewLive());
+ }
+ if (success) {
if (frame_tree_node_->IsMainFrame()) {
- success = InitRenderView(render_view_host, proxy);
-
- // If we are reusing the RenderViewHost and it doesn't already have a
- // RenderWidgetHostView, we need to create one if this is the main frame.
- if (!swapped_out && !render_view_host->GetWidget()->GetView())
- delegate_->CreateRenderWidgetHostViewForRenderManager(render_view_host);
- } else {
- DCHECK(render_view_host->IsRenderViewLive());
- }
-
- if (success) {
- if (frame_tree_node_->IsMainFrame()) {
- // Don't show the main frame's view until we get a DidNavigate from it.
- // Only the RenderViewHost for the top-level RenderFrameHost has a
- // RenderWidgetHostView; RenderWidgetHosts for out-of-process iframes
- // will be created later and hidden.
- if (render_view_host->GetWidget()->GetView())
- render_view_host->GetWidget()->GetView()->Hide();
- }
- // RenderViewHost for |instance| might exist prior to calling
- // CreateRenderFrame. In such a case, InitRenderView will not create the
- // RenderFrame in the renderer process and it needs to be done
- // explicitly.
- if (swapped_out_forbidden) {
- // Init the RFH, so a RenderFrame is created in the renderer.
- DCHECK(new_render_frame_host);
- success = InitRenderFrame(new_render_frame_host.get());
- }
+ // Don't show the main frame's view until we get a DidNavigate from it.
+ // Only the RenderViewHost for the top-level RenderFrameHost has a
+ // RenderWidgetHostView; RenderWidgetHosts for out-of-process iframes
+ // will be created later and hidden.
+ if (render_view_host->GetWidget()->GetView())
+ render_view_host->GetWidget()->GetView()->Hide();
}
+ // RenderViewHost for |instance| might exist prior to calling
+ // CreateRenderFrame. In such a case, InitRenderView will not create the
+ // RenderFrame in the renderer process and it needs to be done
+ // explicitly.
+ DCHECK(new_render_frame_host);
+ success = InitRenderFrame(new_render_frame_host.get());
+ }
- if (success) {
- if (view_routing_id_ptr)
- *view_routing_id_ptr = render_view_host->GetRoutingID();
- }
+ if (success) {
+ if (view_routing_id_ptr)
+ *view_routing_id_ptr = render_view_host->GetRoutingID();
}
- // Returns the new RFH if it isn't swapped out.
- if (success && !swapped_out) {
+ // Return the new RenderFrameHost on successful creation.
+ if (success) {
DCHECK(new_render_frame_host->GetSiteInstance() == instance);
return new_render_frame_host;
}
@@ -1769,14 +1729,12 @@ int RenderFrameHostManager::CreateRenderFrameProxy(SiteInstance* instance) {
// Ensure a RenderViewHost exists for |instance|, as it creates the page
// level structure in Blink.
- if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- render_view_host =
- frame_tree_node_->frame_tree()->GetRenderViewHost(instance);
- if (!render_view_host) {
- CHECK(frame_tree_node_->IsMainFrame());
- render_view_host = frame_tree_node_->frame_tree()->CreateRenderViewHost(
- instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE, true, true);
- }
+ render_view_host =
+ frame_tree_node_->frame_tree()->GetRenderViewHost(instance);
+ if (!render_view_host) {
+ CHECK(frame_tree_node_->IsMainFrame());
+ render_view_host = frame_tree_node_->frame_tree()->CreateRenderViewHost(
+ instance, MSG_ROUTING_NONE, MSG_ROUTING_NONE, true, true);
}
RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(instance);
@@ -1786,8 +1744,7 @@ int RenderFrameHostManager::CreateRenderFrameProxy(SiteInstance* instance) {
if (!proxy)
proxy = CreateRenderFrameProxyHost(instance, render_view_host);
- if (SiteIsolationPolicy::IsSwappedOutStateForbidden() &&
- frame_tree_node_->IsMainFrame()) {
+ if (frame_tree_node_->IsMainFrame()) {
InitRenderView(render_view_host, proxy);
} else {
proxy->InitRenderFrameProxy();
@@ -1802,7 +1759,7 @@ void RenderFrameHostManager::CreateProxiesForChildFrame(FrameTreeNode* child) {
for (const auto& pair : proxy_hosts_) {
// Do not create proxies for subframes in the outer delegate's process,
// since the outer delegate does not need to interact with them.
- if (pair.second == outer_delegate_proxy)
+ if (pair.second.get() == outer_delegate_proxy)
continue;
child->render_manager()->CreateRenderFrameProxy(
@@ -1844,7 +1801,8 @@ void RenderFrameHostManager::CreateOuterDelegateProxy(
// investigate and fix.
render_frame_host->Send(new FrameMsg_SwapOut(
render_frame_host->GetRoutingID(), proxy->GetRoutingID(),
- false /* is_loading */, FrameReplicationState()));
+ false /* is_loading */,
+ render_frame_host->frame_tree_node()->current_replication_state()));
proxy->set_render_frame_proxy_created(true);
}
@@ -1925,8 +1883,95 @@ bool RenderFrameHostManager::InitRenderFrame(
if (existing_proxy) {
proxy_routing_id = existing_proxy->GetRoutingID();
CHECK_NE(proxy_routing_id, MSG_ROUTING_NONE);
- if (!existing_proxy->is_render_frame_proxy_live())
+ if (!existing_proxy->is_render_frame_proxy_live()) {
+ // Calling InitRenderFrameProxy on main frames seems to be causing
+ // https://crbug.com/575245, so track down how this can happen.
+ // TODO(creis): Remove this once we've found the cause.
+ if (!frame_tree_node_->parent()) {
+ base::debug::SetCrashKeyValue(
+ "initrf_frame_id",
+ base::IntToString(render_frame_host->GetRoutingID()));
+ base::debug::SetCrashKeyValue("initrf_proxy_id",
+ base::IntToString(proxy_routing_id));
+ base::debug::SetCrashKeyValue(
+ "initrf_view_id",
+ base::IntToString(
+ render_frame_host->render_view_host()->GetRoutingID()));
+ base::debug::SetCrashKeyValue(
+ "initrf_main_frame_id",
+ base::IntToString(render_frame_host->render_view_host()
+ ->main_frame_routing_id()));
+ base::debug::SetCrashKeyValue(
+ "initrf_view_is_live",
+ render_frame_host->render_view_host()->IsRenderViewLive() ? "yes"
+ : "no");
+ base::debug::DumpWithoutCrashing();
+ }
+
existing_proxy->InitRenderFrameProxy();
+ }
+ }
+
+ // TODO(alexmos): These crash keys are temporary to track down
+ // https://crbug.com/591478. Verify that the parent routing ID
+ // points to a live RenderFrameProxy when this is not a remote-to-local
+ // navigation (i.e., when there's no |existing_proxy|).
+ if (!existing_proxy && frame_tree_node_->parent()) {
+ RenderFrameProxyHost* parent_proxy = RenderFrameProxyHost::FromID(
+ render_frame_host->GetProcess()->GetID(), parent_routing_id);
+ if (!parent_proxy || !parent_proxy->is_render_frame_proxy_live()) {
+ base::debug::SetCrashKeyValue("initrf_parent_proxy_exists",
+ parent_proxy ? "yes" : "no");
+
+ SiteInstance* parent_instance =
+ frame_tree_node_->parent()->current_frame_host()->GetSiteInstance();
+ base::debug::SetCrashKeyValue(
+ "initrf_parent_is_in_same_site_instance",
+ site_instance == parent_instance ? "yes" : "no");
+ base::debug::SetCrashKeyValue("initrf_parent_process_is_live",
+ frame_tree_node_->parent()
+ ->current_frame_host()
+ ->GetProcess()
+ ->HasConnection()
+ ? "yes"
+ : "no");
+ base::debug::SetCrashKeyValue(
+ "initrf_render_view_is_live",
+ render_frame_host->render_view_host()->IsRenderViewLive() ? "yes"
+ : "no");
+
+ // Collect some additional information for root's proxy if it's different
+ // from the parent.
+ FrameTreeNode* root = frame_tree_node_->frame_tree()->root();
+ if (root != frame_tree_node_->parent()) {
+ SiteInstance* root_instance =
+ root->current_frame_host()->GetSiteInstance();
+ base::debug::SetCrashKeyValue(
+ "initrf_root_is_in_same_site_instance",
+ site_instance == root_instance ? "yes" : "no");
+ base::debug::SetCrashKeyValue(
+ "initrf_root_is_in_same_site_instance_as_parent",
+ parent_instance == root_instance ? "yes" : "no");
+ base::debug::SetCrashKeyValue("initrf_root_process_is_live",
+ frame_tree_node_->frame_tree()
+ ->root()
+ ->current_frame_host()
+ ->GetProcess()
+ ->HasConnection()
+ ? "yes"
+ : "no");
+
+ RenderFrameProxyHost* top_proxy =
+ root->render_manager()->GetRenderFrameProxyHost(site_instance);
+ if (top_proxy) {
+ base::debug::SetCrashKeyValue(
+ "initrf_root_proxy_is_live",
+ top_proxy->is_render_frame_proxy_live() ? "yes" : "no");
+ }
+ }
+
+ base::debug::DumpWithoutCrashing();
+ }
}
return delegate_->CreateRenderFrameForRenderManager(
@@ -1939,14 +1984,6 @@ int RenderFrameHostManager::GetRoutingIdForSiteInstance(
if (render_frame_host_->GetSiteInstance() == site_instance)
return render_frame_host_->GetRoutingID();
- // If there is a matching pending RFH, only return it if swapped out is
- // allowed, since otherwise there should be a proxy that should be used
- // instead.
- if (pending_render_frame_host_ &&
- pending_render_frame_host_->GetSiteInstance() == site_instance &&
- !SiteIsolationPolicy::IsSwappedOutStateForbidden())
- return pending_render_frame_host_->GetRoutingID();
-
RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(site_instance);
if (proxy)
return proxy->GetRoutingID();
@@ -2022,6 +2059,7 @@ void RenderFrameHostManager::CommitPending() {
// now to make sure the sad tab shows up, etc.
DCHECK(!render_frame_host_->IsRenderFrameLive());
DCHECK(!render_frame_host_->render_view_host()->IsRenderViewLive());
+ render_frame_host_->ResetLoadingState();
delegate_->RenderProcessGoneFromRenderManager(
render_frame_host_->render_view_host());
}
@@ -2059,7 +2097,7 @@ void RenderFrameHostManager::CommitPending() {
// If this is committing a main frame navigation, update it and set the
// routing id in the RenderViewHost associated with the old RenderFrameHost
// to MSG_ROUTING_NONE.
- if (is_main_frame && SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
+ if (is_main_frame) {
render_frame_host_->render_view_host()->set_main_frame_routing_id(
render_frame_host_->routing_id());
old_render_frame_host->render_view_host()->set_main_frame_routing_id(
@@ -2067,18 +2105,13 @@ void RenderFrameHostManager::CommitPending() {
}
// Swap out the old frame now that the new one is visible.
- // This will swap it out and then put it on the proxy list (if there are other
- // active views in its SiteInstance) or schedule it for deletion when the swap
- // out ack arrives (or immediately if the process isn't live).
- // In the --site-per-process case, old subframe RFHs are not kept alive inside
- // the proxy.
+ // This will swap it out and schedule it for deletion when the swap out ack
+ // arrives (or immediately if the process isn't live).
SwapOutOldFrame(std::move(old_render_frame_host));
- if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- // Since the new RenderFrameHost is now committed, there must be no proxies
- // for its SiteInstance. Delete any existing ones.
- DeleteRenderFrameProxyHost(render_frame_host_->GetSiteInstance());
- }
+ // Since the new RenderFrameHost is now committed, there must be no proxies
+ // for its SiteInstance. Delete any existing ones.
+ DeleteRenderFrameProxyHost(render_frame_host_->GetSiteInstance());
// If this is a subframe, it should have a CrossProcessFrameConnector
// created already. Use it to link the new RFH's view to the proxy that
@@ -2232,9 +2265,9 @@ RenderFrameHostImpl* RenderFrameHostManager::UpdateStateForNavigate(
// The renderer can exit view source mode when any error or cancellation
// happen. We must overwrite to recover the mode.
if (dest_is_view_source_mode) {
- render_frame_host_->render_view_host()->Send(
- new ViewMsg_EnableViewSourceMode(
- render_frame_host_->render_view_host()->GetRoutingID()));
+ DCHECK(!render_frame_host_->GetParent());
+ render_frame_host_->Send(
+ new FrameMsg_EnableViewSourceMode(render_frame_host_->GetRoutingID()));
}
return render_frame_host_.get();
@@ -2273,7 +2306,11 @@ void RenderFrameHostManager::CancelPending() {
TRACE_EVENT1("navigation", "RenderFrameHostManager::CancelPending",
"FrameTreeNode id", frame_tree_node_->frame_tree_node_id());
render_frame_host_->ClearPendingWebUI();
+
+ bool pending_was_loading = pending_render_frame_host_->is_loading();
DiscardUnusedFrame(UnsetPendingRenderFrameHost());
+ if (pending_was_loading)
+ frame_tree_node_->DidStopLoading();
}
scoped_ptr<RenderFrameHostImpl>
@@ -2352,16 +2389,12 @@ RenderFrameProxyHost* RenderFrameHostManager::GetRenderFrameProxyHost(
SiteInstance* instance) const {
auto it = proxy_hosts_.find(instance->GetId());
if (it != proxy_hosts_.end())
- return it->second;
+ return it->second.get();
return nullptr;
}
-std::map<int, RenderFrameProxyHost*>
-RenderFrameHostManager::GetAllProxyHostsForTesting() {
- std::map<int, RenderFrameProxyHost*> result;
- for (const auto& pair : proxy_hosts_)
- result[pair.first] = pair.second;
- return result;
+int RenderFrameHostManager::GetProxyCount() {
+ return proxy_hosts_.size();
}
void RenderFrameHostManager::CollectOpenerFrameTrees(
@@ -2370,12 +2403,39 @@ void RenderFrameHostManager::CollectOpenerFrameTrees(
CHECK(opener_frame_trees);
opener_frame_trees->push_back(frame_tree_node_->frame_tree());
+ // Add the FrameTree of the given node's opener to the list of
+ // |opener_frame_trees| if it doesn't exist there already. |visited_index|
+ // indicates which FrameTrees in |opener_frame_trees| have already been
+ // visited (i.e., those at indices less than |visited_index|).
+ // |nodes_with_back_links| collects FrameTreeNodes with openers in FrameTrees
+ // that have already been visited (such as those with cycles).
size_t visited_index = 0;
while (visited_index < opener_frame_trees->size()) {
FrameTree* frame_tree = (*opener_frame_trees)[visited_index];
visited_index++;
- frame_tree->ForEach(base::Bind(&OpenerForFrameTreeNode, visited_index,
- opener_frame_trees, nodes_with_back_links));
+ for (FrameTreeNode* node : frame_tree->Nodes()) {
+ if (!node->opener())
+ continue;
+
+ FrameTree* opener_tree = node->opener()->frame_tree();
+ const auto& existing_tree_it = std::find(
+ opener_frame_trees->begin(), opener_frame_trees->end(), opener_tree);
+
+ if (existing_tree_it == opener_frame_trees->end()) {
+ // This is a new opener tree that we will need to process.
+ opener_frame_trees->push_back(opener_tree);
+ } else {
+ // If this tree is already on our processing list *and* we have visited
+ // it,
+ // then this node's opener is a back link. This means the node will
+ // need
+ // special treatment to process its opener.
+ size_t position =
+ std::distance(opener_frame_trees->begin(), existing_tree_it);
+ if (position < visited_index)
+ nodes_with_back_links->insert(node);
+ }
+ }
}
}
@@ -2443,29 +2503,29 @@ void RenderFrameHostManager::CreateOpenerProxiesForFrameTree(
} else {
// If any of the RenderViewHosts (current, pending, or swapped out) for this
// FrameTree has the same SiteInstance, then we can return early and reuse
- // them. An exception is if we are in IsSwappedOutStateForbidden mode and
- // find a pending RenderViewHost: in this case, we should still create a
- // proxy, which will allow communicating with the opener until the pending
- // RenderView commits, or if the pending navigation is canceled.
+ // them. An exception is if we find a pending RenderViewHost: in this case,
+ // we should still create a proxy, which will allow communicating with the
+ // opener until the pending RenderView commits, or if the pending navigation
+ // is canceled.
+ // PlzNavigate: similarly, if a speculative RenderViewHost is present, a
+ // proxy should be created.
RenderViewHostImpl* rvh = frame_tree->GetRenderViewHost(instance);
- bool need_proxy_for_pending_rvh =
- SiteIsolationPolicy::IsSwappedOutStateForbidden() &&
- (rvh == pending_render_view_host());
- if (rvh && rvh->IsRenderViewLive() && !need_proxy_for_pending_rvh)
+ bool need_proxy_for_pending_rvh = (rvh == pending_render_view_host());
+ bool need_proxy_for_speculative_rvh =
+ IsBrowserSideNavigationEnabled() && speculative_render_frame_host_ &&
+ speculative_render_frame_host_->GetRenderViewHost() == rvh;
+ if (rvh && rvh->IsRenderViewLive() && !need_proxy_for_pending_rvh &&
+ !need_proxy_for_speculative_rvh) {
return;
+ }
if (rvh && !rvh->IsRenderViewLive()) {
EnsureRenderViewInitialized(rvh, instance);
} else {
- // Create a swapped out RenderView in the given SiteInstance if none
+ // Create a RenderFrameProxyHost in the given SiteInstance if none
// exists. Since an opener can point to a subframe, do this on the root
// frame of the current opener's frame tree.
- if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- frame_tree->root()->render_manager()->CreateRenderFrameProxy(instance);
- } else {
- frame_tree->root()->render_manager()->CreateRenderFrame(
- instance, CREATE_RF_SWAPPED_OUT | CREATE_RF_HIDDEN, nullptr);
- }
+ frame_tree->root()->render_manager()->CreateRenderFrameProxy(instance);
}
}
}
@@ -2479,4 +2539,36 @@ int RenderFrameHostManager::GetOpenerRoutingID(SiteInstance* instance) {
->GetRoutingIdForSiteInstance(instance);
}
+void RenderFrameHostManager::SendPageMessage(IPC::Message* msg) {
+ DCHECK(IPC_MESSAGE_CLASS(*msg) == PageMsgStart);
+
+ // We should always deliver page messages through the main frame.
+ DCHECK(!frame_tree_node_->parent());
+
+ if ((IPC_MESSAGE_CLASS(*msg) != PageMsgStart) || frame_tree_node_->parent()) {
+ delete msg;
+ return;
+ }
+
+ auto send_msg = [](IPC::Sender* sender, int routing_id, IPC::Message* msg) {
+ IPC::Message* copy = new IPC::Message(*msg);
+ copy->set_routing_id(routing_id);
+ sender->Send(copy);
+ };
+
+ for (const auto& pair : proxy_hosts_)
+ send_msg(pair.second.get(), pair.second->GetRoutingID(), msg);
+
+ if (speculative_render_frame_host_) {
+ send_msg(speculative_render_frame_host_.get(),
+ speculative_render_frame_host_->GetRoutingID(), msg);
+ } else if (pending_render_frame_host_) {
+ send_msg(pending_render_frame_host_.get(),
+ pending_render_frame_host_->GetRoutingID(), msg);
+ }
+
+ msg->set_routing_id(render_frame_host_->GetRoutingID());
+ render_frame_host_->Send(msg);
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/render_frame_host_manager.h b/chromium/content/browser/frame_host/render_frame_host_manager.h
index b3b1d7439ce..63a42776833 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager.h
+++ b/chromium/content/browser/frame_host/render_frame_host_manager.h
@@ -9,9 +9,9 @@
#include <list>
#include <map>
+#include <unordered_map>
#include "base/containers/hash_tables.h"
-#include "base/containers/scoped_ptr_hash_map.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
@@ -179,15 +179,6 @@ class CONTENT_EXPORT RenderFrameHostManager
virtual ~Delegate() {}
};
- // Used with FrameTree::ForEach to delete RenderFrameHosts pending shutdown
- // from a FrameTreeNode's RenderFrameHostManager. Used during destruction of
- // WebContentsImpl.
- static bool ClearRFHsPendingShutdown(FrameTreeNode* node);
-
- // Used with FrameTree::ForEach to destroy all WebUI instances associated with
- // RenderFrameHosts.
- static bool ClearWebUIInstances(FrameTreeNode* node);
-
// All three delegate pointers must be non-NULL and are not owned by this
// class. They must outlive this class. The RenderViewHostDelegate and
// RenderWidgetHostDelegate are what will be installed into all
@@ -344,13 +335,11 @@ class CONTENT_EXPORT RenderFrameHostManager
void DidChangeOpener(int opener_routing_id,
SiteInstance* source_site_instance);
- // Creates and initializes a RenderFrameHost. If |flags| has the
- // CREATE_RF_SWAPPED_OUT bit set from the CreateRenderFrameFlags enum, it will
- // initially be placed on the swapped out hosts list. If |view_routing_id_ptr|
+ // Creates and initializes a RenderFrameHost. If |view_routing_id_ptr|
// is not nullptr it will be set to the routing id of the view associated with
// the frame.
scoped_ptr<RenderFrameHostImpl> CreateRenderFrame(SiteInstance* instance,
- int flags,
+ bool hidden,
int* view_routing_id_ptr);
// Helper method to create and initialize a RenderFrameProxyHost and return
@@ -395,8 +384,9 @@ class CONTENT_EXPORT RenderFrameHostManager
RenderFrameProxyHost* GetRenderFrameProxyHost(
SiteInstance* instance) const;
- // Returns whether |render_frame_host| is on the pending deletion list.
- bool IsPendingDeletion(RenderFrameHostImpl* render_frame_host);
+ // Returns whether |render_view_host| will be deleted when its main
+ // RenderFrameHost is deleted from the pending deletion list.
+ bool IsViewPendingDeletion(RenderViewHostImpl* render_view_host);
// If |render_frame_host| is on the pending deletion list, this deletes it.
// Returns whether it was deleted.
@@ -406,6 +396,9 @@ class CONTENT_EXPORT RenderFrameHostManager
// of WebContentsImpl.
void ResetProxyHosts();
+ void ClearRFHsPendingShutdown();
+ void ClearWebUIInstances();
+
// Returns the routing id for a RenderFrameHost or RenderFrameProxyHost
// that has the given SiteInstance and is associated with this
// RenderFrameHostManager. Returns MSG_ROUTING_NONE if none is found.
@@ -415,7 +408,7 @@ class CONTENT_EXPORT RenderFrameHostManager
// Notifies the RenderFrameHostManager that a new NavigationRequest has been
// created and set in the FrameTreeNode so that it can speculatively create a
// new RenderFrameHost (and potentially a new process) if needed.
- void DidCreateNavigationRequest(const NavigationRequest& request);
+ void DidCreateNavigationRequest(NavigationRequest* request);
// PlzNavigate
// Called (possibly several times) during a navigation to select or create an
@@ -439,9 +432,10 @@ class CONTENT_EXPORT RenderFrameHostManager
void OnDidStartLoading();
void OnDidStopLoading();
- // Send updated frame name to all frame proxies when the frame changes its
- // window.name property.
- void OnDidUpdateName(const std::string& name);
+ // OnDidUpdateName gets called when a frame changes its name - it gets the new
+ // |name| and the recalculated |unique_name| and replicates them into all
+ // frame proxies.
+ void OnDidUpdateName(const std::string& name, const std::string& unique_name);
// Sends updated enforcement of strict mixed content checking to all
// frame proxies when the frame changes its setting.
@@ -449,7 +443,8 @@ class CONTENT_EXPORT RenderFrameHostManager
// Send updated origin to all frame proxies when the frame navigates to a new
// origin.
- void OnDidUpdateOrigin(const url::Origin& origin);
+ void OnDidUpdateOrigin(const url::Origin& origin,
+ bool is_potentially_trustworthy_unique_origin);
void EnsureRenderViewInitialized(RenderViewHostImpl* render_view_host,
SiteInstance* instance);
@@ -489,19 +484,45 @@ class CONTENT_EXPORT RenderFrameHostManager
// an inner WebContents.
void SetRWHViewForInnerContents(RenderWidgetHostView* child_rwhv);
- // Returns a copy of the map of proxy hosts. The keys are SiteInstance IDs,
- // the values are RenderFrameProxyHosts.
- std::map<int, RenderFrameProxyHost*> GetAllProxyHostsForTesting();
+ // Returns the number of RenderFrameProxyHosts for this frame.
+ int GetProxyCount();
+
+ // Sends an IPC message to every process in the FrameTree. This should only be
+ // called in the top-level RenderFrameHostManager.
+ void SendPageMessage(IPC::Message* msg);
+
+ // Returns a const reference to the map of proxy hosts. The keys are
+ // SiteInstance IDs, the values are RenderFrameProxyHosts.
+ const std::unordered_map<int32_t, scoped_ptr<RenderFrameProxyHost>>&
+ GetAllProxyHostsForTesting() const {
+ return proxy_hosts_;
+ }
// SiteInstanceImpl::Observer
void ActiveFrameCountIsZero(SiteInstanceImpl* site_instance) override;
void RenderProcessGone(SiteInstanceImpl* site_instance) override;
+ // Sets up the necessary state for a new RenderViewHost. If |proxy| is not
+ // null, it creates a RenderFrameProxy in the target renderer process which is
+ // used to route IPC messages when in swapped out state. Returns early if the
+ // RenderViewHost has already been initialized for another RenderFrameHost.
+ bool InitRenderView(RenderViewHostImpl* render_view_host,
+ RenderFrameProxyHost* proxy);
+
private:
friend class NavigatorTestWithBrowserSideNavigation;
friend class RenderFrameHostManagerTest;
friend class TestWebContents;
+ enum class SiteInstanceRelation {
+ // A SiteInstance in a different browsing instance from the current.
+ UNRELATED,
+ // A SiteInstance in the same browsing instance as the current.
+ RELATED,
+ // The default subframe SiteInstance for the current browsing instance.
+ RELATED_DEFAULT_SUBFRAME,
+ };
+
// Stores information regarding a SiteInstance targeted at a specific URL to
// allow for comparisons without having to actually create new instances. It
// can point to an existing one or store the details needed to create a new
@@ -509,11 +530,11 @@ class CONTENT_EXPORT RenderFrameHostManager
struct CONTENT_EXPORT SiteInstanceDescriptor {
explicit SiteInstanceDescriptor(content::SiteInstance* site_instance)
: existing_site_instance(site_instance),
- new_is_related_to_current(false) {}
+ relation(SiteInstanceRelation::UNRELATED) {}
SiteInstanceDescriptor(BrowserContext* browser_context,
GURL dest_url,
- bool related_to_current);
+ SiteInstanceRelation relation_to_current);
// Set with an existing SiteInstance to be reused.
content::SiteInstance* existing_site_instance;
@@ -521,9 +542,9 @@ class CONTENT_EXPORT RenderFrameHostManager
// In case |existing_site_instance| is null, specify a new site URL.
GURL new_site_url;
- // In case |existing_site_instance| is null, specify if the new site should
- // be created in a new BrowsingInstance or not.
- bool new_is_related_to_current;
+ // In case |existing_site_instance| is null, specify how the new site is
+ // related to the current BrowsingInstance.
+ SiteInstanceRelation relation;
};
// Create a RenderFrameProxyHost owned by this object.
@@ -558,13 +579,14 @@ class CONTENT_EXPORT RenderFrameHostManager
bool new_is_view_source_mode) const;
// Returns the SiteInstance to use for the navigation.
- SiteInstance* GetSiteInstanceForNavigation(const GURL& dest_url,
- SiteInstance* source_instance,
- SiteInstance* dest_instance,
- SiteInstance* candidate_instance,
- ui::PageTransition transition,
- bool dest_is_restore,
- bool dest_is_view_source_mode);
+ scoped_refptr<SiteInstance> GetSiteInstanceForNavigation(
+ const GURL& dest_url,
+ SiteInstance* source_instance,
+ SiteInstance* dest_instance,
+ SiteInstance* candidate_instance,
+ ui::PageTransition transition,
+ bool dest_is_restore,
+ bool dest_is_view_source_mode);
// Returns a descriptor of the appropriate SiteInstance object for the given
// |dest_url|, possibly reusing the current, source or destination
@@ -593,14 +615,13 @@ class CONTENT_EXPORT RenderFrameHostManager
// Converts a SiteInstanceDescriptor to the actual SiteInstance it describes.
// If a |candidate_instance| is provided (is not nullptr) and it matches the
// description, it is returned as is.
- SiteInstance* ConvertToSiteInstance(const SiteInstanceDescriptor& descriptor,
- SiteInstance* candidate_instance);
+ scoped_refptr<SiteInstance> ConvertToSiteInstance(
+ const SiteInstanceDescriptor& descriptor,
+ SiteInstance* candidate_instance);
- // Determines the appropriate url to use as the current url for SiteInstance
- // selection.
- const GURL& GetCurrentURLForSiteInstance(
- SiteInstance* current_instance,
- NavigationEntry* current_entry);
+ // Returns true if |candidate| is currently on the same web site as dest_url.
+ bool IsCurrentlySameSite(RenderFrameHostImpl* candidate,
+ const GURL& dest_url);
// Creates a new RenderFrameHostImpl for the |new_instance| and assign it to
// |pending_render_frame_host_| while respecting the opener route if needed
@@ -641,7 +662,7 @@ class CONTENT_EXPORT RenderFrameHostManager
int32_t view_routing_id,
int32_t frame_routing_id,
int32_t widget_routing_id,
- int flags);
+ bool hidden);
// PlzNavigate
// Create and initialize a speculative RenderFrameHost for an ongoing
@@ -650,13 +671,6 @@ class CONTENT_EXPORT RenderFrameHostManager
bool CreateSpeculativeRenderFrameHost(SiteInstance* old_instance,
SiteInstance* new_instance);
- // Sets up the necessary state for a new RenderViewHost. If |proxy| is not
- // null, it creates a RenderFrameProxy in the target renderer process which is
- // used to route IPC messages when in swapped out state. Returns early if the
- // RenderViewHost has already been initialized for another RenderFrameHost.
- bool InitRenderView(RenderViewHostImpl* render_view_host,
- RenderFrameProxyHost* proxy);
-
// Initialization for RenderFrameHost uses the same sequence as InitRenderView
// above.
bool InitRenderFrame(RenderFrameHostImpl* render_frame_host);
@@ -757,13 +771,10 @@ class CONTENT_EXPORT RenderFrameHostManager
scoped_ptr<NavigationHandleImpl> transfer_navigation_handle_;
// Proxy hosts, indexed by site instance ID.
- base::ScopedPtrHashMap<int32_t, scoped_ptr<RenderFrameProxyHost>>
- proxy_hosts_;
+ std::unordered_map<int32_t, scoped_ptr<RenderFrameProxyHost>> proxy_hosts_;
- // A list of RenderFrameHosts waiting to shut down after swapping out. We use
- // a linked list since we expect frequent deletes and no indexed access, and
- // because sets don't appear to support linked_ptrs.
- typedef std::list<linked_ptr<RenderFrameHostImpl> > RFHPendingDeleteList;
+ // A list of RenderFrameHosts waiting to shut down after swapping out.
+ using RFHPendingDeleteList = std::list<scoped_ptr<RenderFrameHostImpl>>;
RFHPendingDeleteList pending_delete_hosts_;
// The intersitial page currently shown if any, not own by this class
diff --git a/chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc b/chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc
index afb1ca06df8..0e3bbedde79 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_manager_browsertest.cc
@@ -35,6 +35,7 @@
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/bindings_policy.h"
+#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/file_chooser_file_info.h"
#include "content/public/common/file_chooser_params.h"
@@ -47,10 +48,11 @@
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/test/content_browser_test_utils_internal.h"
-#include "net/base/net_util.h"
+#include "content/test/test_frame_navigation_observer.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/request_handler_util.h"
+#include "testing/gmock/include/gmock/gmock-matchers.h"
using base::ASCIIToUTF16;
@@ -1400,75 +1402,6 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, MAYBE_BackForwardNotStale) {
}
}
-// Test for http://crbug.com/130016.
-// Swapping out a render view should update its visiblity state.
-IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
- SwappedOutViewHasCorrectVisibilityState) {
- // This test is invalid in when swapped out is disabled.
- if (SiteIsolationPolicy::IsSwappedOutStateForbidden())
- return;
- StartEmbeddedServer();
-
- // Load a page with links that open in a new window.
- NavigateToPageWithLinks(shell());
-
- // Open a same-site link in a new widnow.
- ShellAddedObserver new_shell_observer;
- bool success = false;
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- shell()->web_contents(),
- "window.domAutomationController.send(clickSameSiteTargetedLink());",
- &success));
- EXPECT_TRUE(success);
- Shell* new_shell = new_shell_observer.GetShell();
-
- // Wait for the navigation in the new tab to finish, if it hasn't.
- WaitForLoadStop(new_shell->web_contents());
- EXPECT_EQ("/navigate_opener.html",
- new_shell->web_contents()->GetLastCommittedURL().path());
-
- RenderViewHost* rvh = new_shell->web_contents()->GetRenderViewHost();
-
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- rvh,
- "window.domAutomationController.send("
- " document.visibilityState == 'visible');",
- &success));
- EXPECT_TRUE(success);
-
- // Now navigate the new window to a different site. This should swap out the
- // tab's existing RenderView, causing it become hidden.
- NavigateToURL(new_shell,
- embedded_test_server()->GetURL("foo.com", "/title1.html"));
-
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- rvh,
- "window.domAutomationController.send("
- " document.visibilityState == 'hidden');",
- &success));
- EXPECT_TRUE(success);
-
- // Going back should make the previously swapped-out view to become visible
- // again.
- {
- TestNavigationObserver back_nav_load_observer(new_shell->web_contents());
- new_shell->web_contents()->GetController().GoBack();
- back_nav_load_observer.Wait();
- }
-
- EXPECT_EQ("/navigate_opener.html",
- new_shell->web_contents()->GetLastCommittedURL().path());
-
- EXPECT_EQ(rvh, new_shell->web_contents()->GetRenderViewHost());
-
- EXPECT_TRUE(ExecuteScriptAndExtractBool(
- rvh,
- "window.domAutomationController.send("
- " document.visibilityState == 'visible');",
- &success));
- EXPECT_TRUE(success);
-}
-
// This class ensures that all the given RenderViewHosts have properly been
// shutdown.
class RenderViewHostDestructionObserver : public WebContentsObserver {
@@ -1693,8 +1626,17 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
// Ensure that renderer-side debug URLs don't take effect on crashed renderers,
// even when going back/forward.
// See https://crbug.com/477606.
+
+// This test is flaky on Android. crbug.com/585327
+#if defined(OS_ANDROID)
+#define MAYBE_IgnoreForwardToRendererDebugURLsWhenCrashed \
+ DISABLED_IgnoreForwardToRendererDebugURLsWhenCrashed
+#else
+#define MAYBE_IgnoreForwardToRendererDebugURLsWhenCrashed \
+ IgnoreForwardToRendererDebugURLsWhenCrashed
+#endif
IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
- IgnoreForwardToRendererDebugURLsWhenCrashed) {
+ MAYBE_IgnoreForwardToRendererDebugURLsWhenCrashed) {
// Visit a WebUI page with bindings.
GURL webui_url = GURL(std::string(kChromeUIScheme) + "://" +
std::string(kChromeUIGpuHost));
@@ -2417,6 +2359,151 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
shell(), embedded_test_server()->GetURL("b.com", "/title3.html")));
}
+// Ensure that we don't crash the renderer in CreateRenderView if a proxy goes
+// away between swapout and the next navigation. See https://crbug.com/581912.
+// Dr.Memory reports a use-after-free in this test, thus it may be flaky on
+// Windows. See https://crbug.com/600957.
+#if defined(OS_WIN)
+#define MAYBE_CreateRenderViewAfterProcessKillAndClosedProxy \
+ DISABLED_CreateRenderViewAfterProcessKillAndClosedProxy
+#else
+#define MAYBE_CreateRenderViewAfterProcessKillAndClosedProxy \
+ CreateRenderViewAfterProcessKillAndClosedProxy
+#endif
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
+ MAYBE_CreateRenderViewAfterProcessKillAndClosedProxy) {
+ StartEmbeddedServer();
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // Give an initial page an unload handler that never completes.
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("a.com", "/title1.html")));
+ EXPECT_TRUE(ExecuteScript(root->current_frame_host(),
+ "window.onunload=function(e){ while(1); };\n"));
+
+ // Open a popup in the same process.
+ Shell* new_shell =
+ OpenPopup(shell()->web_contents(), GURL(url::kAboutBlankURL), "foo");
+ FrameTreeNode* popup_root =
+ static_cast<WebContentsImpl*>(new_shell->web_contents())
+ ->GetFrameTree()
+ ->root();
+ EXPECT_EQ(shell()->web_contents()->GetSiteInstance(),
+ new_shell->web_contents()->GetSiteInstance());
+
+ // Navigate the first tab to a different site, and only wait for commit, not
+ // load stop.
+ RenderFrameHostImpl* rfh_a = root->current_frame_host();
+ SiteInstanceImpl* site_instance_a = rfh_a->GetSiteInstance();
+ TestFrameNavigationObserver commit_observer(root);
+ shell()->LoadURL(embedded_test_server()->GetURL("b.com", "/title2.html"));
+ commit_observer.WaitForCommit();
+ rfh_a->ResetSwapOutTimerForTesting();
+ EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
+ new_shell->web_contents()->GetSiteInstance());
+ EXPECT_TRUE(root->render_manager()->GetRenderFrameProxyHost(site_instance_a));
+
+ // The previous RFH should still be pending deletion, as we wait for either
+ // the SwapOut ACK or a timeout.
+ ASSERT_TRUE(rfh_a->IsRenderFrameLive());
+ ASSERT_FALSE(rfh_a->is_active());
+
+ // The corresponding RVH should not be pending deletion due to the proxy.
+ EXPECT_FALSE(root->render_manager()->IsViewPendingDeletion(
+ rfh_a->render_view_host()));
+
+ // Kill the old process.
+ RenderProcessHost* process = rfh_a->GetProcess();
+ RenderProcessHostWatcher crash_observer(
+ process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+ process->Shutdown(0, false);
+ crash_observer.Wait();
+ EXPECT_FALSE(popup_root->current_frame_host()->IsRenderFrameLive());
+ // |rfh_a| is now deleted, thanks to the bug fix.
+
+ // Close the popup so there is no proxy for a.com in the original tab.
+ new_shell->Close();
+ EXPECT_FALSE(
+ root->render_manager()->GetRenderFrameProxyHost(site_instance_a));
+
+ // Go back in the main frame from b.com to a.com. In https://crbug.com/581912,
+ // the browser process would crash here because there was no main frame
+ // routing ID or proxy in RVHI::CreateRenderView.
+ {
+ TestNavigationObserver back_nav_load_observer(shell()->web_contents());
+ shell()->web_contents()->GetController().GoBack();
+ back_nav_load_observer.Wait();
+ }
+}
+
+// Ensure that we don't crash in RenderViewImpl::Init if a proxy is created
+// after swapout and before navigation. See https://crbug.com/544755.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
+ RenderViewInitAfterNewProxyAndProcessKill) {
+ StartEmbeddedServer();
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // Give an initial page an unload handler that never completes.
+ EXPECT_TRUE(NavigateToURL(
+ shell(), embedded_test_server()->GetURL("a.com", "/title1.html")));
+ EXPECT_TRUE(ExecuteScript(root->current_frame_host(),
+ "window.onunload=function(e){ while(1); };\n"));
+
+ // Navigate the tab to a different site, and only wait for commit, not load
+ // stop.
+ RenderFrameHostImpl* rfh_a = root->current_frame_host();
+ SiteInstanceImpl* site_instance_a = rfh_a->GetSiteInstance();
+ TestFrameNavigationObserver commit_observer(root);
+ shell()->LoadURL(embedded_test_server()->GetURL("b.com", "/title2.html"));
+ commit_observer.WaitForCommit();
+ rfh_a->ResetSwapOutTimerForTesting();
+ EXPECT_NE(site_instance_a, shell()->web_contents()->GetSiteInstance());
+
+ // The previous RFH and RVH should still be pending deletion, as we wait for
+ // either the SwapOut ACK or a timeout.
+ ASSERT_TRUE(rfh_a->IsRenderFrameLive());
+ ASSERT_FALSE(rfh_a->is_active());
+ EXPECT_TRUE(root->render_manager()->IsViewPendingDeletion(
+ rfh_a->render_view_host()));
+
+ // Open a popup in the new B process.
+ Shell* new_shell =
+ OpenPopup(shell()->web_contents(), GURL(url::kAboutBlankURL), "foo");
+ EXPECT_EQ(shell()->web_contents()->GetSiteInstance(),
+ new_shell->web_contents()->GetSiteInstance());
+
+ // Navigate the popup to the original site, but don't wait for commit (which
+ // won't happen). This creates a proxy in the original tab, alongside the
+ // RFH and RVH pending deletion.
+ new_shell->LoadURL(embedded_test_server()->GetURL("a.com", "/title2.html"));
+ EXPECT_TRUE(root->render_manager()->GetRenderFrameProxyHost(site_instance_a));
+
+ // Kill the old process.
+ RenderProcessHost* process = rfh_a->GetProcess();
+ RenderProcessHostWatcher crash_observer(
+ process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+ process->Shutdown(0, false);
+ crash_observer.Wait();
+ // |rfh_a| is now deleted, thanks to the bug fix.
+
+ // Go back in the main frame from b.com to a.com.
+ {
+ TestNavigationObserver back_nav_load_observer(shell()->web_contents());
+ shell()->web_contents()->GetController().GoBack();
+ back_nav_load_observer.Wait();
+ }
+
+ // In https://crbug.com/581912, the renderer process would crash here because
+ // there was a frame, view, and proxy (and is_swapped_out was true).
+ EXPECT_EQ(site_instance_a, root->current_frame_host()->GetSiteInstance());
+ EXPECT_TRUE(root->current_frame_host()->IsRenderFrameLive());
+ EXPECT_TRUE(new_shell->web_contents()->GetMainFrame()->IsRenderFrameLive());
+}
+
// Ensure that we use the same pending RenderFrameHost if a second navigation to
// its site occurs before it commits. Otherwise the renderer process will have
// two competing pending RenderFrames that both try to swap with the same
@@ -2441,23 +2528,173 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
shell()->web_contents());
- RenderFrameHostImpl* pending_rfh =
- web_contents->GetRenderManagerForTesting()->pending_frame_host();
- ASSERT_TRUE(pending_rfh);
+ RenderFrameHostImpl* next_rfh =
+ IsBrowserSideNavigationEnabled()
+ ? web_contents->GetRenderManagerForTesting()->speculative_frame_host()
+ : web_contents->GetRenderManagerForTesting()->pending_frame_host();
+ ASSERT_TRUE(next_rfh);
// Navigate to the same new site and verify that we commit in the same RFH.
GURL cross_site_url2(embedded_test_server()->GetURL("b.com", "/title2.html"));
TestNavigationObserver navigation_observer(web_contents, 1);
shell()->LoadURL(cross_site_url2);
- EXPECT_EQ(pending_rfh,
- web_contents->GetRenderManagerForTesting()->pending_frame_host());
+ if (IsBrowserSideNavigationEnabled()) {
+ EXPECT_EQ(
+ next_rfh,
+ web_contents->GetRenderManagerForTesting()->speculative_frame_host());
+ } else {
+ EXPECT_EQ(next_rfh,
+ web_contents->GetRenderManagerForTesting()->pending_frame_host());
+ }
navigation_observer.Wait();
EXPECT_EQ(cross_site_url2, web_contents->GetLastCommittedURL());
- EXPECT_EQ(pending_rfh, web_contents->GetMainFrame());
- EXPECT_FALSE(
- web_contents->GetRenderManagerForTesting()->pending_frame_host());
+ EXPECT_EQ(next_rfh, web_contents->GetMainFrame());
+ if (IsBrowserSideNavigationEnabled()) {
+ EXPECT_FALSE(
+ web_contents->GetRenderManagerForTesting()->speculative_frame_host());
+ } else {
+ EXPECT_FALSE(
+ web_contents->GetRenderManagerForTesting()->pending_frame_host());
+ }
ResourceDispatcherHost::Get()->SetDelegate(nullptr);
}
+// Check that if a sandboxed subframe opens a cross-process popup such that the
+// popup's opener won't be set, the popup still inherits the subframe's sandbox
+// flags. This matters for rel=noopener and rel=noreferrer links, as well as
+// for some situations in non-site-per-process mode where the popup would
+// normally maintain the opener, but loses it due to being placed in a new
+// process and not creating subframe proxies. The latter might happen when
+// opening the default search provider site. See https://crbug.com/576204.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
+ CrossProcessPopupInheritsSandboxFlagsWithNoOpener) {
+ StartEmbeddedServer();
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ // Add a sandboxed about:blank iframe.
+ {
+ std::string script =
+ "var frame = document.createElement('iframe');\n"
+ "frame.sandbox = 'allow-scripts allow-popups';\n"
+ "document.body.appendChild(frame);\n";
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(), script));
+ }
+
+ // Navigate iframe to a page with target=_blank links, and rewrite the links
+ // to point to valid cross-site URLs.
+ GURL frame_url(
+ embedded_test_server()->GetURL("a.com", "/click-noreferrer-links.html"));
+ NavigateFrameToURL(root->child_at(0), frame_url);
+ std::string script = "setOriginForLinks('http://b.com:" +
+ embedded_test_server()->base_url().port() + "/');";
+ EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), script));
+
+ // Helper to click on the 'rel=noreferrer target=_blank' and 'rel=noopener
+ // target=_blank' links. Checks that these links open a popup that ends up
+ // in a new SiteInstance even without site-per-process and then verifies that
+ // the popup is still sandboxed.
+ auto click_link_and_verify_popup = [this,
+ root](std::string link_opening_script) {
+ ShellAddedObserver new_shell_observer;
+ bool success = false;
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(
+ root->child_at(0)->current_frame_host(),
+ "window.domAutomationController.send(" + link_opening_script + ")",
+ &success));
+ EXPECT_TRUE(success);
+
+ Shell* new_shell = new_shell_observer.GetShell();
+ EXPECT_TRUE(WaitForLoadStop(new_shell->web_contents()));
+ EXPECT_NE(new_shell->web_contents()->GetSiteInstance(),
+ shell()->web_contents()->GetSiteInstance());
+
+ // Check that the popup is sandboxed by checking its document.origin, which
+ // should be unique.
+ std::string origin;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ new_shell->web_contents(),
+ "domAutomationController.send(document.origin)", &origin));
+ EXPECT_EQ("null", origin);
+ };
+
+ click_link_and_verify_popup("clickNoOpenerTargetBlankLink()");
+ click_link_and_verify_popup("clickNoRefTargetBlankLink()");
+}
+
+// When two frames are same-origin but cross-process, they should behave as if
+// they are not same-origin and should not crash.
+IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest,
+ SameOriginFramesInDifferentProcesses) {
+ StartEmbeddedServer();
+
+ // Load a page with links that open in a new window.
+ NavigateToURL(shell(), embedded_test_server()->GetURL(
+ "a.com", "/click-noreferrer-links.html"));
+
+ // Get the original SiteInstance for later comparison.
+ scoped_refptr<SiteInstance> orig_site_instance(
+ shell()->web_contents()->GetSiteInstance());
+ EXPECT_NE(nullptr, orig_site_instance.get());
+
+ // Test clicking a target=foo link.
+ ShellAddedObserver new_shell_observer;
+ bool success = false;
+ EXPECT_TRUE(ExecuteScriptAndExtractBool(
+ shell()->web_contents(),
+ "window.domAutomationController.send(clickSameSiteTargetedLink());"
+ "saveWindowReference();",
+ &success));
+ EXPECT_TRUE(success);
+ Shell* new_shell = new_shell_observer.GetShell();
+
+ // Wait for the navigation in the new tab to finish, if it hasn't.
+ WaitForLoadStop(new_shell->web_contents());
+ EXPECT_EQ("/navigate_opener.html",
+ new_shell->web_contents()->GetLastCommittedURL().path());
+
+ // Do a cross-site navigation that winds up same-site. The same-site
+ // navigation to a.com will commit in a different process than the original
+ // a.com window.
+ NavigateToURL(new_shell, embedded_test_server()->GetURL(
+ "b.com", "/cross-site/a.com/title1.html"));
+ if (AreAllSitesIsolatedForTesting()) {
+ // In --site-per-process mode, both windows will actually be in the same
+ // process.
+ EXPECT_EQ(shell()->web_contents()->GetSiteInstance(),
+ new_shell->web_contents()->GetSiteInstance());
+ } else {
+ EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
+ new_shell->web_contents()->GetSiteInstance());
+ }
+
+ std::string result;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ shell()->web_contents(),
+ "window.domAutomationController.send((function() {\n"
+ " try {\n"
+ " return getLastOpenedWindowLocation();\n"
+ " } catch (e) {\n"
+ " return e.toString();\n"
+ " }\n"
+ "})())",
+ &result));
+ if (AreAllSitesIsolatedForTesting()) {
+ EXPECT_THAT(result,
+ ::testing::MatchesRegex("http://a.com:\\d+/title1.html"));
+ } else {
+ // Accessing a property with normal security checks should throw a
+ // SecurityError if the same-origin windows are in different processes.
+ EXPECT_THAT(result,
+ ::testing::MatchesRegex("SecurityError: Blocked a frame with "
+ "origin \"http://a.com:\\d+\" from "
+ "accessing a cross-origin frame."));
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc b/chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc
index e6e53607689..7556b4050ab 100644
--- a/chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc
+++ b/chromium/content/browser/frame_host/render_frame_host_manager_unittest.cc
@@ -347,7 +347,7 @@ class RenderFrameHostManagerTest : public RenderViewHostImplTestHarness {
TestRenderFrameHost* active_rfh = contents()->GetPendingMainFrame()
? contents()->GetPendingMainFrame()
: old_rfh;
- EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, old_rfh->rfh_state());
+ EXPECT_TRUE(old_rfh->is_active());
// Commit the navigation with a new page ID.
int32_t max_page_id =
@@ -360,32 +360,15 @@ class RenderFrameHostManagerTest : public RenderViewHostImplTestHarness {
active_rfh->SendNavigate(max_page_id + 1, entry_id, true, url);
// Make sure that we start to run the unload handler at the time of commit.
- bool expecting_rfh_shutdown = false;
if (old_rfh != active_rfh && !rfh_observer.deleted()) {
- EXPECT_EQ(RenderFrameHostImpl::STATE_PENDING_SWAP_OUT,
- old_rfh->rfh_state());
- if (!old_rfh->GetSiteInstance()->active_frame_count() ||
- SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- expecting_rfh_shutdown = true;
- EXPECT_TRUE(
- old_rfh->frame_tree_node()->render_manager()->IsPendingDeletion(
- old_rfh));
- }
+ EXPECT_FALSE(old_rfh->is_active());
}
// Simulate the swap out ACK coming from the pending renderer. This should
// either shut down the old RFH or leave it in a swapped out state.
if (old_rfh != active_rfh) {
old_rfh->OnSwappedOut();
- if (expecting_rfh_shutdown) {
- EXPECT_TRUE(rfh_observer.deleted());
- if (!SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- EXPECT_TRUE(rvh_observer.deleted());
- }
- } else {
- EXPECT_EQ(RenderFrameHostImpl::STATE_SWAPPED_OUT,
- old_rfh->rfh_state());
- }
+ EXPECT_TRUE(rfh_observer.deleted());
}
EXPECT_EQ(active_rfh, contents()->GetMainFrame());
EXPECT_EQ(NULL, contents()->GetPendingMainFrame());
@@ -411,8 +394,8 @@ class RenderFrameHostManagerTest : public RenderViewHostImplTestHarness {
new_entry->IsViewSourceMode());
}
- // Creates a test RenderFrameHost that's swapped out.
- TestRenderFrameHost* CreateSwappedOutRenderFrameHost() {
+ // Creates a test RenderViewHost that's swapped out.
+ void CreateSwappedOutRenderViewHost() {
const GURL kChromeURL("chrome://foo");
const GURL kDestUrl("http://www.google.com/");
@@ -441,9 +424,6 @@ class RenderFrameHostManagerTest : public RenderViewHostImplTestHarness {
dest_rfh->SendNavigate(101, entry_id, true, kDestUrl);
ntp_rfh->OnSwappedOut();
-
- EXPECT_TRUE(ntp_rfh->is_swapped_out());
- return ntp_rfh;
}
// Returns the RenderFrameHost that should be used in the navigation to
@@ -459,20 +439,19 @@ class RenderFrameHostManagerTest : public RenderViewHostImplTestHarness {
->frame_tree_node()
->navigator()
->GetController());
- // TODO(carlosk): This implementation below will not work with restore
- // navigations. Method GetNavigationType should be exposed from
- // navigator_impl.cc and used here to determine FrameMsg_Navigate_Type.
- CHECK(entry.restore_type() == NavigationEntryImpl::RESTORE_NONE);
+ FrameMsg_Navigate_Type::Value navigate_type =
+ entry.restore_type() == NavigationEntryImpl::RESTORE_NONE
+ ? FrameMsg_Navigate_Type::NORMAL
+ : FrameMsg_Navigate_Type::RESTORE;
scoped_ptr<NavigationRequest> navigation_request =
NavigationRequest::CreateBrowserInitiated(
manager->frame_tree_node_, frame_entry->url(),
- frame_entry->referrer(), *frame_entry, entry,
- FrameMsg_Navigate_Type::NORMAL, false, base::TimeTicks::Now(),
- controller);
+ frame_entry->referrer(), *frame_entry, entry, navigate_type,
+ LOFI_UNSPECIFIED, false, base::TimeTicks::Now(), controller);
// Simulates request creation that triggers the 1st internal call to
// GetFrameHostForNavigation.
- manager->DidCreateNavigationRequest(*navigation_request);
+ manager->DidCreateNavigationRequest(navigation_request.get());
// And also simulates the 2nd and final call to GetFrameHostForNavigation
// that determines the final frame that will commit the navigation.
@@ -643,50 +622,6 @@ TEST_F(RenderFrameHostManagerTest, FilterMessagesWhileSwappedOut) {
dest_rfh->GetRenderViewHost()->GetRoutingID(), icons)));
EXPECT_FALSE(observer.favicon_received());
}
-
- // In --site-per-process, the RenderFrameHost is deleted on cross-process
- // navigation, so the rest of the test case doesn't apply.
- if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- return;
- }
-
-#if defined(ENABLE_PLUGINS)
- // The same logic should apply to RenderFrameHosts as well and routing through
- // swapped out RFH shouldn't be allowed. Use a PluginCrashObserver to check
- // if the IPC message is allowed through or not.
- {
- PluginFaviconMessageObserver observer(contents());
- EXPECT_TRUE(ntp_rfh->OnMessageReceived(
- FrameHostMsg_PluginCrashed(
- ntp_rfh->GetRoutingID(), base::FilePath(), 0)));
- EXPECT_FALSE(observer.plugin_crashed());
- }
-#endif
-
- // We cannot filter out synchronous IPC messages, because the renderer would
- // be left waiting for a reply. We pick RunBeforeUnloadConfirm as an example
- // that can run easily within a unit test, and that needs to receive a reply
- // without showing an actual dialog.
- MockRenderProcessHost* ntp_process_host = ntp_rfh->GetProcess();
- ntp_process_host->sink().ClearMessages();
- const base::string16 msg = base::ASCIIToUTF16("Message");
- bool result = false;
- base::string16 unused;
- FrameHostMsg_RunBeforeUnloadConfirm before_unload_msg(
- ntp_rfh->GetRoutingID(), kChromeURL, msg, false, &result, &unused);
- // Enable pumping for check in BrowserMessageFilter::CheckCanDispatchOnUI.
- before_unload_msg.EnableMessagePumping();
- EXPECT_TRUE(ntp_rfh->OnMessageReceived(before_unload_msg));
- EXPECT_TRUE(ntp_process_host->sink().GetUniqueMessageMatching(IPC_REPLY_ID));
-
- // Also test RunJavaScriptMessage.
- ntp_process_host->sink().ClearMessages();
- FrameHostMsg_RunJavaScriptMessage js_msg(
- ntp_rfh->GetRoutingID(), msg, msg, kChromeURL,
- JAVASCRIPT_MESSAGE_TYPE_CONFIRM, &result, &unused);
- js_msg.EnableMessagePumping();
- EXPECT_TRUE(ntp_rfh->OnMessageReceived(js_msg));
- EXPECT_TRUE(ntp_process_host->sink().GetUniqueMessageMatching(IPC_REPLY_ID));
}
// Test that the ViewHostMsg_UpdateFaviconURL IPC message is ignored if the
@@ -723,8 +658,8 @@ TEST_F(RenderFrameHostManagerTest, UpdateFaviconURLWhilePendingSwapOut) {
TestRenderFrameHost* rfh2 = contents()->GetPendingMainFrame();
contents()->TestDidNavigate(rfh2, 1, entry_id, true, kDestUrl,
ui::PAGE_TRANSITION_TYPED);
- EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh2->rfh_state());
- EXPECT_EQ(RenderFrameHostImpl::STATE_PENDING_SWAP_OUT, rfh1->rfh_state());
+ EXPECT_FALSE(rfh1->is_active());
+ EXPECT_TRUE(rfh2->is_active());
// The new RVH should be able to update its favicons.
{
@@ -746,95 +681,13 @@ TEST_F(RenderFrameHostManagerTest, UpdateFaviconURLWhilePendingSwapOut) {
}
}
-// Ensure that frames aren't added to the frame tree, if the message is coming
-// from a process different than the parent frame's current RenderFrameHost
-// process. Otherwise it is possible to have collisions of routing ids, as they
-// are scoped per process. See https://crbug.com/415059.
-TEST_F(RenderFrameHostManagerTest, DropCreateChildFrameWhileSwappedOut) {
- const GURL kUrl1("http://foo.com");
- const GURL kUrl2("http://www.google.com/");
-
- // This test is invalid in --site-per-process mode, as swapped-out is no
- // longer used.
- if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- return;
- }
-
- // Navigate to the first site.
- NavigateActiveAndCommit(kUrl1);
- TestRenderFrameHost* initial_rfh = contents()->GetMainFrame();
- {
- RenderFrameHostCreatedObserver observer(contents());
- initial_rfh->OnCreateChildFrame(
- initial_rfh->GetProcess()->GetNextRoutingID(),
- blink::WebTreeScopeType::Document, std::string(),
- blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
- EXPECT_TRUE(observer.created());
- }
-
- // Create one more frame in the same SiteInstance where initial_rfh
- // exists so that initial_rfh doesn't get deleted on navigation to another
- // site.
- initial_rfh->GetSiteInstance()->IncrementActiveFrameCount();
-
- // Navigate to a cross-site URL.
- NavigateActiveAndCommit(kUrl2);
- EXPECT_TRUE(initial_rfh->is_swapped_out());
-
- TestRenderFrameHost* dest_rfh = contents()->GetMainFrame();
- ASSERT_TRUE(dest_rfh);
- EXPECT_NE(initial_rfh, dest_rfh);
-
- {
- // Since the old RFH is now swapped out, it shouldn't process any messages
- // to create child frames.
- RenderFrameHostCreatedObserver observer(contents());
- initial_rfh->OnCreateChildFrame(
- initial_rfh->GetProcess()->GetNextRoutingID(),
- blink::WebTreeScopeType::Document, std::string(),
- blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
- EXPECT_FALSE(observer.created());
- }
-}
-
-TEST_F(RenderFrameHostManagerTest, WhiteListSwapCompositorFrame) {
- // TODO(nasko): Check with kenrb whether this test can be rewritten and
- // whether it makes sense when swapped out is replaced with proxies.
- if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- return;
- }
- TestRenderFrameHost* swapped_out_rfh = CreateSwappedOutRenderFrameHost();
- TestRenderWidgetHostView* swapped_out_rwhv =
- static_cast<TestRenderWidgetHostView*>(
- swapped_out_rfh->GetRenderViewHost()->GetWidget()->GetView());
- EXPECT_FALSE(swapped_out_rwhv->did_swap_compositor_frame());
-
- MockRenderProcessHost* process_host = swapped_out_rfh->GetProcess();
- process_host->sink().ClearMessages();
-
- cc::CompositorFrame frame;
- ViewHostMsg_SwapCompositorFrame msg(
- rvh()->GetRoutingID(), 0, frame, std::vector<IPC::Message>());
-
- EXPECT_TRUE(
- swapped_out_rfh->render_view_host()->GetWidget()->OnMessageReceived(msg));
- EXPECT_TRUE(swapped_out_rwhv->did_swap_compositor_frame());
-}
-
// Test if RenderViewHost::GetRenderWidgetHosts() only returns active
// widgets.
TEST_F(RenderFrameHostManagerTest, GetRenderWidgetHostsReturnsActiveViews) {
- // This test is invalid in --site-per-process mode, as swapped-out is no
- // longer used.
- if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- return;
- }
-
- TestRenderFrameHost* swapped_out_rfh = CreateSwappedOutRenderFrameHost();
- EXPECT_TRUE(swapped_out_rfh->is_swapped_out());
-
+ CreateSwappedOutRenderViewHost();
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.
@@ -851,15 +704,7 @@ TEST_F(RenderFrameHostManagerTest, GetRenderWidgetHostsReturnsActiveViews) {
// including swapped out ones.
TEST_F(RenderFrameHostManagerTest,
GetRenderWidgetHostsWithinGetAllRenderWidgetHosts) {
- // This test is invalid in --site-per-process mode, as swapped-out is no
- // longer used.
- if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- return;
- }
-
- TestRenderFrameHost* swapped_out_rfh = CreateSwappedOutRenderFrameHost();
- EXPECT_TRUE(swapped_out_rfh->is_swapped_out());
-
+ CreateSwappedOutRenderViewHost();
scoped_ptr<RenderWidgetHostIterator> widgets(
RenderWidgetHost::GetRenderWidgetHosts());
@@ -1044,14 +889,14 @@ TEST_F(RenderFrameHostManagerTest, AlwaysSendEnableViewSourceMode) {
// New message should be sent out to make sure to enter view-source mode.
EXPECT_TRUE(process()->sink().GetUniqueMessageMatching(
- ViewMsg_EnableViewSourceMode::ID));
+ FrameMsg_EnableViewSourceMode::ID));
}
// Tests the Init function by checking the initial RenderViewHost.
TEST_F(RenderFrameHostManagerTest, Init) {
// Using TestBrowserContext.
- SiteInstanceImpl* instance =
- static_cast<SiteInstanceImpl*>(SiteInstance::Create(browser_context()));
+ scoped_refptr<SiteInstanceImpl> instance =
+ SiteInstanceImpl::Create(browser_context());
EXPECT_FALSE(instance->HasSite());
scoped_ptr<TestWebContents> web_contents(
@@ -1073,10 +918,8 @@ TEST_F(RenderFrameHostManagerTest, Init) {
// Tests the Navigate function. We navigate three sites consecutively and check
// how the pending/committed RenderViewHost are modified.
TEST_F(RenderFrameHostManagerTest, Navigate) {
- SiteInstance* instance = SiteInstance::Create(browser_context());
-
- scoped_ptr<TestWebContents> web_contents(
- TestWebContents::Create(browser_context(), instance));
+ scoped_ptr<TestWebContents> web_contents(TestWebContents::Create(
+ browser_context(), SiteInstance::Create(browser_context())));
RenderViewHostChangedObserver change_observer(web_contents.get());
RenderFrameHostManager* manager = web_contents->GetRenderManagerForTesting();
@@ -1151,7 +994,8 @@ TEST_F(RenderFrameHostManagerTest, Navigate) {
// Tests WebUI creation.
TEST_F(RenderFrameHostManagerTest, WebUI) {
set_should_create_webui(true);
- SiteInstance* instance = SiteInstance::Create(browser_context());
+ scoped_refptr<SiteInstance> instance =
+ SiteInstance::Create(browser_context());
scoped_ptr<TestWebContents> web_contents(
TestWebContents::Create(browser_context(), instance));
@@ -1209,7 +1053,8 @@ TEST_F(RenderFrameHostManagerTest, WebUI) {
// grant the correct bindings. http://crbug.com/189101.
TEST_F(RenderFrameHostManagerTest, WebUIInNewTab) {
set_should_create_webui(true);
- SiteInstance* blank_instance = SiteInstance::Create(browser_context());
+ scoped_refptr<SiteInstance> blank_instance =
+ SiteInstance::Create(browser_context());
blank_instance->GetProcess()->Init();
// Create a blank tab.
@@ -1436,7 +1281,7 @@ TEST_F(RenderFrameHostManagerTest, NavigateAfterMissingSwapOutACK) {
contents()->GetPendingMainFrame()->SendNavigate(
entry1->GetPageID(), entry1->GetUniqueID(), false, entry1->GetURL());
EXPECT_TRUE(rfh2->IsWaitingForUnloadACK());
- EXPECT_EQ(RenderFrameHostImpl::STATE_PENDING_SWAP_OUT, rfh2->rfh_state());
+ EXPECT_FALSE(rfh2->is_active());
// We should be able to navigate forward.
contents()->GetController().GoForward();
@@ -1444,14 +1289,7 @@ TEST_F(RenderFrameHostManagerTest, NavigateAfterMissingSwapOutACK) {
const NavigationEntry* entry2 = contents()->GetController().GetPendingEntry();
contents()->GetPendingMainFrame()->SendNavigate(
entry2->GetPageID(), entry2->GetUniqueID(), false, entry2->GetURL());
- EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, main_test_rfh()->rfh_state());
- if (!SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- EXPECT_EQ(rfh2, main_test_rfh());
- EXPECT_EQ(RenderFrameHostImpl::STATE_PENDING_SWAP_OUT, rfh1->rfh_state());
- rfh1->OnSwappedOut();
- EXPECT_TRUE(rfh1->is_swapped_out());
- EXPECT_EQ(RenderFrameHostImpl::STATE_SWAPPED_OUT, rfh1->rfh_state());
- }
+ EXPECT_TRUE(main_test_rfh()->is_active());
}
// Test that we create swapped out RFHs for the opener chain when navigating an
@@ -1493,17 +1331,8 @@ TEST_F(RenderFrameHostManagerTest, CreateSwappedOutOpenerRFHs) {
EXPECT_TRUE(site_instance1->IsRelatedSiteInstance(rfh2->GetSiteInstance()));
// Ensure rvh1 is placed on swapped out list of the current tab.
- if (!SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- EXPECT_TRUE(manager->IsRVHOnSwappedOutList(rvh1));
- EXPECT_FALSE(rfh1_deleted_observer.deleted());
- EXPECT_TRUE(manager->IsOnSwappedOutList(rfh1));
- EXPECT_EQ(rfh1,
- manager->GetRenderFrameProxyHost(site_instance1.get())
- ->render_frame_host());
- } else {
- EXPECT_TRUE(rfh1_deleted_observer.deleted());
- EXPECT_TRUE(manager->GetRenderFrameProxyHost(site_instance1.get()));
- }
+ EXPECT_TRUE(rfh1_deleted_observer.deleted());
+ EXPECT_TRUE(manager->GetRenderFrameProxyHost(site_instance1.get()));
EXPECT_EQ(rvh1,
manager->GetSwappedOutRenderViewHost(rvh1->GetSiteInstance()));
@@ -1513,13 +1342,7 @@ TEST_F(RenderFrameHostManagerTest, CreateSwappedOutOpenerRFHs) {
RenderFrameHostImpl* opener1_rfh = opener1_proxy->render_frame_host();
TestRenderViewHost* opener1_rvh = static_cast<TestRenderViewHost*>(
opener1_manager->GetSwappedOutRenderViewHost(rvh2->GetSiteInstance()));
- if (!SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- EXPECT_TRUE(opener1_manager->IsOnSwappedOutList(opener1_rfh));
- EXPECT_TRUE(opener1_manager->IsRVHOnSwappedOutList(opener1_rvh));
- EXPECT_TRUE(opener1_rfh->is_swapped_out());
- } else {
- EXPECT_FALSE(opener1_rfh);
- }
+ EXPECT_FALSE(opener1_rfh);
EXPECT_FALSE(opener1_rvh->is_active());
// Ensure a swapped out RFH and RVH is created in the second opener tab.
@@ -1528,13 +1351,7 @@ TEST_F(RenderFrameHostManagerTest, CreateSwappedOutOpenerRFHs) {
RenderFrameHostImpl* opener2_rfh = opener2_proxy->render_frame_host();
TestRenderViewHost* opener2_rvh = static_cast<TestRenderViewHost*>(
opener2_manager->GetSwappedOutRenderViewHost(rvh2->GetSiteInstance()));
- if (!SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- EXPECT_TRUE(opener2_manager->IsOnSwappedOutList(opener2_rfh));
- EXPECT_TRUE(opener2_manager->IsRVHOnSwappedOutList(opener2_rvh));
- EXPECT_TRUE(opener2_rfh->is_swapped_out());
- } else {
- EXPECT_FALSE(opener2_rfh);
- }
+ EXPECT_FALSE(opener2_rfh);
EXPECT_FALSE(opener2_rvh->is_active());
// Navigate to a cross-BrowsingInstance URL.
@@ -1781,13 +1598,7 @@ TEST_F(RenderFrameHostManagerTest, EnableWebUIWithSwappedOutOpener) {
RenderFrameHostImpl* opener1_rfh = opener1_proxy->render_frame_host();
TestRenderViewHost* opener1_rvh = static_cast<TestRenderViewHost*>(
opener1_manager->GetSwappedOutRenderViewHost(rvh2->GetSiteInstance()));
- if (!SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- EXPECT_TRUE(opener1_manager->IsOnSwappedOutList(opener1_rfh));
- EXPECT_TRUE(opener1_manager->IsRVHOnSwappedOutList(opener1_rvh));
- EXPECT_TRUE(opener1_rfh->is_swapped_out());
- } else {
- EXPECT_FALSE(opener1_rfh);
- }
+ EXPECT_FALSE(opener1_rfh);
EXPECT_FALSE(opener1_rvh->is_active());
// Ensure the new RVH has WebUI bindings.
@@ -1797,7 +1608,7 @@ TEST_F(RenderFrameHostManagerTest, EnableWebUIWithSwappedOutOpener) {
// Test that we reuse the same guest SiteInstance if we navigate across sites.
TEST_F(RenderFrameHostManagerTest, NoSwapOnGuestNavigations) {
GURL guest_url(std::string(kGuestScheme).append("://abc123"));
- SiteInstance* instance =
+ scoped_refptr<SiteInstance> instance =
SiteInstance::CreateForURL(browser_context(), guest_url);
scoped_ptr<TestWebContents> web_contents(
TestWebContents::Create(browser_context(), instance));
@@ -1852,7 +1663,8 @@ TEST_F(RenderFrameHostManagerTest, NoSwapOnGuestNavigations) {
TEST_F(RenderFrameHostManagerTest, NavigateWithEarlyClose) {
TestNotificationTracker notifications;
- SiteInstance* instance = SiteInstance::Create(browser_context());
+ scoped_refptr<SiteInstance> instance =
+ SiteInstance::Create(browser_context());
BeforeUnloadFiredWebContentsDelegate delegate;
scoped_ptr<TestWebContents> web_contents(
@@ -1898,7 +1710,6 @@ TEST_F(RenderFrameHostManagerTest, NavigateWithEarlyClose) {
EXPECT_NE(host2, host);
EXPECT_EQ(host, manager->current_frame_host());
- EXPECT_FALSE(manager->current_frame_host()->is_swapped_out());
EXPECT_EQ(host2, GetPendingFrameHost(manager));
// 3) Close the tab. -------------------------
@@ -1951,7 +1762,7 @@ TEST_F(RenderFrameHostManagerTest, DeleteFrameAfterSwapOutACK) {
contents()->NavigateAndCommit(kUrl1);
TestRenderFrameHost* rfh1 = contents()->GetMainFrame();
RenderFrameDeletedObserver rfh_deleted_observer(rfh1);
- EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state());
+ EXPECT_TRUE(rfh1->is_active());
// Navigate to new site, simulating onbeforeunload approval.
controller().LoadURL(
@@ -1959,14 +1770,14 @@ TEST_F(RenderFrameHostManagerTest, DeleteFrameAfterSwapOutACK) {
int entry_id = controller().GetPendingEntry()->GetUniqueID();
contents()->GetMainFrame()->PrepareForCommit();
EXPECT_TRUE(contents()->CrossProcessNavigationPending());
- EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state());
+ EXPECT_TRUE(rfh1->is_active());
TestRenderFrameHost* rfh2 = contents()->GetPendingMainFrame();
// Simulate the swap out ack, unexpectedly early (before commit). It should
// have no effect.
rfh1->OnSwappedOut();
EXPECT_TRUE(contents()->CrossProcessNavigationPending());
- EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state());
+ EXPECT_TRUE(rfh1->is_active());
// The new page commits.
contents()->TestDidNavigate(rfh2, 1, entry_id, true, kUrl2,
@@ -1974,10 +1785,8 @@ TEST_F(RenderFrameHostManagerTest, DeleteFrameAfterSwapOutACK) {
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(rfh2, contents()->GetMainFrame());
EXPECT_TRUE(contents()->GetPendingMainFrame() == NULL);
- EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh2->rfh_state());
- EXPECT_EQ(RenderFrameHostImpl::STATE_PENDING_SWAP_OUT, rfh1->rfh_state());
- EXPECT_TRUE(
- rfh1->frame_tree_node()->render_manager()->IsPendingDeletion(rfh1));
+ EXPECT_TRUE(rfh2->is_active());
+ EXPECT_FALSE(rfh1->is_active());
// Simulate the swap out ack.
rfh1->OnSwappedOut();
@@ -1997,7 +1806,7 @@ TEST_F(RenderFrameHostManagerTest, SwapOutFrameAfterSwapOutACK) {
contents()->NavigateAndCommit(kUrl1);
TestRenderFrameHost* rfh1 = contents()->GetMainFrame();
RenderFrameDeletedObserver rfh_deleted_observer(rfh1);
- EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state());
+ EXPECT_TRUE(rfh1->is_active());
// Increment the number of active frames in SiteInstanceImpl so that rfh1 is
// not deleted on swap out.
@@ -2009,7 +1818,7 @@ TEST_F(RenderFrameHostManagerTest, SwapOutFrameAfterSwapOutACK) {
int entry_id = controller().GetPendingEntry()->GetUniqueID();
contents()->GetMainFrame()->PrepareForCommit();
EXPECT_TRUE(contents()->CrossProcessNavigationPending());
- EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state());
+ EXPECT_TRUE(rfh1->is_active());
TestRenderFrameHost* rfh2 = contents()->GetPendingMainFrame();
// The new page commits.
@@ -2018,19 +1827,14 @@ TEST_F(RenderFrameHostManagerTest, SwapOutFrameAfterSwapOutACK) {
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(rfh2, contents()->GetMainFrame());
EXPECT_TRUE(contents()->GetPendingMainFrame() == NULL);
- EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh2->rfh_state());
- EXPECT_EQ(RenderFrameHostImpl::STATE_PENDING_SWAP_OUT, rfh1->rfh_state());
+ EXPECT_FALSE(rfh1->is_active());
+ EXPECT_TRUE(rfh2->is_active());
// Simulate the swap out ack.
rfh1->OnSwappedOut();
- // rfh1 should be swapped out or deleted in --site-per-process.
- if (!SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- EXPECT_FALSE(rfh_deleted_observer.deleted());
- EXPECT_TRUE(rfh1->is_swapped_out());
- } else {
- EXPECT_TRUE(rfh_deleted_observer.deleted());
- }
+ // rfh1 should be deleted.
+ EXPECT_TRUE(rfh_deleted_observer.deleted());
}
// Test that the RenderViewHost is properly swapped out if a navigation in the
@@ -2046,7 +1850,7 @@ TEST_F(RenderFrameHostManagerTest,
contents()->NavigateAndCommit(kUrl1);
TestRenderFrameHost* rfh1 = contents()->GetMainFrame();
RenderFrameDeletedObserver rfh_deleted_observer(rfh1);
- EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state());
+ EXPECT_TRUE(rfh1->is_active());
// Increment the number of active frames in SiteInstanceImpl so that rfh1 is
// not deleted on swap out.
@@ -2067,21 +1871,16 @@ TEST_F(RenderFrameHostManagerTest,
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
EXPECT_EQ(rfh2, contents()->GetMainFrame());
EXPECT_TRUE(contents()->GetPendingMainFrame() == NULL);
- EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh2->rfh_state());
- EXPECT_EQ(RenderFrameHostImpl::STATE_PENDING_SWAP_OUT, rfh1->rfh_state());
+ EXPECT_FALSE(rfh1->is_active());
+ EXPECT_TRUE(rfh2->is_active());
// Simulate the swap out ack.
rfh1->OnSwappedOut();
- // rfh1 should be swapped out.
- if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- EXPECT_TRUE(rfh_deleted_observer.deleted());
- EXPECT_TRUE(contents()->GetFrameTree()->root()->render_manager()
- ->GetRenderFrameProxyHost(site_instance.get()));
- } else {
- EXPECT_FALSE(rfh_deleted_observer.deleted());
- EXPECT_TRUE(rfh1->is_swapped_out());
- }
+ // rfh1 should be deleted.
+ EXPECT_TRUE(rfh_deleted_observer.deleted());
+ EXPECT_TRUE(contents()->GetFrameTree()->root()->render_manager()
+ ->GetRenderFrameProxyHost(site_instance.get()));
}
// Test that a RenderFrameHost is properly deleted when a cross-site navigation
@@ -2096,7 +1895,7 @@ TEST_F(RenderFrameHostManagerTest,
// Navigate to the first page.
contents()->NavigateAndCommit(kUrl1);
TestRenderFrameHost* rfh1 = main_test_rfh();
- EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh1->rfh_state());
+ EXPECT_TRUE(rfh1->is_active());
// Navigate to a new site, starting a cross-site navigation.
controller().LoadURL(
@@ -2133,13 +1932,9 @@ TEST_F(RenderFrameHostManagerTest,
FrameHostMsg_BeforeUnload_ACK(0, false, now, now));
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
- if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- EXPECT_TRUE(rfh_deleted_observer.deleted());
- EXPECT_TRUE(contents()->GetFrameTree()->root()->render_manager()
- ->GetRenderFrameProxyHost(site_instance.get()));
- } else {
- EXPECT_FALSE(rfh_deleted_observer.deleted());
- }
+ EXPECT_TRUE(rfh_deleted_observer.deleted());
+ EXPECT_TRUE(contents()->GetFrameTree()->root()->render_manager()
+ ->GetRenderFrameProxyHost(site_instance.get()));
}
}
@@ -2162,11 +1957,11 @@ TEST_F(RenderFrameHostManagerTestWithSiteIsolation, DetachPendingChild) {
contents()->NavigateAndCommit(kUrlA);
contents()->GetMainFrame()->OnCreateChildFrame(
contents()->GetMainFrame()->GetProcess()->GetNextRoutingID(),
- blink::WebTreeScopeType::Document, "frame_name",
+ blink::WebTreeScopeType::Document, "frame_name", "uniqueName1",
blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
contents()->GetMainFrame()->OnCreateChildFrame(
contents()->GetMainFrame()->GetProcess()->GetNextRoutingID(),
- blink::WebTreeScopeType::Document, "frame_name",
+ blink::WebTreeScopeType::Document, "frame_name", "uniqueName2",
blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
RenderFrameHostManager* root_manager =
contents()->GetFrameTree()->root()->render_manager();
@@ -2207,10 +2002,8 @@ TEST_F(RenderFrameHostManagerTestWithSiteIsolation, DetachPendingChild) {
EXPECT_TRUE(GetPendingFrameHost(iframe2));
EXPECT_EQ(host1, GetPendingFrameHost(iframe1));
EXPECT_EQ(host2, GetPendingFrameHost(iframe2));
- EXPECT_TRUE(RenderFrameHostImpl::IsRFHStateActive(
- GetPendingFrameHost(iframe1)->rfh_state()));
- EXPECT_TRUE(RenderFrameHostImpl::IsRFHStateActive(
- GetPendingFrameHost(iframe2)->rfh_state()));
+ EXPECT_TRUE(GetPendingFrameHost(iframe1)->is_active());
+ EXPECT_TRUE(GetPendingFrameHost(iframe2)->is_active());
EXPECT_NE(GetPendingFrameHost(iframe1), GetPendingFrameHost(iframe2));
EXPECT_EQ(GetPendingFrameHost(iframe1)->GetSiteInstance(),
GetPendingFrameHost(iframe2)->GetSiteInstance());
@@ -2303,7 +2096,7 @@ TEST_F(RenderFrameHostManagerTestWithSiteIsolation,
// |contents1| creates an out of process iframe.
contents1->GetMainFrame()->OnCreateChildFrame(
contents1->GetMainFrame()->GetProcess()->GetNextRoutingID(),
- blink::WebTreeScopeType::Document, "frame_name",
+ blink::WebTreeScopeType::Document, "frame_name", "uniqueName1",
blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
RenderFrameHostManager* iframe =
contents()->GetFrameTree()->root()->child_at(0)->render_manager();
@@ -2352,7 +2145,7 @@ TEST_F(RenderFrameHostManagerTestWithSiteIsolation,
EXPECT_TRUE(main_rfh->IsRenderFrameLive());
main_rfh->OnCreateChildFrame(main_rfh->GetProcess()->GetNextRoutingID(),
blink::WebTreeScopeType::Document, std::string(),
- blink::WebSandboxFlags::None,
+ "uniqueName1", blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
RenderFrameHostManager* subframe_rfhm =
contents()->GetFrameTree()->root()->child_at(0)->render_manager();
@@ -2512,10 +2305,10 @@ TEST_F(RenderFrameHostManagerTest, TraverseComplexOpenerChain) {
FrameTreeNode* root1 = tree1->root();
int process_id = root1->current_frame_host()->GetProcess()->GetID();
tree1->AddFrame(root1, process_id, 12, blink::WebTreeScopeType::Document,
- std::string(), blink::WebSandboxFlags::None,
+ std::string(), "uniqueName0", blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
tree1->AddFrame(root1, process_id, 13, blink::WebTreeScopeType::Document,
- std::string(), blink::WebSandboxFlags::None,
+ std::string(), "uniqueName1", blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
scoped_ptr<TestWebContents> tab2(
@@ -2525,10 +2318,10 @@ TEST_F(RenderFrameHostManagerTest, TraverseComplexOpenerChain) {
FrameTreeNode* root2 = tree2->root();
process_id = root2->current_frame_host()->GetProcess()->GetID();
tree2->AddFrame(root2, process_id, 22, blink::WebTreeScopeType::Document,
- std::string(), blink::WebSandboxFlags::None,
+ std::string(), "uniqueName2", blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
tree2->AddFrame(root2, process_id, 23, blink::WebTreeScopeType::Document,
- std::string(), blink::WebSandboxFlags::None,
+ std::string(), "uniqueName3", blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
scoped_ptr<TestWebContents> tab3(
@@ -2543,7 +2336,7 @@ TEST_F(RenderFrameHostManagerTest, TraverseComplexOpenerChain) {
FrameTreeNode* root4 = tree4->root();
process_id = root4->current_frame_host()->GetProcess()->GetID();
tree4->AddFrame(root4, process_id, 42, blink::WebTreeScopeType::Document,
- std::string(), blink::WebSandboxFlags::None,
+ std::string(), "uniqueName4", blink::WebSandboxFlags::None,
blink::WebFrameOwnerProperties());
root1->child_at(1)->SetOpener(root1->child_at(1));
@@ -2592,15 +2385,15 @@ TEST_F(RenderFrameHostManagerTest, PageFocusPropagatesToSubframeProcesses) {
contents()->NavigateAndCommit(kUrlA);
main_test_rfh()->OnCreateChildFrame(
main_test_rfh()->GetProcess()->GetNextRoutingID(),
- blink::WebTreeScopeType::Document, "frame1",
+ blink::WebTreeScopeType::Document, "frame1", "uniqueName1",
blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
main_test_rfh()->OnCreateChildFrame(
main_test_rfh()->GetProcess()->GetNextRoutingID(),
- blink::WebTreeScopeType::Document, "frame2",
+ blink::WebTreeScopeType::Document, "frame2", "uniqueName2",
blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
main_test_rfh()->OnCreateChildFrame(
main_test_rfh()->GetProcess()->GetNextRoutingID(),
- blink::WebTreeScopeType::Document, "frame3",
+ blink::WebTreeScopeType::Document, "frame3", "uniqueName3",
blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
FrameTreeNode* root = contents()->GetFrameTree()->root();
@@ -2690,7 +2483,7 @@ TEST_F(RenderFrameHostManagerTest,
contents()->NavigateAndCommit(kUrlA);
main_test_rfh()->OnCreateChildFrame(
main_test_rfh()->GetProcess()->GetNextRoutingID(),
- blink::WebTreeScopeType::Document, "frame1",
+ blink::WebTreeScopeType::Document, "frame1", "uniqueName1",
blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
FrameTreeNode* root = contents()->GetFrameTree()->root();
@@ -2736,8 +2529,8 @@ TEST_F(RenderFrameHostManagerTest, RestoreNavigationToWebUI) {
set_should_create_webui(true);
const GURL kInitUrl("chrome://foo/");
- SiteInstanceImpl* initial_instance =
- static_cast<SiteInstanceImpl*>(SiteInstance::Create(browser_context()));
+ scoped_refptr<SiteInstanceImpl> initial_instance =
+ SiteInstanceImpl::Create(browser_context());
initial_instance->SetSite(kInitUrl);
scoped_ptr<TestWebContents> web_contents(
TestWebContents::Create(browser_context(), initial_instance));
@@ -2809,6 +2602,7 @@ void RenderFrameHostManagerTest::BaseSimultaneousNavigationWithOneWebUI(
// Starts a reload of the WebUI page.
contents()->GetController().Reload(true);
+ main_test_rfh()->PrepareForCommit();
// It should be a same-site navigation reusing the same WebUI.
EXPECT_EQ(web_ui, manager->GetNavigatingWebUI());
@@ -2974,6 +2768,67 @@ TEST_F(RenderFrameHostManagerTest, SimultaneousNavigationWithTwoWebUIs2) {
BaseSimultaneousNavigationWithTwoWebUIs(commit_new_frame_host);
}
+TEST_F(RenderFrameHostManagerTest, CanCommitOrigin) {
+ const GURL kUrl("http://a.com/");
+ const GURL kUrlBar("http://a.com/bar");
+
+ NavigateActiveAndCommit(kUrl);
+
+ controller().LoadURL(
+ kUrlBar, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
+ main_test_rfh()->PrepareForCommit();
+
+ FrameHostMsg_DidCommitProvisionalLoad_Params params;
+ params.page_id = 0;
+ params.nav_entry_id = 0;
+ params.did_create_new_entry = false;
+ params.transition = ui::PAGE_TRANSITION_LINK;
+ params.should_update_history = false;
+ params.gesture = NavigationGestureAuto;
+ params.was_within_same_page = false;
+ params.is_post = false;
+ params.page_state = PageState::CreateFromURL(kUrlBar);
+
+ struct TestCase {
+ const char* const url;
+ const char* const origin;
+ bool mismatch;
+ } cases[] = {
+ // Positive case where the two match.
+ { "http://a.com/foo.html", "http://a.com", false },
+
+ // Host mismatches.
+ { "http://a.com/", "http://b.com", true },
+ { "http://b.com/", "http://a.com", true },
+
+ // Scheme mismatches.
+ { "file://", "http://a.com", true },
+ { "https://a.com/", "http://a.com", true },
+
+ // about:blank URLs inherit the origin of the context that navigated them.
+ { "about:blank", "http://a.com", false },
+
+ // Unique origin.
+ { "http://a.com", "null", false },
+ };
+
+ for (const auto& test_case : cases) {
+ params.url = GURL(test_case.url);
+ params.origin = url::Origin(GURL(test_case.origin));
+
+ int expected_bad_msg_count = process()->bad_msg_count();
+ if (test_case.mismatch)
+ expected_bad_msg_count++;
+
+ main_test_rfh()->SendNavigateWithParams(&params);
+
+ EXPECT_EQ(expected_bad_msg_count, process()->bad_msg_count())
+ << " url:" << test_case.url
+ << " origin:" << test_case.origin
+ << " mismatch:" << test_case.mismatch;
+ }
+}
+
// RenderFrameHostManagerTest extension for PlzNavigate enabled tests.
class RenderFrameHostManagerTestWithBrowserSideNavigation
: public RenderFrameHostManagerTest {
@@ -3006,9 +2861,10 @@ TEST_F(RenderFrameHostManagerTestWithBrowserSideNavigation,
NavigationRequest::CreateBrowserInitiated(
contents()->GetFrameTree()->root(), frame_entry->url(),
frame_entry->referrer(), *frame_entry, entry,
- FrameMsg_Navigate_Type::NORMAL, false, base::TimeTicks::Now(),
+ FrameMsg_Navigate_Type::NORMAL, LOFI_UNSPECIFIED, false,
+ base::TimeTicks::Now(),
static_cast<NavigationControllerImpl*>(&controller()));
- manager->DidCreateNavigationRequest(*navigation_request);
+ manager->DidCreateNavigationRequest(navigation_request.get());
// As the initial RenderFrame was not live, the new RenderFrameHost should be
// made as active/current immediately along with its WebUI at request time.
@@ -3066,9 +2922,10 @@ TEST_F(RenderFrameHostManagerTestWithBrowserSideNavigation,
NavigationRequest::CreateBrowserInitiated(
contents()->GetFrameTree()->root(), frame_entry->url(),
frame_entry->referrer(), *frame_entry, entry,
- FrameMsg_Navigate_Type::NORMAL, false, base::TimeTicks::Now(),
+ FrameMsg_Navigate_Type::NORMAL, LOFI_UNSPECIFIED, false,
+ base::TimeTicks::Now(),
static_cast<NavigationControllerImpl*>(&controller()));
- manager->DidCreateNavigationRequest(*navigation_request);
+ manager->DidCreateNavigationRequest(navigation_request.get());
// The current WebUI should still be in place and the pending WebUI should be
// set to reuse it.
@@ -3123,9 +2980,10 @@ TEST_F(RenderFrameHostManagerTestWithBrowserSideNavigation,
NavigationRequest::CreateBrowserInitiated(
contents()->GetFrameTree()->root(), frame_entry->url(),
frame_entry->referrer(), *frame_entry, entry,
- FrameMsg_Navigate_Type::NORMAL, false, base::TimeTicks::Now(),
+ FrameMsg_Navigate_Type::NORMAL, LOFI_UNSPECIFIED, false,
+ base::TimeTicks::Now(),
static_cast<NavigationControllerImpl*>(&controller()));
- manager->DidCreateNavigationRequest(*navigation_request);
+ manager->DidCreateNavigationRequest(navigation_request.get());
// The current WebUI should still be in place and there should be a new
// active WebUI instance in the speculative RenderFrameHost.
@@ -3173,8 +3031,8 @@ TEST_F(RenderFrameHostManagerTestWithSiteIsolation,
// Create a child frame and navigate it cross-site.
main_test_rfh()->OnCreateChildFrame(
main_test_rfh()->GetProcess()->GetNextRoutingID(),
- blink::WebTreeScopeType::Document, "frame1", blink::WebSandboxFlags::None,
- blink::WebFrameOwnerProperties());
+ blink::WebTreeScopeType::Document, "frame1", "uniqueName1",
+ blink::WebSandboxFlags::None, blink::WebFrameOwnerProperties());
FrameTreeNode* root = contents()->GetFrameTree()->root();
RenderFrameHostManager* child = root->child_at(0)->render_manager();
diff --git a/chromium/content/browser/frame_host/render_frame_message_filter.cc b/chromium/content/browser/frame_host/render_frame_message_filter.cc
index 21a811a85a9..98bd0fd5e37 100644
--- a/chromium/content/browser/frame_host/render_frame_message_filter.cc
+++ b/chromium/content/browser/frame_host/render_frame_message_filter.cc
@@ -21,6 +21,8 @@
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "gpu/GLES2/gl2extchromium.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "net/cookies/cookie_options.h"
#include "net/cookies/cookie_store.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
@@ -52,6 +54,7 @@ void CreateChildFrameOnUI(
int parent_routing_id,
blink::WebTreeScopeType scope,
const std::string& frame_name,
+ const std::string& frame_unique_name,
blink::WebSandboxFlags sandbox_flags,
const blink::WebFrameOwnerProperties& frame_owner_properties,
int new_routing_id) {
@@ -62,7 +65,7 @@ void CreateChildFrameOnUI(
// processing a subframe creation message.
if (render_frame_host) {
render_frame_host->OnCreateChildFrame(new_routing_id, scope, frame_name,
- sandbox_flags,
+ frame_unique_name, sandbox_flags,
frame_owner_properties);
}
}
@@ -139,80 +142,6 @@ class RenderFrameMessageFilter::OpenChannelToPpapiBrokerCallback
int routing_id_;
};
-class RenderFrameMessageFilter::OpenChannelToNpapiPluginCallback
- : public RenderMessageCompletionCallback,
- public PluginProcessHost::Client {
- public:
- OpenChannelToNpapiPluginCallback(RenderFrameMessageFilter* filter,
- ResourceContext* context,
- IPC::Message* reply_msg)
- : RenderMessageCompletionCallback(filter, reply_msg),
- context_(context),
- host_(nullptr),
- sent_plugin_channel_request_(false) {
- }
-
- int ID() override { return filter()->render_process_id_; }
-
- ResourceContext* GetResourceContext() override { return context_; }
-
- bool OffTheRecord() override {
- if (filter()->incognito_)
- return true;
- if (GetContentClient()->browser()->AllowSaveLocalState(context_))
- return false;
-
- // For now, only disallow storing data for Flash <http://crbug.com/97319>.
- for (const auto& type : info_.mime_types) {
- if (type.mime_type == kFlashPluginSwfMimeType)
- return true;
- }
- return false;
- }
-
- void SetPluginInfo(const WebPluginInfo& info) override { info_ = info; }
-
- void OnFoundPluginProcessHost(PluginProcessHost* host) override {
- DCHECK(host);
- host_ = host;
- }
-
- void OnSentPluginChannelRequest() override {
- sent_plugin_channel_request_ = true;
- }
-
- void OnChannelOpened(const IPC::ChannelHandle& handle) override {
- WriteReplyAndDeleteThis(handle);
- }
-
- void OnError() override { WriteReplyAndDeleteThis(IPC::ChannelHandle()); }
-
- PluginProcessHost* host() const {
- return host_;
- }
-
- bool sent_plugin_channel_request() const {
- return sent_plugin_channel_request_;
- }
-
- void Cancel() {
- delete this;
- }
-
- private:
- void WriteReplyAndDeleteThis(const IPC::ChannelHandle& handle) {
- FrameHostMsg_OpenChannelToPlugin::WriteReplyParams(reply_msg(),
- handle, info_);
- filter()->OnCompletedOpenChannelToNpapiPlugin(this);
- SendReplyAndDeleteThis();
- }
-
- ResourceContext* context_;
- WebPluginInfo info_;
- PluginProcessHost* host_;
- bool sent_plugin_channel_request_;
-};
-
class RenderFrameMessageFilter::OpenChannelToPpapiPluginCallback
: public RenderMessageCompletionCallback,
public PpapiPluginProcessHost::PluginClient {
@@ -269,27 +198,6 @@ RenderFrameMessageFilter::RenderFrameMessageFilter(
RenderFrameMessageFilter::~RenderFrameMessageFilter() {
// This function should be called on the IO thread.
DCHECK_CURRENTLY_ON(BrowserThread::IO);
-#if defined(ENABLE_PLUGINS)
- DCHECK(plugin_host_clients_.empty());
-#endif // ENABLE_PLUGINS
-}
-
-void RenderFrameMessageFilter::OnChannelClosing() {
-#if defined(ENABLE_PLUGINS)
- for (OpenChannelToNpapiPluginCallback* client : plugin_host_clients_) {
- if (client->host()) {
- if (client->sent_plugin_channel_request()) {
- client->host()->CancelSentRequest(client);
- } else {
- client->host()->CancelPendingRequest(client);
- }
- } else {
- plugin_service_->CancelOpenChannelToNpapiPlugin(client);
- }
- client->Cancel();
- }
- plugin_host_clients_.clear();
-#endif // ENABLE_PLUGINS
}
bool RenderFrameMessageFilter::OnMessageReceived(const IPC::Message& message) {
@@ -300,14 +208,11 @@ bool RenderFrameMessageFilter::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER_DELAY_REPLY(FrameHostMsg_GetCookies, OnGetCookies)
IPC_MESSAGE_HANDLER(FrameHostMsg_CookiesEnabled, OnCookiesEnabled)
IPC_MESSAGE_HANDLER(FrameHostMsg_Are3DAPIsBlocked, OnAre3DAPIsBlocked)
- IPC_MESSAGE_HANDLER(FrameHostMsg_DidLose3DContext, OnDidLose3DContext)
IPC_MESSAGE_HANDLER_GENERIC(FrameHostMsg_RenderProcessGone,
OnRenderProcessGone())
#if defined(ENABLE_PLUGINS)
IPC_MESSAGE_HANDLER_DELAY_REPLY(FrameHostMsg_GetPlugins, OnGetPlugins)
IPC_MESSAGE_HANDLER(FrameHostMsg_GetPluginInfo, OnGetPluginInfo)
- IPC_MESSAGE_HANDLER_DELAY_REPLY(FrameHostMsg_OpenChannelToPlugin,
- OnOpenChannelToPlugin)
IPC_MESSAGE_HANDLER_DELAY_REPLY(FrameHostMsg_OpenChannelToPepperPlugin,
OnOpenChannelToPepperPlugin)
IPC_MESSAGE_HANDLER(FrameHostMsg_DidCreateOutOfProcessPepperInstance,
@@ -326,18 +231,15 @@ bool RenderFrameMessageFilter::OnMessageReceived(const IPC::Message& message) {
}
void RenderFrameMessageFilter::OnCreateChildFrame(
- int parent_routing_id,
- blink::WebTreeScopeType scope,
- const std::string& frame_name,
- blink::WebSandboxFlags sandbox_flags,
- const blink::WebFrameOwnerProperties& frame_owner_properties,
+ const FrameHostMsg_CreateChildFrame_Params& params,
int* new_routing_id) {
*new_routing_id = render_widget_helper_->GetNextRoutingID();
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&CreateChildFrameOnUI, render_process_id_, parent_routing_id,
- scope, frame_name, sandbox_flags, frame_owner_properties,
- *new_routing_id));
+ base::Bind(&CreateChildFrameOnUI, render_process_id_,
+ params.parent_routing_id, params.scope, params.frame_name,
+ params.frame_unique_name, params.sandbox_flags,
+ params.frame_owner_properties, *new_routing_id));
}
void RenderFrameMessageFilter::OnSetCookie(int render_frame_id,
@@ -393,10 +295,24 @@ void RenderFrameMessageFilter::OnGetCookies(int render_frame_id,
base::debug::Alias(url_buf);
net::URLRequestContext* context = GetRequestContextForURL(url);
- context->cookie_store()->GetAllCookiesForURLAsync(
- url, base::Bind(&RenderFrameMessageFilter::CheckPolicyForCookies, this,
- render_frame_id, url, first_party_for_cookies,
- reply_msg));
+
+ net::CookieOptions options;
+ if (net::registry_controlled_domains::SameDomainOrHost(
+ url, first_party_for_cookies,
+ net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
+ // TODO(mkwst): This check ought to further distinguish between frames
+ // initiated in a strict or lax same-site context.
+ options.set_same_site_cookie_mode(
+ net::CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
+ } else {
+ options.set_same_site_cookie_mode(
+ net::CookieOptions::SameSiteCookieMode::DO_NOT_INCLUDE);
+ }
+
+ context->cookie_store()->GetCookieListWithOptionsAsync(
+ url, options,
+ base::Bind(&RenderFrameMessageFilter::CheckPolicyForCookies, this,
+ render_frame_id, url, first_party_for_cookies, reply_msg));
}
void RenderFrameMessageFilter::OnCookiesEnabled(
@@ -425,11 +341,8 @@ void RenderFrameMessageFilter::CheckPolicyForCookies(
GetContentClient()->browser()->AllowGetCookie(
url, first_party_for_cookies, cookie_list, resource_context_,
render_process_id_, render_frame_id)) {
- // Gets the cookies from cookie store if allowed.
- context->cookie_store()->GetCookiesWithOptionsAsync(
- url, net::CookieOptions(),
- base::Bind(&RenderFrameMessageFilter::SendGetCookiesResponse,
- this, reply_msg));
+ SendGetCookiesResponse(reply_msg,
+ net::CookieStore::BuildCookieLine(cookie_list));
} else {
SendGetCookiesResponse(reply_msg, std::string());
}
@@ -450,27 +363,6 @@ void RenderFrameMessageFilter::OnAre3DAPIsBlocked(int render_frame_id,
top_origin_url, render_process_id_, render_frame_id, requester);
}
-void RenderFrameMessageFilter::OnDidLose3DContext(
- const GURL& top_origin_url,
- ThreeDAPIType /* unused */,
- int arb_robustness_status_code) {
- GpuDataManagerImpl::DomainGuilt guilt;
- switch (arb_robustness_status_code) {
- case GL_GUILTY_CONTEXT_RESET_ARB:
- guilt = GpuDataManagerImpl::DOMAIN_GUILT_KNOWN;
- break;
- case GL_UNKNOWN_CONTEXT_RESET_ARB:
- guilt = GpuDataManagerImpl::DOMAIN_GUILT_UNKNOWN;
- break;
- default:
- // Ignore lost contexts known to be innocent.
- return;
- }
-
- GpuDataManagerImpl::GetInstance()->BlockDomainFrom3DAPIs(
- top_origin_url, guilt);
-}
-
void RenderFrameMessageFilter::OnRenderProcessGone() {
// FrameHostMessage_RenderProcessGone is a synthetic IPC message used by
// RenderProcessHostImpl to clean things up after a crash (it's injected
@@ -547,28 +439,6 @@ void RenderFrameMessageFilter::OnGetPluginInfo(
nullptr, info, actual_mime_type);
}
-void RenderFrameMessageFilter::OnOpenChannelToPlugin(
- int render_frame_id,
- const GURL& url,
- const GURL& policy_url,
- const std::string& mime_type,
- IPC::Message* reply_msg) {
- OpenChannelToNpapiPluginCallback* client =
- new OpenChannelToNpapiPluginCallback(this, resource_context_, reply_msg);
- DCHECK(!ContainsKey(plugin_host_clients_, client));
- plugin_host_clients_.insert(client);
- plugin_service_->OpenChannelToNpapiPlugin(
- render_process_id_, render_frame_id,
- url, policy_url, mime_type, client);
-}
-
-void RenderFrameMessageFilter::OnCompletedOpenChannelToNpapiPlugin(
- OpenChannelToNpapiPluginCallback* client) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(ContainsKey(plugin_host_clients_, client));
- plugin_host_clients_.erase(client);
-}
-
void RenderFrameMessageFilter::OnOpenChannelToPepperPlugin(
const base::FilePath& path,
IPC::Message* reply_msg) {
diff --git a/chromium/content/browser/frame_host/render_frame_message_filter.h b/chromium/content/browser/frame_host/render_frame_message_filter.h
index 194e2079b44..16190cf3d67 100644
--- a/chromium/content/browser/frame_host/render_frame_message_filter.h
+++ b/chromium/content/browser/frame_host/render_frame_message_filter.h
@@ -20,6 +20,7 @@
#include "content/common/pepper_renderer_instance_data.h"
#endif
+struct FrameHostMsg_CreateChildFrame_Params;
class GURL;
namespace net {
@@ -48,26 +49,17 @@ class RenderFrameMessageFilter : public BrowserMessageFilter {
net::URLRequestContextGetter* request_context,
RenderWidgetHelper* render_widget_helper);
- // IPC::MessageFilter methods:
- void OnChannelClosing() override;
-
// BrowserMessageFilter methods:
bool OnMessageReceived(const IPC::Message& message) override;
private:
- class OpenChannelToNpapiPluginCallback;
class OpenChannelToPpapiPluginCallback;
class OpenChannelToPpapiBrokerCallback;
~RenderFrameMessageFilter() override;
- void OnCreateChildFrame(
- int parent_routing_id,
- blink::WebTreeScopeType scope,
- const std::string& frame_name,
- blink::WebSandboxFlags sandbox_flags,
- const blink::WebFrameOwnerProperties& frame_owner_properties,
- int* new_render_frame_id);
+ void OnCreateChildFrame(const FrameHostMsg_CreateChildFrame_Params& params,
+ int* new_render_frame_id);
void OnSetCookie(int render_frame_id,
const GURL& url,
const GURL& first_party_for_cookies,
@@ -97,9 +89,6 @@ class RenderFrameMessageFilter : public BrowserMessageFilter {
const GURL& top_origin_url,
ThreeDAPIType requester,
bool* blocked);
- void OnDidLose3DContext(const GURL& top_origin_url,
- ThreeDAPIType context_type,
- int arb_robustness_status_code);
void OnRenderProcessGone();
@@ -114,13 +103,6 @@ class RenderFrameMessageFilter : public BrowserMessageFilter {
bool* found,
WebPluginInfo* info,
std::string* actual_mime_type);
- void OnOpenChannelToPlugin(int render_frame_id,
- const GURL& url,
- const GURL& policy_url,
- const std::string& mime_type,
- IPC::Message* reply_msg);
- void OnCompletedOpenChannelToNpapiPlugin(
- OpenChannelToNpapiPluginCallback* client);
void OnOpenChannelToPepperPlugin(const base::FilePath& path,
IPC::Message* reply_msg);
void OnDidCreateOutOfProcessPepperInstance(
@@ -149,8 +131,6 @@ class RenderFrameMessageFilter : public BrowserMessageFilter {
// Initialized to 0, accessed on FILE thread only.
base::TimeTicks last_plugin_refresh_time_;
-
- std::set<OpenChannelToNpapiPluginCallback*> plugin_host_clients_;
#endif // ENABLE_PLUGINS
// Contextual information to be used for requests created here.
diff --git a/chromium/content/browser/frame_host/render_frame_message_filter_browsertest.cc b/chromium/content/browser/frame_host/render_frame_message_filter_browsertest.cc
index 3362e96081c..1cd3cf0b240 100644
--- a/chromium/content/browser/frame_host/render_frame_message_filter_browsertest.cc
+++ b/chromium/content/browser/frame_host/render_frame_message_filter_browsertest.cc
@@ -24,6 +24,7 @@
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
namespace content {
@@ -38,7 +39,14 @@ std::string GetCookieFromJS(RenderFrameHost* frame) {
} // namespace
-using RenderFrameMessageFilterBrowserTest = ContentBrowserTest;
+class RenderFrameMessageFilterBrowserTest : public ContentBrowserTest {
+ protected:
+ void SetUp() override {
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures);
+ ContentBrowserTest::SetUp();
+ }
+};
// Exercises basic cookie operations via javascript, including an http page
// interacting with secure cookies.
@@ -48,7 +56,8 @@ IN_PROC_BROWSER_TEST_F(RenderFrameMessageFilterBrowserTest, Cookies) {
SetupCrossSiteRedirector(embedded_test_server());
net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
- https_server.ServeFilesFromSourceDirectory("content/test/data");
+ https_server.AddDefaultHandlers(
+ base::FilePath(FILE_PATH_LITERAL("content/test/data")));
ASSERT_TRUE(https_server.Start());
// The server sends a HttpOnly cookie. The RenderFrameMessageFilter should
@@ -78,30 +87,74 @@ IN_PROC_BROWSER_TEST_F(RenderFrameMessageFilterBrowserTest, Cookies) {
// Non-TLS page writes secure cookie.
EXPECT_TRUE(ExecuteScript(web_contents_http->GetMainFrame(),
"document.cookie = 'A=1; secure;';"));
- EXPECT_EQ("A=1", GetCookieFromJS(web_contents_https->GetMainFrame()));
+ EXPECT_EQ("", GetCookieFromJS(web_contents_https->GetMainFrame()));
EXPECT_EQ("", GetCookieFromJS(web_contents_http->GetMainFrame()));
// TLS page writes not-secure cookie.
EXPECT_TRUE(ExecuteScript(web_contents_http->GetMainFrame(),
"document.cookie = 'B=2';"));
- EXPECT_EQ("A=1; B=2", GetCookieFromJS(web_contents_https->GetMainFrame()));
+ EXPECT_EQ("B=2", GetCookieFromJS(web_contents_https->GetMainFrame()));
EXPECT_EQ("B=2", GetCookieFromJS(web_contents_http->GetMainFrame()));
- // Non-TLS page writes secure cookie.
+ // TLS page writes secure cookie.
EXPECT_TRUE(ExecuteScript(web_contents_https->GetMainFrame(),
"document.cookie = 'C=3;secure;';"));
- EXPECT_EQ("A=1; B=2; C=3",
+ EXPECT_EQ("B=2; C=3",
GetCookieFromJS(web_contents_https->GetMainFrame()));
EXPECT_EQ("B=2", GetCookieFromJS(web_contents_http->GetMainFrame()));
// TLS page writes not-secure cookie.
EXPECT_TRUE(ExecuteScript(web_contents_https->GetMainFrame(),
"document.cookie = 'D=4';"));
- EXPECT_EQ("A=1; B=2; C=3; D=4",
+ EXPECT_EQ("B=2; C=3; D=4",
GetCookieFromJS(web_contents_https->GetMainFrame()));
EXPECT_EQ("B=2; D=4", GetCookieFromJS(web_contents_http->GetMainFrame()));
}
+// SameSite cookies (that aren't marked as http-only) should be available to
+// JavaScript.
+IN_PROC_BROWSER_TEST_F(RenderFrameMessageFilterBrowserTest, SameSiteCookies) {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(embedded_test_server()->Start());
+ SetupCrossSiteRedirector(embedded_test_server());
+
+ // The server sets five cookies on 'a.com' and on 'b.com', then loads a
+ // page that frames both 'a.com' and 'b.com' under 'a.com'.
+ std::string cookies_to_set =
+ "/set-cookie?normal=1"
+ "&strict=1;SameSite=Strict"
+ "&lax=1;SameSite=Lax"
+ "&strict-http=1;SameSite=Strict;httponly"
+ "&lax-http=1;SameSite=Lax;httponly";
+
+ GURL url = embedded_test_server()->GetURL("a.com", cookies_to_set);
+ NavigateToURL(shell(), url);
+ url = embedded_test_server()->GetURL("b.com", cookies_to_set);
+ NavigateToURL(shell(), url);
+ url = embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(a(),b())");
+ NavigateToURL(shell(), url);
+
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ RenderFrameHost* main_frame = web_contents->GetMainFrame();
+ RenderFrameHost* a_iframe =
+ web_contents->GetFrameTree()->root()->child_at(0)->current_frame_host();
+ RenderFrameHost* b_iframe =
+ web_contents->GetFrameTree()->root()->child_at(1)->current_frame_host();
+
+ // The top-level frame should get both kinds of same-site cookies.
+ EXPECT_EQ("normal=1; strict=1; lax=1", GetCookieFromJS(main_frame));
+
+ // Same-site cookies will be delievered to the 'a.com' frame, as it is same-
+ // site with its ancestors.
+ EXPECT_EQ("normal=1; strict=1; lax=1", GetCookieFromJS(a_iframe));
+
+ // Same-site cookies should not be delievered to the 'b.com' frame, as it
+ // isn't same-site with its ancestors.
+ EXPECT_EQ("normal=1", GetCookieFromJS(b_iframe));
+}
+
// The RenderFrameMessageFilter will kill processes when they access the cookies
// of sites other than the site the process is dedicated to, under site
// isolation.
diff --git a/chromium/content/browser/frame_host/render_frame_proxy_host.cc b/chromium/content/browser/frame_host/render_frame_proxy_host.cc
index 49bcfc9093a..f4ba295b7ad 100644
--- a/chromium/content/browser/frame_host/render_frame_proxy_host.cc
+++ b/chromium/content/browser/frame_host/render_frame_proxy_host.cc
@@ -11,6 +11,7 @@
#include "content/browser/frame_host/cross_process_frame_connector.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/frame_host/navigator.h"
#include "content/browser/frame_host/render_frame_host_delegate.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
@@ -121,18 +122,6 @@ RenderWidgetHostView* RenderFrameProxyHost::GetRenderWidgetHostView() {
->GetRenderWidgetHostView();
}
-void RenderFrameProxyHost::TakeFrameHostOwnership(
- scoped_ptr<RenderFrameHostImpl> render_frame_host) {
- CHECK(render_frame_host_ == nullptr);
- render_frame_host_ = std::move(render_frame_host);
- render_frame_host_->set_render_frame_proxy_host(this);
-}
-
-scoped_ptr<RenderFrameHostImpl> RenderFrameProxyHost::PassFrameHostOwnership() {
- render_frame_host_->set_render_frame_proxy_host(NULL);
- return std::move(render_frame_host_);
-}
-
bool RenderFrameProxyHost::Send(IPC::Message *msg) {
return GetProcess()->Send(msg);
}
@@ -247,9 +236,25 @@ void RenderFrameProxyHost::OnDetach() {
void RenderFrameProxyHost::OnOpenURL(
const FrameHostMsg_OpenURL_Params& params) {
- // TODO(creis): Verify that we are in the same BrowsingInstance as the current
- // RenderFrameHost. See NavigatorImpl::RequestOpenURL.
- frame_tree_node_->current_frame_host()->OpenURL(params, site_instance_.get());
+ GURL validated_url(params.url);
+ GetProcess()->FilterURL(false, &validated_url);
+
+ // Verify that we are in the same BrowsingInstance as the current
+ // RenderFrameHost.
+ RenderFrameHostImpl* current_rfh = frame_tree_node_->current_frame_host();
+ if (!site_instance_->IsRelatedSiteInstance(current_rfh->GetSiteInstance()))
+ return;
+
+ // Since this navigation targeted a specific RenderFrameProxy, it should stay
+ // in the current tab.
+ DCHECK_EQ(CURRENT_TAB, params.disposition);
+
+ // TODO(alexmos, creis): Figure out whether |params.user_gesture| needs to be
+ // passed in as well.
+ frame_tree_node_->navigator()->RequestTransferURL(
+ current_rfh, validated_url, site_instance_.get(), std::vector<GURL>(),
+ params.referrer, ui::PAGE_TRANSITION_LINK, GlobalRequestID(),
+ params.should_replace_current_entry);
}
void RenderFrameProxyHost::OnRouteMessageEvent(
diff --git a/chromium/content/browser/frame_host/render_frame_proxy_host.h b/chromium/content/browser/frame_host/render_frame_proxy_host.h
index 390de28e6b8..6aa2848c3c7 100644
--- a/chromium/content/browser/frame_host/render_frame_proxy_host.h
+++ b/chromium/content/browser/frame_host/render_frame_proxy_host.h
@@ -96,10 +96,6 @@ class RenderFrameProxyHost
RenderViewHostImpl* GetRenderViewHost();
RenderWidgetHostView* GetRenderWidgetHostView();
- void TakeFrameHostOwnership(
- scoped_ptr<RenderFrameHostImpl> render_frame_host);
- scoped_ptr<RenderFrameHostImpl> PassFrameHostOwnership();
-
// IPC::Sender
bool Send(IPC::Message* msg) override;
diff --git a/chromium/content/browser/frame_host/render_widget_host_view_child_frame.cc b/chromium/content/browser/frame_host/render_widget_host_view_child_frame.cc
index e8d384e7233..6c022fba3f6 100644
--- a/chromium/content/browser/frame_host/render_widget_host_view_child_frame.cc
+++ b/chromium/content/browser/frame_host/render_widget_host_view_child_frame.cc
@@ -9,6 +9,8 @@
#include <vector>
#include "build/build_config.h"
+#include "cc/output/copy_output_request.h"
+#include "cc/output/copy_output_result.h"
#include "cc/surfaces/surface.h"
#include "cc/surfaces/surface_factory.h"
#include "cc/surfaces/surface_manager.h"
@@ -22,10 +24,10 @@
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
-#include "content/common/gpu/gpu_messages.h"
#include "content/common/view_messages.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/browser_plugin_guest_mode.h"
+#include "gpu/ipc/common/gpu_messages.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/geometry/size_f.h"
@@ -34,20 +36,14 @@ namespace content {
RenderWidgetHostViewChildFrame::RenderWidgetHostViewChildFrame(
RenderWidgetHost* widget_host)
: host_(RenderWidgetHostImpl::From(widget_host)),
- use_surfaces_(UseSurfacesEnabled()),
next_surface_sequence_(1u),
last_output_surface_id_(0),
current_surface_scale_factor_(1.f),
ack_pending_count_(0),
frame_connector_(nullptr),
weak_factory_(this) {
- if (use_surfaces_) {
- id_allocator_ = CreateSurfaceIdAllocator();
- if (host_->delegate() && host_->delegate()->GetInputEventRouter()) {
- host_->delegate()->GetInputEventRouter()->AddSurfaceIdNamespaceOwner(
- GetSurfaceIdNamespace(), this);
- }
- }
+ id_allocator_ = CreateSurfaceIdAllocator();
+ RegisterSurfaceNamespaceId();
host_->SetView(this);
}
@@ -72,6 +68,11 @@ void RenderWidgetHostViewChildFrame::SetSize(const gfx::Size& size) {
void RenderWidgetHostViewChildFrame::SetBounds(const gfx::Rect& rect) {
SetSize(rect.size());
+
+ if (rect != last_screen_rect_) {
+ last_screen_rect_ = rect;
+ host_->SendScreenRects();
+ }
}
void RenderWidgetHostViewChildFrame::Focus() {
@@ -84,8 +85,7 @@ bool RenderWidgetHostViewChildFrame::HasFocus() const {
}
bool RenderWidgetHostViewChildFrame::IsSurfaceAvailableForCopy() const {
- NOTIMPLEMENTED();
- return false;
+ return surface_factory_ && !surface_id_.is_null();
}
void RenderWidgetHostViewChildFrame::Show() {
@@ -106,11 +106,42 @@ bool RenderWidgetHostViewChildFrame::IsShowing() {
gfx::Rect RenderWidgetHostViewChildFrame::GetViewBounds() const {
gfx::Rect rect;
- if (frame_connector_)
+ if (frame_connector_) {
rect = frame_connector_->ChildFrameRect();
+
+ RenderWidgetHostView* parent_view =
+ frame_connector_->GetParentRenderWidgetHostView();
+
+ // The parent_view can be null in tests when using a TestWebContents.
+ if (parent_view) {
+ // Translate frame_rect by the parent's RenderWidgetHostView offset.
+ rect.Offset(parent_view->GetViewBounds().OffsetFromOrigin());
+ }
+ }
return rect;
}
+gfx::Size RenderWidgetHostViewChildFrame::GetVisibleViewportSize() const {
+ // For subframes, the visual viewport corresponds to the main frame size, so
+ // this bubbles up to the parent until it hits the main frame's
+ // RenderWidgetHostView.
+ //
+ // Currently this excludes webview guests, since they expect the visual
+ // viewport to return the guest's size rather than the page's; one reason why
+ // is that Blink ends up using the visual viewport to calculate things like
+ // window.innerWidth/innerHeight for main frames, and a guest is considered
+ // to be a main frame. This should be cleaned up eventually.
+ bool is_guest = BrowserPluginGuest::IsGuest(RenderViewHostImpl::From(host_));
+ if (frame_connector_ && !is_guest) {
+ RenderWidgetHostView* parent_view =
+ frame_connector_->GetParentRenderWidgetHostView();
+ // The parent_view can be null in unit tests when using a TestWebContents.
+ if (parent_view)
+ return parent_view->GetVisibleViewportSize();
+ }
+ return GetViewBounds().size();
+}
+
gfx::Vector2dF RenderWidgetHostViewChildFrame::GetLastScrollOffset() const {
return last_scroll_offset_;
}
@@ -167,10 +198,6 @@ void RenderWidgetHostViewChildFrame::ImeCompositionRangeChanged(
// TODO(kenrb): Fix OOPIF Ime.
}
-void RenderWidgetHostViewChildFrame::MovePluginWindows(
- const std::vector<WebPluginGeometry>& moves) {
-}
-
void RenderWidgetHostViewChildFrame::UpdateCursor(const WebCursor& cursor) {
if (frame_connector_)
frame_connector_->UpdateCursor(cursor);
@@ -205,16 +232,18 @@ void RenderWidgetHostViewChildFrame::RenderProcessGone(
}
void RenderWidgetHostViewChildFrame::Destroy() {
+ // SurfaceIdNamespaces registered with RenderWidgetHostInputEventRouter
+ // have already been cleared when RenderWidgetHostViewBase notified its
+ // observers of our impending destruction.
if (frame_connector_) {
frame_connector_->set_view(NULL);
frame_connector_ = NULL;
}
- if (use_surfaces_ && host_->delegate() &&
- host_->delegate()->GetInputEventRouter()) {
- host_->delegate()->GetInputEventRouter()->RemoveSurfaceIdNamespaceOwner(
- GetSurfaceIdNamespace());
- }
+ // We notify our observers about shutdown here since we are about to release
+ // host_ and do not want any event calls coming from
+ // RenderWidgetHostInputEventRouter afterwards.
+ NotifyObserversAboutShutdown();
host_->SetView(NULL);
host_ = NULL;
@@ -243,6 +272,24 @@ void RenderWidgetHostViewChildFrame::UnlockCompositingSurface() {
NOTIMPLEMENTED();
}
+void RenderWidgetHostViewChildFrame::RegisterSurfaceNamespaceId() {
+ DCHECK(host_);
+ if (host_->delegate() && host_->delegate()->GetInputEventRouter()) {
+ RenderWidgetHostInputEventRouter* router =
+ host_->delegate()->GetInputEventRouter();
+ if (!router->is_registered(GetSurfaceIdNamespace()))
+ router->AddSurfaceIdNamespaceOwner(GetSurfaceIdNamespace(), this);
+ }
+}
+
+void RenderWidgetHostViewChildFrame::UnregisterSurfaceNamespaceId() {
+ DCHECK(host_);
+ if (host_->delegate() && host_->delegate()->GetInputEventRouter()) {
+ host_->delegate()->GetInputEventRouter()->RemoveSurfaceIdNamespaceOwner(
+ GetSurfaceIdNamespace());
+ }
+}
+
void RenderWidgetHostViewChildFrame::SurfaceDrawn(uint32_t output_surface_id,
cc::SurfaceDrawStatus drawn) {
cc::CompositorFrameAck ack;
@@ -259,20 +306,14 @@ void RenderWidgetHostViewChildFrame::SurfaceDrawn(uint32_t output_surface_id,
void RenderWidgetHostViewChildFrame::OnSwapCompositorFrame(
uint32_t output_surface_id,
scoped_ptr<cc::CompositorFrame> frame) {
+ TRACE_EVENT0("content",
+ "RenderWidgetHostViewChildFrame::OnSwapCompositorFrame");
+
last_scroll_offset_ = frame->metadata.root_scroll_offset;
if (!frame_connector_)
return;
- // When not using surfaces, the frame just gets proxied to
- // the embedder's renderer to be composited.
- if (!frame->delegated_frame_data || !use_surfaces_) {
- frame_connector_->ChildFrameCompositorFrameSwapped(
- output_surface_id, host_->GetProcess()->GetID(), host_->GetRoutingID(),
- std::move(frame));
- return;
- }
-
cc::RenderPass* root_pass =
frame->delegated_frame_data->render_pass_list.back().get();
@@ -321,6 +362,17 @@ void RenderWidgetHostViewChildFrame::OnSwapCompositorFrame(
DCHECK_LT(ack_pending_count_, 1000U);
surface_factory_->SubmitCompositorFrame(surface_id_, std::move(frame),
ack_callback);
+
+ ProcessFrameSwappedCallbacks();
+}
+
+void RenderWidgetHostViewChildFrame::ProcessFrameSwappedCallbacks() {
+ // We only use callbacks once, therefore we make a new list for registration
+ // before we start, and discard the old list entries when we are done.
+ FrameSwappedCallbackList process_callbacks;
+ process_callbacks.swap(frame_swapped_callbacks_);
+ for (scoped_ptr<base::Closure>& callback : process_callbacks)
+ callback->Run();
}
void RenderWidgetHostViewChildFrame::GetScreenInfo(
@@ -340,16 +392,26 @@ bool RenderWidgetHostViewChildFrame::GetScreenColorProfile(
}
gfx::Rect RenderWidgetHostViewChildFrame::GetBoundsInRootWindow() {
- // We do not have any root window specific parts in this view.
- return GetViewBounds();
+ gfx::Rect rect;
+ if (frame_connector_) {
+ RenderWidgetHostViewBase* root_view =
+ frame_connector_->GetRootRenderWidgetHostView();
+
+ // The root_view can be null in tests when using a TestWebContents.
+ if (root_view)
+ rect = root_view->GetBoundsInRootWindow();
+ }
+ return rect;
}
-#if defined(USE_AURA)
void RenderWidgetHostViewChildFrame::ProcessAckedTouchEvent(
const TouchEventWithLatencyInfo& touch,
InputEventAckState ack_result) {
+ if (!frame_connector_)
+ return;
+
+ frame_connector_->ForwardProcessAckedTouchEvent(touch, ack_result);
}
-#endif // defined(USE_AURA)
bool RenderWidgetHostViewChildFrame::LockMouse() {
return false;
@@ -359,9 +421,6 @@ void RenderWidgetHostViewChildFrame::UnlockMouse() {
}
uint32_t RenderWidgetHostViewChildFrame::GetSurfaceIdNamespace() {
- if (!use_surfaces_)
- return 0;
-
return id_allocator_->id_namespace();
}
@@ -381,25 +440,33 @@ void RenderWidgetHostViewChildFrame::ProcessMouseWheelEvent(
host_->ForwardWheelEvent(event);
}
-void RenderWidgetHostViewChildFrame::TransformPointToRootCoordSpace(
- const gfx::Point& point,
- gfx::Point* transformed_point) {
- *transformed_point = point;
- if (!frame_connector_ || !use_surfaces_)
- return;
+void RenderWidgetHostViewChildFrame::ProcessTouchEvent(
+ const blink::WebTouchEvent& event,
+ const ui::LatencyInfo& latency) {
+ if (event.type == blink::WebInputEvent::TouchStart &&
+ frame_connector_ && !frame_connector_->HasFocus()) {
+ frame_connector_->FocusRootView();
+ }
- frame_connector_->TransformPointToRootCoordSpace(point, surface_id_,
- transformed_point);
+ host_->ForwardTouchEventWithLatencyInfo(event, latency);
}
-#if defined(OS_MACOSX)
-void RenderWidgetHostViewChildFrame::SetActive(bool active) {
+void RenderWidgetHostViewChildFrame::ProcessGestureEvent(
+ const blink::WebGestureEvent& event,
+ const ui::LatencyInfo& latency) {
+ host_->ForwardGestureEventWithLatencyInfo(event, latency);
}
-void RenderWidgetHostViewChildFrame::SetWindowVisibility(bool visible) {
+gfx::Point RenderWidgetHostViewChildFrame::TransformPointToRootCoordSpace(
+ const gfx::Point& point) {
+ if (!frame_connector_)
+ return point;
+
+ return frame_connector_->TransformPointToRootCoordSpace(point, surface_id_);
}
-void RenderWidgetHostViewChildFrame::WindowFrameChanged() {
+#if defined(OS_MACOSX)
+void RenderWidgetHostViewChildFrame::SetActive(bool active) {
}
void RenderWidgetHostViewChildFrame::ShowDefinitionForSelection() {
@@ -418,19 +485,46 @@ bool RenderWidgetHostViewChildFrame::IsSpeaking() const {
void RenderWidgetHostViewChildFrame::StopSpeaking() {
}
+#endif // defined(OS_MACOSX)
-bool RenderWidgetHostViewChildFrame::PostProcessEventForPluginIme(
- const NativeWebKeyboardEvent& event) {
- return false;
+void RenderWidgetHostViewChildFrame::RegisterFrameSwappedCallback(
+ scoped_ptr<base::Closure> callback) {
+ frame_swapped_callbacks_.push_back(std::move(callback));
}
-#endif // defined(OS_MACOSX)
void RenderWidgetHostViewChildFrame::CopyFromCompositingSurface(
- const gfx::Rect& /* src_subrect */,
- const gfx::Size& /* dst_size */,
+ const gfx::Rect& src_subrect,
+ const gfx::Size& output_size,
const ReadbackRequestCallback& callback,
- const SkColorType /* preferred_color_type */) {
- callback.Run(SkBitmap(), READBACK_FAILED);
+ const SkColorType preferred_color_type) {
+ if (!IsSurfaceAvailableForCopy()) {
+ // Defer submitting the copy request until after a frame is drawn, at which
+ // point we should be guaranteed that the surface is available.
+ RegisterFrameSwappedCallback(make_scoped_ptr(new base::Closure(base::Bind(
+ &RenderWidgetHostViewChildFrame::SubmitSurfaceCopyRequest, AsWeakPtr(),
+ src_subrect, output_size, callback, preferred_color_type))));
+ return;
+ }
+
+ SubmitSurfaceCopyRequest(src_subrect, output_size, callback,
+ preferred_color_type);
+}
+
+void RenderWidgetHostViewChildFrame::SubmitSurfaceCopyRequest(
+ const gfx::Rect& src_subrect,
+ const gfx::Size& output_size,
+ const ReadbackRequestCallback& callback,
+ const SkColorType preferred_color_type) {
+ DCHECK(IsSurfaceAvailableForCopy());
+
+ scoped_ptr<cc::CopyOutputRequest> request =
+ cc::CopyOutputRequest::CreateRequest(
+ base::Bind(&CopyFromCompositingSurfaceHasResult, output_size,
+ preferred_color_type, callback));
+ if (!src_subrect.IsEmpty())
+ request->set_area(src_subrect);
+
+ surface_factory_->RequestCopyOfSurface(surface_id_, std::move(request));
}
void RenderWidgetHostViewChildFrame::CopyFromCompositingSurfaceToVideoFrame(
@@ -450,17 +544,6 @@ bool RenderWidgetHostViewChildFrame::HasAcceleratedSurface(
return false;
}
-#if defined(OS_WIN)
-void RenderWidgetHostViewChildFrame::SetParentNativeViewAccessible(
- gfx::NativeViewAccessible accessible_parent) {
-}
-
-gfx::NativeViewId RenderWidgetHostViewChildFrame::GetParentForWindowlessPlugin()
- const {
- return NULL;
-}
-#endif // defined(OS_WIN)
-
// cc::SurfaceFactoryClient implementation.
void RenderWidgetHostViewChildFrame::ReturnResources(
const cc::ReturnedResourceArray& resources) {
@@ -481,20 +564,15 @@ void RenderWidgetHostViewChildFrame::ReturnResources(
}
void RenderWidgetHostViewChildFrame::SetBeginFrameSource(
- cc::SurfaceId surface_id,
cc::BeginFrameSource* begin_frame_source) {
// TODO(tansell): Hook this up.
}
BrowserAccessibilityManager*
RenderWidgetHostViewChildFrame::CreateBrowserAccessibilityManager(
- BrowserAccessibilityDelegate* delegate) {
-#if defined(OS_ANDROID) && defined(USE_AURA)
- return nullptr;
-#else
+ BrowserAccessibilityDelegate* delegate, bool for_root_frame) {
return BrowserAccessibilityManager::Create(
BrowserAccessibilityManager::GetEmptyDocument(), delegate);
-#endif
}
void RenderWidgetHostViewChildFrame::ClearCompositorSurfaceIfNecessary() {
@@ -503,4 +581,12 @@ void RenderWidgetHostViewChildFrame::ClearCompositorSurfaceIfNecessary() {
surface_id_ = cc::SurfaceId();
}
+bool RenderWidgetHostViewChildFrame::IsChildFrameForTesting() const {
+ return true;
+}
+
+cc::SurfaceId RenderWidgetHostViewChildFrame::SurfaceIdForTesting() const {
+ return surface_id_;
+};
+
} // namespace content
diff --git a/chromium/content/browser/frame_host/render_widget_host_view_child_frame.h b/chromium/content/browser/frame_host/render_widget_host_view_child_frame.h
index 4bacd21f3d8..825ca060805 100644
--- a/chromium/content/browser/frame_host/render_widget_host_view_child_frame.h
+++ b/chromium/content/browser/frame_host/render_widget_host_view_child_frame.h
@@ -8,8 +8,10 @@
#include <stddef.h>
#include <stdint.h>
+#include <deque>
#include <vector>
+#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "build/build_config.h"
@@ -17,8 +19,10 @@
#include "cc/surfaces/surface_factory_client.h"
#include "cc/surfaces/surface_id_allocator.h"
#include "content/browser/compositor/image_transport_factory.h"
+#include "content/browser/renderer_host/event_with_latency_info.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/common/content_export.h"
+#include "content/common/input/input_event_ack_state.h"
#include "content/public/browser/readback_types.h"
#include "ui/compositor/compositor.h"
#include "ui/gfx/geometry/rect.h"
@@ -58,6 +62,15 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
frame_connector_ = frame_connector;
}
+ // This functions registers single-use callbacks that want to be notified when
+ // the next frame is swapped. The callback is triggered by
+ // OnSwapCompositorFrame, which is the appropriate time to request pixel
+ // readback for the frame that is about to be drawn. Once called, the callback
+ // pointer is released.
+ // TODO(wjmaclean): We should consider making this available in other view
+ // types, such as RenderWidgetHostViewAura.
+ void RegisterFrameSwappedCallback(scoped_ptr<base::Closure> callback);
+
// RenderWidgetHostView implementation.
void InitAsChild(gfx::NativeView parent_view) override;
RenderWidgetHost* GetRenderWidgetHost() const override;
@@ -70,6 +83,7 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
void Hide() override;
bool IsShowing() override;
gfx::Rect GetViewBounds() const override;
+ gfx::Size GetVisibleViewportSize() const override;
gfx::Vector2dF GetLastScrollOffset() const override;
gfx::NativeView GetNativeView() const override;
gfx::NativeViewId GetNativeViewId() const override;
@@ -81,7 +95,6 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
void InitAsPopup(RenderWidgetHostView* parent_host_view,
const gfx::Rect& bounds) override;
void InitAsFullscreen(RenderWidgetHostView* reference_host_view) override;
- void MovePluginWindows(const std::vector<WebPluginGeometry>& moves) override;
void UpdateCursor(const WebCursor& cursor) override;
void SetIsLoading(bool is_loading) override;
void TextInputStateChanged(
@@ -118,56 +131,55 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
void GetScreenInfo(blink::WebScreenInfo* results) override;
bool GetScreenColorProfile(std::vector<char>* color_profile) override;
gfx::Rect GetBoundsInRootWindow() override;
-#if defined(USE_AURA)
void ProcessAckedTouchEvent(const TouchEventWithLatencyInfo& touch,
InputEventAckState ack_result) override;
-#endif // defined(USE_AURA)
bool LockMouse() override;
void UnlockMouse() override;
uint32_t GetSurfaceIdNamespace() override;
void ProcessKeyboardEvent(const NativeWebKeyboardEvent& event) override;
void ProcessMouseEvent(const blink::WebMouseEvent& event) override;
void ProcessMouseWheelEvent(const blink::WebMouseWheelEvent& event) override;
- void TransformPointToRootCoordSpace(const gfx::Point& point,
- gfx::Point* transformed_point) override;
+ void ProcessTouchEvent(const blink::WebTouchEvent& event,
+ const ui::LatencyInfo& latency) override;
+ void ProcessGestureEvent(const blink::WebGestureEvent& event,
+ const ui::LatencyInfo& latency) override;
+ gfx::Point TransformPointToRootCoordSpace(const gfx::Point& point) override;
#if defined(OS_MACOSX)
// RenderWidgetHostView implementation.
void SetActive(bool active) override;
- void SetWindowVisibility(bool visible) override;
- void WindowFrameChanged() override;
void ShowDefinitionForSelection() override;
bool SupportsSpeech() const override;
void SpeakSelection() override;
bool IsSpeaking() const override;
void StopSpeaking() override;
-
- // RenderWidgetHostViewBase implementation.
- bool PostProcessEventForPluginIme(
- const NativeWebKeyboardEvent& event) override;
#endif // defined(OS_MACOSX)
// RenderWidgetHostViewBase implementation.
void LockCompositingSurface() override;
void UnlockCompositingSurface() override;
-#if defined(OS_WIN)
- void SetParentNativeViewAccessible(
- gfx::NativeViewAccessible accessible_parent) override;
- gfx::NativeViewId GetParentForWindowlessPlugin() const override;
-#endif
BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
- BrowserAccessibilityDelegate* delegate) override;
+ BrowserAccessibilityDelegate* delegate, bool for_root_frame) override;
// cc::SurfaceFactoryClient implementation.
void ReturnResources(const cc::ReturnedResourceArray& resources) override;
- void SetBeginFrameSource(cc::SurfaceId surface_id,
- cc::BeginFrameSource* begin_frame_source) override;
+ void SetBeginFrameSource(cc::BeginFrameSource* begin_frame_source) override;
// Declared 'public' instead of 'protected' here to allow derived classes
// to Bind() to it.
void SurfaceDrawn(uint32_t output_surface_id, cc::SurfaceDrawStatus drawn);
+ // Exposed for tests.
+ bool IsChildFrameForTesting() const override;
+ cc::SurfaceId SurfaceIdForTesting() const override;
+ CrossProcessFrameConnector* FrameConnectorForTesting() const {
+ return frame_connector_;
+ }
+
+ void RegisterSurfaceNamespaceId();
+ void UnregisterSurfaceNamespaceId();
+
protected:
friend class RenderWidgetHostView;
friend class RenderWidgetHostViewChildFrameTest;
@@ -176,6 +188,8 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
// Clears current compositor surface, if one is in use.
void ClearCompositorSurfaceIfNecessary();
+ void ProcessFrameSwappedCallbacks();
+
// The last scroll offset of the view.
gfx::Vector2dF last_scroll_offset_;
@@ -183,9 +197,6 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
// The model object.
RenderWidgetHostImpl* host_;
- // Flag determining whether we render into a compositing Surface.
- bool use_surfaces_;
-
// Surface-related state.
scoped_ptr<cc::SurfaceIdAllocator> id_allocator_;
scoped_ptr<cc::SurfaceFactory> surface_factory_;
@@ -194,6 +205,7 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
uint32_t last_output_surface_id_;
gfx::Size current_surface_size_;
float current_surface_scale_factor_;
+ gfx::Rect last_screen_rect_;
uint32_t ack_pending_count_;
cc::ReturnedResourceArray surface_returned_resources_;
@@ -206,6 +218,16 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
}
private:
+ void SubmitSurfaceCopyRequest(const gfx::Rect& src_subrect,
+ const gfx::Size& dst_size,
+ const ReadbackRequestCallback& callback,
+ const SkColorType preferred_color_type);
+
+ using FrameSwappedCallbackList = std::deque<scoped_ptr<base::Closure>>;
+ // Since frame-drawn callbacks are "fire once", we use std::deque to make
+ // it convenient to swap() when processing the list.
+ FrameSwappedCallbackList frame_swapped_callbacks_;
+
base::WeakPtrFactory<RenderWidgetHostViewChildFrame> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewChildFrame);
};
diff --git a/chromium/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc b/chromium/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc
index fbf418b38c0..4584e084c71 100644
--- a/chromium/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc
+++ b/chromium/content/browser/frame_host/render_widget_host_view_child_frame_unittest.cc
@@ -42,23 +42,9 @@ class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
class MockCrossProcessFrameConnector : public CrossProcessFrameConnector {
public:
MockCrossProcessFrameConnector()
- : CrossProcessFrameConnector(nullptr),
- last_scale_factor_received_(0.f),
- received_delegated_frame_(false) {}
+ : CrossProcessFrameConnector(nullptr), last_scale_factor_received_(0.f) {}
~MockCrossProcessFrameConnector() override {}
- void ChildFrameCompositorFrameSwapped(
- uint32_t output_surface_id,
- int host_id,
- int route_id,
- scoped_ptr<cc::CompositorFrame> frame) override {
- received_delegated_frame_ = true;
- last_frame_size_received_ =
- frame->delegated_frame_data->render_pass_list.back()
- ->output_rect.size();
- last_scale_factor_received_ = frame->metadata.device_scale_factor;
- }
-
void SetChildFrameSurface(const cc::SurfaceId& surface_id,
const gfx::Size& frame_size,
float scale_factor,
@@ -71,8 +57,6 @@ class MockCrossProcessFrameConnector : public CrossProcessFrameConnector {
cc::SurfaceId last_surface_id_received_;
gfx::Size last_frame_size_received_;
float last_scale_factor_received_;
-
- bool received_delegated_frame_;
};
} // namespace
@@ -168,27 +152,20 @@ TEST_F(RenderWidgetHostViewChildFrameTest, SwapCompositorFrame) {
view_->OnSwapCompositorFrame(
0, CreateDelegatedFrame(scale_factor, view_size, view_rect));
- if (UseSurfacesEnabled()) {
- cc::SurfaceId id = surface_id();
- if (!id.is_null()) {
+ cc::SurfaceId id = surface_id();
+ if (!id.is_null()) {
#if !defined(OS_ANDROID)
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- cc::SurfaceManager* manager = factory->GetSurfaceManager();
- cc::Surface* surface = manager->GetSurfaceForId(id);
- EXPECT_TRUE(surface);
- // There should be a SurfaceSequence created by the RWHVChildFrame.
- EXPECT_EQ(1u, surface->GetDestructionDependencyCount());
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ cc::SurfaceManager* manager = factory->GetSurfaceManager();
+ cc::Surface* surface = manager->GetSurfaceForId(id);
+ EXPECT_TRUE(surface);
+ // There should be a SurfaceSequence created by the RWHVChildFrame.
+ EXPECT_EQ(1u, surface->GetDestructionDependencyCount());
#endif
- // Surface ID should have been passed to CrossProcessFrameConnector to
- // be sent to the embedding renderer.
- EXPECT_EQ(id, test_frame_connector_->last_surface_id_received_);
- EXPECT_EQ(view_size, test_frame_connector_->last_frame_size_received_);
- EXPECT_EQ(scale_factor,
- test_frame_connector_->last_scale_factor_received_);
- }
- } else {
- EXPECT_TRUE(test_frame_connector_->received_delegated_frame_);
+ // Surface ID should have been passed to CrossProcessFrameConnector to
+ // be sent to the embedding renderer.
+ EXPECT_EQ(id, test_frame_connector_->last_surface_id_received_);
EXPECT_EQ(view_size, test_frame_connector_->last_frame_size_received_);
EXPECT_EQ(scale_factor, test_frame_connector_->last_scale_factor_received_);
}
diff --git a/chromium/content/browser/frame_host/render_widget_host_view_guest.cc b/chromium/content/browser/frame_host/render_widget_host_view_guest.cc
index 9240afb45a9..e90f44bd0b1 100644
--- a/chromium/content/browser/frame_host/render_widget_host_view_guest.cc
+++ b/chromium/content/browser/frame_host/render_widget_host_view_guest.cc
@@ -22,11 +22,11 @@
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
#include "content/common/browser_plugin/browser_plugin_messages.h"
#include "content/common/frame_messages.h"
-#include "content/common/gpu/gpu_messages.h"
#include "content/common/input/web_touch_event_traits.h"
+#include "content/common/site_isolation_policy.h"
#include "content/common/view_messages.h"
-#include "content/common/webplugin_geometry.h"
#include "content/public/common/content_switches.h"
+#include "gpu/ipc/common/gpu_messages.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/platform/WebScreenInfo.h"
@@ -40,20 +40,6 @@
namespace content {
-namespace {
-
-#if defined(USE_AURA)
-blink::WebGestureEvent CreateFlingCancelEvent(double time_stamp) {
- blink::WebGestureEvent gesture_event;
- gesture_event.timeStampSeconds = time_stamp;
- gesture_event.type = blink::WebGestureEvent::GestureFlingCancel;
- gesture_event.sourceDevice = blink::WebGestureDeviceTouchscreen;
- return gesture_event;
-}
-#endif // defined(USE_AURA)
-
-} // namespace
-
RenderWidgetHostViewGuest::RenderWidgetHostViewGuest(
RenderWidgetHost* widget_host,
BrowserPluginGuest* guest,
@@ -62,10 +48,11 @@ RenderWidgetHostViewGuest::RenderWidgetHostViewGuest(
// |guest| is NULL during test.
guest_(guest ? guest->AsWeakPtr() : base::WeakPtr<BrowserPluginGuest>()),
platform_view_(platform_view) {
+ // Inputs for guest view are already scaled.
+ host_->set_scale_input_to_viewport(false);
}
-RenderWidgetHostViewGuest::~RenderWidgetHostViewGuest() {
-}
+RenderWidgetHostViewGuest::~RenderWidgetHostViewGuest() {}
bool RenderWidgetHostViewGuest::OnMessageReceivedFromEmbedder(
const IPC::Message& message,
@@ -166,24 +153,6 @@ void RenderWidgetHostViewGuest::ProcessTouchEvent(
host_->ForwardTouchEventWithLatencyInfo(event, latency);
}
-void RenderWidgetHostViewGuest::RegisterSurfaceNamespaceId() {
- DCHECK(host_);
- if (host_->delegate() && host_->delegate()->GetInputEventRouter()) {
- RenderWidgetHostInputEventRouter* router =
- host_->delegate()->GetInputEventRouter();
- if (!router->is_registered(GetSurfaceIdNamespace()))
- router->AddSurfaceIdNamespaceOwner(GetSurfaceIdNamespace(), this);
- }
-}
-
-void RenderWidgetHostViewGuest::UnregisterSurfaceNamespaceId() {
- DCHECK(host_);
- if (host_->delegate() && host_->delegate()->GetInputEventRouter()) {
- host_->delegate()->GetInputEventRouter()->RemoveSurfaceIdNamespaceOwner(
- GetSurfaceIdNamespace());
- }
-}
-
gfx::Rect RenderWidgetHostViewGuest::GetViewBounds() const {
if (!guest_)
return gfx::Rect();
@@ -196,6 +165,10 @@ gfx::Rect RenderWidgetHostViewGuest::GetViewBounds() const {
guest_->GetScreenCoordinates(embedder_bounds.origin()), size_);
}
+gfx::Rect RenderWidgetHostViewGuest::GetBoundsInRootWindow() {
+ return GetViewBounds();
+}
+
void RenderWidgetHostViewGuest::RenderProcessGone(
base::TerminationStatus status,
int error_code) {
@@ -234,14 +207,9 @@ void RenderWidgetHostViewGuest::SetTooltipText(
void RenderWidgetHostViewGuest::OnSwapCompositorFrame(
uint32_t output_surface_id,
scoped_ptr<cc::CompositorFrame> frame) {
+ TRACE_EVENT0("content", "RenderWidgetHostViewGuest::OnSwapCompositorFrame");
+
last_scroll_offset_ = frame->metadata.root_scroll_offset;
- // When not using surfaces, the frame just gets proxied to
- // the embedder's renderer to be composited.
- if (!frame->delegated_frame_data || !use_surfaces_) {
- guest_->SwapCompositorFrame(output_surface_id, host_->GetProcess()->GetID(),
- host_->GetRoutingID(), std::move(frame));
- return;
- }
cc::RenderPass* root_pass =
frame->delegated_frame_data->render_pass_list.back().get();
@@ -292,6 +260,9 @@ void RenderWidgetHostViewGuest::OnSwapCompositorFrame(
DCHECK(ack_pending_count_ < 1000);
surface_factory_->SubmitCompositorFrame(surface_id_, std::move(frame),
ack_callback);
+
+ ProcessFrameSwappedCallbacks();
+
// If after detaching we are sent a frame, we should finish processing it, and
// then we should clear the surface so that we are not holding resources we
// no longer need.
@@ -356,11 +327,6 @@ gfx::NativeViewAccessible RenderWidgetHostViewGuest::GetNativeViewAccessible() {
return rwhv->GetNativeViewAccessible();
}
-void RenderWidgetHostViewGuest::MovePluginWindows(
- const std::vector<WebPluginGeometry>& moves) {
- platform_view_->MovePluginWindows(moves);
-}
-
void RenderWidgetHostViewGuest::UpdateCursor(const WebCursor& cursor) {
// InterstitialPages are not WebContents so we cannot intercept
// ViewHostMsg_SetCursor for interstitial pages in BrowserPluginGuest.
@@ -368,10 +334,14 @@ void RenderWidgetHostViewGuest::UpdateCursor(const WebCursor& cursor) {
// and so we will always hit this code path.
if (!guest_)
return;
- guest_->SendMessageToEmbedder(
- new BrowserPluginMsg_SetCursor(guest_->browser_plugin_instance_id(),
- cursor));
-
+ if (SiteIsolationPolicy::AreCrossProcessFramesPossible()) {
+ RenderWidgetHostViewBase* rwhvb = GetOwnerRenderWidgetHostView();
+ if (rwhvb)
+ rwhvb->UpdateCursor(cursor);
+ } else {
+ guest_->SendMessageToEmbedder(new BrowserPluginMsg_SetCursor(
+ guest_->browser_plugin_instance_id(), cursor));
+ }
}
void RenderWidgetHostViewGuest::SetIsLoading(bool is_loading) {
@@ -476,14 +446,6 @@ void RenderWidgetHostViewGuest::SetActive(bool active) {
platform_view_->SetActive(active);
}
-void RenderWidgetHostViewGuest::SetWindowVisibility(bool visible) {
- platform_view_->SetWindowVisibility(visible);
-}
-
-void RenderWidgetHostViewGuest::WindowFrameChanged() {
- platform_view_->WindowFrameChanged();
-}
-
void RenderWidgetHostViewGuest::ShowDefinitionForSelection() {
if (!guest_)
return;
@@ -522,12 +484,6 @@ bool RenderWidgetHostViewGuest::IsSpeaking() const {
void RenderWidgetHostViewGuest::StopSpeaking() {
platform_view_->StopSpeaking();
}
-
-bool RenderWidgetHostViewGuest::PostProcessEventForPluginIme(
- const NativeWebKeyboardEvent& event) {
- return false;
-}
-
#endif // defined(OS_MACOSX)
#if defined(OS_ANDROID) || defined(USE_AURA)
@@ -545,69 +501,16 @@ void RenderWidgetHostViewGuest::UnlockCompositingSurface() {
NOTIMPLEMENTED();
}
-#if defined(OS_WIN)
-void RenderWidgetHostViewGuest::SetParentNativeViewAccessible(
- gfx::NativeViewAccessible accessible_parent) {
-}
-
-gfx::NativeViewId RenderWidgetHostViewGuest::GetParentForWindowlessPlugin()
- const {
- return NULL;
-}
-#endif
-
void RenderWidgetHostViewGuest::DestroyGuestView() {
+ // Let our observers know we're going away, since we don't want any event
+ // processing calls coming in after we release host_.
+ NotifyObserversAboutShutdown();
+
host_->SetView(NULL);
host_ = NULL;
base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
}
-bool RenderWidgetHostViewGuest::ForwardGestureEventToRenderer(
- ui::GestureEvent* gesture) {
-#if defined(USE_AURA)
- if (!host_)
- return false;
-
- if ((gesture->type() == ui::ET_GESTURE_PINCH_BEGIN ||
- gesture->type() == ui::ET_GESTURE_PINCH_UPDATE ||
- gesture->type() == ui::ET_GESTURE_PINCH_END) && !pinch_zoom_enabled_) {
- return true;
- }
-
- blink::WebGestureEvent web_gesture =
- MakeWebGestureEventFromUIEvent(*gesture);
- const gfx::Point& client_point = gesture->location();
- const gfx::Point& screen_point = gesture->location();
-
- web_gesture.x = client_point.x();
- web_gesture.y = client_point.y();
- web_gesture.globalX = screen_point.x();
- web_gesture.globalY = screen_point.y();
-
- if (web_gesture.type == blink::WebGestureEvent::Undefined)
- return false;
- if (web_gesture.type == blink::WebGestureEvent::GestureTapDown) {
- host_->ForwardGestureEvent(
- CreateFlingCancelEvent(gesture->time_stamp().InSecondsF()));
- }
- host_->ForwardGestureEvent(web_gesture);
- return true;
-#else
- return false;
-#endif
-}
-
-void RenderWidgetHostViewGuest::ProcessGestures(
- ui::GestureRecognizer::Gestures* gestures) {
- if ((gestures == NULL) || gestures->empty())
- return;
- for (ui::GestureRecognizer::Gestures::iterator g_it = gestures->begin();
- g_it != gestures->end();
- ++g_it) {
- ForwardGestureEventToRenderer(*g_it);
- }
-}
-
RenderWidgetHostViewBase*
RenderWidgetHostViewGuest::GetOwnerRenderWidgetHostView() const {
return static_cast<RenderWidgetHostViewBase*>(
@@ -637,7 +540,6 @@ void RenderWidgetHostViewGuest::GestureEventAck(
void RenderWidgetHostViewGuest::OnHandleInputEvent(
RenderWidgetHostImpl* embedder,
int browser_plugin_instance_id,
- const gfx::Rect& guest_window_rect,
const blink::WebInputEvent* event) {
if (blink::WebInputEvent::isMouseEventType(event->type)) {
// The mouse events for BrowserPlugin are modified by all
diff --git a/chromium/content/browser/frame_host/render_widget_host_view_guest.h b/chromium/content/browser/frame_host/render_widget_host_view_guest.h
index f9d4b1663ce..4e800c8dd94 100644
--- a/chromium/content/browser/frame_host/render_widget_host_view_guest.h
+++ b/chromium/content/browser/frame_host/render_widget_host_view_guest.h
@@ -68,6 +68,7 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
gfx::NativeViewId GetNativeViewId() const override;
gfx::NativeViewAccessible GetNativeViewAccessible() override;
gfx::Rect GetViewBounds() const override;
+ gfx::Rect GetBoundsInRootWindow() override;
gfx::Size GetPhysicalBackingSize() const override;
base::string16 GetSelectedText() const override;
@@ -75,7 +76,6 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
void InitAsPopup(RenderWidgetHostView* parent_host_view,
const gfx::Rect& bounds) override;
void InitAsFullscreen(RenderWidgetHostView* reference_host_view) override;
- void MovePluginWindows(const std::vector<WebPluginGeometry>& moves) override;
void UpdateCursor(const WebCursor& cursor) override;
void SetIsLoading(bool is_loading) override;
void TextInputStateChanged(
@@ -103,8 +103,6 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
#endif
void ProcessTouchEvent(const blink::WebTouchEvent& event,
const ui::LatencyInfo& latency) override;
- void RegisterSurfaceNamespaceId();
- void UnregisterSurfaceNamespaceId();
bool LockMouse() override;
void UnlockMouse() override;
@@ -114,17 +112,11 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
#if defined(OS_MACOSX)
// RenderWidgetHostView implementation.
void SetActive(bool active) override;
- void SetWindowVisibility(bool visible) override;
- void WindowFrameChanged() override;
void ShowDefinitionForSelection() override;
bool SupportsSpeech() const override;
void SpeakSelection() override;
bool IsSpeaking() const override;
void StopSpeaking() override;
-
- // RenderWidgetHostViewBase implementation.
- bool PostProcessEventForPluginIme(
- const NativeWebKeyboardEvent& event) override;
#endif // defined(OS_MACOSX)
#if defined(OS_ANDROID) || defined(USE_AURA)
@@ -136,12 +128,6 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
void LockCompositingSurface() override;
void UnlockCompositingSurface() override;
-#if defined(OS_WIN)
- void SetParentNativeViewAccessible(
- gfx::NativeViewAccessible accessible_parent) override;
- gfx::NativeViewId GetParentForWindowlessPlugin() const override;
-#endif
-
void WheelEventAck(const blink::WebMouseWheelEvent& event,
InputEventAckState ack_result) override;
@@ -155,17 +141,10 @@ class CONTENT_EXPORT RenderWidgetHostViewGuest
// Destroys this view without calling |Destroy| on |platform_view_|.
void DestroyGuestView();
- // Builds and forwards a WebKitGestureEvent to the renderer.
- bool ForwardGestureEventToRenderer(ui::GestureEvent* gesture);
-
- // Process all of the given gestures (passes them on to renderer)
- void ProcessGestures(ui::GestureRecognizer::Gestures* gestures);
-
RenderWidgetHostViewBase* GetOwnerRenderWidgetHostView() const;
void OnHandleInputEvent(RenderWidgetHostImpl* embedder,
int browser_plugin_instance_id,
- const gfx::Rect& guest_window_rect,
const blink::WebInputEvent* event);
// BrowserPluginGuest and RenderWidgetHostViewGuest's lifetimes are not tied
diff --git a/chromium/content/browser/frame_host/render_widget_host_view_guest_unittest.cc b/chromium/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
index 119eb38a840..3d772d46b47 100644
--- a/chromium/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
+++ b/chromium/content/browser/frame_host/render_widget_host_view_guest_unittest.cc
@@ -106,17 +106,15 @@ TEST_F(RenderWidgetHostViewGuestTest, VisibilityTest) {
class TestBrowserPluginGuest : public BrowserPluginGuest {
public:
TestBrowserPluginGuest(WebContentsImpl* web_contents,
- BrowserPluginGuestDelegate* delegate):
- BrowserPluginGuest(web_contents->HasOpener(), web_contents, delegate),
- last_scale_factor_received_(0.f),
- received_delegated_frame_(false) {}
+ BrowserPluginGuestDelegate* delegate)
+ : BrowserPluginGuest(web_contents->HasOpener(), web_contents, delegate),
+ last_scale_factor_received_(0.f) {}
~TestBrowserPluginGuest() override {}
void ResetTestData() {
last_surface_id_received_ = cc::SurfaceId();
last_frame_size_received_ = gfx::Size();
last_scale_factor_received_ = 0.f;
- received_delegated_frame_ = false;
}
void set_has_attached_since_surface_set(bool has_attached_since_surface_set) {
@@ -128,21 +126,6 @@ class TestBrowserPluginGuest : public BrowserPluginGuest {
BrowserPluginGuest::set_attached_for_test(attached);
}
- void SwapCompositorFrame(uint32_t output_surface_id,
- int host_process_id,
- int host_routing_id,
- scoped_ptr<cc::CompositorFrame> frame) override {
- received_delegated_frame_ = true;
- last_frame_size_received_ =
- frame->delegated_frame_data->render_pass_list.back()
- ->output_rect.size();
- last_scale_factor_received_ = frame->metadata.device_scale_factor;
-
- // Call base-class version so that we can test UpdateGuestSizeIfNecessary().
- BrowserPluginGuest::SwapCompositorFrame(output_surface_id, host_process_id,
- host_routing_id, std::move(frame));
- }
-
void SetChildFrameSurface(const cc::SurfaceId& surface_id,
const gfx::Size& frame_size,
float scale_factor,
@@ -156,8 +139,6 @@ class TestBrowserPluginGuest : public BrowserPluginGuest {
gfx::Size last_frame_size_received_;
float last_scale_factor_received_;
float update_scale_factor_received_;
-
- bool received_delegated_frame_;
};
// TODO(wjmaclean): we should restructure RenderWidgetHostViewChildFrameTest to
@@ -259,26 +240,19 @@ TEST_F(RenderWidgetHostViewGuestSurfaceTest, TestGuestSurface) {
view_->OnSwapCompositorFrame(
0, CreateDelegatedFrame(scale_factor, view_size, view_rect));
- if (UseSurfacesEnabled()) {
- cc::SurfaceId id = surface_id();
- if (!id.is_null()) {
+ cc::SurfaceId id = surface_id();
+ if (!id.is_null()) {
#if !defined(OS_ANDROID)
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- cc::SurfaceManager* manager = factory->GetSurfaceManager();
- cc::Surface* surface = manager->GetSurfaceForId(id);
- EXPECT_TRUE(surface);
- // There should be a SurfaceSequence created by the RWHVGuest.
- EXPECT_EQ(1u, surface->GetDestructionDependencyCount());
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ cc::SurfaceManager* manager = factory->GetSurfaceManager();
+ cc::Surface* surface = manager->GetSurfaceForId(id);
+ EXPECT_TRUE(surface);
+ // There should be a SurfaceSequence created by the RWHVGuest.
+ EXPECT_EQ(1u, surface->GetDestructionDependencyCount());
#endif
- // Surface ID should have been passed to BrowserPluginGuest to
- // be sent to the embedding renderer.
- EXPECT_EQ(id, browser_plugin_guest_->last_surface_id_received_);
- EXPECT_EQ(view_size, browser_plugin_guest_->last_frame_size_received_);
- EXPECT_EQ(scale_factor,
- browser_plugin_guest_->last_scale_factor_received_);
- }
- } else {
- EXPECT_TRUE(browser_plugin_guest_->received_delegated_frame_);
+ // Surface ID should have been passed to BrowserPluginGuest to
+ // be sent to the embedding renderer.
+ EXPECT_EQ(id, browser_plugin_guest_->last_surface_id_received_);
EXPECT_EQ(view_size, browser_plugin_guest_->last_frame_size_received_);
EXPECT_EQ(scale_factor, browser_plugin_guest_->last_scale_factor_received_);
}
@@ -289,28 +263,22 @@ TEST_F(RenderWidgetHostViewGuestSurfaceTest, TestGuestSurface) {
view_->OnSwapCompositorFrame(
0, CreateDelegatedFrame(scale_factor, view_size, view_rect));
- if (UseSurfacesEnabled()) {
- cc::SurfaceId id = surface_id();
- if (!id.is_null()) {
+ id = surface_id();
+ if (!id.is_null()) {
#if !defined(OS_ANDROID)
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- cc::SurfaceManager* manager = factory->GetSurfaceManager();
- cc::Surface* surface = manager->GetSurfaceForId(id);
- EXPECT_TRUE(surface);
- // There should be a SurfaceSequence created by the RWHVGuest.
- EXPECT_EQ(1u, surface->GetDestructionDependencyCount());
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ cc::SurfaceManager* manager = factory->GetSurfaceManager();
+ cc::Surface* surface = manager->GetSurfaceForId(id);
+ EXPECT_TRUE(surface);
+ // There should be a SurfaceSequence created by the RWHVGuest.
+ EXPECT_EQ(1u, surface->GetDestructionDependencyCount());
#endif
- // Surface ID should have been passed to BrowserPluginGuest to
- // be sent to the embedding renderer.
- EXPECT_EQ(id, browser_plugin_guest_->last_surface_id_received_);
- EXPECT_EQ(view_size, browser_plugin_guest_->last_frame_size_received_);
- EXPECT_EQ(scale_factor,
- browser_plugin_guest_->last_scale_factor_received_);
- }
- } else {
- EXPECT_TRUE(browser_plugin_guest_->received_delegated_frame_);
+ // Surface ID should have been passed to BrowserPluginGuest to
+ // be sent to the embedding renderer.
+ EXPECT_EQ(id, browser_plugin_guest_->last_surface_id_received_);
EXPECT_EQ(view_size, browser_plugin_guest_->last_frame_size_received_);
- EXPECT_EQ(scale_factor, browser_plugin_guest_->last_scale_factor_received_);
+ EXPECT_EQ(scale_factor,
+ browser_plugin_guest_->last_scale_factor_received_);
}
browser_plugin_guest_->set_attached(false);
@@ -318,8 +286,7 @@ TEST_F(RenderWidgetHostViewGuestSurfaceTest, TestGuestSurface) {
view_->OnSwapCompositorFrame(
0, CreateDelegatedFrame(scale_factor, view_size, view_rect));
- if (UseSurfacesEnabled())
- EXPECT_TRUE(surface_id().is_null());
+ EXPECT_TRUE(surface_id().is_null());
}
} // namespace content
diff --git a/chromium/content/browser/frame_host/traced_frame_tree_node.cc b/chromium/content/browser/frame_host/traced_frame_tree_node.cc
new file mode 100644
index 00000000000..0141b38e854
--- /dev/null
+++ b/chromium/content/browser/frame_host/traced_frame_tree_node.cc
@@ -0,0 +1,69 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/frame_host/traced_frame_tree_node.h"
+
+#include "base/command_line.h"
+#include "base/json/json_writer.h"
+#include "base/strings/stringprintf.h"
+#include "content/browser/frame_host/frame_tree.h"
+#include "content/public/common/content_switches.h"
+#include "url/gurl.h"
+
+namespace content {
+
+TracedFrameTreeNode::TracedFrameTreeNode(const FrameTreeNode& node)
+ : parent_node_id_(-1),
+ process_id_(-1),
+ routing_id_(-1) {
+ FrameTreeNode* parent = node.parent();
+ if (parent)
+ parent_node_id_ = parent->frame_tree_node_id();
+
+ RenderFrameHostImpl* current_frame_host = node.current_frame_host();
+
+ if (current_frame_host->last_committed_url().is_valid())
+ url_ = current_frame_host->last_committed_url().spec();
+
+ // On Windows, |rph->GetHandle()| does not duplicate ownership
+ // of the process handle and the render host still retains it. Therefore, we
+ // cannot create a base::Process object, which provides a proper way to get a
+ // process id, from the handle. For a stopgap, we use this deprecated
+ // function that does not require the ownership (http://crbug.com/417532).
+ process_id_ = base::GetProcId(current_frame_host->GetProcess()->GetHandle());
+
+ routing_id_ = current_frame_host->GetRoutingID();
+ DCHECK_NE(routing_id_, MSG_ROUTING_NONE);
+}
+
+TracedFrameTreeNode::~TracedFrameTreeNode() {
+}
+
+void TracedFrameTreeNode::AppendAsTraceFormat(std::string* out) const {
+ scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue());
+
+ if (parent_node_id_ >= 0) {
+ scoped_ptr<base::DictionaryValue> ref(new base::DictionaryValue());
+ ref->SetString("id_ref", base::StringPrintf("0x%x", parent_node_id_));
+ ref->SetString("scope", "FrameTreeNode");
+ value->Set("parent", std::move(ref));
+ }
+
+ if (process_id_ >= 0) {
+ scoped_ptr<base::DictionaryValue> ref(new base::DictionaryValue());
+ ref->SetInteger("pid_ref", process_id_);
+ ref->SetString("id_ref", base::StringPrintf("0x%x", routing_id_));
+ ref->SetString("scope", "RenderFrame");
+ value->Set("RenderFrame", std::move(ref));
+ }
+
+ if (!url_.empty())
+ value->SetString("url", url_);
+
+ std::string tmp;
+ base::JSONWriter::Write(*value, &tmp);
+ *out += tmp;
+}
+
+} // content
diff --git a/chromium/content/browser/frame_host/traced_frame_tree_node.h b/chromium/content/browser/frame_host/traced_frame_tree_node.h
new file mode 100644
index 00000000000..79c2a80e911
--- /dev/null
+++ b/chromium/content/browser/frame_host/traced_frame_tree_node.h
@@ -0,0 +1,36 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/macros.h"
+#include "base/memory/scoped_vector.h"
+#include "base/trace_event/trace_event_impl.h"
+#include "base/values.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class FrameTree;
+class FrameTreeNode;
+
+// This is a temporary container used when tracing snapshots of FrameTree
+// objects. When a snapshot of a FrameTree is taken, a TracedFrameTreeNode is
+// created and stored by the tracing system until the trace is dumped.
+class CONTENT_EXPORT TracedFrameTreeNode :
+ public base::trace_event::ConvertableToTraceFormat {
+ public:
+ TracedFrameTreeNode(const FrameTreeNode& node);
+ void AppendAsTraceFormat(std::string* out) const override;
+
+ private:
+ ~TracedFrameTreeNode() override;
+
+ int parent_node_id_;
+ std::string url_;
+ int process_id_;
+ int routing_id_;
+
+ DISALLOW_COPY_AND_ASSIGN(TracedFrameTreeNode);
+};
+
+} // content
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc
index f6fd2d4ef39..87ec3714b66 100644
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc
+++ b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.cc
@@ -19,8 +19,8 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/trace_event.h"
-#include "content/browser/udev_linux.h"
#include "device/udev_linux/scoped_udev.h"
+#include "device/udev_linux/udev_linux.h"
namespace {
@@ -77,12 +77,12 @@ GamepadPlatformDataFetcherLinux::GamepadPlatformDataFetcherLinux() {
pad_state_[i].button_mask = 0;
}
- std::vector<UdevLinux::UdevMonitorFilter> filters;
- filters.push_back(UdevLinux::UdevMonitorFilter(kInputSubsystem, NULL));
- udev_.reset(
- new UdevLinux(filters,
- base::Bind(&GamepadPlatformDataFetcherLinux::RefreshDevice,
- base::Unretained(this))));
+ std::vector<device::UdevLinux::UdevMonitorFilter> filters;
+ filters.push_back(
+ device::UdevLinux::UdevMonitorFilter(kInputSubsystem, NULL));
+ udev_.reset(new device::UdevLinux(
+ filters, base::Bind(&GamepadPlatformDataFetcherLinux::RefreshDevice,
+ base::Unretained(this))));
EnumerateDevices();
}
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h
index b98646a4e7f..763f1911dd6 100644
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h
+++ b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_linux.h
@@ -18,9 +18,11 @@ extern "C" {
struct udev_device;
}
-namespace content {
-
+namespace device {
class UdevLinux;
+}
+
+namespace content {
class GamepadPlatformDataFetcherLinux : public GamepadDataFetcher {
public:
@@ -39,7 +41,7 @@ class GamepadPlatformDataFetcherLinux : public GamepadDataFetcher {
// File descriptor for the /dev/input/js* devices. -1 if not in use.
int device_fd_[blink::WebGamepads::itemsLengthCap];
- scoped_ptr<UdevLinux> udev_;
+ scoped_ptr<device::UdevLinux> udev_;
DISALLOW_COPY_AND_ASSIGN(GamepadPlatformDataFetcherLinux);
};
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 3983694f110..c761e83858f 100644
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc
+++ b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.cc
@@ -53,10 +53,25 @@ const WebUChar* GamepadSubTypeName(BYTE sub_type) {
}
}
+const WebUChar* XInputDllFileName() {
+ // Xinput.h defines filename (XINPUT_DLL) on different Windows versions, but
+ // Xinput.h specifies it in build time. Approach here uses the same values
+ // and it is resolving dll filename based on Windows version it is running on.
+ if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
+ // For Windows 8 and 10, XINPUT_DLL is xinput1_4.dll.
+ return FILE_PATH_LITERAL("xinput1_4.dll");
+ } else if (base::win::GetVersion() >= base::win::VERSION_WIN7) {
+ return FILE_PATH_LITERAL("xinput9_1_0.dll");
+ } else {
+ NOTREACHED();
+ return nullptr;
+ }
+}
+
} // namespace
GamepadPlatformDataFetcherWin::GamepadPlatformDataFetcherWin()
- : xinput_dll_(base::FilePath(FILE_PATH_LITERAL("xinput1_3.dll"))),
+ : xinput_dll_(base::FilePath(XInputDllFileName())),
xinput_available_(GetXInputDllFunctions()) {
for (size_t i = 0; i < WebGamepads::itemsLengthCap; ++i) {
platform_pad_state_[i].status = DISCONNECTED;
@@ -317,10 +332,8 @@ void GamepadPlatformDataFetcherWin::GetRawInputPadData(
bool GamepadPlatformDataFetcherWin::GetXInputDllFunctions() {
xinput_get_capabilities_ = NULL;
xinput_get_state_ = NULL;
- xinput_enable_ = reinterpret_cast<XInputEnableFunc>(
+ XInputEnableFunc xinput_enable = reinterpret_cast<XInputEnableFunc>(
xinput_dll_.GetFunctionPointer("XInputEnable"));
- if (!xinput_enable_)
- return false;
xinput_get_capabilities_ = reinterpret_cast<XInputGetCapabilitiesFunc>(
xinput_dll_.GetFunctionPointer("XInputGetCapabilities"));
if (!xinput_get_capabilities_)
@@ -329,7 +342,10 @@ bool GamepadPlatformDataFetcherWin::GetXInputDllFunctions() {
xinput_dll_.GetFunctionPointer("XInputGetState"));
if (!xinput_get_state_)
return false;
- xinput_enable_(true);
+ if (xinput_enable) {
+ // XInputEnable is unavailable before Win8 and deprecated in Win10.
+ xinput_enable(true);
+ }
return true;
}
diff --git a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.h b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.h
index f1efab3440b..53356698bfb 100644
--- a/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.h
+++ b/chromium/content/browser/gamepad/gamepad_platform_data_fetcher_win.h
@@ -49,10 +49,8 @@ class GamepadPlatformDataFetcherWin : public GamepadDataFetcher {
typedef DWORD (WINAPI *XInputGetStateFunc)(
DWORD dwUserIndex, XINPUT_STATE* pState);
- // Get functions from dynamically loaded xinput1_3.dll. We don't use
- // DELAYLOAD because the import library for Win8 SDK pulls xinput1_4 which
- // isn't redistributable. Returns true if loading was successful. We include
- // xinput1_3.dll with Chrome.
+ // Get functions from dynamically loading the xinput dll.
+ // Returns true if loading was successful.
bool GetXInputDllFunctions();
// Scan for connected XInput and DirectInput gamepads.
@@ -71,7 +69,6 @@ class GamepadPlatformDataFetcherWin : public GamepadDataFetcher {
// Function pointers to XInput functionality, retrieved in
// |GetXinputDllFunctions|.
- XInputEnableFunc xinput_enable_;
XInputGetCapabilitiesFunc xinput_get_capabilities_;
XInputGetStateFunc xinput_get_state_;
diff --git a/chromium/content/browser/gamepad/gamepad_provider.cc b/chromium/content/browser/gamepad/gamepad_provider.cc
index 682afc51d35..fea94e012bd 100644
--- a/chromium/content/browser/gamepad/gamepad_provider.cc
+++ b/chromium/content/browser/gamepad/gamepad_provider.cc
@@ -39,6 +39,9 @@ GamepadProvider::ClosureAndThread::ClosureAndThread(
: closure(c), task_runner(m) {
}
+GamepadProvider::ClosureAndThread::ClosureAndThread(
+ const ClosureAndThread& other) = default;
+
GamepadProvider::ClosureAndThread::~ClosureAndThread() {
}
diff --git a/chromium/content/browser/gamepad/gamepad_provider.h b/chromium/content/browser/gamepad/gamepad_provider.h
index f2dcad245bb..fa154111847 100644
--- a/chromium/content/browser/gamepad/gamepad_provider.h
+++ b/chromium/content/browser/gamepad/gamepad_provider.h
@@ -106,6 +106,7 @@ class CONTENT_EXPORT GamepadProvider :
struct ClosureAndThread {
ClosureAndThread(const base::Closure& c,
const scoped_refptr<base::SingleThreadTaskRunner>& m);
+ ClosureAndThread(const ClosureAndThread& other);
~ClosureAndThread();
base::Closure closure;
diff --git a/chromium/content/browser/geofencing/geofencing_manager.cc b/chromium/content/browser/geofencing/geofencing_manager.cc
index 1fce30f3b4d..e420d5fafd6 100644
--- a/chromium/content/browser/geofencing/geofencing_manager.cc
+++ b/chromium/content/browser/geofencing/geofencing_manager.cc
@@ -395,11 +395,12 @@ void GeofencingManager::DeliverGeofencingEvent(
// until the callback dies. Otherwise the registration could be released when
// this method returns - before the event is delivered to the service worker.
active_version->RunAfterStartWorker(
- base::Bind(&GeofencingManager::OnEventError, this),
+ ServiceWorkerMetrics::EventType::GEOFENCING,
base::Bind(&GeofencingManager::DeliverEventToRunningWorker, this,
service_worker_registration, event_type,
registration->region_id, registration->region,
- make_scoped_refptr(active_version)));
+ make_scoped_refptr(active_version)),
+ base::Bind(&GeofencingManager::OnEventError, this));
}
void GeofencingManager::DeliverEventToRunningWorker(
@@ -424,7 +425,8 @@ void GeofencingManager::OnEventResponse(
const scoped_refptr<ServiceWorkerRegistration>& registration,
int request_id,
blink::WebServiceWorkerEventResult result) {
- bool finish_result = worker->FinishRequest(request_id);
+ bool finish_result = worker->FinishRequest(
+ request_id, result == blink::WebServiceWorkerEventResultCompleted);
DCHECK(finish_result)
<< "No messages should be passed to handler if request had "
"already finished";
diff --git a/chromium/content/browser/geofencing/geofencing_service.h b/chromium/content/browser/geofencing/geofencing_service.h
index 8c91193703f..dddbcfb1c70 100644
--- a/chromium/content/browser/geofencing/geofencing_service.h
+++ b/chromium/content/browser/geofencing/geofencing_service.h
@@ -9,6 +9,7 @@
#include <map>
+#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
diff --git a/chromium/content/browser/geolocation/fake_access_token_store.cc b/chromium/content/browser/geolocation/fake_access_token_store.cc
index 9e8704a0792..176513d2530 100644
--- a/chromium/content/browser/geolocation/fake_access_token_store.cc
+++ b/chromium/content/browser/geolocation/fake_access_token_store.cc
@@ -14,7 +14,7 @@ using testing::Invoke;
namespace content {
-FakeAccessTokenStore::FakeAccessTokenStore() : originating_task_runner_(NULL) {
+FakeAccessTokenStore::FakeAccessTokenStore() {
ON_CALL(*this, LoadAccessTokens(_))
.WillByDefault(Invoke(this,
&FakeAccessTokenStore::DefaultLoadAccessTokens));
@@ -33,19 +33,19 @@ void FakeAccessTokenStore::NotifyDelegateTokensLoaded() {
}
net::URLRequestContextGetter* context_getter = NULL;
- callback_.Run(access_token_set_, context_getter);
+ callback_.Run(access_token_map_, context_getter);
}
void FakeAccessTokenStore::DefaultLoadAccessTokens(
- const LoadAccessTokensCallbackType& callback) {
- originating_task_runner_ = base::ThreadTaskRunnerHandle::Get().get();
+ const LoadAccessTokensCallback& callback) {
+ originating_task_runner_ = base::ThreadTaskRunnerHandle::Get();
callback_ = callback;
}
void FakeAccessTokenStore::DefaultSaveAccessToken(
const GURL& server_url, const base::string16& access_token) {
DCHECK(server_url.is_valid());
- access_token_set_[server_url] = access_token;
+ access_token_map_[server_url] = access_token;
}
FakeAccessTokenStore::~FakeAccessTokenStore() {}
diff --git a/chromium/content/browser/geolocation/fake_access_token_store.h b/chromium/content/browser/geolocation/fake_access_token_store.h
index b6b674dfe73..276f5c5b107 100644
--- a/chromium/content/browser/geolocation/fake_access_token_store.h
+++ b/chromium/content/browser/geolocation/fake_access_token_store.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_GEOLOCATION_FAKE_ACCESS_TOKEN_STORE_H_
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
#include "content/public/browser/access_token_store.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -22,18 +23,18 @@ class FakeAccessTokenStore : public AccessTokenStore {
// AccessTokenStore
MOCK_METHOD1(LoadAccessTokens,
- void(const LoadAccessTokensCallbackType& callback));
+ void(const LoadAccessTokensCallback& callback));
MOCK_METHOD2(SaveAccessToken,
void(const GURL& server_url,
const base::string16& access_token));
- void DefaultLoadAccessTokens(const LoadAccessTokensCallbackType& callback);
+ void DefaultLoadAccessTokens(const LoadAccessTokensCallback& callback);
void DefaultSaveAccessToken(const GURL& server_url,
const base::string16& access_token);
- AccessTokenSet access_token_set_;
- LoadAccessTokensCallbackType callback_;
+ AccessTokenMap access_token_map_;
+ LoadAccessTokensCallback callback_;
protected:
// Protected instead of private so we can have NiceMocks.
@@ -43,7 +44,7 @@ class FakeAccessTokenStore : public AccessTokenStore {
// In some tests, NotifyDelegateTokensLoaded() is called on a thread
// other than the originating thread, in which case we must post
// back to it.
- base::SingleThreadTaskRunner* originating_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> originating_task_runner_;
DISALLOW_COPY_AND_ASSIGN(FakeAccessTokenStore);
};
diff --git a/chromium/content/browser/geolocation/geolocation_provider_impl.cc b/chromium/content/browser/geolocation/geolocation_provider_impl.cc
index 60d9efbfc44..c490907c792 100644
--- a/chromium/content/browser/geolocation/geolocation_provider_impl.cc
+++ b/chromium/content/browser/geolocation/geolocation_provider_impl.cc
@@ -22,10 +22,11 @@ GeolocationProvider* GeolocationProvider::GetInstance() {
scoped_ptr<GeolocationProvider::Subscription>
GeolocationProviderImpl::AddLocationUpdateCallback(
- const LocationUpdateCallback& callback, bool use_high_accuracy) {
+ const LocationUpdateCallback& callback,
+ bool enable_high_accuracy) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
scoped_ptr<GeolocationProvider::Subscription> subscription;
- if (use_high_accuracy) {
+ if (enable_high_accuracy) {
subscription = high_accuracy_callbacks_.Add(callback);
} else {
subscription = low_accuracy_callbacks_.Add(callback);
@@ -74,8 +75,7 @@ GeolocationProviderImpl* GeolocationProviderImpl::GetInstance() {
GeolocationProviderImpl::GeolocationProviderImpl()
: base::Thread("Geolocation"),
user_did_opt_into_location_services_(false),
- ignore_location_updates_(false),
- arbitrator_(NULL) {
+ ignore_location_updates_(false) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
high_accuracy_callbacks_.set_removal_callback(
base::Bind(&GeolocationProviderImpl::OnClientsChanged,
@@ -113,12 +113,11 @@ void GeolocationProviderImpl::OnClientsChanged() {
InformProvidersPermissionGranted();
}
// Determine a set of options that satisfies all clients.
- bool use_high_accuracy = !high_accuracy_callbacks_.empty();
+ bool enable_high_accuracy = !high_accuracy_callbacks_.empty();
// Send the current options to the providers as they may have changed.
task = base::Bind(&GeolocationProviderImpl::StartProviders,
- base::Unretained(this),
- use_high_accuracy);
+ base::Unretained(this), enable_high_accuracy);
}
task_runner()->PostTask(FROM_HERE, task);
@@ -130,10 +129,10 @@ void GeolocationProviderImpl::StopProviders() {
arbitrator_->StopProviders();
}
-void GeolocationProviderImpl::StartProviders(bool use_high_accuracy) {
+void GeolocationProviderImpl::StartProviders(bool enable_high_accuracy) {
DCHECK(OnGeolocationThread());
DCHECK(arbitrator_);
- arbitrator_->StartProviders(use_high_accuracy);
+ arbitrator_->StartProviders(enable_high_accuracy);
}
void GeolocationProviderImpl::InformProvidersPermissionGranted() {
@@ -167,14 +166,13 @@ void GeolocationProviderImpl::Init() {
void GeolocationProviderImpl::CleanUp() {
DCHECK(OnGeolocationThread());
- delete arbitrator_;
- arbitrator_ = NULL;
+ arbitrator_.reset();
}
-LocationArbitrator* GeolocationProviderImpl::CreateArbitrator() {
+scoped_ptr<LocationArbitrator> GeolocationProviderImpl::CreateArbitrator() {
LocationArbitratorImpl::LocationUpdateCallback callback = base::Bind(
&GeolocationProviderImpl::OnLocationUpdate, base::Unretained(this));
- return new LocationArbitratorImpl(callback);
+ return make_scoped_ptr(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 fe07da7822f..92129c5093f 100644
--- a/chromium/content/browser/geolocation/geolocation_provider_impl.h
+++ b/chromium/content/browser/geolocation/geolocation_provider_impl.h
@@ -11,6 +11,7 @@
#include "base/callback_forward.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/threading/thread.h"
#include "content/common/content_export.h"
#include "content/public/browser/geolocation_provider.h"
@@ -30,7 +31,7 @@ class CONTENT_EXPORT GeolocationProviderImpl
// GeolocationProvider implementation:
scoped_ptr<GeolocationProvider::Subscription> AddLocationUpdateCallback(
const LocationUpdateCallback& callback,
- bool use_high_accuracy) override;
+ bool enable_high_accuracy) override;
void UserDidOptIntoLocationServices() override;
void OverrideLocationForTesting(const Geoposition& position) override;
@@ -53,7 +54,8 @@ class CONTENT_EXPORT GeolocationProviderImpl
~GeolocationProviderImpl() override;
// Useful for injecting mock geolocation arbitrator in tests.
- virtual LocationArbitrator* CreateArbitrator();
+ // TODO(mvanouwerkerk): Use something like SetArbitratorForTesting instead.
+ virtual scoped_ptr<LocationArbitrator> CreateArbitrator();
private:
bool OnGeolocationThread() const;
@@ -68,7 +70,7 @@ class CONTENT_EXPORT GeolocationProviderImpl
// Starts the geolocation providers or updates their options (delegates to
// arbitrator).
- void StartProviders(bool use_high_accuracy);
+ void StartProviders(bool enable_high_accuracy);
// Updates the providers on the geolocation thread, which must be running.
void InformProvidersPermissionGranted();
@@ -90,7 +92,7 @@ class CONTENT_EXPORT GeolocationProviderImpl
bool ignore_location_updates_;
// Only to be used on the geolocation thread.
- LocationArbitrator* arbitrator_;
+ scoped_ptr<LocationArbitrator> arbitrator_;
DISALLOW_COPY_AND_ASSIGN(GeolocationProviderImpl);
};
diff --git a/chromium/content/browser/geolocation/geolocation_provider_impl_unittest.cc b/chromium/content/browser/geolocation/geolocation_provider_impl_unittest.cc
index 0b354fd01d5..f1c7323f5a4 100644
--- a/chromium/content/browser/geolocation/geolocation_provider_impl_unittest.cc
+++ b/chromium/content/browser/geolocation/geolocation_provider_impl_unittest.cc
@@ -38,16 +38,18 @@ class LocationProviderForTestArbitrator : public GeolocationProviderImpl {
protected:
// GeolocationProviderImpl implementation:
- LocationArbitrator* CreateArbitrator() override;
+ scoped_ptr<LocationArbitrator> CreateArbitrator() override;
private:
+ // An alias to the arbitrator stored in the super class, where it is owned.
MockLocationArbitrator* mock_arbitrator_;
};
-LocationArbitrator* LocationProviderForTestArbitrator::CreateArbitrator() {
+scoped_ptr<LocationArbitrator>
+LocationProviderForTestArbitrator::CreateArbitrator() {
DCHECK(mock_arbitrator_ == NULL);
mock_arbitrator_ = new MockLocationArbitrator;
- return mock_arbitrator_;
+ return make_scoped_ptr(mock_arbitrator_);
}
class GeolocationObserver {
diff --git a/chromium/content/browser/geolocation/geolocation_service_context.cc b/chromium/content/browser/geolocation/geolocation_service_context.cc
index 7cdeb354faf..aeb6e621034 100644
--- a/chromium/content/browser/geolocation/geolocation_service_context.cc
+++ b/chromium/content/browser/geolocation/geolocation_service_context.cc
@@ -16,7 +16,7 @@ GeolocationServiceContext::~GeolocationServiceContext() {
void GeolocationServiceContext::CreateService(
const base::Closure& update_callback,
- mojo::InterfaceRequest<GeolocationService> request) {
+ mojo::InterfaceRequest<blink::mojom::GeolocationService> request) {
GeolocationServiceImpl* service =
new GeolocationServiceImpl(std::move(request), this, update_callback);
services_.push_back(service);
diff --git a/chromium/content/browser/geolocation/geolocation_service_context.h b/chromium/content/browser/geolocation/geolocation_service_context.h
index 843fd3827cb..2e494a12228 100644
--- a/chromium/content/browser/geolocation/geolocation_service_context.h
+++ b/chromium/content/browser/geolocation/geolocation_service_context.h
@@ -8,6 +8,7 @@
#include "base/macros.h"
#include "base/memory/scoped_vector.h"
#include "content/browser/geolocation/geolocation_service_impl.h"
+#include "third_party/WebKit/public/platform/modules/geolocation/geolocation.mojom.h"
namespace content {
@@ -22,8 +23,9 @@ class GeolocationServiceContext {
// Creates a GeolocationServiceImpl that is weakly bound to |request|.
// |update_callback| will be called when services send
// location updates to their clients.
- void CreateService(const base::Closure& update_callback,
- mojo::InterfaceRequest<GeolocationService> request);
+ void CreateService(
+ const base::Closure& update_callback,
+ mojo::InterfaceRequest<blink::mojom::GeolocationService> request);
// Called when a service has a connection error. After this call, it is no
// longer safe to access |service|.
diff --git a/chromium/content/browser/geolocation/geolocation_service_impl.cc b/chromium/content/browser/geolocation/geolocation_service_impl.cc
index 764ff10abdd..5424c141e58 100644
--- a/chromium/content/browser/geolocation/geolocation_service_impl.cc
+++ b/chromium/content/browser/geolocation/geolocation_service_impl.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/metrics/histogram.h"
#include "content/browser/geolocation/geolocation_service_context.h"
-#include "content/public/common/mojo_geoposition.mojom.h"
namespace content {
@@ -79,7 +78,7 @@ GeolocationServiceImpl::~GeolocationServiceImpl() {
// Make sure to respond to any pending callback even without a valid position.
if (!position_callback_.is_null()) {
if (!current_position_.valid) {
- current_position_.error_code = MojoGeoposition::ErrorCode(
+ current_position_.error_code = blink::mojom::Geoposition::ErrorCode(
GEOPOSITION_ERROR_CODE_POSITION_UNAVAILABLE);
current_position_.error_message = mojo::String("");
}
@@ -178,7 +177,7 @@ void GeolocationServiceImpl::OnLocationUpdate(const Geoposition& position) {
current_position_.speed = position.speed;
current_position_.timestamp = position.timestamp.ToDoubleT();
current_position_.error_code =
- MojoGeoposition::ErrorCode(position.error_code);
+ blink::mojom::Geoposition::ErrorCode(position.error_code);
current_position_.error_message = position.error_message;
has_position_to_report_ = true;
diff --git a/chromium/content/browser/geolocation/geolocation_service_impl.h b/chromium/content/browser/geolocation/geolocation_service_impl.h
index d72706e5b3c..e0565eed8d5 100644
--- a/chromium/content/browser/geolocation/geolocation_service_impl.h
+++ b/chromium/content/browser/geolocation/geolocation_service_impl.h
@@ -5,9 +5,8 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "content/browser/geolocation/geolocation_provider_impl.h"
-#include "content/common/geolocation_service.mojom.h"
-#include "content/public/common/mojo_geoposition.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
+#include "third_party/WebKit/public/platform/modules/geolocation/geolocation.mojom.h"
#ifndef CONTENT_BROWSER_GEOLOCATION_GEOLOCATION_SERVICE_IMPL_H_
#define CONTENT_BROWSER_GEOLOCATION_GEOLOCATION_SERVICE_IMPL_H_
@@ -18,14 +17,15 @@ class GeolocationProvider;
class GeolocationServiceContext;
// Implements the GeolocationService Mojo interface.
-class GeolocationServiceImpl : public GeolocationService {
+class GeolocationServiceImpl : public blink::mojom::GeolocationService {
public:
// |context| must outlive this object. |update_callback| will be called when
// location updates are sent, allowing the client to know when the service
// is being used.
- GeolocationServiceImpl(mojo::InterfaceRequest<GeolocationService> request,
- GeolocationServiceContext* context,
- const base::Closure& update_callback);
+ GeolocationServiceImpl(
+ mojo::InterfaceRequest<blink::mojom::GeolocationService> request,
+ GeolocationServiceContext* context,
+ const base::Closure& update_callback);
~GeolocationServiceImpl() override;
// Starts listening for updates.
@@ -40,9 +40,9 @@ class GeolocationServiceImpl : public GeolocationService {
void ClearOverride();
private:
- typedef mojo::Callback<void(MojoGeopositionPtr)> PositionCallback;
+ typedef mojo::Callback<void(blink::mojom::GeopositionPtr)> PositionCallback;
- // GeolocationService:
+ // blink::mojom::GeolocationService:
void SetHighAccuracy(bool high_accuracy) override;
void QueryNextPosition(const PositionCallback& callback) override;
@@ -52,7 +52,7 @@ class GeolocationServiceImpl : public GeolocationService {
void ReportCurrentPosition();
// The binding between this object and the other end of the pipe.
- mojo::Binding<GeolocationService> binding_;
+ mojo::Binding<blink::mojom::GeolocationService> binding_;
// Owns this object.
GeolocationServiceContext* context_;
@@ -69,7 +69,7 @@ class GeolocationServiceImpl : public GeolocationService {
// subsequently been called.
Geoposition position_override_;
- MojoGeoposition current_position_;
+ blink::mojom::Geoposition current_position_;
// Whether this instance is currently observing location updates with high
// accuracy.
diff --git a/chromium/content/browser/geolocation/location_api_adapter_android.cc b/chromium/content/browser/geolocation/location_api_adapter_android.cc
index 4037ab6e36c..e1472ea7d11 100644
--- a/chromium/content/browser/geolocation/location_api_adapter_android.cc
+++ b/chromium/content/browser/geolocation/location_api_adapter_android.cc
@@ -151,7 +151,7 @@ bool AndroidLocationApiAdapter::RegisterGeolocationService(JNIEnv* env) {
}
void AndroidLocationApiAdapter::CreateJavaObject(JNIEnv* env) {
- // Create the Java AndroidLocationProvider object.
+ // Create the Java LocationProviderAdapter object.
java_location_provider_android_object_.Reset(
Java_LocationProviderAdapter_create(env,
base::android::GetApplicationContext()));
diff --git a/chromium/content/browser/geolocation/location_api_adapter_android.h b/chromium/content/browser/geolocation/location_api_adapter_android.h
index c58e26d6612..6e48109a090 100644
--- a/chromium/content/browser/geolocation/location_api_adapter_android.h
+++ b/chromium/content/browser/geolocation/location_api_adapter_android.h
@@ -19,18 +19,18 @@ namespace content {
class LocationProviderAndroid;
struct Geoposition;
-// Interacts with JNI and reports back to AndroidLocationProvider.
-// This class creates a LocationProvider java object and listens for
-// updates.
+// Interacts with JNI and reports back to LocationProviderAndroid. This class
+// creates a LocationProvider java object and listens for updates.
// The simplified flow is:
-// GeolocationProvider runs in a Geolocation Thread and fetches geolocation data
-// from a LocationProvider.
-// AndroidLocationProvider access a singleton AndroidLocationApiAdapter
-// AndroidLocationApiAdapter calls via JNI and uses the main thread Looper
-// in the java side to listen for location updates. We then bounce these updates
-// to the Geolocation thread.
+// - GeolocationProvider runs in a Geolocation Thread and fetches geolocation
+// data from a LocationProvider.
+// - LocationProviderAndroid accesses a singleton AndroidLocationApiAdapter.
+// - AndroidLocationApiAdapter calls via JNI and uses the main thread Looper
+// in the java side to listen for location updates. We then bounce these
+// updates to the Geolocation thread.
+//
// Note that AndroidLocationApiAdapter is a singleton and there's at most only
-// one AndroidLocationProvider that has called Start().
+// one LocationProviderAndroid that has called Start().
class AndroidLocationApiAdapter {
public:
// Starts the underlying location provider, returns true if successful.
@@ -71,7 +71,8 @@ class AndroidLocationApiAdapter {
base::android::ScopedJavaGlobalRef<jobject>
java_location_provider_android_object_;
- LocationProviderAndroid* location_provider_;
+ // TODO(mvanouwerkerk): Use a callback instead of holding a pointer.
+ LocationProviderAndroid* location_provider_; // Owned by the arbitrator.
// Guards against the following member which is accessed on Geolocation
// thread and the JNI main thread looper.
diff --git a/chromium/content/browser/geolocation/location_arbitrator.h b/chromium/content/browser/geolocation/location_arbitrator.h
index feb42e519dc..3f9c6326e22 100644
--- a/chromium/content/browser/geolocation/location_arbitrator.h
+++ b/chromium/content/browser/geolocation/location_arbitrator.h
@@ -17,7 +17,7 @@ public:
virtual ~LocationArbitrator() {};
// See more details in geolocation_provider.
- virtual void StartProviders(bool use_high_accuracy) = 0;
+ virtual void StartProviders(bool enable_high_accuracy) = 0;
virtual void StopProviders() = 0;
// Called everytime permission is granted to a page for using geolocation.
diff --git a/chromium/content/browser/geolocation/location_arbitrator_impl.cc b/chromium/content/browser/geolocation/location_arbitrator_impl.cc
index 03e3676f7e6..d6cb78b1657 100644
--- a/chromium/content/browser/geolocation/location_arbitrator_impl.cc
+++ b/chromium/content/browser/geolocation/location_arbitrator_impl.cc
@@ -47,13 +47,11 @@ GURL LocationArbitratorImpl::DefaultNetworkProviderURL() {
void LocationArbitratorImpl::OnPermissionGranted() {
is_permission_granted_ = true;
- for (ScopedVector<LocationProvider>::iterator i = providers_.begin();
- i != providers_.end(); ++i) {
- (*i)->OnPermissionGranted();
- }
+ for (const auto& provider : providers_)
+ provider->OnPermissionGranted();
}
-void LocationArbitratorImpl::StartProviders(bool use_high_accuracy) {
+void LocationArbitratorImpl::StartProviders(bool enable_high_accuracy) {
// GetAccessTokenStore() will return NULL for embedders not implementing
// the AccessTokenStore class, so we report an error to avoid JavaScript
// requests of location to wait eternally for a reply.
@@ -67,7 +65,7 @@ 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;
+ enable_high_accuracy_ = enable_high_accuracy;
if (providers_.empty()) {
DCHECK(DefaultNetworkProviderURL().is_valid());
access_token_store->LoadAccessTokens(
@@ -79,10 +77,8 @@ void LocationArbitratorImpl::StartProviders(bool use_high_accuracy) {
}
void LocationArbitratorImpl::DoStartProviders() {
- for (ScopedVector<LocationProvider>::iterator i = providers_.begin();
- i != providers_.end(); ++i) {
- (*i)->StartProvider(use_high_accuracy_);
- }
+ for (const auto& provider : providers_)
+ provider->StartProvider(enable_high_accuracy_);
}
void LocationArbitratorImpl::StopProviders() {
@@ -97,7 +93,7 @@ void LocationArbitratorImpl::StopProviders() {
}
void LocationArbitratorImpl::OnAccessTokenStoresLoaded(
- AccessTokenStore::AccessTokenSet access_token_set,
+ AccessTokenStore::AccessTokenMap access_token_map,
net::URLRequestContextGetter* context_getter) {
if (!is_running_ || !providers_.empty()) {
// A second StartProviders() call may have arrived before the first
@@ -105,15 +101,11 @@ void LocationArbitratorImpl::OnAccessTokenStoresLoaded(
return;
}
// If there are no access tokens, boot strap it with the default server URL.
- if (access_token_set.empty())
- access_token_set[DefaultNetworkProviderURL()];
- for (AccessTokenStore::AccessTokenSet::iterator i =
- access_token_set.begin();
- i != access_token_set.end(); ++i) {
- RegisterProvider(
- NewNetworkLocationProvider(
- GetAccessTokenStore(), context_getter,
- i->first, i->second));
+ if (access_token_map.empty())
+ access_token_map[DefaultNetworkProviderURL()];
+ for (const auto& entry : access_token_map) {
+ RegisterProvider(NewNetworkLocationProvider(
+ GetAccessTokenStore(), context_getter, entry.first, entry.second));
}
LocationProvider* provider =
diff --git a/chromium/content/browser/geolocation/location_arbitrator_impl.h b/chromium/content/browser/geolocation/location_arbitrator_impl.h
index 65a55321022..60c9ac57a90 100644
--- a/chromium/content/browser/geolocation/location_arbitrator_impl.h
+++ b/chromium/content/browser/geolocation/location_arbitrator_impl.h
@@ -45,7 +45,7 @@ class CONTENT_EXPORT LocationArbitratorImpl : public LocationArbitrator {
static GURL DefaultNetworkProviderURL();
// LocationArbitrator
- void StartProviders(bool use_high_accuracy) override;
+ void StartProviders(bool enable_high_accuracy) override;
void StopProviders() override;
void OnPermissionGranted() override;
bool HasPermissionBeenGranted() const override;
@@ -69,7 +69,7 @@ class CONTENT_EXPORT LocationArbitratorImpl : public LocationArbitrator {
// |providers_| or deleted on error (e.g. it fails to start).
void RegisterProvider(LocationProvider* provider);
void OnAccessTokenStoresLoaded(
- AccessTokenStore::AccessTokenSet access_token_store,
+ AccessTokenStore::AccessTokenMap access_token_map,
net::URLRequestContextGetter* context_getter);
void DoStartProviders();
@@ -88,7 +88,7 @@ class CONTENT_EXPORT LocationArbitratorImpl : public LocationArbitrator {
LocationUpdateCallback arbitrator_update_callback_;
LocationProvider::LocationProviderUpdateCallback provider_update_callback_;
ScopedVector<LocationProvider> providers_;
- bool use_high_accuracy_;
+ bool enable_high_accuracy_;
// The provider which supplied the current |position_|
const LocationProvider* position_provider_;
bool is_permission_granted_;
diff --git a/chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc b/chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc
index bd5eb6e9d07..0ca94b59f48 100644
--- a/chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc
+++ b/chromium/content/browser/geolocation/location_arbitrator_impl_unittest.cc
@@ -173,8 +173,8 @@ TEST_F(GeolocationLocationArbitratorTest, NormalUsage) {
EXPECT_FALSE(gps());
arbitrator_->StartProviders(false);
- EXPECT_TRUE(access_token_store_->access_token_set_.empty());
- EXPECT_TRUE(access_token_store_->access_token_set_.empty());
+ EXPECT_TRUE(access_token_store_->access_token_map_.empty());
+ EXPECT_TRUE(access_token_store_->access_token_map_.empty());
access_token_store_->NotifyDelegateTokensLoaded();
ASSERT_TRUE(cell());
diff --git a/chromium/content/browser/geolocation/mock_location_arbitrator.cc b/chromium/content/browser/geolocation/mock_location_arbitrator.cc
index 154fcae4bee..1ebef72974f 100644
--- a/chromium/content/browser/geolocation/mock_location_arbitrator.cc
+++ b/chromium/content/browser/geolocation/mock_location_arbitrator.cc
@@ -14,7 +14,7 @@ MockLocationArbitrator::MockLocationArbitrator()
providers_started_(false) {
}
-void MockLocationArbitrator::StartProviders(bool use_high_accuracy) {
+void MockLocationArbitrator::StartProviders(bool enable_high_accuracy) {
providers_started_ = true;
}
diff --git a/chromium/content/browser/geolocation/mock_location_arbitrator.h b/chromium/content/browser/geolocation/mock_location_arbitrator.h
index 31e66016b19..2ee057db201 100644
--- a/chromium/content/browser/geolocation/mock_location_arbitrator.h
+++ b/chromium/content/browser/geolocation/mock_location_arbitrator.h
@@ -20,7 +20,7 @@ class MockLocationArbitrator : public LocationArbitrator {
bool providers_started() const { return providers_started_; }
// LocationArbitrator:
- void StartProviders(bool use_high_accuracy) override;
+ void StartProviders(bool enable_high_accuracy) override;
void StopProviders() override;
void OnPermissionGranted() override;
bool HasPermissionBeenGranted() const override;
diff --git a/chromium/content/browser/geolocation/network_location_provider.cc b/chromium/content/browser/geolocation/network_location_provider.cc
index 5db43fa6784..01748610e38 100644
--- a/chromium/content/browser/geolocation/network_location_provider.cc
+++ b/chromium/content/browser/geolocation/network_location_provider.cc
@@ -81,12 +81,9 @@ bool NetworkLocationProvider::PositionCache::MakeKey(
const size_t kCharsPerMacAddress = 6 * 3 + 1; // e.g. "11:22:33:44:55:66|"
key->reserve(wifi_data.access_point_data.size() * kCharsPerMacAddress);
const base::string16 separator(base::ASCIIToUTF16("|"));
- for (WifiData::AccessPointDataSet::const_iterator iter =
- wifi_data.access_point_data.begin();
- iter != wifi_data.access_point_data.end();
- iter++) {
+ for (const auto& access_point_data : wifi_data.access_point_data) {
*key += separator;
- *key += iter->mac_address;
+ *key += access_point_data.mac_address;
*key += separator;
}
// If the key is the empty string, return false, as we don't want to cache a
@@ -215,7 +212,7 @@ bool NetworkLocationProvider::StartProvider(bool high_accuracy) {
void NetworkLocationProvider::OnWifiDataUpdated() {
DCHECK(CalledOnValidThread());
- wifi_data_updated_timestamp_ = base::Time::Now();
+ wifi_timestamp_ = base::Time::Now();
is_new_data_available_ = is_wifi_data_complete_;
RequestRefresh();
@@ -238,8 +235,8 @@ void NetworkLocationProvider::RequestPosition() {
const Geoposition* cached_position =
position_cache_->FindPosition(wifi_data_);
- DCHECK(!wifi_data_updated_timestamp_.is_null()) <<
- "Timestamp must be set before looking up position";
+ DCHECK(!wifi_timestamp_.is_null())
+ << "Timestamp must be set before looking up position";
if (cached_position) {
DCHECK(cached_position->Validate());
// Record the position and update its timestamp.
@@ -247,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 = wifi_data_updated_timestamp_;
+ position_.timestamp = wifi_timestamp_;
is_new_data_available_ = false;
// Let listeners know that we now have a position available.
NotifyCallback(position_);
@@ -267,8 +264,7 @@ void NetworkLocationProvider::RequestPosition() {
"with new data. Wifi APs: "
<< wifi_data_.access_point_data.size();
}
- request_->MakeRequest(access_token_, wifi_data_,
- wifi_data_updated_timestamp_);
+ request_->MakeRequest(access_token_, wifi_data_, wifi_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 69d891f2494..6c37a8cb16e 100644
--- a/chromium/content/browser/geolocation/network_location_provider.h
+++ b/chromium/content/browser/geolocation/network_location_provider.h
@@ -109,7 +109,7 @@ class NetworkLocationProvider
bool is_wifi_data_complete_;
// The timestamp for the latest wifi data update.
- base::Time wifi_data_updated_timestamp_;
+ base::Time wifi_timestamp_;
// Cached value loaded from the token store or set by a previous server
// response, and sent in each subsequent network request.
diff --git a/chromium/content/browser/geolocation/network_location_provider_unittest.cc b/chromium/content/browser/geolocation/network_location_provider_unittest.cc
index 724eb356427..0b09a39fa8f 100644
--- a/chromium/content/browser/geolocation/network_location_provider_unittest.cc
+++ b/chromium/content/browser/geolocation/network_location_provider_unittest.cc
@@ -126,7 +126,7 @@ class GeolocationNetworkProviderTest : public testing::Test {
access_token_store_.get(),
NULL, // No URLContextGetter needed, as using test urlfecther factory.
test_server_url_,
- access_token_store_->access_token_set_[test_server_url_]);
+ access_token_store_->access_token_map_[test_server_url_]);
if (set_permission_granted)
provider->OnPermissionGranted();
return provider;
@@ -415,7 +415,7 @@ TEST_F(GeolocationNetworkProviderTest, MultipleWifiScansComplete) {
// Token should be in the store.
EXPECT_EQ(base::UTF8ToUTF16(REFERENCE_ACCESS_TOKEN),
- access_token_store_->access_token_set_[test_server_url_]);
+ access_token_store_->access_token_map_[test_server_url_]);
// Wifi updated again, with one less AP. This is 'close enough' to the
// previous scan, so no new request made.
@@ -508,7 +508,7 @@ TEST_F(GeolocationNetworkProviderTest, NetworkRequestDeferredForPermission) {
TEST_F(GeolocationNetworkProviderTest,
NetworkRequestWithWifiDataDeferredForPermission) {
- access_token_store_->access_token_set_[test_server_url_] =
+ access_token_store_->access_token_map_[test_server_url_] =
base::UTF8ToUTF16(REFERENCE_ACCESS_TOKEN);
scoped_ptr<LocationProvider> provider(CreateProvider(false));
EXPECT_TRUE(provider->StartProvider(false));
diff --git a/chromium/content/browser/geolocation/network_location_request.cc b/chromium/content/browser/geolocation/network_location_request.cc
index dd23daeeddd..7471c17160e 100644
--- a/chromium/content/browser/geolocation/network_location_request.cc
+++ b/chromium/content/browser/geolocation/network_location_request.cc
@@ -74,7 +74,7 @@ void RecordUmaAccessPoints(int count) {
GURL FormRequestURL(const GURL& url);
void FormUploadData(const WifiData& wifi_data,
- const base::Time& timestamp,
+ const base::Time& wifi_timestamp,
const base::string16& access_token,
std::string* upload_data);
@@ -83,7 +83,7 @@ void FormUploadData(const WifiData& wifi_data,
void GetLocationFromResponse(bool http_post_result,
int status_code,
const std::string& response_body,
- const base::Time& timestamp,
+ const base::Time& wifi_timestamp,
const GURL& server_url,
Geoposition* position,
base::string16* access_token);
@@ -92,7 +92,7 @@ void GetLocationFromResponse(bool http_post_result,
// Sets |*position| to the parsed location if a valid fix was received,
// otherwise leaves it unchanged.
bool ParseServerResponse(const std::string& response_body,
- const base::Time& timestamp,
+ const base::Time& wifi_timestamp,
Geoposition* position,
base::string16* access_token);
void AddWifiData(const WifiData& wifi_data,
@@ -114,7 +114,7 @@ NetworkLocationRequest::~NetworkLocationRequest() {
bool NetworkLocationRequest::MakeRequest(const base::string16& access_token,
const WifiData& wifi_data,
- const base::Time& timestamp) {
+ const base::Time& wifi_timestamp) {
RecordUmaEvent(NETWORK_LOCATION_REQUEST_EVENT_REQUEST_START);
RecordUmaAccessPoints(wifi_data.access_point_data.size());
if (url_fetcher_ != NULL) {
@@ -123,14 +123,14 @@ bool NetworkLocationRequest::MakeRequest(const base::string16& access_token,
url_fetcher_.reset();
}
wifi_data_ = wifi_data;
- wifi_data_timestamp_ = timestamp;
+ wifi_timestamp_ = wifi_timestamp;
GURL request_url = FormRequestURL(url_);
url_fetcher_ = net::URLFetcher::Create(url_fetcher_id_for_tests, request_url,
net::URLFetcher::POST, this);
url_fetcher_->SetRequestContext(url_context_.get());
std::string upload_data;
- FormUploadData(wifi_data, timestamp, access_token, &upload_data);
+ FormUploadData(wifi_data, wifi_timestamp, access_token, &upload_data);
url_fetcher_->SetUploadData("application/json", upload_data);
url_fetcher_->SetLoadFlags(
net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE |
@@ -154,12 +154,8 @@ void NetworkLocationRequest::OnURLFetchComplete(
base::string16 access_token;
std::string data;
source->GetResponseAsString(&data);
- GetLocationFromResponse(status.is_success(),
- response_code,
- data,
- wifi_data_timestamp_,
- source->GetURL(),
- &position,
+ GetLocationFromResponse(status.is_success(), response_code, data,
+ wifi_timestamp_, source->GetURL(), &position,
&access_token);
const bool server_error =
!status.is_success() || (response_code >= 500 && response_code < 600);
@@ -209,14 +205,14 @@ GURL FormRequestURL(const GURL& url) {
}
void FormUploadData(const WifiData& wifi_data,
- const base::Time& timestamp,
+ const base::Time& wifi_timestamp,
const base::string16& access_token,
std::string* upload_data) {
int age = std::numeric_limits<int32_t>::min(); // Invalid so AddInteger()
// will ignore.
- if (!timestamp.is_null()) {
+ if (!wifi_timestamp.is_null()) {
// Convert absolute timestamps into a relative age.
- int64_t delta_ms = (base::Time::Now() - timestamp).InMilliseconds();
+ int64_t delta_ms = (base::Time::Now() - wifi_timestamp).InMilliseconds();
if (delta_ms >= 0 && delta_ms < std::numeric_limits<int32_t>::max())
age = static_cast<int>(delta_ms);
}
@@ -253,24 +249,17 @@ void AddWifiData(const WifiData& wifi_data,
typedef std::multiset<const AccessPointData*, AccessPointLess> AccessPointSet;
AccessPointSet access_points_by_signal_strength;
- for (WifiData::AccessPointDataSet::const_iterator iter =
- wifi_data.access_point_data.begin();
- iter != wifi_data.access_point_data.end();
- ++iter) {
- access_points_by_signal_strength.insert(&(*iter));
- }
+ for (const auto& ap_data : wifi_data.access_point_data)
+ access_points_by_signal_strength.insert(&ap_data);
base::ListValue* wifi_access_point_list = new base::ListValue();
- for (AccessPointSet::iterator iter =
- access_points_by_signal_strength.begin();
- iter != access_points_by_signal_strength.end();
- ++iter) {
+ for (const auto& ap_data : access_points_by_signal_strength) {
base::DictionaryValue* wifi_dict = new base::DictionaryValue();
- AddString("macAddress", base::UTF16ToUTF8((*iter)->mac_address), wifi_dict);
- AddInteger("signalStrength", (*iter)->radio_signal_strength, wifi_dict);
+ AddString("macAddress", base::UTF16ToUTF8(ap_data->mac_address), wifi_dict);
+ AddInteger("signalStrength", ap_data->radio_signal_strength, wifi_dict);
AddInteger("age", age_milliseconds, wifi_dict);
- AddInteger("channel", (*iter)->channel, wifi_dict);
- AddInteger("signalToNoiseRatio", (*iter)->signal_to_noise, wifi_dict);
+ AddInteger("channel", ap_data->channel, wifi_dict);
+ AddInteger("signalToNoiseRatio", ap_data->signal_to_noise, wifi_dict);
wifi_access_point_list->Append(wifi_dict);
}
request->Set("wifiAccessPoints", wifi_access_point_list);
@@ -292,7 +281,7 @@ void FormatPositionError(const GURL& server_url,
void GetLocationFromResponse(bool http_post_result,
int status_code,
const std::string& response_body,
- const base::Time& timestamp,
+ const base::Time& wifi_timestamp,
const GURL& server_url,
Geoposition* position,
base::string16* access_token) {
@@ -315,7 +304,8 @@ void GetLocationFromResponse(bool http_post_result,
}
// We use the timestamp from the wifi data that was used to generate
// this position fix.
- if (!ParseServerResponse(response_body, timestamp, position, access_token)) {
+ if (!ParseServerResponse(response_body, wifi_timestamp, position,
+ access_token)) {
// We failed to parse the repsonse.
FormatPositionError(server_url, "Response was malformed", position);
RecordUmaEvent(NETWORK_LOCATION_REQUEST_EVENT_RESPONSE_MALFORMED);
@@ -353,14 +343,14 @@ bool GetAsDouble(const base::DictionaryValue& object,
}
bool ParseServerResponse(const std::string& response_body,
- const base::Time& timestamp,
+ const base::Time& wifi_timestamp,
Geoposition* position,
base::string16* access_token) {
DCHECK(position);
DCHECK(!position->Validate());
DCHECK(position->error_code == Geoposition::ERROR_CODE_NONE);
DCHECK(access_token);
- DCHECK(!timestamp.is_null());
+ DCHECK(!wifi_timestamp.is_null());
if (response_body.empty()) {
LOG(WARNING) << "ParseServerResponse() : Response was empty.";
@@ -423,7 +413,7 @@ bool ParseServerResponse(const std::string& response_body,
// All error paths covered: now start actually modifying postion.
position->latitude = latitude;
position->longitude = longitude;
- position->timestamp = timestamp;
+ position->timestamp = wifi_timestamp;
// Other fields are optional.
GetAsDouble(*response_object, kAccuracyString, &position->accuracy);
diff --git a/chromium/content/browser/geolocation/network_location_request.h b/chromium/content/browser/geolocation/network_location_request.h
index fe15b72267d..6f7673af514 100644
--- a/chromium/content/browser/geolocation/network_location_request.h
+++ b/chromium/content/browser/geolocation/network_location_request.h
@@ -5,9 +5,11 @@
#ifndef CONTENT_BROWSER_GEOLOCATION_NETWORK_LOCATION_REQUEST_H_
#define CONTENT_BROWSER_GEOLOCATION_NETWORK_LOCATION_REQUEST_H_
+#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/strings/string16.h"
#include "content/browser/geolocation/wifi_data_provider.h"
#include "content/common/content_export.h"
#include "net/url_request/url_fetcher_delegate.h"
@@ -47,7 +49,7 @@ class NetworkLocationRequest : private net::URLFetcherDelegate {
// started. In all cases, any currently pending request will be canceled.
bool MakeRequest(const base::string16& access_token,
const WifiData& wifi_data,
- const base::Time& timestamp);
+ const base::Time& wifi_timestamp);
bool is_request_pending() const { return url_fetcher_ != NULL; }
const GURL& url() const { return url_; }
@@ -64,7 +66,7 @@ class NetworkLocationRequest : private net::URLFetcherDelegate {
// Keep a copy of the data sent in the request, so we can refer back to it
// when the response arrives.
WifiData wifi_data_;
- base::Time wifi_data_timestamp_;
+ base::Time wifi_timestamp_;
// The start time for the request.
base::TimeTicks request_start_time_;
diff --git a/chromium/content/browser/geolocation/wifi_data.cc b/chromium/content/browser/geolocation/wifi_data.cc
index 2f41c33ee48..d82e6f442f0 100644
--- a/chromium/content/browser/geolocation/wifi_data.cc
+++ b/chromium/content/browser/geolocation/wifi_data.cc
@@ -23,6 +23,8 @@ AccessPointData::~AccessPointData() {}
WifiData::WifiData() {}
+WifiData::WifiData(const WifiData& other) = default;
+
WifiData::~WifiData() {}
bool WifiData::DiffersSignificantly(const WifiData& other) const {
diff --git a/chromium/content/browser/geolocation/wifi_data.h b/chromium/content/browser/geolocation/wifi_data.h
index d6e0b33ab4e..b3cf569bb71 100644
--- a/chromium/content/browser/geolocation/wifi_data.h
+++ b/chromium/content/browser/geolocation/wifi_data.h
@@ -37,6 +37,7 @@ struct AccessPointDataLess {
// All data for wifi.
struct CONTENT_EXPORT WifiData {
WifiData();
+ WifiData(const WifiData& other);
~WifiData();
// Determines whether a new set of WiFi data differs significantly from this.
diff --git a/chromium/content/browser/geolocation/wifi_data_provider.cc b/chromium/content/browser/geolocation/wifi_data_provider.cc
index 71b78c4765e..433572c99fc 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider.cc
@@ -4,11 +4,16 @@
#include "content/browser/geolocation/wifi_data_provider.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/location.h"
+#include "base/thread_task_runner_handle.h"
+
namespace content {
WifiDataProvider::WifiDataProvider()
- : client_loop_(base::MessageLoop::current()) {
- DCHECK(client_loop_);
+ : client_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
+ DCHECK(client_task_runner_);
}
WifiDataProvider::~WifiDataProvider() {
@@ -27,16 +32,12 @@ bool WifiDataProvider::has_callbacks() const {
}
void WifiDataProvider::RunCallbacks() {
- client_loop_->task_runner()->PostTask(
+ client_task_runner_->PostTask(
FROM_HERE, base::Bind(&WifiDataProvider::DoRunCallbacks, this));
}
bool WifiDataProvider::CalledOnClientThread() const {
- return base::MessageLoop::current() == this->client_loop_;
-}
-
-base::MessageLoop* WifiDataProvider::client_loop() const {
- return client_loop_;
+ return client_task_runner()->BelongsToCurrentThread();
}
void WifiDataProvider::DoRunCallbacks() {
diff --git a/chromium/content/browser/geolocation/wifi_data_provider.h b/chromium/content/browser/geolocation/wifi_data_provider.h
index 96ab8817b8a..ce514969d55 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider.h
+++ b/chromium/content/browser/geolocation/wifi_data_provider.h
@@ -7,13 +7,10 @@
#include <set>
-#include "base/bind.h"
-#include "base/callback.h"
+#include "base/callback_forward.h"
#include "base/macros.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/single_thread_task_runner.h"
#include "content/browser/geolocation/wifi_data.h"
#include "content/common/content_export.h"
@@ -57,14 +54,15 @@ class CONTENT_EXPORT WifiDataProvider
bool CalledOnClientThread() const;
- base::MessageLoop* client_loop() const;
+ scoped_refptr<base::SingleThreadTaskRunner> client_task_runner() const {
+ return client_task_runner_;
+ }
private:
void DoRunCallbacks();
- // Reference to the client's message loop. All callbacks should happen in this
- // context.
- base::MessageLoop* client_loop_;
+ // The task runner for the client thread, all callbacks should run on it.
+ scoped_refptr<base::SingleThreadTaskRunner> client_task_runner_;
CallbackSet callbacks_;
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_chromeos.cc b/chromium/content/browser/geolocation/wifi_data_provider_chromeos.cc
index 6060ec1bdbb..4f148667f63 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_chromeos.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider_chromeos.cc
@@ -75,11 +75,11 @@ void WifiDataProviderChromeOs::DoWifiScanTaskOnUIThread() {
WifiData new_data;
if (GetAccessPointData(&new_data.access_point_data)) {
- client_loop()->PostTask(
+ client_task_runner()->PostTask(
FROM_HERE,
base::Bind(&WifiDataProviderChromeOs::DidWifiScanTask, this, new_data));
} else {
- client_loop()->PostTask(
+ client_task_runner()->PostTask(
FROM_HERE,
base::Bind(&WifiDataProviderChromeOs::DidWifiScanTaskNoResults, this));
}
@@ -151,15 +151,13 @@ bool WifiDataProviderChromeOs::GetAccessPointData(
GetWifiAccessPoints(&access_points, &age_ms)) {
return false;
}
- for (chromeos::WifiAccessPointVector::const_iterator i
- = access_points.begin();
- i != access_points.end(); ++i) {
+ for (const auto& access_point : access_points) {
AccessPointData ap_data;
- ap_data.mac_address = base::ASCIIToUTF16(i->mac_address);
- ap_data.radio_signal_strength = i->signal_strength;
- ap_data.channel = i->channel;
- ap_data.signal_to_noise = i->signal_to_noise;
- ap_data.ssid = base::UTF8ToUTF16(i->ssid);
+ ap_data.mac_address = base::ASCIIToUTF16(access_point.mac_address);
+ ap_data.radio_signal_strength = access_point.signal_strength;
+ ap_data.channel = access_point.channel;
+ ap_data.signal_to_noise = access_point.signal_to_noise;
+ ap_data.ssid = base::UTF8ToUTF16(access_point.ssid);
result->insert(ap_data);
}
// If the age is significantly longer than our long polling time, assume the
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_chromeos.h b/chromium/content/browser/geolocation/wifi_data_provider_chromeos.h
index e901f0131f8..c5055dc6d49 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_chromeos.h
+++ b/chromium/content/browser/geolocation/wifi_data_provider_chromeos.h
@@ -7,6 +7,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "content/browser/geolocation/wifi_data_provider.h"
#include "content/browser/geolocation/wifi_polling_policy.h"
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 a5d1744ba00..64bce2732f6 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_chromeos_unittest.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider_chromeos_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
@@ -10,6 +10,7 @@
#include "chromeos/dbus/shill_manager_client.h"
#include "chromeos/network/geolocation_handler.h"
#include "content/browser/geolocation/wifi_data_provider_chromeos.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
@@ -27,7 +28,7 @@ class GeolocationChromeOsWifiDataProviderTest : public testing::Test {
chromeos::DBusThreadManager::Get()->GetShillManagerClient();
manager_test_ = manager_client_->GetTestInterface();
provider_ = new WifiDataProviderChromeOs();
- message_loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
void TearDown() override {
@@ -58,10 +59,10 @@ class GeolocationChromeOsWifiDataProviderTest : public testing::Test {
manager_test_->AddGeoNetwork(shill::kTypeWifi, properties);
}
}
- message_loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
}
- base::MessageLoopForUI message_loop_;
+ TestBrowserThreadBundle thread_bundle_;
scoped_refptr<WifiDataProviderChromeOs> provider_;
chromeos::ShillManagerClient* manager_client_;
chromeos::ShillManagerClient::TestInterface* manager_test_;
@@ -69,17 +70,17 @@ class GeolocationChromeOsWifiDataProviderTest : public testing::Test {
};
TEST_F(GeolocationChromeOsWifiDataProviderTest, NoAccessPoints) {
- message_loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Initial call to GetAccessPointData requests data and will return false.
EXPECT_FALSE(GetAccessPointData());
- message_loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
// Additional call to GetAccessPointData also returns false with no devices.
EXPECT_FALSE(GetAccessPointData());
EXPECT_EQ(0u, ap_data_.size());
}
TEST_F(GeolocationChromeOsWifiDataProviderTest, GetOneAccessPoint) {
- message_loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(GetAccessPointData());
AddAccessPoints(1, 1);
@@ -90,7 +91,7 @@ TEST_F(GeolocationChromeOsWifiDataProviderTest, GetOneAccessPoint) {
}
TEST_F(GeolocationChromeOsWifiDataProviderTest, GetManyAccessPoints) {
- message_loop_.RunUntilIdle();
+ base::RunLoop().RunUntilIdle();
EXPECT_FALSE(GetAccessPointData());
AddAccessPoints(3, 4);
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_common.cc b/chromium/content/browser/geolocation/wifi_data_provider_common.cc
index 4406680c215..572455a6c4f 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_common.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider_common.cc
@@ -82,7 +82,7 @@ void WifiDataProviderCommon::DoWifiScanTask() {
}
void WifiDataProviderCommon::ScheduleNextScan(int interval) {
- client_loop()->task_runner()->PostDelayedTask(
+ client_task_runner()->PostDelayedTask(
FROM_HERE, base::Bind(&WifiDataProviderCommon::DoWifiScanTask,
weak_factory_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(interval));
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 b6521703872..8acf93a9d04 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_common_unittest.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider_common_unittest.cc
@@ -2,16 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <vector>
-
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_util.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
-#include "build/build_config.h"
+#include "base/thread_task_runner_handle.h"
#include "content/browser/geolocation/wifi_data_provider_common.h"
#include "content/browser/geolocation/wifi_data_provider_manager.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -60,25 +60,6 @@ class MockPollingPolicy : public WifiPollingPolicy {
virtual void UpdatePollingInterval(bool) {}
};
-// Stops the specified (nested) message loop when the callback is called.
-class MessageLoopQuitter {
- public:
- explicit MessageLoopQuitter(base::MessageLoop* message_loop)
- : message_loop_to_quit_(message_loop),
- callback_(base::Bind(&MessageLoopQuitter::OnWifiDataUpdate,
- base::Unretained(this))) {
- CHECK(message_loop_to_quit_ != NULL);
- }
-
- void OnWifiDataUpdate() {
- // Provider should call back on client's thread.
- EXPECT_EQ(base::MessageLoop::current(), message_loop_to_quit_);
- message_loop_to_quit_->QuitNow();
- }
- base::MessageLoop* message_loop_to_quit_;
- WifiDataProviderManager::WifiDataUpdateCallback callback_;
-};
-
class WifiDataProviderCommonWithMock : public WifiDataProviderCommon {
public:
WifiDataProviderCommonWithMock()
@@ -112,24 +93,40 @@ WifiDataProvider* CreateWifiDataProviderCommonWithMock() {
class GeolocationWifiDataProviderCommonTest : public testing::Test {
public:
GeolocationWifiDataProviderCommonTest()
- : loop_quitter_(&main_message_loop_) {
- }
+ : main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+ wifi_data_callback_(
+ base::Bind(&GeolocationWifiDataProviderCommonTest::OnWifiDataUpdate,
+ base::Unretained(this))) {}
void SetUp() override {
provider_ = new WifiDataProviderCommonWithMock;
wlan_api_ = provider_->new_wlan_api_.get();
polling_policy_ = provider_->new_polling_policy_.get();
- provider_->AddCallback(&loop_quitter_.callback_);
+ provider_->AddCallback(&wifi_data_callback_);
}
+
void TearDown() override {
- provider_->RemoveCallback(&loop_quitter_.callback_);
+ provider_->RemoveCallback(&wifi_data_callback_);
provider_->StopDataProvider();
provider_ = NULL;
}
+ void OnWifiDataUpdate() {
+ // Callbacks must run on the originating thread.
+ EXPECT_TRUE(main_task_runner_->BelongsToCurrentThread());
+ run_loop_->Quit();
+ }
+
+ void RunLoop() {
+ run_loop_.reset(new base::RunLoop());
+ run_loop_->Run();
+ }
+
protected:
- base::MessageLoop main_message_loop_;
- MessageLoopQuitter loop_quitter_;
+ TestBrowserThreadBundle thread_bundle_;
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+ scoped_ptr<base::RunLoop> run_loop_;
+ WifiDataProviderManager::WifiDataUpdateCallback wifi_data_callback_;
scoped_refptr<WifiDataProviderCommonWithMock> provider_;
MockWlanApi* wlan_api_;
MockPollingPolicy* polling_policy_;
@@ -137,7 +134,7 @@ class GeolocationWifiDataProviderCommonTest : public testing::Test {
TEST_F(GeolocationWifiDataProviderCommonTest, CreateDestroy) {
// Test fixture members were SetUp correctly.
- EXPECT_EQ(&main_message_loop_, base::MessageLoop::current());
+ EXPECT_TRUE(main_task_runner_->BelongsToCurrentThread());
EXPECT_TRUE(NULL != provider_.get());
EXPECT_TRUE(NULL != wlan_api_);
}
@@ -148,20 +145,20 @@ TEST_F(GeolocationWifiDataProviderCommonTest, RunNormal) {
EXPECT_CALL(*polling_policy_, PollingInterval())
.Times(AtLeast(1));
provider_->StartDataProvider();
- main_message_loop_.Run();
+ RunLoop();
SUCCEED();
}
-TEST_F(GeolocationWifiDataProviderCommonTest, NoWifi){
+TEST_F(GeolocationWifiDataProviderCommonTest, NoWifi) {
EXPECT_CALL(*polling_policy_, NoWifiInterval())
.Times(AtLeast(1));
EXPECT_CALL(*wlan_api_, GetAccessPointData(_))
.WillRepeatedly(Return(false));
provider_->StartDataProvider();
- main_message_loop_.Run();
+ RunLoop();
}
-TEST_F(GeolocationWifiDataProviderCommonTest, IntermittentWifi){
+TEST_F(GeolocationWifiDataProviderCommonTest, IntermittentWifi) {
EXPECT_CALL(*polling_policy_, PollingInterval())
.Times(AtLeast(1));
EXPECT_CALL(*polling_policy_, NoWifiInterval())
@@ -180,8 +177,8 @@ TEST_F(GeolocationWifiDataProviderCommonTest, IntermittentWifi){
wlan_api_->data_out_.insert(single_access_point);
provider_->StartDataProvider();
- main_message_loop_.Run();
- main_message_loop_.Run();
+ RunLoop();
+ RunLoop();
}
#if defined(OS_MACOSX)
@@ -195,7 +192,7 @@ TEST_F(GeolocationWifiDataProviderCommonTest, MAYBE_DoAnEmptyScan) {
EXPECT_CALL(*polling_policy_, PollingInterval())
.Times(AtLeast(1));
provider_->StartDataProvider();
- main_message_loop_.Run();
+ RunLoop();
EXPECT_EQ(wlan_api_->calls_, 1);
WifiData data;
EXPECT_TRUE(provider_->GetData(&data));
@@ -221,7 +218,7 @@ TEST_F(GeolocationWifiDataProviderCommonTest, MAYBE_DoScanWithResults) {
wlan_api_->data_out_.insert(single_access_point);
provider_->StartDataProvider();
- main_message_loop_.Run();
+ RunLoop();
EXPECT_EQ(wlan_api_->calls_, 1);
WifiData data;
EXPECT_TRUE(provider_->GetData(&data));
@@ -230,12 +227,11 @@ TEST_F(GeolocationWifiDataProviderCommonTest, MAYBE_DoScanWithResults) {
}
TEST_F(GeolocationWifiDataProviderCommonTest, RegisterUnregister) {
- MessageLoopQuitter loop_quitter(&main_message_loop_);
WifiDataProviderManager::SetFactoryForTesting(
CreateWifiDataProviderCommonWithMock);
- WifiDataProviderManager::Register(&loop_quitter.callback_);
- main_message_loop_.Run();
- WifiDataProviderManager::Unregister(&loop_quitter.callback_);
+ WifiDataProviderManager::Register(&wifi_data_callback_);
+ RunLoop();
+ WifiDataProviderManager::Unregister(&wifi_data_callback_);
WifiDataProviderManager::ResetFactoryForTesting();
}
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_corewlan_mac.mm b/chromium/content/browser/geolocation/wifi_data_provider_corewlan_mac.mm
index 036c7610b43..bbe099f3d2f 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_corewlan_mac.mm
+++ b/chromium/content/browser/geolocation/wifi_data_provider_corewlan_mac.mm
@@ -39,6 +39,7 @@
@property (nonatomic, readonly) NSNumber* phyMode;
@property (nonatomic, readonly) NSNumber* channel;
@property (nonatomic, readonly) NSNumber* rssi;
+@property (nonatomic, readonly) NSInteger rssiValue;
@property (nonatomic, readonly) NSNumber* noise;
@property (nonatomic, readonly) NSData* ieData;
@property (nonatomic, readonly) BOOL isIBSS;
@@ -158,7 +159,7 @@ bool CoreWlanApi::GetAccessPointData(WifiData::AccessPointDataSet* data) {
continue; // crbug.com/545501
access_point_data.mac_address =
MacAddressAsString16(static_cast<const uint8_t*>([mac bytes]));
- access_point_data.radio_signal_strength = [[network rssi] intValue];
+ access_point_data.radio_signal_strength = [network rssiValue];
access_point_data.channel = [[network channel] intValue];
access_point_data.signal_to_noise =
access_point_data.radio_signal_strength - [[network noise] intValue];
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_linux_unittest.cc b/chromium/content/browser/geolocation/wifi_data_provider_linux_unittest.cc
index 3ca35d114b4..7f36a2c25a4 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_linux_unittest.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider_linux_unittest.cc
@@ -9,8 +9,8 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "dbus/message.h"
#include "dbus/mock_bus.h"
#include "dbus/mock_object_proxy.h"
@@ -105,10 +105,9 @@ class GeolocationWifiDataProviderLinuxTest : public testing::Test {
}
protected:
- // DeviceDataProviderImplBase, a super class of WifiDataProviderLinux,
- // requires a message loop to be present. message_loop_ is defined here,
- // as it should outlive wifi_provider_linux_.
- base::MessageLoop message_loop_;
+ // WifiDataProvider requires a task runner to be present. The |thread_bundle_|
+ // is defined here, as it should outlive |wifi_provider_linux_|.
+ TestBrowserThreadBundle thread_bundle_;
scoped_refptr<dbus::MockBus> mock_bus_;
scoped_refptr<dbus::MockObjectProxy> mock_network_manager_proxy_;
scoped_refptr<dbus::MockObjectProxy> mock_access_point_proxy_;
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_manager.h b/chromium/content/browser/geolocation/wifi_data_provider_manager.h
index bb2af81e167..652cf643710 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_manager.h
+++ b/chromium/content/browser/geolocation/wifi_data_provider_manager.h
@@ -21,7 +21,6 @@
#include "base/callback.h"
#include "base/macros.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"
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_win.cc b/chromium/content/browser/geolocation/wifi_data_provider_win.cc
index 4d950ec12fc..7d9db588cd1 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_win.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider_win.cc
@@ -27,6 +27,7 @@
#include <winioctl.h>
#include <wlanapi.h>
+#include "base/memory/free_deleter.h"
#include "base/metrics/histogram.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/windows_version.h"
diff --git a/chromium/content/browser/geolocation/wifi_data_provider_win_unittest.cc b/chromium/content/browser/geolocation/wifi_data_provider_win_unittest.cc
index cb3c21ce3ec..d256a4a3fcb 100644
--- a/chromium/content/browser/geolocation/wifi_data_provider_win_unittest.cc
+++ b/chromium/content/browser/geolocation/wifi_data_provider_win_unittest.cc
@@ -6,13 +6,14 @@
// WifiDataProviderCommon and covered by it's unit tests.
#include "content/browser/geolocation/wifi_data_provider_win.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
TEST(GeolocationWifiDataProviderWinTest, CreateDestroy) {
- // WifiDataProviderCommon requires the client to have a message loop.
- base::MessageLoop dummy_loop;
+ // WifiDataProvider requires a task runner to be present.
+ TestBrowserThreadBundle thread_bundle;
scoped_refptr<WifiDataProviderWin> instance(new WifiDataProviderWin);
instance = NULL;
SUCCEED();
diff --git a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc
index f432608fb27..61082162286 100644
--- a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc
+++ b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.cc
@@ -18,15 +18,14 @@
#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_process_host.h"
-#include "content/browser/gpu/gpu_surface_tracker.h"
#include "content/browser/gpu/shader_disk_cache.h"
#include "content/common/child_process_host_impl.h"
-#include "content/common/gpu/gpu_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/gpu_data_manager.h"
#include "content/public/common/content_client.h"
#include "gpu/command_buffer/service/gpu_switches.h"
+#include "gpu/ipc/common/gpu_messages.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/message_filter.h"
@@ -34,19 +33,6 @@ namespace content {
BrowserGpuChannelHostFactory* BrowserGpuChannelHostFactory::instance_ = NULL;
-struct BrowserGpuChannelHostFactory::CreateRequest {
- CreateRequest(int32_t route_id)
- : event(true, false),
- gpu_host_id(0),
- route_id(route_id),
- result(CREATE_COMMAND_BUFFER_FAILED) {}
- ~CreateRequest() {}
- base::WaitableEvent event;
- int gpu_host_id;
- int32_t route_id;
- CreateCommandBufferResult result;
-};
-
class BrowserGpuChannelHostFactory::EstablishRequest
: public base::RefCountedThreadSafe<EstablishRequest> {
public:
@@ -150,12 +136,11 @@ void BrowserGpuChannelHostFactory::EstablishRequest::EstablishOnIO() {
}
bool preempts = true;
- bool preempted = false;
- bool allow_future_sync_points = true;
+ bool allow_view_command_buffers = true;
bool allow_real_time_streams = true;
host->EstablishGpuChannel(
- gpu_client_id_, gpu_client_tracing_id_, preempts, preempted,
- allow_future_sync_points, allow_real_time_streams,
+ gpu_client_id_, gpu_client_tracing_id_, preempts,
+ allow_view_command_buffers, allow_real_time_streams,
base::Bind(
&BrowserGpuChannelHostFactory::EstablishRequest::OnEstablishedOnIO,
this));
@@ -291,65 +276,11 @@ BrowserGpuChannelHostFactory::AllocateSharedMemory(size_t size) {
return shm;
}
-void BrowserGpuChannelHostFactory::CreateViewCommandBufferOnIO(
- CreateRequest* request,
- int32_t surface_id,
- const GPUCreateCommandBufferConfig& init_params) {
- GpuProcessHost* host = GpuProcessHost::FromID(gpu_host_id_);
- if (!host) {
- request->event.Signal();
- return;
- }
-
- gfx::GLSurfaceHandle surface =
- GpuSurfaceTracker::Get()->GetSurfaceHandle(surface_id);
-
- host->CreateViewCommandBuffer(
- surface,
- gpu_client_id_,
- init_params,
- request->route_id,
- base::Bind(&BrowserGpuChannelHostFactory::CommandBufferCreatedOnIO,
- request));
-}
-
-// static
-void BrowserGpuChannelHostFactory::CommandBufferCreatedOnIO(
- CreateRequest* request, CreateCommandBufferResult result) {
- request->result = result;
- request->event.Signal();
-}
-
-CreateCommandBufferResult BrowserGpuChannelHostFactory::CreateViewCommandBuffer(
- int32_t surface_id,
- const GPUCreateCommandBufferConfig& init_params,
- int32_t route_id) {
- CreateRequest request(route_id);
- GetIOThreadTaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(&BrowserGpuChannelHostFactory::CreateViewCommandBufferOnIO,
- base::Unretained(this), &request, surface_id, init_params));
- // TODO(vadimt): Remove ScopedTracker below once crbug.com/125248 is fixed.
- tracked_objects::ScopedTracker tracking_profile(
- FROM_HERE_WITH_EXPLICIT_FUNCTION(
- "125248 BrowserGpuChannelHostFactory::CreateViewCommandBuffer"));
-
- // We're blocking the UI thread, which is generally undesirable.
- // In this case we need to wait for this before we can show any UI /anyway/,
- // so it won't cause additional jank.
- // TODO(piman): Make this asynchronous (http://crbug.com/125248).
- TRACE_EVENT0("browser",
- "BrowserGpuChannelHostFactory::CreateViewCommandBuffer");
- base::ThreadRestrictions::ScopedAllowWait allow_wait;
- request.event.Wait();
- return request.result;
-}
-
// Blocking the UI thread to open a GPU channel is not supported on Android.
// (Opening the initial channel to a child process involves handling a reply
// task on the UI thread first, so we cannot block here.)
#if !defined(OS_ANDROID)
-GpuChannelHost* BrowserGpuChannelHostFactory::EstablishGpuChannelSync(
+gpu::GpuChannelHost* BrowserGpuChannelHostFactory::EstablishGpuChannelSync(
CauseForGpuLaunch cause_for_gpu_launch) {
EstablishGpuChannel(cause_for_gpu_launch, base::Closure());
@@ -386,7 +317,7 @@ void BrowserGpuChannelHostFactory::EstablishGpuChannel(
}
}
-GpuChannelHost* BrowserGpuChannelHostFactory::GetGpuChannel() {
+gpu::GpuChannelHost* BrowserGpuChannelHostFactory::GetGpuChannel() {
if (gpu_channel_.get() && !gpu_channel_->IsLost())
return gpu_channel_.get();
@@ -405,7 +336,7 @@ void BrowserGpuChannelHostFactory::GpuChannelEstablished() {
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"466866 BrowserGpuChannelHostFactory::GpuChannelEstablished1"));
GetContentClient()->SetGpuInfo(pending_request_->gpu_info());
- gpu_channel_ = GpuChannelHost::Create(
+ gpu_channel_ = gpu::GpuChannelHost::Create(
this, gpu_client_id_, pending_request_->gpu_info(),
pending_request_->channel_handle(), shutdown_event_.get(),
gpu_memory_buffer_manager_.get());
diff --git a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.h b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.h
index 530768c44b4..618e1c23d47 100644
--- a/chromium/content/browser/gpu/browser_gpu_channel_host_factory.h
+++ b/chromium/content/browser/gpu/browser_gpu_channel_host_factory.h
@@ -15,36 +15,34 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "build/build_config.h"
-#include "content/common/gpu/client/gpu_channel_host.h"
+#include "content/common/content_export.h"
+#include "content/common/gpu_process_launch_causes.h"
+#include "gpu/ipc/client/gpu_channel_host.h"
#include "ipc/message_filter.h"
namespace content {
class BrowserGpuMemoryBufferManager;
class CONTENT_EXPORT BrowserGpuChannelHostFactory
- : public GpuChannelHostFactory {
+ : public gpu::GpuChannelHostFactory {
public:
static void Initialize(bool establish_gpu_channel);
static void Terminate();
static BrowserGpuChannelHostFactory* instance() { return instance_; }
- // Overridden from GpuChannelHostFactory:
+ // Overridden from gpu::GpuChannelHostFactory:
bool IsMainThread() override;
scoped_refptr<base::SingleThreadTaskRunner> GetIOThreadTaskRunner() override;
scoped_ptr<base::SharedMemory> AllocateSharedMemory(size_t size) override;
- CreateCommandBufferResult CreateViewCommandBuffer(
- int32_t surface_id,
- const GPUCreateCommandBufferConfig& init_params,
- int32_t route_id) override;
int GpuProcessHostId() { return gpu_host_id_; }
#if !defined(OS_ANDROID)
- GpuChannelHost* EstablishGpuChannelSync(
+ gpu::GpuChannelHost* EstablishGpuChannelSync(
CauseForGpuLaunch cause_for_gpu_launch);
#endif
void EstablishGpuChannel(CauseForGpuLaunch cause_for_gpu_launch,
const base::Closure& callback);
- GpuChannelHost* GetGpuChannel();
+ gpu::GpuChannelHost* GetGpuChannel();
int GetGpuChannelId() { return gpu_client_id_; }
// Used to skip GpuChannelHost tests when there can be no GPU process.
@@ -58,12 +56,7 @@ class CONTENT_EXPORT BrowserGpuChannelHostFactory
~BrowserGpuChannelHostFactory() override;
void GpuChannelEstablished();
- void CreateViewCommandBufferOnIO(
- CreateRequest* request,
- int32_t surface_id,
- const GPUCreateCommandBufferConfig& init_params);
- static void CommandBufferCreatedOnIO(CreateRequest* request,
- CreateCommandBufferResult result);
+
static void AddFilterOnIO(int gpu_host_id,
scoped_refptr<IPC::MessageFilter> filter);
static void InitializeShaderDiskCacheOnIO(int gpu_client_id,
@@ -72,7 +65,7 @@ class CONTENT_EXPORT BrowserGpuChannelHostFactory
const int gpu_client_id_;
const uint64_t gpu_client_tracing_id_;
scoped_ptr<base::WaitableEvent> shutdown_event_;
- scoped_refptr<GpuChannelHost> gpu_channel_;
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel_;
scoped_ptr<BrowserGpuMemoryBufferManager> gpu_memory_buffer_manager_;
int gpu_host_id_;
scoped_refptr<EstablishRequest> pending_request_;
diff --git a/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc b/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc
index d9c25c9344b..7eba55f7457 100644
--- a/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc
+++ b/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.cc
@@ -17,27 +17,15 @@
#include "content/browser/gpu/gpu_process_host.h"
#include "content/common/child_process_host_impl.h"
#include "content/common/generic_shared_memory_id_generator.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h"
-#include "content/common/gpu/gpu_memory_buffer_factory.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/ipc/client/gpu_memory_buffer_impl.h"
+#include "gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.h"
+#include "gpu/ipc/common/gpu_memory_buffer_support.h"
#include "ui/gfx/buffer_format_util.h"
#include "ui/gl/gl_switches.h"
-#if defined(OS_MACOSX)
-#include "content/common/gpu/gpu_memory_buffer_factory_io_surface.h"
-#endif
-
-#if defined(OS_ANDROID)
-#include "content/common/gpu/gpu_memory_buffer_factory_surface_texture.h"
-#endif
-
-#if defined(USE_OZONE)
-#include "content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.h"
-#endif
-
namespace content {
namespace {
@@ -69,7 +57,7 @@ void HostCreateGpuMemoryBufferFromHandle(
void GpuMemoryBufferDeleted(
scoped_refptr<base::SingleThreadTaskRunner> destruction_task_runner,
- const GpuMemoryBufferImpl::DestructionCallback& destruction_callback,
+ const gpu::GpuMemoryBufferImpl::DestructionCallback& destruction_callback,
const gpu::SyncToken& sync_token) {
destruction_task_runner->PostTask(
FROM_HERE, base::Bind(destruction_callback, sync_token));
@@ -78,24 +66,13 @@ void GpuMemoryBufferDeleted(
bool IsNativeGpuMemoryBufferFactoryConfigurationSupported(
gfx::BufferFormat format,
gfx::BufferUsage usage) {
- switch (GpuMemoryBufferFactory::GetNativeType()) {
+ switch (gpu::GetNativeGpuMemoryBufferType()) {
case gfx::SHARED_MEMORY_BUFFER:
return false;
-#if defined(OS_MACOSX)
case gfx::IO_SURFACE_BUFFER:
- return GpuMemoryBufferFactoryIOSurface::
- IsGpuMemoryBufferConfigurationSupported(format, usage);
-#endif
-#if defined(OS_ANDROID)
case gfx::SURFACE_TEXTURE_BUFFER:
- return GpuMemoryBufferFactorySurfaceTexture::
- IsGpuMemoryBufferConfigurationSupported(format, usage);
-#endif
-#if defined(USE_OZONE)
case gfx::OZONE_NATIVE_PIXMAP:
- return GpuMemoryBufferFactoryOzoneNativePixmap::
- IsGpuMemoryBufferConfigurationSupported(format, usage);
-#endif
+ return gpu::IsNativeGpuMemoryBufferConfigurationSupported(format, usage);
default:
NOTREACHED();
return false;
@@ -239,7 +216,7 @@ uint32_t BrowserGpuMemoryBufferManager::GetImageTextureTarget(
return GL_TEXTURE_2D;
}
- switch (GpuMemoryBufferFactory::GetNativeType()) {
+ switch (gpu::GetNativeGpuMemoryBufferType()) {
case gfx::SURFACE_TEXTURE_BUFFER:
case gfx::OZONE_NATIVE_PIXMAP:
// GPU memory buffers that are shared with the GL using EGLImages
@@ -262,8 +239,9 @@ uint32_t BrowserGpuMemoryBufferManager::GetImageTextureTarget(
scoped_ptr<gfx::GpuMemoryBuffer>
BrowserGpuMemoryBufferManager::AllocateGpuMemoryBuffer(const gfx::Size& size,
gfx::BufferFormat format,
- gfx::BufferUsage usage) {
- return AllocateGpuMemoryBufferForSurface(size, format, usage, 0);
+ gfx::BufferUsage usage,
+ int32_t surface_id) {
+ return AllocateGpuMemoryBufferForSurface(size, format, usage, surface_id);
}
scoped_ptr<gfx::GpuMemoryBuffer>
@@ -291,16 +269,6 @@ BrowserGpuMemoryBufferManager::CreateGpuMemoryBufferFromHandle(
return std::move(request.result);
}
-scoped_ptr<gfx::GpuMemoryBuffer>
-BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForScanout(
- const gfx::Size& size,
- gfx::BufferFormat format,
- int32_t surface_id) {
- DCHECK_GT(surface_id, 0);
- return AllocateGpuMemoryBufferForSurface(
- size, format, gfx::BufferUsage::SCANOUT, surface_id);
-}
-
void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForChildProcess(
gfx::GpuMemoryBufferId id,
const gfx::Size& size,
@@ -320,8 +288,9 @@ void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForChildProcess(
}
// Early out if we cannot fallback to shared memory buffer.
- if (!GpuMemoryBufferImplSharedMemory::IsUsageSupported(usage) ||
- !GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(size, format)) {
+ if (!gpu::GpuMemoryBufferImplSharedMemory::IsUsageSupported(usage) ||
+ !gpu::GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(size,
+ format)) {
callback.Run(gfx::GpuMemoryBufferHandle());
return;
}
@@ -338,21 +307,21 @@ void BrowserGpuMemoryBufferManager::AllocateGpuMemoryBufferForChildProcess(
return;
}
- callback.Run(GpuMemoryBufferImplSharedMemory::AllocateForChildProcess(
+ callback.Run(gpu::GpuMemoryBufferImplSharedMemory::AllocateForChildProcess(
id, size, format, child_process_handle));
}
gfx::GpuMemoryBuffer*
BrowserGpuMemoryBufferManager::GpuMemoryBufferFromClientBuffer(
ClientBuffer buffer) {
- return GpuMemoryBufferImpl::FromClientBuffer(buffer);
+ return gpu::GpuMemoryBufferImpl::FromClientBuffer(buffer);
}
void BrowserGpuMemoryBufferManager::SetDestructionSyncToken(
gfx::GpuMemoryBuffer* buffer,
const gpu::SyncToken& sync_token) {
- static_cast<GpuMemoryBufferImpl*>(buffer)
- ->set_destruction_sync_token(sync_token);
+ static_cast<gpu::GpuMemoryBufferImpl*>(buffer)->set_destruction_sync_token(
+ sync_token);
}
bool BrowserGpuMemoryBufferManager::OnMemoryDump(
@@ -485,7 +454,7 @@ void BrowserGpuMemoryBufferManager::HandleCreateGpuMemoryBufferOnIO(
return;
}
- DCHECK(GpuMemoryBufferImplSharedMemory::IsUsageSupported(request->usage))
+ DCHECK(gpu::GpuMemoryBufferImplSharedMemory::IsUsageSupported(request->usage))
<< static_cast<int>(request->usage);
BufferMap& buffers = clients_[request->client_id];
@@ -498,7 +467,7 @@ void BrowserGpuMemoryBufferManager::HandleCreateGpuMemoryBufferOnIO(
// Note: Unretained is safe as IO thread is stopped before manager is
// destroyed.
- request->result = GpuMemoryBufferImplSharedMemory::Create(
+ request->result = gpu::GpuMemoryBufferImplSharedMemory::Create(
new_id, request->size, request->format,
base::Bind(
&GpuMemoryBufferDeleted,
@@ -517,7 +486,7 @@ void BrowserGpuMemoryBufferManager::HandleCreateGpuMemoryBufferFromHandleOnIO(
// Use service side allocation for native types.
if (request->handle.type != gfx::SHARED_MEMORY_BUFFER) {
// Early out if service side allocation is not supported.
- if (request->handle.type != GpuMemoryBufferFactory::GetNativeType() ||
+ if (request->handle.type != gpu::GetNativeGpuMemoryBufferType() ||
!IsNativeGpuMemoryBufferConfiguration(request->format,
request->usage)) {
request->event.Signal();
@@ -535,7 +504,7 @@ void BrowserGpuMemoryBufferManager::HandleCreateGpuMemoryBufferFromHandleOnIO(
return;
}
- DCHECK(GpuMemoryBufferImplSharedMemory::IsUsageSupported(request->usage))
+ DCHECK(gpu::GpuMemoryBufferImplSharedMemory::IsUsageSupported(request->usage))
<< static_cast<int>(request->usage);
BufferMap& buffers = clients_[request->client_id];
@@ -554,7 +523,7 @@ void BrowserGpuMemoryBufferManager::HandleCreateGpuMemoryBufferFromHandleOnIO(
// Note: Unretained is safe as IO thread is stopped before manager is
// destroyed.
- request->result = GpuMemoryBufferImplSharedMemory::CreateFromHandle(
+ request->result = gpu::GpuMemoryBufferImplSharedMemory::CreateFromHandle(
handle, request->size, request->format, request->usage,
base::Bind(
&GpuMemoryBufferDeleted,
@@ -577,7 +546,7 @@ void BrowserGpuMemoryBufferManager::HandleGpuMemoryBufferCreatedOnIO(
// Note: Unretained is safe as IO thread is stopped before manager is
// destroyed.
- request->result = GpuMemoryBufferImpl::CreateFromHandle(
+ request->result = gpu::GpuMemoryBufferImpl::CreateFromHandle(
handle, request->size, request->format, request->usage,
base::Bind(
&GpuMemoryBufferDeleted,
diff --git a/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h b/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h
index 0057192b65b..946ccf0e505 100644
--- a/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h
+++ b/chromium/content/browser/gpu/browser_gpu_memory_buffer_manager.h
@@ -12,6 +12,7 @@
#include "base/callback.h"
#include "base/containers/hash_tables.h"
+#include "base/hash.h"
#include "base/macros.h"
#include "base/trace_event/memory_dump_provider.h"
#include "content/common/content_export.h"
@@ -31,7 +32,7 @@ namespace BASE_HASH_NAMESPACE {
template <>
struct hash<content::GpuMemoryBufferConfigurationKey> {
size_t operator()(const content::GpuMemoryBufferConfigurationKey& key) const {
- return base::HashPair(static_cast<int>(key.first),
+ return base::HashInts(static_cast<int>(key.first),
static_cast<int>(key.second));
}
};
@@ -64,7 +65,8 @@ class CONTENT_EXPORT BrowserGpuMemoryBufferManager
scoped_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer(
const gfx::Size& size,
gfx::BufferFormat format,
- gfx::BufferUsage usage) override;
+ gfx::BufferUsage usage,
+ int32_t surface_id) override;
scoped_ptr<gfx::GpuMemoryBuffer> CreateGpuMemoryBufferFromHandle(
const gfx::GpuMemoryBufferHandle& handle,
const gfx::Size& size,
@@ -78,12 +80,6 @@ class CONTENT_EXPORT BrowserGpuMemoryBufferManager
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) override;
- // Virtual for testing.
- virtual scoped_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBufferForScanout(
- const gfx::Size& size,
- gfx::BufferFormat format,
- int32_t surface_id);
-
void AllocateGpuMemoryBufferForChildProcess(
gfx::GpuMemoryBufferId id,
const gfx::Size& size,
diff --git a/chromium/content/browser/gpu/compositor_util.cc b/chromium/content/browser/gpu/compositor_util.cc
index d7b3e40928e..a7960b35b74 100644
--- a/chromium/content/browser/gpu/compositor_util.cc
+++ b/chromium/content/browser/gpu/compositor_util.cc
@@ -34,6 +34,7 @@ const char* kGpuCompositingFeatureName = "gpu_compositing";
const char* kWebGLFeatureName = "webgl";
const char* kRasterizationFeatureName = "rasterization";
const char* kMultipleRasterThreadsFeatureName = "multiple_raster_threads";
+const char* kNativeGpuMemoryBuffersFeatureName = "native_gpu_memory_buffers";
const int kMinRasterThreads = 1;
const int kMaxRasterThreads = 4;
@@ -154,6 +155,14 @@ const GpuFeatureInfo GetGpuFeatureInfo(size_t index, bool* eof) {
"Raster is using a single thread.",
false
},
+ {
+ kNativeGpuMemoryBuffersFeatureName,
+ false,
+ !BrowserGpuMemoryBufferManager::IsNativeGpuMemoryBuffersEnabled(),
+ "Native GpuMemoryBuffers have been disabled, either via about:flags"
+ " or command line.",
+ true
+ },
};
DCHECK(index < arraysize(kGpuFeatureInfo));
*eof = (index == arraysize(kGpuFeatureInfo) - 1);
@@ -162,12 +171,6 @@ const GpuFeatureInfo GetGpuFeatureInfo(size_t index, bool* eof) {
} // namespace
-bool IsPropertyTreeVerificationEnabled() {
- const base::CommandLine& command_line =
- *base::CommandLine::ForCurrentProcess();
- return command_line.HasSwitch(cc::switches::kEnablePropertyTreeVerification);
-}
-
int NumberOfRendererRasterThreads() {
int num_processors = base::SysInfo::NumberOfProcessors();
@@ -216,8 +219,9 @@ bool IsPartialRasterEnabled() {
// Zero copy currently doesn't take advantage of partial raster.
if (IsZeroCopyUploadEnabled())
return false;
+
const auto& command_line = *base::CommandLine::ForCurrentProcess();
- return command_line.HasSwitch(switches::kEnablePartialRaster);
+ return !command_line.HasSwitch(switches::kDisablePartialRaster);
}
bool IsGpuMemoryBufferCompositorResourcesEnabled() {
@@ -236,12 +240,6 @@ bool IsGpuMemoryBufferCompositorResourcesEnabled() {
if (!BrowserGpuMemoryBufferManager::IsNativeGpuMemoryBuffersEnabled())
return false;
- // GPU rasterization does not support GL_TEXTURE_RECTANGLE_ARB, which is
- // required by GpuMemoryBuffers on Mac.
- // http://crbug.com/551072
- if (IsForceGpuRasterizationEnabled() || IsGpuRasterizationEnabled())
- return false;
-
#if defined(OS_MACOSX)
return true;
#else
@@ -277,24 +275,6 @@ bool IsForceGpuRasterizationEnabled() {
return command_line.HasSwitch(switches::kForceGpuRasterization);
}
-bool UseSurfacesEnabled() {
-#if defined(OS_ANDROID)
- return true;
-#endif
- bool enabled = false;
-#if defined(USE_AURA) || defined(OS_MACOSX)
- enabled = true;
-#endif
-
- const base::CommandLine& command_line =
- *base::CommandLine::ForCurrentProcess();
-
- // Flags override.
- enabled |= command_line.HasSwitch(switches::kUseSurfaces);
- enabled &= !command_line.HasSwitch(switches::kDisableSurfaces);
- return enabled;
-}
-
int GpuRasterizationMSAASampleCount() {
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
diff --git a/chromium/content/browser/gpu/compositor_util.h b/chromium/content/browser/gpu/compositor_util.h
index 1dc495a7758..d66071511a1 100644
--- a/chromium/content/browser/gpu/compositor_util.h
+++ b/chromium/content/browser/gpu/compositor_util.h
@@ -13,10 +13,6 @@ namespace content {
// Note: When adding a function here, please make sure the logic is not
// duplicated in the renderer.
-// Returns true if property tree verification is enabled (via flags or platform
-// default).
-CONTENT_EXPORT bool IsPropertyTreeVerificationEnabled();
-
// Returns true if zero-copy uploads is on (via flags, or platform default).
// Only one of one-copy and zero-copy can be enabled at a time.
CONTENT_EXPORT bool IsZeroCopyUploadEnabled();
@@ -40,9 +36,6 @@ CONTENT_EXPORT bool IsForceGpuRasterizationEnabled();
// Returns the number of raster threads to use for compositing.
CONTENT_EXPORT int NumberOfRendererRasterThreads();
-// Returns true if using cc Surfaces is allowed.
-CONTENT_EXPORT bool UseSurfacesEnabled();
-
CONTENT_EXPORT base::DictionaryValue* GetFeatureStatus();
CONTENT_EXPORT base::Value* GetProblems();
CONTENT_EXPORT std::vector<std::string> GetDriverBugWorkarounds();
diff --git a/chromium/content/browser/gpu/gpu_arc_video_service_host.cc b/chromium/content/browser/gpu/gpu_arc_video_service_host.cc
deleted file mode 100644
index 7ba572d64f1..00000000000
--- a/chromium/content/browser/gpu/gpu_arc_video_service_host.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/gpu/gpu_arc_video_service_host.h"
-
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "content/browser/gpu/gpu_process_host.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "content/public/browser/arc_video_host_delegate.h"
-#include "content/public/browser/browser_thread.h"
-#include "ipc/ipc_channel_handle.h"
-#include "ipc/ipc_message_macros.h"
-#include "ipc/ipc_message_utils.h"
-#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
-
-namespace content {
-
-namespace {
-
-void CreateChannelOnIOThread(
- const GpuProcessHost::CreateArcVideoAcceleratorChannelCallback& callback) {
- GpuProcessHost* gpu_process_host =
- GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
- CAUSE_FOR_GPU_LAUNCH_ARCVIDEOACCELERATOR);
- gpu_process_host->CreateArcVideoAcceleratorChannel(callback);
-}
-
-void HandleChannelCreatedReply(
- const arc::VideoHost::OnRequestArcVideoAcceleratorChannelCallback& callback,
- const IPC::ChannelHandle& handle) {
- MojoHandle wrapped_handle;
- MojoResult wrap_result = mojo::embedder::CreatePlatformHandleWrapper(
- mojo::embedder::ScopedPlatformHandle(
- mojo::embedder::PlatformHandle(handle.socket.fd)),
- &wrapped_handle);
- if (wrap_result != MOJO_RESULT_OK) {
- LOG(WARNING) << "Pipe failed to wrap handles. Closing: " << wrap_result;
- callback.Run(mojo::ScopedHandle());
- return;
- }
- callback.Run(mojo::ScopedHandle(mojo::Handle(wrapped_handle)));
-}
-
-} // namespace
-
-scoped_ptr<arc::VideoHostDelegate> CreateArcVideoHostDelegate() {
- return make_scoped_ptr(new GpuArcVideoServiceHost());
-}
-
-GpuArcVideoServiceHost::GpuArcVideoServiceHost()
- : io_task_runner_(content::BrowserThread::GetMessageLoopProxyForThread(
- content::BrowserThread::IO)) {}
-
-GpuArcVideoServiceHost::~GpuArcVideoServiceHost() {
- DCHECK(thread_checker_.CalledOnValidThread());
-}
-
-void GpuArcVideoServiceHost::OnRequestArcVideoAcceleratorChannel(
- const OnRequestArcVideoAcceleratorChannelCallback& callback) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- io_task_runner_->PostTask(
- FROM_HERE, base::Bind(&CreateChannelOnIOThread,
- base::Bind(&HandleChannelCreatedReply, callback)));
-}
-
-void GpuArcVideoServiceHost::OnStopping() {
- GpuProcessHost::SendOnIO(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
- CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH,
- new GpuMsg_ShutdownArcVideoService());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/gpu/gpu_arc_video_service_host.h b/chromium/content/browser/gpu/gpu_arc_video_service_host.h
deleted file mode 100644
index 3a5ca2a1dd3..00000000000
--- a/chromium/content/browser/gpu/gpu_arc_video_service_host.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_GPU_GPU_ARC_VIDEO_SERVICE_HOST_H_
-#define CONTENT_BROWSER_GPU_GPU_ARC_VIDEO_SERVICE_HOST_H_
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/threading/thread_checker.h"
-#include "components/arc/video/video_host_delegate.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}
-
-namespace IPC {
-struct ChannelHandle;
-}
-
-namespace content {
-
-// This class passes requests from arc::VideoInstance to GpuArcVideoService to
-// create a video accelerator channel in GPU process and reply the created
-// channel.
-//
-// Don't be confused two senses of "host" of this class. This class, which
-// implements arc::VideoHost, handles requests from arc::VideoInstance. At the
-// same time, as its name says, this class is the host of corresponding class,
-// GpuArcVideoService, in the GPU process.
-class GpuArcVideoServiceHost : public arc::VideoHostDelegate {
- public:
- GpuArcVideoServiceHost();
- ~GpuArcVideoServiceHost() override;
-
- // arc::VideoHostDelegate implementation.
- void OnStopping() override;
-
- // arc::VideoHost implementation.
- void OnRequestArcVideoAcceleratorChannel(
- const OnRequestArcVideoAcceleratorChannelCallback& callback) override;
-
- private:
- base::ThreadChecker thread_checker_;
-
- // IO task runner, where GpuProcessHost tasks run.
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuArcVideoServiceHost);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_GPU_GPU_ARC_VIDEO_SERVICE_HOST_H_
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl.cc b/chromium/content/browser/gpu/gpu_data_manager_impl.cc
index 2fe3cae3a06..0a820a42142 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl.cc
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl.cc
@@ -5,6 +5,7 @@
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/gpu/gpu_data_manager_impl_private.h"
+#include "gpu/ipc/common/memory_stats.h"
namespace content {
@@ -81,11 +82,6 @@ void GpuDataManagerImpl::RegisterSwiftShaderPath(
private_->RegisterSwiftShaderPath(path);
}
-bool GpuDataManagerImpl::ShouldUseWarp() const {
- base::AutoLock auto_lock(lock_);
- return private_->ShouldUseWarp();
-}
-
void GpuDataManagerImpl::AddObserver(
GpuDataManagerObserver* observer) {
base::AutoLock auto_lock(lock_);
@@ -149,7 +145,7 @@ void GpuDataManagerImpl::UpdateGpuInfo(const gpu::GPUInfo& gpu_info) {
}
void GpuDataManagerImpl::UpdateVideoMemoryUsageStats(
- const GPUVideoMemoryUsageStats& video_memory_usage_stats) {
+ const gpu::VideoMemoryUsageStats& video_memory_usage_stats) {
base::AutoLock auto_lock(lock_);
private_->UpdateVideoMemoryUsageStats(video_memory_usage_stats);
}
@@ -161,15 +157,10 @@ void GpuDataManagerImpl::AppendRendererCommandLine(
}
void GpuDataManagerImpl::AppendGpuCommandLine(
- base::CommandLine* command_line) const {
- base::AutoLock auto_lock(lock_);
- private_->AppendGpuCommandLine(command_line);
-}
-
-void GpuDataManagerImpl::AppendPluginCommandLine(
- base::CommandLine* command_line) const {
+ base::CommandLine* command_line,
+ gpu::GpuPreferences* gpu_preferences) const {
base::AutoLock auto_lock(lock_);
- private_->AppendPluginCommandLine(command_line);
+ private_->AppendGpuCommandLine(command_line, gpu_preferences);
}
void GpuDataManagerImpl::UpdateRendererWebPrefs(
@@ -246,16 +237,6 @@ size_t GpuDataManagerImpl::GetBlacklistedFeatureCount() const {
return private_->GetBlacklistedFeatureCount();
}
-void GpuDataManagerImpl::SetDisplayCount(unsigned int display_count) {
- base::AutoLock auto_lock(lock_);
- private_->SetDisplayCount(display_count);
-}
-
-unsigned int GpuDataManagerImpl::GetDisplayCount() const {
- base::AutoLock auto_lock(lock_);
- return private_->GetDisplayCount();
-}
-
bool GpuDataManagerImpl::UpdateActiveGpu(uint32_t vendor_id,
uint32_t device_id) {
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 c509e3a2e88..7b436f30662 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl.h
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl.h
@@ -21,7 +21,6 @@
#include "base/time/time.h"
#include "base/values.h"
#include "content/public/browser/gpu_data_manager.h"
-#include "content/public/common/gpu_memory_stats.h"
#include "content/public/common/three_d_api_types.h"
#include "gpu/config/gpu_info.h"
@@ -31,6 +30,11 @@ namespace base {
class CommandLine;
}
+namespace gpu {
+struct GpuPreferences;
+struct VideoMemoryUsageStats;
+}
+
namespace content {
class GpuDataManagerImplPrivate;
@@ -74,7 +78,6 @@ class CONTENT_EXPORT GpuDataManagerImpl
void RequestVideoMemoryUsageStatsUpdate() const override;
bool ShouldUseSwiftShader() const override;
void RegisterSwiftShaderPath(const base::FilePath& path) override;
- bool ShouldUseWarp() const override;
// TODO(kbr): the threading model for the GpuDataManagerObservers is
// not well defined, and it's impossible for callers to correctly
// delete observers from anywhere except in one of the observer's
@@ -104,18 +107,18 @@ class CONTENT_EXPORT GpuDataManagerImpl
void UpdateGpuInfo(const gpu::GPUInfo& gpu_info);
void UpdateVideoMemoryUsageStats(
- const GPUVideoMemoryUsageStats& video_memory_usage_stats);
+ const gpu::VideoMemoryUsageStats& video_memory_usage_stats);
// Insert disable-feature switches corresponding to preliminary gpu feature
// flags into the renderer process command line.
void AppendRendererCommandLine(base::CommandLine* command_line) const;
// Insert switches into gpu process command line: kUseGL, etc.
- void AppendGpuCommandLine(base::CommandLine* command_line) const;
-
- // Insert switches into plugin process command line:
- // kDisableCoreAnimationPlugins.
- void AppendPluginCommandLine(base::CommandLine* command_line) const;
+ // If the gpu_preferences isn't a nullptr, the gpu_preferences will be set
+ // for some GPU switches which have been replaced by GpuPreferences, and those
+ // switches will not be append to the command_line anymore.
+ void AppendGpuCommandLine(base::CommandLine* command_line,
+ gpu::GpuPreferences* gpu_preferences) const;
// Update WebPreferences for renderer based on blacklisting decisions.
void UpdateRendererWebPrefs(WebPreferences* prefs) const;
@@ -173,9 +176,6 @@ class CONTENT_EXPORT GpuDataManagerImpl
// Get number of features being blacklisted.
size_t GetBlacklistedFeatureCount() const;
- void SetDisplayCount(unsigned int display_count);
- unsigned int GetDisplayCount() const;
-
// Set the active gpu.
// Return true if it's a different GPU from the previous active one.
bool UpdateActiveGpu(uint32_t vendor_id, uint32_t device_id);
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 9e272012977..496c2ed6f6a 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -11,6 +11,7 @@
#include "base/metrics/histogram.h"
#include "base/metrics/sparse_histogram.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "base/sys_info.h"
#include "base/trace_event/trace_event.h"
@@ -18,13 +19,14 @@
#include "build/build_config.h"
#include "cc/base/switches.h"
#include "content/browser/gpu/gpu_process_host.h"
-#include "content/common/gpu/gpu_messages.h"
+#include "content/common/gpu_host_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/gpu_data_manager_observer.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/web_preferences.h"
+#include "gpu/command_buffer/service/gpu_preferences.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/config/gpu_control_list_jsons.h"
#include "gpu/config/gpu_driver_bug_workaround_type.h"
@@ -32,6 +34,7 @@
#include "gpu/config/gpu_info_collector.h"
#include "gpu/config/gpu_switches.h"
#include "gpu/config/gpu_util.h"
+#include "gpu/ipc/common/memory_stats.h"
#include "ui/base/ui_base_switches.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_switches.h"
@@ -223,16 +226,6 @@ void DisplayReconfigCallback(CGDirectDisplayID display,
reinterpret_cast<GpuDataManagerImpl*>(gpu_data_manager);
DCHECK(manager);
- // Display change.
- bool display_changed = false;
- uint32_t displayCount;
- CGGetActiveDisplayList(0, NULL, &displayCount);
- if (displayCount != manager->GetDisplayCount()) {
- manager->SetDisplayCount(displayCount);
- display_changed = true;
- }
-
- // Gpu change.
bool gpu_changed = false;
if (flags & kCGDisplayAddFlag) {
uint32_t vendor_id, device_id;
@@ -241,7 +234,7 @@ void DisplayReconfigCallback(CGDirectDisplayID display,
}
}
- if (display_changed || gpu_changed)
+ if (gpu_changed)
manager->HandleGpuSwitch();
}
#endif // OS_MACOSX
@@ -281,7 +274,7 @@ bool GpuDataManagerImplPrivate::IsFeatureBlacklisted(int feature) const {
return true;
}
#endif // OS_CHROMEOS
- if (use_swiftshader_ || ShouldUseWarp()) {
+ if (use_swiftshader_) {
// Skia's software rendering is probably more efficient than going through
// software emulation of the GPU, so use that.
if (feature == gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS)
@@ -297,19 +290,11 @@ bool GpuDataManagerImplPrivate::IsDriverBugWorkaroundActive(int feature) const {
}
size_t GpuDataManagerImplPrivate::GetBlacklistedFeatureCount() const {
- if (use_swiftshader_ || ShouldUseWarp())
+ if (use_swiftshader_)
return 1;
return blacklisted_features_.size();
}
-void GpuDataManagerImplPrivate::SetDisplayCount(unsigned int display_count) {
- display_count_ = display_count;
-}
-
-unsigned int GpuDataManagerImplPrivate::GetDisplayCount() const {
- return display_count_;
-}
-
gpu::GPUInfo GpuDataManagerImplPrivate::GetGPUInfo() const {
return gpu_info_;
}
@@ -321,7 +306,7 @@ void GpuDataManagerImplPrivate::GetGpuProcessHandles(
bool GpuDataManagerImplPrivate::GpuAccessAllowed(
std::string* reason) const {
- if (use_swiftshader_ || ShouldUseWarp())
+ if (use_swiftshader_)
return true;
if (!gpu_process_accessible_) {
@@ -373,8 +358,12 @@ bool GpuDataManagerImplPrivate::GpuAccessAllowed(
}
void GpuDataManagerImplPrivate::RequestCompleteGpuInfoIfNeeded() {
- if (complete_gpu_info_already_requested_ || IsCompleteGpuInfoAvailable())
+ if (complete_gpu_info_already_requested_ || IsCompleteGpuInfoAvailable() ||
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kGpuTestingNoCompleteInfoCollection)) {
return;
+ }
+
complete_gpu_info_already_requested_ = true;
GpuProcessHost::SendOnIO(
@@ -404,10 +393,9 @@ bool GpuDataManagerImplPrivate::IsCompleteGpuInfoAvailable() const {
}
void GpuDataManagerImplPrivate::RequestVideoMemoryUsageStatsUpdate() const {
- GpuProcessHost::SendOnIO(
- GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
- CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH,
- new GpuMsg_GetVideoMemoryUsageStats());
+ GpuProcessHost::SendOnIO(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
+ CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH,
+ new GpuMsg_GetVideoMemoryUsageStats());
}
bool GpuDataManagerImplPrivate::ShouldUseSwiftShader() const {
@@ -420,13 +408,6 @@ void GpuDataManagerImplPrivate::RegisterSwiftShaderPath(
EnableSwiftShaderIfNecessary();
}
-bool GpuDataManagerImplPrivate::ShouldUseWarp() const {
- std::string angle_impl_flag =
- base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kUseANGLE);
- return use_warp_ || angle_impl_flag == gfx::kANGLEImplementationWARPName;
-}
-
void GpuDataManagerImplPrivate::AddObserver(GpuDataManagerObserver* observer) {
GpuDataManagerImpl::UnlockedSession session(owner_);
observer_list_->AddObserver(observer);
@@ -458,10 +439,9 @@ void GpuDataManagerImplPrivate::UnblockDomainFrom3DAPIs(const GURL& url) {
}
void GpuDataManagerImplPrivate::DisableGpuWatchdog() {
- GpuProcessHost::SendOnIO(
- GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
- CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH,
- new GpuMsg_DisableWatchdog);
+ GpuProcessHost::SendOnIO(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
+ CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH,
+ new GpuMsg_DisableWatchdog);
}
void GpuDataManagerImplPrivate::SetGLStrings(const std::string& gl_vendor,
@@ -470,6 +450,13 @@ void GpuDataManagerImplPrivate::SetGLStrings(const std::string& gl_vendor,
if (gl_vendor.empty() && gl_renderer.empty() && gl_version.empty())
return;
+ if (!is_initialized_) {
+ post_init_tasks_.push_back(
+ base::Bind(&GpuDataManagerImplPrivate::SetGLStrings,
+ base::Unretained(this), gl_vendor, gl_renderer, gl_version));
+ return;
+ }
+
// If GPUInfo already got GL strings, do nothing. This is for the rare
// situation where GPU process collected GL strings before this call.
if (!gpu_info_.gl_vendor.empty() ||
@@ -509,8 +496,10 @@ void GpuDataManagerImplPrivate::Initialize() {
}
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(switches::kSkipGpuDataLoading))
+ if (command_line->HasSwitch(switches::kSkipGpuDataLoading)) {
+ RunPostInitTasks();
return;
+ }
gpu::GPUInfo gpu_info;
if (command_line->GetSwitchValueASCII(
@@ -530,6 +519,18 @@ void GpuDataManagerImplPrivate::Initialize() {
TRACE_EVENT0("startup",
"GpuDataManagerImpl::Initialize:CollectBasicGraphicsInfo");
gpu::CollectBasicGraphicsInfo(&gpu_info);
+
+ if (command_line->HasSwitch(switches::kGpuTestingVendorId) &&
+ command_line->HasSwitch(switches::kGpuTestingDeviceId)) {
+ base::HexStringToUInt(
+ command_line->GetSwitchValueASCII(switches::kGpuTestingVendorId),
+ &gpu_info.gpu.vendor_id);
+ base::HexStringToUInt(
+ command_line->GetSwitchValueASCII(switches::kGpuTestingDeviceId),
+ &gpu_info.gpu.device_id);
+ gpu_info.gpu.active = true;
+ gpu_info.secondary_gpus.clear();
+ }
}
#if defined(ARCH_CPU_X86_FAMILY)
if (!gpu_info.gpu.vendor_id || !gpu_info.gpu.device_id) {
@@ -556,16 +557,24 @@ void GpuDataManagerImplPrivate::Initialize() {
if (command_line->HasSwitch(switches::kSingleProcess) ||
command_line->HasSwitch(switches::kInProcessGPU)) {
command_line->AppendSwitch(switches::kDisableGpuWatchdog);
- AppendGpuCommandLine(command_line);
+ AppendGpuCommandLine(command_line, nullptr);
}
}
void GpuDataManagerImplPrivate::UpdateGpuInfoHelper() {
GetContentClient()->SetGpuInfo(gpu_info_);
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
+
+ std::string os_version;
+ if (command_line->HasSwitch(switches::kGpuTestingOsVersion))
+ os_version =
+ command_line->GetSwitchValueASCII(switches::kGpuTestingOsVersion);
+
if (gpu_blacklist_) {
std::set<int> features = gpu_blacklist_->MakeDecision(
- gpu::GpuControlList::kOsAny, std::string(), gpu_info_);
+ gpu::GpuControlList::kOsAny, os_version, gpu_info_);
if (update_histograms_)
UpdateStats(gpu_info_, gpu_blacklist_.get(), features);
@@ -573,13 +582,11 @@ void GpuDataManagerImplPrivate::UpdateGpuInfoHelper() {
}
if (gpu_driver_bug_list_) {
gpu_driver_bugs_ = gpu_driver_bug_list_->MakeDecision(
- gpu::GpuControlList::kOsAny, std::string(), gpu_info_);
+ gpu::GpuControlList::kOsAny, os_version, gpu_info_);
std::set<std::string> disabled_ext_set;
// Merge disabled extensions from the command line with gpu driver bug list.
- const base::CommandLine* command_line =
- base::CommandLine::ForCurrentProcess();
if (command_line) {
const std::vector<std::string>& disabled_command_line_exts =
base::SplitString(
@@ -606,7 +613,7 @@ void GpuDataManagerImplPrivate::UpdateGpuInfoHelper() {
void GpuDataManagerImplPrivate::UpdateGpuInfo(const gpu::GPUInfo& gpu_info) {
// No further update of gpu_info if falling back to SwiftShader.
- if (use_swiftshader_ || ShouldUseWarp())
+ if (use_swiftshader_)
return;
bool was_info_available = IsCompleteGpuInfoAvailable();
@@ -622,7 +629,7 @@ void GpuDataManagerImplPrivate::UpdateGpuInfo(const gpu::GPUInfo& gpu_info) {
}
void GpuDataManagerImplPrivate::UpdateVideoMemoryUsageStats(
- const GPUVideoMemoryUsageStats& video_memory_usage_stats) {
+ const gpu::VideoMemoryUsageStats& video_memory_usage_stats) {
GpuDataManagerImpl::UnlockedSession session(owner_);
observer_list_->Notify(FROM_HERE,
&GpuDataManagerObserver::OnVideoMemoryUsageStatsUpdate,
@@ -648,7 +655,8 @@ void GpuDataManagerImplPrivate::AppendRendererCommandLine(
}
void GpuDataManagerImplPrivate::AppendGpuCommandLine(
- base::CommandLine* command_line) const {
+ base::CommandLine* command_line,
+ gpu::GpuPreferences* gpu_preferences) const {
DCHECK(command_line);
std::string use_gl =
@@ -656,6 +664,9 @@ void GpuDataManagerImplPrivate::AppendGpuCommandLine(
switches::kUseGL);
if (gpu_driver_bugs_.find(gpu::DISABLE_D3D11) != gpu_driver_bugs_.end())
command_line->AppendSwitch(switches::kDisableD3D11);
+ if (gpu_driver_bugs_.find(gpu::DISABLE_DIRECT_COMPOSITION) !=
+ gpu_driver_bugs_.end())
+ command_line->AppendSwitch(switches::kDisableDirectComposition);
if (use_swiftshader_) {
command_line->AppendSwitchASCII(switches::kUseGL, "swiftshader");
} else if ((IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL) ||
@@ -689,12 +700,20 @@ void GpuDataManagerImplPrivate::AppendGpuCommandLine(
}
if (ShouldDisableAcceleratedVideoDecode(command_line)) {
- command_line->AppendSwitch(switches::kDisableAcceleratedVideoDecode);
+ if (gpu_preferences) {
+ gpu_preferences->disable_accelerated_video_decode = true;
+ } else {
+ command_line->AppendSwitch(switches::kDisableAcceleratedVideoDecode);
+ }
}
#if defined(ENABLE_WEBRTC)
if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_VIDEO_ENCODE) &&
!command_line->HasSwitch(switches::kDisableWebRtcHWEncoding)) {
- command_line->AppendSwitch(switches::kDisableWebRtcHWEncoding);
+ if (gpu_preferences) {
+ gpu_preferences->disable_web_rtc_hw_encoding = true;
+ } else {
+ command_line->AppendSwitch(switches::kDisableWebRtcHWEncoding);
+ }
}
#endif
@@ -710,28 +729,6 @@ void GpuDataManagerImplPrivate::AppendGpuCommandLine(
gpu_info_.driver_vendor);
command_line->AppendSwitchASCII(switches::kGpuDriverVersion,
gpu_info_.driver_version);
-
- if (ShouldUseWarp() && !command_line->HasSwitch(switches::kUseANGLE)) {
- command_line->AppendSwitchASCII(switches::kUseANGLE,
- gfx::kANGLEImplementationWARPName);
- }
-}
-
-void GpuDataManagerImplPrivate::AppendPluginCommandLine(
- base::CommandLine* command_line) const {
- DCHECK(command_line);
-
-#if defined(OS_MACOSX)
- // TODO(jbauman): Add proper blacklist support for core animation plugins so
- // special-casing this video card won't be necessary. See
- // http://crbug.com/134015
- if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING)) {
- if (!command_line->HasSwitch(
- switches::kDisableCoreAnimationPlugins))
- command_line->AppendSwitch(
- switches::kDisableCoreAnimationPlugins);
- }
-#endif
}
void GpuDataManagerImplPrivate::UpdateRendererWebPrefs(
@@ -752,16 +749,6 @@ void GpuDataManagerImplPrivate::UpdateRendererWebPrefs(
prefs->flash_stage3d_baseline_enabled = false;
if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS))
prefs->accelerated_2d_canvas_enabled = false;
- // TODO(senorblanco): The renderer shouldn't have an extra setting
- // for this, but should rely on extension availability.
- // Note that |gl_multisampling_enabled| only affects the decoder's
- // default framebuffer allocation, which does not support
- // multisampled_render_to_texture, only msaa with explicit resolve.
- if (IsDriverBugWorkaroundActive(
- gpu::DISABLE_CHROMIUM_FRAMEBUFFER_MULTISAMPLE) ||
- (IsDriverBugWorkaroundActive(gpu::DISABLE_MULTIMONITOR_MULTISAMPLING) &&
- display_count_ > 1))
- prefs->gl_multisampling_enabled = false;
#if defined(USE_AURA)
if (!CanUseGpuBrowserCompositor()) {
@@ -782,12 +769,18 @@ void GpuDataManagerImplPrivate::UpdateRendererWebPrefs(
}
void GpuDataManagerImplPrivate::DisableHardwareAcceleration() {
+ if (!is_initialized_) {
+ post_init_tasks_.push_back(
+ base::Bind(&GpuDataManagerImplPrivate::DisableHardwareAcceleration,
+ base::Unretained(this)));
+ return;
+ }
+
card_blacklisted_ = true;
for (int i = 0; i < gpu::NUMBER_OF_GPU_FEATURE_TYPES; ++i)
blacklisted_features_.insert(i);
- EnableWarpIfNecessary();
EnableSwiftShaderIfNecessary();
NotifyGpuInfoUpdate();
}
@@ -867,10 +860,9 @@ void GpuDataManagerImplPrivate::HandleGpuSwitch() {
// Notify observers in the browser process.
ui::GpuSwitchingManager::GetInstance()->NotifyGpuSwitched();
// Pass the notification to the GPU process to notify observers there.
- GpuProcessHost::SendOnIO(
- GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
- CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH,
- new GpuMsg_GpuSwitched);
+ GpuProcessHost::SendOnIO(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
+ CAUSE_FOR_GPU_LAUNCH_NO_LAUNCH,
+ new GpuMsg_GpuSwitched);
}
bool GpuDataManagerImplPrivate::UpdateActiveGpu(uint32_t vendor_id,
@@ -905,8 +897,6 @@ bool GpuDataManagerImplPrivate::CanUseGpuBrowserCompositor() const {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableGpuCompositing))
return false;
- if (ShouldUseWarp())
- return true;
if (ShouldUseSwiftShader())
return false;
if (IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_GPU_COMPOSITING))
@@ -932,22 +922,8 @@ bool GpuDataManagerImplPrivate::ShouldDisableAcceleratedVideoDecode(
if (group_name == "Disabled")
return true;
- // Accelerated decode is never available with --disable-gpu. It is also
- // currently non-functional with --single-process and --in-process-gpu, but
- // these should be fixable. We set the --disable-accelerated-video-decode flag
- // in these cases so that the renderer can be aware. (Which is important on
- // Android where there is no fallback once WMPI is selected.)
- //
- // TODO(sandersd): Enable support for accelerated decode with
- // --in-process-gpu, at least on Android (necessary to support WebView).
- // http://crbug.com/574935.
- if (command_line->HasSwitch(switches::kDisableGpu) ||
- command_line->HasSwitch(switches::kSingleProcess) ||
- command_line->HasSwitch(switches::kInProcessGPU)) {
- return true;
- }
-
- return false;
+ // Accelerated decode is never available with --disable-gpu.
+ return command_line->HasSwitch(switches::kDisableGpu);
}
void GpuDataManagerImplPrivate::GetDisabledExtensions(
@@ -990,19 +966,17 @@ GpuDataManagerImplPrivate* GpuDataManagerImplPrivate::Create(
return new GpuDataManagerImplPrivate(owner);
}
-GpuDataManagerImplPrivate::GpuDataManagerImplPrivate(
- GpuDataManagerImpl* owner)
+GpuDataManagerImplPrivate::GpuDataManagerImplPrivate(GpuDataManagerImpl* owner)
: complete_gpu_info_already_requested_(false),
observer_list_(new GpuDataManagerObserverList),
use_swiftshader_(false),
- use_warp_(false),
card_blacklisted_(false),
update_histograms_(true),
window_count_(0),
domain_blocking_enabled_(true),
owner_(owner),
- display_count_(0),
gpu_process_accessible_(true),
+ is_initialized_(false),
finalized_(false) {
DCHECK(owner_);
const base::CommandLine* command_line =
@@ -1014,7 +988,6 @@ GpuDataManagerImplPrivate::GpuDataManagerImplPrivate(
DisableHardwareAcceleration();
#if defined(OS_MACOSX)
- CGGetActiveDisplayList (0, NULL, &display_count_);
CGDisplayRegisterReconfigurationCallback(DisplayReconfigCallback, owner_);
#endif // OS_MACOSX
@@ -1059,6 +1032,17 @@ void GpuDataManagerImplPrivate::InitializeImpl(
UpdateGpuInfo(gpu_info);
UpdateGpuSwitchingManager(gpu_info);
UpdatePreliminaryBlacklistedFeatures();
+
+ RunPostInitTasks();
+}
+
+void GpuDataManagerImplPrivate::RunPostInitTasks() {
+ // Set initialized before running callbacks.
+ is_initialized_ = true;
+
+ for (const auto& callback : post_init_tasks_)
+ callback.Run();
+ post_init_tasks_.clear();
}
void GpuDataManagerImplPrivate::UpdateBlacklistedFeatures(
@@ -1072,7 +1056,6 @@ void GpuDataManagerImplPrivate::UpdateBlacklistedFeatures(
blacklisted_features_.insert(gpu::GPU_FEATURE_TYPE_WEBGL);
}
- EnableWarpIfNecessary();
EnableSwiftShaderIfNecessary();
}
@@ -1104,9 +1087,6 @@ void GpuDataManagerImplPrivate::NotifyGpuInfoUpdate() {
}
void GpuDataManagerImplPrivate::EnableSwiftShaderIfNecessary() {
- if (ShouldUseWarp())
- return;
-
if (!GpuAccessAllowed(NULL) ||
blacklisted_features_.count(gpu::GPU_FEATURE_TYPE_WEBGL)) {
if (!swiftshader_path_.empty() &&
@@ -1116,22 +1096,6 @@ void GpuDataManagerImplPrivate::EnableSwiftShaderIfNecessary() {
}
}
-void GpuDataManagerImplPrivate::EnableWarpIfNecessary() {
-#if defined(OS_WIN)
- if (use_warp_)
- return;
- // We should only use WARP if we are unable to use the regular GPU for
- // compositing, and if we in Metro mode.
- use_warp_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kViewerConnect) &&
- !CanUseGpuBrowserCompositor();
-#endif
-}
-
-void GpuDataManagerImplPrivate::ForceWarpModeForTesting() {
- use_warp_ = true;
-}
-
std::string GpuDataManagerImplPrivate::GetDomainFromURL(
const GURL& url) const {
// For the moment, we just use the host, or its IP address, as the
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 b083b601775..229d510dae8 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,11 @@ namespace base {
class CommandLine;
}
+namespace gpu {
+struct GpuPreferences;
+struct VideoMemoryUsageStats;
+}
+
namespace content {
class CONTENT_EXPORT GpuDataManagerImplPrivate {
@@ -49,7 +54,6 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
void RequestVideoMemoryUsageStatsUpdate() const;
bool ShouldUseSwiftShader() const;
void RegisterSwiftShaderPath(const base::FilePath& path);
- bool ShouldUseWarp() const;
void AddObserver(GpuDataManagerObserver* observer);
void RemoveObserver(GpuDataManagerObserver* observer);
void UnblockDomainFrom3DAPIs(const GURL& url);
@@ -67,13 +71,12 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
void UpdateGpuInfo(const gpu::GPUInfo& gpu_info);
void UpdateVideoMemoryUsageStats(
- const GPUVideoMemoryUsageStats& video_memory_usage_stats);
+ const gpu::VideoMemoryUsageStats& video_memory_usage_stats);
void AppendRendererCommandLine(base::CommandLine* command_line) const;
- void AppendGpuCommandLine(base::CommandLine* command_line) const;
-
- void AppendPluginCommandLine(base::CommandLine* command_line) const;
+ void AppendGpuCommandLine(base::CommandLine* command_line,
+ gpu::GpuPreferences* gpu_preferences) const;
void UpdateRendererWebPrefs(WebPreferences* prefs) const;
@@ -116,9 +119,6 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
size_t GetBlacklistedFeatureCount() const;
- void SetDisplayCount(unsigned int display_count);
- unsigned int GetDisplayCount() const;
-
bool UpdateActiveGpu(uint32_t vendor_id, uint32_t device_id);
void OnGpuProcessInitFailure();
@@ -139,8 +139,6 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest,
SwiftShaderRendering2);
FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest,
- WarpEnabledOverridesSwiftShader);
- FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest,
GpuInfoUpdate);
FRIEND_TEST_ALL_PREFIXES(GpuDataManagerImplPrivateTest,
NoGpuInfoUpdateWithSwiftShader);
@@ -197,6 +195,8 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
const std::string& gpu_driver_bug_list_json,
const gpu::GPUInfo& gpu_info);
+ void RunPostInitTasks();
+
void UpdateGpuInfoHelper();
void UpdateBlacklistedFeatures(const std::set<int>& features);
@@ -215,13 +215,6 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
// Try to switch to SwiftShader rendering, if possible and necessary.
void EnableSwiftShaderIfNecessary();
- // Try to switch to WARP rendering if the GPU hardware is not supported or
- // absent, and if we are trying to run in Windows Metro mode.
- void EnableWarpIfNecessary();
-
- // Use only for testing, forces |use_warp_| to true.
- void ForceWarpModeForTesting();
-
// Helper to extract the domain from a given URL.
std::string GetDomainFromURL(const GURL& url) const;
@@ -252,8 +245,6 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
bool use_swiftshader_;
- bool use_warp_;
-
base::FilePath swiftshader_path_;
// Current card force-blacklisted due to GPU crashes, or disabled through
@@ -273,15 +264,20 @@ class CONTENT_EXPORT GpuDataManagerImplPrivate {
GpuDataManagerImpl* owner_;
- unsigned int display_count_;
-
bool gpu_process_accessible_;
+ // True if Initialize() has been completed.
+ bool is_initialized_;
+
// True if all future Initialize calls should be ignored.
bool finalized_;
std::string disabled_extensions_;
+ // If one tries to call a member before initialization then it is defered
+ // until Initialize() is completed.
+ std::vector<base::Closure> post_init_tasks_;
+
DISALLOW_COPY_AND_ASSIGN(GpuDataManagerImplPrivate);
};
diff --git a/chromium/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc b/chromium/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc
index f1865594646..c92f37cbf43 100644
--- a/chromium/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc
+++ b/chromium/content/browser/gpu/gpu_data_manager_impl_private_unittest.cc
@@ -15,6 +15,7 @@
#include "gpu/config/gpu_feature_type.h"
#include "gpu/config/gpu_info.h"
#include "gpu/config/gpu_switches.h"
+#include "gpu/ipc/common/memory_stats.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -43,7 +44,7 @@ class TestObserver : public GpuDataManagerObserver {
void OnGpuInfoUpdate() override { gpu_info_updated_ = true; }
void OnVideoMemoryUsageStatsUpdate(
- const GPUVideoMemoryUsageStats& stats) override {
+ const gpu::VideoMemoryUsageStats& stats) override {
video_memory_usage_stats_updated_ = true;
}
@@ -233,6 +234,7 @@ TEST_F(GpuDataManagerImplPrivateTest, GpuSideExceptions) {
TEST_F(GpuDataManagerImplPrivateTest, DisableHardwareAcceleration) {
ScopedGpuDataManagerImplPrivate manager;
+ manager->InitializeForTesting("", gpu::GPUInfo());
EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
std::string reason;
EXPECT_TRUE(manager->GpuAccessAllowed(&reason));
@@ -248,6 +250,7 @@ TEST_F(GpuDataManagerImplPrivateTest, DisableHardwareAcceleration) {
TEST_F(GpuDataManagerImplPrivateTest, SwiftShaderRendering) {
// Blacklist, then register SwiftShader.
ScopedGpuDataManagerImplPrivate manager;
+ manager->InitializeForTesting("", gpu::GPUInfo());
EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
EXPECT_FALSE(manager->ShouldUseSwiftShader());
@@ -270,6 +273,7 @@ TEST_F(GpuDataManagerImplPrivateTest, SwiftShaderRendering) {
TEST_F(GpuDataManagerImplPrivateTest, SwiftShaderRendering2) {
// Register SwiftShader, then blacklist.
ScopedGpuDataManagerImplPrivate manager;
+ manager->InitializeForTesting("", gpu::GPUInfo());
EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
EXPECT_FALSE(manager->ShouldUseSwiftShader());
@@ -288,22 +292,6 @@ TEST_F(GpuDataManagerImplPrivateTest, SwiftShaderRendering2) {
gpu::GPU_FEATURE_TYPE_ACCELERATED_2D_CANVAS));
}
-TEST_F(GpuDataManagerImplPrivateTest, WarpEnabledOverridesSwiftShader) {
- // If WARP fallback is enabled on Windows 8 it should not allow SwiftShader
- // to be enabled.
-#if defined(OS_WIN)
- if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
- ScopedGpuDataManagerImplPrivate manager;
- manager->ForceWarpModeForTesting();
- const base::FilePath test_path(FILE_PATH_LITERAL("AnyPath"));
- manager->RegisterSwiftShaderPath(test_path);
- manager->DisableHardwareAcceleration();
- EXPECT_TRUE(manager->ShouldUseWarp());
- EXPECT_FALSE(manager->ShouldUseSwiftShader());
- }
-#endif
-}
-
TEST_F(GpuDataManagerImplPrivateTest, GpuInfoUpdate) {
ScopedGpuDataManagerImpl manager;
@@ -327,6 +315,7 @@ TEST_F(GpuDataManagerImplPrivateTest, GpuInfoUpdate) {
TEST_F(GpuDataManagerImplPrivateTest, NoGpuInfoUpdateWithSwiftShader) {
ScopedGpuDataManagerImpl manager;
+ manager->InitializeForTesting("", gpu::GPUInfo());
manager->DisableHardwareAcceleration();
const base::FilePath test_path(FILE_PATH_LITERAL("AnyPath"));
@@ -368,7 +357,7 @@ TEST_F(GpuDataManagerImplPrivateTest, GPUVideoMemoryUsageStatsUpdate) {
}
EXPECT_FALSE(observer.video_memory_usage_stats_updated());
- GPUVideoMemoryUsageStats vram_stats;
+ gpu::VideoMemoryUsageStats vram_stats;
manager->UpdateVideoMemoryUsageStats(vram_stats);
{
base::RunLoop run_loop;
@@ -609,6 +598,43 @@ TEST_F(GpuDataManagerImplPrivateTest, SetGLStringsNoEffects) {
EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
EXPECT_TRUE(manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL));
}
+
+TEST_F(GpuDataManagerImplPrivateTest, SetGLStringsDefered) {
+ const char* kGLVendorMesa = "Tungsten Graphics, Inc";
+ const char* kGLRendererMesa = "Mesa DRI Intel(R) G41";
+ const char* kGLVersionMesa801 = "2.1 Mesa 8.0.1-DEVEL";
+
+ ScopedGpuDataManagerImplPrivate manager;
+ EXPECT_EQ(0u, manager->GetBlacklistedFeatureCount());
+ EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
+
+ const std::string blacklist_json = LONG_STRING_CONST({
+ "name" : "gpu blacklist",
+ "version" : "0.1",
+ "entries" : [ {
+ "id" : 1,
+ "vendor_id" : "0x8086",
+ "device_id" : ["0x0042"],
+ "driver_vendor" : "Mesa",
+ "driver_version" : {"op" : ">=", "value" : "8.0.0"},
+ "features" : ["webgl"]
+ } ]
+ });
+
+ // Check that it is allowed to call SetGLStrings before Initialize.
+
+ // Assume browser gets GL strings from local state.
+ manager->SetGLStrings(kGLVendorMesa, kGLRendererMesa, kGLVersionMesa801);
+
+ gpu::GPUInfo gpu_info;
+ gpu_info.gpu.vendor_id = 0x8086;
+ gpu_info.gpu.device_id = 0x0042;
+ manager->InitializeForTesting(blacklist_json, gpu_info);
+
+ EXPECT_TRUE(manager->GpuAccessAllowed(NULL));
+ EXPECT_EQ(1u, manager->GetBlacklistedFeatureCount());
+ EXPECT_TRUE(manager->IsFeatureBlacklisted(gpu::GPU_FEATURE_TYPE_WEBGL));
+}
#endif // OS_LINUX
TEST_F(GpuDataManagerImplPrivateTest, GpuDriverBugListSingle) {
@@ -616,7 +642,7 @@ TEST_F(GpuDataManagerImplPrivateTest, GpuDriverBugListSingle) {
manager->gpu_driver_bugs_.insert(5);
base::CommandLine command_line(0, NULL);
- manager->AppendGpuCommandLine(&command_line);
+ manager->AppendGpuCommandLine(&command_line, nullptr);
EXPECT_TRUE(command_line.HasSwitch(switches::kGpuDriverBugWorkarounds));
std::string args = command_line.GetSwitchValueASCII(
@@ -630,7 +656,7 @@ TEST_F(GpuDataManagerImplPrivateTest, GpuDriverBugListMultiple) {
manager->gpu_driver_bugs_.insert(7);
base::CommandLine command_line(0, NULL);
- manager->AppendGpuCommandLine(&command_line);
+ manager->AppendGpuCommandLine(&command_line, nullptr);
EXPECT_TRUE(command_line.HasSwitch(switches::kGpuDriverBugWorkarounds));
std::string args = command_line.GetSwitchValueASCII(
diff --git a/chromium/content/browser/gpu/gpu_internals_ui.cc b/chromium/content/browser/gpu/gpu_internals_ui.cc
index e93c9015202..34ba18db3b6 100644
--- a/chromium/content/browser/gpu/gpu_internals_ui.cc
+++ b/chromium/content/browser/gpu/gpu_internals_ui.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include <string>
+#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -42,6 +43,7 @@
#endif
#if defined(OS_WIN)
#include "ui/base/win/shell.h"
+#include "ui/gfx/win/physical_size.h"
#endif
#if defined(OS_LINUX) && defined(USE_X11)
@@ -144,9 +146,20 @@ base::DictionaryValue* GpuInfoAsDictionaryValue() {
ui::win::IsAeroGlassEnabled() ? "Aero Glass" : "none";
basic_info->Append(
NewDescriptionValuePair("Desktop compositing", compositor));
- if (GpuDataManagerImpl::GetInstance()->ShouldUseWarp()) {
- basic_info->Append(NewDescriptionValuePair("Using WARP",
- new base::FundamentalValue(true)));
+
+ std::vector<gfx::PhysicalDisplaySize> display_sizes =
+ gfx::GetPhysicalSizeForDisplays();
+ for (const auto& display_size : display_sizes) {
+ const int w = display_size.width_mm;
+ const int h = display_size.height_mm;
+ const double size_mm = sqrt(w * w + h * h);
+ const double size_inches = 0.0393701 * size_mm;
+ const double rounded_size_inches = floor(10.0 * size_inches) / 10.0;
+ std::string size_string = base::StringPrintf("%.1f\"", rounded_size_inches);
+ std::string description_string = base::StringPrintf(
+ "Diagonal Monitor Size of %s", display_size.display_name.c_str());
+ basic_info->Append(
+ NewDescriptionValuePair(description_string, size_string));
}
#endif
@@ -230,7 +243,7 @@ base::DictionaryValue* GpuInfoAsDictionaryValue() {
scoped_ptr<base::Value> dx_info = base::Value::CreateNullValue();
if (gpu_info.dx_diagnostics.children.size())
dx_info.reset(DxDiagNodeToList(gpu_info.dx_diagnostics));
- info->Set("diagnostics", dx_info.Pass());
+ info->Set("diagnostics", std::move(dx_info));
#endif
return info;
@@ -286,7 +299,19 @@ const char* BufferUsageToString(gfx::BufferUsage usage) {
return nullptr;
}
-base::DictionaryValue* GpuMemoryBufferInfoAsDictionaryValue() {
+base::ListValue* CompositorInfo() {
+ base::ListValue* compositor_info = new base::ListValue();
+
+ compositor_info->Append(NewDescriptionValuePair(
+ "Tile Update Mode",
+ IsZeroCopyUploadEnabled() ? "Zero-copy" : "One-copy"));
+
+ compositor_info->Append(NewDescriptionValuePair(
+ "Partial Raster", IsPartialRasterEnabled() ? "Enabled" : "Disabled"));
+ return compositor_info;
+}
+
+base::ListValue* GpuMemoryBufferInfo() {
base::ListValue* gpu_memory_buffer_info = new base::ListValue();
BrowserGpuMemoryBufferManager* gpu_memory_buffer_manager =
@@ -312,11 +337,7 @@ base::DictionaryValue* GpuMemoryBufferInfoAsDictionaryValue() {
BufferFormatToString(static_cast<gfx::BufferFormat>(format)),
native_usage_support));
}
-
- base::DictionaryValue* info = new base::DictionaryValue();
- info->Set("gpu_memory_buffer_info", gpu_memory_buffer_info);
-
- return info;
+ return gpu_memory_buffer_info;
}
// This class receives javascript messages from the renderer.
@@ -492,18 +513,12 @@ void GpuMessageHandler::OnGpuInfoUpdate() {
workarounds->AppendString(workaround);
feature_status->Set("workarounds", workarounds);
gpu_info_val->Set("featureStatus", feature_status);
+ gpu_info_val->Set("compositorInfo", CompositorInfo());
+ gpu_info_val->Set("gpuMemoryBufferInfo", GpuMemoryBufferInfo());
// Send GPU Info to javascript.
web_ui()->CallJavascriptFunction("browserBridge.onGpuInfoUpdate",
*(gpu_info_val.get()));
-
- // Get GpuMemoryBuffer Info.
- scoped_ptr<base::DictionaryValue> gpu_memory_buffer_info_val(
- GpuMemoryBufferInfoAsDictionaryValue());
-
- // Send GpuMemoryBuffer Info to javascript.
- web_ui()->CallJavascriptFunction("browserBridge.onGpuMemoryBufferInfoUpdate",
- *(gpu_memory_buffer_info_val.get()));
}
void GpuMessageHandler::OnGpuSwitched() {
diff --git a/chromium/content/browser/gpu/gpu_ipc_browsertests.cc b/chromium/content/browser/gpu/gpu_ipc_browsertests.cc
index 1dcb1549049..fd0ba6909dd 100644
--- a/chromium/content/browser/gpu/gpu_ipc_browsertests.cc
+++ b/chromium/content/browser/gpu/gpu_ipc_browsertests.cc
@@ -9,12 +9,13 @@
#include "content/browser/gpu/gpu_process_host_ui_shim.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
+#include "content/common/gpu_process_launch_causes.h"
#include "content/public/browser/gpu_data_manager.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/content_browser_test.h"
#include "gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h"
#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/gpu/GrContext.h"
#include "ui/gl/gl_switches.h"
@@ -27,9 +28,32 @@ const content::CauseForGpuLaunch kInitCause =
content::
CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
+scoped_ptr<WebGraphicsContext3DCommandBufferImpl> CreateContext(
+ gpu::GpuChannelHost* gpu_channel_host) {
+ // This is for an offscreen context, so the default framebuffer doesn't need
+ // any alpha, depth, stencil, antialiasing.
+ gpu::gles2::ContextCreationAttribHelper attributes;
+ attributes.alpha_size = -1;
+ attributes.depth_size = 0;
+ attributes.stencil_size = 0;
+ attributes.samples = 0;
+ attributes.sample_buffers = 0;
+ attributes.bind_generates_resource = false;
+ bool share_resources = false;
+ bool automatic_flushes = false;
+ return make_scoped_ptr(
+ WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
+ gpu_channel_host, attributes, gfx::PreferIntegratedGpu,
+ share_resources, automatic_flushes, GURL(),
+ WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits(),
+ nullptr));
+}
+
class ContextTestBase : public content::ContentBrowserTest {
public:
void SetUpOnMainThread() override {
+ // This may leave the provider_ null in some cases, so tests need to early
+ // out.
if (!content::BrowserGpuChannelHostFactory::CanUseForTesting())
return;
@@ -39,36 +63,36 @@ class ContextTestBase : public content::ContentBrowserTest {
content::BrowserGpuChannelHostFactory* factory =
content::BrowserGpuChannelHostFactory::instance();
CHECK(factory);
- bool lose_context_when_out_of_memory = false;
base::RunLoop run_loop;
factory->EstablishGpuChannel(kInitCause, run_loop.QuitClosure());
run_loop.Run();
- scoped_refptr<content::GpuChannelHost>
- gpu_channel_host(factory->GetGpuChannel());
- DCHECK(gpu_channel_host.get());
- context_.reset(
- WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
- gpu_channel_host.get(),
- blink::WebGraphicsContext3D::Attributes(),
- lose_context_when_out_of_memory,
- GURL(),
- WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits(),
- NULL));
- CHECK(context_.get());
- context_->InitializeOnCurrentThread();
- context_support_ = context_->GetContextSupport();
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel_host(
+ factory->GetGpuChannel());
+ CHECK(gpu_channel_host);
+
+ provider_ = content::ContextProviderCommandBuffer::Create(
+ CreateContext(gpu_channel_host.get()),
+ content::OFFSCREEN_CONTEXT_FOR_TESTING);
+ bool bound = provider_->BindToCurrentThread();
+ CHECK(bound);
+ gl_ = provider_->ContextGL();
+ context_support_ = provider_->ContextSupport();
+
ContentBrowserTest::SetUpOnMainThread();
}
void TearDownOnMainThread() override {
// Must delete the context first.
- context_.reset(NULL);
+ provider_ = nullptr;
ContentBrowserTest::TearDownOnMainThread();
}
protected:
- scoped_ptr<content::WebGraphicsContext3DCommandBufferImpl> context_;
- gpu::ContextSupport* context_support_;
+ gpu::gles2::GLES2Interface* gl_ = nullptr;
+ gpu::ContextSupport* context_support_ = nullptr;
+
+ private:
+ scoped_refptr<content::ContextProviderCommandBuffer> provider_;
};
} // namespace
@@ -121,26 +145,12 @@ class BrowserGpuChannelHostFactoryTest : public ContentBrowserTest {
run_loop.Run();
}
- GpuChannelHost* GetGpuChannel() {
- return GetFactory()->GetGpuChannel();
- }
+ gpu::GpuChannelHost* GetGpuChannel() { return GetFactory()->GetGpuChannel(); }
static void Signal(bool *event) {
CHECK_EQ(*event, false);
*event = true;
}
-
- scoped_ptr<WebGraphicsContext3DCommandBufferImpl> CreateContext() {
- bool lose_context_when_out_of_memory = false;
- return make_scoped_ptr(
- WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
- GetGpuChannel(),
- blink::WebGraphicsContext3D::Attributes(),
- lose_context_when_out_of_memory,
- GURL(),
- WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits(),
- NULL));
- }
};
// Test fails on Chromeos + Mac, flaky on Windows because UI Compositor
@@ -185,7 +195,7 @@ IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest,
IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest,
MAYBE_AlreadyEstablished) {
DCHECK(!IsChannelEstablished());
- scoped_refptr<GpuChannelHost> gpu_channel =
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel =
GetFactory()->EstablishGpuChannelSync(kInitCause);
// Expect established callback immediately.
@@ -199,9 +209,7 @@ IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest,
#endif
// Test fails on Windows because GPU Channel set-up fails.
-// Mac only fails GPU set-up on MacOS 10.6, but we have no version-specific
-// macros for disabling tests.
-#if !defined(OS_WIN) && !defined(OS_MACOSX)
+#if !defined(OS_WIN)
#define MAYBE_GrContextKeepsGpuChannelAlive GrContextKeepsGpuChannelAlive
#else
#define MAYBE_GrContextKeepsGpuChannelAlive \
@@ -221,22 +229,33 @@ IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest,
// Step 2: verify that holding onto the provider's GrContext will
// retain the host after provider is destroyed.
scoped_refptr<ContextProviderCommandBuffer> provider =
- ContextProviderCommandBuffer::Create(CreateContext(),
+ ContextProviderCommandBuffer::Create(CreateContext(GetGpuChannel()),
OFFSCREEN_CONTEXT_FOR_TESTING);
EXPECT_TRUE(provider->BindToCurrentThread());
- skia::RefPtr<GrContext> gr_context = skia::SharePtr(provider->GrContext());
- provider = nullptr;
+ sk_sp<GrContext> gr_context = sk_ref_sp(provider->GrContext());
SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
- skia::RefPtr<SkSurface> surface = skia::AdoptRef(SkSurface::NewRenderTarget(
- gr_context.get(), SkSurface::kNo_Budgeted, info));
+ sk_sp<SkSurface> surface = SkSurface::MakeRenderTarget(
+ gr_context.get(), SkBudgeted::kNo, info);
+ EXPECT_TRUE(surface);
+
+ // Destroy the GL context after we made a surface.
+ provider = nullptr;
+
+ // New surfaces will fail to create now.
+ sk_sp<SkSurface> surface2 =
+ SkSurface::MakeRenderTarget(gr_context.get(), SkBudgeted::kNo, info);
+ EXPECT_FALSE(surface2);
+
+ // Drop our reference to the gr_context also.
gr_context = nullptr;
- // use the canvas after the provider and grcontext have been locally
- // unref'ed. This should work just fine thanks to SkSurface_Gpu ref'ing
- // the GrContext, which is ref'ing the GrGLInterfaceForWebGraphicsContext3D,
- // which owns the commandbuffer instance.
+ // After the context provider is destroyed, the surface no longer has access
+ // to the GrContext, even though it's alive. Use the canvas after the provider
+ // and GrContext have been locally unref'ed. This should work fine as the
+ // GrContext has been abandoned when the GL context provider was destroyed
+ // above.
SkPaint greenFillPaint;
greenFillPaint.setColor(SK_ColorGREEN);
greenFillPaint.setStyle(SkPaint::kFill_Style);
@@ -255,10 +274,10 @@ IN_PROC_BROWSER_TEST_F(BrowserGpuChannelHostFactoryTest,
MAYBE_CrashAndRecover) {
DCHECK(!IsChannelEstablished());
EstablishAndWait();
- scoped_refptr<GpuChannelHost> host = GetGpuChannel();
+ scoped_refptr<gpu::GpuChannelHost> host = GetGpuChannel();
scoped_refptr<ContextProviderCommandBuffer> provider =
- ContextProviderCommandBuffer::Create(CreateContext(),
+ ContextProviderCommandBuffer::Create(CreateContext(GetGpuChannel()),
OFFSCREEN_CONTEXT_FOR_TESTING);
base::RunLoop run_loop;
int counter = 0;
diff --git a/chromium/content/browser/gpu/gpu_process_host.cc b/chromium/content/browser/gpu/gpu_process_host.cc
index b3bd310650a..1f03d6361d5 100644
--- a/chromium/content/browser/gpu/gpu_process_host.cc
+++ b/chromium/content/browser/gpu/gpu_process_host.cc
@@ -31,11 +31,13 @@
#include "content/browser/mojo/mojo_application_host.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/common/child_process_host_impl.h"
-#include "content/common/gpu/gpu_messages.h"
+#include "content/common/establish_channel_params.h"
+#include "content/common/gpu_host_messages.h"
#include "content/common/in_process_child_thread_params.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/gpu_utils.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
@@ -44,6 +46,7 @@
#include "content/public/common/result_codes.h"
#include "content/public/common/sandbox_type.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
+#include "gpu/command_buffer/service/gpu_preferences.h"
#include "gpu/command_buffer/service/gpu_switches.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_switches.h"
@@ -62,6 +65,7 @@
#include "content/common/sandbox_win.h"
#include "sandbox/win/src/sandbox_policy.h"
#include "ui/gfx/switches.h"
+#include "ui/gfx/win/rendering_window_manager.h"
#endif
#if defined(USE_OZONE)
@@ -104,13 +108,10 @@ static const char* const kSwitchNames[] = {
#endif
switches::kEnableHeapProfiling,
switches::kEnableLogging,
- switches::kEnableShareGroupAsyncTextureUpload,
-#if defined(OS_ANDROID)
- switches::kEnableUnifiedMediaPipeline,
-#endif
#if defined(OS_CHROMEOS)
switches::kDisableVaapiAcceleratedVideoEncode,
#endif
+ switches::kGpuDriverBugWorkarounds,
switches::kGpuStartupDialog,
switches::kGpuSandboxAllowSysVShm,
switches::kGpuSandboxFailuresFatal,
@@ -129,13 +130,9 @@ static const char* const kSwitchNames[] = {
switches::kVModule,
#if defined(OS_MACOSX)
switches::kDisableRemoteCoreAnimation,
- switches::kDisableMacOverlays,
switches::kEnableSandboxLogging,
switches::kShowMacOverlayBorders,
#endif
-#if defined(USE_AURA)
- switches::kUIPrioritizeInGpuProcess,
-#endif
#if defined(USE_OZONE)
switches::kOzonePlatform,
#endif
@@ -382,6 +379,14 @@ void GpuProcessHost::SendOnIO(GpuProcessKind kind,
GpuMainThreadFactoryFunction g_gpu_main_thread_factory = NULL;
+GpuProcessHost::EstablishChannelRequest::EstablishChannelRequest()
+ : client_id(0) {}
+
+GpuProcessHost::EstablishChannelRequest::EstablishChannelRequest(
+ const EstablishChannelRequest& other) = default;
+
+GpuProcessHost::EstablishChannelRequest::~EstablishChannelRequest() {}
+
void GpuProcessHost::RegisterGpuMainThreadFactory(
GpuMainThreadFactoryFunction create) {
g_gpu_main_thread_factory = create;
@@ -451,11 +456,6 @@ GpuProcessHost::~GpuProcessHost() {
if (g_gpu_process_hosts[kind_] == this)
g_gpu_process_hosts[kind_] = NULL;
- // If there are any remaining offscreen contexts at the point the
- // GPU process exits, assume something went wrong, and block their
- // URLs from accessing client 3D APIs without prompting.
- BlockLiveOffscreenContexts();
-
UMA_HISTOGRAM_COUNTS_100("GPU.AtExitSurfaceCount",
GpuSurfaceTracker::Get()->GetSurfaceCount());
UMA_HISTOGRAM_BOOLEAN("GPU.AtExitReceivedMemoryStats",
@@ -473,6 +473,7 @@ GpuProcessHost::~GpuProcessHost() {
}
std::string message;
+ bool block_offscreen_contexts = true;
if (!in_process_) {
int exit_code;
base::TerminationStatus status = process_->GetTerminationStatus(
@@ -490,6 +491,14 @@ GpuProcessHost::~GpuProcessHost() {
switch (status) {
case base::TERMINATION_STATUS_NORMAL_TERMINATION:
+ // Don't block offscreen contexts (and force page reload for webgl)
+ // if this was an intentional shutdown or the OOM killer on Android
+ // killed us while Chrome was in the background.
+// TODO(crbug.com/598400): Restrict this to Android for now, since other
+// platforms might fall through here for the 'exit_on_context_lost' workaround.
+#if defined(OS_ANDROID)
+ block_offscreen_contexts = false;
+#endif
message = "The GPU process exited normally. Everything is okay.";
break;
case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
@@ -516,6 +525,12 @@ GpuProcessHost::~GpuProcessHost() {
}
}
+ // If there are any remaining offscreen contexts at the point the
+ // GPU process exits, assume something went wrong, and block their
+ // URLs from accessing client 3D APIs without prompting.
+ if (block_offscreen_contexts)
+ BlockLiveOffscreenContexts();
+
BrowserThread::PostTask(BrowserThread::UI,
FROM_HERE,
base::Bind(&GpuProcessHostUIShim::Destroy,
@@ -535,25 +550,30 @@ bool GpuProcessHost::Init() {
if (!SetupMojo())
return false;
+ gpu::GpuPreferences gpu_preferences = GetGpuPreferencesFromCommandLine();
if (in_process_) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(g_gpu_main_thread_factory);
in_process_gpu_thread_.reset(
g_gpu_main_thread_factory(InProcessChildThreadParams(
- channel_id, base::MessageLoop::current()->task_runner())));
+ channel_id, base::MessageLoop::current()->task_runner()),
+ gpu_preferences));
base::Thread::Options options;
#if defined(OS_WIN)
// WGL needs to create its own window and pump messages on it.
options.message_loop_type = base::MessageLoop::TYPE_UI;
#endif
+#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
+ options.priority = base::ThreadPriority::DISPLAY;
+#endif
in_process_gpu_thread_->StartWithOptions(options);
OnProcessLaunched(); // Fake a callback that the process is ready.
- } else if (!LaunchGpuProcess(channel_id)) {
+ } else if (!LaunchGpuProcess(channel_id, &gpu_preferences)) {
return false;
}
- if (!Send(new GpuMsg_Initialize()))
+ if (!Send(new GpuMsg_Initialize(gpu_preferences)))
return false;
return true;
@@ -599,15 +619,10 @@ bool GpuProcessHost::OnMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(GpuProcessHost, message)
IPC_MESSAGE_HANDLER(GpuHostMsg_Initialized, OnInitialized)
IPC_MESSAGE_HANDLER(GpuHostMsg_ChannelEstablished, OnChannelEstablished)
- IPC_MESSAGE_HANDLER(GpuHostMsg_CommandBufferCreated, OnCommandBufferCreated)
IPC_MESSAGE_HANDLER(GpuHostMsg_GpuMemoryBufferCreated,
OnGpuMemoryBufferCreated)
IPC_MESSAGE_HANDLER(GpuHostMsg_DidCreateOffscreenContext,
OnDidCreateOffscreenContext)
-#if defined(OS_CHROMEOS)
- IPC_MESSAGE_HANDLER(GpuHostMsg_ArcVideoAcceleratorChannelCreated,
- OnArcVideoAcceleratorChannelCreated)
-#endif
IPC_MESSAGE_HANDLER(GpuHostMsg_DidLoseContext, OnDidLoseContext)
IPC_MESSAGE_HANDLER(GpuHostMsg_DidDestroyOffscreenContext,
OnDidDestroyOffscreenContext)
@@ -617,10 +632,8 @@ bool GpuProcessHost::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER_GENERIC(GpuHostMsg_AcceleratedSurfaceBuffersSwapped,
OnAcceleratedSurfaceBuffersSwapped(message))
#endif
- IPC_MESSAGE_HANDLER(GpuHostMsg_DestroyChannel,
- OnDestroyChannel)
- IPC_MESSAGE_HANDLER(GpuHostMsg_CacheShader,
- OnCacheShader)
+ IPC_MESSAGE_HANDLER(GpuHostMsg_DestroyChannel, OnDestroyChannel)
+ IPC_MESSAGE_HANDLER(GpuHostMsg_CacheShader, OnCacheShader)
#if defined(OS_WIN)
IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceCreatedChildWindow,
OnAcceleratedSurfaceCreatedChildWindow)
@@ -634,31 +647,38 @@ bool GpuProcessHost::OnMessageReceived(const IPC::Message& message) {
#if defined(OS_WIN)
void GpuProcessHost::OnAcceleratedSurfaceCreatedChildWindow(
- const gfx::PluginWindowHandle& parent_handle,
- const gfx::PluginWindowHandle& window_handle) {
- DCHECK(process_);
- {
- DWORD process_id = 0;
- DWORD thread_id = GetWindowThreadProcessId(parent_handle, &process_id);
-
- if (!thread_id || process_id != ::GetCurrentProcessId()) {
- process_->TerminateOnBadMessageReceived(
- GpuHostMsg_AcceleratedSurfaceCreatedChildWindow::ID);
- return;
+ gpu::SurfaceHandle parent_handle,
+ gpu::SurfaceHandle window_handle) {
+ if (!in_process_) {
+ DCHECK(process_);
+ {
+ DWORD process_id = 0;
+ DWORD thread_id = GetWindowThreadProcessId(parent_handle, &process_id);
+
+ if (!thread_id || process_id != ::GetCurrentProcessId()) {
+ process_->TerminateOnBadMessageReceived(
+ GpuHostMsg_AcceleratedSurfaceCreatedChildWindow::ID);
+ return;
+ }
}
- }
- {
- DWORD process_id = 0;
- DWORD thread_id = GetWindowThreadProcessId(window_handle, &process_id);
- if (!thread_id || process_id != process_->GetProcess().Pid()) {
- process_->TerminateOnBadMessageReceived(
- GpuHostMsg_AcceleratedSurfaceCreatedChildWindow::ID);
- return;
+ {
+ DWORD process_id = 0;
+ DWORD thread_id = GetWindowThreadProcessId(window_handle, &process_id);
+
+ if (!thread_id || process_id != process_->GetProcess().Pid()) {
+ process_->TerminateOnBadMessageReceived(
+ GpuHostMsg_AcceleratedSurfaceCreatedChildWindow::ID);
+ return;
+ }
}
}
- ::SetParent(window_handle, parent_handle);
+ if (!gfx::RenderingWindowManager::GetInstance()->RegisterChild(
+ parent_handle, window_handle)) {
+ process_->TerminateOnBadMessageReceived(
+ GpuHostMsg_AcceleratedSurfaceCreatedChildWindow::ID);
+ }
}
#endif
@@ -675,8 +695,7 @@ void GpuProcessHost::EstablishGpuChannel(
int client_id,
uint64_t client_tracing_id,
bool preempts,
- bool preempted,
- bool allow_future_sync_points,
+ bool allow_view_command_buffers,
bool allow_real_time_streams,
const EstablishChannelCallback& callback) {
DCHECK(CalledOnValidThread());
@@ -689,15 +708,17 @@ void GpuProcessHost::EstablishGpuChannel(
return;
}
- GpuMsg_EstablishChannel_Params params;
+ EstablishChannelParams params;
params.client_id = client_id;
params.client_tracing_id = client_tracing_id;
params.preempts = preempts;
- params.preempted = preempted;
- params.allow_future_sync_points = allow_future_sync_points;
+ params.allow_view_command_buffers = allow_view_command_buffers;
params.allow_real_time_streams = allow_real_time_streams;
if (Send(new GpuMsg_EstablishChannel(params))) {
- channel_requests_.push(callback);
+ EstablishChannelRequest request;
+ request.client_id = client_id;
+ request.callback = callback;
+ channel_requests_.push(request);
} else {
DVLOG(1) << "Failed to send GpuMsg_EstablishChannel.";
callback.Run(IPC::ChannelHandle(), gpu::GPUInfo());
@@ -709,27 +730,6 @@ void GpuProcessHost::EstablishGpuChannel(
}
}
-void GpuProcessHost::CreateViewCommandBuffer(
- const gfx::GLSurfaceHandle& compositing_surface,
- int client_id,
- const GPUCreateCommandBufferConfig& init_params,
- int route_id,
- const CreateCommandBufferCallback& callback) {
- TRACE_EVENT0("gpu", "GpuProcessHost::CreateViewCommandBuffer");
-
- DCHECK(CalledOnValidThread());
-
- if (!compositing_surface.is_null() &&
- Send(new GpuMsg_CreateViewCommandBuffer(compositing_surface, client_id,
- init_params, route_id))) {
- create_command_buffer_requests_.push(callback);
- } else {
- // Could distinguish here between compositing_surface being NULL
- // and Send failing, if desired.
- callback.Run(CREATE_COMMAND_BUFFER_FAILED_AND_CHANNEL_LOST);
- }
-}
-
void GpuProcessHost::CreateGpuMemoryBuffer(
gfx::GpuMemoryBufferId id,
const gfx::Size& size,
@@ -749,7 +749,9 @@ void GpuProcessHost::CreateGpuMemoryBuffer(
params.usage = usage;
params.client_id = client_id;
params.surface_handle =
- GpuSurfaceTracker::GetInstance()->GetSurfaceHandle(surface_id).handle;
+ surface_id
+ ? GpuSurfaceTracker::GetInstance()->GetSurfaceHandle(surface_id)
+ : gpu::kNullSurfaceHandle;
if (Send(new GpuMsg_CreateGpuMemoryBuffer(params))) {
create_gpu_memory_buffer_requests_.push(callback);
} else {
@@ -791,19 +793,6 @@ void GpuProcessHost::DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
Send(new GpuMsg_DestroyGpuMemoryBuffer(id, client_id, sync_token));
}
-#if defined(OS_CHROMEOS)
-void GpuProcessHost::CreateArcVideoAcceleratorChannel(
- const CreateArcVideoAcceleratorChannelCallback& callback) {
- DCHECK(CalledOnValidThread());
-
- if (Send(new GpuMsg_CreateArcVideoAcceleratorChannel())) {
- create_arc_video_accelerator_channel_requests_.push(callback);
- } else {
- callback.Run(IPC::ChannelHandle());
- }
-}
-#endif
-
void GpuProcessHost::OnInitialized(bool result, const gpu::GPUInfo& gpu_info) {
UMA_HISTOGRAM_BOOLEAN("GPU.GPUProcessInitialized", result);
initialized_ = result;
@@ -822,40 +811,26 @@ void GpuProcessHost::OnChannelEstablished(
if (channel_requests_.empty()) {
// This happens when GPU process is compromised.
RouteOnUIThread(GpuHostMsg_OnLogMessage(
- logging::LOG_WARNING,
- "WARNING",
+ logging::LOG_WARNING, "WARNING",
"Received a ChannelEstablished message but no requests in queue."));
return;
}
- EstablishChannelCallback callback = channel_requests_.front();
+ EstablishChannelRequest request = channel_requests_.front();
channel_requests_.pop();
// Currently if any of the GPU features are blacklisted, we don't establish a
// GPU channel.
if (!channel_handle.name.empty() &&
!GpuDataManagerImpl::GetInstance()->GpuAccessAllowed(NULL)) {
- Send(new GpuMsg_CloseChannel(channel_handle));
- callback.Run(IPC::ChannelHandle(), gpu::GPUInfo());
- RouteOnUIThread(GpuHostMsg_OnLogMessage(
- logging::LOG_WARNING,
- "WARNING",
- "Hardware acceleration is unavailable."));
+ Send(new GpuMsg_CloseChannel(request.client_id));
+ request.callback.Run(IPC::ChannelHandle(), gpu::GPUInfo());
+ RouteOnUIThread(
+ GpuHostMsg_OnLogMessage(logging::LOG_WARNING, "WARNING",
+ "Hardware acceleration is unavailable."));
return;
}
- callback.Run(channel_handle, gpu_info_);
-}
-
-void GpuProcessHost::OnCommandBufferCreated(CreateCommandBufferResult result) {
- TRACE_EVENT0("gpu", "GpuProcessHost::OnCommandBufferCreated");
-
- if (create_command_buffer_requests_.empty())
- return;
-
- CreateCommandBufferCallback callback =
- create_command_buffer_requests_.front();
- create_command_buffer_requests_.pop();
- callback.Run(result);
+ request.callback.Run(channel_handle, gpu_info_);
}
void GpuProcessHost::OnGpuMemoryBufferCreated(
@@ -871,24 +846,6 @@ void GpuProcessHost::OnGpuMemoryBufferCreated(
callback.Run(handle);
}
-#if defined(OS_CHROMEOS)
-void GpuProcessHost::OnArcVideoAcceleratorChannelCreated(
- const IPC::ChannelHandle& handle) {
- if (create_arc_video_accelerator_channel_requests_.empty()) {
- RouteOnUIThread(
- GpuHostMsg_OnLogMessage(logging::LOG_WARNING, "WARNING",
- "Received a ArcVideoAcceleratorChannelCreated "
- "message but no requests in queue."));
- return;
- }
-
- CreateArcVideoAcceleratorChannelCallback callback =
- create_arc_video_accelerator_channel_requests_.front();
- create_arc_video_accelerator_channel_requests_.pop();
- callback.Run(handle);
-}
-#endif
-
void GpuProcessHost::OnDidCreateOffscreenContext(const GURL& url) {
urls_with_live_offscreen_contexts_.insert(url);
}
@@ -935,7 +892,7 @@ void GpuProcessHost::OnDidDestroyOffscreenContext(const GURL& url) {
}
void GpuProcessHost::OnGpuMemoryUmaStatsReceived(
- const GPUMemoryUmaStats& stats) {
+ const gpu::GPUMemoryUmaStats& stats) {
TRACE_EVENT0("gpu", "GpuProcessHost::OnGpuMemoryUmaStatsReceived");
uma_memory_stats_received_ = true;
uma_memory_stats_ = stats;
@@ -993,7 +950,8 @@ void GpuProcessHost::StopGpuProcess() {
Send(new GpuMsg_Finalize());
}
-bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id) {
+bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id,
+ gpu::GpuPreferences* gpu_preferences) {
if (!(gpu_enabled_ &&
GpuDataManagerImpl::GetInstance()->ShouldUseSwiftShader()) &&
!hardware_gpu_enabled_) {
@@ -1027,6 +985,7 @@ bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id) {
base::CommandLine* cmd_line = new base::CommandLine(exe_path);
#endif
+ BrowserChildProcessHostImpl::CopyFeatureAndFieldTrialFlags(cmd_line);
cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kGpuProcess);
cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);
@@ -1038,21 +997,21 @@ bool GpuProcessHost::LaunchGpuProcess(const std::string& channel_id) {
if (kind_ == GPU_PROCESS_KIND_UNSANDBOXED)
cmd_line->AppendSwitch(switches::kDisableGpuSandbox);
+ // TODO(penghuang): Replace all GPU related switches with GpuPreferences.
+ // https://crbug.com/590825
// If you want a browser command-line switch passed to the GPU process
// you need to add it to |kSwitchNames| at the beginning of this file.
cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames,
arraysize(kSwitchNames));
cmd_line->CopySwitchesFrom(
- browser_command_line, switches::kGpuSwitches, switches::kNumGpuSwitches);
- cmd_line->CopySwitchesFrom(
browser_command_line, switches::kGLSwitchesCopiedFromGpuProcessHost,
switches::kGLSwitchesCopiedFromGpuProcessHostNumSwitches);
GetContentClient()->browser()->AppendExtraCommandLineSwitches(
cmd_line, process_->GetData().id);
- GpuDataManagerImpl::GetInstance()->AppendGpuCommandLine(cmd_line);
-
+ GpuDataManagerImpl::GetInstance()->AppendGpuCommandLine(cmd_line,
+ gpu_preferences);
if (cmd_line->HasSwitch(switches::kUseGL)) {
swiftshader_rendering_ =
(cmd_line->GetSwitchValueASCII(switches::kUseGL) == "swiftshader");
@@ -1081,16 +1040,9 @@ void GpuProcessHost::SendOutstandingReplies() {
valid_ = false;
// First send empty channel handles for all EstablishChannel requests.
while (!channel_requests_.empty()) {
- EstablishChannelCallback callback = channel_requests_.front();
+ EstablishChannelRequest request = channel_requests_.front();
channel_requests_.pop();
- callback.Run(IPC::ChannelHandle(), gpu::GPUInfo());
- }
-
- while (!create_command_buffer_requests_.empty()) {
- CreateCommandBufferCallback callback =
- create_command_buffer_requests_.front();
- create_command_buffer_requests_.pop();
- callback.Run(CREATE_COMMAND_BUFFER_FAILED_AND_CHANNEL_LOST);
+ request.callback.Run(IPC::ChannelHandle(), gpu::GPUInfo());
}
while (!create_gpu_memory_buffer_requests_.empty()) {
@@ -1099,15 +1051,6 @@ void GpuProcessHost::SendOutstandingReplies() {
create_gpu_memory_buffer_requests_.pop();
callback.Run(gfx::GpuMemoryBufferHandle());
}
-
-#if defined(OS_CHROMEOS)
- while (!create_arc_video_accelerator_channel_requests_.empty()) {
- CreateArcVideoAcceleratorChannelCallback callback =
- create_arc_video_accelerator_channel_requests_.front();
- create_arc_video_accelerator_channel_requests_.pop();
- callback.Run(IPC::ChannelHandle());
- }
-#endif
}
void GpuProcessHost::BlockLiveOffscreenContexts() {
diff --git a/chromium/content/browser/gpu/gpu_process_host.h b/chromium/content/browser/gpu/gpu_process_host.h
index 3fb0c006fe2..0b35c56b70e 100644
--- a/chromium/content/browser/gpu/gpu_process_host.h
+++ b/chromium/content/browser/gpu/gpu_process_host.h
@@ -15,23 +15,23 @@
#include "base/callback.h"
#include "base/containers/hash_tables.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/non_thread_safe.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
-#include "content/common/gpu/gpu_memory_uma_stats.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
-#include "content/common/gpu/gpu_result_codes.h"
+#include "content/common/gpu_process_launch_causes.h"
#include "content/public/browser/browser_child_process_host_delegate.h"
#include "content/public/browser/gpu_data_manager.h"
#include "gpu/command_buffer/common/constants.h"
#include "gpu/config/gpu_info.h"
+#include "gpu/ipc/common/gpu_memory_uma_stats.h"
+#include "gpu/ipc/common/surface_handle.h"
#include "ipc/ipc_sender.h"
#include "ipc/message_filter.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/gpu_memory_buffer.h"
-#include "ui/gfx/native_widget_types.h"
#include "url/gurl.h"
struct GPUCreateCommandBufferConfig;
@@ -41,6 +41,7 @@ struct ChannelHandle;
}
namespace gpu {
+struct GpuPreferences;
struct SyncToken;
}
@@ -53,7 +54,7 @@ class RenderWidgetHostViewFrameSubscriber;
class ShaderDiskCache;
typedef base::Thread* (*GpuMainThreadFactoryFunction)(
- const InProcessChildThreadParams&);
+ const InProcessChildThreadParams&, const gpu::GpuPreferences&);
class GpuProcessHost : public BrowserChildProcessHostDelegate,
public IPC::Sender,
@@ -68,17 +69,17 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
typedef base::Callback<void(const IPC::ChannelHandle&, const gpu::GPUInfo&)>
EstablishChannelCallback;
- typedef base::Callback<void(CreateCommandBufferResult)>
- CreateCommandBufferCallback;
+ struct EstablishChannelRequest {
+ EstablishChannelRequest();
+ EstablishChannelRequest(const EstablishChannelRequest& other);
+ ~EstablishChannelRequest();
+ int32_t client_id;
+ EstablishChannelCallback callback;
+ };
typedef base::Callback<void(const gfx::GpuMemoryBufferHandle& handle)>
CreateGpuMemoryBufferCallback;
-#if defined(OS_CHROMEOS)
- typedef base::Callback<void(const IPC::ChannelHandle&)>
- CreateArcVideoAcceleratorChannelCallback;
-#endif
-
static bool gpu_enabled() { return gpu_enabled_; }
static int gpu_crash_count() { return gpu_crash_count_; }
@@ -104,6 +105,9 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
CONTENT_EXPORT static void RegisterGpuMainThreadFactory(
GpuMainThreadFactoryFunction create);
+ // BrowserChildProcessHostDelegate implementation.
+ ServiceRegistry* GetServiceRegistry() override;
+
// 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);
@@ -121,20 +125,10 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
void EstablishGpuChannel(int client_id,
uint64_t client_tracing_id,
bool preempts,
- bool preempted,
- bool allow_future_sync_points,
+ bool allow_view_command_buffers,
bool allow_real_time_streams,
const EstablishChannelCallback& callback);
- // Tells the GPU process to create a new command buffer that draws into the
- // given surface.
- void CreateViewCommandBuffer(
- const gfx::GLSurfaceHandle& compositing_surface,
- int client_id,
- const GPUCreateCommandBufferConfig& init_params,
- int route_id,
- const CreateCommandBufferCallback& callback);
-
// Tells the GPU process to create a new GPU memory buffer.
void CreateGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
const gfx::Size& size,
@@ -159,13 +153,6 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
int client_id,
const gpu::SyncToken& sync_token);
-#if defined(OS_CHROMEOS)
- // Tells the GPU process to create a new ipc channel for
- // ArcVideoAccelerator.
- void CreateArcVideoAcceleratorChannel(
- const CreateArcVideoAcceleratorChannelCallback& callback);
-#endif
-
// What kind of GPU process, e.g. sandboxed or unsandboxed.
GpuProcessKind kind();
@@ -175,10 +162,6 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
// Asks the GPU process to stop by itself.
void StopGpuProcess();
- void BeginFrameSubscription(
- int surface_id,
- base::WeakPtr<RenderWidgetHostViewFrameSubscriber> subscriber);
- void EndFrameSubscription(int surface_id);
void LoadedShader(const std::string& key, const std::string& data);
private:
@@ -201,28 +184,25 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
void OnProcessLaunched() override;
void OnProcessLaunchFailed() override;
void OnProcessCrashed(int exit_code) override;
- ServiceRegistry* GetServiceRegistry() override;
// Message handlers.
void OnInitialized(bool result, const gpu::GPUInfo& gpu_info);
void OnChannelEstablished(const IPC::ChannelHandle& channel_handle);
- void OnCommandBufferCreated(CreateCommandBufferResult result);
void OnGpuMemoryBufferCreated(const gfx::GpuMemoryBufferHandle& handle);
- void OnArcVideoAcceleratorChannelCreated(const IPC::ChannelHandle& handle);
void OnDidCreateOffscreenContext(const GURL& url);
void OnDidLoseContext(bool offscreen,
gpu::error::ContextLostReason reason,
const GURL& url);
void OnDidDestroyOffscreenContext(const GURL& url);
- void OnGpuMemoryUmaStatsReceived(const GPUMemoryUmaStats& stats);
+ void OnGpuMemoryUmaStatsReceived(const gpu::GPUMemoryUmaStats& stats);
#if defined(OS_MACOSX)
void OnAcceleratedSurfaceBuffersSwapped(const IPC::Message& message);
#endif
#if defined(OS_WIN)
void OnAcceleratedSurfaceCreatedChildWindow(
- const gfx::PluginWindowHandle& parent_handle,
- const gfx::PluginWindowHandle& window_handle);
+ gpu::SurfaceHandle parent_handle,
+ gpu::SurfaceHandle window_handle);
#endif
void CreateChannelCache(int32_t client_id);
@@ -231,7 +211,8 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
const std::string& key,
const std::string& shader);
- bool LaunchGpuProcess(const std::string& channel_id);
+ bool LaunchGpuProcess(const std::string& channel_id,
+ gpu::GpuPreferences* gpu_preferences);
void SendOutstandingReplies();
@@ -247,21 +228,11 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
// These are the channel requests that we have already sent to
// the GPU process, but haven't heard back about yet.
- std::queue<EstablishChannelCallback> channel_requests_;
-
- // The pending create command buffer requests we need to reply to.
- std::queue<CreateCommandBufferCallback> create_command_buffer_requests_;
+ std::queue<EstablishChannelRequest> channel_requests_;
// The pending create gpu memory buffer requests we need to reply to.
std::queue<CreateGpuMemoryBufferCallback> create_gpu_memory_buffer_requests_;
-#if defined(OS_CHROMEOS)
- // The pending create arc video accelerator channel requests we need to reply
- // to.
- std::queue<CreateArcVideoAcceleratorChannelCallback>
- create_arc_video_accelerator_channel_requests_;
-#endif
-
// Qeueud messages to send when the process launches.
std::queue<IPC::Message*> queued_messages_;
@@ -313,7 +284,7 @@ class GpuProcessHost : public BrowserChildProcessHostDelegate,
// Statics kept around to send to UMA histograms on GPU process lost.
bool uma_memory_stats_received_;
- GPUMemoryUmaStats uma_memory_stats_;
+ gpu::GPUMemoryUmaStats uma_memory_stats_;
typedef std::map<int32_t, scoped_refptr<ShaderDiskCache>>
ClientIdToShaderCacheMap;
diff --git a/chromium/content/browser/gpu/gpu_process_host_ui_shim.cc b/chromium/content/browser/gpu/gpu_process_host_ui_shim.cc
index f50db216e35..a7c5b20bd8d 100644
--- a/chromium/content/browser/gpu/gpu_process_host_ui_shim.cc
+++ b/chromium/content/browser/gpu/gpu_process_host_ui_shim.cc
@@ -22,10 +22,13 @@
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_helper.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
-#include "content/common/gpu/gpu_messages.h"
+#include "content/common/gpu_host_messages.h"
#include "content/public/browser/browser_thread.h"
+#include "gpu/ipc/common/memory_stats.h"
+#include "ui/gfx/swap_result.h"
#if defined(OS_MACOSX)
+#include "content/common/accelerated_surface_buffers_swapped_params_mac.h"
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
#endif
@@ -184,8 +187,7 @@ bool GpuProcessHostUIShim::OnControlMessageReceived(
DCHECK(CalledOnValidThread());
IPC_BEGIN_MESSAGE_MAP(GpuProcessHostUIShim, message)
- IPC_MESSAGE_HANDLER(GpuHostMsg_OnLogMessage,
- OnLogMessage)
+ IPC_MESSAGE_HANDLER(GpuHostMsg_OnLogMessage, OnLogMessage)
#if defined(OS_MACOSX)
IPC_MESSAGE_HANDLER(GpuHostMsg_AcceleratedSurfaceBuffersSwapped,
OnAcceleratedSurfaceBuffersSwapped)
@@ -222,19 +224,19 @@ void GpuProcessHostUIShim::OnGraphicsInfoCollected(
#if defined(OS_MACOSX)
void GpuProcessHostUIShim::OnAcceleratedSurfaceBuffersSwapped(
- const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params) {
+ const AcceleratedSurfaceBuffersSwappedParams& params) {
TRACE_EVENT0("browser",
"GpuProcessHostUIShim::OnAcceleratedSurfaceBuffersSwapped");
if (!ui::LatencyInfo::Verify(params.latency_info,
"GpuHostMsg_AcceleratedSurfaceBuffersSwapped")) {
-
TRACE_EVENT0("browser", "ui::LatencyInfo::Verify failed");
return;
}
// On Mac with delegated rendering, accelerated surfaces are not necessarily
// associated with a RenderWidgetHostViewBase.
- AcceleratedSurfaceMsg_BufferPresented_Params ack_params;
+ BufferPresentedParams ack_params;
+ ack_params.surface_id = params.surface_id;
// If the frame was intended for an NSView that the gfx::AcceleratedWidget is
// no longer attached to, do not pass the frame along to the widget. Just ack
@@ -266,12 +268,12 @@ void GpuProcessHostUIShim::OnAcceleratedSurfaceBuffersSwapped(
content::ImageTransportFactory::GetInstance()->OnGpuSwapBuffersCompleted(
params.surface_id, params.latency_info, gfx::SwapResult::SWAP_ACK);
- Send(new AcceleratedSurfaceMsg_BufferPresented(params.route_id, ack_params));
+ Send(new AcceleratedSurfaceMsg_BufferPresented(ack_params));
}
#endif
void GpuProcessHostUIShim::OnVideoMemoryUsageStatsReceived(
- const GPUVideoMemoryUsageStats& video_memory_usage_stats) {
+ const gpu::VideoMemoryUsageStats& video_memory_usage_stats) {
GpuDataManagerImpl::GetInstance()->UpdateVideoMemoryUsageStats(
video_memory_usage_stats);
}
diff --git a/chromium/content/browser/gpu/gpu_process_host_ui_shim.h b/chromium/content/browser/gpu/gpu_process_host_ui_shim.h
index 251ca2e7654..c0661bf835c 100644
--- a/chromium/content/browser/gpu/gpu_process_host_ui_shim.h
+++ b/chromium/content/browser/gpu/gpu_process_host_ui_shim.h
@@ -21,15 +21,11 @@
#include "base/threading/non_thread_safe.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
-#include "content/common/message_router.h"
-#include "content/public/common/gpu_memory_stats.h"
#include "gpu/config/gpu_info.h"
+#include "gpu/ipc/common/memory_stats.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
-
-#if defined(OS_MACOSX)
-struct GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params;
-#endif
+#include "ipc/message_router.h"
namespace ui {
class LatencyInfo;
@@ -43,7 +39,14 @@ namespace IPC {
class Message;
}
+namespace gpu {
+struct VideoMemoryUsageStats;
+}
+
namespace content {
+#if defined(OS_MACOSX)
+struct AcceleratedSurfaceBuffersSwappedParams;
+#endif
void RouteToGpuProcessHostUIShimTask(int host_id, const IPC::Message& msg);
class GpuProcessHostUIShim : public IPC::Listener,
@@ -98,10 +101,10 @@ class GpuProcessHostUIShim : public IPC::Listener,
#if defined(OS_MACOSX)
void OnAcceleratedSurfaceBuffersSwapped(
- const GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params& params);
+ const AcceleratedSurfaceBuffersSwappedParams& params);
#endif
void OnVideoMemoryUsageStatsReceived(
- const GPUVideoMemoryUsageStats& video_memory_usage_stats);
+ const gpu::VideoMemoryUsageStats& video_memory_usage_stats);
void OnAddSubscription(int32_t process_id, unsigned int target);
void OnRemoveSubscription(int32_t process_id, unsigned int target);
diff --git a/chromium/content/browser/gpu/gpu_surface_tracker.cc b/chromium/content/browser/gpu/gpu_surface_tracker.cc
index bd4e91dc261..60aed74c507 100644
--- a/chromium/content/browser/gpu/gpu_surface_tracker.cc
+++ b/chromium/content/browser/gpu/gpu_surface_tracker.cc
@@ -9,17 +9,19 @@
#if defined(OS_ANDROID)
#include <android/native_window_jni.h>
+#include "content/browser/android/child_process_launcher_android.h"
+#include "ui/gl/android/scoped_java_surface.h"
#endif // defined(OS_ANDROID)
namespace content {
GpuSurfaceTracker::GpuSurfaceTracker()
: next_surface_id_(1) {
- GpuSurfaceLookup::InitInstance(this);
+ gpu::GpuSurfaceLookup::InitInstance(this);
}
GpuSurfaceTracker::~GpuSurfaceTracker() {
- GpuSurfaceLookup::InitInstance(NULL);
+ gpu::GpuSurfaceLookup::InitInstance(NULL);
}
GpuSurfaceTracker* GpuSurfaceTracker::GetInstance() {
@@ -30,7 +32,7 @@ int GpuSurfaceTracker::AddSurfaceForNativeWidget(
gfx::AcceleratedWidget widget) {
base::AutoLock lock(lock_);
int surface_id = next_surface_id_++;
- surface_map_[surface_id] = SurfaceInfo(widget, gfx::GLSurfaceHandle());
+ surface_map_[surface_id] = widget;
return surface_id;
}
@@ -40,20 +42,24 @@ void GpuSurfaceTracker::RemoveSurface(int surface_id) {
surface_map_.erase(surface_id);
}
-void GpuSurfaceTracker::SetSurfaceHandle(int surface_id,
- const gfx::GLSurfaceHandle& handle) {
+gpu::SurfaceHandle GpuSurfaceTracker::GetSurfaceHandle(int surface_id) {
+ DCHECK(surface_id);
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
+#if DCHECK_IS_ON()
base::AutoLock lock(lock_);
DCHECK(surface_map_.find(surface_id) != surface_map_.end());
- SurfaceInfo& info = surface_map_[surface_id];
- info.handle = handle;
-}
-
-gfx::GLSurfaceHandle GpuSurfaceTracker::GetSurfaceHandle(int surface_id) {
+#endif
+ // On Mac and Android, we can't pass the AcceleratedWidget, which is
+ // process-local, so instead we pass the surface_id, so that we can look up
+ // the AcceleratedWidget on the GPU side or when we receive
+ // GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params.
+ return surface_id;
+#else
base::AutoLock lock(lock_);
SurfaceMap::iterator it = surface_map_.find(surface_id);
- if (it == surface_map_.end())
- return gfx::GLSurfaceHandle();
- return it->second.handle;
+ DCHECK(it != surface_map_.end());
+ return it->second;
+#endif
}
gfx::AcceleratedWidget GpuSurfaceTracker::AcquireNativeWidget(int surface_id) {
@@ -63,27 +69,22 @@ gfx::AcceleratedWidget GpuSurfaceTracker::AcquireNativeWidget(int surface_id) {
return gfx::kNullAcceleratedWidget;
#if defined(OS_ANDROID)
- if (it->second.native_widget != gfx::kNullAcceleratedWidget)
- ANativeWindow_acquire(it->second.native_widget);
+ if (it->second != gfx::kNullAcceleratedWidget)
+ ANativeWindow_acquire(it->second);
#endif // defined(OS_ANDROID)
- return it->second.native_widget;
+ return it->second;
}
+#if defined(OS_ANDROID)
+gfx::ScopedJavaSurface GpuSurfaceTracker::AcquireJavaSurface(int surface_id) {
+ return GetViewSurface(surface_id);
+}
+#endif
+
std::size_t GpuSurfaceTracker::GetSurfaceCount() {
base::AutoLock lock(lock_);
return surface_map_.size();
}
-GpuSurfaceTracker::SurfaceInfo::SurfaceInfo()
- : native_widget(gfx::kNullAcceleratedWidget) {}
-
-GpuSurfaceTracker::SurfaceInfo::SurfaceInfo(
- const gfx::AcceleratedWidget& native_widget,
- const gfx::GLSurfaceHandle& handle)
- : native_widget(native_widget), handle(handle) {}
-
-GpuSurfaceTracker::SurfaceInfo::~SurfaceInfo() { }
-
-
} // namespace content
diff --git a/chromium/content/browser/gpu/gpu_surface_tracker.h b/chromium/content/browser/gpu/gpu_surface_tracker.h
index 386eeeae7c4..dbaec68be5f 100644
--- a/chromium/content/browser/gpu/gpu_surface_tracker.h
+++ b/chromium/content/browser/gpu/gpu_surface_tracker.h
@@ -14,7 +14,8 @@
#include "base/memory/singleton.h"
#include "base/synchronization/lock.h"
#include "content/common/content_export.h"
-#include "content/common/gpu/gpu_surface_lookup.h"
+#include "gpu/ipc/common/gpu_surface_lookup.h"
+#include "gpu/ipc/common/surface_handle.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/native_widget_types.h"
@@ -29,12 +30,16 @@ namespace content {
// Note: The ID can exist before the actual native handle for the surface is
// created, for example to allow giving a reference to it to a renderer, so that
// it is unamibiguously identified.
-class CONTENT_EXPORT GpuSurfaceTracker : public GpuSurfaceLookup {
+class CONTENT_EXPORT GpuSurfaceTracker : public gpu::GpuSurfaceLookup {
public:
// GpuSurfaceLookup implementation:
// Returns the native widget associated with a given surface_id.
gfx::AcceleratedWidget AcquireNativeWidget(int surface_id) override;
+#if defined(OS_ANDROID)
+ gfx::ScopedJavaSurface AcquireJavaSurface(int surface_id) override;
+#endif
+
// Gets the global instance of the surface tracker.
static GpuSurfaceTracker* Get() { return GetInstance(); }
@@ -44,13 +49,9 @@ class CONTENT_EXPORT GpuSurfaceTracker : public GpuSurfaceLookup {
// Removes a given existing surface.
void RemoveSurface(int surface_id);
- // Sets the native handle for the given surface.
- // Note: This is an O(log N) lookup.
- void SetSurfaceHandle(int surface_id, const gfx::GLSurfaceHandle& handle);
-
// Gets the native handle for the given surface.
// Note: This is an O(log N) lookup.
- gfx::GLSurfaceHandle GetSurfaceHandle(int surface_id);
+ gpu::SurfaceHandle GetSurfaceHandle(int surface_id);
// Returns the number of surfaces currently registered with the tracker.
std::size_t GetSurfaceCount();
@@ -60,15 +61,7 @@ class CONTENT_EXPORT GpuSurfaceTracker : public GpuSurfaceLookup {
static GpuSurfaceTracker* GetInstance();
private:
- struct SurfaceInfo {
- SurfaceInfo();
- SurfaceInfo(const gfx::AcceleratedWidget& native_widget,
- const gfx::GLSurfaceHandle& handle);
- ~SurfaceInfo();
- gfx::AcceleratedWidget native_widget;
- gfx::GLSurfaceHandle handle;
- };
- typedef std::map<int, SurfaceInfo> SurfaceMap;
+ typedef std::map<int, gfx::AcceleratedWidget> SurfaceMap;
friend struct base::DefaultSingletonTraits<GpuSurfaceTracker>;
diff --git a/chromium/content/browser/histogram_controller.cc b/chromium/content/browser/histogram_controller.cc
index efefa964575..052bd7a5bd7 100644
--- a/chromium/content/browser/histogram_controller.cc
+++ b/chromium/content/browser/histogram_controller.cc
@@ -75,8 +75,7 @@ void HistogramController::GetHistogramDataFromChildProcesses(
for (BrowserChildProcessHostIterator iter; !iter.Done(); ++iter) {
const ChildProcessData& data = iter.GetData();
int type = data.process_type;
- if (type != PROCESS_TYPE_PLUGIN &&
- type != PROCESS_TYPE_GPU &&
+ if (type != PROCESS_TYPE_GPU &&
type != PROCESS_TYPE_PPAPI_PLUGIN &&
type != PROCESS_TYPE_PPAPI_BROKER) {
continue;
@@ -90,8 +89,10 @@ void HistogramController::GetHistogramDataFromChildProcesses(
continue;
++pending_processes;
- if (!iter.Send(new ChildProcessMsg_GetChildHistogramData(sequence_number)))
+ if (!iter.Send(new ChildProcessMsg_GetChildNonPersistentHistogramData(
+ sequence_number))) {
--pending_processes;
+ }
}
BrowserThread::PostTask(
@@ -113,7 +114,8 @@ void HistogramController::GetHistogramData(int sequence_number) {
!it.IsAtEnd(); it.Advance()) {
++pending_processes;
if (!it.GetCurrentValue()->Send(
- new ChildProcessMsg_GetChildHistogramData(sequence_number))) {
+ new ChildProcessMsg_GetChildNonPersistentHistogramData(
+ sequence_number))) {
--pending_processes;
}
}
diff --git a/chromium/content/browser/host_zoom_map_impl.cc b/chromium/content/browser/host_zoom_map_impl.cc
index cb394f81cbe..298a66a8fc4 100644
--- a/chromium/content/browser/host_zoom_map_impl.cc
+++ b/chromium/content/browser/host_zoom_map_impl.cc
@@ -24,7 +24,7 @@
#include "content/public/browser/storage_partition.h"
#include "content/public/common/page_zoom.h"
#include "content/public/common/url_constants.h"
-#include "net/base/net_util.h"
+#include "net/base/url_util.h"
namespace content {
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 e3816d4d37a..71ad4e1c102 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.cc
@@ -18,10 +18,12 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/trace_event/memory_dump_manager.h"
#include "build/build_config.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/indexed_db/indexed_db_blob_info.h"
#include "content/browser/indexed_db/indexed_db_class_factory.h"
+#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/browser/indexed_db/indexed_db_database_error.h"
#include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
#include "content/browser/indexed_db/indexed_db_metadata.h"
@@ -88,20 +90,8 @@ static std::string ComputeOriginIdentifier(const GURL& origin_url) {
return storage::GetIdentifierFromOrigin(origin_url) + "@1";
}
-static base::FilePath ComputeFileName(const GURL& origin_url) {
- return base::FilePath()
- .AppendASCII(storage::GetIdentifierFromOrigin(origin_url))
- .AddExtension(FILE_PATH_LITERAL(".indexeddb.leveldb"));
-}
-
-static base::FilePath ComputeBlobPath(const GURL& origin_url) {
- return base::FilePath()
- .AppendASCII(storage::GetIdentifierFromOrigin(origin_url))
- .AddExtension(FILE_PATH_LITERAL(".indexeddb.blob"));
-}
-
-static base::FilePath ComputeCorruptionFileName(const GURL& origin_url) {
- return ComputeFileName(origin_url)
+static FilePath ComputeCorruptionFileName(const GURL& origin_url) {
+ return IndexedDBContextImpl::GetLevelDBFileName(origin_url)
.Append(FILE_PATH_LITERAL("corruption_info.json"));
}
@@ -413,11 +403,10 @@ WARN_UNUSED_RESULT leveldb::Status IndexedDBBackingStore::SetUpMetadata() {
INTERNAL_CONSISTENCY_ERROR_UNTESTED(SET_UP_METADATA);
return InternalInconsistencyStatus();
}
- std::string int_version_key = DatabaseMetaDataKey::Encode(
- database_id, DatabaseMetaDataKey::USER_INT_VERSION);
- PutVarInt(transaction.get(),
- int_version_key,
- IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
+ std::string version_key = DatabaseMetaDataKey::Encode(
+ database_id, DatabaseMetaDataKey::USER_VERSION);
+ PutVarInt(transaction.get(), version_key,
+ IndexedDBDatabaseMetadata::DEFAULT_VERSION);
}
}
if (s.ok() && db_schema_version < 2) {
@@ -798,6 +787,8 @@ IndexedDBBackingStore::RecordIdentifier::RecordIdentifier()
IndexedDBBackingStore::RecordIdentifier::~RecordIdentifier() {}
IndexedDBBackingStore::Cursor::CursorOptions::CursorOptions() {}
+IndexedDBBackingStore::Cursor::CursorOptions::CursorOptions(
+ const CursorOptions& other) = default;
IndexedDBBackingStore::Cursor::CursorOptions::~CursorOptions() {}
// Values match entries in tools/metrics/histograms/histograms.xml
@@ -908,7 +899,7 @@ leveldb::Status IndexedDBBackingStore::DestroyBackingStore(
const base::FilePath& path_base,
const GURL& origin_url) {
const base::FilePath file_path =
- path_base.Append(ComputeFileName(origin_url));
+ path_base.Append(IndexedDBContextImpl::GetLevelDBFileName(origin_url));
DefaultLevelDBFactory leveldb_factory;
return leveldb_factory.DestroyLevelDB(file_path);
}
@@ -1012,10 +1003,10 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
return scoped_refptr<IndexedDBBackingStore>();
}
- const base::FilePath file_path =
- path_base.Append(ComputeFileName(origin_url));
- const base::FilePath blob_path =
- path_base.Append(ComputeBlobPath(origin_url));
+ const FilePath file_path =
+ path_base.Append(IndexedDBContextImpl::GetLevelDBFileName(origin_url));
+ const FilePath blob_path =
+ path_base.Append(IndexedDBContextImpl::GetBlobStoreFileName(origin_url));
if (IsPathTooLong(file_path)) {
*status = leveldb::Status::IOError("File path too long");
@@ -1105,6 +1096,11 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::Open(
origin_url);
}
+ base::trace_event::MemoryDumpManager::GetInstance()
+ ->RegisterDumpProviderWithSequencedTaskRunner(
+ db.get(), "IndexedDBBackingStore", task_runner,
+ base::trace_event::MemoryDumpProvider::Options());
+
scoped_refptr<IndexedDBBackingStore> backing_store =
Create(indexed_db_factory, origin_url, blob_path, request_context,
std::move(db), std::move(comparator), task_runner, status);
@@ -1149,6 +1145,10 @@ scoped_refptr<IndexedDBBackingStore> IndexedDBBackingStore::OpenInMemory(
return scoped_refptr<IndexedDBBackingStore>();
}
HistogramOpenStatus(INDEXED_DB_BACKING_STORE_OPEN_MEMORY_SUCCESS, origin_url);
+ base::trace_event::MemoryDumpManager::GetInstance()
+ ->RegisterDumpProviderWithSequencedTaskRunner(
+ db.get(), "IndexedDBBackingStore", task_runner,
+ base::trace_event::MemoryDumpProvider::Options());
return Create(NULL /* indexed_db_factory */, origin_url, base::FilePath(),
NULL /* request_context */, std::move(db),
@@ -1218,19 +1218,18 @@ std::vector<base::string16> IndexedDBBackingStore::GetDatabaseNames(
// Look up version by id.
bool found = false;
- int64_t database_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION;
+ int64_t database_version = IndexedDBDatabaseMetadata::DEFAULT_VERSION;
*s = GetVarInt(db_.get(),
DatabaseMetaDataKey::Encode(
- database_id, DatabaseMetaDataKey::USER_INT_VERSION),
- &database_version,
- &found);
+ database_id, DatabaseMetaDataKey::USER_VERSION),
+ &database_version, &found);
if (!s->ok() || !found) {
INTERNAL_READ_ERROR_UNTESTED(GET_DATABASE_NAMES);
continue;
}
// Ignore stale metadata from failed initial opens.
- if (database_version != IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION)
+ if (database_version != IndexedDBDatabaseMetadata::DEFAULT_VERSION)
found_names.push_back(database_name_key.database_name());
}
@@ -1255,11 +1254,9 @@ leveldb::Status IndexedDBBackingStore::GetIDBDatabaseMetaData(
if (!*found)
return leveldb::Status::OK();
- s = GetString(db_.get(),
- DatabaseMetaDataKey::Encode(metadata->id,
- DatabaseMetaDataKey::USER_VERSION),
- &metadata->version,
- found);
+ s = GetVarInt(db_.get(), DatabaseMetaDataKey::Encode(
+ metadata->id, DatabaseMetaDataKey::USER_VERSION),
+ &metadata->version, found);
if (!s.ok()) {
INTERNAL_READ_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
return s;
@@ -1269,22 +1266,8 @@ leveldb::Status IndexedDBBackingStore::GetIDBDatabaseMetaData(
return InternalInconsistencyStatus();
}
- s = GetVarInt(db_.get(),
- DatabaseMetaDataKey::Encode(
- metadata->id, DatabaseMetaDataKey::USER_INT_VERSION),
- &metadata->int_version,
- found);
- if (!s.ok()) {
- INTERNAL_READ_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
- return s;
- }
- if (!*found) {
- INTERNAL_CONSISTENCY_ERROR_UNTESTED(GET_IDBDATABASE_METADATA);
- return InternalInconsistencyStatus();
- }
-
- if (metadata->int_version == IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION)
- metadata->int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION;
+ if (metadata->version == IndexedDBDatabaseMetadata::DEFAULT_VERSION)
+ metadata->version = IndexedDBDatabaseMetadata::NO_VERSION;
s = GetMaxObjectStoreId(
db_.get(), metadata->id, &metadata->max_object_store_id);
@@ -1343,8 +1326,7 @@ WARN_UNUSED_RESULT static leveldb::Status GetNewDatabaseId(
leveldb::Status IndexedDBBackingStore::CreateIDBDatabaseMetaData(
const base::string16& name,
- const base::string16& version,
- int64_t int_version,
+ int64_t version,
int64_t* row_id) {
// TODO(jsbell): Don't persist metadata if open fails. http://crbug.com/395472
scoped_refptr<LevelDBTransaction> transaction =
@@ -1355,20 +1337,15 @@ leveldb::Status IndexedDBBackingStore::CreateIDBDatabaseMetaData(
return s;
DCHECK_GE(*row_id, 0);
- if (int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION)
- int_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION;
+ if (version == IndexedDBDatabaseMetadata::NO_VERSION)
+ version = IndexedDBDatabaseMetadata::DEFAULT_VERSION;
PutInt(transaction.get(),
DatabaseNameKey::Encode(origin_identifier_, name),
*row_id);
- PutString(
- transaction.get(),
- DatabaseMetaDataKey::Encode(*row_id, DatabaseMetaDataKey::USER_VERSION),
- version);
- PutVarInt(transaction.get(),
- DatabaseMetaDataKey::Encode(*row_id,
- DatabaseMetaDataKey::USER_INT_VERSION),
- int_version);
+ PutVarInt(transaction.get(), DatabaseMetaDataKey::Encode(
+ *row_id, DatabaseMetaDataKey::USER_VERSION),
+ version);
PutVarInt(
transaction.get(),
DatabaseMetaDataKey::Encode(
@@ -1384,14 +1361,14 @@ leveldb::Status IndexedDBBackingStore::CreateIDBDatabaseMetaData(
bool IndexedDBBackingStore::UpdateIDBDatabaseIntVersion(
IndexedDBBackingStore::Transaction* transaction,
int64_t row_id,
- int64_t int_version) {
- if (int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION)
- int_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION;
- DCHECK_GE(int_version, 0) << "int_version was " << int_version;
- PutVarInt(transaction->transaction(),
- DatabaseMetaDataKey::Encode(row_id,
- DatabaseMetaDataKey::USER_INT_VERSION),
- int_version);
+ int64_t version) {
+ if (version == IndexedDBDatabaseMetadata::NO_VERSION)
+ version = IndexedDBDatabaseMetadata::DEFAULT_VERSION;
+ DCHECK_GE(version, 0) << "version was " << version;
+ PutVarInt(
+ transaction->transaction(),
+ DatabaseMetaDataKey::Encode(row_id, DatabaseMetaDataKey::USER_VERSION),
+ version);
return true;
}
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 1ba22603a36..f1fecbdf193 100644
--- a/chromium/content/browser/indexed_db/indexed_db_backing_store.h
+++ b/chromium/content/browser/indexed_db/indexed_db_backing_store.h
@@ -287,6 +287,7 @@ class CONTENT_EXPORT IndexedDBBackingStore
struct CursorOptions {
CursorOptions();
+ CursorOptions(const CursorOptions& other);
~CursorOptions();
int64_t database_id;
int64_t object_store_id;
@@ -408,15 +409,13 @@ class CONTENT_EXPORT IndexedDBBackingStore
const base::string16& name,
IndexedDBDatabaseMetadata* metadata,
bool* success) WARN_UNUSED_RESULT;
- virtual leveldb::Status CreateIDBDatabaseMetaData(
- const base::string16& name,
- const base::string16& version,
- int64_t int_version,
- int64_t* row_id);
+ virtual leveldb::Status CreateIDBDatabaseMetaData(const base::string16& name,
+ int64_t version,
+ int64_t* row_id);
virtual bool UpdateIDBDatabaseIntVersion(
IndexedDBBackingStore::Transaction* transaction,
int64_t row_id,
- int64_t int_version);
+ int64_t version);
virtual leveldb::Status DeleteDatabase(const base::string16& name);
// Assumes caller has already closed the backing store.
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 93d281e036a..55acfa0151c 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
@@ -22,6 +22,7 @@
#include "content/browser/indexed_db/indexed_db_leveldb_coding.h"
#include "content/browser/indexed_db/indexed_db_value.h"
#include "content/browser/indexed_db/leveldb/leveldb_factory.h"
+#include "content/browser/quota/mock_quota_manager_proxy.h"
#include "content/public/test/mock_special_storage_policy.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/url_request/url_request_test_util.h"
@@ -235,12 +236,12 @@ class IndexedDBBackingStoreTest : public testing::Test {
const GURL origin("http://localhost:81");
task_runner_ = new base::TestSimpleTaskRunner();
special_storage_policy_ = new MockSpecialStoragePolicy();
+ quota_manager_proxy_ = new MockQuotaManagerProxy(nullptr, nullptr);
special_storage_policy_->SetAllUnlimited(true);
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- idb_context_ = new IndexedDBContextImpl(temp_dir_.path(),
- special_storage_policy_.get(),
- NULL,
- task_runner_.get());
+ idb_context_ = new IndexedDBContextImpl(
+ temp_dir_.path(), special_storage_policy_.get(),
+ quota_manager_proxy_.get(), task_runner_.get());
idb_factory_ = new TestIDBFactory(idb_context_.get());
backing_store_ =
idb_factory_->OpenBackingStoreForTest(origin, &url_request_context_);
@@ -268,6 +269,10 @@ class IndexedDBBackingStoreTest : public testing::Test {
m_key3 = IndexedDBKey(ASCIIToUTF16("key3"));
}
+ void TearDown() override {
+ quota_manager_proxy_->SimulateQuotaManagerDestroyed();
+ }
+
// This just checks the data that survive getting stored and recalled, e.g.
// the file path and UUID will change and thus aren't verified.
bool CheckBlobInfoMatches(const std::vector<IndexedDBBlobInfo>& reads) const {
@@ -345,6 +350,7 @@ class IndexedDBBackingStoreTest : public testing::Test {
base::ScopedTempDir temp_dir_;
scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
scoped_refptr<MockSpecialStoragePolicy> special_storage_policy_;
+ scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
scoped_refptr<IndexedDBContextImpl> idb_context_;
scoped_refptr<TestIDBFactory> idb_factory_;
net::TestURLRequestContext url_request_context_;
@@ -935,8 +941,7 @@ TEST_F(IndexedDBBackingStoreTest, InvalidIds) {
TEST_F(IndexedDBBackingStoreTest, CreateDatabase) {
const base::string16 database_name(ASCIIToUTF16("db1"));
int64_t database_id;
- const base::string16 version(ASCIIToUTF16("old_string_version"));
- const int64_t int_version = 9;
+ const int64_t version = 9;
const int64_t object_store_id = 99;
const base::string16 object_store_name(ASCIIToUTF16("object_store1"));
@@ -952,7 +957,7 @@ TEST_F(IndexedDBBackingStoreTest, CreateDatabase) {
{
leveldb::Status s = backing_store_->CreateIDBDatabaseMetaData(
- database_name, version, int_version, &database_id);
+ database_name, version, &database_id);
EXPECT_TRUE(s.ok());
EXPECT_GT(database_id, 0);
@@ -996,7 +1001,6 @@ TEST_F(IndexedDBBackingStoreTest, CreateDatabase) {
// database.name is not filled in by the implementation.
EXPECT_EQ(version, database.version);
- EXPECT_EQ(int_version, database.int_version);
EXPECT_EQ(database_id, database.id);
s = backing_store_->GetObjectStores(database.id, &database.object_stores);
@@ -1019,25 +1023,22 @@ TEST_F(IndexedDBBackingStoreTest, CreateDatabase) {
}
TEST_F(IndexedDBBackingStoreTest, GetDatabaseNames) {
- const base::string16 string_version(ASCIIToUTF16("string_version"));
-
const base::string16 db1_name(ASCIIToUTF16("db1"));
const int64_t db1_version = 1LL;
int64_t db1_id;
- // Database records with DEFAULT_INT_VERSION represent stale data,
+ // Database records with DEFAULT_VERSION represent stale data,
// and should not be enumerated.
const base::string16 db2_name(ASCIIToUTF16("db2"));
- const int64_t db2_version = IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION;
+ const int64_t db2_version = IndexedDBDatabaseMetadata::DEFAULT_VERSION;
int64_t db2_id;
- leveldb::Status s = backing_store_->CreateIDBDatabaseMetaData(
- db1_name, string_version, db1_version, &db1_id);
+ leveldb::Status s =
+ backing_store_->CreateIDBDatabaseMetaData(db1_name, db1_version, &db1_id);
EXPECT_TRUE(s.ok());
EXPECT_GT(db1_id, 0LL);
- s = backing_store_->CreateIDBDatabaseMetaData(
- db2_name, string_version, db2_version, &db2_id);
+ s = backing_store_->CreateIDBDatabaseMetaData(db2_name, db2_version, &db2_id);
EXPECT_TRUE(s.ok());
EXPECT_GT(db2_id, db1_id);
diff --git a/chromium/content/browser/indexed_db/indexed_db_browsertest.cc b/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
index e659d96a0db..9a53bc6da05 100644
--- a/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_browsertest.cc
@@ -201,7 +201,13 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CursorTestIncognito) {
true /* incognito */);
}
-IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CursorPrefetch) {
+// crbug.com/513787
+#if defined(ANDROID)
+#define MAYBE_CursorPrefetch DISABLED_CursorPrefetch
+#else
+#define MAYBE_CursorPrefetch CursorPrefetch
+#endif
+IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, MAYBE_CursorPrefetch) {
SimpleTest(GetTestUrl("indexeddb", "cursor_prefetch.html"));
}
@@ -461,14 +467,9 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithGCExposed, DISABLED_BlobDidAck) {
EXPECT_EQ(0UL, blob_context->context()->blob_count());
}
-// Very flaky on Linux. See crbug.com/459835.
-#if defined(OS_LINUX)
-#define MAYBE_BlobDidAckPrefetch DISABLED_BlobDidAckPrefetch
-#else
-#define MAYBE_BlobDidAckPrefetch BlobDidAckPrefetch
-#endif
+// Flaky. See crbug.com/459835.
IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTestWithGCExposed,
- MAYBE_BlobDidAckPrefetch) {
+ DISABLED_BlobDidAckPrefetch) {
SimpleTest(GetTestUrl("indexeddb", "blob_did_ack_prefetch.html"));
// Wait for idle so that the blob ack has time to be received/processed by
// the browser process.
@@ -632,12 +633,14 @@ static scoped_ptr<net::test_server::HttpResponse> CorruptDBRequestHandler(
std::string key = net::UnescapeURLComponent(
escaped_key,
net::UnescapeRule::NORMAL | net::UnescapeRule::SPACES |
- net::UnescapeRule::URL_SPECIAL_CHARS);
+ net::UnescapeRule::PATH_SEPARATORS |
+ net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS);
std::string value = net::UnescapeURLComponent(
escaped_value,
net::UnescapeRule::NORMAL | net::UnescapeRule::SPACES |
- net::UnescapeRule::URL_SPECIAL_CHARS);
+ net::UnescapeRule::PATH_SEPARATORS |
+ net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS);
if (key == "method")
fail_method = value;
diff --git a/chromium/content/browser/indexed_db/indexed_db_callbacks.cc b/chromium/content/browser/indexed_db/indexed_db_callbacks.cc
index 6a5ca73916e..a695c4b89c5 100644
--- a/chromium/content/browser/indexed_db/indexed_db_callbacks.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_callbacks.cc
@@ -251,9 +251,8 @@ static bool CreateAllBlobs(
return false;
for (i = 0; i < blob_info.size(); ++i) {
(*blob_or_file_info)[i].uuid =
- CreateBlobData(blob_info[i],
- dispatcher_host,
- dispatcher_host->Context()->TaskRunner());
+ CreateBlobData(blob_info[i], dispatcher_host,
+ dispatcher_host->context()->TaskRunner());
}
return true;
}
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 582f16fc6d7..cbe6016c049 100644
--- a/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_context_impl.cc
@@ -116,9 +116,7 @@ IndexedDBContextImpl::IndexedDBContextImpl(
IDB_TRACE("init");
if (!data_path.empty())
data_path_ = data_path.Append(kIndexedDBDirectory);
- if (quota_manager_proxy) {
- quota_manager_proxy->RegisterClient(new IndexedDBQuotaClient(this));
- }
+ quota_manager_proxy->RegisterClient(new IndexedDBQuotaClient(this));
}
IndexedDBFactory* IndexedDBContextImpl::GetIDBFactory() {
@@ -138,6 +136,12 @@ std::vector<GURL> IndexedDBContextImpl::GetAllOrigins() {
return std::vector<GURL>(origins_set->begin(), origins_set->end());
}
+bool IndexedDBContextImpl::HasOrigin(const GURL& origin) {
+ DCHECK(TaskRunner()->RunsTasksOnCurrentThread());
+ std::set<GURL>* set = GetOriginSet();
+ return set->find(origin) != set->end();
+}
+
std::vector<IndexedDBInfo> IndexedDBContextImpl::GetAllOriginsInfo() {
DCHECK(TaskRunner()->RunsTasksOnCurrentThread());
std::vector<GURL> origins = GetAllOrigins();
@@ -277,9 +281,8 @@ base::ListValue* IndexedDBContextImpl::GetAllOriginsDetails() {
int IndexedDBContextImpl::GetOriginBlobFileCount(const GURL& origin_url) {
DCHECK(TaskRunner()->RunsTasksOnCurrentThread());
int count = 0;
- base::FileEnumerator file_enumerator(
- GetBlobPath(storage::GetIdentifierFromOrigin(origin_url)), true,
- base::FileEnumerator::FILES);
+ base::FileEnumerator file_enumerator(GetBlobStorePath(origin_url), true,
+ base::FileEnumerator::FILES);
for (base::FilePath file_path = file_enumerator.Next(); !file_path.empty();
file_path = file_enumerator.Next()) {
count++;
@@ -289,7 +292,7 @@ int IndexedDBContextImpl::GetOriginBlobFileCount(const GURL& origin_url) {
int64_t IndexedDBContextImpl::GetOriginDiskUsage(const GURL& origin_url) {
DCHECK(TaskRunner()->RunsTasksOnCurrentThread());
- if (data_path_.empty() || !IsInOriginSet(origin_url))
+ if (data_path_.empty() || !HasOrigin(origin_url))
return 0;
EnsureDiskUsageCacheInitialized(origin_url);
return origin_size_map_[origin_url];
@@ -297,7 +300,7 @@ int64_t IndexedDBContextImpl::GetOriginDiskUsage(const GURL& origin_url) {
base::Time IndexedDBContextImpl::GetOriginLastModified(const GURL& origin_url) {
DCHECK(TaskRunner()->RunsTasksOnCurrentThread());
- if (data_path_.empty() || !IsInOriginSet(origin_url))
+ if (data_path_.empty() || !HasOrigin(origin_url))
return base::Time();
base::FilePath idb_directory = GetLevelDBPath(origin_url);
base::File::Info file_info;
@@ -309,7 +312,7 @@ base::Time IndexedDBContextImpl::GetOriginLastModified(const GURL& origin_url) {
void IndexedDBContextImpl::DeleteForOrigin(const GURL& origin_url) {
DCHECK(TaskRunner()->RunsTasksOnCurrentThread());
ForceClose(origin_url, FORCE_CLOSE_DELETE_ORIGIN);
- if (data_path_.empty() || !IsInOriginSet(origin_url))
+ if (data_path_.empty() || !HasOrigin(origin_url))
return;
base::FilePath idb_directory = GetLevelDBPath(origin_url);
@@ -325,13 +328,11 @@ void IndexedDBContextImpl::DeleteForOrigin(const GURL& origin_url) {
const bool kNonRecursive = false;
base::DeleteFile(idb_directory, kNonRecursive);
}
- base::DeleteFile(GetBlobPath(storage::GetIdentifierFromOrigin(origin_url)),
- true /* recursive */);
+ base::DeleteFile(GetBlobStorePath(origin_url), true /* recursive */);
QueryDiskAndUpdateQuotaUsage(origin_url);
if (s.ok()) {
RemoveFromOriginSet(origin_url);
origin_size_map_.erase(origin_url);
- space_available_map_.erase(origin_url);
}
}
@@ -339,14 +340,13 @@ void IndexedDBContextImpl::CopyOriginData(const GURL& origin_url,
IndexedDBContext* dest_context) {
DCHECK(TaskRunner()->RunsTasksOnCurrentThread());
- if (data_path_.empty() || !IsInOriginSet(origin_url))
+ if (data_path_.empty() || !HasOrigin(origin_url))
return;
IndexedDBContextImpl* dest_context_impl =
static_cast<IndexedDBContextImpl*>(dest_context);
ForceClose(origin_url, FORCE_CLOSE_COPY_ORIGIN);
- std::string origin_id = storage::GetIdentifierFromOrigin(origin_url);
// Make sure we're not about to delete our own database.
CHECK_NE(dest_context_impl->data_path().value(), data_path().value());
@@ -375,7 +375,7 @@ void IndexedDBContextImpl::ForceClose(const GURL origin_url,
reason,
FORCE_CLOSE_REASON_MAX);
- if (data_path_.empty() || !IsInOriginSet(origin_url))
+ if (data_path_.empty() || !HasOrigin(origin_url))
return;
if (factory_.get())
@@ -385,7 +385,7 @@ void IndexedDBContextImpl::ForceClose(const GURL origin_url,
size_t IndexedDBContextImpl::GetConnectionCount(const GURL& origin_url) {
DCHECK(TaskRunner()->RunsTasksOnCurrentThread());
- if (data_path_.empty() || !IsInOriginSet(origin_url))
+ if (data_path_.empty() || !HasOrigin(origin_url))
return 0;
if (!factory_.get())
@@ -394,24 +394,17 @@ size_t IndexedDBContextImpl::GetConnectionCount(const GURL& origin_url) {
return factory_->GetConnectionCount(origin_url);
}
-base::FilePath IndexedDBContextImpl::GetLevelDBPath(
- const GURL& origin_url) const {
- std::string origin_id = storage::GetIdentifierFromOrigin(origin_url);
- return GetLevelDBPath(origin_id);
-}
-
std::vector<base::FilePath> IndexedDBContextImpl::GetStoragePaths(
const GURL& origin_url) const {
- std::string origin_id = storage::GetIdentifierFromOrigin(origin_url);
std::vector<base::FilePath> paths;
- paths.push_back(GetLevelDBPath(origin_id));
- paths.push_back(GetBlobPath(origin_id));
+ paths.push_back(GetLevelDBPath(origin_url));
+ paths.push_back(GetBlobStorePath(origin_url));
return paths;
}
base::FilePath IndexedDBContextImpl::GetFilePathForTesting(
- const std::string& origin_id) const {
- return GetLevelDBPath(origin_id);
+ const GURL& origin_url) const {
+ return GetLevelDBPath(origin_url);
}
void IndexedDBContextImpl::SetTaskRunnerForTesting(
@@ -423,30 +416,23 @@ void IndexedDBContextImpl::SetTaskRunnerForTesting(
void IndexedDBContextImpl::ConnectionOpened(const GURL& origin_url,
IndexedDBConnection* connection) {
DCHECK(TaskRunner()->RunsTasksOnCurrentThread());
- if (quota_manager_proxy()) {
- quota_manager_proxy()->NotifyStorageAccessed(
- storage::QuotaClient::kIndexedDatabase,
- origin_url,
- storage::kStorageTypeTemporary);
- }
+ quota_manager_proxy()->NotifyStorageAccessed(
+ storage::QuotaClient::kIndexedDatabase, origin_url,
+ storage::kStorageTypeTemporary);
if (AddToOriginSet(origin_url)) {
// A newly created db, notify the quota system.
QueryDiskAndUpdateQuotaUsage(origin_url);
} else {
EnsureDiskUsageCacheInitialized(origin_url);
}
- QueryAvailableQuota(origin_url);
}
void IndexedDBContextImpl::ConnectionClosed(const GURL& origin_url,
IndexedDBConnection* connection) {
DCHECK(TaskRunner()->RunsTasksOnCurrentThread());
- if (quota_manager_proxy()) {
- quota_manager_proxy()->NotifyStorageAccessed(
- storage::QuotaClient::kIndexedDatabase,
- origin_url,
- storage::kStorageTypeTemporary);
- }
+ quota_manager_proxy()->NotifyStorageAccessed(
+ storage::QuotaClient::kIndexedDatabase, origin_url,
+ storage::kStorageTypeTemporary);
if (factory_.get() && factory_->GetConnectionCount(origin_url) == 0)
QueryDiskAndUpdateQuotaUsage(origin_url);
}
@@ -454,32 +440,11 @@ void IndexedDBContextImpl::ConnectionClosed(const GURL& origin_url,
void IndexedDBContextImpl::TransactionComplete(const GURL& origin_url) {
DCHECK(!factory_.get() || factory_->GetConnectionCount(origin_url) > 0);
QueryDiskAndUpdateQuotaUsage(origin_url);
- QueryAvailableQuota(origin_url);
}
void IndexedDBContextImpl::DatabaseDeleted(const GURL& origin_url) {
AddToOriginSet(origin_url);
QueryDiskAndUpdateQuotaUsage(origin_url);
- QueryAvailableQuota(origin_url);
-}
-
-bool IndexedDBContextImpl::WouldBeOverQuota(const GURL& origin_url,
- int64_t additional_bytes) {
- if (space_available_map_.find(origin_url) == space_available_map_.end()) {
- // We haven't heard back from the QuotaManager yet, just let it through.
- return false;
- }
- bool over_quota = additional_bytes > space_available_map_[origin_url];
- return over_quota;
-}
-
-bool IndexedDBContextImpl::IsOverQuota(const GURL& origin_url) {
- const int kOneAdditionalByte = 1;
- return WouldBeOverQuota(origin_url, kOneAdditionalByte);
-}
-
-storage::QuotaManagerProxy* IndexedDBContextImpl::quota_manager_proxy() {
- return quota_manager_proxy_.get();
}
IndexedDBContextImpl::~IndexedDBContextImpl() {
@@ -509,18 +474,36 @@ IndexedDBContextImpl::~IndexedDBContextImpl() {
&ClearSessionOnlyOrigins, data_path_, special_storage_policy_));
}
-base::FilePath IndexedDBContextImpl::GetBlobPath(
- const std::string& origin_id) const {
- DCHECK(!data_path_.empty());
- return data_path_.AppendASCII(origin_id).AddExtension(kIndexedDBExtension)
+// static
+base::FilePath IndexedDBContextImpl::GetBlobStoreFileName(
+ const GURL& origin_url) {
+ std::string origin_id = storage::GetIdentifierFromOrigin(origin_url);
+ return base::FilePath()
+ .AppendASCII(origin_id)
+ .AddExtension(kIndexedDBExtension)
.AddExtension(kBlobExtension);
}
+// static
+base::FilePath IndexedDBContextImpl::GetLevelDBFileName(
+ const GURL& origin_url) {
+ std::string origin_id = storage::GetIdentifierFromOrigin(origin_url);
+ return base::FilePath()
+ .AppendASCII(origin_id)
+ .AddExtension(kIndexedDBExtension)
+ .AddExtension(kLevelDBExtension);
+}
+
+base::FilePath IndexedDBContextImpl::GetBlobStorePath(
+ const GURL& origin_url) const {
+ DCHECK(!data_path_.empty());
+ return data_path_.Append(GetBlobStoreFileName(origin_url));
+}
+
base::FilePath IndexedDBContextImpl::GetLevelDBPath(
- const std::string& origin_id) const {
+ const GURL& origin_url) const {
DCHECK(!data_path_.empty());
- return data_path_.AppendASCII(origin_id).AddExtension(kIndexedDBExtension)
- .AddExtension(kLevelDBExtension);
+ return data_path_.Append(GetLevelDBFileName(origin_url));
}
int64_t IndexedDBContextImpl::ReadUsageFromDisk(const GURL& origin_url) const {
@@ -545,69 +528,12 @@ void IndexedDBContextImpl::QueryDiskAndUpdateQuotaUsage(
int64_t difference = current_disk_usage - former_disk_usage;
if (difference) {
origin_size_map_[origin_url] = current_disk_usage;
- // quota_manager_proxy() is NULL in unit tests.
- if (quota_manager_proxy()) {
- quota_manager_proxy()->NotifyStorageModified(
- storage::QuotaClient::kIndexedDatabase,
- origin_url,
- storage::kStorageTypeTemporary,
- difference);
- }
+ quota_manager_proxy()->NotifyStorageModified(
+ storage::QuotaClient::kIndexedDatabase, origin_url,
+ storage::kStorageTypeTemporary, difference);
}
}
-void IndexedDBContextImpl::GotUsageAndQuota(const GURL& origin_url,
- storage::QuotaStatusCode status,
- int64_t usage,
- int64_t quota) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(status == storage::kQuotaStatusOk ||
- status == storage::kQuotaErrorAbort)
- << "status was " << status;
- if (status == storage::kQuotaErrorAbort) {
- // We seem to no longer care to wait around for the answer.
- return;
- }
- TaskRunner()->PostTask(FROM_HERE,
- base::Bind(&IndexedDBContextImpl::GotUpdatedQuota,
- this,
- origin_url,
- usage,
- quota));
-}
-
-void IndexedDBContextImpl::GotUpdatedQuota(const GURL& origin_url,
- int64_t usage,
- int64_t quota) {
- DCHECK(TaskRunner()->RunsTasksOnCurrentThread());
- space_available_map_[origin_url] = quota - usage;
-}
-
-void IndexedDBContextImpl::QueryAvailableQuota(const GURL& origin_url) {
- if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- DCHECK(TaskRunner()->RunsTasksOnCurrentThread());
- if (quota_manager_proxy()) {
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(
- &IndexedDBContextImpl::QueryAvailableQuota, this, origin_url));
- }
- return;
- }
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (!quota_manager_proxy() || !quota_manager_proxy()->quota_manager())
- return;
-
- // crbug.com/349708
- TRACE_EVENT0("io", "IndexedDBContextImpl::QueryAvailableQuota");
-
- quota_manager_proxy()->quota_manager()->GetUsageAndQuota(
- origin_url,
- storage::kStorageTypeTemporary,
- base::Bind(&IndexedDBContextImpl::GotUsageAndQuota, this, origin_url));
-}
-
std::set<GURL>* IndexedDBContextImpl::GetOriginSet() {
if (!origin_set_) {
std::vector<GURL> origins;
@@ -620,7 +546,6 @@ std::set<GURL>* IndexedDBContextImpl::GetOriginSet() {
void IndexedDBContextImpl::ResetCaches() {
origin_set_.reset();
origin_size_map_.clear();
- space_available_map_.clear();
}
base::SequencedTaskRunner* IndexedDBContextImpl::TaskRunner() const {
diff --git a/chromium/content/browser/indexed_db/indexed_db_context_impl.h b/chromium/content/browser/indexed_db/indexed_db_context_impl.h
index d175ce46a65..608e0f23394 100644
--- a/chromium/content/browser/indexed_db/indexed_db_context_impl.h
+++ b/chromium/content/browser/indexed_db/indexed_db_context_impl.h
@@ -74,8 +74,7 @@ class CONTENT_EXPORT IndexedDBContextImpl
void DeleteForOrigin(const GURL& origin_url) override;
void CopyOriginData(const GURL& origin_url,
IndexedDBContext* dest_context) override;
- base::FilePath GetFilePathForTesting(
- const std::string& origin_id) const override;
+ base::FilePath GetFilePathForTesting(const GURL& origin_url) const override;
void SetTaskRunnerForTesting(base::SequencedTaskRunner* task_runner) override;
// Methods called by IndexedDBDispatcherHost for quota support.
@@ -83,13 +82,20 @@ class CONTENT_EXPORT IndexedDBContextImpl
void ConnectionClosed(const GURL& origin_url, IndexedDBConnection* db);
void TransactionComplete(const GURL& origin_url);
void DatabaseDeleted(const GURL& origin_url);
- bool WouldBeOverQuota(const GURL& origin_url, int64_t additional_bytes);
- bool IsOverQuota(const GURL& origin_url);
- storage::QuotaManagerProxy* quota_manager_proxy();
+ static base::FilePath GetBlobStoreFileName(const GURL& origin_url);
+ static base::FilePath GetLevelDBFileName(const GURL& origin_url);
+ // Will be null in unit tests.
+ storage::QuotaManagerProxy* quota_manager_proxy() const {
+ return quota_manager_proxy_.get();
+ }
+
+ // Returns a list of all origins with backing stores.
std::vector<GURL> GetAllOrigins();
- base::Time GetOriginLastModified(const GURL& origin_url);
+ bool HasOrigin(const GURL& origin);
+
+ // Used by IndexedDBInternalsUI to populate internals page.
base::ListValue* GetAllOriginsDetails();
// ForceClose takes a value rather than a reference since it may release the
@@ -100,10 +106,6 @@ class CONTENT_EXPORT IndexedDBContextImpl
std::vector<base::FilePath> GetStoragePaths(const GURL& origin_url) const;
base::FilePath data_path() const { return data_path_; }
- bool IsInOriginSet(const GURL& origin_url) {
- std::set<GURL>* set = GetOriginSet();
- return set->find(origin_url) != set->end();
- }
size_t GetConnectionCount(const GURL& origin_url);
int GetOriginBlobFileCount(const GURL& origin_url);
@@ -127,18 +129,13 @@ class CONTENT_EXPORT IndexedDBContextImpl
typedef std::map<GURL, int64_t> OriginToSizeMap;
class IndexedDBGetUsageAndQuotaCallback;
- base::FilePath GetBlobPath(const std::string& origin_id) const;
+ base::FilePath GetBlobStorePath(const GURL& origin_url) const;
base::FilePath GetLevelDBPath(const GURL& origin_url) const;
- base::FilePath GetLevelDBPath(const std::string& origin_id) const;
+
int64_t ReadUsageFromDisk(const GURL& origin_url) const;
void EnsureDiskUsageCacheInitialized(const GURL& origin_url);
void QueryDiskAndUpdateQuotaUsage(const GURL& origin_url);
- void GotUsageAndQuota(const GURL& origin_url,
- storage::QuotaStatusCode,
- int64_t usage,
- int64_t quota);
- void GotUpdatedQuota(const GURL& origin_url, int64_t usage, int64_t quota);
- void QueryAvailableQuota(const GURL& origin_url);
+ base::Time GetOriginLastModified(const GURL& origin_url);
std::set<GURL>* GetOriginSet();
bool AddToOriginSet(const GURL& origin_url) {
@@ -160,7 +157,6 @@ class CONTENT_EXPORT IndexedDBContextImpl
scoped_refptr<base::SequencedTaskRunner> task_runner_;
scoped_ptr<std::set<GURL> > origin_set_;
OriginToSizeMap origin_size_map_;
- OriginToSizeMap space_available_map_;
DISALLOW_COPY_AND_ASSIGN(IndexedDBContextImpl);
};
diff --git a/chromium/content/browser/indexed_db/indexed_db_database.cc b/chromium/content/browser/indexed_db/indexed_db_database.cc
index d90af34cae2..a877a7bac28 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_database.cc
@@ -143,10 +143,6 @@ scoped_refptr<IndexedDBDatabase> IndexedDBDatabase::Create(
return NULL;
}
-namespace {
-const base::string16::value_type kNoStringVersion[] = {0};
-}
-
IndexedDBDatabase::IndexedDBDatabase(const base::string16& name,
IndexedDBBackingStore* backing_store,
IndexedDBFactory* factory,
@@ -154,8 +150,7 @@ IndexedDBDatabase::IndexedDBDatabase(const base::string16& name,
: backing_store_(backing_store),
metadata_(name,
kInvalidId,
- kNoStringVersion,
- IndexedDBDatabaseMetadata::NO_INT_VERSION,
+ IndexedDBDatabaseMetadata::NO_VERSION,
kInvalidId),
identifier_(unique_identifier),
factory_(factory) {
@@ -221,7 +216,7 @@ leveldb::Status IndexedDBDatabase::OpenInternal() {
&metadata_.object_stores);
return backing_store_->CreateIDBDatabaseMetaData(
- metadata_.name, metadata_.version, metadata_.int_version, &metadata_.id);
+ metadata_.name, metadata_.version, &metadata_.id);
}
IndexedDBDatabase::~IndexedDBDatabase() {
@@ -1521,7 +1516,7 @@ void IndexedDBDatabase::VersionChangeOperation(
IndexedDBTransaction* transaction) {
IDB_TRACE1(
"IndexedDBDatabase::VersionChangeOperation", "txn.id", transaction->id());
- int64_t old_version = metadata_.int_version;
+ int64_t old_version = metadata_.version;
DCHECK_GT(version, old_version);
if (!backing_store_->UpdateIDBDatabaseIntVersion(
@@ -1537,12 +1532,9 @@ void IndexedDBDatabase::VersionChangeOperation(
}
transaction->ScheduleAbortTask(
- base::Bind(&IndexedDBDatabase::VersionChangeAbortOperation,
- this,
- metadata_.version,
- metadata_.int_version));
- metadata_.int_version = version;
- metadata_.version = kNoStringVersion;
+ base::Bind(&IndexedDBDatabase::VersionChangeAbortOperation, this,
+ metadata_.version));
+ metadata_.version = version;
DCHECK(!pending_second_half_open_);
pending_second_half_open_.reset(
@@ -1560,7 +1552,7 @@ void IndexedDBDatabase::TransactionFinished(IndexedDBTransaction* transaction,
if (transaction->mode() == blink::WebIDBTransactionModeVersionChange) {
if (pending_second_half_open_) {
if (committed) {
- DCHECK_EQ(pending_second_half_open_->version(), metadata_.int_version);
+ DCHECK_EQ(pending_second_half_open_->version(), metadata_.version);
DCHECK(metadata_.id != kInvalidId);
// Connection was already minted for OnUpgradeNeeded callback.
@@ -1616,7 +1608,7 @@ size_t IndexedDBDatabase::PendingDeleteCount() const {
void IndexedDBDatabase::ProcessPendingCalls() {
if (pending_run_version_change_transaction_call_ && ConnectionCount() == 1) {
DCHECK(pending_run_version_change_transaction_call_->version() >
- metadata_.int_version);
+ metadata_.version);
scoped_ptr<PendingUpgradeCall> pending_call =
std::move(pending_run_version_change_transaction_call_);
RunVersionChangeTransactionFinal(pending_call->callbacks(),
@@ -1709,11 +1701,10 @@ void IndexedDBDatabase::OpenConnection(
// The database was deleted then immediately re-opened; OpenInternal()
// recreates it in the backing store.
if (OpenInternal().ok()) {
- DCHECK_EQ(IndexedDBDatabaseMetadata::NO_INT_VERSION,
- metadata_.int_version);
+ DCHECK_EQ(IndexedDBDatabaseMetadata::NO_VERSION, metadata_.version);
} else {
base::string16 message;
- if (connection.version == IndexedDBDatabaseMetadata::NO_INT_VERSION) {
+ if (connection.version == IndexedDBDatabaseMetadata::NO_VERSION) {
message = ASCIIToUTF16(
"Internal error opening database with no version specified.");
} else {
@@ -1730,12 +1721,11 @@ void IndexedDBDatabase::OpenConnection(
// We infer that the database didn't exist from its lack of either type of
// version.
bool is_new_database =
- metadata_.version == kNoStringVersion &&
- metadata_.int_version == IndexedDBDatabaseMetadata::NO_INT_VERSION;
+ metadata_.version == IndexedDBDatabaseMetadata::NO_VERSION;
- if (connection.version == IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION) {
+ if (connection.version == IndexedDBDatabaseMetadata::DEFAULT_VERSION) {
// For unit tests only - skip upgrade steps. Calling from script with
- // DEFAULT_INT_VERSION throws exception.
+ // DEFAULT_VERSION throws exception.
// TODO(jsbell): DCHECK that not in unit tests.
DCHECK(is_new_database);
connection.callbacks->OnSuccess(
@@ -1747,7 +1737,7 @@ void IndexedDBDatabase::OpenConnection(
// We may need to change the version.
int64_t local_version = connection.version;
- if (local_version == IndexedDBDatabaseMetadata::NO_INT_VERSION) {
+ if (local_version == IndexedDBDatabaseMetadata::NO_VERSION) {
if (!is_new_database) {
connection.callbacks->OnSuccess(
CreateConnection(connection.database_callbacks,
@@ -1760,7 +1750,7 @@ void IndexedDBDatabase::OpenConnection(
local_version = 1;
}
- if (local_version > metadata_.int_version) {
+ if (local_version > metadata_.version) {
RunVersionChangeTransaction(connection.callbacks,
CreateConnection(connection.database_callbacks,
connection.child_process_id),
@@ -1768,16 +1758,16 @@ void IndexedDBDatabase::OpenConnection(
local_version);
return;
}
- if (local_version < metadata_.int_version) {
+ if (local_version < metadata_.version) {
connection.callbacks->OnError(IndexedDBDatabaseError(
blink::WebIDBDatabaseExceptionVersionError,
ASCIIToUTF16("The requested version (") +
Int64ToString16(local_version) +
ASCIIToUTF16(") is less than the existing version (") +
- Int64ToString16(metadata_.int_version) + ASCIIToUTF16(").")));
+ Int64ToString16(metadata_.version) + ASCIIToUTF16(").")));
return;
}
- DCHECK_EQ(local_version, metadata_.int_version);
+ DCHECK_EQ(local_version, metadata_.version);
connection.callbacks->OnSuccess(
CreateConnection(connection.database_callbacks,
connection.child_process_id),
@@ -1797,7 +1787,7 @@ void IndexedDBDatabase::RunVersionChangeTransaction(
// close_pending set.
for (const auto* iter : connections_) {
if (iter != connection.get()) {
- iter->callbacks()->OnVersionChange(metadata_.int_version,
+ iter->callbacks()->OnVersionChange(metadata_.version,
requested_version);
}
}
@@ -1841,7 +1831,7 @@ void IndexedDBDatabase::DeleteDatabase(
// Front end ensures the event is not fired at connections that have
// close_pending set.
connection->callbacks()->OnVersionChange(
- metadata_.int_version, IndexedDBDatabaseMetadata::NO_INT_VERSION);
+ metadata_.version, IndexedDBDatabaseMetadata::NO_VERSION);
}
// OnBlocked will be fired at the request when one of the other
// connections acks that the OnVersionChange was ignored.
@@ -1872,10 +1862,9 @@ void IndexedDBDatabase::DeleteDatabaseFinal(
}
return;
}
- int64_t old_version = metadata_.int_version;
- metadata_.version = kNoStringVersion;
+ int64_t old_version = metadata_.version;
metadata_.id = kInvalidId;
- metadata_.int_version = IndexedDBDatabaseMetadata::NO_INT_VERSION;
+ metadata_.version = IndexedDBDatabaseMetadata::NO_VERSION;
metadata_.object_stores.clear();
callbacks->OnSuccess(old_version);
factory_->DatabaseDeleted(identifier_);
@@ -1895,10 +1884,10 @@ void IndexedDBDatabase::ForceClose() {
void IndexedDBDatabase::VersionChangeIgnored() {
if (pending_run_version_change_transaction_call_)
pending_run_version_change_transaction_call_->callbacks()->OnBlocked(
- metadata_.int_version);
+ metadata_.version);
for (const auto& pending_delete_call : pending_delete_calls_)
- pending_delete_call->callbacks()->OnBlocked(metadata_.int_version);
+ pending_delete_call->callbacks()->OnBlocked(metadata_.version);
}
@@ -1965,13 +1954,11 @@ void IndexedDBDatabase::DeleteObjectStoreAbortOperation(
}
void IndexedDBDatabase::VersionChangeAbortOperation(
- const base::string16& previous_version,
- int64_t previous_int_version,
+ int64_t previous_version,
IndexedDBTransaction* transaction) {
DCHECK(!transaction);
IDB_TRACE("IndexedDBDatabase::VersionChangeAbortOperation");
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 0049e6c20ee..207c1f9c41a 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database.h
+++ b/chromium/content/browser/indexed_db/indexed_db_database.h
@@ -193,8 +193,7 @@ class CONTENT_EXPORT IndexedDBDatabase
scoped_refptr<IndexedDBCallbacks> callbacks,
scoped_ptr<IndexedDBConnection> connection,
IndexedDBTransaction* transaction);
- void VersionChangeAbortOperation(const base::string16& previous_version,
- int64_t previous_int_version,
+ void VersionChangeAbortOperation(int64_t previous_version,
IndexedDBTransaction* transaction);
void DeleteIndexOperation(int64_t object_store_id,
int64_t index_id,
diff --git a/chromium/content/browser/indexed_db/indexed_db_database_callbacks.cc b/chromium/content/browser/indexed_db/indexed_db_database_callbacks.cc
index 35b15c3bce8..69f9b162213 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database_callbacks.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_database_callbacks.cc
@@ -35,7 +35,7 @@ void IndexedDBDatabaseCallbacks::OnVersionChange(int64_t old_version,
if (!dispatcher_host_.get())
return;
- dispatcher_host_->Send(new IndexedDBMsg_DatabaseCallbacksIntVersionChange(
+ dispatcher_host_->Send(new IndexedDBMsg_DatabaseCallbacksVersionChange(
ipc_thread_id_, ipc_database_callbacks_id_, old_version, new_version));
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_database_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_database_unittest.cc
index a837945e4a2..efc1bddf050 100644
--- a/chromium/content/browser/indexed_db/indexed_db_database_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_database_unittest.cc
@@ -76,11 +76,8 @@ TEST(IndexedDBDatabaseTest, ConnectionLifecycle) {
new MockIndexedDBDatabaseCallbacks());
const int64_t transaction_id1 = 1;
IndexedDBPendingConnection connection1(
- request1,
- callbacks1,
- kFakeChildProcessId,
- transaction_id1,
- IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
+ request1, callbacks1, kFakeChildProcessId, transaction_id1,
+ IndexedDBDatabaseMetadata::DEFAULT_VERSION);
db->OpenConnection(connection1);
EXPECT_FALSE(backing_store->HasOneRef()); // db, connection count > 0
@@ -90,11 +87,8 @@ TEST(IndexedDBDatabaseTest, ConnectionLifecycle) {
new MockIndexedDBDatabaseCallbacks());
const int64_t transaction_id2 = 2;
IndexedDBPendingConnection connection2(
- request2,
- callbacks2,
- kFakeChildProcessId,
- transaction_id2,
- IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
+ request2, callbacks2, kFakeChildProcessId, transaction_id2,
+ IndexedDBDatabaseMetadata::DEFAULT_VERSION);
db->OpenConnection(connection2);
EXPECT_FALSE(backing_store->HasOneRef()); // local and connection
@@ -134,11 +128,8 @@ TEST(IndexedDBDatabaseTest, ForcedClose) {
scoped_refptr<MockIndexedDBCallbacks> request(new MockIndexedDBCallbacks());
const int64_t upgrade_transaction_id = 3;
IndexedDBPendingConnection connection(
- request,
- callbacks,
- kFakeChildProcessId,
- upgrade_transaction_id,
- IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
+ request, callbacks, kFakeChildProcessId, upgrade_transaction_id,
+ IndexedDBDatabaseMetadata::DEFAULT_VERSION);
database->OpenConnection(connection);
EXPECT_EQ(database.get(), request->connection()->database());
@@ -198,11 +189,8 @@ TEST(IndexedDBDatabaseTest, PendingDelete) {
new MockIndexedDBDatabaseCallbacks());
const int64_t transaction_id1 = 1;
IndexedDBPendingConnection connection(
- request1,
- callbacks1,
- kFakeChildProcessId,
- transaction_id1,
- IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
+ request1, callbacks1, kFakeChildProcessId, transaction_id1,
+ IndexedDBDatabaseMetadata::DEFAULT_VERSION);
db->OpenConnection(connection);
EXPECT_FALSE(backing_store->HasOneRef()); // local and db
@@ -246,13 +234,9 @@ class IndexedDBDatabaseOperationTest : public testing::Test {
callbacks_ = new MockIndexedDBDatabaseCallbacks();
const int64_t transaction_id = 1;
db_->OpenConnection(IndexedDBPendingConnection(
- request_,
- callbacks_,
- kFakeChildProcessId,
- transaction_id,
- IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION));
- EXPECT_EQ(IndexedDBDatabaseMetadata::NO_INT_VERSION,
- db_->metadata().int_version);
+ request_, callbacks_, kFakeChildProcessId, transaction_id,
+ IndexedDBDatabaseMetadata::DEFAULT_VERSION));
+ EXPECT_EQ(IndexedDBDatabaseMetadata::NO_VERSION, db_->metadata().version);
transaction_ = IndexedDBClassFactory::Get()->CreateIndexedDBTransaction(
transaction_id, callbacks_, std::set<int64_t>() /*scope*/,
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 f0890137038..969ce78e978 100644
--- a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.cc
@@ -33,6 +33,7 @@
#include "storage/browser/blob/blob_data_builder.h"
#include "storage/browser/blob/blob_storage_context.h"
#include "storage/browser/database/database_util.h"
+#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/common/database/database_identifier.h"
#include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseException.h"
#include "url/gurl.h"
@@ -178,7 +179,7 @@ int32_t IndexedDBDispatcherHost::Add(IndexedDBConnection* connection,
return -1;
}
int32_t ipc_database_id = database_dispatcher_host_->map_.Add(connection);
- Context()->ConnectionOpened(origin_url, connection);
+ context()->ConnectionOpened(origin_url, connection);
database_dispatcher_host_->database_url_map_[ipc_database_id] = origin_url;
return ipc_database_id;
}
@@ -187,6 +188,7 @@ void IndexedDBDispatcherHost::RegisterTransactionId(int64_t host_transaction_id,
const GURL& url) {
if (!database_dispatcher_host_)
return;
+ database_dispatcher_host_->transaction_size_map_[host_transaction_id] = 0;
database_dispatcher_host_->transaction_url_map_[host_transaction_id] = url;
}
@@ -277,7 +279,6 @@ IndexedDBCursor* IndexedDBDispatcherHost::GetCursorFromId(
metadata.id = web_metadata.id;
metadata.name = web_metadata.name;
metadata.version = web_metadata.version;
- metadata.int_version = web_metadata.int_version;
metadata.max_object_store_id = web_metadata.max_object_store_id;
for (const auto& iter : web_metadata.object_stores) {
@@ -311,15 +312,10 @@ void IndexedDBDispatcherHost::OnIDBFactoryGetDatabaseNames(
DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
base::FilePath indexed_db_path = indexed_db_context_->data_path();
- GURL origin_url =
- storage::GetOriginFromIdentifier(params.database_identifier);
-
- Context()->GetIDBFactory()->GetDatabaseNames(
- new IndexedDBCallbacks(
- this, params.ipc_thread_id, params.ipc_callbacks_id),
- origin_url,
- indexed_db_path,
- request_context_);
+ context()->GetIDBFactory()->GetDatabaseNames(
+ new IndexedDBCallbacks(this, params.ipc_thread_id,
+ params.ipc_callbacks_id),
+ params.origin, indexed_db_path, request_context_);
}
void IndexedDBDispatcherHost::OnIDBFactoryOpen(
@@ -328,20 +324,13 @@ void IndexedDBDispatcherHost::OnIDBFactoryOpen(
base::TimeTicks begin_time = base::TimeTicks::Now();
base::FilePath indexed_db_path = indexed_db_context_->data_path();
- GURL origin_url =
- storage::GetOriginFromIdentifier(params.database_identifier);
-
int64_t host_transaction_id = HostTransactionId(params.transaction_id);
// TODO(dgrogan): Don't let a non-existing database be opened (and therefore
// created) if this origin is already over quota.
- scoped_refptr<IndexedDBCallbacks> callbacks =
- new IndexedDBCallbacks(this,
- params.ipc_thread_id,
- params.ipc_callbacks_id,
- params.ipc_database_callbacks_id,
- host_transaction_id,
- origin_url);
+ scoped_refptr<IndexedDBCallbacks> callbacks = new IndexedDBCallbacks(
+ this, params.ipc_thread_id, params.ipc_callbacks_id,
+ params.ipc_database_callbacks_id, host_transaction_id, params.origin);
callbacks->SetConnectionOpenStartTime(begin_time);
scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks =
new IndexedDBDatabaseCallbacks(
@@ -352,24 +341,20 @@ void IndexedDBDispatcherHost::OnIDBFactoryOpen(
host_transaction_id,
params.version);
DCHECK(request_context_);
- Context()->GetIDBFactory()->Open(
- params.name, connection, request_context_, origin_url, indexed_db_path);
+ context()->GetIDBFactory()->Open(params.name, connection, request_context_,
+ params.origin, indexed_db_path);
}
void IndexedDBDispatcherHost::OnIDBFactoryDeleteDatabase(
const IndexedDBHostMsg_FactoryDeleteDatabase_Params& params) {
DCHECK(indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
- GURL origin_url =
- storage::GetOriginFromIdentifier(params.database_identifier);
base::FilePath indexed_db_path = indexed_db_context_->data_path();
DCHECK(request_context_);
- Context()->GetIDBFactory()->DeleteDatabase(
- params.name,
- request_context_,
- new IndexedDBCallbacks(
- this, params.ipc_thread_id, params.ipc_callbacks_id),
- origin_url,
- indexed_db_path);
+ context()->GetIDBFactory()->DeleteDatabase(
+ params.name, request_context_,
+ new IndexedDBCallbacks(this, params.ipc_thread_id,
+ params.ipc_callbacks_id),
+ params.origin, indexed_db_path);
}
// OnPutHelper exists only to allow us to hop threads while holding a reference
@@ -399,7 +384,7 @@ void IndexedDBDispatcherHost::FinishTransaction(int64_t host_transaction_id,
TransactionIDToDatabaseIDMap& transaction_database_map =
database_dispatcher_host_->transaction_database_map_;
if (committed)
- Context()->TransactionComplete(transaction_url_map[host_transaction_id]);
+ context()->TransactionComplete(transaction_url_map[host_transaction_id]);
transaction_url_map.erase(host_transaction_id);
transaction_size_map.erase(host_transaction_id);
transaction_database_map.erase(host_transaction_id);
@@ -450,7 +435,7 @@ void IndexedDBDispatcherHost::DestroyObject(MapType* map,
IndexedDBDispatcherHost::DatabaseDispatcherHost::DatabaseDispatcherHost(
IndexedDBDispatcherHost* parent)
- : parent_(parent) {
+ : parent_(parent), weak_factory_(this) {
map_.set_check_on_null_data(true);
}
@@ -461,8 +446,7 @@ IndexedDBDispatcherHost::DatabaseDispatcherHost::~DatabaseDispatcherHost() {
}
void IndexedDBDispatcherHost::DatabaseDispatcherHost::CloseAll() {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
// Abort outstanding transactions started by connections in the associated
// front-end to unblock later transactions. This should only occur on unclean
// (crash) or abrupt (process-kill) shutdowns.
@@ -485,17 +469,16 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::CloseAll() {
IndexedDBConnection* connection = map_.Lookup(iter.first);
if (connection && connection->IsConnected()) {
connection->Close();
- parent_->Context()->ConnectionClosed(iter.second, connection);
+ parent_->context()->ConnectionClosed(iter.second, connection);
}
}
}
bool IndexedDBDispatcherHost::DatabaseDispatcherHost::OnMessageReceived(
const IPC::Message& message) {
- DCHECK(
- (message.type() == IndexedDBHostMsg_DatabasePut::ID ||
- message.type() == IndexedDBHostMsg_AckReceivedBlobs::ID) ||
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK((message.type() == IndexedDBHostMsg_DatabasePut::ID ||
+ message.type() == IndexedDBHostMsg_AckReceivedBlobs::ID) ||
+ parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(
@@ -532,8 +515,7 @@ bool IndexedDBDispatcherHost::DatabaseDispatcherHost::OnMessageReceived(
void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateObjectStore(
const IndexedDBHostMsg_DatabaseCreateObjectStore_Params& params) {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
if (!connection || !connection->IsConnected())
@@ -546,20 +528,13 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateObjectStore(
params.name,
params.key_path,
params.auto_increment);
- if (parent_->Context()->IsOverQuota(
- database_url_map_[params.ipc_database_id])) {
- connection->database()->Abort(
- host_transaction_id,
- IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionQuotaError));
- }
}
void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDeleteObjectStore(
int32_t ipc_database_id,
int64_t transaction_id,
int64_t object_store_id) {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, ipc_database_id);
if (!connection || !connection->IsConnected())
@@ -571,8 +546,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDeleteObjectStore(
void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateTransaction(
const IndexedDBHostMsg_DatabaseCreateTransaction_Params& params) {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
if (!connection || !connection->IsConnected())
@@ -581,8 +555,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateTransaction(
int64_t host_transaction_id =
parent_->HostTransactionId(params.transaction_id);
- if (transaction_database_map_.find(host_transaction_id) !=
- transaction_database_map_.end()) {
+ if (ContainsKey(transaction_database_map_, host_transaction_id)) {
DLOG(ERROR) << "Duplicate host_transaction_id.";
return;
}
@@ -596,8 +569,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateTransaction(
void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnClose(
int32_t ipc_database_id) {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, ipc_database_id);
if (!connection || !connection->IsConnected())
@@ -607,8 +579,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnClose(
void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnVersionChangeIgnored(
int32_t ipc_database_id) {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, ipc_database_id);
if (!connection || !connection->IsConnected())
@@ -618,24 +589,22 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnVersionChangeIgnored(
void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDestroyed(
int32_t ipc_object_id) {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, ipc_object_id);
if (!connection)
return;
if (connection->IsConnected())
connection->Close();
- parent_->Context()
- ->ConnectionClosed(database_url_map_[ipc_object_id], connection);
+ parent_->context()->ConnectionClosed(database_url_map_[ipc_object_id],
+ connection);
database_url_map_.erase(ipc_object_id);
parent_->DestroyObject(&map_, ipc_object_id);
}
void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnGet(
const IndexedDBHostMsg_DatabaseGet_Params& params) {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
if (!connection || !connection->IsConnected())
@@ -654,8 +623,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnGet(
void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnGetAll(
const IndexedDBHostMsg_DatabaseGetAll_Params& params) {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
if (!connection || !connection->IsConnected())
@@ -678,17 +646,15 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnPutWrapper(
->GetBlobDataFromUUID(info.uuid)
.release());
}
- parent_->indexed_db_context_->TaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(
- &IndexedDBDispatcherHost::OnPutHelper, parent_, params, handles));
+ parent_->context()->TaskRunner()->PostTask(
+ FROM_HERE, base::Bind(&IndexedDBDispatcherHost::OnPutHelper, parent_,
+ params, handles));
}
void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnPut(
const IndexedDBHostMsg_DatabasePut_Params& params,
std::vector<storage::BlobDataHandle*> handles) {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
ScopedVector<storage::BlobDataHandle> scoped_handles;
scoped_handles.swap(handles);
@@ -745,17 +711,14 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnPut(
params.put_mode,
callbacks,
params.index_keys);
- TransactionIDToSizeMap* map =
- &parent_->database_dispatcher_host_->transaction_size_map_;
// Size can't be big enough to overflow because it represents the
// actual bytes passed through IPC.
- (*map)[host_transaction_id] += params.value.bits.size();
+ transaction_size_map_[host_transaction_id] += params.value.bits.size();
}
void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnSetIndexKeys(
const IndexedDBHostMsg_DatabaseSetIndexKeys_Params& params) {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
if (!connection || !connection->IsConnected())
@@ -775,8 +738,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnSetIndexesReady(
int64_t transaction_id,
int64_t object_store_id,
const std::vector<int64_t>& index_ids) {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, ipc_database_id);
if (!connection || !connection->IsConnected())
@@ -788,8 +750,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnSetIndexesReady(
void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnOpenCursor(
const IndexedDBHostMsg_DatabaseOpenCursor_Params& params) {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
if (!connection || !connection->IsConnected())
@@ -810,8 +771,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnOpenCursor(
void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCount(
const IndexedDBHostMsg_DatabaseCount_Params& params) {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
if (!connection || !connection->IsConnected())
@@ -829,8 +789,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCount(
void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDeleteRange(
const IndexedDBHostMsg_DatabaseDeleteRange_Params& params) {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
if (!connection || !connection->IsConnected())
@@ -851,8 +810,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnClear(
int32_t ipc_database_id,
int64_t transaction_id,
int64_t object_store_id) {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, ipc_database_id);
if (!connection || !connection->IsConnected())
@@ -868,8 +826,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnClear(
void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnAbort(
int32_t ipc_database_id,
int64_t transaction_id) {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, ipc_database_id);
if (!connection || !connection->IsConnected())
@@ -881,31 +838,62 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnAbort(
void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCommit(
int32_t ipc_database_id,
int64_t transaction_id) {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, ipc_database_id);
if (!connection || !connection->IsConnected())
return;
int64_t host_transaction_id = parent_->HostTransactionId(transaction_id);
+ // May have been aborted by back end before front-end could request commit.
+ if (!ContainsKey(transaction_size_map_, host_transaction_id))
+ return;
+ int64_t transaction_size = transaction_size_map_[host_transaction_id];
+
+ // Always allow empty or delete-only transactions.
+ if (!transaction_size) {
+ connection->database()->Commit(host_transaction_id);
+ return;
+ }
+
+ parent_->context()->quota_manager_proxy()->GetUsageAndQuota(
+ parent_->context()->TaskRunner(),
+ transaction_url_map_[host_transaction_id], storage::kStorageTypeTemporary,
+ base::Bind(&IndexedDBDispatcherHost::DatabaseDispatcherHost::
+ OnGotUsageAndQuotaForCommit,
+ weak_factory_.GetWeakPtr(), ipc_database_id, transaction_id));
+}
+
+void IndexedDBDispatcherHost::DatabaseDispatcherHost::
+ OnGotUsageAndQuotaForCommit(int32_t ipc_database_id,
+ int64_t transaction_id,
+ storage::QuotaStatusCode status,
+ int64_t usage,
+ int64_t quota) {
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
+ IndexedDBConnection* connection = map_.Lookup(ipc_database_id);
+ // May have disconnected while quota check was pending.
+ if (!connection || !connection->IsConnected())
+ return;
+ int64_t host_transaction_id = parent_->HostTransactionId(transaction_id);
+ // May have aborted while quota check was pending.
+ if (!ContainsKey(transaction_size_map_, host_transaction_id))
+ return;
int64_t transaction_size = transaction_size_map_[host_transaction_id];
- if (transaction_size &&
- parent_->Context()->WouldBeOverQuota(
- transaction_url_map_[host_transaction_id], transaction_size)) {
+
+ if (status == storage::kQuotaStatusOk &&
+ usage + transaction_size <= quota) {
+ connection->database()->Commit(host_transaction_id);
+ } else {
connection->database()->Abort(
host_transaction_id,
IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionQuotaError));
- return;
}
-
- connection->database()->Commit(host_transaction_id);
}
void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateIndex(
const IndexedDBHostMsg_DatabaseCreateIndex_Params& params) {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, params.ipc_database_id);
if (!connection || !connection->IsConnected())
@@ -920,12 +908,6 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnCreateIndex(
params.key_path,
params.unique,
params.multi_entry);
- if (parent_->Context()->IsOverQuota(
- database_url_map_[params.ipc_database_id])) {
- connection->database()->Abort(
- host_transaction_id,
- IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionQuotaError));
- }
}
void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDeleteIndex(
@@ -933,8 +915,7 @@ void IndexedDBDispatcherHost::DatabaseDispatcherHost::OnDeleteIndex(
int64_t transaction_id,
int64_t object_store_id,
int64_t index_id) {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBConnection* connection =
parent_->GetOrTerminateProcess(&map_, ipc_database_id);
if (!connection || !connection->IsConnected())
@@ -969,9 +950,8 @@ bool IndexedDBDispatcherHost::CursorDispatcherHost::OnMessageReceived(
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
- DCHECK(
- !handled ||
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(!handled ||
+ parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
return handled;
}
@@ -981,8 +961,7 @@ void IndexedDBDispatcherHost::CursorDispatcherHost::OnAdvance(
int32_t ipc_thread_id,
int32_t ipc_callbacks_id,
uint32_t count) {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBCursor* idb_cursor =
parent_->GetOrTerminateProcess(&map_, ipc_cursor_id);
if (!idb_cursor)
@@ -1000,8 +979,7 @@ void IndexedDBDispatcherHost::CursorDispatcherHost::OnContinue(
int32_t ipc_callbacks_id,
const IndexedDBKey& key,
const IndexedDBKey& primary_key) {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBCursor* idb_cursor =
parent_->GetOrTerminateProcess(&map_, ipc_cursor_id);
if (!idb_cursor)
@@ -1021,8 +999,7 @@ void IndexedDBDispatcherHost::CursorDispatcherHost::OnPrefetch(
int32_t ipc_thread_id,
int32_t ipc_callbacks_id,
int n) {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBCursor* idb_cursor =
parent_->GetOrTerminateProcess(&map_, ipc_cursor_id);
if (!idb_cursor)
@@ -1038,8 +1015,7 @@ void IndexedDBDispatcherHost::CursorDispatcherHost::OnPrefetchReset(
int32_t ipc_cursor_id,
int used_prefetches,
int unused_prefetches) {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
IndexedDBCursor* idb_cursor =
parent_->GetOrTerminateProcess(&map_, ipc_cursor_id);
if (!idb_cursor)
@@ -1054,8 +1030,7 @@ void IndexedDBDispatcherHost::CursorDispatcherHost::OnPrefetchReset(
void IndexedDBDispatcherHost::CursorDispatcherHost::OnDestroyed(
int32_t ipc_object_id) {
- DCHECK(
- parent_->indexed_db_context_->TaskRunner()->RunsTasksOnCurrentThread());
+ DCHECK(parent_->context()->TaskRunner()->RunsTasksOnCurrentThread());
parent_->DestroyObject(&map_, ipc_object_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 29edb8a9728..bba6b814fbf 100644
--- a/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h
+++ b/chromium/content/browser/indexed_db/indexed_db_dispatcher_host.h
@@ -15,10 +15,13 @@
#include "base/id_map.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
#include "content/browser/fileapi/chrome_blob_storage_context.h"
#include "content/public/browser/browser_message_filter.h"
#include "net/url_request/url_request_context_getter.h"
#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/quota/quota_manager.h"
+#include "storage/common/quota/quota_status_code.h"
#include "url/gurl.h"
struct IndexedDBDatabaseMetadata;
@@ -73,7 +76,7 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
void FinishTransaction(int64_t host_transaction_id, bool committed);
// A shortcut for accessing our context.
- IndexedDBContextImpl* Context() { return indexed_db_context_.get(); }
+ IndexedDBContextImpl* context() const { return indexed_db_context_.get(); }
storage::BlobStorageContext* blob_storage_context() const {
return blob_storage_context_->context();
}
@@ -198,6 +201,12 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
void OnAbort(int32_t ipc_database_id, int64_t transaction_id);
void OnCommit(int32_t ipc_database_id, int64_t transaction_id);
+ void OnGotUsageAndQuotaForCommit(int32_t ipc_database_id,
+ int64_t transaction_id,
+ storage::QuotaStatusCode status,
+ int64_t usage,
+ int64_t quota);
+
IndexedDBDispatcherHost* parent_;
IDMap<IndexedDBConnection, IDMapOwnPointer> map_;
WebIDBObjectIDToURLMap database_url_map_;
@@ -205,6 +214,10 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter {
TransactionIDToURLMap transaction_url_map_;
TransactionIDToDatabaseIDMap transaction_database_map_;
+ // Weak pointers are used when an asynchronous quota request is made, in
+ // case the dispatcher is torn down before the response returns.
+ base::WeakPtrFactory<DatabaseDispatcherHost> weak_factory_;
+
private:
DISALLOW_COPY_AND_ASSIGN(DatabaseDispatcherHost);
};
diff --git a/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc b/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc
index 2261dcc30f0..33db01f70fe 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_factory_impl.cc
@@ -17,7 +17,6 @@
#include "content/browser/indexed_db/indexed_db_database_error.h"
#include "content/browser/indexed_db/indexed_db_tracing.h"
#include "content/browser/indexed_db/indexed_db_transaction_coordinator.h"
-#include "storage/common/database/database_identifier.h"
#include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseException.h"
#include "third_party/leveldatabase/env_chromium.h"
diff --git a/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc
index 1dcaecc3378..b61e66c5631 100644
--- a/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_factory_unittest.cc
@@ -17,7 +17,7 @@
#include "content/browser/indexed_db/indexed_db_factory_impl.h"
#include "content/browser/indexed_db/mock_indexed_db_callbacks.h"
#include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h"
-#include "storage/common/database/database_identifier.h"
+#include "content/browser/quota/mock_quota_manager_proxy.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseException.h"
#include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBTypes.h"
@@ -74,12 +74,15 @@ class IndexedDBFactoryTest : public testing::Test {
public:
IndexedDBFactoryTest() {
task_runner_ = new base::TestSimpleTaskRunner();
- context_ = new IndexedDBContextImpl(base::FilePath(),
- NULL /* special_storage_policy */,
- NULL /* quota_manager_proxy */,
- task_runner_.get());
+ quota_manager_proxy_ = new MockQuotaManagerProxy(nullptr, nullptr);
+ context_ = new IndexedDBContextImpl(
+ base::FilePath(), NULL /* special_storage_policy */,
+ quota_manager_proxy_.get(), task_runner_.get());
idb_factory_ = new MockIDBFactory(context_.get());
}
+ ~IndexedDBFactoryTest() override {
+ quota_manager_proxy_->SimulateQuotaManagerDestroyed();
+ }
protected:
// For timers to post events.
@@ -93,7 +96,7 @@ class IndexedDBFactoryTest : public testing::Test {
scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
scoped_refptr<IndexedDBContextImpl> context_;
scoped_refptr<MockIDBFactory> idb_factory_;
-
+ scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
DISALLOW_COPY_AND_ASSIGN(IndexedDBFactoryTest);
};
@@ -279,11 +282,8 @@ TEST_F(IndexedDBFactoryTest, BackingStoreReleasedOnForcedClose) {
new MockIndexedDBDatabaseCallbacks());
const int64_t transaction_id = 1;
IndexedDBPendingConnection connection(
- callbacks,
- db_callbacks,
- 0, /* child_process_id */
- transaction_id,
- IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
+ callbacks, db_callbacks, 0, /* child_process_id */
+ transaction_id, IndexedDBDatabaseMetadata::DEFAULT_VERSION);
factory()->Open(ASCIIToUTF16("db"),
connection,
NULL /* request_context */,
@@ -312,11 +312,8 @@ TEST_F(IndexedDBFactoryTest, BackingStoreReleaseDelayedOnClose) {
new MockIndexedDBDatabaseCallbacks());
const int64_t transaction_id = 1;
IndexedDBPendingConnection connection(
- callbacks,
- db_callbacks,
- 0, /* child_process_id */
- transaction_id,
- IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
+ callbacks, db_callbacks, 0, /* child_process_id */
+ transaction_id, IndexedDBDatabaseMetadata::DEFAULT_VERSION);
factory()->Open(ASCIIToUTF16("db"),
connection,
NULL /* request_context */,
@@ -407,11 +404,8 @@ TEST_F(IndexedDBFactoryTest, ForceCloseReleasesBackingStore) {
new MockIndexedDBDatabaseCallbacks());
const int64_t transaction_id = 1;
IndexedDBPendingConnection connection(
- callbacks,
- db_callbacks,
- 0, /* child_process_id */
- transaction_id,
- IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
+ callbacks, db_callbacks, 0, /* child_process_id */
+ transaction_id, IndexedDBDatabaseMetadata::DEFAULT_VERSION);
factory()->Open(ASCIIToUTF16("db"),
connection,
NULL /* request_context */,
diff --git a/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc b/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc
index 01f83cbe2cb..b2aeb4c9573 100644
--- a/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.cc
@@ -45,8 +45,7 @@ leveldb::Status IndexedDBFakeBackingStore::GetIDBDatabaseMetaData(
leveldb::Status IndexedDBFakeBackingStore::CreateIDBDatabaseMetaData(
const base::string16& name,
- const base::string16& version,
- int64_t int_version,
+ int64_t version,
int64_t* row_id) {
return leveldb::Status::OK();
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.h b/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.h
index 8f033005570..3e168695e6b 100644
--- a/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.h
+++ b/chromium/content/browser/indexed_db/indexed_db_fake_backing_store.h
@@ -30,8 +30,7 @@ class IndexedDBFakeBackingStore : public IndexedDBBackingStore {
IndexedDBDatabaseMetadata*,
bool* found) override;
leveldb::Status CreateIDBDatabaseMetaData(const base::string16& name,
- const base::string16& version,
- int64_t int_version,
+ int64_t version,
int64_t* row_id) override;
bool UpdateIDBDatabaseIntVersion(Transaction*,
int64_t row_id,
diff --git a/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc b/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
index 1e8926009dc..bec8dd85fdf 100644
--- a/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_internals_ui.cc
@@ -214,9 +214,11 @@ void IndexedDBInternalsUI::DownloadOriginDataOnIndexedDBThread(
const scoped_refptr<IndexedDBContextImpl> context,
const GURL& origin_url) {
DCHECK(context->TaskRunner()->RunsTasksOnCurrentThread());
+ // This runs on the IndexedDB task runner to prevent script from reopening
+ // the origin while we are zipping.
// Make sure the database hasn't been deleted since the page was loaded.
- if (!context->IsInOriginSet(origin_url))
+ if (!context->HasOrigin(origin_url))
return;
context->ForceClose(origin_url,
@@ -235,9 +237,6 @@ void IndexedDBInternalsUI::DownloadOriginDataOnIndexedDBThread(
base::FilePath zip_path =
temp_path.AppendASCII(origin_id).AddExtension(FILE_PATH_LITERAL("zip"));
- // This happens on the "webkit" thread (which is really just the IndexedDB
- // thread) as a simple way to avoid another script reopening the origin
- // while we are zipping.
std::vector<base::FilePath> paths = context->GetStoragePaths(origin_url);
zip::ZipWithFilterCallback(context->data_path(), zip_path,
base::Bind(AllowWhitelistedPaths, paths));
@@ -260,7 +259,7 @@ void IndexedDBInternalsUI::ForceCloseOriginOnIndexedDBThread(
DCHECK(context->TaskRunner()->RunsTasksOnCurrentThread());
// Make sure the database hasn't been deleted since the page was loaded.
- if (!context->IsInOriginSet(origin_url))
+ if (!context->HasOrigin(origin_url))
return;
context->ForceClose(origin_url,
diff --git a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc
index eb705378123..8d5185b84b2 100644
--- a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.cc
@@ -14,155 +14,8 @@
#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 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 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.
-//
-// Strings (origins, names, etc) are encoded as UTF-16BE.
-//
-//
-// 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, 3>
-// => Blob journal
-// The format of the journal is:
-// {database_id (var int), blobKey (var int)}*.
-// If the blobKey is kAllBlobsKey, the whole database should be deleted.
-// [BlobJournalKey]
-// <0, 0, 0, 4> => Live blob journal; same format. [LiveBlobJournalKey]
-// <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 (int) [DatabaseNameKey]
-//
-//
-// Database metadata: [DatabaseMetaDataKey]
-// ----------------------------------------
-// The prefix is <database id, 0, 0> followed by a metadata type byte:
-//
-// <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)
-// <database id, 0, 0, 5> => blob key generator current number
-//
-//
-// 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.
-//
-// <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
-//
-// 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.
-//
-//
-// 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, 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
-//
-//
-// 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.
-//
-// <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]
-//
-//
-// 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.
-//
-// <database id, object store id, 1, user key>
-// => "version", serialized script value
-//
-//
-// "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"
-//
-//
-// Blob entry table: [BlobEntryKey]
-// --------------------------------
-//
-// The prefix is followed by a type byte and the encoded IDB primary key.
-//
-// <database id, object store id, 3, user key> => array of IndexedDBBlobInfo
-//
-//
-// 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]
-//
-// 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.
-//
-// Note: In order to be compatible with LevelDB's Bloom filter each bit of the
-// encoded key needs to used and "not ignored" by the comparator.
+// See leveldb_coding_scheme.md for detailed documentation of the coding
+// scheme implemented here.
using base::StringPiece;
using blink::WebIDBKeyType;
@@ -197,6 +50,10 @@ static const unsigned char kIndexedDBKeyBinaryTypeByte = 6;
static const unsigned char kIndexedDBKeyPathTypeCodedByte1 = 0;
static const unsigned char kIndexedDBKeyPathTypeCodedByte2 = 0;
+static const unsigned char kIndexedDBKeyPathNullTypeByte = 0;
+static const unsigned char kIndexedDBKeyPathStringTypeByte = 1;
+static const unsigned char kIndexedDBKeyPathArrayTypeByte = 2;
+
static const unsigned char kObjectStoreDataIndexId = 1;
static const unsigned char kExistsEntryIndexId = 2;
static const unsigned char kBlobEntryIndexId = 3;
@@ -353,6 +210,18 @@ void EncodeIDBKey(const IndexedDBKey& value, std::string* into) {
}
}
+#define COMPILE_ASSERT_MATCHING_VALUES(a, b) \
+ static_assert( \
+ static_cast<unsigned char>(a) == static_cast<unsigned char>(b), \
+ "Blink enum and coding byte must match.")
+
+COMPILE_ASSERT_MATCHING_VALUES(WebIDBKeyPathTypeNull,
+ kIndexedDBKeyPathNullTypeByte);
+COMPILE_ASSERT_MATCHING_VALUES(WebIDBKeyPathTypeString,
+ kIndexedDBKeyPathStringTypeByte);
+COMPILE_ASSERT_MATCHING_VALUES(WebIDBKeyPathTypeArray,
+ kIndexedDBKeyPathArrayTypeByte);
+
void EncodeIDBKeyPath(const IndexedDBKeyPath& value, std::string* into) {
// May be typed, or may be a raw string. An invalid leading
// byte is used to identify typed coding. New records are
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 bd3724c798a..5be0eecfc8b 100644
--- a/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h
+++ b/chromium/content/browser/indexed_db/indexed_db_leveldb_coding.h
@@ -237,9 +237,9 @@ class DatabaseMetaDataKey {
enum MetaDataType {
ORIGIN_NAME = 0,
DATABASE_NAME = 1,
- USER_VERSION = 2,
+ USER_STRING_VERSION = 2, // Obsolete
MAX_OBJECT_STORE_ID = 3,
- USER_INT_VERSION = 4,
+ USER_VERSION = 4,
BLOB_KEY_GENERATOR_CURRENT_NUMBER = 5,
MAX_SIMPLE_METADATA_TYPE = 6
};
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 2f9e141d0ea..0c300848237 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
@@ -888,11 +888,11 @@ TEST(IndexedDBLevelDBCodingTest, ComparisonTest) {
keys.push_back(
DatabaseMetaDataKey::Encode(1, DatabaseMetaDataKey::DATABASE_NAME));
keys.push_back(
- DatabaseMetaDataKey::Encode(1, DatabaseMetaDataKey::USER_VERSION));
+ DatabaseMetaDataKey::Encode(1, DatabaseMetaDataKey::USER_STRING_VERSION));
keys.push_back(
DatabaseMetaDataKey::Encode(1, DatabaseMetaDataKey::MAX_OBJECT_STORE_ID));
keys.push_back(
- DatabaseMetaDataKey::Encode(1, DatabaseMetaDataKey::USER_INT_VERSION));
+ DatabaseMetaDataKey::Encode(1, DatabaseMetaDataKey::USER_VERSION));
keys.push_back(
ObjectStoreMetaDataKey::Encode(1, 1, ObjectStoreMetaDataKey::NAME));
keys.push_back(
diff --git a/chromium/content/browser/indexed_db/indexed_db_metadata.cc b/chromium/content/browser/indexed_db/indexed_db_metadata.cc
index 74bdfbf9d01..899c881ad13 100644
--- a/chromium/content/browser/indexed_db/indexed_db_metadata.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_metadata.cc
@@ -49,19 +49,16 @@ IndexedDBObjectStoreMetadata::~IndexedDBObjectStoreMetadata() = default;
IndexedDBObjectStoreMetadata& IndexedDBObjectStoreMetadata::operator=(
const IndexedDBObjectStoreMetadata& other) = default;
-IndexedDBDatabaseMetadata::IndexedDBDatabaseMetadata()
- : int_version(NO_INT_VERSION) {}
+IndexedDBDatabaseMetadata::IndexedDBDatabaseMetadata() : version(NO_VERSION) {}
IndexedDBDatabaseMetadata::IndexedDBDatabaseMetadata(
const base::string16& name,
int64_t id,
- const base::string16& version,
- int64_t int_version,
+ int64_t version,
int64_t max_object_store_id)
: name(name),
id(id),
version(version),
- int_version(int_version),
max_object_store_id(max_object_store_id) {}
IndexedDBDatabaseMetadata::IndexedDBDatabaseMetadata(
diff --git a/chromium/content/browser/indexed_db/indexed_db_metadata.h b/chromium/content/browser/indexed_db/indexed_db_metadata.h
index 288801722f4..ec9d9acbcb8 100644
--- a/chromium/content/browser/indexed_db/indexed_db_metadata.h
+++ b/chromium/content/browser/indexed_db/indexed_db_metadata.h
@@ -61,18 +61,14 @@ struct CONTENT_EXPORT IndexedDBObjectStoreMetadata {
struct CONTENT_EXPORT IndexedDBDatabaseMetadata {
// TODO(jsbell): These can probably be collapsed into 0.
- enum {
- NO_INT_VERSION = -1,
- DEFAULT_INT_VERSION = 0
- };
+ enum { NO_VERSION = -1, DEFAULT_VERSION = 0 };
typedef std::map<int64_t, IndexedDBObjectStoreMetadata> ObjectStoreMap;
IndexedDBDatabaseMetadata();
IndexedDBDatabaseMetadata(const base::string16& name,
int64_t id,
- const base::string16& version,
- int64_t int_version,
+ int64_t version,
int64_t max_object_store_id);
IndexedDBDatabaseMetadata(const IndexedDBDatabaseMetadata& other);
~IndexedDBDatabaseMetadata();
@@ -80,8 +76,7 @@ struct CONTENT_EXPORT IndexedDBDatabaseMetadata {
base::string16 name;
int64_t id;
- base::string16 version;
- int64_t int_version;
+ int64_t version;
int64_t max_object_store_id;
ObjectStoreMap object_stores;
diff --git a/chromium/content/browser/indexed_db/indexed_db_pending_connection.cc b/chromium/content/browser/indexed_db/indexed_db_pending_connection.cc
index ee16aba741e..34f4924285c 100644
--- a/chromium/content/browser/indexed_db/indexed_db_pending_connection.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_pending_connection.cc
@@ -18,6 +18,9 @@ IndexedDBPendingConnection::IndexedDBPendingConnection(
transaction_id(transaction_id_in),
version(version_in) {}
+IndexedDBPendingConnection::IndexedDBPendingConnection(
+ const IndexedDBPendingConnection& other) = default;
+
IndexedDBPendingConnection::~IndexedDBPendingConnection() {}
} // namespace content
diff --git a/chromium/content/browser/indexed_db/indexed_db_pending_connection.h b/chromium/content/browser/indexed_db/indexed_db_pending_connection.h
index b66d9cd4955..10e1b05df55 100644
--- a/chromium/content/browser/indexed_db/indexed_db_pending_connection.h
+++ b/chromium/content/browser/indexed_db/indexed_db_pending_connection.h
@@ -24,6 +24,7 @@ struct CONTENT_EXPORT IndexedDBPendingConnection {
int child_process_id_in,
int64_t transaction_id_in,
int64_t version_in);
+ IndexedDBPendingConnection(const IndexedDBPendingConnection& other);
~IndexedDBPendingConnection();
scoped_refptr<IndexedDBCallbacks> callbacks;
scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks;
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 433b2c130e0..8fc9ce8cd96 100644
--- a/chromium/content/browser/indexed_db/indexed_db_quota_client.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_quota_client.cc
@@ -11,7 +11,7 @@
#include "base/logging.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
#include "content/public/browser/browser_thread.h"
-#include "net/base/net_util.h"
+#include "net/base/url_util.h"
#include "storage/browser/database/database_util.h"
using storage::QuotaClient;
@@ -90,10 +90,9 @@ void IndexedDBQuotaClient::GetOriginUsage(const GURL& origin_url,
}
base::PostTaskAndReplyWithResult(
- indexed_db_context_->TaskRunner(),
- FROM_HERE,
- base::Bind(
- &GetOriginUsageOnIndexedDBThread, indexed_db_context_, origin_url),
+ indexed_db_context_->TaskRunner(), FROM_HERE,
+ base::Bind(&GetOriginUsageOnIndexedDBThread,
+ base::RetainedRef(indexed_db_context_), origin_url),
callback);
}
@@ -117,10 +116,9 @@ void IndexedDBQuotaClient::GetOriginsForType(
std::set<GURL>* origins_to_return = new std::set<GURL>();
indexed_db_context_->TaskRunner()->PostTaskAndReply(
- FROM_HERE,
- base::Bind(&GetAllOriginsOnIndexedDBThread,
- indexed_db_context_,
- base::Unretained(origins_to_return)),
+ FROM_HERE, base::Bind(&GetAllOriginsOnIndexedDBThread,
+ base::RetainedRef(indexed_db_context_),
+ base::Unretained(origins_to_return)),
base::Bind(&DidGetOrigins, callback, base::Owned(origins_to_return)));
}
@@ -145,11 +143,9 @@ void IndexedDBQuotaClient::GetOriginsForHost(
std::set<GURL>* origins_to_return = new std::set<GURL>();
indexed_db_context_->TaskRunner()->PostTaskAndReply(
- FROM_HERE,
- base::Bind(&GetOriginsForHostOnIndexedDBThread,
- indexed_db_context_,
- host,
- base::Unretained(origins_to_return)),
+ FROM_HERE, base::Bind(&GetOriginsForHostOnIndexedDBThread,
+ base::RetainedRef(indexed_db_context_), host,
+ base::Unretained(origins_to_return)),
base::Bind(&DidGetOrigins, callback, base::Owned(origins_to_return)));
}
@@ -168,10 +164,9 @@ void IndexedDBQuotaClient::DeleteOriginData(const GURL& origin,
}
base::PostTaskAndReplyWithResult(
- indexed_db_context_->TaskRunner(),
- FROM_HERE,
- base::Bind(
- &DeleteOriginDataOnIndexedDBThread, indexed_db_context_, origin),
+ indexed_db_context_->TaskRunner(), FROM_HERE,
+ base::Bind(&DeleteOriginDataOnIndexedDBThread,
+ base::RetainedRef(indexed_db_context_), origin),
callback);
}
diff --git a/chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc
index 31a413693ed..a626dc06650 100644
--- a/chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_quota_client_unittest.cc
@@ -20,7 +20,6 @@
#include "content/public/browser/storage_partition.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
-#include "storage/common/database/database_identifier.h"
#include "testing/gtest/include/gtest/gtest.h"
// Declared to shorten the line lengths.
@@ -139,8 +138,8 @@ class IndexedDBQuotaClientTest : public testing::Test {
}
void AddFakeIndexedDB(const GURL& origin, int size) {
- base::FilePath file_path_origin = idb_context()->GetFilePathForTesting(
- storage::GetIdentifierFromOrigin(origin));
+ base::FilePath file_path_origin =
+ idb_context()->GetFilePathForTesting(origin);
if (!base::CreateDirectory(file_path_origin)) {
LOG(ERROR) << "failed to base::CreateDirectory "
<< file_path_origin.value();
diff --git a/chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc
index 984296807fe..dbe63ac0f71 100644
--- a/chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_transaction_unittest.cc
@@ -43,7 +43,7 @@ class IndexedDBTransactionTest : public testing::Test {
void CreateDB() {
// DB is created here instead of the constructor to workaround a
// "peculiarity of C++". More info at
- // https://code.google.com/p/googletest/wiki/FAQ#My_compiler_complains_that_a_constructor_(or_destructor)_cannot
+ // https://github.com/google/googletest/blob/master/googletest/docs/FAQ.md#my-compiler-complains-that-a-constructor-or-destructor-cannot-return-a-value-whats-going-on
leveldb::Status s;
db_ = IndexedDBDatabase::Create(base::ASCIIToUTF16("db"),
backing_store_.get(),
diff --git a/chromium/content/browser/indexed_db/indexed_db_unittest.cc b/chromium/content/browser/indexed_db/indexed_db_unittest.cc
index f7ea47817e6..7b057d599cc 100644
--- a/chromium/content/browser/indexed_db/indexed_db_unittest.cc
+++ b/chromium/content/browser/indexed_db/indexed_db_unittest.cc
@@ -16,13 +16,13 @@
#include "content/browser/indexed_db/indexed_db_factory_impl.h"
#include "content/browser/indexed_db/mock_indexed_db_callbacks.h"
#include "content/browser/indexed_db/mock_indexed_db_database_callbacks.h"
+#include "content/browser/quota/mock_quota_manager_proxy.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/mock_special_storage_policy.h"
#include "content/public/test/test_browser_context.h"
#include "storage/browser/quota/quota_manager.h"
#include "storage/browser/quota/special_storage_policy.h"
-#include "storage/common/database/database_identifier.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -37,10 +37,14 @@ class IndexedDBTest : public testing::Test {
kSessionOnlyOrigin("http://session-only/"),
task_runner_(new base::TestSimpleTaskRunner),
special_storage_policy_(new MockSpecialStoragePolicy),
+ quota_manager_proxy_(new MockQuotaManagerProxy(nullptr, nullptr)),
file_thread_(BrowserThread::FILE_USER_BLOCKING, &message_loop_),
io_thread_(BrowserThread::IO, &message_loop_) {
special_storage_policy_->AddSessionOnly(kSessionOnlyOrigin);
}
+ ~IndexedDBTest() override {
+ quota_manager_proxy_->SimulateQuotaManagerDestroyed();
+ }
protected:
void FlushIndexedDBTaskRunner() { task_runner_->RunUntilIdle(); }
@@ -48,6 +52,7 @@ class IndexedDBTest : public testing::Test {
base::MessageLoopForIO message_loop_;
scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
scoped_refptr<MockSpecialStoragePolicy> special_storage_policy_;
+ scoped_refptr<MockQuotaManagerProxy> quota_manager_proxy_;
private:
BrowserThreadImpl file_thread_;
@@ -69,17 +74,16 @@ TEST_F(IndexedDBTest, ClearSessionOnlyDatabases) {
scoped_refptr<IndexedDBContextImpl> idb_context =
new IndexedDBContextImpl(temp_dir.path(),
special_storage_policy_.get(),
- NULL,
+ quota_manager_proxy_.get(),
task_runner_.get());
- normal_path = idb_context->GetFilePathForTesting(
- storage::GetIdentifierFromOrigin(kNormalOrigin));
- session_only_path = idb_context->GetFilePathForTesting(
- storage::GetIdentifierFromOrigin(kSessionOnlyOrigin));
+ normal_path = idb_context->GetFilePathForTesting(kNormalOrigin);
+ session_only_path = idb_context->GetFilePathForTesting(kSessionOnlyOrigin);
ASSERT_TRUE(base::CreateDirectory(normal_path));
ASSERT_TRUE(base::CreateDirectory(session_only_path));
FlushIndexedDBTaskRunner();
message_loop_.RunUntilIdle();
+ quota_manager_proxy_->SimulateQuotaManagerDestroyed();
}
FlushIndexedDBTaskRunner();
@@ -103,16 +107,14 @@ TEST_F(IndexedDBTest, SetForceKeepSessionState) {
scoped_refptr<IndexedDBContextImpl> idb_context =
new IndexedDBContextImpl(temp_dir.path(),
special_storage_policy_.get(),
- NULL,
+ quota_manager_proxy_.get(),
task_runner_.get());
// Save session state. This should bypass the destruction-time deletion.
idb_context->SetForceKeepSessionState();
- normal_path = idb_context->GetFilePathForTesting(
- storage::GetIdentifierFromOrigin(kNormalOrigin));
- session_only_path = idb_context->GetFilePathForTesting(
- storage::GetIdentifierFromOrigin(kSessionOnlyOrigin));
+ normal_path = idb_context->GetFilePathForTesting(kNormalOrigin);
+ session_only_path = idb_context->GetFilePathForTesting(kSessionOnlyOrigin);
ASSERT_TRUE(base::CreateDirectory(normal_path));
ASSERT_TRUE(base::CreateDirectory(session_only_path));
message_loop_.RunUntilIdle();
@@ -174,7 +176,7 @@ TEST_F(IndexedDBTest, ForceCloseOpenDatabasesOnDelete) {
scoped_refptr<IndexedDBContextImpl> idb_context =
new IndexedDBContextImpl(temp_dir.path(),
special_storage_policy_.get(),
- NULL,
+ quota_manager_proxy_.get(),
task_runner_.get());
scoped_refptr<ForceCloseDBCallbacks> open_callbacks =
@@ -185,8 +187,7 @@ TEST_F(IndexedDBTest, ForceCloseOpenDatabasesOnDelete) {
IndexedDBFactory* factory = idb_context->GetIDBFactory();
- test_path = idb_context->GetFilePathForTesting(
- storage::GetIdentifierFromOrigin(kTestOrigin));
+ test_path = idb_context->GetFilePathForTesting(kTestOrigin);
IndexedDBPendingConnection open_connection(open_callbacks,
open_db_callbacks,
@@ -233,10 +234,10 @@ TEST_F(IndexedDBTest, DeleteFailsIfDirectoryLocked) {
const GURL kTestOrigin("http://test/");
scoped_refptr<IndexedDBContextImpl> idb_context = new IndexedDBContextImpl(
- temp_dir.path(), special_storage_policy_.get(), NULL, task_runner_.get());
+ temp_dir.path(), special_storage_policy_.get(),
+ quota_manager_proxy_.get(), task_runner_.get());
- base::FilePath test_path = idb_context->GetFilePathForTesting(
- storage::GetIdentifierFromOrigin(kTestOrigin));
+ base::FilePath test_path = idb_context->GetFilePathForTesting(kTestOrigin);
ASSERT_TRUE(base::CreateDirectory(test_path));
scoped_ptr<LevelDBLock> lock =
@@ -258,8 +259,9 @@ TEST_F(IndexedDBTest, ForceCloseOpenDatabasesOnCommitFailure) {
base::ScopedTempDir temp_dir;
ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- scoped_refptr<IndexedDBContextImpl> context = new IndexedDBContextImpl(
- temp_dir.path(), special_storage_policy_.get(), NULL, task_runner_.get());
+ scoped_refptr<IndexedDBContextImpl> context =
+ new IndexedDBContextImpl(temp_dir.path(), special_storage_policy_.get(),
+ quota_manager_proxy_.get(), task_runner_.get());
scoped_refptr<IndexedDBFactoryImpl> factory =
static_cast<IndexedDBFactoryImpl*>(context->GetIDBFactory());
@@ -269,11 +271,8 @@ TEST_F(IndexedDBTest, ForceCloseOpenDatabasesOnCommitFailure) {
new MockIndexedDBDatabaseCallbacks());
const int64_t transaction_id = 1;
IndexedDBPendingConnection connection(
- callbacks,
- db_callbacks,
- 0 /* child_process_id */,
- transaction_id,
- IndexedDBDatabaseMetadata::DEFAULT_INT_VERSION);
+ callbacks, db_callbacks, 0 /* child_process_id */, transaction_id,
+ IndexedDBDatabaseMetadata::DEFAULT_VERSION);
factory->Open(base::ASCIIToUTF16("db"),
connection,
NULL /* request_context */,
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc b/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc
index 8bd919e7c5d..4cb277cc346 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_database.cc
@@ -14,10 +14,13 @@
#include "base/memory/scoped_ptr.h"
#include "base/metrics/histogram.h"
#include "base/strings/string16.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/sys_info.h"
+#include "base/trace_event/memory_dump_manager.h"
+#include "base/trace_event/process_memory_dump.h"
#include "build/build_config.h"
#include "content/browser/indexed_db/indexed_db_class_factory.h"
#include "content/browser/indexed_db/indexed_db_tracing.h"
@@ -89,6 +92,8 @@ LevelDBSnapshot::~LevelDBSnapshot() { db_->ReleaseSnapshot(snapshot_); }
LevelDBDatabase::LevelDBDatabase() {}
LevelDBDatabase::~LevelDBDatabase() {
+ base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
+ this);
// db_'s destructor uses comparator_adapter_; order of deletion is important.
CloseDatabase();
comparator_adapter_.reset();
@@ -311,6 +316,7 @@ leveldb::Status LevelDBDatabase::Open(const base::FilePath& file_name,
(*result)->comparator_adapter_ = std::move(comparator_adapter);
(*result)->comparator_ = comparator;
(*result)->filter_policy_ = std::move(filter_policy);
+ (*result)->file_name_for_tracing = file_name.BaseName().AsUTF8Unsafe();
return s;
}
@@ -340,6 +346,7 @@ scoped_ptr<LevelDBDatabase> LevelDBDatabase::OpenInMemory(
result->comparator_adapter_ = std::move(comparator_adapter);
result->comparator_ = comparator;
result->filter_policy_ = std::move(filter_policy);
+ result->file_name_for_tracing = "in-memory-database";
return result;
}
@@ -438,4 +445,29 @@ void LevelDBDatabase::Compact(const base::StringPiece& start,
void LevelDBDatabase::CompactAll() { db_->CompactRange(NULL, NULL); }
+bool LevelDBDatabase::OnMemoryDump(
+ const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) {
+ if (!db_)
+ return false;
+
+ std::string value;
+ uint64_t size;
+ bool res = db_->GetProperty("leveldb.approximate-memory-usage", &value);
+ DCHECK(res);
+ base::StringToUint64(value, &size);
+
+ auto dump = pmd->CreateAllocatorDump(
+ base::StringPrintf("leveldb/index_db/%p", db_.get()));
+ dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
+ base::trace_event::MemoryAllocatorDump::kUnitsBytes, size);
+ dump->AddString("file_name", "", file_name_for_tracing);
+
+ // Memory is allocated from system allocator (malloc).
+ pmd->AddSuballocation(dump->guid(),
+ base::trace_event::MemoryDumpManager::GetInstance()
+ ->system_allocator_pool_name());
+ return true;
+}
+
} // namespace content
diff --git a/chromium/content/browser/indexed_db/leveldb/leveldb_database.h b/chromium/content/browser/indexed_db/leveldb/leveldb_database.h
index d5e469a6861..1ddc0bc4216 100644
--- a/chromium/content/browser/indexed_db/leveldb/leveldb_database.h
+++ b/chromium/content/browser/indexed_db/leveldb/leveldb_database.h
@@ -12,6 +12,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
+#include "base/trace_event/memory_dump_provider.h"
#include "content/common/content_export.h"
#include "third_party/leveldatabase/src/include/leveldb/comparator.h"
#include "third_party/leveldatabase/src/include/leveldb/status.h"
@@ -54,7 +55,8 @@ class CONTENT_EXPORT LevelDBLock {
DISALLOW_COPY_AND_ASSIGN(LevelDBLock);
};
-class CONTENT_EXPORT LevelDBDatabase {
+class CONTENT_EXPORT LevelDBDatabase
+ : public base::trace_event::MemoryDumpProvider {
public:
class ComparatorAdapter : public leveldb::Comparator {
public:
@@ -82,7 +84,7 @@ class CONTENT_EXPORT LevelDBDatabase {
static leveldb::Status Destroy(const base::FilePath& file_name);
static scoped_ptr<LevelDBLock> LockForTesting(
const base::FilePath& file_name);
- virtual ~LevelDBDatabase();
+ ~LevelDBDatabase() override;
leveldb::Status Put(const base::StringPiece& key, std::string* value);
leveldb::Status Remove(const base::StringPiece& key);
@@ -96,6 +98,10 @@ class CONTENT_EXPORT LevelDBDatabase {
void Compact(const base::StringPiece& start, const base::StringPiece& stop);
void CompactAll();
+ // base::trace_event::MemoryDumpProvider implementation.
+ bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
+ base::trace_event::ProcessMemoryDump* pmd) override;
+
protected:
LevelDBDatabase();
@@ -109,6 +115,7 @@ class CONTENT_EXPORT LevelDBDatabase {
scoped_ptr<leveldb::DB> db_;
scoped_ptr<const leveldb::FilterPolicy> filter_policy_;
const LevelDBComparator* comparator_;
+ std::string file_name_for_tracing;
};
} // namespace content
diff --git a/chromium/content/browser/indexed_db/leveldb_coding_scheme.md b/chromium/content/browser/indexed_db/leveldb_coding_scheme.md
new file mode 100644
index 00000000000..f5674161d71
--- /dev/null
+++ b/chromium/content/browser/indexed_db/leveldb_coding_scheme.md
@@ -0,0 +1,323 @@
+# 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, described here using the notation «a, b, c,
+...». Each key in the backing store starts with a ternary prefix:
+«database id, object store id, index id». For each, the id `0` is
+always reserved for metadata; other ids may be reserved as well.
+
+*** aside
+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 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.
+
+The term "user key" refers to an Indexed DB key value specified by
+user code as opposed to the internal keys as described here.
+
+Integer literals used below (e.g. «0, 0, 0, 201, ...») are defined as
+constants in `indexed_db_leveldb_coding.cc`
+
+*** note
+**Warning:** In order to be compatible with LevelDB's Bloom filter each
+bit of the encoded key needs to used and "not ignored" by the
+comparator.
+***
+
+*** note
+**Warning:** As a custom comparator is used, some code to handle obsolete
+data is still needed as the sort order must be maintained.
+***
+
+- - - -
+
+## Types
+
+### Primitive Types
+
+Generic types which may appear as parts of keys or values are:
+
+* **Byte** - what it says on the tin
+* **Bool** - single byte, 0 = false, otherwise true
+* **Int** - int64_t >= 0; 8 bytes in little-endian order
+* **VarInt** - int64_t >= 0; variable-width, little-endian, 7 bits per
+ byte with high bit set until last
+* **String** - UTF-16BE (must be byte-swapped on x86/x64/ARM); length
+ must be implicit
+* **StringWithLength** - VarInt prefix with length in code units (i.e.
+ bytes/2), followed by String
+* **Binary** - VarInt prefix with length in bytes, followed by data
+ bytes
+* **Double** - IEEE754 64-bit (double), in *host endianness*
+
+*** aside
+There is a mix of network-endian, little-endian, and host-endian. In
+particular, the String encoding requires byte-swapping. Sorry about
+that.
+***
+
+### IDBKey (keys and values)
+
+First byte is the type, followed by type-specific serialization:
+
+* Null (no key): `0` (Byte) _Should not appear in data._
+* Number: `3` (Byte), Double
+* Date: `2` (Byte), Double
+* String: `1` (Byte), StringWithLength
+* Binary: `6` (Byte), Binary
+* Array: `4` (Byte), count (VarInt), IDBKey...
+
+### IDBKeyPath (values)
+
+* Null: `0` (Byte), `0` (Byte), `0` (Byte)
+* String: `0` (Byte), `0` (Byte), `1` (Byte), StringWithLength
+* Array: `0` (Byte), `0` (Byte), `2` (Byte), count (VarInt), StringWithLength...
+
+*** note
+**Compatibility:**
+If length is < 3 or the first two bytes are not `0`, `0` whole value
+is decoded as a String.
+***
+
+### Blob Journal (value)
+
+Blob journals are zero-or-more instances of the structure:
+
+```
+{
+ database_id (VarInt),
+ blobKey (VarInt)
+}
+```
+
+There is no length prefix; just read until you run out of data.
+
+If the blobKey is `DatabaseMetaDataKey::kAllBlobsKey`, the whole
+database should be deleted.
+
+### BlobData (value)
+
+Blob data is zero-or-more instances of the structure:
+
+```
+{
+ is_file (Bool),
+ key (VarInt),
+ type (StringWithLength), // may be empty
+ /*for Blobs only*/ size (VarInt),
+ /*for Files only*/ filename (StringWithLength)
+}
+```
+
+There is no length prefix; just read until you run out of data.
+
+- - - -
+
+## Key Prefix
+[`KeyPrefix`]
+
+Each key is prefixed with «database id, object store id, index id»
+with `0` reserved for metadata.
+
+To save space, the prefix is not encoded with the usual types. The
+first byte defines the lengths of the other fields:
+
+* The top 3 bits are the length of the database id - 1 (in bytes)
+* The next 3 bits are the length of the object store id - 1 (in bytes)
+* The bottom 2 bits are the length of the index id - 1 (in bytes)
+
+This is followed by:
+
+* The database id in little-endian order (1 - 8 bytes)
+* The object store id in little-endian order (1 - 8 bytes)
+* The index id in little-endian order (1 - 4 bytes)
+
+- - - -
+
+## Global metadata
+
+The prefix is «0, 0, 0», followed by a metadata type byte:
+
+key | value
+------------------------------------|------
+«0, 0, 0, 0» | backing store schema version (Int) [`SchemaVersionKey`]
+«0, 0, 0, 1» | maximum allocated database (Int) [`MaxDatabaseIdKey`]
+«0, 0, 0, 2» | SerializedScriptValue version (Int) [`DataVersionKey`]
+«0, 0, 0, 3» | primary BlobJournal [`BlobJournalKey`]
+«0, 0, 0, 4» | live BlobJournal [`LiveBlobJournalKey`]
+«0, 0, 0, 100, database id (VarInt)» | Existence implies the database id is in the free list [`DatabaseFreeListKey`] - _obsolete_
+«0, 0, 0, 201, origin (StringWithLength), database name (StringWithLength)» | Database id (Int) [`DatabaseNameKey`]
+
+*** aside
+Free lists (#100) are no longer used. The ID space is assumed to be
+sufficient.
+***
+
+
+## Database metadata
+[`DatabaseMetaDataKey`]
+
+The prefix is «database id, 0, 0» followed by a metadata type Byte:
+
+key | value
+-----------------------|-------
+«database id, 0, 0, 0» | origin name (String)
+«database id, 0, 0, 1» | database name (String)
+«database id, 0, 0, 2» | IDB string version data (String) - _obsolete_
+«database id, 0, 0, 3» | maximum allocated object store id (Int)
+«database id, 0, 0, 4» | IDB integer version (VarInt)
+«database id, 0, 0, 5» | blob key generator current number (VarInt)
+
+*** aside
+Early versions of the Indexed DB spec used strings for versions
+(#2) instead of monotonically increasing integers.
+***
+
+
+### More database metadata
+
+The prefix is «database id, 0, 0» followed by a type Byte. The object
+store and index id are VarInt, the names are StringWithLength.
+
+key | value
+------------------------------------------------------|-------
+«database id, 0, 0, 150, object store id» | existence implies the object store id is in the free list [`ObjectStoreFreeListKey`] - _obsolete_
+«database id, 0, 0, 151, object store id, index id» | existence implies the index id is in the free list [`IndexFreeListKey`] - _obsolete_
+«database id, 0, 0, 200, object store name» | object store id (Int) [`ObjectStoreNamesKey`] - _obsolete_
+«database id, 0, 0, 201, object store id, index name» | index id (Int) [`IndexNamesKey`] - _obsolete_
+
+*** aside
+Free lists (#150, #151) are no longer used. The ID space is assumed to
+be sufficient.
+
+The name-to-id mappings (#200, #201) are written but no longer read;
+instead the mapping is inferred from the object store and index
+metadata. _These should probably be removed._
+***
+
+
+## Object store metadata
+[`ObjectStoreMetaDataKey`]
+
+The prefix is «database id, 0, 0», followed by a type Byte (`50`),
+then the object store id (VarInt), then a metadata type Byte.
+
+key | value
+--------------------------------------------|-------
+«database id, 0, 0, 50, object store id, 0» | object store name (String)
+«database id, 0, 0, 50, object store id, 1» | key path (IDBKeyPath)
+«database id, 0, 0, 50, object store id, 2» | auto increment flag (Bool)
+«database id, 0, 0, 50, object store id, 3» | is evictable (Bool) - _obsolete_
+«database id, 0, 0, 50, object store id, 4» | last version number (Int)
+«database id, 0, 0, 50, object store id, 5» | maximum allocated index id (Int)
+«database id, 0, 0, 50, object store id, 6» | "has key path" flag (Bool) - _obsolete_
+«database id, 0, 0, 50, object store id, 7» | key generator current number (Int)
+
+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`.
+
+*** aside
+Evictable stores (#3) were present in early iterations of the Indexed
+DB specification.
+
+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 **IDBKeyPath**.
+***
+
+*** note
+**Compatibility:**
+If #6 is not present then a String key path can be assumed.
+If #7 is not present, the key generator state is lazily initialized
+using the maximum numeric key present in existing data.
+***
+
+
+## Index metadata
+[`IndexMetaDataKey`]
+
+The prefix is «database id, 0, 0», followed by a type Byte (100), then
+the object store id (VarInt), then the index id (VarInt), then a
+metadata type Byte.
+
+key | value
+-------------------------------------------------------|-------
+«database id, 0, 0, 100, object store id, index id, 0» | index name (String)
+«database id, 0, 0, 100, object store id, index id, 1» | unique flag (Bool)
+«database id, 0, 0, 100, object store id, index id, 2» | key path (IDBKeyPath)
+«database id, 0, 0, 100, object store id, index id, 3» | multi-entry flag (Bool)
+
+*** note
+**Compatibility:**
+If #3 is not present, the multi-entry flag is unset.
+***
+
+
+## Object store data
+[`ObjectStoreDataKey`]
+
+The reserved index id `1` is used in the prefix. The prefix is
+followed the encoded IDB primary key (IDBKey). The data has a
+version prefix followed by the serialized script value.
+
+key | value
+-----------------------------------------------------|-------
+«database id, object store id, 1, user key (IDBKey)» | version (VarInt), serialized script value
+
+
+## "Exists" entry
+[`ExistsEntryKey`]
+
+The reserved index id `2` is used in the prefix. The prefix is
+followed the encoded IDB primary key (IDBKey).
+
+key | value
+-----------------------------------------------------|-------
+«database id, object store id, 2, user key (IDBKey)» | version (VarInt)
+
+
+## Blob entry table
+[`BlobEntryKey`]
+
+The reserved index id `3` is used in the prefix. The prefix is
+followed the encoded IDB primary key.
+
+key | value
+-----------------------------------------------------|-------
+«database id, object store id, 3, user key (IDBKey)» | BlobData
+
+
+## Index data
+[`IndexDataKey`]
+
+The prefix is followed by a type byte, the encoded index key (IDBKey),
+a sequence number (VarInt), and the encoded primary key (IDBKey).
+
+key | value
+----|-------
+«database id, object store id, index id, index key (IDBKey), sequence number (VarInt), primary key (IDBKey)» | version (VarInt), primary key (IDBKey)
+
+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 key itself. `0` is always written now
+(which, as a VarInt, takes a single byte)
+
+*** note
+**Compatibility:**
+The sequence number and primary key, or just the primary key may not
+be present. In that case, enumerators that need the primary key must
+access the value.
+***
diff --git a/chromium/content/browser/leveldb_wrapper_impl.cc b/chromium/content/browser/leveldb_wrapper_impl.cc
new file mode 100644
index 00000000000..7b7deb5a68b
--- /dev/null
+++ b/chromium/content/browser/leveldb_wrapper_impl.cc
@@ -0,0 +1,143 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/leveldb_wrapper_impl.h"
+
+#include "base/bind.h"
+#include "mojo/common/common_type_converters.h"
+
+namespace content {
+
+LevelDBWrapperImpl::LevelDBWrapperImpl(
+ leveldb::LevelDBDatabase* database,
+ const std::string& prefix,
+ size_t max_size,
+ const base::Closure& no_bindings_callback)
+ : prefix_(prefix),
+ no_bindings_callback_(no_bindings_callback),
+ database_(database),
+ bytes_used_(0),
+ max_size_(max_size) {
+ bindings_.set_connection_error_handler(base::Bind(
+ &LevelDBWrapperImpl::OnConnectionError, base::Unretained(this)));
+}
+
+void LevelDBWrapperImpl::Bind(mojom::LevelDBWrapperRequest request) {
+ bindings_.AddBinding(this, std::move(request));
+}
+
+void LevelDBWrapperImpl::AddObserver(mojom::LevelDBObserverPtr observer) {
+ observers_.AddPtr(std::move(observer));
+}
+
+LevelDBWrapperImpl::~LevelDBWrapperImpl() {}
+
+void LevelDBWrapperImpl::Put(mojo::Array<uint8_t> key,
+ mojo::Array<uint8_t> value,
+ const mojo::String& source,
+ const PutCallback& callback) {
+ bool has_old_item = false;
+ mojo::Array<uint8_t> old_value;
+ size_t old_item_size = 0;
+ auto found = map_.find(key);
+ if (found != map_.end()) {
+ old_value = std::move(found->second);
+ old_item_size = key.size() + old_value.size();
+ has_old_item = true;
+ }
+ size_t new_item_size = key.size() + value.size();
+ size_t new_bytes_used = bytes_used_ - old_item_size + new_item_size;
+
+ // Only check quota if the size is increasing, this allows
+ // shrinking changes to pre-existing maps that are over budget.
+ if (new_item_size > old_item_size && new_bytes_used > max_size_) {
+ callback.Run(false);
+ return;
+ }
+
+ map_[key.Clone()] = value.Clone();
+ bytes_used_ = new_bytes_used;
+ if (!has_old_item) {
+ // We added a new key/value pair.
+ observers_.ForAllPtrs(
+ [&key, &value, &source](mojom::LevelDBObserver* observer) {
+ observer->KeyAdded(key.Clone(), value.Clone(), source);
+ });
+ } else {
+ // We changed the value for an existing key.
+ observers_.ForAllPtrs(
+ [&key, &value, &source, &old_value](mojom::LevelDBObserver* observer) {
+ observer->KeyChanged(
+ key.Clone(), value.Clone(), old_value.Clone(), source);
+ });
+ }
+ callback.Run(true);
+}
+
+void LevelDBWrapperImpl::Delete(mojo::Array<uint8_t> key,
+ const mojo::String& source,
+ const DeleteCallback& callback) {
+ auto found = map_.find(key);
+ if (found == map_.end()) {
+ callback.Run(true);
+ return;
+ }
+
+ mojo::Array<uint8_t> old_value = std::move(found->second);
+ map_.erase(found);
+ bytes_used_ -= key.size() + old_value.size();
+ observers_.ForAllPtrs(
+ [&key, &source, &old_value](mojom::LevelDBObserver* observer) {
+ observer->KeyDeleted(
+ key.Clone(), old_value.Clone(), source);
+ });
+ callback.Run(true);
+}
+
+void LevelDBWrapperImpl::DeleteAll(const mojo::String& source,
+ const DeleteAllCallback& callback) {
+ map_.clear();
+ bytes_used_ = 0;
+ observers_.ForAllPtrs(
+ [&source](mojom::LevelDBObserver* observer) {
+ observer->AllDeleted(source);
+ });
+ callback.Run(true);
+}
+
+void LevelDBWrapperImpl::Get(mojo::Array<uint8_t> key,
+ const GetCallback& callback) {
+ auto found = map_.find(key);
+ if (found == map_.end()) {
+ callback.Run(false, mojo::Array<uint8_t>());
+ return;
+ }
+ callback.Run(true, found->second.Clone());
+}
+
+void LevelDBWrapperImpl::GetAll(const mojo::String& source,
+ const GetAllCallback& callback) {
+
+ mojo::Array<mojom::KeyValuePtr> all(map_.size());
+ for (const auto& it : map_) {
+ mojom::KeyValuePtr kv = mojom::KeyValue::New();
+ kv->key = it.first.Clone();
+ kv->value = it.second.Clone();
+ all.push_back(std::move(kv));
+ }
+ callback.Run(leveldb::DatabaseError::OK, std::move(all));
+ observers_.ForAllPtrs(
+ [source](mojom::LevelDBObserver* observer) {
+ observer->GetAllComplete(source);
+ });
+}
+
+void LevelDBWrapperImpl::OnConnectionError() {
+ if (!bindings_.empty())
+ return;
+
+ no_bindings_callback_.Run();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/leveldb_wrapper_impl.h b/chromium/content/browser/leveldb_wrapper_impl.h
new file mode 100644
index 00000000000..c96edf9ca6b
--- /dev/null
+++ b/chromium/content/browser/leveldb_wrapper_impl.h
@@ -0,0 +1,68 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_LEVELDB_WRAPPER_IMPL_H_
+#define CONTENT_BROWSER_LEVELDB_WRAPPER_IMPL_H_
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "content/common/leveldb_wrapper.mojom.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/interface_ptr_set.h"
+
+namespace content {
+
+// This is a wrapper around a leveldb::LevelDBDatabase. It adds a couple of
+// features:
+// 1) Adds the given prefix, if any, to all keys. This allows the sharing of one
+// database across many, possibly untrusted, consumers and ensuring that they
+// can't access each other's values.
+// 2) Enforces a max_size constraint.
+// 3) Informs an observer when the given prefix' values are modified.
+// 4) Throttles requests to avoid overwhelming the disk.
+class LevelDBWrapperImpl : public mojom::LevelDBWrapper {
+ public:
+ // |no_bindings_callback| will be called when this object has no more
+ // bindings.
+ LevelDBWrapperImpl(leveldb::LevelDBDatabase* database,
+ const std::string& prefix,
+ size_t max_size,
+ const base::Closure& no_bindings_callback);
+ ~LevelDBWrapperImpl() override;
+
+ void Bind(mojom::LevelDBWrapperRequest request);
+ void AddObserver(mojom::LevelDBObserverPtr observer);
+
+ private:
+ // LevelDBWrapperImpl:
+ void Put(mojo::Array<uint8_t> key,
+ mojo::Array<uint8_t> value,
+ const mojo::String& source,
+ const PutCallback& callback) override;
+ void Delete(mojo::Array<uint8_t> key,
+ const mojo::String& source,
+ const DeleteCallback& callback) override;
+ void DeleteAll(const mojo::String& source,
+ const DeleteAllCallback& callback) override;
+ void Get(mojo::Array<uint8_t> key, const GetCallback& callback) override;
+ void GetAll(const mojo::String& source,
+ const GetAllCallback& callback) override;
+
+ void OnConnectionError();
+
+ std::string prefix_;
+ mojo::BindingSet<mojom::LevelDBWrapper> bindings_;
+ mojo::InterfacePtrSet<mojom::LevelDBObserver> observers_;
+ base::Closure no_bindings_callback_;
+ leveldb::LevelDBDatabase* database_;
+ std::map<mojo::Array<uint8_t>, mojo::Array<uint8_t>> map_;
+ size_t bytes_used_;
+ size_t max_size_;
+
+ DISALLOW_COPY_AND_ASSIGN(LevelDBWrapperImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_LEVELDB_WRAPPER_IMPL_H_
diff --git a/chromium/content/browser/loader/async_resource_handler.cc b/chromium/content/browser/loader/async_resource_handler.cc
index df08aa79537..599767b01c1 100644
--- a/chromium/content/browser/loader/async_resource_handler.cc
+++ b/chromium/content/browser/loader/async_resource_handler.cc
@@ -10,6 +10,7 @@
#include "base/command_line.h"
#include "base/containers/hash_tables.h"
#include "base/debug/alias.h"
+#include "base/feature_list.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/shared_memory.h"
@@ -26,10 +27,10 @@
#include "content/common/resource_messages.h"
#include "content/common/view_messages.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/resource_response.h"
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
-#include "net/base/net_util.h"
#include "net/log/net_log.h"
#include "net/url_request/redirect_info.h"
@@ -45,6 +46,14 @@ static int kMaxAllocationSize = 1024 * 32;
// The interval for calls to ReportUploadProgress.
static int kUploadProgressIntervalMsec = 10;
+// Used when kOptimizeIPCForSmallResource is enabled.
+// Small resource typically issues two Read call: one for the content itself
+// and another for getting zero response to detect EOF.
+// Inline these two into the IPC message to avoid allocating an expensive
+// SharedMemory for small resources.
+const int kNumLeadingChunk = 2;
+const int kInlinedLeadingChunkSize = 2048;
+
void GetNumericArg(const std::string& name, int* result) {
const std::string& value =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(name);
@@ -65,6 +74,111 @@ void InitializeResourceBufferConstants() {
} // namespace
+// Used when kOptimizeIPCForSmallResource is enabled.
+// The instance hooks the buffer allocation of AsyncResourceHandler, and
+// determine if we should use SharedMemory or should inline the data into
+// the IPC message.
+class AsyncResourceHandler::InliningHelper {
+ public:
+
+ InliningHelper() {}
+ ~InliningHelper() {}
+
+ void OnResponseReceived(const ResourceResponse& response) {
+ InliningStatus status = IsInliningApplicable(response);
+ UMA_HISTOGRAM_ENUMERATION(
+ "Net.ResourceLoader.InliningStatus",
+ static_cast<int>(status),
+ static_cast<int>(InliningStatus::INLINING_STATUS_COUNT));
+ inlining_applicable_ = status == InliningStatus::APPLICABLE;
+ }
+
+ // Returns true if InliningHelper allocates the buffer for inlining.
+ bool PrepareInlineBufferIfApplicable(scoped_refptr<net::IOBuffer>* buf,
+ int* buf_size) {
+ ++num_allocation_;
+
+ // If the server sends the resource in multiple small chunks,
+ // |num_allocation_| may exceed |kNumLeadingChunk|. Disable inlining and
+ // fall back to the regular resource loading path in that case.
+ if (!inlining_applicable_ ||
+ num_allocation_ > kNumLeadingChunk ||
+ !base::FeatureList::IsEnabled(features::kOptimizeIPCForSmallResource)) {
+ return false;
+ }
+
+ leading_chunk_buffer_ = new net::IOBuffer(kInlinedLeadingChunkSize);
+ *buf = leading_chunk_buffer_;
+ *buf_size = kInlinedLeadingChunkSize;
+ return true;
+ }
+
+ // Returns true if the received data is sent to the consumer.
+ bool SendInlinedDataIfApplicable(int bytes_read,
+ int encoded_data_length,
+ IPC::Sender* sender,
+ int request_id) {
+ DCHECK(sender);
+ if (!leading_chunk_buffer_)
+ return false;
+
+ std::vector<char> data(
+ leading_chunk_buffer_->data(),
+ leading_chunk_buffer_->data() + bytes_read);
+ leading_chunk_buffer_ = nullptr;
+
+ sender->Send(new ResourceMsg_InlinedDataChunkReceived(
+ request_id, data, encoded_data_length));
+ return true;
+ }
+
+ void RecordHistogram(int64_t elapsed_time) {
+ if (inlining_applicable_) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Net.ResourceLoader.ResponseStartToEnd.InliningApplicable",
+ elapsed_time, 1, 100000, 100);
+ }
+ }
+
+ private:
+ enum class InliningStatus : int {
+ APPLICABLE = 0,
+ EARLY_ALLOCATION = 1,
+ UNKNOWN_CONTENT_LENGTH = 2,
+ LARGE_CONTENT = 3,
+ HAS_TRANSFER_ENCODING = 4,
+ HAS_CONTENT_ENCODING = 5,
+ INLINING_STATUS_COUNT,
+ };
+
+ InliningStatus IsInliningApplicable(const ResourceResponse& response) {
+ // Disable if the leading chunk is already arrived.
+ if (num_allocation_)
+ return InliningStatus::EARLY_ALLOCATION;
+
+ // Disable if the content is known to be large.
+ if (response.head.content_length > kInlinedLeadingChunkSize)
+ return InliningStatus::LARGE_CONTENT;
+
+ // Disable if the length of the content is unknown.
+ if (response.head.content_length < 0)
+ return InliningStatus::UNKNOWN_CONTENT_LENGTH;
+
+ if (response.head.headers) {
+ if (response.head.headers->HasHeader("Transfer-Encoding"))
+ return InliningStatus::HAS_TRANSFER_ENCODING;
+ if (response.head.headers->HasHeader("Content-Encoding"))
+ return InliningStatus::HAS_CONTENT_ENCODING;
+ }
+
+ return InliningStatus::APPLICABLE;
+ }
+
+ int num_allocation_ = 0;
+ bool inlining_applicable_ = false;
+ scoped_refptr<net::IOBuffer> leading_chunk_buffer_;
+};
+
class DependentIOBuffer : public net::WrappedIOBuffer {
public:
DependentIOBuffer(ResourceBuffer* backing, char* memory)
@@ -87,7 +201,8 @@ AsyncResourceHandler::AsyncResourceHandler(
did_defer_(false),
has_checked_for_sufficient_resources_(false),
sent_received_response_msg_(false),
- sent_first_data_msg_(false),
+ sent_data_buffer_msg_(false),
+ inlining_helper_(new InliningHelper),
last_upload_position_(0),
waiting_for_upload_progress_ack_(false),
reported_transfer_size_(0) {
@@ -207,6 +322,8 @@ bool AsyncResourceHandler::OnResponseStarted(ResourceResponse* response,
// request commits, avoiding the possibility of e.g. zooming the old content
// or of having to layout the new content twice.
+ response_started_ticks_ = base::TimeTicks::Now();
+
progress_timer_.Stop();
const ResourceRequestInfoImpl* info = GetRequestInfo();
if (!info->filter())
@@ -264,6 +381,7 @@ bool AsyncResourceHandler::OnResponseStarted(ResourceResponse* response,
copy));
}
+ inlining_helper_->OnResponseReceived(*response);
return true;
}
@@ -289,6 +407,14 @@ bool AsyncResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
int min_size) {
DCHECK_EQ(-1, min_size);
+ if (!CheckForSufficientResource())
+ return false;
+
+ // Return early if InliningHelper allocates the buffer, so that we should
+ // inline the data into the IPC message without allocating SharedMemory.
+ if (inlining_helper_->PrepareInlineBufferIfApplicable(buf, buf_size))
+ return true;
+
if (!EnsureResourceBufferIsInitialized())
return false;
@@ -312,31 +438,28 @@ bool AsyncResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
if (!filter)
return false;
+ int encoded_data_length = CalculateEncodedDataLengthToReport();
+
+ // Return early if InliningHelper handled the received data.
+ if (inlining_helper_->SendInlinedDataIfApplicable(
+ bytes_read, encoded_data_length, filter, GetRequestID()))
+ return true;
+
buffer_->ShrinkLastAllocation(bytes_read);
- if (!sent_first_data_msg_) {
- base::SharedMemoryHandle handle;
- int size;
- if (!buffer_->ShareToProcess(filter->PeerHandle(), &handle, &size))
+ if (!sent_data_buffer_msg_) {
+ base::SharedMemoryHandle handle = base::SharedMemory::DuplicateHandle(
+ buffer_->GetSharedMemory().handle());
+ if (!base::SharedMemory::IsHandleValid(handle))
return false;
-
- // TODO(erikchen): Temporary debugging. http://crbug.com/527588.
- CHECK_LE(size, kBufferSize);
filter->Send(new ResourceMsg_SetDataBuffer(
- GetRequestID(), handle, size, filter->peer_pid()));
- sent_first_data_msg_ = true;
+ GetRequestID(), handle, buffer_->GetSharedMemory().mapped_size(),
+ filter->peer_pid()));
+ sent_data_buffer_msg_ = true;
}
int data_offset = buffer_->GetLastAllocationOffset();
- int64_t current_transfer_size = request()->GetTotalReceivedBytes();
- int encoded_data_length = current_transfer_size - reported_transfer_size_;
- reported_transfer_size_ = current_transfer_size;
-
- // TODO(erikchen): Temporary debugging. http://crbug.com/527588.
- CHECK_LE(data_offset, kBufferSize);
-
- filter->Send(new ResourceMsg_DataReceivedDebug(GetRequestID(), data_offset));
filter->Send(new ResourceMsg_DataReceived(
GetRequestID(), data_offset, bytes_read, encoded_data_length));
++pending_data_count_;
@@ -350,9 +473,7 @@ bool AsyncResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
}
void AsyncResourceHandler::OnDataDownloaded(int bytes_downloaded) {
- int64_t current_transfer_size = request()->GetTotalReceivedBytes();
- int encoded_data_length = current_transfer_size - reported_transfer_size_;
- reported_transfer_size_ = current_transfer_size;
+ int encoded_data_length = CalculateEncodedDataLengthToReport();
ResourceMessageFilter* filter = GetFilter();
if (filter) {
@@ -412,20 +533,17 @@ void AsyncResourceHandler::OnResponseCompleted(
request()->GetTotalReceivedBytes();
info->filter()->Send(
new ResourceMsg_RequestComplete(GetRequestID(), request_complete_data));
+
+ if (status.is_success())
+ RecordHistogram();
}
bool AsyncResourceHandler::EnsureResourceBufferIsInitialized() {
+ DCHECK(has_checked_for_sufficient_resources_);
+
if (buffer_.get() && buffer_->IsInitialized())
return true;
- if (!has_checked_for_sufficient_resources_) {
- has_checked_for_sufficient_resources_ = true;
- if (!rdh_->HasSufficientResourcesForRequest(request())) {
- controller()->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
- return false;
- }
- }
-
buffer_ = new ResourceBuffer();
return buffer_->Initialize(kBufferSize,
kMinAllocationSize,
@@ -444,4 +562,49 @@ void AsyncResourceHandler::OnDefer() {
request()->LogBlockedBy("AsyncResourceHandler");
}
+bool AsyncResourceHandler::CheckForSufficientResource() {
+ if (has_checked_for_sufficient_resources_)
+ return true;
+ has_checked_for_sufficient_resources_ = true;
+
+ if (rdh_->HasSufficientResourcesForRequest(request()))
+ return true;
+
+ controller()->CancelWithError(net::ERR_INSUFFICIENT_RESOURCES);
+ return false;
+}
+
+int AsyncResourceHandler::CalculateEncodedDataLengthToReport() {
+ int64_t current_transfer_size = request()->GetTotalReceivedBytes();
+ int encoded_data_length = current_transfer_size - reported_transfer_size_;
+ reported_transfer_size_ = current_transfer_size;
+ return encoded_data_length;
+}
+
+void AsyncResourceHandler::RecordHistogram() {
+ int64_t elapsed_time =
+ (base::TimeTicks::Now() - response_started_ticks_).InMicroseconds();
+ int64_t encoded_length = request()->GetTotalReceivedBytes();
+ if (encoded_length < 2 * 1024) {
+ // The resource was smaller than the smallest required buffer size.
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Net.ResourceLoader.ResponseStartToEnd.LT_2kB",
+ elapsed_time, 1, 100000, 100);
+ } else if (encoded_length < 32 * 1024) {
+ // The resource was smaller than single chunk.
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Net.ResourceLoader.ResponseStartToEnd.LT_32kB",
+ elapsed_time, 1, 100000, 100);
+ } else if (encoded_length < 512 * 1024) {
+ // The resource was smaller than single chunk.
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Net.ResourceLoader.ResponseStartToEnd.LT_512kB",
+ elapsed_time, 1, 100000, 100);
+ } else {
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Net.ResourceLoader.ResponseStartToEnd.Over_512kB",
+ elapsed_time, 1, 100000, 100);
+ }
+
+ inlining_helper_->RecordHistogram(elapsed_time);
+}
+
} // namespace content
diff --git a/chromium/content/browser/loader/async_resource_handler.h b/chromium/content/browser/loader/async_resource_handler.h
index d7f70c2b504..09910213360 100644
--- a/chromium/content/browser/loader/async_resource_handler.h
+++ b/chromium/content/browser/loader/async_resource_handler.h
@@ -14,6 +14,7 @@
#include "base/timer/timer.h"
#include "content/browser/loader/resource_handler.h"
#include "content/browser/loader/resource_message_delegate.h"
+#include "net/base/io_buffer.h"
#include "url/gurl.h"
namespace net {
@@ -55,6 +56,8 @@ class AsyncResourceHandler : public ResourceHandler,
void OnDataDownloaded(int bytes_downloaded) override;
private:
+ class InliningHelper;
+
// IPC message handlers:
void OnFollowRedirect(int request_id);
void OnDataReceivedACK(int request_id);
@@ -65,6 +68,9 @@ class AsyncResourceHandler : public ResourceHandler,
bool EnsureResourceBufferIsInitialized();
void ResumeIfDeferred();
void OnDefer();
+ bool CheckForSufficientResource();
+ int CalculateEncodedDataLengthToReport();
+ void RecordHistogram();
scoped_refptr<ResourceBuffer> buffer_;
ResourceDispatcherHostImpl* rdh_;
@@ -79,7 +85,10 @@ class AsyncResourceHandler : public ResourceHandler,
bool has_checked_for_sufficient_resources_;
bool sent_received_response_msg_;
- bool sent_first_data_msg_;
+ bool sent_data_buffer_msg_;
+
+ std::unique_ptr<InliningHelper> inlining_helper_;
+ base::TimeTicks response_started_ticks_;
uint64_t last_upload_position_;
bool waiting_for_upload_progress_ack_;
diff --git a/chromium/content/browser/loader/async_resource_handler_browsertest.cc b/chromium/content/browser/loader/async_resource_handler_browsertest.cc
index 456c31a544f..4a9c4409534 100644
--- a/chromium/content/browser/loader/async_resource_handler_browsertest.cc
+++ b/chromium/content/browser/loader/async_resource_handler_browsertest.cc
@@ -40,10 +40,10 @@ const size_t kPayloadSize = 1062882; // 2*3^12
const size_t kPayloadSize = 28697814; // 2*3^15
#endif
-scoped_ptr<net::test_server::HttpResponse> HandlePostAndRedirectURLs(
- const std::string& request_path,
- const net::test_server::HttpRequest& request) {
- scoped_ptr<net::test_server::BasicHttpResponse> http_response(
+std::unique_ptr<net::test_server::HttpResponse> HandlePostAndRedirectURLs(
+ const std::string& request_path,
+ const net::test_server::HttpRequest& request) {
+ std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
new net::test_server::BasicHttpResponse());
if (base::StartsWith(request.relative_url, kRedirectPostPath,
base::CompareCase::SENSITIVE)) {
@@ -58,7 +58,7 @@ scoped_ptr<net::test_server::HttpResponse> HandlePostAndRedirectURLs(
EXPECT_EQ(request.content.length(), kPayloadSize);
return std::move(http_response);
} else {
- return scoped_ptr<net::test_server::HttpResponse>();
+ return std::unique_ptr<net::test_server::HttpResponse>();
}
}
diff --git a/chromium/content/browser/loader/async_revalidation_driver.cc b/chromium/content/browser/loader/async_revalidation_driver.cc
index 3c5d45bc13b..b04d32af91f 100644
--- a/chromium/content/browser/loader/async_revalidation_driver.cc
+++ b/chromium/content/browser/loader/async_revalidation_driver.cc
@@ -37,8 +37,8 @@ const int kReadTimeoutInSeconds = 30;
} // namespace
AsyncRevalidationDriver::AsyncRevalidationDriver(
- scoped_ptr<net::URLRequest> request,
- scoped_ptr<ResourceThrottle> throttle,
+ std::unique_ptr<net::URLRequest> request,
+ std::unique_ptr<ResourceThrottle> throttle,
const base::Closure& completion_callback)
: request_(std::move(request)),
throttle_(std::move(throttle)),
diff --git a/chromium/content/browser/loader/async_revalidation_driver.h b/chromium/content/browser/loader/async_revalidation_driver.h
index b96e06ebd5c..4caf263cf85 100644
--- a/chromium/content/browser/loader/async_revalidation_driver.h
+++ b/chromium/content/browser/loader/async_revalidation_driver.h
@@ -5,12 +5,12 @@
#ifndef CONTENT_BROWSER_LOADER_ASYNC_REVALIDATION_DRIVER_H_
#define CONTENT_BROWSER_LOADER_ASYNC_REVALIDATION_DRIVER_H_
+#include <memory>
#include <string>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/timer/timer.h"
#include "content/common/content_export.h"
@@ -33,8 +33,8 @@ class CONTENT_EXPORT AsyncRevalidationDriver : public net::URLRequest::Delegate,
public:
// |completion_callback| is guaranteed to be called on completion,
// regardless of success or failure.
- AsyncRevalidationDriver(scoped_ptr<net::URLRequest> request,
- scoped_ptr<ResourceThrottle> throttle,
+ AsyncRevalidationDriver(std::unique_ptr<net::URLRequest> request,
+ std::unique_ptr<ResourceThrottle> throttle,
const base::Closure& completion_callback);
~AsyncRevalidationDriver() override;
@@ -89,8 +89,8 @@ class CONTENT_EXPORT AsyncRevalidationDriver : public net::URLRequest::Delegate,
scoped_refptr<net::IOBuffer> read_buffer_;
base::OneShotTimer timer_;
- scoped_ptr<net::URLRequest> request_;
- scoped_ptr<ResourceThrottle> throttle_;
+ std::unique_ptr<net::URLRequest> request_;
+ std::unique_ptr<ResourceThrottle> throttle_;
base::Closure completion_callback_;
diff --git a/chromium/content/browser/loader/async_revalidation_driver_unittest.cc b/chromium/content/browser/loader/async_revalidation_driver_unittest.cc
index 1f5a7e4b1f0..a39d9fe3eca 100644
--- a/chromium/content/browser/loader/async_revalidation_driver_unittest.cc
+++ b/chromium/content/browser/loader/async_revalidation_driver_unittest.cc
@@ -13,6 +13,7 @@
#include "base/callback.h"
#include "base/location.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "content/public/browser/client_certificate_delegate.h"
#include "content/public/common/content_client.h"
@@ -63,8 +64,8 @@ class ResourceThrottleStub : public ResourceThrottle {
// There are multiple layers of boilerplate needed to use a URLRequestTestJob
// subclass. Subclasses of AsyncRevalidationDriverTest can use
// BindCreateProtocolHandlerCallback() to bypass most of that boilerplate.
-using CreateProtocolHandlerCallback =
- base::Callback<scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>()>;
+using CreateProtocolHandlerCallback = base::Callback<
+ std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>()>;
template <typename T>
CreateProtocolHandlerCallback BindCreateProtocolHandlerCallback() {
@@ -75,8 +76,9 @@ CreateProtocolHandlerCallback BindCreateProtocolHandlerCallback() {
class TemplatedProtocolHandler
: public net::URLRequestJobFactory::ProtocolHandler {
public:
- static scoped_ptr<net::URLRequestJobFactory::ProtocolHandler> Create() {
- return make_scoped_ptr(new TemplatedProtocolHandler());
+ static std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>
+ Create() {
+ return base::WrapUnique(new TemplatedProtocolHandler());
}
// URLRequestJobFactory::ProtocolHandler implementation:
@@ -132,14 +134,15 @@ class AsyncRevalidationDriverTest : public testing::Test {
}
void SetUpAsyncRevalidationDriverWithRequestToUrl(const GURL& url) {
- scoped_ptr<net::URLRequest> request(test_url_request_context_.CreateRequest(
- url, net::DEFAULT_PRIORITY, nullptr /* delegate */));
+ std::unique_ptr<net::URLRequest> request(
+ test_url_request_context_.CreateRequest(url, net::DEFAULT_PRIORITY,
+ nullptr /* delegate */));
raw_ptr_request_ = request.get();
raw_ptr_resource_throttle_ = new ResourceThrottleStub();
// This use of base::Unretained() is safe because |driver_|, and the closure
// passed to it, will be destroyed before this object is.
driver_.reset(new AsyncRevalidationDriver(
- std::move(request), make_scoped_ptr(raw_ptr_resource_throttle_),
+ std::move(request), base::WrapUnique(raw_ptr_resource_throttle_),
base::Bind(&AsyncRevalidationDriverTest::OnAsyncRevalidationComplete,
base::Unretained(this))));
}
@@ -170,7 +173,7 @@ class AsyncRevalidationDriverTest : public testing::Test {
// The AsyncRevalidationDriver owns the URLRequest and the ResourceThrottle.
ResourceThrottleStub* raw_ptr_resource_throttle_;
net::URLRequest* raw_ptr_request_;
- scoped_ptr<AsyncRevalidationDriver> driver_;
+ std::unique_ptr<AsyncRevalidationDriver> driver_;
bool async_revalidation_complete_called_ = false;
};
@@ -233,7 +236,8 @@ class MockClientCertURLRequestJob : public net::URLRequestTestJob {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::Bind(&MockClientCertURLRequestJob::NotifyCertificateRequested,
- weak_factory_.GetWeakPtr(), cert_request_info));
+ weak_factory_.GetWeakPtr(),
+ base::RetainedRef(cert_request_info)));
}
void ContinueWithCertificate(
@@ -276,7 +280,7 @@ class ScopedDontSelectCertificateBrowserClient
void SelectClientCertificate(
WebContents* web_contents,
net::SSLCertRequestInfo* cert_request_info,
- scoped_ptr<ClientCertificateDelegate> delegate) override {
+ std::unique_ptr<ClientCertificateDelegate> delegate) override {
ADD_FAILURE() << "SelectClientCertificate was called.";
}
diff --git a/chromium/content/browser/loader/async_revalidation_manager.cc b/chromium/content/browser/loader/async_revalidation_manager.cc
index aaaeb68ab83..4b364023e37 100644
--- a/chromium/content/browser/loader/async_revalidation_manager.cc
+++ b/chromium/content/browser/loader/async_revalidation_manager.cc
@@ -96,7 +96,7 @@ void AsyncRevalidationManager::BeginAsyncRevalidation(
for_request.url());
std::pair<AsyncRevalidationMap::iterator, bool> insert_result =
in_progress_.insert(AsyncRevalidationMap::value_type(
- async_revalidation_key, scoped_ptr<AsyncRevalidationDriver>()));
+ async_revalidation_key, std::unique_ptr<AsyncRevalidationDriver>()));
if (!insert_result.second) {
// A matching async revalidation is already in progress for this cache; we
// don't need another one.
@@ -107,7 +107,7 @@ void AsyncRevalidationManager::BeginAsyncRevalidation(
headers.AddHeadersFromString(info->original_headers());
// Construct the request.
- scoped_ptr<net::URLRequest> new_request = request_context->CreateRequest(
+ std::unique_ptr<net::URLRequest> new_request = request_context->CreateRequest(
for_request.url(), net::MINIMUM_PRIORITY, nullptr);
new_request->set_method(for_request.method());
@@ -139,7 +139,7 @@ void AsyncRevalidationManager::BeginAsyncRevalidation(
int child_id = info->GetChildID();
int route_id = info->GetRouteID();
- scoped_ptr<ResourceThrottle> throttle =
+ std::unique_ptr<ResourceThrottle> throttle =
scheduler->ScheduleRequest(child_id, route_id, false, new_request.get());
// AsyncRevalidationDriver does not outlive its entry in |in_progress_|,
diff --git a/chromium/content/browser/loader/async_revalidation_manager.h b/chromium/content/browser/loader/async_revalidation_manager.h
index 1070ea9c8bc..e866b4abc97 100644
--- a/chromium/content/browser/loader/async_revalidation_manager.h
+++ b/chromium/content/browser/loader/async_revalidation_manager.h
@@ -6,10 +6,10 @@
#define CONTENT_BROWSER_LOADER_ASYNC_REVALIDATION_MANAGER_H_
#include <map>
+#include <memory>
#include <string>
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
class GURL;
struct ResourceHostMsg_Request;
@@ -89,9 +89,10 @@ class AsyncRevalidationManager {
};
};
- using AsyncRevalidationMap = std::map<AsyncRevalidationKey,
- scoped_ptr<AsyncRevalidationDriver>,
- AsyncRevalidationKey::LessThan>;
+ using AsyncRevalidationMap =
+ std::map<AsyncRevalidationKey,
+ std::unique_ptr<AsyncRevalidationDriver>,
+ AsyncRevalidationKey::LessThan>;
void OnAsyncRevalidationComplete(AsyncRevalidationMap::iterator it);
diff --git a/chromium/content/browser/loader/async_revalidation_manager_browsertest.cc b/chromium/content/browser/loader/async_revalidation_manager_browsertest.cc
index f7999431b42..56b6a128b62 100644
--- a/chromium/content/browser/loader/async_revalidation_manager_browsertest.cc
+++ b/chromium/content/browser/loader/async_revalidation_manager_browsertest.cc
@@ -2,19 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <memory>
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "base/command_line.h"
+#include "base/feature_list.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "base/strings/string16.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
@@ -42,6 +43,12 @@ class AsyncRevalidationManagerBrowserTest : public ContentBrowserTest {
~AsyncRevalidationManagerBrowserTest() override {}
void SetUp() override {
+ base::FeatureList::ClearInstanceForTesting();
+ std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
+ feature_list->InitializeFromCommandLine(
+ "StaleWhileRevalidate2", std::string());
+ base::FeatureList::SetInstance(std::move(feature_list));
+
ASSERT_TRUE(embedded_test_server()->InitializeAndListen());
ContentBrowserTest::SetUp();
}
@@ -50,10 +57,6 @@ class AsyncRevalidationManagerBrowserTest : public ContentBrowserTest {
embedded_test_server()->StartAcceptingConnections();
}
- void SetUpCommandLine(base::CommandLine* command_line) override {
- command_line->AppendSwitch("enable-stale-while-revalidate");
- }
-
base::RunLoop* run_loop() { return &run_loop_; }
int requests_counted() const { return requests_counted_; }
@@ -80,13 +83,15 @@ class AsyncRevalidationManagerBrowserTest : public ContentBrowserTest {
private:
// A request handler which increases the number in the title tag on every
// request.
- scoped_ptr<HttpResponse> CountingRequestHandler(const HttpRequest& request) {
+ std::unique_ptr<HttpResponse> CountingRequestHandler(
+ const HttpRequest& request) {
if (request.relative_url != kCountedHtmlPath)
return nullptr;
int version = ++requests_counted_;
- scoped_ptr<BasicHttpResponse> http_response(StaleWhileRevalidateHeaders());
+ std::unique_ptr<BasicHttpResponse> http_response(
+ StaleWhileRevalidateHeaders());
http_response->set_content(
base::StringPrintf("<title>Version %d</title>", version));
@@ -98,7 +103,8 @@ class AsyncRevalidationManagerBrowserTest : public ContentBrowserTest {
}
// A request handler which increases a cookie value on every request.
- scoped_ptr<HttpResponse> CookieRequestHandler(const HttpRequest& request) {
+ std::unique_ptr<HttpResponse> CookieRequestHandler(
+ const HttpRequest& request) {
static const char kHtml[] =
"<script>\n"
"var intervalId;\n"
@@ -117,7 +123,8 @@ class AsyncRevalidationManagerBrowserTest : public ContentBrowserTest {
int version = ++requests_counted_;
- scoped_ptr<BasicHttpResponse> http_response(StaleWhileRevalidateHeaders());
+ std::unique_ptr<BasicHttpResponse> http_response(
+ StaleWhileRevalidateHeaders());
http_response->AddCustomHeader("Set-Cookie",
base::StringPrintf("version=%d", version));
http_response->set_content(kHtml);
@@ -126,8 +133,8 @@ class AsyncRevalidationManagerBrowserTest : public ContentBrowserTest {
}
// Generate the standard response headers common to all request handlers.
- scoped_ptr<BasicHttpResponse> StaleWhileRevalidateHeaders() {
- scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse);
+ std::unique_ptr<BasicHttpResponse> StaleWhileRevalidateHeaders() {
+ std::unique_ptr<BasicHttpResponse> http_response(new BasicHttpResponse);
http_response->set_code(net::HTTP_OK);
http_response->set_content_type("text/html; charset=utf-8");
http_response->AddCustomHeader("Cache-Control",
@@ -150,6 +157,10 @@ class AsyncRevalidationManagerBrowserTest : public ContentBrowserTest {
// triggers an async revalidation.
IN_PROC_BROWSER_TEST_F(AsyncRevalidationManagerBrowserTest,
StaleWhileRevalidateIsApplied) {
+ // PlzNavigate: Stale while revalidate is disabled.
+ // TODO(clamy): Re-enable the test when there is support.
+ if (IsBrowserSideNavigationEnabled())
+ return;
RegisterCountingRequestHandler();
GURL url(embedded_test_server()->GetURL(kCountedHtmlPath));
@@ -173,6 +184,10 @@ IN_PROC_BROWSER_TEST_F(AsyncRevalidationManagerBrowserTest,
// The fresh cache entry must become visible once the async revalidation request
// has been sent.
IN_PROC_BROWSER_TEST_F(AsyncRevalidationManagerBrowserTest, CacheIsUpdated) {
+ // PlzNavigate: Stale while revalidate is disabled.
+ // TODO(clamy): Re-enable the test when there is support.
+ if (IsBrowserSideNavigationEnabled())
+ return;
using base::ASCIIToUTF16;
RegisterCountingRequestHandler();
GURL url(embedded_test_server()->GetURL(kCountedHtmlPath));
@@ -201,6 +216,10 @@ IN_PROC_BROWSER_TEST_F(AsyncRevalidationManagerBrowserTest, CacheIsUpdated) {
// applied immediately.
IN_PROC_BROWSER_TEST_F(AsyncRevalidationManagerBrowserTest,
CookieSetAsynchronously) {
+ // PlzNavigate: Stale while revalidate is disabled.
+ // TODO(clamy): Re-enable the test when there is support.
+ if (IsBrowserSideNavigationEnabled())
+ return;
RegisterCookieRequestHandler();
GURL url(embedded_test_server()->GetURL(kCookieHtmlPath));
diff --git a/chromium/content/browser/loader/async_revalidation_manager_unittest.cc b/chromium/content/browser/loader/async_revalidation_manager_unittest.cc
index d0ec206130d..09a70929d88 100644
--- a/chromium/content/browser/loader/async_revalidation_manager_unittest.cc
+++ b/chromium/content/browser/loader/async_revalidation_manager_unittest.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/memory/shared_memory_handle.h"
#include "base/pickle.h"
#include "base/run_loop.h"
@@ -216,7 +217,7 @@ class BlackholeFilter : public ResourceMessageFilter {
}
bool Send(IPC::Message* msg) override {
- scoped_ptr<IPC::Message> take_ownership(msg);
+ std::unique_ptr<IPC::Message> take_ownership(msg);
ReleaseHandlesInMessage(*msg);
return true;
}
@@ -265,7 +266,7 @@ ResourceHostMsg_Request CreateResourceRequest(const char* method,
class AsyncRevalidationManagerTest : public ::testing::Test {
protected:
AsyncRevalidationManagerTest(
- scoped_ptr<net::TestNetworkDelegate> network_delegate)
+ std::unique_ptr<net::TestNetworkDelegate> network_delegate)
: thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
network_delegate_(std::move(network_delegate)) {
browser_context_.reset(new TestBrowserContext());
@@ -283,7 +284,7 @@ class AsyncRevalidationManagerTest : public ::testing::Test {
AsyncRevalidationManagerTest()
: AsyncRevalidationManagerTest(
- make_scoped_ptr(new net::TestNetworkDelegate)) {}
+ base::WrapUnique(new net::TestNetworkDelegate)) {}
void TearDown() override {
host_.CancelRequestsForProcess(filter_->child_id());
@@ -315,10 +316,10 @@ class AsyncRevalidationManagerTest : public ::testing::Test {
}
content::TestBrowserThreadBundle thread_bundle_;
- scoped_ptr<TestBrowserContext> browser_context_;
- scoped_ptr<TestURLRequestJobFactory> job_factory_;
+ std::unique_ptr<TestBrowserContext> browser_context_;
+ std::unique_ptr<TestURLRequestJobFactory> job_factory_;
scoped_refptr<BlackholeFilter> filter_;
- scoped_ptr<net::TestNetworkDelegate> network_delegate_;
+ std::unique_ptr<net::TestNetworkDelegate> network_delegate_;
ResourceDispatcherHostImpl host_;
};
@@ -417,7 +418,7 @@ class AsyncRevalidationManagerRecordingTest
public:
AsyncRevalidationManagerRecordingTest()
: AsyncRevalidationManagerTest(
- make_scoped_ptr(new URLRequestRecordingNetworkDelegate)) {}
+ base::WrapUnique(new URLRequestRecordingNetworkDelegate)) {}
void TearDown() override {
EXPECT_TRUE(IsEmpty());
diff --git a/chromium/content/browser/loader/cross_site_resource_handler.cc b/chromium/content/browser/loader/cross_site_resource_handler.cc
index fad4024ee28..c645670d25c 100644
--- a/chromium/content/browser/loader/cross_site_resource_handler.cc
+++ b/chromium/content/browser/loader/cross_site_resource_handler.cc
@@ -63,7 +63,7 @@ struct CrossSiteResponseParams {
};
void OnCrossSiteResponseHelper(const CrossSiteResponseParams& params) {
- scoped_ptr<CrossSiteTransferringRequest> cross_site_transferring_request(
+ std::unique_ptr<CrossSiteTransferringRequest> cross_site_transferring_request(
new CrossSiteTransferringRequest(params.global_request_id));
RenderFrameHostImpl* rfh =
@@ -110,7 +110,7 @@ CheckNavigationPolicyOnUI(GURL real_url, int process_id, int render_frame_id) {
} // namespace
CrossSiteResourceHandler::CrossSiteResourceHandler(
- scoped_ptr<ResourceHandler> next_handler,
+ std::unique_ptr<ResourceHandler> next_handler,
net::URLRequest* request)
: LayeredResourceHandler(request, std::move(next_handler)),
has_started_response_(false),
@@ -327,7 +327,8 @@ void CrossSiteResourceHandler::StartCrossSiteTransition(
int render_frame_id = info->GetRenderFrameID();
transfer_url_chain = request()->url_chain();
referrer = Referrer(GURL(request()->referrer()), info->GetReferrerPolicy());
- ResourceDispatcherHostImpl::Get()->MarkAsTransferredNavigation(global_id);
+ ResourceDispatcherHostImpl::Get()->MarkAsTransferredNavigation(global_id,
+ response_);
BrowserThread::PostTask(
BrowserThread::UI,
diff --git a/chromium/content/browser/loader/cross_site_resource_handler.h b/chromium/content/browser/loader/cross_site_resource_handler.h
index 3c38fc758d4..61cb935a13e 100644
--- a/chromium/content/browser/loader/cross_site_resource_handler.h
+++ b/chromium/content/browser/loader/cross_site_resource_handler.h
@@ -33,7 +33,7 @@ class CrossSiteResourceHandler : public LayeredResourceHandler {
CANCEL_REQUEST
};
- CrossSiteResourceHandler(scoped_ptr<ResourceHandler> next_handler,
+ CrossSiteResourceHandler(std::unique_ptr<ResourceHandler> next_handler,
net::URLRequest* request);
~CrossSiteResourceHandler() override;
diff --git a/chromium/content/browser/loader/cross_site_resource_handler_browsertest.cc b/chromium/content/browser/loader/cross_site_resource_handler_browsertest.cc
index a6df689d032..eea52307c73 100644
--- a/chromium/content/browser/loader/cross_site_resource_handler_browsertest.cc
+++ b/chromium/content/browser/loader/cross_site_resource_handler_browsertest.cc
@@ -97,7 +97,8 @@ class TestResourceDispatcherHostDelegate
CallbackRunningResourceThrottle(net::URLRequest* request,
TestResourceDispatcherHostDelegate* tracker,
const RequestDeferredHook& run_on_start)
- : request_(request),
+ : resumed_(false),
+ request_(request),
tracker_(tracker),
run_on_start_(run_on_start),
weak_factory_(this) {}
@@ -116,9 +117,12 @@ class TestResourceDispatcherHostDelegate
~CallbackRunningResourceThrottle() override {
// If the request is deleted without being cancelled, its status will
// indicate it succeeded, so have to check if the request is still pending
- // as well.
+ // as well. If the request never even started, the throttle will never
+ // resume it. Check this condition as well to allow for early
+ // cancellation.
tracker_->OnTrackedRequestDestroyed(!request_->is_pending() &&
- request_->status().is_success());
+ request_->status().is_success() &&
+ resumed_);
}
// ResourceThrottle implementation:
@@ -127,7 +131,12 @@ class TestResourceDispatcherHostDelegate
}
private:
- void Resume() { controller()->Resume(); }
+ void Resume() {
+ resumed_ = true;
+ controller()->Resume();
+ }
+
+ bool resumed_;
net::URLRequest* request_;
TestResourceDispatcherHostDelegate* tracker_;
RequestDeferredHook run_on_start_;
@@ -163,7 +172,7 @@ class TestResourceDispatcherHostDelegate
RequestDeferredHook run_on_start_;
// This lives on the UI thread.
- scoped_ptr<base::RunLoop> run_loop_;
+ std::unique_ptr<base::RunLoop> run_loop_;
// Set on the IO thread while |run_loop_| is non-nullptr, read on the UI
// thread after deleting run_loop_.
diff --git a/chromium/content/browser/loader/detachable_resource_handler.cc b/chromium/content/browser/loader/detachable_resource_handler.cc
index 786252f5b6b..4e1bb8adee6 100644
--- a/chromium/content/browser/loader/detachable_resource_handler.cc
+++ b/chromium/content/browser/loader/detachable_resource_handler.cc
@@ -24,7 +24,7 @@ namespace content {
DetachableResourceHandler::DetachableResourceHandler(
net::URLRequest* request,
base::TimeDelta cancel_delay,
- scoped_ptr<ResourceHandler> next_handler)
+ std::unique_ptr<ResourceHandler> next_handler)
: ResourceHandler(request),
next_handler_(std::move(next_handler)),
cancel_delay_(cancel_delay),
diff --git a/chromium/content/browser/loader/detachable_resource_handler.h b/chromium/content/browser/loader/detachable_resource_handler.h
index 95072269956..5db9a159795 100644
--- a/chromium/content/browser/loader/detachable_resource_handler.h
+++ b/chromium/content/browser/loader/detachable_resource_handler.h
@@ -5,10 +5,11 @@
#ifndef CONTENT_BROWSER_LOADER_DETACHABLE_RESOURCE_HANDLER_H_
#define CONTENT_BROWSER_LOADER_DETACHABLE_RESOURCE_HANDLER_H_
+#include <memory>
+
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "content/browser/loader/resource_handler.h"
@@ -36,7 +37,7 @@ class DetachableResourceHandler : public ResourceHandler,
public:
DetachableResourceHandler(net::URLRequest* request,
base::TimeDelta cancel_delay,
- scoped_ptr<ResourceHandler> next_handler);
+ std::unique_ptr<ResourceHandler> next_handler);
~DetachableResourceHandler() override;
bool is_detached() const { return next_handler_ == NULL; }
@@ -70,10 +71,10 @@ class DetachableResourceHandler : public ResourceHandler,
void CancelWithError(int error_code) override;
private:
- scoped_ptr<ResourceHandler> next_handler_;
+ std::unique_ptr<ResourceHandler> next_handler_;
scoped_refptr<net::IOBuffer> read_buffer_;
- scoped_ptr<base::OneShotTimer> detached_timer_;
+ std::unique_ptr<base::OneShotTimer> detached_timer_;
base::TimeDelta cancel_delay_;
bool is_deferred_;
diff --git a/chromium/content/browser/loader/global_routing_id.h b/chromium/content/browser/loader/global_routing_id.h
index df5f202c22e..3f5aadf94c0 100644
--- a/chromium/content/browser/loader/global_routing_id.h
+++ b/chromium/content/browser/loader/global_routing_id.h
@@ -7,6 +7,8 @@
#include <tuple>
+#include "ipc/ipc_message.h"
+
namespace content {
// Uniquely identifies the route from which a net::URLRequest comes.
@@ -38,6 +40,33 @@ struct GlobalRoutingID {
}
};
+// Same as GlobalRoutingID except the route_id must be a RenderFrameHost routing
+// id.
+struct GlobalFrameRoutingId {
+ GlobalFrameRoutingId() : child_id(0), frame_routing_id(MSG_ROUTING_NONE) {}
+
+ GlobalFrameRoutingId(int child_id, int frame_routing_id)
+ : child_id(child_id), frame_routing_id(frame_routing_id) {}
+
+ // The unique ID of the child process (different from OS's PID).
+ int child_id;
+
+ // The route ID (unique for each URLRequest source).
+ int frame_routing_id;
+
+ bool operator<(const GlobalFrameRoutingId& other) const {
+ return std::tie(child_id, frame_routing_id) <
+ std::tie(other.child_id, other.frame_routing_id);
+ }
+ bool operator==(const GlobalFrameRoutingId& other) const {
+ return child_id == other.child_id &&
+ frame_routing_id == other.frame_routing_id;
+ }
+ bool operator!=(const GlobalFrameRoutingId& other) const {
+ return !(*this == other);
+ }
+};
+
} // namespace content
#endif // CONTENT_BROWSER_LOADER_GLOBAL_ROUTING_ID_H_
diff --git a/chromium/content/browser/loader/layered_resource_handler.cc b/chromium/content/browser/loader/layered_resource_handler.cc
index 9ff3d55e6f3..eada59a93f8 100644
--- a/chromium/content/browser/loader/layered_resource_handler.cc
+++ b/chromium/content/browser/loader/layered_resource_handler.cc
@@ -12,7 +12,7 @@ namespace content {
LayeredResourceHandler::LayeredResourceHandler(
net::URLRequest* request,
- scoped_ptr<ResourceHandler> next_handler)
+ std::unique_ptr<ResourceHandler> next_handler)
: ResourceHandler(request), next_handler_(std::move(next_handler)) {}
LayeredResourceHandler::~LayeredResourceHandler() {
diff --git a/chromium/content/browser/loader/layered_resource_handler.h b/chromium/content/browser/loader/layered_resource_handler.h
index 6c37dff5b0e..a71b40c41f1 100644
--- a/chromium/content/browser/loader/layered_resource_handler.h
+++ b/chromium/content/browser/loader/layered_resource_handler.h
@@ -5,7 +5,8 @@
#ifndef CONTENT_BROWSER_LOADER_LAYERED_RESOURCE_HANDLER_H_
#define CONTENT_BROWSER_LOADER_LAYERED_RESOURCE_HANDLER_H_
-#include "base/memory/scoped_ptr.h"
+#include <memory>
+
#include "content/browser/loader/resource_handler.h"
#include "content/common/content_export.h"
@@ -20,7 +21,7 @@ namespace content {
class CONTENT_EXPORT LayeredResourceHandler : public ResourceHandler {
public:
LayeredResourceHandler(net::URLRequest* request,
- scoped_ptr<ResourceHandler> next_handler);
+ std::unique_ptr<ResourceHandler> next_handler);
~LayeredResourceHandler() override;
// ResourceHandler implementation:
@@ -40,7 +41,7 @@ class CONTENT_EXPORT LayeredResourceHandler : public ResourceHandler {
bool* defer) override;
void OnDataDownloaded(int bytes_downloaded) override;
- scoped_ptr<ResourceHandler> next_handler_;
+ std::unique_ptr<ResourceHandler> next_handler_;
};
} // namespace content
diff --git a/chromium/content/browser/loader/mime_type_resource_handler.cc b/chromium/content/browser/loader/mime_type_resource_handler.cc
index 3c69c0ad4d2..2d23d131502 100644
--- a/chromium/content/browser/loader/mime_type_resource_handler.cc
+++ b/chromium/content/browser/loader/mime_type_resource_handler.cc
@@ -10,7 +10,7 @@
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
-#include "base/metrics/histogram.h"
+#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
#include "base/thread_task_runner_handle.h"
@@ -35,35 +35,19 @@
#include "net/base/net_errors.h"
#include "net/http/http_content_disposition.h"
#include "net/http/http_response_headers.h"
+#include "net/url_request/url_request.h"
namespace content {
namespace {
-void RecordSnifferMetrics(bool sniffing_blocked,
- bool we_would_like_to_sniff,
- const std::string& mime_type) {
- static base::HistogramBase* nosniff_usage(NULL);
- if (!nosniff_usage)
- nosniff_usage = base::BooleanHistogram::FactoryGet(
- "nosniff.usage", base::HistogramBase::kUmaTargetedHistogramFlag);
- nosniff_usage->AddBoolean(sniffing_blocked);
-
- if (sniffing_blocked) {
- static base::HistogramBase* nosniff_otherwise(NULL);
- if (!nosniff_otherwise)
- nosniff_otherwise = base::BooleanHistogram::FactoryGet(
- "nosniff.otherwise", base::HistogramBase::kUmaTargetedHistogramFlag);
- nosniff_otherwise->AddBoolean(we_would_like_to_sniff);
-
- static base::HistogramBase* nosniff_empty_mime_type(NULL);
- if (!nosniff_empty_mime_type)
- nosniff_empty_mime_type = base::BooleanHistogram::FactoryGet(
- "nosniff.empty_mime_type",
- base::HistogramBase::kUmaTargetedHistogramFlag);
- nosniff_empty_mime_type->AddBoolean(mime_type.empty());
- }
-}
+const char kAcceptHeader[] = "Accept";
+const char kFrameAcceptHeader[] =
+ "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,"
+ "*/*;q=0.8";
+const char kStylesheetAcceptHeader[] = "text/css,*/*;q=0.1";
+const char kImageAcceptHeader[] = "image/webp,image/*,*/*;q=0.8";
+const char kDefaultAcceptHeader[] = "*/*";
// Used to write into an existing IOBuffer at a given offset.
class DependentIOBuffer : public net::WrappedIOBuffer {
@@ -82,7 +66,7 @@ class DependentIOBuffer : public net::WrappedIOBuffer {
} // namespace
MimeTypeResourceHandler::MimeTypeResourceHandler(
- scoped_ptr<ResourceHandler> next_handler,
+ std::unique_ptr<ResourceHandler> next_handler,
ResourceDispatcherHostImpl* host,
PluginService* plugin_service,
net::URLRequest* request)
@@ -141,6 +125,46 @@ bool MimeTypeResourceHandler::OnResponseStarted(ResourceResponse* response,
return ProcessResponse(defer);
}
+bool MimeTypeResourceHandler::OnWillStart(const GURL& url, bool* defer) {
+ const char* accept_value = nullptr;
+ switch (GetRequestInfo()->GetResourceType()) {
+ case RESOURCE_TYPE_MAIN_FRAME:
+ case RESOURCE_TYPE_SUB_FRAME:
+ accept_value = kFrameAcceptHeader;
+ break;
+ case RESOURCE_TYPE_STYLESHEET:
+ accept_value = kStylesheetAcceptHeader;
+ break;
+ case RESOURCE_TYPE_IMAGE:
+ accept_value = kImageAcceptHeader;
+ break;
+ case RESOURCE_TYPE_SCRIPT:
+ case RESOURCE_TYPE_FONT_RESOURCE:
+ case RESOURCE_TYPE_SUB_RESOURCE:
+ case RESOURCE_TYPE_OBJECT:
+ case RESOURCE_TYPE_MEDIA:
+ case RESOURCE_TYPE_WORKER:
+ case RESOURCE_TYPE_SHARED_WORKER:
+ case RESOURCE_TYPE_PREFETCH:
+ case RESOURCE_TYPE_FAVICON:
+ case RESOURCE_TYPE_XHR:
+ case RESOURCE_TYPE_PING:
+ case RESOURCE_TYPE_SERVICE_WORKER:
+ case RESOURCE_TYPE_CSP_REPORT:
+ case RESOURCE_TYPE_PLUGIN_RESOURCE:
+ accept_value = kDefaultAcceptHeader;
+ break;
+ case RESOURCE_TYPE_LAST_TYPE:
+ NOTREACHED();
+ break;
+ }
+
+ // The false parameter prevents overwriting an existing accept header value,
+ // which is needed because JS can manually set an accept header on an XHR.
+ request()->SetExtraRequestHeaderByName(kAcceptHeader, accept_value, false);
+ return next_handler_->OnWillStart(url, defer);
+}
+
bool MimeTypeResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
int* buf_size,
int min_size) {
@@ -260,8 +284,6 @@ bool MimeTypeResourceHandler::ShouldSniffContent() {
bool we_would_like_to_sniff =
net::ShouldSniffMimeType(request()->url(), mime_type);
- RecordSnifferMetrics(sniffing_blocked, we_would_like_to_sniff, mime_type);
-
if (!sniffing_blocked && we_would_like_to_sniff) {
// We're going to look at the data before deciding what the content type
// is. That means we need to delay sending the ResponseStarted message
@@ -324,7 +346,7 @@ bool MimeTypeResourceHandler::SelectPluginHandler(bool* defer,
if (has_plugin)
plugin_path = plugin.path;
std::string payload;
- scoped_ptr<ResourceHandler> handler(host_->MaybeInterceptAsStream(
+ std::unique_ptr<ResourceHandler> handler(host_->MaybeInterceptAsStream(
plugin_path, request(), response_.get(), &payload));
if (handler) {
*handled_by_plugin = true;
@@ -384,19 +406,15 @@ bool MimeTypeResourceHandler::SelectNextHandler(bool* defer) {
// Install download handler
info->set_is_download(true);
- scoped_ptr<ResourceHandler> handler(
- host_->CreateResourceHandlerForDownload(
- request(),
- true, // is_content_initiated
- must_download,
- DownloadItem::kInvalidId,
- scoped_ptr<DownloadSaveInfo>(new DownloadSaveInfo()),
- DownloadUrlParameters::OnStartedCallback()));
+ std::unique_ptr<ResourceHandler> handler(
+ host_->CreateResourceHandlerForDownload(request(),
+ true, // is_content_initiated
+ must_download));
return UseAlternateNextHandler(std::move(handler), std::string());
}
bool MimeTypeResourceHandler::UseAlternateNextHandler(
- scoped_ptr<ResourceHandler> new_handler,
+ std::unique_ptr<ResourceHandler> new_handler,
const std::string& payload_for_old_handler) {
if (response_->head.headers.get() && // Can be NULL if FTP.
response_->head.headers->response_code() / 100 != 2) {
diff --git a/chromium/content/browser/loader/mime_type_resource_handler.h b/chromium/content/browser/loader/mime_type_resource_handler.h
index 9217683584d..cef22b77b65 100644
--- a/chromium/content/browser/loader/mime_type_resource_handler.h
+++ b/chromium/content/browser/loader/mime_type_resource_handler.h
@@ -34,12 +34,16 @@ struct WebPluginInfo;
// subsequent reads until it's done buffering. As a result, the buffer
// returned by the next ResourceHandler must have a capacity of at least
// net::kMaxBytesToSniff * 2.
+//
+// Before a request is sent, this ResourceHandler will also set an appropriate
+// Accept header on the request based on its ResourceType, if one isn't already
+// present.
class CONTENT_EXPORT MimeTypeResourceHandler
: public LayeredResourceHandler,
public ResourceController {
public:
// If ENABLE_PLUGINS is defined, |plugin_service| must not be NULL.
- MimeTypeResourceHandler(scoped_ptr<ResourceHandler> next_handler,
+ MimeTypeResourceHandler(std::unique_ptr<ResourceHandler> next_handler,
ResourceDispatcherHostImpl* host,
PluginService* plugin_service,
net::URLRequest* request);
@@ -49,6 +53,7 @@ class CONTENT_EXPORT MimeTypeResourceHandler
// ResourceHandler implementation:
void SetController(ResourceController* controller) override;
bool OnResponseStarted(ResourceResponse* response, bool* defer) override;
+ bool OnWillStart(const GURL&, bool* defer) override;
bool OnWillRead(scoped_refptr<net::IOBuffer>* buf,
int* buf_size,
int min_size) override;
@@ -77,7 +82,7 @@ class CONTENT_EXPORT MimeTypeResourceHandler
bool SelectPluginHandler(bool* defer, bool* handled_by_plugin);
// Returns false if the request should be cancelled.
bool SelectNextHandler(bool* defer);
- bool UseAlternateNextHandler(scoped_ptr<ResourceHandler> handler,
+ bool UseAlternateNextHandler(std::unique_ptr<ResourceHandler> handler,
const std::string& payload_for_old_handler);
bool ReplayReadCompleted(bool* defer);
diff --git a/chromium/content/browser/loader/mime_type_resource_handler_unittest.cc b/chromium/content/browser/loader/mime_type_resource_handler_unittest.cc
index 1b3ddcdbdf0..ca9de0b4a77 100644
--- a/chromium/content/browser/loader/mime_type_resource_handler_unittest.cc
+++ b/chromium/content/browser/loader/mime_type_resource_handler_unittest.cc
@@ -6,10 +6,11 @@
#include <stdint.h>
+#include <memory>
+
#include "base/files/file_path.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/public/browser/resource_controller.h"
#include "content/public/browser/resource_dispatcher_host_delegate.h"
@@ -45,7 +46,6 @@ class TestResourceHandler : public ResourceHandler {
}
bool OnWillStart(const GURL& url, bool* defer) override {
- NOTREACHED();
return false;
}
@@ -88,17 +88,14 @@ class TestResourceDispatcherHost : public ResourceDispatcherHostImpl {
bool intercepted_as_stream() const { return intercepted_as_stream_; }
- scoped_ptr<ResourceHandler> CreateResourceHandlerForDownload(
+ std::unique_ptr<ResourceHandler> CreateResourceHandlerForDownload(
net::URLRequest* request,
bool is_content_initiated,
- bool must_download,
- uint32_t id,
- scoped_ptr<DownloadSaveInfo> save_info,
- const DownloadUrlParameters::OnStartedCallback& started_cb) override {
- return scoped_ptr<ResourceHandler>(new TestResourceHandler);
+ bool must_download) override {
+ return std::unique_ptr<ResourceHandler>(new TestResourceHandler);
}
- scoped_ptr<ResourceHandler> MaybeInterceptAsStream(
+ std::unique_ptr<ResourceHandler> MaybeInterceptAsStream(
const base::FilePath& plugin_path,
net::URLRequest* request,
ResourceResponse* response,
@@ -106,9 +103,9 @@ class TestResourceDispatcherHost : public ResourceDispatcherHostImpl {
intercepted_as_stream_count_++;
if (stream_has_handler_) {
intercepted_as_stream_ = true;
- return scoped_ptr<ResourceHandler>(new TestResourceHandler);
+ return std::unique_ptr<ResourceHandler>(new TestResourceHandler);
} else {
- return scoped_ptr<ResourceHandler>();
+ return std::unique_ptr<ResourceHandler>();
}
}
@@ -223,6 +220,11 @@ class MimeTypeResourceHandlerTest : public testing::Test {
bool must_download,
ResourceType request_resource_type);
+ std::string TestAcceptHeaderSetting(ResourceType request_resource_type);
+ std::string TestAcceptHeaderSettingWithURLRequest(
+ ResourceType request_resource_type,
+ net::URLRequest* request);
+
private:
// Whether the URL request should be intercepted as a stream.
bool stream_has_handler_;
@@ -237,7 +239,7 @@ bool MimeTypeResourceHandlerTest::TestStreamIsIntercepted(
bool must_download,
ResourceType request_resource_type) {
net::URLRequestContext context;
- scoped_ptr<net::URLRequest> request(context.CreateRequest(
+ std::unique_ptr<net::URLRequest> request(context.CreateRequest(
GURL("http://www.google.com"), net::DEFAULT_PRIORITY, nullptr));
bool is_main_frame = request_resource_type == RESOURCE_TYPE_MAIN_FRAME;
ResourceRequestInfo::AllocateForTesting(
@@ -258,9 +260,10 @@ bool MimeTypeResourceHandlerTest::TestStreamIsIntercepted(
host.SetDelegate(&host_delegate);
TestFakePluginService plugin_service(plugin_available_, plugin_stale_);
- scoped_ptr<ResourceHandler> mime_sniffing_handler(new MimeTypeResourceHandler(
- scoped_ptr<ResourceHandler>(new TestResourceHandler()), &host,
- &plugin_service, request.get()));
+ std::unique_ptr<ResourceHandler> mime_sniffing_handler(
+ new MimeTypeResourceHandler(
+ std::unique_ptr<ResourceHandler>(new TestResourceHandler()), &host,
+ &plugin_service, request.get()));
TestResourceController resource_controller;
mime_sniffing_handler->SetController(&resource_controller);
@@ -276,6 +279,89 @@ bool MimeTypeResourceHandlerTest::TestStreamIsIntercepted(
return host.intercepted_as_stream();
}
+std::string MimeTypeResourceHandlerTest::TestAcceptHeaderSetting(
+ ResourceType request_resource_type) {
+ net::URLRequestContext context;
+ std::unique_ptr<net::URLRequest> request(context.CreateRequest(
+ GURL("http://www.google.com"), net::DEFAULT_PRIORITY, nullptr));
+ return TestAcceptHeaderSettingWithURLRequest(
+ request_resource_type, request.get());
+}
+
+std::string MimeTypeResourceHandlerTest::TestAcceptHeaderSettingWithURLRequest(
+ ResourceType request_resource_type,
+ net::URLRequest* request) {
+ bool is_main_frame = request_resource_type == RESOURCE_TYPE_MAIN_FRAME;
+ ResourceRequestInfo::AllocateForTesting(
+ request,
+ request_resource_type,
+ nullptr, // context
+ 0, // render_process_id
+ 0, // render_view_id
+ 0, // render_frame_id
+ is_main_frame, // is_main_frame
+ false, // parent_is_main_frame
+ false, // allow_download
+ true, // is_async
+ false); // is_using_lofi
+
+ TestResourceDispatcherHost host(stream_has_handler_);
+ TestResourceDispatcherHostDelegate host_delegate(false);
+ host.SetDelegate(&host_delegate);
+
+ std::unique_ptr<ResourceHandler> mime_sniffing_handler(
+ new MimeTypeResourceHandler(
+ std::unique_ptr<ResourceHandler>(new TestResourceHandler()), &host,
+ nullptr, request));
+
+ bool defer = false;
+ mime_sniffing_handler->OnWillStart(request->url(), &defer);
+ content::RunAllPendingInMessageLoop();
+
+ std::string accept_header;
+ request->extra_request_headers().GetHeader("Accept", &accept_header);
+ return accept_header;
+}
+
+// Test that the proper Accept: header is set based on the ResourceType
+TEST_F(MimeTypeResourceHandlerTest, AcceptHeaders) {
+ EXPECT_EQ(
+ "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,"
+ "*/*;q=0.8",
+ TestAcceptHeaderSetting(RESOURCE_TYPE_MAIN_FRAME));
+ EXPECT_EQ(
+ "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,"
+ "*/*;q=0.8",
+ TestAcceptHeaderSetting(RESOURCE_TYPE_SUB_FRAME));
+ EXPECT_EQ("text/css,*/*;q=0.1",
+ TestAcceptHeaderSetting(RESOURCE_TYPE_STYLESHEET));
+ EXPECT_EQ("*/*",
+ TestAcceptHeaderSetting(RESOURCE_TYPE_SCRIPT));
+ EXPECT_EQ("image/webp,image/*,*/*;q=0.8",
+ TestAcceptHeaderSetting(RESOURCE_TYPE_IMAGE));
+ EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_FONT_RESOURCE));
+ EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_SUB_RESOURCE));
+ EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_OBJECT));
+ EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_MEDIA));
+ EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_WORKER));
+ EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_SHARED_WORKER));
+ EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_PREFETCH));
+ EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_FAVICON));
+ EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_XHR));
+ EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_PING));
+ EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_SERVICE_WORKER));
+ EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_CSP_REPORT));
+ EXPECT_EQ("*/*", TestAcceptHeaderSetting(RESOURCE_TYPE_PLUGIN_RESOURCE));
+
+ // Ensure that if an Accept header is already set, it is not overwritten.
+ net::URLRequestContext context;
+ std::unique_ptr<net::URLRequest> request(context.CreateRequest(
+ GURL("http://www.google.com"), net::DEFAULT_PRIORITY, nullptr));
+ request->SetExtraRequestHeaderByName("Accept", "*", true);
+ EXPECT_EQ("*",
+ TestAcceptHeaderSettingWithURLRequest(RESOURCE_TYPE_XHR, request.get()));
+}
+
// Test that stream requests are correctly intercepted under the right
// circumstances. Test is not relevent when plugins are disabled.
#if defined(ENABLE_PLUGINS)
diff --git a/chromium/content/browser/loader/navigation_resource_handler.cc b/chromium/content/browser/loader/navigation_resource_handler.cc
index 94e046dbf0c..6e1694be6cd 100644
--- a/chromium/content/browser/loader/navigation_resource_handler.cc
+++ b/chromium/content/browser/loader/navigation_resource_handler.cc
@@ -44,6 +44,13 @@ void NavigationResourceHandler::FollowRedirect() {
controller()->Resume();
}
+void NavigationResourceHandler::ProceedWithResponse() {
+ // Detach from the loader; at this point, the request is now owned by the
+ // StreamHandle sent in OnResponseStarted.
+ DetachFromCore();
+ controller()->Resume();
+}
+
void NavigationResourceHandler::SetController(ResourceController* controller) {
writer_.set_controller(controller);
ResourceHandler::SetController(controller);
@@ -84,11 +91,9 @@ bool NavigationResourceHandler::OnResponseStarted(ResourceResponse* response,
writer_.InitializeStream(stream_context->registry(),
request()->url().GetOrigin());
- // Detach from the loader; at this point, the request is now owned by the
- // StreamHandle.
DevToolsNetLogObserver::PopulateResponseInfo(request(), response);
core_->NotifyResponseStarted(response, writer_.stream()->CreateHandle());
- DetachFromCore();
+ *defer = true;
return true;
}
diff --git a/chromium/content/browser/loader/navigation_resource_handler.h b/chromium/content/browser/loader/navigation_resource_handler.h
index e898663611c..b5ba53572ca 100644
--- a/chromium/content/browser/loader/navigation_resource_handler.h
+++ b/chromium/content/browser/loader/navigation_resource_handler.h
@@ -26,6 +26,9 @@ class NavigationResourceHandler : public ResourceHandler {
// Called to the loader to resume a paused redirect.
void FollowRedirect();
+ // Called to proceed with the response.
+ void ProceedWithResponse();
+
// ResourceHandler implementation.
void SetController(ResourceController* controller) override;
bool OnRequestRedirected(const net::RedirectInfo& redirect_info,
diff --git a/chromium/content/browser/loader/navigation_resource_throttle.cc b/chromium/content/browser/loader/navigation_resource_throttle.cc
index 44fd0c131ff..63210620c9f 100644
--- a/chromium/content/browser/loader/navigation_resource_throttle.cc
+++ b/chromium/content/browser/loader/navigation_resource_throttle.cc
@@ -4,9 +4,13 @@
#include "content/browser/loader/navigation_resource_throttle.h"
+#include "base/bind.h"
#include "base/callback.h"
+#include "base/location.h"
+#include "base/logging.h"
#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/resource_controller.h"
#include "content/public/browser/resource_request_info.h"
@@ -26,7 +30,7 @@ typedef base::Callback<void(NavigationThrottle::ThrottleCheckResult)>
void SendCheckResultToIOThread(UIChecksPerformedCallback callback,
NavigationThrottle::ThrottleCheckResult result) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- CHECK(result != NavigationThrottle::DEFER);
+ DCHECK_NE(result, NavigationThrottle::DEFER);
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(callback, result));
}
@@ -93,21 +97,28 @@ void CheckWillRedirectRequestOnUIThread(
}
void WillProcessResponseOnUIThread(
+ UIChecksPerformedCallback callback,
int render_process_id,
int render_frame_host_id,
scoped_refptr<net::HttpResponseHeaders> headers) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderFrameHostImpl* render_frame_host =
RenderFrameHostImpl::FromID(render_process_id, render_frame_host_id);
- if (!render_frame_host)
+ if (!render_frame_host) {
+ SendCheckResultToIOThread(callback, NavigationThrottle::PROCEED);
return;
+ }
NavigationHandleImpl* navigation_handle =
render_frame_host->navigation_handle();
- if (!navigation_handle)
+ if (!navigation_handle) {
+ SendCheckResultToIOThread(callback, NavigationThrottle::PROCEED);
return;
+ }
- navigation_handle->ReadyToCommitNavigation(render_frame_host, headers);
+ navigation_handle->WillProcessResponse(
+ render_frame_host, headers,
+ base::Bind(&SendCheckResultToIOThread, callback));
}
} // namespace
@@ -204,10 +215,15 @@ void NavigationResourceThrottle::WillProcessResponse(bool* defer) {
request_->response_headers()->raw_headers());
}
+ UIChecksPerformedCallback callback =
+ base::Bind(&NavigationResourceThrottle::OnUIChecksPerformed,
+ weak_ptr_factory_.GetWeakPtr());
+
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&WillProcessResponseOnUIThread, render_process_id,
+ base::Bind(&WillProcessResponseOnUIThread, callback, render_process_id,
render_frame_id, response_headers));
+ *defer = true;
}
const char* NavigationResourceThrottle::GetNameForLogging() const {
diff --git a/chromium/content/browser/loader/navigation_url_loader.cc b/chromium/content/browser/loader/navigation_url_loader.cc
index e2507650a81..d9b0c927543 100644
--- a/chromium/content/browser/loader/navigation_url_loader.cc
+++ b/chromium/content/browser/loader/navigation_url_loader.cc
@@ -14,16 +14,16 @@ namespace content {
static NavigationURLLoaderFactory* g_factory = nullptr;
-scoped_ptr<NavigationURLLoader> NavigationURLLoader::Create(
+std::unique_ptr<NavigationURLLoader> NavigationURLLoader::Create(
BrowserContext* browser_context,
- scoped_ptr<NavigationRequestInfo> request_info,
+ std::unique_ptr<NavigationRequestInfo> request_info,
ServiceWorkerNavigationHandle* service_worker_handle,
NavigationURLLoaderDelegate* delegate) {
if (g_factory) {
return g_factory->CreateLoader(browser_context, std::move(request_info),
service_worker_handle, delegate);
}
- return scoped_ptr<NavigationURLLoader>(
+ return std::unique_ptr<NavigationURLLoader>(
new NavigationURLLoaderImpl(browser_context, std::move(request_info),
service_worker_handle, delegate));
}
diff --git a/chromium/content/browser/loader/navigation_url_loader.h b/chromium/content/browser/loader/navigation_url_loader.h
index 0ba836a8d67..f7d3280f9b4 100644
--- a/chromium/content/browser/loader/navigation_url_loader.h
+++ b/chromium/content/browser/loader/navigation_url_loader.h
@@ -5,8 +5,9 @@
#ifndef CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_H_
#define CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_H_
+#include <memory>
+
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
namespace content {
@@ -32,9 +33,9 @@ class CONTENT_EXPORT NavigationURLLoader {
// request parameters should not come in as a navigation-specific
// structure. Information like has_user_gesture and
// should_replace_current_entry shouldn't be needed at this layer.
- static scoped_ptr<NavigationURLLoader> Create(
+ static std::unique_ptr<NavigationURLLoader> Create(
BrowserContext* browser_context,
- scoped_ptr<NavigationRequestInfo> request_info,
+ std::unique_ptr<NavigationRequestInfo> request_info,
ServiceWorkerNavigationHandle* service_worker_handle,
NavigationURLLoaderDelegate* delegate);
@@ -47,6 +48,9 @@ class CONTENT_EXPORT NavigationURLLoader {
// request.
virtual void FollowRedirect() = 0;
+ // Called in response to OnResponseStarted to process the response.
+ virtual void ProceedWithResponse() = 0;
+
protected:
NavigationURLLoader() {}
diff --git a/chromium/content/browser/loader/navigation_url_loader_delegate.h b/chromium/content/browser/loader/navigation_url_loader_delegate.h
index 62351aebf5f..201fa86297e 100644
--- a/chromium/content/browser/loader/navigation_url_loader_delegate.h
+++ b/chromium/content/browser/loader/navigation_url_loader_delegate.h
@@ -5,9 +5,10 @@
#ifndef CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_DELEGATE_H_
#define CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_DELEGATE_H_
+#include <memory>
+
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
namespace net {
@@ -33,7 +34,7 @@ class CONTENT_EXPORT NavigationURLLoaderDelegate {
// |body_stream|.
virtual void OnResponseStarted(
const scoped_refptr<ResourceResponse>& response,
- scoped_ptr<StreamHandle> body_stream) = 0;
+ std::unique_ptr<StreamHandle> body_stream) = 0;
// Called if the request fails before receving a response. |net_error| is a
// network error code for the failure. |has_stale_copy_in_cache| is true if
diff --git a/chromium/content/browser/loader/navigation_url_loader_factory.h b/chromium/content/browser/loader/navigation_url_loader_factory.h
index a2fd37136a7..df7ae0c0cb2 100644
--- a/chromium/content/browser/loader/navigation_url_loader_factory.h
+++ b/chromium/content/browser/loader/navigation_url_loader_factory.h
@@ -5,8 +5,9 @@
#ifndef CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_FACTORY_H_
#define CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_FACTORY_H_
+#include <memory>
+
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "content/browser/loader/navigation_url_loader.h"
namespace content {
@@ -15,9 +16,9 @@ namespace content {
// the loader. This is intended for testing.
class NavigationURLLoaderFactory {
public:
- virtual scoped_ptr<NavigationURLLoader> CreateLoader(
+ virtual std::unique_ptr<NavigationURLLoader> CreateLoader(
BrowserContext* browser_context,
- scoped_ptr<NavigationRequestInfo> request_info,
+ std::unique_ptr<NavigationRequestInfo> request_info,
ServiceWorkerNavigationHandle* service_worker_handle,
NavigationURLLoaderDelegate* delegate) = 0;
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl.cc b/chromium/content/browser/loader/navigation_url_loader_impl.cc
index 1f95ce3165f..8b4c670242e 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_impl.cc
@@ -21,7 +21,7 @@ namespace content {
NavigationURLLoaderImpl::NavigationURLLoaderImpl(
BrowserContext* browser_context,
- scoped_ptr<NavigationRequestInfo> request_info,
+ std::unique_ptr<NavigationRequestInfo> request_info,
ServiceWorkerNavigationHandle* service_worker_handle,
NavigationURLLoaderDelegate* delegate)
: delegate_(delegate), weak_factory_(this) {
@@ -62,6 +62,15 @@ void NavigationURLLoaderImpl::FollowRedirect() {
base::Unretained(core_)));
}
+void NavigationURLLoaderImpl::ProceedWithResponse() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&NavigationURLLoaderImplCore::ProceedWithResponse,
+ base::Unretained(core_)));
+}
+
void NavigationURLLoaderImpl::NotifyRequestRedirected(
const net::RedirectInfo& redirect_info,
const scoped_refptr<ResourceResponse>& response) {
@@ -72,7 +81,7 @@ void NavigationURLLoaderImpl::NotifyRequestRedirected(
void NavigationURLLoaderImpl::NotifyResponseStarted(
const scoped_refptr<ResourceResponse>& response,
- scoped_ptr<StreamHandle> body) {
+ std::unique_ptr<StreamHandle> body) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
delegate_->OnResponseStarted(response, std::move(body));
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl.h b/chromium/content/browser/loader/navigation_url_loader_impl.h
index 5c7fcd0d2b0..51131cc12d0 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl.h
+++ b/chromium/content/browser/loader/navigation_url_loader_impl.h
@@ -5,9 +5,10 @@
#ifndef CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_IMPL_H_
#define CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_IMPL_H_
+#include <memory>
+
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "content/browser/loader/navigation_url_loader.h"
@@ -27,14 +28,14 @@ class NavigationURLLoaderImpl : public NavigationURLLoader {
public:
// The caller is responsible for ensuring that |delegate| outlives the loader.
NavigationURLLoaderImpl(BrowserContext* browser_context,
- scoped_ptr<NavigationRequestInfo> request_info,
+ std::unique_ptr<NavigationRequestInfo> request_info,
ServiceWorkerNavigationHandle* service_worker_handle,
NavigationURLLoaderDelegate* delegate);
~NavigationURLLoaderImpl() override;
- // Called in response to OnRequestRedirected to continue processing the
- // request.
+ // NavigationURLLoader implementation.
void FollowRedirect() override;
+ void ProceedWithResponse() override;
private:
friend class NavigationURLLoaderImplCore;
@@ -45,7 +46,7 @@ class NavigationURLLoaderImpl : public NavigationURLLoader {
// Notifies the delegate that the response has started.
void NotifyResponseStarted(const scoped_refptr<ResourceResponse>& response,
- scoped_ptr<StreamHandle> body);
+ std::unique_ptr<StreamHandle> body);
// Notifies the delegate the request failed to return a response.
void NotifyRequestFailed(bool in_cache, int net_error);
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl_core.cc b/chromium/content/browser/loader/navigation_url_loader_impl_core.cc
index bd7ef98f8ea..84001faae57 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl_core.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_impl_core.cc
@@ -39,7 +39,7 @@ NavigationURLLoaderImplCore::~NavigationURLLoaderImplCore() {
void NavigationURLLoaderImplCore::Start(
ResourceContext* resource_context,
ServiceWorkerNavigationHandleCore* service_worker_handle_core,
- scoped_ptr<NavigationRequestInfo> request_info) {
+ std::unique_ptr<NavigationRequestInfo> request_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
@@ -61,6 +61,13 @@ void NavigationURLLoaderImplCore::FollowRedirect() {
resource_handler_->FollowRedirect();
}
+void NavigationURLLoaderImplCore::ProceedWithResponse() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (resource_handler_)
+ resource_handler_->ProceedWithResponse();
+}
+
void NavigationURLLoaderImplCore::NotifyRequestRedirected(
const net::RedirectInfo& redirect_info,
ResourceResponse* response) {
@@ -87,7 +94,7 @@ void NavigationURLLoaderImplCore::NotifyRequestRedirected(
void NavigationURLLoaderImplCore::NotifyResponseStarted(
ResourceResponse* response,
- scoped_ptr<StreamHandle> body) {
+ std::unique_ptr<StreamHandle> body) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
TRACE_EVENT_ASYNC_END0("navigation", "Navigation redirectDelay", this);
TRACE_EVENT_ASYNC_END2("navigation", "Navigation timeToResponseStarted", this,
diff --git a/chromium/content/browser/loader/navigation_url_loader_impl_core.h b/chromium/content/browser/loader/navigation_url_loader_impl_core.h
index b12629d92f2..67a2925dc19 100644
--- a/chromium/content/browser/loader/navigation_url_loader_impl_core.h
+++ b/chromium/content/browser/loader/navigation_url_loader_impl_core.h
@@ -5,8 +5,9 @@
#ifndef CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_IMPL_CORE_H_
#define CONTENT_BROWSER_LOADER_NAVIGATION_URL_LOADER_IMPL_CORE_H_
+#include <memory>
+
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/loader/navigation_url_loader_impl.h"
@@ -41,11 +42,14 @@ class NavigationURLLoaderImplCore {
// Starts the request.
void Start(ResourceContext* resource_context,
ServiceWorkerNavigationHandleCore* service_worker_handle_core,
- scoped_ptr<NavigationRequestInfo> request_info);
+ std::unique_ptr<NavigationRequestInfo> request_info);
// Follows the current pending redirect.
void FollowRedirect();
+ // Proceeds with processing the response.
+ void ProceedWithResponse();
+
void set_resource_handler(NavigationResourceHandler* resource_handler) {
resource_handler_ = resource_handler;
}
@@ -56,7 +60,7 @@ class NavigationURLLoaderImplCore {
// Notifies |loader_| on the UI thread that the response started.
void NotifyResponseStarted(ResourceResponse* response,
- scoped_ptr<StreamHandle> body);
+ std::unique_ptr<StreamHandle> body);
// Notifies |loader_| on the UI thread that the request failed.
void NotifyRequestFailed(bool in_cache, int net_error);
diff --git a/chromium/content/browser/loader/navigation_url_loader_unittest.cc b/chromium/content/browser/loader/navigation_url_loader_unittest.cc
index efee272495d..8b7c5cccd06 100644
--- a/chromium/content/browser/loader/navigation_url_loader_unittest.cc
+++ b/chromium/content/browser/loader/navigation_url_loader_unittest.cc
@@ -2,12 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <memory>
#include <utility>
#include "base/command_line.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "content/browser/frame_host/navigation_request_info.h"
#include "content/browser/loader/navigation_url_loader_delegate.h"
@@ -110,7 +111,7 @@ class TestNavigationURLLoaderDelegate : public NavigationURLLoaderDelegate {
}
void OnResponseStarted(const scoped_refptr<ResourceResponse>& response,
- scoped_ptr<StreamHandle> body) override {
+ std::unique_ptr<StreamHandle> body) override {
response_ = response;
body_ = std::move(body);
ASSERT_TRUE(response_started_);
@@ -132,13 +133,13 @@ class TestNavigationURLLoaderDelegate : public NavigationURLLoaderDelegate {
net::RedirectInfo redirect_info_;
scoped_refptr<ResourceResponse> redirect_response_;
scoped_refptr<ResourceResponse> response_;
- scoped_ptr<StreamHandle> body_;
+ std::unique_ptr<StreamHandle> body_;
int net_error_;
int on_request_handled_counter_;
- scoped_ptr<base::RunLoop> request_redirected_;
- scoped_ptr<base::RunLoop> response_started_;
- scoped_ptr<base::RunLoop> request_failed_;
+ std::unique_ptr<base::RunLoop> request_redirected_;
+ std::unique_ptr<base::RunLoop> response_started_;
+ std::unique_ptr<base::RunLoop> request_failed_;
};
class RequestBlockingResourceDispatcherHostDelegate
@@ -169,7 +170,7 @@ class NavigationURLLoaderTest : public testing::Test {
"test", net::URLRequestTestJob::CreateProtocolHandler());
job_factory_.SetProtocolHandler(
"blob",
- make_scoped_ptr(new StreamProtocolHandler(
+ base::WrapUnique(new StreamProtocolHandler(
StreamContext::GetFor(browser_context_.get())->registry())));
request_context->set_job_factory(&job_factory_);
@@ -178,17 +179,17 @@ class NavigationURLLoaderTest : public testing::Test {
switches::kEnableBrowserSideNavigation);
}
- scoped_ptr<NavigationURLLoader> MakeTestLoader(
+ std::unique_ptr<NavigationURLLoader> MakeTestLoader(
const GURL& url,
NavigationURLLoaderDelegate* delegate) {
- BeginNavigationParams begin_params("GET", std::string(), net::LOAD_NORMAL,
- false, false,
- REQUEST_CONTEXT_TYPE_LOCATION);
+ BeginNavigationParams begin_params(std::string(), net::LOAD_NORMAL, false,
+ false, REQUEST_CONTEXT_TYPE_LOCATION);
CommonNavigationParams common_params;
common_params.url = url;
- scoped_ptr<NavigationRequestInfo> request_info(new NavigationRequestInfo(
- common_params, begin_params, url, url::Origin(url), true, false, -1,
- scoped_refptr<ResourceRequestBody>()));
+ std::unique_ptr<NavigationRequestInfo> request_info(
+ new NavigationRequestInfo(common_params, begin_params, url,
+ url::Origin(url), true, false, -1,
+ scoped_refptr<ResourceRequestBody>()));
return NavigationURLLoader::Create(
browser_context_.get(), std::move(request_info), nullptr, delegate);
@@ -199,8 +200,8 @@ class NavigationURLLoaderTest : public testing::Test {
net::TestDelegate delegate;
net::URLRequestContext* request_context =
browser_context_->GetResourceContext()->GetRequestContext();
- scoped_ptr<net::URLRequest> request(request_context->CreateRequest(
- url, net::DEFAULT_PRIORITY, &delegate));
+ std::unique_ptr<net::URLRequest> request(
+ request_context->CreateRequest(url, net::DEFAULT_PRIORITY, &delegate));
request->Start();
base::RunLoop().Run();
@@ -212,19 +213,22 @@ class NavigationURLLoaderTest : public testing::Test {
protected:
TestBrowserThreadBundle thread_bundle_;
net::URLRequestJobFactoryImpl job_factory_;
- scoped_ptr<TestBrowserContext> browser_context_;
+ std::unique_ptr<TestBrowserContext> browser_context_;
ResourceDispatcherHostImpl host_;
};
// Tests that a basic request works.
TEST_F(NavigationURLLoaderTest, Basic) {
TestNavigationURLLoaderDelegate delegate;
- scoped_ptr<NavigationURLLoader> loader =
+ std::unique_ptr<NavigationURLLoader> loader =
MakeTestLoader(net::URLRequestTestJob::test_url_1(), &delegate);
// Wait for the response to come back.
delegate.WaitForResponseStarted();
+ // Proceed with the response.
+ loader->ProceedWithResponse();
+
// Check the response is correct.
EXPECT_EQ("text/html", delegate.response()->head.mime_type);
EXPECT_EQ(200, delegate.response()->head.headers->response_code());
@@ -239,7 +243,7 @@ TEST_F(NavigationURLLoaderTest, Basic) {
// Tests that request failures are propagated correctly.
TEST_F(NavigationURLLoaderTest, RequestFailed) {
TestNavigationURLLoaderDelegate delegate;
- scoped_ptr<NavigationURLLoader> loader =
+ std::unique_ptr<NavigationURLLoader> loader =
MakeTestLoader(GURL("bogus:bogus"), &delegate);
// Wait for the request to fail as expected.
@@ -253,9 +257,8 @@ TEST_F(NavigationURLLoaderTest, RequestRedirected) {
// Fake a top-level request. Choose a URL which redirects so the request can
// be paused before the response comes in.
TestNavigationURLLoaderDelegate delegate;
- scoped_ptr<NavigationURLLoader> loader =
- MakeTestLoader(net::URLRequestTestJob::test_url_redirect_to_url_2(),
- &delegate);
+ std::unique_ptr<NavigationURLLoader> loader = MakeTestLoader(
+ net::URLRequestTestJob::test_url_redirect_to_url_2(), &delegate);
// Wait for the request to redirect.
delegate.WaitForRequestRedirected();
@@ -271,6 +274,9 @@ TEST_F(NavigationURLLoaderTest, RequestRedirected) {
loader->FollowRedirect();
delegate.WaitForResponseStarted();
+ // Proceed with the response.
+ loader->ProceedWithResponse();
+
// Check the response is correct.
EXPECT_EQ("text/html", delegate.response()->head.mime_type);
EXPECT_EQ(200, delegate.response()->head.headers->response_code());
@@ -288,9 +294,8 @@ TEST_F(NavigationURLLoaderTest, CancelOnDestruct) {
// Fake a top-level request. Choose a URL which redirects so the request can
// be paused before the response comes in.
TestNavigationURLLoaderDelegate delegate;
- scoped_ptr<NavigationURLLoader> loader =
- MakeTestLoader(net::URLRequestTestJob::test_url_redirect_to_url_2(),
- &delegate);
+ std::unique_ptr<NavigationURLLoader> loader = MakeTestLoader(
+ net::URLRequestTestJob::test_url_redirect_to_url_2(), &delegate);
// Wait for the request to redirect.
delegate.WaitForRequestRedirected();
@@ -306,9 +311,8 @@ TEST_F(NavigationURLLoaderTest, CancelOnDestruct) {
// loader race.
TEST_F(NavigationURLLoaderTest, CancelResponseRace) {
TestNavigationURLLoaderDelegate delegate;
- scoped_ptr<NavigationURLLoader> loader =
- MakeTestLoader(net::URLRequestTestJob::test_url_redirect_to_url_2(),
- &delegate);
+ std::unique_ptr<NavigationURLLoader> loader = MakeTestLoader(
+ net::URLRequestTestJob::test_url_redirect_to_url_2(), &delegate);
// Wait for the request to redirect.
delegate.WaitForRequestRedirected();
@@ -328,9 +332,8 @@ TEST_F(NavigationURLLoaderTest, CancelResponseRace) {
// Tests that the loader may be canceled by context.
TEST_F(NavigationURLLoaderTest, CancelByContext) {
TestNavigationURLLoaderDelegate delegate;
- scoped_ptr<NavigationURLLoader> loader =
- MakeTestLoader(net::URLRequestTestJob::test_url_redirect_to_url_2(),
- &delegate);
+ std::unique_ptr<NavigationURLLoader> loader = MakeTestLoader(
+ net::URLRequestTestJob::test_url_redirect_to_url_2(), &delegate);
// Wait for the request to redirect.
delegate.WaitForRequestRedirected();
@@ -351,7 +354,7 @@ TEST_F(NavigationURLLoaderTest, RequestBlocked) {
host_.SetDelegate(&rdh_delegate);
TestNavigationURLLoaderDelegate delegate;
- scoped_ptr<NavigationURLLoader> loader =
+ std::unique_ptr<NavigationURLLoader> loader =
MakeTestLoader(net::URLRequestTestJob::test_url_1(), &delegate);
// Wait for the request to fail as expected.
@@ -366,12 +369,15 @@ TEST_F(NavigationURLLoaderTest, RequestBlocked) {
TEST_F(NavigationURLLoaderTest, LoaderDetached) {
// Fake a top-level request to a URL whose body does not load immediately.
TestNavigationURLLoaderDelegate delegate;
- scoped_ptr<NavigationURLLoader> loader =
+ std::unique_ptr<NavigationURLLoader> loader =
MakeTestLoader(net::URLRequestTestJob::test_url_2(), &delegate);
// Wait for the response to come back.
delegate.WaitForResponseStarted();
+ // Proceed with the response.
+ loader->ProceedWithResponse();
+
// Check the response is correct.
EXPECT_EQ("text/html", delegate.response()->head.mime_type);
EXPECT_EQ(200, delegate.response()->head.headers->response_code());
@@ -390,12 +396,15 @@ TEST_F(NavigationURLLoaderTest, LoaderDetached) {
TEST_F(NavigationURLLoaderTest, OwnedByHandle) {
// Fake a top-level request to a URL whose body does not load immediately.
TestNavigationURLLoaderDelegate delegate;
- scoped_ptr<NavigationURLLoader> loader =
+ std::unique_ptr<NavigationURLLoader> loader =
MakeTestLoader(net::URLRequestTestJob::test_url_2(), &delegate);
// Wait for the response to come back.
delegate.WaitForResponseStarted();
+ // Proceed with the response.
+ loader->ProceedWithResponse();
+
// Release the body.
delegate.ReleaseBody();
base::RunLoop().RunUntilIdle();
diff --git a/chromium/content/browser/loader/power_save_block_resource_throttle.h b/chromium/content/browser/loader/power_save_block_resource_throttle.h
index 4c678421a05..3f6f1d363d7 100644
--- a/chromium/content/browser/loader/power_save_block_resource_throttle.h
+++ b/chromium/content/browser/loader/power_save_block_resource_throttle.h
@@ -5,11 +5,11 @@
#ifndef CONTENT_BROWSER_LOADER_POWER_SAVE_BLOCK_RESOURCE_THROTTLE_H_
#define CONTENT_BROWSER_LOADER_POWER_SAVE_BLOCK_RESOURCE_THROTTLE_H_
+#include <memory>
#include <string>
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/timer/timer.h"
#include "content/public/browser/resource_throttle.h"
@@ -33,7 +33,7 @@ class PowerSaveBlockResourceThrottle : public ResourceThrottle {
const std::string host_;
base::OneShotTimer timer_;
- scoped_ptr<PowerSaveBlocker> power_save_blocker_;
+ std::unique_ptr<PowerSaveBlocker> power_save_blocker_;
DISALLOW_COPY_AND_ASSIGN(PowerSaveBlockResourceThrottle);
};
diff --git a/chromium/content/browser/loader/redirect_to_file_resource_handler.cc b/chromium/content/browser/loader/redirect_to_file_resource_handler.cc
index 670b3343d30..df246069b59 100644
--- a/chromium/content/browser/loader/redirect_to_file_resource_handler.cc
+++ b/chromium/content/browser/loader/redirect_to_file_resource_handler.cc
@@ -61,7 +61,7 @@ static const int kMaxReadBufSize = 524288;
class RedirectToFileResourceHandler::Writer {
public:
Writer(RedirectToFileResourceHandler* handler,
- scoped_ptr<net::FileStream> file_stream,
+ std::unique_ptr<net::FileStream> file_stream,
ShareableFileReference* deletable_file)
: handler_(handler),
file_stream_(std::move(file_stream)),
@@ -119,7 +119,7 @@ class RedirectToFileResourceHandler::Writer {
RedirectToFileResourceHandler* handler_;
- scoped_ptr<net::FileStream> file_stream_;
+ std::unique_ptr<net::FileStream> file_stream_;
bool is_writing_;
// We create a ShareableFileReference that's deletable for the temp file
@@ -130,7 +130,7 @@ class RedirectToFileResourceHandler::Writer {
};
RedirectToFileResourceHandler::RedirectToFileResourceHandler(
- scoped_ptr<ResourceHandler> next_handler,
+ std::unique_ptr<ResourceHandler> next_handler,
net::URLRequest* request)
: LayeredResourceHandler(request, std::move(next_handler)),
buf_(new net::GrowableIOBuffer()),
@@ -243,7 +243,7 @@ void RedirectToFileResourceHandler::OnResponseCompleted(
void RedirectToFileResourceHandler::DidCreateTemporaryFile(
base::File::Error error_code,
- scoped_ptr<net::FileStream> file_stream,
+ std::unique_ptr<net::FileStream> file_stream,
ShareableFileReference* deletable_file) {
DCHECK(!writer_);
if (error_code != base::File::FILE_OK) {
diff --git a/chromium/content/browser/loader/redirect_to_file_resource_handler.h b/chromium/content/browser/loader/redirect_to_file_resource_handler.h
index cd4d60dc058..6f9db88b03a 100644
--- a/chromium/content/browser/loader/redirect_to_file_resource_handler.h
+++ b/chromium/content/browser/loader/redirect_to_file_resource_handler.h
@@ -5,13 +5,14 @@
#ifndef CONTENT_BROWSER_LOADER_REDIRECT_TO_FILE_RESOURCE_HANDLER_H_
#define CONTENT_BROWSER_LOADER_REDIRECT_TO_FILE_RESOURCE_HANDLER_H_
+#include <memory>
+
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/loader/layered_resource_handler.h"
#include "content/browser/loader/temporary_file_stream.h"
@@ -44,7 +45,7 @@ class CONTENT_EXPORT RedirectToFileResourceHandler
// Create a RedirectToFileResourceHandler for |request| which wraps
// |next_handler|.
- RedirectToFileResourceHandler(scoped_ptr<ResourceHandler> next_handler,
+ RedirectToFileResourceHandler(std::unique_ptr<ResourceHandler> next_handler,
net::URLRequest* request);
~RedirectToFileResourceHandler() override;
@@ -68,7 +69,7 @@ class CONTENT_EXPORT RedirectToFileResourceHandler
private:
void DidCreateTemporaryFile(base::File::Error error_code,
- scoped_ptr<net::FileStream> file_stream,
+ std::unique_ptr<net::FileStream> file_stream,
storage::ShareableFileReference* deletable_file);
// Called by RedirectToFileResourceHandler::Writer.
diff --git a/chromium/content/browser/loader/resource_buffer.cc b/chromium/content/browser/loader/resource_buffer.cc
index 9dc63d63a6c..3f5a5c89b97 100644
--- a/chromium/content/browser/loader/resource_buffer.cc
+++ b/chromium/content/browser/loader/resource_buffer.cc
@@ -61,17 +61,9 @@ bool ResourceBuffer::IsInitialized() const {
return shared_mem_.memory() != NULL;
}
-bool ResourceBuffer::ShareToProcess(
- base::ProcessHandle process_handle,
- base::SharedMemoryHandle* shared_memory_handle,
- int* shared_memory_size) {
+base::SharedMemory& ResourceBuffer::GetSharedMemory() {
CHECK(IsInitialized());
-
- if (!shared_mem_.ShareToProcess(process_handle, shared_memory_handle))
- return false;
-
- *shared_memory_size = buf_size_;
- return true;
+ return shared_mem_;
}
bool ResourceBuffer::CanAllocate() const {
diff --git a/chromium/content/browser/loader/resource_buffer.h b/chromium/content/browser/loader/resource_buffer.h
index e323bf19a41..e071d19ba45 100644
--- a/chromium/content/browser/loader/resource_buffer.h
+++ b/chromium/content/browser/loader/resource_buffer.h
@@ -71,13 +71,8 @@ class CONTENT_EXPORT ResourceBuffer
int max_allocation_size);
bool IsInitialized() const;
- // Returns a shared memory handle that can be passed to the given process.
- // The shared memory handle is only intended to be interpretted by code
- // running in the specified process. NOTE: The caller should ensure that
- // this memory eventually be returned to the operating system.
- bool ShareToProcess(base::ProcessHandle process_handle,
- base::SharedMemoryHandle* shared_memory_handle,
- int* shared_memory_size);
+ // Returns a reference to the underlying shared memory.
+ base::SharedMemory& GetSharedMemory();
// Returns true if Allocate will succeed.
bool CanAllocate() const;
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc b/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
index bad9b869c9f..3a3a13d5550 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_browsertest.cc
@@ -280,14 +280,14 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
namespace {
// Handles |request| by serving a redirect response.
-scoped_ptr<net::test_server::HttpResponse> NoContentResponseHandler(
+std::unique_ptr<net::test_server::HttpResponse> NoContentResponseHandler(
const std::string& path,
const net::test_server::HttpRequest& request) {
if (!base::StartsWith(path, request.relative_url,
base::CompareCase::SENSITIVE))
- return scoped_ptr<net::test_server::HttpResponse>();
+ return std::unique_ptr<net::test_server::HttpResponse>();
- scoped_ptr<net::test_server::BasicHttpResponse> http_response(
+ std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
new net::test_server::BasicHttpResponse);
http_response->set_code(net::HTTP_NO_CONTENT);
return std::move(http_response);
@@ -465,14 +465,14 @@ IN_PROC_BROWSER_TEST_F(ResourceDispatcherHostBrowserTest,
namespace {
-scoped_ptr<net::test_server::HttpResponse> HandleRedirectRequest(
+std::unique_ptr<net::test_server::HttpResponse> HandleRedirectRequest(
const std::string& request_path,
const net::test_server::HttpRequest& request) {
if (!base::StartsWith(request.relative_url, request_path,
base::CompareCase::SENSITIVE))
- return scoped_ptr<net::test_server::HttpResponse>();
+ return std::unique_ptr<net::test_server::HttpResponse>();
- scoped_ptr<net::test_server::BasicHttpResponse> http_response(
+ std::unique_ptr<net::test_server::BasicHttpResponse> http_response(
new net::test_server::BasicHttpResponse);
http_response->set_code(net::HTTP_FOUND);
http_response->AddCustomHeader(
@@ -678,7 +678,7 @@ class LoFiResourceDispatcherHostBrowserTest : public ContentBrowserTest {
}
private:
- scoped_ptr<LoFiModeResourceDispatcherHostDelegate> delegate_;
+ std::unique_ptr<LoFiModeResourceDispatcherHostDelegate> delegate_;
};
// Test that navigating with ShouldEnableLoFiMode returning true fetches the
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
index 529b9781866..21f43ed3e5f 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.cc
@@ -7,7 +7,9 @@
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include <stddef.h>
+
#include <algorithm>
+#include <memory>
#include <set>
#include <utility>
#include <vector>
@@ -17,9 +19,10 @@
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/debug/alias.h"
+#include "base/feature_list.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
+#include "base/memory/ptr_util.h"
#include "base/memory/shared_memory.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/field_trial.h"
@@ -39,6 +42,7 @@
#include "content/browser/download/save_file_manager.h"
#include "content/browser/download/save_file_resource_handler.h"
#include "content/browser/fileapi/chrome_blob_storage_context.h"
+#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/navigation_request_info.h"
#include "content/browser/frame_host/navigator.h"
#include "content/browser/loader/async_resource_handler.h"
@@ -61,6 +65,7 @@
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/resource_context_impl.h"
#include "content/browser/service_worker/foreign_fetch_request_handler.h"
+#include "content/browser/service_worker/link_header_support.h"
#include "content/browser/service_worker/service_worker_request_handler.h"
#include "content/browser/streams/stream.h"
#include "content/browser/streams/stream_context.h"
@@ -68,6 +73,7 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/appcache_interfaces.h"
#include "content/common/navigation_params.h"
+#include "content/common/net/url_request_service_worker_data.h"
#include "content/common/resource_messages.h"
#include "content/common/site_isolation_policy.h"
#include "content/common/ssl_status_serialization.h"
@@ -85,6 +91,7 @@
#include "content/public/browser/stream_info.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/common/browser_side_navigation_policy.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/process_type.h"
#include "ipc/ipc_message_macros.h"
@@ -288,9 +295,6 @@ bool ShouldServiceRequest(int process_type,
const net::HttpRequestHeaders& headers,
ResourceMessageFilter* filter,
ResourceContext* resource_context) {
- if (process_type == PROCESS_TYPE_PLUGIN)
- return true;
-
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
@@ -349,31 +353,15 @@ void RemoveDownloadFileFromChildSecurityPolicy(int child_id,
child_id, path);
}
-DownloadInterruptReason CallbackAndReturn(
- const DownloadUrlParameters::OnStartedCallback& started_cb,
- DownloadInterruptReason interrupt_reason) {
- if (started_cb.is_null())
- return interrupt_reason;
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(
- started_cb, static_cast<DownloadItem*>(NULL), interrupt_reason));
-
- return interrupt_reason;
-}
-
-int GetCertID(net::URLRequest* request, int child_id) {
- if (request->ssl_info().cert.get()) {
- return CertStore::GetInstance()->StoreCert(request->ssl_info().cert.get(),
- child_id);
- }
+int GetCertID(CertStore* cert_store, net::URLRequest* request, int child_id) {
+ if (request->ssl_info().cert.get())
+ return cert_store->StoreCert(request->ssl_info().cert.get(), child_id);
return 0;
}
void NotifyRedirectOnUI(int render_process_id,
int render_frame_host,
- scoped_ptr<ResourceRedirectDetails> details) {
+ std::unique_ptr<ResourceRedirectDetails> details) {
RenderFrameHostImpl* host =
RenderFrameHostImpl::FromID(render_process_id, render_frame_host);
WebContentsImpl* web_contents =
@@ -385,7 +373,7 @@ void NotifyRedirectOnUI(int render_process_id,
void NotifyResponseOnUI(int render_process_id,
int render_frame_host,
- scoped_ptr<ResourceRequestDetails> details) {
+ std::unique_ptr<ResourceRequestDetails> details) {
RenderFrameHostImpl* host =
RenderFrameHostImpl::FromID(render_process_id, render_frame_host);
WebContentsImpl* web_contents =
@@ -415,7 +403,7 @@ void AttachRequestBodyBlobDataHandles(
const ResourceRequestBody::Element& element = (*body->elements())[i];
if (element.type() != ResourceRequestBody::Element::TYPE_BLOB)
continue;
- scoped_ptr<storage::BlobDataHandle> handle =
+ std::unique_ptr<storage::BlobDataHandle> handle =
blob_context->GetBlobDataFromUUID(element.blob_uuid());
DCHECK(handle);
if (!handle)
@@ -448,8 +436,9 @@ void LogResourceRequestTimeOnUI(
bool IsUsingLoFi(LoFiState lofi_state,
ResourceDispatcherHostDelegate* delegate,
const net::URLRequest& request,
- ResourceContext* resource_context) {
- if (lofi_state == LOFI_UNSPECIFIED && delegate)
+ ResourceContext* resource_context,
+ bool is_main_frame) {
+ if (lofi_state == LOFI_UNSPECIFIED && delegate && is_main_frame)
return delegate->ShouldEnableLoFiMode(request, resource_context);
return lofi_state == LOFI_ON;
}
@@ -465,8 +454,80 @@ void RecordAbortRapporOnUI(const GURL& url,
GetContentClient()->browser()->RecordURLMetric("Net.ErrAborted.Slow", url);
}
+// The following functions simplify code paths where the UI thread notifies the
+// ResourceDispatcherHostImpl of information pertaining to loading behavior of
+// frame hosts.
+void NotifyForRouteOnIO(
+ base::Callback<void(ResourceDispatcherHostImpl*,
+ const GlobalFrameRoutingId&)> frame_callback,
+ const GlobalFrameRoutingId& global_routing_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
+ if (rdh)
+ frame_callback.Run(rdh, global_routing_id);
+}
+
+void NotifyForRouteFromUI(
+ const GlobalFrameRoutingId& global_routing_id,
+ base::Callback<void(ResourceDispatcherHostImpl*,
+ const GlobalFrameRoutingId&)> frame_callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&NotifyForRouteOnIO, frame_callback, global_routing_id));
+}
+
+void NotifyForRouteSetOnIO(
+ base::Callback<void(ResourceDispatcherHostImpl*,
+ const GlobalFrameRoutingId&)> frame_callback,
+ std::unique_ptr<std::set<GlobalFrameRoutingId>> routing_ids) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ for (const auto& routing_id : *routing_ids)
+ NotifyForRouteOnIO(frame_callback, routing_id);
+}
+
+void NotifyForEachFrameFromUI(
+ RenderFrameHost* root_frame_host,
+ base::Callback<void(ResourceDispatcherHostImpl*,
+ const GlobalFrameRoutingId&)> frame_callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ FrameTree* frame_tree = static_cast<RenderFrameHostImpl*>(root_frame_host)
+ ->frame_tree_node()
+ ->frame_tree();
+ DCHECK_EQ(root_frame_host, frame_tree->GetMainFrame());
+ std::unique_ptr<std::set<GlobalFrameRoutingId>> routing_ids(
+ new std::set<GlobalFrameRoutingId>());
+ for (FrameTreeNode* node : frame_tree->Nodes()) {
+ RenderFrameHostImpl* frame_host = node->current_frame_host();
+ RenderFrameHostImpl* pending_frame_host =
+ IsBrowserSideNavigationEnabled()
+ ? node->render_manager()->speculative_frame_host()
+ : node->render_manager()->pending_frame_host();
+ if (frame_host)
+ routing_ids->insert(frame_host->GetGlobalFrameRoutingId());
+ if (pending_frame_host)
+ routing_ids->insert(pending_frame_host->GetGlobalFrameRoutingId());
+ }
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&NotifyForRouteSetOnIO, frame_callback,
+ base::Passed(std::move(routing_ids))));
+}
+
} // namespace
+LoaderIOThreadNotifier::LoaderIOThreadNotifier(WebContents* web_contents)
+ : WebContentsObserver(web_contents) {}
+
+LoaderIOThreadNotifier::~LoaderIOThreadNotifier() {}
+
+void LoaderIOThreadNotifier::RenderFrameDeleted(
+ RenderFrameHost* render_frame_host) {
+ NotifyForRouteFromUI(
+ static_cast<RenderFrameHostImpl*>(render_frame_host)
+ ->GetGlobalFrameRoutingId(),
+ base::Bind(&ResourceDispatcherHostImpl::OnRenderFrameDeleted));
+}
+
// static
ResourceDispatcherHost* ResourceDispatcherHost::Get() {
return g_resource_dispatcher_host;
@@ -478,14 +539,14 @@ ResourceDispatcherHostImpl::ResourceDispatcherHostImpl()
is_shutdown_(false),
num_in_flight_requests_(0),
max_num_in_flight_requests_(base::SharedMemory::GetHandleLimit()),
- max_num_in_flight_requests_per_process_(
- static_cast<int>(
- max_num_in_flight_requests_ * kMaxRequestsPerProcessRatio)),
+ max_num_in_flight_requests_per_process_(static_cast<int>(
+ max_num_in_flight_requests_ * kMaxRequestsPerProcessRatio)),
max_outstanding_requests_cost_per_process_(
kMaxOutstandingRequestsCostPerProcess),
filter_(NULL),
delegate_(NULL),
- allow_cross_origin_auth_prompt_(false) {
+ allow_cross_origin_auth_prompt_(false),
+ cert_store_for_testing_(nullptr) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(!g_resource_dispatcher_host);
g_resource_dispatcher_host = this;
@@ -503,11 +564,6 @@ ResourceDispatcherHostImpl::ResourceDispatcherHostImpl()
update_load_states_timer_.reset(new base::RepeatingTimer());
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- // This needs to be called to mark the trial as active, even if the result
- // isn't used.
- std::string stale_while_revalidate_trial_group =
- base::FieldTrialList::FindFullName("StaleWhileRevalidate");
// stale-while-revalidate currently doesn't work with browser-side navigation.
// Only enable stale-while-revalidate if browser navigation is not enabled.
//
@@ -515,9 +571,7 @@ ResourceDispatcherHostImpl::ResourceDispatcherHostImpl()
// together. Or disable stale-while-revalidate completely before browser-side
// navigation becomes the default. crbug.com/561610
if (!IsBrowserSideNavigationEnabled() &&
- (base::StartsWith(stale_while_revalidate_trial_group, "Enabled",
- base::CompareCase::SENSITIVE) ||
- command_line->HasSwitch(switches::kEnableStaleWhileRevalidate))) {
+ base::FeatureList::IsEnabled(features::kStaleWhileRevalidate)) {
async_revalidation_manager_.reset(new AsyncRevalidationManager);
}
}
@@ -533,6 +587,42 @@ ResourceDispatcherHostImpl* ResourceDispatcherHostImpl::Get() {
return g_resource_dispatcher_host;
}
+// static
+void ResourceDispatcherHostImpl::ResumeBlockedRequestsForRouteFromUI(
+ const GlobalFrameRoutingId& global_routing_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ NotifyForRouteFromUI(
+ global_routing_id,
+ base::Bind(&ResourceDispatcherHostImpl::ResumeBlockedRequestsForRoute));
+}
+
+// static
+void ResourceDispatcherHostImpl::BlockRequestsForFrameFromUI(
+ RenderFrameHost* root_frame_host) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ NotifyForEachFrameFromUI(
+ root_frame_host,
+ base::Bind(&ResourceDispatcherHostImpl::BlockRequestsForRoute));
+}
+
+// static
+void ResourceDispatcherHostImpl::ResumeBlockedRequestsForFrameFromUI(
+ RenderFrameHost* root_frame_host) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ NotifyForEachFrameFromUI(
+ root_frame_host,
+ base::Bind(&ResourceDispatcherHostImpl::ResumeBlockedRequestsForRoute));
+}
+
+// static
+void ResourceDispatcherHostImpl::CancelBlockedRequestsForFrameFromUI(
+ RenderFrameHostImpl* root_frame_host) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ NotifyForEachFrameFromUI(
+ root_frame_host,
+ base::Bind(&ResourceDispatcherHostImpl::CancelBlockedRequestsForRoute));
+}
+
void ResourceDispatcherHostImpl::SetDelegate(
ResourceDispatcherHostDelegate* delegate) {
delegate_ = delegate;
@@ -543,6 +633,7 @@ void ResourceDispatcherHostImpl::SetAllowCrossOriginAuthPrompt(bool value) {
}
void ResourceDispatcherHostImpl::AddResourceContext(ResourceContext* context) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
active_resource_contexts_.insert(context);
}
@@ -563,14 +654,15 @@ void ResourceDispatcherHostImpl::CancelRequestsForContext(
// the requests to cancel first, and then we start cancelling. We assert at
// the end that there are no more to cancel since the context is about to go
// away.
- typedef std::vector<linked_ptr<ResourceLoader>> LoaderList;
+ typedef std::vector<std::unique_ptr<ResourceLoader>> LoaderList;
LoaderList loaders_to_cancel;
for (LoaderMap::iterator i = pending_loaders_.begin();
i != pending_loaders_.end();) {
- if (i->second->GetRequestInfo()->GetContext() == context) {
- loaders_to_cancel.push_back(i->second);
- IncrementOutstandingRequestsMemory(-1, *i->second->GetRequestInfo());
+ ResourceLoader* loader = i->second.get();
+ if (loader->GetRequestInfo()->GetContext() == context) {
+ loaders_to_cancel.push_back(std::move(i->second));
+ IncrementOutstandingRequestsMemory(-1, *loader->GetRequestInfo());
pending_loaders_.erase(i++);
} else {
++i;
@@ -579,7 +671,7 @@ void ResourceDispatcherHostImpl::CancelRequestsForContext(
for (BlockedLoadersMap::iterator i = blocked_loaders_map_.begin();
i != blocked_loaders_map_.end();) {
- BlockedLoadersList* loaders = i->second;
+ BlockedLoadersList* loaders = i->second.get();
if (loaders->empty()) {
// This can happen if BlockRequestsForRoute() has been called for a route,
// but we haven't blocked any matching requests yet.
@@ -588,38 +680,35 @@ void ResourceDispatcherHostImpl::CancelRequestsForContext(
}
ResourceRequestInfoImpl* info = loaders->front()->GetRequestInfo();
if (info->GetContext() == context) {
+ std::unique_ptr<BlockedLoadersList> deleter(std::move(i->second));
blocked_loaders_map_.erase(i++);
- for (BlockedLoadersList::const_iterator it = loaders->begin();
- it != loaders->end(); ++it) {
- linked_ptr<ResourceLoader> loader = *it;
+ for (auto& loader : *loaders) {
info = loader->GetRequestInfo();
// We make the assumption that all requests on the list have the same
// ResourceContext.
DCHECK_EQ(context, info->GetContext());
IncrementOutstandingRequestsMemory(-1, *info);
- loaders_to_cancel.push_back(loader);
+ loaders_to_cancel.push_back(std::move(loader));
}
- delete loaders;
} else {
++i;
}
}
#ifndef NDEBUG
- for (LoaderList::iterator i = loaders_to_cancel.begin();
- i != loaders_to_cancel.end(); ++i) {
+ for (const auto& loader : loaders_to_cancel) {
// There is no strict requirement that this be the case, but currently
// downloads, streams, detachable requests, transferred requests, and
// browser-owned requests are the only requests that aren't cancelled when
// the associated processes go away. It may be OK for this invariant to
// change in the future, but if this assertion fires without the invariant
// changing, then it's indicative of a leak.
- DCHECK((*i)->GetRequestInfo()->IsDownload() ||
- (*i)->GetRequestInfo()->is_stream() ||
- ((*i)->GetRequestInfo()->detachable_handler() &&
- (*i)->GetRequestInfo()->detachable_handler()->is_detached()) ||
- (*i)->GetRequestInfo()->GetProcessType() == PROCESS_TYPE_BROWSER ||
- (*i)->is_transferring());
+ DCHECK(loader->GetRequestInfo()->IsDownload() ||
+ loader->GetRequestInfo()->is_stream() ||
+ (loader->GetRequestInfo()->detachable_handler() &&
+ loader->GetRequestInfo()->detachable_handler()->is_detached()) ||
+ loader->GetRequestInfo()->GetProcessType() == PROCESS_TYPE_BROWSER ||
+ loader->is_transferring());
}
#endif
@@ -633,15 +722,13 @@ void ResourceDispatcherHostImpl::CancelRequestsForContext(
}
// Validate that no more requests for this context were added.
- for (LoaderMap::const_iterator i = pending_loaders_.begin();
- i != pending_loaders_.end(); ++i) {
+ for (const auto& loader : pending_loaders_) {
// http://crbug.com/90971
- CHECK_NE(i->second->GetRequestInfo()->GetContext(), context);
+ CHECK_NE(loader.second->GetRequestInfo()->GetContext(), context);
}
- for (BlockedLoadersMap::const_iterator i = blocked_loaders_map_.begin();
- i != blocked_loaders_map_.end(); ++i) {
- BlockedLoadersList* loaders = i->second;
+ for (const auto& blocked_loaders : blocked_loaders_map_) {
+ BlockedLoadersList* loaders = blocked_loaders.second.get();
if (!loaders->empty()) {
ResourceRequestInfoImpl* info = loaders->front()->GetRequestInfo();
// http://crbug.com/90971
@@ -651,21 +738,16 @@ void ResourceDispatcherHostImpl::CancelRequestsForContext(
}
DownloadInterruptReason ResourceDispatcherHostImpl::BeginDownload(
- scoped_ptr<net::URLRequest> request,
+ std::unique_ptr<net::URLRequest> request,
const Referrer& referrer,
bool is_content_initiated,
ResourceContext* context,
int child_id,
int render_view_route_id,
int render_frame_route_id,
- bool prefer_cache,
- bool do_not_prompt_for_login,
- scoped_ptr<DownloadSaveInfo> save_info,
- uint32_t download_id,
- const DownloadStartedCallback& started_callback) {
+ bool do_not_prompt_for_login) {
if (is_shutdown_)
- return CallbackAndReturn(started_callback,
- DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN);
+ return DOWNLOAD_INTERRUPT_REASON_USER_SHUTDOWN;
const GURL& url = request->original_url();
@@ -677,21 +759,6 @@ DownloadInterruptReason ResourceDispatcherHostImpl::BeginDownload(
SetReferrerForRequest(request.get(), referrer);
- int extra_load_flags = net::LOAD_NORMAL;
- if (prefer_cache) {
- // If there is upload data attached, only retrieve from cache because there
- // is no current mechanism to prompt the user for their consent for a
- // re-post. For GETs, try to retrieve data from the cache and skip
- // validating the entry if present.
- if (request->get_upload() != NULL)
- extra_load_flags |= net::LOAD_ONLY_FROM_CACHE;
- else
- extra_load_flags |= net::LOAD_PREFERRING_CACHE;
- } else {
- extra_load_flags |= net::LOAD_DISABLE_CACHE;
- }
- request->SetLoadFlags(request->load_flags() | extra_load_flags);
-
// We treat a download as a main frame load, and thus update the policy URL on
// redirects.
//
@@ -704,20 +771,18 @@ DownloadInterruptReason ResourceDispatcherHostImpl::BeginDownload(
// Check if the renderer is permitted to request the requested URL.
if (!ChildProcessSecurityPolicyImpl::GetInstance()->
CanRequestURL(child_id, url)) {
- VLOG(1) << "Denied unauthorized download request for "
- << url.possibly_invalid_spec();
- return CallbackAndReturn(started_callback,
- DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST);
+ DVLOG(1) << "Denied unauthorized download request for "
+ << url.possibly_invalid_spec();
+ return DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST;
}
request_id_--;
const net::URLRequestContext* request_context = context->GetRequestContext();
if (!request_context->job_factory()->IsHandledURL(url)) {
- VLOG(1) << "Download request for unsupported protocol: "
- << url.possibly_invalid_spec();
- return CallbackAndReturn(started_callback,
- DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST);
+ DVLOG(1) << "Download request for unsupported protocol: "
+ << url.possibly_invalid_spec();
+ return DOWNLOAD_INTERRUPT_REASON_NETWORK_INVALID_REQUEST;
}
ResourceRequestInfoImpl* extra_info =
@@ -726,7 +791,8 @@ DownloadInterruptReason ResourceDispatcherHostImpl::BeginDownload(
extra_info->set_do_not_prompt_for_login(do_not_prompt_for_login);
extra_info->AssociateWithRequest(request.get()); // Request takes ownership.
- if (request->url().SchemeIs(url::kBlobScheme)) {
+ if (request->url().SchemeIs(url::kBlobScheme) &&
+ !storage::BlobProtocolHandler::GetRequestBlobDataHandle(request.get())) {
ChromeBlobStorageContext* blob_context =
GetChromeBlobStorageContextForResourceContext(context);
storage::BlobProtocolHandler::SetRequestedBlobDataHandle(
@@ -736,9 +802,8 @@ DownloadInterruptReason ResourceDispatcherHostImpl::BeginDownload(
// From this point forward, the |DownloadResourceHandler| is responsible for
// |started_callback|.
- scoped_ptr<ResourceHandler> handler(CreateResourceHandlerForDownload(
- request.get(), is_content_initiated, true, download_id,
- std::move(save_info), started_callback));
+ std::unique_ptr<ResourceHandler> handler(CreateResourceHandlerForDownload(
+ request.get(), is_content_initiated, true));
BeginRequestInternal(std::move(request), std::move(handler));
@@ -763,16 +828,13 @@ void ResourceDispatcherHostImpl::Shutdown() {
base::Unretained(this)));
}
-scoped_ptr<ResourceHandler>
+std::unique_ptr<ResourceHandler>
ResourceDispatcherHostImpl::CreateResourceHandlerForDownload(
net::URLRequest* request,
bool is_content_initiated,
- bool must_download,
- uint32_t id,
- scoped_ptr<DownloadSaveInfo> save_info,
- const DownloadUrlParameters::OnStartedCallback& started_cb) {
- scoped_ptr<ResourceHandler> handler(new DownloadResourceHandler(
- id, request, started_cb, std::move(save_info)));
+ bool must_download) {
+ std::unique_ptr<ResourceHandler> handler(
+ new DownloadResourceHandler(request));
if (delegate_) {
const ResourceRequestInfoImpl* request_info(
ResourceRequestInfoImpl::ForRequest(request));
@@ -790,7 +852,8 @@ ResourceDispatcherHostImpl::CreateResourceHandlerForDownload(
return handler;
}
-scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::MaybeInterceptAsStream(
+std::unique_ptr<ResourceHandler>
+ResourceDispatcherHostImpl::MaybeInterceptAsStream(
const base::FilePath& plugin_path,
net::URLRequest* request,
ResourceResponse* response,
@@ -803,19 +866,17 @@ scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::MaybeInterceptAsStream(
if (!delegate_ ||
!delegate_->ShouldInterceptResourceAsStream(
request, plugin_path, mime_type, &origin, payload)) {
- return scoped_ptr<ResourceHandler>();
+ return std::unique_ptr<ResourceHandler>();
}
StreamContext* stream_context =
GetStreamContextForResourceContext(info->GetContext());
- scoped_ptr<StreamResourceHandler> handler(
- new StreamResourceHandler(request,
- stream_context->registry(),
- origin));
+ std::unique_ptr<StreamResourceHandler> handler(
+ new StreamResourceHandler(request, stream_context->registry(), origin));
info->set_is_stream(true);
- scoped_ptr<StreamInfo> stream_info(new StreamInfo);
+ std::unique_ptr<StreamInfo> stream_info(new StreamInfo);
stream_info->handle = handler->stream()->CreateHandle();
stream_info->original_url = request->url();
stream_info->mime_type = mime_type;
@@ -907,9 +968,9 @@ void ResourceDispatcherHostImpl::DidReceiveRedirect(ResourceLoader* loader,
return;
// Notify the observers on the UI thread.
- scoped_ptr<ResourceRedirectDetails> detail(new ResourceRedirectDetails(
+ std::unique_ptr<ResourceRedirectDetails> detail(new ResourceRedirectDetails(
loader->request(),
- GetCertID(loader->request(), info->GetChildID()),
+ GetCertID(GetCertStore(), loader->request(), info->GetChildID()),
new_url));
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
@@ -934,6 +995,8 @@ void ResourceDispatcherHostImpl::DidReceiveResponse(ResourceLoader* loader) {
scheduler_.get());
}
+ ProcessRequestForLinkHeaders(request);
+
int render_process_id, render_frame_host;
if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_host))
return;
@@ -945,8 +1008,8 @@ void ResourceDispatcherHostImpl::DidReceiveResponse(ResourceLoader* loader) {
return;
// Notify the observers on the UI thread.
- scoped_ptr<ResourceRequestDetails> detail(new ResourceRequestDetails(
- request, GetCertID(request, info->GetChildID())));
+ std::unique_ptr<ResourceRequestDetails> detail(new ResourceRequestDetails(
+ request, GetCertID(GetCertStore(), request, info->GetChildID())));
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(
@@ -984,6 +1047,27 @@ void ResourceDispatcherHostImpl::DidFinishLoading(ResourceLoader* loader) {
UMA_HISTOGRAM_LONG_TIMES(
"Net.RequestTime2.ErrAborted", request_loading_time);
+ if (loader->request()->url().SchemeIsHTTPOrHTTPS()) {
+ UMA_HISTOGRAM_LONG_TIMES("Net.RequestTime2.ErrAborted.HttpScheme",
+ request_loading_time);
+ } else {
+ UMA_HISTOGRAM_LONG_TIMES("Net.RequestTime2.ErrAborted.NonHttpScheme",
+ request_loading_time);
+ }
+
+ if (loader->request()->GetTotalReceivedBytes() > 0) {
+ UMA_HISTOGRAM_LONG_TIMES("Net.RequestTime2.ErrAborted.NetworkContent",
+ request_loading_time);
+ } else if (loader->request()->received_response_content_length() > 0) {
+ UMA_HISTOGRAM_LONG_TIMES(
+ "Net.RequestTime2.ErrAborted.NoNetworkContent.CachedContent",
+ request_loading_time);
+ } else {
+ UMA_HISTOGRAM_LONG_TIMES(
+ "Net.RequestTime2.ErrAborted.NoBytesRead",
+ request_loading_time);
+ }
+
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&RecordAbortRapporOnUI, loader->request()->url(),
@@ -1071,17 +1155,15 @@ void ResourceDispatcherHostImpl::OnShutdown() {
// Note that we have to do this in 2 passes as we cannot call
// CancelBlockedRequestsForRoute while iterating over
// blocked_loaders_map_, as it modifies it.
- std::set<GlobalRoutingID> ids;
- for (BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.begin();
- iter != blocked_loaders_map_.end(); ++iter) {
- std::pair<std::set<GlobalRoutingID>::iterator, bool> result =
- ids.insert(iter->first);
+ std::set<GlobalFrameRoutingId> ids;
+ for (const auto& blocked_loaders : blocked_loaders_map_) {
+ std::pair<std::set<GlobalFrameRoutingId>::iterator, bool> result =
+ ids.insert(blocked_loaders.first);
// We should not have duplicates.
DCHECK(result.second);
}
- for (std::set<GlobalRoutingID>::const_iterator iter = ids.begin();
- iter != ids.end(); ++iter) {
- CancelBlockedRequestsForRoute(iter->child_id, iter->route_id);
+ for (const auto& routing_id : ids) {
+ CancelBlockedRequestsForRoute(routing_id);
}
scheduler_.reset();
@@ -1170,18 +1252,32 @@ void ResourceDispatcherHostImpl::OnSyncLoad(
sync_result->routing_id());
}
+bool ResourceDispatcherHostImpl::IsRequestIDInUse(
+ const GlobalRequestID& id) const {
+ if (pending_loaders_.find(id) != pending_loaders_.end())
+ return true;
+ for (const auto& blocked_loaders : blocked_loaders_map_) {
+ for (const auto& loader : *blocked_loaders.second.get()) {
+ ResourceRequestInfoImpl* info = loader->GetRequestInfo();
+ if (info->GetGlobalRequestID() == id)
+ return true;
+ }
+ }
+ return false;
+}
+
void ResourceDispatcherHostImpl::UpdateRequestForTransfer(
int child_id,
int route_id,
int request_id,
const ResourceHostMsg_Request& request_data,
- const linked_ptr<ResourceLoader>& loader) {
- ResourceRequestInfoImpl* info = loader->GetRequestInfo();
- GlobalRoutingID old_routing_id(
- request_data.transferred_request_child_id, info->GetRouteID());
+ LoaderMap::iterator iter) {
+ ResourceRequestInfoImpl* info = iter->second->GetRequestInfo();
+ GlobalFrameRoutingId old_routing_id(request_data.transferred_request_child_id,
+ info->GetRenderFrameID());
GlobalRequestID old_request_id(request_data.transferred_request_child_id,
request_data.transferred_request_request_id);
- GlobalRoutingID new_routing_id(child_id, route_id);
+ GlobalFrameRoutingId new_routing_id(child_id, request_data.render_frame_id);
GlobalRequestID new_request_id(child_id, request_id);
// Clear out data that depends on |info| before updating it.
@@ -1192,7 +1288,11 @@ void ResourceDispatcherHostImpl::UpdateRequestForTransfer(
bool should_update_count = info->counted_as_in_flight_request();
if (should_update_count)
IncrementOutstandingRequestsCount(-1, info);
- pending_loaders_.erase(old_request_id);
+
+ DCHECK(pending_loaders_.find(old_request_id) == iter);
+ std::unique_ptr<ResourceLoader> loader = std::move(iter->second);
+ ResourceLoader* loader_ptr = loader.get();
+ pending_loaders_.erase(iter);
// ResourceHandlers should always get state related to the request from the
// ResourceRequestInfo rather than caching it locally. This lets us update
@@ -1201,9 +1301,17 @@ void ResourceDispatcherHostImpl::UpdateRequestForTransfer(
request_data.origin_pid, request_id,
filter_->GetWeakPtr());
+ // If a certificate is stored with the ResourceResponse, it has to be
+ // updated to be associated with the new process.
+ if (loader->transferring_response()) {
+ UpdateResponseCertificateForTransfer(loader->transferring_response(),
+ loader->request()->ssl_info(),
+ child_id);
+ }
+
// Update maps that used the old IDs, if necessary. Some transfers in tests
// do not actually use a different ID, so not all maps need to be updated.
- pending_loaders_[new_request_id] = loader;
+ pending_loaders_[new_request_id] = std::move(loader);
IncrementOutstandingRequestsMemory(1, *info);
if (should_update_count)
IncrementOutstandingRequestsCount(1, info);
@@ -1211,7 +1319,7 @@ void ResourceDispatcherHostImpl::UpdateRequestForTransfer(
if (blocked_loaders_map_.find(old_routing_id) !=
blocked_loaders_map_.end()) {
blocked_loaders_map_[new_routing_id] =
- blocked_loaders_map_[old_routing_id];
+ std::move(blocked_loaders_map_[old_routing_id]);
blocked_loaders_map_.erase(old_routing_id);
}
}
@@ -1231,15 +1339,21 @@ void ResourceDispatcherHostImpl::UpdateRequestForTransfer(
}
AppCacheInterceptor::CompleteCrossSiteTransfer(
- loader->request(),
+ loader_ptr->request(),
child_id,
- request_data.appcache_host_id);
+ request_data.appcache_host_id,
+ filter_);
ServiceWorkerRequestHandler* handler =
- ServiceWorkerRequestHandler::GetHandler(loader->request());
+ ServiceWorkerRequestHandler::GetHandler(loader_ptr->request());
if (handler) {
- handler->CompleteCrossSiteTransfer(
- child_id, request_data.service_worker_provider_id);
+ if (!handler->SanityCheckIsSameContext(filter_->service_worker_context())) {
+ bad_message::ReceivedBadMessage(
+ filter_, bad_message::RDHI_WRONG_STORAGE_PARTITION);
+ } else {
+ handler->CompleteCrossSiteTransfer(
+ child_id, request_data.service_worker_provider_id);
+ }
}
// We should have a CrossSiteResourceHandler to finish the transfer.
@@ -1254,10 +1368,19 @@ void ResourceDispatcherHostImpl::BeginRequest(
int process_type = filter_->process_type();
int child_id = filter_->child_id();
+ // Reject request id that's currently in use.
+ if (IsRequestIDInUse(GlobalRequestID(child_id, request_id))) {
+ bad_message::ReceivedBadMessage(filter_,
+ bad_message::RDH_INVALID_REQUEST_ID);
+ return;
+ }
+
// PlzNavigate: reject invalid renderer main resource request.
- if (IsBrowserSideNavigationEnabled() &&
- IsResourceTypeFrame(request_data.resource_type) &&
- !request_data.url.SchemeIs(url::kBlobScheme)) {
+ bool is_navigation_stream_request =
+ IsBrowserSideNavigationEnabled() &&
+ IsResourceTypeFrame(request_data.resource_type);
+ if (is_navigation_stream_request &&
+ !request_data.resource_body_stream_url.SchemeIs(url::kBlobScheme)) {
bad_message::ReceivedBadMessage(filter_, bad_message::RDH_INVALID_URL);
return;
}
@@ -1284,10 +1407,9 @@ void ResourceDispatcherHostImpl::BeginRequest(
// If the request is transferring to a new process, we can update our
// state and let it resume with its existing ResourceHandlers.
if (it->second->is_transferring()) {
- linked_ptr<ResourceLoader> deferred_loader = it->second;
+ ResourceLoader* deferred_loader = it->second.get();
UpdateRequestForTransfer(child_id, route_id, request_id,
- request_data, deferred_loader);
-
+ request_data, it);
deferred_loader->CompleteTransfer();
} else {
bad_message::ReceivedBadMessage(
@@ -1325,14 +1447,29 @@ void ResourceDispatcherHostImpl::BeginRequest(
}
// Construct the request.
- scoped_ptr<net::URLRequest> new_request = request_context->CreateRequest(
- request_data.url, request_data.priority, NULL);
+ std::unique_ptr<net::URLRequest> new_request = request_context->CreateRequest(
+ is_navigation_stream_request ? request_data.resource_body_stream_url
+ : request_data.url,
+ request_data.priority, nullptr);
+
+ // PlzNavigate: Always set the method to GET when gaining access to the
+ // stream that contains the response body of a navigation. Otherwise the data
+ // that was already fetched by the browser will not be transmitted to the
+ // renderer.
+ if (is_navigation_stream_request)
+ new_request->set_method("GET");
+ else
+ new_request->set_method(request_data.method);
- new_request->set_method(request_data.method);
new_request->set_first_party_for_cookies(
request_data.first_party_for_cookies);
new_request->set_initiator(request_data.request_initiator);
+ if (request_data.originated_from_service_worker) {
+ new_request->SetUserData(URLRequestServiceWorkerData::kUserDataKey,
+ new URLRequestServiceWorkerData());
+ }
+
// If the request is a MAIN_FRAME request, the first-party URL gets updated on
// redirects.
if (request_data.resource_type == RESOURCE_TYPE_MAIN_FRAME) {
@@ -1426,28 +1563,20 @@ void ResourceDispatcherHostImpl::BeginRequest(
ResourceRequestInfoImpl* extra_info = new ResourceRequestInfoImpl(
process_type, child_id, route_id,
-1, // frame_tree_node_id
- request_data.origin_pid,
- request_id,
- request_data.render_frame_id,
- request_data.is_main_frame,
- request_data.parent_is_main_frame,
- request_data.resource_type,
- request_data.transition_type,
+ request_data.origin_pid, request_id, request_data.render_frame_id,
+ request_data.is_main_frame, request_data.parent_is_main_frame,
+ request_data.resource_type, request_data.transition_type,
request_data.should_replace_current_entry,
false, // is download
false, // is stream
- allow_download,
- request_data.has_user_gesture,
- request_data.enable_load_timing,
- request_data.enable_upload_progress,
- do_not_prompt_for_login,
- request_data.referrer_policy,
- request_data.visiblity_state,
- resource_context, filter_->GetWeakPtr(),
- report_raw_headers,
- !is_sync_load,
- IsUsingLoFi(request_data.lofi_state, delegate_,
- *new_request, resource_context),
+ allow_download, request_data.has_user_gesture,
+ request_data.enable_load_timing, request_data.enable_upload_progress,
+ do_not_prompt_for_login, request_data.referrer_policy,
+ request_data.visiblity_state, resource_context, filter_->GetWeakPtr(),
+ report_raw_headers, !is_sync_load,
+ IsUsingLoFi(request_data.lofi_state, delegate_, *new_request,
+ resource_context,
+ request_data.resource_type == RESOURCE_TYPE_MAIN_FRAME),
support_async_revalidation ? request_data.headers : std::string());
// Request takes ownership.
extra_info->AssociateWithRequest(new_request.get());
@@ -1492,17 +1621,16 @@ void ResourceDispatcherHostImpl::BeginRequest(
request_data.appcache_host_id, request_data.resource_type,
request_data.should_reset_appcache);
- scoped_ptr<ResourceHandler> handler(
- CreateResourceHandler(
- new_request.get(),
- request_data, sync_result, route_id, process_type, child_id,
- resource_context));
+ std::unique_ptr<ResourceHandler> handler(CreateResourceHandler(
+ new_request.get(), request_data, sync_result, route_id, process_type,
+ child_id, resource_context));
if (handler)
BeginRequestInternal(std::move(new_request), std::move(handler));
}
-scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::CreateResourceHandler(
+std::unique_ptr<ResourceHandler>
+ResourceDispatcherHostImpl::CreateResourceHandler(
net::URLRequest* request,
const ResourceHostMsg_Request& request_data,
IPC::Message* sync_result,
@@ -1515,12 +1643,12 @@ scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::CreateResourceHandler(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"456331 ResourceDispatcherHostImpl::CreateResourceHandler"));
// Construct the IPC resource handler.
- scoped_ptr<ResourceHandler> handler;
+ std::unique_ptr<ResourceHandler> handler;
if (sync_result) {
// download_to_file is not supported for synchronous requests.
if (request_data.download_to_file) {
bad_message::ReceivedBadMessage(filter_, bad_message::RDH_BAD_DOWNLOAD);
- return scoped_ptr<ResourceHandler>();
+ return std::unique_ptr<ResourceHandler>();
}
handler.reset(new SyncResourceHandler(request, sync_result, this));
@@ -1569,14 +1697,15 @@ scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::CreateResourceHandler(
child_id, route_id, std::move(handler));
}
-scoped_ptr<ResourceHandler> ResourceDispatcherHostImpl::AddStandardHandlers(
+std::unique_ptr<ResourceHandler>
+ResourceDispatcherHostImpl::AddStandardHandlers(
net::URLRequest* request,
ResourceType resource_type,
ResourceContext* resource_context,
AppCacheService* appcache_service,
int child_id,
int route_id,
- scoped_ptr<ResourceHandler> handler) {
+ std::unique_ptr<ResourceHandler> handler) {
// PlzNavigate: do not add ResourceThrottles for main resource requests from
// the renderer. Decisions about the navigation should have been done in the
// initial request.
@@ -1748,18 +1877,19 @@ ResourceRequestInfoImpl* ResourceDispatcherHostImpl::CreateRequestInfo(
std::string()); // original_headers
}
+void ResourceDispatcherHostImpl::OnRenderFrameDeleted(
+ const GlobalFrameRoutingId& global_routing_id) {
+ CancelRequestsForRoute(global_routing_id);
+}
+
void ResourceDispatcherHostImpl::OnRenderViewHostCreated(int child_id,
- int route_id,
- bool is_visible,
- bool is_audible) {
- scheduler_->OnClientCreated(child_id, route_id, is_visible, is_audible);
+ int route_id) {
+ scheduler_->OnClientCreated(child_id, route_id);
}
-void ResourceDispatcherHostImpl::OnRenderViewHostDeleted(
- int child_id,
- int route_id) {
+void ResourceDispatcherHostImpl::OnRenderViewHostDeleted(int child_id,
+ int route_id) {
scheduler_->OnClientDeleted(child_id, route_id);
- CancelRequestsForRoute(child_id, route_id);
}
void ResourceDispatcherHostImpl::OnRenderViewHostSetIsLoading(int child_id,
@@ -1768,29 +1898,6 @@ void ResourceDispatcherHostImpl::OnRenderViewHostSetIsLoading(int child_id,
scheduler_->OnLoadingStateChanged(child_id, route_id, !is_loading);
}
-void ResourceDispatcherHostImpl::OnRenderViewHostWasHidden(
- int child_id,
- int route_id) {
- scheduler_->OnVisibilityChanged(child_id, route_id, false);
-}
-
-void ResourceDispatcherHostImpl::OnRenderViewHostWasShown(
- int child_id,
- int route_id) {
- scheduler_->OnVisibilityChanged(child_id, route_id, true);
-}
-
-void ResourceDispatcherHostImpl::OnAudioRenderHostStreamStateChanged(
- int child_id,
- int route_id,
- bool is_playing) {
- // The ResourceDispatcherHost may have already been shut down.
- // See http://crbug.com/455098
- if (!scheduler_)
- return;
- scheduler_->OnAudibilityChanged(child_id, route_id, is_playing);
-}
-
// This function is only used for saving feature.
void ResourceDispatcherHostImpl::BeginSaveFile(const GURL& url,
const Referrer& referrer,
@@ -1822,7 +1929,7 @@ void ResourceDispatcherHostImpl::BeginSaveFile(const GURL& url,
return;
}
- scoped_ptr<net::URLRequest> request(
+ std::unique_ptr<net::URLRequest> request(
request_context->CreateRequest(url, net::DEFAULT_PRIORITY, NULL));
request->set_method("GET");
SetReferrerForRequest(request.get(), referrer);
@@ -1837,7 +1944,7 @@ void ResourceDispatcherHostImpl::BeginSaveFile(const GURL& url,
render_frame_route_id, false, context);
extra_info->AssociateWithRequest(request.get()); // Request takes ownership.
- scoped_ptr<ResourceHandler> handler(new SaveFileResourceHandler(
+ std::unique_ptr<ResourceHandler> handler(new SaveFileResourceHandler(
request.get(), save_item_id, save_package_id, child_id,
render_frame_route_id, url, save_file_manager_.get()));
@@ -1845,8 +1952,9 @@ void ResourceDispatcherHostImpl::BeginSaveFile(const GURL& url,
}
void ResourceDispatcherHostImpl::MarkAsTransferredNavigation(
- const GlobalRequestID& id) {
- GetLoader(id)->MarkAsTransferring();
+ const GlobalRequestID& id,
+ const scoped_refptr<ResourceResponse>& response) {
+ GetLoader(id)->MarkAsTransferring(response);
}
void ResourceDispatcherHostImpl::CancelTransferringNavigation(
@@ -1868,29 +1976,33 @@ void ResourceDispatcherHostImpl::ResumeDeferredNavigation(
// for downloads and detachable resources, which belong to the browser process
// even if initiated via a renderer.
void ResourceDispatcherHostImpl::CancelRequestsForProcess(int child_id) {
- CancelRequestsForRoute(child_id, -1 /* cancel all */);
+ CancelRequestsForRoute(
+ GlobalFrameRoutingId(child_id, MSG_ROUTING_NONE /* cancel all */));
registered_temp_files_.erase(child_id);
}
-void ResourceDispatcherHostImpl::CancelRequestsForRoute(int child_id,
- int route_id) {
+void ResourceDispatcherHostImpl::CancelRequestsForRoute(
+ const GlobalFrameRoutingId& global_routing_id) {
// Since pending_requests_ is a map, we first build up a list of all of the
// matching requests to be cancelled, and then we cancel them. Since there
// may be more than one request to cancel, we cannot simply hold onto the map
// iterators found in the first loop.
// Find the global ID of all matching elements.
+ int child_id = global_routing_id.child_id;
+ int route_id = global_routing_id.frame_routing_id;
+ bool cancel_all_routes = (route_id == MSG_ROUTING_NONE);
+
bool any_requests_transferring = false;
std::vector<GlobalRequestID> matching_requests;
- for (LoaderMap::const_iterator i = pending_loaders_.begin();
- i != pending_loaders_.end(); ++i) {
- if (i->first.child_id != child_id)
+ for (const auto& loader : pending_loaders_) {
+ if (loader.first.child_id != child_id)
continue;
- ResourceRequestInfoImpl* info = i->second->GetRequestInfo();
+ ResourceRequestInfoImpl* info = loader.second->GetRequestInfo();
- GlobalRequestID id(child_id, i->first.request_id);
- DCHECK(id == i->first);
+ GlobalRequestID id(child_id, loader.first.request_id);
+ DCHECK(id == loader.first);
// Don't cancel navigations that are expected to live beyond this process.
if (IsTransferredNavigation(id))
any_requests_transferring = true;
@@ -1898,7 +2010,7 @@ void ResourceDispatcherHostImpl::CancelRequestsForRoute(int child_id,
info->detachable_handler()->Detach();
} else if (!info->IsDownload() && !info->is_stream() &&
!IsTransferredNavigation(id) &&
- (route_id == -1 || route_id == info->GetRouteID())) {
+ (cancel_all_routes || route_id == info->GetRenderFrameID())) {
matching_requests.push_back(id);
}
}
@@ -1928,25 +2040,23 @@ void ResourceDispatcherHostImpl::CancelRequestsForRoute(int child_id,
return;
// Now deal with blocked requests if any.
- if (route_id != -1) {
- if (blocked_loaders_map_.find(GlobalRoutingID(child_id, route_id)) !=
+ if (!cancel_all_routes) {
+ if (blocked_loaders_map_.find(global_routing_id) !=
blocked_loaders_map_.end()) {
- CancelBlockedRequestsForRoute(child_id, route_id);
+ CancelBlockedRequestsForRoute(global_routing_id);
}
} else {
- // We have to do all render views for the process |child_id|.
+ // We have to do all render frames for the process |child_id|.
// Note that we have to do this in 2 passes as we cannot call
// CancelBlockedRequestsForRoute while iterating over
- // blocked_loaders_map_, as it modifies it.
- std::set<int> route_ids;
- for (BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.begin();
- iter != blocked_loaders_map_.end(); ++iter) {
- if (iter->first.child_id == child_id)
- route_ids.insert(iter->first.route_id);
+ // blocked_loaders_map_, as blocking requests modifies the map.
+ std::set<GlobalFrameRoutingId> routing_ids;
+ for (const auto& blocked_loaders : blocked_loaders_map_) {
+ if (blocked_loaders.first.child_id == child_id)
+ routing_ids.insert(blocked_loaders.first);
}
- for (std::set<int>::const_iterator iter = route_ids.begin();
- iter != route_ids.end(); ++iter) {
- CancelBlockedRequestsForRoute(child_id, *iter);
+ for (const GlobalFrameRoutingId& route_id : routing_ids) {
+ CancelBlockedRequestsForRoute(route_id);
}
}
}
@@ -2082,7 +2192,7 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
// needs to be checked relative to the child that /requested/ the
// navigation. It's where file upload checks, etc., come in.
(delegate_ && !delegate_->ShouldBeginRequest(
- info.begin_params.method,
+ info.common_params.method,
info.common_params.url,
resource_type,
resource_context))) {
@@ -2113,11 +2223,11 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
// requests that have the ignore limits flag set.
DCHECK(!(load_flags & net::LOAD_IGNORE_LIMITS));
- scoped_ptr<net::URLRequest> new_request;
+ std::unique_ptr<net::URLRequest> new_request;
new_request = request_context->CreateRequest(
info.common_params.url, net::HIGHEST, nullptr);
- new_request->set_method(info.begin_params.method);
+ new_request->set_method(info.common_params.method);
new_request->set_first_party_for_cookies(
info.first_party_for_cookies);
new_request->set_initiator(info.request_initiator);
@@ -2167,8 +2277,8 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
-1, // request_data.origin_pid,
request_id_,
-1, // request_data.render_frame_id,
- info.is_main_frame, info.parent_is_main_frame,
- resource_type, info.common_params.transition,
+ info.is_main_frame, info.parent_is_main_frame, resource_type,
+ info.common_params.transition,
// should_replace_current_entry. This was only maintained at layer for
// request transfers and isn't needed for browser-side navigations.
false,
@@ -2186,8 +2296,8 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
base::WeakPtr<ResourceMessageFilter>(), // filter
false, // request_data.report_raw_headers
true, // is_async
- IsUsingLoFi(info.common_params.lofi_state, delegate_,
- *new_request, resource_context),
+ IsUsingLoFi(info.common_params.lofi_state, delegate_, *new_request,
+ resource_context, info.is_main_frame),
// The original_headers field is for stale-while-revalidate but the
// feature doesn't work with PlzNavigate, so it's just a placeholder
// here.
@@ -2215,8 +2325,8 @@ void ResourceDispatcherHostImpl::BeginNavigationRequest(
// TODO(davidben): Attach AppCacheInterceptor.
- scoped_ptr<ResourceHandler> handler(new NavigationResourceHandler(
- new_request.get(), loader));
+ std::unique_ptr<ResourceHandler> handler(
+ new NavigationResourceHandler(new_request.get(), loader));
// TODO(davidben): Pass in the appropriate appcache_service. Also fix the
// dependency on child_id/route_id. Those are used by the ResourceScheduler;
@@ -2253,8 +2363,8 @@ int ResourceDispatcherHostImpl::CalculateApproximateMemoryCost(
}
void ResourceDispatcherHostImpl::BeginRequestInternal(
- scoped_ptr<net::URLRequest> request,
- scoped_ptr<ResourceHandler> handler) {
+ std::unique_ptr<net::URLRequest> request,
+ std::unique_ptr<ResourceHandler> handler) {
DCHECK(!request->is_pending());
ResourceRequestInfoImpl* info =
ResourceRequestInfoImpl::ForRequest(request.get());
@@ -2290,30 +2400,32 @@ void ResourceDispatcherHostImpl::BeginRequestInternal(
return;
}
- linked_ptr<ResourceLoader> loader(
- new ResourceLoader(std::move(request), std::move(handler), this));
+ std::unique_ptr<ResourceLoader> loader(new ResourceLoader(
+ std::move(request), std::move(handler), GetCertStore(), this));
- GlobalRoutingID id(info->GetGlobalRoutingID());
+ GlobalFrameRoutingId id(info->GetChildID(), info->GetRenderFrameID());
BlockedLoadersMap::const_iterator iter = blocked_loaders_map_.find(id);
if (iter != blocked_loaders_map_.end()) {
// The request should be blocked.
- iter->second->push_back(loader);
+ iter->second->push_back(std::move(loader));
return;
}
- StartLoading(info, loader);
+ StartLoading(info, std::move(loader));
}
void ResourceDispatcherHostImpl::StartLoading(
ResourceRequestInfoImpl* info,
- const linked_ptr<ResourceLoader>& loader) {
+ std::unique_ptr<ResourceLoader> loader) {
// TODO(pkasting): Remove ScopedTracker below once crbug.com/456331 is fixed.
tracked_objects::ScopedTracker tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"456331 ResourceDispatcherHostImpl::StartLoading"));
- pending_loaders_[info->GetGlobalRequestID()] = loader;
- loader->StartRequest();
+ ResourceLoader* loader_ptr = loader.get();
+ pending_loaders_[info->GetGlobalRequestID()] = std::move(loader);
+
+ loader_ptr->StartRequest();
}
void ResourceDispatcherHostImpl::OnUserGesture(WebContentsImpl* contents) {
@@ -2351,7 +2463,7 @@ bool ResourceDispatcherHostImpl::LoadInfoIsMoreInteresting(const LoadInfo& a,
// static
void ResourceDispatcherHostImpl::UpdateLoadInfoOnUIThread(
- scoped_ptr<LoadInfoMap> info_map) {
+ std::unique_ptr<LoadInfoMap> info_map) {
// TODO(erikchen): Remove ScopedTracker below once http://crbug.com/466285
// is fixed.
tracked_objects::ScopedTracker tracking_profile(
@@ -2370,11 +2482,11 @@ void ResourceDispatcherHostImpl::UpdateLoadInfoOnUIThread(
}
}
-scoped_ptr<ResourceDispatcherHostImpl::LoadInfoMap>
+std::unique_ptr<ResourceDispatcherHostImpl::LoadInfoMap>
ResourceDispatcherHostImpl::GetLoadInfoForAllRoutes() {
// Populate this map with load state changes, and then send them on to the UI
// thread where they can be passed along to the respective RVHs.
- scoped_ptr<LoadInfoMap> info_map(new LoadInfoMap());
+ std::unique_ptr<LoadInfoMap> info_map(new LoadInfoMap());
for (const auto& loader : pending_loaders_) {
net::URLRequest* request = loader.second->request();
@@ -2398,7 +2510,7 @@ ResourceDispatcherHostImpl::GetLoadInfoForAllRoutes() {
}
void ResourceDispatcherHostImpl::UpdateLoadInfo() {
- scoped_ptr<LoadInfoMap> info_map(GetLoadInfoForAllRoutes());
+ std::unique_ptr<LoadInfoMap> info_map(GetLoadInfoForAllRoutes());
// Stop the timer if there are no more pending requests. Future new requests
// will restart it as necessary.
@@ -2415,54 +2527,51 @@ void ResourceDispatcherHostImpl::UpdateLoadInfo() {
base::Passed(&info_map)));
}
-void ResourceDispatcherHostImpl::BlockRequestsForRoute(int child_id,
- int route_id) {
+void ResourceDispatcherHostImpl::BlockRequestsForRoute(
+ const GlobalFrameRoutingId& global_routing_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- GlobalRoutingID key(child_id, route_id);
- DCHECK(blocked_loaders_map_.find(key) == blocked_loaders_map_.end()) <<
- "BlockRequestsForRoute called multiple time for the same RVH";
- blocked_loaders_map_[key] = new BlockedLoadersList();
+ DCHECK(blocked_loaders_map_.find(global_routing_id) ==
+ blocked_loaders_map_.end())
+ << "BlockRequestsForRoute called multiple time for the same RFH";
+ blocked_loaders_map_[global_routing_id] =
+ base::WrapUnique(new BlockedLoadersList());
}
-void ResourceDispatcherHostImpl::ResumeBlockedRequestsForRoute(int child_id,
- int route_id) {
- ProcessBlockedRequestsForRoute(child_id, route_id, false);
+void ResourceDispatcherHostImpl::ResumeBlockedRequestsForRoute(
+ const GlobalFrameRoutingId& global_routing_id) {
+ ProcessBlockedRequestsForRoute(global_routing_id, false);
}
-void ResourceDispatcherHostImpl::CancelBlockedRequestsForRoute(int child_id,
- int route_id) {
- ProcessBlockedRequestsForRoute(child_id, route_id, true);
+void ResourceDispatcherHostImpl::CancelBlockedRequestsForRoute(
+ const GlobalFrameRoutingId& global_routing_id) {
+ ProcessBlockedRequestsForRoute(global_routing_id, true);
}
void ResourceDispatcherHostImpl::ProcessBlockedRequestsForRoute(
- int child_id,
- int route_id,
+ const GlobalFrameRoutingId& global_routing_id,
bool cancel_requests) {
- BlockedLoadersMap::iterator iter = blocked_loaders_map_.find(
- GlobalRoutingID(child_id, route_id));
+ BlockedLoadersMap::iterator iter =
+ blocked_loaders_map_.find(global_routing_id);
if (iter == blocked_loaders_map_.end()) {
// It's possible to reach here if the renderer crashed while an interstitial
// page was showing.
return;
}
- BlockedLoadersList* loaders = iter->second;
+ BlockedLoadersList* loaders = iter->second.get();
+ std::unique_ptr<BlockedLoadersList> deleter(std::move(iter->second));
// Removing the vector from the map unblocks any subsequent requests.
blocked_loaders_map_.erase(iter);
- for (BlockedLoadersList::iterator loaders_iter = loaders->begin();
- loaders_iter != loaders->end(); ++loaders_iter) {
- linked_ptr<ResourceLoader> loader = *loaders_iter;
+ for (std::unique_ptr<ResourceLoader>& loader : *loaders) {
ResourceRequestInfoImpl* info = loader->GetRequestInfo();
if (cancel_requests) {
IncrementOutstandingRequestsMemory(-1, *info);
} else {
- StartLoading(info, loader);
+ StartLoading(info, std::move(loader));
}
}
-
- delete loaders;
}
ResourceDispatcherHostImpl::HttpAuthRelationType
@@ -2557,4 +2666,29 @@ int ResourceDispatcherHostImpl::BuildLoadFlagsForRequest(
return load_flags;
}
+void ResourceDispatcherHostImpl::UpdateResponseCertificateForTransfer(
+ ResourceResponse* response,
+ const net::SSLInfo& ssl_info,
+ int child_id) {
+ if (!ssl_info.cert)
+ return;
+ SSLStatus ssl;
+ // DeserializeSecurityInfo() often takes security info sent by a
+ // renderer as input, in which case it's important to check that the
+ // security info deserializes properly and kill the renderer if
+ // not. In this case, however, the security info has been provided by
+ // the ResourceLoader, so it does not need to be treated as untrusted
+ // data.
+ bool deserialized =
+ DeserializeSecurityInfo(response->head.security_info, &ssl);
+ DCHECK(deserialized);
+ ssl.cert_id = GetCertStore()->StoreCert(ssl_info.cert.get(), child_id);
+ response->head.security_info = SerializeSecurityInfo(ssl);
+}
+
+CertStore* ResourceDispatcherHostImpl::GetCertStore() {
+ return cert_store_for_testing_ ? cert_store_for_testing_
+ : CertStore::GetInstance();
+}
+
} // namespace content
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_impl.h b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
index 74922647f29..086f39bea06 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_impl.h
+++ b/chromium/content/browser/loader/resource_dispatcher_host_impl.h
@@ -15,14 +15,13 @@
#include <stdint.h>
#include <map>
+#include <memory>
#include <set>
#include <string>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/memory/linked_ptr.h"
-#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
@@ -40,6 +39,7 @@
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/resource_dispatcher_host.h"
+#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/resource_type.h"
#include "ipc/ipc_message.h"
#include "net/base/request_priority.h"
@@ -64,7 +64,10 @@ class ShareableFileReference;
namespace content {
class AppCacheService;
class AsyncRevalidationManager;
+class CertStore;
+class FrameTree;
class NavigationURLLoaderImplCore;
+class RenderFrameHostImpl;
class ResourceContext;
class ResourceDispatcherHostDelegate;
class ResourceMessageDelegate;
@@ -78,6 +81,22 @@ struct DownloadSaveInfo;
struct NavigationRequestInfo;
struct Referrer;
+// This class is responsible for notifying the IO thread (specifically, the
+// ResourceDispatcherHostImpl) of frame events. It has an interace for callers
+// to use and also sends notifications on WebContentsObserver events. All
+// methods (static or class) will be called from the UI thread and post to the
+// IO thread.
+// TODO(csharrison): Add methods tracking visibility and audio changes, to
+// propogate to the ResourceScheduler.
+class LoaderIOThreadNotifier : public WebContentsObserver {
+ public:
+ explicit LoaderIOThreadNotifier(WebContents* web_contents);
+ ~LoaderIOThreadNotifier() override;
+
+ // content::WebContentsObserver:
+ void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
+};
+
class CONTENT_EXPORT ResourceDispatcherHostImpl
: public ResourceDispatcherHost,
public ResourceLoaderDelegate {
@@ -89,25 +108,28 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// hasn't been created yet.
static ResourceDispatcherHostImpl* Get();
+ // The following static methods should all be called from the UI thread.
+
+ // Resumes requests for a given render frame routing id. This will only resume
+ // requests for a single frame.
+ static void ResumeBlockedRequestsForRouteFromUI(
+ const GlobalFrameRoutingId& global_routing_id);
+
+ // Blocks (and does not start) all requests for the frame and its subframes.
+ static void BlockRequestsForFrameFromUI(RenderFrameHost* root_frame_host);
+
+ // Resumes any blocked requests for the specified frame and its subframes.
+ static void ResumeBlockedRequestsForFrameFromUI(
+ RenderFrameHost* root_frame_host);
+
+ // Cancels any blocked request for the frame and its subframes.
+ static void CancelBlockedRequestsForFrameFromUI(
+ RenderFrameHostImpl* root_frame_host);
+
// ResourceDispatcherHost implementation:
void SetDelegate(ResourceDispatcherHostDelegate* delegate) override;
void SetAllowCrossOriginAuthPrompt(bool value) override;
- DownloadInterruptReason BeginDownload(
- scoped_ptr<net::URLRequest> request,
- const Referrer& referrer,
- bool is_content_initiated,
- ResourceContext* context,
- int child_id,
- int render_view_route_id,
- int render_frame_route_id,
- bool prefer_cache,
- bool do_not_prompt_for_login,
- scoped_ptr<DownloadSaveInfo> save_info,
- uint32_t download_id,
- const DownloadStartedCallback& started_callback) override;
void ClearLoginDelegateForRequest(net::URLRequest* request) override;
- void BlockRequestsForRoute(int child_id, int route_id) override;
- void ResumeBlockedRequestsForRoute(int child_id, int route_id) override;
// Puts the resource dispatcher host in an inactive state (unable to begin
// new requests). Cancels all pending requests.
@@ -128,6 +150,16 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
bool OnMessageReceived(const IPC::Message& message,
ResourceMessageFilter* filter);
+ DownloadInterruptReason BeginDownload(
+ std::unique_ptr<net::URLRequest> request,
+ const Referrer& referrer,
+ bool is_content_initiated,
+ ResourceContext* context,
+ int child_id,
+ int render_view_route_id,
+ int render_frame_route_id,
+ bool do_not_prompt_for_login);
+
// Initiates a save file from the browser process (as opposed to a resource
// request from the renderer or another child process).
void BeginSaveFile(const GURL& url,
@@ -142,9 +174,12 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// Cancels the given request if it still exists.
void CancelRequest(int child_id, int request_id);
- // Marks the request as "parked". This happens if a request is
- // redirected cross-site and needs to be resumed by a new render view.
- void MarkAsTransferredNavigation(const GlobalRequestID& id);
+ // Marks the request, with its current |response|, as "parked". This
+ // happens if a request is redirected cross-site and needs to be
+ // resumed by a new render view.
+ void MarkAsTransferredNavigation(
+ const GlobalRequestID& id,
+ const scoped_refptr<ResourceResponse>& response);
// Cancels a request previously marked as being transferred, for use when a
// navigation was cancelled.
@@ -179,9 +214,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// Called when a RenderViewHost is created.
void OnRenderViewHostCreated(int child_id,
- int route_id,
- bool is_visible,
- bool is_audible);
+ int route_id);
// Called when a RenderViewHost is deleted.
void OnRenderViewHostDeleted(int child_id, int route_id);
@@ -191,17 +224,6 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
int route_id,
bool is_loading);
- // Called when a RenderViewHost is hidden.
- void OnRenderViewHostWasHidden(int child_id, int route_id);
-
- // Called when a RenderViewHost is shown.
- void OnRenderViewHostWasShown(int child_id, int route_id);
-
- // Called when an AudioRenderHost starts or stops playing.
- void OnAudioRenderHostStreamStateChanged(int child_id,
- int route_id,
- bool is_playing);
-
// Force cancels any pending requests for the given process.
void CancelRequestsForProcess(int child_id);
@@ -212,8 +234,17 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
void RemovePendingRequest(int child_id, int request_id);
+ // Causes all new requests for the route identified by |routing_id| to be
+ // blocked (not being started) until ResumeBlockedRequestsForRoute is called.
+ void BlockRequestsForRoute(const GlobalFrameRoutingId& global_routing_id);
+
+ // Resumes any blocked request for the specified route id.
+ void ResumeBlockedRequestsForRoute(
+ const GlobalFrameRoutingId& global_routing_id);
+
// Cancels any blocked request for the specified route id.
- void CancelBlockedRequestsForRoute(int child_id, int route_id);
+ void CancelBlockedRequestsForRoute(
+ const GlobalFrameRoutingId& global_routing_id);
// Maintains a collection of temp files created in support of
// the download_to_file capability. Used to grant access to the
@@ -239,13 +270,10 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// and associated with the request.
// |id| should be |content::DownloadItem::kInvalidId| to request automatic
// assignment. This is marked virtual so it can be overriden in testing.
- virtual scoped_ptr<ResourceHandler> CreateResourceHandlerForDownload(
+ virtual std::unique_ptr<ResourceHandler> CreateResourceHandlerForDownload(
net::URLRequest* request,
bool is_content_initiated,
- bool must_download,
- uint32_t id,
- scoped_ptr<DownloadSaveInfo> save_info,
- const DownloadUrlParameters::OnStartedCallback& started_cb);
+ bool must_download);
// Called to determine whether the response to |request| should be intercepted
// and handled as a stream. Streams are used to pass direct access to a
@@ -259,7 +287,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// and associated with the request. If |payload| is set to a non-empty value,
// the caller must send it to the old resource handler instead of cancelling
// it.
- virtual scoped_ptr<ResourceHandler> MaybeInterceptAsStream(
+ virtual std::unique_ptr<ResourceHandler> MaybeInterceptAsStream(
const base::FilePath& plugin_path,
net::URLRequest* request,
ResourceResponse* response,
@@ -291,6 +319,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
void EnableStaleWhileRevalidateForTesting();
private:
+ friend class LoaderIOThreadNotifier;
friend class ResourceDispatcherHostTest;
FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest,
@@ -301,6 +330,8 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
DetachableResourceTimesOut);
FRIEND_TEST_ALL_PREFIXES(ResourceDispatcherHostTest,
TestProcessCancelDetachableTimesOut);
+ FRIEND_TEST_ALL_PREFIXES(SitePerProcessIgnoreCertErrorsBrowserTest,
+ CrossSiteRedirectCertificateStore);
struct OustandingRequestsStats {
int memory_cost;
@@ -337,12 +368,14 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// A shutdown helper that runs on the IO thread.
void OnShutdown();
+ void OnRenderFrameDeleted(const GlobalFrameRoutingId& global_routing_id);
+
// Helper function for regular and download requests.
- void BeginRequestInternal(scoped_ptr<net::URLRequest> request,
- scoped_ptr<ResourceHandler> handler);
+ void BeginRequestInternal(std::unique_ptr<net::URLRequest> request,
+ std::unique_ptr<ResourceHandler> handler);
void StartLoading(ResourceRequestInfoImpl* info,
- const linked_ptr<ResourceLoader>& loader);
+ std::unique_ptr<ResourceLoader> loader);
// We keep track of how much memory each request needs and how many requests
// are issued by each renderer. These are known as OustandingRequestStats.
@@ -379,8 +412,9 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
static int CalculateApproximateMemoryCost(net::URLRequest* request);
// Force cancels any pending requests for the given route id. This method
- // acts like CancelRequestsForProcess when route_id is -1.
- void CancelRequestsForRoute(int child_id, int route_id);
+ // acts like CancelRequestsForProcess when the |route_id| member of
+ // |routing_id| is MSG_ROUTING_NONE.
+ void CancelRequestsForRoute(const GlobalFrameRoutingId& global_routing_id);
// The list of all requests that we have pending. This list is not really
// optimized, and assumes that we have relatively few requests pending at once
@@ -389,7 +423,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// It may be enhanced in the future to provide some kind of prioritization
// mechanism. We should also consider a hashtable or binary tree if it turns
// out we have a lot of things here.
- typedef std::map<GlobalRequestID, linked_ptr<ResourceLoader> > LoaderMap;
+ using LoaderMap = std::map<GlobalRequestID, std::unique_ptr<ResourceLoader>>;
// Deletes the pending request identified by the iterator passed in.
// This function will invalidate the iterator passed in. Callers should
@@ -416,18 +450,18 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// Used to marshal calls to LoadStateChanged from the IO to UI threads. All
// are done as a single callback to avoid spamming the UI thread.
- static void UpdateLoadInfoOnUIThread(scoped_ptr<LoadInfoMap> info_map);
+ static void UpdateLoadInfoOnUIThread(std::unique_ptr<LoadInfoMap> info_map);
// Gets the most interesting LoadInfo for each GlobalRoutingID.
- scoped_ptr<LoadInfoMap> GetLoadInfoForAllRoutes();
+ std::unique_ptr<LoadInfoMap> GetLoadInfoForAllRoutes();
// Checks all pending requests and updates the load info if necessary.
void UpdateLoadInfo();
// Resumes or cancels (if |cancel_requests| is true) any blocked requests.
- void ProcessBlockedRequestsForRoute(int child_id,
- int route_id,
- bool cancel_requests);
+ void ProcessBlockedRequestsForRoute(
+ const GlobalFrameRoutingId& global_routing_id,
+ bool cancel_requests);
void OnRequestResource(int routing_id,
int request_id,
@@ -436,13 +470,15 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
const ResourceHostMsg_Request& request_data,
IPC::Message* sync_result);
+ bool IsRequestIDInUse(const GlobalRequestID& id) const;
+
// Update the ResourceRequestInfo and internal maps when a request is
// transferred from one process to another.
void UpdateRequestForTransfer(int child_id,
int route_id,
int request_id,
const ResourceHostMsg_Request& request_data,
- const linked_ptr<ResourceLoader>& loader);
+ LoaderMap::iterator iter);
void BeginRequest(int request_id,
const ResourceHostMsg_Request& request_data,
@@ -451,7 +487,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// Creates a ResourceHandler to be used by BeginRequest() for normal resource
// loading.
- scoped_ptr<ResourceHandler> CreateResourceHandler(
+ std::unique_ptr<ResourceHandler> CreateResourceHandler(
net::URLRequest* request,
const ResourceHostMsg_Request& request_data,
IPC::Message* sync_result,
@@ -463,14 +499,14 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// Wraps |handler| in the standard resource handlers for normal resource
// loading and navigation requests. This adds MimeTypeResourceHandler and
// ResourceThrottles.
- scoped_ptr<ResourceHandler> AddStandardHandlers(
+ std::unique_ptr<ResourceHandler> AddStandardHandlers(
net::URLRequest* request,
ResourceType resource_type,
ResourceContext* resource_context,
AppCacheService* appcache_service,
int child_id,
int route_id,
- scoped_ptr<ResourceHandler> handler);
+ std::unique_ptr<ResourceHandler> handler);
void OnDataDownloadedACK(int request_id);
void OnCancelRequest(int request_id);
@@ -521,6 +557,16 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
int child_id,
bool is_sync_load);
+ // The certificate on a ResourceResponse is associated with a
+ // particular renderer process. As a transfer to a new process
+ // completes, the stored certificate has to be updated to reflect the
+ // new renderer process.
+ void UpdateResponseCertificateForTransfer(ResourceResponse* response,
+ const net::SSLInfo& ssl_info,
+ int child_id);
+
+ CertStore* GetCertStore();
+
LoaderMap pending_loaders_;
// Collection of temp files downloaded for child processes via
@@ -534,7 +580,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// A timer that periodically calls UpdateLoadInfo while pending_loaders_ is
// not empty and at least one RenderViewHost is loading.
- scoped_ptr<base::RepeatingTimer> update_load_states_timer_;
+ std::unique_ptr<base::RepeatingTimer> update_load_states_timer_;
// We own the save file manager.
scoped_refptr<SaveFileManager> save_file_manager_;
@@ -551,8 +597,9 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// True if the resource dispatcher host has been shut down.
bool is_shutdown_;
- typedef std::vector<linked_ptr<ResourceLoader> > BlockedLoadersList;
- typedef std::map<GlobalRoutingID, BlockedLoadersList*> BlockedLoadersMap;
+ using BlockedLoadersList = std::vector<std::unique_ptr<ResourceLoader>>;
+ using BlockedLoadersMap =
+ std::map<GlobalFrameRoutingId, std::unique_ptr<BlockedLoadersList>>;
BlockedLoadersMap blocked_loaders_map_;
// Maps the child_ids to the approximate number of bytes
@@ -600,7 +647,7 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
// AsyncRevalidationManager is non-NULL if and only if
// stale-while-revalidate is enabled.
- scoped_ptr<AsyncRevalidationManager> async_revalidation_manager_;
+ std::unique_ptr<AsyncRevalidationManager> async_revalidation_manager_;
// http://crbug.com/90971 - Assists in tracking down use-after-frees on
// shutdown.
@@ -610,7 +657,11 @@ class CONTENT_EXPORT ResourceDispatcherHostImpl
base::ObserverList<ResourceMessageDelegate>*> DelegateMap;
DelegateMap delegate_map_;
- scoped_ptr<ResourceScheduler> scheduler_;
+ std::unique_ptr<ResourceScheduler> scheduler_;
+
+ // Allows tests to use a mock CertStore. If set, the CertStore must
+ // outlive this ResourceDispatcherHostImpl.
+ CertStore* cert_store_for_testing_;
DISALLOW_COPY_AND_ASSIGN(ResourceDispatcherHostImpl);
};
diff --git a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
index 7fbe3995c21..606da908983 100644
--- a/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/loader/resource_dispatcher_host_unittest.cc
@@ -7,6 +7,7 @@
#include <vector>
#include "base/bind.h"
+#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/location.h"
@@ -20,6 +21,7 @@
#include "base/strings/string_split.h"
#include "base/thread_task_runner_handle.h"
#include "content/browser/browser_thread_impl.h"
+#include "content/browser/cert_store_impl.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/loader/cross_site_resource_handler.h"
#include "content/browser/loader/detachable_resource_handler.h"
@@ -30,6 +32,7 @@
#include "content/common/appcache_interfaces.h"
#include "content/common/child_process_host_impl.h"
#include "content/common/resource_messages.h"
+#include "content/common/ssl_status_serialization.h"
#include "content/common/view_messages.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/render_process_host.h"
@@ -41,6 +44,7 @@
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/child_process_host.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/process_type.h"
#include "content/public/common/resource_response.h"
#include "content/public/test/test_browser_context.h"
@@ -50,8 +54,10 @@
#include "net/base/elements_upload_data_stream.h"
#include "net/base/net_errors.h"
#include "net/base/request_priority.h"
+#include "net/base/test_data_directory.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/http/http_util.h"
+#include "net/test/cert_test_util.h"
#include "net/test/url_request/url_request_failed_job.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
@@ -86,9 +92,8 @@ void GetResponseHead(const std::vector<IPC::Message>& messages,
ASSERT_TRUE(IPC::ReadParam(&messages[0], &iter, response_head));
}
-void GenerateIPCMessage(
- scoped_refptr<ResourceMessageFilter> filter,
- scoped_ptr<IPC::Message> message) {
+void GenerateIPCMessage(scoped_refptr<ResourceMessageFilter> filter,
+ std::unique_ptr<IPC::Message> message) {
ResourceDispatcherHostImpl::Get()->OnMessageReceived(
*message, filter.get());
}
@@ -126,6 +131,7 @@ static int RequestIDForMessage(const IPC::Message& msg) {
case ResourceMsg_ReceivedRedirect::ID:
case ResourceMsg_SetDataBuffer::ID:
case ResourceMsg_DataReceived::ID:
+ case ResourceMsg_InlinedDataChunkReceived::ID:
case ResourceMsg_DataDownloaded::ID:
case ResourceMsg_RequestComplete::ID: {
bool result = base::PickleIterator(msg).ReadInt(&request_id);
@@ -760,7 +766,7 @@ class TestResourceDispatcherHostDelegate
bool create_two_throttles_;
int flags_;
int error_code_for_cancellation_;
- scoped_ptr<base::SupportsUserData::Data> user_data_;
+ std::unique_ptr<base::SupportsUserData::Data> user_data_;
};
// Waits for a ShareableFileReference to be released.
@@ -828,7 +834,38 @@ struct LoadInfoTestRequestInfo {
net::UploadProgress upload_progress;
};
-class ResourceDispatcherHostTest : public testing::Test,
+enum class TestConfig {
+ kDefault,
+ kOptimizeIPCForSmallResourceEnabled,
+};
+
+// A mock CertStore that doesn't do anything, unless a default cert id
+// is specified with set_default_cert_id(). If a default cert id is
+// provided, then StoreCert() always returns that cert id.
+class MockCertStore : public content::CertStore {
+ public:
+ MockCertStore() : default_cert_id_(0) {}
+
+ ~MockCertStore() override {}
+
+ int StoreCert(net::X509Certificate* cert, int process_id) override {
+ return default_cert_id_;
+ }
+
+ bool RetrieveCert(int process_id,
+ scoped_refptr<net::X509Certificate>* cert) override {
+ return false;
+ }
+
+ void set_default_cert_id(int default_cert_id) {
+ default_cert_id_ = default_cert_id;
+ }
+
+ private:
+ int default_cert_id_;
+};
+
+class ResourceDispatcherHostTest : public testing::TestWithParam<TestConfig>,
public IPC::Sender {
public:
typedef ResourceDispatcherHostImpl::LoadInfo LoadInfo;
@@ -836,6 +873,7 @@ class ResourceDispatcherHostTest : public testing::Test,
ResourceDispatcherHostTest()
: thread_bundle_(content::TestBrowserThreadBundle::IO_MAINLOOP),
+ use_test_ssl_certificate_(false),
old_factory_(NULL),
send_data_received_acks_(false) {
browser_context_.reset(new TestBrowserContext());
@@ -848,6 +886,7 @@ class ResourceDispatcherHostTest : public testing::Test,
job_factory_.reset(new TestURLRequestJobFactory(this));
request_context->set_job_factory(job_factory_.get());
request_context->set_network_delegate(&network_delegate_);
+ host_.cert_store_for_testing_ = &mock_cert_store_;
}
// IPC::Sender implementation
@@ -869,8 +908,9 @@ class ResourceDispatcherHostTest : public testing::Test,
return true;
}
- scoped_ptr<LoadInfoMap> RunLoadInfoTest(LoadInfoTestRequestInfo* request_info,
- size_t num_requests) {
+ std::unique_ptr<LoadInfoMap> RunLoadInfoTest(
+ LoadInfoTestRequestInfo* request_info,
+ size_t num_requests) {
for (size_t i = 0; i < num_requests; ++i) {
loader_test_request_info_.reset(
new LoadInfoTestRequestInfo(request_info[i]));
@@ -899,6 +939,22 @@ class ResourceDispatcherHostTest : public testing::Test,
browser_context_->GetResourceContext(),
web_contents_->GetRenderProcessHost()->GetID());
child_ids_.insert(web_contents_->GetRenderProcessHost()->GetID());
+
+ base::FeatureList::ClearInstanceForTesting();
+ switch (GetParam()) {
+ case TestConfig::kDefault:
+ base::FeatureList::InitializeInstance(std::string(), std::string());
+ break;
+ case TestConfig::kOptimizeIPCForSmallResourceEnabled: {
+ std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
+ feature_list->InitializeFromCommandLine(
+ features::kOptimizeIPCForSmallResource.name, std::string());
+ base::FeatureList::SetInstance(std::move(feature_list));
+ ASSERT_TRUE(base::FeatureList::IsEnabled(
+ features::kOptimizeIPCForSmallResource));
+ break;
+ }
+ }
}
void TearDown() override {
@@ -941,6 +997,12 @@ class ResourceDispatcherHostTest : public testing::Test,
int request_id,
const GURL& url);
+ void MakeTestRequestWithRenderFrame(int render_view_id,
+ int render_frame_id,
+ int request_id,
+ const GURL& url,
+ ResourceType type);
+
// Generates a request using the given filter and resource type.
void MakeTestRequestWithResourceType(ResourceMessageFilter* filter,
int render_view_id,
@@ -958,6 +1020,11 @@ class ResourceDispatcherHostTest : public testing::Test,
int request_id,
net::RequestPriority priority);
+ void MakeTestRequestWithPriorityAndRenderFrame(int render_view_id,
+ int render_frame_id,
+ int request_id,
+ net::RequestPriority priority);
+
void MakeWebContentsAssociatedDownloadRequest(int request_id,
const GURL& url);
@@ -991,6 +1058,11 @@ class ResourceDispatcherHostTest : public testing::Test,
SetResponse(headers, std::string());
}
+ // If called, requests called from now on will be created as
+ // TestHTTPSURLRequestJobs: that is, a test certificate will be set on
+ // the |ssl_info| field of the response.
+ void SetTestSSLCertificate() { use_test_ssl_certificate_ = true; }
+
void SendDataReceivedACKs(bool send_acks) {
send_data_received_acks_ = send_acks;
}
@@ -1007,7 +1079,7 @@ class ResourceDispatcherHostTest : public testing::Test,
int request_id = -1;
bool result = base::PickleIterator(msg).ReadInt(&request_id);
DCHECK(result);
- scoped_ptr<IPC::Message> ack(
+ std::unique_ptr<IPC::Message> ack(
new ResourceHostMsg_DataReceived_ACK(request_id));
base::ThreadTaskRunnerHandle::Get()->PostTask(
@@ -1030,14 +1102,18 @@ class ResourceDispatcherHostTest : public testing::Test,
wait_for_request_complete_loop_.reset();
}
- scoped_ptr<LoadInfoTestRequestInfo> loader_test_request_info_;
- scoped_ptr<base::RunLoop> wait_for_request_create_loop_;
+ void DeleteRenderFrame(const GlobalFrameRoutingId& global_routing_id) {
+ host_.OnRenderFrameDeleted(global_routing_id);
+ }
+
+ std::unique_ptr<LoadInfoTestRequestInfo> loader_test_request_info_;
+ std::unique_ptr<base::RunLoop> wait_for_request_create_loop_;
content::TestBrowserThreadBundle thread_bundle_;
- scoped_ptr<TestBrowserContext> browser_context_;
- scoped_ptr<TestURLRequestJobFactory> job_factory_;
- scoped_ptr<WebContents> web_contents_;
- scoped_ptr<TestWebContentsObserver> web_contents_observer_;
+ std::unique_ptr<TestBrowserContext> browser_context_;
+ std::unique_ptr<TestURLRequestJobFactory> job_factory_;
+ std::unique_ptr<WebContents> web_contents_;
+ std::unique_ptr<TestWebContentsObserver> web_contents_observer_;
scoped_refptr<ForwardingFilter> filter_;
scoped_refptr<TestFilterSpecifyingChild> web_contents_filter_;
net::TestNetworkDelegate network_delegate_;
@@ -1045,12 +1121,14 @@ class ResourceDispatcherHostTest : public testing::Test,
ResourceIPCAccumulator accum_;
std::string response_headers_;
std::string response_data_;
+ bool use_test_ssl_certificate_;
std::string scheme_;
net::URLRequest::ProtocolFactory* old_factory_;
bool send_data_received_acks_;
std::set<int> child_ids_;
- scoped_ptr<base::RunLoop> wait_for_request_complete_loop_;
+ std::unique_ptr<base::RunLoop> wait_for_request_complete_loop_;
RenderViewHostTestEnabler render_view_host_test_enabler_;
+ MockCertStore mock_cert_store_;
};
void ResourceDispatcherHostTest::MakeTestRequest(int render_view_id,
@@ -1060,6 +1138,19 @@ void ResourceDispatcherHostTest::MakeTestRequest(int render_view_id,
url, RESOURCE_TYPE_SUB_RESOURCE);
}
+void ResourceDispatcherHostTest::MakeTestRequestWithRenderFrame(
+ int render_view_id,
+ int render_frame_id,
+ int request_id,
+ const GURL& url,
+ ResourceType type) {
+ ResourceHostMsg_Request request = CreateResourceRequest("GET", type, url);
+ request.render_frame_id = render_frame_id;
+ ResourceHostMsg_RequestResource msg(render_view_id, request_id, request);
+ host_.OnMessageReceived(msg, filter_.get());
+ KickOffRequest();
+}
+
void ResourceDispatcherHostTest::MakeTestRequestWithResourceType(
ResourceMessageFilter* filter,
int render_view_id,
@@ -1097,8 +1188,18 @@ void ResourceDispatcherHostTest::MakeTestRequestWithPriority(
int render_view_id,
int request_id,
net::RequestPriority priority) {
+ MakeTestRequestWithPriorityAndRenderFrame(render_view_id, -1, request_id,
+ priority);
+}
+
+void ResourceDispatcherHostTest::MakeTestRequestWithPriorityAndRenderFrame(
+ int render_view_id,
+ int render_frame_id,
+ int request_id,
+ net::RequestPriority priority) {
ResourceHostMsg_Request request = CreateResourceRequest(
"GET", RESOURCE_TYPE_SUB_RESOURCE, GURL("http://example.com/priority"));
+ request.render_frame_id = render_frame_id;
request.priority = priority;
ResourceHostMsg_RequestResource msg(render_view_id, request_id, request);
host_.OnMessageReceived(msg, filter_.get());
@@ -1107,20 +1208,16 @@ void ResourceDispatcherHostTest::MakeTestRequestWithPriority(
void ResourceDispatcherHostTest::MakeWebContentsAssociatedDownloadRequest(
int request_id,
const GURL& url) {
- scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo());
- save_info->prompt_for_save_location = false;
net::URLRequestContext* request_context =
browser_context_->GetResourceContext()->GetRequestContext();
- scoped_ptr<net::URLRequest> request(
+ std::unique_ptr<net::URLRequest> request(
request_context->CreateRequest(url, net::DEFAULT_PRIORITY, NULL));
host_.BeginDownload(std::move(request), Referrer(),
false, // is_content_initiated
browser_context_->GetResourceContext(),
web_contents_->GetRenderProcessHost()->GetID(),
web_contents_->GetRoutingID(),
- web_contents_->GetMainFrame()->GetRoutingID(), false,
- false, std::move(save_info), DownloadItem::kInvalidId,
- ResourceDispatcherHostImpl::DownloadStartedCallback());
+ web_contents_->GetMainFrame()->GetRoutingID(), false);
}
void ResourceDispatcherHostTest::CancelRequest(int request_id) {
@@ -1155,6 +1252,22 @@ void CheckRequestCompleteErrorCode(const IPC::Message& message,
ASSERT_EQ(expected_error_code, error_code);
}
+testing::AssertionResult ExtractInlinedChunkData(
+ const IPC::Message& message,
+ std::string* leading_chunk_data) {
+ base::PickleIterator iter(message);
+ int request_id;
+ if (!IPC::ReadParam(&message, &iter, &request_id))
+ return testing::AssertionFailure() << "Could not read request_id";
+
+ std::vector<char> data;
+ if (!IPC::ReadParam(&message, &iter, &data))
+ return testing::AssertionFailure() << "Could not read data";
+ leading_chunk_data->assign(data.begin(), data.end());
+
+ return testing::AssertionSuccess();
+}
+
testing::AssertionResult ExtractDataOffsetAndLength(const IPC::Message& message,
int* data_offset,
int* data_length) {
@@ -1169,10 +1282,39 @@ testing::AssertionResult ExtractDataOffsetAndLength(const IPC::Message& message,
return testing::AssertionSuccess();
}
+void CheckSuccessfulRequestWithErrorCodeForInlinedCase(
+ const std::vector<IPC::Message>& messages,
+ const std::string& reference_data,
+ int expected_error) {
+ // A successful request on the inlined case will have received 3 messages:
+ // ReceivedResponse (indicates headers received)
+ // InlinedDataChunkReceived (contains the content)
+ // RequestComplete (request is done)
+
+ ASSERT_EQ(3U, messages.size());
+
+ // The first messages should be received response
+ ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, messages[0].type());
+ ASSERT_EQ(ResourceMsg_InlinedDataChunkReceived::ID, messages[1].type());
+
+ std::string leading_chunk_data;
+ ASSERT_TRUE(ExtractInlinedChunkData(messages[1], &leading_chunk_data));
+ ASSERT_EQ(reference_data, leading_chunk_data);
+ CheckRequestCompleteErrorCode(messages[2], expected_error);
+}
+
void CheckSuccessfulRequestWithErrorCode(
const std::vector<IPC::Message>& messages,
const std::string& reference_data,
int expected_error) {
+ ASSERT_LT(2U, messages.size());
+ if (base::FeatureList::IsEnabled(features::kOptimizeIPCForSmallResource) &&
+ messages[1].type() == ResourceMsg_InlinedDataChunkReceived::ID) {
+ CheckSuccessfulRequestWithErrorCodeForInlinedCase(
+ messages, reference_data, expected_error);
+ return;
+ }
+
// A successful request will have received 4 messages:
// ReceivedResponse (indicates headers received)
// SetDataBuffer (contains shared memory handle)
@@ -1248,7 +1390,7 @@ void CheckFailedRequest(const std::vector<IPC::Message>& messages,
}
// Tests whether many messages get dispatched properly.
-TEST_F(ResourceDispatcherHostTest, TestMany) {
+TEST_P(ResourceDispatcherHostTest, TestMany) {
MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2());
MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
@@ -1281,7 +1423,7 @@ TEST_F(ResourceDispatcherHostTest, TestMany) {
// Tests whether messages get canceled properly. We issue four requests,
// cancel two of them, and make sure that each sent the proper notifications.
-TEST_F(ResourceDispatcherHostTest, Cancel) {
+TEST_P(ResourceDispatcherHostTest, Cancel) {
MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
MakeTestRequest(0, 2, net::URLRequestTestJob::test_url_2());
MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
@@ -1336,7 +1478,7 @@ TEST_F(ResourceDispatcherHostTest, Cancel) {
// Shows that detachable requests will timeout if the request takes too long to
// complete.
-TEST_F(ResourceDispatcherHostTest, DetachedResourceTimesOut) {
+TEST_P(ResourceDispatcherHostTest, DetachedResourceTimesOut) {
MakeTestRequestWithResourceType(filter_.get(), 0, 1,
net::URLRequestTestJob::test_url_2(),
RESOURCE_TYPE_PREFETCH); // detachable type
@@ -1378,7 +1520,7 @@ TEST_F(ResourceDispatcherHostTest, DetachedResourceTimesOut) {
// If the filter has disappeared then detachable resources should continue to
// load.
-TEST_F(ResourceDispatcherHostTest, DeletedFilterDetached) {
+TEST_P(ResourceDispatcherHostTest, DeletedFilterDetached) {
// test_url_1's data is available synchronously, so use 2 and 3.
ResourceHostMsg_Request request_prefetch = CreateResourceRequest(
"GET", RESOURCE_TYPE_PREFETCH, net::URLRequestTestJob::test_url_2());
@@ -1430,7 +1572,7 @@ TEST_F(ResourceDispatcherHostTest, DeletedFilterDetached) {
// If the filter has disappeared (original process dies) then detachable
// resources should continue to load, even when redirected.
-TEST_F(ResourceDispatcherHostTest, DeletedFilterDetachedRedirect) {
+TEST_P(ResourceDispatcherHostTest, DeletedFilterDetachedRedirect) {
ResourceHostMsg_Request request = CreateResourceRequest(
"GET", RESOURCE_TYPE_PREFETCH,
net::URLRequestTestJob::test_url_redirect_to_url_2());
@@ -1477,7 +1619,7 @@ TEST_F(ResourceDispatcherHostTest, DeletedFilterDetachedRedirect) {
EXPECT_EQ(0, network_delegate()->error_count());
}
-TEST_F(ResourceDispatcherHostTest, CancelWhileStartIsDeferred) {
+TEST_P(ResourceDispatcherHostTest, CancelWhileStartIsDeferred) {
bool was_deleted = false;
// Arrange to have requests deferred before starting.
@@ -1501,7 +1643,7 @@ TEST_F(ResourceDispatcherHostTest, CancelWhileStartIsDeferred) {
EXPECT_TRUE(was_deleted);
}
-TEST_F(ResourceDispatcherHostTest, DetachWhileStartIsDeferred) {
+TEST_P(ResourceDispatcherHostTest, DetachWhileStartIsDeferred) {
bool was_deleted = false;
// Arrange to have requests deferred before starting.
@@ -1543,7 +1685,7 @@ TEST_F(ResourceDispatcherHostTest, DetachWhileStartIsDeferred) {
// Tests if cancel is called in ResourceThrottle::WillStartRequest, then the
// URLRequest will not be started.
-TEST_F(ResourceDispatcherHostTest, CancelInResourceThrottleWillStartRequest) {
+TEST_P(ResourceDispatcherHostTest, CancelInResourceThrottleWillStartRequest) {
TestResourceDispatcherHostDelegate delegate;
delegate.set_flags(CANCEL_BEFORE_START);
host_.SetDelegate(&delegate);
@@ -1565,7 +1707,7 @@ TEST_F(ResourceDispatcherHostTest, CancelInResourceThrottleWillStartRequest) {
EXPECT_EQ(0, job_factory_->url_request_jobs_created_count());
}
-TEST_F(ResourceDispatcherHostTest, PausedStartError) {
+TEST_P(ResourceDispatcherHostTest, PausedStartError) {
// Arrange to have requests deferred before processing response headers.
TestResourceDispatcherHostDelegate delegate;
delegate.set_flags(DEFER_PROCESSING_RESPONSE);
@@ -1583,7 +1725,7 @@ TEST_F(ResourceDispatcherHostTest, PausedStartError) {
}
// Test the WillStartUsingNetwork throttle.
-TEST_F(ResourceDispatcherHostTest, ThrottleNetworkStart) {
+TEST_P(ResourceDispatcherHostTest, ThrottleNetworkStart) {
// Arrange to have requests deferred before processing response headers.
TestResourceDispatcherHostDelegate delegate;
delegate.set_flags(DEFER_NETWORK_START);
@@ -1609,7 +1751,7 @@ TEST_F(ResourceDispatcherHostTest, ThrottleNetworkStart) {
EXPECT_EQ(0, host_.pending_requests());
}
-TEST_F(ResourceDispatcherHostTest, ThrottleAndResumeTwice) {
+TEST_P(ResourceDispatcherHostTest, ThrottleAndResumeTwice) {
// Arrange to have requests deferred before starting.
TestResourceDispatcherHostDelegate delegate;
delegate.set_flags(DEFER_STARTING_REQUEST);
@@ -1647,7 +1789,7 @@ TEST_F(ResourceDispatcherHostTest, ThrottleAndResumeTwice) {
// Tests that the delegate can cancel a request and provide a error code.
-TEST_F(ResourceDispatcherHostTest, CancelInDelegate) {
+TEST_P(ResourceDispatcherHostTest, CancelInDelegate) {
TestResourceDispatcherHostDelegate delegate;
delegate.set_flags(CANCEL_BEFORE_START);
delegate.set_error_code_for_cancellation(net::ERR_ACCESS_DENIED);
@@ -1671,7 +1813,7 @@ TEST_F(ResourceDispatcherHostTest, CancelInDelegate) {
}
// Tests CancelRequestsForProcess
-TEST_F(ResourceDispatcherHostTest, TestProcessCancel) {
+TEST_P(ResourceDispatcherHostTest, TestProcessCancel) {
scoped_refptr<TestFilter> test_filter = new TestFilter(
browser_context_->GetResourceContext());
child_ids_.insert(test_filter->child_id());
@@ -1748,7 +1890,7 @@ TEST_F(ResourceDispatcherHostTest, TestProcessCancel) {
// Tests whether the correct requests get canceled when a RenderViewHost is
// deleted.
-TEST_F(ResourceDispatcherHostTest, CancelRequestsOnRenderViewHostDeleted) {
+TEST_P(ResourceDispatcherHostTest, CancelRequestsOnRenderFrameDeleted) {
// Requests all hang once started. This prevents requests from being
// destroyed due to completion.
job_factory_->SetHangAfterStartJobGeneration(true);
@@ -1756,33 +1898,36 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsOnRenderViewHostDeleted) {
TestResourceDispatcherHostDelegate delegate;
host_.SetDelegate(&delegate);
- host_.OnRenderViewHostCreated(filter_->child_id(), 0, true, false);
+ host_.OnRenderViewHostCreated(filter_->child_id(), 0);
// One RenderView issues a high priority request and a low priority one. Both
// should be started.
- MakeTestRequestWithPriority(0, 1, net::HIGHEST);
- MakeTestRequestWithPriority(0, 2, net::LOWEST);
+ MakeTestRequestWithPriorityAndRenderFrame(0, 10, 1, net::HIGHEST);
+ MakeTestRequestWithPriorityAndRenderFrame(0, 11, 2, net::LOWEST);
KickOffRequest();
EXPECT_EQ(2, network_delegate_.created_requests());
EXPECT_EQ(0, network_delegate_.canceled_requests());
// The same RenderView issues two more low priority requests. The
// ResourceScheduler shouldn't let them start immediately.
- MakeTestRequestWithPriority(0, 3, net::LOWEST);
- MakeTestRequestWithPriority(0, 4, net::LOWEST);
+ MakeTestRequestWithPriorityAndRenderFrame(0, 10, 3, net::LOWEST);
+ MakeTestRequestWithPriorityAndRenderFrame(0, 11, 4, net::LOWEST);
KickOffRequest();
EXPECT_EQ(2, network_delegate_.created_requests());
EXPECT_EQ(0, network_delegate_.canceled_requests());
// Another RenderView in the same process as the old one issues a request,
// which is then started.
- MakeTestRequestWithPriority(1, 5, net::LOWEST);
+ MakeTestRequestWithPriorityAndRenderFrame(1, 12, 5, net::LOWEST);
KickOffRequest();
EXPECT_EQ(3, network_delegate_.created_requests());
EXPECT_EQ(0, network_delegate_.canceled_requests());
- // The first RenderView is destroyed. All 4 of its requests should be
- // cancelled, and none of the two deferred requests should be started.
+ // The first two RenderFrameHosts are destroyed. All 4 of their requests
+ // should be cancelled, and none of the two deferred requests should be
+ // started.
+ DeleteRenderFrame(GlobalFrameRoutingId(filter_->child_id(), 10));
+ DeleteRenderFrame(GlobalFrameRoutingId(filter_->child_id(), 11));
host_.OnRenderViewHostDeleted(filter_->child_id(), 0);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(3, network_delegate_.created_requests());
@@ -1795,7 +1940,7 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsOnRenderViewHostDeleted) {
EXPECT_EQ(0U, msgs.size());
}
-TEST_F(ResourceDispatcherHostTest, TestProcessCancelDetachedTimesOut) {
+TEST_P(ResourceDispatcherHostTest, TestProcessCancelDetachedTimesOut) {
MakeTestRequestWithResourceType(filter_.get(), 0, 1,
net::URLRequestTestJob::test_url_4(),
RESOURCE_TYPE_PREFETCH); // detachable type
@@ -1841,17 +1986,23 @@ TEST_F(ResourceDispatcherHostTest, TestProcessCancelDetachedTimesOut) {
}
// Tests blocking and resuming requests.
-TEST_F(ResourceDispatcherHostTest, TestBlockingResumingRequests) {
- host_.BlockRequestsForRoute(filter_->child_id(), 1);
- host_.BlockRequestsForRoute(filter_->child_id(), 2);
- host_.BlockRequestsForRoute(filter_->child_id(), 3);
-
- MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
- MakeTestRequest(1, 2, net::URLRequestTestJob::test_url_2());
- MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
- MakeTestRequest(1, 4, net::URLRequestTestJob::test_url_1());
- MakeTestRequest(2, 5, net::URLRequestTestJob::test_url_2());
- MakeTestRequest(3, 6, net::URLRequestTestJob::test_url_3());
+TEST_P(ResourceDispatcherHostTest, TestBlockingResumingRequests) {
+ host_.BlockRequestsForRoute(GlobalFrameRoutingId(filter_->child_id(), 11));
+ host_.BlockRequestsForRoute(GlobalFrameRoutingId(filter_->child_id(), 12));
+ host_.BlockRequestsForRoute(GlobalFrameRoutingId(filter_->child_id(), 13));
+
+ MakeTestRequestWithRenderFrame(0, 10, 1, net::URLRequestTestJob::test_url_1(),
+ RESOURCE_TYPE_SUB_RESOURCE);
+ MakeTestRequestWithRenderFrame(1, 11, 2, net::URLRequestTestJob::test_url_2(),
+ RESOURCE_TYPE_SUB_RESOURCE);
+ MakeTestRequestWithRenderFrame(0, 10, 3, net::URLRequestTestJob::test_url_3(),
+ RESOURCE_TYPE_SUB_RESOURCE);
+ MakeTestRequestWithRenderFrame(1, 11, 4, net::URLRequestTestJob::test_url_1(),
+ RESOURCE_TYPE_SUB_RESOURCE);
+ MakeTestRequestWithRenderFrame(2, 12, 5, net::URLRequestTestJob::test_url_2(),
+ RESOURCE_TYPE_SUB_RESOURCE);
+ MakeTestRequestWithRenderFrame(3, 13, 6, net::URLRequestTestJob::test_url_3(),
+ RESOURCE_TYPE_SUB_RESOURCE);
// Flush all the pending requests
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
@@ -1860,14 +2011,15 @@ TEST_F(ResourceDispatcherHostTest, TestBlockingResumingRequests) {
ResourceIPCAccumulator::ClassifiedMessages msgs;
accum_.GetClassifiedMessages(&msgs);
- // All requests but the 2 for the RVH 0 should have been blocked.
+ // All requests but the 2 for the RFH 0 should have been blocked.
ASSERT_EQ(2U, msgs.size());
CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_3());
- // Resume requests for RVH 1 and flush pending requests.
- host_.ResumeBlockedRequestsForRoute(filter_->child_id(), 1);
+ // Resume requests for RFH 11 and flush pending requests.
+ host_.ResumeBlockedRequestsForRoute(
+ GlobalFrameRoutingId(filter_->child_id(), 11));
KickOffRequest();
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
@@ -1877,17 +2029,20 @@ TEST_F(ResourceDispatcherHostTest, TestBlockingResumingRequests) {
CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_2());
CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_1());
- // Test that new requests are not blocked for RVH 1.
- MakeTestRequest(1, 7, net::URLRequestTestJob::test_url_1());
+ // Test that new requests are not blocked for RFH 11.
+ MakeTestRequestWithRenderFrame(1, 11, 7, net::URLRequestTestJob::test_url_1(),
+ RESOURCE_TYPE_SUB_RESOURCE);
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
msgs.clear();
accum_.GetClassifiedMessages(&msgs);
ASSERT_EQ(1U, msgs.size());
CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
- // Now resumes requests for all RVH (2 and 3).
- host_.ResumeBlockedRequestsForRoute(filter_->child_id(), 2);
- host_.ResumeBlockedRequestsForRoute(filter_->child_id(), 3);
+ // Now resumes requests for all RFH (12 and 13).
+ host_.ResumeBlockedRequestsForRoute(
+ GlobalFrameRoutingId(filter_->child_id(), 12));
+ host_.ResumeBlockedRequestsForRoute(
+ GlobalFrameRoutingId(filter_->child_id(), 13));
KickOffRequest();
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
@@ -1899,17 +2054,21 @@ TEST_F(ResourceDispatcherHostTest, TestBlockingResumingRequests) {
}
// Tests blocking and canceling requests.
-TEST_F(ResourceDispatcherHostTest, TestBlockingCancelingRequests) {
- host_.BlockRequestsForRoute(filter_->child_id(), 1);
-
- MakeTestRequest(0, 1, net::URLRequestTestJob::test_url_1());
- MakeTestRequest(1, 2, net::URLRequestTestJob::test_url_2());
- MakeTestRequest(0, 3, net::URLRequestTestJob::test_url_3());
- MakeTestRequest(1, 4, net::URLRequestTestJob::test_url_1());
+TEST_P(ResourceDispatcherHostTest, TestBlockingCancelingRequests) {
+ host_.BlockRequestsForRoute(GlobalFrameRoutingId(filter_->child_id(), 11));
+
+ MakeTestRequestWithRenderFrame(0, 10, 1, net::URLRequestTestJob::test_url_1(),
+ RESOURCE_TYPE_SUB_RESOURCE);
+ MakeTestRequestWithRenderFrame(1, 11, 2, net::URLRequestTestJob::test_url_2(),
+ RESOURCE_TYPE_SUB_RESOURCE);
+ MakeTestRequestWithRenderFrame(0, 10, 3, net::URLRequestTestJob::test_url_3(),
+ RESOURCE_TYPE_SUB_RESOURCE);
+ MakeTestRequestWithRenderFrame(1, 11, 4, net::URLRequestTestJob::test_url_1(),
+ RESOURCE_TYPE_SUB_RESOURCE);
// Blocked detachable resources should not delay cancellation.
- MakeTestRequestWithResourceType(filter_.get(), 1, 5,
- net::URLRequestTestJob::test_url_4(),
- RESOURCE_TYPE_PREFETCH); // detachable type
+ //
+ MakeTestRequestWithRenderFrame(1, 11, 5, net::URLRequestTestJob::test_url_4(),
+ RESOURCE_TYPE_PREFETCH); // detachable type
// Flush all the pending requests.
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
@@ -1918,14 +2077,15 @@ TEST_F(ResourceDispatcherHostTest, TestBlockingCancelingRequests) {
ResourceIPCAccumulator::ClassifiedMessages msgs;
accum_.GetClassifiedMessages(&msgs);
- // The 2 requests for the RVH 0 should have been processed.
+ // The 2 requests for the RFH 10 should have been processed.
ASSERT_EQ(2U, msgs.size());
CheckSuccessfulRequest(msgs[0], net::URLRequestTestJob::test_data_1());
CheckSuccessfulRequest(msgs[1], net::URLRequestTestJob::test_data_3());
- // Cancel requests for RVH 1.
- host_.CancelBlockedRequestsForRoute(filter_->child_id(), 1);
+ // Cancel requests for RFH 11.
+ host_.CancelBlockedRequestsForRoute(
+ GlobalFrameRoutingId(filter_->child_id(), 11));
KickOffRequest();
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
@@ -1935,11 +2095,12 @@ TEST_F(ResourceDispatcherHostTest, TestBlockingCancelingRequests) {
}
// Tests that blocked requests are canceled if their associated process dies.
-TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsProcessDies) {
+TEST_P(ResourceDispatcherHostTest, TestBlockedRequestsProcessDies) {
// This second filter is used to emulate a second process.
scoped_refptr<ForwardingFilter> second_filter = MakeForwardingFilter();
- host_.BlockRequestsForRoute(second_filter->child_id(), 0);
+ host_.BlockRequestsForRoute(
+ GlobalFrameRoutingId(second_filter->child_id(), 0));
MakeTestRequestWithResourceType(filter_.get(), 0, 1,
net::URLRequestTestJob::test_url_1(),
@@ -1981,13 +2142,14 @@ TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsProcessDies) {
// away. Note that we rely on Purify for finding the leaks if any.
// If this test turns the Purify bot red, check the ResourceDispatcherHost
// destructor to make sure the blocked requests are deleted.
-TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsDontLeak) {
+TEST_P(ResourceDispatcherHostTest, TestBlockedRequestsDontLeak) {
// This second filter is used to emulate a second process.
scoped_refptr<ForwardingFilter> second_filter = MakeForwardingFilter();
- host_.BlockRequestsForRoute(filter_->child_id(), 1);
- host_.BlockRequestsForRoute(filter_->child_id(), 2);
- host_.BlockRequestsForRoute(second_filter->child_id(), 1);
+ host_.BlockRequestsForRoute(GlobalFrameRoutingId(filter_->child_id(), 1));
+ host_.BlockRequestsForRoute(GlobalFrameRoutingId(filter_->child_id(), 2));
+ host_.BlockRequestsForRoute(
+ GlobalFrameRoutingId(second_filter->child_id(), 1));
MakeTestRequestWithResourceType(filter_.get(), 0, 1,
net::URLRequestTestJob::test_url_1(),
@@ -2022,9 +2184,9 @@ TEST_F(ResourceDispatcherHostTest, TestBlockedRequestsDontLeak) {
}
// Test the private helper method "CalculateApproximateMemoryCost()".
-TEST_F(ResourceDispatcherHostTest, CalculateApproximateMemoryCost) {
+TEST_P(ResourceDispatcherHostTest, CalculateApproximateMemoryCost) {
net::URLRequestContext context;
- scoped_ptr<net::URLRequest> req(context.CreateRequest(
+ std::unique_ptr<net::URLRequest> req(context.CreateRequest(
GURL("http://www.google.com"), net::DEFAULT_PRIORITY, NULL));
EXPECT_EQ(
4427,
@@ -2040,8 +2202,9 @@ TEST_F(ResourceDispatcherHostTest, CalculateApproximateMemoryCost) {
std::string upload_content;
upload_content.resize(33);
std::fill(upload_content.begin(), upload_content.end(), 'x');
- scoped_ptr<net::UploadElementReader> reader(new net::UploadBytesElementReader(
- upload_content.data(), upload_content.size()));
+ std::unique_ptr<net::UploadElementReader> reader(
+ new net::UploadBytesElementReader(upload_content.data(),
+ upload_content.size()));
req->set_upload(
net::ElementsUploadDataStream::CreateWithReader(std::move(reader), 0));
@@ -2053,7 +2216,7 @@ TEST_F(ResourceDispatcherHostTest, CalculateApproximateMemoryCost) {
// Test that too much memory for outstanding requests for a particular
// render_process_host_id causes requests to fail.
-TEST_F(ResourceDispatcherHostTest, TooMuchOutstandingRequestsMemory) {
+TEST_P(ResourceDispatcherHostTest, TooMuchOutstandingRequestsMemory) {
// Expected cost of each request as measured by
// ResourceDispatcherHost::CalculateApproximateMemoryCost().
int kMemoryCostOfTest2Req =
@@ -2130,7 +2293,7 @@ TEST_F(ResourceDispatcherHostTest, TooMuchOutstandingRequestsMemory) {
// Test that when too many requests are outstanding for a particular
// render_process_host_id, any subsequent request from it fails. Also verify
// that the global limit is honored.
-TEST_F(ResourceDispatcherHostTest, TooManyOutstandingRequests) {
+TEST_P(ResourceDispatcherHostTest, TooManyOutstandingRequests) {
// Tighten the bound on the ResourceDispatcherHost, to speed things up.
const size_t kMaxRequestsPerProcess = 2;
host_.set_max_num_in_flight_requests_per_process(kMaxRequestsPerProcess);
@@ -2193,7 +2356,7 @@ TEST_F(ResourceDispatcherHostTest, TooManyOutstandingRequests) {
}
// Tests that we sniff the mime type for a simple request.
-TEST_F(ResourceDispatcherHostTest, MimeSniffed) {
+TEST_P(ResourceDispatcherHostTest, MimeSniffed) {
std::string raw_headers("HTTP/1.1 200 OK\n\n");
std::string response_data("<html><title>Test One</title></html>");
SetResponse(raw_headers, response_data);
@@ -2215,7 +2378,7 @@ TEST_F(ResourceDispatcherHostTest, MimeSniffed) {
}
// Tests that we don't sniff the mime type when the server provides one.
-TEST_F(ResourceDispatcherHostTest, MimeNotSniffed) {
+TEST_P(ResourceDispatcherHostTest, MimeNotSniffed) {
std::string raw_headers("HTTP/1.1 200 OK\n"
"Content-type: image/jpeg\n\n");
std::string response_data("<html><title>Test One</title></html>");
@@ -2238,7 +2401,7 @@ TEST_F(ResourceDispatcherHostTest, MimeNotSniffed) {
}
// Tests that we don't sniff the mime type when there is no message body.
-TEST_F(ResourceDispatcherHostTest, MimeNotSniffed2) {
+TEST_P(ResourceDispatcherHostTest, MimeNotSniffed2) {
SetResponse("HTTP/1.1 304 Not Modified\n\n");
HandleScheme("http");
@@ -2257,7 +2420,7 @@ TEST_F(ResourceDispatcherHostTest, MimeNotSniffed2) {
ASSERT_EQ("", response_head.mime_type);
}
-TEST_F(ResourceDispatcherHostTest, MimeSniff204) {
+TEST_P(ResourceDispatcherHostTest, MimeSniff204) {
SetResponse("HTTP/1.1 204 No Content\n\n");
HandleScheme("http");
@@ -2276,7 +2439,7 @@ TEST_F(ResourceDispatcherHostTest, MimeSniff204) {
ASSERT_EQ("text/plain", response_head.mime_type);
}
-TEST_F(ResourceDispatcherHostTest, MimeSniffEmpty) {
+TEST_P(ResourceDispatcherHostTest, MimeSniffEmpty) {
SetResponse("HTTP/1.1 200 OK\n\n");
HandleScheme("http");
@@ -2296,7 +2459,7 @@ TEST_F(ResourceDispatcherHostTest, MimeSniffEmpty) {
}
// Tests for crbug.com/31266 (Non-2xx + application/octet-stream).
-TEST_F(ResourceDispatcherHostTest, ForbiddenDownload) {
+TEST_P(ResourceDispatcherHostTest, ForbiddenDownload) {
std::string raw_headers("HTTP/1.1 403 Forbidden\n"
"Content-disposition: attachment; filename=blah\n"
"Content-type: application/octet-stream\n\n");
@@ -2330,7 +2493,7 @@ TEST_F(ResourceDispatcherHostTest, ForbiddenDownload) {
// Test for http://crbug.com/76202 . We don't want to destroy a
// download request prematurely when processing a cancellation from
// the renderer.
-TEST_F(ResourceDispatcherHostTest, IgnoreCancelForDownloads) {
+TEST_P(ResourceDispatcherHostTest, IgnoreCancelForDownloads) {
EXPECT_EQ(0, host_.pending_requests());
int render_view_id = 0;
@@ -2370,7 +2533,7 @@ TEST_F(ResourceDispatcherHostTest, IgnoreCancelForDownloads) {
while (net::URLRequestTestJob::ProcessOnePendingMessage()) {}
}
-TEST_F(ResourceDispatcherHostTest, CancelRequestsForContext) {
+TEST_P(ResourceDispatcherHostTest, CancelRequestsForContext) {
EXPECT_EQ(0, host_.pending_requests());
int render_view_id = 0;
@@ -2411,7 +2574,7 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsForContext) {
EXPECT_EQ(0, host_.pending_requests());
}
-TEST_F(ResourceDispatcherHostTest, CancelRequestsForContextDetached) {
+TEST_P(ResourceDispatcherHostTest, CancelRequestsForContextDetached) {
EXPECT_EQ(0, host_.pending_requests());
int render_view_id = 0;
@@ -2440,7 +2603,11 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsForContextDetached) {
// Test the cancelling of requests that are being transferred to a new renderer
// due to a redirection.
-TEST_F(ResourceDispatcherHostTest, CancelRequestsForContextTransferred) {
+TEST_P(ResourceDispatcherHostTest, CancelRequestsForContextTransferred) {
+ // PlzNavigate: there are no transferred requests in PlzNavigate.
+ if (IsBrowserSideNavigationEnabled())
+ return;
+
EXPECT_EQ(0, host_.pending_requests());
int request_id = 1;
@@ -2457,7 +2624,7 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsForContextTransferred) {
GlobalRequestID global_request_id(web_contents_filter_->child_id(),
request_id);
- host_.MarkAsTransferredNavigation(global_request_id);
+ host_.MarkAsTransferredNavigation(global_request_id, nullptr);
// And now simulate a cancellation coming from the renderer.
ResourceHostMsg_CancelRequest msg(request_id);
@@ -2479,7 +2646,7 @@ TEST_F(ResourceDispatcherHostTest, CancelRequestsForContextTransferred) {
// Test transferred navigations with text/html, which doesn't trigger any
// content sniffing.
-TEST_F(ResourceDispatcherHostTest, TransferNavigationHtml) {
+TEST_P(ResourceDispatcherHostTest, TransferNavigationHtml) {
if (IsBrowserSideNavigationEnabled()) {
SUCCEED() << "Test is not applicable with browser side navigation enabled";
return;
@@ -2551,9 +2718,103 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationHtml) {
CheckSuccessfulRequest(msgs[1], kResponseBody);
}
+// Tests that during a navigation transferred from one process to
+// another, the certificate is updated to be associated with the new
+// process.
+TEST_P(ResourceDispatcherHostTest, TransferNavigationCertificateUpdate) {
+ if (IsBrowserSideNavigationEnabled()) {
+ SUCCEED() << "Test is not applicable with browser side navigation enabled";
+ return;
+ }
+ // This test expects the cross site request to be leaked, so it can transfer
+ // the request directly.
+ CrossSiteResourceHandler::SetLeakRequestsForTesting(true);
+
+ EXPECT_EQ(0, host_.pending_requests());
+
+ int render_view_id = 0;
+ int request_id = 1;
+
+ // Configure initial request.
+ SetResponse(
+ "HTTP/1.1 302 Found\n"
+ "Location: https://example.com/blech\n\n");
+
+ HandleScheme("https");
+
+ // Temporarily replace ContentBrowserClient with one that will trigger the
+ // transfer navigation code paths.
+ TransfersAllNavigationsContentBrowserClient new_client;
+ ContentBrowserClient* old_client = SetBrowserClientForTesting(&new_client);
+
+ MakeTestRequestWithResourceType(filter_.get(), render_view_id, request_id,
+ GURL("https://example2.com/blah"),
+ RESOURCE_TYPE_MAIN_FRAME);
+
+ // Now that the resource loader is blocked on the redirect, update the
+ // response and unblock by telling the AsyncResourceHandler to follow
+ // the redirect.
+ const std::string kResponseBody = "hello world";
+ SetResponse(
+ "HTTP/1.1 200 OK\n"
+ "Content-Type: text/html\n\n",
+ kResponseBody);
+ SetTestSSLCertificate();
+ ResourceHostMsg_FollowRedirect redirect_msg(request_id);
+ host_.OnMessageReceived(redirect_msg, filter_.get());
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Flush all the pending requests to get the response through the
+ // MimeTypeResourceHandler.`
+ while (net::URLRequestTestJob::ProcessOnePendingMessage()) {
+ }
+
+ // Restore, now that we've set up a transfer.
+ SetBrowserClientForTesting(old_client);
+
+ // This second filter is used to emulate a second process.
+ scoped_refptr<ForwardingFilter> second_filter = MakeForwardingFilter();
+
+ int new_render_view_id = 1;
+ int new_request_id = 2;
+
+ ResourceHostMsg_Request request = CreateResourceRequest(
+ "GET", RESOURCE_TYPE_MAIN_FRAME, GURL("https://example.com/blech"));
+ request.transferred_request_child_id = filter_->child_id();
+ request.transferred_request_request_id = request_id;
+
+ // Before sending the transfer request, set up the mock cert store so
+ // that the test can assert that the cert id is set during transfer.
+ mock_cert_store_.set_default_cert_id(1);
+
+ ResourceHostMsg_RequestResource transfer_request_msg(new_render_view_id,
+ new_request_id, request);
+ host_.OnMessageReceived(transfer_request_msg, second_filter.get());
+ base::MessageLoop::current()->RunUntilIdle();
+
+ // Check generated messages.
+ ResourceIPCAccumulator::ClassifiedMessages msgs;
+ accum_.GetClassifiedMessages(&msgs);
+
+ ASSERT_EQ(2U, msgs.size());
+ EXPECT_EQ(ResourceMsg_ReceivedRedirect::ID, msgs[0][0].type());
+ CheckSuccessfulRequest(msgs[1], kResponseBody);
+
+ // Check that the cert id was as expected in ReceivedResponse.
+ ASSERT_EQ(ResourceMsg_ReceivedResponse::ID, msgs[1][0].type());
+ base::PickleIterator iter(msgs[1][0]);
+ int sent_request_id;
+ ASSERT_TRUE(IPC::ReadParam(&msgs[1][0], &iter, &sent_request_id));
+ ResourceResponseHead response;
+ ASSERT_TRUE(IPC::ReadParam(&msgs[1][0], &iter, &response));
+ SSLStatus ssl;
+ ASSERT_TRUE(DeserializeSecurityInfo(response.security_info, &ssl));
+ EXPECT_EQ(1, ssl.cert_id);
+}
+
// Test transferring two navigations with text/html, to ensure the resource
// accounting works.
-TEST_F(ResourceDispatcherHostTest, TransferTwoNavigationsHtml) {
+TEST_P(ResourceDispatcherHostTest, TransferTwoNavigationsHtml) {
if (IsBrowserSideNavigationEnabled()) {
SUCCEED() << "Test is not applicable with browser side navigation enabled";
return;
@@ -2640,7 +2901,7 @@ TEST_F(ResourceDispatcherHostTest, TransferTwoNavigationsHtml) {
// Test transferred navigations with text/plain, which causes
// MimeTypeResourceHandler to buffer the response to sniff the content before
// the transfer occurs.
-TEST_F(ResourceDispatcherHostTest, TransferNavigationText) {
+TEST_P(ResourceDispatcherHostTest, TransferNavigationText) {
if (IsBrowserSideNavigationEnabled()) {
SUCCEED() << "Test is not applicable with browser side navigation enabled";
return;
@@ -2714,7 +2975,7 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationText) {
CheckSuccessfulRequest(msgs[1], kResponseBody);
}
-TEST_F(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
+TEST_P(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
if (IsBrowserSideNavigationEnabled()) {
SUCCEED() << "Test is not applicable with browser side navigation enabled";
return;
@@ -2804,7 +3065,7 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationWithProcessCrash) {
CheckSuccessfulRequest(msgs[1], kResponseBody);
}
-TEST_F(ResourceDispatcherHostTest, TransferNavigationWithTwoRedirects) {
+TEST_P(ResourceDispatcherHostTest, TransferNavigationWithTwoRedirects) {
if (IsBrowserSideNavigationEnabled()) {
SUCCEED() << "Test is not applicable with browser side navigation enabled";
return;
@@ -2898,7 +3159,7 @@ TEST_F(ResourceDispatcherHostTest, TransferNavigationWithTwoRedirects) {
CheckSuccessfulRequest(msgs[1], kResponseBody);
}
-TEST_F(ResourceDispatcherHostTest, UnknownURLScheme) {
+TEST_P(ResourceDispatcherHostTest, UnknownURLScheme) {
EXPECT_EQ(0, host_.pending_requests());
HandleScheme("http");
@@ -2922,7 +3183,7 @@ TEST_F(ResourceDispatcherHostTest, UnknownURLScheme) {
CheckRequestCompleteErrorCode(msgs[0][0], net::ERR_UNKNOWN_URL_SCHEME);
}
-TEST_F(ResourceDispatcherHostTest, DataReceivedACKs) {
+TEST_P(ResourceDispatcherHostTest, DataReceivedACKs) {
EXPECT_EQ(0, host_.pending_requests());
SendDataReceivedACKs(true);
@@ -2947,7 +3208,7 @@ TEST_F(ResourceDispatcherHostTest, DataReceivedACKs) {
// Request a very large detachable resource and cancel part way. Some of the
// data should have been sent to the renderer, but not all.
-TEST_F(ResourceDispatcherHostTest, DataSentBeforeDetach) {
+TEST_P(ResourceDispatcherHostTest, DataSentBeforeDetach) {
EXPECT_EQ(0, host_.pending_requests());
int render_view_id = 0;
@@ -3003,7 +3264,7 @@ TEST_F(ResourceDispatcherHostTest, DataSentBeforeDetach) {
net::ERR_ABORTED);
}
-TEST_F(ResourceDispatcherHostTest, DelayedDataReceivedACKs) {
+TEST_P(ResourceDispatcherHostTest, DelayedDataReceivedACKs) {
EXPECT_EQ(0, host_.pending_requests());
HandleScheme("big-job");
@@ -3052,7 +3313,7 @@ TEST_F(ResourceDispatcherHostTest, DelayedDataReceivedACKs) {
// Flakyness of this test might indicate memory corruption issues with
// for example the ResourceBuffer of AsyncResourceHandler.
-TEST_F(ResourceDispatcherHostTest, DataReceivedUnexpectedACKs) {
+TEST_P(ResourceDispatcherHostTest, DataReceivedUnexpectedACKs) {
EXPECT_EQ(0, host_.pending_requests());
HandleScheme("big-job");
@@ -3105,7 +3366,7 @@ TEST_F(ResourceDispatcherHostTest, DataReceivedUnexpectedACKs) {
}
// Tests the dispatcher host's temporary file management.
-TEST_F(ResourceDispatcherHostTest, RegisterDownloadedTempFile) {
+TEST_P(ResourceDispatcherHostTest, RegisterDownloadedTempFile) {
const int kRequestID = 1;
// Create a temporary file.
@@ -3152,7 +3413,7 @@ TEST_F(ResourceDispatcherHostTest, RegisterDownloadedTempFile) {
// Tests that temporary files held on behalf of child processes are released
// when the child process dies.
-TEST_F(ResourceDispatcherHostTest, ReleaseTemporiesOnProcessExit) {
+TEST_P(ResourceDispatcherHostTest, ReleaseTemporiesOnProcessExit) {
const int kRequestID = 1;
// Create a temporary file.
@@ -3183,7 +3444,7 @@ TEST_F(ResourceDispatcherHostTest, ReleaseTemporiesOnProcessExit) {
EXPECT_FALSE(base::PathExists(file_path));
}
-TEST_F(ResourceDispatcherHostTest, DownloadToFile) {
+TEST_P(ResourceDispatcherHostTest, DownloadToFile) {
// Make a request which downloads to file.
ResourceHostMsg_Request request = CreateResourceRequest(
"GET", RESOURCE_TYPE_SUB_RESOURCE, net::URLRequestTestJob::test_url_1());
@@ -3257,14 +3518,14 @@ TEST_F(ResourceDispatcherHostTest, DownloadToFile) {
}
// Tests GetLoadInfoForAllRoutes when there are no pending requests.
-TEST_F(ResourceDispatcherHostTest, LoadInfoNoRequests) {
- scoped_ptr<LoadInfoMap> load_info_map = RunLoadInfoTest(nullptr, 0);
+TEST_P(ResourceDispatcherHostTest, LoadInfoNoRequests) {
+ std::unique_ptr<LoadInfoMap> load_info_map = RunLoadInfoTest(nullptr, 0);
EXPECT_EQ(0u, load_info_map->size());
}
// Tests GetLoadInfoForAllRoutes when there are 3 requests from the same
// RenderView. The second one is farthest along.
-TEST_F(ResourceDispatcherHostTest, LoadInfo) {
+TEST_P(ResourceDispatcherHostTest, LoadInfo) {
const GlobalRoutingID kId(filter_->child_id(), 0);
LoadInfoTestRequestInfo request_info[] = {
{kId.route_id,
@@ -3280,7 +3541,7 @@ TEST_F(ResourceDispatcherHostTest, LoadInfo) {
net::LOAD_STATE_SENDING_REQUEST,
net::UploadProgress(0, 0)},
};
- scoped_ptr<LoadInfoMap> load_info_map =
+ std::unique_ptr<LoadInfoMap> load_info_map =
RunLoadInfoTest(request_info, arraysize(request_info));
ASSERT_EQ(1u, load_info_map->size());
ASSERT_TRUE(load_info_map->find(kId) != load_info_map->end());
@@ -3293,7 +3554,7 @@ TEST_F(ResourceDispatcherHostTest, LoadInfo) {
// Tests GetLoadInfoForAllRoutes when there are 2 requests with the same
// priority. The first one (Which will have the lowest ID) should be returned.
-TEST_F(ResourceDispatcherHostTest, LoadInfoSamePriority) {
+TEST_P(ResourceDispatcherHostTest, LoadInfoSamePriority) {
const GlobalRoutingID kId(filter_->child_id(), 0);
LoadInfoTestRequestInfo request_info[] = {
{kId.route_id,
@@ -3305,7 +3566,7 @@ TEST_F(ResourceDispatcherHostTest, LoadInfoSamePriority) {
net::LOAD_STATE_IDLE,
net::UploadProgress(0, 0)},
};
- scoped_ptr<LoadInfoMap> load_info_map =
+ std::unique_ptr<LoadInfoMap> load_info_map =
RunLoadInfoTest(request_info, arraysize(request_info));
ASSERT_EQ(1u, load_info_map->size());
ASSERT_TRUE(load_info_map->find(kId) != load_info_map->end());
@@ -3316,7 +3577,7 @@ TEST_F(ResourceDispatcherHostTest, LoadInfoSamePriority) {
}
// Tests GetLoadInfoForAllRoutes when a request is uploading a body.
-TEST_F(ResourceDispatcherHostTest, LoadInfoUploadProgress) {
+TEST_P(ResourceDispatcherHostTest, LoadInfoUploadProgress) {
const GlobalRoutingID kId(filter_->child_id(), 0);
LoadInfoTestRequestInfo request_info[] = {
{kId.route_id,
@@ -3340,7 +3601,7 @@ TEST_F(ResourceDispatcherHostTest, LoadInfoUploadProgress) {
net::LOAD_STATE_READING_RESPONSE,
net::UploadProgress(0, 0)},
};
- scoped_ptr<LoadInfoMap> load_info_map =
+ std::unique_ptr<LoadInfoMap> load_info_map =
RunLoadInfoTest(request_info, arraysize(request_info));
ASSERT_EQ(1u, load_info_map->size());
ASSERT_TRUE(load_info_map->find(kId) != load_info_map->end());
@@ -3354,7 +3615,7 @@ TEST_F(ResourceDispatcherHostTest, LoadInfoUploadProgress) {
// Tests GetLoadInfoForAllRoutes when there are 4 requests from 2 different
// RenderViews. Also tests the case where the first / last requests are the
// most interesting ones.
-TEST_F(ResourceDispatcherHostTest, LoadInfoTwoRenderViews) {
+TEST_P(ResourceDispatcherHostTest, LoadInfoTwoRenderViews) {
const GlobalRoutingID kId1(filter_->child_id(), 0);
const GlobalRoutingID kId2(filter_->child_id(), 1);
LoadInfoTestRequestInfo request_info[] = {
@@ -3375,7 +3636,7 @@ TEST_F(ResourceDispatcherHostTest, LoadInfoTwoRenderViews) {
net::LOAD_STATE_CONNECTING,
net::UploadProgress(0, 0)},
};
- scoped_ptr<LoadInfoMap> load_info_map =
+ std::unique_ptr<LoadInfoMap> load_info_map =
RunLoadInfoTest(request_info, arraysize(request_info));
ASSERT_EQ(2u, load_info_map->size());
@@ -3396,7 +3657,7 @@ TEST_F(ResourceDispatcherHostTest, LoadInfoTwoRenderViews) {
// Confirm that resource response started notifications are correctly
// transmitted to the WebContents.
-TEST_F(ResourceDispatcherHostTest, TransferResponseStarted) {
+TEST_P(ResourceDispatcherHostTest, TransferResponseStarted) {
int initial_count = web_contents_observer_->resource_response_start_count();
MakeWebContentsAssociatedTestRequest(1, net::URLRequestTestJob::test_url_1());
@@ -3408,7 +3669,7 @@ TEST_F(ResourceDispatcherHostTest, TransferResponseStarted) {
// Confirm that request redirected notifications are correctly
// transmitted to the WebContents.
-TEST_F(ResourceDispatcherHostTest, TransferRequestRedirected) {
+TEST_P(ResourceDispatcherHostTest, TransferRequestRedirected) {
int initial_count = web_contents_observer_->resource_request_redirect_count();
MakeWebContentsAssociatedTestRequest(
@@ -3420,15 +3681,13 @@ TEST_F(ResourceDispatcherHostTest, TransferRequestRedirected) {
}
// Confirm that DidChangePriority messages are respected.
-TEST_F(ResourceDispatcherHostTest, DidChangePriority) {
+TEST_P(ResourceDispatcherHostTest, DidChangePriority) {
// ResourceScheduler only throttles http and https requests.
HandleScheme("http");
// Needed to enable scheduling for this child.
host_.OnRenderViewHostCreated(filter_->child_id(), // child_id
- 0, // route_id
- true, // is_visible
- false); // is_audible
+ 0); // route_id
// Prevent any of these requests from completing.
job_factory_->SetDelayedCompleteJobGeneration(true);
@@ -3459,7 +3718,7 @@ TEST_F(ResourceDispatcherHostTest, DidChangePriority) {
// Confirm that resource response started notifications for downloads are not
// transmitted to the WebContents.
-TEST_F(ResourceDispatcherHostTest, TransferResponseStartedDownload) {
+TEST_P(ResourceDispatcherHostTest, TransferResponseStartedDownload) {
int initial_count(web_contents_observer_->resource_response_start_count());
MakeWebContentsAssociatedDownloadRequest(
@@ -3471,7 +3730,7 @@ TEST_F(ResourceDispatcherHostTest, TransferResponseStartedDownload) {
// Confirm that request redirected notifications for downloads are not
// transmitted to the WebContents.
-TEST_F(ResourceDispatcherHostTest, TransferRequestRedirectedDownload) {
+TEST_P(ResourceDispatcherHostTest, TransferRequestRedirectedDownload) {
int initial_count(web_contents_observer_->resource_request_redirect_count());
MakeWebContentsAssociatedDownloadRequest(
@@ -3481,6 +3740,28 @@ TEST_F(ResourceDispatcherHostTest, TransferRequestRedirectedDownload) {
web_contents_observer_->resource_request_redirect_count());
}
+// A URLRequestTestJob that sets a test certificate on the |ssl_info|
+// field of the response.
+class TestHTTPSURLRequestJob : public net::URLRequestTestJob {
+ public:
+ TestHTTPSURLRequestJob(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ const std::string& response_headers,
+ const std::string& response_data,
+ bool auto_advance)
+ : net::URLRequestTestJob(request,
+ network_delegate,
+ response_headers,
+ response_data,
+ auto_advance) {}
+
+ void GetResponseInfo(net::HttpResponseInfo* info) override {
+ net::URLRequestTestJob::GetResponseInfo(info);
+ info->ssl_info.cert =
+ net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
+ }
+};
+
net::URLRequestJob* TestURLRequestJobFactory::MaybeCreateJobWithProtocolHandler(
const std::string& scheme,
net::URLRequest* request,
@@ -3490,7 +3771,7 @@ net::URLRequestJob* TestURLRequestJobFactory::MaybeCreateJobWithProtocolHandler(
test_fixture_->wait_for_request_create_loop_->Quit();
if (test_fixture_->loader_test_request_info_) {
DCHECK_EQ(test_fixture_->loader_test_request_info_->url, request->url());
- scoped_ptr<LoadInfoTestRequestInfo> info =
+ std::unique_ptr<LoadInfoTestRequestInfo> info =
std::move(test_fixture_->loader_test_request_info_);
return new URLRequestLoadInfoJob(request, network_delegate,
info->load_state, info->upload_progress);
@@ -3523,6 +3804,10 @@ net::URLRequestJob* TestURLRequestJobFactory::MaybeCreateJobWithProtocolHandler(
request, network_delegate,
test_fixture_->response_headers_, test_fixture_->response_data_,
false);
+ } else if (test_fixture_->use_test_ssl_certificate_) {
+ return new TestHTTPSURLRequestJob(request, network_delegate,
+ test_fixture_->response_headers_,
+ test_fixture_->response_data_, false);
} else {
return new net::URLRequestTestJob(
request, network_delegate,
@@ -3545,4 +3830,10 @@ net::URLRequestJob* TestURLRequestJobFactory::MaybeInterceptResponse(
return nullptr;
}
+INSTANTIATE_TEST_CASE_P(
+ ResourceDispatcherHostTests,
+ ResourceDispatcherHostTest,
+ testing::Values(TestConfig::kDefault,
+ TestConfig::kOptimizeIPCForSmallResourceEnabled));
+
} // namespace content
diff --git a/chromium/content/browser/loader/resource_loader.cc b/chromium/content/browser/loader/resource_loader.cc
index eee044c6aaf..40e1f2a6074 100644
--- a/chromium/content/browser/loader/resource_loader.cc
+++ b/chromium/content/browser/loader/resource_loader.cc
@@ -13,6 +13,7 @@
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
#include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
#include "content/browser/appcache/appcache_interceptor.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/loader/cross_site_resource_handler.h"
@@ -65,11 +66,10 @@ void StoreSignedCertificateTimestamps(
void GetSSLStatusForRequest(const GURL& url,
const net::SSLInfo& ssl_info,
int child_id,
+ CertStore* cert_store,
SSLStatus* ssl_status) {
DCHECK(ssl_info.cert);
-
- int cert_id =
- CertStore::GetInstance()->StoreCert(ssl_info.cert.get(), child_id);
+ int cert_id = cert_store->StoreCert(ssl_info.cert.get(), child_id);
SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids;
StoreSignedCertificateTimestamps(ssl_info.signed_certificate_timestamps,
@@ -82,6 +82,7 @@ void GetSSLStatusForRequest(const GURL& url,
void PopulateResourceResponse(ResourceRequestInfoImpl* info,
net::URLRequest* request,
+ CertStore* cert_store,
ResourceResponse* response) {
response->head.request_time = request->request_time();
response->head.response_time = request->response_time();
@@ -115,7 +116,7 @@ void PopulateResourceResponse(ResourceRequestInfoImpl* info,
if (request->ssl_info().cert.get()) {
SSLStatus ssl_status;
GetSSLStatusForRequest(request->url(), request->ssl_info(),
- info->GetChildID(), &ssl_status);
+ info->GetChildID(), cert_store, &ssl_status);
response->head.security_info = SerializeSecurityInfo(ssl_status);
response->head.has_major_certificate_errors =
net::IsCertStatusError(ssl_status.cert_status) &&
@@ -131,8 +132,9 @@ void PopulateResourceResponse(ResourceRequestInfoImpl* info,
} // namespace
-ResourceLoader::ResourceLoader(scoped_ptr<net::URLRequest> request,
- scoped_ptr<ResourceHandler> handler,
+ResourceLoader::ResourceLoader(std::unique_ptr<net::URLRequest> request,
+ std::unique_ptr<ResourceHandler> handler,
+ CertStore* cert_store,
ResourceLoaderDelegate* delegate)
: deferred_stage_(DEFERRED_NONE),
request_(std::move(request)),
@@ -142,6 +144,7 @@ ResourceLoader::ResourceLoader(scoped_ptr<net::URLRequest> request,
times_cancelled_before_request_start_(0),
started_request_(false),
times_cancelled_after_request_start_(0),
+ cert_store_(cert_store),
weak_ptr_factory_(this) {
request_->set_delegate(this);
handler_->SetController(this);
@@ -170,6 +173,8 @@ void ResourceLoader::StartRequest() {
return;
}
+ TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::StartRequest", this,
+ TRACE_EVENT_FLAG_FLOW_OUT);
if (defer_start) {
deferred_stage_ = DEFERRED_START;
} else {
@@ -178,6 +183,8 @@ void ResourceLoader::StartRequest() {
}
void ResourceLoader::CancelRequest(bool from_renderer) {
+ TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CancelRequest", this,
+ TRACE_EVENT_FLAG_FLOW_IN);
CancelRequestInternal(net::ERR_ABORTED, from_renderer);
}
@@ -188,13 +195,17 @@ void ResourceLoader::CancelAndIgnore() {
}
void ResourceLoader::CancelWithError(int error_code) {
+ TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CancelWithError", this,
+ TRACE_EVENT_FLAG_FLOW_IN);
CancelRequestInternal(error_code, false);
}
-void ResourceLoader::MarkAsTransferring() {
+void ResourceLoader::MarkAsTransferring(
+ const scoped_refptr<ResourceResponse>& response) {
CHECK(IsResourceTypeFrame(GetRequestInfo()->GetResourceType()))
<< "Can only transfer for navigations";
is_transferring_ = true;
+ transferring_response_ = response;
int child_id = GetRequestInfo()->GetChildID();
AppCacheInterceptor::PrepareForCrossSiteTransfer(request(), child_id);
@@ -212,6 +223,7 @@ void ResourceLoader::CompleteTransfer() {
DCHECK(DEFERRED_READ == deferred_stage_ ||
DEFERRED_RESPONSE_COMPLETE == deferred_stage_);
DCHECK(is_transferring_);
+ DCHECK(transferring_response_);
// In some cases, a process transfer doesn't really happen and the
// request is resumed in the original process. Real transfers to a new process
@@ -225,6 +237,7 @@ void ResourceLoader::CompleteTransfer() {
handler->MaybeCompleteCrossSiteTransferInOldProcess(child_id);
is_transferring_ = false;
+ transferring_response_ = nullptr;
GetRequestInfo()->cross_site_handler()->ResumeResponse();
}
@@ -239,6 +252,8 @@ void ResourceLoader::ClearLoginDelegate() {
void ResourceLoader::OnReceivedRedirect(net::URLRequest* unused,
const net::RedirectInfo& redirect_info,
bool* defer) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
+ "ResourceLoader::OnReceivedRedirect");
DCHECK_EQ(request_.get(), unused);
DVLOG(1) << "OnReceivedRedirect: " << request_->url().spec();
@@ -246,9 +261,8 @@ void ResourceLoader::OnReceivedRedirect(net::URLRequest* unused,
ResourceRequestInfoImpl* info = GetRequestInfo();
- if (info->GetProcessType() != PROCESS_TYPE_PLUGIN &&
- !ChildProcessSecurityPolicyImpl::GetInstance()->
- CanRequestURL(info->GetChildID(), redirect_info.new_url)) {
+ if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(
+ info->GetChildID(), redirect_info.new_url)) {
DVLOG(1) << "Denied unauthorized request for "
<< redirect_info.new_url.possibly_invalid_spec();
@@ -265,8 +279,8 @@ void ResourceLoader::OnReceivedRedirect(net::URLRequest* unused,
return;
}
- scoped_refptr<ResourceResponse> response(new ResourceResponse());
- PopulateResourceResponse(info, request_.get(), response.get());
+ scoped_refptr<ResourceResponse> response = new ResourceResponse();
+ PopulateResourceResponse(info, request_.get(), cert_store_, response.get());
if (!handler_->OnRequestRedirected(redirect_info, response.get(), defer)) {
Cancel();
} else if (*defer) {
@@ -324,6 +338,8 @@ void ResourceLoader::OnSSLCertificateError(net::URLRequest* request,
void ResourceLoader::OnBeforeNetworkStart(net::URLRequest* unused,
bool* defer) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
+ "ResourceLoader::OnBeforeNetworkStart");
DCHECK_EQ(request_.get(), unused);
// Give the handler a chance to delay the URLRequest from using the network.
@@ -336,6 +352,8 @@ void ResourceLoader::OnBeforeNetworkStart(net::URLRequest* unused,
}
void ResourceLoader::OnResponseStarted(net::URLRequest* unused) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
+ "ResourceLoader::OnResponseStarted");
DCHECK_EQ(request_.get(), unused);
DVLOG(1) << "OnResponseStarted: " << request_->url().spec();
@@ -357,6 +375,8 @@ void ResourceLoader::OnResponseStarted(net::URLRequest* unused) {
}
void ResourceLoader::OnReadCompleted(net::URLRequest* unused, int bytes_read) {
+ TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
+ "ResourceLoader::OnReadCompleted");
DCHECK_EQ(request_.get(), unused);
DVLOG(1) << "OnReadCompleted: \"" << request_->url().spec() << "\""
<< " bytes_read = " << bytes_read;
@@ -537,8 +557,8 @@ void ResourceLoader::CancelRequestInternal(int error, bool from_renderer) {
void ResourceLoader::CompleteResponseStarted() {
ResourceRequestInfoImpl* info = GetRequestInfo();
- scoped_refptr<ResourceResponse> response(new ResourceResponse());
- PopulateResourceResponse(info, request_.get(), response.get());
+ scoped_refptr<ResourceResponse> response = new ResourceResponse();
+ PopulateResourceResponse(info, request_.get(), cert_store_, response.get());
delegate_->DidReceiveResponse(this);
@@ -591,6 +611,8 @@ void ResourceLoader::ResumeReading() {
}
void ResourceLoader::ReadMore(int* bytes_read) {
+ TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::ReadMore", this,
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
DCHECK(!is_deferred());
// Make sure we track the buffer in at least one place. This ensures it gets
@@ -619,6 +641,9 @@ void ResourceLoader::ReadMore(int* bytes_read) {
}
void ResourceLoader::CompleteRead(int bytes_read) {
+ TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CompleteRead", this,
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
+
DCHECK(bytes_read >= 0);
DCHECK(request_->status().is_success());
@@ -641,6 +666,9 @@ void ResourceLoader::CompleteRead(int bytes_read) {
}
void ResourceLoader::ResponseCompleted() {
+ TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::ResponseCompleted", this,
+ TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
+
DVLOG(1) << "ResponseCompleted: " << request_->url().spec();
RecordHistograms();
ResourceRequestInfoImpl* info = GetRequestInfo();
@@ -650,7 +678,7 @@ void ResourceLoader::ResponseCompleted() {
if (ssl_info.cert.get() != NULL) {
SSLStatus ssl_status;
GetSSLStatusForRequest(request_->url(), ssl_info, info->GetChildID(),
- &ssl_status);
+ cert_store_, &ssl_status);
security_info = SerializeSecurityInfo(ssl_status);
}
@@ -674,6 +702,8 @@ void ResourceLoader::ResponseCompleted() {
}
void ResourceLoader::CallDidFinishLoading() {
+ TRACE_EVENT_WITH_FLOW0("loading", "ResourceLoader::CallDidFinishLoading",
+ this, TRACE_EVENT_FLAG_FLOW_IN);
delegate_->DidFinishLoading(this);
}
diff --git a/chromium/content/browser/loader/resource_loader.h b/chromium/content/browser/loader/resource_loader.h
index 5b5ecdb500e..976111a7408 100644
--- a/chromium/content/browser/loader/resource_loader.h
+++ b/chromium/content/browser/loader/resource_loader.h
@@ -5,8 +5,9 @@
#ifndef CONTENT_BROWSER_LOADER_RESOURCE_LOADER_H_
#define CONTENT_BROWSER_LOADER_RESOURCE_LOADER_H_
+#include <memory>
+
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/timer/timer.h"
#include "content/browser/loader/resource_handler.h"
@@ -22,6 +23,7 @@ class X509Certificate;
}
namespace content {
+class CertStore;
class ResourceDispatcherHostLoginDelegate;
class ResourceLoaderDelegate;
class ResourceRequestInfoImpl;
@@ -34,8 +36,9 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
public SSLClientAuthHandler::Delegate,
public ResourceController {
public:
- ResourceLoader(scoped_ptr<net::URLRequest> request,
- scoped_ptr<ResourceHandler> handler,
+ ResourceLoader(std::unique_ptr<net::URLRequest> request,
+ std::unique_ptr<ResourceHandler> handler,
+ CertStore* cert_store,
ResourceLoaderDelegate* delegate);
~ResourceLoader() override;
@@ -43,7 +46,7 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
void CancelRequest(bool from_renderer);
bool is_transferring() const { return is_transferring_; }
- void MarkAsTransferring();
+ void MarkAsTransferring(const scoped_refptr<ResourceResponse>& response);
void CompleteTransfer();
net::URLRequest* request() { return request_.get(); }
@@ -51,6 +54,15 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
void ClearLoginDelegate();
+ // Returns a pointer to the ResourceResponse for a request that is
+ // being transferred to a new consumer. The response is valid between
+ // the time that the request is marked as transferring via
+ // MarkAsTransferring() and the time that the transfer is completed
+ // via CompleteTransfer().
+ ResourceResponse* transferring_response() {
+ return transferring_response_.get();
+ }
+
private:
// net::URLRequest::Delegate implementation:
void OnReceivedRedirect(net::URLRequest* request,
@@ -125,12 +137,12 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
};
DeferredStage deferred_stage_;
- scoped_ptr<net::URLRequest> request_;
- scoped_ptr<ResourceHandler> handler_;
+ std::unique_ptr<net::URLRequest> request_;
+ std::unique_ptr<ResourceHandler> handler_;
ResourceLoaderDelegate* delegate_;
scoped_refptr<ResourceDispatcherHostLoginDelegate> login_delegate_;
- scoped_ptr<SSLClientAuthHandler> ssl_client_auth_handler_;
+ std::unique_ptr<SSLClientAuthHandler> ssl_client_auth_handler_;
base::TimeTicks read_deferral_start_time_;
@@ -139,12 +151,22 @@ class CONTENT_EXPORT ResourceLoader : public net::URLRequest::Delegate,
// which point we'll receive a new ResourceHandler.
bool is_transferring_;
+ // Holds the ResourceResponse for a request that is being transferred
+ // to a new consumer. This member is populated when the request is
+ // marked as transferring via MarkAsTransferring(), and it is cleared
+ // when the transfer is completed via CompleteTransfer().
+ scoped_refptr<ResourceResponse> transferring_response_;
+
// Instrumentation add to investigate http://crbug.com/503306.
// TODO(mmenke): Remove once bug is fixed.
int times_cancelled_before_request_start_;
bool started_request_;
int times_cancelled_after_request_start_;
+ // Allows tests to use a mock CertStore. The CertStore must outlive
+ // the ResourceLoader.
+ CertStore* cert_store_;
+
base::WeakPtrFactory<ResourceLoader> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ResourceLoader);
diff --git a/chromium/content/browser/loader/resource_loader_unittest.cc b/chromium/content/browser/loader/resource_loader_unittest.cc
index 05ed7fc4efb..32197c7bc1e 100644
--- a/chromium/content/browser/loader/resource_loader_unittest.cc
+++ b/chromium/content/browser/loader/resource_loader_unittest.cc
@@ -6,13 +6,15 @@
#include <stddef.h>
#include <stdint.h>
+
+#include <memory>
#include <utility>
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
+#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
@@ -111,11 +113,10 @@ class LoaderDestroyingCertStore : public net::ClientCertStore {
// Creates a client certificate store which, when looked up, posts a task to
// reset |loader| and then call the callback. The caller is responsible for
// ensuring the pointers remain valid until the process is complete.
- LoaderDestroyingCertStore(scoped_ptr<ResourceLoader>* loader,
+ LoaderDestroyingCertStore(std::unique_ptr<ResourceLoader>* loader,
const base::Closure& on_loader_deleted_callback)
: loader_(loader),
- on_loader_deleted_callback_(on_loader_deleted_callback) {
- }
+ on_loader_deleted_callback_(on_loader_deleted_callback) {}
// net::ClientCertStore:
void GetClientCerts(const net::SSLCertRequestInfo& cert_request_info,
@@ -133,7 +134,7 @@ class LoaderDestroyingCertStore : public net::ClientCertStore {
// This needs to be static because |loader| owns the
// LoaderDestroyingCertStore (ClientCertStores are actually handles, and not
// global cert stores).
- static void DoCallback(scoped_ptr<ResourceLoader>* loader,
+ static void DoCallback(std::unique_ptr<ResourceLoader>* loader,
const base::Closure& cert_selected_callback,
const base::Closure& on_loader_deleted_callback) {
loader->reset();
@@ -141,7 +142,7 @@ class LoaderDestroyingCertStore : public net::ClientCertStore {
on_loader_deleted_callback.Run();
}
- scoped_ptr<ResourceLoader>* loader_;
+ std::unique_ptr<ResourceLoader>* loader_;
base::Closure on_loader_deleted_callback_;
DISALLOW_COPY_AND_ASSIGN(LoaderDestroyingCertStore);
@@ -167,7 +168,8 @@ class MockClientCertURLRequestJob : public net::URLRequestTestJob {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::Bind(&MockClientCertURLRequestJob::NotifyCertificateRequested,
- weak_factory_.GetWeakPtr(), cert_request_info));
+ weak_factory_.GetWeakPtr(),
+ base::RetainedRef(cert_request_info)));
}
void ContinueWithCertificate(net::X509Certificate* cert,
@@ -426,7 +428,7 @@ class ResourceHandlerStub : public ResourceHandler {
int total_bytes_downloaded_;
base::RunLoop deferred_run_loop_;
base::RunLoop response_completed_run_loop_;
- scoped_ptr<base::RunLoop> wait_for_progress_run_loop_;
+ std::unique_ptr<base::RunLoop> wait_for_progress_run_loop_;
};
// Test browser client that captures calls to SelectClientCertificates and
@@ -446,7 +448,7 @@ class SelectCertificateBrowserClient : public TestContentBrowserClient {
void SelectClientCertificate(
WebContents* web_contents,
net::SSLCertRequestInfo* cert_request_info,
- scoped_ptr<ClientCertificateDelegate> delegate) override {
+ std::unique_ptr<ClientCertificateDelegate> delegate) override {
EXPECT_FALSE(delegate_.get());
++call_count_;
@@ -468,7 +470,7 @@ class SelectCertificateBrowserClient : public TestContentBrowserClient {
private:
net::CertificateList passed_certs_;
int call_count_;
- scoped_ptr<ClientCertificateDelegate> delegate_;
+ std::unique_ptr<ClientCertificateDelegate> delegate_;
base::RunLoop select_certificate_run_loop_;
@@ -480,16 +482,16 @@ class ResourceContextStub : public MockResourceContext {
explicit ResourceContextStub(net::URLRequestContext* test_request_context)
: MockResourceContext(test_request_context) {}
- scoped_ptr<net::ClientCertStore> CreateClientCertStore() override {
+ std::unique_ptr<net::ClientCertStore> CreateClientCertStore() override {
return std::move(dummy_cert_store_);
}
- void SetClientCertStore(scoped_ptr<net::ClientCertStore> store) {
+ void SetClientCertStore(std::unique_ptr<net::ClientCertStore> store) {
dummy_cert_store_ = std::move(store);
}
private:
- scoped_ptr<net::ClientCertStore> dummy_cert_store_;
+ std::unique_ptr<net::ClientCertStore> dummy_cert_store_;
};
// Wraps a ChunkedUploadDataStream to behave as non-chunked to enable upload
@@ -531,8 +533,8 @@ void CreateTemporaryError(
const CreateTemporaryFileStreamCallback& callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
- base::Bind(callback, error, base::Passed(scoped_ptr<net::FileStream>()),
- scoped_refptr<ShareableFileReference>()));
+ base::Bind(callback, error,
+ base::Passed(std::unique_ptr<net::FileStream>()), nullptr));
}
} // namespace
@@ -554,19 +556,19 @@ class ResourceLoaderTest : public testing::Test,
return net::URLRequestTestJob::test_data_1();
}
- virtual scoped_ptr<net::URLRequestJobFactory::ProtocolHandler>
+ virtual std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>
CreateProtocolHandler() {
return net::URLRequestTestJob::CreateProtocolHandler();
}
- virtual scoped_ptr<ResourceHandler> WrapResourceHandler(
- scoped_ptr<ResourceHandlerStub> leaf_handler,
+ virtual std::unique_ptr<ResourceHandler> WrapResourceHandler(
+ std::unique_ptr<ResourceHandlerStub> leaf_handler,
net::URLRequest* request) {
return std::move(leaf_handler);
}
// Replaces loader_ with a new one for |request|.
- void SetUpResourceLoader(scoped_ptr<net::URLRequest> request) {
+ void SetUpResourceLoader(std::unique_ptr<net::URLRequest> request) {
raw_ptr_to_request_ = request.get();
RenderFrameHost* rfh = web_contents_->GetMainFrame();
@@ -576,13 +578,13 @@ class ResourceLoaderTest : public testing::Test,
rfh->GetRoutingID(), true /* is_main_frame */,
false /* parent_is_main_frame */, true /* allow_download */,
false /* is_async */, false /* is_using_lofi_ */);
- scoped_ptr<ResourceHandlerStub> resource_handler(
+ std::unique_ptr<ResourceHandlerStub> resource_handler(
new ResourceHandlerStub(request.get()));
raw_ptr_resource_handler_ = resource_handler.get();
loader_.reset(new ResourceLoader(
std::move(request),
WrapResourceHandler(std::move(resource_handler), raw_ptr_to_request_),
- this));
+ CertStore::GetInstance(), this));
}
void SetUp() override {
@@ -594,11 +596,9 @@ class ResourceLoaderTest : public testing::Test,
web_contents_.reset(
TestWebContents::Create(browser_context_.get(), site_instance.get()));
- scoped_ptr<net::URLRequest> request(
+ std::unique_ptr<net::URLRequest> request(
resource_context_.GetRequestContext()->CreateRequest(
- test_url(),
- net::DEFAULT_PRIORITY,
- nullptr /* delegate */));
+ test_url(), net::DEFAULT_PRIORITY, nullptr /* delegate */));
SetUpResourceLoader(std::move(request));
}
@@ -632,20 +632,20 @@ class ResourceLoaderTest : public testing::Test,
net::URLRequestJobFactoryImpl job_factory_;
net::TestURLRequestContext test_url_request_context_;
ResourceContextStub resource_context_;
- scoped_ptr<TestBrowserContext> browser_context_;
- scoped_ptr<TestWebContents> web_contents_;
+ std::unique_ptr<TestBrowserContext> browser_context_;
+ std::unique_ptr<TestWebContents> web_contents_;
// The ResourceLoader owns the URLRequest and the ResourceHandler.
ResourceHandlerStub* raw_ptr_resource_handler_;
net::URLRequest* raw_ptr_to_request_;
- scoped_ptr<ResourceLoader> loader_;
+ std::unique_ptr<ResourceLoader> loader_;
};
class ClientCertResourceLoaderTest : public ResourceLoaderTest {
protected:
- scoped_ptr<net::URLRequestJobFactory::ProtocolHandler> CreateProtocolHandler()
- override {
- return make_scoped_ptr(new MockClientCertJobProtocolHandler);
+ std::unique_ptr<net::URLRequestJobFactory::ProtocolHandler>
+ CreateProtocolHandler() override {
+ return base::WrapUnique(new MockClientCertJobProtocolHandler);
}
};
@@ -672,11 +672,11 @@ class HTTPSSecurityInfoResourceLoaderTest : public ResourceLoaderTest {
net::URLRequestFilter::GetInstance()->ClearHandlers();
net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
"https", "example.test",
- scoped_ptr<net::URLRequestInterceptor>(
+ std::unique_ptr<net::URLRequestInterceptor>(
new MockHTTPSJobURLRequestInterceptor(false /* redirect */)));
net::URLRequestFilter::GetInstance()->AddHostnameInterceptor(
"https", "example-redirect.test",
- scoped_ptr<net::URLRequestInterceptor>(
+ std::unique_ptr<net::URLRequestInterceptor>(
new MockHTTPSJobURLRequestInterceptor(true /* redirect */)));
}
@@ -692,7 +692,7 @@ TEST_F(ClientCertResourceLoaderTest, WithStoreLookup) {
std::vector<std::string> store_requested_authorities;
net::CertificateList dummy_certs(1, scoped_refptr<net::X509Certificate>(
new net::X509Certificate("test", "test", base::Time(), base::Time())));
- scoped_ptr<ClientCertStoreStub> test_store(new ClientCertStoreStub(
+ std::unique_ptr<ClientCertStoreStub> test_store(new ClientCertStoreStub(
dummy_certs, &store_request_count, &store_requested_authorities));
resource_context_.SetClientCertStore(std::move(test_store));
@@ -804,8 +804,7 @@ TEST_F(ClientCertResourceLoaderTest, StoreAsyncCancel) {
LoaderDestroyingCertStore* test_store =
new LoaderDestroyingCertStore(&loader_,
loader_destroyed_run_loop.QuitClosure());
- resource_context_.SetClientCertStore(
- make_scoped_ptr(test_store));
+ resource_context_.SetClientCertStore(base::WrapUnique(test_store));
loader_->StartRequest();
loader_destroyed_run_loop.Run();
@@ -880,8 +879,8 @@ class ResourceLoaderRedirectToFileTest : public ResourceLoaderTest {
return redirect_to_file_resource_handler_;
}
- scoped_ptr<ResourceHandler> WrapResourceHandler(
- scoped_ptr<ResourceHandlerStub> leaf_handler,
+ std::unique_ptr<ResourceHandler> WrapResourceHandler(
+ std::unique_ptr<ResourceHandlerStub> leaf_handler,
net::URLRequest* request) override {
leaf_handler->set_expect_reads(false);
@@ -893,7 +892,7 @@ class ResourceLoaderRedirectToFileTest : public ResourceLoaderTest {
CHECK(file.IsValid());
// Create mock file streams and a ShareableFileReference.
- scoped_ptr<net::testing::MockFileStream> file_stream(
+ std::unique_ptr<net::testing::MockFileStream> file_stream(
new net::testing::MockFileStream(std::move(file),
base::ThreadTaskRunnerHandle::Get()));
file_stream_ = file_stream.get();
@@ -904,7 +903,7 @@ class ResourceLoaderRedirectToFileTest : public ResourceLoaderTest {
BrowserThread::FILE).get());
// Inject them into the handler.
- scoped_ptr<RedirectToFileResourceHandler> handler(
+ std::unique_ptr<RedirectToFileResourceHandler> handler(
new RedirectToFileResourceHandler(std::move(leaf_handler), request));
redirect_to_file_resource_handler_ = handler.get();
handler->SetCreateTemporaryFileStreamFunctionForTesting(
@@ -915,12 +914,12 @@ class ResourceLoaderRedirectToFileTest : public ResourceLoaderTest {
}
private:
- void PostCallback(
- scoped_ptr<net::FileStream> file_stream,
- const CreateTemporaryFileStreamCallback& callback) {
+ void PostCallback(std::unique_ptr<net::FileStream> file_stream,
+ const CreateTemporaryFileStreamCallback& callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(callback, base::File::FILE_OK,
- base::Passed(&file_stream), deletable_file_));
+ FROM_HERE,
+ base::Bind(callback, base::File::FILE_OK, base::Passed(&file_stream),
+ base::RetainedRef(deletable_file_)));
}
base::FilePath temp_path_;
@@ -1079,7 +1078,7 @@ TEST_F(ResourceLoaderRedirectToFileTest, DownstreamDeferStart) {
// to it.
TEST_F(HTTPSSecurityInfoResourceLoaderTest, SecurityInfoOnHTTPSResource) {
// Start the request and wait for it to finish.
- scoped_ptr<net::URLRequest> request(
+ std::unique_ptr<net::URLRequest> request(
resource_context_.GetRequestContext()->CreateRequest(
test_https_url(), net::DEFAULT_PRIORITY, nullptr /* delegate */));
SetUpResourceLoader(std::move(request));
@@ -1117,7 +1116,7 @@ TEST_F(HTTPSSecurityInfoResourceLoaderTest, SecurityInfoOnHTTPSResource) {
TEST_F(HTTPSSecurityInfoResourceLoaderTest,
SecurityInfoOnHTTPSRedirectResource) {
// Start the request and wait for it to finish.
- scoped_ptr<net::URLRequest> request(
+ std::unique_ptr<net::URLRequest> request(
resource_context_.GetRequestContext()->CreateRequest(
test_https_redirect_url(), net::DEFAULT_PRIORITY,
nullptr /* delegate */));
diff --git a/chromium/content/browser/loader/resource_message_filter.h b/chromium/content/browser/loader/resource_message_filter.h
index 9bac4198f60..7047aa64735 100644
--- a/chromium/content/browser/loader/resource_message_filter.h
+++ b/chromium/content/browser/loader/resource_message_filter.h
@@ -5,9 +5,10 @@
#ifndef CONTENT_BROWSER_LOADER_RESOURCE_MESSAGE_FILTER_H_
#define CONTENT_BROWSER_LOADER_RESOURCE_MESSAGE_FILTER_H_
+#include <memory>
+
#include "base/callback_forward.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_message_filter.h"
diff --git a/chromium/content/browser/loader/resource_request_info_impl.cc b/chromium/content/browser/loader/resource_request_info_impl.cc
index 8511653ee50..37f4e992fb1 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.cc
+++ b/chromium/content/browser/loader/resource_request_info_impl.cc
@@ -8,6 +8,7 @@
#include "content/browser/loader/global_routing_id.h"
#include "content/browser/loader/resource_message_filter.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/net/url_request_service_worker_data.h"
#include "content/common/net/url_request_user_data.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/global_request_id.h"
@@ -106,6 +107,13 @@ bool ResourceRequestInfo::GetRenderFrameForRequest(
return true;
}
+// static
+bool ResourceRequestInfo::OriginatedFromServiceWorker(
+ const net::URLRequest* request) {
+ return !!request->GetUserData(
+ content::URLRequestServiceWorkerData::kUserDataKey);
+}
+
// ----------------------------------------------------------------------------
// ResourceRequestInfoImpl
@@ -269,13 +277,8 @@ bool ResourceRequestInfoImpl::WasIgnoredByHandler() const {
bool ResourceRequestInfoImpl::GetAssociatedRenderFrame(
int* render_process_id,
int* render_frame_id) const {
- if (process_type_ == PROCESS_TYPE_PLUGIN) {
- *render_process_id = origin_pid_;
- *render_frame_id = render_frame_id_;
- } else {
- *render_process_id = child_id_;
- *render_frame_id = render_frame_id_;
- }
+ *render_process_id = child_id_;
+ *render_frame_id = render_frame_id_;
return true;
}
diff --git a/chromium/content/browser/loader/resource_request_info_impl.h b/chromium/content/browser/loader/resource_request_info_impl.h
index 625e58ca890..1e383504c0b 100644
--- a/chromium/content/browser/loader/resource_request_info_impl.h
+++ b/chromium/content/browser/loader/resource_request_info_impl.h
@@ -5,12 +5,12 @@
#ifndef CONTENT_BROWSER_LOADER_RESOURCE_REQUEST_INFO_IMPL_H_
#define CONTENT_BROWSER_LOADER_RESOURCE_REQUEST_INFO_IMPL_H_
+#include <memory>
#include <string>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/supports_user_data.h"
#include "content/public/browser/resource_request_info.h"
diff --git a/chromium/content/browser/loader/resource_scheduler.cc b/chromium/content/browser/loader/resource_scheduler.cc
index 690f20f0a03..ea4c6df775d 100644
--- a/chromium/content/browser/loader/resource_scheduler.cc
+++ b/chromium/content/browser/loader/resource_scheduler.cc
@@ -17,7 +17,6 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/supports_user_data.h"
-#include "base/time/time.h"
#include "content/common/resource_messages.h"
#include "content/public/browser/resource_controller.h"
#include "content/public/browser/resource_request_info.h"
@@ -39,10 +38,6 @@ enum StartMode {
};
// Field trial constants
-const char kThrottleCoalesceFieldTrial[] = "RequestThrottlingAndCoalescing";
-const char kThrottleCoalesceFieldTrialThrottle[] = "Throttle";
-const char kThrottleCoalesceFieldTrialCoalesce[] = "Coalesce";
-
const char kRequestLimitFieldTrial[] = "OutstandingRequestLimiting";
const char kRequestLimitFieldTrialGroupPrefix[] = "Limit";
@@ -56,46 +51,10 @@ const RequestAttributes kAttributeInFlight = 0x01;
const RequestAttributes kAttributeDelayable = 0x02;
const RequestAttributes kAttributeLayoutBlocking = 0x04;
-// Post ResourceScheduler histograms of the following forms:
-// If |histogram_suffix| is NULL or the empty string:
-// ResourceScheduler.base_name.histogram_name
-// Else:
-// ResourceScheduler.base_name.histogram_name.histogram_suffix
-void PostHistogram(const char* base_name,
- const char* histogram_name,
- const char* histogram_suffix,
- base::TimeDelta time) {
- std::string histogram =
- base::StringPrintf("ResourceScheduler.%s.%s", base_name, histogram_name);
- if (histogram_suffix && histogram_suffix[0] != '\0')
- histogram = histogram + "." + histogram_suffix;
- base::HistogramBase* histogram_counter = base::Histogram::FactoryTimeGet(
- histogram, base::TimeDelta::FromMilliseconds(1),
- base::TimeDelta::FromMinutes(5), 50,
- base::Histogram::kUmaTargetedHistogramFlag);
- histogram_counter->AddTime(time);
-}
-
-// For use with PostHistogram to specify the correct string for histogram
-// suffixes based on number of Clients.
-const char* GetNumClientsString(size_t num_clients) {
- if (num_clients == 1)
- return "1Client";
- else if (num_clients <= 5)
- return "Max5Clients";
- else if (num_clients <= 15)
- return "Max15Clients";
- else if (num_clients <= 30)
- return "Max30Clients";
- return "Over30Clients";
-}
-
} // namespace
-static const size_t kCoalescedTimerPeriod = 5000;
static const size_t kDefaultMaxNumDelayableRequestsPerClient = 10;
static const size_t kMaxNumDelayableRequestsPerHost = 6;
-static const size_t kMaxNumThrottledRequestsPerClient = 1;
static const size_t kDefaultMaxNumDelayableWhileLayoutBlocking = 1;
static const net::RequestPriority
kDefaultLayoutBlockingPriorityThreshold = net::LOW;
@@ -191,7 +150,6 @@ class ResourceScheduler::ScheduledResourceRequest : public ResourceThrottle {
const RequestPriorityParams& priority,
bool is_async)
: client_id_(client_id),
- client_state_on_creation_(scheduler->GetClientState(client_id_)),
request_(request),
ready_(false),
deferred_(false),
@@ -224,8 +182,6 @@ class ResourceScheduler::ScheduledResourceRequest : public ResourceThrottle {
if (!request_->status().is_success())
return;
- bool was_deferred = deferred_;
-
// If the request was deferred, need to start it. Otherwise, will just not
// defer starting it in the first place, and the value of |start_mode|
// makes no difference.
@@ -245,32 +201,6 @@ class ResourceScheduler::ScheduledResourceRequest : public ResourceThrottle {
}
ready_ = true;
-
- // The rest of this method is just collecting histograms.
-
- base::TimeTicks time = base::TimeTicks::Now();
- ClientState current_state = scheduler_->GetClientState(client_id_);
- // Note: the client state isn't perfectly accurate since it won't capture
- // tabs which have switched between active and background multiple times.
- // Ex: A tab with the following transitions Active -> Background -> Active
- // will be recorded as Active.
- const char* client_state = "Other";
- if (current_state == client_state_on_creation_ && current_state == ACTIVE) {
- client_state = "Active";
- } else if (current_state == client_state_on_creation_ &&
- current_state == BACKGROUND) {
- client_state = "Background";
- }
-
- base::TimeDelta time_was_deferred = base::TimeDelta::FromMicroseconds(0);
- if (was_deferred)
- time_was_deferred = time - time_deferred_;
- PostHistogram("RequestTimeDeferred", client_state, NULL, time_was_deferred);
- PostHistogram("RequestTimeThrottled", client_state, NULL,
- time - request_->creation_time());
- // TODO(aiolos): Remove one of the above histograms after gaining an
- // understanding of the difference between them and which one is more
- // interesting.
}
void set_request_priority_params(const RequestPriorityParams& priority) {
@@ -313,13 +243,11 @@ class ResourceScheduler::ScheduledResourceRequest : public ResourceThrottle {
// ResourceThrottle interface:
void WillStartRequest(bool* defer) override {
deferred_ = *defer = !ready_;
- time_deferred_ = base::TimeTicks::Now();
}
const char* GetNameForLogging() const override { return "ResourceScheduler"; }
const ClientId client_id_;
- const ResourceScheduler::ClientState client_state_on_creation_;
net::URLRequest* request_;
bool ready_;
bool deferred_;
@@ -328,7 +256,6 @@ class ResourceScheduler::ScheduledResourceRequest : public ResourceThrottle {
ResourceScheduler* scheduler_;
RequestPriorityParams priority_;
uint32_t fifo_ordering_;
- base::TimeTicks time_deferred_;
base::WeakPtrFactory<ResourceScheduler::ScheduledResourceRequest>
weak_ptr_factory_;
@@ -365,29 +292,15 @@ void ResourceScheduler::RequestQueue::Insert(
// Each client represents a tab.
class ResourceScheduler::Client {
public:
- explicit Client(ResourceScheduler* scheduler,
- bool is_visible,
- bool is_audible)
- : is_audible_(is_audible),
- is_visible_(is_visible),
- is_loaded_(false),
- is_paused_(false),
+ explicit Client(ResourceScheduler* scheduler)
+ : is_loaded_(false),
has_html_body_(false),
using_spdy_proxy_(false),
- load_started_time_(base::TimeTicks::Now()),
scheduler_(scheduler),
in_flight_delayable_count_(0),
- total_layout_blocking_count_(0),
- throttle_state_(ResourceScheduler::THROTTLED) {}
-
- ~Client() {
- // Update to default state and pause to ensure the scheduler has a
- // correct count of relevant types of clients.
- is_visible_ = false;
- is_audible_ = false;
- is_paused_ = true;
- UpdateThrottleState();
- }
+ total_layout_blocking_count_(0) {}
+
+ ~Client() {}
void ScheduleRequest(net::URLRequest* url_request,
ScheduledResourceRequest* request) {
@@ -415,10 +328,9 @@ class ResourceScheduler::Client {
RequestSet StartAndRemoveAllRequests() {
// First start any pending requests so that they will be moved into
// in_flight_requests_. This may exceed the limits
- // kDefaultMaxNumDelayableRequestsPerClient, kMaxNumDelayableRequestsPerHost
- // and kMaxNumThrottledRequestsPerClient, so this method must not do
- // anything that depends on those limits before calling
- // ClearInFlightRequests() below.
+ // kDefaultMaxNumDelayableRequestsPerClient and
+ // kMaxNumDelayableRequestsPerHost, so this method must not do anything that
+ // depends on those limits before calling ClearInFlightRequests() below.
while (!pending_requests_.IsEmpty()) {
ScheduledResourceRequest* request =
*pending_requests_.GetNextHighestIterator();
@@ -437,102 +349,10 @@ class ResourceScheduler::Client {
return unowned_requests;
}
- bool is_active() const { return is_visible_ || is_audible_; }
-
bool is_loaded() const { return is_loaded_; }
- bool is_visible() const { return is_visible_; }
-
- void OnAudibilityChanged(bool is_audible) {
- UpdateState(is_audible, &is_audible_);
- }
-
- void OnVisibilityChanged(bool is_visible) {
- UpdateState(is_visible, &is_visible_);
- }
-
- // Function to update any client state variable used to determine whether a
- // Client is active or background. Used for is_visible_ and is_audible_.
- void UpdateState(bool new_state, bool* current_state) {
- bool was_active = is_active();
- *current_state = new_state;
- if (was_active == is_active())
- return;
- last_active_switch_time_ = base::TimeTicks::Now();
- UpdateThrottleState();
- }
-
void OnLoadingStateChanged(bool is_loaded) {
- if (is_loaded == is_loaded_) {
- return;
- }
is_loaded_ = is_loaded;
- UpdateThrottleState();
- if (!is_loaded_) {
- load_started_time_ = base::TimeTicks::Now();
- last_active_switch_time_ = base::TimeTicks();
- return;
- }
- base::TimeTicks cur_time = base::TimeTicks::Now();
- const char* num_clients =
- GetNumClientsString(scheduler_->client_map_.size());
- const char* client_catagory = "Other";
- if (last_active_switch_time_.is_null()) {
- client_catagory = is_active() ? "Active" : "Background";
- } else if (is_active()) {
- base::TimeDelta time_since_active = cur_time - last_active_switch_time_;
- PostHistogram("ClientLoadedTime", "Other.SwitchedToActive", NULL,
- time_since_active);
- PostHistogram("ClientLoadedTime", "Other.SwitchedToActive", num_clients,
- time_since_active);
- }
- base::TimeDelta time_since_load_started = cur_time - load_started_time_;
- PostHistogram("ClientLoadedTime", client_catagory, NULL,
- time_since_load_started);
- PostHistogram("ClientLoadedTime", client_catagory, num_clients,
- time_since_load_started);
- // TODO(aiolos): The above histograms will not take main resource load time
- // into account with PlzNavigate into account. The ResourceScheduler also
- // will load the main resources without a clients with the current logic.
- // Find a way to fix both of these issues.
- }
-
- void SetPaused() {
- is_paused_ = true;
- UpdateThrottleState();
- }
-
- void UpdateThrottleState() {
- ClientThrottleState old_throttle_state = throttle_state_;
- if (!scheduler_->should_throttle()) {
- SetThrottleState(UNTHROTTLED);
- } else if (is_active() && !is_loaded_) {
- SetThrottleState(ACTIVE_AND_LOADING);
- } else if (is_active()) {
- SetThrottleState(UNTHROTTLED);
- } else if (is_paused_) {
- SetThrottleState(PAUSED);
- } else if (!scheduler_->active_clients_loaded()) {
- SetThrottleState(THROTTLED);
- } else if (is_loaded_ && scheduler_->should_coalesce()) {
- SetThrottleState(COALESCED);
- } else if (!is_active()) {
- SetThrottleState(UNTHROTTLED);
- }
-
- if (throttle_state_ == old_throttle_state) {
- return;
- }
- if (throttle_state_ == ACTIVE_AND_LOADING) {
- scheduler_->IncrementActiveClientsLoading();
- } else if (old_throttle_state == ACTIVE_AND_LOADING) {
- scheduler_->DecrementActiveClientsLoading();
- }
- if (throttle_state_ == COALESCED) {
- scheduler_->IncrementCoalescedClients();
- } else if (old_throttle_state == COALESCED) {
- scheduler_->DecrementCoalescedClients();
- }
}
void OnNavigate() {
@@ -573,50 +393,6 @@ class ResourceScheduler::Client {
}
}
- // Called on Client creation, when a Client changes user observability,
- // possibly when all observable Clients have finished loading, and
- // possibly when this Client has finished loading.
- // State changes:
- // Client became observable.
- // any state -> UNTHROTTLED
- // Client is unobservable, but all observable clients finished loading.
- // THROTTLED -> UNTHROTTLED
- // Non-observable client finished loading.
- // THROTTLED || UNTHROTTLED -> COALESCED
- // Non-observable client, an observable client starts loading.
- // COALESCED -> THROTTLED
- // A COALESCED client will transition into UNTHROTTLED when the network is
- // woken up by a heartbeat and then transition back into COALESCED.
- void SetThrottleState(ResourceScheduler::ClientThrottleState throttle_state) {
- if (throttle_state == throttle_state_) {
- return;
- }
- throttle_state_ = throttle_state;
- if (throttle_state_ != PAUSED) {
- is_paused_ = false;
- }
- LoadAnyStartablePendingRequests();
- // TODO(aiolos): Stop any started but not inflght requests when
- // switching to stricter throttle state?
- }
-
- ResourceScheduler::ClientThrottleState throttle_state() const {
- return throttle_state_;
- }
-
- void LoadCoalescedRequests() {
- if (throttle_state_ != COALESCED) {
- return;
- }
- if (scheduler_->active_clients_loaded()) {
- SetThrottleState(UNTHROTTLED);
- } else {
- SetThrottleState(THROTTLED);
- }
- LoadAnyStartablePendingRequests();
- SetThrottleState(COALESCED);
- }
-
private:
enum ShouldStartReqResult {
DO_NOT_START_REQUEST_AND_STOP_SEARCHING,
@@ -785,8 +561,6 @@ class ResourceScheduler::Client {
// All types of requests:
// * If an outstanding request limit is in place, only that number
// of requests may be in flight for a single client at the same time.
- //
- // ACTIVE_AND_LOADING and UNTHROTTLED Clients follow these rules:
// * Non-delayable, High-priority and request-priority capable requests are
// issued immediately.
// * Low priority requests are delayable.
@@ -798,21 +572,7 @@ class ResourceScheduler::Client {
// loading delayable requests.
// * Never exceed 10 delayable requests in flight per client.
// * Never exceed 6 delayable requests for a given host.
- //
- // THROTTLED Clients follow these rules:
- // * Non-delayable and request-priority-capable requests are issued
- // immediately.
- // * At most one non-request-priority-capable request will be issued per
- // THROTTLED Client
- // * If no high priority requests are in flight, start loading low priority
- // requests.
- //
- // COALESCED Clients never load requests, with the following exceptions:
- // * Non-delayable requests are issued imediately.
- // * On a (currently 5 second) heart beat, they load all requests as an
- // UNTHROTTLED Client, and then return to the COALESCED state.
- // * When an active Client makes a request, they are THROTTLED until the
- // active Client finishes loading.
+
ShouldStartReqResult ShouldStartRequest(
ScheduledResourceRequest* request) const {
const net::URLRequest& url_request = *request->url_request();
@@ -823,14 +583,9 @@ class ResourceScheduler::Client {
// TODO(simonjam): This may end up causing disk contention. We should
// experiment with throttling if that happens.
- // TODO(aiolos): We probably want to Coalesce these as well to avoid
- // waking the disk.
if (!url_request.url().SchemeIsHTTPOrHTTPS())
return START_REQUEST;
- if (throttle_state_ == COALESCED)
- return DO_NOT_START_REQUEST_AND_STOP_SEARCHING;
-
if (using_spdy_proxy_ && url_request.url().SchemeIs(url::kHttpScheme))
return START_REQUEST;
@@ -851,13 +606,6 @@ class ResourceScheduler::Client {
if (http_server_properties.SupportsRequestPriority(host_port_pair))
return START_REQUEST;
- if (throttle_state_ == THROTTLED &&
- in_flight_requests_.size() >= kMaxNumThrottledRequestsPerClient) {
- // There may still be request-priority-capable requests that should be
- // issued.
- return DO_NOT_START_REQUEST_AND_KEEP_SEARCHING;
- }
-
// Non-delayable requests.
if (!RequestAttributesAreSet(request->attributes(), kAttributeDelayable))
return START_REQUEST;
@@ -949,52 +697,29 @@ class ResourceScheduler::Client {
}
}
- bool is_audible_;
- bool is_visible_;
bool is_loaded_;
- bool is_paused_;
// Tracks if the main HTML parser has reached the body which marks the end of
// layout-blocking resources.
bool has_html_body_;
bool using_spdy_proxy_;
RequestQueue pending_requests_;
RequestSet in_flight_requests_;
- base::TimeTicks load_started_time_;
- // The last time the client switched state between active and background.
- base::TimeTicks last_active_switch_time_;
ResourceScheduler* scheduler_;
// The number of delayable in-flight requests.
size_t in_flight_delayable_count_;
// The number of layout-blocking in-flight requests.
size_t total_layout_blocking_count_;
- ResourceScheduler::ClientThrottleState throttle_state_;
};
ResourceScheduler::ResourceScheduler()
- : should_coalesce_(false),
- should_throttle_(false),
- active_clients_loading_(0),
- coalesced_clients_(0),
- limit_outstanding_requests_(false),
+ : limit_outstanding_requests_(false),
outstanding_request_limit_(0),
- non_delayable_threshold_(
- kDefaultLayoutBlockingPriorityThreshold),
+ non_delayable_threshold_(kDefaultLayoutBlockingPriorityThreshold),
enable_in_flight_non_delayable_threshold_(false),
in_flight_non_delayable_threshold_(0),
max_num_delayable_while_layout_blocking_(
kDefaultMaxNumDelayableWhileLayoutBlocking),
- max_num_delayable_requests_(kDefaultMaxNumDelayableRequestsPerClient),
- coalescing_timer_(new base::Timer(true /* retain_user_task */,
- true /* is_repeating */)) {
- std::string throttling_trial_group =
- base::FieldTrialList::FindFullName(kThrottleCoalesceFieldTrial);
- if (throttling_trial_group == kThrottleCoalesceFieldTrialThrottle) {
- should_throttle_ = true;
- } else if (throttling_trial_group == kThrottleCoalesceFieldTrialCoalesce) {
- should_coalesce_ = true;
- should_throttle_ = true;
- }
-
+ max_num_delayable_requests_(kDefaultMaxNumDelayableRequestsPerClient) {
std::string outstanding_limit_trial_group =
base::FieldTrialList::FindFullName(kRequestLimitFieldTrial);
std::vector<std::string> split_group(
@@ -1051,30 +776,17 @@ ResourceScheduler::~ResourceScheduler() {
DCHECK(client_map_.empty());
}
-void ResourceScheduler::SetThrottleOptionsForTesting(bool should_throttle,
- bool should_coalesce) {
- should_coalesce_ = should_coalesce;
- should_throttle_ = should_throttle;
- OnLoadingActiveClientsStateChangedForAllClients();
-}
-
-ResourceScheduler::ClientThrottleState
-ResourceScheduler::GetClientStateForTesting(int child_id, int route_id) {
- Client* client = GetClient(child_id, route_id);
- DCHECK(client);
- return client->throttle_state();
-}
-
-scoped_ptr<ResourceThrottle> ResourceScheduler::ScheduleRequest(
+std::unique_ptr<ResourceThrottle> ResourceScheduler::ScheduleRequest(
int child_id,
int route_id,
bool is_async,
net::URLRequest* url_request) {
DCHECK(CalledOnValidThread());
ClientId client_id = MakeClientId(child_id, route_id);
- scoped_ptr<ScheduledResourceRequest> request(new ScheduledResourceRequest(
- client_id, url_request, this,
- RequestPriorityParams(url_request->priority(), 0), is_async));
+ std::unique_ptr<ScheduledResourceRequest> request(
+ new ScheduledResourceRequest(
+ client_id, url_request, this,
+ RequestPriorityParams(url_request->priority(), 0), is_async));
ClientMap::iterator it = client_map_.find(client_id);
if (it == client_map_.end()) {
@@ -1109,17 +821,13 @@ void ResourceScheduler::RemoveRequest(ScheduledResourceRequest* request) {
}
void ResourceScheduler::OnClientCreated(int child_id,
- int route_id,
- bool is_visible,
- bool is_audible) {
+ int route_id) {
DCHECK(CalledOnValidThread());
ClientId client_id = MakeClientId(child_id, route_id);
DCHECK(!ContainsKey(client_map_, client_id));
- Client* client = new Client(this, is_visible, is_audible);
+ Client* client = new Client(this);
client_map_[client_id] = client;
-
- client->UpdateThrottleState();
}
void ResourceScheduler::OnClientDeleted(int child_id, int route_id) {
@@ -1150,23 +858,6 @@ void ResourceScheduler::OnLoadingStateChanged(int child_id,
client->OnLoadingStateChanged(is_loaded);
}
-void ResourceScheduler::OnVisibilityChanged(int child_id,
- int route_id,
- bool is_visible) {
- Client* client = GetClient(child_id, route_id);
- DCHECK(client);
- client->OnVisibilityChanged(is_visible);
-}
-
-void ResourceScheduler::OnAudibilityChanged(int child_id,
- int route_id,
- bool is_audible) {
- Client* client = GetClient(child_id, route_id);
- // We might get this call after the client has been deleted.
- if (client)
- client->OnAudibilityChanged(is_audible);
-}
-
void ResourceScheduler::OnNavigate(int child_id, int route_id) {
DCHECK(CalledOnValidThread());
ClientId client_id = MakeClientId(child_id, route_id);
@@ -1210,12 +901,6 @@ void ResourceScheduler::OnReceivedSpdyProxiedHttpResponse(
client->OnReceivedSpdyProxiedHttpResponse();
}
-bool ResourceScheduler::IsClientVisibleForTesting(int child_id, int route_id) {
- Client* client = GetClient(child_id, route_id);
- DCHECK(client);
- return client->is_visible();
-}
-
bool ResourceScheduler::HasLoadingClients() const {
for (const auto& client : client_map_) {
if (!client.second->is_loaded())
@@ -1234,100 +919,6 @@ ResourceScheduler::Client* ResourceScheduler::GetClient(int child_id,
return client_it->second;
}
-void ResourceScheduler::DecrementActiveClientsLoading() {
- DCHECK_NE(0u, active_clients_loading_);
- --active_clients_loading_;
- DCHECK_EQ(active_clients_loading_, CountActiveClientsLoading());
- if (active_clients_loading_ == 0) {
- OnLoadingActiveClientsStateChangedForAllClients();
- }
-}
-
-void ResourceScheduler::IncrementActiveClientsLoading() {
- ++active_clients_loading_;
- DCHECK_EQ(active_clients_loading_, CountActiveClientsLoading());
- if (active_clients_loading_ == 1) {
- OnLoadingActiveClientsStateChangedForAllClients();
- }
-}
-
-void ResourceScheduler::OnLoadingActiveClientsStateChangedForAllClients() {
- ClientMap::iterator client_it = client_map_.begin();
- while (client_it != client_map_.end()) {
- Client* client = client_it->second;
- client->UpdateThrottleState();
- ++client_it;
- }
-}
-
-size_t ResourceScheduler::CountActiveClientsLoading() const {
- size_t active_and_loading = 0;
- ClientMap::const_iterator client_it = client_map_.begin();
- while (client_it != client_map_.end()) {
- Client* client = client_it->second;
- if (client->throttle_state() == ACTIVE_AND_LOADING) {
- ++active_and_loading;
- }
- ++client_it;
- }
- return active_and_loading;
-}
-
-void ResourceScheduler::IncrementCoalescedClients() {
- ++coalesced_clients_;
- DCHECK(should_coalesce_);
- DCHECK_EQ(coalesced_clients_, CountCoalescedClients());
- if (coalesced_clients_ == 1) {
- coalescing_timer_->Start(
- FROM_HERE,
- base::TimeDelta::FromMilliseconds(kCoalescedTimerPeriod),
- base::Bind(&ResourceScheduler::LoadCoalescedRequests,
- base::Unretained(this)));
- }
-}
-
-void ResourceScheduler::DecrementCoalescedClients() {
- DCHECK(should_coalesce_);
- DCHECK_NE(0U, coalesced_clients_);
- --coalesced_clients_;
- DCHECK_EQ(coalesced_clients_, CountCoalescedClients());
- if (coalesced_clients_ == 0) {
- coalescing_timer_->Stop();
- }
-}
-
-size_t ResourceScheduler::CountCoalescedClients() const {
- DCHECK(should_coalesce_);
- size_t coalesced_clients = 0;
- ClientMap::const_iterator client_it = client_map_.begin();
- while (client_it != client_map_.end()) {
- Client* client = client_it->second;
- if (client->throttle_state() == COALESCED) {
- ++coalesced_clients;
- }
- ++client_it;
- }
- return coalesced_clients_;
-}
-
-void ResourceScheduler::LoadCoalescedRequests() {
- DCHECK(should_coalesce_);
- ClientMap::iterator client_it = client_map_.begin();
- while (client_it != client_map_.end()) {
- Client* client = client_it->second;
- client->LoadCoalescedRequests();
- ++client_it;
- }
-}
-
-ResourceScheduler::ClientState ResourceScheduler::GetClientState(
- ClientId client_id) const {
- ClientMap::const_iterator client_it = client_map_.find(client_id);
- if (client_it == client_map_.end())
- return UNKNOWN;
- return client_it->second->is_active() ? ACTIVE : BACKGROUND;
-}
-
void ResourceScheduler::ReprioritizeRequest(net::URLRequest* request,
net::RequestPriority new_priority,
int new_intra_priority_value) {
diff --git a/chromium/content/browser/loader/resource_scheduler.h b/chromium/content/browser/loader/resource_scheduler.h
index 444d97d1693..a2f114a1a0e 100644
--- a/chromium/content/browser/loader/resource_scheduler.h
+++ b/chromium/content/browser/loader/resource_scheduler.h
@@ -9,13 +9,12 @@
#include <stdint.h>
#include <map>
+#include <memory>
#include <set>
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/threading/non_thread_safe.h"
-#include "base/timer/timer.h"
#include "content/common/content_export.h"
#include "net/base/priority_queue.h"
#include "net/base/request_priority.h"
@@ -56,62 +55,22 @@ class ResourceThrottle;
// the URLRequest.
class CONTENT_EXPORT ResourceScheduler : public base::NonThreadSafe {
public:
- enum ClientThrottleState {
- // TODO(aiolos): Add logic to ShouldStartRequest for PAUSED Clients to only
- // issue synchronous requests.
- // TODO(aiolos): Add max number of THROTTLED Clients, and logic to set
- // subsquent Clients to PAUSED instead. Also add logic to unpause a Client
- // when a background Client becomes COALESCED (ie, finishes loading.)
- // TODO(aiolos): Add tests for the above mentioned logic.
-
- // Currently being deleted client.
- // This state currently follows the same logic for loading requests as
- // UNTHROTTLED/ACTIVE_AND_LOADING Clients. See above TODO's.
- PAUSED,
- // Loaded background client, all observable clients loaded.
- COALESCED,
- // Background client, an observable client is loading.
- THROTTLED,
- // Observable (active) loaded client or
- // Loading background client, all observable clients loaded.
- // Note that clients which would be COALESCED are UNTHROTTLED until
- // coalescing is turned on.
- UNTHROTTLED,
- // Observable (active) loading client.
- ACTIVE_AND_LOADING,
- };
-
ResourceScheduler();
~ResourceScheduler();
- // Use a mock timer when testing.
- void set_timer_for_testing(scoped_ptr<base::Timer> timer) {
- coalescing_timer_.reset(timer.release());
- }
-
- // TODO(aiolos): Remove when throttling and coalescing have landed
- void SetThrottleOptionsForTesting(bool should_throttle, bool should_coalesce);
-
- bool should_coalesce() const { return should_coalesce_; }
- bool should_throttle() const { return should_throttle_; }
-
- ClientThrottleState GetClientStateForTesting(int child_id, int route_id);
-
// Requests that this ResourceScheduler schedule, and eventually loads, the
// specified |url_request|. Caller should delete the returned ResourceThrottle
// when the load completes or is canceled, before |url_request| is deleted.
- scoped_ptr<ResourceThrottle> ScheduleRequest(int child_id,
- int route_id,
- bool is_async,
- net::URLRequest* url_request);
+ std::unique_ptr<ResourceThrottle> ScheduleRequest(
+ int child_id,
+ int route_id,
+ bool is_async,
+ net::URLRequest* url_request);
// Signals from the UI thread, posted as tasks on the IO thread:
// Called when a renderer is created.
- void OnClientCreated(int child_id,
- int route_id,
- bool is_visible,
- bool is_audible);
+ void OnClientCreated(int child_id, int route_id);
// Called when a renderer is destroyed.
void OnClientDeleted(int child_id, int route_id);
@@ -119,12 +78,6 @@ class CONTENT_EXPORT ResourceScheduler : public base::NonThreadSafe {
// Called when a renderer stops or restarts loading.
void OnLoadingStateChanged(int child_id, int route_id, bool is_loaded);
- // Called when a Client is shown or hidden.
- void OnVisibilityChanged(int child_id, int route_id, bool is_visible);
-
- // Called when a Client starts or stops playing audio.
- void OnAudibilityChanged(int child_id, int route_id, bool is_audible);
-
// Signals from IPC messages directly from the renderers:
// Called when a client navigates to a new main document.
@@ -142,11 +95,6 @@ class CONTENT_EXPORT ResourceScheduler : public base::NonThreadSafe {
// Client functions:
- // Called to check if all user observable tabs have completed loading.
- bool active_clients_loaded() const { return active_clients_loading_ == 0; }
-
- bool IsClientVisibleForTesting(int child_id, int route_id);
-
// Returns true if at least one client is currently loading.
bool HasLoadingClients() const;
@@ -203,15 +151,6 @@ class CONTENT_EXPORT ResourceScheduler : public base::NonThreadSafe {
return max_num_delayable_requests_;
}
- enum ClientState {
- // Observable client.
- ACTIVE,
- // Non-observable client.
- BACKGROUND,
- // No client found.
- UNKNOWN,
- };
-
class RequestQueue;
class ScheduledResourceRequest;
struct RequestPriorityParams;
@@ -228,42 +167,13 @@ class CONTENT_EXPORT ResourceScheduler : public base::NonThreadSafe {
// Called when a ScheduledResourceRequest is destroyed.
void RemoveRequest(ScheduledResourceRequest* request);
- // These calls may update the ThrottleState of all clients, and have the
- // potential to be re-entrant.
- // Called when a Client newly becomes active loading.
- void IncrementActiveClientsLoading();
- // Called when an active and loading Client either completes loading or
- // becomes inactive.
- void DecrementActiveClientsLoading();
-
- void OnLoadingActiveClientsStateChangedForAllClients();
-
- size_t CountActiveClientsLoading() const;
-
- // Called when a Client becomes coalesced.
- void IncrementCoalescedClients();
- // Called when a client stops being coalesced.
- void DecrementCoalescedClients();
-
- void LoadCoalescedRequests();
-
- size_t CountCoalescedClients() const;
-
- // Returns UNKNOWN if the corresponding client is not found, else returns
- // whether the client is ACTIVE (user-observable) or BACKGROUND.
- ClientState GetClientState(ClientId client_id) const;
-
// Returns the client ID for the given |child_id| and |route_id| combo.
ClientId MakeClientId(int child_id, int route_id);
// Returns the client for the given |child_id| and |route_id| combo.
Client* GetClient(int child_id, int route_id);
- bool should_coalesce_;
- bool should_throttle_;
ClientMap client_map_;
- size_t active_clients_loading_;
- size_t coalesced_clients_;
bool limit_outstanding_requests_;
size_t outstanding_request_limit_;
net::RequestPriority non_delayable_threshold_;
@@ -271,8 +181,6 @@ class CONTENT_EXPORT ResourceScheduler : public base::NonThreadSafe {
size_t in_flight_non_delayable_threshold_;
size_t max_num_delayable_while_layout_blocking_;
size_t max_num_delayable_requests_;
- // This is a repeating timer to initiate requests on COALESCED Clients.
- scoped_ptr<base::Timer> coalescing_timer_;
RequestSet unowned_requests_;
DISALLOW_COPY_AND_ASSIGN(ResourceScheduler);
diff --git a/chromium/content/browser/loader/resource_scheduler_unittest.cc b/chromium/content/browser/loader/resource_scheduler_unittest.cc
index 1399b52dde3..59b6d0055b9 100644
--- a/chromium/content/browser/loader/resource_scheduler_unittest.cc
+++ b/chromium/content/browser/loader/resource_scheduler_unittest.cc
@@ -46,13 +46,11 @@ const int kChildId2 = 43;
const int kRouteId2 = 67;
const int kBackgroundChildId = 35;
const int kBackgroundRouteId = 43;
-const int kBackgroundChildId2 = 54;
-const int kBackgroundRouteId2 = 82;
class TestRequest : public ResourceController {
public:
- TestRequest(scoped_ptr<net::URLRequest> url_request,
- scoped_ptr<ResourceThrottle> throttle,
+ TestRequest(std::unique_ptr<net::URLRequest> url_request,
+ std::unique_ptr<ResourceThrottle> throttle,
ResourceScheduler* scheduler)
: started_(false),
url_request_(std::move(url_request)),
@@ -94,19 +92,19 @@ class TestRequest : public ResourceController {
private:
bool started_;
- scoped_ptr<net::URLRequest> url_request_;
- scoped_ptr<ResourceThrottle> throttle_;
+ std::unique_ptr<net::URLRequest> url_request_;
+ std::unique_ptr<ResourceThrottle> throttle_;
ResourceScheduler* scheduler_;
};
class CancelingTestRequest : public TestRequest {
public:
- CancelingTestRequest(scoped_ptr<net::URLRequest> url_request,
- scoped_ptr<ResourceThrottle> throttle,
+ CancelingTestRequest(std::unique_ptr<net::URLRequest> url_request,
+ std::unique_ptr<ResourceThrottle> throttle,
ResourceScheduler* scheduler)
: TestRequest(std::move(url_request), std::move(throttle), scheduler) {}
- void set_request_to_cancel(scoped_ptr<TestRequest> request_to_cancel) {
+ void set_request_to_cancel(std::unique_ptr<TestRequest> request_to_cancel) {
request_to_cancel_ = std::move(request_to_cancel);
}
@@ -116,7 +114,7 @@ class CancelingTestRequest : public TestRequest {
request_to_cancel_.reset();
}
- scoped_ptr<TestRequest> request_to_cancel_;
+ std::unique_ptr<TestRequest> request_to_cancel_;
};
class FakeResourceContext : public ResourceContext {
@@ -148,16 +146,9 @@ class ResourceSchedulerTest : public testing::Test {
// mock_timer_.
scheduler_.reset(new ResourceScheduler());
- mock_timer_ = new base::MockTimer(true, true);
- scheduler_->set_timer_for_testing(scoped_ptr<base::Timer>(mock_timer_));
-
- // TODO(aiolos): Remove when throttling and coalescing have both landed.
- scheduler_->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
-
- scheduler_->OnClientCreated(kChildId, kRouteId, true, false);
+ scheduler_->OnClientCreated(kChildId, kRouteId);
scheduler_->OnClientCreated(
- kBackgroundChildId, kBackgroundRouteId, false, false);
+ kBackgroundChildId, kBackgroundRouteId);
}
void CleanupScheduler() {
@@ -171,23 +162,22 @@ class ResourceSchedulerTest : public testing::Test {
// as the argument to kForceFieldTrials.
bool InitializeFieldTrials(const std::string& force_field_trial_argument) {
return base::FieldTrialList::CreateTrialsFromString(
- force_field_trial_argument,
- base::FieldTrialList::DONT_ACTIVATE_TRIALS,
- std::set<std::string>());
+ force_field_trial_argument, std::set<std::string>());
}
- scoped_ptr<net::URLRequest> NewURLRequestWithChildAndRoute(
+ std::unique_ptr<net::URLRequest> NewURLRequestWithChildAndRoute(
const char* url,
net::RequestPriority priority,
int child_id,
int route_id) {
- scoped_ptr<net::URLRequest> url_request(
+ std::unique_ptr<net::URLRequest> url_request(
context_.CreateRequest(GURL(url), priority, NULL));
return url_request;
}
- scoped_ptr<net::URLRequest> NewURLRequest(const char* url,
- net::RequestPriority priority) {
+ std::unique_ptr<net::URLRequest> NewURLRequest(
+ const char* url,
+ net::RequestPriority priority) {
return NewURLRequestWithChildAndRoute(url, priority, kChildId, kRouteId);
}
@@ -236,9 +226,9 @@ class ResourceSchedulerTest : public testing::Test {
int child_id,
int route_id,
bool is_async) {
- scoped_ptr<net::URLRequest> url_request(
+ std::unique_ptr<net::URLRequest> url_request(
NewURLRequestWithChildAndRoute(url, priority, child_id, route_id));
- scoped_ptr<ResourceThrottle> throttle(scheduler_->ScheduleRequest(
+ std::unique_ptr<ResourceThrottle> throttle(scheduler_->ScheduleRequest(
child_id, route_id, is_async, url_request.get()));
TestRequest* request = new TestRequest(std::move(url_request),
std::move(throttle), scheduler());
@@ -265,7 +255,7 @@ class ResourceSchedulerTest : public testing::Test {
BrowserThreadImpl ui_thread_;
BrowserThreadImpl io_thread_;
ResourceDispatcherHostImpl rdh_;
- scoped_ptr<ResourceScheduler> scheduler_;
+ std::unique_ptr<ResourceScheduler> scheduler_;
base::FieldTrialList field_trial_list_;
base::MockTimer* mock_timer_;
net::HttpServerPropertiesImpl http_server_properties_;
@@ -273,14 +263,16 @@ class ResourceSchedulerTest : public testing::Test {
};
TEST_F(ResourceSchedulerTest, OneIsolatedLowRequest) {
- scoped_ptr<TestRequest> request(NewRequest("http://host/1", net::LOWEST));
+ std::unique_ptr<TestRequest> request(
+ NewRequest("http://host/1", net::LOWEST));
EXPECT_TRUE(request->started());
}
TEST_F(ResourceSchedulerTest, OneLowLoadsUntilIdle) {
- scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
- scoped_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
EXPECT_TRUE(high->started());
EXPECT_TRUE(low->started());
EXPECT_FALSE(low2->started());
@@ -291,9 +283,10 @@ TEST_F(ResourceSchedulerTest, OneLowLoadsUntilIdle) {
}
TEST_F(ResourceSchedulerTest, OneLowLoadsUntilBodyInserted) {
- scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
- scoped_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
EXPECT_TRUE(high->started());
EXPECT_TRUE(low->started());
EXPECT_FALSE(low2->started());
@@ -310,9 +303,10 @@ TEST_F(ResourceSchedulerTest, OneLowLoadsUntilBodyInserted) {
}
TEST_F(ResourceSchedulerTest, OneLowLoadsUntilCriticalComplete) {
- scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
- scoped_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
EXPECT_TRUE(high->started());
EXPECT_TRUE(low->started());
EXPECT_FALSE(low2->started());
@@ -327,9 +321,10 @@ TEST_F(ResourceSchedulerTest, OneLowLoadsUntilCriticalComplete) {
}
TEST_F(ResourceSchedulerTest, LowDoesNotBlockCriticalComplete) {
- scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOW));
- scoped_ptr<TestRequest> lowest(NewRequest("http://host/lowest", net::LOWEST));
- scoped_ptr<TestRequest> lowest2(
+ std::unique_ptr<TestRequest> low(NewRequest("http://host/low", net::LOW));
+ std::unique_ptr<TestRequest> lowest(
+ NewRequest("http://host/lowest", net::LOWEST));
+ std::unique_ptr<TestRequest> lowest2(
NewRequest("http://host/lowest", net::LOWEST));
EXPECT_TRUE(low->started());
EXPECT_TRUE(lowest->started());
@@ -343,11 +338,12 @@ TEST_F(ResourceSchedulerTest, LowDoesNotBlockCriticalComplete) {
TEST_F(ResourceSchedulerTest, OneLowLoadsUntilBodyInsertedExceptSpdy) {
http_server_properties_.SetSupportsSpdy(
net::HostPortPair("spdyhost", 443), true);
- scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low_spdy(
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> low_spdy(
NewRequest("https://spdyhost/low", net::LOWEST));
- scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
- scoped_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
EXPECT_TRUE(high->started());
EXPECT_TRUE(low_spdy->started());
EXPECT_TRUE(low->started());
@@ -362,9 +358,10 @@ TEST_F(ResourceSchedulerTest, OneLowLoadsUntilBodyInsertedExceptSpdy) {
TEST_F(ResourceSchedulerTest, NavigationResetsState) {
scheduler()->OnWillInsertBody(kChildId, kRouteId);
scheduler()->OnNavigate(kChildId, kRouteId);
- scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
- scoped_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
EXPECT_TRUE(high->started());
EXPECT_TRUE(low->started());
EXPECT_FALSE(low2->started());
@@ -372,16 +369,18 @@ TEST_F(ResourceSchedulerTest, NavigationResetsState) {
TEST_F(ResourceSchedulerTest, BackgroundRequestStartsImmediately) {
const int route_id = 0; // Indicates a background request.
- scoped_ptr<TestRequest> request(NewRequestWithRoute("http://host/1",
- net::LOWEST, route_id));
+ std::unique_ptr<TestRequest> request(
+ NewRequestWithRoute("http://host/1", net::LOWEST, route_id));
EXPECT_TRUE(request->started());
}
TEST_F(ResourceSchedulerTest, StartMultipleLowRequestsWhenIdle) {
- scoped_ptr<TestRequest> high1(NewRequest("http://host/high1", net::HIGHEST));
- scoped_ptr<TestRequest> high2(NewRequest("http://host/high2", net::HIGHEST));
- scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
- scoped_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> high1(
+ NewRequest("http://host/high1", net::HIGHEST));
+ std::unique_ptr<TestRequest> high2(
+ NewRequest("http://host/high2", net::HIGHEST));
+ std::unique_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
EXPECT_TRUE(high1->started());
EXPECT_TRUE(high2->started());
EXPECT_TRUE(low->started());
@@ -397,20 +396,24 @@ TEST_F(ResourceSchedulerTest, StartMultipleLowRequestsWhenIdle) {
}
TEST_F(ResourceSchedulerTest, CancelOtherRequestsWhileResuming) {
- scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low1(NewRequest("http://host/low1", net::LOWEST));
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> low1(
+ NewRequest("http://host/low1", net::LOWEST));
- scoped_ptr<net::URLRequest> url_request(
+ std::unique_ptr<net::URLRequest> url_request(
NewURLRequest("http://host/low2", net::LOWEST));
- scoped_ptr<ResourceThrottle> throttle(scheduler()->ScheduleRequest(
+ std::unique_ptr<ResourceThrottle> throttle(scheduler()->ScheduleRequest(
kChildId, kRouteId, true, url_request.get()));
- scoped_ptr<CancelingTestRequest> low2(new CancelingTestRequest(
+ std::unique_ptr<CancelingTestRequest> low2(new CancelingTestRequest(
std::move(url_request), std::move(throttle), scheduler()));
low2->Start();
- scoped_ptr<TestRequest> low3(NewRequest("http://host/low3", net::LOWEST));
+ std::unique_ptr<TestRequest> low3(
+ NewRequest("http://host/low3", net::LOWEST));
low2->set_request_to_cancel(std::move(low3));
- scoped_ptr<TestRequest> low4(NewRequest("http://host/low4", net::LOWEST));
+ std::unique_ptr<TestRequest> low4(
+ NewRequest("http://host/low4", net::LOWEST));
EXPECT_TRUE(high->started());
EXPECT_FALSE(low2->started());
@@ -427,7 +430,8 @@ TEST_F(ResourceSchedulerTest, LimitedNumberOfDelayableRequestsInFlight) {
scheduler()->OnWillInsertBody(kChildId, kRouteId);
// Throw in one high priority request to make sure that's not a factor.
- scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
EXPECT_TRUE(high->started());
const int kMaxNumDelayableRequestsPerClient = 10; // Should match the .cc.
@@ -440,10 +444,10 @@ TEST_F(ResourceSchedulerTest, LimitedNumberOfDelayableRequestsInFlight) {
EXPECT_TRUE(lows_singlehost[i]->started());
}
- scoped_ptr<TestRequest> second_last_singlehost(NewRequest("http://host/last",
- net::LOWEST));
- scoped_ptr<TestRequest> last_singlehost(NewRequest("http://host/s_last",
- net::LOWEST));
+ std::unique_ptr<TestRequest> second_last_singlehost(
+ NewRequest("http://host/last", net::LOWEST));
+ std::unique_ptr<TestRequest> last_singlehost(
+ NewRequest("http://host/s_last", net::LOWEST));
EXPECT_FALSE(second_last_singlehost->started());
@@ -468,17 +472,19 @@ TEST_F(ResourceSchedulerTest, LimitedNumberOfDelayableRequestsInFlight) {
EXPECT_TRUE(lows_different_host[i]->started());
}
- scoped_ptr<TestRequest> last_different_host(NewRequest("http://host_new/last",
- net::LOWEST));
+ std::unique_ptr<TestRequest> last_different_host(
+ NewRequest("http://host_new/last", net::LOWEST));
EXPECT_FALSE(last_different_host->started());
}
TEST_F(ResourceSchedulerTest, RaisePriorityAndStart) {
// Dummies to enforce scheduling.
- scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(NewRequest("http://host/req", net::LOWEST));
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> low(NewRequest("http://host/req", net::LOWEST));
- scoped_ptr<TestRequest> request(NewRequest("http://host/req", net::LOWEST));
+ std::unique_ptr<TestRequest> request(
+ NewRequest("http://host/req", net::LOWEST));
EXPECT_FALSE(request->started());
ChangeRequestPriority(request.get(), net::HIGHEST);
@@ -488,11 +494,13 @@ TEST_F(ResourceSchedulerTest, RaisePriorityAndStart) {
TEST_F(ResourceSchedulerTest, RaisePriorityInQueue) {
// Dummies to enforce scheduling.
- scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
- scoped_ptr<TestRequest> request(NewRequest("http://host/req", net::IDLE));
- scoped_ptr<TestRequest> idle(NewRequest("http://host/idle", net::IDLE));
+ std::unique_ptr<TestRequest> request(
+ NewRequest("http://host/req", net::IDLE));
+ std::unique_ptr<TestRequest> idle(NewRequest("http://host/idle", net::IDLE));
EXPECT_FALSE(request->started());
EXPECT_FALSE(idle->started());
@@ -518,11 +526,13 @@ TEST_F(ResourceSchedulerTest, RaisePriorityInQueue) {
TEST_F(ResourceSchedulerTest, LowerPriority) {
// Dummies to enforce scheduling.
- scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
- scoped_ptr<TestRequest> request(NewRequest("http://host/req", net::LOWEST));
- scoped_ptr<TestRequest> idle(NewRequest("http://host/idle", net::IDLE));
+ std::unique_ptr<TestRequest> request(
+ NewRequest("http://host/req", net::LOWEST));
+ std::unique_ptr<TestRequest> idle(NewRequest("http://host/idle", net::IDLE));
EXPECT_FALSE(request->started());
EXPECT_FALSE(idle->started());
@@ -551,11 +561,13 @@ TEST_F(ResourceSchedulerTest, LowerPriority) {
TEST_F(ResourceSchedulerTest, ReprioritizedRequestGoesToBackOfQueue) {
// Dummies to enforce scheduling.
- scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
- scoped_ptr<TestRequest> request(NewRequest("http://host/req", net::LOWEST));
- scoped_ptr<TestRequest> idle(NewRequest("http://host/idle", net::IDLE));
+ std::unique_ptr<TestRequest> request(
+ NewRequest("http://host/req", net::LOWEST));
+ std::unique_ptr<TestRequest> idle(NewRequest("http://host/idle", net::IDLE));
EXPECT_FALSE(request->started());
EXPECT_FALSE(idle->started());
@@ -584,8 +596,9 @@ TEST_F(ResourceSchedulerTest, ReprioritizedRequestGoesToBackOfQueue) {
TEST_F(ResourceSchedulerTest, HigherIntraPriorityGoesToFrontOfQueue) {
// Dummies to enforce scheduling.
- scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
const int kMaxNumDelayableRequestsPerClient = 10; // Should match the .cc.
ScopedVector<TestRequest> lows;
@@ -594,7 +607,8 @@ TEST_F(ResourceSchedulerTest, HigherIntraPriorityGoesToFrontOfQueue) {
lows.push_back(NewRequest(url.c_str(), net::IDLE));
}
- scoped_ptr<TestRequest> request(NewRequest("http://host/req", net::IDLE));
+ std::unique_ptr<TestRequest> request(
+ NewRequest("http://host/req", net::IDLE));
EXPECT_FALSE(request->started());
ChangeRequestPriority(request.get(), net::IDLE, 1);
@@ -609,58 +623,30 @@ TEST_F(ResourceSchedulerTest, HigherIntraPriorityGoesToFrontOfQueue) {
TEST_F(ResourceSchedulerTest, NonHTTPSchedulesImmediately) {
// Dummies to enforce scheduling.
- scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
- scoped_ptr<TestRequest> request(
+ std::unique_ptr<TestRequest> request(
NewRequest("chrome-extension://req", net::LOWEST));
EXPECT_TRUE(request->started());
}
-TEST_F(ResourceSchedulerTest, ActiveLoadingSyncSchedulesImmediately) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
- // Dummies to enforce scheduling.
- scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
-
- scoped_ptr<TestRequest> request(
- NewSyncRequest("http://host/req", net::LOWEST));
- EXPECT_TRUE(request->started());
-}
-
-TEST_F(ResourceSchedulerTest, UnthrottledSyncSchedulesImmediately) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- // Dummies to enforce scheduling.
- scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
-
- scoped_ptr<TestRequest> request(
- NewBackgroundSyncRequest("http://host/req", net::LOWEST));
- EXPECT_TRUE(request->started());
-}
-
TEST_F(ResourceSchedulerTest, SpdyProxySchedulesImmediately) {
- scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
- scoped_ptr<TestRequest> request(NewRequest("http://host/req", net::IDLE));
+ std::unique_ptr<TestRequest> request(
+ NewRequest("http://host/req", net::IDLE));
EXPECT_FALSE(request->started());
scheduler()->OnReceivedSpdyProxiedHttpResponse(kChildId, kRouteId);
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(request->started());
- scoped_ptr<TestRequest> after(NewRequest("http://host/after", net::IDLE));
+ std::unique_ptr<TestRequest> after(
+ NewRequest("http://host/after", net::IDLE));
EXPECT_TRUE(after->started());
}
@@ -668,7 +654,7 @@ TEST_F(ResourceSchedulerTest, NewSpdyHostInDelayableRequests) {
scheduler()->OnWillInsertBody(kChildId, kRouteId);
const int kMaxNumDelayableRequestsPerClient = 10; // Should match the .cc.
- scoped_ptr<TestRequest> low1_spdy(
+ std::unique_ptr<TestRequest> low1_spdy(
NewRequest("http://spdyhost1:8080/low", net::LOWEST));
// Cancel a request after we learn the server supports SPDY.
ScopedVector<TestRequest> lows;
@@ -676,7 +662,7 @@ TEST_F(ResourceSchedulerTest, NewSpdyHostInDelayableRequests) {
string url = "http://host" + base::IntToString(i) + "/low";
lows.push_back(NewRequest(url.c_str(), net::LOWEST));
}
- scoped_ptr<TestRequest> low1(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> low1(NewRequest("http://host/low", net::LOWEST));
EXPECT_FALSE(low1->started());
http_server_properties_.SetSupportsSpdy(
net::HostPortPair("spdyhost1", 8080), true);
@@ -686,7 +672,7 @@ TEST_F(ResourceSchedulerTest, NewSpdyHostInDelayableRequests) {
low1.reset();
base::RunLoop().RunUntilIdle();
- scoped_ptr<TestRequest> low2_spdy(
+ std::unique_ptr<TestRequest> low2_spdy(
NewRequest("http://spdyhost2:8080/low", net::IDLE));
// Reprioritize a request after we learn the server supports SPDY.
EXPECT_TRUE(low2_spdy->started());
@@ -694,1565 +680,10 @@ TEST_F(ResourceSchedulerTest, NewSpdyHostInDelayableRequests) {
net::HostPortPair("spdyhost2", 8080), true);
ChangeRequestPriority(low2_spdy.get(), net::LOWEST);
base::RunLoop().RunUntilIdle();
- scoped_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
EXPECT_TRUE(low2->started());
}
-TEST_F(ResourceSchedulerTest, ThrottledClientCreation) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- EXPECT_TRUE(scheduler()->should_throttle());
- scheduler()->OnClientCreated(
- kBackgroundChildId2, kBackgroundRouteId2, false, false);
-
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- scheduler()->OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
-}
-
-TEST_F(ResourceSchedulerTest, ActiveClientThrottleUpdateOnLoadingChange) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, false);
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-}
-
-TEST_F(ResourceSchedulerTest, CoalesceBackgroundClientOnLoadCompletion) {
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- true /* should_coalesce */);
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId, kBackgroundRouteId, true);
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- EXPECT_EQ(ResourceScheduler::COALESCED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
-}
-
-TEST_F(ResourceSchedulerTest, UnthrottleBackgroundClientOnLoadingStarted) {
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- true /* should_coalesce */);
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId, kBackgroundRouteId, true);
- EXPECT_EQ(ResourceScheduler::COALESCED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
-
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId, kBackgroundRouteId, false);
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
-}
-
-TEST_F(ResourceSchedulerTest, OneRequestPerThrottledClient) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- scoped_ptr<TestRequest> high(
- NewBackgroundRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> request(
- NewBackgroundRequest("http://host/req", net::IDLE));
-
- EXPECT_TRUE(high->started());
- EXPECT_FALSE(request->started());
-}
-
-TEST_F(ResourceSchedulerTest, UnthrottleNewlyVisibleClient) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- scoped_ptr<TestRequest> high(
- NewBackgroundRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> request(
- NewBackgroundRequest("http://host/req", net::IDLE));
- EXPECT_FALSE(request->started());
-
- scheduler()->OnVisibilityChanged(
- kBackgroundChildId, kBackgroundRouteId, true);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_TRUE(request->started());
-}
-
-TEST_F(ResourceSchedulerTest, UnthrottleNewlyAudibleClient) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- scoped_ptr<TestRequest> high(
- NewBackgroundRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> request(
- NewBackgroundRequest("http://host/req", net::IDLE));
- EXPECT_FALSE(request->started());
-
- scheduler()->OnAudibilityChanged(
- kBackgroundChildId, kBackgroundRouteId, true);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_TRUE(request->started());
-}
-
-TEST_F(ResourceSchedulerTest, VisibleClientStillUnthrottledOnAudabilityChange) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
-
- scheduler()->OnAudibilityChanged(kChildId, kRouteId, true);
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
-
- scheduler()->OnAudibilityChanged(kChildId, kRouteId, false);
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
-}
-
-TEST_F(ResourceSchedulerTest, AudibleClientStillUnthrottledOnVisabilityChange) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- scheduler()->OnVisibilityChanged(kChildId, kRouteId, false);
- scheduler()->OnAudibilityChanged(kChildId, kRouteId, true);
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
-
- scheduler()->OnVisibilityChanged(kChildId, kRouteId, true);
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
-
- scheduler()->OnVisibilityChanged(kChildId, kRouteId, false);
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
-}
-
-TEST_F(ResourceSchedulerTest, ThrottledClientStartsNextHighestPriorityRequest) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- scoped_ptr<TestRequest> request(
- NewBackgroundRequest("http://host/req", net::IDLE));
- // Lower priority request started first to test request prioritizaton.
- scoped_ptr<TestRequest> low(
- NewBackgroundRequest("http://host/high", net::IDLE));
- scoped_ptr<TestRequest> high(
- NewBackgroundRequest("http://host/high", net::HIGHEST));
-
- EXPECT_FALSE(low->started());
- EXPECT_FALSE(high->started());
-
- request->Cancel();
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(high->started());
- EXPECT_FALSE(low->started());
-}
-
-TEST_F(ResourceSchedulerTest, ThrottledSpdyProxySchedulesImmediately) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- scoped_ptr<TestRequest> high(
- NewBackgroundRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> request(
- NewBackgroundRequest("http://host/req", net::IDLE));
-
- EXPECT_FALSE(request->started());
-
- scheduler()->OnReceivedSpdyProxiedHttpResponse(kBackgroundChildId,
- kBackgroundRouteId);
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(request->started());
-
- scoped_ptr<TestRequest> after(
- NewBackgroundRequest("http://host/after", net::IDLE));
- EXPECT_TRUE(after->started());
-}
-
-TEST_F(ResourceSchedulerTest, CoalescedClientIssuesNoRequests) {
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- true /* should_coalesce */);
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId, kBackgroundRouteId, true);
- EXPECT_EQ(ResourceScheduler::COALESCED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- scoped_ptr<TestRequest> high(
- NewBackgroundRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> request(
- NewBackgroundRequest("http://host/req", net::IDLE));
-
- EXPECT_FALSE(high->started());
- EXPECT_FALSE(request->started());
-
- scheduler()->OnReceivedSpdyProxiedHttpResponse(kBackgroundChildId,
- kBackgroundRouteId);
- base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(high->started());
-
- scoped_ptr<TestRequest> after(
- NewBackgroundRequest("http://host/after", net::HIGHEST));
- EXPECT_FALSE(after->started());
-}
-
-TEST_F(ResourceSchedulerTest, CoalescedSpdyProxyWaits) {
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- true /* should_coalesce */);
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId, kBackgroundRouteId, true);
- EXPECT_EQ(ResourceScheduler::COALESCED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- scoped_ptr<TestRequest> high(
- NewBackgroundRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> request(
- NewBackgroundRequest("http://host/req", net::IDLE));
-
- EXPECT_FALSE(request->started());
-
- scheduler()->OnReceivedSpdyProxiedHttpResponse(kBackgroundChildId,
- kBackgroundRouteId);
- base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(request->started());
-
- scoped_ptr<TestRequest> after(
- NewBackgroundRequest("http://host/after", net::IDLE));
- EXPECT_FALSE(after->started());
-}
-
-TEST_F(ResourceSchedulerTest, ThrottledNonHTTPSchedulesImmediately) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- // Dummies to enforce scheduling.
- scoped_ptr<TestRequest> high(
- NewBackgroundRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(
- NewBackgroundRequest("http://host/low", net::LOWEST));
-
- scoped_ptr<TestRequest> request(
- NewBackgroundRequest("chrome-extension://req", net::LOWEST));
- EXPECT_TRUE(request->started());
- EXPECT_FALSE(low->started());
-}
-
-TEST_F(ResourceSchedulerTest, CoalescedNonHTTPSchedulesImmediately) {
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- true /* should_coalesce */);
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId, kBackgroundRouteId, true);
- EXPECT_EQ(ResourceScheduler::COALESCED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- // Dummies to enforce scheduling.
- scoped_ptr<TestRequest> high(
- NewBackgroundRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(
- NewBackgroundRequest("http://host/low", net::LOWEST));
-
- scoped_ptr<TestRequest> request(
- NewBackgroundRequest("chrome-extension://req", net::LOWEST));
- EXPECT_TRUE(request->started());
- EXPECT_FALSE(low->started());
-}
-
-TEST_F(ResourceSchedulerTest, ThrottledSyncSchedulesImmediately) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- // Dummies to enforce scheduling.
- scoped_ptr<TestRequest> high(
- NewBackgroundRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(
- NewBackgroundRequest("http://host/low", net::LOWEST));
-
- scoped_ptr<TestRequest> request(
- NewBackgroundSyncRequest("http://host/req", net::LOWEST));
- EXPECT_TRUE(request->started());
- EXPECT_FALSE(low->started());
-}
-
-TEST_F(ResourceSchedulerTest, CoalescedSyncSchedulesImmediately) {
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- true /* should_coalesce */);
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId, kBackgroundRouteId, true);
- EXPECT_EQ(ResourceScheduler::COALESCED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- // Dummies to enforce scheduling.
- scoped_ptr<TestRequest> high(
- NewBackgroundRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(
- NewBackgroundRequest("http://host/low", net::LOWEST));
-
- scoped_ptr<TestRequest> request(
- NewBackgroundSyncRequest("http://host/req", net::LOWEST));
- EXPECT_TRUE(request->started());
- EXPECT_FALSE(low->started());
- EXPECT_FALSE(high->started());
-}
-
-TEST_F(ResourceSchedulerTest, AllBackgroundClientsUnthrottle) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
- EXPECT_FALSE(scheduler()->active_clients_loaded());
-
- scheduler()->OnVisibilityChanged(kChildId, kRouteId, false);
- EXPECT_TRUE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
-
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
-
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, false);
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
-
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId, kBackgroundRouteId, true);
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
-}
-
-TEST_F(ResourceSchedulerTest,
- UnloadedClientVisibilityChangedCorrectlyUnthrottles) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- scheduler()->OnClientCreated(kChildId2, kRouteId2, false, false);
- scheduler()->OnClientCreated(
- kBackgroundChildId2, kBackgroundRouteId2, false, false);
- scheduler()->OnLoadingStateChanged(kChildId2, kRouteId2, true);
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId2, kBackgroundRouteId2, true);
-
- // 1 visible, 3 hidden
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 2 visible, 2 hidden
- scheduler()->OnVisibilityChanged(kChildId2, kRouteId2, true);
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 1 visible, 3 hidden
- scheduler()->OnVisibilityChanged(kChildId2, kRouteId2, false);
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- scheduler()->OnClientDeleted(kChildId2, kRouteId2);
- scheduler()->OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
-}
-
-TEST_F(ResourceSchedulerTest,
- UnloadedClientAudibilityChangedCorrectlyUnthrottles) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- scheduler()->OnClientCreated(kChildId2, kRouteId2, false, false);
- scheduler()->OnClientCreated(
- kBackgroundChildId2, kBackgroundRouteId2, false, false);
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId2, kBackgroundRouteId2, true);
- scheduler()->OnVisibilityChanged(kChildId, kRouteId, false);
- scheduler()->OnAudibilityChanged(kChildId, kRouteId, true);
-
- // 1 audible, 3 hidden
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 2 audible, 2 hidden
- scheduler()->OnAudibilityChanged(kChildId2, kRouteId2, true);
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 1 audible, 3 hidden
- scheduler()->OnAudibilityChanged(kChildId2, kRouteId2, false);
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- scheduler()->OnClientDeleted(kChildId2, kRouteId2);
- scheduler()->OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
-}
-
-TEST_F(ResourceSchedulerTest,
- LoadedClientVisibilityChangedCorrectlyUnthrottles) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- scheduler()->OnClientCreated(kChildId2, kRouteId2, false, false);
- scheduler()->OnClientCreated(
- kBackgroundChildId2, kBackgroundRouteId2, false, false);
- scheduler()->OnLoadingStateChanged(kChildId2, kRouteId2, true);
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId2, kBackgroundRouteId2, true);
- // 1 visible, 3 hidden
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 2 visible, 2 hidden
- scheduler()->OnVisibilityChanged(kChildId2, kRouteId2, true);
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 1 visible, 3 hidden
- scheduler()->OnVisibilityChanged(kChildId2, kRouteId2, false);
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- scheduler()->OnClientDeleted(kChildId2, kRouteId2);
- scheduler()->OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
-}
-
-TEST_F(ResourceSchedulerTest,
- LoadedClientAudibilityChangedCorrectlyUnthrottles) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- scheduler()->OnClientCreated(kChildId2, kRouteId2, false, false);
- scheduler()->OnClientCreated(
- kBackgroundChildId2, kBackgroundRouteId2, false, false);
- scheduler()->OnLoadingStateChanged(kChildId2, kRouteId2, true);
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId2, kBackgroundRouteId2, true);
- scheduler()->OnVisibilityChanged(kChildId, kRouteId, false);
- scheduler()->OnAudibilityChanged(kChildId, kRouteId, true);
- // 1 audible, 3 hidden
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 2 audible, 2 hidden
- scheduler()->OnAudibilityChanged(kChildId2, kRouteId2, true);
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 1 audible, 3 hidden
- scheduler()->OnAudibilityChanged(kChildId2, kRouteId2, false);
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- scheduler()->OnClientDeleted(kChildId2, kRouteId2);
- scheduler()->OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
-}
-
-TEST_F(ResourceSchedulerTest, UnloadedClientBecomesHiddenCorrectlyUnthrottles) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- scheduler()->OnClientCreated(kChildId2, kRouteId2, true, false);
- scheduler()->OnClientCreated(
- kBackgroundChildId2, kBackgroundRouteId2, false, false);
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId2, kBackgroundRouteId2, true);
-
- // 2 visible, 2 hidden
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 1 visible, 3 hidden
- scheduler()->OnVisibilityChanged(kChildId2, kRouteId2, false);
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 0 visible, 4 hidden
- scheduler()->OnVisibilityChanged(kChildId, kRouteId, false);
- EXPECT_TRUE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 1 visible, 3 hidden
- scheduler()->OnVisibilityChanged(kChildId, kRouteId, true);
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- scheduler()->OnClientDeleted(kChildId2, kRouteId2);
- scheduler()->OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
-}
-
-TEST_F(ResourceSchedulerTest, UnloadedClientBecomesSilentCorrectlyUnthrottles) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- scheduler()->OnClientCreated(kChildId2, kRouteId2, false, true);
- scheduler()->OnClientCreated(
- kBackgroundChildId2, kBackgroundRouteId2, false, false);
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId2, kBackgroundRouteId2, true);
- scheduler()->OnAudibilityChanged(kChildId, kRouteId, true);
- scheduler()->OnVisibilityChanged(kChildId, kRouteId, false);
- // 2 audible, 2 hidden
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 1 audible, 3 hidden
- scheduler()->OnAudibilityChanged(kChildId2, kRouteId2, false);
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 0 audible, 4 hidden
- scheduler()->OnAudibilityChanged(kChildId, kRouteId, false);
- EXPECT_TRUE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 1 audible, 3 hidden
- scheduler()->OnAudibilityChanged(kChildId, kRouteId, true);
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- scheduler()->OnClientDeleted(kChildId2, kRouteId2);
- scheduler()->OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
-}
-
-TEST_F(ResourceSchedulerTest, LoadedClientBecomesHiddenCorrectlyThrottles) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- scheduler()->OnClientCreated(kChildId2, kRouteId2, true, false);
- scheduler()->OnClientCreated(
- kBackgroundChildId2, kBackgroundRouteId2, false, false);
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId2, kBackgroundRouteId2, true);
- scheduler()->OnLoadingStateChanged(kChildId2, kRouteId2, true);
- // 2 visible, 2 hidden
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 1 visible, 3 hidden
- scheduler()->OnVisibilityChanged(kChildId2, kRouteId2, false);
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 0 visible, 4 hidden
- scheduler()->OnVisibilityChanged(kChildId, kRouteId, false);
- EXPECT_TRUE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 1 visible, 3 hidden
- scheduler()->OnVisibilityChanged(kChildId2, kRouteId2, true);
- EXPECT_TRUE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- scheduler()->OnClientDeleted(kChildId2, kRouteId2);
- scheduler()->OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
-}
-
-TEST_F(ResourceSchedulerTest, LoadedClientBecomesSilentCorrectlyThrottles) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- scheduler()->OnClientCreated(kChildId2, kRouteId2, false, true);
- scheduler()->OnClientCreated(
- kBackgroundChildId2, kBackgroundRouteId2, false, false);
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId2, kBackgroundRouteId2, true);
- scheduler()->OnLoadingStateChanged(kChildId2, kRouteId2, true);
- scheduler()->OnVisibilityChanged(kChildId, kRouteId, false);
- scheduler()->OnAudibilityChanged(kChildId, kRouteId, true);
- // 2 audible, 2 hidden
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 1 audible, 3 hidden
- scheduler()->OnAudibilityChanged(kChildId2, kRouteId2, false);
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 0 audible, 4 hidden
- scheduler()->OnAudibilityChanged(kChildId, kRouteId, false);
- EXPECT_TRUE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 1 audible, 3 hidden
- scheduler()->OnAudibilityChanged(kChildId2, kRouteId2, true);
- EXPECT_TRUE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- scheduler()->OnClientDeleted(kChildId2, kRouteId2);
- scheduler()->OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
-}
-
-TEST_F(ResourceSchedulerTest, HiddenLoadedChangesCorrectlyStayThrottled) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- scheduler()->OnClientCreated(kChildId2, kRouteId2, true, false);
- scheduler()->OnClientCreated(
- kBackgroundChildId2, kBackgroundRouteId2, false, false);
-
- // 1 visible and 2 hidden loading, 1 visible loaded
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 1 visible and 1 hidden loading, 1 visible and 1 hidden loaded
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId2, kBackgroundRouteId2, true);
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 1 visible loading, 1 visible and 2 hidden loaded
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId, kBackgroundRouteId, true);
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 1 visible and 1 hidden loading, 1 visible and 1 hidden loaded
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId2, kBackgroundRouteId2, true);
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- scheduler()->OnClientDeleted(kChildId2, kRouteId2);
- scheduler()->OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
-}
-
-TEST_F(ResourceSchedulerTest, PartialVisibleClientLoadedDoesNotUnthrottle) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- scheduler()->OnClientCreated(kChildId2, kRouteId2, true, false);
- scheduler()->OnClientCreated(
- kBackgroundChildId2, kBackgroundRouteId2, false, false);
-
- // 2 visible loading, 1 hidden loading, 1 hidden loaded
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId2, kBackgroundRouteId2, true);
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 1 visible and 1 hidden loaded, 1 visible and 1 hidden loading
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 2 visible loading, 1 hidden loading, 1 hidden loaded
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, false);
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- scheduler()->OnClientDeleted(kChildId2, kRouteId2);
- scheduler()->OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
-}
-
-TEST_F(ResourceSchedulerTest, FullVisibleLoadedCorrectlyUnthrottle) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- scheduler()->OnClientCreated(kChildId2, kRouteId2, true, false);
- scheduler()->OnClientCreated(
- kBackgroundChildId2, kBackgroundRouteId2, false, false);
-
- // 1 visible and 1 hidden loaded, 1 visible and 1 hidden loading
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId2, kBackgroundRouteId2, true);
- scheduler()->OnLoadingStateChanged(kChildId2, kRouteId2, true);
- base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- scoped_ptr<TestRequest> high(
- NewBackgroundRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(
- NewBackgroundRequest("http://host/low", net::LOWEST));
-
- EXPECT_TRUE(high->started());
- EXPECT_FALSE(low->started());
-
- // 2 visible loaded, 1 hidden loading, 1 hidden loaded
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
- // kBackgroundClientId unthrottling should unthrottle it's request.
- EXPECT_TRUE(low->started());
-
- // 1 visible and 1 hidden loaded, 1 visible and 1 hidden loading
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, false);
- base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- scheduler()->OnClientDeleted(kChildId2, kRouteId2);
- scheduler()->OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
-}
-
-TEST_F(ResourceSchedulerTest,
- ActiveAndLoadingClientDeletedCorrectlyUnthrottle) {
- // TODO(aiolos): remove when throttling and coalescing have both landed
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- false /* should_coalesce */);
- scheduler()->OnClientCreated(kChildId2, kRouteId2, true, false);
- scheduler()->OnClientCreated(
- kBackgroundChildId2, kBackgroundRouteId2, false, false);
-
- // 1 visible and 1 hidden loaded, 1 visible and 1 hidden loading
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId2, kBackgroundRouteId2, true);
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId2, kRouteId2));
-
- // 1 visible loaded, 1 hidden loading, 1 hidden loaded
- scheduler()->OnClientDeleted(kChildId2, kRouteId2);
- EXPECT_TRUE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- // 1 visible and 1 hidden loaded, 1 visible and 1 hidden loading
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, false);
- EXPECT_FALSE(scheduler()->active_clients_loaded());
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
-
- scheduler()->OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
-}
-
-TEST_F(ResourceSchedulerTest, CoalescedClientCreationStartsTimer) {
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- true /* should_coalesce */);
- EXPECT_FALSE(mock_timer_->IsRunning());
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- EXPECT_FALSE(mock_timer_->IsRunning());
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId, kBackgroundRouteId, true);
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(ResourceScheduler::COALESCED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_TRUE(mock_timer_->IsRunning());
-}
-
-TEST_F(ResourceSchedulerTest, ActiveLoadingClientLoadedAndHiddenStartsTimer) {
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- true /* should_coalesce */);
- EXPECT_FALSE(mock_timer_->IsRunning());
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_FALSE(mock_timer_->IsRunning());
-
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_FALSE(mock_timer_->IsRunning());
-
- scheduler()->OnVisibilityChanged(kChildId, kRouteId, false);
- EXPECT_EQ(ResourceScheduler::COALESCED,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_TRUE(mock_timer_->IsRunning());
-}
-
-TEST_F(ResourceSchedulerTest, ActiveLoadingClientHiddenAndLoadedStartsTimer) {
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- true /* should_coalesce */);
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
- EXPECT_EQ(ResourceScheduler::THROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_FALSE(mock_timer_->IsRunning());
-
- scheduler()->OnVisibilityChanged(kChildId, kRouteId, false);
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
- EXPECT_FALSE(mock_timer_->IsRunning());
-
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_EQ(ResourceScheduler::COALESCED,
- scheduler()->GetClientStateForTesting(kChildId, kRouteId));
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_TRUE(mock_timer_->IsRunning());
-}
-
-TEST_F(ResourceSchedulerTest, CoalescedClientBecomesAudibleStopsTimer) {
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- true /* should_coalesce */);
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- EXPECT_FALSE(mock_timer_->IsRunning());
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId, kBackgroundRouteId, true);
- EXPECT_EQ(ResourceScheduler::COALESCED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_TRUE(mock_timer_->IsRunning());
-
- scheduler()->OnAudibilityChanged(
- kBackgroundChildId, kBackgroundRouteId, true);
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_FALSE(mock_timer_->IsRunning());
-}
-
-TEST_F(ResourceSchedulerTest, LastCoalescedClientDeletionStopsTimer) {
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- true /* should_coalesce */);
- scheduler()->OnClientCreated(
- kBackgroundChildId2, kBackgroundRouteId2, false, false);
- EXPECT_FALSE(mock_timer_->IsRunning());
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- EXPECT_FALSE(mock_timer_->IsRunning());
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId, kBackgroundRouteId, true);
- EXPECT_EQ(ResourceScheduler::COALESCED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId2, kBackgroundRouteId2, true);
- EXPECT_EQ(ResourceScheduler::COALESCED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_TRUE(mock_timer_->IsRunning());
-
- scheduler()->OnClientDeleted(kBackgroundChildId, kBackgroundRouteId);
- EXPECT_TRUE(mock_timer_->IsRunning());
-
- scheduler()->OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
- EXPECT_FALSE(mock_timer_->IsRunning());
-
- // To avoid errors on test tear down.
- scheduler()->OnClientCreated(
- kBackgroundChildId, kBackgroundRouteId, false, false);
-}
-
-TEST_F(ResourceSchedulerTest, LastCoalescedClientStartsLoadingStopsTimer) {
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- true /* should_coalesce */);
- scheduler()->OnClientCreated(
- kBackgroundChildId2, kBackgroundRouteId2, false, false);
- EXPECT_FALSE(mock_timer_->IsRunning());
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- EXPECT_FALSE(mock_timer_->IsRunning());
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId, kBackgroundRouteId, true);
- EXPECT_EQ(ResourceScheduler::COALESCED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId2, kBackgroundRouteId2, true);
- EXPECT_EQ(ResourceScheduler::COALESCED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_TRUE(mock_timer_->IsRunning());
-
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId, kBackgroundRouteId, false);
- EXPECT_TRUE(mock_timer_->IsRunning());
-
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId2, kBackgroundRouteId2, false);
- EXPECT_FALSE(mock_timer_->IsRunning());
-
- // This is needed to avoid errors on test tear down.
- scheduler()->OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
-}
-
-TEST_F(ResourceSchedulerTest, LastCoalescedClientBecomesVisibleStopsTimer) {
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- true /* should_coalesce */);
- scheduler()->OnClientCreated(
- kBackgroundChildId2, kBackgroundRouteId2, false, false);
- EXPECT_FALSE(mock_timer_->IsRunning());
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- EXPECT_FALSE(mock_timer_->IsRunning());
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId, kBackgroundRouteId, true);
- EXPECT_EQ(ResourceScheduler::COALESCED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId2, kBackgroundRouteId2, true);
- EXPECT_EQ(ResourceScheduler::COALESCED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId2,
- kBackgroundRouteId2));
- EXPECT_TRUE(mock_timer_->IsRunning());
-
- scheduler()->OnVisibilityChanged(
- kBackgroundChildId, kBackgroundRouteId, true);
- EXPECT_TRUE(mock_timer_->IsRunning());
-
- scheduler()->OnVisibilityChanged(
- kBackgroundChildId2, kBackgroundRouteId2, true);
- EXPECT_FALSE(mock_timer_->IsRunning());
-
- // To avoid errors on test tear down.
- scheduler()->OnClientDeleted(kBackgroundChildId2, kBackgroundRouteId2);
-}
-
-TEST_F(ResourceSchedulerTest,
- CoalescedClientBecomesLoadingAndVisibleStopsTimer) {
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- true /* should_coalesce */);
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- EXPECT_FALSE(mock_timer_->IsRunning());
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId, kBackgroundRouteId, true);
- EXPECT_EQ(ResourceScheduler::COALESCED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_TRUE(mock_timer_->IsRunning());
-
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId, kBackgroundRouteId, false);
- EXPECT_EQ(ResourceScheduler::UNTHROTTLED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_FALSE(mock_timer_->IsRunning());
-
- scheduler()->OnVisibilityChanged(
- kBackgroundChildId, kBackgroundRouteId, true);
- EXPECT_EQ(ResourceScheduler::ACTIVE_AND_LOADING,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_FALSE(mock_timer_->IsRunning());
-}
-
-TEST_F(ResourceSchedulerTest, CoalescedRequestsIssueOnTimer) {
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- true /* should_coalesce */);
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId, kBackgroundRouteId, true);
- EXPECT_EQ(ResourceScheduler::COALESCED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_TRUE(scheduler()->active_clients_loaded());
-
- scoped_ptr<TestRequest> high(
- NewBackgroundRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(
- NewBackgroundRequest("http://host/low", net::LOWEST));
- EXPECT_FALSE(high->started());
- EXPECT_FALSE(low->started());
-
- FireCoalescingTimer();
- base::RunLoop().RunUntilIdle();
-
- EXPECT_TRUE(high->started());
- EXPECT_TRUE(low->started());
-}
-
-TEST_F(ResourceSchedulerTest, CoalescedRequestsUnthrottleCorrectlyOnTimer) {
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- true /* should_coalesce */);
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId, kBackgroundRouteId, true);
- EXPECT_EQ(ResourceScheduler::COALESCED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_TRUE(scheduler()->active_clients_loaded());
-
- scoped_ptr<TestRequest> high(
- NewBackgroundRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> high2(
- NewBackgroundRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> high3(
- NewBackgroundRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> high4(
- NewBackgroundRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(
- NewBackgroundRequest("http://host/low", net::LOWEST));
- scoped_ptr<TestRequest> low2(
- NewBackgroundRequest("http://host/low", net::LOWEST));
- scoped_ptr<TestRequest> low3(
- NewBackgroundRequest("http://host/low", net::LOWEST));
- scoped_ptr<TestRequest> low4(
- NewBackgroundRequest("http://host/low", net::LOWEST));
-
- http_server_properties_.SetSupportsSpdy(net::HostPortPair("spdyhost", 443),
- true);
- scoped_ptr<TestRequest> low_spdy(
- NewBackgroundRequest("https://spdyhost/low", net::LOW));
- scoped_ptr<TestRequest> sync_request(
- NewBackgroundSyncRequest("http://host/req", net::LOW));
- scoped_ptr<TestRequest> non_http_request(
- NewBackgroundRequest("chrome-extension://req", net::LOW));
-
- // Sync requests should issue immediately.
- EXPECT_TRUE(sync_request->started());
- // Non-http(s) requests should issue immediately.
- EXPECT_TRUE(non_http_request->started());
- // Nothing else should issue without a timer fire.
- EXPECT_FALSE(high->started());
- EXPECT_FALSE(high2->started());
- EXPECT_FALSE(high3->started());
- EXPECT_FALSE(high4->started());
- EXPECT_FALSE(low->started());
- EXPECT_FALSE(low2->started());
- EXPECT_FALSE(low3->started());
- EXPECT_FALSE(low4->started());
- EXPECT_FALSE(low_spdy->started());
-
- FireCoalescingTimer();
- base::RunLoop().RunUntilIdle();
-
- // All high priority requests should issue.
- EXPECT_TRUE(high->started());
- EXPECT_TRUE(high2->started());
- EXPECT_TRUE(high3->started());
- EXPECT_TRUE(high4->started());
- // There should only be one net::LOWEST priority request issued with
- // non-delayable requests in flight.
- EXPECT_TRUE(low->started());
- EXPECT_FALSE(low2->started());
- EXPECT_FALSE(low3->started());
- EXPECT_FALSE(low4->started());
- // Spdy-Enable requests should issue regardless of priority.
- EXPECT_TRUE(low_spdy->started());
-}
-
-TEST_F(ResourceSchedulerTest, CoalescedRequestsWaitForNextTimer) {
- scheduler()->SetThrottleOptionsForTesting(true /* should_throttle */,
- true /* should_coalesce */);
- scheduler()->OnLoadingStateChanged(kChildId, kRouteId, true);
- scheduler()->OnLoadingStateChanged(
- kBackgroundChildId, kBackgroundRouteId, true);
-
- EXPECT_EQ(ResourceScheduler::COALESCED,
- scheduler()->GetClientStateForTesting(kBackgroundChildId,
- kBackgroundRouteId));
- EXPECT_TRUE(scheduler()->active_clients_loaded());
-
- scoped_ptr<TestRequest> high(
- NewBackgroundRequest("http://host/high", net::HIGHEST));
- EXPECT_FALSE(high->started());
-
- FireCoalescingTimer();
- base::RunLoop().RunUntilIdle();
-
- scoped_ptr<TestRequest> high2(
- NewBackgroundRequest("http://host/high2", net::HIGHEST));
- scoped_ptr<TestRequest> low(
- NewBackgroundRequest("http://host/low", net::LOWEST));
-
- EXPECT_TRUE(high->started());
- EXPECT_FALSE(high2->started());
- EXPECT_FALSE(low->started());
-
- FireCoalescingTimer();
- base::RunLoop().RunUntilIdle();
-
- EXPECT_TRUE(high->started());
- EXPECT_TRUE(high2->started());
- EXPECT_TRUE(low->started());
-}
-
-TEST_F(ResourceSchedulerTest, GetVisualSignalFromRenderViewHost) {
- scoped_ptr<MockRenderProcessHostFactory> render_process_host_factory;
- scoped_ptr<TestRenderViewHostFactory> render_view_host_factory;
- scoped_ptr<TestBrowserContext> browser_context;
- scoped_ptr<TestWebContents> web_contents_1;
- scoped_ptr<TestWebContents> web_contents_2;
- render_process_host_factory.reset(new MockRenderProcessHostFactory());
- render_view_host_factory.reset(
- new TestRenderViewHostFactory(render_process_host_factory.get()));
-
- browser_context.reset(new TestBrowserContext());
- scoped_refptr<SiteInstance> site_instance_1 =
- SiteInstance::Create(browser_context.get());
- scoped_refptr<SiteInstance> site_instance_2 =
- SiteInstance::Create(browser_context.get());
- SiteInstanceImpl::set_render_process_host_factory(
- render_process_host_factory.get());
-
- web_contents_1.reset(
- TestWebContents::Create(browser_context.get(), site_instance_1.get()));
- web_contents_2.reset(
- TestWebContents::Create(browser_context.get(), site_instance_2.get()));
- base::RunLoop().RunUntilIdle();
-
- RenderViewHostImpl* rvh1 = web_contents_1->GetRenderViewHost();
- RenderViewHostImpl* rvh2 = web_contents_2->GetRenderViewHost();
- ResourceScheduler* scheduler = ResourceDispatcherHostImpl::Get()->scheduler();
-
- // Check initial visibility is set correctly.
- EXPECT_EQ(scheduler->IsClientVisibleForTesting(rvh1->GetProcess()->GetID(),
- rvh1->GetRoutingID()),
- !rvh1->GetWidget()->is_hidden());
- EXPECT_EQ(scheduler->IsClientVisibleForTesting(rvh2->GetProcess()->GetID(),
- rvh1->GetRoutingID()),
- !rvh2->GetWidget()->is_hidden());
-
- // 1 visible, 1 hidden.
- rvh1->GetWidget()->WasShown(ui::LatencyInfo());
- rvh2->GetWidget()->WasHidden();
- base::RunLoop().RunUntilIdle();
-
- EXPECT_TRUE(scheduler->IsClientVisibleForTesting(rvh1->GetProcess()->GetID(),
- rvh1->GetRoutingID()));
- EXPECT_FALSE(scheduler->IsClientVisibleForTesting(rvh2->GetProcess()->GetID(),
- rvh2->GetRoutingID()));
-
- // Flip the visibility and check again.
- rvh1->GetWidget()->WasHidden();
- rvh2->GetWidget()->WasShown(ui::LatencyInfo());
- base::RunLoop().RunUntilIdle();
-
- EXPECT_FALSE(scheduler->IsClientVisibleForTesting(rvh1->GetProcess()->GetID(),
- rvh1->GetRoutingID()));
- EXPECT_TRUE(scheduler->IsClientVisibleForTesting(rvh2->GetProcess()->GetID(),
- rvh2->GetRoutingID()));
- // Clean up.
- web_contents_1.reset();
- web_contents_2.reset();
- base::RunLoop().RunUntilIdle();
-
- browser_context.reset();
- render_process_host_factory.reset();
-}
-
TEST_F(ResourceSchedulerTest, OustandingRequestLimitEnforced) {
const int kRequestLimit = 3;
ASSERT_TRUE(InitializeFieldTrials(
@@ -2308,9 +739,10 @@ TEST_F(ResourceSchedulerTest, OutstandingRequestLimitDelays) {
kRequestLimit)));
InitializeScheduler();
- scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
- scoped_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
EXPECT_TRUE(high->started());
EXPECT_FALSE(low->started());
EXPECT_FALSE(low2->started());
@@ -2325,12 +757,12 @@ TEST_F(ResourceSchedulerTest, OutstandingRequestLimitDelays) {
// started at some point, or they will hang around forever and prevent other
// async revalidations to the same URL from being issued.
TEST_F(ResourceSchedulerTest, RequestStartedAfterClientDeleted) {
- scheduler_->OnClientCreated(kChildId2, kRouteId2, false, false);
- scoped_ptr<TestRequest> high(NewRequestWithChildAndRoute(
+ scheduler_->OnClientCreated(kChildId2, kRouteId2);
+ std::unique_ptr<TestRequest> high(NewRequestWithChildAndRoute(
"http://host/high", net::HIGHEST, kChildId2, kRouteId2));
- scoped_ptr<TestRequest> lowest1(NewRequestWithChildAndRoute(
+ std::unique_ptr<TestRequest> lowest1(NewRequestWithChildAndRoute(
"http://host/lowest", net::LOWEST, kChildId2, kRouteId2));
- scoped_ptr<TestRequest> lowest2(NewRequestWithChildAndRoute(
+ std::unique_ptr<TestRequest> lowest2(NewRequestWithChildAndRoute(
"http://host/lowest", net::LOWEST, kChildId2, kRouteId2));
EXPECT_FALSE(lowest2->started());
@@ -2346,8 +778,8 @@ TEST_F(ResourceSchedulerTest, RequestStartedAfterClientDeleted) {
// This test is to verify that requests will be started at some point
// even if they were not started by the destructor.
TEST_F(ResourceSchedulerTest, RequestStartedAfterClientDeletedManyDelayable) {
- scheduler_->OnClientCreated(kChildId2, kRouteId2, false, false);
- scoped_ptr<TestRequest> high(NewRequestWithChildAndRoute(
+ scheduler_->OnClientCreated(kChildId2, kRouteId2);
+ std::unique_ptr<TestRequest> high(NewRequestWithChildAndRoute(
"http://host/high", net::HIGHEST, kChildId2, kRouteId2));
const int kMaxNumDelayableRequestsPerClient = 10;
ScopedVector<TestRequest> delayable_requests;
@@ -2355,7 +787,7 @@ TEST_F(ResourceSchedulerTest, RequestStartedAfterClientDeletedManyDelayable) {
delayable_requests.push_back(NewRequestWithChildAndRoute(
"http://host/lowest", net::LOWEST, kChildId2, kRouteId2));
}
- scoped_ptr<TestRequest> lowest(NewRequestWithChildAndRoute(
+ std::unique_ptr<TestRequest> lowest(NewRequestWithChildAndRoute(
"http://host/lowest", net::LOWEST, kChildId2, kRouteId2));
EXPECT_FALSE(lowest->started());
@@ -2386,18 +818,19 @@ TEST_F(ResourceSchedulerTest, DefaultLayoutBlockingPriority) {
kMaxNumDelayableWhileLayoutBlocking,
kMaxNumDelayableRequestsPerClient)));
InitializeScheduler();
- scoped_ptr<TestRequest> high(
+ std::unique_ptr<TestRequest> high(
NewRequest("http://hosthigh/high", net::HIGHEST));
- scoped_ptr<TestRequest> high2(
+ std::unique_ptr<TestRequest> high2(
NewRequest("http://hosthigh/high", net::HIGHEST));
- scoped_ptr<TestRequest> medium(
+ std::unique_ptr<TestRequest> medium(
NewRequest("http://hostmedium/medium", net::MEDIUM));
- scoped_ptr<TestRequest> medium2(
+ std::unique_ptr<TestRequest> medium2(
NewRequest("http://hostmedium/medium", net::MEDIUM));
- scoped_ptr<TestRequest> low(NewRequest("http://hostlow/low", net::LOW));
- scoped_ptr<TestRequest> low2(NewRequest("http://hostlow/low", net::LOW));
- scoped_ptr<TestRequest> lowest(NewRequest("http://hostlowest/lowest", net::LOWEST));
- scoped_ptr<TestRequest> lowest2(
+ std::unique_ptr<TestRequest> low(NewRequest("http://hostlow/low", net::LOW));
+ std::unique_ptr<TestRequest> low2(NewRequest("http://hostlow/low", net::LOW));
+ std::unique_ptr<TestRequest> lowest(
+ NewRequest("http://hostlowest/lowest", net::LOWEST));
+ std::unique_ptr<TestRequest> lowest2(
NewRequest("http://hostlowest/lowest", net::LOWEST));
EXPECT_TRUE(high->started());
EXPECT_TRUE(high2->started());
@@ -2435,18 +868,19 @@ TEST_F(ResourceSchedulerTest, IncreaseLayoutBlockingPriority) {
kMaxNumDelayableWhileLayoutBlocking,
kMaxNumDelayableRequestsPerClient)));
InitializeScheduler();
- scoped_ptr<TestRequest> high(
+ std::unique_ptr<TestRequest> high(
NewRequest("http://hosthigh/high", net::HIGHEST));
- scoped_ptr<TestRequest> high2(
+ std::unique_ptr<TestRequest> high2(
NewRequest("http://hosthigh/high", net::HIGHEST));
- scoped_ptr<TestRequest> medium(
+ std::unique_ptr<TestRequest> medium(
NewRequest("http://hostmedium/medium", net::MEDIUM));
- scoped_ptr<TestRequest> medium2(
+ std::unique_ptr<TestRequest> medium2(
NewRequest("http://hostmedium/medium", net::MEDIUM));
- scoped_ptr<TestRequest> low(NewRequest("http://hostlow/low", net::LOW));
- scoped_ptr<TestRequest> low2(NewRequest("http://hostlow/low", net::LOW));
- scoped_ptr<TestRequest> lowest(NewRequest("http://hostlowest/lowest", net::LOWEST));
- scoped_ptr<TestRequest> lowest2(
+ std::unique_ptr<TestRequest> low(NewRequest("http://hostlow/low", net::LOW));
+ std::unique_ptr<TestRequest> low2(NewRequest("http://hostlow/low", net::LOW));
+ std::unique_ptr<TestRequest> lowest(
+ NewRequest("http://hostlowest/lowest", net::LOWEST));
+ std::unique_ptr<TestRequest> lowest2(
NewRequest("http://hostlowest/lowest", net::LOWEST));
EXPECT_TRUE(high->started());
EXPECT_TRUE(high2->started());
@@ -2495,10 +929,12 @@ TEST_F(ResourceSchedulerTest, UseLayoutBlockingThresholdOne) {
kMaxNumDelayableWhileLayoutBlocking,
kMaxNumDelayableRequestsPerClient)));
InitializeScheduler();
- scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> high2(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
- scoped_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> high2(
+ NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
EXPECT_TRUE(high->started());
EXPECT_TRUE(high2->started());
EXPECT_FALSE(low->started());
@@ -2540,11 +976,14 @@ TEST_F(ResourceSchedulerTest, UseLayoutBlockingThresholdTwo) {
kMaxNumDelayableWhileLayoutBlocking,
kMaxNumDelayableRequestsPerClient)));
InitializeScheduler();
- scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> high2(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> high3(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
- scoped_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> high2(
+ NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> high3(
+ NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
EXPECT_TRUE(high->started());
EXPECT_TRUE(high2->started());
EXPECT_TRUE(high3->started());
@@ -2588,10 +1027,11 @@ TEST_F(ResourceSchedulerTest, TwoDelayableLoadsUntilBodyInserted) {
kMaxNumDelayableWhileLayoutBlocking,
kMaxNumDelayableRequestsPerClient)));
InitializeScheduler();
- scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
- scoped_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
- scoped_ptr<TestRequest> low3(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> low3(NewRequest("http://host/low", net::LOWEST));
EXPECT_TRUE(high->started());
EXPECT_TRUE(low->started());
EXPECT_TRUE(low2->started());
@@ -2627,11 +1067,13 @@ TEST_F(ResourceSchedulerTest,
kMaxNumDelayableWhileLayoutBlocking,
kMaxNumDelayableRequestsPerClient)));
InitializeScheduler();
- scoped_ptr<TestRequest> high(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> high2(NewRequest("http://host/high", net::HIGHEST));
- scoped_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
- scoped_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
- scoped_ptr<TestRequest> low3(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> high(
+ NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> high2(
+ NewRequest("http://host/high", net::HIGHEST));
+ std::unique_ptr<TestRequest> low(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> low2(NewRequest("http://host/low", net::LOWEST));
+ std::unique_ptr<TestRequest> low3(NewRequest("http://host/low", net::LOWEST));
EXPECT_TRUE(high->started());
EXPECT_TRUE(high2->started());
EXPECT_FALSE(low->started());
@@ -2684,8 +1126,8 @@ TEST_F(ResourceSchedulerTest, TwentyMaxNumDelayableRequestsPerClient) {
EXPECT_TRUE(lows_different_host[i]->started());
}
- scoped_ptr<TestRequest> last_different_host(NewRequest("http://host_new/last",
- net::LOWEST));
+ std::unique_ptr<TestRequest> last_different_host(
+ NewRequest("http://host_new/last", net::LOWEST));
EXPECT_FALSE(last_different_host->started());
}
@@ -2725,8 +1167,8 @@ TEST_F(ResourceSchedulerTest,
EXPECT_TRUE(lows_different_host[i]->started());
}
- scoped_ptr<TestRequest> last_different_host(NewRequest("http://host_new/last",
- net::LOWEST));
+ std::unique_ptr<TestRequest> last_different_host(
+ NewRequest("http://host_new/last", net::LOWEST));
EXPECT_FALSE(last_different_host->started());
}
diff --git a/chromium/content/browser/loader/stream_resource_handler.h b/chromium/content/browser/loader/stream_resource_handler.h
index 6bc4253a2f3..42c71e8fb4b 100644
--- a/chromium/content/browser/loader/stream_resource_handler.h
+++ b/chromium/content/browser/loader/stream_resource_handler.h
@@ -5,9 +5,10 @@
#ifndef CONTENT_BROWSER_LOADER_STREAM_RESOURCE_HANDLER_H_
#define CONTENT_BROWSER_LOADER_STREAM_RESOURCE_HANDLER_H_
+#include <memory>
+
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "content/browser/loader/resource_handler.h"
#include "content/browser/loader/stream_writer.h"
diff --git a/chromium/content/browser/loader/temporary_file_stream.cc b/chromium/content/browser/loader/temporary_file_stream.cc
index c8bb3338f5c..bff6ed46268 100644
--- a/chromium/content/browser/loader/temporary_file_stream.cc
+++ b/chromium/content/browser/loader/temporary_file_stream.cc
@@ -20,15 +20,14 @@ namespace content {
namespace {
-void DidCreateTemporaryFile(
- const CreateTemporaryFileStreamCallback& callback,
- scoped_ptr<base::FileProxy> file_proxy,
- base::File::Error error_code,
- const base::FilePath& file_path) {
+void DidCreateTemporaryFile(const CreateTemporaryFileStreamCallback& callback,
+ std::unique_ptr<base::FileProxy> file_proxy,
+ base::File::Error error_code,
+ const base::FilePath& file_path) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!file_proxy->IsValid()) {
- callback.Run(error_code, scoped_ptr<net::FileStream>(), NULL);
+ callback.Run(error_code, std::unique_ptr<net::FileStream>(), NULL);
return;
}
@@ -42,7 +41,7 @@ void DidCreateTemporaryFile(
ShareableFileReference::DELETE_ON_FINAL_RELEASE,
task_runner.get());
- scoped_ptr<net::FileStream> file_stream(
+ std::unique_ptr<net::FileStream> file_stream(
new net::FileStream(file_proxy->TakeFile(), task_runner));
callback.Run(error_code, std::move(file_stream), deletable_file.get());
@@ -54,7 +53,7 @@ void CreateTemporaryFileStream(
const CreateTemporaryFileStreamCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- scoped_ptr<base::FileProxy> file_proxy(new base::FileProxy(
+ std::unique_ptr<base::FileProxy> file_proxy(new base::FileProxy(
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE).get()));
base::FileProxy* proxy = file_proxy.get();
proxy->CreateTemporary(
diff --git a/chromium/content/browser/loader/temporary_file_stream.h b/chromium/content/browser/loader/temporary_file_stream.h
index 280359636d8..406fcc445ee 100644
--- a/chromium/content/browser/loader/temporary_file_stream.h
+++ b/chromium/content/browser/loader/temporary_file_stream.h
@@ -5,9 +5,10 @@
#ifndef CONTENT_BROWSER_LOADER_TEMPORARY_FILE_STREAM_H_
#define CONTENT_BROWSER_LOADER_TEMPORARY_FILE_STREAM_H_
+#include <memory>
+
#include "base/callback_forward.h"
#include "base/files/file.h"
-#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
namespace net {
@@ -21,7 +22,7 @@ class ShareableFileReference;
namespace content {
typedef base::Callback<void(base::File::Error,
- scoped_ptr<net::FileStream>,
+ std::unique_ptr<net::FileStream>,
storage::ShareableFileReference*)>
CreateTemporaryFileStreamCallback;
diff --git a/chromium/content/browser/loader/temporary_file_stream_unittest.cc b/chromium/content/browser/loader/temporary_file_stream_unittest.cc
index a5fe1453312..d492254ee69 100644
--- a/chromium/content/browser/loader/temporary_file_stream_unittest.cc
+++ b/chromium/content/browser/loader/temporary_file_stream_unittest.cc
@@ -39,7 +39,7 @@ class WaitForFileStream {
}
void OnFileStreamCreated(base::File::Error error,
- scoped_ptr<net::FileStream> file_stream,
+ std::unique_ptr<net::FileStream> file_stream,
ShareableFileReference* deletable_file) {
error_ = error;
file_stream_ = std::move(file_stream);
@@ -58,7 +58,7 @@ class WaitForFileStream {
private:
base::RunLoop loop_;
base::File::Error error_;
- scoped_ptr<net::FileStream> file_stream_;
+ std::unique_ptr<net::FileStream> file_stream_;
scoped_refptr<ShareableFileReference> deletable_file_;
};
diff --git a/chromium/content/browser/loader/throttling_resource_handler.cc b/chromium/content/browser/loader/throttling_resource_handler.cc
index 93b9ad74836..99d84e65707 100644
--- a/chromium/content/browser/loader/throttling_resource_handler.cc
+++ b/chromium/content/browser/loader/throttling_resource_handler.cc
@@ -14,7 +14,7 @@
namespace content {
ThrottlingResourceHandler::ThrottlingResourceHandler(
- scoped_ptr<ResourceHandler> next_handler,
+ std::unique_ptr<ResourceHandler> next_handler,
net::URLRequest* request,
ScopedVector<ResourceThrottle> throttles)
: LayeredResourceHandler(request, std::move(next_handler)),
diff --git a/chromium/content/browser/loader/throttling_resource_handler.h b/chromium/content/browser/loader/throttling_resource_handler.h
index 6abefc46e04..32cc6fa0c49 100644
--- a/chromium/content/browser/loader/throttling_resource_handler.h
+++ b/chromium/content/browser/loader/throttling_resource_handler.h
@@ -28,7 +28,7 @@ class ThrottlingResourceHandler : public LayeredResourceHandler,
public ResourceController {
public:
// Takes ownership of the ResourceThrottle instances.
- ThrottlingResourceHandler(scoped_ptr<ResourceHandler> next_handler,
+ ThrottlingResourceHandler(std::unique_ptr<ResourceHandler> next_handler,
net::URLRequest* request,
ScopedVector<ResourceThrottle> throttles);
~ThrottlingResourceHandler() override;
diff --git a/chromium/content/browser/loader/upload_data_stream_builder.cc b/chromium/content/browser/loader/upload_data_stream_builder.cc
index bcabe99484c..f6d614ae37b 100644
--- a/chromium/content/browser/loader/upload_data_stream_builder.cc
+++ b/chromium/content/browser/loader/upload_data_stream_builder.cc
@@ -12,6 +12,7 @@
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "content/browser/fileapi/upload_file_system_file_element_reader.h"
#include "content/common/resource_request_body.h"
@@ -75,20 +76,20 @@ class FileElementReader : public net::UploadFileElementReader {
} // namespace
-scoped_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build(
+std::unique_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build(
ResourceRequestBody* body,
storage::BlobStorageContext* blob_context,
storage::FileSystemContext* file_system_context,
base::SingleThreadTaskRunner* file_task_runner) {
- std::vector<scoped_ptr<net::UploadElementReader>> element_readers;
+ std::vector<std::unique_ptr<net::UploadElementReader>> element_readers;
for (const auto& element : *body->elements()) {
switch (element.type()) {
case ResourceRequestBody::Element::TYPE_BYTES:
element_readers.push_back(
- make_scoped_ptr(new BytesElementReader(body, element)));
+ base::WrapUnique(new BytesElementReader(body, element)));
break;
case ResourceRequestBody::Element::TYPE_FILE:
- element_readers.push_back(make_scoped_ptr(
+ element_readers.push_back(base::WrapUnique(
new FileElementReader(body, file_task_runner, element)));
break;
case ResourceRequestBody::Element::TYPE_FILE_FILESYSTEM:
@@ -96,17 +97,17 @@ scoped_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build(
// supplied a FileSystemContext.
DCHECK(file_system_context);
element_readers.push_back(
- make_scoped_ptr(new content::UploadFileSystemFileElementReader(
+ base::WrapUnique(new content::UploadFileSystemFileElementReader(
file_system_context, element.filesystem_url(), element.offset(),
element.length(), element.expected_modification_time())));
break;
case ResourceRequestBody::Element::TYPE_BLOB: {
DCHECK_EQ(std::numeric_limits<uint64_t>::max(), element.length());
DCHECK_EQ(0ul, element.offset());
- scoped_ptr<storage::BlobDataHandle> handle =
+ std::unique_ptr<storage::BlobDataHandle> handle =
blob_context->GetBlobDataFromUUID(element.blob_uuid());
element_readers.push_back(
- make_scoped_ptr(new storage::UploadBlobElementReader(
+ base::WrapUnique(new storage::UploadBlobElementReader(
std::move(handle), file_system_context, file_task_runner)));
break;
}
@@ -118,7 +119,7 @@ scoped_ptr<net::UploadDataStream> UploadDataStreamBuilder::Build(
}
}
- return make_scoped_ptr(new net::ElementsUploadDataStream(
+ return base::WrapUnique(new net::ElementsUploadDataStream(
std::move(element_readers), body->identifier()));
}
diff --git a/chromium/content/browser/loader/upload_data_stream_builder.h b/chromium/content/browser/loader/upload_data_stream_builder.h
index abbcae822ce..fae5f3a70ca 100644
--- a/chromium/content/browser/loader/upload_data_stream_builder.h
+++ b/chromium/content/browser/loader/upload_data_stream_builder.h
@@ -5,7 +5,8 @@
#ifndef CONTENT_BROWSER_LOADER_UPLOAD_DATA_STREAM_BUILDER_H_
#define CONTENT_BROWSER_LOADER_UPLOAD_DATA_STREAM_BUILDER_H_
-#include "base/memory/scoped_ptr.h"
+#include <memory>
+
#include "content/common/content_export.h"
namespace base {
@@ -40,7 +41,7 @@ class CONTENT_EXPORT UploadDataStreamBuilder {
// |file_system_context| is used to create a FileStreamReader for files with
// filesystem URLs. |file_task_runner| is used to perform file operations
// when the data gets uploaded.
- static scoped_ptr<net::UploadDataStream> Build(
+ static std::unique_ptr<net::UploadDataStream> Build(
ResourceRequestBody* body,
storage::BlobStorageContext* blob_context,
storage::FileSystemContext* file_system_context,
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 fc92cc185aa..6db17f6cd4d 100644
--- a/chromium/content/browser/loader/upload_data_stream_builder_unittest.cc
+++ b/chromium/content/browser/loader/upload_data_stream_builder_unittest.cc
@@ -52,7 +52,7 @@ TEST(UploadDataStreamBuilderTest, CreateUploadDataStream) {
BlobStorageContext context;
BlobDataBuilder builder(kBlob);
builder.AppendData(kBlobData);
- scoped_ptr<BlobDataHandle> handle = context.AddFinishedBlob(&builder);
+ std::unique_ptr<BlobDataHandle> handle = context.AddFinishedBlob(&builder);
request_body->AppendBytes(kData, arraysize(kData) - 1);
request_body->AppendFileRange(base::FilePath(kFilePath), kFileOffset,
@@ -60,9 +60,10 @@ TEST(UploadDataStreamBuilderTest, CreateUploadDataStream) {
request_body->AppendBlob(kBlob);
request_body->set_identifier(kIdentifier);
- scoped_ptr<net::UploadDataStream> upload(UploadDataStreamBuilder::Build(
- request_body.get(), &context, NULL,
- base::ThreadTaskRunnerHandle::Get().get()));
+ std::unique_ptr<net::UploadDataStream> upload(
+ UploadDataStreamBuilder::Build(
+ request_body.get(), &context, NULL,
+ base::ThreadTaskRunnerHandle::Get().get()));
EXPECT_EQ(kIdentifier, upload->identifier());
ASSERT_TRUE(upload->GetElementReaders());
@@ -108,15 +109,17 @@ TEST(UploadDataStreamBuilderTest,
// A blob created from an empty file added several times.
const std::string blob_id("id-0");
- scoped_ptr<BlobDataBuilder> blob_data_builder(new BlobDataBuilder(blob_id));
+ std::unique_ptr<BlobDataBuilder> blob_data_builder(
+ new BlobDataBuilder(blob_id));
blob_data_builder->AppendFile(test_blob_path, 0, kZeroLength, blob_time);
- scoped_ptr<BlobDataHandle> handle =
+ std::unique_ptr<BlobDataHandle> handle =
blob_storage_context.AddFinishedBlob(blob_data_builder.get());
scoped_refptr<ResourceRequestBody> request_body(new ResourceRequestBody());
- scoped_ptr<net::UploadDataStream> upload(UploadDataStreamBuilder::Build(
- request_body.get(), &blob_storage_context, NULL,
- base::ThreadTaskRunnerHandle::Get().get()));
+ std::unique_ptr<net::UploadDataStream> upload(
+ UploadDataStreamBuilder::Build(
+ request_body.get(), &blob_storage_context, NULL,
+ base::ThreadTaskRunnerHandle::Get().get()));
request_body = new ResourceRequestBody();
request_body->AppendBlob(blob_id);
@@ -139,7 +142,7 @@ TEST(UploadDataStreamBuilderTest,
// Purposely (try to) read more than what is in the stream. If we try to
// read zero bytes then UploadDataStream::Read will fail a DCHECK.
int kBufferLength = kZeroLength + 1;
- scoped_ptr<char[]> buffer(new char[kBufferLength]);
+ std::unique_ptr<char[]> buffer(new char[kBufferLength]);
scoped_refptr<net::IOBuffer> io_buffer =
new net::WrappedIOBuffer(buffer.get());
net::TestCompletionCallback read_callback;
@@ -166,14 +169,15 @@ TEST(UploadDataStreamBuilderTest, ResetUploadStreamWithBlob) {
BlobStorageContext blob_storage_context;
BlobDataBuilder builder(kBlob);
builder.AppendData(kBlobData);
- scoped_ptr<BlobDataHandle> handle =
+ std::unique_ptr<BlobDataHandle> handle =
blob_storage_context.AddFinishedBlob(&builder);
request_body->AppendBlob(kBlob);
request_body->set_identifier(kIdentifier);
- scoped_ptr<net::UploadDataStream> upload(UploadDataStreamBuilder::Build(
- request_body.get(), &blob_storage_context, nullptr,
- base::ThreadTaskRunnerHandle::Get().get()));
+ std::unique_ptr<net::UploadDataStream> upload(
+ UploadDataStreamBuilder::Build(
+ request_body.get(), &blob_storage_context, nullptr,
+ base::ThreadTaskRunnerHandle::Get().get()));
net::TestCompletionCallback init_callback;
ASSERT_EQ(net::OK, upload->Init(init_callback.callback()));
diff --git a/chromium/content/browser/mach_broker_mac.h b/chromium/content/browser/mach_broker_mac.h
index f5d50addc3e..32ff5d6e548 100644
--- a/chromium/content/browser/mach_broker_mac.h
+++ b/chromium/content/browser/mach_broker_mac.h
@@ -5,15 +5,11 @@
#ifndef CONTENT_BROWSER_MACH_BROKER_MAC_H_
#define CONTENT_BROWSER_MACH_BROKER_MAC_H_
-#include <mach/mach.h>
-
#include <map>
#include <string>
-#include "base/mac/dispatch_source_mach.h"
-#include "base/mac/scoped_mach_port.h"
+#include "base/mac/mach_port_broker.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
#include "base/process/port_provider_mac.h"
#include "base/process/process_handle.h"
@@ -24,22 +20,12 @@
namespace content {
-// On OS X, the task port of a process is required to collect metrics about the
-// process, and to insert Mach ports into the process. Running |task_for_pid()|
-// is only allowed for privileged code. However, a process has port rights to
-// all its subprocesses, so let the browser's child processes send their Mach
-// port to the browser over IPC.
-//
-// Mach ports can only be sent over Mach IPC, not over the |socketpair()| that
-// the regular IPC system uses. Hence, the child processes open a Mach
-// connection shortly after launching and ipc their mach data to the browser
-// process. This data is kept in a global |MachBroker| object.
-//
-// Since this data arrives over a separate channel, it is not available
-// immediately after a child process has been started.
+// A global |MachBroker| singleton is used by content embedders to provide
+// access to mach task ports for content child processes.
class CONTENT_EXPORT MachBroker : public base::PortProvider,
public BrowserChildProcessObserver,
- public NotificationObserver {
+ public NotificationObserver,
+ public base::PortProvider::Observer {
public:
// For use in child processes. This will send the task port of the current
// process over Mach IPC to the port registered by name (via this class) in
@@ -51,8 +37,7 @@ class CONTENT_EXPORT MachBroker : public base::PortProvider,
static MachBroker* GetInstance();
// The lock that protects this MachBroker object. Clients MUST acquire and
- // release this lock around calls to EnsureRunning(), PlaceholderForPid(),
- // and FinalizePid().
+ // release this lock around calls to EnsureRunning() and PlaceholderForPid().
base::Lock& GetLock();
// Performs any necessary setup that cannot happen in the constructor.
@@ -61,9 +46,8 @@ class CONTENT_EXPORT MachBroker : public base::PortProvider,
void EnsureRunning();
// Adds a placeholder to the map for the given pid with MACH_PORT_NULL.
- // Callers are expected to later update the port with FinalizePid(). Callers
- // MUST acquire the lock given by GetLock() before calling this method (and
- // release the lock afterwards).
+ // Callers MUST acquire the lock given by GetLock() before calling this method
+ // (and release the lock afterwards).
void AddPlaceholderForPid(base::ProcessHandle pid, int child_process_id);
// Implement |base::PortProvider|.
@@ -91,18 +75,8 @@ class CONTENT_EXPORT MachBroker : public base::PortProvider,
MachBroker();
~MachBroker() override;
- // Performs any initialization work.
- bool Init();
-
- // Message handler that is invoked on |dispatch_source_| when an
- // incoming message needs to be received.
- void HandleRequest();
-
- // Updates the mapping for |pid| to include the given |mach_info|. Does
- // nothing if PlaceholderForPid() has not already been called for the given
- // |pid|. Callers MUST acquire the lock given by GetLock() before calling
- // this method (and release the lock afterwards).
- void FinalizePid(base::ProcessHandle pid, mach_port_t task_port);
+ // Implement |base::PortProvider::Observer|.
+ void OnReceivedTaskPort(base::ProcessHandle process) override;
// Removes all mappings belonging to |child_process_id| from the broker.
void InvalidateChildProcessId(int child_process_id);
@@ -117,23 +91,13 @@ class CONTENT_EXPORT MachBroker : public base::PortProvider,
// Accessed only on the UI thread.
NotificationRegistrar registrar_;
- // The Mach port on which the server listens.
- base::mac::ScopedMachReceiveRight server_port_;
-
- // The dispatch source and queue on which Mach messages will be received.
- scoped_ptr<base::DispatchSourceMach> dispatch_source_;
-
- // Stores mach info for every process in the broker.
- typedef std::map<base::ProcessHandle, mach_port_t> MachMap;
- MachMap mach_map_;
-
// Stores the Child process unique id (RenderProcessHost ID) for every
- // process.
+ // process. Protected by base::MachPortBroker::GetLock().
typedef std::map<int, base::ProcessHandle> ChildProcessIdMap;
ChildProcessIdMap child_process_id_map_;
- // Mutex that guards |mach_map_| and |child_process_id_map_|.
- mutable base::Lock lock_;
+ // Underlying port broker that receives and manages mach ports.
+ base::MachPortBroker broker_;
DISALLOW_COPY_AND_ASSIGN(MachBroker);
};
diff --git a/chromium/content/browser/mach_broker_mac.mm b/chromium/content/browser/mach_broker_mac.mm
index 4cf3bb6c77c..dfbf71f600b 100644
--- a/chromium/content/browser/mach_broker_mac.mm
+++ b/chromium/content/browser/mach_broker_mac.mm
@@ -4,18 +4,10 @@
#include "content/browser/mach_broker_mac.h"
-#include <bsm/libbsm.h>
-#include <servers/bootstrap.h>
-
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/logging.h"
-#include "base/mac/foundation_util.h"
-#include "base/mac/mach_logging.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/sys_string_conversions.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_data.h"
@@ -26,55 +18,12 @@
namespace content {
namespace {
+const char kBootstrapName[] = "rohitfork";
+}
-// Mach message structure used in the child as a sending message.
-struct MachBroker_ChildSendMsg {
- mach_msg_header_t header;
- mach_msg_body_t body;
- mach_msg_port_descriptor_t child_task_port;
-};
-
-// Complement to the ChildSendMsg, this is used in the parent for receiving
-// a message. Contains a message trailer with audit information.
-struct MachBroker_ParentRecvMsg : public MachBroker_ChildSendMsg {
- mach_msg_audit_trailer_t trailer;
-};
-
-} // namespace
-
+// static
bool MachBroker::ChildSendTaskPortToParent() {
- // Look up the named MachBroker port that's been registered with the
- // bootstrap server.
- mach_port_t parent_port;
- kern_return_t kr = bootstrap_look_up(bootstrap_port,
- const_cast<char*>(GetMachPortName().c_str()), &parent_port);
- if (kr != KERN_SUCCESS) {
- BOOTSTRAP_LOG(ERROR, kr) << "bootstrap_look_up";
- return false;
- }
- base::mac::ScopedMachSendRight scoped_right(parent_port);
-
- // Create the check in message. This will copy a send right on this process'
- // (the child's) task port and send it to the parent.
- MachBroker_ChildSendMsg msg;
- bzero(&msg, sizeof(msg));
- msg.header.msgh_bits = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_COPY_SEND) |
- MACH_MSGH_BITS_COMPLEX;
- msg.header.msgh_remote_port = parent_port;
- msg.header.msgh_size = sizeof(msg);
- msg.body.msgh_descriptor_count = 1;
- msg.child_task_port.name = mach_task_self();
- msg.child_task_port.disposition = MACH_MSG_TYPE_PORT_SEND;
- msg.child_task_port.type = MACH_MSG_PORT_DESCRIPTOR;
-
- kr = mach_msg(&msg.header, MACH_SEND_MSG | MACH_SEND_TIMEOUT, sizeof(msg),
- 0, MACH_PORT_NULL, 100 /*milliseconds*/, MACH_PORT_NULL);
- if (kr != KERN_SUCCESS) {
- MACH_LOG(ERROR, kr) << "mach_msg";
- return false;
- }
-
- return true;
+ return base::MachPortBroker::ChildSendTaskPortToParent(kBootstrapName);
}
MachBroker* MachBroker::GetInstance() {
@@ -83,11 +32,11 @@ MachBroker* MachBroker::GetInstance() {
}
base::Lock& MachBroker::GetLock() {
- return lock_;
+ return broker_.GetLock();
}
void MachBroker::EnsureRunning() {
- lock_.AssertAcquired();
+ GetLock().AssertAcquired();
if (initialized_)
return;
@@ -99,26 +48,21 @@ void MachBroker::EnsureRunning() {
BrowserThread::UI, FROM_HERE,
base::Bind(&MachBroker::RegisterNotifications, base::Unretained(this)));
- if (!Init()) {
+ if (!broker_.Init()) {
LOG(ERROR) << "Failed to initialize the MachListenerThreadDelegate";
}
}
void MachBroker::AddPlaceholderForPid(base::ProcessHandle pid,
int child_process_id) {
- lock_.AssertAcquired();
+ GetLock().AssertAcquired();
- DCHECK_EQ(0u, mach_map_.count(pid));
- mach_map_[pid] = MACH_PORT_NULL;
+ broker_.AddPlaceholderForPid(pid);
child_process_id_map_[child_process_id] = pid;
}
mach_port_t MachBroker::TaskForPid(base::ProcessHandle pid) const {
- base::AutoLock lock(lock_);
- MachBroker::MachMap::const_iterator it = mach_map_.find(pid);
- if (it == mach_map_.end())
- return MACH_PORT_NULL;
- return it->second;
+ return broker_.TaskForPid(pid);
}
void MachBroker::BrowserChildProcessHostDisconnected(
@@ -152,108 +96,29 @@ std::string MachBroker::GetMachPortName() {
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
const bool is_child = command_line->HasSwitch(switches::kProcessType);
-
- // In non-browser (child) processes, use the parent's pid.
- const pid_t pid = is_child ? getppid() : getpid();
- return base::StringPrintf("%s.rohitfork.%d", base::mac::BaseBundleID(), pid);
+ return base::MachPortBroker::GetMachPortName(kBootstrapName, is_child);
}
-MachBroker::MachBroker() : initialized_(false) {
+MachBroker::MachBroker() : initialized_(false), broker_(kBootstrapName) {
+ broker_.AddObserver(this);
}
-MachBroker::~MachBroker() {}
-
-bool MachBroker::Init() {
- DCHECK(server_port_.get() == MACH_PORT_NULL);
-
- // Check in with launchd and publish the service name.
- mach_port_t port;
- kern_return_t kr =
- bootstrap_check_in(bootstrap_port, GetMachPortName().c_str(), &port);
- if (kr != KERN_SUCCESS) {
- BOOTSTRAP_LOG(ERROR, kr) << "bootstrap_check_in";
- return false;
- }
- server_port_.reset(port);
-
- // Start the dispatch source.
- std::string queue_name =
- base::StringPrintf("%s.MachBroker", base::mac::BaseBundleID());
- dispatch_source_.reset(new base::DispatchSourceMach(
- queue_name.c_str(), server_port_.get(), ^{ HandleRequest(); }));
- dispatch_source_->Resume();
-
- return true;
+MachBroker::~MachBroker() {
+ broker_.RemoveObserver(this);
}
-void MachBroker::HandleRequest() {
- MachBroker_ParentRecvMsg msg;
- bzero(&msg, sizeof(msg));
- msg.header.msgh_size = sizeof(msg);
- msg.header.msgh_local_port = server_port_.get();
-
- const mach_msg_option_t options = MACH_RCV_MSG |
- MACH_RCV_TRAILER_TYPE(MACH_RCV_TRAILER_AUDIT) |
- MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT);
-
- kern_return_t kr = mach_msg(&msg.header,
- options,
- 0,
- sizeof(msg),
- server_port_.get(),
- MACH_MSG_TIMEOUT_NONE,
- MACH_PORT_NULL);
- if (kr != KERN_SUCCESS) {
- MACH_LOG(ERROR, kr) << "mach_msg";
- return;
- }
-
- // Use the kernel audit information to make sure this message is from
- // a task that this process spawned. The kernel audit token contains the
- // unspoofable pid of the task that sent the message.
- //
- // TODO(rsesek): In the 10.7 SDK, there's audit_token_to_pid().
- pid_t child_pid;
- audit_token_to_au32(msg.trailer.msgh_audit,
- NULL, NULL, NULL, NULL, NULL, &child_pid, NULL, NULL);
-
- mach_port_t child_task_port = msg.child_task_port.name;
-
- // Take the lock and update the broker information.
- base::AutoLock lock(GetLock());
- FinalizePid(child_pid, child_task_port);
-}
-
-void MachBroker::FinalizePid(base::ProcessHandle pid,
- mach_port_t task_port) {
- lock_.AssertAcquired();
-
- MachMap::iterator it = mach_map_.find(pid);
- if (it == mach_map_.end()) {
- // Do nothing for unknown pids.
- LOG(ERROR) << "Unknown process " << pid << " is sending Mach IPC messages!";
- return;
- }
-
- DCHECK(it->second == MACH_PORT_NULL);
- if (it->second == MACH_PORT_NULL)
- it->second = task_port;
+void MachBroker::OnReceivedTaskPort(base::ProcessHandle process) {
+ NotifyObservers(process);
}
void MachBroker::InvalidateChildProcessId(int child_process_id) {
- base::AutoLock lock(lock_);
+ base::AutoLock lock(GetLock());
MachBroker::ChildProcessIdMap::iterator it =
child_process_id_map_.find(child_process_id);
if (it == child_process_id_map_.end())
return;
- MachMap::iterator mach_it = mach_map_.find(it->second);
- if (mach_it != mach_map_.end()) {
- kern_return_t kr = mach_port_deallocate(mach_task_self(),
- mach_it->second);
- MACH_LOG_IF(WARNING, kr != KERN_SUCCESS, kr) << "mach_port_deallocate";
- mach_map_.erase(mach_it);
- }
+ broker_.InvalidatePid(it->second);
child_process_id_map_.erase(it);
}
diff --git a/chromium/content/browser/mach_broker_mac_unittest.cc b/chromium/content/browser/mach_broker_mac_unittest.cc
index 9ba50c31090..65eaa91a7c3 100644
--- a/chromium/content/browser/mach_broker_mac_unittest.cc
+++ b/chromium/content/browser/mach_broker_mac_unittest.cc
@@ -4,13 +4,28 @@
#include "content/browser/mach_broker_mac.h"
+#include "base/command_line.h"
#include "base/synchronization/lock.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/test/multiprocess_test.h"
+#include "base/test/test_timeouts.h"
+#include "content/public/test/test_browser_thread_bundle.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/multiprocess_func_list.h"
namespace content {
-class MachBrokerTest : public testing::Test {
+class MachBrokerTest : public testing::Test,
+ public base::PortProvider::Observer {
public:
+ MachBrokerTest()
+ : event_(true, false), received_process_(base::kNullProcessHandle) {
+ broker_.AddObserver(this);
+ }
+ ~MachBrokerTest() override {
+ broker_.RemoveObserver(this);
+ }
+
// Helper function to acquire/release locks and call |PlaceholderForPid()|.
void AddPlaceholderForPid(base::ProcessHandle pid, int child_process_id) {
base::AutoLock lock(broker_.GetLock());
@@ -25,59 +40,72 @@ class MachBrokerTest : public testing::Test {
return broker_.child_process_id_map_.count(child_process_id);
}
- // Helper function to acquire/release locks and call |FinalizePid()|.
- void FinalizePid(base::ProcessHandle pid,
- mach_port_t task_port) {
+ base::Process LaunchTestChild(const std::string& function,
+ int child_process_id) {
base::AutoLock lock(broker_.GetLock());
- broker_.FinalizePid(pid, task_port);
+ base::Process test_child_process = base::SpawnMultiProcessTestChild(
+ function, base::GetMultiProcessTestChildBaseCommandLine(),
+ base::LaunchOptions());
+ broker_.AddPlaceholderForPid(test_child_process.Handle(), child_process_id);
+ return test_child_process;
+ }
+
+ void WaitForChildExit(base::Process& process) {
+ int rv = -1;
+ ASSERT_TRUE(process.WaitForExitWithTimeout(
+ TestTimeouts::action_timeout(), &rv));
+ EXPECT_EQ(0, rv);
+ }
+
+ void WaitForTaskPort() {
+ event_.Wait();
+ }
+
+ // base::PortProvider::Observer:
+ void OnReceivedTaskPort(base::ProcessHandle process) override {
+ received_process_ = process;
+ event_.Signal();
}
protected:
MachBroker broker_;
+ base::WaitableEvent event_;
+ base::ProcessHandle received_process_;
+ TestBrowserThreadBundle thread_bundle_;
};
+MULTIPROCESS_TEST_MAIN(MachBrokerTestChild) {
+ CHECK(MachBroker::ChildSendTaskPortToParent());
+ return 0;
+}
+
TEST_F(MachBrokerTest, Locks) {
// Acquire and release the locks. Nothing bad should happen.
base::AutoLock lock(broker_.GetLock());
}
-TEST_F(MachBrokerTest, AddPlaceholderAndFinalize) {
- // Add a placeholder for PID 1.
- AddPlaceholderForPid(1, 1);
- EXPECT_EQ(0u, broker_.TaskForPid(1));
-
- // Finalize PID 1.
- FinalizePid(1, 100u);
- EXPECT_EQ(100u, broker_.TaskForPid(1));
-
- // Should be no entry for PID 2.
- EXPECT_EQ(0u, broker_.TaskForPid(2));
-}
-
-TEST_F(MachBrokerTest, InvalidateChildProcessId) {
- // Add a placeholder for PID 1 and child process id 50.
- AddPlaceholderForPid(1, 50);
- FinalizePid(1, 100u);
-
- EXPECT_EQ(100u, broker_.TaskForPid(1));
- InvalidateChildProcessId(50);
- EXPECT_EQ(0u, broker_.TaskForPid(1));
-}
-
-TEST_F(MachBrokerTest, ValidateChildProcessIdMap) {
- // Add a placeholder for PID 1 and child process id 50.
- AddPlaceholderForPid(1, 50);
- FinalizePid(1, 100u);
-
- EXPECT_EQ(1, GetChildProcessCount(50));
- InvalidateChildProcessId(50);
- EXPECT_EQ(0, GetChildProcessCount(50));
-}
-
-TEST_F(MachBrokerTest, FinalizeUnknownPid) {
- // Finalizing an entry for an unknown pid should not add it to the map.
- FinalizePid(1u, 100u);
- EXPECT_EQ(0u, broker_.TaskForPid(1u));
+TEST_F(MachBrokerTest, AddChildProcess) {
+ {
+ base::AutoLock lock(broker_.GetLock());
+ broker_.EnsureRunning();
+ }
+ base::Process child_process = LaunchTestChild("MachBrokerTestChild", 7);
+ WaitForTaskPort();
+ EXPECT_EQ(child_process.Handle(), received_process_);
+ WaitForChildExit(child_process);
+
+ EXPECT_NE(static_cast<mach_port_t>(MACH_PORT_NULL),
+ broker_.TaskForPid(child_process.Handle()));
+ EXPECT_EQ(1, GetChildProcessCount(7));
+
+ // Should be no entry for any other PID.
+ EXPECT_EQ(static_cast<mach_port_t>(MACH_PORT_NULL),
+ broker_.TaskForPid(child_process.Handle() + 1));
+
+ InvalidateChildProcessId(7);
+ EXPECT_EQ(static_cast<mach_port_t>(MACH_PORT_NULL),
+ broker_.TaskForPid(child_process.Handle()));
+ EXPECT_EQ(0, GetChildProcessCount(7));
}
} // namespace content
diff --git a/chromium/content/browser/media/OWNERS b/chromium/content/browser/media/OWNERS
index ea102ff5871..5d85067ee22 100644
--- a/chromium/content/browser/media/OWNERS
+++ b/chromium/content/browser/media/OWNERS
@@ -1,15 +1,6 @@
-dalecurtis@chromium.org
-ddorwin@chromium.org
-xhwang@chromium.org
-
-# WebRTC OWNERS.
-perkj@chromium.org
-tommi@chromium.org
+file://media/OWNERS
per-file midi_*=toyoshim@chromium.org
# For changes related to the tab media indicators.
per-file audio_stream_monitor*=miu@chromium.org
-
-# For WebRTC browser tests, etc.
-per-file *webrtc*browsertest*=phoglund@chromium.org
diff --git a/chromium/content/browser/media/android/OWNERS b/chromium/content/browser/media/android/OWNERS
index 99dc93e5d02..5abf5a186b9 100644
--- a/chromium/content/browser/media/android/OWNERS
+++ b/chromium/content/browser/media/android/OWNERS
@@ -1,4 +1 @@
qinmin@chromium.org
-
-per-file media_session*.*=avayvod@chromium.org
-per-file media_session*.*=mlamouri@chromium.org
diff --git a/chromium/content/browser/media/android/browser_demuxer_android.cc b/chromium/content/browser/media/android/browser_demuxer_android.cc
index 9da7170b36f..ed56bf7cea4 100644
--- a/chromium/content/browser/media/android/browser_demuxer_android.cc
+++ b/chromium/content/browser/media/android/browser_demuxer_android.cc
@@ -97,9 +97,9 @@ bool BrowserDemuxerAndroid::OnMessageReceived(const IPC::Message& message) {
return handled;
}
-scoped_ptr<media::DemuxerAndroid> BrowserDemuxerAndroid::CreateDemuxer(
+std::unique_ptr<media::DemuxerAndroid> BrowserDemuxerAndroid::CreateDemuxer(
int demuxer_client_id) {
- return scoped_ptr<media::DemuxerAndroid>(
+ return std::unique_ptr<media::DemuxerAndroid>(
new Internal(this, demuxer_client_id));
}
diff --git a/chromium/content/browser/media/android/browser_demuxer_android.h b/chromium/content/browser/media/android/browser_demuxer_android.h
index f1b28d313e6..5ff37f0a3c3 100644
--- a/chromium/content/browser/media/android/browser_demuxer_android.h
+++ b/chromium/content/browser/media/android/browser_demuxer_android.h
@@ -32,7 +32,7 @@ class CONTENT_EXPORT BrowserDemuxerAndroid : public BrowserMessageFilter {
// Returns an uninitialized demuxer implementation associated with
// |demuxer_client_id|, which can be used to communicate with the real demuxer
// in the renderer process.
- scoped_ptr<media::DemuxerAndroid> CreateDemuxer(int demuxer_client_id);
+ std::unique_ptr<media::DemuxerAndroid> CreateDemuxer(int demuxer_client_id);
protected:
friend class base::RefCountedThreadSafe<BrowserDemuxerAndroid>;
diff --git a/chromium/content/browser/media/android/browser_media_player_manager.cc b/chromium/content/browser/media/android/browser_media_player_manager.cc
index 0622043448b..96f6fcde97c 100644
--- a/chromium/content/browser/media/android/browser_media_player_manager.cc
+++ b/chromium/content/browser/media/android/browser_media_player_manager.cc
@@ -10,7 +10,6 @@
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/media/android/browser_demuxer_android.h"
#include "content/browser/media/android/media_resource_getter_impl.h"
-#include "content/browser/media/android/media_session.h"
#include "content/browser/media/android/media_throttler.h"
#include "content/browser/media/android/media_web_contents_observer_android.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
@@ -52,9 +51,6 @@ namespace content {
const int kMediaPlayerThreshold = 1;
const int kInvalidMediaPlayerId = -1;
-// Minimal duration of a media player in order to be considered as Content type.
-const int kMinimumDurationForContentInSeconds = 5;
-
static BrowserMediaPlayerManager::Factory g_factory = NULL;
static media::MediaUrlInterceptor* media_url_interceptor_ = NULL;
@@ -147,16 +143,13 @@ MediaPlayerAndroid* BrowserMediaPlayerManager::CreateMediaPlayer(
case MEDIA_PLAYER_TYPE_URL: {
const std::string user_agent = GetContentClient()->GetUserAgent();
MediaPlayerBridge* media_player_bridge = new MediaPlayerBridge(
- media_player_params.player_id,
- media_player_params.url,
- media_player_params.first_party_for_cookies,
- user_agent,
- hide_url_log,
+ media_player_params.player_id, media_player_params.url,
+ media_player_params.first_party_for_cookies, user_agent, hide_url_log,
this,
base::Bind(&BrowserMediaPlayerManager::OnDecoderResourcesReleased,
weak_ptr_factory_.GetWeakPtr()),
- media_player_params.frame_url,
- media_player_params.allow_credentials);
+ media_player_params.frame_url, media_player_params.allow_credentials,
+ media_player_params.media_session_id);
if (media_player_params.type == MEDIA_PLAYER_TYPE_REMOTE_ONLY)
return media_player_bridge;
@@ -193,20 +186,20 @@ MediaPlayerAndroid* BrowserMediaPlayerManager::CreateMediaPlayer(
case MEDIA_PLAYER_TYPE_MEDIA_SOURCE: {
if (media::UseMediaThreadForMediaPlayback()) {
return new MediaCodecPlayer(
- media_player_params.player_id,
- weak_ptr_factory_.GetWeakPtr(),
+ media_player_params.player_id, weak_ptr_factory_.GetWeakPtr(),
base::Bind(&BrowserMediaPlayerManager::OnDecoderResourcesReleased,
weak_ptr_factory_.GetWeakPtr()),
demuxer->CreateDemuxer(media_player_params.demuxer_client_id),
- media_player_params.frame_url);
+ media_player_params.frame_url,
+ media_player_params.media_session_id);
} else {
return new MediaSourcePlayer(
- media_player_params.player_id,
- this,
+ media_player_params.player_id, this,
base::Bind(&BrowserMediaPlayerManager::OnDecoderResourcesReleased,
weak_ptr_factory_.GetWeakPtr()),
demuxer->CreateDemuxer(media_player_params.demuxer_client_id),
- media_player_params.frame_url);
+ media_player_params.frame_url,
+ media_player_params.media_session_id);
}
}
}
@@ -233,11 +226,10 @@ BrowserMediaPlayerManager::~BrowserMediaPlayerManager() {
for (MediaPlayerAndroid* player : players_)
player->DeleteOnCorrectThread();
- MediaSession::Get(web_contents())->RemovePlayers(this);
players_.weak_clear();
}
-void BrowserMediaPlayerManager::ExitFullscreen(bool release_media_player) {
+void BrowserMediaPlayerManager::DidExitFullscreen(bool release_media_player) {
#if defined(USE_AURA)
// TODO(crbug.com/548024)
NOTIMPLEMENTED();
@@ -289,6 +281,13 @@ void BrowserMediaPlayerManager::SetVideoSurface(
if (empty_surface)
return;
+ // If we already know the size, set it now. Otherwise it will be set when the
+ // player gets it.
+ if (player->IsPlayerReady()) {
+ video_view_->OnVideoSizeChanged(player->GetVideoWidth(),
+ player->GetVideoHeight());
+ }
+
#if !defined(USE_AURA)
if (RenderWidgetHostViewAndroid* view_android =
static_cast<RenderWidgetHostViewAndroid*>(
@@ -304,21 +303,16 @@ void BrowserMediaPlayerManager::OnMediaMetadataChanged(
Send(new MediaPlayerMsg_MediaMetadataChanged(
RoutingID(), player_id, duration, width, height, success));
if (fullscreen_player_id_ == player_id)
- video_view_->UpdateMediaMetadata();
+ video_view_->OnVideoSizeChanged(width, height);
}
void BrowserMediaPlayerManager::OnPlaybackComplete(int player_id) {
Send(new MediaPlayerMsg_MediaPlaybackCompleted(RoutingID(), player_id));
- MediaSession::Get(web_contents())->RemovePlayer(this, player_id);
-
- if (fullscreen_player_id_ == player_id)
- video_view_->OnPlaybackComplete();
}
void BrowserMediaPlayerManager::OnMediaInterrupted(int player_id) {
// Tell WebKit that the audio should be paused, then release all resources
Send(new MediaPlayerMsg_MediaPlayerReleased(RoutingID(), player_id));
- MediaSession::Get(web_contents())->RemovePlayer(this, player_id);
ReleaseResources(player_id);
}
@@ -334,15 +328,6 @@ void BrowserMediaPlayerManager::OnSeekRequest(
Send(new MediaPlayerMsg_SeekRequest(RoutingID(), player_id, time_to_seek));
}
-void BrowserMediaPlayerManager::ReleaseAllMediaPlayers() {
- for (ScopedVector<MediaPlayerAndroid>::iterator it = players_.begin();
- it != players_.end(); ++it) {
- if ((*it)->player_id() == fullscreen_player_id_)
- fullscreen_player_is_released_ = true;
- (*it)->Release();
- }
-}
-
void BrowserMediaPlayerManager::OnSeekComplete(
int player_id,
const base::TimeDelta& current_time) {
@@ -409,36 +394,12 @@ MediaPlayerAndroid* BrowserMediaPlayerManager::GetPlayer(int player_id) {
bool BrowserMediaPlayerManager::RequestPlay(int player_id,
base::TimeDelta duration,
bool has_audio) {
- if (!has_audio)
- return true;
-
- MediaSession::Type media_session_type =
- duration == base::TimeDelta() ||
- duration.InSeconds() > kMinimumDurationForContentInSeconds
- ? MediaSession::Type::Content
- : MediaSession::Type::Transient;
-
- bool succeeded = MediaSession::Get(web_contents())->AddPlayer(
- this, player_id, media_session_type);
- if (!succeeded)
- Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(), player_id));
- return succeeded;
-}
-
-void BrowserMediaPlayerManager::OnSuspend(int player_id) {
- MediaPlayerAndroid* player = GetPlayer(player_id);
- DCHECK(player);
-
- player->Pause(true);
- Send(new MediaPlayerMsg_DidMediaPlayerPause(RoutingID(), player_id));
-}
-
-void BrowserMediaPlayerManager::OnResume(int player_id) {
- MediaPlayerAndroid* player = GetPlayer(player_id);
- DCHECK(player);
-
- player->Start();
- Send(new MediaPlayerMsg_DidMediaPlayerPlay(RoutingID(), player_id));
+ DCHECK(player_id_to_delegate_id_map_.find(player_id) !=
+ player_id_to_delegate_id_map_.end());
+ return MediaWebContentsObserverAndroid::FromWebContents(web_contents_)
+ ->RequestPlay(render_frame_host_,
+ player_id_to_delegate_id_map_[player_id], has_audio,
+ IsPlayingRemotely(player_id), duration);
}
#if defined(VIDEO_HOLE)
@@ -533,25 +494,29 @@ void BrowserMediaPlayerManager::OnEnterFullscreen(int player_id) {
if (external_video_surface_container_)
external_video_surface_container_->ReleaseExternalVideoSurface(player_id);
#endif // defined(VIDEO_HOLE)
- if (video_view_.get()) {
+ if (video_view_) {
fullscreen_player_id_ = player_id;
video_view_->OpenVideo();
return;
- } else if (!ContentVideoView::GetInstance()) {
+ }
+
+ if (ContentVideoView::GetInstance()) {
// In Android WebView, two ContentViewCores could both try to enter
// fullscreen video, we just ignore the second one.
- video_view_.reset(new ContentVideoView(this));
- base::android::ScopedJavaLocalRef<jobject> j_content_video_view =
- video_view_->GetJavaObject(base::android::AttachCurrentThread());
- if (!j_content_video_view.is_null()) {
- fullscreen_player_id_ = player_id;
- return;
- }
+ Send(new MediaPlayerMsg_DidExitFullscreen(RoutingID(), player_id));
+ return;
}
- // Force the second video to exit fullscreen.
- Send(new MediaPlayerMsg_DidExitFullscreen(RoutingID(), player_id));
- video_view_.reset();
+ // There's no ContentVideoView instance so create one.
+ video_view_.reset(new ContentVideoView(this, GetContentViewCore()));
+ base::android::ScopedJavaLocalRef<jobject> j_content_video_view =
+ video_view_->GetJavaObject(base::android::AttachCurrentThread());
+ if (!j_content_video_view.is_null()) {
+ fullscreen_player_id_ = player_id;
+ } else {
+ Send(new MediaPlayerMsg_DidExitFullscreen(RoutingID(), player_id));
+ video_view_.reset();
+ }
#endif // defined(USE_AURA)
}
@@ -574,7 +539,7 @@ void BrowserMediaPlayerManager::OnInitialize(
if (!player)
return;
- AddPlayer(player);
+ AddPlayer(player, media_player_params.delegate_id);
}
void BrowserMediaPlayerManager::OnStart(int player_id) {
@@ -606,9 +571,6 @@ void BrowserMediaPlayerManager::OnPause(
MediaPlayerAndroid* player = GetPlayer(player_id);
if (player)
player->Pause(is_media_related_action);
-
- if (is_media_related_action && !IsPlayingRemotely(player_id))
- MediaSession::Get(web_contents())->OnPlayerPaused(this, player_id);
}
void BrowserMediaPlayerManager::OnSetVolume(int player_id, double volume) {
@@ -622,7 +584,6 @@ void BrowserMediaPlayerManager::OnSetPoster(int player_id, const GURL& url) {
}
void BrowserMediaPlayerManager::OnSuspendAndReleaseResources(int player_id) {
- MediaSession::Get(web_contents())->RemovePlayer(this, player_id);
ReleaseResources(player_id);
}
@@ -645,9 +606,12 @@ bool BrowserMediaPlayerManager::IsPlayingRemotely(int player_id) {
return false;
}
-void BrowserMediaPlayerManager::AddPlayer(MediaPlayerAndroid* player) {
+void BrowserMediaPlayerManager::AddPlayer(
+ MediaPlayerAndroid* player, int delegate_id) {
DCHECK(!GetPlayer(player->player_id()));
players_.push_back(player);
+ player_id_to_delegate_id_map_[player->player_id()] =
+ delegate_id;
}
void BrowserMediaPlayerManager::DestroyPlayer(int player_id) {
@@ -659,11 +623,11 @@ void BrowserMediaPlayerManager::DestroyPlayer(int player_id) {
#endif
(*it)->DeleteOnCorrectThread();
players_.weak_erase(it);
- MediaSession::Get(web_contents())->RemovePlayer(this, player_id);
break;
}
}
active_players_.erase(player_id);
+ player_id_to_delegate_id_map_.erase(player_id);
}
void BrowserMediaPlayerManager::ReleaseResources(int player_id) {
@@ -674,8 +638,9 @@ void BrowserMediaPlayerManager::ReleaseResources(int player_id) {
fullscreen_player_is_released_ = true;
}
-scoped_ptr<media::MediaPlayerAndroid> BrowserMediaPlayerManager::SwapPlayer(
- int player_id, media::MediaPlayerAndroid* player) {
+std::unique_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) {
@@ -684,12 +649,15 @@ scoped_ptr<media::MediaPlayerAndroid> BrowserMediaPlayerManager::SwapPlayer(
#if defined(VIDEO_HOLE)
ReleaseExternalSurface(player_id);
#endif
+ MediaWebContentsObserverAndroid::FromWebContents(web_contents_)
+ ->DisconnectMediaSession(render_frame_host_,
+ player_id_to_delegate_id_map_[player_id]);
players_.weak_erase(it);
players_.push_back(player);
break;
}
}
- return scoped_ptr<media::MediaPlayerAndroid>(previous_player);
+ return std::unique_ptr<media::MediaPlayerAndroid>(previous_player);
}
bool BrowserMediaPlayerManager::RequestDecoderResources(
diff --git a/chromium/content/browser/media/android/browser_media_player_manager.h b/chromium/content/browser/media/android/browser_media_player_manager.h
index 990d5e1f3c4..8bacb71b9d0 100644
--- a/chromium/content/browser/media/android/browser_media_player_manager.h
+++ b/chromium/content/browser/media/android/browser_media_player_manager.h
@@ -6,20 +6,20 @@
#define CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_MEDIA_PLAYER_MANAGER_H_
#include <map>
+#include <memory>
#include "base/callback.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/time/time.h"
#include "content/browser/android/content_video_view.h"
-#include "content/browser/media/android/media_session_observer.h"
#include "content/common/content_export.h"
#include "ipc/ipc_message.h"
#include "media/base/android/media_player_android.h"
#include "media/base/android/media_player_manager.h"
#include "media/base/android/media_url_interceptor.h"
#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gl/android/scoped_java_surface.h"
#include "url/gurl.h"
namespace media {
@@ -44,7 +44,7 @@ class WebContents;
// process.
class CONTENT_EXPORT BrowserMediaPlayerManager
: public media::MediaPlayerManager,
- public MediaSessionObserver {
+ public ContentVideoView::Client {
public:
// Permits embedders to provide an extended version of the class.
typedef BrowserMediaPlayerManager* (*Factory)(RenderFrameHost*);
@@ -70,17 +70,14 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
~BrowserMediaPlayerManager() override;
- // Fullscreen video playback controls.
- virtual void ExitFullscreen(bool release_media_player);
- virtual void SetVideoSurface(gfx::ScopedJavaSurface surface);
+ // ContentVideoView::Client implementation.
+ void DidExitFullscreen(bool release_media_player) override;
+ void SetVideoSurface(gfx::ScopedJavaSurface surface) override;
// Called when browser player wants the renderer media element to seek.
// Any actual seek started by renderer will be handled by browser in OnSeek().
void OnSeekRequest(int player_id, const base::TimeDelta& time_to_seek);
- // Stops and releases every media managed by this class.
- void ReleaseAllMediaPlayers();
-
// media::MediaPlayerManager overrides.
void OnTimeUpdate(int player_id,
base::TimeDelta current_timestamp,
@@ -111,10 +108,6 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
void OnFrameInfoUpdated();
#endif // defined(VIDEO_HOLE)
- // MediaSessionObserver overrides.
- void OnSuspend(int player_id) override;
- void OnResume(int player_id) override;
-
// Message handlers.
virtual void OnEnterFullscreen(int player_id);
virtual void OnInitialize(
@@ -142,8 +135,9 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
WebContents* web_contents() const { return web_contents_; }
- // Adds a given player to the list.
- void AddPlayer(media::MediaPlayerAndroid* player);
+ // Adds a given player to the list. Not private to allow embedders
+ // to extend the manager and still utilize the base player management.
+ void AddPlayer(media::MediaPlayerAndroid* player, int delegate_id);
// Removes the player with the specified id.
void DestroyPlayer(int player_id);
@@ -154,7 +148,7 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
// 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(
+ std::unique_ptr<media::MediaPlayerAndroid> SwapPlayer(
int player_id,
media::MediaPlayerAndroid* player);
@@ -214,10 +208,11 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
// The fullscreen video view object or NULL if video is not played in
// fullscreen.
- scoped_ptr<ContentVideoView> video_view_;
+ std::unique_ptr<ContentVideoView> video_view_;
#if defined(VIDEO_HOLE)
- scoped_ptr<ExternalVideoSurfaceContainer> external_video_surface_container_;
+ std::unique_ptr<ExternalVideoSurfaceContainer>
+ external_video_surface_container_;
#endif
// Player ID of the fullscreen media player.
@@ -229,7 +224,11 @@ class CONTENT_EXPORT BrowserMediaPlayerManager
WebContents* const web_contents_;
// Object for retrieving resources media players.
- scoped_ptr<media::MediaResourceGetter> media_resource_getter_;
+ std::unique_ptr<media::MediaResourceGetter> media_resource_getter_;
+
+ // Map of player IDs to delegate IDs for use with
+ // MediaWebContentsObserverAndroid.
+ std::map<int, int> player_id_to_delegate_id_map_;
// NOTE: Weak pointers must be invalidated before all other member variables.
base::WeakPtrFactory<BrowserMediaPlayerManager> weak_ptr_factory_;
diff --git a/chromium/content/browser/media/android/browser_media_session_manager.cc b/chromium/content/browser/media/android/browser_media_session_manager.cc
index 146a60fe970..a7e5fd5bbfa 100644
--- a/chromium/content/browser/media/android/browser_media_session_manager.cc
+++ b/chromium/content/browser/media/android/browser_media_session_manager.cc
@@ -6,6 +6,8 @@
#include "content/common/media/media_session_messages_android.h"
#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/common/media_metadata.h"
namespace content {
@@ -23,6 +25,27 @@ void BrowserMediaSessionManager::OnDeactivate(int session_id, int request_id) {
Send(new MediaSessionMsg_DidDeactivate(GetRoutingID(), request_id));
}
+void BrowserMediaSessionManager::OnSetMetadata(
+ int session_id,
+ const MediaMetadata& insecure_metadata) {
+ // When receiving a MediaMetadata, the browser process can't trust that it is
+ // coming from a known and secure source. It must be processed accordingly.
+ MediaMetadata metadata;
+ metadata.title =
+ insecure_metadata.title.substr(0, MediaMetadata::kMaxIPCStringLength);
+ metadata.artist =
+ insecure_metadata.artist.substr(0, MediaMetadata::kMaxIPCStringLength);
+ metadata.album =
+ insecure_metadata.album.substr(0, MediaMetadata::kMaxIPCStringLength);
+
+ if (metadata != insecure_metadata) {
+ render_frame_host_->GetProcess()->ShutdownForBadMessage();
+ return;
+ }
+
+ NOTIMPLEMENTED();
+}
+
int BrowserMediaSessionManager::GetRoutingID() const {
return render_frame_host_->GetRoutingID();
}
diff --git a/chromium/content/browser/media/android/browser_media_session_manager.h b/chromium/content/browser/media/android/browser_media_session_manager.h
index 3b07b295816..b936ba03e55 100644
--- a/chromium/content/browser/media/android/browser_media_session_manager.h
+++ b/chromium/content/browser/media/android/browser_media_session_manager.h
@@ -14,6 +14,7 @@ class Message;
namespace content {
class RenderFrameHost;
+struct MediaMetadata;
class BrowserMediaSessionManager {
public:
@@ -22,6 +23,7 @@ class BrowserMediaSessionManager {
// Message handlers.
void OnActivate(int session_id, int request_id);
void OnDeactivate(int session_id, int request_id);
+ void OnSetMetadata(int session_id, const MediaMetadata& metadata);
int GetRoutingID() const;
diff --git a/chromium/content/browser/media/android/browser_surface_view_manager.cc b/chromium/content/browser/media/android/browser_surface_view_manager.cc
new file mode 100644
index 00000000000..f171a169944
--- /dev/null
+++ b/chromium/content/browser/media/android/browser_surface_view_manager.cc
@@ -0,0 +1,86 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/android/browser_surface_view_manager.h"
+
+#include "content/browser/android/child_process_launcher_android.h"
+#include "content/browser/android/content_view_core_impl.h"
+#include "content/browser/gpu/gpu_surface_tracker.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/media/surface_view_manager_messages_android.h"
+#include "content/public/browser/render_frame_host.h"
+#include "media/base/surface_manager.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace content {
+
+BrowserSurfaceViewManager::BrowserSurfaceViewManager(
+ RenderFrameHost* render_frame_host)
+ : render_frame_host_(render_frame_host),
+ surface_id_(media::SurfaceManager::kNoSurfaceID) {}
+
+BrowserSurfaceViewManager::~BrowserSurfaceViewManager() {}
+
+void BrowserSurfaceViewManager::SetVideoSurface(
+ gfx::ScopedJavaSurface surface) {
+ if (surface.IsEmpty()) {
+ DCHECK_NE(surface_id_, media::SurfaceManager::kNoSurfaceID);
+ GpuSurfaceTracker::Get()->RemoveSurface(surface_id_);
+ UnregisterViewSurface(surface_id_);
+ surface_id_ = media::SurfaceManager::kNoSurfaceID;
+ } else {
+ // We mainly use the surface tracker to allocate a surface id for us. The
+ // lookup will go through the Android specific path and get the java
+ // surface directly, so there's no need to add a valid native widget here.
+ surface_id_ = GpuSurfaceTracker::Get()->AddSurfaceForNativeWidget(
+ gfx::kNullAcceleratedWidget);
+ RegisterViewSurface(surface_id_, surface.j_surface().obj());
+ SendSurfaceID(surface_id_);
+ }
+}
+
+void BrowserSurfaceViewManager::DidExitFullscreen(bool release_media_player) {
+ DVLOG(3) << __FUNCTION__;
+ content_video_view_.reset();
+}
+
+void BrowserSurfaceViewManager::OnCreateFullscreenSurface(
+ const gfx::Size& video_natural_size) {
+ // It's valid to get this call if we already own the fullscreen view. We just
+ // return the existing surface id.
+ if (content_video_view_) {
+ // Send the surface now if we have it. Otherwise it will be returned by
+ // |SetVideoSurface|.
+ if (surface_id_ != media::SurfaceManager::kNoSurfaceID) {
+ SendSurfaceID(surface_id_);
+ OnNaturalSizeChanged(video_natural_size);
+ return;
+ }
+ }
+
+ // If we don't own the fullscreen view, but one exists, it means another
+ // WebContents has it. Ignore this request and return a null surface id.
+ if (ContentVideoView::GetInstance()) {
+ SendSurfaceID(media::SurfaceManager::kNoSurfaceID);
+ return;
+ }
+
+ ContentViewCore* cvc = ContentViewCore::FromWebContents(
+ WebContents::FromRenderFrameHost(render_frame_host_));
+ content_video_view_.reset(new ContentVideoView(this, cvc));
+ OnNaturalSizeChanged(video_natural_size);
+}
+
+void BrowserSurfaceViewManager::OnNaturalSizeChanged(const gfx::Size& size) {
+ if (content_video_view_)
+ content_video_view_->OnVideoSizeChanged(size.width(), size.height());
+}
+
+bool BrowserSurfaceViewManager::SendSurfaceID(int surface_id) {
+ return render_frame_host_->Send(
+ new SurfaceViewManagerMsg_FullscreenSurfaceCreated(
+ render_frame_host_->GetRoutingID(), surface_id));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/android/browser_surface_view_manager.h b/chromium/content/browser/media/android/browser_surface_view_manager.h
new file mode 100644
index 00000000000..2bff709c034
--- /dev/null
+++ b/chromium/content/browser/media/android/browser_surface_view_manager.h
@@ -0,0 +1,54 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_SURFACE_VIEW_MANAGER_H_
+#define CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_SURFACE_VIEW_MANAGER_H_
+
+#include <stdint.h>
+
+#include <memory>
+
+#include "base/macros.h"
+#include "content/browser/android/content_video_view.h"
+#include "content/common/content_export.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace content {
+
+class RenderFrameHost;
+
+// BrowserSurfaceViewManager creates and owns a ContentVideoView on behalf of
+// a fullscreen media player. Its SurfaceView is registered so that a decoder
+// in the GPU process can look it up and render to it.
+class CONTENT_EXPORT BrowserSurfaceViewManager
+ : public ContentVideoView::Client {
+ public:
+ explicit BrowserSurfaceViewManager(RenderFrameHost* render_frame_host);
+ ~BrowserSurfaceViewManager();
+
+ // ContentVideoView::Client overrides.
+ void SetVideoSurface(gfx::ScopedJavaSurface surface) override;
+ void DidExitFullscreen(bool release_media_player) override;
+
+ void OnCreateFullscreenSurface(const gfx::Size& video_natural_size);
+ void OnNaturalSizeChanged(const gfx::Size& size);
+
+ private:
+ // Send a message to return the surface id to the caller.
+ bool SendSurfaceID(int surface_id);
+
+ RenderFrameHost* const render_frame_host_;
+
+ // The surface id of the ContentVideoView surface.
+ int surface_id_;
+
+ // The fullscreen view that contains a SurfaceView.
+ std::unique_ptr<ContentVideoView> content_video_view_;
+
+ DISALLOW_COPY_AND_ASSIGN(BrowserSurfaceViewManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_ANDROID_BROWSER_SURFACE_VIEW_MANAGER_H_
diff --git a/chromium/content/browser/media/android/media_resource_getter_impl.cc b/chromium/content/browser/media/android/media_resource_getter_impl.cc
index e0d6aff5129..473c5327ff2 100644
--- a/chromium/content/browser/media/android/media_resource_getter_impl.cc
+++ b/chromium/content/browser/media/android/media_resource_getter_impl.cc
@@ -54,7 +54,7 @@ static void RequestPlatformPathFromBlobURL(
ChromeBlobStorageContext* blob_storage_context =
GetChromeBlobStorageContextForResourceContext(resource_context);
- scoped_ptr<storage::BlobDataHandle> handle =
+ std::unique_ptr<storage::BlobDataHandle> handle =
blob_storage_context->context()->GetBlobDataFromPublicURL(url);
if (!handle) {
// There are plenty of cases where handle can be empty. The most trivial is
@@ -62,7 +62,7 @@ static void RequestPlatformPathFromBlobURL(
ReturnResultOnUIThread(callback, std::string());
return;
}
- scoped_ptr<storage::BlobDataSnapshot> data = handle->CreateSnapshot();
+ std::unique_ptr<storage::BlobDataSnapshot> data = handle->CreateSnapshot();
if (!data) {
ReturnResultOnUIThread(callback, std::string());
NOTREACHED();
diff --git a/chromium/content/browser/media/android/media_session.h b/chromium/content/browser/media/android/media_session.h
deleted file mode 100644
index fa727b0b049..00000000000
--- a/chromium/content/browser/media/android/media_session.h
+++ /dev/null
@@ -1,181 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_MEDIA_ANDROID_MEDIA_SESSION_H_
-#define CONTENT_BROWSER_MEDIA_ANDROID_MEDIA_SESSION_H_
-
-#include <jni.h>
-#include <stddef.h>
-
-#include "base/android/scoped_java_ref.h"
-#include "base/id_map.h"
-#include "base/macros.h"
-#include "content/browser/media/android/media_session_uma_helper.h"
-#include "content/common/content_export.h"
-#include "content/public/browser/web_contents_observer.h"
-#include "content/public/browser/web_contents_user_data.h"
-
-class MediaSessionBrowserTest;
-
-namespace content {
-
-class MediaSessionObserver;
-
-// MediaSession manages the Android AudioFocus for a given WebContents. It is
-// requesting the audio focus, pausing when requested by the system and dropping
-// it on demand.
-// The audio focus can be of two types: Transient or Content. A Transient audio
-// focus will allow other players to duck instead of pausing and will be
-// declared as temporary to the system. A Content audio focus will not be
-// declared as temporary and will not allow other players to duck. If a given
-// WebContents can only have one audio focus at a time, it will be Content in
-// case of Transient and Content audio focus are both requested.
-// Android system interaction occurs in the Java counterpart to this class.
-class CONTENT_EXPORT MediaSession
- : public WebContentsObserver,
- protected WebContentsUserData<MediaSession> {
- public:
- enum class Type {
- Content,
- Transient
- };
-
- static bool RegisterMediaSession(JNIEnv* env);
-
- // Returns the MediaSession associated to this WebContents. Creates one if
- // none is currently available.
- static MediaSession* Get(WebContents* web_contents);
-
- ~MediaSession() override;
-
- // Adds the given player to the current media session. Returns whether the
- // player was successfully added. If it returns false, AddPlayer() should be
- // called again later.
- bool AddPlayer(MediaSessionObserver* observer, int player_id, Type type);
-
- // Removes the given player from the current media session. Abandons audio
- // focus if that was the last player in the session.
- void RemovePlayer(MediaSessionObserver* observer, int player_id);
-
- // Removes all the players associated with |observer|. Abandons audio focus if
- // these were the last players in the session.
- void RemovePlayers(MediaSessionObserver* observer);
-
- // Called when the Android system requests the MediaSession to be suspended.
- // Called by Java through JNI.
- void OnSuspend(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& obj,
- jboolean temporary);
-
- // Called when the Android system requests the MediaSession to be resumed.
- // Called by Java through JNI.
- void OnResume(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
-
- // Called when a player is paused in the content.
- // If the paused player is the last player, we suspend the MediaSession.
- // Otherwise, the paused player will be removed from the MediaSession.
- void OnPlayerPaused(MediaSessionObserver* observer, int player_id);
-
- // Called when the user requests resuming the session. No-op if the session is
- // not controllable.
- void Resume();
-
- // Called when the user requests suspending the session. No-op if the session
- // is not controllable.
- void Suspend();
-
- // Called when the user requests stopping the session.
- void Stop();
-
- // Returns if the session can be controlled by Resume() and Suspend calls
- // above.
- bool IsControllable() const;
-
- // Returns if the session is currently suspended.
- bool IsSuspended() const;
-
- private:
- friend class content::WebContentsUserData<MediaSession>;
- friend class ::MediaSessionBrowserTest;
-
- // Resets the |j_media_session_| ref to prevent calling the Java backend
- // during content_browsertests.
- void ResetJavaRefForTest();
- bool IsActiveForTest() const;
- Type audio_focus_type_for_test() const;
- void RemoveAllPlayersForTest();
- MediaSessionUmaHelper* uma_helper_for_test();
-
- enum class State {
- ACTIVE,
- SUSPENDED,
- INACTIVE
- };
-
- enum class SuspendType {
- // Suspended by the system because a transient sound needs to be played.
- SYSTEM,
- // Suspended by the UI.
- UI,
- // Suspended by the page via script or user interaction.
- CONTENT,
- };
-
- // Representation of a player for the MediaSession.
- struct PlayerIdentifier {
- PlayerIdentifier(MediaSessionObserver* observer, int player_id);
- PlayerIdentifier(const PlayerIdentifier&) = default;
-
- void operator=(const PlayerIdentifier&) = delete;
- bool operator==(const PlayerIdentifier& player_identifier) const;
-
- // Hash operator for base::hash_map<>.
- struct Hash {
- size_t operator()(const PlayerIdentifier& player_identifier) const;
- };
-
- MediaSessionObserver* observer;
- int player_id;
- };
- using PlayersMap = base::hash_set<PlayerIdentifier, PlayerIdentifier::Hash>;
-
- explicit MediaSession(WebContents* web_contents);
-
- // Setup the JNI.
- void Initialize();
-
- void OnSuspendInternal(SuspendType type, State new_state);
- void OnResumeInternal(SuspendType type);
-
- // Requests audio focus to Android using |j_media_session_|.
- // Returns whether the request was granted. If |j_media_session_| is null, it
- // will always return true.
- bool RequestSystemAudioFocus(Type type);
-
- // To be called after a call to AbandonAudioFocus() in order to call the Java
- // MediaSession if the audio focus really need to be abandoned.
- void AbandonSystemAudioFocusIfNeeded();
-
- // Notifies WebContents about the state change of the media session.
- void UpdateWebContents();
-
- // Internal method that should be used instead of setting audio_focus_state_.
- // It sets audio_focus_state_ and notifies observers about the state change.
- void SetAudioFocusState(State audio_focus_state);
-
- base::android::ScopedJavaGlobalRef<jobject> j_media_session_;
- PlayersMap players_;
-
- State audio_focus_state_;
- SuspendType suspend_type_;
- Type audio_focus_type_;
-
- MediaSessionUmaHelper uma_helper_;
-
- DISALLOW_COPY_AND_ASSIGN(MediaSession);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_MEDIA_ANDROID_MEDIA_SESSION_H_
diff --git a/chromium/content/browser/media/android/media_web_contents_observer_android.cc b/chromium/content/browser/media/android/media_web_contents_observer_android.cc
index 1b48959e9ba..5a6c451f13a 100644
--- a/chromium/content/browser/media/android/media_web_contents_observer_android.cc
+++ b/chromium/content/browser/media/android/media_web_contents_observer_android.cc
@@ -4,13 +4,16 @@
#include "content/browser/media/android/media_web_contents_observer_android.h"
+#include "base/memory/ptr_util.h"
#include "content/browser/media/android/browser_media_player_manager.h"
#include "content/browser/media/android/browser_media_session_manager.h"
-#include "content/browser/media/android/media_session_observer.h"
+#include "content/browser/media/android/browser_surface_view_manager.h"
#include "content/browser/media/cdm/browser_cdm_manager.h"
#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/media/media_player_delegate_messages.h"
#include "content/common/media/media_player_messages_android.h"
#include "content/common/media/media_session_messages_android.h"
+#include "content/common/media/surface_view_manager_messages_android.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "ipc/ipc_message_macros.h"
@@ -18,6 +21,12 @@
namespace content {
+static void SuspendAllMediaPlayersInRenderFrame(
+ RenderFrameHost* render_frame_host) {
+ render_frame_host->Send(new MediaPlayerDelegateMsg_SuspendAllMediaPlayers(
+ render_frame_host->GetRoutingID()));
+}
+
MediaWebContentsObserverAndroid::MediaWebContentsObserverAndroid(
WebContents* web_contents)
: MediaWebContentsObserver(web_contents) {}
@@ -41,7 +50,7 @@ MediaWebContentsObserverAndroid::GetMediaPlayerManager(
BrowserMediaPlayerManager* manager =
BrowserMediaPlayerManager::Create(render_frame_host);
- media_player_managers_.set(render_frame_host, make_scoped_ptr(manager));
+ media_player_managers_.set(render_frame_host, base::WrapUnique(manager));
return manager;
}
@@ -54,10 +63,46 @@ MediaWebContentsObserverAndroid::GetMediaSessionManager(
BrowserMediaSessionManager* manager =
new BrowserMediaSessionManager(render_frame_host);
- media_session_managers_.set(render_frame_host, make_scoped_ptr(manager));
+ media_session_managers_.set(render_frame_host, base::WrapUnique(manager));
return manager;
}
+BrowserSurfaceViewManager*
+MediaWebContentsObserverAndroid::GetSurfaceViewManager(
+ RenderFrameHost* render_frame_host) {
+ auto it = surface_view_managers_.find(render_frame_host);
+ if (it != surface_view_managers_.end())
+ return it->second;
+
+ BrowserSurfaceViewManager* manager =
+ new BrowserSurfaceViewManager(render_frame_host);
+ surface_view_managers_.set(render_frame_host, base::WrapUnique(manager));
+ return manager;
+}
+
+void MediaWebContentsObserverAndroid::SuspendAllMediaPlayers() {
+ web_contents()->ForEachFrame(
+ base::Bind(&SuspendAllMediaPlayersInRenderFrame));
+}
+
+bool MediaWebContentsObserverAndroid::RequestPlay(
+ RenderFrameHost* render_frame_host,
+ int delegate_id,
+ bool has_audio,
+ bool is_remote,
+ base::TimeDelta duration) {
+ return session_controllers_manager()->RequestPlay(
+ MediaPlayerId(render_frame_host, delegate_id),
+ has_audio, is_remote, duration);
+}
+
+void MediaWebContentsObserverAndroid::DisconnectMediaSession(
+ RenderFrameHost* render_frame_host,
+ int delegate_id) {
+ session_controllers_manager()->OnEnd(
+ MediaPlayerId(render_frame_host, delegate_id));
+}
+
#if defined(VIDEO_HOLE)
void MediaWebContentsObserverAndroid::OnFrameInfoUpdated() {
for (auto it = media_player_managers_.begin();
@@ -75,6 +120,7 @@ void MediaWebContentsObserverAndroid::RenderFrameDeleted(
// detaching CDMs from media players yet. See http://crbug.com/330324
media_player_managers_.erase(render_frame_host);
media_session_managers_.erase(render_frame_host);
+ surface_view_managers_.erase(render_frame_host);
// TODO(xhwang): Currently MediaWebContentsObserver, BrowserMediaPlayerManager
// and BrowserCdmManager all run on browser UI thread. So this call is okay.
@@ -96,7 +142,16 @@ bool MediaWebContentsObserverAndroid::OnMessageReceived(
if (OnMediaPlayerMessageReceived(msg, render_frame_host))
return true;
- return OnMediaPlayerSetCdmMessageReceived(msg, render_frame_host);
+ if (OnMediaPlayerSetCdmMessageReceived(msg, render_frame_host))
+ return true;
+
+ if (OnMediaSessionMessageReceived(msg, render_frame_host))
+ return true;
+
+ if (OnSurfaceViewManagerMessageReceived(msg, render_frame_host))
+ return true;
+
+ return false;
}
bool MediaWebContentsObserverAndroid::OnMediaPlayerMessageReceived(
@@ -143,24 +198,55 @@ bool MediaWebContentsObserverAndroid::OnMediaPlayerMessageReceived(
GetMediaPlayerManager(render_frame_host),
BrowserMediaPlayerManager::OnNotifyExternalSurface)
#endif // defined(VIDEO_HOLE)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+bool MediaWebContentsObserverAndroid::OnMediaPlayerSetCdmMessageReceived(
+ const IPC::Message& msg,
+ RenderFrameHost* render_frame_host) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(MediaWebContentsObserverAndroid, msg,
+ render_frame_host)
+ IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_SetCdm, OnSetCdm)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+bool MediaWebContentsObserverAndroid::OnMediaSessionMessageReceived(
+ const IPC::Message& msg,
+ RenderFrameHost* render_frame_host) {
+ bool handled = true;
+
+ IPC_BEGIN_MESSAGE_MAP(MediaWebContentsObserver, msg)
IPC_MESSAGE_FORWARD(MediaSessionHostMsg_Activate,
GetMediaSessionManager(render_frame_host),
BrowserMediaSessionManager::OnActivate)
IPC_MESSAGE_FORWARD(MediaSessionHostMsg_Deactivate,
GetMediaSessionManager(render_frame_host),
BrowserMediaSessionManager::OnDeactivate)
+ IPC_MESSAGE_FORWARD(MediaSessionHostMsg_SetMetadata,
+ GetMediaSessionManager(render_frame_host),
+ BrowserMediaSessionManager::OnSetMetadata)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
+
return handled;
}
-bool MediaWebContentsObserverAndroid::OnMediaPlayerSetCdmMessageReceived(
+bool MediaWebContentsObserverAndroid::OnSurfaceViewManagerMessageReceived(
const IPC::Message& msg,
RenderFrameHost* render_frame_host) {
bool handled = true;
- IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(MediaWebContentsObserverAndroid, msg,
- render_frame_host)
- IPC_MESSAGE_HANDLER(MediaPlayerHostMsg_SetCdm, OnSetCdm)
+ IPC_BEGIN_MESSAGE_MAP(MediaWebContentsObserverAndroid, msg)
+ IPC_MESSAGE_FORWARD(SurfaceViewManagerHostMsg_CreateFullscreenSurface,
+ GetSurfaceViewManager(render_frame_host),
+ BrowserSurfaceViewManager::OnCreateFullscreenSurface)
+ IPC_MESSAGE_FORWARD(SurfaceViewManagerHostMsg_NaturalSizeChanged,
+ GetSurfaceViewManager(render_frame_host),
+ BrowserSurfaceViewManager::OnNaturalSizeChanged)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
diff --git a/chromium/content/browser/media/android/media_web_contents_observer_android.h b/chromium/content/browser/media/android/media_web_contents_observer_android.h
index a95e1615fb6..0f3a2a9bd14 100644
--- a/chromium/content/browser/media/android/media_web_contents_observer_android.h
+++ b/chromium/content/browser/media/android/media_web_contents_observer_android.h
@@ -7,9 +7,10 @@
#include <stdint.h>
+#include <memory>
+
#include "base/containers/scoped_ptr_hash_map.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "content/browser/media/media_web_contents_observer.h"
#include "content/common/content_export.h"
@@ -18,6 +19,7 @@ namespace content {
class BrowserCdmManager;
class BrowserMediaPlayerManager;
class BrowserMediaSessionManager;
+class BrowserSurfaceViewManager;
// This class adds Android specific extensions to the MediaWebContentsObserver.
class CONTENT_EXPORT MediaWebContentsObserverAndroid
@@ -30,19 +32,40 @@ class CONTENT_EXPORT MediaWebContentsObserverAndroid
static MediaWebContentsObserverAndroid* FromWebContents(
WebContents* web_contents);
- // Gets the media player or media session manager associated with the given
- // |render_frame_host| respectively. Creates a new one if it doesn't exist.
- // The caller doesn't own the returned pointer.
+ // Gets one of the managers associated with the given |render_frame_host|.
+ // Creates a new one if it doesn't exist. The caller doesn't own the
+ // returned pointer.
BrowserMediaPlayerManager* GetMediaPlayerManager(
RenderFrameHost* render_frame_host);
BrowserMediaSessionManager* GetMediaSessionManager(
RenderFrameHost* render_frame_host);
+ BrowserSurfaceViewManager* GetSurfaceViewManager(
+ RenderFrameHost* render_frame_host);
+
+ // Called by the WebContents when a tab has been closed but may still be
+ // available for "undo" -- indicates that all media players (even audio only
+ // players typically allowed background audio) bound to this WebContents must
+ // be suspended.
+ void SuspendAllMediaPlayers();
+
+ // Initiates a synchronous MediaSession request for browser side players.
+ //
+ // TODO(dalecurtis): Delete this method once we're no longer using WMPA and
+ // the BrowserMediaPlayerManagers. Tracked by http://crbug.com/580626
+ bool RequestPlay(RenderFrameHost* render_frame_host,
+ int delegate_id,
+ bool has_audio,
+ bool is_remote,
+ base::TimeDelta duration);
+
+ void DisconnectMediaSession(RenderFrameHost* render_frame_host,
+ int delegate_id);
#if defined(VIDEO_HOLE)
void OnFrameInfoUpdated();
#endif // defined(VIDEO_HOLE)
- // MediaWebContentsObserverAndroid overrides.
+ // MediaWebContentsObserver overrides.
void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
bool OnMessageReceived(const IPC::Message& message,
RenderFrameHost* render_frame_host) override;
@@ -56,20 +79,31 @@ class CONTENT_EXPORT MediaWebContentsObserverAndroid
bool OnMediaPlayerSetCdmMessageReceived(const IPC::Message& message,
RenderFrameHost* render_frame_host);
+ bool OnMediaSessionMessageReceived(const IPC::Message& message,
+ RenderFrameHost* render_frame_host);
+
+ bool OnSurfaceViewManagerMessageReceived(const IPC::Message& message,
+ RenderFrameHost* render_frame_host);
+
void OnSetCdm(RenderFrameHost* render_frame_host, int player_id, int cdm_id);
// Map from RenderFrameHost* to BrowserMediaPlayerManager.
using MediaPlayerManagerMap =
base::ScopedPtrHashMap<RenderFrameHost*,
- scoped_ptr<BrowserMediaPlayerManager>>;
+ std::unique_ptr<BrowserMediaPlayerManager>>;
MediaPlayerManagerMap media_player_managers_;
// Map from RenderFrameHost* to BrowserMediaSessionManager.
using MediaSessionManagerMap =
base::ScopedPtrHashMap<RenderFrameHost*,
- scoped_ptr<BrowserMediaSessionManager>>;
+ std::unique_ptr<BrowserMediaSessionManager>>;
MediaSessionManagerMap media_session_managers_;
+ using SurfaceViewManagerMap =
+ base::ScopedPtrHashMap<RenderFrameHost*,
+ std::unique_ptr<BrowserSurfaceViewManager>>;
+ SurfaceViewManagerMap surface_view_managers_;
+
DISALLOW_COPY_AND_ASSIGN(MediaWebContentsObserverAndroid);
};
diff --git a/chromium/content/browser/media/android/provision_fetcher_impl.cc b/chromium/content/browser/media/android/provision_fetcher_impl.cc
index 8e9f689d5e2..6ca51d7c417 100644
--- a/chromium/content/browser/media/android/provision_fetcher_impl.cc
+++ b/chromium/content/browser/media/android/provision_fetcher_impl.cc
@@ -26,7 +26,7 @@ void ProvisionFetcherImpl::Create(
}
ProvisionFetcherImpl::ProvisionFetcherImpl(
- scoped_ptr<media::ProvisionFetcher> provision_fetcher,
+ std::unique_ptr<media::ProvisionFetcher> provision_fetcher,
mojo::InterfaceRequest<ProvisionFetcher> request)
: binding_(this, std::move(request)),
provision_fetcher_(std::move(provision_fetcher)),
diff --git a/chromium/content/browser/media/android/provision_fetcher_impl.h b/chromium/content/browser/media/android/provision_fetcher_impl.h
index 3f009fb89d6..38ae9cb27bd 100644
--- a/chromium/content/browser/media/android/provision_fetcher_impl.h
+++ b/chromium/content/browser/media/android/provision_fetcher_impl.h
@@ -5,8 +5,9 @@
#ifndef CONTENT_BROWSER_MEDIA_ANDROID_PROVISION_FETCHER_IMPL_H_
#define CONTENT_BROWSER_MEDIA_ANDROID_PROVISION_FETCHER_IMPL_H_
+#include <memory>
+
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/public/browser/android/provision_fetcher_factory.h"
#include "media/base/android/provision_fetcher.h"
@@ -25,8 +26,9 @@ class ProvisionFetcherImpl : public media::interfaces::ProvisionFetcher {
RenderFrameHost* render_frame_host,
mojo::InterfaceRequest<media::interfaces::ProvisionFetcher> request);
- ProvisionFetcherImpl(scoped_ptr<media::ProvisionFetcher> provision_fetcher,
- mojo::InterfaceRequest<ProvisionFetcher> request);
+ ProvisionFetcherImpl(
+ std::unique_ptr<media::ProvisionFetcher> provision_fetcher,
+ mojo::InterfaceRequest<ProvisionFetcher> request);
~ProvisionFetcherImpl() override;
// media::interfaces::ProvisionFetcher implementation.
@@ -41,7 +43,7 @@ class ProvisionFetcherImpl : public media::interfaces::ProvisionFetcher {
const std::string& response);
mojo::StrongBinding<media::interfaces::ProvisionFetcher> binding_;
- scoped_ptr<media::ProvisionFetcher> provision_fetcher_;
+ std::unique_ptr<media::ProvisionFetcher> provision_fetcher_;
base::WeakPtrFactory<ProvisionFetcherImpl> weak_factory_;
diff --git a/chromium/content/browser/media/android/url_provision_fetcher.cc b/chromium/content/browser/media/android/url_provision_fetcher.cc
index 7607480c933..83a34b7ba82 100644
--- a/chromium/content/browser/media/android/url_provision_fetcher.cc
+++ b/chromium/content/browser/media/android/url_provision_fetcher.cc
@@ -4,6 +4,7 @@
#include "content/browser/media/android/url_provision_fetcher.h"
+#include "base/memory/ptr_util.h"
#include "content/public/browser/android/provision_fetcher_factory.h"
#include "media/base/bind_to_current_loop.h"
#include "net/url_request/url_fetcher.h"
@@ -68,10 +69,10 @@ void URLProvisionFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
// Implementation of content public method CreateProvisionFetcher().
-scoped_ptr<media::ProvisionFetcher> CreateProvisionFetcher(
+std::unique_ptr<media::ProvisionFetcher> CreateProvisionFetcher(
net::URLRequestContextGetter* context_getter) {
DCHECK(context_getter);
- return make_scoped_ptr(new URLProvisionFetcher(context_getter));
+ return base::WrapUnique(new URLProvisionFetcher(context_getter));
}
} // namespace content
diff --git a/chromium/content/browser/media/android/url_provision_fetcher.h b/chromium/content/browser/media/android/url_provision_fetcher.h
index 7e3d1397e65..b551c3b0345 100644
--- a/chromium/content/browser/media/android/url_provision_fetcher.h
+++ b/chromium/content/browser/media/android/url_provision_fetcher.h
@@ -30,7 +30,7 @@ class URLProvisionFetcher : public media::ProvisionFetcher,
void OnURLFetchComplete(const net::URLFetcher* source) override;
net::URLRequestContextGetter* context_getter_;
- scoped_ptr<net::URLFetcher> request_;
+ std::unique_ptr<net::URLFetcher> request_;
media::ProvisionFetcher::ResponseCB response_cb_;
DISALLOW_COPY_AND_ASSIGN(URLProvisionFetcher);
diff --git a/chromium/content/browser/media/audible_metrics.cc b/chromium/content/browser/media/audible_metrics.cc
index 4a740288e79..3c17cccfd4c 100644
--- a/chromium/content/browser/media/audible_metrics.cc
+++ b/chromium/content/browser/media/audible_metrics.cc
@@ -31,7 +31,8 @@ void AudibleMetrics::UpdateAudibleWebContentsState(
RemoveAudibleWebContents(web_contents);
}
-void AudibleMetrics::SetClockForTest(scoped_ptr<base::TickClock> test_clock) {
+void AudibleMetrics::SetClockForTest(
+ std::unique_ptr<base::TickClock> test_clock) {
clock_ = std::move(test_clock);
}
diff --git a/chromium/content/browser/media/audible_metrics.h b/chromium/content/browser/media/audible_metrics.h
index 408bc8cba27..6ff9351747e 100644
--- a/chromium/content/browser/media/audible_metrics.h
+++ b/chromium/content/browser/media/audible_metrics.h
@@ -5,9 +5,9 @@
#ifndef CONTENT_BROWSER_MEDIA_AUDIBLE_METRICS_H_
#define CONTENT_BROWSER_MEDIA_AUDIBLE_METRICS_H_
+#include <memory>
#include <set>
-#include "base/memory/scoped_ptr.h"
#include "base/time/tick_clock.h"
#include "content/common/content_export.h"
@@ -29,7 +29,7 @@ class CONTENT_EXPORT AudibleMetrics {
void UpdateAudibleWebContentsState(const WebContents* web_contents,
bool audible);
- void SetClockForTest(scoped_ptr<base::TickClock> test_clock);
+ void SetClockForTest(std::unique_ptr<base::TickClock> test_clock);
private:
void AddAudibleWebContents(const WebContents* web_contents);
@@ -37,7 +37,7 @@ class CONTENT_EXPORT AudibleMetrics {
base::TimeTicks concurrent_web_contents_start_time_;
size_t max_concurrent_audible_web_contents_in_session_;
- scoped_ptr<base::TickClock> clock_;
+ std::unique_ptr<base::TickClock> clock_;
std::set<const WebContents*> audible_web_contents_;
diff --git a/chromium/content/browser/media/audible_metrics_unittest.cc b/chromium/content/browser/media/audible_metrics_unittest.cc
index 1a6216b6459..a337bb1ae0c 100644
--- a/chromium/content/browser/media/audible_metrics_unittest.cc
+++ b/chromium/content/browser/media/audible_metrics_unittest.cc
@@ -39,7 +39,7 @@ class AudibleMetricsTest : public testing::Test {
// recognized as initialized.
clock_->Advance(base::TimeDelta::FromMilliseconds(1));
audible_metrics_.SetClockForTest(
- scoped_ptr<base::SimpleTestTickClock>(clock_));
+ std::unique_ptr<base::SimpleTestTickClock>(clock_));
}
void TearDown() override {
@@ -56,7 +56,7 @@ class AudibleMetricsTest : public testing::Test {
return user_action_tester_;
}
- scoped_ptr<base::HistogramSamples> GetHistogramSamplesSinceTestStart(
+ std::unique_ptr<base::HistogramSamples> GetHistogramSamplesSinceTestStart(
const std::string& name) {
return histogram_tester_.GetHistogramSamplesSinceCreation(name);
}
@@ -73,26 +73,24 @@ class AudibleMetricsTest : public testing::Test {
} // anonymous namespace
TEST_F(AudibleMetricsTest, CreateAndKillDoesNothing) {
- {
- scoped_ptr<AudibleMetrics> audible_metrics(new AudibleMetrics());
- }
+ { std::unique_ptr<AudibleMetrics> audible_metrics(new AudibleMetrics()); }
{
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(
CONCURRENT_TAB_WHEN_STARTING_HISTOGRAM));
EXPECT_EQ(0, samples->TotalCount());
}
{
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(
MAX_CONCURRENT_TAB_IN_SESSION_HISTOGRAM));
EXPECT_EQ(0, samples->TotalCount());
}
{
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(CONCURRENT_TABS_TIME_HISTOGRAM));
EXPECT_EQ(0, samples->TotalCount());
}
@@ -105,7 +103,7 @@ TEST_F(AudibleMetricsTest, AudibleStart) {
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, true);
{
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(
CONCURRENT_TAB_WHEN_STARTING_HISTOGRAM));
EXPECT_EQ(1, samples->TotalCount());
@@ -113,7 +111,7 @@ TEST_F(AudibleMetricsTest, AudibleStart) {
}
{
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(
MAX_CONCURRENT_TAB_IN_SESSION_HISTOGRAM));
EXPECT_EQ(1, samples->TotalCount());
@@ -121,7 +119,7 @@ TEST_F(AudibleMetricsTest, AudibleStart) {
}
{
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(CONCURRENT_TABS_TIME_HISTOGRAM));
EXPECT_EQ(0, samples->TotalCount());
}
@@ -135,7 +133,7 @@ TEST_F(AudibleMetricsTest, AudibleStartAndStop) {
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, false);
{
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(
CONCURRENT_TAB_WHEN_STARTING_HISTOGRAM));
EXPECT_EQ(1, samples->TotalCount());
@@ -143,7 +141,7 @@ TEST_F(AudibleMetricsTest, AudibleStartAndStop) {
}
{
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(
MAX_CONCURRENT_TAB_IN_SESSION_HISTOGRAM));
EXPECT_EQ(1, samples->TotalCount());
@@ -151,7 +149,7 @@ TEST_F(AudibleMetricsTest, AudibleStartAndStop) {
}
{
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(CONCURRENT_TABS_TIME_HISTOGRAM));
EXPECT_EQ(0, samples->TotalCount());
}
@@ -168,7 +166,7 @@ TEST_F(AudibleMetricsTest, AddSameTabIsNoOp) {
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, true);
{
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(
CONCURRENT_TAB_WHEN_STARTING_HISTOGRAM));
EXPECT_EQ(1, samples->TotalCount());
@@ -176,7 +174,7 @@ TEST_F(AudibleMetricsTest, AddSameTabIsNoOp) {
}
{
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(
MAX_CONCURRENT_TAB_IN_SESSION_HISTOGRAM));
EXPECT_EQ(1, samples->TotalCount());
@@ -184,7 +182,7 @@ TEST_F(AudibleMetricsTest, AddSameTabIsNoOp) {
}
{
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(CONCURRENT_TABS_TIME_HISTOGRAM));
EXPECT_EQ(0, samples->TotalCount());
}
@@ -214,8 +212,9 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsInSessionIsIncremental) {
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_2, true);
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_3, true);
- scoped_ptr<base::HistogramSamples> samples(GetHistogramSamplesSinceTestStart(
- MAX_CONCURRENT_TAB_IN_SESSION_HISTOGRAM));
+ std::unique_ptr<base::HistogramSamples> samples(
+ GetHistogramSamplesSinceTestStart(
+ MAX_CONCURRENT_TAB_IN_SESSION_HISTOGRAM));
EXPECT_EQ(4, samples->TotalCount());
EXPECT_EQ(1, samples->GetCount(1));
EXPECT_EQ(1, samples->GetCount(2));
@@ -235,8 +234,9 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsInSessionKeepTrackOfRemovedTabs) {
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_2, false);
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_3, true);
- scoped_ptr<base::HistogramSamples> samples(GetHistogramSamplesSinceTestStart(
- MAX_CONCURRENT_TAB_IN_SESSION_HISTOGRAM));
+ std::unique_ptr<base::HistogramSamples> samples(
+ GetHistogramSamplesSinceTestStart(
+ MAX_CONCURRENT_TAB_IN_SESSION_HISTOGRAM));
EXPECT_EQ(2, samples->TotalCount());
EXPECT_EQ(1, samples->GetCount(1));
EXPECT_EQ(1, samples->GetCount(2));
@@ -261,8 +261,9 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsInSessionIsNotCountedTwice) {
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_2, true);
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_3, true);
- scoped_ptr<base::HistogramSamples> samples(GetHistogramSamplesSinceTestStart(
- MAX_CONCURRENT_TAB_IN_SESSION_HISTOGRAM));
+ std::unique_ptr<base::HistogramSamples> samples(
+ GetHistogramSamplesSinceTestStart(
+ MAX_CONCURRENT_TAB_IN_SESSION_HISTOGRAM));
EXPECT_EQ(4, samples->TotalCount());
EXPECT_EQ(1, samples->GetCount(1));
EXPECT_EQ(1, samples->GetCount(2));
@@ -278,7 +279,7 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsWhenStartingAddedPerTab) {
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_1, true);
{
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(
CONCURRENT_TAB_WHEN_STARTING_HISTOGRAM));
EXPECT_EQ(2, samples->TotalCount());
@@ -294,7 +295,7 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsWhenStartingAddedPerTab) {
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_1, true);
{
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(
CONCURRENT_TAB_WHEN_STARTING_HISTOGRAM));
EXPECT_EQ(2, samples->TotalCount());
@@ -310,7 +311,7 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsWhenStartingAddedPerTab) {
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_1, false);
{
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(
CONCURRENT_TAB_WHEN_STARTING_HISTOGRAM));
EXPECT_EQ(2, samples->TotalCount());
@@ -326,7 +327,7 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsWhenStartingAddedPerTab) {
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_1, true);
{
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(
CONCURRENT_TAB_WHEN_STARTING_HISTOGRAM));
EXPECT_EQ(4, samples->TotalCount());
@@ -351,7 +352,7 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsTimeRequiresTwoAudibleTabs) {
// No longer concurrent.
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, false);
{
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(CONCURRENT_TABS_TIME_HISTOGRAM));
EXPECT_EQ(1, samples->TotalCount());
EXPECT_EQ(1, samples->GetCount(1000));
@@ -360,7 +361,7 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsTimeRequiresTwoAudibleTabs) {
// Stopping the second tab is a no-op.
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_1, false);
{
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(CONCURRENT_TABS_TIME_HISTOGRAM));
EXPECT_EQ(1, samples->TotalCount());
EXPECT_EQ(1, samples->GetCount(1000));
@@ -387,7 +388,7 @@ TEST_F(AudibleMetricsTest, ConcurrentTabsTimeRunsAsLongAsTwoAudibleTabs) {
// Mutes the first audible tab.
audible_metrics()->UpdateAudibleWebContentsState(WEB_CONTENTS_0, false);
{
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart(CONCURRENT_TABS_TIME_HISTOGRAM));
EXPECT_EQ(1, samples->TotalCount());
EXPECT_EQ(1, samples->GetCount(1500));
diff --git a/chromium/content/browser/media/audio_stream_monitor_unittest.cc b/chromium/content/browser/media/audio_stream_monitor_unittest.cc
index 9ecee0a5aec..f1d5103d1ce 100644
--- a/chromium/content/browser/media/audio_stream_monitor_unittest.cc
+++ b/chromium/content/browser/media/audio_stream_monitor_unittest.cc
@@ -5,12 +5,12 @@
#include "content/browser/media/audio_stream_monitor.h"
#include <map>
+#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/test/simple_test_tick_clock.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/invalidate_type.h"
diff --git a/chromium/content/browser/media/capture/audio_mirroring_manager.cc b/chromium/content/browser/media/capture/audio_mirroring_manager.cc
index a75eb3c6476..f8b8b3a5b18 100644
--- a/chromium/content/browser/media/capture/audio_mirroring_manager.cc
+++ b/chromium/content/browser/media/capture/audio_mirroring_manager.cc
@@ -209,6 +209,9 @@ AudioMirroringManager::StreamRoutingState::StreamRoutingState(
diverter(stream_diverter),
destination(NULL) {}
+AudioMirroringManager::StreamRoutingState::StreamRoutingState(
+ const StreamRoutingState& other) = default;
+
AudioMirroringManager::StreamRoutingState::~StreamRoutingState() {}
} // namespace content
diff --git a/chromium/content/browser/media/capture/audio_mirroring_manager.h b/chromium/content/browser/media/capture/audio_mirroring_manager.h
index 4e44699097a..a624a0824be 100644
--- a/chromium/content/browser/media/capture/audio_mirroring_manager.h
+++ b/chromium/content/browser/media/capture/audio_mirroring_manager.h
@@ -122,6 +122,7 @@ class CONTENT_EXPORT AudioMirroringManager {
StreamRoutingState(const SourceFrameRef& source_frame,
Diverter* stream_diverter);
+ StreamRoutingState(const StreamRoutingState& other);
~StreamRoutingState();
};
diff --git a/chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc b/chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc
index 0f471c88171..17a46976b4a 100644
--- a/chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc
+++ b/chromium/content/browser/media/capture/audio_mirroring_manager_unittest.cc
@@ -120,7 +120,7 @@ class AudioMirroringManagerTest : public testing::Test {
delete diverter;
}
- void StartMirroringTo(const scoped_ptr<MockMirroringDestination>& dest,
+ void StartMirroringTo(const std::unique_ptr<MockMirroringDestination>& dest,
int expected_inputs_added) {
EXPECT_CALL(*dest, QueryForMatches(_, _))
.WillRepeatedly(Invoke(dest.get(),
@@ -136,12 +136,12 @@ class AudioMirroringManagerTest : public testing::Test {
mirroring_manager_.StartMirroring(dest.get());
}
- void StopMirroringTo(const scoped_ptr<MockMirroringDestination>& dest) {
+ void StopMirroringTo(const std::unique_ptr<MockMirroringDestination>& dest) {
mirroring_manager_.StopMirroring(dest.get());
}
int CountStreamsDivertedTo(
- const scoped_ptr<MockMirroringDestination>& dest) const {
+ const std::unique_ptr<MockMirroringDestination>& dest) const {
int count = 0;
for (StreamRoutes::const_iterator it = mirroring_manager_.routes_.begin();
it != mirroring_manager_.routes_.end(); ++it) {
@@ -175,7 +175,7 @@ const int kYetAnotherRenderFrameId = 7890;
}
TEST_F(AudioMirroringManagerTest, MirroringSessionOfNothing) {
- const scoped_ptr<MockMirroringDestination> destination(
+ const std::unique_ptr<MockMirroringDestination> destination(
new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
StartMirroringTo(destination, 0);
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
@@ -187,7 +187,7 @@ TEST_F(AudioMirroringManagerTest, MirroringSessionOfNothing) {
}
TEST_F(AudioMirroringManagerTest, TwoMirroringSessionsOfNothing) {
- const scoped_ptr<MockMirroringDestination> destination(
+ const std::unique_ptr<MockMirroringDestination> destination(
new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
StartMirroringTo(destination, 0);
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
@@ -195,7 +195,7 @@ TEST_F(AudioMirroringManagerTest, TwoMirroringSessionsOfNothing) {
StopMirroringTo(destination);
EXPECT_EQ(0, destination->query_count());
- const scoped_ptr<MockMirroringDestination> another_destination(
+ const std::unique_ptr<MockMirroringDestination> another_destination(
new MockMirroringDestination(kAnotherRenderProcessId,
kAnotherRenderFrameId));
StartMirroringTo(another_destination, 0);
@@ -212,7 +212,7 @@ TEST_F(AudioMirroringManagerTest, TwoMirroringSessionsOfNothing) {
TEST_F(AudioMirroringManagerTest, StreamLifetimeAroundMirroringSession) {
MockDiverter* const stream =
CreateStream(kRenderProcessId, kRenderFrameId, 1);
- const scoped_ptr<MockMirroringDestination> destination(
+ const std::unique_ptr<MockMirroringDestination> destination(
new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
StartMirroringTo(destination, 1);
EXPECT_EQ(1, destination->query_count());
@@ -232,7 +232,7 @@ TEST_F(AudioMirroringManagerTest, StreamLifetimeAroundMirroringSession) {
// Tests that a mirroring session starts before, and ends after, a stream that
// will be diverted to it.
TEST_F(AudioMirroringManagerTest, StreamLifetimeWithinMirroringSession) {
- const scoped_ptr<MockMirroringDestination> destination(
+ const std::unique_ptr<MockMirroringDestination> destination(
new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
StartMirroringTo(destination, 1);
EXPECT_EQ(0, destination->query_count());
@@ -260,7 +260,7 @@ TEST_F(AudioMirroringManagerTest, StreamLifetimeAcrossTwoMirroringSessions) {
MockDiverter* const stream =
CreateStream(kRenderProcessId, kRenderFrameId, 2);
- const scoped_ptr<MockMirroringDestination> destination(
+ const std::unique_ptr<MockMirroringDestination> destination(
new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
StartMirroringTo(destination, 1);
EXPECT_EQ(1, destination->query_count());
@@ -270,7 +270,7 @@ TEST_F(AudioMirroringManagerTest, StreamLifetimeAcrossTwoMirroringSessions) {
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(0, CountStreamsDivertedTo(destination));
- const scoped_ptr<MockMirroringDestination> second_destination(
+ const std::unique_ptr<MockMirroringDestination> second_destination(
new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
StartMirroringTo(second_destination, 1);
EXPECT_EQ(1, destination->query_count());
@@ -299,13 +299,13 @@ TEST_F(AudioMirroringManagerTest, StreamDivertingStickyToOneDestination_1) {
MockDiverter* const stream =
CreateStream(kRenderProcessId, kRenderFrameId, 2);
- const scoped_ptr<MockMirroringDestination> destination(
+ const std::unique_ptr<MockMirroringDestination> destination(
new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
StartMirroringTo(destination, 1);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(destination));
- const scoped_ptr<MockMirroringDestination> replacement_destination(
+ const std::unique_ptr<MockMirroringDestination> replacement_destination(
new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
StartMirroringTo(replacement_destination, 1);
EXPECT_EQ(1, destination->query_count());
@@ -340,13 +340,13 @@ TEST_F(AudioMirroringManagerTest, StreamDivertingStickyToOneDestination_2) {
MockDiverter* const stream =
CreateStream(kRenderProcessId, kRenderFrameId, 2);
- const scoped_ptr<MockMirroringDestination> destination(
+ const std::unique_ptr<MockMirroringDestination> destination(
new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
StartMirroringTo(destination, 1);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(destination));
- const scoped_ptr<MockMirroringDestination> replacement_destination(
+ const std::unique_ptr<MockMirroringDestination> replacement_destination(
new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
StartMirroringTo(replacement_destination, 1);
EXPECT_EQ(1, destination->query_count());
@@ -382,13 +382,13 @@ TEST_F(AudioMirroringManagerTest, StreamDivertingStickyToOneDestination_3) {
MockDiverter* const stream =
CreateStream(kRenderProcessId, kRenderFrameId, 1);
- const scoped_ptr<MockMirroringDestination> destination(
+ const std::unique_ptr<MockMirroringDestination> destination(
new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
StartMirroringTo(destination, 1);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(destination));
- const scoped_ptr<MockMirroringDestination> replacement_destination(
+ const std::unique_ptr<MockMirroringDestination> replacement_destination(
new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
StartMirroringTo(replacement_destination, 0);
EXPECT_EQ(1, destination->query_count());
@@ -422,7 +422,7 @@ TEST_F(AudioMirroringManagerTest, MultipleStreamsInOneMirroringSession) {
MockDiverter* const stream1 =
CreateStream(kRenderProcessId, kRenderFrameId, 1);
- const scoped_ptr<MockMirroringDestination> destination(
+ const std::unique_ptr<MockMirroringDestination> destination(
new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
StartMirroringTo(destination, 3);
EXPECT_EQ(1, destination->query_count());
@@ -463,13 +463,13 @@ TEST_F(AudioMirroringManagerTest, ThreeSeparateMirroringSessions) {
MockDiverter* const stream =
CreateStream(kRenderProcessId, kRenderFrameId, 1);
- const scoped_ptr<MockMirroringDestination> destination(
+ const std::unique_ptr<MockMirroringDestination> destination(
new MockMirroringDestination(kRenderProcessId, kRenderFrameId));
StartMirroringTo(destination, 1);
EXPECT_EQ(1, destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(destination));
- const scoped_ptr<MockMirroringDestination> another_destination(
+ const std::unique_ptr<MockMirroringDestination> another_destination(
new MockMirroringDestination(kAnotherRenderProcessId,
kAnotherRenderFrameId));
StartMirroringTo(another_destination, 1);
@@ -498,7 +498,7 @@ TEST_F(AudioMirroringManagerTest, ThreeSeparateMirroringSessions) {
EXPECT_EQ(2, another_destination->query_count());
EXPECT_EQ(1, CountStreamsDivertedTo(another_destination));
- const scoped_ptr<MockMirroringDestination> yet_another_destination(
+ const std::unique_ptr<MockMirroringDestination> yet_another_destination(
new MockMirroringDestination(kYetAnotherRenderProcessId,
kYetAnotherRenderFrameId));
StartMirroringTo(yet_another_destination, 1);
diff --git a/chromium/content/browser/media/capture/aura_window_capture_machine.cc b/chromium/content/browser/media/capture/aura_window_capture_machine.cc
index c3405994e94..864243efee3 100644
--- a/chromium/content/browser/media/capture/aura_window_capture_machine.cc
+++ b/chromium/content/browser/media/capture/aura_window_capture_machine.cc
@@ -9,12 +9,11 @@
#include "base/logging.h"
#include "base/metrics/histogram.h"
-#include "base/timer/timer.h"
#include "cc/output/copy_output_request.h"
#include "cc/output/copy_output_result.h"
+#include "content/browser/compositor/gl_helper.h"
#include "content/browser/compositor/image_transport_factory.h"
#include "content/browser/media/capture/desktop_capture_device_uma_types.h"
-#include "content/common/gpu/client/gl_helper.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/power_save_blocker.h"
#include "media/base/video_capture_types.h"
@@ -39,7 +38,6 @@ namespace content {
AuraWindowCaptureMachine::AuraWindowCaptureMachine()
: desktop_window_(NULL),
- timer_(true, true),
screen_capture_(false),
weak_factory_(this) {}
@@ -74,7 +72,7 @@ bool AuraWindowCaptureMachine::InternalStart(
if (!layer)
return false;
- DCHECK(oracle_proxy.get());
+ DCHECK(oracle_proxy);
oracle_proxy_ = oracle_proxy;
capture_params_ = params;
@@ -82,8 +80,11 @@ bool AuraWindowCaptureMachine::InternalStart(
UpdateCaptureSize();
// Start observing compositor updates.
- if (desktop_window_->GetHost())
- desktop_window_->GetHost()->compositor()->AddObserver(this);
+ aura::WindowTreeHost* const host = desktop_window_->GetHost();
+ ui::Compositor* const compositor = host ? host->compositor() : nullptr;
+ if (!compositor)
+ return false;
+ compositor->AddAnimationObserver(this);
power_save_blocker_.reset(
PowerSaveBlocker::Create(
@@ -91,14 +92,6 @@ bool AuraWindowCaptureMachine::InternalStart(
PowerSaveBlocker::kReasonOther,
"DesktopCaptureDevice is running").release());
- // Starts timer.
- timer_.Start(FROM_HERE,
- std::max(oracle_proxy_->min_capture_period(),
- base::TimeDelta::FromMilliseconds(media::
- VideoCaptureOracle::kMinTimerPollPeriodMillis)),
- base::Bind(&AuraWindowCaptureMachine::Capture,
- base::Unretained(this), false));
-
return true;
}
@@ -121,27 +114,34 @@ void AuraWindowCaptureMachine::InternalStop(const base::Closure& callback) {
// Stop observing compositor and window events.
if (desktop_window_) {
- aura::WindowTreeHost* window_host = desktop_window_->GetHost();
- // In the host destructor the compositor is destroyed before the window.
- if (window_host && window_host->compositor())
- window_host->compositor()->RemoveObserver(this);
+ if (aura::WindowTreeHost* host = desktop_window_->GetHost()) {
+ if (ui::Compositor* compositor = host->compositor())
+ compositor->RemoveAnimationObserver(this);
+ }
desktop_window_->RemoveObserver(this);
desktop_window_ = NULL;
cursor_renderer_.reset();
}
- // Stop timer.
- timer_.Stop();
-
callback.Run();
}
+void AuraWindowCaptureMachine::MaybeCaptureForRefresh() {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&AuraWindowCaptureMachine::Capture,
+ // Use of Unretained() is safe here since this task must run
+ // before InternalStop().
+ base::Unretained(this),
+ base::TimeTicks()));
+}
+
void AuraWindowCaptureMachine::SetWindow(aura::Window* window) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(!desktop_window_);
desktop_window_ = window;
- cursor_renderer_.reset(new CursorRendererAura(window));
+ cursor_renderer_.reset(new CursorRendererAura(window, kCursorAlwaysEnabled));
// Start observing window events.
desktop_window_->AddObserver(this);
@@ -155,7 +155,7 @@ void AuraWindowCaptureMachine::SetWindow(aura::Window* window) {
void AuraWindowCaptureMachine::UpdateCaptureSize() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (oracle_proxy_.get() && desktop_window_) {
+ if (oracle_proxy_ && desktop_window_) {
ui::Layer* layer = desktop_window_->layer();
oracle_proxy_->UpdateCaptureSize(ui::ConvertSizeToPixel(
layer, layer->bounds().size()));
@@ -163,7 +163,7 @@ void AuraWindowCaptureMachine::UpdateCaptureSize() {
cursor_renderer_->Clear();
}
-void AuraWindowCaptureMachine::Capture(bool dirty) {
+void AuraWindowCaptureMachine::Capture(base::TimeTicks event_time) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Do not capture if the desktop window is already destroyed.
@@ -177,16 +177,20 @@ void AuraWindowCaptureMachine::Capture(bool dirty) {
// timestamps and damage regions, to leverage the frame timestamp rewriting
// logic. http://crbug.com/492839
const base::TimeTicks start_time = base::TimeTicks::Now();
- const media::VideoCaptureOracle::Event event =
- dirty ? media::VideoCaptureOracle::kCompositorUpdate
- : media::VideoCaptureOracle::kTimerPoll;
+ media::VideoCaptureOracle::Event event;
+ if (event_time.is_null()) {
+ event = media::VideoCaptureOracle::kActiveRefreshRequest;
+ event_time = start_time;
+ } else {
+ event = media::VideoCaptureOracle::kCompositorUpdate;
+ }
if (oracle_proxy_->ObserveEventAndDecideCapture(
- event, gfx::Rect(), start_time, &frame, &capture_frame_cb)) {
- scoped_ptr<cc::CopyOutputRequest> request =
- cc::CopyOutputRequest::CreateRequest(
- base::Bind(&AuraWindowCaptureMachine::DidCopyOutput,
- weak_factory_.GetWeakPtr(),
- frame, start_time, capture_frame_cb));
+ event, gfx::Rect(), event_time, &frame, &capture_frame_cb)) {
+ std::unique_ptr<cc::CopyOutputRequest> request =
+ cc::CopyOutputRequest::CreateRequest(base::Bind(
+ &AuraWindowCaptureMachine::DidCopyOutput,
+ weak_factory_.GetWeakPtr(), frame, event_time, start_time,
+ capture_frame_cb));
gfx::Rect window_rect = gfx::Rect(desktop_window_->bounds().width(),
desktop_window_->bounds().height());
request->set_area(window_rect);
@@ -196,17 +200,18 @@ void AuraWindowCaptureMachine::Capture(bool dirty) {
void AuraWindowCaptureMachine::DidCopyOutput(
scoped_refptr<media::VideoFrame> video_frame,
+ base::TimeTicks event_time,
base::TimeTicks start_time,
const CaptureFrameCallback& capture_frame_cb,
- scoped_ptr<cc::CopyOutputResult> result) {
+ std::unique_ptr<cc::CopyOutputResult> result) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
static bool first_call = true;
- bool succeeded = ProcessCopyOutputResponse(
- video_frame, start_time, capture_frame_cb, std::move(result));
+ const bool succeeded = ProcessCopyOutputResponse(
+ video_frame, event_time, capture_frame_cb, std::move(result));
- base::TimeDelta capture_time = base::TimeTicks::Now() - start_time;
+ const base::TimeDelta capture_time = base::TimeTicks::Now() - start_time;
// The two UMA_ blocks must be put in its own scope since it creates a static
// variable which expected constant histogram name.
@@ -227,18 +232,33 @@ void AuraWindowCaptureMachine::DidCopyOutput(
: FIRST_WINDOW_CAPTURE_FAILED);
}
}
+
+ // If ProcessCopyOutputResponse() failed, it will not run |capture_frame_cb|,
+ // so do that now.
+ if (!succeeded)
+ capture_frame_cb.Run(video_frame, event_time, false);
}
bool AuraWindowCaptureMachine::ProcessCopyOutputResponse(
scoped_refptr<media::VideoFrame> video_frame,
- base::TimeTicks start_time,
+ base::TimeTicks event_time,
const CaptureFrameCallback& capture_frame_cb,
- scoped_ptr<cc::CopyOutputResult> result) {
+ std::unique_ptr<cc::CopyOutputResult> result) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (result->IsEmpty() || result->size().IsEmpty() || !desktop_window_)
+ if (!desktop_window_) {
+ VLOG(1) << "Ignoring CopyOutputResult: Capture target has gone away.";
+ return false;
+ }
+ if (result->IsEmpty()) {
+ VLOG(1) << "CopyOutputRequest failed: No texture or bitmap in result.";
+ return false;
+ }
+ if (result->size().IsEmpty()) {
+ VLOG(1) << "CopyOutputRequest failed: Zero-area texture/bitmap result.";
return false;
- DCHECK(video_frame.get());
+ }
+ DCHECK(video_frame);
// Compute the dest size we want after the letterboxing resize. Make the
// coordinates and sizes even because we letterbox in YUV space
@@ -252,20 +272,26 @@ bool AuraWindowCaptureMachine::ProcessCopyOutputResponse(
region_in_frame.y() & ~1,
region_in_frame.width() & ~1,
region_in_frame.height() & ~1);
- if (region_in_frame.IsEmpty())
+ if (region_in_frame.IsEmpty()) {
+ VLOG(1) << "Aborting capture: Computed empty letterboxed content region.";
return false;
+ }
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
GLHelper* gl_helper = factory->GetGLHelper();
- if (!gl_helper)
+ if (!gl_helper) {
+ VLOG(1) << "Aborting capture: No GLHelper available for YUV readback.";
return false;
+ }
cc::TextureMailbox texture_mailbox;
- scoped_ptr<cc::SingleReleaseCallback> release_callback;
+ std::unique_ptr<cc::SingleReleaseCallback> release_callback;
result->TakeTexture(&texture_mailbox, &release_callback);
DCHECK(texture_mailbox.IsTexture());
- if (!texture_mailbox.IsTexture())
+ if (!texture_mailbox.IsTexture()) {
+ VLOG(1) << "Aborting capture: Failed to take texture from mailbox.";
return false;
+ }
gfx::Rect result_rect(result->size());
if (!yuv_readback_pipeline_ ||
@@ -286,7 +312,7 @@ bool AuraWindowCaptureMachine::ProcessCopyOutputResponse(
texture_mailbox.mailbox(), texture_mailbox.sync_token(),
video_frame.get(), region_in_frame.origin(),
base::Bind(&CopyOutputFinishedForVideo, weak_factory_.GetWeakPtr(),
- start_time, capture_frame_cb, video_frame,
+ event_time, capture_frame_cb, video_frame,
base::Passed(&release_callback)));
return true;
}
@@ -296,10 +322,10 @@ using CaptureFrameCallback =
void AuraWindowCaptureMachine::CopyOutputFinishedForVideo(
base::WeakPtr<AuraWindowCaptureMachine> machine,
- base::TimeTicks start_time,
+ base::TimeTicks event_time,
const CaptureFrameCallback& capture_frame_cb,
const scoped_refptr<media::VideoFrame>& target,
- scoped_ptr<cc::SingleReleaseCallback> release_callback,
+ std::unique_ptr<cc::SingleReleaseCallback> release_callback,
bool result) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -308,11 +334,15 @@ void AuraWindowCaptureMachine::CopyOutputFinishedForVideo(
// Render the cursor and deliver the captured frame if the
// AuraWindowCaptureMachine has not been stopped (i.e., the WeakPtr is
// still valid).
- if (machine.get()) {
+ if (machine) {
if (machine->cursor_renderer_ && result)
machine->cursor_renderer_->RenderOnVideoFrame(target);
- capture_frame_cb.Run(target, start_time, result);
+ } else {
+ VLOG(1) << "Aborting capture: AuraWindowCaptureMachine has gone away.";
+ result = false;
}
+
+ capture_frame_cb.Run(target, event_time, result);
}
void AuraWindowCaptureMachine::OnWindowBoundsChanged(
@@ -341,7 +371,10 @@ void AuraWindowCaptureMachine::OnWindowAddedToRootWindow(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(window == desktop_window_);
- window->GetHost()->compositor()->AddObserver(this);
+ if (aura::WindowTreeHost* host = window->GetHost()) {
+ if (ui::Compositor* compositor = host->compositor())
+ compositor->AddAnimationObserver(this);
+ }
}
void AuraWindowCaptureMachine::OnWindowRemovingFromRootWindow(
@@ -350,20 +383,36 @@ void AuraWindowCaptureMachine::OnWindowRemovingFromRootWindow(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(window == desktop_window_);
- window->GetHost()->compositor()->RemoveObserver(this);
+ if (aura::WindowTreeHost* host = window->GetHost()) {
+ if (ui::Compositor* compositor = host->compositor())
+ compositor->RemoveAnimationObserver(this);
+ }
}
-void AuraWindowCaptureMachine::OnCompositingEnded(
- ui::Compositor* compositor) {
+void AuraWindowCaptureMachine::OnAnimationStep(base::TimeTicks timestamp) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- // TODO(miu): The CopyOutputRequest should be made earlier, at WillCommit().
+ DCHECK(!timestamp.is_null());
+
+ // HACK: The compositor invokes this observer method to step layer animation
+ // forward. Scheduling frame capture was not the intention, and so invoking
+ // this method does not actually indicate the content has changed. However,
+ // this is the only reliable way to ensure all screen changes are captured, as
+ // of this writing.
+ // http://crbug.com/600031
+ //
+ // TODO(miu): Need a better observer callback interface from the compositor
+ // for this use case. The solution here will always capture frames at the
+ // maximum framerate, which means CPU/GPU is being wasted on redundant
+ // captures and quality/smoothness of animating content will suffer
+ // significantly.
// http://crbug.com/492839
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(&AuraWindowCaptureMachine::Capture, weak_factory_.GetWeakPtr(),
- true));
+ Capture(timestamp);
+}
+
+void AuraWindowCaptureMachine::OnCompositingShuttingDown(
+ ui::Compositor* compositor) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ compositor->RemoveAnimationObserver(this);
}
} // namespace content
diff --git a/chromium/content/browser/media/capture/aura_window_capture_machine.h b/chromium/content/browser/media/capture/aura_window_capture_machine.h
index c07c72f8c8c..ca9e09e4463 100644
--- a/chromium/content/browser/media/capture/aura_window_capture_machine.h
+++ b/chromium/content/browser/media/capture/aura_window_capture_machine.h
@@ -5,16 +5,17 @@
#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_AURA_WINDOW_CAPTURE_MACHINE_H_
#define CONTENT_BROWSER_MEDIA_CAPTURE_AURA_WINDOW_CAPTURE_MACHINE_H_
+#include <memory>
+
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
-#include "base/timer/timer.h"
#include "content/browser/media/capture/cursor_renderer_aura.h"
#include "media/capture/content/screen_capture_device_core.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
#include "ui/base/cursor/cursors_aura.h"
#include "ui/compositor/compositor.h"
+#include "ui/compositor/compositor_animation_observer.h"
namespace cc {
@@ -30,7 +31,7 @@ class ReadbackYUVInterface;
class AuraWindowCaptureMachine
: public media::VideoCaptureMachine,
public aura::WindowObserver,
- public ui::CompositorObserver {
+ public ui::CompositorAnimationObserver {
public:
AuraWindowCaptureMachine();
~AuraWindowCaptureMachine() override;
@@ -40,6 +41,7 @@ class AuraWindowCaptureMachine
const media::VideoCaptureParams& params,
const base::Callback<void(bool)> callback) override;
void Stop(const base::Closure& callback) override;
+ void MaybeCaptureForRefresh() override;
// Implements aura::WindowObserver.
void OnWindowBoundsChanged(aura::Window* window,
@@ -50,14 +52,9 @@ class AuraWindowCaptureMachine
void OnWindowRemovingFromRootWindow(aura::Window* window,
aura::Window* new_root) override;
- // Implements ui::CompositorObserver.
- void OnCompositingDidCommit(ui::Compositor* compositor) override {}
- void OnCompositingStarted(ui::Compositor* compositor,
- base::TimeTicks start_time) override {}
- void OnCompositingEnded(ui::Compositor* compositor) override;
- void OnCompositingAborted(ui::Compositor* compositor) override {}
- void OnCompositingLockStateChanged(ui::Compositor* compositor) override {}
- void OnCompositingShuttingDown(ui::Compositor* compositor) override {}
+ // ui::CompositorAnimationObserver implementation.
+ void OnAnimationStep(base::TimeTicks timestamp) override;
+ void OnCompositingShuttingDown(ui::Compositor* compositor) override;
// Sets the window to use for capture.
void SetWindow(aura::Window* window);
@@ -68,9 +65,9 @@ class AuraWindowCaptureMachine
const media::VideoCaptureParams& params);
void InternalStop(const base::Closure& callback);
- // Captures a frame.
- // |dirty| is false for timer polls and true for compositor updates.
- void Capture(bool dirty);
+ // Captures a frame. |event_time| is provided by the compositor, or is null
+ // for refresh requests.
+ void Capture(base::TimeTicks event_time);
// Update capture size. Must be called on the UI thread.
void UpdateCaptureSize();
@@ -79,35 +76,33 @@ class AuraWindowCaptureMachine
media::ThreadSafeCaptureOracle::CaptureFrameCallback;
// Response callback for cc::Layer::RequestCopyOfOutput().
- void DidCopyOutput(
- scoped_refptr<media::VideoFrame> video_frame,
- base::TimeTicks start_time,
- const CaptureFrameCallback& capture_frame_cb,
- scoped_ptr<cc::CopyOutputResult> result);
+ void DidCopyOutput(scoped_refptr<media::VideoFrame> video_frame,
+ base::TimeTicks event_time,
+ base::TimeTicks start_time,
+ const CaptureFrameCallback& capture_frame_cb,
+ std::unique_ptr<cc::CopyOutputResult> result);
// A helper which does the real work for DidCopyOutput. Returns true if
- // succeeded.
- bool ProcessCopyOutputResponse(
- scoped_refptr<media::VideoFrame> video_frame,
- base::TimeTicks start_time,
- const CaptureFrameCallback& capture_frame_cb,
- scoped_ptr<cc::CopyOutputResult> result);
+ // succeeded and |capture_frame_cb| will be run at some future point. Returns
+ // false on error, and |capture_frame_cb| should be run by the caller (with
+ // failure status).
+ bool ProcessCopyOutputResponse(scoped_refptr<media::VideoFrame> video_frame,
+ base::TimeTicks event_time,
+ const CaptureFrameCallback& capture_frame_cb,
+ std::unique_ptr<cc::CopyOutputResult> result);
// Renders the cursor if needed and then delivers the captured frame.
static void CopyOutputFinishedForVideo(
base::WeakPtr<AuraWindowCaptureMachine> machine,
- base::TimeTicks start_time,
+ base::TimeTicks event_time,
const CaptureFrameCallback& capture_frame_cb,
const scoped_refptr<media::VideoFrame>& target,
- scoped_ptr<cc::SingleReleaseCallback> release_callback,
+ std::unique_ptr<cc::SingleReleaseCallback> release_callback,
bool result);
// The window associated with the desktop.
aura::Window* desktop_window_;
- // The timer that kicks off period captures.
- base::Timer timer_;
-
// Whether screen capturing or window capture.
bool screen_capture_;
@@ -118,14 +113,14 @@ class AuraWindowCaptureMachine
media::VideoCaptureParams capture_params_;
// YUV readback pipeline.
- scoped_ptr<content::ReadbackYUVInterface> yuv_readback_pipeline_;
+ std::unique_ptr<content::ReadbackYUVInterface> yuv_readback_pipeline_;
// Renders mouse cursor on frame.
- scoped_ptr<content::CursorRendererAura> cursor_renderer_;
+ std::unique_ptr<content::CursorRendererAura> cursor_renderer_;
// TODO(jiayl): Remove power_save_blocker_ when there is an API to keep the
// screen from sleeping for the drive-by web.
- scoped_ptr<PowerSaveBlocker> power_save_blocker_;
+ std::unique_ptr<PowerSaveBlocker> power_save_blocker_;
// WeakPtrs are used for the asynchronous capture callbacks passed to external
// modules. They are only valid on the UI thread and become invalidated
diff --git a/chromium/content/browser/media/capture/cursor_renderer.h b/chromium/content/browser/media/capture/cursor_renderer.h
index 7416413f421..9ac912e68fe 100644
--- a/chromium/content/browser/media/capture/cursor_renderer.h
+++ b/chromium/content/browser/media/capture/cursor_renderer.h
@@ -21,6 +21,8 @@ namespace content {
// will listen to mouse events.
class CONTENT_EXPORT CursorRenderer {
public:
+ static std::unique_ptr<CursorRenderer> Create(gfx::NativeView view);
+
virtual ~CursorRenderer() {}
// Clears the cursor state being tracked. Called when there is a need to
diff --git a/chromium/content/browser/media/capture/cursor_renderer_aura.cc b/chromium/content/browser/media/capture/cursor_renderer_aura.cc
index 238ed9a1e52..6beceea099f 100644
--- a/chromium/content/browser/media/capture/cursor_renderer_aura.cc
+++ b/chromium/content/browser/media/capture/cursor_renderer_aura.cc
@@ -35,11 +35,24 @@ inline int alpha_blend(int alpha, int src, int dst) {
} // namespace
-CursorRendererAura::CursorRendererAura(aura::Window* window)
- : window_(window), tick_clock_(&default_tick_clock_), weak_factory_(this) {
+// static
+std::unique_ptr<CursorRenderer> CursorRenderer::Create(
+ gfx::NativeWindow window) {
+ return std::unique_ptr<CursorRenderer>(
+ new CursorRendererAura(window, kCursorEnabledOnMouseMovement));
+}
+
+CursorRendererAura::CursorRendererAura(
+ aura::Window* window,
+ CursorDisplaySetting cursor_display_setting)
+ : window_(window),
+ cursor_display_setting_(cursor_display_setting),
+ tick_clock_(&default_tick_clock_),
+ weak_factory_(this) {
if (window_) {
window_->AddObserver(this);
- window_->AddPreTargetHandler(this);
+ if (cursor_display_setting == kCursorEnabledOnMouseMovement)
+ window_->AddPreTargetHandler(this);
}
Clear();
}
@@ -47,7 +60,8 @@ CursorRendererAura::CursorRendererAura(aura::Window* window)
CursorRendererAura::~CursorRendererAura() {
if (window_) {
window_->RemoveObserver(this);
- window_->RemovePreTargetHandler(this);
+ if (cursor_display_setting_ == kCursorEnabledOnMouseMovement)
+ window_->RemovePreTargetHandler(this);
}
}
@@ -61,7 +75,11 @@ void CursorRendererAura::Clear() {
scaled_cursor_bitmap_.reset();
last_mouse_position_x_ = 0;
last_mouse_position_y_ = 0;
- cursor_displayed_ = false;
+ if (cursor_display_setting_ == kCursorEnabledOnMouseMovement) {
+ cursor_displayed_ = false;
+ } else {
+ cursor_displayed_ = true;
+ }
}
bool CursorRendererAura::SnapshotCursorState(const gfx::Rect& region_in_frame) {
@@ -94,6 +112,20 @@ bool CursorRendererAura::SnapshotCursorState(const gfx::Rect& region_in_frame) {
}
}
+ if (cursor_display_setting_ == kCursorEnabledOnMouseMovement) {
+ if (cursor_displayed_) {
+ // Stop displaying cursor if there has been no mouse movement
+ base::TimeDelta now = tick_clock_->NowTicks() - base::TimeTicks();
+ if ((now - last_mouse_movement_timestamp_) >
+ base::TimeDelta::FromSeconds(MAX_IDLE_TIME_SECONDS)) {
+ cursor_displayed_ = false;
+ DVLOG(2) << "Turning off cursor display after idle time";
+ }
+ }
+ if (!cursor_displayed_)
+ return false;
+ }
+
gfx::NativeCursor cursor = window_->GetHost()->last_cursor();
gfx::Point cursor_hot_point;
if (last_cursor_ != cursor ||
@@ -131,16 +163,7 @@ bool CursorRendererAura::SnapshotCursorState(const gfx::Rect& region_in_frame) {
cursor_position.y() * region_in_frame.height() /
window_bounds.height());
- if (cursor_displayed_) {
- // Stop displaying cursor if there has been no mouse movement
- base::TimeDelta now = tick_clock_->NowTicks() - base::TimeTicks();
- if ((now - last_mouse_movement_timestamp_) >
- base::TimeDelta::FromSeconds(MAX_IDLE_TIME_SECONDS)) {
- cursor_displayed_ = false;
- DVLOG(2) << "Turning off cursor display after idle time";
- }
- }
- return cursor_displayed_;
+ return true;
}
// Helper function to composite a cursor bitmap on a YUV420 video frame.
@@ -218,7 +241,8 @@ void CursorRendererAura::OnMouseEvent(ui::MouseEvent* event) {
void CursorRendererAura::OnWindowDestroying(aura::Window* window) {
DCHECK_EQ(window_, window);
- window_->RemovePreTargetHandler(this);
+ if (cursor_display_setting_ == kCursorEnabledOnMouseMovement)
+ window_->RemovePreTargetHandler(this);
window_->RemoveObserver(this);
window_ = nullptr;
}
diff --git a/chromium/content/browser/media/capture/cursor_renderer_aura.h b/chromium/content/browser/media/capture/cursor_renderer_aura.h
index 42dffa6b392..eaa1790d471 100644
--- a/chromium/content/browser/media/capture/cursor_renderer_aura.h
+++ b/chromium/content/browser/media/capture/cursor_renderer_aura.h
@@ -23,13 +23,21 @@
namespace content {
+// Setting to control cursor display based on either mouse movement or always
+// forced to be enabled.
+enum CursorDisplaySetting {
+ kCursorAlwaysEnabled,
+ kCursorEnabledOnMouseMovement
+};
+
// Tracks state for making decisions on cursor display on a captured video
// frame.
class CONTENT_EXPORT CursorRendererAura : public CursorRenderer,
public ui::EventHandler,
public aura::WindowObserver {
public:
- explicit CursorRendererAura(aura::Window* window);
+ explicit CursorRendererAura(aura::Window* window,
+ CursorDisplaySetting cursor_display);
~CursorRendererAura() final;
// CursorRender implementation.
@@ -64,6 +72,9 @@ class CONTENT_EXPORT CursorRendererAura : public CursorRenderer,
float last_mouse_position_y_;
bool cursor_displayed_;
+ // Controls whether cursor is displayed based on active mouse movement.
+ const CursorDisplaySetting cursor_display_setting_;
+
// Allows tests to replace the clock.
base::DefaultTickClock default_tick_clock_;
base::TickClock* tick_clock_;
diff --git a/chromium/content/browser/media/capture/cursor_renderer_aura_unittest.cc b/chromium/content/browser/media/capture/cursor_renderer_aura_unittest.cc
index bb210b9737e..c3989455eb8 100644
--- a/chromium/content/browser/media/capture/cursor_renderer_aura_unittest.cc
+++ b/chromium/content/browser/media/capture/cursor_renderer_aura_unittest.cc
@@ -6,8 +6,9 @@
#include <stdint.h>
+#include <memory>
+
#include "base/files/file_path.h"
-#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
#include "base/test/simple_test_tick_clock.h"
#include "base/time/time.h"
@@ -48,7 +49,8 @@ class CursorRendererAuraTest : public AuraTestBase {
window_.reset(aura::test::CreateTestWindowWithBounds(
gfx::Rect(0, 0, 800, 600), root_window()));
- cursor_renderer_.reset(new CursorRendererAura(window_.get()));
+ cursor_renderer_.reset(
+ new CursorRendererAura(window_.get(), kCursorEnabledOnMouseMovement));
new wm::DefaultActivationClient(root_window());
}
@@ -125,10 +127,36 @@ class CursorRendererAuraTest : public AuraTestBase {
}
protected:
- scoped_ptr<aura::Window> window_;
- scoped_ptr<CursorRendererAura> cursor_renderer_;
+ std::unique_ptr<aura::Window> window_;
+ std::unique_ptr<CursorRendererAura> cursor_renderer_;
};
+TEST_F(CursorRendererAuraTest, CursorAlwaysDisplayed) {
+ // Set up cursor renderer to always display cursor.
+ cursor_renderer_.reset(
+ new CursorRendererAura(window_.get(), kCursorAlwaysEnabled));
+
+ // Cursor displayed at start.
+ EXPECT_TRUE(CursorDisplayed());
+
+ base::SimpleTestTickClock clock;
+ SetTickClock(&clock);
+
+ // Cursor displayed after mouse movement.
+ MoveMouseCursorWithinWindow();
+ EXPECT_TRUE(CursorDisplayed());
+
+ // Cursor displayed after idle period.
+ clock.Advance(base::TimeDelta::FromSeconds(5));
+ SnapshotCursorState(gfx::Rect(10, 10, 200, 200));
+ EXPECT_TRUE(CursorDisplayed());
+
+ // Cursor displayed with mouse outside the window.
+ MoveMouseCursorOutsideWindow();
+ SnapshotCursorState(gfx::Rect(10, 10, 200, 200));
+ EXPECT_TRUE(CursorDisplayed());
+}
+
TEST_F(CursorRendererAuraTest, CursorDuringMouseMovement) {
// Keep window activated.
wm::ActivateWindow(window_.get());
@@ -166,7 +194,7 @@ TEST_F(CursorRendererAuraTest, CursorOnActiveWindow) {
EXPECT_TRUE(CursorDisplayed());
// Cursor not be displayed if a second window is activated.
- scoped_ptr<aura::Window> window2(aura::test::CreateTestWindowWithBounds(
+ std::unique_ptr<aura::Window> window2(aura::test::CreateTestWindowWithBounds(
gfx::Rect(0, 0, 800, 600), root_window()));
wm::ActivateWindow(window2.get());
SnapshotCursorState(gfx::Rect(10, 10, 200, 200));
@@ -200,4 +228,21 @@ TEST_F(CursorRendererAuraTest, CursorRenderedOnFrame) {
EXPECT_TRUE(NonZeroPixelsInRegion(frame, gfx::Rect(50, 50, 70, 70)));
}
+TEST_F(CursorRendererAuraTest, CursorRenderedOnRootWindow) {
+ cursor_renderer_.reset(new CursorRendererAura(root_window(),
+ kCursorEnabledOnMouseMovement));
+ EXPECT_FALSE(CursorDisplayed());
+
+ // Cursor displayed after mouse movement.
+ MoveMouseCursorWithinWindow();
+ EXPECT_TRUE(CursorDisplayed());
+
+ // Cursor being displayed even if another window is activated.
+ std::unique_ptr<aura::Window> window2(aura::test::CreateTestWindowWithBounds(
+ gfx::Rect(0, 0, 800, 600), root_window()));
+ wm::ActivateWindow(window2.get());
+ SnapshotCursorState(gfx::Rect(0, 0, 800, 600));
+ EXPECT_TRUE(CursorDisplayed());
+}
+
} // namespace content
diff --git a/chromium/content/browser/media/capture/cursor_renderer_mac.h b/chromium/content/browser/media/capture/cursor_renderer_mac.h
new file mode 100644
index 00000000000..dc0ab1a322d
--- /dev/null
+++ b/chromium/content/browser/media/capture/cursor_renderer_mac.h
@@ -0,0 +1,48 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_CURSOR_RENDERER_MAC_H_
+#define CONTENT_BROWSER_MEDIA_CAPTURE_CURSOR_RENDERER_MAC_H_
+
+#include "base/mac/scoped_cftyperef.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "content/browser/media/capture/cursor_renderer.h"
+#include "content/common/content_export.h"
+#include "media/base/video_frame.h"
+
+namespace content {
+
+// Tracks state for making decisions on cursor display on a captured video
+// frame.
+class CONTENT_EXPORT CursorRendererMac : public CursorRenderer {
+ public:
+ explicit CursorRendererMac(NSView* view);
+ ~CursorRendererMac() final;
+
+ // CursorRender implementation.
+ void Clear() final;
+ bool SnapshotCursorState(const gfx::Rect& region_in_frame) final;
+ void RenderOnVideoFrame(
+ const scoped_refptr<media::VideoFrame>& target) const final;
+ base::WeakPtr<CursorRenderer> GetWeakPtr() final;
+
+ private:
+ NSView* const view_;
+ base::ScopedCFTypeRef<CFDataRef> last_cursor_data_;
+ int last_cursor_width_;
+ int last_cursor_height_;
+ gfx::Point cursor_position_in_frame_;
+
+ base::TimeTicks last_mouse_movement_timestamp_;
+ float last_mouse_location_x_;
+ float last_mouse_location_y_;
+
+ base::WeakPtrFactory<CursorRendererMac> weak_factory_;
+ DISALLOW_COPY_AND_ASSIGN(CursorRendererMac);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_CAPTURE_CURSOR_RENDERER_MAC_H_
diff --git a/chromium/content/browser/media/capture/cursor_renderer_mac.mm b/chromium/content/browser/media/capture/cursor_renderer_mac.mm
new file mode 100644
index 00000000000..b00394e592d
--- /dev/null
+++ b/chromium/content/browser/media/capture/cursor_renderer_mac.mm
@@ -0,0 +1,189 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/capture/cursor_renderer_mac.h"
+
+#include <ApplicationServices/ApplicationServices.h>
+#include <Cocoa/Cocoa.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <stdint.h>
+
+#include <cmath>
+
+#include "base/logging.h"
+
+namespace content {
+
+namespace {
+
+// RGBA format on cursor bitmap
+const int kBytesPerPixel = 4;
+
+inline int clip_byte(int x) {
+ return std::max(0, std::min(x, 255));
+}
+
+inline int alpha_blend(int alpha, int src, int dst) {
+ return (src * alpha + dst * (255 - alpha)) / 255;
+}
+
+} // namespace
+
+// static
+std::unique_ptr<CursorRenderer> CursorRenderer::Create(gfx::NativeView view) {
+ return std::unique_ptr<CursorRenderer>(new CursorRendererMac(view));
+}
+
+CursorRendererMac::CursorRendererMac(NSView* view)
+ : view_(view), weak_factory_(this) {
+ Clear();
+}
+
+CursorRendererMac::~CursorRendererMac() {}
+
+base::WeakPtr<CursorRenderer> CursorRendererMac::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
+void CursorRendererMac::Clear() {
+ last_cursor_data_.reset();
+ last_cursor_width_ = 0;
+ last_cursor_height_ = 0;
+ last_mouse_location_x_ = 0;
+ last_mouse_location_y_ = 0;
+ last_mouse_movement_timestamp_ = base::TimeTicks();
+}
+
+// Polls mouse cursor location and image and returns whether the mouse
+// cursor should be rendered on the frame.
+bool CursorRendererMac::SnapshotCursorState(const gfx::Rect& region_in_frame) {
+ // Mouse location in window co-ordinates.
+ NSPoint mouse_window_location =
+ [view_ window].mouseLocationOutsideOfEventStream;
+
+ // Mouse co-ordinates directly comparable against frame co-ordinates
+ // after translation.
+ if (mouse_window_location.x < 0 || mouse_window_location.y < 0 ||
+ mouse_window_location.x > region_in_frame.width() ||
+ mouse_window_location.y > region_in_frame.height()) {
+ VLOG(2) << "Mouse outside content region";
+ return false;
+ }
+
+ if (![[view_ window] isKeyWindow]) {
+ VLOG(2) << "Window currently inactive";
+ return false;
+ }
+
+ if ((base::TimeTicks::Now() - last_mouse_movement_timestamp_).InSeconds() >
+ MAX_IDLE_TIME_SECONDS &&
+ std::abs(mouse_window_location.x - last_mouse_location_x_) <
+ MIN_MOVEMENT_PIXELS &&
+ std::abs(mouse_window_location.y - last_mouse_location_y_) <
+ MIN_MOVEMENT_PIXELS) {
+ VLOG(2) << "No mouse movement in a while";
+ return false;
+ }
+
+ // Mouse cursor position within the frame.
+ cursor_position_in_frame_ =
+ gfx::Point(region_in_frame.x() + mouse_window_location.x,
+ region_in_frame.y() + mouse_window_location.y);
+
+ // Grab system cursor.
+ NSCursor* nscursor = [NSCursor currentSystemCursor];
+ NSPoint nshotspot = [nscursor hotSpot];
+ NSImage* nsimage = [nscursor image];
+ NSSize nssize = [nsimage size];
+
+ // The cursor co-ordinates in the window and the video frame co-ordinates are
+ // inverted along y-axis. We render the cursor inverse vertically on the
+ // frame. Hence the inversion on hotspot offset here.
+ cursor_position_in_frame_.Offset(-nshotspot.x,
+ -(nssize.height - nshotspot.y));
+ last_cursor_width_ = nssize.width;
+ last_cursor_height_ = nssize.height;
+
+ CGImageRef cg_image =
+ [nsimage CGImageForProposedRect:NULL context:nil hints:nil];
+ if (!cg_image)
+ return false;
+
+ if (CGImageGetBitsPerPixel(cg_image) != kBytesPerPixel * 8 ||
+ CGImageGetBytesPerRow(cg_image) !=
+ static_cast<size_t>(kBytesPerPixel * nssize.width) ||
+ CGImageGetBitsPerComponent(cg_image) != 8) {
+ return false;
+ }
+
+ CGDataProviderRef provider = CGImageGetDataProvider(cg_image);
+ CFDataRef image_data_ref = CGDataProviderCopyData(provider);
+ if (!image_data_ref)
+ return false;
+ last_cursor_data_.reset(image_data_ref, base::scoped_policy::ASSUME);
+
+ if (std::abs(mouse_window_location.x - last_mouse_location_x_) >
+ MIN_MOVEMENT_PIXELS ||
+ std::abs(mouse_window_location.y - last_mouse_location_y_) >
+ MIN_MOVEMENT_PIXELS) {
+ last_mouse_movement_timestamp_ = base::TimeTicks::Now();
+ last_mouse_location_x_ = mouse_window_location.x;
+ last_mouse_location_y_ = mouse_window_location.y;
+ }
+ return true;
+}
+
+// Helper function to composite a RGBA cursor bitmap on a YUV420 video frame.
+void CursorRendererMac::RenderOnVideoFrame(
+ const scoped_refptr<media::VideoFrame>& target) const {
+ DCHECK(target);
+ DCHECK(last_cursor_data_);
+ const uint8_t* cursor_data_ =
+ reinterpret_cast<const uint8_t*>(CFDataGetBytePtr(last_cursor_data_));
+
+ gfx::Rect visible_rect = target->visible_rect();
+ gfx::Rect rect =
+ gfx::IntersectRects(gfx::Rect(last_cursor_width_, last_cursor_height_) +
+ gfx::Vector2d(cursor_position_in_frame_.x(),
+ cursor_position_in_frame_.y()),
+ visible_rect);
+
+ for (int y = rect.y() + 1; y <= rect.bottom(); ++y) {
+ int cursor_y = rect.bottom() - y;
+ int inverted_y = visible_rect.bottom() - y;
+ uint8_t* yplane =
+ target->data(media::VideoFrame::kYPlane) +
+ inverted_y * target->row_bytes(media::VideoFrame::kYPlane);
+ uint8_t* uplane =
+ target->data(media::VideoFrame::kUPlane) +
+ (inverted_y / 2) * target->row_bytes(media::VideoFrame::kUPlane);
+ uint8_t* vplane =
+ target->data(media::VideoFrame::kVPlane) +
+ (inverted_y / 2) * target->row_bytes(media::VideoFrame::kVPlane);
+ for (int x = rect.x(); x < rect.right(); ++x) {
+ int cursor_x = x - rect.x();
+ int byte_pos = cursor_y * last_cursor_width_ * kBytesPerPixel +
+ cursor_x * kBytesPerPixel;
+ int color_r = cursor_data_[byte_pos];
+ int color_g = cursor_data_[byte_pos + 1];
+ int color_b = cursor_data_[byte_pos + 2];
+ int alpha = cursor_data_[byte_pos + 3];
+ int color_y = clip_byte(
+ ((color_r * 66 + color_g * 129 + color_b * 25 + 128) >> 8) + 16);
+ yplane[x] = alpha_blend(alpha, color_y, yplane[x]);
+
+ // Only sample U and V at even coordinates.
+ if ((x % 2 == 0) && (y % 2 == 0)) {
+ int color_u = clip_byte(
+ ((color_r * -38 + color_g * -74 + color_b * 112 + 128) >> 8) + 128);
+ int color_v = clip_byte(
+ ((color_r * 112 + color_g * -94 + color_b * -18 + 128) >> 8) + 128);
+ uplane[x / 2] = alpha_blend(alpha, color_u, uplane[x / 2]);
+ vplane[x / 2] = alpha_blend(alpha, color_v, vplane[x / 2]);
+ }
+ }
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/capture/desktop_capture_device.cc b/chromium/content/browser/media/capture/desktop_capture_device.cc
index 9359b7c9c34..a76bc8d4fd9 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device.cc
+++ b/chromium/content/browser/media/capture/desktop_capture_device.cc
@@ -64,20 +64,19 @@ bool IsFrameUnpackedOrInverted(webrtc::DesktopFrame* frame) {
class DesktopCaptureDevice::Core : public webrtc::DesktopCapturer::Callback {
public:
Core(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- scoped_ptr<webrtc::DesktopCapturer> capturer,
+ std::unique_ptr<webrtc::DesktopCapturer> capturer,
DesktopMediaID::Type type);
~Core() override;
// Implementation of VideoCaptureDevice methods.
void AllocateAndStart(const media::VideoCaptureParams& params,
- scoped_ptr<Client> client);
+ std::unique_ptr<Client> client);
void SetNotificationWindowId(gfx::NativeViewId window_id);
private:
// webrtc::DesktopCapturer::Callback interface
- webrtc::SharedMemory* CreateSharedMemory(size_t size) override;
void OnCaptureCompleted(webrtc::DesktopFrame* frame) override;
// Method that is scheduled on |task_runner_| to be called on regular interval
@@ -94,11 +93,11 @@ class DesktopCaptureDevice::Core : public webrtc::DesktopCapturer::Callback {
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
// The underlying DesktopCapturer instance used to capture frames.
- scoped_ptr<webrtc::DesktopCapturer> desktop_capturer_;
+ std::unique_ptr<webrtc::DesktopCapturer> desktop_capturer_;
// The device client which proxies device events to the controller. Accessed
// on the task_runner_ thread.
- scoped_ptr<Client> client_;
+ std::unique_ptr<Client> client_;
// Requested video capture frame rate.
float requested_frame_rate_;
@@ -107,12 +106,12 @@ class DesktopCaptureDevice::Core : public webrtc::DesktopCapturer::Callback {
webrtc::DesktopSize previous_frame_size_;
// Determines the size of frames to deliver to the |client_|.
- scoped_ptr<media::CaptureResolutionChooser> resolution_chooser_;
+ std::unique_ptr<media::CaptureResolutionChooser> resolution_chooser_;
// 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_;
+ std::unique_ptr<webrtc::DesktopFrame> output_frame_;
// Timer used to capture the frame.
base::OneShotTimer capture_timer_;
@@ -127,18 +126,18 @@ class DesktopCaptureDevice::Core : public webrtc::DesktopCapturer::Callback {
// The type of the capturer.
DesktopMediaID::Type capturer_type_;
- scoped_ptr<webrtc::BasicDesktopFrame> black_frame_;
+ std::unique_ptr<webrtc::BasicDesktopFrame> black_frame_;
// TODO(jiayl): Remove power_save_blocker_ when there is an API to keep the
// screen from sleeping for the drive-by web.
- scoped_ptr<PowerSaveBlocker> power_save_blocker_;
+ std::unique_ptr<PowerSaveBlocker> power_save_blocker_;
DISALLOW_COPY_AND_ASSIGN(Core);
};
DesktopCaptureDevice::Core::Core(
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- scoped_ptr<webrtc::DesktopCapturer> capturer,
+ std::unique_ptr<webrtc::DesktopCapturer> capturer,
DesktopMediaID::Type type)
: task_runner_(task_runner),
desktop_capturer_(std::move(capturer)),
@@ -156,13 +155,13 @@ DesktopCaptureDevice::Core::~Core() {
void DesktopCaptureDevice::Core::AllocateAndStart(
const media::VideoCaptureParams& params,
- scoped_ptr<Client> client) {
+ std::unique_ptr<Client> client) {
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK_GT(params.requested_format.frame_size.GetArea(), 0);
DCHECK_GT(params.requested_format.frame_rate, 0);
DCHECK(desktop_capturer_);
- DCHECK(client.get());
- DCHECK(!client_.get());
+ DCHECK(client);
+ DCHECK(!client_);
client_ = std::move(client);
requested_frame_rate_ = params.requested_format.frame_rate;
@@ -188,11 +187,6 @@ void DesktopCaptureDevice::Core::SetNotificationWindowId(
desktop_capturer_->SetExcludedWindow(window_id);
}
-webrtc::SharedMemory*
-DesktopCaptureDevice::Core::CreateSharedMemory(size_t size) {
- return NULL;
-}
-
void DesktopCaptureDevice::Core::OnCaptureCompleted(
webrtc::DesktopFrame* frame) {
DCHECK(task_runner_->BelongsToCurrentThread());
@@ -230,7 +224,7 @@ void DesktopCaptureDevice::Core::OnCaptureCompleted(
UMA_HISTOGRAM_TIMES(kUmaWindowCaptureTime, capture_time);
}
- scoped_ptr<webrtc::DesktopFrame> owned_frame(frame);
+ std::unique_ptr<webrtc::DesktopFrame> owned_frame(frame);
// If the frame size has changed, drop the output frame (if any), and
// determine the new output size.
@@ -253,7 +247,7 @@ void DesktopCaptureDevice::Core::OnCaptureCompleted(
// it with a black frame to avoid the video appearing frozen at the last
// frame.
if (frame->size().width() == 1 || frame->size().height() == 1) {
- if (!black_frame_.get()) {
+ if (!black_frame_) {
black_frame_.reset(new webrtc::BasicDesktopFrame(output_size));
memset(black_frame_->data(),
0,
@@ -362,7 +356,7 @@ void DesktopCaptureDevice::Core::DoCapture() {
}
// static
-scoped_ptr<media::VideoCaptureDevice> DesktopCaptureDevice::Create(
+std::unique_ptr<media::VideoCaptureDevice> DesktopCaptureDevice::Create(
const DesktopMediaID& source) {
webrtc::DesktopCaptureOptions options =
webrtc::DesktopCaptureOptions::CreateDefault();
@@ -373,40 +367,40 @@ scoped_ptr<media::VideoCaptureDevice> DesktopCaptureDevice::Create(
options.set_allow_use_magnification_api(true);
#endif
- scoped_ptr<webrtc::DesktopCapturer> capturer;
-
- switch (source.type) {
- case DesktopMediaID::TYPE_SCREEN: {
- scoped_ptr<webrtc::ScreenCapturer> screen_capturer(
- webrtc::ScreenCapturer::Create(options));
- if (screen_capturer && screen_capturer->SelectScreen(source.id)) {
- capturer.reset(new webrtc::DesktopAndCursorComposer(
- screen_capturer.release(),
- webrtc::MouseCursorMonitor::CreateForScreen(options, source.id)));
- IncrementDesktopCaptureCounter(SCREEN_CAPTURER_CREATED);
- }
- break;
- }
-
- case DesktopMediaID::TYPE_WINDOW: {
- scoped_ptr<webrtc::WindowCapturer> window_capturer(
- webrtc::CroppingWindowCapturer::Create(options));
- if (window_capturer && window_capturer->SelectWindow(source.id)) {
- window_capturer->BringSelectedWindowToFront();
- capturer.reset(new webrtc::DesktopAndCursorComposer(
- window_capturer.release(),
- webrtc::MouseCursorMonitor::CreateForWindow(options, source.id)));
- IncrementDesktopCaptureCounter(WINDOW_CAPTURER_CREATED);
- }
- break;
- }
-
- default: {
- NOTREACHED();
- }
+ std::unique_ptr<webrtc::DesktopCapturer> capturer;
+
+ switch (source.type) {
+ case DesktopMediaID::TYPE_SCREEN: {
+ std::unique_ptr<webrtc::ScreenCapturer> screen_capturer(
+ webrtc::ScreenCapturer::Create(options));
+ if (screen_capturer && screen_capturer->SelectScreen(source.id)) {
+ capturer.reset(new webrtc::DesktopAndCursorComposer(
+ screen_capturer.release(),
+ webrtc::MouseCursorMonitor::CreateForScreen(options,
+ source.id)));
+ IncrementDesktopCaptureCounter(SCREEN_CAPTURER_CREATED);
+ }
+ break;
+ }
+
+ case DesktopMediaID::TYPE_WINDOW: {
+ std::unique_ptr<webrtc::WindowCapturer> window_capturer(
+ webrtc::CroppingWindowCapturer::Create(options));
+ if (window_capturer && window_capturer->SelectWindow(source.id)) {
+ window_capturer->BringSelectedWindowToFront();
+ capturer.reset(new webrtc::DesktopAndCursorComposer(
+ window_capturer.release(),
+ webrtc::MouseCursorMonitor::CreateForWindow(options,
+ source.id)));
+ IncrementDesktopCaptureCounter(WINDOW_CAPTURER_CREATED);
+ }
+ break;
+ }
+
+ default: { NOTREACHED(); }
}
- scoped_ptr<media::VideoCaptureDevice> result;
+ std::unique_ptr<media::VideoCaptureDevice> result;
if (capturer)
result.reset(new DesktopCaptureDevice(std::move(capturer), source.type));
@@ -419,7 +413,7 @@ DesktopCaptureDevice::~DesktopCaptureDevice() {
void DesktopCaptureDevice::AllocateAndStart(
const media::VideoCaptureParams& params,
- scoped_ptr<Client> client) {
+ std::unique_ptr<Client> client) {
thread_.task_runner()->PostTask(
FROM_HERE,
base::Bind(&Core::AllocateAndStart, base::Unretained(core_.get()), params,
@@ -446,7 +440,7 @@ void DesktopCaptureDevice::SetNotificationWindowId(
}
DesktopCaptureDevice::DesktopCaptureDevice(
- scoped_ptr<webrtc::DesktopCapturer> capturer,
+ std::unique_ptr<webrtc::DesktopCapturer> capturer,
DesktopMediaID::Type type)
: thread_("desktopCaptureThread") {
#if defined(OS_WIN)
diff --git a/chromium/content/browser/media/capture/desktop_capture_device.h b/chromium/content/browser/media/capture/desktop_capture_device.h
index 7afdedc7f5a..2cb77e668bd 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device.h
+++ b/chromium/content/browser/media/capture/desktop_capture_device.h
@@ -5,9 +5,10 @@
#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_DESKTOP_CAPTURE_DEVICE_H_
#define CONTENT_BROWSER_MEDIA_CAPTURE_DESKTOP_CAPTURE_DEVICE_H_
+#include <memory>
+
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/threading/thread.h"
#include "content/common/content_export.h"
#include "content/public/browser/desktop_media_id.h"
@@ -33,14 +34,14 @@ class CONTENT_EXPORT DesktopCaptureDevice : public media::VideoCaptureDevice {
// Creates capturer for the specified |source| and then creates
// DesktopCaptureDevice for it. May return NULL in case of a failure (e.g. if
// requested window was destroyed).
- static scoped_ptr<media::VideoCaptureDevice> Create(
+ static std::unique_ptr<media::VideoCaptureDevice> Create(
const DesktopMediaID& source);
~DesktopCaptureDevice() override;
// VideoCaptureDevice interface.
void AllocateAndStart(const media::VideoCaptureParams& params,
- scoped_ptr<Client> client) override;
+ std::unique_ptr<Client> client) override;
void StopAndDeAllocate() override;
// Set the platform-dependent window id for the notification window.
@@ -50,11 +51,12 @@ class CONTENT_EXPORT DesktopCaptureDevice : public media::VideoCaptureDevice {
friend class DesktopCaptureDeviceTest;
class Core;
- DesktopCaptureDevice(scoped_ptr<webrtc::DesktopCapturer> desktop_capturer,
- DesktopMediaID::Type type);
+ DesktopCaptureDevice(
+ std::unique_ptr<webrtc::DesktopCapturer> desktop_capturer,
+ DesktopMediaID::Type type);
base::Thread thread_;
- scoped_ptr<Core> core_;
+ std::unique_ptr<Core> core_;
DISALLOW_COPY_AND_ASSIGN(DesktopCaptureDevice);
};
diff --git a/chromium/content/browser/media/capture/desktop_capture_device_aura.cc b/chromium/content/browser/media/capture/desktop_capture_device_aura.cc
index 39f7a07edf8..ac8929bfa8d 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device_aura.cc
+++ b/chromium/content/browser/media/capture/desktop_capture_device_aura.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/logging.h"
+#include "base/memory/ptr_util.h"
#include "base/timer/timer.h"
#include "content/browser/media/capture/aura_window_capture_machine.h"
#include "content/public/browser/browser_thread.h"
@@ -30,7 +31,7 @@ void SetCaptureSource(AuraWindowCaptureMachine* machine,
DesktopCaptureDeviceAura::DesktopCaptureDeviceAura(
const DesktopMediaID& source) {
AuraWindowCaptureMachine* machine = new AuraWindowCaptureMachine();
- core_.reset(new media::ScreenCaptureDeviceCore(make_scoped_ptr(machine)));
+ core_.reset(new media::ScreenCaptureDeviceCore(base::WrapUnique(machine)));
// |core_| owns |machine| and deletes it on UI thread so passing the raw
// pointer to the UI thread is safe here.
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
@@ -42,21 +43,25 @@ DesktopCaptureDeviceAura::~DesktopCaptureDeviceAura() {
}
// static
-scoped_ptr<media::VideoCaptureDevice> DesktopCaptureDeviceAura::Create(
+std::unique_ptr<media::VideoCaptureDevice> DesktopCaptureDeviceAura::Create(
const DesktopMediaID& source) {
if (source.aura_id == DesktopMediaID::kNullId)
return nullptr;
- return scoped_ptr<media::VideoCaptureDevice>(
+ return std::unique_ptr<media::VideoCaptureDevice>(
new DesktopCaptureDeviceAura(source));
}
void DesktopCaptureDeviceAura::AllocateAndStart(
const media::VideoCaptureParams& params,
- scoped_ptr<Client> client) {
+ std::unique_ptr<Client> client) {
DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString();
core_->AllocateAndStart(params, std::move(client));
}
+void DesktopCaptureDeviceAura::RequestRefreshFrame() {
+ core_->RequestRefreshFrame();
+}
+
void DesktopCaptureDeviceAura::StopAndDeAllocate() {
core_->StopAndDeAllocate();
}
diff --git a/chromium/content/browser/media/capture/desktop_capture_device_aura.h b/chromium/content/browser/media/capture/desktop_capture_device_aura.h
index 82ce5956241..73a7d53761c 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device_aura.h
+++ b/chromium/content/browser/media/capture/desktop_capture_device_aura.h
@@ -5,10 +5,10 @@
#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_DESKTOP_CAPTURE_DEVICE_AURA_H_
#define CONTENT_BROWSER_MEDIA_CAPTURE_DESKTOP_CAPTURE_DEVICE_AURA_H_
+#include <memory>
#include <string>
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
#include "content/public/browser/desktop_media_id.h"
#include "media/capture/content/screen_capture_device_core.h"
@@ -26,20 +26,21 @@ class CONTENT_EXPORT DesktopCaptureDeviceAura
public:
// Creates a VideoCaptureDevice for the Aura desktop. If |source| does not
// reference a registered aura window, returns nullptr instead.
- static scoped_ptr<media::VideoCaptureDevice> Create(
+ static std::unique_ptr<media::VideoCaptureDevice> Create(
const DesktopMediaID& source);
~DesktopCaptureDeviceAura() override;
// VideoCaptureDevice implementation.
void AllocateAndStart(const media::VideoCaptureParams& params,
- scoped_ptr<Client> client) override;
+ std::unique_ptr<Client> client) override;
+ void RequestRefreshFrame() override;
void StopAndDeAllocate() override;
private:
explicit DesktopCaptureDeviceAura(const DesktopMediaID& source);
- scoped_ptr<media::ScreenCaptureDeviceCore> core_;
+ std::unique_ptr<media::ScreenCaptureDeviceCore> core_;
DISALLOW_COPY_AND_ASSIGN(DesktopCaptureDeviceAura);
};
diff --git a/chromium/content/browser/media/capture/desktop_capture_device_aura_unittest.cc b/chromium/content/browser/media/capture/desktop_capture_device_aura_unittest.cc
index 43ed2aaef7d..e4bef80946c 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device_aura_unittest.cc
+++ b/chromium/content/browser/media/capture/desktop_capture_device_aura_unittest.cc
@@ -60,32 +60,41 @@ class MockDeviceClient : public media::VideoCaptureDevice::Client {
MOCK_METHOD0(DoReserveOutputBuffer, void(void));
MOCK_METHOD0(DoOnIncomingCapturedBuffer, void(void));
MOCK_METHOD0(DoOnIncomingCapturedVideoFrame, void(void));
+ MOCK_METHOD0(DoResurrectLastOutputBuffer, void(void));
MOCK_METHOD2(OnError,
void(const tracked_objects::Location& from_here,
const std::string& reason));
- // Trampoline methods to workaround GMOCK problems with scoped_ptr<>.
- scoped_ptr<Buffer> ReserveOutputBuffer(
+ // Trampoline methods to workaround GMOCK problems with std::unique_ptr<>.
+ std::unique_ptr<Buffer> ReserveOutputBuffer(
const gfx::Size& dimensions,
media::VideoPixelFormat format,
media::VideoPixelStorage storage) override {
EXPECT_EQ(media::PIXEL_FORMAT_I420, format);
EXPECT_EQ(media::PIXEL_STORAGE_CPU, storage);
DoReserveOutputBuffer();
- return scoped_ptr<Buffer>();
+ return std::unique_ptr<Buffer>();
}
- void OnIncomingCapturedBuffer(scoped_ptr<Buffer> buffer,
+ void OnIncomingCapturedBuffer(std::unique_ptr<Buffer> buffer,
const media::VideoCaptureFormat& frame_format,
const base::TimeTicks& timestamp) override {
DoOnIncomingCapturedBuffer();
}
void OnIncomingCapturedVideoFrame(
- scoped_ptr<Buffer> buffer,
+ std::unique_ptr<Buffer> buffer,
const scoped_refptr<media::VideoFrame>& frame,
const base::TimeTicks& timestamp) override {
DoOnIncomingCapturedVideoFrame();
}
-
+ std::unique_ptr<Buffer> ResurrectLastOutputBuffer(
+ const gfx::Size& dimensions,
+ media::VideoPixelFormat format,
+ media::VideoPixelStorage storage) override {
+ EXPECT_EQ(media::PIXEL_FORMAT_I420, format);
+ EXPECT_EQ(media::PIXEL_STORAGE_CPU, storage);
+ DoResurrectLastOutputBuffer();
+ return std::unique_ptr<Buffer>();
+ }
double GetBufferPoolUtilization() const override { return 0.0; }
};
@@ -133,21 +142,21 @@ class DesktopCaptureDeviceAuraTest : public testing::Test {
private:
base::MessageLoopForUI message_loop_;
BrowserThreadImpl browser_thread_for_ui_;
- scoped_ptr<aura::test::AuraTestHelper> helper_;
- scoped_ptr<aura::Window> desktop_window_;
- scoped_ptr<aura::test::TestWindowDelegate> window_delegate_;
+ std::unique_ptr<aura::test::AuraTestHelper> helper_;
+ std::unique_ptr<aura::Window> desktop_window_;
+ std::unique_ptr<aura::test::TestWindowDelegate> window_delegate_;
DISALLOW_COPY_AND_ASSIGN(DesktopCaptureDeviceAuraTest);
};
TEST_F(DesktopCaptureDeviceAuraTest, StartAndStop) {
- scoped_ptr<media::VideoCaptureDevice> capture_device =
+ std::unique_ptr<media::VideoCaptureDevice> capture_device =
DesktopCaptureDeviceAura::Create(
content::DesktopMediaID::RegisterAuraWindow(
content::DesktopMediaID::TYPE_SCREEN, root_window()));
- ASSERT_TRUE(capture_device.get());
+ ASSERT_TRUE(capture_device);
- scoped_ptr<MockDeviceClient> client(new MockDeviceClient());
+ std::unique_ptr<MockDeviceClient> client(new MockDeviceClient());
EXPECT_CALL(*client, OnError(_, _)).Times(0);
media::VideoCaptureParams capture_params;
diff --git a/chromium/content/browser/media/capture/desktop_capture_device_uma_types.h b/chromium/content/browser/media/capture/desktop_capture_device_uma_types.h
index 0058e9121ec..2578d6ef745 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device_uma_types.h
+++ b/chromium/content/browser/media/capture/desktop_capture_device_uma_types.h
@@ -17,6 +17,9 @@ enum DesktopCaptureCounters {
FIRST_SCREEN_CAPTURE_FAILED,
FIRST_WINDOW_CAPTURE_SUCCEEDED,
FIRST_WINDOW_CAPTURE_FAILED,
+ TAB_VIDEO_CAPTURER_CREATED,
+ TAB_AUDIO_CAPTURER_CREATED,
+ SYSTEM_LOOPBACK_AUDIO_CAPTURER_CREATED,
DESKTOP_CAPTURE_COUNTER_BOUNDARY
};
diff --git a/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc b/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc
index c7b7877cc48..a1dc021360d 100644
--- a/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc
+++ b/chromium/content/browser/media/capture/desktop_capture_device_unittest.cc
@@ -79,32 +79,41 @@ class MockDeviceClient : public media::VideoCaptureDevice::Client {
MOCK_METHOD0(DoReserveOutputBuffer, void(void));
MOCK_METHOD0(DoOnIncomingCapturedBuffer, void(void));
MOCK_METHOD0(DoOnIncomingCapturedVideoFrame, void(void));
+ MOCK_METHOD0(DoResurrectLastOutputBuffer, void(void));
MOCK_METHOD2(OnError,
void(const tracked_objects::Location& from_here,
const std::string& reason));
- // Trampoline methods to workaround GMOCK problems with scoped_ptr<>.
- scoped_ptr<Buffer> ReserveOutputBuffer(
+ // Trampoline methods to workaround GMOCK problems with std::unique_ptr<>.
+ std::unique_ptr<Buffer> ReserveOutputBuffer(
const gfx::Size& dimensions,
media::VideoPixelFormat format,
media::VideoPixelStorage storage) override {
EXPECT_TRUE(format == media::PIXEL_FORMAT_I420 &&
storage == media::PIXEL_STORAGE_CPU);
DoReserveOutputBuffer();
- return scoped_ptr<Buffer>();
+ return std::unique_ptr<Buffer>();
}
- void OnIncomingCapturedBuffer(scoped_ptr<Buffer> buffer,
+ void OnIncomingCapturedBuffer(std::unique_ptr<Buffer> buffer,
const media::VideoCaptureFormat& frame_format,
const base::TimeTicks& timestamp) override {
DoOnIncomingCapturedBuffer();
}
void OnIncomingCapturedVideoFrame(
- scoped_ptr<Buffer> buffer,
+ std::unique_ptr<Buffer> buffer,
const scoped_refptr<media::VideoFrame>& frame,
const base::TimeTicks& timestamp) override {
DoOnIncomingCapturedVideoFrame();
}
-
+ std::unique_ptr<Buffer> ResurrectLastOutputBuffer(
+ const gfx::Size& dimensions,
+ media::VideoPixelFormat format,
+ media::VideoPixelStorage storage) override {
+ EXPECT_TRUE(format == media::PIXEL_FORMAT_I420 &&
+ storage == media::PIXEL_STORAGE_CPU);
+ DoResurrectLastOutputBuffer();
+ return std::unique_ptr<Buffer>();
+ }
double GetBufferPoolUtilization() const override { return 0.0; }
};
@@ -143,7 +152,7 @@ class InvertedDesktopFrame : public webrtc::DesktopFrame {
~InvertedDesktopFrame() override {}
private:
- scoped_ptr<webrtc::DesktopFrame> original_frame_;
+ std::unique_ptr<webrtc::DesktopFrame> original_frame_;
DISALLOW_COPY_AND_ASSIGN(InvertedDesktopFrame);
};
@@ -254,21 +263,22 @@ class FormatChecker {
class DesktopCaptureDeviceTest : public testing::Test {
public:
- void CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer> capturer) {
+ void CreateScreenCaptureDevice(
+ std::unique_ptr<webrtc::DesktopCapturer> capturer) {
capture_device_.reset(new DesktopCaptureDevice(
std::move(capturer), DesktopMediaID::TYPE_SCREEN));
}
void CopyFrame(const uint8_t* frame, int size,
const media::VideoCaptureFormat&, int, base::TimeTicks) {
- ASSERT_TRUE(output_frame_.get() != NULL);
+ ASSERT_TRUE(output_frame_);
ASSERT_EQ(output_frame_->stride() * output_frame_->size().height(), size);
memcpy(output_frame_->data(), frame, size);
}
protected:
- scoped_ptr<DesktopCaptureDevice> capture_device_;
- scoped_ptr<webrtc::DesktopFrame> output_frame_;
+ std::unique_ptr<DesktopCaptureDevice> capture_device_;
+ std::unique_ptr<webrtc::DesktopFrame> output_frame_;
};
// There is currently no screen capturer implementation for ozone. So disable
@@ -280,7 +290,7 @@ class DesktopCaptureDeviceTest : public testing::Test {
#define MAYBE_Capture Capture
#endif
TEST_F(DesktopCaptureDeviceTest, MAYBE_Capture) {
- scoped_ptr<webrtc::DesktopCapturer> capturer(
+ std::unique_ptr<webrtc::DesktopCapturer> capturer(
webrtc::ScreenCapturer::Create(
webrtc::DesktopCaptureOptions::CreateDefault()));
CreateScreenCaptureDevice(std::move(capturer));
@@ -289,7 +299,7 @@ TEST_F(DesktopCaptureDeviceTest, MAYBE_Capture) {
base::WaitableEvent done_event(false, false);
int frame_size;
- scoped_ptr<MockDeviceClient> client(new MockDeviceClient());
+ std::unique_ptr<MockDeviceClient> client(new MockDeviceClient());
EXPECT_CALL(*client, OnError(_, _)).Times(0);
EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly(
DoAll(SaveArg<1>(&frame_size),
@@ -317,13 +327,14 @@ TEST_F(DesktopCaptureDeviceTest, MAYBE_Capture) {
TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeConstantResolution) {
FakeScreenCapturer* mock_capturer = new FakeScreenCapturer();
- CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer>(mock_capturer));
+ CreateScreenCaptureDevice(
+ std::unique_ptr<webrtc::DesktopCapturer>(mock_capturer));
FormatChecker format_checker(gfx::Size(kTestFrameWidth1, kTestFrameHeight1),
gfx::Size(kTestFrameWidth1, kTestFrameHeight1));
base::WaitableEvent done_event(false, false);
- scoped_ptr<MockDeviceClient> client(new MockDeviceClient());
+ std::unique_ptr<MockDeviceClient> client(new MockDeviceClient());
EXPECT_CALL(*client, OnError(_, _)).Times(0);
EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly(
DoAll(WithArg<2>(Invoke(&format_checker,
@@ -358,12 +369,13 @@ TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeConstantResolution) {
TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeFixedAspectRatio) {
FakeScreenCapturer* mock_capturer = new FakeScreenCapturer();
- CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer>(mock_capturer));
+ CreateScreenCaptureDevice(
+ std::unique_ptr<webrtc::DesktopCapturer>(mock_capturer));
FormatChecker format_checker(gfx::Size(888, 500), gfx::Size(532, 300));
base::WaitableEvent done_event(false, false);
- scoped_ptr<MockDeviceClient> client(new MockDeviceClient());
+ std::unique_ptr<MockDeviceClient> client(new MockDeviceClient());
EXPECT_CALL(*client, OnError(_,_)).Times(0);
EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly(
DoAll(WithArg<2>(Invoke(&format_checker,
@@ -401,13 +413,14 @@ TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeFixedAspectRatio) {
TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeVariableResolution) {
FakeScreenCapturer* mock_capturer = new FakeScreenCapturer();
- CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer>(mock_capturer));
+ CreateScreenCaptureDevice(
+ std::unique_ptr<webrtc::DesktopCapturer>(mock_capturer));
FormatChecker format_checker(gfx::Size(kTestFrameWidth1, kTestFrameHeight1),
gfx::Size(kTestFrameWidth2, kTestFrameHeight2));
base::WaitableEvent done_event(false, false);
- scoped_ptr<MockDeviceClient> client(new MockDeviceClient());
+ std::unique_ptr<MockDeviceClient> client(new MockDeviceClient());
EXPECT_CALL(*client, OnError(_,_)).Times(0);
EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly(
DoAll(WithArg<2>(Invoke(&format_checker,
@@ -444,7 +457,8 @@ TEST_F(DesktopCaptureDeviceTest, ScreenResolutionChangeVariableResolution) {
TEST_F(DesktopCaptureDeviceTest, UnpackedFrame) {
FakeScreenCapturer* mock_capturer = new FakeScreenCapturer();
mock_capturer->set_generate_cropped_frames(true);
- CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer>(mock_capturer));
+ CreateScreenCaptureDevice(
+ std::unique_ptr<webrtc::DesktopCapturer>(mock_capturer));
media::VideoCaptureFormat format;
base::WaitableEvent done_event(false, false);
@@ -453,7 +467,7 @@ TEST_F(DesktopCaptureDeviceTest, UnpackedFrame) {
output_frame_.reset(new webrtc::BasicDesktopFrame(
webrtc::DesktopSize(kTestFrameWidth1, kTestFrameHeight1)));
- scoped_ptr<MockDeviceClient> client(new MockDeviceClient());
+ std::unique_ptr<MockDeviceClient> client(new MockDeviceClient());
EXPECT_CALL(*client, OnError(_,_)).Times(0);
EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly(
DoAll(Invoke(this, &DesktopCaptureDeviceTest::CopyFrame),
@@ -475,7 +489,7 @@ TEST_F(DesktopCaptureDeviceTest, UnpackedFrame) {
// Verifies that |output_frame_| has the same data as a packed frame of the
// same size.
- scoped_ptr<webrtc::BasicDesktopFrame> expected_frame(CreateBasicFrame(
+ std::unique_ptr<webrtc::BasicDesktopFrame> expected_frame(CreateBasicFrame(
webrtc::DesktopSize(kTestFrameWidth1, kTestFrameHeight1)));
EXPECT_EQ(output_frame_->stride() * output_frame_->size().height(),
frame_size);
@@ -487,7 +501,8 @@ TEST_F(DesktopCaptureDeviceTest, UnpackedFrame) {
TEST_F(DesktopCaptureDeviceTest, InvertedFrame) {
FakeScreenCapturer* mock_capturer = new FakeScreenCapturer();
mock_capturer->set_generate_inverted_frames(true);
- CreateScreenCaptureDevice(scoped_ptr<webrtc::DesktopCapturer>(mock_capturer));
+ CreateScreenCaptureDevice(
+ std::unique_ptr<webrtc::DesktopCapturer>(mock_capturer));
media::VideoCaptureFormat format;
base::WaitableEvent done_event(false, false);
@@ -496,7 +511,7 @@ TEST_F(DesktopCaptureDeviceTest, InvertedFrame) {
output_frame_.reset(new webrtc::BasicDesktopFrame(
webrtc::DesktopSize(kTestFrameWidth1, kTestFrameHeight1)));
- scoped_ptr<MockDeviceClient> client(new MockDeviceClient());
+ std::unique_ptr<MockDeviceClient> client(new MockDeviceClient());
EXPECT_CALL(*client, OnError(_,_)).Times(0);
EXPECT_CALL(*client, OnIncomingCapturedData(_, _, _, _, _)).WillRepeatedly(
DoAll(Invoke(this, &DesktopCaptureDeviceTest::CopyFrame),
@@ -517,7 +532,7 @@ TEST_F(DesktopCaptureDeviceTest, InvertedFrame) {
// Verifies that |output_frame_| has the same pixel values as the inverted
// frame.
- scoped_ptr<webrtc::DesktopFrame> inverted_frame(
+ std::unique_ptr<webrtc::DesktopFrame> inverted_frame(
new InvertedDesktopFrame(CreateBasicFrame(
webrtc::DesktopSize(kTestFrameWidth1, kTestFrameHeight1))));
EXPECT_EQ(output_frame_->stride() * output_frame_->size().height(),
diff --git a/chromium/content/browser/media/capture/web_contents_audio_input_stream.cc b/chromium/content/browser/media/capture/web_contents_audio_input_stream.cc
index 50051a1a8cb..ce8f7f46419 100644
--- a/chromium/content/browser/media/capture/web_contents_audio_input_stream.cc
+++ b/chromium/content/browser/media/capture/web_contents_audio_input_stream.cc
@@ -4,13 +4,13 @@
#include "content/browser/media/capture/web_contents_audio_input_stream.h"
+#include <memory>
#include <string>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/threading/thread_checker.h"
#include "content/browser/media/capture/audio_mirroring_manager.h"
#include "content/browser/media/capture/web_contents_tracker.h"
@@ -101,7 +101,7 @@ class WebContentsAudioInputStream::Impl
const scoped_refptr<WebContentsTracker> tracker_;
// The AudioInputStream implementation that handles the audio conversion and
// mixing details.
- const scoped_ptr<media::VirtualAudioInputStream> mixer_stream_;
+ const std::unique_ptr<media::VirtualAudioInputStream> mixer_stream_;
State state_;
@@ -131,8 +131,8 @@ WebContentsAudioInputStream::Impl::Impl(
is_target_lost_(false),
callback_(NULL) {
DCHECK(mirroring_manager_);
- DCHECK(tracker_.get());
- DCHECK(mixer_stream_.get());
+ DCHECK(tracker_);
+ DCHECK(mixer_stream_);
// WAIS::Impl can be constructed on any thread, but will DCHECK that all
// its methods from here on are called from the same thread.
@@ -228,23 +228,19 @@ void WebContentsAudioInputStream::Impl::ReportError() {
void WebContentsAudioInputStream::Impl::StartMirroring() {
DCHECK(thread_checker_.CalledOnValidThread());
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&AudioMirroringManager::StartMirroring,
- base::Unretained(mirroring_manager_),
- make_scoped_refptr(this)));
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&AudioMirroringManager::StartMirroring,
+ base::Unretained(mirroring_manager_),
+ base::RetainedRef(this)));
}
void WebContentsAudioInputStream::Impl::StopMirroring() {
DCHECK(thread_checker_.CalledOnValidThread());
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&AudioMirroringManager::StopMirroring,
- base::Unretained(mirroring_manager_),
- make_scoped_refptr(this)));
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&AudioMirroringManager::StopMirroring,
+ base::Unretained(mirroring_manager_),
+ base::RetainedRef(this)));
}
void WebContentsAudioInputStream::Impl::UnmuteWebContentsAudio() {
diff --git a/chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc b/chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc
index 1e8ef1f8f3f..6ec220f767a 100644
--- a/chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc
+++ b/chromium/content/browser/media/capture/web_contents_audio_input_stream_unittest.cc
@@ -361,10 +361,10 @@ class WebContentsAudioInputStreamTest : public testing::Test {
change_callback_.Run(render_process_id != -1 && render_frame_id != -1);
}
- scoped_ptr<TestBrowserThreadBundle> thread_bundle_;
+ std::unique_ptr<TestBrowserThreadBundle> thread_bundle_;
base::Thread audio_thread_;
- scoped_ptr<MockAudioMirroringManager> mock_mirroring_manager_;
+ std::unique_ptr<MockAudioMirroringManager> mock_mirroring_manager_;
scoped_refptr<MockWebContentsTracker> mock_tracker_;
MockVirtualAudioInputStream* mock_vais_; // Owned by wcais_.
diff --git a/chromium/content/browser/media/capture/web_contents_audio_muter.cc b/chromium/content/browser/media/capture/web_contents_audio_muter.cc
index 82a03fa5cf2..e99c768d4bc 100644
--- a/chromium/content/browser/media/capture/web_contents_audio_muter.cc
+++ b/chromium/content/browser/media/capture/web_contents_audio_muter.cc
@@ -55,7 +55,7 @@ class AudioDiscarder : public media::AudioOutputStream {
// Calls FetchAudioData() at regular intervals and discards the data.
media::FakeAudioWorker worker_;
- scoped_ptr<media::AudioBus> audio_bus_;
+ std::unique_ptr<media::AudioBus> audio_bus_;
DISALLOW_COPY_AND_ASSIGN(AudioDiscarder);
};
@@ -133,11 +133,10 @@ void WebContentsAudioMuter::StartMuting() {
return;
is_muting_ = true;
BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
+ BrowserThread::IO, FROM_HERE,
base::Bind(&AudioMirroringManager::StartMirroring,
base::Unretained(AudioMirroringManager::GetInstance()),
- destination_));
+ base::RetainedRef(destination_)));
}
void WebContentsAudioMuter::StopMuting() {
@@ -146,11 +145,10 @@ void WebContentsAudioMuter::StopMuting() {
return;
is_muting_ = false;
BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
+ BrowserThread::IO, FROM_HERE,
base::Bind(&AudioMirroringManager::StopMirroring,
base::Unretained(AudioMirroringManager::GetInstance()),
- destination_));
+ base::RetainedRef(destination_)));
}
} // namespace content
diff --git a/chromium/content/browser/media/capture/web_contents_tracker.cc b/chromium/content/browser/media/capture/web_contents_tracker.cc
index 5007a583af8..01bc9b0b461 100644
--- a/chromium/content/browser/media/capture/web_contents_tracker.cc
+++ b/chromium/content/browser/media/capture/web_contents_tracker.cc
@@ -24,10 +24,10 @@ WebContentsTracker::~WebContentsTracker() {
void WebContentsTracker::Start(int render_process_id, int main_render_frame_id,
const ChangeCallback& callback) {
- DCHECK(!task_runner_.get() || task_runner_->BelongsToCurrentThread());
+ DCHECK(!task_runner_ || task_runner_->BelongsToCurrentThread());
task_runner_ = base::ThreadTaskRunnerHandle::Get();
- DCHECK(task_runner_.get());
+ DCHECK(task_runner_);
callback_ = callback;
if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
@@ -81,7 +81,7 @@ RenderWidgetHost* WebContentsTracker::GetTargetRenderWidgetHost() const {
void WebContentsTracker::SetResizeChangeCallback(
const base::Closure& callback) {
- DCHECK(!task_runner_.get() || task_runner_->BelongsToCurrentThread());
+ DCHECK(!task_runner_ || task_runner_->BelongsToCurrentThread());
resize_callback_ = callback;
}
diff --git a/chromium/content/browser/media/capture/web_contents_video_capture_device.cc b/chromium/content/browser/media/capture/web_contents_video_capture_device.cc
index bf2ef5ac662..0733a1fd9a9 100644
--- a/chromium/content/browser/media/capture/web_contents_video_capture_device.cc
+++ b/chromium/content/browser/media/capture/web_contents_video_capture_device.cc
@@ -51,7 +51,9 @@
#include "content/browser/media/capture/web_contents_video_capture_device.h"
#include <stdint.h>
+
#include <algorithm>
+#include <memory>
#include <utility>
#include "base/bind.h"
@@ -59,7 +61,6 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/histogram.h"
#include "base/sequenced_task_runner.h"
@@ -93,11 +94,6 @@
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/geometry/size_conversions.h"
-#if defined(USE_AURA)
-#include "content/browser/media/capture/cursor_renderer_aura.h"
-#include "content/browser/media/capture/window_activity_tracker_aura.h"
-#endif
-
namespace content {
namespace {
@@ -110,7 +106,7 @@ enum InteractiveModeSettings {
kMinPeriodNoAnimationMillis = 3000
};
-void DeleteOnWorkerThread(scoped_ptr<base::Thread> render_thread,
+void DeleteOnWorkerThread(std::unique_ptr<base::Thread> render_thread,
const base::Closure& callback) {
render_thread.reset();
@@ -188,19 +184,19 @@ class FrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
// knows how to do the capture and prepare the result for delivery.
//
// In practice, this means (a) installing a RenderWidgetHostFrameSubscriber in
-// the RenderWidgetHostView, to process compositor updates, and (b) running a
-// timer to possibly initiate forced, non-event-driven captures needed by
-// downstream consumers that require frame repeats of unchanged content.
+// the RenderWidgetHostView, to process compositor updates, and (b) occasionally
+// initiating forced, non-event-driven captures needed by downstream consumers
+// that request "refresh frames" of unchanged content.
//
// All of this happens on the UI thread, although the
// RenderWidgetHostViewFrameSubscriber we install may be dispatching updates
// autonomously on some other thread.
class ContentCaptureSubscription {
public:
- typedef base::Callback<
- void(const base::TimeTicks&,
- const scoped_refptr<media::VideoFrame>&,
- const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback&)>
+ typedef base::Callback<void(
+ const base::TimeTicks&,
+ const scoped_refptr<media::VideoFrame>&,
+ const RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback&)>
CaptureCallback;
// Create a subscription. Whenever a manual capture is required, the
@@ -212,8 +208,11 @@ class ContentCaptureSubscription {
const CaptureCallback& capture_callback);
~ContentCaptureSubscription();
+ void MaybeCaptureForRefresh();
+
private:
- void OnTimer();
+ // Called for active frame refresh requests, or mouse activity events.
+ void OnEvent(FrameSubscriber* subscriber);
// Maintain a weak reference to the RenderWidgetHost (via its routing ID),
// since the instance could be destroyed externally during the lifetime of
@@ -222,18 +221,18 @@ class ContentCaptureSubscription {
const int render_widget_id_;
VideoFrameDeliveryLog delivery_log_;
- scoped_ptr<FrameSubscriber> timer_subscriber_;
+ std::unique_ptr<FrameSubscriber> refresh_subscriber_;
+ std::unique_ptr<FrameSubscriber> mouse_activity_subscriber_;
CaptureCallback capture_callback_;
- base::Timer timer_;
// Responsible for tracking the cursor state and input events to make
// decisions and then render the mouse cursor on the video frame after
// capture is completed.
- scoped_ptr<content::CursorRenderer> cursor_renderer_;
+ std::unique_ptr<content::CursorRenderer> cursor_renderer_;
// Responsible for tracking the UI events and making a decision on whether
// user is actively interacting with content.
- scoped_ptr<content::WindowActivityTracker> window_activity_tracker_;
+ std::unique_ptr<content::WindowActivityTracker> window_activity_tracker_;
DISALLOW_COPY_AND_ASSIGN(ContentCaptureSubscription);
};
@@ -269,6 +268,7 @@ class WebContentsCaptureMachine : public media::VideoCaptureMachine {
bool IsAutoThrottlingEnabled() const override {
return auto_throttling_enabled_;
}
+ void MaybeCaptureForRefresh() override;
// Starts a copy from the backing store or the composited surface. Must be run
// on the UI BrowserThread. |deliver_frame_cb| will be run when the operation
@@ -285,6 +285,7 @@ class WebContentsCaptureMachine : public media::VideoCaptureMachine {
const scoped_refptr<media::ThreadSafeCaptureOracle>& oracle_proxy,
const media::VideoCaptureParams& params);
void InternalStop(const base::Closure& callback);
+ void InternalMaybeCaptureForRefresh();
bool IsStarted() const;
// Computes the preferred size of the target RenderWidget for optimal capture.
@@ -329,7 +330,7 @@ class WebContentsCaptureMachine : public media::VideoCaptureMachine {
// A dedicated worker thread on which SkBitmap->VideoFrame conversion will
// occur. Only used when this activity cannot be done on the GPU.
- scoped_ptr<base::Thread> render_thread_;
+ std::unique_ptr<base::Thread> render_thread_;
// Makes all the decisions about which frames to copy, and how.
scoped_refptr<media::ThreadSafeCaptureOracle> oracle_proxy_;
@@ -342,7 +343,7 @@ class WebContentsCaptureMachine : public media::VideoCaptureMachine {
// Responsible for forwarding events from the active RenderWidgetHost to the
// oracle, and initiating captures accordingly.
- scoped_ptr<ContentCaptureSubscription> subscription_;
+ std::unique_ptr<ContentCaptureSubscription> subscription_;
// Weak pointer factory used to invalidate callbacks.
// NOTE: Weak pointers must be invalidated before all other member variables.
@@ -356,8 +357,8 @@ bool FrameSubscriber::ShouldCaptureFrame(
base::TimeTicks present_time,
scoped_refptr<media::VideoFrame>* storage,
DeliverFrameCallback* deliver_frame_cb) {
- TRACE_EVENT1("gpu.capture", "FrameSubscriber::ShouldCaptureFrame",
- "instance", this);
+ TRACE_EVENT1("gpu.capture", "FrameSubscriber::ShouldCaptureFrame", "instance",
+ this);
media::ThreadSafeCaptureOracle::CaptureFrameCallback capture_frame_cb;
@@ -405,17 +406,17 @@ void FrameSubscriber::DidCaptureFrame(
bool FrameSubscriber::IsUserInteractingWithContent() {
bool interactive_mode = false;
bool ui_activity = false;
- if (window_activity_tracker_.get()) {
+ if (window_activity_tracker_) {
ui_activity = window_activity_tracker_->IsUiInteractionActive();
}
- if (cursor_renderer_.get()) {
+ if (cursor_renderer_) {
bool animation_active =
(base::TimeTicks::Now() -
oracle_proxy_->last_time_animation_was_detected()) <
base::TimeDelta::FromMilliseconds(kMinPeriodNoAnimationMillis);
if (ui_activity && !animation_active) {
interactive_mode = true;
- } else if (animation_active) {
+ } else if (animation_active && window_activity_tracker_.get()) {
window_activity_tracker_->Reset();
}
}
@@ -429,39 +430,35 @@ ContentCaptureSubscription::ContentCaptureSubscription(
: render_process_id_(source.GetProcess()->GetID()),
render_widget_id_(source.GetRoutingID()),
delivery_log_(),
- capture_callback_(capture_callback),
- timer_(true, true) {
+ capture_callback_(capture_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderWidgetHostView* const view = source.GetView();
-// TODO(isheriff): Cursor resources currently only available on linux. Remove
-// this once we add the necessary resources for windows.
-// https://crbug.com/554280 https://crbug.com/549182
-#if defined(USE_AURA) && defined(OS_LINUX)
- if (view) {
- cursor_renderer_.reset(
- new content::CursorRendererAura(view->GetNativeView()));
- }
-#endif
-// TODO(isheriff): Needs implementation on non-aura platforms.
-// https://crbug.com/567735
-#if defined(USE_AURA)
+#if defined(USE_AURA) || defined(OS_MACOSX)
if (view) {
- window_activity_tracker_.reset(
- new content::WindowActivityTrackerAura(view->GetNativeView()));
+ cursor_renderer_ = CursorRenderer::Create(view->GetNativeView());
+ window_activity_tracker_ =
+ WindowActivityTracker::Create(view->GetNativeView());
}
#endif
- timer_subscriber_.reset(new FrameSubscriber(
- media::VideoCaptureOracle::kTimerPoll, oracle_proxy, &delivery_log_,
+ refresh_subscriber_.reset(new FrameSubscriber(
+ media::VideoCaptureOracle::kActiveRefreshRequest, oracle_proxy,
+ &delivery_log_,
cursor_renderer_ ? cursor_renderer_->GetWeakPtr()
: base::WeakPtr<CursorRenderer>(),
window_activity_tracker_ ? window_activity_tracker_->GetWeakPtr()
: base::WeakPtr<WindowActivityTracker>()));
+ mouse_activity_subscriber_.reset(new FrameSubscriber(
+ media::VideoCaptureOracle::kMouseCursorUpdate, oracle_proxy,
+ &delivery_log_, cursor_renderer_ ? cursor_renderer_->GetWeakPtr()
+ : base::WeakPtr<CursorRenderer>(),
+ window_activity_tracker_ ? window_activity_tracker_->GetWeakPtr()
+ : base::WeakPtr<WindowActivityTracker>()));
// Subscribe to compositor updates. These will be serviced directly by the
// oracle.
if (view) {
- scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber(
+ std::unique_ptr<RenderWidgetHostViewFrameSubscriber> subscriber(
new FrameSubscriber(
media::VideoCaptureOracle::kCompositorUpdate, oracle_proxy,
&delivery_log_, cursor_renderer_ ? cursor_renderer_->GetWeakPtr()
@@ -471,13 +468,12 @@ ContentCaptureSubscription::ContentCaptureSubscription(
view->BeginFrameSubscription(std::move(subscriber));
}
- // Subscribe to timer events. This instance will service these as well.
- timer_.Start(FROM_HERE,
- std::max(oracle_proxy->min_capture_period(),
- base::TimeDelta::FromMilliseconds(media
- ::VideoCaptureOracle::kMinTimerPollPeriodMillis)),
- base::Bind(&ContentCaptureSubscription::OnTimer,
- base::Unretained(this)));
+ // Subscribe to mouse movement and mouse cursor update events.
+ if (window_activity_tracker_) {
+ window_activity_tracker_->RegisterMouseInteractionObserver(
+ base::Bind(&ContentCaptureSubscription::OnEvent, base::Unretained(this),
+ mouse_activity_subscriber_.get()));
+ }
}
ContentCaptureSubscription::~ContentCaptureSubscription() {
@@ -495,16 +491,23 @@ ContentCaptureSubscription::~ContentCaptureSubscription() {
view->EndFrameSubscription();
}
-void ContentCaptureSubscription::OnTimer() {
+void ContentCaptureSubscription::MaybeCaptureForRefresh() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- TRACE_EVENT0("gpu.capture", "ContentCaptureSubscription::OnTimer");
+ OnEvent(refresh_subscriber_.get());
+}
+
+void ContentCaptureSubscription::OnEvent(FrameSubscriber* subscriber) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ TRACE_EVENT0("gpu.capture", "ContentCaptureSubscription::OnEvent");
scoped_refptr<media::VideoFrame> frame;
RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback deliver_frame_cb;
const base::TimeTicks start_time = base::TimeTicks::Now();
- if (timer_subscriber_->ShouldCaptureFrame(gfx::Rect(), start_time, &frame,
- &deliver_frame_cb)) {
+ DCHECK(subscriber == refresh_subscriber_.get() ||
+ subscriber == mouse_activity_subscriber_.get());
+ if (subscriber->ShouldCaptureFrame(gfx::Rect(), start_time, &frame,
+ &deliver_frame_cb)) {
capture_callback_.Run(start_time, frame, deliver_frame_cb);
}
}
@@ -519,12 +522,10 @@ void RenderVideoFrame(
SkAutoLockPixels locker(input);
// Sanity-check the captured bitmap.
- if (input.empty() ||
- !input.readyToDraw() ||
- input.colorType() != kN32_SkColorType ||
- input.width() < 2 || input.height() < 2) {
- DVLOG(1) << "input unacceptable (size="
- << input.getSize()
+ if (input.empty() || !input.readyToDraw() ||
+ input.colorType() != kN32_SkColorType || input.width() < 2 ||
+ input.height() < 2) {
+ DVLOG(1) << "input unacceptable (size=" << input.getSize()
<< ", ready=" << input.readyToDraw()
<< ", colorType=" << input.colorType() << ')';
return;
@@ -555,11 +556,10 @@ void RenderVideoFrame(
method = skia::ImageOperations::RESIZE_BOX;
}
- TRACE_EVENT_ASYNC_STEP_INTO0("gpu.capture",
- "Capture", output.get(), "Scale");
- scaled_bitmap = skia::ImageOperations::Resize(input, method,
- region_in_frame.width(),
- region_in_frame.height());
+ TRACE_EVENT_ASYNC_STEP_INTO0("gpu.capture", "Capture", output.get(),
+ "Scale");
+ scaled_bitmap = skia::ImageOperations::Resize(
+ input, method, region_in_frame.width(), region_in_frame.height());
} else {
scaled_bitmap = input;
}
@@ -568,10 +568,9 @@ void RenderVideoFrame(
{
// Align to 2x2 pixel boundaries, as required by
// media::CopyRGBToVideoFrame().
- const gfx::Rect region_in_yv12_frame(region_in_frame.x() & ~1,
- region_in_frame.y() & ~1,
- region_in_frame.width() & ~1,
- region_in_frame.height() & ~1);
+ const gfx::Rect region_in_yv12_frame(
+ region_in_frame.x() & ~1, region_in_frame.y() & ~1,
+ region_in_frame.width() & ~1, region_in_frame.height() & ~1);
if (region_in_yv12_frame.IsEmpty())
return;
@@ -587,9 +586,7 @@ void RenderVideoFrame(
}
VideoFrameDeliveryLog::VideoFrameDeliveryLog()
- : last_frame_rate_log_time_(),
- count_frames_rendered_(0) {
-}
+ : last_frame_rate_log_time_(), count_frames_rendered_(0) {}
void VideoFrameDeliveryLog::ChronicleFrameDelivery(base::TimeTicks frame_time) {
// Log frame rate, if verbose logging is turned on.
@@ -602,11 +599,9 @@ void VideoFrameDeliveryLog::ChronicleFrameDelivery(base::TimeTicks frame_time) {
++count_frames_rendered_;
const base::TimeDelta elapsed = frame_time - last_frame_rate_log_time_;
if (elapsed >= kFrameRateLogInterval) {
- const double measured_fps =
- count_frames_rendered_ / elapsed.InSecondsF();
- UMA_HISTOGRAM_COUNTS(
- "TabCapture.FrameRate",
- static_cast<int>(measured_fps));
+ const double measured_fps = count_frames_rendered_ / elapsed.InSecondsF();
+ UMA_HISTOGRAM_COUNTS("TabCapture.FrameRate",
+ static_cast<int>(measured_fps));
VLOG(1) << "Current measured frame rate for "
<< "WebContentsVideoCaptureDevice is " << measured_fps << " FPS.";
last_frame_rate_log_time_ = frame_time;
@@ -624,8 +619,8 @@ WebContentsCaptureMachine::WebContentsCaptureMachine(
tracker_(new WebContentsTracker(true)),
auto_throttling_enabled_(enable_auto_throttling),
weak_ptr_factory_(this) {
- DVLOG(1) << "Created WebContentsCaptureMachine for "
- << render_process_id << ':' << main_render_frame_id
+ DVLOG(1) << "Created WebContentsCaptureMachine for " << render_process_id
+ << ':' << main_render_frame_id
<< (auto_throttling_enabled_ ? " with auto-throttling enabled" : "");
}
@@ -642,12 +637,9 @@ void WebContentsCaptureMachine::Start(
const base::Callback<void(bool)> callback) {
// Starts the capture machine asynchronously.
BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI,
- FROM_HERE,
+ BrowserThread::UI, FROM_HERE,
base::Bind(&WebContentsCaptureMachine::InternalStart,
- base::Unretained(this),
- oracle_proxy,
- params),
+ base::Unretained(this), oracle_proxy, params),
callback);
}
@@ -657,7 +649,7 @@ bool WebContentsCaptureMachine::InternalStart(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(!IsStarted());
- DCHECK(oracle_proxy.get());
+ DCHECK(oracle_proxy);
oracle_proxy_ = oracle_proxy;
capture_params_ = params;
@@ -682,11 +674,9 @@ bool WebContentsCaptureMachine::InternalStart(
void WebContentsCaptureMachine::Stop(const base::Closure& callback) {
// Stops the capture machine asynchronously.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE, base::Bind(
- &WebContentsCaptureMachine::InternalStop,
- base::Unretained(this),
- callback));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&WebContentsCaptureMachine::InternalStop,
+ base::Unretained(this), callback));
}
void WebContentsCaptureMachine::InternalStop(const base::Closure& callback) {
@@ -708,14 +698,28 @@ void WebContentsCaptureMachine::InternalStop(const base::Closure& callback) {
// The render thread cannot be stopped on the UI thread, so post a message
// to the thread pool used for blocking operations.
- if (render_thread_.get()) {
+ if (render_thread_) {
BrowserThread::PostBlockingPoolTask(
- FROM_HERE,
- base::Bind(&DeleteOnWorkerThread, base::Passed(&render_thread_),
- callback));
+ FROM_HERE, base::Bind(&DeleteOnWorkerThread,
+ base::Passed(&render_thread_), callback));
}
}
+void WebContentsCaptureMachine::MaybeCaptureForRefresh() {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&WebContentsCaptureMachine::InternalMaybeCaptureForRefresh,
+ // Use of Unretained() is safe here since this task must run
+ // before InternalStop().
+ base::Unretained(this)));
+}
+
+void WebContentsCaptureMachine::InternalMaybeCaptureForRefresh() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (IsStarted() && subscription_)
+ subscription_->MaybeCaptureForRefresh();
+}
+
void WebContentsCaptureMachine::Capture(
const base::TimeTicks& start_time,
const scoped_refptr<media::VideoFrame>& target,
@@ -736,29 +740,28 @@ void WebContentsCaptureMachine::Capture(
last_view_size_ = view_size;
// Measure the number of kilopixels.
- UMA_HISTOGRAM_COUNTS_10000(
- "TabCapture.ViewChangeKiloPixels",
- view_size.width() * view_size.height() / 1024);
+ UMA_HISTOGRAM_COUNTS_10000("TabCapture.ViewChangeKiloPixels",
+ view_size.width() * view_size.height() / 1024);
}
if (view->CanCopyToVideoFrame()) {
view->CopyFromCompositingSurfaceToVideoFrame(
- gfx::Rect(view_size),
- target,
+ gfx::Rect(view_size), target,
base::Bind(&WebContentsCaptureMachine::
- DidCopyFromCompositingSurfaceToVideoFrame,
- weak_ptr_factory_.GetWeakPtr(),
- start_time, deliver_frame_cb));
+ DidCopyFromCompositingSurfaceToVideoFrame,
+ weak_ptr_factory_.GetWeakPtr(), start_time,
+ deliver_frame_cb));
} else {
- const gfx::Size fitted_size = view_size.IsEmpty() ? gfx::Size() :
- media::ComputeLetterboxRegion(target->visible_rect(), view_size).size();
+ const gfx::Size fitted_size =
+ view_size.IsEmpty()
+ ? gfx::Size()
+ : media::ComputeLetterboxRegion(target->visible_rect(), view_size)
+ .size();
rwh->CopyFromBackingStore(
gfx::Rect(),
fitted_size, // Size here is a request not always honored.
base::Bind(&WebContentsCaptureMachine::DidCopyFromBackingStore,
- weak_ptr_factory_.GetWeakPtr(),
- start_time,
- target,
+ weak_ptr_factory_.GetWeakPtr(), start_time, target,
deliver_frame_cb),
kN32_SkColorType);
}
@@ -784,18 +787,17 @@ gfx::Size WebContentsCaptureMachine::ComputeOptimalViewSize() const {
// issues caused by "one pixel stretching" and/or odd-to-even dimension
// scaling, and to improve the performance of consumers of the captured
// video.
- const auto HasIntendedAspectRatio =
- [](const gfx::Size& size, int width_units, int height_units) {
+ const auto HasIntendedAspectRatio = [](
+ const gfx::Size& size, int width_units, int height_units) {
const int a = height_units * size.width();
const int b = width_units * size.height();
const int percentage_diff = 100 * std::abs((a - b)) / b;
return percentage_diff <= 1; // Effectively, anything strictly <2%.
};
- const auto RoundToExactAspectRatio =
- [](const gfx::Size& size, int width_step, int height_step) {
- const int adjusted_height =
- std::max(size.height() - (size.height() % height_step),
- height_step);
+ const auto RoundToExactAspectRatio = [](const gfx::Size& size,
+ int width_step, int height_step) {
+ const int adjusted_height = std::max(
+ size.height() - (size.height() % height_step), height_step);
DCHECK_EQ((adjusted_height * width_step) % height_step, 0);
return gfx::Size(adjusted_height * width_step / height_step,
adjusted_height);
@@ -841,15 +843,15 @@ void WebContentsCaptureMachine::DidCopyFromBackingStore(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::TimeTicks now = base::TimeTicks::Now();
- DCHECK(render_thread_.get());
+ DCHECK(render_thread_);
if (response == READBACK_SUCCESS) {
UMA_HISTOGRAM_TIMES("TabCapture.CopyTimeBitmap", now - start_time);
TRACE_EVENT_ASYNC_STEP_INTO0("gpu.capture", "Capture", target.get(),
"Render");
render_thread_->task_runner()->PostTask(
FROM_HERE, media::BindToCurrentLoop(
- base::Bind(&RenderVideoFrame, bitmap, target,
- base::Bind(deliver_frame_cb, start_time))));
+ base::Bind(&RenderVideoFrame, bitmap, target,
+ base::Bind(deliver_frame_cb, start_time))));
} else {
// Capture can fail due to transient issues, so just skip this frame.
DVLOG(1) << "CopyFromBackingStore failed; skipping frame.";
@@ -903,9 +905,9 @@ void WebContentsCaptureMachine::RenewFrameSubscription(bool had_target) {
if (!had_subscription && tracker_->web_contents())
tracker_->web_contents()->IncrementCapturerCount(ComputeOptimalViewSize());
- subscription_.reset(new ContentCaptureSubscription(*rwh, oracle_proxy_,
- base::Bind(&WebContentsCaptureMachine::Capture,
- weak_ptr_factory_.GetWeakPtr())));
+ subscription_.reset(new ContentCaptureSubscription(
+ *rwh, oracle_proxy_, base::Bind(&WebContentsCaptureMachine::Capture,
+ weak_ptr_factory_.GetWeakPtr())));
}
void WebContentsCaptureMachine::UpdateCaptureSize() {
@@ -938,10 +940,10 @@ WebContentsVideoCaptureDevice::WebContentsVideoCaptureDevice(
int main_render_frame_id,
bool enable_auto_throttling)
: core_(new media::ScreenCaptureDeviceCore(
- scoped_ptr<media::VideoCaptureMachine>(new WebContentsCaptureMachine(
- render_process_id,
- main_render_frame_id,
- enable_auto_throttling)))) {}
+ std::unique_ptr<media::VideoCaptureMachine>(
+ new WebContentsCaptureMachine(render_process_id,
+ main_render_frame_id,
+ enable_auto_throttling)))) {}
WebContentsVideoCaptureDevice::~WebContentsVideoCaptureDevice() {
DVLOG(2) << "WebContentsVideoCaptureDevice@" << this << " destroying.";
@@ -965,11 +967,15 @@ media::VideoCaptureDevice* WebContentsVideoCaptureDevice::Create(
void WebContentsVideoCaptureDevice::AllocateAndStart(
const media::VideoCaptureParams& params,
- scoped_ptr<Client> client) {
+ std::unique_ptr<Client> client) {
DVLOG(1) << "Allocating " << params.requested_format.frame_size.ToString();
core_->AllocateAndStart(params, std::move(client));
}
+void WebContentsVideoCaptureDevice::RequestRefreshFrame() {
+ core_->RequestRefreshFrame();
+}
+
void WebContentsVideoCaptureDevice::StopAndDeAllocate() {
core_->StopAndDeAllocate();
}
diff --git a/chromium/content/browser/media/capture/web_contents_video_capture_device.h b/chromium/content/browser/media/capture/web_contents_video_capture_device.h
index ab0e03ad7d4..ea92b3b2f0f 100644
--- a/chromium/content/browser/media/capture/web_contents_video_capture_device.h
+++ b/chromium/content/browser/media/capture/web_contents_video_capture_device.h
@@ -5,10 +5,10 @@
#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_WEB_CONTENTS_VIDEO_CAPTURE_DEVICE_H_
#define CONTENT_BROWSER_MEDIA_CAPTURE_WEB_CONTENTS_VIDEO_CAPTURE_DEVICE_H_
+#include <memory>
#include <string>
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
#include "media/capture/content/screen_capture_device_core.h"
#include "media/capture/video/video_capture_device.h"
@@ -36,7 +36,8 @@ class CONTENT_EXPORT WebContentsVideoCaptureDevice
// VideoCaptureDevice implementation.
void AllocateAndStart(const media::VideoCaptureParams& params,
- scoped_ptr<Client> client) override;
+ std::unique_ptr<Client> client) override;
+ void RequestRefreshFrame() override;
void StopAndDeAllocate() override;
private:
@@ -45,7 +46,7 @@ class CONTENT_EXPORT WebContentsVideoCaptureDevice
int main_render_frame_id,
bool enable_auto_throttling);
- const scoped_ptr<media::ScreenCaptureDeviceCore> core_;
+ const std::unique_ptr<media::ScreenCaptureDeviceCore> core_;
DISALLOW_COPY_AND_ASSIGN(WebContentsVideoCaptureDevice);
};
diff --git a/chromium/content/browser/media/capture/web_contents_video_capture_device_unittest.cc b/chromium/content/browser/media/capture/web_contents_video_capture_device_unittest.cc
index 9e3bf83c461..81674324bd2 100644
--- a/chromium/content/browser/media/capture/web_contents_video_capture_device_unittest.cc
+++ b/chromium/content/browser/media/capture/web_contents_video_capture_device_unittest.cc
@@ -6,11 +6,13 @@
#include <stddef.h>
#include <stdint.h>
+
#include <utility>
#include "base/bind_helpers.h"
#include "base/debug/debugger.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/test/test_timeouts.h"
#include "base/time/time.h"
@@ -22,8 +24,6 @@
#include "content/browser/renderer_host/render_view_host_factory.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
#include "content/public/browser/web_contents_media_capture_id.h"
#include "content/public/test/mock_render_process_host.h"
@@ -60,7 +60,8 @@ const SkColor kNotInterested = ~kNothingYet;
void DeadlineExceeded(base::Closure quit_closure) {
if (!base::debug::BeingDebugged()) {
- quit_closure.Run();
+ if (!quit_closure.is_null())
+ quit_closure.Run();
FAIL() << "Deadline exceeded while waiting, quitting";
} else {
LOG(WARNING) << "Deadline exceeded; test would fail if debugger weren't "
@@ -94,8 +95,7 @@ class CaptureTestSourceController {
CaptureTestSourceController()
: color_(SK_ColorMAGENTA),
copy_result_size_(kTestWidth, kTestHeight),
- can_copy_to_video_frame_(false),
- use_frame_subscriber_(false) {}
+ can_copy_to_video_frame_(true) {}
void SetSolidColor(SkColor color) {
base::AutoLock guard(lock_);
@@ -136,16 +136,6 @@ class CaptureTestSourceController {
return can_copy_to_video_frame_;
}
- void SetUseFrameSubscriber(bool value) {
- base::AutoLock guard(lock_);
- use_frame_subscriber_ = value;
- }
-
- bool CanUseFrameSubscriber() {
- base::AutoLock guard(lock_);
- return use_frame_subscriber_;
- }
-
void WaitForNextCopy() {
{
base::AutoLock guard(lock_);
@@ -160,7 +150,6 @@ class CaptureTestSourceController {
SkColor color_;
gfx::Size copy_result_size_;
bool can_copy_to_video_frame_;
- bool use_frame_subscriber_;
base::Closure copy_done_;
DISALLOW_COPY_AND_ASSIGN(CaptureTestSourceController);
@@ -209,7 +198,8 @@ class CaptureTestView : public TestRenderWidgetHostView {
}
void BeginFrameSubscription(
- scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) override {
+ std::unique_ptr<RenderWidgetHostViewFrameSubscriber> subscriber)
+ override {
subscriber_.reset(subscriber.release());
}
@@ -233,7 +223,7 @@ class CaptureTestView : public TestRenderWidgetHostView {
}
private:
- scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber_;
+ std::unique_ptr<RenderWidgetHostViewFrameSubscriber> subscriber_;
CaptureTestSourceController* const controller_;
gfx::Rect fake_bounds_;
@@ -286,7 +276,7 @@ class CaptureTestRenderViewHost : public TestRenderViewHost {
bool swapped_out,
CaptureTestSourceController* controller)
: TestRenderViewHost(instance,
- make_scoped_ptr(new CaptureTestRenderWidgetHost(
+ base::WrapUnique(new CaptureTestRenderWidgetHost(
widget_delegate,
instance->GetProcess(),
routing_id,
@@ -368,30 +358,31 @@ class StubClient : public media::VideoCaptureDevice::Client {
MOCK_METHOD0(DoOnIncomingCapturedBuffer, void(void));
- scoped_ptr<media::VideoCaptureDevice::Client::Buffer> ReserveOutputBuffer(
- const gfx::Size& dimensions,
- media::VideoPixelFormat format,
- media::VideoPixelStorage storage) override {
+ std::unique_ptr<media::VideoCaptureDevice::Client::Buffer>
+ ReserveOutputBuffer(const gfx::Size& dimensions,
+ media::VideoPixelFormat format,
+ media::VideoPixelStorage storage) override {
CHECK_EQ(format, media::PIXEL_FORMAT_I420);
int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId; // Ignored.
const int buffer_id = buffer_pool_->ReserveForProducer(
- format, storage, dimensions, &buffer_id_to_drop);
+ dimensions, format, storage, &buffer_id_to_drop);
if (buffer_id == VideoCaptureBufferPool::kInvalidId)
return NULL;
- return scoped_ptr<media::VideoCaptureDevice::Client::Buffer>(
+ return std::unique_ptr<media::VideoCaptureDevice::Client::Buffer>(
new AutoReleaseBuffer(
buffer_pool_, buffer_pool_->GetBufferHandle(buffer_id), buffer_id));
}
- // Trampoline method to workaround GMOCK problems with scoped_ptr<>.
- void OnIncomingCapturedBuffer(scoped_ptr<Buffer> buffer,
+
+ // Trampoline method to workaround GMOCK problems with std::unique_ptr<>.
+ void OnIncomingCapturedBuffer(std::unique_ptr<Buffer> buffer,
const media::VideoCaptureFormat& frame_format,
const base::TimeTicks& timestamp) override {
DoOnIncomingCapturedBuffer();
}
void OnIncomingCapturedVideoFrame(
- scoped_ptr<Buffer> buffer,
+ std::unique_ptr<Buffer> buffer,
const scoped_refptr<media::VideoFrame>& frame,
const base::TimeTicks& timestamp) override {
EXPECT_FALSE(frame->visible_rect().IsEmpty());
@@ -419,6 +410,20 @@ class StubClient : public media::VideoCaptureDevice::Client {
frame->visible_rect().size());
}
+ std::unique_ptr<media::VideoCaptureDevice::Client::Buffer>
+ ResurrectLastOutputBuffer(const gfx::Size& dimensions,
+ media::VideoPixelFormat format,
+ media::VideoPixelStorage storage) override {
+ CHECK_EQ(format, media::PIXEL_FORMAT_I420);
+ const int buffer_id =
+ buffer_pool_->ResurrectLastForProducer(dimensions, format, storage);
+ if (buffer_id == VideoCaptureBufferPool::kInvalidId)
+ return nullptr;
+ return std::unique_ptr<media::VideoCaptureDevice::Client::Buffer>(
+ new AutoReleaseBuffer(
+ buffer_pool_, buffer_pool_->GetBufferHandle(buffer_id), buffer_id));
+ }
+
void OnError(const tracked_objects::Location& from_here,
const std::string& reason) override {
error_callback_.Run();
@@ -431,21 +436,23 @@ class StubClient : public media::VideoCaptureDevice::Client {
public:
AutoReleaseBuffer(
const scoped_refptr<VideoCaptureBufferPool>& pool,
- scoped_ptr<VideoCaptureBufferPool::BufferHandle> buffer_handle,
+ std::unique_ptr<VideoCaptureBufferPool::BufferHandle> buffer_handle,
int buffer_id)
: id_(buffer_id),
pool_(pool),
buffer_handle_(std::move(buffer_handle)) {
- DCHECK(pool_.get());
+ DCHECK(pool_);
}
int id() const override { return id_; }
- gfx::Size dimensions() const override { return gfx::Size(); }
+ gfx::Size dimensions() const override {
+ return buffer_handle_->dimensions();
+ }
size_t mapped_size() const override {
return buffer_handle_->mapped_size();
}
void* data(int plane) override { return buffer_handle_->data(plane); }
ClientBuffer AsClientBuffer(int plane) override { return nullptr; }
-#if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS))
+#if defined(OS_POSIX) && !defined(OS_MACOSX)
base::FileDescriptor AsPlatformFile() override {
return base::FileDescriptor();
}
@@ -456,7 +463,7 @@ class StubClient : public media::VideoCaptureDevice::Client {
const int id_;
const scoped_refptr<VideoCaptureBufferPool> pool_;
- const scoped_ptr<VideoCaptureBufferPool::BufferHandle> buffer_handle_;
+ const std::unique_ptr<VideoCaptureBufferPool::BufferHandle> buffer_handle_;
};
scoped_refptr<VideoCaptureBufferPool> buffer_pool_;
@@ -470,8 +477,7 @@ class StubClientObserver {
public:
StubClientObserver()
: error_encountered_(false),
- wait_color_yuv_(0xcafe1950),
- wait_size_(kTestWidth, kTestHeight) {
+ wait_color_yuv_(0xcafe1950) {
client_.reset(new StubClient(
base::Bind(&StubClientObserver::DidDeliverFrame,
base::Unretained(this)),
@@ -480,34 +486,41 @@ class StubClientObserver {
virtual ~StubClientObserver() {}
- scoped_ptr<media::VideoCaptureDevice::Client> PassClient() {
+ std::unique_ptr<media::VideoCaptureDevice::Client> PassClient() {
return std::move(client_);
}
void QuitIfConditionsMet(SkColor color, const gfx::Size& size) {
base::AutoLock guard(lock_);
- if (error_encountered_)
- base::MessageLoop::current()->QuitWhenIdle();
- else if (wait_color_yuv_ == color && wait_size_.IsEmpty())
- base::MessageLoop::current()->QuitWhenIdle();
- else if (wait_color_yuv_ == color && wait_size_ == size)
+ if (error_encountered_ || wait_color_yuv_ == kNotInterested ||
+ wait_color_yuv_ == color) {
+ last_frame_color_yuv_ = color;
+ last_frame_size_ = size;
base::MessageLoop::current()->QuitWhenIdle();
+ }
}
- // Run the current loop until a frame is delivered with the |expected_color|
- // and any non-empty frame size.
- void WaitForNextColor(SkColor expected_color) {
- WaitForNextColorAndFrameSize(expected_color, gfx::Size());
+ // Run the current loop until the next frame is delivered. Returns the YUV
+ // color and frame size.
+ std::pair<SkColor, gfx::Size> WaitForNextFrame() {
+ {
+ base::AutoLock guard(lock_);
+ wait_color_yuv_ = kNotInterested;
+ error_encountered_ = false;
+ }
+ RunCurrentLoopWithDeadline();
+ {
+ base::AutoLock guard(lock_);
+ CHECK(!error_encountered_);
+ return std::make_pair(last_frame_color_yuv_, last_frame_size_);
+ }
}
- // Run the current loop until a frame is delivered with the |expected_color|
- // and is of the |expected_size|.
- void WaitForNextColorAndFrameSize(SkColor expected_color,
- const gfx::Size& expected_size) {
+ // Run the current loop until a frame is delivered with the |expected_color|.
+ void WaitForNextColor(SkColor expected_color) {
{
base::AutoLock guard(lock_);
wait_color_yuv_ = ConvertRgbToYuv(expected_color);
- wait_size_ = expected_size;
error_encountered_ = false;
}
RunCurrentLoopWithDeadline();
@@ -521,7 +534,6 @@ class StubClientObserver {
{
base::AutoLock guard(lock_);
wait_color_yuv_ = kNotInterested;
- wait_size_ = gfx::Size();
error_encountered_ = false;
}
RunCurrentLoopWithDeadline();
@@ -560,8 +572,9 @@ class StubClientObserver {
base::Lock lock_;
bool error_encountered_;
SkColor wait_color_yuv_;
- gfx::Size wait_size_;
- scoped_ptr<StubClient> client_;
+ SkColor last_frame_color_yuv_;
+ gfx::Size last_frame_size_;
+ std::unique_ptr<StubClient> client_;
DISALLOW_COPY_AND_ASSIGN(StubClientObserver);
};
@@ -590,8 +603,8 @@ class MAYBE_WebContentsVideoCaptureDeviceTest : public testing::Test {
test_screen_.display()->set_bounds(gfx::Rect(0, 0, 2560, 1440));
test_screen_.display()->set_device_scale_factor(kTestDeviceScaleFactor);
- gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, &test_screen_);
- ASSERT_EQ(&test_screen_, gfx::Screen::GetNativeScreen());
+ gfx::Screen::SetScreenInstance(&test_screen_);
+ ASSERT_EQ(&test_screen_, gfx::Screen::GetScreen());
// TODO(nick): Sadness and woe! Much "mock-the-world" boilerplate could be
// eliminated here, if only we could use RenderViewHostTestHarness. The
@@ -649,7 +662,7 @@ class MAYBE_WebContentsVideoCaptureDeviceTest : public testing::Test {
render_view_host_factory_.reset();
render_process_host_factory_.reset();
- gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, NULL);
+ gfx::Screen::SetScreenInstance(nullptr);
}
// Accessors.
@@ -669,19 +682,30 @@ class MAYBE_WebContentsVideoCaptureDeviceTest : public testing::Test {
}
void SimulateDrawEvent() {
- if (source()->CanUseFrameSubscriber()) {
- // Print
- CaptureTestView* test_view = static_cast<CaptureTestView*>(
- web_contents_->GetRenderViewHost()->GetWidget()->GetView());
- test_view->SimulateUpdate();
- } else {
- // Simulate a non-accelerated paint.
- NotificationService::current()->Notify(
- NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
- Source<RenderWidgetHost>(
- web_contents_->GetRenderViewHost()->GetWidget()),
- NotificationService::NoDetails());
- }
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ // Force at least one frame period's worth of time to pass. Otherwise,
+ // internal logic may decide not to capture a frame because the draw events
+ // are more frequent that kTestFramesPerSecond.
+ //
+ // TODO(miu): Instead of physically waiting, we should inject simulated
+ // clocks for testing.
+ base::RunLoop run_loop;
+ BrowserThread::PostDelayedTask(
+ BrowserThread::UI, FROM_HERE,
+ run_loop.QuitClosure(),
+ base::TimeDelta::FromMicroseconds(
+ base::Time::kMicrosecondsPerSecond / kTestFramesPerSecond));
+ run_loop.Run();
+
+ // Schedule the update to occur when the test runs the event loop (and not
+ // before expectations have been set).
+ CaptureTestView* test_view = static_cast<CaptureTestView*>(
+ web_contents_->GetRenderViewHost()->GetWidget()->GetView());
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&CaptureTestView::SimulateUpdate,
+ base::Unretained(test_view)));
}
void SimulateSourceSizeChange(const gfx::Size& size) {
@@ -700,6 +724,45 @@ class MAYBE_WebContentsVideoCaptureDeviceTest : public testing::Test {
as_web_contents_impl->GetMainFrame()->GetRenderWidgetHost(), true);
}
+ // Repeatedly schedules draw events and scans for frames until the output from
+ // the capture device matches the given RGB |color| and frame |size|.
+ void SimulateDrawsUntilNewFrameSizeArrives(SkColor color,
+ const gfx::Size& size) {
+ const base::TimeTicks start_time = base::TimeTicks::Now();
+ while ((base::TimeTicks::Now() - start_time) <
+ TestTimeouts::action_max_timeout()) {
+ SimulateDrawEvent();
+ const auto color_and_size = client_observer()->WaitForNextFrame();
+ if (color_and_size.first == ConvertRgbToYuv(color) &&
+ color_and_size.second == size) {
+ return;
+ }
+ }
+ DeadlineExceeded(base::Closure());
+ }
+
+ void SimulateRefreshFrameRequest() {
+ // Force at least three frame period's worth of time to pass. The wait is
+ // needed because refresh frame requests are only honored when drawing
+ // events, which trigger frame captures, are not occurring frequently
+ // enough.
+ //
+ // TODO(miu): Instead of physically waiting, we should inject simulated
+ // clocks for testing.
+ base::RunLoop run_loop;
+ BrowserThread::PostDelayedTask(
+ BrowserThread::UI, FROM_HERE,
+ run_loop.QuitClosure(),
+ base::TimeDelta::FromMicroseconds(
+ 3 * base::Time::kMicrosecondsPerSecond / kTestFramesPerSecond));
+ run_loop.Run();
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&media::VideoCaptureDevice::RequestRefreshFrame,
+ base::Unretained(device_.get())));
+ }
+
void DestroyVideoCaptureDevice() { device_.reset(); }
StubClientObserver* client_observer() {
@@ -715,21 +778,21 @@ class MAYBE_WebContentsVideoCaptureDeviceTest : public testing::Test {
CaptureTestSourceController controller_;
// Self-registering RenderProcessHostFactory.
- scoped_ptr<MockRenderProcessHostFactory> render_process_host_factory_;
+ std::unique_ptr<MockRenderProcessHostFactory> render_process_host_factory_;
// Creates capture-capable RenderViewHosts whose pixel content production is
// under the control of |controller_|.
- scoped_ptr<CaptureTestRenderViewHostFactory> render_view_host_factory_;
+ std::unique_ptr<CaptureTestRenderViewHostFactory> render_view_host_factory_;
// Self-registering RenderFrameHostFactory.
- scoped_ptr<TestRenderFrameHostFactory> render_frame_host_factory_;
+ std::unique_ptr<TestRenderFrameHostFactory> render_frame_host_factory_;
// A mocked-out browser and tab.
- scoped_ptr<TestBrowserContext> browser_context_;
- scoped_ptr<WebContents> web_contents_;
+ std::unique_ptr<TestBrowserContext> browser_context_;
+ std::unique_ptr<WebContents> web_contents_;
// Finally, the WebContentsVideoCaptureDevice under test.
- scoped_ptr<media::VideoCaptureDevice> device_;
+ std::unique_ptr<media::VideoCaptureDevice> device_;
TestBrowserThreadBundle thread_bundle_;
};
@@ -764,7 +827,9 @@ TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest, WebContentsDestroyed) {
capture_params.requested_format.frame_rate = kTestFramesPerSecond;
capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
device()->AllocateAndStart(capture_params, client_observer()->PassClient());
- // Do one capture to prove
+
+ // Do one capture to prove the tab is initially open and being captured
+ // normally.
source()->SetSolidColor(SK_ColorRED);
SimulateDrawEvent();
ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED));
@@ -804,9 +869,9 @@ TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest,
}
TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest, StopWithRendererWorkToDo) {
- // Set up the test to use RGB copies and an normal
+ // Set up the test to use RGB captures into SkBitmaps instead of YUV captures
+ // into VideoFrames.
source()->SetCanCopyToVideoFrame(false);
- source()->SetUseFrameSubscriber(false);
media::VideoCaptureParams capture_params;
capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight);
capture_params.requested_format.frame_rate = kTestFramesPerSecond;
@@ -815,7 +880,7 @@ TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest, StopWithRendererWorkToDo) {
base::RunLoop().RunUntilIdle();
- for (int i = 0; i < 10; ++i)
+ for (int i = 0; i < 3; ++i)
SimulateDrawEvent();
ASSERT_FALSE(client_observer()->HasError());
@@ -861,8 +926,8 @@ TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest, DeviceRestart) {
// The "happy case" test. No scaling is needed, so we should be able to change
// the picture emitted from the source and expect to see each delivered to the
-// consumer. The test will alternate between the three capture paths, simulating
-// falling in and out of accelerated compositing.
+// consumer. The test will alternate between the RGB/SkBitmap and YUV/VideoFrame
+// capture paths.
TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest, GoesThroughAllTheMotions) {
media::VideoCaptureParams capture_params;
capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight);
@@ -870,26 +935,14 @@ TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest, GoesThroughAllTheMotions) {
capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
device()->AllocateAndStart(capture_params, client_observer()->PassClient());
- for (int i = 0; i < 6; i++) {
+ for (int i = 0; i < 4; i++) {
const char* name = NULL;
- switch (i % 3) {
- case 0:
- source()->SetCanCopyToVideoFrame(true);
- source()->SetUseFrameSubscriber(false);
- name = "VideoFrame";
- break;
- case 1:
- source()->SetCanCopyToVideoFrame(false);
- source()->SetUseFrameSubscriber(true);
- name = "Subscriber";
- break;
- case 2:
- source()->SetCanCopyToVideoFrame(false);
- source()->SetUseFrameSubscriber(false);
- name = "SkBitmap";
- break;
- default:
- FAIL();
+ if (i % 2) {
+ source()->SetCanCopyToVideoFrame(false);
+ name = "SkBitmap";
+ } else {
+ source()->SetCanCopyToVideoFrame(true);
+ name = "VideoFrame";
}
SCOPED_TRACE(base::StringPrintf("Using %s path, iteration #%d", name, i));
@@ -925,17 +978,18 @@ TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest, BadFramesGoodFrames) {
// These frames ought to be dropped during the Render stage. Let
// several captures to happen.
- ASSERT_NO_FATAL_FAILURE(source()->WaitForNextCopy());
- ASSERT_NO_FATAL_FAILURE(source()->WaitForNextCopy());
- ASSERT_NO_FATAL_FAILURE(source()->WaitForNextCopy());
- ASSERT_NO_FATAL_FAILURE(source()->WaitForNextCopy());
- ASSERT_NO_FATAL_FAILURE(source()->WaitForNextCopy());
+ for (int i = 0; i < 3; ++i) {
+ SimulateDrawEvent();
+ ASSERT_NO_FATAL_FAILURE(source()->WaitForNextCopy());
+ }
// Now push some good frames through; they should be processed normally.
source()->SetCopyResultSize(kTestWidth, kTestHeight);
source()->SetSolidColor(SK_ColorGREEN);
+ SimulateDrawEvent();
ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorGREEN));
source()->SetSolidColor(SK_ColorRED);
+ SimulateDrawEvent();
ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED));
device()->StopAndDeAllocate();
@@ -955,17 +1009,14 @@ TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest,
device()->AllocateAndStart(capture_params, client_observer()->PassClient());
- source()->SetUseFrameSubscriber(true);
-
// Source size equals maximum size. Expect delivered frames to be
// kTestWidth by kTestHeight.
source()->SetSolidColor(SK_ColorRED);
const float device_scale_factor = GetDeviceScaleFactor();
SimulateSourceSizeChange(gfx::ConvertSizeToDIP(
device_scale_factor, gfx::Size(kTestWidth, kTestHeight)));
- SimulateDrawEvent();
- ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColorAndFrameSize(
- SK_ColorRED, gfx::Size(kTestWidth, kTestHeight)));
+ SimulateDrawsUntilNewFrameSizeArrives(
+ SK_ColorRED, gfx::Size(kTestWidth, kTestHeight));
// Source size is half in both dimensions. Expect delivered frames to be of
// the same aspect ratio as kTestWidth by kTestHeight, but larger than the
@@ -973,27 +1024,24 @@ TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest,
source()->SetSolidColor(SK_ColorGREEN);
SimulateSourceSizeChange(gfx::ConvertSizeToDIP(
device_scale_factor, gfx::Size(kTestWidth / 2, kTestHeight / 2)));
- SimulateDrawEvent();
- ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColorAndFrameSize(
- SK_ColorGREEN, gfx::Size(180 * kTestWidth / kTestHeight, 180)));
+ SimulateDrawsUntilNewFrameSizeArrives(
+ SK_ColorGREEN, gfx::Size(180 * kTestWidth / kTestHeight, 180));
// Source size changes aspect ratio. Expect delivered frames to be padded
// in the horizontal dimension to preserve aspect ratio.
source()->SetSolidColor(SK_ColorBLUE);
SimulateSourceSizeChange(gfx::ConvertSizeToDIP(
device_scale_factor, gfx::Size(kTestWidth / 2, kTestHeight)));
- SimulateDrawEvent();
- ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColorAndFrameSize(
- SK_ColorBLUE, gfx::Size(kTestWidth, kTestHeight)));
+ SimulateDrawsUntilNewFrameSizeArrives(
+ SK_ColorBLUE, gfx::Size(kTestWidth, kTestHeight));
// Source size changes aspect ratio again. Expect delivered frames to be
// padded in the vertical dimension to preserve aspect ratio.
source()->SetSolidColor(SK_ColorBLACK);
SimulateSourceSizeChange(gfx::ConvertSizeToDIP(
device_scale_factor, gfx::Size(kTestWidth, kTestHeight / 2)));
- SimulateDrawEvent();
- ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColorAndFrameSize(
- SK_ColorBLACK, gfx::Size(kTestWidth, kTestHeight)));
+ SimulateDrawsUntilNewFrameSizeArrives(
+ SK_ColorBLACK, gfx::Size(kTestWidth, kTestHeight));
device()->StopAndDeAllocate();
}
@@ -1012,26 +1060,22 @@ TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest,
device()->AllocateAndStart(capture_params, client_observer()->PassClient());
- source()->SetUseFrameSubscriber(true);
-
// Source size equals maximum size. Expect delivered frames to be
// kTestWidth by kTestHeight.
source()->SetSolidColor(SK_ColorRED);
const float device_scale_factor = GetDeviceScaleFactor();
SimulateSourceSizeChange(gfx::ConvertSizeToDIP(
device_scale_factor, gfx::Size(kTestWidth, kTestHeight)));
- SimulateDrawEvent();
- ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColorAndFrameSize(
- SK_ColorRED, gfx::Size(kTestWidth, kTestHeight)));
+ SimulateDrawsUntilNewFrameSizeArrives(
+ SK_ColorRED, gfx::Size(kTestWidth, kTestHeight));
// Source size is half in both dimensions. Expect delivered frames to also
// be half in both dimensions.
source()->SetSolidColor(SK_ColorGREEN);
SimulateSourceSizeChange(gfx::ConvertSizeToDIP(
device_scale_factor, gfx::Size(kTestWidth / 2, kTestHeight / 2)));
- SimulateDrawEvent();
- ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColorAndFrameSize(
- SK_ColorGREEN, gfx::Size(kTestWidth / 2, kTestHeight / 2)));
+ SimulateDrawsUntilNewFrameSizeArrives(
+ SK_ColorGREEN, gfx::Size(kTestWidth / 2, kTestHeight / 2));
// Source size changes to something arbitrary. Since the source size is
// less than the maximum size, expect delivered frames to be the same size
@@ -1040,9 +1084,7 @@ TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest,
gfx::Size arbitrary_source_size(kTestWidth / 2 + 42, kTestHeight - 10);
SimulateSourceSizeChange(gfx::ConvertSizeToDIP(device_scale_factor,
arbitrary_source_size));
- SimulateDrawEvent();
- ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColorAndFrameSize(
- SK_ColorBLUE, arbitrary_source_size));
+ SimulateDrawsUntilNewFrameSizeArrives(SK_ColorBLUE, arbitrary_source_size);
// Source size changes to something arbitrary that exceeds the maximum frame
// size. Since the source size exceeds the maximum size, expect delivered
@@ -1051,11 +1093,10 @@ TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest,
arbitrary_source_size = gfx::Size(kTestWidth * 2, kTestHeight / 2);
SimulateSourceSizeChange(gfx::ConvertSizeToDIP(device_scale_factor,
arbitrary_source_size));
- SimulateDrawEvent();
- ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColorAndFrameSize(
+ SimulateDrawsUntilNewFrameSizeArrives(
SK_ColorBLACK, gfx::Size(kTestWidth,
kTestWidth * arbitrary_source_size.height() /
- arbitrary_source_size.width())));
+ arbitrary_source_size.width()));
device()->StopAndDeAllocate();
}
@@ -1154,5 +1195,36 @@ TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest,
}
}
+// Tests the RequestRefreshFrame() functionality.
+TEST_F(MAYBE_WebContentsVideoCaptureDeviceTest, ProvidesRefreshFrames) {
+ media::VideoCaptureParams capture_params;
+ capture_params.requested_format.frame_size.SetSize(kTestWidth, kTestHeight);
+ capture_params.requested_format.frame_rate = kTestFramesPerSecond;
+ capture_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
+ device()->AllocateAndStart(capture_params, client_observer()->PassClient());
+
+ // Request a refresh frame before the first frame has been drawn. This forces
+ // a capture.
+ source()->SetSolidColor(SK_ColorRED);
+ SimulateRefreshFrameRequest();
+ ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorRED));
+
+ // Now, draw a frame and wait for a normal frame capture to occur.
+ source()->SetSolidColor(SK_ColorGREEN);
+ SimulateDrawEvent();
+ ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorGREEN));
+
+ // Now, make three more refresh frame requests. Although the source has
+ // changed to BLUE, no draw event has occurred. Therefore, expect the refresh
+ // frames to contain the content from the last drawn frame, which is GREEN.
+ source()->SetSolidColor(SK_ColorBLUE);
+ for (int i = 0; i < 3; ++i) {
+ SimulateRefreshFrameRequest();
+ ASSERT_NO_FATAL_FAILURE(client_observer()->WaitForNextColor(SK_ColorGREEN));
+ }
+
+ device()->StopAndDeAllocate();
+}
+
} // namespace
} // namespace content
diff --git a/chromium/content/browser/media/capture/window_activity_tracker.cc b/chromium/content/browser/media/capture/window_activity_tracker.cc
new file mode 100644
index 00000000000..394792d8a2e
--- /dev/null
+++ b/chromium/content/browser/media/capture/window_activity_tracker.cc
@@ -0,0 +1,54 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/capture/window_activity_tracker.h"
+
+#include "base/time/time.h"
+
+namespace content {
+
+namespace {
+
+// The time period within which a triggered UI event is considered
+// currently active.
+const int kTimePeriodUiEventMicros = 100000; // 100 ms
+
+// Minimum number of user interactions before we consider the user to be in
+// interactive mode. The goal is to prevent user interactions to launch
+// animated content from causing target playout time flip-flop.
+const int kMinUserInteractions = 5;
+
+} // namespace
+
+WindowActivityTracker::WindowActivityTracker() {
+ Reset();
+}
+
+WindowActivityTracker::~WindowActivityTracker() {}
+
+bool WindowActivityTracker::IsUiInteractionActive() const {
+ return ui_events_count_ > kMinUserInteractions;
+}
+
+void WindowActivityTracker::RegisterMouseInteractionObserver(
+ const base::Closure& observer) {
+ mouse_interaction_observer_ = observer;
+}
+
+void WindowActivityTracker::Reset() {
+ ui_events_count_ = 0;
+ last_time_ui_event_detected_ = base::TimeTicks();
+}
+
+void WindowActivityTracker::OnMouseActivity() {
+ if (!mouse_interaction_observer_.is_null())
+ mouse_interaction_observer_.Run();
+ if (base::TimeTicks::Now() - last_time_ui_event_detected_ >
+ base::TimeDelta::FromMicroseconds(kTimePeriodUiEventMicros)) {
+ ui_events_count_++;
+ }
+ last_time_ui_event_detected_ = base::TimeTicks::Now();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/capture/window_activity_tracker.h b/chromium/content/browser/media/capture/window_activity_tracker.h
index 5fd9f0bc8d9..1d07a8ba512 100644
--- a/chromium/content/browser/media/capture/window_activity_tracker.h
+++ b/chromium/content/browser/media/capture/window_activity_tracker.h
@@ -5,9 +5,13 @@
#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_WINDOW_ACTIVITY_TRACKER_H_
#define CONTENT_BROWSER_MEDIA_CAPTURE_WINDOW_ACTIVITY_TRACKER_H_
+#include <memory>
+
+#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
+#include "ui/gfx/native_widget_types.h"
namespace content {
@@ -15,16 +19,39 @@ namespace content {
// whether the user is actively interacting with UI.
class CONTENT_EXPORT WindowActivityTracker {
public:
- virtual ~WindowActivityTracker() {}
+ static std::unique_ptr<WindowActivityTracker> Create(gfx::NativeView view);
+
+ WindowActivityTracker();
+ virtual ~WindowActivityTracker();
// Returns true if UI interaction is active.
- virtual bool IsUiInteractionActive() const = 0;
+ bool IsUiInteractionActive() const;
+
+ // Reports on every mouse movement activity on the window.
+ void RegisterMouseInteractionObserver(const base::Closure& observer);
// Resets any previous UI activity tracked.
- virtual void Reset() = 0;
+ void Reset();
// Returns a weak pointer.
virtual base::WeakPtr<WindowActivityTracker> GetWeakPtr() = 0;
+
+ protected:
+ void OnMouseActivity();
+
+ private:
+ // The last time a UI event was detected.
+ base::TimeTicks last_time_ui_event_detected_;
+
+ // Runs on any mouse interaction from user.
+ base::Closure mouse_interaction_observer_;
+
+ // The number of UI events detected so far. In case of continuous events
+ // such as mouse movement, a single continuous movement is treated
+ // as one event.
+ int ui_events_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowActivityTracker);
};
} // namespace content
diff --git a/chromium/content/browser/media/capture/window_activity_tracker_aura.cc b/chromium/content/browser/media/capture/window_activity_tracker_aura.cc
index e56e4a3f04c..e5a1783146a 100644
--- a/chromium/content/browser/media/capture/window_activity_tracker_aura.cc
+++ b/chromium/content/browser/media/capture/window_activity_tracker_aura.cc
@@ -11,21 +11,15 @@
namespace content {
-namespace {
-// The time period within which a triggered UI event is considered
-// currently active.
-const int kTimePeriodUiEventMicros = 100000; // 100 ms
-
-// Minimum number of user interactions before we consider the user to be in
-// interactive mode. The goal is to prevent user interactions to launch
-// animated content from causing target playout time flip-flop.
-const int kMinUserInteractions = 5;
-} // namespace
+// static
+std::unique_ptr<WindowActivityTracker> WindowActivityTracker::Create(
+ gfx::NativeView window) {
+ return std::unique_ptr<WindowActivityTracker>(
+ new WindowActivityTrackerAura(window));
+}
WindowActivityTrackerAura::WindowActivityTrackerAura(aura::Window* window)
: window_(window),
- last_time_ui_event_detected_(base::TimeTicks()),
- ui_events_count_(0),
weak_factory_(this) {
if (window_) {
window_->AddObserver(this);
@@ -44,21 +38,16 @@ base::WeakPtr<WindowActivityTracker> WindowActivityTrackerAura::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
-bool WindowActivityTrackerAura::IsUiInteractionActive() const {
- return ui_events_count_ > kMinUserInteractions;
-}
-
-void WindowActivityTrackerAura::Reset() {
- ui_events_count_ = 0;
- last_time_ui_event_detected_ = base::TimeTicks();
-}
-
void WindowActivityTrackerAura::OnEvent(ui::Event* event) {
- if (base::TimeTicks::Now() - last_time_ui_event_detected_ >
- base::TimeDelta::FromMicroseconds(kTimePeriodUiEventMicros)) {
- ui_events_count_++;
+ switch (event->type()) {
+ case ui::ET_MOUSE_PRESSED:
+ case ui::ET_MOUSE_RELEASED:
+ case ui::ET_MOUSE_MOVED:
+ WindowActivityTracker::OnMouseActivity();
+ break;
+ default:
+ break;
}
- last_time_ui_event_detected_ = base::TimeTicks::Now();
}
void WindowActivityTrackerAura::OnWindowDestroying(aura::Window* window) {
diff --git a/chromium/content/browser/media/capture/window_activity_tracker_aura.h b/chromium/content/browser/media/capture/window_activity_tracker_aura.h
index c382c7a4bf6..be5f29c3567 100644
--- a/chromium/content/browser/media/capture/window_activity_tracker_aura.h
+++ b/chromium/content/browser/media/capture/window_activity_tracker_aura.h
@@ -24,9 +24,6 @@ class CONTENT_EXPORT WindowActivityTrackerAura : public WindowActivityTracker,
explicit WindowActivityTrackerAura(aura::Window* window);
~WindowActivityTrackerAura() final;
- // WindowActivityTracker overrides.
- bool IsUiInteractionActive() const final;
- void Reset() final;
base::WeakPtr<WindowActivityTracker> GetWeakPtr() final;
private:
@@ -38,14 +35,6 @@ class CONTENT_EXPORT WindowActivityTrackerAura : public WindowActivityTracker,
aura::Window* window_;
- // The last time a UI event was detected.
- base::TimeTicks last_time_ui_event_detected_;
-
- // The number of UI events detected so far. In case of continuous events
- // such as mouse movement, a single continuous movement is treated
- // as one event.
- int ui_events_count_;
-
base::WeakPtrFactory<WindowActivityTrackerAura> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(WindowActivityTrackerAura);
diff --git a/chromium/content/browser/media/capture/window_activity_tracker_mac.h b/chromium/content/browser/media/capture/window_activity_tracker_mac.h
new file mode 100644
index 00000000000..64c91a03ea1
--- /dev/null
+++ b/chromium/content/browser/media/capture/window_activity_tracker_mac.h
@@ -0,0 +1,62 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEDIA_CAPTURE_WINDOW_ACTIVITY_TRACKER_MAC_H_
+#define CONTENT_BROWSER_MEDIA_CAPTURE_WINDOW_ACTIVITY_TRACKER_MAC_H_
+
+#import <AppKit/AppKit.h>
+#import <CoreFoundation/CoreFoundation.h>
+
+#include "base/callback.h"
+#include "base/mac/scoped_nsobject.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "content/browser/media/capture/window_activity_tracker.h"
+#include "content/common/content_export.h"
+#include "ui/base/cocoa/tracking_area.h"
+#include "ui/gfx/native_widget_types.h"
+
+@interface MouseTracker : NSObject {
+ @private
+ ui::ScopedCrTrackingArea trackingArea_;
+
+ // The view on which mouse movement is detected.
+ NSView* nsView_;
+
+ // Runs on any mouse interaction from user.
+ base::Closure mouseInteractionObserver_;
+}
+
+- (instancetype)initWithView:(NSView*)nsView;
+
+// Register an observer for mouse interaction.
+- (void)registerMouseInteractionObserver:(const base::Closure&)observer;
+
+@end
+
+namespace content {
+
+// Tracks UI events and makes a decision on whether the user has been
+// actively interacting with a specified window.
+class CONTENT_EXPORT WindowActivityTrackerMac : public WindowActivityTracker {
+ public:
+ explicit WindowActivityTrackerMac(NSView* view);
+ ~WindowActivityTrackerMac() final;
+
+ base::WeakPtr<WindowActivityTracker> GetWeakPtr() final;
+
+ private:
+ void OnMouseActivity();
+
+ NSView* const view_;
+ base::scoped_nsobject<MouseTracker> mouse_tracker_;
+
+ base::WeakPtrFactory<WindowActivityTrackerMac> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(WindowActivityTrackerMac);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_CAPTURE_WINDOW_ACTIVITY_TRACKER_MAC_H_
diff --git a/chromium/content/browser/media/capture/window_activity_tracker_mac.mm b/chromium/content/browser/media/capture/window_activity_tracker_mac.mm
new file mode 100644
index 00000000000..a0ec7d31afc
--- /dev/null
+++ b/chromium/content/browser/media/capture/window_activity_tracker_mac.mm
@@ -0,0 +1,82 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/capture/window_activity_tracker_mac.h"
+
+#include <AppKit/AppKit.h>
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "base/bind.h"
+#include "ui/base/cocoa/tracking_area.h"
+
+@implementation MouseTracker
+
+- (instancetype)initWithView:(NSView*)nsView {
+ self = [super init];
+ // TODO(isheriff): why are there no pressed/released events ?
+ NSTrackingAreaOptions trackingOptions =
+ NSTrackingMouseMoved | NSTrackingMouseEnteredAndExited |
+ NSTrackingActiveInKeyWindow | NSTrackingInVisibleRect;
+ trackingArea_.reset([[CrTrackingArea alloc] initWithRect:NSZeroRect
+ options:trackingOptions
+ owner:self
+ userInfo:nil]);
+ [nsView addTrackingArea:trackingArea_.get()];
+ nsView_ = nsView;
+ return self;
+}
+
+- (void)stopTracking {
+ if (trackingArea_.get()) {
+ [nsView_ removeTrackingArea:trackingArea_.get()];
+ trackingArea_.reset();
+ }
+}
+
+- (void)registerMouseInteractionObserver:(const base::Closure&)observer {
+ mouseInteractionObserver_ = observer;
+}
+
+- (void)mouseMoved:(NSEvent*)theEvent {
+ mouseInteractionObserver_.Run();
+}
+
+- (void)mouseEntered:(NSEvent*)theEvent {
+}
+
+- (void)mouseExited:(NSEvent*)theEvent {
+}
+
+@end
+
+namespace content {
+
+// static
+std::unique_ptr<WindowActivityTracker> WindowActivityTracker::Create(
+ gfx::NativeView view) {
+ return std::unique_ptr<WindowActivityTracker>(
+ new WindowActivityTrackerMac(view));
+}
+
+WindowActivityTrackerMac::WindowActivityTrackerMac(NSView* view)
+ : view_(view), weak_factory_(this) {
+ mouse_tracker_.reset([[MouseTracker alloc] initWithView:view]);
+ [mouse_tracker_ registerMouseInteractionObserver:
+ base::Bind(&WindowActivityTrackerMac::OnMouseActivity,
+ base::Unretained(this))];
+}
+
+WindowActivityTrackerMac::~WindowActivityTrackerMac() {
+ [mouse_tracker_ stopTracking];
+}
+
+void WindowActivityTrackerMac::OnMouseActivity() {
+ WindowActivityTracker::OnMouseActivity();
+}
+
+base::WeakPtr<WindowActivityTracker> WindowActivityTrackerMac::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/cdm/browser_cdm_manager.cc b/chromium/content/browser/media/cdm/browser_cdm_manager.cc
index 2f997d078ca..b2bc2c97c2e 100644
--- a/chromium/content/browser/media/cdm/browser_cdm_manager.cc
+++ b/chromium/content/browser/media/cdm/browser_cdm_manager.cc
@@ -5,13 +5,14 @@
#include "content/browser/media/cdm/browser_cdm_manager.h"
#include <stddef.h>
+
+#include <memory>
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/lazy_instance.h"
-#include "base/memory/scoped_ptr.h"
#include "base/task_runner.h"
#include "build/build_config.h"
#include "content/public/browser/browser_context.h"
@@ -72,7 +73,10 @@ class CdmPromiseInternal : public media::CdmPromiseTemplate<T...> {
DCHECK(manager_);
}
- ~CdmPromiseInternal() final {}
+ ~CdmPromiseInternal() final {
+ if (!IsPromiseSettled())
+ RejectPromiseOnDestruction();
+ }
// CdmPromiseTemplate<> implementation.
void resolve(const T&... result) final;
@@ -88,7 +92,9 @@ class CdmPromiseInternal : public media::CdmPromiseTemplate<T...> {
}
private:
+ using media::CdmPromiseTemplate<T...>::IsPromiseSettled;
using media::CdmPromiseTemplate<T...>::MarkPromiseSettled;
+ using media::CdmPromiseTemplate<T...>::RejectPromiseOnDestruction;
base::WeakPtr<BrowserCdmManager> const manager_;
const int render_frame_id_;
@@ -370,7 +376,7 @@ void BrowserCdmManager::OnInitializeCdm(
DCHECK(task_runner_->RunsTasksOnCurrentThread());
DCHECK(!GetCdm(render_frame_id, cdm_id));
- scoped_ptr<SimplePromise> promise(new SimplePromise(
+ std::unique_ptr<SimplePromise> promise(new SimplePromise(
weak_ptr_factory_.GetWeakPtr(), render_frame_id, cdm_id, promise_id));
if (params.key_system.size() > media::limits::kMaxKeySystemLength) {
@@ -412,7 +418,7 @@ void BrowserCdmManager::OnSetServerCertificate(
const std::vector<uint8_t>& certificate) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
- scoped_ptr<SimplePromise> promise(new SimplePromise(
+ std::unique_ptr<SimplePromise> promise(new SimplePromise(
weak_ptr_factory_.GetWeakPtr(), render_frame_id, cdm_id, promise_id));
scoped_refptr<MediaKeys> cdm = GetCdm(render_frame_id, cdm_id);
@@ -436,9 +442,9 @@ void BrowserCdmManager::OnCreateSessionAndGenerateRequest(
int render_frame_id = params.render_frame_id;
int cdm_id = params.cdm_id;
const std::vector<uint8_t>& init_data = params.init_data;
- scoped_ptr<NewSessionPromise> promise(
- new NewSessionPromise(weak_ptr_factory_.GetWeakPtr(),
- render_frame_id, cdm_id, params.promise_id));
+ std::unique_ptr<NewSessionPromise> promise(
+ new NewSessionPromise(weak_ptr_factory_.GetWeakPtr(), render_frame_id,
+ cdm_id, params.promise_id));
if (init_data.size() > media::limits::kMaxInitDataLength) {
LOG(WARNING) << "InitData for ID: " << cdm_id
@@ -495,7 +501,7 @@ void BrowserCdmManager::OnLoadSession(
const std::string& session_id) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
- scoped_ptr<NewSessionPromise> promise(new NewSessionPromise(
+ std::unique_ptr<NewSessionPromise> promise(new NewSessionPromise(
weak_ptr_factory_.GetWeakPtr(), render_frame_id, cdm_id, promise_id));
scoped_refptr<MediaKeys> cdm = GetCdm(render_frame_id, cdm_id);
@@ -519,7 +525,7 @@ void BrowserCdmManager::OnUpdateSession(int render_frame_id,
const std::vector<uint8_t>& response) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
- scoped_ptr<SimplePromise> promise(new SimplePromise(
+ std::unique_ptr<SimplePromise> promise(new SimplePromise(
weak_ptr_factory_.GetWeakPtr(), render_frame_id, cdm_id, promise_id));
scoped_refptr<MediaKeys> cdm = GetCdm(render_frame_id, cdm_id);
@@ -549,7 +555,7 @@ void BrowserCdmManager::OnCloseSession(int render_frame_id,
const std::string& session_id) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
- scoped_ptr<SimplePromise> promise(new SimplePromise(
+ std::unique_ptr<SimplePromise> promise(new SimplePromise(
weak_ptr_factory_.GetWeakPtr(), render_frame_id, cdm_id, promise_id));
scoped_refptr<MediaKeys> cdm = GetCdm(render_frame_id, cdm_id);
@@ -567,7 +573,7 @@ void BrowserCdmManager::OnRemoveSession(int render_frame_id,
const std::string& session_id) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
- scoped_ptr<SimplePromise> promise(new SimplePromise(
+ std::unique_ptr<SimplePromise> promise(new SimplePromise(
weak_ptr_factory_.GetWeakPtr(), render_frame_id, cdm_id, promise_id));
scoped_refptr<MediaKeys> cdm = GetCdm(render_frame_id, cdm_id);
@@ -588,7 +594,7 @@ void BrowserCdmManager::OnCdmCreated(
int render_frame_id,
int cdm_id,
const GURL& security_origin,
- scoped_ptr<media::SimpleCdmPromise> promise,
+ std::unique_ptr<media::SimpleCdmPromise> promise,
const scoped_refptr<media::MediaKeys>& cdm,
const std::string& error_message) {
if (!cdm) {
@@ -666,11 +672,12 @@ void BrowserCdmManager::CheckPermissionStatusOnUIThread(
return;
}
- PermissionStatus permission_status = permission_manager->GetPermissionStatus(
- PermissionType::PROTECTED_MEDIA_IDENTIFIER, security_origin,
- web_contents->GetLastCommittedURL().GetOrigin());
+ blink::mojom::PermissionStatus permission_status =
+ permission_manager->GetPermissionStatus(
+ PermissionType::PROTECTED_MEDIA_IDENTIFIER, security_origin,
+ web_contents->GetLastCommittedURL().GetOrigin());
- bool allowed = (permission_status == PERMISSION_STATUS_GRANTED);
+ bool allowed = (permission_status == blink::mojom::PermissionStatus::GRANTED);
if (!task_runner_->RunsTasksOnCurrentThread()) {
task_runner_->PostTask(FROM_HERE,
base::Bind(permission_status_cb, allowed));
@@ -685,7 +692,7 @@ void BrowserCdmManager::CreateSessionAndGenerateRequestIfPermitted(
media::MediaKeys::SessionType session_type,
media::EmeInitDataType init_data_type,
const std::vector<uint8_t>& init_data,
- scoped_ptr<media::NewSessionCdmPromise> promise,
+ std::unique_ptr<media::NewSessionCdmPromise> promise,
bool permission_was_allowed) {
DCHECK(task_runner_->RunsTasksOnCurrentThread());
@@ -709,7 +716,7 @@ void BrowserCdmManager::LoadSessionIfPermitted(
int cdm_id,
media::MediaKeys::SessionType session_type,
const std::string& session_id,
- scoped_ptr<media::NewSessionCdmPromise> promise,
+ std::unique_ptr<media::NewSessionCdmPromise> promise,
bool permission_was_allowed) {
DCHECK_NE(media::MediaKeys::SessionType::TEMPORARY_SESSION, session_type);
DCHECK(task_runner_->RunsTasksOnCurrentThread());
diff --git a/chromium/content/browser/media/cdm/browser_cdm_manager.h b/chromium/content/browser/media/cdm/browser_cdm_manager.h
index e3a986a6f7f..cdf088f3cb8 100644
--- a/chromium/content/browser/media/cdm/browser_cdm_manager.h
+++ b/chromium/content/browser/media/cdm/browser_cdm_manager.h
@@ -8,22 +8,22 @@
#include <stdint.h>
#include <map>
+#include <memory>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
#include "content/common/media/cdm_messages.h"
#include "content/common/media/cdm_messages_enums.h"
#include "content/public/browser/browser_message_filter.h"
-#include "content/public/common/permission_status.mojom.h"
#include "ipc/ipc_message.h"
#include "media/base/cdm_promise.h"
#include "media/base/eme_constants.h"
#include "media/base/media_keys.h"
+#include "third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h"
#include "url/gurl.h"
struct CdmHostMsg_CreateSessionAndGenerateRequest_Params;
@@ -151,7 +151,7 @@ class CONTENT_EXPORT BrowserCdmManager : public BrowserMessageFilter {
void OnCdmCreated(int render_frame_id,
int cdm_id,
const GURL& security_origin,
- scoped_ptr<media::SimpleCdmPromise> promise,
+ std::unique_ptr<media::SimpleCdmPromise> promise,
const scoped_refptr<media::MediaKeys>& cdm,
const std::string& error_message);
@@ -184,17 +184,18 @@ class CONTENT_EXPORT BrowserCdmManager : public BrowserMessageFilter {
media::MediaKeys::SessionType session_type,
media::EmeInitDataType init_data_type,
const std::vector<uint8_t>& init_data,
- scoped_ptr<media::NewSessionCdmPromise> promise,
+ std::unique_ptr<media::NewSessionCdmPromise> promise,
bool permission_was_allowed);
// Calls LoadSession() on the CDM if |permission_was_allowed| is true.
// Otherwise rejects |promise|.
- void LoadSessionIfPermitted(int render_frame_id,
- int cdm_id,
- media::MediaKeys::SessionType session_type,
- const std::string& session_id,
- scoped_ptr<media::NewSessionCdmPromise> promise,
- bool permission_was_allowed);
+ void LoadSessionIfPermitted(
+ int render_frame_id,
+ int cdm_id,
+ media::MediaKeys::SessionType session_type,
+ const std::string& session_id,
+ std::unique_ptr<media::NewSessionCdmPromise> promise,
+ bool permission_was_allowed);
const int render_process_id_;
@@ -202,7 +203,7 @@ class CONTENT_EXPORT BrowserCdmManager : public BrowserMessageFilter {
// dispatched to the browser UI thread.
scoped_refptr<base::TaskRunner> task_runner_;
- scoped_ptr<media::CdmFactory> cdm_factory_;
+ std::unique_ptr<media::CdmFactory> cdm_factory_;
// The key in the following maps is a combination of |render_frame_id| and
// |cdm_id|.
diff --git a/chromium/content/browser/media/encrypted_media_browsertest.cc b/chromium/content/browser/media/encrypted_media_browsertest.cc
index 0f5316302d3..67ba9bbd9f9 100644
--- a/chromium/content/browser/media/encrypted_media_browsertest.cc
+++ b/chromium/content/browser/media/encrypted_media_browsertest.cc
@@ -12,6 +12,7 @@
#include "content/shell/browser/shell.h"
#if defined(OS_ANDROID)
#include "base/android/build_info.h"
+#include "media/base/media.h"
#endif
// Available key systems.
@@ -136,11 +137,8 @@ class EncryptedMediaTest : public content::MediaBrowserTest,
using ::testing::Combine;
using ::testing::Values;
-#if !defined(OS_ANDROID)
-// Encrypted media playback with SRC is not supported on Android.
INSTANTIATE_TEST_CASE_P(SRC_ClearKey, EncryptedMediaTest,
Combine(Values(kClearKeyKeySystem), Values(SRC)));
-#endif // !defined(OS_ANDROID)
INSTANTIATE_TEST_CASE_P(MSE_ClearKey, EncryptedMediaTest,
Combine(Values(kClearKeyKeySystem), Values(MSE)));
@@ -166,25 +164,25 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoClearAudio_WebM) {
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_AudioOnly_WebM_Opus) {
- // Opus is not supported on Android. http://crbug.com/318436
#if defined(OS_ANDROID)
- return;
+ if (!media::PlatformHasOpusSupport())
+ return;
#endif
TestSimplePlayback("bear-320x240-opus-a_enc-a.webm", kWebMAudioOnly);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoAudio_WebM_Opus) {
- // Opus is not supported on Android. http://crbug.com/318436
#if defined(OS_ANDROID)
- return;
+ if (!media::PlatformHasOpusSupport())
+ return;
#endif
TestSimplePlayback("bear-320x240-opus-av_enc-av.webm", kWebMAudioVideo);
}
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, Playback_VideoClearAudio_WebM_Opus) {
- // Opus is not supported on Android. http://crbug.com/318436
#if defined(OS_ANDROID)
- return;
+ if (!media::PlatformHasOpusSupport())
+ return;
#endif
TestSimplePlayback("bear-320x240-opus-av_enc-v.webm", kWebMAudioVideo);
}
@@ -193,9 +191,13 @@ IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, ConfigChangeVideo) {
TestConfigChange();
}
+// Playback of this video on Android w/ Spitzer enabled causes glitches. See
+// http://crbug.com/598963.
+#if !defined(OS_ANDROID)
IN_PROC_BROWSER_TEST_P(EncryptedMediaTest, FrameSizeChangeVideo) {
TestFrameSizeChange();
}
+#endif
IN_PROC_BROWSER_TEST_F(EncryptedMediaTest, UnknownKeySystemThrowsException) {
RunEncryptedMediaTest(kDefaultEmePlayer,
diff --git a/chromium/content/browser/media/media_browsertest.cc b/chromium/content/browser/media/media_browsertest.cc
index 43db9ad4f72..4f6779926ce 100644
--- a/chromium/content/browser/media/media_browsertest.cc
+++ b/chromium/content/browser/media/media_browsertest.cc
@@ -27,7 +27,7 @@ void MediaBrowserTest::RunMediaTestPage(const std::string& html_page,
bool http) {
GURL gurl;
std::string query = media::GetURLQueryString(query_params);
- scoped_ptr<net::EmbeddedTestServer> http_test_server;
+ std::unique_ptr<net::EmbeddedTestServer> http_test_server;
if (http) {
http_test_server.reset(new net::EmbeddedTestServer);
http_test_server->ServeFilesFromSourceDirectory(media::GetTestDataPath());
@@ -131,6 +131,10 @@ IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearMp4) {
PlayVideo("bear.mp4", GetParam());
}
+IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearHighBitDepthMp4) {
+ PlayVideo("bear-320x180-hi10p.mp4", GetParam());
+}
+
IN_PROC_BROWSER_TEST_P(MediaTest, VideoBearSilentMp4) {
PlayVideo("bear_silent.mp4", GetParam());
}
@@ -259,6 +263,10 @@ IN_PROC_BROWSER_TEST_F(MediaTest, Yuv420pRec709H264) {
RunColorFormatTest("yuv420p_rec709.mp4", kEnded);
}
+IN_PROC_BROWSER_TEST_F(MediaTest, Yuv420pHighBitDepth) {
+ RunColorFormatTest("yuv420p_hi10p.mp4", kEnded);
+}
+
IN_PROC_BROWSER_TEST_F(MediaTest, Yuvj420pH264) {
RunColorFormatTest("yuvj420p.mp4", kEnded);
}
diff --git a/chromium/content/browser/media/media_canplaytype_browsertest.cc b/chromium/content/browser/media/media_canplaytype_browsertest.cc
index 83493ccc317..7dba85b1d1a 100644
--- a/chromium/content/browser/media/media_canplaytype_browsertest.cc
+++ b/chromium/content/browser/media/media_canplaytype_browsertest.cc
@@ -21,25 +21,25 @@ const char kMaybe[] = "maybe";
const char kNot[] = "";
#if defined(USE_PROPRIETARY_CODECS)
-const char kPropProbably[] = "probably";
-const char kPropMaybe[] = "maybe";
+const char* kPropProbably = kProbably;
+const char* kPropMaybe = kMaybe;
#else
-const char kPropProbably[] = "";
-const char kPropMaybe[] = "";
+const char* kPropProbably = kNot;
+const char* kPropMaybe = kNot;
#endif // USE_PROPRIETARY_CODECS
#if !defined(OS_ANDROID)
-const char kOggVideoProbably[] = "probably";
-const char kOggVideoMaybe[] = "maybe";
-const char kTheoraProbably[] = "probably";
-const char kOggOpusProbably[] = "probably";
-const char* kMpeg2AacProbably = kPropProbably;
+const char* kOggVideoProbably = kProbably;
+const char* kOggVideoMaybe = kMaybe;
+const char* kTheoraProbably = kProbably;
+const char* kHlsProbably = kNot;
+const char* kHlsMaybe = kNot;
#else
-const char kOggVideoProbably[] = "";
-const char kOggVideoMaybe[] = "";
-const char kTheoraProbably[] = "";
-const char kOggOpusProbably[] = "";
-const char kMpeg2AacProbably[] = "";
+const char* kOggVideoProbably = kNot;
+const char* kOggVideoMaybe = kNot;
+const char* kTheoraProbably = kNot;
+const char* kHlsProbably = kPropProbably;
+const char* kHlsMaybe = kPropMaybe;
#endif // !OS_ANDROID
#if BUILDFLAG(ENABLE_HEVC_DEMUXING)
@@ -69,6 +69,15 @@ const char* kMp2tsAc3Eac3Probably = kPropProbably;
const char* kMp2tsAc3Eac3Probably = kNot;
#endif
+// High 10-bit profile is only available when we can use ffmpeg to decode H.264.
+// Even though FFmpeg is used on Android, we only use platform decoders for
+// H.264
+#if !defined(MEDIA_DISABLE_FFMPEG) && !defined(OS_ANDROID)
+const char* kHi10pProbably = kPropProbably;
+#else
+const char* kHi10pProbably = kPropMaybe;
+#endif
+
namespace content {
class MediaCanPlayTypeTest : public MediaBrowserTest {
@@ -136,6 +145,16 @@ class MediaCanPlayTypeTest : public MediaBrowserTest {
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.300.30\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.-1.30\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.x.30\"'"));
+ // Old-style avc1 codec ids are supported only for video/mp2t container.
+ if (mime != "video/mp2t") {
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.66.13\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.77.30\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.100.40\"'"));
+ }
+ // Old-style codec ids are not supported for avc3 codec strings.
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.66.13\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.77.30\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.100.40\"'"));
// AAC codecs must be followed by one or two valid hexadecimal numbers.
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.no\"'"));
@@ -174,6 +193,19 @@ class MediaCanPlayTypeTest : public MediaBrowserTest {
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\";mp4a.40+\"'"));
// Codecs not belonging to MPEG container.
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1, 1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3, 1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.4D401E, 1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.64001F, 1\"'"));
+
+ // Remove all but "audio/mpeg" when https://crbug.com/592889 is fixed.
+ if (mime != "audio/mpeg" && mime != "audio/mp4" && mime != "video/mp4" &&
+ mime != "application/x-mpegurl" &&
+ mime != "application/vnd.apple.mpegurl" && mime != "video/mp2t") {
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp3\"'"));
+ }
+
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vorbis\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1, vorbis\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3, vorbis\"'"));
@@ -195,12 +227,6 @@ class MediaCanPlayTypeTest : public MediaBrowserTest {
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8, mp4a.40.02\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9, mp4a.40.02\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"1\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1, 1\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3, 1\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.4D401E, 1\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.64001F, 1\"'"));
-
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora, mp4a\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora, mp4a.40.2\"'"));
@@ -299,36 +325,47 @@ class MediaCanPlayTypeTest : public MediaBrowserTest {
void TestOGGUnacceptableCombinations(const std::string& mime) {
// Codecs not belonging to OGG container.
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp8\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp8.0\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp8, opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp8, vorbis\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp9\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp9.0\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp9, opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp9, vorbis\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc3\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1.4D401E\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc3.64001F\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1.66.30\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1, vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc3, vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1, opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc3, opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora, 1\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8.0\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8, opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8, vorbis\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9.0\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9, opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9, vorbis\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.4D401E\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.64001F\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.66.30\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1, vorbis\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3, vorbis\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1, opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3, opus\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1.1.6.L93.B0\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1.1.6.L93.B0\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1.1.6.L93.B0,opus\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1.1.6.L93.B0,opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"mp4a.40\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"mp4a.40.2\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"mp4a.40.02\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"theora, mp4a.40.2\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"theora, mp4a.40.02\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp3\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.66\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.67\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.68\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.69\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.6B\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40.2\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40.02\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora, mp4a.40.2\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora, mp4a.40.02\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ac-3\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ec-3\"'"));
@@ -337,54 +374,59 @@ class MediaCanPlayTypeTest : public MediaBrowserTest {
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.a5\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.a6\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"1\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"theora, 1\"'"));
-
// Codecs are case sensitive.
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"Theora\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"Opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"Vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"Theora, Opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"Theora, Vorbis\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"Theora\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"Opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"Vorbis\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"Theora, Opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"Theora, Vorbis\"'"));
// Unknown codecs.
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"unknown\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"unknown\"'"));
}
void TestWEBMUnacceptableCombinations(const std::string& mime) {
// Codecs not belonging to WEBM container.
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"1\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp8, 1\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp9, 1\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp8.0, 1\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp9.0, 1\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"theora\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"theora, vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"theora, opus\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc3\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1.4D401E\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc3.64001F\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1.66.30\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1, vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc3, vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1, opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc3, opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8, 1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9, 1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8.0, 1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9.0, 1\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora, vorbis\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora, opus\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.4D401E\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.64001F\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.66.30\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1, vorbis\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3, vorbis\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1, opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3, opus\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1.1.6.L93.B0\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1.1.6.L93.B0\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1.1.6.L93.B0,opus\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1.1.6.L93.B0,opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"mp4a.40\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"mp4a.40.2\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"mp4a.40.02\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp8, mp4a.40\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp9, mp4a.40\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp8.0, mp4a.40\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp9.0, mp4a.40\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp3\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.66\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.67\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.68\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.69\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.6B\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40.2\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40.02\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8, mp4a.40\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9, mp4a.40\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8.0, mp4a.40\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9.0, mp4a.40\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ac-3\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ec-3\"'"));
@@ -394,43 +436,51 @@ class MediaCanPlayTypeTest : public MediaBrowserTest {
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.a6\"'"));
// Codecs are case sensitive.
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"VP8, Vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"VP8.0, Opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"VP9, Vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"VP9.0, Opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"VP8, Vorbis\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"VP8.0, Opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"VP9, Vorbis\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"VP9.0, Opus\"'"));
// Unknown codec.
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"unknown\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"unknown\"'"));
}
void TestWAVUnacceptableCombinations(const std::string& mime) {
// Codecs not belonging to WAV container.
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp8\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp9\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp8.0, 1\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vp9.0, 1\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"vorbis\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"theora\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"theora, 1\"'"));
-
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc3\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1.4D401E\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc3.64001F\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1.66.30\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc1, 1\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"avc3, 1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp8.0, 1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vp9.0, 1\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"vorbis\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"opus\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"theora, 1\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.4D401E\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3.64001F\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1.66.30\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc1, 1\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"avc3, 1\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1.1.6.L93.B0\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1.1.6.L93.B0\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hev1.1.6.L93.B0,opus\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"hvc1.1.6.L93.B0,opus\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"mp4a.40\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"mp4a.40.2\"'"));
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"mp4a.40.02\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp3\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.66\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.67\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.68\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.69\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.6B\"'"));
+
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40.2\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.40.02\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ac-3\"'"));
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"ec-3\"'"));
@@ -440,7 +490,7 @@ class MediaCanPlayTypeTest : public MediaBrowserTest {
EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"mp4a.a6\"'"));
// Unknown codec.
- EXPECT_EQ(kNot, CanPlay("'" + mime +"; codecs=\"unknown\"'"));
+ EXPECT_EQ(kNot, CanPlay("'" + mime + "; codecs=\"unknown\"'"));
}
private:
@@ -461,45 +511,31 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_wav) {
}
IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_webm) {
- // On Android, VP9 is supported only on KitKat and above (API level 19) and
- // Opus is supported only on Lollipop and above (API level 21).
- std::string VP9Probably = "probably";
- std::string VP9AndOpusProbably = "probably";
- std::string OpusProbably = "probably";
-#if defined(OS_ANDROID)
- if (base::android::BuildInfo::GetInstance()->sdk_int() < 19)
- VP9Probably = "";
- if (base::android::BuildInfo::GetInstance()->sdk_int() < 21) {
- OpusProbably = "";
- VP9AndOpusProbably = "";
- }
-#endif
EXPECT_EQ(kMaybe, CanPlay("'video/webm'"));
EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp8\"'"));
EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp8.0\"'"));
EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp8, vorbis\"'"));
EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp8.0, vorbis\"'"));
- EXPECT_EQ(OpusProbably, CanPlay("'video/webm; codecs=\"vp8, opus\"'"));
- EXPECT_EQ(OpusProbably, CanPlay("'video/webm; codecs=\"vp8.0, opus\"'"));
+ EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp8, opus\"'"));
+ EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp8.0, opus\"'"));
- EXPECT_EQ(VP9Probably, CanPlay("'video/webm; codecs=\"vp9\"'"));
- EXPECT_EQ(VP9Probably, CanPlay("'video/webm; codecs=\"vp9.0\"'"));
- EXPECT_EQ(VP9Probably, CanPlay("'video/webm; codecs=\"vp9, vorbis\"'"));
- EXPECT_EQ(VP9Probably, CanPlay("'video/webm; codecs=\"vp9.0, vorbis\"'"));
- EXPECT_EQ(VP9AndOpusProbably, CanPlay("'video/webm; codecs=\"vp9, opus\"'"));
- EXPECT_EQ(VP9AndOpusProbably,
- CanPlay("'video/webm; codecs=\"vp9.0, opus\"'"));
+ EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp9\"'"));
+ EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp9.0\"'"));
+ EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp9, vorbis\"'"));
+ EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp9.0, vorbis\"'"));
+ EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp9, opus\"'"));
+ EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp9.0, opus\"'"));
- EXPECT_EQ(VP9Probably, CanPlay("'video/webm; codecs=\"vp8, vp9\"'"));
- EXPECT_EQ(VP9Probably, CanPlay("'video/webm; codecs=\"vp8.0, vp9.0\"'"));
+ EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp8, vp9\"'"));
+ EXPECT_EQ(kProbably, CanPlay("'video/webm; codecs=\"vp8.0, vp9.0\"'"));
TestWEBMUnacceptableCombinations("video/webm");
EXPECT_EQ(kMaybe, CanPlay("'audio/webm'"));
EXPECT_EQ(kProbably, CanPlay("'audio/webm; codecs=\"vorbis\"'"));
- EXPECT_EQ(OpusProbably, CanPlay("'audio/webm; codecs=\"opus\"'"));
- EXPECT_EQ(OpusProbably, CanPlay("'audio/webm; codecs=\"opus, vorbis\"'"));
+ EXPECT_EQ(kProbably, CanPlay("'audio/webm; codecs=\"opus\"'"));
+ EXPECT_EQ(kProbably, CanPlay("'audio/webm; codecs=\"opus, vorbis\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp8\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/webm; codecs=\"vp8.0\"'"));
@@ -532,8 +568,8 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_ogg) {
EXPECT_EQ(kMaybe, CanPlay("'audio/ogg'"));
EXPECT_EQ(kProbably, CanPlay("'audio/ogg; codecs=\"vorbis\"'"));
- EXPECT_EQ(kOggOpusProbably, CanPlay("'audio/ogg; codecs=\"opus\"'"));
- EXPECT_EQ(kOggOpusProbably, CanPlay("'audio/ogg; codecs=\"vorbis, opus\"'"));
+ EXPECT_EQ(kProbably, CanPlay("'audio/ogg; codecs=\"opus\"'"));
+ EXPECT_EQ(kProbably, CanPlay("'audio/ogg; codecs=\"vorbis, opus\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"theora\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/ogg; codecs=\"theora, opus\"'"));
@@ -544,13 +580,12 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_ogg) {
EXPECT_EQ(kMaybe, CanPlay("'application/ogg'"));
EXPECT_EQ(kProbably, CanPlay("'application/ogg; codecs=\"vorbis\"'"));
EXPECT_EQ(kTheoraProbably, CanPlay("'application/ogg; codecs=\"theora\"'"));
- EXPECT_EQ(kOggOpusProbably, CanPlay("'application/ogg; codecs=\"opus\"'"));
+ EXPECT_EQ(kProbably, CanPlay("'application/ogg; codecs=\"opus\"'"));
EXPECT_EQ(kTheoraProbably,
CanPlay("'application/ogg; codecs=\"theora, vorbis\"'"));
EXPECT_EQ(kTheoraProbably,
CanPlay("'application/ogg; codecs=\"theora, opus\"'"));
- EXPECT_EQ(kOggOpusProbably,
- CanPlay("'application/ogg; codecs=\"opus, vorbis\"'"));
+ EXPECT_EQ(kProbably, CanPlay("'application/ogg; codecs=\"opus, vorbis\"'"));
TestOGGUnacceptableCombinations("application/ogg");
}
@@ -572,8 +607,13 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp3) {
EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"avc1.4D401E\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"avc3.64001F\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"avc1.66.30\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"mp4a.66\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"mp4a.67\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"mp4a.68\"'"));
+ // The next two results are wrong due to https://crbug.com/592889.
+ EXPECT_EQ(kPropProbably, CanPlay("'audio/mpeg; codecs=\"mp4a.69\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'audio/mpeg; codecs=\"mp4a.6B\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"mp4a.40.2\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mpeg; codecs=\"mp4a.40.02\"'"));
@@ -587,12 +627,17 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp3) {
EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"avc1.4D401E\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"avc3.64001F\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"avc1.66.30\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"mp4a.66\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"mp4a.67\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"mp4a.68\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"mp4a.69\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"mp4a.6B\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"mp4a.40.2\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"mp4a.40.02\"'"));
TestMPEGUnacceptableCombinations("audio/mp3");
+ EXPECT_EQ(kNot, CanPlay("'audio/mp3; codecs=\"mp3\"'"));
// audio/x-mp3 does not allow any codecs parameter
EXPECT_EQ(kPropProbably, CanPlay("'audio/x-mp3'"));
@@ -602,12 +647,17 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp3) {
EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"avc1.4D401E\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"avc3.64001F\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"avc1.66.30\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"mp4a.66\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"mp4a.67\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"mp4a.68\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"mp4a.69\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"mp4a.6B\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"mp4a.40.2\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"mp4a.40.02\"'"));
TestMPEGUnacceptableCombinations("audio/x-mp3");
+ EXPECT_EQ(kNot, CanPlay("'audio/x-mp3; codecs=\"mp3\"'"));
}
IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
@@ -621,18 +671,19 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1, avc3\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E01E\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42101E\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42701E\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42F01E\"'"));
+
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.42E01E\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.42801E\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.42C01E\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc1.66.13\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc1.77.30\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc1.100.40\"'"));
-
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.42E11E\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42101E\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42701E\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42F01E\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"mp4a.66\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"mp4a.67\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"mp4a.68\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"mp4a.69\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"mp4a.6B\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"mp4a.40.2\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"mp4a.40.02\"'"));
@@ -691,6 +742,8 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
CanPlay("'video/mp4; codecs=\"hvc1.1.6.L93.B0, mp4a.40.5\"'"));
TestMPEGUnacceptableCombinations("video/mp4");
+ // This result is incorrect. See https://crbug.com/592889.
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"mp3\"'"));
EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v'"));
@@ -702,18 +755,19 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc1, avc3\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1.42E01E\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1.42101E\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1.42701E\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1.42F01E\"'"));
+
EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc3.42E01E\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc3.42801E\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc3.42C01E\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"avc1.66.13\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"avc1.77.30\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"avc1.100.40\"'"));
-
- EXPECT_EQ(kPropMaybe, CanPlay("'video/x-m4v; codecs=\"avc1.42E11E\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1.42101E\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1.42701E\"'"));
- EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"avc1.42F01E\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"mp4a.66\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"mp4a.67\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"mp4a.68\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"mp4a.69\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"mp4a.6B\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"mp4a.40.2\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/x-m4v; codecs=\"mp4a.40.02\"'"));
@@ -737,37 +791,35 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
EXPECT_EQ(kPropMaybe,
CanPlay("'video/x-m4v; codecs=\"avc3.42E01E, mp4a.40\"'"));
- EXPECT_EQ(kHevcSupported,
- CanPlay("'video/x-m4v; codecs=\"hev1.1.6.L93.B0\"'"));
- EXPECT_EQ(kHevcSupported,
- CanPlay("'video/x-m4v; codecs=\"hvc1.1.6.L93.B0\"'"));
- EXPECT_EQ(kHevcSupported,
+ EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"hev1.1.6.L93.B0\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"hvc1.1.6.L93.B0\"'"));
+ EXPECT_EQ(kNot,
CanPlay("'video/x-m4v; codecs=\"hev1.1.6.L93.B0, mp4a.40.5\"'"));
- EXPECT_EQ(kHevcSupported,
+ EXPECT_EQ(kNot,
CanPlay("'video/x-m4v; codecs=\"hvc1.1.6.L93.B0, mp4a.40.5\"'"));
- EXPECT_EQ(kAc3Eac3Probably, CanPlay("'video/x-m4v; codecs=\"ac-3\"'"));
- EXPECT_EQ(kAc3Eac3Probably, CanPlay("'video/x-m4v; codecs=\"mp4a.a5\"'"));
- EXPECT_EQ(kAc3Eac3Probably, CanPlay("'video/x-m4v; codecs=\"mp4a.A5\"'"));
- EXPECT_EQ(kAc3Eac3Probably, CanPlay("'video/x-m4v; codecs=\"ec-3\"'"));
- EXPECT_EQ(kAc3Eac3Probably, CanPlay("'video/x-m4v; codecs=\"mp4a.a6\"'"));
- EXPECT_EQ(kAc3Eac3Probably, CanPlay("'video/x-m4v; codecs=\"mp4a.A6\"'"));
- EXPECT_EQ(kAc3Eac3Probably,
- CanPlay("'video/x-m4v; codecs=\"avc1.640028,ac-3\"'"));
- EXPECT_EQ(kAc3Eac3Probably,
- CanPlay("'video/x-m4v; codecs=\"avc1.640028,mp4a.a5\"'"));
- EXPECT_EQ(kAc3Eac3Probably,
- CanPlay("'video/x-m4v; codecs=\"avc1.640028,mp4a.A5\"'"));
- EXPECT_EQ(kAc3Eac3Probably,
- CanPlay("'video/x-m4v; codecs=\"avc1.640028,ec-3\"'"));
- EXPECT_EQ(kAc3Eac3Probably,
- CanPlay("'video/x-m4v; codecs=\"avc1.640028,mp4a.a6\"'"));
- EXPECT_EQ(kAc3Eac3Probably,
- CanPlay("'video/x-m4v; codecs=\"avc1.640028,mp4a.A6\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"ac-3\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"mp4a.a5\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"mp4a.A5\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"ec-3\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"mp4a.a6\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"mp4a.A6\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"avc1.640028,ac-3\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"avc1.640028,mp4a.a5\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"avc1.640028,mp4a.A5\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"avc1.640028,ec-3\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"avc1.640028,mp4a.a6\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/x-m4v; codecs=\"avc1.640028,mp4a.A6\"'"));
TestMPEGUnacceptableCombinations("video/x-m4v");
EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.66\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.67\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.68\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.69\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.6B\"'"));
+
EXPECT_EQ(kPropMaybe, CanPlay("'audio/mp4; codecs=\"mp4a.40\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.40.2\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.40.02\"'"));
@@ -782,7 +834,6 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"avc1.4D401E\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"avc3.64001F\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"avc1.66.30\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"hev1.1.6.L93.B0\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"hvc1.1.6.L93.B0\"'"));
@@ -797,8 +848,17 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
EXPECT_EQ(kAc3Eac3Probably, CanPlay("'audio/mp4; codecs=\"mp4a.A6\"'"));
TestMPEGUnacceptableCombinations("audio/mp4");
+ // This result is incorrect. See https://crbug.com/592889.
+ EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp3\"'"));
EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a'"));
+
+ EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"mp4a.66\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"mp4a.67\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"mp4a.68\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"mp4a.69\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"mp4a.6B\"'"));
+
EXPECT_EQ(kPropMaybe, CanPlay("'audio/x-m4a; codecs=\"mp4a.40\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"mp4a.40.2\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'audio/x-m4a; codecs=\"mp4a.40.02\"'"));
@@ -813,7 +873,6 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"avc1.4D401E\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"avc3.64001F\"'"));
- EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"avc1.66.30\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"hev1.1.6.L93.B0\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"hvc1.1.6.L93.B0\"'"));
@@ -822,27 +881,32 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_mp4) {
EXPECT_EQ(kNot,
CanPlay("'audio/x-m4a; codecs=\"hvc1.1.6.L93.B0, mp4a.40.5\"'"));
- EXPECT_EQ(kAc3Eac3Probably, CanPlay("'audio/x-m4a; codecs=\"ac-3\"'"));
- EXPECT_EQ(kAc3Eac3Probably, CanPlay("'audio/x-m4a; codecs=\"mp4a.a5\"'"));
- EXPECT_EQ(kAc3Eac3Probably, CanPlay("'audio/x-m4a; codecs=\"mp4a.A5\"'"));
- EXPECT_EQ(kAc3Eac3Probably, CanPlay("'audio/x-m4a; codecs=\"ec-3\"'"));
- EXPECT_EQ(kAc3Eac3Probably, CanPlay("'audio/x-m4a; codecs=\"mp4a.a6\"'"));
- EXPECT_EQ(kAc3Eac3Probably, CanPlay("'audio/x-m4a; codecs=\"mp4a.A6\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"ac-3\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"mp4a.a5\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"mp4a.A5\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"ec-3\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"mp4a.a6\"'"));
+ EXPECT_EQ(kNot, CanPlay("'audio/x-m4a; codecs=\"mp4a.A6\"'"));
TestMPEGUnacceptableCombinations("audio/x-m4a");
}
-// When modifying this test, also change CodecSupportTest_Avc3Variants.
IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_Avc1Variants) {
// avc1 without extensions results in "maybe" for compatibility.
EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1\"'"));
- // Any 6-digit hexadecimal number will result in at least "maybe".
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.123456\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.ABCDEF\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.abcdef\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc1.12345\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc1.1234567\"'"));
+ // A valid-looking 6-digit hexadecimal number will result in at least "maybe".
+ // But the first hex byte after the dot must be a valid profile_idc and the
+ // lower two bits of the second byte/4th digit must be zero.
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.42AC23\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.42ACDF\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.42acdf\"'"));
+
+ // Invalid profile 0x12.
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc1.123456\"'"));
+ // Valid profile/level, but reserved bits are set to 1 (4th digit after dot).
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc1.42011E\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc1.42021E\"'"));
// Both upper and lower case hexadecimal digits are accepted.
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E01E\"'"));
@@ -856,68 +920,97 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_Avc1Variants) {
//
// Baseline Profile (66 == 0x42).
- // The first two digits must be 42. The third digit (constraint_set_flags)
- // must be valid hex but it otherwise is ignored. The fourth digit (reserved)
- // must be 0. The last two digits must be any valid level.
+ // The first two digits after the dot must be 42. The third and fourth digits
+ // contain constraint_set_flags and must be valid hex. The last two digits
+ // should be any valid H.264 level. If the level value is invalid the result
+ // will be kMaybe.
//
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42001E\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42401E\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42801E\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.42E00A\"'"));
EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc1.42G01E\"'"));
-
- // The fourth digit must be 0.
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.42E11E\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc1.42000G\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.42E0FF\"'"));
//
// Main Profile (77 == 0x4D).
- // The first two digits must be 4D. The third digit (constraint_set_flags)
- // must be valid hex but it otherwise is ignored. The fourth digit (reserved)
- // must be 0. The last two digits must be any valid level.
+ // The first two digits after the dot must be 4D. The third and fourth digits
+ // contain constraint_set_flags and must be valid hex. The last two digits
+ // should be any valid H.264 level. If the level value is invalid the result
+ // will be kMaybe.
//
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.4D001E\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.4D400A\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.4D800A\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.4DE00A\"'"));
EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc1.4DG01E\"'"));
-
- // The fourth digit must be 0.
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.4DE11E\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc1.4D000G\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.4DE0FF\"'"));
//
// High Profile (100 == 0x64).
- // The first two digits must be 64. The third digit (constraint_set_flags)
- // must be valid hex but it otherwise is ignored. The fourth digit (reserved)
- // must be 0. The last two digits must be any valid level.
+ // The first two digits after the dot must be 64. The third and fourth digits
+ // contain constraint_set_flags and must be valid hex. The last two digits
+ // should be any valid H.264 level. If the level value is invalid the result
+ // will be kMaybe.
//
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.64001E\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.64400A\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.64800A\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.64E00A\"'"));
EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc1.64G01E\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc1.64000G\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.64E0FF\"'"));
- // The fourth digit must be 0.
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.64E11E\"'"));
+ //
+ // High 10-bit Profile (110 == 0x6E).
+ // The first two digits after the dot must be 6E. The third and fourth digits
+ // contain constraint_set_flags and must be valid hex. The last two digits
+ // should be any valid H.264 level. If the level value is invalid the result
+ // will be kMaybe.
+ //
+ EXPECT_EQ(kHi10pProbably, CanPlay("'video/mp4; codecs=\"avc1.6E001E\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.6E400A\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.6E800A\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.6EE00A\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc1.6EG01E\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc1.6E000G\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.6EE0FF\"'"));
//
// Other profiles are not known to be supported.
//
// Extended Profile (88 == 0x58).
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.58A01E\"'"));
+ // Without any constraint flags.
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.58001E\"'"));
+ // With constraint_set0_flag==1 indicating compatibility with baseline
+ // profile.
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.58801E\"'"));
+ // With constraint_set1_flag==1 indicating compatibility with main profile.
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc1.58401E\"'"));
+ // With constraint_set2_flag==1 indicating compatibility with extended
+ // profile, the result is 'maybe' the same as for straight extended profile.
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc1.58201E\"'"));
}
-// When modifying this test, also change CodecSupportTest_Avc1Variants.
IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_Avc3Variants) {
// avc3 without extensions results in "maybe" for compatibility.
EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3\"'"));
- // Any 6-digit hexadecimal number will result in at least "maybe".
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3.123456\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3.ABCDEF\"'"));
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3.abcdef\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc3.12345\"'"));
- EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc3.1234567\"'"));
+ // A valid-looking 6-digit hexadecimal number will result in at least "maybe".
+ // But the first hex byte after the dot must be a valid profile_idc and the
+ // lower two bits of the second byte/4th digit must be zero.
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3.42AC23\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3.42ACDF\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3.42acdf\"'"));
+
+ // Invalid profile 0x12.
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc3.123456\"'"));
+ // Valid profile/level, but reserved bits are set to 1 (4th digit after dot).
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc3.42011E\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc3.42021E\"'"));
// Both upper and lower case hexadecimal digits are accepted.
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.42E01E\"'"));
@@ -931,55 +1024,79 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_Avc3Variants) {
//
// Baseline Profile (66 == 0x42).
- // The first two digits must be 42. The third digit (constraint_set_flags)
- // must be valid hex but it otherwise is ignored. The fourth digit (reserved)
- // must be 0. The last two digits must be any valid level.
+ // The first two digits after the dot must be 42. The third and fourth digits
+ // contain constraint_set_flags and must be valid hex. The last two digits
+ // should be any valid H.264 level. If the level value is invalid the result
+ // will be kMaybe.
//
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.42001E\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.42400A\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.42800A\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.42E00A\"'"));
EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc3.42G01E\"'"));
-
- // The fourth digit must be 0.
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3.42E11E\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc3.42000G\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3.42E0FF\"'"));
//
// Main Profile (77 == 0x4D).
- // The first two digits must be 4D. The third digit (constraint_set_flags)
- // must be valid hex but it otherwise is ignored. The fourth digit (reserved)
- // must be 0. The last two digits must be any valid level.
+ // The first two digits after the dot must be 4D. The third and fourth digits
+ // contain constraint_set_flags and must be valid hex. The last two digits
+ // should be any valid H.264 level. If the level value is invalid the result
+ // will be kMaybe.
//
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.4D001E\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.4D400A\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.4D800A\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.4DE00A\"'"));
EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc3.4DG01E\"'"));
-
- // The fourth digit must be 0.
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3.4DE11E\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc3.4D000G\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3.4DE0FF\"'"));
//
// High Profile (100 == 0x64).
- // The first two digits must be 64. The third digit (constraint_set_flags)
- // must be valid hex but it otherwise is ignored. The fourth digit (reserved)
- // must be 0. The last two digits must be any valid level.
+ // The first two digits after the dot must be 64. The third and fourth digits
+ // contain constraint_set_flags and must be valid hex. The last two digits
+ // should be any valid H.264 level. If the level value is invalid the result
+ // will be kMaybe.
//
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.64001E\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.64400A\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.64800A\"'"));
EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.64E00A\"'"));
EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc3.64G01E\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc3.64000G\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3.64E0FF\"'"));
- // The fourth digit must be 0.
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3.64E11E\"'"));
+ //
+ // High 10-bit Profile (110 == 0x6E).
+ // The first two digits after the dot must be 6E. The third and fourth digits
+ // contain constraint_set_flags and must be valid hex. The last two digits
+ // should be any valid H.264 level. If the level value is invalid the result
+ // will be kMaybe.
+ //
+ EXPECT_EQ(kHi10pProbably, CanPlay("'video/mp4; codecs=\"avc3.6E001E\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.6E400A\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.6E800A\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.6EE00A\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc3.6EG01E\"'"));
+ EXPECT_EQ(kNot, CanPlay("'video/mp4; codecs=\"avc3.6E000G\"'"));
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3.6EE0FF\"'"));
//
// Other profiles are not known to be supported.
//
// Extended Profile (88 == 0x58).
- EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3.58A01E\"'"));
+ // Without any constraint flags.
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3.58001E\"'"));
+ // With constraint_set0_flag==1 indicating compatibility with baseline
+ // profile.
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.58801E\"'"));
+ // With constraint_set1_flag==1 indicating compatibility with main profile.
+ EXPECT_EQ(kPropProbably, CanPlay("'video/mp4; codecs=\"avc3.58401E\"'"));
+ // With constraint_set2_flag==1 indicating compatibility with extended
+ // profile, the result is 'maybe' the same as for straight extended profile.
+ EXPECT_EQ(kPropMaybe, CanPlay("'video/mp4; codecs=\"avc3.58201E\"'"));
}
// Tests AVC levels using AVC1 Baseline (0x42E0zz).
@@ -1080,10 +1197,10 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_Mp4aVariants) {
EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a.63\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a.65\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a.65\"'"));
- // MPEG2 AAC Main, LC, and SSR are supported except on Android.
- EXPECT_EQ(kMpeg2AacProbably, CanPlay("'audio/mp4; codecs=\"mp4a.66\"'"));
- EXPECT_EQ(kMpeg2AacProbably, CanPlay("'audio/mp4; codecs=\"mp4a.67\"'"));
- EXPECT_EQ(kMpeg2AacProbably, CanPlay("'audio/mp4; codecs=\"mp4a.68\"'"));
+ // MPEG2 AAC Main, LC, and SSR are supported.
+ EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.66\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.67\"'"));
+ EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.68\"'"));
// MP3.
EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.69\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a.6A\"'"));
@@ -1133,9 +1250,11 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_Mp4aVariants) {
// See http://crbug.com/440607.
EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a.40.00\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a.40.01\"'"));
+ // MPEG4 AAC LC.
EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.40.02\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a.40.03\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a.40.04\"'"));
+ // MPEG4 AAC SBR v1.
EXPECT_EQ(kPropProbably, CanPlay("'audio/mp4; codecs=\"mp4a.40.05\"'"));
EXPECT_EQ(kNot, CanPlay("'audio/mp4; codecs=\"mp4a.40.029\"'"));
@@ -1151,59 +1270,62 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_Mp4aVariants) {
}
IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_HLS) {
- // HLS are supported only on Android IceCreamSandwich and above (API level 14)
- std::string probablyCanPlayHLS = kNot;
- std::string maybeCanPlayHLS = kNot;
-#if defined(OS_ANDROID)
- if (base::android::BuildInfo::GetInstance()->sdk_int() > 13) {
- probablyCanPlayHLS = kProbably;
- maybeCanPlayHLS = kMaybe;
- }
-#endif
- EXPECT_EQ(maybeCanPlayHLS, CanPlay("'application/x-mpegurl'"));
-
- EXPECT_EQ(maybeCanPlayHLS,
- CanPlay("'application/x-mpegurl; codecs=\"avc1\"'"));
- EXPECT_EQ(maybeCanPlayHLS,
- CanPlay("'application/x-mpegurl; codecs=\"avc3\"'"));
- EXPECT_EQ(maybeCanPlayHLS,
- CanPlay("'application/x-mpegurl; codecs=\"mp4a.40\"'"));
- EXPECT_EQ(maybeCanPlayHLS,
+ EXPECT_EQ(kHlsMaybe, CanPlay("'application/x-mpegurl'"));
+
+ EXPECT_EQ(kHlsMaybe, CanPlay("'application/x-mpegurl; codecs=\"avc1\"'"));
+ EXPECT_EQ(kHlsMaybe, CanPlay("'application/x-mpegurl; codecs=\"avc3\"'"));
+ EXPECT_EQ(kHlsMaybe, CanPlay("'application/x-mpegurl; codecs=\"mp4a.40\"'"));
+ EXPECT_EQ(kHlsMaybe,
CanPlay("'application/x-mpegurl; codecs=\"avc1, mp4a.40\"'"));
- EXPECT_EQ(maybeCanPlayHLS,
+ EXPECT_EQ(kHlsMaybe,
CanPlay("'application/x-mpegurl; codecs=\"avc3, mp4a.40\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
+ EXPECT_EQ(kHlsProbably,
CanPlay("'application/x-mpegurl; codecs=\"avc1.42E01E\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
+ EXPECT_EQ(kHlsProbably,
+ CanPlay("'application/x-mpegurl; codecs=\"avc1.42101E\"'"));
+ EXPECT_EQ(kHlsProbably,
+ CanPlay("'application/x-mpegurl; codecs=\"avc1.42701E\"'"));
+ EXPECT_EQ(kHlsProbably,
+ CanPlay("'application/x-mpegurl; codecs=\"avc1.42F01E\"'"));
+
+ EXPECT_EQ(kHlsProbably,
CanPlay("'application/x-mpegurl; codecs=\"avc3.42E01E\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
+ EXPECT_EQ(kHlsProbably,
CanPlay("'application/x-mpegurl; codecs=\"avc3.42801E\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
+ EXPECT_EQ(kHlsProbably,
CanPlay("'application/x-mpegurl; codecs=\"avc3.42C01E\"'"));
- EXPECT_EQ(maybeCanPlayHLS,
- CanPlay("'application/x-mpegurl; codecs=\"avc1.42E11E\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
- CanPlay("'application/x-mpegurl; codecs=\"avc1.42101E\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
- CanPlay("'application/x-mpegurl; codecs=\"avc1.42701E\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
- CanPlay("'application/x-mpegurl; codecs=\"avc1.42F01E\"'"));
+ // Android, is the only platform that supports these types, and its HLS
+ // implementations uses platform codecs, which do not include MPEG-2 AAC.
+ // See https://crbug.com/544268.
+ EXPECT_EQ(kNot, CanPlay("'application/x-mpegurl; codecs=\"mp4a.66\"'"));
+ EXPECT_EQ(kNot, CanPlay("'application/x-mpegurl; codecs=\"mp4a.67\"'"));
+ EXPECT_EQ(kNot, CanPlay("'application/x-mpegurl; codecs=\"mp4a.68\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
+ EXPECT_EQ(kHlsProbably,
+ CanPlay("'application/x-mpegurl; codecs=\"mp4a.69\"'"));
+ EXPECT_EQ(kHlsProbably,
+ CanPlay("'application/x-mpegurl; codecs=\"mp4a.6B\"'"));
+
+ EXPECT_EQ(kHlsProbably,
CanPlay("'application/x-mpegurl; codecs=\"mp4a.40.2\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
+ EXPECT_EQ(kHlsProbably,
CanPlay("'application/x-mpegurl; codecs=\"mp4a.40.02\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
+ EXPECT_EQ(
+ kHlsProbably,
CanPlay("'application/x-mpegurl; codecs=\"avc1.42E01E, mp4a.40.2\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
+ EXPECT_EQ(
+ kHlsProbably,
CanPlay("'application/x-mpegurl; codecs=\"avc1.42E01E, mp4a.40.02\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
+ EXPECT_EQ(
+ kHlsProbably,
CanPlay("'application/x-mpegurl; codecs=\"avc3.42E01E, mp4a.40.5\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
+ EXPECT_EQ(
+ kHlsProbably,
CanPlay("'application/x-mpegurl; codecs=\"avc3.42E01E, mp4a.40.05\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
+ EXPECT_EQ(
+ kHlsProbably,
CanPlay("'application/x-mpegurl; codecs=\"avc3.42E01E, mp4a.40.29\"'"));
EXPECT_EQ(kNot,
@@ -1222,77 +1344,98 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_HLS) {
EXPECT_EQ(kNot, CanPlay("'application/x-mpegurl; codecs=\"mp4a.a5\"'"));
EXPECT_EQ(kNot, CanPlay("'application/x-mpegurl; codecs=\"mp4a.a6\"'"));
- EXPECT_EQ(maybeCanPlayHLS,
+ EXPECT_EQ(kHlsMaybe,
CanPlay("'application/x-mpegurl; codecs=\"avc1, mp4a.40.2\"'"));
- EXPECT_EQ(maybeCanPlayHLS,
+ EXPECT_EQ(kHlsMaybe,
CanPlay("'application/x-mpegurl; codecs=\"avc1, mp4a.40.02\"'"));
- EXPECT_EQ(maybeCanPlayHLS,
+ EXPECT_EQ(kHlsMaybe,
CanPlay("'application/x-mpegurl; codecs=\"avc3, mp4a.40.2\"'"));
- EXPECT_EQ(maybeCanPlayHLS,
+ EXPECT_EQ(kHlsMaybe,
CanPlay("'application/x-mpegurl; codecs=\"avc3, mp4a.40.02\"'"));
- EXPECT_EQ(maybeCanPlayHLS,
+ EXPECT_EQ(
+ kHlsMaybe,
CanPlay("'application/x-mpegurl; codecs=\"avc1.42E01E, mp4a.40\"'"));
- EXPECT_EQ(maybeCanPlayHLS,
+ EXPECT_EQ(
+ kHlsMaybe,
CanPlay("'application/x-mpegurl; codecs=\"avc3.42E01E, mp4a.40\"'"));
TestMPEGUnacceptableCombinations("application/x-mpegurl");
+ // This result is incorrect. See https://crbug.com/592889.
+ EXPECT_EQ(kHlsProbably, CanPlay("'application/x-mpegurl; codecs=\"mp3\"'"));
- EXPECT_EQ(maybeCanPlayHLS, CanPlay("'application/vnd.apple.mpegurl'"));
+ EXPECT_EQ(kHlsMaybe, CanPlay("'application/vnd.apple.mpegurl'"));
- EXPECT_EQ(maybeCanPlayHLS,
+ EXPECT_EQ(kHlsMaybe,
CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1\"'"));
- EXPECT_EQ(maybeCanPlayHLS,
+ EXPECT_EQ(kHlsMaybe,
CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3\"'"));
- EXPECT_EQ(maybeCanPlayHLS,
+ EXPECT_EQ(kHlsMaybe,
CanPlay("'application/vnd.apple.mpegurl; codecs=\"mp4a.40\"'"));
- EXPECT_EQ(maybeCanPlayHLS,
+ EXPECT_EQ(
+ kHlsMaybe,
CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1, mp4a.40\"'"));
- EXPECT_EQ(maybeCanPlayHLS,
+ EXPECT_EQ(
+ kHlsMaybe,
CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3, mp4a.40\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
+ EXPECT_EQ(kHlsProbably,
CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1.42E01E\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
+ EXPECT_EQ(kHlsProbably,
+ CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1.42101E\"'"));
+ EXPECT_EQ(kHlsProbably,
+ CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1.42701E\"'"));
+ EXPECT_EQ(kHlsProbably,
+ CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1.42F01E\"'"));
+
+ EXPECT_EQ(kHlsProbably,
CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3.42E01E\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
+ EXPECT_EQ(kHlsProbably,
CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3.42801E\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
+ EXPECT_EQ(kHlsProbably,
CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3.42C01E\"'"));
- EXPECT_EQ(maybeCanPlayHLS,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1.42E11E\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1.42101E\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1.42701E\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
- CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1.42F01E\"'"));
+ // Android, is the only platform that supports these types, and its HLS
+ // implementations uses platform codecs, which do not include MPEG-2 AAC.
+ // See https://crbug.com/544268.
+ EXPECT_EQ(kNot,
+ CanPlay("'application/vnd.apple.mpegurl; codecs=\"mp4a.66\"'"));
+ EXPECT_EQ(kNot,
+ CanPlay("'application/vnd.apple.mpegurl; codecs=\"mp4a.67\"'"));
+ EXPECT_EQ(kNot,
+ CanPlay("'application/vnd.apple.mpegurl; codecs=\"mp4a.68\"'"));
+
+ EXPECT_EQ(kHlsProbably,
+ CanPlay("'application/vnd.apple.mpegurl; codecs=\"mp4a.69\"'"));
+ EXPECT_EQ(kHlsProbably,
+ CanPlay("'application/vnd.apple.mpegurl; codecs=\"mp4a.6B\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
+ EXPECT_EQ(kHlsProbably,
CanPlay("'application/vnd.apple.mpegurl; codecs=\"mp4a.40.2\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
+ EXPECT_EQ(kHlsProbably,
CanPlay("'application/vnd.apple.mpegurl; codecs=\"mp4a.40.02\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
+ EXPECT_EQ(kHlsProbably,
CanPlay("'application/vnd.apple.mpegurl; codecs=\"mp4a.40.5\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
+ EXPECT_EQ(kHlsProbably,
CanPlay("'application/vnd.apple.mpegurl; codecs=\"mp4a.40.05\"'"));
- EXPECT_EQ(probablyCanPlayHLS,
+ EXPECT_EQ(kHlsProbably,
CanPlay("'application/vnd.apple.mpegurl; codecs=\"mp4a.40.29\"'"));
- EXPECT_EQ(maybeCanPlayHLS,
+ EXPECT_EQ(
+ kHlsMaybe,
CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1, mp4a.40.2\"'"));
- EXPECT_EQ(maybeCanPlayHLS,
+ EXPECT_EQ(
+ kHlsMaybe,
CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc1, mp4a.40.02\"'"));
- EXPECT_EQ(maybeCanPlayHLS,
+ EXPECT_EQ(
+ kHlsMaybe,
CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3, mp4a.40.2\"'"));
- EXPECT_EQ(maybeCanPlayHLS,
+ EXPECT_EQ(
+ kHlsMaybe,
CanPlay("'application/vnd.apple.mpegurl; codecs=\"avc3, mp4a.40.02\"'"));
- EXPECT_EQ(maybeCanPlayHLS,
- CanPlay("'application/vnd.apple.mpegurl; "
- "codecs=\"avc1.42E01E, mp4a.40\"'"));
- EXPECT_EQ(maybeCanPlayHLS,
- CanPlay("'application/vnd.apple.mpegurl; "
- "codecs=\"avc3.42E01E, mp4a.40\"'"));
+ EXPECT_EQ(kHlsMaybe, CanPlay("'application/vnd.apple.mpegurl; "
+ "codecs=\"avc1.42E01E, mp4a.40\"'"));
+ EXPECT_EQ(kHlsMaybe, CanPlay("'application/vnd.apple.mpegurl; "
+ "codecs=\"avc3.42E01E, mp4a.40\"'"));
EXPECT_EQ(kNot,
CanPlay("'application/vnd.apple.mpegurl; codecs=\"hev1.1.6.L93.B0\"'"));
@@ -1317,6 +1460,9 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_HLS) {
CanPlay("'application/vnd.apple.mpegurl; codecs=\"mp4a.a6\"'"));
TestMPEGUnacceptableCombinations("application/vnd.apple.mpegurl");
+ // This result is incorrect. See https://crbug.com/592889.
+ EXPECT_EQ(kHlsProbably,
+ CanPlay("'application/vnd.apple.mpegurl; codecs=\"mp3\"'"));
}
IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_AAC_ADTS) {
@@ -1336,6 +1482,13 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_Mpeg2Ts) {
EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.42E01E\"'"));
EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.4D401E\"'"));
EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"avc1.640028\"'"));
+
+ EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"mp4a.66\"'"));
+ EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"mp4a.67\"'"));
+ EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"mp4a.68\"'"));
+ EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"mp4a.69\"'"));
+ EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"mp4a.6B\"'"));
+
// AAC LC audio
EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"mp4a.40.2\"'"));
// H.264 + AAC audio combinations
@@ -1360,6 +1513,8 @@ IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest, CodecSupportTest_Mpeg2Ts) {
CanPlay("'video/mp2t; codecs=\"avc1.640028,mp4a.a6\"'"));
TestMPEGUnacceptableCombinations("video/mp2t");
+ // This result is incorrect. See https://crbug.com/592889.
+ EXPECT_EQ(kMp2tsProbably, CanPlay("'video/mp2t; codecs=\"mp3\"'"));
}
IN_PROC_BROWSER_TEST_F(MediaCanPlayTypeTest,
diff --git a/chromium/content/browser/media/media_internals.cc b/chromium/content/browser/media/media_internals.cc
index c6455766ce2..02e40ce350a 100644
--- a/chromium/content/browser/media/media_internals.cc
+++ b/chromium/content/browser/media/media_internals.cc
@@ -123,10 +123,11 @@ class AudioLogImpl : public media::AudioLog {
void StoreComponentMetadata(int component_id, base::DictionaryValue* dict);
std::string FormatCacheKey(int component_id);
- static void SendWebContentsTitleHelper(const std::string& cache_key,
- scoped_ptr<base::DictionaryValue> dict,
- int render_process_id,
- int render_frame_id);
+ static void SendWebContentsTitleHelper(
+ const std::string& cache_key,
+ std::unique_ptr<base::DictionaryValue> dict,
+ int render_process_id,
+ int render_frame_id);
const int owner_id_;
const media::AudioLogFactory::AudioComponent component_;
@@ -208,7 +209,7 @@ void AudioLogImpl::OnSwitchOutputDevice(int component_id,
void AudioLogImpl::SendWebContentsTitle(int component_id,
int render_process_id,
int render_frame_id) {
- scoped_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
StoreComponentMetadata(component_id, dict.get());
SendWebContentsTitleHelper(FormatCacheKey(component_id), std::move(dict),
render_process_id, render_frame_id);
@@ -221,7 +222,7 @@ std::string AudioLogImpl::FormatCacheKey(int component_id) {
// static
void AudioLogImpl::SendWebContentsTitleHelper(
const std::string& cache_key,
- scoped_ptr<base::DictionaryValue> dict,
+ std::unique_ptr<base::DictionaryValue> dict,
int render_process_id,
int render_frame_id) {
// Page title information can only be retrieved from the UI thread.
@@ -281,20 +282,15 @@ class MediaInternals::MediaInternalsUMAHandler {
private:
struct PipelineInfo {
- media::PipelineStatus last_pipeline_status;
- bool has_audio;
- bool has_video;
- bool video_dds;
- bool video_decoder_changed;
+ bool has_pipeline = false;
+ media::PipelineStatus last_pipeline_status = media::PIPELINE_OK;
+ bool has_audio = false;
+ bool has_video = false;
+ bool video_dds = false;
+ bool video_decoder_changed = false;
std::string audio_codec_name;
std::string video_codec_name;
std::string video_decoder;
- PipelineInfo()
- : last_pipeline_status(media::PIPELINE_OK),
- has_audio(false),
- has_video(false),
- video_dds(false),
- video_decoder_changed(false) {}
};
// Helper function to report PipelineStatus associated with a player to UMA.
@@ -324,6 +320,10 @@ void MediaInternals::MediaInternalsUMAHandler::SavePlayerState(
DCHECK_CURRENTLY_ON(BrowserThread::UI);
PlayerInfoMap& player_info = renderer_info_[render_process_id];
switch (event.type) {
+ case media::MediaLogEvent::PIPELINE_STATE_CHANGED: {
+ player_info[event.id].has_pipeline = true;
+ break;
+ }
case media::MediaLogEvent::PIPELINE_ERROR: {
int status;
event.params.GetInteger("pipeline_error", &status);
@@ -404,6 +404,12 @@ std::string MediaInternals::MediaInternalsUMAHandler::GetUMANameForAVStream(
void MediaInternals::MediaInternalsUMAHandler::ReportUMAForPipelineStatus(
const PipelineInfo& player_info) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ // Don't log pipeline status for players which don't actually have a pipeline;
+ // e.g., the Android MediaSourcePlayer implementation.
+ if (!player_info.has_pipeline)
+ return;
+
if (player_info.has_video && player_info.has_audio) {
base::LinearHistogram::FactoryGet(
GetUMANameForAVStream(player_info), 1, media::PIPELINE_STATUS_MAX,
@@ -419,6 +425,9 @@ void MediaInternals::MediaInternalsUMAHandler::ReportUMAForPipelineStatus(
player_info.last_pipeline_status,
media::PIPELINE_STATUS_MAX + 1);
} else {
+ // Note: This metric can be recorded as a result of normal operation with
+ // Media Source Extensions. If a site creates a MediaSource object but never
+ // creates a source buffer or appends data, PIPELINE_OK will be recorded.
UMA_HISTOGRAM_ENUMERATION("Media.PipelineStatus.Unsupported",
player_info.last_pipeline_status,
media::PIPELINE_STATUS_MAX + 1);
@@ -612,11 +621,11 @@ void MediaInternals::UpdateVideoCaptureDeviceCapabilities(
SendVideoCaptureDeviceCapabilities();
}
-scoped_ptr<media::AudioLog> MediaInternals::CreateAudioLog(
+std::unique_ptr<media::AudioLog> MediaInternals::CreateAudioLog(
AudioComponent component) {
base::AutoLock auto_lock(lock_);
- return scoped_ptr<media::AudioLog>(new AudioLogImpl(
- owner_ids_[component]++, component, this));
+ return std::unique_ptr<media::AudioLog>(
+ new AudioLogImpl(owner_ids_[component]++, component, this));
}
void MediaInternals::SetWebContentsTitleForAudioLogEntry(
@@ -675,7 +684,7 @@ void MediaInternals::UpdateAudioLog(AudioLogUpdateType type,
DCHECK_EQ(type, CREATE);
audio_streams_cached_data_.Set(cache_key, value->DeepCopy());
} else if (type == UPDATE_AND_DELETE) {
- scoped_ptr<base::Value> out_value;
+ std::unique_ptr<base::Value> out_value;
CHECK(audio_streams_cached_data_.Remove(cache_key, &out_value));
} else {
base::DictionaryValue* existing_dict = NULL;
diff --git a/chromium/content/browser/media/media_internals.h b/chromium/content/browser/media/media_internals.h
index e4869281ed5..7203b2fc9ac 100644
--- a/chromium/content/browser/media/media_internals.h
+++ b/chromium/content/browser/media/media_internals.h
@@ -76,7 +76,8 @@ class CONTENT_EXPORT MediaInternals
const media::VideoCaptureDeviceInfos& video_capture_device_infos);
// AudioLogFactory implementation. Safe to call from any thread.
- scoped_ptr<media::AudioLog> CreateAudioLog(AudioComponent component) override;
+ std::unique_ptr<media::AudioLog> CreateAudioLog(
+ AudioComponent component) override;
// If possible, i.e. a WebContents exists for the given RenderFrameHostID,
// tells an existing AudioLogEntry the WebContents title for easier
@@ -137,7 +138,7 @@ class CONTENT_EXPORT MediaInternals
bool can_update_;
base::DictionaryValue audio_streams_cached_data_;
int owner_ids_[AUDIO_COMPONENT_MAX];
- scoped_ptr<MediaInternalsUMAHandler> uma_handler_;
+ std::unique_ptr<MediaInternalsUMAHandler> uma_handler_;
DISALLOW_COPY_AND_ASSIGN(MediaInternals);
};
diff --git a/chromium/content/browser/media/media_internals_proxy.cc b/chromium/content/browser/media/media_internals_proxy.cc
index 0ff34cf51af..a8ef88271bf 100644
--- a/chromium/content/browser/media/media_internals_proxy.cc
+++ b/chromium/content/browser/media/media_internals_proxy.cc
@@ -178,7 +178,7 @@ void MediaInternalsProxy::SendNetEventsOnUIThread() {
void MediaInternalsProxy::CallJavaScriptFunctionOnUIThread(
const std::string& function, base::Value* args) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- scoped_ptr<base::Value> args_value(args);
+ std::unique_ptr<base::Value> args_value(args);
std::vector<const base::Value*> args_vector;
args_vector.push_back(args_value.get());
base::string16 update = WebUI::GetJavascriptCall(function, args_vector);
diff --git a/chromium/content/browser/media/media_internals_proxy.h b/chromium/content/browser/media/media_internals_proxy.h
index 5eb9294f14f..84b4a1b1aad 100644
--- a/chromium/content/browser/media/media_internals_proxy.h
+++ b/chromium/content/browser/media/media_internals_proxy.h
@@ -78,7 +78,7 @@ class MediaInternalsProxy
base::Value* args);
MediaInternalsMessageHandler* handler_;
- scoped_ptr<base::ListValue> pending_net_updates_;
+ std::unique_ptr<base::ListValue> pending_net_updates_;
NotificationRegistrar registrar_;
MediaInternals::UpdateCallback update_callback_;
diff --git a/chromium/content/browser/media/media_internals_unittest.cc b/chromium/content/browser/media/media_internals_unittest.cc
index 2ab0539fdb2..808ae856537 100644
--- a/chromium/content/browser/media/media_internals_unittest.cc
+++ b/chromium/content/browser/media/media_internals_unittest.cc
@@ -44,7 +44,7 @@ class MediaInternalsTestBase {
std::string utf8_update = base::UTF16ToUTF8(update);
const std::string::size_type first_brace = utf8_update.find('{');
const std::string::size_type last_brace = utf8_update.rfind('}');
- scoped_ptr<base::Value> output_value = base::JSONReader::Read(
+ std::unique_ptr<base::Value> output_value = base::JSONReader::Read(
utf8_update.substr(first_brace, last_brace - first_brace + 1));
CHECK(output_value);
@@ -122,13 +122,11 @@ TEST_F(MediaInternalsVideoCaptureDeviceTest,
CaptureApiTypeStringMap m;
#if defined(OS_LINUX)
m[VideoCaptureDeviceName::V4L2_SINGLE_PLANE] = "V4L2 SPLANE";
- m[VideoCaptureDeviceName::V4L2_MULTI_PLANE] = "V4L2 MPLANE";
#elif defined(OS_WIN)
m[VideoCaptureDeviceName::MEDIA_FOUNDATION] = "Media Foundation";
m[VideoCaptureDeviceName::DIRECT_SHOW] = "Direct Show";
#elif defined(OS_MACOSX)
m[VideoCaptureDeviceName::AVFOUNDATION] = "AV Foundation";
- m[VideoCaptureDeviceName::QTKIT] = "QTKit";
m[VideoCaptureDeviceName::DECKLINK] = "DeckLink";
#elif defined(OS_ANDROID)
m[VideoCaptureDeviceName::API1] = "Camera API1";
@@ -181,8 +179,8 @@ TEST_F(MediaInternalsVideoCaptureDeviceTest,
formats.push_back(format_hd);
const media::VideoCaptureDeviceInfo device_info(
#if defined(OS_MACOSX)
- media::VideoCaptureDevice::Name("dummy", "dummy",
- media::VideoCaptureDevice::Name::QTKIT),
+ media::VideoCaptureDevice::Name(
+ "dummy", "dummy", media::VideoCaptureDevice::Name::AVFOUNDATION),
#elif defined(OS_WIN)
media::VideoCaptureDevice::Name("dummy", "dummy",
media::VideoCaptureDevice::Name::DIRECT_SHOW),
@@ -220,7 +218,7 @@ TEST_F(MediaInternalsVideoCaptureDeviceTest,
#elif defined(OS_WIN)
ExpectString("captureApi", "Direct Show");
#elif defined(OS_MACOSX)
- ExpectString("captureApi", "QTKit");
+ ExpectString("captureApi", "AV Foundation");
#elif defined(OS_ANDROID)
ExpectString("captureApi", "Camera API2 Legacy");
#endif
@@ -247,7 +245,7 @@ class MediaInternalsAudioLogTest
MediaInternals::UpdateCallback update_cb_;
const media::AudioParameters test_params_;
const media::AudioLogFactory::AudioComponent test_component_;
- scoped_ptr<media::AudioLog> audio_log_;
+ std::unique_ptr<media::AudioLog> audio_log_;
private:
static media::AudioParameters MakeAudioParams() {
diff --git a/chromium/content/browser/media/media_web_contents_observer.cc b/chromium/content/browser/media/media_web_contents_observer.cc
index 67ef0368680..c301e2e345a 100644
--- a/chromium/content/browser/media/media_web_contents_observer.cc
+++ b/chromium/content/browser/media/media_web_contents_observer.cc
@@ -4,14 +4,15 @@
#include "content/browser/media/media_web_contents_observer.h"
+#include <memory>
+
#include "base/lazy_instance.h"
-#include "base/memory/scoped_ptr.h"
#include "build/build_config.h"
#include "content/browser/media/audible_metrics.h"
#include "content/browser/media/audio_stream_monitor.h"
#include "content/browser/power_save_blocker_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
-#include "content/common/frame_messages.h"
+#include "content/common/media/media_player_delegate_messages.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "ipc/ipc_message_macros.h"
@@ -26,7 +27,8 @@ static base::LazyInstance<AudibleMetrics>::Leaky g_audible_metrics =
} // anonymous namespace
MediaWebContentsObserver::MediaWebContentsObserver(WebContents* web_contents)
- : WebContentsObserver(web_contents) {}
+ : WebContentsObserver(web_contents),
+ session_controllers_manager_(this) {}
MediaWebContentsObserver::~MediaWebContentsObserver() {}
@@ -37,6 +39,7 @@ void MediaWebContentsObserver::WebContentsDestroyed() {
void MediaWebContentsObserver::RenderFrameDeleted(
RenderFrameHost* render_frame_host) {
ClearPowerSaveBlockers(render_frame_host);
+ session_controllers_manager_.RenderFrameDeleted(render_frame_host);
}
void MediaWebContentsObserver::MaybeUpdateAudibleState() {
@@ -64,28 +67,71 @@ bool MediaWebContentsObserver::OnMessageReceived(
// TODO(dalecurtis): These should no longer be FrameHostMsg.
IPC_BEGIN_MESSAGE_MAP_WITH_PARAM(MediaWebContentsObserver, msg,
render_frame_host)
- IPC_MESSAGE_HANDLER(FrameHostMsg_MediaPlayingNotification,
- OnMediaPlayingNotification)
- IPC_MESSAGE_HANDLER(FrameHostMsg_MediaPausedNotification,
- OnMediaPausedNotification)
+ IPC_MESSAGE_HANDLER(MediaPlayerDelegateHostMsg_OnMediaDestroyed,
+ OnMediaDestroyed)
+ IPC_MESSAGE_HANDLER(MediaPlayerDelegateHostMsg_OnMediaPaused, OnMediaPaused)
+ IPC_MESSAGE_HANDLER(MediaPlayerDelegateHostMsg_OnMediaPlaying,
+ OnMediaPlaying)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
-void MediaWebContentsObserver::OnMediaPlayingNotification(
+void MediaWebContentsObserver::WasShown() {
+ // Restore power save blocker if there are active video players running.
+ if (!active_video_players_.empty() && !video_power_save_blocker_)
+ CreateVideoPowerSaveBlocker();
+}
+
+void MediaWebContentsObserver::WasHidden() {
+ // If there are entities capturing screenshots or video (e.g., mirroring),
+ // don't release the power save blocker.
+ if (!web_contents()->GetCapturerCount())
+ video_power_save_blocker_.reset();
+}
+
+void MediaWebContentsObserver::OnMediaDestroyed(
+ RenderFrameHost* render_frame_host,
+ int delegate_id) {
+ OnMediaPaused(render_frame_host, delegate_id, true);
+}
+
+void MediaWebContentsObserver::OnMediaPaused(RenderFrameHost* render_frame_host,
+ int delegate_id,
+ bool reached_end_of_stream) {
+ const MediaPlayerId player_id(render_frame_host, delegate_id);
+ const bool removed_audio =
+ RemoveMediaPlayerEntry(player_id, &active_audio_players_);
+ const bool removed_video =
+ RemoveMediaPlayerEntry(player_id, &active_video_players_);
+ MaybeReleasePowerSaveBlockers();
+
+ if (removed_audio || removed_video) {
+ // Notify observers the player has been "paused".
+ static_cast<WebContentsImpl*>(web_contents())
+ ->MediaStoppedPlaying(player_id);
+ }
+
+ if (reached_end_of_stream)
+ session_controllers_manager_.OnEnd(player_id);
+ else
+ session_controllers_manager_.OnPause(player_id);
+}
+
+void MediaWebContentsObserver::OnMediaPlaying(
RenderFrameHost* render_frame_host,
- int64_t player_cookie,
+ int delegate_id,
bool has_video,
bool has_audio,
- bool is_remote) {
+ bool is_remote,
+ base::TimeDelta duration) {
// Ignore the videos playing remotely and don't hold the wake lock for the
// screen. TODO(dalecurtis): Is this correct? It means observers will not
// receive play and pause messages.
if (is_remote)
return;
- const MediaPlayerId id(render_frame_host, player_cookie);
+ const MediaPlayerId id(render_frame_host, delegate_id);
if (has_audio) {
AddMediaPlayerEntry(id, &active_audio_players_);
@@ -107,25 +153,16 @@ void MediaWebContentsObserver::OnMediaPlayingNotification(
}
}
+ if (!session_controllers_manager_.RequestPlay(
+ id, has_audio, is_remote, duration)) {
+ return;
+ }
+
// Notify observers of the new player.
DCHECK(has_audio || has_video);
static_cast<WebContentsImpl*>(web_contents())->MediaStartedPlaying(id);
}
-void MediaWebContentsObserver::OnMediaPausedNotification(
- RenderFrameHost* render_frame_host,
- int64_t player_cookie) {
- const MediaPlayerId id(render_frame_host, player_cookie);
- const bool removed_audio = RemoveMediaPlayerEntry(id, &active_audio_players_);
- const bool removed_video = RemoveMediaPlayerEntry(id, &active_video_players_);
- MaybeReleasePowerSaveBlockers();
-
- if (removed_audio || removed_video) {
- // Notify observers the player has been "paused".
- static_cast<WebContentsImpl*>(web_contents())->MediaStoppedPlaying(id);
- }
-}
-
void MediaWebContentsObserver::ClearPowerSaveBlockers(
RenderFrameHost* render_frame_host) {
std::set<MediaPlayerId> removed_players;
@@ -154,26 +191,12 @@ void MediaWebContentsObserver::CreateVideoPowerSaveBlocker() {
video_power_save_blocker_ = PowerSaveBlocker::Create(
PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
PowerSaveBlocker::kReasonVideoPlayback, "Playing video");
-// TODO(mfomitchev): Support PowerSaveBlocker on Aura - crbug.com/546718.
-#if defined(OS_ANDROID) && !defined(USE_AURA)
+#if defined(OS_ANDROID)
static_cast<PowerSaveBlockerImpl*>(video_power_save_blocker_.get())
->InitDisplaySleepBlocker(web_contents());
#endif
}
-void MediaWebContentsObserver::WasShown() {
- // Restore power save blocker if there are active video players running.
- if (!active_video_players_.empty() && !video_power_save_blocker_)
- CreateVideoPowerSaveBlocker();
-}
-
-void MediaWebContentsObserver::WasHidden() {
- // If there are entities capturing screenshots or video (e.g., mirroring),
- // don't release the power save blocker.
- if (!web_contents()->GetCapturerCount())
- video_power_save_blocker_.reset();
-}
-
void MediaWebContentsObserver::MaybeReleasePowerSaveBlockers() {
// If there are no more audio players and we don't have audio stream
// monitoring, release the audio power save blocker here instead of during
@@ -191,10 +214,7 @@ void MediaWebContentsObserver::MaybeReleasePowerSaveBlockers() {
void MediaWebContentsObserver::AddMediaPlayerEntry(
const MediaPlayerId& id,
ActiveMediaPlayerMap* player_map) {
- DCHECK(std::find((*player_map)[id.first].begin(),
- (*player_map)[id.first].end(),
- id.second) == (*player_map)[id.first].end());
- (*player_map)[id.first].push_back(id.second);
+ (*player_map)[id.first].insert(id.second);
}
bool MediaWebContentsObserver::RemoveMediaPlayerEntry(
@@ -205,11 +225,9 @@ bool MediaWebContentsObserver::RemoveMediaPlayerEntry(
return false;
// Remove the player.
- auto player_for_removal =
- std::remove(it->second.begin(), it->second.end(), id.second);
- if (player_for_removal == it->second.end())
+ bool did_remove = it->second.erase(id.second) == 1;
+ if (!did_remove)
return false;
- it->second.erase(player_for_removal);
// If there are no players left, remove the map entry.
if (it->second.empty())
@@ -226,8 +244,8 @@ void MediaWebContentsObserver::RemoveAllMediaPlayerEntries(
if (it == player_map->end())
return;
- for (int64_t player_cookie : it->second)
- removed_players->insert(MediaPlayerId(render_frame_host, player_cookie));
+ for (int delegate_id : it->second)
+ removed_players->insert(MediaPlayerId(render_frame_host, delegate_id));
player_map->erase(it);
}
diff --git a/chromium/content/browser/media/media_web_contents_observer.h b/chromium/content/browser/media/media_web_contents_observer.h
index 1f76029cf4e..072ef4239fe 100644
--- a/chromium/content/browser/media/media_web_contents_observer.h
+++ b/chromium/content/browser/media/media_web_contents_observer.h
@@ -8,15 +8,16 @@
#include <stdint.h>
#include <map>
+#include <memory>
#include <set>
-#include <vector>
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
+#include "content/browser/media/session/media_session_controllers_manager.h"
#include "content/common/content_export.h"
#include "content/public/browser/web_contents_observer.h"
namespace content {
+
class PowerSaveBlocker;
// This class manages all RenderFrame based media related managers at the
@@ -40,21 +41,29 @@ class CONTENT_EXPORT MediaWebContentsObserver : public WebContentsObserver {
void WasHidden() override;
bool has_audio_power_save_blocker_for_testing() const {
- return audio_power_save_blocker_;
+ return !!audio_power_save_blocker_;
}
bool has_video_power_save_blocker_for_testing() const {
- return video_power_save_blocker_;
+ return !!video_power_save_blocker_;
+ }
+
+ protected:
+ MediaSessionControllersManager* session_controllers_manager() {
+ return &session_controllers_manager_;
}
private:
- void OnMediaPlayingNotification(RenderFrameHost* render_frame_host,
- int64_t player_cookie,
- bool has_video,
- bool has_audio,
- bool is_remote);
- void OnMediaPausedNotification(RenderFrameHost* render_frame_host,
- int64_t player_cookie);
+ void OnMediaDestroyed(RenderFrameHost* render_frame_host, int delegate_id);
+ void OnMediaPaused(RenderFrameHost* render_frame_host,
+ int delegate_id,
+ bool reached_end_of_stream);
+ void OnMediaPlaying(RenderFrameHost* render_frame_host,
+ int delegate_id,
+ bool has_video,
+ bool has_audio,
+ bool is_remote,
+ base::TimeDelta duration);
// Clear |render_frame_host|'s tracking entry for its power save blockers.
void ClearPowerSaveBlockers(RenderFrameHost* render_frame_host);
@@ -69,8 +78,8 @@ class CONTENT_EXPORT MediaWebContentsObserver : public WebContentsObserver {
void MaybeReleasePowerSaveBlockers();
// Helper methods for adding or removing player entries in |player_map|.
- using PlayerList = std::vector<int64_t>;
- using ActiveMediaPlayerMap = std::map<RenderFrameHost*, PlayerList>;
+ using PlayerSet = std::set<int>;
+ using ActiveMediaPlayerMap = std::map<RenderFrameHost*, PlayerSet>;
void AddMediaPlayerEntry(const MediaPlayerId& id,
ActiveMediaPlayerMap* player_map);
// Returns true if an entry is actually removed.
@@ -85,8 +94,10 @@ class CONTENT_EXPORT MediaWebContentsObserver : public WebContentsObserver {
// Tracking variables and associated power save blockers for media playback.
ActiveMediaPlayerMap active_audio_players_;
ActiveMediaPlayerMap active_video_players_;
- scoped_ptr<PowerSaveBlocker> audio_power_save_blocker_;
- scoped_ptr<PowerSaveBlocker> video_power_save_blocker_;
+ std::unique_ptr<PowerSaveBlocker> audio_power_save_blocker_;
+ std::unique_ptr<PowerSaveBlocker> video_power_save_blocker_;
+
+ MediaSessionControllersManager session_controllers_manager_;
DISALLOW_COPY_AND_ASSIGN(MediaWebContentsObserver);
};
diff --git a/chromium/content/browser/media/midi_host.cc b/chromium/content/browser/media/midi_host.cc
index 30261ef7f35..17dccccfea5 100644
--- a/chromium/content/browser/media/midi_host.cc
+++ b/chromium/content/browser/media/midi_host.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/metrics/histogram_macros.h"
#include "base/process/process.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/bad_message.h"
@@ -234,6 +235,7 @@ void MidiHost::Detach() {
// static
bool MidiHost::IsValidWebMIDIData(const std::vector<uint8_t>& data) {
bool in_sysex = false;
+ size_t sysex_start_offset = 0;
size_t waiting_data_length = 0;
for (size_t i = 0; i < data.size(); ++i) {
const uint8_t current = data[i];
@@ -246,14 +248,18 @@ bool MidiHost::IsValidWebMIDIData(const std::vector<uint8_t>& data) {
continue; // Found data byte as expected.
}
if (in_sysex) {
- if (data[i] == kEndOfSysExByte)
+ if (data[i] == kEndOfSysExByte) {
in_sysex = false;
- else if (!IsDataByte(current))
+ UMA_HISTOGRAM_COUNTS("Media.Midi.SysExMessageSizeUpTo1MB",
+ i - sysex_start_offset + 1);
+ } else if (!IsDataByte(current)) {
return false; // Error: |current| should have been data byte.
+ }
continue; // Found data byte as expected.
}
if (current == kSysExByte) {
in_sysex = true;
+ sysex_start_offset = i;
continue; // Found SysEX
}
waiting_data_length = media::midi::GetMidiMessageLength(current);
diff --git a/chromium/content/browser/media/midi_host.h b/chromium/content/browser/media/midi_host.h
index ca3706cbcda..fc126acd357 100644
--- a/chromium/content/browser/media/midi_host.h
+++ b/chromium/content/browser/media/midi_host.h
@@ -8,12 +8,12 @@
#include <stddef.h>
#include <stdint.h>
+#include <memory>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/synchronization/lock.h"
#include "content/common/content_export.h"
diff --git a/chromium/content/browser/media/midi_host_unittest.cc b/chromium/content/browser/media/midi_host_unittest.cc
index 655414e858e..21306af09a1 100644
--- a/chromium/content/browser/media/midi_host_unittest.cc
+++ b/chromium/content/browser/media/midi_host_unittest.cc
@@ -126,7 +126,7 @@ class MidiHostTest : public testing::Test {
}
void OnSendData(uint32_t port) {
- scoped_ptr<IPC::Message> message(
+ std::unique_ptr<IPC::Message> message(
new MidiHostMsg_SendData(port, data_, 0.0));
host_->OnMessageReceived(*message.get());
}
diff --git a/chromium/content/browser/media/session/OWNERS b/chromium/content/browser/media/session/OWNERS
new file mode 100644
index 00000000000..dc2593f577e
--- /dev/null
+++ b/chromium/content/browser/media/session/OWNERS
@@ -0,0 +1,2 @@
+avayvod@chromium.org
+mlamouri@chromium.org
diff --git a/chromium/content/browser/media/android/media_session.cc b/chromium/content/browser/media/session/media_session.cc
index d6061541e88..5c63545c3c4 100644
--- a/chromium/content/browser/media/android/media_session.cc
+++ b/chromium/content/browser/media/session/media_session.cc
@@ -2,18 +2,22 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/media/android/media_session.h"
+#include "content/browser/media/session/media_session.h"
-#include "base/android/context_utils.h"
-#include "base/android/jni_android.h"
-#include "content/browser/media/android/media_session_observer.h"
+#include "content/browser/media/session/media_session_delegate.h"
+#include "content/browser/media/session/media_session_observer.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_delegate.h"
-#include "jni/MediaSession_jni.h"
namespace content {
+namespace {
+
+const double kDefaultVolumeMultiplier = 1.0;
+
+} // anonymous namespace
+
using MediaSessionSuspendedSource =
MediaSessionUmaHelper::MediaSessionSuspendedSource;
@@ -39,11 +43,6 @@ size_t MediaSession::PlayerIdentifier::Hash::operator()(
}
// static
-bool content::MediaSession::RegisterMediaSession(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
-// static
MediaSession* MediaSession::Get(WebContents* web_contents) {
MediaSession* session = FromWebContents(web_contents);
if (!session) {
@@ -62,6 +61,8 @@ MediaSession::~MediaSession() {
bool MediaSession::AddPlayer(MediaSessionObserver* observer,
int player_id,
Type type) {
+ observer->OnSetVolumeMultiplier(player_id, volume_multiplier_);
+
// If the audio focus is already granted and is of type Content, there is
// nothing to do. If it is granted of type Transient the requested type is
// also transient, there is also nothing to do. Otherwise, the session needs
@@ -112,25 +113,9 @@ void MediaSession::RemovePlayers(MediaSessionObserver* observer) {
AbandonSystemAudioFocusIfNeeded();
}
-void MediaSession::OnSuspend(JNIEnv* env,
- const JavaParamRef<jobject>& obj,
- jboolean temporary) {
- // TODO(mlamouri): this check makes it so that if a MediaSession is paused and
- // then loses audio focus, it will still stay in the Suspended state.
- // See https://crbug.com/539998
- if (audio_focus_state_ != State::ACTIVE)
- return;
-
- OnSuspendInternal(SuspendType::SYSTEM,
- temporary ? State::SUSPENDED : State::INACTIVE);
-
-}
-
-void MediaSession::OnResume(JNIEnv* env, const JavaParamRef<jobject>& obj) {
- if (audio_focus_state_ != State::SUSPENDED)
- return;
-
- OnResumeInternal(SuspendType::SYSTEM);
+void MediaSession::RecordSessionDuck() {
+ uma_helper_.RecordSessionSuspended(
+ MediaSessionSuspendedSource::SystemTransientDuck);
}
void MediaSession::OnPlayerPaused(MediaSessionObserver* observer,
@@ -154,39 +139,65 @@ void MediaSession::OnPlayerPaused(MediaSessionObserver* observer,
OnSuspendInternal(SuspendType::CONTENT, State::SUSPENDED);
}
-void MediaSession::Resume() {
- DCHECK(IsSuspended());
-
- // Request audio focus again in case we lost it because another app started
- // playing while the playback was paused.
- State audio_focus_state = RequestSystemAudioFocus(audio_focus_type_)
- ? State::ACTIVE
- : State::INACTIVE;
- SetAudioFocusState(audio_focus_state);
-
- if (audio_focus_state_ != State::ACTIVE)
- return;
+void MediaSession::Resume(SuspendType type) {
+ DCHECK(IsReallySuspended());
+
+ // When the resume requests comes from another source than system, audio focus
+ // must be requested.
+ if (type != SuspendType::SYSTEM) {
+ // Request audio focus again in case we lost it because another app started
+ // playing while the playback was paused.
+ State audio_focus_state = RequestSystemAudioFocus(audio_focus_type_)
+ ? State::ACTIVE
+ : State::INACTIVE;
+ SetAudioFocusState(audio_focus_state);
+
+ if (audio_focus_state_ != State::ACTIVE)
+ return;
+ }
- OnResumeInternal(SuspendType::UI);
+ OnResumeInternal(type);
}
-void MediaSession::Suspend() {
+void MediaSession::Suspend(SuspendType type) {
DCHECK(!IsSuspended());
- OnSuspendInternal(SuspendType::UI, State::SUSPENDED);
+ OnSuspendInternal(type, State::SUSPENDED);
}
-void MediaSession::Stop() {
+void MediaSession::Stop(SuspendType type) {
DCHECK(audio_focus_state_ != State::INACTIVE);
+ DCHECK(type != SuspendType::CONTENT);
+
+ // TODO(mlamouri): merge the logic between UI and SYSTEM.
+ if (type == SuspendType::SYSTEM) {
+ OnSuspendInternal(type, State::INACTIVE);
+ return;
+ }
+
if (audio_focus_state_ != State::SUSPENDED)
- OnSuspendInternal(SuspendType::UI, State::SUSPENDED);
+ OnSuspendInternal(type, State::SUSPENDED);
DCHECK(audio_focus_state_ == State::SUSPENDED);
players_.clear();
AbandonSystemAudioFocusIfNeeded();
}
+void MediaSession::SetVolumeMultiplier(double volume_multiplier) {
+ volume_multiplier_ = volume_multiplier;
+ for (const auto& it : players_)
+ it.observer->OnSetVolumeMultiplier(it.player_id, volume_multiplier_);
+}
+
+bool MediaSession::IsActive() const {
+ return audio_focus_state_ == State::ACTIVE;
+}
+
+bool MediaSession::IsReallySuspended() const {
+ return audio_focus_state_ == State::SUSPENDED;
+}
+
bool MediaSession::IsSuspended() const {
// TODO(mlamouri): should be == State::SUSPENDED.
return audio_focus_state_ != State::ACTIVE;
@@ -198,8 +209,15 @@ bool MediaSession::IsControllable() const {
audio_focus_type_ == Type::Content;
}
-void MediaSession::ResetJavaRefForTest() {
- j_media_session_.Reset();
+std::unique_ptr<base::CallbackList<void(MediaSession::State)>::Subscription>
+MediaSession::RegisterMediaSessionStateChangedCallbackForTest(
+ const StateChangedCallback& cb) {
+ return media_session_state_listeners_.Add(cb);
+}
+
+void MediaSession::SetDelegateForTests(
+ std::unique_ptr<MediaSessionDelegate> delegate) {
+ delegate_ = std::move(delegate);
}
bool MediaSession::IsActiveForTest() const {
@@ -224,6 +242,9 @@ void MediaSession::OnSuspendInternal(SuspendType type, State new_state) {
// UI suspend cannot use State::INACTIVE.
DCHECK(type == SuspendType::SYSTEM || new_state == State::SUSPENDED);
+ if (audio_focus_state_ != State::ACTIVE)
+ return;
+
switch (type) {
case SuspendType::UI:
uma_helper_.RecordSessionSuspended(MediaSessionSuspendedSource::UI);
@@ -277,26 +298,16 @@ void MediaSession::OnResumeInternal(SuspendType type) {
MediaSession::MediaSession(WebContents* web_contents)
: WebContentsObserver(web_contents),
audio_focus_state_(State::INACTIVE),
- audio_focus_type_(Type::Transient) {}
+ audio_focus_type_(Type::Transient),
+ volume_multiplier_(kDefaultVolumeMultiplier) {
+}
void MediaSession::Initialize() {
- JNIEnv* env = base::android::AttachCurrentThread();
- DCHECK(env);
- j_media_session_.Reset(Java_MediaSession_createMediaSession(
- env,
- base::android::GetApplicationContext(),
- reinterpret_cast<intptr_t>(this)));
+ delegate_ = MediaSessionDelegate::Create(this);
}
bool MediaSession::RequestSystemAudioFocus(Type type) {
- // During tests, j_media_session_ might be null.
- if (j_media_session_.is_null())
- return true;
-
- JNIEnv* env = base::android::AttachCurrentThread();
- DCHECK(env);
- bool result = Java_MediaSession_requestAudioFocus(env, j_media_session_.obj(),
- type == Type::Transient);
+ bool result = delegate_->RequestAudioFocus(type);
uma_helper_.RecordRequestAudioFocusResult(result);
return result;
}
@@ -305,18 +316,14 @@ void MediaSession::AbandonSystemAudioFocusIfNeeded() {
if (audio_focus_state_ == State::INACTIVE || !players_.empty())
return;
- // During tests, j_media_session_ might be null.
- if (!j_media_session_.is_null()) {
- JNIEnv* env = base::android::AttachCurrentThread();
- DCHECK(env);
- Java_MediaSession_abandonAudioFocus(env, j_media_session_.obj());
- }
+ delegate_->AbandonAudioFocus();
SetAudioFocusState(State::INACTIVE);
UpdateWebContents();
}
void MediaSession::UpdateWebContents() {
+ media_session_state_listeners_.Notify(audio_focus_state_);
static_cast<WebContentsImpl*>(web_contents())->OnMediaSessionStateChanged();
}
diff --git a/chromium/content/browser/media/session/media_session.h b/chromium/content/browser/media/session/media_session.h
new file mode 100644
index 00000000000..3c0cf1594c3
--- /dev/null
+++ b/chromium/content/browser/media/session/media_session.h
@@ -0,0 +1,212 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_H_
+#define CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_H_
+
+#include <stddef.h>
+
+#include "base/callback_list.h"
+#include "base/id_map.h"
+#include "base/macros.h"
+#include "content/browser/media/session/media_session_uma_helper.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_contents_user_data.h"
+#include "content/public/common/media_metadata.h"
+
+class MediaSessionBrowserTest;
+
+namespace content {
+
+class MediaSessionDelegate;
+class MediaSessionObserver;
+class MediaSessionStateObserver;
+class MediaSessionVisibilityBrowserTest;
+
+// MediaSession manages the media session and audio focus for a given
+// WebContents. It is requesting the audio focus, pausing when requested by the
+// system and dropping it on demand.
+// The audio focus can be of two types: Transient or Content. A Transient audio
+// focus will allow other players to duck instead of pausing and will be
+// declared as temporary to the system. A Content audio focus will not be
+// declared as temporary and will not allow other players to duck. If a given
+// WebContents can only have one audio focus at a time, it will be Content in
+// case of Transient and Content audio focus are both requested.
+// TODO(thakis,mlamouri): MediaSession isn't CONTENT_EXPORT'd because it creates
+// complicated build issues with WebContentsUserData being a non-exported
+// template, see htttps://crbug.com/589840. As a result, the class uses
+// CONTENT_EXPORT for methods that are being used from tests. CONTENT_EXPORT
+// should be moved back to the class when the Windows build will work with it.
+class MediaSession : public WebContentsObserver,
+ protected WebContentsUserData<MediaSession> {
+ public:
+ enum class Type {
+ Content,
+ Transient
+ };
+
+ enum class SuspendType {
+ // Suspended by the system because a transient sound needs to be played.
+ SYSTEM,
+ // Suspended by the UI.
+ UI,
+ // Suspended by the page via script or user interaction.
+ CONTENT,
+ };
+
+ // Returns the MediaSession associated to this WebContents. Creates one if
+ // none is currently available.
+ CONTENT_EXPORT static MediaSession* Get(WebContents* web_contents);
+
+ ~MediaSession() override;
+
+ void setMetadata(const MediaMetadata& metadata) {
+ metadata_ = metadata;
+ }
+ const MediaMetadata& metadata() const { return metadata_; }
+
+ // Adds the given player to the current media session. Returns whether the
+ // player was successfully added. If it returns false, AddPlayer() should be
+ // called again later.
+ CONTENT_EXPORT bool AddPlayer(MediaSessionObserver* observer,
+ int player_id, Type type);
+
+ // Removes the given player from the current media session. Abandons audio
+ // focus if that was the last player in the session.
+ CONTENT_EXPORT void RemovePlayer(MediaSessionObserver* observer,
+ int player_id);
+
+ // Removes all the players associated with |observer|. Abandons audio focus if
+ // these were the last players in the session.
+ CONTENT_EXPORT void RemovePlayers(MediaSessionObserver* observer);
+
+ // Record that the session was ducked.
+ void RecordSessionDuck();
+
+ // Called when a player is paused in the content.
+ // If the paused player is the last player, we suspend the MediaSession.
+ // Otherwise, the paused player will be removed from the MediaSession.
+ CONTENT_EXPORT void OnPlayerPaused(MediaSessionObserver* observer,
+ int player_id);
+
+ // Resume the media session.
+ // |type| represents the origin of the request.
+ CONTENT_EXPORT void Resume(SuspendType type);
+
+ // Suspend the media session.
+ // |type| represents the origin of the request.
+ CONTENT_EXPORT void Suspend(SuspendType type);
+
+ // Stop the media session.
+ // |type| represents the origin of the request.
+ CONTENT_EXPORT void Stop(SuspendType type);
+
+ // Change the volume multiplier of the session to |volume_multiplier|.
+ CONTENT_EXPORT void SetVolumeMultiplier(double volume_multiplier);
+
+ // Returns if the session can be controlled by Resume() and Suspend calls
+ // above.
+ CONTENT_EXPORT bool IsControllable() const;
+
+ // Returns if the session is currently active.
+ CONTENT_EXPORT bool IsActive() const;
+
+ // Returns if the session is currently suspended.
+ // TODO(mlamouri): IsSuspended() below checks if the state is not ACTIVE
+ // instead of checking if the state is SUSPENDED. In order to not have to
+ // change all the callers and make the current refactoring ridiculously huge,
+ // this method is introduced temporarily and will be removed later.
+ bool IsReallySuspended() const;
+
+ // Returns if the session is currently suspended or inactive.
+ CONTENT_EXPORT bool IsSuspended() const;
+
+ private:
+ friend class content::WebContentsUserData<MediaSession>;
+ friend class ::MediaSessionBrowserTest;
+ friend class content::MediaSessionVisibilityBrowserTest;
+ friend class content::MediaSessionStateObserver;
+
+ CONTENT_EXPORT void SetDelegateForTests(
+ std::unique_ptr<MediaSessionDelegate> delegate);
+ CONTENT_EXPORT bool IsActiveForTest() const;
+ CONTENT_EXPORT Type audio_focus_type_for_test() const;
+ CONTENT_EXPORT void RemoveAllPlayersForTest();
+ CONTENT_EXPORT MediaSessionUmaHelper* uma_helper_for_test();
+
+ enum class State {
+ ACTIVE,
+ SUSPENDED,
+ INACTIVE
+ };
+
+ // Representation of a player for the MediaSession.
+ struct PlayerIdentifier {
+ PlayerIdentifier(MediaSessionObserver* observer, int player_id);
+ PlayerIdentifier(const PlayerIdentifier&) = default;
+
+ void operator=(const PlayerIdentifier&) = delete;
+ bool operator==(const PlayerIdentifier& player_identifier) const;
+
+ // Hash operator for base::hash_map<>.
+ struct Hash {
+ size_t operator()(const PlayerIdentifier& player_identifier) const;
+ };
+
+ MediaSessionObserver* observer;
+ int player_id;
+ };
+ using PlayersMap = base::hash_set<PlayerIdentifier, PlayerIdentifier::Hash>;
+ using StateChangedCallback = base::Callback<void(State)>;
+
+ CONTENT_EXPORT explicit MediaSession(WebContents* web_contents);
+
+ void Initialize();
+
+ CONTENT_EXPORT void OnSuspendInternal(SuspendType type, State new_state);
+ CONTENT_EXPORT void OnResumeInternal(SuspendType type);
+
+ // Requests audio focus to the MediaSessionDelegate.
+ // Returns whether the request was granted.
+ bool RequestSystemAudioFocus(Type type);
+
+ // To be called after a call to AbandonAudioFocus() in order request the
+ // delegate to abandon the audio focus.
+ void AbandonSystemAudioFocusIfNeeded();
+
+ // Notifies WebContents about the state change of the media session.
+ void UpdateWebContents();
+
+ // Internal method that should be used instead of setting audio_focus_state_.
+ // It sets audio_focus_state_ and notifies observers about the state change.
+ void SetAudioFocusState(State audio_focus_state);
+
+ // Registers a MediaSession state change callback.
+ CONTENT_EXPORT std::unique_ptr<base::CallbackList<void(State)>::Subscription>
+ RegisterMediaSessionStateChangedCallbackForTest(
+ const StateChangedCallback& cb);
+
+ std::unique_ptr<MediaSessionDelegate> delegate_;
+ PlayersMap players_;
+
+ State audio_focus_state_;
+ SuspendType suspend_type_;
+ Type audio_focus_type_;
+
+ MediaSessionUmaHelper uma_helper_;
+
+ // The volume multiplier of this session. All players in this session should
+ // multiply their volume with this multiplier to get the effective volume.
+ double volume_multiplier_;
+
+ MediaMetadata metadata_;
+ base::CallbackList<void(State)> media_session_state_listeners_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaSession);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_H_
diff --git a/chromium/content/browser/media/android/media_session_browsertest.cc b/chromium/content/browser/media/session/media_session_browsertest.cc
index a0628ae7093..db7a67ee5b6 100644
--- a/chromium/content/browser/media/android/media_session_browsertest.cc
+++ b/chromium/content/browser/media/session/media_session_browsertest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/media/android/media_session.h"
+#include "content/browser/media/session/media_session.h"
#include <stddef.h>
@@ -13,7 +13,8 @@
#include "base/metrics/histogram_samples.h"
#include "base/test/histogram_tester.h"
#include "base/test/simple_test_clock.h"
-#include "content/browser/media/android/media_session_observer.h"
+#include "content/browser/media/session/media_session_delegate.h"
+#include "content/browser/media/session/mock_media_session_observer.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/test/content_browser_test.h"
@@ -23,68 +24,23 @@
using content::WebContents;
using content::WebContentsObserver;
using content::MediaSession;
+using content::MediaSessionDelegate;
using content::MediaSessionObserver;
using content::MediaSessionUmaHelper;
+using content::MockMediaSessionObserver;
using ::testing::Expectation;
namespace {
-class MockMediaSessionObserver : public MediaSessionObserver {
+class MockMediaSessionDelegate : public MediaSessionDelegate {
public:
- MockMediaSessionObserver()
- : received_resume_calls_(0),
- received_suspend_calls_(0) {
+ bool RequestAudioFocus(MediaSession::Type) override {
+ return true;
}
- ~MockMediaSessionObserver() override = default;
-
- // Implements MediaSessionObserver.
- void OnSuspend(int player_id) override {
- DCHECK(player_id >= 0);
- DCHECK(players_.size() > static_cast<size_t>(player_id));
-
- ++received_suspend_calls_;
- players_[player_id] = false;
- }
- void OnResume(int player_id) override {
- DCHECK(player_id >= 0);
- DCHECK(players_.size() > static_cast<size_t>(player_id));
-
- ++received_resume_calls_;
- players_[player_id] = true;
- }
-
- int StartNewPlayer() {
- players_.push_back(true);
- return players_.size() - 1;
- }
-
- bool IsPlaying(size_t player_id) {
- DCHECK(players_.size() > player_id);
- return players_[player_id];
- }
-
- void SetPlaying(size_t player_id, bool playing) {
- DCHECK(players_.size() > player_id);
- players_[player_id] = playing;
+ void AbandonAudioFocus() override {
}
-
- int received_suspend_calls() const {
- return received_suspend_calls_;
- }
-
- int received_resume_calls() const {
- return received_resume_calls_;
- }
-
- private:
- // Basic representation of the players. The position in the vector is the
- // player_id. The value of the vector is the playing status.
- std::vector<bool> players_;
-
- int received_resume_calls_;
- int received_suspend_calls_;
};
class MockWebContentsObserver : public WebContentsObserver {
@@ -92,8 +48,9 @@ class MockWebContentsObserver : public WebContentsObserver {
MockWebContentsObserver(WebContents* web_contents)
: WebContentsObserver(web_contents) {}
- MOCK_METHOD2(MediaSessionStateChanged,
- void(bool is_controllable, bool is_suspended));
+ MOCK_METHOD3(MediaSessionStateChanged,
+ void(bool is_controllable, bool is_suspended,
+ const content::MediaMetadata& metadata));
};
} // namespace
@@ -108,7 +65,8 @@ class MediaSessionBrowserTest : public content::ContentBrowserTest {
mock_web_contents_observer_.reset(
new MockWebContentsObserver(shell()->web_contents()));
media_session_ = MediaSession::Get(shell()->web_contents());
- media_session_->ResetJavaRefForTest();
+ media_session_->SetDelegateForTests(
+ std::unique_ptr<MediaSessionDelegate>(new MockMediaSessionDelegate()));
ASSERT_TRUE(media_session_);
}
@@ -161,27 +119,34 @@ class MediaSessionBrowserTest : public content::ContentBrowserTest {
bool IsSuspended() { return media_session_->IsSuspended(); }
void UIResume() {
- media_session_->Resume();
+ media_session_->Resume(MediaSession::SuspendType::UI);
}
void SystemResume() {
- media_session_->OnResume(nullptr, nullptr);
+ media_session_->OnResumeInternal(MediaSession::SuspendType::SYSTEM);
}
void UISuspend() {
- media_session_->Suspend();
+ media_session_->Suspend(MediaSession::SuspendType::UI);
}
void SystemSuspend(bool temporary) {
- media_session_->OnSuspend(nullptr, nullptr, temporary);
+ media_session_->OnSuspendInternal(
+ MediaSession::SuspendType::SYSTEM,
+ temporary ? MediaSession::State::SUSPENDED
+ : MediaSession::State::INACTIVE);
+ }
+
+ void SystemSetVolumeMultiplier(double volume_multiplier) {
+ media_session_->SetVolumeMultiplier(volume_multiplier);
}
MockWebContentsObserver* mock_web_contents_observer() {
return mock_web_contents_observer_.get();
}
- scoped_ptr<MediaSession> CreateDummyMediaSession() {
- return scoped_ptr<MediaSession>(new MediaSession(nullptr));
+ std::unique_ptr<MediaSession> CreateDummyMediaSession() {
+ return std::unique_ptr<MediaSession>(new MediaSession(nullptr));
}
MediaSessionUmaHelper* GetMediaSessionUMAHelper() {
@@ -190,14 +155,14 @@ class MediaSessionBrowserTest : public content::ContentBrowserTest {
protected:
MediaSession* media_session_;
- scoped_ptr<MockWebContentsObserver> mock_web_contents_observer_;
+ std::unique_ptr<MockWebContentsObserver> mock_web_contents_observer_;
DISALLOW_COPY_AND_ASSIGN(MediaSessionBrowserTest);
};
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
PlayersFromSameObserverDoNotStopEachOtherInSameSession) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -211,15 +176,14 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
PlayersFromManyObserverDoNotStopEachOtherInSameSession) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer_1(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer_1(
new MockMediaSessionObserver);
- scoped_ptr<MockMediaSessionObserver> media_session_observer_2(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer_2(
new MockMediaSessionObserver);
- scoped_ptr<MockMediaSessionObserver> media_session_observer_3(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer_3(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer_1.get(), MediaSession::Type::Content);
-
StartNewPlayer(media_session_observer_2.get(), MediaSession::Type::Content);
StartNewPlayer(media_session_observer_3.get(), MediaSession::Type::Content);
@@ -230,7 +194,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
SuspendedMediaSessionStopsPlayers) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -246,7 +210,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
ResumedMediaSessionRestartsPlayers) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -263,7 +227,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
StartedPlayerOnSuspendedSessionPlaysAlone) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -286,12 +250,31 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
EXPECT_TRUE(media_session_observer->IsPlaying(2));
}
+IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
+ MediaSessionSetVolumeMultiplier) {
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
+ new MockMediaSessionObserver);
+
+ StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
+ StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
+
+ double volume_multiplier = 0.2f;
+ SystemSetVolumeMultiplier(volume_multiplier);
+
+ EXPECT_EQ(volume_multiplier, media_session_observer->GetVolumeMultiplier(0));
+ EXPECT_EQ(volume_multiplier, media_session_observer->GetVolumeMultiplier(1));
+
+ StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
+
+ EXPECT_EQ(volume_multiplier, media_session_observer->GetVolumeMultiplier(2));
+}
+
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, AudioFocusInitialState) {
EXPECT_FALSE(HasAudioFocus());
}
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, StartPlayerGivesFocus) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -300,7 +283,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, StartPlayerGivesFocus) {
}
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, SuspendGivesAwayAudioFocus) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -311,18 +294,18 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, SuspendGivesAwayAudioFocus) {
}
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, StopGivesAwayAudioFocus) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
- media_session_->Stop();
+ media_session_->Stop(MediaSession::SuspendType::UI);
EXPECT_FALSE(HasAudioFocus());
}
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ResumeGivesBackAudioFocus) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -335,7 +318,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ResumeGivesBackAudioFocus) {
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
RemovingLastPlayerDropsAudioFocus) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -352,11 +335,11 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
RemovingLastPlayerFromManyObserversDropsAudioFocus) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer_1(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer_1(
new MockMediaSessionObserver);
- scoped_ptr<MockMediaSessionObserver> media_session_observer_2(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer_2(
new MockMediaSessionObserver);
- scoped_ptr<MockMediaSessionObserver> media_session_observer_3(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer_3(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer_1.get(), MediaSession::Type::Content);
@@ -373,9 +356,9 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
RemovingAllPlayersFromObserversDropsAudioFocus) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer_1(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer_1(
new MockMediaSessionObserver);
- scoped_ptr<MockMediaSessionObserver> media_session_observer_2(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer_2(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer_1.get(), MediaSession::Type::Content);
@@ -390,7 +373,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
}
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ResumePlayGivesAudioFocus) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -405,7 +388,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ResumePlayGivesAudioFocus) {
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
ResumeSuspendAreSentOnlyOncePerPlayers) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -424,7 +407,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
ResumeSuspendAreSentOnlyOncePerPlayersAddedTwice) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -451,7 +434,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
RemovingTheSamePlayerTwiceIsANoop) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -461,7 +444,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
}
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, MediaSessionType) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
// Starting a player with a given type should set the session to that type.
@@ -506,9 +489,9 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, MediaSessionType) {
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ControlsShowForContent) {
EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false));
+ MediaSessionStateChanged(true, false, testing::_));
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
// Starting a player with a content type should show the media controls.
@@ -520,9 +503,9 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ControlsShowForContent) {
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ControlsNoShowForTransient) {
EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(false, false));
+ MediaSessionStateChanged(false, false, testing::_));
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
// Starting a player with a transient type should not show the media controls.
@@ -534,12 +517,12 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ControlsNoShowForTransient) {
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ControlsHideWhenStopped) {
Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false));
+ MediaSessionStateChanged(true, false, testing::_));
EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(false, true))
+ MediaSessionStateChanged(false, true, testing::_))
.After(showControls);
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -552,9 +535,9 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ControlsHideWhenStopped) {
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ControlsShownAcceptTransient) {
EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false));
+ MediaSessionStateChanged(true, false, testing::_));
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -568,13 +551,13 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ControlsShownAcceptTransient) {
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
ControlsShownAfterContentAdded) {
- Expectation dontShowControls = EXPECT_CALL(
- *mock_web_contents_observer(), MediaSessionStateChanged(false, false));
+ Expectation dontShowControls = EXPECT_CALL(*mock_web_contents_observer(),
+ MediaSessionStateChanged(false, false, testing::_));
EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false))
+ MediaSessionStateChanged(true, false, testing::_))
.After(dontShowControls);
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Transient);
@@ -589,9 +572,9 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
ControlsStayIfOnlyOnePlayerHasBeenPaused) {
EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false));
+ MediaSessionStateChanged(true, false, testing::_));
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -608,11 +591,11 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
ControlsHideWhenTheLastPlayerIsRemoved) {
Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false));
+ MediaSessionStateChanged(true, false, testing::_));
EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(false, true))
+ MediaSessionStateChanged(false, true, testing::_))
.After(showControls);
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -632,12 +615,12 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
ControlsHideWhenAllThePlayersAreRemoved) {
Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false));
+ MediaSessionStateChanged(true, false, testing::_));
EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(false, true))
+ MediaSessionStateChanged(false, true, testing::_))
.After(showControls);
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -652,12 +635,12 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
ControlsNotHideWhenTheLastPlayerIsPaused) {
Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false));
+ MediaSessionStateChanged(true, false, testing::_));
EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, true))
+ MediaSessionStateChanged(true, true, testing::_))
.After(showControls);
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -677,12 +660,12 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
SuspendTemporaryUpdatesControls) {
Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false));
+ MediaSessionStateChanged(true, false, testing::_));
EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, true))
+ MediaSessionStateChanged(true, true, testing::_))
.After(showControls);
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -695,15 +678,14 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ControlsUpdatedWhenResumed) {
Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false));
+ MediaSessionStateChanged(true, false, testing::_));
Expectation pauseControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, true))
- .After(showControls);
+ MediaSessionStateChanged(true, true, testing::_)).After(showControls);
EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false))
+ MediaSessionStateChanged(true, false, testing::_))
.After(pauseControls);
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -717,12 +699,12 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ControlsUpdatedWhenResumed) {
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
ControlsHideWhenSessionSuspendedPermanently) {
Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false));
+ MediaSessionStateChanged(true, false, testing::_));
EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(false, true))
+ MediaSessionStateChanged(false, true, testing::_))
.After(showControls);
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -736,20 +718,19 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
ConstrolsHideWhenSessionStops) {
Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false));
+ MediaSessionStateChanged(true, false, testing::_));
Expectation pauseControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, true))
- .After(showControls);
+ MediaSessionStateChanged(true, true, testing::_)).After(showControls);
EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(false, true))
+ MediaSessionStateChanged(false, true, testing::_))
.After(pauseControls);
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
- media_session_->Stop();
+ media_session_->Stop(MediaSession::SuspendType::UI);
EXPECT_FALSE(IsControllable());
EXPECT_TRUE(IsSuspended());
@@ -758,15 +739,14 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
ControlsHideWhenSessionChangesFromContentToTransient) {
Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false));
+ MediaSessionStateChanged(true, false, testing::_));
Expectation pauseControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, true))
- .After(showControls);
+ MediaSessionStateChanged(true, true, testing::_)).After(showControls);
EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(false, false))
+ MediaSessionStateChanged(false, false, testing::_))
.After(pauseControls);
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -783,15 +763,14 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
ControlsUpdatedWhenNewPlayerResetsSession) {
Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false));
+ MediaSessionStateChanged(true, false, testing::_));
Expectation pauseControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, true))
- .After(showControls);
+ MediaSessionStateChanged(true, true, testing::_)).After(showControls);
EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false))
+ MediaSessionStateChanged(true, false, testing::_))
.After(pauseControls);
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -807,15 +786,14 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
ControlsResumedWhenPlayerIsResumed) {
Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false));
+ MediaSessionStateChanged(true, false, testing::_));
Expectation pauseControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, true))
- .After(showControls);
+ MediaSessionStateChanged(true, true, testing::_)).After(showControls);
EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false))
+ MediaSessionStateChanged(true, false, testing::_))
.After(pauseControls);
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -831,11 +809,12 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
ControlsUpdatedDueToResumeSessionAction) {
Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false));
+ MediaSessionStateChanged(true, false, testing::_));
EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, true)).After(showControls);
+ MediaSessionStateChanged(true, true, testing::_))
+ .After(showControls);
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -848,15 +827,14 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
ControlsUpdatedDueToSuspendSessionAction) {
Expectation showControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false));
+ MediaSessionStateChanged(true, false, testing::_));
Expectation pauseControls = EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, true))
- .After(showControls);
+ MediaSessionStateChanged(true, true, testing::_)).After(showControls);
EXPECT_CALL(*mock_web_contents_observer(),
- MediaSessionStateChanged(true, false))
+ MediaSessionStateChanged(true, false, testing::_))
.After(pauseControls);
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -869,7 +847,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
DontResumeBySystemUISuspendedSessions) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -884,7 +862,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
AllowUIResumeForSystemSuspend) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -898,7 +876,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
}
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ResumeSuspendFromUI) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -912,7 +890,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ResumeSuspendFromUI) {
}
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ResumeSuspendFromSystem) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -926,14 +904,14 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, ResumeSuspendFromSystem) {
}
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, UMA_Suspended_SystemTransient) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
base::HistogramTester tester;
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
SystemSuspend(true);
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
tester.GetHistogramSamplesSinceCreation("Media.Session.Suspended"));
EXPECT_EQ(1, samples->TotalCount());
EXPECT_EQ(1, samples->GetCount(0)); // System Transient
@@ -944,14 +922,14 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, UMA_Suspended_SystemTransient) {
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
UMA_Suspended_SystemPermantent) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
base::HistogramTester tester;
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
SystemSuspend(false);
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
tester.GetHistogramSamplesSinceCreation("Media.Session.Suspended"));
EXPECT_EQ(1, samples->TotalCount());
EXPECT_EQ(0, samples->GetCount(0)); // System Transient
@@ -960,14 +938,14 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
}
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, UMA_Suspended_UI) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
base::HistogramTester tester;
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
UISuspend();
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
tester.GetHistogramSamplesSinceCreation("Media.Session.Suspended"));
EXPECT_EQ(1, samples->TotalCount());
EXPECT_EQ(0, samples->GetCount(0)); // System Transient
@@ -976,7 +954,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, UMA_Suspended_UI) {
}
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, UMA_Suspended_Multiple) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
base::HistogramTester tester;
@@ -993,7 +971,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, UMA_Suspended_Multiple) {
SystemSuspend(false);
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
tester.GetHistogramSamplesSinceCreation("Media.Session.Suspended"));
EXPECT_EQ(4, samples->TotalCount());
EXPECT_EQ(1, samples->GetCount(0)); // System Transient
@@ -1002,7 +980,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, UMA_Suspended_Multiple) {
}
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, UMA_Suspended_Crossing) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
base::HistogramTester tester;
@@ -1018,7 +996,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, UMA_Suspended_Crossing) {
SystemSuspend(false);
SystemResume();
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
tester.GetHistogramSamplesSinceCreation("Media.Session.Suspended"));
EXPECT_EQ(2, samples->TotalCount());
EXPECT_EQ(1, samples->GetCount(0)); // System Transient
@@ -1027,14 +1005,14 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, UMA_Suspended_Crossing) {
}
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, UMA_Suspended_Stop) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
new MockMediaSessionObserver);
base::HistogramTester tester;
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
- media_session_->Stop();
+ media_session_->Stop(MediaSession::SuspendType::UI);
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
tester.GetHistogramSamplesSinceCreation("Media.Session.Suspended"));
EXPECT_EQ(1, samples->TotalCount());
EXPECT_EQ(0, samples->GetCount(0)); // System Transient
@@ -1045,33 +1023,33 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, UMA_Suspended_Stop) {
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest, UMA_ActiveTime_NoActivation) {
base::HistogramTester tester;
- scoped_ptr<MediaSession> media_session = CreateDummyMediaSession();
+ std::unique_ptr<MediaSession> media_session = CreateDummyMediaSession();
media_session.reset();
// A MediaSession that wasn't active doesn't register an active time.
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
EXPECT_EQ(0, samples->TotalCount());
}
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
UMA_ActiveTime_SimpleActivation) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
+ new MockMediaSessionObserver);
base::HistogramTester tester;
MediaSessionUmaHelper* media_session_uma_helper = GetMediaSessionUMAHelper();
base::SimpleTestClock* clock = new base::SimpleTestClock();
clock->SetNow(base::Time::Now());
media_session_uma_helper->SetClockForTest(
- scoped_ptr<base::SimpleTestClock>(clock));
+ std::unique_ptr<base::SimpleTestClock>(clock));
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
clock->Advance(base::TimeDelta::FromMilliseconds(1000));
- media_session_->Stop();
+ media_session_->Stop(MediaSession::SuspendType::UI);
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
EXPECT_EQ(1, samples->TotalCount());
EXPECT_EQ(1, samples->GetCount(1000));
@@ -1079,15 +1057,15 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
UMA_ActiveTime_ActivationWithUISuspension) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
+ new MockMediaSessionObserver);
base::HistogramTester tester;
MediaSessionUmaHelper* media_session_uma_helper = GetMediaSessionUMAHelper();
base::SimpleTestClock* clock = new base::SimpleTestClock();
clock->SetNow(base::Time::Now());
media_session_uma_helper->SetClockForTest(
- scoped_ptr<base::SimpleTestClock>(clock));
+ std::unique_ptr<base::SimpleTestClock>(clock));
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -1098,9 +1076,9 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
UIResume();
clock->Advance(base::TimeDelta::FromMilliseconds(1000));
- media_session_->Stop();
+ media_session_->Stop(MediaSession::SuspendType::UI);
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
EXPECT_EQ(1, samples->TotalCount());
EXPECT_EQ(1, samples->GetCount(2000));
@@ -1108,15 +1086,15 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
UMA_ActiveTime_ActivationWithSystemSuspension) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
+ new MockMediaSessionObserver);
base::HistogramTester tester;
MediaSessionUmaHelper* media_session_uma_helper = GetMediaSessionUMAHelper();
base::SimpleTestClock* clock = new base::SimpleTestClock();
clock->SetNow(base::Time::Now());
media_session_uma_helper->SetClockForTest(
- scoped_ptr<base::SimpleTestClock>(clock));
+ std::unique_ptr<base::SimpleTestClock>(clock));
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
@@ -1127,9 +1105,9 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
SystemResume();
clock->Advance(base::TimeDelta::FromMilliseconds(1000));
- media_session_->Stop();
+ media_session_->Stop(MediaSession::SuspendType::UI);
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
EXPECT_EQ(1, samples->TotalCount());
EXPECT_EQ(1, samples->GetCount(2000));
@@ -1137,22 +1115,22 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
UMA_ActiveTime_ActivateSuspendedButNotStopped) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
+ new MockMediaSessionObserver);
base::HistogramTester tester;
MediaSessionUmaHelper* media_session_uma_helper = GetMediaSessionUMAHelper();
base::SimpleTestClock* clock = new base::SimpleTestClock();
clock->SetNow(base::Time::Now());
media_session_uma_helper->SetClockForTest(
- scoped_ptr<base::SimpleTestClock>(clock));
+ std::unique_ptr<base::SimpleTestClock>(clock));
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
clock->Advance(base::TimeDelta::FromMilliseconds(500));
SystemSuspend(true);
{
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
EXPECT_EQ(0, samples->TotalCount());
}
@@ -1162,7 +1140,7 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
UISuspend();
{
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
EXPECT_EQ(0, samples->TotalCount());
}
@@ -1170,27 +1148,27 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
UMA_ActiveTime_ActivateSuspendStopTwice) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
+ new MockMediaSessionObserver);
base::HistogramTester tester;
MediaSessionUmaHelper* media_session_uma_helper = GetMediaSessionUMAHelper();
base::SimpleTestClock* clock = new base::SimpleTestClock();
clock->SetNow(base::Time::Now());
media_session_uma_helper->SetClockForTest(
- scoped_ptr<base::SimpleTestClock>(clock));
+ std::unique_ptr<base::SimpleTestClock>(clock));
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
clock->Advance(base::TimeDelta::FromMilliseconds(500));
SystemSuspend(true);
- media_session_->Stop();
+ media_session_->Stop(MediaSession::SuspendType::UI);
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
clock->Advance(base::TimeDelta::FromMilliseconds(5000));
SystemResume();
- media_session_->Stop();
+ media_session_->Stop(MediaSession::SuspendType::UI);
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
EXPECT_EQ(2, samples->TotalCount());
EXPECT_EQ(1, samples->GetCount(500));
@@ -1199,15 +1177,15 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
UMA_ActiveTime_MultipleActivations) {
- scoped_ptr<MockMediaSessionObserver> media_session_observer(
- new MockMediaSessionObserver);
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
+ new MockMediaSessionObserver);
base::HistogramTester tester;
MediaSessionUmaHelper* media_session_uma_helper = GetMediaSessionUMAHelper();
base::SimpleTestClock* clock = new base::SimpleTestClock();
clock->SetNow(base::Time::Now());
media_session_uma_helper->SetClockForTest(
- scoped_ptr<base::SimpleTestClock>(clock));
+ std::unique_ptr<base::SimpleTestClock>(clock));
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
clock->Advance(base::TimeDelta::FromMilliseconds(10000));
@@ -1215,9 +1193,9 @@ IN_PROC_BROWSER_TEST_F(MediaSessionBrowserTest,
StartNewPlayer(media_session_observer.get(), MediaSession::Type::Content);
clock->Advance(base::TimeDelta::FromMilliseconds(1000));
- media_session_->Stop();
+ media_session_->Stop(MediaSession::SuspendType::UI);
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
tester.GetHistogramSamplesSinceCreation("Media.Session.ActiveTime"));
EXPECT_EQ(2, samples->TotalCount());
EXPECT_EQ(1, samples->GetCount(1000));
diff --git a/chromium/content/browser/media/session/media_session_controller.cc b/chromium/content/browser/media/session/media_session_controller.cc
new file mode 100644
index 00000000000..00ba5a91f88
--- /dev/null
+++ b/chromium/content/browser/media/session/media_session_controller.cc
@@ -0,0 +1,109 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/session/media_session_controller.h"
+
+#include "content/browser/media/media_web_contents_observer.h"
+#include "content/browser/media/session/media_session.h"
+#include "content/common/media/media_player_delegate_messages.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
+
+namespace content {
+
+MediaSessionController::MediaSessionController(
+ const WebContentsObserver::MediaPlayerId& id,
+ MediaWebContentsObserver* media_web_contents_observer)
+ : id_(id),
+ media_web_contents_observer_(media_web_contents_observer),
+ media_session_(
+ MediaSession::Get(media_web_contents_observer_->web_contents())) {}
+
+MediaSessionController::~MediaSessionController() {
+ if (!has_session_)
+ return;
+ media_session_->RemovePlayer(this, player_id_);
+}
+
+bool MediaSessionController::Initialize(bool has_audio,
+ bool is_remote,
+ base::TimeDelta duration) {
+ // Don't generate a new id if one has already been set.
+ if (!has_session_) {
+ // These objects are only created on the UI thread, so this is safe.
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ static uint32_t player_id = 0;
+ player_id_ = static_cast<int>(player_id++);
+ } else {
+ // WebMediaPlayerAndroid does not have an accurate sense of audio presence,
+ // only the MediaPlayerManager does, so WMPA never reports audio unless it's
+ // sure (no video stream). This leads to issues when Initialize() is called
+ // by WMPA (reporting no audio and subsequently releasing the session) after
+ // the manager accurately reported audio.
+ //
+ // To workaround this, |has_audio| is sticky; I.e., once a session has been
+ // created with audio all future sessions will also have audio.
+ //
+ // TODO(dalecurtis): Delete sticky audio once we're no longer using WMPA and
+ // the BrowserMediaPlayerManagers. Tracked by http://crbug.com/580626
+ has_audio = true;
+ }
+
+ // Don't bother with a MediaSession for remote players or without audio. If
+ // we already have a session from a previous call, release it.
+ if (!has_audio || is_remote) {
+ if (has_session_) {
+ has_session_ = false;
+ media_session_->RemovePlayer(this, player_id_);
+ }
+ return true;
+ }
+
+ const MediaSession::Type media_session_type =
+ duration == base::TimeDelta() ||
+ duration >
+ base::TimeDelta::FromSeconds(kMinimumDurationForContentSecs)
+ ? MediaSession::Type::Content
+ : MediaSession::Type::Transient;
+
+ // If a session can't be created, force a pause immediately. Attempt to add a
+ // session even if we already have one. MediaSession expects AddPlayer() to
+ // be called after OnPlaybackPaused() to reactivate the session.
+ if (!media_session_->AddPlayer(this, player_id_, media_session_type)) {
+ OnSuspend(player_id_);
+ return false;
+ }
+
+ has_session_ = true;
+ return true;
+}
+
+void MediaSessionController::OnSuspend(int player_id) {
+ DCHECK_EQ(player_id_, player_id);
+ media_web_contents_observer_->Send(
+ new MediaPlayerDelegateMsg_Pause(id_.first->GetRoutingID(), id_.second));
+}
+
+void MediaSessionController::OnResume(int player_id) {
+ DCHECK_EQ(player_id_, player_id);
+ media_web_contents_observer_->Send(
+ new MediaPlayerDelegateMsg_Play(id_.first->GetRoutingID(), id_.second));
+}
+
+void MediaSessionController::OnSetVolumeMultiplier(int player_id,
+ double volume_multiplier) {
+ DCHECK_EQ(player_id_, player_id);
+ media_web_contents_observer_->Send(
+ new MediaPlayerDelegateMsg_UpdateVolumeMultiplier(
+ id_.first->GetRoutingID(), id_.second, volume_multiplier));
+}
+
+void MediaSessionController::OnPlaybackPaused() {
+ // We check for suspension here since the renderer may issue its own pause
+ // in response to or while a pause from the browser is in flight.
+ if (!media_session_->IsSuspended())
+ media_session_->OnPlayerPaused(this, player_id_);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/session/media_session_controller.h b/chromium/content/browser/media/session/media_session_controller.h
new file mode 100644
index 00000000000..c87aa2a464e
--- /dev/null
+++ b/chromium/content/browser/media/session/media_session_controller.h
@@ -0,0 +1,71 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_CONTROLLER_H_
+#define CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_CONTROLLER_H_
+
+#include "base/compiler_specific.h"
+#include "base/time/time.h"
+#include "content/browser/media/session/media_session_observer.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/web_contents_observer.h"
+
+namespace content {
+
+class MediaSession;
+class MediaWebContentsObserver;
+
+// Helper class for controlling a single player's MediaSession instance. Sends
+// browser side MediaSession commands back to a player hosted in the renderer
+// process.
+class CONTENT_EXPORT MediaSessionController :
+ NON_EXPORTED_BASE(public MediaSessionObserver) {
+ public:
+ MediaSessionController(const WebContentsObserver::MediaPlayerId& id,
+ MediaWebContentsObserver* media_web_contents_observer);
+ ~MediaSessionController() override;
+
+ // Minimum duration of content for a MediaSession instance to be created.
+ enum { kMinimumDurationForContentSecs = 5 };
+
+ // Clients must call this after construction and destroy the controller if it
+ // returns false. May be called more than once; does nothing if none of the
+ // input parameters have changed since the last call.
+ //
+ // Note: Once a session has been initialized with |has_audio| as true, all
+ // future calls to Initialize() will retain this flag.
+ // TODO(dalecurtis): Delete sticky audio once we're no longer using WMPA and
+ // the BrowserMediaPlayerManagers. Tracked by http://crbug.com/580626
+ bool Initialize(bool has_audio, bool is_remote, base::TimeDelta duration);
+
+ // Must be called when a pause occurs on the renderer side media player; keeps
+ // the MediaSession instance in sync with renderer side behavior.
+ void OnPlaybackPaused();
+
+ // MediaSessionObserver implementation.
+ void OnSuspend(int player_id) override;
+ void OnResume(int player_id) override;
+ void OnSetVolumeMultiplier(int player_id, double volume_multiplier) override;
+
+ // Test helpers.
+ int get_player_id_for_testing() const { return player_id_; }
+
+ private:
+ const WebContentsObserver::MediaPlayerId id_;
+
+ // Non-owned pointer; |media_web_contents_observer_| is the owner of |this|.
+ MediaWebContentsObserver* const media_web_contents_observer_;
+
+ // Non-owned pointer; lifetime is the same as |media_web_contents_observer_|.
+ MediaSession* const media_session_;
+
+ int player_id_ = 0;
+ bool has_session_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaSessionController);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_CONTROLLER_H_
diff --git a/chromium/content/browser/media/session/media_session_controller_unittest.cc b/chromium/content/browser/media/session/media_session_controller_unittest.cc
new file mode 100644
index 00000000000..1b04aac3cc9
--- /dev/null
+++ b/chromium/content/browser/media/session/media_session_controller_unittest.cc
@@ -0,0 +1,214 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/tuple.h"
+#include "content/browser/media/media_web_contents_observer.h"
+#include "content/browser/media/session/media_session.h"
+#include "content/browser/media/session/media_session_controller.h"
+#include "content/common/media/media_player_delegate_messages.h"
+#include "content/test/test_render_view_host.h"
+#include "content/test/test_web_contents.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+class MediaSessionControllerTest : public RenderViewHostImplTestHarness {
+ public:
+ void SetUp() override {
+ RenderViewHostImplTestHarness::SetUp();
+ id_ = WebContentsObserver::MediaPlayerId(contents()->GetMainFrame(), 0);
+ controller_ = CreateController();
+ }
+
+ void TearDown() override {
+ // Destruct the controller prior to any other teardown to avoid out of order
+ // destruction relative to the MediaSession instance.
+ controller_.reset();
+ RenderViewHostImplTestHarness::TearDown();
+ }
+
+ protected:
+ std::unique_ptr<MediaSessionController> CreateController() {
+ return std::unique_ptr<MediaSessionController>(new MediaSessionController(
+ id_, contents()->media_web_contents_observer()));
+ }
+
+ MediaSession* media_session() { return MediaSession::Get(contents()); }
+
+ IPC::TestSink& test_sink() { return main_test_rfh()->GetProcess()->sink(); }
+
+ void Suspend() {
+ controller_->OnSuspend(controller_->get_player_id_for_testing());
+ }
+
+ void Resume() {
+ controller_->OnResume(controller_->get_player_id_for_testing());
+ }
+
+ void SetVolumeMultiplier(double multiplier) {
+ controller_->OnSetVolumeMultiplier(controller_->get_player_id_for_testing(),
+ multiplier);
+ }
+
+ // Returns a duration long enough for a media session instance to be created.
+ base::TimeDelta DurationJustRight() {
+ return base::TimeDelta::FromSeconds(
+ MediaSessionController::kMinimumDurationForContentSecs + 1);
+ }
+
+ // Returns a duration too short for a media session instance.
+ base::TimeDelta DurationTooShort() {
+ return base::TimeDelta::FromSeconds(
+ MediaSessionController::kMinimumDurationForContentSecs);
+ }
+
+ template <typename T>
+ bool ReceivedMessagePlayPause() {
+ const IPC::Message* msg = test_sink().GetUniqueMessageMatching(T::ID);
+ if (!msg)
+ return false;
+
+ base::Tuple<int> result;
+ if (!T::Read(msg, &result))
+ return false;
+
+ EXPECT_EQ(id_.second, base::get<0>(result));
+ test_sink().ClearMessages();
+ return id_.second == base::get<0>(result);
+ }
+
+ template <typename T>
+ bool ReceivedMessageVolumeMultiplierUpdate(double expected_multiplier) {
+ const IPC::Message* msg = test_sink().GetUniqueMessageMatching(T::ID);
+ if (!msg)
+ return false;
+
+ base::Tuple<int, double> result;
+ if (!T::Read(msg, &result))
+ return false;
+
+ EXPECT_EQ(id_.second, base::get<0>(result));
+ if (id_.second != base::get<0>(result))
+ return false;
+
+ EXPECT_EQ(expected_multiplier, base::get<1>(result));
+ test_sink().ClearMessages();
+ return expected_multiplier == base::get<1>(result);
+ }
+
+ WebContentsObserver::MediaPlayerId id_;
+ std::unique_ptr<MediaSessionController> controller_;
+};
+
+TEST_F(MediaSessionControllerTest, NoAudioNoSession) {
+ ASSERT_TRUE(controller_->Initialize(false, false, DurationJustRight()));
+ EXPECT_TRUE(media_session()->IsSuspended());
+ EXPECT_FALSE(media_session()->IsControllable());
+}
+
+TEST_F(MediaSessionControllerTest, IsRemoteNoSession) {
+ ASSERT_TRUE(controller_->Initialize(true, true, DurationJustRight()));
+ EXPECT_TRUE(media_session()->IsSuspended());
+ EXPECT_FALSE(media_session()->IsControllable());
+}
+
+TEST_F(MediaSessionControllerTest, TooShortNoControllableSession) {
+ ASSERT_TRUE(controller_->Initialize(true, false, DurationTooShort()));
+ EXPECT_FALSE(media_session()->IsSuspended());
+ EXPECT_FALSE(media_session()->IsControllable());
+}
+
+TEST_F(MediaSessionControllerTest, BasicControls) {
+ ASSERT_TRUE(controller_->Initialize(true, false, DurationJustRight()));
+ EXPECT_FALSE(media_session()->IsSuspended());
+ EXPECT_TRUE(media_session()->IsControllable());
+
+ // Verify suspend notifies the renderer and maintains its session.
+ Suspend();
+ EXPECT_TRUE(ReceivedMessagePlayPause<MediaPlayerDelegateMsg_Pause>());
+
+ // Likewise verify the resume behavior.
+ Resume();
+ EXPECT_TRUE(ReceivedMessagePlayPause<MediaPlayerDelegateMsg_Play>());
+
+ // Verify destruction of the controller removes its session.
+ controller_.reset();
+ EXPECT_TRUE(media_session()->IsSuspended());
+ EXPECT_FALSE(media_session()->IsControllable());
+}
+
+TEST_F(MediaSessionControllerTest, VolumeMultiplier) {
+ ASSERT_TRUE(controller_->Initialize(true, false, DurationJustRight()));
+ EXPECT_FALSE(media_session()->IsSuspended());
+ EXPECT_TRUE(media_session()->IsControllable());
+
+ // Upon creation of the MediaSession the default multiplier will be sent.
+ EXPECT_TRUE(ReceivedMessageVolumeMultiplierUpdate<
+ MediaPlayerDelegateMsg_UpdateVolumeMultiplier>(1.0));
+
+ // Verify a different volume multiplier is sent.
+ const double kTestMultiplier = 0.5;
+ SetVolumeMultiplier(kTestMultiplier);
+ EXPECT_TRUE(ReceivedMessageVolumeMultiplierUpdate<
+ MediaPlayerDelegateMsg_UpdateVolumeMultiplier>(kTestMultiplier));
+}
+
+TEST_F(MediaSessionControllerTest, ControllerSidePause) {
+ ASSERT_TRUE(controller_->Initialize(true, false, DurationJustRight()));
+ EXPECT_FALSE(media_session()->IsSuspended());
+ EXPECT_TRUE(media_session()->IsControllable());
+
+ // Verify pause behavior.
+ controller_->OnPlaybackPaused();
+ EXPECT_TRUE(media_session()->IsSuspended());
+ EXPECT_TRUE(media_session()->IsControllable());
+
+ // Verify the next Initialize() call restores the session.
+ ASSERT_TRUE(controller_->Initialize(true, false, DurationJustRight()));
+ EXPECT_FALSE(media_session()->IsSuspended());
+ EXPECT_TRUE(media_session()->IsControllable());
+}
+
+TEST_F(MediaSessionControllerTest, Reinitialize) {
+ ASSERT_TRUE(controller_->Initialize(false, false, DurationJustRight()));
+ EXPECT_TRUE(media_session()->IsSuspended());
+ EXPECT_FALSE(media_session()->IsControllable());
+
+ // Create a transient type session.
+ ASSERT_TRUE(controller_->Initialize(true, false, DurationTooShort()));
+ EXPECT_FALSE(media_session()->IsSuspended());
+ EXPECT_FALSE(media_session()->IsControllable());
+ const int current_player_id = controller_->get_player_id_for_testing();
+
+ // Reinitialize the session as a content type.
+ ASSERT_TRUE(controller_->Initialize(true, false, DurationJustRight()));
+ EXPECT_FALSE(media_session()->IsSuspended());
+ EXPECT_TRUE(media_session()->IsControllable());
+ // Player id should not change when there's an active session.
+ EXPECT_EQ(current_player_id, controller_->get_player_id_for_testing());
+
+ // Verify suspend notifies the renderer and maintains its session.
+ Suspend();
+ EXPECT_TRUE(ReceivedMessagePlayPause<MediaPlayerDelegateMsg_Pause>());
+
+ // Likewise verify the resume behavior.
+ Resume();
+ EXPECT_TRUE(ReceivedMessagePlayPause<MediaPlayerDelegateMsg_Play>());
+
+ // Attempt to switch to no audio player, which should do nothing.
+ // TODO(dalecurtis): Delete this test once we're no longer using WMPA and
+ // the BrowserMediaPlayerManagers. Tracked by http://crbug.com/580626
+ ASSERT_TRUE(controller_->Initialize(false, false, DurationJustRight()));
+ EXPECT_FALSE(media_session()->IsSuspended());
+ EXPECT_TRUE(media_session()->IsControllable());
+ EXPECT_EQ(current_player_id, controller_->get_player_id_for_testing());
+
+ // Switch to a remote player, which should release the session.
+ ASSERT_TRUE(controller_->Initialize(true, true, DurationJustRight()));
+ EXPECT_TRUE(media_session()->IsSuspended());
+ EXPECT_FALSE(media_session()->IsControllable());
+ EXPECT_EQ(current_player_id, controller_->get_player_id_for_testing());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/session/media_session_controllers_manager.cc b/chromium/content/browser/media/session/media_session_controllers_manager.cc
new file mode 100644
index 00000000000..426f3ceb325
--- /dev/null
+++ b/chromium/content/browser/media/session/media_session_controllers_manager.cc
@@ -0,0 +1,94 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/session/media_session_controllers_manager.h"
+
+#include "base/command_line.h"
+#include "content/browser/media/session/media_session.h"
+#include "content/browser/media/session/media_session_controller.h"
+#include "content/browser/media/session/media_session_observer.h"
+#include "media/base/media_switches.h"
+
+namespace content {
+
+namespace {
+
+bool IsDefaultMediaSessionEnabled() {
+#if defined(OS_ANDROID)
+ return true;
+#else
+ return base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableDefaultMediaSession);
+#endif
+}
+
+} // anonymous namespace
+
+MediaSessionControllersManager::MediaSessionControllersManager(
+ MediaWebContentsObserver* media_web_contents_observer)
+ : media_web_contents_observer_(media_web_contents_observer) {
+}
+
+MediaSessionControllersManager::~MediaSessionControllersManager() = default;
+
+void MediaSessionControllersManager::RenderFrameDeleted(
+ RenderFrameHost* render_frame_host) {
+ if (!IsDefaultMediaSessionEnabled())
+ return;
+
+ for (auto it = controllers_map_.begin(); it != controllers_map_.end();) {
+ if (it->first.first == render_frame_host)
+ it = controllers_map_.erase(it);
+ else
+ ++it;
+ }
+}
+
+bool MediaSessionControllersManager::RequestPlay(const MediaPlayerId& id,
+ bool has_audio, bool is_remote, base::TimeDelta duration) {
+ if (!IsDefaultMediaSessionEnabled())
+ return true;
+
+ // Since we don't remove session instances on pause, there may be an existing
+ // instance for this playback attempt.
+ //
+ // In this case, try to reinitialize it with the new settings. If they are
+ // the same, this is a no-op. If the reinitialize fails, destroy the
+ // controller. A later playback attempt will create a new controller.
+ auto it = controllers_map_.find(id);
+ if (it != controllers_map_.end()) {
+ if (it->second->Initialize(has_audio, is_remote, duration))
+ return true;
+ controllers_map_.erase(it);
+ return false;
+ }
+
+ std::unique_ptr<MediaSessionController> controller(
+ new MediaSessionController(id, media_web_contents_observer_));
+
+ if (!controller->Initialize(has_audio, is_remote, duration))
+ return false;
+
+ controllers_map_[id] = std::move(controller);
+ return true;
+}
+
+void MediaSessionControllersManager::OnPause(const MediaPlayerId& id) {
+ if (!IsDefaultMediaSessionEnabled())
+ return;
+
+ auto it = controllers_map_.find(id);
+ if (it == controllers_map_.end())
+ return;
+
+ it->second->OnPlaybackPaused();
+}
+
+void MediaSessionControllersManager::OnEnd(const MediaPlayerId& id) {
+ if (!IsDefaultMediaSessionEnabled())
+ return;
+ controllers_map_.erase(id);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/session/media_session_controllers_manager.h b/chromium/content/browser/media/session/media_session_controllers_manager.h
new file mode 100644
index 00000000000..f89898ac231
--- /dev/null
+++ b/chromium/content/browser/media/session/media_session_controllers_manager.h
@@ -0,0 +1,63 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_CONTROLLERS_MANAGER_H_
+#define CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_CONTROLLERS_MANAGER_H_
+
+#include <map>
+#include <memory>
+#include <utility>
+
+#include "base/macros.h"
+#include "base/time/time.h"
+#include "content/public/browser/web_contents_observer.h" // For MediaPlayerId.
+
+namespace content {
+
+class MediaSessionController;
+class MediaWebContentsObserver;
+class RenderFrameHost;
+
+// MediaSessionControllersManager is a delegate of MediaWebContentsObserver that
+// handles MediaSessionController instances.
+class MediaSessionControllersManager {
+ public:
+ using MediaPlayerId = WebContentsObserver::MediaPlayerId;
+
+ explicit MediaSessionControllersManager(
+ MediaWebContentsObserver* media_web_contents_observer);
+ ~MediaSessionControllersManager();
+
+ // Clear all the MediaSessionController associated with the given
+ // |render_frame_host|.
+ void RenderFrameDeleted(RenderFrameHost* render_frame_host);
+
+ // Called before a player starts playing. It will be added to the media
+ // session and will have a controller associated with it.
+ // Returns whether the player was added to the session and can start playing.
+ bool RequestPlay(const MediaPlayerId& id,
+ bool has_audio,
+ bool is_remote,
+ base::TimeDelta duration);
+
+ // Called when the given player |id| has paused.
+ void OnPause(const MediaPlayerId& id);
+
+ // Called when the given player |id| has ended.
+ void OnEnd(const MediaPlayerId& id);
+
+ private:
+ // Weak pointer because |this| is owned by |media_web_contents_observer_|.
+ MediaWebContentsObserver* const media_web_contents_observer_;
+
+ using ControllersMap =
+ std::map<MediaPlayerId, std::unique_ptr<MediaSessionController>>;
+ ControllersMap controllers_map_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaSessionControllersManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_CONTROLLERS_MANAGER_H_
diff --git a/chromium/content/browser/media/session/media_session_delegate.h b/chromium/content/browser/media/session/media_session_delegate.h
new file mode 100644
index 00000000000..bc61e043d31
--- /dev/null
+++ b/chromium/content/browser/media/session/media_session_delegate.h
@@ -0,0 +1,26 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_DELEGATE_H_
+#define CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_DELEGATE_H_
+
+#include "content/browser/media/session/media_session.h"
+
+namespace content {
+
+// MediaSessionDelegate is an interface abstracting audio focus handling for the
+// MediaSession class.
+class MediaSessionDelegate {
+ public:
+ // Factory method returning an implementation of MediaSessionDelegate.
+ static std::unique_ptr<MediaSessionDelegate> Create(
+ MediaSession* media_session);
+
+ virtual bool RequestAudioFocus(MediaSession::Type type) = 0;
+ virtual void AbandonAudioFocus() = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_DELEGATE_H_
diff --git a/chromium/content/browser/media/session/media_session_delegate_android.cc b/chromium/content/browser/media/session/media_session_delegate_android.cc
new file mode 100644
index 00000000000..ddcd2865a45
--- /dev/null
+++ b/chromium/content/browser/media/session/media_session_delegate_android.cc
@@ -0,0 +1,95 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/session/media_session_delegate_android.h"
+
+#include "base/android/context_utils.h"
+#include "base/android/jni_android.h"
+#include "jni/MediaSessionDelegate_jni.h"
+
+namespace content {
+
+// static
+bool MediaSessionDelegateAndroid::Register(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+MediaSessionDelegateAndroid::MediaSessionDelegateAndroid(
+ MediaSession* media_session)
+ : media_session_(media_session) {
+}
+
+MediaSessionDelegateAndroid::~MediaSessionDelegateAndroid() {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ DCHECK(env);
+ Java_MediaSessionDelegate_tearDown(env, j_media_session_delegate_.obj());
+}
+
+void MediaSessionDelegateAndroid::Initialize() {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ DCHECK(env);
+ j_media_session_delegate_.Reset(Java_MediaSessionDelegate_create(
+ env,
+ base::android::GetApplicationContext(),
+ reinterpret_cast<intptr_t>(this)));
+}
+
+bool MediaSessionDelegateAndroid::RequestAudioFocus(MediaSession::Type type) {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ DCHECK(env);
+ return Java_MediaSessionDelegate_requestAudioFocus(
+ env, j_media_session_delegate_.obj(),
+ type == MediaSession::Type::Transient);
+}
+
+void MediaSessionDelegateAndroid::AbandonAudioFocus() {
+ JNIEnv* env = base::android::AttachCurrentThread();
+ DCHECK(env);
+ Java_MediaSessionDelegate_abandonAudioFocus(
+ env, j_media_session_delegate_.obj());
+}
+
+void MediaSessionDelegateAndroid::OnSuspend(
+ JNIEnv*, const JavaParamRef<jobject>&, jboolean temporary) {
+ // TODO(mlamouri): this check makes it so that if a MediaSession is paused and
+ // then loses audio focus, it will still stay in the Suspended state.
+ // See https://crbug.com/539998
+ if (!media_session_->IsActive())
+ return;
+
+ if (temporary) {
+ media_session_->Suspend(MediaSession::SuspendType::SYSTEM);
+ } else {
+ media_session_->Stop(MediaSession::SuspendType::SYSTEM);
+ }
+}
+
+void MediaSessionDelegateAndroid::OnResume(
+ JNIEnv*, const JavaParamRef<jobject>&) {
+ if (!media_session_->IsReallySuspended())
+ return;
+
+ media_session_->Resume(MediaSession::SuspendType::SYSTEM);
+}
+
+void MediaSessionDelegateAndroid::OnSetVolumeMultiplier(
+ JNIEnv*, jobject, jdouble volume_multiplier) {
+ media_session_->SetVolumeMultiplier(volume_multiplier);
+}
+
+void MediaSessionDelegateAndroid::RecordSessionDuck(
+ JNIEnv*, const JavaParamRef<jobject>&) {
+ media_session_->RecordSessionDuck();
+}
+
+// static
+std::unique_ptr<MediaSessionDelegate> MediaSessionDelegate::Create(
+ MediaSession* media_session) {
+ MediaSessionDelegateAndroid* delegate =
+ new MediaSessionDelegateAndroid(media_session);
+ delegate->Initialize();
+ return std::unique_ptr<MediaSessionDelegate>(delegate);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/session/media_session_delegate_android.h b/chromium/content/browser/media/session/media_session_delegate_android.h
new file mode 100644
index 00000000000..99d5b1a1094
--- /dev/null
+++ b/chromium/content/browser/media/session/media_session_delegate_android.h
@@ -0,0 +1,59 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_DELEGATE_ANDROID_H_
+#define CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_DELEGATE_ANDROID_H_
+
+#include <jni.h>
+
+#include "base/android/scoped_java_ref.h"
+#include "content/browser/media/session/media_session_delegate.h"
+
+namespace content {
+
+// MediaSessionDelegateAndroid handles the audio focus at a system level on
+// Android. It is also proxying the JNI calls.
+class MediaSessionDelegateAndroid : public MediaSessionDelegate {
+ public:
+ static bool Register(JNIEnv* env);
+
+ explicit MediaSessionDelegateAndroid(MediaSession* media_session);
+ ~MediaSessionDelegateAndroid();
+
+ void Initialize();
+
+ bool RequestAudioFocus(MediaSession::Type type) override;
+ void AbandonAudioFocus() override;
+
+ // Called when the Android system requests the MediaSession to be suspended.
+ // Called by Java through JNI.
+ void OnSuspend(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj,
+ jboolean temporary);
+
+ // Called when the Android system requests the MediaSession to be resumed.
+ // Called by Java through JNI.
+ void OnResume(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
+
+ // Called when the Android system requests the MediaSession to duck.
+ // Called by Java through JNI.
+ void OnSetVolumeMultiplier(JNIEnv* env, jobject obj,
+ jdouble volume_multiplier);
+
+ // Called when the Android system requests the MediaSession to duck.
+ // Called by Java through JNI.
+ void RecordSessionDuck(JNIEnv* env,
+ const base::android::JavaParamRef<jobject> &obj);
+
+ private:
+ // Weak pointer because |this| is owned by |media_session_|.
+ MediaSession* media_session_;
+ base::android::ScopedJavaGlobalRef<jobject> j_media_session_delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaSessionDelegateAndroid);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_DELEGATE_ANDROID_H_
diff --git a/chromium/content/browser/media/session/media_session_delegate_android_browsertest.cc b/chromium/content/browser/media/session/media_session_delegate_android_browsertest.cc
new file mode 100644
index 00000000000..cfc844c406a
--- /dev/null
+++ b/chromium/content/browser/media/session/media_session_delegate_android_browsertest.cc
@@ -0,0 +1,65 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/command_line.h"
+#include "base/run_loop.h"
+#include "content/browser/media/session/media_session.h"
+#include "content/browser/media/session/mock_media_session_observer.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/shell/browser/shell.h"
+
+namespace content {
+
+class MediaSessionDelegateAndroidBrowserTest : public ContentBrowserTest {};
+
+// MAYBE_OnAudioFocusChangeAfterDtorCrash will hit a DCHECK before the crash, it
+// is the only way found to actually reproduce the crash so as a result, the
+// test will only run on builds without DCHECK's.
+// TODO(mlamouri): the test is flaky on one bot. It is disabled until the cause
+// is found.
+#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
+#define MAYBE_OnAudioFocusChangeAfterDtorCrash \
+ DISABLED_OnAudioFocusChangeAfterDtorCrash
+#else
+#define MAYBE_OnAudioFocusChangeAfterDtorCrash \
+ DISABLED_OnAudioFocusChangeAfterDtorCrash
+#endif
+
+IN_PROC_BROWSER_TEST_F(MediaSessionDelegateAndroidBrowserTest,
+ MAYBE_OnAudioFocusChangeAfterDtorCrash) {
+ scoped_ptr<MockMediaSessionObserver> media_session_observer(
+ new MockMediaSessionObserver);
+
+ MediaSession* media_session = MediaSession::Get(shell()->web_contents());
+ ASSERT_TRUE(media_session);
+
+ WebContents* other_web_contents = CreateBrowser()->web_contents();
+ MediaSession* other_media_session = MediaSession::Get(other_web_contents);
+ ASSERT_TRUE(other_media_session);
+
+ media_session_observer->StartNewPlayer();
+ media_session->AddPlayer(media_session_observer.get(), 0,
+ MediaSession::Type::Content);
+ EXPECT_TRUE(media_session->IsActive());
+ EXPECT_FALSE(other_media_session->IsActive());
+
+ media_session_observer->StartNewPlayer();
+ other_media_session->AddPlayer(media_session_observer.get(), 1,
+ MediaSession::Type::Content);
+ EXPECT_TRUE(media_session->IsActive());
+ EXPECT_TRUE(other_media_session->IsActive());
+
+ shell()->CloseAllWindows();
+
+ // Give some time to the AudioFocusManager to send an audioFocusChange message
+ // to the listeners. If the bug is still present, it will crash.
+ {
+ base::RunLoop run_loop;
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE, run_loop.QuitClosure(), base::TimeDelta::FromSeconds(1));
+ run_loop.Run();
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/session/media_session_delegate_default.cc b/chromium/content/browser/media/session/media_session_delegate_default.cc
new file mode 100644
index 00000000000..688ce53d14f
--- /dev/null
+++ b/chromium/content/browser/media/session/media_session_delegate_default.cc
@@ -0,0 +1,62 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/session/media_session_delegate.h"
+
+#include "base/command_line.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "media/base/media_switches.h"
+
+namespace content {
+
+namespace {
+
+// MediaSessionDelegateDefault is the default implementation of
+// MediaSessionDelegate which only handles audio focus between WebContents.
+class MediaSessionDelegateDefault : public MediaSessionDelegate {
+ public:
+ explicit MediaSessionDelegateDefault(MediaSession* media_session);
+
+ // MediaSessionDelegate implementation.
+ bool RequestAudioFocus(MediaSession::Type type) override;
+ void AbandonAudioFocus() override;
+
+ private:
+ // Weak pointer because |this| is owned by |media_session_|.
+ MediaSession* media_session_;
+};
+
+} // anonymous namespace
+
+MediaSessionDelegateDefault::MediaSessionDelegateDefault(
+ MediaSession* media_session)
+ : media_session_(media_session) {
+}
+
+bool MediaSessionDelegateDefault::RequestAudioFocus(MediaSession::Type) {
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableDefaultMediaSession)) {
+ return true;
+ }
+
+ for (WebContentsImpl* web_contents : WebContentsImpl::GetAllWebContents()) {
+ MediaSession* media_session = MediaSession::Get(web_contents);
+ if (media_session == media_session_ || !media_session->IsActive())
+ continue;
+ media_session->Suspend(MediaSession::SuspendType::SYSTEM);
+ }
+ return true;
+}
+
+void MediaSessionDelegateDefault::AbandonAudioFocus() {
+}
+
+// static
+std::unique_ptr<MediaSessionDelegate> MediaSessionDelegate::Create(
+ MediaSession* media_session) {
+ return std::unique_ptr<MediaSessionDelegate>(
+ new MediaSessionDelegateDefault(media_session));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/session/media_session_delegate_default_browsertest.cc b/chromium/content/browser/media/session/media_session_delegate_default_browsertest.cc
new file mode 100644
index 00000000000..cc269269ded
--- /dev/null
+++ b/chromium/content/browser/media/session/media_session_delegate_default_browsertest.cc
@@ -0,0 +1,49 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/command_line.h"
+#include "content/browser/media/session/media_session.h"
+#include "content/browser/media/session/mock_media_session_observer.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/shell/browser/shell.h"
+#include "media/base/media_switches.h"
+
+namespace content {
+
+class MediaSessionDelegateDefaultBrowserTest : public ContentBrowserTest {
+ protected:
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ command_line->AppendSwitch(switches::kEnableDefaultMediaSession);
+ }
+};
+
+IN_PROC_BROWSER_TEST_F(MediaSessionDelegateDefaultBrowserTest,
+ ActiveWebContentsPauseOthers) {
+ std::unique_ptr<MockMediaSessionObserver> media_session_observer(
+ new MockMediaSessionObserver);
+
+ MediaSession* media_session = MediaSession::Get(shell()->web_contents());
+ ASSERT_TRUE(media_session);
+
+ WebContents* other_web_contents = CreateBrowser()->web_contents();
+ MediaSession* other_media_session = MediaSession::Get(other_web_contents);
+ ASSERT_TRUE(other_media_session);
+
+ media_session_observer->StartNewPlayer();
+ media_session->AddPlayer(
+ media_session_observer.get(), 0, MediaSession::Type::Content);
+ EXPECT_TRUE(media_session->IsActive());
+ EXPECT_FALSE(other_media_session->IsActive());
+
+ media_session_observer->StartNewPlayer();
+ other_media_session->AddPlayer(
+ media_session_observer.get(), 1, MediaSession::Type::Content);
+ EXPECT_FALSE(media_session->IsActive());
+ EXPECT_TRUE(other_media_session->IsActive());
+
+ media_session->Stop(MediaSession::SuspendType::UI);
+ other_media_session->Stop(MediaSession::SuspendType::UI);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/android/media_session_observer.h b/chromium/content/browser/media/session/media_session_observer.h
index 6316ab6043c..4d9f4d498c2 100644
--- a/chromium/content/browser/media/android/media_session_observer.h
+++ b/chromium/content/browser/media/session/media_session_observer.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_MEDIA_ANDROID_MEDIA_SESSION_OBSERVER_H_
-#define CONTENT_BROWSER_MEDIA_ANDROID_MEDIA_SESSION_OBSERVER_H_
+#ifndef CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_OBSERVER_H_
+#define CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_OBSERVER_H_
namespace content {
@@ -17,8 +17,13 @@ class MediaSessionObserver {
// The given |player_id| has been resumed by the MediaSession.
virtual void OnResume(int player_id) = 0;
+
+ // The given |player_id| has been set a new volume multiplier by
+ // the MediaSession.
+ virtual void OnSetVolumeMultiplier(int player_id,
+ double volume_multiplier) = 0;
};
} // namespace content
-#endif // CONTENT_BROWSER_MEDIA_ANDROID_MEDIA_SESSION_OBSERVER_H_
+#endif // CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_OBSERVER_H_
diff --git a/chromium/content/browser/media/android/media_session_uma_helper.cc b/chromium/content/browser/media/session/media_session_uma_helper.cc
index 35e79dd9d5d..17a43b03a1f 100644
--- a/chromium/content/browser/media/android/media_session_uma_helper.cc
+++ b/chromium/content/browser/media/session/media_session_uma_helper.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/media/android/media_session_uma_helper.h"
+#include "content/browser/media/session/media_session_uma_helper.h"
#include <utility>
@@ -59,7 +59,7 @@ void MediaSessionUmaHelper::OnSessionInactive() {
}
void MediaSessionUmaHelper::SetClockForTest(
- scoped_ptr<base::Clock> testing_clock) {
+ std::unique_ptr<base::Clock> testing_clock) {
clock_ = std::move(testing_clock);
}
diff --git a/chromium/content/browser/media/android/media_session_uma_helper.h b/chromium/content/browser/media/session/media_session_uma_helper.h
index 69fbaa9363f..290c3b94a4c 100644
--- a/chromium/content/browser/media/android/media_session_uma_helper.h
+++ b/chromium/content/browser/media/session/media_session_uma_helper.h
@@ -2,10 +2,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_MEDIA_ANDROID_MEDIA_SESSION_UMA_HELPER_H_
-#define CONTENT_BROWSER_MEDIA_ANDROID_MEDIA_SESSION_UMA_HELPER_H_
+#ifndef CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_UMA_HELPER_H_
+#define CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_UMA_HELPER_H_
+
+#include <memory>
-#include "base/memory/scoped_ptr.h"
#include "base/time/clock.h"
#include "content/common/content_export.h"
@@ -24,6 +25,7 @@ class CONTENT_EXPORT MediaSessionUmaHelper {
SystemPermanent = 1,
UI = 2,
CONTENT = 3,
+ SystemTransientDuck = 4,
Count // Leave at the end.
};
@@ -39,14 +41,14 @@ class CONTENT_EXPORT MediaSessionUmaHelper {
void OnSessionSuspended();
void OnSessionInactive();
- void SetClockForTest(scoped_ptr<base::Clock> testing_clock);
+ void SetClockForTest(std::unique_ptr<base::Clock> testing_clock);
private:
base::TimeDelta total_active_time_;
base::Time current_active_time_;
- scoped_ptr<base::Clock> clock_;
+ std::unique_ptr<base::Clock> clock_;
};
} // namespace content
-#endif // CONTENT_BROWSER_MEDIA_ANDROID_MEDIA_SESSION_UMA_HELPER_H_
+#endif // CONTENT_BROWSER_MEDIA_SESSION_MEDIA_SESSION_UMA_HELPER_H_
diff --git a/chromium/content/browser/media/android/media_session_uma_helper_unittest.cc b/chromium/content/browser/media/session/media_session_uma_helper_unittest.cc
index c4b3fc3d7d0..de9b2df2e76 100644
--- a/chromium/content/browser/media/android/media_session_uma_helper_unittest.cc
+++ b/chromium/content/browser/media/session/media_session_uma_helper_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/media/android/media_session_uma_helper.h"
+#include "content/browser/media/session/media_session_uma_helper.h"
#include "base/metrics/histogram_samples.h"
#include "base/test/histogram_tester.h"
@@ -24,7 +24,7 @@ class MediaSessionUmaHelperTest : public testing::Test {
clock_ = new base::SimpleTestClock();
clock_->SetNow(base::Time::Now());
media_session_uma_helper_.SetClockForTest(
- scoped_ptr<base::SimpleTestClock>(clock_));
+ std::unique_ptr<base::SimpleTestClock>(clock_));
}
void TearDown() override {
@@ -37,7 +37,7 @@ class MediaSessionUmaHelperTest : public testing::Test {
return media_session_uma_helper_;
};
- scoped_ptr<base::HistogramSamples> GetHistogramSamplesSinceTestStart(
+ std::unique_ptr<base::HistogramSamples> GetHistogramSamplesSinceTestStart(
const std::string& name) {
return histogram_tester_.GetHistogramSamplesSinceCreation(name);
}
@@ -57,13 +57,13 @@ TEST_F(MediaSessionUmaHelperTest, CreateAndKillDoesNothing) {
}
{
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart("Media.Session.Suspended"));
EXPECT_EQ(0, samples->TotalCount());
}
{
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart("Media.Session.ActiveTime"));
EXPECT_EQ(0, samples->TotalCount());
}
@@ -73,7 +73,7 @@ TEST_F(MediaSessionUmaHelperTest, SuspendRegisterImmediately) {
media_session_uma_helper().RecordSessionSuspended(
MediaSessionSuspendedSource::SystemTransient);
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart("Media.Session.Suspended"));
EXPECT_EQ(1, samples->TotalCount());
EXPECT_EQ(1, samples->GetCount(0)); // System Transient
@@ -89,7 +89,7 @@ TEST_F(MediaSessionUmaHelperTest, MultipleSuspend) {
media_session_uma_helper().RecordSessionSuspended(
MediaSessionSuspendedSource::UI);
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart("Media.Session.Suspended"));
EXPECT_EQ(3, samples->TotalCount());
EXPECT_EQ(1, samples->GetCount(0)); // System Transient
@@ -111,7 +111,7 @@ TEST_F(MediaSessionUmaHelperTest, MultipleSuspendSame) {
media_session_uma_helper().RecordSessionSuspended(
MediaSessionSuspendedSource::UI);
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart("Media.Session.Suspended"));
EXPECT_EQ(6, samples->TotalCount());
EXPECT_EQ(2, samples->GetCount(0)); // System Transient
@@ -123,7 +123,7 @@ TEST_F(MediaSessionUmaHelperTest, ActivationNotTerminatedDoesNotCommit) {
media_session_uma_helper().OnSessionActive();
clock()->Advance(base::TimeDelta::FromMilliseconds(1000));
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart("Media.Session.ActiveTime"));
EXPECT_EQ(0, samples->TotalCount());
}
@@ -134,7 +134,7 @@ TEST_F(MediaSessionUmaHelperTest, SuspendActivationNotTerminatedDoesNotCommit) {
clock()->Advance(base::TimeDelta::FromMilliseconds(1000));
media_session_uma_helper().OnSessionSuspended();
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart("Media.Session.ActiveTime"));
EXPECT_EQ(0, samples->TotalCount());
}
@@ -145,7 +145,7 @@ TEST_F(MediaSessionUmaHelperTest, FullActivation) {
clock()->Advance(base::TimeDelta::FromMilliseconds(1000));
media_session_uma_helper().OnSessionInactive();
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart("Media.Session.ActiveTime"));
EXPECT_EQ(1, samples->TotalCount());
EXPECT_EQ(1, samples->GetCount(1000));
@@ -163,7 +163,7 @@ TEST_F(MediaSessionUmaHelperTest, ActivationCycleWithSuspend) {
clock()->Advance(base::TimeDelta::FromMilliseconds(1000));
media_session_uma_helper().OnSessionInactive();
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart("Media.Session.ActiveTime"));
EXPECT_EQ(1, samples->TotalCount());
EXPECT_EQ(1, samples->GetCount(2000));
@@ -187,7 +187,7 @@ TEST_F(MediaSessionUmaHelperTest, ActivationCycleWithMultipleSuspend) {
clock()->Advance(base::TimeDelta::FromMilliseconds(1000));
media_session_uma_helper().OnSessionInactive();
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart("Media.Session.ActiveTime"));
EXPECT_EQ(1, samples->TotalCount());
EXPECT_EQ(1, samples->GetCount(3000));
@@ -222,7 +222,7 @@ TEST_F(MediaSessionUmaHelperTest, MultipleActivations) {
clock()->Advance(base::TimeDelta::FromMilliseconds(1000));
media_session_uma_helper().OnSessionInactive();
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart("Media.Session.ActiveTime"));
EXPECT_EQ(2, samples->TotalCount());
EXPECT_EQ(1, samples->GetCount(2000));
@@ -243,7 +243,7 @@ TEST_F(MediaSessionUmaHelperTest, MultipleActivationCalls) {
// Calling OnSessionActive() multiple times reset the start time of the
// session.
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart("Media.Session.ActiveTime"));
EXPECT_EQ(1, samples->TotalCount());
EXPECT_EQ(1, samples->GetCount(500));
@@ -265,7 +265,7 @@ TEST_F(MediaSessionUmaHelperTest, MultipleSuspendCalls_WhileSuspended) {
// If the session is already suspended, OnSessionSuspended() calls are
// ignored.
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart("Media.Session.ActiveTime"));
EXPECT_EQ(1, samples->TotalCount());
EXPECT_EQ(1, samples->GetCount(1000));
@@ -287,7 +287,7 @@ TEST_F(MediaSessionUmaHelperTest, MultipleSuspendCalls_WhileInactive) {
// If the session is already inactive, OnSessionSuspended() calls are
// ignored.
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart("Media.Session.ActiveTime"));
EXPECT_EQ(1, samples->TotalCount());
EXPECT_EQ(1, samples->GetCount(1000));
@@ -306,7 +306,7 @@ TEST_F(MediaSessionUmaHelperTest, MultipleInactiveCalls) {
media_session_uma_helper().OnSessionInactive();
// If the session is already inactive, OnSessionInactive() calls are ignored.
- scoped_ptr<base::HistogramSamples> samples(
+ std::unique_ptr<base::HistogramSamples> samples(
GetHistogramSamplesSinceTestStart("Media.Session.ActiveTime"));
EXPECT_EQ(1, samples->TotalCount());
EXPECT_EQ(1, samples->GetCount(3000));
diff --git a/chromium/content/browser/media/session/media_session_visibility_browsertest.cc b/chromium/content/browser/media/session/media_session_visibility_browsertest.cc
new file mode 100644
index 00000000000..f83cd858081
--- /dev/null
+++ b/chromium/content/browser/media/session/media_session_visibility_browsertest.cc
@@ -0,0 +1,266 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/command_line.h"
+#include "content/browser/media/session/media_session.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
+#include "content/shell/browser/shell.h"
+#include "media/base/media_switches.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+namespace {
+static const char kStartPlayerScript[] =
+ "document.getElementById('long-video').play()";
+static const char kPausePlayerScript[] =
+ "document.getElementById('long-video').pause()";
+}
+
+
+// Base class of MediaSession visibility tests. The class is intended
+// to be used to run tests under different configurations. Tests
+// should inheret from this class, set up their own command line per
+// their configuration, and use macro INCLUDE_TEST_FROM_BASE_CLASS to
+// include required tests. See
+// media_session_visibility_browsertest_instances.cc for examples.
+class MediaSessionVisibilityBrowserTest
+ : public ContentBrowserTest {
+ public:
+ MediaSessionVisibilityBrowserTest() = default;
+ ~MediaSessionVisibilityBrowserTest() override = default;
+
+ void SetUpOnMainThread() override {
+ ContentBrowserTest::SetUpOnMainThread();
+ web_contents_ = shell()->web_contents();
+ media_session_ = MediaSession::Get(web_contents_);
+
+ media_session_state_loop_runners_[MediaSession::State::ACTIVE] =
+ new MessageLoopRunner();
+ media_session_state_loop_runners_[MediaSession::State::SUSPENDED] =
+ new MessageLoopRunner();
+ media_session_state_loop_runners_[MediaSession::State::INACTIVE] =
+ new MessageLoopRunner();
+ media_session_state_callback_subscription_ =
+ media_session_->RegisterMediaSessionStateChangedCallbackForTest(
+ base::Bind(&MediaSessionVisibilityBrowserTest::
+ OnMediaSessionStateChanged,
+ base::Unretained(this)));
+ }
+
+ void TearDownOnMainThread() override {
+ // Unsubscribe the callback subscription before tearing down, so that the
+ // CallbackList in MediaSession will be empty when it is destroyed.
+ media_session_state_callback_subscription_.reset();
+ }
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ command_line->AppendSwitch(
+ switches::kDisableGestureRequirementForMediaPlayback);
+#if !defined(OS_ANDROID)
+ command_line->AppendSwitch(
+ switches::kEnableDefaultMediaSession);
+#endif // !defined(OS_ANDROID)
+ }
+
+ void LoadTestPage() {
+ TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
+ shell()->LoadURL(GetTestUrl("media/session", "media-session.html"));
+ navigation_observer.Wait();
+ }
+
+ void RunScript(const std::string& script) {
+ ASSERT_TRUE(ExecuteScript(web_contents_->GetMainFrame(), script));
+ }
+
+ void ClearMediaSessionStateLoopRunners() {
+ for (auto& state_loop_runner : media_session_state_loop_runners_)
+ state_loop_runner.second = new MessageLoopRunner();
+ }
+
+ void OnMediaSessionStateChanged(MediaSession::State state) {
+ ASSERT_TRUE(media_session_state_loop_runners_.count(state));
+ media_session_state_loop_runners_[state]->Quit();
+ }
+
+ // TODO(zqzhang): This method is shared with
+ // MediaRouterIntegrationTests. Move it into a general place.
+ void Wait(base::TimeDelta timeout) {
+ base::RunLoop run_loop;
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE, run_loop.QuitClosure(), timeout);
+ run_loop.Run();
+ }
+
+ void WaitForMediaSessionState(MediaSession::State state) {
+ ASSERT_TRUE(media_session_state_loop_runners_.count(state));
+ media_session_state_loop_runners_[state]->Run();
+ }
+
+ protected:
+ void TestSessionInactiveWhenHiddenAfterContentPause() {
+ LoadTestPage();
+
+ ClearMediaSessionStateLoopRunners();
+ RunScript(kStartPlayerScript);
+ WaitForMediaSessionState(MediaSession::State::ACTIVE);
+
+ ClearMediaSessionStateLoopRunners();
+ RunScript(kPausePlayerScript);
+ WaitForMediaSessionState(MediaSession::State::SUSPENDED);
+
+ ClearMediaSessionStateLoopRunners();
+ web_contents_->WasHidden();
+ WaitForMediaSessionState(MediaSession::State::INACTIVE);
+ }
+
+ void TestSessionInactiveWhenHiddenWhilePlaying() {
+ LoadTestPage();
+
+ ClearMediaSessionStateLoopRunners();
+ RunScript(kStartPlayerScript);
+ WaitForMediaSessionState(MediaSession::State::ACTIVE);
+
+ ClearMediaSessionStateLoopRunners();
+ web_contents_->WasHidden();
+ WaitForMediaSessionState(MediaSession::State::INACTIVE);
+ }
+
+ void TestSessionSuspendedWhenHiddenAfterContentPause() {
+ LoadTestPage();
+
+ ClearMediaSessionStateLoopRunners();
+ RunScript(kStartPlayerScript);
+ WaitForMediaSessionState(MediaSession::State::ACTIVE);
+
+ ClearMediaSessionStateLoopRunners();
+ RunScript(kPausePlayerScript);
+ WaitForMediaSessionState(MediaSession::State::SUSPENDED);
+
+ // Wait for 1 second and check the MediaSession state.
+ // No better solution till now.
+ web_contents_->WasHidden();
+ Wait(base::TimeDelta::FromSeconds(1));
+ ASSERT_EQ(media_session_->audio_focus_state_,
+ MediaSession::State::SUSPENDED);
+ }
+
+ void TestSessionActiveWhenHiddenWhilePlaying() {
+ LoadTestPage();
+
+ ClearMediaSessionStateLoopRunners();
+ RunScript(kStartPlayerScript);
+ WaitForMediaSessionState(MediaSession::State::ACTIVE);
+
+ // Wait for 1 second and check the MediaSession state.
+ // No better solution till now.
+ web_contents_->WasHidden();
+ Wait(base::TimeDelta::FromSeconds(1));
+ ASSERT_EQ(media_session_->audio_focus_state_,
+ MediaSession::State::ACTIVE);
+ }
+
+ WebContents* web_contents_;
+ MediaSession* media_session_;
+ // MessageLoopRunners for waiting MediaSession state to change. Note that the
+ // MessageLoopRunners can accept Quit() before calling Run(), thus the state
+ // change can still be captured before waiting. For example, the MediaSession
+ // might go active immediately after calling HTMLMediaElement.play(). A test
+ // can listen to the state change before calling play(), and then wait for the
+ // state change after play().
+ std::map<MediaSession::State, scoped_refptr<MessageLoopRunner> >
+ media_session_state_loop_runners_;
+ std::unique_ptr<base::CallbackList<void(MediaSession::State)>::Subscription>
+ media_session_state_callback_subscription_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MediaSessionVisibilityBrowserTest);
+};
+
+// Helper macro to include tests from the base class.
+#define INCLUDE_TEST_FROM_BASE_CLASS(test_fixture, test_name) \
+ IN_PROC_BROWSER_TEST_F(test_fixture, test_name) { \
+ test_name(); \
+ }
+
+///////////////////////////////////////////////////////////////////////////////
+// Configuration instances.
+
+// UnifiedPipeline + SuspendOnHide
+class MediaSessionVisibilityBrowserTest_UnifiedPipeline_SuspendOnHide :
+ public MediaSessionVisibilityBrowserTest {
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ MediaSessionVisibilityBrowserTest::SetUpCommandLine(command_line);
+#if !defined(OS_ANDROID)
+ command_line->AppendSwitch(switches::kEnableMediaSuspend);
+#endif // defined(OS_ANDROID)
+ }
+};
+
+INCLUDE_TEST_FROM_BASE_CLASS(
+ MediaSessionVisibilityBrowserTest_UnifiedPipeline_SuspendOnHide,
+ TestSessionInactiveWhenHiddenAfterContentPause)
+INCLUDE_TEST_FROM_BASE_CLASS(
+ MediaSessionVisibilityBrowserTest_UnifiedPipeline_SuspendOnHide,
+ TestSessionInactiveWhenHiddenWhilePlaying)
+
+// UnifiedPipeline + NosuspendOnHide
+class MediaSessionVisibilityBrowserTest_UnifiedPipeline_NosuspendOnHide :
+ public MediaSessionVisibilityBrowserTest {
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ MediaSessionVisibilityBrowserTest::SetUpCommandLine(command_line);
+#if defined(OS_ANDROID)
+ command_line->AppendSwitch(switches::kDisableMediaSuspend);
+#endif // defined(OS_ANDROID)
+ }
+};
+
+INCLUDE_TEST_FROM_BASE_CLASS(
+ MediaSessionVisibilityBrowserTest_UnifiedPipeline_NosuspendOnHide,
+ TestSessionSuspendedWhenHiddenAfterContentPause)
+INCLUDE_TEST_FROM_BASE_CLASS(
+ MediaSessionVisibilityBrowserTest_UnifiedPipeline_NosuspendOnHide,
+ TestSessionActiveWhenHiddenWhilePlaying)
+
+#if defined(OS_ANDROID)
+// AndroidPipeline + SuspendOnHide
+class MediaSessionVisibilityBrowserTest_AndroidPipeline_SuspendOnHide :
+ public MediaSessionVisibilityBrowserTest {
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ MediaSessionVisibilityBrowserTest::SetUpCommandLine(command_line);
+ command_line->AppendSwitch(switches::kDisableUnifiedMediaPipeline);
+ }
+};
+
+INCLUDE_TEST_FROM_BASE_CLASS(
+ MediaSessionVisibilityBrowserTest_AndroidPipeline_SuspendOnHide,
+ TestSessionInactiveWhenHiddenAfterContentPause)
+INCLUDE_TEST_FROM_BASE_CLASS(
+ MediaSessionVisibilityBrowserTest_AndroidPipeline_SuspendOnHide,
+ TestSessionInactiveWhenHiddenWhilePlaying)
+
+// AndroidPipeline + NosuspendOnHide
+class MediaSessionVisibilityBrowserTest_AndroidPipeline_NosuspendOnHide :
+ public MediaSessionVisibilityBrowserTest {
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ MediaSessionVisibilityBrowserTest::SetUpCommandLine(command_line);
+ command_line->AppendSwitch(switches::kDisableUnifiedMediaPipeline);
+ command_line->AppendSwitch(switches::kDisableMediaSuspend);
+ }
+};
+
+INCLUDE_TEST_FROM_BASE_CLASS(
+ MediaSessionVisibilityBrowserTest_AndroidPipeline_NosuspendOnHide,
+ TestSessionSuspendedWhenHiddenAfterContentPause)
+INCLUDE_TEST_FROM_BASE_CLASS(
+ MediaSessionVisibilityBrowserTest_AndroidPipeline_NosuspendOnHide,
+ TestSessionActiveWhenHiddenWhilePlaying)
+
+#endif // defined(OS_ANDROID)
+
+} // namespace content
diff --git a/chromium/content/browser/media/session/mock_media_session_observer.cc b/chromium/content/browser/media/session/mock_media_session_observer.cc
new file mode 100644
index 00000000000..edc213a1090
--- /dev/null
+++ b/chromium/content/browser/media/session/mock_media_session_observer.cc
@@ -0,0 +1,70 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/media/session/mock_media_session_observer.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+MockMediaSessionObserver::MockMediaSessionObserver() = default;
+
+MockMediaSessionObserver::~MockMediaSessionObserver() = default;
+
+void MockMediaSessionObserver::OnSuspend(int player_id) {
+ EXPECT_GE(player_id, 0);
+ EXPECT_GT(players_.size(), static_cast<size_t>(player_id));
+
+ ++received_suspend_calls_;
+ players_[player_id].is_playing_ = false;
+}
+
+void MockMediaSessionObserver::OnResume(int player_id) {
+ EXPECT_GE(player_id, 0);
+ EXPECT_GT(players_.size(), static_cast<size_t>(player_id));
+
+ ++received_resume_calls_;
+ players_[player_id].is_playing_ = true;
+}
+
+void MockMediaSessionObserver::OnSetVolumeMultiplier(
+ int player_id, double volume_multiplier) {
+ EXPECT_GE(player_id, 0);
+ EXPECT_GT(players_.size(), static_cast<size_t>(player_id));
+
+ EXPECT_GE(volume_multiplier, 0.0f);
+ EXPECT_LE(volume_multiplier, 1.0f);
+
+ players_[player_id].volume_multiplier_ = volume_multiplier;
+}
+
+int MockMediaSessionObserver::StartNewPlayer() {
+ players_.push_back(MockPlayer(true, 1.0f));
+ return players_.size() - 1;
+}
+
+bool MockMediaSessionObserver::IsPlaying(size_t player_id) {
+ EXPECT_GT(players_.size(), player_id);
+ return players_[player_id].is_playing_;
+}
+
+double MockMediaSessionObserver::GetVolumeMultiplier(size_t player_id) {
+ EXPECT_GT(players_.size(), player_id);
+ return players_[player_id].volume_multiplier_;
+}
+
+void MockMediaSessionObserver::SetPlaying(size_t player_id, bool playing) {
+ EXPECT_GT(players_.size(), player_id);
+ players_[player_id].is_playing_ = playing;
+}
+
+int MockMediaSessionObserver::received_suspend_calls() const {
+ return received_suspend_calls_;
+}
+
+int MockMediaSessionObserver::received_resume_calls() const {
+ return received_resume_calls_;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/media/session/mock_media_session_observer.h b/chromium/content/browser/media/session/mock_media_session_observer.h
new file mode 100644
index 00000000000..03913bced06
--- /dev/null
+++ b/chromium/content/browser/media/session/mock_media_session_observer.h
@@ -0,0 +1,59 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+#include <vector>
+
+#include "content/browser/media/session/media_session_observer.h"
+
+namespace content {
+
+// MockMediaSessionObserver is a mock implementation of MediaSessionObserver to
+// be used in tests.
+class MockMediaSessionObserver : public MediaSessionObserver {
+ public:
+ MockMediaSessionObserver();
+ ~MockMediaSessionObserver() override;
+
+ // Implements MediaSessionObserver.
+ void OnSuspend(int player_id) override;
+ void OnResume(int player_id) override;
+ void OnSetVolumeMultiplier(int player_id, double volume_multiplier) override;
+
+ // Simulate that a new player started.
+ // Returns the player_id.
+ int StartNewPlayer();
+
+ // Returns whether |player_id| is playing.
+ bool IsPlaying(size_t player_id);
+
+ // Returns the volume multiplier of |player_id|.
+ double GetVolumeMultiplier(size_t player_id);
+
+ // Simulate a play state change for |player_id|.
+ void SetPlaying(size_t player_id, bool playing);
+
+ int received_suspend_calls() const;
+ int received_resume_calls() const;
+
+ private:
+ // Internal representation of the players to keep track of their statuses.
+ struct MockPlayer {
+ public:
+ MockPlayer(bool is_playing = true, double volume_multiplier = 1.0f)
+ : is_playing_(is_playing),
+ volume_multiplier_(volume_multiplier) {}
+ bool is_playing_;
+ double volume_multiplier_;
+ };
+
+ // Basic representation of the players. The position in the vector is the
+ // player_id. The value of the vector is the playing status and volume.
+ std::vector<MockPlayer> players_;
+
+ int received_resume_calls_ = 0;
+ int received_suspend_calls_ = 0;
+};
+
+} // namespace content
diff --git a/chromium/content/browser/media/webrtc/OWNERS b/chromium/content/browser/media/webrtc/OWNERS
new file mode 100644
index 00000000000..43cd73bcb81
--- /dev/null
+++ b/chromium/content/browser/media/webrtc/OWNERS
@@ -0,0 +1,5 @@
+perkj@chromium.org
+tommi@chromium.org
+
+# For WebRTC browser tests, etc.
+per-file *webrtc*browsertest*=phoglund@chromium.org
diff --git a/chromium/content/browser/media/webrtc_audio_debug_recordings_browsertest.cc b/chromium/content/browser/media/webrtc/webrtc_audio_debug_recordings_browsertest.cc
index f42aed10011..5fe344d8ab4 100644
--- a/chromium/content/browser/media/webrtc_audio_debug_recordings_browsertest.cc
+++ b/chromium/content/browser/media/webrtc/webrtc_audio_debug_recordings_browsertest.cc
@@ -8,7 +8,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
-#include "content/browser/media/webrtc_internals.h"
+#include "content/browser/media/webrtc/webrtc_internals.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test_utils.h"
@@ -59,7 +59,7 @@ base::FilePath GetExpectedInputAudioFileName(const base::FilePath& base_file,
return base_file.AddExtension(IntToStringType(render_process_id))
.AddExtension(FILE_PATH_LITERAL("source_input"))
.AddExtension(IntToStringType(kExpectedStreamId))
- .AddExtension(FILE_PATH_LITERAL("pcm"));
+ .AddExtension(FILE_PATH_LITERAL("wav"));
}
} // namespace
diff --git a/chromium/content/browser/media/webrtc_browsertest.cc b/chromium/content/browser/media/webrtc/webrtc_browsertest.cc
index 7dd174f7f13..7dd174f7f13 100644
--- a/chromium/content/browser/media/webrtc_browsertest.cc
+++ b/chromium/content/browser/media/webrtc/webrtc_browsertest.cc
diff --git a/chromium/content/browser/media/webrtc_getusermedia_browsertest.cc b/chromium/content/browser/media/webrtc/webrtc_getusermedia_browsertest.cc
index 0645511ffd3..73c8dc97351 100644
--- a/chromium/content/browser/media/webrtc_getusermedia_browsertest.cc
+++ b/chromium/content/browser/media/webrtc/webrtc_getusermedia_browsertest.cc
@@ -6,12 +6,13 @@
#include "base/command_line.h"
#include "base/json/json_reader.h"
+#include "base/memory/ref_counted_memory.h"
#include "base/strings/stringprintf.h"
#include "base/test/trace_event_analyzer.h"
#include "base/trace_event/trace_event_impl.h"
#include "base/values.h"
#include "build/build_config.h"
-#include "content/browser/media/webrtc_internals.h"
+#include "content/browser/media/webrtc/webrtc_internals.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
@@ -146,7 +147,7 @@ class WebRtcGetUserMediaBrowserTest: public WebRtcContentBrowserTest {
// would stop both this code and the browser underneath.
StopTracing();
- scoped_ptr<TraceAnalyzer> analyzer(CreateTraceAnalyzer());
+ std::unique_ptr<TraceAnalyzer> analyzer(CreateTraceAnalyzer());
analyzer->AssociateBeginEndEvents();
trace_analyzer::TraceEventVector events;
DCHECK(measure_filter.size());
@@ -204,7 +205,7 @@ class WebRtcGetUserMediaBrowserTest: public WebRtcContentBrowserTest {
int error_code;
std::string error_message;
- scoped_ptr<base::Value> value = base::JSONReader::ReadAndReturnError(
+ std::unique_ptr<base::Value> value = base::JSONReader::ReadAndReturnError(
devices_as_json, base::JSON_ALLOW_TRAILING_COMMAS, &error_code,
&error_message);
diff --git a/chromium/content/browser/media/webrtc_identity_store.cc b/chromium/content/browser/media/webrtc/webrtc_identity_store.cc
index 2ada2a15f40..0dc62e4ecda 100644
--- a/chromium/content/browser/media/webrtc_identity_store.cc
+++ b/chromium/content/browser/media/webrtc/webrtc_identity_store.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/media/webrtc_identity_store.h"
+#include "content/browser/media/webrtc/webrtc_identity_store.h"
#include <stddef.h>
#include <stdint.h>
@@ -15,7 +15,7 @@
#include "base/macros.h"
#include "base/rand_util.h"
#include "base/threading/worker_pool.h"
-#include "content/browser/media/webrtc_identity_store_backend.h"
+#include "content/browser/media/webrtc/webrtc_identity_store_backend.h"
#include "content/public/browser/browser_thread.h"
#include "crypto/rsa_private_key.h"
#include "net/base/net_errors.h"
@@ -43,7 +43,7 @@ static void GenerateIdentityWorker(const std::string& common_name,
result->error = net::OK;
int serial_number = base::RandInt(0, std::numeric_limits<int>::max());
- scoped_ptr<crypto::RSAPrivateKey> key;
+ std::unique_ptr<crypto::RSAPrivateKey> key;
base::Time now = base::Time::Now();
bool success = net::x509_util::CreateKeyAndSelfSignedCert(
"CN=" + common_name,
diff --git a/chromium/content/browser/media/webrtc_identity_store.h b/chromium/content/browser/media/webrtc/webrtc_identity_store.h
index c788d0dd70d..360171d0f90 100644
--- a/chromium/content/browser/media/webrtc_identity_store.h
+++ b/chromium/content/browser/media/webrtc/webrtc_identity_store.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_MEDIA_WEBRTC_IDENTITY_STORE_H_
-#define CONTENT_BROWSER_MEDIA_WEBRTC_IDENTITY_STORE_H_
+#ifndef CONTENT_BROWSER_MEDIA_WEBRTC_WEBRTC_IDENTITY_STORE_H_
+#define CONTENT_BROWSER_MEDIA_WEBRTC_WEBRTC_IDENTITY_STORE_H_
#include <string>
#include <vector>
@@ -123,4 +123,4 @@ class CONTENT_EXPORT WebRTCIdentityStore
} // namespace content
-#endif // CONTENT_BROWSER_MEDIA_WEBRTC_IDENTITY_STORE_H_
+#endif // CONTENT_BROWSER_MEDIA_WEBRTC_WEBRTC_IDENTITY_STORE_H_
diff --git a/chromium/content/browser/media/webrtc_identity_store_backend.cc b/chromium/content/browser/media/webrtc/webrtc_identity_store_backend.cc
index 76d4827d121..dc247b7a3a7 100644
--- a/chromium/content/browser/media/webrtc_identity_store_backend.cc
+++ b/chromium/content/browser/media/webrtc/webrtc_identity_store_backend.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/media/webrtc_identity_store_backend.h"
+#include "content/browser/media/webrtc/webrtc_identity_store_backend.h"
#include <stddef.h>
#include <stdint.h>
@@ -175,7 +175,7 @@ class WebRTCIdentityStoreBackend::SqlLiteStorage
// The file path of the DB. Empty if temporary.
base::FilePath path_;
scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
- scoped_ptr<sql::Connection> db_;
+ std::unique_ptr<sql::Connection> db_;
// Batched DB operations pending to commit.
PendingOperationList pending_operations_;
@@ -210,7 +210,7 @@ bool WebRTCIdentityStoreBackend::FindIdentity(
DCHECK_EQ(state_, NOT_STARTED);
// Kick off loading the DB.
- scoped_ptr<IdentityMap> out_map(new IdentityMap());
+ std::unique_ptr<IdentityMap> out_map(new IdentityMap());
base::Closure task(
base::Bind(&SqlLiteStorage::Load, sql_lite_storage_, out_map.get()));
// |out_map| will be NULL after this call.
@@ -346,7 +346,8 @@ void WebRTCIdentityStoreBackend::SetValidityPeriodForTesting(
WebRTCIdentityStoreBackend::~WebRTCIdentityStoreBackend() {}
-void WebRTCIdentityStoreBackend::OnLoaded(scoped_ptr<IdentityMap> out_map) {
+void WebRTCIdentityStoreBackend::OnLoaded(
+ std::unique_ptr<IdentityMap> out_map) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (state_ != LOADING)
@@ -514,7 +515,7 @@ void WebRTCIdentityStoreBackend::SqlLiteStorage::BatchOperation(
static const size_t kCommitAfterBatchSize = 512;
// We do a full copy of the cert here, and hopefully just here.
- scoped_ptr<PendingOperation> operation(
+ std::unique_ptr<PendingOperation> operation(
new PendingOperation(type, origin, identity_name, identity));
pending_operations_.push_back(operation.release());
diff --git a/chromium/content/browser/media/webrtc_identity_store_backend.h b/chromium/content/browser/media/webrtc/webrtc_identity_store_backend.h
index 906f71a6e34..e0948b7f7e4 100644
--- a/chromium/content/browser/media/webrtc_identity_store_backend.h
+++ b/chromium/content/browser/media/webrtc/webrtc_identity_store_backend.h
@@ -2,17 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_MEDIA_WEBRTC_IDENTITY_STORE_BACKEND_H_
-#define CONTENT_BROWSER_MEDIA_WEBRTC_IDENTITY_STORE_BACKEND_H_
+#ifndef CONTENT_BROWSER_MEDIA_WEBRTC_WEBRTC_IDENTITY_STORE_BACKEND_H_
+#define CONTENT_BROWSER_MEDIA_WEBRTC_WEBRTC_IDENTITY_STORE_BACKEND_H_
#include <map>
+#include <memory>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
class GURL;
@@ -102,8 +102,7 @@ class WebRTCIdentityStoreBackend
~WebRTCIdentityStoreBackend();
- void OnLoaded(scoped_ptr<IdentityMap> out_map);
-
+ void OnLoaded(std::unique_ptr<IdentityMap> out_map);
// Identities expires after |validity_period_|.
base::TimeDelta validity_period_;
@@ -120,4 +119,4 @@ class WebRTCIdentityStoreBackend
};
}
-#endif // CONTENT_BROWSER_MEDIA_WEBRTC_IDENTITY_STORE_BACKEND_H_
+#endif // CONTENT_BROWSER_MEDIA_WEBRTC_WEBRTC_IDENTITY_STORE_BACKEND_H_
diff --git a/chromium/content/browser/media/webrtc_identity_store_unittest.cc b/chromium/content/browser/media/webrtc/webrtc_identity_store_unittest.cc
index 025e2f3231b..710861c3746 100644
--- a/chromium/content/browser/media/webrtc_identity_store_unittest.cc
+++ b/chromium/content/browser/media/webrtc/webrtc_identity_store_unittest.cc
@@ -2,11 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "content/browser/media/webrtc/webrtc_identity_store.h"
+
+#include <memory>
+
#include "base/bind.h"
#include "base/files/scoped_temp_dir.h"
-#include "base/memory/scoped_ptr.h"
#include "base/test/sequenced_worker_pool_owner.h"
-#include "content/browser/media/webrtc_identity_store.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/public/test/test_utils.h"
#include "net/base/net_errors.h"
@@ -84,7 +86,7 @@ class WebRtcIdentityStoreTest : public testing::Test {
protected:
TestBrowserThreadBundle browser_thread_bundle_;
- scoped_ptr<base::SequencedWorkerPoolOwner> pool_owner_;
+ std::unique_ptr<base::SequencedWorkerPoolOwner> pool_owner_;
scoped_refptr<WebRTCIdentityStore> webrtc_identity_store_;
};
@@ -384,7 +386,7 @@ TEST_F(WebRtcIdentityStoreTest, HandleDBErrors) {
RunUntilIdle();
// Verifies the corrupted table was razed.
- scoped_ptr<sql::Connection> db(new sql::Connection());
+ std::unique_ptr<sql::Connection> db(new sql::Connection());
EXPECT_TRUE(db->Open(db_path));
EXPECT_EQ(0U, sql::test::CountSQLTables(db.get()));
diff --git a/chromium/content/browser/media/webrtc_internals.cc b/chromium/content/browser/media/webrtc/webrtc_internals.cc
index 40aa91baaec..1ebc884a5cb 100644
--- a/chromium/content/browser/media/webrtc_internals.cc
+++ b/chromium/content/browser/media/webrtc/webrtc_internals.cc
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/media/webrtc_internals.h"
+#include "content/browser/media/webrtc/webrtc_internals.h"
#include <stddef.h>
#include "base/strings/string_number_conversions.h"
#include "build/build_config.h"
-#include "content/browser/media/webrtc_internals_ui_observer.h"
+#include "content/browser/media/webrtc/webrtc_internals_ui_observer.h"
#include "content/browser/web_contents/web_contents_view.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
@@ -39,10 +39,37 @@ static base::ListValue* EnsureLogList(base::DictionaryValue* dict) {
} // namespace
-WebRTCInternals::WebRTCInternals()
+WebRTCInternals::PendingUpdate::PendingUpdate(
+ const std::string& command,
+ std::unique_ptr<base::Value> value)
+ : command_(command), value_(std::move(value)) {}
+
+WebRTCInternals::PendingUpdate::PendingUpdate(PendingUpdate&& other)
+ : command_(std::move(other.command_)),
+ value_(std::move(other.value_)) {}
+
+WebRTCInternals::PendingUpdate::~PendingUpdate() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+}
+
+const std::string& WebRTCInternals::PendingUpdate::command() const {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return command_;
+}
+
+const base::Value* WebRTCInternals::PendingUpdate::value() const {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return value_.get();
+}
+
+WebRTCInternals::WebRTCInternals() : WebRTCInternals(500) {}
+
+WebRTCInternals::WebRTCInternals(int aggregate_updates_ms)
: audio_debug_recordings_(false),
event_log_recordings_(false),
- selecting_event_log_(false) {
+ selecting_event_log_(false),
+ aggregate_updates_ms_(aggregate_updates_ms),
+ weak_factory_(this) {
// TODO(grunell): Shouldn't all the webrtc_internals* files be excluded from the
// build if WebRTC is disabled?
#if defined(ENABLE_WEBRTC)
@@ -82,9 +109,6 @@ void WebRTCInternals::OnAddPeerConnection(int render_process_id,
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::DictionaryValue* dict = new base::DictionaryValue();
- if (!dict)
- return;
-
dict->SetInteger("rid", render_process_id);
dict->SetInteger("pid", static_cast<int>(pid));
dict->SetInteger("lid", lid);
@@ -95,7 +119,7 @@ void WebRTCInternals::OnAddPeerConnection(int render_process_id,
CreateOrReleasePowerSaveBlocker();
if (observers_.might_have_observers())
- SendUpdate("addPeerConnection", dict);
+ SendUpdate("addPeerConnection", dict->CreateDeepCopy());
if (render_process_id_set_.insert(render_process_id).second) {
RenderProcessHost* host = RenderProcessHost::FromID(render_process_id);
@@ -122,10 +146,10 @@ void WebRTCInternals::OnRemovePeerConnection(ProcessId pid, int lid) {
CreateOrReleasePowerSaveBlocker();
if (observers_.might_have_observers()) {
- base::DictionaryValue id;
- id.SetInteger("pid", static_cast<int>(pid));
- id.SetInteger("lid", lid);
- SendUpdate("removePeerConnection", &id);
+ std::unique_ptr<base::DictionaryValue> id(new base::DictionaryValue());
+ id->SetInteger("pid", static_cast<int>(pid));
+ id->SetInteger("lid", lid);
+ SendUpdate("removePeerConnection", std::move(id));
}
break;
}
@@ -163,12 +187,13 @@ void WebRTCInternals::OnUpdatePeerConnection(
log->Append(log_entry);
if (observers_.might_have_observers()) {
- base::DictionaryValue update;
- update.SetInteger("pid", static_cast<int>(pid));
- update.SetInteger("lid", lid);
- update.MergeDictionary(log_entry);
+ std::unique_ptr<base::DictionaryValue> update(
+ new base::DictionaryValue());
+ update->SetInteger("pid", static_cast<int>(pid));
+ update->SetInteger("lid", lid);
+ update->MergeDictionary(log_entry);
- SendUpdate("updatePeerConnection", &update);
+ SendUpdate("updatePeerConnection", std::move(update));
}
return;
}
@@ -179,17 +204,13 @@ void WebRTCInternals::OnAddStats(base::ProcessId pid, int lid,
if (!observers_.might_have_observers())
return;
- base::DictionaryValue dict;
- dict.SetInteger("pid", static_cast<int>(pid));
- dict.SetInteger("lid", lid);
-
- base::ListValue* list = value.DeepCopy();
- if (!list)
- return;
+ std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue());
+ dict->SetInteger("pid", static_cast<int>(pid));
+ dict->SetInteger("lid", lid);
- dict.Set("reports", list);
+ dict->Set("reports", value.CreateDeepCopy());
- SendUpdate("addStats", &dict);
+ SendUpdate("addStats", std::move(dict));
}
void WebRTCInternals::OnGetUserMedia(int rid,
@@ -213,7 +234,7 @@ void WebRTCInternals::OnGetUserMedia(int rid,
get_user_media_requests_.Append(dict);
if (observers_.might_have_observers())
- SendUpdate("addGetUserMedia", dict);
+ SendUpdate("addGetUserMedia", dict->CreateDeepCopy());
if (render_process_id_set_.insert(rid).second) {
RenderProcessHost* host = RenderProcessHost::FromID(rid);
@@ -222,12 +243,12 @@ void WebRTCInternals::OnGetUserMedia(int rid,
}
}
-void WebRTCInternals::AddObserver(WebRTCInternalsUIObserver *observer) {
+void WebRTCInternals::AddObserver(WebRTCInternalsUIObserver* observer) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
observers_.AddObserver(observer);
}
-void WebRTCInternals::RemoveObserver(WebRTCInternalsUIObserver *observer) {
+void WebRTCInternals::RemoveObserver(WebRTCInternalsUIObserver* observer) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
observers_.RemoveObserver(observer);
@@ -251,8 +272,8 @@ void WebRTCInternals::UpdateObserver(WebRTCInternalsUIObserver* observer) {
void WebRTCInternals::EnableAudioDebugRecordings(
content::WebContents* web_contents) {
-#if defined(ENABLE_WEBRTC)
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+#if defined(ENABLE_WEBRTC)
#if defined(OS_ANDROID)
EnableAudioDebugRecordingsOnAllRenderProcessHosts();
#else
@@ -273,8 +294,8 @@ void WebRTCInternals::EnableAudioDebugRecordings(
}
void WebRTCInternals::DisableAudioDebugRecordings() {
-#if defined(ENABLE_WEBRTC)
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+#if defined(ENABLE_WEBRTC)
audio_debug_recordings_ = false;
// Tear down the dialog since the user has unchecked the audio debug
@@ -343,21 +364,20 @@ const base::FilePath& WebRTCInternals::GetEventLogRecordingsFilePath() const {
return event_log_recordings_file_path_;
}
-void WebRTCInternals::ResetForTesting() {
+void WebRTCInternals::SendUpdate(const string& command,
+ std::unique_ptr<base::Value> value) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- observers_.Clear();
- peer_connection_data_.Clear();
- CreateOrReleasePowerSaveBlocker();
- get_user_media_requests_.Clear();
- audio_debug_recordings_ = false;
-}
-
-void WebRTCInternals::SendUpdate(const string& command, base::Value* value) {
DCHECK(observers_.might_have_observers());
- FOR_EACH_OBSERVER(WebRTCInternalsUIObserver,
- observers_,
- OnUpdate(command, value));
+ bool queue_was_empty = pending_updates_.empty();
+ pending_updates_.push(PendingUpdate(command, std::move(value)));
+
+ if (queue_was_empty) {
+ BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&WebRTCInternals::ProcessPendingUpdates,
+ weak_factory_.GetWeakPtr()),
+ base::TimeDelta::FromMilliseconds(aggregate_updates_ms_));
+ }
}
void WebRTCInternals::RenderProcessHostDestroyed(RenderProcessHost* host) {
@@ -412,10 +432,11 @@ void WebRTCInternals::OnRendererExit(int render_process_id) {
record->GetInteger("lid", &lid);
record->GetInteger("pid", &pid);
- base::DictionaryValue update;
- update.SetInteger("lid", lid);
- update.SetInteger("pid", pid);
- SendUpdate("removePeerConnection", &update);
+ std::unique_ptr<base::DictionaryValue> update(
+ new base::DictionaryValue());
+ update->SetInteger("lid", lid);
+ update->SetInteger("pid", pid);
+ SendUpdate("removePeerConnection", std::move(update));
}
peer_connection_data_.Remove(i, NULL);
}
@@ -439,9 +460,9 @@ void WebRTCInternals::OnRendererExit(int render_process_id) {
}
if (found_any && observers_.might_have_observers()) {
- base::DictionaryValue update;
- update.SetInteger("rid", render_process_id);
- SendUpdate("removeGetUserMediaForRenderer", &update);
+ std::unique_ptr<base::DictionaryValue> update(new base::DictionaryValue());
+ update->SetInteger("rid", render_process_id);
+ SendUpdate("removeGetUserMediaForRenderer", std::move(update));
}
}
@@ -487,4 +508,15 @@ void WebRTCInternals::CreateOrReleasePowerSaveBlocker() {
}
}
+void WebRTCInternals::ProcessPendingUpdates() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ while (!pending_updates_.empty()) {
+ const auto& update = pending_updates_.front();
+ FOR_EACH_OBSERVER(WebRTCInternalsUIObserver,
+ observers_,
+ OnUpdate(update.command(), update.value()));
+ pending_updates_.pop();
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/media/webrtc_internals.h b/chromium/content/browser/media/webrtc/webrtc_internals.h
index f6470008dd4..e319313df2d 100644
--- a/chromium/content/browser/media/webrtc_internals.h
+++ b/chromium/content/browser/media/webrtc/webrtc_internals.h
@@ -2,15 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_MEDIA_WEBRTC_INTERNALS_H_
-#define CONTENT_BROWSER_MEDIA_WEBRTC_INTERNALS_H_
+#ifndef CONTENT_BROWSER_MEDIA_WEBRTC_WEBRTC_INTERNALS_H_
+#define CONTENT_BROWSER_MEDIA_WEBRTC_WEBRTC_INTERNALS_H_
+
+#include <memory>
+#include <queue>
#include "base/containers/hash_tables.h"
#include "base/gtest_prod_util.h"
#include "base/lazy_instance.h"
-#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/process/process.h"
+#include "base/threading/thread_checker.h"
#include "base/values.h"
#include "content/common/content_export.h"
#include "content/public/browser/render_process_host_observer.h"
@@ -81,8 +85,8 @@ class CONTENT_EXPORT WebRTCInternals : public RenderProcessHostObserver,
const std::string& video_constraints);
// Methods for adding or removing WebRTCInternalsUIObserver.
- void AddObserver(WebRTCInternalsUIObserver *observer);
- void RemoveObserver(WebRTCInternalsUIObserver *observer);
+ void AddObserver(WebRTCInternalsUIObserver* observer);
+ void RemoveObserver(WebRTCInternalsUIObserver* observer);
// Sends all update data to |observer|.
void UpdateObserver(WebRTCInternalsUIObserver* observer);
@@ -100,7 +104,14 @@ class CONTENT_EXPORT WebRTCInternals : public RenderProcessHostObserver,
bool IsEventLogRecordingsEnabled() const;
const base::FilePath& GetEventLogRecordingsFilePath() const;
- void ResetForTesting();
+ protected:
+ // Constructor/Destructor are protected to allow tests to derive from the
+ // class and do per-instance testing without having to use the global
+ // instance.
+ // The default ctor sets |aggregate_updates_ms| to 500ms.
+ WebRTCInternals();
+ explicit WebRTCInternals(int aggregate_updates_ms);
+ ~WebRTCInternals() override;
private:
friend struct base::DefaultLazyInstanceTraits<WebRTCInternals>;
@@ -113,10 +124,8 @@ class CONTENT_EXPORT WebRTCInternals : public RenderProcessHostObserver,
FRIEND_TEST_ALL_PREFIXES(WebRtcInternalsTest,
AudioDebugRecordingsFileSelectionCanceled);
- WebRTCInternals();
- ~WebRTCInternals() override;
-
- void SendUpdate(const std::string& command, base::Value* value);
+ void SendUpdate(const std::string& command,
+ std::unique_ptr<base::Value> value);
// RenderProcessHostObserver implementation.
void RenderProcessHostDestroyed(RenderProcessHost* host) override;
@@ -145,6 +154,12 @@ class CONTENT_EXPORT WebRTCInternals : public RenderProcessHostObserver,
// application for power-saving.
void CreateOrReleasePowerSaveBlocker();
+ // Called on a timer to deliver updates to javascript.
+ // We throttle and bulk together updates to avoid DOS like scenarios where
+ // a page uses a lot of peerconnection instances with many event
+ // notifications.
+ void ProcessPendingUpdates();
+
base::ObserverList<WebRTCInternalsUIObserver> observers_;
// |peer_connection_data_| is a list containing all the PeerConnection
@@ -187,12 +202,43 @@ class CONTENT_EXPORT WebRTCInternals : public RenderProcessHostObserver,
// While |peer_connection_data_| is non-empty, hold an instance of
// PowerSaveBlocker. This prevents the application from being suspended while
// remoting.
- scoped_ptr<PowerSaveBlocker> power_save_blocker_;
+ std::unique_ptr<PowerSaveBlocker> power_save_blocker_;
// Set of render process hosts that |this| is registered as an observer on.
base::hash_set<int> render_process_id_set_;
+
+ // Used to bulk up updates that we send to javascript.
+ // The class owns the value/dictionary and command name of an update.
+ // For each update, a PendingUpdate is stored in the |pending_updates_| queue
+ // and deleted as soon as the update has been delivered.
+ // The class is moveble and not copyable to avoid copying while still allowing
+ // us to use an stl container without needing scoped_ptr or similar.
+ // The class is single threaded, so all operations must occur on the same
+ // thread.
+ class PendingUpdate {
+ public:
+ PendingUpdate(const std::string& command,
+ std::unique_ptr<base::Value> value);
+ PendingUpdate(PendingUpdate&& other);
+ ~PendingUpdate();
+
+ const std::string& command() const;
+ const base::Value* value() const;
+
+ private:
+ base::ThreadChecker thread_checker_;
+ std::string command_;
+ std::unique_ptr<base::Value> value_;
+ DISALLOW_COPY_AND_ASSIGN(PendingUpdate);
+ };
+
+ std::queue<PendingUpdate> pending_updates_;
+ const int aggregate_updates_ms_;
+
+ // Weak factory for this object that we use for bulking up updates.
+ base::WeakPtrFactory<WebRTCInternals> weak_factory_;
};
} // namespace content
-#endif // CONTENT_BROWSER_MEDIA_WEBRTC_INTERNALS_H_
+#endif // CONTENT_BROWSER_MEDIA_WEBRTC_WEBRTC_INTERNALS_H_
diff --git a/chromium/content/browser/media/webrtc_internals_browsertest.cc b/chromium/content/browser/media/webrtc/webrtc_internals_browsertest.cc
index a266d03a7f5..854bf09c9fa 100644
--- a/chromium/content/browser/media/webrtc_internals_browsertest.cc
+++ b/chromium/content/browser/media/webrtc/webrtc_internals_browsertest.cc
@@ -236,7 +236,7 @@ class MAYBE_WebRtcInternalsBrowserTest: public ContentBrowserTest {
"window.domAutomationController.send("
"JSON.stringify(userMediaRequests));",
&json_requests));
- scoped_ptr<base::Value> value_requests =
+ std::unique_ptr<base::Value> value_requests =
base::JSONReader::Read(json_requests);
EXPECT_EQ(base::Value::TYPE_LIST, value_requests->GetType());
@@ -786,7 +786,7 @@ IN_PROC_BROWSER_TEST_F(MAYBE_WebRtcInternalsBrowserTest, CreatePageDump) {
"window.domAutomationController.send("
"JSON.stringify(peerConnectionDataStore));",
&dump_json));
- scoped_ptr<base::Value> dump = base::JSONReader::Read(dump_json);
+ std::unique_ptr<base::Value> dump = base::JSONReader::Read(dump_json);
VerifyPageDumpStructure(dump.get(),
2 /*peer_connection_number*/,
2 /*update_number*/,
diff --git a/chromium/content/browser/media/webrtc_internals_message_handler.cc b/chromium/content/browser/media/webrtc/webrtc_internals_message_handler.cc
index 33a69effdc9..eaaea95a73d 100644
--- a/chromium/content/browser/media/webrtc_internals_message_handler.cc
+++ b/chromium/content/browser/media/webrtc/webrtc_internals_message_handler.cc
@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/media/webrtc_internals_message_handler.h"
+#include "content/browser/media/webrtc/webrtc_internals_message_handler.h"
-#include "content/browser/media/webrtc_internals.h"
+#include "content/browser/media/webrtc/webrtc_internals.h"
#include "content/common/media/peer_connection_tracker_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
diff --git a/chromium/content/browser/media/webrtc_internals_message_handler.h b/chromium/content/browser/media/webrtc/webrtc_internals_message_handler.h
index 1b42f219a1d..82e242eea9d 100644
--- a/chromium/content/browser/media/webrtc_internals_message_handler.h
+++ b/chromium/content/browser/media/webrtc/webrtc_internals_message_handler.h
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_MEDIA_WEBRTC_INTERNALS_MESSAGE_HANDLER_H_
-#define CONTENT_BROWSER_MEDIA_WEBRTC_INTERNALS_MESSAGE_HANDLER_H_
+#ifndef CONTENT_BROWSER_MEDIA_WEBRTC_WEBRTC_INTERNALS_MESSAGE_HANDLER_H_
+#define CONTENT_BROWSER_MEDIA_WEBRTC_WEBRTC_INTERNALS_MESSAGE_HANDLER_H_
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "content/browser/media/webrtc_internals_ui_observer.h"
+#include "content/browser/media/webrtc/webrtc_internals_ui_observer.h"
#include "content/public/browser/web_ui_message_handler.h"
namespace base {
@@ -49,4 +49,4 @@ class WebRTCInternalsMessageHandler : public WebUIMessageHandler,
} // namespace content
-#endif // CONTENT_BROWSER_MEDIA_WEBRTC_INTERNALS_MESSAGE_HANDLER_H_
+#endif // CONTENT_BROWSER_MEDIA_WEBRTC_WEBRTC_INTERNALS_MESSAGE_HANDLER_H_
diff --git a/chromium/content/browser/media/webrtc_internals_ui.cc b/chromium/content/browser/media/webrtc/webrtc_internals_ui.cc
index 67970305741..c08c9f2fdfa 100644
--- a/chromium/content/browser/media/webrtc_internals_ui.cc
+++ b/chromium/content/browser/media/webrtc/webrtc_internals_ui.cc
@@ -2,9 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/media/webrtc_internals_ui.h"
+#include "content/browser/media/webrtc/webrtc_internals_ui.h"
-#include "content/browser/media/webrtc_internals_message_handler.h"
+#include "content/browser/media/webrtc/webrtc_internals_message_handler.h"
#include "content/grit/content_resources.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
diff --git a/chromium/content/browser/media/webrtc_internals_ui.h b/chromium/content/browser/media/webrtc/webrtc_internals_ui.h
index 541af020e49..2347ff9f6a3 100644
--- a/chromium/content/browser/media/webrtc_internals_ui.h
+++ b/chromium/content/browser/media/webrtc/webrtc_internals_ui.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_MEDIA_WEBRTC_INTERNALS_UI_H_
-#define CONTENT_BROWSER_MEDIA_WEBRTC_INTERNALS_UI_H_
+#ifndef CONTENT_BROWSER_MEDIA_WEBRTC_WEBRTC_INTERNALS_UI_H_
+#define CONTENT_BROWSER_MEDIA_WEBRTC_WEBRTC_INTERNALS_UI_H_
#include "base/macros.h"
#include "content/public/browser/web_ui_controller.h"
@@ -21,4 +21,4 @@ class WebRTCInternalsUI : public WebUIController {
} // namespace content
-#endif // CONTENT_BROWSER_MEDIA_WEBRTC_INTERNALS_UI_H_
+#endif // CONTENT_BROWSER_MEDIA_WEBRTC_WEBRTC_INTERNALS_UI_H_
diff --git a/chromium/content/browser/media/webrtc_internals_ui_observer.h b/chromium/content/browser/media/webrtc/webrtc_internals_ui_observer.h
index 31082b6181f..e7dfed1f1d9 100644
--- a/chromium/content/browser/media/webrtc_internals_ui_observer.h
+++ b/chromium/content/browser/media/webrtc/webrtc_internals_ui_observer.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_MEDIA_WEBRTC_INTERNALS_UI_OBSERVER_H_
-#define CONTENT_BROWSER_MEDIA_WEBRTC_INTERNALS_UI_OBSERVER_H_
+#ifndef CONTENT_BROWSER_MEDIA_WEBRTC_WEBRTC_INTERNALS_UI_OBSERVER_H_
+#define CONTENT_BROWSER_MEDIA_WEBRTC_WEBRTC_INTERNALS_UI_OBSERVER_H_
#include <string>
@@ -26,4 +26,4 @@ class WebRTCInternalsUIObserver {
} // namespace content
-#endif // CONTENT_BROWSER_MEDIA_WEBRTC_INTERNALS_UI_OBSERVER_H_
+#endif // CONTENT_BROWSER_MEDIA_WEBRTC_WEBRTC_INTERNALS_UI_OBSERVER_H_
diff --git a/chromium/content/browser/media/webrtc_internals_unittest.cc b/chromium/content/browser/media/webrtc/webrtc_internals_unittest.cc
index 197107fadad..f3b048f5dff 100644
--- a/chromium/content/browser/media/webrtc_internals_unittest.cc
+++ b/chromium/content/browser/media/webrtc/webrtc_internals_unittest.cc
@@ -2,11 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/memory/scoped_ptr.h"
+#include "content/browser/media/webrtc/webrtc_internals.h"
+
+#include <memory>
+
#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/values.h"
-#include "content/browser/media/webrtc_internals.h"
-#include "content/browser/media/webrtc_internals_ui_observer.h"
+#include "content/browser/media/webrtc/webrtc_internals_ui_observer.h"
#include "content/public/test/test_browser_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -20,13 +23,10 @@ static const std::string kUrl = "u";
class MockWebRtcInternalsProxy : public WebRTCInternalsUIObserver {
public:
- void OnUpdate(const std::string& command, const base::Value* value) override {
- command_ = command;
- if (value)
- value_.reset(value->DeepCopy());
- }
+ MockWebRtcInternalsProxy() : loop_(nullptr) {}
+ explicit MockWebRtcInternalsProxy(base::RunLoop* loop) : loop_(loop) {}
- std::string command() {
+ const std::string& command() const {
return command_;
}
@@ -35,15 +35,32 @@ class MockWebRtcInternalsProxy : public WebRTCInternalsUIObserver {
}
private:
- std::string command_;
- scoped_ptr<base::Value> value_;
+ void OnUpdate(const std::string& command, const base::Value* value) override {
+ command_ = command;
+ value_.reset(value ? value->DeepCopy() : nullptr);
+ if (loop_)
+ loop_->Quit();
+ }
+
+ std::string command_;
+ std::unique_ptr<base::Value> value_;
+ base::RunLoop* loop_;
+};
+
+// Derived class for testing only. Allows the tests to have their own instance
+// for testing and control the period for which WebRTCInternals will bulk up
+// updates (changes down from 500ms to 1ms).
+class WebRTCInternalsForTest : public NON_EXPORTED_BASE(WebRTCInternals) {
+ public:
+ WebRTCInternalsForTest() : WebRTCInternals(1) {}
+ ~WebRTCInternalsForTest() override {}
};
+} // namespace
+
class WebRtcInternalsTest : public testing::Test {
public:
- WebRtcInternalsTest() : io_thread_(BrowserThread::UI, &io_loop_) {
- WebRTCInternals::GetInstance()->ResetForTesting();
- }
+ WebRtcInternalsTest() : io_thread_(BrowserThread::UI, &io_loop_) {}
protected:
void VerifyString(const base::DictionaryValue* dict,
@@ -90,30 +107,41 @@ class WebRtcInternalsTest : public testing::Test {
TestBrowserThread io_thread_;
};
-} // namespace
-
TEST_F(WebRtcInternalsTest, AddRemoveObserver) {
- scoped_ptr<MockWebRtcInternalsProxy> observer(
- new MockWebRtcInternalsProxy());
- WebRTCInternals::GetInstance()->AddObserver(observer.get());
- WebRTCInternals::GetInstance()->RemoveObserver(observer.get());
- WebRTCInternals::GetInstance()->OnAddPeerConnection(
+ base::RunLoop loop;
+ MockWebRtcInternalsProxy observer(&loop);
+ WebRTCInternalsForTest webrtc_internals;
+ webrtc_internals.AddObserver(&observer);
+
+ webrtc_internals.RemoveObserver(&observer);
+ // The observer should not get notified of this activity.
+ webrtc_internals.OnAddPeerConnection(
0, 3, 4, kUrl, kRtcConfiguration, kContraints);
- EXPECT_EQ("", observer->command());
- WebRTCInternals::GetInstance()->OnRemovePeerConnection(3, 4);
+ BrowserThread::PostDelayedTask(BrowserThread::UI, FROM_HERE,
+ loop.QuitClosure(),
+ base::TimeDelta::FromMilliseconds(5));
+ loop.Run();
+
+ EXPECT_EQ("", observer.command());
+
+ webrtc_internals.OnRemovePeerConnection(3, 4);
}
TEST_F(WebRtcInternalsTest, SendAddPeerConnectionUpdate) {
- scoped_ptr<MockWebRtcInternalsProxy> observer(
- new MockWebRtcInternalsProxy());
- WebRTCInternals::GetInstance()->AddObserver(observer.get());
- WebRTCInternals::GetInstance()->OnAddPeerConnection(
+ base::RunLoop loop;
+ MockWebRtcInternalsProxy observer(&loop);
+ WebRTCInternalsForTest webrtc_internals;
+ webrtc_internals.AddObserver(&observer);
+ webrtc_internals.OnAddPeerConnection(
0, 1, 2, kUrl, kRtcConfiguration, kContraints);
- EXPECT_EQ("addPeerConnection", observer->command());
+
+ loop.Run();
+
+ ASSERT_EQ("addPeerConnection", observer.command());
base::DictionaryValue* dict = NULL;
- EXPECT_TRUE(observer->value()->GetAsDictionary(&dict));
+ EXPECT_TRUE(observer.value()->GetAsDictionary(&dict));
VerifyInt(dict, "pid", 1);
VerifyInt(dict, "lid", 2);
@@ -121,44 +149,51 @@ TEST_F(WebRtcInternalsTest, SendAddPeerConnectionUpdate) {
VerifyString(dict, "rtcConfiguration", kRtcConfiguration);
VerifyString(dict, "constraints", kContraints);
- WebRTCInternals::GetInstance()->RemoveObserver(observer.get());
- WebRTCInternals::GetInstance()->OnRemovePeerConnection(1, 2);
+ webrtc_internals.RemoveObserver(&observer);
+ webrtc_internals.OnRemovePeerConnection(1, 2);
}
TEST_F(WebRtcInternalsTest, SendRemovePeerConnectionUpdate) {
- scoped_ptr<MockWebRtcInternalsProxy> observer(
- new MockWebRtcInternalsProxy());
- WebRTCInternals::GetInstance()->AddObserver(observer.get());
- WebRTCInternals::GetInstance()->OnAddPeerConnection(
+ base::RunLoop loop;
+ MockWebRtcInternalsProxy observer(&loop);
+ WebRTCInternalsForTest webrtc_internals;
+ webrtc_internals.AddObserver(&observer);
+ webrtc_internals.OnAddPeerConnection(
0, 1, 2, kUrl, kRtcConfiguration, kContraints);
- WebRTCInternals::GetInstance()->OnRemovePeerConnection(1, 2);
- EXPECT_EQ("removePeerConnection", observer->command());
+ webrtc_internals.OnRemovePeerConnection(1, 2);
+
+ loop.Run();
+
+ ASSERT_EQ("removePeerConnection", observer.command());
base::DictionaryValue* dict = NULL;
- EXPECT_TRUE(observer->value()->GetAsDictionary(&dict));
+ EXPECT_TRUE(observer.value()->GetAsDictionary(&dict));
VerifyInt(dict, "pid", 1);
VerifyInt(dict, "lid", 2);
- WebRTCInternals::GetInstance()->RemoveObserver(observer.get());
+ webrtc_internals.RemoveObserver(&observer);
}
TEST_F(WebRtcInternalsTest, SendUpdatePeerConnectionUpdate) {
- scoped_ptr<MockWebRtcInternalsProxy> observer(
- new MockWebRtcInternalsProxy());
- WebRTCInternals::GetInstance()->AddObserver(observer.get());
- WebRTCInternals::GetInstance()->OnAddPeerConnection(
+ base::RunLoop loop;
+ MockWebRtcInternalsProxy observer(&loop);
+ WebRTCInternalsForTest webrtc_internals;
+ webrtc_internals.AddObserver(&observer);
+ webrtc_internals.OnAddPeerConnection(
0, 1, 2, kUrl, kRtcConfiguration, kContraints);
const std::string update_type = "fakeType";
const std::string update_value = "fakeValue";
- WebRTCInternals::GetInstance()->OnUpdatePeerConnection(
+ webrtc_internals.OnUpdatePeerConnection(
1, 2, update_type, update_value);
- EXPECT_EQ("updatePeerConnection", observer->command());
+ loop.Run();
+
+ ASSERT_EQ("updatePeerConnection", observer.command());
base::DictionaryValue* dict = NULL;
- EXPECT_TRUE(observer->value()->GetAsDictionary(&dict));
+ EXPECT_TRUE(observer.value()->GetAsDictionary(&dict));
VerifyInt(dict, "pid", 1);
VerifyInt(dict, "lid", 2);
@@ -169,28 +204,32 @@ TEST_F(WebRtcInternalsTest, SendUpdatePeerConnectionUpdate) {
EXPECT_TRUE(dict->GetString("time", &time));
EXPECT_FALSE(time.empty());
- WebRTCInternals::GetInstance()->OnRemovePeerConnection(1, 2);
- WebRTCInternals::GetInstance()->RemoveObserver(observer.get());
+ webrtc_internals.OnRemovePeerConnection(1, 2);
+ webrtc_internals.RemoveObserver(&observer);
}
TEST_F(WebRtcInternalsTest, AddGetUserMedia) {
- scoped_ptr<MockWebRtcInternalsProxy> observer(new MockWebRtcInternalsProxy());
+ base::RunLoop loop;
+ MockWebRtcInternalsProxy observer(&loop);
+ WebRTCInternalsForTest webrtc_internals;
// Add one observer before "getUserMedia".
- WebRTCInternals::GetInstance()->AddObserver(observer.get());
+ webrtc_internals.AddObserver(&observer);
const int rid = 1;
const int pid = 2;
const std::string audio_constraint = "aaa";
const std::string video_constraint = "vvv";
- WebRTCInternals::GetInstance()->OnGetUserMedia(
+ webrtc_internals.OnGetUserMedia(
rid, pid, kUrl, true, true, audio_constraint, video_constraint);
- EXPECT_EQ("addGetUserMedia", observer->command());
+ loop.Run();
+
+ ASSERT_EQ("addGetUserMedia", observer.command());
VerifyGetUserMediaData(
- observer->value(), rid, pid, kUrl, audio_constraint, video_constraint);
+ observer.value(), rid, pid, kUrl, audio_constraint, video_constraint);
- WebRTCInternals::GetInstance()->RemoveObserver(observer.get());
+ webrtc_internals.RemoveObserver(&observer);
}
TEST_F(WebRtcInternalsTest, SendAllUpdateWithGetUserMedia) {
@@ -198,19 +237,20 @@ TEST_F(WebRtcInternalsTest, SendAllUpdateWithGetUserMedia) {
const int pid = 2;
const std::string audio_constraint = "aaa";
const std::string video_constraint = "vvv";
- WebRTCInternals::GetInstance()->OnGetUserMedia(
+ WebRTCInternalsForTest webrtc_internals;
+ webrtc_internals.OnGetUserMedia(
rid, pid, kUrl, true, true, audio_constraint, video_constraint);
- scoped_ptr<MockWebRtcInternalsProxy> observer(new MockWebRtcInternalsProxy());
+ MockWebRtcInternalsProxy observer;
// Add one observer after "getUserMedia".
- WebRTCInternals::GetInstance()->AddObserver(observer.get());
- WebRTCInternals::GetInstance()->UpdateObserver(observer.get());
+ webrtc_internals.AddObserver(&observer);
+ webrtc_internals.UpdateObserver(&observer);
- EXPECT_EQ("addGetUserMedia", observer->command());
+ EXPECT_EQ("addGetUserMedia", observer.command());
VerifyGetUserMediaData(
- observer->value(), rid, pid, kUrl, audio_constraint, video_constraint);
+ observer.value(), rid, pid, kUrl, audio_constraint, video_constraint);
- WebRTCInternals::GetInstance()->RemoveObserver(observer.get());
+ webrtc_internals.RemoveObserver(&observer);
}
TEST_F(WebRtcInternalsTest, SendAllUpdatesWithPeerConnectionUpdate) {
@@ -218,20 +258,23 @@ TEST_F(WebRtcInternalsTest, SendAllUpdatesWithPeerConnectionUpdate) {
const std::string update_type = "fakeType";
const std::string update_value = "fakeValue";
- WebRTCInternals::GetInstance()->OnAddPeerConnection(
+ WebRTCInternalsForTest webrtc_internals;
+
+ webrtc_internals.OnAddPeerConnection(
rid, pid, lid, kUrl, kRtcConfiguration, kContraints);
- WebRTCInternals::GetInstance()->OnUpdatePeerConnection(
+ webrtc_internals.OnUpdatePeerConnection(
pid, lid, update_type, update_value);
- scoped_ptr<MockWebRtcInternalsProxy> observer(new MockWebRtcInternalsProxy());
- WebRTCInternals::GetInstance()->AddObserver(observer.get());
+ MockWebRtcInternalsProxy observer;
+ webrtc_internals.AddObserver(&observer);
- WebRTCInternals::GetInstance()->UpdateObserver(observer.get());
+ webrtc_internals.UpdateObserver(&observer);
- EXPECT_EQ("updateAllPeerConnections", observer->command());
+ EXPECT_EQ("updateAllPeerConnections", observer.command());
+ ASSERT_TRUE(observer.value());
base::ListValue* list = NULL;
- EXPECT_TRUE(observer->value()->GetAsList(&list));
+ EXPECT_TRUE(observer.value()->GetAsList(&list));
EXPECT_EQ(1U, list->GetSize());
base::DictionaryValue* dict = NULL;
@@ -258,19 +301,25 @@ TEST_F(WebRtcInternalsTest, SendAllUpdatesWithPeerConnectionUpdate) {
TEST_F(WebRtcInternalsTest, OnAddStats) {
const int rid = 0, pid = 1, lid = 2;
- scoped_ptr<MockWebRtcInternalsProxy> observer(new MockWebRtcInternalsProxy());
- WebRTCInternals::GetInstance()->AddObserver(observer.get());
- WebRTCInternals::GetInstance()->OnAddPeerConnection(
+ base::RunLoop loop;
+ MockWebRtcInternalsProxy observer(&loop);
+ WebRTCInternalsForTest webrtc_internals;
+ webrtc_internals.AddObserver(&observer);
+ webrtc_internals.OnAddPeerConnection(
rid, pid, lid, kUrl, kRtcConfiguration, kContraints);
base::ListValue list;
list.AppendString("xxx");
list.AppendString("yyy");
- WebRTCInternals::GetInstance()->OnAddStats(pid, lid, list);
+ webrtc_internals.OnAddStats(pid, lid, list);
+
+ loop.Run();
+
+ EXPECT_EQ("addStats", observer.command());
+ ASSERT_TRUE(observer.value());
- EXPECT_EQ("addStats", observer->command());
base::DictionaryValue* dict = NULL;
- EXPECT_TRUE(observer->value()->GetAsDictionary(&dict));
+ EXPECT_TRUE(observer.value()->GetAsDictionary(&dict));
VerifyInt(dict, "pid", pid);
VerifyInt(dict, "lid", lid);
@@ -278,11 +327,18 @@ TEST_F(WebRtcInternalsTest, OnAddStats) {
}
TEST_F(WebRtcInternalsTest, AudioDebugRecordingsFileSelectionCanceled) {
- scoped_ptr<MockWebRtcInternalsProxy> observer(new MockWebRtcInternalsProxy());
- WebRTCInternals::GetInstance()->AddObserver(observer.get());
- WebRTCInternals::GetInstance()->FileSelectionCanceled(NULL);
- EXPECT_EQ("audioDebugRecordingsFileSelectionCancelled", observer->command());
- EXPECT_EQ(NULL, observer->value());
+ base::RunLoop loop;
+
+ MockWebRtcInternalsProxy observer(&loop);
+ WebRTCInternalsForTest webrtc_internals;
+
+ webrtc_internals.AddObserver(&observer);
+ webrtc_internals.FileSelectionCanceled(nullptr);
+
+ loop.Run();
+
+ EXPECT_EQ("audioDebugRecordingsFileSelectionCancelled", observer.command());
+ EXPECT_EQ(nullptr, observer.value());
}
} // namespace content
diff --git a/chromium/content/browser/media/webrtc_ip_permissions_browsertest.cc b/chromium/content/browser/media/webrtc/webrtc_ip_permissions_browsertest.cc
index 9b05019e40f..9b05019e40f 100644
--- a/chromium/content/browser/media/webrtc_ip_permissions_browsertest.cc
+++ b/chromium/content/browser/media/webrtc/webrtc_ip_permissions_browsertest.cc
diff --git a/chromium/content/browser/media/webrtc_media_recorder_browsertest.cc b/chromium/content/browser/media/webrtc/webrtc_media_recorder_browsertest.cc
index 00f8454dee2..00f8454dee2 100644
--- a/chromium/content/browser/media/webrtc_media_recorder_browsertest.cc
+++ b/chromium/content/browser/media/webrtc/webrtc_media_recorder_browsertest.cc
diff --git a/chromium/content/browser/media/webrtc_webcam_browsertest.cc b/chromium/content/browser/media/webrtc/webrtc_webcam_browsertest.cc
index 32eeb111532..32eeb111532 100644
--- a/chromium/content/browser/media/webrtc_webcam_browsertest.cc
+++ b/chromium/content/browser/media/webrtc/webrtc_webcam_browsertest.cc
diff --git a/chromium/content/browser/memory/memory_message_filter.cc b/chromium/content/browser/memory/memory_message_filter.cc
index 110f8396aae..9ab2adbd18c 100644
--- a/chromium/content/browser/memory/memory_message_filter.cc
+++ b/chromium/content/browser/memory/memory_message_filter.cc
@@ -4,7 +4,7 @@
#include "content/browser/memory/memory_message_filter.h"
-#include "content/browser/memory/memory_pressure_controller.h"
+#include "content/browser/memory/memory_pressure_controller_impl.h"
#include "content/common/memory_messages.h"
namespace content {
@@ -27,11 +27,12 @@ MemoryMessageFilter::MemoryMessageFilter(
MemoryMessageFilter::~MemoryMessageFilter() {}
void MemoryMessageFilter::OnFilterAdded(IPC::Sender* sender) {
- MemoryPressureController::GetInstance()->OnMemoryMessageFilterAdded(this);
+ MemoryPressureControllerImpl::GetInstance()->OnMemoryMessageFilterAdded(this);
}
void MemoryMessageFilter::OnChannelClosing() {
- MemoryPressureController::GetInstance()->OnMemoryMessageFilterRemoved(this);
+ MemoryPressureControllerImpl::GetInstance()
+ ->OnMemoryMessageFilterRemoved(this);
}
bool MemoryMessageFilter::OnMessageReceived(const IPC::Message& message) {
diff --git a/chromium/content/browser/memory/memory_message_filter.h b/chromium/content/browser/memory/memory_message_filter.h
index ad13662477e..5241b9cc556 100644
--- a/chromium/content/browser/memory/memory_message_filter.h
+++ b/chromium/content/browser/memory/memory_message_filter.h
@@ -36,7 +36,7 @@ class CONTENT_EXPORT MemoryMessageFilter : public BrowserMessageFilter {
base::MemoryPressureListener::MemoryPressureLevel level);
protected:
- friend class MemoryPressureController;
+ friend class MemoryPressureControllerImpl;
~MemoryMessageFilter() override;
@@ -46,7 +46,7 @@ class CONTENT_EXPORT MemoryMessageFilter : public BrowserMessageFilter {
private:
// The untyped process host and ProcessType associated with this filter
// instance. The process host is stored as untyped because it is only used as
- // a key in MemoryPressureController; at no point is it ever deferenced to
+ // a key in MemoryPressureControllerImpl; at no point is it ever deferenced to
// invoke any members on a process host.
const void* process_host_;
ProcessType process_type_;
diff --git a/chromium/content/browser/memory/memory_pressure_controller.cc b/chromium/content/browser/memory/memory_pressure_controller_impl.cc
index 11cdbe53714..1026783e468 100644
--- a/chromium/content/browser/memory/memory_pressure_controller.cc
+++ b/chromium/content/browser/memory/memory_pressure_controller_impl.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/memory/memory_pressure_controller.h"
+#include "content/browser/memory/memory_pressure_controller_impl.h"
#include "base/bind.h"
#include "content/browser/memory/memory_message_filter.h"
@@ -10,11 +10,11 @@
namespace content {
-MemoryPressureController::MemoryPressureController() {}
+MemoryPressureControllerImpl::MemoryPressureControllerImpl() {}
-MemoryPressureController::~MemoryPressureController() {}
+MemoryPressureControllerImpl::~MemoryPressureControllerImpl() {}
-void MemoryPressureController::OnMemoryMessageFilterAdded(
+void MemoryPressureControllerImpl::OnMemoryMessageFilterAdded(
MemoryMessageFilter* filter) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -32,7 +32,7 @@ void MemoryPressureController::OnMemoryMessageFilterAdded(
filter->SendSetPressureNotificationsSuppressed(true);
}
-void MemoryPressureController::OnMemoryMessageFilterRemoved(
+void MemoryPressureControllerImpl::OnMemoryMessageFilterRemoved(
MemoryMessageFilter* filter) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -45,20 +45,21 @@ void MemoryPressureController::OnMemoryMessageFilterRemoved(
}
// static
-MemoryPressureController* MemoryPressureController::GetInstance() {
+MemoryPressureControllerImpl* MemoryPressureControllerImpl::GetInstance() {
return base::Singleton<
- MemoryPressureController,
- base::LeakySingletonTraits<MemoryPressureController>>::get();
+ MemoryPressureControllerImpl,
+ base::LeakySingletonTraits<MemoryPressureControllerImpl>>::get();
}
-void MemoryPressureController::SetPressureNotificationsSuppressedInAllProcesses(
+void
+MemoryPressureControllerImpl::SetPressureNotificationsSuppressedInAllProcesses(
bool suppressed) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
// Note that passing base::Unretained(this) is safe here because the
// controller is a leaky singleton.
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&MemoryPressureController::
+ base::Bind(&MemoryPressureControllerImpl::
SetPressureNotificationsSuppressedInAllProcesses,
base::Unretained(this), suppressed));
return;
@@ -72,7 +73,7 @@ void MemoryPressureController::SetPressureNotificationsSuppressedInAllProcesses(
filter_pair.second->SendSetPressureNotificationsSuppressed(suppressed);
}
-void MemoryPressureController::SimulatePressureNotificationInAllProcesses(
+void MemoryPressureControllerImpl::SimulatePressureNotificationInAllProcesses(
base::MemoryPressureListener::MemoryPressureLevel level) {
DCHECK_NE(level, base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE);
@@ -81,7 +82,7 @@ void MemoryPressureController::SimulatePressureNotificationInAllProcesses(
// controller is a leaky singleton.
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&MemoryPressureController::
+ base::Bind(&MemoryPressureControllerImpl::
SimulatePressureNotificationInAllProcesses,
base::Unretained(this), level));
return;
@@ -95,19 +96,19 @@ void MemoryPressureController::SimulatePressureNotificationInAllProcesses(
filter_pair.second->SendSimulatePressureNotification(level);
}
-void MemoryPressureController::SendPressureNotification(
+void MemoryPressureControllerImpl::SendPressureNotification(
const BrowserChildProcessHost* child_process_host,
base::MemoryPressureListener::MemoryPressureLevel level) {
SendPressureNotificationImpl(child_process_host, level);
}
-void MemoryPressureController::SendPressureNotification(
+void MemoryPressureControllerImpl::SendPressureNotification(
const RenderProcessHost* render_process_host,
base::MemoryPressureListener::MemoryPressureLevel level) {
SendPressureNotificationImpl(render_process_host, level);
}
-void MemoryPressureController::SendPressureNotificationImpl(
+void MemoryPressureControllerImpl::SendPressureNotificationImpl(
const void* child_process_host,
base::MemoryPressureListener::MemoryPressureLevel level) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
@@ -117,7 +118,7 @@ void MemoryPressureController::SendPressureNotificationImpl(
// a map; at no point is it dereferenced.
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&MemoryPressureController::SendPressureNotificationImpl,
+ base::Bind(&MemoryPressureControllerImpl::SendPressureNotificationImpl,
base::Unretained(this), child_process_host, level));
return;
}
diff --git a/chromium/content/browser/memory/memory_pressure_controller.h b/chromium/content/browser/memory/memory_pressure_controller_impl.h
index f81540957d7..95d58d250d6 100644
--- a/chromium/content/browser/memory/memory_pressure_controller.h
+++ b/chromium/content/browser/memory/memory_pressure_controller_impl.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_MEMORY_MEMORY_PRESSURE_CONTROLLER_H_
-#define CONTENT_BROWSER_MEMORY_MEMORY_PRESSURE_CONTROLLER_H_
+#ifndef CONTENT_BROWSER_MEMORY_MEMORY_PRESSURE_CONTROLLER_IMPL_H_
+#define CONTENT_BROWSER_MEMORY_MEMORY_PRESSURE_CONTROLLER_IMPL_H_
#include <map>
@@ -19,33 +19,55 @@ class BrowserChildProcessHost;
class MemoryMessageFilter;
class RenderProcessHost;
-class CONTENT_EXPORT MemoryPressureController {
+// Controller for memory pressure IPC messages. Each child process owns and
+// registers a MemoryMessageFilter, which can be used to both suppress and
+// simulate memory pressure messages across processes. This controller
+// coordinates suppressing and simulation of messages, as well as allows for
+// messages to be forwarded to individual processes. This allows the browser
+// process to control what memory pressure messages are seen in child processes.
+// For more details see content/browser/memory/memory_message_filter.h and
+// content/child/memory/child_memory_message_filter.h.
+class CONTENT_EXPORT MemoryPressureControllerImpl {
public:
+ // This method can be called from any thread.
+ static MemoryPressureControllerImpl* GetInstance();
+
// These methods must be called on the IO thread.
void OnMemoryMessageFilterAdded(MemoryMessageFilter* filter);
void OnMemoryMessageFilterRemoved(MemoryMessageFilter* filter);
// These methods can be called from any thread.
+
+ // Suppresses all memory pressure messages from passing through all attached
+ // MemoryMessageFilters. Any messages sent through a "suppressed" filter will
+ // be ignored on the receiving end.
void SetPressureNotificationsSuppressedInAllProcesses(bool suppressed);
+
+ // Simulates memory pressure in all processes by invoking
+ // SimulatePressureNotification on all attached MemoryMessageFilters. These
+ // messages will be received even if suppression is enabled.
void SimulatePressureNotificationInAllProcesses(
base::MemoryPressureListener::MemoryPressureLevel level);
+
+ // Sends a memory pressure notification to the specified browser child process
+ // via its attached MemoryMessageFilter.
void SendPressureNotification(
const BrowserChildProcessHost* child_process_host,
base::MemoryPressureListener::MemoryPressureLevel level);
+
+ // Sends a memory pressure notification to the specified renderer process via
+ // its attached MemoryMessageFilter.
void SendPressureNotification(
const RenderProcessHost* render_process_host,
base::MemoryPressureListener::MemoryPressureLevel level);
- // This method can be called from any thread.
- static MemoryPressureController* GetInstance();
-
protected:
- virtual ~MemoryPressureController();
+ virtual ~MemoryPressureControllerImpl();
private:
- friend struct base::DefaultSingletonTraits<MemoryPressureController>;
+ friend struct base::DefaultSingletonTraits<MemoryPressureControllerImpl>;
- MemoryPressureController();
+ MemoryPressureControllerImpl();
// Implementation of the various SendPressureNotification methods.
void SendPressureNotificationImpl(
@@ -58,9 +80,9 @@ class CONTENT_EXPORT MemoryPressureController {
MemoryMessageFilterMap;
MemoryMessageFilterMap memory_message_filters_;
- DISALLOW_COPY_AND_ASSIGN(MemoryPressureController);
+ DISALLOW_COPY_AND_ASSIGN(MemoryPressureControllerImpl);
};
} // namespace content
-#endif // CONTENT_BROWSER_MEMORY_MEMORY_PRESSURE_CONTROLLER_H_
+#endif // CONTENT_BROWSER_MEMORY_MEMORY_PRESSURE_CONTROLLER_IMPL_H_
diff --git a/chromium/content/browser/memory/memory_pressure_controller_browsertest.cc b/chromium/content/browser/memory/memory_pressure_controller_impl_browsertest.cc
index 5b08a665373..d688fd16a47 100644
--- a/chromium/content/browser/memory/memory_pressure_controller_browsertest.cc
+++ b/chromium/content/browser/memory/memory_pressure_controller_impl_browsertest.cc
@@ -5,7 +5,7 @@
#include "base/bind.h"
#include "base/memory/memory_pressure_listener.h"
#include "content/browser/memory/memory_message_filter.h"
-#include "content/browser/memory/memory_pressure_controller.h"
+#include "content/browser/memory/memory_pressure_controller_impl.h"
#include "content/common/memory_messages.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
@@ -89,7 +89,7 @@ class MemoryMessageFilterForTesting : public MemoryMessageFilter {
~MemoryMessageFilterForTesting() override {}
};
-class MemoryPressureControllerBrowserTest : public ContentBrowserTest {
+class MemoryPressureControllerImplBrowserTest : public ContentBrowserTest {
public:
MOCK_METHOD1(OnMemoryPressure,
void(base::MemoryPressureListener::MemoryPressureLevel level));
@@ -97,14 +97,14 @@ class MemoryPressureControllerBrowserTest : public ContentBrowserTest {
protected:
void SetPressureNotificationsSuppressedInAllProcessesAndWait(
bool suppressed) {
- MemoryPressureController::GetInstance()
+ MemoryPressureControllerImpl::GetInstance()
->SetPressureNotificationsSuppressedInAllProcesses(suppressed);
RunAllPendingInMessageLoop(BrowserThread::IO);
}
void SimulatePressureNotificationInAllProcessesAndWait(
base::MemoryPressureListener::MemoryPressureLevel level) {
- MemoryPressureController::GetInstance()
+ MemoryPressureControllerImpl::GetInstance()
->SimulatePressureNotificationInAllProcesses(level);
RunAllPendingInMessageLoop(BrowserThread::IO);
}
@@ -112,7 +112,7 @@ class MemoryPressureControllerBrowserTest : public ContentBrowserTest {
void SendPressureNotificationAndWait(
const void* fake_process_host,
base::MemoryPressureListener::MemoryPressureLevel level) {
- MemoryPressureController::GetInstance()->SendPressureNotification(
+ MemoryPressureControllerImpl::GetInstance()->SendPressureNotification(
reinterpret_cast<const RenderProcessHost*>(fake_process_host), level);
RunAllPendingInMessageLoop(BrowserThread::IO);
}
@@ -123,7 +123,7 @@ const auto MEMORY_PRESSURE_LEVEL_MODERATE =
const auto MEMORY_PRESSURE_LEVEL_CRITICAL =
base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL;
-IN_PROC_BROWSER_TEST_F(MemoryPressureControllerBrowserTest,
+IN_PROC_BROWSER_TEST_F(MemoryPressureControllerImplBrowserTest,
SetPressureNotificationsSuppressedInAllProcesses) {
scoped_refptr<MemoryMessageFilterForTesting> filter1(
new MemoryMessageFilterForTesting);
@@ -212,13 +212,13 @@ IN_PROC_BROWSER_TEST_F(MemoryPressureControllerBrowserTest,
testing::Mock::VerifyAndClearExpectations(this);
}
-IN_PROC_BROWSER_TEST_F(MemoryPressureControllerBrowserTest,
+IN_PROC_BROWSER_TEST_F(MemoryPressureControllerImplBrowserTest,
SimulatePressureNotificationInAllProcesses) {
scoped_refptr<MemoryMessageFilterForTesting> filter(
new MemoryMessageFilterForTesting);
scoped_ptr<base::MemoryPressureListener> listener(
new base::MemoryPressureListener(
- base::Bind(&MemoryPressureControllerBrowserTest::OnMemoryPressure,
+ base::Bind(&MemoryPressureControllerImplBrowserTest::OnMemoryPressure,
base::Unretained(this))));
NavigateToURL(shell(), GetTestUrl("", "title.html"));
diff --git a/chromium/content/browser/message_port_service.cc b/chromium/content/browser/message_port_service.cc
index 21fc76d40bc..5ced952a457 100644
--- a/chromium/content/browser/message_port_service.cc
+++ b/chromium/content/browser/message_port_service.cc
@@ -198,10 +198,6 @@ void MessagePortService::PostMessageTo(
}
entangled_port.queued_messages.push_back(
std::make_pair(message, sent_message_ports));
-
- if (entangled_port.delegate)
- entangled_port.delegate->MessageWasHeld(entangled_port.route_id);
-
return;
}
@@ -295,6 +291,13 @@ void MessagePortService::HoldMessages(int message_port_id) {
message_ports_[message_port_id].hold_messages_for_destination = true;
}
+bool MessagePortService::AreMessagesHeld(int message_port_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ if (!message_ports_.count(message_port_id))
+ return false;
+ return message_ports_[message_port_id].hold_messages_for_destination;
+}
+
void MessagePortService::ClosePort(int message_port_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!message_ports_.count(message_port_id)) {
diff --git a/chromium/content/browser/message_port_service.h b/chromium/content/browser/message_port_service.h
index c3aeadb50a3..b46a7fa36b1 100644
--- a/chromium/content/browser/message_port_service.h
+++ b/chromium/content/browser/message_port_service.h
@@ -67,6 +67,9 @@ class CONTENT_EXPORT MessagePortService {
// clean up the port.
void HoldMessages(int message_port_id);
+ // Returns true if messages for a message port are on hold.
+ bool AreMessagesHeld(int message_port_id);
+
// Closes and cleans up the message port.
void ClosePort(int message_port_id);
diff --git a/chromium/content/browser/mojo/OWNERS b/chromium/content/browser/mojo/OWNERS
deleted file mode 100644
index 570120fdbb9..00000000000
--- a/chromium/content/browser/mojo/OWNERS
+++ /dev/null
@@ -1,13 +0,0 @@
-# Changes to the renderer capability filter require a security review to avoid
-# exposing new sandbox escapes and undesirable services.
-per-file renderer_capability_filter.cc=set noparent
-per-file renderer_capability_filter.cc=dcheng@chromium.org
-per-file renderer_capability_filter.cc=inferno@chromium.org
-per-file renderer_capability_filter.cc=jln@chromium.org
-per-file renderer_capability_filter.cc=jschuh@chromium.org
-per-file renderer_capability_filter.cc=kenrb@chromium.org
-per-file renderer_capability_filter.cc=mkwst@chromium.org
-per-file renderer_capability_filter.cc=nasko@chromium.org
-per-file renderer_capability_filter.cc=palmer@chromium.org
-per-file renderer_capability_filter.cc=tsepez@chromium.org
-per-file renderer_capability_filter.cc=wfh@chromium.org
diff --git a/chromium/content/browser/mojo/constants.cc b/chromium/content/browser/mojo/constants.cc
new file mode 100644
index 00000000000..cbb79379eeb
--- /dev/null
+++ b/chromium/content/browser/mojo/constants.cc
@@ -0,0 +1,19 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/mojo/constants.h"
+
+namespace content {
+
+// The default application name the browser identifies as when connecting to
+// the shell. This must match the name in
+// src/content/public/app/mojo/content_browser_manifest.json.
+const char kBrowserMojoApplicationName[] = "exe:content_browser";
+
+// The default application name used to identify render processes when
+// connecting them to the shell. This must match the name in
+// src/content/public/app/mojo/content_renderer_manifest.json.
+const char kRendererMojoApplicationName[] = "exe:content_renderer";
+
+} // namespace content
diff --git a/chromium/content/browser/mojo/constants.h b/chromium/content/browser/mojo/constants.h
new file mode 100644
index 00000000000..ed6120a5c33
--- /dev/null
+++ b/chromium/content/browser/mojo/constants.h
@@ -0,0 +1,15 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MOJO_CONSTANTS_H_
+#define CONTENT_BROWSER_MOJO_CONSTANTS_H_
+
+namespace content {
+
+extern const char kBrowserMojoApplicationName[];
+extern const char kRendererMojoApplicationName[];
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MOJO_CONSTANTS_H_
diff --git a/chromium/content/browser/mojo/mojo_app_connection_impl.cc b/chromium/content/browser/mojo/mojo_app_connection_impl.cc
index 2f55450eb12..b2941e2a5dc 100644
--- a/chromium/content/browser/mojo/mojo_app_connection_impl.cc
+++ b/chromium/content/browser/mojo/mojo_app_connection_impl.cc
@@ -9,39 +9,41 @@
#include "base/bind.h"
#include "content/browser/mojo/mojo_shell_context.h"
-#include "mojo/shell/capability_filter.h"
namespace content {
const char kBrowserMojoAppUrl[] = "system:content_browser";
namespace {
-void OnGotContentHandlerID(uint32_t content_handler_id) {}
+void OnGotInstanceID(mojo::shell::mojom::ConnectResult result,
+ const std::string& user_id, uint32_t remote_id) {}
} // namespace
// static
scoped_ptr<MojoAppConnection> MojoAppConnection::Create(
- const GURL& url,
- const GURL& requestor_url) {
+ const std::string& user_id,
+ const std::string& name,
+ const std::string& requestor_name) {
return scoped_ptr<MojoAppConnection>(
- new MojoAppConnectionImpl(url, requestor_url));
+ new MojoAppConnectionImpl(user_id, name, requestor_name));
}
-MojoAppConnectionImpl::MojoAppConnectionImpl(const GURL& url,
- const GURL& requestor_url) {
+MojoAppConnectionImpl::MojoAppConnectionImpl(
+ const std::string& user_id,
+ const std::string& name,
+ const std::string& requestor_name) {
MojoShellContext::ConnectToApplication(
- url, requestor_url, mojo::GetProxy(&services_),
- mojo::ServiceProviderPtr(), mojo::shell::GetPermissiveCapabilityFilter(),
- base::Bind(&OnGotContentHandlerID));
+ user_id, name, requestor_name, mojo::GetProxy(&interfaces_),
+ mojo::shell::mojom::InterfaceProviderPtr(), base::Bind(&OnGotInstanceID));
}
MojoAppConnectionImpl::~MojoAppConnectionImpl() {
}
-void MojoAppConnectionImpl::ConnectToService(
- const std::string& service_name,
+void MojoAppConnectionImpl::GetInterface(
+ const std::string& interface_name,
mojo::ScopedMessagePipeHandle handle) {
- services_->ConnectToService(service_name, std::move(handle));
+ interfaces_->GetInterface(interface_name, std::move(handle));
}
} // namespace content
diff --git a/chromium/content/browser/mojo/mojo_app_connection_impl.h b/chromium/content/browser/mojo/mojo_app_connection_impl.h
index 3cdfc591818..5ed747b2c5f 100644
--- a/chromium/content/browser/mojo/mojo_app_connection_impl.h
+++ b/chromium/content/browser/mojo/mojo_app_connection_impl.h
@@ -7,24 +7,26 @@
#include "base/macros.h"
#include "content/public/browser/mojo_app_connection.h"
-#include "mojo/shell/public/interfaces/service_provider.mojom.h"
-
-class GURL;
+#include "mojo/shell/public/interfaces/interface_provider.mojom.h"
namespace content {
// Implementation of the app connection mechanism provided to browser code.
class MojoAppConnectionImpl : public MojoAppConnection {
public:
- MojoAppConnectionImpl(const GURL& url, const GURL& requestor_url);
+ // Takes a BrowserContext and derives a mojo userid from it for this
+ // connection.
+ MojoAppConnectionImpl(const std::string& user_id,
+ const std::string& name,
+ const std::string& requestor_name);
~MojoAppConnectionImpl() override;
private:
// MojoAppConnection:
- void ConnectToService(const std::string& service_name,
- mojo::ScopedMessagePipeHandle handle) override;
+ void GetInterface(const std::string& interface_name,
+ mojo::ScopedMessagePipeHandle handle) override;
- mojo::ServiceProviderPtr services_;
+ mojo::shell::mojom::InterfaceProviderPtr interfaces_;
DISALLOW_COPY_AND_ASSIGN(MojoAppConnectionImpl);
};
diff --git a/chromium/content/browser/mojo/mojo_application_host.cc b/chromium/content/browser/mojo/mojo_application_host.cc
index 12895d5c353..c1103e15bbb 100644
--- a/chromium/content/browser/mojo/mojo_application_host.cc
+++ b/chromium/content/browser/mojo/mojo_application_host.cc
@@ -10,24 +10,15 @@
#include "content/common/mojo/mojo_messages.h"
#include "content/public/browser/browser_thread.h"
#include "ipc/ipc_sender.h"
-#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h"
+#include "mojo/edk/embedder/platform_channel_pair.h"
namespace content {
namespace {
-base::PlatformFile PlatformFileFromScopedPlatformHandle(
- mojo::embedder::ScopedPlatformHandle handle) {
-#if defined(OS_POSIX)
- return handle.release().fd;
-#elif defined(OS_WIN)
- return handle.release().handle;
-#endif
-}
-
-class ApplicationSetupImpl : public ApplicationSetup {
+class ApplicationSetupImpl : public mojom::ApplicationSetup {
public:
ApplicationSetupImpl(ServiceRegistryImpl* service_registry,
- mojo::InterfaceRequest<ApplicationSetup> request)
+ mojo::InterfaceRequest<mojom::ApplicationSetup> request)
: binding_(this, std::move(request)),
service_registry_(service_registry) {}
@@ -35,25 +26,24 @@ class ApplicationSetupImpl : public ApplicationSetup {
}
private:
- // ApplicationSetup implementation.
- void ExchangeServiceProviders(
- mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services) override {
+ // mojom::ApplicationSetup implementation.
+ void ExchangeInterfaceProviders(
+ mojo::shell::mojom::InterfaceProviderRequest services,
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services) override {
service_registry_->Bind(std::move(services));
service_registry_->BindRemoteServiceProvider(std::move(exposed_services));
}
- mojo::Binding<ApplicationSetup> binding_;
+ mojo::Binding<mojom::ApplicationSetup> binding_;
ServiceRegistryImpl* service_registry_;
};
} // namespace
-MojoApplicationHost::MojoApplicationHost()
- : did_activate_(false) {
+MojoApplicationHost::MojoApplicationHost() : did_activate_(false) {
#if defined(OS_ANDROID)
- service_registry_android_.reset(
- new ServiceRegistryAndroid(&service_registry_));
+ service_registry_android_ =
+ ServiceRegistryAndroid::Create(&service_registry_);
#endif
}
@@ -63,7 +53,7 @@ MojoApplicationHost::~MojoApplicationHost() {
bool MojoApplicationHost::Init() {
DCHECK(!client_handle_.is_valid()) << "Already initialized!";
- mojo::embedder::PlatformChannelPair channel_pair;
+ mojo::edk::PlatformChannelPair channel_pair;
scoped_refptr<base::TaskRunner> io_task_runner;
if (io_task_runner_override_) {
@@ -74,18 +64,13 @@ bool MojoApplicationHost::Init() {
->task_runner();
}
- mojo::ScopedMessagePipeHandle message_pipe = channel_init_.Init(
- PlatformFileFromScopedPlatformHandle(channel_pair.PassServerHandle()),
- io_task_runner);
- if (!message_pipe.is_valid())
- return false;
-
// Forward this to the client once we know its process handle.
client_handle_ = channel_pair.PassClientHandle();
-
+ mojo::ScopedMessagePipeHandle pipe = channel_init_.Init(
+ channel_pair.PassServerHandle().release().handle, io_task_runner);
application_setup_.reset(new ApplicationSetupImpl(
&service_registry_,
- mojo::MakeRequest<ApplicationSetup>(std::move(message_pipe))));
+ mojo::MakeRequest<mojom::ApplicationSetup>(std::move(pipe))));
return true;
}
@@ -94,14 +79,9 @@ void MojoApplicationHost::Activate(IPC::Sender* sender,
DCHECK(!did_activate_);
DCHECK(client_handle_.is_valid());
- base::PlatformFile client_file =
- PlatformFileFromScopedPlatformHandle(std::move(client_handle_));
+ base::PlatformFile client_file = client_handle_.release().handle;
did_activate_ = sender->Send(new MojoMsg_Activate(
- IPC::GetFileHandleForProcess(client_file, process_handle, true)));
-}
-
-void MojoApplicationHost::WillDestroySoon() {
- channel_init_.WillDestroySoon();
+ IPC::GetPlatformFileForTransit(client_file, true)));
}
void MojoApplicationHost::OverrideIOTaskRunnerForTest(
@@ -109,4 +89,5 @@ void MojoApplicationHost::OverrideIOTaskRunnerForTest(
io_task_runner_override_ = io_task_runner;
}
+
} // namespace content
diff --git a/chromium/content/browser/mojo/mojo_application_host.h b/chromium/content/browser/mojo/mojo_application_host.h
index 0ed8ec917ba..3f3387accea 100644
--- a/chromium/content/browser/mojo/mojo_application_host.h
+++ b/chromium/content/browser/mojo/mojo_application_host.h
@@ -12,10 +12,11 @@
#include "content/common/application_setup.mojom.h"
#include "content/common/mojo/channel_init.h"
#include "content/common/mojo/service_registry_impl.h"
-#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h"
+#include "mojo/edk/embedder/scoped_platform_handle.h"
+#include "mojo/public/cpp/system/message_pipe.h"
#if defined(OS_ANDROID)
-#include "content/browser/mojo/service_registry_android.h"
+#include "content/public/browser/android/service_registry_android.h"
#endif
namespace IPC {
@@ -40,8 +41,6 @@ class CONTENT_EXPORT MojoApplicationHost {
bool Init();
void Activate(IPC::Sender* sender, base::ProcessHandle process_handle);
- void WillDestroySoon();
-
ServiceRegistry* service_registry() { return &service_registry_; }
#if defined(OS_ANDROID)
@@ -55,11 +54,11 @@ class CONTENT_EXPORT MojoApplicationHost {
private:
ChannelInit channel_init_;
- mojo::embedder::ScopedPlatformHandle client_handle_;
+ mojo::edk::ScopedPlatformHandle client_handle_;
bool did_activate_;
- scoped_ptr<ApplicationSetup> application_setup_;
+ scoped_ptr<mojom::ApplicationSetup> application_setup_;
ServiceRegistryImpl service_registry_;
scoped_refptr<base::TaskRunner> io_task_runner_override_;
diff --git a/chromium/content/browser/mojo/mojo_child_connection.cc b/chromium/content/browser/mojo/mojo_child_connection.cc
new file mode 100644
index 00000000000..164ba0b027b
--- /dev/null
+++ b/chromium/content/browser/mojo/mojo_child_connection.cc
@@ -0,0 +1,137 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/mojo/mojo_child_connection.h"
+
+#include <stdint.h>
+#include <utility>
+
+#include "base/macros.h"
+#include "base/strings/stringprintf.h"
+#include "base/thread_task_runner_handle.h"
+#include "build/build_config.h"
+#include "content/browser/mojo/constants.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_process_host_observer.h"
+#include "content/public/common/mojo_shell_connection.h"
+#include "ipc/ipc_sender.h"
+#include "mojo/edk/embedder/embedder.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+#include "mojo/shell/public/cpp/connector.h"
+#include "mojo/shell/public/interfaces/shell.mojom.h"
+#include "mojo/shell/public/interfaces/shell_client.mojom.h"
+
+namespace content {
+namespace {
+
+const char kMojoRenderProcessHostConnection[] =
+ "mojo_render_process_host_connection";
+
+class RenderProcessHostConnection : public base::SupportsUserData::Data {
+ public:
+ explicit RenderProcessHostConnection(scoped_ptr<mojo::Connection> connection)
+ : connection_(std::move(connection)) {}
+ ~RenderProcessHostConnection() override {}
+
+ mojo::Connection* get() const { return connection_.get(); }
+
+ private:
+ scoped_ptr<mojo::Connection> connection_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderProcessHostConnection);
+};
+
+void SetMojoConnection(RenderProcessHost* render_process_host,
+ scoped_ptr<mojo::Connection> connection) {
+ render_process_host->SetUserData(
+ kMojoRenderProcessHostConnection,
+ new RenderProcessHostConnection(std::move(connection)));
+}
+
+class PIDSender : public RenderProcessHostObserver {
+ public:
+ PIDSender(
+ RenderProcessHost* host,
+ mojo::shell::mojom::PIDReceiverPtr pid_receiver)
+ : host_(host),
+ pid_receiver_(std::move(pid_receiver)) {
+ pid_receiver_.set_connection_error_handler([this]() { delete this; });
+ DCHECK(!host_->IsReady());
+ host_->AddObserver(this);
+ }
+ ~PIDSender() override {
+ if (host_)
+ host_->RemoveObserver(this);
+ }
+
+ private:
+ // Overridden from RenderProcessHostObserver:
+ void RenderProcessReady(RenderProcessHost* host) override {
+ pid_receiver_->SetPID(base::GetProcId(host->GetHandle()));
+ delete this;
+ }
+
+ void RenderProcessHostDestroyed(RenderProcessHost* host) override {
+ DCHECK_EQ(host_, host);
+ host_ = nullptr;
+ }
+
+ RenderProcessHost* host_;
+ mojo::shell::mojom::PIDReceiverPtr pid_receiver_;
+
+ DISALLOW_COPY_AND_ASSIGN(PIDSender);
+};
+
+} // namespace
+
+std::string MojoConnectToChild(int child_process_id,
+ int instance_id,
+ RenderProcessHost* render_process_host) {
+ // Generate a token and create a pipe which is bound to it. This pipe is
+ // passed to the shell if one is available.
+ std::string pipe_token = mojo::edk::GenerateRandomToken();
+ mojo::ScopedMessagePipeHandle shell_client_pipe =
+ mojo::edk::CreateParentMessagePipe(pipe_token);
+
+ // Some process types get created before the main message loop. In this case
+ // the shell request pipe will simply be closed, and the child can detect
+ // this.
+ if (!MojoShellConnection::Get())
+ return pipe_token;
+
+ mojo::shell::mojom::ShellClientPtr client;
+ client.Bind(mojo::InterfacePtrInfo<mojo::shell::mojom::ShellClient>(
+ std::move(shell_client_pipe), 0u));
+ mojo::shell::mojom::PIDReceiverPtr pid_receiver;
+ mojo::shell::mojom::PIDReceiverRequest pid_receiver_request =
+ GetProxy(&pid_receiver);
+ // PIDSender manages its own lifetime.
+ new PIDSender(render_process_host, std::move(pid_receiver));
+
+ mojo::Identity target(kRendererMojoApplicationName,
+ mojo::shell::mojom::kInheritUserID,
+ base::StringPrintf("%d_%d", child_process_id,
+ instance_id));
+ mojo::Connector::ConnectParams params(target);
+ params.set_client_process_connection(std::move(client),
+ std::move(pid_receiver_request));
+ scoped_ptr<mojo::Connection> connection =
+ MojoShellConnection::Get()->GetConnector()->Connect(&params);
+
+ // Store the connection on the RPH so client code can access it later via
+ // GetMojoConnection().
+ SetMojoConnection(render_process_host, std::move(connection));
+
+ return pipe_token;
+}
+
+mojo::Connection* GetMojoConnection(RenderProcessHost* render_process_host) {
+ RenderProcessHostConnection* connection =
+ static_cast<RenderProcessHostConnection*>(
+ render_process_host->GetUserData(kMojoRenderProcessHostConnection));
+ return connection ? connection->get() : nullptr;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/mojo/mojo_child_connection.h b/chromium/content/browser/mojo/mojo_child_connection.h
new file mode 100644
index 00000000000..2270ce72c34
--- /dev/null
+++ b/chromium/content/browser/mojo/mojo_child_connection.h
@@ -0,0 +1,36 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_MOJO_MOJO_CHILD_CONNECTION_H_
+#define CONTENT_BROWSER_MOJO_MOJO_CHILD_CONNECTION_H_
+
+#include <string>
+
+#include "base/process/process_handle.h"
+#include "mojo/shell/public/interfaces/shell.mojom.h"
+
+namespace mojo {
+class Connection;
+}
+
+namespace content {
+
+class RenderProcessHost;
+
+// Establish a mojo::Connection to the child process, using a pipe created for
+// that purpose. Returns a token that should be passed to the child process and
+// exchanged for a pipe there. That pipe can in turn be passed to
+// MojoShellConnectionImpl::BindToMessagePipe() to initialize the child's
+// shell connection.
+std::string MojoConnectToChild(int child_process_id,
+ int instance_id,
+ RenderProcessHost* render_process_host);
+
+// Returns a mojo connection to the provided render process host. This
+// connection was opened when MojoConnectToChild() was called.
+mojo::Connection* GetMojoConnection(RenderProcessHost* render_process_host);
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_MOJO_MOJO_CHILD_CONNECTION_H_
diff --git a/chromium/content/browser/mojo/mojo_shell_client_host.cc b/chromium/content/browser/mojo/mojo_shell_client_host.cc
deleted file mode 100644
index 326afebb051..00000000000
--- a/chromium/content/browser/mojo/mojo_shell_client_host.cc
+++ /dev/null
@@ -1,219 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/mojo/mojo_shell_client_host.h"
-
-#include <stdint.h>
-#include <utility>
-
-#include "base/macros.h"
-#include "base/strings/stringprintf.h"
-#include "base/thread_task_runner_handle.h"
-#include "build/build_config.h"
-#include "content/common/mojo/mojo_messages.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/render_process_host.h"
-#include "content/public/browser/render_process_host_observer.h"
-#include "content/public/common/mojo_shell_connection.h"
-#include "ipc/ipc_sender.h"
-#include "mojo/converters/network/network_type_converters.h"
-#include "mojo/shell/public/cpp/application_impl.h"
-#include "mojo/shell/public/interfaces/application_manager.mojom.h"
-#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
-#include "third_party/mojo/src/mojo/edk/embedder/platform_channel_pair.h"
-#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h"
-
-namespace content {
-namespace {
-
-const char kMojoShellInstanceURL[] = "mojo_shell_instance_url";
-const char kMojoPlatformFile[] = "mojo_platform_file";
-
-void DidCreateChannel(mojo::embedder::ChannelInfo* info) {}
-
-base::PlatformFile PlatformFileFromScopedPlatformHandle(
- mojo::embedder::ScopedPlatformHandle handle) {
-#if defined(OS_POSIX)
- return handle.release().fd;
-#elif defined(OS_WIN)
- return handle.release().handle;
-#endif
-}
-
-class InstanceURL : public base::SupportsUserData::Data {
- public:
- InstanceURL(const std::string& instance_url) : instance_url_(instance_url) {}
- ~InstanceURL() override {}
-
- std::string get() const { return instance_url_; }
-
- private:
- std::string instance_url_;
-
- DISALLOW_COPY_AND_ASSIGN(InstanceURL);
-};
-
-class InstanceShellHandle : public base::SupportsUserData::Data {
- public:
- InstanceShellHandle(base::PlatformFile shell_handle)
- : shell_handle_(shell_handle) {}
- ~InstanceShellHandle() override {}
-
- base::PlatformFile get() const { return shell_handle_; }
-
- private:
- base::PlatformFile shell_handle_;
-
- DISALLOW_COPY_AND_ASSIGN(InstanceShellHandle);
-};
-
-void SetMojoApplicationInstanceURL(RenderProcessHost* render_process_host,
- const std::string& instance_url) {
- render_process_host->SetUserData(kMojoShellInstanceURL,
- new InstanceURL(instance_url));
-}
-
-void SetMojoPlatformFile(RenderProcessHost* render_process_host,
- base::PlatformFile platform_file) {
- render_process_host->SetUserData(kMojoPlatformFile,
- new InstanceShellHandle(platform_file));
-}
-
-void CallRegisterProcessWithBroker(base::ProcessId pid,
- MojoHandle client_pipe) {
- mojo::shell::mojom::ApplicationManagerPtr application_manager;
- MojoShellConnection::Get()->GetApplication()->ConnectToService(
- "mojo:shell", &application_manager);
- application_manager->RegisterProcessWithBroker(
- static_cast<uint32_t>(pid),
- mojo::ScopedHandle(mojo::Handle(client_pipe)));
-}
-
-class PIDSender : public RenderProcessHostObserver {
- public:
- PIDSender(
- RenderProcessHost* host,
- mojo::shell::mojom::PIDReceiverPtr pid_receiver)
- : host_(host),
- pid_receiver_(std::move(pid_receiver)) {
- pid_receiver_.set_connection_error_handler([this]() { delete this; });
- DCHECK(!host_->IsReady());
- host_->AddObserver(this);
- }
- ~PIDSender() override {
- if (host_)
- host_->RemoveObserver(this);
- }
-
- private:
- // Overridden from RenderProcessHostObserver:
- void RenderProcessReady(RenderProcessHost* host) override {
- pid_receiver_->SetPID(base::GetProcId(host->GetHandle()));
- delete this;
- }
-
- void RenderProcessHostDestroyed(RenderProcessHost* host) override {
- DCHECK_EQ(host_, host);
- host_ = nullptr;
- }
-
- RenderProcessHost* host_;
- mojo::shell::mojom::PIDReceiverPtr pid_receiver_;
-
- DISALLOW_COPY_AND_ASSIGN(PIDSender);
-};
-
-} // namespace
-
-void RegisterChildWithExternalShell(int child_process_id,
- RenderProcessHost* render_process_host) {
- // Some process types get created before the main message loop.
- if (!MojoShellConnection::Get())
- return;
-
- // Create the channel to be shared with the target process.
- mojo::embedder::HandlePassingInformation handle_passing_info;
- mojo::embedder::PlatformChannelPair platform_channel_pair;
-
- // Give one end to the shell so that it can create an instance.
- mojo::embedder::ScopedPlatformHandle platform_channel =
- platform_channel_pair.PassServerHandle();
- mojo::ScopedMessagePipeHandle handle(mojo::embedder::CreateChannel(
- std::move(platform_channel), base::Bind(&DidCreateChannel),
- base::ThreadTaskRunnerHandle::Get()));
- mojo::shell::mojom::ApplicationManagerPtr application_manager;
- MojoShellConnection::Get()->GetApplication()->ConnectToService(
- "mojo:shell", &application_manager);
- // The content of the URL/qualifier we pass is actually meaningless, it's only
- // important that they're unique per process.
- // TODO(beng): We need to specify a restrictive CapabilityFilter here that
- // matches the needs of the target process. Figure out where that
- // specification is best determined (not here, this is a common
- // chokepoint for all process types) and how to wire it through.
- // http://crbug.com/555393
- std::string url =
- base::StringPrintf("exe:chrome_renderer%d", child_process_id);
-
- mojo::shell::mojom::PIDReceiverPtr pid_receiver;
- mojo::InterfaceRequest<mojo::shell::mojom::PIDReceiver> request =
- GetProxy(&pid_receiver);
- new PIDSender(render_process_host, std::move(pid_receiver));
-
- application_manager->CreateInstanceForHandle(
- mojo::ScopedHandle(mojo::Handle(handle.release().value())),
- url,
- CreateCapabilityFilterForRenderer(),
- std::move(request));
-
- // Send the other end to the child via Chrome IPC.
- base::PlatformFile client_file = PlatformFileFromScopedPlatformHandle(
- platform_channel_pair.PassClientHandle());
- SetMojoPlatformFile(render_process_host, client_file);
-
- // Store the URL on the RPH so client code can access it later via
- // GetMojoApplicationInstanceURL().
- SetMojoApplicationInstanceURL(render_process_host, url);
-}
-
-std::string GetMojoApplicationInstanceURL(
- RenderProcessHost* render_process_host) {
- InstanceURL* instance_url = static_cast<InstanceURL*>(
- render_process_host->GetUserData(kMojoShellInstanceURL));
- return instance_url ? instance_url->get() : std::string();
-}
-
-void SendExternalMojoShellHandleToChild(
- base::ProcessHandle process_handle,
- RenderProcessHost* render_process_host) {
- InstanceShellHandle* client_file = static_cast<InstanceShellHandle*>(
- render_process_host->GetUserData(kMojoPlatformFile));
- if (!client_file)
- return;
- render_process_host->Send(new MojoMsg_BindExternalMojoShellHandle(
- IPC::GetFileHandleForProcess(client_file->get(), process_handle, true)));
-}
-
-mojo::embedder::ScopedPlatformHandle RegisterProcessWithBroker(
- base::ProcessId pid) {
- mojo::embedder::PlatformChannelPair platform_channel_pair;
-
- MojoHandle platform_handle_wrapper;
- MojoResult rv = mojo::embedder::CreatePlatformHandleWrapper(
- platform_channel_pair.PassServerHandle(), &platform_handle_wrapper);
- CHECK_EQ(rv, MOJO_RESULT_OK);
-
- if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- CallRegisterProcessWithBroker(pid, platform_handle_wrapper);
- } else {
- BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
- base::Bind(CallRegisterProcessWithBroker, pid,
- platform_handle_wrapper));
- }
-
- return platform_channel_pair.PassClientHandle();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/mojo/mojo_shell_client_host.h b/chromium/content/browser/mojo/mojo_shell_client_host.h
deleted file mode 100644
index 5624643a8e7..00000000000
--- a/chromium/content/browser/mojo/mojo_shell_client_host.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_MOJO_MOJO_SHELL_CLIENT_HOST_H_
-#define CONTENT_BROWSER_MOJO_MOJO_SHELL_CLIENT_HOST_H_
-
-#include <string>
-
-#include "base/process/process_handle.h"
-#include "mojo/shell/public/interfaces/shell.mojom.h"
-#include "third_party/mojo/src/mojo/edk/embedder/scoped_platform_handle.h"
-
-namespace content {
-
-class RenderProcessHost;
-
-// Creates a communication channel between the external Mojo shell and the
-// child. The server handle of this channel is shared with the external shell
-// via Mojo IPC. |child_process_id| is used to uniquify the child in the
-// external shell's instance map.
-void RegisterChildWithExternalShell(int child_process_id,
- RenderProcessHost* render_process_host);
-
-// Returns the URL associated with an instance corresponding to the renderer
-// process in the external shell. This URL can be passed to
-// ConnectToApplication() to open a new connection to this renderer.
-std::string GetMojoApplicationInstanceURL(
- RenderProcessHost* render_process_host);
-
-// Shares a client handle to the Mojo Shell with the child via Chrome IPC.
-void SendExternalMojoShellHandleToChild(base::ProcessHandle process_handle,
- RenderProcessHost* render_process_host);
-
-// Constructs a Capability Filter for the renderer's application instance in the
-// external shell. This contains the restrictions imposed on what applications
-// and interfaces the renderer can see. The implementation lives in
-// renderer_capability_filter.cc so that it can be subject to specific security
-// review.
-mojo::CapabilityFilterPtr CreateCapabilityFilterForRenderer();
-
-// Used for the broker in the new EDK.
-mojo::embedder::ScopedPlatformHandle RegisterProcessWithBroker(
- base::ProcessId pid);
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_MOJO_MOJO_SHELL_CLIENT_HOST_H_
diff --git a/chromium/content/browser/mojo/mojo_shell_context.cc b/chromium/content/browser/mojo/mojo_shell_context.cc
index 199744d3cb6..55ef2985255 100644
--- a/chromium/content/browser/mojo/mojo_shell_context.cc
+++ b/chromium/content/browser/mojo/mojo_shell_context.cc
@@ -6,34 +6,41 @@
#include <utility>
+#include "base/bind.h"
+#include "base/command_line.h"
#include "base/lazy_instance.h"
#include "base/macros.h"
#include "base/path_service.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
+#include "components/profile_service/profile_app.h"
#include "content/browser/gpu/gpu_process_host.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
+#include "content/browser/mojo/constants.h"
+#include "content/common/gpu_process_launch_causes.h"
+#include "content/common/mojo/current_thread_loader.h"
+#include "content/common/mojo/mojo_shell_connection_impl.h"
+#include "content/common/mojo/static_loader.h"
#include "content/common/process_control.mojom.h"
+#include "content/grit/content_resources.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/utility_process_host.h"
#include "content/public/browser/utility_process_host_client.h"
#include "content/public/common/content_client.h"
+#include "content/public/common/content_switches.h"
#include "content/public/common/service_registry.h"
-#include "mojo/common/url_type_converters.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/bindings/string.h"
-#include "mojo/shell/application_loader.h"
-#include "mojo/shell/connect_to_application_params.h"
-#include "mojo/shell/identity.h"
-#include "mojo/shell/package_manager/package_manager_impl.h"
-#include "mojo/shell/public/cpp/application_delegate.h"
-#include "mojo/shell/static_application_loader.h"
-
-#if defined(ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS) || \
- defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
-#include "media/mojo/services/mojo_media_application.h"
-#endif
+#include "mojo/services/catalog/factory.h"
+#include "mojo/services/catalog/manifest_provider.h"
+#include "mojo/services/catalog/store.h"
+#include "mojo/shell/connect_params.h"
+#include "mojo/shell/loader.h"
+#include "mojo/shell/native_runner.h"
+#include "mojo/shell/public/cpp/identity.h"
+#include "mojo/shell/public/cpp/shell_client.h"
+#include "mojo/shell/public/interfaces/connector.mojom.h"
+#include "mojo/shell/runner/host/in_process_native_runner.h"
namespace content {
@@ -43,7 +50,7 @@ namespace {
const MojoShellContext::StaticApplicationMap* g_applications_for_test;
void StartUtilityProcessOnIOThread(
- mojo::InterfaceRequest<ProcessControl> request,
+ mojo::InterfaceRequest<mojom::ProcessControl> request,
const base::string16& process_name,
bool use_sandbox) {
UtilityProcessHost* process_host =
@@ -51,55 +58,53 @@ void StartUtilityProcessOnIOThread(
process_host->SetName(process_name);
if (!use_sandbox)
process_host->DisableSandbox();
- process_host->StartMojoMode();
+ process_host->Start();
ServiceRegistry* services = process_host->GetServiceRegistry();
services->ConnectToRemoteService(std::move(request));
}
-void OnApplicationLoaded(const GURL& url, bool success) {
+void OnApplicationLoaded(const std::string& name, bool success) {
if (!success)
- LOG(ERROR) << "Failed to launch Mojo application for " << url.spec();
+ LOG(ERROR) << "Failed to launch Mojo application for " << name;
}
// The default loader to use for all applications. This does nothing but drop
// the Application request.
-class DefaultApplicationLoader : public mojo::shell::ApplicationLoader {
+class DefaultLoader : public mojo::shell::Loader {
public:
- DefaultApplicationLoader() {}
- ~DefaultApplicationLoader() override {}
+ DefaultLoader() {}
+ ~DefaultLoader() override {}
private:
- // mojo::shell::ApplicationLoader:
- void Load(
- const GURL& url,
- mojo::InterfaceRequest<mojo::Application> application_request) override {}
+ // mojo::shell::Loader:
+ void Load(const std::string& name,
+ mojo::shell::mojom::ShellClientRequest request) override {}
- DISALLOW_COPY_AND_ASSIGN(DefaultApplicationLoader);
+ DISALLOW_COPY_AND_ASSIGN(DefaultLoader);
};
// This launches a utility process and forwards the Load request the
-// ProcessControl service there. The utility process is sandboxed iff
+// mojom::ProcessControl service there. The utility process is sandboxed iff
// |use_sandbox| is true.
-class UtilityProcessLoader : public mojo::shell::ApplicationLoader {
+class UtilityProcessLoader : public mojo::shell::Loader {
public:
UtilityProcessLoader(const base::string16& process_name, bool use_sandbox)
: process_name_(process_name), use_sandbox_(use_sandbox) {}
~UtilityProcessLoader() override {}
private:
- // mojo::shell::ApplicationLoader:
- void Load(
- const GURL& url,
- mojo::InterfaceRequest<mojo::Application> application_request) override {
- ProcessControlPtr process_control;
+ // mojo::shell::Loader:
+ void Load(const std::string& name,
+ mojo::shell::mojom::ShellClientRequest request) override {
+ mojom::ProcessControlPtr process_control;
auto process_request = mojo::GetProxy(&process_control);
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(&StartUtilityProcessOnIOThread,
base::Passed(&process_request),
process_name_, use_sandbox_));
- process_control->LoadApplication(url.spec(), std::move(application_request),
- base::Bind(&OnApplicationLoaded, url));
+ process_control->LoadApplication(name, std::move(request),
+ base::Bind(&OnApplicationLoaded, name));
}
const base::string16 process_name_;
@@ -108,8 +113,10 @@ class UtilityProcessLoader : public mojo::shell::ApplicationLoader {
DISALLOW_COPY_AND_ASSIGN(UtilityProcessLoader);
};
-// Request ProcessControl from GPU process host. Must be called on IO thread.
-void RequestGpuProcessControl(mojo::InterfaceRequest<ProcessControl> request) {
+// Request mojom::ProcessControl from GPU process host. Must be called on IO
+// thread.
+void RequestGpuProcessControl(
+ mojo::InterfaceRequest<mojom::ProcessControl> request) {
BrowserChildProcessHostDelegate* process_host =
GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
CAUSE_FOR_GPU_LAUNCH_MOJO_SETUP);
@@ -120,37 +127,72 @@ void RequestGpuProcessControl(mojo::InterfaceRequest<ProcessControl> request) {
// TODO(xhwang): It's possible that |process_host| is non-null, but the actual
// process is dead. In that case, |request| will be dropped and application
- // load requests through ProcessControl will also fail. Make sure we handle
+ // load requests through mojom::ProcessControl will also fail. Make sure we
+ // handle
// these cases correctly.
process_host->GetServiceRegistry()->ConnectToRemoteService(
std::move(request));
}
// Forwards the load request to the GPU process.
-class GpuProcessLoader : public mojo::shell::ApplicationLoader {
+class GpuProcessLoader : public mojo::shell::Loader {
public:
GpuProcessLoader() {}
~GpuProcessLoader() override {}
private:
- // mojo::shell::ApplicationLoader:
- void Load(
- const GURL& url,
- mojo::InterfaceRequest<mojo::Application> application_request) override {
- ProcessControlPtr process_control;
+ // mojo::shell::Loader:
+ void Load(const std::string& name,
+ mojo::shell::mojom::ShellClientRequest request) override {
+ mojom::ProcessControlPtr process_control;
auto process_request = mojo::GetProxy(&process_control);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&RequestGpuProcessControl, base::Passed(&process_request)));
- process_control->LoadApplication(url.spec(), std::move(application_request),
- base::Bind(&OnApplicationLoaded, url));
+ process_control->LoadApplication(name, std::move(request),
+ base::Bind(&OnApplicationLoaded, name));
}
DISALLOW_COPY_AND_ASSIGN(GpuProcessLoader);
};
+std::string GetStringResource(int id) {
+ return GetContentClient()->GetDataResource(
+ id, ui::ScaleFactor::SCALE_FACTOR_NONE).as_string();
+}
+
} // namespace
+// A ManifestProvider which resolves application names to builtin manifest
+// resources for the catalog service to consume.
+class MojoShellContext::BuiltinManifestProvider
+ : public catalog::ManifestProvider {
+ public:
+ BuiltinManifestProvider() {}
+ ~BuiltinManifestProvider() override {}
+
+ private:
+ // catalog::ManifestProvider:
+ bool GetApplicationManifest(const base::StringPiece& name,
+ std::string* manifest_contents) override {
+ if (name == "mojo:catalog") {
+ *manifest_contents = GetStringResource(IDR_MOJO_CATALOG_MANIFEST);
+ return true;
+ } else if (name == kBrowserMojoApplicationName) {
+ *manifest_contents = GetStringResource(IDR_MOJO_CONTENT_BROWSER_MANIFEST);
+ return true;
+ } else if (name == kRendererMojoApplicationName) {
+ *manifest_contents =
+ GetStringResource(IDR_MOJO_CONTENT_RENDERER_MANIFEST);
+ return true;
+ }
+
+ return false;
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(BuiltinManifestProvider);
+};
+
// Thread-safe proxy providing access to the shell context from any thread.
class MojoShellContext::Proxy {
public:
@@ -161,17 +203,17 @@ class MojoShellContext::Proxy {
~Proxy() {}
void ConnectToApplication(
- const GURL& url,
- const GURL& requestor_url,
- mojo::InterfaceRequest<mojo::ServiceProvider> request,
- mojo::ServiceProviderPtr exposed_services,
- const mojo::shell::CapabilityFilter& filter,
- const mojo::Shell::ConnectToApplicationCallback& callback) {
+ const std::string& user_id,
+ const std::string& name,
+ const std::string& requestor_name,
+ mojo::shell::mojom::InterfaceProviderRequest request,
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services,
+ const mojo::shell::mojom::Connector::ConnectCallback& callback) {
if (task_runner_ == base::ThreadTaskRunnerHandle::Get()) {
if (shell_context_) {
shell_context_->ConnectToApplicationOnOwnThread(
- url, requestor_url, std::move(request), std::move(exposed_services),
- filter, callback);
+ user_id, name, requestor_name, std::move(request),
+ std::move(exposed_services), callback);
}
} else {
// |shell_context_| outlives the main MessageLoop, so it's safe for it to
@@ -179,9 +221,9 @@ class MojoShellContext::Proxy {
task_runner_->PostTask(
FROM_HERE,
base::Bind(&MojoShellContext::ConnectToApplicationOnOwnThread,
- base::Unretained(shell_context_), url, requestor_url,
- base::Passed(&request), base::Passed(&exposed_services),
- filter, callback));
+ base::Unretained(shell_context_), user_id, name,
+ requestor_name, base::Passed(&request),
+ base::Passed(&exposed_services), callback));
}
}
@@ -201,18 +243,23 @@ void MojoShellContext::SetApplicationsForTest(
g_applications_for_test = apps;
}
-MojoShellContext::MojoShellContext() {
+MojoShellContext::MojoShellContext(
+ scoped_refptr<base::SingleThreadTaskRunner> file_thread,
+ scoped_refptr<base::SingleThreadTaskRunner> db_thread) {
proxy_.Get().reset(new Proxy(this));
- // Construct with an empty filepath since mojo: urls can't be registered now
- // the url scheme registry is locked.
- scoped_ptr<mojo::shell::PackageManagerImpl> package_manager(
- new mojo::shell::PackageManagerImpl(base::FilePath(), nullptr));
- application_manager_.reset(
- new mojo::shell::ApplicationManager(std::move(package_manager)));
-
- application_manager_->set_default_loader(
- scoped_ptr<mojo::shell::ApplicationLoader>(new DefaultApplicationLoader));
+ scoped_refptr<base::SingleThreadTaskRunner> file_task_runner =
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE);
+ scoped_ptr<mojo::shell::NativeRunnerFactory> native_runner_factory(
+ new mojo::shell::InProcessNativeRunnerFactory(
+ BrowserThread::GetBlockingPool()));
+ manifest_provider_.reset(new BuiltinManifestProvider);
+ catalog_.reset(new catalog::Factory(file_task_runner.get(), nullptr,
+ manifest_provider_.get()));
+ shell_.reset(new mojo::shell::Shell(std::move(native_runner_factory),
+ catalog_->TakeShellClient()));
+ shell_->set_default_loader(
+ scoped_ptr<mojo::shell::Loader>(new DefaultLoader));
StaticApplicationMap apps;
GetContentClient()->browser()->RegisterInProcessMojoApplications(&apps);
@@ -223,10 +270,8 @@ MojoShellContext::MojoShellContext() {
apps[entry.first] = entry.second;
}
for (const auto& entry : apps) {
- application_manager_->SetLoaderForURL(
- scoped_ptr<mojo::shell::ApplicationLoader>(
- new mojo::shell::StaticApplicationLoader(entry.second)),
- entry.first);
+ shell_->SetLoaderForName(
+ make_scoped_ptr(new StaticLoader(entry.second)), entry.first);
}
ContentBrowserClient::OutOfProcessMojoApplicationMap sandboxed_apps;
@@ -234,8 +279,8 @@ MojoShellContext::MojoShellContext() {
->browser()
->RegisterOutOfProcessMojoApplications(&sandboxed_apps);
for (const auto& app : sandboxed_apps) {
- application_manager_->SetLoaderForURL(
- scoped_ptr<mojo::shell::ApplicationLoader>(
+ shell_->SetLoaderForName(
+ make_scoped_ptr(
new UtilityProcessLoader(app.second, true /* use_sandbox */)),
app.first);
}
@@ -245,59 +290,65 @@ MojoShellContext::MojoShellContext() {
->browser()
->RegisterUnsandboxedOutOfProcessMojoApplications(&unsandboxed_apps);
for (const auto& app : unsandboxed_apps) {
- application_manager_->SetLoaderForURL(
- scoped_ptr<mojo::shell::ApplicationLoader>(
+ shell_->SetLoaderForName(
+ make_scoped_ptr(
new UtilityProcessLoader(app.second, false /* use_sandbox */)),
app.first);
}
-#if (ENABLE_MOJO_MEDIA_IN_BROWSER_PROCESS)
- application_manager_->SetLoaderForURL(
- scoped_ptr<mojo::shell::ApplicationLoader>(
- new mojo::shell::StaticApplicationLoader(
- base::Bind(&media::MojoMediaApplication::CreateApp))),
- GURL("mojo:media"));
-#elif(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
- application_manager_->SetLoaderForURL(
- scoped_ptr<mojo::shell::ApplicationLoader>(new GpuProcessLoader()),
- GURL("mojo:media"));
+#if (ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
+ shell_->SetLoaderForName(make_scoped_ptr(new GpuProcessLoader), "mojo:media");
#endif
+
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kMojoLocalStorage)) {
+ base::Callback<scoped_ptr<mojo::ShellClient>()> profile_callback =
+ base::Bind(&profile::CreateProfileApp, file_thread, db_thread);
+ shell_->SetLoaderForName(
+ make_scoped_ptr(new CurrentThreadLoader(profile_callback)),
+ "mojo:profile");
+ }
+
+ if (!IsRunningInMojoShell()) {
+ MojoShellConnection::Create(
+ shell_->InitInstanceForEmbedder(kBrowserMojoApplicationName),
+ false /* is_external */);
+ }
}
MojoShellContext::~MojoShellContext() {
+ if (!IsRunningInMojoShell())
+ MojoShellConnectionImpl::Destroy();
}
// static
void MojoShellContext::ConnectToApplication(
- const GURL& url,
- const GURL& requestor_url,
- mojo::InterfaceRequest<mojo::ServiceProvider> request,
- mojo::ServiceProviderPtr exposed_services,
- const mojo::shell::CapabilityFilter& filter,
- const mojo::Shell::ConnectToApplicationCallback& callback) {
- proxy_.Get()->ConnectToApplication(url, requestor_url, std::move(request),
- std::move(exposed_services), filter,
- callback);
+ const std::string& user_id,
+ const std::string& name,
+ const std::string& requestor_name,
+ mojo::shell::mojom::InterfaceProviderRequest request,
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services,
+ const mojo::shell::mojom::Connector::ConnectCallback& callback) {
+ proxy_.Get()->ConnectToApplication(user_id, name, requestor_name,
+ std::move(request),
+ std::move(exposed_services), callback);
}
void MojoShellContext::ConnectToApplicationOnOwnThread(
- const GURL& url,
- const GURL& requestor_url,
- mojo::InterfaceRequest<mojo::ServiceProvider> request,
- mojo::ServiceProviderPtr exposed_services,
- const mojo::shell::CapabilityFilter& filter,
- const mojo::Shell::ConnectToApplicationCallback& callback) {
- scoped_ptr<mojo::shell::ConnectToApplicationParams> params(
- new mojo::shell::ConnectToApplicationParams);
- params->set_source(
- mojo::shell::Identity(requestor_url, std::string(),
- mojo::shell::GetPermissiveCapabilityFilter()));
- params->SetTarget(mojo::shell::Identity(url, std::string(), filter));
- params->set_services(std::move(request));
- params->set_exposed_services(std::move(exposed_services));
- params->set_on_application_end(base::Bind(&base::DoNothing));
+ const std::string& user_id,
+ const std::string& name,
+ const std::string& requestor_name,
+ mojo::shell::mojom::InterfaceProviderRequest request,
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services,
+ const mojo::shell::mojom::Connector::ConnectCallback& callback) {
+ scoped_ptr<mojo::shell::ConnectParams> params(new mojo::shell::ConnectParams);
+ mojo::Identity source_id(requestor_name, user_id);
+ params->set_source(source_id);
+ params->set_target(mojo::Identity(name, user_id));
+ params->set_remote_interfaces(std::move(request));
+ params->set_local_interfaces(std::move(exposed_services));
params->set_connect_callback(callback);
- application_manager_->ConnectToApplication(std::move(params));
+ shell_->Connect(std::move(params));
}
} // namespace content
diff --git a/chromium/content/browser/mojo/mojo_shell_context.h b/chromium/content/browser/mojo/mojo_shell_context.h
index e45ab88433f..959fd933af7 100644
--- a/chromium/content/browser/mojo/mojo_shell_context.h
+++ b/chromium/content/browser/mojo/mojo_shell_context.h
@@ -12,14 +12,17 @@
#include "base/lazy_instance.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#include "base/single_thread_task_runner.h"
#include "content/common/content_export.h"
-#include "mojo/shell/application_manager.h"
-#include "mojo/shell/public/interfaces/shell.mojom.h"
+#include "mojo/shell/public/interfaces/connector.mojom.h"
+#include "mojo/shell/shell.h"
-class GURL;
+namespace catalog {
+class Factory;
+}
namespace mojo {
-class ApplicationDelegate;
+class ShellClient;
}
namespace content {
@@ -29,40 +32,44 @@ namespace content {
class CONTENT_EXPORT MojoShellContext {
public:
using StaticApplicationMap =
- std::map<GURL, base::Callback<scoped_ptr<mojo::ApplicationDelegate>()>>;
+ std::map<std::string, base::Callback<scoped_ptr<mojo::ShellClient>()>>;
- MojoShellContext();
+ MojoShellContext(scoped_refptr<base::SingleThreadTaskRunner> file_thread,
+ scoped_refptr<base::SingleThreadTaskRunner> db_thread);
~MojoShellContext();
- // Connects an application at |url| and gets a handle to its exposed services.
- // This is only intended for use in browser code that's not part of some Mojo
- // application. May be called from any thread. |requestor_url| is given to
- // the target application as the requestor's URL upon connection.
+ // Connects an application at |name| and gets a handle to its exposed
+ // services. This is only intended for use in browser code that's not part of
+ // some Mojo application. May be called from any thread. |requestor_name| is
+ // given to the target application as the requestor's name upon connection.
static void ConnectToApplication(
- const GURL& url,
- const GURL& requestor_url,
- mojo::InterfaceRequest<mojo::ServiceProvider> request,
- mojo::ServiceProviderPtr exposed_services,
- const mojo::shell::CapabilityFilter& filter,
- const mojo::Shell::ConnectToApplicationCallback& callback);
+ const std::string& user_id,
+ const std::string& name,
+ const std::string& requestor_name,
+ mojo::shell::mojom::InterfaceProviderRequest request,
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services,
+ const mojo::shell::mojom::Connector::ConnectCallback& callback);
static void SetApplicationsForTest(const StaticApplicationMap* apps);
private:
+ class BuiltinManifestProvider;
class Proxy;
friend class Proxy;
void ConnectToApplicationOnOwnThread(
- const GURL& url,
- const GURL& requestor_url,
- mojo::InterfaceRequest<mojo::ServiceProvider> request,
- mojo::ServiceProviderPtr exposed_services,
- const mojo::shell::CapabilityFilter& filter,
- const mojo::Shell::ConnectToApplicationCallback& callback);
+ const std::string& user_id,
+ const std::string& name,
+ const std::string& requestor_name,
+ mojo::shell::mojom::InterfaceProviderRequest request,
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services,
+ const mojo::shell::mojom::Connector::ConnectCallback& callback);
static base::LazyInstance<scoped_ptr<Proxy>> proxy_;
- scoped_ptr<mojo::shell::ApplicationManager> application_manager_;
+ scoped_ptr<BuiltinManifestProvider> manifest_provider_;
+ scoped_ptr<catalog::Factory> catalog_;
+ scoped_ptr<mojo::shell::Shell> shell_;
DISALLOW_COPY_AND_ASSIGN(MojoShellContext);
};
diff --git a/chromium/content/browser/mojo/renderer_capability_filter.cc b/chromium/content/browser/mojo/renderer_capability_filter.cc
deleted file mode 100644
index 01a8e626dd7..00000000000
--- a/chromium/content/browser/mojo/renderer_capability_filter.cc
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <utility>
-
-#include "components/mus/public/interfaces/gpu.mojom.h"
-#include "content/browser/mojo/mojo_shell_client_host.h"
-
-namespace content {
-
-mojo::CapabilityFilterPtr CreateCapabilityFilterForRenderer() {
- // See https://goo.gl/gkBtCR for a description of what this is and what to
- // think about when changing it.
- mojo::CapabilityFilterPtr filter(mojo::CapabilityFilter::New());
- mojo::Array<mojo::String> window_manager_interfaces;
- window_manager_interfaces.push_back(mus::mojom::Gpu::Name_);
- filter->filter.insert("mojo:mus", std::move(window_manager_interfaces));
- return filter;
-}
-
-} // namespace content
diff --git a/chromium/content/browser/mojo/service_registrar_android.cc b/chromium/content/browser/mojo/service_registrar_android.cc
index e29d7f328c3..cd0cfacf818 100644
--- a/chromium/content/browser/mojo/service_registrar_android.cc
+++ b/chromium/content/browser/mojo/service_registrar_android.cc
@@ -6,7 +6,7 @@
#include "base/android/context_utils.h"
#include "base/android/jni_android.h"
-#include "content/browser/mojo/service_registry_android.h"
+#include "content/public/browser/android/service_registry_android.h"
#include "jni/ServiceRegistrar_jni.h"
namespace content {
diff --git a/chromium/content/browser/mojo/service_registry_android.h b/chromium/content/browser/mojo/service_registry_android.h
deleted file mode 100644
index 17d2cb07bdc..00000000000
--- a/chromium/content/browser/mojo/service_registry_android.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_MOJO_SERVICE_REGISTRY_ANDROID_H_
-#define CONTENT_BROWSER_MOJO_SERVICE_REGISTRY_ANDROID_H_
-
-#include <jni.h>
-
-#include "base/android/scoped_java_ref.h"
-#include "base/macros.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-class ServiceRegistryImpl;
-
-// Android wrapper over ServiceRegistryImpl, allowing the browser services in
-// Java to register with ServiceRegistry.java (and abstracting away the JNI
-// calls).
-class CONTENT_EXPORT ServiceRegistryAndroid {
- public:
- static bool Register(JNIEnv* env);
-
- explicit ServiceRegistryAndroid(ServiceRegistryImpl* service_registry);
- virtual ~ServiceRegistryAndroid();
-
- // Methods called from Java.
- void AddService(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& j_service_registry,
- const base::android::JavaParamRef<jobject>& j_manager,
- const base::android::JavaParamRef<jobject>& j_factory,
- const base::android::JavaParamRef<jstring>& j_name);
- void RemoveService(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& j_service_registry,
- const base::android::JavaParamRef<jstring>& j_name);
- void ConnectToRemoteService(
- JNIEnv* env,
- const base::android::JavaParamRef<jobject>& j_service_registry,
- const base::android::JavaParamRef<jstring>& j_name,
- jint handle);
-
- const base::android::ScopedJavaGlobalRef<jobject>& GetObj() { return obj_; }
-
- private:
- ServiceRegistryImpl* service_registry_;
- base::android::ScopedJavaGlobalRef<jobject> obj_;
-
- DISALLOW_COPY_AND_ASSIGN(ServiceRegistryAndroid);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_MOJO_SERVICE_REGISTRY_ANDROID_H_
diff --git a/chromium/content/browser/mojo_shell_browsertest.cc b/chromium/content/browser/mojo_shell_browsertest.cc
index b291961a077..9777e624052 100644
--- a/chromium/content/browser/mojo_shell_browsertest.cc
+++ b/chromium/content/browser/mojo_shell_browsertest.cc
@@ -7,26 +7,35 @@
#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "content/browser/mojo/mojo_shell_context.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/mojo_app_connection.h"
+#include "content/public/browser/web_contents.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/test_mojo_app.h"
#include "content/public/test/test_mojo_service.mojom.h"
+#include "content/shell/browser/shell.h"
#include "url/gurl.h"
namespace content {
-const char kInProcessTestMojoAppUrl[] = "system:content_in_process_test_app";
+const char kInProcessTestMojoAppName[] = "system:content_in_process_test_app";
class MojoShellTest : public ContentBrowserTest {
public:
MojoShellTest() {
- test_apps_[GURL(kInProcessTestMojoAppUrl)] = base::Bind(&CreateTestApp);
+ test_apps_[kInProcessTestMojoAppName] = base::Bind(&CreateTestApp);
MojoShellContext::SetApplicationsForTest(&test_apps_);
}
+ protected:
+ std::string GetUserId() {
+ return BrowserContext::GetMojoUserIdFor(
+ shell()->web_contents()->GetBrowserContext());
+ }
+
private:
- static scoped_ptr<mojo::ApplicationDelegate> CreateTestApp() {
- return scoped_ptr<mojo::ApplicationDelegate>(new TestMojoApp);
+ static scoped_ptr<mojo::ShellClient> CreateTestApp() {
+ return scoped_ptr<mojo::ShellClient>(new TestMojoApp);
}
MojoShellContext::StaticApplicationMap test_apps_;
@@ -35,10 +44,10 @@ class MojoShellTest : public ContentBrowserTest {
};
IN_PROC_BROWSER_TEST_F(MojoShellTest, TestBrowserConnection) {
- auto test_app = MojoAppConnection::Create(GURL(kInProcessTestMojoAppUrl),
- GURL(kBrowserMojoAppUrl));
- TestMojoServicePtr test_service;
- test_app->ConnectToService(&test_service);
+ auto test_app = MojoAppConnection::Create(
+ GetUserId(), kInProcessTestMojoAppName, kBrowserMojoAppUrl);
+ mojom::TestMojoServicePtr test_service;
+ test_app->GetInterface(&test_service);
base::RunLoop run_loop;
test_service->DoSomething(run_loop.QuitClosure());
@@ -49,10 +58,10 @@ IN_PROC_BROWSER_TEST_F(MojoShellTest, TestUtilityConnection) {
// With no loader registered at this URL, the shell should spawn a utility
// process and connect us to it. content_shell's utility process always hosts
// a TestMojoApp at |kTestMojoAppUrl|.
- auto test_app = MojoAppConnection::Create(GURL(kTestMojoAppUrl),
- GURL(kBrowserMojoAppUrl));
- TestMojoServicePtr test_service;
- test_app->ConnectToService(&test_service);
+ auto test_app = MojoAppConnection::Create(GetUserId(), kTestMojoAppUrl,
+ kBrowserMojoAppUrl);
+ mojom::TestMojoServicePtr test_service;
+ test_app->GetInterface(&test_service);
base::RunLoop run_loop;
test_service->DoSomething(run_loop.QuitClosure());
diff --git a/chromium/content/browser/navigator_connect/OWNERS b/chromium/content/browser/navigator_connect/OWNERS
deleted file mode 100644
index 1b10b3436d9..00000000000
--- a/chromium/content/browser/navigator_connect/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-mek@chromium.org
diff --git a/chromium/content/browser/navigator_connect/navigator_connect_context_impl.cc b/chromium/content/browser/navigator_connect/navigator_connect_context_impl.cc
deleted file mode 100644
index c393c4bf45a..00000000000
--- a/chromium/content/browser/navigator_connect/navigator_connect_context_impl.cc
+++ /dev/null
@@ -1,266 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/navigator_connect/navigator_connect_context_impl.h"
-
-#include <stdint.h>
-
-#include "base/stl_util.h"
-#include "content/browser/message_port_service.h"
-#include "content/browser/navigator_connect/service_port_service_impl.h"
-#include "content/browser/service_worker/service_worker_context_wrapper.h"
-#include "content/common/service_worker/service_worker_utils.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/navigator_connect_service_factory.h"
-#include "content/public/common/navigator_connect_client.h"
-#include "mojo/common/url_type_converters.h"
-
-namespace content {
-
-struct NavigatorConnectContextImpl::Port {
- // ID of this port.
- int id;
- // ID of the port this port is connected to.
- int entangled_id;
-
- // Service url and client origin describing this connection. These fields will
- // always be the same as the same fields for the entangled port.
- GURL target_url;
- GURL client_origin;
-
- // Set to nullptr when the ServicePortService goes away.
- ServicePortServiceImpl* service = nullptr;
-
- // If this port is associated with a service worker, these fields store that
- // information.
- int64_t service_worker_registration_id = kInvalidServiceWorkerRegistrationId;
- GURL service_worker_registration_origin;
-};
-
-NavigatorConnectContextImpl::NavigatorConnectContextImpl(
- const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context)
- : service_worker_context_(service_worker_context), next_port_id_(0) {}
-
-NavigatorConnectContextImpl::~NavigatorConnectContextImpl() {
-}
-
-void NavigatorConnectContextImpl::AddFactory(
- scoped_ptr<NavigatorConnectServiceFactory> factory) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&NavigatorConnectContextImpl::AddFactoryOnIOThread, this,
- base::Passed(&factory)));
-}
-
-void NavigatorConnectContextImpl::AddFactoryOnIOThread(
- scoped_ptr<NavigatorConnectServiceFactory> factory) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- service_factories_.push_back(factory.release());
-}
-
-void NavigatorConnectContextImpl::Connect(
- const GURL& target_url,
- const GURL& origin,
- ServicePortServiceImpl* service_port_service,
- const ConnectCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // Create a new message channel.
- int client_port_id = next_port_id_++;
- int service_port_id = next_port_id_++;
-
- Port& client_port = ports_[client_port_id];
- client_port.id = client_port_id;
- client_port.entangled_id = service_port_id;
- client_port.target_url = target_url;
- client_port.client_origin = origin;
- client_port.service = service_port_service;
-
- Port& service_port = ports_[service_port_id];
- service_port.id = service_port_id;
- service_port.entangled_id = client_port_id;
- service_port.target_url = target_url;
- service_port.client_origin = origin;
-
- // Find the right service worker to service this connection.
- service_worker_context_->FindReadyRegistrationForDocument(
- target_url,
- base::Bind(&NavigatorConnectContextImpl::GotServiceWorkerRegistration,
- this, callback, client_port_id, service_port_id));
-}
-
-void NavigatorConnectContextImpl::PostMessage(
- int sender_port_id,
- const MessagePortMessage& message,
- const std::vector<TransferredMessagePort>& sent_message_ports) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(ports_.find(sender_port_id) != ports_.end());
- DCHECK(message.message_as_value.empty());
-
- const Port& sender_port = ports_[sender_port_id];
- DCHECK(ports_.find(sender_port.entangled_id) != ports_.end());
- const Port& port = ports_[sender_port.entangled_id];
-
- if (port.service_worker_registration_id !=
- kInvalidServiceWorkerRegistrationId) {
- // Port is associated with service worker, dispatch message event via
- // ServiceWorkerVersion.
-
- // Hold messages on transferred message ports. Actual delivery of the
- // message by the service can be asynchronous. When a message is delivered,
- // WebMessagePortChannelImpl instances will be constructed which send
- // MessagePortHostMsg_ReleaseMessages to release messages.
- for (const auto& sent_port : sent_message_ports)
- MessagePortService::GetInstance()->HoldMessages(sent_port.id);
-
- service_worker_context_->FindReadyRegistrationForId(
- port.service_worker_registration_id,
- port.service_worker_registration_origin,
- base::Bind(&NavigatorConnectContextImpl::DeliverMessage, this, port.id,
- message.message_as_string, sent_message_ports));
- return;
- }
-
- if (!port.service) {
- // TODO(mek): Figure out what to do in this situation.
- return;
- }
- port.service->PostMessageToClient(port.id, message, sent_message_ports);
-}
-
-void NavigatorConnectContextImpl::GotServiceWorkerRegistration(
- const ConnectCallback& callback,
- int client_port_id,
- int service_port_id,
- ServiceWorkerStatusCode status,
- const scoped_refptr<ServiceWorkerRegistration>& registration) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(ports_.find(client_port_id) != ports_.end());
- DCHECK(ports_.find(service_port_id) != ports_.end());
-
- if (status != SERVICE_WORKER_OK) {
- // No service worker found, reject connection attempt.
- OnConnectError(callback, client_port_id, service_port_id, status);
- return;
- }
-
- ServiceWorkerVersion* active_version = registration->active_version();
- DCHECK(active_version);
-
- Port& service_port = ports_[service_port_id];
- service_port.service_worker_registration_id = registration->id();
- service_port.service_worker_registration_origin =
- registration->pattern().GetOrigin();
-
- active_version->RunAfterStartWorker(
- base::Bind(&NavigatorConnectContextImpl::OnConnectError, this, callback,
- client_port_id, service_port_id),
- base::Bind(&NavigatorConnectContextImpl::DispatchConnectEvent, this,
- callback, client_port_id, service_port_id, registration,
- make_scoped_refptr(active_version)));
-}
-
-void NavigatorConnectContextImpl::DispatchConnectEvent(
- const ConnectCallback& callback,
- int client_port_id,
- int service_port_id,
- const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration,
- const scoped_refptr<ServiceWorkerVersion>& worker) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(ContainsKey(ports_, client_port_id));
- DCHECK(ContainsKey(ports_, service_port_id));
-
- const Port& service_port = ports_[service_port_id];
- int request_id = worker->StartRequest(
- ServiceWorkerMetrics::EventType::SERVICE_PORT_CONNECT,
- base::Bind(&NavigatorConnectContextImpl::OnConnectError, this, callback,
- client_port_id, service_port_id));
- base::WeakPtr<ServicePortDispatcher> dispatcher =
- worker->GetMojoServiceForRequest<ServicePortDispatcher>(request_id);
- dispatcher->Connect(
- mojo::String::From(service_port.target_url),
- mojo::String::From(service_port.client_origin), service_port_id,
- base::Bind(&NavigatorConnectContextImpl::OnConnectResult, this, callback,
- client_port_id, service_port_id, service_worker_registration,
- worker, request_id));
-}
-
-void NavigatorConnectContextImpl::ServicePortServiceDestroyed(
- ServicePortServiceImpl* service_port_service) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- for (auto& port : ports_) {
- if (port.second.service != service_port_service)
- continue;
- port.second.service = nullptr;
- // TODO(mek): Should actually inform other side of connections that the
- // connection was closed, or in the case of service workers somehow keep
- // track of the connection.
- }
-}
-
-void NavigatorConnectContextImpl::OnConnectError(
- const ConnectCallback& callback,
- int client_port_id,
- int service_port_id,
- ServiceWorkerStatusCode status) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // Destroy ports since connection failed.
- ports_.erase(service_port_id);
- ports_.erase(client_port_id);
- callback.Run(MSG_ROUTING_NONE, false);
-}
-
-void NavigatorConnectContextImpl::OnConnectResult(
- const ConnectCallback& callback,
- int client_port_id,
- int service_port_id,
- const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration,
- const scoped_refptr<ServiceWorkerVersion>& worker,
- int request_id,
- ServicePortConnectResult result,
- const mojo::String& name,
- const mojo::String& data) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (!worker->FinishRequest(request_id))
- return;
-
- if (result != SERVICE_PORT_CONNECT_RESULT_ACCEPT) {
- OnConnectError(callback, client_port_id, service_port_id,
- SERVICE_WORKER_ERROR_FAILED);
- return;
- }
-
- // TODO(mek): Might have to do something else if the client connection got
- // severed while the service side connection was being set up.
- callback.Run(client_port_id, true);
-}
-
-void NavigatorConnectContextImpl::DeliverMessage(
- int port_id,
- const base::string16& message,
- const std::vector<TransferredMessagePort>& sent_message_ports,
- ServiceWorkerStatusCode service_worker_status,
- const scoped_refptr<ServiceWorkerRegistration>&
- service_worker_registration) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(ports_.find(port_id) != ports_.end());
-
- if (service_worker_status != SERVICE_WORKER_OK) {
- // TODO(mek): Do something when no service worker was found.
- return;
- }
-
- ServiceWorkerVersion* active_version =
- service_worker_registration->active_version();
- DCHECK(active_version);
-
- const Port& port = ports_[port_id];
- NavigatorConnectClient client(port.target_url, port.client_origin, port_id);
- active_version->DispatchCrossOriginMessageEvent(
- client, message, sent_message_ports,
- base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/navigator_connect/navigator_connect_context_impl.h b/chromium/content/browser/navigator_connect/navigator_connect_context_impl.h
deleted file mode 100644
index 5337a338203..00000000000
--- a/chromium/content/browser/navigator_connect/navigator_connect_context_impl.h
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_NAVIGATOR_CONNECT_NAVIGATOR_CONNECT_CONTEXT_IMPL_H_
-#define CONTENT_BROWSER_NAVIGATOR_CONNECT_NAVIGATOR_CONNECT_CONTEXT_IMPL_H_
-
-#include <map>
-#include "base/callback_forward.h"
-#include "base/memory/scoped_vector.h"
-#include "base/strings/string16.h"
-#include "content/common/service_port_service.mojom.h"
-#include "content/common/service_worker/service_worker_status_code.h"
-#include "content/public/browser/navigator_connect_context.h"
-
-class GURL;
-
-namespace content {
-
-struct MessagePortMessage;
-class NavigatorConnectService;
-class NavigatorConnectServiceFactory;
-struct NavigatorConnectClient;
-class ServicePortServiceImpl;
-class ServiceWorkerContextWrapper;
-class ServiceWorkerRegistration;
-class ServiceWorkerVersion;
-struct TransferredMessagePort;
-
-// Tracks all active navigator.services connections, as well as available
-// service factories. Delegates connection requests to the correct factory and
-// passes messages on to the correct service.
-// One instance of this class exists per StoragePartition.
-// TODO(mek): Clean up connections, fire of closed events when connections die.
-// TODO(mek): Update service side API to be fully ServicePort based.
-// TODO(mek): Make ServicePorts that live in a service worker be able to survive
-// the worker being restarted.
-// TODO(mek): Add back ability for service ports to be backed by native code.
-class NavigatorConnectContextImpl : public NavigatorConnectContext {
- public:
- using ConnectCallback =
- base::Callback<void(int message_port_id, bool success)>;
-
- explicit NavigatorConnectContextImpl(
- const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context);
-
- // Called when a new connection request comes in from a client. Finds the
- // correct service factory and passes the connection request off to there.
- // Can call the callback before this method call returns.
- void Connect(const GURL& target_url,
- const GURL& origin,
- ServicePortServiceImpl* service_port_service,
- const ConnectCallback& callback);
-
- // Called when a message is sent to a ServicePort. The |sender_port_id| is the
- // id of the port the message is sent from, this will look up what other port
- // the port is entangled with and deliver the message to that port.
- void PostMessage(
- int sender_port_id,
- const MessagePortMessage& message,
- const std::vector<TransferredMessagePort>& sent_message_ports);
-
- // Called by a ServicePortServiceImpl instance when it is about to be
- // destroyed to inform this class that all its connections are no longer
- // valid.
- void ServicePortServiceDestroyed(
- ServicePortServiceImpl* service_port_service);
-
- // NavigatorConnectContext implementation.
- void AddFactory(scoped_ptr<NavigatorConnectServiceFactory> factory) override;
-
- private:
- ~NavigatorConnectContextImpl() override;
-
- void AddFactoryOnIOThread(scoped_ptr<NavigatorConnectServiceFactory> factory);
-
- // Callback called when a ServiceWorkerRegistration has been located (or
- // has failed to be located) for a connection attempt.
- void GotServiceWorkerRegistration(
- const ConnectCallback& callback,
- int client_port_id,
- int service_port_id,
- ServiceWorkerStatusCode status,
- const scoped_refptr<ServiceWorkerRegistration>& registration);
-
- void DispatchConnectEvent(const ConnectCallback& callback,
- int client_port_id,
- int service_port_id,
- const scoped_refptr<ServiceWorkerRegistration>&
- service_worker_registration,
- const scoped_refptr<ServiceWorkerVersion>& worker);
-
- // Callback called when dispatching a connect event failed.
- void OnConnectError(const ConnectCallback& calback,
- int client_port_id,
- int service_port_id,
- ServiceWorkerStatusCode status);
-
- // Callback called with the response to a connect event.
- void OnConnectResult(const ConnectCallback& callback,
- int client_port_id,
- int service_port_id,
- const scoped_refptr<ServiceWorkerRegistration>&
- service_worker_registration,
- const scoped_refptr<ServiceWorkerVersion>& worker,
- int request_id,
- ServicePortConnectResult result,
- const mojo::String& name,
- const mojo::String& data);
-
- // Callback called when a ServiceWorkerRegistration has been located to
- // deliver a message to.
- void DeliverMessage(
- int port_id,
- const base::string16& message,
- const std::vector<TransferredMessagePort>& sent_message_ports,
- ServiceWorkerStatusCode status,
- const scoped_refptr<ServiceWorkerRegistration>& registration);
-
- scoped_refptr<ServiceWorkerContextWrapper> service_worker_context_;
-
- // List of factories to try to handle URLs.
- ScopedVector<NavigatorConnectServiceFactory> service_factories_;
-
- // List of currently active ServicePorts.
- struct Port;
- std::map<int, Port> ports_;
- int next_port_id_;
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_NAVIGATOR_CONNECT_NAVIGATOR_CONNECT_CONTEXT_IMPL_H_
diff --git a/chromium/content/browser/navigator_connect/service_port_service_impl.cc b/chromium/content/browser/navigator_connect/service_port_service_impl.cc
deleted file mode 100644
index 310c304ab3e..00000000000
--- a/chromium/content/browser/navigator_connect/service_port_service_impl.cc
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/navigator_connect/service_port_service_impl.h"
-
-#include <utility>
-
-#include "content/browser/message_port_message_filter.h"
-#include "content/browser/message_port_service.h"
-#include "content/browser/navigator_connect/navigator_connect_context_impl.h"
-#include "content/common/service_port_type_converters.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/common/message_port_types.h"
-#include "mojo/common/common_type_converters.h"
-#include "url/gurl.h"
-
-namespace content {
-
-// static
-void ServicePortServiceImpl::Create(
- const scoped_refptr<NavigatorConnectContextImpl>& navigator_connect_context,
- const scoped_refptr<MessagePortMessageFilter>& message_port_message_filter,
- mojo::InterfaceRequest<ServicePortService> request) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&ServicePortServiceImpl::CreateOnIOThread,
- navigator_connect_context, message_port_message_filter,
- base::Passed(&request)));
-}
-
-ServicePortServiceImpl::~ServicePortServiceImpl() {
- // Should always be destroyed on the IO thread, but can't check that with
- // DCHECK_CURRENTLY_ON because this class could be destroyed during thread
- // shutdown, at which point that check doesn't work.
- navigator_connect_context_->ServicePortServiceDestroyed(this);
-}
-
-void ServicePortServiceImpl::PostMessageToClient(
- int port_id,
- const MessagePortMessage& message,
- const std::vector<TransferredMessagePort>& sent_message_ports) {
- DCHECK(client_.get());
- // Hold messages on transferred message ports. Normally this wouldn't be
- // needed, but since MessagePort uses regular IPC while this class uses mojo,
- // without holding messages mojo IPC might overtake regular IPC resulting in a
- // non-functional port. When WebMessagePortChannelImpl instances are
- // constructed in the renderer, they will send
- // MessagePortHostMsg_ReleaseMessages to release messages.
- for (const auto& port : sent_message_ports)
- MessagePortService::GetInstance()->HoldMessages(port.id);
-
- std::vector<int> new_routing_ids;
- message_port_message_filter_->UpdateMessagePortsWithNewRoutes(
- sent_message_ports, &new_routing_ids);
- client_->PostMessageToPort(
- port_id, mojo::String::From(message.message_as_string),
- mojo::Array<MojoTransferredMessagePortPtr>::From(sent_message_ports),
- mojo::Array<int32_t>::From(new_routing_ids));
-}
-
-// static
-void ServicePortServiceImpl::CreateOnIOThread(
- const scoped_refptr<NavigatorConnectContextImpl>& navigator_connect_context,
- const scoped_refptr<MessagePortMessageFilter>& message_port_message_filter,
- mojo::InterfaceRequest<ServicePortService> request) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- new ServicePortServiceImpl(navigator_connect_context,
- message_port_message_filter, std::move(request));
-}
-
-ServicePortServiceImpl::ServicePortServiceImpl(
- const scoped_refptr<NavigatorConnectContextImpl>& navigator_connect_context,
- const scoped_refptr<MessagePortMessageFilter>& message_port_message_filter,
- mojo::InterfaceRequest<ServicePortService> request)
- : binding_(this, std::move(request)),
- navigator_connect_context_(navigator_connect_context),
- message_port_message_filter_(message_port_message_filter),
- weak_ptr_factory_(this) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-}
-
-void ServicePortServiceImpl::SetClient(ServicePortServiceClientPtr client) {
- DCHECK(!client_.get());
- // TODO(mek): Set ErrorHandler to listen for errors.
- client_ = std::move(client);
-}
-
-void ServicePortServiceImpl::Connect(const mojo::String& target_url,
- const mojo::String& origin,
- const ConnectCallback& callback) {
- navigator_connect_context_->Connect(
- GURL(target_url), GURL(origin), this,
- base::Bind(&ServicePortServiceImpl::OnConnectResult,
- weak_ptr_factory_.GetWeakPtr(), callback));
-}
-
-void ServicePortServiceImpl::PostMessageToPort(
- int32_t port_id,
- const mojo::String& message,
- mojo::Array<MojoTransferredMessagePortPtr> ports) {
- // TODO(mek): Similar to http://crbug.com/490222 this code should make sure
- // port_id belongs to the process this IPC was received from.
- std::vector<TransferredMessagePort> transferred_ports =
- ports.To<std::vector<TransferredMessagePort>>();
-
- MessagePortService* mps = MessagePortService::GetInstance();
- // First, call QueueMessages for all transferred ports, since the ports
- // haven't sent their own IPC for that.
- for (const TransferredMessagePort& port : transferred_ports) {
- mps->QueueMessages(port.id);
- }
-
- navigator_connect_context_->PostMessage(
- port_id, MessagePortMessage(message.To<base::string16>()),
- transferred_ports);
-}
-
-void ServicePortServiceImpl::ClosePort(int32_t port_id) {
- MessagePortService::GetInstance()->Destroy(port_id);
-}
-
-void ServicePortServiceImpl::OnConnectResult(const ConnectCallback& callback,
- int message_port_id,
- bool success) {
- callback.Run(success ? SERVICE_PORT_CONNECT_RESULT_ACCEPT
- : SERVICE_PORT_CONNECT_RESULT_REJECT,
- message_port_id);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/navigator_connect/service_port_service_impl.h b/chromium/content/browser/navigator_connect/service_port_service_impl.h
deleted file mode 100644
index be1815ed3ed..00000000000
--- a/chromium/content/browser/navigator_connect/service_port_service_impl.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_NAVIGATOR_CONNECT_SERVICE_PORT_SERVICE_IMPL_H_
-#define CONTENT_BROWSER_NAVIGATOR_CONNECT_SERVICE_PORT_SERVICE_IMPL_H_
-
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "content/common/service_port_service.mojom.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-
-namespace content {
-struct MessagePortMessage;
-class MessagePortMessageFilter;
-class NavigatorConnectContextImpl;
-struct TransferredMessagePort;
-
-// Browser side class representing a ServicePortCollection in the renderer. One
-// instance of this class is created for each ServicePortCollection, and is
-// automatically destroyed when the ServicePortCollection in the renderer goes
-// away.
-class ServicePortServiceImpl : public ServicePortService {
- public:
- // Factory method called by mojo to create a new instance of this class to
- // handle requests from a new ServicePortCollection.
- static void Create(const scoped_refptr<NavigatorConnectContextImpl>&
- navigator_connect_context,
- const scoped_refptr<MessagePortMessageFilter>&
- message_port_message_filter,
- mojo::InterfaceRequest<ServicePortService> request);
- ~ServicePortServiceImpl() override;
-
- // Called by NavigatorConnectContextImpl to post a message to a port that is
- // owned by this ServicePortCollection.
- void PostMessageToClient(
- int port_id,
- const MessagePortMessage& message,
- const std::vector<TransferredMessagePort>& sent_message_ports);
-
- private:
- static void CreateOnIOThread(
- const scoped_refptr<NavigatorConnectContextImpl>&
- navigator_connect_context,
- const scoped_refptr<MessagePortMessageFilter>&
- message_port_message_filter,
- mojo::InterfaceRequest<ServicePortService> request);
- ServicePortServiceImpl(const scoped_refptr<NavigatorConnectContextImpl>&
- navigator_connect_context,
- const scoped_refptr<MessagePortMessageFilter>&
- message_port_message_filter,
- mojo::InterfaceRequest<ServicePortService> request);
-
- // ServicePortService methods:
- void SetClient(ServicePortServiceClientPtr client) override;
- void Connect(const mojo::String& target_url,
- const mojo::String& origin,
- const ConnectCallback& callback) override;
- void PostMessageToPort(
- int32_t port_id,
- const mojo::String& message,
- mojo::Array<MojoTransferredMessagePortPtr> ports) override;
- void ClosePort(int32_t port_id) override;
-
- // Callback called when a connection to a service has been establised or
- // rejected.
- void OnConnectResult(const ConnectCallback& callback,
- int message_port_id,
- bool success);
-
- mojo::StrongBinding<ServicePortService> binding_;
- scoped_refptr<NavigatorConnectContextImpl> navigator_connect_context_;
- scoped_refptr<MessagePortMessageFilter> message_port_message_filter_;
- ServicePortServiceClientPtr client_;
- base::WeakPtrFactory<ServicePortServiceImpl> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(ServicePortServiceImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_NAVIGATOR_CONNECT_SERVICE_PORT_SERVICE_IMPL_H_
diff --git a/chromium/content/browser/net/quota_policy_cookie_store.cc b/chromium/content/browser/net/quota_policy_cookie_store.cc
index 9404981fb60..6767eb8d4b5 100644
--- a/chromium/content/browser/net/quota_policy_cookie_store.cc
+++ b/chromium/content/browser/net/quota_policy_cookie_store.cc
@@ -129,17 +129,18 @@ CookieStoreConfig::CookieStoreConfig(
CookieStoreConfig::~CookieStoreConfig() {
}
-net::CookieStore* CreateCookieStore(const CookieStoreConfig& config) {
+scoped_ptr<net::CookieStore> CreateCookieStore(
+ const CookieStoreConfig& config) {
// TODO(bcwhite): Remove ScopedTracker below once crbug.com/483686 is fixed.
tracked_objects::ScopedTracker tracking_profile(
FROM_HERE_WITH_EXPLICIT_FUNCTION("483686 content::CreateCookieStore"));
- net::CookieMonster* cookie_monster = nullptr;
+ scoped_ptr<net::CookieMonster> cookie_monster;
if (config.path.empty()) {
// Empty path means in-memory store.
- cookie_monster = new net::CookieMonster(nullptr,
- config.cookie_delegate.get());
+ cookie_monster.reset(
+ new net::CookieMonster(nullptr, config.cookie_delegate.get()));
} else {
scoped_refptr<base::SequencedTaskRunner> client_task_runner =
config.client_task_runner;
@@ -171,8 +172,8 @@ net::CookieStore* CreateCookieStore(const CookieStoreConfig& config) {
sqlite_store.get(),
config.storage_policy.get());
- cookie_monster =
- new net::CookieMonster(persistent_store, config.cookie_delegate.get());
+ cookie_monster.reset(
+ new net::CookieMonster(persistent_store, config.cookie_delegate.get()));
if ((config.session_cookie_mode ==
CookieStoreConfig::PERSISTANT_SESSION_COOKIES) ||
(config.session_cookie_mode ==
@@ -181,7 +182,10 @@ net::CookieStore* CreateCookieStore(const CookieStoreConfig& config) {
}
}
- return cookie_monster;
+ if (!config.cookieable_schemes.empty())
+ cookie_monster->SetCookieableSchemes(config.cookieable_schemes);
+
+ return std::move(cookie_monster);
}
} // namespace content
diff --git a/chromium/content/browser/net/quota_policy_cookie_store_unittest.cc b/chromium/content/browser/net/quota_policy_cookie_store_unittest.cc
index ca33d6ecbd3..01db50f9b3d 100644
--- a/chromium/content/browser/net/quota_policy_cookie_store_unittest.cc
+++ b/chromium/content/browser/net/quota_policy_cookie_store_unittest.cc
@@ -96,10 +96,10 @@ class QuotaPolicyCookieStoreTest : public testing::Test {
const std::string& domain,
const std::string& path,
const base::Time& creation) {
- store_->AddCookie(
- net::CanonicalCookie(
- GURL(), name, value, domain, path, creation, creation, creation,
- false, false, false, net::COOKIE_PRIORITY_DEFAULT));
+ store_->AddCookie(net::CanonicalCookie(
+ GURL(), name, value, domain, path, creation, creation, creation, false,
+ false, net::CookieSameSite::DEFAULT_MODE,
+ net::COOKIE_PRIORITY_DEFAULT));
}
void DestroyStore() {
diff --git a/chromium/content/browser/notifications/notification_database.h b/chromium/content/browser/notifications/notification_database.h
index 4f230a11c86..e5914e1abf1 100644
--- a/chromium/content/browser/notifications/notification_database.h
+++ b/chromium/content/browser/notifications/notification_database.h
@@ -6,11 +6,13 @@
#define CONTENT_BROWSER_NOTIFICATIONS_NOTIFICATION_DATABASE_H_
#include <stdint.h>
+
#include <set>
#include <vector>
#include "base/files/file_path.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/sequence_checker.h"
#include "content/common/content_export.h"
diff --git a/chromium/content/browser/notifications/notification_database_data.proto b/chromium/content/browser/notifications/notification_database_data.proto
index 3047d2b4356..aad02a8cf2a 100644
--- a/chromium/content/browser/notifications/notification_database_data.proto
+++ b/chromium/content/browser/notifications/notification_database_data.proto
@@ -20,16 +20,25 @@ message NotificationDatabaseDataProto {
// A notification action, corresponds to content::PlatformNotificationAction.
//
- // Next tag: 3
+ // Next tag: 6
message NotificationAction {
+ // Corresponds to PlatformNotificationActionType.
+ enum Type {
+ BUTTON = 0;
+ TEXT = 1;
+ }
+
optional string action = 1;
optional string title = 2;
+ optional string icon = 3;
+ optional Type type = 4;
+ optional string placeholder = 5;
}
// Actual data payload of the notification. This message is the protocol
// buffer meant to serialize the content::PlatformNotificationData structure.
//
- // Next tag: 12
+ // Next tag: 15
message NotificationData {
enum Direction {
LEFT_TO_RIGHT = 0;
@@ -43,7 +52,10 @@ message NotificationDatabaseDataProto {
optional string body = 4;
optional string tag = 5;
optional string icon = 6;
+ optional string badge = 14;
repeated int32 vibration_pattern = 9 [packed=true];
+ optional int64 timestamp = 12;
+ optional bool renotify = 13;
optional bool silent = 7;
optional bool require_interaction = 11;
optional bytes data = 8;
diff --git a/chromium/content/browser/notifications/notification_database_data_conversions.cc b/chromium/content/browser/notifications/notification_database_data_conversions.cc
index cf19704f9dc..381f0d3ef9c 100644
--- a/chromium/content/browser/notifications/notification_database_data_conversions.cc
+++ b/chromium/content/browser/notifications/notification_database_data_conversions.cc
@@ -6,8 +6,11 @@
#include <stddef.h>
+#include <memory>
+
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
#include "content/browser/notifications/notification_database_data.pb.h"
#include "content/public/browser/notification_database_data.h"
@@ -50,12 +53,16 @@ bool DeserializeNotificationDatabaseData(const std::string& input,
notification_data->body = base::UTF8ToUTF16(payload.body());
notification_data->tag = payload.tag();
notification_data->icon = GURL(payload.icon());
+ notification_data->badge = GURL(payload.badge());
if (payload.vibration_pattern().size() > 0) {
notification_data->vibration_pattern.assign(
payload.vibration_pattern().begin(), payload.vibration_pattern().end());
}
+ notification_data->timestamp =
+ base::Time::FromInternalValue(payload.timestamp());
+ notification_data->renotify = payload.renotify();
notification_data->silent = payload.silent();
notification_data->require_interaction = payload.require_interaction();
@@ -66,8 +73,25 @@ bool DeserializeNotificationDatabaseData(const std::string& input,
for (const auto& payload_action : payload.actions()) {
PlatformNotificationAction action;
+
+ switch (payload_action.type()) {
+ case NotificationDatabaseDataProto::NotificationAction::BUTTON:
+ action.type = PLATFORM_NOTIFICATION_ACTION_TYPE_BUTTON;
+ break;
+ case NotificationDatabaseDataProto::NotificationAction::TEXT:
+ action.type = PLATFORM_NOTIFICATION_ACTION_TYPE_TEXT;
+ break;
+ default:
+ NOTREACHED();
+ }
+
action.action = payload_action.action();
action.title = base::UTF8ToUTF16(payload_action.title());
+ action.icon = GURL(payload_action.icon());
+ if (payload_action.has_placeholder()) {
+ action.placeholder = base::NullableString16(
+ base::UTF8ToUTF16(payload_action.placeholder()), false);
+ }
notification_data->actions.push_back(action);
}
@@ -78,7 +102,7 @@ bool SerializeNotificationDatabaseData(const NotificationDatabaseData& input,
std::string* output) {
DCHECK(output);
- scoped_ptr<NotificationDatabaseDataProto::NotificationData> payload(
+ std::unique_ptr<NotificationDatabaseDataProto::NotificationData> payload(
new NotificationDatabaseDataProto::NotificationData());
const PlatformNotificationData& notification_data = input.notification_data;
@@ -104,10 +128,13 @@ bool SerializeNotificationDatabaseData(const NotificationDatabaseData& input,
payload->set_body(base::UTF16ToUTF8(notification_data.body));
payload->set_tag(notification_data.tag);
payload->set_icon(notification_data.icon.spec());
+ payload->set_badge(notification_data.badge.spec());
for (size_t i = 0; i < notification_data.vibration_pattern.size(); ++i)
payload->add_vibration_pattern(notification_data.vibration_pattern[i]);
+ payload->set_timestamp(notification_data.timestamp.ToInternalValue());
+ payload->set_renotify(notification_data.renotify);
payload->set_silent(notification_data.silent);
payload->set_require_interaction(notification_data.require_interaction);
@@ -119,8 +146,28 @@ bool SerializeNotificationDatabaseData(const NotificationDatabaseData& input,
for (const PlatformNotificationAction& action : notification_data.actions) {
NotificationDatabaseDataProto::NotificationAction* payload_action =
payload->add_actions();
+
+ switch (action.type) {
+ case PLATFORM_NOTIFICATION_ACTION_TYPE_BUTTON:
+ payload_action->set_type(
+ NotificationDatabaseDataProto::NotificationAction::BUTTON);
+ break;
+ case PLATFORM_NOTIFICATION_ACTION_TYPE_TEXT:
+ payload_action->set_type(
+ NotificationDatabaseDataProto::NotificationAction::TEXT);
+ break;
+ default:
+ NOTREACHED() << "Unknown action type: " << action.type;
+ }
+
payload_action->set_action(action.action);
payload_action->set_title(base::UTF16ToUTF8(action.title));
+ payload_action->set_icon(action.icon.spec());
+
+ if (!action.placeholder.is_null()) {
+ payload_action->set_placeholder(
+ base::UTF16ToUTF8(action.placeholder.string()));
+ }
}
NotificationDatabaseDataProto message;
diff --git a/chromium/content/browser/notifications/notification_database_data_unittest.cc b/chromium/content/browser/notifications/notification_database_data_unittest.cc
index a080ae4d558..bf93b3547ee 100644
--- a/chromium/content/browser/notifications/notification_database_data_unittest.cc
+++ b/chromium/content/browser/notifications/notification_database_data_unittest.cc
@@ -6,8 +6,10 @@
#include <stdint.h>
#include "base/macros.h"
+#include "base/strings/nullable_string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
#include "content/browser/notifications/notification_database_data.pb.h"
#include "content/browser/notifications/notification_database_data_conversions.h"
#include "content/common/notification_constants.h"
@@ -20,13 +22,18 @@ namespace content {
const int64_t kNotificationId = 42;
const int64_t kServiceWorkerRegistrationId = 9001;
+const PlatformNotificationActionType kNotificationActionType =
+ PLATFORM_NOTIFICATION_ACTION_TYPE_TEXT;
const char kOrigin[] = "https://example.com/";
const char kNotificationTitle[] = "My Notification";
const char kNotificationLang[] = "nl";
const char kNotificationBody[] = "Hello, world!";
const char kNotificationTag[] = "my_tag";
const char kNotificationIconUrl[] = "https://example.com/icon.png";
+const char kNotificationBadgeUrl[] = "https://example.com/badge.png";
+const char kNotificationActionIconUrl[] = "https://example.com/action_icon.png";
const int kNotificationVibrationPattern[] = {100, 200, 300};
+const double kNotificationTimestamp = 621046800.;
const unsigned char kNotificationData[] = {0xdf, 0xff, 0x0, 0x0, 0xff, 0xdf};
TEST(NotificationDatabaseDataTest, SerializeAndDeserializeData) {
@@ -45,14 +52,21 @@ TEST(NotificationDatabaseDataTest, SerializeAndDeserializeData) {
notification_data.body = base::ASCIIToUTF16(kNotificationBody);
notification_data.tag = kNotificationTag;
notification_data.icon = GURL(kNotificationIconUrl);
+ notification_data.badge = GURL(kNotificationBadgeUrl);
notification_data.vibration_pattern = vibration_pattern;
+ notification_data.timestamp = base::Time::FromJsTime(kNotificationTimestamp);
+ notification_data.renotify = true;
notification_data.silent = true;
notification_data.require_interaction = true;
notification_data.data = developer_data;
for (size_t i = 0; i < kPlatformNotificationMaxActions; i++) {
PlatformNotificationAction notification_action;
+ notification_action.type = kNotificationActionType;
notification_action.action = base::SizeTToString(i);
notification_action.title = base::SizeTToString16(i);
+ notification_action.icon = GURL(kNotificationActionIconUrl);
+ notification_action.placeholder =
+ base::NullableString16(base::SizeTToString16(i), false);
notification_data.actions.push_back(notification_action);
}
@@ -88,10 +102,13 @@ TEST(NotificationDatabaseDataTest, SerializeAndDeserializeData) {
EXPECT_EQ(notification_data.body, copied_notification_data.body);
EXPECT_EQ(notification_data.tag, copied_notification_data.tag);
EXPECT_EQ(notification_data.icon, copied_notification_data.icon);
+ EXPECT_EQ(notification_data.badge, copied_notification_data.badge);
EXPECT_THAT(copied_notification_data.vibration_pattern,
testing::ElementsAreArray(kNotificationVibrationPattern));
+ EXPECT_EQ(notification_data.timestamp, copied_notification_data.timestamp);
+ EXPECT_EQ(notification_data.renotify, copied_notification_data.renotify);
EXPECT_EQ(notification_data.silent, copied_notification_data.silent);
EXPECT_EQ(notification_data.require_interaction,
copied_notification_data.require_interaction);
@@ -103,10 +120,44 @@ TEST(NotificationDatabaseDataTest, SerializeAndDeserializeData) {
ASSERT_EQ(notification_data.actions.size(),
copied_notification_data.actions.size());
for (size_t i = 0; i < notification_data.actions.size(); ++i) {
+ EXPECT_EQ(notification_data.actions[i].type,
+ copied_notification_data.actions[i].type);
EXPECT_EQ(notification_data.actions[i].action,
copied_notification_data.actions[i].action);
EXPECT_EQ(notification_data.actions[i].title,
copied_notification_data.actions[i].title);
+ EXPECT_EQ(notification_data.actions[i].icon,
+ copied_notification_data.actions[i].icon);
+ EXPECT_EQ(notification_data.actions[i].placeholder,
+ copied_notification_data.actions[i].placeholder);
+ EXPECT_FALSE(copied_notification_data.actions[i].placeholder.is_null());
+ }
+}
+
+TEST(NotificationDatabaseDataTest, SerializeAndDeserializeActionTypes) {
+ PlatformNotificationActionType action_types[] = {
+ PLATFORM_NOTIFICATION_ACTION_TYPE_BUTTON,
+ PLATFORM_NOTIFICATION_ACTION_TYPE_TEXT};
+
+ for (PlatformNotificationActionType action_type : action_types) {
+ PlatformNotificationData notification_data;
+
+ PlatformNotificationAction action;
+ action.type = action_type;
+ notification_data.actions.push_back(action);
+
+ NotificationDatabaseData database_data;
+ database_data.notification_data = notification_data;
+
+ std::string serialized_data;
+ ASSERT_TRUE(
+ SerializeNotificationDatabaseData(database_data, &serialized_data));
+
+ NotificationDatabaseData copied_data;
+ ASSERT_TRUE(
+ DeserializeNotificationDatabaseData(serialized_data, &copied_data));
+
+ EXPECT_EQ(action_type, copied_data.notification_data.actions[0].type);
}
}
@@ -135,4 +186,26 @@ TEST(NotificationDatabaseDataTest, SerializeAndDeserializeDirections) {
}
}
+TEST(NotificationDatabaseDataTest, SerializeAndDeserializeNullPlaceholder) {
+ PlatformNotificationAction action;
+ action.type = kNotificationActionType;
+ action.placeholder = base::NullableString16(); // null string.
+
+ PlatformNotificationData notification_data;
+ notification_data.actions.push_back(action);
+
+ NotificationDatabaseData database_data;
+ database_data.notification_data = notification_data;
+
+ std::string serialized_data;
+ ASSERT_TRUE(
+ SerializeNotificationDatabaseData(database_data, &serialized_data));
+
+ NotificationDatabaseData copied_data;
+ ASSERT_TRUE(
+ DeserializeNotificationDatabaseData(serialized_data, &copied_data));
+
+ EXPECT_TRUE(copied_data.notification_data.actions[0].placeholder.is_null());
+}
+
} // namespace content
diff --git a/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc b/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc
index d48491ce2b8..032d50362f5 100644
--- a/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc
+++ b/chromium/content/browser/notifications/notification_event_dispatcher_impl.cc
@@ -10,32 +10,47 @@
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_storage.h"
+#include "content/common/service_worker/service_worker_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/notification_database_data.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/platform_notification_data.h"
namespace content {
namespace {
-using NotificationClickDispatchCompleteCallback =
- NotificationEventDispatcher::NotificationClickDispatchCompleteCallback;
+using NotificationDispatchCompleteCallback =
+ NotificationEventDispatcher::NotificationDispatchCompleteCallback;
+using NotificationOperationCallback =
+ base::Callback<void(const ServiceWorkerRegistration*,
+ const NotificationDatabaseData&)>;
+using NotificationOperationCallbackWithContext =
+ base::Callback<void(const scoped_refptr<PlatformNotificationContext>&,
+ const ServiceWorkerRegistration*,
+ const NotificationDatabaseData&)>;
-// To be called when the notificationclick event has finished executing. Will
-// post a task to call |dispatch_complete_callback| on the UI thread.
-void NotificationClickEventFinished(
- const NotificationClickDispatchCompleteCallback& dispatch_complete_callback,
- const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration,
- ServiceWorkerStatusCode service_worker_status) {
+// To be called when a notification event has finished executing. Will post a
+// task to call |dispatch_complete_callback| on the UI thread.
+void NotificationEventFinished(
+ const NotificationDispatchCompleteCallback& dispatch_complete_callback,
+ PersistentNotificationStatus status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(dispatch_complete_callback, status));
+}
+
+// To be called when a notification event has finished with a
+// ServiceWorkerStatusCode result. Will call NotificationEventFinished with a
+// PersistentNotificationStatus derived from the service worker status.
+void ServiceWorkerNotificationEventFinished(
+ const NotificationDispatchCompleteCallback& dispatch_complete_callback,
+ ServiceWorkerStatusCode service_worker_status) {
#if defined(OS_ANDROID)
// This LOG(INFO) deliberately exists to help track down the cause of
// https://crbug.com/534537, where notifications sometimes do not react to
// the user clicking on them. It should be removed once that's fixed.
- LOG(INFO) << "The notificationclick event has finished: "
- << service_worker_status;
+ LOG(INFO) << "The notification event has finished: " << service_worker_status;
#endif
PersistentNotificationStatus status = PERSISTENT_NOTIFICATION_STATUS_SUCCESS;
@@ -67,17 +82,17 @@ void NotificationClickEventFinished(
status = PERSISTENT_NOTIFICATION_STATUS_SERVICE_WORKER_ERROR;
break;
}
-
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(dispatch_complete_callback, status));
+ NotificationEventFinished(dispatch_complete_callback, status);
}
-// Dispatches the notificationclick on |service_worker_registration| if the
-// registration was available. Must be called on the IO thread.
-void DispatchNotificationClickEventOnRegistration(
+// Dispatches the given notification action event on
+// |service_worker_registration| if the registration was available. Must be
+// called on the IO thread.
+void DispatchNotificationEventOnRegistration(
const NotificationDatabaseData& notification_database_data,
- int action_index,
- const NotificationClickDispatchCompleteCallback& dispatch_complete_callback,
+ const scoped_refptr<PlatformNotificationContext>& notification_context,
+ const NotificationOperationCallback& dispatch_event_action,
+ const NotificationDispatchCompleteCallback& dispatch_error_callback,
ServiceWorkerStatusCode service_worker_status,
const scoped_refptr<ServiceWorkerRegistration>&
service_worker_registration) {
@@ -87,18 +102,13 @@ void DispatchNotificationClickEventOnRegistration(
// https://crbug.com/534537, where notifications sometimes do not react to
// the user clicking on them. It should be removed once that's fixed.
LOG(INFO) << "Trying to dispatch notification for SW with status: "
- << service_worker_status << " action_index: " << action_index;
+ << service_worker_status;
#endif
if (service_worker_status == SERVICE_WORKER_OK) {
- base::Callback<void(ServiceWorkerStatusCode)> dispatch_event_callback =
- base::Bind(&NotificationClickEventFinished, dispatch_complete_callback,
- service_worker_registration);
-
DCHECK(service_worker_registration->active_version());
- service_worker_registration->active_version()
- ->DispatchNotificationClickEvent(
- dispatch_event_callback, notification_database_data.notification_id,
- notification_database_data.notification_data, action_index);
+
+ dispatch_event_action.Run(service_worker_registration.get(),
+ notification_database_data);
return;
}
@@ -133,16 +143,17 @@ void DispatchNotificationClickEventOnRegistration(
}
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(dispatch_complete_callback, status));
+ base::Bind(dispatch_error_callback, status));
}
// Finds the ServiceWorkerRegistration associated with the |origin| and
// |service_worker_registration_id|. Must be called on the IO thread.
void FindServiceWorkerRegistration(
const GURL& origin,
- int action_index,
- const NotificationClickDispatchCompleteCallback& dispatch_complete_callback,
- scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
+ const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context,
+ const scoped_refptr<PlatformNotificationContext>& notification_context,
+ const NotificationOperationCallback& notification_action_callback,
+ const NotificationDispatchCompleteCallback& dispatch_error_callback,
bool success,
const NotificationDatabaseData& notification_database_data) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -151,22 +162,21 @@ void FindServiceWorkerRegistration(
// This LOG(INFO) deliberately exists to help track down the cause of
// https://crbug.com/534537, where notifications sometimes do not react to
// the user clicking on them. It should be removed once that's fixed.
- LOG(INFO) << "Lookup for ServiceWoker Registration: success:" << success
- << " action_index: " << action_index;
+ LOG(INFO) << "Lookup for ServiceWoker Registration: success: " << success;
#endif
if (!success) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(dispatch_complete_callback,
+ base::Bind(dispatch_error_callback,
PERSISTENT_NOTIFICATION_STATUS_DATABASE_ERROR));
return;
}
service_worker_context->FindReadyRegistrationForId(
notification_database_data.service_worker_registration_id, origin,
- base::Bind(&DispatchNotificationClickEventOnRegistration,
- notification_database_data, action_index,
- dispatch_complete_callback));
+ base::Bind(&DispatchNotificationEventOnRegistration,
+ notification_database_data, notification_context,
+ notification_action_callback, dispatch_error_callback));
}
// Reads the data associated with the |persistent_notification_id| belonging to
@@ -174,41 +184,140 @@ void FindServiceWorkerRegistration(
void ReadNotificationDatabaseData(
int64_t persistent_notification_id,
const GURL& origin,
- int action_index,
- const NotificationClickDispatchCompleteCallback& dispatch_complete_callback,
- scoped_refptr<ServiceWorkerContextWrapper> service_worker_context,
- scoped_refptr<PlatformNotificationContextImpl> notification_context) {
+ const scoped_refptr<ServiceWorkerContextWrapper>& service_worker_context,
+ const scoped_refptr<PlatformNotificationContext>& notification_context,
+ const NotificationOperationCallback& notification_read_callback,
+ const NotificationDispatchCompleteCallback& dispatch_error_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
notification_context->ReadNotificationData(
persistent_notification_id, origin,
- base::Bind(&FindServiceWorkerRegistration, origin, action_index,
- dispatch_complete_callback, service_worker_context));
+ base::Bind(&FindServiceWorkerRegistration, origin, service_worker_context,
+ notification_context, notification_read_callback,
+ dispatch_error_callback));
}
-} // namespace
+// -----------------------------------------------------------------------------
-// static
-NotificationEventDispatcher* NotificationEventDispatcher::GetInstance() {
- return NotificationEventDispatcherImpl::GetInstance();
+// Dispatches the notificationclick event on |service_worker|. Must be called on
+// the IO thread, and with the worker running.
+void DispatchNotificationClickEventOnWorker(
+ const scoped_refptr<ServiceWorkerVersion>& service_worker,
+ const NotificationDatabaseData& notification_database_data,
+ int action_index,
+ const ServiceWorkerVersion::StatusCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ int request_id = service_worker->StartRequest(
+ ServiceWorkerMetrics::EventType::NOTIFICATION_CLICK, callback);
+ service_worker->DispatchSimpleEvent<
+ ServiceWorkerHostMsg_NotificationClickEventFinished>(
+ request_id,
+ ServiceWorkerMsg_NotificationClickEvent(
+ request_id, notification_database_data.notification_id,
+ notification_database_data.notification_data, action_index));
}
-NotificationEventDispatcherImpl*
-NotificationEventDispatcherImpl::GetInstance() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- return base::Singleton<NotificationEventDispatcherImpl>::get();
+// Dispatches the notification click event on the |service_worker_registration|.
+void DoDispatchNotificationClickEvent(
+ int action_index,
+ const NotificationDispatchCompleteCallback& dispatch_complete_callback,
+ const scoped_refptr<PlatformNotificationContext>& notification_context,
+ const ServiceWorkerRegistration* service_worker_registration,
+ const NotificationDatabaseData& notification_database_data) {
+ ServiceWorkerVersion::StatusCallback status_callback = base::Bind(
+ &ServiceWorkerNotificationEventFinished, dispatch_complete_callback);
+ service_worker_registration->active_version()->RunAfterStartWorker(
+ ServiceWorkerMetrics::EventType::NOTIFICATION_CLICK,
+ base::Bind(
+ &DispatchNotificationClickEventOnWorker,
+ make_scoped_refptr(service_worker_registration->active_version()),
+ notification_database_data, action_index, status_callback),
+ status_callback);
}
-NotificationEventDispatcherImpl::NotificationEventDispatcherImpl() {}
+// -----------------------------------------------------------------------------
-NotificationEventDispatcherImpl::~NotificationEventDispatcherImpl() {}
+// Called when the notification data has been deleted to finish the notification
+// close event.
+void OnPersistentNotificationDataDeleted(
+ ServiceWorkerStatusCode service_worker_status,
+ const NotificationDispatchCompleteCallback& dispatch_complete_callback,
+ bool success) {
+ if (service_worker_status != SERVICE_WORKER_OK) {
+ ServiceWorkerNotificationEventFinished(dispatch_complete_callback,
+ service_worker_status);
+ return;
+ }
+ NotificationEventFinished(
+ dispatch_complete_callback,
+ success ? PERSISTENT_NOTIFICATION_STATUS_SUCCESS
+ : PERSISTENT_NOTIFICATION_STATUS_DATABASE_ERROR);
+}
-void NotificationEventDispatcherImpl::DispatchNotificationClickEvent(
+// Called when the persistent notification close event has been handled
+// to remove the notification from the database.
+void DeleteNotificationDataFromDatabase(
+ const int64_t notification_id,
+ const GURL& origin,
+ const scoped_refptr<PlatformNotificationContext>& notification_context,
+ const NotificationDispatchCompleteCallback& dispatch_complete_callback,
+ ServiceWorkerStatusCode status_code) {
+ notification_context->DeleteNotificationData(
+ notification_id, origin,
+ base::Bind(&OnPersistentNotificationDataDeleted, status_code,
+ dispatch_complete_callback));
+}
+
+// Dispatches the notificationclose event on |service_worker|. Must be called on
+// the IO thread, and with the worker running.
+void DispatchNotificationCloseEventOnWorker(
+ const scoped_refptr<ServiceWorkerVersion>& service_worker,
+ const NotificationDatabaseData& notification_database_data,
+ const ServiceWorkerVersion::StatusCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ int request_id = service_worker->StartRequest(
+ ServiceWorkerMetrics::EventType::NOTIFICATION_CLOSE, callback);
+ service_worker->DispatchSimpleEvent<
+ ServiceWorkerHostMsg_NotificationCloseEventFinished>(
+ request_id, ServiceWorkerMsg_NotificationCloseEvent(
+ request_id, notification_database_data.notification_id,
+ notification_database_data.notification_data));
+}
+
+// Actually dispatches the notification close event on the service worker
+// registration.
+void DoDispatchNotificationCloseEvent(
+ bool by_user,
+ const NotificationDispatchCompleteCallback& dispatch_complete_callback,
+ const scoped_refptr<PlatformNotificationContext>& notification_context,
+ const ServiceWorkerRegistration* service_worker_registration,
+ const NotificationDatabaseData& notification_database_data) {
+ const ServiceWorkerVersion::StatusCallback dispatch_event_callback =
+ base::Bind(&DeleteNotificationDataFromDatabase,
+ notification_database_data.notification_id,
+ notification_database_data.origin, notification_context,
+ dispatch_complete_callback);
+ if (by_user) {
+ service_worker_registration->active_version()->RunAfterStartWorker(
+ ServiceWorkerMetrics::EventType::NOTIFICATION_CLOSE,
+ base::Bind(
+ &DispatchNotificationCloseEventOnWorker,
+ make_scoped_refptr(service_worker_registration->active_version()),
+ notification_database_data, dispatch_event_callback),
+ dispatch_event_callback);
+ } else {
+ dispatch_event_callback.Run(ServiceWorkerStatusCode::SERVICE_WORKER_OK);
+ }
+}
+
+// Dispatches any notification event. The actual, specific event dispatch should
+// be done by the |notification_action_callback|.
+void DispatchNotificationEvent(
BrowserContext* browser_context,
int64_t persistent_notification_id,
const GURL& origin,
- int action_index,
- const NotificationClickDispatchCompleteCallback&
- dispatch_complete_callback) {
+ const NotificationOperationCallbackWithContext&
+ notification_action_callback,
+ const NotificationDispatchCompleteCallback& notification_error_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK_GT(persistent_notification_id, 0);
DCHECK(origin.is_valid());
@@ -219,15 +328,57 @@ void NotificationEventDispatcherImpl::DispatchNotificationClickEvent(
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context =
static_cast<ServiceWorkerContextWrapper*>(
partition->GetServiceWorkerContext());
- scoped_refptr<PlatformNotificationContextImpl> notification_context =
- static_cast<PlatformNotificationContextImpl*>(
- partition->GetPlatformNotificationContext());
+ scoped_refptr<PlatformNotificationContext> notification_context =
+ partition->GetPlatformNotificationContext();
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&ReadNotificationDatabaseData, persistent_notification_id,
- origin, action_index, dispatch_complete_callback,
- service_worker_context, notification_context));
+ origin, service_worker_context, notification_context,
+ base::Bind(notification_action_callback, notification_context),
+ notification_error_callback));
+}
+
+} // namespace
+
+// static
+NotificationEventDispatcher* NotificationEventDispatcher::GetInstance() {
+ return NotificationEventDispatcherImpl::GetInstance();
+}
+
+NotificationEventDispatcherImpl*
+NotificationEventDispatcherImpl::GetInstance() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ return base::Singleton<NotificationEventDispatcherImpl>::get();
+}
+
+NotificationEventDispatcherImpl::NotificationEventDispatcherImpl() {}
+
+NotificationEventDispatcherImpl::~NotificationEventDispatcherImpl() {}
+
+void NotificationEventDispatcherImpl::DispatchNotificationClickEvent(
+ BrowserContext* browser_context,
+ int64_t persistent_notification_id,
+ const GURL& origin,
+ int action_index,
+ const NotificationDispatchCompleteCallback& dispatch_complete_callback) {
+ DispatchNotificationEvent(
+ browser_context, persistent_notification_id, origin,
+ base::Bind(&DoDispatchNotificationClickEvent, action_index,
+ dispatch_complete_callback),
+ dispatch_complete_callback);
+}
+
+void NotificationEventDispatcherImpl::DispatchNotificationCloseEvent(
+ BrowserContext* browser_context,
+ int64_t persistent_notification_id,
+ const GURL& origin,
+ bool by_user,
+ const NotificationDispatchCompleteCallback& dispatch_complete_callback) {
+ DispatchNotificationEvent(browser_context, persistent_notification_id, origin,
+ base::Bind(&DoDispatchNotificationCloseEvent,
+ by_user, dispatch_complete_callback),
+ dispatch_complete_callback);
}
} // namespace content
diff --git a/chromium/content/browser/notifications/notification_event_dispatcher_impl.h b/chromium/content/browser/notifications/notification_event_dispatcher_impl.h
index fbc5d429f27..fc19dc9ed77 100644
--- a/chromium/content/browser/notifications/notification_event_dispatcher_impl.h
+++ b/chromium/content/browser/notifications/notification_event_dispatcher_impl.h
@@ -9,6 +9,7 @@
#include "base/macros.h"
#include "base/memory/singleton.h"
+#include "content/public/browser/notification_database_data.h"
#include "content/public/browser/notification_event_dispatcher.h"
namespace content {
@@ -25,8 +26,15 @@ class NotificationEventDispatcherImpl : public NotificationEventDispatcher {
int64_t persistent_notification_id,
const GURL& origin,
int action_index,
- const NotificationClickDispatchCompleteCallback&
- dispatch_complete_callback) override;
+ const NotificationDispatchCompleteCallback& dispatch_complete_callback)
+ override;
+ void DispatchNotificationCloseEvent(
+ BrowserContext* browser_context,
+ int64_t persistent_notification_id,
+ const GURL& origin,
+ bool by_user,
+ const NotificationDispatchCompleteCallback& dispatch_complete_callback)
+ override;
private:
NotificationEventDispatcherImpl();
diff --git a/chromium/content/browser/notifications/notification_message_filter.cc b/chromium/content/browser/notifications/notification_message_filter.cc
index f8c3ba89435..08297505482 100644
--- a/chromium/content/browser/notifications/notification_message_filter.cc
+++ b/chromium/content/browser/notifications/notification_message_filter.cc
@@ -45,6 +45,27 @@ PlatformNotificationData SanitizeNotificationData(
return sanitized_data;
}
+// Returns true when |resources| looks ok, false otherwise.
+bool ValidateNotificationResources(const NotificationResources& resources) {
+ if (resources.notification_icon.width() >
+ kPlatformNotificationMaxIconSizePx ||
+ resources.notification_icon.height() >
+ kPlatformNotificationMaxIconSizePx) {
+ return false;
+ }
+ if (resources.badge.width() > kPlatformNotificationMaxBadgeSizePx ||
+ resources.badge.height() > kPlatformNotificationMaxBadgeSizePx) {
+ return false;
+ }
+ for (const auto& action_icon : resources.action_icons) {
+ if (action_icon.width() > kPlatformNotificationMaxActionIconSizePx ||
+ action_icon.height() > kPlatformNotificationMaxActionIconSizePx) {
+ return false;
+ }
+ }
+ return true;
+}
+
} // namespace
NotificationMessageFilter::NotificationMessageFilter(
@@ -109,12 +130,17 @@ void NotificationMessageFilter::OnCheckNotificationPermission(
void NotificationMessageFilter::OnShowPlatformNotification(
int notification_id,
const GURL& origin,
- const SkBitmap& icon,
- const PlatformNotificationData& notification_data) {
+ const PlatformNotificationData& notification_data,
+ const NotificationResources& notification_resources) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!RenderProcessHost::FromID(process_id_))
return;
+ if (!ValidateNotificationResources(notification_resources)) {
+ bad_message::ReceivedBadMessage(this, bad_message::NMF_INVALID_ARGUMENT);
+ return;
+ }
+
scoped_ptr<DesktopNotificationDelegate> delegate(
new PageNotificationDelegate(process_id_, notification_id));
@@ -126,9 +152,9 @@ void NotificationMessageFilter::OnShowPlatformNotification(
return;
base::Closure close_closure;
- service->DisplayNotification(browser_context_, origin, icon,
- SanitizeNotificationData(notification_data),
- std::move(delegate), &close_closure);
+ service->DisplayNotification(
+ browser_context_, origin, SanitizeNotificationData(notification_data),
+ notification_resources, std::move(delegate), &close_closure);
if (!close_closure.is_null())
close_closures_[notification_id] = close_closure;
@@ -138,8 +164,8 @@ void NotificationMessageFilter::OnShowPersistentNotification(
int request_id,
int64_t service_worker_registration_id,
const GURL& origin,
- const SkBitmap& icon,
- const PlatformNotificationData& notification_data) {
+ const PlatformNotificationData& notification_data,
+ const NotificationResources& notification_resources) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (GetPermissionForOriginOnIO(origin) !=
blink::WebNotificationPermissionAllowed) {
@@ -147,6 +173,11 @@ void NotificationMessageFilter::OnShowPersistentNotification(
return;
}
+ if (!ValidateNotificationResources(notification_resources)) {
+ bad_message::ReceivedBadMessage(this, bad_message::NMF_INVALID_ARGUMENT);
+ return;
+ }
+
NotificationDatabaseData database_data;
database_data.origin = origin;
database_data.service_worker_registration_id = service_worker_registration_id;
@@ -160,15 +191,15 @@ void NotificationMessageFilter::OnShowPersistentNotification(
notification_context_->WriteNotificationData(
origin, database_data,
base::Bind(&NotificationMessageFilter::DidWritePersistentNotificationData,
- weak_factory_io_.GetWeakPtr(), request_id, origin, icon,
- sanitized_notification_data));
+ weak_factory_io_.GetWeakPtr(), request_id, origin,
+ sanitized_notification_data, notification_resources));
}
void NotificationMessageFilter::DidWritePersistentNotificationData(
int request_id,
const GURL& origin,
- const SkBitmap& icon,
const PlatformNotificationData& notification_data,
+ const NotificationResources& notification_resources,
bool success,
int64_t persistent_notification_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -182,8 +213,8 @@ void NotificationMessageFilter::DidWritePersistentNotificationData(
BrowserThread::UI, FROM_HERE,
base::Bind(&PlatformNotificationService::DisplayPersistentNotification,
base::Unretained(service), // The service is a singleton.
- browser_context_, persistent_notification_id, origin, icon,
- notification_data));
+ browser_context_, persistent_notification_id, origin,
+ notification_data, notification_resources));
}
Send(new PlatformNotificationMsg_DidShowPersistent(request_id, success));
diff --git a/chromium/content/browser/notifications/notification_message_filter.h b/chromium/content/browser/notifications/notification_message_filter.h
index 74ecf2f441d..a9d3e231f4d 100644
--- a/chromium/content/browser/notifications/notification_message_filter.h
+++ b/chromium/content/browser/notifications/notification_message_filter.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include <map>
+#include <vector>
#include "base/callback_forward.h"
#include "base/macros.h"
@@ -17,11 +18,11 @@
#include "third_party/WebKit/public/platform/modules/notifications/WebNotificationPermission.h"
class GURL;
-class SkBitmap;
namespace content {
class BrowserContext;
+struct NotificationResources;
class PlatformNotificationContextImpl;
struct PlatformNotificationData;
class PlatformNotificationService;
@@ -57,14 +58,14 @@ class NotificationMessageFilter : public BrowserMessageFilter {
void OnShowPlatformNotification(
int notification_id,
const GURL& origin,
- const SkBitmap& icon,
- const PlatformNotificationData& notification_data);
+ const PlatformNotificationData& notification_data,
+ const NotificationResources& notification_resources);
void OnShowPersistentNotification(
int request_id,
int64_t service_worker_registration_id,
const GURL& origin,
- const SkBitmap& icon,
- const PlatformNotificationData& notification_data);
+ const PlatformNotificationData& notification_data,
+ const NotificationResources& notification_resources);
void OnGetNotifications(int request_id,
int64_t service_worker_registration_id,
const GURL& origin,
@@ -79,8 +80,8 @@ class NotificationMessageFilter : public BrowserMessageFilter {
void DidWritePersistentNotificationData(
int request_id,
const GURL& origin,
- const SkBitmap& icon,
const PlatformNotificationData& notification_data,
+ const NotificationResources& notification_resources,
bool success,
int64_t persistent_notification_id);
diff --git a/chromium/content/browser/permissions/permission_service_context.cc b/chromium/content/browser/permissions/permission_service_context.cc
index 91bd4d04ac1..a83267a0db7 100644
--- a/chromium/content/browser/permissions/permission_service_context.cc
+++ b/chromium/content/browser/permissions/permission_service_context.cc
@@ -32,7 +32,7 @@ PermissionServiceContext::~PermissionServiceContext() {
}
void PermissionServiceContext::CreateService(
- mojo::InterfaceRequest<PermissionService> request) {
+ mojo::InterfaceRequest<blink::mojom::PermissionService> request) {
services_.push_back(new PermissionServiceImpl(this, std::move(request)));
}
diff --git a/chromium/content/browser/permissions/permission_service_context.h b/chromium/content/browser/permissions/permission_service_context.h
index 0534ae1b61d..3db134edd82 100644
--- a/chromium/content/browser/permissions/permission_service_context.h
+++ b/chromium/content/browser/permissions/permission_service_context.h
@@ -10,26 +10,33 @@
#include "content/public/browser/web_contents_observer.h"
#include "mojo/public/cpp/bindings/interface_request.h"
+namespace blink {
+namespace mojom {
+class PermissionService;
+}
+}
+
namespace content {
-class PermissionService;
class PermissionServiceImpl;
class RenderFrameHost;
class RenderProcessHost;
// Provides information to a PermissionService. It is used by the
-// PermissionService to handle request permission UI.
+// PermissionServiceImpl to handle request permission UI.
// There is one PermissionServiceContext per RenderFrameHost/RenderProcessHost
-// which owns it. It then owns all PermissionService associated to their owner.
+// which owns it. It then owns all PermissionServiceImpl associated to their
+// owner.
class PermissionServiceContext : public WebContentsObserver {
public:
explicit PermissionServiceContext(RenderFrameHost* render_frame_host);
explicit PermissionServiceContext(RenderProcessHost* render_process_host);
~PermissionServiceContext() override;
- void CreateService(mojo::InterfaceRequest<PermissionService> request);
+ void CreateService(
+ mojo::InterfaceRequest<blink::mojom::PermissionService> request);
- // Called by a PermissionService identified as |service| when it has a
+ // Called by a PermissionServiceImpl identified as |service| when it has a
// connection error in order to get unregistered and killed.
void ServiceHadConnectionError(PermissionServiceImpl* service);
diff --git a/chromium/content/browser/permissions/permission_service_impl.cc b/chromium/content/browser/permissions/permission_service_impl.cc
index ce1f25f92ad..c7f92a8d9e9 100644
--- a/chromium/content/browser/permissions/permission_service_impl.cc
+++ b/chromium/content/browser/permissions/permission_service_impl.cc
@@ -12,30 +12,35 @@
#include "content/public/browser/permission_manager.h"
#include "content/public/browser/permission_type.h"
+using blink::mojom::PermissionName;
+using blink::mojom::PermissionStatus;
+
namespace content {
namespace {
PermissionType PermissionNameToPermissionType(PermissionName name) {
switch(name) {
- case PERMISSION_NAME_GEOLOCATION:
+ case PermissionName::GEOLOCATION:
return PermissionType::GEOLOCATION;
- case PERMISSION_NAME_NOTIFICATIONS:
+ case PermissionName::NOTIFICATIONS:
return PermissionType::NOTIFICATIONS;
- case PERMISSION_NAME_PUSH_NOTIFICATIONS:
+ case PermissionName::PUSH_NOTIFICATIONS:
return PermissionType::PUSH_MESSAGING;
- case PERMISSION_NAME_MIDI:
+ case PermissionName::MIDI:
return PermissionType::MIDI;
- case PERMISSION_NAME_MIDI_SYSEX:
+ case PermissionName::MIDI_SYSEX:
return PermissionType::MIDI_SYSEX;
- case PERMISSION_NAME_PROTECTED_MEDIA_IDENTIFIER:
+ case PermissionName::PROTECTED_MEDIA_IDENTIFIER:
return PermissionType::PROTECTED_MEDIA_IDENTIFIER;
- case PERMISSION_NAME_DURABLE_STORAGE:
+ case PermissionName::DURABLE_STORAGE:
return PermissionType::DURABLE_STORAGE;
- case PERMISSION_NAME_AUDIO_CAPTURE:
+ case PermissionName::AUDIO_CAPTURE:
return PermissionType::AUDIO_CAPTURE;
- case PERMISSION_NAME_VIDEO_CAPTURE:
+ case PermissionName::VIDEO_CAPTURE:
return PermissionType::VIDEO_CAPTURE;
+ case PermissionName::BACKGROUND_SYNC:
+ return PermissionType::BACKGROUND_SYNC;
}
NOTREACHED();
@@ -67,7 +72,7 @@ PermissionServiceImpl::PendingRequest::~PendingRequest() {
mojo::Array<PermissionStatus> result =
mojo::Array<PermissionStatus>::New(request_count);
for (int i = 0; i < request_count; ++i)
- result[i] = PERMISSION_STATUS_DENIED;
+ result[i] = PermissionStatus::DENIED;
callback.Run(std::move(result));
}
@@ -83,12 +88,12 @@ PermissionServiceImpl::PendingSubscription::PendingSubscription(
PermissionServiceImpl::PendingSubscription::~PendingSubscription() {
if (!callback.is_null())
- callback.Run(PERMISSION_STATUS_ASK);
+ callback.Run(PermissionStatus::ASK);
}
PermissionServiceImpl::PermissionServiceImpl(
PermissionServiceContext* context,
- mojo::InterfaceRequest<PermissionService> request)
+ mojo::InterfaceRequest<blink::mojom::PermissionService> request)
: context_(context),
binding_(this, std::move(request)),
weak_factory_(this) {
@@ -109,7 +114,6 @@ void PermissionServiceImpl::OnConnectionError() {
void PermissionServiceImpl::RequestPermission(
PermissionName permission,
const mojo::String& origin,
- bool user_gesture,
const PermissionStatusCallback& callback) {
// This condition is valid if the call is coming from a ChildThread instead of
// a RenderFrame. Some consumers of the service run in Workers and some in
@@ -122,7 +126,7 @@ void PermissionServiceImpl::RequestPermission(
DCHECK(browser_context);
if (!context_->render_frame_host() ||
!browser_context->GetPermissionManager()) {
- callback.Run(GetPermissionStatusFromName(permission, GURL(origin)));
+ callback.Run(GetPermissionStatusFromName(permission, GURL(origin.get())));
return;
}
@@ -131,8 +135,7 @@ void PermissionServiceImpl::RequestPermission(
int id = browser_context->GetPermissionManager()->RequestPermission(
PermissionNameToPermissionType(permission),
context_->render_frame_host(),
- GURL(origin),
- user_gesture, // TODO(mlamouri): should be removed (crbug.com/423770)
+ GURL(origin.get()),
base::Bind(&PermissionServiceImpl::OnRequestPermissionResponse,
weak_factory_.GetWeakPtr(),
pending_request_id));
@@ -150,13 +153,12 @@ void PermissionServiceImpl::OnRequestPermissionResponse(
int pending_request_id,
PermissionStatus status) {
OnRequestPermissionsResponse(pending_request_id,
- std::vector<PermissionStatus>(1, status));
+ std::vector<PermissionStatus>(1, status));
}
void PermissionServiceImpl::RequestPermissions(
mojo::Array<PermissionName> permissions,
const mojo::String& origin,
- bool user_gesture,
const PermissionsStatusCallback& callback) {
if (permissions.is_null()) {
callback.Run(mojo::Array<PermissionStatus>());
@@ -175,8 +177,10 @@ void PermissionServiceImpl::RequestPermissions(
if (!context_->render_frame_host() ||
!browser_context->GetPermissionManager()) {
mojo::Array<PermissionStatus> result(permissions.size());
- for (size_t i = 0; i < permissions.size(); ++i)
- result[i] = GetPermissionStatusFromName(permissions[i], GURL(origin));
+ for (size_t i = 0; i < permissions.size(); ++i) {
+ result[i] =
+ GetPermissionStatusFromName(permissions[i], GURL(origin.get()));
+ }
callback.Run(std::move(result));
return;
}
@@ -190,8 +194,7 @@ void PermissionServiceImpl::RequestPermissions(
int id = browser_context->GetPermissionManager()->RequestPermissions(
types,
context_->render_frame_host(),
- GURL(origin),
- user_gesture, // TODO(mlamouri): should be removed (crbug.com/423770)
+ GURL(origin.get()),
base::Bind(&PermissionServiceImpl::OnRequestPermissionsResponse,
weak_factory_.GetWeakPtr(),
pending_request_id));
@@ -247,21 +250,21 @@ void PermissionServiceImpl::HasPermission(
PermissionName permission,
const mojo::String& origin,
const PermissionStatusCallback& callback) {
- callback.Run(GetPermissionStatusFromName(permission, GURL(origin)));
+ callback.Run(GetPermissionStatusFromName(permission, GURL(origin.get())));
}
void PermissionServiceImpl::RevokePermission(
PermissionName permission,
const mojo::String& origin,
const PermissionStatusCallback& callback) {
- GURL origin_url(origin);
+ GURL origin_url(origin.get());
PermissionType permission_type = PermissionNameToPermissionType(permission);
- PermissionStatus status = GetPermissionStatusFromType(permission_type,
- origin_url);
+ PermissionStatus status =
+ GetPermissionStatusFromType(permission_type, origin_url);
// Resetting the permission should only be possible if the permission is
// already granted.
- if (status != PERMISSION_STATUS_GRANTED) {
+ if (status != PermissionStatus::GRANTED) {
callback.Run(status);
return;
}
@@ -276,7 +279,7 @@ void PermissionServiceImpl::GetNextPermissionChange(
const mojo::String& mojo_origin,
PermissionStatus last_known_status,
const PermissionStatusCallback& callback) {
- GURL origin(mojo_origin);
+ GURL origin(mojo_origin.get());
PermissionStatus current_status =
GetPermissionStatusFromName(permission, origin);
if (current_status != last_known_status) {
@@ -313,17 +316,19 @@ void PermissionServiceImpl::GetNextPermissionChange(
}
PermissionStatus PermissionServiceImpl::GetPermissionStatusFromName(
- PermissionName permission, const GURL& origin) {
+ PermissionName permission,
+ const GURL& origin) {
return GetPermissionStatusFromType(PermissionNameToPermissionType(permission),
origin);
}
PermissionStatus PermissionServiceImpl::GetPermissionStatusFromType(
- PermissionType type, const GURL& origin) {
+ PermissionType type,
+ const GURL& origin) {
BrowserContext* browser_context = context_->GetBrowserContext();
DCHECK(browser_context);
if (!browser_context->GetPermissionManager())
- return PERMISSION_STATUS_DENIED;
+ return PermissionStatus::DENIED;
// If the embedding_origin is empty we'll use |origin| instead.
GURL embedding_origin = context_->GetEmbeddingOrigin();
diff --git a/chromium/content/browser/permissions/permission_service_impl.h b/chromium/content/browser/permissions/permission_service_impl.h
index 13761daca2f..dfda77549f1 100644
--- a/chromium/content/browser/permissions/permission_service_impl.h
+++ b/chromium/content/browser/permissions/permission_service_impl.h
@@ -9,8 +9,8 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/permissions/permission_service_context.h"
-#include "content/common/permission_service.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
+#include "third_party/WebKit/public/platform/modules/permissions/permission.mojom.h"
namespace content {
@@ -23,7 +23,7 @@ enum class PermissionType;
// to have some information about the current context. That enables the service
// to know whether it can show UI and have knowledge of the associated
// WebContents for example.
-class PermissionServiceImpl : public PermissionService {
+class PermissionServiceImpl : public blink::mojom::PermissionService {
public:
~PermissionServiceImpl() override;
@@ -35,13 +35,15 @@ class PermissionServiceImpl : public PermissionService {
protected:
friend PermissionServiceContext;
- PermissionServiceImpl(PermissionServiceContext* context,
- mojo::InterfaceRequest<PermissionService> request);
+ PermissionServiceImpl(
+ PermissionServiceContext* context,
+ mojo::InterfaceRequest<blink::mojom::PermissionService> request);
private:
- using PermissionStatusCallback = mojo::Callback<void(PermissionStatus)>;
+ using PermissionStatusCallback =
+ mojo::Callback<void(blink::mojom::PermissionStatus)>;
using PermissionsStatusCallback =
- mojo::Callback<void(mojo::Array<PermissionStatus>)>;
+ mojo::Callback<void(mojo::Array<blink::mojom::PermissionStatus>)>;
struct PendingRequest {
PendingRequest(const PermissionsStatusCallback& callback,
@@ -68,50 +70,49 @@ class PermissionServiceImpl : public PermissionService {
};
using SubscriptionsMap = IDMap<PendingSubscription, IDMapOwnPointer>;
- // PermissionService.
- void HasPermission(PermissionName permission,
+ // blink::mojom::PermissionService.
+ void HasPermission(blink::mojom::PermissionName permission,
const mojo::String& origin,
const PermissionStatusCallback& callback) override;
- void RequestPermission(PermissionName permission,
+ void RequestPermission(blink::mojom::PermissionName permission,
const mojo::String& origin,
- bool user_gesture,
const PermissionStatusCallback& callback) override;
- void RequestPermissions(mojo::Array<PermissionName> permissions,
+ void RequestPermissions(mojo::Array<blink::mojom::PermissionName> permissions,
const mojo::String& origin,
- bool user_gesture,
const PermissionsStatusCallback& callback) override;
- void RevokePermission(PermissionName permission,
+ void RevokePermission(blink::mojom::PermissionName permission,
const mojo::String& origin,
const PermissionStatusCallback& callback) override;
void GetNextPermissionChange(
- PermissionName permission,
+ blink::mojom::PermissionName permission,
const mojo::String& origin,
- PermissionStatus last_known_status,
+ blink::mojom::PermissionStatus last_known_status,
const PermissionStatusCallback& callback) override;
void OnConnectionError();
- void OnRequestPermissionResponse(
- int pending_request_id,
- PermissionStatus status);
+ void OnRequestPermissionResponse(int pending_request_id,
+ blink::mojom::PermissionStatus status);
void OnRequestPermissionsResponse(
int pending_request_id,
- const std::vector<PermissionStatus>& result);
-
- PermissionStatus GetPermissionStatusFromName(PermissionName permission,
- const GURL& origin);
- PermissionStatus GetPermissionStatusFromType(PermissionType type,
- const GURL& origin);
+ const std::vector<blink::mojom::PermissionStatus>& result);
+
+ blink::mojom::PermissionStatus GetPermissionStatusFromName(
+ blink::mojom::PermissionName permission,
+ const GURL& origin);
+ blink::mojom::PermissionStatus GetPermissionStatusFromType(
+ PermissionType type,
+ const GURL& origin);
void ResetPermissionStatus(PermissionType type, const GURL& origin);
void OnPermissionStatusChanged(int pending_subscription_id,
- PermissionStatus status);
+ blink::mojom::PermissionStatus status);
RequestsMap pending_requests_;
SubscriptionsMap pending_subscriptions_;
// context_ owns |this|.
PermissionServiceContext* context_;
- mojo::Binding<PermissionService> binding_;
+ mojo::Binding<blink::mojom::PermissionService> binding_;
base::WeakPtrFactory<PermissionServiceImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(PermissionServiceImpl);
diff --git a/chromium/content/browser/plugin_data_remover_impl.cc b/chromium/content/browser/plugin_data_remover_impl.cc
index fa0aab250c0..5299f6bfaea 100644
--- a/chromium/content/browser/plugin_data_remover_impl.cc
+++ b/chromium/content/browser/plugin_data_remover_impl.cc
@@ -15,11 +15,9 @@
#include "base/synchronization/waitable_event.h"
#include "base/version.h"
#include "build/build_config.h"
-#include "content/browser/plugin_process_host.h"
#include "content/browser/plugin_service_impl.h"
#include "content/browser/renderer_host/pepper/pepper_flash_file_message_filter.h"
#include "content/common/child_process_host_impl.h"
-#include "content/common/plugin_process_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/child_process_host.h"
@@ -61,8 +59,7 @@ void PluginDataRemover::GetSupportedPlugins(
}
class PluginDataRemoverImpl::Context
- : public PluginProcessHost::Client,
- public PpapiPluginProcessHost::BrokerClient,
+ : public PpapiPluginProcessHost::BrokerClient,
public IPC::Listener,
public base::RefCountedThreadSafe<Context,
BrowserThread::DeleteOnIOThread> {
@@ -71,8 +68,7 @@ class PluginDataRemoverImpl::Context
: event_(new base::WaitableEvent(true, false)),
begin_time_(begin_time),
is_removing_(false),
- browser_context_path_(browser_context->GetPath()),
- resource_context_(browser_context->GetResourceContext()) {
+ browser_context_path_(browser_context->GetPath()) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
}
@@ -104,23 +100,22 @@ class PluginDataRemoverImpl::Context
base::FilePath plugin_path = plugins[0].path;
+ PepperPluginInfo* pepper_info =
+ plugin_service->GetRegisteredPpapiPluginInfo(plugin_path);
+ if (!pepper_info) {
+ event_->Signal();
+ return;
+ }
+
DCHECK_CURRENTLY_ON(BrowserThread::IO);
remove_start_time_ = base::Time::Now();
is_removing_ = true;
- // Balanced in On[Ppapi]ChannelOpened or OnError. Exactly one them will
- // eventually be called, so we need to keep this object around until then.
- AddRef();
- PepperPluginInfo* pepper_info =
- plugin_service->GetRegisteredPpapiPluginInfo(plugin_path);
- if (pepper_info) {
- plugin_name_ = pepper_info->name;
- // Use the broker since we run this function outside the sandbox.
- plugin_service->OpenChannelToPpapiBroker(0, plugin_path, this);
- } else {
- plugin_service->OpenChannelToNpapiPlugin(
- 0, 0, GURL(), GURL(), mime_type, this);
- }
+ // Balanced in OnPpapiChannelOpened.
+ AddRef();
+ plugin_name_ = pepper_info->name;
+ // Use the broker since we run this function outside the sandbox.
+ plugin_service->OpenChannelToPpapiBroker(0, plugin_path, this);
}
// Called when a timeout happens in order not to block the client
@@ -130,35 +125,8 @@ class PluginDataRemoverImpl::Context
SignalDone();
}
- // PluginProcessHost::Client methods.
- int ID() override {
- // Generate a unique identifier for this PluginProcessHostClient.
- return ChildProcessHostImpl::GenerateChildProcessUniqueId();
- }
-
bool OffTheRecord() override { return false; }
- ResourceContext* GetResourceContext() override { return resource_context_; }
-
- void SetPluginInfo(const WebPluginInfo& info) override {}
-
- void OnFoundPluginProcessHost(PluginProcessHost* host) override {}
-
- void OnSentPluginChannelRequest() override {}
-
- void OnChannelOpened(const IPC::ChannelHandle& handle) override {
- ConnectToChannel(handle, false);
- // Balancing the AddRef call.
- Release();
- }
-
- void OnError() override {
- LOG(ERROR) << "Couldn't open plugin channel";
- SignalDone();
- // Balancing the AddRef call.
- Release();
- }
-
// PpapiPluginProcessHost::BrokerClient implementation.
void GetPpapiChannelInfo(base::ProcessHandle* renderer_handle,
int* renderer_id) override {
@@ -170,7 +138,7 @@ class PluginDataRemoverImpl::Context
base::ProcessId /* peer_pid */,
int /* child_id */) override {
if (!channel_handle.name.empty())
- ConnectToChannel(channel_handle, true);
+ ConnectToChannel(channel_handle);
// Balancing the AddRef call.
Release();
@@ -179,8 +147,6 @@ class PluginDataRemoverImpl::Context
// IPC::Listener methods.
bool OnMessageReceived(const IPC::Message& message) override {
IPC_BEGIN_MESSAGE_MAP(Context, message)
- IPC_MESSAGE_HANDLER(PluginProcessHostMsg_ClearSiteDataResult,
- OnClearSiteDataResult)
IPC_MESSAGE_HANDLER(PpapiHostMsg_ClearSiteDataResult,
OnPpapiClearSiteDataResult)
IPC_MESSAGE_UNHANDLED_ERROR()
@@ -222,7 +188,7 @@ class PluginDataRemoverImpl::Context
}
// Connects the client side of a newly opened plugin channel.
- void ConnectToChannel(const IPC::ChannelHandle& handle, bool is_ppapi) {
+ void ConnectToChannel(const IPC::ChannelHandle& handle) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// If we timed out, don't bother connecting.
@@ -241,13 +207,7 @@ class PluginDataRemoverImpl::Context
? std::numeric_limits<uint64_t>::max()
: (base::Time::Now() - begin_time_).InSeconds();
- IPC::Message* msg;
- if (is_ppapi) {
- msg = CreatePpapiClearSiteDataMsg(max_age);
- } else {
- msg = new PluginProcessMsg_ClearSiteData(
- std::string(), kClearAllData, max_age);
- }
+ IPC::Message* msg = CreatePpapiClearSiteDataMsg(max_age);
if (!channel_->Send(msg)) {
NOTREACHED() << "Couldn't send ClearSiteData message";
SignalDone();
@@ -255,15 +215,9 @@ class PluginDataRemoverImpl::Context
}
}
- // Handles the PpapiHostMsg_ClearSiteDataResult message by delegating to the
- // PluginProcessHostMsg_ClearSiteDataResult handler.
+ // Handles the PpapiHostMsg_ClearSiteDataResult message.
void OnPpapiClearSiteDataResult(uint32_t request_id, bool success) {
DCHECK_EQ(0u, request_id);
- OnClearSiteDataResult(success);
- }
-
- // Handles the PluginProcessHostMsg_ClearSiteDataResult message.
- void OnClearSiteDataResult(bool success) {
LOG_IF(ERROR, !success) << "ClearSiteData returned error";
UMA_HISTOGRAM_TIMES("ClearPluginData.time",
base::Time::Now() - remove_start_time_);
@@ -291,9 +245,6 @@ class PluginDataRemoverImpl::Context
// browser context when we start so we can use it later on the I/O thread.
base::FilePath browser_context_path_;
- // The resource context for the profile. Use only on the I/O thread.
- ResourceContext* resource_context_;
-
// The name of the plugin. Use only on the I/O thread.
std::string plugin_name_;
diff --git a/chromium/content/browser/plugin_loader_posix.cc b/chromium/content/browser/plugin_loader_posix.cc
deleted file mode 100644
index dcfb55812ef..00000000000
--- a/chromium/content/browser/plugin_loader_posix.cc
+++ /dev/null
@@ -1,237 +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/plugin_loader_posix.h"
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/metrics/histogram.h"
-#include "base/single_thread_task_runner.h"
-#include "base/thread_task_runner_handle.h"
-#include "content/browser/utility_process_host_impl.h"
-#include "content/common/child_process_host_impl.h"
-#include "content/common/plugin_list.h"
-#include "content/common/utility_messages.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/plugin_service.h"
-#include "content/public/browser/user_metrics.h"
-
-namespace content {
-
-PluginLoaderPosix::PluginLoaderPosix()
- : next_load_index_(0), loading_plugins_(false) {
-}
-
-void PluginLoaderPosix::GetPlugins(
- const PluginService::GetPluginsCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- std::vector<WebPluginInfo> cached_plugins;
- if (PluginList::Singleton()->GetPluginsNoRefresh(&cached_plugins)) {
- // Can't assume the caller is reentrant.
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(callback, cached_plugins));
- return;
- }
-
- if (!loading_plugins_) {
- loading_plugins_ = true;
- callbacks_.push_back(callback);
-
- // When |loading_plugins_| is set to false, this instance must call
- // SetPlugins().
- PluginList::Singleton()->PrepareForPluginLoading();
-
- BrowserThread::PostTask(BrowserThread::FILE,
- FROM_HERE,
- base::Bind(&PluginLoaderPosix::GetPluginsToLoad,
- make_scoped_refptr(this)));
- } else {
- // If we are currently loading plugins, the plugin list might have been
- // invalidated in the mean time, or might get invalidated before we finish.
- // We'll wait until we have finished the current run, then try to get them
- // again from the plugin list. If it has indeed been invalidated, it will
- // restart plugin loading, otherwise it will immediately run the callback.
- callbacks_.push_back(base::Bind(&PluginLoaderPosix::GetPluginsWrapper,
- make_scoped_refptr(this), callback));
- }
-}
-
-bool PluginLoaderPosix::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(PluginLoaderPosix, message)
- IPC_MESSAGE_HANDLER(UtilityHostMsg_LoadedPlugin, OnPluginLoaded)
- IPC_MESSAGE_HANDLER(UtilityHostMsg_LoadPluginFailed, OnPluginLoadFailed)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void PluginLoaderPosix::OnProcessCrashed(int exit_code) {
- RecordAction(
- base::UserMetricsAction("PluginLoaderPosix.UtilityProcessCrashed"));
-
- if (next_load_index_ == canonical_list_.size()) {
- // How this case occurs is unknown. See crbug.com/111935.
- canonical_list_.clear();
- } else {
- canonical_list_.erase(canonical_list_.begin(),
- canonical_list_.begin() + next_load_index_ + 1);
- }
-
- next_load_index_ = 0;
-
- LoadPluginsInternal();
-}
-
-void PluginLoaderPosix::OnProcessLaunchFailed() {
- FinishedLoadingPlugins();
-}
-
-bool PluginLoaderPosix::Send(IPC::Message* message) {
- if (process_host_.get())
- return process_host_->Send(message);
- return false;
-}
-
-PluginLoaderPosix::~PluginLoaderPosix() {
-}
-
-void PluginLoaderPosix::GetPluginsToLoad() {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
-
- base::TimeTicks start_time(base::TimeTicks::Now());
-
- loaded_plugins_.clear();
- next_load_index_ = 0;
-
- canonical_list_.clear();
- PluginList::Singleton()->GetPluginPathsToLoad(
- &canonical_list_,
- PluginService::GetInstance()->NPAPIPluginsSupported());
-
- internal_plugins_.clear();
- PluginList::Singleton()->GetInternalPlugins(&internal_plugins_);
-
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&PluginLoaderPosix::LoadPluginsInternal,
- make_scoped_refptr(this)));
-
- LOCAL_HISTOGRAM_TIMES("PluginLoaderPosix.GetPluginList",
- (base::TimeTicks::Now() - start_time) *
- base::Time::kMicrosecondsPerMillisecond);
-}
-
-void PluginLoaderPosix::LoadPluginsInternal() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // Check if the list is empty or all plugins have already been loaded before
- // forking.
- if (IsFinishedLoadingPlugins()) {
- FinishedLoadingPlugins();
- return;
- }
-
- RecordAction(
- base::UserMetricsAction("PluginLoaderPosix.LaunchUtilityProcess"));
-
- UtilityProcessHostImpl* host = new UtilityProcessHostImpl(
- this,
- BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get());
- process_host_ = host->AsWeakPtr();
- process_host_->DisableSandbox();
-
- bool launched = LaunchUtilityProcess();
- if (!launched) {
- // The utility process either failed to start or failed to receive the IPC.
- // This process will never receive any callbacks for OnPluginLoaded() or
- // OnPluginLoadFailed().
- FinishedLoadingPlugins();
- }
-}
-
-void PluginLoaderPosix::GetPluginsWrapper(
- const PluginService::GetPluginsCallback& callback,
- const std::vector<WebPluginInfo>& plugins_unused) {
- // We are being called after plugin loading has finished, but we don't know
- // whether the plugin list has been invalidated in the mean time
- // (and therefore |plugins| might already be stale). So we simply ignore it
- // and call regular GetPlugins() instead.
- GetPlugins(callback);
-}
-
-void PluginLoaderPosix::OnPluginLoaded(uint32_t index,
- const WebPluginInfo& plugin) {
- if (index != next_load_index_) {
- LOG(ERROR) << "Received unexpected plugin load message for "
- << plugin.path.value() << "; index=" << index;
- return;
- }
-
- auto it = FindInternalPlugin(plugin.path);
- if (it != internal_plugins_.end()) {
- loaded_plugins_.push_back(*it);
- internal_plugins_.erase(it);
- } else {
- loaded_plugins_.push_back(plugin);
- }
-
- ++next_load_index_;
-
- if (IsFinishedLoadingPlugins())
- FinishedLoadingPlugins();
-}
-
-void PluginLoaderPosix::OnPluginLoadFailed(uint32_t index,
- const base::FilePath& plugin_path) {
- if (index != next_load_index_) {
- LOG(ERROR) << "Received unexpected plugin load failure message for "
- << plugin_path.value() << "; index=" << index;
- return;
- }
-
- ++next_load_index_;
-
- auto it = FindInternalPlugin(plugin_path);
- if (it != internal_plugins_.end()) {
- loaded_plugins_.push_back(*it);
- internal_plugins_.erase(it);
- }
-
- if (IsFinishedLoadingPlugins())
- FinishedLoadingPlugins();
-}
-
-std::vector<WebPluginInfo>::iterator PluginLoaderPosix::FindInternalPlugin(
- const base::FilePath& plugin_path) {
- return std::find_if(internal_plugins_.begin(), internal_plugins_.end(),
- [&plugin_path](const WebPluginInfo& plugin) {
- return plugin.path == plugin_path;
- });
-}
-
-bool PluginLoaderPosix::IsFinishedLoadingPlugins() {
- if (canonical_list_.empty())
- return true;
-
- DCHECK(next_load_index_ <= canonical_list_.size());
- return next_load_index_ == canonical_list_.size();
-}
-
-void PluginLoaderPosix::FinishedLoadingPlugins() {
- loading_plugins_ = false;
- PluginList::Singleton()->SetPlugins(loaded_plugins_);
-
- for (auto& callback : callbacks_) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(callback, loaded_plugins_));
- }
- callbacks_.clear();
-}
-
-bool PluginLoaderPosix::LaunchUtilityProcess() {
- return process_host_->Send(new UtilityMsg_LoadPlugins(canonical_list_));
-}
-
-} // namespace content
diff --git a/chromium/content/browser/plugin_loader_posix.h b/chromium/content/browser/plugin_loader_posix.h
deleted file mode 100644
index 51814131fcf..00000000000
--- a/chromium/content/browser/plugin_loader_posix.h
+++ /dev/null
@@ -1,134 +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_PLUGIN_LOADER_POSIX_H_
-#define CONTENT_BROWSER_PLUGIN_LOADER_POSIX_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/time/time.h"
-#include "content/browser/plugin_service_impl.h"
-#include "content/public/browser/utility_process_host_client.h"
-#include "content/public/common/webplugininfo.h"
-#include "ipc/ipc_sender.h"
-
-namespace content {
-class UtilityProcessHost;
-
-// This class is responsible for managing the out-of-process plugin loading on
-// POSIX systems. It primarily lives on the IO thread, but has a brief stay on
-// the FILE thread to iterate over plugin directories when it is first
-// constructed.
-//
-// The following is the algorithm used to load plugins:
-// 1. This asks the PluginList for the list of all potential plugins to attempt
-// to load. This is referred to as the canonical list.
-// 2. The child process this hosts is forked and the canonical list is sent to
-// it.
-// 3. The child process iterates over the canonical list, attempting to load
-// each plugin in the order specified by the list. It sends an IPC message
-// to the browser after each load, indicating success or failure. The two
-// processes synchronize the position in the vector that will be used to
-// attempt to load the next plugin.
-// 4. If the child dies during this process, the host forks another child and
-// resumes loading at the position past the plugin that it just attempted to
-// load, bypassing the problematic plugin.
-// 5. This algorithm continues until the canonical list has been walked to the
-// end, after which the list of loaded plugins is set on the PluginList and
-// the completion callback is run.
-class CONTENT_EXPORT PluginLoaderPosix
- : public NON_EXPORTED_BASE(UtilityProcessHostClient),
- public IPC::Sender {
- public:
- PluginLoaderPosix();
-
- // Must be called from the IO thread. The |callback| will be called on the IO
- // thread too.
- void GetPlugins(const PluginService::GetPluginsCallback& callback);
-
- // UtilityProcessHostClient:
- void OnProcessCrashed(int exit_code) override;
- void OnProcessLaunchFailed() override;
- bool OnMessageReceived(const IPC::Message& message) override;
-
- // IPC::Sender:
- bool Send(IPC::Message* msg) override;
-
- private:
- ~PluginLoaderPosix() override;
-
- // Called on the FILE thread to get the list of plugin paths to probe.
- void GetPluginsToLoad();
-
- // Must be called on the IO thread.
- virtual void LoadPluginsInternal();
-
- // Called after plugin loading has finished, if we don't know whether the
- // plugin list has been invalidated in the mean time.
- void GetPluginsWrapper(
- const PluginService::GetPluginsCallback& callback,
- const std::vector<WebPluginInfo>& plugins_unused);
-
- // Message handlers.
- void OnPluginLoaded(uint32_t index, const WebPluginInfo& plugin);
- void OnPluginLoadFailed(uint32_t index, const base::FilePath& plugin_path);
-
- // Returns an iterator to the plugin in |internal_plugins_| whose path
- // matches |plugin_path|.
- std::vector<WebPluginInfo>::iterator FindInternalPlugin(
- const base::FilePath& plugin_path);
-
- // Runs all the registered callbacks on each's target loop if the condition
- // for ending the load process is done (i.e. the |next_load_index_| is outside
- // the range of the |canonical_list_|).
- bool MaybeRunPendingCallbacks();
-
- // Returns true if there are no plugins left to load.
- bool IsFinishedLoadingPlugins();
-
- // This method should be called when the plugins are finished loading.
- // It updates the PluginList's list of plugins, and runs the queued callbacks.
- void FinishedLoadingPlugins();
-
- // Launches the utility process that loads the plugins.
- // Virtual for testing.
- virtual bool LaunchUtilityProcess();
-
- // The process host for which this is a client.
- base::WeakPtr<UtilityProcessHost> process_host_;
-
- // A list of paths to plugins which will be loaded by the utility process, in
- // the order specified by this vector.
- std::vector<base::FilePath> canonical_list_;
-
- // The index in |canonical_list_| of the plugin that the child process will
- // attempt to load next.
- size_t next_load_index_;
-
- // Internal plugins that have been registered at the time of loading.
- std::vector<WebPluginInfo> internal_plugins_;
-
- // A vector of plugins that have been loaded successfully.
- std::vector<WebPluginInfo> loaded_plugins_;
-
- // The callback and message loop on which the callback will be run when the
- // plugin loading process has been completed.
- std::vector<PluginService::GetPluginsCallback> callbacks_;
-
- // True if there is (or is about to be) a utility process that loads plugins.
- bool loading_plugins_;
-
- friend class MockPluginLoaderPosix;
- DISALLOW_COPY_AND_ASSIGN(PluginLoaderPosix);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_PLUGIN_LOADER_POSIX_H_
diff --git a/chromium/content/browser/plugin_loader_posix_unittest.cc b/chromium/content/browser/plugin_loader_posix_unittest.cc
deleted file mode 100644
index ec1fa0b51f7..00000000000
--- a/chromium/content/browser/plugin_loader_posix_unittest.cc
+++ /dev/null
@@ -1,426 +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/plugin_loader_posix.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "base/at_exit.h"
-#include "base/bind.h"
-#include "base/files/file_path.h"
-#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/browser/browser_thread_impl.h"
-#include "content/common/plugin_list.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using base::ASCIIToUTF16;
-
-namespace content {
-
-class MockPluginLoaderPosix : public PluginLoaderPosix {
- public:
- MOCK_METHOD0(LoadPluginsInternal, void(void));
-
- size_t number_of_pending_callbacks() {
- return callbacks_.size();
- }
-
- std::vector<base::FilePath>* canonical_list() {
- return &canonical_list_;
- }
-
- size_t next_load_index() {
- return next_load_index_;
- }
-
- const std::vector<WebPluginInfo>& loaded_plugins() {
- return loaded_plugins_;
- }
-
- std::vector<WebPluginInfo>* internal_plugins() {
- return &internal_plugins_;
- }
-
- void RealLoadPluginsInternal() {
- PluginLoaderPosix::LoadPluginsInternal();
- }
-
- bool LaunchUtilityProcess() override {
- // This method always does nothing and returns false. The actual
- // implementation of this method launches another process, which is not
- // very unit_test friendly.
- return false;
- }
-
- void TestOnPluginLoaded(uint32_t index, const WebPluginInfo& plugin) {
- OnPluginLoaded(index, plugin);
- }
-
- void TestOnPluginLoadFailed(uint32_t index, const base::FilePath& path) {
- OnPluginLoadFailed(index, path);
- }
-
- protected:
- virtual ~MockPluginLoaderPosix() {}
-};
-
-void VerifyCallback(int* run_count, const std::vector<WebPluginInfo>&) {
- ++(*run_count);
-}
-
-class PluginLoaderPosixTest : public testing::Test {
- public:
- PluginLoaderPosixTest()
- : plugin1_(ASCIIToUTF16("plugin1"), base::FilePath("/tmp/one.plugin"),
- ASCIIToUTF16("1.0"), base::string16()),
- plugin2_(ASCIIToUTF16("plugin2"), base::FilePath("/tmp/two.plugin"),
- ASCIIToUTF16("2.0"), base::string16()),
- plugin3_(ASCIIToUTF16("plugin3"), base::FilePath("/tmp/three.plugin"),
- ASCIIToUTF16("3.0"), base::string16()),
- file_thread_(BrowserThread::FILE, &message_loop_),
- io_thread_(BrowserThread::IO, &message_loop_),
- plugin_loader_(new MockPluginLoaderPosix) {
- }
-
- void SetUp() override { PluginServiceImpl::GetInstance()->Init(); }
-
- base::MessageLoop* message_loop() { return &message_loop_; }
- MockPluginLoaderPosix* plugin_loader() { return plugin_loader_.get(); }
-
- void AddThreePlugins() {
- plugin_loader_->canonical_list()->clear();
- plugin_loader_->canonical_list()->push_back(plugin1_.path);
- plugin_loader_->canonical_list()->push_back(plugin2_.path);
- plugin_loader_->canonical_list()->push_back(plugin3_.path);
- }
-
- // Data used for testing.
- WebPluginInfo plugin1_;
- WebPluginInfo plugin2_;
- WebPluginInfo plugin3_;
-
- private:
- // Destroys PluginService and PluginList.
- base::ShadowingAtExitManager at_exit_manager_;
-
- base::MessageLoopForIO message_loop_;
- BrowserThreadImpl file_thread_;
- BrowserThreadImpl io_thread_;
-
- scoped_refptr<MockPluginLoaderPosix> plugin_loader_;
-};
-
-TEST_F(PluginLoaderPosixTest, QueueRequests) {
- int did_callback = 0;
- PluginService::GetPluginsCallback callback =
- base::Bind(&VerifyCallback, base::Unretained(&did_callback));
-
- plugin_loader()->GetPlugins(callback);
- plugin_loader()->GetPlugins(callback);
-
- EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1);
- message_loop()->RunUntilIdle();
-
- EXPECT_EQ(0, did_callback);
-
- plugin_loader()->canonical_list()->clear();
- plugin_loader()->canonical_list()->push_back(plugin1_.path);
- plugin_loader()->TestOnPluginLoaded(0, plugin1_);
- message_loop()->RunUntilIdle();
-
- EXPECT_EQ(2, did_callback);
-}
-
-TEST_F(PluginLoaderPosixTest, QueueRequestsAndInvalidate) {
- int did_callback = 0;
- PluginService::GetPluginsCallback callback =
- base::Bind(&VerifyCallback, base::Unretained(&did_callback));
-
- plugin_loader()->GetPlugins(callback);
-
- EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1);
- message_loop()->RunUntilIdle();
-
- EXPECT_EQ(0, did_callback);
- ::testing::Mock::VerifyAndClearExpectations(plugin_loader());
-
- // Invalidate the plugin list, then queue up another request.
- PluginList::Singleton()->RefreshPlugins();
- plugin_loader()->GetPlugins(callback);
-
- EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1);
-
- plugin_loader()->canonical_list()->clear();
- plugin_loader()->canonical_list()->push_back(plugin1_.path);
- plugin_loader()->TestOnPluginLoaded(0, plugin1_);
- message_loop()->RunUntilIdle();
-
- // Only the first request should have been fulfilled.
- EXPECT_EQ(1, did_callback);
-
- plugin_loader()->canonical_list()->clear();
- plugin_loader()->canonical_list()->push_back(plugin1_.path);
- plugin_loader()->TestOnPluginLoaded(0, plugin1_);
- message_loop()->RunUntilIdle();
-
- EXPECT_EQ(2, did_callback);
-}
-
-TEST_F(PluginLoaderPosixTest, ThreeSuccessfulLoads) {
- int did_callback = 0;
- PluginService::GetPluginsCallback callback =
- base::Bind(&VerifyCallback, base::Unretained(&did_callback));
-
- plugin_loader()->GetPlugins(callback);
-
- EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1);
- message_loop()->RunUntilIdle();
-
- AddThreePlugins();
-
- EXPECT_EQ(0u, plugin_loader()->next_load_index());
-
- const std::vector<WebPluginInfo>& plugins(plugin_loader()->loaded_plugins());
-
- plugin_loader()->TestOnPluginLoaded(0, plugin1_);
- EXPECT_EQ(1u, plugin_loader()->next_load_index());
- EXPECT_EQ(1u, plugins.size());
- EXPECT_EQ(plugin1_.name, plugins[0].name);
-
- message_loop()->RunUntilIdle();
- EXPECT_EQ(0, did_callback);
-
- plugin_loader()->TestOnPluginLoaded(1, plugin2_);
- EXPECT_EQ(2u, plugin_loader()->next_load_index());
- EXPECT_EQ(2u, plugins.size());
- EXPECT_EQ(plugin2_.name, plugins[1].name);
-
- message_loop()->RunUntilIdle();
- EXPECT_EQ(0, did_callback);
-
- plugin_loader()->TestOnPluginLoaded(2, plugin3_);
- EXPECT_EQ(3u, plugins.size());
- EXPECT_EQ(plugin3_.name, plugins[2].name);
-
- message_loop()->RunUntilIdle();
- EXPECT_EQ(1, did_callback);
-}
-
-TEST_F(PluginLoaderPosixTest, ThreeSuccessfulLoadsThenCrash) {
- int did_callback = 0;
- PluginService::GetPluginsCallback callback =
- base::Bind(&VerifyCallback, base::Unretained(&did_callback));
-
- plugin_loader()->GetPlugins(callback);
-
- EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(2);
- message_loop()->RunUntilIdle();
-
- AddThreePlugins();
-
- EXPECT_EQ(0u, plugin_loader()->next_load_index());
-
- const std::vector<WebPluginInfo>& plugins(plugin_loader()->loaded_plugins());
-
- plugin_loader()->TestOnPluginLoaded(0, plugin1_);
- EXPECT_EQ(1u, plugin_loader()->next_load_index());
- EXPECT_EQ(1u, plugins.size());
- EXPECT_EQ(plugin1_.name, plugins[0].name);
-
- message_loop()->RunUntilIdle();
- EXPECT_EQ(0, did_callback);
-
- plugin_loader()->TestOnPluginLoaded(1, plugin2_);
- EXPECT_EQ(2u, plugin_loader()->next_load_index());
- EXPECT_EQ(2u, plugins.size());
- EXPECT_EQ(plugin2_.name, plugins[1].name);
-
- message_loop()->RunUntilIdle();
- EXPECT_EQ(0, did_callback);
-
- plugin_loader()->TestOnPluginLoaded(2, plugin3_);
- EXPECT_EQ(3u, plugins.size());
- EXPECT_EQ(plugin3_.name, plugins[2].name);
-
- message_loop()->RunUntilIdle();
- EXPECT_EQ(1, did_callback);
-
- plugin_loader()->OnProcessCrashed(42);
-}
-
-TEST_F(PluginLoaderPosixTest, TwoFailures) {
- int did_callback = 0;
- PluginService::GetPluginsCallback callback =
- base::Bind(&VerifyCallback, base::Unretained(&did_callback));
-
- plugin_loader()->GetPlugins(callback);
-
- EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1);
- message_loop()->RunUntilIdle();
-
- AddThreePlugins();
-
- EXPECT_EQ(0u, plugin_loader()->next_load_index());
-
- const std::vector<WebPluginInfo>& plugins(plugin_loader()->loaded_plugins());
-
- plugin_loader()->TestOnPluginLoadFailed(0, plugin1_.path);
- EXPECT_EQ(1u, plugin_loader()->next_load_index());
- EXPECT_EQ(0u, plugins.size());
-
- message_loop()->RunUntilIdle();
- EXPECT_EQ(0, did_callback);
-
- plugin_loader()->TestOnPluginLoaded(1, plugin2_);
- EXPECT_EQ(2u, plugin_loader()->next_load_index());
- EXPECT_EQ(1u, plugins.size());
- EXPECT_EQ(plugin2_.name, plugins[0].name);
-
- message_loop()->RunUntilIdle();
- EXPECT_EQ(0, did_callback);
-
- plugin_loader()->TestOnPluginLoadFailed(2, plugin3_.path);
- EXPECT_EQ(1u, plugins.size());
-
- message_loop()->RunUntilIdle();
- EXPECT_EQ(1, did_callback);
-}
-
-TEST_F(PluginLoaderPosixTest, CrashedProcess) {
- int did_callback = 0;
- PluginService::GetPluginsCallback callback =
- base::Bind(&VerifyCallback, base::Unretained(&did_callback));
-
- plugin_loader()->GetPlugins(callback);
-
- EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1);
- message_loop()->RunUntilIdle();
-
- AddThreePlugins();
-
- EXPECT_EQ(0u, plugin_loader()->next_load_index());
-
- const std::vector<WebPluginInfo>& plugins(plugin_loader()->loaded_plugins());
-
- plugin_loader()->TestOnPluginLoaded(0, plugin1_);
- EXPECT_EQ(1u, plugin_loader()->next_load_index());
- EXPECT_EQ(1u, plugins.size());
- EXPECT_EQ(plugin1_.name, plugins[0].name);
-
- message_loop()->RunUntilIdle();
- EXPECT_EQ(0, did_callback);
-
- EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1);
- plugin_loader()->OnProcessCrashed(42);
- EXPECT_EQ(1u, plugin_loader()->canonical_list()->size());
- EXPECT_EQ(0u, plugin_loader()->next_load_index());
- EXPECT_EQ(plugin3_.path.value(),
- plugin_loader()->canonical_list()->at(0).value());
-}
-
-TEST_F(PluginLoaderPosixTest, InternalPlugin) {
- int did_callback = 0;
- PluginService::GetPluginsCallback callback =
- base::Bind(&VerifyCallback, base::Unretained(&did_callback));
-
- plugin_loader()->GetPlugins(callback);
-
- EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1);
- message_loop()->RunUntilIdle();
-
- plugin2_.path = base::FilePath("/internal/plugin.plugin");
-
- AddThreePlugins();
-
- plugin_loader()->internal_plugins()->clear();
- plugin_loader()->internal_plugins()->push_back(plugin2_);
-
- EXPECT_EQ(0u, plugin_loader()->next_load_index());
-
- const std::vector<WebPluginInfo>& plugins(plugin_loader()->loaded_plugins());
-
- plugin_loader()->TestOnPluginLoaded(0, plugin1_);
- EXPECT_EQ(1u, plugin_loader()->next_load_index());
- EXPECT_EQ(1u, plugins.size());
- EXPECT_EQ(plugin1_.name, plugins[0].name);
-
- message_loop()->RunUntilIdle();
- EXPECT_EQ(0, did_callback);
-
- // Internal plugins can fail to load if they're built-in with manual
- // entrypoint functions.
- plugin_loader()->TestOnPluginLoadFailed(1, plugin2_.path);
- EXPECT_EQ(2u, plugin_loader()->next_load_index());
- EXPECT_EQ(2u, plugins.size());
- EXPECT_EQ(plugin2_.name, plugins[1].name);
- EXPECT_EQ(0u, plugin_loader()->internal_plugins()->size());
-
- message_loop()->RunUntilIdle();
- EXPECT_EQ(0, did_callback);
-
- plugin_loader()->TestOnPluginLoaded(2, plugin3_);
- EXPECT_EQ(3u, plugins.size());
- EXPECT_EQ(plugin3_.name, plugins[2].name);
-
- message_loop()->RunUntilIdle();
- EXPECT_EQ(1, did_callback);
-}
-
-TEST_F(PluginLoaderPosixTest, AllCrashed) {
- int did_callback = 0;
- PluginService::GetPluginsCallback callback =
- base::Bind(&VerifyCallback, base::Unretained(&did_callback));
-
- plugin_loader()->GetPlugins(callback);
-
- // Spin the loop so that the canonical list of plugins can be set.
- EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(1);
- message_loop()->RunUntilIdle();
- AddThreePlugins();
-
- EXPECT_EQ(0u, plugin_loader()->next_load_index());
-
- // Mock the first two calls like normal.
- testing::Expectation first =
- EXPECT_CALL(*plugin_loader(), LoadPluginsInternal()).Times(2);
- // On the last call, go through the default impl.
- EXPECT_CALL(*plugin_loader(), LoadPluginsInternal())
- .After(first)
- .WillOnce(
- testing::Invoke(plugin_loader(),
- &MockPluginLoaderPosix::RealLoadPluginsInternal));
- plugin_loader()->OnProcessCrashed(42);
- plugin_loader()->OnProcessCrashed(42);
- plugin_loader()->OnProcessCrashed(42);
-
- message_loop()->RunUntilIdle();
- EXPECT_EQ(1, did_callback);
-
- EXPECT_EQ(0u, plugin_loader()->loaded_plugins().size());
-}
-
-TEST_F(PluginLoaderPosixTest, PluginLaunchFailed) {
- int did_callback = 0;
- PluginService::GetPluginsCallback callback =
- base::Bind(&VerifyCallback, base::Unretained(&did_callback));
-
- EXPECT_CALL(*plugin_loader(), LoadPluginsInternal())
- .WillOnce(testing::Invoke(
- plugin_loader(), &MockPluginLoaderPosix::RealLoadPluginsInternal));
-
- plugin_loader()->GetPlugins(callback);
- message_loop()->RunUntilIdle();
- EXPECT_EQ(1, did_callback);
- EXPECT_EQ(0u, plugin_loader()->loaded_plugins().size());
-
- // TODO(erikchen): This is a genuine leak that should be fixed.
- // https://code.google.com/p/chromium/issues/detail?id=431906
- testing::Mock::AllowLeak(plugin_loader());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/plugin_process_host.cc b/chromium/content/browser/plugin_process_host.cc
deleted file mode 100644
index cb14fa7b669..00000000000
--- a/chromium/content/browser/plugin_process_host.cc
+++ /dev/null
@@ -1,442 +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/plugin_process_host.h"
-
-#include <stddef.h>
-
-#include <utility>
-#include <vector>
-
-#include "base/base_switches.h"
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/files/file_path.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/metrics/histogram.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/synchronization/lock.h"
-#include "build/build_config.h"
-#include "components/tracing/tracing_switches.h"
-#include "content/browser/browser_child_process_host_impl.h"
-#include "content/browser/gpu/gpu_data_manager_impl.h"
-#include "content/browser/loader/resource_message_filter.h"
-#include "content/browser/plugin_service_impl.h"
-#include "content/common/child_process_host_impl.h"
-#include "content/common/plugin_process_messages.h"
-#include "content/common/resource_messages.h"
-#include "content/public/browser/browser_thread.h"
-#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 "content/public/common/sandboxed_process_launcher_delegate.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/gfx/switches.h"
-#include "ui/gl/gl_switches.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-
-#if defined(OS_MACOSX)
-#include "base/mac/mac_util.h"
-#include "ui/gfx/geometry/rect.h"
-#endif
-
-#if defined(OS_WIN)
-#include "base/win/windows_version.h"
-#include "content/common/plugin_constants_win.h"
-#endif
-
-namespace content {
-
-namespace {
-
-base::LazyInstance<std::map<base::ProcessId, WebPluginInfo> >
- g_process_webplugin_info = LAZY_INSTANCE_INITIALIZER;
-base::LazyInstance<base::Lock>::Leaky
- g_process_webplugin_info_lock = LAZY_INSTANCE_INITIALIZER;
-}
-
-bool PluginProcessHost::GetWebPluginInfoFromPluginPid(base::ProcessId pid,
- WebPluginInfo* info) {
- base::AutoLock lock(g_process_webplugin_info_lock.Get());
- if (!g_process_webplugin_info.Get().count(pid))
- return false;
-
- *info = g_process_webplugin_info.Get()[pid];
- return true;
-}
-
-#if defined(OS_WIN)
-void PluginProcessHost::OnPluginWindowDestroyed(HWND window, HWND parent) {
- // The window is destroyed at this point, we just care about its parent, which
- // is the intermediate window we created.
- std::set<HWND>::iterator window_index =
- plugin_parent_windows_set_.find(parent);
- if (window_index == plugin_parent_windows_set_.end())
- return;
-
- plugin_parent_windows_set_.erase(window_index);
- PostMessage(parent, WM_CLOSE, 0, 0);
-}
-
-void PluginProcessHost::AddWindow(HWND window) {
- plugin_parent_windows_set_.insert(window);
-}
-#endif // defined(OS_WIN)
-
-// NOTE: changes to this class need to be reviewed by the security team.
-class PluginSandboxedProcessLauncherDelegate
- : public SandboxedProcessLauncherDelegate {
- public:
- explicit PluginSandboxedProcessLauncherDelegate(ChildProcessHost* host)
-#if defined(OS_POSIX)
- : ipc_fd_(host->TakeClientFileDescriptor())
-#endif // OS_POSIX
- {}
-
- ~PluginSandboxedProcessLauncherDelegate() override {}
-
-#if defined(OS_WIN)
- bool ShouldSandbox() override {
- return false;
- }
-
-#elif defined(OS_POSIX)
- base::ScopedFD TakeIpcFd() override { return std::move(ipc_fd_); }
-#endif // OS_WIN
-
- private:
-#if defined(OS_POSIX)
- base::ScopedFD ipc_fd_;
-#endif // OS_POSIX
-
- DISALLOW_COPY_AND_ASSIGN(PluginSandboxedProcessLauncherDelegate);
-};
-
-PluginProcessHost::PluginProcessHost()
- : pid_(base::kNullProcessId)
-#if defined(OS_MACOSX)
- , plugin_cursor_visible_(true)
-#endif
-{
- process_.reset(new BrowserChildProcessHostImpl(PROCESS_TYPE_PLUGIN, this));
-}
-
-PluginProcessHost::~PluginProcessHost() {
-#if defined(OS_WIN)
- // We erase HWNDs from the plugin_parent_windows_set_ when we receive a
- // notification that the window is being destroyed. If we don't receive this
- // notification and the PluginProcessHost instance is being destroyed, it
- // means that the plugin process crashed. We paint a sad face in this case in
- // the renderer process. To ensure that the sad face shows up, and we don't
- // leak HWNDs, we should destroy existing plugin parent windows.
- std::set<HWND>::iterator window_index;
- for (window_index = plugin_parent_windows_set_.begin();
- window_index != plugin_parent_windows_set_.end();
- ++window_index) {
- PostMessage(*window_index, WM_CLOSE, 0, 0);
- }
-#elif defined(OS_MACOSX)
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // If the plugin process crashed but had fullscreen windows open at the time,
- // make sure that the menu bar is visible.
- for (size_t i = 0; i < plugin_fullscreen_windows_set_.size(); ++i) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(base::mac::ReleaseFullScreen,
- base::mac::kFullScreenModeHideAll));
- }
- // If the plugin hid the cursor, reset that.
- if (!plugin_cursor_visible_) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(base::mac::SetCursorVisibility, true));
- }
-#endif
- // Cancel all pending and sent requests.
- CancelRequests();
-
- {
- base::AutoLock lock(g_process_webplugin_info_lock.Get());
- g_process_webplugin_info.Get()[pid_] = info_;
- }
-}
-
-bool PluginProcessHost::Send(IPC::Message* message) {
- return process_->Send(message);
-}
-
-bool PluginProcessHost::Init(const WebPluginInfo& info) {
- info_ = info;
- process_->SetName(info_.name);
-
- std::string channel_id = process_->GetHost()->CreateChannel();
- if (channel_id.empty())
- return false;
-
- // Build command line for plugin. When we have a plugin launcher, we can't
- // allow "self" on linux and we need the real file path.
- const base::CommandLine& browser_command_line =
- *base::CommandLine::ForCurrentProcess();
- base::CommandLine::StringType plugin_launcher =
- browser_command_line.GetSwitchValueNative(switches::kPluginLauncher);
-
-#if defined(OS_LINUX)
- int flags = plugin_launcher.empty() ? ChildProcessHost::CHILD_ALLOW_SELF :
- ChildProcessHost::CHILD_NORMAL;
-#else
- int flags = ChildProcessHost::CHILD_NORMAL;
-#endif
-
- base::FilePath exe_path = ChildProcessHost::GetChildPath(flags);
- if (exe_path.empty())
- return false;
-
- base::CommandLine* cmd_line = new base::CommandLine(exe_path);
- // Put the process type and plugin path first so they're easier to see
- // in process listings using native process management tools.
- cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kPluginProcess);
- cmd_line->AppendSwitchPath(switches::kPluginPath, info.path);
-
-#if defined(OS_WIN)
- if (GetContentClient()->browser()->ShouldUseWindowsPrefetchArgument())
- cmd_line->AppendArg(switches::kPrefetchArgumentOther);
-#endif // defined(OS_WIN)
-
- // Propagate the following switches to the plugin command line (along with
- // any associated values) if present in the browser command line
- static const char* const kSwitchNames[] = {
- switches::kDisableBreakpad,
- switches::kDisableDirectNPAPIRequests,
- switches::kEnableStatsTable,
- switches::kFullMemoryCrashReport,
- switches::kLoggingLevel,
- switches::kLogPluginMessages,
- switches::kNoSandbox,
- switches::kPluginStartupDialog,
- switches::kTraceConfigFile,
- switches::kTraceStartup,
- switches::kUseGL,
- switches::kForceDeviceScaleFactor,
-#if defined(OS_MACOSX)
- switches::kDisableCoreAnimationPlugins,
- switches::kEnableSandboxLogging,
-#endif
- };
-
- cmd_line->CopySwitchesFrom(browser_command_line, kSwitchNames,
- arraysize(kSwitchNames));
-
- GpuDataManagerImpl::GetInstance()->AppendPluginCommandLine(cmd_line);
-
- // If specified, prepend a launcher program to the command line.
- if (!plugin_launcher.empty())
- cmd_line->PrependWrapper(plugin_launcher);
-
- std::string locale = GetContentClient()->browser()->GetApplicationLocale();
- if (!locale.empty()) {
- // Pass on the locale so the null plugin will use the right language in the
- // prompt to install the desired plugin.
- cmd_line->AppendSwitchASCII(switches::kLang, locale);
- }
-
- cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);
-
- // The plugin needs to be shutdown gracefully, i.e. NP_Shutdown needs to be
- // called on the plugin. The plugin process exits when it receives the
- // OnChannelError notification indicating that the browser plugin channel has
- // been destroyed.
- bool terminate_on_shutdown = false;
- process_->Launch(
- new PluginSandboxedProcessLauncherDelegate(process_->GetHost()),
- cmd_line,
- terminate_on_shutdown);
-
- ResourceMessageFilter::GetContextsCallback get_contexts_callback(
- base::Bind(&PluginProcessHost::GetContexts,
- base::Unretained(this)));
-
- // TODO(jam): right now we're passing NULL for appcache, blob storage, file
- // system and host zoom level context. 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, NULL, NULL,
- get_contexts_callback);
- process_->AddFilter(resource_message_filter);
- return true;
-}
-
-void PluginProcessHost::ForceShutdown() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- Send(new PluginProcessMsg_NotifyRenderersOfPendingShutdown());
- process_->ForceShutdown();
-}
-
-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)
-#endif
-#if defined(OS_MACOSX)
- IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginShowWindow,
- OnPluginShowWindow)
- IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginHideWindow,
- OnPluginHideWindow)
- IPC_MESSAGE_HANDLER(PluginProcessHostMsg_PluginSetCursorVisibility,
- OnPluginSetCursorVisibility)
-#endif
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
-
- return handled;
-}
-
-void PluginProcessHost::OnChannelConnected(int32_t peer_pid) {
- for (size_t i = 0; i < pending_requests_.size(); ++i) {
- RequestPluginChannel(pending_requests_[i]);
- }
-
- pending_requests_.clear();
-
- pid_ = peer_pid;
- {
- base::AutoLock lock(g_process_webplugin_info_lock.Get());
- g_process_webplugin_info.Get()[pid_] = info_;
- }
-}
-
-void PluginProcessHost::OnChannelError() {
- CancelRequests();
-}
-
-bool PluginProcessHost::CanShutdown() {
- return sent_requests_.empty();
-}
-
-void PluginProcessHost::OnProcessCrashed(int exit_code) {
- PluginServiceImpl::GetInstance()->RegisterPluginCrash(info_.path);
-}
-
-void PluginProcessHost::CancelRequests() {
- for (size_t i = 0; i < pending_requests_.size(); ++i)
- pending_requests_[i]->OnError();
- pending_requests_.clear();
-
- while (!sent_requests_.empty()) {
- Client* client = sent_requests_.front();
- if (client)
- client->OnError();
- sent_requests_.pop_front();
- }
-}
-
-void PluginProcessHost::OpenChannelToPlugin(Client* client) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&BrowserChildProcessHostImpl::NotifyProcessInstanceCreated,
- process_->GetData()));
- client->SetPluginInfo(info_);
- if (process_->GetHost()->IsChannelOpening()) {
- // The channel is already in the process of being opened. Put
- // this "open channel" request into a queue of requests that will
- // be run once the channel is open.
- pending_requests_.push_back(client);
- return;
- }
-
- // We already have an open channel, send a request right away to plugin.
- RequestPluginChannel(client);
-}
-
-void PluginProcessHost::CancelPendingRequest(Client* client) {
- std::vector<Client*>::iterator it = pending_requests_.begin();
- while (it != pending_requests_.end()) {
- if (client == *it) {
- pending_requests_.erase(it);
- return;
- }
- ++it;
- }
- DCHECK(it != pending_requests_.end());
-}
-
-void PluginProcessHost::CancelSentRequest(Client* client) {
- std::list<Client*>::iterator it = sent_requests_.begin();
- while (it != sent_requests_.end()) {
- if (client == *it) {
- *it = NULL;
- return;
- }
- ++it;
- }
- DCHECK(it != sent_requests_.end());
-}
-
-void PluginProcessHost::RequestPluginChannel(Client* client) {
- // We can't send any sync messages from the browser because it might lead to
- // a hang. However this async messages must be answered right away by the
- // plugin process (i.e. unblocks a Send() call like a sync message) otherwise
- // a deadlock can occur if the plugin creation request from the renderer is
- // a result of a sync message by the plugin process.
- PluginProcessMsg_CreateChannel* msg =
- new PluginProcessMsg_CreateChannel(
- client->ID(),
- client->OffTheRecord());
- msg->set_unblock(true);
- if (Send(msg)) {
- sent_requests_.push_back(client);
- client->OnSentPluginChannelRequest();
- } else {
- client->OnError();
- }
-}
-
-void PluginProcessHost::OnChannelCreated(
- const IPC::ChannelHandle& channel_handle) {
- Client* client = sent_requests_.front();
-
- if (client) {
- if (!resource_context_map_.count(client->ID())) {
- ResourceContextEntry entry;
- entry.ref_count = 0;
- entry.resource_context = client->GetResourceContext();
- resource_context_map_[client->ID()] = entry;
- }
- resource_context_map_[client->ID()].ref_count++;
- client->OnChannelOpened(channel_handle);
- }
- sent_requests_.pop_front();
-}
-
-void PluginProcessHost::OnChannelDestroyed(int renderer_id) {
- resource_context_map_[renderer_id].ref_count--;
- if (!resource_context_map_[renderer_id].ref_count)
- resource_context_map_.erase(renderer_id);
-}
-
-void PluginProcessHost::GetContexts(ResourceType resource_type,
- int origin_pid,
- ResourceContext** resource_context,
- net::URLRequestContext** request_context) {
- *resource_context =
- resource_context_map_[origin_pid].resource_context;
- *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
deleted file mode 100644
index 66ec73dfd8d..00000000000
--- a/chromium/content/browser/plugin_process_host.h
+++ /dev/null
@@ -1,219 +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_PLUGIN_PROCESS_HOST_H_
-#define CONTENT_BROWSER_PLUGIN_PROCESS_HOST_H_
-
-#include "build/build_config.h"
-
-#include <stdint.h>
-
-#include <list>
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/process/process_handle.h"
-#include "content/common/content_export.h"
-#include "content/public/browser/browser_child_process_host_delegate.h"
-#include "content/public/browser/browser_child_process_host_iterator.h"
-#include "content/public/common/process_type.h"
-#include "content/public/common/resource_type.h"
-#include "content/public/common/webplugininfo.h"
-#include "ipc/ipc_channel_proxy.h"
-#include "ui/gfx/native_widget_types.h"
-
-struct ResourceHostMsg_Request;
-
-namespace gfx {
-class Rect;
-}
-
-namespace IPC {
-struct ChannelHandle;
-}
-
-namespace net {
-class URLRequestContext;
-}
-
-namespace content {
-class BrowserChildProcessHostImpl;
-class ResourceContext;
-
-// Represents the browser side of the browser <--> plugin communication
-// channel. Different plugins run in their own process, but multiple instances
-// of the same plugin run in the same process. There will be one
-// PluginProcessHost per plugin process, matched with a corresponding
-// PluginProcess running in the plugin process. The browser is responsible for
-// starting the plugin process when a plugin is created that doesn't already
-// have a process. After that, most of the communication is directly between
-// the renderer and plugin processes.
-class CONTENT_EXPORT PluginProcessHost : public BrowserChildProcessHostDelegate,
- public IPC::Sender {
- public:
- class Client {
- public:
- // Returns an opaque unique identifier for the process requesting
- // the channel.
- virtual int ID() = 0;
- // Returns the resource context for the renderer requesting the channel.
- virtual ResourceContext* GetResourceContext() = 0;
- virtual bool OffTheRecord() = 0;
- virtual void SetPluginInfo(const WebPluginInfo& info) = 0;
- virtual void OnFoundPluginProcessHost(PluginProcessHost* host) = 0;
- virtual void OnSentPluginChannelRequest() = 0;
- // The client should delete itself when one of these methods is called.
- virtual void OnChannelOpened(const IPC::ChannelHandle& handle) = 0;
- virtual void OnError() = 0;
-
- protected:
- virtual ~Client() {}
- };
-
- PluginProcessHost();
- ~PluginProcessHost() override;
-
- // IPC::Sender implementation:
- bool Send(IPC::Message* message) override;
-
- // Initialize the new plugin process, returning true on success. This must
- // be called before the object can be used.
- bool Init(const WebPluginInfo& info);
-
- // Force the plugin process to shutdown (cleanly).
- void ForceShutdown();
-
- bool OnMessageReceived(const IPC::Message& msg) override;
- void OnChannelConnected(int32_t peer_pid) override;
- void OnChannelError() override;
-
- // Tells the plugin process to create a new channel for communication with a
- // renderer. When the plugin process responds with the channel name,
- // OnChannelOpened in the client is called.
- void OpenChannelToPlugin(Client* client);
-
- // This function is called to cancel pending requests to open new channels.
- void CancelPendingRequest(Client* client);
-
- // This function is called to cancel sent requests to open new channels.
- void CancelSentRequest(Client* client);
-
- // This function is called on the IO thread once we receive a reply from the
- // modal HTML dialog (in the form of a JSON string). This function forwards
- // that reply back to the plugin that requested the dialog.
- void OnModalDialogResponse(const std::string& json_retval,
- IPC::Message* sync_result);
-
-#if defined(OS_MACOSX)
- // This function is called on the IO thread when the browser becomes the
- // active application.
- void OnAppActivation();
-#endif
-
- const WebPluginInfo& info() const { return info_; }
-
-#if defined(OS_WIN)
- // Tracks plugin parent windows created on the browser UI thread.
- void AddWindow(HWND window);
-#endif
-
- // Given a pid of a plugin process, returns the plugin information in |info|
- // if we know about that process. Otherwise returns false.
- // This method can be called on any thread.
- static bool GetWebPluginInfoFromPluginPid(base::ProcessId pid,
- WebPluginInfo* info);
-
- private:
- // Sends a message to the plugin process to request creation of a new channel
- // for the given mime type.
- void RequestPluginChannel(Client* client);
-
- // Message handlers.
- void OnChannelCreated(const IPC::ChannelHandle& channel_handle);
- void OnChannelDestroyed(int renderer_id);
-
-#if defined(OS_WIN)
- void OnPluginWindowDestroyed(HWND window, HWND parent);
-#endif
-
-#if defined(OS_MACOSX)
- void OnPluginShowWindow(uint32_t window_id,
- gfx::Rect window_rect,
- bool modal);
- void OnPluginHideWindow(uint32_t window_id, gfx::Rect window_rect);
- void OnPluginSetCursorVisibility(bool visible);
-#endif
-
- bool CanShutdown() override;
- void OnProcessCrashed(int exit_code) override;
-
- void CancelRequests();
-
- // Callback for ResourceMessageFilter.
- void GetContexts(ResourceType resource_type,
- int origin_pid,
- 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_;
-
- // These are the channel requests that we have already sent to
- // the plugin process, but haven't heard back about yet.
- std::list<Client*> sent_requests_;
-
- // Information about the plugin.
- WebPluginInfo info_;
-
- // The pid of the plugin process.
- int pid_;
-
-#if defined(OS_WIN)
- // Tracks plugin parent windows created on the UI thread.
- std::set<HWND> plugin_parent_windows_set_;
-#endif
-#if defined(OS_MACOSX)
- // Tracks plugin windows currently visible.
- std::set<uint32_t> plugin_visible_windows_set_;
- // Tracks full screen windows currently visible.
- std::set<uint32_t> plugin_fullscreen_windows_set_;
- // Tracks modal windows currently visible.
- std::set<uint32_t> plugin_modal_windows_set_;
- // Tracks the current visibility of the cursor.
- bool plugin_cursor_visible_;
-#endif
-
- // Map from render_process_id to its ResourceContext. Instead of storing the
- // raw pointer, we store the struct below. This is needed because a renderer
- // process can actually have multiple IPC channels to the same plugin process,
- // depending on timing conditions with plugin instance creation and shutdown.
- struct ResourceContextEntry {
- ResourceContext* resource_context;
- int ref_count;
- };
- typedef std::map<int, ResourceContextEntry> ResourceContextMap;
- ResourceContextMap resource_context_map_;
-
- scoped_ptr<BrowserChildProcessHostImpl> process_;
-
- DISALLOW_COPY_AND_ASSIGN(PluginProcessHost);
-};
-
-class PluginProcessHostIterator
- : public BrowserChildProcessHostTypeIterator<PluginProcessHost> {
- public:
- PluginProcessHostIterator()
- : BrowserChildProcessHostTypeIterator<PluginProcessHost>(
- PROCESS_TYPE_PLUGIN) {}
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_PLUGIN_PROCESS_HOST_H_
diff --git a/chromium/content/browser/plugin_process_host_mac.cc b/chromium/content/browser/plugin_process_host_mac.cc
deleted file mode 100644
index 8bd04433bf9..00000000000
--- a/chromium/content/browser/plugin_process_host_mac.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <Carbon/Carbon.h>
-#include <stdint.h>
-
-#include "build/build_config.h"
-
-#include <vector>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/mac/mac_util.h"
-#include "content/browser/browser_child_process_host_impl.h"
-#include "content/browser/plugin_process_host.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/child_process_data.h"
-#include "ui/gfx/geometry/rect.h"
-
-namespace content {
-
-void PluginProcessHost::OnPluginShowWindow(uint32_t window_id,
- gfx::Rect window_rect,
- bool modal) {
- plugin_visible_windows_set_.insert(window_id);
- if (modal)
- plugin_modal_windows_set_.insert(window_id);
- CGRect window_bounds = {
- { window_rect.x(), window_rect.y() },
- { window_rect.width(), window_rect.height() }
- };
- CGRect main_display_bounds = CGDisplayBounds(CGMainDisplayID());
- if (CGRectEqualToRect(window_bounds, main_display_bounds) &&
- (plugin_fullscreen_windows_set_.find(window_id) ==
- plugin_fullscreen_windows_set_.end())) {
- plugin_fullscreen_windows_set_.insert(window_id);
- // If the plugin has just shown a window that's the same dimensions as
- // the main display, hide the menubar so that it has the whole screen.
- // (but only if we haven't already seen this fullscreen window, since
- // otherwise our refcounting can get skewed).
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(base::mac::RequestFullScreen,
- base::mac::kFullScreenModeHideAll));
- }
-}
-
-// Must be called on the UI thread.
-// If plugin_pid is -1, the browser will be the active process on return,
-// otherwise that process will be given focus back before this function returns.
-static void ReleasePluginFullScreen(pid_t plugin_pid) {
- // Releasing full screen only works if we are the frontmost process; grab
- // focus, but give it back to the plugin process if requested.
- base::mac::ActivateProcess(base::GetCurrentProcId());
- base::mac::ReleaseFullScreen(base::mac::kFullScreenModeHideAll);
- if (plugin_pid != -1) {
- base::mac::ActivateProcess(plugin_pid);
- }
-}
-
-void PluginProcessHost::OnPluginHideWindow(uint32_t window_id,
- gfx::Rect window_rect) {
- bool had_windows = !plugin_visible_windows_set_.empty();
- plugin_visible_windows_set_.erase(window_id);
- bool browser_needs_activation = had_windows &&
- plugin_visible_windows_set_.empty();
-
- plugin_modal_windows_set_.erase(window_id);
- if (plugin_fullscreen_windows_set_.find(window_id) !=
- plugin_fullscreen_windows_set_.end()) {
- plugin_fullscreen_windows_set_.erase(window_id);
- pid_t plugin_pid =
- browser_needs_activation ? -1 : process_->GetData().handle;
- browser_needs_activation = false;
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(ReleasePluginFullScreen, plugin_pid));
- }
-
- if (browser_needs_activation) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(base::mac::ActivateProcess, base::GetCurrentProcId()));
- }
-}
-
-void PluginProcessHost::OnAppActivation() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // If our plugin process has any modal windows up, we need to bring it forward
- // so that they act more like an in-process modal window would.
- if (!plugin_modal_windows_set_.empty()) {
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(base::mac::ActivateProcess, process_->GetData().handle));
- }
-}
-
-void PluginProcessHost::OnPluginSetCursorVisibility(bool visible) {
- if (plugin_cursor_visible_ != visible) {
- plugin_cursor_visible_ = visible;
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(base::mac::SetCursorVisibility,
- visible));
- }
-}
-
-} // namespace content
diff --git a/chromium/content/browser/plugin_service_impl.cc b/chromium/content/browser/plugin_service_impl.cc
index 700d30428c7..c81e19b6b23 100644
--- a/chromium/content/browser/plugin_service_impl.cc
+++ b/chromium/content/browser/plugin_service_impl.cc
@@ -34,108 +34,27 @@
#include "content/public/common/process_type.h"
#include "content/public/common/webplugininfo.h"
-#if defined(OS_WIN)
-#include "content/common/plugin_constants_win.h"
-#include "ui/gfx/win/hwnd_util.h"
-#endif
-
-#if defined(OS_POSIX)
-#include "content/browser/plugin_loader_posix.h"
-#endif
-
-#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
-using ::base::FilePathWatcher;
-#endif
-
namespace content {
namespace {
// This enum is used to collect Flash usage data.
enum FlashUsage {
- // Number of browser processes that have started at least one NPAPI Flash
- // process during their lifetime.
- START_NPAPI_FLASH_AT_LEAST_ONCE,
// Number of browser processes that have started at least one PPAPI Flash
// process during their lifetime.
- START_PPAPI_FLASH_AT_LEAST_ONCE,
+ START_PPAPI_FLASH_AT_LEAST_ONCE = 1,
// Total number of browser processes.
TOTAL_BROWSER_PROCESSES,
FLASH_USAGE_ENUM_COUNT
};
-enum NPAPIPluginStatus {
- // Platform does not support NPAPI.
- NPAPI_STATUS_UNSUPPORTED,
- // Platform supports NPAPI and NPAPI is disabled.
- NPAPI_STATUS_DISABLED,
- // Platform supports NPAPI and NPAPI is enabled.
- NPAPI_STATUS_ENABLED,
- NPAPI_STATUS_ENUM_COUNT
-};
-
-bool LoadPluginListInProcess() {
-#if defined(OS_WIN)
- return true;
-#else
- // If on POSIX, we don't want to load the list of NPAPI plugins in-process as
- // that causes instability.
-
- // Can't load the plugins on the utility thread when in single process mode
- // since that requires GTK which can only be used on the main thread.
- if (RenderProcessHost::run_renderer_in_process())
- return true;
-
- return !PluginService::GetInstance()->NPAPIPluginsSupported();
-#endif
-}
-
// Callback set on the PluginList to assert that plugin loading happens on the
// correct thread.
void WillLoadPluginsCallback(
base::SequencedWorkerPool::SequenceToken token) {
- if (LoadPluginListInProcess()) {
- CHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
- token));
- } else {
- CHECK(false) << "Plugin loading should happen out-of-process.";
- }
+ CHECK(BrowserThread::GetBlockingPool()->IsRunningSequenceOnCurrentThread(
+ token));
}
-#if defined(OS_MACOSX)
-void NotifyPluginsOfActivation() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- for (PluginProcessHostIterator iter; !iter.Done(); ++iter)
- iter->OnAppActivation();
-}
-#endif
-
-#if defined(OS_POSIX)
-#if !defined(OS_OPENBSD) && !defined(OS_ANDROID)
-void NotifyPluginDirChanged(const base::FilePath& path, bool error) {
- if (error) {
- // TODO(pastarmovj): Add some sensible error handling. Maybe silently
- // stopping the watcher would be enough. Or possibly restart it.
- NOTREACHED();
- return;
- }
- VLOG(1) << "Watched path changed: " << path.value();
- // Make the plugin list update itself
- PluginList::Singleton()->RefreshPlugins();
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&PluginService::PurgePluginListCache,
- static_cast<BrowserContext*>(NULL), false));
-}
-#endif // !defined(OS_OPENBSD) && !defined(OS_ANDROID)
-
-void ForwardCallback(base::SingleThreadTaskRunner* target_task_runner,
- const PluginService::GetPluginsCallback& callback,
- const std::vector<WebPluginInfo>& plugins) {
- target_task_runner->PostTask(FROM_HERE, base::Bind(callback, plugins));
-}
-#endif // defined(OS_POSIX)
-
} // namespace
// static
@@ -159,7 +78,7 @@ PluginServiceImpl* PluginServiceImpl::GetInstance() {
}
PluginServiceImpl::PluginServiceImpl()
- : npapi_plugins_enabled_(false), filter_(NULL) {
+ : filter_(NULL) {
// Collect the total number of browser processes (which create
// PluginServiceImpl objects, to be precise). The number is used to normalize
// the number of processes which start at least one NPAPI/PPAPI Flash process.
@@ -172,8 +91,6 @@ PluginServiceImpl::PluginServiceImpl()
}
PluginServiceImpl::~PluginServiceImpl() {
- // Make sure no plugin channel requests have been leaked.
- DCHECK(pending_plugin_clients_.empty());
}
void PluginServiceImpl::Init() {
@@ -182,80 +99,6 @@ void PluginServiceImpl::Init() {
base::Bind(&WillLoadPluginsCallback, plugin_list_token_));
RegisterPepperPlugins();
-
- // Load any specified on the command line as well.
- const base::CommandLine* command_line =
- base::CommandLine::ForCurrentProcess();
- base::FilePath path =
- command_line->GetSwitchValuePath(switches::kLoadPlugin);
- if (!path.empty())
- AddExtraPluginPath(path);
- path = command_line->GetSwitchValuePath(switches::kExtraPluginDir);
- if (!path.empty())
- PluginList::Singleton()->AddExtraPluginDir(path);
-
- if (command_line->HasSwitch(switches::kDisablePluginsDiscovery))
- PluginList::Singleton()->DisablePluginsDiscovery();
-}
-
-void PluginServiceImpl::StartWatchingPlugins() {
- // Start watching for changes in the plugin list. This means watching
- // for changes in the Windows registry keys and on both Windows and POSIX
- // watch for changes in the paths that are expected to contain plugins.
-#if defined(OS_WIN)
- if (hkcu_key_.Create(HKEY_CURRENT_USER,
- kRegistryMozillaPlugins,
- KEY_NOTIFY) == ERROR_SUCCESS) {
- base::win::RegKey::ChangeCallback callback =
- base::Bind(&PluginServiceImpl::OnKeyChanged, base::Unretained(this),
- base::Unretained(&hkcu_key_));
- hkcu_key_.StartWatching(callback);
- }
- if (hklm_key_.Create(HKEY_LOCAL_MACHINE,
- kRegistryMozillaPlugins,
- KEY_NOTIFY) == ERROR_SUCCESS) {
- base::win::RegKey::ChangeCallback callback =
- base::Bind(&PluginServiceImpl::OnKeyChanged, base::Unretained(this),
- base::Unretained(&hklm_key_));
- hklm_key_.StartWatching(callback);
- }
-#endif
-#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
-// On ChromeOS the user can't install plugins anyway and on Windows all
-// important plugins register themselves in the registry so no need to do that.
-
- // Get the list of all paths for registering the FilePathWatchers
- // that will track and if needed reload the list of plugins on runtime.
- std::vector<base::FilePath> plugin_dirs;
- PluginList::Singleton()->GetPluginDirectories(&plugin_dirs);
-
- for (size_t i = 0; i < plugin_dirs.size(); ++i) {
- // FilePathWatcher can not handle non-absolute paths under windows.
- // We don't watch for file changes in windows now but if this should ever
- // be extended to Windows these lines might save some time of debugging.
-#if defined(OS_WIN)
- if (!plugin_dirs[i].IsAbsolute())
- continue;
-#endif
- FilePathWatcher* watcher = new FilePathWatcher();
- VLOG(1) << "Watching for changes in: " << plugin_dirs[i].value();
- BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&PluginServiceImpl::RegisterFilePathWatcher, watcher,
- plugin_dirs[i]));
- file_watchers_.push_back(watcher);
- }
-#endif
-}
-
-PluginProcessHost* PluginServiceImpl::FindNpapiPluginProcess(
- const base::FilePath& plugin_path) {
- for (PluginProcessHostIterator iter; !iter.Done(); ++iter) {
- if (iter->info().path == plugin_path)
- return *iter;
- }
-
- return NULL;
}
PpapiPluginProcessHost* PluginServiceImpl::FindPpapiPluginProcess(
@@ -280,46 +123,6 @@ PpapiPluginProcessHost* PluginServiceImpl::FindPpapiBrokerProcess(
return NULL;
}
-PluginProcessHost* PluginServiceImpl::FindOrStartNpapiPluginProcess(
- int render_process_id,
- const base::FilePath& plugin_path) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- if (filter_ && !filter_->CanLoadPlugin(render_process_id, plugin_path))
- return NULL;
-
- PluginProcessHost* plugin_host = FindNpapiPluginProcess(plugin_path);
- if (plugin_host)
- return plugin_host;
-
- WebPluginInfo info;
- if (!GetPluginInfoByPath(plugin_path, &info)) {
- return NULL;
- }
-
- // Record when NPAPI Flash process is started for the first time.
- static bool counted = false;
- if (!counted && base::UTF16ToUTF8(info.name) == kFlashPluginName) {
- counted = true;
- UMA_HISTOGRAM_ENUMERATION("Plugin.FlashUsage",
- START_NPAPI_FLASH_AT_LEAST_ONCE,
- FLASH_USAGE_ENUM_COUNT);
- }
-#if defined(OS_CHROMEOS)
- // TODO(ihf): Move to an earlier place once crbug.com/314301 is fixed. For now
- // we still want Plugin.FlashUsage recorded if we end up here.
- LOG(WARNING) << "Refusing to start npapi plugin on ChromeOS.";
- return NULL;
-#endif
- // This plugin isn't loaded by any plugin process, so create a new process.
- scoped_ptr<PluginProcessHost> new_host(new PluginProcessHost());
- if (!new_host->Init(info)) {
- NOTREACHED(); // Init is not expected to fail.
- return NULL;
- }
- return new_host.release();
-}
-
PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiPluginProcess(
int render_process_id,
const base::FilePath& plugin_path,
@@ -388,29 +191,6 @@ PpapiPluginProcessHost* PluginServiceImpl::FindOrStartPpapiBrokerProcess(
return PpapiPluginProcessHost::CreateBrokerHost(*info);
}
-void PluginServiceImpl::OpenChannelToNpapiPlugin(
- int render_process_id,
- int render_frame_id,
- const GURL& url,
- const GURL& page_url,
- const std::string& mime_type,
- PluginProcessHost::Client* client) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(!ContainsKey(pending_plugin_clients_, client));
- pending_plugin_clients_.insert(client);
-
- // Make sure plugins are loaded if necessary.
- PluginServiceFilterParams params = {
- render_process_id,
- render_frame_id,
- page_url,
- client->GetResourceContext()
- };
- GetPlugins(base::Bind(
- &PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin,
- base::Unretained(this), params, url, mime_type, client));
-}
-
void PluginServiceImpl::OpenChannelToPpapiPlugin(
int render_process_id,
const base::FilePath& plugin_path,
@@ -440,78 +220,6 @@ void PluginServiceImpl::OpenChannelToPpapiBroker(
}
}
-void PluginServiceImpl::CancelOpenChannelToNpapiPlugin(
- PluginProcessHost::Client* client) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- DCHECK(ContainsKey(pending_plugin_clients_, client));
- pending_plugin_clients_.erase(client);
-}
-
-void PluginServiceImpl::ForwardGetAllowedPluginForOpenChannelToPlugin(
- const PluginServiceFilterParams& params,
- const GURL& url,
- const std::string& mime_type,
- PluginProcessHost::Client* client,
- const std::vector<WebPluginInfo>&) {
- GetAllowedPluginForOpenChannelToPlugin(
- params.render_process_id, params.render_frame_id, url, params.page_url,
- mime_type, client, params.resource_context);
-}
-
-void PluginServiceImpl::GetAllowedPluginForOpenChannelToPlugin(
- int render_process_id,
- int render_frame_id,
- const GURL& url,
- const GURL& page_url,
- const std::string& mime_type,
- PluginProcessHost::Client* client,
- ResourceContext* resource_context) {
- WebPluginInfo info;
- bool allow_wildcard = true;
- bool found = GetPluginInfo(
- render_process_id, render_frame_id, resource_context,
- url, page_url, mime_type, allow_wildcard,
- NULL, &info, NULL);
- base::FilePath plugin_path;
- if (found)
- plugin_path = info.path;
-
- // Now we jump back to the IO thread to finish opening the channel.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&PluginServiceImpl::FinishOpenChannelToPlugin,
- base::Unretained(this),
- render_process_id,
- plugin_path,
- client));
- if (filter_) {
- DCHECK_EQ(WebPluginInfo::PLUGIN_TYPE_NPAPI, info.type);
- filter_->NPAPIPluginLoaded(render_process_id, render_frame_id, mime_type,
- info);
- }
-}
-
-void PluginServiceImpl::FinishOpenChannelToPlugin(
- int render_process_id,
- const base::FilePath& plugin_path,
- PluginProcessHost::Client* client) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // Make sure it hasn't been canceled yet.
- if (!ContainsKey(pending_plugin_clients_, client))
- return;
- pending_plugin_clients_.erase(client);
-
- PluginProcessHost* plugin_host = FindOrStartNpapiPluginProcess(
- render_process_id, plugin_path);
- if (plugin_host) {
- client->OnFoundPluginProcessHost(plugin_host);
- plugin_host->OpenChannelToPlugin(client);
- } else {
- client->OnError();
- }
-}
-
bool PluginServiceImpl::GetPluginInfoArray(
const GURL& url,
const std::string& mime_type,
@@ -520,8 +228,7 @@ bool PluginServiceImpl::GetPluginInfoArray(
std::vector<std::string>* actual_mime_types) {
bool use_stale = false;
PluginList::Singleton()->GetPluginInfoArray(
- url, mime_type, allow_wildcard, &use_stale, NPAPIPluginsSupported(),
- plugins, actual_mime_types);
+ url, mime_type, allow_wildcard, &use_stale, plugins, actual_mime_types);
return use_stale;
}
@@ -598,23 +305,11 @@ void PluginServiceImpl::GetPlugins(const GetPluginsCallback& callback) {
scoped_refptr<base::SingleThreadTaskRunner> target_task_runner(
base::ThreadTaskRunnerHandle::Get());
- if (LoadPluginListInProcess()) {
- BrowserThread::GetBlockingPool()
- ->PostSequencedWorkerTaskWithShutdownBehavior(
- plugin_list_token_, FROM_HERE,
- base::Bind(&PluginServiceImpl::GetPluginsInternal,
- base::Unretained(this), target_task_runner, callback),
- base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
- return;
- }
-#if defined(OS_POSIX)
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&PluginServiceImpl::GetPluginsOnIOThread,
- base::Unretained(this), target_task_runner, callback));
-#else
- NOTREACHED();
-#endif
+ BrowserThread::GetBlockingPool()->PostSequencedWorkerTaskWithShutdownBehavior(
+ plugin_list_token_, FROM_HERE,
+ base::Bind(&PluginServiceImpl::GetPluginsInternal, base::Unretained(this),
+ base::RetainedRef(target_task_runner), callback),
+ base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
}
void PluginServiceImpl::GetPluginsInternal(
@@ -624,39 +319,11 @@ void PluginServiceImpl::GetPluginsInternal(
plugin_list_token_));
std::vector<WebPluginInfo> plugins;
- PluginList::Singleton()->GetPlugins(&plugins, NPAPIPluginsSupported());
+ PluginList::Singleton()->GetPlugins(&plugins);
target_task_runner->PostTask(FROM_HERE, base::Bind(callback, plugins));
}
-#if defined(OS_POSIX)
-void PluginServiceImpl::GetPluginsOnIOThread(
- base::SingleThreadTaskRunner* target_task_runner,
- const GetPluginsCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- // If we switch back to loading plugins in process, then we need to make
- // sure g_thread_init() gets called since plugins may call glib at load.
-
- if (!plugin_loader_.get())
- plugin_loader_ = new PluginLoaderPosix;
-
- plugin_loader_->GetPlugins(base::Bind(
- &ForwardCallback, make_scoped_refptr(target_task_runner), callback));
-}
-#endif
-
-#if defined(OS_WIN)
-void PluginServiceImpl::OnKeyChanged(base::win::RegKey* key) {
- key->StartWatching(base::Bind(&PluginServiceImpl::OnKeyChanged,
- base::Unretained(this),
- base::Unretained(key)));
-
- PluginList::Singleton()->RefreshPlugins();
- PurgePluginListCache(NULL, false);
-}
-#endif // defined(OS_WIN)
-
void PluginServiceImpl::RegisterPepperPlugins() {
ComputePepperPluginList(&ppapi_plugins_);
for (size_t i = 0; i < ppapi_plugins_.size(); ++i) {
@@ -691,16 +358,6 @@ PepperPluginInfo* PluginServiceImpl::GetRegisteredPpapiPluginInfo(
return &ppapi_plugins_[ppapi_plugins_.size() - 1];
}
-#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
-// static
-void PluginServiceImpl::RegisterFilePathWatcher(FilePathWatcher* watcher,
- const base::FilePath& path) {
- bool result = watcher->Watch(path, false,
- base::Bind(&NotifyPluginDirChanged));
- DCHECK(result);
-}
-#endif
-
void PluginServiceImpl::SetFilter(PluginServiceFilter* filter) {
filter_ = filter;
}
@@ -709,20 +366,6 @@ PluginServiceFilter* PluginServiceImpl::GetFilter() {
return filter_;
}
-void PluginServiceImpl::ForcePluginShutdown(const base::FilePath& plugin_path) {
- if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&PluginServiceImpl::ForcePluginShutdown,
- base::Unretained(this), plugin_path));
- return;
- }
-
- PluginProcessHost* plugin = FindNpapiPluginProcess(plugin_path);
- if (plugin)
- plugin->ForceShutdown();
-}
-
static const unsigned int kMaxCrashesPerInterval = 3;
static const unsigned int kCrashesInterval = 120;
@@ -759,33 +402,9 @@ void PluginServiceImpl::RefreshPlugins() {
PluginList::Singleton()->RefreshPlugins();
}
-void PluginServiceImpl::AddExtraPluginPath(const base::FilePath& path) {
- if (!NPAPIPluginsSupported()) {
- // TODO(jam): remove and just have CHECK once we're sure this doesn't get
- // triggered.
- DVLOG(0) << "NPAPI plugins not supported";
- return;
- }
- PluginList::Singleton()->AddExtraPluginPath(path);
-}
-
-void PluginServiceImpl::RemoveExtraPluginPath(const base::FilePath& path) {
- PluginList::Singleton()->RemoveExtraPluginPath(path);
-}
-
-void PluginServiceImpl::AddExtraPluginDir(const base::FilePath& path) {
- PluginList::Singleton()->AddExtraPluginDir(path);
-}
-
void PluginServiceImpl::RegisterInternalPlugin(
const WebPluginInfo& info,
bool add_at_beginning) {
- // Internal plugins should never be NPAPI.
- CHECK_NE(info.type, WebPluginInfo::PLUGIN_TYPE_NPAPI);
- if (info.type == WebPluginInfo::PLUGIN_TYPE_NPAPI) {
- DVLOG(0) << "Don't register NPAPI plugins when they're not supported";
- return;
- }
PluginList::Singleton()->RegisterInternalPlugin(info, add_at_beginning);
}
@@ -798,76 +417,6 @@ void PluginServiceImpl::GetInternalPlugins(
PluginList::Singleton()->GetInternalPlugins(plugins);
}
-bool PluginServiceImpl::NPAPIPluginsSupported() {
-#if defined(OS_WIN) || defined(OS_MACOSX)
- npapi_plugins_enabled_ = GetContentClient()->browser()->IsNPAPIEnabled();
-#if defined(OS_WIN)
- // NPAPI plugins don't play well with Win32k renderer lockdown.
- if (npapi_plugins_enabled_)
- DisableWin32kRendererLockdown();
-#endif
- NPAPIPluginStatus status =
- npapi_plugins_enabled_ ? NPAPI_STATUS_ENABLED : NPAPI_STATUS_DISABLED;
-#else
- NPAPIPluginStatus status = NPAPI_STATUS_UNSUPPORTED;
-#endif
- UMA_HISTOGRAM_ENUMERATION("Plugin.NPAPIStatus", status,
- NPAPI_STATUS_ENUM_COUNT);
-
- return npapi_plugins_enabled_;
-}
-
-void PluginServiceImpl::DisablePluginsDiscoveryForTesting() {
- PluginList::Singleton()->DisablePluginsDiscovery();
-}
-
-#if defined(OS_MACOSX)
-void PluginServiceImpl::AppActivated() {
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(&NotifyPluginsOfActivation));
-}
-#elif defined(OS_WIN)
-
-bool GetPluginPropertyFromWindow(
- HWND window, const wchar_t* plugin_atom_property,
- base::string16* plugin_property) {
- ATOM plugin_atom = static_cast<ATOM>(
- reinterpret_cast<uintptr_t>(GetPropW(window, plugin_atom_property)));
- if (plugin_atom != 0) {
- WCHAR plugin_property_local[MAX_PATH] = {0};
- GlobalGetAtomNameW(plugin_atom,
- plugin_property_local,
- ARRAYSIZE(plugin_property_local));
- *plugin_property = plugin_property_local;
- return true;
- }
- return false;
-}
-
-bool PluginServiceImpl::GetPluginInfoFromWindow(
- HWND window,
- base::string16* plugin_name,
- base::string16* plugin_version) {
- if (!IsPluginWindow(window))
- return false;
-
-
- DWORD process_id = 0;
- GetWindowThreadProcessId(window, &process_id);
- WebPluginInfo info;
- if (!PluginProcessHost::GetWebPluginInfoFromPluginPid(process_id, &info))
- return false;
-
- *plugin_name = info.name;
- *plugin_version = info.version;
- return true;
-}
-
-bool PluginServiceImpl::IsPluginWindow(HWND window) {
- return gfx::GetClassName(window) == base::string16(kNativeWindowClassName);
-}
-#endif
-
bool PluginServiceImpl::PpapiDevChannelSupported(
BrowserContext* browser_context,
const GURL& document_url) {
diff --git a/chromium/content/browser/plugin_service_impl.h b/chromium/content/browser/plugin_service_impl.h
index 644a26230a5..e167cc34175 100644
--- a/chromium/content/browser/plugin_service_impl.h
+++ b/chromium/content/browser/plugin_service_impl.h
@@ -24,7 +24,6 @@
#include "base/threading/sequenced_worker_pool.h"
#include "base/time/time.h"
#include "build/build_config.h"
-#include "content/browser/plugin_process_host.h"
#include "content/browser/ppapi_plugin_process_host.h"
#include "content/common/content_export.h"
#include "content/public/browser/plugin_service.h"
@@ -48,20 +47,10 @@ class SingleThreadTaskRunner;
namespace content {
class BrowserContext;
class PluginDirWatcherDelegate;
-class PluginLoaderPosix;
class PluginServiceFilter;
class ResourceContext;
struct PepperPluginInfo;
-// base::Bind() has limited arity, and the filter-related methods tend to
-// surpass that limit.
-struct PluginServiceFilterParams {
- int render_process_id;
- int render_frame_id;
- GURL page_url;
- ResourceContext* resource_context;
-};
-
class CONTENT_EXPORT PluginServiceImpl
: NON_EXPORTED_BASE(public PluginService) {
public:
@@ -70,7 +59,6 @@ class CONTENT_EXPORT PluginServiceImpl
// PluginService implementation:
void Init() override;
- void StartWatchingPlugins() override;
bool GetPluginInfoArray(const GURL& url,
const std::string& mime_type,
bool allow_wildcard,
@@ -95,28 +83,12 @@ class CONTENT_EXPORT PluginServiceImpl
const base::FilePath& plugin_path) override;
void SetFilter(PluginServiceFilter* filter) override;
PluginServiceFilter* GetFilter() override;
- void ForcePluginShutdown(const base::FilePath& plugin_path) override;
bool IsPluginUnstable(const base::FilePath& plugin_path) override;
void RefreshPlugins() override;
- void AddExtraPluginPath(const base::FilePath& path) override;
- void RemoveExtraPluginPath(const base::FilePath& path) override;
- void AddExtraPluginDir(const base::FilePath& path) override;
void RegisterInternalPlugin(const WebPluginInfo& info,
bool add_at_beginning) override;
void UnregisterInternalPlugin(const base::FilePath& path) override;
void GetInternalPlugins(std::vector<WebPluginInfo>* plugins) override;
- bool NPAPIPluginsSupported() override;
- void DisablePluginsDiscoveryForTesting() override;
-#if defined(OS_MACOSX)
- void AppActivated() override;
-#elif defined(OS_WIN)
- bool GetPluginInfoFromWindow(HWND window,
- base::string16* plugin_name,
- base::string16* plugin_version) override;
-
- // Returns true iff the given HWND is a plugin.
- bool IsPluginWindow(HWND window);
-#endif
bool PpapiDevChannelSupported(BrowserContext* browser_context,
const GURL& document_url) override;
@@ -124,8 +96,6 @@ class CONTENT_EXPORT PluginServiceImpl
// has been started by this service. This will start a process to host the
// 'plugin_path' if needed. If the process fails to start, the return value
// is NULL. Must be called on the IO thread.
- PluginProcessHost* FindOrStartNpapiPluginProcess(
- int render_process_id, const base::FilePath& plugin_path);
PpapiPluginProcessHost* FindOrStartPpapiPluginProcess(
int render_process_id,
const base::FilePath& plugin_path,
@@ -136,12 +106,6 @@ class CONTENT_EXPORT PluginServiceImpl
// Opens a channel to a plugin process for the given mime type, starting
// a new plugin process if necessary. This must be called on the IO thread
// or else a deadlock can occur.
- void OpenChannelToNpapiPlugin(int render_process_id,
- int render_frame_id,
- const GURL& url,
- const GURL& page_url,
- const std::string& mime_type,
- PluginProcessHost::Client* client);
void OpenChannelToPpapiPlugin(int render_process_id,
const base::FilePath& plugin_path,
const base::FilePath& profile_data_directory,
@@ -150,9 +114,6 @@ class CONTENT_EXPORT PluginServiceImpl
const base::FilePath& path,
PpapiPluginProcessHost::BrokerClient* client);
- // Cancels opening a channel to a NPAPI plugin.
- void CancelOpenChannelToNpapiPlugin(PluginProcessHost::Client* client);
-
// Used to monitor plugin stability.
void RegisterPluginCrash(const base::FilePath& plugin_path);
@@ -171,7 +132,6 @@ class CONTENT_EXPORT PluginServiceImpl
// Returns the plugin process host corresponding to the plugin process that
// has been started by this service. Returns NULL if no process has been
// started.
- PluginProcessHost* FindNpapiPluginProcess(const base::FilePath& plugin_path);
PpapiPluginProcessHost* FindPpapiPluginProcess(
const base::FilePath& plugin_path,
const base::FilePath& profile_data_directory);
@@ -184,67 +144,14 @@ class CONTENT_EXPORT PluginServiceImpl
void GetPluginsInternal(base::SingleThreadTaskRunner* target_task_runner,
const GetPluginsCallback& callback);
-#if defined(OS_POSIX)
- void GetPluginsOnIOThread(base::SingleThreadTaskRunner* target_task_runner,
- const GetPluginsCallback& callback);
-#endif
-
- // Binding directly to GetAllowedPluginForOpenChannelToPlugin() isn't possible
- // because more arity is needed <http://crbug.com/98542>. This just forwards.
- void ForwardGetAllowedPluginForOpenChannelToPlugin(
- const PluginServiceFilterParams& params,
- const GURL& url,
- const std::string& mime_type,
- PluginProcessHost::Client* client,
- const std::vector<WebPluginInfo>&);
- // Helper so we can do the plugin lookup on the FILE thread.
- void GetAllowedPluginForOpenChannelToPlugin(
- int render_process_id,
- int render_frame_id,
- const GURL& url,
- const GURL& page_url,
- const std::string& mime_type,
- PluginProcessHost::Client* client,
- ResourceContext* resource_context);
-
- // Helper so we can finish opening the channel after looking up the
- // plugin.
- void FinishOpenChannelToPlugin(int render_process_id,
- const base::FilePath& plugin_path,
- PluginProcessHost::Client* client);
-
-#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
- // Registers a new FilePathWatcher for a given path.
- static void RegisterFilePathWatcher(base::FilePathWatcher* watcher,
- const base::FilePath& path);
-#endif
-
-#if defined(OS_WIN)
- // Registry keys for getting notifications when new plugins are installed.
- base::win::RegKey hkcu_key_;
- base::win::RegKey hklm_key_;
-#endif
-
- bool npapi_plugins_enabled_;
-
-#if defined(OS_POSIX) && !defined(OS_OPENBSD) && !defined(OS_ANDROID)
- ScopedVector<base::FilePathWatcher> file_watchers_;
-#endif
-
std::vector<PepperPluginInfo> ppapi_plugins_;
// Weak pointer; outlives us.
PluginServiceFilter* filter_;
- std::set<PluginProcessHost::Client*> pending_plugin_clients_;
-
// Used to sequentialize loading plugins from disk.
base::SequencedWorkerPool::SequenceToken plugin_list_token_;
-#if defined(OS_POSIX)
- scoped_refptr<PluginLoaderPosix> plugin_loader_;
-#endif
-
// Used to detect if a given plugin is crashing over and over.
std::map<base::FilePath, std::vector<base::Time> > crash_times_;
diff --git a/chromium/content/browser/power_save_blocker_impl.cc b/chromium/content/browser/power_save_blocker_impl.cc
index b3f15fb58c7..069cd3a327f 100644
--- a/chromium/content/browser/power_save_blocker_impl.cc
+++ b/chromium/content/browser/power_save_blocker_impl.cc
@@ -14,12 +14,8 @@ scoped_ptr<PowerSaveBlocker> PowerSaveBlocker::Create(
PowerSaveBlockerType type,
Reason reason,
const std::string& description) {
-#if defined(OS_ANDROID) && defined(USE_AURA)
- return nullptr;
-#else
return scoped_ptr<PowerSaveBlocker>(
new PowerSaveBlockerImpl(type, reason, description));
-#endif
}
} // namespace content
diff --git a/chromium/content/browser/power_save_blocker_x11.cc b/chromium/content/browser/power_save_blocker_x11.cc
index 97eefef9519..babc81488a0 100644
--- a/chromium/content/browser/power_save_blocker_x11.cc
+++ b/chromium/content/browser/power_save_blocker_x11.cc
@@ -7,6 +7,7 @@
#include <X11/Xlib.h>
#include <stdint.h>
#include <X11/extensions/dpms.h>
+#include <X11/extensions/scrnsaver.h>
// Xlib #defines Status, but we can't have that for some of our headers.
#ifdef Status
#undef Status
@@ -108,12 +109,22 @@ class PowerSaveBlockerImpl::Delegate
void ApplyBlockFinished(dbus::Response* response);
void RemoveBlockFinished(dbus::Response* response);
+ // Wrapper for XScreenSaverSuspend. Checks whether the X11 Screen Saver
+ // Extension is available first. If it isn't, this is a no-op.
+ // Must be called on the UI thread.
+ static void XSSSuspendSet(bool suspend);
+
// If DPMS (the power saving system in X11) is not enabled, then we don't want
// to try to disable power saving, since on some desktop environments that may
// enable DPMS with very poor default settings (e.g. turning off the display
// after only 1 second). Must be called on the UI thread.
static bool DPMSEnabled();
+ // If no other method is available (i.e. not running under a Desktop
+ // Environment) check whether the X11 Screen Saver Extension can be used
+ // to disable the screen saver. Must be called on the UI thread.
+ static bool XSSAvailable();
+
// Returns an appropriate D-Bus API to use based on the desktop environment.
// Must be called on the UI thread, as it may call DPMSEnabled() above.
static DBusAPI SelectAPI();
@@ -180,9 +191,14 @@ void PowerSaveBlockerImpl::Delegate::CleanUp() {
// initializing on the UI thread, then just cancel it. We don't need to
// remove the block because we haven't even applied it yet.
enqueue_apply_ = false;
- } else if (ShouldBlock()) {
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(&Delegate::RemoveBlock, this));
+ } else {
+ if (ShouldBlock()) {
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(&Delegate::RemoveBlock, this));
+ }
+
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(&Delegate::XSSSuspendSet, false));
}
}
@@ -190,12 +206,17 @@ void PowerSaveBlockerImpl::Delegate::InitOnUIThread() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
base::AutoLock lock(lock_);
api_ = SelectAPI();
- if (enqueue_apply_ && ShouldBlock()) {
- // The thread we use here becomes the origin and D-Bus thread for the D-Bus
- // library, so we need to use the same thread above for RemoveBlock(). It
- // must be a thread that allows I/O operations, so we use the FILE thread.
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(&Delegate::ApplyBlock, this));
+
+ if (enqueue_apply_) {
+ if (ShouldBlock()) {
+ // The thread we use here becomes the origin and D-Bus thread for the
+ // D-Bus library, so we need to use the same thread above for
+ // RemoveBlock(). It must be a thread that allows I/O operations, so we
+ // use the FILE thread.
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(&Delegate::ApplyBlock, this));
+ }
+ XSSSuspendSet(true);
}
enqueue_apply_ = false;
}
@@ -384,6 +405,17 @@ void PowerSaveBlockerImpl::Delegate::RemoveBlockFinished(
}
// static
+void PowerSaveBlockerImpl::Delegate::XSSSuspendSet(bool suspend) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ if (!XSSAvailable())
+ return;
+
+ XDisplay* display = gfx::GetXDisplay();
+ XScreenSaverSuspend(display, suspend);
+}
+
+// static
bool PowerSaveBlockerImpl::Delegate::DPMSEnabled() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
XDisplay* display = gfx::GetXDisplay();
@@ -397,6 +429,23 @@ bool PowerSaveBlockerImpl::Delegate::DPMSEnabled() {
}
// static
+bool PowerSaveBlockerImpl::Delegate::XSSAvailable() {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ XDisplay* display = gfx::GetXDisplay();
+ int dummy;
+ int major;
+ int minor;
+
+ if (!XScreenSaverQueryExtension(display, &dummy, &dummy))
+ return false;
+
+ if (!XScreenSaverQueryVersion(display, &major, &minor))
+ return false;
+
+ return major > 1 || (major == 1 && minor >= 1);
+}
+
+// static
DBusAPI PowerSaveBlockerImpl::Delegate::SelectAPI() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
scoped_ptr<base::Environment> env(base::Environment::Create());
diff --git a/chromium/content/browser/ppapi_plugin_process_host.cc b/chromium/content/browser/ppapi_plugin_process_host.cc
index 3523fc10a8b..56ae0eea7f4 100644
--- a/chromium/content/browser/ppapi_plugin_process_host.cc
+++ b/chromium/content/browser/ppapi_plugin_process_host.cc
@@ -35,6 +35,10 @@
#include "ppapi/proxy/ppapi_messages.h"
#include "ui/base/ui_base_switches.h"
+#if defined(OS_POSIX)
+#include "content/public/browser/zygote_handle_linux.h"
+#endif // defined(OS_POSIX)
+
#if defined(OS_WIN)
#include "content/browser/renderer_host/dwrite_font_proxy_message_filter_win.h"
#include "content/common/sandbox_win.h"
@@ -45,6 +49,10 @@
namespace content {
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+ZygoteHandle g_ppapi_zygote;
+#endif // defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+
// NOTE: changes to this class need to be reviewed by the security team.
class PpapiPluginSandboxedProcessLauncherDelegate
: public content::SandboxedProcessLauncherDelegate {
@@ -105,13 +113,18 @@ class PpapiPluginSandboxedProcessLauncherDelegate
}
#elif defined(OS_POSIX)
- bool ShouldUseZygote() override {
+#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
+ ZygoteHandle* GetZygote() override {
const base::CommandLine& browser_command_line =
*base::CommandLine::ForCurrentProcess();
base::CommandLine::StringType plugin_launcher = browser_command_line
.GetSwitchValueNative(switches::kPpapiPluginLauncher);
- return !is_broker_ && plugin_launcher.empty();
+ if (is_broker_ || !plugin_launcher.empty())
+ return nullptr;
+ return GetGenericZygote();
}
+#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
+
base::ScopedFD TakeIpcFd() override { return std::move(ipc_fd_); }
#endif // OS_WIN
@@ -200,6 +213,14 @@ PpapiPluginProcessHost* PpapiPluginProcessHost::CreateBrokerHost(
return NULL;
}
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+// static
+void PpapiPluginProcessHost::EarlyZygoteLaunch() {
+ DCHECK(!g_ppapi_zygote);
+ g_ppapi_zygote = CreateZygote();
+}
+#endif // defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+
// static
void PpapiPluginProcessHost::DidCreateOutOfProcessInstance(
int plugin_process_id,
diff --git a/chromium/content/browser/ppapi_plugin_process_host.h b/chromium/content/browser/ppapi_plugin_process_host.h
index 96593494cd2..85e2b64de50 100644
--- a/chromium/content/browser/ppapi_plugin_process_host.h
+++ b/chromium/content/browser/ppapi_plugin_process_host.h
@@ -116,6 +116,11 @@ class PpapiPluginProcessHost : public BrowserChildProcessHostDelegate,
return profile_data_directory_;
}
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+ // Launch the zygote early in the browser startup.
+ static void EarlyZygoteLaunch();
+#endif // defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+
// The client pointer must remain valid until its callback is issued.
private:
diff --git a/chromium/content/browser/presentation/presentation_service_impl.cc b/chromium/content/browser/presentation/presentation_service_impl.cc
index 07644589a40..c2e30e998c6 100644
--- a/chromium/content/browser/presentation/presentation_service_impl.cc
+++ b/chromium/content/browser/presentation/presentation_service_impl.cc
@@ -39,16 +39,15 @@ int GetNextRequestSessionId() {
// |input|: The message to convert.
// |pass_ownership|: If true, function may reuse strings or buffers from
// |input| without copying. |input| can be freely modified.
-presentation::SessionMessagePtr ToMojoSessionMessage(
+mojom::SessionMessagePtr ToMojoSessionMessage(
content::PresentationSessionMessage* input,
bool pass_ownership) {
DCHECK(input);
- presentation::SessionMessagePtr output(presentation::SessionMessage::New());
+ mojom::SessionMessagePtr output(mojom::SessionMessage::New());
if (input->is_binary()) {
// binary data
DCHECK(input->data);
- output->type = presentation::PresentationMessageType::
- PRESENTATION_MESSAGE_TYPE_ARRAY_BUFFER;
+ output->type = mojom::PresentationMessageType::ARRAY_BUFFER;
if (pass_ownership) {
output->data.Swap(input->data.get());
} else {
@@ -56,8 +55,7 @@ presentation::SessionMessagePtr ToMojoSessionMessage(
}
} else {
// string message
- output->type =
- presentation::PresentationMessageType::PRESENTATION_MESSAGE_TYPE_TEXT;
+ output->type = mojom::PresentationMessageType::TEXT;
if (pass_ownership) {
output->message.Swap(&input->message);
} else {
@@ -68,11 +66,11 @@ presentation::SessionMessagePtr ToMojoSessionMessage(
}
scoped_ptr<PresentationSessionMessage> GetPresentationSessionMessage(
- presentation::SessionMessagePtr input) {
+ mojom::SessionMessagePtr input) {
DCHECK(!input.is_null());
scoped_ptr<content::PresentationSessionMessage> output;
switch (input->type) {
- case presentation::PRESENTATION_MESSAGE_TYPE_TEXT: {
+ case mojom::PresentationMessageType::TEXT: {
DCHECK(!input->message.is_null());
DCHECK(input->data.is_null());
// Return null PresentationSessionMessage if size exceeds.
@@ -84,7 +82,7 @@ scoped_ptr<PresentationSessionMessage> GetPresentationSessionMessage(
input->message.Swap(&output->message);
return output;
}
- case presentation::PRESENTATION_MESSAGE_TYPE_ARRAY_BUFFER: {
+ case mojom::PresentationMessageType::ARRAY_BUFFER: {
DCHECK(!input->data.is_null());
DCHECK(input->message.is_null());
if (input->data.size() > content::kMaxPresentationSessionMessageSize)
@@ -96,7 +94,7 @@ scoped_ptr<PresentationSessionMessage> GetPresentationSessionMessage(
input->data.Swap(output->data.get());
return output;
}
- case presentation::PRESENTATION_MESSAGE_TYPE_BLOB: {
+ case mojom::PresentationMessageType::BLOB: {
DCHECK(!input->data.is_null());
DCHECK(input->message.is_null());
if (input->data.size() > content::kMaxPresentationSessionMessageSize)
@@ -116,10 +114,9 @@ scoped_ptr<PresentationSessionMessage> GetPresentationSessionMessage(
void InvokeNewSessionMojoCallbackWithError(
const NewSessionMojoCallback& callback) {
- callback.Run(
- presentation::PresentationSessionInfoPtr(),
- presentation::PresentationError::From(
- PresentationError(PRESENTATION_ERROR_UNKNOWN, "Internal error")));
+ callback.Run(mojom::PresentationSessionInfoPtr(),
+ mojom::PresentationError::From(PresentationError(
+ PRESENTATION_ERROR_UNKNOWN, "Internal error")));
}
} // namespace
@@ -151,15 +148,14 @@ PresentationServiceImpl::~PresentationServiceImpl() {
// static
void PresentationServiceImpl::CreateMojoService(
RenderFrameHost* render_frame_host,
- mojo::InterfaceRequest<presentation::PresentationService> request) {
+ mojo::InterfaceRequest<mojom::PresentationService> request) {
DVLOG(2) << "CreateMojoService";
WebContents* web_contents =
WebContents::FromRenderFrameHost(render_frame_host);
DCHECK(web_contents);
// This object will be deleted when the RenderFrameHost is about to be
- // deleted (RenderFrameDeleted) or if a connection error occurred
- // (OnConnectionError).
+ // deleted (RenderFrameDeleted).
PresentationServiceImpl* impl = new PresentationServiceImpl(
render_frame_host,
web_contents,
@@ -169,17 +165,13 @@ void PresentationServiceImpl::CreateMojoService(
}
void PresentationServiceImpl::Bind(
- mojo::InterfaceRequest<presentation::PresentationService> request) {
- binding_.reset(new mojo::Binding<presentation::PresentationService>(
- this, std::move(request)));
- binding_->set_connection_error_handler([this]() {
- DVLOG(1) << "Connection error";
- delete this;
- });
+ mojo::InterfaceRequest<mojom::PresentationService> request) {
+ binding_.reset(
+ new mojo::Binding<mojom::PresentationService>(this, std::move(request)));
}
void PresentationServiceImpl::SetClient(
- presentation::PresentationServiceClientPtr client) {
+ mojom::PresentationServiceClientPtr client) {
DCHECK(!client_.get());
// TODO(imcheng): Set ErrorHandler to listen for errors.
client_ = std::move(client);
@@ -231,10 +223,9 @@ void PresentationServiceImpl::StartSession(
DVLOG(2) << "StartSession";
if (!delegate_) {
callback.Run(
- presentation::PresentationSessionInfoPtr(),
- presentation::PresentationError::From(
- PresentationError(PRESENTATION_ERROR_NO_AVAILABLE_SCREENS,
- "No screens found.")));
+ mojom::PresentationSessionInfoPtr(),
+ mojom::PresentationError::From(PresentationError(
+ PRESENTATION_ERROR_NO_AVAILABLE_SCREENS, "No screens found.")));
return;
}
@@ -261,11 +252,10 @@ void PresentationServiceImpl::JoinSession(
const NewSessionMojoCallback& callback) {
DVLOG(2) << "JoinSession";
if (!delegate_) {
- callback.Run(
- presentation::PresentationSessionInfoPtr(),
- presentation::PresentationError::From(
- PresentationError(PRESENTATION_ERROR_NO_PRESENTATION_FOUND,
- "Error joining route: No matching route")));
+ callback.Run(mojom::PresentationSessionInfoPtr(),
+ mojom::PresentationError::From(PresentationError(
+ PRESENTATION_ERROR_NO_PRESENTATION_FOUND,
+ "Error joining route: No matching route")));
return;
}
@@ -314,8 +304,8 @@ void PresentationServiceImpl::OnStartSessionSucceeded(
CHECK(pending_start_session_cb_.get());
pending_start_session_cb_->Run(
- presentation::PresentationSessionInfo::From(session_info),
- presentation::PresentationErrorPtr());
+ mojom::PresentationSessionInfo::From(session_info),
+ mojom::PresentationErrorPtr());
ListenForConnectionStateChange(session_info);
pending_start_session_cb_.reset();
start_session_request_id_ = kInvalidRequestSessionId;
@@ -328,8 +318,8 @@ void PresentationServiceImpl::OnStartSessionError(
return;
CHECK(pending_start_session_cb_.get());
- pending_start_session_cb_->Run(presentation::PresentationSessionInfoPtr(),
- presentation::PresentationError::From(error));
+ pending_start_session_cb_->Run(mojom::PresentationSessionInfoPtr(),
+ mojom::PresentationError::From(error));
pending_start_session_cb_.reset();
start_session_request_id_ = kInvalidRequestSessionId;
}
@@ -339,8 +329,8 @@ void PresentationServiceImpl::OnJoinSessionSucceeded(
const PresentationSessionInfo& session_info) {
if (RunAndEraseJoinSessionMojoCallback(
request_session_id,
- presentation::PresentationSessionInfo::From(session_info),
- presentation::PresentationErrorPtr())) {
+ mojom::PresentationSessionInfo::From(session_info),
+ mojom::PresentationErrorPtr())) {
ListenForConnectionStateChange(session_info);
}
}
@@ -348,16 +338,15 @@ void PresentationServiceImpl::OnJoinSessionSucceeded(
void PresentationServiceImpl::OnJoinSessionError(
int request_session_id,
const PresentationError& error) {
- RunAndEraseJoinSessionMojoCallback(
- request_session_id,
- presentation::PresentationSessionInfoPtr(),
- presentation::PresentationError::From(error));
+ RunAndEraseJoinSessionMojoCallback(request_session_id,
+ mojom::PresentationSessionInfoPtr(),
+ mojom::PresentationError::From(error));
}
bool PresentationServiceImpl::RunAndEraseJoinSessionMojoCallback(
int request_session_id,
- presentation::PresentationSessionInfoPtr session,
- presentation::PresentationErrorPtr error) {
+ mojom::PresentationSessionInfoPtr session,
+ mojom::PresentationErrorPtr error) {
auto it = pending_join_session_cbs_.find(request_session_id);
if (it == pending_join_session_cbs_.end())
return false;
@@ -386,8 +375,8 @@ void PresentationServiceImpl::SetDefaultPresentationURL(
}
void PresentationServiceImpl::SendSessionMessage(
- presentation::PresentationSessionInfoPtr session,
- presentation::SessionMessagePtr session_message,
+ mojom::PresentationSessionInfoPtr session,
+ mojom::SessionMessagePtr session_message,
const SendMessageMojoCallback& callback) {
DVLOG(2) << "SendSessionMessage";
DCHECK(!session_message.is_null());
@@ -434,11 +423,18 @@ void PresentationServiceImpl::Terminate(const mojo::String& presentation_url,
void PresentationServiceImpl::OnConnectionStateChanged(
const PresentationSessionInfo& connection,
- PresentationConnectionState state) {
+ const PresentationConnectionStateChangeInfo& info) {
DCHECK(client_.get());
- client_->OnConnectionStateChanged(
- presentation::PresentationSessionInfo::From(connection),
- PresentationConnectionStateToMojo(state));
+ if (info.state == PRESENTATION_CONNECTION_STATE_CLOSED) {
+ client_->OnConnectionClosed(
+ mojom::PresentationSessionInfo::From(connection),
+ PresentationConnectionCloseReasonToMojo(info.close_reason),
+ info.message);
+ } else {
+ client_->OnConnectionStateChanged(
+ mojom::PresentationSessionInfo::From(connection),
+ PresentationConnectionStateToMojo(info.state));
+ }
}
bool PresentationServiceImpl::FrameMatches(
@@ -451,7 +447,7 @@ bool PresentationServiceImpl::FrameMatches(
}
void PresentationServiceImpl::ListenForSessionMessages(
- presentation::PresentationSessionInfoPtr session) {
+ mojom::PresentationSessionInfoPtr session) {
DVLOG(2) << "ListenForSessionMessages";
if (!delegate_)
return;
@@ -470,13 +466,12 @@ void PresentationServiceImpl::OnSessionMessages(
DCHECK(client_);
DVLOG(2) << "OnSessionMessages";
- mojo::Array<presentation::SessionMessagePtr> mojoMessages(messages.size());
+ mojo::Array<mojom::SessionMessagePtr> mojoMessages(messages.size());
for (size_t i = 0; i < messages.size(); ++i)
mojoMessages[i] = ToMojoSessionMessage(messages[i], pass_ownership);
client_->OnSessionMessagesReceived(
- presentation::PresentationSessionInfo::From(session),
- std::move(mojoMessages));
+ mojom::PresentationSessionInfo::From(session), std::move(mojoMessages));
}
void PresentationServiceImpl::DidNavigateAnyFrame(
@@ -529,8 +524,7 @@ void PresentationServiceImpl::Reset() {
pending_join_session_cbs_.clear();
if (on_session_messages_callback_.get()) {
- on_session_messages_callback_->Run(
- mojo::Array<presentation::SessionMessagePtr>());
+ on_session_messages_callback_->Run(mojo::Array<mojom::SessionMessagePtr>());
on_session_messages_callback_.reset();
}
@@ -552,7 +546,7 @@ void PresentationServiceImpl::OnDefaultPresentationStarted(
const PresentationSessionInfo& connection) {
DCHECK(client_.get());
client_->OnDefaultSessionStarted(
- presentation::PresentationSessionInfo::From(connection));
+ mojom::PresentationSessionInfo::From(connection));
ListenForConnectionStateChange(connection);
}
@@ -597,8 +591,8 @@ PresentationServiceImpl::NewSessionMojoCallbackWrapper
}
void PresentationServiceImpl::NewSessionMojoCallbackWrapper::Run(
- presentation::PresentationSessionInfoPtr session,
- presentation::PresentationErrorPtr error) {
+ mojom::PresentationSessionInfoPtr session,
+ mojom::PresentationErrorPtr error) {
DCHECK(!callback_.is_null());
callback_.Run(std::move(session), std::move(error));
callback_.reset();
diff --git a/chromium/content/browser/presentation/presentation_service_impl.h b/chromium/content/browser/presentation/presentation_service_impl.h
index 88a70546780..b0243353655 100644
--- a/chromium/content/browser/presentation/presentation_service_impl.h
+++ b/chromium/content/browser/presentation/presentation_service_impl.h
@@ -33,9 +33,9 @@ struct LoadCommittedDetails;
struct PresentationSessionMessage;
class RenderFrameHost;
-using NewSessionMojoCallback = mojo::Callback<
- void(presentation::PresentationSessionInfoPtr,
- presentation::PresentationErrorPtr)>;
+using NewSessionMojoCallback =
+ mojo::Callback<void(mojom::PresentationSessionInfoPtr,
+ mojom::PresentationErrorPtr)>;
// Implementation of Mojo PresentationService.
// It handles Presentation API requests coming from Blink / renderer process
@@ -46,7 +46,7 @@ using NewSessionMojoCallback = mojo::Callback<
// This class is instantiated on-demand via Mojo's ConnectToRemoteService
// from the renderer when the first presentation API request is handled.
class CONTENT_EXPORT PresentationServiceImpl
- : public NON_EXPORTED_BASE(presentation::PresentationService),
+ : public NON_EXPORTED_BASE(mojom::PresentationService),
public WebContentsObserver,
public PresentationServiceDelegate::Observer {
public:
@@ -57,7 +57,7 @@ class CONTENT_EXPORT PresentationServiceImpl
// |request|: The instance will be bound to this request. Used for Mojo setup.
static void CreateMojoService(
RenderFrameHost* render_frame_host,
- mojo::InterfaceRequest<presentation::PresentationService> request);
+ mojo::InterfaceRequest<mojom::PresentationService> request);
private:
friend class PresentationServiceImplTest;
@@ -89,14 +89,16 @@ class CONTENT_EXPORT PresentationServiceImpl
MaxPendingJoinSessionRequests);
FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest,
ListenForConnectionStateChange);
+ FRIEND_TEST_ALL_PREFIXES(PresentationServiceImplTest,
+ ListenForConnectionClose);
// Maximum number of pending JoinSession requests at any given time.
static const int kMaxNumQueuedSessionRequests = 10;
using PresentationSessionMojoCallback =
- mojo::Callback<void(presentation::PresentationSessionInfoPtr)>;
+ mojo::Callback<void(mojom::PresentationSessionInfoPtr)>;
using SessionMessagesCallback =
- mojo::Callback<void(mojo::Array<presentation::SessionMessagePtr>)>;
+ mojo::Callback<void(mojo::Array<mojom::SessionMessagePtr>)>;
using SendMessageMojoCallback = mojo::Callback<void(bool)>;
// Listener implementation owned by PresentationServiceImpl. An instance of
@@ -129,8 +131,8 @@ class CONTENT_EXPORT PresentationServiceImpl
const NewSessionMojoCallback& callback);
~NewSessionMojoCallbackWrapper();
- void Run(presentation::PresentationSessionInfoPtr session,
- presentation::PresentationErrorPtr error);
+ void Run(mojom::PresentationSessionInfoPtr session,
+ mojom::PresentationErrorPtr error);
private:
NewSessionMojoCallback callback_;
@@ -149,7 +151,7 @@ class CONTENT_EXPORT PresentationServiceImpl
// PresentationService implementation.
void SetDefaultPresentationURL(const mojo::String& url) override;
- void SetClient(presentation::PresentationServiceClientPtr client) override;
+ void SetClient(mojom::PresentationServiceClientPtr client) override;
void ListenForScreenAvailability(const mojo::String& url) override;
void StopListeningForScreenAvailability(const mojo::String& url) override;
void StartSession(
@@ -159,18 +161,18 @@ class CONTENT_EXPORT PresentationServiceImpl
const mojo::String& presentation_url,
const mojo::String& presentation_id,
const NewSessionMojoCallback& callback) override;
- void SendSessionMessage(presentation::PresentationSessionInfoPtr session_info,
- presentation::SessionMessagePtr session_message,
+ void SendSessionMessage(mojom::PresentationSessionInfoPtr session_info,
+ mojom::SessionMessagePtr session_message,
const SendMessageMojoCallback& callback) override;
void CloseConnection(const mojo::String& presentation_url,
const mojo::String& presentation_id) override;
void Terminate(const mojo::String& presentation_url,
const mojo::String& presentation_id) override;
void ListenForSessionMessages(
- presentation::PresentationSessionInfoPtr session) override;
+ mojom::PresentationSessionInfoPtr session) override;
// Creates a binding between this object and |request|.
- void Bind(mojo::InterfaceRequest<presentation::PresentationService> request);
+ void Bind(mojo::InterfaceRequest<mojom::PresentationService> request);
// WebContentsObserver override.
void DidNavigateAnyFrame(
@@ -194,8 +196,8 @@ class CONTENT_EXPORT PresentationServiceImpl
// Returns true if the callback was found.
bool RunAndEraseJoinSessionMojoCallback(
int request_session_id,
- presentation::PresentationSessionInfoPtr session,
- presentation::PresentationErrorPtr error);
+ mojom::PresentationSessionInfoPtr session,
+ mojom::PresentationErrorPtr error);
// Removes all listeners and resets default presentation URL on this instance
// and informs the PresentationServiceDelegate of such.
@@ -237,8 +239,9 @@ class CONTENT_EXPORT PresentationServiceImpl
// Invoked by the embedder's PresentationServiceDelegate when a
// PresentationConnection's state has changed.
- void OnConnectionStateChanged(const PresentationSessionInfo& connection,
- PresentationConnectionState state);
+ void OnConnectionStateChanged(
+ const PresentationSessionInfo& connection,
+ const PresentationConnectionStateChangeInfo& info);
// Returns true if this object is associated with |render_frame_host|.
bool FrameMatches(content::RenderFrameHost* render_frame_host) const;
@@ -249,7 +252,7 @@ class CONTENT_EXPORT PresentationServiceImpl
// Proxy to the PresentationServiceClient to send results (e.g., screen
// availability) to.
- presentation::PresentationServiceClientPtr client_;
+ mojom::PresentationServiceClientPtr client_;
std::string default_presentation_url_;
@@ -268,7 +271,7 @@ class CONTENT_EXPORT PresentationServiceImpl
// RAII binding of |this| to an Presentation interface request.
// The binding is removed when binding_ is cleared or goes out of scope.
- scoped_ptr<mojo::Binding<presentation::PresentationService>> binding_;
+ scoped_ptr<mojo::Binding<mojom::PresentationService>> binding_;
// There can be only one send message request at a time.
scoped_ptr<SendMessageMojoCallback> send_message_callback_;
diff --git a/chromium/content/browser/presentation/presentation_service_impl_unittest.cc b/chromium/content/browser/presentation/presentation_service_impl_unittest.cc
index cc98878e95c..e25190bd803 100644
--- a/chromium/content/browser/presentation/presentation_service_impl_unittest.cc
+++ b/chromium/content/browser/presentation/presentation_service_impl_unittest.cc
@@ -45,18 +45,15 @@ MATCHER_P(Equals, expected, "") {
const char *const kPresentationId = "presentationId";
const char *const kPresentationUrl = "http://foo.com/index.html";
-bool ArePresentationSessionMessagesEqual(
- const presentation::SessionMessage* expected,
- const presentation::SessionMessage* actual) {
+bool ArePresentationSessionMessagesEqual(const mojom::SessionMessage* expected,
+ const mojom::SessionMessage* actual) {
return expected->type == actual->type &&
expected->message == actual->message &&
expected->data.Equals(actual->data);
}
-void DoNothing(
- presentation::PresentationSessionInfoPtr info,
- presentation::PresentationErrorPtr error) {
-}
+void DoNothing(mojom::PresentationSessionInfoPtr info,
+ mojom::PresentationErrorPtr error) {}
} // namespace
@@ -149,38 +146,47 @@ class MockPresentationServiceDelegate : public PresentationServiceDelegate {
bool screen_availability_listening_supported_ = true;
};
-class MockPresentationServiceClient :
- public presentation::PresentationServiceClient {
+class MockPresentationServiceClient : public mojom::PresentationServiceClient {
public:
MOCK_METHOD2(OnScreenAvailabilityUpdated,
void(const mojo::String& url, bool available));
void OnConnectionStateChanged(
- presentation::PresentationSessionInfoPtr connection,
- presentation::PresentationConnectionState new_state) override {
+ mojom::PresentationSessionInfoPtr connection,
+ mojom::PresentationConnectionState new_state) override {
OnConnectionStateChanged(*connection, new_state);
}
MOCK_METHOD2(OnConnectionStateChanged,
- void(const presentation::PresentationSessionInfo& connection,
- presentation::PresentationConnectionState new_state));
+ void(const mojom::PresentationSessionInfo& connection,
+ mojom::PresentationConnectionState new_state));
+
+ void OnConnectionClosed(mojom::PresentationSessionInfoPtr connection,
+ mojom::PresentationConnectionCloseReason reason,
+ const mojo::String& message) override {
+ OnConnectionClosed(*connection, reason, message);
+ }
+ MOCK_METHOD3(OnConnectionClosed,
+ void(const mojom::PresentationSessionInfo& connection,
+ mojom::PresentationConnectionCloseReason reason,
+ const mojo::String& message));
MOCK_METHOD1(OnScreenAvailabilityNotSupported, void(const mojo::String& url));
void OnSessionMessagesReceived(
- presentation::PresentationSessionInfoPtr session_info,
- mojo::Array<presentation::SessionMessagePtr> messages) override {
+ mojom::PresentationSessionInfoPtr session_info,
+ mojo::Array<mojom::SessionMessagePtr> messages) override {
messages_received_ = std::move(messages);
MessagesReceived();
}
MOCK_METHOD0(MessagesReceived, void());
void OnDefaultSessionStarted(
- presentation::PresentationSessionInfoPtr session_info) override {
+ mojom::PresentationSessionInfoPtr session_info) override {
OnDefaultSessionStarted(*session_info);
}
MOCK_METHOD1(OnDefaultSessionStarted,
- void(const presentation::PresentationSessionInfo& session_info));
+ void(const mojom::PresentationSessionInfo& session_info));
- mojo::Array<presentation::SessionMessagePtr> messages_received_;
+ mojo::Array<mojom::SessionMessagePtr> messages_received_;
};
class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
@@ -196,10 +202,9 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
contents()->GetMainFrame(), contents(), &mock_delegate_));
service_impl_->Bind(std::move(request));
- presentation::PresentationServiceClientPtr client_ptr;
- client_binding_.reset(
- new mojo::Binding<presentation::PresentationServiceClient>(
- &mock_client_, mojo::GetProxy(&client_ptr)));
+ mojom::PresentationServiceClientPtr client_ptr;
+ client_binding_.reset(new mojo::Binding<mojom::PresentationServiceClient>(
+ &mock_client_, mojo::GetProxy(&client_ptr)));
service_impl_->SetClient(std::move(client_ptr));
}
@@ -269,17 +274,16 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
}
void ExpectNewSessionMojoCallbackSuccess(
- presentation::PresentationSessionInfoPtr info,
- presentation::PresentationErrorPtr error) {
+ mojom::PresentationSessionInfoPtr info,
+ mojom::PresentationErrorPtr error) {
EXPECT_FALSE(info.is_null());
EXPECT_TRUE(error.is_null());
if (!run_loop_quit_closure_.is_null())
run_loop_quit_closure_.Run();
}
- void ExpectNewSessionMojoCallbackError(
- presentation::PresentationSessionInfoPtr info,
- presentation::PresentationErrorPtr error) {
+ void ExpectNewSessionMojoCallbackError(mojom::PresentationSessionInfoPtr info,
+ mojom::PresentationErrorPtr error) {
EXPECT_TRUE(info.is_null());
EXPECT_FALSE(error.is_null());
if (!run_loop_quit_closure_.is_null())
@@ -287,8 +291,8 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
}
void ExpectSessionMessages(
- const mojo::Array<presentation::SessionMessagePtr>& expected_msgs,
- const mojo::Array<presentation::SessionMessagePtr>& actual_msgs) {
+ const mojo::Array<mojom::SessionMessagePtr>& expected_msgs,
+ const mojo::Array<mojom::SessionMessagePtr>& actual_msgs) {
EXPECT_EQ(expected_msgs.size(), actual_msgs.size());
for (size_t i = 0; i < actual_msgs.size(); ++i) {
EXPECT_TRUE(ArePresentationSessionMessagesEqual(expected_msgs[i].get(),
@@ -306,18 +310,16 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
void RunListenForSessionMessages(const std::string& text_msg,
const std::vector<uint8_t>& binary_data,
bool pass_ownership) {
- mojo::Array<presentation::SessionMessagePtr> expected_msgs(2);
- expected_msgs[0] = presentation::SessionMessage::New();
- expected_msgs[0]->type =
- presentation::PresentationMessageType::PRESENTATION_MESSAGE_TYPE_TEXT;
+ mojo::Array<mojom::SessionMessagePtr> expected_msgs(2);
+ expected_msgs[0] = mojom::SessionMessage::New();
+ expected_msgs[0]->type = mojom::PresentationMessageType::TEXT;
expected_msgs[0]->message = text_msg;
- expected_msgs[1] = presentation::SessionMessage::New();
- expected_msgs[1]->type = presentation::PresentationMessageType::
- PRESENTATION_MESSAGE_TYPE_ARRAY_BUFFER;
+ expected_msgs[1] = mojom::SessionMessage::New();
+ expected_msgs[1]->type = mojom::PresentationMessageType::ARRAY_BUFFER;
expected_msgs[1]->data = mojo::Array<uint8_t>::From(binary_data);
- presentation::PresentationSessionInfoPtr session(
- presentation::PresentationSessionInfo::New());
+ mojom::PresentationSessionInfoPtr session(
+ mojom::PresentationSessionInfo::New());
session->url = kPresentationUrl;
session->id = kPresentationId;
@@ -342,7 +344,7 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
message->data.reset(new std::vector<uint8_t>(binary_data));
messages.push_back(std::move(message));
- std::vector<presentation::SessionMessagePtr> actual_msgs;
+ std::vector<mojom::SessionMessagePtr> actual_msgs;
{
base::RunLoop run_loop;
EXPECT_CALL(mock_client_, MessagesReceived())
@@ -356,11 +358,10 @@ class PresentationServiceImplTest : public RenderViewHostImplTestHarness {
MockPresentationServiceDelegate mock_delegate_;
scoped_ptr<PresentationServiceImpl> service_impl_;
- mojo::InterfacePtr<presentation::PresentationService> service_ptr_;
+ mojo::InterfacePtr<mojom::PresentationService> service_ptr_;
MockPresentationServiceClient mock_client_;
- scoped_ptr<mojo::Binding<presentation::PresentationServiceClient>>
- client_binding_;
+ scoped_ptr<mojo::Binding<mojom::PresentationServiceClient>> client_binding_;
base::Closure run_loop_quit_closure_;
int default_session_started_count_;
@@ -451,7 +452,7 @@ TEST_F(PresentationServiceImplTest, SetDefaultPresentationUrl) {
service_impl_->SetDefaultPresentationURL(url2);
EXPECT_EQ(url2, service_impl_->default_presentation_url_);
- presentation::PresentationSessionInfo session_info;
+ mojom::PresentationSessionInfo session_info;
session_info.url = url2;
session_info.id = kPresentationId;
base::RunLoop run_loop;
@@ -470,17 +471,51 @@ TEST_F(PresentationServiceImplTest, ListenForConnectionStateChange) {
service_impl_->ListenForConnectionStateChange(connection);
// Trigger state change. It should be propagated back up to |mock_client_|.
- presentation::PresentationSessionInfo presentation_connection;
+ mojom::PresentationSessionInfo presentation_connection;
presentation_connection.url = kPresentationUrl;
presentation_connection.id = kPresentationId;
- base::RunLoop run_loop;
- EXPECT_CALL(mock_client_,
- OnConnectionStateChanged(
- Equals(presentation_connection),
- presentation::PRESENTATION_CONNECTION_STATE_CLOSED))
- .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
- state_changed_cb.Run(content::PRESENTATION_CONNECTION_STATE_CLOSED);
- run_loop.Run();
+ {
+ base::RunLoop run_loop;
+ EXPECT_CALL(mock_client_,
+ OnConnectionStateChanged(
+ Equals(presentation_connection),
+ mojom::PresentationConnectionState::TERMINATED))
+ .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
+ state_changed_cb.Run(PresentationConnectionStateChangeInfo(
+ PRESENTATION_CONNECTION_STATE_TERMINATED));
+ run_loop.Run();
+ }
+}
+
+TEST_F(PresentationServiceImplTest, ListenForConnectionClose) {
+ content::PresentationSessionInfo connection(kPresentationUrl,
+ kPresentationId);
+ content::PresentationConnectionStateChangedCallback state_changed_cb;
+ EXPECT_CALL(mock_delegate_, ListenForConnectionStateChange(_, _, _, _))
+ .WillOnce(SaveArg<3>(&state_changed_cb));
+ service_impl_->ListenForConnectionStateChange(connection);
+
+ // Trigger connection close. It should be propagated back up to
+ // |mock_client_|.
+ mojom::PresentationSessionInfo presentation_connection;
+ presentation_connection.url = kPresentationUrl;
+ presentation_connection.id = kPresentationId;
+ {
+ base::RunLoop run_loop;
+ PresentationConnectionStateChangeInfo closed_info(
+ PRESENTATION_CONNECTION_STATE_CLOSED);
+ closed_info.close_reason = PRESENTATION_CONNECTION_CLOSE_REASON_WENT_AWAY;
+ closed_info.message = "Foo";
+
+ EXPECT_CALL(
+ mock_client_,
+ OnConnectionClosed(Equals(presentation_connection),
+ mojom::PresentationConnectionCloseReason::WENT_AWAY,
+ mojo::String("Foo")))
+ .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
+ state_changed_cb.Run(closed_info);
+ run_loop.Run();
+ }
}
TEST_F(PresentationServiceImplTest, SetSameDefaultPresentationUrl) {
@@ -630,14 +665,12 @@ TEST_F(PresentationServiceImplTest, StartSessionInProgress) {
TEST_F(PresentationServiceImplTest, SendStringMessage) {
std::string message("Test presentation session message");
- presentation::PresentationSessionInfoPtr session(
- presentation::PresentationSessionInfo::New());
+ mojom::PresentationSessionInfoPtr session(
+ mojom::PresentationSessionInfo::New());
session->url = kPresentationUrl;
session->id = kPresentationId;
- presentation::SessionMessagePtr message_request(
- presentation::SessionMessage::New());
- message_request->type = presentation::PresentationMessageType::
- PRESENTATION_MESSAGE_TYPE_TEXT;
+ mojom::SessionMessagePtr message_request(mojom::SessionMessage::New());
+ message_request->type = mojom::PresentationMessageType::TEXT;
message_request->message = message;
service_ptr_->SendSessionMessage(
std::move(session), std::move(message_request),
@@ -669,14 +702,12 @@ TEST_F(PresentationServiceImplTest, SendArrayBuffer) {
std::vector<uint8_t> data;
data.assign(buffer, buffer + sizeof(buffer));
- presentation::PresentationSessionInfoPtr session(
- presentation::PresentationSessionInfo::New());
+ mojom::PresentationSessionInfoPtr session(
+ mojom::PresentationSessionInfo::New());
session->url = kPresentationUrl;
session->id = kPresentationId;
- presentation::SessionMessagePtr message_request(
- presentation::SessionMessage::New());
- message_request->type = presentation::PresentationMessageType::
- PRESENTATION_MESSAGE_TYPE_ARRAY_BUFFER;
+ mojom::SessionMessagePtr message_request(mojom::SessionMessage::New());
+ message_request->type = mojom::PresentationMessageType::ARRAY_BUFFER;
message_request->data = mojo::Array<uint8_t>::From(data);
service_ptr_->SendSessionMessage(
std::move(session), std::move(message_request),
@@ -714,14 +745,12 @@ TEST_F(PresentationServiceImplTest, SendArrayBufferWithExceedingLimit) {
std::vector<uint8_t> data;
data.assign(buffer, buffer + sizeof(buffer));
- presentation::PresentationSessionInfoPtr session(
- presentation::PresentationSessionInfo::New());
+ mojom::PresentationSessionInfoPtr session(
+ mojom::PresentationSessionInfo::New());
session->url = kPresentationUrl;
session->id = kPresentationId;
- presentation::SessionMessagePtr message_request(
- presentation::SessionMessage::New());
- message_request->type = presentation::PresentationMessageType::
- PRESENTATION_MESSAGE_TYPE_ARRAY_BUFFER;
+ mojom::SessionMessagePtr message_request(mojom::SessionMessage::New());
+ message_request->type = mojom::PresentationMessageType::ARRAY_BUFFER;
message_request->data = mojo::Array<uint8_t>::From(data);
service_ptr_->SendSessionMessage(
std::move(session), std::move(message_request),
@@ -746,14 +775,12 @@ TEST_F(PresentationServiceImplTest, SendBlobData) {
std::vector<uint8_t> data;
data.assign(buffer, buffer + sizeof(buffer));
- presentation::PresentationSessionInfoPtr session(
- presentation::PresentationSessionInfo::New());
+ mojom::PresentationSessionInfoPtr session(
+ mojom::PresentationSessionInfo::New());
session->url = kPresentationUrl;
session->id = kPresentationId;
- presentation::SessionMessagePtr message_request(
- presentation::SessionMessage::New());
- message_request->type =
- presentation::PresentationMessageType::PRESENTATION_MESSAGE_TYPE_BLOB;
+ mojom::SessionMessagePtr message_request(mojom::SessionMessage::New());
+ message_request->type = mojom::PresentationMessageType::BLOB;
message_request->data = mojo::Array<uint8_t>::From(data);
service_ptr_->SendSessionMessage(
std::move(session), std::move(message_request),
@@ -808,10 +835,12 @@ TEST_F(PresentationServiceImplTest, MaxPendingJoinSessionRequests) {
TEST_F(PresentationServiceImplTest, ScreenAvailabilityNotSupported) {
mock_delegate_.set_screen_availability_listening_supported(false);
+ base::RunLoop run_loop;
EXPECT_CALL(mock_client_,
- OnScreenAvailabilityNotSupported(Eq(kPresentationUrl)));
-
+ OnScreenAvailabilityNotSupported(Eq(kPresentationUrl)))
+ .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit));
ListenForScreenAvailabilityAndWait(kPresentationUrl, false);
+ run_loop.Run();
}
} // namespace content
diff --git a/chromium/content/browser/presentation/presentation_type_converters.cc b/chromium/content/browser/presentation/presentation_type_converters.cc
index cd649976d5f..6343e979fb5 100644
--- a/chromium/content/browser/presentation/presentation_type_converters.cc
+++ b/chromium/content/browser/presentation/presentation_type_converters.cc
@@ -8,36 +8,51 @@
namespace content {
-presentation::PresentationErrorType PresentationErrorTypeToMojo(
+mojom::PresentationErrorType PresentationErrorTypeToMojo(
content::PresentationErrorType input) {
switch (input) {
case content::PRESENTATION_ERROR_NO_AVAILABLE_SCREENS:
- return presentation::PRESENTATION_ERROR_TYPE_NO_AVAILABLE_SCREENS;
+ return mojom::PresentationErrorType::NO_AVAILABLE_SCREENS;
case content::PRESENTATION_ERROR_SESSION_REQUEST_CANCELLED:
- return presentation::PRESENTATION_ERROR_TYPE_SESSION_REQUEST_CANCELLED;
+ return mojom::PresentationErrorType::SESSION_REQUEST_CANCELLED;
case content::PRESENTATION_ERROR_NO_PRESENTATION_FOUND:
- return presentation::PRESENTATION_ERROR_TYPE_NO_PRESENTATION_FOUND;
+ return mojom::PresentationErrorType::NO_PRESENTATION_FOUND;
case content::PRESENTATION_ERROR_UNKNOWN:
- return presentation::PRESENTATION_ERROR_TYPE_UNKNOWN;
+ return mojom::PresentationErrorType::UNKNOWN;
}
NOTREACHED();
- return presentation::PRESENTATION_ERROR_TYPE_UNKNOWN;
+ return mojom::PresentationErrorType::UNKNOWN;
}
-presentation::PresentationConnectionState PresentationConnectionStateToMojo(
+mojom::PresentationConnectionState PresentationConnectionStateToMojo(
content::PresentationConnectionState state) {
switch (state) {
case content::PRESENTATION_CONNECTION_STATE_CONNECTING:
- return presentation::PRESENTATION_CONNECTION_STATE_CONNECTING;
+ return mojom::PresentationConnectionState::CONNECTING;
case content::PRESENTATION_CONNECTION_STATE_CONNECTED:
- return presentation::PRESENTATION_CONNECTION_STATE_CONNECTED;
+ return mojom::PresentationConnectionState::CONNECTED;
case content::PRESENTATION_CONNECTION_STATE_CLOSED:
- return presentation::PRESENTATION_CONNECTION_STATE_CLOSED;
+ return mojom::PresentationConnectionState::CLOSED;
case content::PRESENTATION_CONNECTION_STATE_TERMINATED:
- return presentation::PRESENTATION_CONNECTION_STATE_TERMINATED;
+ return mojom::PresentationConnectionState::TERMINATED;
}
NOTREACHED();
- return presentation::PRESENTATION_CONNECTION_STATE_TERMINATED;
+ return mojom::PresentationConnectionState::TERMINATED;
+}
+
+mojom::PresentationConnectionCloseReason
+PresentationConnectionCloseReasonToMojo(
+ content::PresentationConnectionCloseReason reason) {
+ switch (reason) {
+ case content::PRESENTATION_CONNECTION_CLOSE_REASON_CONNECTION_ERROR:
+ return mojom::PresentationConnectionCloseReason::CONNECTION_ERROR;
+ case content::PRESENTATION_CONNECTION_CLOSE_REASON_CLOSED:
+ return mojom::PresentationConnectionCloseReason::CLOSED;
+ case content::PRESENTATION_CONNECTION_CLOSE_REASON_WENT_AWAY:
+ return mojom::PresentationConnectionCloseReason::WENT_AWAY;
+ }
+ NOTREACHED();
+ return mojom::PresentationConnectionCloseReason::CONNECTION_ERROR;
}
} // namespace content
diff --git a/chromium/content/browser/presentation/presentation_type_converters.h b/chromium/content/browser/presentation/presentation_type_converters.h
index c707f4fa5e8..e35fbf6abd0 100644
--- a/chromium/content/browser/presentation/presentation_type_converters.h
+++ b/chromium/content/browser/presentation/presentation_type_converters.h
@@ -11,23 +11,26 @@
namespace content {
-CONTENT_EXPORT presentation::PresentationErrorType PresentationErrorTypeToMojo(
+CONTENT_EXPORT mojom::PresentationErrorType PresentationErrorTypeToMojo(
PresentationErrorType input);
-CONTENT_EXPORT presentation::PresentationConnectionState
+CONTENT_EXPORT mojom::PresentationConnectionState
PresentationConnectionStateToMojo(PresentationConnectionState state);
+CONTENT_EXPORT mojom::PresentationConnectionCloseReason
+PresentationConnectionCloseReasonToMojo(
+ PresentationConnectionCloseReason reason);
} // namespace content
namespace mojo {
template <>
-struct TypeConverter<presentation::PresentationSessionInfoPtr,
+struct TypeConverter<content::mojom::PresentationSessionInfoPtr,
content::PresentationSessionInfo> {
- static presentation::PresentationSessionInfoPtr Convert(
+ static content::mojom::PresentationSessionInfoPtr Convert(
const content::PresentationSessionInfo& input) {
- presentation::PresentationSessionInfoPtr output(
- presentation::PresentationSessionInfo::New());
+ content::mojom::PresentationSessionInfoPtr output(
+ content::mojom::PresentationSessionInfo::New());
output->url = input.presentation_url;
output->id = input.presentation_id;
return output;
@@ -36,20 +39,20 @@ struct TypeConverter<presentation::PresentationSessionInfoPtr,
template <>
struct TypeConverter<content::PresentationSessionInfo,
- presentation::PresentationSessionInfoPtr> {
+ content::mojom::PresentationSessionInfoPtr> {
static content::PresentationSessionInfo Convert(
- const presentation::PresentationSessionInfoPtr& input) {
+ const content::mojom::PresentationSessionInfoPtr& input) {
return content::PresentationSessionInfo(input->url, input->id);
}
};
template <>
-struct TypeConverter<presentation::PresentationErrorPtr,
+struct TypeConverter<content::mojom::PresentationErrorPtr,
content::PresentationError> {
- static presentation::PresentationErrorPtr Convert(
+ static content::mojom::PresentationErrorPtr Convert(
const content::PresentationError& input) {
- presentation::PresentationErrorPtr output(
- presentation::PresentationError::New());
+ content::mojom::PresentationErrorPtr output(
+ content::mojom::PresentationError::New());
output->error_type = PresentationErrorTypeToMojo(input.error_type);
output->message = input.message;
return output;
diff --git a/chromium/content/browser/presentation/presentation_type_converters_unittest.cc b/chromium/content/browser/presentation/presentation_type_converters_unittest.cc
index 3107aff3d03..f62c320eb19 100644
--- a/chromium/content/browser/presentation/presentation_type_converters_unittest.cc
+++ b/chromium/content/browser/presentation/presentation_type_converters_unittest.cc
@@ -13,8 +13,8 @@ TEST(PresentationTypeConvertersTest, PresentationSessionInfo) {
std::string presentation_url("http://fooUrl");
std::string presentation_id("presentationId");
PresentationSessionInfo session(presentation_url, presentation_id);
- presentation::PresentationSessionInfoPtr session_mojo(
- presentation::PresentationSessionInfo::From(session));
+ mojom::PresentationSessionInfoPtr session_mojo(
+ mojom::PresentationSessionInfo::From(session));
EXPECT_FALSE(session_mojo.is_null());
EXPECT_EQ(presentation_url, session_mojo->url);
EXPECT_EQ(presentation_id, session_mojo->id);
@@ -23,10 +23,9 @@ TEST(PresentationTypeConvertersTest, PresentationSessionInfo) {
TEST(PresentationTypeConvertersTest, PresentationError) {
std::string message("Error message");
PresentationError error(PRESENTATION_ERROR_NO_AVAILABLE_SCREENS, message);
- presentation::PresentationErrorPtr error_mojo(
- presentation::PresentationError::From(error));
+ mojom::PresentationErrorPtr error_mojo(mojom::PresentationError::From(error));
EXPECT_FALSE(error_mojo.is_null());
- EXPECT_EQ(presentation::PRESENTATION_ERROR_TYPE_NO_AVAILABLE_SCREENS,
+ EXPECT_EQ(mojom::PresentationErrorType::NO_AVAILABLE_SCREENS,
error_mojo->error_type);
EXPECT_EQ(message, error_mojo->message);
}
diff --git a/chromium/content/browser/push_messaging/push_messaging_message_filter.cc b/chromium/content/browser/push_messaging/push_messaging_message_filter.cc
index 41668e37382..26184cf0867 100644
--- a/chromium/content/browser/push_messaging/push_messaging_message_filter.cc
+++ b/chromium/content/browser/push_messaging/push_messaging_message_filter.cc
@@ -5,9 +5,11 @@
#include "content/browser/push_messaging/push_messaging_message_filter.h"
#include <string>
+#include <vector>
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/command_line.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/metrics/histogram.h"
@@ -26,6 +28,7 @@
#include "content/public/browser/web_contents.h"
#include "content/public/common/child_process_host.h"
#include "content/public/common/console_message_level.h"
+#include "content/public/common/content_switches.h"
#include "content/public/common/push_messaging_status.h"
#include "third_party/WebKit/public/platform/modules/push_messaging/WebPushPermissionStatus.h"
@@ -147,7 +150,7 @@ class PushMessagingMessageFilter::Core {
// Private Register methods on UI thread -------------------------------------
void DidRequestPermissionInIncognito(const RegisterData& data,
- PermissionStatus status);
+ blink::mojom::PermissionStatus status);
void DidRegister(const RegisterData& data,
const std::string& push_registration_id,
@@ -249,8 +252,7 @@ bool PushMessagingMessageFilter::OnMessageReceived(
void PushMessagingMessageFilter::OnSubscribeFromDocument(
int render_frame_id,
int request_id,
- const std::string& sender_id,
- bool user_visible,
+ const PushSubscriptionOptions& options,
int64_t service_worker_registration_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// TODO(mvanouwerkerk): Validate arguments?
@@ -258,7 +260,7 @@ void PushMessagingMessageFilter::OnSubscribeFromDocument(
data.request_id = request_id;
data.service_worker_registration_id = service_worker_registration_id;
data.render_frame_id = render_frame_id;
- data.user_visible = user_visible;
+ data.user_visible = options.user_visible_only;
ServiceWorkerRegistration* service_worker_registration =
service_worker_context_->GetLiveRegistration(
@@ -272,20 +274,20 @@ void PushMessagingMessageFilter::OnSubscribeFromDocument(
service_worker_context_->StoreRegistrationUserData(
service_worker_registration_id, data.requesting_origin,
- kPushSenderIdServiceWorkerKey, sender_id,
- base::Bind(&PushMessagingMessageFilter::DidPersistSenderId,
- weak_factory_io_to_io_.GetWeakPtr(), data, sender_id));
+ kPushSenderIdServiceWorkerKey, options.sender_info,
+ base::Bind(&PushMessagingMessageFilter::DidPersistSenderInfo,
+ weak_factory_io_to_io_.GetWeakPtr(), data, options));
}
void PushMessagingMessageFilter::OnSubscribeFromWorker(
int request_id,
int64_t service_worker_registration_id,
- bool user_visible) {
+ const PushSubscriptionOptions& options) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
RegisterData data;
data.request_id = request_id;
data.service_worker_registration_id = service_worker_registration_id;
- data.user_visible = user_visible;
+ data.user_visible = options.user_visible_only;
ServiceWorkerRegistration* service_worker_registration =
service_worker_context_->GetLiveRegistration(
@@ -296,34 +298,43 @@ void PushMessagingMessageFilter::OnSubscribeFromWorker(
}
data.requesting_origin = service_worker_registration->pattern().GetOrigin();
- // This sender_id will be ignored; instead it will be fetched from storage.
- CheckForExistingRegistration(data, std::string() /* sender_id */);
+ if (!options.sender_info.empty()) {
+ service_worker_context_->StoreRegistrationUserData(
+ service_worker_registration_id, data.requesting_origin,
+ kPushSenderIdServiceWorkerKey, options.sender_info,
+ base::Bind(&PushMessagingMessageFilter::DidPersistSenderInfo,
+ weak_factory_io_to_io_.GetWeakPtr(), data, options));
+ } else {
+ // If there is a sender_info in the subscription options, it will be used,
+ // otherwise the registration sender_info will be used.
+ CheckForExistingRegistration(data, options);
+ }
}
-void PushMessagingMessageFilter::DidPersistSenderId(
+void PushMessagingMessageFilter::DidPersistSenderInfo(
const RegisterData& data,
- const std::string& sender_id,
+ const PushSubscriptionOptions& options,
ServiceWorkerStatusCode service_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (service_worker_status != SERVICE_WORKER_OK)
SendSubscriptionError(data, PUSH_REGISTRATION_STATUS_STORAGE_ERROR);
else
- CheckForExistingRegistration(data, sender_id);
+ CheckForExistingRegistration(data, options);
}
void PushMessagingMessageFilter::CheckForExistingRegistration(
const RegisterData& data,
- const std::string& sender_id) {
+ const PushSubscriptionOptions& options) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
service_worker_context_->GetRegistrationUserData(
data.service_worker_registration_id, kPushRegistrationIdServiceWorkerKey,
base::Bind(&PushMessagingMessageFilter::DidCheckForExistingRegistration,
- weak_factory_io_to_io_.GetWeakPtr(), data, sender_id));
+ weak_factory_io_to_io_.GetWeakPtr(), data, options));
}
void PushMessagingMessageFilter::DidCheckForExistingRegistration(
const RegisterData& data,
- const std::string& sender_id,
+ const PushSubscriptionOptions& options,
const std::string& push_registration_id,
ServiceWorkerStatusCode service_worker_status) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -344,11 +355,11 @@ void PushMessagingMessageFilter::DidCheckForExistingRegistration(
// service_worker_status != SERVICE_WORKER_ERROR_NOT_FOUND instead of
// attempting to do a fresh registration?
// https://w3c.github.io/push-api/#widl-PushRegistrationManager-register-Promise-PushRegistration
- if (data.FromDocument()) {
+ if (!options.sender_info.empty()) {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&Core::RegisterOnUI, base::Unretained(ui_core_.get()), data,
- sender_id));
+ options.sender_info));
} else {
service_worker_context_->GetRegistrationUserData(
data.service_worker_registration_id, kPushSenderIdServiceWorkerKey,
@@ -391,7 +402,7 @@ void PushMessagingMessageFilter::DidGetSenderIdFromStorage(
void PushMessagingMessageFilter::Core::RegisterOnUI(
const PushMessagingMessageFilter::RegisterData& data,
- const std::string& sender_id) {
+ const std::string& sender_info) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
PushMessagingService* push_service = service();
if (!push_service) {
@@ -427,7 +438,7 @@ void PushMessagingMessageFilter::Core::RegisterOnUI(
->GetPermissionManager()
->RequestPermission(
PermissionType::PUSH_MESSAGING, render_frame_host,
- data.requesting_origin, false /* user_gesture */,
+ data.requesting_origin,
base::Bind(&PushMessagingMessageFilter::Core::
DidRequestPermissionInIncognito,
weak_factory_ui_to_ui_.GetWeakPtr(), data));
@@ -437,16 +448,18 @@ void PushMessagingMessageFilter::Core::RegisterOnUI(
return;
}
+ PushSubscriptionOptions options;
+ options.user_visible_only = data.user_visible;
+ options.sender_info = sender_info;
if (data.FromDocument()) {
push_service->SubscribeFromDocument(
- data.requesting_origin, data.service_worker_registration_id, sender_id,
- render_process_id_, data.render_frame_id, data.user_visible,
+ data.requesting_origin, data.service_worker_registration_id,
+ render_process_id_, data.render_frame_id, options,
base::Bind(&Core::DidRegister, weak_factory_ui_to_ui_.GetWeakPtr(),
data));
} else {
push_service->SubscribeFromWorker(
- data.requesting_origin, data.service_worker_registration_id, sender_id,
- data.user_visible,
+ data.requesting_origin, data.service_worker_registration_id, options,
base::Bind(&Core::DidRegister, weak_factory_ui_to_ui_.GetWeakPtr(),
data));
}
@@ -454,10 +467,10 @@ void PushMessagingMessageFilter::Core::RegisterOnUI(
void PushMessagingMessageFilter::Core::DidRequestPermissionInIncognito(
const RegisterData& data,
- PermissionStatus status) {
+ blink::mojom::PermissionStatus status) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// Notification permission should always be denied in incognito.
- DCHECK_EQ(PERMISSION_STATUS_DENIED, status);
+ DCHECK_EQ(blink::mojom::PermissionStatus::DENIED, status);
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&PushMessagingMessageFilter::SendSubscriptionError, io_parent_,
@@ -914,9 +927,8 @@ void PushMessagingMessageFilter::Core::GetPermissionStatusOnUI(
request_id, blink::WebPushError::ErrorTypeNotSupported));
return;
}
- GURL embedding_origin = requesting_origin;
- permission_status = push_service->GetPermissionStatus(
- requesting_origin, embedding_origin, user_visible);
+ permission_status =
+ push_service->GetPermissionStatus(requesting_origin, user_visible);
} else if (is_incognito()) {
// Return prompt, so the website can't detect incognito mode.
permission_status = blink::WebPushPermissionStatusPrompt;
diff --git a/chromium/content/browser/push_messaging/push_messaging_message_filter.h b/chromium/content/browser/push_messaging/push_messaging_message_filter.h
index aba0b348abc..d2db18a39c8 100644
--- a/chromium/content/browser/push_messaging/push_messaging_message_filter.h
+++ b/chromium/content/browser/push_messaging/push_messaging_message_filter.h
@@ -23,6 +23,7 @@ namespace content {
class PushMessagingService;
class ServiceWorkerContextWrapper;
+struct PushSubscriptionOptions;
extern const char kPushSenderIdServiceWorkerKey[];
extern const char kPushRegistrationIdServiceWorkerKey[];
@@ -50,26 +51,25 @@ class PushMessagingMessageFilter : public BrowserMessageFilter {
void OnSubscribeFromDocument(int render_frame_id,
int request_id,
- const std::string& sender_id,
- bool user_visible,
+ const PushSubscriptionOptions& options,
int64_t service_worker_registration_id);
void OnSubscribeFromWorker(int request_id,
int64_t service_worker_registration_id,
- bool user_visible);
+ const PushSubscriptionOptions& options);
- void DidPersistSenderId(const RegisterData& data,
- const std::string& sender_id,
- ServiceWorkerStatusCode service_worker_status);
+ void DidPersistSenderInfo(const RegisterData& data,
+ const PushSubscriptionOptions& options,
+ ServiceWorkerStatusCode service_worker_status);
// sender_id is ignored if data.FromDocument() is false.
void CheckForExistingRegistration(const RegisterData& data,
- const std::string& sender_id);
+ const PushSubscriptionOptions& options);
// sender_id is ignored if data.FromDocument() is false.
void DidCheckForExistingRegistration(
const RegisterData& data,
- const std::string& sender_id,
+ const PushSubscriptionOptions& options,
const std::string& push_registration_id,
ServiceWorkerStatusCode service_worker_status);
diff --git a/chromium/content/browser/push_messaging/push_messaging_router.cc b/chromium/content/browser/push_messaging/push_messaging_router.cc
index bc95216ad07..8e93fe71ece 100644
--- a/chromium/content/browser/push_messaging/push_messaging_router.cc
+++ b/chromium/content/browser/push_messaging/push_messaging_router.cc
@@ -10,10 +10,12 @@
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_storage.h"
+#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_status_code.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/storage_partition.h"
+#include "content/public/common/push_event_payload.h"
namespace content {
@@ -22,6 +24,7 @@ namespace {
void RunDeliverCallback(
const PushMessagingRouter::DeliverMessageCallback& deliver_message_callback,
PushDeliveryStatus delivery_status) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(deliver_message_callback, delivery_status));
@@ -34,7 +37,7 @@ void PushMessagingRouter::DeliverMessage(
BrowserContext* browser_context,
const GURL& origin,
int64_t service_worker_registration_id,
- const std::string& data,
+ const PushEventPayload& payload,
const DeliverMessageCallback& deliver_message_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
StoragePartition* partition =
@@ -45,15 +48,15 @@ void PushMessagingRouter::DeliverMessage(
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&PushMessagingRouter::FindServiceWorkerRegistration, origin,
- service_worker_registration_id, data, deliver_message_callback,
- service_worker_context));
+ service_worker_registration_id, payload,
+ deliver_message_callback, service_worker_context));
}
// static
void PushMessagingRouter::FindServiceWorkerRegistration(
const GURL& origin,
int64_t service_worker_registration_id,
- const std::string& data,
+ const PushEventPayload& payload,
const DeliverMessageCallback& deliver_message_callback,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -62,12 +65,12 @@ void PushMessagingRouter::FindServiceWorkerRegistration(
service_worker_context->FindReadyRegistrationForId(
service_worker_registration_id, origin,
base::Bind(&PushMessagingRouter::FindServiceWorkerRegistrationCallback,
- data, deliver_message_callback));
+ payload, deliver_message_callback));
}
// static
void PushMessagingRouter::FindServiceWorkerRegistrationCallback(
- const std::string& data,
+ const PushEventPayload& payload,
const DeliverMessageCallback& deliver_message_callback,
ServiceWorkerStatusCode service_worker_status,
const scoped_refptr<ServiceWorkerRegistration>&
@@ -87,11 +90,28 @@ void PushMessagingRouter::FindServiceWorkerRegistrationCallback(
// alive until the callback dies. Otherwise the registration could be
// released when this method returns - before the event is delivered to the
// service worker.
- base::Callback<void(ServiceWorkerStatusCode)> dispatch_event_callback =
+ version->RunAfterStartWorker(
+ ServiceWorkerMetrics::EventType::PUSH,
+ base::Bind(&PushMessagingRouter::DeliverMessageToWorker,
+ make_scoped_refptr(version), service_worker_registration,
+ payload, deliver_message_callback),
base::Bind(&PushMessagingRouter::DeliverMessageEnd,
- deliver_message_callback, service_worker_registration);
+ deliver_message_callback, service_worker_registration));
+}
- version->DispatchPushEvent(dispatch_event_callback, data);
+// static
+void PushMessagingRouter::DeliverMessageToWorker(
+ const scoped_refptr<ServiceWorkerVersion>& service_worker,
+ const scoped_refptr<ServiceWorkerRegistration>& service_worker_registration,
+ const PushEventPayload& payload,
+ const DeliverMessageCallback& deliver_message_callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ int request_id = service_worker->StartRequest(
+ ServiceWorkerMetrics::EventType::PUSH,
+ base::Bind(&PushMessagingRouter::DeliverMessageEnd,
+ deliver_message_callback, service_worker_registration));
+ service_worker->DispatchSimpleEvent<ServiceWorkerHostMsg_PushEventFinished>(
+ request_id, ServiceWorkerMsg_PushEvent(request_id, payload));
}
// static
diff --git a/chromium/content/browser/push_messaging/push_messaging_router.h b/chromium/content/browser/push_messaging/push_messaging_router.h
index dae9973de26..64adb8a4330 100644
--- a/chromium/content/browser/push_messaging/push_messaging_router.h
+++ b/chromium/content/browser/push_messaging/push_messaging_router.h
@@ -12,13 +12,16 @@
#include "base/memory/weak_ptr.h"
#include "content/common/service_worker/service_worker_status_code.h"
#include "content/public/common/push_messaging_status.h"
+#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerEventResult.h"
#include "url/gurl.h"
namespace content {
class BrowserContext;
+struct PushEventPayload;
class ServiceWorkerContextWrapper;
class ServiceWorkerRegistration;
+class ServiceWorkerVersion;
class PushMessagingRouter {
public:
@@ -31,7 +34,7 @@ class PushMessagingRouter {
BrowserContext* browser_context,
const GURL& origin,
int64_t service_worker_registration_id,
- const std::string& data,
+ const PushEventPayload& payload,
const DeliverMessageCallback& deliver_message_callback);
private:
@@ -40,7 +43,7 @@ class PushMessagingRouter {
static void FindServiceWorkerRegistration(
const GURL& origin,
int64_t service_worker_registration_id,
- const std::string& data,
+ const PushEventPayload& payload,
const DeliverMessageCallback& deliver_message_callback,
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context);
@@ -48,12 +51,21 @@ class PushMessagingRouter {
// |data| on the Service Worker identified by |service_worker_registration|.
// Must be called on the IO thread.
static void FindServiceWorkerRegistrationCallback(
- const std::string& data,
+ const PushEventPayload& payload,
const DeliverMessageCallback& deliver_message_callback,
ServiceWorkerStatusCode service_worker_status,
const scoped_refptr<ServiceWorkerRegistration>&
service_worker_registration);
+ // Delivers a push message with |data| to a specific |service_worker|. Must be
+ // called on the IO thread, with the the worker running.
+ static void DeliverMessageToWorker(
+ const scoped_refptr<ServiceWorkerVersion>& service_worker,
+ const scoped_refptr<ServiceWorkerRegistration>&
+ service_worker_registration,
+ const PushEventPayload& payload,
+ const DeliverMessageCallback& deliver_message_callback);
+
// Gets called asynchronously after the Service Worker has dispatched the push
// event. Must be called on the IO thread.
static void DeliverMessageEnd(
diff --git a/chromium/content/browser/quota/mock_quota_manager_proxy.cc b/chromium/content/browser/quota/mock_quota_manager_proxy.cc
index a8b955d894c..697577b68b6 100644
--- a/chromium/content/browser/quota/mock_quota_manager_proxy.cc
+++ b/chromium/content/browser/quota/mock_quota_manager_proxy.cc
@@ -36,6 +36,16 @@ void MockQuotaManagerProxy::SimulateQuotaManagerDestroyed() {
}
}
+void MockQuotaManagerProxy::GetUsageAndQuota(
+ base::SequencedTaskRunner* original_task_runner,
+ const GURL& origin,
+ StorageType type,
+ const QuotaManager::GetUsageAndQuotaCallback& callback) {
+ if (mock_manager()) {
+ mock_manager()->GetUsageAndQuota(origin, type, callback);
+ }
+}
+
void MockQuotaManagerProxy::NotifyStorageAccessed(
QuotaClient::ID client_id, const GURL& origin, StorageType type) {
++storage_accessed_count_;
diff --git a/chromium/content/browser/quota/mock_quota_manager_proxy.h b/chromium/content/browser/quota/mock_quota_manager_proxy.h
index 118761de5c9..e550a9d9de3 100644
--- a/chromium/content/browser/quota/mock_quota_manager_proxy.h
+++ b/chromium/content/browser/quota/mock_quota_manager_proxy.h
@@ -41,7 +41,7 @@ class MockQuotaManagerProxy : public QuotaManagerProxy {
base::SequencedTaskRunner* original_task_runner,
const GURL& origin,
StorageType type,
- const QuotaManager::GetUsageAndQuotaCallback& callback) override {}
+ const QuotaManager::GetUsageAndQuotaCallback& callback) override;
// Validates the |client_id| and updates the internal access count
// which can be accessed via notify_storage_accessed_count().
diff --git a/chromium/content/browser/quota/quota_backend_impl_unittest.cc b/chromium/content/browser/quota/quota_backend_impl_unittest.cc
index 516cab3e1bd..5dfa037185f 100644
--- a/chromium/content/browser/quota/quota_backend_impl_unittest.cc
+++ b/chromium/content/browser/quota/quota_backend_impl_unittest.cc
@@ -10,6 +10,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/thread_task_runner_handle.h"
#include "storage/browser/fileapi/file_system_usage_cache.h"
#include "storage/browser/fileapi/obfuscated_file_util.h"
diff --git a/chromium/content/browser/quota/quota_manager_unittest.cc b/chromium/content/browser/quota/quota_manager_unittest.cc
index 80889ba8b30..665acd953b7 100644
--- a/chromium/content/browser/quota/quota_manager_unittest.cc
+++ b/chromium/content/browser/quota/quota_manager_unittest.cc
@@ -67,10 +67,17 @@ const int kPerHostTemporaryPortion = QuotaManager::kPerHostTemporaryPortion;
const GURL kTestEvictionOrigin = GURL("http://test.eviction.policy/result");
// Returns a deterministic value for the amount of available disk space.
-int64_t GetAvailableDiskSpaceForTest(const base::FilePath&) {
+int64_t GetAvailableDiskSpaceForTest() {
return kAvailableSpaceForApp + kMinimumPreserveForSystem;
}
+bool GetVolumeInfoForTests(const base::FilePath&,
+ uint64_t* available, uint64_t* total) {
+ *available = static_cast<uint64_t>(GetAvailableDiskSpaceForTest());
+ *total = *available * 2;
+ return true;
+}
+
class TestEvictionPolicy : public storage::QuotaEvictionPolicy {
public:
TestEvictionPolicy() {}
@@ -122,7 +129,7 @@ class QuotaManagerTest : public testing::Test {
// Don't (automatically) start the eviction for testing.
quota_manager_->eviction_disabled_ = true;
// Don't query the hard disk for remaining capacity.
- quota_manager_->get_disk_space_fn_ = &GetAvailableDiskSpaceForTest;
+ quota_manager_->get_volume_info_fn_= &GetVolumeInfoForTests;
additional_callback_count_ = 0;
}
@@ -670,7 +677,7 @@ TEST_F(QuotaManagerTest, GetUsage_MultipleClients) {
QuotaClient::kDatabase));
const int64_t kTempQuotaBase =
- GetAvailableDiskSpaceForTest(base::FilePath()) / kPerHostTemporaryPortion;
+ GetAvailableDiskSpaceForTest() / kPerHostTemporaryPortion;
GetUsageAndQuotaForWebApps(GURL("http://foo.com/"), kTemp);
base::RunLoop().RunUntilIdle();
diff --git a/chromium/content/browser/quota/quota_reservation_manager_unittest.cc b/chromium/content/browser/quota/quota_reservation_manager_unittest.cc
index d2588e168e7..2a9d2e44582 100644
--- a/chromium/content/browser/quota/quota_reservation_manager_unittest.cc
+++ b/chromium/content/browser/quota/quota_reservation_manager_unittest.cc
@@ -12,6 +12,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/location.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
diff --git a/chromium/content/browser/quota/quota_temporary_storage_evictor_unittest.cc b/chromium/content/browser/quota/quota_temporary_storage_evictor_unittest.cc
index 21478c3c635..351c8a1b60b 100644
--- a/chromium/content/browser/quota/quota_temporary_storage_evictor_unittest.cc
+++ b/chromium/content/browser/quota/quota_temporary_storage_evictor_unittest.cc
@@ -50,6 +50,12 @@ class MockQuotaEvictionHandler : public storage::QuotaEvictionHandler {
callback.Run(storage::kQuotaStatusOk);
}
+ void AsyncGetVolumeInfo(const VolumeInfoCallback& callback) override {
+ uint64_t available = static_cast<uint64_t>(available_space_);
+ uint64_t total = (1024 * 1024 * 1024) + (2 * available); // 1G plus some.
+ callback.Run(true, available, total);
+ }
+
void GetUsageAndQuotaForEviction(
const UsageAndQuotaCallback& callback) override {
if (error_on_get_usage_and_quota_) {
diff --git a/chromium/content/browser/quota/storage_monitor_unittest.cc b/chromium/content/browser/quota/storage_monitor_unittest.cc
index 002e860b9df..e0f9cce6f8e 100644
--- a/chromium/content/browser/quota/storage_monitor_unittest.cc
+++ b/chromium/content/browser/quota/storage_monitor_unittest.cc
@@ -11,7 +11,7 @@
#include "base/thread_task_runner_handle.h"
#include "content/public/test/mock_special_storage_policy.h"
#include "content/public/test/mock_storage_client.h"
-#include "net/base/net_util.h"
+#include "net/base/url_util.h"
#include "storage/browser/quota/quota_manager.h"
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/browser/quota/storage_monitor.h"
diff --git a/chromium/content/browser/quota/usage_tracker_unittest.cc b/chromium/content/browser/quota/usage_tracker_unittest.cc
index 78d19b2de3d..887772d943a 100644
--- a/chromium/content/browser/quota/usage_tracker_unittest.cc
+++ b/chromium/content/browser/quota/usage_tracker_unittest.cc
@@ -11,7 +11,7 @@
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
#include "content/public/test/mock_special_storage_policy.h"
-#include "net/base/net_util.h"
+#include "net/base/url_util.h"
#include "storage/browser/quota/usage_tracker.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/content/browser/quota_dispatcher_host.cc b/chromium/content/browser/quota_dispatcher_host.cc
index 8f2043bb4e4..512beaf6aad 100644
--- a/chromium/content/browser/quota_dispatcher_host.cc
+++ b/chromium/content/browser/quota_dispatcher_host.cc
@@ -12,7 +12,7 @@
#include "base/trace_event/trace_event.h"
#include "content/common/quota_messages.h"
#include "content/public/browser/quota_permission_context.h"
-#include "net/base/net_util.h"
+#include "net/base/url_util.h"
#include "storage/browser/quota/quota_manager.h"
#include "url/gurl.h"
diff --git a/chromium/content/browser/renderer_host/DEPS b/chromium/content/browser/renderer_host/DEPS
index e20b55810dc..8c4fbe05818 100644
--- a/chromium/content/browser/renderer_host/DEPS
+++ b/chromium/content/browser/renderer_host/DEPS
@@ -23,13 +23,6 @@ specific_include_rules = {
"+content/public/browser/web_contents_view.h",
"+media/renderers",
],
- "sandbox_ipc_linux\.cc": [
- "+third_party/WebKit/public/platform/linux/WebFontInfo.h",
- "+third_party/WebKit/public/web/WebKit.h",
- ],
- "sandbox_ipc_linux\.h": [
- "+content/child/blink_platform_impl.h",
- ],
"render_process_host_impl\.cc": [
"+content/browser/frame_host/render_frame_message_filter.h",
],
diff --git a/chromium/content/browser/compositor/browser_compositor_view_mac.h b/chromium/content/browser/renderer_host/browser_compositor_view_mac.h
index c6ee6ffe345..9ad7e483b4e 100644
--- a/chromium/content/browser/compositor/browser_compositor_view_mac.h
+++ b/chromium/content/browser/renderer_host/browser_compositor_view_mac.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_COMPOSITOR_BROWSER_COMPOSITOR_VIEW_MAC_H_
-#define CONTENT_BROWSER_COMPOSITOR_BROWSER_COMPOSITOR_VIEW_MAC_H_
+#ifndef CONTENT_BROWSER_RENDERER_HOST_BROWSER_COMPOSITOR_VIEW_MAC_H_
+#define CONTENT_BROWSER_RENDERER_HOST_BROWSER_COMPOSITOR_VIEW_MAC_H_
#include "base/macros.h"
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
@@ -75,4 +75,4 @@ class BrowserCompositorMacPlaceholder {
} // namespace content
-#endif // CONTENT_BROWSER_COMPOSITOR_BROWSER_COMPOSITOR_VIEW_MAC_H_
+#endif // CONTENT_BROWSER_RENDERER_HOST_BROWSER_COMPOSITOR_VIEW_MAC_H_
diff --git a/chromium/content/browser/compositor/browser_compositor_view_mac.mm b/chromium/content/browser/renderer_host/browser_compositor_view_mac.mm
index 4670ed02ced..92ac2e7f131 100644
--- a/chromium/content/browser/compositor/browser_compositor_view_mac.mm
+++ b/chromium/content/browser/renderer_host/browser_compositor_view_mac.mm
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/compositor/browser_compositor_view_mac.h"
+#include "content/browser/renderer_host/browser_compositor_view_mac.h"
#include <stdint.h>
@@ -11,9 +11,7 @@
#include "base/lazy_instance.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/compositor/image_transport_factory.h"
-#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/public/browser/context_factory.h"
-#include "gpu/config/gpu_driver_bug_workaround_type.h"
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
@@ -34,18 +32,12 @@ uint32_t g_placeholder_count = 0;
// A spare BrowserCompositorMac kept around for recycling.
base::LazyInstance<scoped_ptr<BrowserCompositorMac>>
- g_recyclable_browser_compositor;
-
-bool WidgetNeedsGLFinishWorkaround() {
- return GpuDataManagerImpl::GetInstance()->IsDriverBugWorkaroundActive(
- gpu::FORCE_GL_FINISH_AFTER_COMPOSITING);
-}
+ g_recyclable_browser_compositor;
} // namespace
BrowserCompositorMac::BrowserCompositorMac()
- : accelerated_widget_mac_(
- new ui::AcceleratedWidgetMac(WidgetNeedsGLFinishWorkaround())),
+ : accelerated_widget_mac_(new ui::AcceleratedWidgetMac()),
compositor_(content::GetContextFactory(),
ui::WindowResizeHelperMac::Get()->task_runner()) {
compositor_.SetAcceleratedWidget(
diff --git a/chromium/content/browser/renderer_host/clipboard_message_filter.cc b/chromium/content/browser/renderer_host/clipboard_message_filter.cc
index dea3d127604..e50fedb5cb9 100644
--- a/chromium/content/browser/renderer_host/clipboard_message_filter.cc
+++ b/chromium/content/browser/renderer_host/clipboard_message_filter.cc
@@ -250,11 +250,7 @@ void ClipboardMessageFilter::OnWriteImage(ui::ClipboardType clipboard_type,
}
scoped_ptr<base::SharedMemory> bitmap_buffer(
-#if defined(OS_WIN)
- new base::SharedMemory(handle, true, PeerHandle()));
-#else
new base::SharedMemory(handle, true));
-#endif
SkBitmap bitmap;
// Let Skia do some sanity checking for (no negative widths/heights, no
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.cc b/chromium/content/browser/renderer_host/compositor_impl_android.cc
index 74f1e70e44e..43a22a0504b 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.cc
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.cc
@@ -21,6 +21,7 @@
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
+#include "base/sys_info.h"
#include "base/thread_task_runner_handle.h"
#include "base/threading/simple_thread.h"
#include "base/threading/thread.h"
@@ -42,17 +43,15 @@
#include "cc/trees/layer_tree_settings.h"
#include "content/browser/android/child_process_launcher_android.h"
#include "content/browser/compositor/browser_compositor_overlay_candidate_validator_android.h"
+#include "content/browser/compositor/gl_helper.h"
#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/gpu/gpu_surface_tracker.h"
#include "content/browser/renderer_host/render_widget_host_impl.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"
-#include "content/common/gpu/gpu_process_launch_causes.h"
+#include "content/common/gpu_process_launch_causes.h"
#include "content/common/host_shared_bitmap_manager.h"
#include "content/public/browser/android/compositor.h"
#include "content/public/browser/android/compositor_client.h"
@@ -60,6 +59,8 @@
#include "gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/ipc/client/command_buffer_proxy_impl.h"
+#include "gpu/ipc/client/gpu_channel_host.h"
#include "third_party/khronos/GLES2/gl2.h"
#include "third_party/khronos/GLES2/gl2ext.h"
#include "third_party/skia/include/core/SkMallocPixelRef.h"
@@ -127,11 +128,11 @@ class OutputSurfaceWithoutParent : public cc::OutputSurface,
}
private:
- CommandBufferProxyImpl* GetCommandBufferProxy() {
+ gpu::CommandBufferProxyImpl* GetCommandBufferProxy() {
ContextProviderCommandBuffer* provider_command_buffer =
static_cast<content::ContextProviderCommandBuffer*>(
context_provider_.get());
- CommandBufferProxyImpl* command_buffer_proxy =
+ gpu::CommandBufferProxyImpl* command_buffer_proxy =
provider_command_buffer->GetCommandBufferProxy();
DCHECK(command_buffer_proxy);
return command_buffer_proxy;
@@ -168,8 +169,7 @@ class ExternalBeginFrameSource : public cc::BeginFrameSourceBase,
}
// cc::BeginFrameSourceBase implementation:
- void OnNeedsBeginFramesChange(
- bool needs_begin_frames) override {
+ void OnNeedsBeginFramesChanged(bool needs_begin_frames) override {
compositor_->OnNeedsBeginFramesChange(needs_begin_frames);
}
@@ -187,7 +187,6 @@ class ExternalBeginFrameSource : public cc::BeginFrameSourceBase,
static bool g_initialized = false;
-bool g_use_surface_manager = false;
base::LazyInstance<cc::SurfaceManager> g_surface_manager =
LAZY_INSTANCE_INITIALIZER;
@@ -196,8 +195,7 @@ int g_surface_id_namespace = 0;
class SingleThreadTaskGraphRunner : public cc::SingleThreadTaskGraphRunner {
public:
SingleThreadTaskGraphRunner() {
- Start("CompositorTileWorker1",
- base::SimpleThread::Options(base::ThreadPriority::BACKGROUND));
+ Start("CompositorTileWorker1", base::SimpleThread::Options());
}
~SingleThreadTaskGraphRunner() override {
@@ -220,17 +218,6 @@ Compositor* Compositor::Create(CompositorClient* client,
void Compositor::Initialize() {
DCHECK(!CompositorImpl::IsInitialized());
g_initialized = true;
- g_use_surface_manager = UseSurfacesEnabled();
-}
-
-// static
-const cc::LayerSettings& Compositor::LayerSettings() {
- return ui::WindowAndroidCompositor::LayerSettings();
-}
-
-// static
-void Compositor::SetLayerSettings(const cc::LayerSettings& settings) {
- ui::WindowAndroidCompositor::SetLayerSettings(settings);
}
// static
@@ -240,8 +227,6 @@ bool CompositorImpl::IsInitialized() {
// static
cc::SurfaceManager* CompositorImpl::GetSurfaceManager() {
- if (!g_use_surface_manager)
- return nullptr;
return g_surface_manager.Pointer();
}
@@ -257,10 +242,9 @@ scoped_ptr<cc::SurfaceIdAllocator> CompositorImpl::CreateSurfaceIdAllocator() {
CompositorImpl::CompositorImpl(CompositorClient* client,
gfx::NativeWindow root_window)
- : root_layer_(cc::Layer::Create(Compositor::LayerSettings())),
+ : root_layer_(cc::Layer::Create()),
+ surface_id_allocator_(CreateSurfaceIdAllocator()),
resource_manager_(root_window),
- surface_id_allocator_(GetSurfaceManager() ? CreateSurfaceIdAllocator()
- : nullptr),
has_transparent_background_(false),
device_scale_factor_(1),
window_(NULL),
@@ -334,9 +318,6 @@ void CompositorImpl::SetSurface(jobject surface) {
window_ = window;
ANativeWindow_acquire(window);
surface_id_ = tracker->AddSurfaceForNativeWidget(window);
- tracker->SetSurfaceHandle(
- surface_id_,
- gfx::GLSurfaceHandle(surface_id_, gfx::NATIVE_DIRECT));
// Register first, SetVisible() might create an OutputSurface.
RegisterViewSurface(surface_id_, j_surface.obj());
SetVisible(true);
@@ -357,13 +338,10 @@ void CompositorImpl::CreateLayerTreeHost() {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
settings.initial_debug_state.SetRecordRenderingStats(
command_line->HasSwitch(cc::switches::kEnableGpuBenchmarking));
- if (command_line->HasSwitch(cc::switches::kDisableCompositorPropertyTrees))
- settings.use_property_trees = false;
+ settings.initial_debug_state.show_fps_counter =
+ command_line->HasSwitch(cc::switches::kUIShowFPSCounter);
settings.single_thread_proxy_scheduler = true;
- settings.use_compositor_animation_timelines = !command_line->HasSwitch(
- switches::kDisableAndroidCompositorAnimationTimelines);
-
cc::LayerTreeHost::InitParams params;
params.client = this;
params.shared_bitmap_manager = HostSharedBitmapManager::current();
@@ -375,8 +353,7 @@ void CompositorImpl::CreateLayerTreeHost() {
host_ = cc::LayerTreeHost::CreateSingleThreaded(this, &params);
DCHECK(!host_->visible());
host_->SetRootLayer(root_layer_);
- if (surface_id_allocator_)
- host_->set_surface_id_namespace(surface_id_allocator_->id_namespace());
+ host_->set_surface_id_namespace(surface_id_allocator_->id_namespace());
host_->SetViewportSize(size_);
host_->set_has_transparent_background(has_transparent_background_);
host_->SetDeviceScaleFactor(device_scale_factor_);
@@ -434,8 +411,8 @@ void CompositorImpl::SetNeedsComposite() {
static scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
CreateGpuProcessViewContext(
- const scoped_refptr<GpuChannelHost>& gpu_channel_host,
- const blink::WebGraphicsContext3D::Attributes attributes,
+ const scoped_refptr<gpu::GpuChannelHost>& gpu_channel_host,
+ const gpu::gles2::ContextCreationAttribHelper& attributes,
int surface_id) {
GURL url("chrome://gpu/Compositor::createContext3D");
static const size_t kBytesPerPixel = 4;
@@ -451,15 +428,14 @@ CreateGpuProcessViewContext(
limits.max_transfer_buffer_size = std::min(
3 * full_screen_texture_size_in_bytes, kDefaultMaxTransferBufferSize);
limits.mapped_memory_reclaim_limit = 2 * 1024 * 1024;
- bool lose_context_when_out_of_memory = true;
- return make_scoped_ptr(
- new WebGraphicsContext3DCommandBufferImpl(surface_id,
- url,
- gpu_channel_host.get(),
- attributes,
- lose_context_when_out_of_memory,
- limits,
- NULL));
+ GpuSurfaceTracker* tracker = GpuSurfaceTracker::Get();
+ gpu::SurfaceHandle surface_handle = tracker->GetSurfaceHandle(surface_id);
+ bool share_resources = true;
+ bool automatic_flushes = false;
+ return make_scoped_ptr(new WebGraphicsContext3DCommandBufferImpl(
+ surface_handle, url, gpu_channel_host.get(), attributes,
+ gfx::PreferIntegratedGpu, share_resources, automatic_flushes, limits,
+ nullptr));
}
void CompositorImpl::UpdateLayerTreeHost() {
@@ -524,9 +500,34 @@ void CompositorImpl::CreateOutputSurface() {
if (!output_surface_request_pending_ || !host_->visible())
return;
- blink::WebGraphicsContext3D::Attributes attrs;
- attrs.shareResources = true;
- attrs.noAutomaticFlushes = true;
+ // This is used for the browser compositor (offscreen) and for the display
+ // compositor (onscreen), so ask for capabilities needed by either one.
+ // The default framebuffer for an offscreen context is not used, so it does
+ // not need alpha, stencil, depth, antialiasing. The display compositor does
+ // not use these things either, except for alpha when it has a transparent
+ // background.
+ gpu::gles2::ContextCreationAttribHelper attributes;
+ attributes.alpha_size = -1;
+ attributes.stencil_size = 0;
+ attributes.depth_size = 0;
+ attributes.samples = 0;
+ attributes.sample_buffers = 0;
+ attributes.bind_generates_resource = false;
+
+ if (has_transparent_background_) {
+ attributes.alpha_size = 8;
+ } else if (base::SysInfo::IsLowEndDevice()) {
+ // In this case we prefer to use RGB565 format instead of RGBA8888 if
+ // possible.
+ // TODO(danakj): GpuCommandBufferStub constructor checks for alpha == 0 in
+ // order to enable 565, but it should avoid using 565 when -1s are specified
+ // (IOW check that a <= 0 && rgb > 0 && rgb <= 565) then alpha should be -1.
+ attributes.alpha_size = 0;
+ attributes.red_size = 5;
+ attributes.green_size = 6;
+ attributes.blue_size = 5;
+ }
+
pending_swapbuffers_ = 0;
DCHECK(window_);
@@ -538,11 +539,12 @@ void CompositorImpl::CreateOutputSurface() {
// still get marked as lost from the IO thread, at any point in time really).
// But from here on just try and always lead to either
// DidInitializeOutputSurface() or DidFailToInitializeOutputSurface().
- scoped_refptr<GpuChannelHost> gpu_channel_host(factory->GetGpuChannel());
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel_host(factory->GetGpuChannel());
scoped_refptr<ContextProviderCommandBuffer> context_provider(
ContextProviderCommandBuffer::Create(
- CreateGpuProcessViewContext(gpu_channel_host, attrs, surface_id_),
- BROWSER_COMPOSITOR_ONSCREEN_CONTEXT));
+ CreateGpuProcessViewContext(gpu_channel_host, attributes,
+ surface_id_),
+ DISPLAY_COMPOSITOR_ONSCREEN_CONTEXT));
DCHECK(context_provider.get());
scoped_ptr<cc::OutputSurface> real_output_surface(
@@ -552,24 +554,20 @@ void CompositorImpl::CreateOutputSurface() {
base::Unretained(this))));
cc::SurfaceManager* manager = GetSurfaceManager();
- if (manager) {
- display_client_.reset(
- new cc::OnscreenDisplayClient(std::move(real_output_surface), manager,
- HostSharedBitmapManager::current(),
- BrowserGpuMemoryBufferManager::current(),
- host_->settings().renderer_settings,
- base::ThreadTaskRunnerHandle::Get()));
- scoped_ptr<cc::SurfaceDisplayOutputSurface> surface_output_surface(
- new cc::SurfaceDisplayOutputSurface(
- manager, surface_id_allocator_.get(), context_provider, nullptr));
-
- display_client_->set_surface_output_surface(surface_output_surface.get());
- surface_output_surface->set_display_client(display_client_.get());
- display_client_->display()->Resize(size_);
- host_->SetOutputSurface(std::move(surface_output_surface));
- } else {
- host_->SetOutputSurface(std::move(real_output_surface));
- }
+ display_client_.reset(
+ new cc::OnscreenDisplayClient(std::move(real_output_surface), manager,
+ HostSharedBitmapManager::current(),
+ BrowserGpuMemoryBufferManager::current(),
+ host_->settings().renderer_settings,
+ base::ThreadTaskRunnerHandle::Get()));
+ scoped_ptr<cc::SurfaceDisplayOutputSurface> surface_output_surface(
+ new cc::SurfaceDisplayOutputSurface(
+ manager, surface_id_allocator_.get(), context_provider, nullptr));
+
+ display_client_->set_surface_output_surface(surface_output_surface.get());
+ surface_output_surface->set_display_client(display_client_.get());
+ display_client_->display()->Resize(size_);
+ host_->SetOutputSurface(std::move(surface_output_surface));
}
void CompositorImpl::PopulateGpuCapabilities(
@@ -624,10 +622,6 @@ void CompositorImpl::DidCommit() {
root_window_->OnCompositingDidCommit();
}
-void CompositorImpl::AttachLayerForReadback(scoped_refptr<cc::Layer> layer) {
- root_layer_->AddChild(layer);
-}
-
void CompositorImpl::RequestCopyOfOutputOnRootLayer(
scoped_ptr<cc::CopyOutputRequest> request) {
root_layer_->RequestCopyOfOutput(std::move(request));
diff --git a/chromium/content/browser/renderer_host/compositor_impl_android.h b/chromium/content/browser/renderer_host/compositor_impl_android.h
index 9b1a60eb0e9..4bc304ff84c 100644
--- a/chromium/content/browser/renderer_host/compositor_impl_android.h
+++ b/chromium/content/browser/renderer_host/compositor_impl_android.h
@@ -113,7 +113,6 @@ class CONTENT_EXPORT CompositorImpl
void DidAbortSwapBuffers() override;
// WindowAndroidCompositor implementation.
- void AttachLayerForReadback(scoped_refptr<cc::Layer> layer) override;
void RequestCopyOfOutputOnRootLayer(
scoped_ptr<cc::CopyOutputRequest> request) override;
void OnVSync(base::TimeTicks frame_time,
@@ -132,12 +131,12 @@ class CONTENT_EXPORT CompositorImpl
scoped_refptr<cc::Layer> subroot_layer_;
// Destruction order matters here:
+ scoped_ptr<cc::SurfaceIdAllocator> surface_id_allocator_;
base::ObserverList<VSyncObserver, true> observer_list_;
scoped_ptr<cc::LayerTreeHost> host_;
ui::ResourceManagerImpl resource_manager_;
scoped_ptr<cc::OnscreenDisplayClient> display_client_;
- scoped_ptr<cc::SurfaceIdAllocator> surface_id_allocator_;
gfx::Size size_;
bool has_transparent_background_;
diff --git a/chromium/content/browser/renderer_host/compositor_resize_lock_aura.h b/chromium/content/browser/renderer_host/compositor_resize_lock_aura.h
index 981694f329c..f12e43842b5 100644
--- a/chromium/content/browser/renderer_host/compositor_resize_lock_aura.h
+++ b/chromium/content/browser/renderer_host/compositor_resize_lock_aura.h
@@ -9,7 +9,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
-#include "content/browser/compositor/resize_lock.h"
+#include "content/browser/renderer_host/resize_lock.h"
namespace aura {
class WindowTreeHost;
diff --git a/chromium/content/browser/renderer_host/database_message_filter.cc b/chromium/content/browser/renderer_host/database_message_filter.cc
index 9c9f16ea45e..5f9a8ae5d72 100644
--- a/chromium/content/browser/renderer_host/database_message_filter.cc
+++ b/chromium/content/browser/renderer_host/database_message_filter.cc
@@ -163,12 +163,11 @@ void DatabaseMessageFilter::OnDatabaseOpenFile(
// database tracker.
*handle = IPC::InvalidPlatformFileForTransit();
if (file.IsValid()) {
- *handle = IPC::TakeFileHandleForProcess(std::move(file), PeerHandle());
+ *handle = IPC::TakePlatformFileForTransit(std::move(file));
} else if (tracked_file) {
DCHECK(tracked_file->IsValid());
*handle =
- IPC::GetFileHandleForProcess(tracked_file->GetPlatformFile(),
- PeerHandle(), false);
+ IPC::GetPlatformFileForTransit(tracked_file->GetPlatformFile(), false);
}
}
@@ -305,7 +304,7 @@ void DatabaseMessageFilter::OnDatabaseOpened(
int64_t estimated_size) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- if (!DatabaseUtil::IsValidOriginIdentifier(origin_identifier)) {
+ if (!storage::IsValidOriginIdentifier(origin_identifier)) {
bad_message::ReceivedBadMessage(this,
bad_message::DBMF_INVALID_ORIGIN_ON_OPEN);
return;
@@ -357,7 +356,7 @@ void DatabaseMessageFilter::OnHandleSqliteError(
const base::string16& database_name,
int error) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- if (!DatabaseUtil::IsValidOriginIdentifier(origin_identifier)) {
+ if (!storage::IsValidOriginIdentifier(origin_identifier)) {
bad_message::ReceivedBadMessage(
this, bad_message::DBMF_INVALID_ORIGIN_ON_SQLITE_ERROR);
return;
diff --git a/chromium/content/browser/compositor/delegated_frame_host.cc b/chromium/content/browser/renderer_host/delegated_frame_host.cc
index f381da0eadd..e103e320e66 100644
--- a/chromium/content/browser/compositor/delegated_frame_host.cc
+++ b/chromium/content/browser/renderer_host/delegated_frame_host.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/compositor/delegated_frame_host.h"
+#include "content/browser/renderer_host/delegated_frame_host.h"
#include <algorithm>
#include <string>
@@ -21,10 +21,10 @@
#include "cc/surfaces/surface_factory.h"
#include "cc/surfaces/surface_hittest.h"
#include "cc/surfaces/surface_manager.h"
-#include "content/browser/compositor/resize_lock.h"
+#include "content/browser/compositor/gl_helper.h"
#include "content/browser/compositor/surface_utils.h"
#include "content/browser/gpu/compositor_util.h"
-#include "content/common/gpu/client/gl_helper.h"
+#include "content/browser/renderer_host/resize_lock.h"
#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
#include "content/public/common/content_switches.h"
#include "media/base/video_frame.h"
@@ -65,24 +65,26 @@ void RequireCallback(cc::SurfaceManager* manager,
DelegatedFrameHost::DelegatedFrameHost(DelegatedFrameHostClient* client)
: client_(client),
compositor_(nullptr),
- use_surfaces_(UseSurfacesEnabled()),
tick_clock_(new base::DefaultTickClock()),
last_output_surface_id_(0),
pending_delegated_ack_count_(0),
skipped_frames_(false),
+ background_color_(SK_ColorRED),
current_scale_factor_(1.f),
can_lock_compositor_(YES_CAN_LOCK),
- delegated_frame_evictor_(new DelegatedFrameEvictor(this)) {
+ delegated_frame_evictor_(new DelegatedFrameEvictor(this)),
+ begin_frame_source_(nullptr) {
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
factory->AddObserver(this);
id_allocator_ = factory->GetContextFactory()->CreateSurfaceIdAllocator();
+ factory->GetSurfaceManager()->RegisterSurfaceFactoryClient(
+ id_allocator_->id_namespace(), this);
}
void DelegatedFrameHost::WasShown(const ui::LatencyInfo& latency_info) {
delegated_frame_evictor_->SetVisible(true);
- if (surface_id_.is_null() && !frame_provider_.get() &&
- !released_front_lock_.get()) {
+ if (surface_id_.is_null() && !released_front_lock_.get()) {
if (compositor_)
released_front_lock_ = compositor_->GetCompositorLock();
}
@@ -151,8 +153,8 @@ void DelegatedFrameHost::CopyFromCompositingSurface(
scoped_ptr<cc::CopyOutputRequest> request =
cc::CopyOutputRequest::CreateRequest(
- base::Bind(&DelegatedFrameHost::CopyFromCompositingSurfaceHasResult,
- output_size, preferred_color_type, callback));
+ base::Bind(&CopyFromCompositingSurfaceHasResult, output_size,
+ preferred_color_type, callback));
if (!src_subrect.IsEmpty())
request->set_area(src_subrect);
RequestCopyOfOutput(std::move(request));
@@ -169,12 +171,9 @@ void DelegatedFrameHost::CopyFromCompositingSurfaceToVideoFrame(
scoped_ptr<cc::CopyOutputRequest> request =
cc::CopyOutputRequest::CreateRequest(base::Bind(
- &DelegatedFrameHost::
- CopyFromCompositingSurfaceHasResultForVideo,
+ &DelegatedFrameHost::CopyFromCompositingSurfaceHasResultForVideo,
AsWeakPtr(), // For caching the ReadbackYUVInterface on this class.
- nullptr,
- target,
- callback));
+ nullptr, target, callback));
request->set_area(src_subrect);
RequestCopyOfOutput(std::move(request));
}
@@ -200,18 +199,16 @@ void DelegatedFrameHost::EndFrameSubscription() {
}
uint32_t DelegatedFrameHost::GetSurfaceIdNamespace() {
- if (!use_surfaces_)
- return 0;
-
return id_allocator_->id_namespace();
}
cc::SurfaceId DelegatedFrameHost::SurfaceIdAtPoint(
+ cc::SurfaceHittestDelegate* delegate,
const gfx::Point& point,
gfx::Point* transformed_point) {
if (surface_id_.is_null())
return surface_id_;
- cc::SurfaceHittest hittest(nullptr, GetSurfaceManager());
+ cc::SurfaceHittest hittest(delegate, GetSurfaceManager());
gfx::Transform target_transform;
cc::SurfaceId target_surface_id =
hittest.GetTargetSurfaceAtPoint(surface_id_, point, &target_transform);
@@ -243,8 +240,7 @@ bool DelegatedFrameHost::ShouldSkipFrame(gfx::Size size_in_dip) const {
// to replace it. Otherwise may cause hangs when the renderer is waiting for
// the completion of latency infos (such as when taking a Snapshot.)
if (can_lock_compositor_ == NO_PENDING_RENDERER_FRAME ||
- can_lock_compositor_ == NO_PENDING_COMMIT ||
- !resize_lock_.get())
+ can_lock_compositor_ == NO_PENDING_COMMIT || !resize_lock_.get())
return false;
return size_in_dip != resize_lock_->expected_size();
@@ -256,6 +252,45 @@ void DelegatedFrameHost::WasResized() {
!client_->DelegatedFrameHostIsVisible())
EvictDelegatedFrame();
MaybeCreateResizeLock();
+ UpdateGutters();
+}
+
+void DelegatedFrameHost::UpdateGutters() {
+ if (surface_id_.is_null()) {
+ right_gutter_.reset();
+ bottom_gutter_.reset();
+ return;
+ }
+ if (current_frame_size_in_dip_.width() <
+ client_->DelegatedFrameHostDesiredSizeInDIP().width()) {
+ right_gutter_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
+ right_gutter_->SetColor(background_color_);
+ int width = client_->DelegatedFrameHostDesiredSizeInDIP().width() -
+ current_frame_size_in_dip_.width();
+ // The right gutter also includes the bottom-right corner, if necessary.
+ int height = client_->DelegatedFrameHostDesiredSizeInDIP().height();
+ right_gutter_->SetBounds(
+ gfx::Rect(current_frame_size_in_dip_.width(), 0, width, height));
+
+ client_->DelegatedFrameHostGetLayer()->Add(right_gutter_.get());
+ } else {
+ right_gutter_.reset();
+ }
+
+ if (current_frame_size_in_dip_.height() <
+ client_->DelegatedFrameHostDesiredSizeInDIP().height()) {
+ bottom_gutter_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
+ bottom_gutter_->SetColor(background_color_);
+ int width = current_frame_size_in_dip_.width();
+ int height = client_->DelegatedFrameHostDesiredSizeInDIP().height() -
+ current_frame_size_in_dip_.height();
+ bottom_gutter_->SetBounds(
+ gfx::Rect(0, current_frame_size_in_dip_.height(), width, height));
+ client_->DelegatedFrameHostGetLayer()->Add(bottom_gutter_.get());
+
+ } else {
+ bottom_gutter_.reset();
+ }
}
gfx::Size DelegatedFrameHost::GetRequestedRendererSize() const {
@@ -292,8 +327,8 @@ void DelegatedFrameHost::AttemptFrameSubscriberCapture(
scoped_refptr<media::VideoFrame> frame;
RenderWidgetHostViewFrameSubscriber::DeliverFrameCallback callback;
- if (!frame_subscriber()->ShouldCaptureFrame(damage_rect, present_time,
- &frame, &callback))
+ if (!frame_subscriber()->ShouldCaptureFrame(damage_rect, present_time, &frame,
+ &callback))
return;
// Get a texture to re-use; else, create a new one.
@@ -309,9 +344,7 @@ void DelegatedFrameHost::AttemptFrameSubscriberCapture(
scoped_ptr<cc::CopyOutputRequest> request =
cc::CopyOutputRequest::CreateRequest(base::Bind(
&DelegatedFrameHost::CopyFromCompositingSurfaceHasResultForVideo,
- AsWeakPtr(),
- subscriber_texture,
- frame,
+ AsWeakPtr(), subscriber_texture, frame,
base::Bind(callback, present_time)));
// Setting the source in this copy request asks that the layer abort any prior
// uncommitted copy requests made on behalf of the same frame subscriber.
@@ -398,125 +431,79 @@ void DelegatedFrameHost::SwapDelegatedFrame(
if (!surface_returned_resources_.empty())
SendReturnedDelegatedResources(last_output_surface_id_);
- // Drop the cc::DelegatedFrameResourceCollection so that we will not return
- // any resources from the old output surface with the new output surface id.
- if (resource_collection_.get()) {
- resource_collection_->SetClient(NULL);
-
- if (resource_collection_->LoseAllResources())
- SendReturnedDelegatedResources(last_output_surface_id_);
-
- resource_collection_ = NULL;
- }
last_output_surface_id_ = output_surface_id;
}
- bool immediate_ack = !compositor_;
+ bool skip_frame = false;
pending_delegated_ack_count_++;
+ background_color_ = frame->metadata.root_background_color;
+
if (frame_size.IsEmpty()) {
DCHECK(frame_data->resource_list.empty());
EvictDelegatedFrame();
} else {
- if (use_surfaces_) {
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- cc::SurfaceManager* manager = factory->GetSurfaceManager();
- if (!surface_factory_) {
- surface_factory_ =
- make_scoped_ptr(new cc::SurfaceFactory(manager, this));
- }
- if (surface_id_.is_null() || frame_size != current_surface_size_ ||
- frame_size_in_dip != current_frame_size_in_dip_) {
- if (!surface_id_.is_null())
- surface_factory_->Destroy(surface_id_);
- surface_id_ = id_allocator_->GenerateId();
- surface_factory_->Create(surface_id_);
- // manager must outlive compositors using it.
- client_->DelegatedFrameHostGetLayer()->SetShowSurface(
- surface_id_,
- base::Bind(&SatisfyCallback, base::Unretained(manager)),
- base::Bind(&RequireCallback, base::Unretained(manager)), frame_size,
- frame_device_scale_factor, frame_size_in_dip);
- current_surface_size_ = frame_size;
- current_scale_factor_ = frame_device_scale_factor;
- }
-
- frame->metadata.latency_info.insert(frame->metadata.latency_info.end(),
- skipped_latency_info_list_.begin(),
- skipped_latency_info_list_.end());
- skipped_latency_info_list_.clear();
-
- gfx::Size desired_size = client_->DelegatedFrameHostDesiredSizeInDIP();
- if (desired_size != frame_size_in_dip && !desired_size.IsEmpty())
- immediate_ack = true;
-
- cc::SurfaceFactory::DrawCallback ack_callback;
- if (compositor_ && !immediate_ack) {
- ack_callback = base::Bind(&DelegatedFrameHost::SurfaceDrawn,
- AsWeakPtr(), output_surface_id);
- }
- surface_factory_->SubmitCompositorFrame(surface_id_, std::move(frame),
- ack_callback);
- } else {
- if (!resource_collection_.get()) {
- resource_collection_ = new cc::DelegatedFrameResourceCollection;
- resource_collection_->SetClient(this);
- }
- // If the physical frame size changes, we need a new |frame_provider_|. If
- // the physical frame size is the same, but the size in DIP changed, we
- // need to adjust the scale at which the frames will be drawn, and we do
- // this by making a new |frame_provider_| also to ensure the scale change
- // is presented in sync with the new frame content.
- if (!frame_provider_.get() ||
- frame_size != frame_provider_->frame_size() ||
- frame_size_in_dip != current_frame_size_in_dip_) {
- frame_provider_ = new cc::DelegatedFrameProvider(
- resource_collection_.get(), std::move(frame->delegated_frame_data));
- client_->DelegatedFrameHostGetLayer()->SetShowDelegatedContent(
- frame_provider_.get(), frame_size_in_dip);
- } else {
- frame_provider_->SetFrameData(std::move(frame->delegated_frame_data));
- }
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ cc::SurfaceManager* manager = factory->GetSurfaceManager();
+ if (!surface_factory_) {
+ surface_factory_ = make_scoped_ptr(new cc::SurfaceFactory(manager, this));
+ }
+ if (surface_id_.is_null() || frame_size != current_surface_size_ ||
+ frame_size_in_dip != current_frame_size_in_dip_) {
+ if (!surface_id_.is_null())
+ surface_factory_->Destroy(surface_id_);
+ surface_id_ = id_allocator_->GenerateId();
+ surface_factory_->Create(surface_id_);
+ // manager must outlive compositors using it.
+ client_->DelegatedFrameHostGetLayer()->SetShowSurface(
+ surface_id_, base::Bind(&SatisfyCallback, base::Unretained(manager)),
+ base::Bind(&RequireCallback, base::Unretained(manager)), frame_size,
+ frame_device_scale_factor, frame_size_in_dip);
+ current_surface_size_ = frame_size;
+ current_scale_factor_ = frame_device_scale_factor;
}
+
+ frame->metadata.latency_info.insert(frame->metadata.latency_info.end(),
+ skipped_latency_info_list_.begin(),
+ skipped_latency_info_list_.end());
+ skipped_latency_info_list_.clear();
+
+ gfx::Size desired_size = client_->DelegatedFrameHostDesiredSizeInDIP();
+ if (desired_size != frame_size_in_dip && !desired_size.IsEmpty())
+ skip_frame = true;
+
+ cc::SurfaceFactory::DrawCallback ack_callback;
+ if (compositor_ && !skip_frame) {
+ ack_callback = base::Bind(&DelegatedFrameHost::SurfaceDrawn, AsWeakPtr(),
+ output_surface_id);
+ }
+ surface_factory_->SubmitCompositorFrame(surface_id_, std::move(frame),
+ ack_callback);
}
released_front_lock_ = NULL;
current_frame_size_in_dip_ = frame_size_in_dip;
CheckResizeLock();
+ UpdateGutters();
+
if (!damage_rect_in_dip.IsEmpty())
client_->DelegatedFrameHostGetLayer()->OnDelegatedFrameDamage(
damage_rect_in_dip);
- if (immediate_ack) {
+ // Note that |compositor_| may be reset by SetShowSurface or
+ // SetShowDelegatedContent above.
+ if (!compositor_ || skip_frame) {
SendDelegatedFrameAck(output_surface_id);
- } else if (!use_surfaces_) {
- std::vector<ui::LatencyInfo>::const_iterator it;
- for (it = frame->metadata.latency_info.begin();
- it != frame->metadata.latency_info.end(); ++it)
- compositor_->SetLatencyInfo(*it);
- // If we've previously skipped any latency infos add them.
- for (it = skipped_latency_info_list_.begin();
- it != skipped_latency_info_list_.end();
- ++it)
- compositor_->SetLatencyInfo(*it);
- skipped_latency_info_list_.clear();
- AddOnCommitCallbackAndDisableLocks(
- base::Bind(&DelegatedFrameHost::SendDelegatedFrameAck,
- AsWeakPtr(), output_surface_id));
} else {
- AddOnCommitCallbackAndDisableLocks(base::Closure());
+ can_lock_compositor_ = NO_PENDING_COMMIT;
}
- // With Surfaces, WillDrawSurface() will be called as the trigger to attempt
- // a frame subscriber capture instead.
- if (!use_surfaces_)
- AttemptFrameSubscriberCapture(damage_rect);
- if (frame_provider_.get() || !surface_id_.is_null())
+ if (!surface_id_.is_null())
delegated_frame_evictor_->SwappedFrame(
client_->DelegatedFrameHostIsVisible());
// Note: the frame may have been evicted immediately.
}
void DelegatedFrameHost::ClearDelegatedFrame() {
- if (frame_provider_.get() || !surface_id_.is_null())
+ if (!surface_id_.is_null())
EvictDelegatedFrame();
}
@@ -524,8 +511,6 @@ void DelegatedFrameHost::SendDelegatedFrameAck(uint32_t output_surface_id) {
cc::CompositorFrameAck ack;
if (!surface_returned_resources_.empty())
ack.resources.swap(surface_returned_resources_);
- if (resource_collection_.get())
- resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
client_->DelegatedFrameHostSendCompositorSwapAck(output_surface_id, ack);
DCHECK_GT(pending_delegated_ack_count_, 0);
pending_delegated_ack_count_--;
@@ -536,23 +521,11 @@ void DelegatedFrameHost::SurfaceDrawn(uint32_t output_surface_id,
SendDelegatedFrameAck(output_surface_id);
}
-void DelegatedFrameHost::UnusedResourcesAreAvailable() {
- if (pending_delegated_ack_count_)
- return;
-
- SendReturnedDelegatedResources(last_output_surface_id_);
-}
-
void DelegatedFrameHost::SendReturnedDelegatedResources(
uint32_t output_surface_id) {
cc::CompositorFrameAck ack;
- if (!surface_returned_resources_.empty()) {
- ack.resources.swap(surface_returned_resources_);
- } else {
- DCHECK(resource_collection_.get());
- resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
- }
- DCHECK(!ack.resources.empty());
+ DCHECK(!surface_returned_resources_.empty());
+ ack.resources.swap(surface_returned_resources_);
client_->DelegatedFrameHostSendReclaimCompositorResources(output_surface_id,
ack);
@@ -562,8 +535,7 @@ void DelegatedFrameHost::ReturnResources(
const cc::ReturnedResourceArray& resources) {
if (resources.empty())
return;
- std::copy(resources.begin(),
- resources.end(),
+ std::copy(resources.begin(), resources.end(),
std::back_inserter(surface_returned_resources_));
if (!pending_delegated_ack_count_)
SendReturnedDelegatedResources(last_output_surface_id_);
@@ -577,168 +549,19 @@ void DelegatedFrameHost::WillDrawSurface(cc::SurfaceId id,
}
void DelegatedFrameHost::SetBeginFrameSource(
- cc::SurfaceId surface_id,
cc::BeginFrameSource* begin_frame_source) {
- // TODO(tansell): Hook this up.
+ // TODO(enne): forward this to DelegatedFrameHostClient to observe and then to
+ // the renderer as an external begin frame source.
}
void DelegatedFrameHost::EvictDelegatedFrame() {
client_->DelegatedFrameHostGetLayer()->SetShowSolidColorContent();
- frame_provider_ = NULL;
if (!surface_id_.is_null()) {
surface_factory_->Destroy(surface_id_);
surface_id_ = cc::SurfaceId();
}
delegated_frame_evictor_->DiscardedFrame();
-}
-
-// static
-void DelegatedFrameHost::CopyFromCompositingSurfaceHasResult(
- const gfx::Size& dst_size_in_pixel,
- const SkColorType color_type,
- const ReadbackRequestCallback& callback,
- scoped_ptr<cc::CopyOutputResult> result) {
- if (result->IsEmpty() || result->size().IsEmpty()) {
- callback.Run(SkBitmap(), content::READBACK_FAILED);
- return;
- }
-
- gfx::Size output_size_in_pixel;
- if (dst_size_in_pixel.IsEmpty())
- output_size_in_pixel = result->size();
- else
- output_size_in_pixel = dst_size_in_pixel;
-
- if (result->HasTexture()) {
- // GPU-accelerated path
- PrepareTextureCopyOutputResult(output_size_in_pixel, color_type, callback,
- std::move(result));
- return;
- }
-
- DCHECK(result->HasBitmap());
- // Software path
- PrepareBitmapCopyOutputResult(output_size_in_pixel, color_type, callback,
- std::move(result));
-}
-
-static void CopyFromCompositingSurfaceFinished(
- const ReadbackRequestCallback& callback,
- scoped_ptr<cc::SingleReleaseCallback> release_callback,
- scoped_ptr<SkBitmap> bitmap,
- scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock,
- bool result) {
- bitmap_pixels_lock.reset();
-
- gpu::SyncToken sync_token;
- if (result) {
- GLHelper* gl_helper = ImageTransportFactory::GetInstance()->GetGLHelper();
- if (gl_helper)
- gl_helper->GenerateSyncToken(&sync_token);
- }
- const bool lost_resource = !sync_token.HasData();
- release_callback->Run(sync_token, lost_resource);
-
- callback.Run(*bitmap,
- result ? content::READBACK_SUCCESS : content::READBACK_FAILED);
-}
-
-// static
-void DelegatedFrameHost::PrepareTextureCopyOutputResult(
- const gfx::Size& dst_size_in_pixel,
- const SkColorType color_type,
- const ReadbackRequestCallback& callback,
- scoped_ptr<cc::CopyOutputResult> result) {
- DCHECK(result->HasTexture());
- base::ScopedClosureRunner scoped_callback_runner(
- base::Bind(callback, SkBitmap(), content::READBACK_FAILED));
-
- // TODO(siva.gunturi): We should be able to validate the format here using
- // GLHelper::IsReadbackConfigSupported before we processs the result.
- // See crbug.com/415682 and crbug.com/415131.
- scoped_ptr<SkBitmap> bitmap(new SkBitmap);
- if (!bitmap->tryAllocPixels(SkImageInfo::Make(
- dst_size_in_pixel.width(), dst_size_in_pixel.height(), color_type,
- kOpaque_SkAlphaType))) {
- scoped_callback_runner.Reset(base::Bind(
- callback, SkBitmap(), content::READBACK_BITMAP_ALLOCATION_FAILURE));
- return;
- }
-
- ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
- GLHelper* gl_helper = factory->GetGLHelper();
- if (!gl_helper)
- return;
-
- scoped_ptr<SkAutoLockPixels> bitmap_pixels_lock(
- new SkAutoLockPixels(*bitmap));
- uint8_t* pixels = static_cast<uint8_t*>(bitmap->getPixels());
-
- cc::TextureMailbox texture_mailbox;
- scoped_ptr<cc::SingleReleaseCallback> release_callback;
- result->TakeTexture(&texture_mailbox, &release_callback);
- DCHECK(texture_mailbox.IsTexture());
-
- ignore_result(scoped_callback_runner.Release());
-
- gl_helper->CropScaleReadbackAndCleanMailbox(
- texture_mailbox.mailbox(), texture_mailbox.sync_token(), result->size(),
- gfx::Rect(result->size()), dst_size_in_pixel, pixels, color_type,
- base::Bind(&CopyFromCompositingSurfaceFinished, callback,
- base::Passed(&release_callback), base::Passed(&bitmap),
- base::Passed(&bitmap_pixels_lock)),
- GLHelper::SCALER_QUALITY_GOOD);
-}
-
-// static
-void DelegatedFrameHost::PrepareBitmapCopyOutputResult(
- const gfx::Size& dst_size_in_pixel,
- const SkColorType preferred_color_type,
- const ReadbackRequestCallback& callback,
- scoped_ptr<cc::CopyOutputResult> result) {
- SkColorType color_type = preferred_color_type;
- if (color_type != kN32_SkColorType && color_type != kAlpha_8_SkColorType) {
- // Switch back to default colortype if format not supported.
- color_type = kN32_SkColorType;
- }
- DCHECK(result->HasBitmap());
- scoped_ptr<SkBitmap> source = result->TakeBitmap();
- DCHECK(source);
- SkBitmap scaled_bitmap;
- if (source->width() != dst_size_in_pixel.width() ||
- source->height() != dst_size_in_pixel.height()) {
- scaled_bitmap =
- skia::ImageOperations::Resize(*source,
- skia::ImageOperations::RESIZE_BEST,
- dst_size_in_pixel.width(),
- dst_size_in_pixel.height());
- } else {
- scaled_bitmap = *source;
- }
- if (color_type == kN32_SkColorType) {
- DCHECK_EQ(scaled_bitmap.colorType(), kN32_SkColorType);
- callback.Run(scaled_bitmap, READBACK_SUCCESS);
- return;
- }
- DCHECK_EQ(color_type, kAlpha_8_SkColorType);
- // The software path currently always returns N32 bitmap regardless of the
- // |color_type| we ask for.
- DCHECK_EQ(scaled_bitmap.colorType(), kN32_SkColorType);
- // Paint |scaledBitmap| to alpha-only |grayscale_bitmap|.
- SkBitmap grayscale_bitmap;
- bool success = grayscale_bitmap.tryAllocPixels(
- SkImageInfo::MakeA8(scaled_bitmap.width(), scaled_bitmap.height()));
- if (!success) {
- callback.Run(SkBitmap(), content::READBACK_BITMAP_ALLOCATION_FAILURE);
- return;
- }
- SkCanvas canvas(grayscale_bitmap);
- SkPaint paint;
- skia::RefPtr<SkColorFilter> filter =
- skia::AdoptRef(SkLumaColorFilter::Create());
- paint.setColorFilter(filter.get());
- canvas.drawBitmap(scaled_bitmap, SkIntToScalar(0), SkIntToScalar(0), &paint);
- callback.Run(grayscale_bitmap, READBACK_SUCCESS);
+ UpdateGutters();
}
// static
@@ -790,9 +613,8 @@ void DelegatedFrameHost::CopyFromCompositingSurfaceHasResultForVideo(
scoped_ptr<cc::CopyOutputResult> result) {
base::ScopedClosureRunner scoped_callback_runner(
base::Bind(callback, gfx::Rect(), false));
- base::ScopedClosureRunner scoped_return_subscriber_texture(
- base::Bind(&ReturnSubscriberTexture, dfh, subscriber_texture,
- gpu::SyncToken()));
+ base::ScopedClosureRunner scoped_return_subscriber_texture(base::Bind(
+ &ReturnSubscriberTexture, dfh, subscriber_texture, gpu::SyncToken()));
if (!dfh)
return;
@@ -809,10 +631,9 @@ void DelegatedFrameHost::CopyFromCompositingSurfaceHasResultForVideo(
// pixels.
gfx::Rect region_in_frame = media::ComputeLetterboxRegion(
video_frame->visible_rect(), result->size());
- region_in_frame = gfx::Rect(region_in_frame.x() & ~1,
- region_in_frame.y() & ~1,
- region_in_frame.width() & ~1,
- region_in_frame.height() & ~1);
+ region_in_frame =
+ gfx::Rect(region_in_frame.x() & ~1, region_in_frame.y() & ~1,
+ region_in_frame.width() & ~1, region_in_frame.height() & ~1);
if (region_in_frame.IsEmpty())
return;
@@ -863,30 +684,23 @@ void DelegatedFrameHost::CopyFromCompositingSurfaceHasResultForVideo(
yuv_readback_pipeline->scaler()->SrcSize() != result_rect.size() ||
yuv_readback_pipeline->scaler()->SrcSubrect() != result_rect ||
yuv_readback_pipeline->scaler()->DstSize() != region_in_frame.size()) {
- GLHelper::ScalerQuality quality = GLHelper::SCALER_QUALITY_FAST;
- std::string quality_switch = switches::kTabCaptureDownscaleQuality;
- // If we're scaling up, we can use the "best" quality.
- if (result_rect.size().width() < region_in_frame.size().width() &&
- result_rect.size().height() < region_in_frame.size().height())
- quality_switch = switches::kTabCaptureUpscaleQuality;
-
- std::string switch_value =
- base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- quality_switch);
- if (switch_value == "fast")
- quality = GLHelper::SCALER_QUALITY_FAST;
- else if (switch_value == "good")
- quality = GLHelper::SCALER_QUALITY_GOOD;
- else if (switch_value == "best")
- quality = GLHelper::SCALER_QUALITY_BEST;
-
- dfh->yuv_readback_pipeline_.reset(
- gl_helper->CreateReadbackPipelineYUV(quality,
- result_rect.size(),
- result_rect,
- region_in_frame.size(),
- true,
- true));
+ // The scaler chosen here is based on performance measurements of full
+ // end-to-end systems. When down-scaling, always use the "fast" scaler
+ // because it performs well on both low- and high- end machines, provides
+ // decent image quality, and doesn't overwhelm downstream video encoders
+ // with too much entropy (which can drastically increase CPU utilization).
+ // When up-scaling, always use "best" because the quality improvement is
+ // huge with insignificant performance penalty. Note that this strategy
+ // differs from single-frame snapshot capture.
+ GLHelper::ScalerQuality quality =
+ ((result_rect.size().width() < region_in_frame.size().width()) &&
+ (result_rect.size().height() < region_in_frame.size().height()))
+ ? GLHelper::SCALER_QUALITY_BEST
+ : GLHelper::SCALER_QUALITY_FAST;
+
+ dfh->yuv_readback_pipeline_.reset(gl_helper->CreateReadbackPipelineYUV(
+ quality, result_rect.size(), result_rect, region_in_frame.size(), true,
+ true));
yuv_readback_pipeline = dfh->yuv_readback_pipeline_.get();
}
@@ -897,24 +711,20 @@ void DelegatedFrameHost::CopyFromCompositingSurfaceHasResultForVideo(
&DelegatedFrameHost::CopyFromCompositingSurfaceFinishedForVideo,
dfh->AsWeakPtr(), base::Bind(callback, region_in_frame),
subscriber_texture, base::Passed(&release_callback));
- yuv_readback_pipeline->ReadbackYUV(texture_mailbox.mailbox(),
- texture_mailbox.sync_token(),
- video_frame.get(),
- region_in_frame.origin(),
- finished_callback);
+ yuv_readback_pipeline->ReadbackYUV(
+ texture_mailbox.mailbox(), texture_mailbox.sync_token(),
+ video_frame.get(), region_in_frame.origin(), finished_callback);
}
////////////////////////////////////////////////////////////////////////////////
// DelegatedFrameHost, ui::CompositorObserver implementation:
-void DelegatedFrameHost::OnCompositingDidCommit(
- ui::Compositor* compositor) {
+void DelegatedFrameHost::OnCompositingDidCommit(ui::Compositor* compositor) {
if (can_lock_compositor_ == NO_PENDING_COMMIT) {
can_lock_compositor_ = YES_CAN_LOCK;
if (resize_lock_.get() && resize_lock_->GrabDeferredLock())
can_lock_compositor_ = YES_DID_LOCK;
}
- RunOnCommitCallbacks();
if (resize_lock_ &&
resize_lock_->expected_size() == current_frame_size_in_dip_) {
resize_lock_.reset();
@@ -926,17 +736,14 @@ void DelegatedFrameHost::OnCompositingDidCommit(
}
}
-void DelegatedFrameHost::OnCompositingStarted(
- ui::Compositor* compositor, base::TimeTicks start_time) {
+void DelegatedFrameHost::OnCompositingStarted(ui::Compositor* compositor,
+ base::TimeTicks start_time) {
last_draw_ended_ = start_time;
}
-void DelegatedFrameHost::OnCompositingEnded(
- ui::Compositor* compositor) {
-}
+void DelegatedFrameHost::OnCompositingEnded(ui::Compositor* compositor) {}
-void DelegatedFrameHost::OnCompositingAborted(ui::Compositor* compositor) {
-}
+void DelegatedFrameHost::OnCompositingAborted(ui::Compositor* compositor) {}
void DelegatedFrameHost::OnCompositingLockStateChanged(
ui::Compositor* compositor) {
@@ -953,9 +760,8 @@ void DelegatedFrameHost::OnCompositingShuttingDown(ui::Compositor* compositor) {
DCHECK(!compositor_);
}
-void DelegatedFrameHost::OnUpdateVSyncParameters(
- base::TimeTicks timebase,
- base::TimeDelta interval) {
+void DelegatedFrameHost::OnUpdateVSyncParameters(base::TimeTicks timebase,
+ base::TimeDelta interval) {
SetVSyncParameters(timebase, interval);
if (client_->DelegatedFrameHostIsVisible())
client_->DelegatedFrameHostUpdateVSyncParameters(timebase, interval);
@@ -965,7 +771,7 @@ void DelegatedFrameHost::OnUpdateVSyncParameters(
// DelegatedFrameHost, ImageTransportFactoryObserver implementation:
void DelegatedFrameHost::OnLostResources() {
- if (frame_provider_.get() || !surface_id_.is_null())
+ if (!surface_id_.is_null())
EvictDelegatedFrame();
idle_frame_subscriber_textures_.clear();
yuv_readback_pipeline_.reset();
@@ -978,34 +784,17 @@ void DelegatedFrameHost::OnLostResources() {
DelegatedFrameHost::~DelegatedFrameHost() {
DCHECK(!compositor_);
- ImageTransportFactory::GetInstance()->RemoveObserver(this);
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ factory->RemoveObserver(this);
if (!surface_id_.is_null())
surface_factory_->Destroy(surface_id_);
- if (resource_collection_.get())
- resource_collection_->SetClient(NULL);
+ factory->GetSurfaceManager()->UnregisterSurfaceFactoryClient(
+ id_allocator_->id_namespace());
DCHECK(!vsync_manager_.get());
}
-void DelegatedFrameHost::RunOnCommitCallbacks() {
- for (std::vector<base::Closure>::const_iterator
- it = on_compositing_did_commit_callbacks_.begin();
- it != on_compositing_did_commit_callbacks_.end(); ++it) {
- it->Run();
- }
- on_compositing_did_commit_callbacks_.clear();
-}
-
-void DelegatedFrameHost::AddOnCommitCallbackAndDisableLocks(
- const base::Closure& callback) {
- DCHECK(compositor_);
-
- can_lock_compositor_ = NO_PENDING_COMMIT;
- if (!callback.is_null())
- on_compositing_did_commit_callbacks_.push_back(callback);
-}
-
void DelegatedFrameHost::SetCompositor(ui::Compositor* compositor) {
DCHECK(!compositor_);
if (!compositor)
@@ -1015,12 +804,16 @@ void DelegatedFrameHost::SetCompositor(ui::Compositor* compositor) {
DCHECK(!vsync_manager_.get());
vsync_manager_ = compositor_->vsync_manager();
vsync_manager_->AddObserver(this);
+
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ uint32_t parent = compositor->surface_id_allocator()->id_namespace();
+ factory->GetSurfaceManager()->RegisterSurfaceNamespaceHierarchy(
+ parent, id_allocator_->id_namespace());
}
void DelegatedFrameHost::ResetCompositor() {
if (!compositor_)
return;
- RunOnCommitCallbacks();
if (resize_lock_) {
resize_lock_.reset();
client_->DelegatedFrameHostResizeLockWasReleased();
@@ -1031,6 +824,12 @@ void DelegatedFrameHost::ResetCompositor() {
vsync_manager_->RemoveObserver(this);
vsync_manager_ = NULL;
}
+
+ ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
+ uint32_t parent = compositor_->surface_id_allocator()->id_namespace();
+ factory->GetSurfaceManager()->UnregisterSurfaceNamespaceHierarchy(
+ parent, id_allocator_->id_namespace());
+
compositor_ = nullptr;
}
@@ -1041,21 +840,22 @@ void DelegatedFrameHost::SetVSyncParameters(const base::TimeTicks& timebase,
}
void DelegatedFrameHost::LockResources() {
- DCHECK(frame_provider_.get() || !surface_id_.is_null());
+ DCHECK(!surface_id_.is_null());
delegated_frame_evictor_->LockFrame();
}
void DelegatedFrameHost::RequestCopyOfOutput(
scoped_ptr<cc::CopyOutputRequest> request) {
- if (!request_copy_of_output_callback_for_testing_.is_null())
+ if (!request_copy_of_output_callback_for_testing_.is_null()) {
request_copy_of_output_callback_for_testing_.Run(std::move(request));
- else
+ } else {
client_->DelegatedFrameHostGetLayer()->RequestCopyOfOutput(
std::move(request));
+ }
}
void DelegatedFrameHost::UnlockResources() {
- DCHECK(frame_provider_.get() || !surface_id_.is_null());
+ DCHECK(!surface_id_.is_null());
delegated_frame_evictor_->UnlockFrame();
}
@@ -1063,14 +863,10 @@ void DelegatedFrameHost::UnlockResources() {
// DelegatedFrameHost, ui::LayerOwnerDelegate implementation:
void DelegatedFrameHost::OnLayerRecreated(ui::Layer* old_layer,
- ui::Layer* new_layer) {
+ ui::Layer* new_layer) {
// The new_layer is the one that will be used by our Window, so that's the one
// that should keep our frame. old_layer will be returned to the
// RecreateLayer caller, and should have a copy.
- if (frame_provider_.get()) {
- new_layer->SetShowDelegatedContent(frame_provider_.get(),
- current_frame_size_in_dip_);
- }
if (!surface_id_.is_null()) {
ImageTransportFactory* factory = ImageTransportFactory::GetInstance();
cc::SurfaceManager* manager = factory->GetSurfaceManager();
diff --git a/chromium/content/browser/compositor/delegated_frame_host.h b/chromium/content/browser/renderer_host/delegated_frame_host.h
index 21dc4e0c8f9..9f2b1813acc 100644
--- a/chromium/content/browser/compositor/delegated_frame_host.h
+++ b/chromium/content/browser/renderer_host/delegated_frame_host.h
@@ -2,16 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_BROWSER_COMPOSITOR_DELEGATED_FRAME_HOST_H_
-#define CONTENT_BROWSER_COMPOSITOR_DELEGATED_FRAME_HOST_H_
+#ifndef CONTENT_BROWSER_RENDERER_HOST_DELEGATED_FRAME_HOST_H_
+#define CONTENT_BROWSER_RENDERER_HOST_DELEGATED_FRAME_HOST_H_
#include <stdint.h>
#include <vector>
#include "base/gtest_prod_util.h"
-#include "cc/layers/delegated_frame_provider.h"
-#include "cc/layers/delegated_frame_resource_collection.h"
#include "cc/output/copy_output_result.h"
#include "cc/surfaces/surface_factory_client.h"
#include "content/browser/compositor/image_transport_factory.h"
@@ -87,7 +85,6 @@ class CONTENT_EXPORT DelegatedFrameHost
public ui::LayerOwnerDelegate,
public ImageTransportFactoryObserver,
public DelegatedFrameEvictorClient,
- public cc::DelegatedFrameResourceCollectionClient,
public cc::SurfaceFactoryClient,
public base::SupportsWeakPtr<DelegatedFrameHost> {
public:
@@ -116,14 +113,10 @@ class CONTENT_EXPORT DelegatedFrameHost
// DelegatedFrameEvictorClient implementation.
void EvictDelegatedFrame() override;
- // cc::DelegatedFrameProviderClient implementation.
- void UnusedResourcesAreAvailable() override;
-
// cc::SurfaceFactoryClient implementation.
void ReturnResources(const cc::ReturnedResourceArray& resources) override;
void WillDrawSurface(cc::SurfaceId id, const gfx::Rect& damage_rect) override;
- void SetBeginFrameSource(cc::SurfaceId surface_id,
- cc::BeginFrameSource* begin_frame_source) override;
+ void SetBeginFrameSource(cc::BeginFrameSource* begin_frame_source) override;
bool CanCopyToBitmap() const;
@@ -155,11 +148,12 @@ class CONTENT_EXPORT DelegatedFrameHost
void BeginFrameSubscription(
scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber);
void EndFrameSubscription();
- bool HasFrameSubscriber() const { return frame_subscriber_; }
+ bool HasFrameSubscriber() const { return !!frame_subscriber_; }
uint32_t GetSurfaceIdNamespace();
// Returns a null SurfaceId if this DelegatedFrameHost has not yet created
// a compositor Surface.
- cc::SurfaceId SurfaceIdAtPoint(const gfx::Point& point,
+ cc::SurfaceId SurfaceIdAtPoint(cc::SurfaceHittestDelegate* delegate,
+ const gfx::Point& point,
gfx::Point* transformed_point);
// Given the SurfaceID of a Surface that is contained within this class'
@@ -171,9 +165,6 @@ class CONTENT_EXPORT DelegatedFrameHost
gfx::Point* transformed_point);
// Exposed for tests.
- cc::DelegatedFrameProvider* FrameProviderForTesting() const {
- return frame_provider_.get();
- }
cc::SurfaceId SurfaceIdForTesting() const { return surface_id_; }
void OnCompositingDidCommitForTesting(ui::Compositor* compositor) {
OnCompositingDidCommit(compositor);
@@ -211,29 +202,12 @@ class CONTENT_EXPORT DelegatedFrameHost
// Checks if the resize lock can be released because we received an new frame.
void CheckResizeLock();
- // Run all on compositing commit callbacks.
- void RunOnCommitCallbacks();
-
- // Add on compositing commit callback.
- void AddOnCommitCallbackAndDisableLocks(const base::Closure& callback);
+ // Update the layers for the resize gutters to the right and bottom of the
+ // surface layer.
+ void UpdateGutters();
// Called after async thumbnailer task completes. Scales and crops the result
// of the copy.
- static void CopyFromCompositingSurfaceHasResult(
- const gfx::Size& dst_size_in_pixel,
- const SkColorType color_type,
- const ReadbackRequestCallback& callback,
- scoped_ptr<cc::CopyOutputResult> result);
- static void PrepareTextureCopyOutputResult(
- const gfx::Size& dst_size_in_pixel,
- const SkColorType color_type,
- const ReadbackRequestCallback& callback,
- scoped_ptr<cc::CopyOutputResult> result);
- static void PrepareBitmapCopyOutputResult(
- const gfx::Size& dst_size_in_pixel,
- const SkColorType color_type,
- const ReadbackRequestCallback& callback,
- scoped_ptr<cc::CopyOutputResult> result);
static void CopyFromCompositingSurfaceHasResultForVideo(
base::WeakPtr<DelegatedFrameHost> rwhva,
scoped_refptr<OwnedMailbox> subscriber_texture,
@@ -262,12 +236,6 @@ class CONTENT_EXPORT DelegatedFrameHost
DelegatedFrameHostClient* const client_;
ui::Compositor* compositor_;
- // True if this renders into a Surface, false if it renders into a delegated
- // layer.
- bool use_surfaces_;
-
- std::vector<base::Closure> on_compositing_did_commit_callbacks_;
-
// The vsync manager we are observing for changes, if any.
scoped_refptr<ui::CompositorVSyncManager> vsync_manager_;
@@ -293,13 +261,11 @@ class CONTENT_EXPORT DelegatedFrameHost
bool skipped_frames_;
std::vector<ui::LatencyInfo> skipped_latency_info_list_;
- // Holds delegated resources that have been given to a DelegatedFrameProvider,
- // and gives back resources when they are no longer in use for return to the
- // renderer.
- scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection_;
+ scoped_ptr<ui::Layer> right_gutter_;
+ scoped_ptr<ui::Layer> bottom_gutter_;
- // Provides delegated frame updates to the cc::DelegatedRendererLayer.
- scoped_refptr<cc::DelegatedFrameProvider> frame_provider_;
+ // This is the last root background color from a swapped frame.
+ SkColor background_color_;
// State for rendering into a Surface.
scoped_ptr<cc::SurfaceIdAllocator> id_allocator_;
@@ -338,7 +304,7 @@ class CONTENT_EXPORT DelegatedFrameHost
// Subscriber that listens to frame presentation events.
scoped_ptr<RenderWidgetHostViewFrameSubscriber> frame_subscriber_;
- std::vector<scoped_refptr<OwnedMailbox> > idle_frame_subscriber_textures_;
+ std::vector<scoped_refptr<OwnedMailbox>> idle_frame_subscriber_textures_;
// Callback used to pass the output request to the layer or to a function
// specified by a test.
@@ -346,12 +312,13 @@ class CONTENT_EXPORT DelegatedFrameHost
request_copy_of_output_callback_for_testing_;
// YUV readback pipeline.
- scoped_ptr<content::ReadbackYUVInterface>
- yuv_readback_pipeline_;
+ scoped_ptr<content::ReadbackYUVInterface> yuv_readback_pipeline_;
scoped_ptr<DelegatedFrameEvictor> delegated_frame_evictor_;
+
+ cc::BeginFrameSource* begin_frame_source_;
};
} // namespace content
-#endif // CONTENT_BROWSER_COMPOSITOR_DELEGATED_FRAME_HOST_H_
+#endif // CONTENT_BROWSER_RENDERER_HOST_DELEGATED_FRAME_HOST_H_
diff --git a/chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc b/chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc
index 5d186424b66..6d16572b4fe 100644
--- a/chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc
+++ b/chromium/content/browser/renderer_host/dwrite_font_proxy_message_filter_win.cc
@@ -142,13 +142,15 @@ void DWriteFontProxyMessageFilter::OnGetFamilyNames(
mswr::ComPtr<IDWriteFontFamily> family;
HRESULT hr = collection_->GetFontFamily(family_index, &family);
- if (!SUCCEEDED(hr))
+ if (!SUCCEEDED(hr)) {
return;
+ }
mswr::ComPtr<IDWriteLocalizedStrings> localized_names;
hr = family->GetFamilyNames(&localized_names);
- if (!SUCCEEDED(hr))
+ if (!SUCCEEDED(hr)) {
return;
+ }
size_t string_count = localized_names->GetCount();
@@ -157,25 +159,29 @@ void DWriteFontProxyMessageFilter::OnGetFamilyNames(
for (size_t index = 0; index < string_count; ++index) {
UINT32 length = 0;
hr = localized_names->GetLocaleNameLength(index, &length);
- if (!SUCCEEDED(hr))
+ if (!SUCCEEDED(hr)) {
return;
+ }
++length; // Reserve space for the null terminator.
locale.resize(length);
hr = localized_names->GetLocaleName(index, locale.data(), length);
- if (!SUCCEEDED(hr))
+ if (!SUCCEEDED(hr)) {
return;
- DCHECK_EQ(L'\0', locale[length - 1]);
+ }
+ CHECK_EQ(L'\0', locale[length - 1]);
length = 0;
hr = localized_names->GetStringLength(index, &length);
- if (!SUCCEEDED(hr))
+ if (!SUCCEEDED(hr)) {
return;
+ }
++length; // Reserve space for the null terminator.
name.resize(length);
hr = localized_names->GetString(index, name.data(), length);
- if (!SUCCEEDED(hr))
+ if (!SUCCEEDED(hr)) {
return;
- DCHECK_EQ(L'\0', name[length - 1]);
+ }
+ CHECK_EQ(L'\0', name[length - 1]);
// Would be great to use emplace_back instead.
family_names->push_back(std::pair<base::string16, base::string16>(
@@ -194,8 +200,9 @@ void DWriteFontProxyMessageFilter::OnGetFontFiles(
mswr::ComPtr<IDWriteFontFamily> family;
HRESULT hr = collection_->GetFontFamily(family_index, &family);
- if (!SUCCEEDED(hr))
+ if (!SUCCEEDED(hr)) {
return;
+ }
UINT32 font_count = family->GetFontCount();
@@ -206,8 +213,9 @@ void DWriteFontProxyMessageFilter::OnGetFontFiles(
for (UINT32 font_index = 0; font_index < font_count; ++font_index) {
mswr::ComPtr<IDWriteFont> font;
hr = family->GetFont(font_index, &font);
- if (!SUCCEEDED(hr))
+ if (!SUCCEEDED(hr)) {
return;
+ }
AddFilesForFont(&path_set, font.Get());
}
@@ -239,26 +247,30 @@ bool DWriteFontProxyMessageFilter::AddFilesForFont(
mswr::ComPtr<IDWriteFontFace> font_face;
HRESULT hr;
hr = font->CreateFontFace(&font_face);
- if (!SUCCEEDED(hr))
+ if (!SUCCEEDED(hr)) {
return false;
+ }
UINT32 file_count;
hr = font_face->GetFiles(&file_count, nullptr);
- if (!SUCCEEDED(hr))
+ if (!SUCCEEDED(hr)) {
return false;
+ }
std::vector<mswr::ComPtr<IDWriteFontFile>> font_files;
font_files.resize(file_count);
hr = font_face->GetFiles(
&file_count, reinterpret_cast<IDWriteFontFile**>(font_files.data()));
- if (!SUCCEEDED(hr))
+ if (!SUCCEEDED(hr)) {
return false;
+ }
for (unsigned int file_index = 0; file_index < file_count; ++file_index) {
mswr::ComPtr<IDWriteFontFileLoader> loader;
hr = font_files[file_index]->GetLoader(&loader);
- if (!SUCCEEDED(hr))
+ if (!SUCCEEDED(hr)) {
return false;
+ }
mswr::ComPtr<IDWriteLocalFontFileLoader> local_loader;
hr = loader.CopyTo(local_loader.GetAddressOf()); // QueryInterface.
@@ -271,10 +283,11 @@ bool DWriteFontProxyMessageFilter::AddFilesForFont(
// for this font, forcing blink/skia to fall back to whatever font is
// next). If we get telemetry indicating that this case actually
// happens, we can implement this by exposing the loader via ipc. That
- // will likely by loading the font data into shared memory, although we
- // could proxy the stream reads directly instead.
+ // will likely be by loading the font data into shared memory, although
+ // we could proxy the stream reads directly instead.
LogLoaderType(OTHER_LOADER);
DCHECK(false);
+
return false;
} else if (!SUCCEEDED(hr)) {
return false;
@@ -296,20 +309,23 @@ bool DWriteFontProxyMessageFilter::AddLocalFile(
const void* key;
UINT32 key_size;
hr = font_file->GetReferenceKey(&key, &key_size);
- if (!SUCCEEDED(hr))
+ if (!SUCCEEDED(hr)) {
return false;
+ }
UINT32 path_length = 0;
hr = local_loader->GetFilePathLengthFromKey(key, key_size, &path_length);
- if (!SUCCEEDED(hr))
+ if (!SUCCEEDED(hr)) {
return false;
+ }
++path_length; // Reserve space for the null terminator.
std::vector<base::char16> file_path_chars;
file_path_chars.resize(path_length);
hr = local_loader->GetFilePathFromKey(key, key_size, file_path_chars.data(),
path_length);
- if (!SUCCEEDED(hr))
+ if (!SUCCEEDED(hr)) {
return false;
+ }
base::string16 file_path = base::i18n::FoldCase(file_path_chars.data());
if (!base::StartsWith(file_path, windows_fonts_path_,
@@ -319,6 +335,12 @@ bool DWriteFontProxyMessageFilter::AddLocalFile(
// this turns out to be a common case, we can either grant the renderer
// access to these files (not sure if this is actually possible), or
// load the file data ourselves and hand it to the renderer.
+
+ // Really, really, really want to know what families hit this. Current
+ // data indicates about 0.09% of families fall into this case. Nothing to
+ // worry about if it's random obscure fonts noone has ever heard of, but
+ // could be a problem if it's common fonts.
+
LogLoaderType(FILE_OUTSIDE_SANDBOX);
NOTREACHED(); // Not yet implemented.
return false;
diff --git a/chromium/content/browser/renderer_host/event_with_latency_info.h b/chromium/content/browser/renderer_host/event_with_latency_info.h
index f55bb0c4e89..0ff2b4c4eea 100644
--- a/chromium/content/browser/renderer_host/event_with_latency_info.h
+++ b/chromium/content/browser/renderer_host/event_with_latency_info.h
@@ -5,66 +5,13 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_EVENT_WITH_LATENCY_INFO_H_
#define CONTENT_BROWSER_RENDERER_HOST_EVENT_WITH_LATENCY_INFO_H_
-#include "ui/events/latency_info.h"
-
-#include "content/common/input/web_input_event_traits.h"
+#include "content/common/input/event_with_latency_info.h"
#include "content/public/browser/native_web_keyboard_event.h"
-namespace blink {
-class WebGestureEvent;
-class WebMouseEvent;
-class WebMouseWheelEvent;
-class WebTouchEvent;
-}
-
namespace content {
-template <typename T>
-class EventWithLatencyInfo {
- public:
- T event;
- mutable ui::LatencyInfo latency;
-
- explicit EventWithLatencyInfo(const T& e) : event(e) {}
-
- EventWithLatencyInfo(const T& e, const ui::LatencyInfo& l)
- : event(e), latency(l) {}
-
- EventWithLatencyInfo() {}
-
- bool CanCoalesceWith(const EventWithLatencyInfo& other)
- const WARN_UNUSED_RESULT {
- return WebInputEventTraits::CanCoalesce(other.event, event);
- }
-
- void CoalesceWith(const EventWithLatencyInfo& other) {
- // |other| should be a newer event than |this|.
- if (other.latency.trace_id() >= 0 && latency.trace_id() >= 0)
- DCHECK_GT(other.latency.trace_id(), latency.trace_id());
- double old_timestamp = event.timeStampSeconds;
- WebInputEventTraits::Coalesce(other.event, &event);
- // When coalescing two input events, we keep the oldest LatencyInfo
- // for Telemetry latency test since it will represent the longest
- // latency.
- if (other.latency.trace_id() >= 0 &&
- (latency.trace_id() < 0 ||
- other.latency.trace_id() < latency.trace_id())) {
- latency = other.latency;
- }
- latency.AddCoalescedEventTimestamp(old_timestamp);
- }
-};
-
typedef EventWithLatencyInfo<NativeWebKeyboardEvent>
NativeWebKeyboardEventWithLatencyInfo;
-typedef EventWithLatencyInfo<blink::WebGestureEvent>
- GestureEventWithLatencyInfo;
-typedef EventWithLatencyInfo<blink::WebMouseWheelEvent>
- MouseWheelEventWithLatencyInfo;
-typedef EventWithLatencyInfo<blink::WebMouseEvent>
- MouseEventWithLatencyInfo;
-typedef EventWithLatencyInfo<blink::WebTouchEvent>
- TouchEventWithLatencyInfo;
} // namespace content
diff --git a/chromium/content/browser/renderer_host/font_utils_linux.cc b/chromium/content/browser/renderer_host/font_utils_linux.cc
index 715923d6b88..245475f6650 100644
--- a/chromium/content/browser/renderer_host/font_utils_linux.cc
+++ b/chromium/content/browser/renderer_host/font_utils_linux.cc
@@ -12,8 +12,8 @@
#include <string>
#include "base/posix/eintr_wrapper.h"
+#include "ppapi/c/private/pp_private_font_charset.h"
#include "ppapi/c/trusted/ppb_browser_font_trusted.h"
-#include "third_party/npapi/bindings/npapi_extensions.h"
namespace {
@@ -41,30 +41,30 @@ bool MSCharSetToFontconfig(FcLangSet* langset, unsigned fdwCharSet) {
bool is_lgc = false;
switch (fdwCharSet) {
- case NPCharsetAnsi:
+ case PP_PRIVATEFONTCHARSET_ANSI:
// These values I don't really know what to do with, so I'm going to map
// them to English also.
- case NPCharsetDefault:
- case NPCharsetMac:
- case NPCharsetOEM:
- case NPCharsetSymbol:
+ case PP_PRIVATEFONTCHARSET_DEFAULT:
+ case PP_PRIVATEFONTCHARSET_MAC:
+ case PP_PRIVATEFONTCHARSET_OEM:
+ case PP_PRIVATEFONTCHARSET_SYMBOL:
is_lgc = true;
FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("en"));
break;
- case NPCharsetBaltic:
+ case PP_PRIVATEFONTCHARSET_BALTIC:
// The three baltic languages.
is_lgc = true;
FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("et"));
FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("lv"));
FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("lt"));
break;
- case NPCharsetChineseBIG5:
+ case PP_PRIVATEFONTCHARSET_CHINESEBIG5:
FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("zh-tw"));
break;
- case NPCharsetGB2312:
+ case PP_PRIVATEFONTCHARSET_GB2312:
FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("zh-cn"));
break;
- case NPCharsetEastEurope:
+ case PP_PRIVATEFONTCHARSET_EASTEUROPE:
// A scattering of eastern European languages.
is_lgc = true;
FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("pl"));
@@ -73,38 +73,38 @@ bool MSCharSetToFontconfig(FcLangSet* langset, unsigned fdwCharSet) {
FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("hu"));
FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("hr"));
break;
- case NPCharsetGreek:
+ case PP_PRIVATEFONTCHARSET_GREEK:
is_lgc = true;
FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("el"));
break;
- case NPCharsetHangul:
- case NPCharsetJohab:
+ case PP_PRIVATEFONTCHARSET_HANGUL:
+ case PP_PRIVATEFONTCHARSET_JOHAB:
// Korean
FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ko"));
break;
- case NPCharsetRussian:
+ case PP_PRIVATEFONTCHARSET_RUSSIAN:
is_lgc = true;
FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ru"));
break;
- case NPCharsetShiftJIS:
+ case PP_PRIVATEFONTCHARSET_SHIFTJIS:
// Japanese
FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ja"));
break;
- case NPCharsetTurkish:
+ case PP_PRIVATEFONTCHARSET_TURKISH:
is_lgc = true;
FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("tr"));
break;
- case NPCharsetVietnamese:
+ case PP_PRIVATEFONTCHARSET_VIETNAMESE:
is_lgc = true;
FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("vi"));
break;
- case NPCharsetArabic:
+ case PP_PRIVATEFONTCHARSET_ARABIC:
FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("ar"));
break;
- case NPCharsetHebrew:
+ case PP_PRIVATEFONTCHARSET_HEBREW:
FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("he"));
break;
- case NPCharsetThai:
+ case PP_PRIVATEFONTCHARSET_THAI:
FcLangSetAdd(langset, reinterpret_cast<const FcChar8*>("th"));
break;
// default:
diff --git a/chromium/content/browser/renderer_host/gpu_message_filter.cc b/chromium/content/browser/renderer_host/gpu_message_filter.cc
deleted file mode 100644
index 95355b3e3e1..00000000000
--- a/chromium/content/browser/renderer_host/gpu_message_filter.cc
+++ /dev/null
@@ -1,95 +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.
-
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-
-#include "content/browser/renderer_host/gpu_message_filter.h"
-
-#include "base/bind.h"
-#include "build/build_config.h"
-#include "content/browser/gpu/gpu_data_manager_impl.h"
-#include "content/browser/gpu/gpu_process_host.h"
-#include "content/common/child_process_host_impl.h"
-#include "content/common/gpu/gpu_messages.h"
-
-namespace content {
-
-GpuMessageFilter::GpuMessageFilter(int render_process_id)
- : BrowserMessageFilter(GpuMsgStart),
- gpu_process_id_(0),
- render_process_id_(render_process_id),
- weak_ptr_factory_(this) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-}
-
-GpuMessageFilter::~GpuMessageFilter() {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-}
-
-bool GpuMessageFilter::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(GpuMessageFilter, message)
- IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuHostMsg_EstablishGpuChannel,
- OnEstablishGpuChannel)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void GpuMessageFilter::OnEstablishGpuChannel(
- CauseForGpuLaunch cause_for_gpu_launch,
- IPC::Message* reply_ptr) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- scoped_ptr<IPC::Message> reply(reply_ptr);
-
-#if defined(OS_WIN) && defined(ARCH_CPU_X86_64)
- // TODO(jbauman): Remove this when we know why renderer processes are
- // hanging on x86-64. https://crbug.com/577127
- if (!GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor()) {
- reply->set_reply_error();
- Send(reply.release());
- return;
- }
-#endif
-
- GpuProcessHost* host = GpuProcessHost::FromID(gpu_process_id_);
- if (!host) {
- host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
- cause_for_gpu_launch);
- if (!host) {
- reply->set_reply_error();
- Send(reply.release());
- return;
- }
-
- gpu_process_id_ = host->host_id();
- }
-
- bool preempts = false;
- bool preempted = true;
- bool allow_future_sync_points = false;
- bool allow_real_time_streams = false;
- host->EstablishGpuChannel(
- render_process_id_,
- ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId(
- render_process_id_),
- preempts, preempted, allow_future_sync_points, allow_real_time_streams,
- base::Bind(&GpuMessageFilter::EstablishChannelCallback,
- weak_ptr_factory_.GetWeakPtr(), base::Passed(&reply)));
-}
-
-void GpuMessageFilter::EstablishChannelCallback(
- scoped_ptr<IPC::Message> reply,
- const IPC::ChannelHandle& channel,
- const gpu::GPUInfo& gpu_info) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- GpuHostMsg_EstablishGpuChannel::WriteReplyParams(
- reply.get(), render_process_id_, channel, gpu_info);
- Send(reply.release());
-}
-
-} // namespace content
diff --git a/chromium/content/browser/renderer_host/gpu_message_filter.h b/chromium/content/browser/renderer_host/gpu_message_filter.h
deleted file mode 100644
index 393d0babdc6..00000000000
--- a/chromium/content/browser/renderer_host/gpu_message_filter.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.
-
-#ifndef CONTENT_BROWSER_RENDERER_HOST_GPU_MESSAGE_FILTER_H_
-#define CONTENT_BROWSER_RENDERER_HOST_GPU_MESSAGE_FILTER_H_
-
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
-#include "content/public/browser/browser_message_filter.h"
-
-namespace gpu {
-struct GPUInfo;
-}
-
-namespace content {
-
-// A message filter for messages from the renderer to the GpuProcessHost
-// in the browser. Such messages are typically destined for the GPU process,
-// but need to be mediated by the browser.
-class GpuMessageFilter : public BrowserMessageFilter {
- public:
- GpuMessageFilter(int render_process_id);
-
- // BrowserMessageFilter methods:
- bool OnMessageReceived(const IPC::Message& message) override;
-
- private:
- friend class BrowserThread;
- friend class base::DeleteHelper<GpuMessageFilter>;
-
- ~GpuMessageFilter() override;
-
- // Message handlers called on the browser IO thread:
- void OnEstablishGpuChannel(CauseForGpuLaunch,
- IPC::Message* reply);
- // Helper callbacks for the message handlers.
- void EstablishChannelCallback(scoped_ptr<IPC::Message> reply,
- const IPC::ChannelHandle& channel,
- const gpu::GPUInfo& gpu_info);
-
- int gpu_process_id_;
- int render_process_id_;
-
- base::WeakPtrFactory<GpuMessageFilter> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuMessageFilter);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_GPU_MESSAGE_FILTER_H_
diff --git a/chromium/content/browser/renderer_host/ime_adapter_android.cc b/chromium/content/browser/renderer_host/ime_adapter_android.cc
index d70d4969d2e..233c0425b11 100644
--- a/chromium/content/browser/renderer_host/ime_adapter_android.cc
+++ b/chromium/content/browser/renderer_host/ime_adapter_android.cc
@@ -9,8 +9,10 @@
#include <vector>
#include "base/android/jni_android.h"
+#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
+#include "base/feature_list.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "content/browser/frame_host/frame_tree.h"
@@ -26,6 +28,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_features.h"
#include "jni/ImeAdapter_jni.h"
#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
@@ -45,7 +48,7 @@ namespace {
// as a key press of character \r.
NativeWebKeyboardEvent NativeWebKeyboardEventFromKeyEvent(
JNIEnv* env,
- jobject java_key_event,
+ const base::android::JavaRef<jobject>& java_key_event,
int action,
int modifiers,
long time_ms,
@@ -60,8 +63,9 @@ NativeWebKeyboardEvent NativeWebKeyboardEventFromKeyEvent(
type = blink::WebInputEvent::KeyUp;
else
NOTREACHED() << "Invalid Android key event action: " << action;
- return NativeWebKeyboardEvent(java_key_event, type, modifiers,
- time_ms / 1000.0, key_code, scan_code, unicode_char, is_system_key);
+ return NativeWebKeyboardEvent(env, java_key_event, type, modifiers,
+ time_ms / 1000.0, key_code, scan_code,
+ unicode_char, is_system_key);
}
} // anonymous namespace
@@ -203,7 +207,8 @@ void ImeAdapterAndroid::SetComposingText(JNIEnv* env,
if (new_cursor_pos > 0)
new_cursor_pos = text16.length() + new_cursor_pos - 1;
- rwhi->ImeSetComposition(text16, underlines, new_cursor_pos, new_cursor_pos);
+ rwhi->ImeSetComposition(text16, underlines, gfx::Range::InvalidRange(),
+ new_cursor_pos, new_cursor_pos);
}
void ImeAdapterAndroid::CommitText(JNIEnv* env,
@@ -263,6 +268,31 @@ void ImeAdapterAndroid::SetEditableSelectionOffsets(
start, end));
}
+void ImeAdapterAndroid::SetCharacterBounds(
+ const std::vector<gfx::RectF>& character_bounds) {
+ JNIEnv* env = AttachCurrentThread();
+ base::android::ScopedJavaLocalRef<jobject> obj = java_ime_adapter_.get(env);
+ if (obj.is_null())
+ return;
+
+ const size_t coordinates_array_size = character_bounds.size() * 4;
+ scoped_ptr<float[]> coordinates_array(new float[coordinates_array_size]);
+ for (size_t i = 0; i < character_bounds.size(); ++i) {
+ const gfx::RectF& rect = character_bounds[i];
+ const size_t coordinates_array_index = i * 4;
+ coordinates_array[coordinates_array_index + 0] = rect.x();
+ coordinates_array[coordinates_array_index + 1] = rect.y();
+ coordinates_array[coordinates_array_index + 2] = rect.right();
+ coordinates_array[coordinates_array_index + 3] = rect.bottom();
+ }
+ Java_ImeAdapter_setCharacterBounds(
+ env,
+ obj.obj(),
+ base::android::ToJavaFloatArray(env,
+ coordinates_array.get(),
+ coordinates_array_size).obj());
+}
+
void ImeAdapterAndroid::SetComposingRegion(JNIEnv*,
const JavaParamRef<jobject>&,
int start,
@@ -289,6 +319,22 @@ void ImeAdapterAndroid::DeleteSurroundingText(JNIEnv*,
rfh->ExtendSelectionAndDelete(before, after);
}
+bool ImeAdapterAndroid::RequestTextInputStateUpdate(
+ JNIEnv* env,
+ const JavaParamRef<jobject>&) {
+ RenderWidgetHostImpl* rwhi = GetRenderWidgetHostImpl();
+ if (!rwhi)
+ return false;
+ rwhi->Send(new InputMsg_RequestTextInputStateUpdate(rwhi->GetRoutingID()));
+ return true;
+}
+
+bool ImeAdapterAndroid::IsImeThreadEnabled(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>&) {
+ return base::FeatureList::IsEnabled(features::kImeThread);
+}
+
void ImeAdapterAndroid::ResetImeAdapter(JNIEnv* env,
const JavaParamRef<jobject>&) {
java_ime_adapter_.reset();
diff --git a/chromium/content/browser/renderer_host/ime_adapter_android.h b/chromium/content/browser/renderer_host/ime_adapter_android.h
index 0830f27254d..1f559c6ca77 100644
--- a/chromium/content/browser/renderer_host/ime_adapter_android.h
+++ b/chromium/content/browser/renderer_host/ime_adapter_android.h
@@ -7,7 +7,10 @@
#include <jni.h>
+#include <vector>
+
#include "base/android/jni_weak_ref.h"
+#include "ui/gfx/geometry/rect_f.h"
namespace content {
@@ -75,10 +78,14 @@ class ImeAdapterAndroid {
int before,
int after);
void ResetImeAdapter(JNIEnv*, const base::android::JavaParamRef<jobject>&);
+ bool RequestTextInputStateUpdate(JNIEnv*,
+ const base::android::JavaParamRef<jobject>&);
+ bool IsImeThreadEnabled(JNIEnv*, const base::android::JavaParamRef<jobject>&);
// Called from native -> java
void CancelComposition();
void FocusedNodeChanged(bool is_editable_node);
+ void SetCharacterBounds(const std::vector<gfx::RectF>& rects);
private:
RenderWidgetHostImpl* GetRenderWidgetHostImpl();
diff --git a/chromium/content/browser/renderer_host/input/composited_scrolling_browsertest.cc b/chromium/content/browser/renderer_host/input/composited_scrolling_browsertest.cc
index cbf48e8ae7a..fdca6bcfe9e 100644
--- a/chromium/content/browser/renderer_host/input/composited_scrolling_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/composited_scrolling_browsertest.cc
@@ -84,7 +84,7 @@ class CompositedScrollingBrowserTest : public ContentBrowserTest {
RenderWidgetHostImpl* host = GetWidgetHost();
scoped_refptr<FrameWatcher> frame_watcher(new FrameWatcher());
- host->GetProcess()->AddFilter(frame_watcher.get());
+ frame_watcher->AttachTo(shell()->web_contents());
host->GetView()->SetSize(gfx::Size(400, 400));
base::string16 ready_title(base::ASCIIToUTF16("ready"));
diff --git a/chromium/content/browser/renderer_host/input/gesture_event_queue.cc b/chromium/content/browser/renderer_host/input/gesture_event_queue.cc
index 15cda746b21..aa8856951d5 100644
--- a/chromium/content/browser/renderer_host/input/gesture_event_queue.cc
+++ b/chromium/content/browser/renderer_host/input/gesture_event_queue.cc
@@ -186,6 +186,9 @@ void GestureEventQueue::QueueAndForwardIfNecessary(
case WebInputEvent::GestureScrollUpdate:
QueueScrollOrPinchAndForwardIfNecessary(gesture_event);
return;
+ case WebInputEvent::GestureScrollBegin:
+ if (OnScrollBegin(gesture_event))
+ return;
default:
break;
}
@@ -195,6 +198,25 @@ void GestureEventQueue::QueueAndForwardIfNecessary(
client_->SendGestureEventImmediately(gesture_event);
}
+bool GestureEventQueue::OnScrollBegin(
+ const GestureEventWithLatencyInfo& gesture_event) {
+ // If a synthetic scroll begin is encountered, it can cancel out a previous
+ // synthetic scroll end. This allows a later gesture scroll update to coalesce
+ // with the previous one. crbug.com/607340.
+ bool synthetic = gesture_event.event.data.scrollBegin.synthetic;
+ bool have_unsent_events =
+ EventsInFlightCount() < coalesced_gesture_events_.size();
+ if (synthetic && have_unsent_events) {
+ GestureEventWithLatencyInfo* last_event = &coalesced_gesture_events_.back();
+ if (last_event->event.type == WebInputEvent::GestureScrollEnd &&
+ last_event->event.data.scrollEnd.synthetic) {
+ coalesced_gesture_events_.pop_back();
+ return true;
+ }
+ }
+ return false;
+}
+
void GestureEventQueue::ProcessGestureAck(InputEventAckState ack_result,
WebInputEvent::Type type,
const ui::LatencyInfo& latency) {
diff --git a/chromium/content/browser/renderer_host/input/gesture_event_queue.h b/chromium/content/browser/renderer_host/input/gesture_event_queue.h
index 457a9ecb4cf..4df38e8e371 100644
--- a/chromium/content/browser/renderer_host/input/gesture_event_queue.h
+++ b/chromium/content/browser/renderer_host/input/gesture_event_queue.h
@@ -117,6 +117,8 @@ class CONTENT_EXPORT GestureEventQueue {
friend class GestureEventQueueTest;
friend class MockRenderWidgetHost;
+ bool OnScrollBegin(const GestureEventWithLatencyInfo& gesture_event);
+
// TODO(mohsen): There are a bunch of ShouldForward.../ShouldDiscard...
// methods that are getting confusing. This should be somehow fixed. Maybe
// while refactoring GEQ: http://crbug.com/148443.
diff --git a/chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc b/chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc
index 44087274c4b..6b3234a7af5 100644
--- a/chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/gesture_event_queue_unittest.cc
@@ -1154,4 +1154,29 @@ TEST_F(GestureEventQueueTest, DebounceDropsDeferredEvents) {
}
}
+TEST_F(GestureEventQueueTest, CoalescesSyntheticScrollBeginEndEvents) {
+ // Test coalescing of only GestureScrollBegin/End events.
+ SimulateGestureEvent(WebInputEvent::GestureScrollUpdate,
+ blink::WebGestureDeviceTouchpad);
+ EXPECT_EQ(1U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(1U, GestureEventQueueSize());
+
+ WebGestureEvent synthetic_end = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::GestureScrollEnd, blink::WebGestureDeviceTouchpad);
+ synthetic_end.data.scrollEnd.synthetic = true;
+
+ SimulateGestureEvent(synthetic_end);
+ EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(2U, GestureEventQueueSize());
+
+ // Synthetic begin will remove the unsent synthetic end.
+ WebGestureEvent synthetic_begin = SyntheticWebGestureEventBuilder::Build(
+ WebInputEvent::GestureScrollBegin, blink::WebGestureDeviceTouchpad);
+ synthetic_begin.data.scrollBegin.synthetic = true;
+
+ SimulateGestureEvent(synthetic_begin);
+ EXPECT_EQ(0U, GetAndResetSentGestureEventCount());
+ EXPECT_EQ(1U, GestureEventQueueSize());
+}
+
} // 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 5d64568962c..3b466cbb784 100644
--- a/chromium/content/browser/renderer_host/input/input_router.h
+++ b/chromium/content/browser/renderer_host/input/input_router.h
@@ -58,6 +58,10 @@ class InputRouter : public IPC::Listener {
// A scale factor to scale the coordinate in WebInputEvent from DIP
// to viewport.
virtual void SetDeviceScaleFactor(float device_scale_factor) = 0;
+
+ // Sets the frame tree node id of associated frame, used when tracing
+ // input event latencies to relate events to their target frames.
+ virtual void SetFrameTreeNodeId(int frameTreeNodeId) = 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 34fdf0eb9b7..fffed702d63 100644
--- a/chromium/content/browser/renderer_host/input/input_router_client.h
+++ b/chromium/content/browser/renderer_host/input/input_router_client.h
@@ -53,6 +53,13 @@ class CONTENT_EXPORT InputRouterClient {
// Called when a renderer fling has terminated.
virtual void DidStopFlinging() = 0;
+
+ // Called when the input router generates an event. It is intended that the
+ // client will do some processing on |gesture_event| and then send it back
+ // to the InputRouter via SendGestureEvent.
+ virtual void ForwardGestureEventWithLatencyInfo(
+ const blink::WebGestureEvent& gesture_event,
+ const ui::LatencyInfo& latency_info) = 0;
};
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/input_router_impl.cc b/chromium/content/browser/renderer_host/input/input_router_impl.cc
index dcae7142ff7..fcac73f6dde 100644
--- a/chromium/content/browser/renderer_host/input/input_router_impl.cc
+++ b/chromium/content/browser/renderer_host/input/input_router_impl.cc
@@ -16,10 +16,10 @@
#include "content/browser/renderer_host/input/input_router_client.h"
#include "content/browser/renderer_host/input/touch_event_queue.h"
#include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h"
-#include "content/browser/renderer_host/input/web_input_event_util.h"
#include "content/common/content_constants_internal.h"
#include "content/common/edit_command.h"
#include "content/common/input/input_event_ack_state.h"
+#include "content/common/input/input_event_utils.h"
#include "content/common/input/touch_action.h"
#include "content/common/input/web_touch_event_traits.h"
#include "content/common/input_messages.h"
@@ -29,6 +29,7 @@
#include "content/public/browser/user_metrics.h"
#include "content/public/common/content_switches.h"
#include "ipc/ipc_sender.h"
+#include "ui/events/blink/blink_event_util.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
@@ -52,6 +53,8 @@ const char* GetEventAckName(InputEventAckState ack_result) {
case INPUT_EVENT_ACK_STATE_NOT_CONSUMED: return "NOT_CONSUMED";
case INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS: return "NO_CONSUMER_EXISTS";
case INPUT_EVENT_ACK_STATE_IGNORED: return "IGNORED";
+ case INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING:
+ return "SET_NON_BLOCKING";
}
DLOG(WARNING) << "Unhandled InputEventAckState in GetEventAckName.";
return "";
@@ -71,13 +74,16 @@ InputRouterImpl::InputRouterImpl(IPC::Sender* sender,
client_(client),
ack_handler_(ack_handler),
routing_id_(routing_id),
+ frame_tree_node_id_(-1),
select_message_pending_(false),
move_caret_pending_(false),
mouse_move_pending_(false),
- mouse_wheel_pending_(false),
current_ack_source_(ACK_SOURCE_NONE),
flush_requested_(false),
active_renderer_fling_count_(0),
+ wheel_event_queue_(this,
+ UseGestureBasedWheelScrolling(),
+ kDefaultWheelScrollTransactionMs),
touch_event_queue_(this, config.touch_config),
gesture_event_queue_(this, this, config.gesture_config),
device_scale_factor_(1.f) {
@@ -124,38 +130,7 @@ void InputRouterImpl::SendMouseEvent(
void InputRouterImpl::SendWheelEvent(
const MouseWheelEventWithLatencyInfo& wheel_event) {
- if (mouse_wheel_pending_) {
- // If there's already a mouse wheel event waiting to be sent to the
- // renderer, add the new deltas to that event. Not doing so (e.g., by
- // dropping the old event, as for mouse moves) results in very slow
- // scrolling on the Mac.
- if (wheel_event.event.hasPreciseScrollingDeltas)
- DCHECK(wheel_event.event.canScroll);
- DCHECK(!(wheel_event.event.hasPreciseScrollingDeltas &&
- !wheel_event.event.canScroll));
- if (coalesced_mouse_wheel_events_.empty() ||
- (!coalesced_mouse_wheel_events_.empty() &&
- !coalesced_mouse_wheel_events_.back().CanCoalesceWith(wheel_event))) {
- coalesced_mouse_wheel_events_.push_back(wheel_event);
- } else {
- coalesced_mouse_wheel_events_.back().CoalesceWith(wheel_event);
- TRACE_EVENT_INSTANT2("input", "InputRouterImpl::CoalescedWheelEvent",
- TRACE_EVENT_SCOPE_THREAD,
- "total_dx",
- coalesced_mouse_wheel_events_.back().event.deltaX,
- "total_dy",
- coalesced_mouse_wheel_events_.back().event.deltaY);
- }
- return;
- }
-
- mouse_wheel_pending_ = true;
- current_wheel_event_ = wheel_event;
-
- LOCAL_HISTOGRAM_COUNTS_100("Renderer.WheelQueueSize",
- coalesced_mouse_wheel_events_.size());
-
- FilterAndSendWebInputEvent(wheel_event.event, wheel_event.latency);
+ wheel_event_queue_.QueueEvent(wheel_event);
}
void InputRouterImpl::SendKeyboardEvent(
@@ -181,6 +156,8 @@ void InputRouterImpl::SendGestureEvent(
if (touch_action_filter_.FilterGestureEvent(&gesture_event.event))
return;
+ wheel_event_queue_.OnGestureScrollEvent(gesture_event);
+
if (gesture_event.event.sourceDevice == blink::WebGestureDeviceTouchscreen)
touch_event_queue_.OnGestureScrollEvent(gesture_event);
@@ -251,14 +228,10 @@ void InputRouterImpl::RequestNotificationWhenFlushed() {
}
bool InputRouterImpl::HasPendingEvents() const {
- return !touch_event_queue_.empty() ||
- !gesture_event_queue_.empty() ||
- !key_queue_.empty() ||
- mouse_move_pending_ ||
- mouse_wheel_pending_ ||
- select_message_pending_ ||
- move_caret_pending_ ||
- active_renderer_fling_count_ > 0;
+ return !touch_event_queue_.empty() || !gesture_event_queue_.empty() ||
+ !key_queue_.empty() || mouse_move_pending_ ||
+ wheel_event_queue_.has_pending() || select_message_pending_ ||
+ move_caret_pending_ || active_renderer_fling_count_ > 0;
}
void InputRouterImpl::SetDeviceScaleFactor(float device_scale_factor) {
@@ -297,6 +270,18 @@ void InputRouterImpl::OnTouchEventAck(const TouchEventWithLatencyInfo& event,
ack_handler_->OnTouchEventAck(event, ack_result);
}
+void InputRouterImpl::OnFilteringTouchEvent(
+ const WebTouchEvent& touch_event) {
+ // The event stream given to the renderer is not guaranteed to be
+ // valid based on the current TouchEventStreamValidator rules. This event will
+ // never be given to the renderer, but in order to ensure that the event
+ // stream |output_stream_validator_| sees is valid, we give events which are
+ // filtered out to the validator. crbug.com/589111 proposes adding an
+ // additional validator for the events which are actually sent to the
+ // renderer.
+ output_stream_validator_.Validate(touch_event);
+}
+
void InputRouterImpl::OnGestureEventAck(
const GestureEventWithLatencyInfo& event,
InputEventAckState ack_result) {
@@ -304,6 +289,23 @@ void InputRouterImpl::OnGestureEventAck(
ack_handler_->OnGestureEventAck(event, ack_result);
}
+void InputRouterImpl::ForwardGestureEventWithLatencyInfo(
+ const blink::WebGestureEvent& event,
+ const ui::LatencyInfo& latency_info) {
+ client_->ForwardGestureEventWithLatencyInfo(event, latency_info);
+}
+
+void InputRouterImpl::SendMouseWheelEventImmediately(
+ const MouseWheelEventWithLatencyInfo& wheel_event) {
+ FilterAndSendWebInputEvent(wheel_event.event, wheel_event.latency);
+}
+
+void InputRouterImpl::OnMouseWheelEventAck(
+ const MouseWheelEventWithLatencyInfo& event,
+ InputEventAckState ack_result) {
+ ack_handler_->OnWheelEventAck(event, ack_result);
+}
+
bool InputRouterImpl::SendSelectMessage(
scoped_ptr<IPC::Message> message) {
DCHECK(message->type() == InputMsg_SelectRange::ID ||
@@ -348,11 +350,12 @@ void InputRouterImpl::FilterAndSendWebInputEvent(
"InputRouterImpl::FilterAndSendWebInputEvent",
"type",
WebInputEventTraits::GetName(input_event.type));
- TRACE_EVENT_WITH_FLOW1("input,benchmark",
+ TRACE_EVENT_WITH_FLOW2("input,benchmark,devtools.timeline",
"LatencyInfo.Flow",
TRACE_ID_DONT_MANGLE(latency_info.trace_id()),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
- "step", "SendInputEventUI");
+ "step", "SendInputEventUI",
+ "frameTreeNodeId", frame_tree_node_id_);
// Any input event cancels a pending mouse move event.
next_mouse_move_.reset();
@@ -367,21 +370,14 @@ void InputRouterImpl::OfferToHandlers(const WebInputEvent& input_event,
if (OfferToClient(input_event, latency_info))
return;
- OfferToRenderer(input_event, latency_info);
-
- // Touch events should always indicate in the event whether they are
- // cancelable (respect ACK disposition) or not except touchmove.
- bool needs_synthetic_ack =
- !WebInputEventTraits::WillReceiveAckFromRenderer(input_event);
+ bool should_block = WebInputEventTraits::ShouldBlockEventStream(input_event);
+ OfferToRenderer(input_event, latency_info,
+ should_block
+ ? InputEventDispatchType::DISPATCH_TYPE_BLOCKING
+ : InputEventDispatchType::DISPATCH_TYPE_NON_BLOCKING);
- if (WebInputEvent::isTouchEventType(input_event.type) &&
- input_event.type != WebInputEvent::TouchMove) {
- const WebTouchEvent& touch = static_cast<const WebTouchEvent&>(input_event);
- DCHECK_EQ(needs_synthetic_ack, !touch.cancelable);
- }
-
- // The synthetic acks are sent immediately.
- if (needs_synthetic_ack) {
+ // Generate a synthetic ack if the event was sent so it doesn't block.
+ if (!should_block) {
ProcessInputEventAck(
input_event.type, INPUT_EVENT_ACK_STATE_IGNORED, latency_info,
WebInputEventTraits::GetUniqueTouchEventId(input_event),
@@ -418,18 +414,22 @@ bool InputRouterImpl::OfferToClient(const WebInputEvent& input_event,
}
bool InputRouterImpl::OfferToRenderer(const WebInputEvent& input_event,
- const ui::LatencyInfo& latency_info) {
+ const ui::LatencyInfo& latency_info,
+ InputEventDispatchType dispatch_type) {
+ // This conversion is temporary. WebInputEvent should be generated
+ // directly from ui::Event with the viewport coordinates. See
+ // crbug.com/563730.
scoped_ptr<blink::WebInputEvent> event_in_viewport =
- ConvertWebInputEventToViewport(input_event, device_scale_factor_);
+ ui::ScaleWebInputEvent(input_event, device_scale_factor_);
const WebInputEvent* event_to_send =
event_in_viewport ? event_in_viewport.get() : &input_event;
if (Send(new InputMsg_HandleInputEvent(routing_id(), event_to_send,
- latency_info))) {
+ latency_info, dispatch_type))) {
// Ack messages for ignored ack event types should never be sent by the
// renderer. Consequently, such event types should not affect event time
// or in-flight event count metrics.
- if (WebInputEventTraits::WillReceiveAckFromRenderer(*event_to_send)) {
+ if (dispatch_type == InputEventDispatchType::DISPATCH_TYPE_BLOCKING) {
input_event_start_time_ = TimeTicks::Now();
client_->IncrementInFlightEventCount();
}
@@ -594,27 +594,7 @@ void InputRouterImpl::ProcessMouseAck(blink::WebInputEvent::Type type,
void InputRouterImpl::ProcessWheelAck(InputEventAckState ack_result,
const ui::LatencyInfo& latency) {
- // TODO(miletus): Add renderer side latency to each uncoalesced mouse
- // wheel event and add terminal component to each of them.
- current_wheel_event_.latency.AddNewLatencyFrom(latency);
-
- // Process the unhandled wheel event here before calling SendWheelEvent()
- // since it will mutate current_wheel_event_.
- ack_handler_->OnWheelEventAck(current_wheel_event_, ack_result);
-
- // Mark the wheel event complete only after the ACKs have been handled above.
- // For example, ACKing the GesturePinchUpdate could cause another
- // GesturePinchUpdate to be sent, which should queue a wheel event rather than
- // send it immediately.
- mouse_wheel_pending_ = false;
-
- // Send the next (coalesced or synthetic) mouse wheel event.
- if (!coalesced_mouse_wheel_events_.empty()) {
- MouseWheelEventWithLatencyInfo next_wheel_event =
- coalesced_mouse_wheel_events_.front();
- coalesced_mouse_wheel_events_.pop_front();
- SendWheelEvent(next_wheel_event);
- }
+ wheel_event_queue_.ProcessMouseWheelAck(ack_result, latency);
}
void InputRouterImpl::ProcessGestureAck(WebInputEvent::Type type,
@@ -657,4 +637,8 @@ void InputRouterImpl::SignalFlushedIfNecessary() {
client_->DidFlush();
}
+void InputRouterImpl::SetFrameTreeNodeId(int frameTreeNodeId) {
+ frame_tree_node_id_ = frameTreeNodeId;
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/input_router_impl.h b/chromium/content/browser/renderer_host/input/input_router_impl.h
index 36f62b29256..dfa002f1cf6 100644
--- a/chromium/content/browser/renderer_host/input/input_router_impl.h
+++ b/chromium/content/browser/renderer_host/input/input_router_impl.h
@@ -14,9 +14,11 @@
#include "base/time/time.h"
#include "content/browser/renderer_host/input/gesture_event_queue.h"
#include "content/browser/renderer_host/input/input_router.h"
+#include "content/browser/renderer_host/input/mouse_wheel_event_queue.h"
#include "content/browser/renderer_host/input/touch_action_filter.h"
#include "content/browser/renderer_host/input/touch_event_queue.h"
#include "content/browser/renderer_host/input/touchpad_tap_suppression_controller.h"
+#include "content/common/input/input_event_dispatch_type.h"
#include "content/common/input/input_event_stream_validator.h"
#include "content/public/browser/native_web_keyboard_event.h"
@@ -40,6 +42,7 @@ struct InputEventAck;
class CONTENT_EXPORT InputRouterImpl
: public NON_EXPORTED_BASE(InputRouter),
public NON_EXPORTED_BASE(GestureEventQueueClient),
+ public NON_EXPORTED_BASE(MouseWheelEventQueueClient),
public NON_EXPORTED_BASE(TouchEventQueueClient),
public NON_EXPORTED_BASE(TouchpadTapSuppressionControllerClient) {
public:
@@ -75,7 +78,9 @@ class CONTENT_EXPORT InputRouterImpl
// IPC::Listener
bool OnMessageReceived(const IPC::Message& message) override;
-private:
+ void SetFrameTreeNodeId(int frameTreeNodeId) override;
+
+ private:
friend class InputRouterImplTest;
// TouchpadTapSuppressionControllerClient
@@ -87,13 +92,24 @@ private:
const TouchEventWithLatencyInfo& touch_event) override;
void OnTouchEventAck(const TouchEventWithLatencyInfo& event,
InputEventAckState ack_result) override;
+ void OnFilteringTouchEvent(
+ const blink::WebTouchEvent& touch_event) override;
- // GetureEventFilterClient
+ // GestureEventFilterClient
void SendGestureEventImmediately(
const GestureEventWithLatencyInfo& gesture_event) override;
void OnGestureEventAck(const GestureEventWithLatencyInfo& event,
InputEventAckState ack_result) override;
+ // MouseWheelEventQueueClient
+ void SendMouseWheelEventImmediately(
+ const MouseWheelEventWithLatencyInfo& touch_event) override;
+ void OnMouseWheelEventAck(const MouseWheelEventWithLatencyInfo& event,
+ InputEventAckState ack_result) override;
+ void ForwardGestureEventWithLatencyInfo(
+ const blink::WebGestureEvent& gesture_event,
+ const ui::LatencyInfo& latency_info) override;
+
bool SendMoveCaret(scoped_ptr<IPC::Message> message);
bool SendSelectMessage(scoped_ptr<IPC::Message> message);
bool Send(IPC::Message* message);
@@ -115,7 +131,8 @@ private:
// Returns true if |input_event| was successfully sent to the renderer
// as an async IPC Message.
bool OfferToRenderer(const blink::WebInputEvent& input_event,
- const ui::LatencyInfo& latency_info);
+ const ui::LatencyInfo& latency_info,
+ InputEventDispatchType dispatch_type);
// IPC message handlers
void OnInputEventAck(const InputEventAck& ack);
@@ -182,11 +199,11 @@ private:
int routing_id() const { return routing_id_; }
-
IPC::Sender* sender_;
InputRouterClient* client_;
InputAckHandler* ack_handler_;
int routing_id_;
+ int frame_tree_node_id_;
// (Similar to |mouse_move_pending_|.) True while waiting for SelectRange_ACK
// or MoveRangeSelectionExtent_ACK.
@@ -211,21 +228,6 @@ private:
scoped_ptr<MouseEventWithLatencyInfo> next_mouse_move_;
MouseEventWithLatencyInfo current_mouse_move_;
- // (Similar to |mouse_move_pending_|.) True if a mouse wheel event was sent
- // and we are waiting for a corresponding ack.
- bool mouse_wheel_pending_;
- MouseWheelEventWithLatencyInfo current_wheel_event_;
-
- // (Similar to |next_mouse_move_|.) The next mouse wheel events to send.
- // Unlike mouse moves, mouse wheel events received while one is pending are
- // coalesced (by accumulating deltas) if they match the previous event in
- // modifiers. On the Mac, in particular, mouse wheel events are received at a
- // high rate; not waiting for the ack results in jankiness, and using the same
- // mechanism as for mouse moves (just dropping old events when multiple ones
- // would be queued) results in very slow scrolling.
- typedef std::deque<MouseWheelEventWithLatencyInfo> WheelEventQueue;
- WheelEventQueue coalesced_mouse_wheel_events_;
-
// A queue of keyboard events. We can't trust data from the renderer so we
// stuff key events into a queue and pop them out on ACK, feeding our copy
// back to whatever unhandled handler instead of the returned version.
@@ -248,6 +250,7 @@ private:
// to avoid races in bookkeeping when starting a new fling.
int active_renderer_fling_count_;
+ MouseWheelEventQueue wheel_event_queue_;
TouchEventQueue touch_event_queue_;
GestureEventQueue gesture_event_queue_;
TouchActionFilter touch_action_filter_;
diff --git a/chromium/content/browser/renderer_host/input/input_router_impl_perftest.cc b/chromium/content/browser/renderer_host/input/input_router_impl_perftest.cc
index edf67f109a6..90af47fa711 100644
--- a/chromium/content/browser/renderer_host/input/input_router_impl_perftest.cc
+++ b/chromium/content/browser/renderer_host/input/input_router_impl_perftest.cc
@@ -87,6 +87,9 @@ class NullInputRouterClient : public InputRouterClient {
void DidFlush() override {}
void DidOverscroll(const DidOverscrollParams& params) override {}
void DidStopFlinging() override {}
+ void ForwardGestureEventWithLatencyInfo(
+ const blink::WebGestureEvent& event,
+ const ui::LatencyInfo& latency_info) override {}
};
class NullIPCSender : public IPC::Sender {
@@ -239,7 +242,7 @@ class InputRouterImplPerfTest : public testing::Test {
void SendEventAckIfNecessary(const blink::WebInputEvent& event,
InputEventAckState ack_result) {
- if (!WebInputEventTraits::WillReceiveAckFromRenderer(event))
+ if (!WebInputEventTraits::ShouldBlockEventStream(event))
return;
InputEventAck ack(event.type, ack_result);
InputHostMsg_HandleInputEvent_ACK response(0, ack);
diff --git a/chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc b/chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc
index 26b69e97c51..861ecaeefa8 100644
--- a/chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/input_router_impl_unittest.cc
@@ -167,6 +167,18 @@ class InputRouterImplTest : public testing::Test {
browser_context_.reset();
}
+ void SetUpForGestureBasedWheelScrolling(bool enabled) {
+ CHECK(!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableWheelGestures) &&
+ !base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableWheelGestures));
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ enabled ? switches::kEnableWheelGestures
+ : switches::kDisableWheelGestures);
+ TearDown();
+ SetUp();
+ }
+
void SetUpForTouchAckTimeoutTest(int desktop_timeout_ms,
int mobile_timeout_ms) {
config_.touch_config.desktop_touch_ack_timeout_delay =
@@ -936,6 +948,8 @@ TEST_F(InputRouterImplTest, AckedTouchEventState) {
#endif // defined(USE_AURA)
TEST_F(InputRouterImplTest, UnhandledWheelEvent) {
+ SetUpForGestureBasedWheelScrolling(false);
+
// Simulate wheel events.
SimulateWheelEvent(0, 0, 0, -5, 0, false); // sent directly
SimulateWheelEvent(0, 0, 0, -10, 0, false); // enqueued
@@ -959,18 +973,59 @@ TEST_F(InputRouterImplTest, UnhandledWheelEvent) {
InputMsg_HandleInputEvent::ID));
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ // Indicate that the wheel event was unhandled.
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
// Check that the correct unhandled wheel event was received.
+ EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_handler_->ack_state());
+ EXPECT_EQ(ack_handler_->acked_wheel_event().deltaY, -10);
+}
+
+TEST_F(InputRouterImplTest, UnhandledWheelEventWithGestureScrolling) {
+ SetUpForGestureBasedWheelScrolling(true);
+
+ // Simulate wheel events.
+ SimulateWheelEvent(0, 0, 0, -5, 0, false); // sent directly
+ SimulateWheelEvent(0, 0, 0, -10, 0, false); // enqueued
+
+ // Check that only the first event was sent.
+ EXPECT_TRUE(
+ process_->sink().GetUniqueMessageMatching(InputMsg_HandleInputEvent::ID));
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+
+ // Indicate that the wheel event was unhandled.
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ // Check that the ack for the MouseWheel and ScrollBegin
+ // were processed.
+ EXPECT_EQ(2U, ack_handler_->GetAndResetAckCount());
+
+ // There should be a ScrollBegin and ScrollUpdate, MouseWheel sent
+ EXPECT_EQ(3U, GetSentMessageCountAndResetSink());
+
EXPECT_EQ(ack_handler_->acked_wheel_event().deltaY, -5);
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ // Check that the correct unhandled wheel event was received.
+ EXPECT_EQ(2U, ack_handler_->GetAndResetAckCount());
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, ack_handler_->ack_state());
+ EXPECT_EQ(ack_handler_->acked_wheel_event().deltaY, -10);
}
TEST_F(InputRouterImplTest, TouchTypesIgnoringAck) {
OnHasTouchEventHandlers(true);
// Only acks for TouchCancel should always be ignored.
- ASSERT_TRUE(WebInputEventTraits::WillReceiveAckFromRenderer(
+ ASSERT_TRUE(WebInputEventTraits::ShouldBlockEventStream(
GetEventWithType(WebInputEvent::TouchStart)));
- ASSERT_TRUE(WebInputEventTraits::WillReceiveAckFromRenderer(
+ ASSERT_TRUE(WebInputEventTraits::ShouldBlockEventStream(
GetEventWithType(WebInputEvent::TouchMove)));
- ASSERT_TRUE(WebInputEventTraits::WillReceiveAckFromRenderer(
+ ASSERT_TRUE(WebInputEventTraits::ShouldBlockEventStream(
GetEventWithType(WebInputEvent::TouchEnd)));
// Precede the TouchCancel with an appropriate TouchStart;
@@ -1029,8 +1084,7 @@ TEST_F(InputRouterImplTest, GestureTypesIgnoringAck) {
WebInputEvent::GestureScrollEnd};
for (size_t i = 0; i < arraysize(eventTypes); ++i) {
WebInputEvent::Type type = eventTypes[i];
- if (WebInputEventTraits::WillReceiveAckFromRenderer(
- GetEventWithType(type))) {
+ if (WebInputEventTraits::ShouldBlockEventStream(GetEventWithType(type))) {
SimulateGestureEvent(type, blink::WebGestureDeviceTouchscreen);
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
EXPECT_EQ(0U, ack_handler_->GetAndResetAckCount());
@@ -1060,7 +1114,7 @@ TEST_F(InputRouterImplTest, MouseTypesIgnoringAck) {
for (int i = start_type; i <= end_type; ++i) {
WebInputEvent::Type type = static_cast<WebInputEvent::Type>(i);
int expected_in_flight_event_count =
- !WebInputEventTraits::WillReceiveAckFromRenderer(GetEventWithType(type))
+ !WebInputEventTraits::ShouldBlockEventStream(GetEventWithType(type))
? 0
: 1;
@@ -1080,7 +1134,7 @@ TEST_F(InputRouterImplTest, MouseTypesIgnoringAck) {
}
// Guard against breaking changes to the list of ignored event ack types in
-// |WebInputEventTraits::WillReceiveAckFromRenderer|.
+// |WebInputEventTraits::ShouldBlockEventStream|.
TEST_F(InputRouterImplTest, RequiredEventAckTypes) {
const WebInputEvent::Type kRequiredEventAckTypes[] = {
WebInputEvent::MouseMove,
@@ -1098,7 +1152,7 @@ TEST_F(InputRouterImplTest, RequiredEventAckTypes) {
};
for (size_t i = 0; i < arraysize(kRequiredEventAckTypes); ++i) {
const WebInputEvent::Type required_ack_type = kRequiredEventAckTypes[i];
- ASSERT_TRUE(WebInputEventTraits::WillReceiveAckFromRenderer(
+ ASSERT_TRUE(WebInputEventTraits::ShouldBlockEventStream(
GetEventWithType(required_ack_type)));
}
}
@@ -1529,7 +1583,7 @@ TEST_F(InputRouterImplTest, DoubleTapGestureDependsOnFirstTap) {
blink::WebGestureDeviceTouchscreen);
EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
// This test will become invalid if GestureTap stops requiring an ack.
- ASSERT_TRUE(WebInputEventTraits::WillReceiveAckFromRenderer(
+ ASSERT_TRUE(WebInputEventTraits::ShouldBlockEventStream(
GetEventWithType(WebInputEvent::GestureTap)));
EXPECT_EQ(2, client_->in_flight_event_count());
SendInputEventACK(WebInputEvent::GestureTap,
@@ -1559,7 +1613,7 @@ TEST_F(InputRouterImplTest, DoubleTapGestureDependsOnFirstTap) {
SimulateGestureEvent(WebInputEvent::GestureDoubleTap,
blink::WebGestureDeviceTouchscreen);
// This test will become invalid if GestureDoubleTap stops requiring an ack.
- ASSERT_TRUE(WebInputEventTraits::WillReceiveAckFromRenderer(
+ ASSERT_TRUE(WebInputEventTraits::ShouldBlockEventStream(
GetEventWithType(WebInputEvent::GestureDoubleTap)));
EXPECT_EQ(1, client_->in_flight_event_count());
SendInputEventACK(WebInputEvent::GestureTap, INPUT_EVENT_ACK_STATE_CONSUMED);
@@ -1781,7 +1835,8 @@ TEST_F(InputRouterImplTest, TouchpadPinchAndScrollUpdate) {
EXPECT_EQ(1, client_->in_flight_event_count());
// Ack the wheel event.
- SendInputEventACK(WebInputEvent::MouseWheel, INPUT_EVENT_ACK_STATE_CONSUMED);
+ SendInputEventACK(WebInputEvent::GesturePinchUpdate,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
EXPECT_EQ(1U, ack_handler_->GetAndResetAckCount());
EXPECT_EQ(0, client_->in_flight_event_count());
@@ -1824,6 +1879,38 @@ TEST_F(InputRouterImplTest, OverscrollDispatch) {
client_overscroll.current_fling_velocity);
}
+// Tests that touch event stream validation passes when events are filtered
+// out. See crbug.com/581231 for details.
+TEST_F(InputRouterImplTest, TouchValidationPassesWithFilteredInputEvents) {
+ // Touch sequence with touch handler.
+ OnHasTouchEventHandlers(true);
+ PressTouchPoint(1, 1);
+ uint32_t touch_press_event_id = SendTouchEvent();
+ SendTouchEventACK(WebInputEvent::TouchStart,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
+ touch_press_event_id);
+
+ PressTouchPoint(1, 1);
+ touch_press_event_id = SendTouchEvent();
+ SendTouchEventACK(WebInputEvent::TouchStart,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
+ touch_press_event_id);
+
+ // This event will be filtered out, since no consumer exists.
+ ReleaseTouchPoint(1);
+ uint32_t touch_release_event_id = SendTouchEvent();
+ SendTouchEventACK(WebInputEvent::TouchEnd, INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
+ touch_release_event_id);
+
+ // If the validator didn't see the filtered out release event, it will crash
+ // now, upon seeing a press for a touch which it believes to be still pressed.
+ PressTouchPoint(1, 1);
+ touch_press_event_id = SendTouchEvent();
+ SendTouchEventACK(WebInputEvent::TouchStart,
+ INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
+ touch_press_event_id);
+}
+
namespace {
class InputRouterImplScaleEventTest : public InputRouterImplTest {
diff --git a/chromium/content/browser/renderer_host/input/mock_input_router_client.cc b/chromium/content/browser/renderer_host/input/mock_input_router_client.cc
index 07d3d17946e..3ff8a1dc909 100644
--- a/chromium/content/browser/renderer_host/input/mock_input_router_client.cc
+++ b/chromium/content/browser/renderer_host/input/mock_input_router_client.cc
@@ -61,6 +61,14 @@ void MockInputRouterClient::DidOverscroll(const DidOverscrollParams& params) {
void MockInputRouterClient::DidStopFlinging() {
}
+void MockInputRouterClient::ForwardGestureEventWithLatencyInfo(
+ const blink::WebGestureEvent& gesture_event,
+ const ui::LatencyInfo& latency_info) {
+ if (input_router_)
+ input_router_->SendGestureEvent(
+ GestureEventWithLatencyInfo(gesture_event, latency_info));
+}
+
bool MockInputRouterClient::GetAndResetFilterEventCalled() {
bool filter_input_event_called = filter_input_event_called_;
filter_input_event_called_ = false;
diff --git a/chromium/content/browser/renderer_host/input/mock_input_router_client.h b/chromium/content/browser/renderer_host/input/mock_input_router_client.h
index 3ae88350626..29bc4ce6bb8 100644
--- a/chromium/content/browser/renderer_host/input/mock_input_router_client.h
+++ b/chromium/content/browser/renderer_host/input/mock_input_router_client.h
@@ -31,6 +31,9 @@ class MockInputRouterClient : public InputRouterClient {
void DidFlush() override;
void DidOverscroll(const DidOverscrollParams& params) override;
void DidStopFlinging() override;
+ void ForwardGestureEventWithLatencyInfo(
+ const blink::WebGestureEvent& gesture_event,
+ const ui::LatencyInfo& latency_info) override;
bool GetAndResetFilterEventCalled();
size_t GetAndResetDidFlushCount();
diff --git a/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.cc b/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.cc
new file mode 100644
index 00000000000..b459b19aea1
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.cc
@@ -0,0 +1,288 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/mouse_wheel_event_queue.h"
+
+#include "base/metrics/histogram_macros.h"
+#include "base/stl_util.h"
+#include "base/trace_event/trace_event.h"
+
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
+using blink::WebMouseWheelEvent;
+using ui::LatencyInfo;
+
+namespace content {
+
+// This class represents a single queued mouse wheel event. Its main use
+// is that it is reported via trace events.
+class QueuedWebMouseWheelEvent : public MouseWheelEventWithLatencyInfo {
+ public:
+ QueuedWebMouseWheelEvent(const MouseWheelEventWithLatencyInfo& original_event)
+ : MouseWheelEventWithLatencyInfo(original_event) {
+ TRACE_EVENT_ASYNC_BEGIN0("input", "MouseWheelEventQueue::QueueEvent", this);
+ }
+
+ ~QueuedWebMouseWheelEvent() {
+ TRACE_EVENT_ASYNC_END0("input", "MouseWheelEventQueue::QueueEvent", this);
+ }
+
+ private:
+ bool original_can_scroll_;
+ DISALLOW_COPY_AND_ASSIGN(QueuedWebMouseWheelEvent);
+};
+
+MouseWheelEventQueue::MouseWheelEventQueue(MouseWheelEventQueueClient* client,
+ bool send_gestures,
+ int64_t scroll_transaction_ms)
+ : client_(client),
+ needs_scroll_begin_(true),
+ needs_scroll_end_(false),
+ send_gestures_(send_gestures),
+ scroll_transaction_ms_(scroll_transaction_ms),
+ scrolling_device_(blink::WebGestureDeviceUninitialized) {
+ DCHECK(client);
+}
+
+MouseWheelEventQueue::~MouseWheelEventQueue() {
+ if (!wheel_queue_.empty())
+ STLDeleteElements(&wheel_queue_);
+}
+
+void MouseWheelEventQueue::QueueEvent(
+ const MouseWheelEventWithLatencyInfo& event) {
+ TRACE_EVENT0("input", "MouseWheelEventQueue::QueueEvent");
+
+ if (event_sent_for_gesture_ack_ && !wheel_queue_.empty()) {
+ QueuedWebMouseWheelEvent* last_event = wheel_queue_.back();
+ if (last_event->CanCoalesceWith(event)) {
+ last_event->CoalesceWith(event);
+ TRACE_EVENT_INSTANT2("input", "MouseWheelEventQueue::CoalescedWheelEvent",
+ TRACE_EVENT_SCOPE_THREAD, "total_dx",
+ last_event->event.deltaX, "total_dy",
+ last_event->event.deltaY);
+ return;
+ }
+ }
+
+ wheel_queue_.push_back(new QueuedWebMouseWheelEvent(event));
+ TryForwardNextEventToRenderer();
+ LOCAL_HISTOGRAM_COUNTS_100("Renderer.WheelQueueSize", wheel_queue_.size());
+}
+
+void MouseWheelEventQueue::ProcessMouseWheelAck(
+ InputEventAckState ack_result,
+ const LatencyInfo& latency_info) {
+ TRACE_EVENT0("input", "MouseWheelEventQueue::ProcessMouseWheelAck");
+ if (!event_sent_for_gesture_ack_)
+ return;
+
+ event_sent_for_gesture_ack_->latency.AddNewLatencyFrom(latency_info);
+ client_->OnMouseWheelEventAck(*event_sent_for_gesture_ack_, ack_result);
+
+ // If event wasn't consumed then generate a gesture scroll for it.
+ if (send_gestures_ && ack_result != INPUT_EVENT_ACK_STATE_CONSUMED &&
+ event_sent_for_gesture_ack_->event.canScroll &&
+ event_sent_for_gesture_ack_->event.resendingPluginId == -1 &&
+ (scrolling_device_ == blink::WebGestureDeviceUninitialized ||
+ scrolling_device_ == blink::WebGestureDeviceTouchpad)) {
+ WebGestureEvent scroll_update;
+ scroll_update.timeStampSeconds =
+ event_sent_for_gesture_ack_->event.timeStampSeconds;
+
+ scroll_update.x = event_sent_for_gesture_ack_->event.x;
+ scroll_update.y = event_sent_for_gesture_ack_->event.y;
+ scroll_update.globalX = event_sent_for_gesture_ack_->event.globalX;
+ scroll_update.globalY = event_sent_for_gesture_ack_->event.globalY;
+ scroll_update.type = WebInputEvent::GestureScrollUpdate;
+ scroll_update.sourceDevice = blink::WebGestureDeviceTouchpad;
+ scroll_update.resendingPluginId = -1;
+ scroll_update.data.scrollUpdate.deltaX =
+ event_sent_for_gesture_ack_->event.deltaX;
+ scroll_update.data.scrollUpdate.deltaY =
+ event_sent_for_gesture_ack_->event.deltaY;
+ // Only OSX populates the momentumPhase; so expect this to
+ // always be PhaseNone on all other platforms.
+ scroll_update.data.scrollUpdate.inertial =
+ event_sent_for_gesture_ack_->event.momentumPhase !=
+ blink::WebMouseWheelEvent::PhaseNone;
+ if (event_sent_for_gesture_ack_->event.scrollByPage) {
+ scroll_update.data.scrollUpdate.deltaUnits = WebGestureEvent::Page;
+
+ // Turn page scrolls into a *single* page scroll because
+ // the magnitude the number of ticks is lost when coalescing.
+ if (scroll_update.data.scrollUpdate.deltaX)
+ scroll_update.data.scrollUpdate.deltaX =
+ scroll_update.data.scrollUpdate.deltaX > 0 ? 1 : -1;
+ if (scroll_update.data.scrollUpdate.deltaY)
+ scroll_update.data.scrollUpdate.deltaY =
+ scroll_update.data.scrollUpdate.deltaY > 0 ? 1 : -1;
+ } else {
+ scroll_update.data.scrollUpdate.deltaUnits =
+ event_sent_for_gesture_ack_->event.hasPreciseScrollingDeltas
+ ? WebGestureEvent::PrecisePixels
+ : WebGestureEvent::Pixels;
+
+ if (event_sent_for_gesture_ack_->event.railsMode ==
+ WebInputEvent::RailsModeVertical)
+ scroll_update.data.scrollUpdate.deltaX = 0;
+ if (event_sent_for_gesture_ack_->event.railsMode ==
+ WebInputEvent::RailsModeHorizontal)
+ scroll_update.data.scrollUpdate.deltaY = 0;
+ }
+
+ bool current_phase_ended = false;
+ bool has_phase_info = false;
+
+ if (event_sent_for_gesture_ack_->event.phase !=
+ blink::WebMouseWheelEvent::PhaseNone ||
+ event_sent_for_gesture_ack_->event.momentumPhase !=
+ blink::WebMouseWheelEvent::PhaseNone) {
+ has_phase_info = true;
+ current_phase_ended = event_sent_for_gesture_ack_->event.phase ==
+ blink::WebMouseWheelEvent::PhaseEnded ||
+ event_sent_for_gesture_ack_->event.phase ==
+ blink::WebMouseWheelEvent::PhaseCancelled ||
+ event_sent_for_gesture_ack_->event.momentumPhase ==
+ blink::WebMouseWheelEvent::PhaseEnded ||
+ event_sent_for_gesture_ack_->event.momentumPhase ==
+ blink::WebMouseWheelEvent::PhaseCancelled;
+ }
+
+ bool needs_update = scroll_update.data.scrollUpdate.deltaX != 0 ||
+ scroll_update.data.scrollUpdate.deltaY != 0;
+
+ // If there is no update to send and the current phase is ended yet a GSB
+ // needs to be sent, this event sequence doesn't need to be generated
+ // because the events generated will be a GSB (non-synthetic) and GSE
+ // (non-synthetic). This situation arises when OSX generates double
+ // phase end information.
+ bool empty_sequence =
+ !needs_update && needs_scroll_begin_ && current_phase_ended;
+
+ if (needs_update || !empty_sequence) {
+ if (needs_scroll_begin_) {
+ // If no GSB has been sent, it will be a non-synthetic GSB.
+ SendScrollBegin(scroll_update, false);
+ } else if (has_phase_info) {
+ // If a GSB has been sent, generate a synthetic GSB if we have phase
+ // information. This should be removed once crbug.com/526463 is fully
+ // implemented.
+ SendScrollBegin(scroll_update, true);
+ }
+
+ if (needs_update) {
+ ui::LatencyInfo latency = ui::LatencyInfo();
+ latency.AddLatencyNumber(
+ ui::INPUT_EVENT_LATENCY_GENERATE_SCROLL_UPDATE_FROM_MOUSE_WHEEL, 0,
+ 0);
+ client_->ForwardGestureEventWithLatencyInfo(scroll_update, latency);
+ }
+
+ if (current_phase_ended) {
+ // Non-synthetic GSEs are sent when the current phase is canceled or
+ // ended.
+ SendScrollEnd(scroll_update, false);
+ } else if (has_phase_info) {
+ // Generate a synthetic GSE for every update to force hit testing so
+ // that the non-latching behavior is preserved. Remove once
+ // crbug.com/526463 is fully implemented.
+ SendScrollEnd(scroll_update, true);
+ } else {
+ scroll_end_timer_.Start(
+ FROM_HERE,
+ base::TimeDelta::FromMilliseconds(scroll_transaction_ms_),
+ base::Bind(&MouseWheelEventQueue::SendScrollEnd,
+ base::Unretained(this), scroll_update, false));
+ }
+ }
+ }
+
+ event_sent_for_gesture_ack_.reset();
+ TryForwardNextEventToRenderer();
+}
+
+void MouseWheelEventQueue::OnGestureScrollEvent(
+ const GestureEventWithLatencyInfo& gesture_event) {
+ if (gesture_event.event.type == blink::WebInputEvent::GestureScrollBegin) {
+ // If there is a current scroll going on and a new scroll that isn't
+ // wheel based cancel current one by sending a ScrollEnd.
+ if (scroll_end_timer_.IsRunning() &&
+ gesture_event.event.sourceDevice != blink::WebGestureDeviceTouchpad) {
+ base::Closure task = scroll_end_timer_.user_task();
+ scroll_end_timer_.Reset();
+ task.Run();
+ }
+ scrolling_device_ = gesture_event.event.sourceDevice;
+ } else if (scrolling_device_ == gesture_event.event.sourceDevice &&
+ (gesture_event.event.type ==
+ blink::WebInputEvent::GestureScrollEnd ||
+ gesture_event.event.type ==
+ blink::WebInputEvent::GestureFlingStart)) {
+ scrolling_device_ = blink::WebGestureDeviceUninitialized;
+ if (scroll_end_timer_.IsRunning())
+ scroll_end_timer_.Reset();
+ }
+}
+
+void MouseWheelEventQueue::TryForwardNextEventToRenderer() {
+ TRACE_EVENT0("input", "MouseWheelEventQueue::TryForwardNextEventToRenderer");
+
+ if (wheel_queue_.empty() || event_sent_for_gesture_ack_)
+ return;
+
+ event_sent_for_gesture_ack_.reset(wheel_queue_.front());
+ wheel_queue_.pop_front();
+
+ client_->SendMouseWheelEventImmediately(*event_sent_for_gesture_ack_);
+}
+
+void MouseWheelEventQueue::SendScrollEnd(WebGestureEvent update_event,
+ bool synthetic) {
+ DCHECK((synthetic && !needs_scroll_end_) || needs_scroll_end_);
+
+ WebGestureEvent scroll_end(update_event);
+ scroll_end.timeStampSeconds =
+ (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
+ scroll_end.type = WebInputEvent::GestureScrollEnd;
+ scroll_end.resendingPluginId = -1;
+ scroll_end.data.scrollEnd.synthetic = synthetic;
+ scroll_end.data.scrollEnd.inertial = update_event.data.scrollUpdate.inertial;
+ scroll_end.data.scrollEnd.deltaUnits =
+ update_event.data.scrollUpdate.deltaUnits;
+
+ if (!synthetic) {
+ needs_scroll_begin_ = true;
+ needs_scroll_end_ = false;
+
+ if (scroll_end_timer_.IsRunning())
+ scroll_end_timer_.Reset();
+ }
+ client_->ForwardGestureEventWithLatencyInfo(scroll_end, ui::LatencyInfo());
+}
+
+void MouseWheelEventQueue::SendScrollBegin(
+ const WebGestureEvent& gesture_update,
+ bool synthetic) {
+ DCHECK((synthetic && !needs_scroll_begin_) || needs_scroll_begin_);
+
+ WebGestureEvent scroll_begin(gesture_update);
+ scroll_begin.type = WebInputEvent::GestureScrollBegin;
+ scroll_begin.data.scrollBegin.synthetic = synthetic;
+ scroll_begin.data.scrollBegin.inertial =
+ gesture_update.data.scrollUpdate.inertial;
+ scroll_begin.data.scrollBegin.deltaXHint =
+ gesture_update.data.scrollUpdate.deltaX;
+ scroll_begin.data.scrollBegin.deltaYHint =
+ gesture_update.data.scrollUpdate.deltaY;
+ scroll_begin.data.scrollBegin.targetViewport = false;
+ scroll_begin.data.scrollBegin.deltaHintUnits =
+ gesture_update.data.scrollUpdate.deltaUnits;
+
+ needs_scroll_begin_ = false;
+ needs_scroll_end_ = true;
+ client_->ForwardGestureEventWithLatencyInfo(scroll_begin, ui::LatencyInfo());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.h b/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.h
new file mode 100644
index 00000000000..5c5c51e9507
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue.h
@@ -0,0 +1,110 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_INPUT_MOUSE_WHEEL_EVENT_QUEUE_H_
+#define CONTENT_BROWSER_RENDERER_HOST_INPUT_MOUSE_WHEEL_EVENT_QUEUE_H_
+
+#include <deque>
+
+#include "base/time/time.h"
+#include "content/browser/renderer_host/event_with_latency_info.h"
+#include "content/common/content_export.h"
+#include "content/common/input/input_event_ack_state.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+
+namespace content {
+
+// The duration in which a ScrollEnd will be sent after the last
+// ScrollUpdate was sent for wheel based gesture scrolls.
+// Set the default wheel transaction to 0ms until
+// crbug.com/526463 is fully implemented.
+const int64_t kDefaultWheelScrollTransactionMs = 0; // 100;
+
+class QueuedWebMouseWheelEvent;
+
+// Interface with which MouseWheelEventQueue can forward mouse wheel events,
+// and dispatch mouse wheel event responses.
+class CONTENT_EXPORT MouseWheelEventQueueClient {
+ public:
+ virtual ~MouseWheelEventQueueClient() {}
+
+ virtual void SendMouseWheelEventImmediately(
+ const MouseWheelEventWithLatencyInfo& event) = 0;
+ virtual void ForwardGestureEventWithLatencyInfo(
+ const blink::WebGestureEvent& event,
+ const ui::LatencyInfo& latency_info) = 0;
+ virtual void OnMouseWheelEventAck(const MouseWheelEventWithLatencyInfo& event,
+ InputEventAckState ack_result) = 0;
+};
+
+// A queue for throttling and coalescing mouse wheel events.
+class CONTENT_EXPORT MouseWheelEventQueue {
+ public:
+ // The |client| must outlive the MouseWheelEventQueue. |send_gestures|
+ // indicates whether mouse wheel events should generate
+ // Scroll[Begin|Update|End] on unhandled acknowledge events.
+ // |scroll_transaction_ms| is the duration in which the
+ // ScrollEnd should be sent after a ScrollUpdate.
+ MouseWheelEventQueue(MouseWheelEventQueueClient* client,
+ bool send_gestures,
+ int64_t scroll_transaction_ms);
+
+ ~MouseWheelEventQueue();
+
+ // Adds an event to the queue. The event may be coalesced with previously
+ // queued events (e.g. consecutive mouse-wheel events can be coalesced into a
+ // single mouse-wheel event). The event may also be immediately forwarded to
+ // the renderer (e.g. when there are no other queued mouse-wheel event).
+ void QueueEvent(const MouseWheelEventWithLatencyInfo& event);
+
+ // Notifies the queue that a mouse wheel event has been processed by the
+ // renderer.
+ void ProcessMouseWheelAck(InputEventAckState ack_result,
+ const ui::LatencyInfo& latency_info);
+
+ // When GestureScrollBegin is received, and it is a different source
+ // than mouse wheels terminate the current GestureScroll if there is one.
+ // When Gesture{ScrollEnd,FlingStart} is received, resume generating
+ // gestures.
+ void OnGestureScrollEvent(const GestureEventWithLatencyInfo& gesture_event);
+
+ bool has_pending() const WARN_UNUSED_RESULT {
+ return !wheel_queue_.empty() || event_sent_for_gesture_ack_;
+ }
+
+ size_t queued_size() const { return wheel_queue_.size(); }
+ bool event_in_flight() const {
+ return event_sent_for_gesture_ack_ != nullptr;
+ }
+
+ private:
+ void TryForwardNextEventToRenderer();
+ void SendScrollEnd(blink::WebGestureEvent update_event, bool synthetic);
+ void SendScrollBegin(const blink::WebGestureEvent& gesture_update,
+ bool synthetic);
+
+ MouseWheelEventQueueClient* client_;
+ base::OneShotTimer scroll_end_timer_;
+
+ typedef std::deque<QueuedWebMouseWheelEvent*> WheelEventQueue;
+ WheelEventQueue wheel_queue_;
+ scoped_ptr<QueuedWebMouseWheelEvent> event_sent_for_gesture_ack_;
+
+ // True if a non-synthetic GSB needs to be sent before a GSU is sent.
+ bool needs_scroll_begin_;
+
+ // True if a non-synthetic GSE needs to be sent because a non-synthetic
+ // GSB has been sent in the past.
+ bool needs_scroll_end_;
+
+ bool send_gestures_;
+ int64_t scroll_transaction_ms_;
+ blink::WebGestureDevice scrolling_device_;
+
+ DISALLOW_COPY_AND_ASSIGN(MouseWheelEventQueue);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_MOUSE_WHEEL_EVENT_QUEUE_H_
diff --git a/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue_unittest.cc b/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue_unittest.cc
new file mode 100644
index 00000000000..c88761abb66
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/mouse_wheel_event_queue_unittest.cc
@@ -0,0 +1,547 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/mouse_wheel_event_queue.h"
+
+#include <stddef.h>
+#include <utility>
+
+#include "base/location.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/thread_task_runner_handle.h"
+#include "content/browser/renderer_host/input/timeout_monitor.h"
+#include "content/common/input/synthetic_web_input_event_builders.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+
+using blink::WebGestureEvent;
+using blink::WebInputEvent;
+using blink::WebMouseWheelEvent;
+
+namespace content {
+namespace {
+
+const float kWheelScrollX = 10;
+const float kWheelScrollY = 12;
+const float kWheelScrollGlobalX = 50;
+const float kWheelScrollGlobalY = 72;
+const int64_t kScrollEndTimeoutMs = 100;
+
+base::TimeDelta DefaultScrollEndTimeoutDelay() {
+ return base::TimeDelta::FromMilliseconds(kScrollEndTimeoutMs);
+}
+
+#define EXPECT_GESTURE_SCROLL_BEGIN_IMPL(event) \
+ EXPECT_EQ(WebInputEvent::GestureScrollBegin, event->type); \
+ EXPECT_EQ(kWheelScrollX, event->x); \
+ EXPECT_EQ(kWheelScrollY, event->y); \
+ EXPECT_EQ(kWheelScrollGlobalX, event->globalX); \
+ EXPECT_EQ(kWheelScrollGlobalY, event->globalY); \
+ EXPECT_EQ(scroll_units, event->data.scrollBegin.deltaHintUnits);
+
+#define EXPECT_GESTURE_SCROLL_BEGIN(event) \
+ EXPECT_GESTURE_SCROLL_BEGIN_IMPL(event); \
+ EXPECT_FALSE(event->data.scrollBegin.synthetic); \
+ EXPECT_FALSE(event->data.scrollBegin.inertial);
+
+#define EXPECT_SYNTHETIC_GESTURE_SCROLL_BEGIN(event) \
+ EXPECT_GESTURE_SCROLL_BEGIN_IMPL(event); \
+ EXPECT_TRUE(event->data.scrollBegin.synthetic); \
+ EXPECT_FALSE(event->data.scrollBegin.inertial);
+
+#define EXPECT_INERTIAL_GESTURE_SCROLL_BEGIN(event) \
+ EXPECT_GESTURE_SCROLL_BEGIN_IMPL(event); \
+ EXPECT_FALSE(event->data.scrollBegin.synthetic); \
+ EXPECT_TRUE(event->data.scrollBegin.inertial);
+
+#define EXPECT_SYNTHETIC_INERTIAL_GESTURE_SCROLL_BEGIN(event) \
+ EXPECT_GESTURE_SCROLL_BEGIN_IMPL(event); \
+ EXPECT_TRUE(event->data.scrollBegin.synthetic); \
+ EXPECT_TRUE(event->data.scrollBegin.inertial);
+
+#define EXPECT_GESTURE_SCROLL_UPDATE_IMPL(event) \
+ EXPECT_EQ(WebInputEvent::GestureScrollUpdate, event->type); \
+ EXPECT_EQ(scroll_units, event->data.scrollUpdate.deltaUnits); \
+ EXPECT_EQ(kWheelScrollX, event->x); \
+ EXPECT_EQ(kWheelScrollY, event->y); \
+ EXPECT_EQ(kWheelScrollGlobalX, event->globalX); \
+ EXPECT_EQ(kWheelScrollGlobalY, event->globalY);
+
+#define EXPECT_GESTURE_SCROLL_UPDATE(event) \
+ EXPECT_GESTURE_SCROLL_UPDATE_IMPL(event); \
+ EXPECT_FALSE(event->data.scrollUpdate.inertial);
+
+#define EXPECT_GESTURE_SCROLL_UPDATE(event) \
+ EXPECT_GESTURE_SCROLL_UPDATE_IMPL(event); \
+ EXPECT_FALSE(event->data.scrollUpdate.inertial);
+
+#define EXPECT_INERTIAL_GESTURE_SCROLL_UPDATE(event) \
+ EXPECT_GESTURE_SCROLL_UPDATE_IMPL(event); \
+ EXPECT_TRUE(event->data.scrollUpdate.inertial);
+
+#define EXPECT_GESTURE_SCROLL_END_IMPL(event) \
+ EXPECT_EQ(WebInputEvent::GestureScrollEnd, event->type); \
+ EXPECT_EQ(scroll_units, event->data.scrollEnd.deltaUnits); \
+ EXPECT_EQ(kWheelScrollX, event->x); \
+ EXPECT_EQ(kWheelScrollY, event->y); \
+ EXPECT_EQ(kWheelScrollGlobalX, event->globalX); \
+ EXPECT_EQ(kWheelScrollGlobalY, event->globalY);
+
+#define EXPECT_GESTURE_SCROLL_END(event) \
+ EXPECT_GESTURE_SCROLL_END_IMPL(event); \
+ EXPECT_FALSE(event->data.scrollEnd.synthetic); \
+ EXPECT_FALSE(event->data.scrollEnd.inertial);
+
+#define EXPECT_SYNTHETIC_GESTURE_SCROLL_END(event) \
+ EXPECT_GESTURE_SCROLL_END_IMPL(event); \
+ EXPECT_TRUE(event->data.scrollEnd.synthetic); \
+ EXPECT_FALSE(event->data.scrollEnd.inertial);
+
+#define EXPECT_INERTIAL_GESTURE_SCROLL_END(event) \
+ EXPECT_GESTURE_SCROLL_END_IMPL(event); \
+ EXPECT_FALSE(event->data.scrollEnd.synthetic); \
+ EXPECT_TRUE(event->data.scrollEnd.inertial);
+
+#define EXPECT_SYNTHETIC_INERTIAL_GESTURE_SCROLL_END(event) \
+ EXPECT_GESTURE_SCROLL_END_IMPL(event); \
+ EXPECT_TRUE(event->data.scrollEnd.synthetic); \
+ EXPECT_TRUE(event->data.scrollEnd.inertial);
+
+#define EXPECT_MOUSE_WHEEL(event) \
+ EXPECT_EQ(WebInputEvent::MouseWheel, event->type);
+
+} // namespace
+
+class MouseWheelEventQueueTest : public testing::Test,
+ public MouseWheelEventQueueClient {
+ public:
+ MouseWheelEventQueueTest()
+ : acked_event_count_(0),
+ last_acked_event_state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {
+ SetUpForGestureTesting(false);
+ }
+
+ ~MouseWheelEventQueueTest() override {}
+
+ // MouseWheelEventQueueClient
+ void SendMouseWheelEventImmediately(
+ const MouseWheelEventWithLatencyInfo& event) override {
+ WebMouseWheelEvent* cloned_event = new WebMouseWheelEvent();
+ scoped_ptr<WebInputEvent> cloned_event_holder(cloned_event);
+ *cloned_event = event.event;
+ sent_events_.push_back(std::move(cloned_event_holder));
+ }
+
+ void ForwardGestureEventWithLatencyInfo(
+ const blink::WebGestureEvent& event,
+ const ui::LatencyInfo& latency_info) override {
+ WebGestureEvent* cloned_event = new WebGestureEvent();
+ scoped_ptr<WebInputEvent> cloned_event_holder(cloned_event);
+ *cloned_event = event;
+ sent_events_.push_back(std::move(cloned_event_holder));
+ }
+
+ void OnMouseWheelEventAck(const MouseWheelEventWithLatencyInfo& event,
+ InputEventAckState ack_result) override {
+ ++acked_event_count_;
+ last_acked_event_ = event.event;
+ last_acked_event_state_ = ack_result;
+ }
+
+ protected:
+ void SetUpForGestureTesting(bool send_gestures) {
+ queue_.reset(
+ new MouseWheelEventQueue(this, send_gestures, kScrollEndTimeoutMs));
+ }
+
+ size_t queued_event_count() const { return queue_->queued_size(); }
+
+ bool event_in_flight() const { return queue_->event_in_flight(); }
+
+ std::vector<scoped_ptr<WebInputEvent>>& all_sent_events() {
+ return sent_events_;
+ }
+
+ const scoped_ptr<WebInputEvent>& sent_input_event(size_t index) {
+ return sent_events_[index];
+ }
+ const WebGestureEvent* sent_gesture_event(size_t index) {
+ return static_cast<WebGestureEvent*>(sent_events_[index].get());
+ }
+
+ const WebMouseWheelEvent& acked_event() const { return last_acked_event_; }
+
+ size_t GetAndResetSentEventCount() {
+ size_t count = sent_events_.size();
+ sent_events_.clear();
+ return count;
+ }
+
+ size_t GetAndResetAckedEventCount() {
+ size_t count = acked_event_count_;
+ acked_event_count_ = 0;
+ return count;
+ }
+
+ void SendMouseWheelEventAck(InputEventAckState ack_result) {
+ queue_->ProcessMouseWheelAck(ack_result, ui::LatencyInfo());
+ }
+
+ void SendMouseWheel(float x,
+ float y,
+ float global_x,
+ float global_y,
+ float dX,
+ float dY,
+ int modifiers,
+ bool high_precision,
+ WebInputEvent::RailsMode rails_mode) {
+ WebMouseWheelEvent event = SyntheticWebMouseWheelEventBuilder::Build(
+ x, y, global_x, global_y, dX, dY, modifiers, high_precision);
+ event.railsMode = rails_mode;
+ queue_->QueueEvent(MouseWheelEventWithLatencyInfo(event));
+ }
+
+ void SendMouseWheel(float x,
+ float y,
+ float global_x,
+ float global_y,
+ float dX,
+ float dY,
+ int modifiers,
+ bool high_precision) {
+ SendMouseWheel(x, y, global_x, global_y, dX, dY, modifiers, high_precision,
+ WebInputEvent::RailsModeFree);
+ }
+ void SendMouseWheelWithPhase(
+ float x,
+ float y,
+ float global_x,
+ float global_y,
+ float dX,
+ float dY,
+ int modifiers,
+ bool high_precision,
+ blink::WebMouseWheelEvent::Phase phase,
+ blink::WebMouseWheelEvent::Phase momentum_phase) {
+ WebMouseWheelEvent event = SyntheticWebMouseWheelEventBuilder::Build(
+ x, y, global_x, global_y, dX, dY, modifiers, high_precision);
+ event.phase = phase;
+ event.momentumPhase = momentum_phase;
+ queue_->QueueEvent(MouseWheelEventWithLatencyInfo(event));
+ }
+
+ void SendGestureEvent(WebInputEvent::Type type) {
+ WebGestureEvent event;
+ event.type = type;
+ event.sourceDevice = blink::WebGestureDeviceTouchscreen;
+ queue_->OnGestureScrollEvent(
+ GestureEventWithLatencyInfo(event, ui::LatencyInfo()));
+ }
+
+ static void RunTasksAndWait(base::TimeDelta delay) {
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, base::MessageLoop::QuitWhenIdleClosure(), delay);
+ base::MessageLoop::current()->Run();
+ }
+
+ void GestureSendingTest(bool high_precision) {
+ const WebGestureEvent::ScrollUnits scroll_units =
+ high_precision ? WebGestureEvent::PrecisePixels
+ : WebGestureEvent::Pixels;
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 1, 1, 0, high_precision);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_TRUE(event_in_flight());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ // The second mouse wheel should not be sent since one is already in
+ // queue.
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 5, 5, 0, high_precision);
+ EXPECT_EQ(1U, queued_event_count());
+ EXPECT_TRUE(event_in_flight());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+
+ // Receive an ACK for the mouse wheel event and release the next
+ // mouse wheel event.
+ SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_TRUE(event_in_flight());
+ EXPECT_EQ(WebInputEvent::MouseWheel, acked_event().type);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(3U, all_sent_events().size());
+ EXPECT_GESTURE_SCROLL_BEGIN(sent_gesture_event(0));
+ EXPECT_GESTURE_SCROLL_UPDATE(sent_gesture_event(1));
+ EXPECT_MOUSE_WHEEL(sent_input_event(2));
+ EXPECT_EQ(3U, GetAndResetSentEventCount());
+
+ RunTasksAndWait(DefaultScrollEndTimeoutDelay() * 2);
+ EXPECT_EQ(1U, all_sent_events().size());
+ EXPECT_GESTURE_SCROLL_END(sent_gesture_event(0));
+ }
+
+ void PhaseGestureSendingTest(bool high_precision) {
+ const WebGestureEvent::ScrollUnits scroll_units =
+ high_precision ? WebGestureEvent::PrecisePixels
+ : WebGestureEvent::Pixels;
+
+ SendMouseWheelWithPhase(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 1, 1, 0, high_precision,
+ WebMouseWheelEvent::PhaseBegan,
+ WebMouseWheelEvent::PhaseNone);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(3U, all_sent_events().size());
+ EXPECT_GESTURE_SCROLL_BEGIN(sent_gesture_event(0));
+ EXPECT_GESTURE_SCROLL_UPDATE(sent_gesture_event(1));
+ EXPECT_SYNTHETIC_GESTURE_SCROLL_END(sent_gesture_event(2));
+ EXPECT_EQ(3U, GetAndResetSentEventCount());
+
+ SendMouseWheelWithPhase(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 5, 5, 0, high_precision,
+ WebMouseWheelEvent::PhaseChanged,
+ WebMouseWheelEvent::PhaseNone);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(3U, all_sent_events().size());
+ EXPECT_SYNTHETIC_GESTURE_SCROLL_BEGIN(sent_gesture_event(0));
+ EXPECT_GESTURE_SCROLL_UPDATE(sent_gesture_event(1));
+ EXPECT_SYNTHETIC_GESTURE_SCROLL_END(sent_gesture_event(2));
+ EXPECT_EQ(3U, GetAndResetSentEventCount());
+
+ SendMouseWheelWithPhase(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 0, 0, 0, high_precision,
+ WebMouseWheelEvent::PhaseEnded,
+ WebMouseWheelEvent::PhaseNone);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(2U, all_sent_events().size());
+ EXPECT_SYNTHETIC_GESTURE_SCROLL_BEGIN(sent_gesture_event(0));
+ EXPECT_GESTURE_SCROLL_END(sent_gesture_event(1));
+ EXPECT_EQ(2U, GetAndResetSentEventCount());
+
+ // Send a double phase end; OSX does it consistently.
+ SendMouseWheelWithPhase(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 0, 0, 0, high_precision,
+ WebMouseWheelEvent::PhaseEnded,
+ WebMouseWheelEvent::PhaseNone);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, all_sent_events().size());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+
+ SendMouseWheelWithPhase(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 5, 5, 0, high_precision,
+ WebMouseWheelEvent::PhaseNone,
+ WebMouseWheelEvent::PhaseBegan);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(3U, all_sent_events().size());
+ EXPECT_INERTIAL_GESTURE_SCROLL_BEGIN(sent_gesture_event(0));
+ EXPECT_INERTIAL_GESTURE_SCROLL_UPDATE(sent_gesture_event(1));
+ EXPECT_SYNTHETIC_INERTIAL_GESTURE_SCROLL_END(sent_gesture_event(2));
+ EXPECT_EQ(3U, GetAndResetSentEventCount());
+
+ SendMouseWheelWithPhase(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 5, 5, 0, high_precision,
+ WebMouseWheelEvent::PhaseNone,
+ WebMouseWheelEvent::PhaseChanged);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(3U, all_sent_events().size());
+ EXPECT_SYNTHETIC_INERTIAL_GESTURE_SCROLL_BEGIN(sent_gesture_event(0));
+ EXPECT_INERTIAL_GESTURE_SCROLL_UPDATE(sent_gesture_event(1));
+ EXPECT_SYNTHETIC_INERTIAL_GESTURE_SCROLL_END(sent_gesture_event(2));
+ EXPECT_EQ(3U, GetAndResetSentEventCount());
+
+ SendMouseWheelWithPhase(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 0, 0, 0, high_precision,
+ WebMouseWheelEvent::PhaseNone,
+ WebMouseWheelEvent::PhaseEnded);
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(2U, all_sent_events().size());
+ EXPECT_SYNTHETIC_INERTIAL_GESTURE_SCROLL_BEGIN(sent_gesture_event(0));
+ EXPECT_INERTIAL_GESTURE_SCROLL_END(sent_gesture_event(1));
+ EXPECT_EQ(2U, GetAndResetSentEventCount());
+ }
+
+ scoped_ptr<MouseWheelEventQueue> queue_;
+ std::vector<scoped_ptr<WebInputEvent>> sent_events_;
+ size_t acked_event_count_;
+ InputEventAckState last_acked_event_state_;
+ base::MessageLoopForUI message_loop_;
+ WebMouseWheelEvent last_acked_event_;
+};
+
+// Tests that mouse wheel events are queued properly.
+TEST_F(MouseWheelEventQueueTest, Basic) {
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 1, 1, 0, false);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_TRUE(event_in_flight());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ // The second mouse wheel should not be sent since one is already in queue.
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 5, 5, 0, false);
+ EXPECT_EQ(1U, queued_event_count());
+ EXPECT_TRUE(event_in_flight());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+
+ // Receive an ACK for the first mouse wheel event.
+ SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_TRUE(event_in_flight());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(WebInputEvent::MouseWheel, acked_event().type);
+
+ // Receive an ACK for the second mouse wheel event.
+ SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_FALSE(event_in_flight());
+ EXPECT_EQ(0U, GetAndResetSentEventCount());
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(WebInputEvent::MouseWheel, acked_event().type);
+}
+
+TEST_F(MouseWheelEventQueueTest, GestureSending) {
+ SetUpForGestureTesting(true);
+ GestureSendingTest(false);
+}
+
+TEST_F(MouseWheelEventQueueTest, GestureSendingPrecisePixels) {
+ SetUpForGestureTesting(true);
+ GestureSendingTest(false);
+}
+
+TEST_F(MouseWheelEventQueueTest, GestureSendingWithPhaseInformation) {
+ SetUpForGestureTesting(true);
+ PhaseGestureSendingTest(false);
+}
+
+TEST_F(MouseWheelEventQueueTest,
+ GestureSendingWithPhaseInformationPrecisePixels) {
+ SetUpForGestureTesting(true);
+ PhaseGestureSendingTest(true);
+}
+
+TEST_F(MouseWheelEventQueueTest, GestureSendingInterrupted) {
+ SetUpForGestureTesting(true);
+ const WebGestureEvent::ScrollUnits scroll_units = WebGestureEvent::Pixels;
+
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 1, 1, 0, false);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_TRUE(event_in_flight());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ // Receive an ACK for the mouse wheel event.
+ SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_FALSE(event_in_flight());
+ EXPECT_EQ(WebInputEvent::MouseWheel, acked_event().type);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(2U, all_sent_events().size());
+ EXPECT_GESTURE_SCROLL_BEGIN(sent_gesture_event(0));
+ EXPECT_GESTURE_SCROLL_UPDATE(sent_gesture_event(1));
+ EXPECT_EQ(2U, GetAndResetSentEventCount());
+
+ // Ensure that a gesture scroll begin terminates the current scroll event.
+ SendGestureEvent(WebInputEvent::GestureScrollBegin);
+ EXPECT_EQ(1U, all_sent_events().size());
+ EXPECT_GESTURE_SCROLL_END(sent_gesture_event(0));
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 1, 1, 0, false);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_TRUE(event_in_flight());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ // New mouse wheel events won't cause gestures because a scroll
+ // is already in progress by another device.
+ SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_FALSE(event_in_flight());
+ EXPECT_EQ(WebInputEvent::MouseWheel, acked_event().type);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(0U, all_sent_events().size());
+
+ SendGestureEvent(WebInputEvent::GestureScrollEnd);
+ EXPECT_EQ(0U, all_sent_events().size());
+
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 1, 1, 0, false);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_TRUE(event_in_flight());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ // Receive an ACK for the mouse wheel event.
+ SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_FALSE(event_in_flight());
+ EXPECT_EQ(WebInputEvent::MouseWheel, acked_event().type);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(2U, all_sent_events().size());
+ EXPECT_GESTURE_SCROLL_BEGIN(sent_gesture_event(0));
+ EXPECT_GESTURE_SCROLL_UPDATE(sent_gesture_event(1));
+ EXPECT_EQ(2U, GetAndResetSentEventCount());
+}
+
+TEST_F(MouseWheelEventQueueTest, GestureRailScrolling) {
+ SetUpForGestureTesting(true);
+ const WebGestureEvent::ScrollUnits scroll_units = WebGestureEvent::Pixels;
+
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 1, 1, 0, false,
+ WebInputEvent::RailsModeHorizontal);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_TRUE(event_in_flight());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ // Receive an ACK for the mouse wheel event.
+ SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_FALSE(event_in_flight());
+ EXPECT_EQ(WebInputEvent::MouseWheel, acked_event().type);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(2U, all_sent_events().size());
+ EXPECT_GESTURE_SCROLL_BEGIN(sent_gesture_event(0));
+ EXPECT_GESTURE_SCROLL_UPDATE(sent_gesture_event(1));
+ EXPECT_EQ(1U, sent_gesture_event(1)->data.scrollUpdate.deltaX);
+ EXPECT_EQ(0U, sent_gesture_event(1)->data.scrollUpdate.deltaY);
+ EXPECT_EQ(2U, GetAndResetSentEventCount());
+
+ RunTasksAndWait(DefaultScrollEndTimeoutDelay() * 2);
+ EXPECT_EQ(1U, all_sent_events().size());
+ EXPECT_GESTURE_SCROLL_END(sent_gesture_event(0));
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ SendMouseWheel(kWheelScrollX, kWheelScrollY, kWheelScrollGlobalX,
+ kWheelScrollGlobalY, 1, 1, 0, false,
+ WebInputEvent::RailsModeVertical);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_TRUE(event_in_flight());
+ EXPECT_EQ(1U, GetAndResetSentEventCount());
+
+ // Receive an ACK for the mouse wheel event.
+ SendMouseWheelEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, queued_event_count());
+ EXPECT_FALSE(event_in_flight());
+ EXPECT_EQ(WebInputEvent::MouseWheel, acked_event().type);
+ EXPECT_EQ(1U, GetAndResetAckedEventCount());
+ EXPECT_EQ(2U, all_sent_events().size());
+ EXPECT_GESTURE_SCROLL_BEGIN(sent_gesture_event(0));
+ EXPECT_GESTURE_SCROLL_UPDATE(sent_gesture_event(1));
+ EXPECT_EQ(0U, sent_gesture_event(1)->data.scrollUpdate.deltaX);
+ EXPECT_EQ(1U, sent_gesture_event(1)->data.scrollUpdate.deltaY);
+ EXPECT_EQ(2U, GetAndResetSentEventCount());
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/non_blocking_event_browsertest.cc b/chromium/content/browser/renderer_host/input/non_blocking_event_browsertest.cc
new file mode 100644
index 00000000000..431d1986b75
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/non_blocking_event_browsertest.cc
@@ -0,0 +1,218 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <utility>
+
+#include "base/auto_reset.h"
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/macros.h"
+#include "base/run_loop.h"
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h"
+#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/common/input/synthetic_web_input_event_builders.h"
+#include "content/common/input_messages.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_utils.h"
+#include "content/shell/browser/shell.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "ui/events/event_switches.h"
+#include "ui/events/latency_info.h"
+
+using blink::WebInputEvent;
+
+namespace {
+
+// This value has to be larger than the height of the device this test is
+// executed on, otherwise the device will be unable to scroll thus failing
+// tests.
+const int kWebsiteHeight = 10000;
+
+const char kNonBlockingEventDataURL[] =
+ "data:text/html;charset=utf-8,"
+ "<!DOCTYPE html>"
+ "<meta name='viewport' content='width=device-width'/>"
+ "<style>"
+ "html, body {"
+ " margin: 0;"
+ "}"
+ ".spacer { height: 10000px; }"
+ "</style>"
+ "<div class=spacer></div>"
+ "<script>"
+ " document.addEventListener('wheel', function(e) { while(true) {} }, "
+ "{'passive': true});"
+ " document.addEventListener('touchstart', function(e) { while(true) {} }, "
+ "{'passive': true});"
+ " document.title='ready';"
+ "</script>";
+
+const char kPassiveTouchStartBlockingTouchEndDataURL[] =
+ "data:text/html;charset=utf-8,"
+ "<!DOCTYPE html>"
+ "<meta name='viewport' content='width=device-width'/>"
+ "<style>"
+ "html, body {"
+ " margin: 0;"
+ "}"
+ ".spacer { height: 10000px; }"
+ "</style>"
+ "<div class=spacer></div>"
+ "<script>"
+ " document.addEventListener('touchstart', function(e) { while(true) {} }, "
+ "{'passive': true});"
+ " document.addEventListener('touchend', function(e) { while(true) {} });"
+ " document.title='ready';"
+ "</script>";
+
+} // namespace
+
+namespace content {
+
+class NonBlockingEventBrowserTest : public ContentBrowserTest {
+ public:
+ NonBlockingEventBrowserTest() {}
+ ~NonBlockingEventBrowserTest() override {}
+
+ RenderWidgetHostImpl* GetWidgetHost() {
+ return RenderWidgetHostImpl::From(
+ shell()->web_contents()->GetRenderViewHost()->GetWidget());
+ }
+
+ void OnSyntheticGestureCompleted(SyntheticGesture::Result result) {
+ EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result);
+ }
+
+ protected:
+ void LoadURL(const char* page_data) {
+ const GURL data_url(page_data);
+ NavigateToURL(shell(), data_url);
+
+ RenderWidgetHostImpl* host = GetWidgetHost();
+ host->GetView()->SetSize(gfx::Size(400, 400));
+
+ base::string16 ready_title(base::ASCIIToUTF16("ready"));
+ TitleWatcher watcher(shell()->web_contents(), ready_title);
+ ignore_result(watcher.WaitAndGetTitle());
+
+ MainThreadFrameObserver main_thread_sync(host);
+ main_thread_sync.Wait();
+ }
+
+ // ContentBrowserTest:
+ void SetUpCommandLine(base::CommandLine* cmd) override {
+ // TODO(dtapuska): Remove this switch once wheel-gestures ships.
+ cmd->AppendSwitch(switches::kEnableExperimentalWebPlatformFeatures);
+ cmd->AppendSwitch(switches::kEnableWheelGestures);
+ }
+
+ int ExecuteScriptAndExtractInt(const std::string& script) {
+ int value = 0;
+ EXPECT_TRUE(content::ExecuteScriptAndExtractInt(
+ shell()->web_contents(), "domAutomationController.send(" + script + ")",
+ &value));
+ return value;
+ }
+
+ int GetScrollTop() {
+ return ExecuteScriptAndExtractInt("document.scrollingElement.scrollTop");
+ }
+
+ void DoWheelScroll() {
+ EXPECT_EQ(0, GetScrollTop());
+
+ int scrollHeight =
+ ExecuteScriptAndExtractInt("document.documentElement.scrollHeight");
+ EXPECT_EQ(kWebsiteHeight, scrollHeight);
+
+ scoped_refptr<FrameWatcher> frame_watcher(new FrameWatcher());
+ frame_watcher->AttachTo(shell()->web_contents());
+ scoped_refptr<InputMsgWatcher> input_msg_watcher(
+ new InputMsgWatcher(GetWidgetHost(), blink::WebInputEvent::MouseWheel));
+
+ GetWidgetHost()->ForwardWheelEvent(
+ SyntheticWebMouseWheelEventBuilder::Build(10, 10, 0, -53, 0, true));
+
+ // Runs until we get the InputMsgAck callback
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING,
+ input_msg_watcher->WaitForAck());
+
+ // Expect that the compositor scrolled at least one pixel while the
+ // main thread was in a busy loop.
+ while (frame_watcher->LastMetadata().root_scroll_offset.y() <= 0)
+ frame_watcher->WaitFrames(1);
+ }
+
+ void DoTouchScroll() {
+ EXPECT_EQ(0, GetScrollTop());
+
+ int scrollHeight =
+ ExecuteScriptAndExtractInt("document.documentElement.scrollHeight");
+ EXPECT_EQ(kWebsiteHeight, scrollHeight);
+
+ scoped_refptr<FrameWatcher> frame_watcher(new FrameWatcher());
+ frame_watcher->AttachTo(shell()->web_contents());
+
+ SyntheticSmoothScrollGestureParams params;
+ params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ params.anchor = gfx::PointF(50, 50);
+ params.distances.push_back(gfx::Vector2d(0, -45));
+
+ scoped_ptr<SyntheticSmoothScrollGesture> gesture(
+ new SyntheticSmoothScrollGesture(params));
+ GetWidgetHost()->QueueSyntheticGesture(
+ std::move(gesture),
+ base::Bind(&NonBlockingEventBrowserTest::OnSyntheticGestureCompleted,
+ base::Unretained(this)));
+
+ // Expect that the compositor scrolled at least one pixel while the
+ // main thread was in a busy loop.
+ while (frame_watcher->LastMetadata().root_scroll_offset.y() <= 0)
+ frame_watcher->WaitFrames(1);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NonBlockingEventBrowserTest);
+};
+
+IN_PROC_BROWSER_TEST_F(NonBlockingEventBrowserTest, MouseWheel) {
+ LoadURL(kNonBlockingEventDataURL);
+ DoWheelScroll();
+}
+
+// Disabled on MacOS because it doesn't support touch input.
+#if defined(OS_MACOSX)
+#define MAYBE_TouchStart DISABLED_TouchStart
+#else
+#define MAYBE_TouchStart TouchStart
+#endif
+IN_PROC_BROWSER_TEST_F(NonBlockingEventBrowserTest, MAYBE_TouchStart) {
+ LoadURL(kNonBlockingEventDataURL);
+ DoTouchScroll();
+}
+
+// Disabled on MacOS because it doesn't support touch input.
+#if defined(OS_MACOSX)
+#define MAYBE_PassiveTouchStartBlockingTouchEnd \
+ DISABLED_PassiveTouchStartBlockingTouchEnd
+#else
+#define MAYBE_PassiveTouchStartBlockingTouchEnd \
+ PassiveTouchStartBlockingTouchEnd
+#endif
+IN_PROC_BROWSER_TEST_F(NonBlockingEventBrowserTest,
+ MAYBE_PassiveTouchStartBlockingTouchEnd) {
+ LoadURL(kPassiveTouchStartBlockingTouchEndDataURL);
+ DoTouchScroll();
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc b/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc
index 8fc03c71376..b0ba89f77e5 100644
--- a/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc
+++ b/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.cc
@@ -78,6 +78,9 @@ void UpdateLatencyCoordinates(const WebInputEvent& event,
void ComputeInputLatencyHistograms(WebInputEvent::Type type,
int64_t latency_component_id,
const LatencyInfo& latency) {
+ if (latency.coalesced())
+ return;
+
LatencyInfo::LatencyComponent rwh_component;
if (!latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
latency_component_id, &rwh_component)) {
@@ -157,26 +160,24 @@ void ComputeScrollLatencyHistograms(
const LatencyInfo::LatencyComponent& gpu_swap_end_component,
int64_t latency_component_id,
const LatencyInfo& latency) {
+ DCHECK(!latency.coalesced());
+ if (latency.coalesced())
+ return;
+
DCHECK(!gpu_swap_begin_component.event_time.is_null());
DCHECK(!gpu_swap_end_component.event_time.is_null());
- LatencyInfo::LatencyComponent first_original_component, original_component;
+ LatencyInfo::LatencyComponent original_component;
if (latency.FindLatency(
ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- latency_component_id, &first_original_component)) {
+ latency_component_id, &original_component)) {
// This UMA metric tracks the time between the final frame swap for the
// first scroll event in a sequence and the original timestamp of that
// scroll event's underlying touch event.
- for (size_t i = 0; i < first_original_component.event_count; i++) {
+ for (size_t i = 0; i < original_component.event_count; i++) {
UMA_HISTOGRAM_TOUCH_TO_SCROLL_LATENCY(
"Event.Latency.TouchToFirstScrollUpdateSwapBegin",
- first_original_component, gpu_swap_begin_component);
- // TODO(brianderson): Remove this version once we have enough overlapping
- // data with the metric above. crbug.com/478845
- UMA_HISTOGRAM_TOUCH_TO_SCROLL_LATENCY(
- "Event.Latency.TouchToFirstScrollUpdateSwap",
- first_original_component, gpu_swap_end_component);
+ original_component, gpu_swap_begin_component);
}
- original_component = first_original_component;
} else if (!latency.FindLatency(
ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
latency_component_id, &original_component)) {
@@ -184,17 +185,11 @@ void ComputeScrollLatencyHistograms(
}
// This UMA metric tracks the time from when the original touch event is
- // created (averaged if there are multiple) to when the scroll gesture
- // results in final frame swap.
+ // created to when the scroll gesture results in final frame swap.
for (size_t i = 0; i < original_component.event_count; i++) {
UMA_HISTOGRAM_TOUCH_TO_SCROLL_LATENCY(
"Event.Latency.TouchToScrollUpdateSwapBegin", original_component,
gpu_swap_begin_component);
- // TODO(brianderson): Remove this version once we have enough overlapping
- // data with the metric above. crbug.com/478845
- UMA_HISTOGRAM_TOUCH_TO_SCROLL_LATENCY(
- "Event.Latency.TouchToScrollUpdateSwap", original_component,
- gpu_swap_end_component);
}
// TODO(miletus): Add validation for making sure the following components
@@ -292,7 +287,7 @@ RenderWidgetHostLatencyTracker::RenderWidgetHostLatencyTracker()
: last_event_id_(0),
latency_component_id_(0),
device_scale_factor_(1),
- has_seent_first_gesture_scroll_update_(false) {
+ has_seen_first_gesture_scroll_update_(false) {
}
RenderWidgetHostLatencyTracker::~RenderWidgetHostLatencyTracker() {
@@ -345,7 +340,7 @@ void RenderWidgetHostLatencyTracker::OnInputEvent(
UpdateLatencyCoordinates(event, device_scale_factor_, latency);
if (event.type == blink::WebInputEvent::GestureScrollBegin) {
- has_seent_first_gesture_scroll_update_ = false;
+ has_seen_first_gesture_scroll_update_ = false;
} else if (event.type == blink::WebInputEvent::GestureScrollUpdate) {
// Make a copy of the INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT with a
// different name INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT.
@@ -354,14 +349,14 @@ void RenderWidgetHostLatencyTracker::OnInputEvent(
if (latency->FindLatency(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0,
&original_component)) {
latency->AddLatencyNumberWithTimestamp(
- has_seent_first_gesture_scroll_update_
+ has_seen_first_gesture_scroll_update_
? ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT
: ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
latency_component_id_, original_component.sequence_number,
original_component.event_time, original_component.event_count);
}
- has_seent_first_gesture_scroll_update_ = true;
+ has_seen_first_gesture_scroll_update_ = true;
}
}
@@ -432,6 +427,16 @@ void RenderWidgetHostLatencyTracker::OnSwapCompositorFrame(
void RenderWidgetHostLatencyTracker::OnFrameSwapped(
const LatencyInfo& latency) {
+ // Don't report frame latency on wheel events. Previously they were only
+ // reported on touch metrics and we need to be consistent across reporting
+ // metrics.
+ LatencyInfo::LatencyComponent mouse_wheel_scroll_update_component;
+ if (latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_GENERATE_SCROLL_UPDATE_FROM_MOUSE_WHEEL, 0,
+ &mouse_wheel_scroll_update_component)) {
+ return;
+ }
+
LatencyInfo::LatencyComponent gpu_swap_end_component;
if (!latency.FindLatency(
ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0,
diff --git a/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.h b/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.h
index 6df155fe792..633e4e878da 100644
--- a/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.h
+++ b/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker.h
@@ -64,7 +64,7 @@ class CONTENT_EXPORT RenderWidgetHostLatencyTracker {
int64_t last_event_id_;
int64_t latency_component_id_;
float device_scale_factor_;
- bool has_seent_first_gesture_scroll_update_;
+ bool has_seen_first_gesture_scroll_update_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostLatencyTracker);
};
diff --git a/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc b/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc
index baeb15cb755..32497449e01 100644
--- a/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/test/histogram_tester.h"
#include "content/browser/renderer_host/input/render_widget_host_latency_tracker.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "content/public/browser/native_web_keyboard_event.h"
@@ -12,73 +13,170 @@ using blink::WebInputEvent;
namespace content {
namespace {
-const int kTestRoutingId = 3;
-const int kTestProcessId = 1;
+void AddFakeComponents(const RenderWidgetHostLatencyTracker& tracker,
+ ui::LatencyInfo* latency) {
+ latency->AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0, base::TimeTicks::Now(), 1);
+ latency->AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0,
+ base::TimeTicks::Now(), 1);
+ latency->AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0,
+ base::TimeTicks::Now(), 1);
+ latency->AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
+ tracker.latency_component_id(), 0, base::TimeTicks::Now(), 1);
+ latency->AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT, 0, 0,
+ base::TimeTicks::Now(), 1);
+ latency->AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_BROWSER_RECEIVED_RENDERER_SWAP_COMPONENT, 0, 0,
+ base::TimeTicks::Now(), 1);
+}
+
+void AddRenderingScheduledComponent(ui::LatencyInfo* latency, bool main) {
+ if (main) {
+ latency->AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_MAIN_COMPONENT, 0, 0,
+ base::TimeTicks::Now(), 1);
+
+ } else {
+ latency->AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_RENDERING_SCHEDULED_IMPL_COMPONENT, 0, 0,
+ base::TimeTicks::Now(), 1);
+ }
+}
} // namespace
-TEST(RenderWidgetHostLatencyTrackerTest, Basic) {
- RenderWidgetHostLatencyTracker tracker;
- tracker.Initialize(kTestRoutingId, kTestProcessId);
+class RenderWidgetHostLatencyTrackerTest : public testing::Test {
+ public:
+ RenderWidgetHostLatencyTrackerTest() {
+ tracker_.Initialize(kTestRoutingId, kTestProcessId);
+ ResetHistograms();
+ }
- {
- auto scroll = SyntheticWebGestureEventBuilder::BuildScrollUpdate(
- 5.f, -5.f, 0, blink::WebGestureDeviceTouchscreen);
- scroll.timeStampSeconds =
- (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
- ui::LatencyInfo scroll_latency;
- tracker.OnInputEvent(scroll, &scroll_latency);
- EXPECT_TRUE(
- scroll_latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker.latency_component_id(), nullptr));
- EXPECT_TRUE(
- scroll_latency.FindLatency(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
- 0, nullptr));
- EXPECT_EQ(1U, scroll_latency.input_coordinates_size());
+ ::testing::AssertionResult HistogramSizeEq(const char* histogram_name,
+ int size) {
+ uint64_t histogram_size =
+ histogram_tester_->GetAllSamples(histogram_name).size();
+ if (static_cast<uint64_t>(size) == histogram_size) {
+ return ::testing::AssertionSuccess();
+ } else {
+ return ::testing::AssertionFailure() << histogram_name << " expected "
+ << size << " entries, but had "
+ << histogram_size;
+ }
}
- {
- auto wheel = SyntheticWebMouseWheelEventBuilder::Build(
- blink::WebMouseWheelEvent::PhaseChanged);
- wheel.timeStampSeconds =
- (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
- ui::LatencyInfo wheel_latency;
- tracker.OnInputEvent(wheel, &wheel_latency);
- EXPECT_TRUE(
- wheel_latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker.latency_component_id(), nullptr));
- EXPECT_TRUE(
- wheel_latency.FindLatency(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
- 0, nullptr));
- EXPECT_EQ(1U, wheel_latency.input_coordinates_size());
+ RenderWidgetHostLatencyTracker* tracker() { return &tracker_; }
+ void ResetHistograms() {
+ histogram_tester_.reset(new base::HistogramTester());
}
- {
- SyntheticWebTouchEvent touch;
- touch.PressPoint(0, 0);
- touch.PressPoint(1, 1);
- ui::LatencyInfo touch_latency;
- tracker.OnInputEvent(touch, &touch_latency);
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostLatencyTrackerTest);
+ const int kTestRoutingId = 3;
+ const int kTestProcessId = 1;
+ scoped_ptr<base::HistogramTester> histogram_tester_;
+ RenderWidgetHostLatencyTracker tracker_;
+};
+
+TEST_F(RenderWidgetHostLatencyTrackerTest, TestHistograms) {
+ for (bool rendering_on_main : { false, true }) {
+ ResetHistograms();
+ {
+ auto scroll = SyntheticWebGestureEventBuilder::BuildScrollUpdate(
+ 5.f, -5.f, 0, blink::WebGestureDeviceTouchscreen);
+ scroll.timeStampSeconds =
+ (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
+ ui::LatencyInfo scroll_latency;
+ AddFakeComponents(*tracker(), &scroll_latency);
+ AddRenderingScheduledComponent(&scroll_latency, rendering_on_main);
+ tracker()->OnInputEvent(scroll, &scroll_latency);
+ EXPECT_TRUE(scroll_latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
+ tracker()->latency_component_id(), nullptr));
+ EXPECT_TRUE(scroll_latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, nullptr));
+ EXPECT_EQ(1U, scroll_latency.input_coordinates_size());
+ tracker()->OnInputEventAck(scroll, &scroll_latency);
+ }
+
+ {
+ auto wheel = SyntheticWebMouseWheelEventBuilder::Build(
+ blink::WebMouseWheelEvent::PhaseChanged);
+ wheel.timeStampSeconds =
+ (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
+ ui::LatencyInfo wheel_latency;
+ AddFakeComponents(*tracker(), &wheel_latency);
+ AddRenderingScheduledComponent(&wheel_latency, rendering_on_main);
+ tracker()->OnInputEvent(wheel, &wheel_latency);
+ EXPECT_TRUE(wheel_latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
+ tracker()->latency_component_id(), nullptr));
+ EXPECT_TRUE(wheel_latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, nullptr));
+ EXPECT_EQ(1U, wheel_latency.input_coordinates_size());
+ tracker()->OnInputEventAck(wheel, &wheel_latency);
+ }
+
+ {
+ SyntheticWebTouchEvent touch;
+ touch.PressPoint(0, 0);
+ touch.PressPoint(1, 1);
+ ui::LatencyInfo touch_latency;
+ AddFakeComponents(*tracker(), &touch_latency);
+ AddRenderingScheduledComponent(&touch_latency, rendering_on_main);
+ tracker()->OnInputEvent(touch, &touch_latency);
+ EXPECT_TRUE(touch_latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
+ tracker()->latency_component_id(), nullptr));
+ EXPECT_TRUE(touch_latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, nullptr));
+ EXPECT_EQ(2U, touch_latency.input_coordinates_size());
+ tracker()->OnInputEventAck(touch, &touch_latency);
+ tracker()->OnFrameSwapped(touch_latency);
+ }
+
+ EXPECT_TRUE(HistogramSizeEq("Event.Latency.Browser.WheelUI", 1));
+ EXPECT_TRUE(HistogramSizeEq("Event.Latency.Browser.TouchUI", 1));
+ EXPECT_TRUE(HistogramSizeEq("Event.Latency.Browser.WheelAcked", 1));
+ EXPECT_TRUE(HistogramSizeEq("Event.Latency.Browser.TouchAcked", 1));
+ EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.TouchToFirstScrollUpdateSwapBegin", 1));
+ EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.TouchToScrollUpdateSwapBegin", 1));
EXPECT_TRUE(
- touch_latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker.latency_component_id(), nullptr));
+ HistogramSizeEq("Event.Latency.ScrollUpdate.TouchToHandled_Main",
+ rendering_on_main ? 1 : 0));
EXPECT_TRUE(
- touch_latency.FindLatency(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
- 0, nullptr));
- EXPECT_EQ(2U, touch_latency.input_coordinates_size());
+ HistogramSizeEq("Event.Latency.ScrollUpdate.TouchToHandled_Impl",
+ rendering_on_main ? 0 : 1));
+ EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.ScrollUpdate.HandledToRendererSwap_Main",
+ rendering_on_main ? 1 : 0));
+ EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.ScrollUpdate.HandledToRendererSwap_Impl",
+ rendering_on_main ? 0 : 1));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollUpdate.RendererSwapToBrowserNotified", 1));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollUpdate.BrowserNotifiedToBeforeGpuSwap", 1));
+ EXPECT_TRUE(HistogramSizeEq("Event.Latency.ScrollUpdate.GpuSwap", 1));
}
}
-TEST(RenderWidgetHostLatencyTrackerTest,
- LatencyTerminatedOnAckIfRenderingNotScheduled) {
- RenderWidgetHostLatencyTracker tracker;
- tracker.Initialize(kTestRoutingId, kTestProcessId);
-
+TEST_F(RenderWidgetHostLatencyTrackerTest,
+ LatencyTerminatedOnAckIfRenderingNotScheduled) {
{
auto scroll = SyntheticWebGestureEventBuilder::BuildScrollBegin(5.f, -5.f);
ui::LatencyInfo scroll_latency;
- tracker.OnInputEvent(scroll, &scroll_latency);
- tracker.OnInputEventAck(scroll, &scroll_latency);
+ AddFakeComponents(*tracker(), &scroll_latency);
+ // Don't include the rendering schedule component, since we're testing the
+ // case where rendering isn't scheduled.
+ tracker()->OnInputEvent(scroll, &scroll_latency);
+ tracker()->OnInputEventAck(scroll, &scroll_latency);
EXPECT_TRUE(scroll_latency.FindLatency(
ui::INPUT_EVENT_LATENCY_TERMINATED_GESTURE_COMPONENT, 0, nullptr));
EXPECT_TRUE(scroll_latency.terminated());
@@ -88,8 +186,9 @@ TEST(RenderWidgetHostLatencyTrackerTest,
auto wheel = SyntheticWebMouseWheelEventBuilder::Build(
blink::WebMouseWheelEvent::PhaseChanged);
ui::LatencyInfo wheel_latency;
- tracker.OnInputEvent(wheel, &wheel_latency);
- tracker.OnInputEventAck(wheel, &wheel_latency);
+ AddFakeComponents(*tracker(), &wheel_latency);
+ tracker()->OnInputEvent(wheel, &wheel_latency);
+ tracker()->OnInputEventAck(wheel, &wheel_latency);
EXPECT_TRUE(wheel_latency.FindLatency(
ui::INPUT_EVENT_LATENCY_TERMINATED_MOUSE_WHEEL_COMPONENT, 0, nullptr));
EXPECT_TRUE(wheel_latency.terminated());
@@ -99,19 +198,22 @@ TEST(RenderWidgetHostLatencyTrackerTest,
SyntheticWebTouchEvent touch;
touch.PressPoint(0, 0);
ui::LatencyInfo touch_latency;
- tracker.OnInputEvent(touch, &touch_latency);
- tracker.OnInputEventAck(touch, &touch_latency);
+ AddFakeComponents(*tracker(), &touch_latency);
+ tracker()->OnInputEvent(touch, &touch_latency);
+ tracker()->OnInputEventAck(touch, &touch_latency);
EXPECT_TRUE(touch_latency.FindLatency(
ui::INPUT_EVENT_LATENCY_TERMINATED_TOUCH_COMPONENT, 0, nullptr));
EXPECT_TRUE(touch_latency.terminated());
+ tracker()->OnFrameSwapped(touch_latency);
}
{
auto mouse_move = SyntheticWebMouseEventBuilder::Build(
blink::WebMouseEvent::MouseMove);
ui::LatencyInfo mouse_latency;
- tracker.OnInputEvent(mouse_move, &mouse_latency);
- tracker.OnInputEventAck(mouse_move, &mouse_latency);
+ AddFakeComponents(*tracker(), &mouse_latency);
+ tracker()->OnInputEvent(mouse_move, &mouse_latency);
+ tracker()->OnInputEventAck(mouse_move, &mouse_latency);
EXPECT_TRUE(mouse_latency.FindLatency(
ui::INPUT_EVENT_LATENCY_TERMINATED_MOUSE_COMPONENT, 0, nullptr));
EXPECT_TRUE(mouse_latency.terminated());
@@ -121,25 +223,44 @@ TEST(RenderWidgetHostLatencyTrackerTest,
auto key_event = SyntheticWebKeyboardEventBuilder::Build(
blink::WebKeyboardEvent::Char);
ui::LatencyInfo key_latency;
- tracker.OnInputEvent(key_event, &key_latency);
- tracker.OnInputEventAck(key_event, &key_latency);
+ AddFakeComponents(*tracker(), &key_latency);
+ tracker()->OnInputEvent(key_event, &key_latency);
+ tracker()->OnInputEventAck(key_event, &key_latency);
EXPECT_TRUE(key_latency.FindLatency(
ui::INPUT_EVENT_LATENCY_TERMINATED_KEYBOARD_COMPONENT, 0, nullptr));
EXPECT_TRUE(key_latency.terminated());
}
-}
-TEST(RenderWidgetHostLatencyTrackerTest, InputCoordinatesPopulated) {
- RenderWidgetHostLatencyTracker tracker;
- tracker.Initialize(kTestRoutingId, kTestProcessId);
+ EXPECT_TRUE(HistogramSizeEq("Event.Latency.Browser.WheelUI", 1));
+ EXPECT_TRUE(HistogramSizeEq("Event.Latency.Browser.TouchUI", 1));
+ EXPECT_TRUE(HistogramSizeEq("Event.Latency.Browser.WheelAcked", 1));
+ EXPECT_TRUE(HistogramSizeEq("Event.Latency.Browser.TouchAcked", 1));
+ EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.TouchToFirstScrollUpdateSwapBegin", 1));
+ EXPECT_TRUE(HistogramSizeEq("Event.Latency.TouchToScrollUpdateSwapBegin", 1));
+ EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.ScrollUpdate.TouchToHandled_Main", 0));
+ EXPECT_TRUE(
+ HistogramSizeEq("Event.Latency.ScrollUpdate.TouchToHandled_Impl", 0));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollUpdate.HandledToRendererSwap_Main", 0));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollUpdate.HandledToRendererSwap_Impl", 0));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollUpdate.RendererSwapToBrowserNotified", 0));
+ EXPECT_TRUE(HistogramSizeEq(
+ "Event.Latency.ScrollUpdate.BrowserNotifiedToBeforeGpuSwap", 0));
+ EXPECT_TRUE(HistogramSizeEq("Event.Latency.ScrollUpdate.GpuSwap", 0));
+}
+TEST_F(RenderWidgetHostLatencyTrackerTest, InputCoordinatesPopulated) {
{
auto event =
SyntheticWebMouseWheelEventBuilder::Build(0, 0, -5, 0, 0, true);
event.x = 100;
event.y = 200;
ui::LatencyInfo latency_info;
- tracker.OnInputEvent(event, &latency_info);
+ tracker()->OnInputEvent(event, &latency_info);
EXPECT_EQ(1u, latency_info.input_coordinates_size());
EXPECT_EQ(100, latency_info.input_coordinates()[0].x);
EXPECT_EQ(200, latency_info.input_coordinates()[0].y);
@@ -150,7 +271,7 @@ TEST(RenderWidgetHostLatencyTrackerTest, InputCoordinatesPopulated) {
event.x = 300;
event.y = 400;
ui::LatencyInfo latency_info;
- tracker.OnInputEvent(event, &latency_info);
+ tracker()->OnInputEvent(event, &latency_info);
EXPECT_EQ(1u, latency_info.input_coordinates_size());
EXPECT_EQ(300, latency_info.input_coordinates()[0].x);
EXPECT_EQ(400, latency_info.input_coordinates()[0].y);
@@ -162,7 +283,7 @@ TEST(RenderWidgetHostLatencyTrackerTest, InputCoordinatesPopulated) {
event.x = 500;
event.y = 600;
ui::LatencyInfo latency_info;
- tracker.OnInputEvent(event, &latency_info);
+ tracker()->OnInputEvent(event, &latency_info);
EXPECT_EQ(1u, latency_info.input_coordinates_size());
EXPECT_EQ(500, latency_info.input_coordinates()[0].x);
EXPECT_EQ(600, latency_info.input_coordinates()[0].y);
@@ -174,7 +295,7 @@ TEST(RenderWidgetHostLatencyTrackerTest, InputCoordinatesPopulated) {
event.PressPoint(900, 1000);
event.PressPoint(1100, 1200); // LatencyInfo only holds two coordinates.
ui::LatencyInfo latency_info;
- tracker.OnInputEvent(event, &latency_info);
+ tracker()->OnInputEvent(event, &latency_info);
EXPECT_EQ(2u, latency_info.input_coordinates_size());
EXPECT_EQ(700, latency_info.input_coordinates()[0].x);
EXPECT_EQ(800, latency_info.input_coordinates()[0].y);
@@ -186,23 +307,20 @@ TEST(RenderWidgetHostLatencyTrackerTest, InputCoordinatesPopulated) {
NativeWebKeyboardEvent event;
event.type = blink::WebKeyboardEvent::KeyDown;
ui::LatencyInfo latency_info;
- tracker.OnInputEvent(event, &latency_info);
+ tracker()->OnInputEvent(event, &latency_info);
EXPECT_EQ(0u, latency_info.input_coordinates_size());
}
}
-TEST(RenderWidgetHostLatencyTrackerTest, ScrollLatency) {
- RenderWidgetHostLatencyTracker tracker;
- tracker.Initialize(kTestRoutingId, kTestProcessId);
-
+TEST_F(RenderWidgetHostLatencyTrackerTest, ScrollLatency) {
auto scroll_begin = SyntheticWebGestureEventBuilder::BuildScrollBegin(5, -5);
ui::LatencyInfo scroll_latency;
scroll_latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0,
0);
- tracker.OnInputEvent(scroll_begin, &scroll_latency);
+ tracker()->OnInputEvent(scroll_begin, &scroll_latency);
EXPECT_TRUE(
scroll_latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker.latency_component_id(), nullptr));
+ tracker()->latency_component_id(), nullptr));
EXPECT_EQ(2U, scroll_latency.latency_components().size());
// The first GestureScrollUpdate should be provided with
@@ -212,35 +330,35 @@ TEST(RenderWidgetHostLatencyTrackerTest, ScrollLatency) {
scroll_latency = ui::LatencyInfo();
scroll_latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0,
0);
- tracker.OnInputEvent(first_scroll_update, &scroll_latency);
+ tracker()->OnInputEvent(first_scroll_update, &scroll_latency);
EXPECT_TRUE(
scroll_latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker.latency_component_id(), nullptr));
+ tracker()->latency_component_id(), nullptr));
EXPECT_TRUE(scroll_latency.FindLatency(
ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- tracker.latency_component_id(), nullptr));
+ tracker()->latency_component_id(), nullptr));
EXPECT_FALSE(scroll_latency.FindLatency(
ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- tracker.latency_component_id(), nullptr));
+ tracker()->latency_component_id(), nullptr));
EXPECT_EQ(3U, scroll_latency.latency_components().size());
- // Subseqeunt GestureScrollUpdates should be provided with
+ // Subsequent GestureScrollUpdates should be provided with
// INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT.
auto scroll_update = SyntheticWebGestureEventBuilder::BuildScrollUpdate(
-5.f, 5.f, 0, blink::WebGestureDeviceTouchscreen);
scroll_latency = ui::LatencyInfo();
scroll_latency.AddLatencyNumber(ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0,
0);
- tracker.OnInputEvent(scroll_update, &scroll_latency);
+ tracker()->OnInputEvent(scroll_update, &scroll_latency);
EXPECT_TRUE(
scroll_latency.FindLatency(ui::INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- tracker.latency_component_id(), nullptr));
+ tracker()->latency_component_id(), nullptr));
EXPECT_FALSE(scroll_latency.FindLatency(
ui::INPUT_EVENT_LATENCY_FIRST_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- tracker.latency_component_id(), nullptr));
+ tracker()->latency_component_id(), nullptr));
EXPECT_TRUE(scroll_latency.FindLatency(
ui::INPUT_EVENT_LATENCY_SCROLL_UPDATE_ORIGINAL_COMPONENT,
- tracker.latency_component_id(), nullptr));
+ tracker()->latency_component_id(), nullptr));
EXPECT_EQ(3U, scroll_latency.latency_components().size());
}
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture.cc
index ebe8712e15c..a6aa6bd3c7e 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture.cc
@@ -7,6 +7,7 @@
#include "base/logging.h"
#include "content/browser/renderer_host/input/synthetic_gesture_target.h"
#include "content/browser/renderer_host/input/synthetic_pinch_gesture.h"
+#include "content/browser/renderer_host/input/synthetic_pointer_action.h"
#include "content/browser/renderer_host/input/synthetic_smooth_drag_gesture.h"
#include "content/browser/renderer_host/input/synthetic_smooth_scroll_gesture.h"
#include "content/browser/renderer_host/input/synthetic_tap_gesture.h"
@@ -42,6 +43,9 @@ scoped_ptr<SyntheticGesture> SyntheticGesture::Create(
case SyntheticGestureParams::TAP_GESTURE:
return CreateGesture<SyntheticTapGesture,
SyntheticTapGestureParams>(gesture_params);
+ case SyntheticGestureParams::POINTER_ACTION:
+ return CreateGesture<SyntheticPointerAction,
+ SyntheticPointerActionParams>(gesture_params);
}
NOTREACHED() << "Invalid synthetic gesture type";
return scoped_ptr<SyntheticGesture>();
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture.h b/chromium/content/browser/renderer_host/input/synthetic_gesture.h
index 626bd15aa65..4177b067c49 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture.h
@@ -41,8 +41,6 @@ class CONTENT_EXPORT SyntheticGesture {
GESTURE_RESULT_MAX = GESTURE_SOURCE_TYPE_NOT_IMPLEMENTED
};
- enum PointerActionType { PRESS, MOVE, RELEASE };
-
// Update the state of the gesture and forward the appropriate events to the
// platform. This function is called repeatedly by the synthetic gesture
// controller until it stops returning GESTURE_RUNNING.
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.h b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.h
index aeef18f5024..f7b03c2fd79 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller.h
@@ -60,7 +60,7 @@ class CONTENT_EXPORT SyntheticGestureController {
~GestureAndCallbackQueue();
void Push(scoped_ptr<SyntheticGesture> gesture,
const OnGestureCompleteCallback& callback) {
- gestures_.push_back(gesture.release());
+ gestures_.push_back(std::move(gesture));
callbacks_.push(callback);
}
void Pop() {
diff --git a/chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
index 9369bfdfdc8..c1e36823b7e 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_gesture_controller_unittest.cc
@@ -1470,55 +1470,56 @@ TEST_F(SyntheticGestureControllerTest, TapGestureMouse) {
TEST_F(SyntheticGestureControllerTest, PointerTouchAction) {
CreateControllerAndTarget<MockSyntheticPointerTouchActionTarget>();
+ SyntheticPointerActionParams params = SyntheticPointerActionParams(
+ SyntheticPointerActionParams::PointerActionType::PRESS);
+ params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ params.set_index(0);
+ params.set_position(gfx::PointF(54, 89));
SyntheticTouchPointer synthetic_pointer;
- gfx::PointF position(54, 89);
- scoped_ptr<SyntheticPointerAction> gesture(new SyntheticPointerAction(
- SyntheticGestureParams::TOUCH_INPUT, SyntheticGesture::PRESS,
- &synthetic_pointer, position));
+ scoped_ptr<SyntheticPointerAction> gesture(
+ new SyntheticPointerAction(params, &synthetic_pointer));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
MockSyntheticPointerTouchActionTarget* pointer_touch_target =
static_cast<MockSyntheticPointerTouchActionTarget*>(target_);
EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::TouchStart);
- EXPECT_EQ(pointer_touch_target->positions(0), position);
+ EXPECT_EQ(pointer_touch_target->positions(0), params.position());
EXPECT_EQ(pointer_touch_target->states(0), WebTouchPoint::StatePressed);
ASSERT_EQ(pointer_touch_target->touch_length(), 1U);
- position.SetPoint(79, 132);
- gesture.reset(new SyntheticPointerAction(SyntheticGestureParams::TOUCH_INPUT,
- SyntheticGesture::PRESS,
- &synthetic_pointer, position));
+ params.set_index(1);
+ params.set_position(gfx::PointF(79, 132));
+ gesture.reset(new SyntheticPointerAction(params, &synthetic_pointer));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
pointer_touch_target =
static_cast<MockSyntheticPointerTouchActionTarget*>(target_);
EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::TouchStart);
- EXPECT_EQ(pointer_touch_target->indexes(1), 1);
- EXPECT_EQ(pointer_touch_target->positions(1), position);
+ EXPECT_EQ(pointer_touch_target->indexes(1), params.index());
+ EXPECT_EQ(pointer_touch_target->positions(1), params.position());
EXPECT_EQ(pointer_touch_target->states(1), WebTouchPoint::StatePressed);
ASSERT_EQ(pointer_touch_target->touch_length(), 2U);
- int index = 1;
- position.SetPoint(133, 156);
- gesture.reset(new SyntheticPointerAction(
- SyntheticGestureParams::TOUCH_INPUT, SyntheticGesture::MOVE,
- &synthetic_pointer, position, index));
+ params.set_pointer_action_type(
+ SyntheticPointerActionParams::PointerActionType::MOVE);
+ params.set_position(gfx::PointF(133, 156));
+ gesture.reset(new SyntheticPointerAction(params, &synthetic_pointer));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
pointer_touch_target =
static_cast<MockSyntheticPointerTouchActionTarget*>(target_);
EXPECT_EQ(pointer_touch_target->type(), WebInputEvent::TouchMove);
- EXPECT_EQ(pointer_touch_target->positions(1), position);
+ EXPECT_EQ(pointer_touch_target->positions(1), params.position());
EXPECT_EQ(pointer_touch_target->states(1), WebTouchPoint::StateMoved);
ASSERT_EQ(pointer_touch_target->touch_length(), 2U);
- gesture.reset(new SyntheticPointerAction(
- SyntheticGestureParams::TOUCH_INPUT, SyntheticGesture::RELEASE,
- &synthetic_pointer, position, index));
+ params.set_pointer_action_type(
+ SyntheticPointerActionParams::PointerActionType::RELEASE);
+ gesture.reset(new SyntheticPointerAction(params, &synthetic_pointer));
QueueSyntheticGesture(std::move(gesture));
FlushInputUntilComplete();
diff --git a/chromium/content/browser/renderer_host/input/synthetic_pointer_action.cc b/chromium/content/browser/renderer_host/input/synthetic_pointer_action.cc
index 2577e3f5497..6353f342631 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_pointer_action.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_pointer_action.cc
@@ -11,26 +11,24 @@
namespace content {
SyntheticPointerAction::SyntheticPointerAction(
- SyntheticGestureParams::GestureSourceType gesture_source_type,
- PointerActionType pointer_action_type,
- SyntheticPointer* synthetic_pointer,
- gfx::PointF position,
- int index)
- : gesture_source_type_(gesture_source_type),
- pointer_action_type_(pointer_action_type),
- position_(position),
- index_(index),
- synthetic_pointer_(synthetic_pointer) {}
+ const SyntheticPointerActionParams& params)
+ : params_(params) {}
+
+SyntheticPointerAction::SyntheticPointerAction(
+ const SyntheticPointerActionParams& params,
+ SyntheticPointer* synthetic_pointer)
+ : params_(params), synthetic_pointer_(synthetic_pointer) {}
SyntheticPointerAction::~SyntheticPointerAction() {}
SyntheticGesture::Result SyntheticPointerAction::ForwardInputEvents(
const base::TimeTicks& timestamp,
SyntheticGestureTarget* target) {
- if (gesture_source_type_ == SyntheticGestureParams::DEFAULT_INPUT)
- gesture_source_type_ = target->GetDefaultSyntheticGestureSourceType();
+ if (params_.gesture_source_type == SyntheticGestureParams::DEFAULT_INPUT)
+ params_.gesture_source_type =
+ target->GetDefaultSyntheticGestureSourceType();
- DCHECK_NE(gesture_source_type_, SyntheticGestureParams::DEFAULT_INPUT);
+ DCHECK_NE(params_.gesture_source_type, SyntheticGestureParams::DEFAULT_INPUT);
ForwardTouchOrMouseInputEvents(timestamp, target);
return SyntheticGesture::GESTURE_FINISHED;
@@ -39,17 +37,20 @@ SyntheticGesture::Result SyntheticPointerAction::ForwardInputEvents(
void SyntheticPointerAction::ForwardTouchOrMouseInputEvents(
const base::TimeTicks& timestamp,
SyntheticGestureTarget* target) {
- switch (pointer_action_type_) {
- case SyntheticGesture::PRESS:
- synthetic_pointer_->Press(position_.x(), position_.y(), target,
- timestamp);
+ switch (params_.pointer_action_type()) {
+ case SyntheticPointerActionParams::PointerActionType::PRESS:
+ synthetic_pointer_->Press(params_.position().x(), params_.position().y(),
+ target, timestamp);
+ break;
+ case SyntheticPointerActionParams::PointerActionType::MOVE:
+ synthetic_pointer_->Move(params_.index(), params_.position().x(),
+ params_.position().y(), target, timestamp);
break;
- case SyntheticGesture::MOVE:
- synthetic_pointer_->Move(index_, position_.x(), position_.y(), target,
- timestamp);
+ case SyntheticPointerActionParams::PointerActionType::RELEASE:
+ synthetic_pointer_->Release(params_.index(), target, timestamp);
break;
- case SyntheticGesture::RELEASE:
- synthetic_pointer_->Release(index_, target, timestamp);
+ default:
+ NOTREACHED();
break;
}
synthetic_pointer_->DispatchEvent(target, timestamp);
diff --git a/chromium/content/browser/renderer_host/input/synthetic_pointer_action.h b/chromium/content/browser/renderer_host/input/synthetic_pointer_action.h
index d1907764c8a..23b23fa421b 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_pointer_action.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_pointer_action.h
@@ -10,17 +10,15 @@
#include "content/browser/renderer_host/input/synthetic_gesture_target.h"
#include "content/browser/renderer_host/input/synthetic_pointer.h"
#include "content/common/content_export.h"
+#include "content/common/input/synthetic_pointer_action_params.h"
namespace content {
class CONTENT_EXPORT SyntheticPointerAction : public SyntheticGesture {
public:
- SyntheticPointerAction(
- SyntheticGestureParams::GestureSourceType gesture_source_type,
- PointerActionType pointer_action_type,
- SyntheticPointer* synthetic_pointer,
- gfx::PointF position,
- int index = 0);
+ explicit SyntheticPointerAction(const SyntheticPointerActionParams& params);
+ SyntheticPointerAction(const SyntheticPointerActionParams& params,
+ SyntheticPointer* synthetic_pointer);
~SyntheticPointerAction() override;
SyntheticGesture::Result ForwardInputEvents(
@@ -31,10 +29,7 @@ class CONTENT_EXPORT SyntheticPointerAction : public SyntheticGesture {
SyntheticGestureTarget* target);
private:
- SyntheticGestureParams::GestureSourceType gesture_source_type_;
- PointerActionType pointer_action_type_;
- gfx::PointF position_;
- int index_;
+ SyntheticPointerActionParams params_;
SyntheticPointer* synthetic_pointer_;
DISALLOW_COPY_AND_ASSIGN(SyntheticPointerAction);
diff --git a/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc b/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc
index 3ddb0a34caf..6a9264d2f66 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc
+++ b/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.cc
@@ -42,6 +42,9 @@ SyntheticSmoothMoveGestureParams::SyntheticSmoothMoveGestureParams()
prevent_fling(true),
add_slop(true) {}
+SyntheticSmoothMoveGestureParams::SyntheticSmoothMoveGestureParams(
+ const SyntheticSmoothMoveGestureParams& other) = default;
+
SyntheticSmoothMoveGestureParams::~SyntheticSmoothMoveGestureParams() {}
SyntheticSmoothMoveGesture::SyntheticSmoothMoveGesture(
diff --git a/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.h b/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.h
index 577a8c03e81..28be20eb50f 100644
--- a/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.h
+++ b/chromium/content/browser/renderer_host/input/synthetic_smooth_move_gesture.h
@@ -24,6 +24,8 @@ namespace content {
class CONTENT_EXPORT SyntheticSmoothMoveGestureParams {
public:
SyntheticSmoothMoveGestureParams();
+ SyntheticSmoothMoveGestureParams(
+ const SyntheticSmoothMoveGestureParams& other);
~SyntheticSmoothMoveGestureParams();
enum InputType { MOUSE_DRAG_INPUT, MOUSE_WHEEL_INPUT, TOUCH_INPUT };
diff --git a/chromium/content/browser/renderer_host/input/touch_action_browsertest.cc b/chromium/content/browser/renderer_host/input/touch_action_browsertest.cc
index 72c8bc99086..a1a9e8378e1 100644
--- a/chromium/content/browser/renderer_host/input/touch_action_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_action_browsertest.cc
@@ -94,7 +94,7 @@ class TouchActionBrowserTest : public ContentBrowserTest {
RenderWidgetHostImpl* host = GetWidgetHost();
scoped_refptr<FrameWatcher> frame_watcher(new FrameWatcher());
- host->GetProcess()->AddFilter(frame_watcher.get());
+ frame_watcher->AttachTo(shell()->web_contents());
host->GetView()->SetSize(gfx::Size(400, 400));
base::string16 ready_title(base::ASCIIToUTF16("ready"));
diff --git a/chromium/content/browser/renderer_host/input/touch_emulator.cc b/chromium/content/browser/renderer_host/input/touch_emulator.cc
index af8e6031918..1417c637d6e 100644
--- a/chromium/content/browser/renderer_host/input/touch_emulator.cc
+++ b/chromium/content/browser/renderer_host/input/touch_emulator.cc
@@ -250,7 +250,7 @@ void TouchEmulator::HandleEmulatedTouchEvent(blink::WebTouchEvent event) {
if (is_sequence_start)
emulated_stream_active_sequence_count_++;
- event.causesScrollingIfUncanceled = result.did_generate_scroll;
+ event.movedBeyondSlopRegion = result.moved_beyond_slop_region;
client_->ForwardEmulatedTouchEvent(event);
}
@@ -449,6 +449,7 @@ void TouchEmulator::FillTouchEventAndPoint(const WebMouseEvent& mouse_event) {
point.screenPosition.y = mouse_event.globalY;
point.tiltX = 0;
point.tiltY = 0;
+ point.pointerType = blink::WebPointerProperties::PointerType::Touch;
}
bool TouchEmulator::InPinchGestureMode() const {
diff --git a/chromium/content/browser/renderer_host/input/touch_emulator.h b/chromium/content/browser/renderer_host/input/touch_emulator.h
index d02494547a6..c4fd18f74b4 100644
--- a/chromium/content/browser/renderer_host/input/touch_emulator.h
+++ b/chromium/content/browser/renderer_host/input/touch_emulator.h
@@ -30,7 +30,7 @@ class CONTENT_EXPORT TouchEmulator : public ui::GestureProviderClient {
// Note that TouchEmulator should always listen to touch events and their acks
// (even in disabled state) to track native stream presence.
- bool enabled() const { return gesture_provider_; }
+ bool enabled() const { return !!gesture_provider_; }
// Returns |true| if the event was consumed. Consumed event should not
// propagate any further.
diff --git a/chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc b/chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc
index 0062a2f6b52..04cb8191960 100644
--- a/chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_emulator_unittest.cc
@@ -62,8 +62,11 @@ class TouchEmulatorTest : public testing::Test,
EXPECT_EQ(1U, event.touchesLength);
EXPECT_EQ(last_mouse_x_, event.touches[0].position.x);
EXPECT_EQ(last_mouse_y_, event.touches[0].position.y);
- bool expected_cancelable = event.type != WebInputEvent::TouchCancel;
- EXPECT_EQ(expected_cancelable, !!event.cancelable);
+ WebInputEvent::DispatchType expected_dispatch_type =
+ event.type == WebInputEvent::TouchCancel
+ ? WebInputEvent::EventNonBlocking
+ : WebInputEvent::Blocking;
+ EXPECT_EQ(expected_dispatch_type, event.dispatchType);
if (ack_touches_synchronously_) {
emulator()->HandleTouchEventAck(
event, INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
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 550b46bfc47..9f6e3b2f6be 100644
--- a/chromium/content/browser/renderer_host/input/touch_event_queue.cc
+++ b/chromium/content/browser/renderer_host/input/touch_event_queue.cc
@@ -46,8 +46,7 @@ TouchEventWithLatencyInfo ObtainCancelEventForTouchEvent(
bool ShouldTouchTriggerTimeout(const WebTouchEvent& event) {
return (event.type == WebInputEvent::TouchStart ||
event.type == WebInputEvent::TouchMove) &&
- WebInputEventTraits::WillReceiveAckFromRenderer(event) &&
- event.cancelable;
+ event.dispatchType == WebInputEvent::Blocking;
}
// Compare all properties of touch points to determine the state.
@@ -310,7 +309,7 @@ class TouchEventQueue::TouchMoveSlopSuppressor {
if (suppressing_touchmoves_) {
if (event.touchesLength > 1) {
suppressing_touchmoves_ = false;
- } else if (event.causesScrollingIfUncanceled) {
+ } else if (event.movedBeyondSlopRegion) {
suppressing_touchmoves_ = false;
} else {
// No sane slop region should be larger than 60 DIPs.
@@ -467,6 +466,7 @@ void TouchEventQueue::QueueEvent(const TouchEventWithLatencyInfo& event) {
// yields identical results, but this avoids unnecessary allocations.
PreFilterResult filter_result = FilterBeforeForwarding(event.event);
if (filter_result != FORWARD_TO_RENDERER) {
+ client_->OnFilteringTouchEvent(event.event);
client_->OnTouchEventAck(event,
filter_result == ACK_WITH_NO_CONSUMER_EXISTS
? INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS
@@ -537,8 +537,10 @@ void TouchEventQueue::TryForwardNextEventToRenderer() {
// If there are queued touch events, then try to forward them to the renderer
// immediately, or ACK the events back to the client if appropriate.
while (!touch_queue_.empty()) {
- PreFilterResult filter_result =
- FilterBeforeForwarding(touch_queue_.front()->coalesced_event().event);
+ const WebTouchEvent& event = touch_queue_.front()->coalesced_event().event;
+ PreFilterResult filter_result = FilterBeforeForwarding(event);
+ if (filter_result != FORWARD_TO_RENDERER)
+ client_->OnFilteringTouchEvent(event);
switch (filter_result) {
case ACK_WITH_NO_CONSUMER_EXISTS:
PopTouchEventToClient(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS);
@@ -601,7 +603,9 @@ void TouchEventQueue::ForwardNextEventToRenderer() {
if (pending_async_touchmove_) {
if (pending_async_touchmove_->CanCoalesceWith(touch)) {
pending_async_touchmove_->CoalesceWith(touch);
- pending_async_touchmove_->event.cancelable = !send_touch_events_async_;
+ pending_async_touchmove_->event.dispatchType =
+ send_touch_events_async_ ? WebInputEvent::EventNonBlocking
+ : WebInputEvent::Blocking;
touch = *pending_async_touchmove_;
pending_async_touchmove_.reset();
} else {
@@ -614,7 +618,7 @@ void TouchEventQueue::ForwardNextEventToRenderer() {
// platform scrolling and JS pinching. Touchend events, however, remain
// uncancelable, mitigating the risk of jank when transitioning to a fling.
if (send_touch_events_async_ && touch.event.type != WebInputEvent::TouchStart)
- touch.event.cancelable = false;
+ touch.event.dispatchType = WebInputEvent::EventNonBlocking;
SendTouchEventImmediately(&touch);
}
@@ -623,7 +627,7 @@ void TouchEventQueue::FlushPendingAsyncTouchmove() {
DCHECK(!dispatching_touch_);
scoped_ptr<TouchEventWithLatencyInfo> touch =
std::move(pending_async_touchmove_);
- touch->event.cancelable = false;
+ touch->event.dispatchType = WebInputEvent::EventNonBlocking;
touch_queue_.push_front(new CoalescedWebTouchEvent(*touch, true));
SendTouchEventImmediately(touch.get());
}
@@ -695,7 +699,7 @@ bool TouchEventQueue::IsAckTimeoutEnabled() const {
}
bool TouchEventQueue::HasPendingAsyncTouchMoveForTesting() const {
- return pending_async_touchmove_;
+ return !!pending_async_touchmove_;
}
bool TouchEventQueue::IsTimeoutRunningForTesting() const {
@@ -783,7 +787,7 @@ void TouchEventQueue::SendTouchEventImmediately(
// timeout should not be started and the count also should not be increased.
if (dispatching_touch_) {
if (touch->event.type == WebInputEvent::TouchMove &&
- !touch->event.cancelable) {
+ touch->event.dispatchType != WebInputEvent::Blocking) {
// When we send out a uncancelable touch move, we increase the count and
// we do not process input event ack any more, we will just ack to client
// and wait for the ack from render. Also we will remove it from the front
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 4b69d98bbcc..8a19586c618 100644
--- a/chromium/content/browser/renderer_host/input/touch_event_queue.h
+++ b/chromium/content/browser/renderer_host/input/touch_event_queue.h
@@ -35,6 +35,9 @@ class CONTENT_EXPORT TouchEventQueueClient {
virtual void OnTouchEventAck(
const TouchEventWithLatencyInfo& event,
InputEventAckState ack_result) = 0;
+
+ virtual void OnFilteringTouchEvent(
+ const blink::WebTouchEvent& touch_event) = 0;
};
// A queue for throttling and coalescing touch-events.
diff --git a/chromium/content/browser/renderer_host/input/touch_event_queue_unittest.cc b/chromium/content/browser/renderer_host/input/touch_event_queue_unittest.cc
index f1091d48172..f2362b2bb18 100644
--- a/chromium/content/browser/renderer_host/input/touch_event_queue_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_event_queue_unittest.cc
@@ -84,6 +84,9 @@ class TouchEventQueueTest : public testing::Test,
}
}
+ void OnFilteringTouchEvent(const blink::WebTouchEvent& touch_event) override {
+ }
+
protected:
void SetUpForTouchMoveSlopTesting(double slop_length_dips) {
slop_length_dips_ = slop_length_dips;
@@ -105,17 +108,16 @@ class TouchEventQueueTest : public testing::Test,
void SendTouchEvent(WebTouchEvent event) {
if (slop_length_dips_) {
- event.causesScrollingIfUncanceled = false;
+ event.movedBeyondSlopRegion = false;
if (WebTouchEventTraits::IsTouchSequenceStart(event))
anchor_ = event.touches[0].position;
if (event.type == WebInputEvent::TouchMove) {
gfx::Vector2dF delta = anchor_ - event.touches[0].position;
if (delta.LengthSquared() > slop_length_dips_ * slop_length_dips_)
- event.causesScrollingIfUncanceled = true;
+ event.movedBeyondSlopRegion = true;
}
} else {
- event.causesScrollingIfUncanceled =
- event.type == WebInputEvent::TouchMove;
+ event.movedBeyondSlopRegion = event.type == WebInputEvent::TouchMove;
}
queue_->QueueEvent(TouchEventWithLatencyInfo(event, ui::LatencyInfo()));
}
@@ -190,7 +192,7 @@ class TouchEventQueueTest : public testing::Test,
point.radiusX = radius_x;
point.radiusY = radius_y;
touch_event_.touches[index].state = WebTouchPoint::StateMoved;
- touch_event_.causesScrollingIfUncanceled = true;
+ touch_event_.movedBeyondSlopRegion = true;
WebTouchEventTraits::ResetType(WebInputEvent::TouchMove,
touch_event_.timeStampSeconds,
&touch_event_);
@@ -203,7 +205,7 @@ class TouchEventQueueTest : public testing::Test,
WebTouchPoint& point = touch_event_.touches[index];
point.rotationAngle = rotation_angle;
touch_event_.touches[index].state = WebTouchPoint::StateMoved;
- touch_event_.causesScrollingIfUncanceled = true;
+ touch_event_.movedBeyondSlopRegion = true;
WebTouchEventTraits::ResetType(WebInputEvent::TouchMove,
touch_event_.timeStampSeconds,
&touch_event_);
@@ -216,7 +218,7 @@ class TouchEventQueueTest : public testing::Test,
WebTouchPoint& point = touch_event_.touches[index];
point.force = force;
touch_event_.touches[index].state = WebTouchPoint::StateMoved;
- touch_event_.causesScrollingIfUncanceled = true;
+ touch_event_.movedBeyondSlopRegion = true;
WebTouchEventTraits::ResetType(WebInputEvent::TouchMove,
touch_event_.timeStampSeconds,
&touch_event_);
@@ -354,7 +356,7 @@ TEST_F(TouchEventQueueTest, Basic) {
EXPECT_EQ(1U, GetAndResetSentEventCount());
EXPECT_EQ(1U, GetAndResetAckedEventCount());
EXPECT_EQ(WebInputEvent::TouchStart, acked_event().type);
- EXPECT_TRUE(acked_event().cancelable);
+ EXPECT_EQ(WebInputEvent::Blocking, acked_event().dispatchType);
// Receive an ACK for the second touch-event.
SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
@@ -362,7 +364,7 @@ TEST_F(TouchEventQueueTest, Basic) {
EXPECT_EQ(0U, GetAndResetSentEventCount());
EXPECT_EQ(1U, GetAndResetAckedEventCount());
EXPECT_EQ(WebInputEvent::TouchMove, acked_event().type);
- EXPECT_TRUE(acked_event().cancelable);
+ EXPECT_EQ(WebInputEvent::Blocking, acked_event().dispatchType);
}
// Tests that touch-events with multiple points are queued properly.
@@ -1070,7 +1072,7 @@ TEST_F(TouchEventQueueTest, TouchTimeoutBasic) {
SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_FALSE(IsTimeoutRunning());
EXPECT_EQ(WebInputEvent::TouchCancel, sent_event().type);
- EXPECT_FALSE(sent_event().cancelable);
+ EXPECT_NE(WebInputEvent::Blocking, sent_event().dispatchType);
EXPECT_EQ(0U, GetAndResetAckedEventCount());
EXPECT_EQ(1U, GetAndResetSentEventCount());
@@ -1092,7 +1094,7 @@ TEST_F(TouchEventQueueTest, TouchTimeoutBasic) {
// Subsequent events should be handled normally.
PressTouchPoint(0, 1);
EXPECT_EQ(WebInputEvent::TouchStart, sent_event().type);
- EXPECT_TRUE(sent_event().cancelable);
+ EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType);
EXPECT_EQ(1U, GetAndResetSentEventCount());
EXPECT_EQ(0U, GetAndResetAckedEventCount());
}
@@ -1608,7 +1610,7 @@ TEST_F(TouchEventQueueTest, AsyncTouch) {
MoveTouchPoint(0, 10, 5+i);
SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_FALSE(HasPendingAsyncTouchMove());
- EXPECT_TRUE(sent_event().cancelable);
+ EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType);
EXPECT_EQ(0U, queued_event_count());
EXPECT_EQ(1U, GetAndResetSentEventCount());
@@ -1668,9 +1670,9 @@ TEST_F(TouchEventQueueTest, AsyncTouchThrottledAfterScroll) {
EXPECT_FALSE(HasPendingAsyncTouchMove());
EXPECT_EQ(2U, all_sent_events().size());
EXPECT_EQ(WebInputEvent::TouchMove, all_sent_events()[0].type);
- EXPECT_FALSE(all_sent_events()[0].cancelable);
+ EXPECT_NE(WebInputEvent::Blocking, all_sent_events()[0].dispatchType);
EXPECT_EQ(WebInputEvent::TouchEnd, all_sent_events()[1].type);
- EXPECT_FALSE(all_sent_events()[1].cancelable);
+ EXPECT_NE(WebInputEvent::Blocking, all_sent_events()[1].dispatchType);
EXPECT_EQ(2U, GetAndResetSentEventCount());
EXPECT_EQ(0U, GetAndResetAckedEventCount());
EXPECT_EQ(1U, queued_event_count());
@@ -1730,7 +1732,7 @@ TEST_F(TouchEventQueueTest, AsyncTouchThrottledAfterScroll) {
MoveTouchPoint(0, 0, 15);
SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
EXPECT_FALSE(HasPendingAsyncTouchMove());
- EXPECT_FALSE(sent_event().cancelable);
+ EXPECT_NE(WebInputEvent::Blocking, sent_event().dispatchType);
EXPECT_EQ(0U, queued_event_count());
EXPECT_EQ(1U, GetAndResetSentEventCount());
EXPECT_EQ(1U, GetAndResetAckedEventCount());
@@ -1747,9 +1749,9 @@ TEST_F(TouchEventQueueTest, AsyncTouchThrottledAfterScroll) {
EXPECT_FALSE(HasPendingAsyncTouchMove());
EXPECT_EQ(2U, all_sent_events().size());
EXPECT_EQ(WebInputEvent::TouchMove, all_sent_events()[0].type);
- EXPECT_FALSE(all_sent_events()[0].cancelable);
+ EXPECT_NE(WebInputEvent::Blocking, all_sent_events()[0].dispatchType);
EXPECT_EQ(WebInputEvent::TouchStart, all_sent_events()[1].type);
- EXPECT_TRUE(all_sent_events()[1].cancelable);
+ EXPECT_EQ(WebInputEvent::Blocking, all_sent_events()[1].dispatchType);
EXPECT_EQ(2U, GetAndResetSentEventCount());
EXPECT_EQ(0U, GetAndResetAckedEventCount());
EXPECT_EQ(1U, queued_event_count());
@@ -1775,7 +1777,7 @@ TEST_F(TouchEventQueueTest, AsyncTouchThrottledAfterScroll) {
// The pending touchmove should be coalesced with the next (now synchronous)
// touchmove.
MoveTouchPoint(0, 0, 26);
- EXPECT_TRUE(sent_event().cancelable);
+ EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType);
EXPECT_FALSE(HasPendingAsyncTouchMove());
EXPECT_EQ(WebInputEvent::TouchMove, sent_event().type);
EXPECT_EQ(WebTouchPoint::StateMoved, sent_event().touches[0].state);
@@ -1791,14 +1793,14 @@ TEST_F(TouchEventQueueTest, AsyncTouchThrottledAfterScroll) {
ReleaseTouchPoint(0);
EXPECT_EQ(3U, queued_event_count());
SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_TRUE(sent_event().cancelable);
+ EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType);
EXPECT_EQ(WebInputEvent::TouchEnd, sent_event().type);
EXPECT_EQ(2U, queued_event_count());
EXPECT_EQ(1U, GetAndResetSentEventCount());
EXPECT_EQ(1U, GetAndResetAckedEventCount());
SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_TRUE(sent_event().cancelable);
+ EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType);
EXPECT_EQ(WebInputEvent::TouchEnd, sent_event().type);
EXPECT_EQ(1U, queued_event_count());
EXPECT_EQ(1U, GetAndResetSentEventCount());
@@ -1854,11 +1856,11 @@ TEST_F(TouchEventQueueTest, AsyncTouchFlushedByTouchEnd) {
EXPECT_FALSE(HasPendingAsyncTouchMove());
EXPECT_EQ(2U, all_sent_events().size());
EXPECT_EQ(WebInputEvent::TouchMove, all_sent_events()[0].type);
- EXPECT_FALSE(all_sent_events()[0].cancelable);
+ EXPECT_NE(WebInputEvent::Blocking, all_sent_events()[0].dispatchType);
EXPECT_EQ(0, all_sent_events()[0].touches[0].position.x);
EXPECT_EQ(0, all_sent_events()[0].touches[0].position.y);
EXPECT_EQ(WebInputEvent::TouchEnd, all_sent_events()[1].type);
- EXPECT_FALSE(all_sent_events()[1].cancelable);
+ EXPECT_NE(WebInputEvent::Blocking, all_sent_events()[1].dispatchType);
EXPECT_EQ(2U, GetAndResetSentEventCount());
EXPECT_EQ(0U, GetAndResetAckedEventCount());
}
@@ -1900,7 +1902,7 @@ TEST_F(TouchEventQueueTest, AsyncTouchWithAckTimeout) {
MoveTouchPoint(0, 5, 5);
EXPECT_FALSE(IsTimeoutRunning());
EXPECT_FALSE(HasPendingAsyncTouchMove());
- EXPECT_FALSE(sent_event().cancelable);
+ EXPECT_NE(WebInputEvent::Blocking, sent_event().dispatchType);
EXPECT_EQ(1U, GetAndResetAckedEventCount());
EXPECT_EQ(1U, GetAndResetSentEventCount());
@@ -1910,7 +1912,7 @@ TEST_F(TouchEventQueueTest, AsyncTouchWithAckTimeout) {
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
MoveTouchPoint(0, 20, 5);
EXPECT_TRUE(IsTimeoutRunning());
- EXPECT_TRUE(sent_event().cancelable);
+ EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType);
EXPECT_EQ(1U, GetAndResetSentEventCount());
// The timeout should fire, disabling touch forwarding until both acks are
@@ -1923,7 +1925,7 @@ TEST_F(TouchEventQueueTest, AsyncTouchWithAckTimeout) {
// Ack'ing the original event should trigger a cancel event.
SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_FALSE(sent_event().cancelable);
+ EXPECT_NE(WebInputEvent::Blocking, sent_event().dispatchType);
EXPECT_EQ(0U, GetAndResetAckedEventCount());
EXPECT_EQ(1U, GetAndResetSentEventCount());
@@ -1976,9 +1978,9 @@ TEST_F(TouchEventQueueTest, AsyncTouchWithTouchCancelAfterAck) {
EXPECT_EQ(1U, queued_event_count());
EXPECT_EQ(2U, all_sent_events().size());
EXPECT_EQ(WebInputEvent::TouchMove, all_sent_events()[0].type);
- EXPECT_FALSE(all_sent_events()[0].cancelable);
+ EXPECT_NE(WebInputEvent::Blocking, all_sent_events()[0].dispatchType);
EXPECT_EQ(WebInputEvent::TouchCancel, all_sent_events()[1].type);
- EXPECT_FALSE(all_sent_events()[1].cancelable);
+ EXPECT_NE(WebInputEvent::Blocking, all_sent_events()[1].dispatchType);
EXPECT_EQ(2U, GetAndResetSentEventCount());
// Sending the ack is because the async touchmove is not ready for
// dispatching send the ack immediately.
@@ -2064,7 +2066,7 @@ TEST_F(TouchEventQueueTest, SendNextThrottledAsyncTouchMoveAfterAck) {
// Dispatch the touch move event when sufficient time has passed.
MoveTouchPoint(0, 0, 40);
EXPECT_FALSE(HasPendingAsyncTouchMove());
- EXPECT_FALSE(sent_event().cancelable);
+ EXPECT_NE(WebInputEvent::Blocking, sent_event().dispatchType);
// When we dispatch an async touchmove, we do not put it back to the queue
// any more and we will ack to client right away.
EXPECT_EQ(0U, queued_event_count());
@@ -2124,7 +2126,7 @@ TEST_F(TouchEventQueueTest, SendNextAsyncTouchMoveAfterAckAndTimeExpire) {
AdvanceTouchTime(kMinSecondsBetweenThrottledTouchmoves + 0.1);
MoveTouchPoint(0, 0, 40);
EXPECT_FALSE(HasPendingAsyncTouchMove());
- EXPECT_FALSE(sent_event().cancelable);
+ EXPECT_NE(WebInputEvent::Blocking, sent_event().dispatchType);
// When we dispatch an async touchmove, we do not put it back to the queue
// any more and we will ack to client right away.
EXPECT_EQ(0U, queued_event_count());
@@ -2147,7 +2149,7 @@ TEST_F(TouchEventQueueTest, SendNextAsyncTouchMoveAfterAckAndTimeExpire) {
MoveTouchPoint(0, 0, 50);
EXPECT_FALSE(HasPendingAsyncTouchMove());
EXPECT_EQ(WebInputEvent::TouchMove, sent_event().type);
- EXPECT_FALSE(sent_event().cancelable);
+ EXPECT_NE(WebInputEvent::Blocking, sent_event().dispatchType);
EXPECT_EQ(0U, queued_event_count());
EXPECT_EQ(1U, GetAndResetSentEventCount());
EXPECT_EQ(1U, GetAndResetAckedEventCount());
@@ -2182,7 +2184,7 @@ TEST_F(TouchEventQueueTest, AsyncTouchFlushedByNonTouchMove) {
AdvanceTouchTime(kMinSecondsBetweenThrottledTouchmoves + 0.1);
MoveTouchPoint(0, 0, 40);
EXPECT_FALSE(HasPendingAsyncTouchMove());
- EXPECT_FALSE(sent_event().cancelable);
+ EXPECT_NE(WebInputEvent::Blocking, sent_event().dispatchType);
// When we dispatch an async touchmove, we do not put it back to the queue
// any more and we will ack to client right away.
EXPECT_EQ(0U, queued_event_count());
@@ -2208,13 +2210,13 @@ TEST_F(TouchEventQueueTest, AsyncTouchFlushedByNonTouchMove) {
EXPECT_FALSE(HasPendingAsyncTouchMove());
EXPECT_EQ(2U, all_sent_events().size());
EXPECT_EQ(WebInputEvent::TouchMove, all_sent_events()[0].type);
- EXPECT_FALSE(all_sent_events()[0].cancelable);
+ EXPECT_NE(WebInputEvent::Blocking, all_sent_events()[0].dispatchType);
EXPECT_EQ(10 + 10 * i, all_sent_events()[0].touches[0].position.x);
EXPECT_EQ(10 + 10 * i, all_sent_events()[0].touches[0].position.y);
EXPECT_EQ(static_cast<size_t>(i + 2),
uncancelable_touch_moves_pending_ack_count());
EXPECT_EQ(WebInputEvent::TouchStart, all_sent_events()[1].type);
- EXPECT_TRUE(all_sent_events()[1].cancelable);
+ EXPECT_EQ(WebInputEvent::Blocking, all_sent_events()[1].dispatchType);
EXPECT_EQ(2U, GetAndResetSentEventCount());
EXPECT_EQ(0U, GetAndResetAckedEventCount());
@@ -2260,7 +2262,7 @@ TEST_F(TouchEventQueueTest, AsyncTouchFlushedByNonTouchMove) {
EXPECT_FALSE(HasPendingAsyncTouchMove());
EXPECT_EQ(0U, queued_event_count());
EXPECT_EQ(WebInputEvent::TouchMove, sent_event().type);
- EXPECT_FALSE(sent_event().cancelable);
+ EXPECT_NE(WebInputEvent::Blocking, sent_event().dispatchType);
EXPECT_EQ(1U, GetAndResetSentEventCount());
EXPECT_EQ(0U, GetAndResetAckedEventCount());
}
@@ -2296,7 +2298,7 @@ TEST_F(TouchEventQueueTest, DoNotIncreaseIfClientConsumeAsyncTouchMove) {
AdvanceTouchTime(kMinSecondsBetweenThrottledTouchmoves + 0.1);
MoveTouchPoint(0, 0, 40);
EXPECT_FALSE(HasPendingAsyncTouchMove());
- EXPECT_FALSE(sent_event().cancelable);
+ EXPECT_NE(WebInputEvent::Blocking, sent_event().dispatchType);
// When we dispatch an async touchmove, we do not put it back to the queue
// any more and we will ack to client right away.
EXPECT_EQ(0U, queued_event_count());
@@ -2322,7 +2324,7 @@ TEST_F(TouchEventQueueTest, DoNotIncreaseIfClientConsumeAsyncTouchMove) {
MoveTouchPoint(0, 0, 50);
EXPECT_FALSE(HasPendingAsyncTouchMove());
EXPECT_EQ(WebInputEvent::TouchMove, sent_event().type);
- EXPECT_FALSE(sent_event().cancelable);
+ EXPECT_NE(WebInputEvent::Blocking, sent_event().dispatchType);
EXPECT_EQ(0U, queued_event_count());
EXPECT_EQ(1U, GetAndResetSentEventCount());
EXPECT_EQ(1U, GetAndResetAckedEventCount());
@@ -2347,7 +2349,7 @@ TEST_F(TouchEventQueueTest, TouchAbsorptionWithConsumedFirstMove) {
MoveTouchPoint(0, 60, 5);
SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_EQ(0U, queued_event_count());
- EXPECT_TRUE(sent_event().cancelable);
+ EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType);
EXPECT_EQ(1U, GetAndResetSentEventCount());
MoveTouchPoint(0, 20, 5);
@@ -2358,7 +2360,7 @@ TEST_F(TouchEventQueueTest, TouchAbsorptionWithConsumedFirstMove) {
SendGestureEventAck(WebInputEvent::GestureScrollUpdate,
INPUT_EVENT_ACK_STATE_CONSUMED);
EXPECT_EQ(0U, queued_event_count());
- EXPECT_TRUE(sent_event().cancelable);
+ EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType);
EXPECT_EQ(1U, GetAndResetSentEventCount());
// Touch move event is throttled.
@@ -2372,39 +2374,39 @@ TEST_F(TouchEventQueueTest, TouchStartCancelableDuringScroll) {
// active scroll sequence.
PressTouchPoint(0, 1);
SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_TRUE(sent_event().cancelable);
+ EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType);
ASSERT_EQ(1U, GetAndResetSentEventCount());
MoveTouchPoint(0, 20, 5);
- EXPECT_TRUE(sent_event().cancelable);
+ EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType);
SendGestureEvent(blink::WebInputEvent::GestureScrollBegin);
SendGestureEvent(blink::WebInputEvent::GestureScrollUpdate);
SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_TRUE(sent_event().cancelable);
+ EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType);
ASSERT_EQ(1U, GetAndResetSentEventCount());
// Even though scrolling has begun, touchstart events should be cancelable,
// allowing, for example, customized pinch processing.
PressTouchPoint(10, 11);
SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_TRUE(sent_event().cancelable);
+ EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType);
ASSERT_EQ(1U, GetAndResetSentEventCount());
// As the touch start was consumed, touchmoves should no longer be throttled.
MoveTouchPoint(1, 11, 11);
SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_TRUE(sent_event().cancelable);
+ EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType);
ASSERT_EQ(1U, GetAndResetSentEventCount());
// With throttling disabled, touchend and touchmove events should also be
// cancelable.
MoveTouchPoint(1, 12, 12);
SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_TRUE(sent_event().cancelable);
+ EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType);
ASSERT_EQ(1U, GetAndResetSentEventCount());
ReleaseTouchPoint(1);
SendTouchEventAck(INPUT_EVENT_ACK_STATE_CONSUMED);
- EXPECT_TRUE(sent_event().cancelable);
+ EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType);
ASSERT_EQ(1U, GetAndResetSentEventCount());
// If subsequent touchmoves aren't consumed, the generated scroll events
@@ -2412,17 +2414,17 @@ TEST_F(TouchEventQueueTest, TouchStartCancelableDuringScroll) {
MoveTouchPoint(0, 25, 5);
SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
SendGestureEvent(blink::WebInputEvent::GestureScrollUpdate);
- EXPECT_TRUE(sent_event().cancelable);
+ EXPECT_EQ(WebInputEvent::Blocking, sent_event().dispatchType);
ASSERT_EQ(1U, GetAndResetSentEventCount());
AdvanceTouchTime(kMinSecondsBetweenThrottledTouchmoves + 0.1);
MoveTouchPoint(0, 30, 5);
SendTouchEventAck(INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
- EXPECT_FALSE(sent_event().cancelable);
+ EXPECT_NE(WebInputEvent::Blocking, sent_event().dispatchType);
ASSERT_EQ(1U, GetAndResetSentEventCount());
// The touchend will be uncancelable during an active scroll sequence.
ReleaseTouchPoint(0);
- EXPECT_FALSE(sent_event().cancelable);
+ EXPECT_NE(WebInputEvent::Blocking, sent_event().dispatchType);
ASSERT_EQ(1U, GetAndResetSentEventCount());
}
diff --git a/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc b/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc
index 2c68ac71ac2..7ff1dd06701 100644
--- a/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_input_browsertest.cc
@@ -19,6 +19,7 @@
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
@@ -88,54 +89,6 @@ const char kTouchEventDataURL[] =
namespace content {
-class InputEventMessageFilter : public BrowserMessageFilter {
- public:
- InputEventMessageFilter()
- : BrowserMessageFilter(InputMsgStart),
- type_(WebInputEvent::Undefined),
- state_(INPUT_EVENT_ACK_STATE_UNKNOWN) {}
-
- void WaitForAck(WebInputEvent::Type type) {
- base::RunLoop run_loop;
- base::AutoReset<base::Closure> reset_quit(&quit_, run_loop.QuitClosure());
- base::AutoReset<WebInputEvent::Type> reset_type(&type_, type);
- run_loop.Run();
- }
-
- InputEventAckState last_ack_state() const { return state_; }
-
- protected:
- ~InputEventMessageFilter() override {}
-
- private:
- void ReceivedEventAck(WebInputEvent::Type type, InputEventAckState state) {
- if (type_ == type) {
- state_ = state;
- quit_.Run();
- }
- }
-
- // BrowserMessageFilter:
- bool OnMessageReceived(const IPC::Message& message) override {
- if (message.type() == InputHostMsg_HandleInputEvent_ACK::ID) {
- InputHostMsg_HandleInputEvent_ACK::Param params;
- InputHostMsg_HandleInputEvent_ACK::Read(&message, &params);
- WebInputEvent::Type type = base::get<0>(params).type;
- InputEventAckState ack = base::get<0>(params).state;
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&InputEventMessageFilter::ReceivedEventAck,
- this, type, ack));
- }
- return false;
- }
-
- base::Closure quit_;
- WebInputEvent::Type type_;
- InputEventAckState state_;
-
- DISALLOW_COPY_AND_ASSIGN(InputEventMessageFilter);
-};
-
class TouchInputBrowserTest : public ContentBrowserTest {
public:
TouchInputBrowserTest() {}
@@ -146,33 +99,27 @@ class TouchInputBrowserTest : public ContentBrowserTest {
shell()->web_contents()->GetRenderViewHost()->GetWidget());
}
- InputEventMessageFilter* filter() { return filter_.get(); }
+ scoped_refptr<InputMsgWatcher> AddFilter(blink::WebInputEvent::Type type) {
+ return new InputMsgWatcher(GetWidgetHost(), type);
+ }
protected:
- void LoadURLAndAddFilter() {
+ void LoadURL() {
const GURL data_url(kTouchEventDataURL);
NavigateToURL(shell(), data_url);
- WebContentsImpl* web_contents =
- static_cast<WebContentsImpl*>(shell()->web_contents());
- RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
- web_contents->GetRenderViewHost()->GetWidget());
+ RenderWidgetHostImpl* host = GetWidgetHost();
host->GetView()->SetSize(gfx::Size(400, 400));
// The page is loaded in the renderer, wait for a new frame to arrive.
while (!host->ScheduleComposite())
GiveItSomeTime();
-
- filter_ = new InputEventMessageFilter();
- host->GetProcess()->AddFilter(filter_.get());
}
void SetUpCommandLine(base::CommandLine* cmd) override {
cmd->AppendSwitchASCII(switches::kTouchEvents,
switches::kTouchEventsEnabled);
}
-
- scoped_refptr<InputEventMessageFilter> filter_;
};
#if defined(OS_MACOSX)
@@ -182,17 +129,16 @@ class TouchInputBrowserTest : public ContentBrowserTest {
#define MAYBE_TouchNoHandler TouchNoHandler
#endif
IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, MAYBE_TouchNoHandler) {
- LoadURLAndAddFilter();
+ LoadURL();
SyntheticWebTouchEvent touch;
// A press on |first| should be acked with NO_CONSUMER_EXISTS since there is
// no touch-handler on it.
touch.PressPoint(25, 25);
+ scoped_refptr<InputMsgWatcher> filter = AddFilter(WebInputEvent::TouchStart);
GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
- filter()->WaitForAck(WebInputEvent::TouchStart);
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
- filter()->last_ack_state());
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, filter->WaitForAck());
// If a touch-press is acked with NO_CONSUMER_EXISTS, then subsequent
// touch-points don't need to be dispatched until the touch point is released.
@@ -208,20 +154,21 @@ IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, MAYBE_TouchNoHandler) {
#define MAYBE_TouchHandlerNoConsume TouchHandlerNoConsume
#endif
IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, MAYBE_TouchHandlerNoConsume) {
- LoadURLAndAddFilter();
+ LoadURL();
SyntheticWebTouchEvent touch;
// Press on |second| should be acked with NOT_CONSUMED since there is a
// touch-handler on |second|, but it doesn't consume the event.
touch.PressPoint(125, 25);
+ scoped_refptr<InputMsgWatcher> filter = AddFilter(WebInputEvent::TouchStart);
GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
- filter()->WaitForAck(WebInputEvent::TouchStart);
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter()->last_ack_state());
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NOT_CONSUMED, filter->WaitForAck());
+ filter = AddFilter(WebInputEvent::TouchEnd);
touch.ReleasePoint(0);
GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
- filter()->WaitForAck(WebInputEvent::TouchEnd);
touch.ResetPoints();
+ filter->WaitForAck();
}
#if defined(OS_CHROMEOS)
@@ -231,19 +178,20 @@ IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, MAYBE_TouchHandlerNoConsume) {
#define MAYBE_TouchHandlerConsume TouchHandlerConsume
#endif
IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, MAYBE_TouchHandlerConsume) {
- LoadURLAndAddFilter();
+ LoadURL();
SyntheticWebTouchEvent touch;
// Press on |third| should be acked with CONSUMED since the touch-handler on
// |third| consimes the event.
touch.PressPoint(25, 125);
+ scoped_refptr<InputMsgWatcher> filter = AddFilter(WebInputEvent::TouchStart);
GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
- filter()->WaitForAck(WebInputEvent::TouchStart);
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, filter()->last_ack_state());
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, filter->WaitForAck());
touch.ReleasePoint(0);
+ filter = AddFilter(WebInputEvent::TouchEnd);
GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
- filter()->WaitForAck(WebInputEvent::TouchEnd);
+ filter->WaitForAck();
}
#if defined(OS_CHROMEOS)
@@ -256,21 +204,20 @@ IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, MAYBE_TouchHandlerConsume) {
#define MAYBE_MultiPointTouchPress MultiPointTouchPress
#endif
IN_PROC_BROWSER_TEST_F(TouchInputBrowserTest, MAYBE_MultiPointTouchPress) {
- LoadURLAndAddFilter();
+ LoadURL();
SyntheticWebTouchEvent touch;
// Press on |first|, which sould be acked with NO_CONSUMER_EXISTS. Then press
// on |third|. That point should be acked with CONSUMED.
touch.PressPoint(25, 25);
+ scoped_refptr<InputMsgWatcher> filter = AddFilter(WebInputEvent::TouchStart);
GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
- filter()->WaitForAck(WebInputEvent::TouchStart);
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
- filter()->last_ack_state());
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS, filter->WaitForAck());
touch.PressPoint(25, 125);
+ filter = AddFilter(WebInputEvent::TouchStart);
GetWidgetHost()->ForwardTouchEventWithLatencyInfo(touch, ui::LatencyInfo());
- filter()->WaitForAck(WebInputEvent::TouchStart);
- EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, filter()->last_ack_state());
+ EXPECT_EQ(INPUT_EVENT_ACK_STATE_CONSUMED, filter->WaitForAck());
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
index b59cc2bd010..348b5e6fea0 100644
--- a/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
+++ b/chromium/content/browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc
@@ -4,6 +4,7 @@
#include "content/browser/renderer_host/input/touch_selection_controller_client_aura.h"
+#include "base/command_line.h"
#include "base/json/json_reader.h"
#include "base/macros.h"
#include "base/run_loop.h"
@@ -17,6 +18,7 @@
#include "ui/aura/window_tree_host.h"
#include "ui/events/event_utils.h"
#include "ui/events/test/event_generator.h"
+#include "ui/gfx/switches.h"
#include "ui/touch_selection/touch_selection_controller_test_api.h"
namespace content {
@@ -153,6 +155,23 @@ class TouchSelectionControllerClientAuraTest : public ContentBrowserTest {
"empty_textfield()");
}
+ RenderWidgetHostViewAura* GetRenderWidgetHostViewAura() {
+ return static_cast<RenderWidgetHostViewAura*>(
+ shell()->web_contents()->GetRenderWidgetHostView());
+ }
+
+ TestTouchSelectionControllerClientAura* selection_controller_client() {
+ return selection_controller_client_;
+ }
+
+ void InitSelectionController() {
+ RenderWidgetHostViewAura* rwhva = GetRenderWidgetHostViewAura();
+ selection_controller_client_ =
+ new TestTouchSelectionControllerClientAura(rwhva);
+ rwhva->SetSelectionControllerClientForTest(
+ make_scoped_ptr(selection_controller_client_));
+ }
+
private:
void SetUpOnMainThread() override {
ContentBrowserTest::SetUpOnMainThread();
@@ -162,11 +181,15 @@ class TouchSelectionControllerClientAuraTest : public ContentBrowserTest {
void TearDownOnMainThread() override {
menu_runner_ = nullptr;
+ selection_controller_client_ = nullptr;
ContentBrowserTest::TearDownOnMainThread();
}
scoped_ptr<TestTouchSelectionMenuRunner> menu_runner_;
+ TestTouchSelectionControllerClientAura* selection_controller_client_ =
+ nullptr;
+
DISALLOW_COPY_AND_ASSIGN(TouchSelectionControllerClientAuraTest);
};
@@ -175,21 +198,15 @@ class TouchSelectionControllerClientAuraTest : public ContentBrowserTest {
IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest, BasicSelection) {
// Set the test page up.
ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/touch_selection.html"));
- WebContents* web_contents =
- static_cast<WebContentsImpl*>(shell()->web_contents());
- RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
- web_contents->GetRenderWidgetHostView());
- TestTouchSelectionControllerClientAura* selection_controller_client =
- new TestTouchSelectionControllerClientAura(rwhva);
- rwhva->SetSelectionControllerClientForTest(
- make_scoped_ptr(selection_controller_client));
+ InitSelectionController();
+ RenderWidgetHostViewAura* rwhva = GetRenderWidgetHostViewAura();
EXPECT_EQ(ui::TouchSelectionController::INACTIVE,
rwhva->selection_controller()->active_status());
EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
// Long-press on the text and wait for handles to appear.
- selection_controller_client->InitWaitForSelectionEvent(
+ selection_controller_client()->InitWaitForSelectionEvent(
ui::SELECTION_HANDLES_SHOWN);
gfx::PointF point;
@@ -199,7 +216,7 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest, BasicSelection) {
ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
rwhva->OnGestureEvent(&long_press);
- selection_controller_client->Wait();
+ selection_controller_client()->Wait();
// Check that selection is active and the quick menu is showing.
EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE,
@@ -214,36 +231,29 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest,
BasicInsertionFollowedByTapsOnHandle) {
// Set the test page up.
ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/touch_selection.html"));
- WebContents* web_contents =
- static_cast<WebContentsImpl*>(shell()->web_contents());
- RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
- web_contents->GetRenderWidgetHostView());
- TestTouchSelectionControllerClientAura* selection_controller_client =
- new TestTouchSelectionControllerClientAura(rwhva);
- rwhva->SetSelectionControllerClientForTest(
- make_scoped_ptr(selection_controller_client));
+ InitSelectionController();
+ RenderWidgetHostViewAura* rwhva = GetRenderWidgetHostViewAura();
EXPECT_EQ(ui::TouchSelectionController::INACTIVE,
rwhva->selection_controller()->active_status());
EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
ui::test::EventGeneratorDelegate* generator_delegate =
ui::test::EventGenerator::default_delegate;
- ui::test::EventGenerator generator(
- web_contents->GetContentNativeView()->GetRootWindow());
+ gfx::NativeView native_view = rwhva->GetNativeView();
+ ui::test::EventGenerator generator(native_view->GetRootWindow());
// Tap inside the textfield and wait for the insertion handle to appear.
- selection_controller_client->InitWaitForSelectionEvent(
+ selection_controller_client()->InitWaitForSelectionEvent(
ui::INSERTION_HANDLE_SHOWN);
gfx::PointF point_f;
ASSERT_TRUE(GetPointInsideTextfield(&point_f));
gfx::Point point = gfx::ToRoundedPoint(point_f);
- generator_delegate->ConvertPointFromTarget(
- web_contents->GetContentNativeView(), &point);
+ generator_delegate->ConvertPointFromTarget(native_view, &point);
generator.GestureTapAt(point);
- selection_controller_client->Wait();
+ selection_controller_client()->Wait();
// Check that insertion is active, but the quick menu is not showing.
EXPECT_EQ(ui::TouchSelectionController::INSERTION_ACTIVE,
@@ -253,8 +263,7 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest,
// Tap on the insertion handle; the quick menu should appear.
gfx::Point handle_center = gfx::ToRoundedPoint(
rwhva->selection_controller()->GetStartHandleRect().CenterPoint());
- generator_delegate->ConvertPointFromTarget(
- web_contents->GetContentNativeView(), &handle_center);
+ generator_delegate->ConvertPointFromTarget(native_view, &handle_center);
generator.GestureTapAt(handle_center);
EXPECT_TRUE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
@@ -269,14 +278,9 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest,
EmptyTextfieldInsertionOnTap) {
// Set the test page up.
ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/touch_selection.html"));
- WebContents* web_contents =
- static_cast<WebContentsImpl*>(shell()->web_contents());
- RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
- web_contents->GetRenderWidgetHostView());
- TestTouchSelectionControllerClientAura* selection_controller_client =
- new TestTouchSelectionControllerClientAura(rwhva);
- rwhva->SetSelectionControllerClientForTest(
- make_scoped_ptr(selection_controller_client));
+ InitSelectionController();
+
+ RenderWidgetHostViewAura* rwhva = GetRenderWidgetHostViewAura();
// Clear textfield contents.
ASSERT_TRUE(EmptyTextfield());
@@ -286,7 +290,7 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest,
EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
// Tap inside the textfield and wait for the insertion cursor.
- selection_controller_client->InitWaitForSelectionEvent(
+ selection_controller_client()->InitWaitForSelectionEvent(
ui::SELECTION_ESTABLISHED);
gfx::PointF point;
@@ -297,7 +301,7 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest,
tap_details);
rwhva->OnGestureEvent(&tap);
- selection_controller_client->Wait();
+ selection_controller_client()->Wait();
// Check that insertion is not active and the quick menu is not showing.
EXPECT_EQ(ui::TouchSelectionController::INACTIVE,
@@ -310,21 +314,15 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest,
QuickMenuHiddenOnTouch) {
// Set the test page up.
ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/touch_selection.html"));
- WebContents* web_contents =
- static_cast<WebContentsImpl*>(shell()->web_contents());
- RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
- web_contents->GetRenderWidgetHostView());
- TestTouchSelectionControllerClientAura* selection_controller_client =
- new TestTouchSelectionControllerClientAura(rwhva);
- rwhva->SetSelectionControllerClientForTest(
- make_scoped_ptr(selection_controller_client));
+ InitSelectionController();
+ RenderWidgetHostViewAura* rwhva = GetRenderWidgetHostViewAura();
EXPECT_EQ(ui::TouchSelectionController::INACTIVE,
rwhva->selection_controller()->active_status());
EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
// Long-press on the text and wait for selection handles to appear.
- selection_controller_client->InitWaitForSelectionEvent(
+ selection_controller_client()->InitWaitForSelectionEvent(
ui::SELECTION_HANDLES_SHOWN);
gfx::PointF point;
@@ -334,15 +332,14 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest,
ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
rwhva->OnGestureEvent(&long_press);
- selection_controller_client->Wait();
+ selection_controller_client()->Wait();
EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE,
rwhva->selection_controller()->active_status());
EXPECT_TRUE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
- ui::test::EventGenerator generator(
- web_contents->GetContentNativeView()->GetRootWindow(),
- web_contents->GetContentNativeView());
+ ui::test::EventGenerator generator(rwhva->GetNativeView()->GetRootWindow(),
+ rwhva->GetNativeView());
// Put the first finger down: the quick menu should get hidden.
generator.PressTouchId(0);
@@ -373,14 +370,9 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest,
IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest, HiddenOnScroll) {
// Set the test page up.
ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/touch_selection.html"));
- WebContents* web_contents =
- static_cast<WebContentsImpl*>(shell()->web_contents());
- RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
- web_contents->GetRenderWidgetHostView());
- TestTouchSelectionControllerClientAura* selection_controller_client =
- new TestTouchSelectionControllerClientAura(rwhva);
- rwhva->SetSelectionControllerClientForTest(
- make_scoped_ptr(selection_controller_client));
+ InitSelectionController();
+
+ RenderWidgetHostViewAura* rwhva = GetRenderWidgetHostViewAura();
ui::TouchSelectionControllerTestApi selection_controller_test_api(
rwhva->selection_controller());
@@ -389,7 +381,7 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest, HiddenOnScroll) {
EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
// Long-press on the text and wait for selection handles to appear.
- selection_controller_client->InitWaitForSelectionEvent(
+ selection_controller_client()->InitWaitForSelectionEvent(
ui::SELECTION_HANDLES_SHOWN);
gfx::PointF point;
@@ -399,7 +391,7 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest, HiddenOnScroll) {
ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
rwhva->OnGestureEvent(&long_press);
- selection_controller_client->Wait();
+ selection_controller_client()->Wait();
EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE,
rwhva->selection_controller()->active_status());
@@ -452,21 +444,15 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest,
HiddenAfterOverscroll) {
// Set the page up.
ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/touch_selection.html"));
- WebContents* web_contents =
- static_cast<WebContentsImpl*>(shell()->web_contents());
- RenderWidgetHostViewAura* rwhva = static_cast<RenderWidgetHostViewAura*>(
- web_contents->GetRenderWidgetHostView());
- TestTouchSelectionControllerClientAura* selection_controller_client =
- new TestTouchSelectionControllerClientAura(rwhva);
- rwhva->SetSelectionControllerClientForTest(
- make_scoped_ptr(selection_controller_client));
+ InitSelectionController();
+ RenderWidgetHostViewAura* rwhva = GetRenderWidgetHostViewAura();
EXPECT_EQ(ui::TouchSelectionController::INACTIVE,
rwhva->selection_controller()->active_status());
EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
// Long-press on the text and wait for touch handles to appear.
- selection_controller_client->InitWaitForSelectionEvent(
+ selection_controller_client()->InitWaitForSelectionEvent(
ui::SELECTION_HANDLES_SHOWN);
gfx::PointF point;
@@ -476,7 +462,7 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest,
ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
rwhva->OnGestureEvent(&long_press);
- selection_controller_client->Wait();
+ selection_controller_client()->Wait();
EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE,
rwhva->selection_controller()->active_status());
@@ -484,7 +470,7 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest,
// Scroll such that an overscroll is initiated and wait for it to complete:
// touch selection should not be active at the end.
- selection_controller_client->InitWaitForSelectionEvent(
+ selection_controller_client()->InitWaitForSelectionEvent(
ui::SELECTION_HANDLES_CLEARED);
ui::GestureEvent scroll_begin(
@@ -502,11 +488,182 @@ IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraTest,
ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END));
rwhva->OnGestureEvent(&scroll_end);
- selection_controller_client->Wait();
+ selection_controller_client()->Wait();
EXPECT_EQ(ui::TouchSelectionController::INACTIVE,
rwhva->selection_controller()->active_status());
EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
}
+class TouchSelectionControllerClientAuraScaleFactorTest
+ : public TouchSelectionControllerClientAuraTest {
+ public:
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ command_line->AppendSwitchASCII(switches::kForceDeviceScaleFactor, "2");
+ }
+};
+
+#if defined(OS_WIN)
+// High DPI tests are disabled on Windows due to crbug.com/545547.
+#define MAYBE_SelectionHandleCoordinates DISABLED_SelectionHandleCoordinates
+#define MAYBE_InsertionHandleCoordinates DISABLED_InsertionHandleCoordinates
+#else
+#define MAYBE_SelectionHandleCoordinates SelectionHandleCoordinates
+#define MAYBE_InsertionHandleCoordinates InsertionHandleCoordinates
+#endif
+
+// Tests that selection handles are properly positioned at 2x DSF.
+IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraScaleFactorTest,
+ MAYBE_SelectionHandleCoordinates) {
+ // Set the test page up.
+ ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/touch_selection.html"));
+ InitSelectionController();
+
+ RenderWidgetHostViewAura* rwhva = GetRenderWidgetHostViewAura();
+
+ EXPECT_EQ(ui::TouchSelectionController::INACTIVE,
+ rwhva->selection_controller()->active_status());
+ EXPECT_FALSE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
+ EXPECT_EQ(2.f, rwhva->current_device_scale_factor());
+
+ // Long-press on the text and wait for handles to appear.
+ selection_controller_client()->InitWaitForSelectionEvent(
+ ui::SELECTION_HANDLES_SHOWN);
+ gfx::PointF point;
+ ASSERT_TRUE(GetPointInsideText(&point));
+ ui::GestureEvent long_press(
+ point.x(), point.y(), 0, ui::EventTimeForNow(),
+ ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
+ rwhva->OnGestureEvent(&long_press);
+ selection_controller_client()->Wait();
+
+ // Check that selection is active and the quick menu is showing.
+ EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE,
+ rwhva->selection_controller()->active_status());
+ EXPECT_TRUE(ui::TouchSelectionMenuRunner::GetInstance()->IsRunning());
+ const ui::TouchSelectionController* controller =
+ GetRenderWidgetHostViewAura()->selection_controller();
+
+ gfx::PointF start_top = controller->start().edge_top();
+
+ // The selection start should be uppper left, and selection end should be
+ // upper right.
+ EXPECT_LT(controller->start().edge_top().x(), point.x());
+ EXPECT_LT(controller->start().edge_bottom().x(), point.x());
+
+ EXPECT_LT(point.x(), controller->end().edge_top().x());
+ EXPECT_LT(point.x(), controller->end().edge_bottom().x());
+
+ // Handles are created below the selection. The top position should roughly
+ // be within the handle size from the touch position.
+ float handle_size = controller->start().edge_bottom().y() -
+ controller->start().edge_top().y();
+ float handle_max_bottom = point.y() + handle_size;
+ EXPECT_GT(handle_max_bottom, controller->start().edge_top().y());
+ EXPECT_GT(handle_max_bottom, controller->end().edge_top().y());
+
+ gfx::Point handle_point = gfx::ToRoundedPoint(
+ rwhva->selection_controller()->GetStartHandleRect().CenterPoint());
+
+ // Move the selection handle. Touch the handle first.
+ selection_controller_client()->InitWaitForSelectionEvent(
+ ui::SELECTION_HANDLE_DRAG_STARTED);
+ ui::TouchEvent touch_down(ui::ET_TOUCH_PRESSED, handle_point, 0,
+ ui::EventTimeForNow());
+ rwhva->OnTouchEvent(&touch_down);
+ selection_controller_client()->Wait();
+
+ // Move it.
+ selection_controller_client()->InitWaitForSelectionEvent(
+ ui::SELECTION_HANDLES_MOVED);
+ handle_point.Offset(10, 0);
+ ui::TouchEvent touch_move(ui::ET_TOUCH_MOVED, handle_point, 0,
+ ui::EventTimeForNow());
+ rwhva->OnTouchEvent(&touch_move);
+ selection_controller_client()->Wait();
+
+ // Then release.
+ selection_controller_client()->InitWaitForSelectionEvent(
+ ui::SELECTION_HANDLE_DRAG_STOPPED);
+ ui::TouchEvent touch_up(ui::ET_TOUCH_RELEASED, handle_point, 0,
+ ui::EventTimeForNow());
+ rwhva->OnTouchEvent(&touch_up);
+ selection_controller_client()->Wait();
+
+ // The handle should have moved to right.
+ EXPECT_EQ(start_top.y(), controller->start().edge_top().y());
+ EXPECT_LT(start_top.x(), controller->start().edge_top().x());
+
+ EXPECT_EQ(ui::TouchSelectionController::SELECTION_ACTIVE,
+ rwhva->selection_controller()->active_status());
+}
+
+// Tests that insertion handles are properly positioned at 2x DSF.
+IN_PROC_BROWSER_TEST_F(TouchSelectionControllerClientAuraScaleFactorTest,
+ MAYBE_InsertionHandleCoordinates) {
+ // Set the test page up.
+ ASSERT_NO_FATAL_FAILURE(StartTestWithPage("/touch_selection.html"));
+ InitSelectionController();
+
+ RenderWidgetHostViewAura* rwhva = GetRenderWidgetHostViewAura();
+
+ // Tap inside the textfield and wait for the insertion cursor.
+ selection_controller_client()->InitWaitForSelectionEvent(
+ ui::INSERTION_HANDLE_SHOWN);
+
+ gfx::PointF point;
+ ASSERT_TRUE(GetPointInsideTextfield(&point));
+ ui::GestureEventDetails tap_details(ui::ET_GESTURE_TAP);
+ tap_details.set_tap_count(1);
+ ui::GestureEvent tap(point.x(), point.y(), 0, ui::EventTimeForNow(),
+ tap_details);
+ rwhva->OnGestureEvent(&tap);
+
+ selection_controller_client()->Wait();
+
+ EXPECT_EQ(ui::TouchSelectionController::INSERTION_ACTIVE,
+ rwhva->selection_controller()->active_status());
+
+ gfx::RectF initial_handle_rect =
+ rwhva->selection_controller()->GetStartHandleRect();
+
+ // Move the insertion handle. Touch the handle first.
+ gfx::Point handle_point =
+ gfx::ToRoundedPoint(initial_handle_rect.CenterPoint());
+
+ selection_controller_client()->InitWaitForSelectionEvent(
+ ui::INSERTION_HANDLE_DRAG_STARTED);
+ ui::TouchEvent touch_down(ui::ET_TOUCH_PRESSED, handle_point, 0,
+ ui::EventTimeForNow());
+ rwhva->OnTouchEvent(&touch_down);
+ selection_controller_client()->Wait();
+
+ // Move it.
+ selection_controller_client()->InitWaitForSelectionEvent(
+ ui::INSERTION_HANDLE_MOVED);
+ handle_point.Offset(10, 0);
+ ui::TouchEvent touch_move(ui::ET_TOUCH_MOVED, handle_point, 0,
+ ui::EventTimeForNow());
+ rwhva->OnTouchEvent(&touch_move);
+ selection_controller_client()->Wait();
+
+ // Then release.
+ selection_controller_client()->InitWaitForSelectionEvent(
+ ui::INSERTION_HANDLE_DRAG_STOPPED);
+ ui::TouchEvent touch_up(ui::ET_TOUCH_RELEASED, handle_point, 0,
+ ui::EventTimeForNow());
+ rwhva->OnTouchEvent(&touch_up);
+ selection_controller_client()->Wait();
+
+ gfx::RectF moved_handle_rect =
+ rwhva->selection_controller()->GetStartHandleRect();
+
+ // The handle should have moved to right.
+ EXPECT_EQ(initial_handle_rect.y(), moved_handle_rect.y());
+ EXPECT_LT(initial_handle_rect.x(), moved_handle_rect.x());
+
+ EXPECT_EQ(ui::TouchSelectionController::INSERTION_ACTIVE,
+ rwhva->selection_controller()->active_status());
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc b/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc
index 791422d38de..a5ffc019ad9 100644
--- a/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc
+++ b/chromium/content/browser/renderer_host/input/touchscreen_tap_suppression_controller.cc
@@ -45,7 +45,7 @@ bool TouchscreenTapSuppressionController::FilterTapEvent(
return true;
case WebInputEvent::GestureTapUnconfirmed:
- return stashed_tap_down_;
+ return !!stashed_tap_down_;
case WebInputEvent::GestureTapCancel:
case WebInputEvent::GestureTap:
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 3fb06bb9082..c0ffc1b0683 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
@@ -4,8 +4,11 @@
#include "content/browser/renderer_host/input/web_input_event_builders_android.h"
+#include <android/input.h>
+
#include "base/logging.h"
#include "content/browser/renderer_host/input/web_input_event_util.h"
+#include "ui/events/android/key_event_utils.h"
#include "ui/events/android/motion_event_android.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
@@ -18,6 +21,7 @@ using blink::WebKeyboardEvent;
using blink::WebGestureEvent;
using blink::WebMouseEvent;
using blink::WebMouseWheelEvent;
+using blink::WebPointerProperties;
using blink::WebTouchEvent;
using blink::WebTouchPoint;
@@ -25,7 +29,41 @@ namespace content {
namespace {
-ui::DomKey GetDomKeyFromEvent(int keycode, int unicode_character) {
+int WebInputEventToAndroidModifier(int web_modifier) {
+ int android_modifier = 0;
+ // Currently only Shift, CapsLock are used, add other modifiers if required.
+ if (web_modifier & WebInputEvent::ShiftKey)
+ android_modifier |= AMETA_SHIFT_ON;
+ if (web_modifier & WebInputEvent::CapsLockOn)
+ android_modifier |= AMETA_CAPS_LOCK_ON;
+ return android_modifier;
+}
+
+ui::DomKey GetDomKeyFromEvent(
+ JNIEnv* env,
+ const base::android::JavaRef<jobject>& android_key_event,
+ int keycode,
+ int modifiers,
+ int unicode_character) {
+ // Synthetic key event, not enough information to get DomKey.
+ if (android_key_event.is_null() && !unicode_character)
+ return ui::DomKey::UNIDENTIFIED;
+
+ if (!unicode_character && env) {
+ // According to spec |kAllowedModifiers| should be Shift and AltGr, however
+ // Android doesn't have AltGr key and ImeAdapter::getModifiers won't pass it
+ // either.
+ // According to discussion we want to honor CapsLock and possibly NumLock as
+ // well. https://github.com/w3c/uievents/issues/70
+ const int kAllowedModifiers =
+ WebInputEvent::ShiftKey | WebInputEvent::CapsLockOn;
+ int fallback_modifiers =
+ WebInputEventToAndroidModifier(modifiers & kAllowedModifiers);
+
+ unicode_character = ui::events::android::GetKeyEventUnicodeChar(
+ env, android_key_event, fallback_modifiers);
+ }
+
ui::DomKey key = ui::GetDomKeyFromAndroidEvent(keycode, unicode_character);
if (key != ui::DomKey::NONE)
return key;
@@ -34,13 +72,16 @@ ui::DomKey GetDomKeyFromEvent(int keycode, int unicode_character) {
} // namespace
-WebKeyboardEvent WebKeyboardEventBuilder::Build(WebInputEvent::Type type,
- int modifiers,
- double time_sec,
- int keycode,
- int scancode,
- int unicode_character,
- bool is_system_key) {
+WebKeyboardEvent WebKeyboardEventBuilder::Build(
+ JNIEnv* env,
+ const base::android::JavaRef<jobject>& android_key_event,
+ WebInputEvent::Type type,
+ int modifiers,
+ double time_sec,
+ int keycode,
+ int scancode,
+ int unicode_character,
+ bool is_system_key) {
DCHECK(WebInputEvent::isKeyboardEventType(type));
WebKeyboardEvent result;
@@ -55,7 +96,8 @@ WebKeyboardEvent WebKeyboardEventBuilder::Build(WebInputEvent::Type type,
result.modifiers |= DomCodeToWebInputEventModifiers(dom_code);
result.nativeKeyCode = keycode;
result.domCode = static_cast<int>(dom_code);
- result.domKey = GetDomKeyFromEvent(keycode, unicode_character);
+ result.domKey = GetDomKeyFromEvent(env, android_key_event, keycode, modifiers,
+ unicode_character);
result.unmodifiedText[0] = unicode_character;
if (result.windowsKeyCode == ui::VKEY_RETURN) {
// This is the same behavior as GTK:
@@ -70,17 +112,21 @@ WebKeyboardEvent WebKeyboardEventBuilder::Build(WebInputEvent::Type type,
return result;
}
-WebMouseEvent WebMouseEventBuilder::Build(blink::WebInputEvent::Type type,
- WebMouseEvent::Button button,
- double time_sec,
- int window_x,
- int window_y,
- int modifiers,
- int click_count) {
+WebMouseEvent WebMouseEventBuilder::Build(
+ WebInputEvent::Type type,
+ WebMouseEvent::Button button,
+ double time_sec,
+ int window_x,
+ int window_y,
+ int modifiers,
+ int click_count,
+ WebPointerProperties::PointerType pointer_type) {
+
DCHECK(WebInputEvent::isMouseEventType(type));
WebMouseEvent result;
result.type = type;
+ result.pointerType = pointer_type;
result.x = window_x;
result.y = window_y;
result.windowX = window_x;
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_android.h b/chromium/content/browser/renderer_host/input/web_input_event_builders_android.h
index 5ade65a3cbf..b6bcf44c7e1 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_android.h
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_android.h
@@ -7,6 +7,8 @@
#include <jni.h>
+#include "base/android/scoped_java_ref.h"
+#include "content/common/content_export.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
namespace ui {
@@ -17,13 +19,15 @@ namespace content {
class WebMouseEventBuilder {
public:
- static blink::WebMouseEvent Build(blink::WebInputEvent::Type type,
- blink::WebMouseEvent::Button button,
- double time_sec,
- int window_x,
- int window_y,
- int modifiers,
- int click_count);
+ static blink::WebMouseEvent Build(
+ blink::WebInputEvent::Type type,
+ blink::WebMouseEvent::Button button,
+ double time_sec,
+ int window_x,
+ int window_y,
+ int modifiers,
+ int click_count,
+ blink::WebPointerProperties::PointerType pointer_type);
};
class WebMouseWheelEventBuilder {
@@ -36,15 +40,18 @@ class WebMouseWheelEventBuilder {
int window_y);
};
-class WebKeyboardEventBuilder {
+class CONTENT_EXPORT WebKeyboardEventBuilder {
public:
- static blink::WebKeyboardEvent Build(blink::WebInputEvent::Type type,
- int modifiers,
- double time_sec,
- int keycode,
- int scancode,
- int unicode_character,
- bool is_system_key);
+ static blink::WebKeyboardEvent Build(
+ JNIEnv* env,
+ const base::android::JavaRef<jobject>& android_key_event,
+ blink::WebInputEvent::Type type,
+ int modifiers,
+ double time_sec,
+ int keycode,
+ int scancode,
+ int unicode_character,
+ bool is_system_key);
};
class WebGestureEventBuilder {
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_android_unittest.cc b/chromium/content/browser/renderer_host/input/web_input_event_builders_android_unittest.cc
new file mode 100644
index 00000000000..3e047d850ef
--- /dev/null
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_android_unittest.cc
@@ -0,0 +1,169 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/input/web_input_event_builders_android.h"
+
+#include <android/input.h>
+#include <android/keycodes.h>
+
+#include "base/android/jni_android.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "ui/events/android/key_event_utils.h"
+#include "ui/events/gesture_detection/motion_event.h"
+#include "ui/events/keycodes/dom/dom_code.h"
+#include "ui/events/keycodes/dom/dom_key.h"
+#include "ui/events/keycodes/dom/keycode_converter.h"
+#include "ui/events/keycodes/keyboard_codes_posix.h"
+
+using base::android::AttachCurrentThread;
+using base::android::ScopedJavaLocalRef;
+using blink::WebKeyboardEvent;
+
+namespace {
+
+const int kCombiningAccent = 0x80000000;
+const int kCombiningAccentMask = 0x7fffffff;
+const int kCompositionKeyCode = 229;
+
+WebKeyboardEvent CreateFakeWebKeyboardEvent(JNIEnv* env,
+ int key_code,
+ int web_modifier,
+ int unicode_character) {
+ ScopedJavaLocalRef<jobject> keydown_event =
+ ui::events::android::CreateKeyEvent(env, ui::MotionEvent::ACTION_DOWN,
+ key_code);
+
+ WebKeyboardEvent web_event = content::WebKeyboardEventBuilder::Build(
+ env, keydown_event, WebKeyboardEvent::KeyDown, web_modifier, 0, key_code,
+ 0, unicode_character, false);
+ return web_event;
+}
+
+} // anonymous namespace
+
+class WebInputEventBuilderAndroidTest : public testing::Test {};
+
+// This test case is based on VirtualKeyboard layout.
+// https://github.com/android/platform_frameworks_base/blob/master/data/keyboards/Virtual.kcm
+TEST(WebInputEventBuilderAndroidTest, DomKeyCtrlShift) {
+ JNIEnv* env = AttachCurrentThread();
+
+ struct DomKeyTestCase {
+ int key_code;
+ int character;
+ int shift_character;
+ } table[] = {
+ {AKEYCODE_0, '0', ')'}, {AKEYCODE_1, '1', '!'}, {AKEYCODE_2, '2', '@'},
+ {AKEYCODE_3, '3', '#'}, {AKEYCODE_4, '4', '$'}, {AKEYCODE_5, '5', '%'},
+ {AKEYCODE_6, '6', '^'}, {AKEYCODE_7, '7', '&'}, {AKEYCODE_8, '8', '*'},
+ {AKEYCODE_9, '9', '('}, {AKEYCODE_A, 'a', 'A'}, {AKEYCODE_B, 'b', 'B'},
+ {AKEYCODE_C, 'c', 'C'}, {AKEYCODE_D, 'd', 'D'}, {AKEYCODE_E, 'e', 'E'},
+ {AKEYCODE_F, 'f', 'F'}, {AKEYCODE_G, 'g', 'G'}, {AKEYCODE_H, 'h', 'H'},
+ {AKEYCODE_I, 'i', 'I'}, {AKEYCODE_J, 'j', 'J'}, {AKEYCODE_K, 'k', 'K'},
+ {AKEYCODE_L, 'l', 'L'}, {AKEYCODE_M, 'm', 'M'}, {AKEYCODE_N, 'n', 'N'},
+ {AKEYCODE_O, 'o', 'O'}, {AKEYCODE_P, 'p', 'P'}, {AKEYCODE_Q, 'q', 'Q'},
+ {AKEYCODE_R, 'r', 'R'}, {AKEYCODE_S, 's', 'S'}, {AKEYCODE_T, 't', 'T'},
+ {AKEYCODE_U, 'u', 'U'}, {AKEYCODE_V, 'v', 'V'}, {AKEYCODE_W, 'w', 'W'},
+ {AKEYCODE_X, 'x', 'X'}, {AKEYCODE_Y, 'y', 'Y'}, {AKEYCODE_Z, 'z', 'Z'}};
+
+ for (const DomKeyTestCase& entry : table) {
+ // Tests DomKey without modifier.
+ WebKeyboardEvent web_event =
+ CreateFakeWebKeyboardEvent(env, entry.key_code, 0, entry.character);
+ EXPECT_EQ(ui::DomKey::FromCharacter(entry.character), web_event.domKey)
+ << ui::KeycodeConverter::DomKeyToKeyString(web_event.domKey);
+
+ // Tests DomKey with Ctrl.
+ web_event = CreateFakeWebKeyboardEvent(env, entry.key_code,
+ WebKeyboardEvent::ControlKey, 0);
+ EXPECT_EQ(ui::DomKey::FromCharacter(entry.character), web_event.domKey)
+ << ui::KeycodeConverter::DomKeyToKeyString(web_event.domKey);
+
+ // Tests DomKey with Ctrl and Shift.
+ web_event = CreateFakeWebKeyboardEvent(
+ env, entry.key_code,
+ WebKeyboardEvent::ControlKey | WebKeyboardEvent::ShiftKey, 0);
+ EXPECT_EQ(ui::DomKey::FromCharacter(entry.shift_character),
+ web_event.domKey)
+ << ui::KeycodeConverter::DomKeyToKeyString(web_event.domKey);
+ }
+}
+
+// This test case is based on VirtualKeyboard layout.
+// https://github.com/android/platform_frameworks_base/blob/master/data/keyboards/Virtual.kcm
+TEST(WebInputEventBuilderAndroidTest, DomKeyCtrlAlt) {
+ JNIEnv* env = AttachCurrentThread();
+
+ struct DomKeyTestCase {
+ int key_code;
+ int character;
+ int alt_character;
+ } table[] = {{AKEYCODE_0, '0', 0}, {AKEYCODE_1, '1', 0},
+ {AKEYCODE_2, '2', 0}, {AKEYCODE_3, '3', 0},
+ {AKEYCODE_4, '4', 0}, {AKEYCODE_5, '5', 0},
+ {AKEYCODE_6, '6', 0}, {AKEYCODE_7, '7', 0},
+ {AKEYCODE_8, '8', 0}, {AKEYCODE_9, '9', 0},
+ {AKEYCODE_A, 'a', 0}, {AKEYCODE_B, 'b', 0},
+ {AKEYCODE_C, 'c', u'\u00e7'}, {AKEYCODE_D, 'd', 0},
+ {AKEYCODE_E, 'e', u'\u0301'}, {AKEYCODE_F, 'f', 0},
+ {AKEYCODE_G, 'g', 0}, {AKEYCODE_H, 'h', 0},
+ {AKEYCODE_I, 'i', u'\u0302'}, {AKEYCODE_J, 'j', 0},
+ {AKEYCODE_K, 'k', 0}, {AKEYCODE_L, 'l', 0},
+ {AKEYCODE_M, 'm', 0}, {AKEYCODE_N, 'n', u'\u0303'},
+ {AKEYCODE_O, 'o', 0}, {AKEYCODE_P, 'p', 0},
+ {AKEYCODE_Q, 'q', 0}, {AKEYCODE_R, 'r', 0},
+ {AKEYCODE_S, 's', u'\u00df'}, {AKEYCODE_T, 't', 0},
+ {AKEYCODE_U, 'u', u'\u0308'}, {AKEYCODE_V, 'v', 0},
+ {AKEYCODE_W, 'w', 0}, {AKEYCODE_X, 'x', 0},
+ {AKEYCODE_Y, 'y', 0}, {AKEYCODE_Z, 'z', 0}};
+
+ for (const DomKeyTestCase& entry : table) {
+ // Tests DomKey with Alt.
+ WebKeyboardEvent web_event = CreateFakeWebKeyboardEvent(
+ env, entry.key_code, WebKeyboardEvent::AltKey, entry.alt_character);
+ ui::DomKey expected_alt_dom_key;
+ if (entry.alt_character == 0)
+ expected_alt_dom_key = ui::DomKey::FromCharacter(entry.character);
+ else if (entry.alt_character & kCombiningAccent)
+ expected_alt_dom_key = ui::DomKey::DeadKeyFromCombiningCharacter(
+ entry.alt_character & kCombiningAccentMask);
+ else
+ expected_alt_dom_key = ui::DomKey::FromCharacter(entry.alt_character);
+ EXPECT_EQ(expected_alt_dom_key, web_event.domKey)
+ << ui::KeycodeConverter::DomKeyToKeyString(web_event.domKey);
+
+ // Tests DomKey with Ctrl and Alt.
+ web_event = CreateFakeWebKeyboardEvent(
+ env, entry.key_code,
+ WebKeyboardEvent::ControlKey | WebKeyboardEvent::AltKey, 0);
+ EXPECT_EQ(ui::DomKey::FromCharacter(entry.character), web_event.domKey)
+ << ui::KeycodeConverter::DomKeyToKeyString(web_event.domKey);
+ }
+}
+
+// Testing AKEYCODE_LAST_CHANNEL because it's overlapping with
+// COMPOSITION_KEY_CODE (both 229).
+TEST(WebInputEventBuilderAndroidTest, LastChannelKey) {
+ JNIEnv* env = AttachCurrentThread();
+
+ // AKEYCODE_LAST_CHANNEL (229) is not defined in minimum NDK.
+ WebKeyboardEvent web_event =
+ CreateFakeWebKeyboardEvent(env, 229, 0, 0);
+ EXPECT_EQ(229, web_event.nativeKeyCode);
+ EXPECT_EQ(ui::KeyboardCode::VKEY_UNKNOWN, web_event.windowsKeyCode);
+ EXPECT_EQ(static_cast<int>(ui::DomCode::NONE), web_event.domCode);
+ EXPECT_EQ(ui::DomKey::MEDIA_LAST, web_event.domKey);
+}
+
+// Synthetic key event should produce DomKey::UNIDENTIFIED.
+TEST(WebInputEventBuilderAndroidTest, DomKeySyntheticEvent) {
+ WebKeyboardEvent web_event = content::WebKeyboardEventBuilder::Build(
+ nullptr, nullptr, WebKeyboardEvent::KeyDown, 0, 0, kCompositionKeyCode, 0,
+ 0, false);
+ EXPECT_EQ(kCompositionKeyCode, web_event.nativeKeyCode);
+ EXPECT_EQ(ui::KeyboardCode::VKEY_UNKNOWN, web_event.windowsKeyCode);
+ EXPECT_EQ(static_cast<int>(ui::DomCode::NONE), web_event.domCode);
+ EXPECT_EQ(ui::DomKey::UNIDENTIFIED, web_event.domKey);
+}
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_mac.mm b/chromium/content/browser/renderer_host/input/web_input_event_builders_mac.mm
index 82386ed5450..2e8ea376b85 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_mac.mm
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_mac.mm
@@ -39,6 +39,7 @@
#include "base/strings/string_util.h"
#include "content/browser/renderer_host/input/web_input_event_util.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "ui/base/cocoa/cocoa_base_utils.h"
#include "ui/events/keycodes/keyboard_code_conversion.h"
#include "ui/events/keycodes/keyboard_code_conversion_mac.h"
@@ -516,9 +517,8 @@ int ModifiersFromEvent(NSEvent* event) {
void SetWebEventLocationFromEventInView(blink::WebMouseEvent* result,
NSEvent* event,
NSView* view) {
- NSPoint window_local = [event locationInWindow];
-
- NSPoint screen_local = [[view window] convertBaseToScreen:window_local];
+ NSPoint screen_local = ui::ConvertPointFromWindowToScreen(
+ [view window], [event locationInWindow]);
result->globalX = screen_local.x;
// Flip y.
NSScreen* primary_screen = ([[NSScreen screens] count] > 0)
@@ -529,7 +529,8 @@ void SetWebEventLocationFromEventInView(blink::WebMouseEvent* result,
else
result->globalY = screen_local.y;
- NSPoint content_local = [view convertPoint:window_local fromView:nil];
+ NSPoint content_local =
+ [view convertPoint:[event locationInWindow] fromView:nil];
result->x = content_local.x;
result->y = [view frame].size.height - content_local.y; // Flip y.
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm b/chromium/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm
index 3c8c5a284b5..555fecb141d 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm
+++ b/chromium/content/browser/renderer_host/input/web_input_event_builders_mac_unittest.mm
@@ -112,7 +112,8 @@ TEST(WebInputEventBuilderMacTest, ControlSequence) {
EXPECT_EQ(ui::VKEY_OEM_4, web_event.windowsKeyCode);
EXPECT_EQ(ui::DomCode::BRACKET_LEFT,
static_cast<ui::DomCode>(web_event.domCode));
- EXPECT_EQ(ui::DomKey::FromCharacter(0x1b), web_event.domKey);
+ // Will only pass on US layout.
+ EXPECT_EQ(ui::DomKey::FromCharacter('['), web_event.domKey);
}
// Test that numpad keys get mapped correctly.
@@ -246,3 +247,188 @@ TEST(WebInputEventBuilderMacTest, SystemKeyEvents) {
webEvent = WebKeyboardEventBuilder::Build(macEvent);
EXPECT_TRUE(webEvent.isSystemKey);
}
+
+// Test conversion from key combination with Control to DomKey.
+// TODO(chongz): Move DomKey tests for all platforms into one place.
+// http://crbug.com/587589
+// This test case only works for U.S. layout.
+TEST(WebInputEventBuilderMacTest, DomKeyCtrlShift) {
+ struct DomKeyTestCase {
+ int mac_key_code;
+ unichar character;
+ unichar shift_character;
+ } table[] = {
+ {kVK_ANSI_0, '0', ')'}, {kVK_ANSI_1, '1', '!'}, {kVK_ANSI_2, '2', '@'},
+ {kVK_ANSI_3, '3', '#'}, {kVK_ANSI_4, '4', '$'}, {kVK_ANSI_5, '5', '%'},
+ {kVK_ANSI_6, '6', '^'}, {kVK_ANSI_7, '7', '&'}, {kVK_ANSI_8, '8', '*'},
+ {kVK_ANSI_9, '9', '('}, {kVK_ANSI_A, 'a', 'A'}, {kVK_ANSI_B, 'b', 'B'},
+ {kVK_ANSI_C, 'c', 'C'}, {kVK_ANSI_D, 'd', 'D'}, {kVK_ANSI_E, 'e', 'E'},
+ {kVK_ANSI_F, 'f', 'F'}, {kVK_ANSI_G, 'g', 'G'}, {kVK_ANSI_H, 'h', 'H'},
+ {kVK_ANSI_I, 'i', 'I'}, {kVK_ANSI_J, 'j', 'J'}, {kVK_ANSI_K, 'k', 'K'},
+ {kVK_ANSI_L, 'l', 'L'}, {kVK_ANSI_M, 'm', 'M'}, {kVK_ANSI_N, 'n', 'N'},
+ {kVK_ANSI_O, 'o', 'O'}, {kVK_ANSI_P, 'p', 'P'}, {kVK_ANSI_Q, 'q', 'Q'},
+ {kVK_ANSI_R, 'r', 'R'}, {kVK_ANSI_S, 's', 'S'}, {kVK_ANSI_T, 't', 'T'},
+ {kVK_ANSI_U, 'u', 'U'}, {kVK_ANSI_V, 'v', 'V'}, {kVK_ANSI_W, 'w', 'W'},
+ {kVK_ANSI_X, 'x', 'X'}, {kVK_ANSI_Y, 'y', 'Y'}, {kVK_ANSI_Z, 'z', 'Z'}};
+
+ for (const DomKeyTestCase& entry : table) {
+ // Tests ctrl_dom_key.
+ NSEvent* mac_event = BuildFakeKeyEvent(entry.mac_key_code, entry.character,
+ NSControlKeyMask, NSKeyDown);
+ WebKeyboardEvent web_event = WebKeyboardEventBuilder::Build(mac_event);
+ EXPECT_EQ(ui::DomKey::FromCharacter(entry.character), web_event.domKey);
+ // Tests ctrl_shift_dom_key.
+ mac_event = BuildFakeKeyEvent(entry.mac_key_code, entry.shift_character,
+ NSControlKeyMask | NSShiftKeyMask, NSKeyDown);
+ web_event = WebKeyboardEventBuilder::Build(mac_event);
+ EXPECT_EQ(ui::DomKey::FromCharacter(entry.shift_character),
+ web_event.domKey);
+ }
+}
+
+// This test case only works for U.S. layout.
+TEST(WebInputEventBuilderMacTest, DomKeyCtrlAlt) {
+ struct DomKeyTestCase {
+ int mac_key_code;
+ unichar alt_character;
+ unichar ctrl_alt_character;
+ } table[] = {{kVK_ANSI_0, u"º"[0], u"0"[0]}, {kVK_ANSI_1, u"¡"[0], u"1"[0]},
+ {kVK_ANSI_2, u"™"[0], u"2"[0]}, {kVK_ANSI_3, u"£"[0], u"3"[0]},
+ {kVK_ANSI_4, u"¢"[0], u"4"[0]}, {kVK_ANSI_5, u"∞"[0], u"5"[0]},
+ {kVK_ANSI_6, u"§"[0], u"6"[0]}, {kVK_ANSI_7, u"¶"[0], u"7"[0]},
+ {kVK_ANSI_8, u"•"[0], u"8"[0]}, {kVK_ANSI_9, u"ª"[0], u"9"[0]},
+ {kVK_ANSI_A, u"å"[0], u"å"[0]}, {kVK_ANSI_B, u"∫"[0], u"∫"[0]},
+ {kVK_ANSI_C, u"ç"[0], u"ç"[0]}, {kVK_ANSI_D, u"∂"[0], u"∂"[0]},
+ {kVK_ANSI_F, u"ƒ"[0], u"ƒ"[0]}, {kVK_ANSI_G, u"©"[0], u"©"[0]},
+ {kVK_ANSI_H, u"˙"[0], u"˙"[0]}, {kVK_ANSI_J, u"∆"[0], u"∆"[0]},
+ {kVK_ANSI_K, u"˚"[0], u"˚"[0]}, {kVK_ANSI_L, u"¬"[0], u"¬"[0]},
+ {kVK_ANSI_M, u"µ"[0], u"µ"[0]}, {kVK_ANSI_O, u"ø"[0], u"ø"[0]},
+ {kVK_ANSI_P, u"π"[0], u"π"[0]}, {kVK_ANSI_Q, u"œ"[0], u"œ"[0]},
+ {kVK_ANSI_R, u"®"[0], u"®"[0]}, {kVK_ANSI_S, u"ß"[0], u"ß"[0]},
+ {kVK_ANSI_T, u"†"[0], u"†"[0]}, {kVK_ANSI_V, u"√"[0], u"√"[0]},
+ {kVK_ANSI_W, u"∑"[0], u"∑"[0]}, {kVK_ANSI_X, u"≈"[0], u"≈"[0]},
+ {kVK_ANSI_Y, u"¥"[0], u"¥"[0]}, {kVK_ANSI_Z, u"Ω"[0], u"Ω"[0]}};
+
+ for (const DomKeyTestCase& entry : table) {
+ // Tests alt_dom_key.
+ NSEvent* mac_event = BuildFakeKeyEvent(
+ entry.mac_key_code, entry.alt_character, NSAlternateKeyMask, NSKeyDown);
+ WebKeyboardEvent web_event = WebKeyboardEventBuilder::Build(mac_event);
+ EXPECT_EQ(ui::DomKey::FromCharacter(entry.alt_character), web_event.domKey)
+ << "a " << entry.alt_character;
+ // Tests ctrl_alt_dom_key.
+ mac_event =
+ BuildFakeKeyEvent(entry.mac_key_code, entry.ctrl_alt_character,
+ NSControlKeyMask | NSAlternateKeyMask, NSKeyDown);
+ web_event = WebKeyboardEventBuilder::Build(mac_event);
+ EXPECT_EQ(ui::DomKey::FromCharacter(entry.ctrl_alt_character),
+ web_event.domKey)
+ << "a_c " << entry.ctrl_alt_character;
+ }
+
+ struct DeadDomKeyTestCase {
+ int mac_key_code;
+ unichar alt_accent_character;
+ } dead_key_table[] = {{kVK_ANSI_E, u"´"[0]},
+ {kVK_ANSI_I, u"ˆ"[0]},
+ {kVK_ANSI_N, u"˜"[0]},
+ {kVK_ANSI_U, u"¨"[0]}};
+
+ for (const DeadDomKeyTestCase& entry : dead_key_table) {
+ // Tests alt_accent_character.
+ NSEvent* mac_event =
+ BuildFakeKeyEvent(entry.mac_key_code, 0, NSAlternateKeyMask, NSKeyDown);
+ WebKeyboardEvent web_event = WebKeyboardEventBuilder::Build(mac_event);
+ EXPECT_EQ(
+ ui::DomKey::DeadKeyFromCombiningCharacter(entry.alt_accent_character),
+ web_event.domKey)
+ << "a " << entry.alt_accent_character;
+
+ // Tests alt_accent_character with ctrl.
+ mac_event =
+ BuildFakeKeyEvent(entry.mac_key_code, 0,
+ NSControlKeyMask | NSAlternateKeyMask, NSKeyDown);
+ web_event = WebKeyboardEventBuilder::Build(mac_event);
+ EXPECT_EQ(
+ ui::DomKey::DeadKeyFromCombiningCharacter(entry.alt_accent_character),
+ web_event.domKey)
+ << "a_c " << entry.alt_accent_character;
+ }
+}
+
+TEST(WebInputEventBuilderMacTest, DomKeyNonPrintable) {
+ struct DomKeyTestCase {
+ int mac_key_code;
+ unichar character;
+ ui::DomKey dom_key;
+ } table[] = {
+ {kVK_Return, kReturnCharCode, ui::DomKey::ENTER},
+ {kVK_Tab, kTabCharCode, ui::DomKey::TAB},
+ {kVK_Delete, kBackspaceCharCode, ui::DomKey::BACKSPACE},
+ {kVK_Escape, kEscapeCharCode, ui::DomKey::ESCAPE},
+ {kVK_F1, NSF1FunctionKey, ui::DomKey::F1},
+ {kVK_F2, NSF2FunctionKey, ui::DomKey::F2},
+ {kVK_F3, NSF3FunctionKey, ui::DomKey::F3},
+ {kVK_F4, NSF4FunctionKey, ui::DomKey::F4},
+ {kVK_F5, NSF5FunctionKey, ui::DomKey::F5},
+ {kVK_F6, NSF6FunctionKey, ui::DomKey::F6},
+ {kVK_F7, NSF7FunctionKey, ui::DomKey::F7},
+ {kVK_F8, NSF8FunctionKey, ui::DomKey::F8},
+ {kVK_F9, NSF9FunctionKey, ui::DomKey::F9},
+ {kVK_F10, NSF10FunctionKey, ui::DomKey::F10},
+ {kVK_F11, NSF11FunctionKey, ui::DomKey::F11},
+ {kVK_F12, NSF12FunctionKey, ui::DomKey::F12},
+ {kVK_F13, NSF13FunctionKey, ui::DomKey::F13},
+ {kVK_F14, NSF14FunctionKey, ui::DomKey::F14},
+ {kVK_F15, NSF15FunctionKey, ui::DomKey::F15},
+ {kVK_F16, NSF16FunctionKey, ui::DomKey::F16},
+ {kVK_F17, NSF17FunctionKey, ui::DomKey::F17},
+ {kVK_F18, NSF18FunctionKey, ui::DomKey::F18},
+ {kVK_F19, NSF19FunctionKey, ui::DomKey::F19},
+ {kVK_F20, NSF20FunctionKey, ui::DomKey::F20},
+ {kVK_Help, kHelpCharCode, ui::DomKey::HELP},
+ {kVK_Home, NSHomeFunctionKey, ui::DomKey::HOME},
+ {kVK_PageUp, NSPageUpFunctionKey, ui::DomKey::PAGE_UP},
+ {kVK_ForwardDelete, NSDeleteFunctionKey, ui::DomKey::DEL},
+ {kVK_End, NSEndFunctionKey, ui::DomKey::END},
+ {kVK_PageDown, NSPageDownFunctionKey, ui::DomKey::PAGE_DOWN},
+ {kVK_LeftArrow, NSLeftArrowFunctionKey, ui::DomKey::ARROW_LEFT},
+ {kVK_RightArrow, NSRightArrowFunctionKey, ui::DomKey::ARROW_RIGHT},
+ {kVK_DownArrow, NSDownArrowFunctionKey, ui::DomKey::ARROW_DOWN},
+ {kVK_UpArrow, NSUpArrowFunctionKey, ui::DomKey::ARROW_UP}};
+
+ for (const DomKeyTestCase& entry : table) {
+ // Tests non-printable key.
+ NSEvent* mac_event =
+ BuildFakeKeyEvent(entry.mac_key_code, entry.character, 0, NSKeyDown);
+ WebKeyboardEvent web_event = WebKeyboardEventBuilder::Build(mac_event);
+ EXPECT_EQ(entry.dom_key, web_event.domKey) << entry.mac_key_code;
+ // Tests non-printable key with Shift.
+ mac_event = BuildFakeKeyEvent(entry.mac_key_code, entry.character,
+ NSShiftKeyMask, NSKeyDown);
+ web_event = WebKeyboardEventBuilder::Build(mac_event);
+ EXPECT_EQ(entry.dom_key, web_event.domKey) << "s " << entry.mac_key_code;
+ }
+}
+
+TEST(WebInputEventBuilderMacTest, DomKeyFlagsChanged) {
+ struct DomKeyTestCase {
+ int mac_key_code;
+ ui::DomKey dom_key;
+ } table[] = {{kVK_Command, ui::DomKey::META},
+ {kVK_Shift, ui::DomKey::SHIFT},
+ {kVK_RightShift, ui::DomKey::SHIFT},
+ {kVK_CapsLock, ui::DomKey::CAPS_LOCK},
+ {kVK_Option, ui::DomKey::ALT},
+ {kVK_RightOption, ui::DomKey::ALT},
+ {kVK_Control, ui::DomKey::CONTROL},
+ {kVK_RightControl, ui::DomKey::CONTROL},
+ {kVK_Function, ui::DomKey::FN}};
+
+ for (const DomKeyTestCase& entry : table) {
+ NSEvent* mac_event =
+ BuildFakeKeyEvent(entry.mac_key_code, 0, 0, NSFlagsChanged);
+ WebKeyboardEvent web_event = WebKeyboardEventBuilder::Build(mac_event);
+ EXPECT_EQ(entry.dom_key, web_event.domKey) << entry.mac_key_code;
+ }
+}
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_util.cc b/chromium/content/browser/renderer_host/input/web_input_event_util.cc
index 579e243e274..9368a26a5dd 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_util.cc
+++ b/chromium/content/browser/renderer_host/input/web_input_event_util.cc
@@ -14,7 +14,6 @@
#include "ui/events/blink/blink_event_util.h"
#include "ui/events/event_constants.h"
#include "ui/events/gesture_detection/gesture_event_data.h"
-#include "ui/events/gesture_detection/motion_event.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/gfx/geometry/safe_integer_conversions.h"
@@ -22,7 +21,6 @@ using blink::WebGestureEvent;
using blink::WebInputEvent;
using blink::WebTouchEvent;
using blink::WebTouchPoint;
-using ui::MotionEvent;
namespace content {
@@ -70,112 +68,4 @@ blink::WebInputEvent::Modifiers DomCodeToWebInputEventModifiers(
return static_cast<blink::WebInputEvent::Modifiers>(0);
}
-// This coversino is temporary. WebInputEvent should be generated
-// directly fromui::Event with the viewport coordinates. See
-// crbug.com/563730.
-scoped_ptr<blink::WebInputEvent> ConvertWebInputEventToViewport(
- const blink::WebInputEvent& event,
- float scale) {
- scoped_ptr<blink::WebInputEvent> scaled_event;
- if (scale == 1.f)
- return scaled_event;
- if (event.type == blink::WebMouseEvent::MouseWheel) {
- blink::WebMouseWheelEvent* wheel_event = new blink::WebMouseWheelEvent;
- scaled_event.reset(wheel_event);
- *wheel_event = static_cast<const blink::WebMouseWheelEvent&>(event);
- wheel_event->x *= scale;
- wheel_event->y *= scale;
- wheel_event->deltaX *= scale;
- wheel_event->deltaY *= scale;
- wheel_event->wheelTicksX *= scale;
- wheel_event->wheelTicksY *= scale;
- } else if (blink::WebInputEvent::isMouseEventType(event.type)) {
- blink::WebMouseEvent* mouse_event = new blink::WebMouseEvent;
- scaled_event.reset(mouse_event);
- *mouse_event = static_cast<const blink::WebMouseEvent&>(event);
- mouse_event->x *= scale;
- mouse_event->y *= scale;
- mouse_event->windowX = mouse_event->x;
- mouse_event->windowY = mouse_event->y;
- mouse_event->movementX *= scale;
- mouse_event->movementY *= scale;
- } else if (blink::WebInputEvent::isTouchEventType(event.type)) {
- blink::WebTouchEvent* touch_event = new blink::WebTouchEvent;
- scaled_event.reset(touch_event);
- *touch_event = static_cast<const blink::WebTouchEvent&>(event);
- for (unsigned i = 0; i < touch_event->touchesLength; i++) {
- touch_event->touches[i].position.x *= scale;
- touch_event->touches[i].position.y *= scale;
- touch_event->touches[i].radiusX *= scale;
- touch_event->touches[i].radiusY *= scale;
- }
- } else if (blink::WebInputEvent::isGestureEventType(event.type)) {
- blink::WebGestureEvent* gesture_event = new blink::WebGestureEvent;
- scaled_event.reset(gesture_event);
- *gesture_event = static_cast<const blink::WebGestureEvent&>(event);
- gesture_event->x *= scale;
- gesture_event->y *= scale;
- switch (gesture_event->type) {
- case blink::WebInputEvent::GestureScrollUpdate:
- gesture_event->data.scrollUpdate.deltaX *= scale;
- gesture_event->data.scrollUpdate.deltaY *= scale;
- break;
- case blink::WebInputEvent::GestureScrollBegin:
- gesture_event->data.scrollBegin.deltaXHint *= scale;
- gesture_event->data.scrollBegin.deltaYHint *= scale;
- break;
-
- case blink::WebInputEvent::GesturePinchUpdate:
- // Scale in pinch gesture is DSF agnostic.
- break;
-
- case blink::WebInputEvent::GestureDoubleTap:
- case blink::WebInputEvent::GestureTap:
- case blink::WebInputEvent::GestureTapUnconfirmed:
- gesture_event->data.tap.width *= scale;
- gesture_event->data.tap.height *= scale;
- break;
-
- case blink::WebInputEvent::GestureTapDown:
- gesture_event->data.tapDown.width *= scale;
- gesture_event->data.tapDown.height *= scale;
- break;
-
- case blink::WebInputEvent::GestureShowPress:
- gesture_event->data.showPress.width *= scale;
- gesture_event->data.showPress.height *= scale;
- break;
-
- case blink::WebInputEvent::GestureLongPress:
- case blink::WebInputEvent::GestureLongTap:
- gesture_event->data.longPress.width *= scale;
- gesture_event->data.longPress.height *= scale;
- break;
-
- case blink::WebInputEvent::GestureTwoFingerTap:
- gesture_event->data.twoFingerTap.firstFingerWidth *= scale;
- gesture_event->data.twoFingerTap.firstFingerHeight *= scale;
- break;
-
- case blink::WebInputEvent::GestureFlingStart:
- gesture_event->data.flingStart.velocityX *= scale;
- gesture_event->data.flingStart.velocityY *= scale;
- break;
-
- // These event does not have location data.
- case blink::WebInputEvent::GesturePinchBegin:
- case blink::WebInputEvent::GesturePinchEnd:
- case blink::WebInputEvent::GestureTapCancel:
- case blink::WebInputEvent::GestureFlingCancel:
- case blink::WebInputEvent::GestureScrollEnd:
- break;
-
- // TODO(oshima): Find out if ContextMenu needs to be scaled.
- default:
- break;
- }
- }
- return scaled_event;
-}
-
} // namespace content
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 8cc3e45af40..b7963a38e28 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
@@ -15,7 +15,6 @@ namespace ui {
enum class DomCode;
struct GestureEventData;
struct GestureEventDetails;
-class MotionEvent;
}
namespace content {
@@ -25,10 +24,6 @@ int WebEventModifiersToEventFlags(int modifiers);
blink::WebInputEvent::Modifiers DomCodeToWebInputEventModifiers(
ui::DomCode code);
-CONTENT_EXPORT scoped_ptr<blink::WebInputEvent> ConvertWebInputEventToViewport(
- const blink::WebInputEvent& event,
- float scale);
-
} // namespace content
#endif // CONTENT_BROWSER_RENDERER_HOST_INPUT_WEB_INPUT_EVENT_UTIL_H_
diff --git a/chromium/content/browser/renderer_host/input/web_input_event_util_unittest.cc b/chromium/content/browser/renderer_host/input/web_input_event_util_unittest.cc
index 77810308059..20dce73ec21 100644
--- a/chromium/content/browser/renderer_host/input/web_input_event_util_unittest.cc
+++ b/chromium/content/browser/renderer_host/input/web_input_event_util_unittest.cc
@@ -125,12 +125,4 @@ TEST(WebInputEventUtilTest, ScrollUpdateConversion) {
EXPECT_TRUE(web_event.data.scrollUpdate.previousUpdateInSequencePrevented);
}
-TEST(WebInputEventUtilTest, NoScalingWith1DSF) {
- auto event =
- SyntheticWebMouseEventBuilder::Build(blink::WebInputEvent::MouseMove,
- 10, 10, 0);
- EXPECT_FALSE(ConvertWebInputEventToViewport(event, 1.f));
- EXPECT_TRUE(ConvertWebInputEventToViewport(event, 2.f));
-}
-
} // namespace content
diff --git a/chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc b/chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc
index 9e2305747a5..3412b33cde8 100644
--- a/chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc
+++ b/chromium/content/browser/renderer_host/legacy_render_widget_host_win.cc
@@ -6,6 +6,7 @@
#include "base/command_line.h"
#include "base/memory/scoped_ptr.h"
+#include "base/win/win_util.h"
#include "base/win/windows_version.h"
#include "content/browser/accessibility/browser_accessibility_manager_win.h"
#include "content/browser/accessibility/browser_accessibility_win.h"
@@ -96,6 +97,10 @@ void LegacyRenderWidgetHostHWND::OnFinalMessage(HWND hwnd) {
host_->OnLegacyWindowDestroyed();
host_ = NULL;
}
+
+ // Re-enable flicks for just a moment
+ base::win::EnableFlicks(hwnd);
+
delete this;
}
@@ -136,6 +141,9 @@ bool LegacyRenderWidgetHostHWND::Init() {
if (direct_manipulation_helper_)
direct_manipulation_helper_->Initialize(hwnd());
+ // Disable pen flicks (http://crbug.com/506977)
+ base::win::DisableFlicks(hwnd());
+
return !!SUCCEEDED(hr);
}
@@ -181,7 +189,7 @@ LRESULT LegacyRenderWidgetHostHWND::OnGetObject(UINT message,
return static_cast<LRESULT>(0L);
base::win::ScopedComPtr<IAccessible> root(
- manager->GetRoot()->ToBrowserAccessibilityWin());
+ ToBrowserAccessibilityWin(manager->GetRoot()));
return LresultFromObject(IID_IAccessible, w_param,
static_cast<IAccessible*>(root.Detach()));
}
diff --git a/chromium/content/browser/renderer_host/media/OWNERS b/chromium/content/browser/renderer_host/media/OWNERS
index b77671af71b..111357356a4 100644
--- a/chromium/content/browser/renderer_host/media/OWNERS
+++ b/chromium/content/browser/renderer_host/media/OWNERS
@@ -1,6 +1,4 @@
-dalecurtis@chromium.org
-ddorwin@chromium.org
-xhwang@chromium.org
+file://media/OWNERS
# WebRTC OWNERS.
perkj@chromium.org
diff --git a/chromium/content/browser/renderer_host/media/audio_input_debug_writer.cc b/chromium/content/browser/renderer_host/media/audio_input_debug_writer.cc
index 5a500b49365..7866c651a34 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_debug_writer.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_debug_writer.cc
@@ -3,22 +3,150 @@
// found in the LICENSE file.
#include "content/browser/renderer_host/media/audio_input_debug_writer.h"
-
+#include <stdint.h>
+#include <array>
#include <utility>
-
+#include "base/logging.h"
+#include "base/sys_byteorder.h"
#include "content/public/browser/browser_thread.h"
#include "media/base/audio_bus.h"
namespace content {
-AudioInputDebugWriter::AudioInputDebugWriter(base::File file)
- : file_(std::move(file)), interleaved_data_size_(0), weak_factory_(this) {}
+namespace {
+
+// Windows WAVE format header
+// Byte order: Little-endian
+// Offset Length Content
+// 0 4 "RIFF"
+// 4 4 <file length - 8>
+// 8 4 "WAVE"
+// 12 4 "fmt "
+// 16 4 <length of the fmt data> (=16)
+// 20 2 <WAVE file encoding tag>
+// 22 2 <channels>
+// 24 4 <sample rate>
+// 28 4 <bytes per second> (sample rate * block align)
+// 32 2 <block align> (channels * bits per sample / 8)
+// 34 2 <bits per sample>
+// 36 4 "data"
+// 40 4 <sample data size(n)>
+// 44 (n) <sample data>
+
+// We write 16 bit PCM only.
+static const uint16_t kBytesPerSample = 2;
+
+static const uint32_t kWavHeaderSize = 44;
+static const uint32_t kFmtChunkSize = 16;
+// 4 bytes for ID + 4 bytes for size.
+static const uint32_t kChunkHeaderSize = 8;
+static const uint16_t kWavFormatPcm = 1;
+
+static const char kRiff[] = {'R', 'I', 'F', 'F'};
+static const char kWave[] = {'W', 'A', 'V', 'E'};
+static const char kFmt[] = {'f', 'm', 't', ' '};
+static const char kData[] = {'d', 'a', 't', 'a'};
+
+typedef std::array<char, kWavHeaderSize> WavHeaderBuffer;
+
+class CharBufferWriter {
+ public:
+ CharBufferWriter(char* buf, int max_size)
+ : buf_(buf), max_size_(max_size), size_(0) {}
+
+ void Write(const char* data, int data_size) {
+ CHECK_LE(size_ + data_size, max_size_);
+ memcpy(&buf_[size_], data, data_size);
+ size_ += data_size;
+ }
+
+ void Write(const char(&data)[4]) { Write(static_cast<const char*>(data), 4); }
+
+ void WriteLE16(uint16_t data) {
+ uint16_t val = base::ByteSwapToLE16(data);
+ Write(reinterpret_cast<const char*>(&val), sizeof(val));
+ }
+
+ void WriteLE32(uint32_t data) {
+ uint32_t val = base::ByteSwapToLE32(data);
+ Write(reinterpret_cast<const char*>(&val), sizeof(val));
+ }
+
+ private:
+ char* buf_;
+ const int max_size_;
+ int size_;
+
+ DISALLOW_COPY_AND_ASSIGN(CharBufferWriter);
+};
+
+// Writes Wave header to the specified address, there should be at least
+// kWavHeaderSize bytes allocated for it.
+void WriteWavHeader(WavHeaderBuffer* buf,
+ uint32_t channels,
+ uint32_t sample_rate,
+ uint64_t samples) {
+ // We'll need to add (kWavHeaderSize - kChunkHeaderSize) to payload to
+ // calculate Riff chunk size.
+ static const uint32_t kMaxBytesInPayload =
+ std::numeric_limits<uint32_t>::max() -
+ (kWavHeaderSize - kChunkHeaderSize);
+ const uint64_t bytes_in_payload_64 = samples * kBytesPerSample;
+
+ // In case payload is too large and causes uint32_t overflow, we just specify
+ // the maximum possible value; all the payload above that count will be
+ // interpreted as garbage.
+ const uint32_t bytes_in_payload = bytes_in_payload_64 > kMaxBytesInPayload
+ ? kMaxBytesInPayload
+ : bytes_in_payload_64;
+ LOG_IF(WARNING, bytes_in_payload < bytes_in_payload_64)
+ << "Number of samples is too large and will be clipped by Wave header,"
+ << " all the data above " << kMaxBytesInPayload
+ << " bytes will appear as junk";
+ const uint32_t block_align = channels * kBytesPerSample;
+ const uint32_t byte_rate = channels * sample_rate * kBytesPerSample;
+ const uint32_t riff_chunk_size =
+ bytes_in_payload + kWavHeaderSize - kChunkHeaderSize;
+
+ CharBufferWriter writer(&(*buf)[0], kWavHeaderSize);
+
+ writer.Write(kRiff);
+ writer.WriteLE32(riff_chunk_size);
+ writer.Write(kWave);
+ writer.Write(kFmt);
+ writer.WriteLE32(kFmtChunkSize);
+ writer.WriteLE16(kWavFormatPcm);
+ writer.WriteLE16(channels);
+ writer.WriteLE32(sample_rate);
+ writer.WriteLE32(byte_rate);
+ writer.WriteLE16(block_align);
+ writer.WriteLE16(kBytesPerSample * 8);
+ writer.Write(kData);
+ writer.WriteLE32(bytes_in_payload);
+}
+
+} // namespace
+
+AudioInputDebugWriter::AudioInputDebugWriter(
+ base::File file,
+ const media::AudioParameters& params)
+ : file_(std::move(file)),
+ samples_(0),
+ params_(params),
+ interleaved_data_size_(0),
+ weak_factory_(this) {
+ DCHECK_EQ(params.bits_per_sample(), kBytesPerSample * 8);
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(&AudioInputDebugWriter::WriteHeader,
+ weak_factory_.GetWeakPtr()));
+}
AudioInputDebugWriter::~AudioInputDebugWriter() {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+ WriteHeader();
}
-void AudioInputDebugWriter::Write(scoped_ptr<media::AudioBus> data) {
+void AudioInputDebugWriter::Write(std::unique_ptr<media::AudioBus> data) {
BrowserThread::PostTask(
BrowserThread::FILE,
FROM_HERE,
@@ -27,19 +155,43 @@ void AudioInputDebugWriter::Write(scoped_ptr<media::AudioBus> data) {
base::Passed(&data)));
}
-void AudioInputDebugWriter::DoWrite(scoped_ptr<media::AudioBus> data) {
+void AudioInputDebugWriter::DoWrite(std::unique_ptr<media::AudioBus> data) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
-
// Convert to 16 bit audio and write to file.
int data_size = data->frames() * data->channels();
if (!interleaved_data_ || interleaved_data_size_ < data_size) {
interleaved_data_.reset(new int16_t[data_size]);
interleaved_data_size_ = data_size;
}
+ samples_ += data_size;
data->ToInterleaved(data->frames(), sizeof(interleaved_data_[0]),
interleaved_data_.get());
+
+#ifndef ARCH_CPU_LITTLE_ENDIAN
+ static_assert(sizeof(interleaved_data_[0]) == sizeof(uint16_t),
+ "Only 2 bytes per channel is supported.");
+ for (int i = 0; i < data_size; ++i)
+ interleaved_data_[i] = base::ByteSwapToLE16(interleaved_data_[i]);
+#endif
+
file_.WriteAtCurrentPos(reinterpret_cast<char*>(interleaved_data_.get()),
data_size * sizeof(interleaved_data_[0]));
}
+// This method is called twice: on construction of AudioInputDebugWriter size of
+// the data is unknown, so the header is written with zero sizes; then on
+// destruction it is re-written with the actual size info accumulated throughout
+// its lifetime.
+void AudioInputDebugWriter::WriteHeader() {
+ DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+
+ WavHeaderBuffer buf;
+ WriteWavHeader(&buf, params_.channels(), params_.sample_rate(), samples_);
+ file_.Write(0, &buf[0], kWavHeaderSize);
+
+ // Write() does not move the cursor if file is not in APPEND mode; Seek() so
+ // that the header is not overwritten by the following writes.
+ file_.Seek(base::File::FROM_BEGIN, kWavHeaderSize);
+}
+
} // namspace content
diff --git a/chromium/content/browser/renderer_host/media/audio_input_debug_writer.h b/chromium/content/browser/renderer_host/media/audio_input_debug_writer.h
index 13977756877..0741001d99c 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_debug_writer.h
+++ b/chromium/content/browser/renderer_host/media/audio_input_debug_writer.h
@@ -7,13 +7,16 @@
#include <stdint.h>
+#include <memory>
+
#include "base/files/file.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/move.h"
+#include "content/common/content_export.h"
#include "media/audio/audio_input_writer.h"
+#include "media/audio/audio_parameters.h"
namespace media {
@@ -28,24 +31,37 @@ namespace content {
// thread. Must be destroyed on the FILE thread. Write call can be made on any
// thread. This object must be unregistered in Write caller before destroyed.
// When created, it takes ownership of |file|.
-class AudioInputDebugWriter : public media::AudioInputWriter {
+class CONTENT_EXPORT AudioInputDebugWriter
+ : public NON_EXPORTED_BASE(media::AudioInputWriter) {
public:
- explicit AudioInputDebugWriter(base::File file);
+ AudioInputDebugWriter(base::File file, const media::AudioParameters& params);
~AudioInputDebugWriter() override;
// Write data from |data| to file.
- void Write(scoped_ptr<media::AudioBus> data) override;
+ void Write(std::unique_ptr<media::AudioBus> data) override;
private:
// Write data from |data| to file. Called on the FILE thread.
- void DoWrite(scoped_ptr<media::AudioBus> data);
+ void DoWrite(std::unique_ptr<media::AudioBus> data);
+
+ // Write wave header to file. Called on the FILE thread twice: on construction
+ // of AudioInputDebugWriter size of the wave data is unknown, so the header is
+ // written with zero sizes; then on destruction it is re-written with the
+ // actual size info accumulated throughout the object lifetime.
+ void WriteHeader();
// The file to write to.
base::File file_;
+ // Number of written samples.
+ uint64_t samples_;
+
+ // Input audio parameters required to build wave header.
+ media::AudioParameters params_;
+
// Intermediate buffer to be written to file. Interleaved 16 bit audio data.
- scoped_ptr<int16_t[]> interleaved_data_;
+ std::unique_ptr<int16_t[]> interleaved_data_;
int interleaved_data_size_;
base::WeakPtrFactory<AudioInputDebugWriter> weak_factory_;
diff --git a/chromium/content/browser/renderer_host/media/audio_input_debug_writer_unittest.cc b/chromium/content/browser/renderer_host/media/audio_input_debug_writer_unittest.cc
new file mode 100644
index 00000000000..ee8b5d5cdfd
--- /dev/null
+++ b/chromium/content/browser/renderer_host/media/audio_input_debug_writer_unittest.cc
@@ -0,0 +1,270 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stdint.h>
+
+#include "base/files/file_util.h"
+#include "base/sys_byteorder.h"
+#include "content/browser/renderer_host/media/audio_input_debug_writer.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "media/base/audio_bus.h"
+#include "media/base/test_helpers.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+static const uint16_t kBytesPerSample = sizeof(uint16_t);
+static const uint16_t kPcmEncoding = 1;
+static const size_t kWavHeaderSize = 44;
+
+uint16_t ReadLE2(const char* buf) {
+ return static_cast<uint8_t>(buf[0]) | (static_cast<uint8_t>(buf[1]) << 8);
+}
+
+uint32_t ReadLE4(const char* buf) {
+ return static_cast<uint8_t>(buf[0]) | (static_cast<uint8_t>(buf[1]) << 8) |
+ (static_cast<uint8_t>(buf[2]) << 16) |
+ (static_cast<uint8_t>(buf[3]) << 24);
+}
+
+} // namespace
+
+// <channel layout, sample rate, frames per buffer, number of buffer writes
+typedef std::tr1::tuple<media::ChannelLayout, int, int, int>
+ AudioInputDebugWriterTestData;
+
+class AudioInputDebugWriterTest
+ : public testing::TestWithParam<AudioInputDebugWriterTestData> {
+ public:
+ AudioInputDebugWriterTest()
+ : params_(media::AudioParameters::Format::AUDIO_PCM_LINEAR,
+ std::tr1::get<0>(GetParam()),
+ std::tr1::get<1>(GetParam()),
+ kBytesPerSample * 8,
+ std::tr1::get<2>(GetParam())),
+ writes_(std::tr1::get<3>(GetParam())),
+ source_samples_(params_.frames_per_buffer() * params_.channels() *
+ writes_),
+ source_interleaved_(source_samples_ ? new int16_t[source_samples_]
+ : nullptr) {
+ InitSourceInterleaved(source_interleaved_.get(), source_samples_);
+ }
+
+ protected:
+ virtual ~AudioInputDebugWriterTest() {}
+
+ static void InitSourceInterleaved(int16_t* source_interleaved,
+ int source_samples) {
+ if (source_samples) {
+ // equal steps to cover int16_t range of values
+ int16_t step = 0xffff / source_samples;
+ int16_t val = std::numeric_limits<int16_t>::min();
+ for (int i = 0; i < source_samples; ++i, val += step)
+ source_interleaved[i] = val;
+ }
+ }
+
+ static void VerifyHeader(const char(&wav_header)[kWavHeaderSize],
+ const media::AudioParameters& params,
+ int writes,
+ int64_t file_length) {
+ uint32_t block_align = params.channels() * kBytesPerSample;
+ uint32_t data_size =
+ static_cast<uint32_t>(params.frames_per_buffer() * params.channels() *
+ writes * kBytesPerSample);
+ // Offset Length Content
+ // 0 4 "RIFF"
+ EXPECT_EQ(0, strncmp(wav_header, "RIFF", 4));
+ // 4 4 <file length - 8>
+ EXPECT_EQ(static_cast<uint64_t>(file_length - 8), ReadLE4(wav_header + 4));
+ EXPECT_EQ(static_cast<uint32_t>(data_size + kWavHeaderSize - 8),
+ ReadLE4(wav_header + 4));
+ // 8 4 "WAVE"
+ // 12 4 "fmt "
+ EXPECT_EQ(0, strncmp(wav_header + 8, "WAVEfmt ", 8));
+ // 16 4 <length of the fmt data> (=16)
+ EXPECT_EQ(16U, ReadLE4(wav_header + 16));
+ // 20 2 <WAVE file encoding tag>
+ EXPECT_EQ(kPcmEncoding, ReadLE2(wav_header + 20));
+ // 22 2 <channels>
+ EXPECT_EQ(params.channels(), ReadLE2(wav_header + 22));
+ // 24 4 <sample rate>
+ EXPECT_EQ(static_cast<uint32_t>(params.sample_rate()),
+ ReadLE4(wav_header + 24));
+ // 28 4 <bytes per second> (sample rate * block align)
+ EXPECT_EQ(static_cast<uint32_t>(params.sample_rate()) * block_align,
+ ReadLE4(wav_header + 28));
+ // 32 2 <block align> (channels * bits per sample / 8)
+ EXPECT_EQ(block_align, ReadLE2(wav_header + 32));
+ // 34 2 <bits per sample>
+ EXPECT_EQ(kBytesPerSample * 8, ReadLE2(wav_header + 34));
+ // 36 4 "data"
+ EXPECT_EQ(0, strncmp(wav_header + 36, "data", 4));
+ // 40 4 <sample data size(n)>
+ EXPECT_EQ(data_size, ReadLE4(wav_header + 40));
+ }
+
+ // |result_interleaved| is expected to be little-endian.
+ static void VerifyDataRecording(const int16_t* source_interleaved,
+ const int16_t* result_interleaved,
+ int16_t source_samples) {
+ // Allow mismatch by 1 due to rounding error in int->float->int
+ // calculations.
+ for (int i = 0; i < source_samples; ++i)
+ EXPECT_LE(std::abs(static_cast<int16_t>(
+ base::ByteSwapToLE16(source_interleaved[i])) -
+ result_interleaved[i]),
+ 1)
+ << "i = " << i << " source " << source_interleaved[i] << " result "
+ << result_interleaved[i];
+ }
+
+ void VerifyRecording(const base::FilePath& file_path) {
+ base::File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
+ EXPECT_TRUE(file.IsValid());
+
+ char wav_header[kWavHeaderSize];
+ EXPECT_EQ(file.Read(0, wav_header, kWavHeaderSize),
+ static_cast<int>(kWavHeaderSize));
+ VerifyHeader(wav_header, params_, writes_, file.GetLength());
+
+ if (source_samples_ > 0) {
+ std::unique_ptr<int16_t[]> result_interleaved(
+ new int16_t[source_samples_]);
+ memset(result_interleaved.get(), 0, source_samples_ * kBytesPerSample);
+
+ // Recording is read from file as a byte sequence, so it stored as
+ // little-endian.
+ int read = file.Read(kWavHeaderSize,
+ reinterpret_cast<char*>(result_interleaved.get()),
+ source_samples_ * kBytesPerSample);
+ EXPECT_EQ(static_cast<int>(file.GetLength() - kWavHeaderSize), read);
+
+ VerifyDataRecording(source_interleaved_.get(), result_interleaved.get(),
+ source_samples_);
+ }
+ }
+
+ void TestDoneOnFileThread(const base::Closure& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::FILE);
+
+ // |writer| must be destroyed on FILE thread.
+ input_debug_writer_.reset(nullptr);
+ callback.Run();
+ }
+
+ void DoDebugRecording(base::File file) {
+ if (!file.IsValid())
+ return;
+
+ input_debug_writer_.reset(
+ new AudioInputDebugWriter(std::move(file), params_));
+ // Write tasks are posted to BrowserThread::FILE.
+ for (int i = 0; i < writes_; ++i) {
+ std::unique_ptr<media::AudioBus> bus = media::AudioBus::Create(
+ params_.channels(), params_.frames_per_buffer());
+
+ bus->FromInterleaved(
+ source_interleaved_.get() +
+ i * params_.channels() * params_.frames_per_buffer(),
+ params_.frames_per_buffer(), kBytesPerSample);
+
+ input_debug_writer_->Write(std::move(bus));
+ }
+
+ media::WaitableMessageLoopEvent event;
+
+ // Post a task to BrowserThread::FILE indicating that all the writes are
+ // done.
+ BrowserThread::PostTask(
+ BrowserThread::FILE, FROM_HERE,
+ base::Bind(&AudioInputDebugWriterTest::TestDoneOnFileThread,
+ base::Unretained(this), event.GetClosure()));
+
+ // Wait for TestDoneOnFileThread() to call event's closure.
+ event.RunAndWait();
+ }
+
+ protected:
+ TestBrowserThreadBundle thread_bundle_;
+
+ // Writer under test.
+ std::unique_ptr<AudioInputDebugWriter> input_debug_writer_;
+
+ // AudioBus parameters.
+ media::AudioParameters params_;
+
+ // Number of times to write AudioBus to the file.
+ int writes_;
+
+ // Number of samples in the source data.
+ int source_samples_;
+
+ // Source data.
+ std::unique_ptr<int16_t[]> source_interleaved_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AudioInputDebugWriterTest);
+};
+
+TEST_P(AudioInputDebugWriterTest, WaveRecordingTest) {
+ base::FilePath file_path;
+ EXPECT_TRUE(base::CreateTemporaryFile(&file_path));
+
+ base::File file(file_path,
+ base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
+ EXPECT_TRUE(file.IsValid());
+
+ DoDebugRecording(std::move(file));
+
+ VerifyRecording(file_path);
+
+ if (::testing::Test::HasFailure()) {
+ LOG(ERROR) << "Test failed; keeping recording(s) at ["
+ << file_path.value().c_str() << "].";
+ } else {
+ EXPECT_TRUE(base::DeleteFile(file_path, false));
+ }
+}
+
+INSTANTIATE_TEST_CASE_P(
+ AudioInputDebugWriterTest,
+ AudioInputDebugWriterTest,
+ // Using 10ms sframes per buffer everywhere.
+ testing::Values(
+ // No writes.
+ std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO,
+ 44100,
+ 44100 / 100,
+ 0),
+ // 1 write of mono.
+ std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO,
+ 44100,
+ 44100 / 100,
+ 1),
+ // 1 second of mono.
+ std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO,
+ 44100,
+ 44100 / 100,
+ 100),
+ // 1 second of mono, higher rate.
+ std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_MONO,
+ 48000,
+ 48000 / 100,
+ 100),
+ // 1 second of stereo.
+ std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_STEREO,
+ 44100,
+ 44100 / 100,
+ 100),
+ // 15 seconds of stereo, higher rate.
+ std::tr1::make_tuple(media::ChannelLayout::CHANNEL_LAYOUT_STEREO,
+ 48000,
+ 48000 / 100,
+ 1500)));
+
+} // 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 65148e04e90..72f8ee0a391 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
@@ -4,8 +4,9 @@
#include "content/browser/renderer_host/media/audio_input_device_manager.h"
+#include <memory>
+
#include "base/bind.h"
-#include "base/memory/scoped_ptr.h"
#include "base/metrics/histogram_macros.h"
#include "build/build_config.h"
#include "content/public/browser/browser_thread.h"
@@ -172,7 +173,7 @@ void AudioInputDeviceManager::EnumerateOnDeviceThread(
audio_manager_->GetAudioInputDeviceNames(&device_names);
}
- scoped_ptr<StreamDeviceInfoArray> devices(new StreamDeviceInfoArray());
+ std::unique_ptr<StreamDeviceInfoArray> devices(new StreamDeviceInfoArray());
for (media::AudioDeviceNames::iterator it = device_names.begin();
it != device_names.end(); ++it) {
// Add device information to device vector.
@@ -241,7 +242,7 @@ void AudioInputDeviceManager::OpenOnDeviceThread(
void AudioInputDeviceManager::DevicesEnumeratedOnIOThread(
MediaStreamType stream_type,
- scoped_ptr<StreamDeviceInfoArray> devices) {
+ std::unique_ptr<StreamDeviceInfoArray> devices) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// Ensure that |devices| gets deleted on exit.
if (listener_)
diff --git a/chromium/content/browser/renderer_host/media/audio_input_device_manager.h b/chromium/content/browser/renderer_host/media/audio_input_device_manager.h
index d3f01b35f78..0f58242f75d 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_device_manager.h
+++ b/chromium/content/browser/renderer_host/media/audio_input_device_manager.h
@@ -84,8 +84,9 @@ class CONTENT_EXPORT AudioInputDeviceManager : public MediaStreamProvider {
// Callback used by EnumerateOnDeviceThread(), called with a list of
// enumerated devices on IO thread.
- void DevicesEnumeratedOnIOThread(MediaStreamType stream_type,
- scoped_ptr<StreamDeviceInfoArray> devices);
+ void DevicesEnumeratedOnIOThread(
+ MediaStreamType stream_type,
+ std::unique_ptr<StreamDeviceInfoArray> devices);
// Callback used by OpenOnDeviceThread(), called with the session_id
// referencing the opened device on IO thread.
void OpenedOnIOThread(int session_id, const StreamDeviceInfo& info);
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 4fac69d7dda..dd387bbdf23 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
@@ -2,20 +2,21 @@
// 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/audio_input_device_manager.h"
+
#include <stddef.h>
+#include <memory>
#include <string>
#include "base/bind.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
#include "build/build_config.h"
#include "content/browser/browser_thread_impl.h"
-#include "content/browser/renderer_host/media/audio_input_device_manager.h"
#include "content/public/common/media_stream_request.h"
#include "media/audio/audio_manager_base.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -94,11 +95,11 @@ class MAYBE_AudioInputDeviceManagerTest : public testing::Test {
io_thread_.reset();
}
- scoped_ptr<base::MessageLoop> message_loop_;
- scoped_ptr<BrowserThreadImpl> io_thread_;
+ std::unique_ptr<base::MessageLoop> message_loop_;
+ std::unique_ptr<BrowserThreadImpl> io_thread_;
scoped_refptr<AudioInputDeviceManager> manager_;
- scoped_ptr<MockAudioInputDeviceManagerListener> audio_input_listener_;
- scoped_ptr<media::AudioManager> audio_manager_;
+ std::unique_ptr<MockAudioInputDeviceManagerListener> audio_input_listener_;
+ std::unique_ptr<media::AudioManager> audio_manager_;
StreamDeviceInfoArray devices_;
private:
@@ -141,7 +142,7 @@ TEST_F(MAYBE_AudioInputDeviceManagerTest, OpenMultipleDevices) {
InSequence s;
int index = 0;
- scoped_ptr<int[]> session_id(new int[devices_.size()]);
+ std::unique_ptr<int[]> session_id(new int[devices_.size()]);
// Opens the devices in a loop.
for (StreamDeviceInfoArray::const_iterator iter = devices_.begin();
@@ -238,7 +239,7 @@ TEST_F(MAYBE_AudioInputDeviceManagerTest, AccessAndCloseSession) {
InSequence s;
int index = 0;
- scoped_ptr<int[]> session_id(new int[devices_.size()]);
+ std::unique_ptr<int[]> session_id(new int[devices_.size()]);
// Loops through the devices and calls Open()/Close()/GetOpenedDeviceInfoById
// for each device.
diff --git a/chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc b/chromium/content/browser/renderer_host/media/audio_input_renderer_host.cc
index 60f64596171..2d8a89a1481 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
@@ -16,9 +16,10 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
+#include "content/browser/media/capture/desktop_capture_device_uma_types.h"
#include "content/browser/media/capture/web_contents_audio_input_stream.h"
#include "content/browser/media/media_internals.h"
-#include "content/browser/media/webrtc_internals.h"
+#include "content/browser/media/webrtc/webrtc_internals.h"
#include "content/browser/renderer_host/media/audio_input_debug_writer.h"
#include "content/browser/renderer_host/media/audio_input_device_manager.h"
#include "content/browser/renderer_host/media/audio_input_sync_writer.h"
@@ -35,7 +36,7 @@ namespace {
const base::FilePath::CharType kDebugRecordingFileNameAddition[] =
FILE_PATH_LITERAL("source_input");
const base::FilePath::CharType kDebugRecordingFileNameExtension[] =
- FILE_PATH_LITERAL("pcm");
+ FILE_PATH_LITERAL("wav");
#endif
void LogMessage(int stream_id, const std::string& msg, bool add_prefix) {
@@ -52,7 +53,7 @@ void LogMessage(int stream_id, const std::string& msg, bool add_prefix) {
base::File CreateDebugRecordingFile(base::FilePath file_path) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
base::File recording_file(
- file_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_APPEND);
+ file_path, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
PLOG_IF(ERROR, !recording_file.IsValid())
<< "Could not open debug recording file, error="
<< recording_file.error_details();
@@ -65,7 +66,7 @@ void CloseFile(base::File file) {
}
void DeleteInputDebugWriterOnFileThread(
- scoped_ptr<AudioInputDebugWriter> writer) {
+ std::unique_ptr<AudioInputDebugWriter> writer) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
// |writer| must be closed and destroyed on FILE thread.
}
@@ -90,17 +91,22 @@ struct AudioInputRendererHost::AudioEntry {
// The synchronous writer to be used by the controller. We have the
// ownership of the writer.
- scoped_ptr<media::AudioInputController::SyncWriter> writer;
+ std::unique_ptr<AudioInputSyncWriter> writer;
// Must be deleted on the file thread. Must be posted for deletion and nulled
// before the AudioEntry is deleted.
- scoped_ptr<AudioInputDebugWriter> input_debug_writer;
+ std::unique_ptr<AudioInputDebugWriter> input_debug_writer;
// Set to true after we called Close() for the controller.
bool pending_close;
// If this entry's layout has a keyboard mic channel.
bool has_keyboard_mic;
+
+#ifdef ENABLE_WEBRTC
+ // Stream audio parameters, used to build wave header for debug recording.
+ media::AudioParameters audio_params;
+#endif // ENABLE_WEBRTC
};
AudioInputRendererHost::AudioEntry::AudioEntry()
@@ -168,35 +174,25 @@ void AudioInputRendererHost::OnDestruct() const {
void AudioInputRendererHost::OnCreated(
media::AudioInputController* controller) {
BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(
- &AudioInputRendererHost::DoCompleteCreation,
- this,
- make_scoped_refptr(controller)));
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&AudioInputRendererHost::DoCompleteCreation, this,
+ base::RetainedRef(controller)));
}
void AudioInputRendererHost::OnRecording(
media::AudioInputController* controller) {
BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(
- &AudioInputRendererHost::DoSendRecordingMessage,
- this,
- make_scoped_refptr(controller)));
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&AudioInputRendererHost::DoSendRecordingMessage, this,
+ base::RetainedRef(controller)));
}
void AudioInputRendererHost::OnError(media::AudioInputController* controller,
media::AudioInputController::ErrorCode error_code) {
BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(
- &AudioInputRendererHost::DoHandleError,
- this,
- make_scoped_refptr(controller),
- error_code));
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&AudioInputRendererHost::DoHandleError, this,
+ base::RetainedRef(controller), error_code));
}
void AudioInputRendererHost::OnData(media::AudioInputController* controller,
@@ -206,12 +202,9 @@ void AudioInputRendererHost::OnData(media::AudioInputController* controller,
void AudioInputRendererHost::OnLog(media::AudioInputController* controller,
const std::string& message) {
- BrowserThread::PostTask(BrowserThread::IO,
- FROM_HERE,
- base::Bind(&AudioInputRendererHost::DoLog,
- this,
- make_scoped_refptr(controller),
- message));
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&AudioInputRendererHost::DoLog, this,
+ base::RetainedRef(controller), message));
}
void AudioInputRendererHost::set_renderer_pid(int32_t renderer_pid) {
@@ -252,8 +245,7 @@ void AudioInputRendererHost::DoCompleteCreation(
return;
}
- AudioInputSyncWriter* writer =
- static_cast<AudioInputSyncWriter*>(entry->writer.get());
+ AudioInputSyncWriter* writer = entry->writer.get();
base::SyncSocket::TransitDescriptor socket_transit_descriptor;
@@ -391,6 +383,7 @@ void AudioInputRendererHost::DoCreateStream(
audio_params.set_format(media::AudioParameters::AUDIO_FAKE);
// Check if we have the permission to open the device and which device to use.
+ MediaStreamType type = MEDIA_NO_SERVICE;
std::string device_name;
std::string device_id = media::AudioManagerBase::kDefaultDeviceId;
if (audio_params.format() != media::AudioParameters::AUDIO_FAKE) {
@@ -403,14 +396,14 @@ void AudioInputRendererHost::DoCreateStream(
MaybeUnregisterKeyboardMicStream(config);
return;
}
-
+ type = info->device.type;
device_id = info->device.id;
device_name = info->device.name;
oss << ": device_name=" << device_name;
}
// Create a new AudioEntry structure.
- scoped_ptr<AudioEntry> entry(new AudioEntry());
+ std::unique_ptr<AudioEntry> entry(new AudioEntry());
const uint32_t segment_size =
(sizeof(media::AudioInputBufferParameters) +
@@ -429,7 +422,7 @@ void AudioInputRendererHost::DoCreateStream(
return;
}
- scoped_ptr<AudioInputSyncWriter> writer(new AudioInputSyncWriter(
+ std::unique_ptr<AudioInputSyncWriter> writer(new AudioInputSyncWriter(
entry->shared_memory.memory(), entry->shared_memory.requested_size(),
entry->shared_memory_segment_count, audio_params));
@@ -453,6 +446,9 @@ void AudioInputRendererHost::DoCreateStream(
audio_mirroring_manager_),
entry->writer.get(),
user_input_monitor_);
+ // Only count for captures from desktop media picker dialog.
+ if (entry->controller.get() && type == MEDIA_DESKTOP_AUDIO_CAPTURE)
+ IncrementDesktopCaptureCounter(TAB_AUDIO_CAPTURER_CREATED);
} else {
// We call CreateLowLatency regardless of the value of
// |audio_params.format|. Low latency can currently mean different things in
@@ -468,6 +464,13 @@ void AudioInputRendererHost::DoCreateStream(
user_input_monitor_,
config.automatic_gain_control);
oss << ", AGC=" << config.automatic_gain_control;
+
+ // Only count for captures from desktop media picker dialog and system loop
+ // back audio.
+ if (entry->controller.get() && type == MEDIA_DESKTOP_AUDIO_CAPTURE &&
+ device_id == media::AudioManagerBase::kLoopbackInputDeviceId) {
+ IncrementDesktopCaptureCounter(SYSTEM_LOOPBACK_AUDIO_CAPTURER_CREATED);
+ }
}
if (!entry->controller.get()) {
@@ -483,6 +486,10 @@ void AudioInputRendererHost::DoCreateStream(
}
#endif
+#if defined(ENABLE_WEBRTC)
+ entry->audio_params = audio_params;
+#endif // ENABLE_WEBRTC
+
MediaStreamManager::SendMessageToNativeLog(oss.str());
DVLOG(1) << oss.str();
@@ -594,7 +601,7 @@ void AudioInputRendererHost::DeleteEntry(AudioEntry* entry) {
#endif
// Delete the entry when this method goes out of scope.
- scoped_ptr<AudioEntry> entry_deleter(entry);
+ std::unique_ptr<AudioEntry> entry_deleter(entry);
// Erase the entry from the map.
audio_entries_.erase(entry->stream_id);
@@ -705,7 +712,8 @@ void AudioInputRendererHost::DoEnableDebugRecording(
base::Bind(&CloseFile, Passed(std::move(file))));
return;
}
- entry->input_debug_writer.reset(new AudioInputDebugWriter(std::move(file)));
+ entry->input_debug_writer.reset(
+ new AudioInputDebugWriter(std::move(file), entry->audio_params));
entry->controller->EnableDebugRecording(entry->input_debug_writer.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 dd549965446..cd6ed9db082 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
@@ -24,15 +24,15 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_INPUT_RENDERER_HOST_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_INPUT_RENDERER_HOST_H_
+#include <stdint.h>
+
#include <map>
+#include <memory>
#include <string>
-#include <stdint.h>
-
#include "base/compiler_specific.h"
#include "base/macros.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/sequenced_task_runner_helpers.h"
@@ -259,7 +259,7 @@ class CONTENT_EXPORT AudioInputRendererHost
// Raw pointer of the UserInputMonitor.
media::UserInputMonitor* user_input_monitor_;
- scoped_ptr<media::AudioLog> audio_log_;
+ std::unique_ptr<media::AudioLog> audio_log_;
base::WeakPtrFactory<AudioInputRendererHost> weak_factory_;
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 1ddc66c1e29..caa326127b6 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
@@ -61,9 +61,9 @@ AudioInputSyncWriter::AudioInputSyncWriter(void* shared_memory,
CHECK_EQ(0U, reinterpret_cast<uintptr_t>(ptr) &
(AudioBus::kChannelAlignment - 1));
AudioInputBuffer* buffer = reinterpret_cast<AudioInputBuffer*>(ptr);
- scoped_ptr<AudioBus> audio_bus =
+ std::unique_ptr<AudioBus> audio_bus =
AudioBus::WrapMemory(params, buffer->audio);
- audio_buses_.push_back(audio_bus.release());
+ audio_buses_.push_back(std::move(audio_bus));
ptr += shared_memory_segment_size_;
}
}
@@ -132,7 +132,8 @@ void AudioInputSyncWriter::Write(const AudioBus* data,
// writing. We verify that each buffer index is in sequence.
size_t number_of_indices_available = socket_->Peek() / sizeof(uint32_t);
if (number_of_indices_available > 0) {
- scoped_ptr<uint32_t[]> indices(new uint32_t[number_of_indices_available]);
+ std::unique_ptr<uint32_t[]> indices(
+ new uint32_t[number_of_indices_available]);
size_t bytes_received = socket_->Receive(
&indices[0],
number_of_indices_available * sizeof(indices[0]));
@@ -249,10 +250,10 @@ bool AudioInputSyncWriter::PushDataToFifo(const AudioBus* data,
overflow_params_.push_back(params);
// Push audio data to fifo.
- scoped_ptr<AudioBus> audio_bus =
+ std::unique_ptr<AudioBus> audio_bus =
AudioBus::Create(data->channels(), data->frames());
data->CopyTo(audio_bus.get());
- overflow_buses_.push_back(audio_bus.release());
+ overflow_buses_.push_back(std::move(audio_bus));
DCHECK_LE(overflow_buses_.size(), static_cast<size_t>(kMaxOverflowBusesSize));
DCHECK_EQ(overflow_params_.size(), overflow_buses_.size());
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 8429e44ee73..432901633fe 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
@@ -59,7 +59,7 @@ class CONTENT_EXPORT AudioInputSyncWriter
protected:
// Socket for transmitting audio data.
- scoped_ptr<base::CancelableSyncSocket> socket_;
+ std::unique_ptr<base::CancelableSyncSocket> socket_;
private:
friend class AudioInputSyncWriterTest;
@@ -107,7 +107,7 @@ class CONTENT_EXPORT AudioInputSyncWriter
// Socket to be used by the renderer. The reference is released after
// PrepareForeignSocketHandle() is called and ran successfully.
- scoped_ptr<base::CancelableSyncSocket> foreign_socket_;
+ std::unique_ptr<base::CancelableSyncSocket> foreign_socket_;
// The time of the creation of this object.
base::Time creation_time_;
diff --git a/chromium/content/browser/renderer_host/media/audio_input_sync_writer_unittest.cc b/chromium/content/browser/renderer_host/media/audio_input_sync_writer_unittest.cc
index d691b22d342..0fdf34203ce 100644
--- a/chromium/content/browser/renderer_host/media/audio_input_sync_writer_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/audio_input_sync_writer_unittest.cc
@@ -2,16 +2,18 @@
// 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/audio_input_sync_writer.h"
+
#include <stddef.h>
#include <stdint.h>
+#include <memory>
+
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/sync_socket.h"
#include "base/time/time.h"
#include "build/build_config.h"
-#include "content/browser/renderer_host/media/audio_input_sync_writer.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "media/audio/audio_parameters.h"
#include "media/base/audio_bus.h"
@@ -181,9 +183,9 @@ class AudioInputSyncWriterTest : public testing::Test {
}
protected:
- scoped_ptr<AudioInputSyncWriterUnderTest> writer_;
+ std::unique_ptr<AudioInputSyncWriterUnderTest> writer_;
MockCancelableSyncSocket* socket_;
- scoped_ptr<AudioBus> audio_bus_;
+ std::unique_ptr<AudioBus> audio_bus_;
private:
TestBrowserThreadBundle thread_bundle_;
diff --git a/chromium/content/browser/renderer_host/media/audio_output_device_enumerator.cc b/chromium/content/browser/renderer_host/media/audio_output_device_enumerator.cc
index 54c05311e1f..24ef8f9ec2e 100644
--- a/chromium/content/browser/renderer_host/media/audio_output_device_enumerator.cc
+++ b/chromium/content/browser/renderer_host/media/audio_output_device_enumerator.cc
@@ -17,7 +17,7 @@ namespace {
AudioOutputDeviceEnumeration EnumerateDevicesOnDeviceThread(
media::AudioManager* audio_manager) {
- DCHECK(audio_manager->GetWorkerTaskRunner()->BelongsToCurrentThread());
+ DCHECK(audio_manager->GetTaskRunner()->BelongsToCurrentThread());
AudioOutputDeviceEnumeration snapshot;
media::AudioDeviceNames device_names;
@@ -54,6 +54,9 @@ AudioOutputDeviceEnumeration::AudioOutputDeviceEnumeration(
AudioOutputDeviceEnumeration::AudioOutputDeviceEnumeration()
: has_actual_devices(false) {}
+AudioOutputDeviceEnumeration::AudioOutputDeviceEnumeration(
+ const AudioOutputDeviceEnumeration& other) = default;
+
AudioOutputDeviceEnumeration::~AudioOutputDeviceEnumeration() {}
AudioOutputDeviceEnumerator::AudioOutputDeviceEnumerator(
@@ -114,7 +117,7 @@ void AudioOutputDeviceEnumerator::DoEnumerateDevices() {
is_enumeration_ongoing_ = true;
seq_last_enumeration_ = NewEventSequence();
base::PostTaskAndReplyWithResult(
- audio_manager_->GetWorkerTaskRunner().get(), FROM_HERE,
+ audio_manager_->GetTaskRunner().get(), FROM_HERE,
base::Bind(&EnumerateDevicesOnDeviceThread, audio_manager_),
base::Bind(&AudioOutputDeviceEnumerator::DevicesEnumerated,
weak_factory_.GetWeakPtr()));
diff --git a/chromium/content/browser/renderer_host/media/audio_output_device_enumerator.h b/chromium/content/browser/renderer_host/media/audio_output_device_enumerator.h
index bf223a9bccd..1de0ea8074f 100644
--- a/chromium/content/browser/renderer_host/media/audio_output_device_enumerator.h
+++ b/chromium/content/browser/renderer_host/media/audio_output_device_enumerator.h
@@ -12,13 +12,14 @@
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_OUTPUT_DEVICE_ENUMERATOR_H_
#include <stdint.h>
+
#include <list>
+#include <memory>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
@@ -50,6 +51,7 @@ struct AudioOutputDeviceEnumeration {
const std::vector<AudioOutputDeviceInfo>& devices,
bool has_actual_devices);
AudioOutputDeviceEnumeration();
+ AudioOutputDeviceEnumeration(const AudioOutputDeviceEnumeration& other);
~AudioOutputDeviceEnumeration();
std::vector<AudioOutputDeviceInfo> devices;
diff --git a/chromium/content/browser/renderer_host/media/audio_output_device_enumerator_unittest.cc b/chromium/content/browser/renderer_host/media/audio_output_device_enumerator_unittest.cc
index ac6140cbb01..f84f87e2bd0 100644
--- a/chromium/content/browser/renderer_host/media/audio_output_device_enumerator_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/audio_output_device_enumerator_unittest.cc
@@ -2,18 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "content/browser/renderer_host/media/audio_output_device_enumerator.h"
+
+#include <memory>
#include <string>
#include "base/bind.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/thread_task_runner_handle.h"
-#include "content/browser/renderer_host/media/audio_output_device_enumerator.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "media/audio/audio_manager_base.h"
#include "media/audio/fake_audio_log_factory.h"
@@ -118,7 +119,7 @@ class AudioOutputDeviceEnumeratorTest : public ::testing::Test {
}
protected:
- scoped_ptr<MockAudioManager> audio_manager_;
+ std::unique_ptr<MockAudioManager> audio_manager_;
TestBrowserThreadBundle thread_bundle_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
base::RunLoop run_loop_;
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 d469d342433..20d5215bb5a 100644
--- a/chromium/content/browser/renderer_host/media/audio_renderer_host.cc
+++ b/chromium/content/browser/renderer_host/media/audio_renderer_host.cc
@@ -17,7 +17,6 @@
#include "content/browser/bad_message.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/media/audio_stream_monitor.h"
#include "content/browser/media/capture/audio_mirroring_manager.h"
#include "content/browser/media/media_internals.h"
@@ -31,7 +30,6 @@
#include "content/public/browser/media_device_id.h"
#include "content/public/browser/media_observer.h"
#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/render_view_host.h"
#include "content/public/common/content_switches.h"
#include "media/audio/audio_device_name.h"
#include "media/audio/audio_manager_base.h"
@@ -51,34 +49,6 @@ namespace {
base::LazyInstance<media::AudioStreamsTracker> g_audio_streams_tracker =
LAZY_INSTANCE_INITIALIZER;
-// TODO(aiolos): This is a temporary hack until the resource scheduler is
-// migrated to RenderFrames for the Site Isolation project. It's called in
-// response to low frequency playback state changes. http://crbug.com/472869
-int RenderFrameIdToRenderViewId(int render_process_id, int render_frame_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- RenderFrameHost* const frame =
- RenderFrameHost::FromID(render_process_id, render_frame_id);
- return frame ? frame->GetRenderViewHost()->GetRoutingID() : MSG_ROUTING_NONE;
-}
-
-void NotifyResourceDispatcherOfAudioStateChange(int render_process_id,
- bool is_playing,
- int render_view_id) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (render_view_id == MSG_ROUTING_NONE || !ResourceDispatcherHostImpl::Get())
- return;
-
- ResourceDispatcherHostImpl::Get()->OnAudioRenderHostStreamStateChanged(
- render_process_id, render_view_id, is_playing);
-}
-
-media::AudioParameters DummyParams() {
- return media::AudioParameters(
- media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO,
- media::AudioParameters::kAudioCDSampleRate, 16,
- media::AudioParameters::kAudioCDSampleRate / 10);
-}
-
std::pair<int, std::pair<bool, std::string>> MakeAuthorizationData(
int stream_id,
bool authorized,
@@ -118,7 +88,7 @@ bool IsDefaultDeviceId(const std::string& device_id) {
AudioOutputDeviceInfo GetDefaultDeviceInfoOnDeviceThread(
media::AudioManager* audio_manager) {
- DCHECK(audio_manager->GetWorkerTaskRunner()->BelongsToCurrentThread());
+ DCHECK(audio_manager->GetTaskRunner()->BelongsToCurrentThread());
AudioOutputDeviceInfo default_device_info = {
media::AudioManagerBase::kDefaultDeviceId,
audio_manager->GetDefaultDeviceName(),
@@ -147,7 +117,7 @@ void MaybeFixAudioParameters(media::AudioParameters* params) {
// If hardware parameters are still invalid, use dummy parameters with
// fake audio path and let the client handle the error.
if (!params->IsValid())
- *params = DummyParams();
+ *params = media::AudioParameters::UnavailableDeviceParams();
}
} // namespace
@@ -160,8 +130,8 @@ class AudioRendererHost::AudioEntry
int render_frame_id,
const media::AudioParameters& params,
const std::string& output_device_id,
- scoped_ptr<base::SharedMemory> shared_memory,
- scoped_ptr<media::AudioOutputController::SyncReader> reader);
+ std::unique_ptr<base::SharedMemory> shared_memory,
+ std::unique_ptr<media::AudioOutputController::SyncReader> reader);
~AudioEntry() override;
int stream_id() const {
@@ -197,10 +167,10 @@ class AudioRendererHost::AudioEntry
const int render_frame_id_;
// Shared memory for transmission of the audio data. Used by |reader_|.
- const scoped_ptr<base::SharedMemory> shared_memory_;
+ const std::unique_ptr<base::SharedMemory> shared_memory_;
// The synchronous reader to be used by |controller_|.
- const scoped_ptr<media::AudioOutputController::SyncReader> reader_;
+ const std::unique_ptr<media::AudioOutputController::SyncReader> reader_;
// The AudioOutputController that manages the audio stream.
const scoped_refptr<media::AudioOutputController> controller_;
@@ -214,8 +184,8 @@ AudioRendererHost::AudioEntry::AudioEntry(
int render_frame_id,
const media::AudioParameters& params,
const std::string& output_device_id,
- scoped_ptr<base::SharedMemory> shared_memory,
- scoped_ptr<media::AudioOutputController::SyncReader> reader)
+ std::unique_ptr<base::SharedMemory> shared_memory,
+ std::unique_ptr<media::AudioOutputController::SyncReader> reader)
: host_(host),
stream_id_(stream_id),
render_frame_id_(render_frame_id),
@@ -450,7 +420,8 @@ void AudioRendererHost::OnRequestDeviceAuthorization(
if (!IsValidDeviceId(device_id)) {
Send(new AudioMsg_NotifyDeviceAuthorized(
- stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND, DummyParams()));
+ stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
+ media::AudioParameters::UnavailableDeviceParams()));
return;
}
@@ -505,7 +476,7 @@ void AudioRendererHost::OnDeviceAuthorized(int stream_id,
authorizations_.erase(auth_data);
Send(new AudioMsg_NotifyDeviceAuthorized(
stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_AUTHORIZED,
- DummyParams()));
+ media::AudioParameters::UnavailableDeviceParams()));
return;
}
@@ -517,7 +488,7 @@ void AudioRendererHost::OnDeviceAuthorized(int stream_id,
!media_stream_manager_->audio_output_device_enumerator()
->IsCacheEnabled()) {
base::PostTaskAndReplyWithResult(
- audio_manager_->GetWorkerTaskRunner().get(), FROM_HERE,
+ audio_manager_->GetTaskRunner().get(), FROM_HERE,
base::Bind(&GetDefaultDeviceInfoOnDeviceThread, audio_manager_),
base::Bind(&AudioRendererHost::OnDeviceIDTranslated, this, stream_id,
true));
@@ -544,7 +515,8 @@ void AudioRendererHost::OnDeviceIDTranslated(
if (!device_found) {
authorizations_.erase(auth_data);
Send(new AudioMsg_NotifyDeviceAuthorized(
- stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND, DummyParams()));
+ stream_id, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND,
+ media::AudioParameters::UnavailableDeviceParams()));
return;
}
@@ -592,13 +564,13 @@ void AudioRendererHost::DoCreateStream(int stream_id,
// Create the shared memory and share with the renderer process.
uint32_t shared_memory_size = sizeof(media::AudioOutputBufferParameters) +
AudioBus::CalculateMemorySize(params);
- scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
+ std::unique_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
if (!shared_memory->CreateAndMapAnonymous(shared_memory_size)) {
SendErrorMessage(stream_id);
return;
}
- scoped_ptr<AudioSyncReader> reader(
+ std::unique_ptr<AudioSyncReader> reader(
new AudioSyncReader(shared_memory.get(), params));
if (!reader->Init()) {
SendErrorMessage(stream_id);
@@ -610,7 +582,7 @@ void AudioRendererHost::DoCreateStream(int stream_id,
if (media_observer)
media_observer->OnCreatingAudioStream(render_process_id_, render_frame_id);
- scoped_ptr<AudioEntry> entry(
+ std::unique_ptr<AudioEntry> entry(
new AudioEntry(this, stream_id, render_frame_id, params, device_unique_id,
std::move(shared_memory), std::move(reader)));
if (mirroring_manager_) {
@@ -684,7 +656,7 @@ void AudioRendererHost::OnCloseStream(int stream_id) {
AudioEntryMap::iterator i = audio_entries_.find(stream_id);
if (i == audio_entries_.end())
return;
- scoped_ptr<AudioEntry> entry(i->second);
+ std::unique_ptr<AudioEntry> entry(i->second);
audio_entries_.erase(i);
g_audio_streams_tracker.Get().DecreaseStreamCount();
@@ -694,7 +666,7 @@ void AudioRendererHost::OnCloseStream(int stream_id) {
audio_log_->OnClosed(stream_id);
}
-void AudioRendererHost::DeleteEntry(scoped_ptr<AudioEntry> entry) {
+void AudioRendererHost::DeleteEntry(std::unique_ptr<AudioEntry> entry) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// De-register the controller from the AudioMirroringManager now that the
@@ -738,10 +710,7 @@ void AudioRendererHost::UpdateNumPlayingStreams(AudioEntry* entry,
if (entry->playing() == is_playing)
return;
- bool should_alert_resource_scheduler;
if (is_playing) {
- should_alert_resource_scheduler =
- !RenderFrameHasActiveAudio(entry->render_frame_id());
entry->set_playing(true);
base::AtomicRefCountInc(&num_playing_streams_);
@@ -755,9 +724,6 @@ void AudioRendererHost::UpdateNumPlayingStreams(AudioEntry* entry,
}
} else {
entry->set_playing(false);
- should_alert_resource_scheduler =
- !RenderFrameHasActiveAudio(entry->render_frame_id());
-
// Inform the RenderProcessHost when there is no more audio playing.
if (!base::AtomicRefCountDec(&num_playing_streams_)) {
BrowserThread::PostTask(
@@ -766,15 +732,6 @@ void AudioRendererHost::UpdateNumPlayingStreams(AudioEntry* entry,
render_process_id_));
}
}
-
- if (should_alert_resource_scheduler && ResourceDispatcherHostImpl::Get()) {
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&RenderFrameIdToRenderViewId, render_process_id_,
- entry->render_frame_id()),
- base::Bind(&NotifyResourceDispatcherOfAudioStateChange,
- render_process_id_, is_playing));
- }
}
bool AudioRendererHost::HasActiveAudio() {
@@ -799,10 +756,9 @@ void AudioRendererHost::CheckOutputDeviceAccess(
const OutputDeviceAccessCB& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // Skip origin check in requests for the default device with an empty
- // security origin.
- bool skip_origin_check = gurl_security_origin.is_empty() && device_id.empty();
- if (!skip_origin_check &&
+ // Check security origin if nondefault device is requested.
+ // Ignore check for default device, which is always authorized.
+ if (!IsDefaultDeviceId(device_id) &&
!ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(
render_process_id_, gurl_security_origin)) {
content::bad_message::ReceivedBadMessage(this,
@@ -815,7 +771,7 @@ void AudioRendererHost::CheckOutputDeviceAccess(
} else {
// Check that MediaStream device permissions have been granted,
// hence the use of a MediaStreamUIProxy.
- scoped_ptr<MediaStreamUIProxy> ui_proxy = MediaStreamUIProxy::Create();
+ std::unique_ptr<MediaStreamUIProxy> ui_proxy = MediaStreamUIProxy::Create();
// Use MEDIA_DEVICE_AUDIO_CAPTURE instead of MEDIA_DEVICE_AUDIO_OUTPUT
// because MediaStreamUIProxy::CheckAccess does not currently support
@@ -829,9 +785,10 @@ void AudioRendererHost::CheckOutputDeviceAccess(
}
}
-void AudioRendererHost::AccessChecked(scoped_ptr<MediaStreamUIProxy> ui_proxy,
- const OutputDeviceAccessCB& callback,
- bool have_access) {
+void AudioRendererHost::AccessChecked(
+ std::unique_ptr<MediaStreamUIProxy> ui_proxy,
+ const OutputDeviceAccessCB& callback,
+ bool have_access) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
callback.Run(have_access);
}
@@ -856,8 +813,9 @@ void AudioRendererHost::TranslateDeviceID(
}
}
DCHECK(!device_id.empty()); // Default device must always be found
- AudioOutputDeviceInfo device_info = {std::string(), std::string(),
- DummyParams()};
+ AudioOutputDeviceInfo device_info = {
+ std::string(), std::string(),
+ media::AudioParameters::UnavailableDeviceParams()};
callback.Run(false, device_info);
}
diff --git a/chromium/content/browser/renderer_host/media/audio_renderer_host.h b/chromium/content/browser/renderer_host/media/audio_renderer_host.h
index e549df20cc9..b4e9d3f329a 100644
--- a/chromium/content/browser/renderer_host/media/audio_renderer_host.h
+++ b/chromium/content/browser/renderer_host/media/audio_renderer_host.h
@@ -40,17 +40,17 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_RENDERER_HOST_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_AUDIO_RENDERER_HOST_H_
+#include <stddef.h>
+
#include <map>
+#include <memory>
#include <string>
#include <utility>
-#include <stddef.h>
-
#include "base/atomic_ref_count.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/process/process.h"
#include "base/sequenced_task_runner_helpers.h"
#include "content/browser/renderer_host/media/audio_output_device_enumerator.h"
@@ -203,7 +203,7 @@ class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter {
// Delete an audio entry, notifying observers first. This is called by
// AudioOutputController after it has closed.
- void DeleteEntry(scoped_ptr<AudioEntry> entry);
+ void DeleteEntry(std::unique_ptr<AudioEntry> entry);
// Send an error message to the renderer, then close the stream.
void ReportErrorAndClose(int stream_id);
@@ -223,7 +223,7 @@ class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter {
const OutputDeviceAccessCB& callback);
// Invoke |callback| after permission to use a device has been checked.
- void AccessChecked(scoped_ptr<MediaStreamUIProxy> ui_proxy,
+ void AccessChecked(std::unique_ptr<MediaStreamUIProxy> ui_proxy,
const OutputDeviceAccessCB& callback,
bool have_access);
@@ -242,7 +242,7 @@ class CONTENT_EXPORT AudioRendererHost : public BrowserMessageFilter {
media::AudioManager* const audio_manager_;
AudioMirroringManager* const mirroring_manager_;
- scoped_ptr<media::AudioLog> audio_log_;
+ std::unique_ptr<media::AudioLog> audio_log_;
// Used to access to AudioInputDeviceManager.
MediaStreamManager* media_stream_manager_;
diff --git a/chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc b/chromium/content/browser/renderer_host/media/audio_renderer_host_unittest.cc
index 396d9239507..3e3b4f3d40c 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
@@ -2,18 +2,20 @@
// 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/audio_renderer_host.h"
+
#include <stdint.h>
+#include <memory>
+
#include "base/bind.h"
#include "base/command_line.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "base/sync_socket.h"
#include "content/browser/media/capture/audio_mirroring_manager.h"
#include "content/browser/media/media_internals.h"
#include "content/browser/renderer_host/media/audio_input_device_manager.h"
-#include "content/browser/renderer_host/media/audio_renderer_host.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/common/media/audio_messages.h"
#include "content/public/common/content_switches.h"
@@ -157,8 +159,8 @@ class MockAudioRendererHost : public AudioRendererHost {
}
}
- scoped_ptr<base::SharedMemory> shared_memory_;
- scoped_ptr<base::SyncSocket> sync_socket_;
+ std::unique_ptr<base::SharedMemory> shared_memory_;
+ std::unique_ptr<base::SyncSocket> sync_socket_;
uint32_t shared_memory_length_;
DISALLOW_COPY_AND_ASSIGN(MockAudioRendererHost);
@@ -217,7 +219,9 @@ class AudioRendererHostTest : public testing::Test {
}
protected:
- void Create() { Create(false, kDefaultDeviceId, url::Origin()); }
+ void Create() {
+ Create(false, kDefaultDeviceId, url::Origin(GURL(kSecurityOrigin)));
+ }
void Create(bool unified_stream,
const std::string& device_id,
@@ -319,9 +323,9 @@ class AudioRendererHostTest : public testing::Test {
private:
// MediaStreamManager uses a DestructionObserver, so it must outlive the
// TestBrowserThreadBundle.
- scoped_ptr<MediaStreamManager> media_stream_manager_;
+ std::unique_ptr<MediaStreamManager> media_stream_manager_;
TestBrowserThreadBundle thread_bundle_;
- scoped_ptr<media::AudioManager> audio_manager_;
+ std::unique_ptr<media::AudioManager> audio_manager_;
MockAudioMirroringManager mirroring_manager_;
scoped_refptr<MockAudioRendererHost> host_;
@@ -389,7 +393,7 @@ TEST_F(AudioRendererHostTest, SimulateErrorAndClose) {
}
TEST_F(AudioRendererHostTest, CreateUnifiedStreamAndClose) {
- Create(true, kDefaultDeviceId, url::Origin());
+ Create(true, kDefaultDeviceId, url::Origin(GURL(kSecurityOrigin)));
Close();
}
diff --git a/chromium/content/browser/renderer_host/media/audio_sync_reader.cc b/chromium/content/browser/renderer_host/media/audio_sync_reader.cc
index 85b13f8453c..af94822adae 100644
--- a/chromium/content/browser/renderer_host/media/audio_sync_reader.cc
+++ b/chromium/content/browser/renderer_host/media/audio_sync_reader.cc
@@ -46,6 +46,7 @@ AudioSyncReader::AudioSyncReader(base::SharedMemory* shared_memory,
packet_size_(shared_memory_->requested_size()),
renderer_callback_count_(0),
renderer_missed_callback_count_(0),
+ trailing_renderer_missed_callback_count_(0),
#if defined(OS_MACOSX)
maximum_wait_time_(params.GetBufferDuration() / 2),
#else
@@ -66,6 +67,24 @@ AudioSyncReader::~AudioSyncReader() {
if (!renderer_callback_count_)
return;
+ DVLOG(1) << "Trailing glitch count on destruction: "
+ << trailing_renderer_missed_callback_count_;
+
+ // Subtract 'trailing' count of callbacks missed just before the destructor
+ // call. This happens if the renderer process was killed or e.g. the page
+ // refreshed while the output device was open etc.
+ // This trims off the end of both the missed and total counts so that we
+ // preserve the proportion of counts before the teardown period.
+ DCHECK_LE(trailing_renderer_missed_callback_count_,
+ renderer_missed_callback_count_);
+ DCHECK_LE(trailing_renderer_missed_callback_count_, renderer_callback_count_);
+
+ renderer_missed_callback_count_ -= trailing_renderer_missed_callback_count_;
+ renderer_callback_count_ -= trailing_renderer_missed_callback_count_;
+
+ if (!renderer_callback_count_)
+ return;
+
// Recording the percentage of deadline misses gives us a rough overview of
// how many users might be running into audio glitches.
int percentage_missed =
@@ -107,6 +126,7 @@ void AudioSyncReader::UpdatePendingBytes(uint32_t bytes,
void AudioSyncReader::Read(AudioBus* dest) {
++renderer_callback_count_;
if (!WaitUntilDataIsReady()) {
+ ++trailing_renderer_missed_callback_count_;
++renderer_missed_callback_count_;
if (renderer_missed_callback_count_ <= 100) {
LOG(WARNING) << "AudioSyncReader::Read timed out, audio glitch count="
@@ -118,6 +138,8 @@ void AudioSyncReader::Read(AudioBus* dest) {
return;
}
+ trailing_renderer_missed_callback_count_ = 0;
+
if (mute_audio_)
dest->Zero();
else
diff --git a/chromium/content/browser/renderer_host/media/audio_sync_reader.h b/chromium/content/browser/renderer_host/media/audio_sync_reader.h
index 6e07e5129b6..05c68e9d2c1 100644
--- a/chromium/content/browser/renderer_host/media/audio_sync_reader.h
+++ b/chromium/content/browser/renderer_host/media/audio_sync_reader.h
@@ -59,14 +59,14 @@ class AudioSyncReader : public media::AudioOutputController::SyncReader {
const bool mute_audio_;
// Socket for transmitting audio data.
- scoped_ptr<base::CancelableSyncSocket> socket_;
+ std::unique_ptr<base::CancelableSyncSocket> socket_;
// Socket to be used by the renderer. The reference is released after
// PrepareForeignSocketHandle() is called and ran successfully.
- scoped_ptr<base::CancelableSyncSocket> foreign_socket_;
+ std::unique_ptr<base::CancelableSyncSocket> foreign_socket_;
// Shared memory wrapper used for transferring audio data to Read() callers.
- scoped_ptr<media::AudioBus> output_bus_;
+ std::unique_ptr<media::AudioBus> output_bus_;
// Maximum amount of audio data which can be transferred in one Read() call.
const int packet_size_;
@@ -75,6 +75,7 @@ class AudioSyncReader : public media::AudioOutputController::SyncReader {
// report a UMA stat during destruction.
size_t renderer_callback_count_;
size_t renderer_missed_callback_count_;
+ size_t trailing_renderer_missed_callback_count_;
// The maximum amount of time to wait for data from the renderer. Calculated
// from the parameters given at construction.
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 9fee099443a..0c18286db4f 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
@@ -288,7 +288,7 @@ class MediaStreamDispatcherHostTest : public testing::Test {
EXPECT_CALL(*stream_ui_, OnStarted(_, _));
}
media_stream_manager_->UseFakeUIForTests(
- scoped_ptr<FakeMediaStreamUIProxy>(stream_ui_));
+ std::unique_ptr<FakeMediaStreamUIProxy>(stream_ui_));
}
void GenerateStreamAndWaitForResult(int render_frame_id,
@@ -422,11 +422,11 @@ class MediaStreamDispatcherHostTest : public testing::Test {
}
scoped_refptr<MockMediaStreamDispatcherHost> host_;
- scoped_ptr<media::AudioManager> audio_manager_;
- scoped_ptr<MediaStreamManager> media_stream_manager_;
+ std::unique_ptr<media::AudioManager> audio_manager_;
+ std::unique_ptr<MediaStreamManager> media_stream_manager_;
MockMediaStreamUIProxy* stream_ui_;
ContentBrowserClient* old_browser_client_;
- scoped_ptr<ContentClient> content_client_;
+ std::unique_ptr<ContentClient> content_client_;
content::TestBrowserThreadBundle thread_bundle_;
content::TestBrowserContext browser_context_;
media::AudioDeviceNames physical_audio_devices_;
@@ -846,7 +846,8 @@ TEST_F(MediaStreamDispatcherHostTest, CloseFromUI) {
StreamControls controls(false, true);
base::Closure close_callback;
- scoped_ptr<MockMediaStreamUIProxy> stream_ui(new MockMediaStreamUIProxy());
+ std::unique_ptr<MockMediaStreamUIProxy> stream_ui(
+ new MockMediaStreamUIProxy());
EXPECT_CALL(*stream_ui, OnStarted(_, _))
.WillOnce(SaveArg<0>(&close_callback));
media_stream_manager_->UseFakeUIForTests(std::move(stream_ui));
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 f602e8d26b1..6d1f005d298 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager.cc
@@ -24,6 +24,7 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
+#include "base/task_runner_util.h"
#include "base/threading/thread.h"
#include "base/threading/thread_local.h"
#include "build/build_config.h"
@@ -37,6 +38,7 @@
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/desktop_media_id.h"
#include "content/public/browser/media_observer.h"
#include "content/public/browser/media_request_state.h"
#include "content/public/browser/render_process_host.h"
@@ -60,18 +62,15 @@
#include "chromeos/audio/cras_audio_handler.h"
#endif
+#if defined(OS_MACOSX)
+#include "media/capture/device_monitor_mac.h"
+#endif
+
namespace content {
base::LazyInstance<base::ThreadLocalPointer<MediaStreamManager>>::Leaky
g_media_stream_manager_tls_ptr = LAZY_INSTANCE_INITIALIZER;
-// Forward declaration of DeviceMonitorMac and its only useable method.
-class DeviceMonitorMac {
- public:
- void StartMonitoring(
- const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner);
-};
-
namespace {
// Creates a random label used to identify requests.
std::string RandomLabel() {
@@ -99,6 +98,9 @@ void ParseStreamType(const StreamControls& controls,
MediaStreamType* video_type) {
*audio_type = MEDIA_NO_SERVICE;
*video_type = MEDIA_NO_SERVICE;
+ const bool audio_support_flag_for_desktop_share =
+ !base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableAudioSupportForDesktopShare);
if (controls.audio.requested) {
if (!controls.audio.stream_source.empty()) {
// This is tab or screen capture.
@@ -106,6 +108,9 @@ void ParseStreamType(const StreamControls& controls,
*audio_type = content::MEDIA_TAB_AUDIO_CAPTURE;
} else if (controls.audio.stream_source == kMediaStreamSourceSystem) {
*audio_type = content::MEDIA_DESKTOP_AUDIO_CAPTURE;
+ } else if (audio_support_flag_for_desktop_share &&
+ controls.audio.stream_source == kMediaStreamSourceDesktop) {
+ *audio_type = content::MEDIA_DESKTOP_AUDIO_CAPTURE;
}
} else {
// This is normal audio device capture.
@@ -278,7 +283,7 @@ class MediaStreamManager::DeviceRequest {
}
bool HasUIRequest() const { return ui_request_.get() != nullptr; }
- scoped_ptr<MediaStreamRequest> DetachUIRequest() {
+ std::unique_ptr<MediaStreamRequest> DetachUIRequest() {
return std::move(ui_request_);
}
@@ -342,13 +347,13 @@ class MediaStreamManager::DeviceRequest {
// Currently it is only used by |DEVICE_ACCESS| type.
MediaStreamManager::MediaRequestResponseCallback callback;
- scoped_ptr<MediaStreamUIProxy> ui_proxy;
+ std::unique_ptr<MediaStreamUIProxy> ui_proxy;
std::string tab_capture_device_id;
private:
std::vector<MediaRequestState> state_;
- scoped_ptr<MediaStreamRequest> ui_request_;
+ std::unique_ptr<MediaStreamRequest> ui_request_;
MediaStreamType audio_type_;
MediaStreamType video_type_;
int target_process_id_;
@@ -948,9 +953,9 @@ void MediaStreamManager::StartMonitoringOnUIThread() {
// fixed.
tracked_objects::ScopedTracker tracking_profile2(
FROM_HERE_WITH_EXPLICIT_FUNCTION(
- "458404 MediaStreamManager::GetWorkerTaskRunner"));
+ "458404 MediaStreamManager::GetTaskRunner"));
const scoped_refptr<base::SingleThreadTaskRunner> task_runner =
- audio_manager_->GetWorkerTaskRunner();
+ audio_manager_->GetTaskRunner();
// TODO(erikchen): Remove ScopedTracker below once crbug.com/458404 is
// fixed.
tracked_objects::ScopedTracker tracking_profile3(
@@ -1101,7 +1106,7 @@ void MediaStreamManager::DeleteRequest(const std::string& label) {
for (DeviceRequests::iterator request_it = requests_.begin();
request_it != requests_.end(); ++request_it) {
if (request_it->first == label) {
- scoped_ptr<DeviceRequest> request(request_it->second);
+ std::unique_ptr<DeviceRequest> request(request_it->second);
requests_.erase(request_it);
return;
}
@@ -1109,8 +1114,34 @@ void MediaStreamManager::DeleteRequest(const std::string& label) {
NOTREACHED();
}
-void MediaStreamManager::PostRequestToUI(const std::string& label,
- DeviceRequest* request) {
+void MediaStreamManager::ReadOutputParamsAndPostRequestToUI(
+ const std::string& label,
+ DeviceRequest* request) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // Actual audio parameters are required only for MEDIA_TAB_AUDIO_CAPTURE.
+ // TODO(guidou): MEDIA_TAB_AUDIO_CAPTURE should not be a special case. See
+ // crbug.com/584287.
+ if (request->audio_type() == MEDIA_TAB_AUDIO_CAPTURE) {
+ // Read output parameters on the correct thread for native audio OS calls.
+ // Using base::Unretained is safe since |audio_manager_| is deleted after
+ // its task runner, and MediaStreamManager is deleted on the UI thread,
+ // after the IO thread has been stopped.
+ base::PostTaskAndReplyWithResult(
+ audio_manager_->GetTaskRunner().get(), FROM_HERE,
+ base::Bind(&media::AudioManager::GetDefaultOutputStreamParameters,
+ base::Unretained(audio_manager_)),
+ base::Bind(&MediaStreamManager::PostRequestToUI, base::Unretained(this),
+ label, request));
+ } else {
+ PostRequestToUI(label, request, media::AudioParameters());
+ }
+}
+
+void MediaStreamManager::PostRequestToUI(
+ const std::string& label,
+ DeviceRequest* request,
+ const media::AudioParameters& output_parameters) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(request->HasUIRequest());
DVLOG(1) << "PostRequestToUI({label= " << label << "})";
@@ -1124,7 +1155,10 @@ void MediaStreamManager::PostRequestToUI(const std::string& label,
if (IsVideoMediaType(video_type))
request->SetState(video_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
- if (use_fake_ui_) {
+ // If using the fake UI, it will just auto-select from the available devices.
+ // The fake UI doesn't work for desktop sharing requests since we can't see
+ // its devices from here; always use the real UI for such requests.
+ if (use_fake_ui_ && request->video_type() != MEDIA_DESKTOP_VIDEO_CAPTURE) {
if (!fake_ui_)
fake_ui_.reset(new FakeMediaStreamUIProxy());
@@ -1152,7 +1186,7 @@ void MediaStreamManager::PostRequestToUI(const std::string& label,
request->ui_proxy->RequestAccess(
request->DetachUIRequest(),
base::Bind(&MediaStreamManager::HandleAccessRequestResponse,
- base::Unretained(this), label));
+ base::Unretained(this), label, output_parameters));
}
void MediaStreamManager::SetupRequest(const std::string& label) {
@@ -1221,7 +1255,7 @@ void MediaStreamManager::SetupRequest(const std::string& label) {
return;
}
}
- PostRequestToUI(label, request);
+ ReadOutputParamsAndPostRequestToUI(label, request);
}
bool MediaStreamManager::SetupDeviceCaptureRequest(DeviceRequest* request) {
@@ -1314,7 +1348,11 @@ bool MediaStreamManager::SetupScreenCaptureRequest(DeviceRequest* request) {
}
}
- request->CreateUIRequest("", video_device_id);
+ const std::string audio_device_id =
+ request->audio_type() == MEDIA_DESKTOP_AUDIO_CAPTURE ? video_device_id
+ : "";
+
+ request->CreateUIRequest(audio_device_id, video_device_id);
return true;
}
@@ -1527,7 +1565,7 @@ void MediaStreamManager::InitializeDeviceManagersOnIOThread() {
"457525 MediaStreamManager::InitializeDeviceManagersOnIOThread 1"));
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!device_task_runner_.get());
- device_task_runner_ = audio_manager_->GetWorkerTaskRunner();
+ device_task_runner_ = audio_manager_->GetTaskRunner();
// TODO(dalecurtis): Remove ScopedTracker below once crbug.com/457525 is
// fixed.
@@ -1728,7 +1766,7 @@ void MediaStreamManager::DevicesEnumerated(
if (!SetupDeviceCaptureRequest(request))
FinalizeRequestFailed(label, request, MEDIA_DEVICE_NO_HARDWARE);
else
- PostRequestToUI(label, request);
+ ReadOutputParamsAndPostRequestToUI(label, request);
break;
}
}
@@ -1754,7 +1792,7 @@ void MediaStreamManager::OnResume() {
}
void MediaStreamManager::UseFakeUIForTests(
- scoped_ptr<FakeMediaStreamUIProxy> fake_ui) {
+ std::unique_ptr<FakeMediaStreamUIProxy> fake_ui) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
use_fake_ui_ = true;
fake_ui_ = std::move(fake_ui);
@@ -1775,21 +1813,14 @@ void MediaStreamManager::UnregisterNativeLogCallback(int renderer_host_id) {
}
void MediaStreamManager::AddLogMessageOnIOThread(const std::string& message) {
- // Get render process ids on the IO thread.
DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
- for (const LabeledDeviceRequest& labeled_request : requests_) {
- DeviceRequest* const request = labeled_request.second;
- if (request->request_type == MEDIA_GENERATE_STREAM) {
- const auto& found = log_callbacks_.find(request->requesting_process_id);
- if (found != log_callbacks_.end())
- found->second.Run(message);
- }
- }
+ for (const auto& callback : log_callbacks_)
+ callback.second.Run(message);
}
void MediaStreamManager::HandleAccessRequestResponse(
const std::string& label,
+ const media::AudioParameters& output_parameters,
const MediaStreamDevices& devices,
content::MediaStreamRequestResult result) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -1824,29 +1855,27 @@ void MediaStreamManager::HandleAccessRequestResponse(
if (device_info.device.type == content::MEDIA_TAB_VIDEO_CAPTURE ||
device_info.device.type == content::MEDIA_TAB_AUDIO_CAPTURE) {
device_info.device.id = request->tab_capture_device_id;
+ }
- // Initialize the sample_rate and channel_layout here since for audio
- // mirroring, we don't go through EnumerateDevices where these are usually
- // initialized.
- if (device_info.device.type == content::MEDIA_TAB_AUDIO_CAPTURE) {
- const media::AudioParameters parameters =
- audio_manager_->GetDefaultOutputStreamParameters();
- int sample_rate = parameters.sample_rate();
- // If we weren't able to get the native sampling rate or the sample_rate
- // is outside the valid range for input devices set reasonable defaults.
- if (sample_rate <= 0 || sample_rate > 96000)
- sample_rate = 44100;
-
- device_info.device.input.sample_rate = sample_rate;
- device_info.device.input.channel_layout = media::CHANNEL_LAYOUT_STEREO;
- }
+ // Initialize the sample_rate and channel_layout here since for audio
+ // mirroring, we don't go through EnumerateDevices where these are usually
+ // initialized.
+ if (device_info.device.type == content::MEDIA_TAB_AUDIO_CAPTURE ||
+ device_info.device.type == content::MEDIA_DESKTOP_AUDIO_CAPTURE) {
+ int sample_rate = output_parameters.sample_rate();
+ // If we weren't able to get the native sampling rate or the sample_rate
+ // is outside the valid range for input devices set reasonable defaults.
+ if (sample_rate <= 0 || sample_rate > 96000)
+ sample_rate = 44100;
+
+ device_info.device.input.sample_rate = sample_rate;
+ device_info.device.input.channel_layout = media::CHANNEL_LAYOUT_STEREO;
}
- if (device_info.device.type == request->audio_type()) {
+ if (device_info.device.type == request->audio_type())
found_audio = true;
- } else if (device_info.device.type == request->video_type()) {
+ else if (device_info.device.type == request->video_type())
found_video = true;
- }
// If this is request for a new MediaStream, a device is only opened once
// per render frame. This is so that the permission to use a device can be
@@ -2016,15 +2045,27 @@ void MediaStreamManager::OnMediaStreamUIWindowId(MediaStreamType video_type,
if (!window_id)
return;
- // Pass along for desktop capturing. Ignored for other stream types.
- if (video_type == MEDIA_DESKTOP_VIDEO_CAPTURE) {
- for (const StreamDeviceInfo& device_info : devices ) {
- if (device_info.device.type == MEDIA_DESKTOP_VIDEO_CAPTURE) {
- video_capture_manager_->SetDesktopCaptureWindowId(
- device_info.session_id, window_id);
- break;
- }
- }
+ if (video_type != MEDIA_DESKTOP_VIDEO_CAPTURE)
+ return;
+
+ // Pass along for desktop screen and window capturing when
+ // DesktopCaptureDevice is used.
+ for (const StreamDeviceInfo& device_info : devices) {
+ if (device_info.device.type != MEDIA_DESKTOP_VIDEO_CAPTURE)
+ continue;
+
+ DesktopMediaID media_id = DesktopMediaID::Parse(device_info.device.id);
+ // WebContentsVideoCaptureDevice is used for tab/webcontents.
+ if (media_id.type == DesktopMediaID::TYPE_WEB_CONTENTS)
+ continue;
+#if defined(USE_AURA)
+ // DesktopCaptureDevicAura is used when aura_id is valid.
+ if (media_id.aura_id > DesktopMediaID::kNullId)
+ continue;
+#endif
+ video_capture_manager_->SetDesktopCaptureWindowId(device_info.session_id,
+ window_id);
+ break;
}
}
diff --git a/chromium/content/browser/renderer_host/media/media_stream_manager.h b/chromium/content/browser/renderer_host/media/media_stream_manager.h
index 21d4f2f4050..52c3fa71d44 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_manager.h
+++ b/chromium/content/browser/renderer_host/media/media_stream_manager.h
@@ -28,12 +28,12 @@
#include <list>
#include <map>
+#include <memory>
#include <string>
#include <utility>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/power_monitor/power_observer.h"
#include "base/system_monitor/system_monitor.h"
@@ -72,7 +72,7 @@ class CONTENT_EXPORT MediaStreamManager
public:
// Callback to deliver the result of a media request.
typedef base::Callback<void(const MediaStreamDevices& devices,
- scoped_ptr<MediaStreamUIProxy> ui)>
+ std::unique_ptr<MediaStreamUIProxy> ui)>
MediaRequestResponseCallback;
// Adds |message| to native logs for outstanding device requests, for use by
@@ -212,7 +212,7 @@ class CONTENT_EXPORT MediaStreamManager
// Called by the tests to specify a fake UI that should be used for next
// generated stream (or when using --use-fake-ui-for-media-stream).
- void UseFakeUIForTests(scoped_ptr<FakeMediaStreamUIProxy> fake_ui);
+ void UseFakeUIForTests(std::unique_ptr<FakeMediaStreamUIProxy> fake_ui);
// Register and unregister a new callback for receiving native log entries.
// The registered callback will be invoked on the IO thread.
@@ -265,9 +265,12 @@ class CONTENT_EXPORT MediaStreamManager
void NotifyDevicesChanged(MediaStreamType stream_type,
const StreamDeviceInfoArray& devices);
- void HandleAccessRequestResponse(const std::string& label,
- const MediaStreamDevices& devices,
- content::MediaStreamRequestResult result);
+ // |output_parameters| contains real values only if the request requires it.
+ void HandleAccessRequestResponse(
+ const std::string& label,
+ const media::AudioParameters& output_parameters,
+ const MediaStreamDevices& devices,
+ content::MediaStreamRequestResult result);
void StopMediaStreamFromBrowser(const std::string& label);
void DoEnumerateDevices(const std::string& label);
@@ -319,7 +322,12 @@ class CONTENT_EXPORT MediaStreamManager
bool SetupScreenCaptureRequest(DeviceRequest* request);
// Called when a request has been setup and devices have been enumerated if
// needed.
- void PostRequestToUI(const std::string& label, DeviceRequest* request);
+ void ReadOutputParamsAndPostRequestToUI(const std::string& label,
+ DeviceRequest* request);
+ // Called when audio output parameters have been read if needed.
+ void PostRequestToUI(const std::string& label,
+ DeviceRequest* request,
+ const media::AudioParameters& output_parameters);
// Returns true if a device with |device_id| has already been requested with
// a render procecss_id and render_frame_id and type equal to the the values
// in |request|. If it has been requested, |device_info| contain information
@@ -402,7 +410,7 @@ class CONTENT_EXPORT MediaStreamManager
media::AudioManager* const audio_manager_; // not owned
scoped_refptr<AudioInputDeviceManager> audio_input_device_manager_;
scoped_refptr<VideoCaptureManager> video_capture_manager_;
- scoped_ptr<AudioOutputDeviceEnumerator> audio_output_device_enumerator_;
+ std::unique_ptr<AudioOutputDeviceEnumerator> audio_output_device_enumerator_;
#if defined(OS_WIN)
base::Thread video_capture_thread_;
#endif
@@ -423,7 +431,7 @@ class CONTENT_EXPORT MediaStreamManager
DeviceRequests requests_;
bool use_fake_ui_;
- scoped_ptr<FakeMediaStreamUIProxy> fake_ui_;
+ std::unique_ptr<FakeMediaStreamUIProxy> fake_ui_;
// Maps render process hosts to log callbacks. Used on the IO thread.
std::map<int, base::Callback<void(const std::string&)>> log_callbacks_;
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 9f7fadb0755..9c606327c53 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
@@ -66,9 +66,8 @@ ResourceContext::SaltCallback GetMockSaltCallback() {
return base::Bind(&ReturnMockSalt);
}
-// This class mocks the audio manager and overrides the
-// GetAudioInputDeviceNames() method to ensure that we can run our tests on
-// the buildbots. media::AudioManagerBase
+// This class mocks the audio manager and overrides some methods to ensure that
+// we can run our tests on the buildbots.
class MockAudioManager : public AudioManagerPlatform {
public:
MockAudioManager()
@@ -103,6 +102,17 @@ class MockAudioManager : public AudioManagerPlatform {
}
}
+ media::AudioParameters GetDefaultOutputStreamParameters() override {
+ return media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_STEREO, 48000, 16, 128);
+ }
+
+ media::AudioParameters GetOutputStreamParameters(
+ const std::string& device_id) override {
+ return media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_STEREO, 48000, 16, 128);
+ }
+
void SetNumAudioOutputDevices(size_t num_devices) {
num_output_devices_ = num_devices;
}
@@ -180,7 +190,7 @@ class MediaStreamManagerTest : public ::testing::Test {
MOCK_METHOD1(Response, void(int index));
void ResponseCallback(int index,
const MediaStreamDevices& devices,
- scoped_ptr<MediaStreamUIProxy> ui_proxy) {
+ std::unique_ptr<MediaStreamUIProxy> ui_proxy) {
Response(index);
task_runner_->PostTask(FROM_HERE, run_loop_.QuitClosure());
}
@@ -200,8 +210,8 @@ class MediaStreamManagerTest : public ::testing::Test {
security_origin, callback);
}
- scoped_ptr<MockAudioManager> audio_manager_;
- scoped_ptr<MediaStreamManager> media_stream_manager_;
+ std::unique_ptr<MockAudioManager> audio_manager_;
+ std::unique_ptr<MediaStreamManager> media_stream_manager_;
content::TestBrowserThreadBundle thread_bundle_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
base::RunLoop run_loop_;
diff --git a/chromium/content/browser/renderer_host/media/media_stream_ui_controller_unittest.cc b/chromium/content/browser/renderer_host/media/media_stream_ui_controller_unittest.cc
index f21618f484e..f0f93b476ad 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_ui_controller_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_ui_controller_unittest.cc
@@ -70,10 +70,10 @@ class MediaStreamDeviceUIControllerTest
std::string());
}
- scoped_ptr<base::MessageLoop> message_loop_;
- scoped_ptr<BrowserThreadImpl> ui_thread_;
- scoped_ptr<BrowserThreadImpl> io_thread_;
- scoped_ptr<MediaStreamUIController> ui_controller_;
+ std::unique_ptr<base::MessageLoop> message_loop_;
+ std::unique_ptr<BrowserThreadImpl> ui_thread_;
+ std::unique_ptr<BrowserThreadImpl> io_thread_;
+ std::unique_ptr<MediaStreamUIController> ui_controller_;
private:
DISALLOW_COPY_AND_ASSIGN(MediaStreamDeviceUIControllerTest);
@@ -97,7 +97,7 @@ TEST_F(MediaStreamDeviceUIControllerTest, GenerateAndRemoveRequest) {
}
TEST_F(MediaStreamDeviceUIControllerTest, HandleRequestUsingFakeUI) {
- ui_controller_->UseFakeUI(scoped_ptr<MediaStreamUI>());
+ ui_controller_->UseFakeUI(std::unique_ptr<MediaStreamUI>());
const std::string label = "label";
CreateDummyRequest(label, true, true);
@@ -111,7 +111,7 @@ TEST_F(MediaStreamDeviceUIControllerTest, HandleRequestUsingFakeUI) {
}
TEST_F(MediaStreamDeviceUIControllerTest, CreateRequestsAndCancelTheFirst) {
- ui_controller_->UseFakeUI(scoped_ptr<MediaStreamUI>());
+ ui_controller_->UseFakeUI(std::unique_ptr<MediaStreamUI>());
// Create the first audio request.
const std::string label_1 = "label_1";
@@ -139,7 +139,7 @@ TEST_F(MediaStreamDeviceUIControllerTest, CreateRequestsAndCancelTheFirst) {
}
TEST_F(MediaStreamDeviceUIControllerTest, CreateRequestsAndCancelTheLast) {
- ui_controller_->UseFakeUI(scoped_ptr<MediaStreamUI>());
+ ui_controller_->UseFakeUI(std::unique_ptr<MediaStreamUI>());
// Create the first audio request.
const std::string label_1 = "label_1";
diff --git a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc
index 6cecbec2feb..79ae89de62a 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.cc
@@ -45,7 +45,7 @@ class MediaStreamUIProxy::Core {
RenderFrameHostDelegate* test_render_delegate);
~Core();
- void RequestAccess(scoped_ptr<MediaStreamRequest> request);
+ void RequestAccess(std::unique_ptr<MediaStreamRequest> request);
bool CheckAccess(const GURL& security_origin,
MediaStreamType type,
int process_id,
@@ -55,13 +55,13 @@ class MediaStreamUIProxy::Core {
private:
void ProcessAccessRequestResponse(const MediaStreamDevices& devices,
content::MediaStreamRequestResult result,
- scoped_ptr<MediaStreamUI> stream_ui);
+ std::unique_ptr<MediaStreamUI> stream_ui);
void ProcessStopRequestFromUI();
RenderFrameHostDelegate* GetRenderFrameHostDelegate(int render_process_id,
int render_frame_id);
base::WeakPtr<MediaStreamUIProxy> proxy_;
- scoped_ptr<MediaStreamUI> ui_;
+ std::unique_ptr<MediaStreamUI> ui_;
RenderFrameHostDelegate* const test_render_delegate_;
@@ -84,7 +84,7 @@ MediaStreamUIProxy::Core::~Core() {
}
void MediaStreamUIProxy::Core::RequestAccess(
- scoped_ptr<MediaStreamRequest> request) {
+ std::unique_ptr<MediaStreamRequest> request) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderFrameHostDelegate* render_delegate = GetRenderFrameHostDelegate(
@@ -94,7 +94,7 @@ void MediaStreamUIProxy::Core::RequestAccess(
if (!render_delegate) {
ProcessAccessRequestResponse(MediaStreamDevices(),
MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN,
- scoped_ptr<MediaStreamUI>());
+ std::unique_ptr<MediaStreamUI>());
return;
}
SetAndCheckAncestorFlag(request.get());
@@ -129,7 +129,7 @@ void MediaStreamUIProxy::Core::OnStarted(gfx::NativeViewId* window_id) {
void MediaStreamUIProxy::Core::ProcessAccessRequestResponse(
const MediaStreamDevices& devices,
content::MediaStreamRequestResult result,
- scoped_ptr<MediaStreamUI> stream_ui) {
+ std::unique_ptr<MediaStreamUI> stream_ui) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
ui_ = std::move(stream_ui);
@@ -158,14 +158,14 @@ RenderFrameHostDelegate* MediaStreamUIProxy::Core::GetRenderFrameHostDelegate(
}
// static
-scoped_ptr<MediaStreamUIProxy> MediaStreamUIProxy::Create() {
- return scoped_ptr<MediaStreamUIProxy>(new MediaStreamUIProxy(NULL));
+std::unique_ptr<MediaStreamUIProxy> MediaStreamUIProxy::Create() {
+ return std::unique_ptr<MediaStreamUIProxy>(new MediaStreamUIProxy(NULL));
}
// static
-scoped_ptr<MediaStreamUIProxy> MediaStreamUIProxy::CreateForTests(
+std::unique_ptr<MediaStreamUIProxy> MediaStreamUIProxy::CreateForTests(
RenderFrameHostDelegate* render_delegate) {
- return scoped_ptr<MediaStreamUIProxy>(
+ return std::unique_ptr<MediaStreamUIProxy>(
new MediaStreamUIProxy(render_delegate));
}
@@ -181,7 +181,7 @@ MediaStreamUIProxy::~MediaStreamUIProxy() {
}
void MediaStreamUIProxy::RequestAccess(
- scoped_ptr<MediaStreamRequest> request,
+ std::unique_ptr<MediaStreamRequest> request,
const ResponseCallback& response_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -290,7 +290,7 @@ void FakeMediaStreamUIProxy::SetCameraAccess(bool access) {
}
void FakeMediaStreamUIProxy::RequestAccess(
- scoped_ptr<MediaStreamRequest> request,
+ std::unique_ptr<MediaStreamRequest> request,
const ResponseCallback& response_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
diff --git a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.h b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.h
index 0c2eaeae196..a89d35b87e3 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.h
+++ b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy.h
@@ -5,9 +5,10 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_UI_PROXY_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_MEDIA_STREAM_UI_PROXY_H_
+#include <memory>
+
#include "base/callback.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/media_stream_request.h"
@@ -28,8 +29,8 @@ class CONTENT_EXPORT MediaStreamUIProxy {
typedef base::Callback<void(gfx::NativeViewId window_id)> WindowIdCallback;
- static scoped_ptr<MediaStreamUIProxy> Create();
- static scoped_ptr<MediaStreamUIProxy> CreateForTests(
+ static std::unique_ptr<MediaStreamUIProxy> Create();
+ static std::unique_ptr<MediaStreamUIProxy> CreateForTests(
RenderFrameHostDelegate* render_delegate);
virtual ~MediaStreamUIProxy();
@@ -38,7 +39,7 @@ class CONTENT_EXPORT MediaStreamUIProxy {
// WebContentsDelegate::RequestMediaAccessPermission(). The specified
// |response_callback| is called when the WebContentsDelegate approves or
// denies request.
- virtual void RequestAccess(scoped_ptr<MediaStreamRequest> request,
+ virtual void RequestAccess(std::unique_ptr<MediaStreamRequest> request,
const ResponseCallback& response_callback);
// Checks if we have permission to access the microphone or camera. Note that
@@ -78,7 +79,7 @@ class CONTENT_EXPORT MediaStreamUIProxy {
void OnCheckedAccess(const base::Callback<void(bool)>& callback,
bool have_access);
- scoped_ptr<Core, content::BrowserThread::DeleteOnUIThread> core_;
+ std::unique_ptr<Core, content::BrowserThread::DeleteOnUIThread> core_;
ResponseCallback response_callback_;
base::Closure stop_callback_;
@@ -97,7 +98,7 @@ class CONTENT_EXPORT FakeMediaStreamUIProxy : public MediaStreamUIProxy {
void SetCameraAccess(bool access);
// MediaStreamUIProxy overrides.
- void RequestAccess(scoped_ptr<MediaStreamRequest> request,
+ void RequestAccess(std::unique_ptr<MediaStreamRequest> request,
const ResponseCallback& response_callback) override;
void CheckAccess(const GURL& security_origin,
MediaStreamType type,
diff --git a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
index eae9607c600..a3ce7707d3d 100644
--- a/chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/media_stream_ui_proxy_unittest.cc
@@ -72,7 +72,7 @@ class MediaStreamUIProxyTest : public testing::Test {
MockRenderFrameHostDelegate delegate_;
MockResponseCallback response_callback_;
- scoped_ptr<MediaStreamUIProxy> proxy_;
+ std::unique_ptr<MediaStreamUIProxy> proxy_;
};
MATCHER_P(SameRequest, expected, "") {
@@ -88,13 +88,10 @@ MATCHER_P(SameRequest, expected, "") {
}
TEST_F(MediaStreamUIProxyTest, Deny) {
- scoped_ptr<MediaStreamRequest> request (
- new MediaStreamRequest(0, 0, 0, GURL("http://origin/"),
- false,
- MEDIA_GENERATE_STREAM, std::string(),
- std::string(),
- MEDIA_DEVICE_AUDIO_CAPTURE,
- MEDIA_DEVICE_VIDEO_CAPTURE));
+ std::unique_ptr<MediaStreamRequest> request(new MediaStreamRequest(
+ 0, 0, 0, GURL("http://origin/"), false, MEDIA_GENERATE_STREAM,
+ std::string(), std::string(), MEDIA_DEVICE_AUDIO_CAPTURE,
+ MEDIA_DEVICE_VIDEO_CAPTURE));
MediaStreamRequest* request_ptr = request.get();
proxy_->RequestAccess(
std::move(request),
@@ -108,7 +105,7 @@ TEST_F(MediaStreamUIProxyTest, Deny) {
ASSERT_FALSE(callback.is_null());
MediaStreamDevices devices;
- callback.Run(devices, MEDIA_DEVICE_OK, scoped_ptr<MediaStreamUI>());
+ callback.Run(devices, MEDIA_DEVICE_OK, std::unique_ptr<MediaStreamUI>());
MediaStreamDevices response;
EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _))
@@ -119,13 +116,10 @@ TEST_F(MediaStreamUIProxyTest, Deny) {
}
TEST_F(MediaStreamUIProxyTest, AcceptAndStart) {
- scoped_ptr<MediaStreamRequest> request (
- new MediaStreamRequest(0, 0, 0,
- GURL("http://origin/"), false,
- MEDIA_GENERATE_STREAM, std::string(),
- std::string(),
- MEDIA_DEVICE_AUDIO_CAPTURE,
- MEDIA_DEVICE_VIDEO_CAPTURE));
+ std::unique_ptr<MediaStreamRequest> request(new MediaStreamRequest(
+ 0, 0, 0, GURL("http://origin/"), false, MEDIA_GENERATE_STREAM,
+ std::string(), std::string(), MEDIA_DEVICE_AUDIO_CAPTURE,
+ MEDIA_DEVICE_VIDEO_CAPTURE));
MediaStreamRequest* request_ptr = request.get();
proxy_->RequestAccess(
std::move(request),
@@ -141,7 +135,7 @@ TEST_F(MediaStreamUIProxyTest, AcceptAndStart) {
MediaStreamDevices devices;
devices.push_back(
MediaStreamDevice(MEDIA_DEVICE_AUDIO_CAPTURE, "Mic", "Mic"));
- scoped_ptr<MockMediaStreamUI> ui(new MockMediaStreamUI());
+ std::unique_ptr<MockMediaStreamUI> ui(new MockMediaStreamUI());
EXPECT_CALL(*ui, OnStarted(_)).WillOnce(Return(0));
callback.Run(devices, MEDIA_DEVICE_OK, std::move(ui));
@@ -158,13 +152,10 @@ TEST_F(MediaStreamUIProxyTest, AcceptAndStart) {
// Verify that the proxy can be deleted before the request is processed.
TEST_F(MediaStreamUIProxyTest, DeleteBeforeAccepted) {
- scoped_ptr<MediaStreamRequest> request (
- new MediaStreamRequest(0, 0, 0,
- GURL("http://origin/"), false,
- MEDIA_GENERATE_STREAM, std::string(),
- std::string(),
- MEDIA_DEVICE_AUDIO_CAPTURE,
- MEDIA_DEVICE_VIDEO_CAPTURE));
+ std::unique_ptr<MediaStreamRequest> request(new MediaStreamRequest(
+ 0, 0, 0, GURL("http://origin/"), false, MEDIA_GENERATE_STREAM,
+ std::string(), std::string(), MEDIA_DEVICE_AUDIO_CAPTURE,
+ MEDIA_DEVICE_VIDEO_CAPTURE));
MediaStreamRequest* request_ptr = request.get();
proxy_->RequestAccess(
std::move(request),
@@ -180,18 +171,15 @@ TEST_F(MediaStreamUIProxyTest, DeleteBeforeAccepted) {
proxy_.reset();
MediaStreamDevices devices;
- scoped_ptr<MediaStreamUI> ui;
+ std::unique_ptr<MediaStreamUI> ui;
callback.Run(devices, MEDIA_DEVICE_OK, std::move(ui));
}
TEST_F(MediaStreamUIProxyTest, StopFromUI) {
- scoped_ptr<MediaStreamRequest> request (
- new MediaStreamRequest(0, 0, 0,
- GURL("http://origin/"), false,
- MEDIA_GENERATE_STREAM, std::string(),
- std::string(),
- MEDIA_DEVICE_AUDIO_CAPTURE,
- MEDIA_DEVICE_VIDEO_CAPTURE));
+ std::unique_ptr<MediaStreamRequest> request(new MediaStreamRequest(
+ 0, 0, 0, GURL("http://origin/"), false, MEDIA_GENERATE_STREAM,
+ std::string(), std::string(), MEDIA_DEVICE_AUDIO_CAPTURE,
+ MEDIA_DEVICE_VIDEO_CAPTURE));
MediaStreamRequest* request_ptr = request.get();
proxy_->RequestAccess(
std::move(request),
@@ -209,7 +197,7 @@ TEST_F(MediaStreamUIProxyTest, StopFromUI) {
MediaStreamDevices devices;
devices.push_back(
MediaStreamDevice(MEDIA_DEVICE_AUDIO_CAPTURE, "Mic", "Mic"));
- scoped_ptr<MockMediaStreamUI> ui(new MockMediaStreamUI());
+ std::unique_ptr<MockMediaStreamUI> ui(new MockMediaStreamUI());
EXPECT_CALL(*ui, OnStarted(_))
.WillOnce(testing::DoAll(SaveArg<0>(&stop_callback), Return(0)));
callback.Run(devices, MEDIA_DEVICE_OK, std::move(ui));
@@ -234,13 +222,10 @@ TEST_F(MediaStreamUIProxyTest, StopFromUI) {
}
TEST_F(MediaStreamUIProxyTest, WindowIdCallbackCalled) {
- scoped_ptr<MediaStreamRequest> request (
- new MediaStreamRequest(0, 0, 0,
- GURL("http://origin/"), false,
- MEDIA_GENERATE_STREAM, std::string(),
- std::string(),
- MEDIA_NO_SERVICE,
- MEDIA_DESKTOP_VIDEO_CAPTURE));
+ std::unique_ptr<MediaStreamRequest> request(new MediaStreamRequest(
+ 0, 0, 0, GURL("http://origin/"), false, MEDIA_GENERATE_STREAM,
+ std::string(), std::string(), MEDIA_NO_SERVICE,
+ MEDIA_DESKTOP_VIDEO_CAPTURE));
MediaStreamRequest* request_ptr = request.get();
proxy_->RequestAccess(
@@ -254,7 +239,7 @@ TEST_F(MediaStreamUIProxyTest, WindowIdCallbackCalled) {
message_loop_.RunUntilIdle();
const int kWindowId = 1;
- scoped_ptr<MockMediaStreamUI> ui(new MockMediaStreamUI());
+ std::unique_ptr<MockMediaStreamUI> ui(new MockMediaStreamUI());
EXPECT_CALL(*ui, OnStarted(_)).WillOnce(Return(kWindowId));
callback.Run(MediaStreamDevices(), MEDIA_DEVICE_OK, std::move(ui));
diff --git a/chromium/content/browser/renderer_host/media/peer_connection_tracker_host.cc b/chromium/content/browser/renderer_host/media/peer_connection_tracker_host.cc
index 41580ebe9c7..12f6edc96d1 100644
--- a/chromium/content/browser/renderer_host/media/peer_connection_tracker_host.cc
+++ b/chromium/content/browser/renderer_host/media/peer_connection_tracker_host.cc
@@ -4,7 +4,7 @@
#include "content/browser/renderer_host/media/peer_connection_tracker_host.h"
#include "base/power_monitor/power_monitor.h"
-#include "content/browser/media/webrtc_internals.h"
+#include "content/browser/media/webrtc/webrtc_internals.h"
#include "content/common/media/peer_connection_tracker_messages.h"
#include "content/public/browser/render_process_host.h"
diff --git a/chromium/content/browser/renderer_host/media/video_capture_buffer_pool.cc b/chromium/content/browser/renderer_host/media/video_capture_buffer_pool.cc
index a934a40cf81..df4e70b92d8 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
@@ -4,8 +4,10 @@
#include "content/browser/renderer_host/media/video_capture_buffer_pool.h"
+#include <memory>
+
#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
+#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "build/build_config.h"
#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
@@ -16,99 +18,31 @@ namespace content {
const int VideoCaptureBufferPool::kInvalidId = -1;
-// A simple holder of a memory-backed buffer and accessors to it.
-class SimpleBufferHandle final : public VideoCaptureBufferPool::BufferHandle {
- public:
- SimpleBufferHandle(void* data,
- size_t mapped_size,
- base::SharedMemoryHandle handle)
- : data_(data),
- mapped_size_(mapped_size)
-#if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS))
- ,
- handle_(handle)
-#endif
- {
- }
- ~SimpleBufferHandle() override {}
-
- gfx::Size dimensions() const override {
- NOTREACHED();
- return gfx::Size();
- }
- size_t mapped_size() const override { return mapped_size_; }
- void* data(int plane) override {
- DCHECK_EQ(plane, 0);
- return data_;
- }
- ClientBuffer AsClientBuffer(int plane) override {
- NOTREACHED();
- return nullptr;
- }
-#if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS))
- base::FileDescriptor AsPlatformFile() override {
- return handle_;
- }
-#endif
-
- private:
- void* const data_;
- const size_t mapped_size_;
-#if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS))
- const base::SharedMemoryHandle handle_;
-#endif
-};
-
-// A holder of a GpuMemoryBuffer-backed buffer. Holds weak references to
-// GpuMemoryBuffer-backed buffers and provides accessors to their data.
-class GpuMemoryBufferBufferHandle final
- : public VideoCaptureBufferPool::BufferHandle {
- public:
- GpuMemoryBufferBufferHandle(const gfx::Size& dimensions,
- std::vector<
- scoped_ptr<gfx::GpuMemoryBuffer>>* gmbs)
- : dimensions_(dimensions), gmbs_(gmbs) {
- DCHECK(gmbs);
- }
- ~GpuMemoryBufferBufferHandle() override {}
-
- gfx::Size dimensions() const override { return dimensions_; }
- size_t mapped_size() const override { return dimensions_.GetArea(); }
- void* data(int plane) override {
- DCHECK_GE(plane, 0);
- DCHECK_LT(plane, static_cast<int>(gmbs_->size()));
- DCHECK((*gmbs_)[plane]);
- return (*gmbs_)[plane]->memory(0);
- }
- ClientBuffer AsClientBuffer(int plane) override {
- DCHECK_GE(plane, 0);
- DCHECK_LT(plane, static_cast<int>(gmbs_->size()));
- return (*gmbs_)[plane]->AsClientBuffer();
- }
-#if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS))
- base::FileDescriptor AsPlatformFile() override {
- NOTREACHED();
- return base::FileDescriptor();
- }
-#endif
-
- private:
- const gfx::Size dimensions_;
- std::vector<scoped_ptr<gfx::GpuMemoryBuffer>>* const gmbs_;
-};
-
// Tracker specifics for SharedMemory.
class VideoCaptureBufferPool::SharedMemTracker final : public Tracker {
public:
- SharedMemTracker();
- bool Init(media::VideoPixelFormat format,
+ SharedMemTracker() : Tracker() {}
+
+ bool Init(const gfx::Size& dimensions,
+ media::VideoPixelFormat format,
media::VideoPixelStorage storage_type,
- const gfx::Size& dimensions,
- base::Lock* lock) override;
+ base::Lock* lock) override {
+ DVLOG(2) << "allocating ShMem of " << dimensions.ToString();
+ set_dimensions(dimensions);
+ // |dimensions| can be 0x0 for trackers that do not require memory backing.
+ set_max_pixel_count(dimensions.GetArea());
+ set_pixel_format(format);
+ set_storage_type(storage_type);
+ mapped_size_ =
+ media::VideoCaptureFormat(dimensions, 0.0f, format, storage_type)
+ .ImageAllocationSize();
+ if (!mapped_size_)
+ return true;
+ return shared_memory_.CreateAndMapAnonymous(mapped_size_);
+ }
- scoped_ptr<BufferHandle> GetBufferHandle() override {
- return make_scoped_ptr(new SimpleBufferHandle(
- shared_memory_.memory(), mapped_size_, shared_memory_.handle()));
+ std::unique_ptr<BufferHandle> GetBufferHandle() override {
+ return base::WrapUnique(new SharedMemBufferHandle(this));
}
bool ShareToProcess(base::ProcessHandle process_handle,
base::SharedMemoryHandle* new_handle) override {
@@ -122,6 +56,37 @@ class VideoCaptureBufferPool::SharedMemTracker final : public Tracker {
}
private:
+ // A simple proxy that implements the BufferHandle interface, providing
+ // accessors to SharedMemTracker's memory and properties.
+ class SharedMemBufferHandle : public VideoCaptureBufferPool::BufferHandle {
+ public:
+ // |tracker| must outlive SimpleBufferHandle. This is ensured since a
+ // tracker is pinned until ownership of this SimpleBufferHandle is returned
+ // to VideoCaptureBufferPool.
+ explicit SharedMemBufferHandle(SharedMemTracker* tracker)
+ : tracker_(tracker) {}
+ ~SharedMemBufferHandle() override {}
+
+ gfx::Size dimensions() const override { return tracker_->dimensions(); }
+ size_t mapped_size() const override { return tracker_->mapped_size_; }
+ void* data(int plane) override {
+ DCHECK_EQ(plane, 0);
+ return tracker_->shared_memory_.memory();
+ }
+ ClientBuffer AsClientBuffer(int plane) override {
+ NOTREACHED();
+ return nullptr;
+ }
+#if defined(OS_POSIX) && !defined(OS_MACOSX)
+ base::FileDescriptor AsPlatformFile() override {
+ return tracker_->shared_memory_.handle();
+ }
+#endif
+
+ private:
+ SharedMemTracker* const tracker_;
+ };
+
// The memory created to be shared with renderer processes.
base::SharedMemory shared_memory_;
size_t mapped_size_;
@@ -131,151 +96,155 @@ class VideoCaptureBufferPool::SharedMemTracker final : public Tracker {
// associated pixel dimensions.
class VideoCaptureBufferPool::GpuMemoryBufferTracker final : public Tracker {
public:
- GpuMemoryBufferTracker();
- bool Init(media::VideoPixelFormat format,
+ GpuMemoryBufferTracker() : Tracker() {}
+
+ ~GpuMemoryBufferTracker() override {
+ for (const auto& gmb : gpu_memory_buffers_)
+ gmb->Unmap();
+ }
+
+ bool Init(const gfx::Size& dimensions,
+ media::VideoPixelFormat format,
media::VideoPixelStorage storage_type,
- const gfx::Size& dimensions,
- base::Lock* lock) override;
- ~GpuMemoryBufferTracker() override;
+ base::Lock* lock) override {
+ DVLOG(2) << "allocating GMB for " << dimensions.ToString();
+ // BrowserGpuMemoryBufferManager::current() may not be accessed on IO
+ // Thread.
+ DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DCHECK(BrowserGpuMemoryBufferManager::current());
+ // This class is only expected to be called with I420 buffer requests at
+ // this point.
+ DCHECK_EQ(format, media::PIXEL_FORMAT_I420);
+ set_dimensions(dimensions);
+ set_max_pixel_count(dimensions.GetArea());
+ set_pixel_format(format);
+ set_storage_type(storage_type);
+ // |dimensions| can be 0x0 for trackers that do not require memory backing.
+ if (dimensions.GetArea() == 0u)
+ return true;
- scoped_ptr<BufferHandle> GetBufferHandle() override {
+ base::AutoUnlock auto_unlock(*lock);
+ const size_t num_planes = media::VideoFrame::NumPlanes(pixel_format());
+ for (size_t i = 0; i < num_planes; ++i) {
+ const gfx::Size& size =
+ media::VideoFrame::PlaneSize(pixel_format(), i, dimensions);
+ gpu_memory_buffers_.push_back(
+ BrowserGpuMemoryBufferManager::current()->AllocateGpuMemoryBuffer(
+ size, gfx::BufferFormat::R_8,
+ gfx::BufferUsage::GPU_READ_CPU_READ_WRITE, 0 /* surface_id */));
+
+ DLOG_IF(ERROR, !gpu_memory_buffers_[i]) << "Allocating GpuMemoryBuffer";
+ if (!gpu_memory_buffers_[i] || !gpu_memory_buffers_[i]->Map())
+ return false;
+ }
+ return true;
+ }
+
+ std::unique_ptr<BufferHandle> GetBufferHandle() override {
DCHECK_EQ(gpu_memory_buffers_.size(),
media::VideoFrame::NumPlanes(pixel_format()));
- return make_scoped_ptr(
- new GpuMemoryBufferBufferHandle(dimensions_, &gpu_memory_buffers_));
+ return base::WrapUnique(new GpuMemoryBufferBufferHandle(this));
}
+
bool ShareToProcess(base::ProcessHandle process_handle,
base::SharedMemoryHandle* new_handle) override {
NOTREACHED();
return false;
}
+
bool ShareToProcess2(int plane,
base::ProcessHandle process_handle,
- gfx::GpuMemoryBufferHandle* new_handle) override;
-
- private:
- gfx::Size dimensions_;
- // Owned references to GpuMemoryBuffers.
- std::vector<scoped_ptr<gfx::GpuMemoryBuffer>> gpu_memory_buffers_;
-};
-
-VideoCaptureBufferPool::SharedMemTracker::SharedMemTracker() : Tracker() {}
-
-bool VideoCaptureBufferPool::SharedMemTracker::Init(
- media::VideoPixelFormat format,
- media::VideoPixelStorage storage_type,
- const gfx::Size& dimensions,
- base::Lock* lock) {
- DVLOG(2) << "allocating ShMem of " << dimensions.ToString();
- set_pixel_format(format);
- set_storage_type(storage_type);
- // |dimensions| can be 0x0 for trackers that do not require memory backing.
- set_pixel_count(dimensions.GetArea());
- mapped_size_ =
- media::VideoCaptureFormat(dimensions, 0.0f, format, storage_type)
- .ImageAllocationSize();
- if (!mapped_size_)
- return true;
- return shared_memory_.CreateAndMapAnonymous(mapped_size_);
-}
-
-VideoCaptureBufferPool::GpuMemoryBufferTracker::GpuMemoryBufferTracker()
- : Tracker() {
-}
-
-VideoCaptureBufferPool::GpuMemoryBufferTracker::~GpuMemoryBufferTracker() {
- for (const auto& gmb : gpu_memory_buffers_)
- gmb->Unmap();
-}
-
-bool VideoCaptureBufferPool::GpuMemoryBufferTracker::Init(
- media::VideoPixelFormat format,
- media::VideoPixelStorage storage_type,
- const gfx::Size& dimensions,
- base::Lock* lock) {
- DVLOG(2) << "allocating GMB for " << dimensions.ToString();
- // BrowserGpuMemoryBufferManager::current() may not be accessed on IO Thread.
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::IO));
- DCHECK(BrowserGpuMemoryBufferManager::current());
- // This class is only expected to be called with I420 buffer requests at this
- // point.
- DCHECK_EQ(format, media::PIXEL_FORMAT_I420);
- set_pixel_format(format);
- set_storage_type(storage_type);
- set_pixel_count(dimensions.GetArea());
- // |dimensions| can be 0x0 for trackers that do not require memory backing.
- if (dimensions.GetArea() == 0u)
+ gfx::GpuMemoryBufferHandle* new_handle) override {
+ DCHECK_LE(plane, static_cast<int>(gpu_memory_buffers_.size()));
+
+ const auto& current_gmb_handle = gpu_memory_buffers_[plane]->GetHandle();
+ switch (current_gmb_handle.type) {
+ case gfx::EMPTY_BUFFER:
+ NOTREACHED();
+ return false;
+ case gfx::SHARED_MEMORY_BUFFER: {
+ DCHECK(base::SharedMemory::IsHandleValid(current_gmb_handle.handle));
+ base::SharedMemory shared_memory(
+ base::SharedMemory::DuplicateHandle(current_gmb_handle.handle),
+ false);
+ shared_memory.ShareToProcess(process_handle, &new_handle->handle);
+ DCHECK(base::SharedMemory::IsHandleValid(new_handle->handle));
+ new_handle->type = gfx::SHARED_MEMORY_BUFFER;
+ return true;
+ }
+ case gfx::IO_SURFACE_BUFFER:
+ case gfx::SURFACE_TEXTURE_BUFFER:
+ case gfx::OZONE_NATIVE_PIXMAP:
+ *new_handle = current_gmb_handle;
+ return true;
+ }
+ NOTREACHED();
return true;
- dimensions_ = dimensions;
-
- lock->Release();
- const size_t num_planes = media::VideoFrame::NumPlanes(pixel_format());
- for (size_t i = 0; i < num_planes; ++i) {
- const gfx::Size& size =
- media::VideoFrame::PlaneSize(pixel_format(), i, dimensions);
- gpu_memory_buffers_.push_back(
- BrowserGpuMemoryBufferManager::current()->AllocateGpuMemoryBuffer(
- size, gfx::BufferFormat::R_8,
- gfx::BufferUsage::GPU_READ_CPU_READ_WRITE));
-
- DLOG_IF(ERROR, !gpu_memory_buffers_[i]) << "Allocating GpuMemoryBuffer";
- if (!gpu_memory_buffers_[i] || !gpu_memory_buffers_[i]->Map())
- return false;
}
- lock->Acquire();
- return true;
-}
-bool VideoCaptureBufferPool::GpuMemoryBufferTracker::ShareToProcess2(
- int plane,
- base::ProcessHandle process_handle,
- gfx::GpuMemoryBufferHandle* new_handle) {
- DCHECK_LE(plane, static_cast<int>(gpu_memory_buffers_.size()));
-
- const auto& current_gmb_handle = gpu_memory_buffers_[plane]->GetHandle();
- switch (current_gmb_handle.type) {
- case gfx::EMPTY_BUFFER:
+ private:
+ // A simple proxy that implements the BufferHandle interface, providing
+ // accessors to GpuMemoryBufferTracker's memory and properties.
+ class GpuMemoryBufferBufferHandle
+ : public VideoCaptureBufferPool::BufferHandle {
+ public:
+ // |tracker| must outlive GpuMemoryBufferBufferHandle. This is ensured since
+ // a tracker is pinned until ownership of this GpuMemoryBufferBufferHandle
+ // is returned to VideoCaptureBufferPool.
+ explicit GpuMemoryBufferBufferHandle(GpuMemoryBufferTracker* tracker)
+ : tracker_(tracker) {}
+ ~GpuMemoryBufferBufferHandle() override {}
+
+ gfx::Size dimensions() const override { return tracker_->dimensions(); }
+ size_t mapped_size() const override {
+ return tracker_->dimensions().GetArea();
+ }
+ void* data(int plane) override {
+ DCHECK_GE(plane, 0);
+ DCHECK_LT(plane, static_cast<int>(tracker_->gpu_memory_buffers_.size()));
+ DCHECK(tracker_->gpu_memory_buffers_[plane]);
+ return tracker_->gpu_memory_buffers_[plane]->memory(0);
+ }
+ ClientBuffer AsClientBuffer(int plane) override {
+ DCHECK_GE(plane, 0);
+ DCHECK_LT(plane, static_cast<int>(tracker_->gpu_memory_buffers_.size()));
+ return tracker_->gpu_memory_buffers_[plane]->AsClientBuffer();
+ }
+#if defined(OS_POSIX) && !defined(OS_MACOSX)
+ base::FileDescriptor AsPlatformFile() override {
NOTREACHED();
- return false;
- case gfx::SHARED_MEMORY_BUFFER: {
- DCHECK(base::SharedMemory::IsHandleValid(current_gmb_handle.handle));
- base::SharedMemory shared_memory(
- base::SharedMemory::DuplicateHandle(current_gmb_handle.handle),
- false);
- shared_memory.ShareToProcess(process_handle, &new_handle->handle);
- DCHECK(base::SharedMemory::IsHandleValid(new_handle->handle));
- new_handle->type = gfx::SHARED_MEMORY_BUFFER;
- return true;
+ return base::FileDescriptor();
}
- case gfx::IO_SURFACE_BUFFER:
- case gfx::SURFACE_TEXTURE_BUFFER:
- case gfx::OZONE_NATIVE_PIXMAP:
- *new_handle = current_gmb_handle;
- return true;
- }
- NOTREACHED();
- return true;
-}
+#endif
+
+ private:
+ GpuMemoryBufferTracker* const tracker_;
+ };
+
+ // Owned references to GpuMemoryBuffers.
+ std::vector<std::unique_ptr<gfx::GpuMemoryBuffer>> gpu_memory_buffers_;
+};
// static
-scoped_ptr<VideoCaptureBufferPool::Tracker>
+std::unique_ptr<VideoCaptureBufferPool::Tracker>
VideoCaptureBufferPool::Tracker::CreateTracker(
media::VideoPixelStorage storage) {
switch (storage) {
case media::PIXEL_STORAGE_GPUMEMORYBUFFER:
- return make_scoped_ptr(new GpuMemoryBufferTracker());
+ return base::WrapUnique(new GpuMemoryBufferTracker());
case media::PIXEL_STORAGE_CPU:
- return make_scoped_ptr(new SharedMemTracker());
+ return base::WrapUnique(new SharedMemTracker());
}
NOTREACHED();
- return scoped_ptr<VideoCaptureBufferPool::Tracker>();
+ return std::unique_ptr<VideoCaptureBufferPool::Tracker>();
}
VideoCaptureBufferPool::Tracker::~Tracker() {}
VideoCaptureBufferPool::VideoCaptureBufferPool(int count)
: count_(count),
- next_buffer_id_(0) {
+ next_buffer_id_(0),
+ last_relinquished_buffer_id_(kInvalidId) {
DCHECK_GT(count, 0);
}
@@ -318,27 +287,26 @@ bool VideoCaptureBufferPool::ShareToProcess2(
return false;
}
-scoped_ptr<VideoCaptureBufferPool::BufferHandle>
+std::unique_ptr<VideoCaptureBufferPool::BufferHandle>
VideoCaptureBufferPool::GetBufferHandle(int buffer_id) {
base::AutoLock lock(lock_);
Tracker* tracker = GetTracker(buffer_id);
if (!tracker) {
NOTREACHED() << "Invalid buffer_id.";
- return scoped_ptr<BufferHandle>();
+ return std::unique_ptr<BufferHandle>();
}
DCHECK(tracker->held_by_producer());
return tracker->GetBufferHandle();
}
-int VideoCaptureBufferPool::ReserveForProducer(
- media::VideoPixelFormat format,
- media::VideoPixelStorage storage,
- const gfx::Size& dimensions,
- int* buffer_id_to_drop) {
+int VideoCaptureBufferPool::ReserveForProducer(const gfx::Size& dimensions,
+ media::VideoPixelFormat format,
+ media::VideoPixelStorage storage,
+ int* buffer_id_to_drop) {
base::AutoLock lock(lock_);
- return ReserveForProducerInternal(format, storage, dimensions,
+ return ReserveForProducerInternal(dimensions, format, storage,
buffer_id_to_drop);
}
@@ -351,6 +319,7 @@ void VideoCaptureBufferPool::RelinquishProducerReservation(int buffer_id) {
}
DCHECK(tracker->held_by_producer());
tracker->set_held_by_producer(false);
+ last_relinquished_buffer_id_ = buffer_id;
}
void VideoCaptureBufferPool::HoldForConsumers(
@@ -385,6 +354,36 @@ void VideoCaptureBufferPool::RelinquishConsumerHold(int buffer_id,
num_clients);
}
+int VideoCaptureBufferPool::ResurrectLastForProducer(
+ const gfx::Size& dimensions,
+ media::VideoPixelFormat format,
+ media::VideoPixelStorage storage) {
+ base::AutoLock lock(lock_);
+
+ // Return early if the last relinquished buffer has been re-used already.
+ if (last_relinquished_buffer_id_ == kInvalidId)
+ return kInvalidId;
+
+ // If there are no consumers reading from this buffer, then it's safe to
+ // provide this buffer back to the producer (because the producer may
+ // potentially modify the content). Check that the expected dimensions,
+ // format, and storage match.
+ TrackerMap::iterator it = trackers_.find(last_relinquished_buffer_id_);
+ DCHECK(it != trackers_.end());
+ DCHECK(!it->second->held_by_producer());
+ if (it->second->consumer_hold_count() == 0 &&
+ it->second->dimensions() == dimensions &&
+ it->second->pixel_format() == format &&
+ it->second->storage_type() == storage) {
+ it->second->set_held_by_producer(true);
+ const int resurrected_buffer_id = last_relinquished_buffer_id_;
+ last_relinquished_buffer_id_ = kInvalidId;
+ return resurrected_buffer_id;
+ }
+
+ return kInvalidId;
+}
+
double VideoCaptureBufferPool::GetBufferPoolUtilization() const {
base::AutoLock lock(lock_);
int num_buffers_held = 0;
@@ -397,9 +396,9 @@ double VideoCaptureBufferPool::GetBufferPoolUtilization() const {
}
int VideoCaptureBufferPool::ReserveForProducerInternal(
+ const gfx::Size& dimensions,
media::VideoPixelFormat pixel_format,
media::VideoPixelStorage storage_type,
- const gfx::Size& dimensions,
int* buffer_id_to_drop) {
lock_.AssertAcquired();
@@ -408,32 +407,50 @@ int VideoCaptureBufferPool::ReserveForProducerInternal(
// largest one that's not big enough, in case we have to reallocate a tracker.
*buffer_id_to_drop = kInvalidId;
size_t largest_size_in_pixels = 0;
+ TrackerMap::iterator tracker_of_last_resort = trackers_.end();
TrackerMap::iterator tracker_to_drop = trackers_.end();
for (TrackerMap::iterator it = trackers_.begin(); it != trackers_.end();
++it) {
Tracker* const tracker = it->second;
if (!tracker->consumer_hold_count() && !tracker->held_by_producer()) {
- if (tracker->pixel_count() >= size_in_pixels &&
+ if (tracker->max_pixel_count() >= size_in_pixels &&
(tracker->pixel_format() == pixel_format) &&
(tracker->storage_type() == storage_type)) {
+ if (it->first == last_relinquished_buffer_id_) {
+ // This buffer would do just fine, but avoid returning it because the
+ // client may want to resurrect it. It will be returned perforce if
+ // the pool has reached it's maximum limit (see code below).
+ tracker_of_last_resort = it;
+ continue;
+ }
// Existing tracker is big enough and has correct format. Reuse it.
+ tracker->set_dimensions(dimensions);
tracker->set_held_by_producer(true);
return it->first;
}
- if (tracker->pixel_count() > largest_size_in_pixels) {
- largest_size_in_pixels = tracker->pixel_count();
+ if (tracker->max_pixel_count() > largest_size_in_pixels) {
+ largest_size_in_pixels = tracker->max_pixel_count();
tracker_to_drop = it;
}
}
}
// Preferably grow the pool by creating a new tracker. If we're at maximum
- // size, then reallocate by deleting an existing one instead.
+ // size, then try using |tracker_of_last_resort| or reallocate by deleting an
+ // existing one instead.
if (trackers_.size() == static_cast<size_t>(count_)) {
+ if (tracker_of_last_resort != trackers_.end()) {
+ last_relinquished_buffer_id_ = kInvalidId;
+ tracker_of_last_resort->second->set_dimensions(dimensions);
+ tracker_of_last_resort->second->set_held_by_producer(true);
+ return tracker_of_last_resort->first;
+ }
if (tracker_to_drop == trackers_.end()) {
// We're out of space, and can't find an unused tracker to reallocate.
return kInvalidId;
}
+ if (tracker_to_drop->first == last_relinquished_buffer_id_)
+ last_relinquished_buffer_id_ = kInvalidId;
*buffer_id_to_drop = tracker_to_drop->first;
delete tracker_to_drop->second;
trackers_.erase(tracker_to_drop);
@@ -442,10 +459,10 @@ int VideoCaptureBufferPool::ReserveForProducerInternal(
// Create the new tracker.
const int buffer_id = next_buffer_id_++;
- scoped_ptr<Tracker> tracker = Tracker::CreateTracker(storage_type);
+ std::unique_ptr<Tracker> tracker = Tracker::CreateTracker(storage_type);
// TODO(emircan): We pass the lock here to solve GMB allocation issue, see
// crbug.com/545238.
- if (!tracker->Init(pixel_format, storage_type, dimensions, &lock_)) {
+ if (!tracker->Init(dimensions, pixel_format, storage_type, &lock_)) {
DLOG(ERROR) << "Error initializing Tracker";
return kInvalidId;
}
diff --git a/chromium/content/browser/renderer_host/media/video_capture_buffer_pool.h b/chromium/content/browser/renderer_host/media/video_capture_buffer_pool.h
index c69a842a79b..ba92d4d4f86 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_buffer_pool.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_buffer_pool.h
@@ -58,7 +58,7 @@ class CONTENT_EXPORT VideoCaptureBufferPool
virtual size_t mapped_size() const = 0;
virtual void* data(int plane) = 0;
virtual ClientBuffer AsClientBuffer(int plane) = 0;
-#if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS))
+#if defined(OS_POSIX) && !defined(OS_MACOSX)
virtual base::FileDescriptor AsPlatformFile() = 0;
#endif
};
@@ -76,7 +76,7 @@ class CONTENT_EXPORT VideoCaptureBufferPool
gfx::GpuMemoryBufferHandle* new_handle);
// Try and obtain a BufferHandle for |buffer_id|.
- scoped_ptr<BufferHandle> GetBufferHandle(int buffer_id);
+ std::unique_ptr<BufferHandle> GetBufferHandle(int buffer_id);
// Reserve or allocate a buffer to support a packed frame of |dimensions| of
// pixel |format| and return its id. This will fail (returning kInvalidId) if
@@ -91,9 +91,9 @@ class CONTENT_EXPORT VideoCaptureBufferPool
// On occasion, this call will decide to free an old buffer to make room for a
// new allocation at a larger size. If so, the ID of the destroyed buffer is
// returned via |buffer_id_to_drop|.
- int ReserveForProducer(media::VideoPixelFormat format,
+ int ReserveForProducer(const gfx::Size& dimensions,
+ media::VideoPixelFormat format,
media::VideoPixelStorage storage,
- const gfx::Size& dimensions,
int* buffer_id_to_drop);
// Indicate that a buffer held for the producer should be returned back to the
@@ -111,6 +111,18 @@ class CONTENT_EXPORT VideoCaptureBufferPool
// done, a buffer is returned to the pool for reuse.
void RelinquishConsumerHold(int buffer_id, int num_clients);
+ // Attempt to reserve the same buffer that was relinquished in the last call
+ // to RelinquishProducerReservation(). If the buffer is not still being
+ // consumed, and has not yet been re-used since being consumed, and the
+ // specified |dimensions|, |format|, and |storage| agree with its last
+ // reservation, this will succeed. Otherwise, |kInvalidId| will be returned.
+ //
+ // A producer may assume the content of the buffer has been preserved and may
+ // also make modifications.
+ int ResurrectLastForProducer(const gfx::Size& dimensions,
+ media::VideoPixelFormat format,
+ media::VideoPixelStorage storage);
+
// Returns a snapshot of the current number of buffers in-use divided by the
// maximum |count_|.
double GetBufferPoolUtilization() const;
@@ -122,18 +134,23 @@ class CONTENT_EXPORT VideoCaptureBufferPool
// Tracker carries indication of pixel format and storage type.
class Tracker {
public:
- static scoped_ptr<Tracker> CreateTracker(media::VideoPixelStorage storage);
+ static std::unique_ptr<Tracker> CreateTracker(
+ media::VideoPixelStorage storage);
Tracker()
- : pixel_count_(0), held_by_producer_(false), consumer_hold_count_(0) {}
- virtual bool Init(media::VideoPixelFormat format,
+ : max_pixel_count_(0),
+ held_by_producer_(false),
+ consumer_hold_count_(0) {}
+ virtual bool Init(const gfx::Size& dimensions,
+ media::VideoPixelFormat format,
media::VideoPixelStorage storage_type,
- const gfx::Size& dimensions,
base::Lock* lock) = 0;
virtual ~Tracker();
- size_t pixel_count() const { return pixel_count_; }
- void set_pixel_count(size_t count) { pixel_count_ = count; }
+ const gfx::Size& dimensions() const { return dimensions_; }
+ void set_dimensions(const gfx::Size& dim) { dimensions_ = dim; }
+ size_t max_pixel_count() const { return max_pixel_count_; }
+ void set_max_pixel_count(size_t count) { max_pixel_count_ = count; }
media::VideoPixelFormat pixel_format() const {
return pixel_format_;
}
@@ -151,7 +168,7 @@ class CONTENT_EXPORT VideoCaptureBufferPool
// Returns a handle to the underlying storage, be that a block of Shared
// Memory, or a GpuMemoryBuffer.
- virtual scoped_ptr<BufferHandle> GetBufferHandle() = 0;
+ virtual std::unique_ptr<BufferHandle> GetBufferHandle() = 0;
virtual bool ShareToProcess(base::ProcessHandle process_handle,
base::SharedMemoryHandle* new_handle) = 0;
@@ -160,11 +177,17 @@ class CONTENT_EXPORT VideoCaptureBufferPool
gfx::GpuMemoryBufferHandle* new_handle) = 0;
private:
- size_t pixel_count_;
+ // |dimensions_| may change as a Tracker is re-used, but |max_pixel_count_|,
+ // |pixel_format_|, and |storage_type_| are set once for the lifetime of a
+ // Tracker.
+ gfx::Size dimensions_;
+ size_t max_pixel_count_;
media::VideoPixelFormat pixel_format_;
media::VideoPixelStorage storage_type_;
+
// Indicates whether this Tracker is currently referenced by the producer.
bool held_by_producer_;
+
// Number of consumer processes which hold this Tracker.
int consumer_hold_count_;
};
@@ -172,9 +195,9 @@ class CONTENT_EXPORT VideoCaptureBufferPool
friend class base::RefCountedThreadSafe<VideoCaptureBufferPool>;
virtual ~VideoCaptureBufferPool();
- int ReserveForProducerInternal(media::VideoPixelFormat format,
+ int ReserveForProducerInternal(const gfx::Size& dimensions,
+ media::VideoPixelFormat format,
media::VideoPixelStorage storage,
- const gfx::Size& dimensions,
int* tracker_id_to_drop);
Tracker* GetTracker(int buffer_id);
@@ -188,6 +211,10 @@ class CONTENT_EXPORT VideoCaptureBufferPool
// The ID of the next buffer.
int next_buffer_id_;
+ // The ID of the buffer last relinquished by the producer (a candidate for
+ // resurrection).
+ int last_relinquished_buffer_id_;
+
// The buffers, indexed by the first parameter, a buffer id.
using TrackerMap = std::map<int, Tracker*>;
TrackerMap trackers_;
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 21c61326024..cb867b5900f 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
@@ -9,12 +9,15 @@
#include <stddef.h>
#include <stdint.h>
#include <string.h>
+
+#include <memory>
#include <utility>
+#include <vector>
#include "base/bind.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "build/build_config.h"
#include "cc/test/test_context_provider.h"
@@ -102,11 +105,12 @@ class VideoCaptureBufferPoolTest
public:
StubBrowserGpuMemoryBufferManager() : BrowserGpuMemoryBufferManager(1, 1) {}
- scoped_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer(
+ std::unique_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer(
const gfx::Size& size,
gfx::BufferFormat format,
- gfx::BufferUsage usage) override {
- return make_scoped_ptr(new MockGpuMemoryBuffer(size));
+ gfx::BufferUsage usage,
+ int32_t surface_id) override {
+ return base::WrapUnique(new MockGpuMemoryBuffer(size));
}
};
class MockBufferQueue : public BufferQueue {
@@ -130,7 +134,7 @@ class VideoCaptureBufferPoolTest
class Buffer {
public:
Buffer(const scoped_refptr<VideoCaptureBufferPool> pool,
- scoped_ptr<VideoCaptureBufferPool::BufferHandle> buffer_handle,
+ std::unique_ptr<VideoCaptureBufferPool::BufferHandle> buffer_handle,
int id)
: id_(id), pool_(pool), buffer_handle_(std::move(buffer_handle)) {}
~Buffer() { pool_->RelinquishProducerReservation(id()); }
@@ -141,7 +145,7 @@ class VideoCaptureBufferPoolTest
private:
const int id_;
const scoped_refptr<VideoCaptureBufferPool> pool_;
- const scoped_ptr<VideoCaptureBufferPool::BufferHandle> buffer_handle_;
+ const std::unique_ptr<VideoCaptureBufferPool::BufferHandle> buffer_handle_;
};
VideoCaptureBufferPoolTest()
@@ -165,8 +169,9 @@ class VideoCaptureBufferPoolTest
expected_dropped_id_ = expected_dropped_id;
}
- scoped_ptr<Buffer> ReserveBuffer(const gfx::Size& dimensions,
- PixelFormatAndStorage format_and_storage) {
+ std::unique_ptr<Buffer> ReserveBuffer(
+ const gfx::Size& dimensions,
+ PixelFormatAndStorage format_and_storage) {
// To verify that ReserveBuffer always sets |buffer_id_to_drop|,
// initialize it to something different than the expected value.
int buffer_id_to_drop = ~expected_dropped_id_;
@@ -175,26 +180,38 @@ class VideoCaptureBufferPoolTest
<< media::VideoPixelFormatToString(format_and_storage.pixel_format)
<< " " << dimensions.ToString();
const int buffer_id = pool_->ReserveForProducer(
- format_and_storage.pixel_format, format_and_storage.pixel_storage,
- dimensions, &buffer_id_to_drop);
+ dimensions, format_and_storage.pixel_format,
+ format_and_storage.pixel_storage, &buffer_id_to_drop);
if (buffer_id == VideoCaptureBufferPool::kInvalidId)
- return scoped_ptr<Buffer>();
+ return std::unique_ptr<Buffer>();
EXPECT_EQ(expected_dropped_id_, buffer_id_to_drop);
- scoped_ptr<VideoCaptureBufferPool::BufferHandle> buffer_handle =
+ std::unique_ptr<VideoCaptureBufferPool::BufferHandle> buffer_handle =
pool_->GetBufferHandle(buffer_id);
- return scoped_ptr<Buffer>(
+ return std::unique_ptr<Buffer>(
new Buffer(pool_, std::move(buffer_handle), buffer_id));
}
+ std::unique_ptr<Buffer> ResurrectLastBuffer(
+ const gfx::Size& dimensions,
+ PixelFormatAndStorage format_and_storage) {
+ const int buffer_id = pool_->ResurrectLastForProducer(
+ dimensions, format_and_storage.pixel_format,
+ format_and_storage.pixel_storage);
+ if (buffer_id == VideoCaptureBufferPool::kInvalidId)
+ return std::unique_ptr<Buffer>();
+ return std::unique_ptr<Buffer>(
+ new Buffer(pool_, pool_->GetBufferHandle(buffer_id), buffer_id));
+ }
+
base::MessageLoop loop_;
int expected_dropped_id_;
scoped_refptr<VideoCaptureBufferPool> pool_;
private:
#if !defined(OS_ANDROID)
- scoped_ptr<StubBrowserGpuMemoryBufferManager> gpu_memory_buffer_manager_;
- scoped_ptr<MockBufferQueue> output_surface_;
+ std::unique_ptr<StubBrowserGpuMemoryBufferManager> gpu_memory_buffer_manager_;
+ std::unique_ptr<MockBufferQueue> output_surface_;
#endif
DISALLOW_COPY_AND_ASSIGN(VideoCaptureBufferPoolTest);
@@ -215,13 +232,13 @@ TEST_P(VideoCaptureBufferPoolTest, BufferPool) {
// reserved.
ASSERT_EQ(0.0, pool_->GetBufferPoolUtilization());
- scoped_ptr<Buffer> buffer1 = ReserveBuffer(size_lo, GetParam());
+ std::unique_ptr<Buffer> buffer1 = ReserveBuffer(size_lo, GetParam());
ASSERT_NE(nullptr, buffer1.get());
ASSERT_EQ(1.0 / kTestBufferPoolSize, pool_->GetBufferPoolUtilization());
- scoped_ptr<Buffer> buffer2 = ReserveBuffer(size_lo, GetParam());
+ std::unique_ptr<Buffer> buffer2 = ReserveBuffer(size_lo, GetParam());
ASSERT_NE(nullptr, buffer2.get());
ASSERT_EQ(2.0 / kTestBufferPoolSize, pool_->GetBufferPoolUtilization());
- scoped_ptr<Buffer> buffer3 = ReserveBuffer(size_lo, GetParam());
+ std::unique_ptr<Buffer> buffer3 = ReserveBuffer(size_lo, GetParam());
ASSERT_NE(nullptr, buffer3.get());
ASSERT_EQ(3.0 / kTestBufferPoolSize, pool_->GetBufferPoolUtilization());
@@ -251,7 +268,7 @@ TEST_P(VideoCaptureBufferPoolTest, BufferPool) {
// Release 1st buffer and retry; this should succeed.
buffer1.reset();
ASSERT_EQ(2.0 / kTestBufferPoolSize, pool_->GetBufferPoolUtilization());
- scoped_ptr<Buffer> buffer4 = ReserveBuffer(size_lo, GetParam());
+ std::unique_ptr<Buffer> buffer4 = ReserveBuffer(size_lo, GetParam());
ASSERT_NE(nullptr, buffer4.get());
ASSERT_EQ(3.0 / kTestBufferPoolSize, pool_->GetBufferPoolUtilization());
@@ -371,6 +388,138 @@ TEST_P(VideoCaptureBufferPoolTest, BufferPool) {
buffer4.reset();
}
+// Tests that a previously-released buffer can be immediately resurrected under
+// normal conditions.
+TEST_P(VideoCaptureBufferPoolTest, ResurrectsLastBuffer) {
+ ExpectDroppedId(VideoCaptureBufferPool::kInvalidId);
+
+ // At the start, there should be nothing to resurrect.
+ std::unique_ptr<Buffer> resurrected =
+ ResurrectLastBuffer(gfx::Size(10, 10), GetParam());
+ ASSERT_EQ(nullptr, resurrected.get());
+
+ // Reserve a 10x10 buffer and fill it with 0xab values.
+ std::unique_ptr<Buffer> original =
+ ReserveBuffer(gfx::Size(10, 10), GetParam());
+ ASSERT_NE(nullptr, original.get());
+ const size_t original_mapped_size = original->mapped_size();
+ memset(original->data(), 0xab, original_mapped_size);
+
+ // Try to resurrect a buffer BEFORE releasing |original|. This should fail.
+ resurrected = ResurrectLastBuffer(gfx::Size(10, 10), GetParam());
+ ASSERT_EQ(nullptr, resurrected.get());
+
+ // Release |original| and then try to resurrect it. Confirm the content of
+ // the resurrected buffer is a fill of 0xab values.
+ original.reset();
+ resurrected = ResurrectLastBuffer(gfx::Size(10, 10), GetParam());
+ ASSERT_NE(nullptr, resurrected.get());
+ ASSERT_EQ(original_mapped_size, resurrected->mapped_size());
+ uint8_t* resurrected_memory = reinterpret_cast<uint8_t*>(resurrected->data());
+ for (size_t i = 0; i < original_mapped_size; ++i)
+ EXPECT_EQ(0xab, resurrected_memory[i]) << "Mismatch at byte offset: " << i;
+
+ // Now, fill the resurrected buffer with 0xbc values and release it.
+ memset(resurrected_memory, 0xbc, original_mapped_size);
+ resurrected.reset();
+
+ // Finally, resurrect the buffer again, and confirm it contains a fill of 0xbc
+ // values.
+ resurrected = ResurrectLastBuffer(gfx::Size(10, 10), GetParam());
+ ASSERT_NE(nullptr, resurrected.get());
+ ASSERT_EQ(original_mapped_size, resurrected->mapped_size());
+ resurrected_memory = reinterpret_cast<uint8_t*>(resurrected->data());
+ for (size_t i = 0; i < original_mapped_size; ++i)
+ EXPECT_EQ(0xbc, resurrected_memory[i]) << "Mismatch at byte offset: " << i;
+}
+
+// Tests that a buffer cannot be resurrected if its properties do not match.
+TEST_P(VideoCaptureBufferPoolTest, DoesNotResurrectIfPropertiesNotMatched) {
+ ExpectDroppedId(VideoCaptureBufferPool::kInvalidId);
+
+ // Reserve a 10x10 buffer, fill it with 0xcd values, and release it.
+ std::unique_ptr<Buffer> original =
+ ReserveBuffer(gfx::Size(10, 10), GetParam());
+ ASSERT_NE(nullptr, original.get());
+ const size_t original_mapped_size = original->mapped_size();
+ memset(original->data(), 0xcd, original_mapped_size);
+ original.reset();
+
+ // Expect that the buffer cannot be resurrected if the dimensions do not
+ // match.
+ std::unique_ptr<Buffer> resurrected =
+ ResurrectLastBuffer(gfx::Size(8, 8), GetParam());
+ ASSERT_EQ(nullptr, resurrected.get());
+
+ // Expect that the buffer cannot be resurrected if the pixel format does not
+ // match.
+ PixelFormatAndStorage altered_format_or_storage = GetParam();
+ altered_format_or_storage.pixel_format =
+ (altered_format_or_storage.pixel_format == media::PIXEL_FORMAT_I420
+ ? media::PIXEL_FORMAT_ARGB
+ : media::PIXEL_FORMAT_I420);
+ resurrected =
+ ResurrectLastBuffer(gfx::Size(10, 10), altered_format_or_storage);
+ ASSERT_EQ(nullptr, resurrected.get());
+
+ // Expect that the buffer cannot be resurrected if the pixel storage does not
+ // match.
+ altered_format_or_storage = GetParam();
+ altered_format_or_storage.pixel_storage =
+ (altered_format_or_storage.pixel_storage == media::PIXEL_STORAGE_CPU)
+ ? media::PIXEL_STORAGE_GPUMEMORYBUFFER
+ : media::PIXEL_STORAGE_CPU;
+ resurrected =
+ ResurrectLastBuffer(gfx::Size(10, 10), altered_format_or_storage);
+ ASSERT_EQ(nullptr, resurrected.get());
+
+ // Finally, check that the buffer CAN be resurrected if all properties match.
+ resurrected = ResurrectLastBuffer(gfx::Size(10, 10), GetParam());
+ ASSERT_NE(nullptr, resurrected.get());
+ ASSERT_EQ(original_mapped_size, resurrected->mapped_size());
+ uint8_t* resurrected_memory = reinterpret_cast<uint8_t*>(resurrected->data());
+ for (size_t i = 0; i < original_mapped_size; ++i)
+ EXPECT_EQ(0xcd, resurrected_memory[i]) << "Mismatch at byte offset: " << i;
+}
+
+// Tests that the buffers are managed by the pool such that the last-released
+// buffer is kept around as long as possible (for successful resurrection).
+TEST_P(VideoCaptureBufferPoolTest, AvoidsClobberingForResurrectingLastBuffer) {
+ ExpectDroppedId(VideoCaptureBufferPool::kInvalidId);
+
+ // Reserve a 10x10 buffer, fill it with 0xde values, and release it.
+ std::unique_ptr<Buffer> original =
+ ReserveBuffer(gfx::Size(10, 10), GetParam());
+ ASSERT_NE(nullptr, original.get());
+ const size_t original_mapped_size = original->mapped_size();
+ memset(original->data(), 0xde, original_mapped_size);
+ original.reset();
+
+ // Reserve all but one of the pool's buffers.
+ std::vector<std::unique_ptr<Buffer>> held_buffers;
+ for (int i = 0; i < kTestBufferPoolSize - 1; ++i) {
+ held_buffers.push_back(ReserveBuffer(gfx::Size(10, 10), GetParam()));
+ ASSERT_NE(nullptr, held_buffers.back().get());
+ }
+
+ // Now, attempt to resurrect the original buffer. This should succeed.
+ std::unique_ptr<Buffer> resurrected =
+ ResurrectLastBuffer(gfx::Size(10, 10), GetParam());
+ ASSERT_NE(nullptr, resurrected.get());
+ ASSERT_EQ(original_mapped_size, resurrected->mapped_size());
+ uint8_t* resurrected_memory = reinterpret_cast<uint8_t*>(resurrected->data());
+ for (size_t i = 0; i < original_mapped_size; ++i)
+ EXPECT_EQ(0xde, resurrected_memory[i]) << "Mismatch at byte offset: " << i;
+ resurrected.reset();
+
+ // Reserve the final buffer in the pool, and then confirm resurrection does
+ // not succeed.
+ held_buffers.push_back(ReserveBuffer(gfx::Size(10, 10), GetParam()));
+ ASSERT_NE(nullptr, held_buffers.back().get());
+ resurrected = ResurrectLastBuffer(gfx::Size(10, 10), GetParam());
+ ASSERT_EQ(nullptr, resurrected.get());
+}
+
INSTANTIATE_TEST_CASE_P(,
VideoCaptureBufferPoolTest,
testing::ValuesIn(kCapturePixelFormatAndStorages));
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 6cde5f0d671..bad1a51a0ca 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller.cc
@@ -12,15 +12,16 @@
#include "base/bind.h"
#include "base/command_line.h"
+#include "base/memory/ptr_util.h"
#include "base/metrics/histogram.h"
#include "base/metrics/sparse_histogram.h"
#include "base/stl_util.h"
#include "build/build_config.h"
+#include "content/browser/compositor/gl_helper.h"
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/video_capture_buffer_pool.h"
#include "content/browser/renderer_host/media/video_capture_device_client.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
-#include "content/common/gpu/client/gl_helper.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "media/base/video_frame.h"
@@ -141,10 +142,10 @@ VideoCaptureController::GetWeakPtrForIOThread() {
return weak_ptr_factory_.GetWeakPtr();
}
-scoped_ptr<media::VideoCaptureDevice::Client>
+std::unique_ptr<media::VideoCaptureDevice::Client>
VideoCaptureController::NewDeviceClient() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- return make_scoped_ptr(new VideoCaptureDeviceClient(
+ return base::WrapUnique(new VideoCaptureDeviceClient(
this->GetWeakPtrForIOThread(), buffer_pool_));
}
@@ -260,14 +261,22 @@ int VideoCaptureController::GetClientCount() const {
return controller_clients_.size();
}
-int VideoCaptureController::GetActiveClientCount() const {
+bool VideoCaptureController::HasActiveClient() const {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- int active_client_count = 0;
for (ControllerClient* client : controller_clients_) {
if (!client->paused)
- ++active_client_count;
+ return true;
}
- return active_client_count;
+ return false;
+}
+
+bool VideoCaptureController::HasPausedClient() const {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ for (ControllerClient* client : controller_clients_) {
+ if (client->paused)
+ return true;
+ }
+ return false;
}
void VideoCaptureController::StopSession(int session_id) {
@@ -344,7 +353,7 @@ VideoCaptureController::~VideoCaptureController() {
}
void VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread(
- scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer,
+ std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer,
const scoped_refptr<VideoFrame>& frame,
const base::TimeTicks& timestamp) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -357,7 +366,8 @@ void VideoCaptureController::DoIncomingCapturedVideoFrameOnIOThread(
frame->metadata()->SetDouble(VideoFrameMetadata::FRAME_RATE,
video_capture_format_.frame_rate);
}
- scoped_ptr<base::DictionaryValue> metadata(new base::DictionaryValue());
+ std::unique_ptr<base::DictionaryValue> metadata(
+ new base::DictionaryValue());
frame->metadata()->MergeInternalValuesInto(metadata.get());
// Only I420 pixel format is currently supported.
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 66611445963..8baca918c99 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_controller.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_controller.h
@@ -41,11 +41,11 @@
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_CONTROLLER_H_
#include <list>
+#include <memory>
#include "base/compiler_specific.h"
#include "base/macros.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 "content/browser/renderer_host/media/video_capture_controller_event_handler.h"
@@ -71,7 +71,7 @@ class CONTENT_EXPORT VideoCaptureController {
// Return a new VideoCaptureDeviceClient to forward capture events to this
// instance.
- scoped_ptr<media::VideoCaptureDevice::Client> NewDeviceClient();
+ std::unique_ptr<media::VideoCaptureDevice::Client> NewDeviceClient();
// Start video capturing and try to use the resolution specified in |params|.
// Buffers will be shared to the client as necessary. The client will continue
@@ -99,8 +99,11 @@ class CONTENT_EXPORT VideoCaptureController {
int GetClientCount() const;
- // Return the number of clients that aren't paused.
- int GetActiveClientCount() const;
+ // Return true if there is client that isn't paused.
+ bool HasActiveClient() const;
+
+ // Return true if there is client paused.
+ bool HasPausedClient() const;
// API called directly by VideoCaptureManager in case the device is
// prematurely closed.
@@ -124,7 +127,7 @@ class CONTENT_EXPORT VideoCaptureController {
// Worker functions on IO thread. Called by the VideoCaptureDeviceClient.
virtual void DoIncomingCapturedVideoFrameOnIOThread(
- scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer,
+ std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer,
const scoped_refptr<media::VideoFrame>& frame,
const base::TimeTicks& timestamp);
virtual void DoErrorOnIOThread();
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 e7d8d219012..3285de9c065 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
@@ -5,7 +5,8 @@
#ifndef CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_CONTROLLER_EVENT_HANDLER_H_
#define CONTENT_BROWSER_RENDERER_HOST_MEDIA_VIDEO_CAPTURE_CONTROLLER_EVENT_HANDLER_H_
-#include "base/memory/scoped_ptr.h"
+#include <memory>
+
#include "base/memory/shared_memory.h"
#include "content/common/content_export.h"
#include "ui/gfx/geometry/size.h"
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 99e563f50a1..0e28d307e9a 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
@@ -8,6 +8,8 @@
#include <stdint.h>
#include <string.h>
+
+#include <memory>
#include <string>
#include <utility>
@@ -16,7 +18,6 @@
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
@@ -133,10 +134,10 @@ class VideoCaptureControllerTest : public testing::Test {
}
TestBrowserThreadBundle bundle_;
- scoped_ptr<MockVideoCaptureControllerEventHandler> client_a_;
- scoped_ptr<MockVideoCaptureControllerEventHandler> client_b_;
- scoped_ptr<VideoCaptureController> controller_;
- scoped_ptr<media::VideoCaptureDevice::Client> device_;
+ std::unique_ptr<MockVideoCaptureControllerEventHandler> client_a_;
+ std::unique_ptr<MockVideoCaptureControllerEventHandler> client_b_;
+ std::unique_ptr<VideoCaptureController> controller_;
+ std::unique_ptr<media::VideoCaptureDevice::Client> device_;
private:
DISALLOW_COPY_AND_ASSIGN(VideoCaptureControllerTest);
@@ -290,9 +291,8 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
// side effect this will cause the first buffer to be shared with clients.
uint8_t buffer_no = 1;
ASSERT_EQ(0.0, device_->GetBufferPoolUtilization());
- scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer(
- device_->ReserveOutputBuffer(capture_resolution,
- media::PIXEL_FORMAT_I420,
+ std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer(
+ device_->ReserveOutputBuffer(capture_resolution, media::PIXEL_FORMAT_I420,
media::PIXEL_STORAGE_CPU));
ASSERT_TRUE(buffer.get());
ASSERT_EQ(1.0 / kPoolSize, device_->GetBufferPoolUtilization());
@@ -331,6 +331,7 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(client_a_.get());
Mock::VerifyAndClearExpectations(client_b_.get());
+
// Expect VideoCaptureController set the metadata in |video_frame| to hold a
// resource utilization of 0.5 (the largest of all reported values).
double resource_utilization_in_metadata = -1.0;
@@ -342,9 +343,8 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
// Second buffer which ought to use the same shared memory buffer. In this
// case pretend that the Buffer pointer is held by the device for a long
// delay. This shouldn't affect anything.
- scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer2 =
- device_->ReserveOutputBuffer(capture_resolution,
- media::PIXEL_FORMAT_I420,
+ std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer2 =
+ device_->ReserveOutputBuffer(capture_resolution, media::PIXEL_FORMAT_I420,
media::PIXEL_STORAGE_CPU);
ASSERT_TRUE(buffer2.get());
memset(buffer2->data(), buffer_no++, buffer2->mapped_size());
@@ -359,15 +359,27 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
base::TimeTicks());
// The buffer should be delivered to the clients in any order.
- EXPECT_CALL(*client_a_,
- DoI420BufferReady(client_a_route_1, capture_resolution))
- .Times(1);
- EXPECT_CALL(*client_b_,
- DoI420BufferReady(client_b_route_1, capture_resolution))
- .Times(1);
- EXPECT_CALL(*client_a_,
- DoI420BufferReady(client_a_route_2, capture_resolution))
- .Times(1);
+ {
+ InSequence s;
+ EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1)).Times(1);
+ EXPECT_CALL(*client_a_,
+ DoI420BufferReady(client_a_route_1, capture_resolution))
+ .Times(1);
+ }
+ {
+ InSequence s;
+ EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1)).Times(1);
+ EXPECT_CALL(*client_b_,
+ DoI420BufferReady(client_b_route_1, capture_resolution))
+ .Times(1);
+ }
+ {
+ InSequence s;
+ EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2)).Times(1);
+ EXPECT_CALL(*client_a_,
+ DoI420BufferReady(client_a_route_2, capture_resolution))
+ .Times(1);
+ }
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(client_a_.get());
Mock::VerifyAndClearExpectations(client_b_.get());
@@ -389,7 +401,7 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
// Third, fourth, and fifth buffers. Pretend they all arrive at the same time.
for (int i = 0; i < kPoolSize; i++) {
- scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer =
+ std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer =
device_->ReserveOutputBuffer(capture_resolution,
media::PIXEL_FORMAT_I420,
media::PIXEL_STORAGE_CPU);
@@ -407,23 +419,24 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
media::PIXEL_FORMAT_I420,
media::PIXEL_STORAGE_CPU).get());
- // The new client needs to be told of 3 buffers; the old clients only 2.
+ // The new client needs to be notified of the creation of |kPoolSize| buffers;
+ // the old clients only |kPoolSize - 2|.
EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_2)).Times(kPoolSize);
EXPECT_CALL(*client_b_,
DoI420BufferReady(client_b_route_2, capture_resolution))
.Times(kPoolSize);
EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_1))
- .Times(kPoolSize - 1);
+ .Times(kPoolSize - 2);
EXPECT_CALL(*client_a_,
DoI420BufferReady(client_a_route_1, capture_resolution))
.Times(kPoolSize);
EXPECT_CALL(*client_a_, DoBufferCreated(client_a_route_2))
- .Times(kPoolSize - 1);
+ .Times(kPoolSize - 2);
EXPECT_CALL(*client_a_,
DoI420BufferReady(client_a_route_2, capture_resolution))
.Times(kPoolSize);
EXPECT_CALL(*client_b_, DoBufferCreated(client_b_route_1))
- .Times(kPoolSize - 1);
+ .Times(kPoolSize - 2);
EXPECT_CALL(*client_b_,
DoI420BufferReady(client_b_route_1, capture_resolution))
.Times(kPoolSize);
@@ -438,9 +451,8 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
EXPECT_CALL(*client_b_, DoEnded(client_b_route_1)).Times(1);
controller_->StopSession(300);
// Queue up another buffer.
- scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer3 =
- device_->ReserveOutputBuffer(capture_resolution,
- media::PIXEL_FORMAT_I420,
+ std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer3 =
+ device_->ReserveOutputBuffer(capture_resolution, media::PIXEL_FORMAT_I420,
media::PIXEL_STORAGE_CPU);
ASSERT_TRUE(buffer3.get());
memset(buffer3->data(), buffer_no++, buffer3->mapped_size());
@@ -450,9 +462,8 @@ TEST_F(VideoCaptureControllerTest, NormalCaptureMultipleClients) {
device_->OnIncomingCapturedVideoFrame(std::move(buffer3), video_frame,
base::TimeTicks());
- scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer4 =
- device_->ReserveOutputBuffer(capture_resolution,
- media::PIXEL_FORMAT_I420,
+ std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer4 =
+ device_->ReserveOutputBuffer(capture_resolution, media::PIXEL_FORMAT_I420,
media::PIXEL_STORAGE_CPU);
{
// Kill A2 via session close (posts a task to disconnect, but A2 must not
@@ -506,9 +517,8 @@ TEST_F(VideoCaptureControllerTest, ErrorBeforeDeviceCreation) {
base::RunLoop().RunUntilIdle();
Mock::VerifyAndClearExpectations(client_b_.get());
- scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer(
- device_->ReserveOutputBuffer(capture_resolution,
- media::PIXEL_FORMAT_I420,
+ std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer(
+ device_->ReserveOutputBuffer(capture_resolution, media::PIXEL_FORMAT_I420,
media::PIXEL_STORAGE_CPU));
ASSERT_TRUE(buffer.get());
scoped_refptr<media::VideoFrame> video_frame =
@@ -544,7 +554,7 @@ TEST_F(VideoCaptureControllerTest, ErrorAfterDeviceCreation) {
Mock::VerifyAndClearExpectations(client_a_.get());
const gfx::Size dims(320, 240);
- scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer(
+ std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer(
device_->ReserveOutputBuffer(dims, media::PIXEL_FORMAT_I420,
media::PIXEL_STORAGE_CPU));
ASSERT_TRUE(buffer.get());
diff --git a/chromium/content/browser/renderer_host/media/video_capture_device_client.cc b/chromium/content/browser/renderer_host/media/video_capture_device_client.cc
index b4d142e99ff..cf6ad3a9814 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_device_client.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_device_client.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/location.h"
+#include "base/memory/ptr_util.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
@@ -47,7 +48,7 @@ class AutoReleaseBuffer : public media::VideoCaptureDevice::Client::Buffer {
ClientBuffer AsClientBuffer(int plane) override {
return buffer_handle_->AsClientBuffer(plane);
}
-#if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS))
+#if defined(OS_POSIX) && !defined(OS_MACOSX)
base::FileDescriptor AsPlatformFile() override {
return buffer_handle_->AsPlatformFile();
}
@@ -58,7 +59,7 @@ class AutoReleaseBuffer : public media::VideoCaptureDevice::Client::Buffer {
const int id_;
const scoped_refptr<VideoCaptureBufferPool> pool_;
- const scoped_ptr<VideoCaptureBufferPool::BufferHandle> buffer_handle_;
+ const std::unique_ptr<VideoCaptureBufferPool::BufferHandle> buffer_handle_;
};
VideoCaptureDeviceClient::VideoCaptureDeviceClient(
@@ -133,7 +134,7 @@ void VideoCaptureDeviceClient::OnIncomingCapturedData(
use_gpu_memory_buffers_ ? media::PIXEL_STORAGE_GPUMEMORYBUFFER
: media::PIXEL_STORAGE_CPU;
uint8_t *y_plane_data, *u_plane_data, *v_plane_data;
- scoped_ptr<Buffer> buffer(
+ std::unique_ptr<Buffer> buffer(
ReserveI420OutputBuffer(dimensions, output_pixel_storage, &y_plane_data,
&u_plane_data, &v_plane_data));
if (!buffer.get()) {
@@ -188,10 +189,10 @@ void VideoCaptureDeviceClient::OnIncomingCapturedData(
NOTREACHED() << "RGB24 is only available in Linux and Windows platforms";
#endif
#if defined(OS_WIN)
- // TODO(wjia): Currently, for RGB24 on WIN, capture device always
- // passes in positive src_width and src_height. Remove this hardcoded
- // value when nagative src_height is supported. The negative src_height
- // indicates that vertical flipping is needed.
+ // TODO(wjia): Currently, for RGB24 on WIN, capture device always passes
+ // in positive src_width and src_height. Remove this hardcoded value when
+ // negative src_height is supported. The negative src_height indicates
+ // that vertical flipping is needed.
flip = true;
#endif
break;
@@ -256,57 +257,7 @@ void VideoCaptureDeviceClient::OnIncomingCapturedData(
OnIncomingCapturedBuffer(std::move(buffer), output_format, timestamp);
}
-void VideoCaptureDeviceClient::OnIncomingCapturedYuvData(
- const uint8_t* y_data,
- const uint8_t* u_data,
- const uint8_t* v_data,
- size_t y_stride,
- size_t u_stride,
- size_t v_stride,
- const VideoCaptureFormat& frame_format,
- int clockwise_rotation,
- const base::TimeTicks& timestamp) {
- TRACE_EVENT0("video", "VideoCaptureDeviceClient::OnIncomingCapturedYuvData");
- DCHECK_EQ(media::PIXEL_FORMAT_I420, frame_format.pixel_format);
- DCHECK_EQ(media::PIXEL_STORAGE_CPU, frame_format.pixel_storage);
- DCHECK_EQ(0, clockwise_rotation) << "Rotation not supported";
-
- uint8_t *y_plane_data, *u_plane_data, *v_plane_data;
- scoped_ptr<Buffer> buffer(ReserveI420OutputBuffer(
- frame_format.frame_size, frame_format.pixel_storage, &y_plane_data,
- &u_plane_data, &v_plane_data));
- if (!buffer.get())
- return;
-
- const size_t dst_y_stride =
- VideoFrame::RowBytes(VideoFrame::kYPlane, media::PIXEL_FORMAT_I420,
- frame_format.frame_size.width());
- const size_t dst_u_stride =
- VideoFrame::RowBytes(VideoFrame::kUPlane, media::PIXEL_FORMAT_I420,
- frame_format.frame_size.width());
- const size_t dst_v_stride =
- VideoFrame::RowBytes(VideoFrame::kVPlane, media::PIXEL_FORMAT_I420,
- frame_format.frame_size.width());
- DCHECK_GE(y_stride, dst_y_stride);
- DCHECK_GE(u_stride, dst_u_stride);
- DCHECK_GE(v_stride, dst_v_stride);
-
- if (libyuv::I420Copy(y_data, y_stride,
- u_data, u_stride,
- v_data, v_stride,
- y_plane_data, dst_y_stride,
- u_plane_data, dst_u_stride,
- v_plane_data, dst_v_stride,
- frame_format.frame_size.width(),
- frame_format.frame_size.height())) {
- DLOG(WARNING) << "Failed to copy buffer";
- return;
- }
-
- OnIncomingCapturedBuffer(std::move(buffer), frame_format, timestamp);
-};
-
-scoped_ptr<media::VideoCaptureDevice::Client::Buffer>
+std::unique_ptr<media::VideoCaptureDevice::Client::Buffer>
VideoCaptureDeviceClient::ReserveOutputBuffer(
const gfx::Size& frame_size,
media::VideoPixelFormat pixel_format,
@@ -320,25 +271,21 @@ VideoCaptureDeviceClient::ReserveOutputBuffer(
// it's a ShMem GMB or a DmaBuf GMB.
int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId;
const int buffer_id = buffer_pool_->ReserveForProducer(
- pixel_format, pixel_storage, frame_size, &buffer_id_to_drop);
- if (buffer_id == VideoCaptureBufferPool::kInvalidId)
- return NULL;
-
- scoped_ptr<media::VideoCaptureDevice::Client::Buffer> output_buffer(
- new AutoReleaseBuffer(buffer_pool_, buffer_id));
-
+ frame_size, pixel_format, pixel_storage, &buffer_id_to_drop);
if (buffer_id_to_drop != VideoCaptureBufferPool::kInvalidId) {
BrowserThread::PostTask(BrowserThread::IO,
FROM_HERE,
base::Bind(&VideoCaptureController::DoBufferDestroyedOnIOThread,
controller_, buffer_id_to_drop));
}
-
- return output_buffer;
+ if (buffer_id == VideoCaptureBufferPool::kInvalidId)
+ return nullptr;
+ return base::WrapUnique<Buffer>(
+ new AutoReleaseBuffer(buffer_pool_, buffer_id));
}
void VideoCaptureDeviceClient::OnIncomingCapturedBuffer(
- scoped_ptr<Buffer> buffer,
+ std::unique_ptr<Buffer> buffer,
const VideoCaptureFormat& frame_format,
const base::TimeTicks& timestamp) {
// Currently, only I420 pixel format is supported.
@@ -376,7 +323,7 @@ void VideoCaptureDeviceClient::OnIncomingCapturedBuffer(
}
void VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame(
- scoped_ptr<Buffer> buffer,
+ std::unique_ptr<Buffer> buffer,
const scoped_refptr<VideoFrame>& frame,
const base::TimeTicks& timestamp) {
BrowserThread::PostTask(
@@ -390,6 +337,19 @@ void VideoCaptureDeviceClient::OnIncomingCapturedVideoFrame(
timestamp));
}
+std::unique_ptr<media::VideoCaptureDevice::Client::Buffer>
+VideoCaptureDeviceClient::ResurrectLastOutputBuffer(
+ const gfx::Size& dimensions,
+ media::VideoPixelFormat format,
+ media::VideoPixelStorage storage) {
+ const int buffer_id =
+ buffer_pool_->ResurrectLastForProducer(dimensions, format, storage);
+ if (buffer_id == VideoCaptureBufferPool::kInvalidId)
+ return nullptr;
+ return base::WrapUnique<Buffer>(
+ new AutoReleaseBuffer(buffer_pool_, buffer_id));
+}
+
void VideoCaptureDeviceClient::OnError(
const tracked_objects::Location& from_here,
const std::string& reason) {
@@ -417,7 +377,7 @@ double VideoCaptureDeviceClient::GetBufferPoolUtilization() const {
return buffer_pool_->GetBufferPoolUtilization();
}
-scoped_ptr<media::VideoCaptureDevice::Client::Buffer>
+std::unique_ptr<media::VideoCaptureDevice::Client::Buffer>
VideoCaptureDeviceClient::ReserveI420OutputBuffer(
const gfx::Size& dimensions,
media::VideoPixelStorage storage,
@@ -430,10 +390,10 @@ VideoCaptureDeviceClient::ReserveI420OutputBuffer(
DCHECK(dimensions.width());
const media::VideoPixelFormat format = media::PIXEL_FORMAT_I420;
- scoped_ptr<Buffer> buffer(ReserveOutputBuffer(
- dimensions, media::PIXEL_FORMAT_I420, storage));
+ std::unique_ptr<Buffer> buffer(
+ ReserveOutputBuffer(dimensions, media::PIXEL_FORMAT_I420, storage));
if (!buffer)
- return scoped_ptr<Buffer>();
+ return std::unique_ptr<Buffer>();
switch (storage) {
case media::PIXEL_STORAGE_CPU:
@@ -459,7 +419,7 @@ VideoCaptureDeviceClient::ReserveI420OutputBuffer(
return buffer;
}
NOTREACHED();
- return scoped_ptr<Buffer>();
+ return std::unique_ptr<Buffer>();
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/media/video_capture_device_client.h b/chromium/content/browser/renderer_host/media/video_capture_device_client.h
index 8215f5642a2..46a8d106da1 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_device_client.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_device_client.h
@@ -8,9 +8,10 @@
#include <stddef.h>
#include <stdint.h>
+#include <memory>
+
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
#include "media/capture/video/video_capture_device.h"
@@ -49,26 +50,21 @@ class CONTENT_EXPORT VideoCaptureDeviceClient
const media::VideoCaptureFormat& frame_format,
int rotation,
const base::TimeTicks& timestamp) override;
- void OnIncomingCapturedYuvData(const uint8_t* y_data,
- const uint8_t* u_data,
- const uint8_t* v_data,
- size_t y_stride,
- size_t u_stride,
- size_t v_stride,
- const media::VideoCaptureFormat& frame_format,
- int clockwise_rotation,
- const base::TimeTicks& timestamp) override;
- scoped_ptr<Buffer> ReserveOutputBuffer(
+ std::unique_ptr<Buffer> ReserveOutputBuffer(
const gfx::Size& dimensions,
media::VideoPixelFormat format,
media::VideoPixelStorage storage) override;
- void OnIncomingCapturedBuffer(scoped_ptr<Buffer> buffer,
+ void OnIncomingCapturedBuffer(std::unique_ptr<Buffer> buffer,
const media::VideoCaptureFormat& frame_format,
const base::TimeTicks& timestamp) override;
void OnIncomingCapturedVideoFrame(
- scoped_ptr<Buffer> buffer,
+ std::unique_ptr<Buffer> buffer,
const scoped_refptr<media::VideoFrame>& frame,
const base::TimeTicks& timestamp) override;
+ std::unique_ptr<Buffer> ResurrectLastOutputBuffer(
+ const gfx::Size& dimensions,
+ media::VideoPixelFormat format,
+ media::VideoPixelStorage storage) override;
void OnError(const tracked_objects::Location& from_here,
const std::string& reason) override;
void OnLog(const std::string& message) override;
@@ -87,17 +83,18 @@ class CONTENT_EXPORT VideoCaptureDeviceClient
// GpuMemoryBuffers in R_8 format representing I420 planes are reserved. The
// output buffers stay reserved and mapped for use until the Buffer objects
// are destroyed or returned.
- scoped_ptr<Buffer> ReserveI420OutputBuffer(const gfx::Size& dimensions,
- media::VideoPixelStorage storage,
- uint8_t** y_plane_data,
- uint8_t** u_plane_data,
- uint8_t** v_plane_data);
+ std::unique_ptr<Buffer> ReserveI420OutputBuffer(
+ const gfx::Size& dimensions,
+ media::VideoPixelStorage storage,
+ uint8_t** y_plane_data,
+ uint8_t** u_plane_data,
+ uint8_t** v_plane_data);
// The controller to which we post events.
const base::WeakPtr<VideoCaptureController> controller_;
// Hardware JPEG decoder.
- scoped_ptr<VideoCaptureGpuJpegDecoder> external_jpeg_decoder_;
+ std::unique_ptr<VideoCaptureGpuJpegDecoder> external_jpeg_decoder_;
// Whether |external_jpeg_decoder_| has been initialized.
bool external_jpeg_decoder_initialized_;
diff --git a/chromium/content/browser/renderer_host/media/video_capture_device_client_unittest.cc b/chromium/content/browser/renderer_host/media/video_capture_device_client_unittest.cc
index 56c0a120345..d96b9d941a8 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_device_client_unittest.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_device_client_unittest.cc
@@ -2,18 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "content/browser/renderer_host/media/video_capture_device_client.h"
+
#include <stddef.h>
+#include <memory>
+
#include "base/bind.h"
+#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "content/browser/renderer_host/media/video_capture_buffer_pool.h"
#include "content/browser/renderer_host/media/video_capture_controller.h"
-#include "content/browser/renderer_host/media/video_capture_device_client.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "media/base/limits.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -41,7 +44,7 @@ class MockVideoCaptureController : public VideoCaptureController {
MOCK_METHOD1(DoBufferDestroyedOnIOThread, void(int buffer_id_to_drop));
void DoIncomingCapturedVideoFrameOnIOThread(
- scoped_ptr<media::VideoCaptureDevice::Client::Buffer> buffer,
+ std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> buffer,
const scoped_refptr<media::VideoFrame>& frame,
const base::TimeTicks& timestamp) override {
MockDoIncomingCapturedVideoFrameOnIOThread(frame->coded_size());
@@ -60,8 +63,8 @@ class VideoCaptureDeviceClientTest : public ::testing::Test {
protected:
const content::TestBrowserThreadBundle thread_bundle_;
- const scoped_ptr<MockVideoCaptureController> controller_;
- const scoped_ptr<media::VideoCaptureDevice::Client> device_client_;
+ const std::unique_ptr<MockVideoCaptureController> controller_;
+ const std::unique_ptr<media::VideoCaptureDevice::Client> device_client_;
private:
DISALLOW_COPY_AND_ASSIGN(VideoCaptureDeviceClientTest);
@@ -79,6 +82,7 @@ TEST_F(VideoCaptureDeviceClientTest, Minimal) {
media::PIXEL_FORMAT_I420,
media::PIXEL_STORAGE_CPU);
DCHECK(device_client_.get());
+ EXPECT_CALL(*controller_, DoLogOnIOThread(_)).Times(1);
EXPECT_CALL(*controller_, MockDoIncomingCapturedVideoFrameOnIOThread(_))
.Times(1);
device_client_->OnIncomingCapturedData(data, kScratchpadSizeInBytes,
@@ -100,6 +104,7 @@ TEST_F(VideoCaptureDeviceClientTest, FailsSilentlyGivenInvalidFrameFormat) {
media::VideoPixelStorage::PIXEL_STORAGE_CPU);
DCHECK(device_client_.get());
// Expect the the call to fail silently inside the VideoCaptureDeviceClient.
+ EXPECT_CALL(*controller_, DoLogOnIOThread(_)).Times(1);
EXPECT_CALL(*controller_, MockDoIncomingCapturedVideoFrameOnIOThread(_))
.Times(0);
device_client_->OnIncomingCapturedData(data, kScratchpadSizeInBytes,
@@ -119,6 +124,7 @@ TEST_F(VideoCaptureDeviceClientTest, DropsFrameIfNoBuffer) {
media::PIXEL_STORAGE_CPU);
// We expect the second frame to be silently dropped, so these should
// only be called once despite the two frames.
+ EXPECT_CALL(*controller_, DoLogOnIOThread(_)).Times(1);
EXPECT_CALL(*controller_, MockDoIncomingCapturedVideoFrameOnIOThread(_))
.Times(1);
// Pass two frames. The second will be dropped.
@@ -132,39 +138,42 @@ TEST_F(VideoCaptureDeviceClientTest, DropsFrameIfNoBuffer) {
Mock::VerifyAndClearExpectations(controller_.get());
}
-// Tests that buffer-based capture API accepts all memory-backed pixel formats.
-TEST_F(VideoCaptureDeviceClientTest, DataCaptureInEachVideoFormatInSequence) {
+// Tests that buffer-based capture API accepts some memory-backed pixel formats.
+TEST_F(VideoCaptureDeviceClientTest, DataCaptureGoodPixelFormats) {
// The usual ReserveOutputBuffer() -> OnIncomingCapturedVideoFrame() cannot
// be used since it does not accept all pixel formats. The memory backed
// buffer OnIncomingCapturedData() is used instead, with a dummy scratchpad
// buffer.
const size_t kScratchpadSizeInBytes = 400;
unsigned char data[kScratchpadSizeInBytes] = {};
- const gfx::Size capture_resolution(10, 10);
- ASSERT_GE(kScratchpadSizeInBytes, capture_resolution.GetArea() * 4u)
+ const gfx::Size kCaptureResolution(10, 10);
+ ASSERT_GE(kScratchpadSizeInBytes, kCaptureResolution.GetArea() * 4u)
<< "Scratchpad is too small to hold the largest pixel format (ARGB).";
- for (int format = 0; format < media::PIXEL_FORMAT_MAX;
- ++format) {
- // Conversion from some formats are unsupported.
- if (format == media::PIXEL_FORMAT_UNKNOWN ||
- format == media::PIXEL_FORMAT_YV16 ||
- format == media::PIXEL_FORMAT_YV12A ||
- format == media::PIXEL_FORMAT_YV24 ||
- format == media::PIXEL_FORMAT_ARGB ||
- format == media::PIXEL_FORMAT_XRGB ||
- format == media::PIXEL_FORMAT_MJPEG ||
- format == media::PIXEL_FORMAT_MT21) {
- continue;
- }
-#if !defined(OS_LINUX) && !defined(OS_WIN)
- if (format == media::PIXEL_FORMAT_RGB24){
- continue;
- }
+ media::VideoCaptureParams params;
+ params.requested_format = media::VideoCaptureFormat(
+ kCaptureResolution, 30.0f, media::PIXEL_FORMAT_UNKNOWN);
+
+ // Only use the VideoPixelFormats that we know supported. Do not add
+ // PIXEL_FORMAT_MJPEG since it would need a real JPEG header.
+ const media::VideoPixelFormat kSupportedFormats[] = {
+ media::PIXEL_FORMAT_I420,
+ media::PIXEL_FORMAT_YV12,
+ media::PIXEL_FORMAT_NV12,
+ media::PIXEL_FORMAT_NV21,
+ media::PIXEL_FORMAT_YUY2,
+ media::PIXEL_FORMAT_UYVY,
+#if defined(OS_WIN) || defined(OS_LINUX)
+ media::PIXEL_FORMAT_RGB24,
#endif
- media::VideoCaptureParams params;
- params.requested_format = media::VideoCaptureFormat(
- capture_resolution, 30.0f, media::VideoPixelFormat(format));
+ media::PIXEL_FORMAT_RGB32,
+ media::PIXEL_FORMAT_ARGB
+ };
+
+ for (media::VideoPixelFormat format : kSupportedFormats) {
+ params.requested_format.pixel_format = format;
+
+ EXPECT_CALL(*controller_, DoLogOnIOThread(_)).Times(1);
EXPECT_CALL(*controller_, MockDoIncomingCapturedVideoFrameOnIOThread(_))
.Times(1);
device_client_->OnIncomingCapturedData(
@@ -198,6 +207,8 @@ TEST_F(VideoCaptureDeviceClientTest, CheckRotationsAndCrops) {
const size_t kScratchpadSizeInBytes = 400;
unsigned char data[kScratchpadSizeInBytes] = {};
+ EXPECT_CALL(*controller_, DoLogOnIOThread(_)).Times(1);
+
media::VideoCaptureParams params;
for (const auto& size_and_rotation : kSizeAndRotations) {
ASSERT_GE(kScratchpadSizeInBytes,
diff --git a/chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc b/chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc
index c48181acdb5..043587f39ef 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.cc
@@ -16,10 +16,10 @@
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
-#include "content/common/gpu/client/gpu_jpeg_decode_accelerator_host.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/common/content_switches.h"
#include "media/base/video_frame.h"
+#include "media/gpu/ipc/client/gpu_jpeg_decode_accelerator_host.h"
namespace content {
@@ -80,7 +80,7 @@ void VideoCaptureGpuJpegDecoder::DecodeCapturedData(
size_t in_buffer_size,
const media::VideoCaptureFormat& frame_format,
const base::TimeTicks& timestamp,
- scoped_ptr<media::VideoCaptureDevice::Client::Buffer> out_buffer) {
+ std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> out_buffer) {
DCHECK(CalledOnValidThread());
DCHECK(decoder_);
@@ -120,7 +120,7 @@ void VideoCaptureGpuJpegDecoder::DecodeCapturedData(
// Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
next_bitstream_buffer_id_ = (next_bitstream_buffer_id_ + 1) & 0x3FFFFFFF;
-#if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS))
+#if defined(OS_POSIX) && !defined(OS_MACOSX)
const gfx::Size dimensions = frame_format.frame_size;
base::SharedMemoryHandle out_handle = out_buffer->AsPlatformFile();
scoped_refptr<media::VideoFrame> out_frame =
@@ -209,7 +209,7 @@ void VideoCaptureGpuJpegDecoder::GpuChannelEstablishedOnUIThread(
base::WeakPtr<VideoCaptureGpuJpegDecoder> weak_this) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- scoped_refptr<GpuChannelHost> gpu_channel_host(
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel_host(
BrowserGpuChannelHostFactory::instance()->GetGpuChannel());
task_runner->PostTask(
FROM_HERE, base::Bind(&VideoCaptureGpuJpegDecoder::FinishInitialization,
@@ -217,14 +217,28 @@ void VideoCaptureGpuJpegDecoder::GpuChannelEstablishedOnUIThread(
}
void VideoCaptureGpuJpegDecoder::FinishInitialization(
- scoped_refptr<GpuChannelHost> gpu_channel_host) {
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel_host) {
+ TRACE_EVENT0("gpu", "VideoCaptureGpuJpegDecoder::FinishInitialization");
DCHECK(CalledOnValidThread());
base::AutoLock lock(lock_);
if (!gpu_channel_host) {
LOG(ERROR) << "Failed to establish GPU channel for JPEG decoder";
} else if (gpu_channel_host->gpu_info().jpeg_decode_accelerator_supported) {
gpu_channel_host_ = std::move(gpu_channel_host);
- decoder_ = gpu_channel_host_->CreateJpegDecoder(this);
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner =
+ BrowserGpuChannelHostFactory::instance()->GetIOThreadTaskRunner();
+
+ int32_t route_id = gpu_channel_host_->GenerateRouteID();
+ std::unique_ptr<media::GpuJpegDecodeAcceleratorHost> decoder(
+ new media::GpuJpegDecodeAcceleratorHost(gpu_channel_host_.get(),
+ route_id, io_task_runner));
+ if (decoder->Initialize(this)) {
+ gpu_channel_host_->AddRouteWithTaskRunner(
+ route_id, decoder->GetReceiver(), io_task_runner);
+ decoder_ = std::move(decoder);
+ } else {
+ DLOG(ERROR) << "Failed to initialize JPEG decoder";
+ }
}
decoder_status_ = decoder_ ? INIT_PASSED : FAILED;
RecordInitDecodeUMA_Locked();
diff --git a/chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h b/chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h
index 554cb104614..1650357ac94 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_gpu_jpeg_decoder.h
@@ -8,12 +8,12 @@
#include <stddef.h>
#include <stdint.h>
+#include <memory>
#include <string>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread.h"
@@ -21,12 +21,15 @@
#include "media/capture/video/video_capture_device.h"
#include "media/video/jpeg_decode_accelerator.h"
+namespace gpu {
+class GpuChannelHost;
+}
+
namespace media {
class VideoFrame;
}
namespace content {
-class GpuChannelHost;
// Adapter to GpuJpegDecodeAccelerator for VideoCaptureDevice::Client. It takes
// care of GpuJpegDecodeAccelerator creation, shared memory, and threading
@@ -50,9 +53,10 @@ class CONTENT_EXPORT VideoCaptureGpuJpegDecoder
};
typedef base::Callback<void(
- scoped_ptr<media::VideoCaptureDevice::Client::Buffer>,
+ std::unique_ptr<media::VideoCaptureDevice::Client::Buffer>,
const scoped_refptr<media::VideoFrame>&,
- const base::TimeTicks&)> DecodeDoneCB;
+ const base::TimeTicks&)>
+ DecodeDoneCB;
// |decode_done_cb| is called on the IO thread when decode succeed. This can
// be on any thread. |decode_done_cb| is never called after
@@ -72,7 +76,7 @@ class CONTENT_EXPORT VideoCaptureGpuJpegDecoder
size_t in_buffer_size,
const media::VideoCaptureFormat& frame_format,
const base::TimeTicks& timestamp,
- scoped_ptr<media::VideoCaptureDevice::Client::Buffer> out_buffer);
+ std::unique_ptr<media::VideoCaptureDevice::Client::Buffer> out_buffer);
// JpegDecodeAccelerator::Client implementation.
// These will be called on IO thread.
@@ -90,7 +94,8 @@ class CONTENT_EXPORT VideoCaptureGpuJpegDecoder
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
base::WeakPtr<VideoCaptureGpuJpegDecoder> weak_this);
- void FinishInitialization(scoped_refptr<GpuChannelHost> gpu_channel_host);
+ void FinishInitialization(
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel_host);
// Returns true if the decoding of last frame is not finished yet.
bool IsDecoding_Locked() const;
@@ -98,10 +103,10 @@ class CONTENT_EXPORT VideoCaptureGpuJpegDecoder
// Records |decoder_status_| to histogram.
void RecordInitDecodeUMA_Locked();
- scoped_refptr<GpuChannelHost> gpu_channel_host_;
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel_host_;
// The underlying JPEG decode accelerator.
- scoped_ptr<media::JpegDecodeAccelerator> decoder_;
+ std::unique_ptr<media::JpegDecodeAccelerator> decoder_;
// The callback to run when decode succeeds.
const DecodeDoneCB decode_done_cb_;
@@ -120,7 +125,7 @@ class CONTENT_EXPORT VideoCaptureGpuJpegDecoder
// Shared memory to store JPEG stream buffer. The input BitstreamBuffer is
// backed by this.
- scoped_ptr<base::SharedMemory> in_shared_memory_;
+ std::unique_ptr<base::SharedMemory> in_shared_memory_;
STATUS decoder_status_;
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 ed3fea64858..46db2279ee5 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_host.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_host.cc
@@ -4,9 +4,10 @@
#include "content/browser/renderer_host/media/video_capture_host.h"
+#include <memory>
+
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "base/memory/scoped_ptr.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"
@@ -147,6 +148,8 @@ bool VideoCaptureHost::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Start, OnStartCapture)
IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Pause, OnPauseCapture)
IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Resume, OnResumeCapture)
+ IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_RequestRefreshFrame,
+ OnRequestRefreshFrame)
IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_Stop, OnStopCapture)
IPC_MESSAGE_HANDLER(VideoCaptureHostMsg_BufferReady,
OnRendererFinishedWithBuffer)
@@ -262,6 +265,22 @@ void VideoCaptureHost::OnResumeCapture(
}
}
+void VideoCaptureHost::OnRequestRefreshFrame(int device_id) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DVLOG(1) << "VideoCaptureHost::OnRequestRefreshFrame, device_id "
+ << device_id;
+
+ VideoCaptureControllerID controller_id(device_id);
+ EntryMap::iterator it = entries_.find(controller_id);
+ if (it == entries_.end())
+ return;
+
+ if (VideoCaptureController* controller = it->second.get()) {
+ media_stream_manager_->video_capture_manager()
+ ->RequestRefreshFrameForClient(controller);
+ }
+}
+
void VideoCaptureHost::OnRendererFinishedWithBuffer(
int device_id,
int buffer_id,
diff --git a/chromium/content/browser/renderer_host/media/video_capture_host.h b/chromium/content/browser/renderer_host/media/video_capture_host.h
index c35153f106b..800f562e16f 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_host.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_host.h
@@ -127,6 +127,10 @@ class CONTENT_EXPORT VideoCaptureHost
media::VideoCaptureSessionId session_id,
const media::VideoCaptureParams& params);
+ // IPC message: Requests that the video capture send a frame "soon" (e.g., to
+ // resolve picture loss or quality issues).
+ void OnRequestRefreshFrame(int device_id);
+
// IPC message: Called when a renderer is finished using a buffer. Notifies
// the controller.
void OnRendererFinishedWithBuffer(int device_id,
diff --git a/chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc b/chromium/content/browser/renderer_host/media/video_capture_host_unittest.cc
index b1d991a95fe..933c58ddc75 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
@@ -2,9 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "content/browser/renderer_host/media/video_capture_host.h"
+
#include <stdint.h>
#include <map>
+#include <memory>
#include <string>
#include "base/bind.h"
@@ -13,7 +16,6 @@
#include "base/files/scoped_file.h"
#include "base/location.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
@@ -24,7 +26,6 @@
#include "content/browser/renderer_host/media/media_stream_manager.h"
#include "content/browser/renderer_host/media/media_stream_requester.h"
#include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
-#include "content/browser/renderer_host/media/video_capture_host.h"
#include "content/browser/renderer_host/media/video_capture_manager.h"
#include "content/common/media/video_capture_messages.h"
#include "content/public/common/content_switches.h"
@@ -280,7 +281,7 @@ class VideoCaptureHostTest : public testing::Test {
#endif
media_stream_manager_.reset(new MediaStreamManager(audio_manager_.get()));
media_stream_manager_->UseFakeUIForTests(
- scoped_ptr<FakeMediaStreamUIProxy>());
+ std::unique_ptr<FakeMediaStreamUIProxy>());
// Create a Host and connect it to a simulated IPC channel.
host_ = new MockVideoCaptureHost(media_stream_manager_.get());
@@ -483,8 +484,8 @@ class VideoCaptureHostTest : public testing::Test {
private:
StrictMock<MockMediaStreamRequester> stream_requester_;
- scoped_ptr<media::AudioManager> audio_manager_;
- scoped_ptr<MediaStreamManager> media_stream_manager_;
+ std::unique_ptr<media::AudioManager> audio_manager_;
+ std::unique_ptr<MediaStreamManager> media_stream_manager_;
content::TestBrowserThreadBundle thread_bundle_;
content::TestBrowserContext browser_context_;
content::TestContentBrowserClient browser_client_;
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 dcee567489c..cf31a65f6d9 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager.cc
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager.cc
@@ -21,6 +21,7 @@
#include "base/thread_task_runner_handle.h"
#include "base/threading/sequenced_worker_pool.h"
#include "build/build_config.h"
+#include "content/browser/media/capture/desktop_capture_device_uma_types.h"
#include "content/browser/media/capture/web_contents_video_capture_device.h"
#include "content/browser/media/media_internals.h"
#include "content/browser/renderer_host/media/video_capture_controller.h"
@@ -52,14 +53,22 @@ namespace {
// by the ConsolidateCaptureFormats() method.
bool IsCaptureFormatSmaller(const media::VideoCaptureFormat& format1,
const media::VideoCaptureFormat& format2) {
- if (format1.frame_size.GetArea() == format2.frame_size.GetArea())
+ DCHECK(format1.frame_size.GetCheckedArea().IsValid());
+ DCHECK(format2.frame_size.GetCheckedArea().IsValid());
+ if (format1.frame_size.GetCheckedArea().ValueOrDefault(0) ==
+ format2.frame_size.GetCheckedArea().ValueOrDefault(0)) {
return format1.frame_rate > format2.frame_rate;
- return format1.frame_size.GetArea() < format2.frame_size.GetArea();
+ }
+ return format1.frame_size.GetCheckedArea().ValueOrDefault(0) <
+ format2.frame_size.GetCheckedArea().ValueOrDefault(0);
}
bool IsCaptureFormatSizeEqual(const media::VideoCaptureFormat& format1,
const media::VideoCaptureFormat& format2) {
- return format1.frame_size.GetArea() == format2.frame_size.GetArea();
+ DCHECK(format1.frame_size.GetCheckedArea().IsValid());
+ DCHECK(format2.frame_size.GetCheckedArea().IsValid());
+ return format1.frame_size.GetCheckedArea().ValueOrDefault(0) ==
+ format2.frame_size.GetCheckedArea().ValueOrDefault(0);
}
// This function receives a list of capture formats, removes duplicated
@@ -110,6 +119,8 @@ void LogVideoCaptureEvent(VideoCaptureEvent event) {
// Counter used for identifying a DeviceRequest to start a capture device.
static int g_device_start_id = 0;
+const media::VideoCaptureSessionId kFakeSessionId = -1;
+
} // namespace
namespace content {
@@ -117,10 +128,12 @@ namespace content {
VideoCaptureManager::DeviceEntry::DeviceEntry(
MediaStreamType stream_type,
const std::string& id,
- scoped_ptr<VideoCaptureController> controller)
+ std::unique_ptr<VideoCaptureController> controller,
+ const media::VideoCaptureParams& params)
: serial_id(g_device_start_id++),
stream_type(stream_type),
id(id),
+ parameters(params),
video_capture_controller_(std::move(controller)) {}
VideoCaptureManager::DeviceEntry::~DeviceEntry() {
@@ -132,12 +145,12 @@ VideoCaptureManager::DeviceEntry::~DeviceEntry() {
}
void VideoCaptureManager::DeviceEntry::SetVideoCaptureDevice(
- scoped_ptr<media::VideoCaptureDevice> device) {
+ std::unique_ptr<media::VideoCaptureDevice> device) {
DCHECK(thread_checker_.CalledOnValidThread());
video_capture_device_.swap(device);
}
-scoped_ptr<media::VideoCaptureDevice>
+std::unique_ptr<media::VideoCaptureDevice>
VideoCaptureManager::DeviceEntry::ReleaseVideoCaptureDevice() {
DCHECK(thread_checker_.CalledOnValidThread());
return std::move(video_capture_device_);
@@ -166,7 +179,7 @@ VideoCaptureManager::CaptureDeviceStartRequest::CaptureDeviceStartRequest(
}
VideoCaptureManager::VideoCaptureManager(
- scoped_ptr<media::VideoCaptureDeviceFactory> factory)
+ std::unique_ptr<media::VideoCaptureDeviceFactory> factory)
: listener_(NULL),
new_capture_session_id_(1),
video_capture_device_factory_(std::move(factory)) {}
@@ -184,6 +197,11 @@ void VideoCaptureManager::Register(
DCHECK(!device_task_runner_.get());
listener_ = listener;
device_task_runner_ = device_task_runner;
+#if defined(OS_ANDROID)
+ app_status_listener_.reset(new base::android::ApplicationStatusListener(
+ base::Bind(&VideoCaptureManager::OnApplicationStateChange,
+ base::Unretained(this))));
+#endif
}
void VideoCaptureManager::Unregister() {
@@ -208,17 +226,13 @@ void VideoCaptureManager::EnumerateDevices(MediaStreamType stream_type) {
// Bind a callback to ConsolidateDevicesInfoOnDeviceThread() with an argument
// for another callback to OnDevicesInfoEnumerated() to be run in the current
// loop, i.e. IO loop. Pass a timer for UMA histogram collection.
- base::Callback<void(scoped_ptr<media::VideoCaptureDevice::Names>)>
- devices_enumerated_callback =
- base::Bind(&VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread,
- this,
- media::BindToCurrentLoop(base::Bind(
- &VideoCaptureManager::OnDevicesInfoEnumerated,
- this,
- stream_type,
- base::Owned(new base::ElapsedTimer()))),
- stream_type,
- devices_info_cache_);
+ base::Callback<void(std::unique_ptr<media::VideoCaptureDevice::Names>)>
+ devices_enumerated_callback = base::Bind(
+ &VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread, this,
+ media::BindToCurrentLoop(
+ base::Bind(&VideoCaptureManager::OnDevicesInfoEnumerated, this,
+ stream_type, base::Owned(new base::ElapsedTimer()))),
+ stream_type, devices_info_cache_);
// OK to use base::Unretained() since we own the VCDFactory and |this| is
// bound in |devices_enumerated_callback|.
device_task_runner_->PostTask(FROM_HERE,
@@ -353,7 +367,7 @@ void VideoCaptureManager::HandleQueuedStartRequest() {
DVLOG(3) << "HandleQueuedStartRequest, Post start to device thread, device = "
<< entry->id << " start id = " << entry->serial_id;
- base::Callback<scoped_ptr<media::VideoCaptureDevice>(void)>
+ base::Callback<std::unique_ptr<media::VideoCaptureDevice>(void)>
start_capture_function;
switch (entry->stream_type) {
@@ -419,7 +433,7 @@ void VideoCaptureManager::HandleQueuedStartRequest() {
void VideoCaptureManager::OnDeviceStarted(
int serial_id,
- scoped_ptr<media::VideoCaptureDevice> device) {
+ std::unique_ptr<media::VideoCaptureDevice> device) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(serial_id == device_start_queue_.begin()->serial_id());
DVLOG(3) << "OnDeviceStarted";
@@ -450,6 +464,7 @@ void VideoCaptureManager::OnDeviceStarted(
if (entry->stream_type == MEDIA_DESKTOP_VIDEO_CAPTURE) {
const media::VideoCaptureSessionId session_id =
device_start_queue_.front().session_id();
+ DCHECK(session_id != kFakeSessionId);
MaybePostDesktopCaptureWindowId(session_id);
}
}
@@ -458,15 +473,15 @@ void VideoCaptureManager::OnDeviceStarted(
HandleQueuedStartRequest();
}
-scoped_ptr<media::VideoCaptureDevice>
+std::unique_ptr<media::VideoCaptureDevice>
VideoCaptureManager::DoStartDeviceCaptureOnDeviceThread(
const media::VideoCaptureDevice::Name& name,
const media::VideoCaptureParams& params,
- scoped_ptr<media::VideoCaptureDevice::Client> device_client) {
+ std::unique_ptr<media::VideoCaptureDevice::Client> device_client) {
SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime");
DCHECK(IsOnDeviceThread());
- scoped_ptr<media::VideoCaptureDevice> video_capture_device;
+ std::unique_ptr<media::VideoCaptureDevice> video_capture_device;
video_capture_device = video_capture_device_factory_->Create(name);
if (!video_capture_device) {
@@ -478,15 +493,15 @@ VideoCaptureManager::DoStartDeviceCaptureOnDeviceThread(
return video_capture_device;
}
-scoped_ptr<media::VideoCaptureDevice>
+std::unique_ptr<media::VideoCaptureDevice>
VideoCaptureManager::DoStartTabCaptureOnDeviceThread(
const std::string& id,
const media::VideoCaptureParams& params,
- scoped_ptr<media::VideoCaptureDevice::Client> device_client) {
+ std::unique_ptr<media::VideoCaptureDevice::Client> device_client) {
SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime");
DCHECK(IsOnDeviceThread());
- scoped_ptr<media::VideoCaptureDevice> video_capture_device;
+ std::unique_ptr<media::VideoCaptureDevice> video_capture_device;
video_capture_device.reset(WebContentsVideoCaptureDevice::Create(id));
if (!video_capture_device) {
@@ -498,18 +513,26 @@ VideoCaptureManager::DoStartTabCaptureOnDeviceThread(
return video_capture_device;
}
-scoped_ptr<media::VideoCaptureDevice>
+std::unique_ptr<media::VideoCaptureDevice>
VideoCaptureManager::DoStartDesktopCaptureOnDeviceThread(
const std::string& id,
const media::VideoCaptureParams& params,
- scoped_ptr<media::VideoCaptureDevice::Client> device_client) {
+ std::unique_ptr<media::VideoCaptureDevice::Client> device_client) {
SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StartDeviceTime");
DCHECK(IsOnDeviceThread());
- scoped_ptr<media::VideoCaptureDevice> video_capture_device;
+ std::unique_ptr<media::VideoCaptureDevice> video_capture_device;
#if defined(ENABLE_SCREEN_CAPTURE)
DesktopMediaID desktop_id = DesktopMediaID::Parse(id);
- if (!desktop_id.is_null()) {
+ if (desktop_id.is_null()) {
+ device_client->OnError(FROM_HERE, "Desktop media ID is null");
+ return nullptr;
+ }
+
+ if (desktop_id.type == DesktopMediaID::TYPE_WEB_CONTENTS) {
+ video_capture_device.reset(WebContentsVideoCaptureDevice::Create(id));
+ IncrementDesktopCaptureCounter(TAB_VIDEO_CAPTURER_CREATED);
+ } else {
#if defined(USE_AURA)
video_capture_device = DesktopCaptureDeviceAura::Create(desktop_id);
#endif
@@ -539,7 +562,7 @@ void VideoCaptureManager::StartCaptureForClient(
<< ", request: "
<< media::VideoCaptureFormat::ToString(params.requested_format);
- DeviceEntry* entry = GetOrCreateDeviceEntry(session_id);
+ DeviceEntry* entry = GetOrCreateDeviceEntry(session_id, params);
if (!entry) {
done_cb.Run(base::WeakPtr<VideoCaptureController>());
return;
@@ -550,7 +573,8 @@ void VideoCaptureManager::StartCaptureForClient(
LogVideoCaptureEvent(VIDEO_CAPTURE_START_CAPTURE);
// First client starts the device.
- if (entry->video_capture_controller()->GetActiveClientCount() == 0) {
+ if (!entry->video_capture_controller()->HasActiveClient() &&
+ !entry->video_capture_controller()->HasPausedClient()) {
DVLOG(1) << "VideoCaptureManager starting device (type = "
<< entry->stream_type << ", id = " << entry->id << ")";
QueueStartDevice(session_id, entry, params);
@@ -625,9 +649,6 @@ void VideoCaptureManager::PauseCaptureForClient(
return;
controller->PauseClient(client_id, client_handler);
- // Release the capture device if there are no more clients.
- if (!controller->GetActiveClientCount())
- DoStopDevice(entry);
}
void VideoCaptureManager::ResumeCaptureForClient(
@@ -650,15 +671,25 @@ void VideoCaptureManager::ResumeCaptureForClient(
if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE)
return;
- // We can't resume a capturing client, which will crash with Camera2 API.
- // Refer to crbug/514740 for more details.
- if (!controller->ResumeClient(client_id, client_handler))
- return;
- if (controller->GetActiveClientCount() != 1)
- return;
+ controller->ResumeClient(client_id, client_handler);
+}
+
+void VideoCaptureManager::RequestRefreshFrameForClient(
+ VideoCaptureController* controller) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // This is first active client, allocate the camera.
- QueueStartDevice(session_id, entry, params);
+ if (DeviceEntry* entry = GetDeviceEntryForController(controller)) {
+ if (media::VideoCaptureDevice* device = entry->video_capture_device()) {
+ device_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&media::VideoCaptureDevice::RequestRefreshFrame,
+ // Unretained is safe to use here because |device| would be
+ // null if it was scheduled for shutdown and destruction,
+ // and because this task is guaranteed to run before the
+ // task that destroys the |device|.
+ base::Unretained(device)));
+ }
+ }
}
bool VideoCaptureManager::GetDeviceSupportedFormats(
@@ -756,7 +787,7 @@ void VideoCaptureManager::MaybePostDesktopCaptureWindowId(
}
void VideoCaptureManager::DoStopDeviceOnDeviceThread(
- scoped_ptr<media::VideoCaptureDevice> device) {
+ std::unique_ptr<media::VideoCaptureDevice> device) {
SCOPED_UMA_HISTOGRAM_TIMER("Media.VideoCaptureManager.StopDeviceTime");
DCHECK(IsOnDeviceThread());
device->StopAndDeAllocate();
@@ -821,7 +852,7 @@ void VideoCaptureManager::ConsolidateDevicesInfoOnDeviceThread(
on_devices_enumerated_callback,
MediaStreamType stream_type,
const media::VideoCaptureDeviceInfos& old_device_info_cache,
- scoped_ptr<media::VideoCaptureDevice::Names> names_snapshot) {
+ std::unique_ptr<media::VideoCaptureDevice::Names> names_snapshot) {
DCHECK(IsOnDeviceThread());
// Construct |new_devices_info_cache| with the cached devices that are still
// present in the system, and remove their names from |names_snapshot|, so we
@@ -881,11 +912,9 @@ VideoCaptureManager::GetDeviceEntryForController(
void VideoCaptureManager::DestroyDeviceEntryIfNoClients(DeviceEntry* entry) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // Removal of the last active client stops the device. It is important to only
- // check active clients and not all clients, because otherwise this class gets
- // into a bad state and might crash next time VideoCaptureManager::Open() is
- // called.
- if (entry->video_capture_controller()->GetActiveClientCount() == 0) {
+ // Removal of the last client stops the device.
+ if (!entry->video_capture_controller()->HasActiveClient() &&
+ !entry->video_capture_controller()->HasPausedClient()) {
DVLOG(1) << "VideoCaptureManager stopping device (type = "
<< entry->stream_type << ", id = " << entry->id << ")";
@@ -902,7 +931,8 @@ void VideoCaptureManager::DestroyDeviceEntryIfNoClients(DeviceEntry* entry) {
}
VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry(
- media::VideoCaptureSessionId capture_session_id) {
+ media::VideoCaptureSessionId capture_session_id,
+ const media::VideoCaptureParams& params) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
SessionMap::iterator session_it = sessions_.find(capture_session_id);
@@ -922,10 +952,11 @@ VideoCaptureManager::DeviceEntry* VideoCaptureManager::GetOrCreateDeviceEntry(
const int max_buffers = device_info.type == MEDIA_TAB_VIDEO_CAPTURE ?
kMaxNumberOfBuffersForTabCapture : kMaxNumberOfBuffers;
- scoped_ptr<VideoCaptureController> video_capture_controller(
+ std::unique_ptr<VideoCaptureController> video_capture_controller(
new VideoCaptureController(max_buffers));
- DeviceEntry* new_device = new DeviceEntry(
- device_info.type, device_info.id, std::move(video_capture_controller));
+ DeviceEntry* new_device =
+ new DeviceEntry(device_info.type, device_info.id,
+ std::move(video_capture_controller), params);
devices_.push_back(new_device);
return new_device;
}
@@ -978,4 +1009,49 @@ void VideoCaptureManager::InitializeCaptureDeviceApiOnUIThread(
}
#endif
+#if defined(OS_ANDROID)
+void VideoCaptureManager::OnApplicationStateChange(
+ base::android::ApplicationState state) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (state == base::android::APPLICATION_STATE_HAS_RUNNING_ACTIVITIES) {
+ ResumeDevices();
+ } else if (state == base::android::APPLICATION_STATE_HAS_STOPPED_ACTIVITIES) {
+ ReleaseDevices();
+ }
+}
+
+void VideoCaptureManager::ReleaseDevices() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ for (auto& entry : devices_) {
+ // Do not stop Content Video Capture devices, e.g. Tab or Screen capture.
+ if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE)
+ continue;
+
+ DoStopDevice(entry);
+ }
+}
+
+void VideoCaptureManager::ResumeDevices() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ for (auto& entry : devices_) {
+ // Do not resume Content Video Capture devices, e.g. Tab or Screen capture.
+ // Do not try to restart already running devices. A device will be running
+ // if the Application state changes from
+ // APPLICATION_STATE_HAS_RUNNING_ACTIVITIES
+ // ->APPLICATION_STATE_HAS_PAUSED_ACTIVITIES
+ // ->APPLICATION_STATE_HAS_RUNNING_ACTIVITIES
+ if (entry->stream_type != MEDIA_DEVICE_VIDEO_CAPTURE ||
+ entry->video_capture_device())
+ continue;
+
+ // Session ID is only valid for Screen capture. So we can fake it to resume
+ // video capture devices here.
+ QueueStartDevice(kFakeSessionId, entry, entry->parameters);
+ }
+}
+#endif // defined(OS_ANDROID)
+
} // 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 6a5fc9c36f8..6e3e9561feb 100644
--- a/chromium/content/browser/renderer_host/media/video_capture_manager.h
+++ b/chromium/content/browser/renderer_host/media/video_capture_manager.h
@@ -35,6 +35,10 @@
#include "media/capture/video/video_capture_device_factory.h"
#include "media/capture/video/video_capture_device_info.h"
+#if defined(OS_ANDROID)
+#include "base/android/application_status_listener.h"
+#endif
+
namespace content {
class VideoCaptureController;
class VideoCaptureControllerEventHandler;
@@ -47,7 +51,7 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
void(const base::WeakPtr<VideoCaptureController>&)> DoneCB;
explicit VideoCaptureManager(
- scoped_ptr<media::VideoCaptureDeviceFactory> factory);
+ std::unique_ptr<media::VideoCaptureDeviceFactory> factory);
void Unregister();
@@ -112,6 +116,10 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
VideoCaptureControllerID client_id,
VideoCaptureControllerEventHandler* client_handler);
+ // Called by VideoCaptureHost to request a refresh frame from the video
+ // capture device.
+ void RequestRefreshFrameForClient(VideoCaptureController* controller);
+
// Retrieves all capture supported formats for a particular device. Returns
// false if the |capture_session_id| is not found. The supported formats are
// cached during device(s) enumeration, and depending on the underlying
@@ -174,7 +182,8 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
// Finds a DeviceEntry entry for the indicated session, creating a fresh one
// if necessary. Returns NULL if the session id is invalid.
DeviceEntry* GetOrCreateDeviceEntry(
- media::VideoCaptureSessionId capture_session_id);
+ media::VideoCaptureSessionId capture_session_id,
+ const media::VideoCaptureParams& params);
// Finds the DeviceEntry that owns a particular controller pointer.
DeviceEntry* GetDeviceEntryForController(
@@ -190,7 +199,7 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
on_devices_enumerated_callback,
MediaStreamType stream_type,
const media::VideoCaptureDeviceInfos& old_device_info_cache,
- scoped_ptr<media::VideoCaptureDevice::Names> names_snapshot);
+ std::unique_ptr<media::VideoCaptureDevice::Names> names_snapshot);
// Starting a capture device can take 1-2 seconds.
// To avoid multiple unnecessary start/stop commands to the OS, each start
@@ -202,7 +211,7 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
DeviceEntry* entry,
const media::VideoCaptureParams& params);
void OnDeviceStarted(int serial_id,
- scoped_ptr<media::VideoCaptureDevice> device);
+ std::unique_ptr<media::VideoCaptureDevice> device);
void DoStopDevice(DeviceEntry* entry);
void HandleQueuedStartRequest();
@@ -210,24 +219,26 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
// VideoCaptureDevice is returned to the IO-thread and stored in
// a DeviceEntry in |devices_|. Ownership of |client| passes to
// the device.
- scoped_ptr<media::VideoCaptureDevice> DoStartDeviceCaptureOnDeviceThread(
+ std::unique_ptr<media::VideoCaptureDevice> DoStartDeviceCaptureOnDeviceThread(
const media::VideoCaptureDevice::Name& name,
const media::VideoCaptureParams& params,
- scoped_ptr<media::VideoCaptureDevice::Client> client);
+ std::unique_ptr<media::VideoCaptureDevice::Client> client);
- scoped_ptr<media::VideoCaptureDevice> DoStartTabCaptureOnDeviceThread(
+ std::unique_ptr<media::VideoCaptureDevice> DoStartTabCaptureOnDeviceThread(
const std::string& device_id,
const media::VideoCaptureParams& params,
- scoped_ptr<media::VideoCaptureDevice::Client> client);
+ std::unique_ptr<media::VideoCaptureDevice::Client> client);
- scoped_ptr<media::VideoCaptureDevice> DoStartDesktopCaptureOnDeviceThread(
+ std::unique_ptr<media::VideoCaptureDevice>
+ DoStartDesktopCaptureOnDeviceThread(
const std::string& device_id,
const media::VideoCaptureParams& params,
- scoped_ptr<media::VideoCaptureDevice::Client> client);
+ std::unique_ptr<media::VideoCaptureDevice::Client> client);
// Stops and destroys the VideoCaptureDevice held in
// |device|.
- void DoStopDeviceOnDeviceThread(scoped_ptr<media::VideoCaptureDevice> device);
+ void DoStopDeviceOnDeviceThread(
+ std::unique_ptr<media::VideoCaptureDevice> device);
media::VideoCaptureDeviceInfo* FindDeviceInfoById(
const std::string& id,
@@ -252,12 +263,26 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
// Once initialization is done, and_then will be run on the IO thread.
void InitializeCaptureDeviceApiOnUIThread(const base::Closure& and_then);
- // Due to initialization issues with AVFoundation and QTKit on Mac, we need
+ // Due to initialization issues with AVFoundation on Mac, we need
// to make sure we initialize the APIs on the UI thread before we can reliably
// use them. This variable is only checked and set on the IO thread.
bool capture_device_api_initialized_ = false;
#endif
+#if defined(OS_ANDROID)
+ // On Android, we used to stop the video device when the host tab is hidden.
+ // This caused problems on some devices when the device was stopped and
+ // restarted quickly. See http://crbug/582295. Now instead, the device is
+ // only stopped when Chrome goes to background. When a tab is hidden, it will
+ // not receive video frames but the device is not stopped.
+ void OnApplicationStateChange(base::android::ApplicationState state);
+ void ReleaseDevices();
+ void ResumeDevices();
+
+ std::unique_ptr<base::android::ApplicationStatusListener>
+ app_status_listener_;
+#endif
+
// The message loop of media stream device thread, where VCD's live.
scoped_refptr<base::SingleThreadTaskRunner> device_task_runner_;
@@ -283,25 +308,28 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
public:
DeviceEntry(MediaStreamType stream_type,
const std::string& id,
- scoped_ptr<VideoCaptureController> controller);
+ std::unique_ptr<VideoCaptureController> controller,
+ const media::VideoCaptureParams& params);
~DeviceEntry();
const int serial_id;
const MediaStreamType stream_type;
const std::string id;
+ const media::VideoCaptureParams parameters;
VideoCaptureController* video_capture_controller();
media::VideoCaptureDevice* video_capture_device();
- void SetVideoCaptureDevice(scoped_ptr<media::VideoCaptureDevice> device);
- scoped_ptr<media::VideoCaptureDevice> ReleaseVideoCaptureDevice();
+ void SetVideoCaptureDevice(
+ std::unique_ptr<media::VideoCaptureDevice> device);
+ std::unique_ptr<media::VideoCaptureDevice> ReleaseVideoCaptureDevice();
private:
// The controller.
- scoped_ptr<VideoCaptureController> video_capture_controller_;
+ std::unique_ptr<VideoCaptureController> video_capture_controller_;
// The capture device.
- scoped_ptr<media::VideoCaptureDevice> video_capture_device_;
+ std::unique_ptr<media::VideoCaptureDevice> video_capture_device_;
base::ThreadChecker thread_checker_;
};
@@ -340,7 +368,8 @@ class CONTENT_EXPORT VideoCaptureManager : public MediaStreamProvider {
// Device creation factory injected on construction from MediaStreamManager or
// from the test harness.
- scoped_ptr<media::VideoCaptureDeviceFactory> video_capture_device_factory_;
+ std::unique_ptr<media::VideoCaptureDeviceFactory>
+ video_capture_device_factory_;
// Local cache of the enumerated video capture devices' names and capture
// supported formats. A snapshot of the current devices and their capabilities
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 954544c6b62..222dc5d0744 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
@@ -4,19 +4,20 @@
// Unit test for VideoCaptureManager.
+#include "content/browser/renderer_host/media/video_capture_manager.h"
+
#include <stdint.h>
+#include <memory>
#include <string>
#include "base/bind.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.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/capture/video/fake_video_capture_device_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -81,8 +82,9 @@ class VideoCaptureManagerTest : public testing::Test {
message_loop_.get()));
io_thread_.reset(new BrowserThreadImpl(BrowserThread::IO,
message_loop_.get()));
- vcm_ = new VideoCaptureManager(scoped_ptr<media::VideoCaptureDeviceFactory>(
- new media::FakeVideoCaptureDeviceFactory()));
+ vcm_ = new VideoCaptureManager(
+ std::unique_ptr<media::VideoCaptureDeviceFactory>(
+ new media::FakeVideoCaptureDeviceFactory()));
video_capture_device_factory_ =
static_cast<media::FakeVideoCaptureDeviceFactory*>(
vcm_->video_capture_device_factory());
@@ -161,11 +163,11 @@ class VideoCaptureManagerTest : public testing::Test {
int next_client_id_;
std::map<VideoCaptureControllerID, VideoCaptureController*> controllers_;
scoped_refptr<VideoCaptureManager> vcm_;
- scoped_ptr<MockMediaStreamProviderListener> listener_;
- scoped_ptr<base::MessageLoop> message_loop_;
- scoped_ptr<BrowserThreadImpl> ui_thread_;
- scoped_ptr<BrowserThreadImpl> io_thread_;
- scoped_ptr<MockFrameObserver> frame_observer_;
+ std::unique_ptr<MockMediaStreamProviderListener> listener_;
+ std::unique_ptr<base::MessageLoop> message_loop_;
+ std::unique_ptr<BrowserThreadImpl> ui_thread_;
+ std::unique_ptr<BrowserThreadImpl> io_thread_;
+ std::unique_ptr<MockFrameObserver> frame_observer_;
media::FakeVideoCaptureDeviceFactory* video_capture_device_factory_;
private:
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 dc1e590cb70..c98d34a8f7e 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
@@ -7,7 +7,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/media/webrtc_identity_store.h"
+#include "content/browser/media/webrtc/webrtc_identity_store.h"
#include "content/common/media/webrtc_identity_messages.h"
#include "content/public/browser/content_browser_client.h"
#include "net/base/net_errors.h"
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 1a38a45f0fb..5314d577b68 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
@@ -5,7 +5,7 @@
#include <deque>
#include "content/browser/child_process_security_policy_impl.h"
-#include "content/browser/media/webrtc_identity_store.h"
+#include "content/browser/media/webrtc/webrtc_identity_store.h"
#include "content/browser/renderer_host/media/webrtc_identity_service_host.h"
#include "content/common/media/webrtc_identity_messages.h"
#include "content/public/test/mock_resource_context.h"
@@ -19,7 +19,9 @@ namespace content {
namespace {
-const char FAKE_URL[] = "http://fake.com";
+const char FAKE_URL[] = "http://www.fake.com";
+const char FAKE_SITE[] = "http://fake.com";
+const char OTHER_SITE[] = "https://other.com";
const char FAKE_FIRST_PARTY_URL[] = "http://fake.firstparty.com";
const char FAKE_IDENTITY_NAME[] = "fake identity";
const char FAKE_COMMON_NAME[] = "fake common name";
@@ -178,7 +180,7 @@ class WebRTCIdentityServiceHostTest : public ::testing::Test {
protected:
TestBrowserThreadBundle browser_thread_bundle_;
- scoped_ptr<MockResourceContext> mock_resource_context_;
+ std::unique_ptr<MockResourceContext> mock_resource_context_;
scoped_refptr<MockWebRTCIdentityStore> store_;
scoped_refptr<WebRTCIdentityServiceHostForTest> host_;
};
@@ -231,12 +233,22 @@ TEST_F(WebRTCIdentityServiceHostTest, TestOnRequestFailed) {
TEST_F(WebRTCIdentityServiceHostTest, TestOriginAccessDenied) {
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
- policy->Remove(FAKE_RENDERER_ID);
+ policy->LockToOrigin(FAKE_RENDERER_ID, GURL(OTHER_SITE));
SendRequestToHost();
VerifyRequestFailedMessage(net::ERR_ACCESS_DENIED);
}
+TEST_F(WebRTCIdentityServiceHostTest, TestOriginAccessAllowed) {
+ ChildProcessSecurityPolicyImpl* policy =
+ ChildProcessSecurityPolicyImpl::GetInstance();
+ policy->LockToOrigin(FAKE_RENDERER_ID, GURL(FAKE_SITE));
+
+ SendRequestToHost();
+ store_->RunCompletionCallback(net::OK, FAKE_CERTIFICATE, FAKE_PRIVATE_KEY);
+ VerifyIdentityReadyMessage(FAKE_CERTIFICATE, FAKE_PRIVATE_KEY);
+}
+
// Verifies that we do not crash if we try to cancel a completed request.
TEST_F(WebRTCIdentityServiceHostTest, TestCancelAfterRequestCompleted) {
SendRequestToHost();
diff --git a/chromium/content/browser/renderer_host/memory_benchmark_message_filter.cc b/chromium/content/browser/renderer_host/memory_benchmark_message_filter.cc
deleted file mode 100644
index 9125a8c0873..00000000000
--- a/chromium/content/browser/renderer_host/memory_benchmark_message_filter.cc
+++ /dev/null
@@ -1,41 +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/memory_benchmark_message_filter.h"
-
-#include "build/build_config.h"
-#include "content/common/memory_benchmark_messages.h"
-
-#if defined(USE_TCMALLOC) && (defined(OS_LINUX) || defined(OS_ANDROID))
-
-#include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
-
-namespace content {
-
-MemoryBenchmarkMessageFilter::MemoryBenchmarkMessageFilter()
- : BrowserMessageFilter(MemoryBenchmarkMsgStart) {
-}
-
-bool MemoryBenchmarkMessageFilter::OnMessageReceived(
- const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(MemoryBenchmarkMessageFilter, message)
- IPC_MESSAGE_HANDLER(MemoryBenchmarkHostMsg_HeapProfilerDump,
- OnHeapProfilerDump)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-MemoryBenchmarkMessageFilter::~MemoryBenchmarkMessageFilter() {
-}
-
-void MemoryBenchmarkMessageFilter::OnHeapProfilerDump(
- const std::string& reason) {
- ::HeapProfilerDump(reason.c_str());
-}
-
-} // namespace content
-
-#endif // defined(USE_TCMALLOC) && (defined(OS_LINUX) || defined(OS_ANDROID))
diff --git a/chromium/content/browser/renderer_host/memory_benchmark_message_filter.h b/chromium/content/browser/renderer_host/memory_benchmark_message_filter.h
deleted file mode 100644
index 0bafa73b49e..00000000000
--- a/chromium/content/browser/renderer_host/memory_benchmark_message_filter.h
+++ /dev/null
@@ -1,31 +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_MEMORY_BENCHMARK_MESSAGE_FILTER_H_
-#define CONTENT_BROWSER_RENDERER_HOST_MEMORY_BENCHMARK_MESSAGE_FILTER_H_
-
-#include <string>
-
-#include "base/macros.h"
-#include "content/public/browser/browser_message_filter.h"
-
-namespace content {
-
-class MemoryBenchmarkMessageFilter : public BrowserMessageFilter {
- public:
- MemoryBenchmarkMessageFilter();
-
- bool OnMessageReceived(const IPC::Message& message) override;
-
- private:
- ~MemoryBenchmarkMessageFilter() override;
-
- void OnHeapProfilerDump(const std::string& reason);
-
- DISALLOW_COPY_AND_ASSIGN(MemoryBenchmarkMessageFilter);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_RENDERER_HOST_MEMORY_BENCHMARK_MESSAGE_FILTER_H_
diff --git a/chromium/content/browser/renderer_host/native_web_keyboard_event_android.cc b/chromium/content/browser/renderer_host/native_web_keyboard_event_android.cc
index fb32d70ae08..696bb0de920 100644
--- a/chromium/content/browser/renderer_host/native_web_keyboard_event_android.cc
+++ b/chromium/content/browser/renderer_host/native_web_keyboard_event_android.cc
@@ -29,25 +29,46 @@ NativeWebKeyboardEvent::NativeWebKeyboardEvent()
skip_in_browser(false) {
}
-NativeWebKeyboardEvent::NativeWebKeyboardEvent(
- blink::WebInputEvent::Type type,
- int modifiers, double time_secs, int keycode, int scancode,
- int unicode_character, bool is_system_key)
- : WebKeyboardEvent(WebKeyboardEventBuilder::Build(
- type, modifiers, time_secs, keycode, scancode, unicode_character,
- is_system_key)) {
+NativeWebKeyboardEvent::NativeWebKeyboardEvent(blink::WebInputEvent::Type type,
+ int modifiers,
+ double time_secs,
+ int keycode,
+ int scancode,
+ int unicode_character,
+ bool is_system_key)
+ : WebKeyboardEvent(WebKeyboardEventBuilder::Build(nullptr,
+ nullptr,
+ type,
+ modifiers,
+ time_secs,
+ keycode,
+ scancode,
+ unicode_character,
+ is_system_key)) {
os_event = NULL;
skip_in_browser = false;
}
NativeWebKeyboardEvent::NativeWebKeyboardEvent(
- jobject android_key_event, blink::WebInputEvent::Type type,
- int modifiers, double time_secs, int keycode, int scancode,
- int unicode_character, bool is_system_key)
- : WebKeyboardEvent(WebKeyboardEventBuilder::Build(
- type, modifiers, time_secs, keycode, scancode, unicode_character,
- is_system_key)) {
- os_event = NewGlobalRefForKeyEvent(android_key_event);
+ JNIEnv* env,
+ const base::android::JavaRef<jobject>& android_key_event,
+ blink::WebInputEvent::Type type,
+ int modifiers,
+ double time_secs,
+ int keycode,
+ int scancode,
+ int unicode_character,
+ bool is_system_key)
+ : WebKeyboardEvent(WebKeyboardEventBuilder::Build(env,
+ android_key_event,
+ type,
+ modifiers,
+ time_secs,
+ keycode,
+ scancode,
+ unicode_character,
+ is_system_key)) {
+ os_event = NewGlobalRefForKeyEvent(android_key_event.obj());
skip_in_browser = false;
}
diff --git a/chromium/content/browser/renderer_host/overscroll_controller.cc b/chromium/content/browser/renderer_host/overscroll_controller.cc
index b622dc85338..34c631a56dd 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller.cc
+++ b/chromium/content/browser/renderer_host/overscroll_controller.cc
@@ -7,6 +7,7 @@
#include "base/command_line.h"
#include "base/logging.h"
#include "content/browser/renderer_host/overscroll_controller_delegate.h"
+#include "content/common/input/input_event_utils.h"
#include "content/public/browser/overscroll_configuration.h"
#include "content/public/common/content_switches.h"
@@ -19,6 +20,13 @@ bool IsScrollEndEffectEnabled() {
switches::kScrollEndEffect) == "1";
}
+bool IsGestureEventFromTouchpad(const blink::WebInputEvent& event) {
+ DCHECK(blink::WebInputEvent::isGestureEventType(event.type));
+ const blink::WebGestureEvent& gesture =
+ static_cast<const blink::WebGestureEvent&>(event);
+ return gesture.sourceDevice == blink::WebGestureDeviceTouchpad;
+}
+
} // namespace
namespace content {
@@ -28,18 +36,64 @@ OverscrollController::OverscrollController()
scroll_state_(STATE_UNKNOWN),
overscroll_delta_x_(0.f),
overscroll_delta_y_(0.f),
- delegate_(NULL) {
-}
+ delegate_(NULL),
+ use_gesture_wheel_scrolling_(UseGestureBasedWheelScrolling()) {}
OverscrollController::~OverscrollController() {
}
+bool OverscrollController::ShouldProcessEvent(
+ const blink::WebInputEvent& event) {
+ if (use_gesture_wheel_scrolling_) {
+ switch (event.type) {
+ case blink::WebInputEvent::MouseWheel:
+ return false;
+ case blink::WebInputEvent::GestureScrollBegin:
+ case blink::WebInputEvent::GestureScrollUpdate:
+ case blink::WebInputEvent::GestureScrollEnd: {
+ const blink::WebGestureEvent& gesture =
+ static_cast<const blink::WebGestureEvent&>(event);
+ if (gesture.sourceDevice == blink::WebGestureDeviceTouchpad)
+ return true;
+ blink::WebGestureEvent::ScrollUnits scrollUnits;
+ switch (event.type) {
+ case blink::WebInputEvent::GestureScrollBegin:
+ scrollUnits = gesture.data.scrollBegin.deltaHintUnits;
+ break;
+ case blink::WebInputEvent::GestureScrollUpdate:
+ scrollUnits = gesture.data.scrollUpdate.deltaUnits;
+ break;
+ case blink::WebInputEvent::GestureScrollEnd:
+ scrollUnits = gesture.data.scrollEnd.deltaUnits;
+ break;
+ default:
+ scrollUnits = blink::WebGestureEvent::Pixels;
+ break;
+ }
+
+ return scrollUnits == blink::WebGestureEvent::PrecisePixels;
+ }
+ default:
+ break;
+ }
+ }
+ return true;
+}
+
bool OverscrollController::WillHandleEvent(const blink::WebInputEvent& event) {
+ if (!ShouldProcessEvent(event))
+ return false;
+
bool reset_scroll_state = false;
if (scroll_state_ != STATE_UNKNOWN ||
overscroll_delta_x_ || overscroll_delta_y_) {
switch (event.type) {
case blink::WebInputEvent::GestureScrollEnd:
+ // Avoid resetting the state on GestureScrollEnd generated
+ // from the touchpad since it is sent based on a timeout.
+ reset_scroll_state = !IsGestureEventFromTouchpad(event);
+ break;
+
case blink::WebInputEvent::GestureFlingStart:
reset_scroll_state = true;
break;
@@ -95,6 +149,9 @@ bool OverscrollController::WillHandleEvent(const blink::WebInputEvent& event) {
void OverscrollController::ReceivedEventACK(const blink::WebInputEvent& event,
bool processed) {
+ if (!ShouldProcessEvent(event))
+ return;
+
if (processed) {
// If a scroll event is consumed by the page, i.e. some content on the page
// has been scrolled, then there is not going to be an overscroll gesture,
@@ -142,6 +199,13 @@ bool OverscrollController::DispatchEventCompletesAction (
event.type != blink::WebInputEvent::GestureFlingStart)
return false;
+ // Avoid completing the action on GestureScrollEnd generated
+ // from the touchpad since it is sent based on a timeout not
+ // when the user has stopped interacting.
+ if (event.type == blink::WebInputEvent::GestureScrollEnd &&
+ IsGestureEventFromTouchpad(event))
+ return false;
+
if (!delegate_)
return false;
@@ -199,6 +263,12 @@ bool OverscrollController::DispatchEventResetsState(
return !wheel.hasPreciseScrollingDeltas;
}
+ // Avoid resetting overscroll on GestureScrollBegin/End generated
+ // from the touchpad since it is sent based on a timeout.
+ case blink::WebInputEvent::GestureScrollBegin:
+ case blink::WebInputEvent::GestureScrollEnd:
+ return !IsGestureEventFromTouchpad(event);
+
case blink::WebInputEvent::GestureScrollUpdate:
case blink::WebInputEvent::GestureFlingCancel:
return false;
@@ -221,16 +291,15 @@ bool OverscrollController::ProcessEventForOverscroll(
break;
event_processed =
ProcessOverscroll(wheel.deltaX * wheel.accelerationRatioX,
- wheel.deltaY * wheel.accelerationRatioY,
- wheel.type);
+ wheel.deltaY * wheel.accelerationRatioY, true);
break;
}
case blink::WebInputEvent::GestureScrollUpdate: {
const blink::WebGestureEvent& gesture =
static_cast<const blink::WebGestureEvent&>(event);
- event_processed = ProcessOverscroll(gesture.data.scrollUpdate.deltaX,
- gesture.data.scrollUpdate.deltaY,
- gesture.type);
+ event_processed = ProcessOverscroll(
+ gesture.data.scrollUpdate.deltaX, gesture.data.scrollUpdate.deltaY,
+ gesture.sourceDevice == blink::WebGestureDeviceTouchpad);
break;
}
case blink::WebInputEvent::GestureFlingStart: {
@@ -270,15 +339,14 @@ bool OverscrollController::ProcessEventForOverscroll(
bool OverscrollController::ProcessOverscroll(float delta_x,
float delta_y,
- blink::WebInputEvent::Type type) {
+ bool is_touchpad) {
if (scroll_state_ != STATE_CONTENT_SCROLLING)
overscroll_delta_x_ += delta_x;
overscroll_delta_y_ += delta_y;
float horiz_threshold = GetOverscrollConfig(
- WebInputEvent::isGestureEventType(type) ?
- OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN :
- OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHPAD);
+ is_touchpad ? OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHPAD
+ : OVERSCROLL_CONFIG_HORIZ_THRESHOLD_START_TOUCHSCREEN);
float vert_threshold = GetOverscrollConfig(
OVERSCROLL_CONFIG_VERT_THRESHOLD_START);
if (fabs(overscroll_delta_x_) <= horiz_threshold &&
diff --git a/chromium/content/browser/renderer_host/overscroll_controller.h b/chromium/content/browser/renderer_host/overscroll_controller.h
index 92fa093bf13..90f310f19fb 100644
--- a/chromium/content/browser/renderer_host/overscroll_controller.h
+++ b/chromium/content/browser/renderer_host/overscroll_controller.h
@@ -92,9 +92,7 @@ class OverscrollController {
// and the over scroll amount (i.e. |overscroll_mode_|, |overscroll_delta_x_|
// and |overscroll_delta_y_|). Returns true if overscroll was handled by the
// delegate.
- bool ProcessOverscroll(float delta_x,
- float delta_y,
- blink::WebInputEvent::Type event_type);
+ bool ProcessOverscroll(float delta_x, float delta_y, bool is_touchpad);
// Completes the desired action from the current gesture.
void CompleteAction();
@@ -103,6 +101,9 @@ class OverscrollController {
// appropriate).
void SetOverscrollMode(OverscrollMode new_mode);
+ // Whether this event should be processed or not handled by the controller.
+ bool ShouldProcessEvent(const blink::WebInputEvent& event);
+
// The current state of overscroll gesture.
OverscrollMode overscroll_mode_;
@@ -121,6 +122,7 @@ class OverscrollController {
// The delegate that receives the overscroll updates. The delegate is not
// owned by this controller.
OverscrollControllerDelegate* delegate_;
+ bool use_gesture_wheel_scrolling_;
DISALLOW_COPY_AND_ASSIGN(OverscrollController);
};
diff --git a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
index 784a808edfa..b1bc3c3c4f2 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.cc
@@ -14,7 +14,6 @@
#include "content/public/browser/resource_context.h"
#include "net/base/address_list.h"
#include "net/base/completion_callback.h"
-#include "net/base/ip_address_number.h"
#include "net/base/net_errors.h"
#include "net/base/network_interfaces.h"
#include "net/base/sys_addrinfo.h"
@@ -346,14 +345,13 @@ void P2PSocketDispatcherHost::DoGetNetworkList() {
void P2PSocketDispatcherHost::SendNetworkList(
const net::NetworkInterfaceList& list,
- const net::IPAddressNumber& default_ipv4_local_address,
- const net::IPAddressNumber& default_ipv6_local_address) {
+ const net::IPAddress& default_ipv4_local_address,
+ const net::IPAddress& default_ipv6_local_address) {
Send(new P2PMsg_NetworkListChanged(list, default_ipv4_local_address,
default_ipv6_local_address));
}
-net::IPAddressNumber P2PSocketDispatcherHost::GetDefaultLocalAddress(
- int family) {
+net::IPAddress P2PSocketDispatcherHost::GetDefaultLocalAddress(int family) {
DCHECK(family == AF_INET || family == AF_INET6);
// Creation and connection of a UDP socket might be janky.
@@ -364,23 +362,20 @@ net::IPAddressNumber P2PSocketDispatcherHost::GetDefaultLocalAddress(
net::DatagramSocket::DEFAULT_BIND, net::RandIntCallback(), NULL,
net::NetLog::Source()));
- net::IPAddressNumber ip_address_number;
+ net::IPAddress ip_address;
if (family == AF_INET) {
- ip_address_number.assign(kPublicIPv4Host,
- kPublicIPv4Host + net::kIPv4AddressSize);
+ ip_address = net::IPAddress(kPublicIPv4Host);
} else {
- ip_address_number.assign(kPublicIPv6Host,
- kPublicIPv6Host + net::kIPv6AddressSize);
+ ip_address = net::IPAddress(kPublicIPv6Host);
}
- if (socket->Connect(net::IPEndPoint(ip_address_number, kPublicPort)) !=
- net::OK) {
- return net::IPAddressNumber();
+ if (socket->Connect(net::IPEndPoint(ip_address, kPublicPort)) != net::OK) {
+ return net::IPAddress();
}
net::IPEndPoint local_address;
if (socket->GetLocalAddress(&local_address) != net::OK)
- return net::IPAddressNumber();
+ return net::IPAddress();
return local_address.address();
}
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 d783e1fbfed..5b4ef05c2c0 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_dispatcher_host.h
@@ -18,6 +18,7 @@
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_process_host.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/network_change_notifier.h"
@@ -93,13 +94,13 @@ class P2PSocketDispatcherHost
void DoGetNetworkList();
void SendNetworkList(const net::NetworkInterfaceList& list,
- const net::IPAddressNumber& default_ipv4_local_address,
- const net::IPAddressNumber& default_ipv6_local_address);
+ const net::IPAddress& default_ipv4_local_address,
+ const net::IPAddress& default_ipv6_local_address);
// This connects a UDP socket to a public IP address and gets local
// address. Since it binds to the "any" address (0.0.0.0 or ::) internally, it
// retrieves the default local address.
- net::IPAddressNumber GetDefaultLocalAddress(int family);
+ net::IPAddress GetDefaultLocalAddress(int family);
void OnAddressResolved(DnsRequest* request,
const net::IPAddressList& addresses);
@@ -116,8 +117,8 @@ class P2PSocketDispatcherHost
std::set<DnsRequest*> dns_requests_;
P2PMessageThrottler throttler_;
- net::IPAddressNumber default_ipv4_local_address_;
- net::IPAddressNumber default_ipv6_local_address_;
+ net::IPAddress default_ipv4_local_address_;
+ net::IPAddress default_ipv6_local_address_;
bool dump_incoming_rtp_packet_;
bool dump_outgoing_rtp_packet_;
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host.cc b/chromium/content/browser/renderer_host/p2p/socket_host.cc
index ef6b58820c1..fa593fcf936 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host.cc
@@ -11,34 +11,14 @@
#include "content/browser/renderer_host/p2p/socket_host_udp.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/public/browser/browser_thread.h"
-#include "crypto/hmac.h"
-#include "third_party/webrtc/base/asyncpacketsocket.h"
-#include "third_party/webrtc/base/byteorder.h"
-#include "third_party/webrtc/base/messagedigest.h"
-#include "third_party/webrtc/p2p/base/stun.h"
+#include "third_party/webrtc/media/base/rtputils.h"
+#include "third_party/webrtc/media/base/turnutils.h"
namespace {
const uint32_t kStunMagicCookie = 0x2112A442;
-const size_t kMinRtpHeaderLength = 12;
const size_t kMinRtcpHeaderLength = 8;
-const size_t kRtpExtensionHeaderLength = 4;
const size_t kDtlsRecordHeaderLength = 13;
-const size_t kTurnChannelHeaderLength = 4;
-const size_t kAbsSendTimeExtensionLength = 3;
-const size_t kOneByteHeaderLength = 1;
-const size_t kMaxRtpPacketLength = 2048;
-
-// Fake auth tag written by the render process if external authentication is
-// enabled. HMAC in packet will be compared against this value before updating
-// packet with actual HMAC value.
-static const unsigned char kFakeAuthTag[10] = {
- 0xba, 0xdd, 0xba, 0xdd, 0xba, 0xdd, 0xba, 0xdd, 0xba, 0xdd
-};
-
-bool IsTurnChannelData(const char* data, size_t length) {
- return length >= kTurnChannelHeaderLength && ((*data & 0xC0) == 0x40);
-}
bool IsDtlsPacket(const char* data, size_t length) {
const uint8_t* u = reinterpret_cast<const uint8_t*>(data);
@@ -54,406 +34,10 @@ bool IsRtcpPacket(const char* data, size_t length) {
return (type >= 64 && type < 96);
}
-bool IsTurnSendIndicationPacket(const char* data, size_t length) {
- if (length < content::P2PSocketHost::kStunHeaderSize) {
- return false;
- }
-
- uint16_t type = rtc::GetBE16(data);
- return (type == cricket::TURN_SEND_INDICATION);
-}
-
-bool IsRtpPacket(const char* data, size_t length) {
- return (length >= kMinRtpHeaderLength) && ((*data & 0xC0) == 0x80);
-}
-
-// Verifies rtp header and message length.
-bool ValidateRtpHeader(const char* rtp, size_t length, size_t* header_length) {
- if (header_length) {
- *header_length = 0;
- }
-
- if (length < kMinRtpHeaderLength) {
- return false;
- }
-
- size_t cc_count = rtp[0] & 0x0F;
- size_t header_length_without_extension = kMinRtpHeaderLength + 4 * cc_count;
- if (header_length_without_extension > length) {
- return false;
- }
-
- // If extension bit is not set, we are done with header processing, as input
- // length is verified above.
- if (!(rtp[0] & 0x10)) {
- if (header_length)
- *header_length = header_length_without_extension;
-
- return true;
- }
-
- rtp += header_length_without_extension;
-
- if (header_length_without_extension + kRtpExtensionHeaderLength > length) {
- return false;
- }
-
- // Getting extension profile length.
- // Length is in 32 bit words.
- uint16_t extension_length_in_32bits = rtc::GetBE16(rtp + 2);
- size_t extension_length = extension_length_in_32bits * 4;
-
- size_t rtp_header_length = extension_length +
- header_length_without_extension +
- kRtpExtensionHeaderLength;
-
- // Verify input length against total header size.
- if (rtp_header_length > length) {
- return false;
- }
-
- if (header_length) {
- *header_length = rtp_header_length;
- }
- return true;
-}
-
-void UpdateAbsSendTimeExtensionValue(char* extension_data,
- size_t length,
- uint32_t abs_send_time) {
- // Absolute send time in RTP streams.
- //
- // The absolute send time is signaled to the receiver in-band using the
- // general mechanism for RTP header extensions [RFC5285]. The payload
- // of this extension (the transmitted value) is a 24-bit unsigned integer
- // containing the sender's current time in seconds as a fixed point number
- // with 18 bits fractional part.
- //
- // The form of the absolute send time extension block:
- //
- // 0 1 2 3
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | ID | len=2 | absolute send time |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- if (length != kAbsSendTimeExtensionLength) {
- NOTREACHED();
- return;
- }
-
- // Now() has resolution ~1-15ms
- uint32_t now_second = abs_send_time;
- if (!now_second) {
- uint64_t now_us =
- (base::TimeTicks::Now() - base::TimeTicks()).InMicroseconds();
- // Convert second to 24-bit unsigned with 18 bit fractional part
- now_second =
- ((now_us << 18) / base::Time::kMicrosecondsPerSecond) & 0x00FFFFFF;
- }
- // TODO(mallinath) - Add SetBE24 to byteorder.h in libjingle.
- extension_data[0] = static_cast<uint8_t>(now_second >> 16);
- extension_data[1] = static_cast<uint8_t>(now_second >> 8);
- extension_data[2] = static_cast<uint8_t>(now_second);
-}
-
-// Assumes |length| is actual packet length + tag length. Updates HMAC at end of
-// the RTP packet.
-void UpdateRtpAuthTag(char* rtp,
- size_t length,
- const rtc::PacketOptions& options) {
- // If there is no key, return.
- if (options.packet_time_params.srtp_auth_key.empty()) {
- return;
- }
-
- size_t tag_length = options.packet_time_params.srtp_auth_tag_len;
-
- // ROC (rollover counter) is at the beginning of the auth tag.
- const size_t kRocLength = 4;
- if (tag_length < kRocLength || tag_length > length) {
- NOTREACHED();
- return;
- }
-
- crypto::HMAC hmac(crypto::HMAC::SHA1);
- if (!hmac.Init(reinterpret_cast<const unsigned char*>(
- &options.packet_time_params.srtp_auth_key[0]),
- options.packet_time_params.srtp_auth_key.size())) {
- NOTREACHED();
- return;
- }
-
- if (tag_length > hmac.DigestLength()) {
- NOTREACHED();
- return;
- }
-
- char* auth_tag = rtp + (length - tag_length);
-
- // We should have a fake HMAC value @ auth_tag.
- DCHECK_EQ(0, memcmp(auth_tag, kFakeAuthTag, tag_length));
-
- // Copy ROC after end of rtp packet.
- memcpy(auth_tag, &options.packet_time_params.srtp_packet_index, kRocLength);
- // Authentication of a RTP packet will have RTP packet + ROC size.
- int auth_required_length = length - tag_length + kRocLength;
-
- unsigned char output[64];
- if (!hmac.Sign(base::StringPiece(rtp, auth_required_length),
- output, sizeof(output))) {
- NOTREACHED();
- return;
- }
- // Copy HMAC from output to packet. This is required as auth tag length
- // may not be equal to the actual HMAC length.
- memcpy(auth_tag, output, tag_length);
-}
-
} // namespace
namespace content {
-namespace packet_processing_helpers {
-
-bool ApplyPacketOptions(char* data,
- size_t length,
- const rtc::PacketOptions& options,
- uint32_t abs_send_time) {
- DCHECK(data != NULL);
- DCHECK(length > 0);
- // if there is no valid |rtp_sendtime_extension_id| and |srtp_auth_key| in
- // PacketOptions, nothing to be updated in this packet.
- if (options.packet_time_params.rtp_sendtime_extension_id == -1 &&
- options.packet_time_params.srtp_auth_key.empty()) {
- return true;
- }
-
- DCHECK(!IsDtlsPacket(data, length));
- DCHECK(!IsRtcpPacket(data, length));
-
- // If there is a srtp auth key present then packet must be a RTP packet.
- // RTP packet may have been wrapped in a TURN Channel Data or
- // TURN send indication.
- size_t rtp_start_pos;
- size_t rtp_length;
- if (!GetRtpPacketStartPositionAndLength(
- data, length, &rtp_start_pos, &rtp_length)) {
- // This method should never return false.
- NOTREACHED();
- return false;
- }
-
- // Skip to rtp packet.
- char* start = data + rtp_start_pos;
- // If packet option has non default value (-1) for sendtime extension id,
- // then we should parse the rtp packet to update the timestamp. Otherwise
- // just calculate HMAC and update packet with it.
- if (options.packet_time_params.rtp_sendtime_extension_id != -1) {
- UpdateRtpAbsSendTimeExtension(
- start,
- rtp_length,
- options.packet_time_params.rtp_sendtime_extension_id,
- abs_send_time);
- }
-
- UpdateRtpAuthTag(start, rtp_length, options);
- return true;
-}
-
-bool GetRtpPacketStartPositionAndLength(const char* packet,
- size_t length,
- size_t* rtp_start_pos,
- size_t* rtp_packet_length) {
- if (length < kMinRtpHeaderLength || length > kMaxRtpPacketLength) {
- return false;
- }
-
- size_t rtp_begin;
- size_t rtp_length = 0;
- if (IsTurnChannelData(packet, length)) {
- // Turn Channel Message header format.
- // 0 1 2 3
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | Channel Number | Length |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | |
- // / Application Data /
- // / /
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- rtp_begin = kTurnChannelHeaderLength;
- rtp_length = rtc::GetBE16(&packet[2]);
- if (length < rtp_length + kTurnChannelHeaderLength) {
- return false;
- }
- } else if (IsTurnSendIndicationPacket(packet, length)) {
- // Validate STUN message length.
- const size_t stun_message_length = rtc::GetBE16(&packet[2]);
- if (stun_message_length + P2PSocketHost::kStunHeaderSize != length) {
- return false;
- }
-
- // First skip mandatory stun header which is of 20 bytes.
- rtp_begin = P2PSocketHost::kStunHeaderSize;
- // Loop through STUN attributes until we find STUN DATA attribute.
- bool data_attr_present = false;
- while (rtp_begin < length) {
- // Keep reading STUN attributes until we hit DATA attribute.
- // Attribute will be a TLV structure.
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | Type | Length |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | Value (variable) ....
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // The value in the length field MUST contain the length of the Value
- // part of the attribute, prior to padding, measured in bytes. Since
- // STUN aligns attributes on 32-bit boundaries, attributes whose content
- // is not a multiple of 4 bytes are padded with 1, 2, or 3 bytes of
- // padding so that its value contains a multiple of 4 bytes. The
- // padding bits are ignored, and may be any value.
- uint16_t attr_type, attr_length;
- const int kAttrHeaderLength = sizeof(attr_type) + sizeof(attr_length);
-
- if (length < rtp_begin + kAttrHeaderLength) {
- return false;
- }
-
- // Getting attribute type and length.
- attr_type = rtc::GetBE16(&packet[rtp_begin]);
- attr_length = rtc::GetBE16(
- &packet[rtp_begin + sizeof(attr_type)]);
-
- rtp_begin += kAttrHeaderLength; // Skip STUN_DATA_ATTR header.
-
- // Checking for bogus attribute length.
- if (length < rtp_begin + attr_length) {
- return false;
- }
-
- if (attr_type != cricket::STUN_ATTR_DATA) {
- rtp_begin += attr_length;
- if ((attr_length % 4) != 0) {
- rtp_begin += (4 - (attr_length % 4));
- }
- continue;
- }
-
- data_attr_present = true;
- rtp_length = attr_length;
-
- // We found STUN_DATA_ATTR. We can skip parsing rest of the packet.
- break;
- }
-
- if (!data_attr_present) {
- // There is no data attribute present in the message. We can't do anything
- // with the message.
- return false;
- }
-
- } else {
- // This is a raw RTP packet.
- rtp_begin = 0;
- rtp_length = length;
- }
-
- // Making sure we have a valid RTP packet at the end.
- if (IsRtpPacket(packet + rtp_begin, rtp_length) &&
- ValidateRtpHeader(packet + rtp_begin, rtp_length, NULL)) {
- *rtp_start_pos = rtp_begin;
- *rtp_packet_length = rtp_length;
- return true;
- }
- return false;
-}
-
-// ValidateRtpHeader must be called before this method to make sure, we have
-// a sane rtp packet.
-bool UpdateRtpAbsSendTimeExtension(char* rtp,
- size_t length,
- int extension_id,
- uint32_t abs_send_time) {
- // 0 1 2 3
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // |V=2|P|X| CC |M| PT | sequence number |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | timestamp |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | synchronization source (SSRC) identifier |
- // +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
- // | contributing source (CSRC) identifiers |
- // | .... |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
- // Return if extension bit is not set.
- if (!(rtp[0] & 0x10)) {
- return true;
- }
-
- size_t cc_count = rtp[0] & 0x0F;
- size_t header_length_without_extension = kMinRtpHeaderLength + 4 * cc_count;
-
- rtp += header_length_without_extension;
-
- // Getting extension profile ID and length.
- uint16_t profile_id = rtc::GetBE16(rtp);
- // Length is in 32 bit words.
- uint16_t extension_length_in_32bits = rtc::GetBE16(rtp + 2);
- size_t extension_length = extension_length_in_32bits * 4;
-
- rtp += kRtpExtensionHeaderLength; // Moving past extension header.
-
- bool found = false;
- // WebRTC is using one byte header extension.
- // TODO(mallinath) - Handle two byte header extension.
- if (profile_id == 0xBEDE) { // OneByte extension header
- // 0
- // 0 1 2 3 4 5 6 7
- // +-+-+-+-+-+-+-+-+
- // | ID |length |
- // +-+-+-+-+-+-+-+-+
-
- // 0 1 2 3
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | 0xBE | 0xDE | length=3 |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | ID | L=0 | data | ID | L=1 | data...
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // ...data | 0 (pad) | 0 (pad) | ID | L=3 |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- // | data |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- const char* extension_start = rtp;
- const char* extension_end = extension_start + extension_length;
-
- while (rtp < extension_end) {
- const int id = (*rtp & 0xF0) >> 4;
- const size_t length = (*rtp & 0x0F) + 1;
- if (rtp + kOneByteHeaderLength + length > extension_end) {
- return false;
- }
- // The 4-bit length is the number minus one of data bytes of this header
- // extension element following the one-byte header.
- if (id == extension_id) {
- UpdateAbsSendTimeExtensionValue(
- rtp + kOneByteHeaderLength, length, abs_send_time);
- found = true;
- break;
- }
- rtp += kOneByteHeaderLength + length;
- // Counting padding bytes.
- while ((rtp < extension_end) && (*rtp == 0)) {
- ++rtp;
- }
- }
- }
- return found;
-}
-
-} // packet_processing_helpers
-
P2PSocketHost::P2PSocketHost(IPC::Sender* message_sender,
int socket_id,
ProtocolType protocol_type)
@@ -622,17 +206,19 @@ void P2PSocketHost::DumpRtpPacket(const char* packet,
size_t rtp_packet_pos = 0;
size_t rtp_packet_length = length;
- if (!packet_processing_helpers::GetRtpPacketStartPositionAndLength(
- packet, length, &rtp_packet_pos, &rtp_packet_length)) {
+ if (!cricket::UnwrapTurnPacket(reinterpret_cast<const uint8_t*>(packet),
+ length, &rtp_packet_pos, &rtp_packet_length)) {
return;
}
packet += rtp_packet_pos;
size_t header_length = 0;
- bool valid = ValidateRtpHeader(packet, rtp_packet_length, &header_length);
+ bool valid =
+ cricket::ValidateRtpHeader(reinterpret_cast<const uint8_t*>(packet),
+ rtp_packet_length, &header_length);
if (!valid) {
- DCHECK(false);
+ NOTREACHED();
return;
}
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host.h b/chromium/content/browser/renderer_host/p2p/socket_host.h
index 37ffddbf8cb..0b14f0f4885 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host.h
@@ -31,33 +31,6 @@ struct PacketOptions;
namespace content {
class P2PMessageThrottler;
-namespace packet_processing_helpers {
-
-// This method can handle only RTP packet, otherwise this method must not be
-// called. It will try to do, 1. update absolute send time extension header
-// if present with current time and 2. update HMAC in RTP packet.
-// If abs_send_time is 0, ApplyPacketOption will get current time from system.
-CONTENT_EXPORT bool ApplyPacketOptions(char* data,
- size_t length,
- const rtc::PacketOptions& options,
- uint32_t abs_send_time);
-
-// Helper method which finds RTP ofset and length if the packet is encapsulated
-// in a TURN Channel Message or TURN Send Indication message.
-CONTENT_EXPORT bool GetRtpPacketStartPositionAndLength(
- const char* data,
- size_t length,
- size_t* rtp_start_pos,
- size_t* rtp_packet_length);
-
-// Helper method which updates absoulute send time extension if present.
-CONTENT_EXPORT bool UpdateRtpAbsSendTimeExtension(char* rtp,
- size_t length,
- int extension_id,
- uint32_t abs_send_time);
-
-} // packet_processing_helpers
-
// Base class for P2P sockets.
class CONTENT_EXPORT P2PSocketHost {
public:
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 cd93a129370..10398dc614f 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp.cc
@@ -16,14 +16,13 @@
#include "jingle/glue/proxy_resolving_client_socket.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.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 "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
-#include "third_party/webrtc/base/asyncpacketsocket.h"
+#include "third_party/webrtc/media/base/rtputils.h"
namespace {
@@ -528,10 +527,10 @@ void P2PSocketHostTcp::DoSend(const net::IPEndPoint& to,
*reinterpret_cast<uint16_t*>(buffer->data()) = base::HostToNet16(data.size());
memcpy(buffer->data() + kPacketHeaderSize, &data[0], data.size());
- packet_processing_helpers::ApplyPacketOptions(
- buffer->data() + kPacketHeaderSize,
- buffer->BytesRemaining() - kPacketHeaderSize,
- options, 0);
+ cricket::ApplyPacketOptions(
+ reinterpret_cast<uint8_t*>(buffer->data()) + kPacketHeaderSize,
+ buffer->BytesRemaining() - kPacketHeaderSize, options.packet_time_params,
+ (base::TimeTicks::Now() - base::TimeTicks()).InMicroseconds());
WriteOrQueue(buffer);
}
@@ -601,8 +600,10 @@ void P2PSocketHostStunTcp::DoSend(const net::IPEndPoint& to,
new net::DrainableIOBuffer(new net::IOBuffer(size), size);
memcpy(buffer->data(), &data[0], data.size());
- packet_processing_helpers::ApplyPacketOptions(
- buffer->data(), data.size(), options, 0);
+ cricket::ApplyPacketOptions(
+ reinterpret_cast<uint8_t*>(buffer->data()), data.size(),
+ options.packet_time_params,
+ (base::TimeTicks::Now() - base::TimeTicks()).InMicroseconds());
if (pad_bytes) {
char padding[4] = {0};
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.cc b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.cc
index dc49bfdca9f..3d55c29bceb 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_tcp_server.cc
@@ -11,7 +11,6 @@
#include "content/common/p2p_messages.h"
#include "net/base/address_list.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/socket/stream_socket.h"
namespace {
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.cc b/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.cc
index dce2bd60ddb..81ca20db22e 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.cc
@@ -11,6 +11,7 @@
#include "base/thread_task_runner_handle.h"
#include "net/base/completion_callback.h"
#include "net/base/io_buffer.h"
+#include "net/base/ip_address.h"
const int kStunHeaderSize = 20;
const uint16_t kStunBindingRequest = 0x0001;
@@ -159,10 +160,6 @@ bool FakeSocket::WasEverUsed() const {
return true;
}
-bool FakeSocket::UsingTCPFastOpen() const {
- return false;
-}
-
bool FakeSocket::WasNpnNegotiated() const {
return false;
}
@@ -217,7 +214,7 @@ void CreateStunError(std::vector<char>* packet) {
}
net::IPEndPoint ParseAddress(const std::string& ip_str, uint16_t port) {
- net::IPAddressNumber ip;
- EXPECT_TRUE(net::ParseIPLiteralToNumber(ip_str, &ip));
+ net::IPAddress ip;
+ EXPECT_TRUE(ip.AssignFromIPLiteral(ip_str));
return net::IPEndPoint(ip, port);
}
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h b/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h
index 77a8319b263..f1a60cc72a6 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_test_utils.h
@@ -61,7 +61,6 @@ class FakeSocket : public net::StreamSocket {
void SetSubresourceSpeculation() override;
void SetOmniboxSpeculation() override;
bool WasEverUsed() const override;
- bool UsingTCPFastOpen() const override;
bool WasNpnNegotiated() const override;
net::NextProto GetNegotiatedProtocol() const override;
bool GetSSLInfo(net::SSLInfo* ssl_info) override;
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 0dbfcec4265..451353603e4 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_udp.cc
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_udp.cc
@@ -18,8 +18,7 @@
#include "ipc/ipc_sender.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
-#include "third_party/webrtc/base/asyncpacketsocket.h"
+#include "third_party/webrtc/media/base/rtputils.h"
namespace {
@@ -85,6 +84,9 @@ P2PSocketHostUdp::PendingPacket::PendingPacket(
memcpy(data->data(), &content[0], size);
}
+P2PSocketHostUdp::PendingPacket::PendingPacket(const PendingPacket& other) =
+ default;
+
P2PSocketHostUdp::PendingPacket::~PendingPacket() {
}
@@ -294,9 +296,10 @@ void P2PSocketHostUdp::DoSend(const PendingPacket& packet) {
}
base::TimeTicks send_time = base::TimeTicks::Now();
-
- packet_processing_helpers::ApplyPacketOptions(
- packet.data->data(), packet.size, packet.packet_options, 0);
+ cricket::ApplyPacketOptions(reinterpret_cast<uint8_t*>(packet.data->data()),
+ packet.size,
+ packet.packet_options.packet_time_params,
+ (send_time - base::TimeTicks()).InMicroseconds());
auto callback_binding =
base::Bind(&P2PSocketHostUdp::OnSend, base::Unretained(this), packet.id,
packet.packet_options.packet_id, send_time);
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 93fb6335458..57f1db397af 100644
--- a/chromium/content/browser/renderer_host/p2p/socket_host_udp.h
+++ b/chromium/content/browser/renderer_host/p2p/socket_host_udp.h
@@ -58,6 +58,7 @@ class CONTENT_EXPORT P2PSocketHostUdp : public P2PSocketHost {
const std::vector<char>& content,
const rtc::PacketOptions& options,
uint64_t id);
+ PendingPacket(const PendingPacket& other);
~PendingPacket();
net::IPEndPoint to;
scoped_refptr<net::IOBuffer> data;
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 7bf0944514b..aecd85a7c60 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
@@ -121,12 +121,12 @@ class FakeDatagramServerSocket : public net::DatagramServerSocket {
void AllowBroadcast() override { NOTIMPLEMENTED(); }
- int JoinGroup(const net::IPAddressNumber& group_address) const override {
+ int JoinGroup(const net::IPAddress& group_address) const override {
NOTIMPLEMENTED();
return net::ERR_NOT_IMPLEMENTED;
}
- int LeaveGroup(const net::IPAddressNumber& group_address) const override {
+ int LeaveGroup(const net::IPAddress& group_address) const override {
NOTIMPLEMENTED();
return net::ERR_NOT_IMPLEMENTED;
}
diff --git a/chromium/content/browser/renderer_host/p2p/socket_host_unittest.cc b/chromium/content/browser/renderer_host/p2p/socket_host_unittest.cc
deleted file mode 100644
index c92e9d75630..00000000000
--- a/chromium/content/browser/renderer_host/p2p/socket_host_unittest.cc
+++ /dev/null
@@ -1,386 +0,0 @@
-// Copyright (c) 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/renderer_host/p2p/socket_host.h"
-
-#include <stddef.h>
-
-#include <vector>
-
-#include "base/memory/scoped_ptr.h"
-#include "content/browser/renderer_host/p2p/socket_host_test_utils.h"
-#include "net/base/ip_endpoint.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-static unsigned char kFakeTag[4] = { 0xba, 0xdd, 0xba, 0xdd };
-static unsigned char kTestKey[] = "12345678901234567890";
-static unsigned char kTestAstValue[3] = { 0xaa, 0xbb, 0xcc };
-
-// Rtp message with invalid length.
-static unsigned char kRtpMsgWithInvalidLength[] = {
- 0x94, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0xAA, 0xBB, 0xCC, 0XDD, // SSRC
- 0xDD, 0xCC, 0xBB, 0xAA // Only 1 CSRC, but CC count is 4.
-};
-
-// Rtp message with single byte header extension, invalid extension length.
-static unsigned char kRtpMsgWithInvalidExtnLength[] = {
- 0x90, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0xBE, 0xDE, 0x0A, 0x00 // Extn length - 0x0A00
-};
-
-// Valid rtp Message with 2 byte header extension.
-static unsigned char kRtpMsgWith2ByteExtnHeader[] = {
- 0x90, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0xAA, 0xBB, 0xCC, 0XDD, // SSRC
- 0x10, 0x00, 0x00, 0x01, // 2 Byte header extension
- 0x01, 0x00, 0x00, 0x00
-};
-
-// Stun Indication message with Zero length
-static unsigned char kTurnSendIndicationMsgWithNoAttributes[] = {
- 0x00, 0x16, 0x00, 0x00, // Zero length
- 0x21, 0x12, 0xA4, 0x42, // magic cookie
- '0', '1', '2', '3', // transaction id
- '4', '5', '6', '7',
- '8', '9', 'a', 'b',
-};
-
-// Stun Send Indication message with invalid length in stun header.
-static unsigned char kTurnSendIndicationMsgWithInvalidLength[] = {
- 0x00, 0x16, 0xFF, 0x00, // length of 0xFF00
- 0x21, 0x12, 0xA4, 0x42, // magic cookie
- '0', '1', '2', '3', // transaction id
- '4', '5', '6', '7',
- '8', '9', 'a', 'b',
-};
-
-// Stun Send Indication message with no DATA attribute in message.
-static unsigned char kTurnSendIndicatinMsgWithNoDataAttribute[] = {
- 0x00, 0x16, 0x00, 0x08, // length of
- 0x21, 0x12, 0xA4, 0x42, // magic cookie
- '0', '1', '2', '3', // transaction id
- '4', '5', '6', '7',
- '8', '9', 'a', 'b',
- 0x00, 0x20, 0x00, 0x04, // Mapped address.
- 0x00, 0x00, 0x00, 0x00
-};
-
-// A valid STUN indication message with a valid RTP header in data attribute
-// payload field and no extension bit set.
-static unsigned char kTurnSendIndicationMsgWithoutRtpExtension[] = {
- 0x00, 0x16, 0x00, 0x18, // length of
- 0x21, 0x12, 0xA4, 0x42, // magic cookie
- '0', '1', '2', '3', // transaction id
- '4', '5', '6', '7',
- '8', '9', 'a', 'b',
- 0x00, 0x20, 0x00, 0x04, // Mapped address.
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x13, 0x00, 0x0C, // Data attribute.
- 0x80, 0x00, 0x00, 0x00, // RTP packet.
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
-};
-
-// A valid STUN indication message with a valid RTP header and a extension
-// header.
-static unsigned char kTurnSendIndicationMsgWithAbsSendTimeExtension[] = {
- 0x00, 0x16, 0x00, 0x24, // length of
- 0x21, 0x12, 0xA4, 0x42, // magic cookie
- '0', '1', '2', '3', // transaction id
- '4', '5', '6', '7',
- '8', '9', 'a', 'b',
- 0x00, 0x20, 0x00, 0x04, // Mapped address.
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x13, 0x00, 0x18, // Data attribute.
- 0x90, 0x00, 0x00, 0x00, // RTP packet.
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0xBE, 0xDE, 0x00, 0x02,
- 0x22, 0xaa, 0xbb, 0xcc,
- 0x32, 0xaa, 0xbb, 0xcc,
-};
-
-// A valid TURN channel header, but not RTP packet.
-static unsigned char kTurnChannelMsgNoRtpPacket[] = {
- 0x40, 0x00, 0x00, 0x04,
- 0xaa, 0xbb, 0xcc, 0xdd,
-};
-
-// Turn ChannelMessage with zero length of payload.
-static unsigned char kTurnChannelMsgWithZeroLength[] = {
- 0x40, 0x00, 0x00, 0x00
-};
-
-// Turn ChannelMessage, wrapping a RTP packet without extension.
-static unsigned char kTurnChannelMsgWithRtpPacket[] = {
- 0x40, 0x00, 0x00, 0x0C,
- 0x80, 0x00, 0x00, 0x00, // RTP packet.
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
-};
-
-// Turn ChannelMessage, wrapping a RTP packet with AbsSendTime Extension.
-static unsigned char kTurnChannelMsgWithAbsSendTimeExtension[] = {
- 0x40, 0x00, 0x00, 0x14,
- 0x90, 0x00, 0x00, 0x00, // RTP packet.
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0xBE, 0xDE, 0x00, 0x01,
- 0x32, 0xaa, 0xbb, 0xcc,
-};
-
-// RTP packet with single byte extension header of length 4 bytes.
-// Extension id = 3 and length = 3
-static unsigned char kRtpMsgWithAbsSendTimeExtension[] = {
- 0x90, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00,
- 0xBE, 0xDE, 0x00, 0x02,
- 0x22, 0x00, 0x02, 0x1c,
- 0x32, 0xaa, 0xbb, 0xcc,
-};
-
-// Index of AbsSendTimeExtn data in message |kRtpMsgWithAbsSendTimeExtension|.
-static const int kAstIndexInRtpMsg = 21;
-
-namespace content {
-
-// This test verifies parsing of all invalid raw packets.
-TEST(P2PSocketHostTest, TestInvalidRawRtpMessages) {
- size_t start_pos = SIZE_MAX, rtp_length = SIZE_MAX;
- EXPECT_FALSE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
- reinterpret_cast<char*>(kRtpMsgWithInvalidLength),
- sizeof(kRtpMsgWithInvalidLength),
- &start_pos, &rtp_length));
- EXPECT_EQ(SIZE_MAX, start_pos);
- EXPECT_EQ(SIZE_MAX, rtp_length);
-
- EXPECT_FALSE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
- reinterpret_cast<char*>(kRtpMsgWithInvalidExtnLength),
- sizeof(kRtpMsgWithInvalidExtnLength),
- &start_pos, &rtp_length));
- EXPECT_EQ(SIZE_MAX, start_pos);
- EXPECT_EQ(SIZE_MAX, rtp_length);
-}
-
-// Verify invalid TURN send indication messages. Messages are proper STUN
-// messages with incorrect values in attributes.
-TEST(P2PSocketHostTest, TestInvalidTurnSendIndicationMessages) {
- // Initializing out params to very large value.
- size_t start_pos = SIZE_MAX, rtp_length = SIZE_MAX;
- EXPECT_FALSE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
- reinterpret_cast<char*>(kTurnSendIndicationMsgWithNoAttributes),
- sizeof(kTurnSendIndicationMsgWithNoAttributes),
- &start_pos, &rtp_length));
- EXPECT_EQ(SIZE_MAX, start_pos);
- EXPECT_EQ(SIZE_MAX, rtp_length);
-
- EXPECT_FALSE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
- reinterpret_cast<char*>(kTurnSendIndicationMsgWithInvalidLength),
- sizeof(kTurnSendIndicationMsgWithInvalidLength),
- &start_pos, &rtp_length));
- EXPECT_EQ(SIZE_MAX, start_pos);
- EXPECT_EQ(SIZE_MAX, rtp_length);
-
- EXPECT_FALSE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
- reinterpret_cast<char*>(kTurnSendIndicatinMsgWithNoDataAttribute),
- sizeof(kTurnSendIndicatinMsgWithNoDataAttribute),
- &start_pos, &rtp_length));
- EXPECT_EQ(SIZE_MAX, start_pos);
- EXPECT_EQ(SIZE_MAX, rtp_length);
-}
-
-// This test verifies incorrectly formed TURN channel messages.
-TEST(P2PSocketHostTest, TestInvalidTurnChannelMessages) {
- size_t start_pos = SIZE_MAX, rtp_length = SIZE_MAX;
- EXPECT_FALSE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
- reinterpret_cast<char*>(kTurnChannelMsgNoRtpPacket),
- sizeof(kTurnChannelMsgNoRtpPacket),
- &start_pos, &rtp_length));
- EXPECT_EQ(SIZE_MAX, start_pos);
- EXPECT_EQ(SIZE_MAX, rtp_length);
-
- EXPECT_FALSE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
- reinterpret_cast<char*>(kTurnChannelMsgWithZeroLength),
- sizeof(kTurnChannelMsgWithZeroLength),
- &start_pos, &rtp_length));
- EXPECT_EQ(SIZE_MAX, start_pos);
- EXPECT_EQ(SIZE_MAX, rtp_length);
-}
-
-// This test verifies parsing of a valid RTP packet which has 2byte header
-// extension instead of a 1 byte header extension.
-TEST(P2PSocketHostTest, TestValid2ByteExtnHdrRtpMessage) {
- size_t start_pos = SIZE_MAX, rtp_length = SIZE_MAX;
- EXPECT_TRUE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
- reinterpret_cast<char*>(kRtpMsgWith2ByteExtnHeader),
- sizeof(kRtpMsgWith2ByteExtnHeader),
- &start_pos, &rtp_length));
- EXPECT_EQ(20U, rtp_length);
- EXPECT_EQ(0U, start_pos);
-}
-
-// This test verifies parsing of a valid RTP packet which has 1 byte header
-// AbsSendTime extension in it.
-TEST(P2PSocketHostTest, TestValidRtpPacketWithAbsSendTimeExtension) {
- size_t start_pos = SIZE_MAX, rtp_length = SIZE_MAX;
- EXPECT_TRUE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
- reinterpret_cast<char*>(kRtpMsgWithAbsSendTimeExtension),
- sizeof(kRtpMsgWithAbsSendTimeExtension),
- &start_pos, &rtp_length));
- EXPECT_EQ(24U, rtp_length);
- EXPECT_EQ(0U, start_pos);
-}
-
-// This test verifies parsing of a valid TURN Send Indication messages.
-TEST(P2PSocketHostTest, TestValidTurnSendIndicationMessages) {
- size_t start_pos = SIZE_MAX, rtp_length = SIZE_MAX;
- EXPECT_TRUE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
- reinterpret_cast<char*>(kTurnSendIndicationMsgWithoutRtpExtension),
- sizeof(kTurnSendIndicationMsgWithoutRtpExtension),
- &start_pos, &rtp_length));
- EXPECT_EQ(12U, rtp_length);
- EXPECT_EQ(32U, start_pos);
-
- start_pos = SIZE_MAX, rtp_length = SIZE_MAX;
- EXPECT_TRUE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
- reinterpret_cast<char*>(kTurnSendIndicationMsgWithAbsSendTimeExtension),
- sizeof(kTurnSendIndicationMsgWithAbsSendTimeExtension),
- &start_pos, &rtp_length));
- EXPECT_EQ(24U, rtp_length);
- EXPECT_EQ(32U, start_pos);
-}
-
-// This test verifies parsing of valid TURN Channel Messages.
-TEST(P2PSocketHostTest, TestValidTurnChannelMessages) {
- size_t start_pos = 0, rtp_length = 0;
- EXPECT_TRUE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
- reinterpret_cast<char*>(kTurnChannelMsgWithRtpPacket),
- sizeof(kTurnChannelMsgWithRtpPacket), &start_pos, &rtp_length));
- EXPECT_EQ(12U, rtp_length);
- EXPECT_EQ(4U, start_pos);
-
- start_pos = 0, rtp_length = 0;
- EXPECT_TRUE(packet_processing_helpers::GetRtpPacketStartPositionAndLength(
- reinterpret_cast<char*>(kTurnChannelMsgWithAbsSendTimeExtension),
- sizeof(kTurnChannelMsgWithAbsSendTimeExtension),
- &start_pos, &rtp_length));
- EXPECT_EQ(20U, rtp_length);
- EXPECT_EQ(4U, start_pos);
-}
-
-// Verify handling of a 2 byte extension header RTP messsage. Currently we don't
-// handle this kind of message.
-TEST(P2PSocketHostTest, TestUpdateAbsSendTimeExtensionIn2ByteHeaderExtn) {
- EXPECT_FALSE(packet_processing_helpers::UpdateRtpAbsSendTimeExtension(
- reinterpret_cast<char*>(kRtpMsgWith2ByteExtnHeader),
- sizeof(kRtpMsgWith2ByteExtnHeader),
- 3,
- 0));
-}
-
-// Verify finding an extension ID in the TURN send indication message.
-TEST(P2PSocketHostTest, TestUpdateAbsSendTimeExtensionInTurnSendIndication) {
- EXPECT_TRUE(packet_processing_helpers::UpdateRtpAbsSendTimeExtension(
- reinterpret_cast<char*>(kTurnSendIndicationMsgWithoutRtpExtension),
- sizeof(kTurnSendIndicationMsgWithoutRtpExtension),
- 3,
- 0));
-
- EXPECT_TRUE(packet_processing_helpers::UpdateRtpAbsSendTimeExtension(
- reinterpret_cast<char*>(kTurnSendIndicationMsgWithAbsSendTimeExtension),
- sizeof(kTurnSendIndicationMsgWithAbsSendTimeExtension),
- 3,
- 0));
-}
-
-// Test without any packet options variables set. This method should return
-// without HMAC value in the packet.
-TEST(P2PSocketHostTest, TestApplyPacketOptionsWithDefaultValues) {
- unsigned char fake_tag[4] = { 0xba, 0xdd, 0xba, 0xdd };
- rtc::PacketOptions options;
- std::vector<char> rtp_packet;
- rtp_packet.resize(sizeof(kRtpMsgWithAbsSendTimeExtension) + 4); // tag length
- memcpy(&rtp_packet[0], kRtpMsgWithAbsSendTimeExtension,
- sizeof(kRtpMsgWithAbsSendTimeExtension));
- memcpy(&rtp_packet[sizeof(kRtpMsgWithAbsSendTimeExtension)], fake_tag, 4);
- EXPECT_TRUE(
- packet_processing_helpers::ApplyPacketOptions(
- &rtp_packet[0], rtp_packet.size(), options, 0));
- // Making sure we have't updated the HMAC.
- EXPECT_EQ(0, memcmp(&rtp_packet[sizeof(kRtpMsgWithAbsSendTimeExtension)],
- fake_tag, 4));
-
- // Verify AbsouluteSendTime extension field is not modified.
- EXPECT_EQ(0, memcmp(&rtp_packet[kAstIndexInRtpMsg],
- kTestAstValue, sizeof(kTestAstValue)));
-}
-
-// Veirfy HMAC is updated when packet option parameters are set.
-TEST(P2PSocketHostTest, TestApplyPacketOptionsWithAuthParams) {
- rtc::PacketOptions options;
- options.packet_time_params.srtp_auth_key.resize(20);
- options.packet_time_params.srtp_auth_key.assign(
- kTestKey, kTestKey + sizeof(kTestKey));
- options.packet_time_params.srtp_auth_tag_len = 4;
-
- std::vector<char> rtp_packet;
- rtp_packet.resize(sizeof(kRtpMsgWithAbsSendTimeExtension) + 4); // tag length
- memcpy(&rtp_packet[0], kRtpMsgWithAbsSendTimeExtension,
- sizeof(kRtpMsgWithAbsSendTimeExtension));
- memcpy(&rtp_packet[sizeof(kRtpMsgWithAbsSendTimeExtension)], kFakeTag, 4);
- EXPECT_TRUE(packet_processing_helpers::ApplyPacketOptions(
- &rtp_packet[0], rtp_packet.size(), options, 0));
- // HMAC should be different from fake_tag.
- EXPECT_NE(0, memcmp(&rtp_packet[sizeof(kRtpMsgWithAbsSendTimeExtension)],
- kFakeTag, sizeof(kFakeTag)));
-
- // Verify AbsouluteSendTime extension field is not modified.
- EXPECT_EQ(0, memcmp(&rtp_packet[kAstIndexInRtpMsg],
- kTestAstValue, sizeof(kTestAstValue)));
-}
-
-// Verify finding an extension ID in a raw rtp message.
-TEST(P2PSocketHostTest, TestUpdateAbsSendTimeExtensionInRtpPacket) {
- EXPECT_TRUE(packet_processing_helpers::UpdateRtpAbsSendTimeExtension(
- reinterpret_cast<char*>(kRtpMsgWithAbsSendTimeExtension),
- sizeof(kRtpMsgWithAbsSendTimeExtension),
- 3,
- 0));
-}
-
-// Verify we update both AbsSendTime extension header and HMAC.
-TEST(P2PSocketHostTest, TestApplyPacketOptionsWithAuthParamsAndAbsSendTime) {
- rtc::PacketOptions options;
- options.packet_time_params.srtp_auth_key.resize(20);
- options.packet_time_params.srtp_auth_key.assign(
- kTestKey, kTestKey + sizeof(kTestKey));
- options.packet_time_params.srtp_auth_tag_len = 4;
- options.packet_time_params.rtp_sendtime_extension_id = 3;
- // 3 is also present in the test message.
-
- std::vector<char> rtp_packet;
- rtp_packet.resize(sizeof(kRtpMsgWithAbsSendTimeExtension) + 4); // tag length
- memcpy(&rtp_packet[0], kRtpMsgWithAbsSendTimeExtension,
- sizeof(kRtpMsgWithAbsSendTimeExtension));
- memcpy(&rtp_packet[sizeof(kRtpMsgWithAbsSendTimeExtension)], kFakeTag, 4);
- EXPECT_TRUE(packet_processing_helpers::ApplyPacketOptions(
- &rtp_packet[0], rtp_packet.size(), options, 0xccbbaa));
- // HMAC should be different from fake_tag.
- EXPECT_NE(0, memcmp(&rtp_packet[sizeof(kRtpMsgWithAbsSendTimeExtension)],
- kFakeTag, sizeof(kFakeTag)));
-
- // ApplyPackets should have the new timestamp passed as input.
- unsigned char timestamp_array[3] = { 0xcc, 0xbb, 0xaa };
- EXPECT_EQ(0, memcmp(&rtp_packet[kAstIndexInRtpMsg],
- timestamp_array, sizeof(timestamp_array)));
-}
-
-} // namespace content
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 eaa9c51b71f..852a7d2e24f 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
@@ -211,7 +211,7 @@ bool BrowserPpapiHostImpl::HostMessageFilter::OnMessageReceived(
IPC_MESSAGE_HANDLER(PpapiHostMsg_LogInterfaceUsage,
OnHostMsgLogInterfaceUsage)
IPC_MESSAGE_UNHANDLED(handled = ppapi_host_->OnMessageReceived(msg))
- IPC_END_MESSAGE_MAP();
+ IPC_END_MESSAGE_MAP()
return handled;
}
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc b/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc
index faead267821..eea865bd9df 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.cc
@@ -147,6 +147,9 @@ PepperFileIOHost::UIThreadStuff::UIThreadStuff() {
resolved_render_process_id = base::kNullProcessId;
}
+PepperFileIOHost::UIThreadStuff::UIThreadStuff(const UIThreadStuff& other) =
+ default;
+
PepperFileIOHost::UIThreadStuff::~UIThreadStuff() {}
int32_t PepperFileIOHost::OnHostMsgOpen(
@@ -195,7 +198,6 @@ int32_t PepperFileIOHost::OnHostMsgOpen(
case storage::kFileSystemTypeDeviceMedia:
case storage::kFileSystemTypePicasa:
case storage::kFileSystemTypeItunes:
- case storage::kFileSystemTypeIphoto:
break;
default:
return PP_ERROR_NOACCESS;
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.h b/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.h
index 90de1da7b43..6899c2faa86 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_file_io_host.h
@@ -49,6 +49,7 @@ class PepperFileIOHost : public ppapi::host::ResourceHost,
struct UIThreadStuff {
UIThreadStuff();
+ UIThreadStuff(const UIThreadStuff& other);
~UIThreadStuff();
base::ProcessId resolved_render_process_id;
scoped_refptr<storage::FileSystemContext> file_system_context;
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc
index 3059dd7780e..6f030773518 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_flash_file_message_filter.cc
@@ -136,7 +136,7 @@ int32_t PepperFlashFileMessageFilter::OnOpenFile(
}
IPC::PlatformFileForTransit transit_file =
- IPC::TakeFileHandleForProcess(std::move(file), plugin_process_.Handle());
+ IPC::TakePlatformFileForTransit(std::move(file));
ppapi::host::ReplyMessageContext reply_context =
context->MakeReplyMessageContext();
reply_context.params.AppendHandle(ppapi::proxy::SerializedHandle(
@@ -258,7 +258,7 @@ int32_t PepperFlashFileMessageFilter::OnCreateTemporaryFile(
return ppapi::FileErrorToPepperError(file.error_details());
IPC::PlatformFileForTransit transit_file =
- IPC::TakeFileHandleForProcess(std::move(file), plugin_process_.Handle());
+ IPC::TakePlatformFileForTransit(std::move(file));
ppapi::host::ReplyMessageContext reply_context =
context->MakeReplyMessageContext();
reply_context.params.AppendHandle(ppapi::proxy::SerializedHandle(
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 c841981c21b..60cba96ac3d 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
@@ -70,7 +70,7 @@ void CreateNetAddressListFromAddressList(
PP_NetAddress_Private address;
for (size_t i = 0; i < list.size(); ++i) {
if (!ppapi::NetAddressPrivateImpl::IPEndPointToNetAddress(
- list[i].address(), list[i].port(), &address)) {
+ list[i].address().bytes(), list[i].port(), &address)) {
net_address_list->clear();
return;
}
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 1f9d27bafa0..467597fb39d 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
@@ -98,6 +98,7 @@ int32_t PepperInternalFileRefBackend::MakeDirectory(
if (!GetFileSystemURL().is_valid())
return PP_ERROR_FAILED;
+ PpapiPluginMsg_FileRef_MakeDirectoryReply reply;
GetFileSystemContext()->operation_runner()->CreateDirectory(
GetFileSystemURL(),
!!(make_directory_flags & PP_MAKEDIRECTORYFLAG_EXCLUSIVE),
@@ -105,7 +106,7 @@ int32_t PepperInternalFileRefBackend::MakeDirectory(
base::Bind(&PepperInternalFileRefBackend::DidFinish,
weak_factory_.GetWeakPtr(),
reply_context,
- PpapiPluginMsg_FileRef_MakeDirectoryReply()));
+ reply));
return PP_OK_COMPLETIONPENDING;
}
@@ -116,6 +117,7 @@ int32_t PepperInternalFileRefBackend::Touch(
if (!GetFileSystemURL().is_valid())
return PP_ERROR_FAILED;
+ PpapiPluginMsg_FileRef_TouchReply reply;
GetFileSystemContext()->operation_runner()->TouchFile(
GetFileSystemURL(),
ppapi::PPTimeToTime(last_access_time),
@@ -123,7 +125,7 @@ int32_t PepperInternalFileRefBackend::Touch(
base::Bind(&PepperInternalFileRefBackend::DidFinish,
weak_factory_.GetWeakPtr(),
reply_context,
- PpapiPluginMsg_FileRef_TouchReply()));
+ reply));
return PP_OK_COMPLETIONPENDING;
}
@@ -132,13 +134,14 @@ int32_t PepperInternalFileRefBackend::Delete(
if (!GetFileSystemURL().is_valid())
return PP_ERROR_FAILED;
+ PpapiPluginMsg_FileRef_DeleteReply reply;
GetFileSystemContext()->operation_runner()->Remove(
GetFileSystemURL(),
false,
base::Bind(&PepperInternalFileRefBackend::DidFinish,
weak_factory_.GetWeakPtr(),
reply_context,
- PpapiPluginMsg_FileRef_DeleteReply()));
+ reply));
return PP_OK_COMPLETIONPENDING;
}
@@ -154,6 +157,7 @@ int32_t PepperInternalFileRefBackend::Rename(
if (!new_url.IsInSameFileSystem(GetFileSystemURL()))
return PP_ERROR_FAILED;
+ PpapiPluginMsg_FileRef_RenameReply reply;
GetFileSystemContext()->operation_runner()->Move(
GetFileSystemURL(),
new_url,
@@ -161,7 +165,7 @@ int32_t PepperInternalFileRefBackend::Rename(
base::Bind(&PepperInternalFileRefBackend::DidFinish,
weak_factory_.GetWeakPtr(),
reply_context,
- PpapiPluginMsg_FileRef_RenameReply()));
+ reply));
return PP_OK_COMPLETIONPENDING;
}
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
index 2d07e2a54f6..211906a15a9 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_network_monitor_host.cc
@@ -106,7 +106,7 @@ void PepperNetworkMonitorHost::SendNetworkList(
network_copy.addresses.resize(
1, ppapi::NetAddressPrivateImpl::kInvalidNetAddress);
bool result = ppapi::NetAddressPrivateImpl::IPEndPointToNetAddress(
- network.address, 0, &(network_copy.addresses[0]));
+ network.address.bytes(), 0, &(network_copy.addresses[0]));
DCHECK(result);
// TODO(sergeyu): Currently net::NetworkInterfaceList provides
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 b80d1c6f9c3..1f9ac0effa6 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
@@ -10,6 +10,7 @@
#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/storage_partition.h"
#include "content/public/common/socket_permission_request.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
@@ -58,6 +59,9 @@ PepperNetworkProxyHost::~PepperNetworkProxyHost() {
PepperNetworkProxyHost::UIThreadData::UIThreadData() : is_allowed(false) {}
+PepperNetworkProxyHost::UIThreadData::UIThreadData(const UIThreadData& other) =
+ default;
+
PepperNetworkProxyHost::UIThreadData::~UIThreadData() {}
// static
@@ -67,13 +71,9 @@ PepperNetworkProxyHost::GetUIThreadDataOnUIThread(int render_process_id,
bool is_external_plugin) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
PepperNetworkProxyHost::UIThreadData result;
- RenderProcessHost* render_process_host =
- RenderProcessHost::FromID(render_process_id);
- if (render_process_host && render_process_host->GetBrowserContext()) {
- result.context_getter =
- render_process_host->GetBrowserContext()
- ->GetRequestContextForRenderProcess(render_process_id);
- }
+ RenderProcessHost* rph = RenderProcessHost::FromID(render_process_id);
+ if (rph)
+ result.context_getter = rph->GetStoragePartition()->GetURLRequestContext();
SocketPermissionRequest request(
content::SocketPermissionRequest::RESOLVE_PROXY, std::string(), 0);
@@ -146,6 +146,7 @@ void PepperNetworkProxyHost::TryToSendUnsentRequests() {
request.reply_context,
base::Owned(proxy_info));
int result = proxy_service_->ResolveProxy(request.url,
+ std::string(),
net::LOAD_NORMAL,
proxy_info,
callback,
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.h b/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.h
index 0992c9fc68d..309e692db09 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_network_proxy_host.h
@@ -48,6 +48,7 @@ class CONTENT_EXPORT PepperNetworkProxyHost : public ppapi::host::ResourceHost {
// DidGetUIThreadData, which sets allowed_ and proxy_service_.
struct UIThreadData {
UIThreadData();
+ UIThreadData(const UIThreadData& other);
~UIThreadData();
bool is_allowed;
scoped_refptr<net::URLRequestContextGetter> context_getter;
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 94ee8d71c81..cb87538b016 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_socket_utils.cc
@@ -181,11 +181,12 @@ std::string AddressToFirewallString(const net::IPAddressNumber& address) {
void OpenFirewallHole(const net::IPEndPoint& address,
chromeos::FirewallHole::PortType type,
FirewallHoleOpenCallback callback) {
- if (IsLoopbackAddress(address.address())) {
+ if (IsLoopbackAddress(address.address().bytes())) {
callback.Run(nullptr);
return;
}
- std::string address_string = AddressToFirewallString(address.address());
+ std::string address_string =
+ AddressToFirewallString(address.address().bytes());
chromeos::FirewallHole::Open(type, address.port(), address_string, callback);
}
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 e342c233ba1..080a63a385c 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
@@ -5,6 +5,7 @@
#include "content/browser/renderer_host/pepper/pepper_tcp_server_socket_message_filter.h"
#include <utility>
+#include <vector>
#include "base/bind.h"
#include "base/bind_helpers.h"
@@ -15,9 +16,9 @@
#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_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/private/ppb_net_address_private.h"
#include "ppapi/host/dispatch_host_message.h"
@@ -172,7 +173,7 @@ void PepperTCPServerSocketMessageFilter::DoListen(
int32_t backlog) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- net::IPAddressNumber address;
+ std::vector<uint8_t> address;
uint16_t port;
if (state_ != STATE_BEFORE_LISTENING ||
!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) {
@@ -186,7 +187,7 @@ void PepperTCPServerSocketMessageFilter::DoListen(
socket_.reset(new net::TCPSocket(NULL, net::NetLog::Source()));
int net_result = net::OK;
do {
- net::IPEndPoint ip_end_point(address, port);
+ net::IPEndPoint ip_end_point(net::IPAddress(address), port);
net_result = socket_->Open(ip_end_point.GetFamily());
if (net_result != net::OK)
break;
@@ -235,7 +236,7 @@ void PepperTCPServerSocketMessageFilter::OnListenCompleted(
return;
}
if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
- end_point.address(), end_point.port(), &addr)) {
+ end_point.address().bytes(), end_point.port(), &addr)) {
SendListenError(context, PP_ERROR_FAILED);
state_ = STATE_BEFORE_LISTENING;
return;
@@ -301,12 +302,10 @@ void PepperTCPServerSocketMessageFilter::OnAcceptCompleted(
return;
}
if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
- ip_end_point_local.address(),
- ip_end_point_local.port(),
+ ip_end_point_local.address().bytes(), ip_end_point_local.port(),
&local_addr) ||
!NetAddressPrivateImpl::IPEndPointToNetAddress(
- accepted_address_.address(),
- accepted_address_.port(),
+ accepted_address_.address().bytes(), accepted_address_.port(),
&remote_addr)) {
SendAcceptError(context, PP_ERROR_FAILED);
return;
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
index 91a851228a7..661fdc52e5d 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
+++ b/chromium/content/browser/renderer_host/pepper/pepper_tcp_socket_message_filter.cc
@@ -6,6 +6,7 @@
#include <cstring>
#include <utility>
+#include <vector>
#include "base/bind.h"
#include "base/location.h"
@@ -23,6 +24,7 @@
#include "net/base/address_family.h"
#include "net/base/host_port_pair.h"
#include "net/base/io_buffer.h"
+#include "net/base/ip_address.h"
#include "net/base/net_errors.h"
#include "net/dns/single_request_host_resolver.h"
#include "net/socket/client_socket_factory.h"
@@ -573,14 +575,14 @@ void PepperTCPSocketMessageFilter::DoBind(
int pp_result = PP_OK;
do {
- net::IPAddressNumber address;
+ std::vector<uint8_t> address;
uint16_t port;
if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(
net_addr, &address, &port)) {
pp_result = PP_ERROR_ADDRESS_INVALID;
break;
}
- net::IPEndPoint bind_addr(address, port);
+ net::IPEndPoint bind_addr(net::IPAddress(address), port);
DCHECK(!socket_->IsValid());
pp_result = NetErrorToPepperError(socket_->Open(bind_addr.GetFamily()));
@@ -604,8 +606,7 @@ void PepperTCPSocketMessageFilter::DoBind(
PP_NetAddress_Private local_addr =
NetAddressPrivateImpl::kInvalidNetAddress;
if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
- ip_end_point_local.address(),
- ip_end_point_local.port(),
+ ip_end_point_local.address().bytes(), ip_end_point_local.port(),
&local_addr)) {
pp_result = PP_ERROR_ADDRESS_INVALID;
break;
@@ -834,12 +835,10 @@ void PepperTCPSocketMessageFilter::OnConnectCompleted(
PP_NetAddress_Private remote_addr =
NetAddressPrivateImpl::kInvalidNetAddress;
if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
- ip_end_point_local.address(),
- ip_end_point_local.port(),
+ ip_end_point_local.address().bytes(), ip_end_point_local.port(),
&local_addr) ||
!NetAddressPrivateImpl::IPEndPointToNetAddress(
- ip_end_point_remote.address(),
- ip_end_point_remote.port(),
+ ip_end_point_remote.address().bytes(), ip_end_point_remote.port(),
&remote_addr)) {
pp_result = PP_ERROR_ADDRESS_INVALID;
break;
@@ -1007,12 +1006,10 @@ void PepperTCPSocketMessageFilter::OnAcceptCompleted(
return;
}
if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
- ip_end_point_local.address(),
- ip_end_point_local.port(),
+ ip_end_point_local.address().bytes(), ip_end_point_local.port(),
&local_addr) ||
!NetAddressPrivateImpl::IPEndPointToNetAddress(
- accepted_address_.address(),
- accepted_address_.port(),
+ accepted_address_.address().bytes(), accepted_address_.port(),
&remote_addr)) {
SendAcceptError(context, PP_ERROR_ADDRESS_INVALID);
return;
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 2dc256b3dae..b5f6e14c89e 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
@@ -53,12 +53,14 @@ size_t g_num_instances = 0;
namespace content {
PepperUDPSocketMessageFilter::PendingSend::PendingSend(
- const net::IPAddressNumber& address,
+ const net::IPAddress& address,
int port,
const scoped_refptr<net::IOBufferWithSize>& buffer,
const ppapi::host::ReplyMessageContext& context)
- : address(address), port(port), buffer(buffer), context(context) {
-}
+ : address(address), port(port), buffer(buffer), context(context) {}
+
+PepperUDPSocketMessageFilter::PendingSend::PendingSend(
+ const PendingSend& other) = default;
PepperUDPSocketMessageFilter::PendingSend::~PendingSend() {
}
@@ -361,13 +363,13 @@ int32_t PepperUDPSocketMessageFilter::OnMsgJoinGroup(
if (!socket_)
return PP_ERROR_FAILED;
- net::IPAddressNumber group;
+ std::vector<uint8_t> group;
uint16_t port;
if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &group, &port))
return PP_ERROR_ADDRESS_INVALID;
- return NetErrorToPepperError(socket_->JoinGroup(group));
+ return NetErrorToPepperError(socket_->JoinGroup(net::IPAddress(group)));
}
int32_t PepperUDPSocketMessageFilter::OnMsgLeaveGroup(
@@ -382,13 +384,13 @@ int32_t PepperUDPSocketMessageFilter::OnMsgLeaveGroup(
if (!socket_)
return PP_ERROR_FAILED;
- net::IPAddressNumber group;
+ std::vector<uint8_t> group;
uint16_t port;
if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &group, &port))
return PP_ERROR_ADDRESS_INVALID;
- return NetErrorToPepperError(socket_->LeaveGroup(group));
+ return NetErrorToPepperError(socket_->LeaveGroup(net::IPAddress(group)));
}
void PepperUDPSocketMessageFilter::DoBind(
@@ -405,13 +407,13 @@ void PepperUDPSocketMessageFilter::DoBind(
net::DatagramSocket::DEFAULT_BIND, net::RandIntCallback(),
NULL, net::NetLog::Source()));
- net::IPAddressNumber address;
+ std::vector<uint8_t> address;
uint16_t port;
if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) {
SendBindError(context, PP_ERROR_ADDRESS_INVALID);
return;
}
- net::IPEndPoint end_point(address, port);
+ net::IPEndPoint end_point(net::IPAddress(address), port);
{
int net_result = socket->Open(end_point.GetFamily());
if (net_result != net::OK) {
@@ -492,7 +494,8 @@ void PepperUDPSocketMessageFilter::DoBind(
PP_NetAddress_Private net_address = NetAddressPrivateImpl::kInvalidNetAddress;
if (!NetAddressPrivateImpl::IPEndPointToNetAddress(
- bound_address.address(), bound_address.port(), &net_address)) {
+ bound_address.address().bytes(), bound_address.port(),
+ &net_address)) {
SendBindError(context, PP_ERROR_ADDRESS_INVALID);
return;
}
@@ -585,7 +588,7 @@ void PepperUDPSocketMessageFilter::DoSendTo(
return;
}
- net::IPAddressNumber address;
+ std::vector<uint8_t> address;
uint16_t port;
if (!NetAddressPrivateImpl::NetAddressToIPEndPoint(addr, &address, &port)) {
SendSendToError(context, PP_ERROR_ADDRESS_INVALID);
@@ -603,7 +606,8 @@ void PepperUDPSocketMessageFilter::DoSendTo(
return;
}
- pending_sends_.push(PendingSend(address, port, buffer, context));
+ pending_sends_.push(
+ PendingSend(net::IPAddress(address), port, buffer, context));
// If there are other sends pending, we can't start yet.
if (num_pending_sends)
return;
@@ -644,7 +648,8 @@ void PepperUDPSocketMessageFilter::OnRecvFromCompleted(int net_result) {
PP_NetAddress_Private addr = NetAddressPrivateImpl::kInvalidNetAddress;
if (pp_result >= 0 &&
!NetAddressPrivateImpl::IPEndPointToNetAddress(
- recvfrom_address_.address(), recvfrom_address_.port(), &addr)) {
+ recvfrom_address_.address().bytes(), recvfrom_address_.port(),
+ &addr)) {
pp_result = PP_ERROR_ADDRESS_INVALID;
}
diff --git a/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h b/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h
index 314599beedf..64205819d09 100644
--- a/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h
+++ b/chromium/content/browser/renderer_host/pepper/pepper_udp_socket_message_filter.h
@@ -19,6 +19,7 @@
#include "content/common/content_export.h"
#include "content/public/common/process_type.h"
#include "net/base/completion_callback.h"
+#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/udp/udp_socket.h"
#include "ppapi/c/pp_instance.h"
@@ -75,13 +76,14 @@ class CONTENT_EXPORT PepperUDPSocketMessageFilter
};
struct PendingSend {
- PendingSend(const net::IPAddressNumber& address,
+ PendingSend(const net::IPAddress& address,
int port,
const scoped_refptr<net::IOBufferWithSize>& buffer,
const ppapi::host::ReplyMessageContext& context);
+ PendingSend(const PendingSend& other);
~PendingSend();
- net::IPAddressNumber address;
+ net::IPAddress address;
int port;
scoped_refptr<net::IOBufferWithSize> buffer;
ppapi::host::ReplyMessageContext context;
diff --git a/chromium/content/browser/renderer_host/pepper/quota_reservation.cc b/chromium/content/browser/renderer_host/pepper/quota_reservation.cc
index 5343cbd153f..518421a7031 100644
--- a/chromium/content/browser/renderer_host/pepper/quota_reservation.cc
+++ b/chromium/content/browser/renderer_host/pepper/quota_reservation.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
#include "content/public/browser/browser_thread.h"
#include "storage/browser/fileapi/file_system_operation_runner.h"
#include "storage/browser/fileapi/quota/open_file_handle.h"
diff --git a/chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc b/chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc
index c1068db228b..1416587d0fb 100644
--- a/chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc
+++ b/chromium/content/browser/renderer_host/pepper/quota_reservation_unittest.cc
@@ -13,6 +13,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/location.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
diff --git a/chromium/content/browser/renderer_host/render_message_filter.cc b/chromium/content/browser/renderer_host/render_message_filter.cc
index cec7b8b1225..8d5ae8e9d47 100644
--- a/chromium/content/browser/renderer_host/render_message_filter.cc
+++ b/chromium/content/browser/renderer_host/render_message_filter.cc
@@ -24,17 +24,20 @@
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
#include "content/browser/download/download_stats.h"
+#include "content/browser/fileapi/chrome_blob_storage_context.h"
#include "content/browser/gpu/browser_gpu_memory_buffer_manager.h"
+#include "content/browser/gpu/gpu_data_manager_impl.h"
+#include "content/browser/gpu/gpu_process_host.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/media/media_internals.h"
#include "content/browser/renderer_host/pepper/pepper_security_helper.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_widget_helper.h"
+#include "content/browser/resource_context_impl.h"
#include "content/common/child_process_host_impl.h"
#include "content/common/child_process_messages.h"
#include "content/common/content_constants_internal.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
#include "content/common/host_shared_bitmap_manager.h"
#include "content/common/render_process_messages.h"
#include "content/common/view_messages.h"
@@ -42,12 +45,14 @@
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/download_save_info.h"
+#include "content/public/browser/download_manager.h"
+#include "content/public/browser/download_url_parameters.h"
#include "content/public/browser/resource_context.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/context_menu_params.h"
#include "content/public/common/url_constants.h"
+#include "gpu/ipc/client/gpu_memory_buffer_impl.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_platform_file.h"
#include "media/audio/audio_manager.h"
@@ -62,6 +67,7 @@
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "ppapi/shared_impl/file_type_conversion.h"
+#include "storage/browser/blob/blob_storage_context.h"
#include "ui/gfx/color_profile.h"
#include "url/gurl.h"
@@ -100,6 +106,21 @@ base::LazyInstance<gfx::ColorProfile>::Leaky g_color_profile =
LAZY_INSTANCE_INITIALIZER;
#endif
+void DownloadUrlOnUIThread(scoped_ptr<DownloadUrlParameters> parameters) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ RenderProcessHost* render_process_host =
+ RenderProcessHost::FromID(parameters->render_process_host_id());
+ if (!render_process_host)
+ return;
+
+ BrowserContext* browser_context = render_process_host->GetBrowserContext();
+ DownloadManager* download_manager =
+ BrowserContext::GetDownloadManager(browser_context);
+ RecordDownloadSource(INITIATED_BY_RENDERER);
+ download_manager->DownloadUrl(std::move(parameters));
+}
+
} // namespace
RenderMessageFilter::RenderMessageFilter(
@@ -118,9 +139,11 @@ RenderMessageFilter::RenderMessageFilter(
resource_context_(browser_context->GetResourceContext()),
render_widget_helper_(render_widget_helper),
dom_storage_context_(dom_storage_context),
+ gpu_process_id_(0),
render_process_id_(render_process_id),
audio_manager_(audio_manager),
- media_internals_(media_internals) {
+ media_internals_(media_internals),
+ weak_ptr_factory_(this) {
DCHECK(request_context_.get());
if (render_widget_helper)
@@ -169,6 +192,10 @@ bool RenderMessageFilter::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER_DELAY_REPLY(
ChildProcessHostMsg_SyncAllocateGpuMemoryBuffer,
OnAllocateGpuMemoryBuffer)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(ChildProcessHostMsg_EstablishGpuChannel,
+ OnEstablishGpuChannel)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(ChildProcessHostMsg_HasGpuProcess,
+ OnHasGpuProcess)
IPC_MESSAGE_HANDLER(ChildProcessHostMsg_DeletedGpuMemoryBuffer,
OnDeletedGpuMemoryBuffer)
IPC_MESSAGE_HANDLER(ChildProcessHostMsg_AllocatedSharedBitmap,
@@ -372,19 +399,26 @@ void RenderMessageFilter::DownloadUrl(int render_view_id,
if (!resource_context_)
return;
- scoped_ptr<DownloadSaveInfo> save_info(new DownloadSaveInfo());
- save_info->suggested_name = suggested_name;
- save_info->prompt_for_save_location = use_prompt;
- scoped_ptr<net::URLRequest> request(
- resource_context_->GetRequestContext()->CreateRequest(
- url, net::DEFAULT_PRIORITY, NULL));
- RecordDownloadSource(INITIATED_BY_RENDERER);
- resource_dispatcher_host_->BeginDownload(
- std::move(request), referrer,
- true, // is_content_initiated
- resource_context_, render_process_id_, render_view_id, render_frame_id,
- false, false, std::move(save_info), DownloadItem::kInvalidId,
- ResourceDispatcherHostImpl::DownloadStartedCallback());
+ scoped_ptr<DownloadUrlParameters> parameters(
+ new DownloadUrlParameters(url, render_process_id_, render_view_id,
+ render_frame_id, resource_context_));
+ parameters->set_content_initiated(true);
+ parameters->set_suggested_name(suggested_name);
+ parameters->set_prompt(use_prompt);
+ parameters->set_referrer(referrer);
+
+ if (url.SchemeIsBlob()) {
+ ChromeBlobStorageContext* blob_context =
+ GetChromeBlobStorageContextForResourceContext(resource_context_);
+ parameters->set_blob_data_handle(
+ blob_context->context()->GetBlobDataFromPublicURL(url));
+ // Don't care if the above fails. We are going to let the download go
+ // through and allow it to be interrupted so that the embedder can deal.
+ }
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&DownloadUrlOnUIThread, base::Passed(&parameters)));
}
void RenderMessageFilter::OnDownloadUrl(int render_view_id,
@@ -639,6 +673,74 @@ void RenderMessageFilter::GpuMemoryBufferAllocated(
Send(reply);
}
+void RenderMessageFilter::OnEstablishGpuChannel(
+ CauseForGpuLaunch cause_for_gpu_launch,
+ IPC::Message* reply_ptr) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ scoped_ptr<IPC::Message> reply(reply_ptr);
+
+#if defined(OS_WIN) && defined(ARCH_CPU_X86_64)
+ // TODO(jbauman): Remove this when we know why renderer processes are
+ // hanging on x86-64. https://crbug.com/577127
+ if (!GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor()) {
+ reply->set_reply_error();
+ Send(reply.release());
+ return;
+ }
+#endif
+
+ GpuProcessHost* host = GpuProcessHost::FromID(gpu_process_id_);
+ if (!host) {
+ host = GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
+ cause_for_gpu_launch);
+ if (!host) {
+ reply->set_reply_error();
+ Send(reply.release());
+ return;
+ }
+
+ gpu_process_id_ = host->host_id();
+ }
+
+ bool preempts = false;
+ bool allow_view_command_buffers = false;
+ bool allow_real_time_streams = false;
+ host->EstablishGpuChannel(
+ render_process_id_,
+ ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId(
+ render_process_id_),
+ preempts, allow_view_command_buffers, allow_real_time_streams,
+ base::Bind(&RenderMessageFilter::EstablishChannelCallback,
+ weak_ptr_factory_.GetWeakPtr(), base::Passed(&reply)));
+}
+
+void RenderMessageFilter::OnHasGpuProcess(IPC::Message* reply_ptr) {
+ scoped_ptr<IPC::Message> reply(reply_ptr);
+ GpuProcessHost::GetProcessHandles(
+ base::Bind(&RenderMessageFilter::GetGpuProcessHandlesCallback,
+ weak_ptr_factory_.GetWeakPtr(), base::Passed(&reply)));
+}
+
+void RenderMessageFilter::EstablishChannelCallback(
+ scoped_ptr<IPC::Message> reply,
+ const IPC::ChannelHandle& channel,
+ const gpu::GPUInfo& gpu_info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ ChildProcessHostMsg_EstablishGpuChannel::WriteReplyParams(
+ reply.get(), render_process_id_, channel, gpu_info);
+ Send(reply.release());
+}
+
+void RenderMessageFilter::GetGpuProcessHandlesCallback(
+ scoped_ptr<IPC::Message> reply,
+ const std::list<base::ProcessHandle>& handles) {
+ bool has_gpu_process = handles.size() > 0;
+ ChildProcessHostMsg_HasGpuProcess::WriteReplyParams(reply.get(),
+ has_gpu_process);
+ Send(reply.release());
+}
+
void RenderMessageFilter::OnDeletedGpuMemoryBuffer(
gfx::GpuMemoryBufferId id,
const gpu::SyncToken& sync_token) {
diff --git a/chromium/content/browser/renderer_host/render_message_filter.h b/chromium/content/browser/renderer_host/render_message_filter.h
index ce07dfee796..a42690e2808 100644
--- a/chromium/content/browser/renderer_host/render_message_filter.h
+++ b/chromium/content/browser/renderer_host/render_message_filter.h
@@ -15,13 +15,16 @@
#include "base/macros.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/shared_memory.h"
+#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner_helpers.h"
#include "base/strings/string16.h"
#include "build/build_config.h"
#include "cc/resources/shared_bitmap_manager.h"
+#include "content/common/gpu_process_launch_causes.h"
#include "content/common/host_discardable_shared_memory_manager.h"
#include "content/common/host_shared_bitmap_manager.h"
#include "content/public/browser/browser_message_filter.h"
+#include "gpu/config/gpu_info.h"
#include "ipc/message_filter.h"
#include "media/audio/audio_parameters.h"
#include "media/base/channel_layout.h"
@@ -160,6 +163,16 @@ class CONTENT_EXPORT RenderMessageFilter : public BrowserMessageFilter {
void OnGetMonitorColorProfile(std::vector<char>* profile);
#endif
+ // Message handlers called on the browser IO thread:
+ void OnEstablishGpuChannel(CauseForGpuLaunch, IPC::Message* reply);
+ void OnHasGpuProcess(IPC::Message* reply);
+ // Helper callbacks for the message handlers.
+ void EstablishChannelCallback(scoped_ptr<IPC::Message> reply,
+ const IPC::ChannelHandle& channel,
+ const gpu::GPUInfo& gpu_info);
+ void GetGpuProcessHandlesCallback(
+ scoped_ptr<IPC::Message> reply,
+ const std::list<base::ProcessHandle>& handles);
// Used to ask the browser to allocate a block of shared memory for the
// renderer to send back data in, since shared memory can't be created
// in the renderer on POSIX due to the sandbox.
@@ -234,11 +247,14 @@ class CONTENT_EXPORT RenderMessageFilter : public BrowserMessageFilter {
scoped_refptr<DOMStorageContextWrapper> dom_storage_context_;
+ int gpu_process_id_;
int render_process_id_;
media::AudioManager* audio_manager_;
MediaInternals* media_internals_;
+ base::WeakPtrFactory<RenderMessageFilter> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(RenderMessageFilter);
};
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 667dc22a081..248555b5937 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.cc
@@ -24,8 +24,11 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/metrics/field_trial.h"
+#include "base/memory/shared_memory.h"
+#include "base/memory/shared_memory_handle.h"
#include "base/metrics/histogram.h"
+#include "base/metrics/persistent_histogram_allocator.h"
+#include "base/metrics/persistent_memory_allocator.h"
#include "base/process/process_handle.h"
#include "base/rand_util.h"
#include "base/single_thread_task_runner.h"
@@ -45,6 +48,7 @@
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/background_sync/background_sync_service_impl.h"
#include "content/browser/bad_message.h"
+#include "content/browser/blob_storage/blob_dispatcher_host.h"
#include "content/browser/bluetooth/bluetooth_dispatcher_host.h"
#include "content/browser/browser_child_process_host_impl.h"
#include "content/browser/browser_main.h"
@@ -80,7 +84,7 @@
#include "content/browser/message_port_message_filter.h"
#include "content/browser/mime_registry_message_filter.h"
#include "content/browser/mojo/mojo_application_host.h"
-#include "content/browser/navigator_connect/service_port_service_impl.h"
+#include "content/browser/mojo/mojo_child_connection.h"
#include "content/browser/notifications/notification_message_filter.h"
#include "content/browser/permissions/permission_service_context.h"
#include "content/browser/permissions/permission_service_impl.h"
@@ -91,13 +95,11 @@
#include "content/browser/renderer_host/database_message_filter.h"
#include "content/browser/renderer_host/file_utilities_message_filter.h"
#include "content/browser/renderer_host/gamepad_browser_message_filter.h"
-#include "content/browser/renderer_host/gpu_message_filter.h"
#include "content/browser/renderer_host/media/audio_input_renderer_host.h"
#include "content/browser/renderer_host/media/audio_renderer_host.h"
#include "content/browser/renderer_host/media/media_stream_dispatcher_host.h"
#include "content/browser/renderer_host/media/peer_connection_tracker_host.h"
#include "content/browser/renderer_host/media/video_capture_host.h"
-#include "content/browser/renderer_host/memory_benchmark_message_filter.h"
#include "content/browser/renderer_host/pepper/pepper_message_filter.h"
#include "content/browser/renderer_host/pepper/pepper_renderer_connection.h"
#include "content/browser/renderer_host/render_message_filter.h"
@@ -121,17 +123,18 @@
#include "content/common/child_process_messages.h"
#include "content/common/content_switches_internal.h"
#include "content/common/frame_messages.h"
-#include "content/common/gpu/gpu_messages.h"
+#include "content/common/gpu_host_messages.h"
#include "content/common/in_process_child_thread_params.h"
#include "content/common/mojo/channel_init.h"
#include "content/common/mojo/mojo_messages.h"
+#include "content/common/mojo/mojo_shell_connection_impl.h"
#include "content/common/render_process_messages.h"
#include "content/common/resource_messages.h"
#include "content/common/site_isolation_policy.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/navigator_connect_context.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_process_host_factory.h"
@@ -165,12 +168,11 @@
#include "ipc/ipc_switches.h"
#include "ipc/mojo/ipc_channel_mojo.h"
#include "media/base/media_switches.h"
+#include "mojo/edk/embedder/embedder.h"
+#include "mojo/shell/runner/common/switches.h"
#include "net/url_request/url_request_context_getter.h"
#include "ppapi/shared_impl/ppapi_switches.h"
#include "storage/browser/fileapi/sandbox_file_system_backend.h"
-#include "third_party/icu/source/common/unicode/unistr.h"
-#include "third_party/icu/source/i18n/unicode/timezone.h"
-#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/ui_base_switches.h"
#include "ui/events/event_switches.h"
@@ -197,14 +199,18 @@
#include "ui/gfx/win/dpi.h"
#endif
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MACOSX)
#include "content/browser/bootstrap_sandbox_manager_mac.h"
#include "content/browser/mach_broker_mac.h"
#endif
+#if defined(OS_POSIX)
+#include "content/browser/zygote_host/zygote_communication_linux.h"
+#include "content/browser/zygote_host/zygote_host_impl_linux.h"
+#include "content/public/browser/zygote_handle_linux.h"
+#endif // defined(OS_POSIX)
+
#if defined(USE_OZONE)
-#include "ui/ozone/public/client_native_pixmap_factory.h"
-#include "ui/ozone/public/ozone_platform.h"
#include "ui/ozone/public/ozone_switches.h"
#endif
@@ -217,7 +223,7 @@
#endif
#if defined(ENABLE_WEBRTC)
-#include "content/browser/media/webrtc_internals.h"
+#include "content/browser/media/webrtc/webrtc_internals.h"
#include "content/browser/renderer_host/media/media_stream_track_metrics_host.h"
#include "content/browser/renderer_host/media/webrtc_identity_service_host.h"
#include "content/browser/renderer_host/p2p/socket_dispatcher_host.h"
@@ -225,11 +231,6 @@
#include "content/common/media/media_stream_messages.h"
#endif
-#if defined(MOJO_SHELL_CLIENT)
-#include "content/browser/mojo/mojo_shell_client_host.h"
-#include "content/common/mojo/mojo_shell_connection_impl.h"
-#endif
-
#if defined(OS_WIN)
#define IntToStringType base::IntToString16
#else
@@ -284,8 +285,7 @@ void GetContexts(
#if defined(ENABLE_WEBRTC)
// Creates a file used for handing over to the renderer.
-IPC::PlatformFileForTransit CreateFileForProcess(base::FilePath file_path,
- base::ProcessHandle process) {
+IPC::PlatformFileForTransit CreateFileForProcess(base::FilePath file_path) {
DCHECK_CURRENTLY_ON(BrowserThread::FILE);
base::File dump_file(file_path,
base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_APPEND);
@@ -294,16 +294,12 @@ IPC::PlatformFileForTransit CreateFileForProcess(base::FilePath file_path,
<< dump_file.error_details();
return IPC::InvalidPlatformFileForTransit();
}
- return IPC::TakeFileHandleForProcess(std::move(dump_file), process);
+ return IPC::TakePlatformFileForTransit(std::move(dump_file));
}
// Allow us to only run the trial in the first renderer.
bool has_done_stun_trials = false;
-// Does nothing. Just to avoid races between enable and disable.
-void DisableAecDumpOnFileThread() {
- DCHECK_CURRENTLY_ON(BrowserThread::FILE);
-}
#endif
// the global list of all renderer processes
@@ -363,6 +359,12 @@ SiteProcessMap* GetSiteProcessMapForBrowserContext(BrowserContext* context) {
return map;
}
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+// This static member variable holds the zygote communication information for
+// the renderer.
+ZygoteHandle g_render_zygote;
+#endif // defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+
// NOTE: changes to this class need to be reviewed by the security team.
class RendererSandboxedProcessLauncherDelegate
: public SandboxedProcessLauncherDelegate {
@@ -390,13 +392,17 @@ class RendererSandboxedProcessLauncherDelegate
}
#elif defined(OS_POSIX)
- bool ShouldUseZygote() override {
+#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
+ ZygoteHandle* GetZygote() override {
const base::CommandLine& browser_command_line =
*base::CommandLine::ForCurrentProcess();
base::CommandLine::StringType renderer_prefix =
browser_command_line.GetSwitchValueNative(switches::kRendererCmdPrefix);
- return renderer_prefix.empty();
+ if (!renderer_prefix.empty())
+ return nullptr;
+ return GetGenericZygote();
}
+#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
base::ScopedFD TakeIpcFd() override { return std::move(ipc_fd_); }
#endif // OS_WIN
@@ -439,24 +445,6 @@ std::string UintVectorToString(const std::vector<unsigned>& vector) {
return str;
}
-// Copies kEnableFeatures and kDisableFeatures to the renderer command line.
-// Generates them from the FeatureList override state, to take into account
-// overrides from FieldTrials.
-void CopyEnableDisableFeatureFlagsToRenderer(base::CommandLine* renderer_cmd) {
- std::string enabled_features;
- std::string disabled_features;
- base::FeatureList::GetInstance()->GetFeatureOverrides(&enabled_features,
- &disabled_features);
- if (!enabled_features.empty()) {
- renderer_cmd->AppendSwitchASCII(switches::kEnableFeatures,
- enabled_features);
- }
- if (!disabled_features.empty()) {
- renderer_cmd->AppendSwitchASCII(switches::kDisableFeatures,
- disabled_features);
- }
-}
-
} // namespace
RendererMainThreadFactoryFunction g_renderer_main_thread_factory = NULL;
@@ -526,6 +514,18 @@ void RenderProcessHost::SetMaxRendererProcessCount(size_t count) {
g_max_renderer_count_override = count;
}
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+// static
+void RenderProcessHostImpl::EarlyZygoteLaunch() {
+ DCHECK(!g_render_zygote);
+ // TODO(kerrnel): Investigate doing this without the ZygoteHostImpl as a
+ // proxy. It is currently done this way due to concerns about race
+ // conditions.
+ ZygoteHostImpl::GetInstance()->SetRendererSandboxStatus(
+ (*GetGenericZygote())->GetSandboxStatus());
+}
+#endif // defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+
RenderProcessHostImpl::RenderProcessHostImpl(
BrowserContext* browser_context,
StoragePartitionImpl* storage_partition_impl,
@@ -592,17 +592,13 @@ RenderProcessHostImpl::RenderProcessHostImpl(
// render process. This ensures that when a test is being run in one of the
// single process modes, the global attachment broker is the privileged
// attachment broker, rather than an unprivileged attachment broker.
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MACOSX)
IPC::AttachmentBrokerPrivileged::CreateBrokerIfNeeded(
MachBroker::GetInstance());
#else
IPC::AttachmentBrokerPrivileged::CreateBrokerIfNeeded();
-#endif // defined(OS_MACOSX) && !defined(OS_IOS)
+#endif // defined(OS_MACOSX)
#endif // USE_ATTACHMENT_BROKER
-
-#if defined(MOJO_SHELL_CLIENT)
- RegisterChildWithExternalShell(id_, this);
-#endif
}
// static
@@ -681,6 +677,8 @@ bool RenderProcessHostImpl::Init() {
if (channel_)
return true;
+ shell_pipe_token_ = MojoConnectToChild(id_, instance_id_++, this);
+
base::CommandLine::StringType renderer_prefix;
// A command prefix is something prepended to the command line of the spawned
// process.
@@ -709,10 +707,6 @@ bool RenderProcessHostImpl::Init() {
const std::string channel_id =
IPC::Channel::GenerateVerifiedChannelID(std::string());
channel_ = CreateChannelProxy(channel_id);
-#if USE_ATTACHMENT_BROKER
- IPC::AttachmentBroker::GetGlobal()->RegisterCommunicationChannel(
- channel_.get());
-#endif
// Setup the Mojo channel.
mojo_application_host_->Init();
@@ -735,7 +729,8 @@ bool RenderProcessHostImpl::Init() {
g_renderer_main_thread_factory(InProcessChildThreadParams(
channel_id,
BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO)
- ->task_runner())));
+ ->task_runner(),
+ in_process_renderer_handle_.release())));
base::Thread::Options options;
#if defined(OS_WIN) && !defined(OS_MACOSX)
@@ -792,11 +787,18 @@ scoped_ptr<IPC::ChannelProxy> RenderProcessHostImpl::CreateChannelProxy(
const std::string& channel_id) {
scoped_refptr<base::SingleThreadTaskRunner> runner =
BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO);
- scoped_refptr<base::SequencedTaskRunner> mojo_task_runner =
- BrowserThread::UnsafeGetMessageLoopForThread(BrowserThread::IO)
- ->task_runner();
if (ShouldUseMojoChannel()) {
VLOG(1) << "Mojo Channel is enabled on host";
+ mojo::ScopedMessagePipeHandle handle;
+
+ if (run_renderer_in_process()) {
+ mojo::MessagePipe pipe;
+ handle = std::move(pipe.handle0);
+ in_process_renderer_handle_ = std::move(pipe.handle1);
+ } else {
+ mojo_channel_token_ = mojo::edk::GenerateRandomToken();
+ handle = mojo::edk::CreateParentMessagePipe(mojo_channel_token_);
+ }
// Do NOT expand ifdef or run time condition checks here! Synchronous
// IPCs from browser process are banned. It is only narrowly allowed
@@ -806,14 +808,20 @@ scoped_ptr<IPC::ChannelProxy> RenderProcessHostImpl::CreateChannelProxy(
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kIPCSyncCompositing)) {
return IPC::SyncChannel::Create(
- IPC::ChannelMojo::CreateServerFactory(mojo_task_runner, channel_id),
- this, runner.get(), true, &never_signaled_);
+ IPC::ChannelMojo::CreateServerFactory(std::move(handle)), this,
+ runner.get(), true, &never_signaled_);
}
#endif // OS_ANDROID
- return IPC::ChannelProxy::Create(
- IPC::ChannelMojo::CreateServerFactory(mojo_task_runner, channel_id),
- this, runner.get());
+ std::unique_ptr<IPC::ChannelProxy> channel(
+ new IPC::ChannelProxy(this, runner.get()));
+#if USE_ATTACHMENT_BROKER
+ IPC::AttachmentBroker::GetGlobal()->RegisterCommunicationChannel(
+ channel.get(), content::BrowserThread::GetMessageLoopProxyForThread(
+ content::BrowserThread::IO));
+#endif
+ channel->Init(IPC::ChannelMojo::CreateServerFactory(std::move(handle)), true);
+ return channel;
}
// Do NOT expand ifdef or run time condition checks here! See comment above.
@@ -825,8 +833,15 @@ scoped_ptr<IPC::ChannelProxy> RenderProcessHostImpl::CreateChannelProxy(
}
#endif // OS_ANDROID
- return IPC::ChannelProxy::Create(channel_id, IPC::Channel::MODE_SERVER, this,
- runner.get());
+ std::unique_ptr<IPC::ChannelProxy> channel(
+ new IPC::ChannelProxy(this, runner.get()));
+#if USE_ATTACHMENT_BROKER
+ IPC::AttachmentBroker::GetGlobal()->RegisterCommunicationChannel(
+ channel.get(), content::BrowserThread::GetMessageLoopProxyForThread(
+ content::BrowserThread::IO));
+#endif
+ channel->Init(channel_id, IPC::Channel::MODE_SERVER, true);
+ return channel;
}
void RenderProcessHostImpl::CreateMessageFilters() {
@@ -843,10 +858,12 @@ void RenderProcessHostImpl::CreateMessageFilters() {
new BrowserPluginMessageFilter(GetID()));
AddFilter(bp_message_filter.get());
+ scoped_refptr<net::URLRequestContextGetter> request_context(
+ storage_partition_impl_->GetURLRequestContext());
scoped_refptr<RenderMessageFilter> render_message_filter(
new RenderMessageFilter(
GetID(), GetBrowserContext(),
- GetBrowserContext()->GetRequestContextForRenderProcess(GetID()),
+ request_context.get(),
widget_helper_.get(), audio_manager, media_internals,
storage_partition_impl_->GetDOMStorageContext()));
AddFilter(render_message_filter.get());
@@ -858,13 +875,11 @@ void RenderProcessHostImpl::CreateMessageFilters() {
nullptr,
#endif
GetBrowserContext(),
- GetBrowserContext()->GetRequestContextForRenderProcess(GetID()),
+ request_context.get(),
widget_helper_.get()));
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()));
@@ -872,10 +887,14 @@ void RenderProcessHostImpl::CreateMessageFilters() {
base::Bind(&GetContexts, browser_context->GetResourceContext(),
request_context, media_request_context));
+ // Several filters need the Blob storage context, so fetch it in advance.
+ scoped_refptr<ChromeBlobStorageContext> blob_storage_context =
+ ChromeBlobStorageContext::GetFor(browser_context);
+
ResourceMessageFilter* resource_message_filter = new ResourceMessageFilter(
GetID(), PROCESS_TYPE_RENDERER,
storage_partition_impl_->GetAppCacheService(),
- ChromeBlobStorageContext::GetFor(browser_context),
+ blob_storage_context.get(),
storage_partition_impl_->GetFileSystemContext(),
storage_partition_impl_->GetServiceWorkerContext(),
storage_partition_impl_->GetHostZoomLevelContext(),
@@ -907,10 +926,8 @@ void RenderProcessHostImpl::CreateMessageFilters() {
AddFilter(new IndexedDBDispatcherHost(
GetID(), storage_partition_impl_->GetURLRequestContext(),
storage_partition_impl_->GetIndexedDBContext(),
- ChromeBlobStorageContext::GetFor(browser_context)));
+ blob_storage_context.get()));
- gpu_message_filter_ = new GpuMessageFilter(GetID());
- AddFilter(gpu_message_filter_);
#if defined(ENABLE_WEBRTC)
AddFilter(new WebRTCIdentityServiceHost(
GetID(), storage_partition_impl_->GetWebRTCIdentityStore(),
@@ -930,8 +947,8 @@ void RenderProcessHostImpl::CreateMessageFilters() {
AddFilter(new FileAPIMessageFilter(
GetID(), storage_partition_impl_->GetURLRequestContext(),
storage_partition_impl_->GetFileSystemContext(),
- ChromeBlobStorageContext::GetFor(browser_context),
- StreamContext::GetFor(browser_context)));
+ blob_storage_context.get(), StreamContext::GetFor(browser_context)));
+ AddFilter(new BlobDispatcherHost(blob_storage_context.get()));
AddFilter(new FileUtilitiesMessageFilter(GetID()));
AddFilter(new MimeRegistryMessageFilter());
AddFilter(
@@ -959,8 +976,9 @@ void RenderProcessHostImpl::CreateMessageFilters() {
base::Bind(&GetRequestContext, request_context, media_request_context,
RESOURCE_TYPE_SUB_RESOURCE));
- AddFilter(
- new WebSocketDispatcherHost(GetID(), websocket_request_context_callback));
+ AddFilter(new WebSocketDispatcherHost(
+ GetID(), websocket_request_context_callback, blob_storage_context.get(),
+ storage_partition_impl_));
message_port_message_filter_ = new MessagePortMessageFilter(
base::Bind(&RenderWidgetHelper::GetNextRoutingID,
@@ -994,14 +1012,12 @@ void RenderProcessHostImpl::CreateMessageFilters() {
#if defined(ENABLE_WEBRTC)
p2p_socket_dispatcher_host_ = new P2PSocketDispatcherHost(
- resource_context,
- browser_context->GetRequestContextForRenderProcess(GetID()));
+ resource_context, request_context.get());
AddFilter(p2p_socket_dispatcher_host_.get());
#endif
AddFilter(new TraceMessageFilter(GetID()));
- AddFilter(new ResolveProxyMsgHelper(
- browser_context->GetRequestContextForRenderProcess(GetID())));
+ AddFilter(new ResolveProxyMsgHelper(request_context.get()));
AddFilter(new QuotaDispatcherHost(
GetID(), storage_partition_impl_->GetQuotaManager(),
GetContentClient()->browser()->CreateQuotaPermissionContext()));
@@ -1018,19 +1034,22 @@ void RenderProcessHostImpl::CreateMessageFilters() {
AddFilter(new DeviceOrientationAbsoluteMessageFilter());
AddFilter(new ProfilerMessageFilter(PROCESS_TYPE_RENDERER));
AddFilter(new HistogramMessageFilter());
-#if defined(USE_TCMALLOC) && (defined(OS_LINUX) || defined(OS_ANDROID))
- if (browser_command_line.HasSwitch(switches::kEnableMemoryBenchmarking))
- AddFilter(new MemoryBenchmarkMessageFilter());
-#endif
AddFilter(new MemoryMessageFilter(this));
AddFilter(new PushMessagingMessageFilter(
GetID(), storage_partition_impl_->GetServiceWorkerContext()));
-#if defined(OS_ANDROID) && !defined(USE_AURA)
+#if defined(OS_ANDROID)
AddFilter(new ScreenOrientationMessageFilterAndroid());
#endif
AddFilter(new GeofencingDispatcherHost(
storage_partition_impl_->GetGeofencingManager()));
- if (browser_command_line.HasSwitch(switches::kEnableWebBluetooth)) {
+
+ bool enable_web_bluetooth =
+ browser_command_line.HasSwitch(switches::kEnableWebBluetooth);
+#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
+ enable_web_bluetooth = true;
+#endif
+
+ if (enable_web_bluetooth) {
bluetooth_dispatcher_host_ = new BluetoothDispatcherHost(GetID());
AddFilter(bluetooth_dispatcher_host_.get());
}
@@ -1053,10 +1072,9 @@ void RenderProcessHostImpl::RegisterMojoServices() {
&BackgroundSyncContextImpl::CreateService,
base::Unretained(storage_partition_impl_->GetBackgroundSyncContext())));
- mojo_application_host_->service_registry()->AddService(base::Bind(
- &content::ServicePortServiceImpl::Create,
- make_scoped_refptr(storage_partition_impl_->GetNavigatorConnectContext()),
- message_port_message_filter_));
+ mojo_application_host_->service_registry()->AddService(
+ base::Bind(&RenderProcessHostImpl::CreateStoragePartitionService,
+ base::Unretained(this)));
#if defined(OS_ANDROID)
ServiceRegistrarAndroid::RegisterProcessHostServices(
@@ -1067,6 +1085,15 @@ void RenderProcessHostImpl::RegisterMojoServices() {
mojo_application_host_->service_registry());
}
+void RenderProcessHostImpl::CreateStoragePartitionService(
+ mojo::InterfaceRequest<mojom::StoragePartitionService> request) {
+ // DO NOT REMOVE THIS COMMAND LINE CHECK WITHOUT SECURITY REVIEW!
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kMojoLocalStorage)) {
+ storage_partition_impl_->Bind(std::move(request));
+ }
+}
+
int RenderProcessHostImpl::GetNextRoutingID() {
return widget_helper_->GetNextRoutingID();
}
@@ -1085,6 +1112,11 @@ ServiceRegistry* RenderProcessHostImpl::GetServiceRegistry() {
return mojo_application_host_->service_registry();
}
+scoped_ptr<base::SharedPersistentMemoryAllocator>
+RenderProcessHostImpl::TakeMetricsAllocator() {
+ return std::move(metrics_allocator_);
+}
+
const base::TimeTicks& RenderProcessHostImpl::GetInitTimeForNavigationMetrics()
const {
return init_time_;
@@ -1227,9 +1259,6 @@ StoragePartition* RenderProcessHostImpl::GetStoragePartition() const {
}
static void AppendCompositorCommandLineFlags(base::CommandLine* command_line) {
- if (IsPropertyTreeVerificationEnabled())
- command_line->AppendSwitch(cc::switches::kEnablePropertyTreeVerification);
-
command_line->AppendSwitchASCII(
switches::kNumRasterThreads,
base::IntToString(NumberOfRendererRasterThreads()));
@@ -1245,8 +1274,8 @@ static void AppendCompositorCommandLineFlags(base::CommandLine* command_line) {
if (IsZeroCopyUploadEnabled())
command_line->AppendSwitch(switches::kEnableZeroCopy);
- if (IsPartialRasterEnabled())
- command_line->AppendSwitch(switches::kEnablePartialRaster);
+ if (!IsPartialRasterEnabled())
+ command_line->AppendSwitch(switches::kDisablePartialRaster);
if (IsForceGpuRasterizationEnabled())
command_line->AppendSwitch(switches::kForceGpuRasterization);
@@ -1259,6 +1288,9 @@ static void AppendCompositorCommandLineFlags(base::CommandLine* command_line) {
// Persistent buffers may come at a performance hit (not all platform specific
// buffers support it), so only enable them if partial raster is enabled and
// we are actually going to use them.
+ // TODO(dcastagna): Once GPU_READ_CPU_READ_WRITE_PERSISTENT is removed
+ // kContentImageTextureTarget and kVideoImageTextureTarget can be merged into
+ // one flag.
gfx::BufferUsage buffer_usage =
IsPartialRasterEnabled()
? gfx::BufferUsage::GPU_READ_CPU_READ_WRITE_PERSISTENT
@@ -1274,10 +1306,15 @@ static void AppendCompositorCommandLineFlags(base::CommandLine* command_line) {
command_line->AppendSwitchASCII(switches::kContentImageTextureTarget,
UintVectorToString(image_targets));
- command_line->AppendSwitchASCII(
- switches::kVideoImageTextureTarget,
- base::UintToString(BrowserGpuMemoryBufferManager::GetImageTextureTarget(
- gfx::BufferFormat::R_8, gfx::BufferUsage::GPU_READ_CPU_READ_WRITE)));
+ for (size_t format = 0;
+ format < static_cast<size_t>(gfx::BufferFormat::LAST) + 1; format++) {
+ image_targets[format] =
+ BrowserGpuMemoryBufferManager::GetImageTextureTarget(
+ static_cast<gfx::BufferFormat>(format),
+ gfx::BufferUsage::GPU_READ_CPU_READ_WRITE);
+ }
+ command_line->AppendSwitchASCII(switches::kVideoImageTextureTarget,
+ UintVectorToString(image_targets));
// Appending disable-gpu-feature switches due to software rendering list.
GpuDataManagerImpl* gpu_data_manager = GpuDataManagerImpl::GetInstance();
@@ -1306,16 +1343,6 @@ void RenderProcessHostImpl::AppendRendererCommandLine(
GetContentClient()->browser()->GetApplicationLocale();
command_line->AppendSwitchASCII(switches::kLang, locale);
- // If we run base::FieldTrials, we want to pass to their state to the
- // renderer so that it can act in accordance with each state, or record
- // histograms relating to the base::FieldTrial states.
- std::string field_trial_states;
- base::FieldTrialList::AllStatesToString(&field_trial_states);
- if (!field_trial_states.empty()) {
- command_line->AppendSwitchASCII(switches::kForceFieldTrials,
- field_trial_states);
- }
-
GetContentClient()->browser()->AppendExtraCommandLineSwitches(command_line,
GetID());
@@ -1328,6 +1355,11 @@ void RenderProcessHostImpl::AppendRendererCommandLine(
#endif
AppendCompositorCommandLineFlags(command_line);
+
+ if (!mojo_channel_token_.empty()) {
+ command_line->AppendSwitchASCII(switches::kMojoChannelToken,
+ mojo_channel_token_);
+ }
}
void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
@@ -1337,27 +1369,27 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
// with any associated values) if present in the browser command line.
static const char* const kSwitchNames[] = {
switches::kAgcStartupMinVolume,
+ switches::kAecRefinedAdaptiveFilter,
switches::kAllowLoopbackInPeerConnection,
+ switches::kAndroidFontsPath,
switches::kAudioBufferSize,
switches::kBlinkPlatformLogChannels,
switches::kBlinkSettings,
switches::kDefaultTileWidth,
switches::kDefaultTileHeight,
+ switches::kDisable2dCanvasImageChromium,
switches::kDisable3DAPIs,
switches::kDisableAcceleratedJpegDecoding,
switches::kDisableAcceleratedVideoDecode,
switches::kDisableBlinkFeatures,
switches::kDisableBreakpad,
- switches::kDisableCompositorAnimationTimelines,
switches::kDisablePreferCompositingToLCDText,
switches::kDisableDatabases,
- switches::kDisableDelayAgnosticAec,
- switches::kDisableDirectNPAPIRequests,
switches::kDisableDisplayList2dCanvas,
switches::kDisableDistanceFieldText,
- switches::kDisableEncryptedMedia,
switches::kDisableFileSystem,
switches::kDisableGestureRequirementForMediaPlayback,
+ switches::kDisableGestureRequirementForPresentation,
switches::kDisableGpuCompositing,
switches::kDisableGpuMemoryBufferVideoFrames,
switches::kDisableGpuVsync,
@@ -1367,9 +1399,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDisableLCDText,
switches::kDisableLocalStorage,
switches::kDisableLogging,
- switches::kDisableMediaSource,
switches::kDisableMediaSuspend,
- switches::kDisableMojoChannel,
switches::kDisableNotifications,
switches::kDisableOverlayScrollbar,
switches::kDisablePermissionsAPI,
@@ -1386,10 +1416,11 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kDisableTouchAdjustment,
switches::kDisableTouchDragDrop,
switches::kDisableV8IdleTasks,
+ switches::kDisableWebGLImageChromium,
+ switches::kDisableWheelGestures,
switches::kDomAutomationController,
switches::kEnableBlinkFeatures,
switches::kEnableBrowserSideNavigation,
- switches::kEnableCredentialManagerAPI,
switches::kEnableDisplayList2dCanvas,
switches::kEnableDistanceFieldText,
switches::kEnableExperimentalCanvasFeatures,
@@ -1403,19 +1434,19 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kEnableLinkDisambiguationPopup,
switches::kEnableLowResTiling,
switches::kEnableMediaSuspend,
+ switches::kEnableMojoChannel,
switches::kEnableInbandTextTracks,
switches::kEnableLCDText,
switches::kEnableLogging,
switches::kEnableMemoryBenchmarking,
switches::kEnableNetworkInformation,
+ switches::kEnableNotificationActionIcons,
switches::kEnableOverlayScrollbar,
switches::kEnablePinch,
switches::kEnablePluginPlaceholderTesting,
switches::kEnablePreciseMemoryInfo,
switches::kEnablePreferCompositingToLCDText,
- switches::kEnablePrefixedEncryptedMedia,
switches::kEnableRGBA4444Textures,
- switches::kEnableRendererMojoChannel,
switches::kEnableSkiaBenchmarking,
switches::kEnableSlimmingPaintV2,
switches::kEnableSmoothScrolling,
@@ -1430,6 +1461,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kEnableWebGLDraftExtensions,
switches::kEnableWebGLImageChromium,
switches::kEnableWebVR,
+ switches::kEnableWheelGestures,
switches::kExplicitlyAllowedPorts,
switches::kForceDeviceScaleFactor,
switches::kForceDisplayList2dCanvas,
@@ -1443,6 +1475,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kMaxUntiledLayerWidth,
switches::kMaxUntiledLayerHeight,
switches::kMemoryMetrics,
+ switches::kMojoLocalStorage,
switches::kNoReferrers,
switches::kNoSandbox,
switches::kOverridePluginPowerSaverForTesting,
@@ -1457,6 +1490,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kSitePerProcess,
switches::kStatsCollectionController,
switches::kTestType,
+ switches::kTopDocumentIsolation,
switches::kTouchEvents,
switches::kTouchTextSelectionStrategy,
switches::kTraceConfigFile,
@@ -1467,8 +1501,6 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
// --in-process-webgl.
switches::kUseGL,
switches::kUseMobileUserAgent,
- switches::kUseNewMediaCache,
- switches::kUseNormalPriorityForTileTaskWorkerThreads,
switches::kUseRemoteCompositing,
switches::kV,
switches::kVideoThreads,
@@ -1478,24 +1510,23 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
// also be added to chrome/browser/chromeos/login/chrome_restart_request.cc.
cc::switches::kDisableCachedPictureRaster,
cc::switches::kDisableCompositedAntialiasing,
- cc::switches::kDisableCompositorPropertyTrees,
cc::switches::kDisableMainFrameBeforeActivation,
cc::switches::kDisableThreadedAnimation,
cc::switches::kEnableBeginFrameScheduling,
cc::switches::kEnableGpuBenchmarking,
cc::switches::kEnableMainFrameBeforeActivation,
+ cc::switches::kEnableTileCompression,
cc::switches::kShowCompositedLayerBorders,
+ cc::switches::kShowFPSCounter,
cc::switches::kShowLayerAnimationBounds,
cc::switches::kShowPropertyChangedRects,
cc::switches::kShowReplicaScreenSpaceRects,
cc::switches::kShowScreenSpaceRects,
cc::switches::kShowSurfaceDamageRects,
cc::switches::kSlowDownRasterScaleFactor,
- cc::switches::kStrictLayerPropertyChangeChecking,
cc::switches::kTopControlsHideThreshold,
cc::switches::kTopControlsShowThreshold,
- scheduler::switches::kEnableVirtualizedTime,
scheduler::switches::kDisableBackgroundTimerThrottling,
#if defined(ENABLE_PLUGINS)
@@ -1514,8 +1545,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
switches::kEnableLowEndDeviceMode,
switches::kDisableLowEndDeviceMode,
#if defined(OS_ANDROID)
- switches::kDisableWebAudio,
- switches::kEnableUnifiedMediaPipeline,
+ switches::kDisableUnifiedMediaPipeline,
switches::kIPCSyncCompositing,
switches::kRendererWaitForJavaDebugger,
#endif
@@ -1526,6 +1556,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
#if defined(OS_WIN)
switches::kDisableDirectWrite,
switches::kDisableWin32kRendererLockDown,
+ switches::kTrySupportedChannelLayouts,
switches::kTraceExportEventsToETW,
#endif
#if defined(USE_OZONE)
@@ -1534,12 +1565,11 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
#if defined(OS_CHROMEOS)
switches::kDisableVaapiAcceleratedVideoEncode,
#endif
- "use-new-edk", // TODO(use_chrome_edk): temporary.
};
renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames,
arraysize(kSwitchNames));
- CopyEnableDisableFeatureFlagsToRenderer(renderer_cmd);
+ BrowserChildProcessHostImpl::CopyFeatureAndFieldTrialFlags(renderer_cmd);
if (browser_cmd.HasSwitch(switches::kTraceStartup) &&
BrowserMainLoop::GetInstance()->is_tracing_startup_for_duration()) {
@@ -1578,9 +1608,19 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
}
}
-#if defined(MOJO_SHELL_CLIENT)
- if (IsRunningInMojoShell())
- renderer_cmd->AppendSwitch(switches::kEnableMojoShellConnection);
+ if (!shell_pipe_token_.empty()) {
+ renderer_cmd->AppendSwitchASCII(switches::kPrimordialPipeToken,
+ shell_pipe_token_);
+ }
+
+#if defined(OS_WIN) && !defined(OFFICIAL_BUILD)
+ // Needed because we can't show the dialog from the sandbox. Don't pass
+ // --no-sandbox in official builds because that would bypass the bad_flgs
+ // prompt.
+ if (renderer_cmd->HasSwitch(switches::kRendererStartupDialog) &&
+ !renderer_cmd->HasSwitch(switches::kNoSandbox)) {
+ renderer_cmd->AppendSwitch(switches::kNoSandbox);
+ }
#endif
}
@@ -1651,9 +1691,18 @@ bool RenderProcessHostImpl::FastShutdownIfPossible() {
bool RenderProcessHostImpl::Send(IPC::Message* msg) {
TRACE_EVENT0("renderer_host", "RenderProcessHostImpl::Send");
+#if !defined(OS_ANDROID)
+ DCHECK(!msg->is_sync());
+#endif
+
if (!channel_) {
+#if defined(OS_ANDROID)
+ if (msg->is_sync()) {
+ delete msg;
+ return false;
+ }
+#endif
if (!is_initialized_) {
- DCHECK(!msg->is_sync());
queued_messages_.push(msg);
return true;
} else {
@@ -1663,6 +1712,12 @@ bool RenderProcessHostImpl::Send(IPC::Message* msg) {
}
if (child_process_launcher_.get() && child_process_launcher_->IsStarting()) {
+#if defined(OS_ANDROID)
+ if (msg->is_sync()) {
+ delete msg;
+ return false;
+ }
+#endif
queued_messages_.push(msg);
return true;
}
@@ -1741,12 +1796,6 @@ void RenderProcessHostImpl::OnChannelConnected(int32_t peer_pid) {
tracked_objects::ThreadData::status();
Send(new ChildProcessMsg_SetProfilerStatus(status));
-#if defined(USE_OZONE)
- Send(new ChildProcessMsg_InitializeClientNativePixmapFactory(
- base::FileDescriptor(
- ui::OzonePlatform::GetInstance()->OpenClientNativePixmapDevice())));
-#endif
-
// Inform AudioInputRendererHost about the new render process PID.
// AudioInputRendererHost is reference counted, so its lifetime is
// guaranteed during the lifetime of the closure.
@@ -1820,10 +1869,8 @@ void RenderProcessHostImpl::Cleanup() {
}
#if defined(ENABLE_WEBRTC)
- if (is_initialized_) {
- BrowserMainLoop::GetInstance()->media_stream_manager()->
- UnregisterNativeLogCallback(GetID());
- }
+ if (is_initialized_)
+ ClearWebRtcLogMessageCallback();
#endif
// When there are no other owners of this object, we can delete ourselves.
@@ -1882,7 +1929,6 @@ void RenderProcessHostImpl::Cleanup() {
channel_.reset();
// The following members should be cleared in ProcessDied() as well!
- gpu_message_filter_ = NULL;
message_port_message_filter_ = NULL;
RemoveUserData(kSessionStorageHolderKey);
@@ -1922,10 +1968,6 @@ base::TimeDelta RenderProcessHostImpl::GetChildProcessIdleTime() const {
return base::TimeTicks::Now() - child_process_activity_time_;
}
-void RenderProcessHostImpl::ResumeRequestsForView(int route_id) {
- widget_helper_->ResumeRequestsForView(route_id);
-}
-
void RenderProcessHostImpl::FilterURL(bool empty_allowed, GURL* url) {
FilterURL(this, empty_allowed, url);
}
@@ -1960,7 +2002,7 @@ void RenderProcessHostImpl::DisableAudioDebugRecordings() {
// for avoiding races between enable and disable. Nothing is done on the FILE
// thread.
BrowserThread::PostTaskAndReply(
- BrowserThread::FILE, FROM_HERE, base::Bind(&DisableAecDumpOnFileThread),
+ BrowserThread::FILE, FROM_HERE, base::Bind(&base::DoNothing),
base::Bind(&RenderProcessHostImpl::SendDisableAecDumpToRenderer,
weak_factory_.GetWeakPtr()));
@@ -1992,7 +2034,7 @@ void RenderProcessHostImpl::DisableEventLogRecordings() {
// for avoiding races between enable and disable. Nothing is done on the FILE
// thread.
BrowserThread::PostTaskAndReply(
- BrowserThread::FILE, FROM_HERE, base::Bind(&DisableAecDumpOnFileThread),
+ BrowserThread::FILE, FROM_HERE, base::Bind(&base::DoNothing),
base::Bind(&RenderProcessHostImpl::SendDisableEventLogToRenderer,
weak_factory_.GetWeakPtr()));
}
@@ -2005,6 +2047,14 @@ void RenderProcessHostImpl::SetWebRtcLogMessageCallback(
#endif
}
+void RenderProcessHostImpl::ClearWebRtcLogMessageCallback() {
+#if defined(ENABLE_WEBRTC)
+ BrowserMainLoop::GetInstance()
+ ->media_stream_manager()
+ ->UnregisterNativeLogCallback(GetID());
+#endif
+}
+
RenderProcessHostImpl::WebRtcStopRtpDumpCallback
RenderProcessHostImpl::StartRtpDump(
bool incoming,
@@ -2076,11 +2126,6 @@ void RenderProcessHostImpl::FilterURL(RenderProcessHost* rph,
if (empty_allowed && url->is_empty())
return;
- // The browser process should never hear the swappedout:// URL from any
- // of the renderer's messages. Check for this in debug builds, but don't
- // let it crash a release browser.
- DCHECK(GURL(kSwappedOutURL) != *url);
-
if (!url->is_valid()) {
// Have to use about:blank for the denied case, instead of an empty GURL.
// This is because the browser treats navigation to an empty GURL as a
@@ -2309,6 +2354,31 @@ void RenderProcessHostImpl::RegisterProcessHostForSite(
map->RegisterProcess(site, process);
}
+void RenderProcessHostImpl::CreateSharedRendererHistogramAllocator() {
+ DCHECK(!metrics_allocator_);
+
+ // Create a persistent memory segment for renderer histograms only if
+ // they're active in the browser.
+ if (!base::GlobalHistogramAllocator::Get())
+ return;
+
+ // Get handle to the renderer process. Stop if there is none.
+ base::ProcessHandle destination = GetHandle();
+ if (destination == base::kNullProcessHandle)
+ return;
+
+ // TODO(bcwhite): Update this with the correct memory size.
+ scoped_ptr<base::SharedMemory> shm(new base::SharedMemory());
+ shm->CreateAndMapAnonymous(2 << 20); // 2 MiB
+ metrics_allocator_.reset(new base::SharedPersistentMemoryAllocator(
+ std::move(shm), GetID(), "RendererMetrics", /*readonly=*/false));
+
+ base::SharedMemoryHandle shm_handle;
+ metrics_allocator_->shared_memory()->ShareToProcess(destination, &shm_handle);
+ Send(new ChildProcessMsg_SetHistogramMemory(
+ shm_handle, metrics_allocator_->shared_memory()->mapped_size()));
+}
+
void RenderProcessHostImpl::ProcessDied(bool already_dead,
RendererClosedDetails* known_details) {
// Our child process has died. If we didn't expect it, it's a crash.
@@ -2346,7 +2416,6 @@ void RenderProcessHostImpl::ProcessDied(bool already_dead,
}
RendererClosedDetails details(status, exit_code);
- mojo_application_host_->WillDestroySoon();
child_process_launcher_.reset();
#if USE_ATTACHMENT_BROKER
@@ -2374,7 +2443,6 @@ void RenderProcessHostImpl::ProcessDied(bool already_dead,
RenderProcessExited(this, status, exit_code));
within_process_died_observer_ = false;
- gpu_message_filter_ = NULL;
message_port_message_filter_ = NULL;
RemoveUserData(kSessionStorageHolderKey);
@@ -2434,8 +2502,6 @@ void RenderProcessHostImpl::OnShutdownRequest() {
FOR_EACH_OBSERVER(RenderProcessHostObserver, observers_,
RenderProcessWillExit(this));
- mojo_application_host_->WillDestroySoon();
-
Send(new ChildProcessMsg_Shutdown());
}
@@ -2507,17 +2573,17 @@ void RenderProcessHostImpl::OnProcessLaunched() {
is_process_backgrounded_ =
child_process_launcher_->GetProcess().IsProcessBackgrounded();
-#if defined(OS_WIN)
- // Experiment with not setting the initial priority of a renderer, as this
- // might be a visible tab but since no widgets are currently present, it
- // will get backgrounded. See https://crbug.com/560446.
- if (base::FeatureList::IsEnabled(
- features::kUpdateRendererPriorityOnStartup)) {
- UpdateProcessPriority();
- }
-#else
+ // Disable updating process priority on startup for now as it incorrectly
+ // results in backgrounding foreground navigations until their first commit
+ // is made. A better long term solution would be to be aware of the tab's
+ // visibility at this point. https://crbug.com/560446.
+ // Except on Android for now because of https://crbug.com/601184 :-(.
+#if defined(OS_ANDROID)
UpdateProcessPriority();
#endif
+
+ // Share histograms between the renderer and this process.
+ CreateSharedRendererHistogramAllocator();
}
// NOTE: This needs to be before sending queued messages because
@@ -2531,35 +2597,6 @@ void RenderProcessHostImpl::OnProcessLaunched() {
Source<RenderProcessHost>(this),
NotificationService::NoDetails());
- if (base::CommandLine::ForCurrentProcess()->HasSwitch("use-new-edk") &&
- child_process_launcher_.get()) {
- base::ProcessHandle process_handle =
- child_process_launcher_->GetProcess().Handle();
- mojo::embedder::ScopedPlatformHandle client_pipe;
-#if defined(MOJO_SHELL_CLIENT)
- if (IsRunningInMojoShell()) {
- client_pipe = RegisterProcessWithBroker(
- child_process_launcher_->GetProcess().Pid());
- } else
-#endif
- {
- client_pipe = mojo::embedder::ChildProcessLaunched(process_handle);
- }
- Send(new ChildProcessMsg_SetMojoParentPipeHandle(
- IPC::GetFileHandleForProcess(
-#if defined(OS_WIN)
- client_pipe.release().handle,
-#else
- client_pipe.release().fd,
-#endif
- process_handle, true)));
- }
-
-#if defined(MOJO_SHELL_CLIENT)
- // Send the mojo shell handle to the renderer.
- SendExternalMojoShellHandleToChild(GetHandle(), this);
-#endif
-
// Allow Mojo to be setup before the renderer sees any Chrome IPC messages.
// This way, Mojo can be safely used from the renderer in response to any
// Chrome IPC message.
@@ -2618,20 +2655,7 @@ void RenderProcessHostImpl::OnCloseACK(int old_route_id) {
}
void RenderProcessHostImpl::OnGpuSwitched() {
- // We are updating all widgets including swapped out ones.
- scoped_ptr<RenderWidgetHostIterator> widgets(
- RenderWidgetHostImpl::GetAllRenderWidgetHosts());
- while (RenderWidgetHost* widget = widgets->GetNextHost()) {
- RenderViewHost* rvh = RenderViewHost::From(widget);
- if (!rvh)
- continue;
-
- // Skip widgets in other processes.
- if (rvh->GetProcess()->GetID() != GetID())
- continue;
-
- rvh->OnWebkitPreferencesChanged();
- }
+ RecomputeAndUpdateWebKitPreferences();
}
#if defined(ENABLE_WEBRTC)
@@ -2712,8 +2736,7 @@ void RenderProcessHostImpl::EnableAecDumpForId(const base::FilePath& file,
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::FILE, FROM_HERE,
- base::Bind(&CreateFileForProcess, file.AddExtension(IntToStringType(id)),
- GetHandle()),
+ base::Bind(&CreateFileForProcess, file.AddExtension(IntToStringType(id))),
base::Bind(&RenderProcessHostImpl::SendAecDumpFileToRenderer,
weak_factory_.GetWeakPtr(), id));
}
@@ -2723,8 +2746,7 @@ void RenderProcessHostImpl::EnableEventLogForId(const base::FilePath& file,
DCHECK_CURRENTLY_ON(BrowserThread::UI);
BrowserThread::PostTaskAndReplyWithResult(
BrowserThread::FILE, FROM_HERE,
- base::Bind(&CreateFileForProcess, file.AddExtension(IntToStringType(id)),
- GetHandle()),
+ base::Bind(&CreateFileForProcess, file.AddExtension(IntToStringType(id))),
base::Bind(&RenderProcessHostImpl::SendEventLogFileToRenderer,
weak_factory_.GetWeakPtr(), id));
}
@@ -2775,4 +2797,21 @@ BluetoothDispatcherHost* RenderProcessHostImpl::GetBluetoothDispatcherHost() {
return bluetooth_dispatcher_host_.get();
}
+void RenderProcessHostImpl::RecomputeAndUpdateWebKitPreferences() {
+ // We are updating all widgets including swapped out ones.
+ scoped_ptr<RenderWidgetHostIterator> widgets(
+ RenderWidgetHostImpl::GetAllRenderWidgetHosts());
+ while (RenderWidgetHost* widget = widgets->GetNextHost()) {
+ RenderViewHost* rvh = RenderViewHost::From(widget);
+ if (!rvh)
+ continue;
+
+ // Skip widgets in other processes.
+ if (rvh->GetProcess()->GetID() != GetID())
+ continue;
+
+ rvh->OnWebkitPreferencesChanged();
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_process_host_impl.h b/chromium/content/browser/renderer_host/render_process_host_impl.h
index 79154957c35..6d83d4b0515 100644
--- a/chromium/content/browser/renderer_host/render_process_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_process_host_impl.h
@@ -13,6 +13,7 @@
#include <string>
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
#include "base/process/process.h"
@@ -53,7 +54,6 @@ class AudioRendererHost;
class BluetoothDispatcherHost;
class BrowserCdmManager;
class BrowserDemuxerAndroid;
-class GpuMessageFilter;
class InProcessChildThreadParams;
class MessagePortMessageFilter;
class MojoApplicationHost;
@@ -71,6 +71,10 @@ class RenderWidgetHostViewFrameSubscriber;
class StoragePartition;
class StoragePartitionImpl;
+namespace mojom {
+class StoragePartitionService;
+}
+
typedef base::Thread* (*RendererMainThreadFactoryFunction)(
const InProcessChildThreadParams& params);
@@ -138,7 +142,6 @@ class CONTENT_EXPORT RenderProcessHostImpl
bool FastShutdownForPageCount(size_t count) override;
bool FastShutdownStarted() const override;
base::TimeDelta GetChildProcessIdleTime() const override;
- void ResumeRequestsForView(int route_id) override;
void FilterURL(bool empty_allowed, GURL* url) override;
#if defined(ENABLE_WEBRTC)
void EnableAudioDebugRecordings(const base::FilePath& file) override;
@@ -147,6 +150,7 @@ class CONTENT_EXPORT RenderProcessHostImpl
void DisableEventLogRecordings() override;
void SetWebRtcLogMessageCallback(
base::Callback<void(const std::string&)> callback) override;
+ void ClearWebRtcLogMessageCallback() override;
WebRtcStopRtpDumpCallback StartRtpDump(
bool incoming,
bool outgoing,
@@ -155,6 +159,8 @@ class CONTENT_EXPORT RenderProcessHostImpl
void ResumeDeferredNavigation(const GlobalRequestID& request_id) override;
void NotifyTimezoneChange(const std::string& timezone) override;
ServiceRegistry* GetServiceRegistry() override;
+ scoped_ptr<base::SharedPersistentMemoryAllocator> TakeMetricsAllocator()
+ override;
const base::TimeTicks& GetInitTimeForNavigationMetrics() const override;
bool SubscribeUniformEnabled() const override;
void OnAddSubscription(unsigned int target) override;
@@ -263,6 +269,13 @@ class CONTENT_EXPORT RenderProcessHostImpl
BluetoothDispatcherHost* GetBluetoothDispatcherHost();
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+ // Launch the zygote early in the browser startup.
+ static void EarlyZygoteLaunch();
+#endif // defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+
+ void RecomputeAndUpdateWebKitPreferences();
+
protected:
// A proxy for our IPC::Channel that lives on the IO thread.
scoped_ptr<IPC::ChannelProxy> channel_;
@@ -296,6 +309,9 @@ class CONTENT_EXPORT RenderProcessHostImpl
// Registers Mojo services to be exposed to the renderer.
void RegisterMojoServices();
+ void CreateStoragePartitionService(
+ mojo::InterfaceRequest<mojom::StoragePartitionService> request);
+
// Control message handlers.
void OnShutdownRequest();
void SuddenTerminationChanged(bool enabled);
@@ -318,6 +334,12 @@ class CONTENT_EXPORT RenderProcessHostImpl
// change.
void UpdateProcessPriority();
+ // Creates a PersistentMemoryAllocator and shares it with the renderer
+ // process for it to store histograms from that process. The allocator is
+ // available for extraction by a SubprocesMetricsProvider in order to
+ // report those histograms to UMA.
+ void CreateSharedRendererHistogramAllocator();
+
// Handle termination of our process.
void ProcessDied(bool already_dead, RendererClosedDetails* known_details);
@@ -346,6 +368,10 @@ class CONTENT_EXPORT RenderProcessHostImpl
base::FilePath GetEventLogFilePathWithExtensions(const base::FilePath& file);
#endif
+ // The token to be passed to the child process and exchanged for a message
+ // pipe to the shell.
+ std::string shell_pipe_token_;
+
scoped_ptr<MojoApplicationHost> mojo_application_host_;
// The registered IPC listener objects. When this list is empty, we should
@@ -365,14 +391,6 @@ class CONTENT_EXPORT RenderProcessHostImpl
// IO thread.
scoped_refptr<RenderWidgetHelper> widget_helper_;
- // The filter for GPU-related messages coming from the renderer.
- // Thread safety note: this field is to be accessed from the UI thread.
- // We don't keep a reference to it, to avoid it being destroyed on the UI
- // thread, but we clear this field when we clear channel_. When channel_ goes
- // away, it posts a task to the IO thread to destroy it there, so we know that
- // it's valid if non-NULL.
- GpuMessageFilter* gpu_message_filter_;
-
// The filter for MessagePort messages coming from the renderer.
scoped_refptr<MessagePortMessageFilter> message_port_message_filter_;
@@ -403,6 +421,11 @@ class CONTENT_EXPORT RenderProcessHostImpl
// The globally-unique identifier for this RPH.
const int id_;
+ // A secondary ID used by the Mojo shell to distinguish different incarnations
+ // of the same RPH from each other. Unlike |id_| this is not globally unique,
+ // but it is guaranteed to change every time Init() is called.
+ int instance_id_ = 1;
+
BrowserContext* browser_context_;
// Owned by |browser_context_|.
@@ -477,7 +500,8 @@ class CONTENT_EXPORT RenderProcessHostImpl
// for UMA.
int max_worker_count_;
- // Context shared for each PermissionService instance created for this RPH.
+ // Context shared for each mojom::PermissionService instance created for this
+ // RPH.
scoped_ptr<PermissionServiceContext> permission_service_context_;
// This is a set of all subscription targets valuebuffers in the GPU process
@@ -494,6 +518,9 @@ class CONTENT_EXPORT RenderProcessHostImpl
// Whether or not the CHROMIUM_subscribe_uniform WebGL extension is enabled
bool subscribe_uniform_enabled_;
+ // The memory allocator, if any, in which the renderer will write its metrics.
+ scoped_ptr<base::SharedPersistentMemoryAllocator> metrics_allocator_;
+
bool channel_connected_;
bool sent_render_process_ready_;
@@ -506,6 +533,9 @@ class CONTENT_EXPORT RenderProcessHostImpl
base::WaitableEvent never_signaled_;
#endif
+ std::string mojo_channel_token_;
+ mojo::ScopedMessagePipeHandle in_process_renderer_handle_;
+
base::WeakPtrFactory<RenderProcessHostImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderProcessHostImpl);
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 13b2c082480..bcd1c9ab1bd 100644
--- a/chromium/content/browser/renderer_host/render_view_host_factory.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_factory.cc
@@ -15,6 +15,9 @@ namespace content {
RenderViewHostFactory* RenderViewHostFactory::factory_ = nullptr;
// static
+bool RenderViewHostFactory::is_real_render_view_host_ = false;
+
+// static
RenderViewHost* RenderViewHostFactory::Create(
SiteInstance* instance,
RenderViewHostDelegate* delegate,
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 62b23900d6a..a6f7dd5e6ce 100644
--- a/chromium/content/browser/renderer_host/render_view_host_factory.h
+++ b/chromium/content/browser/renderer_host/render_view_host_factory.h
@@ -39,6 +39,18 @@ class RenderViewHostFactory {
return !!factory_;
}
+ // Returns true if the RenderViewHost instance is not a test instance.
+ CONTENT_EXPORT static bool is_real_render_view_host() {
+ return is_real_render_view_host_;
+ }
+
+ // Sets the is_real_render_view_host flag which indicates that the
+ // RenderViewHost instance is not a test instance.
+ CONTENT_EXPORT static void set_is_real_render_view_host(
+ bool is_real_render_view_host) {
+ is_real_render_view_host_ = is_real_render_view_host;
+ }
+
protected:
RenderViewHostFactory() {}
virtual ~RenderViewHostFactory() {}
@@ -67,6 +79,10 @@ class RenderViewHostFactory {
// create the default RenderViewHosts.
CONTENT_EXPORT static RenderViewHostFactory* factory_;
+ // Set to true if the RenderViewHost is not a test instance. Defaults to
+ // false.
+ CONTENT_EXPORT static bool is_real_render_view_host_;
+
DISALLOW_COPY_AND_ASSIGN(RenderViewHostFactory);
};
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 f8175ab639c..f4891f2d404 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.cc
@@ -11,6 +11,7 @@
#include "base/callback.h"
#include "base/command_line.h"
+#include "base/debug/dump_without_crashing.h"
#include "base/i18n/rtl.h"
#include "base/json/json_reader.h"
#include "base/message_loop/message_loop.h"
@@ -35,10 +36,10 @@
#include "content/browser/host_zoom_map_impl.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
#include "content/browser/renderer_host/dip_util.h"
-#include "content/browser/renderer_host/media/audio_renderer_host.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_delegate_view.h"
+#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/common/browser_plugin/browser_plugin_messages.h"
#include "content/common/content_switches_internal.h"
@@ -46,6 +47,7 @@
#include "content/common/frame_messages.h"
#include "content/common/input_messages.h"
#include "content/common/inter_process_time_ticks_converter.h"
+#include "content/common/site_isolation_policy.h"
#include "content/common/speech_recognition_messages.h"
#include "content/common/swapped_out_messages.h"
#include "content/common/view_messages.h"
@@ -74,7 +76,7 @@
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "net/base/filename_util.h"
-#include "net/base/net_util.h"
+#include "net/base/url_util.h"
#include "net/url_request/url_request_context_getter.h"
#include "storage/browser/fileapi/isolated_context.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -220,7 +222,6 @@ RenderViewHostImpl::RenderViewHostImpl(SiteInstance* instance,
enabled_bindings_(0),
page_id_(-1),
is_active_(!swapped_out),
- is_pending_deletion_(false),
is_swapped_out_(swapped_out),
main_frame_routing_id_(main_frame_routing_id),
is_waiting_for_close_ack_(false),
@@ -240,21 +241,11 @@ RenderViewHostImpl::RenderViewHostImpl(SiteInstance* instance,
GetProcess()->EnableSendQueue();
if (ResourceDispatcherHostImpl::Get()) {
- bool has_active_audio = false;
- if (has_initialized_audio_host) {
- scoped_refptr<AudioRendererHost> arh =
- static_cast<RenderProcessHostImpl*>(GetProcess())
- ->audio_renderer_host();
- if (arh.get())
- has_active_audio =
- arh->RenderFrameHasActiveAudio(main_frame_routing_id_);
- }
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&ResourceDispatcherHostImpl::OnRenderViewHostCreated,
base::Unretained(ResourceDispatcherHostImpl::Get()),
- GetProcess()->GetID(), GetRoutingID(),
- !GetWidget()->is_hidden(), has_active_audio));
+ GetProcess()->GetID(), GetRoutingID()));
}
}
@@ -300,6 +291,14 @@ bool RenderViewHostImpl::CreateRenderView(
CHECK(main_frame_routing_id_ != MSG_ROUTING_NONE ||
proxy_route_id != MSG_ROUTING_NONE);
+ // We should not set both main_frame_routing_id_ and proxy_route_id. Log
+ // cases that this happens (without crashing) to track down
+ // https://crbug.com/574245.
+ // TODO(creis): Remove this once we've found the cause.
+ if (main_frame_routing_id_ != MSG_ROUTING_NONE &&
+ proxy_route_id != MSG_ROUTING_NONE)
+ base::debug::DumpWithoutCrashing();
+
GetWidget()->set_renderer_initialized(true);
// Ensure the RenderView starts with a next_page_id larger than any existing
@@ -365,7 +364,7 @@ bool RenderViewHostImpl::CreateRenderView(
RenderFrameHostImpl::FromID(GetProcess()->GetID(), main_frame_routing_id_)
->SetRenderFrameCreated(true);
}
- GetWidget()->SendScreenRects();
+ GetWidget()->delegate()->SendScreenRects();
PostRenderViewReady();
return true;
@@ -403,11 +402,6 @@ WebPreferences RenderViewHostImpl::ComputeWebkitPrefs() {
!command_line.HasSwitch(switches::kDisableLocalStorage);
prefs.databases_enabled =
!command_line.HasSwitch(switches::kDisableDatabases);
-#if defined(OS_ANDROID)
- // WebAudio is enabled by default on x86 and ARM.
- prefs.webaudio_enabled =
- !command_line.HasSwitch(switches::kDisableWebAudio);
-#endif
prefs.experimental_webgl_enabled =
GpuProcessHost::gpu_enabled() &&
@@ -482,8 +476,9 @@ WebPreferences RenderViewHostImpl::ComputeWebkitPrefs() {
!command_line.HasSwitch(switches::kDisableTouchAdjustment);
prefs.enable_scroll_animator =
- !command_line.HasSwitch(switches::kDisableSmoothScrolling) &&
- gfx::Animation::ShouldRenderRichAnimation();
+ command_line.HasSwitch(switches::kEnableSmoothScrolling) ||
+ (!command_line.HasSwitch(switches::kDisableSmoothScrolling) &&
+ gfx::Animation::ScrollAnimationsEnabledBySystem());
// Certain GPU features might have been blacklisted.
GpuDataManagerImpl::GetInstance()->UpdateRendererWebPrefs(&prefs);
@@ -530,14 +525,13 @@ WebPreferences RenderViewHostImpl::ComputeWebkitPrefs() {
prefs.v8_cache_options = GetV8CacheOptions();
+ prefs.user_gesture_required_for_presentation = !command_line.HasSwitch(
+ switches::kDisableGestureRequirementForPresentation);
+
GetContentClient()->browser()->OverrideWebkitPrefs(this, &prefs);
return prefs;
}
-void RenderViewHostImpl::SuppressDialogsUntilSwapOut() {
- Send(new ViewMsg_SuppressDialogsUntilSwapOut(GetRoutingID()));
-}
-
void RenderViewHostImpl::ClosePage() {
is_waiting_for_close_ack_ = true;
GetWidget()->StartHangMonitorTimeout(
@@ -572,19 +566,6 @@ void RenderViewHostImpl::ClosePageIgnoringUnloadEvents() {
delegate_->Close(this);
}
-#if defined(OS_ANDROID)
-void RenderViewHostImpl::ActivateNearestFindResult(int request_id,
- float x,
- float y) {
- Send(new InputMsg_ActivateNearestFindResult(GetRoutingID(),
- request_id, x, y));
-}
-
-void RenderViewHostImpl::RequestFindMatchRects(int current_version) {
- Send(new ViewMsg_FindMatchRects(GetRoutingID(), current_version));
-}
-#endif
-
void RenderViewHostImpl::RenderProcessReady(RenderProcessHost* host) {
if (render_view_ready_on_process_launch_) {
render_view_ready_on_process_launch_ = false;
@@ -886,9 +867,6 @@ bool RenderViewHostImpl::SuddenTerminationAllowed() const {
// RenderViewHostImpl, IPC message handlers:
bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
- if (!BrowserMessageFilter::CheckCanDispatchOnUI(msg, GetWidget()))
- return true;
-
// Filter out most IPC messages if this renderer is swapped out.
// We still want to handle certain ACKs to keep our state consistent.
if (is_swapped_out_) {
@@ -959,26 +937,6 @@ void RenderViewHostImpl::ShutdownAndDestroy() {
delete this;
}
-void RenderViewHostImpl::RenderWidgetWillBeHidden() {
- if (ResourceDispatcherHostImpl::Get()) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&ResourceDispatcherHostImpl::OnRenderViewHostWasHidden,
- base::Unretained(ResourceDispatcherHostImpl::Get()),
- GetProcess()->GetID(), GetRoutingID()));
- }
-}
-
-void RenderViewHostImpl::RenderWidgetWillBeShown() {
- if (ResourceDispatcherHostImpl::Get()) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&ResourceDispatcherHostImpl::OnRenderViewHostWasShown,
- base::Unretained(ResourceDispatcherHostImpl::Get()),
- GetProcess()->GetID(), GetRoutingID()));
- }
-}
-
void RenderViewHostImpl::CreateNewWindow(
int32_t route_id,
int32_t main_frame_route_id,
@@ -1015,8 +973,7 @@ void RenderViewHostImpl::OnShowView(int route_id,
void RenderViewHostImpl::OnShowWidget(int route_id,
const gfx::Rect& initial_rect) {
- if (is_active_)
- delegate_->ShowCreatedWidget(route_id, initial_rect);
+ delegate_->ShowCreatedWidget(route_id, initial_rect);
Send(new ViewMsg_Move_ACK(route_id));
}
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 9d9455dfab7..4ec87ca0711 100644
--- a/chromium/content/browser/renderer_host/render_view_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_view_host_impl.h
@@ -150,11 +150,6 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
void OnWebkitPreferencesChanged() override;
void SelectWordAroundCaret() override;
-#if defined(OS_ANDROID)
- void ActivateNearestFindResult(int request_id, float x, float y) override;
- void RequestFindMatchRects(int current_version) override;
-#endif
-
// RenderProcessHostObserver implementation
void RenderProcessReady(RenderProcessHost* host) override;
void RenderProcessExited(RenderProcessHost* host,
@@ -193,16 +188,6 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
bool is_active() const { return is_active_; }
void set_is_active(bool is_active) { is_active_ = is_active; }
- // Tracks whether this RenderViewHost is pending deletion. This is tracked
- // separately from the main frame pending deletion state, because the
- // RenderViewHost's main frame is cleared when the main frame's
- // RenderFrameHost is marked for deletion.
- //
- // TODO(nasko,alexmos): This should not be necessary once swapped-out is
- // removed.
- bool is_pending_deletion() const { return is_pending_deletion_; }
- void set_pending_deletion() { is_pending_deletion_ = true; }
-
// Tracks whether this RenderViewHost is swapped out, according to its main
// frame RenderFrameHost.
void set_is_swapped_out(bool is_swapped_out) {
@@ -212,12 +197,6 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
// TODO(creis): Remove as part of http://crbug.com/418265.
bool is_waiting_for_close_ack() const { return is_waiting_for_close_ack_; }
- // Tells the renderer that this RenderView will soon be swapped out, and thus
- // not to create any new modal dialogs until it happens. This must be done
- // separately so that the PageGroupLoadDeferrers of any current dialogs are no
- // longer on the stack when we attempt to swap it out.
- void SuppressDialogsUntilSwapOut();
-
// Tells the renderer process to run the page's unload handler.
// A ClosePage_ACK ack is sent back when the handler execution completes.
void ClosePage();
@@ -255,6 +234,11 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
// Creates a full screen RenderWidget.
void CreateNewFullscreenWidget(int32_t route_id);
+ // TODO(creis): Remove after debugging https:/crbug.com/575245.
+ int main_frame_routing_id() const {
+ return main_frame_routing_id_;
+ }
+
void set_main_frame_routing_id(int routing_id) {
main_frame_routing_id_ = routing_id;
}
@@ -264,15 +248,15 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
size_t end_offset);
// Increases the refcounting on this RVH. This is done by the FrameTree on
- // creation of a RenderFrameHost.
+ // creation of a RenderFrameHost or RenderFrameProxyHost.
void increment_ref_count() { ++frames_ref_count_; }
// Decreases the refcounting on this RVH. This is done by the FrameTree on
- // destruction of a RenderFrameHost.
+ // destruction of a RenderFrameHost or RenderFrameProxyHost.
void decrement_ref_count() { --frames_ref_count_; }
// Returns the refcount on this RVH, that is the number of RenderFrameHosts
- // currently using it.
+ // and RenderFrameProxyHosts currently using it.
int ref_count() { return frames_ref_count_; }
// NOTE: Do not add functions that just send an IPC message that are called in
@@ -286,8 +270,6 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
void RenderWidgetDidInit() override;
void RenderWidgetWillSetIsLoading(bool is_loading) override;
void RenderWidgetGotFocus() override;
- void RenderWidgetWillBeHidden() override;
- void RenderWidgetWillBeShown() override;
void RenderWidgetDidForwardMouseEvent(
const blink::WebMouseEvent& mouse_event) override;
bool MayRenderWidgetForwardKeyboardEvent(
@@ -334,6 +316,9 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
FRIEND_TEST_ALL_PREFIXES(RenderViewHostTest, RoutingIdSane);
FRIEND_TEST_ALL_PREFIXES(RenderFrameHostManagerTest,
CleanUpSwappedOutRVHOnProcessCrash);
+ FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
+ NavigateMainFrameToChildSite);
+
// Send RenderViewReady to observers once the process is launched, but not
// re-entrantly.
void PostRenderViewReady();
@@ -392,9 +377,6 @@ class CONTENT_EXPORT RenderViewHostImpl : public RenderViewHost,
// it is not visible to the user in any of these cases.
bool is_active_;
- // True if this RenderViewHost is pending deletion.
- bool is_pending_deletion_;
-
// Tracks whether the main frame RenderFrameHost is swapped out. Unlike
// is_active_, this is false when the frame is pending swap out or deletion.
// TODO(creis): Remove this when we no longer use swappedout://.
diff --git a/chromium/content/browser/renderer_host/render_widget_helper.cc b/chromium/content/browser/renderer_host/render_widget_helper.cc
index 93283733b31..e6a225c7ab3 100644
--- a/chromium/content/browser/renderer_host/render_widget_helper.cc
+++ b/chromium/content/browser/renderer_host/render_widget_helper.cc
@@ -82,17 +82,6 @@ void RenderWidgetHelper::ResumeDeferredNavigation(
request_id));
}
-void RenderWidgetHelper::ResumeRequestsForView(int route_id) {
- // We only need to resume blocked requests if we used a valid route_id.
- // See CreateNewWindow.
- if (route_id != MSG_ROUTING_NONE) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&RenderWidgetHelper::OnResumeRequestsForView,
- this, route_id));
- }
-}
-
void RenderWidgetHelper::OnResumeDeferredNavigation(
const GlobalRequestID& request_id) {
resource_dispatcher_host_->ResumeDeferredNavigation(request_id);
@@ -122,17 +111,19 @@ void RenderWidgetHelper::CreateNewWindow(
// should be updated to give the widget a distinct routing ID.
// https://crbug.com/545684
*main_frame_widget_route_id = *route_id;
- // Block resource requests until the view is created, since the HWND might
- // be needed if a response ends up creating a plugin.
+ // Block resource requests until the frame is created, since the HWND might
+ // be needed if a response ends up creating a plugin. We'll only have a
+ // single frame at this point. These requests will be resumed either in
+ // WebContentsImpl::CreateNewWindow or RenderFrameHost::Init.
resource_dispatcher_host_->BlockRequestsForRoute(
- render_process_id_, *route_id);
+ GlobalFrameRoutingId(render_process_id_, *main_frame_route_id));
}
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&RenderWidgetHelper::OnCreateWindowOnUI, this, params,
*route_id, *main_frame_route_id, *main_frame_widget_route_id,
- make_scoped_refptr(session_storage_namespace)));
+ base::RetainedRef(session_storage_namespace)));
}
void RenderWidgetHelper::OnCreateWindowOnUI(
@@ -149,11 +140,6 @@ void RenderWidgetHelper::OnCreateWindowOnUI(
session_storage_namespace);
}
-void RenderWidgetHelper::OnResumeRequestsForView(int route_id) {
- resource_dispatcher_host_->ResumeBlockedRequestsForRoute(
- render_process_id_, route_id);
-}
-
void RenderWidgetHelper::CreateNewWidget(int opener_id,
blink::WebPopupType popup_type,
int* route_id) {
diff --git a/chromium/content/browser/renderer_host/render_widget_helper.h b/chromium/content/browser/renderer_host/render_widget_helper.h
index c4b8baf7bf4..43878c707a5 100644
--- a/chromium/content/browser/renderer_host/render_widget_helper.h
+++ b/chromium/content/browser/renderer_host/render_widget_helper.h
@@ -96,10 +96,6 @@ class RenderWidgetHelper
// for documentation.
void ResumeDeferredNavigation(const GlobalRequestID& request_id);
- // Called to resume the requests for a view after it's ready. The view was
- // created by CreateNewWindow which initially blocked the requests.
- void ResumeRequestsForView(int route_id);
-
// IO THREAD ONLY -----------------------------------------------------------
void CreateNewWindow(const ViewHostMsg_CreateWindow_Params& params,
@@ -128,9 +124,6 @@ class RenderWidgetHelper
int32_t main_frame_widget_route_id,
SessionStorageNamespace* session_storage_namespace);
- // Called on the IO thread after a window was created on the UI thread.
- void OnResumeRequestsForView(int route_id);
-
// Called on the UI thread to finish creating a widget.
void OnCreateWidgetOnUI(int32_t opener_id,
int32_t route_id,
diff --git a/chromium/content/browser/renderer_host/render_widget_host_delegate.cc b/chromium/content/browser/renderer_host/render_widget_host_delegate.cc
index c158a41c529..e08c7da3e47 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_delegate.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_delegate.cc
@@ -34,13 +34,6 @@ BrowserAccessibilityManager*
return NULL;
}
-#if defined(OS_WIN)
-gfx::NativeViewAccessible
- RenderWidgetHostDelegate::GetParentNativeViewAccessible() {
- return NULL;
-}
-#endif
-
// If a delegate does not override this, the RenderWidgetHostView will
// assume it is the sole platform event consumer.
RenderWidgetHostInputEventRouter*
diff --git a/chromium/content/browser/renderer_host/render_widget_host_delegate.h b/chromium/content/browser/renderer_host/render_widget_host_delegate.h
index f7fbb0e3622..aa38066ec28 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_delegate.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_delegate.h
@@ -78,22 +78,18 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
// the event itself.
virtual bool HandleWheelEvent(const blink::WebMouseWheelEvent& event);
- // Notification the user has performed a direct interaction (mouse down, mouse
- // wheel, raw key down, or gesture tap) while focus was on the page. Informs
- // the delegate that a user is interacting with a site. Only the first mouse
- // wheel event during a scroll will trigger this method.
- virtual void OnUserInteraction(const blink::WebInputEvent::Type type) {}
+ // Notification the user has performed a direct interaction (mouse down,
+ // scroll, raw key down, gesture tap, or browser-initiated navigation) while
+ // focus was on the page. Informs the delegate that a user is interacting with
+ // a site.
+ virtual void OnUserInteraction(RenderWidgetHostImpl* render_widget_host,
+ const blink::WebInputEvent::Type type) {}
// Callback to give the browser a chance to handle the specified gesture
// event before sending it to the renderer.
// Returns true if the |event| was handled.
virtual bool PreHandleGestureEvent(const blink::WebGestureEvent& event);
- // Notification the user has made a gesture while focus was on the
- // page. This is used to avoid uninitiated user downloads (aka carpet
- // bombing), see DownloadRequestLimiter for details.
- virtual void OnUserGesture(RenderWidgetHostImpl* render_widget_host) {}
-
// Notifies that screen rects were sent to renderer process.
virtual void DidSendScreenRects(RenderWidgetHostImpl* rwh) {}
@@ -171,15 +167,20 @@ class CONTENT_EXPORT RenderWidgetHostDelegate {
// Notification that the widget has lost the mouse lock.
virtual void LostMouseLock(RenderWidgetHostImpl* render_widget_host) {}
-#if defined(OS_WIN)
- virtual gfx::NativeViewAccessible GetParentNativeViewAccessible();
-#endif
-
- // Called when the widget has sent a compositor proto. This is used in Blimp
+ // Called when the widget has sent a compositor proto. This is used in Btlimp
// mode with the RemoteChannel compositor.
virtual void ForwardCompositorProto(RenderWidgetHostImpl* render_widget_host,
const std::vector<uint8_t>& proto) {}
+ // Called when the visibility of the RenderFrameProxyHost in outter
+ // WebContents changes. This method is only called on an inner WebContents and
+ // will eventually notify all the RenderWidgetHostViews belonging to that
+ // WebContents.
+ virtual void OnRenderFrameProxyVisibilityChanged(bool visible) {}
+
+ // Update the renderer's cache of the screen rect of the view and window.
+ virtual void SendScreenRects() {}
+
protected:
virtual ~RenderWidgetHostDelegate() {}
};
diff --git a/chromium/content/browser/renderer_host/render_widget_host_impl.cc b/chromium/content/browser/renderer_host/render_widget_host_impl.cc
index 6516e5ec903..88a1a613cce 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.cc
@@ -45,15 +45,16 @@
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_helper.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
+#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
#include "content/browser/renderer_host/render_widget_host_owner_delegate.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/common/content_constants_internal.h"
#include "content/common/content_switches_internal.h"
#include "content/common/cursors/webcursor.h"
#include "content/common/frame_messages.h"
-#include "content/common/gpu/gpu_messages.h"
#include "content/common/host_shared_bitmap_manager.h"
#include "content/common/input_messages.h"
+#include "content/common/resize_params.h"
#include "content/common/view_messages.h"
#include "content/public/browser/native_web_keyboard_event.h"
#include "content/public/browser/notification_service.h"
@@ -65,6 +66,7 @@
#include "content/public/common/web_preferences.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/service/gpu_switches.h"
+#include "gpu/ipc/common/gpu_messages.h"
#include "skia/ext/image_operations.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
@@ -75,10 +77,6 @@
#include "ui/gfx/skbitmap_operations.h"
#include "ui/snapshot/snapshot.h"
-#if defined(OS_WIN)
-#include "content/common/plugin_constants_win.h"
-#endif
-
#if defined(OS_MACOSX)
#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
#endif
@@ -96,13 +94,6 @@ using blink::WebTextDirection;
namespace content {
namespace {
-// The amount of time after a mouse wheel event is sent to the delegate
-// OnUserInteraction method before another mouse wheel event will be sent. This
-// interval is used by the Blink EventHandler in its orthogonal heuristic for
-// detecting the end of a scroll event (if no event has been seen in 0.1
-// seconds, send an end scroll).
-const double kMouseWheelCoalesceIntervalInSeconds = 0.1;
-
bool g_check_for_pending_resize_ack = true;
// <process id, routing id>
@@ -206,16 +197,17 @@ RenderWidgetHostImpl::RenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
pending_mouse_lock_request_(false),
allow_privileged_mouse_lock_(false),
has_touch_handler_(false),
- is_in_gesture_scroll_(false),
+ is_in_touchpad_gesture_scroll_(false),
+ is_in_touchscreen_gesture_scroll_(false),
received_paint_after_load_(false),
next_browser_snapshot_id_(1),
owned_by_render_frame_host_(false),
is_focused_(false),
+ scale_input_to_viewport_(IsUseZoomForDSFEnabled()),
hung_renderer_delay_(
base::TimeDelta::FromMilliseconds(kHungRendererDelayMs)),
new_content_rendering_delay_(
base::TimeDelta::FromMilliseconds(kNewContentRenderingDelayMs)),
- mouse_wheel_coalesce_timer_(new base::ElapsedTimer()),
weak_factory_(this) {
CHECK(delegate_);
CHECK_NE(MSG_ROUTING_NONE, routing_id_);
@@ -374,8 +366,6 @@ void RenderWidgetHostImpl::SendScreenRects() {
last_window_screen_rect_ = view_->GetBoundsInRootWindow();
Send(new ViewMsg_UpdateScreenRects(
GetRoutingID(), last_view_screen_rect_, last_window_screen_rect_));
- if (delegate_)
- delegate_->DidSendScreenRects(this);
waiting_for_screen_rects_ack_ = true;
}
@@ -399,8 +389,6 @@ void RenderWidgetHostImpl::Init() {
renderer_initialized_ = true;
- GetProcess()->ResumeRequestsForView(routing_id_);
-
// If the RWHV has not yet been set, the surface ID namespace will get
// passed down by the call to SetView().
if (view_) {
@@ -437,12 +425,17 @@ bool RenderWidgetHostImpl::IsLoading() const {
}
bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
+ // Only process messages if the RenderWidget is alive.
+ if (!renderer_initialized())
+ return false;
+
if (owner_delegate_ && owner_delegate_->OnMessageReceived(msg))
return true;
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostImpl, msg)
IPC_MESSAGE_HANDLER(FrameHostMsg_RenderProcessGone, OnRenderProcessGone)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_HittestData, OnHittestData)
IPC_MESSAGE_HANDLER(InputHostMsg_QueueSyntheticGesture,
OnQueueSyntheticGesture)
IPC_MESSAGE_HANDLER(InputHostMsg_ImeCancelComposition,
@@ -465,12 +458,6 @@ bool RenderWidgetHostImpl::OnMessageReceived(const IPC::Message &msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionChanged, OnSelectionChanged)
IPC_MESSAGE_HANDLER(ViewHostMsg_SelectionBoundsChanged,
OnSelectionBoundsChanged)
-#if defined(OS_WIN)
- IPC_MESSAGE_HANDLER(ViewHostMsg_WindowlessPluginDummyWindowCreated,
- OnWindowlessPluginDummyWindowCreated)
- IPC_MESSAGE_HANDLER(ViewHostMsg_WindowlessPluginDummyWindowDestroyed,
- OnWindowlessPluginDummyWindowDestroyed)
-#endif
IPC_MESSAGE_HANDLER(InputHostMsg_ImeCompositionRangeChanged,
OnImeCompositionRangeChanged)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidFirstPaintAfterLoad,
@@ -509,9 +496,6 @@ void RenderWidgetHostImpl::WasHidden() {
if (is_hidden_)
return;
- if (owner_delegate_)
- owner_delegate_->RenderWidgetWillBeHidden();
-
TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::WasHidden");
is_hidden_ = true;
@@ -536,9 +520,6 @@ void RenderWidgetHostImpl::WasShown(const ui::LatencyInfo& latency_info) {
if (!is_hidden_)
return;
- if (owner_delegate_)
- owner_delegate_->RenderWidgetWillBeShown();
-
TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::WasShown");
is_hidden_ = false;
@@ -580,9 +561,8 @@ void RenderWidgetHostImpl::WasShown(const ui::LatencyInfo& latency_info) {
WasResized();
}
-bool RenderWidgetHostImpl::GetResizeParams(
- ViewMsg_Resize_Params* resize_params) {
- *resize_params = ViewMsg_Resize_Params();
+bool RenderWidgetHostImpl::GetResizeParams(ResizeParams* resize_params) {
+ *resize_params = ResizeParams();
GetWebScreenInfo(&resize_params->screen_info);
if (delegate_) {
@@ -633,11 +613,10 @@ bool RenderWidgetHostImpl::GetResizeParams(
}
void RenderWidgetHostImpl::SetInitialRenderSizeParams(
- const ViewMsg_Resize_Params& resize_params) {
+ const ResizeParams& resize_params) {
resize_ack_pending_ = resize_params.needs_resize_ack;
- old_resize_params_ =
- make_scoped_ptr(new ViewMsg_Resize_Params(resize_params));
+ old_resize_params_ = make_scoped_ptr(new ResizeParams(resize_params));
}
void RenderWidgetHostImpl::WasResized() {
@@ -650,7 +629,7 @@ void RenderWidgetHostImpl::WasResized() {
return;
}
- scoped_ptr<ViewMsg_Resize_Params> params(new ViewMsg_Resize_Params);
+ scoped_ptr<ResizeParams> params(new ResizeParams);
if (color_profile_out_of_date_)
DispatchColorProfile();
if (!GetResizeParams(params.get()))
@@ -681,7 +660,7 @@ void RenderWidgetHostImpl::DispatchColorProfile() {
FROM_HERE,
base::Bind(&RenderWidgetHostImpl::SendColorProfile,
weak_factory_.GetWeakPtr()));
-#elif !defined(OS_CHROMEOS) && !defined(OS_IOS) && !defined(OS_ANDROID)
+#elif !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
// Only support desktop Mac and Linux at this time.
SendColorProfile();
#endif
@@ -1045,21 +1024,26 @@ void RenderWidgetHostImpl::ForwardGestureEventWithLatencyInfo(
// TODO(wjmaclean) Remove the code for supporting resending gesture events
// when WebView transitions to OOPIF and BrowserPlugin is removed.
// http://crbug.com/533069
+ bool* is_in_gesture_scroll =
+ gesture_event.sourceDevice ==
+ blink::WebGestureDevice::WebGestureDeviceTouchpad
+ ? &is_in_touchpad_gesture_scroll_
+ : &is_in_touchscreen_gesture_scroll_;
if (gesture_event.type == blink::WebInputEvent::GestureScrollBegin) {
- DCHECK(!is_in_gesture_scroll_);
- is_in_gesture_scroll_ = true;
+ DCHECK(!(*is_in_gesture_scroll));
+ *is_in_gesture_scroll = true;
} else if (gesture_event.type == blink::WebInputEvent::GestureScrollEnd ||
gesture_event.type == blink::WebInputEvent::GestureFlingStart) {
- DCHECK(is_in_gesture_scroll_ ||
+ DCHECK(*is_in_gesture_scroll ||
(gesture_event.type == blink::WebInputEvent::GestureFlingStart &&
gesture_event.sourceDevice ==
blink::WebGestureDevice::WebGestureDeviceTouchpad));
- is_in_gesture_scroll_ = false;
+ *is_in_gesture_scroll = false;
}
bool scroll_update_needs_wrapping =
gesture_event.type == blink::WebInputEvent::GestureScrollUpdate &&
- gesture_event.resendingPluginId != -1 && !is_in_gesture_scroll_;
+ gesture_event.resendingPluginId != -1 && !(*is_in_gesture_scroll);
if (scroll_update_needs_wrapping) {
ForwardGestureEventWithLatencyInfo(
@@ -1135,13 +1119,6 @@ void RenderWidgetHostImpl::ForwardKeyboardEvent(
return;
}
- if (key_event.type == WebKeyboardEvent::Char &&
- (key_event.windowsKeyCode == ui::VKEY_RETURN ||
- key_event.windowsKeyCode == ui::VKEY_SPACE)) {
- if (delegate_)
- delegate_->OnUserGesture(this);
- }
-
// Double check the type to make sure caller hasn't sent us nonsense that
// will mess up our key queue.
if (!WebInputEvent::isKeyboardEventType(key_event.type))
@@ -1264,7 +1241,7 @@ void RenderWidgetHostImpl::GetWebScreenInfo(blink::WebScreenInfo* result) {
// TODO(sievers): find a way to make this done another way so the method
// can be const.
latency_tracker_.set_device_scale_factor(result->deviceScaleFactor);
- if (IsUseZoomForDSFEnabled())
+ if (scale_input_to_viewport_)
input_router_->SetDeviceScaleFactor(result->deviceScaleFactor);
}
@@ -1307,10 +1284,10 @@ const NativeWebKeyboardEvent*
}
void RenderWidgetHostImpl::OnSelectionChanged(const base::string16& text,
- size_t offset,
+ uint32_t offset,
const gfx::Range& range) {
if (view_)
- view_->SelectionChanged(text, offset, range);
+ view_->SelectionChanged(text, static_cast<size_t>(offset), range);
}
void RenderWidgetHostImpl::OnSelectionBoundsChanged(
@@ -1403,10 +1380,12 @@ void RenderWidgetHostImpl::NotifyTextDirection() {
void RenderWidgetHostImpl::ImeSetComposition(
const base::string16& text,
const std::vector<blink::WebCompositionUnderline>& underlines,
+ const gfx::Range& replacement_range,
int selection_start,
int selection_end) {
Send(new InputMsg_ImeSetComposition(
- GetRoutingID(), text, underlines, selection_start, selection_end));
+ GetRoutingID(), text, underlines, replacement_range,
+ selection_start, selection_end));
}
void RenderWidgetHostImpl::ImeConfirmComposition(
@@ -1419,7 +1398,8 @@ void RenderWidgetHostImpl::ImeConfirmComposition(
void RenderWidgetHostImpl::ImeCancelComposition() {
Send(new InputMsg_ImeSetComposition(GetRoutingID(), base::string16(),
- std::vector<blink::WebCompositionUnderline>(), 0, 0));
+ std::vector<blink::WebCompositionUnderline>(),
+ gfx::Range::InvalidRange(), 0, 0));
}
void RenderWidgetHostImpl::RejectMouseLockOrUnlockIfNecessary() {
@@ -1468,8 +1448,10 @@ void RenderWidgetHostImpl::Destroy(bool also_delete) {
if (delegate_)
delegate_->RenderWidgetDeleted(this);
- if (also_delete)
+ if (also_delete) {
+ CHECK(!owner_delegate_);
delete this;
+ }
}
void RenderWidgetHostImpl::RendererIsUnresponsive() {
@@ -1509,6 +1491,12 @@ void RenderWidgetHostImpl::OnRenderProcessGone(int status, int exit_code) {
}
}
+void RenderWidgetHostImpl::OnHittestData(
+ const FrameHostMsg_HittestData_Params& params) {
+ if (delegate_)
+ delegate_->GetInputEventRouter()->OnHittestData(params);
+}
+
void RenderWidgetHostImpl::OnClose() {
ShutdownAndDestroyWidget(true);
}
@@ -1679,14 +1667,6 @@ void RenderWidgetHostImpl::DidUpdateBackingStore(
TRACE_EVENT0("renderer_host", "RenderWidgetHostImpl::DidUpdateBackingStore");
TimeTicks update_start = TimeTicks::Now();
- // Move the plugins if the view hasn't already been destroyed. Plugin moves
- // will not be re-issued, so must move them now, regardless of whether we
- // paint or not. MovePluginWindows attempts to move the plugin windows and
- // in the process could dispatch other window messages which could cause the
- // view to be destroyed.
- if (view_)
- view_->MovePluginWindows(params.plugin_window_moves);
-
NotificationService::current()->Notify(
NOTIFICATION_RENDER_WIDGET_HOST_DID_UPDATE_BACKING_STORE,
Source<RenderWidgetHost>(this),
@@ -1826,43 +1806,6 @@ void RenderWidgetHostImpl::OnShowDisambiguationPopup(
Send(new ViewMsg_ReleaseDisambiguationPopupBitmap(GetRoutingID(), id));
}
-#if defined(OS_WIN)
-void RenderWidgetHostImpl::OnWindowlessPluginDummyWindowCreated(
- gfx::NativeViewId dummy_activation_window) {
- HWND hwnd = reinterpret_cast<HWND>(dummy_activation_window);
-
- // This may happen as a result of a race condition when the plugin is going
- // away.
- wchar_t window_title[MAX_PATH + 1] = {0};
- if (!IsWindow(hwnd) ||
- !GetWindowText(hwnd, window_title, arraysize(window_title)) ||
- lstrcmpiW(window_title, kDummyActivationWindowName) != 0) {
- return;
- }
-
-#if defined(USE_AURA)
- SetParent(hwnd,
- reinterpret_cast<HWND>(view_->GetParentForWindowlessPlugin()));
-#else
- SetParent(hwnd, reinterpret_cast<HWND>(GetNativeViewId()));
-#endif
- dummy_windows_for_activation_.push_back(hwnd);
-}
-
-void RenderWidgetHostImpl::OnWindowlessPluginDummyWindowDestroyed(
- gfx::NativeViewId dummy_activation_window) {
- HWND hwnd = reinterpret_cast<HWND>(dummy_activation_window);
- std::list<HWND>::iterator i = dummy_windows_for_activation_.begin();
- for (; i != dummy_windows_for_activation_.end(); ++i) {
- if ((*i) == hwnd) {
- dummy_windows_for_activation_.erase(i);
- return;
- }
- }
- NOTREACHED() << "Unknown dummy window";
-}
-#endif
-
void RenderWidgetHostImpl::SetIgnoreInputEvents(bool ignore_input_events) {
ignore_input_events_ = ignore_input_events;
}
@@ -1900,25 +1843,11 @@ InputEventAckState RenderWidgetHostImpl::FilterInputEvent(
if (!process_->HasConnection())
return INPUT_EVENT_ACK_STATE_UNKNOWN;
- if (event.type == WebInputEvent::MouseDown ||
- event.type == WebInputEvent::GestureTapDown) {
- if (delegate_)
- delegate_->OnUserGesture(this);
- }
-
- if (delegate_) {
- if (event.type == WebInputEvent::MouseDown ||
- event.type == WebInputEvent::GestureTapDown ||
- event.type == WebInputEvent::RawKeyDown) {
- delegate_->OnUserInteraction(event.type);
- } else if (event.type == WebInputEvent::MouseWheel) {
- if (mouse_wheel_coalesce_timer_->Elapsed().InSecondsF() >
- kMouseWheelCoalesceIntervalInSeconds) {
- delegate_->OnUserInteraction(event.type);
- }
-
- mouse_wheel_coalesce_timer_.reset(new base::ElapsedTimer());
- }
+ if (delegate_ && (event.type == WebInputEvent::MouseDown ||
+ event.type == WebInputEvent::GestureScrollBegin ||
+ event.type == WebInputEvent::GestureTapDown ||
+ event.type == WebInputEvent::RawKeyDown)) {
+ delegate_->OnUserInteraction(this, event.type);
}
return view_ ? view_->FilterInputEvent(event)
@@ -1966,11 +1895,6 @@ void RenderWidgetHostImpl::OnKeyboardEventAck(
InputEventAckState ack_result) {
latency_tracker_.OnInputEventAck(event.event, &event.latency);
-#if defined(OS_MACOSX)
- if (!is_hidden() && view_ && view_->PostProcessEventForPluginIme(event.event))
- return;
-#endif
-
// We only send unprocessed key event upwards if we are not hidden,
// because the user has moved away from us and no longer expect any effect
// of this key event.
@@ -2245,11 +2169,4 @@ BrowserAccessibilityManager*
delegate_->GetOrCreateRootBrowserAccessibilityManager() : NULL;
}
-#if defined(OS_WIN)
-gfx::NativeViewAccessible
- RenderWidgetHostImpl::GetParentNativeViewAccessible() {
- return delegate_ ? delegate_->GetParentNativeViewAccessible() : NULL;
-}
-#endif
-
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_impl.h b/chromium/content/browser/renderer_host/render_widget_host_impl.h
index d5d9d5ad654..04984b1e87f 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_impl.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_impl.h
@@ -46,10 +46,14 @@
#include "ui/events/latency_info.h"
#include "ui/gfx/native_widget_types.h"
+struct FrameHostMsg_HittestData_Params;
struct ViewHostMsg_SelectionBounds_Params;
struct ViewHostMsg_TextInputState_Params;
struct ViewHostMsg_UpdateRect_Params;
-struct ViewMsg_Resize_Params;
+
+namespace base {
+class RefCountedBytes;
+}
namespace blink {
class WebInputEvent;
@@ -81,6 +85,7 @@ class TimeoutMonitor;
class TouchEmulator;
class WebCursor;
struct EditCommand;
+struct ResizeParams;
// This implements the RenderWidgetHost interface that is exposed to
// embedders of content, and adds things only visible to content.
@@ -289,7 +294,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
// when it has received a message.
void ForwardGestureEventWithLatencyInfo(
const blink::WebGestureEvent& gesture_event,
- const ui::LatencyInfo& ui_latency);
+ const ui::LatencyInfo& ui_latency) override;
void ForwardTouchEventWithLatencyInfo(
const blink::WebTouchEvent& touch_event,
const ui::LatencyInfo& ui_latency);
@@ -338,6 +343,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
void ImeSetComposition(
const base::string16& text,
const std::vector<blink::WebCompositionUnderline>& underlines,
+ const gfx::Range& replacement_range,
int selection_start,
int selection_end);
@@ -469,10 +475,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
void RejectMouseLockOrUnlockIfNecessary();
-#if defined(OS_WIN)
- gfx::NativeViewAccessible GetParentNativeViewAccessible();
-#endif
-
void set_renderer_initialized(bool renderer_initialized) {
renderer_initialized_ = renderer_initialized;
}
@@ -485,11 +487,11 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
// Fills in the |resize_params| struct.
// Returns |false| if the update is redundant, |true| otherwise.
- bool GetResizeParams(ViewMsg_Resize_Params* resize_params);
+ bool GetResizeParams(ResizeParams* resize_params);
// Sets the |resize_params| that were sent to the renderer bundled with the
// request to create a new RenderWidget.
- void SetInitialRenderSizeParams(const ViewMsg_Resize_Params& resize_params);
+ void SetInitialRenderSizeParams(const ResizeParams& resize_params);
// Called when we receive a notification indicating that the renderer process
// is gone. This will reset our state so that our state will be consistent if
@@ -506,6 +508,11 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
bool renderer_initialized() const { return renderer_initialized_; }
+ bool scale_input_to_viewport() const { return scale_input_to_viewport_; }
+ void set_scale_input_to_viewport(bool scale_input_to_viewport) {
+ scale_input_to_viewport_ = scale_input_to_viewport;
+ }
+
protected:
// Retrieves an id the renderer can use to refer to its view.
// This is used for various IPC messages, including plugins.
@@ -578,18 +585,13 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
void OnShowDisambiguationPopup(const gfx::Rect& rect_pixels,
const gfx::Size& size,
const cc::SharedBitmapId& id);
-#if defined(OS_WIN)
- void OnWindowlessPluginDummyWindowCreated(
- gfx::NativeViewId dummy_activation_window);
- void OnWindowlessPluginDummyWindowDestroyed(
- gfx::NativeViewId dummy_activation_window);
-#endif
void OnSelectionChanged(const base::string16& text,
- size_t offset,
+ uint32_t offset,
const gfx::Range& range);
void OnSelectionBoundsChanged(
const ViewHostMsg_SelectionBounds_Params& params);
void OnForwardCompositorProto(const std::vector<uint8_t>& proto);
+ void OnHittestData(const FrameHostMsg_HittestData_Params& params);
// Called (either immediately or asynchronously) after we're done with our
// BackingStore and can send an ACK to the renderer so it can paint onto it
@@ -684,7 +686,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
gfx::Size current_size_;
// Resize information that was previously sent to the renderer.
- scoped_ptr<ViewMsg_Resize_Params> old_resize_params_;
+ scoped_ptr<ResizeParams> old_resize_params_;
// The next auto resize to send.
gfx::Size new_auto_size_;
@@ -767,7 +769,8 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
// TODO(wjmaclean) Remove the code for supporting resending gesture events
// when WebView transitions to OOPIF and BrowserPlugin is removed.
// http://crbug.com/533069
- bool is_in_gesture_scroll_;
+ bool is_in_touchpad_gesture_scroll_;
+ bool is_in_touchscreen_gesture_scroll_;
scoped_ptr<SyntheticGestureController> synthetic_gesture_controller_;
@@ -792,10 +795,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
// being sent, in which case the timer should fire).
bool received_paint_after_load_;
-#if defined(OS_WIN)
- std::list<HWND> dummy_windows_for_activation_;
-#endif
-
RenderWidgetHostLatencyTracker latency_tracker_;
int next_browser_snapshot_id_;
@@ -812,6 +811,10 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
// causing HasFocus to return false when is_focused_ is true.
bool is_focused_;
+ // When true, the host will scale the input to viewport.
+ // TODO(oshima): Remove this once crbug.com/563730 is addressed.
+ bool scale_input_to_viewport_;
+
// This value indicates how long to wait before we consider a renderer hung.
base::TimeDelta hung_renderer_delay_;
@@ -819,11 +822,6 @@ class CONTENT_EXPORT RenderWidgetHostImpl : public RenderWidgetHost,
// renderer process before clearing any previously displayed content.
base::TimeDelta new_content_rendering_delay_;
- // Timer used to batch together mouse wheel events for the delegate
- // OnUserInteraction method. A wheel event is only dispatched when a wheel
- // event has not been seen for kMouseWheelCoalesceInterval seconds prior.
- scoped_ptr<base::ElapsedTimer> mouse_wheel_coalesce_timer_;
-
base::WeakPtrFactory<RenderWidgetHostImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostImpl);
diff --git a/chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc b/chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc
index eef72ac2c73..3fd57796c7a 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_input_event_router.cc
@@ -4,17 +4,98 @@
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
+#include "cc/quads/surface_draw_quad.h"
+#include "cc/surfaces/surface_id_allocator.h"
#include "cc/surfaces/surface_manager.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
+#include "content/common/frame_messages.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
+namespace {
+
+void TransformEventTouchPositions(blink::WebTouchEvent* event,
+ const gfx::Vector2d& delta) {
+ for (unsigned i = 0; i < event->touchesLength; ++i) {
+ event->touches[i].position.x += delta.x();
+ event->touches[i].position.y += delta.y();
+ }
+}
+
+} // anonymous namespace
+
namespace content {
+void RenderWidgetHostInputEventRouter::OnRenderWidgetHostViewBaseDestroyed(
+ RenderWidgetHostViewBase* view) {
+ view->RemoveObserver(this);
+
+ // Remove this view from the owner_map.
+ for (auto entry : owner_map_) {
+ if (entry.second == view) {
+ owner_map_.erase(entry.first);
+ // There will only be one instance of a particular view in the map.
+ break;
+ }
+ }
+
+ if (view == touch_target_) {
+ touch_target_ = nullptr;
+ touch_delta_ = gfx::Vector2d();
+ active_touches_ = 0;
+ }
+
+ // If the target that's being destroyed is in the gesture target queue, we
+ // replace it with nullptr so that we maintain the 1:1 correspondence between
+ // queue entries and the touch sequences that underly them.
+ for (size_t i = 0; i < gesture_target_queue_.size(); ++i) {
+ if (gesture_target_queue_[i].target == view)
+ gesture_target_queue_[i].target = nullptr;
+ }
+
+ if (view == gesture_target_) {
+ gesture_target_ = nullptr;
+ gesture_delta_ = gfx::Vector2d();
+ }
+}
+
+void RenderWidgetHostInputEventRouter::ClearAllObserverRegistrations() {
+ for (auto entry : owner_map_)
+ entry.second->RemoveObserver(this);
+ owner_map_.clear();
+}
+
+RenderWidgetHostInputEventRouter::HittestDelegate::HittestDelegate(
+ const std::unordered_map<cc::SurfaceId, HittestData, cc::SurfaceIdHash>&
+ hittest_data)
+ : hittest_data_(hittest_data) {}
+
+bool RenderWidgetHostInputEventRouter::HittestDelegate::RejectHitTarget(
+ const cc::SurfaceDrawQuad* surface_quad,
+ const gfx::Point& point_in_quad_space) {
+ auto it = hittest_data_.find(surface_quad->surface_id);
+ if (it != hittest_data_.end() && it->second.ignored_for_hittest)
+ return true;
+ return false;
+}
+
+bool RenderWidgetHostInputEventRouter::HittestDelegate::AcceptHitTarget(
+ const cc::SurfaceDrawQuad* surface_quad,
+ const gfx::Point& point_in_quad_space) {
+ auto it = hittest_data_.find(surface_quad->surface_id);
+ if (it != hittest_data_.end() && !it->second.ignored_for_hittest)
+ return true;
+ return false;
+}
+
RenderWidgetHostInputEventRouter::RenderWidgetHostInputEventRouter()
- : active_touches_(0) {}
+ : touch_target_(nullptr),
+ gesture_target_(nullptr),
+ active_touches_(0) {}
RenderWidgetHostInputEventRouter::~RenderWidgetHostInputEventRouter() {
- owner_map_.clear();
+ // We may be destroyed before some of the owners in the map, so we must
+ // remove ourself from their observer lists.
+ ClearAllObserverRegistrations();
}
RenderWidgetHostViewBase* RenderWidgetHostInputEventRouter::FindEventTarget(
@@ -28,12 +109,16 @@ RenderWidgetHostViewBase* RenderWidgetHostInputEventRouter::FindEventTarget(
return root_view;
}
+ // The hittest delegate is used to reject hittesting quads based on extra
+ // hittesting data send by the renderer.
+ HittestDelegate delegate(hittest_data_);
+
// The conversion of point to transform_point is done over the course of the
// hit testing, and reflect transformations that would normally be applied in
// the renderer process if the event was being routed between frames within a
// single process with only one RenderWidgetHost.
uint32_t surface_id_namespace =
- root_view->SurfaceIdNamespaceAtPoint(point, transformed_point);
+ root_view->SurfaceIdNamespaceAtPoint(&delegate, point, transformed_point);
const SurfaceIdNamespaceOwnerMap::iterator iter =
owner_map_.find(surface_id_namespace);
// If the point hit a Surface whose namspace is no longer in the map, then
@@ -41,12 +126,8 @@ RenderWidgetHostViewBase* RenderWidgetHostInputEventRouter::FindEventTarget(
// parent frame has not sent a new compositor frame since that happened.
if (iter == owner_map_.end())
return root_view;
- RenderWidgetHostViewBase* target = iter->second.get();
- // If we find the weak pointer is now null, it means the map entry is stale
- // and should be removed to free space.
- if (!target)
- owner_map_.erase(iter);
- return target;
+
+ return iter->second;
}
void RenderWidgetHostInputEventRouter::RouteMouseEvent(
@@ -79,6 +160,39 @@ void RenderWidgetHostInputEventRouter::RouteMouseWheelEvent(
target->ProcessMouseWheelEvent(*event);
}
+void RenderWidgetHostInputEventRouter::RouteGestureEvent(
+ RenderWidgetHostViewBase* root_view,
+ blink::WebGestureEvent* event,
+ const ui::LatencyInfo& latency) {
+ // We use GestureTapDown to detect the start of a gesture sequence since there
+ // is no WebGestureEvent equivalent for ET_GESTURE_BEGIN. Note that this
+ // means the GestureFlingCancel that always comes between ET_GESTURE_BEGIN and
+ // GestureTapDown is sent to the previous target, in case it is still in a
+ // fling.
+ if (event->type == blink::WebInputEvent::GestureTapDown) {
+ if (gesture_target_queue_.empty()) {
+ LOG(ERROR) << "Gesture sequence start detected with no target available.";
+ // Ignore this gesture sequence as no target is available.
+ // TODO(wjmaclean): this only happens on Windows, and should not happen.
+ // https://crbug.com/595422
+ gesture_target_ = nullptr;
+ return;
+ }
+
+ const GestureTargetData& data = gesture_target_queue_.front();
+ gesture_target_ = data.target;
+ gesture_delta_ = data.delta;
+ gesture_target_queue_.pop_front();
+ }
+
+ if (!gesture_target_)
+ return;
+
+ event->x += gesture_delta_.x();
+ event->y += gesture_delta_.y();
+ gesture_target_->ProcessGestureEvent(*event, latency);
+}
+
void RenderWidgetHostInputEventRouter::RouteTouchEvent(
RenderWidgetHostViewBase* root_view,
blink::WebTouchEvent* event,
@@ -88,36 +202,50 @@ void RenderWidgetHostInputEventRouter::RouteTouchEvent(
if (!active_touches_) {
// Since this is the first touch, it defines the target for the rest
// of this sequence.
- DCHECK(!current_touch_target_);
+ DCHECK(!touch_target_);
gfx::Point transformed_point;
gfx::Point original_point(event->touches[0].position.x,
event->touches[0].position.y);
- RenderWidgetHostViewBase* target =
+ touch_target_ =
FindEventTarget(root_view, original_point, &transformed_point);
- if (!target)
- return;
- // Store the weak-ptr to the target, since it could disappear in the
- // middle of a touch sequence.
- current_touch_target_ = target->GetWeakPtr();
+ // TODO(wjmaclean): Instead of just computing a delta, we should extract
+ // the complete transform. We assume it doesn't change for the duration
+ // of the touch sequence, though this could be wrong; a better approach
+ // might be to always transform each point to the touch_target_
+ // for the duration of the sequence.
+ touch_delta_ = transformed_point - original_point;
+ gesture_target_queue_.emplace_back(touch_target_, touch_delta_);
+
+ if (!touch_target_)
+ return;
}
++active_touches_;
- if (current_touch_target_)
- current_touch_target_->ProcessTouchEvent(*event, latency);
+ if (touch_target_) {
+ TransformEventTouchPositions(event, touch_delta_);
+ touch_target_->ProcessTouchEvent(*event, latency);
+ }
break;
}
case blink::WebInputEvent::TouchMove:
- if (current_touch_target_)
- current_touch_target_->ProcessTouchEvent(*event, latency);
+ if (touch_target_) {
+ TransformEventTouchPositions(event, touch_delta_);
+ touch_target_->ProcessTouchEvent(*event, latency);
+ }
break;
case blink::WebInputEvent::TouchEnd:
case blink::WebInputEvent::TouchCancel:
+ if (!touch_target_)
+ break;
+
DCHECK(active_touches_);
- if (current_touch_target_)
- current_touch_target_->ProcessTouchEvent(*event, latency);
+ TransformEventTouchPositions(event, touch_delta_);
+ touch_target_->ProcessTouchEvent(*event, latency);
--active_touches_;
- if (!active_touches_)
- current_touch_target_ = WeakTarget();
+ if (!active_touches_) {
+ touch_target_ = nullptr;
+ touch_delta_ = gfx::Vector2d();
+ }
break;
default:
NOTREACHED();
@@ -128,12 +256,37 @@ void RenderWidgetHostInputEventRouter::AddSurfaceIdNamespaceOwner(
uint32_t id,
RenderWidgetHostViewBase* owner) {
DCHECK(owner_map_.find(id) == owner_map_.end());
- owner_map_.insert(std::make_pair(id, owner->GetWeakPtr()));
+ // We want to be notified if the owner is destroyed so we can remove it from
+ // our map.
+ owner->AddObserver(this);
+ owner_map_.insert(std::make_pair(id, owner));
}
void RenderWidgetHostInputEventRouter::RemoveSurfaceIdNamespaceOwner(
uint32_t id) {
- owner_map_.erase(id);
+ auto it_to_remove = owner_map_.find(id);
+ if (it_to_remove != owner_map_.end()) {
+ it_to_remove->second->RemoveObserver(this);
+ owner_map_.erase(it_to_remove);
+ }
+
+ for (auto it = hittest_data_.begin(); it != hittest_data_.end();) {
+ if (cc::SurfaceIdAllocator::NamespaceForId(it->first) == id)
+ it = hittest_data_.erase(it);
+ else
+ ++it;
+ }
+}
+
+void RenderWidgetHostInputEventRouter::OnHittestData(
+ const FrameHostMsg_HittestData_Params& params) {
+ if (owner_map_.find(cc::SurfaceIdAllocator::NamespaceForId(
+ params.surface_id)) == owner_map_.end()) {
+ return;
+ }
+ HittestData data;
+ data.ignored_for_hittest = params.ignored_for_hittest;
+ hittest_data_[params.surface_id] = data;
}
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_input_event_router.h b/chromium/content/browser/renderer_host/render_widget_host_input_event_router.h
index 03902f5b3d1..b4123539c58 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_input_event_router.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_input_event_router.h
@@ -7,12 +7,22 @@
#include <stdint.h>
+#include <deque>
+#include <unordered_map>
+
#include "base/containers/hash_tables.h"
+#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
+#include "cc/surfaces/surface_hittest_delegate.h"
+#include "cc/surfaces/surface_id.h"
+#include "content/browser/renderer_host/render_widget_host_view_base_observer.h"
#include "content/common/content_export.h"
+#include "ui/gfx/geometry/vector2d.h"
+
+struct FrameHostMsg_HittestData_Params;
namespace blink {
+class WebGestureEvent;
class WebMouseEvent;
class WebMouseWheelEvent;
class WebTouchEvent;
@@ -36,15 +46,22 @@ class RenderWidgetHostViewBase;
// own. When an input event requires routing based on window coordinates,
// this class requests a Surface hit test from the provided |root_view| and
// forwards the event to the owning RWHV of the returned Surface ID.
-class CONTENT_EXPORT RenderWidgetHostInputEventRouter {
+class CONTENT_EXPORT RenderWidgetHostInputEventRouter
+ : public RenderWidgetHostViewBaseObserver {
public:
RenderWidgetHostInputEventRouter();
- ~RenderWidgetHostInputEventRouter();
+ ~RenderWidgetHostInputEventRouter() final;
+
+ void OnRenderWidgetHostViewBaseDestroyed(
+ RenderWidgetHostViewBase* view) override;
void RouteMouseEvent(RenderWidgetHostViewBase* root_view,
blink::WebMouseEvent* event);
void RouteMouseWheelEvent(RenderWidgetHostViewBase* root_view,
blink::WebMouseWheelEvent* event);
+ void RouteGestureEvent(RenderWidgetHostViewBase* root_view,
+ blink::WebGestureEvent* event,
+ const ui::LatencyInfo& latency);
void RouteTouchEvent(RenderWidgetHostViewBase* root_view,
blink::WebTouchEvent *event,
const ui::LatencyInfo& latency);
@@ -56,20 +73,57 @@ class CONTENT_EXPORT RenderWidgetHostInputEventRouter {
return owner_map_.find(id) != owner_map_.end();
}
+ void OnHittestData(const FrameHostMsg_HittestData_Params& params);
+
private:
- using WeakTarget = base::WeakPtr<RenderWidgetHostViewBase>;
+ struct HittestData {
+ bool ignored_for_hittest;
+ };
+
+ class HittestDelegate : public cc::SurfaceHittestDelegate {
+ public:
+ HittestDelegate(
+ const std::unordered_map<cc::SurfaceId, HittestData, cc::SurfaceIdHash>&
+ hittest_data);
+ bool RejectHitTarget(const cc::SurfaceDrawQuad* surface_quad,
+ const gfx::Point& point_in_quad_space) override;
+ bool AcceptHitTarget(const cc::SurfaceDrawQuad* surface_quad,
+ const gfx::Point& point_in_quad_space) override;
+
+ const std::unordered_map<cc::SurfaceId, HittestData, cc::SurfaceIdHash>&
+ hittest_data_;
+ };
+
using SurfaceIdNamespaceOwnerMap =
- base::hash_map<uint32_t, base::WeakPtr<RenderWidgetHostViewBase>>;
+ base::hash_map<uint32_t, RenderWidgetHostViewBase*>;
+ struct GestureTargetData {
+ RenderWidgetHostViewBase* target;
+ const gfx::Vector2d delta;
+
+ GestureTargetData(RenderWidgetHostViewBase* target, gfx::Vector2d delta)
+ : target(target), delta(delta) {}
+ };
+ using GestureTargetQueue = std::deque<GestureTargetData>;
+
+ void ClearAllObserverRegistrations();
RenderWidgetHostViewBase* FindEventTarget(RenderWidgetHostViewBase* root_view,
const gfx::Point& point,
gfx::Point* transformed_point);
SurfaceIdNamespaceOwnerMap owner_map_;
- WeakTarget current_touch_target_;
+ GestureTargetQueue gesture_target_queue_;
+ RenderWidgetHostViewBase* touch_target_;
+ RenderWidgetHostViewBase* gesture_target_;
+ gfx::Vector2d touch_delta_;
+ gfx::Vector2d gesture_delta_;
int active_touches_;
+ std::unordered_map<cc::SurfaceId, HittestData, cc::SurfaceIdHash>
+ hittest_data_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostInputEventRouter);
+ FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest,
+ InputEventRouterGestureTargetQueueTest);
};
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_owner_delegate.h b/chromium/content/browser/renderer_host/render_widget_host_owner_delegate.h
index c2b0c45ec09..9bc1197fc6e 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_owner_delegate.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_owner_delegate.h
@@ -41,10 +41,6 @@ class CONTENT_EXPORT RenderWidgetHostOwnerDelegate {
// The RenderWidgetHost got the focus.
virtual void RenderWidgetGotFocus() = 0;
- // The RenderWidgetHost will be hidden or shown.
- virtual void RenderWidgetWillBeHidden() = 0;
- virtual void RenderWidgetWillBeShown() = 0;
-
// The RenderWidgetHost forwarded a mouse event.
virtual void RenderWidgetDidForwardMouseEvent(
const blink::WebMouseEvent& mouse_event) = 0;
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 c76fc12376b..c56ec9ae858 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_unittest.cc
@@ -22,6 +22,7 @@
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "content/common/input_messages.h"
+#include "content/common/resize_params.h"
#include "content/common/view_messages.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/mock_render_process_host.h"
@@ -36,7 +37,7 @@
#include "content/browser/renderer_host/render_widget_host_view_android.h"
#endif
-#if defined(USE_AURA) || (defined(OS_MACOSX) && !defined(OS_IOS))
+#if defined(USE_AURA) || defined(OS_MACOSX)
#include "content/browser/compositor/test/no_transport_image_transport_factory.h"
#endif
@@ -124,6 +125,7 @@ class MockInputRouter : public InputRouter {
void RequestNotificationWhenFlushed() override {}
bool HasPendingEvents() const override { return false; }
void SetDeviceScaleFactor(float device_scale_factor) override {}
+ void SetFrameTreeNodeId(int frameTreeNodeId) override {}
// IPC::Listener
bool OnMessageReceived(const IPC::Message& message) override {
@@ -455,14 +457,14 @@ class RenderWidgetHostTest : public testing::Test {
browser_context_.reset(new TestBrowserContext());
delegate_.reset(new MockRenderWidgetHostDelegate());
process_ = new RenderWidgetHostProcess(browser_context_.get());
-#if defined(USE_AURA) || (defined(OS_MACOSX) && !defined(OS_IOS))
+#if defined(USE_AURA) || defined(OS_MACOSX)
ImageTransportFactory::InitializeForUnitTests(
scoped_ptr<ImageTransportFactory>(
new NoTransportImageTransportFactory));
#endif
#if defined(USE_AURA)
screen_.reset(aura::TestScreen::Create(gfx::Size()));
- gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, screen_.get());
+ gfx::Screen::SetScreenInstance(screen_.get());
#endif
host_.reset(new MockRenderWidgetHost(delegate_.get(), process_,
process_->GetNextRoutingID()));
@@ -482,10 +484,10 @@ class RenderWidgetHostTest : public testing::Test {
browser_context_.reset();
#if defined(USE_AURA)
- gfx::Screen::SetScreenInstance(gfx::SCREEN_TYPE_NATIVE, nullptr);
+ gfx::Screen::SetScreenInstance(nullptr);
screen_.reset();
#endif
-#if defined(USE_AURA) || (defined(OS_MACOSX) && !defined(OS_IOS))
+#if defined(USE_AURA) || defined(OS_MACOSX)
ImageTransportFactory::Terminate();
#endif
@@ -494,7 +496,7 @@ class RenderWidgetHostTest : public testing::Test {
}
void SetInitialRenderSizeParams() {
- ViewMsg_Resize_Params render_size_params;
+ ResizeParams render_size_params;
host_->GetResizeParams(&render_size_params);
host_->SetInitialRenderSizeParams(render_size_params);
}
@@ -1627,7 +1629,7 @@ TEST_F(RenderWidgetHostTest, ResizeParams) {
view_->set_bounds(bounds);
view_->SetMockPhysicalBackingSize(physical_backing_size);
- ViewMsg_Resize_Params resize_params;
+ ResizeParams resize_params;
host_->GetResizeParams(&resize_params);
EXPECT_EQ(bounds.size(), resize_params.new_size);
EXPECT_EQ(physical_backing_size, resize_params.physical_backing_size);
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 841754602d9..acb9d446490 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
@@ -18,8 +18,6 @@
#include "base/strings/utf_string_conversions.h"
#include "base/sys_info.h"
#include "base/threading/worker_pool.h"
-#include "cc/layers/delegated_frame_provider.h"
-#include "cc/layers/delegated_renderer_layer.h"
#include "cc/layers/layer.h"
#include "cc/layers/surface_layer.h"
#include "cc/output/compositor_frame.h"
@@ -40,6 +38,7 @@
#include "content/browser/android/overscroll_controller_android.h"
#include "content/browser/android/popup_touch_handle_drawable.h"
#include "content/browser/android/synchronous_compositor_base.h"
+#include "content/browser/compositor/gl_helper.h"
#include "content/browser/devtools/render_frame_devtools_agent_host.h"
#include "content/browser/gpu/browser_gpu_channel_host_factory.h"
#include "content/browser/gpu/compositor_util.h"
@@ -56,10 +55,9 @@
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "content/common/gpu/client/gl_helper.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
+#include "content/common/gpu_host_messages.h"
+#include "content/common/gpu_process_launch_causes.h"
#include "content/common/input/did_overscroll_params.h"
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
@@ -118,25 +116,23 @@ const int kUndefinedOutputSurfaceId = -1;
static const char kAsyncReadBackString[] = "Compositing.CopyFromSurfaceTime";
-class GLHelperHolder
- : public blink::WebGraphicsContext3D::WebGraphicsContextLostCallback {
+class GLHelperHolder {
public:
static GLHelperHolder* Create();
- ~GLHelperHolder() override;
- void Initialize();
-
- // WebGraphicsContextLostCallback implementation.
- void onContextLost() override;
-
- GLHelper* GetGLHelper() { return gl_helper_.get(); }
- bool IsLost() { return !context_.get() || context_->isContextLost(); }
+ GLHelper* gl_helper() { return gl_helper_.get(); }
+ bool IsLost() {
+ if (!gl_helper_)
+ return true;
+ return provider_->ContextGL()->GetGraphicsResetStatusKHR() != GL_NO_ERROR;
+ }
private:
- GLHelperHolder();
- static scoped_ptr<WebGraphicsContext3DCommandBufferImpl> CreateContext3D();
+ GLHelperHolder() = default;
+ void Initialize();
+ void OnContextLost();
- scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context_;
+ scoped_refptr<ContextProviderCommandBuffer> provider_;
scoped_ptr<GLHelper> gl_helper_;
DISALLOW_COPY_AND_ASSIGN(GLHelperHolder);
@@ -145,49 +141,28 @@ class GLHelperHolder
GLHelperHolder* GLHelperHolder::Create() {
GLHelperHolder* holder = new GLHelperHolder;
holder->Initialize();
-
return holder;
}
-GLHelperHolder::GLHelperHolder() {
-}
-
-GLHelperHolder::~GLHelperHolder() {
-}
-
void GLHelperHolder::Initialize() {
- context_ = CreateContext3D();
- if (context_) {
- context_->setContextLostCallback(this);
- gl_helper_.reset(new GLHelper(context_->GetImplementation(),
- context_->GetContextSupport()));
- }
-}
+ auto* factory = BrowserGpuChannelHostFactory::instance();
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel_host(factory->GetGpuChannel());
-void GLHelperHolder::onContextLost() {
- // Need to post a task because the command buffer client cannot be deleted
- // from within this callback.
- LOG(ERROR) << "Context lost.";
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&RenderWidgetHostViewAndroid::OnContextLost));
-}
-
-scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
-GLHelperHolder::CreateContext3D() {
- BrowserGpuChannelHostFactory* factory =
- BrowserGpuChannelHostFactory::instance();
- scoped_refptr<GpuChannelHost> gpu_channel_host(factory->GetGpuChannel());
- // GLHelper can only be used in asynchronous APIs for postprocessing after
- // Browser Compositor operations (i.e. readback).
- if (!gpu_channel_host.get()) {
- // The Browser Compositor is in charge of reestablishing the channel.
- return scoped_ptr<WebGraphicsContext3DCommandBufferImpl>();
- }
+ // The Browser Compositor is in charge of reestablishing the channel if its
+ // missing.
+ if (!gpu_channel_host)
+ return;
+
+ // This is for an offscreen context, so we don't need the default framebuffer
+ // to have alpha, stencil, depth, antialiasing.
+ gpu::gles2::ContextCreationAttribHelper attributes;
+ attributes.alpha_size = -1;
+ attributes.stencil_size = 0;
+ attributes.depth_size = 0;
+ attributes.samples = 0;
+ attributes.sample_buffers = 0;
+ attributes.bind_generates_resource = false;
- blink::WebGraphicsContext3D::Attributes attrs;
- attrs.shareResources = true;
- GURL url("chrome://gpu/RenderWidgetHostViewAndroid");
static const size_t kBytesPerPixel = 4;
gfx::DeviceDisplayInfo display_info;
size_t full_screen_texture_size_in_bytes = display_info.GetDisplayHeight() *
@@ -201,23 +176,37 @@ GLHelperHolder::CreateContext3D() {
3 * full_screen_texture_size_in_bytes, kDefaultMaxTransferBufferSize);
limits.mapped_memory_reclaim_limit =
WebGraphicsContext3DCommandBufferImpl::kNoLimit;
- bool lose_context_when_out_of_memory = false;
+
+ bool share_resources = true;
+ // TODO(danakj): This should be false probably, it is for the main thread
+ // context which is used for GLHelper.
+ bool automatic_flushes = true;
+ GURL url("chrome://gpu/RenderWidgetHostViewAndroid");
+
scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
new WebGraphicsContext3DCommandBufferImpl(
- 0, // offscreen
- url, gpu_channel_host.get(), attrs, lose_context_when_out_of_memory,
- limits, nullptr));
- context->SetContextType(BROWSER_OFFSCREEN_MAINTHREAD_CONTEXT);
- if (context->InitializeOnCurrentThread()) {
- context->traceBeginCHROMIUM(
- "gpu_toplevel",
- base::StringPrintf("CmdBufferImageTransportFactory-%p",
- context.get()).c_str());
- } else {
- context.reset();
- }
+ gpu::kNullSurfaceHandle, // offscreen
+ url, gpu_channel_host.get(), attributes, gfx::PreferIntegratedGpu,
+ share_resources, automatic_flushes, limits, nullptr));
+ provider_ = ContextProviderCommandBuffer::Create(
+ std::move(context), BROWSER_OFFSCREEN_MAINTHREAD_CONTEXT);
+ if (!provider_->BindToCurrentThread())
+ return;
+ provider_->ContextGL()->TraceBeginCHROMIUM(
+ "gpu_toplevel",
+ base::StringPrintf("CmdBufferImageTransportFactory-%p", provider_.get())
+ .c_str());
+ provider_->SetLostContextCallback(
+ base::Bind(&GLHelperHolder::OnContextLost, base::Unretained(this)));
+ gl_helper_.reset(
+ new GLHelper(provider_->ContextGL(), provider_->ContextSupport()));
+}
- return context;
+void GLHelperHolder::OnContextLost() {
+ // Need to post a task because the command buffer client cannot be deleted
+ // from within this callback.
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&RenderWidgetHostViewAndroid::OnContextLost));
}
// This can only be used for readback postprocessing. It may return null if the
@@ -233,7 +222,7 @@ GLHelper* GetPostReadbackGLHelper() {
if (!g_readback_helper_holder)
g_readback_helper_holder = GLHelperHolder::Create();
- return g_readback_helper_holder->GetGLHelper();
+ return g_readback_helper_holder->gl_helper();
}
void CopyFromCompositingSurfaceFinished(
@@ -323,7 +312,6 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
is_window_visible_(true),
is_window_activity_started_(true),
content_view_core_(nullptr),
- content_view_core_window_android_(nullptr),
ime_adapter_android_(this),
cached_background_color_(SK_ColorWHITE),
last_output_surface_id_(kUndefinedOutputSurfaceId),
@@ -343,10 +331,10 @@ RenderWidgetHostViewAndroid::RenderWidgetHostViewAndroid(
}
RenderWidgetHostViewAndroid::~RenderWidgetHostViewAndroid() {
+ if (content_view_core_)
+ content_view_core_->RemoveObserver(this);
SetContentViewCore(NULL);
DCHECK(ack_callbacks_.empty());
- if (resource_collection_.get())
- resource_collection_->SetClient(NULL);
DCHECK(!surface_factory_);
DCHECK(surface_id_.is_null());
}
@@ -429,8 +417,7 @@ void RenderWidgetHostViewAndroid::GetScaledContentBitmap(
src_subrect = gfx::Rect(bounds);
DCHECK_LE(src_subrect.width() + src_subrect.x(), bounds.width());
DCHECK_LE(src_subrect.height() + src_subrect.y(), bounds.height());
- const gfx::Display& display =
- gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
+ const gfx::Display& display = gfx::Screen::GetScreen()->GetPrimaryDisplay();
float device_scale_factor = display.device_scale_factor();
DCHECK_GT(device_scale_factor, 0);
gfx::Size dst_size(
@@ -444,21 +431,15 @@ void RenderWidgetHostViewAndroid::GetScaledContentBitmap(
scoped_refptr<cc::Layer> RenderWidgetHostViewAndroid::CreateDelegatedLayer()
const {
scoped_refptr<cc::Layer> delegated_layer;
- if (!surface_id_.is_null()) {
- cc::SurfaceManager* manager = CompositorImpl::GetSurfaceManager();
- DCHECK(manager);
- // manager must outlive compositors using it.
- scoped_refptr<cc::SurfaceLayer> surface_layer = cc::SurfaceLayer::Create(
- Compositor::LayerSettings(),
- base::Bind(&SatisfyCallback, base::Unretained(manager)),
- base::Bind(&RequireCallback, base::Unretained(manager)));
- surface_layer->SetSurfaceId(surface_id_, 1.f, texture_size_in_layer_);
- delegated_layer = surface_layer;
- } else {
- DCHECK(frame_provider_.get());
- delegated_layer = cc::DelegatedRendererLayer::Create(
- Compositor::LayerSettings(), frame_provider_);
- }
+ DCHECK(!surface_id_.is_null());
+ cc::SurfaceManager* manager = CompositorImpl::GetSurfaceManager();
+ DCHECK(manager);
+ // manager must outlive compositors using it.
+ scoped_refptr<cc::SurfaceLayer> surface_layer = cc::SurfaceLayer::Create(
+ base::Bind(&SatisfyCallback, base::Unretained(manager)),
+ base::Bind(&RequireCallback, base::Unretained(manager)));
+ surface_layer->SetSurfaceId(surface_id_, 1.f, texture_size_in_layer_);
+ delegated_layer = surface_layer;
delegated_layer->SetBounds(texture_size_in_layer_);
delegated_layer->SetIsDrawable(true);
delegated_layer->SetContentsOpaque(true);
@@ -500,13 +481,6 @@ RenderWidgetHostViewAndroid::GetNativeViewAccessible() {
return NULL;
}
-void RenderWidgetHostViewAndroid::MovePluginWindows(
- const std::vector<WebPluginGeometry>& moves) {
- // We don't have plugin windows on Android. Do nothing. Note: this is called
- // from RenderWidgetHost::OnUpdateRect which is itself invoked while
- // processing the corresponding message from Renderer.
-}
-
void RenderWidgetHostViewAndroid::Focus() {
host_->Focus();
if (overscroll_controller_)
@@ -562,12 +536,14 @@ void RenderWidgetHostViewAndroid::LockCompositingSurface() {
}
void RenderWidgetHostViewAndroid::UnlockCompositingSurface() {
- if (!frame_evictor_->HasFrame() || locks_on_frame_count_ == 0)
+ if (!frame_evictor_->HasFrame()) {
+ DCHECK_EQ(locks_on_frame_count_, 0u);
return;
+ }
DCHECK(HasValidFrame());
- frame_evictor_->UnlockFrame();
locks_on_frame_count_--;
+ frame_evictor_->UnlockFrame();
if (locks_on_frame_count_ == 0) {
if (last_frame_info_) {
@@ -625,9 +601,20 @@ gfx::Rect RenderWidgetHostViewAndroid::GetViewBounds() const {
if (!content_view_core_)
return gfx::Rect(default_size_);
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableOSKOverscroll))
+ return gfx::Rect(content_view_core_->GetViewSizeWithOSKHidden());
+
return gfx::Rect(content_view_core_->GetViewSize());
}
+gfx::Size RenderWidgetHostViewAndroid::GetVisibleViewportSize() const {
+ if (!content_view_core_)
+ return gfx::Rect(default_size_).size();
+
+ return gfx::Rect(content_view_core_->GetViewSize()).size();
+}
+
gfx::Size RenderWidgetHostViewAndroid::GetPhysicalBackingSize() const {
if (!content_view_core_)
return gfx::Size();
@@ -672,7 +659,7 @@ void RenderWidgetHostViewAndroid::TextInputStateChanged(
host_->Send(new InputMsg_ImeEventAck(host_->GetRoutingID()));
}
- if (!IsShowing())
+ if (!content_view_core_)
return;
content_view_core_->UpdateImeAdapter(
@@ -739,15 +726,15 @@ bool RenderWidgetHostViewAndroid::OnTouchEvent(
if (!result.succeeded)
return false;
- blink::WebTouchEvent web_event =
- ui::CreateWebTouchEventFromMotionEvent(event, result.did_generate_scroll);
+ blink::WebTouchEvent web_event = ui::CreateWebTouchEventFromMotionEvent(
+ event, result.moved_beyond_slop_region);
host_->ForwardTouchEventWithLatencyInfo(web_event, ui::LatencyInfo());
// Send a proactive BeginFrame for this vsync to reduce scroll latency for
// scroll-inducing touch events. Note that Android's Choreographer ensures
// that BeginFrame requests made during ACTION_MOVE dispatch will be honored
// in the same vsync phase.
- if (observing_root_window_ && result.did_generate_scroll)
+ if (observing_root_window_ && result.moved_beyond_slop_region)
RequestVSyncUpdate(BEGIN_FRAME);
return true;
@@ -798,7 +785,11 @@ void RenderWidgetHostViewAndroid::ImeCancelComposition() {
void RenderWidgetHostViewAndroid::ImeCompositionRangeChanged(
const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) {
- // TODO(yukawa): Implement this.
+ std::vector<gfx::RectF> character_bounds_float;
+ for (const gfx::Rect& rect : character_bounds) {
+ character_bounds_float.emplace_back(rect);
+ }
+ ime_adapter_android_.SetCharacterBounds(character_bounds_float);
}
void RenderWidgetHostViewAndroid::FocusedNodeChanged(bool is_editable_node) {
@@ -811,6 +802,7 @@ void RenderWidgetHostViewAndroid::RenderProcessGone(
}
void RenderWidgetHostViewAndroid::Destroy() {
+ host_->ViewDestroyed();
RemoveLayers();
SetContentViewCore(NULL);
@@ -885,8 +877,7 @@ void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
callback.Run(SkBitmap(), READBACK_SURFACE_UNAVAILABLE);
return;
}
- const gfx::Display& display =
- gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
+ const gfx::Display& display = gfx::Screen::GetScreen()->GetPrimaryDisplay();
float device_scale_factor = display.device_scale_factor();
gfx::Size dst_size_in_pixel =
gfx::ConvertRectToPixel(device_scale_factor, gfx::Rect(dst_size)).size();
@@ -901,27 +892,22 @@ void RenderWidgetHostViewAndroid::CopyFromCompositingSurface(
return;
}
- scoped_ptr<cc::CopyOutputRequest> request;
- scoped_refptr<cc::Layer> readback_layer;
- DCHECK(content_view_core_window_android_);
+ if (!content_view_core_ || !(content_view_core_->GetWindowAndroid())) {
+ callback.Run(SkBitmap(), READBACK_FAILED);
+ return;
+ }
ui::WindowAndroidCompositor* compositor =
- content_view_core_window_android_->GetCompositor();
+ content_view_core_->GetWindowAndroid()->GetCompositor();
DCHECK(compositor);
- DCHECK(frame_provider_.get() || !surface_id_.is_null());
- scoped_refptr<cc::Layer> layer = CreateDelegatedLayer();
- DCHECK(layer);
- layer->SetHideLayerAndSubtree(true);
- compositor->AttachLayerForReadback(layer);
-
- readback_layer = layer;
- request = cc::CopyOutputRequest::CreateRequest(
- base::Bind(&RenderWidgetHostViewAndroid::
- PrepareTextureCopyOutputResultForDelegatedReadback,
- dst_size_in_pixel, preferred_color_type, start_time,
- readback_layer, callback));
+ DCHECK(!surface_id_.is_null());
+ scoped_ptr<cc::CopyOutputRequest> request =
+ cc::CopyOutputRequest::CreateRequest(
+ base::Bind(&PrepareTextureCopyOutputResult,
+ dst_size_in_pixel, preferred_color_type, start_time,
+ callback));
if (!src_subrect_in_pixel.IsEmpty())
request->set_area(src_subrect_in_pixel);
- readback_layer->RequestCopyOfOutput(std::move(request));
+ layer_->RequestCopyOfOutput(std::move(request));
}
void RenderWidgetHostViewAndroid::CopyFromCompositingSurfaceToVideoFrame(
@@ -956,8 +942,6 @@ void RenderWidgetHostViewAndroid::SendDelegatedFrameAck(
cc::CompositorFrameAck ack;
if (!surface_returned_resources_.empty())
ack.resources.swap(surface_returned_resources_);
- if (resource_collection_.get())
- resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
host_->Send(new ViewMsg_SwapCompositorFrameAck(host_->GetRoutingID(),
output_surface_id, ack));
}
@@ -966,24 +950,13 @@ void RenderWidgetHostViewAndroid::SendReturnedDelegatedResources(
uint32_t output_surface_id) {
DCHECK(host_);
cc::CompositorFrameAck ack;
- if (!surface_returned_resources_.empty()) {
- ack.resources.swap(surface_returned_resources_);
- } else {
- DCHECK(resource_collection_.get());
- resource_collection_->TakeUnusedResourcesForChildCompositor(&ack.resources);
- }
+ DCHECK(!surface_returned_resources_.empty());
+ ack.resources.swap(surface_returned_resources_);
host_->Send(new ViewMsg_ReclaimCompositorResources(host_->GetRoutingID(),
output_surface_id, ack));
}
-void RenderWidgetHostViewAndroid::UnusedResourcesAreAvailable() {
- DCHECK(surface_id_.is_null());
- if (ack_callbacks_.size())
- return;
- SendReturnedDelegatedResources(last_output_surface_id_);
-}
-
void RenderWidgetHostViewAndroid::ReturnResources(
const cc::ReturnedResourceArray& resources) {
if (resources.empty())
@@ -995,14 +968,12 @@ void RenderWidgetHostViewAndroid::ReturnResources(
}
void RenderWidgetHostViewAndroid::SetBeginFrameSource(
- cc::SurfaceId surface_id,
cc::BeginFrameSource* begin_frame_source) {
// TODO(tansell): Hook this up.
}
void RenderWidgetHostViewAndroid::DestroyDelegatedContent() {
RemoveLayers();
- frame_provider_ = NULL;
if (!surface_id_.is_null()) {
DCHECK(surface_factory_.get());
surface_factory_->Destroy(surface_id_);
@@ -1015,14 +986,6 @@ void RenderWidgetHostViewAndroid::CheckOutputSurfaceChanged(
uint32_t output_surface_id) {
if (output_surface_id == last_output_surface_id_)
return;
- // Drop the cc::DelegatedFrameResourceCollection so that we will not return
- // any resources from the old output surface with the new output surface id.
- if (resource_collection_.get()) {
- resource_collection_->SetClient(NULL);
- if (resource_collection_->LoseAllResources())
- SendReturnedDelegatedResources(last_output_surface_id_);
- resource_collection_ = NULL;
- }
DestroyDelegatedContent();
surface_factory_.reset();
if (!surface_returned_resources_.empty())
@@ -1034,53 +997,35 @@ void RenderWidgetHostViewAndroid::CheckOutputSurfaceChanged(
void RenderWidgetHostViewAndroid::SubmitCompositorFrame(
scoped_ptr<cc::CompositorFrame> frame) {
cc::SurfaceManager* manager = CompositorImpl::GetSurfaceManager();
- if (manager) {
- if (!surface_factory_) {
- surface_factory_ = make_scoped_ptr(new cc::SurfaceFactory(manager, this));
- }
- if (surface_id_.is_null() ||
- texture_size_in_layer_ != current_surface_size_ ||
- location_bar_content_translation_ !=
- frame->metadata.location_bar_content_translation ||
- current_viewport_selection_ != frame->metadata.selection) {
- RemoveLayers();
- if (!surface_id_.is_null())
- surface_factory_->Destroy(surface_id_);
- surface_id_ = id_allocator_->GenerateId();
- surface_factory_->Create(surface_id_);
- layer_ = CreateDelegatedLayer();
-
- DCHECK(layer_);
-
- current_surface_size_ = texture_size_in_layer_;
- location_bar_content_translation_ =
- frame->metadata.location_bar_content_translation;
- current_viewport_selection_ = frame->metadata.selection;
- AttachLayers();
- }
-
- cc::SurfaceFactory::DrawCallback ack_callback =
- base::Bind(&RenderWidgetHostViewAndroid::RunAckCallbacks,
- weak_ptr_factory_.GetWeakPtr());
- surface_factory_->SubmitCompositorFrame(surface_id_, std::move(frame),
- ack_callback);
- } else {
- if (!resource_collection_.get()) {
- resource_collection_ = new cc::DelegatedFrameResourceCollection;
- resource_collection_->SetClient(this);
- }
- if (!frame_provider_.get() ||
- texture_size_in_layer_ != frame_provider_->frame_size()) {
- RemoveLayers();
- frame_provider_ = new cc::DelegatedFrameProvider(
- resource_collection_.get(), std::move(frame->delegated_frame_data));
- layer_ = cc::DelegatedRendererLayer::Create(Compositor::LayerSettings(),
- frame_provider_);
- AttachLayers();
- } else {
- frame_provider_->SetFrameData(std::move(frame->delegated_frame_data));
- }
+ if (!surface_factory_) {
+ surface_factory_ = make_scoped_ptr(new cc::SurfaceFactory(manager, this));
}
+ if (surface_id_.is_null() ||
+ texture_size_in_layer_ != current_surface_size_ ||
+ location_bar_content_translation_ !=
+ frame->metadata.location_bar_content_translation ||
+ current_viewport_selection_ != frame->metadata.selection) {
+ RemoveLayers();
+ if (!surface_id_.is_null())
+ surface_factory_->Destroy(surface_id_);
+ surface_id_ = id_allocator_->GenerateId();
+ surface_factory_->Create(surface_id_);
+ layer_ = CreateDelegatedLayer();
+
+ DCHECK(layer_);
+
+ current_surface_size_ = texture_size_in_layer_;
+ location_bar_content_translation_ =
+ frame->metadata.location_bar_content_translation;
+ current_viewport_selection_ = frame->metadata.selection;
+ AttachLayers();
+ }
+
+ cc::SurfaceFactory::DrawCallback ack_callback =
+ base::Bind(&RenderWidgetHostViewAndroid::RunAckCallbacks,
+ weak_ptr_factory_.GetWeakPtr());
+ surface_factory_->SubmitCompositorFrame(surface_id_, std::move(frame),
+ ack_callback);
}
void RenderWidgetHostViewAndroid::SwapDelegatedFrame(
@@ -1233,9 +1178,9 @@ bool RenderWidgetHostViewAndroid::SupportsAnimation() const {
}
void RenderWidgetHostViewAndroid::SetNeedsAnimate() {
- DCHECK(content_view_core_window_android_);
+ DCHECK(content_view_core_ && content_view_core_->GetWindowAndroid());
DCHECK(using_browser_compositor_);
- content_view_core_window_android_->SetNeedsAnimate();
+ content_view_core_->GetWindowAndroid()->SetNeedsAnimate();
}
void RenderWidgetHostViewAndroid::MoveCaret(const gfx::PointF& position) {
@@ -1364,7 +1309,8 @@ void RenderWidgetHostViewAndroid::OnFrameMetadataUpdated(
frame_metadata.scrollable_viewport_size,
frame_metadata.location_bar_offset,
frame_metadata.location_bar_content_translation,
- is_mobile_optimized);
+ is_mobile_optimized,
+ frame_metadata.selection.start);
#if defined(VIDEO_HOLE)
if (host_) {
WebContents* web_contents =
@@ -1473,17 +1419,20 @@ void RenderWidgetHostViewAndroid::RequestVSyncUpdate(uint32_t requests) {
// vsync requests will be pushed if/when we resume observing in
// |StartObservingRootWindow()|.
if (observing_root_window_ && should_request_vsync)
- content_view_core_window_android_->RequestVSyncUpdate();
+ content_view_core_->GetWindowAndroid()->RequestVSyncUpdate();
}
void RenderWidgetHostViewAndroid::StartObservingRootWindow() {
- DCHECK(content_view_core_window_android_);
+ DCHECK(content_view_core_);
+ // TODO(yusufo): This will need to have a better fallback for cases where
+ // setContentViewCore is called with a valid ContentViewCore without a window.
+ DCHECK(content_view_core_->GetWindowAndroid());
DCHECK(is_showing_);
if (observing_root_window_)
return;
observing_root_window_ = true;
- content_view_core_window_android_->AddObserver(this);
+ content_view_core_->GetWindowAndroid()->AddObserver(this);
// Clear existing vsync requests to allow a request to the new window.
uint32_t outstanding_vsync_requests = outstanding_vsync_requests_;
@@ -1492,7 +1441,7 @@ void RenderWidgetHostViewAndroid::StartObservingRootWindow() {
}
void RenderWidgetHostViewAndroid::StopObservingRootWindow() {
- if (!content_view_core_window_android_) {
+ if (!content_view_core_ || !(content_view_core_->GetWindowAndroid())) {
DCHECK(!observing_root_window_);
return;
}
@@ -1504,7 +1453,7 @@ void RenderWidgetHostViewAndroid::StopObservingRootWindow() {
is_window_activity_started_ = true;
is_window_visible_ = true;
observing_root_window_ = false;
- content_view_core_window_android_->RemoveObserver(this);
+ content_view_core_->GetWindowAndroid()->RemoveObserver(this);
}
void RenderWidgetHostViewAndroid::SendBeginFrame(base::TimeTicks frame_time,
@@ -1547,9 +1496,10 @@ void RenderWidgetHostViewAndroid::RequestDisallowInterceptTouchEvent() {
}
void RenderWidgetHostViewAndroid::EvictDelegatedFrame() {
+ DCHECK_EQ(locks_on_frame_count_, 0u);
+ frame_evictor_->DiscardedFrame();
if (layer_.get())
DestroyDelegatedContent();
- frame_evictor_->DiscardedFrame();
}
bool RenderWidgetHostViewAndroid::HasAcceleratedSurface(
@@ -1660,22 +1610,12 @@ void RenderWidgetHostViewAndroid::OnSetNeedsFlushInput() {
BrowserAccessibilityManager*
RenderWidgetHostViewAndroid::CreateBrowserAccessibilityManager(
- BrowserAccessibilityDelegate* delegate) {
- // TODO(dmazzoni): Currently there can only be one
- // BrowserAccessibilityManager per ContentViewCore, so return NULL
- // if there's already a BrowserAccessibilityManager for the main
- // frame. Eventually, in order to support cross-process iframes on
- // Android we'll need to add support for a
- // BrowserAccessibilityManager for a child frame.
- // http://crbug.com/423846
- if (!host_ || host_->GetRootBrowserAccessibilityManager())
- return NULL;
-
- base::android::ScopedJavaLocalRef<jobject> obj;
- if (content_view_core_)
- obj = content_view_core_->GetJavaObject();
+ BrowserAccessibilityDelegate* delegate, bool for_root_frame) {
+ base::android::ScopedJavaLocalRef<jobject> content_view_core_obj;
+ if (for_root_frame && host_ && content_view_core_)
+ content_view_core_obj = content_view_core_->GetJavaObject();
return new BrowserAccessibilityManagerAndroid(
- obj,
+ content_view_core_obj,
BrowserAccessibilityManagerAndroid::GetEmptyDocument(),
delegate);
}
@@ -1772,6 +1712,9 @@ SkColor RenderWidgetHostViewAndroid::GetCachedBackgroundColor() const {
void RenderWidgetHostViewAndroid::DidOverscroll(
const DidOverscrollParams& params) {
+ if (sync_compositor_)
+ sync_compositor_->DidOverscroll(params);
+
if (!content_view_core_ || !layer_.get() || !is_showing_)
return;
@@ -1803,12 +1746,13 @@ void RenderWidgetHostViewAndroid::SetContentViewCore(
selection_controller_.reset();
ReleaseLocksOnSurface();
resize = true;
+ if (content_view_core_)
+ content_view_core_->RemoveObserver(this);
+ if (content_view_core)
+ content_view_core->AddObserver(this);
}
content_view_core_ = content_view_core;
- content_view_core_window_android_ =
- content_view_core_ ? content_view_core_->GetWindowAndroid() : nullptr;
- DCHECK_EQ(!!content_view_core_, !!content_view_core_window_android_);
BrowserAccessibilityManager* manager = NULL;
if (host_)
@@ -1836,7 +1780,7 @@ void RenderWidgetHostViewAndroid::SetContentViewCore(
selection_controller_ = CreateSelectionController(this, content_view_core_);
if (!overscroll_controller_ &&
- content_view_core_window_android_->GetCompositor()) {
+ content_view_core_->GetWindowAndroid()->GetCompositor()) {
overscroll_controller_ = CreateOverscrollController(content_view_core_);
}
@@ -1871,6 +1815,10 @@ void RenderWidgetHostViewAndroid::OnGestureEvent(
SendGestureEvent(web_gesture);
}
+void RenderWidgetHostViewAndroid::OnContentViewCoreDestroyed() {
+ SetContentViewCore(NULL);
+}
+
void RenderWidgetHostViewAndroid::OnCompositingDidCommit() {
RunAckCallbacks(cc::SurfaceDrawStatus::DRAWN);
}
@@ -1891,6 +1839,19 @@ void RenderWidgetHostViewAndroid::OnRootWindowVisibilityChanged(bool visible) {
HideInternal();
}
+void RenderWidgetHostViewAndroid::OnAttachedToWindow() {
+ if (is_showing_)
+ StartObservingRootWindow();
+ DCHECK(content_view_core_ && content_view_core_->GetWindowAndroid());
+ if (content_view_core_->GetWindowAndroid()->GetCompositor())
+ OnAttachCompositor();
+}
+
+void RenderWidgetHostViewAndroid::OnDetachedFromWindow() {
+ StopObservingRootWindow();
+ OnDetachCompositor();
+}
+
void RenderWidgetHostViewAndroid::OnAttachCompositor() {
DCHECK(content_view_core_);
if (!overscroll_controller_)
@@ -1954,19 +1915,10 @@ void RenderWidgetHostViewAndroid::OnLostResources() {
DCHECK(ack_callbacks_.empty());
}
-// static
-void RenderWidgetHostViewAndroid::
- PrepareTextureCopyOutputResultForDelegatedReadback(
- const gfx::Size& dst_size_in_pixel,
- SkColorType color_type,
- const base::TimeTicks& start_time,
- scoped_refptr<cc::Layer> readback_layer,
- const ReadbackRequestCallback& callback,
- scoped_ptr<cc::CopyOutputResult> result) {
- readback_layer->RemoveFromParent();
- PrepareTextureCopyOutputResult(dst_size_in_pixel, color_type, start_time,
- callback, std::move(result));
-}
+// TODO(wjmaclean): There is significant overlap between
+// PrepareTextureCopyOutputResult and CopyFromCompositingSurfaceFinished in
+// this file, and the versions in surface_utils.cc. They should
+// be merged. See https://crbug.com/582955
// static
void RenderWidgetHostViewAndroid::PrepareTextureCopyOutputResult(
@@ -2057,8 +2009,7 @@ void RenderWidgetHostViewAndroid::OnStylusSelectTap(base::TimeTicks time,
// static
void RenderWidgetHostViewBase::GetDefaultScreenInfo(
blink::WebScreenInfo* results) {
- const gfx::Display& display =
- gfx::Screen::GetNativeScreen()->GetPrimaryDisplay();
+ const gfx::Display& display = gfx::Screen::GetScreen()->GetPrimaryDisplay();
results->rect = display.bounds();
// TODO(husky): Remove any system controls from availableRect.
results->availableRect = display.work_area();
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 0d51b7037fe..ed0cd31d666 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_android.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_android.h
@@ -18,11 +18,11 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/process/process.h"
-#include "cc/layers/delegated_frame_resource_collection.h"
#include "cc/output/begin_frame_args.h"
#include "cc/surfaces/surface_factory_client.h"
#include "cc/surfaces/surface_id.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
+#include "content/browser/android/content_view_core_impl_observer.h"
#include "content/browser/renderer_host/delegated_frame_evictor.h"
#include "content/browser/renderer_host/ime_adapter_android.h"
#include "content/browser/renderer_host/input/stylus_text_selector.h"
@@ -42,8 +42,6 @@ struct ViewHostMsg_TextInputState_Params;
namespace cc {
class CopyOutputResult;
-class DelegatedFrameProvider;
-class DelegatedRendererLayer;
class Layer;
class SurfaceFactory;
class SurfaceIdAllocator;
@@ -58,6 +56,7 @@ class WebMouseEvent;
namespace content {
class ContentViewCoreImpl;
+class ContentViewCoreObserver;
class OverscrollControllerAndroid;
class RenderWidgetHost;
class RenderWidgetHostImpl;
@@ -70,13 +69,13 @@ struct NativeWebKeyboardEvent;
// -----------------------------------------------------------------------------
class CONTENT_EXPORT RenderWidgetHostViewAndroid
: public RenderWidgetHostViewBase,
- public cc::DelegatedFrameResourceCollectionClient,
public cc::SurfaceFactoryClient,
public ui::GestureProviderClient,
public ui::WindowAndroidObserver,
public DelegatedFrameEvictorClient,
public StylusTextSelectorClient,
- public ui::TouchSelectionControllerClient {
+ public ui::TouchSelectionControllerClient,
+ public content::ContentViewCoreImplObserver {
public:
RenderWidgetHostViewAndroid(RenderWidgetHostImpl* widget,
ContentViewCoreImpl* content_view_core);
@@ -97,7 +96,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
gfx::NativeView GetNativeView() const override;
gfx::NativeViewId GetNativeViewId() const override;
gfx::NativeViewAccessible GetNativeViewAccessible() override;
- void MovePluginWindows(const std::vector<WebPluginGeometry>& moves) override;
void Focus() override;
bool HasFocus() const override;
bool IsSurfaceAvailableForCopy() const override;
@@ -105,6 +103,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void Hide() override;
bool IsShowing() override;
gfx::Rect GetViewBounds() const override;
+ gfx::Size GetVisibleViewportSize() const override;
gfx::Size GetPhysicalBackingSize() const override;
bool DoTopControlsShrinkBlinkSize() const override;
float GetTopControlsHeight() const override;
@@ -149,7 +148,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void GestureEventAck(const blink::WebGestureEvent& event,
InputEventAckState ack_result) override;
BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
- BrowserAccessibilityDelegate* delegate) override;
+ BrowserAccessibilityDelegate* delegate, bool for_root_frame) override;
bool LockMouse() override;
void UnlockMouse() override;
void OnSwapCompositorFrame(uint32_t output_surface_id,
@@ -168,13 +167,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
size_t end_offset) override;
void OnDidNavigateMainFrameToNewPage() override;
- // cc::DelegatedFrameResourceCollectionClient implementation.
- void UnusedResourcesAreAvailable() override;
-
// cc::SurfaceFactoryClient implementation.
void ReturnResources(const cc::ReturnedResourceArray& resources) override;
- void SetBeginFrameSource(cc::SurfaceId surface_id,
- cc::BeginFrameSource* begin_frame_source) override;
+ void SetBeginFrameSource(cc::BeginFrameSource* begin_frame_source) override;
// ui::GestureProviderClient implementation.
void OnGestureEvent(const ui::GestureEventData& gesture) override;
@@ -190,6 +185,11 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
void OnActivityStopped() override;
void OnActivityStarted() override;
+ // content::ContentViewCoreImplObserver implementation.
+ void OnContentViewCoreDestroyed() override;
+ void OnAttachedToWindow() override;
+ void OnDetachedFromWindow() override;
+
// DelegatedFrameEvictor implementation
void EvictDelegatedFrame() override;
@@ -291,13 +291,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
const base::TimeTicks& start_time,
const ReadbackRequestCallback& callback,
scoped_ptr<cc::CopyOutputResult> result);
- static void PrepareTextureCopyOutputResultForDelegatedReadback(
- const gfx::Size& dst_size_in_pixel,
- SkColorType color_type,
- const base::TimeTicks& start_time,
- scoped_refptr<cc::Layer> readback_layer,
- const ReadbackRequestCallback& callback,
- scoped_ptr<cc::CopyOutputResult> result);
// DevTools ScreenCast support for Android WebView.
void SynchronousCopyContents(const gfx::Rect& src_subrect_in_pixel,
@@ -350,20 +343,11 @@ class CONTENT_EXPORT RenderWidgetHostViewAndroid
// ContentViewCoreImpl is our interface to the view system.
ContentViewCoreImpl* content_view_core_;
- // Cache the WindowAndroid instance exposed by ContentViewCore to avoid
- // calling into ContentViewCore when it is being detached from the
- // WebContents during destruction. The WindowAndroid has stronger lifetime
- // guarantees, and should be safe to use for observer detachment.
- // This will be non-null iff |content_view_core_| is non-null.
- ui::WindowAndroid* content_view_core_window_android_;
-
ImeAdapterAndroid ime_adapter_android_;
// Body background color of the underlying document.
SkColor cached_background_color_;
- scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection_;
- scoped_refptr<cc::DelegatedFrameProvider> frame_provider_;
scoped_refptr<cc::Layer> layer_;
scoped_ptr<cc::SurfaceIdAllocator> id_allocator_;
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 c5494d9976f..30b07782949 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
@@ -25,6 +25,7 @@
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/accessibility/browser_accessibility_state_impl.h"
#include "content/browser/bad_message.h"
+#include "content/browser/compositor/gl_helper.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
@@ -44,8 +45,7 @@
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
#include "content/browser/renderer_host/ui_events_helper.h"
#include "content/browser/renderer_host/web_input_event_aura.h"
-#include "content/common/gpu/client/gl_helper.h"
-#include "content/common/gpu/gpu_messages.h"
+#include "content/common/content_switches_internal.h"
#include "content/common/site_isolation_policy.h"
#include "content/common/view_messages.h"
#include "content/public/browser/content_browser_client.h"
@@ -54,6 +54,7 @@
#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/common/content_switches.h"
+#include "gpu/ipc/common/gpu_messages.h"
#include "third_party/WebKit/public/platform/WebScreenInfo.h"
#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
@@ -99,10 +100,9 @@
#include "content/browser/accessibility/browser_accessibility_manager_win.h"
#include "content/browser/accessibility/browser_accessibility_win.h"
#include "content/browser/renderer_host/legacy_render_widget_host_win.h"
-#include "content/common/plugin_constants_win.h"
#include "ui/base/win/hidden_window.h"
+#include "ui/display/win/screen_win.h"
#include "ui/gfx/gdi_util.h"
-#include "ui/gfx/screen_win.h"
#include "ui/gfx/win/dpi.h"
#endif
@@ -140,97 +140,6 @@ const int kMouseLockBorderPercentage = 15;
const int kResizeLockTimeoutMs = 67;
#if defined(OS_WIN)
-// Used to associate a plugin HWND with its RenderWidgetHostViewAura instance.
-const wchar_t kWidgetOwnerProperty[] = L"RenderWidgetHostViewAuraOwner";
-
-BOOL CALLBACK WindowDestroyingCallback(HWND window, LPARAM param) {
- RenderWidgetHostViewAura* widget =
- reinterpret_cast<RenderWidgetHostViewAura*>(param);
- if (GetProp(window, kWidgetOwnerProperty) == widget) {
- // Properties set on HWNDs must be removed to avoid leaks.
- RemoveProp(window, kWidgetOwnerProperty);
- RenderWidgetHostViewBase::DetachPluginWindowsCallback(window);
- }
- return TRUE;
-}
-
-BOOL CALLBACK HideWindowsCallback(HWND window, LPARAM param) {
- RenderWidgetHostViewAura* widget =
- reinterpret_cast<RenderWidgetHostViewAura*>(param);
- if (GetProp(window, kWidgetOwnerProperty) == widget)
- SetParent(window, ui::GetHiddenWindow());
- return TRUE;
-}
-
-BOOL CALLBACK ShowWindowsCallback(HWND window, LPARAM param) {
- RenderWidgetHostViewAura* widget =
- reinterpret_cast<RenderWidgetHostViewAura*>(param);
-
- if (GetProp(window, kWidgetOwnerProperty) == widget &&
- widget->GetNativeView()->GetHost()) {
- HWND parent = widget->GetNativeView()->GetHost()->GetAcceleratedWidget();
- SetParent(window, parent);
- }
- return TRUE;
-}
-
-struct CutoutRectsParams {
- RenderWidgetHostViewAura* widget;
- std::vector<gfx::Rect> cutout_rects;
- std::map<HWND, WebPluginGeometry>* geometry;
-};
-
-// Used to update the region for the windowed plugin to draw in. We start with
-// the clip rect from the renderer, then remove the cutout rects from the
-// renderer, and then remove the transient windows from the root window and the
-// constrained windows from the parent window.
-BOOL CALLBACK SetCutoutRectsCallback(HWND window, LPARAM param) {
- CutoutRectsParams* params = reinterpret_cast<CutoutRectsParams*>(param);
-
- if (GetProp(window, kWidgetOwnerProperty) == params->widget) {
- // First calculate the offset of this plugin from the root window, since
- // the cutouts are relative to the root window.
- HWND parent =
- params->widget->GetNativeView()->GetHost()->GetAcceleratedWidget();
- POINT offset;
- offset.x = offset.y = 0;
- MapWindowPoints(window, parent, &offset, 1);
-
- // Now get the cached clip rect and cutouts for this plugin window that came
- // from the renderer.
- std::map<HWND, WebPluginGeometry>::iterator i = params->geometry->begin();
- while (i != params->geometry->end() &&
- i->second.window != window &&
- GetParent(i->second.window) != window) {
- ++i;
- }
-
- if (i == params->geometry->end()) {
- NOTREACHED();
- return TRUE;
- }
-
- HRGN hrgn = CreateRectRgn(i->second.clip_rect.x(),
- i->second.clip_rect.y(),
- i->second.clip_rect.right(),
- i->second.clip_rect.bottom());
- // We start with the cutout rects that came from the renderer, then add the
- // ones that came from transient and constrained windows.
- std::vector<gfx::Rect> cutout_rects = i->second.cutout_rects;
- for (size_t i = 0; i < params->cutout_rects.size(); ++i) {
- gfx::Rect offset_cutout = params->cutout_rects[i];
- offset_cutout.Offset(-offset.x, -offset.y);
- cutout_rects.push_back(offset_cutout);
- }
- gfx::SubtractRectanglesFromRegion(hrgn, cutout_rects);
- // If we don't have any cutout rects then no point in messing with the
- // window region.
- if (cutout_rects.size())
- SetWindowRgn(window, hrgn, TRUE);
- }
- return TRUE;
-}
-
// A callback function for EnumThreadWindows to enumerate and dismiss
// any owned popup windows.
BOOL CALLBACK DismissOwnedPopups(HWND window, LPARAM arg) {
@@ -261,9 +170,9 @@ bool IsXButtonUpEvent(const ui::MouseEvent* event) {
}
void GetScreenInfoForWindow(WebScreenInfo* results, aura::Window* window) {
- const gfx::Display display = window ?
- gfx::Screen::GetScreenFor(window)->GetDisplayNearestWindow(window) :
- gfx::Screen::GetScreenFor(window)->GetPrimaryDisplay();
+ gfx::Screen* screen = gfx::Screen::GetScreen();
+ const gfx::Display display = window ? screen->GetDisplayNearestWindow(window)
+ : screen->GetPrimaryDisplay();
results->rect = display.bounds();
results->availableRect = display.work_area();
// TODO(derat|oshima): Don't hardcode this. Get this from display object.
@@ -474,21 +383,20 @@ RenderWidgetHostViewAura::RenderWidgetHostViewAura(RenderWidgetHost* host,
#if defined(OS_WIN)
legacy_render_widget_host_HWND_(NULL),
legacy_window_destroyed_(false),
- showing_context_menu_(false),
#endif
has_snapped_to_boundary_(false),
is_guest_view_hack_(is_guest_view_hack),
begin_frame_observer_proxy_(this),
set_focus_on_mouse_down_or_key_event_(false),
device_scale_factor_(0.0f),
+ disable_input_event_router_for_testing_(false),
weak_ptr_factory_(this) {
if (!is_guest_view_hack_)
host_->SetView(this);
// Let the page-level input event router know about our surface ID
// namespace for surface-based hit testing.
- if (UseSurfacesEnabled() && host_->delegate() &&
- host_->delegate()->GetInputEventRouter()) {
+ if (host_->delegate() && host_->delegate()->GetInputEventRouter()) {
host_->delegate()->GetInputEventRouter()->AddSurfaceIdNamespaceOwner(
GetSurfaceIdNamespace(), this);
}
@@ -528,7 +436,7 @@ void RenderWidgetHostViewAura::InitAsChild(
parent_view->AddChild(GetNativeView());
const gfx::Display display =
- gfx::Screen::GetScreenFor(window_)->GetDisplayNearestWindow(window_);
+ gfx::Screen::GetScreen()->GetDisplayNearestWindow(window_);
device_scale_factor_ = display.device_scale_factor();
}
@@ -581,7 +489,7 @@ void RenderWidgetHostViewAura::InitAsPopup(
event_filter_for_popup_exit_.reset(new EventFilterForPopupExit(this));
const gfx::Display display =
- gfx::Screen::GetScreenFor(window_)->GetDisplayNearestWindow(window_);
+ gfx::Screen::GetScreen()->GetDisplayNearestWindow(window_);
device_scale_factor_ = display.device_scale_factor();
}
@@ -604,8 +512,8 @@ void RenderWidgetHostViewAura::InitAsFullscreen(
host_tracker_.reset(new aura::WindowTracker);
host_tracker_->Add(reference_window);
}
- gfx::Display display = gfx::Screen::GetScreenFor(window_)->
- GetDisplayNearestWindow(reference_window);
+ gfx::Display display =
+ gfx::Screen::GetScreen()->GetDisplayNearestWindow(reference_window);
parent = reference_window->GetRootWindow();
bounds = display.bounds();
}
@@ -614,7 +522,7 @@ void RenderWidgetHostViewAura::InitAsFullscreen(
Focus();
const gfx::Display display =
- gfx::Screen::GetScreenFor(window_)->GetDisplayNearestWindow(window_);
+ gfx::Screen::GetScreen()->GetDisplayNearestWindow(window_);
device_scale_factor_ = display.device_scale_factor();
}
@@ -659,29 +567,22 @@ void RenderWidgetHostViewAura::Show() {
GetNativeView()->GetHost()->GetAcceleratedWidget());
legacy_render_widget_host_HWND_->SetBounds(
window_->GetBoundsInRootWindow());
- }
- LPARAM lparam = reinterpret_cast<LPARAM>(this);
- EnumChildWindows(ui::GetHiddenWindow(), ShowWindowsCallback, lparam);
-
- if (legacy_render_widget_host_HWND_)
legacy_render_widget_host_HWND_->Show();
+ }
#endif
}
void RenderWidgetHostViewAura::Hide() {
window_->Hide();
+ // TODO(wjmaclean): can host_ ever be null?
if (host_ && !host_->is_hidden()) {
host_->WasHidden();
delegated_frame_host_->WasHidden();
#if defined(OS_WIN)
- constrained_rects_.clear();
aura::WindowTreeHost* host = window_->GetHost();
if (host) {
- HWND parent = host->GetAcceleratedWidget();
- LPARAM lparam = reinterpret_cast<LPARAM>(this);
- EnumChildWindows(parent, HideWindowsCallback, lparam);
// We reparent the legacy Chrome_RenderWidgetHostHWND window to the global
// hidden window on the same lines as Windowed plugin windows.
if (legacy_render_widget_host_HWND_)
@@ -746,7 +647,7 @@ gfx::NativeViewAccessible RenderWidgetHostViewAura::GetNativeViewAccessible() {
BrowserAccessibilityManager* manager =
host_->GetOrCreateRootBrowserAccessibilityManager();
if (manager)
- return manager->GetRoot()->ToBrowserAccessibilityWin();
+ return ToBrowserAccessibilityWin(manager->GetRoot());
#endif
NOTIMPLEMENTED();
@@ -770,10 +671,14 @@ void RenderWidgetHostViewAura::SetKeyboardFocus() {
#if defined(OS_WIN)
if (CanFocus()) {
aura::WindowTreeHost* host = window_->GetHost();
- if (host)
- ::SetFocus(host->GetAcceleratedWidget());
+ if (host) {
+ gfx::AcceleratedWidget hwnd = host->GetAcceleratedWidget();
+ if (!(::GetWindowLong(hwnd, GWL_EXSTYLE) & WS_EX_NOACTIVATE))
+ ::SetFocus(hwnd);
+ }
}
#endif
+ // TODO(wjmaclean): can host_ ever be null?
if (host_ && set_focus_on_mouse_down_or_key_event_) {
set_focus_on_mouse_down_or_key_event_ = false;
host_->Focus();
@@ -795,12 +700,7 @@ RenderFrameHostImpl* RenderWidgetHostViewAura::GetFocusedFrame() {
bool RenderWidgetHostViewAura::CanRendererHandleEvent(
const ui::MouseEvent* event,
bool mouse_locked,
- bool selection_popup) {
-#if defined(OS_WIN)
- bool showing_context_menu = showing_context_menu_;
- showing_context_menu_ = false;
-#endif
-
+ bool selection_popup) const {
if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED)
return false;
@@ -811,7 +711,7 @@ bool RenderWidgetHostViewAura::CanRendererHandleEvent(
// Don't forward the mouse leave message which is received when the context
// menu is displayed by the page. This confuses the page and causes state
// changes.
- if (showing_context_menu)
+ if (IsShowingContextMenu())
return false;
#endif
return true;
@@ -870,7 +770,8 @@ bool RenderWidgetHostViewAura::ShouldRouteEvent(const ui::Event* event) const {
// frame. TODO(wjmaclean): At present, this doesn't work for OOPIF, but
// it should be a simple extension to modify RenderWidgetHostViewChildFrame
// in a similar manner to RenderWidgetHostViewGuest.
- bool result = host_->delegate() && host_->delegate()->GetInputEventRouter();
+ bool result = host_->delegate() && host_->delegate()->GetInputEventRouter() &&
+ !disable_input_event_router_for_testing_;
if (event->IsMouseEvent())
result = result && SiteIsolationPolicy::AreCrossProcessFramesPossible();
return result;
@@ -884,8 +785,14 @@ void RenderWidgetHostViewAura::HandleParentBoundsChanged() {
window_->GetBoundsInRootWindow());
}
#endif
- if (!in_shutdown_)
- host_->SendScreenRects();
+ if (!in_shutdown_) {
+ // Send screen rects through the delegate if there is one. Not every
+ // RenderWidgetHost has a delegate (for example, drop-down widgets).
+ if (host_->delegate())
+ host_->delegate()->SendScreenRects();
+ else
+ host_->SendScreenRects();
+ }
}
void RenderWidgetHostViewAura::ParentHierarchyChanged() {
@@ -894,58 +801,6 @@ void RenderWidgetHostViewAura::ParentHierarchyChanged() {
HandleParentBoundsChanged();
}
-void RenderWidgetHostViewAura::MovePluginWindows(
- const std::vector<WebPluginGeometry>& plugin_window_moves) {
-#if defined(OS_WIN)
- // We need to clip the rectangle to the tab's viewport, otherwise we will draw
- // over the browser UI.
- if (!window_->GetRootWindow()) {
- DCHECK(plugin_window_moves.empty());
- return;
- }
- HWND parent = window_->GetHost()->GetAcceleratedWidget();
- gfx::Rect view_bounds = window_->GetBoundsInRootWindow();
- std::vector<WebPluginGeometry> moves = plugin_window_moves;
-
- gfx::Rect view_port(view_bounds.size());
-
- for (size_t i = 0; i < moves.size(); ++i) {
- gfx::Rect clip(moves[i].clip_rect);
- gfx::Vector2d view_port_offset(
- moves[i].window_rect.OffsetFromOrigin());
- clip.Offset(view_port_offset);
- clip.Intersect(view_port);
- clip.Offset(-view_port_offset);
- moves[i].clip_rect = clip;
-
- moves[i].window_rect.Offset(view_bounds.OffsetFromOrigin());
-
- plugin_window_moves_[moves[i].window] = moves[i];
-
- // constrained_rects_ are relative to the root window. We want to convert
- // them to be relative to the plugin window.
- for (size_t j = 0; j < constrained_rects_.size(); ++j) {
- gfx::Rect offset_cutout = constrained_rects_[j];
- offset_cutout -= moves[i].window_rect.OffsetFromOrigin();
- moves[i].cutout_rects.push_back(offset_cutout);
- }
- }
-
- MovePluginWindowsHelper(parent, moves);
-
- // Make sure each plugin window (or its wrapper if it exists) has a pointer to
- // |this|.
- for (size_t i = 0; i < moves.size(); ++i) {
- HWND window = moves[i].window;
- if (GetParent(window) != parent) {
- window = GetParent(window);
- }
- if (!GetProp(window, kWidgetOwnerProperty))
- SetProp(window, kWidgetOwnerProperty, this);
- }
-#endif // defined(OS_WIN)
-}
-
void RenderWidgetHostViewAura::Focus() {
// Make sure we have a FocusClient before attempting to Focus(). In some
// situations we may not yet be in a valid Window hierarchy (such as reloading
@@ -994,8 +849,8 @@ void RenderWidgetHostViewAura::SetInsets(const gfx::Insets& insets) {
void RenderWidgetHostViewAura::UpdateCursor(const WebCursor& cursor) {
current_cursor_ = cursor;
- const gfx::Display display = gfx::Screen::GetScreenFor(window_)->
- GetDisplayNearestWindow(window_);
+ const gfx::Display display =
+ gfx::Screen::GetScreen()->GetDisplayNearestWindow(window_);
current_cursor_.SetDisplayInfo(display);
UpdateCursorIfOverSelf();
}
@@ -1170,34 +1025,10 @@ bool RenderWidgetHostViewAura::UsesNativeWindowFrame() const {
return (legacy_render_widget_host_HWND_ != NULL);
}
-void RenderWidgetHostViewAura::UpdateConstrainedWindowRects(
- const std::vector<gfx::Rect>& rects) {
- // Check this before setting constrained_rects_, so that next time they're set
- // and we have a root window we don't early return.
- if (!window_->GetHost())
- return;
-
- if (rects == constrained_rects_)
- return;
-
- constrained_rects_ = rects;
-
- HWND parent = window_->GetHost()->GetAcceleratedWidget();
- CutoutRectsParams params;
- params.widget = this;
- params.cutout_rects = constrained_rects_;
- params.geometry = &plugin_window_moves_;
- LPARAM lparam = reinterpret_cast<LPARAM>(&params);
- EnumChildWindows(parent, SetCutoutRectsCallback, lparam);
-}
-
void RenderWidgetHostViewAura::UpdateMouseLockRegion() {
- // Clip the cursor if chrome is running on regular desktop.
- if (gfx::Screen::GetScreenFor(window_) == gfx::Screen::GetNativeScreen()) {
- RECT window_rect =
- gfx::win::DIPToScreenRect(window_->GetBoundsInScreen()).ToRECT();
- ::ClipCursor(&window_rect);
- }
+ RECT window_rect =
+ gfx::win::DIPToScreenRect(window_->GetBoundsInScreen()).ToRECT();
+ ::ClipCursor(&window_rect);
}
void RenderWidgetHostViewAura::OnLegacyWindowDestroyed() {
@@ -1216,6 +1047,13 @@ void RenderWidgetHostViewAura::OnSwapCompositorFrame(
return;
cc::ViewportSelection selection = frame->metadata.selection;
+ if (IsUseZoomForDSFEnabled()) {
+ float viewportToDIPScale = 1.0f / current_device_scale_factor_;
+ selection.start.edge_top.Scale(viewportToDIPScale);
+ selection.start.edge_bottom.Scale(viewportToDIPScale);
+ selection.end.edge_top.Scale(viewportToDIPScale);
+ selection.end.edge_bottom.Scale(viewportToDIPScale);
+ }
delegated_frame_host_->SwapDelegatedFrame(output_surface_id,
std::move(frame));
@@ -1232,21 +1070,6 @@ void RenderWidgetHostViewAura::DidStopFlinging() {
selection_controller_client_->OnScrollCompleted();
}
-#if defined(OS_WIN)
-void RenderWidgetHostViewAura::SetParentNativeViewAccessible(
- gfx::NativeViewAccessible accessible_parent) {
-}
-
-gfx::NativeViewId RenderWidgetHostViewAura::GetParentForWindowlessPlugin()
- const {
- if (legacy_render_widget_host_HWND_) {
- return reinterpret_cast<gfx::NativeViewId>(
- legacy_render_widget_host_HWND_->hwnd());
- }
- return NULL;
-}
-#endif
-
bool RenderWidgetHostViewAura::HasAcceleratedSurface(
const gfx::Size& desired_size) {
// Aura doesn't use GetBackingStore for accelerated pages, so it doesn't
@@ -1408,12 +1231,12 @@ InputEventAckState RenderWidgetHostViewAura::FilterInputEvent(
BrowserAccessibilityManager*
RenderWidgetHostViewAura::CreateBrowserAccessibilityManager(
- BrowserAccessibilityDelegate* delegate) {
+ BrowserAccessibilityDelegate* delegate, bool for_root_frame) {
BrowserAccessibilityManager* manager = NULL;
#if defined(OS_WIN)
manager = new BrowserAccessibilityManagerWin(
BrowserAccessibilityManagerWin::GetEmptyDocument(), delegate);
-#elif !defined(OS_ANDROID)
+#else
manager = BrowserAccessibilityManager::Create(
BrowserAccessibilityManager::GetEmptyDocument(), delegate);
#endif
@@ -1604,6 +1427,7 @@ void RenderWidgetHostViewAura::UnlockMouse() {
// RenderWidgetHostViewAura, ui::TextInputClient implementation:
void RenderWidgetHostViewAura::SetCompositionText(
const ui::CompositionText& composition) {
+ // TODO(wjmaclean): can host_ ever be null?
if (!host_)
return;
@@ -1625,6 +1449,7 @@ void RenderWidgetHostViewAura::SetCompositionText(
// TODO(suzhe): due to a bug of webkit, we can't use selection range with
// composition string. See: https://bugs.webkit.org/show_bug.cgi?id=37788
host_->ImeSetComposition(composition.text, underlines,
+ gfx::Range::InvalidRange(),
composition.selection.end(),
composition.selection.end());
@@ -1632,6 +1457,7 @@ void RenderWidgetHostViewAura::SetCompositionText(
}
void RenderWidgetHostViewAura::ConfirmCompositionText() {
+ // TODO(wjmaclean): can host_ ever be null?
if (host_ && has_composition_text_) {
host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
false);
@@ -1640,6 +1466,7 @@ void RenderWidgetHostViewAura::ConfirmCompositionText() {
}
void RenderWidgetHostViewAura::ClearCompositionText() {
+ // TODO(wjmaclean): can host_ ever be null?
if (host_ && has_composition_text_)
host_->ImeCancelComposition();
has_composition_text_ = false;
@@ -1647,6 +1474,7 @@ void RenderWidgetHostViewAura::ClearCompositionText() {
void RenderWidgetHostViewAura::InsertText(const base::string16& text) {
DCHECK(text_input_type_ != ui::TEXT_INPUT_TYPE_NONE);
+ // TODO(wjmaclean): can host_ ever be null?
if (host_)
host_->ImeConfirmComposition(text, gfx::Range::InvalidRange(), false);
has_composition_text_ = false;
@@ -1659,6 +1487,7 @@ void RenderWidgetHostViewAura::InsertChar(const ui::KeyEvent& event) {
}
// Ignore character messages for VKEY_RETURN sent on CTRL+M. crbug.com/315547
+ // TODO(wjmaclean): can host_ ever be null?
if (host_ &&
(accept_return_character_ || event.GetCharacter() != ui::VKEY_RETURN)) {
// Send a blink::WebInputEvent::Char event to |host_|.
@@ -1794,6 +1623,7 @@ bool RenderWidgetHostViewAura::GetTextFromRange(
}
void RenderWidgetHostViewAura::OnInputMethodChanged() {
+ // TODO(wjmaclean): can host_ ever be null?
if (!host_)
return;
@@ -1803,6 +1633,7 @@ void RenderWidgetHostViewAura::OnInputMethodChanged() {
bool RenderWidgetHostViewAura::ChangeTextDirectionAndLayoutAlignment(
base::i18n::TextDirection direction) {
+ // TODO(wjmaclean): can host_ ever be null?
if (!host_)
return false;
host_->UpdateTextDirection(
@@ -1852,7 +1683,7 @@ void RenderWidgetHostViewAura::OnDisplayRemoved(
void RenderWidgetHostViewAura::OnDisplayMetricsChanged(
const gfx::Display& display, uint32_t metrics) {
// The screen info should be updated regardless of the metric change.
- gfx::Screen* screen = gfx::Screen::GetScreenFor(window_);
+ gfx::Screen* screen = gfx::Screen::GetScreen();
if (display.id() == screen->GetDisplayNearestWindow(window_).id()) {
UpdateScreenInfo(window_);
current_cursor_.SetDisplayInfo(display);
@@ -1916,13 +1747,14 @@ void RenderWidgetHostViewAura::OnPaint(const ui::PaintContext& context) {
void RenderWidgetHostViewAura::OnDeviceScaleFactorChanged(
float device_scale_factor) {
+ // TODO(wjmaclean): can host_ ever be null?
if (!host_ || !window_->GetRootWindow())
return;
UpdateScreenInfo(window_);
device_scale_factor_ = device_scale_factor;
- const gfx::Display display = gfx::Screen::GetScreenFor(window_)->
+ const gfx::Display display = gfx::Screen::GetScreen()->
GetDisplayNearestWindow(window_);
DCHECK_EQ(device_scale_factor, display.device_scale_factor());
current_cursor_.SetDisplayInfo(display);
@@ -1931,17 +1763,6 @@ void RenderWidgetHostViewAura::OnDeviceScaleFactorChanged(
void RenderWidgetHostViewAura::OnWindowDestroying(aura::Window* window) {
#if defined(OS_WIN)
- HWND parent = NULL;
- // If the tab was hidden and it's closed, host_->is_hidden would have been
- // reset to false in RenderWidgetHostImpl::RendererExited.
- if (!window_->GetRootWindow() || host_->is_hidden()) {
- parent = ui::GetHiddenWindow();
- } else {
- parent = window_->GetHost()->GetAcceleratedWidget();
- }
- LPARAM lparam = reinterpret_cast<LPARAM>(this);
- EnumChildWindows(parent, WindowDestroyingCallback, lparam);
-
// The LegacyRenderWidgetHostHWND instance is destroyed when its window is
// destroyed. Normally we control when that happens via the Destroy call
// in the dtor. However there may be cases where the window is destroyed
@@ -2038,6 +1859,11 @@ void RenderWidgetHostViewAura::OnKeyEvent(ui::KeyEvent* event) {
void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
TRACE_EVENT0("input", "RenderWidgetHostViewAura::OnMouseEvent");
+ ForwardMouseEventToParent(event);
+ // TODO(mgiuca): Return if event->handled() returns true. This currently
+ // breaks drop-down lists which means something is incorrectly setting
+ // event->handled to true (http://crbug.com/577983).
+
if (mouse_locked_) {
aura::client::CursorClient* cursor_client =
aura::client::GetCursorClient(window_->GetRootWindow());
@@ -2195,23 +2021,12 @@ void RenderWidgetHostViewAura::OnMouseEvent(ui::MouseEvent* event) {
break;
}
- // Needed to propagate mouse event to |window_->parent()->delegate()|, but
- // note that it might be something other than a WebContentsViewAura instance.
- // TODO(pkotwicz): Find a better way of doing this.
- // In fullscreen mode which is typically used by flash, don't forward
- // the mouse events to the parent. The renderer and the plugin process
- // handle these events.
- if (!is_fullscreen_ && window_->parent() && window_->parent()->delegate() &&
- !(event->flags() & ui::EF_FROM_TOUCH)) {
- event->ConvertLocationToTarget(window_, window_->parent());
- window_->parent()->delegate()->OnMouseEvent(event);
- }
-
if (!IsXButtonUpEvent(event))
event->SetHandled();
}
uint32_t RenderWidgetHostViewAura::SurfaceIdNamespaceAtPoint(
+ cc::SurfaceHittestDelegate* delegate,
const gfx::Point& point,
gfx::Point* transformed_point) {
DCHECK(device_scale_factor_ != 0.0f);
@@ -2220,8 +2035,8 @@ uint32_t RenderWidgetHostViewAura::SurfaceIdNamespaceAtPoint(
// |point| from DIPs to pixels before hittesting.
gfx::Point point_in_pixels =
gfx::ConvertPointToPixel(device_scale_factor_, point);
- cc::SurfaceId id = delegated_frame_host_->SurfaceIdAtPoint(point_in_pixels,
- transformed_point);
+ cc::SurfaceId id = delegated_frame_host_->SurfaceIdAtPoint(
+ delegate, point_in_pixels, transformed_point);
*transformed_point =
gfx::ConvertPointToDIP(device_scale_factor_, *transformed_point);
@@ -2248,12 +2063,24 @@ void RenderWidgetHostViewAura::ProcessTouchEvent(
host_->ForwardTouchEventWithLatencyInfo(event, latency);
}
+void RenderWidgetHostViewAura::ProcessGestureEvent(
+ const blink::WebGestureEvent& event,
+ const ui::LatencyInfo& latency) {
+ host_->ForwardGestureEventWithLatencyInfo(event, latency);
+}
+
void RenderWidgetHostViewAura::TransformPointToLocalCoordSpace(
const gfx::Point& point,
cc::SurfaceId original_surface,
gfx::Point* transformed_point) {
+ // Transformations use physical pixels rather than DIP, so conversion
+ // is necessary.
+ gfx::Point point_in_pixels =
+ gfx::ConvertPointToPixel(device_scale_factor_, point);
delegated_frame_host_->TransformPointToLocalCoordSpace(
- point, original_surface, transformed_point);
+ point_in_pixels, original_surface, transformed_point);
+ *transformed_point =
+ gfx::ConvertPointToDIP(device_scale_factor_, *transformed_point);
}
void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) {
@@ -2356,11 +2183,21 @@ void RenderWidgetHostViewAura::OnGestureEvent(ui::GestureEvent* event) {
blink::WebGestureEvent fling_cancel = gesture;
fling_cancel.type = blink::WebInputEvent::GestureFlingCancel;
fling_cancel.sourceDevice = blink::WebGestureDeviceTouchscreen;
- host_->ForwardGestureEvent(fling_cancel);
+ if (ShouldRouteEvent(event)) {
+ host_->delegate()->GetInputEventRouter()->RouteGestureEvent(
+ this, &fling_cancel, ui::LatencyInfo());
+ } else {
+ host_->ForwardGestureEvent(fling_cancel);
+ }
}
if (gesture.type != blink::WebInputEvent::Undefined) {
- host_->ForwardGestureEventWithLatencyInfo(gesture, *event->latency());
+ if (ShouldRouteEvent(event)) {
+ host_->delegate()->GetInputEventRouter()->RouteGestureEvent(
+ this, &gesture, *event->latency());
+ } else {
+ host_->ForwardGestureEventWithLatencyInfo(gesture, *event->latency());
+ }
if (event->type() == ui::ET_GESTURE_SCROLL_BEGIN ||
event->type() == ui::ET_GESTURE_SCROLL_UPDATE ||
@@ -2447,7 +2284,7 @@ void RenderWidgetHostViewAura::OnWindowFocused(aura::Window* gained_focus,
// If we lose the focus while fullscreen, close the window; Pepper Flash
// won't do it for us (unlike NPAPI Flash). However, we do not close the
// window if we lose the focus to a window on another display.
- gfx::Screen* screen = gfx::Screen::GetScreenFor(window_);
+ gfx::Screen* screen = gfx::Screen::GetScreen();
bool focusing_other_display =
gained_focus && screen->GetNumDisplays() > 1 &&
(screen->GetDisplayNearestWindow(window_).id() !=
@@ -2498,11 +2335,6 @@ RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
selection_controller_.reset();
selection_controller_client_.reset();
- if (UseSurfacesEnabled() && host_->delegate() &&
- host_->delegate()->GetInputEventRouter()) {
- host_->delegate()->GetInputEventRouter()->RemoveSurfaceIdNamespaceOwner(
- GetSurfaceIdNamespace());
- }
delegated_frame_host_.reset();
window_observer_.reset();
if (window_) {
@@ -2510,7 +2342,7 @@ RenderWidgetHostViewAura::~RenderWidgetHostViewAura() {
window_->GetHost()->RemoveObserver(this);
UnlockMouse();
aura::client::SetTooltipText(window_, NULL);
- gfx::Screen::GetScreenFor(window_)->RemoveObserver(this);
+ gfx::Screen::GetScreen()->RemoveObserver(this);
// This call is usually no-op since |this| object is already removed from
// the Aura root window and we don't have a way to get an input method
@@ -2546,7 +2378,7 @@ void RenderWidgetHostViewAura::CreateAuraWindow() {
aura::client::SetActivationDelegate(window_, this);
aura::client::SetFocusChangeObserver(window_, this);
window_->set_layer_owner_delegate(delegated_frame_host_.get());
- gfx::Screen::GetScreenFor(window_)->AddObserver(this);
+ gfx::Screen::GetScreen()->AddObserver(this);
}
void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
@@ -2557,7 +2389,7 @@ void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
if (!root_window)
return;
- gfx::Screen* screen = gfx::Screen::GetScreenFor(GetNativeView());
+ gfx::Screen* screen = gfx::Screen::GetScreen();
DCHECK(screen);
gfx::Point cursor_screen_point = screen->GetCursorScreenPoint();
@@ -2577,8 +2409,8 @@ void RenderWidgetHostViewAura::UpdateCursorIfOverSelf() {
if (hwnd_at_point == legacy_render_widget_host_HWND_->hwnd())
hwnd_at_point = legacy_render_widget_host_HWND_->GetParent();
- gfx::ScreenWin* screen_win = static_cast<gfx::ScreenWin*>(screen);
- DCHECK(screen_win);
+ display::win::ScreenWin* screen_win =
+ static_cast<display::win::ScreenWin*>(screen);
window_at_screen_point = screen_win->GetNativeWindowFromHWND(
hwnd_at_point);
}
@@ -2640,6 +2472,7 @@ bool RenderWidgetHostViewAura::NeedsMouseCapture() {
void RenderWidgetHostViewAura::FinishImeCompositionSession() {
if (!has_composition_text_)
return;
+ // TODO(wjmaclean): can host_ ever be null?
if (host_) {
host_->ImeConfirmComposition(base::string16(), gfx::Range::InvalidRange(),
false);
@@ -2705,31 +2538,32 @@ void RenderWidgetHostViewAura::SnapToPhysicalPixelBoundary() {
// to avoid the web contents area looking blurry we translate the web contents
// in the +x, +y direction to land on the nearest pixel boundary. This may
// cause the bottom and right edges to be clipped slightly, but that's ok.
- aura::Window* snapped = NULL;
- // On desktop, use the root window. On alternative environment (ash),
- // use the toplevel window which must be already snapped.
- if (gfx::Screen::GetScreenFor(window_) !=
- gfx::Screen::GetScreenByType(gfx::SCREEN_TYPE_ALTERNATE)) {
- snapped = window_->GetRootWindow();
- } else {
- snapped = window_->GetToplevelWindow();
- }
+ aura::Window* snapped = window_->GetRootWindow();
if (snapped && snapped != window_)
ui::SnapLayerToPhysicalPixelBoundary(snapped->layer(), window_->layer());
has_snapped_to_boundary_ = true;
}
-void RenderWidgetHostViewAura::OnShowContextMenu() {
+bool RenderWidgetHostViewAura::OnShowContextMenu(
+ const ContextMenuParams& params) {
#if defined(OS_WIN)
- showing_context_menu_ = true;
+ last_context_menu_params_.reset();
+
+ if (params.source_type == ui::MENU_SOURCE_LONG_PRESS) {
+ last_context_menu_params_.reset(new ContextMenuParams);
+ *last_context_menu_params_ = params;
+ return false;
+ }
#endif
+ return true;
}
void RenderWidgetHostViewAura::SetSelectionControllerClientForTest(
scoped_ptr<TouchSelectionControllerClientAura> client) {
selection_controller_client_.swap(client);
CreateSelectionController();
+ disable_input_event_router_for_testing_ = true;
}
void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) {
@@ -2742,15 +2576,8 @@ void RenderWidgetHostViewAura::InternalSetBounds(const gfx::Rect& rect) {
delegated_frame_host_->WasResized();
#if defined(OS_WIN)
// Create the legacy dummy window which corresponds to the bounds of the
- // webcontents. This will be passed as the container window for windowless
- // plugins.
- // Plugins like Flash assume the container window which is returned via the
- // NPNVnetscapeWindow property corresponds to the bounds of the webpage.
- // This is not true in Aura where we have only HWND which is the main Aura
- // window. If we return this window to plugins like Flash then it causes the
- // coordinate translations done by these plugins to break.
- // Additonally the legacy dummy window is needed for accessibility and for
- // scrolling to work in legacy drivers for trackpoints/trackpads, etc.
+ // webcontents. It is needed for accessibility and for scrolling to work in
+ // legacy drivers for trackpoints/trackpads, etc.
if (!legacy_window_destroyed_ && GetNativeViewId()) {
if (!legacy_render_widget_host_HWND_) {
legacy_render_widget_host_HWND_ = LegacyRenderWidgetHostHWND::Create(
@@ -2931,17 +2758,86 @@ void RenderWidgetHostViewAura::HandleGestureForTouchSelection(
}
break;
case ui::ET_GESTURE_SCROLL_BEGIN:
- selection_controller_->OnScrollBeginEvent();
selection_controller_client_->OnScrollStarted();
break;
case ui::ET_GESTURE_SCROLL_END:
selection_controller_client_->OnScrollCompleted();
break;
+#if defined(OS_WIN)
+ case ui::ET_GESTURE_LONG_TAP: {
+ if (!last_context_menu_params_)
+ break;
+
+ scoped_ptr<ContextMenuParams> context_menu_params =
+ std::move(last_context_menu_params_);
+
+ // On Windows we want to display the context menu when the long press
+ // gesture is released. To achieve that, we switch the saved context
+ // menu params source type to MENU_SOURCE_TOUCH. This is to ensure that
+ // the RenderWidgetHostViewAura::OnShowContextMenu function which is
+ // called from the ShowContextMenu call below, does not treat it as
+ // a context menu request coming in from the long press gesture.
+ DCHECK(context_menu_params->source_type == ui::MENU_SOURCE_LONG_PRESS);
+ context_menu_params->source_type = ui::MENU_SOURCE_TOUCH;
+
+ RenderViewHostDelegateView* delegate_view =
+ GetRenderViewHostDelegateView();
+ if (delegate_view)
+ delegate_view->ShowContextMenu(GetFocusedFrame(),
+ *context_menu_params);
+
+ event->SetHandled();
+ // WARNING: we may have been deleted during the call to ShowContextMenu().
+ break;
+ }
+#endif
default:
break;
}
}
+void RenderWidgetHostViewAura::ForwardMouseEventToParent(
+ ui::MouseEvent* event) {
+ // Needed to propagate mouse event to |window_->parent()->delegate()|, but
+ // note that it might be something other than a WebContentsViewAura instance.
+ // TODO(pkotwicz): Find a better way of doing this.
+ // In fullscreen mode which is typically used by flash, don't forward
+ // the mouse events to the parent. The renderer and the plugin process
+ // handle these events.
+ if (is_fullscreen_)
+ return;
+
+ if (event->flags() & ui::EF_FROM_TOUCH)
+ return;
+
+ if (!window_->parent() || !window_->parent()->delegate())
+ return;
+
+ // Take a copy of |event|, to avoid ConvertLocationToTarget mutating the
+ // event.
+ scoped_ptr<ui::Event> event_copy = ui::Event::Clone(*event);
+ ui::MouseEvent* mouse_event = static_cast<ui::MouseEvent*>(event_copy.get());
+ mouse_event->ConvertLocationToTarget(window_, window_->parent());
+ window_->parent()->delegate()->OnMouseEvent(mouse_event);
+ if (mouse_event->handled())
+ event->SetHandled();
+}
+
+RenderViewHostDelegateView*
+RenderWidgetHostViewAura::GetRenderViewHostDelegateView() {
+ // Use RenderViewHostDelegate to get to the WebContentsViewAura, which will
+ // actually show the disambiguation popup.
+ RenderViewHost* rvh = RenderViewHost::From(host_);
+ if (!rvh)
+ return nullptr;
+
+ RenderViewHostDelegate* delegate = rvh->GetDelegate();
+ if (!delegate)
+ return nullptr;
+
+ return delegate->GetDelegateView();
+}
+
////////////////////////////////////////////////////////////////////////////////
// DelegatedFrameHost, public:
@@ -3027,6 +2923,10 @@ uint32_t RenderWidgetHostViewAura::GetSurfaceIdNamespace() {
return delegated_frame_host_->GetSurfaceIdNamespace();
}
+cc::SurfaceId RenderWidgetHostViewAura::SurfaceIdForTesting() const {
+ return delegated_frame_host_->SurfaceIdForTesting();
+}
+
////////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewBase, public:
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_aura.h b/chromium/content/browser/renderer_host/render_widget_host_view_aura.h
index 9aecd40beb6..05de299c6dc 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
@@ -22,13 +22,14 @@
#include "base/memory/weak_ptr.h"
#include "build/build_config.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
-#include "content/browser/compositor/delegated_frame_host.h"
#include "content/browser/compositor/image_transport_factory.h"
#include "content/browser/compositor/owned_mailbox.h"
#include "content/browser/renderer_host/begin_frame_observer_proxy.h"
+#include "content/browser/renderer_host/delegated_frame_host.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/common/content_export.h"
#include "content/common/cursors/webcursor.h"
+#include "content/public/common/context_menu_params.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "ui/aura/client/cursor_client_observer.h"
#include "ui/aura/client/focus_change_observer.h"
@@ -82,6 +83,7 @@ class LegacyRenderWidgetHostHWND;
class OverscrollController;
class RenderFrameHostImpl;
+class RenderViewHostDelegateView;
class RenderWidgetHostImpl;
class RenderWidgetHostView;
class TouchSelectionControllerClientAura;
@@ -131,7 +133,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void InitAsPopup(RenderWidgetHostView* parent_host_view,
const gfx::Rect& pos) override;
void InitAsFullscreen(RenderWidgetHostView* reference_host_view) override;
- void MovePluginWindows(const std::vector<WebPluginGeometry>& moves) override;
void Focus() override;
void UpdateCursor(const WebCursor& cursor) override;
void SetIsLoading(bool is_loading) override;
@@ -178,7 +179,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
InputEventAckState FilterInputEvent(
const blink::WebInputEvent& input_event) override;
BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
- BrowserAccessibilityDelegate* delegate) override;
+ BrowserAccessibilityDelegate* delegate, bool for_root_frame) override;
gfx::AcceleratedWidget AccessibilityGetAcceleratedWidget() override;
gfx::NativeViewAccessible AccessibilityGetNativeViewAccessible() override;
void ShowDisambiguationPopup(const gfx::Rect& rect_pixels,
@@ -193,22 +194,19 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
void LockCompositingSurface() override;
void UnlockCompositingSurface() override;
uint32_t GetSurfaceIdNamespace() override;
- uint32_t SurfaceIdNamespaceAtPoint(const gfx::Point& point,
+ uint32_t SurfaceIdNamespaceAtPoint(cc::SurfaceHittestDelegate* delegate,
+ const gfx::Point& point,
gfx::Point* transformed_point) override;
void ProcessMouseEvent(const blink::WebMouseEvent& event) override;
void ProcessMouseWheelEvent(const blink::WebMouseWheelEvent& event) override;
void ProcessTouchEvent(const blink::WebTouchEvent& event,
const ui::LatencyInfo& latency) override;
+ void ProcessGestureEvent(const blink::WebGestureEvent& event,
+ const ui::LatencyInfo& latency) override;
void TransformPointToLocalCoordSpace(const gfx::Point& point,
cc::SurfaceId original_surface,
gfx::Point* transformed_point) override;
-#if defined(OS_WIN)
- void SetParentNativeViewAccessible(
- gfx::NativeViewAccessible accessible_parent) override;
- gfx::NativeViewId GetParentForWindowlessPlugin() const override;
-#endif
-
// Overridden from ui::TextInputClient:
void SetCompositionText(const ui::CompositionText& composition) override;
void ConfirmCompositionText() override;
@@ -286,11 +284,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
const gfx::Point& new_origin) override;
#if defined(OS_WIN)
- // Sets the cutout rects from constrained windows. These are rectangles that
- // windowed NPAPI plugins shouldn't paint in. Overwrites any previous cutout
- // rects.
- void UpdateConstrainedWindowRects(const std::vector<gfx::Rect>& rects);
-
// Updates the cursor clip region. Used for mouse locking.
void UpdateMouseLockRegion();
@@ -330,13 +323,20 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
}
// Called when the context menu is about to be displayed.
- void OnShowContextMenu();
+ // Returns true if the context menu should be displayed. We only return false
+ // on Windows if the context menu is being displayed in response to a long
+ // press gesture. On Windows we should be consistent like other apps and
+ // display the menu when the touch is released.
+ bool OnShowContextMenu(const ContextMenuParams& params);
// Used in tests to set a mock client for touch selection controller. It will
// create a new touch selection controller for the new client.
void SetSelectionControllerClientForTest(
scoped_ptr<TouchSelectionControllerClientAura> client);
+ // Exposed for tests.
+ cc::SurfaceId SurfaceIdForTesting() const override;
+
protected:
~RenderWidgetHostViewAura() override;
@@ -346,6 +346,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
DelegatedFrameHost* GetDelegatedFrameHost() const {
return delegated_frame_host_.get();
}
+
const ui::MotionEventAura& pointer_state() const { return pointer_state_; }
private:
@@ -490,7 +491,7 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// Returns true if the |event| passed in can be forwarded to the renderer.
bool CanRendererHandleEvent(const ui::MouseEvent* event,
bool mouse_locked,
- bool selection_popup);
+ bool selection_popup) const;
// Returns true when we can do SurfaceHitTesting for the event type.
bool ShouldRouteEvent(const ui::Event* event) const;
@@ -515,6 +516,13 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// handled if it should not be further processed.
void HandleGestureForTouchSelection(ui::GestureEvent* event);
+ // Forwards a mouse event to this view's parent window delegate.
+ void ForwardMouseEventToParent(ui::MouseEvent* event);
+
+ // Returns the RenderViewHostDelegateView instance for this view. Returns
+ // NULL on failure.
+ RenderViewHostDelegateView* GetRenderViewHostDelegateView();
+
// The model object.
RenderWidgetHostImpl* const host_;
@@ -618,17 +626,6 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
CursorVisibilityState cursor_visibility_state_in_renderer_;
#if defined(OS_WIN)
- // The list of rectangles from constrained windows over this view. Windowed
- // NPAPI plugins shouldn't draw over them.
- std::vector<gfx::Rect> constrained_rects_;
-
- typedef std::map<HWND, WebPluginGeometry> PluginWindowMoves;
- // Contains information about each windowed plugin's clip and cutout rects (
- // from the renderer). This is needed because when the transient windows
- // over this view changes, we need this information in order to create a new
- // region for the HWND.
- PluginWindowMoves plugin_window_moves_;
-
// The LegacyRenderWidgetHostHWND class provides a dummy HWND which is used
// for accessibility, as the container for windowless plugins like
// Flash/Silverlight, etc and for legacy drivers for trackpoints/trackpads,
@@ -645,9 +642,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
// exercise.
bool legacy_window_destroyed_;
- // Set to true when a context menu is being displayed. Reset to false when
- // a mouse leave is received in this context.
- bool showing_context_menu_;
+ // Contains a copy of the last context menu request parameters. Only set when
+ // we receive a request to show the context menu on a long press.
+ scoped_ptr<ContextMenuParams> last_context_menu_params_;
#endif
bool has_snapped_to_boundary_;
@@ -685,6 +682,11 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
float device_scale_factor_;
+ // Allows tests to send gesture events for testing without first sending a
+ // corresponding touch sequence, as would be required by
+ // RenderWidgetHostInputEventRouter.
+ bool disable_input_event_router_for_testing_;
+
base::WeakPtrFactory<RenderWidgetHostViewAura> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAura);
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc b/chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
index 4eef57c2d54..da442867180 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_aura_unittest.cc
@@ -23,27 +23,35 @@
#include "cc/surfaces/surface.h"
#include "cc/surfaces/surface_manager.h"
#include "content/browser/browser_thread_impl.h"
-#include "content/browser/compositor/resize_lock.h"
+#include "content/browser/compositor/gl_helper.h"
#include "content/browser/compositor/test/no_transport_image_transport_factory.h"
#include "content/browser/frame_host/render_widget_host_view_guest.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/renderer_host/input/input_router.h"
+#include "content/browser/renderer_host/input/mouse_wheel_event_queue.h"
#include "content/browser/renderer_host/input/web_input_event_util.h"
#include "content/browser/renderer_host/overscroll_controller.h"
#include "content/browser/renderer_host/overscroll_controller_delegate.h"
+#include "content/browser/renderer_host/render_view_host_factory.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
-#include "content/common/gpu/client/gl_helper.h"
-#include "content/common/gpu/gpu_messages.h"
+#include "content/browser/renderer_host/resize_lock.h"
+#include "content/browser/web_contents/web_contents_view_aura.h"
#include "content/common/host_shared_bitmap_manager.h"
+#include "content/common/input/input_event_utils.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
+#include "content/public/browser/web_contents_view_delegate.h"
+#include "content/public/common/context_menu_params.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
+#include "content/test/test_render_view_host.h"
+#include "content/test/test_web_contents.h"
#include "ipc/ipc_test_sink.h"
+#include "media/base/video_frame.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/client/aura_constants.h"
@@ -144,9 +152,11 @@ class TestOverscrollDelegate : public OverscrollControllerDelegate {
class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
public:
- MockRenderWidgetHostDelegate() {}
+ MockRenderWidgetHostDelegate() : rwh_(nullptr) {}
~MockRenderWidgetHostDelegate() override {}
const NativeWebKeyboardEvent* last_event() const { return last_event_.get(); }
+ void set_widget_host(RenderWidgetHostImpl* rwh) { rwh_ = rwh; }
+
protected:
// RenderWidgetHostDelegate:
bool PreHandleKeyboardEvent(const NativeWebKeyboardEvent& event,
@@ -158,9 +168,14 @@ class MockRenderWidgetHostDelegate : public RenderWidgetHostDelegate {
void Copy() override {}
void Paste() override {}
void SelectAll() override {}
+ void SendScreenRects() override {
+ if (rwh_)
+ rwh_->SendScreenRects();
+ }
private:
scoped_ptr<NativeWebKeyboardEvent> last_event_;
+ RenderWidgetHostImpl* rwh_;
DISALLOW_COPY_AND_ASSIGN(MockRenderWidgetHostDelegate);
};
@@ -262,7 +277,7 @@ class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
FakeRenderWidgetHostViewAura(RenderWidgetHost* widget,
bool is_guest_view_hack)
: RenderWidgetHostViewAura(widget, is_guest_view_hack),
- has_resize_lock_(false) {}
+ can_create_resize_lock_(true) {}
void UseFakeDispatcher() {
dispatcher_ = new FakeWindowEventDispatcher(window()->GetHost());
@@ -279,7 +294,9 @@ class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
new FakeResizeLock(desired_size, defer_compositor_lock));
}
- bool DelegatedFrameCanCreateResizeLock() const override { return true; }
+ bool DelegatedFrameCanCreateResizeLock() const override {
+ return can_create_resize_lock_;
+ }
void RunOnCompositingDidCommit() {
GetDelegatedFrameHost()->OnCompositingDidCommitForTesting(
@@ -299,16 +316,12 @@ class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
}
}
- cc::DelegatedFrameProvider* frame_provider() const {
- return GetDelegatedFrameHost()->FrameProviderForTesting();
- }
-
cc::SurfaceId surface_id() const {
return GetDelegatedFrameHost()->SurfaceIdForTesting();
}
bool HasFrameData() const {
- return frame_provider() || !surface_id().is_null();
+ return !surface_id().is_null();
}
bool released_front_lock_active() const {
@@ -327,7 +340,7 @@ class FakeRenderWidgetHostViewAura : public RenderWidgetHostViewAura {
return pointer_state();
}
- bool has_resize_lock_;
+ bool can_create_resize_lock_;
gfx::Size last_frame_size_;
scoped_ptr<cc::CopyOutputRequest> last_copy_request_;
FakeWindowEventDispatcher* dispatcher_;
@@ -402,8 +415,10 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
sink_ = &process_host_->sink();
int32_t routing_id = process_host_->GetNextRoutingID();
- parent_host_ =
- new RenderWidgetHostImpl(&delegate_, process_host_, routing_id, false);
+ delegates_.push_back(make_scoped_ptr(new MockRenderWidgetHostDelegate));
+ parent_host_ = new RenderWidgetHostImpl(delegates_.back().get(),
+ process_host_, routing_id, false);
+ delegates_.back()->set_widget_host(parent_host_);
parent_view_ = new RenderWidgetHostViewAura(parent_host_,
is_guest_view_hack_);
parent_view_->InitAsChild(NULL);
@@ -412,8 +427,10 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
gfx::Rect());
routing_id = process_host_->GetNextRoutingID();
- widget_host_ =
- new RenderWidgetHostImpl(&delegate_, process_host_, routing_id, false);
+ delegates_.push_back(make_scoped_ptr(new MockRenderWidgetHostDelegate));
+ widget_host_ = new RenderWidgetHostImpl(delegates_.back().get(),
+ process_host_, routing_id, false);
+ delegates_.back()->set_widget_host(widget_host_);
widget_host_->Init();
view_ = new FakeRenderWidgetHostViewAura(widget_host_, is_guest_view_hack_);
}
@@ -502,8 +519,8 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
return;
}
- if (!WebInputEventTraits::WillReceiveAckFromRenderer(
- *base::get<0>(params)))
+ InputEventDispatchType dispatch_type = base::get<2>(params);
+ if (dispatch_type == InputEventDispatchType::DISPATCH_TYPE_NON_BLOCKING)
return;
const blink::WebInputEvent* event = base::get<0>(params);
@@ -525,7 +542,7 @@ class RenderWidgetHostViewAuraTest : public testing::Test {
BrowserThreadImpl browser_thread_for_ui_;
scoped_ptr<aura::test::AuraTestHelper> aura_test_helper_;
scoped_ptr<BrowserContext> browser_context_;
- MockRenderWidgetHostDelegate delegate_;
+ std::vector<scoped_ptr<MockRenderWidgetHostDelegate>> delegates_;
MockRenderProcessHost* process_host_;
// Tests should set these to NULL if they've already triggered their
@@ -588,12 +605,27 @@ class RenderWidgetHostViewAuraOverscrollTest
protected:
void SetUpOverscrollEnvironmentWithDebounce(int debounce_interval_in_ms) {
- SetUpOverscrollEnvironmentImpl(debounce_interval_in_ms);
+ SetUpOverscrollEnvironmentImpl(debounce_interval_in_ms, false);
+ }
+
+ void SetUpOverscrollEnvironmentWithWheelGestures() {
+ SetUpOverscrollEnvironmentImpl(0, true);
+ }
+
+ void SetUpOverscrollEnvironment() {
+ SetUpOverscrollEnvironmentImpl(0, false);
}
- void SetUpOverscrollEnvironment() { SetUpOverscrollEnvironmentImpl(0); }
+ void SetUpOverscrollEnvironmentImpl(int debounce_interval_in_ms,
+ bool enable_wheel_gestures) {
+ CHECK(!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableWheelGestures) &&
+ !base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableWheelGestures));
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ enable_wheel_gestures ? switches::kEnableWheelGestures
+ : switches::kDisableWheelGestures);
- void SetUpOverscrollEnvironmentImpl(int debounce_interval_in_ms) {
ui::GestureConfiguration::GetInstance()->set_scroll_debounce_interval_in_ms(
debounce_interval_in_ms);
@@ -1078,9 +1110,10 @@ TEST_F(RenderWidgetHostViewAuraTest, SetCompositionText) {
EXPECT_EQ(underlines[i].background_color,
base::get<1>(params)[i].backgroundColor);
}
+ EXPECT_EQ(gfx::Range::InvalidRange(), base::get<2>(params));
// highlighted range
- EXPECT_EQ(4, base::get<2>(params)) << "Should be the same to the caret pos";
EXPECT_EQ(4, base::get<3>(params)) << "Should be the same to the caret pos";
+ EXPECT_EQ(4, base::get<4>(params)) << "Should be the same to the caret pos";
}
view_->ImeCancelComposition();
@@ -1655,6 +1688,54 @@ TEST_F(RenderWidgetHostViewAuraTest, RecreateLayers) {
}
}
+// If the view size is larger than the compositor frame then extra layers
+// should be created to fill the gap.
+TEST_F(RenderWidgetHostViewAuraTest, DelegatedFrameGutter) {
+ gfx::Size large_size(100, 100);
+ gfx::Size small_size(40, 45);
+ gfx::Size medium_size(40, 95);
+
+ // Prevent the DelegatedFrameHost from skipping frames.
+ view_->can_create_resize_lock_ = false;
+
+ view_->InitAsChild(NULL);
+ aura::client::ParentWindowWithContext(
+ view_->GetNativeView(), parent_view_->GetNativeView()->GetRootWindow(),
+ gfx::Rect());
+ view_->SetSize(large_size);
+ view_->Show();
+ scoped_ptr<cc::CompositorFrame> frame =
+ MakeDelegatedFrame(1.f, small_size, gfx::Rect(small_size));
+ frame->metadata.root_background_color = SK_ColorRED;
+ view_->OnSwapCompositorFrame(0, std::move(frame));
+
+ ui::Layer* parent_layer = view_->GetNativeView()->layer();
+
+ ASSERT_EQ(2u, parent_layer->children().size());
+ EXPECT_EQ(gfx::Rect(40, 0, 60, 100), parent_layer->children()[0]->bounds());
+ EXPECT_EQ(SK_ColorRED, parent_layer->children()[0]->background_color());
+ EXPECT_EQ(gfx::Rect(0, 45, 40, 55), parent_layer->children()[1]->bounds());
+ EXPECT_EQ(SK_ColorRED, parent_layer->children()[1]->background_color());
+
+ view_->SetSize(medium_size);
+
+ // Right gutter is unnecessary.
+ ASSERT_EQ(1u, parent_layer->children().size());
+ EXPECT_EQ(gfx::Rect(0, 45, 40, 50), parent_layer->children()[0]->bounds());
+
+ frame = MakeDelegatedFrame(1.f, medium_size, gfx::Rect(medium_size));
+ view_->OnSwapCompositorFrame(0, std::move(frame));
+ EXPECT_EQ(0u, parent_layer->children().size());
+
+ view_->SetSize(large_size);
+ ASSERT_EQ(2u, parent_layer->children().size());
+
+ // This should evict the frame and remove the gutter layers.
+ view_->Hide();
+ view_->SetSize(small_size);
+ ASSERT_EQ(0u, parent_layer->children().size());
+}
+
TEST_F(RenderWidgetHostViewAuraTest, Resize) {
gfx::Size size1(100, 100);
gfx::Size size2(200, 200);
@@ -1920,8 +2001,10 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFrames) {
// Create a bunch of renderers.
for (size_t i = 0; i < renderer_count; ++i) {
int32_t routing_id = process_host_->GetNextRoutingID();
- hosts[i] =
- new RenderWidgetHostImpl(&delegate_, process_host_, routing_id, false);
+ delegates_.push_back(make_scoped_ptr(new MockRenderWidgetHostDelegate));
+ hosts[i] = new RenderWidgetHostImpl(delegates_.back().get(), process_host_,
+ routing_id, false);
+ delegates_.back()->set_widget_host(hosts[i]);
hosts[i]->Init();
views[i] = new FakeRenderWidgetHostViewAura(hosts[i], false);
views[i]->InitAsChild(NULL);
@@ -2084,8 +2167,10 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithLocking) {
// Create a bunch of renderers.
for (size_t i = 0; i < renderer_count; ++i) {
int32_t routing_id = process_host_->GetNextRoutingID();
- hosts[i] =
- new RenderWidgetHostImpl(&delegate_, process_host_, routing_id, false);
+ delegates_.push_back(make_scoped_ptr(new MockRenderWidgetHostDelegate));
+ hosts[i] = new RenderWidgetHostImpl(delegates_.back().get(), process_host_,
+ routing_id, false);
+ delegates_.back()->set_widget_host(hosts[i]);
hosts[i]->Init();
views[i] = new FakeRenderWidgetHostViewAura(hosts[i], false);
views[i]->InitAsChild(NULL);
@@ -2153,8 +2238,10 @@ TEST_F(RenderWidgetHostViewAuraTest, DiscardDelegatedFramesWithMemoryPressure) {
// Create a bunch of renderers.
for (size_t i = 0; i < renderer_count; ++i) {
int32_t routing_id = process_host_->GetNextRoutingID();
- hosts[i] =
- new RenderWidgetHostImpl(&delegate_, process_host_, routing_id, false);
+ delegates_.push_back(make_scoped_ptr(new MockRenderWidgetHostDelegate));
+ hosts[i] = new RenderWidgetHostImpl(delegates_.back().get(), process_host_,
+ routing_id, false);
+ delegates_.back()->set_widget_host(hosts[i]);
hosts[i]->Init();
views[i] = new FakeRenderWidgetHostViewAura(hosts[i], false);
views[i]->InitAsChild(NULL);
@@ -2215,9 +2302,6 @@ TEST_F(RenderWidgetHostViewAuraTest, SoftwareDPIChange) {
view_->OnSwapCompositorFrame(
1, MakeDelegatedFrame(1.f, frame_size, gfx::Rect(frame_size)));
- // Save the frame provider.
- scoped_refptr<cc::DelegatedFrameProvider> frame_provider =
- view_->frame_provider();
cc::SurfaceId surface_id = view_->surface_id();
// This frame will have the same number of physical pixels, but has a new
@@ -2225,13 +2309,10 @@ TEST_F(RenderWidgetHostViewAuraTest, SoftwareDPIChange) {
view_->OnSwapCompositorFrame(
1, MakeDelegatedFrame(2.f, frame_size, gfx::Rect(frame_size)));
- // When we get a new frame with the same frame size in physical pixels, but a
- // different scale, we should generate a new frame provider, as the final
- // result will need to be scaled differently to the screen.
- if (frame_provider.get())
- EXPECT_NE(frame_provider.get(), view_->frame_provider());
- else
- EXPECT_NE(surface_id, view_->surface_id());
+ // When we get a new frame with the same frame size in physical pixels, but
+ // a different scale, we should generate a surface, as the final result will
+ // need to be scaled differently to the screen.
+ EXPECT_NE(surface_id, view_->surface_id());
}
class RenderWidgetHostViewAuraCopyRequestTest
@@ -2578,6 +2659,70 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, WheelScrollEventOverscrolls) {
EXPECT_EQ(1U, sink_->message_count());
}
+// Disabled on MacOS because it doesn't support wheel gestures
+// just yet.
+#if defined(OS_MACOSX)
+#define MAYBE_WheelScrollEventOverscrollsWithWheelGestures \
+ DISABLED_WheelScrollEventOverscrollsWithWheelGestures
+#else
+#define MAYBE_WheelScrollEventOverscrollsWithWheelGestures \
+ WheelScrollEventOverscrollsWithWheelGestures
+#endif
+TEST_F(RenderWidgetHostViewAuraOverscrollTest,
+ MAYBE_WheelScrollEventOverscrollsWithWheelGestures) {
+ SetUpOverscrollEnvironmentWithWheelGestures();
+
+ // Simulate wheel events.
+ SimulateWheelEvent(-5, 0, 0, true); // sent directly
+ SimulateWheelEvent(-1, 1, 0, true); // enqueued
+ SimulateWheelEvent(-10, -3, 0, true); // coalesced into previous event
+ SimulateWheelEvent(-15, -1, 0, true); // coalesced into previous event
+ SimulateWheelEvent(-30, -3, 0, true); // coalesced into previous event
+ SimulateWheelEvent(-20, 6, 1, true); // enqueued, different modifiers
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+
+ // Receive ACK the first wheel event as not processed.
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ // ScrollBegin, ScrollUpdate, MouseWheel will be queued events
+ EXPECT_EQ(3U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
+
+ // Receive ACK for the second (coalesced) event as not processed. This will
+ // start a back navigation. However, this will also cause the queued next
+ // event to be sent to the renderer. But since overscroll navigation has
+ // started, that event will also be included in the overscroll computation
+ // instead of being sent to the renderer. So the result will be an overscroll
+ // back navigation, and no event will be sent to the renderer.
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ // ScrollUpdate, MouseWheel will be queued events
+ EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ EXPECT_EQ(OVERSCROLL_WEST, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_WEST, overscroll_delegate()->current_mode());
+ EXPECT_EQ(-81.f, overscroll_delta_x());
+ EXPECT_EQ(-31.f, overscroll_delegate()->delta_x());
+ EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
+ EXPECT_EQ(0U, sink_->message_count());
+
+ // Send a mouse-move event. This should cancel the overscroll navigation.
+ SimulateMouseMove(5, 10, 0);
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
+ EXPECT_EQ(1U, sink_->message_count());
+}
+
// Tests that if some scroll events are consumed towards the start, then
// subsequent scrolls do not horizontal overscroll.
TEST_F(RenderWidgetHostViewAuraOverscrollTest,
@@ -2642,6 +2787,65 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
EXPECT_EQ(OVERSCROLL_WEST, overscroll_mode());
}
+// Tests that if some scroll events are consumed towards the start, then
+// subsequent scrolls do not horizontal overscroll.
+// Disabled on MacOS because it doesn't support wheel gestures
+// just yet.
+#if defined(OS_MACOSX)
+#define MAYBE_WheelScrollConsumedDoNotHorizOverscrollWithWheelGestures \
+ DISABLED_WheelScrollConsumedDoNotHorizOverscrollWithWheelGestures
+#else
+#define MAYBE_WheelScrollConsumedDoNotHorizOverscrollWithWheelGestures \
+ WheelScrollConsumedDoNotHorizOverscrollWithWheelGestures
+#endif
+TEST_F(RenderWidgetHostViewAuraOverscrollTest,
+ MAYBE_WheelScrollConsumedDoNotHorizOverscrollWithWheelGestures) {
+ SetUpOverscrollEnvironmentWithWheelGestures();
+
+ // Simulate wheel events.
+ SimulateWheelEvent(-5, 0, 0, true); // sent directly
+ SimulateWheelEvent(-1, -1, 0, true); // enqueued
+ SimulateWheelEvent(-10, -3, 0, true); // coalesced into previous event
+ SimulateWheelEvent(-15, -1, 0, true); // coalesced into previous event
+ SimulateWheelEvent(-30, -3, 0, true); // coalesced into previous event
+ SimulateWheelEvent(-20, 6, 1, true); // enqueued, different modifiers
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+
+ // Receive ACK the first wheel event as processed.
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ // ScrollBegin, ScrollUpdate, MouseWheel will be queued events
+ EXPECT_EQ(3U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
+
+ // Receive ACK for the second (coalesced) event as not processed. This should
+ // not initiate overscroll, since the beginning of the scroll has been
+ // consumed. The queued event with different modifiers should be sent to the
+ // renderer.
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ // ScrollUpdate, MouseWheel will be queued events
+ EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ // ScrollUpdate will be queued events
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ EXPECT_EQ(0U, sink_->message_count());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+}
+
// Tests that wheel-scrolling correctly turns overscroll on and off.
TEST_F(RenderWidgetHostViewAuraOverscrollTest, WheelScrollOverscrollToggle) {
SetUpOverscrollEnvironment();
@@ -2701,6 +2905,95 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, WheelScrollOverscrollToggle) {
EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
}
+// Tests that wheel-scrolling correctly turns overscroll on and off.
+// Disabled on MacOS because it doesn't support wheel gestures
+// just yet.
+#if defined(OS_MACOSX)
+#define MAYBE_WheelScrollOverscrollToggleWithWheelGestures \
+ DISABLED_WheelScrollOverscrollToggleWithWheelGestures
+#else
+#define MAYBE_WheelScrollOverscrollToggleWithWheelGestures \
+ WheelScrollOverscrollToggleWithWheelGestures
+#endif
+TEST_F(RenderWidgetHostViewAuraOverscrollTest,
+ MAYBE_WheelScrollOverscrollToggleWithWheelGestures) {
+ SetUpOverscrollEnvironmentWithWheelGestures();
+
+ // Send a wheel event. ACK the event as not processed. This should not
+ // initiate an overscroll gesture since it doesn't cross the threshold yet.
+ SimulateWheelEvent(10, 0, 0, true);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
+
+ // Scroll some more so as to not overscroll.
+ SimulateWheelEvent(10, 0, 0, true);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
+
+ // Scroll some more to initiate an overscroll.
+ SimulateWheelEvent(40, 0, 0, true);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(OVERSCROLL_EAST, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->current_mode());
+ EXPECT_EQ(60.f, overscroll_delta_x());
+ EXPECT_EQ(10.f, overscroll_delegate()->delta_x());
+ EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
+
+ // Scroll in the reverse direction enough to abort the overscroll.
+ SimulateWheelEvent(-20, 0, 0, true);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, sink_->message_count());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
+
+ // Continue to scroll in the reverse direction.
+ SimulateWheelEvent(-20, 0, 0, true);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
+
+ // Continue to scroll in the reverse direction enough to initiate overscroll
+ // in that direction.
+ SimulateWheelEvent(-55, 0, 0, true);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(OVERSCROLL_WEST, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_WEST, overscroll_delegate()->current_mode());
+ EXPECT_EQ(-75.f, overscroll_delta_x());
+ EXPECT_EQ(-25.f, overscroll_delegate()->delta_x());
+ EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
+}
+
TEST_F(RenderWidgetHostViewAuraOverscrollTest,
ScrollEventsOverscrollWithFling) {
SetUpOverscrollEnvironment();
@@ -2744,6 +3037,68 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
EXPECT_EQ(2U, sink_->message_count());
}
+// Disabled on MacOS because it doesn't support wheel gestures
+// just yet.
+#if defined(OS_MACOSX)
+#define MAYBE_ScrollEventsOverscrollWithFlingAndWheelGestures \
+ DISABLED_ScrollEventsOverscrollWithFlingAndWheelGestures
+#else
+#define MAYBE_ScrollEventsOverscrollWithFlingAndWheelGestures \
+ ScrollEventsOverscrollWithFlingAndWheelGestures
+#endif
+TEST_F(RenderWidgetHostViewAuraOverscrollTest,
+ MAYBE_ScrollEventsOverscrollWithFlingAndWheelGestures) {
+ SetUpOverscrollEnvironmentWithWheelGestures();
+
+ // Send a wheel event. ACK the event as not processed. This should not
+ // initiate an overscroll gesture since it doesn't cross the threshold yet.
+ SimulateWheelEvent(10, 0, 0, true);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+
+ // Scroll some more so as to not overscroll.
+ SimulateWheelEvent(20, 0, 0, true);
+ EXPECT_EQ(1U, sink_->message_count());
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
+ sink_->ClearMessages();
+
+ // Scroll some more to initiate an overscroll.
+ SimulateWheelEvent(30, 0, 0, true);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(OVERSCROLL_EAST, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->current_mode());
+ EXPECT_EQ(60.f, overscroll_delta_x());
+ EXPECT_EQ(10.f, overscroll_delegate()->delta_x());
+ EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+
+ // Send a fling start, but with a small velocity, so that the overscroll is
+ // aborted. The fling should proceed to the renderer, through the gesture
+ // event filter.
+ SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
+ blink::WebGestureDeviceTouchscreen);
+ SimulateGestureFlingStartEvent(0.f, 0.1f, blink::WebGestureDeviceTouchpad);
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(3U, sink_->message_count());
+}
+
// Same as ScrollEventsOverscrollWithFling, but with zero velocity. Checks that
// the zero-velocity fling does not reach the renderer.
TEST_F(RenderWidgetHostViewAuraOverscrollTest,
@@ -2788,6 +3143,70 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
EXPECT_EQ(2U, sink_->message_count());
}
+// Same as ScrollEventsOverscrollWithFling, but with zero velocity. Checks that
+// the zero-velocity fling does not reach the renderer.
+// Disabled on MacOS because it doesn't support wheel gestures
+// just yet.
+#if defined(OS_MACOSX)
+#define MAYBE_ScrollEventsOverscrollWithZeroFlingAndWheelGestures \
+ DISABLED_ScrollEventsOverscrollWithZeroFlingAndWheelGestures
+#else
+#define MAYBE_ScrollEventsOverscrollWithZeroFlingAndWheelGestures \
+ ScrollEventsOverscrollWithZeroFlingAndWheelGestures
+#endif
+TEST_F(RenderWidgetHostViewAuraOverscrollTest,
+ MAYBE_ScrollEventsOverscrollWithZeroFlingAndWheelGestures) {
+ SetUpOverscrollEnvironmentWithWheelGestures();
+
+ // Send a wheel event. ACK the event as not processed. This should not
+ // initiate an overscroll gesture since it doesn't cross the threshold yet.
+ SimulateWheelEvent(10, 0, 0, true);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+
+ // Scroll some more so as to not overscroll.
+ SimulateWheelEvent(20, 0, 0, true);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
+
+ // Scroll some more to initiate an overscroll.
+ SimulateWheelEvent(30, 0, 0, true);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(OVERSCROLL_EAST, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->current_mode());
+ EXPECT_EQ(60.f, overscroll_delta_x());
+ EXPECT_EQ(10.f, overscroll_delegate()->delta_x());
+ EXPECT_EQ(0.f, overscroll_delegate()->delta_y());
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+
+ // Send a fling start, but with a small velocity, so that the overscroll is
+ // aborted. The fling should proceed to the renderer, through the gesture
+ // event filter.
+ SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
+ blink::WebGestureDeviceTouchscreen);
+ SimulateGestureFlingStartEvent(10.f, 0.f, blink::WebGestureDeviceTouchpad);
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(3U, sink_->message_count());
+}
+
// Tests that a fling in the opposite direction of the overscroll cancels the
// overscroll nav instead of completing it.
TEST_F(RenderWidgetHostViewAuraOverscrollTest, ReverseFlingCancelsOverscroll) {
@@ -3260,6 +3679,61 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
}
+// Disabled on MacOS because it doesn't support wheel gestures
+// just yet.
+#if defined(OS_MACOSX)
+#define MAYBE_OverscrollDirectionChangeMouseWheelWithWheelGestures \
+ DISABLED_OverscrollDirectionChangeMouseWheelWithWheelGestures
+#else
+#define MAYBE_OverscrollDirectionChangeMouseWheelWithWheelGestures \
+ OverscrollDirectionChangeMouseWheelWithWheelGestures
+#endif
+TEST_F(RenderWidgetHostViewAuraOverscrollTest,
+ MAYBE_OverscrollDirectionChangeMouseWheelWithWheelGestures) {
+ SetUpOverscrollEnvironmentWithWheelGestures();
+
+ // Send wheel event and receive ack as not consumed.
+ SimulateWheelEvent(125, -5, 0, true);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ // ScrollBegin, ScrollUpdate messages.
+ EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(OVERSCROLL_EAST, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->current_mode());
+
+ // Send another wheel event, but in the reverse direction. The overscroll
+ // controller will not consume the event, because it is not triggering
+ // gesture-nav.
+
+ SimulateWheelEvent(-260, 0, 0, true);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ // Since it was unhandled; the overscroll should now be west
+ EXPECT_EQ(OVERSCROLL_WEST, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_WEST, overscroll_delegate()->current_mode());
+
+ SimulateWheelEvent(-20, 0, 0, true);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ // wheel event ack generates gesture scroll update; which gets consumed
+ // solely by the overflow controller.
+ EXPECT_EQ(0U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(OVERSCROLL_WEST, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_WEST, overscroll_delegate()->current_mode());
+}
+
// Tests that if a mouse-move event completes the overscroll gesture, future
// move events do reach the renderer.
TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollMouseMoveCompletion) {
@@ -3340,6 +3814,101 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, OverscrollMouseMoveCompletion) {
INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
}
+// Tests that if a mouse-move event completes the overscroll gesture, future
+// move events do reach the renderer.
+// Disabled on MacOS because it doesn't support wheel gestures
+// just yet.
+#if defined(OS_MACOSX)
+#define MAYBE_OverscrollMouseMoveCompletionWheelGestures \
+ DISABLED_OverscrollMouseMoveCompletionWheelGestures
+#else
+#define MAYBE_OverscrollMouseMoveCompletionWheelGestures \
+ OverscrollMouseMoveCompletionWheelGestures
+#endif
+TEST_F(RenderWidgetHostViewAuraOverscrollTest,
+ MAYBE_OverscrollMouseMoveCompletionWheelGestures) {
+ SetUpOverscrollEnvironmentWithWheelGestures();
+
+ SimulateWheelEvent(5, 0, 0, true); // sent directly
+ SimulateWheelEvent(-1, 0, 0, true); // enqueued
+ SimulateWheelEvent(-10, -3, 0, true); // coalesced into previous event
+ SimulateWheelEvent(-15, -1, 0, true); // coalesced into previous event
+ SimulateWheelEvent(-30, -3, 0, true); // coalesced into previous event
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+
+ // Receive ACK the first wheel event as not processed.
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(3U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
+
+ // Receive ACK for the second (coalesced) event as not processed. This will
+ // start an overcroll gesture.
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(OVERSCROLL_WEST, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_WEST, overscroll_delegate()->current_mode());
+ EXPECT_EQ(0U, sink_->message_count());
+
+ // Send a mouse-move event. This should cancel the overscroll navigation
+ // (since the amount overscrolled is not above the threshold), and so the
+ // mouse-move should reach the renderer.
+ SimulateMouseMove(5, 10, 0);
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->completed_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+
+ SendInputEventACK(WebInputEvent::MouseMove,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ // Moving the mouse more should continue to send the events to the renderer.
+ SimulateMouseMove(5, 10, 0);
+ SendInputEventACK(WebInputEvent::MouseMove,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+
+ // Now try with gestures.
+ SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
+ blink::WebGestureDeviceTouchscreen);
+ SimulateGestureScrollUpdateEvent(300, -5, 0);
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(OVERSCROLL_EAST, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->current_mode());
+ sink_->ClearMessages();
+
+ // Overscroll gesture is in progress. Send a mouse-move now. This should
+ // complete the gesture (because the amount overscrolled is above the
+ // threshold).
+ SimulateMouseMove(5, 10, 0);
+ EXPECT_EQ(OVERSCROLL_EAST, overscroll_delegate()->completed_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+ SendInputEventACK(WebInputEvent::MouseMove,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ SimulateGestureEvent(WebInputEvent::GestureScrollEnd,
+ blink::WebGestureDeviceTouchscreen);
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_delegate()->current_mode());
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+
+ // Move mouse some more. The mouse-move events should reach the renderer.
+ SimulateMouseMove(5, 10, 0);
+ EXPECT_EQ(1U, GetSentMessageCountAndResetSink());
+
+ SendInputEventACK(WebInputEvent::MouseMove,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+}
+
// Tests that if a page scrolled, then the overscroll controller's states are
// reset after the end of the scroll.
TEST_F(RenderWidgetHostViewAuraOverscrollTest,
@@ -3374,11 +3943,14 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest,
// consumed and have triggered a fling animation (as tracked by the router).
EXPECT_FALSE(parent_host_->input_router()->HasPendingEvents());
+ SimulateGestureEvent(WebInputEvent::GestureScrollEnd,
+ blink::WebGestureDeviceTouchscreen);
+
SimulateWheelEvent(-5, 0, 0, true); // sent directly
SimulateWheelEvent(-60, 0, 0, true); // enqueued
SimulateWheelEvent(-100, 0, 0, true); // coalesced into previous event
EXPECT_TRUE(ScrollStateIsUnknown());
- EXPECT_EQ(2U, GetSentMessageCountAndResetSink());
+ EXPECT_EQ(3U, GetSentMessageCountAndResetSink());
// The first wheel scroll did not scroll content. Overscroll should not start
// yet, since enough hasn't been scrolled.
@@ -3496,7 +4068,7 @@ TEST_F(RenderWidgetHostViewAuraTest, KeyEvent) {
ui::EF_NONE);
view_->OnKeyEvent(&key_event);
- const NativeWebKeyboardEvent* event = delegate_.last_event();
+ const NativeWebKeyboardEvent* event = delegates_.back()->last_event();
EXPECT_NE(nullptr, event);
if (event) {
EXPECT_EQ(key_event.key_code(), event->windowsKeyCode);
@@ -3627,6 +4199,112 @@ TEST_F(RenderWidgetHostViewAuraOverscrollTest, ScrollDeltasResetOnEnd) {
EXPECT_EQ(0.f, overscroll_delta_y());
}
+// Tests that the scroll deltas stored within the overscroll controller get
+// reset at the end of the overscroll gesture even if the overscroll threshold
+// isn't surpassed and the overscroll mode stays OVERSCROLL_NONE.
+// Disabled on MacOS because it doesn't support wheel gestures
+// just yet.
+#if defined(OS_MACOSX)
+#define MAYBE_ScrollDeltasResetOnEndWithWheelGestures \
+ DISABLED_ScrollDeltasResetOnEndWithWheelGestures
+#else
+#define MAYBE_ScrollDeltasResetOnEndWithWheelGestures \
+ ScrollDeltasResetOnEndWithWheelGestures
+#endif
+TEST_F(RenderWidgetHostViewAuraOverscrollTest,
+ MAYBE_ScrollDeltasResetOnEndWithWheelGestures) {
+ SetUpOverscrollEnvironmentWithWheelGestures();
+ // Wheel event scroll ending with mouse move.
+ SimulateWheelEvent(-30, -10, 0, true); // sent directly
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(-30.f, overscroll_delta_x());
+ EXPECT_EQ(-10.f, overscroll_delta_y());
+ SimulateMouseMove(5, 10, 0);
+ EXPECT_EQ(0.f, overscroll_delta_x());
+ EXPECT_EQ(0.f, overscroll_delta_y());
+
+ // Scroll gesture.
+ SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
+ blink::WebGestureDeviceTouchscreen);
+ SimulateGestureScrollUpdateEvent(-30, -5, 0);
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(-30.f, overscroll_delta_x());
+ EXPECT_EQ(-5.f, overscroll_delta_y());
+ SimulateGestureEvent(WebInputEvent::GestureScrollEnd,
+ blink::WebGestureDeviceTouchscreen);
+ EXPECT_EQ(0.f, overscroll_delta_x());
+ EXPECT_EQ(0.f, overscroll_delta_y());
+
+ // Wheel event scroll ending with a fling.
+ SimulateWheelEvent(5, 0, 0, true);
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ SimulateWheelEvent(10, -5, 0, true);
+ SendInputEventACK(WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ SendInputEventACK(WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ EXPECT_EQ(OVERSCROLL_NONE, overscroll_mode());
+ EXPECT_EQ(15.f, overscroll_delta_x());
+ EXPECT_EQ(-5.f, overscroll_delta_y());
+ SimulateGestureEvent(WebInputEvent::GestureScrollBegin,
+ blink::WebGestureDeviceTouchscreen);
+ SimulateGestureFlingStartEvent(0.f, 0.1f, blink::WebGestureDeviceTouchpad);
+ EXPECT_EQ(0.f, overscroll_delta_x());
+ EXPECT_EQ(0.f, overscroll_delta_y());
+}
+
+TEST_F(RenderWidgetHostViewAuraTest, ForwardMouseEvent) {
+ aura::Window* root = parent_view_->GetNativeView()->GetRootWindow();
+
+ // Set up test delegate and window hierarchy.
+ aura::test::EventCountDelegate delegate;
+ scoped_ptr<aura::Window> parent(new aura::Window(&delegate));
+ parent->Init(ui::LAYER_TEXTURED);
+ root->AddChild(parent.get());
+ view_->InitAsChild(parent.get());
+
+ // Simulate mouse events, ensure they are forwarded to delegate.
+ ui::MouseEvent mouse_event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+ ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
+ 0);
+ view_->OnMouseEvent(&mouse_event);
+ EXPECT_EQ("1 0", delegate.GetMouseButtonCountsAndReset());
+
+ // Simulate mouse events, ensure they are forwarded to delegate.
+ mouse_event = ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(),
+ ui::EventTimeForNow(), 0, 0);
+ view_->OnMouseEvent(&mouse_event);
+ EXPECT_EQ("0 1 0", delegate.GetMouseMotionCountsAndReset());
+
+ // Lock the mouse, simulate, and ensure they are forwarded.
+ view_->LockMouse();
+
+ mouse_event =
+ ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+ ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0);
+ view_->OnMouseEvent(&mouse_event);
+ EXPECT_EQ("1 0", delegate.GetMouseButtonCountsAndReset());
+
+ mouse_event = ui::MouseEvent(ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(),
+ ui::EventTimeForNow(), 0, 0);
+ view_->OnMouseEvent(&mouse_event);
+ EXPECT_EQ("0 1 0", delegate.GetMouseMotionCountsAndReset());
+
+ view_->UnlockMouse();
+
+ // view_ will be destroyed when parent is destroyed.
+ view_ = nullptr;
+}
+
// Tests the RenderWidgetHostImpl sends the correct surface ID namespace to
// the renderer process.
TEST_F(RenderWidgetHostViewAuraTest, SurfaceIdNamespaceInitialized) {
@@ -3645,4 +4323,159 @@ TEST_F(RenderWidgetHostViewAuraTest, SurfaceIdNamespaceInitialized) {
EXPECT_EQ(view_->GetSurfaceIdNamespace(), base::get<0>(params));
}
+// This class provides functionality to test a RenderWidgetHostViewAura
+// instance which has been hooked up to a test RenderViewHost instance and
+// a WebContents instance.
+class RenderWidgetHostViewAuraWithViewHarnessTest
+ : public RenderViewHostImplTestHarness {
+ public:
+ RenderWidgetHostViewAuraWithViewHarnessTest()
+ : view_(nullptr) {}
+ ~RenderWidgetHostViewAuraWithViewHarnessTest() override {}
+
+ protected:
+ void SetUp() override {
+ ImageTransportFactory::InitializeForUnitTests(
+ scoped_ptr<ImageTransportFactory>(
+ new NoTransportImageTransportFactory));
+ RenderViewHostImplTestHarness::SetUp();
+ // Delete the current RenderWidgetHostView instance before setting
+ // the RWHVA as the view.
+ delete contents()->GetRenderViewHost()->GetWidget()->GetView();
+ // This instance is destroyed in the TearDown method below.
+ view_ = new RenderWidgetHostViewAura(
+ contents()->GetRenderViewHost()->GetWidget(),
+ false);
+ }
+
+ void TearDown() override {
+ view_->Destroy();
+ RenderViewHostImplTestHarness::TearDown();
+ ImageTransportFactory::Terminate();
+ }
+
+ RenderWidgetHostViewAura* view() {
+ return view_;
+ }
+
+ private:
+ RenderWidgetHostViewAura* view_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewAuraWithViewHarnessTest);
+};
+
+// Provides a mock implementation of the WebContentsViewDelegate class.
+// Currently provides functionality to validate the ShowContextMenu
+// callback.
+class MockWebContentsViewDelegate : public WebContentsViewDelegate {
+ public:
+ MockWebContentsViewDelegate()
+ : context_menu_request_received_(false) {}
+
+ ~MockWebContentsViewDelegate() override {}
+
+ bool context_menu_request_received() const {
+ return context_menu_request_received_;
+ }
+
+ ui::MenuSourceType context_menu_source_type() const {
+ return context_menu_params_.source_type;
+ }
+
+ // WebContentsViewDelegate overrides.
+ void ShowContextMenu(RenderFrameHost* render_frame_host,
+ const ContextMenuParams& params) override {
+ context_menu_request_received_ = true;
+ context_menu_params_ = params;
+ }
+
+ void ClearState() {
+ context_menu_request_received_ = false;
+ context_menu_params_.source_type = ui::MENU_SOURCE_NONE;
+ }
+
+ private:
+ bool context_menu_request_received_;
+ ContextMenuParams context_menu_params_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockWebContentsViewDelegate);
+};
+
+// On Windows we don't want the context menu to be displayed in the context of
+// a long press gesture. It should be displayed when the touch is released.
+// On other platforms we should display the context menu in the long press
+// gesture.
+// This test validates this behavior.
+TEST_F(RenderWidgetHostViewAuraWithViewHarnessTest,
+ ContextMenuTest) {
+ // This instance will be destroyed when the WebContents instance is
+ // destroyed.
+ MockWebContentsViewDelegate* delegate = new MockWebContentsViewDelegate;
+ static_cast<WebContentsViewAura*>(
+ contents()->GetView())->SetDelegateForTesting(delegate);
+
+ RenderViewHostFactory::set_is_real_render_view_host(true);
+
+ // A context menu request with the MENU_SOURCE_MOUSE source type should
+ // result in the MockWebContentsViewDelegate::ShowContextMenu method
+ // getting called. This means that the request worked correctly.
+ ContextMenuParams context_menu_params;
+ context_menu_params.source_type = ui::MENU_SOURCE_MOUSE;
+ contents()->ShowContextMenu(contents()->GetRenderViewHost()->GetMainFrame(),
+ context_menu_params);
+ EXPECT_TRUE(delegate->context_menu_request_received());
+ EXPECT_EQ(delegate->context_menu_source_type(), ui::MENU_SOURCE_MOUSE);
+
+ // A context menu request with the MENU_SOURCE_TOUCH source type should
+ // result in the MockWebContentsViewDelegate::ShowContextMenu method
+ // getting called on all platforms. This means that the request worked
+ // correctly.
+ delegate->ClearState();
+ context_menu_params.source_type = ui::MENU_SOURCE_TOUCH;
+ contents()->ShowContextMenu(contents()->GetRenderViewHost()->GetMainFrame(),
+ context_menu_params);
+ EXPECT_TRUE(delegate->context_menu_request_received());
+
+ // A context menu request with the MENU_SOURCE_LONG_TAP source type should
+ // result in the MockWebContentsViewDelegate::ShowContextMenu method
+ // getting called on all platforms. This means that the request worked
+ // correctly.
+ delegate->ClearState();
+ context_menu_params.source_type = ui::MENU_SOURCE_LONG_TAP;
+ contents()->ShowContextMenu(contents()->GetRenderViewHost()->GetMainFrame(),
+ context_menu_params);
+ EXPECT_TRUE(delegate->context_menu_request_received());
+
+ // A context menu request with the MENU_SOURCE_LONG_PRESS source type should
+ // result in the MockWebContentsViewDelegate::ShowContextMenu method
+ // getting called on non Windows platforms. This means that the request
+ // worked correctly. On Windows this should be blocked.
+ delegate->ClearState();
+ context_menu_params.source_type = ui::MENU_SOURCE_LONG_PRESS;
+ contents()->ShowContextMenu(contents()->GetRenderViewHost()->GetMainFrame(),
+ context_menu_params);
+#if defined(OS_WIN)
+ EXPECT_FALSE(delegate->context_menu_request_received());
+#else
+ EXPECT_TRUE(delegate->context_menu_request_received());
+#endif
+
+#if defined(OS_WIN)
+ // On Windows the context menu request blocked above should be received when
+ // the ET_GESTURE_LONG_TAP gesture is sent to the RenderWidgetHostViewAura
+ // instance. This means that the touch was released.
+ delegate->ClearState();
+
+ ui::GestureEventDetails event_details(ui::ET_GESTURE_LONG_TAP);
+ ui::GestureEvent gesture_event(
+ 100, 100, 0, ui::EventTimeForNow(), event_details);
+ view()->OnGestureEvent(&gesture_event);
+
+ EXPECT_TRUE(delegate->context_menu_request_received());
+ EXPECT_EQ(delegate->context_menu_source_type(), ui::MENU_SOURCE_TOUCH);
+#endif
+
+ RenderViewHostFactory::set_is_real_render_view_host(false);
+}
+
} // 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 a2a0884d005..d7e3d00af10 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
@@ -10,354 +10,19 @@
#include "content/browser/gpu/gpu_data_manager_impl.h"
#include "content/browser/renderer_host/input/synthetic_gesture_target_base.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/renderer_host/render_widget_host_view_base_observer.h"
#include "content/common/content_switches_internal.h"
#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
#include "ui/gfx/display.h"
+#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/geometry/size_f.h"
#include "ui/gfx/screen.h"
-#if defined(OS_WIN)
-#include "base/command_line.h"
-#include "base/message_loop/message_loop.h"
-#include "base/win/wrapped_window_proc.h"
-#include "content/browser/plugin_process_host.h"
-#include "content/browser/plugin_service_impl.h"
-#include "content/common/plugin_constants_win.h"
-#include "content/common/webplugin_geometry.h"
-#include "content/public/browser/browser_thread.h"
-#include "content/public/browser/child_process_data.h"
-#include "content/public/common/content_switches.h"
-#include "ui/gfx/gdi_util.h"
-#include "ui/gfx/win/dpi.h"
-#include "ui/gfx/win/hwnd_util.h"
-#endif
-
namespace content {
-#if defined(OS_WIN)
-
-namespace {
-
-// |window| is the plugin HWND, created and destroyed in the plugin process.
-// |parent| is the parent HWND, created and destroyed on the browser UI thread.
-void NotifyPluginProcessHostHelper(HWND window, HWND parent, int tries) {
- // How long to wait between each try.
- static const int kTryDelayMs = 200;
-
- DWORD plugin_process_id;
- bool found_starting_plugin_process = false;
- GetWindowThreadProcessId(window, &plugin_process_id);
- for (PluginProcessHostIterator iter; !iter.Done(); ++iter) {
- if (!iter.GetData().handle) {
- found_starting_plugin_process = true;
- continue;
- }
- if (base::GetProcId(iter.GetData().handle) == plugin_process_id) {
- iter->AddWindow(parent);
- return;
- }
- }
-
- if (found_starting_plugin_process) {
- // A plugin process has started but we don't have its handle yet. Since
- // it's most likely the one for this plugin, try a few more times after a
- // delay.
- if (tries > 0) {
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&NotifyPluginProcessHostHelper, window, parent, tries - 1),
- base::TimeDelta::FromMilliseconds(kTryDelayMs));
- return;
- }
- }
-
- // The plugin process might have died in the time to execute the task, don't
- // leak the HWND.
- PostMessage(parent, WM_CLOSE, 0, 0);
-}
-
-// The plugin wrapper window which lives in the browser process has this proc
-// as its window procedure. We only handle the WM_PARENTNOTIFY message sent by
-// windowed plugins for mouse input. This is forwarded off to the wrappers
-// parent which is typically the RVH window which turns on user gesture.
-LRESULT CALLBACK PluginWrapperWindowProc(HWND window, unsigned int message,
- WPARAM wparam, LPARAM lparam) {
- if (message == WM_PARENTNOTIFY) {
- switch (LOWORD(wparam)) {
- case WM_LBUTTONDOWN:
- case WM_RBUTTONDOWN:
- case WM_MBUTTONDOWN:
- ::SendMessage(GetParent(window), message, wparam, lparam);
- return 0;
- default:
- break;
- }
- }
- return ::DefWindowProc(window, message, wparam, lparam);
-}
-
-bool IsPluginWrapperWindow(HWND window) {
- return gfx::GetClassNameW(window) ==
- base::string16(kWrapperNativeWindowClassName);
-}
-
-// Create an intermediate window between the given HWND and its parent.
-HWND ReparentWindow(HWND window, HWND parent) {
- static ATOM atom = 0;
- static HMODULE instance = NULL;
- if (!atom) {
- WNDCLASSEX window_class;
- base::win::InitializeWindowClass(
- kWrapperNativeWindowClassName,
- &base::win::WrappedWindowProc<PluginWrapperWindowProc>,
- CS_DBLCLKS,
- 0,
- 0,
- NULL,
- // xxx reinterpret_cast<HBRUSH>(COLOR_WINDOW+1),
- reinterpret_cast<HBRUSH>(COLOR_GRAYTEXT+1),
- NULL,
- NULL,
- NULL,
- &window_class);
- instance = window_class.hInstance;
- atom = RegisterClassEx(&window_class);
- }
- DCHECK(atom);
-
- HWND new_parent = CreateWindowEx(
- WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR,
- MAKEINTATOM(atom), 0,
- WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
- 0, 0, 0, 0, parent, 0, instance, 0);
- gfx::CheckWindowCreated(new_parent);
- ::SetParent(window, new_parent);
- // How many times we try to find a PluginProcessHost whose process matches
- // the HWND.
- static const int kMaxTries = 5;
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&NotifyPluginProcessHostHelper, window, new_parent,
- kMaxTries));
- return new_parent;
-}
-
-BOOL CALLBACK PaintEnumChildProc(HWND hwnd, LPARAM lparam) {
- if (!PluginServiceImpl::GetInstance()->IsPluginWindow(hwnd))
- return TRUE;
-
- gfx::Rect* rect = reinterpret_cast<gfx::Rect*>(lparam);
- 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());
-
- // SendMessage gets the message across much quicker than PostMessage, since it
- // doesn't get queued. When the plugin thread calls PeekMessage or other
- // Win32 APIs, sent messages are dispatched automatically.
- SendNotifyMessage(hwnd, msg, wparam, lparam);
-
- return TRUE;
-}
-
-// Windows callback for OnDestroy to detach the plugin windows.
-BOOL CALLBACK DetachPluginWindowsCallbackInternal(HWND window, LPARAM param) {
- RenderWidgetHostViewBase::DetachPluginWindowsCallback(window);
- return TRUE;
-}
-
-} // namespace
-
-// static
-void RenderWidgetHostViewBase::DetachPluginWindowsCallback(HWND window) {
- if (PluginServiceImpl::GetInstance()->IsPluginWindow(window) &&
- !IsHungAppWindow(window)) {
- ::ShowWindow(window, SW_HIDE);
- SetParent(window, NULL);
- }
-}
-
-// static
-void RenderWidgetHostViewBase::MovePluginWindowsHelper(
- HWND parent,
- const std::vector<WebPluginGeometry>& moves) {
- if (moves.empty())
- return;
-
- bool oop_plugins = !base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kSingleProcess);
-
- HDWP defer_window_pos_info =
- ::BeginDeferWindowPos(static_cast<int>(moves.size()));
-
- if (!defer_window_pos_info) {
- NOTREACHED();
- return;
- }
-
-#if defined(USE_AURA)
- std::vector<RECT> invalidate_rects;
-#endif
-
- for (size_t i = 0; i < moves.size(); ++i) {
- unsigned long flags = 0;
- const WebPluginGeometry& move = moves[i];
- HWND window = move.window;
-
- // As the plugin parent window which lives on the browser UI thread is
- // destroyed asynchronously, it is possible that we have a stale window
- // sent in by the renderer for moving around.
- // Note: get the parent before checking if the window is valid, to avoid a
- // race condition where the window is destroyed after the check but before
- // the GetParent call.
- HWND cur_parent = ::GetParent(window);
- if (!::IsWindow(window))
- continue;
-
- if (!PluginServiceImpl::GetInstance()->IsPluginWindow(window)) {
- // The renderer should only be trying to move plugin windows. However,
- // this may happen as a result of a race condition (i.e. even after the
- // check right above), so we ignore it.
- continue;
- }
-
- if (oop_plugins) {
- if (cur_parent == GetDesktopWindow()) {
- // The plugin window hasn't been parented yet, add an intermediate
- // window that lives on this thread to speed up scrolling. Note this
- // only works with out of process plugins since we depend on
- // PluginProcessHost to destroy the intermediate HWNDs.
- cur_parent = ReparentWindow(window, parent);
- ::ShowWindow(window, SW_SHOW); // Window was created hidden.
- } else if (!IsPluginWrapperWindow(cur_parent)) {
- continue; // Race if plugin process is shutting down.
- }
-
- // We move the intermediate parent window which doesn't result in cross-
- // process synchronous Windows messages.
- window = cur_parent;
- } else {
- if (cur_parent == GetDesktopWindow())
- SetParent(window, parent);
- }
-
- if (move.visible)
- flags |= SWP_SHOWWINDOW;
- else
- flags |= SWP_HIDEWINDOW;
-
-#if defined(USE_AURA)
- if (GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor()) {
- // Without this flag, Windows repaints the parent area uncovered by this
- // move. However when software compositing is used the clipping region is
- // ignored. Since in Aura the browser chrome could be under the plugin, if
- // if Windows tries to paint it synchronously inside EndDeferWindowsPos
- // then it won't have the data and it will flash white. So instead we
- // manually redraw the plugin.
- // Why not do this for native Windows? Not sure if there are any
- // performance issues with this.
- flags |= SWP_NOREDRAW;
- }
-#endif
-
- if (move.rects_valid) {
- 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(),
- clip_rect_in_pixel.bottom());
- gfx::SubtractRectanglesFromRegion(hrgn, move.cutout_rects);
-
- // Note: System will own the hrgn after we call SetWindowRgn,
- // so we don't need to call DeleteObject(hrgn)
- ::SetWindowRgn(window, hrgn,
- !move.clip_rect.IsEmpty() && (flags & SWP_NOREDRAW) == 0);
-
-#if defined(USE_AURA)
- // When using the software compositor, if the clipping rectangle is empty
- // then DeferWindowPos won't redraw the newly uncovered area under the
- // plugin.
- if (clip_rect_in_pixel.IsEmpty() &&
- !GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor()) {
- RECT r;
- GetClientRect(window, &r);
- MapWindowPoints(window, parent, reinterpret_cast<POINT*>(&r), 2);
- invalidate_rects.push_back(r);
- }
-#endif
- } else {
- flags |= SWP_NOMOVE;
- flags |= SWP_NOSIZE;
- }
-
- gfx::Rect window_rect_in_pixel =
- gfx::win::DIPToScreenRect(move.window_rect);
- defer_window_pos_info = ::DeferWindowPos(defer_window_pos_info,
- window, NULL,
- window_rect_in_pixel.x(),
- window_rect_in_pixel.y(),
- window_rect_in_pixel.width(),
- window_rect_in_pixel.height(),
- flags);
-
- if (!defer_window_pos_info) {
- DCHECK(false) << "DeferWindowPos failed, so all plugin moves ignored.";
- return;
- }
- }
-
- ::EndDeferWindowPos(defer_window_pos_info);
-
-#if defined(USE_AURA)
- if (GpuDataManagerImpl::GetInstance()->CanUseGpuBrowserCompositor()) {
- for (size_t i = 0; i < moves.size(); ++i) {
- const WebPluginGeometry& move = moves[i];
- RECT r;
- GetWindowRect(move.window, &r);
- gfx::Rect gr(r);
- PaintEnumChildProc(move.window, reinterpret_cast<LPARAM>(&gr));
- }
- } else {
- for (size_t i = 0; i < invalidate_rects.size(); ++i) {
- ::RedrawWindow(
- parent, &invalidate_rects[i], NULL,
- // These flags are from WebPluginDelegateImpl::NativeWndProc.
- RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_FRAME | RDW_UPDATENOW);
- }
- }
-#endif
-}
-
-// static
-void RenderWidgetHostViewBase::PaintPluginWindowsHelper(
- HWND parent, const gfx::Rect& damaged_screen_rect) {
- LPARAM lparam = reinterpret_cast<LPARAM>(&damaged_screen_rect);
- EnumChildWindows(parent, PaintEnumChildProc, lparam);
-}
-
-// static
-void RenderWidgetHostViewBase::DetachPluginsHelper(HWND parent) {
- // When a tab is closed all its child plugin windows are destroyed
- // automatically. This happens before plugins get any notification that its
- // instances are tearing down.
- //
- // Plugins like Quicktime assume that their windows will remain valid as long
- // as they have plugin instances active. Quicktime crashes in this case
- // because its windowing code cleans up an internal data structure that the
- // handler for NPP_DestroyStream relies on.
- //
- // The fix is to detach plugin windows from web contents when it is going
- // away. This will prevent the plugin windows from getting destroyed
- // automatically. The detached plugin windows will get cleaned up in proper
- // sequence as part of the usual cleanup when the plugin instance goes away.
- EnumChildWindows(parent, DetachPluginWindowsCallbackInternal, NULL);
-}
-
-#endif // OS_WIN
-
namespace {
// How many microseconds apart input events should be flushed.
@@ -376,11 +41,28 @@ RenderWidgetHostViewBase::RenderWidgetHostViewBase()
current_display_rotation_(gfx::Display::ROTATE_0),
pinch_zoom_enabled_(content::IsPinchToZoomEnabled()),
renderer_frame_number_(0),
- weak_factory_(this) {
-}
+ weak_factory_(this) {}
RenderWidgetHostViewBase::~RenderWidgetHostViewBase() {
DCHECK(!mouse_locked_);
+ // We call this here to guarantee that observers are notified before we go
+ // away. However, some subclasses may wish to call this earlier in their
+ // shutdown process, e.g. to force removal from
+ // RenderWidgetHostInputEventRouter's surface map before relinquishing a
+ // host pointer, as in RenderWidgetHostViewGuest. There is no harm in calling
+ // NotifyObserversAboutShutdown() twice, as the observers are required to
+ // de-register on the first call, and so the second call does nothing.
+ NotifyObserversAboutShutdown();
+}
+
+void RenderWidgetHostViewBase::NotifyObserversAboutShutdown() {
+ // Note: RenderWidgetHostInputEventRouter is an observer, and uses the
+ // following notification to remove this view from its surface owners map.
+ FOR_EACH_OBSERVER(RenderWidgetHostViewBaseObserver,
+ observers_,
+ OnRenderWidgetHostViewBaseDestroyed(this));
+ // All observers are required to disconnect after they are notified.
+ DCHECK(!observers_.might_have_observers());
}
bool RenderWidgetHostViewBase::OnMessageReceived(const IPC::Message& msg){
@@ -400,9 +82,8 @@ bool RenderWidgetHostViewBase::GetBackgroundOpaque() {
}
gfx::Size RenderWidgetHostViewBase::GetPhysicalBackingSize() const {
- gfx::NativeView view = GetNativeView();
gfx::Display display =
- gfx::Screen::GetScreenFor(view)->GetDisplayNearestWindow(view);
+ gfx::Screen::GetScreen()->GetDisplayNearestWindow(GetNativeView());
return gfx::ScaleToCeiledSize(GetRequestedRendererSize(),
display.device_scale_factor());
}
@@ -491,7 +172,7 @@ blink::WebPopupType RenderWidgetHostViewBase::GetPopupType() {
BrowserAccessibilityManager*
RenderWidgetHostViewBase::CreateBrowserAccessibilityManager(
- BrowserAccessibilityDelegate* delegate) {
+ BrowserAccessibilityDelegate* delegate, bool for_root_frame) {
NOTREACHED();
return NULL;
}
@@ -525,8 +206,8 @@ void RenderWidgetHostViewBase::UpdateScreenInfo(gfx::NativeView view) {
if (GetRenderWidgetHost())
impl = RenderWidgetHostImpl::From(GetRenderWidgetHost());
- if (impl)
- impl->SendScreenRects();
+ if (impl && impl->delegate())
+ impl->delegate()->SendScreenRects();
if (HasDisplayPropertyChanged(view) && impl)
impl->NotifyScreenInfoChanged();
@@ -534,7 +215,7 @@ void RenderWidgetHostViewBase::UpdateScreenInfo(gfx::NativeView view) {
bool RenderWidgetHostViewBase::HasDisplayPropertyChanged(gfx::NativeView view) {
gfx::Display display =
- gfx::Screen::GetScreenFor(view)->GetDisplayNearestWindow(view);
+ gfx::Screen::GetScreen()->GetDisplayNearestWindow(view);
if (current_display_area_ == display.work_area() &&
current_device_scale_factor_ == display.device_scale_factor() &&
current_display_rotation_ == display.rotation()) {
@@ -676,16 +357,22 @@ uint32_t RenderWidgetHostViewBase::GetSurfaceIdNamespace() {
}
uint32_t RenderWidgetHostViewBase::SurfaceIdNamespaceAtPoint(
+ cc::SurfaceHittestDelegate* delegate,
const gfx::Point& point,
gfx::Point* transformed_point) {
NOTREACHED();
return 0;
}
-void RenderWidgetHostViewBase::TransformPointToRootCoordSpace(
- const gfx::Point& point,
- gfx::Point* transformed_point) {
- *transformed_point = point;
+gfx::Point RenderWidgetHostViewBase::TransformPointToRootCoordSpace(
+ const gfx::Point& point) {
+ return point;
+}
+
+gfx::PointF RenderWidgetHostViewBase::TransformPointToRootCoordSpaceF(
+ const gfx::PointF& point) {
+ return gfx::PointF(TransformPointToRootCoordSpace(
+ gfx::ToRoundedPoint(point)));
}
void RenderWidgetHostViewBase::TransformPointToLocalCoordSpace(
@@ -695,4 +382,22 @@ void RenderWidgetHostViewBase::TransformPointToLocalCoordSpace(
*transformed_point = point;
}
+void RenderWidgetHostViewBase::AddObserver(
+ RenderWidgetHostViewBaseObserver* observer) {
+ observers_.AddObserver(observer);
+}
+
+void RenderWidgetHostViewBase::RemoveObserver(
+ RenderWidgetHostViewBaseObserver* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+bool RenderWidgetHostViewBase::IsChildFrameForTesting() const {
+ return false;
+}
+
+cc::SurfaceId RenderWidgetHostViewBase::SurfaceIdForTesting() const {
+ return cc::SurfaceId();
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_base.h b/chromium/content/browser/renderer_host/render_widget_host_view_base.h
index d714137a2d6..c6d15c1cc0e 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
@@ -14,10 +14,12 @@
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#include "base/observer_list.h"
#include "base/process/kill.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
#include "cc/output/compositor_frame.h"
+#include "cc/surfaces/surface_id.h"
#include "content/browser/renderer_host/event_with_latency_info.h"
#include "content/common/content_export.h"
#include "content/common/input/input_event_ack_state.h"
@@ -51,6 +53,10 @@ class WebMouseEvent;
class WebMouseWheelEvent;
}
+namespace cc {
+class SurfaceHittestDelegate;
+}
+
namespace ui {
class LatencyInfo;
}
@@ -58,12 +64,12 @@ class LatencyInfo;
namespace content {
class BrowserAccessibilityDelegate;
class BrowserAccessibilityManager;
+class RenderWidgetHostViewBaseObserver;
class SyntheticGesture;
class SyntheticGestureTarget;
class WebCursor;
struct DidOverscrollParams;
struct NativeWebKeyboardEvent;
-struct WebPluginGeometry;
// Basic implementation shared by concrete RenderWidgetHostView subclasses.
class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
@@ -71,6 +77,10 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
public:
~RenderWidgetHostViewBase() override;
+ float current_device_scale_factor() const {
+ return current_device_scale_factor_;
+ }
+
// RenderWidgetHostView implementation.
void SetBackgroundColor(SkColor color) override;
void SetBackgroundColorToDefault() final;
@@ -88,6 +98,12 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
scoped_ptr<RenderWidgetHostViewFrameSubscriber> subscriber) override;
void EndFrameSubscription() override;
+ // This only needs to be overridden by RenderWidgetHostViewBase subclasses
+ // that handle content embedded within other RenderWidgetHostViews.
+ gfx::Point TransformPointToRootCoordSpace(const gfx::Point& point) override;
+ gfx::PointF TransformPointToRootCoordSpaceF(
+ const gfx::PointF& point) override;
+
// IPC::Listener implementation:
bool OnMessageReceived(const IPC::Message& msg) override;
@@ -155,9 +171,12 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
// be used to inject synthetic input events.
virtual scoped_ptr<SyntheticGestureTarget> CreateSyntheticGestureTarget();
- // Create a BrowserAccessibilityManager for this view.
+ // Create a BrowserAccessibilityManager for a frame in this view.
+ // If |for_root_frame| is true, creates a BrowserAccessibilityManager
+ // suitable for the root frame, which may be linked to its native
+ // window container.
virtual BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
- BrowserAccessibilityDelegate* delegate);
+ BrowserAccessibilityDelegate* delegate, bool for_root_frame);
virtual void AccessibilityShowMenu(const gfx::Point& point);
virtual gfx::Point AccessibilityOriginInScreen(const gfx::Rect& bounds);
@@ -196,22 +215,17 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
// methods are invoked on the RenderWidgetHostView that should be able to
// properly handle the event (i.e. it has focus for keyboard events, or has
// been identified by hit testing mouse, touch or gesture events).
- virtual uint32_t SurfaceIdNamespaceAtPoint(const gfx::Point& point,
- gfx::Point* transformed_point);
+ virtual uint32_t SurfaceIdNamespaceAtPoint(
+ cc::SurfaceHittestDelegate* delegate,
+ const gfx::Point& point,
+ gfx::Point* transformed_point);
virtual void ProcessKeyboardEvent(const NativeWebKeyboardEvent& event) {}
virtual void ProcessMouseEvent(const blink::WebMouseEvent& event) {}
virtual void ProcessMouseWheelEvent(const blink::WebMouseWheelEvent& event) {}
virtual void ProcessTouchEvent(const blink::WebTouchEvent& event,
- const ui::LatencyInfo& latency) {}
-
- // If a RenderWidgetHost is dealing with points that are transformed from the
- // root frame for a page (i.e. because its content is contained within
- // that of another RenderWidgetHost), this provides a facility to convert
- // a point from its own coordinate space to that of the root frame.
- // This only needs to be overriden by RenderWidgetHostView subclasses
- // that handle content embedded within other RenderWidgetHostViews.
- virtual void TransformPointToRootCoordSpace(const gfx::Point& point,
- gfx::Point* transformed_point);
+ const ui::LatencyInfo& latency) {}
+ virtual void ProcessGestureEvent(const blink::WebGestureEvent& event,
+ const ui::LatencyInfo& latency) {}
// Transform a point that is in the coordinate space of a Surface that is
// embedded within the RenderWidgetHostViewBase's Surface to the
@@ -243,11 +257,6 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
// helps to position the full screen widget on the correct monitor.
virtual void InitAsFullscreen(RenderWidgetHostView* reference_host_view) = 0;
- // Moves all plugin windows as described in the given list.
- // |scroll_offset| is the scroll offset of the render view.
- virtual void MovePluginWindows(
- const std::vector<WebPluginGeometry>& moves) = 0;
-
// Sets the cursor to the one associated with the specified cursor_type
virtual void UpdateCursor(const WebCursor& cursor) = 0;
@@ -354,51 +363,26 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
virtual void LockCompositingSurface() = 0;
virtual void UnlockCompositingSurface() = 0;
-#if defined(OS_MACOSX)
- // Does any event handling necessary for plugin IME; should be called after
- // the plugin has already had a chance to process the event. If plugin IME is
- // not enabled, this is a no-op, so it is always safe to call.
- // Returns true if the event was handled by IME.
- virtual bool PostProcessEventForPluginIme(
- const NativeWebKeyboardEvent& event) = 0;
-#endif
-
// Updates the range of the marked text in an IME composition.
virtual void ImeCompositionRangeChanged(
const gfx::Range& range,
const std::vector<gfx::Rect>& character_bounds) = 0;
-#if defined(OS_WIN)
- virtual void SetParentNativeViewAccessible(
- gfx::NativeViewAccessible accessible_parent) = 0;
-
- // Returns an HWND that's given as the parent window for windowless Flash to
- // workaround crbug.com/301548.
- virtual gfx::NativeViewId GetParentForWindowlessPlugin() const = 0;
+ // Add and remove observers for lifetime event notifications. The order in
+ // which notifications are sent to observers is undefined. Clients must be
+ // sure to remove the observer before they go away.
+ void AddObserver(RenderWidgetHostViewBaseObserver* observer);
+ void RemoveObserver(RenderWidgetHostViewBaseObserver* observer);
- // The callback that DetachPluginsHelper calls for each child window. Call
- // this directly if you want to do custom filtering on plugin windows first.
- static void DetachPluginWindowsCallback(HWND window);
-#endif
+ // Exposed for testing.
+ virtual bool IsChildFrameForTesting() const;
+ virtual cc::SurfaceId SurfaceIdForTesting() const;
protected:
// Interface class only, do not construct.
RenderWidgetHostViewBase();
-#if defined(OS_WIN)
- // Shared implementation of MovePluginWindows for use by win and aura/wina.
- static void MovePluginWindowsHelper(
- HWND parent,
- const std::vector<WebPluginGeometry>& moves);
-
- static void PaintPluginWindowsHelper(
- HWND parent,
- const gfx::Rect& damaged_screen_rect);
-
- // Needs to be called before the HWND backing the view goes away to avoid
- // crashes in Windowed plugins.
- static void DetachPluginsHelper(HWND parent);
-#endif
+ void NotifyObserversAboutShutdown();
// Whether this view is a popup and what kind of popup it is (select,
// autofill...).
@@ -447,6 +431,8 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView,
base::OneShotTimer flush_input_timer_;
+ base::ObserverList<RenderWidgetHostViewBaseObserver> observers_;
+
base::WeakPtrFactory<RenderWidgetHostViewBase> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewBase);
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_base_observer.cc b/chromium/content/browser/renderer_host/render_widget_host_view_base_observer.cc
new file mode 100644
index 00000000000..92f1247d12f
--- /dev/null
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_base_observer.cc
@@ -0,0 +1,14 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/render_widget_host_view_base_observer.h"
+
+namespace content {
+
+RenderWidgetHostViewBaseObserver::~RenderWidgetHostViewBaseObserver() {}
+
+void RenderWidgetHostViewBaseObserver::OnRenderWidgetHostViewBaseDestroyed(
+ RenderWidgetHostViewBase*) {}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_base_observer.h b/chromium/content/browser/renderer_host/render_widget_host_view_base_observer.h
new file mode 100644
index 00000000000..acd3882fc02
--- /dev/null
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_base_observer.h
@@ -0,0 +1,32 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_BASE_OBSERVER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_BASE_OBSERVER_H_
+
+#include "base/macros.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class RenderWidgetHostViewBase;
+
+class CONTENT_EXPORT RenderWidgetHostViewBaseObserver {
+ public:
+ // All derived classes must de-register as observers when receiving this
+ // notification.
+ virtual void OnRenderWidgetHostViewBaseDestroyed(
+ RenderWidgetHostViewBase* view);
+
+ protected:
+ RenderWidgetHostViewBaseObserver() = default;
+ virtual ~RenderWidgetHostViewBaseObserver();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostViewBaseObserver);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_RENDER_WIDGET_HOST_VIEW_BASE_OBSERVER_H_
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 d7f79a0b573..d1f1fbae2d0 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
@@ -276,9 +276,8 @@ class FakeFrameSubscriber : public RenderWidgetHostViewFrameSubscriber {
DeliverFrameCallback callback_;
};
-// Disable tests for Android and IOS as these platforms have incomplete
-// implementation.
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
+// Disable tests for Android as it has an incomplete implementation.
+#if !defined(OS_ANDROID)
// The CopyFromBackingStore() API should work on all platforms when compositing
// is enabled.
@@ -1005,7 +1004,7 @@ INSTANTIATE_TEST_CASE_P(
CompositingRenderWidgetHostViewBrowserTestTabCaptureHighDPI,
kTestCompositingModes);
-#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
+#endif // !defined(OS_ANDROID)
} // namespace
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mac.h b/chromium/content/browser/renderer_host/render_widget_host_view_mac.h
index 459f16a15bc..0c1b9a9c6e4 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
@@ -21,8 +21,9 @@
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
-#include "content/browser/compositor/browser_compositor_view_mac.h"
-#include "content/browser/compositor/delegated_frame_host.h"
+#include "cc/surfaces/surface_id.h"
+#include "content/browser/renderer_host/browser_compositor_view_mac.h"
+#include "content/browser/renderer_host/delegated_frame_host.h"
#include "content/browser/renderer_host/input/mouse_wheel_rails_filter_mac.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/common/content_export.h"
@@ -80,8 +81,6 @@ class Layer;
// Is YES if there was a mouse-down as yet unbalanced with a mouse-up.
BOOL hasOpenMouseDown_;
- NSWindow* lastWindow_; // weak
-
// The cursor for the page. This is passed up from the renderer.
base::scoped_nsobject<NSCursor> currentCursor_;
@@ -130,6 +129,9 @@ class Layer;
// Underline information of the |markedText_|.
std::vector<blink::WebCompositionUnderline> underlines_;
+ // Replacement range information received from |setMarkedText:|.
+ gfx::Range setMarkedTextReplacementRange_;
+
// Indicates if doCommandBySelector method receives any edit command when
// handling a key down event.
BOOL hasEditCommands_;
@@ -139,12 +141,6 @@ class Layer;
// etc.
content::EditCommands editCommands_;
- // The plugin that currently has focus (-1 if no plugin has focus).
- int focusedPluginIdentifier_;
-
- // Whether or not plugin IME is currently enabled active.
- BOOL pluginImeActive_;
-
// Whether the previous mouse event was ignored due to hitTest check.
BOOL mouseEventWasIgnored_;
@@ -200,13 +196,6 @@ class Layer;
- (void)cancelComposition;
// Confirm ongoing composition.
- (void)confirmComposition;
-// Enables or disables plugin IME.
-- (void)setPluginImeActive:(BOOL)active;
-// Updates the current plugin focus state.
-- (void)pluginFocusChanged:(BOOL)focused forPlugin:(int)pluginId;
-// Evaluates the event in the context of plugin IME, if plugin IME is enabled.
-// Returns YES if the event was handled.
-- (BOOL)postProcessEventForPluginIme:(NSEvent*)event;
- (void)updateCursor:(NSCursor*)cursor;
- (NSRect)firstViewRectForCharacterRange:(NSRange)theRange
actualRange:(NSRangePointer)actualRange;
@@ -281,8 +270,6 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
gfx::Rect GetViewBounds() const override;
void SetShowingContextMenu(bool showing) override;
void SetActive(bool active) override;
- void SetWindowVisibility(bool visible) override;
- void WindowFrameChanged() override;
void ShowDefinitionForSelection() override;
bool SupportsSpeech() const override;
void SpeakSelection() override;
@@ -294,7 +281,6 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
void InitAsPopup(RenderWidgetHostView* parent_host_view,
const gfx::Rect& pos) override;
void InitAsFullscreen(RenderWidgetHostView* reference_host_view) override;
- void MovePluginWindows(const std::vector<WebPluginGeometry>& moves) override;
void Focus() override;
void UpdateCursor(const WebCursor& cursor) override;
void SetIsLoading(bool is_loading) override;
@@ -329,10 +315,8 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
scoped_ptr<cc::CompositorFrame> frame) override;
void ClearCompositorFrame() override;
BrowserAccessibilityManager* CreateBrowserAccessibilityManager(
- BrowserAccessibilityDelegate* delegate) override;
+ BrowserAccessibilityDelegate* delegate, bool for_root_frame) override;
gfx::Point AccessibilityOriginInScreen(const gfx::Rect& bounds) override;
- bool PostProcessEventForPluginIme(
- const NativeWebKeyboardEvent& event) override;
bool HasAcceleratedSurface(const gfx::Size& desired_size) override;
void GetScreenInfo(blink::WebScreenInfo* results) override;
@@ -345,16 +329,23 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
void UnlockMouse() override;
void WheelEventAck(const blink::WebMouseWheelEvent& event,
InputEventAckState ack_result) override;
+ void GestureEventAck(const blink::WebGestureEvent& event,
+ InputEventAckState ack_result) override;
scoped_ptr<SyntheticGestureTarget> CreateSyntheticGestureTarget() override;
uint32_t GetSurfaceIdNamespace() override;
- uint32_t SurfaceIdNamespaceAtPoint(const gfx::Point& point,
+ uint32_t SurfaceIdNamespaceAtPoint(cc::SurfaceHittestDelegate* delegate,
+ const gfx::Point& point,
gfx::Point* transformed_point) override;
// Returns true when we can do SurfaceHitTesting for the event type.
bool ShouldRouteEvent(const blink::WebInputEvent& event) const;
void ProcessMouseEvent(const blink::WebMouseEvent& event) override;
void ProcessMouseWheelEvent(const blink::WebMouseWheelEvent& event) override;
+ void ProcessTouchEvent(const blink::WebTouchEvent& event,
+ const ui::LatencyInfo& latency) override;
+ void ProcessGestureEvent(const blink::WebGestureEvent& event,
+ const ui::LatencyInfo& latency) override;
void TransformPointToLocalCoordSpace(const gfx::Point& point,
cc::SurfaceId original_surface,
gfx::Point* transformed_point) override;
@@ -375,9 +366,6 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
void SetTextInputActive(bool active);
- // Sends completed plugin IME notification and text back to the renderer.
- void PluginImeCompositionCompleted(const base::string16& text, int plugin_id);
-
const std::string& selected_text() const { return selected_text_; }
const gfx::Range& composition_range() const { return composition_range_; }
const base::string16& selection_text() const { return selection_text_; }
@@ -525,6 +513,9 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// state, if appropriate (see BrowserCompositorViewState for details).
void DestroySuspendedBrowserCompositorViewIfNeeded();
+ // Exposed for testing.
+ cc::SurfaceId SurfaceIdForTesting() const override;
+
private:
friend class RenderWidgetHostViewMacTest;
@@ -546,8 +537,6 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
void DestroyBrowserCompositorView();
// IPC message handlers.
- void OnPluginFocusChanged(bool focused, int plugin_id);
- void OnStartPluginIme();
void OnGetRenderedTextCompleted(const std::string& text);
// Send updated vsync parameters to the renderer.
@@ -577,6 +566,9 @@ class CONTENT_EXPORT RenderWidgetHostViewMac
// RenderWidgetHostViewGuest.
bool is_guest_view_hack_;
+ // True if gestures are generated for mouse wheel events.
+ bool wheel_gestures_enabled_;
+
// selected text on the renderer.
std::string selected_text_;
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 ef38d30fe02..0581389eeaf 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
@@ -21,6 +21,7 @@
#include "base/mac/scoped_cftyperef.h"
#import "base/mac/scoped_nsobject.h"
#include "base/mac/sdk_forward_declarations.h"
+#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/numerics/safe_conversions.h"
@@ -31,32 +32,32 @@
#include "base/sys_info.h"
#include "base/trace_event/trace_event.h"
#import "content/browser/accessibility/browser_accessibility_cocoa.h"
+#import "content/browser/accessibility/browser_accessibility_mac.h"
#include "content/browser/accessibility/browser_accessibility_manager_mac.h"
#include "content/browser/bad_message.h"
#import "content/browser/cocoa/system_hotkey_helper_mac.h"
#import "content/browser/cocoa/system_hotkey_map.h"
-#include "content/browser/compositor/resize_lock.h"
#include "content/browser/frame_host/frame_tree.h"
#include "content/browser/frame_host/frame_tree_node.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/gpu/compositor_util.h"
+#import "content/browser/renderer_host/input/synthetic_gesture_target_mac.h"
#include "content/browser/renderer_host/input/web_input_event_builders_mac.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_helper.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
-#import "content/browser/renderer_host/input/synthetic_gesture_target_mac.h"
#import "content/browser/renderer_host/render_widget_host_view_mac_dictionary_helper.h"
#import "content/browser/renderer_host/render_widget_host_view_mac_editcommand_helper.h"
#include "content/browser/renderer_host/render_widget_resize_helper_mac.h"
+#include "content/browser/renderer_host/resize_lock.h"
#import "content/browser/renderer_host/text_input_client_mac.h"
#include "content/common/accessibility_messages.h"
#include "content/common/edit_command.h"
-#include "content/common/gpu/gpu_messages.h"
+#include "content/common/input/input_event_utils.h"
#include "content/common/input_messages.h"
#include "content/common/site_isolation_policy.h"
#include "content/common/view_messages.h"
-#include "content/common/webplugin_geometry.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_plugin_guest_manager.h"
#include "content/public/browser/browser_thread.h"
@@ -64,12 +65,14 @@
#include "content/public/browser/render_widget_host_view_frame_subscriber.h"
#import "content/public/browser/render_widget_host_view_mac_delegate.h"
#include "content/public/browser/web_contents.h"
+#include "gpu/ipc/common/gpu_messages.h"
#include "skia/ext/platform_canvas.h"
#include "skia/ext/skia_utils_mac.h"
#include "third_party/WebKit/public/platform/WebScreenInfo.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
-#import "third_party/mozilla/ComplexTextInputPanel.h"
+#import "ui/base/clipboard/clipboard_util_mac.h"
#include "ui/base/cocoa/animation_utils.h"
+#include "ui/base/cocoa/cocoa_base_utils.h"
#import "ui/base/cocoa/fullscreen_window_manager.h"
#import "ui/base/cocoa/underlay_opengl_hosting_window.h"
#include "ui/base/layout.h"
@@ -174,11 +177,14 @@ static BOOL SupportsBackingPropertiesChangedNotification() {
- (id)initWithRenderWidgetHostViewMac:(RenderWidgetHostViewMac*)r;
- (void)processedWheelEvent:(const blink::WebMouseWheelEvent&)event
consumed:(BOOL)consumed;
+- (void)processedGestureScrollEvent:(const blink::WebGestureEvent&)event
+ consumed:(BOOL)consumed;
- (void)keyEvent:(NSEvent*)theEvent wasKeyEquivalent:(BOOL)equiv;
- (void)windowDidChangeBackingProperties:(NSNotification*)notification;
- (void)windowChangedGlobalFrame:(NSNotification*)notification;
-- (void)checkForPluginImeCancellation;
+- (void)windowDidBecomeKey:(NSNotification*)notification;
+- (void)windowDidResignKey:(NSNotification*)notification;
- (void)updateScreenProperties;
- (void)setResponderDelegate:
(NSObject<RenderWidgetHostViewMacDelegate>*)delegate;
@@ -396,7 +402,7 @@ NSWindow* ApparentWindowForView(NSView* view) {
blink::WebScreenInfo GetWebScreenInfo(NSView* view) {
gfx::Display display =
- gfx::Screen::GetNativeScreen()->GetDisplayNearestWindow(view);
+ gfx::Screen::GetScreen()->GetDisplayNearestWindow(view);
NSScreen* screen = [NSScreen deepestScreen];
@@ -519,6 +525,7 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget,
is_loading_(false),
allow_pause_for_resize_or_repaint_(true),
is_guest_view_hack_(is_guest_view_hack),
+ wheel_gestures_enabled_(UseGestureBasedWheelScrolling()),
fullscreen_parent_host_view_(NULL),
weak_factory_(this) {
// |cocoa_view_| owns us and we will be deleted when |cocoa_view_|
@@ -539,14 +546,14 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget,
root_layer_.reset(new ui::Layer(ui::LAYER_SOLID_COLOR));
delegated_frame_host_.reset(new DelegatedFrameHost(this));
- gfx::Screen::GetScreenFor(cocoa_view_)->AddObserver(this);
+ gfx::Screen::GetScreen()->AddObserver(this);
if (!is_guest_view_hack_)
render_widget_host_->SetView(this);
// Let the page-level input event router know about our surface ID
// namespace for surface-based hit testing.
- if (UseSurfacesEnabled() && render_widget_host_->delegate() &&
+ if (render_widget_host_->delegate() &&
render_widget_host_->delegate()->GetInputEventRouter()) {
render_widget_host_->delegate()
->GetInputEventRouter()
@@ -555,7 +562,7 @@ RenderWidgetHostViewMac::RenderWidgetHostViewMac(RenderWidgetHost* widget,
}
RenderWidgetHostViewMac::~RenderWidgetHostViewMac() {
- gfx::Screen::GetScreenFor(cocoa_view_)->RemoveObserver(this);
+ gfx::Screen::GetScreen()->RemoveObserver(this);
// This is being called from |cocoa_view_|'s destructor, so invalidate the
// pointer.
@@ -563,14 +570,6 @@ RenderWidgetHostViewMac::~RenderWidgetHostViewMac() {
UnlockMouse();
- if (UseSurfacesEnabled() && render_widget_host_ &&
- render_widget_host_->delegate() &&
- render_widget_host_->delegate()->GetInputEventRouter()) {
- render_widget_host_->delegate()
- ->GetInputEventRouter()
- ->RemoveSurfaceIdNamespaceOwner(GetSurfaceIdNamespace());
- }
-
// Ensure that the browser compositor is destroyed in a safe order.
ShutdownBrowserCompositor();
@@ -595,6 +594,10 @@ void RenderWidgetHostViewMac::SetAllowPauseForResizeOrRepaint(bool allow) {
allow_pause_for_resize_or_repaint_ = allow;
}
+cc::SurfaceId RenderWidgetHostViewMac::SurfaceIdForTesting() const {
+ return delegated_frame_host_->SurfaceIdForTesting();
+}
+
///////////////////////////////////////////////////////////////////////////////
// RenderWidgetHostViewMac, RenderWidgetHostView implementation:
@@ -681,8 +684,6 @@ void RenderWidgetHostViewMac::DestroySuspendedBrowserCompositorViewIfNeeded() {
bool RenderWidgetHostViewMac::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(RenderWidgetHostViewMac, message)
- IPC_MESSAGE_HANDLER(ViewHostMsg_PluginFocusChanged, OnPluginFocusChanged)
- IPC_MESSAGE_HANDLER(ViewHostMsg_StartPluginIme, OnStartPluginIme)
IPC_MESSAGE_HANDLER(ViewMsg_GetRenderedTextCompleted,
OnGetRenderedTextCompleted)
IPC_MESSAGE_UNHANDLED(handled = false)
@@ -892,7 +893,7 @@ void RenderWidgetHostViewMac::WasOccluded() {
// occur in this specific order. However, because thumbnail generation is
// asychronous, that operation won't run before SuspendBrowserCompositorView()
// completes. As a result you won't get a thumbnail for the page unless you
- // happen to switch back to it. See http://crbug.com/530707 .
+ // execute these two statements in this specific order.
render_widget_host_->WasHidden();
SuspendBrowserCompositorView();
}
@@ -967,14 +968,6 @@ gfx::NativeViewAccessible RenderWidgetHostViewMac::GetNativeViewAccessible() {
return cocoa_view_;
}
-void RenderWidgetHostViewMac::MovePluginWindows(
- const std::vector<WebPluginGeometry>& moves) {
- // Must be overridden, but unused on this platform. Core Animation
- // plugins are drawn by the GPU process (through the compositor),
- // and Core Graphics plugins are drawn by the renderer process.
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-}
-
void RenderWidgetHostViewMac::Focus() {
[[cocoa_view_ window] makeFirstResponder:cocoa_view_];
}
@@ -1002,7 +995,7 @@ gfx::Rect RenderWidgetHostViewMac::GetViewBounds() const {
return gfx::Rect(gfx::Size(NSWidth(bounds), NSHeight(bounds)));
bounds = [cocoa_view_ convertRect:bounds toView:nil];
- bounds.origin = [enclosing_window convertBaseToScreen:bounds.origin];
+ bounds = [enclosing_window convertRectToScreen:bounds];
return FlipNSRectToRectScreen(bounds);
}
@@ -1057,6 +1050,9 @@ void RenderWidgetHostViewMac::RenderProcessGone(base::TerminationStatus status,
}
void RenderWidgetHostViewMac::Destroy() {
+ // SurfaceIdNamespaces registered with RenderWidgetHostInputEventRouter
+ // have already been cleared when RenderWidgetHostViewBase notified its
+ // observers of our impending destruction.
[[NSNotificationCenter defaultCenter]
removeObserver:cocoa_view_
name:NSWindowWillCloseNotification
@@ -1079,20 +1075,14 @@ void RenderWidgetHostViewMac::Destroy() {
// object needs to survive until the stack unwinds.
pepper_fullscreen_window_.autorelease();
- // Clear SurfaceID namespace ownership before we shutdown the
- // compositor.
- if (UseSurfacesEnabled() && render_widget_host_ &&
- render_widget_host_->delegate() &&
- render_widget_host_->delegate()->GetInputEventRouter()) {
- render_widget_host_->delegate()
- ->GetInputEventRouter()
- ->RemoveSurfaceIdNamespaceOwner(GetSurfaceIdNamespace());
- }
-
// Delete the delegated frame state, which will reach back into
// render_widget_host_.
ShutdownBrowserCompositor();
+ // Make sure none of our observers send events for us to process after
+ // we release render_widget_host_.
+ NotifyObserversAboutShutdown();
+
// We get this call just before |render_widget_host_| deletes
// itself. But we are owned by |cocoa_view_|, which may be retained
// by some other code. Examples are WebContentsViewMac's
@@ -1277,27 +1267,6 @@ void RenderWidgetHostViewMac::KillSelf() {
}
}
-bool RenderWidgetHostViewMac::PostProcessEventForPluginIme(
- const NativeWebKeyboardEvent& event) {
- // Check WebInputEvent type since multiple types of events can be sent into
- // WebKit for the same OS event (e.g., RawKeyDown and Char), so filtering is
- // necessary to avoid double processing.
- // Also check the native type, since NSFlagsChanged is considered a key event
- // for WebKit purposes, but isn't considered a key event by the OS.
- if (event.type == WebInputEvent::RawKeyDown &&
- [event.os_event type] == NSKeyDown)
- return [cocoa_view_ postProcessEventForPluginIme:event.os_event];
- return false;
-}
-
-void RenderWidgetHostViewMac::PluginImeCompositionCompleted(
- const base::string16& text, int plugin_id) {
- if (render_widget_host_) {
- render_widget_host_->Send(new ViewMsg_PluginImeCompositionCompleted(
- render_widget_host_->GetRoutingID(), text, plugin_id));
- }
-}
-
bool RenderWidgetHostViewMac::GetLineBreakIndex(
const std::vector<gfx::Rect>& bounds,
const gfx::Range& range,
@@ -1312,7 +1281,8 @@ bool RenderWidgetHostViewMac::GetLineBreakIndex(
// 75% of maximum height.
// TODO(nona): Check the threshold is reliable or not.
// TODO(nona): Bidi support.
- const size_t loop_end_idx = std::min(bounds.size(), range.end());
+ const size_t loop_end_idx =
+ std::min(bounds.size(), static_cast<size_t>(range.end()));
int max_height = 0;
int min_y_offset = std::numeric_limits<int32_t>::max();
for (size_t idx = range.start(); idx < loop_end_idx; ++idx) {
@@ -1551,6 +1521,10 @@ void RenderWidgetHostViewMac::UnlockMouse() {
void RenderWidgetHostViewMac::WheelEventAck(
const blink::WebMouseWheelEvent& event,
InputEventAckState ack_result) {
+ // TODO(dtapuska): Remove this handling of the wheel event ack
+ // once wheel gestures is enabled for a full release; see crbug.com/598798.
+ if (wheel_gestures_enabled_)
+ return;
bool consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
// Only record a wheel event as unhandled if JavaScript handlers got a chance
// to see it (no-op wheel events are ignored by the event dispatcher)
@@ -1558,6 +1532,23 @@ void RenderWidgetHostViewMac::WheelEventAck(
[cocoa_view_ processedWheelEvent:event consumed:consumed];
}
+void RenderWidgetHostViewMac::GestureEventAck(
+ const blink::WebGestureEvent& event,
+ InputEventAckState ack_result) {
+ if (!wheel_gestures_enabled_)
+ return;
+ bool consumed = ack_result == INPUT_EVENT_ACK_STATE_CONSUMED;
+ switch (event.type) {
+ case blink::WebInputEvent::GestureScrollBegin:
+ case blink::WebInputEvent::GestureScrollUpdate:
+ case blink::WebInputEvent::GestureScrollEnd:
+ [cocoa_view_ processedGestureScrollEvent:event consumed:consumed];
+ return;
+ default:
+ break;
+ }
+}
+
scoped_ptr<SyntheticGestureTarget>
RenderWidgetHostViewMac::CreateSyntheticGestureTarget() {
RenderWidgetHostImpl* host =
@@ -1572,16 +1563,17 @@ uint32_t RenderWidgetHostViewMac::GetSurfaceIdNamespace() {
}
uint32_t RenderWidgetHostViewMac::SurfaceIdNamespaceAtPoint(
+ cc::SurfaceHittestDelegate* delegate,
const gfx::Point& point,
gfx::Point* transformed_point) {
// The surface hittest happens in device pixels, so we need to convert the
// |point| from DIPs to pixels before hittesting.
- float scale_factor = gfx::Screen::GetScreenFor(cocoa_view_)
+ float scale_factor = gfx::Screen::GetScreen()
->GetDisplayNearestWindow(cocoa_view_)
.device_scale_factor();
gfx::Point point_in_pixels = gfx::ConvertPointToPixel(scale_factor, point);
- cc::SurfaceId id = delegated_frame_host_->SurfaceIdAtPoint(point_in_pixels,
- transformed_point);
+ cc::SurfaceId id = delegated_frame_host_->SurfaceIdAtPoint(
+ delegate, point_in_pixels, transformed_point);
*transformed_point = gfx::ConvertPointToDIP(scale_factor, *transformed_point);
// It is possible that the renderer has not yet produced a surface, in which
@@ -1612,12 +1604,31 @@ void RenderWidgetHostViewMac::ProcessMouseWheelEvent(
render_widget_host_->ForwardWheelEvent(event);
}
+void RenderWidgetHostViewMac::ProcessTouchEvent(
+ const blink::WebTouchEvent& event,
+ const ui::LatencyInfo& latency) {
+ render_widget_host_->ForwardTouchEventWithLatencyInfo(event, latency);
+}
+
+void RenderWidgetHostViewMac::ProcessGestureEvent(
+ const blink::WebGestureEvent& event,
+ const ui::LatencyInfo& latency) {
+ render_widget_host_->ForwardGestureEventWithLatencyInfo(event, latency);
+}
+
void RenderWidgetHostViewMac::TransformPointToLocalCoordSpace(
const gfx::Point& point,
cc::SurfaceId original_surface,
gfx::Point* transformed_point) {
+ // Transformations use physical pixels rather than DIP, so conversion
+ // is necessary.
+ float scale_factor = gfx::Screen::GetScreen()
+ ->GetDisplayNearestWindow(cocoa_view_)
+ .device_scale_factor();
+ gfx::Point point_in_pixels = gfx::ConvertPointToPixel(scale_factor, point);
delegated_frame_host_->TransformPointToLocalCoordSpace(
- point, original_surface, transformed_point);
+ point_in_pixels, original_surface, transformed_point);
+ *transformed_point = gfx::ConvertPointToDIP(scale_factor, *transformed_point);
}
bool RenderWidgetHostViewMac::Send(IPC::Message* message) {
@@ -1652,25 +1663,8 @@ void RenderWidgetHostViewMac::SetActive(bool active) {
}
if (HasFocus())
SetTextInputActive(active);
- if (!active) {
- [cocoa_view_ setPluginImeActive:NO];
+ if (!active)
UnlockMouse();
- }
-}
-
-void RenderWidgetHostViewMac::SetWindowVisibility(bool visible) {
- if (render_widget_host_) {
- render_widget_host_->Send(new ViewMsg_SetWindowVisibility(
- render_widget_host_->GetRoutingID(), visible));
- }
-}
-
-void RenderWidgetHostViewMac::WindowFrameChanged() {
- if (render_widget_host_) {
- render_widget_host_->Send(new ViewMsg_WindowFrameChanged(
- render_widget_host_->GetRoutingID(), GetBoundsInRootWindow(),
- GetViewBounds()));
- }
}
void RenderWidgetHostViewMac::ShowDefinitionForSelection() {
@@ -1679,6 +1673,9 @@ void RenderWidgetHostViewMac::ShowDefinitionForSelection() {
}
void RenderWidgetHostViewMac::SetBackgroundColor(SkColor color) {
+ if (color == background_color_)
+ return;
+
RenderWidgetHostViewBase::SetBackgroundColor(color);
bool opaque = GetBackgroundOpaque();
@@ -1688,11 +1685,16 @@ void RenderWidgetHostViewMac::SetBackgroundColor(SkColor color) {
[cocoa_view_ setOpaque:opaque];
if (browser_compositor_state_ != BrowserCompositorDestroyed)
browser_compositor_->compositor()->SetHostHasTransparentBackground(!opaque);
+
+ ScopedCAActionDisabler disabler;
+ base::ScopedCFTypeRef<CGColorRef> cg_color(
+ skia::CGColorCreateFromSkColor(color));
+ [background_layer_ setBackgroundColor:cg_color];
}
BrowserAccessibilityManager*
RenderWidgetHostViewMac::CreateBrowserAccessibilityManager(
- BrowserAccessibilityDelegate* delegate) {
+ BrowserAccessibilityDelegate* delegate, bool for_root_frame) {
return new BrowserAccessibilityManagerMac(
cocoa_view_,
BrowserAccessibilityManagerMac::GetEmptyDocument(),
@@ -1706,7 +1708,7 @@ gfx::Point RenderWidgetHostViewMac::AccessibilityOriginInScreen(
origin.y = NSHeight([cocoa_view_ bounds]) - origin.y;
NSPoint originInWindow = [cocoa_view_ convertPoint:origin toView:nil];
NSPoint originInScreen =
- [[cocoa_view_ window] convertBaseToScreen:originInWindow];
+ ui::ConvertPointFromWindowToScreen([cocoa_view_ window], originInWindow);
originInScreen.y = originInScreen.y - size.height;
return gfx::Point(originInScreen.x, originInScreen.y);
}
@@ -1723,15 +1725,6 @@ void RenderWidgetHostViewMac::SetTextInputActive(bool active) {
}
}
-void RenderWidgetHostViewMac::OnPluginFocusChanged(bool focused,
- int plugin_id) {
- [cocoa_view_ pluginFocusChanged:(focused ? YES : NO) forPlugin:plugin_id];
-}
-
-void RenderWidgetHostViewMac::OnStartPluginIme() {
- [cocoa_view_ setPluginImeActive:YES];
-}
-
void RenderWidgetHostViewMac::OnGetRenderedTextCompleted(
const std::string& text) {
SpeakText(text);
@@ -1761,7 +1754,7 @@ void RenderWidgetHostViewMac::OnDisplayRemoved(const gfx::Display& display) {
void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
const gfx::Display& display, uint32_t metrics) {
- gfx::Screen* screen = gfx::Screen::GetScreenFor(cocoa_view_);
+ gfx::Screen* screen = gfx::Screen::GetScreen();
if (display.id() != screen->GetDisplayNearestWindow(cocoa_view_).id())
return;
@@ -1787,7 +1780,6 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
renderWidgetHostView_.reset(r);
canBeKeyView_ = YES;
opaque_ = YES;
- focusedPluginIdentifier_ = -1;
pinchHasReachedZoomThreshold_ = false;
// OpenGL support:
@@ -1837,6 +1829,12 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
[responderDelegate_ rendererHandledWheelEvent:event consumed:consumed];
}
+- (void)processedGestureScrollEvent:(const blink::WebGestureEvent&)event
+ consumed:(BOOL)consumed {
+ [responderDelegate_ rendererHandledGestureScrollEvent:event
+ consumed:consumed];
+}
+
- (BOOL)respondsToSelector:(SEL)selector {
// Trickiness: this doesn't mean "does this object's superclass respond to
// this selector" but rather "does the -respondsToSelector impl from the
@@ -2152,22 +2150,14 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
markedText_.clear();
markedTextSelectedRange_ = NSMakeRange(NSNotFound, 0);
underlines_.clear();
+ setMarkedTextReplacementRange_ = gfx::Range::InvalidRange();
unmarkTextCalled_ = NO;
hasEditCommands_ = NO;
editCommands_.clear();
- // Before doing anything with a key down, check to see if plugin IME has been
- // cancelled, since the plugin host needs to be informed of that before
- // receiving the keydown.
- if ([theEvent type] == NSKeyDown)
- [self checkForPluginImeCancellation];
-
// Sends key down events to input method first, then we can decide what should
// be done according to input method's feedback.
- // If a plugin is active, bypass this step since events are forwarded directly
- // to the plugin IME.
- if (focusedPluginIdentifier_ == -1)
- [self interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
+ [self interpretKeyEvents:[NSArray arrayWithObject:theEvent]];
handlingKeyDown_ = NO;
@@ -2237,6 +2227,7 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
// When marked text is available, |markedTextSelectedRange_| will be the
// range being selected inside the marked text.
widgetHost->ImeSetComposition(markedText_, underlines_,
+ setMarkedTextReplacementRange_,
markedTextSelectedRange_.location,
NSMaxRange(markedTextSelectedRange_));
} else if (oldHasMarkedText && !hasMarkedText_ && !textInserted) {
@@ -2248,6 +2239,9 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
}
}
+ // Clear information from |interpretKeyEvents:|
+ setMarkedTextReplacementRange_ = gfx::Range::InvalidRange();
+
// If the key event was handled by the input method but it also generated some
// edit commands, then we need to send the real key event and corresponding
// edit commands here. This usually occurs when the input method wants to
@@ -2402,11 +2396,11 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
renderWidgetHostView_->selected_text());
if ([text length] == 0)
return;
- NSPasteboard* pasteboard = [NSPasteboard pasteboardWithUniqueName];
+ scoped_refptr<ui::UniquePasteboard> pasteboard = new ui::UniquePasteboard;
NSArray* types = [NSArray arrayWithObject:NSStringPboardType];
- [pasteboard declareTypes:types owner:nil];
- if ([pasteboard setString:text forType:NSStringPboardType])
- NSPerformService(@"Look Up in Dictionary", pasteboard);
+ [pasteboard->get() declareTypes:types owner:nil];
+ if ([pasteboard->get() setString:text forType:NSStringPboardType])
+ NSPerformService(@"Look Up in Dictionary", pasteboard->get());
return;
}
dispatch_async(dispatch_get_main_queue(), ^{
@@ -2564,6 +2558,14 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
removeObserver:self
name:NSWindowDidEndLiveResizeNotification
object:oldWindow];
+ [notificationCenter
+ removeObserver:self
+ name:NSWindowDidBecomeKeyNotification
+ object:oldWindow];
+ [notificationCenter
+ removeObserver:self
+ name:NSWindowDidResignKeyNotification
+ object:oldWindow];
}
if (newWindow) {
if (supportsBackingPropertiesNotification) {
@@ -2583,6 +2585,14 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
selector:@selector(windowChangedGlobalFrame:)
name:NSWindowDidEndLiveResizeNotification
object:newWindow];
+ [notificationCenter addObserver:self
+ selector:@selector(windowDidBecomeKey:)
+ name:NSWindowDidBecomeKeyNotification
+ object:newWindow];
+ [notificationCenter addObserver:self
+ selector:@selector(windowDidResignKey:)
+ name:NSWindowDidResignKeyNotification
+ object:newWindow];
}
}
@@ -2620,7 +2630,10 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
if (!renderWidgetHostView_->render_widget_host_)
return;
- renderWidgetHostView_->render_widget_host_->SendScreenRects();
+ if (renderWidgetHostView_->render_widget_host_->delegate())
+ renderWidgetHostView_->render_widget_host_->delegate()->SendScreenRects();
+ else
+ renderWidgetHostView_->render_widget_host_->SendScreenRects();
renderWidgetHostView_->render_widget_host_->WasResized();
if (renderWidgetHostView_->delegated_frame_host_)
renderWidgetHostView_->delegated_frame_host_->WasResized();
@@ -2646,6 +2659,28 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
return canBeKeyView_;
}
+- (void)windowDidBecomeKey:(NSNotification*)notification {
+ DCHECK([self window]);
+ DCHECK_EQ([self window], [notification object]);
+ if ([[self window] firstResponder] == self)
+ renderWidgetHostView_->SetActive(true);
+}
+
+- (void)windowDidResignKey:(NSNotification*)notification {
+ DCHECK([self window]);
+ DCHECK_EQ([self window], [notification object]);
+
+ // If our app is still active and we're still the key window, ignore this
+ // message, since it just means that a menu extra (on the "system status bar")
+ // was activated; we'll get another |-windowDidResignKey| if we ever really
+ // lose key window status.
+ if ([NSApp isActive] && ([NSApp keyWindow] == [self window]))
+ return;
+
+ if ([[self window] firstResponder] == self)
+ renderWidgetHostView_->SetActive(false);
+}
+
- (BOOL)becomeFirstResponder {
if (!renderWidgetHostView_->render_widget_host_)
return NO;
@@ -2768,8 +2803,8 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
if (([attribute isEqualToString:NSAccessibilityChildrenAttribute] ||
[attribute isEqualToString:NSAccessibilityContentsAttribute]) &&
manager) {
- return [NSArray arrayWithObjects:manager->
- GetRoot()->ToBrowserAccessibilityCocoa(), nil];
+ return [NSArray arrayWithObjects:ToBrowserAccessibilityCocoa(
+ manager->GetRoot()), nil];
} else if ([attribute isEqualToString:NSAccessibilityRoleAttribute]) {
return NSAccessibilityScrollAreaRole;
}
@@ -2790,11 +2825,12 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
->GetRootBrowserAccessibilityManager();
if (!manager)
return self;
- NSPoint pointInWindow = [[self window] convertScreenToBase:point];
+ NSPoint pointInWindow =
+ ui::ConvertPointFromScreenToWindow([self window], point);
NSPoint localPoint = [self convertPoint:pointInWindow fromView:nil];
localPoint.y = NSHeight([self bounds]) - localPoint.y;
BrowserAccessibilityCocoa* root =
- manager->GetRoot()->ToBrowserAccessibilityCocoa();
+ ToBrowserAccessibilityCocoa(manager->GetRoot());
id obj = [root accessibilityHitTest:localPoint];
return obj;
}
@@ -2812,7 +2848,7 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
->GetRootBrowserAccessibilityManager();
// Only child is root.
if (manager &&
- manager->GetRoot()->ToBrowserAccessibilityCocoa() == child) {
+ ToBrowserAccessibilityCocoa(manager->GetRoot()) == child) {
return 0;
} else {
return NSNotFound;
@@ -2824,11 +2860,11 @@ void RenderWidgetHostViewMac::OnDisplayMetricsChanged(
renderWidgetHostView_->render_widget_host_
->GetRootBrowserAccessibilityManager();
if (manager) {
- BrowserAccessibility* focused_item = manager->GetFocus(NULL);
+ BrowserAccessibility* focused_item = manager->GetFocus();
DCHECK(focused_item);
if (focused_item) {
BrowserAccessibilityCocoa* focused_item_cocoa =
- focused_item->ToBrowserAccessibilityCocoa();
+ ToBrowserAccessibilityCocoa(focused_item);
DCHECK(focused_item_cocoa);
if (focused_item_cocoa)
return focused_item_cocoa;
@@ -2914,7 +2950,7 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
// |thePoint| is in screen coordinates, but needs to be converted to WebKit
// coordinates (upper left origin). Scroll offsets will be taken care of in
// the renderer.
- thePoint = [[self window] convertScreenToBase:thePoint];
+ thePoint = ui::ConvertPointFromScreenToWindow([self window], thePoint);
thePoint = [self convertPoint:thePoint fromView:nil];
thePoint.y = NSHeight([self frame]) - thePoint.y;
@@ -2961,7 +2997,7 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
// Convert into screen coordinates for return.
rect = [self convertRect:rect toView:nil];
- rect.origin = [[self window] convertBaseToScreen:rect.origin];
+ rect = [[self window] convertRectToScreen:rect];
return rect;
}
@@ -3024,9 +3060,6 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
// nil when the caret is in non-editable content or password box to avoid
// making input methods do their work.
- (NSTextInputContext *)inputContext {
- if (focusedPluginIdentifier_ != -1)
- return [[ComplexTextInputPanel sharedComplexTextInputPanel] inputContext];
-
switch(renderWidgetHostView_->text_input_type_) {
case ui::TEXT_INPUT_TYPE_NONE:
case ui::TEXT_INPUT_TYPE_PASSWORD:
@@ -3099,9 +3132,11 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
// is empty to update the input method state. (Our input method backend can
// automatically cancels an ongoing composition when we send an empty text.
// So, it is OK to send an empty text to the renderer.)
- if (!handlingKeyDown_) {
+ if (handlingKeyDown_) {
+ setMarkedTextReplacementRange_ = gfx::Range(replacementRange);
+ } else {
renderWidgetHostView_->render_widget_host_->ImeSetComposition(
- markedText_, underlines_,
+ markedText_, underlines_, gfx::Range(replacementRange),
newSelRange.location, NSMaxRange(newSelRange));
}
}
@@ -3177,22 +3212,6 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
renderWidgetHostView_->DestroySuspendedBrowserCompositorViewIfNeeded();
}
- if (canBeKeyView_) {
- NSWindow* newWindow = [self window];
- // Pointer comparison only, since we don't know if lastWindow_ is still
- // valid.
- if (newWindow) {
- // If we move into a new window, refresh the frame information. We
- // don't need to do it if it was the same window as it used to be in,
- // since that case is covered by WasShown(). We only want to do this for
- // real browser views, not popups.
- if (newWindow != lastWindow_) {
- lastWindow_ = newWindow;
- renderWidgetHostView_->WindowFrameChanged();
- }
- }
- }
-
// If we switch windows (or are removed from the view hierarchy), cancel any
// open mouse-downs.
if (hasOpenMouseDown_) {
@@ -3304,54 +3323,6 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
[self cancelComposition];
}
-- (void)setPluginImeActive:(BOOL)active {
- if (active == pluginImeActive_)
- return;
-
- pluginImeActive_ = active;
- if (!active) {
- [[ComplexTextInputPanel sharedComplexTextInputPanel] cancelComposition];
- renderWidgetHostView_->PluginImeCompositionCompleted(
- base::string16(), focusedPluginIdentifier_);
- }
-}
-
-- (void)pluginFocusChanged:(BOOL)focused forPlugin:(int)pluginId {
- if (focused)
- focusedPluginIdentifier_ = pluginId;
- else if (focusedPluginIdentifier_ == pluginId)
- focusedPluginIdentifier_ = -1;
-
- // Whenever plugin focus changes, plugin IME resets.
- [self setPluginImeActive:NO];
-}
-
-- (BOOL)postProcessEventForPluginIme:(NSEvent*)event {
- if (!pluginImeActive_)
- return false;
-
- ComplexTextInputPanel* inputPanel =
- [ComplexTextInputPanel sharedComplexTextInputPanel];
- NSString* composited_string = nil;
- BOOL handled = [inputPanel interpretKeyEvent:event
- string:&composited_string];
- if (composited_string) {
- renderWidgetHostView_->PluginImeCompositionCompleted(
- base::SysNSStringToUTF16(composited_string), focusedPluginIdentifier_);
- pluginImeActive_ = NO;
- }
- return handled;
-}
-
-- (void)checkForPluginImeCancellation {
- if (pluginImeActive_ &&
- ![[ComplexTextInputPanel sharedComplexTextInputPanel] inComposition]) {
- renderWidgetHostView_->PluginImeCompositionCompleted(
- base::string16(), focusedPluginIdentifier_);
- pluginImeActive_ = NO;
- }
-}
-
// Overriding a NSResponder method to support application services.
- (id)validRequestorForSendType:(NSString*)sendType
@@ -3376,20 +3347,6 @@ extern NSString *NSTextInputReplacementRangeAttributeName;
return requestor;
}
-- (void)viewWillStartLiveResize {
- [super viewWillStartLiveResize];
- RenderWidgetHostImpl* widget = renderWidgetHostView_->render_widget_host_;
- if (widget)
- widget->Send(new ViewMsg_SetInLiveResize(widget->GetRoutingID(), true));
-}
-
-- (void)viewDidEndLiveResize {
- [super viewDidEndLiveResize];
- RenderWidgetHostImpl* widget = renderWidgetHostView_->render_widget_host_;
- if (widget)
- widget->Send(new ViewMsg_SetInLiveResize(widget->GetRoutingID(), false));
-}
-
- (void)updateCursor:(NSCursor*)cursor {
if (currentCursor_ == cursor)
return;
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 ac3cb9467f2..5cc1841dbd6 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
@@ -8,6 +8,7 @@
#include <stddef.h>
#include <stdint.h>
+#include "base/command_line.h"
#include "base/mac/mac_util.h"
#include "base/mac/scoped_nsautorelease_pool.h"
#include "base/mac/sdk_forward_declarations.h"
@@ -18,15 +19,16 @@
#include "content/browser/frame_host/render_widget_host_view_guest.h"
#include "content/browser/gpu/compositor_util.h"
#include "content/browser/renderer_host/render_widget_host_delegate.h"
-#include "content/common/gpu/gpu_messages.h"
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_widget_host_view_mac_delegate.h"
+#include "content/public/common/content_switches.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_utils.h"
#include "content/test/test_render_view_host.h"
+#include "gpu/ipc/common/gpu_messages.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/gtest_mac.h"
@@ -77,6 +79,11 @@
if (!consumed)
unhandledWheelEventReceived_ = true;
}
+- (void)rendererHandledGestureScrollEvent:(const blink::WebGestureEvent&)event
+ consumed:(BOOL)consumed {
+ if (!consumed && event.type == blink::WebInputEvent::GestureScrollUpdate)
+ unhandledWheelEventReceived_ = true;
+}
- (void)touchesBeganWithEvent:(NSEvent*)event {}
- (void)touchesMovedWithEvent:(NSEvent*)event {}
- (void)touchesCancelledWithEvent:(NSEvent*)event {}
@@ -150,7 +157,9 @@ class MockRenderWidgetHostImpl : public RenderWidgetHostImpl {
MockRenderWidgetHostImpl(RenderWidgetHostDelegate* delegate,
RenderProcessHost* process,
int32_t routing_id)
- : RenderWidgetHostImpl(delegate, process, routing_id, false) {}
+ : RenderWidgetHostImpl(delegate, process, routing_id, false) {
+ set_renderer_initialized(true);
+ }
MOCK_METHOD0(Focus, void());
MOCK_METHOD0(Blur, void());
@@ -244,6 +253,19 @@ class RenderWidgetHostViewMacTest : public RenderViewHostImplTestHarness {
RenderViewHostImplTestHarness::TearDown();
}
+ void SetupForWheelGestures(bool enable_wheel_gestures) {
+ CHECK(!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableWheelGestures));
+ CHECK(!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableWheelGestures));
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ enable_wheel_gestures ? switches::kEnableWheelGestures
+ : switches::kDisableWheelGestures);
+ // Owned by its |cocoa_view()|, i.e. |rwhv_cocoa_|.
+ rwhv_mac_ = new RenderWidgetHostViewMac(rvh()->GetWidget(), false);
+ rwhv_cocoa_.reset([rwhv_mac_->cocoa_view() retain]);
+ }
+
void RecycleAndWait() {
pool_.Recycle();
base::MessageLoop::current()->RunUntilIdle();
@@ -726,17 +748,22 @@ TEST_F(RenderWidgetHostViewMacTest, UpdateCompositionMultilineCase) {
// firstRectForCharacterRange:actualRange] are handled in a sane manner if they
// arrive after the C++ RenderWidgetHostView is destroyed.
TEST_F(RenderWidgetHostViewMacTest, CompositionEventAfterDestroy) {
- // The test view isn't in an NSWindow to perform the final coordinate
- // conversion, so use an origin of 0,0, but verify the size.
const gfx::Rect composition_bounds(0, 0, 30, 40);
const gfx::Range range(0, 1);
rwhv_mac_->ImeCompositionRangeChanged(
range, std::vector<gfx::Rect>(1, composition_bounds));
NSRange actual_range = NSMakeRange(0, 0);
+
+ base::scoped_nsobject<CocoaTestHelperWindow> window(
+ [[CocoaTestHelperWindow alloc] init]);
+ [[window contentView] addSubview:rwhv_cocoa_];
+ [rwhv_cocoa_ setFrame:NSMakeRect(0, 0, 400, 400)];
+
NSRect rect = [rwhv_cocoa_ firstRectForCharacterRange:range.ToNSRange()
actualRange:&actual_range];
- EXPECT_NSEQ(NSMakeRect(0, 0, 30, 40), rect);
+ EXPECT_EQ(30, rect.size.width);
+ EXPECT_EQ(40, rect.size.height);
EXPECT_EQ(range, gfx::Range(actual_range));
DestroyHostViewRetainCocoaView();
@@ -754,6 +781,7 @@ TEST_F(RenderWidgetHostViewMacTest, BlurAndFocusOnSetActive) {
TestBrowserContext browser_context;
MockRenderProcessHost* process_host =
new MockRenderProcessHost(&browser_context);
+ process_host->Init();
// Owned by its |cocoa_view()|.
int32_t routing_id = process_host->GetNextRoutingID();
@@ -808,6 +836,7 @@ TEST_F(RenderWidgetHostViewMacTest, ScrollWheelEndEventDelivery) {
MockRenderWidgetHostImpl* host =
new MockRenderWidgetHostImpl(&delegate, process_host, routing_id);
RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false);
+ process_host->sink().ClearMessages();
// Send an initial wheel event with NSEventPhaseBegan to the view.
NSEvent* event1 = MockScrollWheelEventWithPhase(@selector(phaseBegan), 0);
@@ -837,6 +866,8 @@ TEST_F(RenderWidgetHostViewMacTest, IgnoreEmptyUnhandledWheelEvent) {
if (!base::mac::IsOSLionOrLater())
return;
+ SetupForWheelGestures(false);
+
// Initialize the view associated with a MockRenderWidgetHostImpl, rather than
// the MockRenderProcessHost that is set up by the test harness which mocks
// out |OnMessageReceived()|.
@@ -849,6 +880,7 @@ TEST_F(RenderWidgetHostViewMacTest, IgnoreEmptyUnhandledWheelEvent) {
MockRenderWidgetHostImpl* host =
new MockRenderWidgetHostImpl(&delegate, process_host, routing_id);
RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false);
+ process_host->sink().ClearMessages();
// Add a delegate to the view.
base::scoped_nsobject<MockRenderWidgetHostViewMacDelegate> view_delegate(
@@ -889,6 +921,75 @@ TEST_F(RenderWidgetHostViewMacTest, IgnoreEmptyUnhandledWheelEvent) {
host->ShutdownAndDestroyWidget(true);
}
+TEST_F(RenderWidgetHostViewMacTest,
+ IgnoreEmptyUnhandledWheelEventWithWheelGestures) {
+ // This tests Lion+ functionality, so don't run the test pre-Lion.
+ if (!base::mac::IsOSLionOrLater())
+ return;
+
+ SetupForWheelGestures(true);
+
+ // Initialize the view associated with a MockRenderWidgetHostImpl, rather than
+ // the MockRenderProcessHost that is set up by the test harness which mocks
+ // out |OnMessageReceived()|.
+ TestBrowserContext browser_context;
+ MockRenderProcessHost* process_host =
+ new MockRenderProcessHost(&browser_context);
+ process_host->Init();
+ MockRenderWidgetHostDelegate delegate;
+ int32_t routing_id = process_host->GetNextRoutingID();
+ MockRenderWidgetHostImpl* host =
+ new MockRenderWidgetHostImpl(&delegate, process_host, routing_id);
+ RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false);
+ process_host->sink().ClearMessages();
+
+ // Add a delegate to the view.
+ base::scoped_nsobject<MockRenderWidgetHostViewMacDelegate> view_delegate(
+ [[MockRenderWidgetHostViewMacDelegate alloc] init]);
+ view->SetDelegate(view_delegate.get());
+
+ // Send an initial wheel event for scrolling by 3 lines.
+ NSEvent* event1 = MockScrollWheelEventWithPhase(@selector(phaseBegan), 3);
+ [view->cocoa_view() scrollWheel:event1];
+ ASSERT_EQ(1U, process_host->sink().message_count());
+ process_host->sink().ClearMessages();
+
+ // Indicate that the wheel event was unhandled.
+ InputEventAck unhandled_ack(blink::WebInputEvent::MouseWheel,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ scoped_ptr<IPC::Message> response1(
+ new InputHostMsg_HandleInputEvent_ACK(0, unhandled_ack));
+ host->OnMessageReceived(*response1);
+ ASSERT_EQ(2U, process_host->sink().message_count());
+ process_host->sink().ClearMessages();
+
+ InputEventAck unhandled_scroll_ack(blink::WebInputEvent::GestureScrollUpdate,
+ INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+ scoped_ptr<IPC::Message> scroll_response1(
+ new InputHostMsg_HandleInputEvent_ACK(0, unhandled_scroll_ack));
+ host->OnMessageReceived(*scroll_response1);
+
+ // Check that the view delegate got an unhandled wheel event.
+ ASSERT_EQ(YES, view_delegate.get().unhandledWheelEventReceived);
+ view_delegate.get().unhandledWheelEventReceived = NO;
+
+ // Send another wheel event, this time for scrolling by 0 lines (empty event).
+ NSEvent* event2 = MockScrollWheelEventWithPhase(@selector(phaseChanged), 0);
+ [view->cocoa_view() scrollWheel:event2];
+ ASSERT_EQ(2U, process_host->sink().message_count());
+
+ // Indicate that the wheel event was also unhandled.
+ scoped_ptr<IPC::Message> response2(
+ new InputHostMsg_HandleInputEvent_ACK(0, unhandled_ack));
+ host->OnMessageReceived(*response2);
+
+ // Check that the view delegate ignored the empty unhandled wheel event.
+ ASSERT_EQ(NO, view_delegate.get().unhandledWheelEventReceived);
+
+ // Clean up.
+ host->ShutdownAndDestroyWidget(true);
+}
+
// Tests that when view initiated shutdown happens (i.e. RWHView is deleted
// before RWH), we clean up properly and don't leak the RWHVGuest.
TEST_F(RenderWidgetHostViewMacTest, GuestViewDoesNotLeak) {
@@ -896,6 +997,7 @@ TEST_F(RenderWidgetHostViewMacTest, GuestViewDoesNotLeak) {
TestBrowserContext browser_context;
MockRenderProcessHost* process_host =
new MockRenderProcessHost(&browser_context);
+ process_host->Init();
int32_t routing_id = process_host->GetNextRoutingID();
// Owned by its |cocoa_view()|.
@@ -938,6 +1040,7 @@ TEST_F(RenderWidgetHostViewMacTest, Background) {
TestBrowserContext browser_context;
MockRenderProcessHost* process_host =
new MockRenderProcessHost(&browser_context);
+ process_host->Init();
MockRenderWidgetHostDelegate delegate;
int32_t routing_id = process_host->GetNextRoutingID();
MockRenderWidgetHostImpl* host =
@@ -993,7 +1096,9 @@ class RenderWidgetHostViewMacPinchTest : public RenderWidgetHostViewMacTest {
break;
}
DCHECK(message);
- base::Tuple<IPC::WebInputEventPointer, ui::LatencyInfo> data;
+ base::Tuple<IPC::WebInputEventPointer, ui::LatencyInfo,
+ InputEventDispatchType>
+ data;
InputMsg_HandleInputEvent::Read(message, &data);
IPC::WebInputEventPointer ipc_event = base::get<0>(data);
const blink::WebGestureEvent* gesture_event =
@@ -1020,6 +1125,7 @@ TEST_F(RenderWidgetHostViewMacPinchTest, PinchThresholding) {
MockRenderWidgetHostImpl* host =
new MockRenderWidgetHostImpl(&delegate, process_host_, routing_id);
RenderWidgetHostViewMac* view = new RenderWidgetHostViewMac(host, false);
+ process_host_->sink().ClearMessages();
// We'll use this IPC message to ack events.
InputEventAck ack(blink::WebInputEvent::GesturePinchUpdate,
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mus.cc b/chromium/content/browser/renderer_host/render_widget_host_view_mus.cc
index 3cfdacf4c85..eb29bde8f99 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_mus.cc
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_mus.cc
@@ -9,12 +9,12 @@
#include "build/build_config.h"
#include "components/mus/public/cpp/window.h"
#include "components/mus/public/cpp/window_tree_connection.h"
-#include "content/browser/mojo/mojo_shell_client_host.h"
+#include "content/browser/mojo/mojo_child_connection.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/common/render_widget_window_tree_client_factory.mojom.h"
#include "content/public/common/mojo_shell_connection.h"
-#include "mojo/shell/public/cpp/application_impl.h"
+#include "mojo/shell/public/cpp/connector.h"
#include "ui/aura/client/screen_position_client.h"
#include "ui/aura/window.h"
#include "ui/base/hit_test.h"
@@ -38,9 +38,8 @@ RenderWidgetHostViewMus::RenderWidgetHostViewMus(mus::Window* parent_window,
// Connect to the renderer, pass it a WindowTreeClient interface request
// and embed that client inside our mus window.
- std::string url = GetMojoApplicationInstanceURL(host_->GetProcess());
mojom::RenderWidgetWindowTreeClientFactoryPtr factory;
- MojoShellConnection::Get()->GetApplication()->ConnectToService(url, &factory);
+ GetMojoConnection(host_->GetProcess())->GetInterface(&factory);
mus::mojom::WindowTreeClientPtr window_tree_client;
factory->CreateWindowTreeClientForRenderWidget(
@@ -180,10 +179,6 @@ gfx::NativeViewAccessible RenderWidgetHostViewMus::GetNativeViewAccessible() {
return gfx::NativeViewAccessible();
}
-void RenderWidgetHostViewMus::MovePluginWindows(
- const std::vector<WebPluginGeometry>& moves) {
-}
-
void RenderWidgetHostViewMus::UpdateCursor(const WebCursor& cursor) {
// TODO(fsamuel): Implement cursors in Mus.
NOTIMPLEMENTED();
@@ -277,13 +272,6 @@ gfx::Rect RenderWidgetHostViewMus::GetBoundsInRootWindow() {
void RenderWidgetHostViewMus::SetActive(bool active) {
}
-void RenderWidgetHostViewMus::SetWindowVisibility(bool visible) {
- // TODO(fsamuel): Propagate visibility to Mus?
-}
-
-void RenderWidgetHostViewMus::WindowFrameChanged() {
-}
-
void RenderWidgetHostViewMus::ShowDefinitionForSelection() {
// TODO(fsamuel): Implement this on Mac.
}
@@ -305,12 +293,6 @@ bool RenderWidgetHostViewMus::IsSpeaking() const {
void RenderWidgetHostViewMus::StopSpeaking() {
// TODO(fsamuel): Implement this on Mac.
}
-
-bool RenderWidgetHostViewMus::PostProcessEventForPluginIme(
- const NativeWebKeyboardEvent& event) {
- return false;
-}
-
#endif // defined(OS_MACOSX)
void RenderWidgetHostViewMus::LockCompositingSurface() {
@@ -321,14 +303,4 @@ void RenderWidgetHostViewMus::UnlockCompositingSurface() {
NOTIMPLEMENTED();
}
-#if defined(OS_WIN)
-void RenderWidgetHostViewMus::SetParentNativeViewAccessible(
- gfx::NativeViewAccessible accessible_parent) {}
-
-gfx::NativeViewId RenderWidgetHostViewMus::GetParentForWindowlessPlugin()
- const {
- return gfx::NativeViewId();
-}
-#endif
-
} // namespace content
diff --git a/chromium/content/browser/renderer_host/render_widget_host_view_mus.h b/chromium/content/browser/renderer_host/render_widget_host_view_mus.h
index 0db6d732fba..3a96b9f9b5b 100644
--- a/chromium/content/browser/renderer_host/render_widget_host_view_mus.h
+++ b/chromium/content/browser/renderer_host/render_widget_host_view_mus.h
@@ -65,7 +65,6 @@ class CONTENT_EXPORT RenderWidgetHostViewMus : public RenderWidgetHostViewBase {
void InitAsPopup(RenderWidgetHostView* parent_host_view,
const gfx::Rect& bounds) override;
void InitAsFullscreen(RenderWidgetHostView* reference_host_view) override;
- void MovePluginWindows(const std::vector<WebPluginGeometry>& moves) override;
void UpdateCursor(const WebCursor& cursor) override;
void SetIsLoading(bool is_loading) override;
void TextInputStateChanged(
@@ -106,28 +105,16 @@ class CONTENT_EXPORT RenderWidgetHostViewMus : public RenderWidgetHostViewBase {
#if defined(OS_MACOSX)
// RenderWidgetHostView implementation.
void SetActive(bool active) override;
- void SetWindowVisibility(bool visible) override;
- void WindowFrameChanged() override;
void ShowDefinitionForSelection() override;
bool SupportsSpeech() const override;
void SpeakSelection() override;
bool IsSpeaking() const override;
void StopSpeaking() override;
-
- // RenderWidgetHostViewBase implementation.
- bool PostProcessEventForPluginIme(
- const NativeWebKeyboardEvent& event) override;
#endif // defined(OS_MACOSX)
void LockCompositingSurface() override;
void UnlockCompositingSurface() override;
-#if defined(OS_WIN)
- void SetParentNativeViewAccessible(
- gfx::NativeViewAccessible accessible_parent) override;
- gfx::NativeViewId GetParentForWindowlessPlugin() const override;
-#endif
-
RenderWidgetHostImpl* host_;
aura::Window* aura_window_;
diff --git a/chromium/content/browser/compositor/resize_lock.cc b/chromium/content/browser/renderer_host/resize_lock.cc
index ddbc4437872..dca36fa8a07 100644
--- a/chromium/content/browser/compositor/resize_lock.cc
+++ b/chromium/content/browser/renderer_host/resize_lock.cc
@@ -2,13 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/compositor/resize_lock.h"
+#include "content/browser/renderer_host/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) {
+ : new_size_(new_size), defer_compositor_lock_(defer_compositor_lock) {
if (!defer_compositor_lock_)
LockCompositor();
}
diff --git a/chromium/content/browser/compositor/resize_lock.h b/chromium/content/browser/renderer_host/resize_lock.h
index 8b4829785eb..fa8d963ccae 100644
--- a/chromium/content/browser/compositor/resize_lock.h
+++ b/chromium/content/browser/renderer_host/resize_lock.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_COMPOSITOR_RESIZE_LOCK_H_
-#define CONTENT_BROWSER_COMPOSITOR_RESIZE_LOCK_H_
+#ifndef CONTENT_BROWSER_RENDERER_HOST_RESIZE_LOCK_H_
+#define CONTENT_BROWSER_RENDERER_HOST_RESIZE_LOCK_H_
#include "base/macros.h"
#include "content/common/content_export.h"
@@ -34,4 +34,4 @@ class CONTENT_EXPORT ResizeLock {
} // namespace content
-#endif // CONTENT_BROWSER_COMPOSITOR_RESIZE_LOCK_H_
+#endif // CONTENT_BROWSER_RENDERER_HOST_RESIZE_LOCK_H_
diff --git a/chromium/content/browser/renderer_host/sandbox_ipc_linux.cc b/chromium/content/browser/renderer_host/sandbox_ipc_linux.cc
index 465ddbdc285..94a34b58d1b 100644
--- a/chromium/content/browser/renderer_host/sandbox_ipc_linux.cc
+++ b/chromium/content/browser/renderer_host/sandbox_ipc_linux.cc
@@ -27,18 +27,11 @@
#include "content/common/set_process_title.h"
#include "content/public/common/content_switches.h"
#include "ppapi/c/trusted/ppb_browser_font_trusted.h"
-#include "third_party/WebKit/public/platform/linux/WebFontInfo.h"
-#include "third_party/WebKit/public/web/WebKit.h"
-#include "third_party/npapi/bindings/npapi_extensions.h"
#include "third_party/skia/include/ports/SkFontConfigInterface.h"
#include "ui/gfx/font.h"
+#include "ui/gfx/font_fallback_linux.h"
#include "ui/gfx/font_render_params.h"
-using blink::WebCString;
-using blink::WebFontInfo;
-using blink::WebUChar;
-using blink::WebUChar32;
-
namespace content {
namespace {
@@ -167,12 +160,12 @@ void SandboxIPCHandler::HandleRequestFromRenderer(int fd) {
}
int SandboxIPCHandler::FindOrAddPath(const SkString& path) {
- int count = paths_.count();
+ int count = paths_.size();
for (int i = 0; i < count; ++i) {
- if (path == *paths_[i])
+ if (path == paths_[i])
return i;
}
- *paths_.append() = new SkString(path);
+ paths_.emplace_back(path);
return count;
}
@@ -221,9 +214,9 @@ void SandboxIPCHandler::HandleFontOpenRequest(
uint32_t index;
if (!iter.ReadUInt32(&index))
return;
- if (index >= static_cast<uint32_t>(paths_.count()))
+ if (index >= static_cast<uint32_t>(paths_.size()))
return;
- const int result_fd = open(paths_[index]->c_str(), O_RDONLY);
+ const int result_fd = open(paths_[index].c_str(), O_RDONLY);
base::Pickle reply;
if (result_fd == -1) {
@@ -249,8 +242,7 @@ void SandboxIPCHandler::HandleGetFallbackFontForChar(
// The other side of this call is
// content/common/child_process_sandbox_support_impl_linux.cc
- EnsureWebKitInitialized();
- WebUChar32 c;
+ UChar32 c;
if (!iter.ReadInt(&c))
return;
@@ -258,27 +250,17 @@ void SandboxIPCHandler::HandleGetFallbackFontForChar(
if (!iter.ReadString(&preferred_locale))
return;
- blink::WebFallbackFont fallbackFont;
- WebFontInfo::fallbackFontForChar(c, preferred_locale.c_str(), &fallbackFont);
-
- int pathIndex = FindOrAddPath(SkString(fallbackFont.filename.data()));
- fallbackFont.fontconfigInterfaceId = pathIndex;
+ auto fallback_font = gfx::GetFallbackFontForChar(c, preferred_locale);
+ int fontconfig_interface_id =
+ FindOrAddPath(SkString(fallback_font.filename.data()));
base::Pickle reply;
- if (fallbackFont.name.data()) {
- reply.WriteString(fallbackFont.name.data());
- } else {
- reply.WriteString(std::string());
- }
- if (fallbackFont.filename.data()) {
- reply.WriteString(fallbackFont.filename.data());
- } else {
- reply.WriteString(std::string());
- }
- reply.WriteInt(fallbackFont.fontconfigInterfaceId);
- reply.WriteInt(fallbackFont.ttcIndex);
- reply.WriteBool(fallbackFont.isBold);
- reply.WriteBool(fallbackFont.isItalic);
+ reply.WriteString(fallback_font.name);
+ reply.WriteString(fallback_font.filename);
+ reply.WriteInt(fontconfig_interface_id);
+ reply.WriteInt(fallback_font.ttc_index);
+ reply.WriteBool(fallback_font.is_bold);
+ reply.WriteBool(fallback_font.is_italic);
SendRendererReply(fds, reply, -1);
}
@@ -297,8 +279,6 @@ void SandboxIPCHandler::HandleGetStyleForStrike(
return;
}
- EnsureWebKitInitialized();
-
gfx::FontRenderParamsQuery query;
query.families.push_back(family);
query.pixel_size = pixel_size;
@@ -434,21 +414,10 @@ void SandboxIPCHandler::SendRendererReply(
}
SandboxIPCHandler::~SandboxIPCHandler() {
- paths_.deleteAll();
- if (blink_platform_impl_)
- blink::shutdownWithoutV8();
-
if (IGNORE_EINTR(close(lifeline_fd_)) < 0)
PLOG(ERROR) << "close";
if (IGNORE_EINTR(close(browser_socket_)) < 0)
PLOG(ERROR) << "close";
}
-void SandboxIPCHandler::EnsureWebKitInitialized() {
- if (blink_platform_impl_)
- return;
- blink_platform_impl_.reset(new BlinkPlatformImpl);
- blink::initializeWithoutV8(blink_platform_impl_.get());
-}
-
} // namespace content
diff --git a/chromium/content/browser/renderer_host/sandbox_ipc_linux.h b/chromium/content/browser/renderer_host/sandbox_ipc_linux.h
index a11a8787237..f1a6bd5ea3a 100644
--- a/chromium/content/browser/renderer_host/sandbox_ipc_linux.h
+++ b/chromium/content/browser/renderer_host/sandbox_ipc_linux.h
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// http://code.google.com/p/chromium/wiki/LinuxSandboxIPC
+// https://chromium.googlesource.com/chromium/src/+/master/docs/linux_sandbox_ipc.md
#ifndef CONTENT_BROWSER_RENDERER_HOST_SANDBOX_IPC_LINUX_H_
#define CONTENT_BROWSER_RENDERER_HOST_SANDBOX_IPC_LINUX_H_
@@ -14,7 +14,6 @@
#include "base/memory/scoped_ptr.h"
#include "base/pickle.h"
#include "base/threading/simple_thread.h"
-#include "content/child/blink_platform_impl.h"
#include "skia/ext/skia_utils_base.h"
namespace content {
@@ -30,8 +29,6 @@ class SandboxIPCHandler : public base::DelegateSimpleThread::Delegate {
void Run() override;
private:
- void EnsureWebKitInitialized();
-
int FindOrAddPath(const SkString& path);
void HandleRequestFromRenderer(int fd);
@@ -70,8 +67,7 @@ class SandboxIPCHandler : public base::DelegateSimpleThread::Delegate {
const int lifeline_fd_;
const int browser_socket_;
- scoped_ptr<BlinkPlatformImpl> blink_platform_impl_;
- SkTDArray<SkString*> paths_;
+ std::vector<SkString> paths_;
DISALLOW_COPY_AND_ASSIGN(SandboxIPCHandler);
};
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 aa265fca27c..51cb7893d91 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
@@ -148,7 +148,6 @@ TEST_F(TextInputClientMacTest, TimeoutCharacterIndex) {
TEST_F(TextInputClientMacTest, NotFoundCharacterIndex) {
ScopedTestingThread thread(this);
const NSUInteger kPreviousValue = 42;
- const size_t kNotFoundValue = static_cast<size_t>(-1);
// Set an arbitrary value to ensure the index is not |NSNotFound|.
PostTask(FROM_HERE,
@@ -159,7 +158,7 @@ TEST_F(TextInputClientMacTest, NotFoundCharacterIndex) {
new TextInputClientMessageFilter(widget()->GetProcess()->GetID()));
scoped_ptr<IPC::Message> message(
new TextInputClientReplyMsg_GotCharacterIndexForPoint(
- widget()->GetRoutingID(), kNotFoundValue));
+ widget()->GetRoutingID(), UINT32_MAX));
// Set |WTF::notFound| to the index |kTaskDelayMs| after the previous
// setting.
PostTask(FROM_HERE,
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 94000653867..95780b055d8 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
@@ -38,7 +38,7 @@ class CONTENT_EXPORT TextInputClientMessageFilter
void OnGotStringAtPoint(
const mac::AttributedStringCoder::EncodedString& encoded_string,
const gfx::Point& point);
- void OnGotCharacterIndexForPoint(size_t index);
+ void OnGotCharacterIndexForPoint(uint32_t index);
void OnGotFirstRectForRange(const gfx::Rect& rect);
void OnGotStringFromRange(
const mac::AttributedStringCoder::EncodedString& string,
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 34e9467826d..56dba28480d 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
@@ -48,14 +48,17 @@ void TextInputClientMessageFilter::OnGotStringAtPoint(
service->GetStringAtPointReply(string, NSPointFromCGPoint(point.ToCGPoint()));
}
-void TextInputClientMessageFilter::OnGotCharacterIndexForPoint(size_t index) {
+void TextInputClientMessageFilter::OnGotCharacterIndexForPoint(uint32_t index) {
TextInputClientMac* service = TextInputClientMac::GetInstance();
// |index| could be WTF::notFound (-1) and its value is different from
// NSNotFound so we need to convert it.
- if (index == static_cast<size_t>(-1)) {
- index = NSNotFound;
+ size_t char_index;
+ if (index == UINT32_MAX) {
+ char_index = NSNotFound;
+ } else {
+ char_index = index;
}
- service->SetCharacterIndexAndSignal(index);
+ service->SetCharacterIndexAndSignal(char_index);
}
void TextInputClientMessageFilter::OnGotFirstRectForRange(
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 c4ed46155bd..59bc129469d 100644
--- a/chromium/content/browser/renderer_host/web_input_event_aura.cc
+++ b/chromium/content/browser/renderer_host/web_input_event_aura.cc
@@ -399,11 +399,11 @@ blink::WebMouseEvent MakeWebMouseEventFromAuraEvent(
break;
}
- webkit_event.tiltX = roundf(event.pointer_details().tilt_x());
- webkit_event.tiltY = roundf(event.pointer_details().tilt_y());
- webkit_event.force = event.pointer_details().force();
+ webkit_event.tiltX = roundf(event.pointer_details().tilt_x);
+ webkit_event.tiltY = roundf(event.pointer_details().tilt_y);
+ webkit_event.force = event.pointer_details().force;
webkit_event.pointerType =
- EventPointerTypeToWebPointerType(event.pointer_details().pointer_type());
+ EventPointerTypeToWebPointerType(event.pointer_details().pointer_type);
return webkit_event;
}
@@ -428,11 +428,11 @@ blink::WebMouseWheelEvent MakeWebMouseWheelEventFromAuraEvent(
webkit_event.wheelTicksX = webkit_event.deltaX / kPixelsPerTick;
webkit_event.wheelTicksY = webkit_event.deltaY / kPixelsPerTick;
- webkit_event.tiltX = roundf(event.pointer_details().tilt_x());
- webkit_event.tiltY = roundf(event.pointer_details().tilt_y());
- webkit_event.force = event.pointer_details().force();
+ webkit_event.tiltX = roundf(event.pointer_details().tilt_x);
+ webkit_event.tiltY = roundf(event.pointer_details().tilt_y);
+ webkit_event.force = event.pointer_details().force;
webkit_event.pointerType =
- EventPointerTypeToWebPointerType(event.pointer_details().pointer_type());
+ EventPointerTypeToWebPointerType(event.pointer_details().pointer_type);
return webkit_event;
}
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 2d46dfb2e40..412c607eeeb 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
@@ -21,7 +21,7 @@
#include <X11/keysym.h>
#include <X11/Xlib.h>
#include "ui/events/test/events_test_utils_x11.h"
-#include "ui/gfx/x/x11_types.h"
+#include "ui/gfx/x/x11_types.h" // nogncheck
#endif
namespace content {
@@ -425,7 +425,7 @@ TEST(WebInputEventAuraTest, TestMakeWebMouseEvent) {
webkit_event.pointerType);
EXPECT_EQ(0, webkit_event.tiltX);
EXPECT_EQ(0, webkit_event.tiltY);
- EXPECT_FLOAT_EQ(0.0f, webkit_event.force);
+ EXPECT_TRUE(std::isnan(webkit_event.force));
EXPECT_EQ(123, webkit_event.x);
EXPECT_EQ(123, webkit_event.windowX);
EXPECT_EQ(321, webkit_event.y);
@@ -478,7 +478,7 @@ TEST(WebInputEventAuraTest, TestMakeWebMouseWheelEvent) {
webkit_event.pointerType);
EXPECT_EQ(0, webkit_event.tiltX);
EXPECT_EQ(0, webkit_event.tiltY);
- EXPECT_FLOAT_EQ(0.0f, webkit_event.force);
+ EXPECT_TRUE(std::isnan(webkit_event.force));
EXPECT_EQ(123, webkit_event.x);
EXPECT_EQ(123, webkit_event.windowX);
EXPECT_EQ(321, webkit_event.y);
@@ -503,7 +503,7 @@ TEST(WebInputEventAuraTest, TestMakeWebMouseWheelEvent) {
webkit_event.pointerType);
EXPECT_EQ(0, webkit_event.tiltX);
EXPECT_EQ(0, webkit_event.tiltY);
- EXPECT_FLOAT_EQ(0.0f, webkit_event.force);
+ EXPECT_TRUE(std::isnan(webkit_event.force));
EXPECT_EQ(123, webkit_event.x);
EXPECT_EQ(123, webkit_event.windowX);
EXPECT_EQ(321, webkit_event.y);
diff --git a/chromium/content/browser/renderer_host/websocket_blob_sender.cc b/chromium/content/browser/renderer_host/websocket_blob_sender.cc
new file mode 100644
index 00000000000..8fe56fd4deb
--- /dev/null
+++ b/chromium/content/browser/renderer_host/websocket_blob_sender.cc
@@ -0,0 +1,284 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/websocket_blob_sender.h"
+
+#include <algorithm>
+#include <ostream>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback_helpers.h"
+#include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
+#include "content/browser/renderer_host/websocket_dispatcher_host.h"
+#include "content/browser/renderer_host/websocket_host.h"
+#include "net/base/io_buffer.h"
+#include "net/base/net_errors.h"
+#include "net/websockets/websocket_channel.h"
+#include "net/websockets/websocket_frame.h"
+#include "storage/browser/blob/blob_data_handle.h"
+#include "storage/browser/blob/blob_reader.h"
+#include "storage/browser/blob/blob_storage_context.h"
+
+namespace content {
+
+namespace {
+
+using storage::BlobReader;
+using storage::BlobDataHandle;
+using storage::BlobStorageContext;
+
+// This must be smaller than the send quota high water mark or this class will
+// never send anything.
+const int kMinimumNonFinalFrameSize = 8 * 1024;
+
+// The IOBuffer has a fixed size for simplicity.
+const size_t kBufferSize = 128 * 1024;
+
+} // namespace
+
+// This is needed to make DCHECK_EQ(), etc. compile.
+std::ostream& operator<<(std::ostream& os, WebSocketBlobSender::State state) {
+ static const char* const kStateStrings[] = {
+ "NONE",
+ "READ_SIZE",
+ "READ_SIZE_COMPLETE",
+ "WAIT_FOR_QUOTA",
+ "WAIT_FOR_QUOTA_COMPLETE",
+ "READ",
+ "READ_COMPLETE",
+ };
+ if (state < WebSocketBlobSender::State::NONE ||
+ state > WebSocketBlobSender::State::READ_COMPLETE) {
+ return os << "Bad State (" << static_cast<int>(state) << ")";
+ }
+ return os << kStateStrings[static_cast<int>(state)];
+}
+
+WebSocketBlobSender::WebSocketBlobSender(scoped_ptr<Channel> channel)
+ : channel_(std::move(channel)) {}
+
+WebSocketBlobSender::~WebSocketBlobSender() {}
+
+int WebSocketBlobSender::Start(
+ const std::string& uuid,
+ uint64_t expected_size,
+ BlobStorageContext* context,
+ storage::FileSystemContext* file_system_context,
+ base::SingleThreadTaskRunner* file_task_runner,
+ net::WebSocketEventInterface::ChannelState* channel_state,
+ const net::CompletionCallback& callback) {
+ DCHECK(context);
+ DCHECK(channel_state);
+ DCHECK(!reader_);
+ scoped_ptr<storage::BlobDataHandle> data_handle(
+ context->GetBlobDataFromUUID(uuid));
+ if (!data_handle)
+ return net::ERR_INVALID_HANDLE;
+ reader_ = data_handle->CreateReader(file_system_context, file_task_runner);
+ expected_size_ = expected_size;
+ next_state_ = State::READ_SIZE;
+ int rv = DoLoop(net::OK, channel_state);
+ if (*channel_state == net::WebSocketEventInterface::CHANNEL_ALIVE &&
+ rv == net::ERR_IO_PENDING) {
+ callback_ = callback;
+ }
+ return rv;
+}
+
+void WebSocketBlobSender::OnNewSendQuota() {
+ if (next_state_ == State::WAIT_FOR_QUOTA)
+ DoLoopAsync(net::OK);
+ // |this| may be deleted.
+}
+
+uint64_t WebSocketBlobSender::ActualSize() const {
+ return reader_->total_size();
+}
+
+void WebSocketBlobSender::OnReadComplete(int rv) {
+ DCHECK_EQ(State::READ_COMPLETE, next_state_);
+ DoLoopAsync(rv);
+ // |this| may be deleted.
+}
+
+void WebSocketBlobSender::OnSizeCalculated(int rv) {
+ DCHECK_EQ(State::READ_SIZE_COMPLETE, next_state_);
+ DoLoopAsync(rv);
+ // |this| may be deleted.
+}
+
+int WebSocketBlobSender::DoLoop(int result,
+ Channel::ChannelState* channel_state) {
+ DCHECK_NE(State::NONE, next_state_);
+ int rv = result;
+ do {
+ State state = next_state_;
+ next_state_ = State::NONE;
+ switch (state) {
+ case State::READ_SIZE:
+ DCHECK_EQ(net::OK, rv);
+ rv = DoReadSize();
+ break;
+
+ case State::READ_SIZE_COMPLETE:
+ rv = DoReadSizeComplete(rv);
+ break;
+
+ case State::WAIT_FOR_QUOTA:
+ DCHECK_EQ(net::OK, rv);
+ rv = DoWaitForQuota();
+ break;
+
+ case State::WAIT_FOR_QUOTA_COMPLETE:
+ DCHECK_EQ(net::OK, rv);
+ rv = DoWaitForQuotaComplete();
+ break;
+
+ case State::READ:
+ DCHECK_EQ(net::OK, rv);
+ rv = DoRead();
+ break;
+
+ case State::READ_COMPLETE:
+ rv = DoReadComplete(rv, channel_state);
+ break;
+
+ default:
+ NOTREACHED();
+ break;
+ }
+ } while (*channel_state != net::WebSocketEventInterface::CHANNEL_DELETED &&
+ rv != net::ERR_IO_PENDING && next_state_ != State::NONE);
+ return rv;
+}
+
+void WebSocketBlobSender::DoLoopAsync(int result) {
+ Channel::ChannelState channel_state =
+ net::WebSocketEventInterface::CHANNEL_ALIVE;
+ int rv = DoLoop(result, &channel_state);
+ if (channel_state == net::WebSocketEventInterface::CHANNEL_ALIVE &&
+ rv != net::ERR_IO_PENDING) {
+ ResetAndReturn(&callback_).Run(rv);
+ }
+ // |this| may be deleted.
+}
+
+int WebSocketBlobSender::DoReadSize() {
+ next_state_ = State::READ_SIZE_COMPLETE;
+ // This use of base::Unretained() is safe because BlobReader cannot call the
+ // callback after it has been destroyed, and it is owned by this object.
+ BlobReader::Status status = reader_->CalculateSize(base::Bind(
+ &WebSocketBlobSender::OnSizeCalculated, base::Unretained(this)));
+ switch (status) {
+ case BlobReader::Status::NET_ERROR:
+ return reader_->net_error();
+
+ case BlobReader::Status::IO_PENDING:
+ return net::ERR_IO_PENDING;
+
+ case BlobReader::Status::DONE:
+ return net::OK;
+ }
+ NOTREACHED();
+ return net::ERR_UNEXPECTED;
+}
+
+int WebSocketBlobSender::DoReadSizeComplete(int result) {
+ if (result < 0)
+ return result;
+ if (reader_->total_size() != expected_size_)
+ return net::ERR_UPLOAD_FILE_CHANGED;
+ bytes_left_ = expected_size_;
+ // The result of the call to std::min() must fit inside a size_t because
+ // kBufferSize is type size_t.
+ size_t buffer_size = static_cast<size_t>(
+ std::min(bytes_left_, base::strict_cast<uint64_t>(kBufferSize)));
+ buffer_ = new net::IOBuffer(buffer_size);
+ next_state_ = State::WAIT_FOR_QUOTA;
+ return net::OK;
+}
+
+// The WAIT_FOR_QUOTA state has a self-edge; it will wait in this state until
+// there is enough quota to send some data.
+int WebSocketBlobSender::DoWaitForQuota() {
+ size_t quota = channel_->GetSendQuota();
+ if (kMinimumNonFinalFrameSize <= quota || bytes_left_ <= quota) {
+ next_state_ = State::WAIT_FOR_QUOTA_COMPLETE;
+ return net::OK;
+ }
+ next_state_ = State::WAIT_FOR_QUOTA;
+ return net::ERR_IO_PENDING;
+}
+
+// State::WAIT_FOR_QUOTA_COMPLETE exists just to give the state machine the
+// expected shape. It should be mostly optimised out.
+int WebSocketBlobSender::DoWaitForQuotaComplete() {
+ next_state_ = State::READ;
+ return net::OK;
+}
+
+int WebSocketBlobSender::DoRead() {
+ next_state_ = State::READ_COMPLETE;
+ size_t quota = channel_->GetSendQuota();
+ // |desired_bytes| must fit in a size_t because |quota| is of type
+ // size_t and so cannot be larger than its maximum value.
+ size_t desired_bytes =
+ static_cast<size_t>(std::min(bytes_left_, static_cast<uint64_t>(quota)));
+
+ // For simplicity this method only reads as many bytes as are currently
+ // needed.
+ size_t bytes_to_read = std::min(desired_bytes, kBufferSize);
+ int bytes_read = 0;
+ DCHECK(reader_);
+ DCHECK(buffer_);
+
+ // This use of base::Unretained is safe because the BlobReader object won't
+ // call the callback after it has been destroyed, and it belongs to this
+ // object.
+ BlobReader::Status status = reader_->Read(
+ buffer_.get(), bytes_to_read, &bytes_read,
+ base::Bind(&WebSocketBlobSender::OnReadComplete, base::Unretained(this)));
+
+ switch (status) {
+ case BlobReader::Status::NET_ERROR:
+ return reader_->net_error();
+
+ case BlobReader::Status::IO_PENDING:
+ return net::ERR_IO_PENDING;
+
+ case BlobReader::Status::DONE:
+ return bytes_read;
+ }
+ NOTREACHED();
+ return net::ERR_UNEXPECTED;
+}
+
+int WebSocketBlobSender::DoReadComplete(int result,
+ Channel::ChannelState* channel_state) {
+ if (result < 0)
+ return result;
+ DCHECK_GE(channel_->GetSendQuota(), static_cast<size_t>(result));
+ uint64_t bytes_read = static_cast<uint64_t>(result);
+ DCHECK_GE(bytes_left_, bytes_read);
+ bytes_left_ -= bytes_read;
+ bool fin = bytes_left_ == 0;
+ std::vector<char> data(buffer_->data(), buffer_->data() + bytes_read);
+ DCHECK(fin || data.size() > 0u) << "Non-final frames should be non-empty";
+ *channel_state = channel_->SendFrame(fin, data);
+ if (*channel_state == net::WebSocketEventInterface::CHANNEL_DELETED) {
+ // |this| is deleted.
+ return net::ERR_CONNECTION_RESET;
+ }
+
+ // It is important not to set next_state_ until after the call to SendFrame()
+ // because SendFrame() will sometimes call OnNewSendQuota() synchronously.
+ if (!fin)
+ next_state_ = State::WAIT_FOR_QUOTA;
+ return net::OK;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/websocket_blob_sender.h b/chromium/content/browser/renderer_host/websocket_blob_sender.h
new file mode 100644
index 00000000000..6dcfe7328a6
--- /dev/null
+++ b/chromium/content/browser/renderer_host/websocket_blob_sender.h
@@ -0,0 +1,139 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_RENDERER_HOST_WEBSOCKET_BLOB_SENDER_H_
+#define CONTENT_BROWSER_RENDERER_HOST_WEBSOCKET_BLOB_SENDER_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include <iosfwd>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+#include "net/base/completion_callback.h"
+#include "net/websockets/websocket_event_interface.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace net {
+class IOBuffer;
+}
+
+namespace storage {
+class BlobReader;
+class BlobStorageContext;
+class FileSystemContext;
+}
+
+namespace content {
+
+class WebSocketHost;
+
+// Read the contents of a Blob and write it to a WebSocket. Single-use: a new
+// object must be created each time a Blob is sent. Destroying the object
+// cancels all pending operations.
+class CONTENT_EXPORT WebSocketBlobSender final {
+ public:
+ // An abstraction of the WebSocketChannel this object will send frames to.
+ class Channel {
+ public:
+ using ChannelState = net::WebSocketEventInterface::ChannelState;
+
+ Channel() {}
+ virtual ~Channel() {}
+
+ // The currently available quota for sending. It must not decrease without
+ // SendFrame() being called.
+ virtual size_t GetSendQuota() const = 0;
+
+ // Send a binary frame. |fin| is true for the final frame of the message.
+ // |data| is the contents of the frame. data.size() must be less than
+ // GetSendQuota(). If this call returns CHANNEL_DELETED, WebSocketBlobSender
+ // will assume that it has been deleted and return without calling any
+ // callbacks or accessing any other member data.
+ virtual ChannelState SendFrame(bool fin, const std::vector<char>& data) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Channel);
+ };
+
+ // |channel| will be destroyed when this object is.
+ explicit WebSocketBlobSender(scoped_ptr<Channel> channel);
+ ~WebSocketBlobSender();
+
+ // Checks that the blob identified by |uuid| exists, has the size
+ // |expected_size| and then starts sending it via |channel_|. Returns
+ // ERR_IO_PENDING to indicate that |callback| will be called later with the
+ // result. net::OK indicates synchronous success. Any other net error code
+ // indicates synchronous failure. This method may result in the destruction of
+ // the channel, in which case |*channel_state| will be set to CHANNEL_DELETED.
+ int Start(const std::string& uuid,
+ uint64_t expected_size,
+ storage::BlobStorageContext* context,
+ storage::FileSystemContext* file_system_context,
+ base::SingleThreadTaskRunner* file_task_runner,
+ net::WebSocketEventInterface::ChannelState* channel_state,
+ const net::CompletionCallback& callback);
+
+ // Sends more data if the object was waiting for quota and the new value of
+ // GetSendQuota() is large enough.
+ void OnNewSendQuota();
+
+ uint64_t expected_size() const { return expected_size_; }
+
+ // ActualSize() should only be called after completion: ie. Start() returned a
+ // value other than ERR_IO_PENDING or |callback_| has been called.
+ uint64_t ActualSize() const;
+
+ private:
+ // State proceeds through READ_SIZE and READ_SIZE_COMPLETE, then
+ // loops WAIT_FOR_QUOTA -> WAIT_FOR_QUOTA_COMPLETE -> READ
+ // -> READ_COMPLETE -> WAIT_FOR_QUOTA until the Blob is completely
+ // sent.
+ enum class State {
+ NONE = 0,
+ READ_SIZE,
+ READ_SIZE_COMPLETE,
+ WAIT_FOR_QUOTA,
+ WAIT_FOR_QUOTA_COMPLETE,
+ READ,
+ READ_COMPLETE,
+ };
+
+ // This is needed to make DCHECK_EQ(), etc. compile.
+ friend std::ostream& operator<<(std::ostream& os, State state);
+
+ void OnReadComplete(int rv);
+ void OnSizeCalculated(int rv);
+ // |channel_state| should point to CHANNEL_ALIVE when called. If it is
+ // CHANNEL_DELETED on return, the object has been deleted.
+ int DoLoop(int result, Channel::ChannelState* channel_state);
+ void DoLoopAsync(int result);
+ int DoReadSize();
+ int DoReadSizeComplete(int result);
+ int DoWaitForQuota();
+ int DoWaitForQuotaComplete();
+ int DoRead();
+ int DoReadComplete(int result, Channel::ChannelState* channel_state);
+
+ State next_state_ = State::NONE;
+ uint64_t expected_size_ = 0;
+ uint64_t bytes_left_ = 0;
+ net::CompletionCallback callback_;
+ scoped_refptr<net::IOBuffer> buffer_;
+ scoped_ptr<storage::BlobReader> reader_;
+ const scoped_ptr<Channel> channel_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebSocketBlobSender);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_RENDERER_HOST_WEBSOCKET_BLOB_SENDER_H_
diff --git a/chromium/content/browser/renderer_host/websocket_blob_sender_unittest.cc b/chromium/content/browser/renderer_host/websocket_blob_sender_unittest.cc
new file mode 100644
index 00000000000..fe2f936d123
--- /dev/null
+++ b/chromium/content/browser/renderer_host/websocket_blob_sender_unittest.cc
@@ -0,0 +1,446 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/renderer_host/websocket_blob_sender.h"
+
+#include <string.h>
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "base/files/file.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/location.h"
+#include "base/memory/weak_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/task_runner.h"
+#include "base/time/time.h"
+#include "content/browser/fileapi/chrome_blob_storage_context.h"
+#include "content/public/browser/blob_handle.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/storage_partition.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "net/base/completion_callback.h"
+#include "net/base/net_errors.h"
+#include "net/base/test_completion_callback.h"
+#include "storage/common/fileapi/file_system_types.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace {
+
+const char kDummyUrl[] = "http://www.example.com/";
+const char kBanana[] = "banana";
+
+// This is small so that the tests do not waste too much time just copying bytes
+// around. But it has to be larger than kMinimumNonFinalFrameSize defined in
+// websocket_blob_sender.cc.
+const size_t kInitialQuota = 16 * 1024;
+
+using net::TestCompletionCallback;
+
+// A fake channel for testing. Records the contents of the message that was sent
+// through it. Quota is restricted, and is refreshed asynchronously in response
+// to calls to SendFrame().
+class FakeChannel : public WebSocketBlobSender::Channel {
+ public:
+ // |notify_new_quota| will be run asynchronously on the current MessageLoop
+ // every time GetSendQuota() increases.
+ FakeChannel() : weak_factory_(this) {}
+
+ // This method must be called before SendFrame() is.
+ void set_notify_new_quota(const base::Closure& notify_new_quota) {
+ notify_new_quota_ = notify_new_quota;
+ }
+
+ size_t GetSendQuota() const override { return current_send_quota_; }
+
+ ChannelState SendFrame(bool fin, const std::vector<char>& data) override {
+ ++frames_sent_;
+ EXPECT_FALSE(got_fin_);
+ if (fin)
+ got_fin_ = true;
+ EXPECT_LE(data.size(), current_send_quota_);
+ message_.insert(message_.end(), data.begin(), data.end());
+ current_send_quota_ -= data.size();
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&FakeChannel::RefreshQuota, weak_factory_.GetWeakPtr()));
+ return net::WebSocketEventInterface::CHANNEL_ALIVE;
+ }
+
+ bool got_fin() const { return got_fin_; }
+
+ int frames_sent() const { return frames_sent_; }
+
+ const std::vector<char>& message() const { return message_; }
+
+ private:
+ void RefreshQuota() {
+ if (current_send_quota_ == kInitialQuota)
+ return;
+ current_send_quota_ = kInitialQuota;
+ DCHECK(!notify_new_quota_.is_null());
+ notify_new_quota_.Run();
+ }
+
+ base::Closure notify_new_quota_;
+ size_t current_send_quota_ = kInitialQuota;
+ int frames_sent_ = 0;
+ bool got_fin_ = false;
+ std::vector<char> message_;
+ base::WeakPtrFactory<FakeChannel> weak_factory_;
+};
+
+class WebSocketBlobSenderTest : public ::testing::Test {
+ protected:
+ // The Windows implementation of net::FileStream::Context requires a real IO
+ // MessageLoop.
+ WebSocketBlobSenderTest()
+ : threads_(TestBrowserThreadBundle::IO_MAINLOOP),
+ chrome_blob_storage_context_(
+ ChromeBlobStorageContext::GetFor(&browser_context_)),
+ fake_channel_(nullptr),
+ sender_() {}
+ ~WebSocketBlobSenderTest() override {}
+
+ void SetUp() override {
+ // ChromeBlobStorageContext::GetFor() does some work asynchronously.
+ base::RunLoop().RunUntilIdle();
+ SetUpSender();
+ }
+
+ // This method can be overriden to use a different channel implementation.
+ virtual void SetUpSender() {
+ fake_channel_ = new FakeChannel;
+ sender_.reset(new WebSocketBlobSender(make_scoped_ptr(fake_channel_)));
+ fake_channel_->set_notify_new_quota(base::Bind(
+ &WebSocketBlobSender::OnNewSendQuota, base::Unretained(sender_.get())));
+ }
+
+ storage::BlobStorageContext* context() {
+ return chrome_blob_storage_context_->context();
+ }
+
+ storage::FileSystemContext* GetFileSystemContext() {
+ StoragePartition* partition = BrowserContext::GetStoragePartitionForSite(
+ &browser_context_, GURL(kDummyUrl));
+ return partition->GetFileSystemContext();
+ }
+
+ // |string| is copied.
+ scoped_ptr<BlobHandle> CreateMemoryBackedBlob(const char* string) {
+ scoped_ptr<BlobHandle> handle =
+ chrome_blob_storage_context_->CreateMemoryBackedBlob(string,
+ strlen(string));
+ EXPECT_TRUE(handle);
+ return handle;
+ }
+
+ // Call sender_.Start() with the other parameters filled in appropriately for
+ // this test fixture.
+ int Start(const std::string& uuid,
+ uint64_t expected_size,
+ const net::CompletionCallback& callback) {
+ net::WebSocketEventInterface::ChannelState channel_state =
+ net::WebSocketEventInterface::CHANNEL_ALIVE;
+ return sender_->Start(
+ uuid, expected_size, context(), GetFileSystemContext(),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE).get(),
+ &channel_state, callback);
+ }
+
+ void NotCalledCallbackImpl(int rv) {
+ ADD_FAILURE()
+ << "Callback that should not be called was called with argument " << rv;
+ }
+
+ net::CompletionCallback NotCalled() {
+ return base::Bind(&WebSocketBlobSenderTest::NotCalledCallbackImpl,
+ base::Unretained(this));
+ }
+
+ void ExpectOkAndQuit(base::RunLoop* run_loop, int result) {
+ EXPECT_EQ(net::OK, result);
+ run_loop->Quit();
+ }
+
+ net::CompletionCallback ExpectOkAndQuitCallback(base::RunLoop* run_loop) {
+ return base::Bind(&WebSocketBlobSenderTest::ExpectOkAndQuit,
+ base::Unretained(this), run_loop);
+ }
+
+ TestBrowserThreadBundle threads_;
+ TestBrowserContext browser_context_;
+ scoped_refptr<ChromeBlobStorageContext> chrome_blob_storage_context_;
+ // |fake_channel_| is owned by |sender_|.
+ FakeChannel* fake_channel_;
+ scoped_ptr<WebSocketBlobSender> sender_;
+};
+
+TEST_F(WebSocketBlobSenderTest, Construction) {}
+
+TEST_F(WebSocketBlobSenderTest, EmptyBlob) {
+ scoped_ptr<BlobHandle> handle = CreateMemoryBackedBlob("");
+
+ // The APIs allow for this to be asynchronous but that is unlikely in
+ // practice.
+ int result = Start(handle->GetUUID(), UINT64_C(0), NotCalled());
+ // If this fails with result == -1, someone has changed the code to be
+ // asynchronous and this test should be adapted to match.
+ EXPECT_EQ(net::OK, result);
+ EXPECT_TRUE(fake_channel_->got_fin());
+ EXPECT_EQ(0U, fake_channel_->message().size());
+}
+
+TEST_F(WebSocketBlobSenderTest, SmallBlob) {
+ scoped_ptr<BlobHandle> handle = CreateMemoryBackedBlob(kBanana);
+
+ EXPECT_EQ(net::OK, Start(handle->GetUUID(), UINT64_C(6), NotCalled()));
+ EXPECT_TRUE(fake_channel_->got_fin());
+ EXPECT_EQ(1, fake_channel_->frames_sent());
+ EXPECT_EQ(std::vector<char>(kBanana, kBanana + 6), fake_channel_->message());
+}
+
+TEST_F(WebSocketBlobSenderTest, SizeMismatch) {
+ scoped_ptr<BlobHandle> handle = CreateMemoryBackedBlob(kBanana);
+
+ EXPECT_EQ(net::ERR_UPLOAD_FILE_CHANGED,
+ Start(handle->GetUUID(), UINT64_C(5), NotCalled()));
+ EXPECT_EQ(0, fake_channel_->frames_sent());
+}
+
+TEST_F(WebSocketBlobSenderTest, InvalidUUID) {
+ EXPECT_EQ(net::ERR_INVALID_HANDLE,
+ Start("sandwich", UINT64_C(0), NotCalled()));
+}
+
+TEST_F(WebSocketBlobSenderTest, LargeMessage) {
+ std::string message(kInitialQuota + 10, 'a');
+ scoped_ptr<BlobHandle> handle = CreateMemoryBackedBlob(message.c_str());
+
+ base::RunLoop run_loop;
+ int rv = Start(handle->GetUUID(), message.size(),
+ ExpectOkAndQuitCallback(&run_loop));
+ EXPECT_EQ(net::ERR_IO_PENDING, rv);
+ EXPECT_EQ(1, fake_channel_->frames_sent());
+ run_loop.Run();
+ EXPECT_EQ(2, fake_channel_->frames_sent());
+ EXPECT_TRUE(fake_channel_->got_fin());
+ std::vector<char> expected_message(message.begin(), message.end());
+ EXPECT_EQ(expected_message, fake_channel_->message());
+}
+
+// A message exactly equal to the available quota should be sent in one frame.
+TEST_F(WebSocketBlobSenderTest, ExactSizeMessage) {
+ std::string message(kInitialQuota, 'a');
+ scoped_ptr<BlobHandle> handle = CreateMemoryBackedBlob(message.c_str());
+
+ EXPECT_EQ(net::OK, Start(handle->GetUUID(), message.size(), NotCalled()));
+ EXPECT_EQ(1, fake_channel_->frames_sent());
+ EXPECT_TRUE(fake_channel_->got_fin());
+ std::vector<char> expected_message(message.begin(), message.end());
+ EXPECT_EQ(expected_message, fake_channel_->message());
+}
+
+// If the connection is closed while sending a message, the WebSocketBlobSender
+// object will be destroyed. It needs to handle this case without error.
+TEST_F(WebSocketBlobSenderTest, AbortedSend) {
+ std::string message(kInitialQuota + 10, 'a');
+ scoped_ptr<BlobHandle> handle = CreateMemoryBackedBlob(message.c_str());
+
+ int rv = Start(handle->GetUUID(), message.size(), NotCalled());
+ EXPECT_EQ(net::ERR_IO_PENDING, rv);
+ sender_.reset();
+}
+
+// Invalid file-backed blob.
+TEST_F(WebSocketBlobSenderTest, InvalidFileBackedBlob) {
+ base::FilePath path(FILE_PATH_LITERAL(
+ "WebSocketBlobSentTest.InvalidFileBackedBlob.NonExistentFile"));
+ scoped_ptr<BlobHandle> handle =
+ chrome_blob_storage_context_->CreateFileBackedBlob(path, 0u, 32u,
+ base::Time::Now());
+ EXPECT_TRUE(handle);
+
+ TestCompletionCallback callback;
+ int rv =
+ callback.GetResult(Start(handle->GetUUID(), 5u, callback.callback()));
+ EXPECT_EQ(net::ERR_FILE_NOT_FOUND, rv);
+}
+
+// A test fixture that does the additional work necessary to create working
+// file-backed blobs.
+class WebSocketFileBackedBlobSenderTest : public WebSocketBlobSenderTest {
+ protected:
+ void SetUp() override {
+ WebSocketBlobSenderTest::SetUp();
+ // temp_dir_ is recursively deleted on destruction.
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ }
+
+ void CreateFile(const std::string& contents,
+ const base::FilePath& path,
+ base::File::Info* info) {
+ ASSERT_EQ(contents.size(), static_cast<size_t>(base::WriteFile(
+ path, contents.data(), contents.size())));
+ ASSERT_TRUE(base::GetFileInfo(path, info));
+ }
+
+ scoped_ptr<BlobHandle> CreateFileBackedBlob(const std::string& contents) {
+ base::FilePath path = temp_dir_.path().AppendASCII("blob.dat");
+ base::File::Info info;
+ CreateFile(contents, path, &info);
+ if (HasFatalFailure())
+ return nullptr;
+ return chrome_blob_storage_context_->CreateFileBackedBlob(
+ path, 0u, contents.size(), info.last_modified);
+ }
+
+ base::ScopedTempDir temp_dir_;
+};
+
+TEST_F(WebSocketFileBackedBlobSenderTest, EmptyBlob) {
+ scoped_ptr<BlobHandle> handle = CreateFileBackedBlob("");
+ ASSERT_TRUE(handle);
+
+ TestCompletionCallback callback;
+ int result = callback.GetResult(
+ Start(handle->GetUUID(), UINT64_C(0), callback.callback()));
+ EXPECT_EQ(net::OK, result);
+ EXPECT_TRUE(fake_channel_->got_fin());
+ EXPECT_EQ(0U, fake_channel_->message().size());
+}
+
+TEST_F(WebSocketFileBackedBlobSenderTest, SizeMismatch) {
+ scoped_ptr<BlobHandle> handle = CreateFileBackedBlob(kBanana);
+ ASSERT_TRUE(handle);
+
+ TestCompletionCallback callback;
+ int result = Start(handle->GetUUID(), UINT64_C(8), callback.callback());
+ // This test explicitly aims to test the asynchronous code path, otherwise it
+ // would be identical to the other SizeMismatch test above.
+ EXPECT_EQ(net::ERR_IO_PENDING, result);
+ EXPECT_EQ(net::ERR_UPLOAD_FILE_CHANGED, callback.WaitForResult());
+ EXPECT_EQ(0, fake_channel_->frames_sent());
+}
+
+TEST_F(WebSocketFileBackedBlobSenderTest, LargeMessage) {
+ std::string message = "the green potato had lunch with the angry cat. ";
+ while (message.size() <= kInitialQuota) {
+ message = message + message;
+ }
+ scoped_ptr<BlobHandle> handle = CreateFileBackedBlob(message);
+ ASSERT_TRUE(handle);
+
+ TestCompletionCallback callback;
+ int result = Start(handle->GetUUID(), message.size(), callback.callback());
+ EXPECT_EQ(net::OK, callback.GetResult(result));
+ std::vector<char> expected_message(message.begin(), message.end());
+ EXPECT_EQ(expected_message, fake_channel_->message());
+}
+
+// The WebSocketBlobSender needs to handle a connection close while doing file
+// IO cleanly.
+TEST_F(WebSocketFileBackedBlobSenderTest, Aborted) {
+ scoped_ptr<BlobHandle> handle = CreateFileBackedBlob(kBanana);
+
+ int rv = Start(handle->GetUUID(), UINT64_C(6), NotCalled());
+ EXPECT_EQ(net::ERR_IO_PENDING, rv);
+ sender_.reset();
+}
+
+class DeletingFakeChannel : public WebSocketBlobSender::Channel {
+ public:
+ explicit DeletingFakeChannel(
+ scoped_ptr<WebSocketBlobSender>* sender_to_delete)
+ : sender_(sender_to_delete) {}
+
+ size_t GetSendQuota() const override { return kInitialQuota; }
+
+ ChannelState SendFrame(bool fin, const std::vector<char>& data) override {
+ sender_->reset();
+ // |this| is deleted here.
+ return net::WebSocketEventInterface::CHANNEL_DELETED;
+ }
+
+ private:
+ scoped_ptr<WebSocketBlobSender>* sender_;
+};
+
+class WebSocketBlobSenderDeletingTest : public WebSocketBlobSenderTest {
+ protected:
+ void SetUpSender() override {
+ sender_.reset(new WebSocketBlobSender(
+ make_scoped_ptr(new DeletingFakeChannel(&sender_))));
+ }
+};
+
+// This test only does something useful when run under AddressSanitizer or a
+// similar tool that can detect use-after-free bugs.
+TEST_F(WebSocketBlobSenderDeletingTest, SenderDeleted) {
+ scoped_ptr<BlobHandle> handle = CreateMemoryBackedBlob(kBanana);
+
+ EXPECT_EQ(net::ERR_CONNECTION_RESET,
+ Start(handle->GetUUID(), UINT64_C(6), NotCalled()));
+ EXPECT_FALSE(sender_);
+}
+
+// SendFrame() calls OnSendNewQuota() synchronously while filling the operating
+// system's socket write buffer. The purpose of this Channel implementation is
+// to verify that the synchronous case works correctly.
+class SynchronousFakeChannel : public WebSocketBlobSender::Channel {
+ public:
+ // This method must be called before SendFrame() is.
+ void set_notify_new_quota(const base::Closure& notify_new_quota) {
+ notify_new_quota_ = notify_new_quota;
+ }
+
+ size_t GetSendQuota() const override { return kInitialQuota; }
+
+ ChannelState SendFrame(bool fin, const std::vector<char>& data) override {
+ message_.insert(message_.end(), data.begin(), data.end());
+ notify_new_quota_.Run();
+ return net::WebSocketEventInterface::CHANNEL_ALIVE;
+ }
+
+ const std::vector<char>& message() const { return message_; }
+
+ private:
+ base::Closure notify_new_quota_;
+ std::vector<char> message_;
+};
+
+class WebSocketBlobSenderSynchronousTest : public WebSocketBlobSenderTest {
+ protected:
+ void SetUpSender() override {
+ synchronous_fake_channel_ = new SynchronousFakeChannel;
+ sender_.reset(
+ new WebSocketBlobSender(make_scoped_ptr(synchronous_fake_channel_)));
+ synchronous_fake_channel_->set_notify_new_quota(base::Bind(
+ &WebSocketBlobSender::OnNewSendQuota, base::Unretained(sender_.get())));
+ }
+
+ SynchronousFakeChannel* synchronous_fake_channel_ = nullptr;
+};
+
+TEST_F(WebSocketBlobSenderSynchronousTest, LargeMessage) {
+ std::string message(kInitialQuota + 10, 'a');
+ scoped_ptr<BlobHandle> handle = CreateMemoryBackedBlob(message.c_str());
+
+ int rv = Start(handle->GetUUID(), message.size(), NotCalled());
+ EXPECT_EQ(net::OK, rv);
+ std::vector<char> expected_message(message.begin(), message.end());
+ EXPECT_EQ(expected_message, synchronous_fake_channel_->message());
+}
+
+} // namespace
+
+} // namespace content
diff --git a/chromium/content/browser/renderer_host/websocket_dispatcher_host.cc b/chromium/content/browser/renderer_host/websocket_dispatcher_host.cc
index 0cdf66383a5..e7049004b32 100644
--- a/chromium/content/browser/renderer_host/websocket_dispatcher_host.cc
+++ b/chromium/content/browser/renderer_host/websocket_dispatcher_host.cc
@@ -6,6 +6,7 @@
#include <stddef.h>
+#include <algorithm>
#include <string>
#include <vector>
@@ -15,6 +16,7 @@
#include "base/rand_util.h"
#include "base/stl_util.h"
#include "content/browser/child_process_security_policy_impl.h"
+#include "content/browser/fileapi/chrome_blob_storage_context.h"
#include "content/browser/renderer_host/websocket_host.h"
#include "content/common/websocket_messages.h"
@@ -35,7 +37,9 @@ const int kMaxPendingWebSocketConnections = 255;
WebSocketDispatcherHost::WebSocketDispatcherHost(
int process_id,
- const GetRequestContextCallback& get_context_callback)
+ const GetRequestContextCallback& get_context_callback,
+ ChromeBlobStorageContext* blob_storage_context,
+ StoragePartition* storage_partition)
: BrowserMessageFilter(WebSocketMsgStart),
process_id_(process_id),
get_context_callback_(get_context_callback),
@@ -46,7 +50,9 @@ WebSocketDispatcherHost::WebSocketDispatcherHost(
num_current_succeeded_connections_(0),
num_previous_succeeded_connections_(0),
num_current_failed_connections_(0),
- num_previous_failed_connections_(0) {}
+ num_previous_failed_connections_(0),
+ blob_storage_context_(blob_storage_context),
+ storage_partition_(storage_partition) {}
WebSocketDispatcherHost::WebSocketDispatcherHost(
int process_id,
@@ -60,7 +66,8 @@ WebSocketDispatcherHost::WebSocketDispatcherHost(
num_current_succeeded_connections_(0),
num_previous_succeeded_connections_(0),
num_current_failed_connections_(0),
- num_previous_failed_connections_(0) {}
+ num_previous_failed_connections_(0),
+ storage_partition_(nullptr) {}
WebSocketHost* WebSocketDispatcherHost::CreateWebSocketHost(
int routing_id,
@@ -72,6 +79,7 @@ WebSocketHost* WebSocketDispatcherHost::CreateWebSocketHost(
bool WebSocketDispatcherHost::OnMessageReceived(const IPC::Message& message) {
switch (message.type()) {
case WebSocketHostMsg_AddChannelRequest::ID:
+ case WebSocketHostMsg_SendBlob::ID:
case WebSocketMsg_SendFrame::ID:
case WebSocketMsg_FlowControl::ID:
case WebSocketMsg_DropChannel::ID:
@@ -95,9 +103,10 @@ bool WebSocketDispatcherHost::OnMessageReceived(const IPC::Message& message) {
return true; // We handled the message (by ignoring it).
}
if (num_pending_connections_ >= kMaxPendingWebSocketConnections) {
- if(!Send(new WebSocketMsg_NotifyFailure(routing_id,
- "Error in connection establishment: net::ERR_INSUFFICIENT_RESOURCES"
- ))) {
+ if (!Send(new WebSocketMsg_NotifyFailure(
+ routing_id,
+ "Error in connection establishment: "
+ "net::ERR_INSUFFICIENT_RESOURCES"))) {
DVLOG(1) << "Sending of message type "
<< "WebSocketMsg_NotifyFailure failed.";
}
@@ -127,6 +136,12 @@ bool WebSocketDispatcherHost::CanReadRawCookies() const {
return policy->CanReadRawCookies(process_id_);
}
+storage::BlobStorageContext* WebSocketDispatcherHost::blob_storage_context()
+ const {
+ DCHECK(blob_storage_context_);
+ return blob_storage_context_->context();
+}
+
WebSocketHost* WebSocketDispatcherHost::GetHost(int routing_id) const {
WebSocketHostTable::const_iterator it = hosts_.find(routing_id);
return it == hosts_.end() ? NULL : it->second;
@@ -202,6 +217,10 @@ WebSocketHostState WebSocketDispatcherHost::NotifyFailure(
return WEBSOCKET_HOST_DELETED;
}
+WebSocketHostState WebSocketDispatcherHost::BlobSendComplete(int routing_id) {
+ return SendOrDrop(new WebSocketMsg_BlobSendComplete(routing_id));
+}
+
WebSocketHostState WebSocketDispatcherHost::DoDropChannel(
int routing_id,
bool was_clean,
diff --git a/chromium/content/browser/renderer_host/websocket_dispatcher_host.h b/chromium/content/browser/renderer_host/websocket_dispatcher_host.h
index 56c5f3aaa5d..5d5c804ddf3 100644
--- a/chromium/content/browser/renderer_host/websocket_dispatcher_host.h
+++ b/chromium/content/browser/renderer_host/websocket_dispatcher_host.h
@@ -13,6 +13,7 @@
#include "base/compiler_specific.h"
#include "base/containers/hash_tables.h"
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "content/common/content_export.h"
@@ -23,8 +24,14 @@ namespace net {
class URLRequestContext;
} // namespace net
+namespace storage {
+class BlobStorageContext;
+}
+
namespace content {
+class ChromeBlobStorageContext;
+class StoragePartition;
struct WebSocketHandshakeRequest;
struct WebSocketHandshakeResponse;
class WebSocketHost;
@@ -49,9 +56,10 @@ class CONTENT_EXPORT WebSocketDispatcherHost : public BrowserMessageFilter {
WEBSOCKET_HOST_DELETED
};
- WebSocketDispatcherHost(
- int process_id,
- const GetRequestContextCallback& get_context_callback);
+ WebSocketDispatcherHost(int process_id,
+ const GetRequestContextCallback& get_context_callback,
+ ChromeBlobStorageContext* blob_storage_context,
+ StoragePartition* storage_partition);
// BrowserMessageFilter:
bool OnMessageReceived(const IPC::Message& message) override;
@@ -96,6 +104,8 @@ class CONTENT_EXPORT WebSocketDispatcherHost : public BrowserMessageFilter {
int routing_id,
const std::string& message) WARN_UNUSED_RESULT;
+ WebSocketHostState BlobSendComplete(int routing_id);
+
// Sends a WebSocketMsg_DropChannel IPC and deletes and unregisters the
// channel.
WebSocketHostState DoDropChannel(int routing_id,
@@ -109,6 +119,13 @@ class CONTENT_EXPORT WebSocketDispatcherHost : public BrowserMessageFilter {
int render_process_id() const { return process_id_; }
+ // Returns a BlobStorageContext associated with this object's render process.
+ // The pointer will be valid for as long this object is.
+ storage::BlobStorageContext* blob_storage_context() const;
+
+ // Returns the StoragePartition associated with this render process.
+ StoragePartition* storage_partition() const { return storage_partition_; }
+
protected:
// For testing. Specify a factory method that creates mock version of
// WebSocketHost.
@@ -181,6 +198,12 @@ class CONTENT_EXPORT WebSocketDispatcherHost : public BrowserMessageFilter {
int64_t num_current_failed_connections_;
int64_t num_previous_failed_connections_;
+ // Needed to read from blobs for browser-side blob sending.
+ const scoped_refptr<const ChromeBlobStorageContext> blob_storage_context_;
+
+ // Needed to access to the StoragePartition for browser-side blob sending.
+ StoragePartition* const storage_partition_;
+
DISALLOW_COPY_AND_ASSIGN(WebSocketDispatcherHost);
};
diff --git a/chromium/content/browser/renderer_host/websocket_host.cc b/chromium/content/browser/renderer_host/websocket_host.cc
index 5551e9643bf..88c333a77e9 100644
--- a/chromium/content/browser/renderer_host/websocket_host.cc
+++ b/chromium/content/browser/renderer_host/websocket_host.cc
@@ -4,20 +4,29 @@
#include "content/browser/renderer_host/websocket_host.h"
+#include <inttypes.h>
#include <utility>
+#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/location.h"
+#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
#include "base/thread_task_runner_handle.h"
+#include "content/browser/bad_message.h"
+#include "content/browser/renderer_host/websocket_blob_sender.h"
#include "content/browser/renderer_host/websocket_dispatcher_host.h"
#include "content/browser/ssl/ssl_error_handler.h"
#include "content/browser/ssl/ssl_manager.h"
#include "content/common/websocket_messages.h"
+#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/storage_partition.h"
#include "ipc/ipc_message_macros.h"
+#include "net/base/net_errors.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
@@ -86,12 +95,41 @@ ChannelState StateCast(WebSocketDispatcherHost::WebSocketHostState host_state) {
return static_cast<ChannelState>(host_state);
}
+// Implementation of WebSocketBlobSender::Channel
+class SendChannelImpl final : public WebSocketBlobSender::Channel {
+ public:
+ explicit SendChannelImpl(net::WebSocketChannel* channel)
+ : channel_(channel) {}
+
+ // Implementation of WebSocketBlobSender::Channel
+ size_t GetSendQuota() const override {
+ return static_cast<size_t>(channel_->current_send_quota());
+ }
+
+ ChannelState SendFrame(bool fin, const std::vector<char>& data) override {
+ int opcode = first_frame_ ? net::WebSocketFrameHeader::kOpCodeBinary
+ : net::WebSocketFrameHeader::kOpCodeContinuation;
+ first_frame_ = false;
+ return channel_->SendFrame(fin, opcode, data);
+ }
+
+ private:
+ net::WebSocketChannel* channel_;
+ bool first_frame_ = true;
+
+ DISALLOW_COPY_AND_ASSIGN(SendChannelImpl);
+};
+
+} // namespace
+
// Implementation of net::WebSocketEventInterface. Receives events from our
// WebSocketChannel object. Each event is translated to an IPC and sent to the
// renderer or child process via WebSocketDispatcherHost.
-class WebSocketEventHandler : public net::WebSocketEventInterface {
+class WebSocketHost::WebSocketEventHandler final
+ : public net::WebSocketEventInterface {
public:
WebSocketEventHandler(WebSocketDispatcherHost* dispatcher,
+ WebSocketHost* host,
int routing_id,
int render_frame_id);
~WebSocketEventHandler() override;
@@ -120,7 +158,7 @@ class WebSocketEventHandler : public net::WebSocketEventInterface {
bool fatal) override;
private:
- class SSLErrorHandlerDelegate : public SSLErrorHandler::Delegate {
+ class SSLErrorHandlerDelegate final : public SSLErrorHandler::Delegate {
public:
SSLErrorHandlerDelegate(
scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks);
@@ -140,6 +178,7 @@ class WebSocketEventHandler : public net::WebSocketEventInterface {
};
WebSocketDispatcherHost* const dispatcher_;
+ WebSocketHost* const host_;
const int routing_id_;
const int render_frame_id_;
scoped_ptr<SSLErrorHandlerDelegate> ssl_error_handler_delegate_;
@@ -147,20 +186,21 @@ class WebSocketEventHandler : public net::WebSocketEventInterface {
DISALLOW_COPY_AND_ASSIGN(WebSocketEventHandler);
};
-WebSocketEventHandler::WebSocketEventHandler(
+WebSocketHost::WebSocketEventHandler::WebSocketEventHandler(
WebSocketDispatcherHost* dispatcher,
+ WebSocketHost* host,
int routing_id,
int render_frame_id)
: dispatcher_(dispatcher),
+ host_(host),
routing_id_(routing_id),
- render_frame_id_(render_frame_id) {
-}
+ render_frame_id_(render_frame_id) {}
-WebSocketEventHandler::~WebSocketEventHandler() {
+WebSocketHost::WebSocketEventHandler::~WebSocketEventHandler() {
DVLOG(1) << "WebSocketEventHandler destroyed routing_id=" << routing_id_;
}
-ChannelState WebSocketEventHandler::OnAddChannelResponse(
+ChannelState WebSocketHost::WebSocketEventHandler::OnAddChannelResponse(
const std::string& selected_protocol,
const std::string& extensions) {
DVLOG(3) << "WebSocketEventHandler::OnAddChannelResponse"
@@ -172,7 +212,7 @@ ChannelState WebSocketEventHandler::OnAddChannelResponse(
routing_id_, selected_protocol, extensions));
}
-ChannelState WebSocketEventHandler::OnDataFrame(
+ChannelState WebSocketHost::WebSocketEventHandler::OnDataFrame(
bool fin,
net::WebSocketFrameHeader::OpCode type,
const std::vector<char>& data) {
@@ -180,27 +220,31 @@ ChannelState WebSocketEventHandler::OnDataFrame(
<< " routing_id=" << routing_id_ << " fin=" << fin
<< " type=" << type << " data is " << data.size() << " bytes";
- return StateCast(dispatcher_->SendFrame(
- routing_id_, fin, OpCodeToMessageType(type), data));
+ return StateCast(dispatcher_->SendFrame(routing_id_, fin,
+ OpCodeToMessageType(type), data));
}
-ChannelState WebSocketEventHandler::OnClosingHandshake() {
+ChannelState WebSocketHost::WebSocketEventHandler::OnClosingHandshake() {
DVLOG(3) << "WebSocketEventHandler::OnClosingHandshake"
<< " routing_id=" << routing_id_;
return StateCast(dispatcher_->NotifyClosingHandshake(routing_id_));
}
-ChannelState WebSocketEventHandler::OnFlowControl(int64_t quota) {
+ChannelState WebSocketHost::WebSocketEventHandler::OnFlowControl(
+ int64_t quota) {
DVLOG(3) << "WebSocketEventHandler::OnFlowControl"
<< " routing_id=" << routing_id_ << " quota=" << quota;
+ if (host_->blob_sender_)
+ host_->blob_sender_->OnNewSendQuota();
return StateCast(dispatcher_->SendFlowControl(routing_id_, quota));
}
-ChannelState WebSocketEventHandler::OnDropChannel(bool was_clean,
- uint16_t code,
- const std::string& reason) {
+ChannelState WebSocketHost::WebSocketEventHandler::OnDropChannel(
+ bool was_clean,
+ uint16_t code,
+ const std::string& reason) {
DVLOG(3) << "WebSocketEventHandler::OnDropChannel"
<< " routing_id=" << routing_id_ << " was_clean=" << was_clean
<< " code=" << code << " reason=\"" << reason << "\"";
@@ -209,15 +253,15 @@ ChannelState WebSocketEventHandler::OnDropChannel(bool was_clean,
dispatcher_->DoDropChannel(routing_id_, was_clean, code, reason));
}
-ChannelState WebSocketEventHandler::OnFailChannel(const std::string& message) {
+ChannelState WebSocketHost::WebSocketEventHandler::OnFailChannel(
+ const std::string& message) {
DVLOG(3) << "WebSocketEventHandler::OnFailChannel"
- << " routing_id=" << routing_id_
- << " message=\"" << message << "\"";
+ << " routing_id=" << routing_id_ << " message=\"" << message << "\"";
return StateCast(dispatcher_->NotifyFailure(routing_id_, message));
}
-ChannelState WebSocketEventHandler::OnStartOpeningHandshake(
+ChannelState WebSocketHost::WebSocketEventHandler::OnStartOpeningHandshake(
scoped_ptr<net::WebSocketHandshakeRequestInfo> request) {
bool should_send = dispatcher_->CanReadRawCookies();
DVLOG(3) << "WebSocketEventHandler::OnStartOpeningHandshake "
@@ -237,11 +281,11 @@ ChannelState WebSocketEventHandler::OnStartOpeningHandshake(
request->headers.ToString();
request_to_pass.request_time = request->request_time;
- return StateCast(dispatcher_->NotifyStartOpeningHandshake(routing_id_,
- request_to_pass));
+ return StateCast(
+ dispatcher_->NotifyStartOpeningHandshake(routing_id_, request_to_pass));
}
-ChannelState WebSocketEventHandler::OnFinishOpeningHandshake(
+ChannelState WebSocketHost::WebSocketEventHandler::OnFinishOpeningHandshake(
scoped_ptr<net::WebSocketHandshakeResponseInfo> response) {
bool should_send = dispatcher_->CanReadRawCookies();
DVLOG(3) << "WebSocketEventHandler::OnFinishOpeningHandshake "
@@ -254,7 +298,7 @@ ChannelState WebSocketEventHandler::OnFinishOpeningHandshake(
response_to_pass.url.Swap(&response->url);
response_to_pass.status_code = response->status_code;
response_to_pass.status_text.swap(response->status_text);
- void* iter = NULL;
+ size_t iter = 0;
std::string name, value;
while (response->headers->EnumerateHeaderLines(&iter, &name, &value))
response_to_pass.headers.push_back(std::make_pair(name, value));
@@ -263,11 +307,11 @@ ChannelState WebSocketEventHandler::OnFinishOpeningHandshake(
response->headers->raw_headers());
response_to_pass.response_time = response->response_time;
- return StateCast(dispatcher_->NotifyFinishOpeningHandshake(routing_id_,
- response_to_pass));
+ return StateCast(
+ dispatcher_->NotifyFinishOpeningHandshake(routing_id_, response_to_pass));
}
-ChannelState WebSocketEventHandler::OnSSLCertificateError(
+ChannelState WebSocketHost::WebSocketEventHandler::OnSSLCertificateError(
scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks,
const GURL& url,
const net::SSLInfo& ssl_info,
@@ -284,20 +328,21 @@ ChannelState WebSocketEventHandler::OnSSLCertificateError(
return WebSocketEventInterface::CHANNEL_ALIVE;
}
-WebSocketEventHandler::SSLErrorHandlerDelegate::SSLErrorHandlerDelegate(
- scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks)
+WebSocketHost::WebSocketEventHandler::SSLErrorHandlerDelegate::
+ SSLErrorHandlerDelegate(
+ scoped_ptr<net::WebSocketEventInterface::SSLErrorCallbacks> callbacks)
: callbacks_(std::move(callbacks)), weak_ptr_factory_(this) {}
-WebSocketEventHandler::SSLErrorHandlerDelegate::~SSLErrorHandlerDelegate() {}
+WebSocketHost::WebSocketEventHandler::SSLErrorHandlerDelegate::
+ ~SSLErrorHandlerDelegate() {}
base::WeakPtr<SSLErrorHandler::Delegate>
-WebSocketEventHandler::SSLErrorHandlerDelegate::GetWeakPtr() {
+WebSocketHost::WebSocketEventHandler::SSLErrorHandlerDelegate::GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
-void WebSocketEventHandler::SSLErrorHandlerDelegate::CancelSSLRequest(
- int error,
- const net::SSLInfo* ssl_info) {
+void WebSocketHost::WebSocketEventHandler::SSLErrorHandlerDelegate::
+ CancelSSLRequest(int error, const net::SSLInfo* ssl_info) {
DVLOG(3) << "SSLErrorHandlerDelegate::CancelSSLRequest"
<< " error=" << error
<< " cert_status=" << (ssl_info ? ssl_info->cert_status
@@ -305,13 +350,12 @@ void WebSocketEventHandler::SSLErrorHandlerDelegate::CancelSSLRequest(
callbacks_->CancelSSLRequest(error, ssl_info);
}
-void WebSocketEventHandler::SSLErrorHandlerDelegate::ContinueSSLRequest() {
+void WebSocketHost::WebSocketEventHandler::SSLErrorHandlerDelegate::
+ ContinueSSLRequest() {
DVLOG(3) << "SSLErrorHandlerDelegate::ContinueSSLRequest";
callbacks_->ContinueSSLRequest();
}
-} // namespace
-
WebSocketHost::WebSocketHost(int routing_id,
WebSocketDispatcherHost* dispatcher,
net::URLRequestContext* url_request_context,
@@ -337,6 +381,7 @@ bool WebSocketHost::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(WebSocketHost, message)
IPC_MESSAGE_HANDLER(WebSocketHostMsg_AddChannelRequest, OnAddChannelRequest)
+ IPC_MESSAGE_HANDLER(WebSocketHostMsg_SendBlob, OnSendBlob)
IPC_MESSAGE_HANDLER(WebSocketMsg_SendFrame, OnSendFrame)
IPC_MESSAGE_HANDLER(WebSocketMsg_FlowControl, OnFlowControl)
IPC_MESSAGE_HANDLER(WebSocketMsg_DropChannel, OnDropChannel)
@@ -383,7 +428,8 @@ void WebSocketHost::AddChannel(
DCHECK(!channel_);
scoped_ptr<net::WebSocketEventInterface> event_interface(
- new WebSocketEventHandler(dispatcher_, routing_id_, render_frame_id));
+ new WebSocketEventHandler(dispatcher_, this, routing_id_,
+ render_frame_id));
channel_.reset(new net::WebSocketChannel(std::move(event_interface),
url_request_context_));
@@ -404,6 +450,41 @@ void WebSocketHost::AddChannel(
// |this| may have been deleted here.
}
+void WebSocketHost::OnSendBlob(const std::string& uuid,
+ uint64_t expected_size) {
+ DVLOG(3) << "WebSocketHost::OnSendBlob"
+ << " routing_id=" << routing_id_ << " uuid=" << uuid
+ << " expected_size=" << expected_size;
+
+ DCHECK(channel_);
+ if (blob_sender_) {
+ bad_message::ReceivedBadMessage(
+ dispatcher_, bad_message::WSH_SEND_BLOB_DURING_BLOB_SEND);
+ return;
+ }
+ blob_sender_.reset(new WebSocketBlobSender(
+ make_scoped_ptr(new SendChannelImpl(channel_.get()))));
+ StoragePartition* partition = dispatcher_->storage_partition();
+ storage::FileSystemContext* file_system_context =
+ partition->GetFileSystemContext();
+
+ net::WebSocketEventInterface::ChannelState channel_state =
+ net::WebSocketEventInterface::CHANNEL_ALIVE;
+
+ // This use of base::Unretained is safe because the WebSocketBlobSender object
+ // is owned by this object and will not call it back after destruction.
+ int rv = blob_sender_->Start(
+ uuid, expected_size, dispatcher_->blob_storage_context(),
+ file_system_context,
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE).get(),
+ &channel_state,
+ base::Bind(&WebSocketHost::BlobSendComplete, base::Unretained(this)));
+ if (channel_state == net::WebSocketEventInterface::CHANNEL_ALIVE &&
+ rv != net::ERR_IO_PENDING)
+ BlobSendComplete(rv);
+ // |this| may be destroyed here.
+}
+
void WebSocketHost::OnSendFrame(bool fin,
WebSocketMessageType type,
const std::vector<char>& data) {
@@ -412,6 +493,11 @@ void WebSocketHost::OnSendFrame(bool fin,
<< " type=" << type << " data is " << data.size() << " bytes";
DCHECK(channel_);
+ if (blob_sender_) {
+ bad_message::ReceivedBadMessage(
+ dispatcher_, bad_message::WSH_SEND_FRAME_DURING_BLOB_SEND);
+ return;
+ }
channel_->SendFrame(fin, MessageTypeToOpCode(type), data);
}
@@ -441,16 +527,52 @@ void WebSocketHost::OnDropChannel(bool was_clean,
// WebSocketChannel is not yet created due to the delay introduced by
// per-renderer WebSocket throttling.
WebSocketDispatcherHost::WebSocketHostState result =
- dispatcher_->DoDropChannel(routing_id_,
- false,
- net::kWebSocketErrorAbnormalClosure,
- "");
+ dispatcher_->DoDropChannel(routing_id_, false,
+ net::kWebSocketErrorAbnormalClosure, "");
DCHECK_EQ(WebSocketDispatcherHost::WEBSOCKET_HOST_DELETED, result);
return;
}
+ blob_sender_.reset();
// TODO(yhirano): Handle |was_clean| appropriately.
channel_->StartClosingHandshake(code, reason);
}
+void WebSocketHost::BlobSendComplete(int result) {
+ DVLOG(3) << "WebSocketHost::BlobSendComplete"
+ << " routing_id=" << routing_id_
+ << " result=" << net::ErrorToString(result);
+
+ // All paths through this method must reset blob_sender_, so take ownership
+ // at the beginning.
+ scoped_ptr<WebSocketBlobSender> blob_sender(std::move(blob_sender_));
+ switch (result) {
+ case net::OK:
+ ignore_result(dispatcher_->BlobSendComplete(routing_id_));
+ // |this| may be destroyed here.
+ return;
+
+ case net::ERR_UPLOAD_FILE_CHANGED: {
+ uint64_t expected_size = blob_sender->expected_size();
+ uint64_t actual_size = blob_sender->ActualSize();
+ if (expected_size != actual_size) {
+ ignore_result(dispatcher_->NotifyFailure(
+ routing_id_,
+ base::StringPrintf("Blob size mismatch; renderer size = %" PRIu64
+ ", browser size = %" PRIu64,
+ expected_size, actual_size)));
+ // |this| is destroyed here.
+ return;
+ } // else fallthrough
+ }
+
+ default:
+ ignore_result(dispatcher_->NotifyFailure(
+ routing_id_,
+ "Failed to load Blob: error code = " + net::ErrorToString(result)));
+ // |this| is destroyed here.
+ return;
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/renderer_host/websocket_host.h b/chromium/content/browser/renderer_host/websocket_host.h
index efdc9d1bd00..e95f65c31f4 100644
--- a/chromium/content/browser/renderer_host/websocket_host.h
+++ b/chromium/content/browser/renderer_host/websocket_host.h
@@ -34,6 +34,7 @@ class Message;
namespace content {
+class WebSocketBlobSender;
class WebSocketDispatcherHost;
// Host of net::WebSocketChannel. The lifetime of an instance of this class is
@@ -60,6 +61,8 @@ class CONTENT_EXPORT WebSocketHost {
void OnHandshakeSucceeded() { handshake_succeeded_ = true; }
private:
+ class WebSocketEventHandler;
+
// Handlers for each message type, dispatched by OnMessageReceived(), as
// defined in content/common/websocket_messages.h
@@ -73,6 +76,8 @@ class CONTENT_EXPORT WebSocketHost {
const url::Origin& origin,
int render_frame_id);
+ void OnSendBlob(const std::string& uuid, uint64_t expected_size);
+
void OnSendFrame(bool fin,
WebSocketMessageType type,
const std::vector<char>& data);
@@ -81,6 +86,11 @@ class CONTENT_EXPORT WebSocketHost {
void OnDropChannel(bool was_clean, uint16_t code, const std::string& reason);
+ void BlobSendComplete(int result);
+
+ // non-NULL if and only if this object is currently in "blob sending mode".
+ scoped_ptr<WebSocketBlobSender> blob_sender_;
+
// The channel we use to send events to the network.
scoped_ptr<net::WebSocketChannel> channel_;
diff --git a/chromium/content/browser/resolve_proxy_msg_helper.cc b/chromium/content/browser/resolve_proxy_msg_helper.cc
index e189f1c83d3..7b1e04ed0bc 100644
--- a/chromium/content/browser/resolve_proxy_msg_helper.cc
+++ b/chromium/content/browser/resolve_proxy_msg_helper.cc
@@ -92,7 +92,7 @@ void ResolveProxyMsgHelper::StartPendingRequest() {
// Start the request.
int result = proxy_service_->ResolveProxy(
- req.url, net::LOAD_NORMAL, &proxy_info_,
+ req.url, std::string(), net::LOAD_NORMAL, &proxy_info_,
base::Bind(&ResolveProxyMsgHelper::OnResolveProxyCompleted,
base::Unretained(this)),
&req.pac_req, NULL, net::BoundNetLog());
diff --git a/chromium/content/browser/resolve_proxy_msg_helper_unittest.cc b/chromium/content/browser/resolve_proxy_msg_helper_unittest.cc
index 5e3dd0de584..bc723fe8796 100644
--- a/chromium/content/browser/resolve_proxy_msg_helper_unittest.cc
+++ b/chromium/content/browser/resolve_proxy_msg_helper_unittest.cc
@@ -90,8 +90,7 @@ class ResolveProxyMsgHelperTest : public testing::Test, public IPC::Listener {
private:
bool OnMessageReceived(const IPC::Message& msg) override {
- base::TupleTypes<ViewHostMsg_ResolveProxy::ReplyParam>::ValueTuple
- reply_data;
+ ViewHostMsg_ResolveProxy::ReplyParam reply_data;
EXPECT_TRUE(ViewHostMsg_ResolveProxy::ReadReplyParam(&msg, &reply_data));
DCHECK(!pending_result_.get());
pending_result_.reset(
diff --git a/chromium/content/browser/resource_context_impl.cc b/chromium/content/browser/resource_context_impl.cc
index a4f0303e0da..017e08dc3c9 100644
--- a/chromium/content/browser/resource_context_impl.cc
+++ b/chromium/content/browser/resource_context_impl.cc
@@ -6,6 +6,7 @@
#include <stdint.h>
+#include "base/bind.h"
#include "base/logging.h"
#include "content/browser/fileapi/chrome_blob_storage_context.h"
#include "content/browser/loader/resource_dispatcher_host_impl.h"
@@ -37,8 +38,13 @@ std::string ReturnEmptySalt() {
ResourceContext::ResourceContext() {
- if (ResourceDispatcherHostImpl::Get())
- ResourceDispatcherHostImpl::Get()->AddResourceContext(this);
+ ResourceDispatcherHostImpl* rdhi = ResourceDispatcherHostImpl::Get();
+ if (rdhi) {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&ResourceDispatcherHostImpl::AddResourceContext,
+ base::Unretained(rdhi), this));
+ }
}
ResourceContext::~ResourceContext() {
diff --git a/chromium/content/browser/resources/gpu/browser_bridge.js b/chromium/content/browser/resources/gpu/browser_bridge.js
index b835f44207c..c2ad051d09b 100644
--- a/chromium/content/browser/resources/gpu/browser_bridge.js
+++ b/chromium/content/browser/resources/gpu/browser_bridge.js
@@ -36,11 +36,9 @@ cr.define('gpu', function() {
applySimulatedData_: function applySimulatedData(data) {
// set up things according to the simulated data
this.gpuInfo_ = data.gpuInfo;
- this.gpuMemoryBufferInfo_ = data.gpuMemoryBufferInfo;
this.clientInfo_ = data.clientInfo;
this.logMessages_ = data.logMessages;
cr.dispatchSimpleEvent(this, 'gpuInfoUpdate');
- cr.dispatchSimpleEvent(this, 'gpuMemoryBufferInfoUpdate');
cr.dispatchSimpleEvent(this, 'clientInfoChange');
cr.dispatchSimpleEvent(this, 'logMessagesChange');
},
@@ -97,21 +95,6 @@ cr.define('gpu', function() {
},
/**
- * Get gpuMemoryBufferInfo data.
- */
- get gpuMemoryBufferInfo() {
- return this.gpuMemoryBufferInfo_;
- },
-
- /**
- * Called from gpu c++ code when GpuMemoryBuffer Info is updated.
- */
- onGpuMemoryBufferInfoUpdate: function(gpuMemoryBufferInfo) {
- this.gpuMemoryBufferInfo_ = gpuMemoryBufferInfo;
- cr.dispatchSimpleEvent(this, 'gpuMemoryBufferInfoUpdate');
- },
-
- /**
* This function begins a request for the ClientInfo. If it comes back
* as undefined, then we will issue the request again in 250ms.
*/
diff --git a/chromium/content/browser/resources/gpu/info_view.html b/chromium/content/browser/resources/gpu/info_view.html
index da813fc8dba..b1cef9cc2a3 100644
--- a/chromium/content/browser/resources/gpu/info_view.html
+++ b/chromium/content/browser/resources/gpu/info_view.html
@@ -23,11 +23,6 @@ found in the LICENSE file.
</div>
<div>
- <h3>GpuMemoryBuffer Status</h3>
- <div id="gpu-memory-buffer-info"></div>
- </div>
-
- <div>
<h3>Version Information</h3>
<div id="client-info"></div>
</div>
@@ -37,6 +32,16 @@ found in the LICENSE file.
<div id="basic-info"></div>
</div>
+ <div>
+ <h3>Compositor Information</h3>
+ <div id="compositor-info"></div>
+ </div>
+
+ <div>
+ <h3>GpuMemoryBuffers Status</h3>
+ <div id="gpu-memory-buffer-info"></div>
+ </div>
+
<div class="diagnostics">
<h3>Diagnostics</h3>
<div class="diagnostics-loading">... loading ...</div>
diff --git a/chromium/content/browser/resources/gpu/info_view.js b/chromium/content/browser/resources/gpu/info_view.js
index 3566369cd70..8a98725ed4a 100644
--- a/chromium/content/browser/resources/gpu/info_view.js
+++ b/chromium/content/browser/resources/gpu/info_view.js
@@ -23,8 +23,6 @@ cr.define('gpu', function() {
cr.ui.TabPanel.prototype.decorate.apply(this);
browserBridge.addEventListener('gpuInfoUpdate', this.refresh.bind(this));
- browserBridge.addEventListener('gpuMemoryBufferInfoUpdate',
- this.refresh.bind(this));
browserBridge.addEventListener('logMessagesChange',
this.refresh.bind(this));
browserBridge.addEventListener('clientInfoChange',
@@ -96,6 +94,7 @@ cr.define('gpu', function() {
'panel_fitting': 'Panel Fitting',
'rasterization': 'Rasterization',
'multiple_raster_threads': 'Multiple Raster Threads',
+ 'native_gpu_memory_buffers': 'Native GpuMemoryBuffers',
};
var statusMap = {
@@ -154,7 +153,6 @@ cr.define('gpu', function() {
var workaroundsDiv = this.querySelector('.workarounds-div');
var workaroundsList = this.querySelector('.workarounds-list');
var gpuInfo = browserBridge.gpuInfo;
- var gpuMemoryBufferInfo = browserBridge.gpuMemoryBufferInfo;
var i;
if (gpuInfo) {
// Not using jstemplate here for blacklist status because we construct
@@ -219,17 +217,22 @@ cr.define('gpu', function() {
problemsList.hidden = true;
workaroundsList.hidden = true;
}
- if (gpuMemoryBufferInfo.gpu_memory_buffer_info)
- this.setTable_('gpu-memory-buffer-info',
- gpuMemoryBufferInfo.gpu_memory_buffer_info);
- else
- this.setTable_('gpu-memory-buffer-info', []);
if (gpuInfo.basic_info)
this.setTable_('basic-info', gpuInfo.basic_info);
else
this.setTable_('basic-info', []);
+ if (gpuInfo.compositorInfo)
+ this.setTable_('compositor-info', gpuInfo.compositorInfo);
+ else
+ this.setTable_('compositor-info', []);
+
+ if (gpuInfo.gpuMemoryBufferInfo)
+ this.setTable_('gpu-memory-buffer-info', gpuInfo.gpuMemoryBufferInfo);
+ else
+ this.setTable_('gpu-memory-buffer-info', []);
+
if (gpuInfo.diagnostics) {
diagnosticsDiv.hidden = false;
diagnosticsLoadingDiv.hidden = true;
diff --git a/chromium/content/browser/resources/media/OWNERS b/chromium/content/browser/resources/media/OWNERS
index ffdcc7a1cb8..c6ef7b7f49d 100644
--- a/chromium/content/browser/resources/media/OWNERS
+++ b/chromium/content/browser/resources/media/OWNERS
@@ -1,4 +1,2 @@
-dalecurtis@chromium.org
-ddorwin@chromium.org
+file://media/OWNERS
tommi@chromium.org
-xhwang@chromium.org
diff --git a/chromium/content/browser/resources/media/dump_creator.js b/chromium/content/browser/resources/media/dump_creator.js
index 75076493e16..c8f53dfc165 100644
--- a/chromium/content/browser/resources/media/dump_creator.js
+++ b/chromium/content/browser/resources/media/dump_creator.js
@@ -47,12 +47,12 @@ var DumpCreator = (function() {
'<p><div>&lt;base filename&gt;.&lt;render process ID&gt;' +
'.aec_dump.&lt;recording ID&gt;</div>' +
'<div>&lt;base filename&gt;.&lt;render process ID&gt;' +
- '.source_input.&lt;stream ID&gt;.pcm</div></p>' +
+ '.source_input.&lt;stream ID&gt;.wav</div></p>' +
'<p class=audio-recordings-info>If recordings are disabled and then' +
- ' enabled using the same base filename, the files will be appended' +
- ' to and may become invalid. It is recommended to choose a new base' +
- ' filename each time or move the produced files before enabling' +
- ' again.</p>' +
+ ' enabled using the same base filename, the microphone recording file' +
+ ' will be overwritten, and the AEC dump file will be appended to and' +
+ ' may become invalid. It is recommended to choose a new base filename' +
+ ' each time or move the produced files before enabling again.</p>' +
'<p><label><input type=checkbox>' +
'Enable diagnostic packet and event recording</label></p>' +
'<p class=audio-recordings-info>A diagnostic packet and event' +
@@ -62,14 +62,12 @@ var DumpCreator = (function() {
' and RTCP packets are logged. These do not include any audio or' +
' video information, nor any other types of personally identifiable' +
' information (so no IP addresses or URLs). Checking this box will' +
- ' enable the recording for ongoing WebRTC calls and for future' +
- ' WebRTC calls. When the box is unchecked or this page is closed,' +
- ' all ongoing recordings will be stopped and this recording' +
- ' functionality will be disabled for future WebRTC calls. Recording' +
- ' in multiple tabs or multiple recordings in the same tab is' +
- ' currently not supported. When enabling, a filename for the' +
- ' recording can be selected. If an existing file is selected, it' +
- ' will be overwritten. </p>';
+ ' enable the recording for currently ongoing WebRTC calls. When' +
+ ' the box is unchecked or this page is closed, all active recordings' +
+ ' will be stopped. Recording in multiple tabs or multiple recordings' +
+ ' in the same tab is currently not supported. When enabling, a' +
+ ' filename for the recording can be selected. If an existing file is' +
+ ' selected, it will be overwritten. </p>';
content.getElementsByTagName('a')[0].addEventListener(
'click', this.onDownloadData_.bind(this));
content.getElementsByTagName('input')[0].addEventListener(
diff --git a/chromium/content/browser/resources/service_worker/serviceworker_internals.html b/chromium/content/browser/resources/service_worker/serviceworker_internals.html
index 4e81776e760..fcc23b43d1e 100644
--- a/chromium/content/browser/resources/service_worker/serviceworker_internals.html
+++ b/chromium/content/browser/resources/service_worker/serviceworker_internals.html
@@ -49,11 +49,8 @@
<button href="#" class="stop"
jsvalues=".cmdArgs:{partition_id:$partition_id,version_id:version_id}"
jsdisplay="$this.running_status == 'RUNNING'">Stop</button>
- <button href="#" class="push"
- jsvalues=".cmdArgs:{partition_id:$partition_id,version_id:version_id}"
- jsdisplay="$this.running_status == 'RUNNING'">Push</button>
<button href="#" class="inspect"
- jsvalues=".cmdArgs:{process_id:process_id,devtools_agent_route_id:devtools_agent_route_id}"
+ jsvalues=".cmdArgs:{process_host_id:process_host_id,devtools_agent_route_id:devtools_agent_route_id}"
jsdisplay="$this.running_status == 'RUNNING'">Inspect</button>
<span class="operation-status" style="display: none">Running...</span>
</div>
diff --git a/chromium/content/browser/resources/service_worker/serviceworker_internals.js b/chromium/content/browser/resources/service_worker/serviceworker_internals.js
index ff382dd75ad..087c5a65cf7 100644
--- a/chromium/content/browser/resources/service_worker/serviceworker_internals.js
+++ b/chromium/content/browser/resources/service_worker/serviceworker_internals.js
@@ -42,7 +42,7 @@ cr.define('serviceworker', function() {
}
// All commands are completed with 'onOperationComplete'.
- var COMMANDS = ['stop', 'push', 'inspect', 'unregister', 'start'];
+ var COMMANDS = ['stop', 'inspect', 'unregister', 'start'];
function commandHandler(command) {
return function(event) {
var link = event.target;
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_browsertest.cc b/chromium/content/browser/screen_orientation/screen_orientation_browsertest.cc
index 77675b994cb..efdd4cf81eb 100644
--- a/chromium/content/browser/screen_orientation/screen_orientation_browsertest.cc
+++ b/chromium/content/browser/screen_orientation/screen_orientation_browsertest.cc
@@ -51,7 +51,7 @@ class ScreenOrientationBrowserTest : public ContentBrowserTest {
ASSERT_NE(blink::WebScreenOrientationUndefined, type);
screen_info.orientationType = type;
- ViewMsg_Resize_Params params;
+ ResizeParams params;
params.screen_info = screen_info;
params.new_size = gfx::Size(0, 0);
params.physical_backing_size = gfx::Size(300, 300);
@@ -227,18 +227,22 @@ class ScreenOrientationLockDisabledBrowserTest : public ContentBrowserTest {
// Check that when --disable-screen-orientation-lock is passed to the command
// line, screen.orientation.lock() correctly reports to not be supported.
-// Flaky: https://crbug.com/498236
-IN_PROC_BROWSER_TEST_F(ScreenOrientationLockDisabledBrowserTest,
- DISABLED_NotSupported) {
+IN_PROC_BROWSER_TEST_F(ScreenOrientationLockDisabledBrowserTest, NotSupported) {
GURL test_url = GetTestUrl("screen_orientation",
"screen_orientation_lock_disabled.html");
- TestNavigationObserver navigation_observer(shell()->web_contents(), 2);
+ TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
shell()->LoadURL(test_url);
navigation_observer.Wait();
- EXPECT_EQ("NotSupportedError",
- shell()->web_contents()->GetLastCommittedURL().ref());
+ {
+ ASSERT_TRUE(ExecuteScript(shell()->web_contents(), "run();"));
+
+ TestNavigationObserver navigation_observer(shell()->web_contents(), 1);
+ navigation_observer.Wait();
+ EXPECT_EQ("NotSupportedError",
+ shell()->web_contents()->GetLastCommittedURL().ref());
+ }
}
#endif // defined(OS_ANDROID)
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_delegate_win.cc b/chromium/content/browser/screen_orientation/screen_orientation_delegate_win.cc
new file mode 100644
index 00000000000..d4bc93f4af7
--- /dev/null
+++ b/chromium/content/browser/screen_orientation/screen_orientation_delegate_win.cc
@@ -0,0 +1,133 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/screen_orientation/screen_orientation_delegate_win.h"
+
+#include <windows.h>
+
+#include "content/public/browser/screen_orientation_provider.h"
+
+namespace {
+
+// SetDisplayAutoRotationPreferences is available on Windows 8 and after.
+void SetDisplayAutoRotationPreferencesWrapper(
+ ORIENTATION_PREFERENCE orientation) {
+ using SetDisplayAutoRotationPreferencesPtr =
+ void(WINAPI*)(ORIENTATION_PREFERENCE);
+ static SetDisplayAutoRotationPreferencesPtr
+ set_display_auto_rotation_preferences_func =
+ reinterpret_cast<SetDisplayAutoRotationPreferencesPtr>(
+ GetProcAddress(GetModuleHandleA("user32.dll"),
+ "SetDisplayAutoRotationPreferences"));
+ if (set_display_auto_rotation_preferences_func)
+ set_display_auto_rotation_preferences_func(orientation);
+}
+
+// GetAutoRotationState is available on Windows 8 and after.
+BOOL GetAutoRotationStateWrapper(PAR_STATE state) {
+ using GetAutoRotationStatePtr = BOOL(WINAPI*)(PAR_STATE);
+ static GetAutoRotationStatePtr get_auto_rotation_state_func =
+ reinterpret_cast<GetAutoRotationStatePtr>(GetProcAddress(
+ GetModuleHandleA("user32.dll"), "GetAutoRotationState"));
+ if (get_auto_rotation_state_func)
+ return get_auto_rotation_state_func(state);
+ return FALSE;
+}
+
+bool GetDisplayOrientation(bool* landscape, bool* flipped) {
+ DEVMODE dm = {};
+ dm.dmSize = sizeof(dm);
+ if (!EnumDisplaySettings(nullptr, ENUM_CURRENT_SETTINGS, &dm))
+ return false;
+ *flipped = (dm.dmDisplayOrientation == DMDO_270 ||
+ dm.dmDisplayOrientation == DMDO_180);
+ *landscape = (dm.dmPelsWidth > dm.dmPelsHeight);
+ return true;
+}
+
+} // namespace
+
+namespace content {
+
+ScreenOrientationDelegateWin::ScreenOrientationDelegateWin() {
+ ScreenOrientationProvider::SetDelegate(this);
+}
+
+ScreenOrientationDelegateWin::~ScreenOrientationDelegateWin() {
+ ScreenOrientationProvider::SetDelegate(nullptr);
+}
+
+bool ScreenOrientationDelegateWin::FullScreenRequired(
+ WebContents* web_contents) {
+ return false;
+}
+
+void ScreenOrientationDelegateWin::Lock(
+ WebContents* web_contents,
+ blink::WebScreenOrientationLockType lock_orientation) {
+ ORIENTATION_PREFERENCE prefs = ORIENTATION_PREFERENCE_NONE;
+ bool landscape = true;
+ bool flipped = false;
+ switch (lock_orientation) {
+ case blink::WebScreenOrientationLockPortraitPrimary:
+ prefs = ORIENTATION_PREFERENCE_PORTRAIT;
+ break;
+ case blink::WebScreenOrientationLockPortraitSecondary:
+ prefs = ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED;
+ break;
+ case blink::WebScreenOrientationLockLandscapePrimary:
+ prefs = ORIENTATION_PREFERENCE_LANDSCAPE;
+ break;
+ case blink::WebScreenOrientationLockLandscapeSecondary:
+ prefs = ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED;
+ break;
+ case blink::WebScreenOrientationLockPortrait:
+ if (!GetDisplayOrientation(&landscape, &flipped))
+ return;
+ prefs = (flipped && !landscape) ? ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED
+ : ORIENTATION_PREFERENCE_PORTRAIT;
+ break;
+ case blink::WebScreenOrientationLockLandscape:
+ if (!GetDisplayOrientation(&landscape, &flipped))
+ return;
+ prefs = (flipped && landscape) ? ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED
+ : ORIENTATION_PREFERENCE_LANDSCAPE;
+ break;
+ case blink::WebScreenOrientationLockNatural:
+ if (!GetDisplayOrientation(&landscape, &flipped))
+ return;
+ prefs = landscape ? ORIENTATION_PREFERENCE_LANDSCAPE
+ : ORIENTATION_PREFERENCE_PORTRAIT;
+ break;
+ case blink::WebScreenOrientationLockAny:
+ if (!GetDisplayOrientation(&landscape, &flipped))
+ return;
+ if (landscape) {
+ prefs = flipped ? ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED
+ : ORIENTATION_PREFERENCE_LANDSCAPE;
+ } else {
+ prefs = flipped ? ORIENTATION_PREFERENCE_PORTRAIT_FLIPPED
+ : ORIENTATION_PREFERENCE_PORTRAIT;
+ }
+ break;
+ case blink::WebScreenOrientationLockDefault:
+ default:
+ break;
+ }
+ SetDisplayAutoRotationPreferencesWrapper(prefs);
+}
+
+bool ScreenOrientationDelegateWin::ScreenOrientationProviderSupported() {
+ AR_STATE auto_rotation_state = {};
+ return (GetAutoRotationStateWrapper(&auto_rotation_state) &&
+ !(auto_rotation_state & AR_NOSENSOR) &&
+ !(auto_rotation_state & AR_NOT_SUPPORTED) &&
+ !(auto_rotation_state & AR_MULTIMON));
+}
+
+void ScreenOrientationDelegateWin::Unlock(WebContents* web_contents) {
+ SetDisplayAutoRotationPreferencesWrapper(ORIENTATION_PREFERENCE_NONE);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/screen_orientation/screen_orientation_delegate_win.h b/chromium/content/browser/screen_orientation/screen_orientation_delegate_win.h
new file mode 100644
index 00000000000..7651d5a7e65
--- /dev/null
+++ b/chromium/content/browser/screen_orientation/screen_orientation_delegate_win.h
@@ -0,0 +1,30 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_SCREEN_ORIENTATION_SCREEN_ORIENTATION_DELEGATE_WIN_H_
+#define CONTENT_BROWSER_SCREEN_ORIENTATION_SCREEN_ORIENTATION_DELEGATE_WIN_H_
+
+#include "content/public/browser/screen_orientation_delegate.h"
+
+namespace content {
+
+class ScreenOrientationDelegateWin : public ScreenOrientationDelegate {
+ public:
+ ScreenOrientationDelegateWin();
+ ~ScreenOrientationDelegateWin() override;
+
+ private:
+ // content::ScreenOrientationDelegate:
+ bool FullScreenRequired(WebContents* web_contents) override;
+ void Lock(WebContents* web_contents,
+ blink::WebScreenOrientationLockType lock_orientation) override;
+ bool ScreenOrientationProviderSupported() override;
+ void Unlock(WebContents* web_contents) override;
+
+ DISALLOW_COPY_AND_ASSIGN(ScreenOrientationDelegateWin);
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SCREEN_ORIENTATION_SCREEN_ORIENTATION_DELEGATE_WIN_H_
diff --git a/chromium/content/browser/security_exploit_browsertest.cc b/chromium/content/browser/security_exploit_browsertest.cc
index c515609c576..45117a39d96 100644
--- a/chromium/content/browser/security_exploit_browsertest.cc
+++ b/chromium/content/browser/security_exploit_browsertest.cc
@@ -23,6 +23,7 @@
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/interstitial_page.h"
#include "content/public/browser/interstitial_page_delegate.h"
+#include "content/public/browser/resource_dispatcher_host.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/appcache_info.h"
#include "content/public/common/browser_side_navigation_policy.h"
@@ -33,10 +34,12 @@
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
+#include "content/test/content_browser_test_utils_internal.h"
#include "content/test/test_content_browser_client.h"
#include "ipc/ipc_security_test_util.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/url_request/url_request_slow_download_job.h"
using IPC::IpcSecurityTestUtil;
@@ -44,6 +47,11 @@ namespace content {
namespace {
+// This request id is used by tests that craft a
+// ResourceHostMsg_RequestResource. The id is sufficiently large that it doesn't
+// collide with ids used by previous navigation requests.
+const int kRequestIdNotPreviouslyUsed = 10000;
+
// This is a helper function for the tests which attempt to create a
// duplicate RenderViewHost or RenderWidgetHost. It tries to create two objects
// with the same process and routing ids, which causes a collision.
@@ -98,13 +106,11 @@ RenderViewHostImpl* PrepareToDuplicateHosts(Shell* shell,
return next_rfh->render_view_host();
}
-ResourceHostMsg_Request CreateXHRRequestWithOrigin(const char* origin) {
+ResourceHostMsg_Request CreateXHRRequest(const char* url) {
ResourceHostMsg_Request request;
request.method = "GET";
- request.url = GURL("http://bar.com/simple_page.html");
- request.first_party_for_cookies = GURL(origin);
+ request.url = GURL(url);
request.referrer_policy = blink::WebReferrerPolicyDefault;
- request.headers = base::StringPrintf("Origin: %s\r\n", origin);
request.load_flags = 0;
request.origin_pid = 0;
request.resource_type = RESOURCE_TYPE_XHR;
@@ -120,6 +126,44 @@ ResourceHostMsg_Request CreateXHRRequestWithOrigin(const char* origin) {
return request;
}
+ResourceHostMsg_Request CreateXHRRequestWithOrigin(const char* origin) {
+ ResourceHostMsg_Request request =
+ CreateXHRRequest("http://bar.com/simple_page.html");
+ request.first_party_for_cookies = GURL(origin);
+ request.headers = base::StringPrintf("Origin: %s\r\n", origin);
+ return request;
+}
+
+void TryCreateDuplicateRequestIds(Shell* shell, bool block_loaders) {
+ NavigateToURL(shell, GURL("http://foo.com/simple_page.html"));
+ RenderFrameHost* rfh = shell->web_contents()->GetMainFrame();
+
+ if (block_loaders) {
+ // Test the case where loaders are placed into blocked_loaders_map_.
+ ResourceDispatcherHost::BlockRequestsForFrameFromUI(rfh);
+ }
+
+ // URLRequestSlowDownloadJob waits for another request to kFinishDownloadUrl
+ // to finish all pending requests. It is never sent, so the following URL
+ // blocks indefinitely, which is good because the request stays alive and the
+ // test can try to reuse the request id without a race.
+ const char* blocking_url = net::URLRequestSlowDownloadJob::kUnknownSizeUrl;
+ ResourceHostMsg_Request request(CreateXHRRequest(blocking_url));
+
+ // Use the same request id twice.
+ RenderProcessHostWatcher process_killed(
+ rfh->GetProcess(), RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+ IPC::IpcSecurityTestUtil::PwnMessageReceived(
+ rfh->GetProcess()->GetChannel(),
+ ResourceHostMsg_RequestResource(rfh->GetRoutingID(),
+ kRequestIdNotPreviouslyUsed, request));
+ IPC::IpcSecurityTestUtil::PwnMessageReceived(
+ rfh->GetProcess()->GetChannel(),
+ ResourceHostMsg_RequestResource(rfh->GetRoutingID(),
+ kRequestIdNotPreviouslyUsed, request));
+ process_killed.Wait();
+}
+
} // namespace
@@ -145,6 +189,12 @@ class SecurityExploitBrowserTest : public ContentBrowserTest {
",EXCLUDE localhost");
}
+ void SetUpOnMainThread() override {
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&net::URLRequestSlowDownloadJob::AddUrlHandler));
+ }
+
protected:
// Tests that a given file path sent in a ViewHostMsg_RunFileChooser will
// cause renderer to be killed.
@@ -384,7 +434,8 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidOriginHeaders) {
RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
IPC::IpcSecurityTestUtil::PwnMessageReceived(
web_rfh->GetProcess()->GetChannel(),
- ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), 1,
+ ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(),
+ kRequestIdNotPreviouslyUsed,
chrome_origin_msg));
web_process_killed.Wait();
}
@@ -404,7 +455,8 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidOriginHeaders) {
RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
IPC::IpcSecurityTestUtil::PwnMessageReceived(
web_rfh->GetProcess()->GetChannel(),
- ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), 1,
+ ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(),
+ kRequestIdNotPreviouslyUsed,
embedder_isolated_origin_msg));
web_process_killed.Wait();
SetBrowserClientForTesting(old_client);
@@ -418,7 +470,8 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidOriginHeaders) {
RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
IPC::IpcSecurityTestUtil::PwnMessageReceived(
web_rfh->GetProcess()->GetChannel(),
- ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), 1,
+ ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(),
+ kRequestIdNotPreviouslyUsed,
invalid_origin_msg));
web_process_killed.Wait();
}
@@ -431,10 +484,77 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidOriginHeaders) {
RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
IPC::IpcSecurityTestUtil::PwnMessageReceived(
web_rfh->GetProcess()->GetChannel(),
- ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(), 1,
+ ResourceHostMsg_RequestResource(web_rfh->GetRoutingID(),
+ kRequestIdNotPreviouslyUsed,
invalid_scheme_origin_msg));
web_process_killed.Wait();
}
}
+// Renderer process should not be able to create multiple requests with the same
+// id.
+IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, InvalidRequestId) {
+ // Existing loader in pending_loaders_.
+ TryCreateDuplicateRequestIds(shell(), false);
+ // Existing loader in blocked_loaders_map_.
+ TryCreateDuplicateRequestIds(shell(), true);
+}
+
+// Test that receiving a commit with incorrect origin properly terminates the
+// renderer process.
+IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTest, MismatchedOriginOnCommit) {
+ GURL start_url(embedded_test_server()->GetURL("/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), start_url));
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // Setup an URL which will never commit, allowing this test to send its own,
+ // malformed, commit message.
+ GURL url(embedded_test_server()->GetURL("/title2.html"));
+ NavigationStallDelegate stall_delegate(url);
+ ResourceDispatcherHost::Get()->SetDelegate(&stall_delegate);
+
+ // Use LoadURL, as the test shouldn't wait for navigation commit.
+ NavigationController& controller = shell()->web_contents()->GetController();
+ controller.LoadURL(url, Referrer(), ui::PAGE_TRANSITION_LINK, std::string());
+ EXPECT_NE(nullptr, controller.GetPendingEntry());
+ EXPECT_EQ(url, controller.GetPendingEntry()->GetURL());
+
+ RenderProcessHostWatcher exit_observer(
+ root->current_frame_host()->GetProcess(),
+ RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
+
+ // Create commit params with different origins in params.url and
+ // params.origin.
+ FrameHostMsg_DidCommitProvisionalLoad_Params params;
+ params.page_id = 0;
+ params.nav_entry_id = 0;
+ params.did_create_new_entry = false;
+ params.url = url;
+ params.transition = ui::PAGE_TRANSITION_LINK;
+ params.should_update_history = false;
+ params.gesture = NavigationGestureAuto;
+ params.was_within_same_page = false;
+ params.is_post = false;
+ params.page_state = PageState::CreateFromURL(url);
+ params.origin = url::Origin(GURL("http://bar.com/"));
+
+ FrameHostMsg_DidCommitProvisionalLoad msg(
+ root->current_frame_host()->routing_id(), params);
+ IPC::IpcSecurityTestUtil::PwnMessageReceived(
+ root->current_frame_host()->GetProcess()->GetChannel(), msg);
+
+ // When the IPC message is received and validation fails, the process is
+ // terminated. However, the notification for that should be processed in a
+ // separate task of the message loop, so ensure that the process is still
+ // considered alive.
+ EXPECT_TRUE(root->current_frame_host()->GetProcess()->HasConnection());
+
+ exit_observer.Wait();
+ EXPECT_FALSE(exit_observer.did_exit_normally());
+ ResourceDispatcherHost::Get()->SetDelegate(nullptr);
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.cc b/chromium/content/browser/service_worker/embedded_worker_instance.cc
index 9d3290b6d63..69b222a37f9 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_instance.cc
@@ -17,9 +17,11 @@
#include "content/common/content_switches_internal.h"
#include "content/common/mojo/service_registry_impl.h"
#include "content/common/service_worker/embedded_worker_messages.h"
+#include "content/common/service_worker/embedded_worker_settings.h"
#include "content/common/service_worker/embedded_worker_setup.mojom.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/common/child_process_host.h"
#include "ipc/ipc_message.h"
@@ -29,6 +31,11 @@ namespace content {
namespace {
+// When a service worker version's failure count exceeds
+// |kMaxSameProcessFailureCount|, the embedded worker is forced to start in a
+// new process.
+const int kMaxSameProcessFailureCount = 2;
+
void NotifyWorkerReadyForInspectionOnUI(int worker_process_id,
int worker_route_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -54,6 +61,7 @@ void RegisterToWorkerDevToolsManagerOnUI(
const base::WeakPtr<ServiceWorkerContextCore>& service_worker_context_weak,
int64_t service_worker_version_id,
const GURL& url,
+ const GURL& scope,
const base::Callback<void(int worker_devtools_agent_route_id,
bool wait_for_debugger)>& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -64,13 +72,10 @@ void RegisterToWorkerDevToolsManagerOnUI(
worker_devtools_agent_route_id = rph->GetNextRoutingID();
wait_for_debugger =
ServiceWorkerDevToolsManager::GetInstance()->WorkerCreated(
- process_id,
- worker_devtools_agent_route_id,
+ process_id, worker_devtools_agent_route_id,
ServiceWorkerDevToolsManager::ServiceWorkerIdentifier(
- service_worker_context,
- service_worker_context_weak,
- service_worker_version_id,
- url));
+ service_worker_context, service_worker_context_weak,
+ service_worker_version_id, url, scope));
}
BrowserThread::PostTask(
BrowserThread::IO,
@@ -81,16 +86,17 @@ void RegisterToWorkerDevToolsManagerOnUI(
void SetupMojoOnUIThread(
int process_id,
int thread_id,
- mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::InterfacePtrInfo<mojo::ServiceProvider> exposed_services) {
+ mojo::shell::mojom::InterfaceProviderRequest services,
+ mojo::shell::mojom::InterfaceProviderPtrInfo exposed_services) {
RenderProcessHost* rph = RenderProcessHost::FromID(process_id);
// |rph| or its ServiceRegistry may be NULL in unit tests.
if (!rph || !rph->GetServiceRegistry())
return;
- EmbeddedWorkerSetupPtr setup;
+ mojom::EmbeddedWorkerSetupPtr setup;
rph->GetServiceRegistry()->ConnectToRemoteService(mojo::GetProxy(&setup));
- setup->ExchangeServiceProviders(thread_id, std::move(services),
- mojo::MakeProxy(std::move(exposed_services)));
+ setup->ExchangeInterfaceProviders(
+ thread_id, std::move(services),
+ mojo::MakeProxy(std::move(exposed_services)));
}
} // namespace
@@ -140,10 +146,12 @@ class EmbeddedWorkerInstance::WorkerProcessHandle {
public:
WorkerProcessHandle(const base::WeakPtr<ServiceWorkerContextCore>& context,
int embedded_worker_id,
- int process_id)
+ int process_id,
+ bool is_new_process)
: context_(context),
embedded_worker_id_(embedded_worker_id),
- process_id_(process_id) {
+ process_id_(process_id),
+ is_new_process_(is_new_process) {
DCHECK_NE(ChildProcessHost::kInvalidUniqueID, process_id_);
}
@@ -153,12 +161,14 @@ class EmbeddedWorkerInstance::WorkerProcessHandle {
}
int process_id() const { return process_id_; }
+ bool is_new_process() const { return is_new_process_; }
private:
base::WeakPtr<ServiceWorkerContextCore> context_;
const int embedded_worker_id_;
const int process_id_;
+ const bool is_new_process_;
DISALLOW_COPY_AND_ASSIGN(WorkerProcessHandle);
};
@@ -172,13 +182,21 @@ class EmbeddedWorkerInstance::StartTask {
public:
enum class ProcessAllocationState { NOT_ALLOCATED, ALLOCATING, ALLOCATED };
- explicit StartTask(EmbeddedWorkerInstance* instance)
+ StartTask(EmbeddedWorkerInstance* instance, const GURL& script_url)
: instance_(instance),
state_(ProcessAllocationState::NOT_ALLOCATED),
- weak_factory_(this) {}
+ is_installed_(false),
+ start_situation_(ServiceWorkerMetrics::StartSituation::UNKNOWN),
+ weak_factory_(this) {
+ TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", "EmbeddedWorkerInstance::Start",
+ this, "Script", script_url.spec());
+ }
~StartTask() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ TRACE_EVENT_ASYNC_END0("ServiceWorker", "EmbeddedWorkerInstance::Start",
+ this);
+
if (!instance_->context_)
return;
@@ -210,17 +228,22 @@ class EmbeddedWorkerInstance::StartTask {
void Start(scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params,
const StatusCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
- "EmbeddedWorkerInstance::ProcessAllocate",
- params.get(), "Scope", params->scope.spec(),
- "Script URL", params->script_url.spec());
state_ = ProcessAllocationState::ALLOCATING;
start_callback_ = callback;
+ is_installed_ = params->is_installed;
+
+ if (!GetContentClient()->browser()->IsBrowserStartupComplete())
+ start_situation_ = ServiceWorkerMetrics::StartSituation::DURING_STARTUP;
GURL scope(params->scope);
GURL script_url(params->script_url);
+
+ bool can_use_existing_process =
+ instance_->context_->GetVersionFailureCount(
+ params->service_worker_version_id) < kMaxSameProcessFailureCount;
instance_->context_->process_manager()->AllocateWorkerProcess(
- instance_->embedded_worker_id(), scope, script_url,
+ instance_->embedded_worker_id_, scope, script_url,
+ can_use_existing_process,
base::Bind(&StartTask::OnProcessAllocated, weak_factory_.GetWeakPtr(),
base::Passed(&params)));
}
@@ -234,18 +257,24 @@ class EmbeddedWorkerInstance::StartTask {
// |task| may be destroyed.
}
+ bool is_installed() const { return is_installed_; }
+ ServiceWorkerMetrics::StartSituation start_situation() const {
+ return start_situation_;
+ }
+
private:
void OnProcessAllocated(
scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params,
ServiceWorkerStatusCode status,
int process_id,
- bool is_new_process) {
+ bool is_new_process,
+ const EmbeddedWorkerSettings& settings) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- TRACE_EVENT_ASYNC_END1("ServiceWorker",
- "EmbeddedWorkerInstance::ProcessAllocate",
- params.get(), "Status", status);
if (status != SERVICE_WORKER_OK) {
+ TRACE_EVENT_ASYNC_STEP_PAST1(
+ "ServiceWorker", "EmbeddedWorkerInstance::Start", this,
+ "OnProcessAllocated", "Error", ServiceWorkerStatusToString(status));
DCHECK_EQ(ChildProcessHost::kInvalidUniqueID, process_id);
StatusCallback callback = start_callback_;
start_callback_.Reset();
@@ -254,19 +283,39 @@ class EmbeddedWorkerInstance::StartTask {
return;
}
+ TRACE_EVENT_ASYNC_STEP_PAST1(
+ "ServiceWorker", "EmbeddedWorkerInstance::Start", this,
+ "OnProcessAllocated", "Is New Process", is_new_process);
+ if (is_installed_)
+ ServiceWorkerMetrics::RecordProcessCreated(is_new_process);
+
+ if (start_situation_ == ServiceWorkerMetrics::StartSituation::UNKNOWN) {
+ if (is_new_process)
+ start_situation_ = ServiceWorkerMetrics::StartSituation::NEW_PROCESS;
+ else
+ start_situation_ =
+ ServiceWorkerMetrics::StartSituation::EXISTING_PROCESS;
+ }
+
// Notify the instance that a process is allocated.
state_ = ProcessAllocationState::ALLOCATED;
instance_->OnProcessAllocated(make_scoped_ptr(new WorkerProcessHandle(
- instance_->context_, instance_->embedded_worker_id(), process_id)));
+ instance_->context_, instance_->embedded_worker_id(), process_id,
+ is_new_process)));
+
+ // TODO(bengr): Support changes to this setting while the worker
+ // is running.
+ params->settings.data_saver_enabled = settings.data_saver_enabled;
// Register the instance to DevToolsManager on UI thread.
const int64_t service_worker_version_id = params->service_worker_version_id;
+ const GURL& scope = params->scope;
GURL script_url(params->script_url);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(RegisterToWorkerDevToolsManagerOnUI, process_id,
instance_->context_.get(), instance_->context_,
- service_worker_version_id, script_url,
+ service_worker_version_id, script_url, scope,
base::Bind(&StartTask::OnRegisteredToDevToolsManager,
weak_factory_.GetWeakPtr(), base::Passed(&params),
is_new_process)));
@@ -278,6 +327,9 @@ class EmbeddedWorkerInstance::StartTask {
int worker_devtools_agent_route_id,
bool wait_for_debugger) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ TRACE_EVENT_ASYNC_STEP_PAST0("ServiceWorker",
+ "EmbeddedWorkerInstance::Start", this,
+ "OnRegisteredToDevToolsManager");
// Notify the instance that it is registered to the devtools manager.
instance_->OnRegisteredToDevToolsManager(
@@ -293,6 +345,9 @@ class EmbeddedWorkerInstance::StartTask {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
ServiceWorkerStatusCode status = instance_->registry_->SendStartWorker(
std::move(params), instance_->process_id());
+ TRACE_EVENT_ASYNC_STEP_PAST1(
+ "ServiceWorker", "EmbeddedWorkerInstance::Start", this,
+ "SendStartWorker", "Status", ServiceWorkerStatusToString(status));
if (status != SERVICE_WORKER_OK) {
StatusCallback callback = start_callback_;
start_callback_.Reset();
@@ -312,11 +367,20 @@ class EmbeddedWorkerInstance::StartTask {
StatusCallback start_callback_;
ProcessAllocationState state_;
+ // Used for UMA.
+ bool is_installed_;
+ ServiceWorkerMetrics::StartSituation start_situation_;
+
base::WeakPtrFactory<StartTask> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(StartTask);
};
+bool EmbeddedWorkerInstance::Listener::OnMessageReceived(
+ const IPC::Message& message) {
+ return false;
+}
+
EmbeddedWorkerInstance::~EmbeddedWorkerInstance() {
DCHECK(status_ == STOPPING || status_ == STOPPED) << status_;
devtools_proxy_.reset();
@@ -325,10 +389,9 @@ EmbeddedWorkerInstance::~EmbeddedWorkerInstance() {
process_handle_.reset();
}
-void EmbeddedWorkerInstance::Start(int64_t service_worker_version_id,
- const GURL& scope,
- const GURL& script_url,
- const StatusCallback& callback) {
+void EmbeddedWorkerInstance::Start(
+ scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params,
+ const StatusCallback& callback) {
if (!context_) {
callback.Run(SERVICE_WORKER_ERROR_ABORT);
// |this| may be destroyed by the callback.
@@ -336,27 +399,21 @@ void EmbeddedWorkerInstance::Start(int64_t service_worker_version_id,
}
DCHECK(status_ == STOPPED);
- // TODO(horo): If we will see crashes here, we have to find the root cause of
- // the invalid version ID. Otherwise change CHECK to DCHECK.
- CHECK_NE(service_worker_version_id, kInvalidServiceWorkerVersionId);
- start_timing_ = base::TimeTicks::Now();
+ DCHECK(!params->pause_after_download || !params->is_installed);
+ DCHECK_NE(kInvalidServiceWorkerVersionId, params->service_worker_version_id);
+ step_time_ = base::TimeTicks::Now();
status_ = STARTING;
starting_phase_ = ALLOCATING_PROCESS;
network_accessed_for_script_ = false;
service_registry_.reset(new ServiceRegistryImpl());
FOR_EACH_OBSERVER(Listener, listener_list_, OnStarting());
- scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
- new EmbeddedWorkerMsg_StartWorker_Params());
params->embedded_worker_id = embedded_worker_id_;
- params->service_worker_version_id = service_worker_version_id;
- params->scope = scope;
- params->script_url = script_url;
params->worker_devtools_agent_route_id = MSG_ROUTING_NONE;
params->wait_for_debugger = false;
- params->v8_cache_options = GetV8CacheOptions();
+ params->settings.v8_cache_options = GetV8CacheOptions();
- inflight_start_task_.reset(new StartTask(this));
+ inflight_start_task_.reset(new StartTask(this, params->script_url));
inflight_start_task_->Start(std::move(params), callback);
}
@@ -401,6 +458,13 @@ ServiceWorkerStatusCode EmbeddedWorkerInstance::SendMessage(
thread_id_, embedded_worker_id_, message));
}
+void EmbeddedWorkerInstance::ResumeAfterDownload() {
+ if (process_id() == ChildProcessHost::kInvalidUniqueID || status_ != STARTING)
+ return;
+ registry_->Send(process_id(), new EmbeddedWorkerMsg_ResumeAfterDownload(
+ embedded_worker_id_));
+}
+
ServiceRegistry* EmbeddedWorkerInstance::GetServiceRegistry() {
DCHECK(status_ == STARTING || status_ == RUNNING) << status_;
return service_registry_.get();
@@ -439,27 +503,21 @@ void EmbeddedWorkerInstance::OnRegisteredToDevToolsManager(
new DevToolsProxy(process_id(), worker_devtools_agent_route_id));
}
if (wait_for_debugger) {
- // We don't measure the start time when wait_for_debugger flag is set. So we
- // set the NULL time here.
- start_timing_ = base::TimeTicks();
- } else {
- DCHECK(!start_timing_.is_null());
- if (is_new_process) {
- UMA_HISTOGRAM_TIMES("EmbeddedWorkerInstance.NewProcessAllocation",
- base::TimeTicks::Now() - start_timing_);
- } else {
- UMA_HISTOGRAM_TIMES("EmbeddedWorkerInstance.ExistingProcessAllocation",
- base::TimeTicks::Now() - start_timing_);
- }
- UMA_HISTOGRAM_BOOLEAN("EmbeddedWorkerInstance.ProcessCreated",
- is_new_process);
- // Reset |start_timing_| to measure the time excluding the process
- // allocation time.
- start_timing_ = base::TimeTicks::Now();
+ // We don't measure the start time when wait_for_debugger flag is set. So
+ // we set the NULL time here.
+ step_time_ = base::TimeTicks();
}
}
void EmbeddedWorkerInstance::OnStartWorkerMessageSent() {
+ if (!step_time_.is_null()) {
+ base::TimeDelta duration = UpdateStepTime();
+ if (inflight_start_task_->is_installed()) {
+ ServiceWorkerMetrics::RecordTimeToSendStartWorker(
+ duration, inflight_start_task_->start_situation());
+ }
+ }
+
starting_phase_ = SENT_START_WORKER;
FOR_EACH_OBSERVER(Listener, listener_list_, OnStartWorkerMessageSent());
}
@@ -478,32 +536,69 @@ void EmbeddedWorkerInstance::OnScriptReadFinished() {
}
void EmbeddedWorkerInstance::OnScriptLoaded() {
- FOR_EACH_OBSERVER(Listener, listener_list_, OnScriptLoaded());
+ using LoadSource = ServiceWorkerMetrics::LoadSource;
+
+ if (!inflight_start_task_)
+ return;
+ LoadSource source;
+ if (network_accessed_for_script_) {
+ DCHECK(!inflight_start_task_->is_installed());
+ source = LoadSource::NETWORK;
+ } else if (inflight_start_task_->is_installed()) {
+ source = LoadSource::SERVICE_WORKER_STORAGE;
+ } else {
+ source = LoadSource::HTTP_CACHE;
+ }
+ TRACE_EVENT_ASYNC_STEP_PAST1(
+ "ServiceWorker", "EmbeddedWorkerInstance::Start",
+ inflight_start_task_.get(), "OnScriptLoaded", "Source",
+ ServiceWorkerMetrics::LoadSourceToString(source));
+
+ if (!step_time_.is_null()) {
+ base::TimeDelta duration = UpdateStepTime();
+ ServiceWorkerMetrics::RecordTimeToLoad(
+ duration, source, inflight_start_task_->start_situation());
+ }
+
starting_phase_ = SCRIPT_LOADED;
+ FOR_EACH_OBSERVER(Listener, listener_list_, OnScriptLoaded());
+ // |this| may be destroyed by the callback.
+}
+
+void EmbeddedWorkerInstance::OnURLJobCreatedForMainScript() {
+ if (!inflight_start_task_)
+ return;
+ TRACE_EVENT_ASYNC_STEP_PAST0("ServiceWorker", "EmbeddedWorkerInstance::Start",
+ inflight_start_task_.get(), "OnURLJobCreated");
+ if (!step_time_.is_null()) {
+ base::TimeDelta duration = UpdateStepTime();
+ if (inflight_start_task_->is_installed())
+ ServiceWorkerMetrics::RecordTimeToURLJob(
+ duration, inflight_start_task_->start_situation());
+ }
}
void EmbeddedWorkerInstance::OnThreadStarted(int thread_id) {
+ if (!inflight_start_task_)
+ return;
+ TRACE_EVENT_ASYNC_STEP_PAST0("ServiceWorker", "EmbeddedWorkerInstance::Start",
+ inflight_start_task_.get(), "OnThreadStarted");
+
starting_phase_ = THREAD_STARTED;
- if (!start_timing_.is_null()) {
- if (network_accessed_for_script_) {
- UMA_HISTOGRAM_TIMES("EmbeddedWorkerInstance.ScriptLoadWithNetworkAccess",
- base::TimeTicks::Now() - start_timing_);
- } else {
- UMA_HISTOGRAM_TIMES(
- "EmbeddedWorkerInstance.ScriptLoadWithoutNetworkAccess",
- base::TimeTicks::Now() - start_timing_);
- }
- // Reset |start_timing_| to measure the time excluding the process
- // allocation time and the script loading time.
- start_timing_ = base::TimeTicks::Now();
+ if (!step_time_.is_null()) {
+ base::TimeDelta duration = UpdateStepTime();
+ if (inflight_start_task_->is_installed())
+ ServiceWorkerMetrics::RecordTimeToStartThread(
+ duration, inflight_start_task_->start_situation());
}
+
thread_id_ = thread_id;
FOR_EACH_OBSERVER(Listener, listener_list_, OnThreadStarted());
- mojo::ServiceProviderPtr exposed_services;
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services;
service_registry_->Bind(GetProxy(&exposed_services));
- mojo::ServiceProviderPtr services;
- mojo::InterfaceRequest<mojo::ServiceProvider> services_request =
+ mojo::shell::mojom::InterfaceProviderPtr services;
+ mojo::shell::mojom::InterfaceProviderRequest services_request =
GetProxy(&services);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
@@ -514,6 +609,11 @@ void EmbeddedWorkerInstance::OnThreadStarted(int thread_id) {
}
void EmbeddedWorkerInstance::OnScriptLoadFailed() {
+ if (!inflight_start_task_)
+ return;
+ TRACE_EVENT_ASYNC_STEP_PAST0("ServiceWorker", "EmbeddedWorkerInstance::Start",
+ inflight_start_task_.get(),
+ "OnScriptLoadFailed");
FOR_EACH_OBSERVER(Listener, listener_list_, OnScriptLoadFailed());
}
@@ -522,10 +622,15 @@ void EmbeddedWorkerInstance::OnScriptEvaluated(bool success) {
return;
DCHECK_EQ(STARTING, status_);
+ TRACE_EVENT_ASYNC_STEP_PAST1("ServiceWorker", "EmbeddedWorkerInstance::Start",
+ inflight_start_task_.get(), "OnScriptEvaluated",
+ "Success", success);
starting_phase_ = SCRIPT_EVALUATED;
- if (success && !start_timing_.is_null()) {
- UMA_HISTOGRAM_TIMES("EmbeddedWorkerInstance.ScriptEvaluate",
- base::TimeTicks::Now() - start_timing_);
+ if (!step_time_.is_null()) {
+ base::TimeDelta duration = UpdateStepTime();
+ if (success && inflight_start_task_->is_installed())
+ ServiceWorkerMetrics::RecordTimeToEvaluateScript(
+ duration, inflight_start_task_->start_situation());
}
base::WeakPtr<EmbeddedWorkerInstance> weak_this = weak_factory_.GetWeakPtr();
@@ -563,6 +668,10 @@ void EmbeddedWorkerInstance::Detach() {
OnDetached();
}
+base::WeakPtr<EmbeddedWorkerInstance> EmbeddedWorkerInstance::AsWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
bool EmbeddedWorkerInstance::OnMessageReceived(const IPC::Message& message) {
ListenerList::Iterator it(&listener_list_);
while (Listener* listener = it.GetNext()) {
@@ -602,6 +711,11 @@ int EmbeddedWorkerInstance::process_id() const {
return ChildProcessHost::kInvalidUniqueID;
}
+bool EmbeddedWorkerInstance::is_new_process() const {
+ DCHECK(process_handle_);
+ return process_handle_->is_new_process();
+}
+
int EmbeddedWorkerInstance::worker_devtools_agent_route_id() const {
if (devtools_proxy_)
return devtools_proxy_->agent_route_id();
@@ -648,6 +762,15 @@ void EmbeddedWorkerInstance::OnStartFailed(const StatusCallback& callback,
OnStopped(old_status));
}
+base::TimeDelta EmbeddedWorkerInstance::UpdateStepTime() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(!step_time_.is_null());
+ base::TimeTicks now = base::TimeTicks::Now();
+ base::TimeDelta duration = now - step_time_;
+ step_time_ = now;
+ return duration;
+}
+
// static
std::string EmbeddedWorkerInstance::StatusToString(Status status) {
switch (status) {
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance.h b/chromium/content/browser/service_worker/embedded_worker_instance.h
index a4ed91ca8a4..0c9b67ee5d6 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance.h
+++ b/chromium/content/browser/service_worker/embedded_worker_instance.h
@@ -15,10 +15,12 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/strings/string16.h"
#include "base/time/time.h"
+#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_status_code.h"
#include "url/gurl.h"
@@ -100,7 +102,7 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
int line_number,
const GURL& source_url) {}
// Returns false if the message is not handled by this listener.
- virtual bool OnMessageReceived(const IPC::Message& message) = 0;
+ CONTENT_EXPORT virtual bool OnMessageReceived(const IPC::Message& message);
};
~EmbeddedWorkerInstance();
@@ -108,9 +110,9 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
// Starts the worker. It is invalid to call this when the worker is not in
// STOPPED status. |callback| is invoked after the worker script has been
// started and evaluated, or when an error occurs.
- void Start(int64_t service_worker_version_id,
- const GURL& scope,
- const GURL& script_url,
+ // |params| should be populated with service worker version info needed
+ // to start the worker.
+ void Start(scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params,
const StatusCallback& callback);
// Stops the worker. It is invalid to call this when the worker is
@@ -129,6 +131,9 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
// status.
ServiceWorkerStatusCode SendMessage(const IPC::Message& message);
+ // Resumes the worker if it paused after download.
+ void ResumeAfterDownload();
+
// Returns the ServiceRegistry for this worker. It is invalid to call this
// when the worker is not in STARTING or RUNNING status.
ServiceRegistry* GetServiceRegistry();
@@ -141,6 +146,9 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
}
int process_id() const;
int thread_id() const { return thread_id_; }
+ // This should be called only when the worker instance has a valid process,
+ // that is, when |process_id()| returns a valid process id.
+ bool is_new_process() const;
int worker_devtools_agent_route_id() const;
MessagePortMessageFilter* message_port_message_filter() const;
@@ -150,7 +158,11 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
void set_devtools_attached(bool attached) { devtools_attached_ = attached; }
bool devtools_attached() const { return devtools_attached_; }
- // Called when the script load request accessed the network.
+ bool network_accessed_for_script() const {
+ return network_accessed_for_script_;
+ }
+
+ // Called when the main script load accessed the network.
void OnNetworkAccessedForScriptLoad();
// Called when reading the main script from the service worker script cache
@@ -158,11 +170,17 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
void OnScriptReadStarted();
void OnScriptReadFinished();
+ // Called when the net::URLRequestJob to load the service worker script
+ // created. Not called for import scripts.
+ void OnURLJobCreatedForMainScript();
+
static std::string StatusToString(Status status);
static std::string StartingPhaseToString(StartingPhase phase);
void Detach();
+ base::WeakPtr<EmbeddedWorkerInstance> AsWeakPtr();
+
private:
typedef base::ObserverList<Listener> ListenerList;
class DevToolsProxy;
@@ -253,6 +271,10 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
void OnStartFailed(const StatusCallback& callback,
ServiceWorkerStatusCode status);
+ // Returns the time elapsed since |step_time_| and updates |step_time_|
+ // to the current time.
+ base::TimeDelta UpdateStepTime();
+
base::WeakPtr<ServiceWorkerContextCore> context_;
scoped_refptr<EmbeddedWorkerRegistry> registry_;
const int embedded_worker_id_;
@@ -275,7 +297,9 @@ class CONTENT_EXPORT EmbeddedWorkerInstance {
scoped_ptr<DevToolsProxy> devtools_proxy_;
scoped_ptr<StartTask> inflight_start_task_;
- base::TimeTicks start_timing_;
+
+ // Used for UMA. The start time of the current start sequence step.
+ base::TimeTicks step_time_;
base::WeakPtrFactory<EmbeddedWorkerInstance> weak_factory_;
diff --git a/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc b/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc
index dcbb856d9d7..1db995ab1e6 100644
--- a/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_instance_unittest.cc
@@ -32,6 +32,17 @@ void SaveStatusAndCall(ServiceWorkerStatusCode* out,
callback.Run();
}
+scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params>
+CreateStartParams(int version_id, const GURL& scope, const GURL& script_url) {
+ scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
+ new EmbeddedWorkerMsg_StartWorker_Params);
+ params->service_worker_version_id = version_id;
+ params->scope = scope;
+ params->script_url = script_url;
+ params->pause_after_download = false;
+ return params;
+}
+
} // namespace
class EmbeddedWorkerInstanceTest : public testing::Test,
@@ -85,8 +96,10 @@ class EmbeddedWorkerInstanceTest : public testing::Test,
const GURL& url) {
ServiceWorkerStatusCode status;
base::RunLoop run_loop;
- worker->Start(id, pattern, url, base::Bind(&SaveStatusAndCall, &status,
- run_loop.QuitClosure()));
+ scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params =
+ CreateStartParams(id, pattern, url);
+ worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
+ run_loop.QuitClosure()));
run_loop.Run();
return status;
}
@@ -118,13 +131,15 @@ class StalledInStartWorkerHelper : public EmbeddedWorkerTestHelper {
void OnStartWorker(int embedded_worker_id,
int64_t service_worker_version_id,
const GURL& scope,
- const GURL& script_url) override {
+ const GURL& script_url,
+ bool pause_after_download) override {
if (force_stall_in_start_) {
// Do nothing to simulate a stall in the worker process.
return;
}
- EmbeddedWorkerTestHelper::OnStartWorker(
- embedded_worker_id, service_worker_version_id, scope, script_url);
+ EmbeddedWorkerTestHelper::OnStartWorker(embedded_worker_id,
+ service_worker_version_id, scope,
+ script_url, pause_after_download);
}
void set_force_stall_in_start(bool force_stall_in_start) {
@@ -162,11 +177,10 @@ TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) {
// Start should succeed.
ServiceWorkerStatusCode status;
base::RunLoop run_loop;
- worker->Start(
- service_worker_version_id,
- pattern,
- url,
- base::Bind(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
+ scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params =
+ CreateStartParams(service_worker_version_id, pattern, url);
+ worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
+ run_loop.QuitClosure()));
EXPECT_EQ(EmbeddedWorkerInstance::STARTING, worker->status());
run_loop.Run();
EXPECT_EQ(SERVICE_WORKER_OK, status);
@@ -192,6 +206,72 @@ TEST_F(EmbeddedWorkerInstanceTest, StartAndStop) {
EmbeddedWorkerMsg_StopWorker::ID));
}
+// Test that a worker that failed twice will use a new render process
+// on the next attempt.
+TEST_F(EmbeddedWorkerInstanceTest, ForceNewProcess) {
+ scoped_ptr<EmbeddedWorkerInstance> worker =
+ embedded_worker_registry()->CreateWorker();
+ EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+
+ const int64_t service_worker_version_id = 55L;
+ const GURL pattern("http://example.com/");
+ const GURL url("http://example.com/worker.js");
+
+ // Simulate adding one process to the pattern.
+ helper_->SimulateAddProcessToPattern(pattern,
+ helper_->mock_render_process_id());
+
+ // Also simulate adding a "newly created" process to the pattern because
+ // unittests can't actually create a new process itself.
+ // ServiceWorkerProcessManager only chooses this process id in unittests if
+ // can_use_existing_process is false.
+ helper_->SimulateAddProcessToPattern(pattern,
+ helper_->new_render_process_id());
+
+ {
+ // Start once normally.
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ base::RunLoop run_loop;
+ scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
+ CreateStartParams(service_worker_version_id, pattern, url));
+ worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
+ run_loop.QuitClosure()));
+ run_loop.Run();
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(EmbeddedWorkerInstance::RUNNING, worker->status());
+ // The worker should be using the default render process.
+ EXPECT_EQ(helper_->mock_render_process_id(), worker->process_id());
+
+ EXPECT_EQ(SERVICE_WORKER_OK, worker->Stop());
+ base::RunLoop().RunUntilIdle();
+ }
+
+ // Fail twice.
+ context()->UpdateVersionFailureCount(service_worker_version_id,
+ SERVICE_WORKER_ERROR_FAILED);
+ context()->UpdateVersionFailureCount(service_worker_version_id,
+ SERVICE_WORKER_ERROR_FAILED);
+
+ {
+ // Start again.
+ ServiceWorkerStatusCode status;
+ base::RunLoop run_loop;
+ scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
+ CreateStartParams(service_worker_version_id, pattern, url));
+ worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
+ run_loop.QuitClosure()));
+ EXPECT_EQ(EmbeddedWorkerInstance::STARTING, worker->status());
+ run_loop.Run();
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+
+ EXPECT_EQ(EmbeddedWorkerInstance::RUNNING, worker->status());
+ // The worker should be using the new render process.
+ EXPECT_EQ(helper_->new_render_process_id(), worker->process_id());
+ EXPECT_EQ(SERVICE_WORKER_OK, worker->Stop());
+ base::RunLoop().RunUntilIdle();
+ }
+}
+
TEST_F(EmbeddedWorkerInstanceTest, StopWhenDevToolsAttached) {
scoped_ptr<EmbeddedWorkerInstance> worker =
embedded_worker_registry()->CreateWorker();
@@ -256,9 +336,10 @@ TEST_F(EmbeddedWorkerInstanceTest, RemoveWorkerInSharedProcess) {
// Start worker1.
ServiceWorkerStatusCode status;
base::RunLoop run_loop;
- worker1->Start(
- version_id1, pattern, url,
- base::Bind(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
+ scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
+ CreateStartParams(version_id1, pattern, url));
+ worker1->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
+ run_loop.QuitClosure()));
run_loop.Run();
EXPECT_EQ(SERVICE_WORKER_OK, status);
}
@@ -267,9 +348,10 @@ TEST_F(EmbeddedWorkerInstanceTest, RemoveWorkerInSharedProcess) {
// Start worker2.
ServiceWorkerStatusCode status;
base::RunLoop run_loop;
- worker2->Start(
- version_id2, pattern, url,
- base::Bind(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
+ scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
+ CreateStartParams(version_id2, pattern, url));
+ worker2->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
+ run_loop.QuitClosure()));
run_loop.Run();
EXPECT_EQ(SERVICE_WORKER_OK, status);
}
@@ -303,9 +385,10 @@ TEST_F(EmbeddedWorkerInstanceTest, DetachDuringProcessAllocation) {
// Run the start worker sequence and detach during process allocation.
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
- worker->Start(
- version_id, scope, url,
- base::Bind(&SaveStatusAndCall, &status, base::Bind(&base::DoNothing)));
+ scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
+ CreateStartParams(version_id, scope, url));
+ worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
+ base::Bind(&base::DoNothing)));
worker->Detach();
base::RunLoop().RunUntilIdle();
@@ -334,9 +417,10 @@ TEST_F(EmbeddedWorkerInstanceTest, DetachAfterSendingStartWorkerMessage) {
// Run the start worker sequence until a start worker message is sent.
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
- worker->Start(
- version_id, scope, url,
- base::Bind(&SaveStatusAndCall, &status, base::Bind(base::DoNothing)));
+ scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
+ CreateStartParams(version_id, scope, url));
+ worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
+ base::Bind(&base::DoNothing)));
base::RunLoop().RunUntilIdle();
ASSERT_EQ(2u, events_.size());
@@ -371,9 +455,11 @@ TEST_F(EmbeddedWorkerInstanceTest, StopDuringProcessAllocation) {
// Stop the start worker sequence before a process is allocated.
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
- worker->Start(
- version_id, scope, url,
- base::Bind(&SaveStatusAndCall, &status, base::Bind(base::DoNothing)));
+
+ scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
+ CreateStartParams(version_id, scope, url));
+ worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
+ base::Bind(&base::DoNothing)));
worker->Stop();
base::RunLoop().RunUntilIdle();
@@ -393,8 +479,9 @@ TEST_F(EmbeddedWorkerInstanceTest, StopDuringProcessAllocation) {
// Restart the worker.
status = SERVICE_WORKER_ERROR_MAX_VALUE;
scoped_ptr<base::RunLoop> run_loop(new base::RunLoop);
- worker->Start(version_id, scope, url, base::Bind(&SaveStatusAndCall, &status,
- run_loop->QuitClosure()));
+ params = CreateStartParams(version_id, scope, url);
+ worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
+ run_loop->QuitClosure()));
run_loop->Run();
EXPECT_EQ(SERVICE_WORKER_OK, status);
@@ -407,6 +494,37 @@ TEST_F(EmbeddedWorkerInstanceTest, StopDuringProcessAllocation) {
worker->Stop();
}
+TEST_F(EmbeddedWorkerInstanceTest, StopDuringPausedAfterDownload) {
+ const int64_t version_id = 55L;
+ const GURL scope("http://example.com/");
+ const GURL url("http://example.com/worker.js");
+
+ scoped_ptr<EmbeddedWorkerInstance> worker =
+ embedded_worker_registry()->CreateWorker();
+ worker->AddListener(this);
+
+ // Run the start worker sequence until pause after download.
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+
+ scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
+ CreateStartParams(version_id, scope, url));
+ params->pause_after_download = true;
+ worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
+ base::Bind(&base::DoNothing)));
+ base::RunLoop().RunUntilIdle();
+
+ // Make the worker stopping and attempt to send a resume after download
+ // message.
+ worker->Stop();
+ worker->ResumeAfterDownload();
+ base::RunLoop().RunUntilIdle();
+
+ // The resume after download message should not have been sent.
+ EXPECT_EQ(EmbeddedWorkerInstance::STOPPED, worker->status());
+ EXPECT_FALSE(ipc_sink()->GetFirstMessageMatching(
+ EmbeddedWorkerMsg_ResumeAfterDownload::ID));
+}
+
TEST_F(EmbeddedWorkerInstanceTest, StopAfterSendingStartWorkerMessage) {
const int64_t version_id = 55L;
const GURL scope("http://example.com/");
@@ -419,9 +537,10 @@ TEST_F(EmbeddedWorkerInstanceTest, StopAfterSendingStartWorkerMessage) {
// Run the start worker sequence until a start worker message is sent.
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
- worker->Start(
- version_id, scope, url,
- base::Bind(&SaveStatusAndCall, &status, base::Bind(base::DoNothing)));
+ scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
+ CreateStartParams(version_id, scope, url));
+ worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
+ base::Bind(&base::DoNothing)));
base::RunLoop().RunUntilIdle();
ASSERT_EQ(2u, events_.size());
@@ -450,8 +569,10 @@ TEST_F(EmbeddedWorkerInstanceTest, StopAfterSendingStartWorkerMessage) {
->set_force_stall_in_start(false);
status = SERVICE_WORKER_ERROR_MAX_VALUE;
scoped_ptr<base::RunLoop> run_loop(new base::RunLoop);
- worker->Start(version_id, scope, url, base::Bind(&SaveStatusAndCall, &status,
- run_loop->QuitClosure()));
+
+ params = CreateStartParams(version_id, scope, url);
+ worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
+ run_loop->QuitClosure()));
run_loop->Run();
// The worker should be started.
@@ -478,9 +599,10 @@ TEST_F(EmbeddedWorkerInstanceTest, Detach) {
// Start the worker.
base::RunLoop run_loop;
- worker->Start(
- version_id, pattern, url,
- base::Bind(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
+ scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
+ CreateStartParams(version_id, pattern, url));
+ worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
+ run_loop.QuitClosure()));
run_loop.Run();
// Detach.
@@ -512,9 +634,10 @@ TEST_F(EmbeddedWorkerInstanceTest, FailToSendStartIPC) {
// Attempt to start the worker.
base::RunLoop run_loop;
- worker->Start(
- version_id, pattern, url,
- base::Bind(&SaveStatusAndCall, &status, run_loop.QuitClosure()));
+ scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
+ CreateStartParams(version_id, pattern, url));
+ worker->Start(std::move(params), base::Bind(&SaveStatusAndCall, &status,
+ run_loop.QuitClosure()));
run_loop.Run();
// The callback should have run, and we should have got an OnStopped message.
diff --git a/chromium/content/browser/service_worker/embedded_worker_test_helper.cc b/chromium/content/browser/service_worker/embedded_worker_test_helper.cc
index 3f572923391..25fcbd5561f 100644
--- a/chromium/content/browser/service_worker/embedded_worker_test_helper.cc
+++ b/chromium/content/browser/service_worker/embedded_worker_test_helper.cc
@@ -20,6 +20,7 @@
#include "content/common/service_worker/embedded_worker_messages.h"
#include "content/common/service_worker/embedded_worker_setup.mojom.h"
#include "content/common/service_worker/service_worker_messages.h"
+#include "content/public/common/push_event_payload.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
@@ -50,17 +51,18 @@ class MockMessagePortMessageFilter : public MessagePortMessageFilter {
} // namespace
class EmbeddedWorkerTestHelper::MockEmbeddedWorkerSetup
- : public EmbeddedWorkerSetup {
+ : public mojom::EmbeddedWorkerSetup {
public:
- static void Create(const base::WeakPtr<EmbeddedWorkerTestHelper>& helper,
- mojo::InterfaceRequest<EmbeddedWorkerSetup> request) {
+ static void Create(
+ const base::WeakPtr<EmbeddedWorkerTestHelper>& helper,
+ mojo::InterfaceRequest<mojom::EmbeddedWorkerSetup> request) {
new MockEmbeddedWorkerSetup(helper, std::move(request));
}
- void ExchangeServiceProviders(
+ void ExchangeInterfaceProviders(
int32_t thread_id,
- mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services) override {
+ mojo::shell::mojom::InterfaceProviderRequest services,
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services) override {
if (!helper_)
return;
helper_->OnSetupMojoStub(thread_id, std::move(services),
@@ -68,12 +70,13 @@ class EmbeddedWorkerTestHelper::MockEmbeddedWorkerSetup
}
private:
- MockEmbeddedWorkerSetup(const base::WeakPtr<EmbeddedWorkerTestHelper>& helper,
- mojo::InterfaceRequest<EmbeddedWorkerSetup> request)
+ MockEmbeddedWorkerSetup(
+ const base::WeakPtr<EmbeddedWorkerTestHelper>& helper,
+ mojo::InterfaceRequest<mojom::EmbeddedWorkerSetup> request)
: helper_(helper), binding_(this, std::move(request)) {}
base::WeakPtr<EmbeddedWorkerTestHelper> helper_;
- mojo::StrongBinding<EmbeddedWorkerSetup> binding_;
+ mojo::StrongBinding<mojom::EmbeddedWorkerSetup> binding_;
};
EmbeddedWorkerTestHelper::EmbeddedWorkerTestHelper(
@@ -89,7 +92,8 @@ EmbeddedWorkerTestHelper::EmbeddedWorkerTestHelper(
base::ThreadTaskRunnerHandle::Get()));
wrapper_->InitInternal(user_data_directory, std::move(database_task_manager),
base::ThreadTaskRunnerHandle::Get(), nullptr, nullptr);
- wrapper_->process_manager()->SetProcessIdForTest(mock_render_process_id_);
+ wrapper_->process_manager()->SetProcessIdForTest(mock_render_process_id());
+ wrapper_->process_manager()->SetNewProcessIdForTest(new_render_process_id());
registry()->AddChildProcessSender(mock_render_process_id_, this,
NewMessagePortMessageFilter());
@@ -98,7 +102,7 @@ EmbeddedWorkerTestHelper::EmbeddedWorkerTestHelper(
new ServiceRegistryImpl);
render_process_service_registry_.ServiceRegistry::AddService(
base::Bind(&MockEmbeddedWorkerSetup::Create, weak_factory_.GetWeakPtr()));
- mojo::ServiceProviderPtr services;
+ mojo::shell::mojom::InterfaceProviderPtr services;
render_process_service_registry_.Bind(mojo::GetProxy(&services));
host_service_registry->BindRemoteServiceProvider(std::move(services));
render_process_host_->SetServiceRegistry(std::move(host_service_registry));
@@ -128,6 +132,8 @@ bool EmbeddedWorkerTestHelper::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(EmbeddedWorkerTestHelper, message)
IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_StartWorker, OnStartWorkerStub)
+ IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_ResumeAfterDownload,
+ OnResumeAfterDownloadStub)
IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_StopWorker, OnStopWorkerStub)
IPC_MESSAGE_HANDLER(EmbeddedWorkerContextMsg_MessageToWorker,
OnMessageToWorkerStub)
@@ -153,14 +159,20 @@ void EmbeddedWorkerTestHelper::ShutdownContext() {
void EmbeddedWorkerTestHelper::OnStartWorker(int embedded_worker_id,
int64_t service_worker_version_id,
const GURL& scope,
- const GURL& script_url) {
+ const GURL& script_url,
+ bool pause_after_download) {
embedded_worker_id_service_worker_version_id_map_[embedded_worker_id] =
service_worker_version_id;
SimulateWorkerReadyForInspection(embedded_worker_id);
SimulateWorkerScriptCached(embedded_worker_id);
SimulateWorkerScriptLoaded(embedded_worker_id);
- SimulateWorkerThreadStarted(next_thread_id_++, embedded_worker_id);
- SimulateWorkerScriptEvaluated(embedded_worker_id);
+ if (!pause_after_download)
+ OnResumeAfterDownload(embedded_worker_id);
+}
+
+void EmbeddedWorkerTestHelper::OnResumeAfterDownload(int embedded_worker_id) {
+ SimulateWorkerThreadStarted(GetNextThreadId(), embedded_worker_id);
+ SimulateWorkerScriptEvaluated(embedded_worker_id, true /* success */);
SimulateWorkerStarted(embedded_worker_id);
}
@@ -177,6 +189,8 @@ bool EmbeddedWorkerTestHelper::OnMessageToWorker(
current_embedded_worker_id_ = embedded_worker_id;
IPC_BEGIN_MESSAGE_MAP(EmbeddedWorkerTestHelper, message)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ActivateEvent, OnActivateEventStub)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ExtendableMessageEvent,
+ OnExtendableMessageEventStub)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_InstallEvent, OnInstallEventStub)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_FetchEvent, OnFetchEventStub)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_PushEvent, OnPushEventStub)
@@ -197,6 +211,13 @@ void EmbeddedWorkerTestHelper::OnActivateEvent(int embedded_worker_id,
blink::WebServiceWorkerEventResultCompleted));
}
+void EmbeddedWorkerTestHelper::OnExtendableMessageEvent(int embedded_worker_id,
+ int request_id) {
+ SimulateSend(new ServiceWorkerHostMsg_ExtendableMessageEventFinished(
+ embedded_worker_id, request_id,
+ blink::WebServiceWorkerEventResultCompleted));
+}
+
void EmbeddedWorkerTestHelper::OnInstallEvent(int embedded_worker_id,
int request_id) {
// The installing worker may have been doomed and terminated.
@@ -218,12 +239,14 @@ void EmbeddedWorkerTestHelper::OnFetchEvent(
ServiceWorkerResponse(GURL(), 200, "OK",
blink::WebServiceWorkerResponseTypeDefault,
ServiceWorkerHeaderMap(), std::string(), 0, GURL(),
- blink::WebServiceWorkerResponseErrorUnknown)));
+ blink::WebServiceWorkerResponseErrorUnknown,
+ base::Time(), false /* is_in_cache_storage */,
+ std::string() /* cache_storage_cache_name */)));
}
void EmbeddedWorkerTestHelper::OnPushEvent(int embedded_worker_id,
int request_id,
- const std::string& data) {
+ const PushEventPayload& payload) {
SimulateSend(new ServiceWorkerHostMsg_PushEventFinished(
embedded_worker_id, request_id,
blink::WebServiceWorkerEventResultCompleted));
@@ -270,11 +293,12 @@ void EmbeddedWorkerTestHelper::SimulateWorkerThreadStarted(
}
void EmbeddedWorkerTestHelper::SimulateWorkerScriptEvaluated(
- int embedded_worker_id) {
+ int embedded_worker_id,
+ bool success) {
EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
ASSERT_TRUE(worker != NULL);
- registry()->OnWorkerScriptEvaluated(
- worker->process_id(), embedded_worker_id, true /* success */);
+ registry()->OnWorkerScriptEvaluated(worker->process_id(), embedded_worker_id,
+ success);
}
void EmbeddedWorkerTestHelper::SimulateWorkerStarted(
@@ -310,7 +334,16 @@ void EmbeddedWorkerTestHelper::OnStartWorkerStub(
base::Bind(&EmbeddedWorkerTestHelper::OnStartWorker,
weak_factory_.GetWeakPtr(), params.embedded_worker_id,
params.service_worker_version_id, params.scope,
- params.script_url));
+ params.script_url, params.pause_after_download));
+}
+
+void EmbeddedWorkerTestHelper::OnResumeAfterDownloadStub(
+ int embedded_worker_id) {
+ EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
+ ASSERT_TRUE(worker);
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(&EmbeddedWorkerTestHelper::OnResumeAfterDownload,
+ weak_factory_.GetWeakPtr(), embedded_worker_id));
}
void EmbeddedWorkerTestHelper::OnStopWorkerStub(int embedded_worker_id) {
@@ -342,11 +375,18 @@ void EmbeddedWorkerTestHelper::OnMessageToWorkerStub(
void EmbeddedWorkerTestHelper::OnActivateEventStub(int request_id) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind(&EmbeddedWorkerTestHelper::OnActivateEvent,
- weak_factory_.GetWeakPtr(),
- current_embedded_worker_id_,
- request_id));
+ FROM_HERE, base::Bind(&EmbeddedWorkerTestHelper::OnActivateEvent,
+ weak_factory_.GetWeakPtr(),
+ current_embedded_worker_id_, request_id));
+}
+
+void EmbeddedWorkerTestHelper::OnExtendableMessageEventStub(
+ int request_id,
+ const ServiceWorkerMsg_ExtendableMessageEvent_Params& params) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::Bind(&EmbeddedWorkerTestHelper::OnExtendableMessageEvent,
+ weak_factory_.GetWeakPtr(),
+ current_embedded_worker_id_, request_id));
}
void EmbeddedWorkerTestHelper::OnInstallEventStub(int request_id) {
@@ -370,18 +410,19 @@ void EmbeddedWorkerTestHelper::OnFetchEventStub(
request));
}
-void EmbeddedWorkerTestHelper::OnPushEventStub(int request_id,
- const std::string& data) {
+void EmbeddedWorkerTestHelper::OnPushEventStub(
+ int request_id,
+ const PushEventPayload& payload) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(&EmbeddedWorkerTestHelper::OnPushEvent,
weak_factory_.GetWeakPtr(),
- current_embedded_worker_id_, request_id, data));
+ current_embedded_worker_id_, request_id, payload));
}
void EmbeddedWorkerTestHelper::OnSetupMojoStub(
int thread_id,
- mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services) {
+ mojo::shell::mojom::InterfaceProviderRequest services,
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services) {
scoped_ptr<ServiceRegistryImpl> new_registry(new ServiceRegistryImpl);
new_registry->Bind(std::move(services));
new_registry->BindRemoteServiceProvider(std::move(exposed_services));
diff --git a/chromium/content/browser/service_worker/embedded_worker_test_helper.h b/chromium/content/browser/service_worker/embedded_worker_test_helper.h
index a95454a9490..a9d34b511ad 100644
--- a/chromium/content/browser/service_worker/embedded_worker_test_helper.h
+++ b/chromium/content/browser/service_worker/embedded_worker_test_helper.h
@@ -21,8 +21,9 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
-struct EmbeddedWorkerMsg_StartWorker_Params;
class GURL;
+struct EmbeddedWorkerMsg_StartWorker_Params;
+struct ServiceWorkerMsg_ExtendableMessageEvent_Params;
namespace content {
@@ -32,8 +33,9 @@ class MessagePortMessageFilter;
class MockRenderProcessHost;
class ServiceWorkerContextCore;
class ServiceWorkerContextWrapper;
-struct ServiceWorkerFetchRequest;
class TestBrowserContext;
+struct PushEventPayload;
+struct ServiceWorkerFetchRequest;
// In-Process EmbeddedWorker test helper.
//
@@ -77,12 +79,21 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
ServiceWorkerContextWrapper* context_wrapper() { return wrapper_.get(); }
void ShutdownContext();
- int mock_render_process_id() const { return mock_render_process_id_;}
- // Mock render process. Only set if the one-parameter constructor was used.
+ int GetNextThreadId() { return next_thread_id_++; }
+
+ int mock_render_process_id() const { return mock_render_process_id_; }
MockRenderProcessHost* mock_render_process_host() {
return render_process_host_.get();
}
+ std::map<int, int64_t> embedded_worker_id_service_worker_version_id_map() {
+ return embedded_worker_id_service_worker_version_id_map_;
+ }
+
+ // Only used for tests that force creating a new render process. There is no
+ // corresponding MockRenderProcessHost.
+ int new_render_process_id() const { return mock_render_process_id_ + 1; }
+
TestBrowserContext* browser_context() { return browser_context_.get(); }
protected:
@@ -95,7 +106,9 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
virtual void OnStartWorker(int embedded_worker_id,
int64_t service_worker_version_id,
const GURL& scope,
- const GURL& script_url);
+ const GURL& script_url,
+ bool pause_after_download);
+ virtual void OnResumeAfterDownload(int embedded_worker_id);
virtual void OnStopWorker(int embedded_worker_id);
virtual bool OnMessageToWorker(int thread_id,
int embedded_worker_id,
@@ -110,13 +123,14 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
// worker. By default they just return success via
// SimulateSendReplyToBrowser.
virtual void OnActivateEvent(int embedded_worker_id, int request_id);
+ virtual void OnExtendableMessageEvent(int embedded_worker_id, int request_id);
virtual void OnInstallEvent(int embedded_worker_id, int request_id);
virtual void OnFetchEvent(int embedded_worker_id,
int request_id,
const ServiceWorkerFetchRequest& request);
virtual void OnPushEvent(int embedded_worker_id,
int request_id,
- const std::string& data);
+ const PushEventPayload& payload);
// These functions simulate sending an EmbeddedHostMsg message to the
// browser.
@@ -124,7 +138,7 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
void SimulateWorkerScriptCached(int embedded_worker_id);
void SimulateWorkerScriptLoaded(int embedded_worker_id);
void SimulateWorkerThreadStarted(int thread_id, int embedded_worker_id);
- void SimulateWorkerScriptEvaluated(int embedded_worker_id);
+ void SimulateWorkerScriptEvaluated(int embedded_worker_id, bool success);
void SimulateWorkerStarted(int embedded_worker_id);
void SimulateWorkerStopped(int embedded_worker_id);
void SimulateSend(IPC::Message* message);
@@ -135,18 +149,23 @@ class EmbeddedWorkerTestHelper : public IPC::Sender,
class MockEmbeddedWorkerSetup;
void OnStartWorkerStub(const EmbeddedWorkerMsg_StartWorker_Params& params);
+ void OnResumeAfterDownloadStub(int embedded_worker_id);
void OnStopWorkerStub(int embedded_worker_id);
void OnMessageToWorkerStub(int thread_id,
int embedded_worker_id,
const IPC::Message& message);
void OnActivateEventStub(int request_id);
+ void OnExtendableMessageEventStub(
+ int request_id,
+ const ServiceWorkerMsg_ExtendableMessageEvent_Params& params);
void OnInstallEventStub(int request_id);
void OnFetchEventStub(int request_id,
const ServiceWorkerFetchRequest& request);
- void OnPushEventStub(int request_id, const std::string& data);
- void OnSetupMojoStub(int thread_id,
- mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services);
+ void OnPushEventStub(int request_id, const PushEventPayload& payload);
+ void OnSetupMojoStub(
+ int thread_id,
+ mojo::shell::mojom::InterfaceProviderRequest services,
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services);
MessagePortMessageFilter* NewMessagePortMessageFilter();
diff --git a/chromium/content/browser/service_worker/foreign_fetch_request_handler.cc b/chromium/content/browser/service_worker/foreign_fetch_request_handler.cc
index e86e6ecabf8..ec4d5cdb6b8 100644
--- a/chromium/content/browser/service_worker/foreign_fetch_request_handler.cc
+++ b/chromium/content/browser/service_worker/foreign_fetch_request_handler.cc
@@ -4,6 +4,8 @@
#include "content/browser/service_worker/foreign_fetch_request_handler.h"
+#include <string>
+
#include "base/macros.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_url_request_job.h"
@@ -120,8 +122,9 @@ net::URLRequestJob* ForeignFetchRequestHandler::MaybeCreateJob(
ServiceWorkerURLRequestJob* job = new ServiceWorkerURLRequestJob(
request, network_delegate, std::string(), blob_storage_context_,
- resource_context, request_mode_, credentials_mode_, redirect_mode_, false,
- request_context_type_, frame_type_, body_, this);
+ resource_context, request_mode_, credentials_mode_, redirect_mode_,
+ resource_type_, request_context_type_, frame_type_, body_,
+ ServiceWorkerFetchType::FOREIGN_FETCH, this);
job_ = job->GetWeakPtr();
context_->FindReadyRegistrationForDocument(
@@ -179,7 +182,14 @@ void ForeignFetchRequestHandler::DidFindRegistration(
}
}
- if (!scope_matches) {
+ const url::Origin& request_origin = job->request()->initiator();
+ bool origin_matches = active_version->foreign_fetch_origins().empty();
+ for (const url::Origin& origin : active_version->foreign_fetch_origins()) {
+ if (request_origin.IsSameOriginWith(origin))
+ origin_matches = true;
+ }
+
+ if (!scope_matches || !origin_matches) {
job->FallbackToNetwork();
return;
}
@@ -201,7 +211,9 @@ void ForeignFetchRequestHandler::OnStartCompleted(
const GURL& original_url_via_service_worker,
blink::WebServiceWorkerResponseType response_type_via_service_worker,
base::TimeTicks service_worker_start_time,
- base::TimeTicks service_worker_ready_time) {}
+ base::TimeTicks service_worker_ready_time,
+ bool response_is_in_cache_storage,
+ const std::string& response_cache_storage_cache_name) {}
ServiceWorkerVersion* ForeignFetchRequestHandler::GetServiceWorkerVersion(
ServiceWorkerMetrics::URLRequestJobResult* result) {
@@ -214,11 +226,6 @@ ServiceWorkerVersion* ForeignFetchRequestHandler::GetServiceWorkerVersion(
return target_worker_.get();
}
-GURL ForeignFetchRequestHandler::GetRequestingOrigin() {
- // TODO(mek): Implement this.
- return GURL();
-}
-
void ForeignFetchRequestHandler::ClearJob() {
job_.reset();
target_worker_ = nullptr;
diff --git a/chromium/content/browser/service_worker/foreign_fetch_request_handler.h b/chromium/content/browser/service_worker/foreign_fetch_request_handler.h
index 196f7e0f013..9bbf4ea1c1a 100644
--- a/chromium/content/browser/service_worker/foreign_fetch_request_handler.h
+++ b/chromium/content/browser/service_worker/foreign_fetch_request_handler.h
@@ -106,10 +106,11 @@ class CONTENT_EXPORT ForeignFetchRequestHandler
const GURL& original_url_via_service_worker,
blink::WebServiceWorkerResponseType response_type_via_service_worker,
base::TimeTicks worker_start_time,
- base::TimeTicks service_worker_ready_time) override;
+ base::TimeTicks service_worker_ready_time,
+ bool response_is_in_cache_storage,
+ const std::string& response_cache_storage_cache_name) override;
ServiceWorkerVersion* GetServiceWorkerVersion(
ServiceWorkerMetrics::URLRequestJobResult* result) override;
- GURL GetRequestingOrigin() override;
// Sets |job_| to nullptr, and clears all extra response info associated with
// that job.
diff --git a/chromium/content/browser/service_worker/link_header_support.cc b/chromium/content/browser/service_worker/link_header_support.cc
new file mode 100644
index 00000000000..1a957c72693
--- /dev/null
+++ b/chromium/content/browser/service_worker/link_header_support.cc
@@ -0,0 +1,311 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/service_worker/link_header_support.h"
+
+#include "base/command_line.h"
+#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
+#include "content/browser/loader/resource_message_filter.h"
+#include "content/browser/loader/resource_request_info_impl.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/common/service_worker/service_worker_utils.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/content_client.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/origin_util.h"
+#include "net/http/http_util.h"
+#include "net/url_request/url_request.h"
+
+namespace content {
+
+namespace {
+
+// A variation of base::StringTokenizer and net::HttpUtil::ValuesIterator.
+// Takes the parsing of StringTokenizer and adds support for quoted strings that
+// are quoted by matching <> (and does not support escaping in those strings).
+// Also has the behavior of ValuesIterator where it strips whitespace from all
+// values and only outputs non-empty values.
+// Only supports ',' as separator and supports '' "" and <> as quote chars.
+// TODO(mek): Figure out if there is a way to share this with the parsing code
+// in blink::LinkHeader.
+class ValueTokenizer {
+ public:
+ ValueTokenizer(std::string::const_iterator begin,
+ std::string::const_iterator end)
+ : token_begin_(begin), token_end_(begin), end_(end) {}
+
+ std::string::const_iterator token_begin() const { return token_begin_; }
+ std::string::const_iterator token_end() const { return token_end_; }
+
+ bool GetNext() {
+ while (GetNextInternal()) {
+ net::HttpUtil::TrimLWS(&token_begin_, &token_end_);
+
+ // Only return non-empty values.
+ if (token_begin_ != token_end_)
+ return true;
+ }
+ return false;
+ }
+
+ private:
+ // Updates token_begin_ and token_end_ to point to the (possibly empty) next
+ // token. Returns false if end-of-string was reached first.
+ bool GetNextInternal() {
+ // First time this is called token_end_ points to the first character in the
+ // input. Every other time token_end_ points to the delimiter at the end of
+ // the last returned token (which could be the end of the string).
+
+ // End of string, return false.
+ if (token_end_ == end_)
+ return false;
+
+ // Skip past the delimiter.
+ if (*token_end_ == ',')
+ ++token_end_;
+
+ // Make token_begin_ point to the beginning of the next token, and search
+ // for the end of the token in token_end_.
+ token_begin_ = token_end_;
+
+ // Set to true if we're currently inside a quoted string.
+ bool in_quote = false;
+ // Set to true if we're currently inside a quoted string, and have just
+ // encountered an escape character. In this case a closing quote will be
+ // ignored.
+ bool in_escape = false;
+ // If currently in a quoted string, this is the character that (when not
+ // escaped) indicates the end of the string.
+ char quote_close_char = '\0';
+ // If currently in a quoted string, this is set to true if it is possible to
+ // escape the closing quote using '\'.
+ bool quote_allows_escape = false;
+
+ while (token_end_ != end_) {
+ char c = *token_end_;
+ if (in_quote) {
+ if (in_escape) {
+ in_escape = false;
+ } else if (quote_allows_escape && c == '\\') {
+ in_escape = true;
+ } else if (c == quote_close_char) {
+ in_quote = false;
+ }
+ } else {
+ if (c == ',')
+ break;
+ if (c == '\'' || c == '"' || c == '<') {
+ in_quote = true;
+ quote_close_char = (c == '<' ? '>' : c);
+ quote_allows_escape = (c != '<');
+ }
+ }
+ ++token_end_;
+ }
+ return true;
+ }
+
+ std::string::const_iterator token_begin_;
+ std::string::const_iterator token_end_;
+ std::string::const_iterator end_;
+};
+
+// Parses one link in a link header into its url and parameters.
+// A link is of the form "<some-url>; param1=value1; param2=value2".
+// Returns false if parsing the link failed, returns true on success. This
+// method is more lenient than the RFC. It doesn't fail on things like invalid
+// characters in the URL, and also doesn't verify that certain parameters should
+// or shouldn't be quoted strings.
+// If a parameter occurs more than once in the link, only the first value is
+// returned in params as this is the required behavior for all attributes chrome
+// currently cares about in link headers.
+bool ParseLink(std::string::const_iterator begin,
+ std::string::const_iterator end,
+ std::string* url,
+ std::unordered_map<std::string, std::string>* params) {
+ // Can't parse an empty string.
+ if (begin == end)
+ return false;
+
+ // Extract the URL part (everything between '<' and first '>' character).
+ if (*begin != '<')
+ return false;
+ ++begin;
+ std::string::const_iterator url_begin = begin;
+ std::string::const_iterator url_end = std::find(begin, end, '>');
+ // Fail if we did not find a '>'.
+ if (url_end == end)
+ return false;
+ begin = url_end;
+ net::HttpUtil::TrimLWS(&url_begin, &url_end);
+ *url = std::string(url_begin, url_end);
+
+ // Skip the '>' at the end of the URL, trim any remaining whitespace, and make
+ // sure it is followed by a ';' to indicate the start of parameters.
+ ++begin;
+ net::HttpUtil::TrimLWS(&begin, &end);
+ if (begin != end && *begin != ';')
+ return false;
+
+ // Parse all the parameters.
+ net::HttpUtil::NameValuePairsIterator params_iterator(
+ begin, end, ';', net::HttpUtil::NameValuePairsIterator::VALUES_OPTIONAL);
+ while (params_iterator.GetNext()) {
+ if (!net::HttpUtil::IsToken(params_iterator.name_begin(),
+ params_iterator.name_end()))
+ return false;
+ std::string name = base::ToLowerASCII(base::StringPiece(
+ params_iterator.name_begin(), params_iterator.name_end()));
+ params->insert(std::make_pair(name, params_iterator.value()));
+ }
+ return params_iterator.valid();
+}
+
+void RegisterServiceWorkerFinished(int64_t trace_id, bool result) {
+ TRACE_EVENT_ASYNC_END1("ServiceWorker",
+ "LinkHeaderResourceThrottle::HandleServiceWorkerLink",
+ trace_id, "Success", result);
+}
+
+void HandleServiceWorkerLink(
+ const net::URLRequest* request,
+ const std::string& url,
+ const std::unordered_map<std::string, std::string>& params,
+ ServiceWorkerContextWrapper* service_worker_context_for_testing) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures)) {
+ // TODO(mek): Integrate with experimental framework.
+ return;
+ }
+
+ if (ContainsKey(params, "anchor"))
+ return;
+
+ const ResourceRequestInfoImpl* request_info =
+ ResourceRequestInfoImpl::ForRequest(request);
+ ResourceMessageFilter* filter = request_info->filter();
+ ServiceWorkerContext* service_worker_context =
+ filter ? filter->service_worker_context()
+ : service_worker_context_for_testing;
+ if (!service_worker_context)
+ return;
+
+ // TODO(mek): serviceworker links should only be supported on requests from
+ // secure contexts. For now just check the initiator origin, even though that
+ // is not correct: 1) the initiator isn't the origin that matters in case of
+ // navigations, and 2) more than just a secure origin this needs to be a
+ // secure context.
+ if (!request->initiator().unique() &&
+ !IsOriginSecure(GURL(request->initiator().Serialize())))
+ return;
+
+ // TODO(mek): support for a serviceworker link on a request that wouldn't ever
+ // be able to be intercepted by a serviceworker isn't very useful, so this
+ // should share logic with ServiceWorkerRequestHandler and
+ // ForeignFetchRequestHandler to limit the requests for which serviceworker
+ // links are processed.
+
+ GURL context_url = request->url();
+ GURL script_url = context_url.Resolve(url);
+ auto scope_param = params.find("scope");
+ GURL scope_url = scope_param == params.end()
+ ? script_url.Resolve("./")
+ : context_url.Resolve(scope_param->second);
+
+ if (!context_url.is_valid() || !script_url.is_valid() ||
+ !scope_url.is_valid())
+ return;
+ if (!ServiceWorkerUtils::CanRegisterServiceWorker(context_url, scope_url,
+ script_url))
+ return;
+ std::string error;
+ if (ServiceWorkerUtils::ContainsDisallowedCharacter(scope_url, script_url,
+ &error))
+ return;
+
+ int render_process_id = -1;
+ int render_frame_id = -1;
+ ResourceRequestInfo::GetRenderFrameForRequest(request, &render_process_id,
+ &render_frame_id);
+
+ if (!GetContentClient()->browser()->AllowServiceWorker(
+ scope_url, request->first_party_for_cookies(),
+ request_info->GetContext(), render_process_id, render_frame_id))
+ return;
+
+ static int64_t trace_id = 0;
+ TRACE_EVENT_ASYNC_BEGIN2(
+ "ServiceWorker", "LinkHeaderResourceThrottle::HandleServiceWorkerLink",
+ ++trace_id, "Pattern", scope_url.spec(), "Script URL", script_url.spec());
+ service_worker_context->RegisterServiceWorker(
+ scope_url, script_url,
+ base::Bind(&RegisterServiceWorkerFinished, trace_id));
+}
+
+void ProcessLinkHeaderValueForRequest(
+ const net::URLRequest* request,
+ std::string::const_iterator value_begin,
+ std::string::const_iterator value_end,
+ ServiceWorkerContextWrapper* service_worker_context_for_testing) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ std::string url;
+ std::unordered_map<std::string, std::string> params;
+ if (!ParseLink(value_begin, value_end, &url, &params))
+ return;
+
+ for (const auto& rel :
+ base::SplitStringPiece(params["rel"], HTTP_LWS, base::TRIM_WHITESPACE,
+ base::SPLIT_WANT_NONEMPTY)) {
+ if (base::EqualsCaseInsensitiveASCII(rel, "serviceworker"))
+ HandleServiceWorkerLink(request, url, params,
+ service_worker_context_for_testing);
+ }
+}
+
+} // namespace
+
+void ProcessRequestForLinkHeaders(const net::URLRequest* request) {
+ std::string link_header;
+ request->GetResponseHeaderByName("link", &link_header);
+ if (link_header.empty())
+ return;
+
+ ProcessLinkHeaderForRequest(request, link_header);
+}
+
+void ProcessLinkHeaderForRequest(
+ const net::URLRequest* request,
+ const std::string& link_header,
+ ServiceWorkerContextWrapper* service_worker_context_for_testing) {
+ ValueTokenizer tokenizer(link_header.begin(), link_header.end());
+ while (tokenizer.GetNext()) {
+ ProcessLinkHeaderValueForRequest(request, tokenizer.token_begin(),
+ tokenizer.token_end(),
+ service_worker_context_for_testing);
+ }
+}
+
+void SplitLinkHeaderForTesting(const std::string& header,
+ std::vector<std::string>* values) {
+ values->clear();
+ ValueTokenizer tokenizer(header.begin(), header.end());
+ while (tokenizer.GetNext()) {
+ values->push_back(
+ std::string(tokenizer.token_begin(), tokenizer.token_end()));
+ }
+}
+
+bool ParseLinkHeaderValueForTesting(
+ const std::string& link,
+ std::string* url,
+ std::unordered_map<std::string, std::string>* params) {
+ return ParseLink(link.begin(), link.end(), url, params);
+}
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/link_header_support.h b/chromium/content/browser/service_worker/link_header_support.h
new file mode 100644
index 00000000000..b47a6b06503
--- /dev/null
+++ b/chromium/content/browser/service_worker/link_header_support.h
@@ -0,0 +1,38 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_SERVICE_WORKER_LINK_HEADER_SUPPORT_H_
+#define CONTENT_BROWSER_SERVICE_WORKER_LINK_HEADER_SUPPORT_H_
+
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "base/macros.h"
+#include "content/common/content_export.h"
+
+namespace net {
+class URLRequest;
+}
+
+namespace content {
+class ServiceWorkerContextWrapper;
+
+void ProcessRequestForLinkHeaders(const net::URLRequest* request);
+
+CONTENT_EXPORT void ProcessLinkHeaderForRequest(
+ const net::URLRequest* request,
+ const std::string& link_header,
+ ServiceWorkerContextWrapper* service_worker_context_for_testing = nullptr);
+
+CONTENT_EXPORT void SplitLinkHeaderForTesting(const std::string& header,
+ std::vector<std::string>* values);
+CONTENT_EXPORT bool ParseLinkHeaderValueForTesting(
+ const std::string& link,
+ std::string* url,
+ std::unordered_map<std::string, std::string>* params);
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_SERVICE_WORKER_LINK_HEADER_SUPPORT_H_
diff --git a/chromium/content/browser/service_worker/link_header_support_unittest.cc b/chromium/content/browser/service_worker/link_header_support_unittest.cc
new file mode 100644
index 00000000000..ae293fe720e
--- /dev/null
+++ b/chromium/content/browser/service_worker/link_header_support_unittest.cc
@@ -0,0 +1,410 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/service_worker/link_header_support.h"
+
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/run_loop.h"
+#include "content/browser/service_worker/embedded_worker_test_helper.h"
+#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/browser/service_worker/service_worker_registration.h"
+#include "content/public/browser/resource_request_info.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/mock_resource_context.h"
+#include "content/public/test/test_browser_thread_bundle.h"
+#include "net/http/http_response_headers.h"
+#include "net/url_request/url_request_test_job.h"
+#include "net/url_request/url_request_test_util.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace content {
+
+namespace {
+
+TEST(LinkHeaderTest, SplitEmpty) {
+ std::vector<std::string> values;
+ SplitLinkHeaderForTesting("", &values);
+ ASSERT_EQ(0u, values.size());
+}
+
+TEST(LinkHeaderTest, SplitSimple) {
+ std::vector<std::string> values;
+ SplitLinkHeaderForTesting("hello", &values);
+ ASSERT_EQ(1u, values.size());
+ EXPECT_EQ("hello", values[0]);
+
+ SplitLinkHeaderForTesting("foo, bar", &values);
+ ASSERT_EQ(2u, values.size());
+ EXPECT_EQ("foo", values[0]);
+ EXPECT_EQ("bar", values[1]);
+
+ SplitLinkHeaderForTesting(" 1\t,\t2,3", &values);
+ ASSERT_EQ(3u, values.size());
+ EXPECT_EQ("1", values[0]);
+ EXPECT_EQ("2", values[1]);
+ EXPECT_EQ("3", values[2]);
+}
+
+TEST(LinkHeaderTest, SplitSkipsEmpty) {
+ std::vector<std::string> values;
+ SplitLinkHeaderForTesting(", foo, , \t, bar", &values);
+ ASSERT_EQ(2u, values.size());
+ EXPECT_EQ("foo", values[0]);
+ EXPECT_EQ("bar", values[1]);
+}
+
+TEST(LinkHeaderTest, SplitQuotes) {
+ std::vector<std::string> values;
+ SplitLinkHeaderForTesting("\"foo,bar\", 'bar,foo', <hel,lo>", &values);
+ ASSERT_EQ(3u, values.size());
+ EXPECT_EQ("\"foo,bar\"", values[0]);
+ EXPECT_EQ("'bar,foo'", values[1]);
+ EXPECT_EQ("<hel,lo>", values[2]);
+}
+
+TEST(LinkHeaderTest, SplitEscapedQuotes) {
+ std::vector<std::string> values;
+ SplitLinkHeaderForTesting("\"f\\\"oo,bar\", 'b\\'ar,foo', <hel\\>,lo>",
+ &values);
+ ASSERT_EQ(4u, values.size());
+ EXPECT_EQ("\"f\\\"oo,bar\"", values[0]);
+ EXPECT_EQ("'b\\'ar,foo'", values[1]);
+ EXPECT_EQ("<hel\\>", values[2]);
+ EXPECT_EQ("lo>", values[3]);
+}
+
+struct SimpleParseTestData {
+ const char* link;
+ bool valid;
+ const char* url;
+ const char* rel;
+ const char* as;
+};
+
+void PrintTo(const SimpleParseTestData& test, std::ostream* os) {
+ *os << ::testing::PrintToString(test.link);
+}
+
+class SimpleParseTest : public ::testing::TestWithParam<SimpleParseTestData> {};
+
+TEST_P(SimpleParseTest, Simple) {
+ const SimpleParseTestData test = GetParam();
+
+ std::string url;
+ std::unordered_map<std::string, std::string> params;
+ EXPECT_EQ(test.valid,
+ ParseLinkHeaderValueForTesting(test.link, &url, &params));
+ if (test.valid) {
+ EXPECT_EQ(test.url, url);
+ EXPECT_EQ(test.rel, params["rel"]);
+ EXPECT_EQ(test.as, params["as"]);
+ }
+}
+
+// Test data mostly copied from blink::LinkHeaderTest. Expectations for some
+// test cases are different though. Mostly because blink::LinkHeader is stricter
+// about validity while parsing (primarily things like mismatched quotes), and
+// factors in knowledge about semantics of Link headers (parameters that are
+// required to have a value if they occur, some parameters are auto-lower-cased,
+// headers with an "anchor" parameter are rejected by base::LinkHeader).
+// The code this tests purely parses without actually interpreting the data, as
+// it is expected that another layer on top will do more specific validations.
+const SimpleParseTestData simple_parse_tests[] = {
+ {"</images/cat.jpg>; rel=prefetch", true, "/images/cat.jpg", "prefetch",
+ ""},
+ {"</images/cat.jpg>;rel=prefetch", true, "/images/cat.jpg", "prefetch", ""},
+ {"</images/cat.jpg> ;rel=prefetch", true, "/images/cat.jpg", "prefetch",
+ ""},
+ {"</images/cat.jpg> ; rel=prefetch", true, "/images/cat.jpg",
+ "prefetch", ""},
+ {"< /images/cat.jpg> ; rel=prefetch", true, "/images/cat.jpg",
+ "prefetch", ""},
+ {"</images/cat.jpg > ; rel=prefetch", true, "/images/cat.jpg",
+ "prefetch", ""},
+ {"</images/cat.jpg wutwut> ; rel=prefetch", true,
+ "/images/cat.jpg wutwut", "prefetch", ""},
+ {"</images/cat.jpg wutwut \t > ; rel=prefetch", true,
+ "/images/cat.jpg wutwut", "prefetch", ""},
+ {"</images/cat.jpg>; rel=prefetch ", true, "/images/cat.jpg", "prefetch",
+ ""},
+ {"</images/cat.jpg>; Rel=prefetch ", true, "/images/cat.jpg", "prefetch",
+ ""},
+ {"</images/cat.jpg>; Rel=PReFetCh ", true, "/images/cat.jpg", "PReFetCh",
+ ""},
+ {"</images/cat.jpg>; rel=prefetch; rel=somethingelse", true,
+ "/images/cat.jpg", "prefetch", ""},
+ {"</images/cat.jpg>\t\t ; \trel=prefetch \t ", true, "/images/cat.jpg",
+ "prefetch", ""},
+ {"</images/cat.jpg>; rel= prefetch", true, "/images/cat.jpg", "prefetch",
+ ""},
+ {"<../images/cat.jpg?dog>; rel= prefetch", true, "../images/cat.jpg?dog",
+ "prefetch", ""},
+ {"</images/cat.jpg>; rel =prefetch", true, "/images/cat.jpg", "prefetch",
+ ""},
+ {"</images/cat.jpg>; rel pel=prefetch", false},
+ {"< /images/cat.jpg>", true, "/images/cat.jpg", "", ""},
+ {"</images/cat.jpg>; wut=sup; rel =prefetch", true, "/images/cat.jpg",
+ "prefetch", ""},
+ {"</images/cat.jpg>; wut=sup ; rel =prefetch", true, "/images/cat.jpg",
+ "prefetch", ""},
+ {"</images/cat.jpg>; wut=sup ; rel =prefetch \t ;", true,
+ "/images/cat.jpg", "prefetch", ""},
+ {"</images/cat.jpg> wut=sup ; rel =prefetch \t ;", false},
+ {"< /images/cat.jpg", false},
+ {"< http://wut.com/ sdfsdf ?sd>; rel=dns-prefetch", true,
+ "http://wut.com/ sdfsdf ?sd", "dns-prefetch", ""},
+ {"< http://wut.com/%20%20%3dsdfsdf?sd>; rel=dns-prefetch", true,
+ "http://wut.com/%20%20%3dsdfsdf?sd", "dns-prefetch", ""},
+ {"< http://wut.com/dfsdf?sdf=ghj&wer=rty>; rel=prefetch", true,
+ "http://wut.com/dfsdf?sdf=ghj&wer=rty", "prefetch", ""},
+ {"< http://wut.com/dfsdf?sdf=ghj&wer=rty>;;;;; rel=prefetch", true,
+ "http://wut.com/dfsdf?sdf=ghj&wer=rty", "prefetch", ""},
+ {"< http://wut.com/%20%20%3dsdfsdf?sd>; rel=preload;as=image", true,
+ "http://wut.com/%20%20%3dsdfsdf?sd", "preload", "image"},
+ {"< http://wut.com/%20%20%3dsdfsdf?sd>; rel=preload;as=whatever", true,
+ "http://wut.com/%20%20%3dsdfsdf?sd", "preload", "whatever"},
+ {"</images/cat.jpg>; rel=prefetch;", true, "/images/cat.jpg", "prefetch",
+ ""},
+ {"</images/cat.jpg>; rel=prefetch ;", true, "/images/cat.jpg",
+ "prefetch", ""},
+ {"</images/ca,t.jpg>; rel=prefetch ;", true, "/images/ca,t.jpg",
+ "prefetch", ""},
+ {"<simple.css>; rel=stylesheet; title=\"title with a DQUOTE and "
+ "backslash\"",
+ true, "simple.css", "stylesheet", ""},
+ {"<simple.css>; rel=stylesheet; title=\"title with a DQUOTE \\\" and "
+ "backslash: \\\"",
+ true, "simple.css", "stylesheet", ""},
+ {"<simple.css>; title=\"title with a DQUOTE \\\" and backslash: \"; "
+ "rel=stylesheet; ",
+ true, "simple.css", "stylesheet", ""},
+ {"<simple.css>; title=\'title with a DQUOTE \\\' and backslash: \'; "
+ "rel=stylesheet; ",
+ true, "simple.css", "stylesheet", ""},
+ {"<simple.css>; title=\"title with a DQUOTE \\\" and ;backslash,: \"; "
+ "rel=stylesheet; ",
+ true, "simple.css", "stylesheet", ""},
+ {"<simple.css>; title=\"title with a DQUOTE \' and ;backslash,: \"; "
+ "rel=stylesheet; ",
+ true, "simple.css", "stylesheet", ""},
+ {"<simple.css>; title=\"\"; rel=stylesheet; ", true, "simple.css",
+ "stylesheet", ""},
+ {"<simple.css>; title=\"\"; rel=\"stylesheet\"; ", true, "simple.css",
+ "stylesheet", ""},
+ {"<simple.css>; rel=stylesheet; title=\"", true, "simple.css", "stylesheet",
+ ""},
+ {"<simple.css>; rel=stylesheet; title=\"\"", true, "simple.css",
+ "stylesheet", ""},
+ {"<simple.css>; rel=\"stylesheet\"; title=\"", true, "simple.css",
+ "stylesheet", ""},
+ {"<simple.css>; rel=\";style,sheet\"; title=\"", true, "simple.css",
+ ";style,sheet", ""},
+ {"<simple.css>; rel=\"bla'sdf\"; title=\"", true, "simple.css", "bla'sdf",
+ ""},
+ {"<simple.css>; rel=\"\"; title=\"\"", true, "simple.css", "", ""},
+ {"<simple.css>; rel=''; title=\"\"", true, "simple.css", "", ""},
+ {"<simple.css>; rel=''; bla", true, "simple.css", "", ""},
+ {"<simple.css>; rel='prefetch", true, "simple.css", "prefetch", ""},
+ {"<simple.css>; rel=\"prefetch", true, "simple.css", "prefetch", ""},
+ {"<simple.css>; rel=\"", true, "simple.css", "", ""},
+ {"simple.css; rel=prefetch", false},
+ {"<simple.css>; rel=prefetch; rel=foobar", true, "simple.css", "prefetch",
+ ""},
+};
+
+INSTANTIATE_TEST_CASE_P(LinkHeaderTest,
+ SimpleParseTest,
+ testing::ValuesIn(simple_parse_tests));
+
+void SaveFoundRegistrationsCallback(
+ ServiceWorkerStatusCode expected_status,
+ bool* called,
+ std::vector<ServiceWorkerRegistrationInfo>* registrations,
+ ServiceWorkerStatusCode status,
+ const std::vector<ServiceWorkerRegistrationInfo>& result) {
+ EXPECT_EQ(expected_status, status);
+ *called = true;
+ *registrations = result;
+}
+
+ServiceWorkerContextWrapper::GetRegistrationsInfosCallback
+SaveFoundRegistrations(
+ ServiceWorkerStatusCode expected_status,
+ bool* called,
+ std::vector<ServiceWorkerRegistrationInfo>* registrations) {
+ *called = false;
+ return base::Bind(&SaveFoundRegistrationsCallback, expected_status, called,
+ registrations);
+}
+
+class LinkHeaderServiceWorkerTest : public ::testing::Test {
+ public:
+ LinkHeaderServiceWorkerTest()
+ : thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP),
+ resource_context_(&request_context_) {
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableExperimentalWebPlatformFeatures);
+ }
+ ~LinkHeaderServiceWorkerTest() override {}
+
+ void SetUp() override {
+ helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
+ }
+
+ void TearDown() override { helper_.reset(); }
+
+ ServiceWorkerContextWrapper* context_wrapper() {
+ return helper_->context_wrapper();
+ }
+
+ void ProcessLinkHeader(const GURL& request_url,
+ const std::string& link_header) {
+ scoped_ptr<net::URLRequest> request = request_context_.CreateRequest(
+ request_url, net::DEFAULT_PRIORITY, &request_delegate_);
+ ResourceRequestInfo::AllocateForTesting(
+ request.get(), RESOURCE_TYPE_SCRIPT, &resource_context_,
+ -1 /* render_process_id */, -1 /* render_view_id */,
+ -1 /* render_frame_id */, false /* is_main_frame */,
+ false /* parent_is_main_frame */, true /* allow_download */,
+ true /* is_async */, false /* is_using_lofi */);
+
+ ProcessLinkHeaderForRequest(request.get(), link_header, context_wrapper());
+ base::RunLoop().RunUntilIdle();
+ }
+
+ std::vector<ServiceWorkerRegistrationInfo> GetRegistrations() {
+ bool called;
+ std::vector<ServiceWorkerRegistrationInfo> registrations;
+ context_wrapper()->GetAllRegistrations(
+ SaveFoundRegistrations(SERVICE_WORKER_OK, &called, &registrations));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(called);
+ return registrations;
+ }
+
+ private:
+ TestBrowserThreadBundle thread_bundle_;
+ scoped_ptr<EmbeddedWorkerTestHelper> helper_;
+ net::TestURLRequestContext request_context_;
+ net::TestDelegate request_delegate_;
+ MockResourceContext resource_context_;
+};
+
+TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_Basic) {
+ ProcessLinkHeader(GURL("https://example.com/foo/bar/"),
+ "<../foo.js>; rel=serviceworker");
+
+ std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
+ ASSERT_EQ(1u, registrations.size());
+ EXPECT_EQ(GURL("https://example.com/foo/"), registrations[0].pattern);
+ EXPECT_EQ(GURL("https://example.com/foo/foo.js"),
+ registrations[0].active_version.script_url);
+}
+
+TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeWithFragment) {
+ ProcessLinkHeader(GURL("https://example.com/foo/bar/"),
+ "<../bar.js>; rel=serviceworker; scope=\"scope#ref\"");
+
+ std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
+ ASSERT_EQ(1u, registrations.size());
+ EXPECT_EQ(GURL("https://example.com/foo/bar/scope"),
+ registrations[0].pattern);
+ EXPECT_EQ(GURL("https://example.com/foo/bar.js"),
+ registrations[0].active_version.script_url);
+}
+
+TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeAbsoluteUrl) {
+ ProcessLinkHeader(GURL("https://example.com/foo/bar/"),
+ "<bar.js>; rel=serviceworker; "
+ "scope=\"https://example.com:443/foo/bar/scope\"");
+
+ std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
+ ASSERT_EQ(1u, registrations.size());
+ EXPECT_EQ(GURL("https://example.com/foo/bar/scope"),
+ registrations[0].pattern);
+ EXPECT_EQ(GURL("https://example.com/foo/bar/bar.js"),
+ registrations[0].active_version.script_url);
+}
+
+TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeDifferentOrigin) {
+ ProcessLinkHeader(
+ GURL("https://example.com/foobar/"),
+ "<bar.js>; rel=serviceworker; scope=\"https://google.com/scope\"");
+
+ std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
+ ASSERT_EQ(0u, registrations.size());
+}
+
+TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScopeUrlEncodedSlash) {
+ ProcessLinkHeader(GURL("https://example.com/foobar/"),
+ "<bar.js>; rel=serviceworker; scope=\"./foo%2Fbar\"");
+
+ std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
+ ASSERT_EQ(0u, registrations.size());
+}
+
+TEST_F(LinkHeaderServiceWorkerTest,
+ InstallServiceWorker_ScriptUrlEncodedSlash) {
+ ProcessLinkHeader(GURL("https://example.com/foobar/"),
+ "<foo%2Fbar.js>; rel=serviceworker");
+
+ std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
+ ASSERT_EQ(0u, registrations.size());
+}
+
+TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_ScriptAbsoluteUrl) {
+ ProcessLinkHeader(
+ GURL("https://example.com/foobar/"),
+ "<https://example.com/bar.js>; rel=serviceworker; scope=foo");
+
+ std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
+ ASSERT_EQ(1u, registrations.size());
+ EXPECT_EQ(GURL("https://example.com/foobar/foo"), registrations[0].pattern);
+ EXPECT_EQ(GURL("https://example.com/bar.js"),
+ registrations[0].active_version.script_url);
+}
+
+TEST_F(LinkHeaderServiceWorkerTest,
+ InstallServiceWorker_ScriptDifferentOrigin) {
+ ProcessLinkHeader(
+ GURL("https://example.com/foobar/"),
+ "<https://google.com/bar.js>; rel=serviceworker; scope=foo");
+
+ std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
+ ASSERT_EQ(0u, registrations.size());
+}
+
+TEST_F(LinkHeaderServiceWorkerTest, InstallServiceWorker_MultipleWorkers) {
+ ProcessLinkHeader(GURL("https://example.com/foobar/"),
+ "<bar.js>; rel=serviceworker; scope=foo, <baz.js>; "
+ "rel=serviceworker; scope=scope");
+
+ std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
+ ASSERT_EQ(2u, registrations.size());
+ EXPECT_EQ(GURL("https://example.com/foobar/foo"), registrations[0].pattern);
+ EXPECT_EQ(GURL("https://example.com/foobar/bar.js"),
+ registrations[0].active_version.script_url);
+ EXPECT_EQ(GURL("https://example.com/foobar/scope"), registrations[1].pattern);
+ EXPECT_EQ(GURL("https://example.com/foobar/baz.js"),
+ registrations[1].active_version.script_url);
+}
+
+TEST_F(LinkHeaderServiceWorkerTest,
+ InstallServiceWorker_ValidAndInvalidValues) {
+ ProcessLinkHeader(
+ GURL("https://example.com/foobar/"),
+ "<https://google.com/bar.js>; rel=serviceworker; scope=foo, <baz.js>; "
+ "rel=serviceworker; scope=scope");
+
+ std::vector<ServiceWorkerRegistrationInfo> registrations = GetRegistrations();
+ ASSERT_EQ(1u, registrations.size());
+ EXPECT_EQ(GURL("https://example.com/foobar/scope"), registrations[0].pattern);
+ EXPECT_EQ(GURL("https://example.com/foobar/baz.js"),
+ registrations[0].active_version.script_url);
+}
+
+} // namespace
+
+} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_browsertest.cc b/chromium/content/browser/service_worker/service_worker_browsertest.cc
index 205f067a1eb..b8f99a4b3b3 100644
--- a/chromium/content/browser/service_worker/service_worker_browsertest.cc
+++ b/chromium/content/browser/service_worker/service_worker_browsertest.cc
@@ -4,16 +4,22 @@
#include <stddef.h>
#include <stdint.h>
+#include <map>
#include <utility>
#include "base/bind.h"
#include "base/callback.h"
#include "base/command_line.h"
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
+#include "base/strings/string16.h"
+#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/thread_task_runner_handle.h"
+#include "base/time/time.h"
#include "build/build_config.h"
#include "content/browser/fileapi/chrome_blob_storage_context.h"
#include "content/browser/service_worker/embedded_worker_instance.h"
@@ -21,6 +27,7 @@
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_observer.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/browser/service_worker/service_worker_fetch_dispatcher.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
#include "content/browser/service_worker/service_worker_version.h"
@@ -29,19 +36,25 @@
#include "content/common/service_worker/service_worker_types.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/navigation_entry.h"
#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/render_view_host.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
+#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/referrer.h"
+#include "content/public/common/resource_type.h"
#include "content/public/common/security_style.h"
#include "content/public/common/ssl_status.h"
+#include "content/public/common/web_preferences.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
#include "content/shell/browser/shell_content_browser_client.h"
+#include "content/test/test_content_browser_client.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
@@ -74,12 +87,9 @@ void RunOnIOThreadWithDelay(const base::Closure& closure,
base::TimeDelta delay) {
base::RunLoop run_loop;
BrowserThread::PostDelayedTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&RunAndQuit,
- closure,
- run_loop.QuitClosure(),
- base::ThreadTaskRunnerHandle::Get()),
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&RunAndQuit, closure, run_loop.QuitClosure(),
+ base::RetainedRef(base::ThreadTaskRunnerHandle::Get())),
delay);
run_loop.Run();
}
@@ -110,38 +120,6 @@ base::Closure CreatePrepareReceiver(bool* is_prepared) {
return base::Bind(&ReceivePrepareResult, is_prepared);
}
-// Contrary to the style guide, the output parameter of this function comes
-// before input parameters so Bind can be used on it to create a FetchCallback
-// to pass to DispatchFetchEvent.
-void ReceiveFetchResult(BrowserThread::ID run_quit_thread,
- const base::Closure& quit,
- ChromeBlobStorageContext* blob_context,
- FetchResult* out_result,
- ServiceWorkerStatusCode actual_status,
- ServiceWorkerFetchEventResult actual_result,
- const ServiceWorkerResponse& actual_response) {
- out_result->status = actual_status;
- out_result->result = actual_result;
- out_result->response = actual_response;
- if (!actual_response.blob_uuid.empty()) {
- out_result->blob_data_handle =
- blob_context->context()->GetBlobDataFromUUID(
- actual_response.blob_uuid);
- }
- if (!quit.is_null())
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit);
-}
-
-ServiceWorkerVersion::FetchCallback CreateResponseReceiver(
- BrowserThread::ID run_quit_thread,
- const base::Closure& quit,
- ChromeBlobStorageContext* blob_context,
- FetchResult* result) {
- return base::Bind(&ReceiveFetchResult, run_quit_thread, quit,
- make_scoped_refptr<ChromeBlobStorageContext>(blob_context),
- result);
-}
-
void ReceiveFindRegistrationStatus(
BrowserThread::ID run_quit_thread,
const base::Closure& quit,
@@ -224,6 +202,53 @@ scoped_ptr<net::test_server::HttpResponse> VerifyServiceWorkerHeaderInRequest(
return std::move(http_response);
}
+scoped_ptr<net::test_server::HttpResponse> VerifySaveDataHeaderInRequest(
+ const net::test_server::HttpRequest& request) {
+ auto it = request.headers.find("Save-Data");
+ EXPECT_NE(request.headers.end(), it);
+ EXPECT_EQ("on", it->second);
+
+ scoped_ptr<net::test_server::BasicHttpResponse> http_response(
+ new net::test_server::BasicHttpResponse());
+ http_response->set_content_type("text/javascript");
+ return std::move(http_response);
+}
+
+scoped_ptr<net::test_server::HttpResponse> VerifySaveDataHeaderNotInRequest(
+ const net::test_server::HttpRequest& request) {
+ auto it = request.headers.find("Save-Data");
+ EXPECT_EQ(request.headers.end(), it);
+ return make_scoped_ptr(new net::test_server::BasicHttpResponse());
+}
+
+scoped_ptr<net::test_server::HttpResponse>
+VerifySaveDataNotInAccessControlRequestHeader(
+ const net::test_server::HttpRequest& request) {
+ // Save-Data should be present.
+ auto it = request.headers.find("Save-Data");
+ EXPECT_NE(request.headers.end(), it);
+ EXPECT_EQ("on", it->second);
+
+ scoped_ptr<net::test_server::BasicHttpResponse> http_response(
+ new net::test_server::BasicHttpResponse());
+ if (request.method == net::test_server::METHOD_OPTIONS) {
+ // Access-Control-Request-Headers should contain 'X-Custom-Header' and not
+ // contain 'Save-Data'.
+ auto acrh_iter = request.headers.find("Access-Control-Request-Headers");
+ EXPECT_NE(request.headers.end(), acrh_iter);
+ EXPECT_NE(std::string::npos, acrh_iter->second.find("x-custom-header"));
+ EXPECT_EQ(std::string::npos, acrh_iter->second.find("save-data"));
+ http_response->AddCustomHeader("Access-Control-Allow-Headers",
+ acrh_iter->second);
+ http_response->AddCustomHeader("Access-Control-Allow-Methods", "GET");
+ http_response->AddCustomHeader("Access-Control-Allow-Origin", "*");
+ } else {
+ http_response->AddCustomHeader("Access-Control-Allow-Origin", "*");
+ http_response->set_content("PASS");
+ }
+ return std::move(http_response);
+}
+
// The ImportsBustMemcache test requires that the imported script
// would naturally be cached in blink's memcache, but the embedded
// test server doesn't produce headers that allow the blink's memcache
@@ -231,7 +256,7 @@ scoped_ptr<net::test_server::HttpResponse> VerifyServiceWorkerHeaderInRequest(
// an experiration far in the future.
class LongLivedResourceInterceptor : public net::URLRequestInterceptor {
public:
- LongLivedResourceInterceptor(const std::string& body)
+ explicit LongLivedResourceInterceptor(const std::string& body)
: body_(body) {}
~LongLivedResourceInterceptor() override {}
@@ -597,17 +622,30 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
void StartOnIOThread(const base::Closure& done,
ServiceWorkerStatusCode* result) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
- version_->StartWorker(CreateReceiver(BrowserThread::UI, done, result));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiver(BrowserThread::UI, done, result));
}
void InstallOnIOThread(const base::Closure& done,
ServiceWorkerStatusCode* result) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
version_->SetStatus(ServiceWorkerVersion::INSTALLING);
- version_->DispatchInstallEvent(
+ version_->RunAfterStartWorker(
+ ServiceWorkerMetrics::EventType::INSTALL,
+ base::Bind(&self::DispatchInstallEventOnIOThread, this, done, result),
CreateReceiver(BrowserThread::UI, done, result));
}
+ void DispatchInstallEventOnIOThread(const base::Closure& done,
+ ServiceWorkerStatusCode* result) {
+ ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ int request_id =
+ version_->StartRequest(ServiceWorkerMetrics::EventType::INSTALL,
+ CreateReceiver(BrowserThread::UI, done, result));
+ version_->DispatchSimpleEvent<ServiceWorkerHostMsg_InstallEventFinished>(
+ request_id, ServiceWorkerMsg_InstallEvent(request_id));
+ }
+
void StoreOnIOThread(const base::Closure& done,
ServiceWorkerStatusCode* result,
int64_t version_id) {
@@ -624,26 +662,69 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
registration_->SetActiveVersion(version_.get());
- version_->DispatchActivateEvent(
+ version_->RunAfterStartWorker(
+ ServiceWorkerMetrics::EventType::ACTIVATE,
+ base::Bind(&self::DispatchActivateEventOnIOThread, this, done, result),
CreateReceiver(BrowserThread::UI, done, result));
}
+ void DispatchActivateEventOnIOThread(const base::Closure& done,
+ ServiceWorkerStatusCode* result) {
+ ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ int request_id =
+ version_->StartRequest(ServiceWorkerMetrics::EventType::INSTALL,
+ CreateReceiver(BrowserThread::UI, done, result));
+ version_->DispatchSimpleEvent<ServiceWorkerHostMsg_ActivateEventFinished>(
+ request_id, ServiceWorkerMsg_ActivateEvent(request_id));
+ }
+
void FetchOnIOThread(const base::Closure& done,
bool* prepare_result,
FetchResult* result) {
ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
- ServiceWorkerFetchRequest request(
- embedded_test_server()->GetURL("/service_worker/empty.html"),
- "GET",
- ServiceWorkerHeaderMap(),
- Referrer(),
- false);
+ scoped_ptr<ServiceWorkerFetchRequest> request(new ServiceWorkerFetchRequest(
+ embedded_test_server()->GetURL("/service_worker/empty.html"), "GET",
+ ServiceWorkerHeaderMap(), Referrer(), false));
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
- version_->DispatchFetchEvent(
- request,
+ fetch_dispatcher_.reset(new ServiceWorkerFetchDispatcher(
+ std::move(request), version_.get(), RESOURCE_TYPE_MAIN_FRAME,
CreatePrepareReceiver(prepare_result),
- CreateResponseReceiver(
- BrowserThread::UI, done, blob_context_.get(), result));
+ CreateResponseReceiver(done, blob_context_.get(), result)));
+ fetch_dispatcher_->Run();
+ }
+
+ // Contrary to the style guide, the output parameter of this function comes
+ // before input parameters so Bind can be used on it to create a FetchCallback
+ // to pass to DispatchFetchEvent.
+ void ReceiveFetchResultOnIOThread(
+ const base::Closure& quit,
+ ChromeBlobStorageContext* blob_context,
+ FetchResult* out_result,
+ ServiceWorkerStatusCode actual_status,
+ ServiceWorkerFetchEventResult actual_result,
+ const ServiceWorkerResponse& actual_response,
+ const scoped_refptr<ServiceWorkerVersion>& worker) {
+ ASSERT_TRUE(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ ASSERT_TRUE(fetch_dispatcher_);
+ fetch_dispatcher_.reset();
+ out_result->status = actual_status;
+ out_result->result = actual_result;
+ out_result->response = actual_response;
+ if (!actual_response.blob_uuid.empty()) {
+ out_result->blob_data_handle =
+ blob_context->context()->GetBlobDataFromUUID(
+ actual_response.blob_uuid);
+ }
+ if (!quit.is_null())
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit);
+ }
+
+ ServiceWorkerFetchDispatcher::FetchCallback CreateResponseReceiver(
+ const base::Closure& quit,
+ ChromeBlobStorageContext* blob_context,
+ FetchResult* result) {
+ return base::Bind(&self::ReceiveFetchResultOnIOThread, this, quit,
+ base::RetainedRef(blob_context), result);
}
void StopOnIOThread(const base::Closure& done,
@@ -656,6 +737,7 @@ class ServiceWorkerVersionBrowserTest : public ServiceWorkerBrowserTest {
scoped_refptr<ServiceWorkerRegistration> registration_;
scoped_refptr<ServiceWorkerVersion> version_;
scoped_refptr<ChromeBlobStorageContext> blob_context_;
+ scoped_ptr<ServiceWorkerFetchDispatcher> fetch_dispatcher_;
};
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, StartAndStop) {
@@ -791,13 +873,13 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, Activate_Rejected) {
ActivateTestHelper("/service_worker/worker_activate_rejected.js",
- SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED);
+ SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED);
}
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
InstallWithWaitUntil_Rejected) {
InstallTestHelper("/service_worker/worker_install_rejected.js",
- SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED);
+ SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED);
}
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
@@ -815,7 +897,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
base::Bind(&self::InstallOnIOThread, this,
install_run_loop.QuitClosure(), &status));
install_run_loop.Run();
- ASSERT_EQ(SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED, status);
+ ASSERT_EQ(SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED, status);
const base::string16 expected =
base::ASCIIToUTF16("Rejecting oninstall event");
@@ -827,7 +909,7 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
class WaitForLoaded : public EmbeddedWorkerInstance::Listener {
public:
- WaitForLoaded(const base::Closure& quit) : quit_(quit) {}
+ explicit WaitForLoaded(const base::Closure& quit) : quit_(quit) {}
void OnThreadStarted() override {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, quit_);
@@ -838,10 +920,7 @@ class WaitForLoaded : public EmbeddedWorkerInstance::Listener {
base::Closure quit_;
};
-// This test has started flaking somewhat consistently on Win, Mac and Linux.
-// Disabling for now, see http://crbug.com/496065.
-IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
- DISABLED_TimeoutStartingWorker) {
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutStartingWorker) {
RunOnIOThread(base::Bind(&self::SetUpRegistrationOnIOThread, this,
"/service_worker/while_true_worker.js"));
@@ -897,7 +976,9 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, TimeoutWorkerInEvent) {
base::TimeDelta::FromMilliseconds(100));
install_run_loop.Run();
- EXPECT_EQ(SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED, status);
+ // Terminating a worker, even one in an infinite loop, is treated as if
+ // waitUntil was rejected in the renderer code.
+ EXPECT_EQ(SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED, status);
}
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchEvent_Response) {
@@ -922,6 +1003,35 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchEvent_Response) {
}
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+ FetchEvent_ResponseViaCache) {
+ ServiceWorkerFetchEventResult result;
+ ServiceWorkerResponse response1;
+ ServiceWorkerResponse response2;
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle;
+ const base::Time start_time(base::Time::Now());
+
+ RunOnIOThread(
+ base::Bind(&self::SetUpRegistrationOnIOThread, this,
+ "/service_worker/fetch_event_response_via_cache.js"));
+
+ FetchOnRegisteredWorker(&result, &response1, &blob_data_handle);
+ ASSERT_EQ(SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE, result);
+ EXPECT_EQ(200, response1.status_code);
+ EXPECT_EQ("OK", response1.status_text);
+ EXPECT_TRUE(response1.response_time >= start_time);
+ EXPECT_FALSE(response1.is_in_cache_storage);
+ EXPECT_EQ(std::string(), response2.cache_storage_cache_name);
+
+ FetchOnRegisteredWorker(&result, &response2, &blob_data_handle);
+ ASSERT_EQ(SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE, result);
+ EXPECT_EQ(200, response2.status_code);
+ EXPECT_EQ("OK", response2.status_text);
+ EXPECT_EQ(response1.response_time, response2.response_time);
+ EXPECT_TRUE(response2.is_in_cache_storage);
+ EXPECT_EQ("cache_name", response2.cache_storage_cache_name);
+}
+
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
FetchEvent_respondWithRejection) {
ServiceWorkerFetchEventResult result;
ServiceWorkerResponse response;
@@ -950,6 +1060,174 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
ASSERT_FALSE(blob_data_handle);
}
+class MockContentBrowserClient : public TestContentBrowserClient {
+ public:
+ MockContentBrowserClient()
+ : TestContentBrowserClient(), data_saver_enabled_(false) {}
+
+ ~MockContentBrowserClient() override {}
+
+ void set_data_saver_enabled(bool enabled) { data_saver_enabled_ = enabled; }
+
+ // ContentBrowserClient overrides:
+ bool IsDataSaverEnabled(BrowserContext* context) override {
+ return data_saver_enabled_;
+ }
+
+ void OverrideWebkitPrefs(RenderViewHost* render_view_host,
+ WebPreferences* prefs) override {
+ prefs->data_saver_enabled = data_saver_enabled_;
+ }
+
+ private:
+ bool data_saver_enabled_;
+};
+
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchWithSaveData) {
+ embedded_test_server()->RegisterRequestHandler(
+ base::Bind(&VerifySaveDataHeaderInRequest));
+ MockContentBrowserClient content_browser_client;
+ content_browser_client.set_data_saver_enabled(true);
+ ContentBrowserClient* old_client =
+ SetBrowserClientForTesting(&content_browser_client);
+ InstallTestHelper("/service_worker/fetch_in_install.js", SERVICE_WORKER_OK);
+ SetBrowserClientForTesting(old_client);
+}
+
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
+ RequestWorkerScriptWithSaveData) {
+ embedded_test_server()->RegisterRequestHandler(
+ base::Bind(&VerifySaveDataHeaderInRequest));
+ MockContentBrowserClient content_browser_client;
+ content_browser_client.set_data_saver_enabled(true);
+ ContentBrowserClient* old_client =
+ SetBrowserClientForTesting(&content_browser_client);
+ InstallTestHelper("/service_worker/generated_sw.js", SERVICE_WORKER_OK);
+ SetBrowserClientForTesting(old_client);
+}
+
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest, FetchWithoutSaveData) {
+ embedded_test_server()->RegisterRequestHandler(
+ base::Bind(&VerifySaveDataHeaderNotInRequest));
+ MockContentBrowserClient content_browser_client;
+ ContentBrowserClient* old_client =
+ SetBrowserClientForTesting(&content_browser_client);
+ InstallTestHelper("/service_worker/fetch_in_install.js", SERVICE_WORKER_OK);
+ SetBrowserClientForTesting(old_client);
+}
+
+IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, FetchPageWithSaveData) {
+ const char kPageUrl[] = "/service_worker/handle_fetch.html";
+ const char kWorkerUrl[] = "/service_worker/add_save_data_to_title.js";
+ MockContentBrowserClient content_browser_client;
+ content_browser_client.set_data_saver_enabled(true);
+ ContentBrowserClient* old_client =
+ SetBrowserClientForTesting(&content_browser_client);
+ shell()->web_contents()->GetRenderViewHost()->OnWebkitPreferencesChanged();
+ scoped_refptr<WorkerActivatedObserver> observer =
+ new WorkerActivatedObserver(wrapper());
+ observer->Init();
+ public_context()->RegisterServiceWorker(
+ embedded_test_server()->GetURL(kPageUrl),
+ embedded_test_server()->GetURL(kWorkerUrl),
+ base::Bind(&ExpectResultAndRun, true, base::Bind(&base::DoNothing)));
+ observer->Wait();
+
+ const base::string16 title1 = base::ASCIIToUTF16("save-data=on");
+ TitleWatcher title_watcher1(shell()->web_contents(), title1);
+ NavigateToURL(shell(), embedded_test_server()->GetURL(kPageUrl));
+ EXPECT_EQ(title1, title_watcher1.WaitAndGetTitle());
+
+ SetBrowserClientForTesting(old_client);
+ shell()->Close();
+
+ base::RunLoop run_loop;
+ public_context()->UnregisterServiceWorker(
+ embedded_test_server()->GetURL(kPageUrl),
+ base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure()));
+ run_loop.Run();
+}
+
+// Tests that when data saver is enabled and a cross-origin fetch by a webpage
+// is intercepted by a serviceworker, and the serviceworker does a fetch, the
+// preflight request does not have save-data in Access-Control-Request-Headers.
+IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, CrossOriginFetchWithSaveData) {
+ const char kPageUrl[] = "/service_worker/fetch_cross_origin.html";
+ const char kWorkerUrl[] = "/service_worker/fetch_event_pass_through.js";
+ net::EmbeddedTestServer cross_origin_server;
+ cross_origin_server.ServeFilesFromSourceDirectory("content/test/data");
+ cross_origin_server.RegisterRequestHandler(
+ base::Bind(&VerifySaveDataNotInAccessControlRequestHeader));
+ cross_origin_server.Start();
+
+ MockContentBrowserClient content_browser_client;
+ content_browser_client.set_data_saver_enabled(true);
+ ContentBrowserClient* old_client =
+ SetBrowserClientForTesting(&content_browser_client);
+ shell()->web_contents()->GetRenderViewHost()->OnWebkitPreferencesChanged();
+ scoped_refptr<WorkerActivatedObserver> observer =
+ new WorkerActivatedObserver(wrapper());
+ observer->Init();
+ public_context()->RegisterServiceWorker(
+ embedded_test_server()->GetURL(kPageUrl),
+ embedded_test_server()->GetURL(kWorkerUrl),
+ base::Bind(&ExpectResultAndRun, true, base::Bind(&base::DoNothing)));
+ observer->Wait();
+
+ const base::string16 title = base::ASCIIToUTF16("PASS");
+ TitleWatcher title_watcher(shell()->web_contents(), title);
+ NavigateToURL(shell(),
+ embedded_test_server()->GetURL(base::StringPrintf(
+ "%s?%s", kPageUrl,
+ cross_origin_server.GetURL("/cross_origin_request.html")
+ .spec()
+ .c_str())));
+ EXPECT_EQ(title, title_watcher.WaitAndGetTitle());
+
+ SetBrowserClientForTesting(old_client);
+ shell()->Close();
+
+ base::RunLoop run_loop;
+ public_context()->UnregisterServiceWorker(
+ embedded_test_server()->GetURL(kPageUrl),
+ base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure()));
+ run_loop.Run();
+}
+
+IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest,
+ FetchPageWithSaveDataPassThroughOnFetch) {
+ const char kPageUrl[] = "/service_worker/pass_through_fetch.html";
+ const char kWorkerUrl[] = "/service_worker/fetch_event_pass_through.js";
+ MockContentBrowserClient content_browser_client;
+ content_browser_client.set_data_saver_enabled(true);
+ ContentBrowserClient* old_client =
+ SetBrowserClientForTesting(&content_browser_client);
+ shell()->web_contents()->GetRenderViewHost()->OnWebkitPreferencesChanged();
+ scoped_refptr<WorkerActivatedObserver> observer =
+ new WorkerActivatedObserver(wrapper());
+ observer->Init();
+ public_context()->RegisterServiceWorker(
+ embedded_test_server()->GetURL(kPageUrl),
+ embedded_test_server()->GetURL(kWorkerUrl),
+ base::Bind(&ExpectResultAndRun, true, base::Bind(&base::DoNothing)));
+ observer->Wait();
+
+ embedded_test_server()->RegisterRequestHandler(
+ base::Bind(&VerifySaveDataHeaderInRequest));
+
+ NavigateToURLBlockUntilNavigationsComplete(
+ shell(), embedded_test_server()->GetURL(kPageUrl), 1);
+
+ SetBrowserClientForTesting(old_client);
+ shell()->Close();
+
+ base::RunLoop run_loop;
+ public_context()->UnregisterServiceWorker(
+ embedded_test_server()->GetURL(kPageUrl),
+ base::Bind(&ExpectResultAndRun, true, run_loop.QuitClosure()));
+ run_loop.Run();
+}
+
IN_PROC_BROWSER_TEST_F(ServiceWorkerBrowserTest, Reload) {
const char kPageUrl[] = "/service_worker/reload.html";
const char kWorkerUrl[] = "/service_worker/fetch_event_reload.js";
diff --git a/chromium/content/browser/service_worker/service_worker_cache_writer_unittest.cc b/chromium/content/browser/service_worker/service_worker_cache_writer_unittest.cc
index bc0eac40557..8c88982c718 100644
--- a/chromium/content/browser/service_worker/service_worker_cache_writer_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_cache_writer_unittest.cc
@@ -11,7 +11,6 @@
#include <string>
#include "base/macros.h"
-#include "base/stl_util.h"
#include "content/browser/service_worker/service_worker_disk_cache.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -38,7 +37,10 @@ namespace {
// there are any expected reads that have not yet happened.
class MockServiceWorkerResponseReader : public ServiceWorkerResponseReader {
public:
- MockServiceWorkerResponseReader() : ServiceWorkerResponseReader(0, nullptr) {}
+ MockServiceWorkerResponseReader()
+ : ServiceWorkerResponseReader(
+ 0,
+ base::WeakPtr<AppCacheDiskCacheInterface>()) {}
~MockServiceWorkerResponseReader() override {}
// ServiceWorkerResponseReader overrides
@@ -90,6 +92,8 @@ class MockServiceWorkerResponseReader : public ServiceWorkerResponseReader {
size_t pending_buffer_len_;
scoped_refptr<HttpResponseInfoIOBuffer> pending_info_;
net::CompletionCallback pending_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockServiceWorkerResponseReader);
};
void MockServiceWorkerResponseReader::ReadInfo(
@@ -194,7 +198,9 @@ void MockServiceWorkerResponseReader::CompletePendingRead() {
class MockServiceWorkerResponseWriter : public ServiceWorkerResponseWriter {
public:
MockServiceWorkerResponseWriter()
- : ServiceWorkerResponseWriter(0, nullptr),
+ : ServiceWorkerResponseWriter(
+ 0,
+ base::WeakPtr<AppCacheDiskCacheInterface>()),
info_written_(0),
data_written_(0) {}
~MockServiceWorkerResponseWriter() override {}
@@ -236,6 +242,8 @@ class MockServiceWorkerResponseWriter : public ServiceWorkerResponseWriter {
size_t data_written_;
net::CompletionCallback pending_callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockServiceWorkerResponseWriter);
};
void MockServiceWorkerResponseWriter::WriteInfo(
@@ -311,14 +319,14 @@ void MockServiceWorkerResponseWriter::CompletePendingWrite() {
class ServiceWorkerCacheWriterTest : public ::testing::Test {
public:
- ServiceWorkerCacheWriterTest()
- : readers_deleter_(&readers_), writers_deleter_(&writers_) {}
+ ServiceWorkerCacheWriterTest() {}
+ ~ServiceWorkerCacheWriterTest() override {}
MockServiceWorkerResponseReader* ExpectReader() {
scoped_ptr<MockServiceWorkerResponseReader> reader(
new MockServiceWorkerResponseReader);
MockServiceWorkerResponseReader* borrowed_reader = reader.get();
- readers_.push_back(reader.release()); // give ownership to |readers_|
+ readers_.push_back(std::move(reader));
return borrowed_reader;
}
@@ -326,7 +334,7 @@ class ServiceWorkerCacheWriterTest : public ::testing::Test {
scoped_ptr<MockServiceWorkerResponseWriter> writer(
new MockServiceWorkerResponseWriter);
MockServiceWorkerResponseWriter* borrowed_writer = writer.get();
- writers_.push_back(writer.release()); // give ownership to |writers_|
+ writers_.push_back(std::move(writer));
return borrowed_writer;
}
@@ -340,17 +348,8 @@ class ServiceWorkerCacheWriterTest : public ::testing::Test {
}
protected:
- // TODO(ellyjones): when unique_ptr<> is allowed, make these instead:
- // std::list<unique_ptr<...>>
- // Right now, these cannot use scoped_ptr.
- // Their elements are deleted by the STLElementDeleters below when this object
- // goes out of scope.
- std::list<MockServiceWorkerResponseReader*> readers_;
- std::list<MockServiceWorkerResponseWriter*> writers_;
- STLElementDeleter<std::list<MockServiceWorkerResponseReader*>>
- readers_deleter_;
- STLElementDeleter<std::list<MockServiceWorkerResponseWriter*>>
- writers_deleter_;
+ std::list<scoped_ptr<MockServiceWorkerResponseReader>> readers_;
+ std::list<scoped_ptr<MockServiceWorkerResponseWriter>> writers_;
scoped_ptr<ServiceWorkerCacheWriter> cache_writer_;
bool write_complete_ = false;
net::Error last_error_;
@@ -358,14 +357,15 @@ class ServiceWorkerCacheWriterTest : public ::testing::Test {
scoped_ptr<ServiceWorkerResponseReader> CreateReader() {
if (readers_.empty())
return make_scoped_ptr<ServiceWorkerResponseReader>(nullptr);
- scoped_ptr<ServiceWorkerResponseReader> reader(readers_.front());
+ scoped_ptr<ServiceWorkerResponseReader> reader(std::move(readers_.front()));
readers_.pop_front();
return reader;
}
+
scoped_ptr<ServiceWorkerResponseWriter> CreateWriter() {
if (writers_.empty())
return make_scoped_ptr<ServiceWorkerResponseWriter>(nullptr);
- scoped_ptr<ServiceWorkerResponseWriter> writer(writers_.front());
+ scoped_ptr<ServiceWorkerResponseWriter> writer(std::move(writers_.front()));
writers_.pop_front();
return writer;
}
@@ -391,6 +391,9 @@ class ServiceWorkerCacheWriterTest : public ::testing::Test {
return cache_writer_->MaybeWriteData(buf.get(), data.size(),
CreateWriteCallback());
}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerCacheWriterTest);
};
// Passthrough tests:
diff --git a/chromium/content/browser/service_worker/service_worker_client_utils.cc b/chromium/content/browser/service_worker/service_worker_client_utils.cc
index 26ef4d35f18..93fe0f3ef33 100644
--- a/chromium/content/browser/service_worker/service_worker_client_utils.cc
+++ b/chromium/content/browser/service_worker/service_worker_client_utils.cc
@@ -11,13 +11,17 @@
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/browser/storage_partition_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/service_worker/service_worker_client_info.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/page_navigator.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/child_process_host.h"
@@ -90,8 +94,60 @@ class OpenURLObserver : public WebContentsObserver {
DISALLOW_COPY_AND_ASSIGN(OpenURLObserver);
};
+ServiceWorkerClientInfo GetWindowClientInfoOnUI(
+ int render_process_id,
+ int render_frame_id,
+ const std::string& client_uuid) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ RenderFrameHostImpl* render_frame_host =
+ RenderFrameHostImpl::FromID(render_process_id, render_frame_id);
+ if (!render_frame_host)
+ return ServiceWorkerClientInfo();
+
+ // TODO(mlamouri,michaeln): it is possible to end up collecting information
+ // for a frame that is actually being navigated and isn't exactly what we are
+ // expecting.
+ return ServiceWorkerClientInfo(
+ client_uuid, render_frame_host->GetVisibilityState(),
+ render_frame_host->IsFocused(), render_frame_host->GetLastCommittedURL(),
+ render_frame_host->GetParent() ? REQUEST_CONTEXT_FRAME_TYPE_NESTED
+ : REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL,
+ render_frame_host->frame_tree_node()->last_focus_time(),
+ blink::WebServiceWorkerClientTypeWindow);
+}
+
+ServiceWorkerClientInfo FocusOnUI(int render_process_id,
+ int render_frame_id,
+ const std::string& client_uuid) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ RenderFrameHostImpl* render_frame_host =
+ RenderFrameHostImpl::FromID(render_process_id, render_frame_id);
+ WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
+ WebContents::FromRenderFrameHost(render_frame_host));
+
+ if (!render_frame_host || !web_contents)
+ return ServiceWorkerClientInfo();
+
+ FrameTreeNode* frame_tree_node = render_frame_host->frame_tree_node();
+
+ // Focus the frame in the frame tree node, in case it has changed.
+ frame_tree_node->frame_tree()->SetFocusedFrame(
+ frame_tree_node, render_frame_host->GetSiteInstance());
+
+ // Focus the frame's view to make sure the frame is now considered as focused.
+ render_frame_host->GetView()->Focus();
+
+ // Move the web contents to the foreground.
+ web_contents->Activate();
+
+ return GetWindowClientInfoOnUI(render_process_id, render_frame_id,
+ client_uuid);
+}
+
// This is only called for main frame navigations in OpenWindowOnUI().
-void DidOpenURL(const OpenURLCallback& callback, WebContents* web_contents) {
+void DidOpenURLOnUI(const OpenURLCallback& callback,
+ WebContents* web_contents) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(web_contents);
RenderFrameHostImpl* rfhi =
@@ -133,7 +189,7 @@ void OpenWindowOnUI(
true /* is_renderer_initiated */);
GetContentClient()->browser()->OpenURL(browser_context, params,
- base::Bind(&DidOpenURL, callback));
+ base::Bind(&DidOpenURLOnUI, callback));
}
void NavigateClientOnUI(const GURL& url,
@@ -176,15 +232,13 @@ void DidNavigate(const base::WeakPtr<ServiceWorkerContextCore>& context,
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!context) {
- callback.Run(SERVICE_WORKER_ERROR_ABORT, std::string(),
- ServiceWorkerClientInfo());
+ callback.Run(SERVICE_WORKER_ERROR_ABORT, ServiceWorkerClientInfo());
return;
}
if (render_process_id == ChildProcessHost::kInvalidUniqueID &&
render_frame_id == MSG_ROUTING_NONE) {
- callback.Run(SERVICE_WORKER_ERROR_FAILED, std::string(),
- ServiceWorkerClientInfo());
+ callback.Run(SERVICE_WORKER_ERROR_FAILED, ServiceWorkerClientInfo());
return;
}
@@ -196,19 +250,23 @@ void DidNavigate(const base::WeakPtr<ServiceWorkerContextCore>& context,
provider_host->frame_id() != render_frame_id) {
continue;
}
- provider_host->GetWindowClientInfo(
- base::Bind(callback, SERVICE_WORKER_OK, provider_host->client_uuid()));
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&GetWindowClientInfoOnUI, provider_host->process_id(),
+ provider_host->route_id(), provider_host->client_uuid()),
+ base::Bind(callback, SERVICE_WORKER_OK));
return;
}
// If here, it means that no provider_host was found, in which case, the
// renderer should still be informed that the window was opened.
- callback.Run(SERVICE_WORKER_OK, std::string(), ServiceWorkerClientInfo());
+ callback.Run(SERVICE_WORKER_OK, ServiceWorkerClientInfo());
}
void AddWindowClient(
ServiceWorkerProviderHost* host,
std::vector<base::Tuple<int, int, std::string>>* client_info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (host->client_type() != blink::WebServiceWorkerClientTypeWindow)
return;
client_info->push_back(base::MakeTuple(host->process_id(), host->frame_id(),
@@ -218,6 +276,7 @@ void AddWindowClient(
void AddNonWindowClient(ServiceWorkerProviderHost* host,
const ServiceWorkerClientQueryOptions& options,
ServiceWorkerClients* clients) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
blink::WebServiceWorkerClientType host_client_type = host->client_type();
if (host_client_type == blink::WebServiceWorkerClientTypeWindow)
return;
@@ -225,12 +284,11 @@ void AddNonWindowClient(ServiceWorkerProviderHost* host,
options.client_type != host_client_type)
return;
- ServiceWorkerClientInfo client_info(blink::WebPageVisibilityStateHidden,
- false, // is_focused
- host->document_url(),
- REQUEST_CONTEXT_FRAME_TYPE_NONE,
- base::TimeTicks(), host_client_type);
- client_info.client_uuid = host->client_uuid();
+ ServiceWorkerClientInfo client_info(
+ host->client_uuid(), blink::WebPageVisibilityStateHidden,
+ false, // is_focused
+ host->document_url(), REQUEST_CONTEXT_FRAME_TYPE_NONE, base::TimeTicks(),
+ host_client_type);
clients->push_back(client_info);
}
@@ -239,12 +297,12 @@ void OnGetWindowClientsOnUI(
const std::vector<base::Tuple<int, int, std::string>>& clients_info,
const GURL& script_url,
const GetWindowClientsCallback& callback) {
- scoped_ptr<ServiceWorkerClients> clients(new ServiceWorkerClients);
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ scoped_ptr<ServiceWorkerClients> clients(new ServiceWorkerClients);
for (const auto& it : clients_info) {
- ServiceWorkerClientInfo info =
- ServiceWorkerProviderHost::GetWindowClientInfoOnUI(base::get<0>(it),
- base::get<1>(it));
+ ServiceWorkerClientInfo info = GetWindowClientInfoOnUI(
+ base::get<0>(it), base::get<1>(it), base::get<2>(it));
// If the request to the provider_host returned an empty
// ServiceWorkerClientInfo, that means that it wasn't possible to associate
@@ -259,7 +317,6 @@ void OnGetWindowClientsOnUI(
if (info.url.GetOrigin() != script_url.GetOrigin())
continue;
- info.client_uuid = base::get<2>(it);
clients->push_back(info);
}
@@ -287,6 +344,7 @@ void DidGetClients(const ClientsCallback& callback,
void GetNonWindowClients(const base::WeakPtr<ServiceWorkerVersion>& controller,
const ServiceWorkerClientQueryOptions& options,
ServiceWorkerClients* clients) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!options.include_uncontrolled) {
for (auto& controllee : controller->controllee_map())
AddNonWindowClient(controllee.second, options, clients);
@@ -343,6 +401,18 @@ void GetWindowClients(const base::WeakPtr<ServiceWorkerVersion>& controller,
} // namespace
+void FocusWindowClient(ServiceWorkerProviderHost* provider_host,
+ const ClientCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK_EQ(blink::WebServiceWorkerClientTypeWindow,
+ provider_host->client_type());
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&FocusOnUI, provider_host->process_id(),
+ provider_host->frame_id(), provider_host->client_uuid()),
+ callback);
+}
+
void OpenWindow(const GURL& url,
const GURL& script_url,
int worker_process_id,
@@ -371,6 +441,34 @@ void NavigateClient(const GURL& url,
base::Bind(&DidNavigate, context, script_url.GetOrigin(), callback)));
}
+void GetClient(ServiceWorkerProviderHost* provider_host,
+ const ClientCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ blink::WebServiceWorkerClientType client_type = provider_host->client_type();
+ DCHECK(client_type == blink::WebServiceWorkerClientTypeWindow ||
+ client_type == blink::WebServiceWorkerClientTypeWorker ||
+ client_type == blink::WebServiceWorkerClientTypeSharedWorker)
+ << client_type;
+
+ if (client_type == blink::WebServiceWorkerClientTypeWindow) {
+ BrowserThread::PostTaskAndReplyWithResult(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&GetWindowClientInfoOnUI, provider_host->process_id(),
+ provider_host->route_id(), provider_host->client_uuid()),
+ callback);
+ return;
+ }
+
+ ServiceWorkerClientInfo client_info(
+ provider_host->client_uuid(), blink::WebPageVisibilityStateHidden,
+ false, // is_focused
+ provider_host->document_url(), REQUEST_CONTEXT_FRAME_TYPE_NONE,
+ base::TimeTicks(), provider_host->client_type());
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(callback, client_info));
+}
+
void GetClients(const base::WeakPtr<ServiceWorkerVersion>& controller,
const ServiceWorkerClientQueryOptions& options,
const ClientsCallback& callback) {
diff --git a/chromium/content/browser/service_worker/service_worker_client_utils.h b/chromium/content/browser/service_worker/service_worker_client_utils.h
index 258268e1e0d..be46f6c13e7 100644
--- a/chromium/content/browser/service_worker/service_worker_client_utils.h
+++ b/chromium/content/browser/service_worker/service_worker_client_utils.h
@@ -17,6 +17,7 @@ class GURL;
namespace content {
class ServiceWorkerContextCore;
+class ServiceWorkerProviderHost;
class ServiceWorkerVersion;
struct ServiceWorkerClientInfo;
struct ServiceWorkerClientQueryOptions;
@@ -25,11 +26,17 @@ namespace service_worker_client_utils {
using NavigationCallback =
base::Callback<void(ServiceWorkerStatusCode status,
- const std::string& client_uuid,
const ServiceWorkerClientInfo& client_info)>;
+using ClientCallback =
+ base::Callback<void(const ServiceWorkerClientInfo& client_info)>;
using ServiceWorkerClients = std::vector<ServiceWorkerClientInfo>;
using ClientsCallback = base::Callback<void(ServiceWorkerClients* clients)>;
+// Focuses the window client associated with |provider_host|. |callback| is
+// called with the client information on completion.
+void FocusWindowClient(ServiceWorkerProviderHost* provider_host,
+ const ClientCallback& callback);
+
// Opens a new window and navigates it to |url|. |callback| is called with the
// window's client information on completion.
void OpenWindow(const GURL& url,
@@ -47,6 +54,11 @@ void NavigateClient(const GURL& url,
const base::WeakPtr<ServiceWorkerContextCore>& context,
const NavigationCallback& callback);
+// Gets the client specified by |provider_host|. |callback| is called with the
+// client information on completion.
+void GetClient(ServiceWorkerProviderHost* provider_host,
+ const ClientCallback& callback);
+
// Collects clients matched with |options|. |callback| is called with the client
// information sorted in MRU order (most recently focused order) on completion.
void GetClients(const base::WeakPtr<ServiceWorkerVersion>& controller,
diff --git a/chromium/content/browser/service_worker/service_worker_context_core.cc b/chromium/content/browser/service_worker/service_worker_context_core.cc
index f6aa2123468..1bf5d3e11ba 100644
--- a/chromium/content/browser/service_worker/service_worker_context_core.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_core.cc
@@ -4,6 +4,8 @@
#include "content/browser/service_worker/service_worker_context_core.h"
+#include <limits>
+#include <set>
#include <utility>
#include "base/barrier_closure.h"
@@ -102,8 +104,9 @@ class ClearAllServiceWorkersHelper
void DidGetAllRegistrations(
const base::WeakPtr<ServiceWorkerContextCore>& context,
+ ServiceWorkerStatusCode status,
const std::vector<ServiceWorkerRegistrationInfo>& registrations) {
- if (!context)
+ if (!context || status != SERVICE_WORKER_OK)
return;
// Make a copy of live versions map because StopWorker() removes the version
// from it when we were starting up and don't have a process yet.
@@ -217,6 +220,7 @@ ServiceWorkerContextCore::ServiceWorkerContextCore(
: wrapper_(wrapper),
providers_(new ProcessToProviderMap),
provider_by_uuid_(new ProviderByClientUUIDMap),
+ force_update_on_page_load_(false),
next_handle_id_(0),
next_registration_handle_id_(0),
was_service_worker_registered_(false),
@@ -365,12 +369,6 @@ void ServiceWorkerContextCore::RegisterServiceWorker(
const RegistrationCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
was_service_worker_registered_ = true;
- if (storage()->IsDisabled()) {
- callback.Run(SERVICE_WORKER_ERROR_ABORT, std::string(),
- kInvalidServiceWorkerRegistrationId);
- return;
- }
-
job_coordinator_->Register(
pattern,
script_url,
@@ -385,9 +383,6 @@ void ServiceWorkerContextCore::UpdateServiceWorker(
ServiceWorkerRegistration* registration,
bool force_bypass_cache) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (storage()->IsDisabled())
- return;
-
job_coordinator_->Update(registration, force_bypass_cache);
}
@@ -398,44 +393,16 @@ void ServiceWorkerContextCore::UpdateServiceWorker(
ServiceWorkerProviderHost* provider_host,
const UpdateCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (storage()->IsDisabled()) {
- callback.Run(SERVICE_WORKER_ERROR_ABORT, std::string(),
- kInvalidServiceWorkerRegistrationId);
- return;
- }
-
job_coordinator_->Update(registration, force_bypass_cache,
skip_script_comparison, provider_host,
base::Bind(&ServiceWorkerContextCore::UpdateComplete,
AsWeakPtr(), callback));
}
-void ServiceWorkerContextCore::SetForceUpdateOnPageLoad(
- int64_t registration_id,
- bool force_update_on_page_load) {
- ServiceWorkerRegistration* registration =
- GetLiveRegistration(registration_id);
- if (!registration)
- return;
- registration->set_force_update_on_page_load(force_update_on_page_load);
-
- if (observer_list_.get()) {
- observer_list_->Notify(
- FROM_HERE,
- &ServiceWorkerContextObserver::OnForceUpdateOnPageLoadChanged,
- registration_id, force_update_on_page_load);
- }
-}
-
void ServiceWorkerContextCore::UnregisterServiceWorker(
const GURL& pattern,
const UnregistrationCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (storage()->IsDisabled()) {
- callback.Run(SERVICE_WORKER_ERROR_ABORT);
- return;
- }
-
job_coordinator_->Unregister(
pattern,
base::Bind(&ServiceWorkerContextCore::UnregistrationComplete,
@@ -448,12 +415,6 @@ void ServiceWorkerContextCore::UnregisterServiceWorkers(
const GURL& origin,
const UnregistrationCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- if (storage()->IsDisabled()) {
- // Not posting as new task to match implementations above.
- callback.Run(SERVICE_WORKER_ERROR_ABORT);
- return;
- }
-
storage()->GetAllRegistrationsInfos(base::Bind(
&ServiceWorkerContextCore::DidGetAllRegistrationsForUnregisterForOrigin,
AsWeakPtr(), callback, origin));
@@ -462,7 +423,12 @@ void ServiceWorkerContextCore::UnregisterServiceWorkers(
void ServiceWorkerContextCore::DidGetAllRegistrationsForUnregisterForOrigin(
const UnregistrationCallback& result,
const GURL& origin,
+ ServiceWorkerStatusCode status,
const std::vector<ServiceWorkerRegistrationInfo>& registrations) {
+ if (status != SERVICE_WORKER_OK) {
+ result.Run(status);
+ return;
+ }
std::set<GURL> scopes;
for (const auto& registration_info : registrations) {
if (origin == registration_info.pattern.GetOrigin()) {
@@ -718,6 +684,36 @@ void ServiceWorkerContextCore::CheckHasServiceWorker(
AsWeakPtr(), other_url, callback));
}
+void ServiceWorkerContextCore::UpdateVersionFailureCount(
+ int64_t version_id,
+ ServiceWorkerStatusCode status) {
+ // Don't count these, they aren't start worker failures.
+ if (status == SERVICE_WORKER_ERROR_DISALLOWED)
+ return;
+
+ auto it = failure_counts_.find(version_id);
+ if (status == SERVICE_WORKER_OK) {
+ if (it != failure_counts_.end())
+ failure_counts_.erase(it);
+ return;
+ }
+
+ if (it != failure_counts_.end()) {
+ DCHECK_GT(it->second, 0);
+ if (it->second < std::numeric_limits<int>::max())
+ ++it->second;
+ } else {
+ failure_counts_[version_id] = 1;
+ }
+}
+
+int ServiceWorkerContextCore::GetVersionFailureCount(int64_t version_id) {
+ auto it = failure_counts_.find(version_id);
+ if (it == failure_counts_.end())
+ return 0;
+ return it->second;
+}
+
void ServiceWorkerContextCore::OnRunningStateChanged(
ServiceWorkerVersion* version) {
if (!observer_list_)
diff --git a/chromium/content/browser/service_worker/service_worker_context_core.h b/chromium/content/browser/service_worker/service_worker_context_core.h
index f9448864207..2551336bd45 100644
--- a/chromium/content/browser/service_worker/service_worker_context_core.h
+++ b/chromium/content/browser/service_worker/service_worker_context_core.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include <map>
+#include <string>
#include <vector>
#include "base/callback.h"
@@ -206,13 +207,15 @@ class CONTENT_EXPORT ServiceWorkerContextCore
ServiceWorkerProviderHost* provider_host,
const UpdateCallback& callback);
- // Used in DevTools to update the service worker registration without
- // consulting the browser cache while loading the controlled page. The loading
- // is delayed until the update completes and the new worker is activated. The
- // new worker skips the waiting state and immediately becomes active after
- // installed.
- void SetForceUpdateOnPageLoad(int64_t registration_id,
- bool force_update_on_page_load);
+ // Used in DevTools to update the service worker registrations without
+ // consulting the browser cache while loading the controlled page. The
+ // loading is delayed until the update completes and the new worker is
+ // activated. The new worker skips the waiting state and immediately
+ // becomes active after installed.
+ bool force_update_on_page_load() { return force_update_on_page_load_; }
+ void set_force_update_on_page_load(bool force_update_on_page_load) {
+ force_update_on_page_load_ = force_update_on_page_load;
+ }
// This class maintains collections of live instances, this class
// does not own these object or influence their lifetime.
@@ -276,6 +279,12 @@ class CONTENT_EXPORT ServiceWorkerContextCore
const GURL& other_url,
const ServiceWorkerContext::CheckHasServiceWorkerCallback callback);
+ void UpdateVersionFailureCount(int64_t version_id,
+ ServiceWorkerStatusCode status);
+ // Returns the count of consecutive start worker failures for the given
+ // version. The count resets to zero when the worker successfully starts.
+ int GetVersionFailureCount(int64_t version_id);
+
base::WeakPtr<ServiceWorkerContextCore> AsWeakPtr() {
return weak_factory_.GetWeakPtr();
}
@@ -307,6 +316,7 @@ class CONTENT_EXPORT ServiceWorkerContextCore
void DidGetAllRegistrationsForUnregisterForOrigin(
const UnregistrationCallback& result,
const GURL& origin,
+ ServiceWorkerStatusCode status,
const std::vector<ServiceWorkerRegistrationInfo>& registrations);
void DidFindRegistrationForCheckHasServiceWorker(
@@ -330,12 +340,14 @@ class CONTENT_EXPORT ServiceWorkerContextCore
std::map<int64_t, ServiceWorkerRegistration*> live_registrations_;
std::map<int64_t, ServiceWorkerVersion*> live_versions_;
std::map<int64_t, scoped_refptr<ServiceWorkerVersion>> protected_versions_;
+ std::map<int64_t /* version_id */, int /* count */> failure_counts_;
// PlzNavigate
// Map of ServiceWorkerNavigationHandleCores used for navigation requests.
std::map<int, ServiceWorkerNavigationHandleCore*>
navigation_handle_cores_map_;
+ bool force_update_on_page_load_;
int next_handle_id_;
int next_registration_handle_id_;
// Set in RegisterServiceWorker(), cleared in ClearAllServiceWorkersForTest().
diff --git a/chromium/content/browser/service_worker/service_worker_context_observer.h b/chromium/content/browser/service_worker/service_worker_context_observer.h
index 86c238546b8..b643153f951 100644
--- a/chromium/content/browser/service_worker/service_worker_context_observer.h
+++ b/chromium/content/browser/service_worker/service_worker_context_observer.h
@@ -80,8 +80,6 @@ class ServiceWorkerContextObserver {
const GURL& pattern) {}
virtual void OnRegistrationDeleted(int64_t registration_id,
const GURL& pattern) {}
- virtual void OnForceUpdateOnPageLoadChanged(int64_t registration_id,
- bool force_update_on_page_load) {}
// Notified when the storage corruption recovery is completed and all stored
// data is wiped out.
diff --git a/chromium/content/browser/service_worker/service_worker_context_request_handler.cc b/chromium/content/browser/service_worker/service_worker_context_request_handler.cc
index 8b76146de80..c354eae6cd3 100644
--- a/chromium/content/browser/service_worker/service_worker_context_request_handler.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_request_handler.cc
@@ -83,6 +83,8 @@ net::URLRequestJob* ServiceWorkerContextRequestHandler::MaybeCreateJob(
incumbent_resource_id =
stored_version->script_cache_map()->LookupResourceId(request->url());
}
+ if (resource_type_ == RESOURCE_TYPE_SERVICE_WORKER)
+ version_->embedded_worker()->OnURLJobCreatedForMainScript();
return new ServiceWorkerWriteToCacheJob(
request, network_delegate, resource_type_, context_, version_.get(),
extra_load_flags, resource_id, incumbent_resource_id);
@@ -90,6 +92,8 @@ net::URLRequestJob* ServiceWorkerContextRequestHandler::MaybeCreateJob(
int64_t resource_id = kInvalidServiceWorkerResourceId;
if (ShouldReadFromScriptCache(request->url(), &resource_id)) {
+ if (resource_type_ == RESOURCE_TYPE_SERVICE_WORKER)
+ version_->embedded_worker()->OnURLJobCreatedForMainScript();
return new ServiceWorkerReadFromCacheJob(request, network_delegate,
resource_type_, context_, version_,
resource_id);
diff --git a/chromium/content/browser/service_worker/service_worker_context_request_handler_unittest.cc b/chromium/content/browser/service_worker/service_worker_context_request_handler_unittest.cc
index 94bc88e612b..260fd9d21db 100644
--- a/chromium/content/browser/service_worker/service_worker_context_request_handler_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_request_handler_unittest.cc
@@ -17,6 +17,7 @@
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_write_to_cache_job.h"
#include "content/common/service_worker/service_worker_utils.h"
+#include "content/public/browser/resource_request_info.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_request_context.h"
@@ -160,4 +161,30 @@ TEST_F(ServiceWorkerContextRequestHandlerTest, UpdateForceBypassCache) {
EXPECT_TRUE(sw_job->net_request_->load_flags() & net::LOAD_BYPASS_CACHE);
}
+TEST_F(ServiceWorkerContextRequestHandlerTest,
+ ServiceWorkerDataRequestAnnotation) {
+ version_->SetStatus(ServiceWorkerVersion::NEW);
+ provider_host_->running_hosted_version_ = version_;
+
+ // Conduct a resource fetch for the main script.
+ const GURL kScriptUrl("http://host/script.js");
+ scoped_ptr<net::URLRequest> request = url_request_context_.CreateRequest(
+ kScriptUrl, net::DEFAULT_PRIORITY, &url_request_delegate_);
+ scoped_ptr<ServiceWorkerContextRequestHandler> handler(
+ new ServiceWorkerContextRequestHandler(
+ context()->AsWeakPtr(), provider_host_,
+ base::WeakPtr<storage::BlobStorageContext>(),
+ RESOURCE_TYPE_SERVICE_WORKER));
+ scoped_ptr<net::URLRequestJob> job(
+ handler->MaybeCreateJob(request.get(), nullptr, nullptr));
+ ASSERT_TRUE(job.get());
+ ServiceWorkerWriteToCacheJob* sw_job =
+ static_cast<ServiceWorkerWriteToCacheJob*>(job.get());
+
+ // Verify that the request is properly annotated as originating from a
+ // Service Worker.
+ EXPECT_TRUE(ResourceRequestInfo::OriginatedFromServiceWorker(
+ sw_job->net_request_.get()));
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_context_watcher.cc b/chromium/content/browser/service_worker/service_worker_context_watcher.cc
index d28f8bf6f96..55ed1ec7f8c 100644
--- a/chromium/content/browser/service_worker/service_worker_context_watcher.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_watcher.cc
@@ -61,6 +61,7 @@ void ServiceWorkerContextWatcher::GetStoredRegistrationsOnIOThread() {
}
void ServiceWorkerContextWatcher::OnStoredRegistrationsOnIOThread(
+ ServiceWorkerStatusCode status,
const std::vector<ServiceWorkerRegistrationInfo>& stored_registrations) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
context_->AddObserver(this);
@@ -280,17 +281,4 @@ void ServiceWorkerContextWatcher::OnRegistrationDeleted(int64_t registration_id,
ServiceWorkerRegistrationInfo::IS_DELETED);
}
-void ServiceWorkerContextWatcher::OnForceUpdateOnPageLoadChanged(
- int64_t registration_id,
- bool force_update_on_page_load) {
- ServiceWorkerRegistration* registration =
- context_->GetLiveRegistration(registration_id);
- if (!registration)
- return;
- std::vector<ServiceWorkerRegistrationInfo> registrations;
- registrations.push_back(registration->GetInfo());
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(registration_callback_, registrations));
-}
-
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_context_watcher.h b/chromium/content/browser/service_worker/service_worker_context_watcher.h
index 506418bacc1..0ba5a53f8ef 100644
--- a/chromium/content/browser/service_worker/service_worker_context_watcher.h
+++ b/chromium/content/browser/service_worker/service_worker_context_watcher.h
@@ -47,6 +47,7 @@ class ServiceWorkerContextWatcher
void GetStoredRegistrationsOnIOThread();
void OnStoredRegistrationsOnIOThread(
+ ServiceWorkerStatusCode status,
const std::vector<ServiceWorkerRegistrationInfo>& stored_registrations);
void StopOnIOThread();
@@ -98,8 +99,6 @@ class ServiceWorkerContextWatcher
const GURL& pattern) override;
void OnRegistrationDeleted(int64_t registration_id,
const GURL& pattern) override;
- void OnForceUpdateOnPageLoadChanged(int64_t registration_id,
- bool force_update_on_page_load) override;
base::ScopedPtrHashMap<int64_t, scoped_ptr<ServiceWorkerVersionInfo>>
version_info_map_;
diff --git a/chromium/content/browser/service_worker/service_worker_context_wrapper.cc b/chromium/content/browser/service_worker/service_worker_context_wrapper.cc
index cfe5d87e8f0..d513a6931db 100644
--- a/chromium/content/browser/service_worker/service_worker_context_wrapper.cc
+++ b/chromium/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -29,7 +29,7 @@
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
-#include "net/base/net_util.h"
+#include "net/base/url_util.h"
#include "storage/browser/quota/quota_manager_proxy.h"
#include "storage/browser/quota/special_storage_policy.h"
@@ -62,6 +62,7 @@ void StartActiveWorkerOnIO(
// it from being deleted while starting the worker. If the refcount of
// |registration| is 1, it will be deleted after WorkerStarted is called.
registration->active_version()->StartWorker(
+ ServiceWorkerMetrics::EventType::UNKNOWN,
base::Bind(WorkerStarted, callback));
return;
}
@@ -101,6 +102,8 @@ ServiceWorkerContextWrapper::ServiceWorkerContextWrapper(
}
ServiceWorkerContextWrapper::~ServiceWorkerContextWrapper() {
+ DCHECK(!resource_context_);
+ DCHECK(!request_context_getter_);
}
void ServiceWorkerContextWrapper::Init(
@@ -130,6 +133,28 @@ void ServiceWorkerContextWrapper::Shutdown() {
base::Bind(&ServiceWorkerContextWrapper::ShutdownOnIO, this));
}
+void ServiceWorkerContextWrapper::InitializeResourceContext(
+ ResourceContext* resource_context,
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ resource_context_ = resource_context;
+ request_context_getter_ = request_context_getter;
+ // Can be null in tests.
+ if (request_context_getter_)
+ request_context_getter_->AddObserver(this);
+}
+
+void ServiceWorkerContextWrapper::OnContextShuttingDown() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ // OnContextShuttingDown is called when the ProfileIOData (ResourceContext) is
+ // shutting down, so call ShutdownOnIO() to clear resource_context_.
+ // This doesn't seem to be called when using content_shell, so we still must
+ // also call ShutdownOnIO() in Shutdown(), which is called when the storage
+ // partition is destroyed.
+ ShutdownOnIO();
+}
+
void ServiceWorkerContextWrapper::DeleteAndStartOver() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!context_core_) {
@@ -158,12 +183,6 @@ ResourceContext* ServiceWorkerContextWrapper::resource_context() {
return resource_context_;
}
-void ServiceWorkerContextWrapper::set_resource_context(
- ResourceContext* resource_context) {
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
- resource_context_ = resource_context;
-}
-
static void FinishRegistrationOnIO(
const ServiceWorkerContext::ResultCallback& continuation,
ServiceWorkerStatusCode status,
@@ -192,10 +211,8 @@ void ServiceWorkerContextWrapper::RegisterServiceWorker(
return;
}
if (!context_core_) {
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(continuation, false));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(continuation, false));
return;
}
context()->RegisterServiceWorker(
@@ -228,10 +245,8 @@ void ServiceWorkerContextWrapper::UnregisterServiceWorker(
return;
}
if (!context_core_) {
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(continuation, false));
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(continuation, false));
return;
}
@@ -277,19 +292,17 @@ void ServiceWorkerContextWrapper::StartServiceWorker(
}
void ServiceWorkerContextWrapper::SetForceUpdateOnPageLoad(
- int64_t registration_id,
bool force_update_on_page_load) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&ServiceWorkerContextWrapper::SetForceUpdateOnPageLoad, this,
- registration_id, force_update_on_page_load));
+ force_update_on_page_load));
return;
}
if (!context_core_)
return;
- context_core_->SetForceUpdateOnPageLoad(registration_id,
- force_update_on_page_load);
+ context_core_->set_force_update_on_page_load(force_update_on_page_load);
}
void ServiceWorkerContextWrapper::GetAllOriginsInfo(
@@ -309,6 +322,7 @@ void ServiceWorkerContextWrapper::GetAllOriginsInfo(
void ServiceWorkerContextWrapper::DidGetAllRegistrationsForGetAllOrigins(
const GetUsageInfoCallback& callback,
+ ServiceWorkerStatusCode status,
const std::vector<ServiceWorkerRegistrationInfo>& registrations) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
std::vector<ServiceWorkerUsageInfo> usage_infos;
@@ -574,7 +588,8 @@ void ServiceWorkerContextWrapper::GetAllRegistrations(
const GetRegistrationsInfosCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (!context_core_) {
- RunSoon(base::Bind(callback, std::vector<ServiceWorkerRegistrationInfo>()));
+ RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_ABORT,
+ std::vector<ServiceWorkerRegistrationInfo>()));
return;
}
context_core_->storage()->GetAllRegistrationsInfos(callback);
@@ -657,15 +672,11 @@ void ServiceWorkerContextWrapper::InitInternal(
storage::SpecialStoragePolicy* special_storage_policy) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(&ServiceWorkerContextWrapper::InitInternal,
- this,
- user_data_directory,
- base::Passed(&database_task_manager),
- disk_cache_thread,
- make_scoped_refptr(quota_manager_proxy),
- make_scoped_refptr(special_storage_policy)));
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&ServiceWorkerContextWrapper::InitInternal, this,
+ user_data_directory, base::Passed(&database_task_manager),
+ disk_cache_thread, base::RetainedRef(quota_manager_proxy),
+ base::RetainedRef(special_storage_policy)));
return;
}
// TODO(pkasting): Remove ScopedTracker below once crbug.com/477117 is fixed.
@@ -683,6 +694,10 @@ void ServiceWorkerContextWrapper::InitInternal(
void ServiceWorkerContextWrapper::ShutdownOnIO() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ // Can be null in tests.
+ if (request_context_getter_)
+ request_context_getter_->RemoveObserver(this);
+ request_context_getter_ = nullptr;
resource_context_ = nullptr;
context_core_.reset();
}
diff --git a/chromium/content/browser/service_worker/service_worker_context_wrapper.h b/chromium/content/browser/service_worker/service_worker_context_wrapper.h
index a81e8889265..4009d3ce2aa 100644
--- a/chromium/content/browser/service_worker/service_worker_context_wrapper.h
+++ b/chromium/content/browser/service_worker/service_worker_context_wrapper.h
@@ -7,6 +7,7 @@
#include <stdint.h>
+#include <string>
#include <vector>
#include "base/files/file_path.h"
@@ -16,6 +17,7 @@
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/common/content_export.h"
#include "content/public/browser/service_worker_context.h"
+#include "net/url_request/url_request_context_getter_observer.h"
namespace base {
class FilePath;
@@ -42,6 +44,7 @@ class StoragePartitionImpl;
// is what is used internally in the service worker lib.
class CONTENT_EXPORT ServiceWorkerContextWrapper
: NON_EXPORTED_BASE(public ServiceWorkerContext),
+ public net::URLRequestContextGetterObserver,
public base::RefCountedThreadSafe<ServiceWorkerContextWrapper> {
public:
using StatusCallback = base::Callback<void(ServiceWorkerStatusCode)>;
@@ -63,6 +66,14 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
storage::SpecialStoragePolicy* special_storage_policy);
void Shutdown();
+ // Must be called on the IO thread.
+ void InitializeResourceContext(
+ ResourceContext* resource_context,
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter);
+
+ // For net::URLRequestContextGetterObserver
+ void OnContextShuttingDown() override;
+
// Deletes all files on disk and restarts the system asynchronously. This
// leaves the system in a disabled state until it's done. This should be
// called on the IO thread.
@@ -79,8 +90,6 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
// shutdown.
ResourceContext* resource_context();
- void set_resource_context(ResourceContext* resource_context);
-
// The process manager can be used on either UI or IO.
ServiceWorkerProcessManager* process_manager() {
return process_manager_.get();
@@ -102,11 +111,13 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
void StopAllServiceWorkersForOrigin(const GURL& origin) override;
void ClearAllServiceWorkersForTest(const base::Closure& callback) override;
+ // These methods must only be called from the IO thread.
ServiceWorkerRegistration* GetLiveRegistration(int64_t registration_id);
ServiceWorkerVersion* GetLiveVersion(int64_t version_id);
std::vector<ServiceWorkerRegistrationInfo> GetAllLiveRegistrationInfo();
std::vector<ServiceWorkerVersionInfo> GetAllLiveVersionInfo();
+ // Must be called from the IO thread.
void HasMainFrameProviderHost(const GURL& origin,
const BoolCallback& callback) const;
@@ -119,6 +130,8 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
// - If the registration does not have the active version but has the waiting
// version, activates the waiting version and runs |callback| when it is
// activated.
+ //
+ // Must be called from the IO thread.
void FindReadyRegistrationForDocument(
const GURL& document_url,
const FindRegistrationCallback& callback);
@@ -132,10 +145,13 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
// - If the registration does not have the active version but has the waiting
// version, activates the waiting version and runs |callback| when it is
// activated.
+ //
+ // Must be called from the IO thread.
void FindReadyRegistrationForId(int64_t registration_id,
const GURL& origin,
const FindRegistrationCallback& callback);
+ // All these methods must be called from the IO thread.
void GetAllRegistrations(const GetRegistrationsInfosCallback& callback);
void GetRegistrationUserData(int64_t registration_id,
const std::string& key,
@@ -152,15 +168,19 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
const std::string& key,
const GetUserDataForAllRegistrationsCallback& callback);
+ // This function can be called from any thread, but the callback will always
+ // be called on the UI thread.
void StartServiceWorker(const GURL& pattern, const StatusCallback& callback);
+
+ // These methods can be called from any thread.
void UpdateRegistration(const GURL& pattern);
- void SetForceUpdateOnPageLoad(int64_t registration_id,
- bool force_update_on_page_load);
+ void SetForceUpdateOnPageLoad(bool force_update_on_page_load);
void AddObserver(ServiceWorkerContextObserver* observer);
void RemoveObserver(ServiceWorkerContextObserver* observer);
bool is_incognito() const { return is_incognito_; }
+ // Must be called from the IO thread.
bool OriginHasForeignFetchRegistrations(const GURL& origin);
private:
@@ -198,6 +218,7 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
void DidGetAllRegistrationsForGetAllOrigins(
const GetUsageInfoCallback& callback,
+ ServiceWorkerStatusCode status,
const std::vector<ServiceWorkerRegistrationInfo>& registrations);
void DidCheckHasServiceWorker(const CheckHasServiceWorkerCallback& callback,
@@ -215,7 +236,7 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
const scoped_refptr<base::ObserverListThreadSafe<
ServiceWorkerContextObserver>> observer_list_;
const scoped_ptr<ServiceWorkerProcessManager> process_manager_;
- // Cleared in Shutdown():
+ // Cleared in ShutdownOnIO():
scoped_ptr<ServiceWorkerContextCore> context_core_;
// Initialized in Init(); true if the user data directory is empty.
@@ -227,6 +248,8 @@ class CONTENT_EXPORT ServiceWorkerContextWrapper
// The ResourceContext associated with this context.
ResourceContext* resource_context_;
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
+
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContextWrapper);
};
diff --git a/chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc b/chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc
index 42e72fe1da8..88cc1b9191f 100644
--- a/chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc
+++ b/chromium/content/browser/service_worker/service_worker_controllee_request_handler.cc
@@ -20,7 +20,7 @@
#include "content/public/common/content_client.h"
#include "content/public/common/resource_response_info.h"
#include "net/base/load_flags.h"
-#include "net/base/net_util.h"
+#include "net/base/url_util.h"
#include "net/url_request/url_request.h"
namespace content {
@@ -103,8 +103,8 @@ net::URLRequestJob* ServiceWorkerControlleeRequestHandler::MaybeCreateJob(
scoped_ptr<ServiceWorkerURLRequestJob> job(new ServiceWorkerURLRequestJob(
request, network_delegate, provider_host_->client_uuid(),
blob_storage_context_, resource_context, request_mode_, credentials_mode_,
- redirect_mode_, is_main_resource_load_, request_context_type_,
- frame_type_, body_, this));
+ redirect_mode_, resource_type_, request_context_type_, frame_type_, body_,
+ ServiceWorkerFetchType::FETCH, this));
job_ = job->GetWeakPtr();
resource_context_ = resource_context;
@@ -143,6 +143,8 @@ void ServiceWorkerControlleeRequestHandler::GetExtraResponseInfo(
response_type_via_service_worker_;
response_info->service_worker_start_time = service_worker_start_time_;
response_info->service_worker_ready_time = service_worker_ready_time_;
+ response_info->is_in_cache_storage = response_is_in_cache_storage_;
+ response_info->cache_storage_cache_name = response_cache_storage_cache_name_;
}
void ServiceWorkerControlleeRequestHandler::PrepareForMainResource(
@@ -180,7 +182,7 @@ ServiceWorkerControlleeRequestHandler::DidLookupRegistrationForMainResource(
return;
const bool need_to_update = !force_update_started_ && registration &&
- registration->force_update_on_page_load();
+ context_->force_update_on_page_load();
if (provider_host_ && !need_to_update)
provider_host_->SetAllowAssociation(true);
@@ -233,11 +235,9 @@ ServiceWorkerControlleeRequestHandler::DidLookupRegistrationForMainResource(
if (active_version.get() &&
active_version->status() == ServiceWorkerVersion::ACTIVATING) {
provider_host_->SetAllowAssociation(false);
- registration->active_version()->RegisterStatusChangeCallback(
- base::Bind(&self::OnVersionStatusChanged,
- weak_factory_.GetWeakPtr(),
- registration,
- active_version));
+ registration->active_version()->RegisterStatusChangeCallback(base::Bind(
+ &self::OnVersionStatusChanged, weak_factory_.GetWeakPtr(),
+ base::RetainedRef(registration), base::RetainedRef(active_version)));
TRACE_EVENT_ASYNC_END2(
"ServiceWorker",
"ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
@@ -389,11 +389,15 @@ void ServiceWorkerControlleeRequestHandler::OnStartCompleted(
const GURL& original_url_via_service_worker,
blink::WebServiceWorkerResponseType response_type_via_service_worker,
base::TimeTicks service_worker_start_time,
- base::TimeTicks service_worker_ready_time) {
+ base::TimeTicks service_worker_ready_time,
+ bool response_is_in_cache_storage,
+ const std::string& response_cache_storage_cache_name) {
was_fetched_via_service_worker_ = was_fetched_via_service_worker;
was_fallback_required_ = was_fallback_required;
original_url_via_service_worker_ = original_url_via_service_worker;
response_type_via_service_worker_ = response_type_via_service_worker;
+ response_is_in_cache_storage_ = response_is_in_cache_storage;
+ response_cache_storage_cache_name_ = response_cache_storage_cache_name;
// Update times, if not already set by a previous Job.
if (service_worker_start_time_.is_null()) {
@@ -433,11 +437,6 @@ void ServiceWorkerControlleeRequestHandler::MainResourceLoadFailed() {
provider_host_->NotifyControllerLost();
}
-GURL ServiceWorkerControlleeRequestHandler::GetRequestingOrigin() {
- DCHECK(provider_host_);
- return provider_host_->document_url().GetOrigin();
-}
-
void ServiceWorkerControlleeRequestHandler::ClearJob() {
job_.reset();
was_fetched_via_service_worker_ = false;
@@ -445,6 +444,8 @@ void ServiceWorkerControlleeRequestHandler::ClearJob() {
original_url_via_service_worker_ = GURL();
response_type_via_service_worker_ =
blink::WebServiceWorkerResponseTypeDefault;
+ response_is_in_cache_storage_ = false;
+ response_cache_storage_cache_name_ = std::string();
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_controllee_request_handler.h b/chromium/content/browser/service_worker/service_worker_controllee_request_handler.h
index 1526385a460..736f1b5ea5c 100644
--- a/chromium/content/browser/service_worker/service_worker_controllee_request_handler.h
+++ b/chromium/content/browser/service_worker/service_worker_controllee_request_handler.h
@@ -100,14 +100,15 @@ class CONTENT_EXPORT ServiceWorkerControlleeRequestHandler
const GURL& original_url_via_service_worker,
blink::WebServiceWorkerResponseType response_type_via_service_worker,
base::TimeTicks worker_start_time,
- base::TimeTicks service_worker_ready_time) override;
+ base::TimeTicks service_worker_ready_time,
+ bool response_is_in_cache_storage,
+ const std::string& response_cache_storage_cache_name) override;
ServiceWorkerVersion* GetServiceWorkerVersion(
ServiceWorkerMetrics::URLRequestJobResult* result) override;
bool RequestStillValid(
ServiceWorkerMetrics::URLRequestJobResult* result) override;
void MainResourceLoadFailed() override;
- GURL GetRequestingOrigin() override;
// Sets |job_| to nullptr, and clears all extra response info associated with
// that job, except for timing information.
@@ -137,6 +138,8 @@ class CONTENT_EXPORT ServiceWorkerControlleeRequestHandler
blink::WebServiceWorkerResponseType response_type_via_service_worker_;
base::TimeTicks service_worker_start_time_;
base::TimeTicks service_worker_ready_time_;
+ bool response_is_in_cache_storage_ = false;
+ std::string response_cache_storage_cache_name_;
base::WeakPtrFactory<ServiceWorkerControlleeRequestHandler> weak_factory_;
diff --git a/chromium/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc b/chromium/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
index bf79f74dea1..dd522e0e7d0 100644
--- a/chromium/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
@@ -38,13 +38,32 @@ int kMockProviderId = 1;
}
+class FailureHelper : public EmbeddedWorkerTestHelper {
+ public:
+ FailureHelper() : EmbeddedWorkerTestHelper(base::FilePath()) {}
+ ~FailureHelper() override {}
+
+ protected:
+ void OnStartWorker(int embedded_worker_id,
+ int64_t service_worker_version_id,
+ const GURL& scope,
+ const GURL& script_url,
+ bool pause_after_download) override {
+ SimulateWorkerStopped(embedded_worker_id);
+ }
+};
+
class ServiceWorkerControlleeRequestHandlerTest : public testing::Test {
public:
ServiceWorkerControlleeRequestHandlerTest()
: browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
void SetUp() override {
- helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
+ SetUpWithHelper(new EmbeddedWorkerTestHelper(base::FilePath()));
+ }
+
+ void SetUpWithHelper(EmbeddedWorkerTestHelper* helper) {
+ helper_.reset(helper);
// A new unstored registration/version.
scope_ = GURL("http://host/scope/");
diff --git a/chromium/content/browser/service_worker/service_worker_database.cc b/chromium/content/browser/service_worker/service_worker_database.cc
index c4c3a8b952b..5254e87cd39 100644
--- a/chromium/content/browser/service_worker/service_worker_database.cc
+++ b/chromium/content/browser/service_worker/service_worker_database.cc
@@ -25,6 +25,7 @@
#include "third_party/leveldatabase/src/include/leveldb/db.h"
#include "third_party/leveldatabase/src/include/leveldb/env.h"
#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
+#include "url/origin.h"
// LevelDB database schema
// =======================
@@ -283,6 +284,9 @@ ServiceWorkerDatabase::RegistrationData::RegistrationData()
resources_total_size_bytes(0) {
}
+ServiceWorkerDatabase::RegistrationData::RegistrationData(
+ const RegistrationData& other) = default;
+
ServiceWorkerDatabase::RegistrationData::~RegistrationData() {
}
@@ -1193,6 +1197,15 @@ ServiceWorkerDatabase::Status ServiceWorkerDatabase::ParseRegistrationData(
}
out->foreign_fetch_scopes.push_back(sub_scope_url);
}
+ for (int i = 0; i < data.foreign_fetch_origin_size(); ++i) {
+ url::Origin parsed_origin(GURL(data.foreign_fetch_origin(i)));
+ if (parsed_origin.unique()) {
+ DLOG(ERROR) << "Foreign fetch origin '" << data.foreign_fetch_origin(i)
+ << "' is not valid.";
+ return ServiceWorkerDatabase::STATUS_ERROR_CORRUPTED;
+ }
+ out->foreign_fetch_origins.push_back(parsed_origin);
+ }
return ServiceWorkerDatabase::STATUS_OK;
}
@@ -1224,6 +1237,8 @@ void ServiceWorkerDatabase::WriteRegistrationDataInBatch(
<< "'.";
data.add_foreign_fetch_scope(url.spec());
}
+ for (const url::Origin& origin : registration.foreign_fetch_origins)
+ data.add_foreign_fetch_origin(origin.Serialize());
std::string value;
bool success = data.SerializeToString(&value);
diff --git a/chromium/content/browser/service_worker/service_worker_database.h b/chromium/content/browser/service_worker/service_worker_database.h
index 191ef4d7d56..a32e60afbad 100644
--- a/chromium/content/browser/service_worker/service_worker_database.h
+++ b/chromium/content/browser/service_worker/service_worker_database.h
@@ -21,6 +21,7 @@
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_status_code.h"
#include "url/gurl.h"
+#include "url/origin.h"
namespace leveldb {
class DB;
@@ -68,11 +69,13 @@ class CONTENT_EXPORT ServiceWorkerDatabase {
bool has_fetch_handler;
base::Time last_update_check;
std::vector<GURL> foreign_fetch_scopes;
+ std::vector<url::Origin> foreign_fetch_origins;
// Not populated until ServiceWorkerStorage::StoreRegistration is called.
int64_t resources_total_size_bytes;
RegistrationData();
+ RegistrationData(const RegistrationData& other);
~RegistrationData();
};
diff --git a/chromium/content/browser/service_worker/service_worker_database.proto b/chromium/content/browser/service_worker/service_worker_database.proto
index 5cce5a78bdc..e85f2a7c830 100644
--- a/chromium/content/browser/service_worker/service_worker_database.proto
+++ b/chromium/content/browser/service_worker/service_worker_database.proto
@@ -27,6 +27,7 @@ message ServiceWorkerRegistrationData {
optional uint64 resources_total_size_bytes = 8;
repeated string foreign_fetch_scope = 9;
+ repeated string foreign_fetch_origin = 10;
}
message ServiceWorkerResourceRecord {
diff --git a/chromium/content/browser/service_worker/service_worker_database_task_manager.h b/chromium/content/browser/service_worker/service_worker_database_task_manager.h
index dbe9aa25190..f13472a5258 100644
--- a/chromium/content/browser/service_worker/service_worker_database_task_manager.h
+++ b/chromium/content/browser/service_worker/service_worker_database_task_manager.h
@@ -7,6 +7,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
namespace base {
diff --git a/chromium/content/browser/service_worker/service_worker_database_unittest.cc b/chromium/content/browser/service_worker/service_worker_database_unittest.cc
index 2b99bb4206f..9cdbae66638 100644
--- a/chromium/content/browser/service_worker/service_worker_database_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_database_unittest.cc
@@ -18,6 +18,7 @@
#include "content/common/service_worker/service_worker_types.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
+#include "url/origin.h"
namespace content {
@@ -70,6 +71,7 @@ void VerifyRegistrationData(const RegistrationData& expected,
EXPECT_EQ(expected.resources_total_size_bytes,
actual.resources_total_size_bytes);
EXPECT_EQ(expected.foreign_fetch_scopes, actual.foreign_fetch_scopes);
+ EXPECT_EQ(expected.foreign_fetch_origins, actual.foreign_fetch_origins);
}
void VerifyResourceRecords(const std::vector<Resource>& expected,
@@ -758,6 +760,8 @@ TEST(ServiceWorkerDatabaseTest, Registration_Overwrite) {
data.version_id = 200;
data.resources_total_size_bytes = 10 + 11;
data.foreign_fetch_scopes.push_back(URL(origin, "/foo"));
+ data.foreign_fetch_origins.push_back(
+ url::Origin(GURL("https://chromium.org")));
std::vector<Resource> resources1;
resources1.push_back(CreateResource(1, URL(origin, "/resource1"), 10));
@@ -787,6 +791,8 @@ TEST(ServiceWorkerDatabaseTest, Registration_Overwrite) {
updated_data.version_id = data.version_id + 1;
updated_data.resources_total_size_bytes = 12 + 13;
updated_data.foreign_fetch_scopes.clear();
+ updated_data.foreign_fetch_origins.push_back(
+ url::Origin(GURL("https://example.com")));
std::vector<Resource> resources2;
resources2.push_back(CreateResource(3, URL(origin, "/resource3"), 12));
resources2.push_back(CreateResource(4, URL(origin, "/resource4"), 13));
diff --git a/chromium/content/browser/service_worker/service_worker_disk_cache.cc b/chromium/content/browser/service_worker/service_worker_disk_cache.cc
index ef8f168f852..f398e61bd2e 100644
--- a/chromium/content/browser/service_worker/service_worker_disk_cache.cc
+++ b/chromium/content/browser/service_worker/service_worker_disk_cache.cc
@@ -11,17 +11,17 @@ ServiceWorkerDiskCache::ServiceWorkerDiskCache()
ServiceWorkerResponseReader::ServiceWorkerResponseReader(
int64_t resource_id,
- ServiceWorkerDiskCache* disk_cache)
+ const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache)
: AppCacheResponseReader(resource_id, 0, disk_cache) {}
ServiceWorkerResponseWriter::ServiceWorkerResponseWriter(
int64_t resource_id,
- ServiceWorkerDiskCache* disk_cache)
+ const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache)
: AppCacheResponseWriter(resource_id, 0, disk_cache) {}
ServiceWorkerResponseMetadataWriter::ServiceWorkerResponseMetadataWriter(
int64_t resource_id,
- ServiceWorkerDiskCache* disk_cache)
+ const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache)
: AppCacheResponseMetadataWriter(resource_id, 0, disk_cache) {}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_disk_cache.h b/chromium/content/browser/service_worker/service_worker_disk_cache.h
index 90f29bcb3f3..b5ce04cddc5 100644
--- a/chromium/content/browser/service_worker/service_worker_disk_cache.h
+++ b/chromium/content/browser/service_worker/service_worker_disk_cache.h
@@ -29,8 +29,10 @@ class CONTENT_EXPORT ServiceWorkerResponseReader
protected:
// Should only be constructed by the storage class.
friend class ServiceWorkerStorage;
- ServiceWorkerResponseReader(int64_t resource_id,
- ServiceWorkerDiskCache* disk_cache);
+
+ ServiceWorkerResponseReader(
+ int64_t resource_id,
+ const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache);
};
class CONTENT_EXPORT ServiceWorkerResponseWriter
@@ -38,8 +40,10 @@ class CONTENT_EXPORT ServiceWorkerResponseWriter
protected:
// Should only be constructed by the storage class.
friend class ServiceWorkerStorage;
- ServiceWorkerResponseWriter(int64_t resource_id,
- ServiceWorkerDiskCache* disk_cache);
+
+ ServiceWorkerResponseWriter(
+ int64_t resource_id,
+ const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache);
};
class CONTENT_EXPORT ServiceWorkerResponseMetadataWriter
@@ -47,8 +51,10 @@ class CONTENT_EXPORT ServiceWorkerResponseMetadataWriter
protected:
// Should only be constructed by the storage class.
friend class ServiceWorkerStorage;
- ServiceWorkerResponseMetadataWriter(int64_t resource_id,
- ServiceWorkerDiskCache* disk_cache);
+
+ ServiceWorkerResponseMetadataWriter(
+ int64_t resource_id,
+ const base::WeakPtr<AppCacheDiskCacheInterface>& disk_cache);
};
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc b/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
index f8d80e08730..d15732d41aa 100644
--- a/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -10,11 +10,13 @@
#include "base/macros.h"
#include "base/profiler/scoped_tracker.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/bad_message.h"
#include "content/browser/message_port_message_filter.h"
#include "content/browser/message_port_service.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
+#include "content/browser/service_worker/service_worker_client_utils.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_handle.h"
@@ -30,7 +32,6 @@
#include "content/public/common/content_client.h"
#include "content/public/common/origin_util.h"
#include "ipc/ipc_message_macros.h"
-#include "net/base/net_util.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerError.h"
#include "url/gurl.h"
@@ -52,21 +53,9 @@ const uint32_t kFilteredMessageClasses[] = {
ServiceWorkerMsgStart, EmbeddedWorkerMsgStart,
};
-bool AllOriginsMatch(const GURL& url_a, const GURL& url_b, const GURL& url_c) {
- return url_a.GetOrigin() == url_b.GetOrigin() &&
- url_a.GetOrigin() == url_c.GetOrigin();
-}
-
-bool CanRegisterServiceWorker(const GURL& document_url,
- const GURL& pattern,
- const GURL& script_url) {
- DCHECK(document_url.is_valid());
- DCHECK(pattern.is_valid());
- DCHECK(script_url.is_valid());
- return AllOriginsMatch(document_url, pattern, script_url) &&
- OriginCanAccessServiceWorkers(document_url) &&
- OriginCanAccessServiceWorkers(pattern) &&
- OriginCanAccessServiceWorkers(script_url);
+void RunSoon(const base::Closure& callback) {
+ if (!callback.is_null())
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
}
bool CanUnregisterServiceWorker(const GURL& document_url,
@@ -120,10 +109,9 @@ ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() {
void ServiceWorkerDispatcherHost::Init(
ServiceWorkerContextWrapper* context_wrapper) {
if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(&ServiceWorkerDispatcherHost::Init,
- this, make_scoped_refptr(context_wrapper)));
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&ServiceWorkerDispatcherHost::Init, this,
+ base::RetainedRef(context_wrapper)));
return;
}
@@ -183,6 +171,8 @@ bool ServiceWorkerDispatcherHost::OnMessageReceived(
OnProviderDestroyed)
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SetVersionId,
OnSetHostedVersionId)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DeprecatedPostMessageToWorker,
+ OnDeprecatedPostMessageToWorker)
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToWorker,
OnPostMessageToWorker)
IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerReadyForInspection,
@@ -261,7 +251,7 @@ ServiceWorkerHandle* ServiceWorkerDispatcherHost::FindServiceWorkerHandle(
return handle;
}
}
- return NULL;
+ return nullptr;
}
ServiceWorkerRegistrationHandle*
@@ -329,8 +319,8 @@ void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
return;
}
- if (!CanRegisterServiceWorker(
- provider_host->document_url(), pattern, script_url)) {
+ if (!ServiceWorkerUtils::CanRegisterServiceWorker(
+ provider_host->document_url(), pattern, script_url)) {
bad_message::ReceivedBadMessage(this, bad_message::SWDH_REGISTER_CANNOT);
return;
}
@@ -352,11 +342,9 @@ void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
return;
}
- TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
- "ServiceWorkerDispatcherHost::RegisterServiceWorker",
- request_id,
- "Pattern", pattern.spec(),
- "Script URL", script_url.spec());
+ TRACE_EVENT_ASYNC_BEGIN2(
+ "ServiceWorker", "ServiceWorkerDispatcherHost::RegisterServiceWorker",
+ request_id, "Scope", pattern.spec(), "Script URL", script_url.spec());
GetContext()->RegisterServiceWorker(
pattern,
script_url,
@@ -442,6 +430,9 @@ void ServiceWorkerDispatcherHost::OnUpdateServiceWorker(
return;
}
+ TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
+ "ServiceWorkerDispatcherHost::UpdateServiceWorker",
+ request_id, "Scope", registration->pattern().spec());
GetContext()->UpdateServiceWorker(
registration, false /* force_bypass_cache */,
false /* skip_script_comparison */, provider_host,
@@ -511,7 +502,7 @@ void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
TRACE_EVENT_ASYNC_BEGIN1(
"ServiceWorker", "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
- request_id, "Pattern", registration->pattern().spec());
+ request_id, "Scope", registration->pattern().spec());
GetContext()->UnregisterServiceWorker(
registration->pattern(),
base::Bind(&ServiceWorkerDispatcherHost::UnregistrationComplete, this,
@@ -523,11 +514,10 @@ void ServiceWorkerDispatcherHost::OnGetRegistration(
int request_id,
int provider_id,
const GURL& document_url) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
TRACE_EVENT0("ServiceWorker",
"ServiceWorkerDispatcherHost::OnGetRegistration");
- DCHECK_CURRENTLY_ON(BrowserThread::IO);
-
if (!GetContext()) {
Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
thread_id, request_id, blink::WebServiceWorkerError::ErrorTypeAbort,
@@ -581,17 +571,9 @@ void ServiceWorkerDispatcherHost::OnGetRegistration(
return;
}
- if (GetContext()->storage()->IsDisabled()) {
- SendGetRegistrationError(thread_id, request_id, SERVICE_WORKER_ERROR_ABORT);
- return;
- }
-
- TRACE_EVENT_ASYNC_BEGIN1(
- "ServiceWorker",
- "ServiceWorkerDispatcherHost::GetRegistration",
- request_id,
- "Document URL", document_url.spec());
-
+ TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker",
+ "ServiceWorkerDispatcherHost::GetRegistration",
+ request_id, "Document URL", document_url.spec());
GetContext()->storage()->FindRegistrationForDocument(
document_url,
base::Bind(&ServiceWorkerDispatcherHost::GetRegistrationComplete,
@@ -605,6 +587,8 @@ void ServiceWorkerDispatcherHost::OnGetRegistrations(int thread_id,
int request_id,
int provider_id) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerDispatcherHost::OnGetRegistrations");
if (!GetContext()) {
Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
@@ -654,16 +638,9 @@ void ServiceWorkerDispatcherHost::OnGetRegistrations(int thread_id,
return;
}
- if (GetContext()->storage()->IsDisabled()) {
- SendGetRegistrationsError(thread_id, request_id,
- SERVICE_WORKER_ERROR_ABORT);
- return;
- }
-
TRACE_EVENT_ASYNC_BEGIN0("ServiceWorker",
"ServiceWorkerDispatcherHost::GetRegistrations",
request_id);
-
GetContext()->storage()->GetRegistrationsForOrigin(
provider_host->document_url().GetOrigin(),
base::Bind(&ServiceWorkerDispatcherHost::GetRegistrationsComplete, this,
@@ -689,10 +666,8 @@ void ServiceWorkerDispatcherHost::OnGetRegistrationForReady(
return;
TRACE_EVENT_ASYNC_BEGIN0(
- "ServiceWorker",
- "ServiceWorkerDispatcherHost::GetRegistrationForReady",
+ "ServiceWorker", "ServiceWorkerDispatcherHost::GetRegistrationForReady",
request_id);
-
if (!provider_host->GetRegistrationForReady(base::Bind(
&ServiceWorkerDispatcherHost::GetRegistrationForReadyComplete,
this, thread_id, request_id, provider_host->AsWeakPtr()))) {
@@ -703,7 +678,9 @@ void ServiceWorkerDispatcherHost::OnGetRegistrationForReady(
void ServiceWorkerDispatcherHost::OnPostMessageToWorker(
int handle_id,
+ int provider_id,
const base::string16& message,
+ const url::Origin& source_origin,
const std::vector<TransferredMessagePort>& sent_message_ports) {
TRACE_EVENT0("ServiceWorker",
"ServiceWorkerDispatcherHost::OnPostMessageToWorker");
@@ -716,6 +693,71 @@ void ServiceWorkerDispatcherHost::OnPostMessageToWorker(
return;
}
+ ServiceWorkerProviderHost* sender_provider_host =
+ GetContext()->GetProviderHost(render_process_id_, provider_id);
+ if (!sender_provider_host) {
+ bad_message::ReceivedBadMessage(this, bad_message::SWDH_POST_MESSAGE);
+ return;
+ }
+
+ DispatchExtendableMessageEvent(
+ make_scoped_refptr(handle->version()), message, source_origin,
+ sent_message_ports, sender_provider_host,
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+}
+
+void ServiceWorkerDispatcherHost::DispatchExtendableMessageEvent(
+ scoped_refptr<ServiceWorkerVersion> worker,
+ const base::string16& message,
+ const url::Origin& source_origin,
+ const std::vector<TransferredMessagePort>& sent_message_ports,
+ ServiceWorkerProviderHost* sender_provider_host,
+ const StatusCallback& callback) {
+ for (const TransferredMessagePort& port : sent_message_ports)
+ MessagePortService::GetInstance()->HoldMessages(port.id);
+
+ switch (sender_provider_host->provider_type()) {
+ case SERVICE_WORKER_PROVIDER_FOR_WINDOW:
+ case SERVICE_WORKER_PROVIDER_FOR_WORKER:
+ case SERVICE_WORKER_PROVIDER_FOR_SHARED_WORKER:
+ service_worker_client_utils::GetClient(
+ sender_provider_host,
+ base::Bind(&ServiceWorkerDispatcherHost::
+ DispatchExtendableMessageEventInternal<
+ ServiceWorkerClientInfo>,
+ this, worker, message, source_origin, sent_message_ports,
+ callback));
+ break;
+ case SERVICE_WORKER_PROVIDER_FOR_CONTROLLER:
+ RunSoon(base::Bind(
+ &ServiceWorkerDispatcherHost::DispatchExtendableMessageEventInternal<
+ ServiceWorkerObjectInfo>,
+ this, worker, message, source_origin, sent_message_ports, callback,
+ sender_provider_host->GetOrCreateServiceWorkerHandle(
+ sender_provider_host->running_hosted_version())));
+ break;
+ case SERVICE_WORKER_PROVIDER_FOR_SANDBOXED_FRAME:
+ case SERVICE_WORKER_PROVIDER_UNKNOWN:
+ NOTREACHED() << sender_provider_host->provider_type();
+ break;
+ }
+}
+
+void ServiceWorkerDispatcherHost::OnDeprecatedPostMessageToWorker(
+ int handle_id,
+ const base::string16& message,
+ const std::vector<TransferredMessagePort>& sent_message_ports) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerDispatcherHost::OnDeprecatedPostMessageToWorker");
+ if (!GetContext())
+ return;
+
+ ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
+ if (!handle) {
+ bad_message::ReceivedBadMessage(this, bad_message::SWDH_POST_MESSAGE);
+ return;
+ }
+
handle->version()->DispatchMessageEvent(
message, sent_message_ports,
base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
@@ -748,11 +790,11 @@ void ServiceWorkerDispatcherHost::OnProviderCreated(
GetContext()->GetNavigationHandleCore(provider_id);
if (navigation_handle_core != nullptr)
provider_host = navigation_handle_core->RetrievePreCreatedHost();
- if (provider_host == nullptr) {
- bad_message::ReceivedBadMessage(
- this, bad_message::SWDH_PROVIDER_CREATED_NO_HOST);
+
+ // If no host is found, the navigation has been cancelled in the meantime.
+ // Just return as the navigation will be stopped in the renderer as well.
+ if (provider_host == nullptr)
return;
- }
DCHECK_EQ(SERVICE_WORKER_PROVIDER_FOR_WINDOW, provider_type);
provider_host->CompleteNavigationInitialized(render_process_id_, route_id,
this);
@@ -776,8 +818,15 @@ void ServiceWorkerDispatcherHost::OnProviderDestroyed(int provider_id) {
if (!GetContext())
return;
if (!GetContext()->GetProviderHost(render_process_id_, provider_id)) {
- bad_message::ReceivedBadMessage(
- this, bad_message::SWDH_PROVIDER_DESTROYED_NO_HOST);
+ // PlzNavigate: in some cancellation of navigation cases, it is possible
+ // for the pre-created hoist to have been destroyed before being claimed by
+ // the renderer. The provider is then destroyed in the renderer, and no
+ // matching host will be found.
+ if (!IsBrowserSideNavigationEnabled() ||
+ !ServiceWorkerUtils::IsBrowserAssignedProviderId(provider_id)) {
+ bad_message::ReceivedBadMessage(
+ this, bad_message::SWDH_PROVIDER_DESTROYED_NO_HOST);
+ }
return;
}
GetContext()->RemoveProviderHost(render_process_id_, provider_id);
@@ -799,12 +848,16 @@ void ServiceWorkerDispatcherHost::OnSetHostedVersionId(int provider_id,
if (!provider_host->IsContextAlive())
return;
+ // We might not be STARTING if the stop sequence was entered (STOPPING) or
+ // ended up being detached (STOPPED).
ServiceWorkerVersion* version = GetContext()->GetLiveVersion(version_id);
- if (!version || version->running_status() == ServiceWorkerVersion::STOPPING)
+ if (!version || version->running_status() != ServiceWorkerVersion::STARTING)
return;
- if (!provider_host->SetHostedVersionId(version_id))
+ if (!provider_host->SetHostedVersion(version)) {
bad_message::ReceivedBadMessage(this, bad_message::SWDH_SET_HOSTED_VERSION);
+ return;
+ }
// Retrieve the registration associated with |version|. The registration
// must be alive because the version keeps it during starting worker.
@@ -825,6 +878,96 @@ void ServiceWorkerDispatcherHost::OnSetHostedVersionId(int provider_id,
provider_id, info, attrs));
}
+template <typename SourceInfo>
+void ServiceWorkerDispatcherHost::DispatchExtendableMessageEventInternal(
+ scoped_refptr<ServiceWorkerVersion> worker,
+ const base::string16& message,
+ const url::Origin& source_origin,
+ const std::vector<TransferredMessagePort>& sent_message_ports,
+ const StatusCallback& callback,
+ const SourceInfo& source_info) {
+ if (!source_info.IsValid()) {
+ DidFailToDispatchExtendableMessageEvent<SourceInfo>(
+ sent_message_ports, source_info, callback, SERVICE_WORKER_ERROR_FAILED);
+ return;
+ }
+ worker->RunAfterStartWorker(
+ ServiceWorkerMetrics::EventType::MESSAGE,
+ base::Bind(&ServiceWorkerDispatcherHost::
+ DispatchExtendableMessageEventAfterStartWorker,
+ this, worker, message, source_origin, sent_message_ports,
+ ExtendableMessageEventSource(source_info), callback),
+ base::Bind(
+ &ServiceWorkerDispatcherHost::DidFailToDispatchExtendableMessageEvent<
+ SourceInfo>,
+ this, sent_message_ports, source_info, callback));
+}
+
+void ServiceWorkerDispatcherHost::
+ DispatchExtendableMessageEventAfterStartWorker(
+ scoped_refptr<ServiceWorkerVersion> worker,
+ const base::string16& message,
+ const url::Origin& source_origin,
+ const std::vector<TransferredMessagePort>& sent_message_ports,
+ const ExtendableMessageEventSource& source,
+ const StatusCallback& callback) {
+ int request_id =
+ worker->StartRequest(ServiceWorkerMetrics::EventType::MESSAGE, callback);
+
+ MessagePortMessageFilter* filter =
+ worker->embedded_worker()->message_port_message_filter();
+ std::vector<int> new_routing_ids;
+ filter->UpdateMessagePortsWithNewRoutes(sent_message_ports, &new_routing_ids);
+
+ ServiceWorkerMsg_ExtendableMessageEvent_Params params;
+ params.message = message;
+ params.source_origin = source_origin;
+ params.message_ports = sent_message_ports;
+ params.new_routing_ids = new_routing_ids;
+ params.source = source;
+
+ // Hide the client url if the client has a unique origin.
+ if (source_origin.unique()) {
+ if (params.source.client_info.IsValid())
+ params.source.client_info.url = GURL();
+ else
+ params.source.service_worker_info.url = GURL();
+ }
+
+ worker->DispatchSimpleEvent<
+ ServiceWorkerHostMsg_ExtendableMessageEventFinished>(
+ request_id, ServiceWorkerMsg_ExtendableMessageEvent(request_id, params));
+}
+
+template <typename SourceInfo>
+void ServiceWorkerDispatcherHost::DidFailToDispatchExtendableMessageEvent(
+ const std::vector<TransferredMessagePort>& sent_message_ports,
+ const SourceInfo& source_info,
+ const StatusCallback& callback,
+ ServiceWorkerStatusCode status) {
+ // Transfering the message ports failed, so destroy the ports.
+ for (const TransferredMessagePort& port : sent_message_ports)
+ MessagePortService::GetInstance()->ClosePort(port.id);
+ if (source_info.IsValid())
+ ReleaseSourceInfo(source_info);
+ callback.Run(status);
+}
+
+void ServiceWorkerDispatcherHost::ReleaseSourceInfo(
+ const ServiceWorkerClientInfo& source_info) {
+ // ServiceWorkerClientInfo is just a snapshot of the client. There is no need
+ // to do anything for it.
+}
+
+void ServiceWorkerDispatcherHost::ReleaseSourceInfo(
+ const ServiceWorkerObjectInfo& source_info) {
+ ServiceWorkerHandle* handle = handles_.Lookup(source_info.handle_id);
+ DCHECK(handle);
+ handle->DecrementRefCount();
+ if (handle->HasNoRefCount())
+ handles_.Remove(source_info.handle_id);
+}
+
ServiceWorkerRegistrationHandle*
ServiceWorkerDispatcherHost::FindRegistrationHandle(int provider_id,
int64_t registration_id) {
@@ -863,6 +1006,9 @@ void ServiceWorkerDispatcherHost::RegistrationComplete(
ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id) {
+ TRACE_EVENT_ASYNC_END2(
+ "ServiceWorker", "ServiceWorkerDispatcherHost::RegisterServiceWorker",
+ request_id, "Status", status, "Registration ID", registration_id);
if (!GetContext())
return;
@@ -872,7 +1018,13 @@ void ServiceWorkerDispatcherHost::RegistrationComplete(
return; // The provider has already been destroyed.
if (status != SERVICE_WORKER_OK) {
- SendRegistrationError(thread_id, request_id, status, status_message);
+ base::string16 error_message;
+ blink::WebServiceWorkerError::ErrorType error_type;
+ GetServiceWorkerRegistrationStatusResponse(status, status_message,
+ &error_type, &error_message);
+ Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
+ thread_id, request_id, error_type,
+ base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) + error_message));
return;
}
@@ -887,11 +1039,6 @@ void ServiceWorkerDispatcherHost::RegistrationComplete(
Send(new ServiceWorkerMsg_ServiceWorkerRegistered(
thread_id, request_id, info, attrs));
- TRACE_EVENT_ASYNC_END1("ServiceWorker",
- "ServiceWorkerDispatcherHost::RegisterServiceWorker",
- request_id,
- "Registration ID",
- registration_id);
}
void ServiceWorkerDispatcherHost::UpdateComplete(
@@ -901,6 +1048,9 @@ void ServiceWorkerDispatcherHost::UpdateComplete(
ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id) {
+ TRACE_EVENT_ASYNC_END2(
+ "ServiceWorker", "ServiceWorkerDispatcherHost::UpdateServiceWorker",
+ request_id, "Status", status, "Registration ID", registration_id);
if (!GetContext())
return;
@@ -910,7 +1060,13 @@ void ServiceWorkerDispatcherHost::UpdateComplete(
return; // The provider has already been destroyed.
if (status != SERVICE_WORKER_OK) {
- SendUpdateError(thread_id, request_id, status, status_message);
+ base::string16 error_message;
+ blink::WebServiceWorkerError::ErrorType error_type;
+ GetServiceWorkerRegistrationStatusResponse(status, status_message,
+ &error_type, &error_message);
+ Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
+ thread_id, request_id, error_type,
+ base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) + error_message));
return;
}
@@ -924,9 +1080,6 @@ void ServiceWorkerDispatcherHost::UpdateComplete(
registration, &info, &attrs);
Send(new ServiceWorkerMsg_ServiceWorkerUpdated(thread_id, request_id));
- TRACE_EVENT_ASYNC_END1("ServiceWorker",
- "ServiceWorkerDispatcherHost::UpdateServiceWorker",
- request_id, "Registration ID", registration_id);
}
void ServiceWorkerDispatcherHost::OnWorkerReadyForInspection(
@@ -1126,19 +1279,24 @@ void ServiceWorkerDispatcherHost::UnregistrationComplete(
int thread_id,
int request_id,
ServiceWorkerStatusCode status) {
+ TRACE_EVENT_ASYNC_END1("ServiceWorker",
+ "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
+ request_id, "Status", status);
if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
- SendUnregistrationError(thread_id, request_id, status);
+ base::string16 error_message;
+ blink::WebServiceWorkerError::ErrorType error_type;
+ GetServiceWorkerRegistrationStatusResponse(status, std::string(),
+ &error_type, &error_message);
+ Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
+ thread_id, request_id, error_type,
+ base::ASCIIToUTF16(kServiceWorkerUnregisterErrorPrefix) +
+ error_message));
return;
}
const bool is_success = (status == SERVICE_WORKER_OK);
Send(new ServiceWorkerMsg_ServiceWorkerUnregistered(thread_id,
request_id,
is_success));
- TRACE_EVENT_ASYNC_END1(
- "ServiceWorker",
- "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
- request_id,
- "Status", status);
}
void ServiceWorkerDispatcherHost::GetRegistrationComplete(
@@ -1147,13 +1305,10 @@ void ServiceWorkerDispatcherHost::GetRegistrationComplete(
int request_id,
ServiceWorkerStatusCode status,
const scoped_refptr<ServiceWorkerRegistration>& registration) {
- TRACE_EVENT_ASYNC_END1("ServiceWorker",
- "ServiceWorkerDispatcherHost::GetRegistration",
- request_id,
- "Registration ID",
- registration.get() ? registration->id()
- : kInvalidServiceWorkerRegistrationId);
-
+ TRACE_EVENT_ASYNC_END2(
+ "ServiceWorker", "ServiceWorkerDispatcherHost::GetRegistration",
+ request_id, "Status", status, "Registration ID",
+ registration ? registration->id() : kInvalidServiceWorkerRegistrationId);
if (!GetContext())
return;
@@ -1163,7 +1318,15 @@ void ServiceWorkerDispatcherHost::GetRegistrationComplete(
return; // The provider has already been destroyed.
if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
- SendGetRegistrationError(thread_id, request_id, status);
+ base::string16 error_message;
+ blink::WebServiceWorkerError::ErrorType error_type;
+ GetServiceWorkerRegistrationStatusResponse(status, std::string(),
+ &error_type, &error_message);
+ Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
+ thread_id, request_id, error_type,
+ base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
+ error_message));
+
return;
}
@@ -1185,11 +1348,12 @@ void ServiceWorkerDispatcherHost::GetRegistrationsComplete(
int thread_id,
int provider_id,
int request_id,
+ ServiceWorkerStatusCode status,
const std::vector<scoped_refptr<ServiceWorkerRegistration>>&
registrations) {
- TRACE_EVENT_ASYNC_END0("ServiceWorker",
+ TRACE_EVENT_ASYNC_END1("ServiceWorker",
"ServiceWorkerDispatcherHost::GetRegistrations",
- request_id);
+ request_id, "Status", status);
if (!GetContext())
return;
@@ -1198,6 +1362,18 @@ void ServiceWorkerDispatcherHost::GetRegistrationsComplete(
if (!provider_host)
return; // The provider has already been destroyed.
+ if (status != SERVICE_WORKER_OK) {
+ base::string16 error_message;
+ blink::WebServiceWorkerError::ErrorType error_type;
+ GetServiceWorkerRegistrationStatusResponse(status, std::string(),
+ &error_type, &error_message);
+ Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
+ thread_id, request_id, error_type,
+ base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
+ error_message));
+ return;
+ }
+
std::vector<ServiceWorkerRegistrationObjectInfo> object_infos;
std::vector<ServiceWorkerVersionAttributes> version_attrs;
@@ -1224,13 +1400,10 @@ void ServiceWorkerDispatcherHost::GetRegistrationForReadyComplete(
base::WeakPtr<ServiceWorkerProviderHost> provider_host,
ServiceWorkerRegistration* registration) {
DCHECK(registration);
- TRACE_EVENT_ASYNC_END1("ServiceWorker",
- "ServiceWorkerDispatcherHost::GetRegistrationForReady",
- request_id,
- "Registration ID",
- registration ? registration->id()
- : kInvalidServiceWorkerRegistrationId);
-
+ TRACE_EVENT_ASYNC_END1(
+ "ServiceWorker", "ServiceWorkerDispatcherHost::GetRegistrationForReady",
+ request_id, "Registration ID",
+ registration ? registration->id() : kInvalidServiceWorkerRegistrationId);
if (!GetContext())
return;
@@ -1242,75 +1415,6 @@ void ServiceWorkerDispatcherHost::GetRegistrationForReadyComplete(
thread_id, request_id, info, attrs));
}
-void ServiceWorkerDispatcherHost::SendRegistrationError(
- int thread_id,
- int request_id,
- ServiceWorkerStatusCode status,
- const std::string& status_message) {
- base::string16 error_message;
- blink::WebServiceWorkerError::ErrorType error_type;
- GetServiceWorkerRegistrationStatusResponse(status, status_message,
- &error_type, &error_message);
- Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
- thread_id, request_id, error_type,
- base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) + error_message));
-}
-
-void ServiceWorkerDispatcherHost::SendUpdateError(
- int thread_id,
- int request_id,
- ServiceWorkerStatusCode status,
- const std::string& status_message) {
- base::string16 error_message;
- blink::WebServiceWorkerError::ErrorType error_type;
- GetServiceWorkerRegistrationStatusResponse(status, status_message,
- &error_type, &error_message);
- Send(new ServiceWorkerMsg_ServiceWorkerUpdateError(
- thread_id, request_id, error_type,
- base::ASCIIToUTF16(kServiceWorkerUpdateErrorPrefix) + error_message));
-}
-
-void ServiceWorkerDispatcherHost::SendUnregistrationError(
- int thread_id,
- int request_id,
- ServiceWorkerStatusCode status) {
- base::string16 error_message;
- blink::WebServiceWorkerError::ErrorType error_type;
- GetServiceWorkerRegistrationStatusResponse(status, std::string(), &error_type,
- &error_message);
- Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
- thread_id, request_id, error_type,
- base::ASCIIToUTF16(kServiceWorkerUnregisterErrorPrefix) + error_message));
-}
-
-void ServiceWorkerDispatcherHost::SendGetRegistrationError(
- int thread_id,
- int request_id,
- ServiceWorkerStatusCode status) {
- base::string16 error_message;
- blink::WebServiceWorkerError::ErrorType error_type;
- GetServiceWorkerRegistrationStatusResponse(status, std::string(), &error_type,
- &error_message);
- Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
- thread_id, request_id, error_type,
- base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
- error_message));
-}
-
-void ServiceWorkerDispatcherHost::SendGetRegistrationsError(
- int thread_id,
- int request_id,
- ServiceWorkerStatusCode status) {
- base::string16 error_message;
- blink::WebServiceWorkerError::ErrorType error_type;
- GetServiceWorkerRegistrationStatusResponse(status, std::string(), &error_type,
- &error_message);
- Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationsError(
- thread_id, request_id, error_type,
- base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
- error_message));
-}
-
ServiceWorkerContextCore* ServiceWorkerDispatcherHost::GetContext() {
if (!context_wrapper_.get())
return nullptr;
diff --git a/chromium/content/browser/service_worker/service_worker_dispatcher_host.h b/chromium/content/browser/service_worker/service_worker_dispatcher_host.h
index 89ff78997c2..b0287ffba11 100644
--- a/chromium/content/browser/service_worker/service_worker_dispatcher_host.h
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host.h
@@ -21,6 +21,10 @@
class GURL;
struct EmbeddedWorkerHostMsg_ReportConsoleMessage_Params;
+namespace url {
+class Origin;
+}
+
namespace content {
class MessagePortMessageFilter;
@@ -84,8 +88,11 @@ class CONTENT_EXPORT ServiceWorkerDispatcherHost : public BrowserMessageFilter {
private:
friend class BrowserThread;
friend class base::DeleteHelper<ServiceWorkerDispatcherHost>;
+ friend class ServiceWorkerDispatcherHostTest;
friend class TestingServiceWorkerDispatcherHost;
+ using StatusCallback = base::Callback<void(ServiceWorkerStatusCode status)>;
+
// IPC Message handlers
void OnRegisterServiceWorker(int thread_id,
int request_id,
@@ -136,10 +143,51 @@ class CONTENT_EXPORT ServiceWorkerDispatcherHost : public BrowserMessageFilter {
void OnDecrementRegistrationRefCount(int registration_handle_id);
void OnPostMessageToWorker(
int handle_id,
+ int provider_id,
+ const base::string16& message,
+ const url::Origin& source_origin,
+ const std::vector<TransferredMessagePort>& sent_message_ports);
+
+ // TODO(nhiroki): Remove this after ExtendableMessageEvent is enabled by
+ // default (crbug.com/543198).
+ void OnDeprecatedPostMessageToWorker(
+ int handle_id,
const base::string16& message,
const std::vector<TransferredMessagePort>& sent_message_ports);
+
void OnTerminateWorker(int handle_id);
+ void DispatchExtendableMessageEvent(
+ scoped_refptr<ServiceWorkerVersion> worker,
+ const base::string16& message,
+ const url::Origin& source_origin,
+ const std::vector<TransferredMessagePort>& sent_message_ports,
+ ServiceWorkerProviderHost* sender_provider_host,
+ const StatusCallback& callback);
+ template <typename SourceInfo>
+ void DispatchExtendableMessageEventInternal(
+ scoped_refptr<ServiceWorkerVersion> worker,
+ const base::string16& message,
+ const url::Origin& source_origin,
+ const std::vector<TransferredMessagePort>& sent_message_ports,
+ const StatusCallback& callback,
+ const SourceInfo& source_info);
+ void DispatchExtendableMessageEventAfterStartWorker(
+ scoped_refptr<ServiceWorkerVersion> worker,
+ const base::string16& message,
+ const url::Origin& source_origin,
+ const std::vector<TransferredMessagePort>& sent_message_ports,
+ const ExtendableMessageEventSource& source,
+ const StatusCallback& callback);
+ template <typename SourceInfo>
+ void DidFailToDispatchExtendableMessageEvent(
+ const std::vector<TransferredMessagePort>& sent_message_ports,
+ const SourceInfo& source_info,
+ const StatusCallback& callback,
+ ServiceWorkerStatusCode status);
+ void ReleaseSourceInfo(const ServiceWorkerClientInfo& source_info);
+ void ReleaseSourceInfo(const ServiceWorkerObjectInfo& source_info);
+
ServiceWorkerRegistrationHandle* FindRegistrationHandle(
int provider_id,
int64_t registration_handle_id);
@@ -157,63 +205,37 @@ class CONTENT_EXPORT ServiceWorkerDispatcherHost : public BrowserMessageFilter {
ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id);
-
void UpdateComplete(int thread_id,
int provider_id,
int request_id,
ServiceWorkerStatusCode status,
const std::string& status_message,
int64_t registration_id);
-
void UnregistrationComplete(int thread_id,
int request_id,
ServiceWorkerStatusCode status);
-
void GetRegistrationComplete(
int thread_id,
int provider_id,
int request_id,
ServiceWorkerStatusCode status,
const scoped_refptr<ServiceWorkerRegistration>& registration);
-
void GetRegistrationsComplete(
int thread_id,
int provider_id,
int request_id,
+ ServiceWorkerStatusCode status,
const std::vector<scoped_refptr<ServiceWorkerRegistration>>&
registrations);
-
void GetRegistrationForReadyComplete(
int thread_id,
int request_id,
base::WeakPtr<ServiceWorkerProviderHost> provider_host,
ServiceWorkerRegistration* registration);
- void SendRegistrationError(int thread_id,
- int request_id,
- ServiceWorkerStatusCode status,
- const std::string& status_message);
-
- void SendUpdateError(int thread_id,
- int request_id,
- ServiceWorkerStatusCode status,
- const std::string& status_message);
-
- void SendUnregistrationError(int thread_id,
- int request_id,
- ServiceWorkerStatusCode status);
-
- void SendGetRegistrationError(int thread_id,
- int request_id,
- ServiceWorkerStatusCode status);
-
- void SendGetRegistrationsError(int thread_id,
- int request_id,
- ServiceWorkerStatusCode status);
-
ServiceWorkerContextCore* GetContext();
- int render_process_id_;
+ const int render_process_id_;
MessagePortMessageFilter* const message_port_message_filter_;
ResourceContext* resource_context_;
scoped_refptr<ServiceWorkerContextWrapper> context_wrapper_;
diff --git a/chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc b/chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
index 84e1b6e0a35..7c9ad083ef9 100644
--- a/chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host_unittest.cc
@@ -11,11 +11,13 @@
#include "base/files/file_path.h"
#include "base/run_loop.h"
#include "content/browser/browser_thread_impl.h"
+#include "content/browser/message_port_service.h"
#include "content/browser/service_worker/embedded_worker_instance.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/browser/service_worker/service_worker_handle.h"
#include "content/common/service_worker/embedded_worker_messages.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/public/common/content_switches.h"
@@ -35,8 +37,17 @@ static void SaveStatusCallback(bool* called,
*out = status;
}
+void SetUpDummyMessagePort(std::vector<TransferredMessagePort>* ports) {
+ int port_id = -1;
+ MessagePortService::GetInstance()->Create(MSG_ROUTING_NONE, nullptr,
+ &port_id);
+ TransferredMessagePort dummy_port;
+ dummy_port.id = port_id;
+ ports->push_back(dummy_port);
}
+} // namespace
+
static const int kRenderFrameId = 1;
class TestingServiceWorkerDispatcherHost : public ServiceWorkerDispatcherHost {
@@ -65,25 +76,86 @@ class TestingServiceWorkerDispatcherHost : public ServiceWorkerDispatcherHost {
~TestingServiceWorkerDispatcherHost() override {}
};
+class FailToStartWorkerTestHelper : public EmbeddedWorkerTestHelper {
+ public:
+ FailToStartWorkerTestHelper() : EmbeddedWorkerTestHelper(base::FilePath()) {}
+
+ void OnStartWorker(int embedded_worker_id,
+ int64_t service_worker_version_id,
+ const GURL& scope,
+ const GURL& script_url,
+ bool pause_after_download) override {
+ EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
+ registry()->OnWorkerStopped(worker->process_id(), embedded_worker_id);
+ }
+};
+
class ServiceWorkerDispatcherHostTest : public testing::Test {
protected:
ServiceWorkerDispatcherHostTest()
: browser_thread_bundle_(TestBrowserThreadBundle::IO_MAINLOOP) {}
void SetUp() override {
- helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
- dispatcher_host_ = new TestingServiceWorkerDispatcherHost(
- helper_->mock_render_process_id(), context_wrapper(),
- &resource_context_, helper_.get());
+ Initialize(make_scoped_ptr(new EmbeddedWorkerTestHelper(base::FilePath())));
}
- void TearDown() override { helper_.reset(); }
+ void TearDown() override {
+ version_ = nullptr;
+ registration_ = nullptr;
+ helper_.reset();
+ }
ServiceWorkerContextCore* context() { return helper_->context(); }
ServiceWorkerContextWrapper* context_wrapper() {
return helper_->context_wrapper();
}
+ void Initialize(scoped_ptr<EmbeddedWorkerTestHelper> helper) {
+ helper_.reset(helper.release());
+ dispatcher_host_ = new TestingServiceWorkerDispatcherHost(
+ helper_->mock_render_process_id(), context_wrapper(),
+ &resource_context_, helper_.get());
+ }
+
+ void SetUpRegistration(const GURL& scope, const GURL& script_url) {
+ registration_ = new ServiceWorkerRegistration(
+ scope, 1L, helper_->context()->AsWeakPtr());
+ version_ = new ServiceWorkerVersion(registration_.get(), script_url, 1L,
+ helper_->context()->AsWeakPtr());
+ std::vector<ServiceWorkerDatabase::ResourceRecord> records;
+ records.push_back(
+ ServiceWorkerDatabase::ResourceRecord(10, version_->script_url(), 100));
+ version_->script_cache_map()->SetResources(records);
+
+ // Make the registration findable via storage functions.
+ helper_->context()->storage()->LazyInitialize(base::Bind(&base::DoNothing));
+ base::RunLoop().RunUntilIdle();
+ bool called = false;
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ helper_->context()->storage()->StoreRegistration(
+ registration_.get(), version_.get(),
+ base::Bind(&SaveStatusCallback, &called, &status));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(called);
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+ }
+
+ void SendSetHostedVersionId(int provider_id, int64_t version_id) {
+ dispatcher_host_->OnMessageReceived(
+ ServiceWorkerHostMsg_SetVersionId(provider_id, version_id));
+ }
+
+ void SendProviderCreated(ServiceWorkerProviderType type,
+ const GURL& pattern) {
+ const int64_t kProviderId = 99;
+ dispatcher_host_->OnMessageReceived(ServiceWorkerHostMsg_ProviderCreated(
+ kProviderId, MSG_ROUTING_NONE, type));
+ helper_->SimulateAddProcessToPattern(pattern,
+ helper_->mock_render_process_id());
+ provider_host_ = context()->GetProviderHost(
+ helper_->mock_render_process_id(), kProviderId);
+ }
+
void SendRegister(int64_t provider_id, GURL pattern, GURL worker_url) {
dispatcher_host_->OnMessageReceived(
ServiceWorkerHostMsg_RegisterServiceWorker(
@@ -146,6 +218,18 @@ class ServiceWorkerDispatcherHostTest : public testing::Test {
dispatcher_host_->ipc_sink()->ClearMessages();
}
+ void DispatchExtendableMessageEvent(
+ scoped_refptr<ServiceWorkerVersion> worker,
+ const base::string16& message,
+ const url::Origin& source_origin,
+ const std::vector<TransferredMessagePort>& sent_message_ports,
+ ServiceWorkerProviderHost* sender_provider_host,
+ const ServiceWorkerDispatcherHost::StatusCallback& callback) {
+ dispatcher_host_->DispatchExtendableMessageEvent(
+ std::move(worker), message, source_origin, sent_message_ports,
+ sender_provider_host, callback);
+ }
+
ServiceWorkerProviderHost* CreateServiceWorkerProviderHost(int provider_id) {
return new ServiceWorkerProviderHost(
helper_->mock_render_process_id(), kRenderFrameId, provider_id,
@@ -153,11 +237,13 @@ class ServiceWorkerDispatcherHostTest : public testing::Test {
dispatcher_host_.get());
}
-
TestBrowserThreadBundle browser_thread_bundle_;
content::MockResourceContext resource_context_;
scoped_ptr<EmbeddedWorkerTestHelper> helper_;
scoped_refptr<TestingServiceWorkerDispatcherHost> dispatcher_host_;
+ scoped_refptr<ServiceWorkerRegistration> registration_;
+ scoped_refptr<ServiceWorkerVersion> version_;
+ ServiceWorkerProviderHost* provider_host_;
};
class ServiceWorkerTestContentBrowserClient : public TestContentBrowserClient {
@@ -526,60 +612,33 @@ TEST_F(ServiceWorkerDispatcherHostTest, GetRegistrations_EarlyContextDeletion) {
}
TEST_F(ServiceWorkerDispatcherHostTest, CleanupOnRendererCrash) {
+ GURL pattern = GURL("http://www.example.com/");
+ GURL script_url = GURL("http://www.example.com/service_worker.js");
int process_id = helper_->mock_render_process_id();
- // Add a provider and worker.
- const int64_t kProviderId = 99; // Dummy value
- dispatcher_host_->OnMessageReceived(ServiceWorkerHostMsg_ProviderCreated(
- kProviderId, MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_WINDOW));
+ SendProviderCreated(SERVICE_WORKER_PROVIDER_FOR_WINDOW, pattern);
+ SetUpRegistration(pattern, script_url);
+ int64_t provider_id = provider_host_->provider_id();
- GURL pattern = GURL("http://www.example.com/");
- scoped_refptr<ServiceWorkerRegistration> registration(
- new ServiceWorkerRegistration(pattern,
- 1L,
- helper_->context()->AsWeakPtr()));
- scoped_refptr<ServiceWorkerVersion> version(
- new ServiceWorkerVersion(registration.get(),
- GURL("http://www.example.com/service_worker.js"),
- 1L,
- helper_->context()->AsWeakPtr()));
- std::vector<ServiceWorkerDatabase::ResourceRecord> records;
- records.push_back(
- ServiceWorkerDatabase::ResourceRecord(10, version->script_url(), 100));
- version->script_cache_map()->SetResources(records);
-
- // Make the registration findable via storage functions.
- helper_->context()->storage()->LazyInitialize(base::Bind(&base::DoNothing));
- base::RunLoop().RunUntilIdle();
+ // Start up the worker.
bool called = false;
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_ABORT;
- helper_->context()->storage()->StoreRegistration(
- registration.get(),
- version.get(),
- base::Bind(&SaveStatusCallback, &called, &status));
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(called);
- ASSERT_EQ(SERVICE_WORKER_OK, status);
-
- helper_->SimulateAddProcessToPattern(pattern, process_id);
-
- // Start up the worker.
- status = SERVICE_WORKER_ERROR_ABORT;
- version->StartWorker(base::Bind(&SaveStatusCallback, &called, &status));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ base::Bind(&SaveStatusCallback, &called, &status));
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(called);
EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_TRUE(context()->GetProviderHost(process_id, kProviderId));
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version->running_status());
+ EXPECT_TRUE(context()->GetProviderHost(process_id, provider_id));
+ EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
// Simulate the render process crashing.
dispatcher_host_->OnFilterRemoved();
// The dispatcher host should clean up the state from the process.
- EXPECT_FALSE(context()->GetProviderHost(process_id, kProviderId));
- EXPECT_EQ(ServiceWorkerVersion::STOPPED, version->running_status());
+ EXPECT_FALSE(context()->GetProviderHost(process_id, provider_id));
+ EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
// We should be able to hook up a new dispatcher host although the old object
// is not yet destroyed. This is what the browser does when reusing a crashed
@@ -592,8 +651,114 @@ TEST_F(ServiceWorkerDispatcherHostTest, CleanupOnRendererCrash) {
// the old dispatcher cleaned up the old provider host, the new one won't
// complain.
new_dispatcher_host->OnMessageReceived(ServiceWorkerHostMsg_ProviderCreated(
- kProviderId, MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_WINDOW));
+ provider_id, MSG_ROUTING_NONE, SERVICE_WORKER_PROVIDER_FOR_WINDOW));
EXPECT_EQ(0, new_dispatcher_host->bad_messages_received_count_);
}
+TEST_F(ServiceWorkerDispatcherHostTest, DispatchExtendableMessageEvent) {
+ GURL pattern = GURL("http://www.example.com/");
+ GURL script_url = GURL("http://www.example.com/service_worker.js");
+
+ SendProviderCreated(SERVICE_WORKER_PROVIDER_FOR_CONTROLLER, pattern);
+ SetUpRegistration(pattern, script_url);
+
+ // Set the running hosted version so that we can retrieve a valid service
+ // worker object information for the source attribute of the message event.
+ provider_host_->running_hosted_version_ = version_;
+
+ // Set aside the initial refcount of the worker handle.
+ provider_host_->GetOrCreateServiceWorkerHandle(version_.get());
+ ServiceWorkerHandle* sender_worker_handle =
+ dispatcher_host_->FindServiceWorkerHandle(provider_host_->provider_id(),
+ version_->version_id());
+ const int ref_count = sender_worker_handle->ref_count();
+
+ // Dispatch ExtendableMessageEvent.
+ std::vector<TransferredMessagePort> ports;
+ SetUpDummyMessagePort(&ports);
+ bool called = false;
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ DispatchExtendableMessageEvent(
+ version_, base::string16(), url::Origin(version_->scope().GetOrigin()),
+ ports, provider_host_, base::Bind(&SaveStatusCallback, &called, &status));
+ for (TransferredMessagePort port : ports)
+ EXPECT_TRUE(MessagePortService::GetInstance()->AreMessagesHeld(port.id));
+ EXPECT_EQ(ref_count + 1, sender_worker_handle->ref_count());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(called);
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+
+ // Messages should be held until ports are created at the destination.
+ for (TransferredMessagePort port : ports)
+ EXPECT_TRUE(MessagePortService::GetInstance()->AreMessagesHeld(port.id));
+
+ EXPECT_EQ(ref_count + 1, sender_worker_handle->ref_count());
+}
+
+TEST_F(ServiceWorkerDispatcherHostTest, DispatchExtendableMessageEvent_Fail) {
+ GURL pattern = GURL("http://www.example.com/");
+ GURL script_url = GURL("http://www.example.com/service_worker.js");
+
+ Initialize(make_scoped_ptr(new FailToStartWorkerTestHelper));
+ SendProviderCreated(SERVICE_WORKER_PROVIDER_FOR_CONTROLLER, pattern);
+ SetUpRegistration(pattern, script_url);
+
+ // Set the running hosted version so that we can retrieve a valid service
+ // worker object information for the source attribute of the message event.
+ provider_host_->running_hosted_version_ = version_;
+
+ // Set aside the initial refcount of the worker handle.
+ provider_host_->GetOrCreateServiceWorkerHandle(version_.get());
+ ServiceWorkerHandle* sender_worker_handle =
+ dispatcher_host_->FindServiceWorkerHandle(provider_host_->provider_id(),
+ version_->version_id());
+ const int ref_count = sender_worker_handle->ref_count();
+
+ // Try to dispatch ExtendableMessageEvent. This should fail to start the
+ // worker and to dispatch the event.
+ std::vector<TransferredMessagePort> ports;
+ SetUpDummyMessagePort(&ports);
+ bool called = false;
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+ DispatchExtendableMessageEvent(
+ version_, base::string16(), url::Origin(version_->scope().GetOrigin()),
+ ports, provider_host_, base::Bind(&SaveStatusCallback, &called, &status));
+ for (TransferredMessagePort port : ports)
+ EXPECT_TRUE(MessagePortService::GetInstance()->AreMessagesHeld(port.id));
+ EXPECT_EQ(ref_count + 1, sender_worker_handle->ref_count());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(called);
+ EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status);
+
+ // The error callback should clean up the ports and handle.
+ for (TransferredMessagePort port : ports)
+ EXPECT_FALSE(MessagePortService::GetInstance()->AreMessagesHeld(port.id));
+ EXPECT_EQ(ref_count, sender_worker_handle->ref_count());
+}
+
+TEST_F(ServiceWorkerDispatcherHostTest, OnSetHostedVersionId) {
+ GURL pattern = GURL("http://www.example.com/");
+ GURL script_url = GURL("http://www.example.com/service_worker.js");
+
+ Initialize(make_scoped_ptr(new FailToStartWorkerTestHelper));
+ SendProviderCreated(SERVICE_WORKER_PROVIDER_FOR_CONTROLLER, pattern);
+ SetUpRegistration(pattern, script_url);
+
+ const int64_t kProviderId = 99; // Dummy value
+ bool called;
+ ServiceWorkerStatusCode status;
+ // StartWorker puts the worker in STARTING state but it will have no
+ // process id yet.
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ base::Bind(&SaveStatusCallback, &called, &status));
+ EXPECT_NE(version_->embedded_worker()->process_id(),
+ provider_host_->process_id());
+ // SendSetHostedVersionId should reject because the provider host process id
+ // is different.
+ SendSetHostedVersionId(kProviderId, version_->version_id());
+ base::RunLoop().RunUntilIdle();
+ EXPECT_FALSE(dispatcher_host_->ipc_sink()->GetUniqueMessageMatching(
+ ServiceWorkerMsg_AssociateRegistration::ID));
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
index 60c4eb66ef6..dfcce9a5f9a 100644
--- a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
+++ b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.cc
@@ -9,18 +9,41 @@
#include "base/bind.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/service_worker/service_worker_version.h"
+#include "content/common/service_worker/service_worker_messages.h"
namespace content {
+namespace {
+using EventType = ServiceWorkerMetrics::EventType;
+EventType ResourceTypeToEventType(ResourceType resource_type) {
+ switch (resource_type) {
+ case RESOURCE_TYPE_MAIN_FRAME:
+ return EventType::FETCH_MAIN_FRAME;
+ case RESOURCE_TYPE_SUB_FRAME:
+ return EventType::FETCH_SUB_FRAME;
+ case RESOURCE_TYPE_SHARED_WORKER:
+ return EventType::FETCH_SHARED_WORKER;
+ case RESOURCE_TYPE_SERVICE_WORKER:
+ case RESOURCE_TYPE_LAST_TYPE:
+ NOTREACHED() << resource_type;
+ return EventType::FETCH_SUB_RESOURCE;
+ default:
+ return EventType::FETCH_SUB_RESOURCE;
+ }
+}
+} // namespace
+
ServiceWorkerFetchDispatcher::ServiceWorkerFetchDispatcher(
scoped_ptr<ServiceWorkerFetchRequest> request,
ServiceWorkerVersion* version,
+ ResourceType resource_type,
const base::Closure& prepare_callback,
const FetchCallback& fetch_callback)
: version_(version),
prepare_callback_(prepare_callback),
fetch_callback_(fetch_callback),
request_(std::move(request)),
+ resource_type_(resource_type),
weak_factory_(this) {}
ServiceWorkerFetchDispatcher::~ServiceWorkerFetchDispatcher() {}
@@ -36,7 +59,7 @@ void ServiceWorkerFetchDispatcher::Run() {
weak_factory_.GetWeakPtr()));
return;
}
- DispatchFetchEvent();
+ DidWaitActivation();
}
void ServiceWorkerFetchDispatcher::DidWaitActivation() {
@@ -45,7 +68,12 @@ void ServiceWorkerFetchDispatcher::DidWaitActivation() {
DidFailActivation();
return;
}
- DispatchFetchEvent();
+ version_->RunAfterStartWorker(
+ GetEventType(),
+ base::Bind(&ServiceWorkerFetchDispatcher::DispatchFetchEvent,
+ weak_factory_.GetWeakPtr()),
+ base::Bind(&ServiceWorkerFetchDispatcher::DidFail,
+ weak_factory_.GetWeakPtr()));
}
void ServiceWorkerFetchDispatcher::DidFailActivation() {
@@ -59,14 +87,18 @@ void ServiceWorkerFetchDispatcher::DidFailActivation() {
}
void ServiceWorkerFetchDispatcher::DispatchFetchEvent() {
- TRACE_EVENT_ASYNC_BEGIN0(
- "ServiceWorker",
- "ServiceWorkerFetchDispatcher::DispatchFetchEvent",
- request_.get());
- version_->DispatchFetchEvent(
- *request_.get(),
- base::Bind(&ServiceWorkerFetchDispatcher::DidPrepare,
- weak_factory_.GetWeakPtr()),
+ DCHECK_EQ(ServiceWorkerVersion::RUNNING, version_->running_status())
+ << "Worker stopped too soon after it was started.";
+
+ DCHECK(!prepare_callback_.is_null());
+ base::Closure prepare_callback = prepare_callback_;
+ prepare_callback.Run();
+
+ int request_id = version_->StartRequest(
+ GetEventType(), base::Bind(&ServiceWorkerFetchDispatcher::DidFail,
+ weak_factory_.GetWeakPtr()));
+ version_->DispatchEvent<ServiceWorkerHostMsg_FetchEventFinished>(
+ request_id, ServiceWorkerMsg_FetchEvent(request_id, *request_.get()),
base::Bind(&ServiceWorkerFetchDispatcher::DidFinish,
weak_factory_.GetWeakPtr()));
}
@@ -77,17 +109,34 @@ void ServiceWorkerFetchDispatcher::DidPrepare() {
prepare_callback.Run();
}
+void ServiceWorkerFetchDispatcher::DidFail(ServiceWorkerStatusCode status) {
+ DCHECK(!fetch_callback_.is_null());
+ FetchCallback fetch_callback = fetch_callback_;
+ scoped_refptr<ServiceWorkerVersion> version = version_;
+ fetch_callback.Run(status, SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK,
+ ServiceWorkerResponse(), version);
+}
+
void ServiceWorkerFetchDispatcher::DidFinish(
- ServiceWorkerStatusCode status,
+ int request_id,
ServiceWorkerFetchEventResult fetch_result,
const ServiceWorkerResponse& response) {
- TRACE_EVENT_ASYNC_END0(
- "ServiceWorker",
- "ServiceWorkerFetchDispatcher::DispatchFetchEvent",
- request_.get());
+ const bool handled =
+ (fetch_result == SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE);
+ if (!version_->FinishRequest(request_id, handled))
+ NOTREACHED() << "Should only receive one reply per event";
+
DCHECK(!fetch_callback_.is_null());
FetchCallback fetch_callback = fetch_callback_;
- fetch_callback.Run(status, fetch_result, response, version_);
+ scoped_refptr<ServiceWorkerVersion> version = version_;
+ fetch_callback.Run(SERVICE_WORKER_OK, fetch_result, response, version);
+}
+
+ServiceWorkerMetrics::EventType ServiceWorkerFetchDispatcher::GetEventType()
+ const {
+ if (request_->fetch_type == ServiceWorkerFetchType::FOREIGN_FETCH)
+ return ServiceWorkerMetrics::EventType::FOREIGN_FETCH;
+ return ResourceTypeToEventType(resource_type_);
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h
index 518be84906b..82a4a2d551d 100644
--- a/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h
+++ b/chromium/content/browser/service_worker/service_worker_fetch_dispatcher.h
@@ -8,24 +8,28 @@
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "content/browser/service_worker/service_worker_metrics.h"
+#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_status_code.h"
#include "content/common/service_worker/service_worker_types.h"
+#include "content/public/common/resource_type.h"
namespace content {
class ServiceWorkerVersion;
// A helper class to dispatch fetch event to a service worker.
-class ServiceWorkerFetchDispatcher {
+class CONTENT_EXPORT ServiceWorkerFetchDispatcher {
public:
typedef base::Callback<void(ServiceWorkerStatusCode,
ServiceWorkerFetchEventResult,
const ServiceWorkerResponse&,
- scoped_refptr<ServiceWorkerVersion>)>
+ const scoped_refptr<ServiceWorkerVersion>&)>
FetchCallback;
ServiceWorkerFetchDispatcher(scoped_ptr<ServiceWorkerFetchRequest> request,
ServiceWorkerVersion* version,
+ ResourceType resource_type,
const base::Closure& prepare_callback,
const FetchCallback& fetch_callback);
~ServiceWorkerFetchDispatcher();
@@ -39,14 +43,18 @@ class ServiceWorkerFetchDispatcher {
void DidFailActivation();
void DispatchFetchEvent();
void DidPrepare();
- void DidFinish(ServiceWorkerStatusCode status,
+ void DidFail(ServiceWorkerStatusCode status);
+ void DidFinish(int request_id,
ServiceWorkerFetchEventResult fetch_result,
const ServiceWorkerResponse& response);
+ ServiceWorkerMetrics::EventType GetEventType() const;
+
scoped_refptr<ServiceWorkerVersion> version_;
base::Closure prepare_callback_;
FetchCallback fetch_callback_;
scoped_ptr<ServiceWorkerFetchRequest> request_;
+ ResourceType resource_type_;
base::WeakPtrFactory<ServiceWorkerFetchDispatcher> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerFetchDispatcher);
diff --git a/chromium/content/browser/service_worker/service_worker_handle.h b/chromium/content/browser/service_worker/service_worker_handle.h
index a9c0e443a51..4d8651af83d 100644
--- a/chromium/content/browser/service_worker/service_worker_handle.h
+++ b/chromium/content/browser/service_worker/service_worker_handle.h
@@ -54,6 +54,7 @@ class CONTENT_EXPORT ServiceWorkerHandle
int handle_id() const { return handle_id_; }
ServiceWorkerVersion* version() { return version_.get(); }
+ int ref_count() const { return ref_count_; }
bool HasNoRefCount() const { return ref_count_ <= 0; }
void IncrementRefCount();
void DecrementRefCount();
diff --git a/chromium/content/browser/service_worker/service_worker_handle_unittest.cc b/chromium/content/browser/service_worker/service_worker_handle_unittest.cc
index 25514ffbd58..ae15a98e549 100644
--- a/chromium/content/browser/service_worker/service_worker_handle_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_handle_unittest.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <vector>
+
#include "base/macros.h"
#include "base/run_loop.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
@@ -142,20 +144,18 @@ TEST_F(ServiceWorkerHandleTest, OnVersionStateChanged) {
// Start the worker, and then...
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
- version_->StartWorker(CreateReceiverOnCurrentThread(&status));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
- // ...dispatch install event.
- status = SERVICE_WORKER_ERROR_FAILED;
+ // ...update state to installing...
version_->SetStatus(ServiceWorkerVersion::INSTALLING);
- version_->DispatchInstallEvent(CreateReceiverOnCurrentThread(&status));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ // ...and update state to installed.
version_->SetStatus(ServiceWorkerVersion::INSTALLED);
- ASSERT_EQ(4UL, ipc_sink()->message_count());
+ ASSERT_EQ(3UL, ipc_sink()->message_count());
ASSERT_EQ(0L, dispatcher_host_->bad_message_received_count_);
// We should be sending 1. StartWorker,
@@ -165,13 +165,10 @@ TEST_F(ServiceWorkerHandleTest, OnVersionStateChanged) {
VerifyStateChangedMessage(handle->handle_id(),
blink::WebServiceWorkerStateInstalling,
ipc_sink()->GetMessageAt(1));
- // 3. SendMessageToWorker (to send InstallEvent), and
- EXPECT_EQ(EmbeddedWorkerContextMsg_MessageToWorker::ID,
- ipc_sink()->GetMessageAt(2)->type());
- // 4. StateChanged (state == Installed).
+ // 3. StateChanged (state == Installed).
VerifyStateChangedMessage(handle->handle_id(),
blink::WebServiceWorkerStateInstalled,
- ipc_sink()->GetMessageAt(3));
+ ipc_sink()->GetMessageAt(2));
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_info.cc b/chromium/content/browser/service_worker/service_worker_info.cc
index 836e979763d..0f4a4c5d9e7 100644
--- a/chromium/content/browser/service_worker/service_worker_info.cc
+++ b/chromium/content/browser/service_worker/service_worker_info.cc
@@ -51,12 +51,14 @@ ServiceWorkerVersionInfo::ServiceWorkerVersionInfo(
thread_id(thread_id),
devtools_agent_route_id(devtools_agent_route_id) {}
+ServiceWorkerVersionInfo::ServiceWorkerVersionInfo(
+ const ServiceWorkerVersionInfo& other) = default;
+
ServiceWorkerVersionInfo::~ServiceWorkerVersionInfo() {}
ServiceWorkerRegistrationInfo::ServiceWorkerRegistrationInfo()
: registration_id(kInvalidServiceWorkerRegistrationId),
delete_flag(IS_NOT_DELETED),
- force_update_on_page_load(IS_NOT_FORCED),
stored_version_size_bytes(0) {}
ServiceWorkerRegistrationInfo::ServiceWorkerRegistrationInfo(
@@ -66,14 +68,12 @@ ServiceWorkerRegistrationInfo::ServiceWorkerRegistrationInfo(
: pattern(pattern),
registration_id(registration_id),
delete_flag(delete_flag),
- force_update_on_page_load(IS_NOT_FORCED),
stored_version_size_bytes(0) {}
ServiceWorkerRegistrationInfo::ServiceWorkerRegistrationInfo(
const GURL& pattern,
int64_t registration_id,
DeleteFlag delete_flag,
- ForceUpdateOnPageLoad force_update_on_page_load,
const ServiceWorkerVersionInfo& active_version,
const ServiceWorkerVersionInfo& waiting_version,
const ServiceWorkerVersionInfo& installing_version,
@@ -81,12 +81,14 @@ ServiceWorkerRegistrationInfo::ServiceWorkerRegistrationInfo(
: pattern(pattern),
registration_id(registration_id),
delete_flag(delete_flag),
- force_update_on_page_load(force_update_on_page_load),
active_version(active_version),
waiting_version(waiting_version),
installing_version(installing_version),
stored_version_size_bytes(stored_version_size_bytes) {}
+ServiceWorkerRegistrationInfo::ServiceWorkerRegistrationInfo(
+ const ServiceWorkerRegistrationInfo& other) = default;
+
ServiceWorkerRegistrationInfo::~ServiceWorkerRegistrationInfo() {}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_info.h b/chromium/content/browser/service_worker/service_worker_info.h
index b1c0a73f082..8de17feaa24 100644
--- a/chromium/content/browser/service_worker/service_worker_info.h
+++ b/chromium/content/browser/service_worker/service_worker_info.h
@@ -37,6 +37,7 @@ struct CONTENT_EXPORT ServiceWorkerVersionInfo {
int process_id,
int thread_id,
int devtools_agent_route_id);
+ ServiceWorkerVersionInfo(const ServiceWorkerVersionInfo& other);
~ServiceWorkerVersionInfo();
ServiceWorkerVersion::RunningStatus running_status;
@@ -55,7 +56,6 @@ struct CONTENT_EXPORT ServiceWorkerVersionInfo {
struct CONTENT_EXPORT ServiceWorkerRegistrationInfo {
public:
enum DeleteFlag { IS_NOT_DELETED, IS_DELETED };
- enum ForceUpdateOnPageLoad { IS_NOT_FORCED, IS_FORCED };
ServiceWorkerRegistrationInfo();
ServiceWorkerRegistrationInfo(const GURL& pattern,
int64_t registration_id,
@@ -64,17 +64,16 @@ struct CONTENT_EXPORT ServiceWorkerRegistrationInfo {
const GURL& pattern,
int64_t registration_id,
DeleteFlag delete_flag,
- ForceUpdateOnPageLoad force_update_on_page_load,
const ServiceWorkerVersionInfo& active_version,
const ServiceWorkerVersionInfo& waiting_version,
const ServiceWorkerVersionInfo& installing_version,
int64_t active_version_total_size_bytes);
+ ServiceWorkerRegistrationInfo(const ServiceWorkerRegistrationInfo& other);
~ServiceWorkerRegistrationInfo();
GURL pattern;
int64_t registration_id;
DeleteFlag delete_flag;
- ForceUpdateOnPageLoad force_update_on_page_load;
ServiceWorkerVersionInfo active_version;
ServiceWorkerVersionInfo waiting_version;
ServiceWorkerVersionInfo installing_version;
diff --git a/chromium/content/browser/service_worker/service_worker_internals_ui.cc b/chromium/content/browser/service_worker/service_worker_internals_ui.cc
index ae899dca58d..61eaffbba7b 100644
--- a/chromium/content/browser/service_worker/service_worker_internals_ui.cc
+++ b/chromium/content/browser/service_worker/service_worker_internals_ui.cc
@@ -22,10 +22,12 @@
#include "content/grit/content_resources.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/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_data_source.h"
+#include "content/public/common/child_process_host.h"
#include "content/public/common/url_constants.h"
using base::DictionaryValue;
@@ -89,29 +91,23 @@ void CallServiceWorkerVersionMethodWithVersionID(
(*version.get().*method)(callback);
}
-void DispatchPushEventWithVersionID(
- scoped_refptr<ServiceWorkerContextWrapper> context,
- int64_t version_id,
- const ServiceWorkerInternalsUI::StatusCallback& callback) {
- if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
- BrowserThread::PostTask(
- BrowserThread::IO,
- FROM_HERE,
- base::Bind(DispatchPushEventWithVersionID,
- context,
- version_id,
- callback));
- return;
- }
-
- scoped_refptr<ServiceWorkerVersion> version =
- context->GetLiveVersion(version_id);
- if (!version.get()) {
- callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND);
- return;
- }
- std::string data = "Test push message from ServiceWorkerInternals.";
- version->DispatchPushEvent(callback, data);
+base::ProcessId GetRealProcessId(int process_host_id) {
+ if (process_host_id == ChildProcessHost::kInvalidUniqueID)
+ return base::kNullProcessId;
+
+ RenderProcessHost* rph = RenderProcessHost::FromID(process_host_id);
+ if (!rph)
+ return base::kNullProcessId;
+
+ base::ProcessHandle handle = rph->GetHandle();
+ if (handle == base::kNullProcessHandle)
+ return base::kNullProcessId;
+ // TODO(nhiroki): On Windows, |rph->GetHandle()| does not duplicate ownership
+ // of the process handle and the render host still retains it. Therefore, we
+ // cannot create a base::Process object, which provides a proper way to get a
+ // process id, from the handle. For a stopgap, we use this deprecated
+ // function that does not require the ownership (http://crbug.com/417532).
+ return base::GetProcId(handle);
}
void UpdateVersionInfo(const ServiceWorkerVersionInfo& version,
@@ -153,7 +149,9 @@ void UpdateVersionInfo(const ServiceWorkerVersionInfo& version,
}
info->SetString("script_url", version.script_url.spec());
info->SetString("version_id", base::Int64ToString(version.version_id));
- info->SetInteger("process_id", version.process_id);
+ info->SetInteger("process_id",
+ static_cast<int>(GetRealProcessId(version.process_id)));
+ info->SetInteger("process_host_id", version.process_id);
info->SetInteger("thread_id", version.thread_id);
info->SetInteger("devtools_agent_route_id", version.devtools_agent_route_id);
}
@@ -207,6 +205,7 @@ ListValue* GetVersionListValue(
void DidGetStoredRegistrationsOnIOThread(
scoped_refptr<ServiceWorkerContextWrapper> context,
const GetRegistrationsCallback& callback,
+ ServiceWorkerStatusCode status,
const std::vector<ServiceWorkerRegistrationInfo>& stored_registrations) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
BrowserThread::PostTask(
@@ -358,10 +357,6 @@ ServiceWorkerInternalsUI::ServiceWorkerInternalsUI(WebUI* web_ui)
base::Unretained(this),
&ServiceWorkerVersion::StopWorker));
web_ui->RegisterMessageCallback(
- "push",
- base::Bind(&ServiceWorkerInternalsUI::DispatchPushEvent,
- base::Unretained(this)));
- web_ui->RegisterMessageCallback(
"inspect",
base::Bind(&ServiceWorkerInternalsUI::InspectWorker,
base::Unretained(this)));
@@ -510,38 +505,15 @@ void ServiceWorkerInternalsUI::CallServiceWorkerVersionMethod(
method, context, version_id, callback);
}
-void ServiceWorkerInternalsUI::DispatchPushEvent(
- const ListValue* args) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- int callback_id;
- int partition_id;
- int64_t version_id = 0;
- std::string version_id_string;
- const DictionaryValue* cmd_args = NULL;
- scoped_refptr<ServiceWorkerContextWrapper> context;
- if (!args->GetInteger(0, &callback_id) ||
- !args->GetDictionary(1, &cmd_args) ||
- !cmd_args->GetInteger("partition_id", &partition_id) ||
- !GetServiceWorkerContext(partition_id, &context) ||
- !cmd_args->GetString("version_id", &version_id_string) ||
- !base::StringToInt64(version_id_string, &version_id)) {
- return;
- }
-
- base::Callback<void(ServiceWorkerStatusCode)> callback =
- base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
- DispatchPushEventWithVersionID(context, version_id, callback);
-}
-
void ServiceWorkerInternalsUI::InspectWorker(const ListValue* args) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
int callback_id;
const DictionaryValue* cmd_args = NULL;
- int process_id = 0;
+ int process_host_id = 0;
int devtools_agent_route_id = 0;
if (!args->GetInteger(0, &callback_id) ||
!args->GetDictionary(1, &cmd_args) ||
- !cmd_args->GetInteger("process_id", &process_id) ||
+ !cmd_args->GetInteger("process_host_id", &process_host_id) ||
!cmd_args->GetInteger("devtools_agent_route_id",
&devtools_agent_route_id)) {
return;
@@ -550,7 +522,8 @@ void ServiceWorkerInternalsUI::InspectWorker(const ListValue* args) {
base::Bind(OperationCompleteCallback, AsWeakPtr(), callback_id);
scoped_refptr<DevToolsAgentHostImpl> agent_host(
ServiceWorkerDevToolsManager::GetInstance()
- ->GetDevToolsAgentHostForWorker(process_id, devtools_agent_route_id));
+ ->GetDevToolsAgentHostForWorker(process_host_id,
+ devtools_agent_route_id));
if (!agent_host.get()) {
callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND);
return;
diff --git a/chromium/content/browser/service_worker/service_worker_internals_ui.h b/chromium/content/browser/service_worker/service_worker_internals_ui.h
index bc1c5b93511..b04df03aab9 100644
--- a/chromium/content/browser/service_worker/service_worker_internals_ui.h
+++ b/chromium/content/browser/service_worker/service_worker_internals_ui.h
@@ -52,7 +52,6 @@ class ServiceWorkerInternalsUI
void GetAllRegistrations(const base::ListValue* args);
void CallServiceWorkerVersionMethod(ServiceWorkerVersionMethod method,
const base::ListValue* args);
- void DispatchPushEvent(const base::ListValue* args);
void InspectWorker(const base::ListValue* args);
void Unregister(const base::ListValue* args);
void StartWorker(const base::ListValue* args);
diff --git a/chromium/content/browser/service_worker/service_worker_job_coordinator.cc b/chromium/content/browser/service_worker/service_worker_job_coordinator.cc
index b8f71cf5796..9dd023e9e94 100644
--- a/chromium/content/browser/service_worker/service_worker_job_coordinator.cc
+++ b/chromium/content/browser/service_worker/service_worker_job_coordinator.cc
@@ -23,6 +23,9 @@ bool IsRegisterJob(const ServiceWorkerRegisterJobBase& job) {
ServiceWorkerJobCoordinator::JobQueue::JobQueue() {}
+ServiceWorkerJobCoordinator::JobQueue::JobQueue(const JobQueue& other) =
+ default;
+
ServiceWorkerJobCoordinator::JobQueue::~JobQueue() {
DCHECK(jobs_.empty()) << "Destroying JobQueue with " << jobs_.size()
<< " unfinished jobs";
diff --git a/chromium/content/browser/service_worker/service_worker_job_coordinator.h b/chromium/content/browser/service_worker/service_worker_job_coordinator.h
index 728b8206b8f..5b4c1f19eea 100644
--- a/chromium/content/browser/service_worker/service_worker_job_coordinator.h
+++ b/chromium/content/browser/service_worker/service_worker_job_coordinator.h
@@ -56,6 +56,7 @@ class CONTENT_EXPORT ServiceWorkerJobCoordinator {
class JobQueue {
public:
JobQueue();
+ JobQueue(const JobQueue& other);
~JobQueue();
// Adds a job to the queue. If an identical job is already at the end of the
diff --git a/chromium/content/browser/service_worker/service_worker_job_unittest.cc b/chromium/content/browser/service_worker/service_worker_job_unittest.cc
index a5572a4f60b..a86b0781706 100644
--- a/chromium/content/browser/service_worker/service_worker_job_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_job_unittest.cc
@@ -17,6 +17,7 @@
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_registration_status.h"
#include "content/browser/service_worker/service_worker_test_utils.h"
+#include "content/common/service_worker/embedded_worker_messages.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "ipc/ipc_test_sink.h"
@@ -274,6 +275,8 @@ TEST_F(ServiceWorkerJobTest, Register) {
GURL("http://www.example.com/service_worker.js"));
ASSERT_NE(scoped_refptr<ServiceWorkerRegistration>(NULL), registration);
+ EXPECT_TRUE(helper_->inner_ipc_sink()->GetUniqueMessageMatching(
+ ServiceWorkerMsg_InstallEvent::ID));
}
// Make sure registrations are cleaned up when they are unregistered.
@@ -359,7 +362,8 @@ class FailToStartWorkerTestHelper : public EmbeddedWorkerTestHelper {
void OnStartWorker(int embedded_worker_id,
int64_t service_worker_version_id,
const GURL& scope,
- const GURL& script_url) override {
+ const GURL& script_url,
+ bool pause_after_download) override {
EmbeddedWorkerInstance* worker = registry()->GetWorker(embedded_worker_id);
registry()->OnWorkerStopped(worker->process_id(), embedded_worker_id);
}
@@ -639,7 +643,8 @@ TEST_F(ServiceWorkerJobTest, UnregisterWaitingSetsRedundant) {
scoped_refptr<ServiceWorkerVersion> version = new ServiceWorkerVersion(
registration.get(), script_url, 1L, helper_->context()->AsWeakPtr());
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
- version->StartWorker(CreateReceiverOnCurrentThread(&status));
+ version->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
ASSERT_EQ(SERVICE_WORKER_OK, status);
@@ -788,6 +793,10 @@ class UpdateJobTestHelper
return context()->job_coordinator();
}
+ void set_force_start_worker_failure(bool force_start_worker_failure) {
+ force_start_worker_failure_ = force_start_worker_failure;
+ }
+
scoped_refptr<ServiceWorkerRegistration> SetupInitialRegistration(
const GURL& test_origin) {
scoped_refptr<ServiceWorkerRegistration> registration;
@@ -811,7 +820,8 @@ class UpdateJobTestHelper
void OnStartWorker(int embedded_worker_id,
int64_t version_id,
const GURL& scope,
- const GURL& script) override {
+ const GURL& script,
+ bool pause_after_download) override {
const std::string kMockScriptBody = "mock_script";
const uint64_t kMockScriptSize = 19284;
ServiceWorkerVersion* version = context()->GetLiveVersion(version_id);
@@ -823,29 +833,51 @@ class UpdateJobTestHelper
ASSERT_TRUE(version);
version->AddListener(this);
+ // Simulate network access.
+ base::TimeDelta time_since_last_check =
+ base::Time::Now() - registration->last_update_check();
+ if (!is_update || script.GetOrigin() != kNoChangeOrigin ||
+ time_since_last_check > base::TimeDelta::FromHours(
+ kServiceWorkerScriptMaxCacheAgeInHours)) {
+ version->embedded_worker()->OnNetworkAccessedForScriptLoad();
+ }
+
+ int64_t resource_id = storage()->NewResourceId();
+ version->script_cache_map()->NotifyStartedCaching(script, resource_id);
if (!is_update) {
// Spoof caching the script for the initial version.
- int64_t resource_id = storage()->NewResourceId();
- version->script_cache_map()->NotifyStartedCaching(script, resource_id);
WriteStringResponse(storage(), resource_id, kMockScriptBody);
version->script_cache_map()->NotifyFinishedCaching(
script, kMockScriptSize, net::URLRequestStatus(), std::string());
} else {
if (script.GetOrigin() == kNoChangeOrigin) {
- version->SetStartWorkerStatusCode(SERVICE_WORKER_ERROR_EXISTS);
- EmbeddedWorkerTestHelper::OnStopWorker(embedded_worker_id);
+ // Simulate fetching the updated script and finding it's identical to
+ // the incumbent.
+ net::URLRequestStatus status =
+ net::URLRequestStatus::FromError(net::ERR_FILE_EXISTS);
+ version->script_cache_map()->NotifyFinishedCaching(
+ script, kMockScriptSize, status, std::string());
+ SimulateWorkerScriptLoaded(embedded_worker_id);
return;
}
// Spoof caching the script for the new version.
- int64_t resource_id = storage()->NewResourceId();
- version->script_cache_map()->NotifyStartedCaching(script, resource_id);
WriteStringResponse(storage(), resource_id, "mock_different_script");
version->script_cache_map()->NotifyFinishedCaching(
script, kMockScriptSize, net::URLRequestStatus(), std::string());
}
- EmbeddedWorkerTestHelper::OnStartWorker(embedded_worker_id, version_id,
- scope, script);
+
+ EmbeddedWorkerTestHelper::OnStartWorker(
+ embedded_worker_id, version_id, scope, script, pause_after_download);
+ }
+
+ void OnResumeAfterDownload(int embedded_worker_id) override {
+ if (!force_start_worker_failure_) {
+ EmbeddedWorkerTestHelper::OnResumeAfterDownload(embedded_worker_id);
+ } else {
+ SimulateWorkerThreadStarted(GetNextThreadId(), embedded_worker_id);
+ SimulateWorkerScriptEvaluated(embedded_worker_id, false);
+ }
}
// ServiceWorkerRegistration::Listener overrides
@@ -865,7 +897,6 @@ class UpdateJobTestHelper
}
void OnUpdateFound(ServiceWorkerRegistration* registration) override {
- ASSERT_FALSE(update_found_);
update_found_ = true;
}
@@ -882,6 +913,7 @@ class UpdateJobTestHelper
std::vector<AttributeChangeLogEntry> attribute_change_log_;
std::vector<StateChangeLogEntry> state_change_log_;
bool update_found_ = false;
+ bool force_start_worker_failure_ = false;
};
// Helper class for update tests that evicts the active version when the update
@@ -894,7 +926,8 @@ class EvictIncumbentVersionHelper : public UpdateJobTestHelper {
void OnStartWorker(int embedded_worker_id,
int64_t version_id,
const GURL& scope,
- const GURL& script) override {
+ const GURL& script,
+ bool pause_after_download) override {
ServiceWorkerVersion* version = context()->GetLiveVersion(version_id);
ServiceWorkerRegistration* registration =
context()->GetLiveRegistration(version->registration_id());
@@ -907,7 +940,7 @@ class EvictIncumbentVersionHelper : public UpdateJobTestHelper {
make_scoped_refptr(registration->active_version()));
}
UpdateJobTestHelper::OnStartWorker(embedded_worker_id, version_id, scope,
- script);
+ script, pause_after_download);
}
void OnRegistrationFailed(ServiceWorkerRegistration* registration) override {
@@ -965,16 +998,41 @@ TEST_F(ServiceWorkerJobTest, Update_BumpLastUpdateCheckTime) {
helper_.reset(update_helper);
scoped_refptr<ServiceWorkerRegistration> registration =
update_helper->SetupInitialRegistration(kNoChangeOrigin);
+ ASSERT_TRUE(registration.get());
- // Run an update where the last update check was less than 24 hours ago. The
- // check time shouldn't change, as we didn't bypass cache.
+ registration->AddListener(update_helper);
+
+ // Run an update where the script did not change and the network was not
+ // accessed. The check time should not be updated.
registration->set_last_update_check(kToday);
registration->active_version()->StartUpdate();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(kToday, registration->last_update_check());
+ EXPECT_FALSE(update_helper->update_found_);
+
+ // Run an update where the script did not change and the network was accessed.
+ // The check time should be updated.
+ registration->set_last_update_check(kYesterday);
+ registration->active_version()->StartUpdate();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_LT(kYesterday, registration->last_update_check());
+ EXPECT_FALSE(update_helper->update_found_);
+ registration->RemoveListener(update_helper);
+
+ registration = update_helper->SetupInitialRegistration(kNewVersionOrigin);
+ ASSERT_TRUE(registration.get());
- // Run an update where the last update check was over 24 hours ago. The
- // check time should change, as the cache was bypassed.
+ registration->AddListener(update_helper);
+
+ // Run an update where the script changed. The check time should be updated.
+ registration->set_last_update_check(kYesterday);
+ registration->active_version()->StartUpdate();
+ base::RunLoop().RunUntilIdle();
+ EXPECT_LT(kYesterday, registration->last_update_check());
+
+ // Run an update to a worker that loads successfully but fails to start up
+ // (script evaluation failure). The check time should be updated.
+ update_helper->set_force_start_worker_failure(true);
registration->set_last_update_check(kYesterday);
registration->active_version()->StartUpdate();
base::RunLoop().RunUntilIdle();
@@ -1370,7 +1428,8 @@ class EventCallbackHelper : public EmbeddedWorkerTestHelper {
void set_activate_event_result(blink::WebServiceWorkerEventResult result) {
activate_event_result_ = result;
}
-private:
+
+ private:
base::Closure install_callback_;
blink::WebServiceWorkerEventResult install_event_result_;
blink::WebServiceWorkerEventResult activate_event_result_;
@@ -1488,4 +1547,39 @@ TEST_F(ServiceWorkerJobTest, RemoveControlleeDuringInstall_RejectActivate) {
FindRegistrationForPattern(pattern, SERVICE_WORKER_OK);
}
+TEST_F(ServiceWorkerJobTest, Update_PauseAfterDownload) {
+ UpdateJobTestHelper* update_helper = new UpdateJobTestHelper;
+ helper_.reset(update_helper);
+ IPC::TestSink* sink = update_helper->ipc_sink();
+
+ // The initial version should not pause after download.
+ scoped_refptr<ServiceWorkerRegistration> registration =
+ update_helper->SetupInitialRegistration(kNewVersionOrigin);
+ {
+ const IPC::Message* start_msg =
+ sink->GetUniqueMessageMatching(EmbeddedWorkerMsg_StartWorker::ID);
+ ASSERT_TRUE(start_msg);
+ EmbeddedWorkerMsg_StartWorker::Param param;
+ EmbeddedWorkerMsg_StartWorker::Read(start_msg, &param);
+ EmbeddedWorkerMsg_StartWorker_Params start_params = base::get<0>(param);
+ EXPECT_FALSE(start_params.pause_after_download);
+ sink->ClearMessages();
+ }
+
+ // The updated version should pause after download.
+ registration->AddListener(update_helper);
+ registration->active_version()->StartUpdate();
+ base::RunLoop().RunUntilIdle();
+ {
+ const IPC::Message* start_msg =
+ sink->GetUniqueMessageMatching(EmbeddedWorkerMsg_StartWorker::ID);
+ ASSERT_TRUE(start_msg);
+ EmbeddedWorkerMsg_StartWorker::Param param;
+ EmbeddedWorkerMsg_StartWorker::Read(start_msg, &param);
+ EmbeddedWorkerMsg_StartWorker_Params start_params = base::get<0>(param);
+ EXPECT_TRUE(start_params.pause_after_download);
+ sink->ClearMessages();
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_metrics.cc b/chromium/content/browser/service_worker/service_worker_metrics.cc
index c2fc43b905f..3fdb74f5651 100644
--- a/chromium/content/browser/service_worker/service_worker_metrics.cc
+++ b/chromium/content/browser/service_worker/service_worker_metrics.cc
@@ -16,6 +16,35 @@ namespace content {
namespace {
+std::string StartSituationToSuffix(
+ ServiceWorkerMetrics::StartSituation situation) {
+ switch (situation) {
+ case ServiceWorkerMetrics::StartSituation::DURING_STARTUP:
+ return "_DuringStartup";
+ case ServiceWorkerMetrics::StartSituation::NEW_PROCESS:
+ return "_NewProcess";
+ case ServiceWorkerMetrics::StartSituation::EXISTING_PROCESS:
+ return "_ExistingProcess";
+ default:
+ NOTREACHED() << static_cast<int>(situation);
+ }
+ return "_Unknown";
+}
+
+// Use this for histograms with dynamically generated names, which
+// otherwise can't use the UMA_HISTOGRAM macro without code duplication.
+void RecordSuffixedTimeHistogram(const std::string& name,
+ const std::string& suffix,
+ base::TimeDelta sample) {
+ const std::string name_with_suffix = name + suffix;
+ // This unrolls UMA_HISTOGRAM_MEDIUM_TIMES.
+ base::HistogramBase* histogram_pointer = base::Histogram::FactoryTimeGet(
+ name_with_suffix, base::TimeDelta::FromMilliseconds(10),
+ base::TimeDelta::FromMinutes(3), 50,
+ base::HistogramBase::kUmaTargetedHistogramFlag);
+ histogram_pointer->AddTime(sample);
+}
+
void RecordURLMetricOnUI(const GURL& url) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
GetContentClient()->browser()->RecordURLMetric(
@@ -46,6 +75,44 @@ enum EventHandledRatioType {
} // namespace
+const char* ServiceWorkerMetrics::EventTypeToString(EventType event_type) {
+ switch (event_type) {
+ case EventType::ACTIVATE:
+ return "Activate";
+ case EventType::INSTALL:
+ return "Install";
+ case EventType::SYNC:
+ return "Sync";
+ case EventType::NOTIFICATION_CLICK:
+ return "Notification Click";
+ case EventType::NOTIFICATION_CLOSE:
+ return "Notification Close";
+ case EventType::PUSH:
+ return "Push";
+ case EventType::GEOFENCING:
+ return "Geofencing";
+ case EventType::MESSAGE:
+ return "Message";
+ case EventType::FETCH_MAIN_FRAME:
+ return "Fetch Main Frame";
+ case EventType::FETCH_SUB_FRAME:
+ return "Fetch Sub Frame";
+ case EventType::FETCH_SHARED_WORKER:
+ return "Fetch Shared Worker";
+ case EventType::FETCH_SUB_RESOURCE:
+ return "Fetch Subresource";
+ case EventType::UNKNOWN:
+ return "Unknown";
+ case EventType::FOREIGN_FETCH:
+ return "Foreign Fetch";
+ case EventType::DEPRECATED_FETCH:
+ case EventType::NUM_TYPES:
+ break;
+ }
+ NOTREACHED() << "Got unexpected event type: " << static_cast<int>(event_type);
+ return "error";
+}
+
bool ServiceWorkerMetrics::ShouldExcludeSiteFromHistogram(Site site) {
return site == ServiceWorkerMetrics::Site::NEW_TAB_PAGE;
}
@@ -118,22 +185,37 @@ void ServiceWorkerMetrics::CountControlledPageLoad(const GURL& url) {
void ServiceWorkerMetrics::RecordStartWorkerStatus(
ServiceWorkerStatusCode status,
+ EventType purpose,
bool is_installed) {
if (is_installed) {
UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Status", status,
SERVICE_WORKER_ERROR_MAX_VALUE);
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartWorker.Purpose",
+ static_cast<int>(purpose),
+ static_cast<int>(EventType::NUM_TYPES));
+ if (status == SERVICE_WORKER_ERROR_TIMEOUT) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "ServiceWorker.StartWorker.Timeout.StartPurpose",
+ static_cast<int>(purpose), static_cast<int>(EventType::NUM_TYPES));
+ }
} else {
UMA_HISTOGRAM_ENUMERATION("ServiceWorker.StartNewWorker.Status", status,
SERVICE_WORKER_ERROR_MAX_VALUE);
}
}
-void ServiceWorkerMetrics::RecordStartWorkerTime(const base::TimeDelta& time,
- bool is_installed) {
- if (is_installed)
- UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.StartWorker.Time", time);
- else
+void ServiceWorkerMetrics::RecordStartWorkerTime(
+ base::TimeDelta time,
+ bool is_installed,
+ StartSituation start_situation) {
+ if (is_installed) {
+ std::string name = "ServiceWorker.StartWorker.Time";
+ UMA_HISTOGRAM_MEDIUM_TIMES(name, time);
+ RecordSuffixedTimeHistogram(name, StartSituationToSuffix(start_situation),
+ time);
+ } else {
UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.StartNewWorker.Time", time);
+ }
}
void ServiceWorkerMetrics::RecordWorkerStopped(StopStatus status) {
@@ -142,7 +224,7 @@ void ServiceWorkerMetrics::RecordWorkerStopped(StopStatus status) {
static_cast<int>(StopStatus::NUM_TYPES));
}
-void ServiceWorkerMetrics::RecordStopWorkerTime(const base::TimeDelta& time) {
+void ServiceWorkerMetrics::RecordStopWorkerTime(base::TimeDelta time) {
UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.StopWorker.Time", time);
}
@@ -169,11 +251,24 @@ void ServiceWorkerMetrics::RecordEventHandledRatio(EventType event,
else if (handled_events == 0)
type = EVENT_HANDLED_NONE;
- // For now Fetch is the only type that is recorded.
- if (event != EventType::FETCH)
- return;
- UMA_HISTOGRAM_ENUMERATION("ServiceWorker.EventHandledRatioType.Fetch", type,
- NUM_EVENT_HANDLED_RATIO_TYPE);
+ // For now Fetch and Foreign Fetch are the only types that are recorded.
+ switch (event) {
+ case EventType::FETCH_MAIN_FRAME:
+ case EventType::FETCH_SUB_FRAME:
+ case EventType::FETCH_SHARED_WORKER:
+ case EventType::FETCH_SUB_RESOURCE:
+ UMA_HISTOGRAM_ENUMERATION("ServiceWorker.EventHandledRatioType.Fetch",
+ type, NUM_EVENT_HANDLED_RATIO_TYPE);
+ break;
+ case EventType::FOREIGN_FETCH:
+ UMA_HISTOGRAM_ENUMERATION(
+ "ServiceWorker.EventHandledRatioType.ForeignFetch", type,
+ NUM_EVENT_HANDLED_RATIO_TYPE);
+ break;
+ default:
+ // Do nothing.
+ break;
+ }
}
void ServiceWorkerMetrics::RecordEventTimeout(EventType event) {
@@ -183,7 +278,8 @@ void ServiceWorkerMetrics::RecordEventTimeout(EventType event) {
}
void ServiceWorkerMetrics::RecordEventDuration(EventType event,
- const base::TimeDelta& time) {
+ base::TimeDelta time,
+ bool was_handled) {
switch (event) {
case EventType::ACTIVATE:
UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.ActivateEvent.Time", time);
@@ -191,6 +287,27 @@ void ServiceWorkerMetrics::RecordEventDuration(EventType event,
case EventType::INSTALL:
UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.InstallEvent.Time", time);
break;
+ case EventType::FETCH_MAIN_FRAME:
+ case EventType::FETCH_SUB_FRAME:
+ case EventType::FETCH_SHARED_WORKER:
+ case EventType::FETCH_SUB_RESOURCE:
+ if (was_handled) {
+ UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.FetchEvent.HasResponse.Time",
+ time);
+ } else {
+ UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.FetchEvent.Fallback.Time",
+ time);
+ }
+ break;
+ case EventType::FOREIGN_FETCH:
+ if (was_handled) {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "ServiceWorker.ForeignFetchEvent.HasResponse.Time", time);
+ } else {
+ UMA_HISTOGRAM_MEDIUM_TIMES(
+ "ServiceWorker.ForeignFetchEvent.Fallback.Time", time);
+ }
+ break;
case EventType::SYNC:
UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.BackgroundSyncEvent.Time",
time);
@@ -199,17 +316,24 @@ void ServiceWorkerMetrics::RecordEventDuration(EventType event,
UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.NotificationClickEvent.Time",
time);
break;
+ case EventType::NOTIFICATION_CLOSE:
+ UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.NotificationCloseEvent.Time",
+ time);
+ break;
case EventType::PUSH:
UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.PushEvent.Time", time);
break;
+ case EventType::MESSAGE:
+ // TODO(nhiroki): Record event duration for Message event after
+ // ExtendableMessageEvent is enabled by default (crbug.com/543198).
+ break;
- // Event duration for fetch is recorded separately.
- case EventType::FETCH:
// For now event duration for these events is not recorded.
case EventType::GEOFENCING:
- case EventType::SERVICE_PORT_CONNECT:
break;
+ case EventType::DEPRECATED_FETCH:
+ case EventType::UNKNOWN:
case EventType::NUM_TYPES:
NOTREACHED() << "Invalid event type";
break;
@@ -228,23 +352,6 @@ void ServiceWorkerMetrics::RecordFetchEventStatus(
}
}
-void ServiceWorkerMetrics::RecordFetchEventTime(
- ServiceWorkerFetchEventResult result,
- const base::TimeDelta& time) {
- switch (result) {
- case ServiceWorkerFetchEventResult::
- SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK:
- UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.FetchEvent.Fallback.Time",
- time);
- break;
- case ServiceWorkerFetchEventResult::
- SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE:
- UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.FetchEvent.HasResponse.Time",
- time);
- break;
- }
-}
-
void ServiceWorkerMetrics::RecordURLRequestJobResult(
bool is_main_resource,
URLRequestJobResult result) {
@@ -276,9 +383,98 @@ void ServiceWorkerMetrics::RecordFallbackedRequestMode(FetchRequestMode mode) {
mode, FETCH_REQUEST_MODE_LAST + 1);
}
-void ServiceWorkerMetrics::RecordTimeBetweenEvents(
- const base::TimeDelta& time) {
+void ServiceWorkerMetrics::RecordTimeBetweenEvents(base::TimeDelta time) {
UMA_HISTOGRAM_MEDIUM_TIMES("ServiceWorker.TimeBetweenEvents", time);
}
+void ServiceWorkerMetrics::RecordProcessCreated(bool is_new_process) {
+ UMA_HISTOGRAM_BOOLEAN("EmbeddedWorkerInstance.ProcessCreated",
+ is_new_process);
+}
+
+void ServiceWorkerMetrics::RecordTimeToSendStartWorker(
+ base::TimeDelta duration,
+ StartSituation situation) {
+ std::string name = "EmbeddedWorkerInstance.Start.TimeToSendStartWorker";
+ UMA_HISTOGRAM_MEDIUM_TIMES(name, duration);
+ RecordSuffixedTimeHistogram(name, StartSituationToSuffix(situation),
+ duration);
+}
+
+void ServiceWorkerMetrics::RecordTimeToURLJob(base::TimeDelta duration,
+ StartSituation situation) {
+ std::string name = "EmbeddedWorkerInstance.Start.TimeToURLJob";
+ UMA_HISTOGRAM_MEDIUM_TIMES(name, duration);
+ RecordSuffixedTimeHistogram(name, StartSituationToSuffix(situation),
+ duration);
+}
+
+void ServiceWorkerMetrics::RecordTimeToLoad(base::TimeDelta duration,
+ LoadSource source,
+ StartSituation situation) {
+ std::string name;
+ switch (source) {
+ case LoadSource::NETWORK:
+ name = "EmbeddedWorkerInstance.Start.TimeToLoad.Network";
+ UMA_HISTOGRAM_MEDIUM_TIMES(name, duration);
+ RecordSuffixedTimeHistogram(name, StartSituationToSuffix(situation),
+ duration);
+ break;
+ case LoadSource::HTTP_CACHE:
+ name = "EmbeddedWorkerInstance.Start.TimeToLoad.HttpCache";
+ UMA_HISTOGRAM_MEDIUM_TIMES(name, duration);
+ RecordSuffixedTimeHistogram(name, StartSituationToSuffix(situation),
+ duration);
+ break;
+ case LoadSource::SERVICE_WORKER_STORAGE:
+ name = "EmbeddedWorkerInstance.Start.TimeToLoad.InstalledScript";
+ UMA_HISTOGRAM_MEDIUM_TIMES(name, duration);
+ RecordSuffixedTimeHistogram(name, StartSituationToSuffix(situation),
+ duration);
+ break;
+ default:
+ NOTREACHED() << static_cast<int>(source);
+ }
+}
+
+void ServiceWorkerMetrics::RecordTimeToStartThread(base::TimeDelta duration,
+ StartSituation situation) {
+ std::string name = "EmbeddedWorkerInstance.Start.TimeToStartThread";
+ UMA_HISTOGRAM_MEDIUM_TIMES(name, duration);
+ RecordSuffixedTimeHistogram(name, StartSituationToSuffix(situation),
+ duration);
+}
+
+void ServiceWorkerMetrics::RecordTimeToEvaluateScript(
+ base::TimeDelta duration,
+ StartSituation situation) {
+ std::string name = "EmbeddedWorkerInstance.Start.TimeToEvaluateScript";
+ UMA_HISTOGRAM_MEDIUM_TIMES(name, duration);
+ RecordSuffixedTimeHistogram(name, StartSituationToSuffix(situation),
+ duration);
+}
+
+const char* ServiceWorkerMetrics::LoadSourceToString(LoadSource source) {
+ switch (source) {
+ case LoadSource::NETWORK:
+ return "Network";
+ case LoadSource::HTTP_CACHE:
+ return "HTTP cache";
+ case LoadSource::SERVICE_WORKER_STORAGE:
+ return "Service worker storage";
+ }
+ NOTREACHED() << static_cast<int>(source);
+ return nullptr;
+}
+
+ServiceWorkerMetrics::StartSituation ServiceWorkerMetrics::GetStartSituation(
+ bool is_browser_startup_complete,
+ bool is_new_process) {
+ if (!is_browser_startup_complete)
+ return StartSituation::DURING_STARTUP;
+ if (is_new_process)
+ return StartSituation::NEW_PROCESS;
+ return StartSituation::EXISTING_PROCESS;
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_metrics.h b/chromium/content/browser/service_worker/service_worker_metrics.h
index 83dfb2ac5f8..e14d1ad3789 100644
--- a/chromium/content/browser/service_worker/service_worker_metrics.h
+++ b/chromium/content/browser/service_worker/service_worker_metrics.h
@@ -18,6 +18,7 @@ namespace content {
class ServiceWorkerMetrics {
public:
+ // Used for UMA. Append-only.
enum ReadResponseResult {
READ_OK,
READ_HEADERS_ERROR,
@@ -25,6 +26,7 @@ class ServiceWorkerMetrics {
NUM_READ_RESPONSE_RESULT_TYPES,
};
+ // Used for UMA. Append-only.
enum WriteResponseResult {
WRITE_OK,
WRITE_HEADERS_ERROR,
@@ -32,6 +34,7 @@ class ServiceWorkerMetrics {
NUM_WRITE_RESPONSE_RESULT_TYPES,
};
+ // Used for UMA. Append-only.
enum DeleteAndStartOverResult {
DELETE_OK,
DELETE_DATABASE_ERROR,
@@ -39,6 +42,7 @@ class ServiceWorkerMetrics {
NUM_DELETE_AND_START_OVER_RESULT_TYPES,
};
+ // Used for UMA. Append-only.
enum URLRequestJobResult {
REQUEST_JOB_FALLBACK_RESPONSE,
REQUEST_JOB_FALLBACK_FOR_CORS,
@@ -74,22 +78,43 @@ class ServiceWorkerMetrics {
// Used for UMA. Append-only.
enum class EventType {
- ACTIVATE,
- INSTALL,
- FETCH,
- SYNC,
- NOTIFICATION_CLICK,
- PUSH,
- GEOFENCING,
- SERVICE_PORT_CONNECT,
+ ACTIVATE = 0,
+ INSTALL = 1,
+ DEPRECATED_FETCH = 2, // Deprecated, use a more specific FETCH_ type.
+ SYNC = 3,
+ NOTIFICATION_CLICK = 4,
+ PUSH = 5,
+ GEOFENCING = 6,
+ // SERVICE_PORT_CONNECT = 7,
+ MESSAGE = 8,
+ NOTIFICATION_CLOSE = 9,
+ FETCH_MAIN_FRAME = 10,
+ FETCH_SUB_FRAME = 11,
+ FETCH_SHARED_WORKER = 12,
+ FETCH_SUB_RESOURCE = 13,
+ UNKNOWN = 14, // Used when event type is not known.
+ FOREIGN_FETCH = 15,
// Add new events to record here.
-
NUM_TYPES
};
// Used for UMA. Append only.
enum class Site { OTHER, NEW_TAB_PAGE, NUM_TYPES };
+ // Not used for UMA.
+ enum class StartSituation {
+ UNKNOWN,
+ DURING_STARTUP,
+ EXISTING_PROCESS,
+ NEW_PROCESS
+ };
+
+ // Not used for UMA.
+ enum class LoadSource { NETWORK, HTTP_CACHE, SERVICE_WORKER_STORAGE };
+
+ // Converts an event type to a string. Used for tracing.
+ static const char* EventTypeToString(EventType event_type);
+
// Excludes NTP scope from UMA for now as it tends to dominate the stats and
// makes the results largely skewed. Some metrics don't follow this policy
// and hence don't call this function.
@@ -117,18 +142,20 @@ class ServiceWorkerMetrics {
// Records the result of trying to start a worker. |is_installed| indicates
// whether the version has been installed.
static void RecordStartWorkerStatus(ServiceWorkerStatusCode status,
+ EventType purpose,
bool is_installed);
// Records the time taken to successfully start a worker. |is_installed|
// indicates whether the version has been installed.
- static void RecordStartWorkerTime(const base::TimeDelta& time,
- bool is_installed);
+ static void RecordStartWorkerTime(base::TimeDelta time,
+ bool is_installed,
+ StartSituation start_situation);
// Records the result of trying to stop a worker.
static void RecordWorkerStopped(StopStatus status);
// Records the time taken to successfully stop a worker.
- static void RecordStopWorkerTime(const base::TimeDelta& time);
+ static void RecordStopWorkerTime(base::TimeDelta time);
static void RecordActivateEventStatus(ServiceWorkerStatusCode status);
static void RecordInstallEventStatus(ServiceWorkerStatusCode status);
@@ -143,17 +170,14 @@ class ServiceWorkerMetrics {
static void RecordEventTimeout(EventType event);
// Records the amount of time spent handling an event.
- static void RecordEventDuration(EventType event, const base::TimeDelta& time);
+ static void RecordEventDuration(EventType event,
+ base::TimeDelta time,
+ bool was_handled);
// Records the result of dispatching a fetch event to a service worker.
static void RecordFetchEventStatus(bool is_main_resource,
ServiceWorkerStatusCode status);
- // Records the amount of time spent handling a fetch event with the given
- // result.
- static void RecordFetchEventTime(ServiceWorkerFetchEventResult result,
- const base::TimeDelta& time);
-
// Records result of a ServiceWorkerURLRequestJob that was forwarded to
// the service worker.
static void RecordURLRequestJobResult(bool is_main_resource,
@@ -171,7 +195,25 @@ class ServiceWorkerMetrics {
// Called at the beginning of each ServiceWorkerVersion::Dispatch*Event
// function. Records the time elapsed since idle (generally the time since the
// previous event ended).
- static void RecordTimeBetweenEvents(const base::TimeDelta& time);
+ static void RecordTimeBetweenEvents(base::TimeDelta time);
+
+ // The following record steps of EmbeddedWorkerInstance's start sequence.
+ static void RecordProcessCreated(bool is_new_process);
+ static void RecordTimeToSendStartWorker(base::TimeDelta duration,
+ StartSituation start_situation);
+ static void RecordTimeToURLJob(base::TimeDelta duration,
+ StartSituation start_situation);
+ static void RecordTimeToLoad(base::TimeDelta duration,
+ LoadSource source,
+ StartSituation start_situation);
+ static void RecordTimeToStartThread(base::TimeDelta duration,
+ StartSituation start_situation);
+ static void RecordTimeToEvaluateScript(base::TimeDelta duration,
+ StartSituation start_situation);
+
+ static const char* LoadSourceToString(LoadSource source);
+ static StartSituation GetStartSituation(bool is_browser_startup_complete,
+ bool is_new_process);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(ServiceWorkerMetrics);
diff --git a/chromium/content/browser/service_worker/service_worker_process_manager.cc b/chromium/content/browser/service_worker/service_worker_process_manager.cc
index 4b559edce8a..74253b59d57 100644
--- a/chromium/content/browser/service_worker/service_worker_process_manager.cc
+++ b/chromium/content/browser/service_worker/service_worker_process_manager.cc
@@ -11,9 +11,12 @@
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
+#include "content/common/service_worker/embedded_worker_settings.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/site_instance.h"
#include "content/public/common/child_process_host.h"
+#include "content/public/common/content_client.h"
#include "url/gurl.h"
namespace content {
@@ -40,6 +43,9 @@ ServiceWorkerProcessManager::ProcessInfo::ProcessInfo(int process_id)
: process_id(process_id) {
}
+ServiceWorkerProcessManager::ProcessInfo::ProcessInfo(
+ const ProcessInfo& other) = default;
+
ServiceWorkerProcessManager::ProcessInfo::~ProcessInfo() {
}
@@ -47,6 +53,7 @@ ServiceWorkerProcessManager::ServiceWorkerProcessManager(
BrowserContext* browser_context)
: browser_context_(browser_context),
process_id_for_test_(ChildProcessHost::kInvalidUniqueID),
+ new_process_id_for_test_(ChildProcessHost::kInvalidUniqueID),
weak_this_factory_(this) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
weak_this_ = weak_this_factory_.GetWeakPtr();
@@ -132,29 +139,36 @@ void ServiceWorkerProcessManager::AllocateWorkerProcess(
int embedded_worker_id,
const GURL& pattern,
const GURL& script_url,
+ bool can_use_existing_process,
const base::Callback<void(ServiceWorkerStatusCode,
int process_id,
- bool is_new_process)>& callback) {
+ bool is_new_process,
+ const EmbeddedWorkerSettings&)>& callback) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
BrowserThread::PostTask(
- BrowserThread::UI,
- FROM_HERE,
+ BrowserThread::UI, FROM_HERE,
base::Bind(&ServiceWorkerProcessManager::AllocateWorkerProcess,
- weak_this_,
- embedded_worker_id,
- pattern,
- script_url,
- callback));
+ weak_this_, embedded_worker_id, pattern, script_url,
+ can_use_existing_process, callback));
return;
}
+ // This |EmbeddedWorkerSettings| only populates |data_saver_enabled|,
+ // but in general, this function will populate settings from prefs, while
+ // the caller will be responsible for populating settings from other sources,
+ // such as command line switches.
+ EmbeddedWorkerSettings settings;
+ settings.data_saver_enabled =
+ GetContentClient()->browser()->IsDataSaverEnabled(browser_context_);
+
if (process_id_for_test_ != ChildProcessHost::kInvalidUniqueID) {
// Let tests specify the returned process ID. Note: We may need to be able
// to specify the error code too.
- BrowserThread::PostTask(
- BrowserThread::IO, FROM_HERE,
- base::Bind(callback, SERVICE_WORKER_OK, process_id_for_test_,
- false /* is_new_process */));
+ int result = can_use_existing_process ? process_id_for_test_
+ : new_process_id_for_test_;
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(callback, SERVICE_WORKER_OK, result,
+ false /* is_new_process */, settings));
return;
}
@@ -162,7 +176,7 @@ void ServiceWorkerProcessManager::AllocateWorkerProcess(
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(callback, SERVICE_WORKER_ERROR_ABORT,
ChildProcessHost::kInvalidUniqueID,
- false /* is_new_process */));
+ false /* is_new_process */, settings));
return;
}
@@ -171,15 +185,18 @@ void ServiceWorkerProcessManager::AllocateWorkerProcess(
CHECK(!ContainsKey(instance_info_, embedded_worker_id))
<< embedded_worker_id << " already has a process allocated";
- int process_id = FindAvailableProcess(pattern);
- if (process_id != ChildProcessHost::kInvalidUniqueID) {
- RenderProcessHost::FromID(process_id)->IncrementWorkerRefCount();
- instance_info_.insert(
- std::make_pair(embedded_worker_id, ProcessInfo(process_id)));
- BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
- base::Bind(callback, SERVICE_WORKER_OK, process_id,
- false /* is_new_process */));
- return;
+ if (can_use_existing_process) {
+ int process_id = FindAvailableProcess(pattern);
+ if (process_id != ChildProcessHost::kInvalidUniqueID) {
+ RenderProcessHost::FromID(process_id)->IncrementWorkerRefCount();
+ instance_info_.insert(
+ std::make_pair(embedded_worker_id, ProcessInfo(process_id)));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(callback, SERVICE_WORKER_OK, process_id,
+ false /* is_new_process */, settings));
+ return;
+ }
}
// No existing processes available; start a new one.
@@ -196,7 +213,7 @@ void ServiceWorkerProcessManager::AllocateWorkerProcess(
BrowserThread::IO, FROM_HERE,
base::Bind(callback, SERVICE_WORKER_ERROR_PROCESS_NOT_FOUND,
ChildProcessHost::kInvalidUniqueID,
- false /* is_new_process */));
+ false /* is_new_process */, settings));
return;
}
@@ -206,7 +223,7 @@ void ServiceWorkerProcessManager::AllocateWorkerProcess(
rph->IncrementWorkerRefCount();
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(callback, SERVICE_WORKER_OK, rph->GetID(),
- true /* is_new_process */));
+ true /* is_new_process */, settings));
}
void ServiceWorkerProcessManager::ReleaseWorkerProcess(int embedded_worker_id) {
diff --git a/chromium/content/browser/service_worker/service_worker_process_manager.h b/chromium/content/browser/service_worker/service_worker_process_manager.h
index 443aafbd017..465ed5a8fea 100644
--- a/chromium/content/browser/service_worker/service_worker_process_manager.h
+++ b/chromium/content/browser/service_worker/service_worker_process_manager.h
@@ -20,6 +20,7 @@ class GURL;
namespace content {
class BrowserContext;
+struct EmbeddedWorkerSettings;
class SiteInstance;
// Interacts with the UI thread to keep RenderProcessHosts alive while the
@@ -49,9 +50,11 @@ class CONTENT_EXPORT ServiceWorkerProcessManager {
int embedded_worker_id,
const GURL& pattern,
const GURL& script_url,
+ bool can_use_existing_process,
const base::Callback<void(ServiceWorkerStatusCode,
int process_id,
- bool is_new_process)>& callback);
+ bool is_new_process,
+ const EmbeddedWorkerSettings&)>& callback);
// Drops a reference to a process that was running a Service Worker, and its
// SiteInstance. This must match a call to AllocateWorkerProcess.
@@ -66,6 +69,11 @@ class CONTENT_EXPORT ServiceWorkerProcessManager {
process_id_for_test_ = process_id;
}
+ // Sets the process ID to be used for tests that force creating a new process.
+ void SetNewProcessIdForTest(int process_id) {
+ new_process_id_for_test_ = process_id;
+ }
+
// Adds/removes process reference for the |pattern|, the process with highest
// references count will be chosen to start a worker.
void AddProcessReferenceToPattern(const GURL& pattern, int process_id);
@@ -87,6 +95,7 @@ class CONTENT_EXPORT ServiceWorkerProcessManager {
struct ProcessInfo {
explicit ProcessInfo(const scoped_refptr<SiteInstance>& site_instance);
explicit ProcessInfo(int process_id);
+ ProcessInfo(const ProcessInfo& other);
~ProcessInfo();
// Stores the SiteInstance the Worker lives inside. This needs to outlive
@@ -132,6 +141,7 @@ class CONTENT_EXPORT ServiceWorkerProcessManager {
// In unit tests, this will be returned as the process for all
// EmbeddedWorkerInstances.
int process_id_for_test_;
+ int new_process_id_for_test_;
// Candidate processes info for each pattern, should be accessed on the
// UI thread.
diff --git a/chromium/content/browser/service_worker/service_worker_process_manager_unittest.cc b/chromium/content/browser/service_worker/service_worker_process_manager_unittest.cc
index 384f996b862..98ded5986e9 100644
--- a/chromium/content/browser/service_worker/service_worker_process_manager_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_process_manager_unittest.cc
@@ -6,6 +6,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "content/browser/service_worker/service_worker_process_manager.h"
+#include "content/common/service_worker/embedded_worker_settings.h"
#include "content/public/common/child_process_host.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/test_browser_context.h"
@@ -24,7 +25,8 @@ void DidAllocateWorkerProcess(const base::Closure& quit_closure,
bool* is_new_process_out,
ServiceWorkerStatusCode status,
int process_id,
- bool is_new_process) {
+ bool is_new_process,
+ const EmbeddedWorkerSettings& settings) {
*status_out = status;
*process_id_out = process_id;
*is_new_process_out = is_new_process;
@@ -143,6 +145,7 @@ TEST_F(ServiceWorkerProcessManagerTest,
bool is_new_process = true;
process_manager_->AllocateWorkerProcess(
kEmbeddedWorkerId1, scope1, script_url_,
+ true /* can_use_existing_process */,
base::Bind(&DidAllocateWorkerProcess, run_loop1.QuitClosure(), &status,
&process_id, &is_new_process));
run_loop1.Run();
@@ -167,6 +170,7 @@ TEST_F(ServiceWorkerProcessManagerTest,
is_new_process = true;
process_manager_->AllocateWorkerProcess(
kEmbeddedWorkerId2, scope1, script_url_,
+ true /* can_use_existing_process */,
base::Bind(&DidAllocateWorkerProcess, run_loop2.QuitClosure(), &status,
&process_id, &is_new_process));
run_loop2.Run();
@@ -182,7 +186,7 @@ TEST_F(ServiceWorkerProcessManagerTest,
ASSERT_TRUE(found != instance_info.end());
EXPECT_EQ(host1->GetID(), found->second.process_id);
- // (3) Allocate a process to the other worker whose scope is different from
+ // (3) Allocate a process to a third worker whose scope is different from
// other workers.
base::RunLoop run_loop3;
status = SERVICE_WORKER_ERROR_MAX_VALUE;
@@ -190,6 +194,7 @@ TEST_F(ServiceWorkerProcessManagerTest,
is_new_process = true;
process_manager_->AllocateWorkerProcess(
kEmbeddedWorkerId3, scope2, script_url_,
+ true /* can_use_existing_process */,
base::Bind(&DidAllocateWorkerProcess, run_loop3.QuitClosure(), &status,
&process_id, &is_new_process));
run_loop3.Run();
@@ -234,7 +239,7 @@ TEST_F(ServiceWorkerProcessManagerTest, AllocateWorkerProcess_InShutdown) {
int process_id = -10;
bool is_new_process = true;
process_manager_->AllocateWorkerProcess(
- 1, pattern_, script_url_,
+ 1, pattern_, script_url_, true /* can_use_existing_process */,
base::Bind(&DidAllocateWorkerProcess, run_loop.QuitClosure(), &status,
&process_id, &is_new_process));
run_loop.Run();
diff --git a/chromium/content/browser/service_worker/service_worker_provider_host.cc b/chromium/content/browser/service_worker/service_worker_provider_host.cc
index 1d79f5290b0..0c8c35d8f9b 100644
--- a/chromium/content/browser/service_worker/service_worker_provider_host.cc
+++ b/chromium/content/browser/service_worker/service_worker_provider_host.cc
@@ -9,9 +9,6 @@
#include "base/guid.h"
#include "base/stl_util.h"
#include "base/time/time.h"
-#include "content/browser/frame_host/frame_tree.h"
-#include "content/browser/frame_host/frame_tree_node.h"
-#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/message_port_message_filter.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_request_handler.h"
@@ -20,14 +17,10 @@
#include "content/browser/service_worker/service_worker_handle.h"
#include "content/browser/service_worker/service_worker_registration_handle.h"
#include "content/browser/service_worker/service_worker_version.h"
-#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/resource_request_body.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/common/service_worker/service_worker_utils.h"
-#include "content/public/browser/render_frame_host.h"
-#include "content/public/browser/render_widget_host_view.h"
-#include "content/public/browser/web_contents.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/child_process_host.h"
@@ -35,32 +28,6 @@ namespace content {
namespace {
-ServiceWorkerClientInfo FocusOnUIThread(int render_process_id,
- int render_frame_id) {
- RenderFrameHostImpl* render_frame_host =
- RenderFrameHostImpl::FromID(render_process_id, render_frame_id);
- WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
- WebContents::FromRenderFrameHost(render_frame_host));
-
- if (!render_frame_host || !web_contents)
- return ServiceWorkerClientInfo();
-
- FrameTreeNode* frame_tree_node = render_frame_host->frame_tree_node();
-
- // Focus the frame in the frame tree node, in case it has changed.
- frame_tree_node->frame_tree()->SetFocusedFrame(
- frame_tree_node, render_frame_host->GetSiteInstance());
-
- // Focus the frame's view to make sure the frame is now considered as focused.
- render_frame_host->GetView()->Focus();
-
- // Move the web contents to the foreground.
- web_contents->Activate();
-
- return ServiceWorkerProviderHost::GetWindowClientInfoOnUI(render_process_id,
- render_frame_id);
-}
-
// PlzNavigate
// Next ServiceWorkerProviderHost ID for navigations, starts at -2 and keeps
// going down.
@@ -218,25 +185,21 @@ void ServiceWorkerProviderHost::SetControllerVersionAttribute(
notify_controllerchange));
}
-bool ServiceWorkerProviderHost::SetHostedVersionId(int64_t version_id) {
- if (!context_)
- return true; // System is shutting down.
+bool ServiceWorkerProviderHost::SetHostedVersion(
+ ServiceWorkerVersion* version) {
+ // TODO(falken): Unclear why we check active_version. Should this just check
+ // that IsProviderForClient() is false?
if (active_version())
return false; // Unexpected bad message.
- ServiceWorkerVersion* live_version = context_->GetLiveVersion(version_id);
- if (!live_version)
- return true; // Was deleted before it got started.
-
- ServiceWorkerVersionInfo info = live_version->GetInfo();
- if (info.running_status != ServiceWorkerVersion::STARTING ||
- info.process_id != render_process_id_) {
+ DCHECK_EQ(ServiceWorkerVersion::STARTING, version->running_status());
+ if (version->embedded_worker()->process_id() != render_process_id_) {
// If we aren't trying to start this version in our process
// something is amiss.
return false;
}
- running_hosted_version_ = live_version;
+ running_hosted_version_ = version;
return true;
}
@@ -433,50 +396,6 @@ void ServiceWorkerProviderHost::PostMessageToClient(
Send(new ServiceWorkerMsg_MessageToDocument(params));
}
-void ServiceWorkerProviderHost::Focus(const GetClientInfoCallback& callback) {
- if (provider_type_ != SERVICE_WORKER_PROVIDER_FOR_WINDOW) {
- callback.Run(ServiceWorkerClientInfo());
- return;
- }
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&FocusOnUIThread, render_process_id_, route_id_), callback);
-}
-
-void ServiceWorkerProviderHost::GetWindowClientInfo(
- const GetClientInfoCallback& callback) const {
- if (provider_type_ != SERVICE_WORKER_PROVIDER_FOR_WINDOW) {
- callback.Run(ServiceWorkerClientInfo());
- return;
- }
- BrowserThread::PostTaskAndReplyWithResult(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&ServiceWorkerProviderHost::GetWindowClientInfoOnUI,
- render_process_id_, route_id_),
- callback);
-}
-
-// static
-ServiceWorkerClientInfo ServiceWorkerProviderHost::GetWindowClientInfoOnUI(
- int render_process_id,
- int render_frame_id) {
- RenderFrameHostImpl* render_frame_host =
- RenderFrameHostImpl::FromID(render_process_id, render_frame_id);
- if (!render_frame_host)
- return ServiceWorkerClientInfo();
-
- // TODO(mlamouri,michaeln): it is possible to end up collecting information
- // for a frame that is actually being navigated and isn't exactly what we are
- // expecting.
- return ServiceWorkerClientInfo(
- render_frame_host->GetVisibilityState(), render_frame_host->IsFocused(),
- render_frame_host->GetLastCommittedURL(),
- render_frame_host->GetParent() ? REQUEST_CONTEXT_FRAME_TYPE_NESTED
- : REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL,
- render_frame_host->frame_tree_node()->last_focus_time(),
- blink::WebServiceWorkerClientTypeWindow);
-}
-
void ServiceWorkerProviderHost::AddScopedProcessReferenceToPattern(
const GURL& pattern) {
associated_patterns_.push_back(pattern);
@@ -592,12 +511,11 @@ void ServiceWorkerProviderHost::SendSetVersionAttributesMessage(
return;
if (!IsReadyToSendMessages()) {
- queued_events_.push_back(
- base::Bind(&ServiceWorkerProviderHost::SendSetVersionAttributesMessage,
- AsWeakPtr(), registration_handle_id, changed_mask,
- make_scoped_refptr(installing_version),
- make_scoped_refptr(waiting_version),
- make_scoped_refptr(active_version)));
+ queued_events_.push_back(base::Bind(
+ &ServiceWorkerProviderHost::SendSetVersionAttributesMessage,
+ AsWeakPtr(), registration_handle_id, changed_mask,
+ base::RetainedRef(installing_version),
+ base::RetainedRef(waiting_version), base::RetainedRef(active_version)));
return;
}
diff --git a/chromium/content/browser/service_worker/service_worker_provider_host.h b/chromium/content/browser/service_worker/service_worker_provider_host.h
index 2748e293810..3f1d247b210 100644
--- a/chromium/content/browser/service_worker/service_worker_provider_host.h
+++ b/chromium/content/browser/service_worker/service_worker_provider_host.h
@@ -51,8 +51,6 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
: public NON_EXPORTED_BASE(ServiceWorkerRegistration::Listener),
public base::SupportsWeakPtr<ServiceWorkerProviderHost> {
public:
- using GetClientInfoCallback =
- base::Callback<void(const ServiceWorkerClientInfo&)>;
using GetRegistrationForReadyCallback =
base::Callback<void(ServiceWorkerRegistration* reigstration)>;
@@ -133,9 +131,9 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
// Clears the associated registration and stop listening to it.
void DisassociateRegistration();
- // Returns false if the version is not in the expected STARTING in our
- // process state. That would be indicative of a bad IPC message.
- bool SetHostedVersionId(int64_t versions_id);
+ // Returns false if we have an active version or |version| is using a
+ // different process. That would be indicative of a bad IPC message.
+ bool SetHostedVersion(ServiceWorkerVersion* version);
// Returns a handler for a request, the handler may return NULL if
// the request doesn't require special handling.
@@ -175,20 +173,6 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
const base::string16& message,
const std::vector<TransferredMessagePort>& sent_message_ports);
- // Activates the WebContents associated with
- // { render_process_id_, route_id_ }.
- // Runs the |callback| with the updated ServiceWorkerClientInfo in parameter.
- void Focus(const GetClientInfoCallback& callback);
-
- // Asks the renderer to send back the document information.
- void GetWindowClientInfo(const GetClientInfoCallback& callback) const;
-
- // Same as above but has to be called from the UI thread.
- // It is taking the process and frame ids in parameter because |this| is meant
- // to live on the IO thread.
- static ServiceWorkerClientInfo GetWindowClientInfoOnUI(int render_process_id,
- int render_frame_id);
-
// Adds reference of this host's process to the |pattern|, the reference will
// be removed in destructor.
void AddScopedProcessReferenceToPattern(const GURL& pattern);
@@ -264,12 +248,18 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
Update_ElongatedScript);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerWriteToCacheJobTest,
Update_EmptyScript);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDispatcherHostTest,
+ DispatchExtendableMessageEvent);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerDispatcherHostTest,
+ DispatchExtendableMessageEvent_Fail);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
UpdateBefore24Hours);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
UpdateAfter24Hours);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
UpdateForceBypassCache);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
+ ServiceWorkerDataRequestAnnotation);
struct OneShotGetReadyCallback {
GetRegistrationForReadyCallback callback;
diff --git a/chromium/content/browser/service_worker/service_worker_read_from_cache_job.cc b/chromium/content/browser/service_worker/service_worker_read_from_cache_job.cc
index bd9844b327e..24f84342fed 100644
--- a/chromium/content/browser/service_worker/service_worker_read_from_cache_job.cc
+++ b/chromium/content/browser/service_worker/service_worker_read_from_cache_job.cc
@@ -139,7 +139,6 @@ void ServiceWorkerReadFromCacheJob::StartAsync() {
http_info_io_buffer_.get(),
base::Bind(&ServiceWorkerReadFromCacheJob::OnReadInfoComplete,
weak_factory_.GetWeakPtr()));
- SetStatus(net::URLRequestStatus(net::URLRequestStatus::IO_PENDING, 0));
}
const net::HttpResponseInfo* ServiceWorkerReadFromCacheJob::http_info() const {
@@ -161,7 +160,6 @@ void ServiceWorkerReadFromCacheJob::OnReadInfoComplete(int result) {
return;
}
DCHECK_GE(result, 0);
- SetStatus(net::URLRequestStatus()); // Clear the IO_PENDING status
http_info_.reset(http_info_io_buffer_->http_info.release());
if (is_range_request())
SetupRangeResponse(http_info_io_buffer_->response_data_size);
diff --git a/chromium/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc b/chromium/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc
index aa7508b7520..6cb1cbd28b4 100644
--- a/chromium/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_read_from_cache_job_unittest.cc
@@ -7,6 +7,7 @@
#include <stdint.h>
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "content/browser/fileapi/mock_url_request_delegate.h"
#include "content/browser/service_worker/embedded_worker_test_helper.h"
@@ -20,6 +21,7 @@
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_job_factory_impl.h"
#include "net/url_request/url_request_status.h"
+#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -59,16 +61,23 @@ class ServiceWorkerReadFromCacheJobTest : public testing::Test {
kResourceSize),
imported_script_(kImportedScriptResourceId,
GURL("http://example.com/imported.js"),
- kResourceSize) {}
+ kResourceSize),
+ test_job_interceptor_(nullptr) {}
~ServiceWorkerReadFromCacheJobTest() override {}
void SetUp() override {
helper_.reset(new EmbeddedWorkerTestHelper(base::FilePath()));
InitializeStorage();
- url_request_context_.reset(new net::URLRequestContext);
- url_request_job_factory_.reset(new net::URLRequestJobFactoryImpl);
- url_request_context_->set_job_factory(url_request_job_factory_.get());
+ url_request_context_.reset(new net::TestURLRequestContext(true));
+
+ // The |test_job_factory_| takes ownership of the interceptor.
+ test_job_interceptor_ = new net::TestJobInterceptor();
+ EXPECT_TRUE(test_job_factory_.SetProtocolHandler(
+ url::kHttpScheme, make_scoped_ptr(test_job_interceptor_)));
+ url_request_context_->set_job_factory(&test_job_factory_);
+
+ url_request_context_->Init();
}
void InitializeStorage() {
@@ -145,9 +154,8 @@ class ServiceWorkerReadFromCacheJobTest : public testing::Test {
return status;
}
- void StartAndWaitForJob(
- const scoped_ptr<ServiceWorkerReadFromCacheJob>& job) {
- job->Start();
+ void StartAndWaitForRequest(net::URLRequest* request) {
+ request->Start();
// MockURLRequestDelegate quits the loop when the request is completed.
base::RunLoop().RunUntilIdle();
}
@@ -168,8 +176,11 @@ class ServiceWorkerReadFromCacheJobTest : public testing::Test {
ServiceWorkerDatabase::ResourceRecord main_script_;
ServiceWorkerDatabase::ResourceRecord imported_script_;
- scoped_ptr<net::URLRequestContext> url_request_context_;
- scoped_ptr<net::URLRequestJobFactoryImpl> url_request_job_factory_;
+ // |test_job_interceptor_| is owned by |test_job_factory_|.
+ net::TestJobInterceptor* test_job_interceptor_;
+ net::URLRequestJobFactoryImpl test_job_factory_;
+
+ scoped_ptr<net::TestURLRequestContext> url_request_context_;
MockURLRequestDelegate delegate_;
};
@@ -177,12 +188,12 @@ TEST_F(ServiceWorkerReadFromCacheJobTest, ReadMainScript) {
// Read the main script from the diskcache.
scoped_ptr<net::URLRequest> request = url_request_context_->CreateRequest(
main_script_.url, net::DEFAULT_PRIORITY, &delegate_);
- scoped_ptr<ServiceWorkerReadFromCacheJob> job(
- new ServiceWorkerReadFromCacheJob(
+ test_job_interceptor_->set_main_intercept_job(
+ make_scoped_ptr(new ServiceWorkerReadFromCacheJob(
request.get(), nullptr /* NetworkDelegate */,
RESOURCE_TYPE_SERVICE_WORKER, context()->AsWeakPtr(), version_,
- main_script_.resource_id));
- StartAndWaitForJob(job);
+ main_script_.resource_id)));
+ StartAndWaitForRequest(request.get());
EXPECT_EQ(net::URLRequestStatus::SUCCESS, request->status().status());
EXPECT_EQ(0, request->status().error());
@@ -194,11 +205,11 @@ TEST_F(ServiceWorkerReadFromCacheJobTest, ReadImportedScript) {
// Read the imported script from the diskcache.
scoped_ptr<net::URLRequest> request = url_request_context_->CreateRequest(
imported_script_.url, net::DEFAULT_PRIORITY, &delegate_);
- scoped_ptr<ServiceWorkerReadFromCacheJob> job(
- new ServiceWorkerReadFromCacheJob(
+ test_job_interceptor_->set_main_intercept_job(
+ make_scoped_ptr(new ServiceWorkerReadFromCacheJob(
request.get(), nullptr /* NetworkDelegate */, RESOURCE_TYPE_SCRIPT,
- context()->AsWeakPtr(), version_, imported_script_.resource_id));
- StartAndWaitForJob(job);
+ context()->AsWeakPtr(), version_, imported_script_.resource_id)));
+ StartAndWaitForRequest(request.get());
EXPECT_EQ(net::URLRequestStatus::SUCCESS, request->status().status());
EXPECT_EQ(0, request->status().error());
@@ -214,12 +225,12 @@ TEST_F(ServiceWorkerReadFromCacheJobTest, ResourceNotFound) {
GURL("http://example.com/nonexistent"), net::DEFAULT_PRIORITY,
&delegate_);
const int64_t kNonexistentResourceId = 100;
- scoped_ptr<ServiceWorkerReadFromCacheJob> job(
- new ServiceWorkerReadFromCacheJob(
+ test_job_interceptor_->set_main_intercept_job(
+ make_scoped_ptr(new ServiceWorkerReadFromCacheJob(
request.get(), nullptr /* NetworkDelegate */,
RESOURCE_TYPE_SERVICE_WORKER, context()->AsWeakPtr(), version_,
- kNonexistentResourceId));
- StartAndWaitForJob(job);
+ kNonexistentResourceId)));
+ StartAndWaitForRequest(request.get());
EXPECT_EQ(net::URLRequestStatus::FAILED, request->status().status());
EXPECT_EQ(net::ERR_CACHE_MISS, request->status().error());
diff --git a/chromium/content/browser/service_worker/service_worker_register_job.cc b/chromium/content/browser/service_worker/service_worker_register_job.cc
index 69f5acdcb9c..0dfb0d5e64d 100644
--- a/chromium/content/browser/service_worker/service_worker_register_job.cc
+++ b/chromium/content/browser/service_worker/service_worker_register_job.cc
@@ -6,8 +6,6 @@
#include <stdint.h>
-#include <vector>
-
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
@@ -16,6 +14,8 @@
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_storage.h"
+#include "content/browser/service_worker/service_worker_write_to_cache_job.h"
+#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_thread.h"
@@ -87,7 +87,7 @@ void ServiceWorkerRegisterJob::AddCallback(
}
RunSoon(base::Bind(callback, promise_resolved_status_,
promise_resolved_status_message_,
- promise_resolved_registration_));
+ base::RetainedRef(promise_resolved_registration_)));
}
void ServiceWorkerRegisterJob::Start() {
@@ -344,36 +344,27 @@ void ServiceWorkerRegisterJob::UpdateAndContinue() {
set_new_version(new ServiceWorkerVersion(registration(), script_url_,
version_id, context_));
new_version()->set_force_bypass_cache_for_scripts(force_bypass_cache_);
- new_version()->set_skip_script_comparison(skip_script_comparison_);
+ if (registration()->has_installed_version() && !skip_script_comparison_) {
+ new_version()->set_pause_after_download(true);
+ new_version()->embedded_worker()->AddListener(this);
+ } else {
+ new_version()->set_pause_after_download(false);
+ }
new_version()->StartWorker(
+ ServiceWorkerMetrics::EventType::INSTALL,
base::Bind(&ServiceWorkerRegisterJob::OnStartWorkerFinished,
weak_factory_.GetWeakPtr()));
}
void ServiceWorkerRegisterJob::OnStartWorkerFinished(
ServiceWorkerStatusCode status) {
+ BumpLastUpdateCheckTimeIfNeeded();
+
if (status == SERVICE_WORKER_OK) {
InstallAndContinue();
return;
}
- // The updated worker is identical to the incumbent.
- if (status == SERVICE_WORKER_ERROR_EXISTS) {
- // Only bump the last check time when we've bypassed the browser cache.
- base::TimeDelta time_since_last_check =
- base::Time::Now() - registration()->last_update_check();
- if (time_since_last_check > base::TimeDelta::FromHours(
- kServiceWorkerScriptMaxCacheAgeInHours) ||
- new_version()->force_bypass_cache_for_scripts()) {
- registration()->set_last_update_check(base::Time::Now());
- context_->storage()->UpdateLastUpdateCheckTime(registration());
- }
-
- ResolvePromise(SERVICE_WORKER_OK, std::string(), registration());
- Complete(status, "The updated worker is identical to the incumbent.");
- return;
- }
-
// "If serviceWorker fails to start up..." then reject the promise with an
// error and abort.
if (status == SERVICE_WORKER_ERROR_TIMEOUT) {
@@ -411,7 +402,10 @@ void ServiceWorkerRegisterJob::InstallAndContinue() {
registration()->NotifyUpdateFound();
// "Fire an event named install..."
- new_version()->DispatchInstallEvent(
+ new_version()->RunAfterStartWorker(
+ ServiceWorkerMetrics::EventType::INSTALL,
+ base::Bind(&ServiceWorkerRegisterJob::DispatchInstallEvent,
+ weak_factory_.GetWeakPtr()),
base::Bind(&ServiceWorkerRegisterJob::OnInstallFinished,
weak_factory_.GetWeakPtr()));
@@ -422,18 +416,32 @@ void ServiceWorkerRegisterJob::InstallAndContinue() {
Complete(SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED);
}
+void ServiceWorkerRegisterJob::DispatchInstallEvent() {
+ DCHECK_EQ(ServiceWorkerVersion::INSTALLING, new_version()->status())
+ << new_version()->status();
+ DCHECK_EQ(ServiceWorkerVersion::RUNNING, new_version()->running_status())
+ << "Worker stopped too soon after it was started.";
+ int request_id = new_version()->StartRequest(
+ ServiceWorkerMetrics::EventType::INSTALL,
+ base::Bind(&ServiceWorkerRegisterJob::OnInstallFinished,
+ weak_factory_.GetWeakPtr()));
+ new_version()->DispatchSimpleEvent<ServiceWorkerHostMsg_InstallEventFinished>(
+ request_id, ServiceWorkerMsg_InstallEvent(request_id));
+}
+
void ServiceWorkerRegisterJob::OnInstallFinished(
ServiceWorkerStatusCode status) {
ServiceWorkerMetrics::RecordInstallEventStatus(status);
if (status != SERVICE_WORKER_OK) {
// "8. If installFailed is true, then:..."
- Complete(status);
+ Complete(status, std::string("ServiceWorker failed to install: ") +
+ ServiceWorkerStatusToString(status));
return;
}
SetPhase(STORE);
- registration()->set_last_update_check(base::Time::Now());
+ DCHECK(!registration()->last_update_check().is_null());
context_->storage()->StoreRegistration(
registration(),
new_version(),
@@ -486,6 +494,12 @@ void ServiceWorkerRegisterJob::CompleteInternal(
ServiceWorkerStatusCode status,
const std::string& status_message) {
SetPhase(COMPLETE);
+
+ if (new_version()) {
+ new_version()->set_pause_after_download(false);
+ new_version()->embedded_worker()->RemoveListener(this);
+ }
+
if (status != SERVICE_WORKER_OK) {
if (registration()) {
if (should_uninstall_on_failure_)
@@ -514,7 +528,7 @@ void ServiceWorkerRegisterJob::CompleteInternal(
if (registration()) {
context_->storage()->NotifyDoneInstallingRegistration(
registration(), new_version(), status);
- if (registration()->waiting_version() || registration()->active_version())
+ if (registration()->has_installed_version())
registration()->set_is_uninstalled(false);
}
}
@@ -553,4 +567,41 @@ void ServiceWorkerRegisterJob::AddRegistrationToMatchingProviderHosts(
}
}
+void ServiceWorkerRegisterJob::OnScriptLoaded() {
+ DCHECK(new_version()->pause_after_download());
+ new_version()->set_pause_after_download(false);
+ net::URLRequestStatus status =
+ new_version()->script_cache_map()->main_script_status();
+ if (!status.is_success()) {
+ // OnScriptLoaded signifies a successful network load, which translates into
+ // a script cache error only in the byte-for-byte identical case.
+ DCHECK_EQ(status.error(),
+ ServiceWorkerWriteToCacheJob::kIdenticalScriptError);
+
+ BumpLastUpdateCheckTimeIfNeeded();
+ ResolvePromise(SERVICE_WORKER_OK, std::string(), registration());
+ Complete(SERVICE_WORKER_ERROR_EXISTS,
+ "The updated worker is identical to the incumbent.");
+ return;
+ }
+
+ new_version()->embedded_worker()->ResumeAfterDownload();
+}
+
+void ServiceWorkerRegisterJob::BumpLastUpdateCheckTimeIfNeeded() {
+ // Bump the last update check time only when the register/update job fetched
+ // the version having bypassed the network cache. We assume that the
+ // BYPASS_CACHE flag evicts an existing cache entry, so even if the install
+ // ultimately failed for whatever reason, we know the version in the HTTP
+ // cache is not stale, so it's OK to bump the update check time.
+ if (new_version()->embedded_worker()->network_accessed_for_script() ||
+ new_version()->force_bypass_cache_for_scripts() ||
+ registration()->last_update_check().is_null()) {
+ registration()->set_last_update_check(base::Time::Now());
+
+ if (registration()->has_installed_version())
+ context_->storage()->UpdateLastUpdateCheckTime(registration());
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_register_job.h b/chromium/content/browser/service_worker/service_worker_register_job.h
index 15033bcc455..66c7822d62d 100644
--- a/chromium/content/browser/service_worker/service_worker_register_job.h
+++ b/chromium/content/browser/service_worker/service_worker_register_job.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_REGISTER_JOB_H_
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_REGISTER_JOB_H_
+#include <string>
#include <vector>
#include "base/macros.h"
@@ -34,7 +35,8 @@ class ServiceWorkerStorage;
// - waiting for older ServiceWorkerVersions to deactivate
// - designating the new version to be the 'active' version
// - updating storage
-class ServiceWorkerRegisterJob : public ServiceWorkerRegisterJobBase {
+class ServiceWorkerRegisterJob : public ServiceWorkerRegisterJobBase,
+ public EmbeddedWorkerInstance::Listener {
public:
typedef base::Callback<void(ServiceWorkerStatusCode status,
const std::string& status_message,
@@ -120,6 +122,7 @@ class ServiceWorkerRegisterJob : public ServiceWorkerRegisterJobBase {
void OnStartWorkerFinished(ServiceWorkerStatusCode status);
void OnStoreRegistrationComplete(ServiceWorkerStatusCode status);
void InstallAndContinue();
+ void DispatchInstallEvent();
void OnInstallFinished(ServiceWorkerStatusCode status);
void Complete(ServiceWorkerStatusCode status);
void Complete(ServiceWorkerStatusCode status,
@@ -133,6 +136,11 @@ class ServiceWorkerRegisterJob : public ServiceWorkerRegisterJobBase {
void AddRegistrationToMatchingProviderHosts(
ServiceWorkerRegistration* registration);
+ // EmbeddedWorkerInstance::Listener implementation:
+ void OnScriptLoaded() override;
+
+ void BumpLastUpdateCheckTimeIfNeeded();
+
// The ServiceWorkerContextCore object should always outlive this.
base::WeakPtr<ServiceWorkerContextCore> context_;
diff --git a/chromium/content/browser/service_worker/service_worker_registration.cc b/chromium/content/browser/service_worker/service_worker_registration.cc
index 6689ca4eb8f..90aa7ffed3c 100644
--- a/chromium/content/browser/service_worker/service_worker_registration.cc
+++ b/chromium/content/browser/service_worker/service_worker_registration.cc
@@ -10,6 +10,7 @@
#include "content/browser/service_worker/service_worker_info.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/browser/service_worker/service_worker_register_job.h"
+#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/browser_thread.h"
@@ -35,7 +36,6 @@ ServiceWorkerRegistration::ServiceWorkerRegistration(
is_uninstalling_(false),
is_uninstalled_(false),
should_activate_when_ready_(false),
- force_update_on_page_load_(false),
resources_total_size_bytes_(0),
context_(context) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -92,8 +92,6 @@ ServiceWorkerRegistrationInfo ServiceWorkerRegistration::GetInfo() {
pattern(), registration_id_,
is_deleted_ ? ServiceWorkerRegistrationInfo::IS_DELETED
: ServiceWorkerRegistrationInfo::IS_NOT_DELETED,
- force_update_on_page_load_ ? ServiceWorkerRegistrationInfo::IS_FORCED
- : ServiceWorkerRegistrationInfo::IS_NOT_FORCED,
GetVersionInfo(active_version_.get()),
GetVersionInfo(waiting_version_.get()),
GetVersionInfo(installing_version_.get()), resources_total_size_bytes_);
@@ -285,9 +283,12 @@ void ServiceWorkerRegistration::ActivateWaitingVersion() {
FOR_EACH_OBSERVER(Listener, listeners_, OnSkippedWaiting(this));
// "10. Queue a task to fire an event named activate..."
- activating_version->DispatchActivateEvent(
- base::Bind(&ServiceWorkerRegistration::OnActivateEventFinished,
- this, activating_version));
+ activating_version->RunAfterStartWorker(
+ ServiceWorkerMetrics::EventType::ACTIVATE,
+ base::Bind(&ServiceWorkerRegistration::DispatchActivateEvent, this,
+ activating_version),
+ base::Bind(&ServiceWorkerRegistration::OnActivateEventFinished, this,
+ activating_version));
}
void ServiceWorkerRegistration::DeleteVersion(
@@ -338,8 +339,27 @@ void ServiceWorkerRegistration::RegisterRegistrationFinishedCallback(
registration_finished_callbacks_.push_back(callback);
}
+void ServiceWorkerRegistration::DispatchActivateEvent(
+ const scoped_refptr<ServiceWorkerVersion>& activating_version) {
+ if (activating_version != active_version()) {
+ OnActivateEventFinished(activating_version, SERVICE_WORKER_ERROR_FAILED);
+ return;
+ }
+
+ DCHECK_EQ(ServiceWorkerVersion::ACTIVATING, activating_version->status());
+ DCHECK_EQ(ServiceWorkerVersion::RUNNING, activating_version->running_status())
+ << "Worker stopped too soon after it was started.";
+ int request_id = activating_version->StartRequest(
+ ServiceWorkerMetrics::EventType::ACTIVATE,
+ base::Bind(&ServiceWorkerRegistration::OnActivateEventFinished, this,
+ activating_version));
+ activating_version
+ ->DispatchSimpleEvent<ServiceWorkerHostMsg_ActivateEventFinished>(
+ request_id, ServiceWorkerMsg_ActivateEvent(request_id));
+}
+
void ServiceWorkerRegistration::OnActivateEventFinished(
- ServiceWorkerVersion* activating_version,
+ const scoped_refptr<ServiceWorkerVersion>& activating_version,
ServiceWorkerStatusCode status) {
if (!context_ || activating_version != active_version() ||
activating_version->status() != ServiceWorkerVersion::ACTIVATING)
diff --git a/chromium/content/browser/service_worker/service_worker_registration.h b/chromium/content/browser/service_worker/service_worker_registration.h
index dab20434ce5..3450bcded8f 100644
--- a/chromium/content/browser/service_worker/service_worker_registration.h
+++ b/chromium/content/browser/service_worker/service_worker_registration.h
@@ -86,6 +86,10 @@ class CONTENT_EXPORT ServiceWorkerRegistration
return installing_version_.get();
}
+ bool has_installed_version() const {
+ return active_version() || waiting_version();
+ }
+
ServiceWorkerVersion* GetNewestVersion() const;
void AddListener(Listener* listener);
@@ -138,11 +142,6 @@ class CONTENT_EXPORT ServiceWorkerRegistration
void RegisterRegistrationFinishedCallback(const base::Closure& callback);
void NotifyRegistrationFinished();
- bool force_update_on_page_load() const { return force_update_on_page_load_; }
- void set_force_update_on_page_load(bool force_update_on_page_load) {
- force_update_on_page_load_ = force_update_on_page_load;
- }
-
private:
friend class base::RefCounted<ServiceWorkerRegistration>;
@@ -157,8 +156,10 @@ class CONTENT_EXPORT ServiceWorkerRegistration
// This method corresponds to the [[Activate]] algorithm.
void ActivateWaitingVersion();
+ void DispatchActivateEvent(
+ const scoped_refptr<ServiceWorkerVersion>& activating_version);
void OnActivateEventFinished(
- ServiceWorkerVersion* activating_version,
+ const scoped_refptr<ServiceWorkerVersion>& activating_version,
ServiceWorkerStatusCode status);
void OnDeleteFinished(ServiceWorkerStatusCode status);
@@ -175,7 +176,6 @@ class CONTENT_EXPORT ServiceWorkerRegistration
bool is_uninstalling_;
bool is_uninstalled_;
bool should_activate_when_ready_;
- bool force_update_on_page_load_;
base::Time last_update_check_;
int64_t resources_total_size_bytes_;
diff --git a/chromium/content/browser/service_worker/service_worker_request_handler.cc b/chromium/content/browser/service_worker/service_worker_request_handler.cc
index 05984a1a34b..f8190e2aa2f 100644
--- a/chromium/content/browser/service_worker/service_worker_request_handler.cc
+++ b/chromium/content/browser/service_worker/service_worker_request_handler.cc
@@ -22,7 +22,7 @@
#include "content/public/common/child_process_host.h"
#include "content/public/common/origin_util.h"
#include "ipc/ipc_message.h"
-#include "net/base/net_util.h"
+#include "net/base/url_util.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_interceptor.h"
#include "storage/browser/blob/blob_storage_context.h"
@@ -232,6 +232,13 @@ void ServiceWorkerRequestHandler::MaybeCompleteCrossSiteTransferInOldProcess(
CompleteCrossSiteTransfer(old_process_id_, old_provider_id_);
}
+bool ServiceWorkerRequestHandler::SanityCheckIsSameContext(
+ ServiceWorkerContextWrapper* wrapper) {
+ if (!wrapper)
+ return !context_;
+ return context_.get() == wrapper->context();
+}
+
ServiceWorkerRequestHandler::~ServiceWorkerRequestHandler() {
}
diff --git a/chromium/content/browser/service_worker/service_worker_request_handler.h b/chromium/content/browser/service_worker/service_worker_request_handler.h
index 9f9c7eb40cf..e75a993efcd 100644
--- a/chromium/content/browser/service_worker/service_worker_request_handler.h
+++ b/chromium/content/browser/service_worker/service_worker_request_handler.h
@@ -6,6 +6,7 @@
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_REQUEST_HANDLER_H_
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/supports_user_data.h"
#include "base/time/time.h"
@@ -30,6 +31,7 @@ class BlobStorageContext;
namespace content {
class ResourceContext;
+class ResourceMessageFilter;
class ResourceRequestBody;
class ServiceWorkerContextCore;
class ServiceWorkerContextWrapper;
@@ -109,6 +111,10 @@ class CONTENT_EXPORT ServiceWorkerRequestHandler
void MaybeCompleteCrossSiteTransferInOldProcess(
int old_process_id);
+ // Useful for detecting storage partition mismatches in the context of cross
+ // site transfer navigations.
+ bool SanityCheckIsSameContext(ServiceWorkerContextWrapper* wrapper);
+
protected:
ServiceWorkerRequestHandler(
base::WeakPtr<ServiceWorkerContextCore> context,
diff --git a/chromium/content/browser/service_worker/service_worker_storage.cc b/chromium/content/browser/service_worker/service_worker_storage.cc
index fff872684d5..ddb1e647c0c 100644
--- a/chromium/content/browser/service_worker/service_worker_storage.cc
+++ b/chromium/content/browser/service_worker/service_worker_storage.cc
@@ -96,6 +96,9 @@ DidDeleteRegistrationParams::DidDeleteRegistrationParams()
: registration_id(kInvalidServiceWorkerRegistrationId) {
}
+ServiceWorkerStorage::DidDeleteRegistrationParams::DidDeleteRegistrationParams(
+ const DidDeleteRegistrationParams& other) = default;
+
ServiceWorkerStorage::
DidDeleteRegistrationParams::~DidDeleteRegistrationParams() {
}
@@ -338,7 +341,7 @@ void ServiceWorkerStorage::GetRegistrationsForOrigin(
if (state_ != INITIALIZING) {
RunSoon(
FROM_HERE,
- base::Bind(callback,
+ base::Bind(callback, SERVICE_WORKER_ERROR_ABORT,
std::vector<scoped_refptr<ServiceWorkerRegistration>>()));
}
return;
@@ -364,8 +367,9 @@ void ServiceWorkerStorage::GetAllRegistrationsInfos(
base::Bind(&ServiceWorkerStorage::GetAllRegistrationsInfos,
weak_factory_.GetWeakPtr(), callback))) {
if (state_ != INITIALIZING) {
- RunSoon(FROM_HERE, base::Bind(
- callback, std::vector<ServiceWorkerRegistrationInfo>()));
+ RunSoon(FROM_HERE,
+ base::Bind(callback, SERVICE_WORKER_ERROR_ABORT,
+ std::vector<ServiceWorkerRegistrationInfo>()));
}
return;
}
@@ -403,6 +407,7 @@ void ServiceWorkerStorage::StoreRegistration(
data.last_update_check = registration->last_update_check();
data.is_active = (version == registration->active_version());
data.foreign_fetch_scopes = version->foreign_fetch_scopes();
+ data.foreign_fetch_origins = version->foreign_fetch_origins();
ResourceList resources;
version->script_cache_map()->GetResources(&resources);
@@ -462,7 +467,6 @@ void ServiceWorkerStorage::UpdateToActiveState(
void ServiceWorkerStorage::UpdateLastUpdateCheckTime(
ServiceWorkerRegistration* registration) {
DCHECK(registration);
-
DCHECK(state_ == INITIALIZED || state_ == DISABLED) << state_;
if (IsDisabled())
return;
@@ -516,24 +520,26 @@ void ServiceWorkerStorage::DeleteRegistration(int64_t registration_id,
scoped_ptr<ServiceWorkerResponseReader>
ServiceWorkerStorage::CreateResponseReader(int64_t resource_id) {
return make_scoped_ptr(
- new ServiceWorkerResponseReader(resource_id, disk_cache()));
+ new ServiceWorkerResponseReader(resource_id, disk_cache()->GetWeakPtr()));
}
scoped_ptr<ServiceWorkerResponseWriter>
ServiceWorkerStorage::CreateResponseWriter(int64_t resource_id) {
return make_scoped_ptr(
- new ServiceWorkerResponseWriter(resource_id, disk_cache()));
+ new ServiceWorkerResponseWriter(resource_id, disk_cache()->GetWeakPtr()));
}
scoped_ptr<ServiceWorkerResponseMetadataWriter>
ServiceWorkerStorage::CreateResponseMetadataWriter(int64_t resource_id) {
- return make_scoped_ptr(
- new ServiceWorkerResponseMetadataWriter(resource_id, disk_cache()));
+ return make_scoped_ptr(new ServiceWorkerResponseMetadataWriter(
+ resource_id, disk_cache()->GetWeakPtr()));
}
void ServiceWorkerStorage::StoreUncommittedResourceId(int64_t resource_id) {
DCHECK_NE(kInvalidServiceWorkerResourceId, resource_id);
- DCHECK_EQ(INITIALIZED, state_);
+ DCHECK(INITIALIZED == state_ || DISABLED == state_) << state_;
+ if (IsDisabled())
+ return;
if (!has_checked_for_stale_resources_)
DeleteStaleResources();
@@ -549,11 +555,18 @@ void ServiceWorkerStorage::StoreUncommittedResourceId(int64_t resource_id) {
void ServiceWorkerStorage::DoomUncommittedResource(int64_t resource_id) {
DCHECK_NE(kInvalidServiceWorkerResourceId, resource_id);
+ DCHECK(INITIALIZED == state_ || DISABLED == state_) << state_;
+ if (IsDisabled())
+ return;
DoomUncommittedResources(std::set<int64_t>(&resource_id, &resource_id + 1));
}
void ServiceWorkerStorage::DoomUncommittedResources(
const std::set<int64_t>& resource_ids) {
+ DCHECK(INITIALIZED == state_ || DISABLED == state_) << state_;
+ if (IsDisabled())
+ return;
+
PostTaskAndReplyWithResult(
database_task_manager_->GetTaskRunner(), FROM_HERE,
base::Bind(&ServiceWorkerDatabase::PurgeUncommittedResourceIds,
@@ -758,10 +771,6 @@ void ServiceWorkerStorage::Disable() {
disk_cache_->Disable();
}
-bool ServiceWorkerStorage::IsDisabled() const {
- return state_ == DISABLED;
-}
-
void ServiceWorkerStorage::PurgeResources(const ResourceList& resources) {
if (!has_checked_for_stale_resources_)
DeleteStaleResources();
@@ -971,7 +980,8 @@ void ServiceWorkerStorage::DidGetRegistrations(
if (status != ServiceWorkerDatabase::STATUS_OK &&
status != ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND) {
ScheduleDeleteAndStartOver();
- callback.Run(std::vector<scoped_refptr<ServiceWorkerRegistration>>());
+ callback.Run(DatabaseStatusToStatusCode(status),
+ std::vector<scoped_refptr<ServiceWorkerRegistration>>());
return;
}
@@ -994,7 +1004,7 @@ void ServiceWorkerStorage::DidGetRegistrations(
}
}
- callback.Run(registrations);
+ callback.Run(SERVICE_WORKER_OK, registrations);
}
void ServiceWorkerStorage::DidGetRegistrationsInfos(
@@ -1006,7 +1016,8 @@ void ServiceWorkerStorage::DidGetRegistrationsInfos(
if (status != ServiceWorkerDatabase::STATUS_OK &&
status != ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND) {
ScheduleDeleteAndStartOver();
- callback.Run(std::vector<ServiceWorkerRegistrationInfo>());
+ callback.Run(DatabaseStatusToStatusCode(status),
+ std::vector<ServiceWorkerRegistrationInfo>());
return;
}
@@ -1063,7 +1074,7 @@ void ServiceWorkerStorage::DidGetRegistrationsInfos(
}
}
- callback.Run(infos);
+ callback.Run(SERVICE_WORKER_OK, infos);
}
void ServiceWorkerStorage::DidStoreRegistration(
@@ -1228,6 +1239,7 @@ ServiceWorkerStorage::GetOrCreateRegistration(
ServiceWorkerVersion::ACTIVATED : ServiceWorkerVersion::INSTALLED);
version->script_cache_map()->SetResources(resources);
version->set_foreign_fetch_scopes(data.foreign_fetch_scopes);
+ version->set_foreign_fetch_origins(data.foreign_fetch_origins);
}
if (version->status() == ServiceWorkerVersion::ACTIVATED)
@@ -1274,12 +1286,16 @@ ServiceWorkerStorage::FindInstallingRegistrationForId(int64_t registration_id) {
}
ServiceWorkerDiskCache* ServiceWorkerStorage::disk_cache() {
- DCHECK_EQ(INITIALIZED, state_);
+ DCHECK(INITIALIZED == state_ || DISABLED == state_) << state_;
if (disk_cache_)
return disk_cache_.get();
-
disk_cache_.reset(new ServiceWorkerDiskCache);
+ if (IsDisabled()) {
+ disk_cache_->Disable();
+ return disk_cache_.get();
+ }
+
base::FilePath path = GetDiskCachePath();
if (path.empty()) {
int rv = disk_cache_->InitWithMemBackend(kMaxMemDiskCacheSize,
@@ -1687,6 +1703,10 @@ void ServiceWorkerStorage::DeleteAllDataForOriginsFromDB(
database->DeleteAllDataForOrigins(origins, &newly_purgeable_resources);
}
+bool ServiceWorkerStorage::IsDisabled() const {
+ return state_ == DISABLED;
+}
+
// TODO(nhiroki): The corruption recovery should not be scheduled if the error
// is transient and it can get healed soon (e.g. IO error). To do that, the
// database should not disable itself when an error occurs and the storage
diff --git a/chromium/content/browser/service_worker/service_worker_storage.h b/chromium/content/browser/service_worker/service_worker_storage.h
index 92042def120..c4dbe08cd76 100644
--- a/chromium/content/browser/service_worker/service_worker_storage.h
+++ b/chromium/content/browser/service_worker/service_worker_storage.h
@@ -48,7 +48,9 @@ struct ServiceWorkerRegistrationInfo;
// This class provides an interface to store and retrieve ServiceWorker
// registration data. The lifetime is equal to ServiceWorkerContextCore that is
-// an owner of this class.
+// an owner of this class. When a storage operation fails, this is marked as
+// disabled and all subsequent requests are aborted until the context core is
+// restarted.
class CONTENT_EXPORT ServiceWorkerStorage
: NON_EXPORTED_BASE(public ServiceWorkerVersion::Listener) {
public:
@@ -58,10 +60,14 @@ class CONTENT_EXPORT ServiceWorkerStorage
const scoped_refptr<ServiceWorkerRegistration>&
registration)> FindRegistrationCallback;
typedef base::Callback<void(
+ ServiceWorkerStatusCode status,
const std::vector<scoped_refptr<ServiceWorkerRegistration>>&
- registrations)> GetRegistrationsCallback;
- typedef base::Callback<void(const std::vector<ServiceWorkerRegistrationInfo>&
- registrations)> GetRegistrationsInfosCallback;
+ registrations)>
+ GetRegistrationsCallback;
+ typedef base::Callback<void(
+ ServiceWorkerStatusCode status,
+ const std::vector<ServiceWorkerRegistrationInfo>& registrations)>
+ GetRegistrationsInfosCallback;
typedef base::Callback<
void(const std::string& data, ServiceWorkerStatusCode status)>
GetUserDataCallback;
@@ -142,6 +148,8 @@ class CONTENT_EXPORT ServiceWorkerStorage
const GURL& origin,
const StatusCallback& callback);
+ // Creates a resource accessor. Never returns nullptr but an accessor may be
+ // associated with the disabled disk cache if the storage is disabled.
scoped_ptr<ServiceWorkerResponseReader> CreateResponseReader(
int64_t resource_id);
scoped_ptr<ServiceWorkerResponseWriter> CreateResponseWriter(
@@ -211,12 +219,12 @@ class CONTENT_EXPORT ServiceWorkerStorage
ServiceWorkerRegistration* registration);
void Disable();
- bool IsDisabled() const;
// |resources| must already be on the purgeable list.
void PurgeResources(const ResourceList& resources);
private:
+ friend class ServiceWorkerDispatcherHostTest;
friend class ServiceWorkerHandleTest;
friend class ServiceWorkerStorageTest;
friend class ServiceWorkerResourceStorageTest;
@@ -267,6 +275,7 @@ class CONTENT_EXPORT ServiceWorkerStorage
StatusCallback callback;
DidDeleteRegistrationParams();
+ DidDeleteRegistrationParams(const DidDeleteRegistrationParams& other);
~DidDeleteRegistrationParams();
};
@@ -481,6 +490,7 @@ class CONTENT_EXPORT ServiceWorkerStorage
ServiceWorkerDatabase* database,
const std::set<GURL>& origins);
+ bool IsDisabled() const;
void ScheduleDeleteAndStartOver();
void DidDeleteDatabase(
const StatusCallback& callback,
diff --git a/chromium/content/browser/service_worker/service_worker_storage_unittest.cc b/chromium/content/browser/service_worker/service_worker_storage_unittest.cc
index 6b757161d2f..a2a88ef0bd8 100644
--- a/chromium/content/browser/service_worker/service_worker_storage_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_storage_unittest.cc
@@ -82,31 +82,39 @@ ServiceWorkerStorage::FindRegistrationCallback MakeFindCallback(
void GetAllCallback(
bool* was_called,
+ ServiceWorkerStatusCode* result,
std::vector<scoped_refptr<ServiceWorkerRegistration>>* all_out,
+ ServiceWorkerStatusCode status,
const std::vector<scoped_refptr<ServiceWorkerRegistration>>& all) {
*was_called = true;
+ *result = status;
*all_out = all;
}
void GetAllInfosCallback(
bool* was_called,
+ ServiceWorkerStatusCode* result,
std::vector<ServiceWorkerRegistrationInfo>* all_out,
+ ServiceWorkerStatusCode status,
const std::vector<ServiceWorkerRegistrationInfo>& all) {
*was_called = true;
+ *result = status;
*all_out = all;
}
ServiceWorkerStorage::GetRegistrationsCallback MakeGetRegistrationsCallback(
bool* was_called,
+ ServiceWorkerStatusCode* status,
std::vector<scoped_refptr<ServiceWorkerRegistration>>* all) {
- return base::Bind(&GetAllCallback, was_called, all);
+ return base::Bind(&GetAllCallback, was_called, status, all);
}
ServiceWorkerStorage::GetRegistrationsInfosCallback
MakeGetRegistrationsInfosCallback(
bool* was_called,
+ ServiceWorkerStatusCode* status,
std::vector<ServiceWorkerRegistrationInfo>* all) {
- return base::Bind(&GetAllInfosCallback, was_called, all);
+ return base::Bind(&GetAllInfosCallback, was_called, status, all);
}
void GetUserDataCallback(
@@ -131,11 +139,11 @@ void GetUserDataForAllRegistrationsCallback(
*status_out = status;
}
-void WriteResponse(ServiceWorkerStorage* storage,
- int64_t id,
- const std::string& headers,
- IOBuffer* body,
- int length) {
+int WriteResponse(ServiceWorkerStorage* storage,
+ int64_t id,
+ const std::string& headers,
+ IOBuffer* body,
+ int length) {
scoped_ptr<ServiceWorkerResponseWriter> writer =
storage->CreateResponseWriter(id);
@@ -146,36 +154,45 @@ void WriteResponse(ServiceWorkerStorage* storage,
info->headers = new net::HttpResponseHeaders(headers);
scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
new HttpResponseInfoIOBuffer(info.release());
+ int rv = 0;
{
TestCompletionCallback cb;
writer->WriteInfo(info_buffer.get(), cb.callback());
- int rv = cb.WaitForResult();
- EXPECT_LT(0, rv);
+ rv = cb.WaitForResult();
+ if (rv < 0)
+ return rv;
}
{
TestCompletionCallback cb;
writer->WriteData(body, length, cb.callback());
- int rv = cb.WaitForResult();
- EXPECT_EQ(length, rv);
+ rv = cb.WaitForResult();
}
+ return rv;
}
-void WriteStringResponse(ServiceWorkerStorage* storage,
- int64_t id,
- const std::string& headers,
- const std::string& body) {
+int WriteStringResponse(ServiceWorkerStorage* storage,
+ int64_t id,
+ const std::string& headers,
+ const std::string& body) {
scoped_refptr<IOBuffer> body_buffer(new WrappedIOBuffer(body.data()));
- WriteResponse(storage, id, headers, body_buffer.get(), body.length());
+ return WriteResponse(storage, id, headers, body_buffer.get(), body.length());
}
-void WriteBasicResponse(ServiceWorkerStorage* storage, int64_t id) {
- scoped_ptr<ServiceWorkerResponseWriter> writer =
- storage->CreateResponseWriter(id);
-
+int WriteBasicResponse(ServiceWorkerStorage* storage, int64_t id) {
const char kHttpHeaders[] = "HTTP/1.0 200 HONKYDORY\0Content-Length: 5\0\0";
const char kHttpBody[] = "Hello";
std::string headers(kHttpHeaders, arraysize(kHttpHeaders));
- WriteStringResponse(storage, id, headers, std::string(kHttpBody));
+ return WriteStringResponse(storage, id, headers, std::string(kHttpBody));
+}
+
+int ReadResponseInfo(ServiceWorkerStorage* storage,
+ int64_t id,
+ HttpResponseInfoIOBuffer* info_buffer) {
+ scoped_ptr<ServiceWorkerResponseReader> reader =
+ storage->CreateResponseReader(id);
+ TestCompletionCallback cb;
+ reader->ReadInfo(info_buffer, cb.callback());
+ return cb.WaitForResult();
}
bool VerifyBasicResponse(ServiceWorkerStorage* storage,
@@ -186,28 +203,22 @@ bool VerifyBasicResponse(ServiceWorkerStorage* storage,
storage->CreateResponseReader(id);
scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
new HttpResponseInfoIOBuffer();
- {
- TestCompletionCallback cb;
- reader->ReadInfo(info_buffer.get(), cb.callback());
- int rv = cb.WaitForResult();
- if (expected_positive_result)
- EXPECT_LT(0, rv);
- if (rv <= 0)
- return false;
- }
+ int rv = ReadResponseInfo(storage, id, info_buffer.get());
+ if (expected_positive_result)
+ EXPECT_LT(0, rv);
+ if (rv <= 0)
+ return false;
std::string received_body;
- {
- const int kBigEnough = 512;
- scoped_refptr<net::IOBuffer> buffer = new IOBuffer(kBigEnough);
- TestCompletionCallback cb;
- reader->ReadData(buffer.get(), kBigEnough, cb.callback());
- int rv = cb.WaitForResult();
- EXPECT_EQ(static_cast<int>(kExpectedHttpBody.size()), rv);
- if (rv <= 0)
- return false;
- received_body.assign(buffer->data(), rv);
- }
+ const int kBigEnough = 512;
+ scoped_refptr<net::IOBuffer> buffer = new IOBuffer(kBigEnough);
+ TestCompletionCallback cb;
+ reader->ReadData(buffer.get(), kBigEnough, cb.callback());
+ rv = cb.WaitForResult();
+ EXPECT_EQ(static_cast<int>(kExpectedHttpBody.size()), rv);
+ if (rv <= 0)
+ return false;
+ received_body.assign(buffer->data(), rv);
bool status_match =
std::string("HONKYDORY") ==
@@ -321,7 +332,7 @@ class ServiceWorkerStorageTest : public testing::Test {
scoped_refptr<ServiceWorkerRegistration> registration,
scoped_refptr<ServiceWorkerVersion> version) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
+ ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
storage()->StoreRegistration(registration.get(),
version.get(),
MakeStatusCallback(&was_called, &result));
@@ -334,7 +345,7 @@ class ServiceWorkerStorageTest : public testing::Test {
ServiceWorkerStatusCode DeleteRegistration(int64_t registration_id,
const GURL& origin) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
+ ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
storage()->DeleteRegistration(
registration_id, origin, MakeStatusCallback(&was_called, &result));
EXPECT_FALSE(was_called); // always async
@@ -343,32 +354,37 @@ class ServiceWorkerStorageTest : public testing::Test {
return result;
}
- void GetAllRegistrationsInfos(
+ ServiceWorkerStatusCode GetAllRegistrationsInfos(
std::vector<ServiceWorkerRegistrationInfo>* registrations) {
bool was_called = false;
+ ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
storage()->GetAllRegistrationsInfos(
- MakeGetRegistrationsInfosCallback(&was_called, registrations));
+ MakeGetRegistrationsInfosCallback(&was_called, &result, registrations));
EXPECT_FALSE(was_called); // always async
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
+ return result;
}
- void GetRegistrationsForOrigin(
+ ServiceWorkerStatusCode GetRegistrationsForOrigin(
const GURL& origin,
std::vector<scoped_refptr<ServiceWorkerRegistration>>* registrations) {
bool was_called = false;
+ ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
storage()->GetRegistrationsForOrigin(
- origin, MakeGetRegistrationsCallback(&was_called, registrations));
+ origin,
+ MakeGetRegistrationsCallback(&was_called, &result, registrations));
EXPECT_FALSE(was_called); // always async
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(was_called);
+ return result;
}
ServiceWorkerStatusCode GetUserData(int64_t registration_id,
const std::string& key,
std::string* data) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
+ ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
storage()->GetUserData(
registration_id, key,
base::Bind(&GetUserDataCallback, &was_called, data, &result));
@@ -383,7 +399,7 @@ class ServiceWorkerStorageTest : public testing::Test {
const std::string& key,
const std::string& data) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
+ ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
storage()->StoreUserData(
registration_id, origin, key, data,
MakeStatusCallback(&was_called, &result));
@@ -396,7 +412,7 @@ class ServiceWorkerStorageTest : public testing::Test {
ServiceWorkerStatusCode ClearUserData(int64_t registration_id,
const std::string& key) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
+ ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
storage()->ClearUserData(
registration_id, key, MakeStatusCallback(&was_called, &result));
EXPECT_FALSE(was_called); // always async
@@ -409,7 +425,7 @@ class ServiceWorkerStorageTest : public testing::Test {
const std::string& key,
std::vector<std::pair<int64_t, std::string>>* data) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
+ ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
storage()->GetUserDataForAllRegistrations(
key, base::Bind(&GetUserDataForAllRegistrationsCallback, &was_called,
data, &result));
@@ -420,9 +436,9 @@ class ServiceWorkerStorageTest : public testing::Test {
}
ServiceWorkerStatusCode UpdateToActiveState(
- scoped_refptr<ServiceWorkerRegistration> registration) {
+ const scoped_refptr<ServiceWorkerRegistration>& registration) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
+ ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
storage()->UpdateToActiveState(registration.get(),
MakeStatusCallback(&was_called, &result));
EXPECT_FALSE(was_called); // always async
@@ -431,8 +447,9 @@ class ServiceWorkerStorageTest : public testing::Test {
return result;
}
- void UpdateLastUpdateCheckTime(ServiceWorkerRegistration* registration) {
- storage()->UpdateLastUpdateCheckTime(registration);
+ void UpdateLastUpdateCheckTime(
+ const scoped_refptr<ServiceWorkerRegistration>& registration) {
+ storage()->UpdateLastUpdateCheckTime(registration.get());
base::RunLoop().RunUntilIdle();
}
@@ -440,7 +457,7 @@ class ServiceWorkerStorageTest : public testing::Test {
const GURL& document_url,
scoped_refptr<ServiceWorkerRegistration>* registration) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
+ ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
storage()->FindRegistrationForDocument(
document_url, MakeFindCallback(&was_called, &result, registration));
base::RunLoop().RunUntilIdle();
@@ -452,7 +469,7 @@ class ServiceWorkerStorageTest : public testing::Test {
const GURL& scope,
scoped_refptr<ServiceWorkerRegistration>* registration) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
+ ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
storage()->FindRegistrationForPattern(
scope, MakeFindCallback(&was_called, &result, registration));
EXPECT_FALSE(was_called); // always async
@@ -466,7 +483,7 @@ class ServiceWorkerStorageTest : public testing::Test {
const GURL& origin,
scoped_refptr<ServiceWorkerRegistration>* registration) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
+ ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
storage()->FindRegistrationForId(
registration_id, origin,
MakeFindCallback(&was_called, &result, registration));
@@ -479,7 +496,7 @@ class ServiceWorkerStorageTest : public testing::Test {
int64_t registration_id,
scoped_refptr<ServiceWorkerRegistration>* registration) {
bool was_called = false;
- ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_FAILED;
+ ServiceWorkerStatusCode result = SERVICE_WORKER_ERROR_MAX_VALUE;
storage()->FindRegistrationForIdOnly(
registration_id, MakeFindCallback(&was_called, &result, registration));
base::RunLoop().RunUntilIdle();
@@ -493,6 +510,84 @@ class ServiceWorkerStorageTest : public testing::Test {
TestBrowserThreadBundle browser_thread_bundle_;
};
+TEST_F(ServiceWorkerStorageTest, DisabledStorage) {
+ const GURL kScope("http://www.example.com/scope/");
+ const GURL kScript("http://www.example.com/script.js");
+ const GURL kDocumentUrl("http://www.example.com/scope/document.html");
+ const int64_t kRegistrationId = 0;
+ const int64_t kVersionId = 0;
+ const int64_t kResourceId = 0;
+
+ LazyInitialize();
+ storage()->Disable();
+
+ scoped_refptr<ServiceWorkerRegistration> found_registration;
+ EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT,
+ FindRegistrationForDocument(kDocumentUrl, &found_registration));
+ EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT,
+ FindRegistrationForPattern(kScope, &found_registration));
+ EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT,
+ FindRegistrationForId(kRegistrationId, kScope.GetOrigin(),
+ &found_registration));
+ EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT,
+ FindRegistrationForIdOnly(kRegistrationId, &found_registration));
+ EXPECT_FALSE(storage()->GetUninstallingRegistration(kScope.GetOrigin()));
+
+ std::vector<scoped_refptr<ServiceWorkerRegistration>> found_registrations;
+ EXPECT_EQ(
+ SERVICE_WORKER_ERROR_ABORT,
+ GetRegistrationsForOrigin(kScope.GetOrigin(), &found_registrations));
+
+ std::vector<ServiceWorkerRegistrationInfo> all_registrations;
+ EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT,
+ GetAllRegistrationsInfos(&all_registrations));
+
+ scoped_refptr<ServiceWorkerRegistration> live_registration =
+ new ServiceWorkerRegistration(kScope, kRegistrationId,
+ context()->AsWeakPtr());
+ scoped_refptr<ServiceWorkerVersion> live_version = new ServiceWorkerVersion(
+ live_registration.get(), kScript, kVersionId, context()->AsWeakPtr());
+ EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT,
+ StoreRegistration(live_registration, live_version));
+
+ EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT, UpdateToActiveState(live_registration));
+
+ EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT,
+ DeleteRegistration(kRegistrationId, kScope.GetOrigin()));
+
+ // Response reader and writer created by the disabled storage should fail to
+ // access the disk cache.
+ scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
+ new HttpResponseInfoIOBuffer();
+ EXPECT_EQ(net::ERR_CACHE_MISS,
+ ReadResponseInfo(storage(), kResourceId, info_buffer.get()));
+ EXPECT_EQ(net::ERR_FAILED, WriteBasicResponse(storage(), kResourceId));
+ EXPECT_EQ(net::ERR_FAILED,
+ WriteResponseMetadata(storage(), kResourceId, "foo"));
+
+ const std::string kUserDataKey = "key";
+ std::string user_data_out;
+ EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT,
+ GetUserData(kRegistrationId, kUserDataKey, &user_data_out));
+ EXPECT_EQ(
+ SERVICE_WORKER_ERROR_ABORT,
+ StoreUserData(kRegistrationId, kScope.GetOrigin(), kUserDataKey, "foo"));
+ EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT,
+ ClearUserData(kRegistrationId, kUserDataKey));
+ std::vector<std::pair<int64_t, std::string>> data_list_out;
+ EXPECT_EQ(SERVICE_WORKER_ERROR_ABORT,
+ GetUserDataForAllRegistrations(kUserDataKey, &data_list_out));
+
+ EXPECT_FALSE(
+ storage()->OriginHasForeignFetchRegistrations(kScope.GetOrigin()));
+
+ // Next available ids should be invalid.
+ EXPECT_EQ(kInvalidServiceWorkerRegistrationId,
+ storage()->NewRegistrationId());
+ EXPECT_EQ(kInvalidServiceWorkerVersionId, storage()->NewVersionId());
+ EXPECT_EQ(kInvalidServiceWorkerResourceId, storage()->NewRegistrationId());
+}
+
TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
const GURL kScope("http://www.test.not/scope/");
const GURL kScript("http://www.test.not/script.js");
@@ -504,6 +599,7 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
const int64_t kRegistrationId = 0;
const int64_t kVersionId = 0;
const GURL kForeignFetchScope("http://www.test.not/scope/ff/");
+ const url::Origin kForeignFetchOrigin(GURL("https://example.com/"));
const base::Time kToday = base::Time::Now();
const base::Time kYesterday = kToday - base::TimeDelta::FromDays(1);
@@ -539,6 +635,8 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
live_version->script_cache_map()->SetResources(resources);
live_version->set_foreign_fetch_scopes(
std::vector<GURL>(1, kForeignFetchScope));
+ live_version->set_foreign_fetch_origins(
+ std::vector<url::Origin>(1, kForeignFetchOrigin));
live_registration->SetWaitingVersion(live_version);
live_registration->set_last_update_check(kYesterday);
EXPECT_EQ(SERVICE_WORKER_OK,
@@ -592,7 +690,7 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
EXPECT_EQ(kResource1Size + kResource2Size,
found_registration->resources_total_size_bytes());
std::vector<ServiceWorkerRegistrationInfo> all_registrations;
- GetAllRegistrationsInfos(&all_registrations);
+ EXPECT_EQ(SERVICE_WORKER_OK, GetAllRegistrationsInfos(&all_registrations));
EXPECT_EQ(1u, all_registrations.size());
ServiceWorkerRegistrationInfo info = all_registrations[0];
EXPECT_EQ(kResource1Size + kResource2Size, info.stored_version_size_bytes);
@@ -601,12 +699,15 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
// Finding by origin should provide the same result if origin is kScope.
std::vector<scoped_refptr<ServiceWorkerRegistration>>
registrations_for_origin;
- GetRegistrationsForOrigin(kScope.GetOrigin(), &registrations_for_origin);
+ EXPECT_EQ(
+ SERVICE_WORKER_OK,
+ GetRegistrationsForOrigin(kScope.GetOrigin(), &registrations_for_origin));
EXPECT_EQ(1u, registrations_for_origin.size());
registrations_for_origin.clear();
- GetRegistrationsForOrigin(GURL("http://example.com/").GetOrigin(),
- &registrations_for_origin);
+ EXPECT_EQ(SERVICE_WORKER_OK,
+ GetRegistrationsForOrigin(GURL("http://example.com/").GetOrigin(),
+ &registrations_for_origin));
EXPECT_TRUE(registrations_for_origin.empty());
found_registration = NULL;
@@ -629,6 +730,11 @@ TEST_F(ServiceWorkerStorageTest, StoreFindUpdateDeleteRegistration) {
1u, found_registration->waiting_version()->foreign_fetch_scopes().size());
EXPECT_EQ(kForeignFetchScope,
found_registration->waiting_version()->foreign_fetch_scopes()[0]);
+ EXPECT_EQ(
+ 1u,
+ found_registration->waiting_version()->foreign_fetch_origins().size());
+ EXPECT_EQ(kForeignFetchOrigin,
+ found_registration->waiting_version()->foreign_fetch_origins()[0]);
// Update to active and update the last check time.
scoped_refptr<ServiceWorkerVersion> temp_version =
@@ -720,16 +826,19 @@ TEST_F(ServiceWorkerStorageTest, InstallingRegistrationsAreFindable) {
EXPECT_FALSE(found_registration.get());
std::vector<ServiceWorkerRegistrationInfo> all_registrations;
- GetAllRegistrationsInfos(&all_registrations);
+ EXPECT_EQ(SERVICE_WORKER_OK, GetAllRegistrationsInfos(&all_registrations));
EXPECT_TRUE(all_registrations.empty());
std::vector<scoped_refptr<ServiceWorkerRegistration>>
registrations_for_origin;
- GetRegistrationsForOrigin(kScope.GetOrigin(), &registrations_for_origin);
+ EXPECT_EQ(
+ SERVICE_WORKER_OK,
+ GetRegistrationsForOrigin(kScope.GetOrigin(), &registrations_for_origin));
EXPECT_TRUE(registrations_for_origin.empty());
- GetRegistrationsForOrigin(GURL("http://example.com/").GetOrigin(),
- &registrations_for_origin);
+ EXPECT_EQ(SERVICE_WORKER_OK,
+ GetRegistrationsForOrigin(GURL("http://example.com/").GetOrigin(),
+ &registrations_for_origin));
EXPECT_TRUE(registrations_for_origin.empty());
// Notify storage of it being installed.
@@ -757,17 +866,20 @@ TEST_F(ServiceWorkerStorageTest, InstallingRegistrationsAreFindable) {
EXPECT_EQ(live_registration, found_registration);
found_registration = NULL;
- GetAllRegistrationsInfos(&all_registrations);
+ EXPECT_EQ(SERVICE_WORKER_OK, GetAllRegistrationsInfos(&all_registrations));
EXPECT_EQ(1u, all_registrations.size());
all_registrations.clear();
// Finding by origin should provide the same result if origin is kScope.
- GetRegistrationsForOrigin(kScope.GetOrigin(), &registrations_for_origin);
+ EXPECT_EQ(
+ SERVICE_WORKER_OK,
+ GetRegistrationsForOrigin(kScope.GetOrigin(), &registrations_for_origin));
EXPECT_EQ(1u, registrations_for_origin.size());
registrations_for_origin.clear();
- GetRegistrationsForOrigin(GURL("http://example.com/").GetOrigin(),
- &registrations_for_origin);
+ EXPECT_EQ(SERVICE_WORKER_OK,
+ GetRegistrationsForOrigin(GURL("http://example.com/").GetOrigin(),
+ &registrations_for_origin));
EXPECT_TRUE(registrations_for_origin.empty());
// Notify storage of installation no longer happening.
@@ -792,14 +904,17 @@ TEST_F(ServiceWorkerStorageTest, InstallingRegistrationsAreFindable) {
FindRegistrationForPattern(kScope, &found_registration));
EXPECT_FALSE(found_registration.get());
- GetAllRegistrationsInfos(&all_registrations);
+ EXPECT_EQ(SERVICE_WORKER_OK, GetAllRegistrationsInfos(&all_registrations));
EXPECT_TRUE(all_registrations.empty());
- GetRegistrationsForOrigin(kScope.GetOrigin(), &registrations_for_origin);
+ EXPECT_EQ(
+ SERVICE_WORKER_OK,
+ GetRegistrationsForOrigin(kScope.GetOrigin(), &registrations_for_origin));
EXPECT_TRUE(registrations_for_origin.empty());
- GetRegistrationsForOrigin(GURL("http://example.com/").GetOrigin(),
- &registrations_for_origin);
+ EXPECT_EQ(SERVICE_WORKER_OK,
+ GetRegistrationsForOrigin(GURL("http://example.com/").GetOrigin(),
+ &registrations_for_origin));
EXPECT_TRUE(registrations_for_origin.empty());
}
@@ -1241,7 +1356,7 @@ TEST_F(ServiceWorkerResourceStorageDiskTest, DeleteAndStartOver) {
ASSERT_TRUE(base::DirectoryExists(storage()->GetDatabasePath()));
base::RunLoop run_loop;
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_ABORT;
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
storage()->DeleteAndStartOver(
base::Bind(&StatusAndQuitCallback, &status, run_loop.QuitClosure()));
run_loop.Run();
@@ -1266,7 +1381,7 @@ TEST_F(ServiceWorkerResourceStorageDiskTest,
ASSERT_TRUE(base::PathExists(file_path));
base::RunLoop run_loop;
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_ABORT;
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
storage()->DeleteAndStartOver(
base::Bind(&StatusAndQuitCallback, &status, run_loop.QuitClosure()));
run_loop.Run();
@@ -1292,7 +1407,7 @@ TEST_F(ServiceWorkerResourceStorageDiskTest,
ASSERT_TRUE(base::PathExists(file_path));
base::RunLoop run_loop;
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_ABORT;
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
storage()->DeleteAndStartOver(
base::Bind(&StatusAndQuitCallback, &status, run_loop.QuitClosure()));
run_loop.Run();
diff --git a/chromium/content/browser/service_worker/service_worker_url_request_job.cc b/chromium/content/browser/service_worker/service_worker_url_request_job.cc
index 44fab7f581a..47128f0c5c1 100644
--- a/chromium/content/browser/service_worker/service_worker_url_request_job.cc
+++ b/chromium/content/browser/service_worker/service_worker_url_request_job.cc
@@ -28,6 +28,7 @@
#include "content/browser/streams/stream_registry.h"
#include "content/common/resource_request_body.h"
#include "content/common/service_worker/service_worker_types.h"
+#include "content/common/service_worker/service_worker_utils.h"
#include "content/public/browser/blob_handle.h"
#include "content/public/browser/resource_request_info.h"
#include "content/public/browser/service_worker_context.h"
@@ -115,10 +116,11 @@ ServiceWorkerURLRequestJob::ServiceWorkerURLRequestJob(
FetchRequestMode request_mode,
FetchCredentialsMode credentials_mode,
FetchRedirectMode redirect_mode,
- bool is_main_resource_load,
+ ResourceType resource_type,
RequestContextType request_context_type,
RequestContextFrameType frame_type,
scoped_refptr<ResourceRequestBody> body,
+ ServiceWorkerFetchType fetch_type,
Delegate* delegate)
: net::URLRequestJob(request, network_delegate),
delegate_(delegate),
@@ -132,11 +134,12 @@ ServiceWorkerURLRequestJob::ServiceWorkerURLRequestJob(
request_mode_(request_mode),
credentials_mode_(credentials_mode),
redirect_mode_(redirect_mode),
- is_main_resource_load_(is_main_resource_load),
+ resource_type_(resource_type),
request_context_type_(request_context_type),
frame_type_(frame_type),
fall_back_required_(false),
body_(body),
+ fetch_type_(fetch_type),
weak_factory_(this) {
DCHECK(delegate_) << "ServiceWorkerURLRequestJob requires a delegate";
}
@@ -308,7 +311,8 @@ void ServiceWorkerURLRequestJob::OnBeforeNetworkStart(net::URLRequest* request,
void ServiceWorkerURLRequestJob::OnResponseStarted(net::URLRequest* request) {
// TODO(falken): Add Content-Length, Content-Type if they were not provided in
// the ServiceWorkerResponse.
- response_time_ = base::Time::Now();
+ if (response_time_.is_null())
+ response_time_ = base::Time::Now();
CommitResponseHeader();
}
@@ -429,7 +433,7 @@ void ServiceWorkerURLRequestJob::StartRequest() {
// Send a fetch event to the ServiceWorker associated to the
// provider_host.
fetch_dispatcher_.reset(new ServiceWorkerFetchDispatcher(
- CreateFetchRequest(), active_worker,
+ CreateFetchRequest(), active_worker, resource_type_,
base::Bind(&ServiceWorkerURLRequestJob::DidPrepareFetchEvent,
weak_factory_.GetWeakPtr()),
base::Bind(&ServiceWorkerURLRequestJob::DidDispatchFetchEvent,
@@ -446,11 +450,13 @@ scoped_ptr<ServiceWorkerFetchRequest>
ServiceWorkerURLRequestJob::CreateFetchRequest() {
std::string blob_uuid;
uint64_t blob_size = 0;
- CreateRequestBodyBlob(&blob_uuid, &blob_size);
+ // The upload data in URLRequest may have been cleared while handing redirect.
+ if (request_->has_upload())
+ CreateRequestBodyBlob(&blob_uuid, &blob_size);
scoped_ptr<ServiceWorkerFetchRequest> request(
new ServiceWorkerFetchRequest());
request->mode = request_mode_;
- request->is_main_resource_load = is_main_resource_load_;
+ request->is_main_resource_load = IsMainResourceLoad();
request->request_context_type = request_context_type_;
request->frame_type = frame_type_;
request->url = request_->url();
@@ -479,6 +485,7 @@ ServiceWorkerURLRequestJob::CreateFetchRequest() {
request->referrer =
Referrer(GURL(request_->referrer()), blink::WebReferrerPolicyDefault);
}
+ request->fetch_type = fetch_type_;
return request;
}
@@ -562,9 +569,9 @@ void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
ServiceWorkerStatusCode status,
ServiceWorkerFetchEventResult fetch_result,
const ServiceWorkerResponse& response,
- scoped_refptr<ServiceWorkerVersion> version) {
+ const scoped_refptr<ServiceWorkerVersion>& version) {
fetch_dispatcher_.reset();
- ServiceWorkerMetrics::RecordFetchEventStatus(is_main_resource_load_, status);
+ ServiceWorkerMetrics::RecordFetchEventStatus(IsMainResourceLoad(), status);
// Check if we're not orphaned.
if (!request()) {
@@ -582,7 +589,7 @@ void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
if (status != SERVICE_WORKER_OK) {
RecordResult(ServiceWorkerMetrics::REQUEST_JOB_ERROR_FETCH_EVENT_DISPATCH);
- if (is_main_resource_load_) {
+ if (IsMainResourceLoad()) {
// Using the service worker failed, so fallback to network.
delegate_->MainResourceLoadFailed();
response_type_ = FALLBACK_TO_NETWORK;
@@ -602,7 +609,8 @@ void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
// we returns a fall_back_required response to the renderer.
if ((request_mode_ == FETCH_REQUEST_MODE_CORS ||
request_mode_ == FETCH_REQUEST_MODE_CORS_WITH_FORCED_PREFLIGHT) &&
- delegate_->GetRequestingOrigin() != request()->url().GetOrigin()) {
+ !request()->initiator().IsSameOriginWith(
+ url::Origin(request()->url()))) {
fall_back_required_ = true;
RecordResult(ServiceWorkerMetrics::REQUEST_JOB_FALLBACK_FOR_CORS);
CreateResponseHeader(
@@ -657,6 +665,7 @@ void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
streaming_version_->AddStreamingURLRequestJob(this);
response_url_ = response.url;
service_worker_response_type_ = response.response_type;
+ response_time_ = response.response_time;
CreateResponseHeader(
response.status_code, response.status_text, response.headers);
load_timing_info_.receive_headers_end = base::TimeTicks::Now();
@@ -694,6 +703,9 @@ void ServiceWorkerURLRequestJob::DidDispatchFetchEvent(
response_url_ = response.url;
service_worker_response_type_ = response.response_type;
+ response_time_ = response.response_time;
+ response_is_in_cache_storage_ = response.is_in_cache_storage;
+ response_cache_storage_cache_name_ = response.cache_storage_cache_name;
CreateResponseHeader(
response.status_code, response.status_text, response.headers);
load_timing_info_.receive_headers_end = base::TimeTicks::Now();
@@ -762,8 +774,7 @@ void ServiceWorkerURLRequestJob::RecordResult(
return;
}
did_record_result_ = true;
- ServiceWorkerMetrics::RecordURLRequestJobResult(is_main_resource_load_,
- result);
+ ServiceWorkerMetrics::RecordURLRequestJobResult(IsMainResourceLoad(), result);
if (request())
request()->net_log().AddEvent(RequestJobResultToNetEventType(result));
}
@@ -777,7 +788,7 @@ void ServiceWorkerURLRequestJob::RecordStatusZeroResponseError(
return;
}
RecordResult(ServiceWorkerMetrics::REQUEST_JOB_ERROR_RESPONSE_STATUS_ZERO);
- ServiceWorkerMetrics::RecordStatusZeroResponseError(is_main_resource_load_,
+ ServiceWorkerMetrics::RecordStatusZeroResponseError(IsMainResourceLoad(),
error);
}
@@ -823,13 +834,20 @@ void ServiceWorkerURLRequestJob::OnStartCompleted() const {
GURL() /* original_url_via_service_worker */,
blink::WebServiceWorkerResponseTypeDefault,
base::TimeTicks() /* service_worker_start_time */,
- base::TimeTicks() /* service_worker_ready_time */);
+ base::TimeTicks() /* service_worker_ready_time */,
+ false /* respons_is_in_cache_storage */,
+ std::string() /* response_cache_storage_cache_name */);
return;
}
delegate_->OnStartCompleted(true /* was_fetched_via_service_worker */,
fall_back_required_, response_url_,
service_worker_response_type_, worker_start_time_,
- worker_ready_time_);
+ worker_ready_time_, response_is_in_cache_storage_,
+ response_cache_storage_cache_name_);
+}
+
+bool ServiceWorkerURLRequestJob::IsMainResourceLoad() const {
+ return ServiceWorkerUtils::IsMainResourceType(resource_type_);
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_url_request_job.h b/chromium/content/browser/service_worker/service_worker_url_request_job.h
index 8f9946d4547..9c4101f5d3d 100644
--- a/chromium/content/browser/service_worker/service_worker_url_request_job.h
+++ b/chromium/content/browser/service_worker/service_worker_url_request_job.h
@@ -75,7 +75,9 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob
const GURL& original_url_via_service_worker,
blink::WebServiceWorkerResponseType response_type_via_service_worker,
base::TimeTicks worker_start_time,
- base::TimeTicks service_worker_ready_time) = 0;
+ base::TimeTicks service_worker_ready_time,
+ bool response_is_in_cache_storage,
+ const std::string& response_cache_storage_cache_name) = 0;
// Returns the ServiceWorkerVersion fetch events for this request job should
// be dispatched to. If no appropriate worker can be determined, returns
@@ -92,9 +94,6 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob
// Called to signal that loading failed, and that the resource being loaded
// was a main resource.
virtual void MainResourceLoadFailed() {}
-
- // Returns the origin of the page/context which initiated this request.
- virtual GURL GetRequestingOrigin() = 0;
};
ServiceWorkerURLRequestJob(
@@ -106,10 +105,11 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob
FetchRequestMode request_mode,
FetchCredentialsMode credentials_mode,
FetchRedirectMode redirect_mode,
- bool is_main_resource_load,
+ ResourceType resource_type,
RequestContextType request_context_type,
RequestContextFrameType frame_type,
scoped_refptr<ResourceRequestBody> body,
+ ServiceWorkerFetchType fetch_type,
Delegate* delegate);
~ServiceWorkerURLRequestJob() override;
@@ -190,10 +190,11 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob
// For FORWARD_TO_SERVICE_WORKER case.
void DidPrepareFetchEvent();
- void DidDispatchFetchEvent(ServiceWorkerStatusCode status,
- ServiceWorkerFetchEventResult fetch_result,
- const ServiceWorkerResponse& response,
- scoped_refptr<ServiceWorkerVersion> version);
+ void DidDispatchFetchEvent(
+ ServiceWorkerStatusCode status,
+ ServiceWorkerFetchEventResult fetch_result,
+ const ServiceWorkerResponse& response,
+ const scoped_refptr<ServiceWorkerVersion>& version);
// Populates |http_response_headers_|.
void CreateResponseHeader(int status_code,
@@ -228,6 +229,8 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob
// calls it.
void OnStartCompleted() const;
+ bool IsMainResourceLoad() const;
+
// Not owned.
Delegate* delegate_;
@@ -262,7 +265,7 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob
FetchRequestMode request_mode_;
FetchCredentialsMode credentials_mode_;
FetchRedirectMode redirect_mode_;
- const bool is_main_resource_load_;
+ const ResourceType resource_type_;
RequestContextType request_context_type_;
RequestContextFrameType frame_type_;
bool fall_back_required_;
@@ -271,10 +274,14 @@ class CONTENT_EXPORT ServiceWorkerURLRequestJob
scoped_refptr<ResourceRequestBody> body_;
scoped_ptr<storage::BlobDataHandle> request_body_blob_data_handle_;
scoped_refptr<ServiceWorkerVersion> streaming_version_;
+ ServiceWorkerFetchType fetch_type_;
ResponseBodyType response_body_type_ = UNKNOWN;
bool did_record_result_ = false;
+ bool response_is_in_cache_storage_ = false;
+ std::string response_cache_storage_cache_name_;
+
base::WeakPtrFactory<ServiceWorkerURLRequestJob> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerURLRequestJob);
diff --git a/chromium/content/browser/service_worker/service_worker_url_request_job_unittest.cc b/chromium/content/browser/service_worker/service_worker_url_request_job_unittest.cc
index 80c5bd39390..6440dd12c2a 100644
--- a/chromium/content/browser/service_worker/service_worker_url_request_job_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_url_request_job_unittest.cc
@@ -72,7 +72,9 @@ class TestCallbackTracker {
const GURL& original_url_via_service_worker,
blink::WebServiceWorkerResponseType response_type_via_service_worker,
base::TimeTicks service_worker_start_time,
- base::TimeTicks service_worker_ready_time) {
+ base::TimeTicks service_worker_ready_time,
+ bool response_is_in_cache_storage,
+ const std::string& response_cache_storage_cache_name) {
++times_on_start_completed_invoked_;
was_fetched_via_service_worker_ = was_fetched_via_service_worker;
@@ -82,6 +84,8 @@ class TestCallbackTracker {
blink::WebServiceWorkerResponseTypeDefault;
service_worker_start_time_ = service_worker_start_time;
service_worker_ready_time_ = service_worker_ready_time;
+ response_is_in_cache_storage_ = response_is_in_cache_storage;
+ response_cache_storage_cache_name_ = response_cache_storage_cache_name;
}
void OnPrepareToRestart(base::TimeTicks service_worker_start_time,
@@ -127,6 +131,14 @@ class TestCallbackTracker {
return service_worker_ready_time_;
}
+ bool response_is_in_cache_storage() const {
+ return response_is_in_cache_storage_;
+ }
+
+ const std::string& response_cache_storage_cache_name() const {
+ return response_cache_storage_cache_name_;
+ }
+
private:
int times_on_start_completed_invoked_ = 0;
int times_prepare_to_restart_invoked_ = 0;
@@ -140,6 +152,8 @@ class TestCallbackTracker {
blink::WebServiceWorkerResponseTypeDefault;
base::TimeTicks service_worker_start_time_;
base::TimeTicks service_worker_ready_time_;
+ bool response_is_in_cache_storage_ = false;
+ std::string response_cache_storage_cache_name_;
DISALLOW_COPY_AND_ASSIGN(TestCallbackTracker);
};
@@ -174,9 +188,10 @@ class MockHttpProtocolHandler
request, network_delegate, provider_host_->client_uuid(),
blob_storage_context_, resource_context_, FETCH_REQUEST_MODE_NO_CORS,
FETCH_CREDENTIALS_MODE_OMIT, FetchRedirectMode::FOLLOW_MODE,
- true /* is_main_resource_load */, REQUEST_CONTEXT_TYPE_HYPERLINK,
+ RESOURCE_TYPE_MAIN_FRAME, REQUEST_CONTEXT_TYPE_HYPERLINK,
REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL,
- scoped_refptr<ResourceRequestBody>(), delegate_);
+ scoped_refptr<ResourceRequestBody>(), ServiceWorkerFetchType::FETCH,
+ delegate_);
job_->ForwardToServiceWorker();
return job_;
}
@@ -346,11 +361,14 @@ class ServiceWorkerURLRequestJobTest
const GURL& original_url_via_service_worker,
blink::WebServiceWorkerResponseType response_type_via_service_worker,
base::TimeTicks worker_start_time,
- base::TimeTicks service_worker_ready_time) override {
+ base::TimeTicks service_worker_ready_time,
+ bool response_is_in_cache_storage,
+ const std::string& response_cache_storage_cache_name) override {
callback_tracker_.OnStartCompleted(
was_fetched_via_service_worker, was_fallback_required,
original_url_via_service_worker, response_type_via_service_worker,
- worker_start_time, service_worker_ready_time);
+ worker_start_time, service_worker_ready_time,
+ response_is_in_cache_storage, response_cache_storage_cache_name);
}
ServiceWorkerVersion* GetServiceWorkerVersion(
@@ -381,11 +399,6 @@ class ServiceWorkerURLRequestJobTest
provider_host_->NotifyControllerLost();
}
- GURL GetRequestingOrigin() override {
- CHECK(provider_host_);
- return provider_host_->document_url().GetOrigin();
- }
-
TestBrowserThreadBundle thread_bundle_;
scoped_ptr<TestBrowserContext> browser_context_;
@@ -420,6 +433,9 @@ TEST_F(ServiceWorkerURLRequestJobTest, Simple) {
callback_tracker_.response_type_via_service_worker());
EXPECT_FALSE(callback_tracker_.service_worker_start_time().is_null());
EXPECT_FALSE(callback_tracker_.service_worker_ready_time().is_null());
+ EXPECT_FALSE(callback_tracker_.response_is_in_cache_storage());
+ EXPECT_EQ(std::string(),
+ callback_tracker_.response_cache_storage_cache_name());
}
class ProviderDeleteHelper : public EmbeddedWorkerTestHelper {
@@ -438,7 +454,9 @@ class ProviderDeleteHelper : public EmbeddedWorkerTestHelper {
ServiceWorkerResponse(
GURL(), 200, "OK", blink::WebServiceWorkerResponseTypeDefault,
ServiceWorkerHeaderMap(), std::string(), 0, GURL(),
- blink::WebServiceWorkerResponseErrorUnknown)));
+ blink::WebServiceWorkerResponseErrorUnknown, base::Time(),
+ false /* response_is_in_cache_storage */,
+ std::string() /* response_cache_storage_cache_name */)));
}
private:
@@ -510,7 +528,9 @@ class BlobResponder : public EmbeddedWorkerTestHelper {
ServiceWorkerResponse(
GURL(), 200, "OK", blink::WebServiceWorkerResponseTypeDefault,
ServiceWorkerHeaderMap(), blob_uuid_, blob_size_, GURL(),
- blink::WebServiceWorkerResponseErrorUnknown)));
+ blink::WebServiceWorkerResponseErrorUnknown, base::Time(),
+ false /* response_is_in_cache_storage */,
+ std::string() /* response_cache_storage_cache_name */)));
}
std::string blob_uuid_;
@@ -579,10 +599,12 @@ class StreamResponder : public EmbeddedWorkerTestHelper {
SimulateSend(new ServiceWorkerHostMsg_FetchEventFinished(
embedded_worker_id, request_id,
SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
- ServiceWorkerResponse(GURL(), 200, "OK",
- blink::WebServiceWorkerResponseTypeDefault,
- ServiceWorkerHeaderMap(), "", 0, stream_url_,
- blink::WebServiceWorkerResponseErrorUnknown)));
+ ServiceWorkerResponse(
+ GURL(), 200, "OK", blink::WebServiceWorkerResponseTypeDefault,
+ ServiceWorkerHeaderMap(), "", 0, stream_url_,
+ blink::WebServiceWorkerResponseErrorUnknown, base::Time(),
+ false /* response_is_in_cache_storage */,
+ std::string() /* response_cache_storage_cache_name */)));
}
const GURL stream_url_;
diff --git a/chromium/content/browser/service_worker/service_worker_version.cc b/chromium/content/browser/service_worker/service_worker_version.cc
index 54268049a22..cf3c209d330 100644
--- a/chromium/content/browser/service_worker/service_worker_version.cc
+++ b/chromium/content/browser/service_worker/service_worker_version.cc
@@ -6,6 +6,7 @@
#include <stddef.h>
+#include <limits>
#include <map>
#include <string>
@@ -32,6 +33,7 @@
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_metrics.h"
#include "content/browser/service_worker/service_worker_registration.h"
+#include "content/common/service_worker/embedded_worker_messages.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_type_converters.h"
#include "content/common/service_worker/service_worker_utils.h"
@@ -62,10 +64,6 @@ const int kUpdateDelaySeconds = 1;
// Timeout for waiting for a response to a ping.
const int kPingTimeoutSeconds = 30;
-// If the SW was destructed while starting up, how many seconds it
-// had to start up for this to be considered a timeout occurrence.
-const int kDestructedStartingWorkerTimeoutThresholdSeconds = 5;
-
const char kClaimClientsStateErrorMesage[] =
"Only the active worker can claim clients.";
@@ -87,29 +85,6 @@ void RunCallbacks(ServiceWorkerVersion* version,
callback.Run(arg);
}
-template <typename IDMAP, typename... Params>
-void RunIDMapCallbacks(IDMAP* requests, const Params&... params) {
- typename IDMAP::iterator iter(requests);
- while (!iter.IsAtEnd()) {
- iter.GetCurrentValue()->callback.Run(params...);
- iter.Advance();
- }
- requests->Clear();
-}
-
-template <typename CallbackType, typename... Params>
-bool RunIDMapCallback(IDMap<CallbackType, IDMapOwnPointer>* requests,
- int request_id,
- const Params&... params) {
- CallbackType* request = requests->Lookup(request_id);
- if (!request)
- return false;
-
- request->callback.Run(params...);
- requests->Remove(request_id);
- return true;
-}
-
void RunStartWorkerCallback(
const StatusCallback& callback,
scoped_refptr<ServiceWorkerRegistration> protect,
@@ -139,13 +114,6 @@ void RunTaskAfterStartWorker(
task.Run();
}
-void RunErrorFetchCallback(const ServiceWorkerVersion::FetchCallback& callback,
- ServiceWorkerStatusCode status) {
- callback.Run(status,
- SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK,
- ServiceWorkerResponse());
-}
-
void RunErrorMessageCallback(
const std::vector<TransferredMessagePort>& sent_message_ports,
const ServiceWorkerVersion::StatusCallback& callback,
@@ -202,6 +170,38 @@ bool IsInstalled(ServiceWorkerVersion::Status status) {
return false;
}
+std::string VersionStatusToString(ServiceWorkerVersion::Status status) {
+ switch (status) {
+ case ServiceWorkerVersion::NEW:
+ return "new";
+ case ServiceWorkerVersion::INSTALLING:
+ return "installing";
+ case ServiceWorkerVersion::INSTALLED:
+ return "installed";
+ case ServiceWorkerVersion::ACTIVATING:
+ return "activating";
+ case ServiceWorkerVersion::ACTIVATED:
+ return "activated";
+ case ServiceWorkerVersion::REDUNDANT:
+ return "redundant";
+ }
+ NOTREACHED() << status;
+ return std::string();
+}
+
+const int kInvalidTraceId = -1;
+
+int NextTraceId() {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ static int trace_id = 0;
+ if (trace_id == std::numeric_limits<int>::max())
+ trace_id = 0;
+ else
+ ++trace_id;
+ DCHECK_NE(kInvalidTraceId, trace_id);
+ return trace_id;
+}
+
} // namespace
const int ServiceWorkerVersion::kTimeoutTimerDelaySeconds = 30;
@@ -324,13 +324,13 @@ ServiceWorkerVersion::ServiceWorkerVersion(
ServiceWorkerVersion::~ServiceWorkerVersion() {
in_dtor_ = true;
- // The user may have closed the tab waiting for SW to start up.
- if (GetTickDuration(start_time_) >
- base::TimeDelta::FromSeconds(
- kDestructedStartingWorkerTimeoutThresholdSeconds)) {
- DCHECK(timeout_timer_.IsRunning());
- DCHECK(!embedded_worker_->devtools_attached());
- RecordStartWorkerResult(SERVICE_WORKER_ERROR_TIMEOUT);
+ // Record UMA if the worker was trying to start. One way we get here is if the
+ // user closed the tab before the SW could start up.
+ if (!start_callbacks_.empty()) {
+ // RecordStartWorkerResult must be the first element of start_callbacks_.
+ StatusCallback record_start_worker_result = start_callbacks_[0];
+ start_callbacks_.clear();
+ record_start_worker_result.Run(SERVICE_WORKER_ERROR_ABORT);
}
if (context_)
@@ -388,46 +388,64 @@ ServiceWorkerVersionInfo ServiceWorkerVersion::GetInfo() {
return info;
}
-void ServiceWorkerVersion::StartWorker(const StatusCallback& callback) {
+void ServiceWorkerVersion::StartWorker(ServiceWorkerMetrics::EventType purpose,
+ const StatusCallback& callback) {
+ TRACE_EVENT_INSTANT2(
+ "ServiceWorker", "ServiceWorkerVersion::StartWorker (instant)",
+ TRACE_EVENT_SCOPE_THREAD, "Script", script_url_.spec(), "Purpose",
+ ServiceWorkerMetrics::EventTypeToString(purpose));
+
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ const bool is_browser_startup_complete =
+ GetContentClient()->browser()->IsBrowserStartupComplete();
if (!context_) {
- RecordStartWorkerResult(SERVICE_WORKER_ERROR_ABORT);
+ RecordStartWorkerResult(purpose, status_, kInvalidTraceId,
+ is_browser_startup_complete,
+ SERVICE_WORKER_ERROR_ABORT);
RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_ABORT));
return;
}
if (is_redundant()) {
- RecordStartWorkerResult(SERVICE_WORKER_ERROR_REDUNDANT);
+ RecordStartWorkerResult(purpose, status_, kInvalidTraceId,
+ is_browser_startup_complete,
+ SERVICE_WORKER_ERROR_REDUNDANT);
RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_REDUNDANT));
return;
}
+
// Check that the worker is allowed to start on the given scope. Since this
// worker might not be used for a specific frame/process, use -1.
// resource_context() can return null in unit tests.
if (context_->wrapper()->resource_context() &&
!GetContentClient()->browser()->AllowServiceWorker(
scope_, scope_, context_->wrapper()->resource_context(), -1, -1)) {
- RecordStartWorkerResult(SERVICE_WORKER_ERROR_DISALLOWED);
+ RecordStartWorkerResult(purpose, status_, kInvalidTraceId,
+ is_browser_startup_complete,
+ SERVICE_WORKER_ERROR_DISALLOWED);
RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_DISALLOWED));
return;
}
- prestart_status_ = status_;
-
// Ensure the live registration during starting worker so that the worker can
// get associated with it in SWDispatcherHost::OnSetHostedVersionId().
context_->storage()->FindRegistrationForId(
- registration_id_,
- scope_.GetOrigin(),
+ registration_id_, scope_.GetOrigin(),
base::Bind(&ServiceWorkerVersion::DidEnsureLiveRegistrationForStartWorker,
- weak_factory_.GetWeakPtr(),
- callback));
+ weak_factory_.GetWeakPtr(), purpose, status_,
+ is_browser_startup_complete, callback));
}
void ServiceWorkerVersion::StopWorker(const StatusCallback& callback) {
+ TRACE_EVENT_INSTANT2("ServiceWorker",
+ "ServiceWorkerVersion::StopWorker (instant)",
+ TRACE_EVENT_SCOPE_THREAD, "Script", script_url_.spec(),
+ "Status", VersionStatusToString(status_));
+
if (running_status() == STOPPED) {
RunSoon(base::Bind(callback, SERVICE_WORKER_OK));
return;
}
+
if (stop_callbacks_.empty()) {
ServiceWorkerStatusCode status = embedded_worker_->Stop();
if (status != SERVICE_WORKER_OK) {
@@ -475,11 +493,9 @@ void ServiceWorkerVersion::DeferScheduledUpdate() {
int ServiceWorkerVersion::StartRequest(
ServiceWorkerMetrics::EventType event_type,
const StatusCallback& error_callback) {
- OnBeginEvent();
- DCHECK_EQ(RUNNING, running_status())
- << "Can only start a request with a running worker.";
- return AddRequest(error_callback, &custom_requests_, REQUEST_CUSTOM,
- event_type);
+ return StartRequestWithCustomTimeout(
+ event_type, error_callback,
+ base::TimeDelta::FromMinutes(kRequestTimeoutMinutes), KILL_ON_TIMEOUT);
}
int ServiceWorkerVersion::StartRequestWithCustomTimeout(
@@ -490,25 +506,58 @@ int ServiceWorkerVersion::StartRequestWithCustomTimeout(
OnBeginEvent();
DCHECK_EQ(RUNNING, running_status())
<< "Can only start a request with a running worker.";
- return AddRequestWithExpiration(
- error_callback, &custom_requests_, REQUEST_CUSTOM, event_type,
- base::TimeTicks::Now() + timeout, timeout_behavior);
+ DCHECK(event_type == ServiceWorkerMetrics::EventType::INSTALL ||
+ event_type == ServiceWorkerMetrics::EventType::ACTIVATE ||
+ event_type == ServiceWorkerMetrics::EventType::MESSAGE ||
+ status() == ACTIVATED)
+ << "Event of type " << static_cast<int>(event_type)
+ << " can only be dispatched to an active worker: " << status();
+
+ PendingRequest<StatusCallback>* request = new PendingRequest<StatusCallback>(
+ error_callback, base::TimeTicks::Now(), event_type);
+ int request_id = custom_requests_.Add(request);
+ TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker", "ServiceWorkerVersion::Request",
+ request, "Request id", request_id, "Event type",
+ ServiceWorkerMetrics::EventTypeToString(event_type));
+ base::TimeTicks expiration_time = base::TimeTicks::Now() + timeout;
+ requests_.push(
+ RequestInfo(request_id, event_type, expiration_time, timeout_behavior));
+ return request_id;
}
-bool ServiceWorkerVersion::FinishRequest(int request_id) {
+bool ServiceWorkerVersion::FinishRequest(int request_id, bool was_handled) {
PendingRequest<StatusCallback>* request = custom_requests_.Lookup(request_id);
if (!request)
return false;
+ // TODO(kinuko): Record other event statuses too.
+ metrics_->RecordEventHandledStatus(request->event_type, was_handled);
ServiceWorkerMetrics::RecordEventDuration(
- request->event_type, base::TimeTicks::Now() - request->start_time);
- RemoveCallbackAndStopIfRedundant(&custom_requests_, request_id);
+ request->event_type, base::TimeTicks::Now() - request->start_time,
+ was_handled);
+
+ RestartTick(&idle_time_);
+ TRACE_EVENT_ASYNC_END1("ServiceWorker", "ServiceWorkerVersion::Request",
+ request, "Handled", was_handled);
+ custom_requests_.Remove(request_id);
+ if (is_redundant()) {
+ // The stop should be already scheduled, but try to stop immediately, in
+ // order to release worker resources soon.
+ StopWorkerIfIdle();
+ }
return true;
}
void ServiceWorkerVersion::RunAfterStartWorker(
- const StatusCallback& error_callback,
- const base::Closure& task) {
- StartWorker(base::Bind(&RunTaskAfterStartWorker, weak_factory_.GetWeakPtr(),
+ ServiceWorkerMetrics::EventType purpose,
+ const base::Closure& task,
+ const StatusCallback& error_callback) {
+ if (running_status() == RUNNING) {
+ DCHECK(start_callbacks_.empty());
+ task.Run();
+ return;
+ }
+ StartWorker(purpose,
+ base::Bind(&RunTaskAfterStartWorker, weak_factory_.GetWeakPtr(),
error_callback, task));
}
@@ -530,12 +579,13 @@ void ServiceWorkerVersion::DispatchMessageEventInternal(
OnBeginEvent();
if (running_status() != RUNNING) {
// Schedule calling this method after starting the worker.
- StartWorker(base::Bind(
- &RunTaskAfterStartWorker, weak_factory_.GetWeakPtr(),
- base::Bind(&RunErrorMessageCallback, sent_message_ports, callback),
- base::Bind(&self::DispatchMessageEventInternal,
- weak_factory_.GetWeakPtr(), message, sent_message_ports,
- callback)));
+ StartWorker(ServiceWorkerMetrics::EventType::MESSAGE,
+ base::Bind(&RunTaskAfterStartWorker, weak_factory_.GetWeakPtr(),
+ base::Bind(&RunErrorMessageCallback,
+ sent_message_ports, callback),
+ base::Bind(&self::DispatchMessageEventInternal,
+ weak_factory_.GetWeakPtr(), message,
+ sent_message_ports, callback)));
return;
}
@@ -553,164 +603,6 @@ void ServiceWorkerVersion::DispatchMessageEventInternal(
RunSoon(base::Bind(callback, status));
}
-void ServiceWorkerVersion::DispatchInstallEvent(
- const StatusCallback& callback) {
- OnBeginEvent();
- DCHECK_EQ(INSTALLING, status()) << status();
-
- if (running_status() != RUNNING) {
- // Schedule calling this method after starting the worker.
- StartWorker(
- base::Bind(&RunTaskAfterStartWorker,
- weak_factory_.GetWeakPtr(),
- callback,
- base::Bind(&self::DispatchInstallEventAfterStartWorker,
- weak_factory_.GetWeakPtr(),
- callback)));
- } else {
- DispatchInstallEventAfterStartWorker(callback);
- }
-}
-
-void ServiceWorkerVersion::DispatchActivateEvent(
- const StatusCallback& callback) {
- OnBeginEvent();
- DCHECK_EQ(ACTIVATING, status()) << status();
-
- if (running_status() != RUNNING) {
- // Schedule calling this method after starting the worker.
- StartWorker(
- base::Bind(&RunTaskAfterStartWorker,
- weak_factory_.GetWeakPtr(),
- callback,
- base::Bind(&self::DispatchActivateEventAfterStartWorker,
- weak_factory_.GetWeakPtr(),
- callback)));
- } else {
- DispatchActivateEventAfterStartWorker(callback);
- }
-}
-
-void ServiceWorkerVersion::DispatchFetchEvent(
- const ServiceWorkerFetchRequest& request,
- const base::Closure& prepare_callback,
- const FetchCallback& fetch_callback) {
- OnBeginEvent();
- DCHECK_EQ(ACTIVATED, status()) << status();
-
- if (running_status() != RUNNING) {
- // Schedule calling this method after starting the worker.
- StartWorker(base::Bind(&RunTaskAfterStartWorker,
- weak_factory_.GetWeakPtr(),
- base::Bind(&RunErrorFetchCallback, fetch_callback),
- base::Bind(&self::DispatchFetchEvent,
- weak_factory_.GetWeakPtr(),
- request,
- prepare_callback,
- fetch_callback)));
- return;
- }
-
- prepare_callback.Run();
-
- int request_id = AddRequest(fetch_callback, &fetch_requests_, REQUEST_FETCH,
- ServiceWorkerMetrics::EventType::FETCH);
- ServiceWorkerStatusCode status = embedded_worker_->SendMessage(
- ServiceWorkerMsg_FetchEvent(request_id, request));
- if (status != SERVICE_WORKER_OK) {
- fetch_requests_.Remove(request_id);
- RunSoon(base::Bind(&RunErrorFetchCallback,
- fetch_callback,
- SERVICE_WORKER_ERROR_FAILED));
- }
-}
-
-void ServiceWorkerVersion::DispatchNotificationClickEvent(
- const StatusCallback& callback,
- int64_t persistent_notification_id,
- const PlatformNotificationData& notification_data,
- int action_index) {
- OnBeginEvent();
- DCHECK_EQ(ACTIVATED, status()) << status();
- if (running_status() != RUNNING) {
- // Schedule calling this method after starting the worker.
- StartWorker(base::Bind(
- &RunTaskAfterStartWorker, weak_factory_.GetWeakPtr(), callback,
- base::Bind(&self::DispatchNotificationClickEvent,
- weak_factory_.GetWeakPtr(), callback,
- persistent_notification_id, notification_data,
- action_index)));
- return;
- }
-
- int request_id = AddRequest(
- callback, &notification_click_requests_, REQUEST_NOTIFICATION_CLICK,
- ServiceWorkerMetrics::EventType::NOTIFICATION_CLICK);
- ServiceWorkerStatusCode status =
- embedded_worker_->SendMessage(ServiceWorkerMsg_NotificationClickEvent(
- request_id, persistent_notification_id, notification_data,
- action_index));
- if (status != SERVICE_WORKER_OK) {
- notification_click_requests_.Remove(request_id);
- RunSoon(base::Bind(callback, status));
- }
-}
-
-void ServiceWorkerVersion::DispatchPushEvent(const StatusCallback& callback,
- const std::string& data) {
- OnBeginEvent();
- DCHECK_EQ(ACTIVATED, status()) << status();
- if (running_status() != RUNNING) {
- // Schedule calling this method after starting the worker.
- StartWorker(base::Bind(&RunTaskAfterStartWorker,
- weak_factory_.GetWeakPtr(), callback,
- base::Bind(&self::DispatchPushEvent,
- weak_factory_.GetWeakPtr(),
- callback, data)));
- return;
- }
-
- int request_id = AddRequest(callback, &push_requests_, REQUEST_PUSH,
- ServiceWorkerMetrics::EventType::PUSH);
- ServiceWorkerStatusCode status = embedded_worker_->SendMessage(
- ServiceWorkerMsg_PushEvent(request_id, data));
- if (status != SERVICE_WORKER_OK) {
- push_requests_.Remove(request_id);
- RunSoon(base::Bind(callback, status));
- }
-}
-
-void ServiceWorkerVersion::DispatchCrossOriginMessageEvent(
- const NavigatorConnectClient& client,
- const base::string16& message,
- const std::vector<TransferredMessagePort>& sent_message_ports,
- const StatusCallback& callback) {
- OnBeginEvent();
- // Unlike in the case of DispatchMessageEvent, here the caller is assumed to
- // have already put all the sent message ports on hold. So no need to do that
- // here again.
-
- if (running_status() != RUNNING) {
- // Schedule calling this method after starting the worker.
- StartWorker(base::Bind(
- &RunTaskAfterStartWorker, weak_factory_.GetWeakPtr(),
- base::Bind(&RunErrorMessageCallback, sent_message_ports, callback),
- base::Bind(&self::DispatchCrossOriginMessageEvent,
- weak_factory_.GetWeakPtr(), client, message,
- sent_message_ports, callback)));
- return;
- }
-
- MessagePortMessageFilter* filter =
- embedded_worker_->message_port_message_filter();
- std::vector<int> new_routing_ids;
- filter->UpdateMessagePortsWithNewRoutes(sent_message_ports, &new_routing_ids);
- ServiceWorkerStatusCode status =
- embedded_worker_->SendMessage(ServiceWorkerMsg_CrossOriginMessageToWorker(
- client, message, sent_message_ports, new_routing_ids));
- RunSoon(base::Bind(callback, status));
-}
-
void ServiceWorkerVersion::AddControllee(
ServiceWorkerProviderHost* provider_host) {
const std::string& uuid = provider_host->client_uuid();
@@ -831,12 +723,10 @@ ServiceWorkerVersion::GetMainScriptHttpResponseInfo() {
ServiceWorkerVersion::RequestInfo::RequestInfo(
int id,
- RequestType type,
ServiceWorkerMetrics::EventType event_type,
const base::TimeTicks& expiration,
TimeoutBehavior timeout_behavior)
: id(id),
- type(type),
event_type(event_type),
expiration(expiration),
timeout_behavior(timeout_behavior) {}
@@ -867,6 +757,8 @@ ServiceWorkerVersion::BaseMojoServiceWrapper::~BaseMojoServiceWrapper() {
while (!iter.IsAtEnd()) {
PendingRequest<StatusCallback>* request = iter.GetCurrentValue();
if (request->mojo_service == service_name_) {
+ TRACE_EVENT_ASYNC_END1("ServiceWorker", "ServiceWorkerVersion::Request",
+ request, "Error", "Service Disconnected");
request->callback.Run(SERVICE_WORKER_ERROR_FAILED);
worker_->custom_requests_.Remove(iter.GetCurrentKey());
}
@@ -875,8 +767,6 @@ ServiceWorkerVersion::BaseMojoServiceWrapper::~BaseMojoServiceWrapper() {
}
void ServiceWorkerVersion::OnThreadStarted() {
- if (running_status() == STOPPING)
- return;
DCHECK_EQ(STARTING, running_status());
// Activate ping/pong now that JavaScript execution will start.
ping_controller_->Activate();
@@ -899,6 +789,10 @@ void ServiceWorkerVersion::OnStarted() {
void ServiceWorkerVersion::OnStopping() {
DCHECK(stop_time_.is_null());
RestartTick(&stop_time_);
+ TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker", "ServiceWorkerVersion::StopWorker",
+ stop_time_.ToInternalValue(), "Script",
+ script_url_.spec(), "Version Status",
+ VersionStatusToString(status_));
// Shorten the interval so stalling in stopped can be fixed quickly. Once the
// worker stops, the timer is disabled. The interval will be reset to normal
@@ -969,18 +863,9 @@ void ServiceWorkerVersion::OnReportConsoleMessage(int source_identifier,
bool ServiceWorkerVersion::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(ServiceWorkerVersion, message)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetClient, OnGetClient)
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetClients,
OnGetClients)
- IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ActivateEventFinished,
- OnActivateEventFinished)
- IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_InstallEventFinished,
- OnInstallEventFinished)
- IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_FetchEventFinished,
- OnFetchEventFinished)
- IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_NotificationClickEventFinished,
- OnNotificationClickEventFinished)
- IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PushEventFinished,
- OnPushEventFinished)
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_OpenWindow,
OnOpenWindow)
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SetCachedMetadata,
@@ -1013,34 +898,39 @@ void ServiceWorkerVersion::OnStartSentAndScriptEvaluated(
}
}
-void ServiceWorkerVersion::DispatchInstallEventAfterStartWorker(
- const StatusCallback& callback) {
- DCHECK_EQ(RUNNING, running_status())
- << "Worker stopped too soon after it was started.";
-
- int request_id = AddRequest(callback, &install_requests_, REQUEST_INSTALL,
- ServiceWorkerMetrics::EventType::INSTALL);
- ServiceWorkerStatusCode status = embedded_worker_->SendMessage(
- ServiceWorkerMsg_InstallEvent(request_id));
- if (status != SERVICE_WORKER_OK) {
- install_requests_.Remove(request_id);
- RunSoon(base::Bind(callback, status));
+void ServiceWorkerVersion::OnGetClient(int request_id,
+ const std::string& client_uuid) {
+ if (!context_)
+ return;
+ TRACE_EVENT_ASYNC_BEGIN1("ServiceWorker", "ServiceWorkerVersion::OnGetClient",
+ request_id, "client_uuid", client_uuid);
+ ServiceWorkerProviderHost* provider_host =
+ context_->GetProviderHostByClientID(client_uuid);
+ if (!provider_host ||
+ provider_host->document_url().GetOrigin() != script_url_.GetOrigin()) {
+ // The promise will be resolved to 'undefined'.
+ OnGetClientFinished(request_id, ServiceWorkerClientInfo());
+ return;
}
+ service_worker_client_utils::GetClient(
+ provider_host, base::Bind(&ServiceWorkerVersion::OnGetClientFinished,
+ weak_factory_.GetWeakPtr(), request_id));
}
-void ServiceWorkerVersion::DispatchActivateEventAfterStartWorker(
- const StatusCallback& callback) {
- DCHECK_EQ(RUNNING, running_status())
- << "Worker stopped too soon after it was started.";
+void ServiceWorkerVersion::OnGetClientFinished(
+ int request_id,
+ const ServiceWorkerClientInfo& client_info) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ TRACE_EVENT_ASYNC_END1("ServiceWorker", "ServiceWorkerVersion::OnGetClient",
+ request_id, "client_type", client_info.client_type);
- int request_id = AddRequest(callback, &activate_requests_, REQUEST_ACTIVATE,
- ServiceWorkerMetrics::EventType::ACTIVATE);
- ServiceWorkerStatusCode status =
- embedded_worker_->SendMessage(ServiceWorkerMsg_ActivateEvent(request_id));
- if (status != SERVICE_WORKER_OK) {
- activate_requests_.Remove(request_id);
- RunSoon(base::Bind(callback, status));
- }
+ // When Clients.get() is called on the script evaluation phase, the running
+ // status can be STARTING here.
+ if (running_status() != STARTING && running_status() != RUNNING)
+ return;
+
+ embedded_worker_->SendMessage(
+ ServiceWorkerMsg_DidGetClient(request_id, client_info));
}
void ServiceWorkerVersion::OnGetClients(
@@ -1071,126 +961,21 @@ void ServiceWorkerVersion::OnGetClientsFinished(int request_id,
ServiceWorkerMsg_DidGetClients(request_id, *clients));
}
-void ServiceWorkerVersion::OnActivateEventFinished(
- int request_id,
- blink::WebServiceWorkerEventResult result) {
- DCHECK(ACTIVATING == status() ||
- REDUNDANT == status()) << status();
- TRACE_EVENT0("ServiceWorker",
- "ServiceWorkerVersion::OnActivateEventFinished");
-
- PendingRequest<StatusCallback>* request =
- activate_requests_.Lookup(request_id);
- if (!request) {
- NOTREACHED() << "Got unexpected message: " << request_id;
- return;
- }
- ServiceWorkerStatusCode rv = SERVICE_WORKER_OK;
- if (result == blink::WebServiceWorkerEventResultRejected)
- rv = SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED;
-
- ServiceWorkerMetrics::RecordEventDuration(
- request->event_type, base::TimeTicks::Now() - request->start_time);
-
- scoped_refptr<ServiceWorkerVersion> protect(this);
- request->callback.Run(rv);
- RemoveCallbackAndStopIfRedundant(&activate_requests_, request_id);
-}
-
-void ServiceWorkerVersion::OnInstallEventFinished(
+void ServiceWorkerVersion::OnSimpleEventResponse(
int request_id,
blink::WebServiceWorkerEventResult result) {
- // Status is REDUNDANT if the worker was doomed while handling the install
- // event, and finished handling before being terminated.
- DCHECK(status() == INSTALLING || status() == REDUNDANT) << status();
- TRACE_EVENT0("ServiceWorker",
- "ServiceWorkerVersion::OnInstallEventFinished");
-
- PendingRequest<StatusCallback>* request =
- install_requests_.Lookup(request_id);
- if (!request) {
- NOTREACHED() << "Got unexpected message: " << request_id;
- return;
- }
- ServiceWorkerStatusCode status = SERVICE_WORKER_OK;
- if (result == blink::WebServiceWorkerEventResultRejected)
- status = SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED;
-
- ServiceWorkerMetrics::RecordEventDuration(
- request->event_type, base::TimeTicks::Now() - request->start_time);
-
- scoped_refptr<ServiceWorkerVersion> protect(this);
- request->callback.Run(status);
- RemoveCallbackAndStopIfRedundant(&install_requests_, request_id);
-}
-
-void ServiceWorkerVersion::OnFetchEventFinished(
- int request_id,
- ServiceWorkerFetchEventResult result,
- const ServiceWorkerResponse& response) {
- TRACE_EVENT1("ServiceWorker",
- "ServiceWorkerVersion::OnFetchEventFinished",
- "Request id", request_id);
- PendingRequest<FetchCallback>* request = fetch_requests_.Lookup(request_id);
- if (!request) {
- NOTREACHED() << "Got unexpected message: " << request_id;
- return;
- }
-
- // TODO(kinuko): Record other event statuses too.
- const bool handled = (result == SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE);
- metrics_->RecordEventHandledStatus(ServiceWorkerMetrics::EventType::FETCH,
- handled);
-
- ServiceWorkerMetrics::RecordFetchEventTime(
- result, base::TimeTicks::Now() - request->start_time);
-
- scoped_refptr<ServiceWorkerVersion> protect(this);
- request->callback.Run(SERVICE_WORKER_OK, result, response);
- RemoveCallbackAndStopIfRedundant(&fetch_requests_, request_id);
-}
-
-void ServiceWorkerVersion::OnNotificationClickEventFinished(
- int request_id) {
- TRACE_EVENT1("ServiceWorker",
- "ServiceWorkerVersion::OnNotificationClickEventFinished",
- "Request id", request_id);
- PendingRequest<StatusCallback>* request =
- notification_click_requests_.Lookup(request_id);
- if (!request) {
- NOTREACHED() << "Got unexpected message: " << request_id;
- return;
- }
-
- ServiceWorkerMetrics::RecordEventDuration(
- request->event_type, base::TimeTicks::Now() - request->start_time);
+ // Copy error callback before calling FinishRequest.
+ PendingRequest<StatusCallback>* request = custom_requests_.Lookup(request_id);
+ DCHECK(request) << "Invalid request id";
+ StatusCallback callback = request->callback;
- scoped_refptr<ServiceWorkerVersion> protect(this);
- request->callback.Run(SERVICE_WORKER_OK);
- RemoveCallbackAndStopIfRedundant(&notification_click_requests_, request_id);
-}
+ FinishRequest(request_id,
+ result == blink::WebServiceWorkerEventResultCompleted);
-void ServiceWorkerVersion::OnPushEventFinished(
- int request_id,
- blink::WebServiceWorkerEventResult result) {
- TRACE_EVENT1("ServiceWorker",
- "ServiceWorkerVersion::OnPushEventFinished",
- "Request id", request_id);
- PendingRequest<StatusCallback>* request = push_requests_.Lookup(request_id);
- if (!request) {
- NOTREACHED() << "Got unexpected message: " << request_id;
- return;
- }
ServiceWorkerStatusCode status = SERVICE_WORKER_OK;
if (result == blink::WebServiceWorkerEventResultRejected)
status = SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED;
-
- ServiceWorkerMetrics::RecordEventDuration(
- request->event_type, base::TimeTicks::Now() - request->start_time);
-
- scoped_refptr<ServiceWorkerVersion> protect(this);
- request->callback.Run(status);
- RemoveCallbackAndStopIfRedundant(&push_requests_, request_id);
+ callback.Run(status);
}
void ServiceWorkerVersion::OnOpenWindow(int request_id, GURL url) {
@@ -1232,7 +1017,6 @@ void ServiceWorkerVersion::OnOpenWindow(int request_id, GURL url) {
void ServiceWorkerVersion::OnOpenWindowFinished(
int request_id,
ServiceWorkerStatusCode status,
- const std::string& client_uuid,
const ServiceWorkerClientInfo& client_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -1245,16 +1029,8 @@ void ServiceWorkerVersion::OnOpenWindowFinished(
return;
}
- ServiceWorkerClientInfo client(client_info);
-
- // If the |client_info| is empty, it means that the opened window wasn't
- // controlled but the action still succeeded. The renderer process is
- // expecting an empty client in such case.
- if (!client.IsEmpty())
- client.client_uuid = client_uuid;
-
- embedded_worker_->SendMessage(ServiceWorkerMsg_OpenWindowResponse(
- request_id, client));
+ embedded_worker_->SendMessage(
+ ServiceWorkerMsg_OpenWindowResponse(request_id, client_info));
}
void ServiceWorkerVersion::OnSetCachedMetadata(const GURL& url,
@@ -1336,25 +1112,27 @@ void ServiceWorkerVersion::OnFocusClient(int request_id,
// possibly due to timing issue or bad message.
return;
}
- provider_host->Focus(base::Bind(&ServiceWorkerVersion::OnFocusClientFinished,
- weak_factory_.GetWeakPtr(), request_id,
- client_uuid));
+ if (provider_host->client_type() != blink::WebServiceWorkerClientTypeWindow) {
+ // focus() should be called only for WindowClient. This may happen due to
+ // bad message.
+ return;
+ }
+
+ service_worker_client_utils::FocusWindowClient(
+ provider_host, base::Bind(&ServiceWorkerVersion::OnFocusClientFinished,
+ weak_factory_.GetWeakPtr(), request_id));
}
void ServiceWorkerVersion::OnFocusClientFinished(
int request_id,
- const std::string& client_uuid,
- const ServiceWorkerClientInfo& client) {
+ const ServiceWorkerClientInfo& client_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (running_status() != RUNNING)
return;
- ServiceWorkerClientInfo client_info(client);
- client_info.client_uuid = client_uuid;
-
- embedded_worker_->SendMessage(ServiceWorkerMsg_FocusClientResponse(
- request_id, client_info));
+ embedded_worker_->SendMessage(
+ ServiceWorkerMsg_FocusClientResponse(request_id, client_info));
}
void ServiceWorkerVersion::OnNavigateClient(int request_id,
@@ -1403,7 +1181,6 @@ void ServiceWorkerVersion::OnNavigateClient(int request_id,
void ServiceWorkerVersion::OnNavigateClientFinished(
int request_id,
ServiceWorkerStatusCode status,
- const std::string& client_uuid,
const ServiceWorkerClientInfo& client_info) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
@@ -1416,16 +1193,8 @@ void ServiceWorkerVersion::OnNavigateClientFinished(
return;
}
- ServiceWorkerClientInfo client(client_info);
-
- // If the |client_info| is empty, it means that the navigated client wasn't
- // controlled but the action still succeeded. The renderer process is
- // expecting an empty client in such case.
- if (!client.IsEmpty())
- client.client_uuid = client_uuid;
-
embedded_worker_->SendMessage(
- ServiceWorkerMsg_NavigateClientResponse(request_id, client));
+ ServiceWorkerMsg_NavigateClientResponse(request_id, client_info));
}
void ServiceWorkerVersion::OnSkipWaiting(int request_id) {
@@ -1476,7 +1245,8 @@ void ServiceWorkerVersion::OnPongFromWorker() {
}
void ServiceWorkerVersion::OnRegisterForeignFetchScopes(
- const std::vector<GURL>& sub_scopes) {
+ const std::vector<GURL>& sub_scopes,
+ const std::vector<url::Origin>& origins) {
DCHECK(status() == INSTALLING || status() == REDUNDANT) << status();
// Renderer should have already verified all these urls are inside the
// worker's scope, but verify again here on the browser process side.
@@ -1494,11 +1264,24 @@ void ServiceWorkerVersion::OnRegisterForeignFetchScopes(
return;
}
}
- foreign_fetch_scopes_.insert(foreign_fetch_scopes_.end(), sub_scopes.begin(),
- sub_scopes.end());
+ for (const url::Origin& url : origins) {
+ if (url.unique()) {
+ DVLOG(1) << "Received unexpected unique origin from renderer process.";
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&KillEmbeddedWorkerProcess, embedded_worker_->process_id(),
+ RESULT_CODE_KILLED_BAD_MESSAGE));
+ return;
+ }
+ }
+ set_foreign_fetch_scopes(sub_scopes);
+ set_foreign_fetch_origins(origins);
}
void ServiceWorkerVersion::DidEnsureLiveRegistrationForStartWorker(
+ ServiceWorkerMetrics::EventType purpose,
+ Status prestart_status,
+ bool is_browser_startup_complete,
const StatusCallback& callback,
ServiceWorkerStatusCode status,
const scoped_refptr<ServiceWorkerRegistration>& registration) {
@@ -1515,12 +1298,15 @@ void ServiceWorkerVersion::DidEnsureLiveRegistrationForStartWorker(
}
}
if (status != SERVICE_WORKER_OK) {
- RecordStartWorkerResult(status);
+ RecordStartWorkerResult(purpose, prestart_status, kInvalidTraceId,
+ is_browser_startup_complete, status);
RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_START_WORKER_FAILED));
return;
}
if (is_redundant()) {
- RecordStartWorkerResult(SERVICE_WORKER_ERROR_REDUNDANT);
+ RecordStartWorkerResult(purpose, prestart_status, kInvalidTraceId,
+ is_browser_startup_complete,
+ SERVICE_WORKER_ERROR_REDUNDANT);
RunSoon(base::Bind(callback, SERVICE_WORKER_ERROR_REDUNDANT));
return;
}
@@ -1531,34 +1317,54 @@ void ServiceWorkerVersion::DidEnsureLiveRegistrationForStartWorker(
case RUNNING:
RunSoon(base::Bind(callback, SERVICE_WORKER_OK));
return;
+ case STARTING:
+ DCHECK(!start_callbacks_.empty());
+ break;
case STOPPING:
case STOPPED:
- case STARTING:
if (start_callbacks_.empty()) {
+ int trace_id = NextTraceId();
+ TRACE_EVENT_ASYNC_BEGIN2(
+ "ServiceWorker", "ServiceWorkerVersion::StartWorker", trace_id,
+ "Script", script_url_.spec(), "Purpose",
+ ServiceWorkerMetrics::EventTypeToString(purpose));
start_callbacks_.push_back(
base::Bind(&ServiceWorkerVersion::RecordStartWorkerResult,
- weak_factory_.GetWeakPtr()));
+ weak_factory_.GetWeakPtr(), purpose, prestart_status,
+ trace_id, is_browser_startup_complete));
}
- // Keep the live registration while starting the worker.
- start_callbacks_.push_back(
- base::Bind(&RunStartWorkerCallback, callback, protect));
- StartWorkerInternal();
- return;
+ break;
}
+
+ // Keep the live registration while starting the worker.
+ start_callbacks_.push_back(
+ base::Bind(&RunStartWorkerCallback, callback, protect));
+
+ if (running_status() == STOPPED)
+ StartWorkerInternal();
+ DCHECK(timeout_timer_.IsRunning());
}
void ServiceWorkerVersion::StartWorkerInternal() {
- if (!metrics_)
- metrics_.reset(new Metrics(this));
+ DCHECK_EQ(STOPPED, running_status());
- if (!timeout_timer_.IsRunning())
- StartTimeoutTimer();
- if (running_status() == STOPPED) {
- embedded_worker_->Start(
- version_id_, scope_, script_url_,
- base::Bind(&ServiceWorkerVersion::OnStartSentAndScriptEvaluated,
- weak_factory_.GetWeakPtr()));
- }
+ DCHECK(!metrics_);
+ metrics_.reset(new Metrics(this));
+
+ StartTimeoutTimer();
+
+ scoped_ptr<EmbeddedWorkerMsg_StartWorker_Params> params(
+ new EmbeddedWorkerMsg_StartWorker_Params());
+ params->service_worker_version_id = version_id_;
+ params->scope = scope_;
+ params->script_url = script_url_;
+ params->is_installed = IsInstalled(status_);
+ params->pause_after_download = pause_after_download_;
+
+ embedded_worker_->Start(
+ std::move(params),
+ base::Bind(&ServiceWorkerVersion::OnStartSentAndScriptEvaluated,
+ weak_factory_.GetWeakPtr()));
}
void ServiceWorkerVersion::StartTimeoutTimer() {
@@ -1719,24 +1525,35 @@ void ServiceWorkerVersion::StopWorkerIfIdle() {
}
bool ServiceWorkerVersion::HasInflightRequests() const {
- return !activate_requests_.IsEmpty() || !install_requests_.IsEmpty() ||
- !fetch_requests_.IsEmpty() ||
- !notification_click_requests_.IsEmpty() || !push_requests_.IsEmpty() ||
- !custom_requests_.IsEmpty() || !streaming_url_request_jobs_.empty();
+ return !custom_requests_.IsEmpty() || !streaming_url_request_jobs_.empty();
}
void ServiceWorkerVersion::RecordStartWorkerResult(
+ ServiceWorkerMetrics::EventType purpose,
+ Status prestart_status,
+ int trace_id,
+ bool is_browser_startup_complete,
ServiceWorkerStatusCode status) {
+ if (trace_id != kInvalidTraceId) {
+ TRACE_EVENT_ASYNC_END1("ServiceWorker", "ServiceWorkerVersion::StartWorker",
+ trace_id, "Status",
+ ServiceWorkerStatusToString(status));
+ }
base::TimeTicks start_time = start_time_;
ClearTick(&start_time_);
- ServiceWorkerMetrics::RecordStartWorkerStatus(status,
- IsInstalled(prestart_status_));
+ if (context_)
+ context_->UpdateVersionFailureCount(version_id_, status);
+
+ ServiceWorkerMetrics::RecordStartWorkerStatus(status, purpose,
+ IsInstalled(prestart_status));
if (status == SERVICE_WORKER_OK && !start_time.is_null() &&
!skip_recording_startup_time_) {
- ServiceWorkerMetrics::RecordStartWorkerTime(GetTickDuration(start_time),
- IsInstalled(prestart_status_));
+ ServiceWorkerMetrics::RecordStartWorkerTime(
+ GetTickDuration(start_time), IsInstalled(prestart_status),
+ ServiceWorkerMetrics::GetStartSituation(
+ is_browser_startup_complete, embedded_worker_->is_new_process()));
}
if (status != SERVICE_WORKER_ERROR_TIMEOUT)
@@ -1763,73 +1580,16 @@ void ServiceWorkerVersion::RecordStartWorkerResult(
EmbeddedWorkerInstance::STARTING_PHASE_MAX_VALUE);
}
-template <typename IDMAP>
-void ServiceWorkerVersion::RemoveCallbackAndStopIfRedundant(IDMAP* callbacks,
- int request_id) {
- RestartTick(&idle_time_);
- callbacks->Remove(request_id);
- if (is_redundant()) {
- // The stop should be already scheduled, but try to stop immediately, in
- // order to release worker resources soon.
- StopWorkerIfIdle();
- }
-}
-
-template <typename CallbackType>
-int ServiceWorkerVersion::AddRequest(
- const CallbackType& callback,
- IDMap<PendingRequest<CallbackType>, IDMapOwnPointer>* callback_map,
- RequestType request_type,
- ServiceWorkerMetrics::EventType event_type) {
- base::TimeTicks expiration_time =
- base::TimeTicks::Now() +
- base::TimeDelta::FromMinutes(kRequestTimeoutMinutes);
- return AddRequestWithExpiration(callback, callback_map, request_type,
- event_type, expiration_time, KILL_ON_TIMEOUT);
-}
-
-template <typename CallbackType>
-int ServiceWorkerVersion::AddRequestWithExpiration(
- const CallbackType& callback,
- IDMap<PendingRequest<CallbackType>, IDMapOwnPointer>* callback_map,
- RequestType request_type,
- ServiceWorkerMetrics::EventType event_type,
- base::TimeTicks expiration,
- TimeoutBehavior timeout_behavior) {
- int request_id = callback_map->Add(new PendingRequest<CallbackType>(
- callback, base::TimeTicks::Now(), event_type));
- requests_.push(RequestInfo(request_id, request_type, event_type, expiration,
- timeout_behavior));
- return request_id;
-}
-
bool ServiceWorkerVersion::MaybeTimeOutRequest(const RequestInfo& info) {
- switch (info.type) {
- case REQUEST_ACTIVATE:
- return RunIDMapCallback(&activate_requests_, info.id,
- SERVICE_WORKER_ERROR_TIMEOUT);
- case REQUEST_INSTALL:
- return RunIDMapCallback(&install_requests_, info.id,
- SERVICE_WORKER_ERROR_TIMEOUT);
- case REQUEST_FETCH:
- return RunIDMapCallback(
- &fetch_requests_, info.id, SERVICE_WORKER_ERROR_TIMEOUT,
- /* The other args are ignored for non-OK status. */
- SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK, ServiceWorkerResponse());
- case REQUEST_NOTIFICATION_CLICK:
- return RunIDMapCallback(&notification_click_requests_, info.id,
- SERVICE_WORKER_ERROR_TIMEOUT);
- case REQUEST_PUSH:
- return RunIDMapCallback(&push_requests_, info.id,
- SERVICE_WORKER_ERROR_TIMEOUT);
- case REQUEST_CUSTOM:
- return RunIDMapCallback(&custom_requests_, info.id,
- SERVICE_WORKER_ERROR_TIMEOUT);
- case NUM_REQUEST_TYPES:
- break;
- }
- NOTREACHED() << "Got unexpected request type: " << info.type;
- return false;
+ PendingRequest<StatusCallback>* request = custom_requests_.Lookup(info.id);
+ if (!request)
+ return false;
+
+ TRACE_EVENT_ASYNC_END1("ServiceWorker", "ServiceWorkerVersion::Request",
+ request, "Error", "Timeout");
+ request->callback.Run(SERVICE_WORKER_ERROR_TIMEOUT);
+ custom_requests_.Remove(info.id);
+ return true;
}
void ServiceWorkerVersion::SetAllRequestExpirations(
@@ -1917,7 +1677,12 @@ void ServiceWorkerVersion::OnStoppedInternal(
(old_status != EmbeddedWorkerInstance::STARTING) &&
!in_dtor_ && !ping_controller_->IsTimedOut();
- ClearTick(&stop_time_);
+ if (!stop_time_.is_null()) {
+ TRACE_EVENT_ASYNC_END1("ServiceWorker", "ServiceWorkerVersion::StopWorker",
+ stop_time_.ToInternalValue(), "Restart",
+ should_restart);
+ ClearTick(&stop_time_);
+ }
StopTimeoutTimer();
// Fire all stop callbacks.
@@ -1933,16 +1698,15 @@ void ServiceWorkerVersion::OnStoppedInternal(
// Let all message callbacks fail (this will also fire and clear all
// callbacks for events).
// TODO(kinuko): Consider if we want to add queue+resend mechanism here.
- RunIDMapCallbacks(&activate_requests_,
- SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED);
- RunIDMapCallbacks(&install_requests_,
- SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED);
- RunIDMapCallbacks(&fetch_requests_, SERVICE_WORKER_ERROR_FAILED,
- SERVICE_WORKER_FETCH_EVENT_RESULT_FALLBACK,
- ServiceWorkerResponse());
- RunIDMapCallbacks(&notification_click_requests_, SERVICE_WORKER_ERROR_FAILED);
- RunIDMapCallbacks(&push_requests_, SERVICE_WORKER_ERROR_FAILED);
- RunIDMapCallbacks(&custom_requests_, SERVICE_WORKER_ERROR_FAILED);
+ IDMap<PendingRequest<StatusCallback>, IDMapOwnPointer>::iterator iter(
+ &custom_requests_);
+ while (!iter.IsAtEnd()) {
+ TRACE_EVENT_ASYNC_END1("ServiceWorker", "ServiceWorkerVersion::Request",
+ iter.GetCurrentValue(), "Error", "Worker Stopped");
+ iter.GetCurrentValue()->callback.Run(SERVICE_WORKER_ERROR_FAILED);
+ iter.Advance();
+ }
+ custom_requests_.Clear();
// Close all mojo services. This will also fire and clear all callbacks
// for messages that are still outstanding for those services.
diff --git a/chromium/content/browser/service_worker/service_worker_version.h b/chromium/content/browser/service_worker/service_worker_version.h
index 96c54453043..b9517507545 100644
--- a/chromium/content/browser/service_worker/service_worker_version.h
+++ b/chromium/content/browser/service_worker/service_worker_version.h
@@ -7,6 +7,7 @@
#include <stdint.h>
+#include <functional>
#include <map>
#include <queue>
#include <set>
@@ -32,14 +33,14 @@
#include "content/public/common/service_registry.h"
#include "ipc/ipc_message.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerEventResult.h"
+#include "url/gurl.h"
+#include "url/origin.h"
// Windows headers will redefine SendMessage.
#ifdef SendMessage
#undef SendMessage
#endif
-class GURL;
-
namespace net {
class HttpResponseInfo;
}
@@ -51,8 +52,6 @@ class ServiceWorkerContextCore;
class ServiceWorkerProviderHost;
class ServiceWorkerRegistration;
class ServiceWorkerURLRequestJob;
-struct NavigatorConnectClient;
-struct PlatformNotificationData;
struct ServiceWorkerClientInfo;
struct ServiceWorkerVersionInfo;
struct TransferredMessagePort;
@@ -67,9 +66,6 @@ class CONTENT_EXPORT ServiceWorkerVersion
public EmbeddedWorkerInstance::Listener {
public:
typedef base::Callback<void(ServiceWorkerStatusCode)> StatusCallback;
- typedef base::Callback<void(ServiceWorkerStatusCode,
- ServiceWorkerFetchEventResult,
- const ServiceWorkerResponse&)> FetchCallback;
enum RunningStatus {
STOPPED = EmbeddedWorkerInstance::STOPPED,
@@ -149,6 +145,13 @@ class CONTENT_EXPORT ServiceWorkerVersion
foreign_fetch_scopes_ = scopes;
}
+ const std::vector<url::Origin>& foreign_fetch_origins() const {
+ return foreign_fetch_origins_;
+ }
+ void set_foreign_fetch_origins(const std::vector<url::Origin>& origins) {
+ foreign_fetch_origins_ = origins;
+ }
+
// This sets the new status and also run status change callbacks
// if there're any (see RegisterStatusChangeCallback).
void SetStatus(Status status);
@@ -160,7 +163,9 @@ class CONTENT_EXPORT ServiceWorkerVersion
// Starts an embedded worker for this version.
// This returns OK (success) if the worker is already running.
- void StartWorker(const StatusCallback& callback);
+ // |purpose| is recorded in UMA.
+ void StartWorker(ServiceWorkerMetrics::EventType purpose,
+ const StatusCallback& callback);
// Stops an embedded worker for this version.
// This returns OK (success) if the worker is already stopped.
@@ -178,8 +183,12 @@ class CONTENT_EXPORT ServiceWorkerVersion
// Starts the worker if it isn't already running, and calls |task| when the
// worker is running, or |error_callback| if starting the worker failed.
- void RunAfterStartWorker(const StatusCallback& error_callback,
- const base::Closure& task);
+ // If the worker is already running, |task| is executed synchronously (before
+ // this method returns).
+ // |purpose| is used for UMA.
+ void RunAfterStartWorker(ServiceWorkerMetrics::EventType purpose,
+ const base::Closure& task,
+ const StatusCallback& error_callback);
// Call this while the worker is running before dispatching an event to the
// worker. This informs ServiceWorkerVersion about the event in progress.
@@ -201,7 +210,10 @@ class CONTENT_EXPORT ServiceWorkerVersion
// Informs ServiceWorkerVersion that an event has finished being dispatched.
// Returns false if no pending requests with the provided id exist, for
// example if the request has already timed out.
- bool FinishRequest(int request_id);
+ // Pass the result of the event to |was_handled|, which is used to record
+ // statistics based on the event status.
+ // TODO(mek): Use something other than a bool for event status.
+ bool FinishRequest(int request_id, bool was_handled);
// Connects to a specific mojo service exposed by the (running) service
// worker. If a connection to a service for the same Interface already exists
@@ -224,74 +236,23 @@ class CONTENT_EXPORT ServiceWorkerVersion
const IPC::Message& message,
const ResponseCallbackType& callback);
+ // For simple events where the full functionality of DispatchEvent is not
+ // needed, this method can be used instead. The ResponseMessage must consist
+ // of just a request_id and a blink::WebServiceWorkerEventResult field. The
+ // result is converted to a ServiceWorkerStatusCode and passed to the error
+ // handler associated with the request. Additionally this methods calls
+ // FinishRequest before passing the reply to the callback.
+ template <typename ResponseMessage>
+ void DispatchSimpleEvent(int request_id, const IPC::Message& message);
+
// Sends a message event to the associated embedded worker.
+ // TODO(nhiroki): Remove this after ExtendableMessageEvent is enabled by
+ // default (crbug.com/543198).
void DispatchMessageEvent(
const base::string16& message,
const std::vector<TransferredMessagePort>& sent_message_ports,
const StatusCallback& callback);
- // Sends install event to the associated embedded worker and asynchronously
- // calls |callback| when it errors out or it gets a response from the worker
- // to notify install completion.
- //
- // This must be called when the status() is NEW. Calling this changes
- // the version's status to INSTALLING.
- // Upon completion, the version's status will be changed to INSTALLED
- // on success, or back to NEW on failure.
- void DispatchInstallEvent(const StatusCallback& callback);
-
- // Sends activate event to the associated embedded worker and asynchronously
- // calls |callback| when it errors out or it gets a response from the worker
- // to notify activation completion.
- //
- // This must be called when the status() is INSTALLED. Calling this changes
- // the version's status to ACTIVATING.
- // Upon completion, the version's status will be changed to ACTIVATED
- // on success, or back to INSTALLED on failure.
- void DispatchActivateEvent(const StatusCallback& callback);
-
- // Sends fetch event to the associated embedded worker and calls
- // |callback| with the response from the worker.
- //
- // This must be called when the status() is ACTIVATED. Calling this in other
- // statuses will result in an error SERVICE_WORKER_ERROR_FAILED.
- void DispatchFetchEvent(const ServiceWorkerFetchRequest& request,
- const base::Closure& prepare_callback,
- const FetchCallback& fetch_callback);
-
- // Sends notificationclick event to the associated embedded worker and
- // asynchronously calls |callback| when it errors out or it gets a response
- // from the worker to notify completion.
- //
- // This must be called when the status() is ACTIVATED.
- void DispatchNotificationClickEvent(
- const StatusCallback& callback,
- int64_t persistent_notification_id,
- const PlatformNotificationData& notification_data,
- int action_index);
-
- // Sends push event to the associated embedded worker and asynchronously calls
- // |callback| when it errors out or it gets a response from the worker to
- // notify completion.
- //
- // This must be called when the status() is ACTIVATED.
- void DispatchPushEvent(const StatusCallback& callback,
- const std::string& data);
-
- // Sends a cross origin message event to the associated embedded worker and
- // asynchronously calls |callback| when the message was sent (or failed to
- // sent).
- // It is the responsibility of the code calling this method to make sure that
- // any transferred message ports are put on hold while potentially a process
- // for the service worker is spun up.
- //
- // This must be called when the status() is ACTIVATED.
- void DispatchCrossOriginMessageEvent(
- const NavigatorConnectClient& client,
- const base::string16& message,
- const std::vector<TransferredMessagePort>& sent_message_ports,
- const StatusCallback& callback);
-
// Adds and removes |provider_host| as a controllee of this ServiceWorker.
// A potential controllee is a host having the version as its .installing
// or .waiting version.
@@ -342,9 +303,9 @@ class CONTENT_EXPORT ServiceWorkerVersion
force_bypass_cache_for_scripts_ = force_bypass_cache_for_scripts;
}
- bool skip_script_comparison() const { return skip_script_comparison_; }
- void set_skip_script_comparison(bool skip_script_comparison) {
- skip_script_comparison_ = skip_script_comparison;
+ bool pause_after_download() const { return pause_after_download_; }
+ void set_pause_after_download(bool pause_after_download) {
+ pause_after_download_ = pause_after_download;
}
void SetDevToolsAttached(bool attached);
@@ -379,7 +340,6 @@ class CONTENT_EXPORT ServiceWorkerVersion
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, StaleUpdate_RunningWorker);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest,
StaleUpdate_DoNotDeferTimer);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerWaitForeverInFetchTest, RequestTimeout);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, RequestTimeout);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerFailToStartTest, Timeout);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionBrowserTest,
@@ -393,32 +353,19 @@ class CONTENT_EXPORT ServiceWorkerVersion
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, RequestCustomizedTimeout);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest,
RequestCustomizedTimeoutKill);
- FRIEND_TEST_ALL_PREFIXES(ServiceWorkerWaitForeverInFetchTest,
- MixedRequestTimeouts);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerVersionTest, MixedRequestTimeouts);
class Metrics;
class PingController;
- enum RequestType {
- REQUEST_ACTIVATE,
- REQUEST_INSTALL,
- REQUEST_FETCH,
- REQUEST_NOTIFICATION_CLICK,
- REQUEST_PUSH,
- REQUEST_CUSTOM,
- NUM_REQUEST_TYPES
- };
-
struct RequestInfo {
RequestInfo(int id,
- RequestType type,
ServiceWorkerMetrics::EventType event_type,
const base::TimeTicks& expiration,
TimeoutBehavior timeout_behavior);
~RequestInfo();
bool operator>(const RequestInfo& other) const;
int id;
- RequestType type;
ServiceWorkerMetrics::EventType event_type;
base::TimeTicks expiration;
TimeoutBehavior timeout_behavior;
@@ -494,17 +441,20 @@ class CONTENT_EXPORT ServiceWorkerVersion
template <typename ResponseMessage, typename CallbackType>
class EventResponseHandler : public EmbeddedWorkerInstance::Listener {
public:
- EventResponseHandler(EmbeddedWorkerInstance* worker,
+ EventResponseHandler(const base::WeakPtr<EmbeddedWorkerInstance>& worker,
int request_id,
const CallbackType& callback)
: worker_(worker), request_id_(request_id), callback_(callback) {
worker_->AddListener(this);
}
- ~EventResponseHandler() override { worker_->RemoveListener(this); }
+ ~EventResponseHandler() override {
+ if (worker_)
+ worker_->RemoveListener(this);
+ }
bool OnMessageReceived(const IPC::Message& message) override;
private:
- EmbeddedWorkerInstance* const worker_;
+ base::WeakPtr<EmbeddedWorkerInstance> const worker_;
const int request_id_;
const CallbackType callback_;
};
@@ -544,9 +494,6 @@ class CONTENT_EXPORT ServiceWorkerVersion
void OnStartSentAndScriptEvaluated(ServiceWorkerStatusCode status);
- void DispatchInstallEventAfterStartWorker(const StatusCallback& callback);
- void DispatchActivateEventAfterStartWorker(const StatusCallback& callback);
-
void DispatchMessageEventInternal(
const base::string16& message,
const std::vector<TransferredMessagePort>& sent_message_ports,
@@ -554,24 +501,18 @@ class CONTENT_EXPORT ServiceWorkerVersion
// Message handlers.
+ // This corresponds to the spec's get(id) steps.
+ void OnGetClient(int request_id, const std::string& client_uuid);
+
// This corresponds to the spec's matchAll(options) steps.
void OnGetClients(int request_id,
const ServiceWorkerClientQueryOptions& options);
- void OnActivateEventFinished(int request_id,
- blink::WebServiceWorkerEventResult result);
- void OnInstallEventFinished(int request_id,
- blink::WebServiceWorkerEventResult result);
- void OnFetchEventFinished(int request_id,
- ServiceWorkerFetchEventResult result,
- const ServiceWorkerResponse& response);
- void OnNotificationClickEventFinished(int request_id);
- void OnPushEventFinished(int request_id,
- blink::WebServiceWorkerEventResult result);
+ void OnSimpleEventResponse(int request_id,
+ blink::WebServiceWorkerEventResult result);
void OnOpenWindow(int request_id, GURL url);
void OnOpenWindowFinished(int request_id,
ServiceWorkerStatusCode status,
- const std::string& client_uuid,
const ServiceWorkerClientInfo& client_info);
void OnSetCachedMetadata(const GURL& url, const std::vector<char>& data);
@@ -589,19 +530,21 @@ class CONTENT_EXPORT ServiceWorkerVersion
const GURL& url);
void OnNavigateClientFinished(int request_id,
ServiceWorkerStatusCode status,
- const std::string& client_uuid,
- const ServiceWorkerClientInfo& client);
+ const ServiceWorkerClientInfo& client_info);
void OnSkipWaiting(int request_id);
void OnClaimClients(int request_id);
void OnPongFromWorker();
void OnFocusClientFinished(int request_id,
- const std::string& client_uuid,
- const ServiceWorkerClientInfo& client);
+ const ServiceWorkerClientInfo& client_info);
- void OnRegisterForeignFetchScopes(const std::vector<GURL>& sub_scopes);
+ void OnRegisterForeignFetchScopes(const std::vector<GURL>& sub_scopes,
+ const std::vector<url::Origin>& origins);
void DidEnsureLiveRegistrationForStartWorker(
+ ServiceWorkerMetrics::EventType purpose,
+ Status prestart_status,
+ bool is_browser_startup_complete,
const StatusCallback& callback,
ServiceWorkerStatusCode status,
const scoped_refptr<ServiceWorkerRegistration>& registration);
@@ -609,6 +552,9 @@ class CONTENT_EXPORT ServiceWorkerVersion
void DidSkipWaiting(int request_id);
+ void OnGetClientFinished(int request_id,
+ const ServiceWorkerClientInfo& client_info);
+
void OnGetClientsFinished(int request_id, ServiceWorkerClients* clients);
// The timeout timer periodically calls OnTimeoutTimer, which stops the worker
@@ -629,26 +575,11 @@ class CONTENT_EXPORT ServiceWorkerVersion
// RecordStartWorkerResult is added as a start callback by StartTimeoutTimer
// and records metrics about startup.
- void RecordStartWorkerResult(ServiceWorkerStatusCode status);
-
- template <typename IDMAP>
- void RemoveCallbackAndStopIfRedundant(IDMAP* callbacks, int request_id);
-
- template <typename CallbackType>
- int AddRequest(
- const CallbackType& callback,
- IDMap<PendingRequest<CallbackType>, IDMapOwnPointer>* callback_map,
- RequestType request_type,
- ServiceWorkerMetrics::EventType event_type);
-
- template <typename CallbackType>
- int AddRequestWithExpiration(
- const CallbackType& callback,
- IDMap<PendingRequest<CallbackType>, IDMapOwnPointer>* callback_map,
- RequestType request_type,
- ServiceWorkerMetrics::EventType event_type,
- base::TimeTicks expiration,
- TimeoutBehavior timeout_behavior);
+ void RecordStartWorkerResult(ServiceWorkerMetrics::EventType purpose,
+ Status prestart_status,
+ int trace_id,
+ bool is_browser_startup_complete,
+ ServiceWorkerStatusCode status);
bool MaybeTimeOutRequest(const RequestInfo& info);
void SetAllRequestExpirations(const base::TimeTicks& expiration);
@@ -682,6 +613,7 @@ class CONTENT_EXPORT ServiceWorkerVersion
const GURL script_url_;
const GURL scope_;
std::vector<GURL> foreign_fetch_scopes_;
+ std::vector<url::Origin> foreign_fetch_origins_;
Status status_ = NEW;
scoped_ptr<EmbeddedWorkerInstance> embedded_worker_;
@@ -691,12 +623,6 @@ class CONTENT_EXPORT ServiceWorkerVersion
// Message callbacks. (Update HasInflightRequests() too when you update this
// list.)
- IDMap<PendingRequest<StatusCallback>, IDMapOwnPointer> activate_requests_;
- IDMap<PendingRequest<StatusCallback>, IDMapOwnPointer> install_requests_;
- IDMap<PendingRequest<FetchCallback>, IDMapOwnPointer> fetch_requests_;
- IDMap<PendingRequest<StatusCallback>, IDMapOwnPointer>
- notification_click_requests_;
- IDMap<PendingRequest<StatusCallback>, IDMapOwnPointer> push_requests_;
IDMap<PendingRequest<StatusCallback>, IDMapOwnPointer> custom_requests_;
// Stores all open connections to mojo services. Maps the service name to
@@ -722,7 +648,8 @@ class CONTENT_EXPORT ServiceWorkerVersion
base::TimeTicks idle_time_;
// Holds the time that the outstanding StartWorker() request started.
base::TimeTicks start_time_;
- // Holds the time the worker entered STOPPING status.
+ // Holds the time the worker entered STOPPING status. This is also used as a
+ // trace event id.
base::TimeTicks stop_time_;
// Holds the time the worker was detected as stale and needs updating. We try
// to update once the worker stops, but will also update if it stays alive too
@@ -739,15 +666,13 @@ class CONTENT_EXPORT ServiceWorkerVersion
bool skip_waiting_ = false;
bool skip_recording_startup_time_ = false;
bool force_bypass_cache_for_scripts_ = false;
- bool skip_script_comparison_ = false;
+ bool pause_after_download_ = false;
bool is_update_scheduled_ = false;
bool in_dtor_ = false;
std::vector<int> pending_skip_waiting_requests_;
scoped_ptr<net::HttpResponseInfo> main_script_http_info_;
- // The status when StartWorker was invoked. Used for UMA.
- Status prestart_status_ = NEW;
// If not OK, the reason that StartWorker failed. Used for
// running |start_callbacks_|.
ServiceWorkerStatusCode start_worker_status_ = SERVICE_WORKER_OK;
@@ -804,10 +729,18 @@ void ServiceWorkerVersion::DispatchEvent(int request_id,
} else {
request->listener.reset(
new EventResponseHandler<ResponseMessage, ResponseCallbackType>(
- embedded_worker(), request_id, callback));
+ embedded_worker()->AsWeakPtr(), request_id, callback));
}
}
+template <typename ResponseMessage>
+void ServiceWorkerVersion::DispatchSimpleEvent(int request_id,
+ const IPC::Message& message) {
+ DispatchEvent<ResponseMessage>(
+ request_id, message,
+ base::Bind(&ServiceWorkerVersion::OnSimpleEventResponse, this));
+}
+
template <typename ResponseMessage, typename CallbackType>
bool ServiceWorkerVersion::EventResponseHandler<ResponseMessage, CallbackType>::
OnMessageReceived(const IPC::Message& message) {
@@ -818,12 +751,16 @@ bool ServiceWorkerVersion::EventResponseHandler<ResponseMessage, CallbackType>::
if (!result || received_request_id != request_id_)
return false;
+ CallbackType protect(callback_);
// Essentially same code as what IPC_MESSAGE_FORWARD expands to.
void* param = nullptr;
if (!ResponseMessage::Dispatch(&message, &callback_, this, param,
&CallbackType::Run))
message.set_dispatch_error();
+ // At this point |this| can have been deleted, so don't do anything other
+ // than returning.
+
return true;
}
diff --git a/chromium/content/browser/service_worker/service_worker_version_unittest.cc b/chromium/content/browser/service_worker/service_worker_version_unittest.cc
index f3d1aeb8f70..49a86ea1f85 100644
--- a/chromium/content/browser/service_worker/service_worker_version_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_version_unittest.cc
@@ -33,6 +33,12 @@ IPC_MESSAGE_ROUTED1(TestMsg_MessageFromWorker, int)
IPC_MESSAGE_CONTROL1(TestMsg_TestEvent, int)
IPC_MESSAGE_ROUTED2(TestMsg_TestEventResult, int, std::string)
+IPC_MESSAGE_ROUTED2(TestMsg_TestSimpleEventResult,
+ int,
+ blink::WebServiceWorkerEventResult)
+
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebServiceWorkerEventResult,
+ blink::WebServiceWorkerEventResultLast)
// ---------------------------------------------------------------------------
@@ -74,6 +80,13 @@ class MessageReceiver : public EmbeddedWorkerTestHelper {
new TestMsg_TestEventResult(embedded_worker_id, request_id, reply));
}
+ void SimulateSendSimpleEventResult(int embedded_worker_id,
+ int request_id,
+ blink::WebServiceWorkerEventResult reply) {
+ SimulateSend(new TestMsg_TestSimpleEventResult(embedded_worker_id,
+ request_id, reply));
+ }
+
private:
void OnMessage() {
// Do nothing.
@@ -94,13 +107,6 @@ void ObserveStatusChanges(ServiceWorkerVersion* version,
base::Bind(&ObserveStatusChanges, base::Unretained(version), statuses));
}
-void ReceiveFetchResult(ServiceWorkerStatusCode* status,
- ServiceWorkerStatusCode actual_status,
- ServiceWorkerFetchEventResult actual_result,
- const ServiceWorkerResponse& response) {
- *status = actual_status;
-}
-
void ReceiveTestEventResult(int* request_id,
std::string* data,
const base::Closure& callback,
@@ -156,9 +162,9 @@ base::Time GetYesterday() {
base::TimeDelta::FromSeconds(1);
}
-class TestMojoServiceImpl : public TestMojoService {
+class TestMojoServiceImpl : public mojom::TestMojoService {
public:
- static void Create(mojo::InterfaceRequest<TestMojoService> request) {
+ static void Create(mojo::InterfaceRequest<mojom::TestMojoService> request) {
new TestMojoServiceImpl(std::move(request));
}
@@ -166,15 +172,16 @@ class TestMojoServiceImpl : public TestMojoService {
callback.Run();
}
- void GetRequestorURL(const GetRequestorURLCallback& callback) override {
+ void GetRequestorName(const GetRequestorNameCallback& callback) override {
callback.Run(mojo::String(""));
}
private:
- explicit TestMojoServiceImpl(mojo::InterfaceRequest<TestMojoService> request)
+ explicit TestMojoServiceImpl(
+ mojo::InterfaceRequest<mojom::TestMojoService> request)
: binding_(this, std::move(request)) {}
- mojo::StrongBinding<TestMojoService> binding_;
+ mojo::StrongBinding<mojom::TestMojoService> binding_;
};
} // namespace
@@ -240,6 +247,29 @@ class ServiceWorkerVersionTest : public testing::Test {
helper_.reset();
}
+ void SimulateDispatchEvent(ServiceWorkerMetrics::EventType event_type) {
+ ServiceWorkerStatusCode status =
+ SERVICE_WORKER_ERROR_MAX_VALUE; // dummy value
+
+ // Make sure worker is running.
+ scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner);
+ version_->RunAfterStartWorker(event_type, runner->QuitClosure(),
+ CreateReceiverOnCurrentThread(&status));
+ runner->Run();
+ EXPECT_EQ(SERVICE_WORKER_ERROR_MAX_VALUE, status);
+ EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+
+ // Start request, as if an event is being dispatched.
+ int request_id = version_->StartRequest(
+ event_type, CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+
+ // And finish request, as if a response to the event was received.
+ EXPECT_TRUE(version_->FinishRequest(request_id, true));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(SERVICE_WORKER_ERROR_MAX_VALUE, status);
+ }
+
TestBrowserThreadBundle thread_bundle_;
scoped_ptr<MessageReceiver> helper_;
scoped_refptr<ServiceWorkerRegistration> registration_;
@@ -256,14 +286,31 @@ class MessageReceiverDisallowStart : public MessageReceiver {
: MessageReceiver() {}
~MessageReceiverDisallowStart() override {}
+ enum class StartMode { STALL, FAIL, SUCCEED };
+
void OnStartWorker(int embedded_worker_id,
int64_t service_worker_version_id,
const GURL& scope,
- const GURL& script_url) override {
- // Do nothing.
+ const GURL& script_url,
+ bool pause_after_download) override {
+ switch (mode_) {
+ case StartMode::STALL:
+ break; // Do nothing.
+ case StartMode::FAIL:
+ OnStopWorker(embedded_worker_id);
+ break;
+ case StartMode::SUCCEED:
+ MessageReceiver::OnStartWorker(embedded_worker_id,
+ service_worker_version_id, scope,
+ script_url, pause_after_download);
+ break;
+ }
}
+ void set_start_mode(StartMode mode) { mode_ = mode; }
+
private:
+ StartMode mode_ = StartMode::STALL;
DISALLOW_COPY_AND_ASSIGN(MessageReceiverDisallowStart);
};
@@ -272,6 +319,12 @@ class ServiceWorkerFailToStartTest : public ServiceWorkerVersionTest {
ServiceWorkerFailToStartTest()
: ServiceWorkerVersionTest() {}
+ void set_start_mode(MessageReceiverDisallowStart::StartMode mode) {
+ MessageReceiverDisallowStart* helper =
+ static_cast<MessageReceiverDisallowStart*>(helper_.get());
+ helper->set_start_mode(mode);
+ }
+
scoped_ptr<MessageReceiver> GetMessageReceiver() override {
return make_scoped_ptr(new MessageReceiverDisallowStart());
}
@@ -305,33 +358,6 @@ class ServiceWorkerStallInStoppingTest : public ServiceWorkerVersionTest {
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerStallInStoppingTest);
};
-class MessageReceiverDisallowFetch : public MessageReceiver {
- public:
- MessageReceiverDisallowFetch() : MessageReceiver() {}
- ~MessageReceiverDisallowFetch() override {}
-
- void OnFetchEvent(int embedded_worker_id,
- int request_id,
- const ServiceWorkerFetchRequest& request) override {
- // Do nothing.
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MessageReceiverDisallowFetch);
-};
-
-class ServiceWorkerWaitForeverInFetchTest : public ServiceWorkerVersionTest {
- protected:
- ServiceWorkerWaitForeverInFetchTest() : ServiceWorkerVersionTest() {}
-
- scoped_ptr<MessageReceiver> GetMessageReceiver() override {
- return make_scoped_ptr(new MessageReceiverDisallowFetch());
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ServiceWorkerWaitForeverInFetchTest);
-};
-
class MessageReceiverMojoTestService : public MessageReceiver {
public:
MessageReceiverMojoTestService() : MessageReceiver() {}
@@ -362,15 +388,18 @@ TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) {
ServiceWorkerStatusCode status1 = SERVICE_WORKER_ERROR_FAILED;
ServiceWorkerStatusCode status2 = SERVICE_WORKER_ERROR_FAILED;
ServiceWorkerStatusCode status3 = SERVICE_WORKER_ERROR_FAILED;
- version_->StartWorker(CreateReceiverOnCurrentThread(&status1));
- version_->StartWorker(CreateReceiverOnCurrentThread(&status2));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status1));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status2));
EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
// Call StartWorker() after it's started.
- version_->StartWorker(CreateReceiverOnCurrentThread(&status3));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status3));
base::RunLoop().RunUntilIdle();
// All should just succeed.
@@ -397,7 +426,8 @@ TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) {
status2 = SERVICE_WORKER_ERROR_FAILED;
status3 = SERVICE_WORKER_ERROR_FAILED;
- version_->StartWorker(CreateReceiverOnCurrentThread(&status1));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status1));
EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
base::RunLoop().RunUntilIdle();
@@ -408,7 +438,8 @@ TEST_F(ServiceWorkerVersionTest, ConcurrentStartAndStop) {
version_->StopWorker(CreateReceiverOnCurrentThread(&status2));
// And try calling StartWorker while StopWorker is in queue.
- version_->StartWorker(CreateReceiverOnCurrentThread(&status3));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status3));
EXPECT_EQ(ServiceWorkerVersion::STOPPING, version_->running_status());
base::RunLoop().RunUntilIdle();
@@ -424,27 +455,18 @@ TEST_F(ServiceWorkerVersionTest, DispatchEventToStoppedWorker) {
EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
// Dispatch an event without starting the worker.
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
version_->SetStatus(ServiceWorkerVersion::INSTALLING);
- version_->DispatchInstallEvent(CreateReceiverOnCurrentThread(&status));
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ SimulateDispatchEvent(ServiceWorkerMetrics::EventType::INSTALL);
// The worker should be now started.
EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
// Stop the worker, and then dispatch an event immediately after that.
- status = SERVICE_WORKER_ERROR_FAILED;
ServiceWorkerStatusCode stop_status = SERVICE_WORKER_ERROR_FAILED;
version_->StopWorker(CreateReceiverOnCurrentThread(&stop_status));
- version_->DispatchInstallEvent(CreateReceiverOnCurrentThread(&status));
- base::RunLoop().RunUntilIdle();
+ SimulateDispatchEvent(ServiceWorkerMetrics::EventType::INSTALL);
EXPECT_EQ(SERVICE_WORKER_OK, stop_status);
- // Dispatch an event should return SERVICE_WORKER_OK since the worker
- // should have been restarted to dispatch the event.
- EXPECT_EQ(SERVICE_WORKER_OK, status);
-
// The worker should be now started again.
EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
}
@@ -452,7 +474,8 @@ TEST_F(ServiceWorkerVersionTest, DispatchEventToStoppedWorker) {
TEST_F(ServiceWorkerVersionTest, StartUnregisteredButStillLiveWorker) {
// Start the worker.
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
- version_->StartWorker(CreateReceiverOnCurrentThread(&status));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
@@ -476,14 +499,7 @@ TEST_F(ServiceWorkerVersionTest, StartUnregisteredButStillLiveWorker) {
// Dispatch an event on the unregistered and stopped but still live worker.
status = SERVICE_WORKER_ERROR_FAILED;
- version_->DispatchFetchEvent(ServiceWorkerFetchRequest(),
- base::Bind(&base::DoNothing),
- base::Bind(&ReceiveFetchResult, &status));
- base::RunLoop().RunUntilIdle();
-
- // Dispatch an event should return SERVICE_WORKER_OK since the worker
- // should have been restarted to dispatch the event.
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ SimulateDispatchEvent(ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME);
// The worker should be now started again.
EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
@@ -492,7 +508,8 @@ TEST_F(ServiceWorkerVersionTest, StartUnregisteredButStillLiveWorker) {
TEST_F(ServiceWorkerVersionTest, ReceiveMessageFromWorker) {
// Start worker.
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
- version_->StartWorker(CreateReceiverOnCurrentThread(&status));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
EXPECT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
@@ -515,39 +532,36 @@ TEST_F(ServiceWorkerVersionTest, ReceiveMessageFromWorker) {
TEST_F(ServiceWorkerVersionTest, InstallAndWaitCompletion) {
version_->SetStatus(ServiceWorkerVersion::INSTALLING);
- // Dispatch an install event.
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
- version_->DispatchInstallEvent(CreateReceiverOnCurrentThread(&status));
-
// Wait for the completion.
bool status_change_called = false;
version_->RegisterStatusChangeCallback(
base::Bind(&VerifyCalled, &status_change_called));
- base::RunLoop().RunUntilIdle();
+ // Dispatch an install event.
+ SimulateDispatchEvent(ServiceWorkerMetrics::EventType::INSTALL);
// Version's status must not have changed during installation.
- EXPECT_EQ(SERVICE_WORKER_OK, status);
EXPECT_FALSE(status_change_called);
EXPECT_EQ(ServiceWorkerVersion::INSTALLING, version_->status());
}
TEST_F(ServiceWorkerVersionTest, ActivateAndWaitCompletion) {
- version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
+ // TODO(mek): This test (and the one above for the install event) made more
+ // sense back when ServiceWorkerVersion was responsible for updating the
+ // status. Now a better version of this test should probably be added to
+ // ServiceWorkerRegistrationTest instead.
- // Dispatch an activate event.
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
- version_->DispatchActivateEvent(CreateReceiverOnCurrentThread(&status));
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
// Wait for the completion.
bool status_change_called = false;
version_->RegisterStatusChangeCallback(
base::Bind(&VerifyCalled, &status_change_called));
- base::RunLoop().RunUntilIdle();
+ // Dispatch an activate event.
+ SimulateDispatchEvent(ServiceWorkerMetrics::EventType::ACTIVATE);
// Version's status must not have changed during activation.
- EXPECT_EQ(SERVICE_WORKER_OK, status);
EXPECT_FALSE(status_change_called);
EXPECT_EQ(ServiceWorkerVersion::ACTIVATING, version_->status());
}
@@ -557,8 +571,8 @@ TEST_F(ServiceWorkerVersionTest, RepeatedlyObserveStatusChanges) {
// Repeatedly observe status changes (the callback re-registers itself).
std::vector<ServiceWorkerVersion::Status> statuses;
- version_->RegisterStatusChangeCallback(
- base::Bind(&ObserveStatusChanges, version_, &statuses));
+ version_->RegisterStatusChangeCallback(base::Bind(
+ &ObserveStatusChanges, base::RetainedRef(version_), &statuses));
version_->SetStatus(ServiceWorkerVersion::INSTALLING);
version_->SetStatus(ServiceWorkerVersion::INSTALLED);
@@ -586,7 +600,8 @@ TEST_F(ServiceWorkerVersionTest, IdleTimeout) {
// Verify the timer is running after the worker is started.
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
- version_->StartWorker(CreateReceiverOnCurrentThread(&status));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
EXPECT_TRUE(version_->timeout_timer_.IsRunning());
@@ -601,7 +616,8 @@ TEST_F(ServiceWorkerVersionTest, IdleTimeout) {
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
status = SERVICE_WORKER_ERROR_FAILED;
- version_->StartWorker(CreateReceiverOnCurrentThread(&status));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
EXPECT_TRUE(version_->timeout_timer_.IsRunning());
@@ -619,15 +635,9 @@ TEST_F(ServiceWorkerVersionTest, IdleTimeout) {
EXPECT_LT(idle_time, version_->idle_time_);
// Completing an event resets the idle time.
- status = SERVICE_WORKER_ERROR_FAILED;
version_->idle_time_ -= kOneSecond;
idle_time = version_->idle_time_;
- version_->DispatchFetchEvent(ServiceWorkerFetchRequest(),
- base::Bind(&base::DoNothing),
- base::Bind(&ReceiveFetchResult, &status));
- base::RunLoop().RunUntilIdle();
-
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ SimulateDispatchEvent(ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME);
EXPECT_LT(idle_time, version_->idle_time_);
// Starting and finishing a request resets the idle time.
@@ -636,7 +646,7 @@ TEST_F(ServiceWorkerVersionTest, IdleTimeout) {
int request_id =
version_->StartRequest(ServiceWorkerMetrics::EventType::SYNC,
CreateReceiverOnCurrentThread(&status));
- EXPECT_TRUE(version_->FinishRequest(request_id));
+ EXPECT_TRUE(version_->FinishRequest(request_id, true));
EXPECT_EQ(SERVICE_WORKER_OK, status);
EXPECT_LT(idle_time, version_->idle_time_);
@@ -658,7 +668,8 @@ TEST_F(ServiceWorkerVersionTest, IdleTimeout) {
TEST_F(ServiceWorkerVersionTest, SetDevToolsAttached) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
- version_->StartWorker(CreateReceiverOnCurrentThread(&status));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
ASSERT_EQ(ServiceWorkerVersion::STARTING, version_->running_status());
@@ -690,7 +701,8 @@ TEST_F(ServiceWorkerVersionTest, StoppingBeforeDestruct) {
version_->AddListener(&listener);
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
- version_->StartWorker(CreateReceiverOnCurrentThread(&status));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
@@ -702,31 +714,22 @@ TEST_F(ServiceWorkerVersionTest, StoppingBeforeDestruct) {
// Test that update isn't triggered for a non-stale worker.
TEST_F(ServiceWorkerVersionTest, StaleUpdate_FreshWorker) {
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
-
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
registration_->SetActiveVersion(version_);
registration_->set_last_update_check(base::Time::Now());
- version_->DispatchPushEvent(CreateReceiverOnCurrentThread(&status),
- std::string());
- base::RunLoop().RunUntilIdle();
+ SimulateDispatchEvent(ServiceWorkerMetrics::EventType::PUSH);
- EXPECT_EQ(SERVICE_WORKER_OK, status);
EXPECT_TRUE(version_->stale_time_.is_null());
EXPECT_FALSE(version_->update_timer_.IsRunning());
}
// Test that update isn't triggered for a non-active worker.
TEST_F(ServiceWorkerVersionTest, StaleUpdate_NonActiveWorker) {
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
-
version_->SetStatus(ServiceWorkerVersion::INSTALLING);
registration_->SetInstallingVersion(version_);
registration_->set_last_update_check(GetYesterday());
- version_->DispatchInstallEvent(CreateReceiverOnCurrentThread(&status));
- base::RunLoop().RunUntilIdle();
+ SimulateDispatchEvent(ServiceWorkerMetrics::EventType::INSTALL);
- EXPECT_EQ(SERVICE_WORKER_OK, status);
EXPECT_TRUE(version_->stale_time_.is_null());
EXPECT_FALSE(version_->update_timer_.IsRunning());
}
@@ -739,10 +742,7 @@ TEST_F(ServiceWorkerVersionTest, StaleUpdate_StartWorker) {
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
registration_->SetActiveVersion(version_);
registration_->set_last_update_check(GetYesterday());
- version_->DispatchPushEvent(CreateReceiverOnCurrentThread(&status),
- std::string());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ SimulateDispatchEvent(ServiceWorkerMetrics::EventType::PUSH);
EXPECT_FALSE(version_->stale_time_.is_null());
EXPECT_FALSE(version_->update_timer_.IsRunning());
@@ -756,16 +756,11 @@ TEST_F(ServiceWorkerVersionTest, StaleUpdate_StartWorker) {
// Test that staleness is detected on a running worker.
TEST_F(ServiceWorkerVersionTest, StaleUpdate_RunningWorker) {
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
-
// Start a fresh worker.
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
registration_->SetActiveVersion(version_);
registration_->set_last_update_check(base::Time::Now());
- version_->DispatchPushEvent(CreateReceiverOnCurrentThread(&status),
- std::string());
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_OK, status);
+ SimulateDispatchEvent(ServiceWorkerMetrics::EventType::PUSH);
EXPECT_TRUE(version_->stale_time_.is_null());
// Simulate it running for a day. It will be marked stale.
@@ -798,10 +793,13 @@ TEST_F(ServiceWorkerVersionTest, StaleUpdate_DoNotDeferTimer) {
version_->stale_time_ = stale_time;
// Stale time is not deferred.
- version_->DispatchPushEvent(
- base::Bind(&ServiceWorkerUtils::NoOpStatusCallback), std::string());
- version_->DispatchPushEvent(
- base::Bind(&ServiceWorkerUtils::NoOpStatusCallback), std::string());
+ version_->RunAfterStartWorker(
+ ServiceWorkerMetrics::EventType::UNKNOWN, base::Bind(&base::DoNothing),
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+ version_->RunAfterStartWorker(
+ ServiceWorkerMetrics::EventType::UNKNOWN, base::Bind(&base::DoNothing),
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+ base::RunLoop().RunUntilIdle();
EXPECT_EQ(stale_time, version_->stale_time_);
// Timeout triggers the update.
@@ -811,24 +809,26 @@ TEST_F(ServiceWorkerVersionTest, StaleUpdate_DoNotDeferTimer) {
// Update timer is not deferred.
base::TimeTicks run_time = version_->update_timer_.desired_run_time();
- version_->DispatchPushEvent(
- base::Bind(&ServiceWorkerUtils::NoOpStatusCallback), std::string());
- version_->DispatchPushEvent(
- base::Bind(&ServiceWorkerUtils::NoOpStatusCallback), std::string());
- version_->DispatchPushEvent(
- base::Bind(&ServiceWorkerUtils::NoOpStatusCallback), std::string());
+ SimulateDispatchEvent(ServiceWorkerMetrics::EventType::PUSH);
+ SimulateDispatchEvent(ServiceWorkerMetrics::EventType::PUSH);
+ SimulateDispatchEvent(ServiceWorkerMetrics::EventType::PUSH);
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(version_->stale_time_.is_null());
EXPECT_EQ(run_time, version_->update_timer_.desired_run_time());
}
-TEST_F(ServiceWorkerWaitForeverInFetchTest, RequestTimeout) {
+TEST_F(ServiceWorkerVersionTest, RequestTimeout) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
-
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
- version_->DispatchFetchEvent(ServiceWorkerFetchRequest(),
- base::Bind(&base::DoNothing),
- base::Bind(&ReceiveFetchResult, &status));
+
+ version_->StartWorker(ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME,
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+ base::RunLoop().RunUntilIdle();
+
+ // Create a request.
+ int request_id =
+ version_->StartRequest(ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME,
+ CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
// Callback has not completed yet.
@@ -842,13 +842,15 @@ TEST_F(ServiceWorkerWaitForeverInFetchTest, RequestTimeout) {
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, status);
EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
+ EXPECT_FALSE(version_->FinishRequest(request_id, true));
}
TEST_F(ServiceWorkerVersionTest, RequestCustomizedTimeout) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
- version_->StartWorker(base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC,
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
base::RunLoop().RunUntilIdle();
// Create a request that should expire Now().
@@ -863,7 +865,7 @@ TEST_F(ServiceWorkerVersionTest, RequestCustomizedTimeout) {
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, status);
- EXPECT_FALSE(version_->FinishRequest(request_id));
+ EXPECT_FALSE(version_->FinishRequest(request_id, true));
// CONTINUE_ON_TIMEOUT timeouts don't stop the service worker.
EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
@@ -873,7 +875,8 @@ TEST_F(ServiceWorkerVersionTest, RequestCustomizedTimeoutKill) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
- version_->StartWorker(base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC,
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
base::RunLoop().RunUntilIdle();
// Create a request that should expire Now().
@@ -888,28 +891,29 @@ TEST_F(ServiceWorkerVersionTest, RequestCustomizedTimeoutKill) {
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, status);
- EXPECT_FALSE(version_->FinishRequest(request_id));
+ EXPECT_FALSE(version_->FinishRequest(request_id, true));
// KILL_ON_TIMEOUT timeouts should stop the service worker.
EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
}
-TEST_F(ServiceWorkerWaitForeverInFetchTest, MixedRequestTimeouts) {
+TEST_F(ServiceWorkerVersionTest, MixedRequestTimeouts) {
ServiceWorkerStatusCode sync_status =
SERVICE_WORKER_ERROR_NETWORK; // dummy value
ServiceWorkerStatusCode fetch_status =
SERVICE_WORKER_ERROR_NETWORK; // dummy value
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
- version_->StartWorker(base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME,
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
base::RunLoop().RunUntilIdle();
// Create a fetch request that should expire sometime later.
- version_->DispatchFetchEvent(ServiceWorkerFetchRequest(),
- base::Bind(&base::DoNothing),
- base::Bind(&ReceiveFetchResult, &fetch_status));
+ int fetch_request_id =
+ version_->StartRequest(ServiceWorkerMetrics::EventType::FETCH_MAIN_FRAME,
+ CreateReceiverOnCurrentThread(&fetch_status));
// Create a request that should expire Now().
- int request_id = version_->StartRequestWithCustomTimeout(
+ int sync_request_id = version_->StartRequestWithCustomTimeout(
ServiceWorkerMetrics::EventType::SYNC,
CreateReceiverOnCurrentThread(&sync_status), base::TimeDelta(),
ServiceWorkerVersion::CONTINUE_ON_TIMEOUT);
@@ -927,7 +931,7 @@ TEST_F(ServiceWorkerWaitForeverInFetchTest, MixedRequestTimeouts) {
EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
// Gracefully handle the sync event finishing after the timeout.
- EXPECT_FALSE(version_->FinishRequest(request_id));
+ EXPECT_FALSE(version_->FinishRequest(sync_request_id, true));
// Verify that the fetch times out later.
version_->SetAllRequestExpirations(base::TimeTicks::Now());
@@ -935,43 +939,17 @@ TEST_F(ServiceWorkerWaitForeverInFetchTest, MixedRequestTimeouts) {
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, fetch_status);
- // Other timeouts do stop the service worker.
- EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
-}
-
-TEST_F(ServiceWorkerVersionTest, RequestTimeout) {
- ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
-
- version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
- version_->StartWorker(base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
- base::RunLoop().RunUntilIdle();
- int request_id =
- version_->StartRequest(ServiceWorkerMetrics::EventType::SYNC,
- CreateReceiverOnCurrentThread(&status));
- base::RunLoop().RunUntilIdle();
-
- // Callback has not completed yet.
- EXPECT_EQ(SERVICE_WORKER_ERROR_NETWORK, status);
- EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+ // Fetch request should no longer exist.
+ EXPECT_FALSE(version_->FinishRequest(fetch_request_id, true));
- // Simulate timeout.
- EXPECT_TRUE(version_->timeout_timer_.IsRunning());
- version_->SetAllRequestExpirations(
- base::TimeTicks::Now() -
- base::TimeDelta::FromMinutes(
- ServiceWorkerVersion::kRequestTimeoutMinutes + 1));
- version_->timeout_timer_.user_task().Run();
- base::RunLoop().RunUntilIdle();
- EXPECT_EQ(SERVICE_WORKER_ERROR_TIMEOUT, status);
+ // Other timeouts do stop the service worker.
EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
-
- EXPECT_FALSE(version_->FinishRequest(request_id));
}
TEST_F(ServiceWorkerFailToStartTest, RendererCrash) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
- version_->StartWorker(
- CreateReceiverOnCurrentThread(&status));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
// Callback has not completed yet.
@@ -994,10 +972,9 @@ TEST_F(ServiceWorkerFailToStartTest, RendererCrash) {
TEST_F(ServiceWorkerFailToStartTest, Timeout) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
- // We could just call StartWorker but make it interesting and test
- // starting the worker as part of dispatching an event.
- version_->SetStatus(ServiceWorkerVersion::ACTIVATING);
- version_->DispatchActivateEvent(CreateReceiverOnCurrentThread(&status));
+ // Start starting the worker.
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
// Callback has not completed yet.
@@ -1021,7 +998,8 @@ TEST_F(ServiceWorkerFailToStartTest, Timeout) {
TEST_F(ServiceWorkerStallInStoppingTest, DetachThenStart) {
// Start a worker.
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
- version_->StartWorker(CreateReceiverOnCurrentThread(&status));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
@@ -1050,7 +1028,8 @@ TEST_F(ServiceWorkerStallInStoppingTest, DetachThenStart) {
// Try to start the worker again. It should work.
status = SERVICE_WORKER_ERROR_FAILED;
- version_->StartWorker(CreateReceiverOnCurrentThread(&status));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
@@ -1067,7 +1046,8 @@ TEST_F(ServiceWorkerStallInStoppingTest, DetachThenStart) {
TEST_F(ServiceWorkerStallInStoppingTest, DetachThenRestart) {
// Start a worker.
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
- version_->StartWorker(CreateReceiverOnCurrentThread(&status));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
@@ -1079,7 +1059,8 @@ TEST_F(ServiceWorkerStallInStoppingTest, DetachThenRestart) {
// Worker is now stalled in stopping. Add a start worker requset.
ServiceWorkerStatusCode start_status = SERVICE_WORKER_ERROR_FAILED;
- version_->StartWorker(CreateReceiverOnCurrentThread(&start_status));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&start_status));
// Simulate timeout. The worker should stop and get restarted.
EXPECT_TRUE(version_->timeout_timer_.IsRunning());
@@ -1098,56 +1079,84 @@ TEST_F(ServiceWorkerVersionTest, RegisterForeignFetchScopes) {
version_->SetStatus(ServiceWorkerVersion::INSTALLING);
// Start a worker.
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_FAILED;
- version_->StartWorker(CreateReceiverOnCurrentThread(&status));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
EXPECT_EQ(0, helper_->mock_render_process_host()->bad_msg_count());
- // Invalid URL, should kill worker (but in tests will only increase bad
+ GURL valid_scope_1("http://www.example.com/test/subscope");
+ GURL valid_scope_2("http://www.example.com/test/othersubscope");
+ std::vector<GURL> valid_scopes;
+ valid_scopes.push_back(valid_scope_1);
+ valid_scopes.push_back(valid_scope_2);
+
+ std::vector<url::Origin> all_origins;
+ url::Origin valid_origin(GURL("https://chromium.org/"));
+ std::vector<url::Origin> valid_origin_list(1, valid_origin);
+
+ // Invalid subscope, should kill worker (but in tests will only increase bad
// message count).
- version_->OnRegisterForeignFetchScopes(std::vector<GURL>(1, GURL()));
+ version_->OnRegisterForeignFetchScopes(std::vector<GURL>(1, GURL()),
+ valid_origin_list);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(1, helper_->mock_render_process_host()->bad_msg_count());
EXPECT_EQ(0u, version_->foreign_fetch_scopes_.size());
+ EXPECT_EQ(0u, version_->foreign_fetch_origins_.size());
- // URL outside the scope of the worker.
+ // Subscope outside the scope of the worker.
version_->OnRegisterForeignFetchScopes(
- std::vector<GURL>(1, GURL("http://www.example.com/wrong")));
+ std::vector<GURL>(1, GURL("http://www.example.com/wrong")),
+ valid_origin_list);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(2, helper_->mock_render_process_host()->bad_msg_count());
EXPECT_EQ(0u, version_->foreign_fetch_scopes_.size());
+ EXPECT_EQ(0u, version_->foreign_fetch_origins_.size());
- // URL on wrong origin.
+ // Subscope on wrong origin.
version_->OnRegisterForeignFetchScopes(
- std::vector<GURL>(1, GURL("http://example.com/test/")));
+ std::vector<GURL>(1, GURL("http://example.com/test/")),
+ valid_origin_list);
base::RunLoop().RunUntilIdle();
EXPECT_EQ(3, helper_->mock_render_process_host()->bad_msg_count());
EXPECT_EQ(0u, version_->foreign_fetch_scopes_.size());
+ EXPECT_EQ(0u, version_->foreign_fetch_origins_.size());
- // Valid URL 1.
- GURL valid_scope_1("http://www.example.com/test/subscope");
- version_->OnRegisterForeignFetchScopes(std::vector<GURL>(1, valid_scope_1));
+ // Invalid origin.
+ version_->OnRegisterForeignFetchScopes(
+ valid_scopes, std::vector<url::Origin>(1, url::Origin()));
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(3, helper_->mock_render_process_host()->bad_msg_count());
+ EXPECT_EQ(4, helper_->mock_render_process_host()->bad_msg_count());
+ EXPECT_EQ(0u, version_->foreign_fetch_scopes_.size());
+ EXPECT_EQ(0u, version_->foreign_fetch_origins_.size());
+
+ // Valid subscope, no origins.
+ version_->OnRegisterForeignFetchScopes(std::vector<GURL>(1, valid_scope_1),
+ all_origins);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(4, helper_->mock_render_process_host()->bad_msg_count());
EXPECT_EQ(1u, version_->foreign_fetch_scopes_.size());
EXPECT_EQ(valid_scope_1, version_->foreign_fetch_scopes_[0]);
+ EXPECT_EQ(0u, version_->foreign_fetch_origins_.size());
- // Valid URL 2.
- GURL valid_scope_2("http://www.example.com/test/subscope");
- version_->OnRegisterForeignFetchScopes(std::vector<GURL>(1, valid_scope_2));
+ // Valid subscope, explicit origins.
+ version_->OnRegisterForeignFetchScopes(valid_scopes, valid_origin_list);
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(3, helper_->mock_render_process_host()->bad_msg_count());
+ EXPECT_EQ(4, helper_->mock_render_process_host()->bad_msg_count());
EXPECT_EQ(2u, version_->foreign_fetch_scopes_.size());
EXPECT_EQ(valid_scope_1, version_->foreign_fetch_scopes_[0]);
EXPECT_EQ(valid_scope_2, version_->foreign_fetch_scopes_[1]);
+ EXPECT_EQ(1u, version_->foreign_fetch_origins_.size());
+ EXPECT_EQ(valid_origin, version_->foreign_fetch_origins_[0]);
}
TEST_F(ServiceWorkerVersionTest, RendererCrashDuringEvent) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
- version_->StartWorker(CreateReceiverOnCurrentThread(&status));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC,
+ CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
@@ -1173,14 +1182,15 @@ TEST_F(ServiceWorkerVersionTest, RendererCrashDuringEvent) {
EXPECT_EQ(ServiceWorkerVersion::STOPPED, version_->running_status());
// Request already failed, calling finsh should return false.
- EXPECT_FALSE(version_->FinishRequest(request_id));
+ EXPECT_FALSE(version_->FinishRequest(request_id, true));
}
TEST_F(ServiceWorkerVersionWithMojoTest, MojoService) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
- version_->StartWorker(CreateReceiverOnCurrentThread(&status));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC,
+ CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
@@ -1189,22 +1199,23 @@ TEST_F(ServiceWorkerVersionWithMojoTest, MojoService) {
int request_id = version_->StartRequest(
ServiceWorkerMetrics::EventType::SYNC,
CreateReceiverOnCurrentThread(&status, runner->QuitClosure()));
- base::WeakPtr<TestMojoService> service =
- version_->GetMojoServiceForRequest<TestMojoService>(request_id);
+ base::WeakPtr<mojom::TestMojoService> service =
+ version_->GetMojoServiceForRequest<mojom::TestMojoService>(request_id);
service->DoSomething(runner->QuitClosure());
runner->Run();
// Mojo service does exist in worker, so error callback should not have been
// called and FinishRequest should return true.
EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_TRUE(version_->FinishRequest(request_id));
+ EXPECT_TRUE(version_->FinishRequest(request_id, true));
}
TEST_F(ServiceWorkerVersionTest, NonExistentMojoService) {
ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_NETWORK; // dummy value
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
- version_->StartWorker(CreateReceiverOnCurrentThread(&status));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC,
+ CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
@@ -1213,15 +1224,15 @@ TEST_F(ServiceWorkerVersionTest, NonExistentMojoService) {
int request_id = version_->StartRequest(
ServiceWorkerMetrics::EventType::SYNC,
CreateReceiverOnCurrentThread(&status, runner->QuitClosure()));
- base::WeakPtr<TestMojoService> service =
- version_->GetMojoServiceForRequest<TestMojoService>(request_id);
+ base::WeakPtr<mojom::TestMojoService> service =
+ version_->GetMojoServiceForRequest<mojom::TestMojoService>(request_id);
service->DoSomething(runner->QuitClosure());
runner->Run();
// Mojo service doesn't exist in worker, so error callback should have been
// called and FinishRequest should return false.
EXPECT_EQ(SERVICE_WORKER_ERROR_FAILED, status);
- EXPECT_FALSE(version_->FinishRequest(request_id));
+ EXPECT_FALSE(version_->FinishRequest(request_id, true));
}
TEST_F(ServiceWorkerVersionTest, DispatchEvent) {
@@ -1229,7 +1240,8 @@ TEST_F(ServiceWorkerVersionTest, DispatchEvent) {
// Activate and start worker.
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
- version_->StartWorker(CreateReceiverOnCurrentThread(&status));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC,
+ CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
@@ -1265,7 +1277,65 @@ TEST_F(ServiceWorkerVersionTest, DispatchEvent) {
// Should not have timed out, so error callback should not have been
// called and FinishRequest should return true.
EXPECT_EQ(SERVICE_WORKER_OK, status);
- EXPECT_TRUE(version_->FinishRequest(request_id));
+ EXPECT_TRUE(version_->FinishRequest(request_id, true));
+}
+
+TEST_F(ServiceWorkerFailToStartTest, FailingWorkerUsesNewRendererProcess) {
+ ServiceWorkerStatusCode status = SERVICE_WORKER_ERROR_MAX_VALUE;
+
+ helper_->SimulateAddProcessToPattern(pattern_,
+ helper_->new_render_process_id());
+ ServiceWorkerContextCore* context = helper_->context();
+ int64_t id = version_->version_id();
+
+ // Start once. It should choose the "existing process".
+ set_start_mode(MessageReceiverDisallowStart::StartMode::SUCCEED);
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(helper_->mock_render_process_id(),
+ version_->embedded_worker()->process_id());
+ version_->StopWorker(CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+
+ // Fail once.
+ set_start_mode(MessageReceiverDisallowStart::StartMode::FAIL);
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status);
+ EXPECT_EQ(1, context->GetVersionFailureCount(id));
+
+ // Fail again.
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(SERVICE_WORKER_ERROR_START_WORKER_FAILED, status);
+ EXPECT_EQ(2, context->GetVersionFailureCount(id));
+
+ // Succeed. It should choose the "new process".
+ set_start_mode(MessageReceiverDisallowStart::StartMode::SUCCEED);
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(helper_->new_render_process_id(),
+ version_->embedded_worker()->process_id());
+ EXPECT_EQ(0, context->GetVersionFailureCount(id));
+ version_->StopWorker(CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+
+ // Start again. It should choose the "existing process" again as we no longer
+ // force creation of a new process.
+ version_->StartWorker(ServiceWorkerMetrics::EventType::UNKNOWN,
+ CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(helper_->mock_render_process_id(),
+ version_->embedded_worker()->process_id());
+ version_->StopWorker(CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
}
TEST_F(ServiceWorkerVersionTest, DispatchConcurrentEvent) {
@@ -1273,7 +1343,8 @@ TEST_F(ServiceWorkerVersionTest, DispatchConcurrentEvent) {
// Activate and start worker.
version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
- version_->StartWorker(CreateReceiverOnCurrentThread(&status));
+ version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC,
+ CreateReceiverOnCurrentThread(&status));
base::RunLoop().RunUntilIdle();
EXPECT_EQ(SERVICE_WORKER_OK, status);
EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
@@ -1328,7 +1399,7 @@ TEST_F(ServiceWorkerVersionTest, DispatchConcurrentEvent) {
EXPECT_EQ(request_id2, received_request_id2);
EXPECT_EQ(reply2, received_data2);
EXPECT_EQ(SERVICE_WORKER_OK, status2);
- EXPECT_TRUE(version_->FinishRequest(request_id2));
+ EXPECT_TRUE(version_->FinishRequest(request_id2, true));
// Reply to first event.
std::string reply1("hello world");
@@ -1341,7 +1412,81 @@ TEST_F(ServiceWorkerVersionTest, DispatchConcurrentEvent) {
EXPECT_EQ(request_id2, received_request_id2);
EXPECT_EQ(reply1, received_data1);
EXPECT_EQ(SERVICE_WORKER_OK, status1);
- EXPECT_TRUE(version_->FinishRequest(request_id1));
+ EXPECT_TRUE(version_->FinishRequest(request_id1, true));
+}
+
+TEST_F(ServiceWorkerVersionTest, DispatchSimpleEvent_Completed) {
+ ServiceWorkerStatusCode status =
+ SERVICE_WORKER_ERROR_MAX_VALUE; // dummy value
+
+ // Activate and start worker.
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC,
+ CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+
+ // Start request and dispatch test event.
+ status = SERVICE_WORKER_ERROR_MAX_VALUE; // dummy value
+ scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner);
+ int request_id = version_->StartRequest(
+ ServiceWorkerMetrics::EventType::SYNC,
+ CreateReceiverOnCurrentThread(&status, runner->QuitClosure()));
+ version_->DispatchSimpleEvent<TestMsg_TestSimpleEventResult>(
+ request_id, TestMsg_TestEvent(request_id));
+
+ // Verify event got dispatched to worker.
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(1u, helper_->inner_ipc_sink()->message_count());
+ const IPC::Message* msg = helper_->inner_ipc_sink()->GetMessageAt(0);
+ EXPECT_EQ(TestMsg_TestEvent::ID, msg->type());
+
+ // Simulate sending reply to event.
+ helper_->SimulateSendSimpleEventResult(
+ version_->embedded_worker()->embedded_worker_id(), request_id,
+ blink::WebServiceWorkerEventResultCompleted);
+ runner->Run();
+
+ // Verify callback was called with correct status.
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+}
+
+TEST_F(ServiceWorkerVersionTest, DispatchSimpleEvent_Rejected) {
+ ServiceWorkerStatusCode status =
+ SERVICE_WORKER_ERROR_MAX_VALUE; // dummy value
+
+ // Activate and start worker.
+ version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
+ version_->StartWorker(ServiceWorkerMetrics::EventType::SYNC,
+ CreateReceiverOnCurrentThread(&status));
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(SERVICE_WORKER_OK, status);
+ EXPECT_EQ(ServiceWorkerVersion::RUNNING, version_->running_status());
+
+ // Start request and dispatch test event.
+ status = SERVICE_WORKER_ERROR_MAX_VALUE; // dummy value
+ scoped_refptr<MessageLoopRunner> runner(new MessageLoopRunner);
+ int request_id = version_->StartRequest(
+ ServiceWorkerMetrics::EventType::SYNC,
+ CreateReceiverOnCurrentThread(&status, runner->QuitClosure()));
+ version_->DispatchSimpleEvent<TestMsg_TestSimpleEventResult>(
+ request_id, TestMsg_TestEvent(request_id));
+
+ // Verify event got dispatched to worker.
+ base::RunLoop().RunUntilIdle();
+ ASSERT_EQ(1u, helper_->inner_ipc_sink()->message_count());
+ const IPC::Message* msg = helper_->inner_ipc_sink()->GetMessageAt(0);
+ EXPECT_EQ(TestMsg_TestEvent::ID, msg->type());
+
+ // Simulate sending reply to event.
+ helper_->SimulateSendSimpleEventResult(
+ version_->embedded_worker()->embedded_worker_id(), request_id,
+ blink::WebServiceWorkerEventResultRejected);
+ runner->Run();
+
+ // Verify callback was called with correct status.
+ EXPECT_EQ(SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED, status);
}
} // namespace content
diff --git a/chromium/content/browser/service_worker/service_worker_write_to_cache_job.cc b/chromium/content/browser/service_worker/service_worker_write_to_cache_job.cc
index f878812996b..96e9e8f6a71 100644
--- a/chromium/content/browser/service_worker/service_worker_write_to_cache_job.cc
+++ b/chromium/content/browser/service_worker/service_worker_write_to_cache_job.cc
@@ -13,6 +13,7 @@
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_disk_cache.h"
#include "content/browser/service_worker/service_worker_metrics.h"
+#include "content/common/net/url_request_service_worker_data.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/common/service_worker/service_worker_utils.h"
#include "net/base/io_buffer.h"
@@ -41,17 +42,11 @@ const char kRedirectError[] =
"The script resource is behind a redirect, which is disallowed.";
const char kServiceWorkerAllowed[] = "Service-Worker-Allowed";
-// The net error code used when the job fails the update attempt because the new
-// script is byte-by-byte identical to the incumbent script. This error is shown
-// in DevTools and in netlog, so we want something obscure enough that it won't
-// conflict with a legitimate network error, and not too alarming if seen by
-// developers.
-// TODO(falken): Redesign this class so we don't have to fail at the network
-// stack layer just to cancel the update.
-const net::Error kIdenticalScriptError = net::ERR_FILE_EXISTS;
-
} // namespace
+const net::Error ServiceWorkerWriteToCacheJob::kIdenticalScriptError =
+ net::ERR_FILE_EXISTS;
+
ServiceWorkerWriteToCacheJob::ServiceWorkerWriteToCacheJob(
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
@@ -190,6 +185,8 @@ void ServiceWorkerWriteToCacheJob::InitNetRequest(
request()->first_party_for_cookies());
net_request_->set_initiator(request()->initiator());
net_request_->SetReferrer(request()->referrer());
+ net_request_->SetUserData(URLRequestServiceWorkerData::kUserDataKey,
+ new URLRequestServiceWorkerData());
if (extra_load_flags)
net_request_->SetLoadFlags(net_request_->load_flags() | extra_load_flags);
@@ -337,8 +334,10 @@ void ServiceWorkerWriteToCacheJob::OnResponseStarted(
version_->SetMainScriptHttpResponseInfo(net_request_->response_info());
}
- if (net_request_->response_info().network_accessed)
+ if (net_request_->response_info().network_accessed &&
+ !(net_request_->response_info().was_cached)) {
version_->embedded_worker()->OnNetworkAccessedForScriptLoad();
+ }
http_info_.reset(new net::HttpResponseInfo(net_request_->response_info()));
scoped_refptr<HttpResponseInfoIOBuffer> info_buffer =
@@ -361,12 +360,10 @@ void ServiceWorkerWriteToCacheJob::OnWriteHeadersComplete(net::Error error) {
NotifyStartError(net::URLRequestStatus::FromError(error));
return;
}
- SetStatus(net::URLRequestStatus());
NotifyHeadersComplete();
}
void ServiceWorkerWriteToCacheJob::OnWriteDataComplete(net::Error error) {
- SetStatus(net::URLRequestStatus::FromError(error));
DCHECK_NE(net::ERR_IO_PENDING, error);
if (io_buffer_bytes_ == 0)
error = NotifyFinishedCaching(net::URLRequestStatus::FromError(error), "");
@@ -448,7 +445,6 @@ void ServiceWorkerWriteToCacheJob::NotifyStartErrorHelper(
net::URLRequestStatus reported_status = status;
std::string reported_status_message = status_message;
- SetStatus(reported_status);
NotifyStartError(reported_status);
}
@@ -469,8 +465,7 @@ net::Error ServiceWorkerWriteToCacheJob::NotifyFinishedCaching(
// exists.
if (status.status() == net::URLRequestStatus::SUCCESS &&
!cache_writer_->did_replace()) {
- result = kIdenticalScriptError;
- status = net::URLRequestStatus::FromError(result);
+ status = net::URLRequestStatus::FromError(kIdenticalScriptError);
version_->SetStartWorkerStatusCode(SERVICE_WORKER_ERROR_EXISTS);
version_->script_cache_map()->NotifyFinishedCaching(url_, size, status,
std::string());
@@ -486,7 +481,7 @@ net::Error ServiceWorkerWriteToCacheJob::NotifyFinishedCaching(
scoped_ptr<ServiceWorkerResponseReader>
ServiceWorkerWriteToCacheJob::CreateCacheResponseReader() {
if (incumbent_resource_id_ == kInvalidServiceWorkerResourceId ||
- version_->skip_script_comparison()) {
+ !version_->pause_after_download()) {
return nullptr;
}
return context_->storage()->CreateResponseReader(incumbent_resource_id_);
diff --git a/chromium/content/browser/service_worker/service_worker_write_to_cache_job.h b/chromium/content/browser/service_worker/service_worker_write_to_cache_job.h
index 8cb483cb41c..314fcb2ad08 100644
--- a/chromium/content/browser/service_worker/service_worker_write_to_cache_job.h
+++ b/chromium/content/browser/service_worker/service_worker_write_to_cache_job.h
@@ -40,8 +40,9 @@ class ServiceWorkerVersions;
// incumbent script is detected. The incumbent script is progressively compared
// with the new script as it is read from network. Once a change is detected,
// everything that matched is copied to disk, and from then on the script is
-// written as it continues to be read from network. If the scripts were
-// identical, the job fails so the worker can be discarded.
+// written as it continues to be read from network. If the scripts are
+// identical, the resulting ServiceWorkerScriptCacheMap's main script status is
+// set to kIdenticalScriptError.
class CONTENT_EXPORT ServiceWorkerWriteToCacheJob
: public net::URLRequestJob,
public net::URLRequest::Delegate {
@@ -55,6 +56,10 @@ class CONTENT_EXPORT ServiceWorkerWriteToCacheJob
int64_t resource_id,
int64_t incumbent_resource_id);
+ // The error code used when update fails because the new
+ // script is byte-by-byte identical to the incumbent script.
+ const static net::Error kIdenticalScriptError;
+
private:
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
UpdateBefore24Hours);
@@ -62,6 +67,8 @@ class CONTENT_EXPORT ServiceWorkerWriteToCacheJob
UpdateAfter24Hours);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
UpdateForceBypassCache);
+ FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
+ ServiceWorkerDataRequestAnnotation);
~ServiceWorkerWriteToCacheJob() override;
diff --git a/chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc b/chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc
index 43881d790d2..7b9873d2858 100644
--- a/chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc
+++ b/chromium/content/browser/service_worker/service_worker_write_to_cache_job_unittest.cc
@@ -379,6 +379,7 @@ class ServiceWorkerWriteToCacheJobTest : public testing::Test {
scoped_refptr<ServiceWorkerVersion> new_version =
new ServiceWorkerVersion(registration_.get(), script_url_,
NextVersionId(), context()->AsWeakPtr());
+ new_version->set_pause_after_download(true);
CreateHostForVersion(helper_->mock_render_process_id(), provider_id,
new_version);
diff --git a/chromium/content/browser/shared_worker/shared_worker_host.cc b/chromium/content/browser/shared_worker/shared_worker_host.cc
index 8aefff131ee..e98be02d575 100644
--- a/chromium/content/browser/shared_worker/shared_worker_host.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_host.cc
@@ -89,6 +89,7 @@ void SharedWorkerHost::Start(bool pause_on_start) {
params.name = instance_->name();
params.content_security_policy = instance_->content_security_policy();
params.security_policy_type = instance_->security_policy_type();
+ params.creation_address_space = instance_->creation_address_space();
params.pause_on_start = pause_on_start;
params.route_id = worker_route_id_;
Send(new WorkerProcessMsg_CreateWorker(params));
@@ -181,22 +182,6 @@ void SharedWorkerHost::WorkerConnected(int message_port_id) {
}
}
-void SharedWorkerHost::AllowDatabase(const GURL& url,
- const base::string16& name,
- const base::string16& display_name,
- unsigned long estimated_size,
- bool* result) {
- if (!instance_)
- return;
- *result = GetContentClient()->browser()->AllowWorkerDatabase(
- url,
- name,
- display_name,
- estimated_size,
- instance_->resource_context(),
- GetRenderFrameIDsForWorker());
-}
-
void SharedWorkerHost::AllowFileSystem(const GURL& url,
scoped_ptr<IPC::Message> reply_msg) {
if (!instance_)
diff --git a/chromium/content/browser/shared_worker/shared_worker_host.h b/chromium/content/browser/shared_worker/shared_worker_host.h
index 9fb9ca3550a..621c69bb93c 100644
--- a/chromium/content/browser/shared_worker/shared_worker_host.h
+++ b/chromium/content/browser/shared_worker/shared_worker_host.h
@@ -62,11 +62,6 @@ class SharedWorkerHost {
void WorkerScriptLoadFailed();
void WorkerConnected(int message_port_id);
void WorkerContextDestroyed();
- void AllowDatabase(const GURL& url,
- const base::string16& name,
- const base::string16& display_name,
- unsigned long estimated_size,
- bool* result);
void AllowFileSystem(const GURL& url, scoped_ptr<IPC::Message> reply_msg);
void AllowIndexedDB(const GURL& url,
const base::string16& name,
diff --git a/chromium/content/browser/shared_worker/shared_worker_instance.cc b/chromium/content/browser/shared_worker/shared_worker_instance.cc
index caa3876e63d..282cf190515 100644
--- a/chromium/content/browser/shared_worker/shared_worker_instance.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_instance.cc
@@ -13,6 +13,7 @@ SharedWorkerInstance::SharedWorkerInstance(
const base::string16& name,
const base::string16& content_security_policy,
blink::WebContentSecurityPolicyType security_policy_type,
+ blink::WebAddressSpace creation_address_space,
ResourceContext* resource_context,
const WorkerStoragePartitionId& partition_id,
blink::WebSharedWorkerCreationContextType creation_context_type)
@@ -20,6 +21,7 @@ SharedWorkerInstance::SharedWorkerInstance(
name_(name),
content_security_policy_(content_security_policy),
security_policy_type_(security_policy_type),
+ creation_address_space_(creation_address_space),
resource_context_(resource_context),
partition_id_(partition_id),
creation_context_type_(creation_context_type) {
@@ -31,6 +33,7 @@ SharedWorkerInstance::SharedWorkerInstance(const SharedWorkerInstance& other)
name_(other.name_),
content_security_policy_(other.content_security_policy_),
security_policy_type_(other.security_policy_type_),
+ creation_address_space_(other.creation_address_space_),
resource_context_(other.resource_context_),
partition_id_(other.partition_id_),
creation_context_type_(other.creation_context_type_) {}
diff --git a/chromium/content/browser/shared_worker/shared_worker_instance.h b/chromium/content/browser/shared_worker/shared_worker_instance.h
index 025da9b8008..947621e1261 100644
--- a/chromium/content/browser/shared_worker/shared_worker_instance.h
+++ b/chromium/content/browser/shared_worker/shared_worker_instance.h
@@ -9,6 +9,7 @@
#include "content/browser/shared_worker/worker_storage_partition.h"
#include "content/common/content_export.h"
+#include "third_party/WebKit/public/platform/WebAddressSpace.h"
#include "third_party/WebKit/public/web/WebContentSecurityPolicy.h"
#include "third_party/WebKit/public/web/WebSharedWorkerCreationContextType.h"
#include "url/gurl.h"
@@ -25,6 +26,7 @@ class CONTENT_EXPORT SharedWorkerInstance {
const base::string16& name,
const base::string16& content_security_policy,
blink::WebContentSecurityPolicyType security_policy_type,
+ blink::WebAddressSpace creation_address_space,
ResourceContext* resource_context,
const WorkerStoragePartitionId& partition_id,
blink::WebSharedWorkerCreationContextType creation_context_type);
@@ -52,6 +54,9 @@ class CONTENT_EXPORT SharedWorkerInstance {
blink::WebContentSecurityPolicyType security_policy_type() const {
return security_policy_type_;
}
+ blink::WebAddressSpace creation_address_space() const {
+ return creation_address_space_;
+ }
ResourceContext* resource_context() const {
return resource_context_;
}
@@ -65,6 +70,7 @@ class CONTENT_EXPORT SharedWorkerInstance {
const base::string16 name_;
const base::string16 content_security_policy_;
const blink::WebContentSecurityPolicyType security_policy_type_;
+ const blink::WebAddressSpace creation_address_space_;
ResourceContext* const resource_context_;
const WorkerStoragePartitionId partition_id_;
const blink::WebSharedWorkerCreationContextType creation_context_type_;
diff --git a/chromium/content/browser/shared_worker/shared_worker_instance_unittest.cc b/chromium/content/browser/shared_worker/shared_worker_instance_unittest.cc
index c78cb1fe0a5..9e773f71472 100644
--- a/chromium/content/browser/shared_worker/shared_worker_instance_unittest.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_instance_unittest.cc
@@ -49,7 +49,7 @@ class SharedWorkerInstanceTest : public testing::Test {
TEST_F(SharedWorkerInstanceTest, MatchesTest) {
SharedWorkerInstance instance1(
GURL("http://example.com/w.js"), base::string16(), base::string16(),
- blink::WebContentSecurityPolicyTypeReport,
+ blink::WebContentSecurityPolicyTypeReport, blink::WebAddressSpacePublic,
browser_context_->GetResourceContext(), partition_id_,
blink::WebSharedWorkerCreationContextTypeNonsecure);
EXPECT_TRUE(Matches(instance1, "http://example.com/w.js", ""));
@@ -64,8 +64,8 @@ TEST_F(SharedWorkerInstanceTest, MatchesTest) {
SharedWorkerInstance instance2(
GURL("http://example.com/w.js"), base::ASCIIToUTF16("name"),
base::string16(), blink::WebContentSecurityPolicyTypeReport,
- browser_context_->GetResourceContext(), partition_id_,
- blink::WebSharedWorkerCreationContextTypeNonsecure);
+ blink::WebAddressSpacePublic, browser_context_->GetResourceContext(),
+ partition_id_, blink::WebSharedWorkerCreationContextTypeNonsecure);
EXPECT_FALSE(Matches(instance2, "http://example.com/w.js", ""));
EXPECT_FALSE(Matches(instance2, "http://example.com/w2.js", ""));
EXPECT_FALSE(Matches(instance2, "http://example.net/w.js", ""));
@@ -80,4 +80,17 @@ TEST_F(SharedWorkerInstanceTest, MatchesTest) {
EXPECT_FALSE(Matches(instance2, "http://example.net/w2.js", "name2"));
}
+TEST_F(SharedWorkerInstanceTest, AddressSpace) {
+ for (int i = 0; i < static_cast<int>(blink::WebAddressSpaceLast); i++) {
+ SharedWorkerInstance instance(
+ GURL("http://example.com/w.js"), base::ASCIIToUTF16("name"),
+ base::string16(), blink::WebContentSecurityPolicyTypeReport,
+ static_cast<blink::WebAddressSpace>(i),
+ browser_context_->GetResourceContext(), partition_id_,
+ blink::WebSharedWorkerCreationContextTypeNonsecure);
+ EXPECT_EQ(static_cast<blink::WebAddressSpace>(i),
+ instance.creation_address_space());
+ }
+}
+
} // namespace content
diff --git a/chromium/content/browser/shared_worker/shared_worker_message_filter.cc b/chromium/content/browser/shared_worker/shared_worker_message_filter.cc
index 47902dbdfe6..d6ca6a15ead 100644
--- a/chromium/content/browser/shared_worker/shared_worker_message_filter.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_message_filter.cc
@@ -73,7 +73,6 @@ bool SharedWorkerMessageFilter::OnMessageReceived(const IPC::Message& message) {
OnWorkerScriptLoadFailed)
IPC_MESSAGE_HANDLER(WorkerHostMsg_WorkerConnected,
OnWorkerConnected)
- IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_AllowDatabase, OnAllowDatabase)
IPC_MESSAGE_HANDLER_DELAY_REPLY(
WorkerProcessHostMsg_RequestFileSystemAccessSync,
OnRequestFileSystemAccess)
@@ -143,22 +142,6 @@ void SharedWorkerMessageFilter::OnWorkerConnected(int message_port_id,
this);
}
-void SharedWorkerMessageFilter::OnAllowDatabase(
- int worker_route_id,
- const GURL& url,
- const base::string16& name,
- const base::string16& display_name,
- unsigned long estimated_size,
- bool* result) {
- SharedWorkerServiceImpl::GetInstance()->AllowDatabase(worker_route_id,
- url,
- name,
- display_name,
- estimated_size,
- result,
- this);
-}
-
void SharedWorkerMessageFilter::OnRequestFileSystemAccess(
int worker_route_id,
const GURL& url,
diff --git a/chromium/content/browser/shared_worker/shared_worker_message_filter.h b/chromium/content/browser/shared_worker/shared_worker_message_filter.h
index da0d32ca8ad..b6845e7faef 100644
--- a/chromium/content/browser/shared_worker/shared_worker_message_filter.h
+++ b/chromium/content/browser/shared_worker/shared_worker_message_filter.h
@@ -55,12 +55,6 @@ class CONTENT_EXPORT SharedWorkerMessageFilter : public BrowserMessageFilter {
void OnWorkerScriptLoaded(int worker_route_id);
void OnWorkerScriptLoadFailed(int worker_route_id);
void OnWorkerConnected(int message_port_id, int worker_route_id);
- void OnAllowDatabase(int worker_route_id,
- const GURL& url,
- const base::string16& name,
- const base::string16& display_name,
- unsigned long estimated_size,
- bool* result);
void OnRequestFileSystemAccess(int worker_route_id,
const GURL& url,
IPC::Message* reply_msg);
diff --git a/chromium/content/browser/shared_worker/shared_worker_service_impl.cc b/chromium/content/browser/shared_worker/shared_worker_service_impl.cc
index 653eb11146b..31443a39da9 100644
--- a/chromium/content/browser/shared_worker/shared_worker_service_impl.cc
+++ b/chromium/content/browser/shared_worker/shared_worker_service_impl.cc
@@ -292,8 +292,8 @@ void SharedWorkerServiceImpl::CreateWorker(
*creation_error = blink::WebWorkerCreationErrorNone;
scoped_ptr<SharedWorkerInstance> instance(new SharedWorkerInstance(
params.url, params.name, params.content_security_policy,
- params.security_policy_type, resource_context, partition_id,
- params.creation_context_type));
+ params.security_policy_type, params.creation_address_space,
+ resource_context, partition_id, params.creation_context_type));
scoped_ptr<SharedWorkerPendingInstance::SharedWorkerPendingRequest> request(
new SharedWorkerPendingInstance::SharedWorkerPendingRequest(
filter,
@@ -396,20 +396,6 @@ void SharedWorkerServiceImpl::WorkerConnected(
host->WorkerConnected(message_port_id);
}
-void SharedWorkerServiceImpl::AllowDatabase(
- int worker_route_id,
- const GURL& url,
- const base::string16& name,
- const base::string16& display_name,
- unsigned long estimated_size,
- bool* result,
- SharedWorkerMessageFilter* filter) {
- if (SharedWorkerHost* host = FindSharedWorkerHost(filter, worker_route_id))
- host->AllowDatabase(url, name, display_name, estimated_size, result);
- else
- *result = false;
-}
-
void SharedWorkerServiceImpl::AllowFileSystem(
int worker_route_id,
const GURL& url,
diff --git a/chromium/content/browser/shared_worker/shared_worker_service_impl.h b/chromium/content/browser/shared_worker/shared_worker_service_impl.h
index 7b6bf85f03c..4af3bbf2537 100644
--- a/chromium/content/browser/shared_worker/shared_worker_service_impl.h
+++ b/chromium/content/browser/shared_worker/shared_worker_service_impl.h
@@ -10,6 +10,7 @@
#include "base/compiler_specific.h"
#include "base/containers/scoped_ptr_hash_map.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
#include "base/observer_list.h"
#include "content/public/browser/notification_observer.h"
@@ -70,13 +71,6 @@ class CONTENT_EXPORT SharedWorkerServiceImpl
void WorkerConnected(int message_port_id,
int worker_route_id,
SharedWorkerMessageFilter* filter);
- void AllowDatabase(int worker_route_id,
- const GURL& url,
- const base::string16& name,
- const base::string16& display_name,
- unsigned long estimated_size,
- bool* result,
- SharedWorkerMessageFilter* filter);
void AllowFileSystem(int worker_route_id,
const GURL& url,
IPC::Message* reply_msg,
diff --git a/chromium/content/browser/shared_worker/worker_browsertest.cc b/chromium/content/browser/shared_worker/worker_browsertest.cc
index 553d129916b..278d0eb877a 100644
--- a/chromium/content/browser/shared_worker/worker_browsertest.cc
+++ b/chromium/content/browser/shared_worker/worker_browsertest.cc
@@ -172,7 +172,8 @@ IN_PROC_BROWSER_TEST_F(WorkerTest, WorkerTlsClientAuth) {
net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_server.ServeFilesFromSourceDirectory("content/test/data");
net::SSLServerConfig ssl_config;
- ssl_config.require_client_cert = true;
+ ssl_config.client_cert_type =
+ net::SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT;
https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK, ssl_config);
ASSERT_TRUE(https_server.Start());
@@ -192,7 +193,8 @@ IN_PROC_BROWSER_TEST_F(WorkerTest, SharedWorkerTlsClientAuth) {
net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
https_server.ServeFilesFromSourceDirectory("content/test/data");
net::SSLServerConfig ssl_config;
- ssl_config.require_client_cert = true;
+ ssl_config.client_cert_type =
+ net::SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT;
https_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK, ssl_config);
ASSERT_TRUE(https_server.Start());
diff --git a/chromium/content/browser/site_instance_impl.cc b/chromium/content/browser/site_instance_impl.cc
index 9f88bafc19e..40271d4354f 100644
--- a/chromium/content/browser/site_instance_impl.cc
+++ b/chromium/content/browser/site_instance_impl.cc
@@ -27,8 +27,9 @@ SiteInstanceImpl::SiteInstanceImpl(BrowsingInstance* browsing_instance)
: id_(next_site_instance_id_++),
active_frame_count_(0),
browsing_instance_(browsing_instance),
- process_(NULL),
- has_site_(false) {
+ process_(nullptr),
+ has_site_(false),
+ is_default_subframe_site_instance_(false) {
DCHECK(browsing_instance);
}
@@ -42,8 +43,22 @@ SiteInstanceImpl::~SiteInstanceImpl() {
// the BrowsingInstance. Any future visits to a page from this site
// (within the same BrowsingInstance) can safely create a new SiteInstance.
if (has_site_)
- browsing_instance_->UnregisterSiteInstance(
- static_cast<SiteInstance*>(this));
+ browsing_instance_->UnregisterSiteInstance(this);
+}
+
+scoped_refptr<SiteInstanceImpl> SiteInstanceImpl::Create(
+ BrowserContext* browser_context) {
+ return make_scoped_refptr(
+ new SiteInstanceImpl(new BrowsingInstance(browser_context)));
+}
+
+scoped_refptr<SiteInstanceImpl> SiteInstanceImpl::CreateForURL(
+ BrowserContext* browser_context,
+ const GURL& url) {
+ // This will create a new SiteInstance and BrowsingInstance.
+ scoped_refptr<BrowsingInstance> instance(
+ new BrowsingInstance(browser_context));
+ return instance->GetSiteInstanceForURL(url);
}
int32_t SiteInstanceImpl::GetId() {
@@ -177,7 +192,8 @@ bool SiteInstanceImpl::HasRelatedSiteInstance(const GURL& url) {
return browsing_instance_->HasSiteInstance(url);
}
-SiteInstance* SiteInstanceImpl::GetRelatedSiteInstance(const GURL& url) {
+scoped_refptr<SiteInstance> SiteInstanceImpl::GetRelatedSiteInstance(
+ const GURL& url) {
return browsing_instance_->GetSiteInstanceForURL(url);
}
@@ -211,11 +227,16 @@ bool SiteInstanceImpl::HasWrongProcessForURL(const GURL& url) {
GetProcess(), browsing_instance_->browser_context(), site_url);
}
+scoped_refptr<SiteInstanceImpl>
+SiteInstanceImpl::GetDefaultSubframeSiteInstance() {
+ return browsing_instance_->GetDefaultSubframeSiteInstance();
+}
+
bool SiteInstanceImpl::RequiresDedicatedProcess() {
if (!has_site_)
return false;
- return SiteInstanceImpl::DoesSiteRequireDedicatedProcess(GetBrowserContext(),
- site_);
+
+ return DoesSiteRequireDedicatedProcess(GetBrowserContext(), site_);
}
void SiteInstanceImpl::IncrementActiveFrameCount() {
@@ -253,17 +274,16 @@ BrowserContext* SiteInstanceImpl::GetBrowserContext() const {
}
// static
-SiteInstance* SiteInstance::Create(BrowserContext* browser_context) {
- return new SiteInstanceImpl(new BrowsingInstance(browser_context));
+scoped_refptr<SiteInstance> SiteInstance::Create(
+ BrowserContext* browser_context) {
+ return SiteInstanceImpl::Create(browser_context);
}
// static
-SiteInstance* SiteInstance::CreateForURL(BrowserContext* browser_context,
- const GURL& url) {
- // This will create a new SiteInstance and BrowsingInstance.
- scoped_refptr<BrowsingInstance> instance(
- new BrowsingInstance(browser_context));
- return instance->GetSiteInstanceForURL(url);
+scoped_refptr<SiteInstance> SiteInstance::CreateForURL(
+ BrowserContext* browser_context,
+ const GURL& url) {
+ return SiteInstanceImpl::CreateForURL(browser_context, url);
}
// static
@@ -379,7 +399,7 @@ bool SiteInstanceImpl::DoesSiteRequireDedicatedProcess(
void SiteInstanceImpl::RenderProcessHostDestroyed(RenderProcessHost* host) {
DCHECK_EQ(process_, host);
process_->RemoveObserver(this);
- process_ = NULL;
+ process_ = nullptr;
}
void SiteInstanceImpl::RenderProcessWillExit(RenderProcessHost* host) {
diff --git a/chromium/content/browser/site_instance_impl.h b/chromium/content/browser/site_instance_impl.h
index b54de7f5886..9089a02ab89 100644
--- a/chromium/content/browser/site_instance_impl.h
+++ b/chromium/content/browser/site_instance_impl.h
@@ -20,30 +20,42 @@ namespace content {
class BrowsingInstance;
class RenderProcessHostFactory;
-class CONTENT_EXPORT SiteInstanceImpl : public SiteInstance,
- public RenderProcessHostObserver {
+class CONTENT_EXPORT SiteInstanceImpl final : public SiteInstance,
+ public RenderProcessHostObserver {
public:
- class Observer {
+ class CONTENT_EXPORT Observer {
public:
// Called when this SiteInstance transitions to having no active frames,
// as measured by active_frame_count().
- virtual void ActiveFrameCountIsZero(SiteInstanceImpl* site_instance) = 0;
+ virtual void ActiveFrameCountIsZero(SiteInstanceImpl* site_instance) {}
// Called when the renderer process of this SiteInstance has exited.
virtual void RenderProcessGone(SiteInstanceImpl* site_instance) = 0;
};
+ static scoped_refptr<SiteInstanceImpl> Create(
+ BrowserContext* browser_context);
+ static scoped_refptr<SiteInstanceImpl> CreateForURL(
+ BrowserContext* browser_context,
+ const GURL& url);
+
// SiteInstance interface overrides.
int32_t GetId() override;
bool HasProcess() const override;
RenderProcessHost* GetProcess() override;
BrowserContext* GetBrowserContext() const override;
const GURL& GetSiteURL() const override;
- SiteInstance* GetRelatedSiteInstance(const GURL& url) override;
+ scoped_refptr<SiteInstance> GetRelatedSiteInstance(const GURL& url) override;
bool IsRelatedSiteInstance(const SiteInstance* instance) override;
size_t GetRelatedActiveContentsCount() override;
bool RequiresDedicatedProcess() override;
+ // Returns the SiteInstance, related to this one, that should be used
+ // for subframes when an oopif is required, but a dedicated process is not.
+ // This SiteInstance will be created if it doesn't already exist. There is
+ // at most one of these per BrowsingInstance.
+ scoped_refptr<SiteInstanceImpl> GetDefaultSubframeSiteInstance();
+
// Set the web site that this SiteInstance is rendering pages for.
// This includes the scheme and registered domain, but not the port. If the
// URL does not have a valid registered domain, then the full hostname is
@@ -88,6 +100,10 @@ class CONTENT_EXPORT SiteInstanceImpl : public SiteInstance,
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
+ bool is_default_subframe_site_instance() {
+ return is_default_subframe_site_instance_;
+ }
+
// Sets the global factory used to create new RenderProcessHosts. It may be
// NULL, in which case the default RenderProcessHost will be created (this is
// the behavior if you don't call this function). The factory must be set
@@ -113,19 +129,16 @@ class CONTENT_EXPORT SiteInstanceImpl : public SiteInstance,
static bool DoesSiteRequireDedicatedProcess(BrowserContext* browser_context,
const GURL& effective_url);
- protected:
+ private:
friend class BrowsingInstance;
- friend class SiteInstance;
-
- // Virtual to allow tests to extend it.
- ~SiteInstanceImpl() override;
+ friend class SiteInstanceTestBrowserClient;
- // Create a new SiteInstance. Protected to give access to BrowsingInstance
- // and tests; most callers should use Create or GetRelatedSiteInstance
- // instead.
+ // Create a new SiteInstance. Only BrowsingInstance should call this
+ // directly; clients should use Create() or GetRelatedSiteInstance() instead.
explicit SiteInstanceImpl(BrowsingInstance* browsing_instance);
- private:
+ ~SiteInstanceImpl() override;
+
// RenderProcessHostObserver implementation.
void RenderProcessHostDestroyed(RenderProcessHost* host) override;
void RenderProcessWillExit(RenderProcessHost* host) override;
@@ -136,6 +149,10 @@ class CONTENT_EXPORT SiteInstanceImpl : public SiteInstance,
// Used to restrict a process' origin access rights.
void LockToOrigin();
+ void set_is_default_subframe_site_instance() {
+ is_default_subframe_site_instance_ = true;
+ }
+
// An object used to construct RenderProcessHosts.
static const RenderProcessHostFactory* g_render_process_host_factory_;
@@ -163,6 +180,11 @@ class CONTENT_EXPORT SiteInstanceImpl : public SiteInstance,
// Whether SetSite has been called.
bool has_site_;
+ // Whether this SiteInstance is the default subframe SiteInstance for its
+ // BrowsingInstance. Only one SiteInstance per BrowsingInstance can have this
+ // be true.
+ bool is_default_subframe_site_instance_;
+
base::ObserverList<Observer, true> observers_;
DISALLOW_COPY_AND_ASSIGN(SiteInstanceImpl);
diff --git a/chromium/content/browser/site_instance_impl_unittest.cc b/chromium/content/browser/site_instance_impl_unittest.cc
index b632d74a19b..18cf06fa0f7 100644
--- a/chromium/content/browser/site_instance_impl_unittest.cc
+++ b/chromium/content/browser/site_instance_impl_unittest.cc
@@ -34,14 +34,15 @@
#include "url/url_util.h"
namespace content {
-namespace {
const char kPrivilegedScheme[] = "privileged";
class SiteInstanceTestBrowserClient : public TestContentBrowserClient {
public:
- SiteInstanceTestBrowserClient()
- : privileged_process_id_(-1) {
+ explicit SiteInstanceTestBrowserClient()
+ : privileged_process_id_(-1),
+ site_instance_delete_count_(0),
+ browsing_instance_delete_count_(0) {
WebUIControllerFactory::RegisterFactory(
ContentWebUIControllerFactory::GetInstance());
}
@@ -61,8 +62,32 @@ class SiteInstanceTestBrowserClient : public TestContentBrowserClient {
privileged_process_id_ = process_id;
}
+ void SiteInstanceDeleting(content::SiteInstance* site_instance) override {
+ site_instance_delete_count_++;
+ // Infer deletion of the browsing instance.
+ if (static_cast<SiteInstanceImpl*>(site_instance)
+ ->browsing_instance_->HasOneRef()) {
+ browsing_instance_delete_count_++;
+ }
+ }
+
+ int GetAndClearSiteInstanceDeleteCount() {
+ int result = site_instance_delete_count_;
+ site_instance_delete_count_ = 0;
+ return result;
+ }
+
+ int GetAndClearBrowsingInstanceDeleteCount() {
+ int result = browsing_instance_delete_count_;
+ browsing_instance_delete_count_ = 0;
+ return result;
+ }
+
private:
int privileged_process_id_;
+
+ int site_instance_delete_count_;
+ int browsing_instance_delete_count_;
};
class SiteInstanceTest : public testing::Test {
@@ -72,8 +97,7 @@ class SiteInstanceTest : public testing::Test {
file_user_blocking_thread_(BrowserThread::FILE_USER_BLOCKING,
&message_loop_),
io_thread_(BrowserThread::IO, &message_loop_),
- old_browser_client_(NULL) {
- }
+ old_browser_client_(nullptr) {}
void SetUp() override {
old_browser_client_ = SetBrowserClientForTesting(&browser_client_);
@@ -88,7 +112,7 @@ class SiteInstanceTest : public testing::Test {
EXPECT_TRUE(RenderProcessHost::AllHostsIterator().IsAtEnd());
SetBrowserClientForTesting(old_browser_client_);
- SiteInstanceImpl::set_render_process_host_factory(NULL);
+ SiteInstanceImpl::set_render_process_host_factory(nullptr);
// http://crbug.com/143565 found SiteInstanceTest leaking an
// AppCacheDatabase. This happens because some part of the test indirectly
@@ -114,6 +138,8 @@ class SiteInstanceTest : public testing::Test {
message_loop_.RunUntilIdle();
}
+ SiteInstanceTestBrowserClient* browser_client() { return &browser_client_; }
+
private:
base::MessageLoopForUI message_loop_;
TestBrowserThread ui_thread_;
@@ -125,64 +151,16 @@ class SiteInstanceTest : public testing::Test {
MockRenderProcessHostFactory rph_factory_;
};
-// Subclass of BrowsingInstance that updates a counter when deleted and
-// returns TestSiteInstances from GetSiteInstanceForURL.
-class TestBrowsingInstance : public BrowsingInstance {
- public:
- TestBrowsingInstance(BrowserContext* browser_context, int* delete_counter)
- : BrowsingInstance(browser_context),
- delete_counter_(delete_counter) {
- }
-
- // Make a few methods public for tests.
- using BrowsingInstance::browser_context;
- using BrowsingInstance::HasSiteInstance;
- using BrowsingInstance::GetSiteInstanceForURL;
- using BrowsingInstance::RegisterSiteInstance;
- using BrowsingInstance::UnregisterSiteInstance;
-
- private:
- ~TestBrowsingInstance() override { (*delete_counter_)++; }
-
- int* delete_counter_;
-};
-
-// Subclass of SiteInstanceImpl that updates a counter when deleted.
-class TestSiteInstance : public SiteInstanceImpl {
- public:
- static TestSiteInstance* CreateTestSiteInstance(
- BrowserContext* browser_context,
- int* site_delete_counter,
- int* browsing_delete_counter) {
- TestBrowsingInstance* browsing_instance =
- new TestBrowsingInstance(browser_context, browsing_delete_counter);
- return new TestSiteInstance(browsing_instance, site_delete_counter);
- }
-
- private:
- TestSiteInstance(BrowsingInstance* browsing_instance, int* delete_counter)
- : SiteInstanceImpl(browsing_instance), delete_counter_(delete_counter) {}
- ~TestSiteInstance() override { (*delete_counter_)++; }
-
- int* delete_counter_;
-};
-
-} // namespace
-
// Test to ensure no memory leaks for SiteInstance objects.
TEST_F(SiteInstanceTest, SiteInstanceDestructor) {
// The existence of this object will cause WebContentsImpl to create our
// test one instead of the real one.
RenderViewHostTestEnabler rvh_test_enabler;
- int site_delete_counter = 0;
- int browsing_delete_counter = 0;
const GURL url("test:foo");
// Ensure that instances are deleted when their NavigationEntries are gone.
- TestSiteInstance* instance =
- TestSiteInstance::CreateTestSiteInstance(NULL, &site_delete_counter,
- &browsing_delete_counter);
- EXPECT_EQ(0, site_delete_counter);
+ scoped_refptr<SiteInstanceImpl> instance = SiteInstanceImpl::Create(nullptr);
+ EXPECT_EQ(0, browser_client()->GetAndClearSiteInstanceDeleteCount());
NavigationEntryImpl* e1 = new NavigationEntryImpl(
instance, 0, url, Referrer(), base::string16(), ui::PAGE_TRANSITION_LINK,
@@ -190,43 +168,45 @@ TEST_F(SiteInstanceTest, SiteInstanceDestructor) {
// Redundantly setting e1's SiteInstance shouldn't affect the ref count.
e1->set_site_instance(instance);
- EXPECT_EQ(0, site_delete_counter);
+ EXPECT_EQ(0, browser_client()->GetAndClearSiteInstanceDeleteCount());
+ EXPECT_EQ(0, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
// Add a second reference
NavigationEntryImpl* e2 = new NavigationEntryImpl(
instance, 0, url, Referrer(), base::string16(), ui::PAGE_TRANSITION_LINK,
false);
+ instance = nullptr;
+ EXPECT_EQ(0, browser_client()->GetAndClearSiteInstanceDeleteCount());
+ EXPECT_EQ(0, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
+
// Now delete both entries and be sure the SiteInstance goes away.
delete e1;
- EXPECT_EQ(0, site_delete_counter);
- EXPECT_EQ(0, browsing_delete_counter);
+ EXPECT_EQ(0, browser_client()->GetAndClearSiteInstanceDeleteCount());
+ EXPECT_EQ(0, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
delete e2;
- EXPECT_EQ(1, site_delete_counter);
// instance is now deleted
- EXPECT_EQ(1, browsing_delete_counter);
+ EXPECT_EQ(1, browser_client()->GetAndClearSiteInstanceDeleteCount());
+ EXPECT_EQ(1, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
// browsing_instance is now deleted
// Ensure that instances are deleted when their RenderViewHosts are gone.
scoped_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
- instance =
- TestSiteInstance::CreateTestSiteInstance(browser_context.get(),
- &site_delete_counter,
- &browsing_delete_counter);
{
scoped_ptr<WebContentsImpl> web_contents(static_cast<WebContentsImpl*>(
WebContents::Create(WebContents::CreateParams(
- browser_context.get(), instance))));
- EXPECT_EQ(1, site_delete_counter);
- EXPECT_EQ(1, browsing_delete_counter);
+ browser_context.get(),
+ SiteInstance::Create(browser_context.get())))));
+ EXPECT_EQ(0, browser_client()->GetAndClearSiteInstanceDeleteCount());
+ EXPECT_EQ(0, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
}
// Make sure that we flush any messages related to the above WebContentsImpl
// destruction.
DrainMessageLoops();
- EXPECT_EQ(2, site_delete_counter);
- EXPECT_EQ(2, browsing_delete_counter);
+ EXPECT_EQ(1, browser_client()->GetAndClearSiteInstanceDeleteCount());
+ EXPECT_EQ(1, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
// contents is now deleted, along with instance and browsing_instance
}
@@ -234,40 +214,31 @@ TEST_F(SiteInstanceTest, SiteInstanceDestructor) {
// SiteInstances can be changed afterwards. Also tests that the ref counts are
// updated properly after the change.
TEST_F(SiteInstanceTest, CloneNavigationEntry) {
- int site_delete_counter1 = 0;
- int site_delete_counter2 = 0;
- int browsing_delete_counter = 0;
const GURL url("test:foo");
- SiteInstanceImpl* instance1 =
- TestSiteInstance::CreateTestSiteInstance(NULL, &site_delete_counter1,
- &browsing_delete_counter);
- SiteInstanceImpl* instance2 =
- TestSiteInstance::CreateTestSiteInstance(NULL, &site_delete_counter2,
- &browsing_delete_counter);
-
scoped_ptr<NavigationEntryImpl> e1 = make_scoped_ptr(new NavigationEntryImpl(
- instance1, 0, url, Referrer(), base::string16(), ui::PAGE_TRANSITION_LINK,
- false));
+ SiteInstanceImpl::Create(nullptr), 0, url, Referrer(), base::string16(),
+ ui::PAGE_TRANSITION_LINK, false));
+
// Clone the entry.
scoped_ptr<NavigationEntryImpl> e2 = e1->Clone();
// Should be able to change the SiteInstance of the cloned entry.
- e2->set_site_instance(instance2);
+ e2->set_site_instance(SiteInstanceImpl::Create(nullptr));
+
+ EXPECT_EQ(0, browser_client()->GetAndClearSiteInstanceDeleteCount());
+ EXPECT_EQ(0, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
- // The first SiteInstance should go away after resetting e1, since e2 should
- // no longer be referencing it.
+ // The first SiteInstance and BrowsingInstance should go away after resetting
+ // e1, since e2 should no longer be referencing it.
e1.reset();
- EXPECT_EQ(1, site_delete_counter1);
- EXPECT_EQ(0, site_delete_counter2);
+ EXPECT_EQ(1, browser_client()->GetAndClearSiteInstanceDeleteCount());
+ EXPECT_EQ(1, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
// The second SiteInstance should go away after resetting e2.
e2.reset();
- EXPECT_EQ(1, site_delete_counter1);
- EXPECT_EQ(1, site_delete_counter2);
-
- // Both BrowsingInstances are also now deleted.
- EXPECT_EQ(2, browsing_delete_counter);
+ EXPECT_EQ(1, browser_client()->GetAndClearSiteInstanceDeleteCount());
+ EXPECT_EQ(1, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
DrainMessageLoops();
}
@@ -277,16 +248,16 @@ TEST_F(SiteInstanceTest, GetProcess) {
// Ensure that GetProcess returns a process.
scoped_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
scoped_ptr<RenderProcessHost> host1;
- scoped_refptr<SiteInstanceImpl> instance(static_cast<SiteInstanceImpl*>(
- SiteInstance::Create(browser_context.get())));
+ scoped_refptr<SiteInstanceImpl> instance(
+ SiteInstanceImpl::Create(browser_context.get()));
host1.reset(instance->GetProcess());
- EXPECT_TRUE(host1.get() != NULL);
+ EXPECT_TRUE(host1.get() != nullptr);
// Ensure that GetProcess creates a new process.
- scoped_refptr<SiteInstanceImpl> instance2(static_cast<SiteInstanceImpl*>(
- SiteInstance::Create(browser_context.get())));
+ scoped_refptr<SiteInstanceImpl> instance2(
+ SiteInstanceImpl::Create(browser_context.get()));
scoped_ptr<RenderProcessHost> host2(instance2->GetProcess());
- EXPECT_TRUE(host2.get() != NULL);
+ EXPECT_TRUE(host2.get() != nullptr);
EXPECT_NE(host1.get(), host2.get());
DrainMessageLoops();
@@ -294,8 +265,7 @@ TEST_F(SiteInstanceTest, GetProcess) {
// Test to ensure SetSite and site() work properly.
TEST_F(SiteInstanceTest, SetSite) {
- scoped_refptr<SiteInstanceImpl> instance(static_cast<SiteInstanceImpl*>(
- SiteInstance::Create(NULL)));
+ scoped_refptr<SiteInstanceImpl> instance(SiteInstanceImpl::Create(nullptr));
EXPECT_FALSE(instance->HasSite());
EXPECT_TRUE(instance->GetSiteURL().is_empty());
@@ -311,45 +281,45 @@ TEST_F(SiteInstanceTest, SetSite) {
TEST_F(SiteInstanceTest, GetSiteForURL) {
// Pages are irrelevant.
GURL test_url = GURL("http://www.google.com/index.html");
- GURL site_url = SiteInstanceImpl::GetSiteForURL(NULL, test_url);
+ GURL site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
EXPECT_EQ(GURL("http://google.com"), site_url);
EXPECT_EQ("http", site_url.scheme());
EXPECT_EQ("google.com", site_url.host());
// Ports are irrlevant.
test_url = GURL("https://www.google.com:8080");
- site_url = SiteInstanceImpl::GetSiteForURL(NULL, test_url);
+ site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
EXPECT_EQ(GURL("https://google.com"), site_url);
// Hostnames without TLDs are ok.
test_url = GURL("http://foo/a.html");
- site_url = SiteInstanceImpl::GetSiteForURL(NULL, test_url);
+ site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
EXPECT_EQ(GURL("http://foo"), site_url);
EXPECT_EQ("foo", site_url.host());
// File URLs should include the scheme.
test_url = GURL("file:///C:/Downloads/");
- site_url = SiteInstanceImpl::GetSiteForURL(NULL, test_url);
+ site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
EXPECT_EQ(GURL("file:"), site_url);
EXPECT_EQ("file", site_url.scheme());
EXPECT_FALSE(site_url.has_host());
// Some file URLs have hosts in the path.
test_url = GURL("file://server/path");
- site_url = SiteInstanceImpl::GetSiteForURL(NULL, test_url);
+ site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
EXPECT_EQ(GURL("file://server"), site_url);
EXPECT_EQ("server", site_url.host());
// Data URLs should include the scheme.
test_url = GURL("data:text/html,foo");
- site_url = SiteInstanceImpl::GetSiteForURL(NULL, test_url);
+ site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
EXPECT_EQ(GURL("data:"), site_url);
EXPECT_EQ("data", site_url.scheme());
EXPECT_FALSE(site_url.has_host());
// Javascript URLs should include the scheme.
test_url = GURL("javascript:foo();");
- site_url = SiteInstanceImpl::GetSiteForURL(NULL, test_url);
+ site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
EXPECT_EQ(GURL("javascript:"), site_url);
EXPECT_EQ("javascript", site_url.scheme());
EXPECT_FALSE(site_url.has_host());
@@ -359,7 +329,7 @@ TEST_F(SiteInstanceTest, GetSiteForURL) {
std::string guest_url(kGuestScheme);
guest_url.append("://abc123/path");
test_url = GURL(guest_url);
- site_url = SiteInstanceImpl::GetSiteForURL(NULL, test_url);
+ site_url = SiteInstanceImpl::GetSiteForURL(nullptr, test_url);
EXPECT_EQ(test_url, site_url);
DrainMessageLoops();
@@ -377,29 +347,31 @@ TEST_F(SiteInstanceTest, IsSameWebSite) {
GURL url_blank = GURL(url::kAboutBlankURL);
// Same scheme and port -> same site.
- EXPECT_TRUE(SiteInstance::IsSameWebSite(NULL, url_foo, url_foo2));
+ EXPECT_TRUE(SiteInstance::IsSameWebSite(nullptr, url_foo, url_foo2));
// Different scheme -> different site.
- EXPECT_FALSE(SiteInstance::IsSameWebSite(NULL, url_foo, url_foo_https));
+ EXPECT_FALSE(SiteInstance::IsSameWebSite(nullptr, url_foo, url_foo_https));
// Different port -> same site.
// (Changes to document.domain make renderer ignore the port.)
- EXPECT_TRUE(SiteInstance::IsSameWebSite(NULL, url_foo, url_foo_port));
+ EXPECT_TRUE(SiteInstance::IsSameWebSite(nullptr, url_foo, url_foo_port));
// JavaScript links should be considered same site for anything.
- EXPECT_TRUE(SiteInstance::IsSameWebSite(NULL, url_javascript, url_foo));
- EXPECT_TRUE(SiteInstance::IsSameWebSite(NULL, url_javascript, url_foo_https));
- EXPECT_TRUE(SiteInstance::IsSameWebSite(NULL, url_javascript, url_foo_port));
+ EXPECT_TRUE(SiteInstance::IsSameWebSite(nullptr, url_javascript, url_foo));
+ EXPECT_TRUE(
+ SiteInstance::IsSameWebSite(nullptr, url_javascript, url_foo_https));
+ EXPECT_TRUE(
+ SiteInstance::IsSameWebSite(nullptr, url_javascript, url_foo_port));
// Navigating to a blank page is considered the same site.
- EXPECT_TRUE(SiteInstance::IsSameWebSite(NULL, url_foo, url_blank));
- EXPECT_TRUE(SiteInstance::IsSameWebSite(NULL, url_foo_https, url_blank));
- EXPECT_TRUE(SiteInstance::IsSameWebSite(NULL, url_foo_port, url_blank));
+ EXPECT_TRUE(SiteInstance::IsSameWebSite(nullptr, url_foo, url_blank));
+ EXPECT_TRUE(SiteInstance::IsSameWebSite(nullptr, url_foo_https, url_blank));
+ EXPECT_TRUE(SiteInstance::IsSameWebSite(nullptr, url_foo_port, url_blank));
// Navigating from a blank site is not considered to be the same site.
- EXPECT_FALSE(SiteInstance::IsSameWebSite(NULL, url_blank, url_foo));
- EXPECT_FALSE(SiteInstance::IsSameWebSite(NULL, url_blank, url_foo_https));
- EXPECT_FALSE(SiteInstance::IsSameWebSite(NULL, url_blank, url_foo_port));
+ EXPECT_FALSE(SiteInstance::IsSameWebSite(nullptr, url_blank, url_foo));
+ EXPECT_FALSE(SiteInstance::IsSameWebSite(nullptr, url_blank, url_foo_https));
+ EXPECT_FALSE(SiteInstance::IsSameWebSite(nullptr, url_blank, url_foo_port));
DrainMessageLoops();
}
@@ -409,22 +381,20 @@ TEST_F(SiteInstanceTest, IsSameWebSite) {
TEST_F(SiteInstanceTest, OneSiteInstancePerSite) {
ASSERT_FALSE(base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kProcessPerSite));
- int delete_counter = 0;
scoped_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
- TestBrowsingInstance* browsing_instance =
- new TestBrowsingInstance(browser_context.get(), &delete_counter);
+ BrowsingInstance* browsing_instance =
+ new BrowsingInstance(browser_context.get());
const GURL url_a1("http://www.google.com/1.html");
scoped_refptr<SiteInstanceImpl> site_instance_a1(
- static_cast<SiteInstanceImpl*>(
- browsing_instance->GetSiteInstanceForURL(url_a1)));
- EXPECT_TRUE(site_instance_a1.get() != NULL);
+ browsing_instance->GetSiteInstanceForURL(url_a1));
+ EXPECT_TRUE(site_instance_a1.get() != nullptr);
// A separate site should create a separate SiteInstance.
const GURL url_b1("http://www.yahoo.com/");
scoped_refptr<SiteInstanceImpl> site_instance_b1(
- static_cast<SiteInstanceImpl*>(
- browsing_instance->GetSiteInstanceForURL(url_b1)));
+
+ browsing_instance->GetSiteInstanceForURL(url_b1));
EXPECT_NE(site_instance_a1.get(), site_instance_b1.get());
EXPECT_TRUE(site_instance_a1->IsRelatedSiteInstance(site_instance_b1.get()));
@@ -442,12 +412,11 @@ TEST_F(SiteInstanceTest, OneSiteInstancePerSite) {
// A visit to the original site in a new BrowsingInstance (same or different
// browser context) should return a different SiteInstance.
- TestBrowsingInstance* browsing_instance2 =
- new TestBrowsingInstance(browser_context.get(), &delete_counter);
+ BrowsingInstance* browsing_instance2 =
+ new BrowsingInstance(browser_context.get());
// Ensure the new SiteInstance is ref counted so that it gets deleted.
scoped_refptr<SiteInstanceImpl> site_instance_a2_2(
- static_cast<SiteInstanceImpl*>(
- browsing_instance2->GetSiteInstanceForURL(url_a2)));
+ browsing_instance2->GetSiteInstanceForURL(url_a2));
EXPECT_NE(site_instance_a1.get(), site_instance_a2_2.get());
EXPECT_FALSE(
site_instance_a1->IsRelatedSiteInstance(site_instance_a2_2.get()));
@@ -483,23 +452,20 @@ TEST_F(SiteInstanceTest, OneSiteInstancePerSite) {
TEST_F(SiteInstanceTest, OneSiteInstancePerSiteInBrowserContext) {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kProcessPerSite);
- int delete_counter = 0;
scoped_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
- TestBrowsingInstance* browsing_instance =
- new TestBrowsingInstance(browser_context.get(), &delete_counter);
+ scoped_refptr<BrowsingInstance> browsing_instance =
+ new BrowsingInstance(browser_context.get());
const GURL url_a1("http://www.google.com/1.html");
scoped_refptr<SiteInstanceImpl> site_instance_a1(
- static_cast<SiteInstanceImpl*>(
- browsing_instance->GetSiteInstanceForURL(url_a1)));
- EXPECT_TRUE(site_instance_a1.get() != NULL);
+ browsing_instance->GetSiteInstanceForURL(url_a1));
+ EXPECT_TRUE(site_instance_a1.get() != nullptr);
scoped_ptr<RenderProcessHost> process_a1(site_instance_a1->GetProcess());
// A separate site should create a separate SiteInstance.
const GURL url_b1("http://www.yahoo.com/");
scoped_refptr<SiteInstanceImpl> site_instance_b1(
- static_cast<SiteInstanceImpl*>(
- browsing_instance->GetSiteInstanceForURL(url_b1)));
+ browsing_instance->GetSiteInstanceForURL(url_b1));
EXPECT_NE(site_instance_a1.get(), site_instance_b1.get());
EXPECT_TRUE(site_instance_a1->IsRelatedSiteInstance(site_instance_b1.get()));
@@ -517,24 +483,22 @@ TEST_F(SiteInstanceTest, OneSiteInstancePerSiteInBrowserContext) {
// A visit to the original site in a new BrowsingInstance (same browser
// context) should return a different SiteInstance with the same process.
- TestBrowsingInstance* browsing_instance2 =
- new TestBrowsingInstance(browser_context.get(), &delete_counter);
+ BrowsingInstance* browsing_instance2 =
+ new BrowsingInstance(browser_context.get());
scoped_refptr<SiteInstanceImpl> site_instance_a1_2(
- static_cast<SiteInstanceImpl*>(
- browsing_instance2->GetSiteInstanceForURL(url_a1)));
- EXPECT_TRUE(site_instance_a1.get() != NULL);
+ browsing_instance2->GetSiteInstanceForURL(url_a1));
+ EXPECT_TRUE(site_instance_a1.get() != nullptr);
EXPECT_NE(site_instance_a1.get(), site_instance_a1_2.get());
EXPECT_EQ(process_a1.get(), site_instance_a1_2->GetProcess());
// A visit to the original site in a new BrowsingInstance (different browser
// context) should return a different SiteInstance with a different process.
scoped_ptr<TestBrowserContext> browser_context2(new TestBrowserContext());
- TestBrowsingInstance* browsing_instance3 =
- new TestBrowsingInstance(browser_context2.get(), &delete_counter);
+ BrowsingInstance* browsing_instance3 =
+ new BrowsingInstance(browser_context2.get());
scoped_refptr<SiteInstanceImpl> site_instance_a2_3(
- static_cast<SiteInstanceImpl*>(
- browsing_instance3->GetSiteInstanceForURL(url_a2)));
- EXPECT_TRUE(site_instance_a2_3.get() != NULL);
+ browsing_instance3->GetSiteInstanceForURL(url_a2));
+ EXPECT_TRUE(site_instance_a2_3.get() != nullptr);
scoped_ptr<RenderProcessHost> process_a2_3(site_instance_a2_3->GetProcess());
EXPECT_NE(site_instance_a1.get(), site_instance_a2_3.get());
EXPECT_NE(process_a1.get(), process_a2_3.get());
@@ -561,10 +525,10 @@ TEST_F(SiteInstanceTest, OneSiteInstancePerSiteInBrowserContext) {
DrainMessageLoops();
}
-static SiteInstanceImpl* CreateSiteInstance(BrowserContext* browser_context,
- const GURL& url) {
- return static_cast<SiteInstanceImpl*>(
- SiteInstance::CreateForURL(browser_context, url));
+static scoped_refptr<SiteInstanceImpl> CreateSiteInstance(
+ BrowserContext* browser_context,
+ const GURL& url) {
+ return SiteInstanceImpl::CreateForURL(browser_context, url);
}
// Test to ensure that pages that require certain privileges are grouped
@@ -635,8 +599,8 @@ TEST_F(SiteInstanceTest, ProcessSharingByType) {
TEST_F(SiteInstanceTest, HasWrongProcessForURL) {
scoped_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
scoped_ptr<RenderProcessHost> host;
- scoped_refptr<SiteInstanceImpl> instance(static_cast<SiteInstanceImpl*>(
- SiteInstance::Create(browser_context.get())));
+ scoped_refptr<SiteInstanceImpl> instance(
+ SiteInstanceImpl::Create(browser_context.get()));
EXPECT_FALSE(instance->HasSite());
EXPECT_TRUE(instance->GetSiteURL().is_empty());
@@ -651,7 +615,7 @@ TEST_F(SiteInstanceTest, HasWrongProcessForURL) {
// The call to GetProcess actually creates a new real process, which works
// fine, but might be a cause for problems in different contexts.
host.reset(instance->GetProcess());
- EXPECT_TRUE(host.get() != NULL);
+ EXPECT_TRUE(host.get() != nullptr);
EXPECT_TRUE(instance->HasProcess());
EXPECT_FALSE(instance->HasWrongProcessForURL(GURL("http://evernote.com")));
@@ -662,8 +626,8 @@ TEST_F(SiteInstanceTest, HasWrongProcessForURL) {
// Test that WebUI SiteInstances reject normal web URLs.
const GURL webui_url("chrome://gpu");
- scoped_refptr<SiteInstanceImpl> webui_instance(static_cast<SiteInstanceImpl*>(
- SiteInstance::Create(browser_context.get())));
+ scoped_refptr<SiteInstanceImpl> webui_instance(
+ SiteInstanceImpl::Create(browser_context.get()));
webui_instance->SetSite(webui_url);
scoped_ptr<RenderProcessHost> webui_host(webui_instance->GetProcess());
@@ -680,8 +644,7 @@ TEST_F(SiteInstanceTest, HasWrongProcessForURL) {
// even if we haven't called GetProcess yet. Make sure HasWrongProcessForURL
// doesn't crash (http://crbug.com/137070).
scoped_refptr<SiteInstanceImpl> webui_instance2(
- static_cast<SiteInstanceImpl*>(
- SiteInstance::Create(browser_context.get())));
+ SiteInstanceImpl::Create(browser_context.get()));
webui_instance2->SetSite(webui_url);
EXPECT_FALSE(webui_instance2->HasWrongProcessForURL(webui_url));
EXPECT_TRUE(
@@ -697,8 +660,8 @@ TEST_F(SiteInstanceTest, HasWrongProcessForURLInSitePerProcess) {
scoped_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
scoped_ptr<RenderProcessHost> host;
- scoped_refptr<SiteInstanceImpl> instance(static_cast<SiteInstanceImpl*>(
- SiteInstance::Create(browser_context.get())));
+ scoped_refptr<SiteInstanceImpl> instance(
+ SiteInstanceImpl::Create(browser_context.get()));
instance->SetSite(GURL("http://evernote.com/"));
EXPECT_TRUE(instance->HasSite());
@@ -710,7 +673,7 @@ TEST_F(SiteInstanceTest, HasWrongProcessForURLInSitePerProcess) {
// The call to GetProcess actually creates a new real process, which works
// fine, but might be a cause for problems in different contexts.
host.reset(instance->GetProcess());
- EXPECT_TRUE(host.get() != NULL);
+ EXPECT_TRUE(host.get() != nullptr);
EXPECT_TRUE(instance->HasProcess());
EXPECT_FALSE(instance->HasWrongProcessForURL(GURL("http://evernote.com")));
@@ -728,8 +691,8 @@ TEST_F(SiteInstanceTest, ProcessPerSiteWithWrongBindings) {
scoped_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
scoped_ptr<RenderProcessHost> host;
scoped_ptr<RenderProcessHost> host2;
- scoped_refptr<SiteInstanceImpl> instance(static_cast<SiteInstanceImpl*>(
- SiteInstance::Create(browser_context.get())));
+ scoped_refptr<SiteInstanceImpl> instance(
+ SiteInstanceImpl::Create(browser_context.get()));
EXPECT_FALSE(instance->HasSite());
EXPECT_TRUE(instance->GetSiteURL().is_empty());
@@ -742,7 +705,7 @@ TEST_F(SiteInstanceTest, ProcessPerSiteWithWrongBindings) {
// The call to GetProcess actually creates a new real process.
host.reset(instance->GetProcess());
- EXPECT_TRUE(host.get() != NULL);
+ EXPECT_TRUE(host.get() != nullptr);
EXPECT_TRUE(instance->HasProcess());
// Without bindings, this should look like the wrong process.
@@ -752,11 +715,10 @@ TEST_F(SiteInstanceTest, ProcessPerSiteWithWrongBindings) {
// same process. Make sure it doesn't use the same process if the bindings
// are missing.
scoped_refptr<SiteInstanceImpl> instance2(
- static_cast<SiteInstanceImpl*>(
- SiteInstance::Create(browser_context.get())));
+ SiteInstanceImpl::Create(browser_context.get()));
instance2->SetSite(webui_url);
host2.reset(instance2->GetProcess());
- EXPECT_TRUE(host2.get() != NULL);
+ EXPECT_TRUE(host2.get() != nullptr);
EXPECT_TRUE(instance2->HasProcess());
EXPECT_NE(host.get(), host2.get());
@@ -770,8 +732,8 @@ TEST_F(SiteInstanceTest, NoProcessPerSiteForEmptySite) {
switches::kProcessPerSite);
scoped_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
scoped_ptr<RenderProcessHost> host;
- scoped_refptr<SiteInstanceImpl> instance(static_cast<SiteInstanceImpl*>(
- SiteInstance::Create(browser_context.get())));
+ scoped_refptr<SiteInstanceImpl> instance(
+ SiteInstanceImpl::Create(browser_context.get()));
instance->SetSite(GURL());
EXPECT_TRUE(instance->HasSite());
@@ -784,4 +746,53 @@ TEST_F(SiteInstanceTest, NoProcessPerSiteForEmptySite) {
DrainMessageLoops();
}
+TEST_F(SiteInstanceTest, DefaultSubframeSiteInstance) {
+ if (AreAllSitesIsolatedForTesting())
+ return; // --top-document-isolation is not possible.
+
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kTopDocumentIsolation);
+
+ scoped_ptr<TestBrowserContext> browser_context(new TestBrowserContext());
+ scoped_refptr<SiteInstanceImpl> main_instance =
+ SiteInstanceImpl::Create(browser_context.get());
+ scoped_refptr<SiteInstanceImpl> subframe_instance =
+ main_instance->GetDefaultSubframeSiteInstance();
+ int subframe_instance_id = subframe_instance->GetId();
+
+ EXPECT_NE(main_instance, subframe_instance);
+ EXPECT_EQ(subframe_instance, main_instance->GetDefaultSubframeSiteInstance());
+ EXPECT_FALSE(main_instance->is_default_subframe_site_instance());
+ EXPECT_TRUE(subframe_instance->is_default_subframe_site_instance());
+
+ EXPECT_EQ(0, browser_client()->GetAndClearSiteInstanceDeleteCount());
+ EXPECT_EQ(0, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
+
+ // Free the subframe instance.
+ subframe_instance = nullptr;
+ EXPECT_EQ(1, browser_client()->GetAndClearSiteInstanceDeleteCount());
+ EXPECT_EQ(0, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
+
+ // Calling GetDefaultSubframeSiteInstance again should return a new
+ // SiteInstance with a different ID from the original.
+ subframe_instance = main_instance->GetDefaultSubframeSiteInstance();
+ EXPECT_NE(subframe_instance->GetId(), subframe_instance_id);
+ EXPECT_FALSE(main_instance->is_default_subframe_site_instance());
+ EXPECT_TRUE(subframe_instance->is_default_subframe_site_instance());
+ EXPECT_EQ(subframe_instance->GetDefaultSubframeSiteInstance(),
+ subframe_instance);
+ EXPECT_EQ(0, browser_client()->GetAndClearSiteInstanceDeleteCount());
+ EXPECT_EQ(0, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
+
+ // Free the main instance.
+ main_instance = nullptr;
+ EXPECT_EQ(1, browser_client()->GetAndClearSiteInstanceDeleteCount());
+ EXPECT_EQ(0, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
+
+ // Free the subframe instance, which should free the browsing instance.
+ subframe_instance = nullptr;
+ EXPECT_EQ(1, browser_client()->GetAndClearSiteInstanceDeleteCount());
+ EXPECT_EQ(1, browser_client()->GetAndClearBrowsingInstanceDeleteCount());
+}
+
} // namespace content
diff --git a/chromium/content/browser/site_per_process_browsertest.cc b/chromium/content/browser/site_per_process_browsertest.cc
index 08f4c26bcb8..618ff8fec2c 100644
--- a/chromium/content/browser/site_per_process_browsertest.cc
+++ b/chromium/content/browser/site_per_process_browsertest.cc
@@ -26,17 +26,23 @@
#include "content/browser/frame_host/render_frame_proxy_host.h"
#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
#include "content/browser/gpu/compositor_util.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/browser/renderer_host/input/synthetic_tap_gesture.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_input_event_router.h"
+#include "content/browser/renderer_host/render_widget_host_view_aura.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/common/frame_messages.h"
+#include "content/common/input/synthetic_tap_gesture_params.h"
#include "content/common/view_messages.h"
+#include "content/public/browser/cert_store.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/resource_dispatcher_host.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_switches.h"
+#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/public/test/test_navigation_observer.h"
@@ -49,8 +55,19 @@
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "third_party/WebKit/public/web/WebSandboxFlags.h"
+#include "ui/events/event.h"
+#include "ui/events/event_utils.h"
+#include "ui/gfx/geometry/point.h"
#include "ui/gfx/switches.h"
+#if defined(USE_AURA)
+#include "content/browser/renderer_host/render_widget_host_view_aura.h"
+#endif
+
+#if defined(OS_MACOSX)
+#include "ui/base/test/scoped_preferred_scroller_style_mac.h"
+#endif
+
namespace content {
namespace {
@@ -118,6 +135,15 @@ void SimulateMouseClick(RenderWidgetHost* rwh, int x, int y) {
rwh->ForwardMouseEvent(mouse_event);
}
+// Retrieve document.origin for the frame |ftn|.
+std::string GetDocumentOrigin(FrameTreeNode* ftn) {
+ std::string origin;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ ftn->current_frame_host(),
+ "domAutomationController.send(document.origin)", &origin));
+ return origin;
+}
+
class RenderWidgetHostMouseEventMonitor {
public:
explicit RenderWidgetHostMouseEventMonitor(RenderWidgetHost* host)
@@ -152,9 +178,6 @@ class RenderWidgetHostMouseEventMonitor {
void SurfaceHitTestTestHelper(
Shell* shell,
net::test_server::EmbeddedTestServer* embedded_test_server) {
- if (!UseSurfacesEnabled())
- return;
-
GURL main_url(embedded_test_server->GetURL(
"/frame_tree/page_with_positioned_frame.html"));
NavigateToURL(shell, main_url);
@@ -186,19 +209,9 @@ void SurfaceHitTestTestHelper(
RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
child_node->current_frame_host()->GetRenderWidgetHost()->GetView());
- // We need to wait for a compositor frame from the child frame, at which
- // point its surface will be created.
- while (rwhv_child->RendererFrameNumber() <= 0) {
- // TODO(lazyboy): Find a better way to avoid sleeping like this. See
- // http://crbug.com/405282 for details.
- base::RunLoop run_loop;
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, run_loop.QuitClosure(),
- base::TimeDelta::FromMilliseconds(10));
- run_loop.Run();
- }
-
- uint32_t cur_render_frame_number = root_view->RendererFrameNumber();
+ SurfaceHitTestReadyNotifier notifier(
+ static_cast<RenderWidgetHostViewChildFrame*>(rwhv_child));
+ notifier.WaitForSurfaceReady();
// Target input event to child frame.
blink::WebMouseEvent child_event;
@@ -211,32 +224,6 @@ void SurfaceHitTestTestHelper(
child_frame_monitor.ResetEventReceived();
router->RouteMouseEvent(root_view, &child_event);
- while (!child_frame_monitor.EventWasReceived()) {
- // This is working around a big synchronization problem. It is very
- // difficult to know if we have received a compositor frame from the
- // main frame renderer *after* it received the child frame's surface
- // ID. Hit testing won't work until this happens. So if the hit test
- // fails then we wait for another frame to arrive and try again.
- // TODO(kenrb): We need a better way to do all of this, possibly coming
- // from http://crbug.com/405282.
- while (root_view->RendererFrameNumber() <= cur_render_frame_number) {
- base::RunLoop run_loop;
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, run_loop.QuitClosure(),
- base::TimeDelta::FromMilliseconds(10));
- run_loop.Run();
- }
- cur_render_frame_number = root_view->RendererFrameNumber();
- child_event.type = blink::WebInputEvent::MouseDown;
- child_event.button = blink::WebPointerProperties::ButtonLeft;
- child_event.x = 75;
- child_event.y = 75;
- child_event.clickCount = 1;
- main_frame_monitor.ResetEventReceived();
- child_frame_monitor.ResetEventReceived();
- router->RouteMouseEvent(root_view, &child_event);
- }
-
EXPECT_TRUE(child_frame_monitor.EventWasReceived());
EXPECT_EQ(23, child_frame_monitor.event().x);
EXPECT_EQ(23, child_frame_monitor.event().y);
@@ -545,7 +532,6 @@ class RenderWidgetHostVisibilityObserver : public NotificationObserver {
message_loop_runner_->Quit();
}
- RenderWidgetHostImpl* render_widget_host_;
bool expected_visibility_state_;
scoped_refptr<MessageLoopRunner> message_loop_runner_;
NotificationRegistrar registrar_;
@@ -556,6 +542,33 @@ class RenderWidgetHostVisibilityObserver : public NotificationObserver {
DISALLOW_COPY_AND_ASSIGN(RenderWidgetHostVisibilityObserver);
};
+// A mock CertStore that always assigns the render process host id as
+// the certificate id. Certificates are never removed.
+class MockCertStore : public CertStore {
+ public:
+ MockCertStore() {}
+ ~MockCertStore() override {}
+
+ int StoreCert(net::X509Certificate* cert,
+ int render_process_host_id) override {
+ certs_[render_process_host_id] = cert;
+ return render_process_host_id;
+ }
+
+ bool RetrieveCert(int cert_id,
+ scoped_refptr<net::X509Certificate>* cert) override {
+ if (certs_.find(cert_id) == certs_.end())
+ return false;
+ *cert = certs_[cert_id];
+ return true;
+ }
+
+ private:
+ std::map<int, scoped_refptr<net::X509Certificate>> certs_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockCertStore);
+};
+
} // namespace
//
@@ -597,6 +610,20 @@ class SitePerProcessHighDPIBrowserTest : public SitePerProcessBrowserTest {
}
};
+// SitePerProcessIgnoreCertErrorsBrowserTest
+
+class SitePerProcessIgnoreCertErrorsBrowserTest
+ : public SitePerProcessBrowserTest {
+ public:
+ SitePerProcessIgnoreCertErrorsBrowserTest() {}
+
+ protected:
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ SitePerProcessBrowserTest::SetUpCommandLine(command_line);
+ command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
+ }
+};
+
// Ensure that navigating subframes in --site-per-process mode works and the
// correct documents are committed.
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossSiteIframe) {
@@ -728,9 +755,11 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossSiteIframe) {
// Test that mouse events are being routed to the correct RenderWidgetHostView
// based on coordinates.
-#if defined(OS_ANDROID)
+#if defined(OS_ANDROID) || defined(THREAD_SANITIZER)
// Browser process hit testing is not implemented on Android.
// https://crbug.com/491334
+// The test times out often on TSAN bot.
+// https://crbug.com/591170.
#define MAYBE_SurfaceHitTestTest DISABLED_SurfaceHitTestTest
#else
#define MAYBE_SurfaceHitTestTest SurfaceHitTestTest
@@ -753,6 +782,150 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessHighDPIBrowserTest,
SurfaceHitTestTestHelper(shell(), embedded_test_server());
}
+// Test that mouse events are being routed to the correct RenderWidgetHostView
+// when there are nested out-of-process iframes.
+#if defined(OS_ANDROID)
+// Browser process hit testing is not implemented on Android.
+// https://crbug.com/491334
+#define MAYBE_NestedSurfaceHitTestTest DISABLED_NestedSurfaceHitTestTest
+#else
+#define MAYBE_NestedSurfaceHitTestTest NestedSurfaceHitTestTest
+#endif
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ MAYBE_NestedSurfaceHitTestTest) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "/frame_tree/page_with_positioned_nested_frames.html"));
+ NavigateToURL(shell(), main_url);
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ ASSERT_EQ(1U, root->child_count());
+
+ FrameTreeNode* parent_iframe_node = root->child_at(0);
+ GURL site_url(embedded_test_server()->GetURL(
+ "a.com", "/frame_tree/page_with_positioned_frame.html"));
+ EXPECT_EQ(site_url, parent_iframe_node->current_url());
+ EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
+ parent_iframe_node->current_frame_host()->GetSiteInstance());
+
+ FrameTreeNode* nested_iframe_node = parent_iframe_node->child_at(0);
+ GURL nested_site_url(
+ embedded_test_server()->GetURL("baz.com", "/title1.html"));
+ EXPECT_EQ(nested_site_url, nested_iframe_node->current_url());
+ EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
+ nested_iframe_node->current_frame_host()->GetSiteInstance());
+ EXPECT_NE(parent_iframe_node->current_frame_host()->GetSiteInstance(),
+ nested_iframe_node->current_frame_host()->GetSiteInstance());
+
+ // Create listeners for mouse events.
+ RenderWidgetHostMouseEventMonitor main_frame_monitor(
+ root->current_frame_host()->GetRenderWidgetHost());
+ RenderWidgetHostMouseEventMonitor nested_frame_monitor(
+ nested_iframe_node->current_frame_host()->GetRenderWidgetHost());
+
+ RenderWidgetHostInputEventRouter* router =
+ static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetInputEventRouter();
+
+ RenderWidgetHostViewBase* root_view = static_cast<RenderWidgetHostViewBase*>(
+ root->current_frame_host()->GetRenderWidgetHost()->GetView());
+ RenderWidgetHostViewBase* rwhv_nested =
+ static_cast<RenderWidgetHostViewBase*>(
+ nested_iframe_node->current_frame_host()
+ ->GetRenderWidgetHost()
+ ->GetView());
+
+ SurfaceHitTestReadyNotifier notifier(
+ static_cast<RenderWidgetHostViewChildFrame*>(rwhv_nested));
+ notifier.WaitForSurfaceReady();
+
+ // Target input event to nested frame.
+ blink::WebMouseEvent nested_event;
+ nested_event.type = blink::WebInputEvent::MouseDown;
+ nested_event.button = blink::WebPointerProperties::ButtonLeft;
+ nested_event.x = 125;
+ nested_event.y = 125;
+ nested_event.clickCount = 1;
+ nested_frame_monitor.ResetEventReceived();
+ main_frame_monitor.ResetEventReceived();
+ router->RouteMouseEvent(root_view, &nested_event);
+
+ EXPECT_TRUE(nested_frame_monitor.EventWasReceived());
+ EXPECT_EQ(21, nested_frame_monitor.event().x);
+ EXPECT_EQ(21, nested_frame_monitor.event().y);
+ EXPECT_FALSE(main_frame_monitor.EventWasReceived());
+}
+
+// This test tests that browser process hittesting ignores frames with
+// pointer-events: none.
+#if defined(OS_ANDROID)
+// Browser process hit testing is not implemented on Android.
+// https://crbug.com/491334
+#define MAYBE_SurfaceHitTestPointerEventsNone \
+ DISABLED_SurfaceHitTestPointerEventsNone
+#elif defined(THREAD_SANITIZER)
+// Flaky on TSAN. https://crbug.com/582277
+#define MAYBE_SurfaceHitTestPointerEventsNone \
+ DISABLED_SurfaceHitTestPointerEventsNone
+#else
+#define MAYBE_SurfaceHitTestPointerEventsNone SurfaceHitTestPointerEventsNone
+#endif
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ MAYBE_SurfaceHitTestPointerEventsNone) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "/frame_tree/page_with_positioned_frame_pointer-events_none.html"));
+ NavigateToURL(shell(), main_url);
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ ASSERT_EQ(1U, root->child_count());
+
+ FrameTreeNode* child_node = root->child_at(0);
+ GURL site_url(embedded_test_server()->GetURL("baz.com", "/title1.html"));
+ EXPECT_EQ(site_url, child_node->current_url());
+ EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
+ child_node->current_frame_host()->GetSiteInstance());
+
+ // Create listeners for mouse events.
+ RenderWidgetHostMouseEventMonitor main_frame_monitor(
+ root->current_frame_host()->GetRenderWidgetHost());
+ RenderWidgetHostMouseEventMonitor child_frame_monitor(
+ child_node->current_frame_host()->GetRenderWidgetHost());
+
+ RenderWidgetHostInputEventRouter* router =
+ static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetInputEventRouter();
+
+ RenderWidgetHostViewBase* root_view = static_cast<RenderWidgetHostViewBase*>(
+ root->current_frame_host()->GetRenderWidgetHost()->GetView());
+ RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
+ child_node->current_frame_host()->GetRenderWidgetHost()->GetView());
+
+ SurfaceHitTestReadyNotifier notifier(
+ static_cast<RenderWidgetHostViewChildFrame*>(rwhv_child));
+ notifier.WaitForSurfaceReady();
+
+ // Target input event to child frame.
+ blink::WebMouseEvent child_event;
+ child_event.type = blink::WebInputEvent::MouseDown;
+ child_event.button = blink::WebPointerProperties::ButtonLeft;
+ child_event.x = 75;
+ child_event.y = 75;
+ child_event.clickCount = 1;
+ main_frame_monitor.ResetEventReceived();
+ child_frame_monitor.ResetEventReceived();
+ router->RouteMouseEvent(root_view, &child_event);
+
+ EXPECT_TRUE(main_frame_monitor.EventWasReceived());
+ EXPECT_EQ(75, main_frame_monitor.event().x);
+ EXPECT_EQ(75, main_frame_monitor.event().y);
+ EXPECT_FALSE(child_frame_monitor.EventWasReceived());
+}
+
// Tests OOPIF rendering by checking that the RWH of the iframe generates
// OnSwapCompositorFrame message.
#if defined(OS_ANDROID)
@@ -1230,6 +1403,157 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
DepictFrameTree(root));
}
+// Ensure that the renderer process doesn't crash when the main frame navigates
+// a remote child to a page that results in a network error.
+// See https://crbug.com/558016.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigateRemoteAfterError) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(a)"));
+ NavigateToURL(shell(), main_url);
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // Load same-site page into iframe.
+ {
+ TestNavigationObserver observer(shell()->web_contents());
+ FrameTreeNode* child = root->child_at(0);
+ GURL http_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ NavigateFrameToURL(child, http_url);
+ EXPECT_EQ(http_url, observer.last_navigation_url());
+ EXPECT_TRUE(observer.last_navigation_succeeded());
+ observer.Wait();
+ }
+
+ // Load cross-site page into iframe.
+ {
+ TestNavigationObserver observer(shell()->web_contents());
+ FrameTreeNode* child = root->child_at(0);
+ GURL url = embedded_test_server()->GetURL("foo.com", "/title2.html");
+ NavigateFrameToURL(root->child_at(0), url);
+ EXPECT_TRUE(observer.last_navigation_succeeded());
+ EXPECT_EQ(url, observer.last_navigation_url());
+ observer.Wait();
+
+ // Ensure that we have created a new process for the subframe.
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = http://foo.com/",
+ DepictFrameTree(root));
+ SiteInstance* site_instance =
+ child->current_frame_host()->GetSiteInstance();
+ EXPECT_NE(shell()->web_contents()->GetSiteInstance(), site_instance);
+ }
+
+ // Stop the test server and try to navigate the remote frame.
+ {
+ GURL url = embedded_test_server()->GetURL("bar.com", "/title3.html");
+ EXPECT_TRUE(embedded_test_server()->ShutdownAndWaitUntilComplete());
+ NavigateIframeToURL(shell()->web_contents(), "child-0", url);
+ }
+}
+
+// Ensure that a cross-site page ends up in the correct process when it
+// successfully loads after earlier encountering a network error for it.
+// See https://crbug.com/560511.
+// TODO(creis): Make the net error page show in the correct process as well,
+// per https://crbug.com/588314.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ProcessTransferAfterError) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(a)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ FrameTreeNode* child = root->child_at(0);
+ GURL url_a = child->current_url();
+
+ // Disable host resolution in the test server and try to navigate the subframe
+ // cross-site, which will lead to a committed net error (which looks like
+ // success to the TestNavigationObserver).
+ GURL url_b = embedded_test_server()->GetURL("b.com", "/title3.html");
+ host_resolver()->ClearRules();
+ TestNavigationObserver observer(shell()->web_contents());
+ NavigateIframeToURL(shell()->web_contents(), "child-0", url_b);
+ EXPECT_TRUE(observer.last_navigation_succeeded());
+ EXPECT_EQ(url_b, observer.last_navigation_url());
+ EXPECT_EQ(2, shell()->web_contents()->GetController().GetEntryCount());
+
+ // PlzNavigate: Ensure that we have created a new process for the subframe.
+ if (IsBrowserSideNavigationEnabled()) {
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = http://b.com/",
+ DepictFrameTree(root));
+ EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
+ child->current_frame_host()->GetSiteInstance());
+ }
+
+ // The FrameTreeNode should update its URL (so that we don't affect other uses
+ // of the API), but the frame's last_successful_url shouldn't change and the
+ // origin should be empty.
+ // PlzNavigate: We have switched RenderFrameHosts for the subframe, so the
+ // last succesful url should be empty (since the frame only loaded an error
+ // page).
+ if (IsBrowserSideNavigationEnabled())
+ EXPECT_EQ(GURL(), child->current_frame_host()->last_successful_url());
+ else
+ EXPECT_EQ(url_a, child->current_frame_host()->last_successful_url());
+ EXPECT_EQ(url_b, child->current_url());
+ EXPECT_EQ("null", child->current_origin().Serialize());
+
+ // Try again after re-enabling host resolution.
+ host_resolver()->AddRule("*", "127.0.0.1");
+ NavigateIframeToURL(shell()->web_contents(), "child-0", url_b);
+ EXPECT_TRUE(observer.last_navigation_succeeded());
+ EXPECT_EQ(url_b, observer.last_navigation_url());
+
+ // The FrameTreeNode should have updated its URL and origin.
+ EXPECT_EQ(url_b, child->current_frame_host()->last_successful_url());
+ EXPECT_EQ(url_b, child->current_url());
+ EXPECT_EQ(url_b.GetOrigin().spec(),
+ child->current_origin().Serialize() + '/');
+
+ // Ensure that we have created a new process for the subframe.
+ // PlzNavigate: the subframe should still be in its separate process.
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = http://b.com/",
+ DepictFrameTree(root));
+ EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
+ child->current_frame_host()->GetSiteInstance());
+
+ // Make sure that the navigation replaced the error page and that going back
+ // ends up on the original site.
+ EXPECT_EQ(2, shell()->web_contents()->GetController().GetEntryCount());
+ {
+ TestNavigationObserver back_load_observer(shell()->web_contents());
+ shell()->web_contents()->GetController().GoBack();
+ back_load_observer.Wait();
+ }
+ EXPECT_EQ(
+ " Site A\n"
+ " +--Site A\n"
+ "Where A = http://a.com/",
+ DepictFrameTree(root));
+ EXPECT_EQ(shell()->web_contents()->GetSiteInstance(),
+ child->current_frame_host()->GetSiteInstance());
+ EXPECT_EQ(url_a, child->current_frame_host()->last_successful_url());
+ EXPECT_EQ(url_a, child->current_url());
+ EXPECT_EQ(url_a.GetOrigin().spec(),
+ child->current_origin().Serialize() + '/');
+}
+
// Verify that killing a cross-site frame's process B and then navigating a
// frame to B correctly recreates all proxies in B.
//
@@ -1273,10 +1597,6 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Navigate the second subframe to b.com to recreate the b.com process.
GURL b_url = embedded_test_server()->GetURL("b.com", "/post_message.html");
NavigateFrameToURL(root->child_at(1), b_url);
- // TODO(alexmos): This can be removed once TestFrameNavigationObserver is
- // fixed to use DidFinishLoad.
- EXPECT_TRUE(
- WaitForRenderFrameReady(root->child_at(1)->current_frame_host()));
EXPECT_TRUE(observer.last_navigation_succeeded());
EXPECT_EQ(b_url, observer.last_navigation_url());
EXPECT_TRUE(root->child_at(1)->current_frame_host()->IsRenderFrameLive());
@@ -2004,6 +2324,9 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
#endif
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
MAYBE_FrameOwnerPropertiesPropagationScrolling) {
+#if defined(OS_MACOSX)
+ ui::test::ScopedPreferredScrollerStyle scroller_style_override(false);
+#endif
GURL main_url(embedded_test_server()->GetURL(
"a.com", "/frame_owner_properties_scrolling.html"));
NavigateToURL(shell(), main_url);
@@ -2063,11 +2386,6 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
set_scrolling_property(root->current_frame_host(), scrolling_values[i]);
for (size_t j = 0; j < arraysize(urls); ++j) {
NavigateFrameToURL(child, urls[j]);
-
- // TODO(alexmos): This can be removed once TestFrameNavigationObserver is
- // fixed to use DidFinishLoad.
- EXPECT_TRUE(WaitForRenderFrameReady(child->current_frame_host()));
-
EXPECT_EQ(expect_scrollbar, has_scrollbar(child->current_frame_host()));
}
}
@@ -2142,9 +2460,6 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
" 'marginheight', '%d');", current_margin_height)));
NavigateFrameToURL(child, urls[i]);
- // TODO(alexmos): This can be removed once TestFrameNavigationObserver is
- // fixed to use DidFinishLoad.
- EXPECT_TRUE(WaitForRenderFrameReady(child->current_frame_host()));
std::string actual_margin_width;
EXPECT_TRUE(ExecuteScriptAndExtractString(
@@ -2384,11 +2699,11 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DynamicSandboxFlags) {
// Both frames should not be sandboxed to start with.
EXPECT_EQ(blink::WebSandboxFlags::None,
- root->child_at(0)->current_replication_state().sandbox_flags);
+ root->child_at(0)->pending_sandbox_flags());
EXPECT_EQ(blink::WebSandboxFlags::None,
root->child_at(0)->effective_sandbox_flags());
EXPECT_EQ(blink::WebSandboxFlags::None,
- root->child_at(1)->current_replication_state().sandbox_flags);
+ root->child_at(1)->pending_sandbox_flags());
EXPECT_EQ(blink::WebSandboxFlags::None,
root->child_at(1)->effective_sandbox_flags());
@@ -2399,7 +2714,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DynamicSandboxFlags) {
"'allow-scripts');"));
// Check that updated sandbox flags are propagated to browser process.
- // The new flags should be set in current_replication_state(), while
+ // The new flags should be reflected in pending_sandbox_flags(), while
// effective_sandbox_flags() should still reflect the old flags, because
// sandbox flag updates take place only after navigations. "allow-scripts"
// resets both SandboxFlags::Scripts and SandboxFlags::AutomaticFeatures bits
@@ -2407,8 +2722,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DynamicSandboxFlags) {
blink::WebSandboxFlags expected_flags =
blink::WebSandboxFlags::All & ~blink::WebSandboxFlags::Scripts &
~blink::WebSandboxFlags::AutomaticFeatures;
- EXPECT_EQ(expected_flags,
- root->child_at(0)->current_replication_state().sandbox_flags);
+ EXPECT_EQ(expected_flags, root->child_at(0)->pending_sandbox_flags());
EXPECT_EQ(blink::WebSandboxFlags::None,
root->child_at(0)->effective_sandbox_flags());
@@ -2434,8 +2748,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DynamicSandboxFlags) {
// Confirm that the browser process has updated the frame's current sandbox
// flags.
- EXPECT_EQ(expected_flags,
- root->child_at(0)->current_replication_state().sandbox_flags);
+ EXPECT_EQ(expected_flags, root->child_at(0)->pending_sandbox_flags());
EXPECT_EQ(expected_flags, root->child_at(0)->effective_sandbox_flags());
// Opening a popup in the now-sandboxed frame should fail.
@@ -2477,6 +2790,10 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, DynamicSandboxFlags) {
&success));
EXPECT_TRUE(success);
EXPECT_EQ(1u, Shell::windows().size());
+
+ // Child of a sandboxed frame should also be sandboxed on the browser side.
+ EXPECT_EQ(expected_flags,
+ root->child_at(0)->child_at(0)->effective_sandbox_flags());
}
// Check that dynamic updates to iframe sandbox flags are propagated correctly.
@@ -2511,26 +2828,20 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
blink::WebSandboxFlags expected_flags =
blink::WebSandboxFlags::All & ~blink::WebSandboxFlags::Scripts &
~blink::WebSandboxFlags::AutomaticFeatures;
- EXPECT_EQ(expected_flags,
- root->child_at(1)->current_replication_state().sandbox_flags);
+ EXPECT_EQ(expected_flags, root->child_at(1)->pending_sandbox_flags());
EXPECT_EQ(blink::WebSandboxFlags::None,
root->child_at(1)->effective_sandbox_flags());
// Navigate the second subframe to a page on bar.com. This will trigger a
- // remote-to-local frame swap in bar.com's process. The target page has
- // another frame, so use TestFrameNavigationObserver to wait for all frames
- // to be loaded.
- TestFrameNavigationObserver frame_observer(root->child_at(1), 2);
+ // remote-to-local frame swap in bar.com's process.
GURL bar_url(embedded_test_server()->GetURL(
"bar.com", "/frame_tree/page_with_one_frame.html"));
NavigateFrameToURL(root->child_at(1), bar_url);
- frame_observer.Wait();
EXPECT_EQ(bar_url, root->child_at(1)->current_url());
ASSERT_EQ(1U, root->child_at(1)->child_count());
// Confirm that the browser process has updated the current sandbox flags.
- EXPECT_EQ(expected_flags,
- root->child_at(1)->current_replication_state().sandbox_flags);
+ EXPECT_EQ(expected_flags, root->child_at(1)->pending_sandbox_flags());
EXPECT_EQ(expected_flags, root->child_at(1)->effective_sandbox_flags());
// Opening a popup in the sandboxed second frame should fail.
@@ -2576,7 +2887,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// The frame should not be sandboxed to start with.
EXPECT_EQ(blink::WebSandboxFlags::None,
- root->child_at(0)->current_replication_state().sandbox_flags);
+ root->child_at(0)->pending_sandbox_flags());
EXPECT_EQ(blink::WebSandboxFlags::None,
root->child_at(0)->effective_sandbox_flags());
@@ -2587,7 +2898,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
"'allow-scripts');"));
// Check that updated sandbox flags are propagated to browser process.
- // The new flags should be set in current_replication_state(), while
+ // The new flags should be set in pending_sandbox_flags(), while
// effective_sandbox_flags() should still reflect the old flags, because
// sandbox flag updates take place only after navigations. "allow-scripts"
// resets both SandboxFlags::Scripts and SandboxFlags::AutomaticFeatures bits
@@ -2595,8 +2906,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
blink::WebSandboxFlags expected_flags =
blink::WebSandboxFlags::All & ~blink::WebSandboxFlags::Scripts &
~blink::WebSandboxFlags::AutomaticFeatures;
- EXPECT_EQ(expected_flags,
- root->child_at(0)->current_replication_state().sandbox_flags);
+ EXPECT_EQ(expected_flags, root->child_at(0)->pending_sandbox_flags());
EXPECT_EQ(blink::WebSandboxFlags::None,
root->child_at(0)->effective_sandbox_flags());
@@ -2611,8 +2921,7 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Confirm that the browser process has updated the frame's current sandbox
// flags.
- EXPECT_EQ(expected_flags,
- root->child_at(0)->current_replication_state().sandbox_flags);
+ EXPECT_EQ(expected_flags, root->child_at(0)->pending_sandbox_flags());
EXPECT_EQ(expected_flags, root->child_at(0)->effective_sandbox_flags());
// Opening a popup in the now-sandboxed frame should fail.
@@ -2706,11 +3015,11 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
blink::WebSandboxFlags::All & ~blink::WebSandboxFlags::Scripts &
~blink::WebSandboxFlags::AutomaticFeatures &
~blink::WebSandboxFlags::Origin;
- EXPECT_EQ(expected_flags,
- root->child_at(1)->current_replication_state().sandbox_flags);
+ EXPECT_EQ(expected_flags, root->child_at(1)->effective_sandbox_flags());
// The child of the sandboxed frame should've inherited sandbox flags, so it
// should not be able to create popups.
+ EXPECT_EQ(expected_flags, bottom_child->effective_sandbox_flags());
bool success = false;
EXPECT_TRUE(
ExecuteScriptAndExtractBool(bottom_child->current_frame_host(),
@@ -2934,6 +3243,47 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_TRUE(node3->current_frame_host()->IsRenderFrameLive());
}
+// Ensure that the renderer does not crash when a local frame with a remote
+// parent frame is swapped from local to remote, then back to local again.
+// See https://crbug.com/585654.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ NavigateSiblingsToSameProcess) {
+ GURL main_url(
+ embedded_test_server()->GetURL("/frame_tree/page_with_two_frames.html"));
+ NavigateToURL(shell(), main_url);
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ FrameTreeNode* node2 = root->child_at(0);
+ FrameTreeNode* node3 = root->child_at(1);
+
+ // Navigate the second iframe to the same process as the first.
+ GURL frame_url = embedded_test_server()->GetURL("bar.com", "/title1.html");
+ NavigateFrameToURL(node3, frame_url);
+
+ // Verify that they are in the same process.
+ EXPECT_EQ(node2->current_frame_host()->GetSiteInstance(),
+ node3->current_frame_host()->GetSiteInstance());
+ EXPECT_NE(root->current_frame_host()->GetSiteInstance(),
+ node3->current_frame_host()->GetSiteInstance());
+
+ // Navigate the first iframe into its parent's process.
+ GURL title_url = embedded_test_server()->GetURL("/title2.html");
+ NavigateFrameToURL(node2, title_url);
+ EXPECT_NE(node2->current_frame_host()->GetSiteInstance(),
+ node3->current_frame_host()->GetSiteInstance());
+
+ // Return the first iframe to the same process as its sibling, and ensure
+ // that it does not crash.
+ NavigateFrameToURL(node2, frame_url);
+ EXPECT_EQ(node2->current_frame_host()->GetSiteInstance(),
+ node3->current_frame_host()->GetSiteInstance());
+ EXPECT_TRUE(node2->current_frame_host()->IsRenderFrameLive());
+}
+
// Verify that load events for iframe elements work when the child frame is
// out-of-process. In such cases, the load event is forwarded from the child
// frame to the parent frame via the browser process.
@@ -3149,13 +3499,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, IndexedFrameAccess) {
GURL c_url(embedded_test_server()->GetURL("c.com", "/post_message.html"));
GURL d_url(embedded_test_server()->GetURL("d.com", "/post_message.html"));
NavigateFrameToURL(child0, b_url);
- // TODO(alexmos): The calls to WaitForRenderFrameReady can be removed once
- // TestFrameNavigationObserver is fixed to use DidFinishLoad.
- EXPECT_TRUE(WaitForRenderFrameReady(child0->current_frame_host()));
NavigateFrameToURL(child1, c_url);
- EXPECT_TRUE(WaitForRenderFrameReady(child1->current_frame_host()));
NavigateFrameToURL(child2, d_url);
- EXPECT_TRUE(WaitForRenderFrameReady(child2->current_frame_host()));
EXPECT_EQ(
" Site A ------------ proxies for B C D\n"
@@ -3331,6 +3676,42 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, OpenPopupWithRemoteParent) {
EXPECT_TRUE(success);
}
+// Test that cross-process popups can't be navigated to disallowed URLs by
+// their opener. This ensures that proper URL validation is performed when
+// RenderFrameProxyHosts are navigated. See https://crbug.com/595339.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigatePopupToIllegalURL) {
+ GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ // Open a cross-site popup.
+ GURL popup_url(embedded_test_server()->GetURL("b.com", "/title2.html"));
+ Shell* popup = OpenPopup(shell()->web_contents(), popup_url, "foo");
+ EXPECT_TRUE(popup);
+ EXPECT_NE(popup->web_contents()->GetSiteInstance(),
+ shell()->web_contents()->GetSiteInstance());
+
+ // From the opener, navigate the popup to a file:/// URL. This should be
+ // disallowed and result in an about:blank navigation.
+ GURL file_url("file:///");
+ NavigateNamedFrame(shell()->web_contents(), file_url, "foo");
+ EXPECT_TRUE(WaitForLoadStop(popup->web_contents()));
+ EXPECT_EQ(GURL(url::kAboutBlankURL),
+ popup->web_contents()->GetLastCommittedURL());
+
+ // Navigate popup back to a cross-site URL.
+ EXPECT_TRUE(NavigateToURL(popup, popup_url));
+ EXPECT_NE(popup->web_contents()->GetSiteInstance(),
+ shell()->web_contents()->GetSiteInstance());
+
+ // Now try the same test with a chrome:// URL.
+ GURL chrome_url(std::string(kChromeUIScheme) + "://" +
+ std::string(kChromeUIGpuHost));
+ NavigateNamedFrame(shell()->web_contents(), chrome_url, "foo");
+ EXPECT_TRUE(WaitForLoadStop(popup->web_contents()));
+ EXPECT_EQ(GURL(url::kAboutBlankURL),
+ popup->web_contents()->GetLastCommittedURL());
+}
+
// Verify that named frames are discoverable from their opener's ancestors.
// See https://crbug.com/511474.
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
@@ -3549,8 +3930,6 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// Navigate popup's subframe to another site.
GURL frame_url(embedded_test_server()->GetURL("c.com", "/post_message.html"));
NavigateFrameToURL(popup_root->child_at(0), frame_url);
- EXPECT_TRUE(
- WaitForRenderFrameReady(popup_root->child_at(0)->current_frame_host()));
// Check that the new subframe process still sees correct opener for its
// parent by sending a postMessage to subframe's parent.opener.
@@ -3691,8 +4070,6 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
GURL frame_url(
embedded_test_server()->GetURL("baz.com", "/post_message.html"));
NavigateFrameToURL(popup_root->child_at(0), frame_url);
- EXPECT_TRUE(
- WaitForRenderFrameReady(popup_root->child_at(0)->current_frame_host()));
// Check that the second subframe's opener is still correct in the first
// subframe's new process. Verify it both in JS and with a postMessage.
@@ -3738,6 +4115,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
->root();
RenderFrameHostImpl* rfh = root->current_frame_host();
RenderViewHostImpl* rvh = rfh->render_view_host();
+ int rvh_routing_id = rvh->GetRoutingID();
+ SiteInstanceImpl* site_instance = rfh->GetSiteInstance();
RenderFrameDeletedObserver deleted_observer(rfh);
// Install a BrowserMessageFilter to drop SwapOut ACK messages in A's
@@ -3751,13 +4130,15 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
GURL b_url(embedded_test_server()->GetURL("b.com", "/title2.html"));
TestFrameNavigationObserver commit_observer(root);
shell()->LoadURL(b_url);
- commit_observer.Wait();
+ commit_observer.WaitForCommit();
+ EXPECT_FALSE(deleted_observer.deleted());
+ rfh->ResetSwapOutTimerForTesting();
// Since the SwapOut ACK for A->B is dropped, the first page's
// RenderFrameHost and RenderViewHost should be pending deletion after the
// last navigation.
- EXPECT_TRUE(root->render_manager()->IsPendingDeletion(rfh));
- EXPECT_TRUE(rvh->is_pending_deletion());
+ EXPECT_FALSE(rfh->is_active());
+ EXPECT_TRUE(root->render_manager()->IsViewPendingDeletion(rvh));
// Wait for process A to exit so we can reinitialize it cleanly for the next
// navigation. This can be removed once https://crbug.com/535246 is fixed.
@@ -3771,19 +4152,48 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
TestNavigationObserver navigation_observer(shell()->web_contents());
shell()->LoadURL(a_url);
RenderViewHostImpl* pending_rvh =
- root->render_manager()->pending_render_view_host();
- EXPECT_EQ(rvh->GetSiteInstance(), pending_rvh->GetSiteInstance());
- EXPECT_NE(rvh, pending_rvh);
-
- // Simulate that the dropped SwapOut ACK message arrives now on the original
- // RenderFrameHost, which should now get deleted.
- rfh->OnSwappedOut();
+ IsBrowserSideNavigationEnabled()
+ ? root->render_manager()->speculative_frame_host()->render_view_host()
+ : root->render_manager()->pending_render_view_host();
+ EXPECT_EQ(site_instance, pending_rvh->GetSiteInstance());
+ EXPECT_NE(rvh_routing_id, pending_rvh->GetRoutingID());
+
+ // TODO(alexmos, creis): Once https://crbug.com/535246 is fixed and the
+ // process_exit_observer is not needed above, we'll need to simulate that the
+ // dropped SwapOut ACK message arrives now on the original RenderFrameHost,
+ // causing it to be deleted.
EXPECT_TRUE(deleted_observer.deleted());
// Make sure the last navigation finishes without crashing.
navigation_observer.Wait();
}
+// Test for https://crbug.com/591478, where navigating to a cross-site page with
+// a subframe on the old site could cause the old RenderViewHost (now pending
+// deletion) to be reused.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ DontReusePendingDeleteRenderViewHostForSubframe) {
+ GURL main_url(embedded_test_server()->GetURL("a.com", "/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ std::string script =
+ "window.onunload = function() { "
+ " var start = Date.now();"
+ " while (Date.now() - start < 1000);"
+ "}";
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(), script));
+
+ // Navigating cross-site with an iframe to the original site shouldn't crash.
+ GURL second_url(embedded_test_server()->GetURL(
+ "b.com", "/cross_site_iframe_factory.html?b(a)"));
+ EXPECT_TRUE(NavigateToURL(shell(), second_url));
+
+ // If the subframe is created while the main frame is pending deletion, then
+ // the RVH will be different.
+ // TODO(creis, alexmos): Find a way to assert this that isn't flaky. For now,
+ // the test is just likely (not certain) to catch regressions by crashing.
+}
+
// Check that when a cross-process frame acquires focus, the old focused frame
// loses focus and fires blur events. Starting on a page with a cross-site
// subframe, simulate mouse clicks to switch focus from root frame to subframe
@@ -4196,10 +4606,293 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, OpenerSetLocation) {
EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), cross_url);
}
+// Ensure that a cross-process subframe with a touch-handler can receive touch
+// events.
+#if defined(USE_AURA)
+// Browser process hit testing is not implemented on Android, and this test
+// requires Aura for RenderWidgetHostViewAura::OnTouchEvent().
+// https://crbug.com/491334
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ SubframeTouchEventRouting) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "/frame_tree/page_with_positioned_nested_frames.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ FrameTreeNode* root = web_contents->GetFrameTree()->root();
+ ASSERT_EQ(1U, root->child_count());
+
+ GURL frame_url(
+ embedded_test_server()->GetURL("b.com", "/page_with_touch_handler.html"));
+ NavigateFrameToURL(root->child_at(0), frame_url);
+
+ // Synchronize with the child and parent renderers to guarantee that the
+ // surface information required for event hit testing is ready.
+ RenderWidgetHostViewBase* child_rwhv = static_cast<RenderWidgetHostViewBase*>(
+ root->child_at(0)->current_frame_host()->GetView());
+ SurfaceHitTestReadyNotifier notifier(
+ static_cast<RenderWidgetHostViewChildFrame*>(child_rwhv));
+ notifier.WaitForSurfaceReady();
+
+ // Simulate touch event to sub-frame.
+ gfx::Point child_center(150, 150);
+ auto rwhv = static_cast<RenderWidgetHostViewAura*>(
+ web_contents->GetRenderWidgetHostView());
+ ui::TouchEvent touch_event(ui::ET_TOUCH_PRESSED, child_center, 0, 0,
+ ui::EventTimeForNow(), 30.f, 30.f, 0.f, 0.f);
+ rwhv->OnTouchEvent(&touch_event);
+
+ // Verify touch handler in subframe was invoked
+ std::string result;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ root->child_at(0)->current_frame_host(),
+ "window.domAutomationController.send(getLastTouchEvent());", &result));
+ EXPECT_EQ("touchstart", result);
+}
+
+namespace {
+
+// Declared here to be close to the SubframeGestureEventRouting test.
+void OnSyntheticGestureCompleted(scoped_refptr<MessageLoopRunner> runner,
+ SyntheticGesture::Result result) {
+ EXPECT_EQ(SyntheticGesture::GESTURE_FINISHED, result);
+ runner->Quit();
+}
+
+} // namespace anonymous
+
+// Flaky under TSan. https://crbug.com/592320
+#if defined(THREAD_SANITIZER)
+#define MAYBE_SubframeGestureEventRouting DISABLED_SubframeGestureEventRouting
+#else
+#define MAYBE_SubframeGestureEventRouting SubframeGestureEventRouting
+#endif
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ MAYBE_SubframeGestureEventRouting) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "/frame_tree/page_with_positioned_nested_frames.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ FrameTreeNode* root = web_contents->GetFrameTree()->root();
+ ASSERT_EQ(1U, root->child_count());
+
+ GURL frame_url(
+ embedded_test_server()->GetURL("b.com", "/page_with_click_handler.html"));
+ NavigateFrameToURL(root->child_at(0), frame_url);
+ auto child_frame_host = root->child_at(0)->current_frame_host();
+
+ // Synchronize with the child and parent renderers to guarantee that the
+ // surface information required for event hit testing is ready.
+ RenderWidgetHostViewBase* child_rwhv = static_cast<RenderWidgetHostViewBase*>(
+ child_frame_host->GetView());
+ SurfaceHitTestReadyNotifier notifier(
+ static_cast<RenderWidgetHostViewChildFrame*>(child_rwhv));
+ notifier.WaitForSurfaceReady();
+
+ // There have been no GestureTaps sent yet.
+ {
+ std::string result;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ child_frame_host,
+ "window.domAutomationController.send(getClickStatus());", &result));
+ EXPECT_EQ("0 clicks received", result);
+ }
+
+ // Simulate touch sequence to send GestureTap to sub-frame.
+ SyntheticTapGestureParams params;
+ params.gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ gfx::Point center(150, 150);
+ params.position = gfx::PointF(center.x(), center.y());
+ params.duration_ms = 100;
+ scoped_ptr<SyntheticTapGesture> gesture(new SyntheticTapGesture(params));
+
+ scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner();
+
+ RenderWidgetHostImpl* render_widget_host =
+ root->current_frame_host()->GetRenderWidgetHost();
+ // TODO(wjmaclean): Convert the call to base::Bind() to a lambda someday.
+ render_widget_host->QueueSyntheticGesture(
+ std::move(gesture), base::Bind(OnSyntheticGestureCompleted, runner));
+
+ // We need to run the message loop while we wait for the synthetic gesture
+ // to be processed; the callback registered above will get us out of the
+ // message loop when that happens.
+ runner->Run();
+ runner = nullptr;
+
+ // Verify click handler in subframe was invoked
+ {
+ std::string result;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ child_frame_host,
+ "window.domAutomationController.send(getClickStatus());", &result));
+ EXPECT_EQ("1 click received", result);
+ }
+}
+
+namespace {
+
+// Defined here to be close to
+// SitePerProcessBrowserTest.InputEventRouterGestureTargetQueueTest.
+void SendTouchTapWithExpectedTarget(
+ RenderWidgetHostViewBase* root_view,
+ const gfx::Point& touch_point,
+ RenderWidgetHostViewBase*& router_touch_target,
+ const RenderWidgetHostViewBase* expected_target) {
+ auto root_view_aura = static_cast<RenderWidgetHostViewAura*>(root_view);
+ ui::TouchEvent touch_event_pressed(ui::ET_TOUCH_PRESSED, touch_point, 0,
+ 0, ui::EventTimeForNow(), 30.f, 30.f, 0.f,
+ 0.f);
+ root_view_aura->OnTouchEvent(&touch_event_pressed);
+ EXPECT_EQ(expected_target, router_touch_target);
+ ui::TouchEvent touch_event_released(ui::ET_TOUCH_RELEASED, touch_point,
+ 0, 0, ui::EventTimeForNow(), 30.f, 30.f,
+ 0.f, 0.f);
+ root_view_aura->OnTouchEvent(&touch_event_released);
+ EXPECT_EQ(nullptr, router_touch_target);
+}
+
+void SendGestureTapSequenceWithExpectedTarget(
+ RenderWidgetHostViewBase* root_view,
+ gfx::Point gesture_point,
+ RenderWidgetHostViewBase*& router_gesture_target,
+ const RenderWidgetHostViewBase* old_expected_target,
+ const RenderWidgetHostViewBase* expected_target) {
+ auto root_view_aura = static_cast<RenderWidgetHostViewAura*>(root_view);
+
+ ui::GestureEvent gesture_begin_event(
+ gesture_point.x(), gesture_point.y(), 0, ui::EventTimeForNow(),
+ ui::GestureEventDetails(ui::ET_GESTURE_BEGIN));
+ root_view_aura->OnGestureEvent(&gesture_begin_event);
+ // We expect to still have the old gesture target in place for the
+ // GestureFlingCancel that will be inserted before GestureTapDown.
+ // Note: the GestureFlingCancel is inserted by RenderWidgetHostViewAura::
+ // OnGestureEvent() when it sees ui::ET_GESTURE_TAP_DOWN, so we don't
+ // explicitly add it here.
+ EXPECT_EQ(old_expected_target, router_gesture_target);
+
+ ui::GestureEvent gesture_tap_down_event(
+ gesture_point.x(), gesture_point.y(), 0, ui::EventTimeForNow(),
+ ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN));
+ root_view_aura->OnGestureEvent(&gesture_tap_down_event);
+ EXPECT_EQ(expected_target, router_gesture_target);
+
+ ui::GestureEvent gesture_show_press_event(
+ gesture_point.x(), gesture_point.y(), 0, ui::EventTimeForNow(),
+ ui::GestureEventDetails(ui::ET_GESTURE_SHOW_PRESS));
+ root_view_aura->OnGestureEvent(&gesture_show_press_event);
+ EXPECT_EQ(expected_target, router_gesture_target);
+
+ ui::GestureEventDetails gesture_tap_details(ui::ET_GESTURE_TAP);
+ gesture_tap_details.set_tap_count(1);
+ ui::GestureEvent gesture_tap_event(
+ gesture_point.x(), gesture_point.y(), 0, ui::EventTimeForNow(),
+ gesture_tap_details);
+ root_view_aura->OnGestureEvent(&gesture_tap_event);
+ EXPECT_EQ(expected_target, router_gesture_target);
+
+ ui::GestureEvent gesture_end_event(
+ gesture_point.x(), gesture_point.y(), 0, ui::EventTimeForNow(),
+ ui::GestureEventDetails(ui::ET_GESTURE_END));
+ root_view_aura->OnGestureEvent(&gesture_end_event);
+ EXPECT_EQ(expected_target, router_gesture_target);
+}
+
+} // namespace anonymous
+
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ InputEventRouterGestureTargetQueueTest) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "/frame_tree/page_with_positioned_nested_frames.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ WebContentsImpl* web_contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ FrameTreeNode* root = web_contents->GetFrameTree()->root();
+ ASSERT_EQ(1U, root->child_count());
+
+ GURL frame_url(
+ embedded_test_server()->GetURL("b.com", "/page_with_click_handler.html"));
+ NavigateFrameToURL(root->child_at(0), frame_url);
+ auto child_frame_host = root->child_at(0)->current_frame_host();
+
+ // Synchronize with the child and parent renderers to guarantee that the
+ // surface information required for event hit testing is ready.
+ auto rwhv_child =
+ static_cast<RenderWidgetHostViewBase*>(child_frame_host->GetView());
+ SurfaceHitTestReadyNotifier notifier(
+ static_cast<RenderWidgetHostViewChildFrame*>(rwhv_child));
+ notifier.WaitForSurfaceReady();
+
+ // All touches & gestures are sent to the main frame's view, and should be
+ // routed appropriately from there.
+ auto rwhv_parent = static_cast<RenderWidgetHostViewBase*>(
+ web_contents->GetRenderWidgetHostView());
+
+ RenderWidgetHostInputEventRouter* router =
+ web_contents->GetInputEventRouter();
+ EXPECT_TRUE(router->gesture_target_queue_.empty());
+ EXPECT_EQ(nullptr, router->gesture_target_);
+
+ // Send touch sequence to main-frame.
+ gfx::Point main_frame_point(25, 25);
+ SendTouchTapWithExpectedTarget(rwhv_parent, main_frame_point,
+ router->touch_target_, rwhv_parent);
+ EXPECT_EQ(1LU, router->gesture_target_queue_.size());
+ EXPECT_EQ(nullptr, router->gesture_target_);
+
+
+ // Send touch sequence to child.
+ gfx::Point child_center(150, 150);
+ SendTouchTapWithExpectedTarget(rwhv_parent, child_center,
+ router->touch_target_, rwhv_child);
+ EXPECT_EQ(2LU, router->gesture_target_queue_.size());
+ EXPECT_EQ(nullptr, router->gesture_target_);
+
+ // Send another touch sequence to main frame.
+ SendTouchTapWithExpectedTarget(rwhv_parent, main_frame_point,
+ router->touch_target_, rwhv_parent);
+ EXPECT_EQ(3LU, router->gesture_target_queue_.size());
+ EXPECT_EQ(nullptr, router->gesture_target_);
+
+ // Send Gestures to clear GestureTargetQueue.
+
+ // The first touch sequence should generate a GestureTapDown, sent to the
+ // main frame.
+ SendGestureTapSequenceWithExpectedTarget(rwhv_parent, main_frame_point,
+ router->gesture_target_, nullptr,
+ rwhv_parent);
+ EXPECT_EQ(2LU, router->gesture_target_queue_.size());
+ // Note: rwhv_parent is the target used for GestureFlingCancel sent by
+ // RenderWidgetHostViewAura::OnGestureEvent() at the start of the next gesture
+ // sequence; the sequence itself goes to rwhv_child.
+ EXPECT_EQ(rwhv_parent, router->gesture_target_);
+
+ // The second touch sequence should generate a GestureTapDown, sent to the
+ // child frame.
+ SendGestureTapSequenceWithExpectedTarget(rwhv_parent, child_center,
+ router->gesture_target_, rwhv_parent,
+ rwhv_child);
+ EXPECT_EQ(1LU, router->gesture_target_queue_.size());
+ EXPECT_EQ(rwhv_child, router->gesture_target_);
+
+ // The third touch sequence should generate a GestureTapDown, sent to the
+ // main frame.
+ SendGestureTapSequenceWithExpectedTarget(rwhv_parent, main_frame_point,
+ router->gesture_target_, rwhv_child,
+ rwhv_parent);
+ EXPECT_EQ(0LU, router->gesture_target_queue_.size());
+ EXPECT_EQ(rwhv_parent, router->gesture_target_);
+}
+#endif // defined(USE_AURA)
+
// Ensure that a cross-process subframe can receive keyboard events when in
-// focus.
+// focus. Flaky: https://crbug.com/596508.
IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
- SubframeKeyboardEventRouting) {
+ DISABLED_SubframeKeyboardEventRouting) {
GURL main_url(embedded_test_server()->GetURL(
"a.com", "/frame_tree/page_with_one_frame.html"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -4211,7 +4904,6 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
GURL frame_url(
embedded_test_server()->GetURL("b.com", "/page_with_input_field.html"));
NavigateFrameToURL(root->child_at(0), frame_url);
- EXPECT_TRUE(WaitForRenderFrameReady(root->child_at(0)->current_frame_host()));
// Focus the subframe and then its input field. The return value
// "input-focus" will be sent once the input field's focus event fires.
@@ -4248,7 +4940,10 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
//
// The test then presses <tab> six times to cycle through focused elements 1-6.
// The test then repeats this with <shift-tab> to cycle in reverse order.
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, SequentialFocusNavigation) {
+
+// Freqently times out. https://crbug.com/599730.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ DISABLED_SequentialFocusNavigation) {
GURL main_url(embedded_test_server()->GetURL(
"a.com", "/cross_site_iframe_factory.html?a(b,c)"));
EXPECT_TRUE(NavigateToURL(shell(), main_url));
@@ -4355,33 +5050,25 @@ class ContextMenuObserverDelegate : public WebContentsDelegate {
DISALLOW_COPY_AND_ASSIGN(ContextMenuObserverDelegate);
};
-// Test that a mouse right-click to an out-of-process iframe causes a context
-// menu to be generated with the correct screen position.
-#if defined(OS_ANDROID)
-// Browser process hit testing is not implemented on Android.
-// https://crbug.com/491334
-#define MAYBE_CreateContextMenuTest DISABLED_CreateContextMenuTest
-#else
-#define MAYBE_CreateContextMenuTest CreateContextMenuTest
-#endif
-IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_CreateContextMenuTest) {
- if (!UseSurfacesEnabled())
- return;
-
- GURL main_url(embedded_test_server()->GetURL(
+// Helper function to run the CreateContextMenuTest in either normal
+// or high DPI mode.
+void CreateContextMenuTestHelper(
+ Shell* shell,
+ net::test_server::EmbeddedTestServer* embedded_test_server) {
+ GURL main_url(embedded_test_server->GetURL(
"/frame_tree/page_with_positioned_frame.html"));
- NavigateToURL(shell(), main_url);
+ EXPECT_TRUE(NavigateToURL(shell, main_url));
// It is safe to obtain the root frame tree node here, as it doesn't change.
- FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell->web_contents())
->GetFrameTree()
->root();
ASSERT_EQ(1U, root->child_count());
FrameTreeNode* child_node = root->child_at(0);
- GURL site_url(embedded_test_server()->GetURL("baz.com", "/title1.html"));
+ GURL site_url(embedded_test_server->GetURL("baz.com", "/title1.html"));
EXPECT_EQ(site_url, child_node->current_url());
- EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
+ EXPECT_NE(shell->web_contents()->GetSiteInstance(),
child_node->current_frame_host()->GetSiteInstance());
RenderWidgetHostViewBase* root_view = static_cast<RenderWidgetHostViewBase*>(
@@ -4392,37 +5079,33 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_CreateContextMenuTest) {
// Ensure that the child process renderer is ready to have input events
// routed to it. This happens when the browser process has received
// updated compositor surfaces from both renderer processes.
- gfx::Point point(75, 75);
- gfx::Point transformed_point;
- while (root_view->SurfaceIdNamespaceAtPoint(point, &transformed_point) !=
- rwhv_child->GetSurfaceIdNamespace()) {
- base::RunLoop run_loop;
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
- run_loop.Run();
- }
+ SurfaceHitTestReadyNotifier notifier(
+ static_cast<RenderWidgetHostViewChildFrame*>(rwhv_child));
+ notifier.WaitForSurfaceReady();
// A WebContentsDelegate to listen for the ShowContextMenu message.
ContextMenuObserverDelegate context_menu_delegate;
- shell()->web_contents()->SetDelegate(&context_menu_delegate);
+ shell->web_contents()->SetDelegate(&context_menu_delegate);
RenderWidgetHostInputEventRouter* router =
- static_cast<WebContentsImpl*>(shell()->web_contents())
+ static_cast<WebContentsImpl*>(shell->web_contents())
->GetInputEventRouter();
+ gfx::Point point(75, 75);
+
// Target right-click event to child frame.
blink::WebMouseEvent click_event;
click_event.type = blink::WebInputEvent::MouseDown;
click_event.button = blink::WebPointerProperties::ButtonRight;
- click_event.x = 75;
- click_event.y = 75;
+ click_event.x = point.x();
+ click_event.y = point.y();
click_event.clickCount = 1;
router->RouteMouseEvent(root_view, &click_event);
// We also need a MouseUp event, needed by Windows.
click_event.type = blink::WebInputEvent::MouseUp;
- click_event.x = 75;
- click_event.y = 75;
+ click_event.x = point.x();
+ click_event.y = point.y();
router->RouteMouseEvent(root_view, &click_event);
context_menu_delegate.Wait();
@@ -4433,6 +5116,293 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_CreateContextMenuTest) {
EXPECT_EQ(point.y(), params.y);
}
+// Test that a mouse right-click to an out-of-process iframe causes a context
+// menu to be generated with the correct screen position.
+#if defined(OS_ANDROID)
+// Browser process hit testing is not implemented on Android.
+// https://crbug.com/491334
+#define MAYBE_CreateContextMenuTest DISABLED_CreateContextMenuTest
+#else
+#define MAYBE_CreateContextMenuTest CreateContextMenuTest
+#endif
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_CreateContextMenuTest) {
+ CreateContextMenuTestHelper(shell(), embedded_test_server());
+}
+
+// Test that a mouse right-click to an out-of-process iframe causes a context
+// menu to be generated with the correct screen position on a screen with
+// non-default scale factor.
+#if defined(OS_ANDROID) || defined(OS_WIN)
+// Browser process hit testing is not implemented on Android.
+// https://crbug.com/491334
+// Windows is disabled because of https://crbug.com/545547.
+#define MAYBE_HighDPICreateContextMenuTest DISABLED_HighDPICreateContextMenuTest
+#else
+#define MAYBE_HighDPICreateContextMenuTest HighDPICreateContextMenuTest
+#endif
+IN_PROC_BROWSER_TEST_F(SitePerProcessHighDPIBrowserTest,
+ MAYBE_HighDPICreateContextMenuTest) {
+ CreateContextMenuTestHelper(shell(), embedded_test_server());
+}
+
+class ShowWidgetMessageFilter : public content::BrowserMessageFilter {
+ public:
+ ShowWidgetMessageFilter()
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
+ : content::BrowserMessageFilter(FrameMsgStart),
+#else
+ : content::BrowserMessageFilter(ViewMsgStart),
+#endif
+ message_loop_runner_(new content::MessageLoopRunner) {
+ }
+
+ bool OnMessageReceived(const IPC::Message& message) override {
+ IPC_BEGIN_MESSAGE_MAP(ShowWidgetMessageFilter, message)
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_ShowPopup, OnShowPopup)
+#else
+ IPC_MESSAGE_HANDLER(ViewHostMsg_ShowWidget, OnShowWidget)
+#endif
+ IPC_END_MESSAGE_MAP()
+ return false;
+ }
+
+ gfx::Rect last_initial_rect() const { return initial_rect_; }
+
+ void Wait() {
+ initial_rect_ = gfx::Rect();
+ message_loop_runner_->Run();
+ }
+
+ void Reset() {
+ initial_rect_ = gfx::Rect();
+ message_loop_runner_ = new content::MessageLoopRunner;
+ }
+
+ private:
+ ~ShowWidgetMessageFilter() override {}
+
+ void OnShowWidget(int route_id, const gfx::Rect& initial_rect) {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI, FROM_HERE,
+ base::Bind(&ShowWidgetMessageFilter::OnShowWidgetOnUI, this, route_id,
+ initial_rect));
+ }
+
+#if defined(OS_MACOSX) || defined(OS_ANDROID)
+ void OnShowPopup(const FrameHostMsg_ShowPopup_Params& params) {
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI, FROM_HERE,
+ base::Bind(&ShowWidgetMessageFilter::OnShowWidgetOnUI, this,
+ MSG_ROUTING_NONE, params.bounds));
+ }
+#endif
+
+ void OnShowWidgetOnUI(int route_id, const gfx::Rect& initial_rect) {
+ initial_rect_ = initial_rect;
+ message_loop_runner_->Quit();
+ }
+
+ scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
+ gfx::Rect initial_rect_;
+
+ DISALLOW_COPY_AND_ASSIGN(ShowWidgetMessageFilter);
+};
+
+// Test that clicking a select element in an out-of-process iframe creates
+// a popup menu in the correct position.
+#if defined(OS_ANDROID)
+// Surface-based hit testing and coordinate translation is not yet available
+// on Android.
+#define MAYBE_PopupMenuTest DISABLED_PopupMenuTest
+#else
+#define MAYBE_PopupMenuTest PopupMenuTest
+#endif
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_PopupMenuTest) {
+ GURL main_url(
+ embedded_test_server()->GetURL("/cross_site_iframe_factory.html?a(a)"));
+ NavigateToURL(shell(), main_url);
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+#if !defined(OS_MACOSX)
+ // Unused variable on Mac.
+ RenderWidgetHostViewBase* rwhv_root = static_cast<RenderWidgetHostViewBase*>(
+ root->current_frame_host()->GetRenderWidgetHost()->GetView());
+#endif
+ static_cast<WebContentsImpl*>(shell()->web_contents())->SendScreenRects();
+
+ content::TestNavigationObserver navigation_observer(shell()->web_contents());
+ FrameTreeNode* child_node = root->child_at(0);
+ GURL site_url(embedded_test_server()->GetURL(
+ "baz.com", "/site_isolation/page-with-select.html"));
+ NavigateFrameToURL(child_node, site_url);
+ navigation_observer.Wait();
+
+ RenderWidgetHostViewBase* rwhv_child = static_cast<RenderWidgetHostViewBase*>(
+ child_node->current_frame_host()->GetRenderWidgetHost()->GetView());
+
+ EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
+ child_node->current_frame_host()->GetSiteInstance());
+
+ scoped_refptr<ShowWidgetMessageFilter> filter = new ShowWidgetMessageFilter();
+ child_node->current_frame_host()->GetProcess()->AddFilter(filter.get());
+
+ // Target left-click event to child frame.
+ blink::WebMouseEvent click_event;
+ click_event.type = blink::WebInputEvent::MouseDown;
+ click_event.button = blink::WebPointerProperties::ButtonLeft;
+ click_event.x = 15;
+ click_event.y = 15;
+ click_event.clickCount = 1;
+ rwhv_child->ProcessMouseEvent(click_event);
+
+ // Dismiss the popup.
+ click_event.x = 1;
+ click_event.y = 1;
+ rwhv_child->ProcessMouseEvent(click_event);
+
+ filter->Wait();
+ gfx::Rect popup_rect = filter->last_initial_rect();
+#if defined(OS_MACOSX)
+ // On Mac we receive the coordinates before they are transformed, so they
+ // are still relative to the out-of-process iframe origin.
+ EXPECT_EQ(popup_rect.x(), 9);
+ EXPECT_EQ(popup_rect.y(), 9);
+#else
+ EXPECT_EQ(popup_rect.x() - rwhv_root->GetViewBounds().x(), 354);
+ EXPECT_EQ(popup_rect.y() - rwhv_root->GetViewBounds().y(), 94);
+#endif
+}
+
+// Test that clicking a select element in a nested out-of-process iframe creates
+// a popup menu in the correct position, even if the top-level page repositions
+// its out-of-process iframe. This verifies that screen positioning information
+// is propagating down the frame tree correctly.
+#if defined(OS_ANDROID)
+// Surface-based hit testing and coordinate translation is not yet avaiable on
+// Android.
+#define MAYBE_NestedPopupMenuTest DISABLED_NestedPopupMenuTest
+#else
+// Times out frequently. https://crbug.com/599730.
+#define MAYBE_NestedPopupMenuTest DISABLED_NestedPopupMenuTest
+#endif
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, MAYBE_NestedPopupMenuTest) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "/cross_site_iframe_factory.html?a(b(c))"));
+ NavigateToURL(shell(), main_url);
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+#if !defined(OS_MACOSX)
+ // Undefined variable on Mac.
+ RenderWidgetHostViewBase* rwhv_root = static_cast<RenderWidgetHostViewBase*>(
+ root->current_frame_host()->GetRenderWidgetHost()->GetView());
+#endif
+ static_cast<WebContentsImpl*>(shell()->web_contents())->SendScreenRects();
+
+ // For clarity, we are labeling the frame tree nodes as:
+ // - root_node
+ // \-> b_node (out-of-process from root and c_node)
+ // \-> c_node (out-of-process from root and b_node)
+
+ content::TestNavigationObserver navigation_observer(shell()->web_contents());
+ FrameTreeNode* b_node = root->child_at(0);
+ FrameTreeNode* c_node = b_node->child_at(0);
+ GURL site_url(embedded_test_server()->GetURL(
+ "baz.com", "/site_isolation/page-with-select.html"));
+ NavigateFrameToURL(c_node, site_url);
+
+ RenderWidgetHostViewBase* rwhv_c_node =
+ static_cast<RenderWidgetHostViewBase*>(
+ c_node->current_frame_host()->GetRenderWidgetHost()->GetView());
+
+ EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
+ c_node->current_frame_host()->GetSiteInstance());
+
+ scoped_refptr<ShowWidgetMessageFilter> filter = new ShowWidgetMessageFilter();
+ c_node->current_frame_host()->GetProcess()->AddFilter(filter.get());
+
+ // Target left-click event to child frame.
+ blink::WebMouseEvent click_event;
+ click_event.type = blink::WebInputEvent::MouseDown;
+ click_event.button = blink::WebPointerProperties::ButtonLeft;
+ click_event.x = 15;
+ click_event.y = 15;
+ click_event.clickCount = 1;
+ rwhv_c_node->ProcessMouseEvent(click_event);
+
+ // Prompt the WebContents to dismiss the popup by clicking elsewhere.
+ click_event.x = 1;
+ click_event.y = 1;
+ rwhv_c_node->ProcessMouseEvent(click_event);
+
+ filter->Wait();
+
+ gfx::Rect popup_rect = filter->last_initial_rect();
+
+#if defined(OS_MACOSX)
+ EXPECT_EQ(popup_rect.x(), 9);
+ EXPECT_EQ(popup_rect.y(), 9);
+#else
+ EXPECT_EQ(popup_rect.x() - rwhv_root->GetViewBounds().x(), 354);
+ EXPECT_EQ(popup_rect.y() - rwhv_root->GetViewBounds().y(), 154);
+#endif
+
+ // Save the screen rect for b_node. Since it updates asynchronously from
+ // the script command that changes it, we need to wait for it to change
+ // before attempting to create the popup widget again.
+ gfx::Rect last_b_node_bounds_rect =
+ b_node->current_frame_host()->GetView()->GetViewBounds();
+
+ std::string script =
+ "var iframe = document.querySelector('iframe');"
+ "iframe.style.position = 'absolute';"
+ "iframe.style.left = 150;"
+ "iframe.style.top = 150;";
+ EXPECT_TRUE(ExecuteScript(root->current_frame_host(), script));
+
+ filter->Reset();
+
+ // Busy loop to wait for b_node's screen rect to get updated. There
+ // doesn't seem to be any better way to find out when this happens.
+ while (last_b_node_bounds_rect.x() ==
+ b_node->current_frame_host()->GetView()->GetViewBounds().x() &&
+ last_b_node_bounds_rect.y() ==
+ b_node->current_frame_host()->GetView()->GetViewBounds().y()) {
+ base::RunLoop run_loop;
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, run_loop.QuitClosure(), TestTimeouts::tiny_timeout());
+ run_loop.Run();
+ }
+
+ click_event.button = blink::WebPointerProperties::ButtonLeft;
+ click_event.x = 15;
+ click_event.y = 15;
+ click_event.clickCount = 1;
+ rwhv_c_node->ProcessMouseEvent(click_event);
+
+ click_event.x = 1;
+ click_event.y = 1;
+ rwhv_c_node->ProcessMouseEvent(click_event);
+
+ filter->Wait();
+
+ popup_rect = filter->last_initial_rect();
+
+#if defined(OS_MACOSX)
+ EXPECT_EQ(popup_rect.x(), 9);
+ EXPECT_EQ(popup_rect.y(), 9);
+#else
+ EXPECT_EQ(popup_rect.x() - rwhv_root->GetViewBounds().x(), 203);
+ EXPECT_EQ(popup_rect.y() - rwhv_root->GetViewBounds().y(), 248);
+#endif
+}
+
// Test for https://crbug.com/526304, where a parent frame executes a
// remote-to-local navigation on a child frame and immediately removes the same
// child frame. This test exercises the path where the detach happens before
@@ -4511,6 +5481,37 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
EXPECT_EQ(1, child_count);
}
+// Similar to NavigateProxyAndDetachBeforeCommit, but uses a synchronous
+// navigation to about:blank and the parent removes the child frame in a load
+// event handler for the subframe.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NavigateAboutBlankAndDetach) {
+ GURL main_url(
+ embedded_test_server()->GetURL("a.com", "/remove_frame_on_load.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ WebContents* contents = shell()->web_contents();
+ FrameTreeNode* root =
+ static_cast<WebContentsImpl*>(contents)->GetFrameTree()->root();
+ EXPECT_EQ(1U, root->child_count());
+ FrameTreeNode* child = root->child_at(0);
+ EXPECT_NE(shell()->web_contents()->GetSiteInstance(),
+ child->current_frame_host()->GetSiteInstance());
+
+ // Navigate the child frame to "about:blank" from the parent document.
+ TestNavigationObserver observer(shell()->web_contents());
+ EXPECT_TRUE(
+ ExecuteScript(root->current_frame_host(),
+ base::StringPrintf("f.src = '%s'", url::kAboutBlankURL)));
+ observer.Wait();
+
+ // Make sure the a.com renderer does not crash and the frame is removed.
+ int child_count = 0;
+ EXPECT_TRUE(ExecuteScriptAndExtractInt(
+ root->current_frame_host(), "domAutomationController.send(frames.length)",
+ &child_count));
+ EXPECT_EQ(0, child_count);
+}
+
// Test for https://crbug.com/568670. In A-embed-B, simultaneously have B
// create a new (local) child frame, and have A detach B's proxy. The child
// frame creation sends an IPC to create a new proxy in A's process, and if
@@ -4602,11 +5603,15 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
// observer to ensure there is no crash when a new RenderFrame creation is
// attempted.
RenderProcessHost* process =
- node->render_manager()->pending_frame_host()->GetProcess();
+ IsBrowserSideNavigationEnabled()
+ ? node->render_manager()->speculative_frame_host()->GetProcess()
+ : node->render_manager()->pending_frame_host()->GetProcess();
RenderProcessHostWatcher watcher(
process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
int frame_routing_id =
- node->render_manager()->pending_frame_host()->GetRoutingID();
+ IsBrowserSideNavigationEnabled()
+ ? node->render_manager()->speculative_frame_host()->GetRoutingID()
+ : node->render_manager()->pending_frame_host()->GetRoutingID();
int proxy_routing_id =
node->render_manager()->GetProxyToParent()->GetRoutingID();
@@ -4625,6 +5630,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
params.previous_sibling_routing_id = MSG_ROUTING_NONE;
params.widget_params.routing_id = MSG_ROUTING_NONE;
params.widget_params.hidden = true;
+ params.replication_state.name = "name";
+ params.replication_state.unique_name = "name";
process->Send(new FrameMsg_NewFrame(params));
}
@@ -4689,6 +5696,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ParentDetachRemoteChild) {
params.previous_sibling_routing_id = MSG_ROUTING_NONE;
params.widget_params.routing_id = widget_routing_id;
params.widget_params.hidden = true;
+ params.replication_state.name = "name";
+ params.replication_state.unique_name = "name";
process->Send(new FrameMsg_NewFrame(params));
}
@@ -4745,4 +5754,572 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, VisibilityChanged) {
EXPECT_TRUE(show_observer.WaitUntilSatisfied());
}
+// Verify that sandbox flags inheritance works across multiple levels of
+// frames. See https://crbug.com/576845.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, SandboxFlagsInheritance) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(a)"));
+ NavigateToURL(shell(), main_url);
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // Set sandbox flags for child frame.
+ EXPECT_TRUE(ExecuteScript(
+ root->current_frame_host(),
+ "document.querySelector('iframe').sandbox = 'allow-scripts';"));
+
+ // Calculate expected flags. Note that "allow-scripts" resets both
+ // WebSandboxFlags::Scripts and WebSandboxFlags::AutomaticFeatures bits per
+ // blink::parseSandboxPolicy().
+ blink::WebSandboxFlags expected_flags =
+ blink::WebSandboxFlags::All & ~blink::WebSandboxFlags::Scripts &
+ ~blink::WebSandboxFlags::AutomaticFeatures;
+ EXPECT_EQ(expected_flags, root->child_at(0)->pending_sandbox_flags());
+ EXPECT_EQ(blink::WebSandboxFlags::None,
+ root->child_at(0)->effective_sandbox_flags());
+
+ // Navigate child frame so that the sandbox flags take effect. Use a page
+ // with three levels of frames and make sure all frames properly inherit
+ // sandbox flags.
+ GURL frame_url(embedded_test_server()->GetURL(
+ "b.com", "/cross_site_iframe_factory.html?b(c(d))"));
+ NavigateFrameToURL(root->child_at(0), frame_url);
+
+ // Wait for subframes to load as well.
+ ASSERT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ // Check each new frame's sandbox flags on the browser process side.
+ FrameTreeNode* b_child = root->child_at(0);
+ FrameTreeNode* c_child = b_child->child_at(0);
+ FrameTreeNode* d_child = c_child->child_at(0);
+ EXPECT_EQ(expected_flags, b_child->effective_sandbox_flags());
+ EXPECT_EQ(expected_flags, c_child->effective_sandbox_flags());
+ EXPECT_EQ(expected_flags, d_child->effective_sandbox_flags());
+
+ // Check whether each frame is sandboxed on the renderer side, by seeing if
+ // each frame's origin is unique ("null").
+ EXPECT_EQ("null", GetDocumentOrigin(b_child));
+ EXPECT_EQ("null", GetDocumentOrigin(c_child));
+ EXPECT_EQ("null", GetDocumentOrigin(d_child));
+}
+
+// Check that sandbox flags are not inherited before they take effect. Create
+// a child frame, update its sandbox flags but don't navigate the frame, and
+// ensure that a new cross-site grandchild frame doesn't inherit the new flags
+// (which shouldn't have taken effect).
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ SandboxFlagsNotInheritedBeforeNavigation) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(a)"));
+ NavigateToURL(shell(), main_url);
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // Set sandbox flags for child frame.
+ EXPECT_TRUE(ExecuteScript(
+ root->current_frame_host(),
+ "document.querySelector('iframe').sandbox = 'allow-scripts';"));
+
+ // These flags should be pending but not take effect, since there's been no
+ // navigation.
+ blink::WebSandboxFlags expected_flags =
+ blink::WebSandboxFlags::All & ~blink::WebSandboxFlags::Scripts &
+ ~blink::WebSandboxFlags::AutomaticFeatures;
+ FrameTreeNode* child = root->child_at(0);
+ EXPECT_EQ(expected_flags, child->pending_sandbox_flags());
+ EXPECT_EQ(blink::WebSandboxFlags::None, child->effective_sandbox_flags());
+
+ // Add a new grandchild frame and navigate it cross-site.
+ RenderFrameHostCreatedObserver frame_observer(shell()->web_contents(), 1);
+ EXPECT_TRUE(ExecuteScript(
+ child->current_frame_host(),
+ "document.body.appendChild(document.createElement('iframe'));"));
+ frame_observer.Wait();
+
+ FrameTreeNode* grandchild = child->child_at(0);
+ GURL frame_url(embedded_test_server()->GetURL("b.com", "/title1.html"));
+ TestFrameNavigationObserver navigation_observer(grandchild);
+ NavigateFrameToURL(grandchild, frame_url);
+ navigation_observer.Wait();
+
+ // Since the update flags haven't yet taken effect in its parent, this
+ // grandchild frame should not be sandboxed.
+ EXPECT_EQ(blink::WebSandboxFlags::None, grandchild->pending_sandbox_flags());
+ EXPECT_EQ(blink::WebSandboxFlags::None,
+ grandchild->effective_sandbox_flags());
+
+ // Check that the grandchild frame isn't sandboxed on the renderer side. If
+ // sandboxed, its origin would be unique ("null").
+ EXPECT_EQ(frame_url.GetOrigin().spec(), GetDocumentOrigin(grandchild) + "/");
+}
+
+// Verify that popups opened from sandboxed frames inherit sandbox flags from
+// their opener, and that they keep these inherited flags after being navigated
+// cross-site. See https://crbug.com/483584.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ NewPopupInheritsSandboxFlagsFromOpener) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(a)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // Set sandbox flags for child frame.
+ EXPECT_TRUE(ExecuteScript(root->current_frame_host(),
+ "document.querySelector('iframe').sandbox = "
+ " 'allow-scripts allow-popups';"));
+
+ // Calculate expected flags. Note that "allow-scripts" resets both
+ // WebSandboxFlags::Scripts and WebSandboxFlags::AutomaticFeatures bits per
+ // blink::parseSandboxPolicy().
+ blink::WebSandboxFlags expected_flags =
+ blink::WebSandboxFlags::All & ~blink::WebSandboxFlags::Scripts &
+ ~blink::WebSandboxFlags::AutomaticFeatures &
+ ~blink::WebSandboxFlags::Popups;
+ EXPECT_EQ(expected_flags, root->child_at(0)->pending_sandbox_flags());
+
+ // Navigate child frame cross-site. The sandbox flags should take effect.
+ GURL frame_url(embedded_test_server()->GetURL("b.com", "/title1.html"));
+ TestFrameNavigationObserver frame_observer(root->child_at(0));
+ NavigateFrameToURL(root->child_at(0), frame_url);
+ frame_observer.Wait();
+ EXPECT_EQ(expected_flags, root->child_at(0)->effective_sandbox_flags());
+
+ // Verify that they've also taken effect on the renderer side. The sandboxed
+ // frame's origin should be unique.
+ EXPECT_EQ("null", GetDocumentOrigin(root->child_at(0)));
+
+ // Open a popup named "foo" from the sandboxed child frame.
+ Shell* foo_shell = OpenPopup(root->child_at(0)->current_frame_host(),
+ GURL(url::kAboutBlankURL), "foo");
+ EXPECT_TRUE(foo_shell);
+
+ FrameTreeNode* foo_root =
+ static_cast<WebContentsImpl*>(foo_shell->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // Check that the sandbox flags for new popup are correct in the browser
+ // process.
+ EXPECT_EQ(expected_flags, foo_root->effective_sandbox_flags());
+
+ // The popup's origin should be unique, since it's sandboxed.
+ EXPECT_EQ("null", GetDocumentOrigin(foo_root));
+
+ // Navigate the popup cross-site. This should keep the unique origin and the
+ // inherited sandbox flags.
+ GURL c_url(embedded_test_server()->GetURL("c.com", "/title1.html"));
+ TestFrameNavigationObserver popup_observer(foo_root);
+ EXPECT_TRUE(ExecuteScript(foo_root->current_frame_host(),
+ "location.href = '" + c_url.spec() + "';"));
+ popup_observer.Wait();
+ EXPECT_EQ(c_url, foo_shell->web_contents()->GetLastCommittedURL());
+
+ // Confirm that the popup is still sandboxed, both on browser and renderer
+ // sides.
+ EXPECT_EQ(expected_flags, foo_root->effective_sandbox_flags());
+ EXPECT_EQ("null", GetDocumentOrigin(foo_root));
+}
+
+// Verify that popups opened from frames sandboxed with the
+// "allow-popups-to-escape-sandbox" directive do *not* inherit sandbox flags
+// from their opener.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ OpenUnsandboxedPopupFromSandboxedFrame) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(a)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ // It is safe to obtain the root frame tree node here, as it doesn't change.
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // Set sandbox flags for child frame, specifying that popups opened from it
+ // should not be sandboxed.
+ EXPECT_TRUE(ExecuteScript(
+ root->current_frame_host(),
+ "document.querySelector('iframe').sandbox = "
+ " 'allow-scripts allow-popups allow-popups-to-escape-sandbox';"));
+
+ // Set expected flags for the child frame. Note that "allow-scripts" resets
+ // both WebSandboxFlags::Scripts and WebSandboxFlags::AutomaticFeatures bits
+ // per blink::parseSandboxPolicy().
+ blink::WebSandboxFlags expected_flags =
+ blink::WebSandboxFlags::All & ~blink::WebSandboxFlags::Scripts &
+ ~blink::WebSandboxFlags::AutomaticFeatures &
+ ~blink::WebSandboxFlags::Popups &
+ ~blink::WebSandboxFlags::PropagatesToAuxiliaryBrowsingContexts;
+ EXPECT_EQ(expected_flags, root->child_at(0)->pending_sandbox_flags());
+
+ // Navigate child frame cross-site. The sandbox flags should take effect.
+ GURL frame_url(embedded_test_server()->GetURL("b.com", "/title1.html"));
+ TestFrameNavigationObserver frame_observer(root->child_at(0));
+ NavigateFrameToURL(root->child_at(0), frame_url);
+ frame_observer.Wait();
+ EXPECT_EQ(expected_flags, root->child_at(0)->effective_sandbox_flags());
+
+ // Open a cross-site popup named "foo" from the child frame.
+ GURL b_url(embedded_test_server()->GetURL("c.com", "/title1.html"));
+ Shell* foo_shell =
+ OpenPopup(root->child_at(0)->current_frame_host(), b_url, "foo");
+ EXPECT_TRUE(foo_shell);
+
+ FrameTreeNode* foo_root =
+ static_cast<WebContentsImpl*>(foo_shell->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // Check that the sandbox flags for new popup are correct in the browser
+ // process. They should not have been inherited.
+ EXPECT_EQ(blink::WebSandboxFlags::None, foo_root->effective_sandbox_flags());
+
+ // The popup's origin should match |b_url|, since it's not sandboxed.
+ std::string popup_origin;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ foo_root->current_frame_host(),
+ "domAutomationController.send(document.origin)",
+ &popup_origin));
+ EXPECT_EQ(b_url.GetOrigin().spec(), popup_origin + "/");
+}
+
+// Tests that the WebContents is notified when passive mixed content is
+// displayed in an OOPIF. The test ignores cert errors so that an HTTPS
+// iframe can be loaded from a site other than localhost (the
+// EmbeddedTestServer serves a certificate that is valid for localhost).
+// This test crashes on Windows under Dr. Memory, see https://crbug.com/600942.
+#if defined(OS_WIN)
+#define MAYBE_PassiveMixedContentInIframe DISABLED_PassiveMixedContentInIframe
+#else
+#define MAYBE_PassiveMixedContentInIframe PassiveMixedContentInIframe
+#endif
+IN_PROC_BROWSER_TEST_F(SitePerProcessIgnoreCertErrorsBrowserTest,
+ MAYBE_PassiveMixedContentInIframe) {
+ net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
+ https_server.ServeFilesFromSourceDirectory("content/test/data");
+ ASSERT_TRUE(https_server.Start());
+ SetupCrossSiteRedirector(&https_server);
+
+ GURL iframe_url(
+ https_server.GetURL("/mixed-content/basic-passive-in-iframe.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), iframe_url));
+ EXPECT_TRUE(shell()->web_contents()->DisplayedInsecureContent());
+
+ // When the subframe navigates, the WebContents should still be marked
+ // as having displayed insecure content.
+ GURL navigate_url(https_server.GetURL("/title1.html"));
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ NavigateFrameToURL(root->child_at(0), navigate_url);
+ EXPECT_TRUE(shell()->web_contents()->DisplayedInsecureContent());
+
+ // When the main frame navigates, it should no longer be marked as
+ // displaying insecure content.
+ EXPECT_TRUE(
+ NavigateToURL(shell(), https_server.GetURL("b.com", "/title1.html")));
+ EXPECT_FALSE(shell()->web_contents()->DisplayedInsecureContent());
+}
+
+// Tests that, when a parent frame is set to strictly block mixed
+// content via Content Security Policy, child OOPIFs cannot display
+// mixed content.
+IN_PROC_BROWSER_TEST_F(SitePerProcessIgnoreCertErrorsBrowserTest,
+ PassiveMixedContentInIframeWithStrictBlocking) {
+ net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
+ https_server.ServeFilesFromSourceDirectory("content/test/data");
+ ASSERT_TRUE(https_server.Start());
+ SetupCrossSiteRedirector(&https_server);
+
+ GURL iframe_url_with_strict_blocking(https_server.GetURL(
+ "/mixed-content/basic-passive-in-iframe-with-strict-blocking.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), iframe_url_with_strict_blocking));
+ EXPECT_FALSE(shell()->web_contents()->DisplayedInsecureContent());
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ EXPECT_TRUE(root->current_replication_state()
+ .should_enforce_strict_mixed_content_checking);
+ EXPECT_TRUE(root->child_at(0)
+ ->current_replication_state()
+ .should_enforce_strict_mixed_content_checking);
+
+ // When the subframe navigates, it should still be marked as enforcing
+ // strict mixed content.
+ GURL navigate_url(https_server.GetURL("/title1.html"));
+ NavigateFrameToURL(root->child_at(0), navigate_url);
+ EXPECT_TRUE(root->current_replication_state()
+ .should_enforce_strict_mixed_content_checking);
+ EXPECT_TRUE(root->child_at(0)
+ ->current_replication_state()
+ .should_enforce_strict_mixed_content_checking);
+
+ // When the main frame navigates, it should no longer be marked as
+ // enforcing strict mixed content.
+ EXPECT_TRUE(
+ NavigateToURL(shell(), https_server.GetURL("b.com", "/title1.html")));
+ EXPECT_FALSE(root->current_replication_state()
+ .should_enforce_strict_mixed_content_checking);
+}
+
+// Tests that active mixed content is blocked in an OOPIF. The test
+// ignores cert errors so that an HTTPS iframe can be loaded from a site
+// other than localhost (the EmbeddedTestServer serves a certificate
+// that is valid for localhost).
+IN_PROC_BROWSER_TEST_F(SitePerProcessIgnoreCertErrorsBrowserTest,
+ ActiveMixedContentInIframe) {
+ net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
+ https_server.ServeFilesFromSourceDirectory("content/test/data");
+ ASSERT_TRUE(https_server.Start());
+ SetupCrossSiteRedirector(&https_server);
+
+ GURL iframe_url(
+ https_server.GetURL("/mixed-content/basic-active-in-iframe.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), iframe_url));
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ ASSERT_EQ(1U, root->child_count());
+ FrameTreeNode* mixed_child = root->child_at(0)->child_at(0);
+ ASSERT_TRUE(mixed_child);
+ // The child iframe attempted to create a mixed iframe; this should
+ // have been blocked, so the mixed iframe should not have committed a
+ // load.
+ EXPECT_FALSE(mixed_child->has_committed_real_load());
+}
+
+// Test setting a cross-origin iframe to display: none.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossSiteIframeDisplayNone) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ NavigateToURL(shell(), main_url);
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ RenderWidgetHost* root_render_widget_host =
+ root->current_frame_host()->GetRenderWidgetHost();
+
+ // Set the iframe to display: none.
+ EXPECT_TRUE(
+ ExecuteScript(shell()->web_contents(),
+ "document.querySelector('iframe').style.display = 'none'"));
+
+ // Waits until pending frames are done.
+ scoped_ptr<MainThreadFrameObserver> observer(
+ new MainThreadFrameObserver(root_render_widget_host));
+ observer->Wait();
+
+ // Force the renderer to generate a new frame.
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
+ "document.body.style.background = 'black'"));
+
+ // Waits for the next frame.
+ observer->Wait();
+}
+
+// Test that a cross-origin iframe can be blocked by X-Frame-Options and CSP
+// frame-ancestors.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ CrossSiteIframeBlockedByXFrameOptionsOrCSP) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(a)"));
+ NavigateToURL(shell(), main_url);
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // Add a load event handler for the iframe element.
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
+ "document.querySelector('iframe').onload = "
+ " function() { document.title = 'loaded'; };"));
+
+ GURL blocked_urls[] = {
+ embedded_test_server()->GetURL("b.com", "/frame-ancestors-none.html"),
+ embedded_test_server()->GetURL("b.com", "/x-frame-options-deny.html")
+ };
+
+ for (size_t i = 0; i < arraysize(blocked_urls); ++i) {
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(),
+ "document.title = 'not loaded';"));
+ base::string16 expected_title(base::UTF8ToUTF16("loaded"));
+ TitleWatcher title_watcher(shell()->web_contents(), expected_title);
+
+ // Navigate the subframe to a blocked URL.
+ TestNavigationObserver load_observer(shell()->web_contents());
+ EXPECT_TRUE(ExecuteScript(
+ shell()->web_contents(),
+ "frames[0].location.href = '" + blocked_urls[i].spec() + "';"));
+ load_observer.Wait();
+
+ // The blocked frame's origin should become unique.
+ EXPECT_EQ("null", root->child_at(0)->current_origin().Serialize());
+
+ // The blocked frame should still fire a load event in its parent's process.
+ EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle());
+
+ // Check that the current RenderFrameHost has stopped loading.
+ EXPECT_FALSE(root->child_at(0)->current_frame_host()->is_loading());
+
+ // The blocked navigation should behave like an empty 200 response. Make
+ // sure that the frame's document.title is empty: this double-checks both
+ // that the blocked URL's contents wasn't loaded, and that the old page
+ // isn't active anymore (both of these pages have non-empty titles).
+ std::string frame_title;
+ EXPECT_TRUE(ExecuteScriptAndExtractString(
+ root->child_at(0)->current_frame_host(),
+ "domAutomationController.send(document.title)", &frame_title));
+ EXPECT_EQ("", frame_title);
+
+ // Navigate the subframe to another cross-origin page and ensure that this
+ // navigation succeeds. Use a renderer-initiated navigation to test the
+ // transfer logic, which used to have some issues with this.
+ GURL c_url(embedded_test_server()->GetURL("c.com", "/title1.html"));
+ EXPECT_TRUE(NavigateIframeToURL(shell()->web_contents(), "child-0", c_url));
+ EXPECT_EQ(c_url, root->child_at(0)->current_url());
+
+ // When a page gets blocked due to XFO or CSP, it is sandboxed with the
+ // SandboxOrigin flag (i.e., its origin is set to be unique) to ensure that
+ // the blocked page is seen as cross-origin. However, those flags shouldn't
+ // affect future navigations for a frame. Verify this for the above
+ // navigation.
+ EXPECT_EQ(c_url.GetOrigin().spec(),
+ root->child_at(0)->current_origin().Serialize() + "/");
+ EXPECT_EQ(blink::WebSandboxFlags::None,
+ root->child_at(0)->effective_sandbox_flags());
+ }
+}
+
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, ScreenCoordinates) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ NavigateToURL(shell(), main_url);
+
+ FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ FrameTreeNode* child = root->child_at(0);
+
+ const char* properties[] = {"screenX", "screenY", "outerWidth",
+ "outerHeight"};
+
+ for (const char* property : properties) {
+ std::string script = "window.domAutomationController.send(window.";
+ script += property;
+ script += ");";
+ int root_value = 1;
+ int child_value = 2;
+ EXPECT_TRUE(ExecuteScriptAndExtractInt(root->current_frame_host(),
+ script.c_str(), &root_value));
+
+ EXPECT_TRUE(ExecuteScriptAndExtractInt(child->current_frame_host(),
+ script.c_str(), &child_value));
+
+ EXPECT_EQ(root_value, child_value);
+ }
+}
+
+// Tests that the certificate store is updated during a cross-site
+// redirect navigation. (See https://crbug.com/561754.) Ignores
+// certificate errors so that it can use the cross-site redirector to
+// redirect from HTTPS to HTTPS.
+IN_PROC_BROWSER_TEST_F(SitePerProcessIgnoreCertErrorsBrowserTest,
+ CrossSiteRedirectCertificateStore) {
+ net::EmbeddedTestServer https_server(net::EmbeddedTestServer::TYPE_HTTPS);
+ https_server.ServeFilesFromSourceDirectory("content/test/data");
+ ASSERT_TRUE(https_server.Start());
+ SetupCrossSiteRedirector(&https_server);
+
+ ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
+ ASSERT_TRUE(rdh);
+ MockCertStore mock_cert_store;
+ rdh->cert_store_for_testing_ = &mock_cert_store;
+
+ // First, navigate to an |https_server| URL to ensure that the site
+ // instance is assigned a site. This will force a renderer transfer to
+ // happen on the following navigation that redirects to a different
+ // site.
+ GURL url(https_server.GetURL("/title1.html"));
+ EXPECT_TRUE(NavigateToURL(shell(), url));
+ int original_process_id =
+ shell()->web_contents()->GetRenderProcessHost()->GetID();
+
+ url = https_server.GetURL("/cross-site/a.test/title1.html");
+ // NavigateToURL() returns false because the committed URL doesn't
+ // match |url| (because it redirected).
+ EXPECT_FALSE(NavigateToURL(shell(), url));
+ EXPECT_TRUE(IsLastCommittedEntryOfPageType(shell()->web_contents(),
+ PAGE_TYPE_NORMAL));
+ int new_process_id = shell()->web_contents()->GetRenderProcessHost()->GetID();
+
+ // Test that the mock certificate store saw the certificate associated with
+ // the new renderer process.
+ EXPECT_NE(original_process_id, new_process_id);
+ scoped_refptr<net::X509Certificate> original_cert;
+ scoped_refptr<net::X509Certificate> transfer_cert;
+ ASSERT_TRUE(
+ mock_cert_store.RetrieveCert(original_process_id, &original_cert));
+ ASSERT_TRUE(mock_cert_store.RetrieveCert(new_process_id, &transfer_cert));
+ EXPECT_TRUE(https_server.GetCertificate()->Equals(original_cert.get()));
+ EXPECT_TRUE(https_server.GetCertificate()->Equals(transfer_cert.get()));
+ // Test that the final cert id stored in the navigation entry is the
+ // cert id corresponding to the second renderer process.
+ EXPECT_EQ(new_process_id, shell()
+ ->web_contents()
+ ->GetController()
+ .GetVisibleEntry()
+ ->GetSSL()
+ .cert_id);
+}
+
+// Tests that the swapped out state on RenderViewHost is properly reset when
+// the main frame is navigated to the same SiteInstance as one of its child
+// frames.
+IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest,
+ NavigateMainFrameToChildSite) {
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
+
+ WebContentsImpl* contents =
+ static_cast<WebContentsImpl*>(shell()->web_contents());
+ FrameTreeNode* root = contents->GetFrameTree()->root();
+ EXPECT_EQ(1U, root->child_count());
+
+ // Ensure the RenderViewHost for the SiteInstance of the child is considered
+ // in swapped out state.
+ RenderViewHostImpl* rvh = contents->GetFrameTree()->GetRenderViewHost(
+ root->child_at(0)->current_frame_host()->GetSiteInstance());
+ EXPECT_TRUE(rvh->is_swapped_out_);
+
+ // Have the child frame navigate its parent to its SiteInstance.
+ GURL b_url(embedded_test_server()->GetURL("b.com", "/title1.html"));
+ std::string script = base::StringPrintf(
+ "window.domAutomationController.send("
+ "parent.location = '%s');",
+ b_url.spec().c_str());
+
+ TestFrameNavigationObserver frame_observer(root);
+ EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), script));
+ frame_observer.Wait();
+ EXPECT_EQ(b_url, root->current_url());
+
+ // Verify that the same RenderViewHost is preserved and that it is no longer
+ // in swapped out state.
+ EXPECT_EQ(rvh, contents->GetFrameTree()->GetRenderViewHost(
+ root->current_frame_host()->GetSiteInstance()));
+ EXPECT_FALSE(rvh->is_swapped_out_);
+}
+
} // namespace content
diff --git a/chromium/content/browser/speech/speech_recognizer_impl.cc b/chromium/content/browser/speech/speech_recognizer_impl.cc
index 273187d4b76..f11b5d306a2 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl.cc
+++ b/chromium/content/browser/speech/speech_recognizer_impl.cc
@@ -793,7 +793,8 @@ void SpeechRecognizerImpl::CloseAudioControllerAsynchronously() {
// Close has completed (in the audio thread) and automatically destroy it
// afterwards (upon return from OnAudioClosed).
audio_controller_->Close(base::Bind(&SpeechRecognizerImpl::OnAudioClosed,
- this, audio_controller_));
+ this,
+ base::RetainedRef(audio_controller_)));
audio_controller_ = NULL; // The controller is still refcounted by Bind.
audio_log_->OnClosed(0);
}
@@ -835,6 +836,9 @@ SpeechRecognizerImpl::FSMEventArgs::FSMEventArgs(FSMEvent event_value)
engine_error(SPEECH_RECOGNITION_ERROR_NONE) {
}
+SpeechRecognizerImpl::FSMEventArgs::FSMEventArgs(const FSMEventArgs& other) =
+ default;
+
SpeechRecognizerImpl::FSMEventArgs::~FSMEventArgs() {
}
diff --git a/chromium/content/browser/speech/speech_recognizer_impl.h b/chromium/content/browser/speech/speech_recognizer_impl.h
index ff2484beed0..007142b9228 100644
--- a/chromium/content/browser/speech/speech_recognizer_impl.h
+++ b/chromium/content/browser/speech/speech_recognizer_impl.h
@@ -81,6 +81,7 @@ class CONTENT_EXPORT SpeechRecognizerImpl
struct FSMEventArgs {
explicit FSMEventArgs(FSMEvent event_value);
+ FSMEventArgs(const FSMEventArgs& other);
~FSMEventArgs();
FSMEvent event;
diff --git a/chromium/content/browser/ssl/ssl_client_auth_handler.cc b/chromium/content/browser/ssl/ssl_client_auth_handler.cc
index 3c1e42cb1f7..9f5efaeee36 100644
--- a/chromium/content/browser/ssl/ssl_client_auth_handler.cc
+++ b/chromium/content/browser/ssl/ssl_client_auth_handler.cc
@@ -45,7 +45,7 @@ class ClientCertificateDelegateImpl : public ClientCertificateDelegate {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&SSLClientAuthHandler::ContinueWithCertificate, handler_,
- make_scoped_refptr(cert)));
+ base::RetainedRef(cert)));
}
private:
@@ -88,7 +88,7 @@ class SSLClientAuthHandler::Core : public base::RefCountedThreadSafe<Core> {
client_cert_store_(std::move(client_cert_store)),
cert_request_info_(cert_request_info) {}
- bool has_client_cert_store() const { return client_cert_store_; }
+ bool has_client_cert_store() const { return !!client_cert_store_; }
void GetClientCerts() {
if (client_cert_store_) {
@@ -178,8 +178,7 @@ void SSLClientAuthHandler::DidGetClientCerts() {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&SSLClientAuthHandler::ContinueWithCertificate,
- weak_factory_.GetWeakPtr(),
- scoped_refptr<net::X509Certificate>()));
+ weak_factory_.GetWeakPtr(), nullptr));
return;
}
@@ -198,7 +197,7 @@ void SSLClientAuthHandler::DidGetClientCerts() {
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&SelectCertificateOnUIThread, render_process_host_id,
- render_frame_host_id, cert_request_info_,
+ render_frame_host_id, base::RetainedRef(cert_request_info_),
weak_factory_.GetWeakPtr()));
}
diff --git a/chromium/content/browser/ssl/ssl_client_auth_handler.h b/chromium/content/browser/ssl/ssl_client_auth_handler.h
index 72c6cbd4dea..1deafbc8a1d 100644
--- a/chromium/content/browser/ssl/ssl_client_auth_handler.h
+++ b/chromium/content/browser/ssl/ssl_client_auth_handler.h
@@ -8,6 +8,7 @@
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_thread.h"
diff --git a/chromium/content/browser/storage_partition_impl.cc b/chromium/content/browser/storage_partition_impl.cc
index 0afff15d733..28b0eb13450 100644
--- a/chromium/content/browser/storage_partition_impl.cc
+++ b/chromium/content/browser/storage_partition_impl.cc
@@ -18,7 +18,6 @@
#include "content/browser/geofencing/geofencing_manager.h"
#include "content/browser/gpu/shader_disk_cache.h"
#include "content/browser/host_zoom_map_impl.h"
-#include "content/browser/navigator_connect/navigator_connect_context_impl.h"
#include "content/browser/notifications/platform_notification_context_impl.h"
#include "content/common/dom_storage/dom_storage_types.h"
#include "content/public/browser/browser_context.h"
@@ -349,7 +348,6 @@ StoragePartitionImpl::StoragePartitionImpl(
storage::SpecialStoragePolicy* special_storage_policy,
GeofencingManager* geofencing_manager,
HostZoomLevelContext* host_zoom_level_context,
- NavigatorConnectContextImpl* navigator_connect_context,
PlatformNotificationContextImpl* platform_notification_context,
BackgroundSyncContextImpl* background_sync_context)
: partition_path_(partition_path),
@@ -365,7 +363,6 @@ StoragePartitionImpl::StoragePartitionImpl(
special_storage_policy_(special_storage_policy),
geofencing_manager_(geofencing_manager),
host_zoom_level_context_(host_zoom_level_context),
- navigator_connect_context_(navigator_connect_context),
platform_notification_context_(platform_notification_context),
background_sync_context_(background_sync_context),
browser_context_(browser_context) {
@@ -408,12 +405,15 @@ StoragePartitionImpl::~StoragePartitionImpl() {
StoragePartitionImpl* StoragePartitionImpl::Create(
BrowserContext* context,
bool in_memory,
- const base::FilePath& partition_path) {
+ const base::FilePath& relative_partition_path) {
// Ensure that these methods are called on the UI thread, except for
// unittests where a UI thread might not have been created.
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
!BrowserThread::IsMessageLoopValid(BrowserThread::UI));
+ base::FilePath partition_path =
+ context->GetPath().Append(relative_partition_path);
+
// All of the clients have to be created and registered with the
// QuotaManager prior to the QuotaManger being used. We do them
// all together here prior to handing out a reference to anything
@@ -440,9 +440,11 @@ StoragePartitionImpl* StoragePartitionImpl::Create(
BrowserThread::GetMessageLoopProxyForThread(
BrowserThread::FILE).get());
- base::FilePath path = in_memory ? base::FilePath() : partition_path;
scoped_refptr<DOMStorageContextWrapper> dom_storage_context =
- new DOMStorageContextWrapper(path, context->GetSpecialStoragePolicy());
+ new DOMStorageContextWrapper(
+ BrowserContext::GetMojoUserIdFor(context),
+ in_memory ? base::FilePath() : context->GetPath(),
+ relative_partition_path, context->GetSpecialStoragePolicy());
// BrowserMainLoop may not be initialized in unit tests. Tests will
// need to inject their own task runner into the IndexedDBContext.
@@ -454,6 +456,8 @@ StoragePartitionImpl* StoragePartitionImpl::Create(
->task_runner()
.get()
: NULL;
+
+ base::FilePath path = in_memory ? base::FilePath() : partition_path;
scoped_refptr<IndexedDBContextImpl> indexed_db_context =
new IndexedDBContextImpl(path,
context->GetSpecialStoragePolicy(),
@@ -462,8 +466,7 @@ StoragePartitionImpl* StoragePartitionImpl::Create(
scoped_refptr<CacheStorageContextImpl> cache_storage_context =
new CacheStorageContextImpl(context);
- cache_storage_context->Init(path, quota_manager->proxy(),
- context->GetSpecialStoragePolicy());
+ cache_storage_context->Init(path, make_scoped_refptr(quota_manager->proxy()));
scoped_refptr<ServiceWorkerContextWrapper> service_worker_context =
new ServiceWorkerContextWrapper(context);
@@ -487,9 +490,6 @@ StoragePartitionImpl* StoragePartitionImpl::Create(
new HostZoomLevelContext(
context->CreateZoomLevelDelegate(partition_path)));
- scoped_refptr<NavigatorConnectContextImpl> navigator_connect_context =
- new NavigatorConnectContextImpl(service_worker_context);
-
scoped_refptr<PlatformNotificationContextImpl> platform_notification_context =
new PlatformNotificationContextImpl(path, context,
service_worker_context);
@@ -506,8 +506,7 @@ StoragePartitionImpl* StoragePartitionImpl::Create(
cache_storage_context.get(), service_worker_context.get(),
webrtc_identity_store.get(), special_storage_policy.get(),
geofencing_manager.get(), host_zoom_level_context.get(),
- navigator_connect_context.get(), platform_notification_context.get(),
- background_sync_context.get());
+ platform_notification_context.get(), background_sync_context.get());
service_worker_context->set_storage_partition(storage_partition);
@@ -577,11 +576,6 @@ ZoomLevelDelegate* StoragePartitionImpl::GetZoomLevelDelegate() {
return host_zoom_level_context_->GetZoomLevelDelegate();
}
-NavigatorConnectContextImpl*
-StoragePartitionImpl::GetNavigatorConnectContext() {
- return navigator_connect_context_.get();
-}
-
PlatformNotificationContextImpl*
StoragePartitionImpl::GetPlatformNotificationContext() {
return platform_notification_context_.get();
@@ -591,6 +585,14 @@ BackgroundSyncContextImpl* StoragePartitionImpl::GetBackgroundSyncContext() {
return background_sync_context_.get();
}
+void StoragePartitionImpl::OpenLocalStorage(
+ const url::Origin& origin,
+ mojom::LevelDBObserverPtr observer,
+ mojo::InterfaceRequest<mojom::LevelDBWrapper> request) {
+ dom_storage_context_->OpenLocalStorage(
+ origin, std::move(observer), std::move(request));
+}
+
void StoragePartitionImpl::ClearDataImpl(
uint32_t remove_mask,
uint32_t quota_storage_remove_mask,
@@ -652,42 +654,30 @@ void StoragePartitionImpl::QuotaManagedDataDeletionHelper::ClearDataOnIOThread(
// within the user-specified timeframe, and deal with the resulting set in
// ClearQuotaManagedOriginsOnIOThread().
quota_manager->GetOriginsModifiedSince(
- storage::kStorageTypePersistent,
- begin,
+ storage::kStorageTypePersistent, begin,
base::Bind(&QuotaManagedDataDeletionHelper::ClearOriginsOnIOThread,
- base::Unretained(this),
- quota_manager,
- special_storage_policy,
- origin_matcher,
- decrement_callback));
+ base::Unretained(this), base::RetainedRef(quota_manager),
+ special_storage_policy, origin_matcher, decrement_callback));
}
// Do the same for temporary quota.
if (quota_storage_remove_mask & QUOTA_MANAGED_STORAGE_MASK_TEMPORARY) {
IncrementTaskCountOnIO();
quota_manager->GetOriginsModifiedSince(
- storage::kStorageTypeTemporary,
- begin,
+ storage::kStorageTypeTemporary, begin,
base::Bind(&QuotaManagedDataDeletionHelper::ClearOriginsOnIOThread,
- base::Unretained(this),
- quota_manager,
- special_storage_policy,
- origin_matcher,
- decrement_callback));
+ base::Unretained(this), base::RetainedRef(quota_manager),
+ special_storage_policy, origin_matcher, decrement_callback));
}
// Do the same for syncable quota.
if (quota_storage_remove_mask & QUOTA_MANAGED_STORAGE_MASK_SYNCABLE) {
IncrementTaskCountOnIO();
quota_manager->GetOriginsModifiedSince(
- storage::kStorageTypeSyncable,
- begin,
+ storage::kStorageTypeSyncable, begin,
base::Bind(&QuotaManagedDataDeletionHelper::ClearOriginsOnIOThread,
- base::Unretained(this),
- quota_manager,
- special_storage_policy,
- origin_matcher,
- decrement_callback));
+ base::Unretained(this), base::RetainedRef(quota_manager),
+ special_storage_policy, origin_matcher, decrement_callback));
}
DecrementTaskCountOnIO();
@@ -892,6 +882,11 @@ BrowserContext* StoragePartitionImpl::browser_context() const {
return browser_context_;
}
+void StoragePartitionImpl::Bind(
+ mojo::InterfaceRequest<mojom::StoragePartitionService> request) {
+ bindings_.AddBinding(this, std::move(request));
+}
+
void StoragePartitionImpl::OverrideQuotaManagerForTesting(
storage::QuotaManager* quota_manager) {
quota_manager_ = quota_manager;
diff --git a/chromium/content/browser/storage_partition_impl.h b/chromium/content/browser/storage_partition_impl.h
index ece0a8ebff6..d564f9ec235 100644
--- a/chromium/content/browser/storage_partition_impl.h
+++ b/chromium/content/browser/storage_partition_impl.h
@@ -18,17 +18,19 @@
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/host_zoom_level_context.h"
#include "content/browser/indexed_db/indexed_db_context_impl.h"
-#include "content/browser/media/webrtc_identity_store.h"
-#include "content/browser/navigator_connect/navigator_connect_context_impl.h"
+#include "content/browser/media/webrtc/webrtc_identity_store.h"
#include "content/browser/notifications/platform_notification_context_impl.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/common/content_export.h"
+#include "content/common/storage_partition_service.mojom.h"
#include "content/public/browser/storage_partition.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
#include "storage/browser/quota/special_storage_policy.h"
namespace content {
-class StoragePartitionImpl : public StoragePartition {
+class StoragePartitionImpl : public StoragePartition,
+ public mojom::StoragePartitionService {
public:
CONTENT_EXPORT ~StoragePartitionImpl() override;
@@ -57,10 +59,15 @@ class StoragePartitionImpl : public StoragePartition {
HostZoomMap* GetHostZoomMap() override;
HostZoomLevelContext* GetHostZoomLevelContext() override;
ZoomLevelDelegate* GetZoomLevelDelegate() override;
- NavigatorConnectContextImpl* GetNavigatorConnectContext() override;
PlatformNotificationContextImpl* GetPlatformNotificationContext() override;
BackgroundSyncContextImpl* GetBackgroundSyncContext() override;
+ // mojom::StoragePartitionService interface.
+ void OpenLocalStorage(
+ const url::Origin& origin,
+ mojom::LevelDBObserverPtr observer,
+ mojo::InterfaceRequest<mojom::LevelDBWrapper> request) override;
+
void ClearDataForOrigin(uint32_t remove_mask,
uint32_t quota_storage_remove_mask,
const GURL& storage_origin,
@@ -81,6 +88,9 @@ class StoragePartitionImpl : public StoragePartition {
// Can return nullptr while |this| is being destroyed.
BrowserContext* browser_context() const;
+ // Called by each renderer process once.
+ void Bind(mojo::InterfaceRequest<mojom::StoragePartitionService> request);
+
struct DataDeletionHelper;
struct QuotaManagedDataDeletionHelper;
@@ -120,15 +130,16 @@ class StoragePartitionImpl : public StoragePartition {
FRIEND_TEST_ALL_PREFIXES(StoragePartitionImplTest,
RemoveLocalStorageForLastWeek);
- // The |partition_path| is the absolute path to the root of this
- // StoragePartition's on-disk storage.
+ // |relative_partition_path| is the relative path under |profile_path| to the
+ // StoragePartition's on-disk-storage.
//
- // If |in_memory| is true, the |partition_path| is (ab)used as a way of
- // distinguishing different in-memory partitions, but nothing is persisted
+ // If |in_memory| is true, the |relative_partition_path| is (ab)used as a way
+ // of distinguishing different in-memory partitions, but nothing is persisted
// on to disk.
- static StoragePartitionImpl* Create(BrowserContext* context,
- bool in_memory,
- const base::FilePath& profile_path);
+ static StoragePartitionImpl* Create(
+ BrowserContext* context,
+ bool in_memory,
+ const base::FilePath& relative_partition_path);
CONTENT_EXPORT StoragePartitionImpl(
BrowserContext* browser_context,
@@ -145,7 +156,6 @@ class StoragePartitionImpl : public StoragePartition {
storage::SpecialStoragePolicy* special_storage_policy,
GeofencingManager* geofencing_manager,
HostZoomLevelContext* host_zoom_level_context,
- NavigatorConnectContextImpl* navigator_connect_context,
PlatformNotificationContextImpl* platform_notification_context,
BackgroundSyncContextImpl* background_sync_context);
@@ -190,10 +200,11 @@ class StoragePartitionImpl : public StoragePartition {
scoped_refptr<storage::SpecialStoragePolicy> special_storage_policy_;
scoped_refptr<GeofencingManager> geofencing_manager_;
scoped_refptr<HostZoomLevelContext> host_zoom_level_context_;
- scoped_refptr<NavigatorConnectContextImpl> navigator_connect_context_;
scoped_refptr<PlatformNotificationContextImpl> platform_notification_context_;
scoped_refptr<BackgroundSyncContextImpl> background_sync_context_;
+ mojo::BindingSet<mojom::StoragePartitionService> bindings_;
+
// Raw pointer that should always be valid. The BrowserContext owns the
// StoragePartitionImplMap which then owns StoragePartitionImpl. When the
// BrowserContext is destroyed, |this| will be destroyed too.
diff --git a/chromium/content/browser/storage_partition_impl_map.cc b/chromium/content/browser/storage_partition_impl_map.cc
index 75c257ac081..83360f39a83 100644
--- a/chromium/content/browser/storage_partition_impl_map.cc
+++ b/chromium/content/browser/storage_partition_impl_map.cc
@@ -39,8 +39,6 @@
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/content_browser_client.h"
-#include "content/public/browser/navigator_connect_context.h"
-#include "content/public/browser/navigator_connect_service_factory.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
@@ -396,12 +394,11 @@ StoragePartitionImpl* StoragePartitionImplMap::Get(
if (it != partitions_.end())
return it->second;
- base::FilePath partition_path =
- browser_context_->GetPath().Append(
- GetStoragePartitionPath(partition_domain, partition_name));
- StoragePartitionImpl* partition =
- StoragePartitionImpl::Create(browser_context_, in_memory,
- partition_path);
+ base::FilePath relative_partition_path =
+ GetStoragePartitionPath(partition_domain, partition_name);
+
+ StoragePartitionImpl* partition = StoragePartitionImpl::Create(
+ browser_context_, in_memory, relative_partition_path);
partitions_[partition_config] = partition;
partition->GetQuotaManager()->SetTemporaryStorageEvictionPolicy(
@@ -462,14 +459,13 @@ StoragePartitionImpl* StoragePartitionImplMap::Get(
// These calls must happen after StoragePartitionImpl::Create().
if (partition_domain.empty()) {
partition->SetURLRequestContext(
- GetContentClient()->browser()->CreateRequestContext(
- browser_context_, &protocol_handlers,
- std::move(request_interceptors)));
+ browser_context_->CreateRequestContext(
+ &protocol_handlers, std::move(request_interceptors)));
} else {
partition->SetURLRequestContext(
- GetContentClient()->browser()->CreateRequestContextForStoragePartition(
- browser_context_, partition->GetPath(), in_memory,
- &protocol_handlers, std::move(request_interceptors)));
+ browser_context_->CreateRequestContextForStoragePartition(
+ partition->GetPath(), in_memory, &protocol_handlers,
+ std::move(request_interceptors)));
}
partition->SetMediaURLRequestContext(
partition_domain.empty() ?
@@ -477,9 +473,6 @@ StoragePartitionImpl* StoragePartitionImplMap::Get(
browser_context_->GetMediaRequestContextForStoragePartition(
partition->GetPath(), in_memory));
- GetContentClient()->browser()->GetAdditionalNavigatorConnectServices(
- partition->GetNavigatorConnectContext());
-
PostCreateInitialization(partition, in_memory);
return partition;
@@ -590,28 +583,29 @@ void StoragePartitionImplMap::PostCreateInitialization(
if (BrowserThread::IsMessageLoopValid(BrowserThread::IO)) {
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ChromeAppCacheService::InitializeOnIOThread,
- partition->GetAppCacheService(),
- in_memory ? base::FilePath() :
- partition->GetPath().Append(kAppCacheDirname),
- browser_context_->GetResourceContext(),
- make_scoped_refptr(partition->GetURLRequestContext()),
- make_scoped_refptr(
- browser_context_->GetSpecialStoragePolicy())));
+ base::Bind(
+ &ChromeAppCacheService::InitializeOnIOThread,
+ partition->GetAppCacheService(),
+ in_memory ? base::FilePath()
+ : partition->GetPath().Append(kAppCacheDirname),
+ browser_context_->GetResourceContext(),
+ base::RetainedRef(partition->GetURLRequestContext()),
+ base::RetainedRef(browser_context_->GetSpecialStoragePolicy())));
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&CacheStorageContextImpl::SetBlobParametersForCache,
partition->GetCacheStorageContext(),
- make_scoped_refptr(partition->GetURLRequestContext()),
- make_scoped_refptr(
+ base::RetainedRef(partition->GetURLRequestContext()),
+ base::RetainedRef(
ChromeBlobStorageContext::GetFor(browser_context_))));
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ServiceWorkerContextWrapper::set_resource_context,
+ base::Bind(&ServiceWorkerContextWrapper::InitializeResourceContext,
partition->GetServiceWorkerContext(),
- browser_context_->GetResourceContext()));
+ browser_context_->GetResourceContext(),
+ base::RetainedRef(partition->GetURLRequestContext())));
// We do not call InitializeURLRequestContext() for media contexts because,
// other than the HTTP cache, the media contexts share the same backing
diff --git a/chromium/content/browser/streams/stream_url_request_job.cc b/chromium/content/browser/streams/stream_url_request_job.cc
index e26fe35a41a..69251bda5da 100644
--- a/chromium/content/browser/streams/stream_url_request_job.cc
+++ b/chromium/content/browser/streams/stream_url_request_job.cc
@@ -23,7 +23,7 @@ StreamURLRequestJob::StreamURLRequestJob(
net::URLRequest* request,
net::NetworkDelegate* network_delegate,
scoped_refptr<Stream> stream)
- : net::URLRequestJob(request, network_delegate),
+ : net::URLRangeRequestJob(request, network_delegate),
stream_(stream),
headers_set_(false),
pending_buffer_size_(0),
@@ -147,31 +147,18 @@ int StreamURLRequestJob::GetResponseCode() const {
return response_info_->headers->response_code();
}
-void StreamURLRequestJob::SetExtraRequestHeaders(
- const net::HttpRequestHeaders& headers) {
- std::string range_header;
- if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) {
- std::vector<net::HttpByteRange> ranges;
- if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) {
- if (ranges.size() == 1) {
- // Streams don't support seeking, so a non-zero starting position
- // doesn't make sense.
- if (ranges[0].first_byte_position() == 0) {
- max_range_ = ranges[0].last_byte_position() + 1;
- } else {
- NotifyFailure(net::ERR_METHOD_NOT_SUPPORTED);
- return;
- }
- } else {
- NotifyFailure(net::ERR_METHOD_NOT_SUPPORTED);
- return;
- }
+void StreamURLRequestJob::DidStart() {
+ if (range_parse_result() == net::OK && ranges().size() > 0) {
+ // Only one range is supported, and it must start at the first byte.
+ if (ranges().size() > 1 || ranges()[0].first_byte_position() != 0) {
+ NotifyFailure(net::ERR_METHOD_NOT_SUPPORTED);
+ return;
}
+
+ max_range_ = ranges()[0].last_byte_position() + 1;
}
-}
-void StreamURLRequestJob::DidStart() {
- // We only support GET request.
+ // This class only supports GET requests.
if (request()->method() != "GET") {
NotifyFailure(net::ERR_METHOD_NOT_SUPPORTED);
return;
diff --git a/chromium/content/browser/streams/stream_url_request_job.h b/chromium/content/browser/streams/stream_url_request_job.h
index ded5fa729ca..d11e6e7bdb9 100644
--- a/chromium/content/browser/streams/stream_url_request_job.h
+++ b/chromium/content/browser/streams/stream_url_request_job.h
@@ -9,7 +9,7 @@
#include "content/browser/streams/stream_read_observer.h"
#include "content/common/content_export.h"
#include "net/http/http_status_code.h"
-#include "net/url_request/url_request_job.h"
+#include "net/url_request/url_range_request_job.h"
namespace content {
@@ -17,7 +17,7 @@ class Stream;
// A request job that handles reading stream URLs.
class CONTENT_EXPORT StreamURLRequestJob
- : public net::URLRequestJob,
+ : public net::URLRangeRequestJob,
public StreamReadObserver {
public:
StreamURLRequestJob(net::URLRequest* request,
@@ -34,7 +34,6 @@ class CONTENT_EXPORT StreamURLRequestJob
bool GetMimeType(std::string* mime_type) const override;
void GetResponseInfo(net::HttpResponseInfo* info) override;
int GetResponseCode() const override;
- void SetExtraRequestHeaders(const net::HttpRequestHeaders& headers) override;
protected:
~StreamURLRequestJob() override;
diff --git a/chromium/content/browser/system_message_window_win.cc b/chromium/content/browser/system_message_window_win.cc
deleted file mode 100644
index 0316fc7cb02..00000000000
--- a/chromium/content/browser/system_message_window_win.cc
+++ /dev/null
@@ -1,164 +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/system_message_window_win.h"
-
-#include <dbt.h>
-#include <stddef.h>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/system_monitor/system_monitor.h"
-#include "base/win/wrapped_window_proc.h"
-#include "media/audio/win/core_audio_util_win.h"
-
-namespace content {
-
-namespace {
-const wchar_t kWindowClassName[] = L"Chrome_SystemMessageWindow";
-
-// A static map from a device category guid to base::SystemMonitor::DeviceType.
-struct {
- const GUID device_category;
- const base::SystemMonitor::DeviceType device_type;
-} const kDeviceCategoryMap[] = {
- { KSCATEGORY_AUDIO, base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE },
- { KSCATEGORY_VIDEO, base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE },
-};
-} // namespace
-
-// Manages the device notification handles for SystemMessageWindowWin.
-class SystemMessageWindowWin::DeviceNotifications {
- public:
- explicit DeviceNotifications(HWND hwnd) : notifications_() {
- Register(hwnd);
- }
-
- ~DeviceNotifications() {
- Unregister();
- }
-
- void Register(HWND hwnd) {
- // Request to receive device notifications. All applications receive basic
- // notifications via WM_DEVICECHANGE but in order to receive detailed device
- // arrival and removal messages, we need to register.
- DEV_BROADCAST_DEVICEINTERFACE filter = {0};
- filter.dbcc_size = sizeof(filter);
- filter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
- bool core_audio_support = media::CoreAudioUtil::IsSupported();
- for (size_t i = 0; i < arraysize(kDeviceCategoryMap); ++i) {
- // If CoreAudio is supported, AudioDeviceListenerWin will
- // take care of monitoring audio devices.
- if (core_audio_support &&
- KSCATEGORY_AUDIO == kDeviceCategoryMap[i].device_category) {
- continue;
- }
-
- filter.dbcc_classguid = kDeviceCategoryMap[i].device_category;
- DCHECK_EQ(notifications_[i], static_cast<HDEVNOTIFY>(NULL));
- notifications_[i] = RegisterDeviceNotification(
- hwnd, &filter, DEVICE_NOTIFY_WINDOW_HANDLE);
- DPLOG_IF(ERROR, !notifications_[i])
- << "RegisterDeviceNotification failed";
- }
- }
-
- void Unregister() {
- for (size_t i = 0; i < arraysize(notifications_); ++i) {
- if (notifications_[i]) {
- UnregisterDeviceNotification(notifications_[i]);
- notifications_[i] = NULL;
- }
- }
- }
-
- private:
- HDEVNOTIFY notifications_[arraysize(kDeviceCategoryMap)];
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(DeviceNotifications);
-};
-
-
-SystemMessageWindowWin::SystemMessageWindowWin() {
- WNDCLASSEX window_class;
- base::win::InitializeWindowClass(
- kWindowClassName,
- &base::win::WrappedWindowProc<SystemMessageWindowWin::WndProcThunk>,
- 0, 0, 0, NULL, NULL, NULL, NULL, NULL,
- &window_class);
- instance_ = window_class.hInstance;
- ATOM clazz = RegisterClassEx(&window_class);
- DCHECK(clazz);
-
- window_ = CreateWindow(kWindowClassName,
- 0, 0, 0, 0, 0, 0, 0, 0, instance_, 0);
- SetWindowLongPtr(window_, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
- device_notifications_.reset(new DeviceNotifications(window_));
-}
-
-SystemMessageWindowWin::~SystemMessageWindowWin() {
- if (window_) {
- DestroyWindow(window_);
- UnregisterClass(kWindowClassName, instance_);
- }
-}
-
-LRESULT SystemMessageWindowWin::OnDeviceChange(UINT event_type, LPARAM data) {
- base::SystemMonitor* monitor = base::SystemMonitor::Get();
- base::SystemMonitor::DeviceType device_type =
- base::SystemMonitor::DEVTYPE_UNKNOWN;
- switch (event_type) {
- case DBT_DEVNODES_CHANGED:
- // For this notification, we're happy with the default DEVTYPE_UNKNOWN.
- break;
-
- case DBT_DEVICEREMOVECOMPLETE:
- case DBT_DEVICEARRIVAL: {
- // This notification has more details about the specific device that
- // was added or removed. See if this is a category we're interested
- // in monitoring and if so report the specific device type. If we don't
- // find the category in our map, ignore the notification and do not
- // notify the system monitor.
- DEV_BROADCAST_DEVICEINTERFACE* device_interface =
- reinterpret_cast<DEV_BROADCAST_DEVICEINTERFACE*>(data);
- if (device_interface->dbcc_devicetype != DBT_DEVTYP_DEVICEINTERFACE)
- return TRUE;
- for (size_t i = 0; i < arraysize(kDeviceCategoryMap); ++i) {
- if (kDeviceCategoryMap[i].device_category ==
- device_interface->dbcc_classguid) {
- device_type = kDeviceCategoryMap[i].device_type;
- break;
- }
- }
-
- // Devices that we do not have a DEVTYPE_ for, get detected via
- // DBT_DEVNODES_CHANGED, so we avoid sending additional notifications
- // for those here.
- if (device_type == base::SystemMonitor::DEVTYPE_UNKNOWN)
- return TRUE;
- break;
- }
-
- default:
- return TRUE;
- }
-
- monitor->ProcessDevicesChanged(device_type);
-
- return TRUE;
-}
-
-LRESULT CALLBACK SystemMessageWindowWin::WndProc(HWND hwnd, UINT message,
- WPARAM wparam, LPARAM lparam) {
- switch (message) {
- case WM_DEVICECHANGE:
- return OnDeviceChange(static_cast<UINT>(wparam), lparam);
- default:
- break;
- }
-
- return ::DefWindowProc(hwnd, message, wparam, lparam);
-}
-
-} // namespace content
diff --git a/chromium/content/browser/system_message_window_win.h b/chromium/content/browser/system_message_window_win.h
deleted file mode 100644
index 061db54908f..00000000000
--- a/chromium/content/browser/system_message_window_win.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_SYSTEM_MESSAGE_WINDOW_WIN_H_
-#define CONTENT_BROWSER_SYSTEM_MESSAGE_WINDOW_WIN_H_
-
-#include <windows.h>
-
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-class CONTENT_EXPORT SystemMessageWindowWin {
- public:
- SystemMessageWindowWin();
-
- virtual ~SystemMessageWindowWin();
-
- virtual LRESULT OnDeviceChange(UINT event_type, LPARAM data);
-
- private:
- void Init();
-
- LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
- WPARAM wparam, LPARAM lparam);
-
- static LRESULT CALLBACK WndProcThunk(HWND hwnd,
- UINT message,
- WPARAM wparam,
- LPARAM lparam) {
- SystemMessageWindowWin* msg_wnd = reinterpret_cast<SystemMessageWindowWin*>(
- GetWindowLongPtr(hwnd, GWLP_USERDATA));
- if (msg_wnd)
- return msg_wnd->WndProc(hwnd, message, wparam, lparam);
- return ::DefWindowProc(hwnd, message, wparam, lparam);
- }
-
- HMODULE instance_;
- HWND window_;
- class DeviceNotifications;
- scoped_ptr<DeviceNotifications> device_notifications_;
-
- DISALLOW_COPY_AND_ASSIGN(SystemMessageWindowWin);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_SYSTEM_MESSAGE_WINDOW_WIN_H_
diff --git a/chromium/content/browser/system_message_window_win_unittest.cc b/chromium/content/browser/system_message_window_win_unittest.cc
deleted file mode 100644
index fac8f2baafd..00000000000
--- a/chromium/content/browser/system_message_window_win_unittest.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/system_message_window_win.h"
-
-#include <dbt.h>
-#include <string>
-#include <vector>
-
-#include "base/files/file_path.h"
-#include "base/system_monitor/system_monitor.h"
-#include "base/test/mock_devices_changed_observer.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-class SystemMessageWindowWinTest : public testing::Test {
- public:
- ~SystemMessageWindowWinTest() override {}
-
- protected:
- void SetUp() override {
- system_monitor_.AddDevicesChangedObserver(&observer_);
- }
-
- base::MessageLoop message_loop_;
- base::SystemMonitor system_monitor_;
- base::MockDevicesChangedObserver observer_;
- SystemMessageWindowWin window_;
-};
-
-TEST_F(SystemMessageWindowWinTest, DevicesChanged) {
- EXPECT_CALL(observer_, OnDevicesChanged(testing::_)).Times(1);
- window_.OnDeviceChange(DBT_DEVNODES_CHANGED, NULL);
- message_loop_.RunUntilIdle();
-}
-
-TEST_F(SystemMessageWindowWinTest, RandomMessage) {
- window_.OnDeviceChange(DBT_DEVICEQUERYREMOVE, NULL);
- message_loop_.RunUntilIdle();
-}
-
-} // namespace content
diff --git a/chromium/content/browser/theme_helper_mac.mm b/chromium/content/browser/theme_helper_mac.mm
index aa5ebd05a0d..7cc95a70aaf 100644
--- a/chromium/content/browser/theme_helper_mac.mm
+++ b/chromium/content/browser/theme_helper_mac.mm
@@ -8,8 +8,8 @@
#include "base/command_line.h"
#include "base/mac/mac_util.h"
-#include "base/mac/sdk_forward_declarations.h"
#include "base/strings/sys_string_conversions.h"
+#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_service.h"
@@ -18,25 +18,11 @@
#include "content/public/common/content_switches.h"
using content::RenderProcessHost;
+using content::RenderProcessHostImpl;
using content::ThemeHelperMac;
namespace {
-bool GetScrollAnimationEnabled() {
- bool enabled = false;
- id value = nil;
- if (base::mac::IsOSMountainLionOrLater()) {
- value = [[NSUserDefaults standardUserDefaults]
- objectForKey:@"NSScrollAnimationEnabled"];
- } else {
- value = [[NSUserDefaults standardUserDefaults]
- objectForKey:@"AppleScrollAnimationEnabled"];
- }
- if (value)
- enabled = [value boolValue];
- return enabled;
-}
-
blink::WebScrollbarButtonsPlacement GetButtonPlacement() {
NSString* scrollbar_variant = [[NSUserDefaults standardUserDefaults]
objectForKey:@"AppleScrollBarVariant"];
@@ -64,7 +50,6 @@ void FillScrollbarThemeParams(ViewMsg_UpdateScrollbarTheme_Params* params) {
[defaults boolForKey:@"AppleScrollerPagingBehavior"];
params->preferred_scroller_style =
ThemeHelperMac::GetPreferredScrollerStyle();
- params->scroll_animation_enabled = GetScrollAnimationEnabled();
params->button_placement = GetButtonPlacement();
}
@@ -139,12 +124,10 @@ ViewMsg_SystemColorsChanged* CreateSystemColorsChangedMessage() {
switches::kSingleProcess)) {
NSNotificationCenter* center = [NSNotificationCenter defaultCenter];
- if ([NSScroller respondsToSelector:@selector(preferredScrollerStyle)]) {
- [center addObserver:self
- selector:@selector(behaviorPrefsChanged:)
- name:NSPreferredScrollerStyleDidChangeNotification
- object:nil];
- }
+ [center addObserver:self
+ selector:@selector(behaviorPrefsChanged:)
+ name:NSPreferredScrollerStyleDidChangeNotification
+ object:nil];
[center addObserver:self
selector:@selector(systemColorsChanged:)
@@ -177,7 +160,10 @@ ViewMsg_SystemColorsChanged* CreateSystemColorsChangedMessage() {
for (RenderProcessHost::iterator it(RenderProcessHost::AllHostsIterator());
!it.IsAtEnd();
it.Advance()) {
- it.GetCurrentValue()->Send(new ViewMsg_UpdateScrollbarTheme(params));
+ RenderProcessHostImpl* rphi =
+ static_cast<RenderProcessHostImpl*>(it.GetCurrentValue());
+ rphi->RecomputeAndUpdateWebKitPreferences();
+ rphi->Send(new ViewMsg_UpdateScrollbarTheme(params));
}
}
@@ -193,8 +179,6 @@ ThemeHelperMac* ThemeHelperMac::GetInstance() {
// static
blink::ScrollerStyle ThemeHelperMac::GetPreferredScrollerStyle() {
- if (![NSScroller respondsToSelector:@selector(preferredScrollerStyle)])
- return blink::ScrollerStyleLegacy;
return static_cast<blink::ScrollerStyle>([NSScroller preferredScrollerStyle]);
}
@@ -219,9 +203,11 @@ void ThemeHelperMac::Observe(int type,
FillScrollbarThemeParams(&params);
params.redraw = false;
- RenderProcessHost* rph = Source<RenderProcessHost>(source).ptr();
- rph->Send(new ViewMsg_UpdateScrollbarTheme(params));
- rph->Send(CreateSystemColorsChangedMessage());
+ RenderProcessHostImpl* rphi =
+ Source<content::RenderProcessHostImpl>(source).ptr();
+ rphi->RecomputeAndUpdateWebKitPreferences();
+ rphi->Send(new ViewMsg_UpdateScrollbarTheme(params));
+ rphi->Send(CreateSystemColorsChangedMessage());
}
} // namespace content
diff --git a/chromium/content/browser/top_document_isolation_browsertest.cc b/chromium/content/browser/top_document_isolation_browsertest.cc
new file mode 100644
index 00000000000..dd4541f2318
--- /dev/null
+++ b/chromium/content/browser/top_document_isolation_browsertest.cc
@@ -0,0 +1,571 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/command_line.h"
+#include "content/browser/frame_host/frame_tree_node.h"
+#include "content/browser/web_contents/web_contents_impl.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/content_browser_test.h"
+#include "content/public/test/content_browser_test_utils.h"
+#include "content/public/test/test_navigation_observer.h"
+#include "content/shell/browser/shell.h"
+#include "content/test/content_browser_test_utils_internal.h"
+#include "content/test/test_frame_navigation_observer.h"
+#include "net/dns/mock_host_resolver.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class TopDocumentIsolationTest : public ContentBrowserTest {
+ public:
+ TopDocumentIsolationTest() {}
+
+ protected:
+ std::string DepictFrameTree(FrameTreeNode* node) {
+ return visualizer_.DepictFrameTree(node);
+ }
+
+ void SetUpCommandLine(base::CommandLine* command_line) override {
+ command_line->AppendSwitch(switches::kTopDocumentIsolation);
+ }
+
+ void SetUpOnMainThread() override {
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(embedded_test_server()->Start());
+ SetupCrossSiteRedirector(embedded_test_server());
+ }
+
+ FrameTreeNode* root() {
+ return static_cast<WebContentsImpl*>(shell()->web_contents())
+ ->GetFrameTree()
+ ->root();
+ }
+
+ void GoBack() {
+ TestNavigationObserver back_load_observer(shell()->web_contents());
+ shell()->web_contents()->GetController().GoBack();
+ back_load_observer.Wait();
+ }
+
+ Shell* OpenPopup(FrameTreeNode* opener, const std::string& url) {
+ GURL gurl =
+ opener->current_frame_host()->GetLastCommittedURL().Resolve(url);
+ return content::OpenPopup(opener->current_frame_host(), gurl, "_blank");
+ }
+
+ void RendererInitiatedNavigateToURL(FrameTreeNode* node, const GURL& url) {
+ TestFrameNavigationObserver nav_observer(node);
+ ASSERT_TRUE(ExecuteScript(node->current_frame_host(),
+ "window.location.href='" + url.spec() + "'"));
+ nav_observer.Wait();
+ }
+
+ private:
+ FrameTreeVisualizer visualizer_;
+};
+
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, SameSiteDeeplyNested) {
+ if (content::AreAllSitesIsolatedForTesting())
+ return; // Top Document Isolation is disabled in this mode.
+
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(a,a(a,a(a)))"));
+
+ NavigateToURL(shell(), main_url);
+
+ EXPECT_EQ(
+ " Site A\n"
+ " |--Site A\n"
+ " +--Site A\n"
+ " |--Site A\n"
+ " +--Site A\n"
+ " +--Site A\n"
+ "Where A = http://a.com/",
+ DepictFrameTree(root()));
+}
+
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, CrossSiteDeeplyNested) {
+ if (content::AreAllSitesIsolatedForTesting())
+ return; // Top Document Isolation is disabled in this mode.
+
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b(c(d(b))))"));
+
+ NavigateToURL(shell(), main_url);
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ " +--Site B -- proxies for A\n"
+ " +--Site B -- proxies for A\n"
+ " +--Site B -- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = default subframe process",
+ DepictFrameTree(root()));
+}
+
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, ReturnToTopSite) {
+ if (content::AreAllSitesIsolatedForTesting())
+ return; // Top Document Isolation is disabled in this mode.
+
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b(a(c)))"));
+
+ NavigateToURL(shell(), main_url);
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ " +--Site A -- proxies for B\n"
+ " +--Site B -- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = default subframe process",
+ DepictFrameTree(root()));
+}
+
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, NavigateSubframeToTopSite) {
+ if (content::AreAllSitesIsolatedForTesting())
+ return; // Top Document Isolation is disabled in this mode.
+
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b(c(d)))"));
+
+ NavigateToURL(shell(), main_url);
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ " +--Site B -- proxies for A\n"
+ " +--Site B -- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = default subframe process",
+ DepictFrameTree(root()));
+
+ GURL ada_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(d(a))"));
+ RendererInitiatedNavigateToURL(root()->child_at(0)->child_at(0), ada_url);
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ " +--Site A -- proxies for B\n"
+ " +--Site B -- proxies for A\n"
+ " +--Site A -- proxies for B\n"
+ "Where A = http://a.com/\n"
+ " B = default subframe process",
+ DepictFrameTree(root()));
+}
+
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, NavigateToSubframeSite) {
+ if (content::AreAllSitesIsolatedForTesting())
+ return; // Top Document Isolation is disabled in this mode.
+
+ GURL ab_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+ GURL ba_url(embedded_test_server()->GetURL(
+ "b.com", "/cross_site_iframe_factory.html?b(a, c)"));
+
+ NavigateToURL(shell(), ab_url);
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = default subframe process",
+ DepictFrameTree(root()));
+
+ NavigateToURL(shell(), ba_url);
+
+ EXPECT_EQ(
+ " Site C ------------ proxies for B\n"
+ " |--Site B ------- proxies for C\n"
+ " +--Site B ------- proxies for C\n"
+ "Where B = default subframe process\n"
+ " C = http://b.com/",
+ DepictFrameTree(root()));
+}
+
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
+ NavigateToSubframeSiteWithPopup) {
+ if (content::AreAllSitesIsolatedForTesting())
+ return; // Top Document Isolation is disabled in this mode.
+
+ // A(B) -> B(A), but while a separate B(A) popup exists.
+ GURL ab_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
+
+ NavigateToURL(shell(), ab_url);
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = default subframe process",
+ DepictFrameTree(root()));
+
+ Shell* popup =
+ OpenPopup(root()->child_at(0), "/cross_site_iframe_factory.html?b(a)");
+ FrameTreeNode* popup_root =
+ static_cast<WebContentsImpl*>(popup->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // This popup's main frame must stay in the default subframe siteinstance,
+ // since its opener (the b.com subframe) may synchronously script it. Note
+ // that the popup's subframe is same-site with window.top.opener.top, the
+ // a.com main frame of the tab. But --top-document-isolation does not
+ // currently place the popup subframe in the a.com process in this case.
+ EXPECT_EQ(
+ " Site B\n"
+ " +--Site B\n"
+ "Where B = default subframe process",
+ DepictFrameTree(popup_root));
+
+ GURL ba_url(embedded_test_server()->GetURL(
+ "b.com", "/cross_site_iframe_factory.html?b(a, c)"));
+ NavigateToURL(shell(), ba_url);
+
+ // This navigation destroys the popup's opener, so we allow the main frame to
+ // commit in a top level process for b.com, in spite of the b.com popup in the
+ // default subframe process.
+ EXPECT_EQ(
+ " Site C ------------ proxies for B\n"
+ " |--Site B ------- proxies for C\n"
+ " +--Site B ------- proxies for C\n"
+ "Where B = default subframe process\n"
+ " C = http://b.com/",
+ DepictFrameTree(root()));
+ EXPECT_EQ(
+ " Site B\n"
+ " +--Site B\n"
+ "Where B = default subframe process",
+ DepictFrameTree(popup_root));
+
+ // Navigate the popup to a new site.
+ GURL c_url(embedded_test_server()->GetURL(
+ "c.com", "/cross_site_iframe_factory.html?c(c, c, c, c)"));
+ NavigateToURL(popup, c_url);
+ EXPECT_EQ(
+ " Site D ------------ proxies for B\n"
+ " |--Site D ------- proxies for B\n"
+ " |--Site D ------- proxies for B\n"
+ " |--Site D ------- proxies for B\n"
+ " +--Site D ------- proxies for B\n"
+ "Where B = default subframe process\n"
+ " D = http://c.com/",
+ DepictFrameTree(popup_root));
+ NavigateToURL(shell(), c_url);
+ EXPECT_EQ(
+ " Site D\n"
+ " |--Site D\n"
+ " |--Site D\n"
+ " |--Site D\n"
+ " +--Site D\n"
+ "Where D = http://c.com/",
+ DepictFrameTree(popup_root));
+ EXPECT_EQ(
+ " Site D\n"
+ " |--Site D\n"
+ " |--Site D\n"
+ " |--Site D\n"
+ " +--Site D\n"
+ "Where D = http://c.com/",
+ DepictFrameTree(root()));
+}
+
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest,
+ NavigateToSubframeSiteWithPopup2) {
+ if (content::AreAllSitesIsolatedForTesting())
+ return; // Top Document Isolation is disabled in this mode.
+
+ // A(B, C) -> C(A, B), but while a separate C(A) popup exists.
+ //
+ // This test is constructed so that c.com is the second site to commit in the
+ // default subframe SiteInstance, so the default subframe SiteInstance does
+ // not have a "c.com" as the value of GetSiteURL().
+ GURL abb_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(b, b)"));
+
+ NavigateToURL(shell(), abb_url);
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " |--Site B ------- proxies for A\n"
+ " +--Site B ------- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = default subframe process",
+ DepictFrameTree(root()));
+
+ // A(B, B) -> A(B, C)
+ GURL c_url(embedded_test_server()->GetURL(
+ "c.com", "/cross_site_iframe_factory.html?c"));
+ NavigateFrameToURL(root()->child_at(1), c_url);
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " |--Site B ------- proxies for A\n"
+ " +--Site B ------- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = default subframe process",
+ DepictFrameTree(root()));
+
+ // This test exercises what happens when the SiteURL of the default subframe
+ // siteinstance doesn't match the subframe site.
+ EXPECT_NE("c.com", root()
+ ->child_at(1)
+ ->current_frame_host()
+ ->GetSiteInstance()
+ ->GetSiteURL()
+ .host());
+
+ // Subframe C creates C(A) popup.
+ Shell* popup =
+ OpenPopup(root()->child_at(1), "/cross_site_iframe_factory.html?c(a)");
+
+ FrameTreeNode* popup_root =
+ static_cast<WebContentsImpl*>(popup->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // The popup must stay with its opener, in the default subframe process.
+ EXPECT_EQ(
+ " Site B\n"
+ " +--Site B\n"
+ "Where B = default subframe process",
+ DepictFrameTree(popup_root));
+
+ GURL cab_url(embedded_test_server()->GetURL(
+ "c.com", "/cross_site_iframe_factory.html?c(a, b)"));
+ NavigateToURL(shell(), cab_url);
+
+ // This c.com navigation currently breaks out of the default subframe process,
+ // even though that process houses a c.com pop-up.
+ EXPECT_EQ(
+ " Site C ------------ proxies for B\n"
+ " |--Site B ------- proxies for C\n"
+ " +--Site B ------- proxies for C\n"
+ "Where B = default subframe process\n"
+ " C = http://c.com/",
+ DepictFrameTree(root()));
+
+ // c.com popup should remain where it was, in the subframe process.
+ EXPECT_EQ(
+ " Site B\n"
+ " +--Site B\n"
+ "Where B = default subframe process",
+ DepictFrameTree(popup_root));
+ EXPECT_EQ(nullptr, popup_root->opener());
+
+ // If we navigate the popup to a new site, it ought to transfer processes.
+ GURL d_url(embedded_test_server()->GetURL(
+ "d.com", "/cross_site_iframe_factory.html?d"));
+ NavigateToURL(popup, d_url);
+ EXPECT_EQ(
+ " Site D ------------ proxies for B\n"
+ "Where B = default subframe process\n"
+ " D = http://d.com/",
+ DepictFrameTree(popup_root));
+ NavigateToURL(shell(), d_url);
+ EXPECT_EQ(
+ " Site D\n"
+ "Where D = http://d.com/",
+ DepictFrameTree(popup_root));
+ EXPECT_EQ(
+ " Site D\n"
+ "Where D = http://d.com/",
+ DepictFrameTree(root()));
+}
+
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, FramesForSitesInHistory) {
+ if (content::AreAllSitesIsolatedForTesting())
+ return; // Top Document Isolation is disabled in this mode.
+
+ // First, do a series of navigations.
+ GURL a_url = embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a");
+ GURL b_url = embedded_test_server()->GetURL(
+ "b.com", "/cross_site_iframe_factory.html?b");
+ GURL c_url = embedded_test_server()->GetURL(
+ "c.com", "/cross_site_iframe_factory.html?c");
+
+ // Browser-initiated navigation to a.com.
+ NavigateToURL(shell(), a_url);
+ EXPECT_EQ(
+ " Site A\n"
+ "Where A = http://a.com/",
+ DepictFrameTree(root()));
+
+ // Browser-initiated navigation to b.com.
+ NavigateToURL(shell(), b_url);
+ EXPECT_EQ(
+ " Site B\n"
+ "Where B = http://b.com/",
+ DepictFrameTree(root()));
+
+ // Renderer-initiated navigation back to a.com. This shouldn't swap processes.
+ RendererInitiatedNavigateToURL(root(), a_url);
+ EXPECT_EQ(
+ " Site B\n"
+ "Where B = http://b.com/",
+ DepictFrameTree(root()));
+
+ // Browser-initiated navigation to c.com.
+ NavigateToURL(shell(), c_url);
+ EXPECT_EQ(
+ " Site C\n"
+ "Where C = http://c.com/",
+ DepictFrameTree(root()));
+
+ // Now, navigate to a fourth site with iframes to the sites in the history.
+ NavigateToURL(shell(),
+ embedded_test_server()->GetURL(
+ "d.com", "/cross_site_iframe_factory.html?d(a,b,c)"));
+
+ EXPECT_EQ(
+ " Site D ------------ proxies for E\n"
+ " |--Site E ------- proxies for D\n"
+ " |--Site E ------- proxies for D\n"
+ " +--Site E ------- proxies for D\n"
+ "Where D = http://d.com/\n"
+ " E = default subframe process",
+ DepictFrameTree(root()));
+
+ // Now try going back.
+ GoBack();
+ EXPECT_EQ(
+ " Site C\n"
+ "Where C = http://c.com/",
+ DepictFrameTree(root()));
+ GoBack();
+ EXPECT_EQ(
+ " Site B\n"
+ "Where B = http://b.com/",
+ DepictFrameTree(root()));
+ GoBack();
+ EXPECT_EQ(
+ " Site B\n"
+ "Where B = http://b.com/",
+ DepictFrameTree(root()));
+ GoBack();
+ EXPECT_EQ(
+ " Site A\n"
+ "Where A = http://a.com/",
+ DepictFrameTree(root()));
+}
+
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, CrossSiteAtLevelTwo) {
+ if (content::AreAllSitesIsolatedForTesting())
+ return; // Top Document Isolation is disabled in this mode.
+
+ GURL main_url(embedded_test_server()->GetURL(
+ "a.com", "/cross_site_iframe_factory.html?a(a(b, a))"));
+
+ NavigateToURL(shell(), main_url);
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site A ------- proxies for B\n"
+ " |--Site B -- proxies for A\n"
+ " +--Site A -- proxies for B\n"
+ "Where A = http://a.com/\n"
+ " B = default subframe process",
+ DepictFrameTree(root()));
+
+ GURL c_url(embedded_test_server()->GetURL(
+ "c.com", "/cross_site_iframe_factory.html?c"));
+ NavigateFrameToURL(root()->child_at(0)->child_at(1), c_url);
+
+ // This navigation should complete in the default subframe siteinstance.
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site A ------- proxies for B\n"
+ " |--Site B -- proxies for A\n"
+ " +--Site B -- proxies for A\n"
+ "Where A = http://a.com/\n"
+ " B = default subframe process",
+ DepictFrameTree(root()));
+}
+
+IN_PROC_BROWSER_TEST_F(TopDocumentIsolationTest, PopupAndRedirection) {
+ if (content::AreAllSitesIsolatedForTesting())
+ return; // Top Document Isolation is disabled in this mode.
+
+ GURL main_url(embedded_test_server()->GetURL(
+ "page.com", "/cross_site_iframe_factory.html?page(adnetwork)"));
+
+ // User opens page on page.com which contains a subframe from adnetwork.com.
+ NavigateToURL(shell(), main_url);
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ "Where A = http://page.com/\n"
+ " B = default subframe process",
+ DepictFrameTree(root()));
+
+ GURL ad_url(embedded_test_server()->GetURL(
+ "ad.com", "/cross_site_iframe_factory.html?ad"));
+
+ // adnetwork.com retrieves an ad from advertiser (ad.com) and redirects the
+ // subframe to ad.com.
+ RendererInitiatedNavigateToURL(root()->child_at(0), ad_url);
+
+ // The subframe still uses the default subframe SiteInstance after navigation.
+ EXPECT_EQ(
+ " Site A ------------ proxies for B\n"
+ " +--Site B ------- proxies for A\n"
+ "Where A = http://page.com/\n"
+ " B = default subframe process",
+ DepictFrameTree(root()));
+
+ // User clicks the ad in the subframe, which opens a popup on the ad
+ // network's domain.
+ GURL popup_url(embedded_test_server()->GetURL(
+ "adnetwork.com", "/cross_site_iframe_factory.html?adnetwork"));
+ Shell* popup = OpenPopup(root()->child_at(0), popup_url.spec());
+
+ FrameTreeNode* popup_root =
+ static_cast<WebContentsImpl*>(popup->web_contents())
+ ->GetFrameTree()
+ ->root();
+
+ // It's ok for the popup to break out of the subframe process because it's
+ // currently cross-site from its opener frame.
+ EXPECT_EQ(
+ " Site C ------------ proxies for B\n"
+ "Where B = default subframe process\n"
+ " C = http://adnetwork.com/",
+ DepictFrameTree(popup_root));
+
+ EXPECT_EQ(
+ " Site A ------------ proxies for B C\n"
+ " +--Site B ------- proxies for A C\n"
+ "Where A = http://page.com/\n"
+ " B = default subframe process\n"
+ " C = http://adnetwork.com/",
+ DepictFrameTree(root()));
+
+ // The popup redirects itself to the advertiser's website (ad.com).
+ RendererInitiatedNavigateToURL(popup_root, ad_url);
+
+ // This must join its same-site opener, in the default subframe SiteInstance.
+ EXPECT_EQ(
+ " Site A ------------ proxies for B C\n"
+ " +--Site B ------- proxies for A C\n"
+ "Where A = http://page.com/\n"
+ " B = default subframe process\n"
+ " C = http://adnetwork.com/",
+ DepictFrameTree(root()));
+ EXPECT_EQ(
+ " Site C ------------ proxies for B\n"
+ "Where B = default subframe process\n"
+ " C = http://adnetwork.com/",
+ DepictFrameTree(popup_root));
+}
+
+} // namespace content
diff --git a/chromium/content/browser/tracing/BUILD.gn b/chromium/content/browser/tracing/BUILD.gn
index 2122c79aa59..b71bf1b4428 100644
--- a/chromium/content/browser/tracing/BUILD.gn
+++ b/chromium/content/browser/tracing/BUILD.gn
@@ -12,7 +12,7 @@ tracing_gen_dir = "$root_gen_dir/content/browser/tracing"
tracing_grd = "$tracing_gen_dir/tracing_resources.grd"
action("generate_tracing_grd") {
- visibility = [ ":*" ]
+ visibility = [ ":*" ] # Depend on ":resources" to get this.
script = "generate_trace_viewer_grd.py"
input_pages = [
diff --git a/chromium/content/browser/tracing/DEPS b/chromium/content/browser/tracing/DEPS
index b99424f6482..982848711e3 100644
--- a/chromium/content/browser/tracing/DEPS
+++ b/chromium/content/browser/tracing/DEPS
@@ -2,4 +2,5 @@ include_rules = [
# Generated by the local tracing_resources.gyp:tracing_resources
"+grit/tracing_resources.h",
"+third_party/zlib/zlib.h",
+ "+tools/battor_agent",
]
diff --git a/chromium/content/browser/tracing/background_tracing_config_impl.cc b/chromium/content/browser/tracing/background_tracing_config_impl.cc
index 32eebe5a715..741e90e912f 100644
--- a/chromium/content/browser/tracing/background_tracing_config_impl.cc
+++ b/chromium/content/browser/tracing/background_tracing_config_impl.cc
@@ -30,6 +30,7 @@ const char kConfigCategoryBenchmarkDeep[] = "BENCHMARK_DEEP";
const char kConfigCategoryBenchmarkGPU[] = "BENCHMARK_GPU";
const char kConfigCategoryBenchmarkIPC[] = "BENCHMARK_IPC";
const char kConfigCategoryBenchmarkStartup[] = "BENCHMARK_STARTUP";
+const char kConfigCategoryBenchmarkBlinkGC[] = "BENCHMARK_BLINK_GC";
const char kConfigCategoryBlinkStyle[] = "BLINK_STYLE";
} // namespace
@@ -54,6 +55,8 @@ std::string BackgroundTracingConfigImpl::CategoryPresetToString(
return kConfigCategoryBenchmarkIPC;
case BackgroundTracingConfigImpl::BENCHMARK_STARTUP:
return kConfigCategoryBenchmarkStartup;
+ case BackgroundTracingConfigImpl::BENCHMARK_BLINK_GC:
+ return kConfigCategoryBenchmarkBlinkGC;
case BackgroundTracingConfigImpl::BLINK_STYLE:
return kConfigCategoryBlinkStyle;
}
@@ -89,6 +92,11 @@ bool BackgroundTracingConfigImpl::StringToCategoryPreset(
return true;
}
+ if (category_preset_string == kConfigCategoryBenchmarkBlinkGC) {
+ *category_preset = BackgroundTracingConfigImpl::BENCHMARK_BLINK_GC;
+ return true;
+ }
+
if (category_preset_string == kConfigCategoryBlinkStyle) {
*category_preset = BackgroundTracingConfigImpl::BLINK_STYLE;
return true;
diff --git a/chromium/content/browser/tracing/background_tracing_config_impl.h b/chromium/content/browser/tracing/background_tracing_config_impl.h
index 841a04711a5..0cee4b198ab 100644
--- a/chromium/content/browser/tracing/background_tracing_config_impl.h
+++ b/chromium/content/browser/tracing/background_tracing_config_impl.h
@@ -30,6 +30,7 @@ class CONTENT_EXPORT BackgroundTracingConfigImpl
BENCHMARK_GPU,
BENCHMARK_IPC,
BENCHMARK_STARTUP,
+ BENCHMARK_BLINK_GC,
BLINK_STYLE
};
diff --git a/chromium/content/browser/tracing/background_tracing_config_unittest.cc b/chromium/content/browser/tracing/background_tracing_config_unittest.cc
index 2b95069a401..901e865e60b 100644
--- a/chromium/content/browser/tracing/background_tracing_config_unittest.cc
+++ b/chromium/content/browser/tracing/background_tracing_config_unittest.cc
@@ -269,6 +269,44 @@ TEST_F(BackgroundTracingConfigTest, PreemptiveConfigFromValidString) {
EXPECT_EQ(config->scenario_name(), "my_awesome_experiment");
}
+TEST_F(BackgroundTracingConfigTest, ValidPreemptiveCategoryToString) {
+ scoped_ptr<BackgroundTracingConfigImpl> config = ReadFromJSONString(
+ "{\"mode\":\"PREEMPTIVE_TRACING_MODE\", \"category\": "
+ "\"BENCHMARK\",\"configs\": [{\"rule\": "
+ "\"MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED\", \"trigger_name\":\"foo\"}]}");
+
+ BackgroundTracingConfigImpl::CategoryPreset categories[] = {
+ BackgroundTracingConfigImpl::BENCHMARK,
+ BackgroundTracingConfigImpl::BENCHMARK_DEEP,
+ BackgroundTracingConfigImpl::BENCHMARK_GPU,
+ BackgroundTracingConfigImpl::BENCHMARK_IPC,
+ BackgroundTracingConfigImpl::BENCHMARK_STARTUP,
+ BackgroundTracingConfigImpl::BENCHMARK_BLINK_GC,
+ BackgroundTracingConfigImpl::BLINK_STYLE,
+ };
+
+ const char* category_strings[] = {"BENCHMARK", "BENCHMARK_DEEP",
+ "BENCHMARK_GPU", "BENCHMARK_IPC",
+ "BENCHMARK_STARTUP", "BENCHMARK_BLINK_GC",
+ "BLINK_STYLE"};
+ for (size_t i = 0;
+ i <
+ sizeof(categories) / sizeof(BackgroundTracingConfigImpl::CategoryPreset);
+ i++) {
+ config->set_category_preset(categories[i]);
+ std::string expected =
+ std::string("{\"category\":\"") + category_strings[i] +
+ std::string(
+ "\",\"configs\":[{\"rule\":"
+ "\"MONITOR_AND_DUMP_WHEN_TRIGGER_NAMED\",\"trigger_name\":"
+ "\"foo\"}],\"mode\":\"PREEMPTIVE_TRACING_MODE\"}");
+ EXPECT_EQ(ConfigToString(config.get()), expected.c_str());
+ scoped_ptr<BackgroundTracingConfigImpl> config2 =
+ ReadFromJSONString(expected);
+ EXPECT_EQ(config->category_preset(), config2->category_preset());
+ }
+}
+
TEST_F(BackgroundTracingConfigTest, ReactiveConfigFromValidString) {
scoped_ptr<BackgroundTracingConfigImpl> config;
diff --git a/chromium/content/browser/tracing/background_tracing_manager_impl.cc b/chromium/content/browser/tracing/background_tracing_manager_impl.cc
index 250d0fa4c13..ca394886207 100644
--- a/chromium/content/browser/tracing/background_tracing_manager_impl.cc
+++ b/chromium/content/browser/tracing/background_tracing_manager_impl.cc
@@ -188,7 +188,7 @@ bool BackgroundTracingManagerImpl::SetActiveScenario(
}
bool BackgroundTracingManagerImpl::HasActiveScenario() {
- return config_;
+ return !!config_;
}
bool BackgroundTracingManagerImpl::IsTracingForTesting() {
@@ -515,6 +515,8 @@ BackgroundTracingManagerImpl::GetCategoryFilterStringForCategoryPreset(
return "benchmark,toplevel,startup,disabled-by-default-file,"
"disabled-by-default-toplevel.flow,"
"disabled-by-default-ipc.flow";
+ case BackgroundTracingConfigImpl::CategoryPreset::BENCHMARK_BLINK_GC:
+ return "blink_gc,disabled-by-default-blink_gc";
case BackgroundTracingConfigImpl::CategoryPreset::BLINK_STYLE:
return "blink_style";
}
diff --git a/chromium/content/browser/tracing/battor_power_trace_provider.cc b/chromium/content/browser/tracing/battor_power_trace_provider.cc
deleted file mode 100644
index 41e99110381..00000000000
--- a/chromium/content/browser/tracing/battor_power_trace_provider.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/browser/tracing/battor_power_trace_provider.h"
-
-namespace content {
-
-BattorPowerTraceProvider::BattorPowerTraceProvider() {}
-
-BattorPowerTraceProvider::~BattorPowerTraceProvider() {}
-
-bool BattorPowerTraceProvider::IsConnected() {
- return false;
-}
-
-bool BattorPowerTraceProvider::StartTracing() {
- return false;
-}
-
-bool BattorPowerTraceProvider::StopTracing() {
- return false;
-}
-
-void BattorPowerTraceProvider::RecordClockSyncMarker(int sync_id) {}
-
-void BattorPowerTraceProvider::GetLog(std::string* log_str) {
- // Get logs from battor.
- *log_str = "";
-}
-}
diff --git a/chromium/content/browser/tracing/battor_power_trace_provider.h b/chromium/content/browser/tracing/battor_power_trace_provider.h
deleted file mode 100644
index 8a9a5b5e890..00000000000
--- a/chromium/content/browser/tracing/battor_power_trace_provider.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_BROWSER_TRACING_BATTOR_POWER_TRACE_PROVIDER_H_
-#define CONTENT_BROWSER_TRACING_BATTOR_POWER_TRACE_PROVIDER_H_
-
-#include <string>
-
-#include "base/macros.h"
-
-namespace content {
-
-// This class handles the connection with the battor h/w using
-// chrome serial port interfaces.
-// TODO(charliea): port over battor C code.
-class BattorPowerTraceProvider {
- public:
- BattorPowerTraceProvider();
- bool IsConnected();
- bool StartTracing();
- bool StopTracing();
- void RecordClockSyncMarker(int sync_id);
- void GetLog(std::string* log_str);
- ~BattorPowerTraceProvider();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(BattorPowerTraceProvider);
-};
-}
-#endif // CONTENT_BROWSER_TRACING_BATTOR_POWER_TRACE_PROVIDER_H_
diff --git a/chromium/content/browser/tracing/etw_system_event_consumer_win.cc b/chromium/content/browser/tracing/etw_system_event_consumer_win.cc
index 07dfd4db7b8..09d81f7dbbd 100644
--- a/chromium/content/browser/tracing/etw_system_event_consumer_win.cc
+++ b/chromium/content/browser/tracing/etw_system_event_consumer_win.cc
@@ -11,6 +11,7 @@
#include "base/lazy_instance.h"
#include "base/memory/singleton.h"
#include "base/strings/stringprintf.h"
+#include "base/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "base/trace_event/trace_event_impl.h"
#include "content/public/browser/browser_thread.h"
@@ -49,11 +50,16 @@ std::string EtwSystemEventConsumer::GetTraceEventLabel() {
return kETWTraceLabel;
}
-bool EtwSystemEventConsumer::StartAgentTracing(
- const base::trace_event::TraceConfig& trace_config) {
+void EtwSystemEventConsumer::StartAgentTracing(
+ const base::trace_event::TraceConfig& trace_config,
+ const StartAgentTracingCallback& callback) {
// Activate kernel tracing.
- if (!StartKernelSessionTracing())
- return false;
+ if (!StartKernelSessionTracing()) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(callback, GetTracingAgentName(), false /* success */));
+ return;
+ }
// Start the consumer thread and start consuming events.
thread_.Start();
@@ -62,7 +68,9 @@ bool EtwSystemEventConsumer::StartAgentTracing(
base::Bind(&EtwSystemEventConsumer::TraceAndConsumeOnThread,
base::Unretained(this)));
- return true;
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::Bind(callback, GetTracingAgentName(), true /* success */));
}
void EtwSystemEventConsumer::StopAgentTracing(
diff --git a/chromium/content/browser/tracing/etw_system_event_consumer_win.h b/chromium/content/browser/tracing/etw_system_event_consumer_win.h
index 4327365386a..f14a37e623e 100644
--- a/chromium/content/browser/tracing/etw_system_event_consumer_win.h
+++ b/chromium/content/browser/tracing/etw_system_event_consumer_win.h
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/macros.h"
#include "base/memory/ref_counted_memory.h"
+#include "base/memory/scoped_ptr.h"
#include "base/threading/thread.h"
#include "base/trace_event/tracing_agent.h"
#include "base/values.h"
@@ -28,8 +29,8 @@ class EtwSystemEventConsumer
// base::trace_event::TracingAgent implementation.
std::string GetTracingAgentName() override;
std::string GetTraceEventLabel() override;
- bool StartAgentTracing(
- const base::trace_event::TraceConfig& trace_config) override;
+ void StartAgentTracing(const base::trace_event::TraceConfig& trace_config,
+ const StartAgentTracingCallback& callback) override;
void StopAgentTracing(const StopAgentTracingCallback& callback) override;
// Retrieve the ETW consumer instance.
diff --git a/chromium/content/browser/tracing/power_tracing_agent.cc b/chromium/content/browser/tracing/power_tracing_agent.cc
index 6bf47e66bd2..5c0d654afa7 100644
--- a/chromium/content/browser/tracing/power_tracing_agent.cc
+++ b/chromium/content/browser/tracing/power_tracing_agent.cc
@@ -2,12 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/memory/singleton.h"
+#include "base/thread_task_runner_handle.h"
#include "base/trace_event/trace_event_impl.h"
-#include "content/browser/tracing/battor_power_trace_provider.h"
#include "content/browser/tracing/power_tracing_agent.h"
-#include "content/public/browser/browser_thread.h"
+#include "tools/battor_agent/battor_finder.h"
namespace content {
@@ -23,10 +24,7 @@ PowerTracingAgent* PowerTracingAgent::GetInstance() {
return base::Singleton<PowerTracingAgent>::get();
}
-PowerTracingAgent::PowerTracingAgent() : thread_("PowerTracingAgentThread") {
- battor_trace_provider_.reset(new BattorPowerTraceProvider());
-}
-
+PowerTracingAgent::PowerTracingAgent() {}
PowerTracingAgent::~PowerTracingAgent() {}
std::string PowerTracingAgent::GetTracingAgentName() {
@@ -37,103 +35,151 @@ std::string PowerTracingAgent::GetTraceEventLabel() {
return kPowerTraceLabel;
}
-bool PowerTracingAgent::StartAgentTracing(
- const base::trace_event::TraceConfig& trace_config) {
+void PowerTracingAgent::StartAgentTracing(
+ const base::trace_event::TraceConfig& trace_config,
+ const StartAgentTracingCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- // TODO(charliea): When system tracing is enabled in about://tracing, it will
- // trigger power tracing. We need a way of checking if BattOr is connected.
- // Currently, IsConnected() always returns false, so that we do not include
- // BattOr trace until it is hooked up.
- if (!battor_trace_provider_->IsConnected())
- return false;
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(&PowerTracingAgent::FindBattOrOnFileThread,
+ base::Unretained(this), callback));
+}
+
+void PowerTracingAgent::FindBattOrOnFileThread(
+ const StartAgentTracingCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::FILE);
- thread_.Start();
+ std::string path = battor::BattOrFinder::FindBattOr();
+ if (path.empty()) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(callback, GetTracingAgentName(), false /* success */));
+ return;
+ }
- thread_.task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&PowerTracingAgent::TraceOnThread, base::Unretained(this)));
- return true;
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&PowerTracingAgent::StartAgentTracingOnIOThread,
+ base::Unretained(this), path, callback));
}
-void PowerTracingAgent::StopAgentTracing(
- const StopAgentTracingCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(thread_.IsRunning());
+void PowerTracingAgent::StartAgentTracingOnIOThread(
+ const std::string& path,
+ const StartAgentTracingCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
- thread_.task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&PowerTracingAgent::FlushOnThread, base::Unretained(this),
- callback));
+ battor_agent_.reset(new battor::BattOrAgent(
+ path, this,
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE),
+ BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI)));
+
+ start_tracing_callback_ = callback;
+ battor_agent_->StartTracing();
}
-void PowerTracingAgent::OnStopTracingDone(
- const StopAgentTracingCallback& callback,
- const scoped_refptr<base::RefCountedString>& result) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
+void PowerTracingAgent::OnStartTracingComplete(battor::BattOrError error) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
- // Pass the serialized events.
- callback.Run(GetTracingAgentName(), GetTraceEventLabel(), result);
+ bool success = (error == battor::BATTOR_ERROR_NONE);
+ if (!success)
+ battor_agent_.reset();
- // Stop the power tracing agent thread on file thread.
BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&base::Thread::Stop, base::Unretained(&thread_)));
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(start_tracing_callback_, GetTracingAgentName(), success));
+ start_tracing_callback_.Reset();
}
-void PowerTracingAgent::TraceOnThread() {
- DCHECK(thread_.task_runner()->BelongsToCurrentThread());
- battor_trace_provider_->StartTracing();
+void PowerTracingAgent::StopAgentTracing(
+ const StopAgentTracingCallback& callback) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&PowerTracingAgent::StopAgentTracingOnIOThread,
+ base::Unretained(this), callback));
}
-void PowerTracingAgent::FlushOnThread(
+void PowerTracingAgent::StopAgentTracingOnIOThread(
const StopAgentTracingCallback& callback) {
- DCHECK(thread_.task_runner()->BelongsToCurrentThread());
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ if (!battor_agent_) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(callback, GetTracingAgentName(), GetTraceEventLabel(),
+ nullptr /* events_str_ptr */));
+ return;
+ }
+
+ stop_tracing_callback_ = callback;
+ battor_agent_->StopTracing();
+}
+
+void PowerTracingAgent::OnStopTracingComplete(const std::string& trace,
+ battor::BattOrError error) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ scoped_refptr<base::RefCountedString> result(new base::RefCountedString());
+ if (error == battor::BATTOR_ERROR_NONE)
+ result->data() = trace;
- battor_trace_provider_->StopTracing();
- std::string battor_logs;
- battor_trace_provider_->GetLog(&battor_logs);
- scoped_refptr<base::RefCountedString> result =
- base::RefCountedString::TakeString(&battor_logs);
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(&PowerTracingAgent::OnStopTracingDone,
- base::Unretained(this),
- callback,
- result));
-}
-
-bool PowerTracingAgent::SupportsExplicitClockSync() {
- return true;
+ base::Bind(stop_tracing_callback_, GetTracingAgentName(),
+ GetTraceEventLabel(), result));
+ stop_tracing_callback_.Reset();
+ battor_agent_.reset();
}
void PowerTracingAgent::RecordClockSyncMarker(
- int sync_id,
+ const std::string& sync_id,
const RecordClockSyncMarkerCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(SupportsExplicitClockSync());
- thread_.task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&PowerTracingAgent::RecordClockSyncMarkerOnThread,
- base::Unretained(this),
- sync_id,
- callback));
+ BrowserThread::PostTask(
+ BrowserThread::IO, FROM_HERE,
+ base::Bind(&PowerTracingAgent::RecordClockSyncMarkerOnIOThread,
+ base::Unretained(this), sync_id, callback));
}
-void PowerTracingAgent::RecordClockSyncMarkerOnThread(
- int sync_id,
+void PowerTracingAgent::RecordClockSyncMarkerOnIOThread(
+ const std::string& sync_id,
const RecordClockSyncMarkerCallback& callback) {
- DCHECK(thread_.task_runner()->BelongsToCurrentThread());
- DCHECK(SupportsExplicitClockSync());
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ DCHECK(battor_agent_);
- base::TimeTicks issue_ts = base::TimeTicks::Now();
- battor_trace_provider_->RecordClockSyncMarker(sync_id);
+ record_clock_sync_marker_sync_id_ = sync_id;
+ record_clock_sync_marker_callback_ = callback;
+ record_clock_sync_marker_start_time_ = base::TimeTicks::Now();
+ battor_agent_->RecordClockSyncMarker(sync_id);
+}
+
+void PowerTracingAgent::OnRecordClockSyncMarkerComplete(
+ battor::BattOrError error) {
+ DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+ base::TimeTicks issue_start_ts = record_clock_sync_marker_start_time_;
base::TimeTicks issue_end_ts = base::TimeTicks::Now();
+ if (error != battor::BATTOR_ERROR_NONE)
+ issue_start_ts = issue_end_ts = base::TimeTicks();
+
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
- base::Bind(callback, sync_id, issue_ts, issue_end_ts));
+ base::Bind(record_clock_sync_marker_callback_,
+ record_clock_sync_marker_sync_id_,
+ issue_start_ts,
+ issue_end_ts));
+
+ record_clock_sync_marker_callback_.Reset();
+ record_clock_sync_marker_sync_id_ = std::string();
+ record_clock_sync_marker_start_time_ = base::TimeTicks();
+}
+
+bool PowerTracingAgent::SupportsExplicitClockSync() {
+ return battor_agent_->SupportsExplicitClockSync();
}
} // namespace content
diff --git a/chromium/content/browser/tracing/power_tracing_agent.h b/chromium/content/browser/tracing/power_tracing_agent.h
index 58c6a87d02c..0fa97fe5dd5 100644
--- a/chromium/content/browser/tracing/power_tracing_agent.h
+++ b/chromium/content/browser/tracing/power_tracing_agent.h
@@ -7,8 +7,12 @@
#include "base/macros.h"
#include "base/memory/ref_counted_memory.h"
+#include "base/memory/scoped_ptr.h"
#include "base/threading/thread.h"
#include "base/trace_event/tracing_agent.h"
+#include "content/public/browser/browser_thread.h"
+#include "tools/battor_agent/battor_agent.h"
+#include "tools/battor_agent/battor_error.h"
namespace base {
template <typename Type>
@@ -17,46 +21,61 @@ struct DefaultSingletonTraits;
namespace content {
-class BattorPowerTraceProvider;
-
-class PowerTracingAgent : public base::trace_event::TracingAgent {
+class PowerTracingAgent : public base::trace_event::TracingAgent,
+ public battor::BattOrAgent::Listener {
public:
// Retrieve the singleton instance.
static PowerTracingAgent* GetInstance();
+ void StartAgentTracing(const base::trace_event::TraceConfig& trace_config,
+ const StartAgentTracingCallback& callback) override;
+ void StopAgentTracing(const StopAgentTracingCallback& callback) override;
+ void RecordClockSyncMarker(
+ const std::string& sync_id,
+ const RecordClockSyncMarkerCallback& callback) override;
+
+ bool SupportsExplicitClockSync() override;
+
// base::trace_event::TracingAgent implementation.
std::string GetTracingAgentName() override;
std::string GetTraceEventLabel() override;
- bool StartAgentTracing(
- const base::trace_event::TraceConfig& trace_config) override;
- void StopAgentTracing(const StopAgentTracingCallback& callback) override;
-
- bool SupportsExplicitClockSync() override;
- void RecordClockSyncMarker(
- int sync_id,
- const RecordClockSyncMarkerCallback& callback) override;
+ // BattOrAgent::Listener implementation.
+ void OnStartTracingComplete(battor::BattOrError error) override;
+ void OnStopTracingComplete(const std::string& trace,
+ battor::BattOrError error) override;
+ void OnRecordClockSyncMarkerComplete(battor::BattOrError error) override;
private:
// This allows constructor and destructor to be private and usable only
// by the Singleton class.
friend struct base::DefaultSingletonTraits<PowerTracingAgent>;
- // Constructor.
PowerTracingAgent();
~PowerTracingAgent() override;
- void OnStopTracingDone(const StopAgentTracingCallback& callback,
- const scoped_refptr<base::RefCountedString>& result);
-
- void TraceOnThread();
- void FlushOnThread(const StopAgentTracingCallback& callback);
- void RecordClockSyncMarkerOnThread(
- int sync_id,
+ void FindBattOrOnFileThread(const StartAgentTracingCallback& callback);
+ void StartAgentTracingOnIOThread(const std::string& path,
+ const StartAgentTracingCallback& callback);
+ void StopAgentTracingOnIOThread(const StopAgentTracingCallback& callback);
+ void RecordClockSyncMarkerOnIOThread(
+ const std::string& sync_id,
const RecordClockSyncMarkerCallback& callback);
- base::Thread thread_;
- scoped_ptr<BattorPowerTraceProvider> battor_trace_provider_;
+ // Returns the path of a BattOr (e.g. /dev/ttyUSB0), or an empty string if
+ // none are found.
+ std::string GetBattOrPath();
+
+ // All interactions with the BattOrAgent (after construction) must happen on
+ // the IO thread.
+ scoped_ptr<battor::BattOrAgent, BrowserThread::DeleteOnIOThread>
+ battor_agent_;
+
+ StartAgentTracingCallback start_tracing_callback_;
+ StopAgentTracingCallback stop_tracing_callback_;
+ std::string record_clock_sync_marker_sync_id_;
+ base::TimeTicks record_clock_sync_marker_start_time_;
+ RecordClockSyncMarkerCallback record_clock_sync_marker_callback_;
DISALLOW_COPY_AND_ASSIGN(PowerTracingAgent);
};
diff --git a/chromium/content/browser/tracing/trace_message_filter.cc b/chromium/content/browser/tracing/trace_message_filter.cc
index 45cb7023379..d9168e718bb 100644
--- a/chromium/content/browser/tracing/trace_message_filter.cc
+++ b/chromium/content/browser/tracing/trace_message_filter.cc
@@ -18,7 +18,6 @@ TraceMessageFilter::TraceMessageFilter(int child_process_id)
ChildProcessHostImpl::ChildProcessUniqueIdToTracingProcessId(
child_process_id)),
is_awaiting_end_ack_(false),
- is_awaiting_capture_monitoring_snapshot_ack_(false),
is_awaiting_buffer_percent_full_ack_(false) {
}
@@ -29,9 +28,6 @@ void TraceMessageFilter::OnChannelClosing() {
if (is_awaiting_end_ack_)
OnEndTracingAck(std::vector<std::string>());
- if (is_awaiting_capture_monitoring_snapshot_ack_)
- OnCaptureMonitoringSnapshotAcked();
-
if (is_awaiting_buffer_percent_full_ack_)
OnTraceLogStatusReply(base::trace_event::TraceLogStatus());
@@ -46,12 +42,8 @@ bool TraceMessageFilter::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(TracingHostMsg_ChildSupportsTracing,
OnChildSupportsTracing)
IPC_MESSAGE_HANDLER(TracingHostMsg_EndTracingAck, OnEndTracingAck)
- IPC_MESSAGE_HANDLER(TracingHostMsg_CaptureMonitoringSnapshotAck,
- OnCaptureMonitoringSnapshotAcked)
IPC_MESSAGE_HANDLER(TracingHostMsg_TraceDataCollected,
OnTraceDataCollected)
- IPC_MESSAGE_HANDLER(TracingHostMsg_MonitoringTraceDataCollected,
- OnMonitoringTraceDataCollected)
IPC_MESSAGE_HANDLER(TracingHostMsg_WatchEventMatched,
OnWatchEventMatched)
IPC_MESSAGE_HANDLER(TracingHostMsg_TraceLogStatusReply,
@@ -90,25 +82,6 @@ void TraceMessageFilter::SendCancelTracing() {
Send(new TracingMsg_CancelTracing);
}
-void TraceMessageFilter::SendStartMonitoring(
- const base::trace_event::TraceConfig& trace_config) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- Send(new TracingMsg_StartMonitoring(trace_config.ToString(),
- base::TimeTicks::Now()));
-}
-
-void TraceMessageFilter::SendStopMonitoring() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- Send(new TracingMsg_StopMonitoring);
-}
-
-void TraceMessageFilter::SendCaptureMonitoringSnapshot() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- DCHECK(!is_awaiting_capture_monitoring_snapshot_ack_);
- is_awaiting_capture_monitoring_snapshot_ack_ = true;
- Send(new TracingMsg_CaptureMonitoringSnapshot);
-}
-
void TraceMessageFilter::SendGetTraceLogStatus() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(!is_awaiting_buffer_percent_full_ack_);
@@ -155,32 +128,12 @@ void TraceMessageFilter::OnEndTracingAck(
}
}
-void TraceMessageFilter::OnCaptureMonitoringSnapshotAcked() {
- // is_awaiting_capture_monitoring_snapshot_ack_ should always be true here,
- // but check in case the child process is compromised.
- if (is_awaiting_capture_monitoring_snapshot_ack_) {
- is_awaiting_capture_monitoring_snapshot_ack_ = false;
- TracingControllerImpl::GetInstance()->OnCaptureMonitoringSnapshotAcked(
- this);
- } else {
- NOTREACHED();
- }
-}
-
void TraceMessageFilter::OnTraceDataCollected(const std::string& data) {
scoped_refptr<base::RefCountedString> data_ptr(new base::RefCountedString());
data_ptr->data() = data;
TracingControllerImpl::GetInstance()->OnTraceDataCollected(data_ptr);
}
-void TraceMessageFilter::OnMonitoringTraceDataCollected(
- const std::string& data) {
- scoped_refptr<base::RefCountedString> data_ptr(new base::RefCountedString());
- data_ptr->data() = data;
- TracingControllerImpl::GetInstance()->OnMonitoringTraceDataCollected(
- data_ptr);
-}
-
void TraceMessageFilter::OnWatchEventMatched() {
TracingControllerImpl::GetInstance()->OnWatchEventMatched();
}
diff --git a/chromium/content/browser/tracing/trace_message_filter.h b/chromium/content/browser/tracing/trace_message_filter.h
index 22d91d914ad..94c435ed1b6 100644
--- a/chromium/content/browser/tracing/trace_message_filter.h
+++ b/chromium/content/browser/tracing/trace_message_filter.h
@@ -32,10 +32,6 @@ class TraceMessageFilter : public BrowserMessageFilter {
const base::trace_event::TraceConfig& trace_config);
void SendEndTracing();
void SendCancelTracing();
- void SendStartMonitoring(
- const base::trace_event::TraceConfig& trace_config);
- void SendStopMonitoring();
- void SendCaptureMonitoringSnapshot();
void SendGetTraceLogStatus();
void SendSetWatchEvent(const std::string& category_name,
const std::string& event_name);
@@ -50,11 +46,9 @@ class TraceMessageFilter : public BrowserMessageFilter {
// Message handlers.
void OnChildSupportsTracing();
void OnEndTracingAck(const std::vector<std::string>& known_categories);
- void OnCaptureMonitoringSnapshotAcked();
void OnWatchEventMatched();
void OnTraceLogStatusReply(const base::trace_event::TraceLogStatus& status);
void OnTraceDataCollected(const std::string& data);
- void OnMonitoringTraceDataCollected(const std::string& data);
void OnGlobalMemoryDumpRequest(
const base::trace_event::MemoryDumpRequestArgs& args);
void OnProcessMemoryDumpResponse(uint64_t dump_guid, bool success);
@@ -71,8 +65,6 @@ class TraceMessageFilter : public BrowserMessageFilter {
// Awaiting ack for previously sent SendEndTracing
bool is_awaiting_end_ack_;
- // Awaiting ack for previously sent SendCaptureMonitoringSnapshot
- bool is_awaiting_capture_monitoring_snapshot_ack_;
// Awaiting ack for previously sent SendGetTraceLogStatus
bool is_awaiting_buffer_percent_full_ack_;
diff --git a/chromium/content/browser/tracing/tracing_controller_browsertest.cc b/chromium/content/browser/tracing/tracing_controller_browsertest.cc
index d4b8671d915..8cafbd7df88 100644
--- a/chromium/content/browser/tracing/tracing_controller_browsertest.cc
+++ b/chromium/content/browser/tracing/tracing_controller_browsertest.cc
@@ -80,7 +80,7 @@ class TracingControllerTestEndpoint
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(done_callback_, base::Passed(std::move(metadata)),
- chunk_ptr));
+ base::RetainedRef(chunk_ptr)));
}
protected:
@@ -99,9 +99,6 @@ class TracingControllerTest : public ContentBrowserTest {
get_categories_done_callback_count_ = 0;
enable_recording_done_callback_count_ = 0;
disable_recording_done_callback_count_ = 0;
- enable_monitoring_done_callback_count_ = 0;
- disable_monitoring_done_callback_count_ = 0;
- capture_monitoring_snapshot_done_callback_count_ = 0;
ContentBrowserTest::SetUp();
}
@@ -145,28 +142,7 @@ class TracingControllerTest : public ContentBrowserTest {
last_actual_recording_file_path_ = file_path;
}
- void StartMonitoringDoneCallbackTest(base::Closure quit_callback) {
- enable_monitoring_done_callback_count_++;
- quit_callback.Run();
- }
-
- void StopMonitoringDoneCallbackTest(base::Closure quit_callback) {
- disable_monitoring_done_callback_count_++;
- quit_callback.Run();
- }
-
- void CaptureMonitoringSnapshotDoneCallbackTest(
- base::Closure quit_callback, const base::FilePath& file_path) {
- capture_monitoring_snapshot_done_callback_count_++;
- EXPECT_TRUE(PathExists(file_path));
- int64_t file_size;
- base::GetFileSize(file_path, &file_size);
- EXPECT_TRUE(file_size > 0);
- quit_callback.Run();
- last_actual_monitoring_file_path_ = file_path;
- }
-
- int get_categories_done_callback_count() const {
+ int get_categories_done_callback_count() const {
return get_categories_done_callback_count_;
}
@@ -178,26 +154,10 @@ class TracingControllerTest : public ContentBrowserTest {
return disable_recording_done_callback_count_;
}
- int enable_monitoring_done_callback_count() const {
- return enable_monitoring_done_callback_count_;
- }
-
- int disable_monitoring_done_callback_count() const {
- return disable_monitoring_done_callback_count_;
- }
-
- int capture_monitoring_snapshot_done_callback_count() const {
- return capture_monitoring_snapshot_done_callback_count_;
- }
-
base::FilePath last_actual_recording_file_path() const {
return last_actual_recording_file_path_;
}
- base::FilePath last_actual_monitoring_file_path() const {
- return last_actual_monitoring_file_path_;
- }
-
const base::DictionaryValue* last_metadata() const {
return last_metadata_.get();
}
@@ -382,96 +342,11 @@ class TracingControllerTest : public ContentBrowserTest {
}
}
- void TestEnableCaptureAndStopMonitoring(
- const base::FilePath& result_file_path) {
- Navigate(shell());
-
- TracingController* controller = TracingController::GetInstance();
-
- {
- bool is_monitoring;
- TraceConfig trace_config("", "");
- controller->GetMonitoringStatus(
- &is_monitoring, &trace_config);
- EXPECT_FALSE(is_monitoring);
- EXPECT_EQ("-*Debug,-*Test", trace_config.ToCategoryFilterString());
- EXPECT_FALSE(trace_config.GetTraceRecordMode() == RECORD_CONTINUOUSLY);
- EXPECT_FALSE(trace_config.IsSamplingEnabled());
- EXPECT_FALSE(trace_config.IsSystraceEnabled());
- }
-
- {
- base::RunLoop run_loop;
- TracingController::StartMonitoringDoneCallback callback =
- base::Bind(&TracingControllerTest::StartMonitoringDoneCallbackTest,
- base::Unretained(this),
- run_loop.QuitClosure());
-
- TraceConfig trace_config("*", "");
- trace_config.EnableSampling();
- bool result = controller->StartMonitoring(trace_config, callback);
- ASSERT_TRUE(result);
- run_loop.Run();
- EXPECT_EQ(enable_monitoring_done_callback_count(), 1);
- }
-
- {
- bool is_monitoring;
- TraceConfig trace_config("", "");
- controller->GetMonitoringStatus(&is_monitoring, &trace_config);
- EXPECT_TRUE(is_monitoring);
- EXPECT_EQ("*", trace_config.ToCategoryFilterString());
- EXPECT_FALSE(trace_config.GetTraceRecordMode() == RECORD_CONTINUOUSLY);
- EXPECT_TRUE(trace_config.IsSamplingEnabled());
- EXPECT_FALSE(trace_config.IsSystraceEnabled());
- }
-
- {
- base::RunLoop run_loop;
- base::Closure callback = base::Bind(
- &TracingControllerTest::CaptureMonitoringSnapshotDoneCallbackTest,
- base::Unretained(this),
- run_loop.QuitClosure(),
- result_file_path);
- ASSERT_TRUE(controller->CaptureMonitoringSnapshot(
- TracingController::CreateFileSink(result_file_path, callback)));
- run_loop.Run();
- EXPECT_EQ(capture_monitoring_snapshot_done_callback_count(), 1);
- }
-
- {
- base::RunLoop run_loop;
- TracingController::StopMonitoringDoneCallback callback =
- base::Bind(&TracingControllerTest::StopMonitoringDoneCallbackTest,
- base::Unretained(this),
- run_loop.QuitClosure());
- bool result = controller->StopMonitoring(callback);
- ASSERT_TRUE(result);
- run_loop.Run();
- EXPECT_EQ(disable_monitoring_done_callback_count(), 1);
- }
-
- {
- bool is_monitoring;
- TraceConfig trace_config("", "");
- controller->GetMonitoringStatus(&is_monitoring, &trace_config);
- EXPECT_FALSE(is_monitoring);
- EXPECT_EQ("", trace_config.ToCategoryFilterString());
- EXPECT_FALSE(trace_config.GetTraceRecordMode() == RECORD_CONTINUOUSLY);
- EXPECT_FALSE(trace_config.IsSamplingEnabled());
- EXPECT_FALSE(trace_config.IsSystraceEnabled());
- }
- }
-
private:
int get_categories_done_callback_count_;
int enable_recording_done_callback_count_;
int disable_recording_done_callback_count_;
- int enable_monitoring_done_callback_count_;
- int disable_monitoring_done_callback_count_;
- int capture_monitoring_snapshot_done_callback_count_;
base::FilePath last_actual_recording_file_path_;
- base::FilePath last_actual_monitoring_file_path_;
scoped_ptr<const base::DictionaryValue> last_metadata_;
std::string last_data_;
};
@@ -585,45 +460,4 @@ IN_PROC_BROWSER_TEST_F(TracingControllerTest,
base::RunLoop().RunUntilIdle();
}
-IN_PROC_BROWSER_TEST_F(TracingControllerTest,
- EnableCaptureAndStopMonitoring) {
- base::FilePath file_path;
- base::CreateTemporaryFile(&file_path);
- TestEnableCaptureAndStopMonitoring(file_path);
-}
-
-IN_PROC_BROWSER_TEST_F(TracingControllerTest,
- EnableCaptureAndStopMonitoringWithFilePath) {
- base::FilePath file_path;
- base::CreateTemporaryFile(&file_path);
- TestEnableCaptureAndStopMonitoring(file_path);
- EXPECT_EQ(file_path.value(), last_actual_monitoring_file_path().value());
-}
-
-// See http://crbug.com/392446
-#if defined(OS_ANDROID)
-#define MAYBE_EnableCaptureAndStopMonitoringWithEmptyFileAndNullCallback \
- DISABLED_EnableCaptureAndStopMonitoringWithEmptyFileAndNullCallback
-#else
-#define MAYBE_EnableCaptureAndStopMonitoringWithEmptyFileAndNullCallback \
- EnableCaptureAndStopMonitoringWithEmptyFileAndNullCallback
-#endif
-IN_PROC_BROWSER_TEST_F(
- TracingControllerTest,
- MAYBE_EnableCaptureAndStopMonitoringWithEmptyFileAndNullCallback) {
- Navigate(shell());
-
- TracingController* controller = TracingController::GetInstance();
- TraceConfig trace_config("*", "");
- trace_config.EnableSampling();
- EXPECT_TRUE(controller->StartMonitoring(
- trace_config,
- TracingController::StartMonitoringDoneCallback()));
- controller->CaptureMonitoringSnapshot(NULL);
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(controller->StopMonitoring(
- TracingController::StopMonitoringDoneCallback()));
- base::RunLoop().RunUntilIdle();
-}
-
} // namespace content
diff --git a/chromium/content/browser/tracing/tracing_controller_impl.cc b/chromium/content/browser/tracing/tracing_controller_impl.cc
index 684bea8ec49..06ef7c8f04b 100644
--- a/chromium/content/browser/tracing/tracing_controller_impl.cc
+++ b/chromium/content/browser/tracing/tracing_controller_impl.cc
@@ -6,14 +6,18 @@
#include "base/bind.h"
#include "base/cpu.h"
#include "base/files/file_util.h"
+#include "base/guid.h"
#include "base/json/string_escape.h"
#include "base/macros.h"
+#include "base/memory/ref_counted_memory.h"
#include "base/strings/string_number_conversions.h"
#include "base/sys_info.h"
+#include "base/thread_task_runner_handle.h"
+#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
+#include "components/tracing/process_metrics_memory_dump_provider.h"
#include "content/browser/tracing/file_tracing_provider_impl.h"
-#include "content/browser/tracing/power_tracing_agent.h"
#include "content/browser/tracing/trace_message_filter.h"
#include "content/browser/tracing/tracing_ui.h"
#include "content/common/child_process_messages.h"
@@ -27,6 +31,15 @@
#include "gpu/config/gpu_info.h"
#include "net/base/network_change_notifier.h"
+#if (defined(OS_POSIX) && defined(USE_UDEV)) || defined(OS_WIN) || \
+ defined(OS_MACOSX)
+#define ENABLE_POWER_TRACING
+#endif
+
+#if defined(ENABLE_POWER_TRACING)
+#include "content/browser/tracing/power_tracing_agent.h"
+#endif
+
#if defined(OS_CHROMEOS)
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/debug_daemon_client.h"
@@ -50,7 +63,9 @@ const char kChromeTracingAgentName[] = "chrome";
const char kETWTracingAgentName[] = "etw";
const char kChromeTraceLabel[] = "traceEvents";
-const int kIssueClockSyncTimeout = 30;
+const int kStartTracingTimeoutSeconds = 30;
+const int kIssueClockSyncTimeoutSeconds = 30;
+const int kStopTracingRetryTimeMilliseconds = 100;
std::string GetNetworkTypeString() {
switch (net::NetworkChangeNotifier::GetConnectionType()) {
@@ -75,6 +90,24 @@ std::string GetNetworkTypeString() {
return "Unknown";
}
+std::string GetClockString() {
+ switch (base::TimeTicks::GetClock()) {
+ case base::TimeTicks::Clock::LINUX_CLOCK_MONOTONIC:
+ return "LINUX_CLOCK_MONOTONIC";
+ case base::TimeTicks::Clock::IOS_CF_ABSOLUTE_TIME_MINUS_KERN_BOOTTIME:
+ return "IOS_CF_ABSOLUTE_TIME_MINUS_KERN_BOOTTIME";
+ case base::TimeTicks::Clock::MAC_MACH_ABSOLUTE_TIME:
+ return "MAC_MACH_ABSOLUTE_TIME";
+ case base::TimeTicks::Clock::WIN_QPC:
+ return "WIN_QPC";
+ case base::TimeTicks::Clock::WIN_ROLLOVER_PROTECTED_TIME_GET_TIME:
+ return "WIN_ROLLOVER_PROTECTED_TIME_GET_TIME";
+ }
+
+ NOTREACHED();
+ return std::string();
+}
+
scoped_ptr<base::DictionaryValue> GenerateTracingMetadataDict() {
scoped_ptr<base::DictionaryValue> metadata_dict(new base::DictionaryValue());
@@ -130,7 +163,7 @@ scoped_ptr<base::DictionaryValue> GenerateTracingMetadataDict() {
if (delegate)
delegate->GenerateMetadataDict(metadata_dict.get());
- // Highres ticks.
+ metadata_dict->SetString("clock-domain", GetClockString());
metadata_dict->SetBoolean("highres-ticks",
base::TimeTicks::IsHighResolution());
@@ -144,17 +177,15 @@ TracingController* TracingController::GetInstance() {
}
TracingControllerImpl::TracingControllerImpl()
- : pending_stop_tracing_ack_count_(0),
- pending_capture_monitoring_snapshot_ack_count_(0),
+ : pending_start_tracing_ack_count_(0),
+ pending_stop_tracing_ack_count_(0),
pending_trace_log_status_ack_count_(0),
maximum_trace_buffer_usage_(0),
approximate_event_count_(0),
pending_memory_dump_ack_count_(0),
failed_memory_dump_count_(0),
- clock_sync_id_(0),
pending_clock_sync_ack_count_(0),
- is_tracing_(false),
- is_monitoring_(false) {
+ is_tracing_(false) {
base::trace_event::MemoryDumpManager::GetInstance()->Initialize(
this /* delegate */, true /* is_coordinator */);
@@ -218,6 +249,9 @@ bool TracingControllerImpl::StartTracing(
return false;
is_tracing_ = true;
start_tracing_done_callback_ = callback;
+ start_tracing_trace_config_.reset(
+ new base::trace_event::TraceConfig(trace_config));
+ pending_start_tracing_ack_count_ = 0;
#if defined(OS_ANDROID)
if (pending_get_categories_done_callback_.is_null())
@@ -225,56 +259,92 @@ bool TracingControllerImpl::StartTracing(
#endif
if (trace_config.IsSystraceEnabled()) {
- if (PowerTracingAgent::GetInstance()->StartAgentTracing(trace_config))
- additional_tracing_agents_.push_back(PowerTracingAgent::GetInstance());
+#if defined(ENABLE_POWER_TRACING)
+ PowerTracingAgent::GetInstance()->StartAgentTracing(
+ trace_config,
+ base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked,
+ base::Unretained(this)));
+ ++pending_start_tracing_ack_count_;
+#endif
+
#if defined(OS_CHROMEOS)
chromeos::DebugDaemonClient* debug_daemon =
chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
- if (debug_daemon && debug_daemon->StartAgentTracing(trace_config)) {
- debug_daemon->SetStopAgentTracingTaskRunner(
- BrowserThread::GetBlockingPool());
- additional_tracing_agents_.push_back(
- chromeos::DBusThreadManager::Get()->GetDebugDaemonClient());
+ if (debug_daemon) {
+ debug_daemon->StartAgentTracing(
+ trace_config,
+ base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked,
+ base::Unretained(this)));
+ ++pending_start_tracing_ack_count_;
}
#elif defined(OS_WIN)
- if (EtwSystemEventConsumer::GetInstance()->StartAgentTracing(
- trace_config)) {
- additional_tracing_agents_.push_back(
- EtwSystemEventConsumer::GetInstance());
- }
+ EtwSystemEventConsumer::GetInstance()->StartAgentTracing(
+ trace_config,
+ base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked,
+ base::Unretained(this)));
+ ++pending_start_tracing_ack_count_;
#endif
}
// TraceLog may have been enabled in startup tracing before threads are ready.
if (TraceLog::GetInstance()->IsEnabled())
return true;
- return StartAgentTracing(trace_config);
+
+ StartAgentTracing(trace_config,
+ base::Bind(&TracingControllerImpl::OnStartAgentTracingAcked,
+ base::Unretained(this)));
+ ++pending_start_tracing_ack_count_;
+
+ // Set a deadline to ensure all agents ack within a reasonable time frame.
+ start_tracing_timer_.Start(
+ FROM_HERE, base::TimeDelta::FromSeconds(kStartTracingTimeoutSeconds),
+ base::Bind(&TracingControllerImpl::OnAllTracingAgentsStarted,
+ base::Unretained(this)));
+
+ return true;
}
-void TracingControllerImpl::OnStartAgentTracingDone(
- const TraceConfig& trace_config,
- const StartTracingDoneCallback& callback) {
+void TracingControllerImpl::OnAllTracingAgentsStarted() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- TRACE_EVENT_API_ADD_METADATA_EVENT("IsTimeTicksHighResolution", "value",
- base::TimeTicks::IsHighResolution());
- TRACE_EVENT_API_ADD_METADATA_EVENT("TraceConfig", "value",
- trace_config.AsConvertableToTraceFormat());
+ TRACE_EVENT_API_ADD_METADATA_EVENT(
+ TraceLog::GetCategoryGroupEnabled("__metadata"),
+ "IsTimeTicksHighResolution", "value",
+ base::TimeTicks::IsHighResolution());
+ TRACE_EVENT_API_ADD_METADATA_EVENT(
+ TraceLog::GetCategoryGroupEnabled("__metadata"), "TraceConfig", "value",
+ start_tracing_trace_config_->AsConvertableToTraceFormat());
// Notify all child processes.
for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
it != trace_message_filters_.end(); ++it) {
- it->get()->SendBeginTracing(trace_config);
+ it->get()->SendBeginTracing(*start_tracing_trace_config_);
}
- if (!callback.is_null())
- callback.Run();
+ if (!start_tracing_done_callback_.is_null())
+ start_tracing_done_callback_.Run();
+
+ start_tracing_done_callback_.Reset();
+ start_tracing_trace_config_.reset();
}
bool TracingControllerImpl::StopTracing(
const scoped_refptr<TraceDataSink>& trace_data_sink) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
+ if (!can_stop_tracing())
+ return false;
+
+ // If we're still waiting to start tracing, try again after a delay.
+ if (start_tracing_timer_.IsRunning()) {
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(base::IgnoreResult(&TracingControllerImpl::StopTracing),
+ base::Unretained(this), trace_data_sink),
+ base::TimeDelta::FromMilliseconds(kStopTracingRetryTimeMilliseconds));
+ return true;
+ }
+
if (trace_data_sink) {
if (TraceLog::GetInstance()->GetCurrentTraceConfig()
.IsArgumentFilterEnabled()) {
@@ -288,9 +358,6 @@ bool TracingControllerImpl::StopTracing(
trace_data_sink->AddMetadata(*GenerateTracingMetadataDict().get());
}
- if (!can_stop_tracing())
- return false;
-
trace_data_sink_ = trace_data_sink;
// Issue clock sync marker before actually stopping tracing.
@@ -340,134 +407,6 @@ void TracingControllerImpl::OnStopTracingDone() {
StopAgentTracing(StopAgentTracingCallback());
}
-bool TracingControllerImpl::StartMonitoring(
- const TraceConfig& trace_config,
- const StartMonitoringDoneCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- if (!can_start_monitoring())
- return false;
- OnMonitoringStateChanged(true);
-
-#if defined(OS_ANDROID)
- TraceLog::GetInstance()->AddClockSyncMetadataEvent();
-#endif
-
- base::Closure on_start_monitoring_done_callback =
- base::Bind(&TracingControllerImpl::OnStartMonitoringDone,
- base::Unretained(this),
- trace_config, callback);
- if (!BrowserThread::PostTask(
- BrowserThread::FILE, FROM_HERE,
- base::Bind(&TracingControllerImpl::SetEnabledOnFileThread,
- base::Unretained(this), trace_config,
- base::trace_event::TraceLog::MONITORING_MODE,
- on_start_monitoring_done_callback))) {
- // BrowserThread::PostTask fails if the threads haven't been created yet,
- // so it should be safe to just use TraceLog::SetEnabled directly.
- base::trace_event::TraceLog::GetInstance()->SetEnabled(
- trace_config, base::trace_event::TraceLog::MONITORING_MODE);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- on_start_monitoring_done_callback);
- }
- return true;
-}
-
-void TracingControllerImpl::OnStartMonitoringDone(
- const TraceConfig& trace_config,
- const StartMonitoringDoneCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- // Notify all child processes.
- for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
- it != trace_message_filters_.end(); ++it) {
- it->get()->SendStartMonitoring(trace_config);
- }
-
- if (!callback.is_null())
- callback.Run();
-}
-
-bool TracingControllerImpl::StopMonitoring(
- const StopMonitoringDoneCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- if (!can_stop_monitoring())
- return false;
-
- base::Closure on_stop_monitoring_done_callback =
- base::Bind(&TracingControllerImpl::OnStopMonitoringDone,
- base::Unretained(this), callback);
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(&TracingControllerImpl::SetDisabledOnFileThread,
- base::Unretained(this),
- on_stop_monitoring_done_callback));
- return true;
-}
-
-void TracingControllerImpl::OnStopMonitoringDone(
- const StopMonitoringDoneCallback& callback) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- OnMonitoringStateChanged(false);
-
- // Notify all child processes.
- for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
- it != trace_message_filters_.end(); ++it) {
- it->get()->SendStopMonitoring();
- }
- if (!callback.is_null())
- callback.Run();
-}
-
-void TracingControllerImpl::GetMonitoringStatus(
- bool* out_enabled,
- TraceConfig* out_trace_config) {
- *out_enabled = is_monitoring_;
- *out_trace_config = TraceLog::GetInstance()->GetCurrentTraceConfig();
-}
-
-bool TracingControllerImpl::CaptureMonitoringSnapshot(
- const scoped_refptr<TraceDataSink>& monitoring_data_sink) {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
-
- if (!can_stop_monitoring())
- return false;
-
- if (!monitoring_data_sink.get())
- return false;
-
- monitoring_data_sink_ = monitoring_data_sink;
-
- // Count myself in pending_capture_monitoring_snapshot_ack_count_,
- // acked below.
- pending_capture_monitoring_snapshot_ack_count_ =
- trace_message_filters_.size() + 1;
- pending_capture_monitoring_filters_ = trace_message_filters_;
-
- // Handle special case of zero child processes by immediately flushing the
- // trace log. Once the flush has completed the caller will be notified that
- // the capture snapshot has ended.
- if (pending_capture_monitoring_snapshot_ack_count_ == 1) {
- // Flush asynchronously now, because we don't have any children to wait for.
- TraceLog::GetInstance()->FlushButLeaveBufferIntact(
- base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected,
- base::Unretained(this)));
- }
-
- // Notify all child processes.
- for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
- it != trace_message_filters_.end(); ++it) {
- it->get()->SendCaptureMonitoringSnapshot();
- }
-
-#if defined(OS_ANDROID)
- TraceLog::GetInstance()->AddClockSyncMetadataEvent();
-#endif
-
- return true;
-}
-
bool TracingControllerImpl::GetTraceBufferUsage(
const GetTraceBufferUsageCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -491,8 +430,7 @@ bool TracingControllerImpl::GetTraceBufferUsage(
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
- base::Unretained(this), scoped_refptr<TraceMessageFilter>(),
- status));
+ base::Unretained(this), nullptr, status));
// Notify all child processes.
for (TraceMessageFilterSet::iterator it = trace_message_filters_.begin();
@@ -549,13 +487,21 @@ bool TracingControllerImpl::IsTracing() const {
void TracingControllerImpl::AddTraceMessageFilter(
TraceMessageFilter* trace_message_filter) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
base::Bind(&TracingControllerImpl::AddTraceMessageFilter,
base::Unretained(this),
- make_scoped_refptr(trace_message_filter)));
+ base::RetainedRef(trace_message_filter)));
return;
}
+#if defined(OS_LINUX)
+ // On Linux the browser process dumps process metrics for child process due to
+ // sandbox.
+ tracing::ProcessMetricsMemoryDumpProvider::RegisterForProcess(
+ trace_message_filter->peer_pid());
+#endif
+
trace_message_filters_.insert(trace_message_filter);
if (can_cancel_watch_event()) {
trace_message_filter->SendSetWatchEvent(watch_category_name_,
@@ -565,10 +511,6 @@ void TracingControllerImpl::AddTraceMessageFilter(
trace_message_filter->SendBeginTracing(
TraceLog::GetInstance()->GetCurrentTraceConfig());
}
- if (can_stop_monitoring()) {
- trace_message_filter->SendStartMonitoring(
- TraceLog::GetInstance()->GetCurrentTraceConfig());
- }
FOR_EACH_OBSERVER(TraceMessageFilterObserver, trace_message_filter_observers_,
OnTraceMessageFilterAdded(trace_message_filter));
@@ -577,13 +519,19 @@ void TracingControllerImpl::AddTraceMessageFilter(
void TracingControllerImpl::RemoveTraceMessageFilter(
TraceMessageFilter* trace_message_filter) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
base::Bind(&TracingControllerImpl::RemoveTraceMessageFilter,
base::Unretained(this),
- make_scoped_refptr(trace_message_filter)));
+ base::RetainedRef(trace_message_filter)));
return;
}
+#if defined(OS_LINUX)
+ tracing::ProcessMetricsMemoryDumpProvider::UnregisterForProcess(
+ trace_message_filter->peer_pid());
+#endif
+
// If a filter is removed while a response from that filter is pending then
// simulate the response. Otherwise the response count will be wrong and the
// completion callback will never be executed.
@@ -591,23 +539,14 @@ void TracingControllerImpl::RemoveTraceMessageFilter(
TraceMessageFilterSet::const_iterator it =
pending_stop_tracing_filters_.find(trace_message_filter);
if (it != pending_stop_tracing_filters_.end()) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
base::Bind(&TracingControllerImpl::OnStopTracingAcked,
base::Unretained(this),
- make_scoped_refptr(trace_message_filter),
+ base::RetainedRef(trace_message_filter),
std::vector<std::string>()));
}
}
- if (pending_capture_monitoring_snapshot_ack_count_ > 0) {
- TraceMessageFilterSet::const_iterator it =
- pending_capture_monitoring_filters_.find(trace_message_filter);
- if (it != pending_capture_monitoring_filters_.end()) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked,
- base::Unretained(this),
- make_scoped_refptr(trace_message_filter)));
- }
- }
if (pending_trace_log_status_ack_count_ > 0) {
TraceMessageFilterSet::const_iterator it =
pending_trace_log_status_filters_.find(trace_message_filter);
@@ -616,7 +555,7 @@ void TracingControllerImpl::RemoveTraceMessageFilter(
BrowserThread::UI, FROM_HERE,
base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
base::Unretained(this),
- make_scoped_refptr(trace_message_filter),
+ base::RetainedRef(trace_message_filter),
base::trace_event::TraceLogStatus()));
}
}
@@ -628,22 +567,69 @@ void TracingControllerImpl::RemoveTraceMessageFilter(
BrowserThread::UI, FROM_HERE,
base::Bind(&TracingControllerImpl::OnProcessMemoryDumpResponse,
base::Unretained(this),
- make_scoped_refptr(trace_message_filter),
+ base::RetainedRef(trace_message_filter),
pending_memory_dump_guid_, false /* success */));
}
}
trace_message_filters_.erase(trace_message_filter);
}
+void TracingControllerImpl::AddTracingAgent(const std::string& agent_name) {
+#if defined(OS_CHROMEOS)
+ auto debug_daemon =
+ chromeos::DBusThreadManager::Get()->GetDebugDaemonClient();
+ if (agent_name == debug_daemon->GetTracingAgentName()) {
+ additional_tracing_agents_.push_back(debug_daemon);
+ debug_daemon->SetStopAgentTracingTaskRunner(
+ BrowserThread::GetBlockingPool());
+ return;
+ }
+#elif defined(OS_WIN)
+ auto etw_agent = EtwSystemEventConsumer::GetInstance();
+ if (agent_name == etw_agent->GetTracingAgentName()) {
+ additional_tracing_agents_.push_back(etw_agent);
+ return;
+ }
+#endif
+
+#if defined(ENABLE_POWER_TRACING)
+ auto power_agent = PowerTracingAgent::GetInstance();
+ if (agent_name == power_agent->GetTracingAgentName()) {
+ additional_tracing_agents_.push_back(power_agent);
+ return;
+ }
+#endif
+
+ DCHECK(agent_name == kChromeTracingAgentName);
+}
+
+void TracingControllerImpl::OnStartAgentTracingAcked(
+ const std::string& agent_name,
+ bool success) {
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+ // Don't taken any further action if the ack came after the deadline.
+ if (!start_tracing_timer_.IsRunning())
+ return;
+
+ if (success)
+ AddTracingAgent(agent_name);
+
+ if (--pending_start_tracing_ack_count_ == 0) {
+ start_tracing_timer_.Stop();
+ OnAllTracingAgentsStarted();
+ }
+}
+
void TracingControllerImpl::OnStopTracingAcked(
TraceMessageFilter* trace_message_filter,
const std::vector<std::string>& known_category_groups) {
if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&TracingControllerImpl::OnStopTracingAcked,
- base::Unretained(this),
- make_scoped_refptr(trace_message_filter),
- known_category_groups));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(
+ &TracingControllerImpl::OnStopTracingAcked, base::Unretained(this),
+ base::RetainedRef(trace_message_filter), known_category_groups));
return;
}
@@ -700,7 +686,8 @@ void TracingControllerImpl::OnEndAgentTracingAcked(
const scoped_refptr<base::RefCountedString>& events_str_ptr) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- if (trace_data_sink_.get()) {
+ if (trace_data_sink_.get() && events_str_ptr &&
+ !events_str_ptr->data().empty()) {
std::string json_string;
if (agent_name == kETWTracingAgentName) {
// The Windows kernel events are kept into a JSON format stored as string
@@ -715,44 +702,6 @@ void TracingControllerImpl::OnEndAgentTracingAcked(
OnStopTracingAcked(NULL, category_groups);
}
-void TracingControllerImpl::OnCaptureMonitoringSnapshotAcked(
- TraceMessageFilter* trace_message_filter) {
- if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&TracingControllerImpl::OnCaptureMonitoringSnapshotAcked,
- base::Unretained(this),
- make_scoped_refptr(trace_message_filter)));
- return;
- }
-
- if (pending_capture_monitoring_snapshot_ack_count_ == 0)
- return;
-
- if (trace_message_filter &&
- !pending_capture_monitoring_filters_.erase(trace_message_filter)) {
- // The response from the specified message filter has already been received.
- return;
- }
-
- if (--pending_capture_monitoring_snapshot_ack_count_ == 1) {
- // All acks from subprocesses have been received. Now flush the local trace.
- // During or after this call, our OnLocalMonitoringTraceDataCollected
- // will be called with the last of the local trace data.
- TraceLog::GetInstance()->FlushButLeaveBufferIntact(
- base::Bind(&TracingControllerImpl::OnLocalMonitoringTraceDataCollected,
- base::Unretained(this)));
- return;
- }
-
- if (pending_capture_monitoring_snapshot_ack_count_ != 0)
- return;
-
- if (monitoring_data_sink_.get()) {
- monitoring_data_sink_->Close();
- monitoring_data_sink_ = NULL;
- }
-}
-
void TracingControllerImpl::OnTraceDataCollected(
const scoped_refptr<base::RefCountedString>& events_str_ptr) {
// OnTraceDataCollected may be called from any browser thread, either by the
@@ -768,19 +717,6 @@ void TracingControllerImpl::OnTraceDataCollected(
trace_data_sink_->AddTraceChunk(events_str_ptr->data());
}
-void TracingControllerImpl::OnMonitoringTraceDataCollected(
- const scoped_refptr<base::RefCountedString>& events_str_ptr) {
- if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(&TracingControllerImpl::OnMonitoringTraceDataCollected,
- base::Unretained(this), events_str_ptr));
- return;
- }
-
- if (monitoring_data_sink_.get())
- monitoring_data_sink_->AddTraceChunk(events_str_ptr->data());
-}
-
void TracingControllerImpl::OnLocalTraceDataCollected(
const scoped_refptr<base::RefCountedString>& events_str_ptr,
bool has_more_events) {
@@ -796,19 +732,6 @@ void TracingControllerImpl::OnLocalTraceDataCollected(
OnStopTracingAcked(NULL, category_groups);
}
-void TracingControllerImpl::OnLocalMonitoringTraceDataCollected(
- const scoped_refptr<base::RefCountedString>& events_str_ptr,
- bool has_more_events) {
- if (events_str_ptr->data().size())
- OnMonitoringTraceDataCollected(events_str_ptr);
-
- if (has_more_events)
- return;
-
- // Simulate an CaptureMonitoringSnapshotAcked for the local trace.
- OnCaptureMonitoringSnapshotAcked(NULL);
-}
-
void TracingControllerImpl::OnTraceLogStatusReply(
TraceMessageFilter* trace_message_filter,
const base::trace_event::TraceLogStatus& status) {
@@ -817,7 +740,7 @@ void TracingControllerImpl::OnTraceLogStatusReply(
BrowserThread::UI, FROM_HERE,
base::Bind(&TracingControllerImpl::OnTraceLogStatusReply,
base::Unretained(this),
- make_scoped_refptr(trace_message_filter), status));
+ base::RetainedRef(trace_message_filter), status));
return;
}
@@ -875,29 +798,25 @@ std::string TracingControllerImpl::GetTraceEventLabel() {
return kChromeTraceLabel;
}
-bool TracingControllerImpl::StartAgentTracing(
- const base::trace_event::TraceConfig& trace_config) {
+void TracingControllerImpl::StartAgentTracing(
+ const base::trace_event::TraceConfig& trace_config,
+ const StartAgentTracingCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- base::Closure on_start_tracing_done_callback =
- base::Bind(&TracingControllerImpl::OnStartAgentTracingDone,
- base::Unretained(this),
- trace_config, start_tracing_done_callback_);
+ base::Closure on_agent_started =
+ base::Bind(callback, kChromeTracingAgentName, true);
if (!BrowserThread::PostTask(
BrowserThread::FILE, FROM_HERE,
base::Bind(&TracingControllerImpl::SetEnabledOnFileThread,
base::Unretained(this), trace_config,
base::trace_event::TraceLog::RECORDING_MODE,
- on_start_tracing_done_callback))) {
+ on_agent_started))) {
// BrowserThread::PostTask fails if the threads haven't been created yet,
// so it should be safe to just use TraceLog::SetEnabled directly.
base::trace_event::TraceLog::GetInstance()->SetEnabled(
trace_config, base::trace_event::TraceLog::RECORDING_MODE);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- on_start_tracing_done_callback);
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, on_agent_started);
}
-
- return true;
}
void TracingControllerImpl::StopAgentTracing(
@@ -935,19 +854,13 @@ bool TracingControllerImpl::SupportsExplicitClockSync() {
}
void TracingControllerImpl::RecordClockSyncMarker(
- int sync_id,
+ const std::string& sync_id,
const RecordClockSyncMarkerCallback& callback) {
DCHECK(SupportsExplicitClockSync());
TRACE_EVENT_CLOCK_SYNC_RECEIVER(sync_id);
}
-int TracingControllerImpl::GetUniqueClockSyncID() {
- DCHECK_CURRENTLY_ON(BrowserThread::UI);
- // There is no need to lock because this function only runs on UI thread.
- return ++clock_sync_id_;
-}
-
void TracingControllerImpl::IssueClockSyncMarker() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(pending_clock_sync_ack_count_ == 0);
@@ -955,7 +868,7 @@ void TracingControllerImpl::IssueClockSyncMarker() {
for (const auto& it : additional_tracing_agents_) {
if (it->SupportsExplicitClockSync()) {
it->RecordClockSyncMarker(
- GetUniqueClockSyncID(),
+ base::GenerateGUID(),
base::Bind(&TracingControllerImpl::OnClockSyncMarkerRecordedByAgent,
base::Unretained(this)));
pending_clock_sync_ack_count_++;
@@ -968,20 +881,22 @@ void TracingControllerImpl::IssueClockSyncMarker() {
StopTracingAfterClockSync();
} else {
clock_sync_timer_.Start(
- FROM_HERE,
- base::TimeDelta::FromSeconds(kIssueClockSyncTimeout),
- this,
- &TracingControllerImpl::StopTracingAfterClockSync);
+ FROM_HERE, base::TimeDelta::FromSeconds(kIssueClockSyncTimeoutSeconds),
+ this, &TracingControllerImpl::StopTracingAfterClockSync);
}
}
void TracingControllerImpl::OnClockSyncMarkerRecordedByAgent(
- int sync_id,
+ const std::string& sync_id,
const base::TimeTicks& issue_ts,
const base::TimeTicks& issue_end_ts) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
- TRACE_EVENT_CLOCK_SYNC_ISSUER(sync_id, issue_ts, issue_end_ts);
+ // TODO(charliea): Change this function so that it can accept a boolean
+ // success indicator instead of having to rely on sentinel issue_ts and
+ // issue_end_ts values to signal failure.
+ if (!(issue_ts == base::TimeTicks() || issue_end_ts == base::TimeTicks()))
+ TRACE_EVENT_CLOCK_SYNC_ISSUER(sync_id, issue_ts, issue_end_ts);
// Timer is not running means that clock sync already timed out.
if (!clock_sync_timer_.IsRunning())
@@ -1066,7 +981,7 @@ void TracingControllerImpl::OnProcessMemoryDumpResponse(
BrowserThread::UI, FROM_HERE,
base::Bind(&TracingControllerImpl::OnProcessMemoryDumpResponse,
base::Unretained(this),
- make_scoped_refptr(trace_message_filter), dump_guid,
+ base::RetainedRef(trace_message_filter), dump_guid,
success));
return;
}
@@ -1116,17 +1031,4 @@ void TracingControllerImpl::FinalizeGlobalMemoryDumpIfAllProcessesReplied() {
pending_memory_dump_guid_ = 0;
}
-void TracingControllerImpl::OnMonitoringStateChanged(bool is_monitoring) {
- if (is_monitoring_ == is_monitoring)
- return;
-
- is_monitoring_ = is_monitoring;
-#if !defined(OS_ANDROID)
- for (std::set<TracingUI*>::iterator it = tracing_uis_.begin();
- it != tracing_uis_.end(); it++) {
- (*it)->OnMonitoringStateChanged(is_monitoring);
- }
-#endif
-}
-
} // namespace content
diff --git a/chromium/content/browser/tracing/tracing_controller_impl.h b/chromium/content/browser/tracing/tracing_controller_impl.h
index 90dcc408076..7a6c17b2b79 100644
--- a/chromium/content/browser/tracing/tracing_controller_impl.h
+++ b/chromium/content/browser/tracing/tracing_controller_impl.h
@@ -41,16 +41,6 @@ class TracingControllerImpl
bool StartTracing(const base::trace_event::TraceConfig& trace_config,
const StartTracingDoneCallback& callback) override;
bool StopTracing(const scoped_refptr<TraceDataSink>& sink) override;
- bool StartMonitoring(
- const base::trace_event::TraceConfig& trace_config,
- const StartMonitoringDoneCallback& callback) override;
- bool StopMonitoring(
- const StopMonitoringDoneCallback& callback) override;
- void GetMonitoringStatus(
- bool* out_enabled,
- base::trace_event::TraceConfig* out_trace_config) override;
- bool CaptureMonitoringSnapshot(
- const scoped_refptr<TraceDataSink>& sink) override;
bool GetTraceBufferUsage(
const GetTraceBufferUsageCallback& callback) override;
bool SetWatchEvent(const std::string& category_name,
@@ -65,12 +55,12 @@ class TracingControllerImpl
// base::trace_event::TracingAgent implementation.
std::string GetTracingAgentName() override;
std::string GetTraceEventLabel() override;
- bool StartAgentTracing(
- const base::trace_event::TraceConfig& trace_config) override;
+ void StartAgentTracing(const base::trace_event::TraceConfig& trace_config,
+ const StartAgentTracingCallback& callback) override;
void StopAgentTracing(const StopAgentTracingCallback& callback) override;
bool SupportsExplicitClockSync() override;
void RecordClockSyncMarker(
- int sync_id,
+ const std::string& sync_id,
const RecordClockSyncMarkerCallback& callback) override;
// base::trace_event::MemoryDumpManagerDelegate implementation.
@@ -124,17 +114,17 @@ class TracingControllerImpl
void OnTraceDataCollected(
const scoped_refptr<base::RefCountedString>& events_str_ptr);
- void OnMonitoringTraceDataCollected(
- const scoped_refptr<base::RefCountedString>& events_str_ptr);
// Callback of TraceLog::Flush() for the local trace.
void OnLocalTraceDataCollected(
const scoped_refptr<base::RefCountedString>& events_str_ptr,
bool has_more_events);
- // Callback of TraceLog::FlushMonitoring() for the local trace.
- void OnLocalMonitoringTraceDataCollected(
- const scoped_refptr<base::RefCountedString>& events_str_ptr,
- bool has_more_events);
+
+ // Adds the tracing agent with the specified agent name to the list of
+ // additional tracing agents.
+ void AddTracingAgent(const std::string& agent_name);
+
+ void OnStartAgentTracingAcked(const std::string& agent_name, bool success);
void OnStopTracingAcked(
TraceMessageFilter* trace_message_filter,
@@ -145,9 +135,6 @@ class TracingControllerImpl
const std::string& events_label,
const scoped_refptr<base::RefCountedString>& events_str_ptr);
- void OnCaptureMonitoringSnapshotAcked(
- TraceMessageFilter* trace_message_filter);
-
void OnTraceLogStatusReply(TraceMessageFilter* trace_message_filter,
const base::trace_event::TraceLogStatus& status);
void OnProcessMemoryDumpResponse(TraceMessageFilter* trace_message_filter,
@@ -166,37 +153,30 @@ class TracingControllerImpl
int mode,
const base::Closure& callback);
void SetDisabledOnFileThread(const base::Closure& callback);
- void OnStartAgentTracingDone(
- const base::trace_event::TraceConfig& trace_config,
- const StartTracingDoneCallback& callback);
+ void OnAllTracingAgentsStarted();
void StopTracingAfterClockSync();
void OnStopTracingDone();
- void OnStartMonitoringDone(
- const base::trace_event::TraceConfig& trace_config,
- const StartMonitoringDoneCallback& callback);
- void OnStopMonitoringDone(const StopMonitoringDoneCallback& callback);
- void OnMonitoringStateChanged(bool is_monitoring);
-
- int GetUniqueClockSyncID();
// Issue clock sync markers to the tracing agents.
void IssueClockSyncMarker();
void OnClockSyncMarkerRecordedByAgent(
- int sync_id,
+ const std::string& sync_id,
const base::TimeTicks& issue_ts,
const base::TimeTicks& issue_end_ts);
typedef std::set<scoped_refptr<TraceMessageFilter>> TraceMessageFilterSet;
TraceMessageFilterSet trace_message_filters_;
+ // Pending acks for StartTracing.
+ int pending_start_tracing_ack_count_;
+ base::OneShotTimer start_tracing_timer_;
+ StartTracingDoneCallback start_tracing_done_callback_;
+ scoped_ptr<base::trace_event::TraceConfig> start_tracing_trace_config_;
+
// Pending acks for StopTracing.
int pending_stop_tracing_ack_count_;
TraceMessageFilterSet pending_stop_tracing_filters_;
- // Pending acks for CaptureMonitoringSnapshot.
- int pending_capture_monitoring_snapshot_ack_count_;
- TraceMessageFilterSet pending_capture_monitoring_filters_;
-
// Pending acks for GetTraceLogStatus.
int pending_trace_log_status_ack_count_;
TraceMessageFilterSet pending_trace_log_status_filters_;
@@ -210,7 +190,6 @@ class TracingControllerImpl
uint64_t pending_memory_dump_guid_;
base::trace_event::MemoryDumpCallback pending_memory_dump_callback_;
- StartTracingDoneCallback start_tracing_done_callback_;
std::vector<base::trace_event::TracingAgent*> additional_tracing_agents_;
int clock_sync_id_;
int pending_clock_sync_ack_count_;
diff --git a/chromium/content/browser/tracing/tracing_controller_impl_data_sinks.cc b/chromium/content/browser/tracing/tracing_controller_impl_data_sinks.cc
index 025619f2024..1ee6327893a 100644
--- a/chromium/content/browser/tracing/tracing_controller_impl_data_sinks.cc
+++ b/chromium/content/browser/tracing/tracing_controller_impl_data_sinks.cc
@@ -34,9 +34,10 @@ class StringTraceDataEndpoint : public TracingController::TraceDataEndpoint {
scoped_refptr<base::RefCountedString> str =
base::RefCountedString::TakeString(&tmp);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(completion_callback_,
- base::Passed(std::move(metadata)), str));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(completion_callback_, base::Passed(std::move(metadata)),
+ base::RetainedRef(str)));
}
private:
diff --git a/chromium/content/browser/tracing/tracing_ui.cc b/chromium/content/browser/tracing/tracing_ui.cc
index 13eaa402036..074a771a1a8 100644
--- a/chromium/content/browser/tracing/tracing_ui.cc
+++ b/chromium/content/browser/tracing/tracing_ui.cc
@@ -145,55 +145,6 @@ void OnTraceBufferStatusResult(const WebUIDataSource::GotDataCallback& callback,
callback.Run(status_base64);
}
-void OnMonitoringEnabledAck(const WebUIDataSource::GotDataCallback& callback);
-
-bool StartMonitoring(const std::string& data64,
- const WebUIDataSource::GotDataCallback& callback) {
- base::trace_event::TraceConfig trace_config("", "");
- if (!GetTracingOptions(data64, &trace_config))
- return false;
-
- return TracingController::GetInstance()->StartMonitoring(
- trace_config,
- base::Bind(OnMonitoringEnabledAck, callback));
-}
-
-void OnMonitoringEnabledAck(const WebUIDataSource::GotDataCallback& callback) {
- base::RefCountedString* res = new base::RefCountedString();
- callback.Run(res);
-}
-
-void OnMonitoringDisabled(const WebUIDataSource::GotDataCallback& callback) {
- base::RefCountedString* res = new base::RefCountedString();
- callback.Run(res);
-}
-
-void GetMonitoringStatus(const WebUIDataSource::GotDataCallback& callback) {
- bool is_monitoring;
- base::trace_event::TraceConfig config("", "");
- TracingController::GetInstance()->GetMonitoringStatus(
- &is_monitoring, &config);
-
- base::DictionaryValue monitoring_options;
- monitoring_options.SetBoolean("isMonitoring", is_monitoring);
- monitoring_options.SetString("categoryFilter",
- config.ToCategoryFilterString());
- monitoring_options.SetBoolean("useSystemTracing", config.IsSystraceEnabled());
- monitoring_options.SetBoolean(
- "useContinuousTracing",
- config.GetTraceRecordMode() == base::trace_event::RECORD_CONTINUOUSLY);
- monitoring_options.SetBoolean("useSampling", config.IsSamplingEnabled());
-
- std::string monitoring_options_json;
- base::JSONWriter::Write(monitoring_options, &monitoring_options_json);
-
- base::RefCountedString* monitoring_options_base64 =
- new base::RefCountedString();
- base::Base64Encode(monitoring_options_json,
- &monitoring_options_base64->data());
- callback.Run(monitoring_options_base64);
-}
-
void TracingCallbackWrapperBase64(
const WebUIDataSource::GotDataCallback& callback,
scoped_ptr<const base::DictionaryValue> metadata,
@@ -241,29 +192,6 @@ bool OnBeginJSONRequest(const std::string& path,
return TracingController::GetInstance()->StopTracing(data_sink);
}
- const char* StartMonitoringPath = "json/begin_monitoring?";
- if (path.find(StartMonitoringPath) == 0) {
- std::string data = path.substr(strlen(StartMonitoringPath));
- return StartMonitoring(data, callback);
- }
- if (path == "json/end_monitoring") {
- return TracingController::GetInstance()->StopMonitoring(
- base::Bind(OnMonitoringDisabled, callback));
- }
- if (path == "json/capture_monitoring_compressed") {
- scoped_refptr<TracingControllerImpl::TraceDataSink> data_sink =
- TracingController::CreateCompressedStringSink(
- TracingController::CreateCallbackEndpoint(
- base::Bind(TracingCallbackWrapperBase64, callback)));
- AddCustomMetadata(data_sink.get());
- TracingController::GetInstance()->CaptureMonitoringSnapshot(data_sink);
- return true;
- }
- if (path == "json/get_monitoring_status") {
- GetMonitoringStatus(callback);
- return true;
- }
-
LOG(ERROR) << "Unhandled request to " << path;
return false;
}
@@ -317,11 +245,6 @@ TracingUI::~TracingUI() {
TracingControllerImpl::GetInstance()->UnregisterTracingUI(this);
}
-void TracingUI::OnMonitoringStateChanged(bool is_monitoring) {
- web_ui()->CallJavascriptFunction(
- "onMonitoringStateChanged", base::FundamentalValue(is_monitoring));
-}
-
void TracingUI::DoUploadBase64Encoded(const base::ListValue* args) {
std::string file_contents_base64;
if (!args || args->empty() || !args->GetString(0, &file_contents_base64)) {
diff --git a/chromium/content/browser/tracing/tracing_ui.h b/chromium/content/browser/tracing/tracing_ui.h
index 22e8616cab5..4e65de11a7a 100644
--- a/chromium/content/browser/tracing/tracing_ui.h
+++ b/chromium/content/browser/tracing/tracing_ui.h
@@ -24,7 +24,6 @@ class CONTENT_EXPORT TracingUI : public WebUIController {
public:
explicit TracingUI(WebUI* web_ui);
~TracingUI() override;
- void OnMonitoringStateChanged(bool is_monitoring);
void OnTraceUploadProgress(int64_t current, int64_t total);
void OnTraceUploadComplete(bool success, const std::string& feedback);
diff --git a/chromium/content/browser/udev_linux.cc b/chromium/content/browser/udev_linux.cc
deleted file mode 100644
index 1890523d714..00000000000
--- a/chromium/content/browser/udev_linux.cc
+++ /dev/null
@@ -1,66 +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/udev_linux.h"
-
-#include <stddef.h>
-
-#include "base/message_loop/message_loop.h"
-
-namespace content {
-
-UdevLinux::UdevLinux(const std::vector<UdevMonitorFilter>& filters,
- const UdevNotificationCallback& callback)
- : udev_(device::udev_new()),
- monitor_(device::udev_monitor_new_from_netlink(udev_.get(), "udev")),
- monitor_fd_(-1),
- callback_(callback) {
- CHECK(udev_);
- CHECK(monitor_);
-
- for (size_t i = 0; i < filters.size(); ++i) {
- int ret = device::udev_monitor_filter_add_match_subsystem_devtype(
- monitor_.get(), filters[i].subsystem, filters[i].devtype);
- CHECK_EQ(0, ret);
- }
-
- int ret = device::udev_monitor_enable_receiving(monitor_.get());
- CHECK_EQ(0, ret);
- monitor_fd_ = device::udev_monitor_get_fd(monitor_.get());
- CHECK_GE(monitor_fd_, 0);
-
- bool success = base::MessageLoopForIO::current()->WatchFileDescriptor(
- monitor_fd_,
- true,
- base::MessageLoopForIO::WATCH_READ,
- &monitor_watcher_,
- this);
- CHECK(success);
-}
-
-UdevLinux::~UdevLinux() {
- monitor_watcher_.StopWatchingFileDescriptor();
-}
-
-udev* UdevLinux::udev_handle() {
- return udev_.get();
-}
-
-void UdevLinux::OnFileCanReadWithoutBlocking(int fd) {
- // Events occur when devices attached to the system are added, removed, or
- // change state. udev_monitor_receive_device() will return a device object
- // representing the device which changed and what type of change occured.
- DCHECK_EQ(monitor_fd_, fd);
- device::ScopedUdevDevicePtr dev(
- device::udev_monitor_receive_device(monitor_.get()));
- if (!dev)
- return;
-
- callback_.Run(dev.get());
-}
-
-void UdevLinux::OnFileCanWriteWithoutBlocking(int fd) {
-}
-
-} // namespace content
diff --git a/chromium/content/browser/udev_linux.h b/chromium/content/browser/udev_linux.h
deleted file mode 100644
index 3e4ac44a778..00000000000
--- a/chromium/content/browser/udev_linux.h
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// UdevLinux listens for device change notifications from udev and runs
-// callbacks when notifications occur.
-//
-// UdevLinux must be created on a MessageLoop of TYPE_IO.
-// UdevLinux is not thread-safe.
-//
-// Example usage:
-//
-// class UdevLinux;
-//
-// class Foo {
-// public:
-// Foo() {
-// std::vector<UdevLinux::UdevMonitorFilter> filters;
-// filters.push_back(content::UdevLinux::UdevMonitorFilter("block", NULL));
-// udev_.reset(new UdevLinux(filters,
-// base::Bind(&Foo::Notify, this)));
-// }
-//
-// // Called when a "block" device attaches/detaches.
-// // To hold on to |device|, call udev_device_ref(device).
-// void Notify(udev_device* device) {
-// // Do something with |device|.
-// }
-//
-// private:
-// scoped_ptr<UdevLinux> udev_;
-//
-// DISALLOW_COPY_AND_ASSIGN(Foo);
-// };
-
-#ifndef CONTENT_BROWSER_UDEV_LINUX_H_
-#define CONTENT_BROWSER_UDEV_LINUX_H_
-
-#include <vector>
-
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/message_loop/message_pump_libevent.h"
-#include "device/udev_linux/scoped_udev.h"
-
-extern "C" {
-struct udev;
-struct udev_device;
-struct udev_monitor;
-}
-
-namespace content {
-
-class UdevLinux : public base::MessagePumpLibevent::Watcher {
- public:
- typedef base::Callback<void(udev_device*)> UdevNotificationCallback;
-
- // subsystem and devtype parameter for
- // udev_monitor_filter_add_match_subsystem_devtype().
- struct UdevMonitorFilter {
- UdevMonitorFilter(const char* subsystem_in, const char* devtype_in)
- : subsystem(subsystem_in),
- devtype(devtype_in) {
- }
- const char* subsystem;
- const char* devtype;
- };
-
- // Filter incoming devices based on |filters|.
- // Calls |callback| upon device change events.
- UdevLinux(const std::vector<UdevMonitorFilter>& filters,
- const UdevNotificationCallback& callback);
- ~UdevLinux() override;
-
- // Returns the udev handle to be passed into other udev_*() functions.
- udev* udev_handle();
-
- private:
- // base::MessagePump:Libevent::Watcher implementation.
- void OnFileCanReadWithoutBlocking(int fd) override;
- void OnFileCanWriteWithoutBlocking(int fd) override;
-
- // libudev-related items, the main context, and the monitoring context to be
- // notified about changes to device states.
- device::ScopedUdevPtr udev_;
- device::ScopedUdevMonitorPtr monitor_;
- int monitor_fd_;
- base::MessagePumpLibevent::FileDescriptorWatcher monitor_watcher_;
- UdevNotificationCallback callback_;
-
- DISALLOW_COPY_AND_ASSIGN(UdevLinux);
-};
-
-} // namespace content
-
-#endif // CONTENT_BROWSER_UDEV_LINUX_H_
diff --git a/chromium/content/browser/utility_process_host_impl.cc b/chromium/content/browser/utility_process_host_impl.cc
index 42c31bd9b2a..0ad33097570 100644
--- a/chromium/content/browser/utility_process_host_impl.cc
+++ b/chromium/content/browser/utility_process_host_impl.cc
@@ -37,6 +37,10 @@
#include "ipc/ipc_switches.h"
#include "ui/base/ui_base_switches.h"
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+#include "content/public/browser/zygote_handle_linux.h"
+#endif // defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+
#if defined(OS_WIN)
#include "sandbox/win/src/sandbox_policy.h"
#include "sandbox/win/src/sandbox_types.h"
@@ -44,6 +48,12 @@
namespace content {
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+namespace {
+ZygoteHandle g_utility_zygote;
+} // namespace
+#endif // defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+
// NOTE: changes to this class need to be reviewed by the security team.
class UtilitySandboxedProcessLauncherDelegate
: public SandboxedProcessLauncherDelegate {
@@ -58,7 +68,9 @@ class UtilitySandboxedProcessLauncherDelegate
launch_elevated_(launch_elevated)
#elif defined(OS_POSIX)
env_(env),
+#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
no_sandbox_(no_sandbox),
+#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
ipc_fd_(host->TakeClientFileDescriptor())
#endif // OS_WIN
{}
@@ -88,9 +100,13 @@ class UtilitySandboxedProcessLauncherDelegate
#elif defined(OS_POSIX)
- bool ShouldUseZygote() override {
- return !no_sandbox_ && exposed_dir_.empty();
+#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
+ ZygoteHandle* GetZygote() override {
+ if (no_sandbox_ || !exposed_dir_.empty())
+ return nullptr;
+ return GetGenericZygote();
}
+#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
base::EnvironmentMap GetEnvironment() override { return env_; }
base::ScopedFD TakeIpcFd() override { return std::move(ipc_fd_); }
#endif // OS_WIN
@@ -106,7 +122,9 @@ class UtilitySandboxedProcessLauncherDelegate
bool launch_elevated_;
#elif defined(OS_POSIX)
base::EnvironmentMap env_;
+#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
bool no_sandbox_;
+#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
base::ScopedFD ipc_fd_;
#endif // OS_WIN
};
@@ -139,6 +157,7 @@ UtilityProcessHostImpl::UtilityProcessHostImpl(
#endif
started_(false),
name_(base::ASCIIToUTF16("utility process")),
+ mojo_application_host_(new MojoApplicationHost),
weak_ptr_factory_(this) {
}
@@ -199,27 +218,27 @@ void UtilityProcessHostImpl::SetEnv(const base::EnvironmentMap& env) {
#endif // OS_POSIX
-bool UtilityProcessHostImpl::StartMojoMode() {
- CHECK(!mojo_application_host_);
- mojo_application_host_.reset(new MojoApplicationHost);
-
- bool mojo_result = mojo_application_host_->Init();
- if (!mojo_result)
- return false;
-
+bool UtilityProcessHostImpl::Start() {
return StartProcess();
}
ServiceRegistry* UtilityProcessHostImpl::GetServiceRegistry() {
- if (mojo_application_host_)
- return mojo_application_host_->service_registry();
- return nullptr;
+ DCHECK(mojo_application_host_);
+ return mojo_application_host_->service_registry();
}
void UtilityProcessHostImpl::SetName(const base::string16& name) {
name_ = name;
}
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+// static
+void UtilityProcessHostImpl::EarlyZygoteLaunch() {
+ DCHECK(!g_utility_zygote);
+ g_utility_zygote = CreateZygote();
+}
+#endif // defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+
bool UtilityProcessHostImpl::StartProcess() {
if (started_)
return true;
@@ -228,6 +247,10 @@ bool UtilityProcessHostImpl::StartProcess() {
if (is_batch_mode_)
return true;
+ bool mojo_result = mojo_application_host_->Init();
+ if (!mojo_result)
+ return false;
+
// Name must be set or metrics_service will crash in any test which
// launches a UtilityProcessHost.
process_.reset(new BrowserChildProcessHostImpl(PROCESS_TYPE_UTILITY, this));
@@ -296,7 +319,6 @@ bool UtilityProcessHostImpl::StartProcess() {
// Browser command-line switches to propagate to the utility process.
static const char* const kSwitchNames[] = {
- switches::kDebugPluginLoading,
switches::kNoSandbox,
switches::kProfilerTiming,
#if defined(OS_MACOSX)
@@ -371,15 +393,14 @@ void UtilityProcessHostImpl::OnProcessCrashed(int exit_code) {
}
void UtilityProcessHostImpl::OnProcessLaunched() {
- if (mojo_application_host_) {
- base::ProcessHandle handle;
- if (RenderProcessHost::run_renderer_in_process())
- handle = base::GetCurrentProcessHandle();
- else
- handle = process_->GetData().handle;
-
- mojo_application_host_->Activate(this, handle);
- }
+ DCHECK(mojo_application_host_);
+ base::ProcessHandle handle;
+ if (RenderProcessHost::run_renderer_in_process())
+ handle = base::GetCurrentProcessHandle();
+ else
+ handle = process_->GetData().handle;
+
+ mojo_application_host_->Activate(this, handle);
}
} // namespace content
diff --git a/chromium/content/browser/utility_process_host_impl.h b/chromium/content/browser/utility_process_host_impl.h
index 94aafa7c517..25974950208 100644
--- a/chromium/content/browser/utility_process_host_impl.h
+++ b/chromium/content/browser/utility_process_host_impl.h
@@ -57,12 +57,17 @@ class CONTENT_EXPORT UtilityProcessHostImpl
#if defined(OS_POSIX)
void SetEnv(const base::EnvironmentMap& env) override;
#endif
- bool StartMojoMode() override;
+ bool Start() override;
ServiceRegistry* GetServiceRegistry() override;
void SetName(const base::string16& name) override;
void set_child_flags(int flags) { child_flags_ = flags; }
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+ // Launch the zygote early in the browser startup.
+ static void EarlyZygoteLaunch();
+#endif // defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+
private:
// Starts a process if necessary. Returns true if it succeeded or a process
// has already been started via StartBatchMode().
diff --git a/chromium/content/browser/vr/android/cardboard/cardboard_vr_device.cc b/chromium/content/browser/vr/android/cardboard/cardboard_vr_device.cc
index 9d9aca7c632..d42d2b9d81c 100644
--- a/chromium/content/browser/vr/android/cardboard/cardboard_vr_device.cc
+++ b/chromium/content/browser/vr/android/cardboard/cardboard_vr_device.cc
@@ -40,9 +40,9 @@ CardboardVRDevice::~CardboardVRDevice() {
j_cardboard_device_.obj());
}
-VRDeviceInfoPtr CardboardVRDevice::GetVRDevice() {
+mojom::VRDeviceInfoPtr CardboardVRDevice::GetVRDevice() {
TRACE_EVENT0("input", "CardboardVRDevice::GetVRDevice");
- VRDeviceInfoPtr device = VRDeviceInfo::New();
+ mojom::VRDeviceInfoPtr device = mojom::VRDeviceInfo::New();
JNIEnv* env = AttachCurrentThread();
@@ -58,15 +58,15 @@ VRDeviceInfoPtr CardboardVRDevice::GetVRDevice() {
std::vector<float> fov;
base::android::JavaFloatArrayToFloatVector(env, j_fov.obj(), &fov);
- device->hmdInfo = VRHMDInfo::New();
- VRHMDInfoPtr& hmdInfo = device->hmdInfo;
+ device->hmdInfo = mojom::VRHMDInfo::New();
+ mojom::VRHMDInfoPtr& hmdInfo = device->hmdInfo;
- hmdInfo->leftEye = VREyeParameters::New();
- hmdInfo->rightEye = VREyeParameters::New();
- VREyeParametersPtr& left_eye = hmdInfo->leftEye;
- VREyeParametersPtr& right_eye = hmdInfo->rightEye;
+ hmdInfo->leftEye = mojom::VREyeParameters::New();
+ hmdInfo->rightEye = mojom::VREyeParameters::New();
+ mojom::VREyeParametersPtr& left_eye = hmdInfo->leftEye;
+ mojom::VREyeParametersPtr& right_eye = hmdInfo->rightEye;
- left_eye->recommendedFieldOfView = VRFieldOfView::New();
+ left_eye->recommendedFieldOfView = mojom::VRFieldOfView::New();
left_eye->recommendedFieldOfView->upDegrees = fov[0];
left_eye->recommendedFieldOfView->downDegrees = fov[1];
left_eye->recommendedFieldOfView->leftDegrees = fov[2];
@@ -74,7 +74,7 @@ VRDeviceInfoPtr CardboardVRDevice::GetVRDevice() {
// Cardboard devices always assume a mirrored FOV, so this is just the left
// eye FOV with the left and right degrees swapped.
- right_eye->recommendedFieldOfView = VRFieldOfView::New();
+ right_eye->recommendedFieldOfView = mojom::VRFieldOfView::New();
right_eye->recommendedFieldOfView->upDegrees = fov[0];
right_eye->recommendedFieldOfView->downDegrees = fov[1];
right_eye->recommendedFieldOfView->leftDegrees = fov[3];
@@ -88,12 +88,12 @@ VRDeviceInfoPtr CardboardVRDevice::GetVRDevice() {
float ipd = Java_CardboardVRDevice_getIpd(env, j_cardboard_device_.obj());
- left_eye->eyeTranslation = VRVector3::New();
+ left_eye->eyeTranslation = mojom::VRVector3::New();
left_eye->eyeTranslation->x = ipd * -0.5f;
left_eye->eyeTranslation->y = 0.0f;
left_eye->eyeTranslation->z = 0.0f;
- right_eye->eyeTranslation = VRVector3::New();
+ right_eye->eyeTranslation = mojom::VRVector3::New();
right_eye->eyeTranslation->x = ipd * 0.5f;
right_eye->eyeTranslation->y = 0.0f;
right_eye->eyeTranslation->z = 0.0f;
@@ -106,13 +106,13 @@ VRDeviceInfoPtr CardboardVRDevice::GetVRDevice() {
base::android::JavaIntArrayToIntVector(env, j_screen_size.obj(),
&screen_size);
- left_eye->renderRect = VRRect::New();
+ left_eye->renderRect = mojom::VRRect::New();
left_eye->renderRect->x = 0;
left_eye->renderRect->y = 0;
left_eye->renderRect->width = screen_size[0] / 2.0;
left_eye->renderRect->height = screen_size[1];
- right_eye->renderRect = VRRect::New();
+ right_eye->renderRect = mojom::VRRect::New();
right_eye->renderRect->x = screen_size[0] / 2.0;
right_eye->renderRect->y = 0;
right_eye->renderRect->width = screen_size[0] / 2.0;
@@ -121,9 +121,9 @@ VRDeviceInfoPtr CardboardVRDevice::GetVRDevice() {
return device;
}
-VRSensorStatePtr CardboardVRDevice::GetSensorState() {
+mojom::VRSensorStatePtr CardboardVRDevice::GetSensorState() {
TRACE_EVENT0("input", "CardboardVRDevice::GetSensorState");
- VRSensorStatePtr state = VRSensorState::New();
+ mojom::VRSensorStatePtr state = mojom::VRSensorState::New();
state->timestamp = base::Time::Now().ToJsTime();
state->frameIndex = frame_index_++;
@@ -145,13 +145,13 @@ VRSensorStatePtr CardboardVRDevice::GetSensorState() {
gfx::DecomposedTransform decomposed_transform;
gfx::DecomposeTransform(&decomposed_transform, transform);
- state->orientation = VRVector4::New();
+ state->orientation = mojom::VRVector4::New();
state->orientation->x = decomposed_transform.quaternion[0];
state->orientation->y = decomposed_transform.quaternion[1];
state->orientation->z = decomposed_transform.quaternion[2];
state->orientation->w = decomposed_transform.quaternion[3];
- state->position = VRVector3::New();
+ state->position = mojom::VRVector3::New();
state->position->x = decomposed_transform.translate[0];
state->position->y = decomposed_transform.translate[1];
state->position->z = decomposed_transform.translate[2];
diff --git a/chromium/content/browser/vr/android/cardboard/cardboard_vr_device.h b/chromium/content/browser/vr/android/cardboard/cardboard_vr_device.h
index 66f82876ab1..2708c6ad47c 100644
--- a/chromium/content/browser/vr/android/cardboard/cardboard_vr_device.h
+++ b/chromium/content/browser/vr/android/cardboard/cardboard_vr_device.h
@@ -20,8 +20,8 @@ class CardboardVRDevice : public VRDevice {
explicit CardboardVRDevice(VRDeviceProvider* provider);
~CardboardVRDevice() override;
- VRDeviceInfoPtr GetVRDevice() override;
- VRSensorStatePtr GetSensorState() override;
+ mojom::VRDeviceInfoPtr GetVRDevice() override;
+ mojom::VRSensorStatePtr GetSensorState() override;
void ResetSensor() override;
private:
diff --git a/chromium/content/browser/vr/vr_device.h b/chromium/content/browser/vr/vr_device.h
index e3026d73ef8..e3f181715eb 100644
--- a/chromium/content/browser/vr/vr_device.h
+++ b/chromium/content/browser/vr/vr_device.h
@@ -30,8 +30,8 @@ class VRDevice {
VRDeviceProvider* provider() const { return provider_; }
unsigned int id() const { return id_; }
- virtual VRDeviceInfoPtr GetVRDevice() = 0;
- virtual VRSensorStatePtr GetSensorState() = 0;
+ virtual mojom::VRDeviceInfoPtr GetVRDevice() = 0;
+ virtual mojom::VRSensorStatePtr GetSensorState() = 0;
virtual void ResetSensor() = 0;
private:
diff --git a/chromium/content/browser/vr/vr_device_manager.cc b/chromium/content/browser/vr/vr_device_manager.cc
index c99ee393009..181f48d07a7 100644
--- a/chromium/content/browser/vr/vr_device_manager.cc
+++ b/chromium/content/browser/vr/vr_device_manager.cc
@@ -45,7 +45,8 @@ VRDeviceManager::~VRDeviceManager() {
g_vr_device_manager = nullptr;
}
-void VRDeviceManager::BindRequest(mojo::InterfaceRequest<VRService> request) {
+void VRDeviceManager::BindRequest(
+ mojo::InterfaceRequest<mojom::VRService> request) {
VRDeviceManager* device_manager = GetInstance();
device_manager->bindings_.AddBinding(device_manager, std::move(request));
}
@@ -77,7 +78,7 @@ bool VRDeviceManager::HasInstance() {
return !!g_vr_device_manager;
}
-mojo::Array<VRDeviceInfoPtr> VRDeviceManager::GetVRDevices() {
+mojo::Array<mojom::VRDeviceInfoPtr> VRDeviceManager::GetVRDevices() {
DCHECK(thread_checker_.CalledOnValidThread());
InitializeProviders();
@@ -86,7 +87,7 @@ mojo::Array<VRDeviceInfoPtr> VRDeviceManager::GetVRDevices() {
for (const auto& provider : providers_)
provider->GetDevices(&devices);
- mojo::Array<VRDeviceInfoPtr> out_devices(0);
+ mojo::Array<mojom::VRDeviceInfoPtr> out_devices;
for (const auto& device : devices) {
if (device->id() == VR_DEVICE_LAST_ID)
continue;
@@ -94,7 +95,7 @@ mojo::Array<VRDeviceInfoPtr> VRDeviceManager::GetVRDevices() {
if (devices_.find(device->id()) == devices_.end())
devices_[device->id()] = device;
- VRDeviceInfoPtr vr_device_info = device->GetVRDevice();
+ mojom::VRDeviceInfoPtr vr_device_info = device->GetVRDevice();
if (vr_device_info.is_null())
continue;
diff --git a/chromium/content/browser/vr/vr_device_manager.h b/chromium/content/browser/vr/vr_device_manager.h
index 4eb39ea685e..f1dc81b081f 100644
--- a/chromium/content/browser/vr/vr_device_manager.h
+++ b/chromium/content/browser/vr/vr_device_manager.h
@@ -18,20 +18,20 @@
#include "content/browser/vr/vr_device_provider.h"
#include "content/common/content_export.h"
#include "content/common/vr_service.mojom.h"
-#include "mojo/common/weak_binding_set.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
namespace content {
-class VRDeviceManager : public VRService {
+class VRDeviceManager : public mojom::VRService {
public:
~VRDeviceManager() override;
- static void BindRequest(mojo::InterfaceRequest<VRService> request);
+ static void BindRequest(mojo::InterfaceRequest<mojom::VRService> request);
// Returns the VRDeviceManager singleton.
static VRDeviceManager* GetInstance();
- mojo::Array<VRDeviceInfoPtr> GetVRDevices();
+ mojo::Array<mojom::VRDeviceInfoPtr> GetVRDevices();
VRDevice* GetDevice(unsigned int index);
private:
@@ -47,7 +47,7 @@ class VRDeviceManager : public VRService {
void InitializeProviders();
void RegisterProvider(scoped_ptr<VRDeviceProvider> provider);
- // VRService implementation
+ // mojom::VRService implementation
void GetDevices(const GetDevicesCallback& callback) override;
void GetSensorState(uint32_t index,
const GetSensorStateCallback& callback) override;
@@ -65,7 +65,7 @@ class VRDeviceManager : public VRService {
bool vr_initialized_;
- mojo::WeakBindingSet<VRService> bindings_;
+ mojo::BindingSet<mojom::VRService> bindings_;
// For testing. If true will not delete self when consumer count reaches 0.
bool keep_alive_;
diff --git a/chromium/content/browser/vr/vr_device_manager_unittest.cc b/chromium/content/browser/vr/vr_device_manager_unittest.cc
index 001d4403e67..86f35ae1d65 100644
--- a/chromium/content/browser/vr/vr_device_manager_unittest.cc
+++ b/chromium/content/browser/vr/vr_device_manager_unittest.cc
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <utility>
+
#include "base/macros.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/scoped_ptr.h"
@@ -38,7 +40,7 @@ VRDeviceManagerTest::~VRDeviceManagerTest() {
void VRDeviceManagerTest::SetUp() {
scoped_ptr<FakeVRDeviceProvider> provider(new FakeVRDeviceProvider());
provider_ = provider.get();
- device_manager_.reset(new VRDeviceManager(provider.Pass()));
+ device_manager_.reset(new VRDeviceManager(std::move(provider)));
}
TEST_F(VRDeviceManagerTest, InitializationTest) {
@@ -46,15 +48,15 @@ TEST_F(VRDeviceManagerTest, InitializationTest) {
// Calling GetDevices should initialize the service if it hasn't been
// initialized yet or the providesr have been released.
- // The VRService should initialize each of it's providers upon it's own
+ // The mojom::VRService should initialize each of it's providers upon it's own
// initialization.
- mojo::Array<VRDeviceInfoPtr> webvr_devices;
+ mojo::Array<mojom::VRDeviceInfoPtr> webvr_devices;
webvr_devices = device_manager_->GetVRDevices();
EXPECT_TRUE(provider_->IsInitialized());
}
TEST_F(VRDeviceManagerTest, GetDevicesBasicTest) {
- mojo::Array<VRDeviceInfoPtr> webvr_devices;
+ mojo::Array<mojom::VRDeviceInfoPtr> webvr_devices;
webvr_devices = device_manager_->GetVRDevices();
// Calling GetVRDevices should initialize the providers.
EXPECT_TRUE(provider_->IsInitialized());
diff --git a/chromium/content/browser/wake_lock/wake_lock_browsertest.cc b/chromium/content/browser/wake_lock/wake_lock_browsertest.cc
index 3ac458973ce..59e3ab71e1c 100644
--- a/chromium/content/browser/wake_lock/wake_lock_browsertest.cc
+++ b/chromium/content/browser/wake_lock/wake_lock_browsertest.cc
@@ -73,10 +73,10 @@ class WakeLockTest : public ContentBrowserTest {
void WaitForPossibleUpdate() {
// As Mojo channels have no common FIFO order in respect to each other and
// to the Chromium IPC, we cannot assume that when screen.keepAwake state
- // is changed from within a script, WakeLockService will receive an update
- // request before ExecuteScript() returns. Therefore, some time slack is
- // needed to make sure that WakeLockService has received any possible update
- // requests before checking the resulting wake lock state.
+ // is changed from within a script, mojom::WakeLockService will receive an
+ // update request before ExecuteScript() returns. Therefore, some time slack
+ // is needed to make sure that mojom::WakeLockService has received any
+ // possible update requests before checking the resulting wake lock state.
base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
RunAllPendingInMessageLoop();
}
diff --git a/chromium/content/browser/wake_lock/wake_lock_service_context.cc b/chromium/content/browser/wake_lock/wake_lock_service_context.cc
index a6da2103def..8b551660d80 100644
--- a/chromium/content/browser/wake_lock/wake_lock_service_context.cc
+++ b/chromium/content/browser/wake_lock/wake_lock_service_context.cc
@@ -25,7 +25,7 @@ WakeLockServiceContext::~WakeLockServiceContext() {}
void WakeLockServiceContext::CreateService(
int render_process_id,
int render_frame_id,
- mojo::InterfaceRequest<WakeLockService> request) {
+ mojo::InterfaceRequest<mojom::WakeLockService> request) {
new WakeLockServiceImpl(weak_factory_.GetWeakPtr(), render_process_id,
render_frame_id, std::move(request));
}
@@ -56,7 +56,7 @@ void WakeLockServiceContext::CancelWakeLock(int render_process_id,
}
bool WakeLockServiceContext::HasWakeLockForTests() const {
- return wake_lock_;
+ return !!wake_lock_;
}
void WakeLockServiceContext::CreateWakeLock() {
@@ -65,7 +65,7 @@ void WakeLockServiceContext::CreateWakeLock() {
PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep,
PowerSaveBlocker::kReasonOther, "Wake Lock API");
-#if defined(OS_ANDROID) && !defined(USE_AURA)
+#if defined(OS_ANDROID)
// On Android, additionaly associate the blocker with this WebContents.
DCHECK(web_contents());
diff --git a/chromium/content/browser/wake_lock/wake_lock_service_context.h b/chromium/content/browser/wake_lock/wake_lock_service_context.h
index f3114d73e94..73527dc2820 100644
--- a/chromium/content/browser/wake_lock/wake_lock_service_context.h
+++ b/chromium/content/browser/wake_lock/wake_lock_service_context.h
@@ -30,7 +30,7 @@ class CONTENT_EXPORT WakeLockServiceContext : public WebContentsObserver {
// Creates a WakeLockServiceImpl that is strongly bound to |request|.
void CreateService(int render_process_id,
int render_frame_id,
- mojo::InterfaceRequest<WakeLockService> request);
+ mojo::InterfaceRequest<mojom::WakeLockService> request);
// WebContentsObserver implementation.
void RenderFrameDeleted(RenderFrameHost* render_frame_host) override;
diff --git a/chromium/content/browser/wake_lock/wake_lock_service_impl.cc b/chromium/content/browser/wake_lock/wake_lock_service_impl.cc
index 036cb1dec9a..61df4c478f2 100644
--- a/chromium/content/browser/wake_lock/wake_lock_service_impl.cc
+++ b/chromium/content/browser/wake_lock/wake_lock_service_impl.cc
@@ -14,7 +14,7 @@ WakeLockServiceImpl::WakeLockServiceImpl(
base::WeakPtr<WakeLockServiceContext> context,
int render_process_id,
int render_frame_id,
- mojo::InterfaceRequest<WakeLockService> request)
+ mojo::InterfaceRequest<mojom::WakeLockService> request)
: context_(context),
render_process_id_(render_process_id),
render_frame_id_(render_frame_id),
diff --git a/chromium/content/browser/wake_lock/wake_lock_service_impl.h b/chromium/content/browser/wake_lock/wake_lock_service_impl.h
index 903f5057fa3..19b8fa55312 100644
--- a/chromium/content/browser/wake_lock/wake_lock_service_impl.h
+++ b/chromium/content/browser/wake_lock/wake_lock_service_impl.h
@@ -15,12 +15,12 @@ namespace content {
class WakeLockServiceContext;
-class WakeLockServiceImpl : public WakeLockService {
+class WakeLockServiceImpl : public mojom::WakeLockService {
public:
WakeLockServiceImpl(base::WeakPtr<WakeLockServiceContext> context,
int render_process_id,
int render_frame_id,
- mojo::InterfaceRequest<WakeLockService> request);
+ mojo::InterfaceRequest<mojom::WakeLockService> request);
~WakeLockServiceImpl() override;
// WakeLockSevice implementation.
@@ -31,7 +31,7 @@ class WakeLockServiceImpl : public WakeLockService {
base::WeakPtr<WakeLockServiceContext> context_;
const int render_process_id_;
const int render_frame_id_;
- mojo::StrongBinding<WakeLockService> binding_;
+ mojo::StrongBinding<mojom::WakeLockService> binding_;
DISALLOW_COPY_AND_ASSIGN(WakeLockServiceImpl);
};
diff --git a/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc b/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
index 97dd750160c..93f166e2d20 100644
--- a/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
+++ b/chromium/content/browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc
@@ -38,13 +38,14 @@ class OverscrollTestWebContents : public TestWebContents {
static OverscrollTestWebContents* Create(
BrowserContext* browser_context,
- SiteInstance* instance,
+ scoped_refptr<SiteInstance> instance,
scoped_ptr<aura::Window> fake_native_view,
scoped_ptr<aura::Window> fake_contents_window) {
OverscrollTestWebContents* web_contents = new OverscrollTestWebContents(
browser_context, std::move(fake_native_view),
std::move(fake_contents_window));
- web_contents->Init(WebContents::CreateParams(browser_context, instance));
+ web_contents->Init(
+ WebContents::CreateParams(browser_context, std::move(instance)));
return web_contents;
}
@@ -112,7 +113,7 @@ class OverscrollNavigationOverlayTest : public RenderViewHostImplTestHarness {
// offset -1 on layer_delegate_.
scoped_ptr<aura::Window> window(
GetOverlay()->CreateBackWindow(GetBackSlideWindowBounds()));
- bool window_created = window;
+ bool window_created = !!window;
// Performs BACK navigation, sets image from layer_delegate_ on
// image_delegate_.
GetOverlay()->OnOverscrollCompleting();
@@ -307,7 +308,6 @@ TEST_F(OverscrollNavigationOverlayTest, Navigation_LoadingUpdate) {
// this is a "safety net" in case we mis-identify the destination webpage
// (which can happen if a new navigation is performed while while a GestureNav
// navigation is in progress).
- contents()->TestSetIsLoading(true);
contents()->TestSetIsLoading(false);
EXPECT_FALSE(GetOverlay()->web_contents());
NavigationEntry* pending = contents()->GetController().GetPendingEntry();
diff --git a/chromium/content/browser/web_contents/aura/shadow_layer_delegate.cc b/chromium/content/browser/web_contents/aura/shadow_layer_delegate.cc
index 067a1472258..a4a1660be5b 100644
--- a/chromium/content/browser/web_contents/aura/shadow_layer_delegate.cc
+++ b/chromium/content/browser/web_contents/aura/shadow_layer_delegate.cc
@@ -42,14 +42,12 @@ void ShadowLayerDelegate::OnPaintLayer(const ui::PaintContext& context) {
points[0].iset(0, 0);
points[1].iset(kShadowThick, 0);
- skia::RefPtr<SkShader> shader = skia::AdoptRef(
- SkGradientShader::CreateLinear(points, kShadowColors, NULL,
- arraysize(points), SkShader::kRepeat_TileMode));
-
gfx::Rect paint_rect = gfx::Rect(0, 0, kShadowThick,
layer_->bounds().height());
SkPaint paint;
- paint.setShader(shader.get());
+ paint.setShader(SkGradientShader::MakeLinear(points, kShadowColors, NULL,
+ arraysize(points),
+ SkShader::kRepeat_TileMode));
ui::PaintRecorder recorder(context, layer_->size());
recorder.canvas()->DrawRect(paint_rect, paint);
}
diff --git a/chromium/content/browser/web_contents/web_contents_android.cc b/chromium/content/browser/web_contents/web_contents_android.cc
index f772161f6ee..7a5e1f62d7a 100644
--- a/chromium/content/browser/web_contents/web_contents_android.cc
+++ b/chromium/content/browser/web_contents/web_contents_android.cc
@@ -69,18 +69,9 @@ void JavaScriptResultCallback(const ScopedJavaGlobalRef<jobject>& callback,
}
struct AccessibilitySnapshotParams {
- AccessibilitySnapshotParams(float scale,
- float horizontal_scroll,
- float vertical_offset)
- : scale_factor(scale),
- x_scroll(horizontal_scroll),
- y_offset(vertical_offset),
- has_tree_data(false),
- should_select_leaf_nodes(false) {}
-
- float scale_factor;
- float x_scroll;
- float y_offset;
+ AccessibilitySnapshotParams()
+ : has_tree_data(false), should_select_leaf_nodes(false) {}
+
bool has_tree_data;
// The current text selection within this tree, if any, expressed as the
// node ID and character offset of the anchor (selection start) and focus
@@ -96,12 +87,12 @@ struct AccessibilitySnapshotParams {
ScopedJavaLocalRef<jobject> WalkAXTreeDepthFirst(
JNIEnv* env,
BrowserAccessibilityAndroid* node,
+ const gfx::Rect& parent_rect,
AccessibilitySnapshotParams* params) {
ScopedJavaLocalRef<jstring> j_text =
ConvertUTF16ToJavaString(env, node->GetText());
ScopedJavaLocalRef<jstring> j_class =
ConvertUTF8ToJavaString(env, node->GetClassName());
- const gfx::Rect& location = node->GetLocalBoundsRect();
// The style attributes exists and valid if size attribute exists. Otherwise,
// they are not. Use a negative size information to indicate the existence
// of style information.
@@ -116,15 +107,18 @@ ScopedJavaLocalRef<jobject> WalkAXTreeDepthFirst(
size = node->GetFloatAttribute(ui::AX_ATTR_FONT_SIZE);
text_style = node->GetIntAttribute(ui::AX_ATTR_TEXT_STYLE);
}
- float scale_factor = params->scale_factor;
+
+ const gfx::Rect& absolute_rect = node->GetLocalBoundsRect();
+ gfx::Rect parent_relative_rect = absolute_rect;
+ bool is_root = node->GetParent() == nullptr;
+ if (!is_root) {
+ parent_relative_rect.Offset(-parent_rect.OffsetFromOrigin());
+ }
ScopedJavaLocalRef<jobject> j_node =
Java_WebContentsImpl_createAccessibilitySnapshotNode(
- env, scale_factor * location.x() - params->x_scroll,
- scale_factor * location.y() + params->y_offset,
- scale_factor * node->GetScrollX(), scale_factor * node->GetScrollY(),
- scale_factor * location.width(), scale_factor * location.height(),
- j_text.obj(), color, bgcolor, scale_factor * size, text_style,
- j_class.obj());
+ env, parent_relative_rect.x(), parent_relative_rect.y(),
+ absolute_rect.width(), absolute_rect.height(), is_root, j_text.obj(),
+ color, bgcolor, size, text_style, j_class.obj());
if (params->has_tree_data && node->PlatformIsLeaf()) {
int start_selection = 0;
@@ -150,14 +144,14 @@ ScopedJavaLocalRef<jobject> WalkAXTreeDepthFirst(
static_cast<BrowserAccessibilityAndroid*>(
node->PlatformGetChild(i));
Java_WebContentsImpl_addAccessibilityNodeAsChild(
- env, j_node.obj(), WalkAXTreeDepthFirst(env, child, params).obj());
+ env, j_node.obj(),
+ WalkAXTreeDepthFirst(env, child, absolute_rect, params).obj());
}
return j_node;
}
// Walks over the AXTreeUpdate and creates a light weight snapshot.
void AXTreeSnapshotCallback(const ScopedJavaGlobalRef<jobject>& callback,
- AccessibilitySnapshotParams* params,
const ui::AXTreeUpdate& result) {
JNIEnv* env = base::android::AttachCurrentThread();
if (result.nodes.empty()) {
@@ -170,27 +164,21 @@ void AXTreeSnapshotCallback(const ScopedJavaGlobalRef<jobject>& callback,
manager->set_prune_tree_for_screen_reader(false);
BrowserAccessibilityAndroid* root =
static_cast<BrowserAccessibilityAndroid*>(manager->GetRoot());
+ AccessibilitySnapshotParams params;
if (result.has_tree_data) {
- params->has_tree_data = true;
- params->sel_anchor_object_id = result.tree_data.sel_anchor_object_id;
- params->sel_anchor_offset = result.tree_data.sel_anchor_offset;
- params->sel_focus_object_id = result.tree_data.sel_focus_object_id;
- params->sel_focus_offset = result.tree_data.sel_focus_offset;
+ params.has_tree_data = true;
+ params.sel_anchor_object_id = result.tree_data.sel_anchor_object_id;
+ params.sel_anchor_offset = result.tree_data.sel_anchor_offset;
+ params.sel_focus_object_id = result.tree_data.sel_focus_object_id;
+ params.sel_focus_offset = result.tree_data.sel_focus_offset;
}
- ScopedJavaLocalRef<jobject> j_root = WalkAXTreeDepthFirst(env, root, params);
+ gfx::Rect parent_rect;
+ ScopedJavaLocalRef<jobject> j_root =
+ WalkAXTreeDepthFirst(env, root, parent_rect, &params);
Java_WebContentsImpl_onAccessibilitySnapshot(
env, j_root.obj(), callback.obj());
}
-void ReleaseAllMediaPlayers(WebContents* web_contents,
- RenderFrameHost* render_frame_host) {
- BrowserMediaPlayerManager* manager =
- MediaWebContentsObserverAndroid::FromWebContents(web_contents)
- ->GetMediaPlayerManager(render_frame_host);
- if (manager)
- manager->ReleaseAllMediaPlayers();
-}
-
} // namespace
// static
@@ -398,13 +386,17 @@ void WebContentsAndroid::OnShow(JNIEnv* env, const JavaParamRef<jobject>& obj) {
web_contents_->WasShown();
}
-void WebContentsAndroid::ReleaseMediaPlayers(
+void WebContentsAndroid::SuspendAllMediaPlayers(
JNIEnv* env,
const JavaParamRef<jobject>& jobj) {
-#if defined(ENABLE_BROWSER_CDMS)
- web_contents_->ForEachFrame(
- base::Bind(&ReleaseAllMediaPlayers, base::Unretained(web_contents_)));
-#endif // defined(ENABLE_BROWSER_CDMS)
+ MediaWebContentsObserverAndroid::FromWebContents(web_contents_)
+ ->SuspendAllMediaPlayers();
+}
+
+void WebContentsAndroid::SetAudioMuted(JNIEnv* env,
+ const JavaParamRef<jobject>& jobj,
+ jboolean mute) {
+ web_contents_->SetAudioMuted(mute);
}
void WebContentsAndroid::ShowInterstitialPage(JNIEnv* env,
@@ -441,7 +433,7 @@ jboolean WebContentsAndroid::IsRenderWidgetHostViewReady(
void WebContentsAndroid::ExitFullscreen(JNIEnv* env,
const JavaParamRef<jobject>& obj) {
- web_contents_->ExitFullscreen();
+ web_contents_->ExitFullscreen(/*will_cause_resize=*/false);
}
void WebContentsAndroid::UpdateTopControlsState(
@@ -604,21 +596,15 @@ jint WebContentsAndroid::GetThemeColor(JNIEnv* env,
void WebContentsAndroid::RequestAccessibilitySnapshot(
JNIEnv* env,
const JavaParamRef<jobject>& obj,
- const JavaParamRef<jobject>& callback,
- jfloat y_offset,
- jfloat x_scroll) {
+ const JavaParamRef<jobject>& callback) {
// Secure the Java callback in a scoped object and give ownership of it to the
// base::Callback.
ScopedJavaGlobalRef<jobject> j_callback;
j_callback.Reset(env, callback);
gfx::DeviceDisplayInfo device_info;
- ContentViewCoreImpl* contentViewCore =
- ContentViewCoreImpl::FromWebContents(web_contents_);
- AccessibilitySnapshotParams* params = new AccessibilitySnapshotParams(
- contentViewCore->GetScaleFactor(), y_offset, x_scroll);
WebContentsImpl::AXTreeSnapshotCallback snapshot_callback =
- base::Bind(&AXTreeSnapshotCallback, j_callback, base::Owned(params));
+ base::Bind(&AXTreeSnapshotCallback, j_callback);
static_cast<WebContentsImpl*>(web_contents_)->RequestAXTreeSnapshot(
snapshot_callback);
}
@@ -682,6 +668,11 @@ void WebContentsAndroid::OnContextMenuClosed(JNIEnv* env,
->NotifyContextMenuClosed(CustomContextMenuContext());
}
+void WebContentsAndroid::ReloadLoFiImages(JNIEnv* env,
+ const JavaParamRef<jobject>& obj) {
+ static_cast<WebContentsImpl*>(web_contents_)->ReloadLoFiImages();
+}
+
void WebContentsAndroid::OnFinishGetContentBitmap(
ScopedJavaGlobalRef<jobject>* obj,
ScopedJavaGlobalRef<jobject>* callback,
diff --git a/chromium/content/browser/web_contents/web_contents_android.h b/chromium/content/browser/web_contents/web_contents_android.h
index 9453d52d020..432b65ac5a5 100644
--- a/chromium/content/browser/web_contents/web_contents_android.h
+++ b/chromium/content/browser/web_contents/web_contents_android.h
@@ -78,8 +78,11 @@ class CONTENT_EXPORT WebContentsAndroid
void OnHide(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
void OnShow(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
- void ReleaseMediaPlayers(JNIEnv* env,
- const base::android::JavaParamRef<jobject>& jobj);
+ void SuspendAllMediaPlayers(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& jobj);
+ void SetAudioMuted(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& jobj,
+ jboolean mute);
void ShowInterstitialPage(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
@@ -149,9 +152,7 @@ class CONTENT_EXPORT WebContentsAndroid
void RequestAccessibilitySnapshot(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj,
- const base::android::JavaParamRef<jobject>& callback,
- jfloat y_offset,
- jfloat x_scroll);
+ const base::android::JavaParamRef<jobject>& callback);
void ResumeMediaSession(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
@@ -178,6 +179,9 @@ class CONTENT_EXPORT WebContentsAndroid
void OnContextMenuClosed(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
+ void ReloadLoFiImages(JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& obj);
+
void set_synchronous_compositor_client(SynchronousCompositorClient* client) {
synchronous_compositor_client_ = client;
}
diff --git a/chromium/content/browser/web_contents/web_contents_impl.cc b/chromium/content/browser/web_contents/web_contents_impl.cc
index b5b0b7853c7..e41ef9f6c7d 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl.cc
@@ -14,6 +14,7 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
#include "base/metrics/histogram.h"
#include "base/process/process.h"
#include "base/profiler/scoped_tracker.h"
@@ -45,6 +46,7 @@
#include "content/browser/frame_host/navigation_handle_impl.h"
#include "content/browser/frame_host/navigator_impl.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/frame_host/render_frame_proxy_host.h"
#include "content/browser/frame_host/render_widget_host_view_child_frame.h"
#include "content/browser/geolocation/geolocation_service_context.h"
#include "content/browser/host_zoom_map_impl.h"
@@ -53,6 +55,7 @@
#include "content/browser/media/audio_stream_monitor.h"
#include "content/browser/media/capture/web_contents_audio_muter.h"
#include "content/browser/media/media_web_contents_observer.h"
+#include "content/browser/media/session/media_session.h"
#include "content/browser/message_port_message_filter.h"
#include "content/browser/plugin_content_origin_whitelist.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
@@ -72,6 +75,7 @@
#include "content/common/browser_plugin/browser_plugin_messages.h"
#include "content/common/frame_messages.h"
#include "content/common/input_messages.h"
+#include "content/common/page_messages.h"
#include "content/common/site_isolation_policy.h"
#include "content/common/ssl_status_serialization.h"
#include "content/common/view_messages.h"
@@ -114,7 +118,9 @@
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "skia/public/type_converters.h"
+#include "third_party/WebKit/public/web/WebSandboxFlags.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/accessibility/ax_tree_combiner.h"
#include "ui/base/layout.h"
#include "ui/gfx/display.h"
#include "ui/gfx/screen.h"
@@ -122,14 +128,10 @@
#if defined(OS_ANDROID)
#include "content/browser/android/content_video_view.h"
-#include "content/browser/media/android/media_session.h"
-#include "content/browser/media/android/media_web_contents_observer_android.h"
-#endif // OS_ANDROID
-
-#if defined(OS_ANDROID) && !defined(USE_AURA)
#include "content/browser/android/date_time_chooser_android.h"
+#include "content/browser/media/android/media_web_contents_observer_android.h"
#include "content/browser/web_contents/web_contents_android.h"
-#endif // OS_ANDROID && !USE_AURA
+#endif // OS_ANDROID
#if defined(OS_MACOSX)
#include "base/mac/foundation_util.h"
@@ -164,49 +166,12 @@ void NotifyCacheOnIO(
cache->OnExternalCacheHit(url, http_method);
}
-bool FindMatchingProcess(int render_process_id,
- bool* did_match_process,
- FrameTreeNode* node) {
- if (node->current_frame_host()->GetProcess()->GetID() == render_process_id) {
- *did_match_process = true;
- return false;
+bool HasMatchingProcess(FrameTree* tree, int render_process_id) {
+ for (FrameTreeNode* node : tree->Nodes()) {
+ if (node->current_frame_host()->GetProcess()->GetID() == render_process_id)
+ return true;
}
- return true;
-}
-
-bool ForEachFrameInternal(
- const base::Callback<void(RenderFrameHost*)>& on_frame,
- FrameTreeNode* node) {
- on_frame.Run(node->current_frame_host());
- return true;
-}
-
-bool ForEachPendingFrameInternal(
- const base::Callback<void(RenderFrameHost*)>& on_frame,
- FrameTreeNode* node) {
- RenderFrameHost* pending_frame_host =
- node->render_manager()->pending_frame_host();
- if (pending_frame_host)
- on_frame.Run(pending_frame_host);
- return true;
-}
-
-void SendToAllFramesInternal(int* number_of_messages,
- IPC::Message* message,
- RenderFrameHost* rfh) {
- *number_of_messages = *number_of_messages + 1;
- IPC::Message* message_copy = new IPC::Message(*message);
- message_copy->set_routing_id(rfh->GetRoutingID());
- rfh->Send(message_copy);
-}
-
-void AddRenderWidgetHostViewToSet(std::set<RenderWidgetHostView*>* set,
- RenderFrameHost* rfh) {
- RenderWidgetHostView* rwhv = static_cast<RenderFrameHostImpl*>(rfh)
- ->frame_tree_node()
- ->render_manager()
- ->GetRenderWidgetHostView();
- set->insert(rwhv);
+ return false;
}
void SetAccessibilityModeOnFrame(AccessibilityMode mode,
@@ -218,6 +183,44 @@ void ResetAccessibility(RenderFrameHost* rfh) {
static_cast<RenderFrameHostImpl*>(rfh)->AccessibilityReset();
}
+using AXTreeSnapshotCallback =
+ base::Callback<void(const ui::AXTreeUpdate&)>;
+
+// Helper class used by WebContentsImpl::RequestAXTreeSnapshot.
+// Handles the callbacks from parallel snapshot requests to each frame,
+// and feeds the results to an AXTreeCombiner, which converts them into a
+// single combined accessibility tree.
+class AXTreeSnapshotCombiner : public base::RefCounted<AXTreeSnapshotCombiner> {
+ public:
+ explicit AXTreeSnapshotCombiner(AXTreeSnapshotCallback callback)
+ : callback_(callback) {
+ }
+
+ AXTreeSnapshotCallback AddFrame(bool is_root) {
+ // Adds a reference to |this|.
+ return base::Bind(&AXTreeSnapshotCombiner::ReceiveSnapshot,
+ this,
+ is_root);
+ }
+
+ void ReceiveSnapshot(bool is_root, const ui::AXTreeUpdate& snapshot) {
+ combiner_.AddTree(snapshot, is_root);
+ }
+
+ private:
+ friend class base::RefCounted<AXTreeSnapshotCombiner>;
+
+ // This is called automatically after the last call to ReceiveSnapshot
+ // when there are no more references to this object.
+ ~AXTreeSnapshotCombiner() {
+ combiner_.Combine();
+ callback_.Run(combiner_.combined());
+ }
+
+ ui::AXTreeCombiner combiner_;
+ AXTreeSnapshotCallback callback_;
+};
+
} // namespace
WebContents* WebContents::Create(const WebContents::CreateParams& params) {
@@ -354,15 +357,11 @@ WebContentsImpl::WebContentsImpl(BrowserContext* browser_context)
controller_(this, browser_context),
render_view_host_delegate_view_(NULL),
created_with_opener_(false),
-#if defined(OS_WIN)
- accessible_parent_(NULL),
-#endif
frame_tree_(new NavigatorImpl(&controller_, this),
this,
this,
this,
this),
- is_loading_(false),
is_load_to_different_document_(false),
crashed_status_(base::TERMINATION_STATUS_STILL_RUNNING),
crashed_error_code_(0),
@@ -378,6 +377,7 @@ WebContentsImpl::WebContentsImpl(BrowserContext* browser_context)
did_first_visually_non_empty_paint_(false),
capturer_count_(0),
should_normally_be_visible_(true),
+ did_first_set_visible_(false),
is_being_destroyed_(false),
notify_disconnection_(false),
dialog_manager_(NULL),
@@ -398,6 +398,7 @@ WebContentsImpl::WebContentsImpl(BrowserContext* browser_context)
accessibility_mode_(
BrowserAccessibilityStateImpl::GetInstance()->accessibility_mode()),
audio_stream_monitor_(this),
+ bluetooth_connected_device_count_(0),
virtual_keyboard_requested_(false),
page_scale_factor_is_one_(true),
loading_weak_factory_(this),
@@ -410,6 +411,7 @@ WebContentsImpl::WebContentsImpl(BrowserContext* browser_context)
#else
media_web_contents_observer_.reset(new MediaWebContentsObserver(this));
#endif
+ loader_io_thread_notifier_.reset(new LoaderIOThreadNotifier(this));
wake_lock_service_context_.reset(new WakeLockServiceContext(this));
}
@@ -418,18 +420,15 @@ WebContentsImpl::~WebContentsImpl() {
rwh_input_event_router_.reset();
- // Delete all RFH pending shutdown, which will lead the corresponding RVH to
- // shutdown and be deleted as well.
- frame_tree_.ForEach(
- base::Bind(&RenderFrameHostManager::ClearRFHsPendingShutdown));
-
- // Destroy all WebUI instances.
- frame_tree_.ForEach(base::Bind(&RenderFrameHostManager::ClearWebUIInstances));
-
- for (std::set<RenderWidgetHostImpl*>::iterator iter =
- created_widgets_.begin(); iter != created_widgets_.end(); ++iter) {
- (*iter)->DetachDelegate();
+ for (FrameTreeNode* node : frame_tree_.Nodes()) {
+ // Delete all RFHs pending shutdown, which will lead the corresponding RVHs
+ // to be shutdown and be deleted as well.
+ node->render_manager()->ClearRFHsPendingShutdown();
+ node->render_manager()->ClearWebUIInstances();
}
+
+ for (RenderWidgetHostImpl* widget : created_widgets_)
+ widget->DetachDelegate();
created_widgets_.clear();
// Clear out any JavaScript state.
@@ -469,7 +468,8 @@ WebContentsImpl::~WebContentsImpl() {
// PlzNavigate: clear up state specific to browser-side navigation.
if (IsBrowserSideNavigationEnabled()) {
- frame_tree_.root()->ResetNavigationRequest(false);
+ // Do not update state as the WebContents is being destroyed.
+ frame_tree_.root()->ResetNavigationRequest(true);
if (root->speculative_frame_host()) {
root->speculative_frame_host()->SetRenderFrameCreated(false);
root->speculative_frame_host()->SetNavigationHandle(
@@ -510,11 +510,28 @@ WebContentsImpl* WebContentsImpl::CreateWithOpener(
TRACE_EVENT0("browser", "WebContentsImpl::CreateWithOpener");
WebContentsImpl* new_contents = new WebContentsImpl(params.browser_context);
+ FrameTreeNode* new_root = new_contents->GetFrameTree()->root();
+
if (!params.opener_suppressed && opener) {
- new_contents->GetFrameTree()->root()->SetOpener(opener);
+ new_root->SetOpener(opener);
new_contents->created_with_opener_ = true;
}
+ // If the opener is sandboxed, a new popup must inherit the opener's sandbox
+ // flags, and these flags take effect immediately. An exception is if the
+ // opener's sandbox flags lack the PropagatesToAuxiliaryBrowsingContexts
+ // bit (which is controlled by the "allow-popups-to-escape-sandbox" token).
+ // See https://html.spec.whatwg.org/#attr-iframe-sandbox.
+ if (opener) {
+ blink::WebSandboxFlags opener_flags = opener->effective_sandbox_flags();
+ const blink::WebSandboxFlags inherit_flag =
+ blink::WebSandboxFlags::PropagatesToAuxiliaryBrowsingContexts;
+ if ((opener_flags & inherit_flag) == inherit_flag) {
+ new_root->SetPendingSandboxFlags(opener_flags);
+ new_root->CommitPendingSandboxFlags();
+ }
+ }
+
// This may be true even when opener is null, such as when opening blocked
// popups.
if (params.created_with_opener)
@@ -647,7 +664,7 @@ bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host,
OnUnregisterProtocolHandler)
IPC_MESSAGE_HANDLER(FrameHostMsg_UpdatePageImportanceSignals,
OnUpdatePageImportanceSignals)
- IPC_MESSAGE_HANDLER(ViewHostMsg_Find_Reply, OnFindReply)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_Find_Reply, OnFindReply)
IPC_MESSAGE_HANDLER(ViewHostMsg_AppCacheAccessed, OnAppCacheAccessed)
IPC_MESSAGE_HANDLER(ViewHostMsg_WebUISend, OnWebUISend)
#if defined(ENABLE_PLUGINS)
@@ -670,8 +687,8 @@ bool WebContentsImpl::OnMessageReceived(RenderViewHost* render_view_host,
OnHideValidationMessage)
IPC_MESSAGE_HANDLER(ViewHostMsg_MoveValidationMessage,
OnMoveValidationMessage)
-#if defined(OS_ANDROID) && !defined(USE_AURA)
- IPC_MESSAGE_HANDLER(ViewHostMsg_FindMatchRects_Reply,
+#if defined(OS_ANDROID)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_FindMatchRects_Reply,
OnFindMatchRectsReply)
IPC_MESSAGE_HANDLER(ViewHostMsg_OpenDateTimeDialog,
OnOpenDateTimeDialog)
@@ -775,17 +792,37 @@ RenderFrameHostImpl* WebContentsImpl::FindFrameByFrameTreeNodeId(
void WebContentsImpl::ForEachFrame(
const base::Callback<void(RenderFrameHost*)>& on_frame) {
- frame_tree_.ForEach(base::Bind(&ForEachFrameInternal, on_frame));
+ for (FrameTreeNode* node : frame_tree_.Nodes()) {
+ on_frame.Run(node->current_frame_host());
+ }
+}
+
+std::vector<RenderFrameHost*> WebContentsImpl::GetAllFrames() {
+ std::vector<RenderFrameHost*> frame_hosts;
+ for (FrameTreeNode* node : frame_tree_.Nodes())
+ frame_hosts.push_back(node->current_frame_host());
+ return frame_hosts;
}
int WebContentsImpl::SendToAllFrames(IPC::Message* message) {
int number_of_messages = 0;
- ForEachFrame(
- base::Bind(&SendToAllFramesInternal, &number_of_messages, message));
+ for (RenderFrameHost* rfh : GetAllFrames()) {
+ if (!rfh->IsRenderFrameLive())
+ continue;
+
+ ++number_of_messages;
+ IPC::Message* message_copy = new IPC::Message(*message);
+ message_copy->set_routing_id(rfh->GetRoutingID());
+ rfh->Send(message_copy);
+ }
delete message;
return number_of_messages;
}
+void WebContentsImpl::SendPageMessage(IPC::Message* msg) {
+ frame_tree_.root()->render_manager()->SendPageMessage(msg);
+}
+
RenderViewHostImpl* WebContentsImpl::GetRenderViewHost() const {
return GetRenderManager()->current_host();
}
@@ -837,12 +874,14 @@ void WebContentsImpl::SetAccessibilityMode(AccessibilityMode mode) {
return;
accessibility_mode_ = mode;
- frame_tree_.ForEach(
- base::Bind(&ForEachFrameInternal,
- base::Bind(&SetAccessibilityModeOnFrame, mode)));
- frame_tree_.ForEach(
- base::Bind(&ForEachPendingFrameInternal,
- base::Bind(&SetAccessibilityModeOnFrame, mode)));
+
+ for (FrameTreeNode* node : frame_tree_.Nodes()) {
+ SetAccessibilityModeOnFrame(mode, node->current_frame_host());
+ RenderFrameHost* pending_frame_host =
+ node->render_manager()->pending_frame_host();
+ if (pending_frame_host)
+ SetAccessibilityModeOnFrame(mode, pending_frame_host);
+ }
}
void WebContentsImpl::AddAccessibilityMode(AccessibilityMode mode) {
@@ -854,10 +893,16 @@ void WebContentsImpl::RemoveAccessibilityMode(AccessibilityMode mode) {
}
void WebContentsImpl::RequestAXTreeSnapshot(AXTreeSnapshotCallback callback) {
- // TODO(dmazzoni): http://crbug.com/475608 This only returns the
- // accessibility tree from the main frame and everything in the
- // same site instance.
- GetMainFrame()->RequestAXTreeSnapshot(callback);
+ // Send a request to each of the frames in parallel. Each one will return
+ // an accessibility tree snapshot, and AXTreeSnapshotCombiner will combine
+ // them into a single tree and call |callback| with that result, then
+ // delete |combiner|.
+ AXTreeSnapshotCombiner* combiner = new AXTreeSnapshotCombiner(callback);
+ for (FrameTreeNode* frame_tree_node : frame_tree_.Nodes()) {
+ bool is_root = frame_tree_node->parent() == nullptr;
+ frame_tree_node->current_frame_host()->RequestAXTreeSnapshot(
+ combiner->AddFrame(is_root));
+ }
}
WebUI* WebContentsImpl::CreateSubframeWebUI(const GURL& url,
@@ -890,8 +935,8 @@ void WebContentsImpl::SetUserAgentOverride(const std::string& override) {
// Reload the page if a load is currently in progress to avoid having
// different parts of the page loaded using different user agents.
NavigationEntry* entry = controller_.GetVisibleEntry();
- if (is_loading_ && entry != NULL && entry->GetIsOverridingUserAgent())
- controller_.ReloadIgnoringCache(true);
+ if (IsLoading() && entry != NULL && entry->GetIsOverridingUserAgent())
+ controller_.ReloadBypassingCache(true);
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
UserAgentOverrideSet(override));
@@ -902,10 +947,12 @@ const std::string& WebContentsImpl::GetUserAgentOverride() const {
}
void WebContentsImpl::EnableTreeOnlyAccessibilityMode() {
- if (GetAccessibilityMode() != AccessibilityModeOff)
- ForEachFrame(base::Bind(&ResetAccessibility));
- else
+ if (GetAccessibilityMode() != AccessibilityModeOff) {
+ for (RenderFrameHost* rfh : GetAllFrames())
+ ResetAccessibility(rfh);
+ } else {
AddAccessibilityMode(AccessibilityModeTreeOnly);
+ }
}
bool WebContentsImpl::IsTreeOnlyAccessibilityModeForTesting() const {
@@ -916,16 +963,6 @@ bool WebContentsImpl::IsFullAccessibilityModeForTesting() const {
return accessibility_mode_ == AccessibilityModeComplete;
}
-#if defined(OS_WIN)
-void WebContentsImpl::SetParentNativeViewAccessible(
-gfx::NativeViewAccessible accessible_parent) {
- accessible_parent_ = accessible_parent;
- RenderFrameHostImpl* rfh = GetMainFrame();
- if (rfh)
- rfh->SetParentNativeViewAccessible(accessible_parent);
-}
-#endif
-
const PageImportanceSignals& WebContentsImpl::GetPageImportanceSignals() const {
return page_importance_signals_;
}
@@ -934,11 +971,8 @@ const base::string16& WebContentsImpl::GetTitle() const {
// Transient entries take precedence. They are used for interstitial pages
// that are shown on top of existing pages.
NavigationEntry* entry = controller_.GetTransientEntry();
- std::string accept_languages =
- GetContentClient()->browser()->GetAcceptLangs(
- GetBrowserContext());
if (entry) {
- return entry->GetTitleForDisplay(accept_languages);
+ return entry->GetTitleForDisplay();
}
WebUI* navigating_web_ui = GetRenderManager()->GetNavigatingWebUI();
@@ -979,7 +1013,7 @@ const base::string16& WebContentsImpl::GetTitle() const {
}
if (entry) {
- return entry->GetTitleForDisplay(accept_languages);
+ return entry->GetTitleForDisplay();
}
// |page_title_when_no_navigation_entry_| is finally used
@@ -1028,11 +1062,13 @@ SiteInstanceImpl* WebContentsImpl::GetPendingSiteInstance() const {
}
bool WebContentsImpl::IsLoading() const {
- return is_loading_;
+ return frame_tree_.IsLoading() &&
+ !(ShowingInterstitialPage() &&
+ GetRenderManager()->interstitial_page()->pause_throbber());
}
bool WebContentsImpl::IsLoadingToDifferentDocument() const {
- return is_loading_ && is_load_to_different_document_;
+ return IsLoading() && is_load_to_different_document_;
}
bool WebContentsImpl::IsWaitingForResponse() const {
@@ -1132,6 +1168,27 @@ void WebContentsImpl::SetAudioMuted(bool mute) {
NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
}
+void WebContentsImpl::IncrementBluetoothConnectedDeviceCount() {
+ // Notify for UI updates if the state changes.
+ bluetooth_connected_device_count_++;
+ if (bluetooth_connected_device_count_ == 1) {
+ NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
+ }
+}
+
+void WebContentsImpl::DecrementBluetoothConnectedDeviceCount() {
+ // Notify for UI updates if the state changes.
+ DCHECK(bluetooth_connected_device_count_ != 0);
+ bluetooth_connected_device_count_--;
+ if (bluetooth_connected_device_count_ == 0) {
+ NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB);
+ }
+}
+
+bool WebContentsImpl::IsConnectedToBluetoothDevice() const {
+ return bluetooth_connected_device_count_ > 0;
+}
+
bool WebContentsImpl::IsCrashed() const {
return (crashed_status_ == base::TERMINATION_STATUS_PROCESS_CRASHED ||
crashed_status_ == base::TERMINATION_STATUS_ABNORMAL_TERMINATION ||
@@ -1158,6 +1215,10 @@ base::TerminationStatus WebContentsImpl::GetCrashedStatus() const {
return crashed_status_;
}
+int WebContentsImpl::GetCrashedErrorCode() const {
+ return crashed_error_code_;
+}
+
bool WebContentsImpl::IsBeingDestroyed() const {
return is_being_destroyed_;
}
@@ -1265,6 +1326,19 @@ void WebContentsImpl::AttachToOuterWebContentsFrame(
WebContents* outer_web_contents,
RenderFrameHost* outer_contents_frame) {
CHECK(BrowserPluginGuestMode::UseCrossProcessFramesForGuests());
+ RenderFrameHostManager* render_manager = GetRenderManager();
+
+ // When the WebContents being initialized has an opener, the browser side
+ // Render{View,Frame}Host must be initialized and the RenderWidgetHostView
+ // created. This is needed because the usual initialization happens during
+ // the first navigation, but when attaching a new window we don't navigate
+ // before attaching. If the browser side is already initialized, the calls
+ // below will just early return.
+ render_manager->InitRenderView(GetRenderViewHost(), nullptr);
+ GetMainFrame()->Init();
+ if (!render_manager->GetRenderWidgetHostView())
+ CreateRenderWidgetHostViewForRenderManager(GetRenderViewHost());
+
// Create a link to our outer WebContents.
node_.reset(new WebContentsTreeNode());
node_->ConnectToOuterWebContents(
@@ -1276,16 +1350,21 @@ void WebContentsImpl::AttachToOuterWebContentsFrame(
// Create a proxy in top-level RenderFrameHostManager, pointing to the
// SiteInstance of the outer WebContents. The proxy will be used to send
// postMessage to the inner WebContents.
- GetRenderManager()->CreateOuterDelegateProxy(
+ render_manager->CreateOuterDelegateProxy(
outer_contents_frame->GetSiteInstance(),
static_cast<RenderFrameHostImpl*>(outer_contents_frame));
- GetRenderManager()->SetRWHViewForInnerContents(
- GetRenderManager()->GetRenderWidgetHostView());
+ render_manager->SetRWHViewForInnerContents(
+ render_manager->GetRenderWidgetHostView());
+
+ static_cast<RenderWidgetHostViewChildFrame*>(
+ render_manager->GetRenderWidgetHostView())
+ ->RegisterSurfaceNamespaceId();
}
void WebContentsImpl::Stop() {
- frame_tree_.ForEach(base::Bind(&FrameTreeNode::StopLoading));
+ for (FrameTreeNode* node : frame_tree_.Nodes())
+ node->StopLoading();
FOR_EACH_OBSERVER(WebContentsObserver, observers_, NavigationStopped());
}
@@ -1371,7 +1450,11 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params) {
GetRenderManager()->Init(site_instance.get(), view_routing_id,
params.main_frame_routing_id,
main_frame_widget_routing_id);
- frame_tree_.root()->SetFrameName(params.main_frame_name);
+
+ // blink::FrameTree::setName uses |name| as the |unique_name| for the main
+ // frame - let's do the same thing here.
+ std::string unique_name = params.main_frame_name;
+ frame_tree_.root()->SetFrameName(params.main_frame_name, unique_name);
WebContentsViewDelegate* delegate =
GetContentClient()->browser()->GetWebContentsViewDelegate(this);
@@ -1419,7 +1502,7 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params) {
manifest_manager_host_.reset(new ManifestManagerHost(this));
-#if defined(OS_ANDROID) && !defined(USE_AURA)
+#if defined(OS_ANDROID)
date_time_chooser_.reset(new DateTimeChooserAndroid());
#endif
@@ -1493,8 +1576,13 @@ WebContentsImpl::GetRenderWidgetHostViewsInTree() {
if (ShowingInterstitialPage()) {
set.insert(GetRenderWidgetHostView());
} else {
- ForEachFrame(
- base::Bind(&AddRenderWidgetHostViewToSet, base::Unretained(&set)));
+ for (RenderFrameHost* rfh : GetAllFrames()) {
+ RenderWidgetHostView* rwhv = static_cast<RenderFrameHostImpl*>(rfh)
+ ->frame_tree_node()
+ ->render_manager()
+ ->GetRenderWidgetHostView();
+ set.insert(rwhv);
+ }
}
return set;
}
@@ -1670,11 +1758,13 @@ void WebContentsImpl::EnterFullscreenMode(const GURL& origin) {
delegate_->EnterFullscreenModeForTab(this, origin);
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidToggleFullscreenModeForTab(IsFullscreenForCurrentTab(
- GetRenderViewHost()->GetWidget())));
+ DidToggleFullscreenModeForTab(
+ IsFullscreenForCurrentTab(
+ GetRenderViewHost()->GetWidget()),
+ false));
}
-void WebContentsImpl::ExitFullscreenMode() {
+void WebContentsImpl::ExitFullscreenMode(bool will_cause_resize) {
// This method is being called to leave renderer-initiated fullscreen mode.
// Make sure any existing fullscreen widget is shut down first.
RenderWidgetHostView* const widget_view = GetFullscreenRenderWidgetHostView();
@@ -1686,26 +1776,32 @@ void WebContentsImpl::ExitFullscreenMode() {
#if defined(OS_ANDROID)
ContentVideoView* video_view = ContentVideoView::GetInstance();
if (video_view != NULL)
- video_view->OnExitFullscreen();
+ video_view->ExitFullscreen();
#endif
if (delegate_)
delegate_->ExitFullscreenModeForTab(this);
- // Ensure web contents exit fullscreen state by sending a resize message,
- // which includes the fullscreen state. This is required for the situation
- // of the browser moving the view into a fullscreen state "browser fullscreen"
- // and then the contents entering "tab fullscreen". Exiting the contents
- // "tab fullscreen" then won't have the side effect of the view resizing,
- // hence the explicit call here is required.
- if (RenderWidgetHostView* rwh_view = GetRenderWidgetHostView()) {
- if (RenderWidgetHost* render_widget_host = rwh_view->GetRenderWidgetHost())
- render_widget_host->WasResized();
+ // The fullscreen state is communicated to the renderer through a resize
+ // message. If the change in fullscreen state doesn't cause a view resize
+ // then we must ensure web contents exit the fullscreen state by explicitly
+ // sending a resize message. This is required for the situation of the browser
+ // moving the view into a "browser fullscreen" state and then the contents
+ // entering "tab fullscreen". Exiting the contents "tab fullscreen" then won't
+ // have the side effect of the view resizing, hence the explicit call here is
+ // required.
+ if (!will_cause_resize) {
+ if (RenderWidgetHostView* rwhv = GetRenderWidgetHostView()) {
+ if (RenderWidgetHost* render_widget_host = rwhv->GetRenderWidgetHost())
+ render_widget_host->WasResized();
+ }
}
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidToggleFullscreenModeForTab(IsFullscreenForCurrentTab(
- GetRenderViewHost()->GetWidget())));
+ DidToggleFullscreenModeForTab(
+ IsFullscreenForCurrentTab(
+ GetRenderViewHost()->GetWidget()),
+ will_cause_resize));
}
bool WebContentsImpl::IsFullscreenForCurrentTab(
@@ -1751,11 +1847,15 @@ void WebContentsImpl::LostMouseLock(RenderWidgetHostImpl* render_widget_host) {
void WebContentsImpl::ForwardCompositorProto(
RenderWidgetHostImpl* render_widget_host,
const std::vector<uint8_t>& proto) {
- if (render_widget_host != GetRenderViewHost()->GetWidget())
- return;
-
if (delegate_)
- delegate_->ForwardCompositorProto(proto);
+ delegate_->ForwardCompositorProto(render_widget_host, proto);
+}
+
+void WebContentsImpl::OnRenderFrameProxyVisibilityChanged(bool visible) {
+ if (visible)
+ WasShown();
+ else
+ WasHidden();
}
void WebContentsImpl::CreateNewWindow(
@@ -1771,12 +1871,6 @@ void WebContentsImpl::CreateNewWindow(
// SiteInstance in its own BrowsingInstance.
bool is_guest = BrowserPluginGuest::IsGuest(this);
- if (is_guest && BrowserPluginGuestMode::UseCrossProcessFramesForGuests()) {
- // TODO(lazyboy): CreateNewWindow doesn't work for OOPIF-based <webview>
- // yet.
- NOTREACHED();
- }
-
// If the opener is to be suppressed, the new window can be in any process.
// Since routing ids are process specific, we must not have one passed in
// as argument here.
@@ -1791,10 +1885,7 @@ void WebContentsImpl::CreateNewWindow(
// in this WebContents' FrameTree. If any other process sends the request, it
// is invalid and the process must be terminated.
int render_process_id = source_site_instance->GetProcess()->GetID();
- bool did_match_process = false;
- frame_tree_.ForEach(
- base::Bind(&FindMatchingProcess, render_process_id, &did_match_process));
- if (!did_match_process) {
+ if (!HasMatchingProcess(&frame_tree_, render_process_id)) {
RenderProcessHost* rph = source_site_instance->GetProcess();
base::ProcessHandle process_handle = rph->GetHandle();
if (process_handle != base::kNullProcessHandle) {
@@ -1831,7 +1922,10 @@ void WebContentsImpl::CreateNewWindow(
// delete the RenderView that had already been created.
Send(new ViewMsg_Close(route_id));
}
- GetRenderViewHost()->GetProcess()->ResumeRequestsForView(route_id);
+ // It's safe to only target the frame because the render process will not
+ // have a chance to create more frames at this point.
+ ResourceDispatcherHostImpl::ResumeBlockedRequestsForRouteFromUI(
+ GlobalFrameRoutingId(render_process_id, main_frame_route_id));
return;
}
@@ -1939,20 +2033,16 @@ void WebContentsImpl::CreateNewWidget(int32_t render_process_id,
int32_t route_id,
bool is_fullscreen,
blink::WebPopupType popup_type) {
- RenderProcessHost* process = GetRenderProcessHost();
+ RenderProcessHost* process = RenderProcessHost::FromID(render_process_id);
// A message to create a new widget can only come from an active process for
// this WebContentsImpl instance. If any other process sends the request,
// it is invalid and the process must be terminated.
- bool did_match_process = false;
- frame_tree_.ForEach(
- base::Bind(&FindMatchingProcess, render_process_id, &did_match_process));
- if (!did_match_process) {
- RenderProcessHost* rph = RenderProcessHost::FromID(render_process_id);
- base::ProcessHandle process_handle = rph->GetHandle();
+ if (!HasMatchingProcess(&frame_tree_, render_process_id)) {
+ base::ProcessHandle process_handle = process->GetHandle();
if (process_handle != base::kNullProcessHandle) {
RecordAction(
base::UserMetricsAction("Terminate_ProcessMismatch_CreateNewWidget"));
- rph->Shutdown(RESULT_CODE_KILLED, false);
+ process->Shutdown(RESULT_CODE_KILLED, false);
}
return;
}
@@ -2194,7 +2284,19 @@ void WebContentsImpl::OnMoveValidationMessage(
delegate_->MoveValidationMessage(this, anchor_in_root_view);
}
-void WebContentsImpl::DidSendScreenRects(RenderWidgetHostImpl* rwh) {
+void WebContentsImpl::SendScreenRects() {
+ for (FrameTreeNode* node : frame_tree_.Nodes()) {
+ if (node->current_frame_host()->GetRenderWidgetHost())
+ node->current_frame_host()->GetRenderWidgetHost()->SendScreenRects();
+ }
+
+ RenderWidgetHostViewBase* rwhv =
+ static_cast<RenderWidgetHostViewBase*>(GetRenderWidgetHostView());
+ if (rwhv) {
+ SendPageMessage(new PageMsg_UpdateWindowScreenRect(
+ MSG_ROUTING_NONE, rwhv->GetBoundsInRootWindow()));
+ }
+
if (browser_plugin_embedder_)
browser_plugin_embedder_->DidSendScreenRects();
}
@@ -2290,13 +2392,35 @@ void WebContentsImpl::AttachInterstitialPage(
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
DidAttachInterstitialPage());
+
+ // Stop the throbber if needed while the interstitial page is shown.
+ if (frame_tree_.IsLoading())
+ LoadingStateChanged(true, true, nullptr);
+}
+
+void WebContentsImpl::DidProceedOnInterstitial() {
+ // The interstitial page should no longer be pausing the throbber.
+ DCHECK(!(ShowingInterstitialPage() &&
+ GetRenderManager()->interstitial_page()->pause_throbber()));
+
+ // Restart the throbber now that the interstitial page no longer pauses it.
+ if (ShowingInterstitialPage() && frame_tree_.IsLoading())
+ LoadingStateChanged(true, true, nullptr);
}
void WebContentsImpl::DetachInterstitialPage() {
+ bool interstitial_pausing_throbber =
+ ShowingInterstitialPage() &&
+ GetRenderManager()->interstitial_page()->pause_throbber();
if (ShowingInterstitialPage())
GetRenderManager()->remove_interstitial_page();
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
DidDetachInterstitialPage());
+
+ // Restart the throbber if needed now that the interstitial page is going
+ // away.
+ if (interstitial_pausing_throbber && frame_tree_.IsLoading())
+ LoadingStateChanged(true, true, nullptr);
}
void WebContentsImpl::SetHistoryOffsetAndLength(int history_offset,
@@ -2313,13 +2437,17 @@ void WebContentsImpl::SetHistoryOffsetAndLengthForView(
render_view_host->GetRoutingID(), history_offset, history_length));
}
-void WebContentsImpl::ReloadFocusedFrame(bool ignore_cache) {
+void WebContentsImpl::ReloadFocusedFrame(bool bypass_cache) {
RenderFrameHost* focused_frame = GetFocusedFrame();
if (!focused_frame)
return;
focused_frame->Send(new FrameMsg_Reload(
- focused_frame->GetRoutingID(), ignore_cache));
+ focused_frame->GetRoutingID(), bypass_cache));
+}
+
+void WebContentsImpl::ReloadLoFiImages() {
+ SendToAllFrames(new FrameMsg_ReloadLoFiImages(MSG_ROUTING_NONE));
}
void WebContentsImpl::Undo() {
@@ -2674,14 +2802,6 @@ void WebContentsImpl::DidGetRedirectForResourceRequest(
NOTIFICATION_RESOURCE_RECEIVED_REDIRECT,
Source<WebContents>(this),
Details<const ResourceRedirectDetails>(&details));
-
- if (IsResourceTypeFrame(details.resource_type)) {
- NavigationHandleImpl* navigation_handle =
- static_cast<RenderFrameHostImpl*>(render_frame_host)
- ->navigation_handle();
- if (navigation_handle)
- navigation_handle->DidRedirectNavigation(details.new_url);
- }
}
void WebContentsImpl::NotifyWebContentsFocused() {
@@ -2696,7 +2816,8 @@ void WebContentsImpl::SystemDragEnded() {
}
void WebContentsImpl::UserGestureDone() {
- OnUserGesture(GetRenderViewHost()->GetWidget());
+ OnUserInteraction(GetRenderViewHost()->GetWidget(),
+ blink::WebInputEvent::Undefined);
}
void WebContentsImpl::SetClosedByUserGesture(bool value) {
@@ -2796,7 +2917,7 @@ int WebContentsImpl::DownloadImage(
const WebContents::ImageDownloadCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
static int next_image_download_id = 0;
- const image_downloader::ImageDownloaderPtr& mojo_image_downloader =
+ const content::mojom::ImageDownloaderPtr& mojo_image_downloader =
GetMainFrame()->GetMojoImageDownloader();
const int download_id = ++next_image_download_id;
if (!mojo_image_downloader) {
@@ -2804,29 +2925,18 @@ int WebContentsImpl::DownloadImage(
// Android), the downloader service will be invalid. Pre-Mojo, this would
// hang the callback indefinetly since the IPC would be dropped. Now,
// respond with a 400 HTTP error code to indicate that something went wrong.
- image_downloader::DownloadResultPtr result =
- image_downloader::DownloadResult::New();
- result->http_status_code = 400;
BrowserThread::PostTask(
BrowserThread::UI, FROM_HERE,
base::Bind(&WebContentsImpl::OnDidDownloadImage,
- weak_factory_.GetWeakPtr(), callback, download_id, url,
- base::Passed(&result)));
+ weak_factory_.GetWeakPtr(), callback, download_id, url, 400,
+ nullptr, nullptr));
return download_id;
}
- image_downloader::DownloadRequestPtr req =
- image_downloader::DownloadRequest::New();
-
- req->url = mojo::String::From(url);
- req->is_favicon = is_favicon;
- req->max_bitmap_size = max_bitmap_size;
- req->bypass_cache = bypass_cache;
-
mojo_image_downloader->DownloadImage(
- std::move(req), base::Bind(&WebContentsImpl::OnDidDownloadImage,
- weak_factory_.GetWeakPtr(), callback,
- download_id, url));
+ mojo::String::From(url), is_favicon, max_bitmap_size, bypass_cache,
+ base::Bind(&WebContentsImpl::OnDidDownloadImage,
+ weak_factory_.GetWeakPtr(), callback, download_id, url));
return download_id;
}
@@ -2848,7 +2958,8 @@ void WebContentsImpl::Find(int request_id,
browser_plugin_embedder_->Find(request_id, search_text, options)) {
return;
}
- Send(new ViewMsg_Find(GetRoutingID(), request_id, search_text, options));
+ GetMainFrame()->Send(new FrameMsg_Find(GetMainFrame()->GetRoutingID(),
+ request_id, search_text, options));
}
void WebContentsImpl::StopFinding(StopFindAction action) {
@@ -2857,7 +2968,8 @@ void WebContentsImpl::StopFinding(StopFindAction action) {
browser_plugin_embedder_->StopFinding(action)) {
return;
}
- Send(new ViewMsg_StopFinding(GetRoutingID(), action));
+ GetMainFrame()->Send(
+ new FrameMsg_StopFinding(GetMainFrame()->GetRoutingID(), action));
}
void WebContentsImpl::InsertCSS(const std::string& css) {
@@ -2877,10 +2989,10 @@ void WebContentsImpl::HasManifest(const HasManifestCallback& callback) {
manifest_manager_host_->HasManifest(GetMainFrame(), callback);
}
-void WebContentsImpl::ExitFullscreen() {
+void WebContentsImpl::ExitFullscreen(bool will_cause_resize) {
// Clean up related state and initiate the fullscreen exit.
GetRenderViewHost()->GetWidget()->RejectMouseLockOrUnlockIfNecessary();
- ExitFullscreenMode();
+ ExitFullscreenMode(will_cause_resize);
}
void WebContentsImpl::ResumeLoadingCreatedWebContents() {
@@ -2900,9 +3012,28 @@ void WebContentsImpl::ResumeLoadingCreatedWebContents() {
}
bool WebContentsImpl::FocusLocationBarByDefault() {
- NavigationEntry* entry = controller_.GetVisibleEntry();
- if (entry && entry->GetURL() == GURL(url::kAboutBlankURL))
+ // When the browser is started with about:blank as the startup URL, focus
+ // the location bar (which will also select its contents) so people can
+ // simply begin typing to navigate elsewhere.
+ //
+ // We need to be careful not to trigger this for anything other than the
+ // startup navigation. In particular, if we allow an attacker to open a
+ // popup to about:blank, then navigate, focusing the Omnibox will cause the
+ // end of the new URL to be scrolled into view instead of the start,
+ // allowing the attacker to spoof other URLs. The conditions checked here
+ // are all aimed at ensuring no such attacker-controlled navigation can
+ // trigger this.
+ //
+ // Note that we check the pending entry instead of the visible one; for the
+ // startup URL case these are the same, but for the attacker-controlled
+ // navigation case the visible entry is the committed "about:blank" URL and
+ // the pending entry is the problematic navigation elsewhere.
+ NavigationEntryImpl* entry = controller_.GetPendingEntry();
+ if (controller_.IsInitialNavigation() && entry &&
+ !entry->is_renderer_initiated() &&
+ entry->GetURL() == GURL(url::kAboutBlankURL)) {
return true;
+ }
return delegate_ && delegate_->ShouldFocusLocationBarByDefault(this);
}
@@ -3063,7 +3194,7 @@ void WebContentsImpl::DidNavigateMainFramePreCommit(
return;
}
if (IsFullscreenForCurrentTab(GetRenderViewHost()->GetWidget()))
- ExitFullscreen();
+ ExitFullscreen(false);
DCHECK(!IsFullscreenForCurrentTab(GetRenderViewHost()->GetWidget()));
}
@@ -3188,8 +3319,8 @@ void WebContentsImpl::OnDidLoadResourceFromMemoryCache(
resource_type == RESOURCE_TYPE_MEDIA ?
GetBrowserContext()->GetMediaRequestContextForRenderProcess(
GetRenderProcessHost()->GetID()) :
- GetBrowserContext()->GetRequestContextForRenderProcess(
- GetRenderProcessHost()->GetID()));
+ GetRenderProcessHost()->GetStoragePartition()->
+ GetURLRequestContext());
BrowserThread::PostTask(
BrowserThread::IO,
FROM_HERE,
@@ -3362,7 +3493,7 @@ void WebContentsImpl::OnFindReply(int request_id,
}
}
-#if defined(OS_ANDROID) && !defined(USE_AURA)
+#if defined(OS_ANDROID)
void WebContentsImpl::OnFindMatchRectsReply(
int version,
const std::vector<gfx::RectF>& rects,
@@ -3512,29 +3643,26 @@ void WebContentsImpl::OnUpdateFaviconURL(
DidUpdateFaviconURL(candidates));
}
-#if defined(OS_ANDROID)
-
void WebContentsImpl::OnMediaSessionStateChanged() {
MediaSession* session = MediaSession::Get(this);
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
MediaSessionStateChanged(session->IsControllable(),
- session->IsSuspended()));
+ session->IsSuspended(),
+ session->metadata()));
}
void WebContentsImpl::ResumeMediaSession() {
- MediaSession::Get(this)->Resume();
+ MediaSession::Get(this)->Resume(MediaSession::SuspendType::UI);
}
void WebContentsImpl::SuspendMediaSession() {
- MediaSession::Get(this)->Suspend();
+ MediaSession::Get(this)->Suspend(MediaSession::SuspendType::UI);
}
void WebContentsImpl::StopMediaSession() {
- MediaSession::Get(this)->Stop();
+ MediaSession::Get(this)->Stop(MediaSession::SuspendType::UI);
}
-#endif // defined(OS_ANDROID)
-
void WebContentsImpl::OnFirstVisuallyNonEmptyPaint() {
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
DidFirstVisuallyNonEmptyPaint());
@@ -3577,53 +3705,6 @@ bool WebContentsImpl::HasAccessedInitialDocument() {
return has_accessed_initial_document_;
}
-// Notifies the RenderWidgetHost instance about the fact that the page is
-// loading, or done loading.
-void WebContentsImpl::SetIsLoading(bool is_loading,
- bool to_different_document,
- LoadNotificationDetails* details) {
- if (is_loading == is_loading_)
- return;
-
- if (!is_loading) {
- load_state_ = net::LoadStateWithParam(net::LOAD_STATE_IDLE,
- base::string16());
- load_state_host_.clear();
- upload_size_ = 0;
- upload_position_ = 0;
- }
-
- GetRenderManager()->SetIsLoading(is_loading);
-
- is_loading_ = is_loading;
- waiting_for_response_ = is_loading;
- is_load_to_different_document_ = to_different_document;
-
- if (delegate_)
- delegate_->LoadingStateChanged(this, to_different_document);
- NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD);
-
- std::string url = (details ? details->url.possibly_invalid_spec() : "NULL");
- if (is_loading) {
- TRACE_EVENT_ASYNC_BEGIN2("browser,navigation", "WebContentsImpl Loading",
- this, "URL", url, "Main FrameTreeNode id",
- GetFrameTree()->root()->frame_tree_node_id());
- FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidStartLoading());
- } else {
- TRACE_EVENT_ASYNC_END1("browser,navigation", "WebContentsImpl Loading",
- this, "URL", url);
- FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidStopLoading());
- }
-
- // TODO(avi): Remove. http://crbug.com/170921
- int type = is_loading ? NOTIFICATION_LOAD_START : NOTIFICATION_LOAD_STOP;
- NotificationDetails det = NotificationService::NoDetails();
- if (details)
- det = Details<LoadNotificationDetails>(details);
- NotificationService::current()->Notify(
- type, Source<NavigationController>(&controller_), det);
-}
-
void WebContentsImpl::UpdateMaxPageIDIfNecessary(RenderViewHost* rvh) {
// If we are creating a RVH for a restored controller, then we need to make
// sure the RenderView starts with a next_page_id_ larger than the number
@@ -3689,6 +3770,59 @@ void WebContentsImpl::ResetLoadProgressState() {
loading_last_progress_update_ = base::TimeTicks();
}
+// Notifies the RenderWidgetHost instance about the fact that the page is
+// loading, or done loading.
+void WebContentsImpl::LoadingStateChanged(bool to_different_document,
+ bool due_to_interstitial,
+ LoadNotificationDetails* details) {
+ // Do not send notifications about loading changes in the FrameTree while the
+ // interstitial page is pausing the throbber.
+ if (ShowingInterstitialPage() &&
+ GetRenderManager()->interstitial_page()->pause_throbber() &&
+ !due_to_interstitial) {
+ return;
+ }
+
+ bool is_loading = IsLoading();
+
+ if (!is_loading) {
+ load_state_ = net::LoadStateWithParam(net::LOAD_STATE_IDLE,
+ base::string16());
+ load_state_host_.clear();
+ upload_size_ = 0;
+ upload_position_ = 0;
+ }
+
+ GetRenderManager()->SetIsLoading(is_loading);
+
+ waiting_for_response_ = is_loading;
+ is_load_to_different_document_ = to_different_document;
+
+ if (delegate_)
+ delegate_->LoadingStateChanged(this, to_different_document);
+ NotifyNavigationStateChanged(INVALIDATE_TYPE_LOAD);
+
+ std::string url = (details ? details->url.possibly_invalid_spec() : "NULL");
+ if (is_loading) {
+ TRACE_EVENT_ASYNC_BEGIN2("browser,navigation", "WebContentsImpl Loading",
+ this, "URL", url, "Main FrameTreeNode id",
+ GetFrameTree()->root()->frame_tree_node_id());
+ FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidStartLoading());
+ } else {
+ TRACE_EVENT_ASYNC_END1("browser,navigation", "WebContentsImpl Loading",
+ this, "URL", url);
+ FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidStopLoading());
+ }
+
+ // TODO(avi): Remove. http://crbug.com/170921
+ int type = is_loading ? NOTIFICATION_LOAD_START : NOTIFICATION_LOAD_STOP;
+ NotificationDetails det = NotificationService::NoDetails();
+ if (details)
+ det = Details<LoadNotificationDetails>(details);
+ NotificationService::current()->Notify(
+ type, Source<NavigationController>(&controller_), det);
+}
+
void WebContentsImpl::NotifyViewSwapped(RenderViewHost* old_host,
RenderViewHost* new_host) {
// After sending out a swap notification, we need to send a disconnect
@@ -3744,6 +3878,16 @@ void WebContentsImpl::RenderFrameCreated(RenderFrameHost* render_frame_host) {
observers_,
RenderFrameCreated(render_frame_host));
SetAccessibilityModeOnFrame(accessibility_mode_, render_frame_host);
+
+ if (!render_frame_host->IsRenderFrameLive() || render_frame_host->GetParent())
+ return;
+
+ NavigationEntry* entry = controller_.GetPendingEntry();
+ if (entry && entry->IsViewSourceMode()) {
+ // Put the renderer in view source mode.
+ render_frame_host->Send(
+ new FrameMsg_EnableViewSourceMode(render_frame_host->GetRoutingID()));
+ }
}
void WebContentsImpl::RenderFrameDeleted(RenderFrameHost* render_frame_host) {
@@ -3774,18 +3918,14 @@ void WebContentsImpl::RunJavaScriptMessage(
// showing an interstitial as it's shown over the previous page and we don't
// want the hidden page's dialogs to interfere with the interstitial.
bool suppress_this_message =
- static_cast<RenderFrameHostImpl*>(render_frame_host)->is_swapped_out() ||
ShowingInterstitialPage() || !delegate_ ||
delegate_->ShouldSuppressDialogs(this) ||
!delegate_->GetJavaScriptDialogManager(this);
if (!suppress_this_message) {
- std::string accept_lang = GetContentClient()->browser()->
- GetAcceptLangs(GetBrowserContext());
dialog_manager_ = delegate_->GetJavaScriptDialogManager(this);
dialog_manager_->RunJavaScriptDialog(
- this, frame_url, accept_lang, javascript_message_type, message,
- default_prompt,
+ this, frame_url, javascript_message_type, message, default_prompt,
base::Bind(&WebContentsImpl::OnDialogClosed, base::Unretained(this),
render_frame_host->GetProcess()->GetID(),
render_frame_host->GetRoutingID(), reply_msg, false),
@@ -3806,7 +3946,6 @@ void WebContentsImpl::RunJavaScriptMessage(
void WebContentsImpl::RunBeforeUnloadConfirm(
RenderFrameHost* render_frame_host,
- const base::string16& message,
bool is_reload,
IPC::Message* reply_msg) {
RenderFrameHostImpl* rfhi =
@@ -3815,7 +3954,7 @@ void WebContentsImpl::RunBeforeUnloadConfirm(
delegate_->WillRunBeforeUnloadConfirm();
bool suppress_this_message =
- rfhi->rfh_state() != RenderFrameHostImpl::STATE_DEFAULT ||
+ !rfhi->is_active() ||
ShowingInterstitialPage() || !delegate_ ||
delegate_->ShouldSuppressDialogs(this) ||
!delegate_->GetJavaScriptDialogManager(this);
@@ -3827,7 +3966,7 @@ void WebContentsImpl::RunBeforeUnloadConfirm(
is_showing_before_unload_dialog_ = true;
dialog_manager_ = delegate_->GetJavaScriptDialogManager(this);
dialog_manager_->RunBeforeUnloadDialog(
- this, message, is_reload,
+ this, is_reload,
base::Bind(&WebContentsImpl::OnDialogClosed, base::Unretained(this),
render_frame_host->GetProcess()->GetID(),
render_frame_host->GetRoutingID(), reply_msg,
@@ -3844,12 +3983,6 @@ bool WebContentsImpl::IsNeverVisible() {
return delegate_->IsNeverVisible(this);
}
-#if defined(OS_WIN)
-gfx::NativeViewAccessible WebContentsImpl::GetParentNativeViewAccessible() {
- return accessible_parent_;
-}
-#endif
-
RenderViewHostDelegateView* WebContentsImpl::GetDelegateView() {
return render_view_host_delegate_view_;
}
@@ -3889,13 +4022,6 @@ void WebContentsImpl::RenderViewCreated(RenderViewHost* render_view_host) {
Source<WebContents>(this),
Details<RenderViewHost>(render_view_host));
- NavigationEntry* entry = controller_.GetPendingEntry();
- if (entry && entry->IsViewSourceMode()) {
- // Put the renderer in view source mode.
- render_view_host->Send(
- new ViewMsg_EnableViewSourceMode(render_view_host->GetRoutingID()));
- }
-
view_->RenderViewCreated(render_view_host);
FOR_EACH_OBSERVER(
@@ -3940,7 +4066,7 @@ void WebContentsImpl::RenderViewTerminated(RenderViewHost* rvh,
// Ensure fullscreen mode is exited in the |delegate_| since a crashed
// renderer may not have made a clean exit.
if (IsFullscreenForCurrentTab(GetRenderViewHost()->GetWidget()))
- ExitFullscreenMode();
+ ExitFullscreenMode(false);
// Cancel any visible dialogs so they are not left dangling over the sad tab.
CancelActiveAndPendingDialogs();
@@ -3948,15 +4074,13 @@ void WebContentsImpl::RenderViewTerminated(RenderViewHost* rvh,
if (delegate_)
delegate_->HideValidationMessage(this);
- SetIsLoading(false, true, nullptr);
- NotifyDisconnected();
- SetIsCrashed(status, error_code);
-
// Reset the loading progress. TODO(avi): What does it mean to have a
// "renderer crash" when there is more than one renderer process serving a
// webpage? Once this function is called at a more granular frame level, we
// probably will need to more granularly reset the state here.
ResetLoadProgressState();
+ NotifyDisconnected();
+ SetIsCrashed(status, error_code);
FOR_EACH_OBSERVER(WebContentsObserver,
observers_,
@@ -4050,7 +4174,7 @@ void WebContentsImpl::RequestMove(const gfx::Rect& new_bounds) {
void WebContentsImpl::DidStartLoading(FrameTreeNode* frame_tree_node,
bool to_different_document) {
- SetIsLoading(true, to_different_document, nullptr);
+ LoadingStateChanged(to_different_document, false, nullptr);
// Notify accessibility that the user is navigating away from the
// current document.
@@ -4084,7 +4208,7 @@ void WebContentsImpl::DidStopLoading() {
controller_.GetCurrentEntryIndex()));
}
- SetIsLoading(false, true, details.get());
+ LoadingStateChanged(true, false, details.get());
}
void WebContentsImpl::DidChangeLoadProgress() {
@@ -4206,9 +4330,9 @@ void WebContentsImpl::UpdateTitle(RenderFrameHost* render_frame_host,
NavigationEntryImpl* entry = controller_.GetEntryWithPageID(
render_frame_host->GetSiteInstance(), page_id);
- NavigationEntryImpl* new_entry = controller_.GetEntryWithUniqueID(
- static_cast<RenderFrameHostImpl*>(render_frame_host)->nav_entry_id());
- DCHECK_EQ(entry, new_entry);
+ // TODO(creis): Find a way to use nav entry IDs to locate the entry to update,
+ // and intentionally skip updates when the most recent commit was ignored.
+ // See https://crbug.com/577449.
// We can handle title updates when we don't have an entry in
// UpdateTitleForEntry, but only if the update is from the current RVH.
@@ -4272,16 +4396,12 @@ void WebContentsImpl::EnsureOpenerProxiesExist(RenderFrameHost* source_rfh) {
return;
}
- if (GetBrowserPluginGuest()) {
- // We create a swapped out RenderView or RenderFrameProxyHost for the
- // embedder in the guest's render process but we intentionally do not
- // expose the embedder's opener chain to it.
- if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- source_web_contents->GetRenderManager()->CreateRenderFrameProxy(
- GetSiteInstance());
- } else {
- source_web_contents->CreateSwappedOutRenderView(GetSiteInstance());
- }
+ if (this != source_web_contents && GetBrowserPluginGuest()) {
+ // We create a RenderFrameProxyHost for the embedder in the guest's render
+ // process but we intentionally do not expose the embedder's opener chain
+ // to it.
+ source_web_contents->GetRenderManager()->CreateRenderFrameProxy(
+ GetSiteInstance());
} else {
RenderFrameHostImpl* source_rfhi =
static_cast<RenderFrameHostImpl*>(source_rfh);
@@ -4301,36 +4421,24 @@ bool WebContentsImpl::AddMessageToConsole(int32_t level,
source_id);
}
-int WebContentsImpl::CreateSwappedOutRenderView(
- SiteInstance* instance) {
- int render_view_routing_id = MSG_ROUTING_NONE;
- if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- GetRenderManager()->CreateRenderFrameProxy(instance);
- } else {
- GetRenderManager()->CreateRenderFrame(
- instance, CREATE_RF_SWAPPED_OUT | CREATE_RF_HIDDEN,
- &render_view_routing_id);
- }
- return render_view_routing_id;
-}
-
-void WebContentsImpl::OnUserGesture(RenderWidgetHostImpl* render_widget_host) {
+void WebContentsImpl::OnUserInteraction(
+ RenderWidgetHostImpl* render_widget_host,
+ const blink::WebInputEvent::Type type) {
+ // Ignore when the renderer is swapped out.
+ // TODO(dominickn,creis): support widgets for out-of-process iframes.
if (render_widget_host != GetRenderViewHost()->GetWidget())
return;
- // Notify observers.
- FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidGetUserGesture());
+ FOR_EACH_OBSERVER(WebContentsObserver, observers_,
+ DidGetUserInteraction(type));
ResourceDispatcherHostImpl* rdh = ResourceDispatcherHostImpl::Get();
- if (rdh) // NULL in unittests.
+ // Exclude scroll events as user gestures for resource load dispatches.
+ // rdh is NULL in unittests.
+ if (rdh && type != blink::WebInputEvent::MouseWheel)
rdh->OnUserGesture(this);
}
-void WebContentsImpl::OnUserInteraction(const blink::WebInputEvent::Type type) {
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidGetUserInteraction(type));
-}
-
void WebContentsImpl::OnIgnoredUIEvent() {
// Notify observers.
FOR_EACH_OBSERVER(WebContentsObserver, observers_, DidGetIgnoredUIEvent());
@@ -4338,6 +4446,9 @@ void WebContentsImpl::OnIgnoredUIEvent() {
void WebContentsImpl::RendererUnresponsive(
RenderWidgetHostImpl* render_widget_host) {
+ FOR_EACH_OBSERVER(WebContentsObserver, observers_,
+ OnRendererUnresponsive(render_widget_host));
+
// Don't show hung renderer dialog for a swapped out RVH.
if (render_widget_host != GetRenderViewHost()->GetWidget())
return;
@@ -4404,9 +4515,7 @@ void WebContentsImpl::LoadStateChanged(
load_state_ = load_state;
upload_position_ = upload_position;
upload_size_ = upload_size;
- load_state_host_ = url_formatter::IDNToUnicode(
- url.host(),
- GetContentClient()->browser()->GetAcceptLangs(GetBrowserContext()));
+ load_state_host_ = url_formatter::IDNToUnicode(url.host());
if (load_state_.state == net::LOAD_STATE_READING_RESPONSE)
SetNotWaitingForResponse();
if (IsLoading()) {
@@ -4574,7 +4683,7 @@ bool WebContentsImpl::CreateRenderFrameForRenderManager(
return true;
}
-#if defined(OS_ANDROID) && !defined(USE_AURA)
+#if defined(OS_ANDROID)
base::android::ScopedJavaLocalRef<jobject>
WebContentsImpl::GetJavaWebContents() {
@@ -4614,14 +4723,14 @@ void WebContentsImpl::OnDidDownloadImage(
const ImageDownloadCallback& callback,
int id,
const GURL& image_url,
- image_downloader::DownloadResultPtr result) {
- const std::vector<SkBitmap> images =
- result->images.To<std::vector<SkBitmap>>();
- const std::vector<gfx::Size> original_image_sizes =
- result->original_image_sizes.To<std::vector<gfx::Size>>();
+ int32_t http_status_code,
+ mojo::Array<skia::mojom::BitmapPtr> images,
+ mojo::Array<mojo::SizePtr> original_image_sizes) {
+ const std::vector<SkBitmap> bitmaps = images.To<std::vector<SkBitmap>>();
+ const std::vector<gfx::Size> sizes =
+ original_image_sizes.To<std::vector<gfx::Size>>();
- callback.Run(id, result->http_status_code, image_url, images,
- original_image_sizes);
+ callback.Run(id, http_status_code, image_url, bitmaps, sizes);
}
void WebContentsImpl::OnDialogClosed(int render_process_id,
@@ -4635,11 +4744,12 @@ void WebContentsImpl::OnDialogClosed(int render_process_id,
last_dialog_suppressed_ = dialog_was_suppressed;
if (is_showing_before_unload_dialog_ && !success) {
- // If a beforeunload dialog is canceled, we need to stop the throbber from
- // spinning, since we forced it to start spinning in Navigate.
- if (rfh)
- DidStopLoading();
- controller_.DiscardNonCommittedEntries();
+ // It is possible for the current RenderFrameHost to have changed in the
+ // meantime. Do not reset the navigation state in that case.
+ if (rfh && rfh == rfh->frame_tree_node()->current_frame_host()) {
+ rfh->frame_tree_node()->BeforeUnloadCanceled();
+ controller_.DiscardNonCommittedEntries();
+ }
FOR_EACH_OBSERVER(WebContentsObserver, observers_,
BeforeUnloadDialogCancelled());
@@ -4763,6 +4873,29 @@ void WebContentsImpl::MediaStoppedPlaying(
FOR_EACH_OBSERVER(WebContentsObserver, observers_, MediaStoppedPlaying(id));
}
+void WebContentsImpl::UpdateWebContentsVisibility(bool visible) {
+ if (!did_first_set_visible_) {
+ // If this WebContents has not yet been set to be visible for the first
+ // time, ignore any requests to make it hidden, since resources would
+ // immediately be destroyed and only re-created after content loaded. In
+ // this state the window content is undefined and can show garbage.
+ // However, the page load mechanism requires an activation call through a
+ // visibility call to (re)load.
+ if (visible) {
+ did_first_set_visible_ = true;
+ WasShown();
+ }
+ return;
+ }
+ if (visible == should_normally_be_visible_)
+ return;
+
+ if (visible)
+ WasShown();
+ else
+ WasHidden();
+}
+
void WebContentsImpl::SetJavaScriptDialogManagerForTesting(
JavaScriptDialogManager* dialog_manager) {
dialog_manager_ = dialog_manager;
diff --git a/chromium/content/browser/web_contents/web_contents_impl.h b/chromium/content/browser/web_contents/web_contents_impl.h
index 5e0547168e3..bdf85b4c17e 100644
--- a/chromium/content/browser/web_contents/web_contents_impl.h
+++ b/chromium/content/browser/web_contents/web_contents_impl.h
@@ -7,6 +7,7 @@
#include <stdint.h>
+#include <functional>
#include <map>
#include <set>
#include <string>
@@ -58,6 +59,7 @@ class DownloadItem;
class GeolocationServiceContext;
class InterstitialPageImpl;
class JavaScriptDialogManager;
+class LoaderIOThreadNotifier;
class ManifestManagerHost;
class MediaWebContentsObserver;
class PluginContentOriginWhitelist;
@@ -83,7 +85,7 @@ struct LoadNotificationDetails;
struct ResourceRedirectDetails;
struct ResourceRequestDetails;
-#if defined(OS_ANDROID) && !defined(USE_AURA)
+#if defined(OS_ANDROID)
class WebContentsAndroid;
#endif
@@ -118,12 +120,6 @@ class CONTENT_EXPORT WebContentsImpl
static WebContents* FromRenderFrameHostID(int render_process_host_id,
int render_frame_host_id);
- // Creates a swapped out RenderView. This is used by the browser plugin to
- // create a swapped out RenderView in the embedder render process for the
- // guest, to expose the guest's window object to the embedder.
- // This returns the routing ID of the newly created swapped out RenderView.
- int CreateSwappedOutRenderView(SiteInstance* instance);
-
// Complex initialization here. Specifically needed to avoid having
// members call back into our virtual functions in the constructor.
virtual void Init(const WebContents::CreateParams& params);
@@ -131,7 +127,7 @@ class CONTENT_EXPORT WebContentsImpl
// Returns the SavePackage which manages the page saving job. May be NULL.
SavePackage* save_package() const { return save_package_.get(); }
-#if defined(OS_ANDROID) && !defined(USE_AURA)
+#if defined(OS_ANDROID)
// In Android WebView, the RenderView needs created even there is no
// navigation entry, this allows Android WebViews to use
// javascript: URLs that load into the DOMWindow before the first page
@@ -244,6 +240,7 @@ class CONTENT_EXPORT WebContentsImpl
int frame_tree_node_id) override;
void ForEachFrame(
const base::Callback<void(RenderFrameHost*)>& on_frame) override;
+ std::vector<RenderFrameHost*> GetAllFrames() override;
int SendToAllFrames(IPC::Message* message) override;
RenderViewHostImpl* GetRenderViewHost() const override;
int GetRoutingID() const override;
@@ -260,10 +257,6 @@ class CONTENT_EXPORT WebContentsImpl
void EnableTreeOnlyAccessibilityMode() override;
bool IsTreeOnlyAccessibilityModeForTesting() const override;
bool IsFullAccessibilityModeForTesting() const override;
-#if defined(OS_WIN)
- void SetParentNativeViewAccessible(
- gfx::NativeViewAccessible accessible_parent) override;
-#endif
const PageImportanceSignals& GetPageImportanceSignals() const override;
const base::string16& GetTitle() const override;
int32_t GetMaxPageID() override;
@@ -284,9 +277,13 @@ class CONTENT_EXPORT WebContentsImpl
int GetCapturerCount() const override;
bool IsAudioMuted() const override;
void SetAudioMuted(bool mute) override;
+ void IncrementBluetoothConnectedDeviceCount();
+ void DecrementBluetoothConnectedDeviceCount();
+ bool IsConnectedToBluetoothDevice() const override;
bool IsCrashed() const override;
void SetIsCrashed(base::TerminationStatus status, int error_code) override;
base::TerminationStatus GetCrashedStatus() const override;
+ int GetCrashedErrorCode() const override;
bool IsBeingDestroyed() const override;
void NotifyNavigationStateChanged(InvalidateTypes changed_flags) override;
base::TimeTicks GetLastActiveTime() const override;
@@ -300,7 +297,7 @@ class CONTENT_EXPORT WebContentsImpl
RenderFrameHost* outer_contents_frame) override;
void Stop() override;
WebContents* Clone() override;
- void ReloadFocusedFrame(bool ignore_cache) override;
+ void ReloadFocusedFrame(bool bypass_cache) override;
void Undo() override;
void Redo() override;
void Cut() override;
@@ -315,6 +312,7 @@ class CONTENT_EXPORT WebContentsImpl
void ReplaceMisspelling(const base::string16& word) override;
void NotifyContextMenuClosed(
const CustomContextMenuContext& context) override;
+ void ReloadLoFiImages() override;
void ExecuteCustomContextMenuCommand(
int action,
const CustomContextMenuContext& context) override;
@@ -377,17 +375,16 @@ class CONTENT_EXPORT WebContentsImpl
bool WasRecentlyAudible() override;
void GetManifest(const GetManifestCallback& callback) override;
void HasManifest(const HasManifestCallback& callback) override;
- void ExitFullscreen() override;
+ void ExitFullscreen(bool will_cause_resize) override;
void ResumeLoadingCreatedWebContents() override;
-#if defined(OS_ANDROID)
void OnMediaSessionStateChanged();
void ResumeMediaSession() override;
void SuspendMediaSession() override;
void StopMediaSession() override;
-#if !defined(USE_AURA)
+
+#if defined(OS_ANDROID)
base::android::ScopedJavaLocalRef<jobject> GetJavaWebContents() override;
virtual WebContentsAndroid* GetWebContentsAndroid();
-#endif // !USE_AURA
#elif defined(OS_MACOSX)
void SetAllowOtherViews(bool allow) override;
bool GetAllowOtherViews() override;
@@ -415,7 +412,6 @@ class CONTENT_EXPORT WebContentsImpl
JavaScriptMessageType type,
IPC::Message* reply_msg) override;
void RunBeforeUnloadConfirm(RenderFrameHost* render_frame_host,
- const base::string16& message,
bool is_reload,
IPC::Message* reply_msg) override;
void DidAccessInitialDocument() override;
@@ -441,15 +437,12 @@ class CONTENT_EXPORT WebContentsImpl
GeolocationServiceContext* GetGeolocationServiceContext() override;
WakeLockServiceContext* GetWakeLockServiceContext() override;
void EnterFullscreenMode(const GURL& origin) override;
- void ExitFullscreenMode() override;
+ void ExitFullscreenMode(bool will_cause_resize) override;
bool ShouldRouteMessageEvent(
RenderFrameHost* target_rfh,
SiteInstance* source_site_instance) const override;
void EnsureOpenerProxiesExist(RenderFrameHost* source_rfh) override;
scoped_ptr<WebUIImpl> CreateWebUIForRenderFrameHost(const GURL& url) override;
-#if defined(OS_WIN)
- gfx::NativeViewAccessible GetParentNativeViewAccessible() override;
-#endif
// RenderViewHostDelegate ----------------------------------------------------
RenderViewHostDelegateView* GetDelegateView() override;
@@ -480,7 +473,8 @@ class CONTENT_EXPORT WebContentsImpl
const base::string16& source_id) override;
RendererPreferences GetRendererPrefs(
BrowserContext* browser_context) const override;
- void OnUserInteraction(const blink::WebInputEvent::Type type) override;
+ void OnUserInteraction(RenderWidgetHostImpl* render_widget_host,
+ const blink::WebInputEvent::Type type) override;
void OnIgnoredUIEvent() override;
void LoadStateChanged(const GURL& url,
const net::LoadStateWithParam& load_state,
@@ -580,9 +574,7 @@ class CONTENT_EXPORT WebContentsImpl
bool* is_keyboard_shortcut) override;
void HandleKeyboardEvent(const NativeWebKeyboardEvent& event) override;
bool HandleWheelEvent(const blink::WebMouseWheelEvent& event) override;
- void OnUserGesture(RenderWidgetHostImpl* render_widget_host) override;
bool PreHandleGestureEvent(const blink::WebGestureEvent& event) override;
- void DidSendScreenRects(RenderWidgetHostImpl* rwh) override;
BrowserAccessibilityManager* GetRootBrowserAccessibilityManager() override;
BrowserAccessibilityManager* GetOrCreateRootBrowserAccessibilityManager()
override;
@@ -614,6 +606,8 @@ class CONTENT_EXPORT WebContentsImpl
void LostMouseLock(RenderWidgetHostImpl* render_widget_host) override;
void ForwardCompositorProto(RenderWidgetHostImpl* render_widget_host,
const std::vector<uint8_t>& proto) override;
+ void OnRenderFrameProxyVisibilityChanged(bool visible) override;
+ void SendScreenRects() override;
// RenderFrameHostManager::Delegate ------------------------------------------
@@ -704,12 +698,8 @@ class CONTENT_EXPORT WebContentsImpl
// Unsets the currently showing interstitial.
void DetachInterstitialPage() override;
- // Changes the IsLoading state and notifies the delegate as needed.
- // |details| is used to provide details on the load that just finished
- // (but can be null if not applicable).
- void SetIsLoading(bool is_loading,
- bool to_different_document,
- LoadNotificationDetails* details) override;
+ // Unpause the throbber if it was paused.
+ void DidProceedOnInterstitial() override;
typedef base::Callback<void(WebContents*)> CreatedCallback;
@@ -729,6 +719,9 @@ class CONTENT_EXPORT WebContentsImpl
return media_web_contents_observer_.get();
}
+ // Update the web contents visibility.
+ void UpdateWebContentsVisibility(bool visible);
+
private:
friend class WebContentsObserver;
friend class WebContents; // To implement factory methods.
@@ -753,6 +746,8 @@ class CONTENT_EXPORT WebContentsImpl
FRIEND_TEST_ALL_PREFIXES(SitePerProcessBrowserTest, CrossSiteIframe);
FRIEND_TEST_ALL_PREFIXES(SitePerProcessAccessibilityBrowserTest,
CrossSiteIframeAccessibility);
+ FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
+ JavaScriptDialogsInMainAndSubframes);
// So InterstitialPageImpl can access SetIsLoading.
friend class InterstitialPageImpl;
@@ -823,7 +818,9 @@ class CONTENT_EXPORT WebContentsImpl
void OnDidDownloadImage(const ImageDownloadCallback& callback,
int id,
const GURL& image_url,
- image_downloader::DownloadResultPtr result);
+ int32_t http_status_code,
+ mojo::Array<skia::mojom::BitmapPtr> images,
+ mojo::Array<mojo::SizePtr> original_image_sizes);
// Callback function when showing JavaScript dialogs. Takes in a routing ID
// pair to identify the RenderFrameHost that opened the dialog, because it's
@@ -879,7 +876,7 @@ class CONTENT_EXPORT WebContentsImpl
const gfx::Rect& selection_rect,
int active_match_ordinal,
bool final_update);
-#if defined(OS_ANDROID) && !defined(USE_AURA)
+#if defined(OS_ANDROID)
void OnFindMatchRectsReply(int version,
const std::vector<gfx::RectF>& rects,
const gfx::RectF& active_rect);
@@ -976,6 +973,9 @@ class CONTENT_EXPORT WebContentsImpl
// called once as this call also removes it from the internal map.
WebContentsImpl* GetCreatedWindow(int route_id);
+ // Sends a Page message IPC.
+ void SendPageMessage(IPC::Message* msg);
+
// Tracking loading progress -------------------------------------------------
// Resets the tracking state of the current load progress.
@@ -984,6 +984,15 @@ class CONTENT_EXPORT WebContentsImpl
// Notifies the delegate that the load progress was updated.
void SendChangeLoadProgress();
+ // Notifies the delegate of a change in loading state.
+ // |details| is used to provide details on the load that just finished
+ // (but can be null if not applicable).
+ // |due_to_interstitial| is true if the change in load state occurred because
+ // an interstitial page started showing/proceeded.
+ void LoadingStateChanged(bool to_different_document,
+ bool due_to_interstitial,
+ LoadNotificationDetails* details);
+
// Misc non-view stuff -------------------------------------------------------
// Sets the history for a specified RenderViewHost to |history_length|
@@ -1064,10 +1073,6 @@ class CONTENT_EXPORT WebContentsImpl
// is closed.
bool created_with_opener_;
-#if defined(OS_WIN)
- gfx::NativeViewAccessible accessible_parent_;
-#endif
-
// Helper classes ------------------------------------------------------------
// Manages the frame tree of the page and process swaps in each node.
@@ -1082,9 +1087,6 @@ class CONTENT_EXPORT WebContentsImpl
// Data for loading state ----------------------------------------------------
- // Indicates whether we're currently loading a resource.
- bool is_loading_;
-
// Indicates whether the current load is to a different document. Only valid
// if is_loading_ is true.
bool is_load_to_different_document_;
@@ -1161,6 +1163,12 @@ class CONTENT_EXPORT WebContentsImpl
// Tracks whether RWHV should be visible once capturer_count_ becomes zero.
bool should_normally_be_visible_;
+ // Tracks whether this WebContents was ever set to be visible. Used to
+ // facilitate WebContents being loaded in the background by setting
+ // |should_normally_be_visible_|. Ensures WasShown() will trigger when first
+ // becoming visible to the user, and prevents premature unloading.
+ bool did_first_set_visible_;
+
// See getter above.
bool is_being_destroyed_;
@@ -1203,7 +1211,7 @@ class CONTENT_EXPORT WebContentsImpl
// this overrides |preferred_size_|.
gfx::Size preferred_size_for_capture_;
-#if defined(OS_ANDROID) && !defined(USE_AURA)
+#if defined(OS_ANDROID)
// Date time chooser opened by this tab.
// Only used in Android since all other platforms use a multi field UI.
scoped_ptr<DateTimeChooserAndroid> date_time_chooser_;
@@ -1303,8 +1311,13 @@ class CONTENT_EXPORT WebContentsImpl
// Created on-demand to mute all audio output from this WebContents.
scoped_ptr<WebContentsAudioMuter> audio_muter_;
+ size_t bluetooth_connected_device_count_;
+
bool virtual_keyboard_requested_;
+ // Notifies ResourceDispatcherHostImpl of various events related to loading.
+ scoped_ptr<LoaderIOThreadNotifier> loader_io_thread_notifier_;
+
// Manages media players, CDMs, and power save blockers for media.
scoped_ptr<MediaWebContentsObserver> media_web_contents_observer_;
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 532cf018ff7..6534b140d49 100644
--- a/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -11,6 +11,8 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/web_contents/web_contents_view.h"
#include "content/common/frame_messages.h"
+#include "content/common/site_isolation_policy.h"
+#include "content/public/browser/javascript_dialog_manager.h"
#include "content/public/browser/load_notification_details.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/notification_details.h"
@@ -18,6 +20,7 @@
#include "content/public/browser/notification_types.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
+#include "content/public/browser/resource_dispatcher_host.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/url_constants.h"
@@ -27,6 +30,7 @@
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "content/shell/browser/shell.h"
+#include "content/test/content_browser_test_utils_internal.h"
#include "net/dns/mock_host_resolver.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -108,8 +112,13 @@ class NavigateOnCommitObserver : public WebContentsObserver {
const LoadCommittedDetails& load_details) override {
if (!done_) {
done_ = true;
- shell_->Stop();
shell_->LoadURL(url_);
+
+ // There should be a pending entry.
+ CHECK(shell_->web_contents()->GetController().GetPendingEntry());
+
+ // Now that there is a pending entry, stop the load.
+ shell_->Stop();
}
}
@@ -189,16 +198,8 @@ class LoadingStateChangedDelegate : public WebContentsDelegate {
int loadingStateToDifferentDocumentCount_;
};
-// See: http://crbug.com/298193
-#if defined(OS_WIN) || defined(OS_LINUX)
-#define MAYBE_DidStopLoadingDetails DISABLED_DidStopLoadingDetails
-#else
-#define MAYBE_DidStopLoadingDetails DidStopLoadingDetails
-#endif
-
// Test that DidStopLoading includes the correct URL in the details.
-IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
- MAYBE_DidStopLoadingDetails) {
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, DidStopLoadingDetails) {
ASSERT_TRUE(embedded_test_server()->Start());
LoadStopNotificationObserver load_observer(
@@ -212,20 +213,15 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
load_observer.controller_);
}
-// See: http://crbug.com/298193
-#if defined(OS_WIN) || defined(OS_LINUX)
-#define MAYBE_DidStopLoadingDetailsWithPending \
- DISABLED_DidStopLoadingDetailsWithPending
-#else
-#define MAYBE_DidStopLoadingDetailsWithPending DidStopLoadingDetailsWithPending
-#endif
-
// Test that DidStopLoading includes the correct URL in the details when a
// pending entry is present.
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
- MAYBE_DidStopLoadingDetailsWithPending) {
+ DidStopLoadingDetailsWithPending) {
ASSERT_TRUE(embedded_test_server()->Start());
- GURL url("data:text/html,<div>test</div>");
+ // TODO(clamy): Add a cross-process navigation case as well once
+ // crbug.com/581024 is fixed.
+ GURL url1 = embedded_test_server()->GetURL("/title1.html");
+ GURL url2 = embedded_test_server()->GetURL("/title2.html");
// Listen for the first load to stop.
LoadStopNotificationObserver load_observer(
@@ -233,12 +229,11 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
// Start a new pending navigation as soon as the first load commits.
// We will hear a DidStopLoading from the first load as the new load
// is started.
- NavigateOnCommitObserver commit_observer(
- shell(), embedded_test_server()->GetURL("/title2.html"));
- NavigateToURL(shell(), url);
+ NavigateOnCommitObserver commit_observer(shell(), url2);
+ NavigateToURL(shell(), url1);
load_observer.Wait();
- EXPECT_EQ(url, load_observer.url_);
+ EXPECT_EQ(url1, load_observer.url_);
EXPECT_EQ(0, load_observer.session_index_);
EXPECT_EQ(&shell()->web_contents()->GetController(),
load_observer.controller_);
@@ -606,19 +601,21 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
// Simulate a navigation that has not completed.
+ const GURL kURL2 = embedded_test_server()->GetURL("/title2.html");
+ NavigationStallDelegate stall_delegate(kURL2);
+ ResourceDispatcherHost::Get()->SetDelegate(&stall_delegate);
scoped_ptr<LoadProgressDelegateAndObserver> delegate(
new LoadProgressDelegateAndObserver(shell()));
- RenderFrameHost* main_frame = shell()->web_contents()->GetMainFrame();
- FrameHostMsg_DidStartLoading start_msg(main_frame->GetRoutingID(), true);
- static_cast<RenderFrameHostImpl*>(main_frame)->OnMessageReceived(start_msg);
+ shell()->LoadURL(kURL2);
EXPECT_TRUE(delegate->did_start_loading);
EXPECT_FALSE(delegate->did_stop_loading);
// Also simulate a DidChangeLoadProgress, but not a DidStopLoading.
+ RenderFrameHostImpl* main_frame = static_cast<RenderFrameHostImpl*>(
+ shell()->web_contents()->GetMainFrame());
FrameHostMsg_DidChangeLoadProgress progress_msg(main_frame->GetRoutingID(),
1.0);
- static_cast<RenderFrameHostImpl*>(main_frame)->OnMessageReceived(
- progress_msg);
+ main_frame->OnMessageReceived(progress_msg);
EXPECT_TRUE(delegate->did_start_loading);
EXPECT_FALSE(delegate->did_stop_loading);
@@ -631,6 +628,8 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
// We should have gotten to DidStopLoading.
EXPECT_TRUE(delegate->did_stop_loading);
+
+ ResourceDispatcherHost::Get()->SetDelegate(nullptr);
}
struct FirstVisuallyNonEmptyPaintObserver : public WebContentsObserver {
@@ -818,4 +817,197 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, NewNamedWindow) {
}
}
+// TODO(clamy): Make the test work on Windows and on Mac. On Mac and Windows,
+// there seem to be an issue with the ShellJavascriptDialogManager.
+#if defined(OS_WIN) || defined(OS_MACOSX)
+#define MAYBE_NoResetOnBeforeUnloadCanceledOnCommit \
+ DISABLED_NoResetOnBeforeUnloadCanceledOnCommit
+#else
+#define MAYBE_NoResetOnBeforeUnloadCanceledOnCommit \
+ NoResetOnBeforeUnloadCanceledOnCommit
+#endif
+// Test that if a BeforeUnload dialog is destroyed due to the commit of a
+// cross-site navigation, it will not reset the loading state.
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ MAYBE_NoResetOnBeforeUnloadCanceledOnCommit) {
+ ASSERT_TRUE(embedded_test_server()->Start());
+ const GURL kStartURL(
+ embedded_test_server()->GetURL("/hang_before_unload.html"));
+ const GURL kCrossSiteURL(
+ embedded_test_server()->GetURL("bar.com", "/title1.html"));
+
+ // Navigate to a first web page with a BeforeUnload event listener.
+ EXPECT_TRUE(NavigateToURL(shell(), kStartURL));
+
+ // Start a cross-site navigation that will not commit for the moment.
+ TestNavigationManager cross_site_delayer(shell()->web_contents(),
+ kCrossSiteURL);
+ shell()->LoadURL(kCrossSiteURL);
+ cross_site_delayer.WaitForWillStartRequest();
+
+ // Click on a link in the page. This will show the BeforeUnload dialog.
+ // Ensure the dialog is not dismissed, which will cause it to still be
+ // present when the cross-site navigation later commits.
+ // Note: the javascript function executed will not do the link click but
+ // schedule it for afterwards. Since the BeforeUnload event is synchronous,
+ // clicking on the link right away would cause the ExecuteScript to never
+ // return.
+ SetShouldProceedOnBeforeUnload(shell(), false);
+ EXPECT_TRUE(ExecuteScript(shell()->web_contents(), "clickLinkSoon()"));
+ WaitForAppModalDialog(shell());
+
+ // Have the cross-site navigation commit. The main RenderFrameHost should
+ // still be loading after that.
+ cross_site_delayer.ResumeNavigation();
+ cross_site_delayer.WaitForNavigationFinished();
+ EXPECT_TRUE(shell()->web_contents()->IsLoading());
+}
+
+namespace {
+
+class TestJavaScriptDialogManager : public JavaScriptDialogManager,
+ public WebContentsDelegate {
+ public:
+ TestJavaScriptDialogManager() : message_loop_runner_(new MessageLoopRunner) {}
+ ~TestJavaScriptDialogManager() override {}
+
+ void Wait() {
+ message_loop_runner_->Run();
+ message_loop_runner_ = new MessageLoopRunner;
+ }
+
+ std::string last_message() { return last_message_; }
+
+ // WebContentsDelegate
+
+ JavaScriptDialogManager* GetJavaScriptDialogManager(
+ WebContents* source) override {
+ return this;
+ }
+
+ // JavaScriptDialogManager
+
+ void RunJavaScriptDialog(WebContents* web_contents,
+ const GURL& origin_url,
+ JavaScriptMessageType javascript_message_type,
+ const base::string16& message_text,
+ const base::string16& default_prompt_text,
+ const DialogClosedCallback& callback,
+ bool* did_suppress_message) override {
+ last_message_ = base::UTF16ToUTF8(message_text);
+ *did_suppress_message = true;
+
+ message_loop_runner_->Quit();
+ };
+
+ void RunBeforeUnloadDialog(WebContents* web_contents,
+ bool is_reload,
+ const DialogClosedCallback& callback) override {}
+
+ bool HandleJavaScriptDialog(WebContents* web_contents,
+ bool accept,
+ const base::string16* prompt_override) override {
+ return true;
+ }
+
+ void CancelActiveAndPendingDialogs(WebContents* web_contents) override {}
+
+ void ResetDialogState(WebContents* web_contents) override {}
+
+ private:
+ std::string last_message_;
+
+ // The MessageLoopRunner used to spin the message loop.
+ scoped_refptr<MessageLoopRunner> message_loop_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestJavaScriptDialogManager);
+};
+
+} // namespace
+
+IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
+ JavaScriptDialogsInMainAndSubframes) {
+ WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
+ TestJavaScriptDialogManager dialog_manager;
+ wc->SetDelegate(&dialog_manager);
+
+ host_resolver()->AddRule("*", "127.0.0.1");
+ ASSERT_TRUE(embedded_test_server()->Start());
+
+ NavigateToURL(shell(),
+ embedded_test_server()->GetURL("a.com", "/title1.html"));
+ EXPECT_TRUE(WaitForLoadStop(wc));
+
+ FrameTreeNode* root = wc->GetFrameTree()->root();
+ ASSERT_EQ(0U, root->child_count());
+
+ std::string script =
+ "var iframe = document.createElement('iframe');"
+ "document.body.appendChild(iframe);";
+ EXPECT_TRUE(content::ExecuteScript(root->current_frame_host(), script));
+ EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
+
+ ASSERT_EQ(1U, root->child_count());
+ FrameTreeNode* frame = root->child_at(0);
+ ASSERT_NE(nullptr, frame);
+
+ url::Replacements<char> clear_port;
+ clear_port.ClearPort();
+
+ // A dialog from the main frame.
+ std::string alert_location = "alert(document.location)";
+ EXPECT_TRUE(
+ content::ExecuteScript(root->current_frame_host(), alert_location));
+ dialog_manager.Wait();
+ EXPECT_EQ(GURL("http://a.com/title1.html"),
+ GURL(dialog_manager.last_message()).ReplaceComponents(clear_port));
+
+ // A dialog from the subframe.
+ EXPECT_TRUE(
+ content::ExecuteScript(frame->current_frame_host(), alert_location));
+ dialog_manager.Wait();
+ EXPECT_EQ("about:blank", dialog_manager.last_message());
+
+ // Navigate the subframe cross-site.
+ NavigateFrameToURL(frame,
+ embedded_test_server()->GetURL("b.com", "/title2.html"));
+ EXPECT_TRUE(WaitForLoadStop(wc));
+
+ // A dialog from the subframe.
+ EXPECT_TRUE(
+ content::ExecuteScript(frame->current_frame_host(), alert_location));
+ dialog_manager.Wait();
+ EXPECT_EQ(GURL("http://b.com/title2.html"),
+ GURL(dialog_manager.last_message()).ReplaceComponents(clear_port));
+
+ // A dialog from the main frame.
+ EXPECT_TRUE(
+ content::ExecuteScript(root->current_frame_host(), alert_location));
+ dialog_manager.Wait();
+ EXPECT_EQ(GURL("http://a.com/title1.html"),
+ GURL(dialog_manager.last_message()).ReplaceComponents(clear_port));
+
+ // Navigate the top frame cross-site; ensure that dialogs work.
+ NavigateToURL(shell(),
+ embedded_test_server()->GetURL("c.com", "/title3.html"));
+ EXPECT_TRUE(WaitForLoadStop(wc));
+ EXPECT_TRUE(
+ content::ExecuteScript(root->current_frame_host(), alert_location));
+ dialog_manager.Wait();
+ EXPECT_EQ(GURL("http://c.com/title3.html"),
+ GURL(dialog_manager.last_message()).ReplaceComponents(clear_port));
+
+ // Navigate back; ensure that dialogs work.
+ wc->GetController().GoBack();
+ EXPECT_TRUE(WaitForLoadStop(wc));
+ EXPECT_TRUE(
+ content::ExecuteScript(root->current_frame_host(), alert_location));
+ dialog_manager.Wait();
+ EXPECT_EQ(GURL("http://a.com/title1.html"),
+ GURL(dialog_manager.last_message()).ReplaceComponents(clear_port));
+
+ wc->SetDelegate(nullptr);
+ wc->SetJavaScriptDialogManagerForTesting(nullptr);
+}
+
} // namespace content
diff --git a/chromium/content/browser/web_contents/web_contents_impl_unittest.cc b/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
index 4d1e2e6f026..ef96953682c 100644
--- a/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
+++ b/chromium/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -23,6 +23,7 @@
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/common/frame_messages.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
+#include "content/common/media/media_player_delegate_messages.h"
#include "content/common/site_isolation_policy.h"
#include "content/common/view_messages.h"
#include "content/public/browser/global_request_id.h"
@@ -40,6 +41,7 @@
#include "content/public/common/content_constants.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/mock_render_process_host.h"
+#include "content/public/test/test_browser_context.h"
#include "content/public/test/test_utils.h"
#include "content/test/test_content_browser_client.h"
#include "content/test/test_content_client.h"
@@ -50,6 +52,7 @@
#include "net/test/cert_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "url/url_constants.h"
namespace content {
namespace {
@@ -352,12 +355,14 @@ class FakeValidationMessageDelegate : public WebContentsDelegate {
TEST_F(WebContentsImplTest, UpdateTitle) {
NavigationControllerImpl& cont =
static_cast<NavigationControllerImpl&>(controller());
+ cont.LoadURL(GURL(url::kAboutBlankURL), Referrer(), ui::PAGE_TRANSITION_TYPED,
+ std::string());
+
FrameHostMsg_DidCommitProvisionalLoad_Params params;
InitNavigateParams(&params, 0, 0, true, GURL(url::kAboutBlankURL),
ui::PAGE_TRANSITION_TYPED);
- LoadCommittedDetails details;
- cont.RendererDidNavigate(contents()->GetMainFrame(), params, &details);
+ contents()->GetMainFrame()->SendNavigateWithParams(&params);
contents()->UpdateTitle(contents()->GetMainFrame(), 0,
base::ASCIIToUTF16(" Lots O' Whitespace\n"),
@@ -411,16 +416,15 @@ TEST_F(WebContentsImplTest, NTPViewSource) {
cont.LoadURL(
kGURL, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = cont.GetPendingEntry()->GetUniqueID();
- rvh()->GetDelegate()->RenderViewCreated(rvh());
// Did we get the expected message?
EXPECT_TRUE(process()->sink().GetFirstMessageMatching(
- ViewMsg_EnableViewSourceMode::ID));
+ FrameMsg_EnableViewSourceMode::ID));
FrameHostMsg_DidCommitProvisionalLoad_Params params;
InitNavigateParams(&params, 0, entry_id, true, kGURL,
ui::PAGE_TRANSITION_TYPED);
- LoadCommittedDetails details;
- cont.RendererDidNavigate(contents()->GetMainFrame(), params, &details);
+ contents()->GetMainFrame()->PrepareForCommit();
+ contents()->GetMainFrame()->SendNavigateWithParams(&params);
// Also check title and url.
EXPECT_EQ(base::ASCIIToUTF16(kUrl), contents()->GetTitle());
}
@@ -487,7 +491,7 @@ TEST_F(WebContentsImplTest, SimpleNavigation) {
TEST_F(WebContentsImplTest, NavigateToExcessivelyLongURL) {
// Construct a URL that's kMaxURLChars + 1 long of all 'a's.
const GURL url(std::string("http://example.org/").append(
- kMaxURLChars + 1, 'a'));
+ url::kMaxURLChars + 1, 'a'));
controller().LoadURL(
url, Referrer(), ui::PAGE_TRANSITION_GENERATED, std::string());
@@ -545,6 +549,7 @@ TEST_F(WebContentsImplTest, CrossSiteBoundaries) {
EXPECT_EQ(url, contents()->GetLastCommittedURL());
EXPECT_EQ(url2, contents()->GetVisibleURL());
TestRenderFrameHost* pending_rfh = contents()->GetPendingMainFrame();
+ EXPECT_TRUE(pending_rfh->GetLastCommittedURL().is_empty());
int pending_rvh_delete_count = 0;
pending_rfh->GetRenderViewHost()->set_delete_counter(
&pending_rvh_delete_count);
@@ -585,10 +590,6 @@ TEST_F(WebContentsImplTest, CrossSiteBoundaries) {
if (IsBrowserSideNavigationEnabled())
contents()->GetMainFrame()->PrepareForCommit();
TestRenderFrameHost* goback_rfh = contents()->GetPendingMainFrame();
- if (!SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- // Recycling the rfh is a behavior specific to swappedout://
- EXPECT_EQ(orig_rfh, goback_rfh);
- }
EXPECT_TRUE(contents()->CrossProcessNavigationPending());
// Navigations should be suspended in goback_rfh until BeforeUnloadACK.
@@ -971,20 +972,15 @@ TEST_F(WebContentsImplTest, FindOpenerRVHWhenPending) {
popup->GetRenderManager()->GetOpenerRoutingID(instance);
RenderFrameProxyHost* proxy =
contents()->GetRenderManager()->GetRenderFrameProxyHost(instance);
- if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- EXPECT_TRUE(proxy);
- EXPECT_EQ(proxy->GetRoutingID(), opener_frame_routing_id);
-
- // Ensure that committing the navigation removes the proxy.
- int entry_id = controller().GetPendingEntry()->GetUniqueID();
- contents()->TestDidNavigate(pending_rfh, 2, entry_id, true, url2,
- ui::PAGE_TRANSITION_TYPED);
- EXPECT_FALSE(
- contents()->GetRenderManager()->GetRenderFrameProxyHost(instance));
- } else {
- EXPECT_FALSE(proxy);
- EXPECT_EQ(pending_rfh->GetRoutingID(), opener_frame_routing_id);
- }
+ EXPECT_TRUE(proxy);
+ EXPECT_EQ(proxy->GetRoutingID(), opener_frame_routing_id);
+
+ // Ensure that committing the navigation removes the proxy.
+ entry_id = controller().GetPendingEntry()->GetUniqueID();
+ contents()->TestDidNavigate(pending_rfh, 2, entry_id, true, url2,
+ ui::PAGE_TRANSITION_TYPED);
+ EXPECT_FALSE(
+ contents()->GetRenderManager()->GetRenderFrameProxyHost(instance));
}
// Tests that WebContentsImpl uses the current URL, not the SiteInstance's site,
@@ -1399,6 +1395,7 @@ TEST_F(WebContentsImplTest, CrossSiteNotPreemptedDuringBeforeUnload) {
url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry1_id = controller().GetPendingEntry()->GetUniqueID();
TestRenderFrameHost* orig_rfh = contents()->GetMainFrame();
+ orig_rfh->PrepareForCommit();
EXPECT_FALSE(contents()->CrossProcessNavigationPending());
// Navigate to new site, with the beforeunload request in flight.
@@ -3044,7 +3041,6 @@ TEST_F(WebContentsImplTestWithSiteIsolation, StartStopEventsBalance) {
controller().LoadURL(
main_url, Referrer(), ui::PAGE_TRANSITION_TYPED, std::string());
int entry_id = controller().GetPendingEntry()->GetUniqueID();
- orig_rfh->PrepareForCommit();
orig_rfh->OnMessageReceived(
FrameHostMsg_DidStartLoading(orig_rfh->GetRoutingID(), false));
contents()->TestDidNavigate(orig_rfh, 1, entry_id, true, main_url,
@@ -3060,7 +3056,6 @@ TEST_F(WebContentsImplTestWithSiteIsolation, StartStopEventsBalance) {
// Navigate the child frame to about:blank, which will send both
// DidStartLoading and DidStopLoading messages.
{
- subframe->SendRendererInitiatedNavigationRequest(initial_url, false);
subframe->OnMessageReceived(
FrameHostMsg_DidStartLoading(subframe->GetRoutingID(), true));
subframe->SendNavigateWithTransition(1, 0, false, initial_url,
@@ -3200,9 +3195,7 @@ TEST_F(WebContentsImplTest, NoEarlyStop) {
}
TEST_F(WebContentsImplTest, MediaPowerSaveBlocking) {
- // PlayerIDs are actually pointers cast to int64_t, so verify that both
- // negative
- // and positive player ids don't blow up.
+ // Verify that both negative and positive player ids don't blow up.
const int kPlayerAudioVideoId = 15;
const int kPlayerAudioOnlyId = -15;
const int kPlayerVideoOnlyId = 30;
@@ -3236,8 +3229,8 @@ TEST_F(WebContentsImplTest, MediaPowerSaveBlocking) {
// Start a player with both audio and video. A video power save blocker
// should be created. If audio stream monitoring is available, an audio power
// save blocker should be created too.
- rfh->OnMessageReceived(FrameHostMsg_MediaPlayingNotification(
- 0, kPlayerAudioVideoId, true, true, false));
+ rfh->OnMessageReceived(MediaPlayerDelegateHostMsg_OnMediaPlaying(
+ 0, kPlayerAudioVideoId, true, true, false, base::TimeDelta()));
EXPECT_TRUE(has_video_power_save_blocker());
EXPECT_EQ(has_audio_power_save_blocker(),
!AudioStreamMonitor::monitoring_available());
@@ -3249,8 +3242,8 @@ TEST_F(WebContentsImplTest, MediaPowerSaveBlocking) {
// Start another player that only has video. There should be no change in
// the power save blockers. The notification should take into account the
// visibility state of the WebContents.
- rfh->OnMessageReceived(FrameHostMsg_MediaPlayingNotification(
- 0, kPlayerVideoOnlyId, true, false, false));
+ rfh->OnMessageReceived(MediaPlayerDelegateHostMsg_OnMediaPlaying(
+ 0, kPlayerVideoOnlyId, true, false, false, base::TimeDelta()));
EXPECT_FALSE(has_video_power_save_blocker());
EXPECT_EQ(has_audio_power_save_blocker(),
!AudioStreamMonitor::monitoring_available());
@@ -3261,16 +3254,16 @@ TEST_F(WebContentsImplTest, MediaPowerSaveBlocking) {
// Start another player that only has audio. There should be no change in
// the power save blockers.
- rfh->OnMessageReceived(FrameHostMsg_MediaPlayingNotification(
- 0, kPlayerAudioOnlyId, false, true, false));
+ rfh->OnMessageReceived(MediaPlayerDelegateHostMsg_OnMediaPlaying(
+ 0, kPlayerAudioOnlyId, false, true, false, base::TimeDelta()));
EXPECT_TRUE(has_video_power_save_blocker());
EXPECT_EQ(has_audio_power_save_blocker(),
!AudioStreamMonitor::monitoring_available());
// Start a remote player. There should be no change in the power save
// blockers.
- rfh->OnMessageReceived(FrameHostMsg_MediaPlayingNotification(
- 0, kPlayerRemoteId, true, true, true));
+ rfh->OnMessageReceived(MediaPlayerDelegateHostMsg_OnMediaPlaying(
+ 0, kPlayerRemoteId, true, true, true, base::TimeDelta()));
EXPECT_TRUE(has_video_power_save_blocker());
EXPECT_EQ(has_audio_power_save_blocker(),
!AudioStreamMonitor::monitoring_available());
@@ -3278,34 +3271,34 @@ TEST_F(WebContentsImplTest, MediaPowerSaveBlocking) {
// Destroy the original audio video player. Both power save blockers should
// remain.
rfh->OnMessageReceived(
- FrameHostMsg_MediaPausedNotification(0, kPlayerAudioVideoId));
+ MediaPlayerDelegateHostMsg_OnMediaPaused(0, kPlayerAudioVideoId, false));
EXPECT_TRUE(has_video_power_save_blocker());
EXPECT_EQ(has_audio_power_save_blocker(),
!AudioStreamMonitor::monitoring_available());
// Destroy the audio only player. The video power save blocker should remain.
rfh->OnMessageReceived(
- FrameHostMsg_MediaPausedNotification(0, kPlayerAudioOnlyId));
+ MediaPlayerDelegateHostMsg_OnMediaPaused(0, kPlayerAudioOnlyId, false));
EXPECT_TRUE(has_video_power_save_blocker());
EXPECT_FALSE(has_audio_power_save_blocker());
// Destroy the video only player. No power save blockers should remain.
rfh->OnMessageReceived(
- FrameHostMsg_MediaPausedNotification(0, kPlayerVideoOnlyId));
+ MediaPlayerDelegateHostMsg_OnMediaPaused(0, kPlayerVideoOnlyId, false));
EXPECT_FALSE(has_video_power_save_blocker());
EXPECT_FALSE(has_audio_power_save_blocker());
// Destroy the remote player. No power save blockers should remain.
rfh->OnMessageReceived(
- FrameHostMsg_MediaPausedNotification(0, kPlayerRemoteId));
+ MediaPlayerDelegateHostMsg_OnMediaPaused(0, kPlayerRemoteId, false));
EXPECT_FALSE(has_video_power_save_blocker());
EXPECT_FALSE(has_audio_power_save_blocker());
// Start a player with both audio and video. A video power save blocker
// should be created. If audio stream monitoring is available, an audio power
// save blocker should be created too.
- rfh->OnMessageReceived(FrameHostMsg_MediaPlayingNotification(
- 0, kPlayerAudioVideoId, true, true, false));
+ rfh->OnMessageReceived(MediaPlayerDelegateHostMsg_OnMediaPlaying(
+ 0, kPlayerAudioVideoId, true, true, false, base::TimeDelta()));
EXPECT_TRUE(has_video_power_save_blocker());
EXPECT_EQ(has_audio_power_save_blocker(),
!AudioStreamMonitor::monitoring_available());
@@ -3321,6 +3314,7 @@ TEST_F(WebContentsImplTest, MediaPowerSaveBlocking) {
TEST_F(WebContentsImplTest, ThemeColorChangeDependingOnFirstVisiblePaint) {
TestWebContentsObserver observer(contents());
TestRenderFrameHost* rfh = contents()->GetMainFrame();
+ rfh->InitializeRenderFrameIfNeeded();
SkColor transparent = SK_ColorTRANSPARENT;
@@ -3371,6 +3365,9 @@ TEST_F(WebContentsImplTest, LoadResourceFromMemoryCacheWithBadSecurityInfo) {
// does not mistakenly think it has seen a good certificate and thus forget any
// user exceptions for that host. See https://crbug.com/516808.
TEST_F(WebContentsImplTest, LoadResourceFromMemoryCacheWithEmptySecurityInfo) {
+ WebContentsImplTestBrowserClient browser_client;
+ SetBrowserClientForTesting(&browser_client);
+
scoped_refptr<net::X509Certificate> cert =
net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
SSLPolicyBackend* backend = contents()->controller_.ssl_manager()->backend();
@@ -3383,8 +3380,12 @@ TEST_F(WebContentsImplTest, LoadResourceFromMemoryCacheWithEmptySecurityInfo) {
RESOURCE_TYPE_MAIN_FRAME);
EXPECT_TRUE(backend->HasAllowException(test_url.host()));
+
+ DeleteContents();
}
+namespace {
+
class TestJavaScriptDialogManager : public JavaScriptDialogManager {
public:
TestJavaScriptDialogManager() {}
@@ -3396,7 +3397,6 @@ class TestJavaScriptDialogManager : public JavaScriptDialogManager {
void RunJavaScriptDialog(WebContents* web_contents,
const GURL& origin_url,
- const std::string& accept_lang,
JavaScriptMessageType javascript_message_type,
const base::string16& message_text,
const base::string16& default_prompt_text,
@@ -3406,7 +3406,6 @@ class TestJavaScriptDialogManager : public JavaScriptDialogManager {
};
void RunBeforeUnloadDialog(WebContents* web_contents,
- const base::string16& message_text,
bool is_reload,
const DialogClosedCallback& callback) override {}
@@ -3426,26 +3425,23 @@ class TestJavaScriptDialogManager : public JavaScriptDialogManager {
DISALLOW_COPY_AND_ASSIGN(TestJavaScriptDialogManager);
};
+} // namespace
+
TEST_F(WebContentsImplTest, ResetJavaScriptDialogOnUserNavigate) {
- scoped_ptr<TestJavaScriptDialogManager> delegate(
- new TestJavaScriptDialogManager());
- contents()->SetJavaScriptDialogManagerForTesting(delegate.get());
+ TestJavaScriptDialogManager dialog_manager;
+ contents()->SetJavaScriptDialogManagerForTesting(&dialog_manager);
// A user-initiated navigation.
-
- contents()->GetMainFrame()->PrepareForCommit();
contents()->TestDidNavigate(contents()->GetMainFrame(), 1, 0, true,
GURL("about:whatever"),
ui::PAGE_TRANSITION_TYPED);
- EXPECT_EQ(1u, delegate->reset_count());
+ EXPECT_EQ(1u, dialog_manager.reset_count());
// An automatic navigation.
-
- contents()->GetMainFrame()->PrepareForCommit();
contents()->GetMainFrame()->SendNavigateWithModificationCallback(
2, 0, true, GURL(url::kAboutBlankURL), base::Bind(SetAsNonUserGesture));
- EXPECT_EQ(1u, delegate->reset_count());
+ EXPECT_EQ(1u, dialog_manager.reset_count());
contents()->SetJavaScriptDialogManagerForTesting(nullptr);
}
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 a899bf33104..7053c50b576 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_aura.cc
@@ -91,8 +91,10 @@ bool IsScrollEndEffectEnabled() {
RenderWidgetHostViewAura* ToRenderWidgetHostViewAura(
RenderWidgetHostView* view) {
- if (!view || RenderViewHostFactory::has_factory())
+ if (!view || (RenderViewHostFactory::has_factory() &&
+ !RenderViewHostFactory::is_real_render_view_host())) {
return NULL; // Can't cast to RenderWidgetHostViewAura in unit tests.
+ }
RenderViewHost* rvh = RenderViewHost::From(view->GetRenderWidgetHost());
WebContentsImpl* web_contents = static_cast<WebContentsImpl*>(
@@ -236,7 +238,7 @@ const ui::Clipboard::FormatType& GetFileSystemFileFormatType() {
void WriteFileSystemFilesToPickle(
const std::vector<DropData::FileSystemFileInfo>& file_system_files,
base::Pickle* pickle) {
- pickle->WriteSizeT(file_system_files.size());
+ pickle->WriteUInt32(file_system_files.size());
for (size_t i = 0; i < file_system_files.size(); ++i) {
pickle->WriteString(file_system_files[i].url.spec());
pickle->WriteInt64(file_system_files[i].size);
@@ -249,12 +251,12 @@ bool ReadFileSystemFilesFromPickle(
std::vector<DropData::FileSystemFileInfo>* file_system_files) {
base::PickleIterator iter(pickle);
- size_t num_files = 0;
- if (!iter.ReadSizeT(&num_files))
+ uint32_t num_files = 0;
+ if (!iter.ReadUInt32(&num_files))
return false;
file_system_files->resize(num_files);
- for (size_t i = 0; i < num_files; ++i) {
+ for (uint32_t i = 0; i < num_files; ++i) {
std::string url_string;
int64_t size = 0;
if (!iter.ReadString(&url_string) || !iter.ReadInt64(&size))
@@ -404,11 +406,6 @@ class WebContentsViewAura::WindowObserver
: view_(view),
host_window_(NULL) {
view_->window_->AddObserver(this);
-
-#if defined(OS_WIN)
- if (view_->window_->GetRootWindow())
- view_->window_->GetRootWindow()->AddObserver(this);
-#endif
}
~WindowObserver() override {
@@ -417,64 +414,8 @@ class WebContentsViewAura::WindowObserver
view_->window_->GetHost()->RemoveObserver(this);
if (host_window_)
host_window_->RemoveObserver(this);
-#if defined(OS_WIN)
- if (host_window_) {
- const aura::Window::Windows& children = host_window_->children();
- for (size_t i = 0; i < children.size(); ++i)
- children[i]->RemoveObserver(this);
- }
-
- aura::Window* root_window = view_->window_->GetRootWindow();
- if (root_window) {
- root_window->RemoveObserver(this);
- const aura::Window::Windows& root_children = root_window->children();
- for (size_t i = 0; i < root_children.size(); ++i)
- root_children[i]->RemoveObserver(this);
- }
-#endif
}
-#if defined(OS_WIN)
- // Constrained windows are added as children of the parent's parent's view
- // which may overlap with windowed NPAPI plugins. In that case, tell the RWHV
- // so that it can update the plugins' cutout rects accordingly.
- // Note: this is hard coding how Chrome layer adds its dialogs. Since NPAPI is
- // going to be deprecated in a year, this is ok for now. The test for this is
- // PrintPreviewTest.WindowedNPAPIPluginHidden.
- void OnWindowAdded(aura::Window* new_window) override {
- if (!new_window->Contains(view_->window_.get())) {
- // Skip the case when the parent moves to the root window.
- if (new_window != host_window_) {
- // Observe sibling windows of the WebContents, or children of the root
- // window.
- if (new_window->parent() == host_window_ ||
- new_window->parent() == view_->window_->GetRootWindow()) {
- new_window->AddObserver(this);
- }
- }
- }
-
- if (new_window->parent() == host_window_) {
- UpdateConstrainedWindows(NULL);
- }
- }
-
- void OnWillRemoveWindow(aura::Window* window) override {
- if (window == view_->window_.get())
- return;
-
- window->RemoveObserver(this);
- UpdateConstrainedWindows(window);
- }
-
- void OnWindowVisibilityChanged(aura::Window* window, bool visible) override {
- if (window == view_->window_.get() || window->parent() == host_window_ ||
- window->parent() == view_->window_->GetRootWindow()) {
- UpdateConstrainedWindows(NULL);
- }
- }
-#endif
-
void OnWindowParentChanged(aura::Window* window,
aura::Window* parent) override {
if (window != view_->window_.get())
@@ -488,46 +429,9 @@ class WebContentsViewAura::WindowObserver
if (host_window_)
host_window_->RemoveObserver(this);
-#if defined(OS_WIN)
- if (host_window_) {
- const aura::Window::Windows& children = host_window_->children();
- for (size_t i = 0; i < children.size(); ++i)
- children[i]->RemoveObserver(this);
- RenderWidgetHostViewAura* rwhv = ToRenderWidgetHostViewAura(
- view_->web_contents_->GetRenderWidgetHostView());
- if (rwhv)
- rwhv->UpdateConstrainedWindowRects(std::vector<gfx::Rect>());
- }
-
- // When we get parented to the root window, the code below will watch the
- // host window, aka root window. Since we already watch the root window on
- // Windows, unregister first so that the debug check doesn't fire.
- if (host_window && host_window == window->GetRootWindow())
- host_window->RemoveObserver(this);
-
- // We need to undo the above if we were parented to the root window and then
- // got parented to another window. At that point, the code before the ifdef
- // would have stopped watching the root window.
- if (window->GetRootWindow() &&
- host_window != window->GetRootWindow() &&
- !window->GetRootWindow()->HasObserver(this)) {
- window->GetRootWindow()->AddObserver(this);
- }
-#endif
-
host_window_ = host_window;
- if (host_window) {
+ if (host_window)
host_window->AddObserver(this);
-#if defined(OS_WIN)
- if (host_window != window->GetRootWindow()) {
- const aura::Window::Windows& children = host_window->children();
- for (size_t i = 0; i < children.size(); ++i) {
- if (!children[i]->Contains(view_->window_.get()))
- children[i]->AddObserver(this);
- }
- }
-#endif
- }
}
void OnWindowBoundsChanged(aura::Window* window,
@@ -541,10 +445,6 @@ class WebContentsViewAura::WindowObserver
if (selection_controller_client)
selection_controller_client->OnWindowMoved();
}
-#if defined(OS_WIN)
- } else {
- UpdateConstrainedWindows(NULL);
-#endif
}
}
@@ -556,32 +456,14 @@ class WebContentsViewAura::WindowObserver
}
void OnWindowAddedToRootWindow(aura::Window* window) override {
- if (window == view_->window_.get()) {
+ if (window == view_->window_.get())
window->GetHost()->AddObserver(this);
-#if defined(OS_WIN)
- if (!window->GetRootWindow()->HasObserver(this))
- window->GetRootWindow()->AddObserver(this);
-#endif
- }
}
void OnWindowRemovingFromRootWindow(aura::Window* window,
aura::Window* new_root) override {
- if (window == view_->window_.get()) {
+ if (window == view_->window_.get())
window->GetHost()->RemoveObserver(this);
-#if defined(OS_WIN)
- window->GetRootWindow()->RemoveObserver(this);
-
- const aura::Window::Windows& root_children =
- window->GetRootWindow()->children();
- for (size_t i = 0; i < root_children.size(); ++i) {
- if (root_children[i] != view_->window_.get() &&
- root_children[i] != host_window_) {
- root_children[i]->RemoveObserver(this);
- }
- }
-#endif
- }
}
// Overridden WindowTreeHostObserver:
@@ -596,46 +478,7 @@ class WebContentsViewAura::WindowObserver
}
private:
- void SendScreenRects() {
- RenderWidgetHostImpl::From(
- view_->web_contents_->GetRenderViewHost()->GetWidget())
- ->SendScreenRects();
- }
-
-#if defined(OS_WIN)
- void UpdateConstrainedWindows(aura::Window* exclude) {
- RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
- view_->web_contents_->GetRenderWidgetHostView());
- if (!view)
- return;
-
- std::vector<gfx::Rect> constrained_windows;
- if (host_window_) {
- const aura::Window::Windows& children = host_window_->children();
- for (size_t i = 0; i < children.size(); ++i) {
- if (!children[i]->Contains(view_->window_.get()) &&
- children[i] != exclude &&
- children[i]->IsVisible()) {
- constrained_windows.push_back(children[i]->GetBoundsInRootWindow());
- }
- }
- }
-
- aura::Window* root_window = view_->window_->GetRootWindow();
- const aura::Window::Windows& root_children = root_window->children();
- if (root_window) {
- for (size_t i = 0; i < root_children.size(); ++i) {
- if (root_children[i]->IsVisible() &&
- !root_children[i]->Contains(view_->window_.get())) {
- constrained_windows.push_back(
- root_children[i]->GetBoundsInRootWindow());
- }
- }
- }
-
- view->UpdateConstrainedWindowRects(constrained_windows);
- }
-#endif
+ void SendScreenRects() { view_->web_contents_->SendScreenRects(); }
WebContentsViewAura* view_;
@@ -658,8 +501,11 @@ WebContentsViewAura::WebContentsViewAura(WebContentsImpl* web_contents,
current_rvh_for_drag_(NULL),
current_overscroll_gesture_(OVERSCROLL_NONE),
completed_overscroll_gesture_(OVERSCROLL_NONE),
- navigation_overlay_(nullptr),
- is_or_was_visible_(false) {
+ navigation_overlay_(nullptr) {}
+
+void WebContentsViewAura::SetDelegateForTesting(
+ WebContentsViewDelegate* delegate) {
+ delegate_.reset(delegate);
}
////////////////////////////////////////////////////////////////////////////////
@@ -688,8 +534,7 @@ void WebContentsViewAura::SizeChangedCommon(const gfx::Size& size) {
void WebContentsViewAura::EndDrag(blink::WebDragOperationsMask ops) {
aura::Window* root_window = GetNativeView()->GetRootWindow();
- gfx::Point screen_loc =
- gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
+ gfx::Point screen_loc = gfx::Screen::GetScreen()->GetCursorScreenPoint();
gfx::Point client_loc = screen_loc;
RenderViewHost* rvh = web_contents_->GetRenderViewHost();
aura::Window* window = rvh->GetWidget()->GetView()->GetNativeView();
@@ -839,7 +684,6 @@ void WebContentsViewAura::CreateView(
window_.reset(new aura::Window(this));
window_->set_owned_by_parent(false);
window_->SetType(ui::wm::WINDOW_TYPE_CONTROL);
- window_->SetTransparent(false);
window_->Init(ui::LAYER_NOT_DRAWN);
window_->AddObserver(this);
aura::Window* root_window = context ? context->GetRootWindow() : NULL;
@@ -951,11 +795,12 @@ void WebContentsViewAura::ShowContextMenu(RenderFrameHost* render_frame_host,
selection_controller_client->HandleContextMenu(params)) {
return;
}
+
if (delegate_) {
RenderWidgetHostViewAura* view = ToRenderWidgetHostViewAura(
web_contents_->GetRenderWidgetHostView());
- if (view)
- view->OnShowContextMenu();
+ if (view && !view->OnShowContextMenu(params))
+ return;
delegate_->ShowContextMenu(render_frame_host, params);
// WARNING: we may have been deleted during the call to ShowContextMenu().
@@ -1197,8 +1042,7 @@ void WebContentsViewAura::OnMouseEvent(ui::MouseEvent* event) {
web_contents_->GetDelegate()->ActivateContents(web_contents_);
web_contents_->GetDelegate()->ContentsMouseEvent(
- web_contents_,
- gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
+ web_contents_, gfx::Screen::GetScreen()->GetCursorScreenPoint(),
type == ui::ET_MOUSE_MOVED, type == ui::ET_MOUSE_EXITED);
}
@@ -1223,8 +1067,7 @@ void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent& event) {
if (drag_dest_delegate_)
drag_dest_delegate_->DragInitialize(web_contents_);
- gfx::Point screen_pt =
- gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
+ gfx::Point screen_pt = gfx::Screen::GetScreen()->GetCursorScreenPoint();
web_contents_->GetRenderViewHost()->DragTargetDragEnter(
*current_drop_data_.get(), event.location(), screen_pt, op,
ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
@@ -1244,8 +1087,7 @@ int WebContentsViewAura::OnDragUpdated(const ui::DropTargetEvent& event) {
return ui::DragDropTypes::DRAG_NONE;
blink::WebDragOperationsMask op = ConvertToWeb(event.source_operations());
- gfx::Point screen_pt =
- gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint();
+ gfx::Point screen_pt = gfx::Screen::GetScreen()->GetCursorScreenPoint();
web_contents_->GetRenderViewHost()->DragTargetDragOver(
event.location(), screen_pt, op,
ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
@@ -1280,8 +1122,7 @@ int WebContentsViewAura::OnPerformDrop(const ui::DropTargetEvent& event) {
return ui::DragDropTypes::DRAG_NONE;
web_contents_->GetRenderViewHost()->DragTargetDrop(
- event.location(),
- gfx::Screen::GetScreenFor(GetNativeView())->GetCursorScreenPoint(),
+ event.location(), gfx::Screen::GetScreen()->GetCursorScreenPoint(),
ConvertAuraEventFlagsToWebInputEventModifiers(event.flags()));
if (drag_dest_delegate_)
drag_dest_delegate_->OnDrop();
@@ -1295,30 +1136,7 @@ void WebContentsViewAura::OnWindowVisibilityChanged(aura::Window* window,
if (window != window_.get() && window_->Contains(window))
return;
- UpdateWebContentsVisibility(visible);
-}
-
-void WebContentsViewAura::UpdateWebContentsVisibility(bool visible) {
- if (!is_or_was_visible_) {
- // We should not hide the web contents before it was shown the first time,
- // since resources would immediately be destroyed and only re-created after
- // content got loaded. In this state the window content is undefined and can
- // show garbage.
- // However - the page load mechanism requires an activation call through a
- // visibility call to (re)load.
- if (visible) {
- is_or_was_visible_ = true;
- web_contents_->WasShown();
- }
- return;
- }
- if (visible) {
- if (!web_contents_->should_normally_be_visible())
- web_contents_->WasShown();
- } else {
- if (web_contents_->should_normally_be_visible())
- web_contents_->WasHidden();
- }
+ web_contents_->UpdateWebContentsVisibility(visible);
}
} // namespace content
diff --git a/chromium/content/browser/web_contents/web_contents_view_aura.h b/chromium/content/browser/web_contents/web_contents_view_aura.h
index 70c29b0583b..2c4b41d6cc4 100644
--- a/chromium/content/browser/web_contents/web_contents_view_aura.h
+++ b/chromium/content/browser/web_contents/web_contents_view_aura.h
@@ -39,8 +39,8 @@ class WebContentsViewDelegate;
class WebContentsImpl;
class WebDragDestDelegate;
-class WebContentsViewAura
- : public WebContentsView,
+class CONTENT_EXPORT WebContentsViewAura
+ : NON_EXPORTED_BASE(public WebContentsView),
public RenderViewHostDelegateView,
public OverscrollControllerDelegate,
public aura::WindowDelegate,
@@ -50,6 +50,9 @@ class WebContentsViewAura
WebContentsViewAura(WebContentsImpl* web_contents,
WebContentsViewDelegate* delegate);
+ // Allow the WebContentsViewDelegate to be set explicitly.
+ void SetDelegateForTesting(WebContentsViewDelegate* delegate);
+
private:
class WindowObserver;
@@ -157,9 +160,6 @@ class WebContentsViewAura
// Overridden from aura::WindowObserver:
void OnWindowVisibilityChanged(aura::Window* window, bool visible) override;
- // Update the web contents visiblity.
- void UpdateWebContentsVisibility(bool visible);
-
FRIEND_TEST_ALL_PREFIXES(WebContentsViewAuraTest, EnableDisableOverscroll);
scoped_ptr<aura::Window> window_;
@@ -196,10 +196,6 @@ class WebContentsViewAura
scoped_ptr<GestureNavSimple> gesture_nav_simple_;
- // On Windows we can run into problems if resources get released within the
- // initialization phase while the content (and its dimensions) are not known.
- bool is_or_was_visible_;
-
DISALLOW_COPY_AND_ASSIGN(WebContentsViewAura);
};
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 8d08134b629..b8960350aa2 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
@@ -272,7 +272,7 @@ class WebContentsViewAuraTest : public ContentBrowserTest {
controller->SetScreenshotManager(make_scoped_ptr(screenshot_manager_));
frame_watcher_ = new FrameWatcher();
- GetRenderWidgetHost()->GetProcess()->AddFilter(frame_watcher_.get());
+ frame_watcher_->AttachTo(shell()->web_contents());
}
void SetUpCommandLine(base::CommandLine* cmd) override {
diff --git a/chromium/content/browser/web_contents/web_contents_view_mac.h b/chromium/content/browser/web_contents/web_contents_view_mac.h
index 62a8b34219f..bcd6a26c9bc 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mac.h
+++ b/chromium/content/browser/web_contents/web_contents_view_mac.h
@@ -50,6 +50,11 @@ CONTENT_EXPORT
- (void)setMouseDownCanMoveWindow:(BOOL)canMove;
- (void)setOpaque:(BOOL)opaque;
+
+// Returns the available drag operations. This is a required method for
+// NSDraggingSource. It is supposedly deprecated, but the non-deprecated API
+// -[NSWindow dragImage:...] still relies on it.
+- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal;
@end
namespace content {
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 9556dde593a..b87c8b96365 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mac.mm
+++ b/chromium/content/browser/web_contents/web_contents_view_mac.mm
@@ -8,6 +8,7 @@
#include <string>
+#include "base/command_line.h"
#import "base/mac/mac_util.h"
#import "base/mac/scoped_sending_event.h"
#include "base/mac/sdk_forward_declarations.h"
@@ -23,6 +24,7 @@
#include "content/common/view_messages.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_view_delegate.h"
+#include "content/public/common/content_switches.h"
#include "skia/ext/skia_utils_mac.h"
#import "third_party/mozilla/NSPasteboard+Utils.h"
#include "ui/base/clipboard/custom_data_helper.h"
@@ -43,16 +45,17 @@ using content::WebContentsViewMac;
// Ensure that the blink::WebDragOperation enum values stay in sync with
// NSDragOperation constants, since the code below static_casts between 'em.
-#define STATIC_ASSERT_MATCHING_ENUM(name) \
- static_assert(int(NS##name) == int(blink::Web##name), "enum mismatch: " #name)
-STATIC_ASSERT_MATCHING_ENUM(DragOperationNone);
-STATIC_ASSERT_MATCHING_ENUM(DragOperationCopy);
-STATIC_ASSERT_MATCHING_ENUM(DragOperationLink);
-STATIC_ASSERT_MATCHING_ENUM(DragOperationGeneric);
-STATIC_ASSERT_MATCHING_ENUM(DragOperationPrivate);
-STATIC_ASSERT_MATCHING_ENUM(DragOperationMove);
-STATIC_ASSERT_MATCHING_ENUM(DragOperationDelete);
-STATIC_ASSERT_MATCHING_ENUM(DragOperationEvery);
+#define STATIC_ASSERT_ENUM(a, b) \
+ static_assert(static_cast<int>(a) == static_cast<int>(b), \
+ "enum mismatch: " #a)
+STATIC_ASSERT_ENUM(NSDragOperationNone, blink::WebDragOperationNone);
+STATIC_ASSERT_ENUM(NSDragOperationCopy, blink::WebDragOperationCopy);
+STATIC_ASSERT_ENUM(NSDragOperationLink, blink::WebDragOperationLink);
+STATIC_ASSERT_ENUM(NSDragOperationGeneric, blink::WebDragOperationGeneric);
+STATIC_ASSERT_ENUM(NSDragOperationPrivate, blink::WebDragOperationPrivate);
+STATIC_ASSERT_ENUM(NSDragOperationMove, blink::WebDragOperationMove);
+STATIC_ASSERT_ENUM(NSDragOperationDelete, blink::WebDragOperationDelete);
+STATIC_ASSERT_ENUM(NSDragOperationEvery, blink::WebDragOperationEvery);
@interface WebContentsViewCocoa (Private)
- (id)initWithWebContentsViewMac:(WebContentsViewMac*)w;
@@ -66,6 +69,7 @@ STATIC_ASSERT_MATCHING_ENUM(DragOperationEvery);
- (void)cancelDeferredClose;
- (void)clearWebContentsView;
- (void)closeTabAfterEvent;
+- (void)updateWebContentsVisibility;
- (void)viewDidBecomeFirstResponder:(NSNotification*)notification;
- (content::WebContentsImpl*)webContents;
@end
@@ -114,13 +118,15 @@ gfx::NativeWindow WebContentsViewMac::GetTopLevelNativeWindow() const {
}
void WebContentsViewMac::GetContainerBounds(gfx::Rect* out) const {
- // Convert bounds to window coordinate space.
- NSRect bounds =
- [cocoa_view_.get() convertRect:[cocoa_view_.get() bounds] toView:nil];
-
- // Convert bounds to screen coordinate space.
NSWindow* window = [cocoa_view_.get() window];
- bounds.origin = [window convertBaseToScreen:bounds.origin];
+ NSRect bounds = [cocoa_view_.get() bounds];
+ if (window) {
+ // Convert bounds to window coordinate space.
+ bounds = [cocoa_view_.get() convertRect:bounds toView:nil];
+
+ // Convert bounds to screen coordinate space.
+ bounds = [window convertRectToScreen:bounds];
+ }
// Flip y to account for screen flip.
NSScreen* screen = [[NSScreen screens] firstObject];
@@ -519,8 +525,6 @@ void WebContentsViewMac::CloseTab() {
// NSDraggingSource methods
-// Returns what kind of drag operations are available. This is a required
-// method for NSDraggingSource.
- (NSDragOperation)draggingSourceOperationMaskForLocal:(BOOL)isLocal {
if (dragSource_)
return [dragSource_ draggingSourceOperationMaskForLocal:isLocal];
@@ -610,6 +614,15 @@ void WebContentsViewMac::CloseTab() {
FocusThroughTabTraversal(direction == NSSelectingPrevious);
}
+- (void)updateWebContentsVisibility {
+ WebContentsImpl* webContents = [self webContents];
+ if (!webContents || webContents->IsBeingDestroyed())
+ return;
+
+ const bool viewVisible = [self window] && ![self isHiddenOrHasHiddenAncestor];
+ webContents->UpdateWebContentsVisibility(viewVisible);
+}
+
// When the subviews require a layout, their size should be reset to the size
// of this view. (It is possible for the size to get out of sync as an
// optimization in preparation for an upcoming WebContentsView resize.
@@ -625,10 +638,12 @@ void WebContentsViewMac::CloseTab() {
NSNotificationCenter* notificationCenter =
[NSNotificationCenter defaultCenter];
- // Occlusion notification APIs are new in Mavericks.
- bool supportsOcclusionAPIs = base::mac::IsOSMavericksOrLater();
+ // Occlusion is highly undesirable for browser tests, since it will
+ // flakily change test behavior.
+ static bool isDisabled = base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableBackgroundingOccludedWindowsForTesting);
- if (supportsOcclusionAPIs) {
+ if (!isDisabled) {
if (oldWindow) {
[notificationCenter
removeObserver:self
@@ -658,4 +673,16 @@ void WebContentsViewMac::CloseTab() {
}
}
+- (void)viewDidMoveToWindow {
+ [self updateWebContentsVisibility];
+}
+
+- (void)viewDidHide {
+ [self updateWebContentsVisibility];
+}
+
+- (void)viewDidUnhide {
+ [self updateWebContentsVisibility];
+}
+
@end
diff --git a/chromium/content/browser/web_contents/web_contents_view_mus.cc b/chromium/content/browser/web_contents/web_contents_view_mus.cc
index b987ab198b8..d4860b3a81b 100644
--- a/chromium/content/browser/web_contents/web_contents_view_mus.cc
+++ b/chromium/content/browser/web_contents/web_contents_view_mus.cc
@@ -104,7 +104,6 @@ void WebContentsViewMus::CreateView(const gfx::Size& initial_size,
aura_window_.reset(new aura::Window(this));
aura_window_->set_owned_by_parent(false);
aura_window_->SetType(ui::wm::WINDOW_TYPE_CONTROL);
- aura_window_->SetTransparent(false);
aura_window_->Init(ui::LAYER_NOT_DRAWN);
aura::Window* root_window = context ? context->GetRootWindow() : nullptr;
if (root_window) {
diff --git a/chromium/content/browser/web_contents/web_drag_dest_mac.mm b/chromium/content/browser/web_contents/web_drag_dest_mac.mm
index ec674126d52..452bfc89cf2 100644
--- a/chromium/content/browser/web_contents/web_drag_dest_mac.mm
+++ b/chromium/content/browser/web_contents/web_drag_dest_mac.mm
@@ -15,6 +15,7 @@
#include "third_party/WebKit/public/web/WebInputEvent.h"
#import "third_party/mozilla/NSPasteboard+Utils.h"
#include "ui/base/clipboard/custom_data_helper.h"
+#include "ui/base/cocoa/cocoa_base_utils.h"
#import "ui/base/dragdrop/cocoa_dnd_util.h"
#include "ui/base/window_open_disposition.h"
@@ -98,7 +99,8 @@ int GetModifierFlags() {
- (NSPoint)flipWindowPointToScreen:(const NSPoint&)windowPoint
view:(NSView*)view {
DCHECK(view);
- NSPoint screenPoint = [[view window] convertBaseToScreen:windowPoint];
+ NSPoint screenPoint =
+ ui::ConvertPointFromWindowToScreen([view window], windowPoint);
NSScreen* screen = [[view window] screen];
NSRect screenFrame = [screen frame];
screenPoint.y = screenFrame.size.height - screenPoint.y;
diff --git a/chromium/content/browser/web_contents/web_drag_dest_mac_unittest.mm b/chromium/content/browser/web_contents/web_drag_dest_mac_unittest.mm
index efa6452e267..b6a6946ab7d 100644
--- a/chromium/content/browser/web_contents/web_drag_dest_mac_unittest.mm
+++ b/chromium/content/browser/web_contents/web_drag_dest_mac_unittest.mm
@@ -5,6 +5,7 @@
#include "base/mac/mac_util.h"
#include "base/mac/scoped_nsautorelease_pool.h"
#import "base/mac/scoped_nsobject.h"
+#include "base/memory/ref_counted.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#import "content/browser/web_contents/web_drag_dest_mac.h"
@@ -13,6 +14,7 @@
#include "content/test/test_web_contents.h"
#include "testing/gtest/include/gtest/gtest.h"
#import "third_party/mozilla/NSPasteboard+Utils.h"
+#import "ui/base/clipboard/clipboard_util_mac.h"
#import "ui/base/dragdrop/cocoa_dnd_util.h"
#import "ui/gfx/test/ui_cocoa_test_helper.h"
@@ -82,88 +84,80 @@ TEST_F(WebDragDestTest, Flip) {
}
TEST_F(WebDragDestTest, URL) {
- NSPasteboard* pboard = nil;
NSString* url = nil;
NSString* title = nil;
GURL result_url;
base::string16 result_title;
// Put a URL on the pasteboard and check it.
- pboard = [NSPasteboard pasteboardWithUniqueName];
+ scoped_refptr<ui::UniquePasteboard> pboard = new ui::UniquePasteboard;
url = @"http://www.google.com/";
- PutURLOnPasteboard(url, pboard);
- EXPECT_TRUE(ui::PopulateURLAndTitleFromPasteboard(
- &result_url, &result_title, pboard, NO));
+ PutURLOnPasteboard(url, pboard->get());
+ EXPECT_TRUE(ui::PopulateURLAndTitleFromPasteboard(&result_url, &result_title,
+ pboard->get(), NO));
EXPECT_EQ(base::SysNSStringToUTF8(url), result_url.spec());
- [pboard releaseGlobally];
// Put a 'url ' and 'urln' on the pasteboard and check it.
- pboard = [NSPasteboard pasteboardWithUniqueName];
+ pboard = new ui::UniquePasteboard;
url = @"http://www.google.com/";
title = @"Title of Awesomeness!",
- PutCoreURLAndTitleOnPasteboard(url, title, pboard);
- EXPECT_TRUE(ui::PopulateURLAndTitleFromPasteboard(
- &result_url, &result_title, pboard, NO));
+ PutCoreURLAndTitleOnPasteboard(url, title, pboard->get());
+ EXPECT_TRUE(ui::PopulateURLAndTitleFromPasteboard(&result_url, &result_title,
+ pboard->get(), NO));
EXPECT_EQ(base::SysNSStringToUTF8(url), result_url.spec());
EXPECT_EQ(base::SysNSStringToUTF16(title), result_title);
- [pboard releaseGlobally];
// Also check that it passes file:// via 'url '/'urln' properly.
- pboard = [NSPasteboard pasteboardWithUniqueName];
+ pboard = new ui::UniquePasteboard;
url = @"file:///tmp/dont_delete_me.txt";
title = @"very important";
- PutCoreURLAndTitleOnPasteboard(url, title, pboard);
- EXPECT_TRUE(ui::PopulateURLAndTitleFromPasteboard(
- &result_url, &result_title, pboard, NO));
+ PutCoreURLAndTitleOnPasteboard(url, title, pboard->get());
+ EXPECT_TRUE(ui::PopulateURLAndTitleFromPasteboard(&result_url, &result_title,
+ pboard->get(), NO));
EXPECT_EQ(base::SysNSStringToUTF8(url), result_url.spec());
EXPECT_EQ(base::SysNSStringToUTF16(title), result_title);
- [pboard releaseGlobally];
// And javascript:.
- pboard = [NSPasteboard pasteboardWithUniqueName];
+ pboard = new ui::UniquePasteboard;
url = @"javascript:open('http://www.youtube.com/')";
title = @"kill some time";
- PutCoreURLAndTitleOnPasteboard(url, title, pboard);
- EXPECT_TRUE(ui::PopulateURLAndTitleFromPasteboard(
- &result_url, &result_title, pboard, NO));
+ PutCoreURLAndTitleOnPasteboard(url, title, pboard->get());
+ EXPECT_TRUE(ui::PopulateURLAndTitleFromPasteboard(&result_url, &result_title,
+ pboard->get(), NO));
EXPECT_EQ(base::SysNSStringToUTF8(url), result_url.spec());
EXPECT_EQ(base::SysNSStringToUTF16(title), result_title);
- [pboard releaseGlobally];
- pboard = [NSPasteboard pasteboardWithUniqueName];
+ pboard = new ui::UniquePasteboard;
url = @"/bin/sh";
- [pboard declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType]
- owner:nil];
- [pboard setPropertyList:[NSArray arrayWithObject:url]
- forType:NSFilenamesPboardType];
- EXPECT_FALSE(ui::PopulateURLAndTitleFromPasteboard(
- &result_url, &result_title, pboard, NO));
- EXPECT_TRUE(ui::PopulateURLAndTitleFromPasteboard(
- &result_url, &result_title, pboard, YES));
+ [pboard->get() declareTypes:[NSArray arrayWithObject:NSFilenamesPboardType]
+ owner:nil];
+ [pboard->get() setPropertyList:[NSArray arrayWithObject:url]
+ forType:NSFilenamesPboardType];
+ EXPECT_FALSE(ui::PopulateURLAndTitleFromPasteboard(&result_url, &result_title,
+ pboard->get(), NO));
+ EXPECT_TRUE(ui::PopulateURLAndTitleFromPasteboard(&result_url, &result_title,
+ pboard->get(), YES));
base::scoped_nsobject<NSURL> expected_output(
[[NSURL alloc] initFileURLWithPath:url isDirectory:NO]);
EXPECT_EQ([[expected_output absoluteString] UTF8String], result_url.spec());
EXPECT_EQ("sh", base::UTF16ToUTF8(result_title));
- [pboard releaseGlobally];
}
TEST_F(WebDragDestTest, Data) {
DropData data;
- NSPasteboard* pboard = [NSPasteboard pasteboardWithUniqueName];
+ scoped_refptr<ui::UniquePasteboard> pboard = new ui::UniquePasteboard;
- PutURLOnPasteboard(@"http://www.google.com", pboard);
- [pboard addTypes:[NSArray arrayWithObjects:NSHTMLPboardType,
- NSStringPboardType, nil]
- owner:nil];
+ PutURLOnPasteboard(@"http://www.google.com", pboard->get());
+ [pboard->get() addTypes:[NSArray arrayWithObjects:NSHTMLPboardType,
+ NSStringPboardType, nil]
+ owner:nil];
NSString* htmlString = @"<html><body><b>hi there</b></body></html>";
NSString* textString = @"hi there";
- [pboard setString:htmlString forType:NSHTMLPboardType];
- [pboard setString:textString forType:NSStringPboardType];
- [drag_dest_ populateDropData:&data fromPasteboard:pboard];
+ [pboard->get() setString:htmlString forType:NSHTMLPboardType];
+ [pboard->get() setString:textString forType:NSStringPboardType];
+ [drag_dest_ populateDropData:&data fromPasteboard:pboard->get()];
EXPECT_EQ(data.url.spec(), "http://www.google.com/");
EXPECT_EQ(base::SysNSStringToUTF16(textString), data.text.string());
EXPECT_EQ(base::SysNSStringToUTF16(htmlString), data.html.string());
-
- [pboard releaseGlobally];
}
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 a94f9d32daa..14321f47879 100644
--- a/chromium/content/browser/web_contents/web_drag_source_mac.mm
+++ b/chromium/content/browser/web_contents/web_drag_source_mac.mm
@@ -30,6 +30,7 @@
#include "net/base/filename_util.h"
#include "net/base/mime_util.h"
#include "ui/base/clipboard/custom_data_helper.h"
+#include "ui/base/cocoa/cocoa_base_utils.h"
#include "ui/base/dragdrop/cocoa_dnd_util.h"
#include "ui/gfx/image/image.h"
#include "ui/resources/grit/ui_resources.h"
@@ -173,8 +174,8 @@ void PromiseWriterHelper(const DropData& drop_data,
// Strip out any existing escapes and then re-escape uniformly.
if (!url && dropData_->url.SchemeIs(url::kJavaScriptScheme)) {
net::UnescapeRule::Type unescapeRules =
- net::UnescapeRule::SPACES |
- net::UnescapeRule::URL_SPECIAL_CHARS |
+ net::UnescapeRule::SPACES | net::UnescapeRule::PATH_SEPARATORS |
+ net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS |
net::UnescapeRule::SPOOFING_AND_CONTROL_CHARS;
std::string unescapedUrlString =
net::UnescapeURLComponent(dropData_->url.spec(), unescapeRules);
@@ -222,7 +223,8 @@ void PromiseWriterHelper(const DropData& drop_data,
- (NSPoint)convertScreenPoint:(NSPoint)screenPoint {
DCHECK([contentsView_ window]);
- NSPoint basePoint = [[contentsView_ window] convertScreenToBase:screenPoint];
+ NSPoint basePoint =
+ ui::ConvertPointFromScreenToWindow([contentsView_ window], screenPoint);
return [contentsView_ convertPoint:basePoint fromView:nil];
}
diff --git a/chromium/content/browser/web_contents/web_drag_source_mac_unittest.mm b/chromium/content/browser/web_contents/web_drag_source_mac_unittest.mm
index 036c9268f8e..edc18884810 100644
--- a/chromium/content/browser/web_contents/web_drag_source_mac_unittest.mm
+++ b/chromium/content/browser/web_contents/web_drag_source_mac_unittest.mm
@@ -4,10 +4,12 @@
#import "content/browser/web_contents/web_drag_source_mac.h"
+#include "base/memory/ref_counted.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/common/drop_data.h"
#include "content/public/test/test_renderer_host.h"
#include "testing/gtest/include/gtest/gtest.h"
+#import "ui/base/clipboard/clipboard_util_mac.h"
#include "url/gurl.h"
namespace content {
@@ -23,19 +25,19 @@ TEST_F(WebDragSourceMacTest, DragInvalidlyEscapedBookmarklet) {
dropData->url = GURL("javascript:%");
WebContentsImpl* contentsImpl = static_cast<WebContentsImpl*>(contents.get());
+ scoped_refptr<ui::UniquePasteboard> pasteboard1 = new ui::UniquePasteboard;
base::scoped_nsobject<WebDragSource> source([[WebDragSource alloc]
- initWithContents:contentsImpl
- view:view
- dropData:dropData.get()
- image:nil
- offset:NSZeroPoint
- pasteboard:[NSPasteboard pasteboardWithUniqueName]
- dragOperationMask:NSDragOperationCopy]);
+ initWithContents:contentsImpl
+ view:view
+ dropData:dropData.get()
+ image:nil
+ offset:NSZeroPoint
+ pasteboard:pasteboard1->get()
+ dragOperationMask:NSDragOperationCopy]);
// Test that this call doesn't throw any exceptions: http://crbug.com/128371
- base::scoped_nsobject<NSPasteboard> pasteboard(
- [NSPasteboard pasteboardWithUniqueName]);
- [source lazyWriteToPasteboard:pasteboard forType:NSURLPboardType];
+ scoped_refptr<ui::UniquePasteboard> pasteboard2 = new ui::UniquePasteboard;
+ [source lazyWriteToPasteboard:pasteboard2->get() forType:NSURLPboardType];
}
} // namespace content
diff --git a/chromium/content/browser/webui/OWNERS b/chromium/content/browser/webui/OWNERS
index 658a9f5cd0c..262db997c92 100644
--- a/chromium/content/browser/webui/OWNERS
+++ b/chromium/content/browser/webui/OWNERS
@@ -1 +1,2 @@
+dbeam@chromium.org
estade@chromium.org
diff --git a/chromium/content/browser/webui/content_web_ui_controller_factory.cc b/chromium/content/browser/webui/content_web_ui_controller_factory.cc
index 196da55c9f9..9d87359ded1 100644
--- a/chromium/content/browser/webui/content_web_ui_controller_factory.cc
+++ b/chromium/content/browser/webui/content_web_ui_controller_factory.cc
@@ -19,7 +19,7 @@
#include "content/public/common/url_constants.h"
#if defined(ENABLE_WEBRTC)
-#include "content/browser/media/webrtc_internals_ui.h"
+#include "content/browser/media/webrtc/webrtc_internals_ui.h"
#endif
namespace content {
diff --git a/chromium/content/browser/webui/url_data_manager_backend.cc b/chromium/content/browser/webui/url_data_manager_backend.cc
index b604a461224..7dfd7575996 100644
--- a/chromium/content/browser/webui/url_data_manager_backend.cc
+++ b/chromium/content/browser/webui/url_data_manager_backend.cc
@@ -674,15 +674,14 @@ bool URLDataManagerBackend::StartRequest(const net::URLRequest* request,
// message loop before request for data. And correspondingly their
// replies are put on the IO thread in the same order.
target_message_loop->task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&GetMimeTypeOnUI, scoped_refptr<URLDataSourceImpl>(source),
- path, job->AsWeakPtr()));
+ FROM_HERE, base::Bind(&GetMimeTypeOnUI, base::RetainedRef(source), path,
+ job->AsWeakPtr()));
// The DataSource wants StartDataRequest to be called on a specific thread,
// usually the UI thread, for this path.
target_message_loop->task_runner()->PostTask(
FROM_HERE, base::Bind(&URLDataManagerBackend::CallStartRequest,
- make_scoped_refptr(source), path,
+ base::RetainedRef(source), path,
render_process_id, render_frame_id, request_id));
}
return true;
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 9a026008daf..eeac51d9e3d 100644
--- a/chromium/content/browser/webui/web_ui_data_source_impl.cc
+++ b/chromium/content/browser/webui/web_ui_data_source_impl.cc
@@ -12,10 +12,11 @@
#include "base/macros.h"
#include "base/memory/ref_counted_memory.h"
#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
#include "content/grit/content_resources.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
-#include "mojo/public/js/constants.h"
+#include "ui/base/template_expressions.h"
#include "ui/base/webui/jstemplate_builder.h"
#include "ui/base/webui/web_ui_util.h"
@@ -36,8 +37,7 @@ void WebUIDataSource::Add(BrowserContext* browser_context,
// URLDataSource.
class WebUIDataSourceImpl::InternalDataSource : public URLDataSource {
public:
- InternalDataSource(WebUIDataSourceImpl* parent) : parent_(parent) {
- }
+ explicit InternalDataSource(WebUIDataSourceImpl* parent) : parent_(parent) {}
~InternalDataSource() override {}
@@ -80,9 +80,7 @@ class WebUIDataSourceImpl::InternalDataSource : public URLDataSource {
};
WebUIDataSourceImpl::WebUIDataSourceImpl(const std::string& source_name)
- : URLDataSourceImpl(
- source_name,
- new InternalDataSource(this)),
+ : URLDataSourceImpl(source_name, new InternalDataSource(this)),
source_name_(source_name),
default_resource_(-1),
add_csp_(true),
@@ -90,26 +88,30 @@ WebUIDataSourceImpl::WebUIDataSourceImpl(const std::string& source_name)
frame_src_set_(false),
deny_xframe_options_(true),
disable_set_font_strings_(false),
- replace_existing_source_(true) {
-}
+ replace_existing_source_(true) {}
WebUIDataSourceImpl::~WebUIDataSourceImpl() {
}
void WebUIDataSourceImpl::AddString(const std::string& name,
const base::string16& value) {
+ // TODO(dschuyler): Share only one copy of these strings.
localized_strings_.SetString(name, value);
+ replacements_[name] = base::UTF16ToUTF8(value);
}
void WebUIDataSourceImpl::AddString(const std::string& name,
const std::string& value) {
localized_strings_.SetString(name, value);
+ replacements_[name] = value;
}
void WebUIDataSourceImpl::AddLocalizedString(const std::string& name,
int ids) {
localized_strings_.SetString(
name, GetContentClient()->GetLocalizedString(ids));
+ replacements_[name] =
+ base::UTF16ToUTF8(GetContentClient()->GetLocalizedString(ids));
}
void WebUIDataSourceImpl::AddLocalizedStrings(
@@ -119,6 +121,11 @@ void WebUIDataSourceImpl::AddLocalizedStrings(
void WebUIDataSourceImpl::AddBoolean(const std::string& name, bool value) {
localized_strings_.SetBoolean(name, value);
+ // TODO(dschuyler): Change name of |localized_strings_| to |load_time_data_|
+ // or similar. These values haven't been found as strings for
+ // localization. The boolean values are not added to |replacements_|
+ // for the same reason, that they are used as flags, rather than string
+ // replacements.
}
void WebUIDataSourceImpl::SetJsonPath(const std::string& path) {
@@ -139,24 +146,6 @@ void WebUIDataSourceImpl::SetRequestFilter(
filter_callback_ = callback;
}
-void WebUIDataSourceImpl::AddMojoResources() {
- static const struct {
- const char* path;
- int id;
- } resources[] = {
- {mojo::kBindingsModuleName, IDR_MOJO_BINDINGS_JS},
- {mojo::kBufferModuleName, IDR_MOJO_BUFFER_JS},
- {mojo::kCodecModuleName, IDR_MOJO_CODEC_JS},
- {mojo::kConnectionModuleName, IDR_MOJO_CONNECTION_JS},
- {mojo::kConnectorModuleName, IDR_MOJO_CONNECTOR_JS},
- {mojo::kRouterModuleName, IDR_MOJO_ROUTER_JS},
- {mojo::kUnicodeModuleName, IDR_MOJO_UNICODE_JS},
- {mojo::kValidatorModuleName, IDR_MOJO_VALIDATOR_JS},
- };
- for (size_t i = 0; i < arraysize(resources); ++i)
- AddResourcePath(resources[i].path, resources[i].id);
-}
-
void WebUIDataSourceImpl::DisableReplaceExistingSource() {
replace_existing_source_ = false;
}
@@ -230,7 +219,19 @@ void WebUIDataSourceImpl::StartDataRequest(
if (result != path_to_idr_map_.end())
resource_id = result->second;
DCHECK_NE(resource_id, -1);
- SendFromResourceBundle(callback, resource_id);
+ scoped_refptr<base::RefCountedMemory> response(
+ GetContentClient()->GetDataResourceBytes(resource_id));
+
+ // TODO(dschuyler): improve filtering of which resource to run template
+ // expansion upon.
+ if (GetMimeType(path) == "text/html") {
+ std::string replaced = ui::ReplaceTemplateExpressions(
+ base::StringPiece(response->front_as<char>(), response->size()),
+ replacements_);
+ response = base::RefCountedString::TakeString(&replaced);
+ }
+
+ callback.Run(response.get());
}
void WebUIDataSourceImpl::SendLocalizedStringsAsJSON(
@@ -245,11 +246,4 @@ void WebUIDataSourceImpl::SendLocalizedStringsAsJSON(
callback.Run(base::RefCountedString::TakeString(&template_data));
}
-void WebUIDataSourceImpl::SendFromResourceBundle(
- const URLDataSource::GotDataCallback& callback, int idr) {
- scoped_refptr<base::RefCountedStaticMemory> response(
- GetContentClient()->GetDataResourceBytes(idr));
- callback.Run(response.get());
-}
-
} // namespace content
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 7d899a9e194..53cbc736cc9 100644
--- a/chromium/content/browser/webui/web_ui_data_source_impl.h
+++ b/chromium/content/browser/webui/web_ui_data_source_impl.h
@@ -17,6 +17,7 @@
#include "content/common/content_export.h"
#include "content/public/browser/url_data_source.h"
#include "content/public/browser/web_ui_data_source.h"
+#include "ui/base/template_expressions.h"
namespace content {
@@ -38,7 +39,6 @@ class CONTENT_EXPORT WebUIDataSourceImpl
void SetDefaultResource(int resource_id) override;
void SetRequestFilter(
const WebUIDataSource::HandleRequestCallback& callback) override;
- void AddMojoResources() override;
void DisableReplaceExistingSource() override;
void DisableContentSecurityPolicy() override;
void OverrideContentSecurityPolicyObjectSrc(const std::string& data) override;
@@ -52,10 +52,6 @@ class CONTENT_EXPORT WebUIDataSourceImpl
void SendLocalizedStringsAsJSON(
const URLDataSource::GotDataCallback& callback);
- // Completes a request by sending the file specified by |idr|.
- void SendFromResourceBundle(
- const URLDataSource::GotDataCallback& callback, int idr);
-
private:
class InternalDataSource;
friend class InternalDataSource;
@@ -85,6 +81,10 @@ class CONTENT_EXPORT WebUIDataSourceImpl
int default_resource_;
std::string json_path_;
std::map<std::string, int> path_to_idr_map_;
+ // The |replacements_| is intended to replace |localized_strings_|.
+ // TODO(dschuyler): phase out |localized_strings_| in Q1 2016. (Or rename
+ // to |load_time_flags_| if the usage is reduced to storing flags only).
+ ui::TemplateReplacements replacements_;
base::DictionaryValue localized_strings_;
WebUIDataSource::HandleRequestCallback filter_callback_;
bool add_csp_;
@@ -99,6 +99,6 @@ class CONTENT_EXPORT WebUIDataSourceImpl
DISALLOW_COPY_AND_ASSIGN(WebUIDataSourceImpl);
};
-} // content
+} // namespace content
#endif // CONTENT_BROWSER_WEBUI_WEB_UI_DATA_SOURCE_IMPL_H_
diff --git a/chromium/content/browser/webui/web_ui_impl.h b/chromium/content/browser/webui/web_ui_impl.h
index 26c051def9e..1c812a5660c 100644
--- a/chromium/content/browser/webui/web_ui_impl.h
+++ b/chromium/content/browser/webui/web_ui_impl.h
@@ -10,6 +10,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/memory/weak_ptr.h"
#include "content/public/browser/web_ui.h"
diff --git a/chromium/content/browser/webui/web_ui_mojo_browsertest.cc b/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
index 805f1bb5775..920f891693a 100644
--- a/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
+++ b/chromium/content/browser/webui/web_ui_mojo_browsertest.cc
@@ -31,7 +31,6 @@
#include "content/test/data/web_ui_test_mojo_bindings.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/bindings/interface_request.h"
-#include "mojo/public/js/constants.h"
#include "mojo/test/test_utils.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
@@ -44,21 +43,10 @@ bool got_message = false;
// up the generated file from disk and returns it.
bool GetResource(const std::string& id,
const WebUIDataSource::GotDataCallback& callback) {
- // These are handled by the WebUIDataSource that AddMojoDataSource() creates.
- if (id == mojo::kBindingsModuleName ||
- id == mojo::kBufferModuleName ||
- id == mojo::kCodecModuleName ||
- id == mojo::kConnectionModuleName ||
- id == mojo::kConnectorModuleName ||
- id == mojo::kUnicodeModuleName ||
- id == mojo::kRouterModuleName ||
- id == mojo::kValidatorModuleName)
- return false;
-
if (id.find(".mojom") != std::string::npos) {
std::string contents;
CHECK(base::ReadFileToString(mojo::test::GetFilePathForJSResource(id),
- &contents, std::string::npos))
+ &contents))
<< id;
base::RefCountedString* ref_contents = new base::RefCountedString;
ref_contents->data() = contents;
@@ -70,23 +58,22 @@ bool GetResource(const std::string& id,
CHECK(base::PathService::Get(content::DIR_TEST_DATA, &path));
path = path.AppendASCII(id.substr(0, id.find("?")));
std::string contents;
- CHECK(base::ReadFileToString(path, &contents, std::string::npos))
- << path.value();
+ CHECK(base::ReadFileToString(path, &contents)) << path.value();
base::RefCountedString* ref_contents = new base::RefCountedString;
ref_contents->data() = contents;
callback.Run(ref_contents);
return true;
}
-class BrowserTargetImpl : public BrowserTarget {
+class BrowserTargetImpl : public mojom::BrowserTarget {
public:
BrowserTargetImpl(base::RunLoop* run_loop,
- mojo::InterfaceRequest<BrowserTarget> request)
+ mojo::InterfaceRequest<mojom::BrowserTarget> request)
: run_loop_(run_loop), binding_(this, std::move(request)) {}
~BrowserTargetImpl() override {}
- // BrowserTarget overrides:
+ // mojom::BrowserTarget overrides:
void Start(const mojo::Closure& closure) override {
closure.Run();
}
@@ -99,7 +86,7 @@ class BrowserTargetImpl : public BrowserTarget {
base::RunLoop* run_loop_;
private:
- mojo::Binding<BrowserTarget> binding_;
+ mojo::Binding<mojom::BrowserTarget> binding_;
DISALLOW_COPY_AND_ASSIGN(BrowserTargetImpl);
};
@@ -110,7 +97,6 @@ class TestWebUIController : public WebUIController {
: WebUIController(web_ui), run_loop_(run_loop) {
content::WebUIDataSource* data_source =
WebUIDataSource::Create("mojo-web-ui");
- data_source->AddMojoResources();
data_source->SetRequestFilter(base::Bind(&GetResource));
content::WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(),
data_source);
@@ -135,12 +121,12 @@ class PingTestWebUIController : public TestWebUIController {
// WebUIController overrides:
void RenderViewCreated(RenderViewHost* render_view_host) override {
- render_view_host->GetMainFrame()->GetServiceRegistry()->
- AddService<BrowserTarget>(base::Bind(
- &PingTestWebUIController::CreateHandler, base::Unretained(this)));
+ render_view_host->GetMainFrame()->GetServiceRegistry()->AddService(
+ base::Bind(&PingTestWebUIController::CreateHandler,
+ base::Unretained(this)));
}
- void CreateHandler(mojo::InterfaceRequest<BrowserTarget> request) {
+ void CreateHandler(mojo::InterfaceRequest<mojom::BrowserTarget> request) {
browser_target_.reset(new BrowserTargetImpl(run_loop_, std::move(request)));
}
diff --git a/chromium/content/browser/zygote_host/zygote_communication_linux.cc b/chromium/content/browser/zygote_host/zygote_communication_linux.cc
new file mode 100644
index 00000000000..54f5176adbd
--- /dev/null
+++ b/chromium/content/browser/zygote_host/zygote_communication_linux.cc
@@ -0,0 +1,437 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/browser/zygote_host/zygote_communication_linux.h"
+
+#include <string.h>
+#include <sys/socket.h>
+
+#include "base/base_switches.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/metrics/histogram.h"
+#include "base/metrics/sparse_histogram.h"
+#include "base/path_service.h"
+#include "base/pickle.h"
+#include "base/posix/eintr_wrapper.h"
+#include "base/posix/unix_domain_socket_linux.h"
+#include "content/browser/renderer_host/render_sandbox_host_linux.h"
+#include "content/browser/zygote_host/zygote_host_impl_linux.h"
+#include "content/common/child_process_sandbox_support_impl_linux.h"
+#include "content/common/zygote_commands_linux.h"
+#include "content/public/browser/content_browser_client.h"
+#include "content/public/common/content_switches.h"
+#include "content/public/common/result_codes.h"
+#include "sandbox/linux/services/namespace_sandbox.h"
+#include "sandbox/linux/suid/client/setuid_sandbox_host.h"
+#include "ui/gfx/switches.h"
+
+namespace content {
+
+namespace {
+
+// Receive a fixed message on fd and return the sender's PID.
+// Returns true if the message received matches the expected message.
+bool ReceiveFixedMessage(int fd,
+ const char* expect_msg,
+ size_t expect_len,
+ base::ProcessId* sender_pid) {
+ char buf[expect_len + 1];
+ std::vector<base::ScopedFD> fds_vec;
+
+ const ssize_t len = base::UnixDomainSocket::RecvMsgWithPid(
+ fd, buf, sizeof(buf), &fds_vec, sender_pid);
+ if (static_cast<size_t>(len) != expect_len)
+ return false;
+ if (memcmp(buf, expect_msg, expect_len) != 0)
+ return false;
+ if (!fds_vec.empty())
+ return false;
+ return true;
+}
+
+} // namespace
+
+ZygoteCommunication::ZygoteCommunication()
+ : control_fd_(-1),
+ control_lock_(),
+ pid_(),
+ list_of_running_zygote_children_(),
+ child_tracking_lock_(),
+ sandbox_status_(0),
+ have_read_sandbox_status_word_(false),
+ init_(false) {}
+
+ZygoteCommunication::~ZygoteCommunication() {}
+
+bool ZygoteCommunication::SendMessage(const base::Pickle& data,
+ const std::vector<int>* fds) {
+ DCHECK_NE(-1, control_fd_);
+ CHECK(data.size() <= kZygoteMaxMessageLength)
+ << "Trying to send too-large message to zygote (sending " << data.size()
+ << " bytes, max is " << kZygoteMaxMessageLength << ")";
+ CHECK(!fds || fds->size() <= base::UnixDomainSocket::kMaxFileDescriptors)
+ << "Trying to send message with too many file descriptors to zygote "
+ << "(sending " << fds->size() << ", max is "
+ << base::UnixDomainSocket::kMaxFileDescriptors << ")";
+
+ return base::UnixDomainSocket::SendMsg(control_fd_, data.data(), data.size(),
+ fds ? *fds : std::vector<int>());
+}
+
+ssize_t ZygoteCommunication::ReadSandboxStatus() {
+ DCHECK_NE(-1, control_fd_);
+ // At startup we send a kZygoteCommandGetSandboxStatus request to the zygote,
+ // but don't wait for the reply. Thus, the first time that we read from the
+ // zygote, we get the reply to that request.
+ ssize_t bytes_read = HANDLE_EINTR(
+ read(control_fd_, &sandbox_status_, sizeof(sandbox_status_)));
+ if (bytes_read != sizeof(sandbox_status_)) {
+ return -1;
+ }
+ return bytes_read;
+}
+
+ssize_t ZygoteCommunication::ReadReply(void* buf, size_t buf_len) {
+ DCHECK_NE(-1, control_fd_);
+ if (!have_read_sandbox_status_word_) {
+ if (ReadSandboxStatus() == -1) {
+ return -1;
+ }
+ have_read_sandbox_status_word_ = true;
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Linux.SandboxStatus", sandbox_status_);
+ }
+
+ return HANDLE_EINTR(read(control_fd_, buf, buf_len));
+}
+
+pid_t ZygoteCommunication::ForkRequest(const std::vector<std::string>& argv,
+ scoped_ptr<FileDescriptorInfo> mapping,
+ const std::string& process_type) {
+ DCHECK(init_);
+
+ base::Pickle pickle;
+ int raw_socks[2];
+ PCHECK(0 == socketpair(AF_UNIX, SOCK_SEQPACKET, 0, raw_socks));
+ base::ScopedFD my_sock(raw_socks[0]);
+ base::ScopedFD peer_sock(raw_socks[1]);
+ CHECK(base::UnixDomainSocket::EnableReceiveProcessId(my_sock.get()));
+
+ pickle.WriteInt(kZygoteCommandFork);
+ pickle.WriteString(process_type);
+ pickle.WriteInt(argv.size());
+ for (std::vector<std::string>::const_iterator i = argv.begin();
+ i != argv.end(); ++i)
+ pickle.WriteString(*i);
+
+ // Fork requests contain one file descriptor for the PID oracle, and one
+ // more for each file descriptor mapping for the child process.
+ const size_t num_fds_to_send = 1 + mapping->GetMappingSize();
+ pickle.WriteInt(num_fds_to_send);
+
+ std::vector<int> fds;
+
+ // First FD to send is peer_sock.
+ // TODO(morrita): Ideally, this should be part of the mapping so that
+ // FileDescriptorInfo can manages its lifetime.
+ fds.push_back(peer_sock.get());
+
+ // The rest come from mapping.
+ for (size_t i = 0; i < mapping->GetMappingSize(); ++i) {
+ pickle.WriteUInt32(mapping->GetIDAt(i));
+ fds.push_back(mapping->GetFDAt(i));
+ }
+
+ // Sanity check that we've populated |fds| correctly.
+ DCHECK_EQ(num_fds_to_send, fds.size());
+
+ pid_t pid;
+ {
+ base::AutoLock lock(control_lock_);
+ if (!SendMessage(pickle, &fds))
+ return base::kNullProcessHandle;
+ mapping.reset();
+ peer_sock.reset();
+
+ {
+ char buf[sizeof(kZygoteChildPingMessage) + 1];
+ std::vector<base::ScopedFD> recv_fds;
+ base::ProcessId real_pid;
+
+ ssize_t n = base::UnixDomainSocket::RecvMsgWithPid(
+ my_sock.get(), buf, sizeof(buf), &recv_fds, &real_pid);
+ if (n != sizeof(kZygoteChildPingMessage) ||
+ 0 != memcmp(buf, kZygoteChildPingMessage,
+ sizeof(kZygoteChildPingMessage))) {
+ // Zygote children should still be trustworthy when they're supposed to
+ // ping us, so something's broken if we don't receive a valid ping.
+ LOG(ERROR) << "Did not receive ping from zygote child";
+ NOTREACHED();
+ real_pid = -1;
+ }
+ my_sock.reset();
+
+ // Always send PID back to zygote.
+ base::Pickle pid_pickle;
+ pid_pickle.WriteInt(kZygoteCommandForkRealPID);
+ pid_pickle.WriteInt(real_pid);
+ if (!SendMessage(pid_pickle, NULL))
+ return base::kNullProcessHandle;
+ }
+
+ // Read the reply, which pickles the PID and an optional UMA enumeration.
+ static const unsigned kMaxReplyLength = 2048;
+ char buf[kMaxReplyLength];
+ const ssize_t len = ReadReply(buf, sizeof(buf));
+
+ base::Pickle reply_pickle(buf, len);
+ base::PickleIterator iter(reply_pickle);
+ if (len <= 0 || !iter.ReadInt(&pid))
+ return base::kNullProcessHandle;
+
+ // If there is a nonempty UMA name string, then there is a UMA
+ // enumeration to record.
+ std::string uma_name;
+ int uma_sample;
+ int uma_boundary_value;
+ if (iter.ReadString(&uma_name) && !uma_name.empty() &&
+ iter.ReadInt(&uma_sample) && iter.ReadInt(&uma_boundary_value)) {
+ // We cannot use the UMA_HISTOGRAM_ENUMERATION macro here,
+ // because that's only for when the name is the same every time.
+ // Here we're using whatever name we got from the other side.
+ // But since it's likely that the same one will be used repeatedly
+ // (even though it's not guaranteed), we cache it here.
+ static base::HistogramBase* uma_histogram;
+ if (!uma_histogram || uma_histogram->histogram_name() != uma_name) {
+ uma_histogram = base::LinearHistogram::FactoryGet(
+ uma_name, 1, uma_boundary_value, uma_boundary_value + 1,
+ base::HistogramBase::kUmaTargetedHistogramFlag);
+ }
+ uma_histogram->Add(uma_sample);
+ }
+
+ if (pid <= 0)
+ return base::kNullProcessHandle;
+ }
+
+#if !defined(OS_OPENBSD)
+ // This is just a starting score for a renderer or extension (the
+ // only types of processes that will be started this way). It will
+ // get adjusted as time goes on. (This is the same value as
+ // chrome::kLowestRendererOomScore in chrome/chrome_constants.h, but
+ // that's not something we can include here.)
+ const int kLowestRendererOomScore = 300;
+ ZygoteHostImpl::GetInstance()->AdjustRendererOOMScore(
+ pid, kLowestRendererOomScore);
+#endif
+
+ ZygoteChildBorn(pid);
+ return pid;
+}
+
+void ZygoteCommunication::EnsureProcessTerminated(pid_t process) {
+ DCHECK(init_);
+ base::Pickle pickle;
+
+ pickle.WriteInt(kZygoteCommandReap);
+ pickle.WriteInt(process);
+ if (!SendMessage(pickle, NULL))
+ LOG(ERROR) << "Failed to send Reap message to zygote";
+ ZygoteChildDied(process);
+}
+
+void ZygoteCommunication::ZygoteChildBorn(pid_t process) {
+ base::AutoLock lock(child_tracking_lock_);
+ bool new_element_inserted =
+ list_of_running_zygote_children_.insert(process).second;
+ DCHECK(new_element_inserted);
+}
+
+void ZygoteCommunication::ZygoteChildDied(pid_t process) {
+ base::AutoLock lock(child_tracking_lock_);
+ size_t num_erased = list_of_running_zygote_children_.erase(process);
+ DCHECK_EQ(1U, num_erased);
+}
+
+void ZygoteCommunication::Init() {
+ CHECK(!init_);
+
+ base::FilePath chrome_path;
+ CHECK(PathService::Get(base::FILE_EXE, &chrome_path));
+ base::CommandLine cmd_line(chrome_path);
+
+ cmd_line.AppendSwitchASCII(switches::kProcessType, switches::kZygoteProcess);
+
+ int fds[2];
+ CHECK(socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds) == 0);
+ CHECK(base::UnixDomainSocket::EnableReceiveProcessId(fds[0]));
+ base::FileHandleMappingVector fds_to_map;
+ fds_to_map.push_back(std::make_pair(fds[1], kZygoteSocketPairFd));
+
+ base::LaunchOptions options;
+ const base::CommandLine& browser_command_line =
+ *base::CommandLine::ForCurrentProcess();
+ if (browser_command_line.HasSwitch(switches::kZygoteCmdPrefix)) {
+ cmd_line.PrependWrapper(
+ browser_command_line.GetSwitchValueNative(switches::kZygoteCmdPrefix));
+ }
+ // Append any switches from the browser process that need to be forwarded on
+ // to the zygote/renderers.
+ // Should this list be obtained from browser_render_process_host.cc?
+ static const char* kForwardSwitches[] = {
+ switches::kAllowSandboxDebugging, switches::kAndroidFontsPath,
+ switches::kDisableSeccompFilterSandbox,
+ switches::kEnableHeapProfiling,
+ switches::kEnableLogging, // Support, e.g., --enable-logging=stderr.
+ // Zygote process needs to know what resources to have loaded when it
+ // becomes a renderer process.
+ switches::kForceDeviceScaleFactor, switches::kLoggingLevel,
+ switches::kNoSandbox, switches::kPpapiInProcess,
+ switches::kRegisterPepperPlugins, switches::kV, switches::kVModule,
+ };
+ cmd_line.CopySwitchesFrom(browser_command_line, kForwardSwitches,
+ arraysize(kForwardSwitches));
+
+ GetContentClient()->browser()->AppendExtraCommandLineSwitches(&cmd_line, -1);
+
+ const bool using_namespace_sandbox =
+ ZygoteHostImpl::GetInstance()->ShouldUseNamespaceSandbox();
+ // A non empty sandbox_cmd means we want a SUID sandbox.
+ const bool using_suid_sandbox =
+ !ZygoteHostImpl::GetInstance()->SandboxCommand().empty() &&
+ !using_namespace_sandbox;
+
+ // Start up the sandbox host process and get the file descriptor for the
+ // renderers to talk to it.
+ const int sfd = RenderSandboxHostLinux::GetInstance()->GetRendererSocket();
+ fds_to_map.push_back(std::make_pair(sfd, GetSandboxFD()));
+
+ base::ScopedFD dummy_fd;
+ if (using_suid_sandbox) {
+ scoped_ptr<sandbox::SetuidSandboxHost> sandbox_host(
+ sandbox::SetuidSandboxHost::Create());
+ sandbox_host->PrependWrapper(&cmd_line);
+ sandbox_host->SetupLaunchOptions(&options, &fds_to_map, &dummy_fd);
+ sandbox_host->SetupLaunchEnvironment();
+ }
+
+ options.fds_to_remap = &fds_to_map;
+ base::Process process =
+ using_namespace_sandbox
+ ? sandbox::NamespaceSandbox::LaunchProcess(cmd_line, options)
+ : base::LaunchProcess(cmd_line, options);
+ CHECK(process.IsValid()) << "Failed to launch zygote process";
+
+ dummy_fd.reset();
+
+ if (using_suid_sandbox || using_namespace_sandbox) {
+ // The SUID sandbox will execute the zygote in a new PID namespace, and
+ // the main zygote process will then fork from there. Watch now our
+ // elaborate dance to find and validate the zygote's PID.
+
+ // First we receive a message from the zygote boot process.
+ base::ProcessId boot_pid;
+ CHECK(ReceiveFixedMessage(fds[0], kZygoteBootMessage,
+ sizeof(kZygoteBootMessage), &boot_pid));
+
+ // Within the PID namespace, the zygote boot process thinks it's PID 1,
+ // but its real PID can never be 1. This gives us a reliable test that
+ // the kernel is translating the sender's PID to our namespace.
+ CHECK_GT(boot_pid, 1)
+ << "Received invalid process ID for zygote; kernel might be too old? "
+ "See crbug.com/357670 or try using --"
+ << switches::kDisableSetuidSandbox << " to workaround.";
+
+ // Now receive the message that the zygote's ready to go, along with the
+ // main zygote process's ID.
+ CHECK(ReceiveFixedMessage(fds[0], kZygoteHelloMessage,
+ sizeof(kZygoteHelloMessage), &pid_));
+ CHECK_GT(pid_, 1);
+
+ if (process.Pid() != pid_) {
+ // Reap the sandbox.
+ base::EnsureProcessGetsReaped(process.Pid());
+ }
+ } else {
+ // Not using the SUID sandbox.
+ // Note that ~base::Process() will reset the internal value, but there's no
+ // real "handle" on POSIX so that is safe.
+ pid_ = process.Pid();
+ }
+
+ close(fds[1]);
+ control_fd_ = fds[0];
+
+ ZygoteHostImpl::GetInstance()->AddZygotePid(pid_);
+
+ base::Pickle pickle;
+ pickle.WriteInt(kZygoteCommandGetSandboxStatus);
+ if (!SendMessage(pickle, NULL))
+ LOG(FATAL) << "Cannot communicate with zygote";
+
+ init_ = true;
+}
+
+base::TerminationStatus ZygoteCommunication::GetTerminationStatus(
+ base::ProcessHandle handle,
+ bool known_dead,
+ int* exit_code) {
+ DCHECK(init_);
+ base::Pickle pickle;
+ pickle.WriteInt(kZygoteCommandGetTerminationStatus);
+ pickle.WriteBool(known_dead);
+ pickle.WriteInt(handle);
+
+ static const unsigned kMaxMessageLength = 128;
+ char buf[kMaxMessageLength];
+ ssize_t len;
+ {
+ base::AutoLock lock(control_lock_);
+ if (!SendMessage(pickle, NULL))
+ LOG(ERROR) << "Failed to send GetTerminationStatus message to zygote";
+ len = ReadReply(buf, sizeof(buf));
+ }
+
+ // Set this now to handle the error cases.
+ if (exit_code)
+ *exit_code = RESULT_CODE_NORMAL_EXIT;
+ int status = base::TERMINATION_STATUS_NORMAL_TERMINATION;
+
+ if (len == -1) {
+ LOG(WARNING) << "Error reading message from zygote: " << errno;
+ } else if (len == 0) {
+ LOG(WARNING) << "Socket closed prematurely.";
+ } else {
+ base::Pickle read_pickle(buf, len);
+ int tmp_status, tmp_exit_code;
+ base::PickleIterator iter(read_pickle);
+ if (!iter.ReadInt(&tmp_status) || !iter.ReadInt(&tmp_exit_code)) {
+ LOG(WARNING)
+ << "Error parsing GetTerminationStatus response from zygote.";
+ } else {
+ if (exit_code)
+ *exit_code = tmp_exit_code;
+ status = tmp_status;
+ }
+ }
+
+ if (status != base::TERMINATION_STATUS_STILL_RUNNING) {
+ ZygoteChildDied(handle);
+ }
+ return static_cast<base::TerminationStatus>(status);
+}
+
+int ZygoteCommunication::GetSandboxStatus() {
+ if (have_read_sandbox_status_word_) {
+ return sandbox_status_;
+ }
+ if (ReadSandboxStatus() == -1) {
+ return 0;
+ }
+ have_read_sandbox_status_word_ = true;
+ UMA_HISTOGRAM_SPARSE_SLOWLY("Linux.SandboxStatus", sandbox_status_);
+ return sandbox_status_;
+}
+
+} // namespace content
diff --git a/chromium/content/browser/zygote_host/zygote_communication_linux.h b/chromium/content/browser/zygote_host/zygote_communication_linux.h
new file mode 100644
index 00000000000..d3f4403cb15
--- /dev/null
+++ b/chromium/content/browser/zygote_host/zygote_communication_linux.h
@@ -0,0 +1,93 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_BROWSER_ZYGOTE_HOST_ZYGOTE_COMMUNICATION_LINUX_H_
+#define CONTENT_BROWSER_ZYGOTE_HOST_ZYGOTE_COMMUNICATION_LINUX_H_
+
+#include <set>
+#include <vector>
+
+#include "base/memory/scoped_ptr.h"
+#include "base/process/kill.h"
+#include "base/synchronization/lock.h"
+#include "content/common/content_export.h"
+#include "content/public/browser/file_descriptor_info.h"
+
+namespace content {
+
+class CONTENT_EXPORT ZygoteCommunication {
+ public:
+ ZygoteCommunication();
+ ~ZygoteCommunication();
+
+ void Init();
+
+ // Tries to start a process of type indicated by process_type.
+ // Returns its pid on success, otherwise base::kNullProcessHandle;
+ pid_t ForkRequest(const std::vector<std::string>& command_line,
+ scoped_ptr<FileDescriptorInfo> mapping,
+ const std::string& process_type);
+
+ void EnsureProcessTerminated(pid_t process);
+
+ // Should be called every time a Zygote child died.
+ void ZygoteChildDied(pid_t process);
+
+ // Get the termination status (and, optionally, the exit code) of
+ // the process. |exit_code| is set to the exit code of the child
+ // process. (|exit_code| may be NULL.)
+ // 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. 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);
+
+ // Returns the sandbox status of this zygote.
+ int GetSandboxStatus();
+
+ private:
+ // Whether we should use the namespace sandbox instead of the setuid sandbox.
+ bool ShouldUseNamespaceSandbox();
+
+ // Should be called every time a Zygote child is born.
+ void ZygoteChildBorn(pid_t process);
+
+ // Read the reply from the zygote.
+ ssize_t ReadReply(void* buf, size_t buf_len);
+
+ // Sends |data| to the zygote via |control_fd_|. If |fds| is non-NULL, the
+ // included file descriptors will also be passed. The caller is responsible
+ // for acquiring |control_lock_|.
+ bool SendMessage(const base::Pickle& data, const std::vector<int>* fds);
+
+ // Get the sandbox status from the zygote.
+ ssize_t ReadSandboxStatus();
+
+ int control_fd_; // the socket to the zygote.
+ // A lock protecting all communication with the zygote. This lock must be
+ // acquired before sending a command and released after the result has been
+ // received.
+ base::Lock control_lock_;
+ // The pid of the zygote.
+ pid_t pid_;
+ // The list of running zygote children.
+ std::set<pid_t> list_of_running_zygote_children_;
+ // The lock to guard the list of running zygote children.
+ base::Lock child_tracking_lock_;
+ int sandbox_status_;
+ bool have_read_sandbox_status_word_;
+ bool use_suid_sandbox_for_adj_oom_score_;
+ // Set to true when the zygote is initialized successfully.
+ bool init_;
+};
+
+} // namespace content
+
+#endif // CONTENT_BROWSER_ZYGOTE_HOST_ZYGOTE_COMMUNICATION_LINUX_H_
diff --git a/chromium/content/browser/zygote_host/zygote_handle_linux.cc b/chromium/content/browser/zygote_host/zygote_handle_linux.cc
new file mode 100644
index 00000000000..55830f57487
--- /dev/null
+++ b/chromium/content/browser/zygote_host/zygote_handle_linux.cc
@@ -0,0 +1,22 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/browser/zygote_handle_linux.h"
+
+#include "content/browser/zygote_host/zygote_communication_linux.h"
+
+namespace content {
+
+ZygoteHandle CreateZygote() {
+ ZygoteHandle zygote = new ZygoteCommunication();
+ zygote->Init();
+ return zygote;
+}
+
+ZygoteHandle* GetGenericZygote() {
+ static ZygoteHandle zygote;
+ return &zygote;
+}
+
+} // namespace content
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 5c964c531d3..e798f96fd7a 100644
--- a/chromium/content/browser/zygote_host/zygote_host_impl_linux.cc
+++ b/chromium/content/browser/zygote_host/zygote_host_impl_linux.cc
@@ -4,100 +4,32 @@
#include "content/browser/zygote_host/zygote_host_impl_linux.h"
-#include <errno.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "base/base_switches.h"
+#include "base/allocator/allocator_extension.h"
#include "base/command_line.h"
-#include "base/environment.h"
#include "base/files/file_enumerator.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_file.h"
-#include "base/linux_util.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/linked_ptr.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/metrics/histogram.h"
-#include "base/metrics/sparse_histogram.h"
-#include "base/path_service.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/posix/unix_domain_socket_linux.h"
-#include "base/process/launch.h"
+#include "base/process/kill.h"
#include "base/process/memory.h"
-#include "base/process/process_handle.h"
#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/time/time.h"
-#include "build/build_config.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"
-#include "content/public/common/result_codes.h"
#include "sandbox/linux/services/credentials.h"
-#include "sandbox/linux/services/namespace_sandbox.h"
-#include "sandbox/linux/services/namespace_utils.h"
-#include "sandbox/linux/suid/client/setuid_sandbox_host.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"
-#endif
namespace content {
-namespace {
-
-// Receive a fixed message on fd and return the sender's PID.
-// Returns true if the message received matches the expected message.
-bool ReceiveFixedMessage(int fd,
- const char* expect_msg,
- size_t expect_len,
- base::ProcessId* sender_pid) {
- char buf[expect_len + 1];
- std::vector<base::ScopedFD> fds_vec;
-
- const ssize_t len = base::UnixDomainSocket::RecvMsgWithPid(
- fd, buf, sizeof(buf), &fds_vec, sender_pid);
- if (static_cast<size_t>(len) != expect_len)
- return false;
- if (memcmp(buf, expect_msg, expect_len) != 0)
- return false;
- if (!fds_vec.empty())
- return false;
- return true;
-}
-
-} // namespace
-
// static
ZygoteHost* ZygoteHost::GetInstance() {
return ZygoteHostImpl::GetInstance();
}
ZygoteHostImpl::ZygoteHostImpl()
- : control_fd_(-1),
- control_lock_(),
- pid_(-1),
- init_(false),
+ : should_use_namespace_sandbox_(true),
use_suid_sandbox_for_adj_oom_score_(false),
sandbox_binary_(),
- have_read_sandbox_status_word_(false),
- sandbox_status_(0),
- child_tracking_lock_(),
- list_of_running_zygote_children_(),
- should_teardown_after_last_child_exits_(false) {}
+ zygote_pids_lock_(),
+ zygote_pids_() {}
-ZygoteHostImpl::~ZygoteHostImpl() { TearDown(); }
+ZygoteHostImpl::~ZygoteHostImpl() {}
// static
ZygoteHostImpl* ZygoteHostImpl::GetInstance() {
@@ -105,348 +37,59 @@ ZygoteHostImpl* ZygoteHostImpl::GetInstance() {
}
void ZygoteHostImpl::Init(const std::string& sandbox_cmd) {
- DCHECK(!init_);
- init_ = true;
-
- base::FilePath chrome_path;
- CHECK(PathService::Get(base::FILE_EXE, &chrome_path));
- base::CommandLine cmd_line(chrome_path);
+ sandbox_binary_ = sandbox_cmd;
- cmd_line.AppendSwitchASCII(switches::kProcessType, switches::kZygoteProcess);
-
- int fds[2];
- CHECK(socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds) == 0);
- CHECK(base::UnixDomainSocket::EnableReceiveProcessId(fds[0]));
- base::FileHandleMappingVector fds_to_map;
- fds_to_map.push_back(std::make_pair(fds[1], kZygoteSocketPairFd));
-
- base::LaunchOptions options;
- const base::CommandLine& browser_command_line =
+ const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
- if (browser_command_line.HasSwitch(switches::kZygoteCmdPrefix)) {
- cmd_line.PrependWrapper(
- browser_command_line.GetSwitchValueNative(switches::kZygoteCmdPrefix));
+ if (command_line.HasSwitch(switches::kNoSandbox) ||
+ command_line.HasSwitch(switches::kDisableNamespaceSandbox) ||
+ !sandbox::Credentials::CanCreateProcessInNewUserNS()) {
+ should_use_namespace_sandbox_ = false;
}
- // Append any switches from the browser process that need to be forwarded on
- // to the zygote/renderers.
- // Should this list be obtained from browser_render_process_host.cc?
- static const char* kForwardSwitches[] = {
- switches::kAllowSandboxDebugging,
- switches::kDisableSeccompFilterSandbox,
- switches::kEnableHeapProfiling,
- switches::kEnableLogging, // Support, e.g., --enable-logging=stderr.
- // Zygote process needs to know what resources to have loaded when it
- // becomes a renderer process.
- switches::kForceDeviceScaleFactor,
- switches::kLoggingLevel,
- switches::kNoSandbox,
- switches::kPpapiInProcess,
- switches::kRegisterPepperPlugins,
- switches::kV,
- switches::kVModule,
- };
- cmd_line.CopySwitchesFrom(browser_command_line, kForwardSwitches,
- arraysize(kForwardSwitches));
-
- GetContentClient()->browser()->AppendExtraCommandLineSwitches(&cmd_line, -1);
-
- sandbox_binary_ = sandbox_cmd.c_str();
const bool using_namespace_sandbox = ShouldUseNamespaceSandbox();
// A non empty sandbox_cmd means we want a SUID sandbox.
const bool using_suid_sandbox =
- !sandbox_cmd.empty() && !using_namespace_sandbox;
+ !sandbox_binary_.empty() && !using_namespace_sandbox;
// Use the SUID sandbox for adjusting OOM scores when we are using the setuid
- // or namespace sandbox. This is needed beacuse the processes are
- // non-dumpable, so /proc/pid/oom_score_adj can only be written by root.
- use_suid_sandbox_for_adj_oom_score_ =
- !sandbox_binary_.empty() && using_suid_sandbox;
+ // sandbox. This is needed beacuse the processes are non-dumpable, so
+ // /proc/pid/oom_score_adj can only be written by root.
+ use_suid_sandbox_for_adj_oom_score_ = using_suid_sandbox;
#if defined(OS_CHROMEOS)
// Chrome OS has a kernel patch that restricts oom_score_adj. See
// crbug.com/576409 for details.
- if (!sandbox_binary_.empty() && using_namespace_sandbox) {
+ if (!sandbox_binary_.empty()) {
use_suid_sandbox_for_adj_oom_score_ = true;
}
#endif
-
- // Start up the sandbox host process and get the file descriptor for the
- // renderers to talk to it.
- const int sfd = RenderSandboxHostLinux::GetInstance()->GetRendererSocket();
- fds_to_map.push_back(std::make_pair(sfd, GetSandboxFD()));
-
- base::ScopedFD dummy_fd;
- if (using_suid_sandbox) {
- scoped_ptr<sandbox::SetuidSandboxHost> sandbox_host(
- sandbox::SetuidSandboxHost::Create());
- sandbox_host->PrependWrapper(&cmd_line);
- sandbox_host->SetupLaunchOptions(&options, &fds_to_map, &dummy_fd);
- sandbox_host->SetupLaunchEnvironment();
- }
-
- options.fds_to_remap = &fds_to_map;
- base::Process process =
- using_namespace_sandbox
- ? sandbox::NamespaceSandbox::LaunchProcess(cmd_line, options)
- : base::LaunchProcess(cmd_line, options);
- CHECK(process.IsValid()) << "Failed to launch zygote process";
-
- dummy_fd.reset();
-
- if (using_suid_sandbox || using_namespace_sandbox) {
- // The SUID sandbox will execute the zygote in a new PID namespace, and
- // the main zygote process will then fork from there. Watch now our
- // elaborate dance to find and validate the zygote's PID.
-
- // First we receive a message from the zygote boot process.
- base::ProcessId boot_pid;
- CHECK(ReceiveFixedMessage(
- fds[0], kZygoteBootMessage, sizeof(kZygoteBootMessage), &boot_pid));
-
- // Within the PID namespace, the zygote boot process thinks it's PID 1,
- // but its real PID can never be 1. This gives us a reliable test that
- // the kernel is translating the sender's PID to our namespace.
- CHECK_GT(boot_pid, 1)
- << "Received invalid process ID for zygote; kernel might be too old? "
- "See crbug.com/357670 or try using --"
- << switches::kDisableSetuidSandbox << " to workaround.";
-
- // Now receive the message that the zygote's ready to go, along with the
- // main zygote process's ID.
- CHECK(ReceiveFixedMessage(
- fds[0], kZygoteHelloMessage, sizeof(kZygoteHelloMessage), &pid_));
- CHECK_GT(pid_, 1);
-
- if (process.Pid() != pid_) {
- // Reap the sandbox.
- base::EnsureProcessGetsReaped(process.Pid());
- }
- } else {
- // Not using the SUID sandbox.
- // Note that ~base::Process() will reset the internal value, but there's no
- // real "handle" on POSIX so that is safe.
- pid_ = process.Pid();
- }
-
- close(fds[1]);
- control_fd_ = fds[0];
-
- base::Pickle pickle;
- pickle.WriteInt(kZygoteCommandGetSandboxStatus);
- if (!SendMessage(pickle, NULL))
- LOG(FATAL) << "Cannot communicate with zygote";
- // We don't wait for the reply. We'll read it in ReadReply.
}
-void ZygoteHostImpl::TearDownAfterLastChild() {
- bool do_teardown = false;
- {
- base::AutoLock lock(child_tracking_lock_);
- should_teardown_after_last_child_exits_ = true;
- do_teardown = list_of_running_zygote_children_.empty();
- }
- if (do_teardown) {
- TearDown();
- }
+void ZygoteHostImpl::AddZygotePid(pid_t pid) {
+ base::AutoLock lock(zygote_pids_lock_);
+ zygote_pids_.insert(pid);
}
-// Note: this is also called from the destructor.
-void ZygoteHostImpl::TearDown() {
- base::AutoLock lock(control_lock_);
- if (control_fd_ > -1) {
- // Closing the IPC channel will act as a notification to exit
- // to the Zygote.
- if (IGNORE_EINTR(close(control_fd_))) {
- PLOG(ERROR) << "Could not close Zygote control channel.";
- NOTREACHED();
- }
- control_fd_ = -1;
- }
-}
-
-void ZygoteHostImpl::ZygoteChildBorn(pid_t process) {
- base::AutoLock lock(child_tracking_lock_);
- bool new_element_inserted =
- list_of_running_zygote_children_.insert(process).second;
- DCHECK(new_element_inserted);
+bool ZygoteHostImpl::IsZygotePid(pid_t pid) {
+ base::AutoLock lock(zygote_pids_lock_);
+ return zygote_pids_.find(pid) != zygote_pids_.end();
}
-void ZygoteHostImpl::ZygoteChildDied(pid_t process) {
- bool do_teardown = false;
- {
- base::AutoLock lock(child_tracking_lock_);
- size_t num_erased = list_of_running_zygote_children_.erase(process);
- DCHECK_EQ(1U, num_erased);
- do_teardown = should_teardown_after_last_child_exits_ &&
- list_of_running_zygote_children_.empty();
- }
- if (do_teardown) {
- TearDown();
- }
+const std::string& ZygoteHostImpl::SandboxCommand() const {
+ return sandbox_binary_;
}
-bool ZygoteHostImpl::SendMessage(const base::Pickle& data,
- const std::vector<int>* fds) {
- DCHECK_NE(-1, control_fd_);
- CHECK(data.size() <= kZygoteMaxMessageLength)
- << "Trying to send too-large message to zygote (sending " << data.size()
- << " bytes, max is " << kZygoteMaxMessageLength << ")";
- CHECK(!fds || fds->size() <= base::UnixDomainSocket::kMaxFileDescriptors)
- << "Trying to send message with too many file descriptors to zygote "
- << "(sending " << fds->size() << ", max is "
- << base::UnixDomainSocket::kMaxFileDescriptors << ")";
-
- return base::UnixDomainSocket::SendMsg(control_fd_,
- data.data(), data.size(),
- fds ? *fds : std::vector<int>());
+void ZygoteHostImpl::SetRendererSandboxStatus(int status) {
+ renderer_sandbox_status_ = status;
}
-ssize_t ZygoteHostImpl::ReadReply(void* buf, size_t buf_len) {
- DCHECK_NE(-1, control_fd_);
- // At startup we send a kZygoteCommandGetSandboxStatus request to the zygote,
- // but don't wait for the reply. Thus, the first time that we read from the
- // zygote, we get the reply to that request.
- if (!have_read_sandbox_status_word_) {
- if (HANDLE_EINTR(read(control_fd_, &sandbox_status_,
- sizeof(sandbox_status_))) !=
- sizeof(sandbox_status_)) {
- return -1;
- }
-
- have_read_sandbox_status_word_ = true;
- UMA_HISTOGRAM_SPARSE_SLOWLY("Linux.SandboxStatus", sandbox_status_);
- }
-
- return HANDLE_EINTR(read(control_fd_, buf, buf_len));
+int ZygoteHostImpl::GetRendererSandboxStatus() const {
+ return renderer_sandbox_status_;
}
-pid_t ZygoteHostImpl::ForkRequest(const std::vector<std::string>& argv,
- scoped_ptr<FileDescriptorInfo> mapping,
- const std::string& process_type) {
- DCHECK(init_);
- base::Pickle pickle;
-
- int raw_socks[2];
- PCHECK(0 == socketpair(AF_UNIX, SOCK_SEQPACKET, 0, raw_socks));
- base::ScopedFD my_sock(raw_socks[0]);
- base::ScopedFD peer_sock(raw_socks[1]);
- CHECK(base::UnixDomainSocket::EnableReceiveProcessId(my_sock.get()));
-
- pickle.WriteInt(kZygoteCommandFork);
- pickle.WriteString(process_type);
- pickle.WriteInt(argv.size());
- for (std::vector<std::string>::const_iterator
- i = argv.begin(); i != argv.end(); ++i)
- pickle.WriteString(*i);
-
- // Fork requests contain one file descriptor for the PID oracle, and one
- // more for each file descriptor mapping for the child process.
- const size_t num_fds_to_send = 1 + mapping->GetMappingSize();
- pickle.WriteInt(num_fds_to_send);
-
- std::vector<int> fds;
-
- // First FD to send is peer_sock.
- // TODO(morrita): Ideally, this should be part of the mapping so that
- // FileDescriptorInfo can manages its lifetime.
- fds.push_back(peer_sock.get());
-
- // The rest come from mapping.
- for (size_t i = 0; i < mapping->GetMappingSize(); ++i) {
- pickle.WriteUInt32(mapping->GetIDAt(i));
- fds.push_back(mapping->GetFDAt(i));
- }
-
- // Sanity check that we've populated |fds| correctly.
- DCHECK_EQ(num_fds_to_send, fds.size());
-
- pid_t pid;
- {
- base::AutoLock lock(control_lock_);
- if (!SendMessage(pickle, &fds))
- return base::kNullProcessHandle;
- mapping.reset();
- peer_sock.reset();
-
- {
- char buf[sizeof(kZygoteChildPingMessage) + 1];
- std::vector<base::ScopedFD> recv_fds;
- base::ProcessId real_pid;
-
- ssize_t n = base::UnixDomainSocket::RecvMsgWithPid(
- my_sock.get(), buf, sizeof(buf), &recv_fds, &real_pid);
- if (n != sizeof(kZygoteChildPingMessage) ||
- 0 != memcmp(buf,
- kZygoteChildPingMessage,
- sizeof(kZygoteChildPingMessage))) {
- // Zygote children should still be trustworthy when they're supposed to
- // ping us, so something's broken if we don't receive a valid ping.
- LOG(ERROR) << "Did not receive ping from zygote child";
- NOTREACHED();
- real_pid = -1;
- }
- my_sock.reset();
-
- // Always send PID back to zygote.
- base::Pickle pid_pickle;
- pid_pickle.WriteInt(kZygoteCommandForkRealPID);
- pid_pickle.WriteInt(real_pid);
- if (!SendMessage(pid_pickle, NULL))
- return base::kNullProcessHandle;
- }
-
- // Read the reply, which pickles the PID and an optional UMA enumeration.
- static const unsigned kMaxReplyLength = 2048;
- char buf[kMaxReplyLength];
- const ssize_t len = ReadReply(buf, sizeof(buf));
-
- base::Pickle reply_pickle(buf, len);
- base::PickleIterator iter(reply_pickle);
- if (len <= 0 || !iter.ReadInt(&pid))
- return base::kNullProcessHandle;
-
- // If there is a nonempty UMA name string, then there is a UMA
- // enumeration to record.
- std::string uma_name;
- int uma_sample;
- int uma_boundary_value;
- if (iter.ReadString(&uma_name) &&
- !uma_name.empty() &&
- iter.ReadInt(&uma_sample) &&
- iter.ReadInt(&uma_boundary_value)) {
- // We cannot use the UMA_HISTOGRAM_ENUMERATION macro here,
- // because that's only for when the name is the same every time.
- // Here we're using whatever name we got from the other side.
- // But since it's likely that the same one will be used repeatedly
- // (even though it's not guaranteed), we cache it here.
- static base::HistogramBase* uma_histogram;
- if (!uma_histogram || uma_histogram->histogram_name() != uma_name) {
- uma_histogram = base::LinearHistogram::FactoryGet(
- uma_name, 1,
- uma_boundary_value,
- uma_boundary_value + 1,
- base::HistogramBase::kUmaTargetedHistogramFlag);
- }
- uma_histogram->Add(uma_sample);
- }
-
- if (pid <= 0)
- return base::kNullProcessHandle;
- }
-
-#if !defined(OS_OPENBSD)
- // This is just a starting score for a renderer or extension (the
- // only types of processes that will be started this way). It will
- // get adjusted as time goes on. (This is the same value as
- // chrome::kLowestRendererOomScore in chrome/chrome_constants.h, but
- // that's not something we can include here.)
- const int kLowestRendererOomScore = 300;
- AdjustRendererOOMScore(pid, kLowestRendererOomScore);
-#endif
-
- ZygoteChildBorn(pid);
- return pid;
+bool ZygoteHostImpl::ShouldUseNamespaceSandbox() {
+ return should_use_namespace_sandbox_;
}
#if !defined(OS_OPENBSD)
@@ -492,13 +135,12 @@ void ZygoteHostImpl::AdjustRendererOOMScore(base::ProcessHandle pid,
}
if (use_suid_sandbox_for_adj_oom_score_ && !selinux) {
-#if defined(USE_TCMALLOC)
// If heap profiling is running, these processes are not exiting, at least
// on ChromeOS. The easiest thing to do is not launch them when profiling.
// TODO(stevenjb): Investigate further and fix.
- if (IsHeapProfilerRunning())
+ if (base::allocator::IsHeapProfilerRunning())
return;
-#endif
+
std::vector<std::string> adj_oom_score_cmdline;
adj_oom_score_cmdline.push_back(sandbox_binary_);
adj_oom_score_cmdline.push_back(sandbox::kAdjustOOMScoreSwitch);
@@ -522,92 +164,4 @@ void ZygoteHostImpl::AdjustRendererOOMScore(base::ProcessHandle pid,
}
#endif
-void ZygoteHostImpl::EnsureProcessTerminated(pid_t process) {
- DCHECK(init_);
- base::Pickle pickle;
-
- pickle.WriteInt(kZygoteCommandReap);
- pickle.WriteInt(process);
- if (!SendMessage(pickle, NULL))
- LOG(ERROR) << "Failed to send Reap message to zygote";
- ZygoteChildDied(process);
-}
-
-base::TerminationStatus ZygoteHostImpl::GetTerminationStatus(
- base::ProcessHandle handle,
- bool known_dead,
- int* exit_code) {
- DCHECK(init_);
- base::Pickle pickle;
- pickle.WriteInt(kZygoteCommandGetTerminationStatus);
- pickle.WriteBool(known_dead);
- pickle.WriteInt(handle);
-
- static const unsigned kMaxMessageLength = 128;
- char buf[kMaxMessageLength];
- ssize_t len;
- {
- base::AutoLock lock(control_lock_);
- if (!SendMessage(pickle, NULL))
- LOG(ERROR) << "Failed to send GetTerminationStatus message to zygote";
- len = ReadReply(buf, sizeof(buf));
- }
-
- // Set this now to handle the error cases.
- if (exit_code)
- *exit_code = RESULT_CODE_NORMAL_EXIT;
- int status = base::TERMINATION_STATUS_NORMAL_TERMINATION;
-
- if (len == -1) {
- LOG(WARNING) << "Error reading message from zygote: " << errno;
- } else if (len == 0) {
- LOG(WARNING) << "Socket closed prematurely.";
- } else {
- base::Pickle read_pickle(buf, len);
- int tmp_status, tmp_exit_code;
- base::PickleIterator iter(read_pickle);
- if (!iter.ReadInt(&tmp_status) || !iter.ReadInt(&tmp_exit_code)) {
- LOG(WARNING)
- << "Error parsing GetTerminationStatus response from zygote.";
- } else {
- if (exit_code)
- *exit_code = tmp_exit_code;
- status = tmp_status;
- }
- }
-
- if (status != base::TERMINATION_STATUS_STILL_RUNNING) {
- ZygoteChildDied(handle);
- }
- return static_cast<base::TerminationStatus>(status);
-}
-
-pid_t ZygoteHostImpl::GetPid() const {
- return pid_;
-}
-
-int ZygoteHostImpl::GetSandboxStatus() const {
- if (have_read_sandbox_status_word_)
- return sandbox_status_;
- return 0;
-}
-
-bool ZygoteHostImpl::ShouldUseNamespaceSandbox() {
- const base::CommandLine& command_line =
- *base::CommandLine::ForCurrentProcess();
- if (command_line.HasSwitch(switches::kNoSandbox)) {
- return false;
- }
-
- if (command_line.HasSwitch(switches::kDisableNamespaceSandbox)) {
- return false;
- }
-
- if (!sandbox::Credentials::CanCreateProcessInNewUserNS()) {
- return false;
- }
-
- return true;
-}
-
} // namespace content
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 6793f73757c..e42a222913f 100644
--- a/chromium/content/browser/zygote_host/zygote_host_impl_linux.h
+++ b/chromium/content/browser/zygote_host/zygote_host_impl_linux.h
@@ -5,16 +5,13 @@
#ifndef CONTENT_BROWSER_ZYGOTE_HOST_ZYGOTE_HOST_IMPL_LINUX_H_
#define CONTENT_BROWSER_ZYGOTE_HOST_ZYGOTE_HOST_IMPL_LINUX_H_
-#include <stddef.h>
+#include <sys/types.h>
#include <set>
#include <string>
-#include <vector>
-#include "base/pickle.h"
-#include "base/process/kill.h"
+#include "base/process/process_handle.h"
#include "base/synchronization/lock.h"
-#include "content/public/browser/file_descriptor_info.h"
#include "content/public/browser/zygote_host_linux.h"
namespace base {
@@ -31,35 +28,19 @@ class CONTENT_EXPORT ZygoteHostImpl : public ZygoteHost {
void Init(const std::string& sandbox_cmd);
- // After the last known Zygote child exits, notify the Zygote to exit.
- void TearDownAfterLastChild();
-
- // Tries to start a process of type indicated by process_type.
- // Returns its pid on success, otherwise
- // base::kNullProcessHandle;
- pid_t ForkRequest(const std::vector<std::string>& command_line,
- scoped_ptr<FileDescriptorInfo> mapping,
- const std::string& process_type);
- void EnsureProcessTerminated(pid_t process);
-
- // Get the termination status (and, optionally, the exit code) of
- // the process. |exit_code| is set to the exit code of the child
- // process. (|exit_code| may be NULL.)
- // 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. 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);
-
- // ZygoteHost implementation:
- pid_t GetPid() const override;
- int GetSandboxStatus() const override;
+ // Retrieves the sandbox command passed into Init();
+ const std::string& SandboxCommand() const;
+
+ // Tells the ZygoteHost the PIDs of all the zygotes.
+ void AddZygotePid(pid_t pid);
+
+ // Returns whether or not this pid is the pid of a zygote.
+ bool IsZygotePid(pid_t pid) override;
+
+ bool ShouldUseNamespaceSandbox();
+
+ void SetRendererSandboxStatus(int status);
+ int GetRendererSandboxStatus() const override;
void AdjustRendererOOMScore(base::ProcessHandle process_handle,
int score) override;
@@ -69,42 +50,14 @@ class CONTENT_EXPORT ZygoteHostImpl : public ZygoteHost {
ZygoteHostImpl();
~ZygoteHostImpl() override;
- // Notify the Zygote to exit immediately. This object should not be
- // used afterwards.
- void TearDown();
-
- // Should be called every time a Zygote child is born.
- void ZygoteChildBorn(pid_t process);
-
- // Should be called every time a Zygote child died.
- void ZygoteChildDied(pid_t process);
-
- // Sends |data| to the zygote via |control_fd_|. If |fds| is non-NULL, the
- // included file descriptors will also be passed. The caller is responsible
- // for acquiring |control_lock_|.
- bool SendMessage(const base::Pickle& data, const std::vector<int>* fds);
-
- ssize_t ReadReply(void* buf, size_t buflen);
-
- // Whether we should use the namespace sandbox instead of the setuid sandbox.
- bool ShouldUseNamespaceSandbox();
-
- int control_fd_; // the socket to the zygote
- // A lock protecting all communication with the zygote. This lock must be
- // acquired before sending a command and released after the result has been
- // received.
- base::Lock control_lock_;
- pid_t pid_;
- bool init_;
+ int renderer_sandbox_status_;
+ bool should_use_namespace_sandbox_;
bool use_suid_sandbox_for_adj_oom_score_;
std::string sandbox_binary_;
- bool have_read_sandbox_status_word_;
- int sandbox_status_;
- // A lock protecting list_of_running_zygote_children_ and
- // should_teardown_after_last_child_exits_.
- base::Lock child_tracking_lock_;
- std::set<pid_t> list_of_running_zygote_children_;
- bool should_teardown_after_last_child_exits_;
+ // This lock protects the |zygote_pids_| set.
+ base::Lock zygote_pids_lock_;
+ // This is a set of PIDs representing all the running zygotes.
+ std::set<pid_t> zygote_pids_;
};
} // namespace content
diff --git a/chromium/content/child/BUILD.gn b/chromium/content/child/BUILD.gn
index 86e154d319c..b3526cb793b 100644
--- a/chromium/content/child/BUILD.gn
+++ b/chromium/content/child/BUILD.gn
@@ -7,9 +7,17 @@ import("//build/config/ui.gni")
import("//content/child/child.gni")
source_set("child") {
- # Only the public target should depend on this. All other targets (even
- # internal content ones) should depend on the public one.
- visibility = [ "//content/public/child:child_sources" ]
+ # Targets external to content should always link to the public API.
+ # Internal targets can link to this but only if they're child processes
+ # (i.e. not content/browser or content/common) and only if they're inside the
+ # content component (i.e. not content/test or content/shell).
+ visibility = [
+ "//content/gpu/*",
+ "//content/ppapi_plugin/*",
+ "//content/public/child:child_sources",
+ "//content/renderer/*",
+ "//content/utility/*",
+ ]
sources = rebase_path(content_child_gypi_values.private_child_sources,
".",
@@ -21,22 +29,31 @@ source_set("child") {
]
public_deps = [
- "//third_party/mojo/src/mojo/edk/system",
+ "//gpu/ipc/client:client",
+ "//mojo/edk/system",
]
deps = [
"//base",
"//components/mime_util",
+ "//components/scheduler:scheduler",
"//components/tracing",
"//components/tracing:startup_tracing",
"//components/webcrypto",
- "//content/common:mojo_bindings",
+ "//content/app/resources",
+ "//content/app/strings",
+ "//content/common",
+ "//crypto:platform",
"//mojo/common",
- "//mojo/environment:chromium",
"//mojo/message_pump",
"//mojo/shell/public/interfaces",
+ "//mojo/shell/runner/common",
"//net",
"//skia",
+ "//storage/common",
+ "//third_party/WebKit/public:blink_headers",
+ "//third_party/WebKit/public:image_resources",
+ "//third_party/WebKit/public:resources",
"//third_party/icu",
"//ui/base",
"//ui/events/gestures/blink",
@@ -59,71 +76,12 @@ source_set("child") {
if (enable_plugins) {
deps += [ "//ppapi/proxy" ]
-
- if (is_win || is_android || !use_aura) {
- sources -= [ "npapi/webplugin_delegate_impl_aura.cc" ]
- }
} else {
- sources -= [
- "browser_font_resource_trusted.cc",
- "npapi/plugin_host.cc",
- "npapi/plugin_host.h",
- "npapi/plugin_instance.cc",
- "npapi/plugin_instance.h",
- "npapi/plugin_lib.cc",
- "npapi/plugin_lib.h",
- "npapi/webplugin.h",
- "npapi/webplugin_delegate.h",
- "npapi/webplugin_delegate_impl.cc",
- "npapi/webplugin_delegate_impl.h",
- "npapi/webplugin_resource_client.h",
- ]
-
- if (is_mac) {
- sources -= [
- "npapi/plugin_instance_mac.mm",
- "npapi/plugin_web_event_converter_mac.h",
- "npapi/plugin_web_event_converter_mac.mm",
- "npapi/webplugin_accelerated_surface_mac.h",
- "npapi/webplugin_delegate_impl_mac.mm",
- ]
- } else if (is_win) {
- sources -= [
- "npapi/webplugin_delegate_impl_win.cc",
- "npapi/webplugin_ime_win.cc",
- "npapi/webplugin_ime_win.h",
- ]
- } else if (is_android) {
- sources -= [ "npapi/webplugin_delegate_impl_android.cc" ]
- }
- sources -= [ "npapi/webplugin_delegate_impl_aura.cc" ]
+ sources -= [ "browser_font_resource_trusted.cc" ]
}
configs += [
"//content:content_implementation",
"//build/config/compiler:no_size_t_to_int_warning",
]
-
- if (is_ios) {
- # iOS only needs a small portion of content; exclude all the
- # implementation, and re-include what is used.
- sources = []
- } else {
- deps += [
- "//components/scheduler:scheduler",
- "//content/app/resources",
- "//content/app/strings",
- "//crypto:platform",
- "//storage/common",
- "//third_party/WebKit/public:blink",
- "//third_party/WebKit/public:image_resources",
- "//third_party/WebKit/public:resources",
- "//third_party/npapi",
- ]
- }
-
- if (use_aura && is_mac) {
- # This file is already excluded on non-Mac.
- sources -= [ "npapi/webplugin_delegate_impl_mac.mm" ]
- }
}
diff --git a/chromium/content/child/OWNERS b/chromium/content/child/OWNERS
index b212a3fd8e7..62b2db68ad4 100644
--- a/chromium/content/child/OWNERS
+++ b/chromium/content/child/OWNERS
@@ -1,3 +1,6 @@
+# For Blink API usage
+esprehn@chromium.org
+
per-file appcache*=michaeln@chromium.org
# WebSocket
diff --git a/chromium/content/child/appcache/appcache_dispatcher.h b/chromium/content/child/appcache/appcache_dispatcher.h
index 4dffb180e76..f556756408d 100644
--- a/chromium/content/child/appcache/appcache_dispatcher.h
+++ b/chromium/content/child/appcache/appcache_dispatcher.h
@@ -5,10 +5,10 @@
#ifndef CONTENT_CHILD_APPCACHE_APPCACHE_DISPATCHER_H_
#define CONTENT_CHILD_APPCACHE_APPCACHE_DISPATCHER_H_
+#include <memory>
#include <string>
#include <vector>
-#include "base/memory/scoped_ptr.h"
#include "content/child/appcache/appcache_backend_proxy.h"
#include "content/common/appcache_interfaces.h"
#include "ipc/ipc_listener.h"
@@ -45,7 +45,7 @@ class AppCacheDispatcher : public IPC::Listener {
void OnContentBlocked(int host_id, const GURL& manifest_url);
AppCacheBackendProxy backend_proxy_;
- scoped_ptr<AppCacheFrontend> frontend_;
+ std::unique_ptr<AppCacheFrontend> frontend_;
};
} // namespace content
diff --git a/chromium/content/child/appcache/appcache_frontend_impl.cc b/chromium/content/child/appcache/appcache_frontend_impl.cc
index 76b4b1f4e54..8bc059f79ac 100644
--- a/chromium/content/child/appcache/appcache_frontend_impl.cc
+++ b/chromium/content/child/appcache/appcache_frontend_impl.cc
@@ -90,45 +90,51 @@ void AppCacheFrontendImpl::OnContentBlocked(int host_id,
// Ensure that enum values never get out of sync with the
// ones declared for use within the WebKit api
-#define STATIC_ASSERT_ENUM(a, b, desc) \
- static_assert((int)a == (int)b, desc)
-
-// Confirm that WebApplicationCacheHost::<a> == APPCACHE_<b>.
-#define STATIC_ASSERT_WAC_ENUM(a, b) \
- STATIC_ASSERT_ENUM(WebApplicationCacheHost:: a, APPCACHE_##b, #a)
-
-STATIC_ASSERT_WAC_ENUM(Uncached, STATUS_UNCACHED);
-STATIC_ASSERT_WAC_ENUM(Idle, STATUS_IDLE);
-STATIC_ASSERT_WAC_ENUM(Checking, STATUS_CHECKING);
-STATIC_ASSERT_WAC_ENUM(Downloading, STATUS_DOWNLOADING);
-STATIC_ASSERT_WAC_ENUM(UpdateReady, STATUS_UPDATE_READY);
-STATIC_ASSERT_WAC_ENUM(Obsolete, STATUS_OBSOLETE);
-
-STATIC_ASSERT_WAC_ENUM(CheckingEvent, CHECKING_EVENT);
-STATIC_ASSERT_WAC_ENUM(ErrorEvent, ERROR_EVENT);
-STATIC_ASSERT_WAC_ENUM(NoUpdateEvent, NO_UPDATE_EVENT);
-STATIC_ASSERT_WAC_ENUM(DownloadingEvent, DOWNLOADING_EVENT);
-STATIC_ASSERT_WAC_ENUM(ProgressEvent, PROGRESS_EVENT);
-STATIC_ASSERT_WAC_ENUM(UpdateReadyEvent, UPDATE_READY_EVENT);
-STATIC_ASSERT_WAC_ENUM(CachedEvent, CACHED_EVENT);
-STATIC_ASSERT_WAC_ENUM(ObsoleteEvent, OBSOLETE_EVENT);
-
-STATIC_ASSERT_WAC_ENUM(ManifestError, MANIFEST_ERROR);
-STATIC_ASSERT_WAC_ENUM(SignatureError, SIGNATURE_ERROR);
-STATIC_ASSERT_WAC_ENUM(ResourceError, RESOURCE_ERROR);
-STATIC_ASSERT_WAC_ENUM(ChangedError, CHANGED_ERROR);
-STATIC_ASSERT_WAC_ENUM(AbortError, ABORT_ERROR);
-STATIC_ASSERT_WAC_ENUM(QuotaError, QUOTA_ERROR);
-STATIC_ASSERT_WAC_ENUM(PolicyError, POLICY_ERROR);
-STATIC_ASSERT_WAC_ENUM(UnknownError, UNKNOWN_ERROR);
-
-// Confirm that WebConsoleMessage::<a> == APPCACHE_<b>.
-#define STATIC_ASSERT_WCM_ENUM(a, b) \
- STATIC_ASSERT_ENUM(WebConsoleMessage:: a, APPCACHE_##b, #a)
-
-STATIC_ASSERT_WCM_ENUM(LevelDebug, LOG_DEBUG);
-STATIC_ASSERT_WCM_ENUM(LevelLog, LOG_INFO);
-STATIC_ASSERT_WCM_ENUM(LevelWarning, LOG_WARNING);
-STATIC_ASSERT_WCM_ENUM(LevelError, LOG_ERROR);
+#define STATIC_ASSERT_ENUM(a, b) \
+ static_assert(static_cast<int>(a) == static_cast<int>(b), \
+ "mismatched enum: " #a)
+
+STATIC_ASSERT_ENUM(WebApplicationCacheHost::Uncached, APPCACHE_STATUS_UNCACHED);
+STATIC_ASSERT_ENUM(WebApplicationCacheHost::Idle, APPCACHE_STATUS_IDLE);
+STATIC_ASSERT_ENUM(WebApplicationCacheHost::Checking, APPCACHE_STATUS_CHECKING);
+STATIC_ASSERT_ENUM(WebApplicationCacheHost::Downloading,
+ APPCACHE_STATUS_DOWNLOADING);
+STATIC_ASSERT_ENUM(WebApplicationCacheHost::UpdateReady,
+ APPCACHE_STATUS_UPDATE_READY);
+STATIC_ASSERT_ENUM(WebApplicationCacheHost::Obsolete, APPCACHE_STATUS_OBSOLETE);
+
+STATIC_ASSERT_ENUM(WebApplicationCacheHost::CheckingEvent,
+ APPCACHE_CHECKING_EVENT);
+STATIC_ASSERT_ENUM(WebApplicationCacheHost::ErrorEvent, APPCACHE_ERROR_EVENT);
+STATIC_ASSERT_ENUM(WebApplicationCacheHost::NoUpdateEvent,
+ APPCACHE_NO_UPDATE_EVENT);
+STATIC_ASSERT_ENUM(WebApplicationCacheHost::DownloadingEvent,
+ APPCACHE_DOWNLOADING_EVENT);
+STATIC_ASSERT_ENUM(WebApplicationCacheHost::ProgressEvent,
+ APPCACHE_PROGRESS_EVENT);
+STATIC_ASSERT_ENUM(WebApplicationCacheHost::UpdateReadyEvent,
+ APPCACHE_UPDATE_READY_EVENT);
+STATIC_ASSERT_ENUM(WebApplicationCacheHost::CachedEvent, APPCACHE_CACHED_EVENT);
+STATIC_ASSERT_ENUM(WebApplicationCacheHost::ObsoleteEvent,
+ APPCACHE_OBSOLETE_EVENT);
+
+STATIC_ASSERT_ENUM(WebApplicationCacheHost::ManifestError,
+ APPCACHE_MANIFEST_ERROR);
+STATIC_ASSERT_ENUM(WebApplicationCacheHost::SignatureError,
+ APPCACHE_SIGNATURE_ERROR);
+STATIC_ASSERT_ENUM(WebApplicationCacheHost::ResourceError,
+ APPCACHE_RESOURCE_ERROR);
+STATIC_ASSERT_ENUM(WebApplicationCacheHost::ChangedError,
+ APPCACHE_CHANGED_ERROR);
+STATIC_ASSERT_ENUM(WebApplicationCacheHost::AbortError, APPCACHE_ABORT_ERROR);
+STATIC_ASSERT_ENUM(WebApplicationCacheHost::QuotaError, APPCACHE_QUOTA_ERROR);
+STATIC_ASSERT_ENUM(WebApplicationCacheHost::PolicyError, APPCACHE_POLICY_ERROR);
+STATIC_ASSERT_ENUM(WebApplicationCacheHost::UnknownError,
+ APPCACHE_UNKNOWN_ERROR);
+
+STATIC_ASSERT_ENUM(WebConsoleMessage::LevelDebug, APPCACHE_LOG_DEBUG);
+STATIC_ASSERT_ENUM(WebConsoleMessage::LevelLog, APPCACHE_LOG_INFO);
+STATIC_ASSERT_ENUM(WebConsoleMessage::LevelWarning, APPCACHE_LOG_WARNING);
+STATIC_ASSERT_ENUM(WebConsoleMessage::LevelError, APPCACHE_LOG_ERROR);
} // namespace content
diff --git a/chromium/content/child/appcache/web_application_cache_host_impl.cc b/chromium/content/child/appcache/web_application_cache_host_impl.cc
index 12fa2a21494..9b96260977a 100644
--- a/chromium/content/child/appcache/web_application_cache_host_impl.cc
+++ b/chromium/content/child/appcache/web_application_cache_host_impl.cc
@@ -270,7 +270,7 @@ void WebApplicationCacheHostImpl::didFinishLoadingMainResource(bool success) {
// TODO(michaeln): write me
}
-WebApplicationCacheHost::Status WebApplicationCacheHostImpl::status() {
+WebApplicationCacheHost::Status WebApplicationCacheHostImpl::getStatus() {
return static_cast<WebApplicationCacheHost::Status>(status_);
}
diff --git a/chromium/content/child/appcache/web_application_cache_host_impl.h b/chromium/content/child/appcache/web_application_cache_host_impl.h
index a26b7df8e32..c50b45e7a44 100644
--- a/chromium/content/child/appcache/web_application_cache_host_impl.h
+++ b/chromium/content/child/appcache/web_application_cache_host_impl.h
@@ -49,7 +49,7 @@ class WebApplicationCacheHostImpl
void didReceiveResponseForMainResource(const blink::WebURLResponse&) override;
void didReceiveDataForMainResource(const char* data, unsigned len) override;
void didFinishLoadingMainResource(bool success) override;
- blink::WebApplicationCacheHost::Status status() override;
+ blink::WebApplicationCacheHost::Status getStatus() override;
bool startUpdate() override;
bool swapCache() override;
void getResourceList(blink::WebVector<ResourceInfo>* resources) override;
diff --git a/chromium/content/child/assert_matching_enums.cc b/chromium/content/child/assert_matching_enums.cc
index c211ee1537c..69025290579 100644
--- a/chromium/content/child/assert_matching_enums.cc
+++ b/chromium/content/child/assert_matching_enums.cc
@@ -6,57 +6,42 @@
// from Blink are valid.
#include "base/macros.h"
-#include "cc/animation/animation.h"
#include "content/public/common/screen_orientation_values.h"
#include "media/base/mime_util.h"
-#include "third_party/WebKit/public/platform/WebCompositorAnimation.h"
#include "third_party/WebKit/public/platform/WebMimeRegistry.h"
#include "third_party/WebKit/public/platform/modules/screen_orientation/WebScreenOrientationLockType.h"
namespace content {
-#define STATIC_ASSERT_MATCHING_ENUM(expected, actual) \
- static_assert(int(expected) == int(actual), "mismatching enums: " #expected)
+#define STATIC_ASSERT_ENUM(a, b) \
+ static_assert(static_cast<int>(a) == static_cast<int>(b), \
+ "mismatching enums: " #a)
// ScreenOrientationValues
-STATIC_ASSERT_MATCHING_ENUM(blink::WebScreenOrientationLockDefault,
- SCREEN_ORIENTATION_VALUES_DEFAULT);
-STATIC_ASSERT_MATCHING_ENUM(blink::WebScreenOrientationLockPortraitPrimary,
- SCREEN_ORIENTATION_VALUES_PORTRAIT_PRIMARY);
-STATIC_ASSERT_MATCHING_ENUM(blink::WebScreenOrientationLockPortraitSecondary,
- SCREEN_ORIENTATION_VALUES_PORTRAIT_SECONDARY);
-STATIC_ASSERT_MATCHING_ENUM(blink::WebScreenOrientationLockLandscapePrimary,
- SCREEN_ORIENTATION_VALUES_LANDSCAPE_PRIMARY);
-STATIC_ASSERT_MATCHING_ENUM(blink::WebScreenOrientationLockLandscapeSecondary,
- SCREEN_ORIENTATION_VALUES_LANDSCAPE_SECONDARY);
-STATIC_ASSERT_MATCHING_ENUM(blink::WebScreenOrientationLockAny,
- SCREEN_ORIENTATION_VALUES_ANY);
-STATIC_ASSERT_MATCHING_ENUM(blink::WebScreenOrientationLockLandscape,
- SCREEN_ORIENTATION_VALUES_LANDSCAPE);
-STATIC_ASSERT_MATCHING_ENUM(blink::WebScreenOrientationLockPortrait,
- SCREEN_ORIENTATION_VALUES_PORTRAIT);
-STATIC_ASSERT_MATCHING_ENUM(blink::WebScreenOrientationLockNatural,
- SCREEN_ORIENTATION_VALUES_NATURAL);
+STATIC_ASSERT_ENUM(blink::WebScreenOrientationLockDefault,
+ SCREEN_ORIENTATION_VALUES_DEFAULT);
+STATIC_ASSERT_ENUM(blink::WebScreenOrientationLockPortraitPrimary,
+ SCREEN_ORIENTATION_VALUES_PORTRAIT_PRIMARY);
+STATIC_ASSERT_ENUM(blink::WebScreenOrientationLockPortraitSecondary,
+ SCREEN_ORIENTATION_VALUES_PORTRAIT_SECONDARY);
+STATIC_ASSERT_ENUM(blink::WebScreenOrientationLockLandscapePrimary,
+ SCREEN_ORIENTATION_VALUES_LANDSCAPE_PRIMARY);
+STATIC_ASSERT_ENUM(blink::WebScreenOrientationLockLandscapeSecondary,
+ SCREEN_ORIENTATION_VALUES_LANDSCAPE_SECONDARY);
+STATIC_ASSERT_ENUM(blink::WebScreenOrientationLockAny,
+ SCREEN_ORIENTATION_VALUES_ANY);
+STATIC_ASSERT_ENUM(blink::WebScreenOrientationLockLandscape,
+ SCREEN_ORIENTATION_VALUES_LANDSCAPE);
+STATIC_ASSERT_ENUM(blink::WebScreenOrientationLockPortrait,
+ SCREEN_ORIENTATION_VALUES_PORTRAIT);
+STATIC_ASSERT_ENUM(blink::WebScreenOrientationLockNatural,
+ SCREEN_ORIENTATION_VALUES_NATURAL);
// SupportsType
-STATIC_ASSERT_MATCHING_ENUM(blink::WebMimeRegistry::IsNotSupported,
- media::IsNotSupported);
-STATIC_ASSERT_MATCHING_ENUM(blink::WebMimeRegistry::IsSupported,
- media::IsSupported);
-STATIC_ASSERT_MATCHING_ENUM(blink::WebMimeRegistry::MayBeSupported,
- media::MayBeSupported);
-
-// TargetProperty
-STATIC_ASSERT_MATCHING_ENUM(
- blink::WebCompositorAnimation::TargetPropertyTransform,
- cc::Animation::TRANSFORM);
-STATIC_ASSERT_MATCHING_ENUM(
- blink::WebCompositorAnimation::TargetPropertyOpacity,
- cc::Animation::OPACITY);
-STATIC_ASSERT_MATCHING_ENUM(blink::WebCompositorAnimation::TargetPropertyFilter,
- cc::Animation::FILTER);
-STATIC_ASSERT_MATCHING_ENUM(
- blink::WebCompositorAnimation::TargetPropertyScrollOffset,
- cc::Animation::SCROLL_OFFSET);
+STATIC_ASSERT_ENUM(blink::WebMimeRegistry::IsNotSupported,
+ media::IsNotSupported);
+STATIC_ASSERT_ENUM(blink::WebMimeRegistry::IsSupported, media::IsSupported);
+STATIC_ASSERT_ENUM(blink::WebMimeRegistry::MayBeSupported,
+ media::MayBeSupported);
} // namespace content
diff --git a/chromium/content/child/background_sync/background_sync_provider.cc b/chromium/content/child/background_sync/background_sync_provider.cc
index d29a40f9e38..af6ed44e152 100644
--- a/chromium/content/child/background_sync/background_sync_provider.cc
+++ b/chromium/content/child/background_sync/background_sync_provider.cc
@@ -5,18 +5,18 @@
#include "content/child/background_sync/background_sync_provider.h"
#include <stddef.h>
+
+#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/lazy_instance.h"
-#include "base/memory/scoped_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_local.h"
#include "content/child/background_sync/background_sync_type_converters.h"
#include "content/child/child_thread_impl.h"
#include "content/child/service_worker/web_service_worker_registration_impl.h"
#include "content/public/common/background_sync.mojom.h"
-#include "content/public/common/permission_status.mojom.h"
#include "third_party/WebKit/public/platform/modules/background_sync/WebSyncError.h"
#include "third_party/WebKit/public/platform/modules/background_sync/WebSyncRegistration.h"
@@ -35,7 +35,7 @@ int64_t GetServiceWorkerRegistrationId(
}
void ConnectToServiceOnMainThread(
- mojo::InterfaceRequest<BackgroundSyncService> request) {
+ mojo::InterfaceRequest<mojom::BackgroundSyncService> request) {
DCHECK(ChildThreadImpl::current());
ChildThreadImpl::current()->service_registry()->ConnectToRemoteService(
std::move(request));
@@ -68,7 +68,7 @@ BackgroundSyncProvider::GetOrCreateThreadSpecificInstance(
bool have_worker_id = (WorkerThread::GetCurrentId() > 0);
if (!main_thread_task_runner->BelongsToCurrentThread() && !have_worker_id) {
// On a worker thread, this could happen if this method is called
- // very late (say by a garbage collected SyncRegistration).
+ // very late (say by a garbage collected mojom::SyncRegistration).
return nullptr;
}
@@ -87,230 +87,81 @@ BackgroundSyncProvider::GetOrCreateThreadSpecificInstance(
void BackgroundSyncProvider::registerBackgroundSync(
const blink::WebSyncRegistration* options,
blink::WebServiceWorkerRegistration* service_worker_registration,
- bool requested_from_service_worker,
blink::WebSyncRegistrationCallbacks* callbacks) {
DCHECK(options);
DCHECK(service_worker_registration);
DCHECK(callbacks);
int64_t service_worker_registration_id =
GetServiceWorkerRegistrationId(service_worker_registration);
- scoped_ptr<const blink::WebSyncRegistration> optionsPtr(options);
- scoped_ptr<blink::WebSyncRegistrationCallbacks> callbacksPtr(callbacks);
+ std::unique_ptr<const blink::WebSyncRegistration> optionsPtr(options);
+ std::unique_ptr<blink::WebSyncRegistrationCallbacks> callbacksPtr(callbacks);
// base::Unretained is safe here, as the mojo channel will be deleted (and
// will wipe its callbacks) before 'this' is deleted.
GetBackgroundSyncServicePtr()->Register(
- mojo::ConvertTo<SyncRegistrationPtr>(*(optionsPtr.get())),
- service_worker_registration_id, requested_from_service_worker,
- base::Bind(&BackgroundSyncProvider::RegisterCallback,
- base::Unretained(this),
- base::Passed(std::move(callbacksPtr))));
-}
-
-void BackgroundSyncProvider::unregisterBackgroundSync(
- int64_t handle_id,
- blink::WebServiceWorkerRegistration* service_worker_registration,
- blink::WebSyncUnregistrationCallbacks* callbacks) {
- DCHECK(service_worker_registration);
- DCHECK(callbacks);
- int64_t service_worker_registration_id =
- GetServiceWorkerRegistrationId(service_worker_registration);
- scoped_ptr<blink::WebSyncUnregistrationCallbacks> callbacksPtr(callbacks);
-
- // base::Unretained is safe here, as the mojo channel will be deleted (and
- // will wipe its callbacks) before 'this' is deleted.
- GetBackgroundSyncServicePtr()->Unregister(
- handle_id, service_worker_registration_id,
- base::Bind(&BackgroundSyncProvider::UnregisterCallback,
- base::Unretained(this),
- base::Passed(std::move(callbacksPtr))));
-}
-
-void BackgroundSyncProvider::getRegistration(
- blink::WebSyncRegistration::Periodicity periodicity,
- const blink::WebString& tag,
- blink::WebServiceWorkerRegistration* service_worker_registration,
- blink::WebSyncRegistrationCallbacks* callbacks) {
- DCHECK(service_worker_registration);
- DCHECK(callbacks);
- int64_t service_worker_registration_id =
- GetServiceWorkerRegistrationId(service_worker_registration);
- scoped_ptr<blink::WebSyncRegistrationCallbacks> callbacksPtr(callbacks);
-
- // base::Unretained is safe here, as the mojo channel will be deleted (and
- // will wipe its callbacks) before 'this' is deleted.
- GetBackgroundSyncServicePtr()->GetRegistration(
- mojo::ConvertTo<BackgroundSyncPeriodicity>(periodicity), tag.utf8(),
+ mojo::ConvertTo<mojom::SyncRegistrationPtr>(*(optionsPtr.get())),
service_worker_registration_id,
- base::Bind(&BackgroundSyncProvider::GetRegistrationCallback,
+ base::Bind(&BackgroundSyncProvider::RegisterCallback,
base::Unretained(this),
base::Passed(std::move(callbacksPtr))));
}
void BackgroundSyncProvider::getRegistrations(
- blink::WebSyncRegistration::Periodicity periodicity,
blink::WebServiceWorkerRegistration* service_worker_registration,
blink::WebSyncGetRegistrationsCallbacks* callbacks) {
DCHECK(service_worker_registration);
DCHECK(callbacks);
int64_t service_worker_registration_id =
GetServiceWorkerRegistrationId(service_worker_registration);
- scoped_ptr<blink::WebSyncGetRegistrationsCallbacks> callbacksPtr(callbacks);
+ std::unique_ptr<blink::WebSyncGetRegistrationsCallbacks> callbacksPtr(
+ callbacks);
// base::Unretained is safe here, as the mojo channel will be deleted (and
// will wipe its callbacks) before 'this' is deleted.
GetBackgroundSyncServicePtr()->GetRegistrations(
- mojo::ConvertTo<BackgroundSyncPeriodicity>(periodicity),
service_worker_registration_id,
base::Bind(&BackgroundSyncProvider::GetRegistrationsCallback,
base::Unretained(this),
base::Passed(std::move(callbacksPtr))));
}
-void BackgroundSyncProvider::getPermissionStatus(
- blink::WebSyncRegistration::Periodicity periodicity,
- blink::WebServiceWorkerRegistration* service_worker_registration,
- blink::WebSyncGetPermissionStatusCallbacks* callbacks) {
- DCHECK(service_worker_registration);
- DCHECK(callbacks);
- int64_t service_worker_registration_id =
- GetServiceWorkerRegistrationId(service_worker_registration);
- scoped_ptr<blink::WebSyncGetPermissionStatusCallbacks> callbacksPtr(
- callbacks);
-
- // base::Unretained is safe here, as the mojo channel will be deleted (and
- // will wipe its callbacks) before 'this' is deleted.
- GetBackgroundSyncServicePtr()->GetPermissionStatus(
- mojo::ConvertTo<BackgroundSyncPeriodicity>(periodicity),
- service_worker_registration_id,
- base::Bind(&BackgroundSyncProvider::GetPermissionStatusCallback,
- base::Unretained(this),
- base::Passed(std::move(callbacksPtr))));
-}
-
-void BackgroundSyncProvider::releaseRegistration(int64_t handle_id) {
- GetBackgroundSyncServicePtr()->ReleaseRegistration(handle_id);
-}
-
-void BackgroundSyncProvider::notifyWhenFinished(
- int64_t handle_id,
- blink::WebSyncNotifyWhenFinishedCallbacks* callbacks) {
- DCHECK(callbacks);
-
- scoped_ptr<blink::WebSyncNotifyWhenFinishedCallbacks> callbacks_ptr(
- callbacks);
-
- // base::Unretained is safe here, as the mojo channel will be deleted (and
- // will wipe its callbacks) before 'this' is deleted.
- GetBackgroundSyncServicePtr()->NotifyWhenFinished(
- handle_id, base::Bind(&BackgroundSyncProvider::NotifyWhenFinishedCallback,
- base::Unretained(this),
- base::Passed(std::move(callbacks_ptr))));
-}
-
-void BackgroundSyncProvider::DuplicateRegistrationHandle(
- int64_t handle_id,
- const BackgroundSyncService::DuplicateRegistrationHandleCallback&
- callback) {
- GetBackgroundSyncServicePtr()->DuplicateRegistrationHandle(handle_id,
- callback);
-}
-
void BackgroundSyncProvider::WillStopCurrentWorkerThread() {
delete this;
}
void BackgroundSyncProvider::RegisterCallback(
- scoped_ptr<blink::WebSyncRegistrationCallbacks> callbacks,
- BackgroundSyncError error,
- const SyncRegistrationPtr& options) {
+ std::unique_ptr<blink::WebSyncRegistrationCallbacks> callbacks,
+ mojom::BackgroundSyncError error,
+ const mojom::SyncRegistrationPtr& options) {
// TODO(iclelland): Determine the correct error message to return in each case
- scoped_ptr<blink::WebSyncRegistration> result;
+ std::unique_ptr<blink::WebSyncRegistration> result;
switch (error) {
- case BACKGROUND_SYNC_ERROR_NONE:
+ case mojom::BackgroundSyncError::NONE:
if (!options.is_null())
- result =
- mojo::ConvertTo<scoped_ptr<blink::WebSyncRegistration>>(options);
- callbacks->onSuccess(blink::adoptWebPtr(result.release()));
+ result = mojo::ConvertTo<std::unique_ptr<blink::WebSyncRegistration>>(
+ options);
+ callbacks->onSuccess(std::move(result));
break;
- case BACKGROUND_SYNC_ERROR_NOT_FOUND:
+ case mojom::BackgroundSyncError::NOT_FOUND:
NOTREACHED();
break;
- case BACKGROUND_SYNC_ERROR_STORAGE:
+ case mojom::BackgroundSyncError::STORAGE:
callbacks->onError(
blink::WebSyncError(blink::WebSyncError::ErrorTypeUnknown,
"Background Sync is disabled."));
break;
- case BACKGROUND_SYNC_ERROR_NOT_ALLOWED:
+ case mojom::BackgroundSyncError::NOT_ALLOWED:
callbacks->onError(
blink::WebSyncError(blink::WebSyncError::ErrorTypeNoPermission,
"Attempted to register a sync event without a "
"window or registration tag too long."));
break;
- case BACKGROUND_SYNC_ERROR_NO_SERVICE_WORKER:
- callbacks->onError(
- blink::WebSyncError(blink::WebSyncError::ErrorTypeUnknown,
- "No service worker is active."));
- break;
- }
-}
-
-void BackgroundSyncProvider::UnregisterCallback(
- scoped_ptr<blink::WebSyncUnregistrationCallbacks> callbacks,
- BackgroundSyncError error) {
- // TODO(iclelland): Determine the correct error message to return in each case
- switch (error) {
- case BACKGROUND_SYNC_ERROR_NONE:
- callbacks->onSuccess(true);
- break;
- case BACKGROUND_SYNC_ERROR_NOT_FOUND:
- callbacks->onSuccess(false);
- break;
- case BACKGROUND_SYNC_ERROR_STORAGE:
+ case mojom::BackgroundSyncError::PERMISSION_DENIED:
callbacks->onError(
- blink::WebSyncError(blink::WebSyncError::ErrorTypeUnknown,
- "Background Sync is disabled."));
- break;
- case BACKGROUND_SYNC_ERROR_NOT_ALLOWED:
- // This error should never be returned from
- // BackgroundSyncManager::Unregister
- NOTREACHED();
+ blink::WebSyncError(blink::WebSyncError::ErrorTypePermissionDenied,
+ "Permission denied."));
break;
- case BACKGROUND_SYNC_ERROR_NO_SERVICE_WORKER:
- callbacks->onError(
- blink::WebSyncError(blink::WebSyncError::ErrorTypeUnknown,
- "No service worker is active."));
- break;
- }
-}
-
-void BackgroundSyncProvider::GetRegistrationCallback(
- scoped_ptr<blink::WebSyncRegistrationCallbacks> callbacks,
- BackgroundSyncError error,
- const SyncRegistrationPtr& options) {
- // TODO(iclelland): Determine the correct error message to return in each case
- scoped_ptr<blink::WebSyncRegistration> result;
- switch (error) {
- case BACKGROUND_SYNC_ERROR_NONE:
- if (!options.is_null())
- result =
- mojo::ConvertTo<scoped_ptr<blink::WebSyncRegistration>>(options);
- callbacks->onSuccess(blink::adoptWebPtr(result.release()));
- break;
- case BACKGROUND_SYNC_ERROR_NOT_FOUND:
- callbacks->onSuccess(nullptr);
- break;
- case BACKGROUND_SYNC_ERROR_STORAGE:
- callbacks->onError(
- blink::WebSyncError(blink::WebSyncError::ErrorTypeUnknown,
- "Background Sync is disabled."));
- break;
- case BACKGROUND_SYNC_ERROR_NOT_ALLOWED:
- // This error should never be returned from
- // BackgroundSyncManager::GetRegistration
- NOTREACHED();
- break;
- case BACKGROUND_SYNC_ERROR_NO_SERVICE_WORKER:
+ case mojom::BackgroundSyncError::NO_SERVICE_WORKER:
callbacks->onError(
blink::WebSyncError(blink::WebSyncError::ErrorTypeUnknown,
"No service worker is active."));
@@ -319,113 +170,36 @@ void BackgroundSyncProvider::GetRegistrationCallback(
}
void BackgroundSyncProvider::GetRegistrationsCallback(
- scoped_ptr<blink::WebSyncGetRegistrationsCallbacks> callbacks,
- BackgroundSyncError error,
- const mojo::Array<SyncRegistrationPtr>& registrations) {
+ std::unique_ptr<blink::WebSyncGetRegistrationsCallbacks> callbacks,
+ mojom::BackgroundSyncError error,
+ const mojo::Array<mojom::SyncRegistrationPtr>& registrations) {
// TODO(iclelland): Determine the correct error message to return in each case
switch (error) {
- case BACKGROUND_SYNC_ERROR_NONE: {
+ case mojom::BackgroundSyncError::NONE: {
blink::WebVector<blink::WebSyncRegistration*> results(
registrations.size());
for (size_t i = 0; i < registrations.size(); ++i) {
- results[i] = mojo::ConvertTo<scoped_ptr<blink::WebSyncRegistration>>(
- registrations[i])
- .release();
+ results[i] =
+ mojo::ConvertTo<std::unique_ptr<blink::WebSyncRegistration>>(
+ registrations[i])
+ .release();
}
callbacks->onSuccess(results);
break;
}
- case BACKGROUND_SYNC_ERROR_NOT_FOUND:
- case BACKGROUND_SYNC_ERROR_NOT_ALLOWED:
+ case mojom::BackgroundSyncError::NOT_FOUND:
+ case mojom::BackgroundSyncError::NOT_ALLOWED:
+ case mojom::BackgroundSyncError::PERMISSION_DENIED:
// These errors should never be returned from
// BackgroundSyncManager::GetRegistrations
NOTREACHED();
break;
- case BACKGROUND_SYNC_ERROR_STORAGE:
- callbacks->onError(
- blink::WebSyncError(blink::WebSyncError::ErrorTypeUnknown,
- "Background Sync is disabled."));
- break;
- case BACKGROUND_SYNC_ERROR_NO_SERVICE_WORKER:
- callbacks->onError(
- blink::WebSyncError(blink::WebSyncError::ErrorTypeUnknown,
- "No service worker is active."));
- break;
- }
-}
-
-void BackgroundSyncProvider::GetPermissionStatusCallback(
- scoped_ptr<blink::WebSyncGetPermissionStatusCallbacks> callbacks,
- BackgroundSyncError error,
- PermissionStatus status) {
- // TODO(iclelland): Determine the correct error message to return in each case
- switch (error) {
- case BACKGROUND_SYNC_ERROR_NONE:
- switch (status) {
- case PERMISSION_STATUS_GRANTED:
- callbacks->onSuccess(blink::WebSyncPermissionStatusGranted);
- break;
- case PERMISSION_STATUS_DENIED:
- callbacks->onSuccess(blink::WebSyncPermissionStatusDenied);
- break;
- case PERMISSION_STATUS_ASK:
- callbacks->onSuccess(blink::WebSyncPermissionStatusPrompt);
- break;
- }
- break;
- case BACKGROUND_SYNC_ERROR_NOT_FOUND:
- case BACKGROUND_SYNC_ERROR_NOT_ALLOWED:
- // These errors should never be returned from
- // BackgroundSyncManager::GetPermissionStatus
- NOTREACHED();
- break;
- case BACKGROUND_SYNC_ERROR_STORAGE:
- callbacks->onError(
- blink::WebSyncError(blink::WebSyncError::ErrorTypeUnknown,
- "Background Sync is disabled."));
- break;
- case BACKGROUND_SYNC_ERROR_NO_SERVICE_WORKER:
- callbacks->onError(
- blink::WebSyncError(blink::WebSyncError::ErrorTypeUnknown,
- "No service worker is active."));
- break;
- }
-}
-
-void BackgroundSyncProvider::NotifyWhenFinishedCallback(
- scoped_ptr<blink::WebSyncNotifyWhenFinishedCallbacks> callbacks,
- BackgroundSyncError error,
- BackgroundSyncState state) {
- switch (error) {
- case BACKGROUND_SYNC_ERROR_NONE:
- switch (state) {
- case BACKGROUND_SYNC_STATE_PENDING:
- case BACKGROUND_SYNC_STATE_FIRING:
- case BACKGROUND_SYNC_STATE_REREGISTERED_WHILE_FIRING:
- case BACKGROUND_SYNC_STATE_UNREGISTERED_WHILE_FIRING:
- NOTREACHED();
- break;
- case BACKGROUND_SYNC_STATE_SUCCESS:
- callbacks->onSuccess();
- break;
- case BACKGROUND_SYNC_STATE_FAILED:
- case BACKGROUND_SYNC_STATE_UNREGISTERED:
- callbacks->onError(blink::WebSyncError(
- blink::WebSyncError::ErrorTypeAbort,
- "Sync failed, unregistered, or overwritten."));
- break;
- }
- break;
- case BACKGROUND_SYNC_ERROR_NOT_FOUND:
- case BACKGROUND_SYNC_ERROR_NOT_ALLOWED:
- NOTREACHED();
- break;
- case BACKGROUND_SYNC_ERROR_STORAGE:
+ case mojom::BackgroundSyncError::STORAGE:
callbacks->onError(
blink::WebSyncError(blink::WebSyncError::ErrorTypeUnknown,
"Background Sync is disabled."));
break;
- case BACKGROUND_SYNC_ERROR_NO_SERVICE_WORKER:
+ case mojom::BackgroundSyncError::NO_SERVICE_WORKER:
callbacks->onError(
blink::WebSyncError(blink::WebSyncError::ErrorTypeUnknown,
"No service worker is active."));
@@ -433,10 +207,10 @@ void BackgroundSyncProvider::NotifyWhenFinishedCallback(
}
}
-BackgroundSyncServicePtr&
+mojom::BackgroundSyncServicePtr&
BackgroundSyncProvider::GetBackgroundSyncServicePtr() {
if (!background_sync_service_.get()) {
- mojo::InterfaceRequest<BackgroundSyncService> request =
+ mojo::InterfaceRequest<mojom::BackgroundSyncService> request =
mojo::GetProxy(&background_sync_service_);
main_thread_task_runner_->PostTask(
FROM_HERE,
diff --git a/chromium/content/child/background_sync/background_sync_provider.h b/chromium/content/child/background_sync/background_sync_provider.h
index 3d5aea289a6..cdfe270a903 100644
--- a/chromium/content/child/background_sync/background_sync_provider.h
+++ b/chromium/content/child/background_sync/background_sync_provider.h
@@ -7,10 +7,10 @@
#include <stdint.h>
+#include <memory>
#include <string>
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "content/common/background_sync_service.mojom.h"
#include "content/public/child/worker_thread.h"
#include "third_party/WebKit/public/platform/modules/background_sync/WebSyncProvider.h"
@@ -22,12 +22,12 @@ class SingleThreadTaskRunner;
namespace content {
// The BackgroundSyncProvider is called by the SyncManager and SyncRegistration
-// objects (and their Periodic counterparts) and communicates with the
-// BackgroundSyncManager object in the browser process. Each thread will have
-// its own instance (e.g. main thread, worker threads), instantiated as needed
-// by BlinkPlatformImpl. Each instance of the provider creates a new mojo
-// connection to a new BackgroundSyncManagerImpl, which then talks to the
-// BackgroundSyncManager object.
+// objects and communicates with the BackgroundSyncManager object in the browser
+// process. Each thread will have its own instance (e.g. main thread, worker
+// threads), instantiated as needed by BlinkPlatformImpl. Each instance of
+// the provider creates a new mojo connection to a new
+// BackgroundSyncManagerImpl, which then talks to the BackgroundSyncManager
+// object.
class BackgroundSyncProvider : public blink::WebSyncProvider,
public WorkerThread::Observer {
public:
@@ -48,35 +48,10 @@ class BackgroundSyncProvider : public blink::WebSyncProvider,
void registerBackgroundSync(
const blink::WebSyncRegistration* options,
blink::WebServiceWorkerRegistration* service_worker_registration,
- bool requested_from_service_worker,
- blink::WebSyncRegistrationCallbacks* callbacks) override;
- void unregisterBackgroundSync(
- int64_t handle_id,
- blink::WebServiceWorkerRegistration* service_worker_registration,
- blink::WebSyncUnregistrationCallbacks* callbacks) override;
- void getRegistration(
- blink::WebSyncRegistration::Periodicity,
- const blink::WebString& tag,
- blink::WebServiceWorkerRegistration* service_worker_registration,
blink::WebSyncRegistrationCallbacks* callbacks) override;
void getRegistrations(
- blink::WebSyncRegistration::Periodicity periodicity,
blink::WebServiceWorkerRegistration* service_worker_registration,
blink::WebSyncGetRegistrationsCallbacks* callbacks) override;
- void getPermissionStatus(
- blink::WebSyncRegistration::Periodicity periodicity,
- blink::WebServiceWorkerRegistration* service_worker_registration,
- blink::WebSyncGetPermissionStatusCallbacks* callbacks) override;
- // TODO(jkarlin): Rename to releaseRegistrationHandle.
- void releaseRegistration(int64_t handle_id) override;
- void notifyWhenFinished(
- int64_t handle_id,
- blink::WebSyncNotifyWhenFinishedCallbacks* callbacks) override;
-
- void DuplicateRegistrationHandle(
- int64_t handle_id,
- const BackgroundSyncService::DuplicateRegistrationHandleCallback&
- callback);
// WorkerThread::Observer implementation.
void WillStopCurrentWorkerThread() override;
@@ -84,33 +59,18 @@ class BackgroundSyncProvider : public blink::WebSyncProvider,
private:
// Callback handlers
void RegisterCallback(
- scoped_ptr<blink::WebSyncRegistrationCallbacks> callbacks,
- BackgroundSyncError error,
- const SyncRegistrationPtr& options);
- void UnregisterCallback(
- scoped_ptr<blink::WebSyncUnregistrationCallbacks> callbacks,
- BackgroundSyncError error);
- void GetRegistrationCallback(
- scoped_ptr<blink::WebSyncRegistrationCallbacks> callbacks,
- BackgroundSyncError error,
- const SyncRegistrationPtr& options);
+ std::unique_ptr<blink::WebSyncRegistrationCallbacks> callbacks,
+ mojom::BackgroundSyncError error,
+ const mojom::SyncRegistrationPtr& options);
void GetRegistrationsCallback(
- scoped_ptr<blink::WebSyncGetRegistrationsCallbacks> callbacks,
- BackgroundSyncError error,
- const mojo::Array<SyncRegistrationPtr>& registrations);
- void GetPermissionStatusCallback(
- scoped_ptr<blink::WebSyncGetPermissionStatusCallbacks> callbacks,
- BackgroundSyncError error,
- PermissionStatus status);
- void NotifyWhenFinishedCallback(
- scoped_ptr<blink::WebSyncNotifyWhenFinishedCallbacks> callbacks,
- BackgroundSyncError error,
- BackgroundSyncState state);
+ std::unique_ptr<blink::WebSyncGetRegistrationsCallbacks> callbacks,
+ mojom::BackgroundSyncError error,
+ const mojo::Array<mojom::SyncRegistrationPtr>& registrations);
// Helper method that returns an initialized BackgroundSyncServicePtr.
- BackgroundSyncServicePtr& GetBackgroundSyncServicePtr();
+ mojom::BackgroundSyncServicePtr& GetBackgroundSyncServicePtr();
- BackgroundSyncServicePtr background_sync_service_;
+ mojom::BackgroundSyncServicePtr background_sync_service_;
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
DISALLOW_COPY_AND_ASSIGN(BackgroundSyncProvider);
diff --git a/chromium/content/child/background_sync/background_sync_type_converters.cc b/chromium/content/child/background_sync/background_sync_type_converters.cc
index de459d26d92..c687da64ecd 100644
--- a/chromium/content/child/background_sync/background_sync_type_converters.cc
+++ b/chromium/content/child/background_sync/background_sync_type_converters.cc
@@ -13,139 +13,81 @@ namespace mojo {
static_cast<int>(blink::blink_name), \
"mojo and blink enums must match")
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_PERIODICITY_PERIODIC,
- WebSyncRegistration::PeriodicityPeriodic);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_PERIODICITY_ONE_SHOT,
- WebSyncRegistration::PeriodicityOneShot);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_PERIODICITY_MAX,
- WebSyncRegistration::PeriodicityOneShot);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_PERIODICITY_MAX,
- WebSyncRegistration::PeriodicityLast);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_NETWORK_STATE_ANY,
+COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncNetworkState::ANY,
WebSyncRegistration::NetworkStateAny);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_NETWORK_STATE_AVOID_CELLULAR,
+COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncNetworkState::AVOID_CELLULAR,
WebSyncRegistration::NetworkStateAvoidCellular);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_NETWORK_STATE_ONLINE,
+COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncNetworkState::ONLINE,
WebSyncRegistration::NetworkStateOnline);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_NETWORK_STATE_MAX,
+COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncNetworkState::MAX,
WebSyncRegistration::NetworkStateOnline);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_NETWORK_STATE_MAX,
+COMPILE_ASSERT_MATCHING_ENUM(mojom::BackgroundSyncNetworkState::MAX,
WebSyncRegistration::NetworkStateLast);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_POWER_STATE_AUTO,
- WebSyncRegistration::PowerStateAuto);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_POWER_STATE_AVOID_DRAINING,
- WebSyncRegistration::PowerStateAvoidDraining);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_POWER_STATE_MAX,
- WebSyncRegistration::PowerStateAvoidDraining);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_POWER_STATE_MAX,
- WebSyncRegistration::PowerStateLast);
COMPILE_ASSERT_MATCHING_ENUM(
- BACKGROUND_SYNC_EVENT_LAST_CHANCE_IS_NOT_LAST_CHANCE,
+ mojom::BackgroundSyncEventLastChance::IS_NOT_LAST_CHANCE,
WebServiceWorkerContextProxy::IsNotLastChance);
-COMPILE_ASSERT_MATCHING_ENUM(BACKGROUND_SYNC_EVENT_LAST_CHANCE_IS_LAST_CHANCE,
- WebServiceWorkerContextProxy::IsLastChance);
-
-// static
-blink::WebSyncRegistration::Periodicity
- TypeConverter<blink::WebSyncRegistration::Periodicity,
- content::BackgroundSyncPeriodicity>::Convert(
- content::BackgroundSyncPeriodicity input) {
- return static_cast<blink::WebSyncRegistration::Periodicity>(input);
-}
-
-// static
-content::BackgroundSyncPeriodicity
- TypeConverter<content::BackgroundSyncPeriodicity,
- blink::WebSyncRegistration::Periodicity>::Convert(
- blink::WebSyncRegistration::Periodicity input) {
- return static_cast<content::BackgroundSyncPeriodicity>(input);
-}
+COMPILE_ASSERT_MATCHING_ENUM(
+ mojom::BackgroundSyncEventLastChance::IS_LAST_CHANCE,
+ WebServiceWorkerContextProxy::IsLastChance);
// static
blink::WebSyncRegistration::NetworkState
- TypeConverter<blink::WebSyncRegistration::NetworkState,
- content::BackgroundSyncNetworkState>::Convert(
- content::BackgroundSyncNetworkState input) {
+TypeConverter<blink::WebSyncRegistration::NetworkState,
+ content::mojom::BackgroundSyncNetworkState>::
+ Convert(content::mojom::BackgroundSyncNetworkState input) {
return static_cast<blink::WebSyncRegistration::NetworkState>(input);
}
// static
-content::BackgroundSyncNetworkState
- TypeConverter<content::BackgroundSyncNetworkState,
- blink::WebSyncRegistration::NetworkState>::Convert(
- blink::WebSyncRegistration::NetworkState input) {
- return static_cast<content::BackgroundSyncNetworkState>(input);
-}
-
-// static
-blink::WebSyncRegistration::PowerState
- TypeConverter<blink::WebSyncRegistration::PowerState,
- content::BackgroundSyncPowerState>::Convert(
- content::BackgroundSyncPowerState input) {
- return static_cast<blink::WebSyncRegistration::PowerState>(input);
-}
-
-// static
-content::BackgroundSyncPowerState
- TypeConverter<content::BackgroundSyncPowerState,
- blink::WebSyncRegistration::PowerState>::Convert(
- blink::WebSyncRegistration::PowerState input) {
- return static_cast<content::BackgroundSyncPowerState>(input);
+content::mojom::BackgroundSyncNetworkState
+TypeConverter<content::mojom::BackgroundSyncNetworkState,
+ blink::WebSyncRegistration::NetworkState>::
+ Convert(blink::WebSyncRegistration::NetworkState input) {
+ return static_cast<content::mojom::BackgroundSyncNetworkState>(input);
}
// static
-scoped_ptr<blink::WebSyncRegistration> TypeConverter<
- scoped_ptr<blink::WebSyncRegistration>,
- content::SyncRegistrationPtr>::Convert(
- const content::SyncRegistrationPtr& input) {
- scoped_ptr<blink::WebSyncRegistration> result(
+std::unique_ptr<blink::WebSyncRegistration>
+TypeConverter<std::unique_ptr<blink::WebSyncRegistration>,
+ content::mojom::SyncRegistrationPtr>::
+ Convert(const content::mojom::SyncRegistrationPtr& input) {
+ std::unique_ptr<blink::WebSyncRegistration> result(
new blink::WebSyncRegistration());
- result->id = input->handle_id;
- result->periodicity =
- ConvertTo<blink::WebSyncRegistration::Periodicity>(input->periodicity);
+ result->id = input->id;
result->tag = blink::WebString::fromUTF8(input->tag);
- result->minPeriodMs = input->min_period_ms;
result->networkState =
ConvertTo<blink::WebSyncRegistration::NetworkState>(input->network_state);
- result->powerState =
- ConvertTo<blink::WebSyncRegistration::PowerState>(input->power_state);
return result;
}
// static
-content::SyncRegistrationPtr TypeConverter<
- content::SyncRegistrationPtr,
- blink::WebSyncRegistration>::Convert(
- const blink::WebSyncRegistration& input) {
- content::SyncRegistrationPtr result(
- content::SyncRegistration::New());
- result->handle_id = input.id;
- result->periodicity =
- ConvertTo<content::BackgroundSyncPeriodicity>(input.periodicity);
+content::mojom::SyncRegistrationPtr
+TypeConverter<content::mojom::SyncRegistrationPtr, blink::WebSyncRegistration>::
+ Convert(const blink::WebSyncRegistration& input) {
+ content::mojom::SyncRegistrationPtr result(
+ content::mojom::SyncRegistration::New());
+ result->id = input.id;
result->tag = input.tag.utf8();
- result->min_period_ms = input.minPeriodMs;
result->network_state =
- ConvertTo<content::BackgroundSyncNetworkState>(input.networkState);
- result->power_state =
- ConvertTo<content::BackgroundSyncPowerState>(input.powerState);
+ ConvertTo<content::mojom::BackgroundSyncNetworkState>(input.networkState);
return result;
}
// static
blink::WebServiceWorkerContextProxy::LastChanceOption
TypeConverter<blink::WebServiceWorkerContextProxy::LastChanceOption,
- content::BackgroundSyncEventLastChance>::
- Convert(content::BackgroundSyncEventLastChance input) {
+ content::mojom::BackgroundSyncEventLastChance>::
+ Convert(content::mojom::BackgroundSyncEventLastChance input) {
return static_cast<blink::WebServiceWorkerContextProxy::LastChanceOption>(
input);
}
// static
-content::BackgroundSyncEventLastChance
-TypeConverter<content::BackgroundSyncEventLastChance,
+content::mojom::BackgroundSyncEventLastChance
+TypeConverter<content::mojom::BackgroundSyncEventLastChance,
blink::WebServiceWorkerContextProxy::LastChanceOption>::
Convert(blink::WebServiceWorkerContextProxy::LastChanceOption input) {
- return static_cast<content::BackgroundSyncEventLastChance>(input);
+ return static_cast<content::mojom::BackgroundSyncEventLastChance>(input);
}
} // namespace mojo
diff --git a/chromium/content/child/background_sync/background_sync_type_converters.h b/chromium/content/child/background_sync/background_sync_type_converters.h
index 0cf12a1eca0..fc9f59a8622 100644
--- a/chromium/content/child/background_sync/background_sync_type_converters.h
+++ b/chromium/content/child/background_sync/background_sync_type_converters.h
@@ -5,7 +5,8 @@
#ifndef CONTENT_CHILD_BACKGROUND_SYNC_BACKGROUND_SYNC_TYPE_CONVERTERS_H_
#define CONTENT_CHILD_BACKGROUND_SYNC_BACKGROUND_SYNC_TYPE_CONVERTERS_H_
-#include "base/memory/scoped_ptr.h"
+#include <memory>
+
#include "content/common/background_sync_service.mojom.h"
#include "content/common/content_export.h"
#include "mojo/public/cpp/bindings/type_converter.h"
@@ -15,90 +16,57 @@
namespace mojo {
-// blink::WebSyngRegistration::Periodicity <=>
-// content::BackgroundSyncPeriodicity
-
-template <>
-struct CONTENT_EXPORT TypeConverter<blink::WebSyncRegistration::Periodicity,
- content::BackgroundSyncPeriodicity> {
- static blink::WebSyncRegistration::Periodicity Convert(
- content::BackgroundSyncPeriodicity input);
-};
-
-template <>
-struct CONTENT_EXPORT TypeConverter<content::BackgroundSyncPeriodicity,
- blink::WebSyncRegistration::Periodicity> {
- static content::BackgroundSyncPeriodicity Convert(
- blink::WebSyncRegistration::Periodicity input);
-};
-
// blink::WebSyncRegistration::NetworkState <=>
-// content::BackgroundSyncNetworkState
+// content::mojom::BackgroundSyncNetworkState
template <>
-struct CONTENT_EXPORT TypeConverter<blink::WebSyncRegistration::NetworkState,
- content::BackgroundSyncNetworkState> {
+struct CONTENT_EXPORT
+ TypeConverter<blink::WebSyncRegistration::NetworkState,
+ content::mojom::BackgroundSyncNetworkState> {
static blink::WebSyncRegistration::NetworkState Convert(
- content::BackgroundSyncNetworkState input);
+ content::mojom::BackgroundSyncNetworkState input);
};
template <>
-struct CONTENT_EXPORT TypeConverter<content::BackgroundSyncNetworkState,
- blink::WebSyncRegistration::NetworkState> {
- static content::BackgroundSyncNetworkState Convert(
+struct CONTENT_EXPORT TypeConverter<content::mojom::BackgroundSyncNetworkState,
+ blink::WebSyncRegistration::NetworkState> {
+ static content::mojom::BackgroundSyncNetworkState Convert(
blink::WebSyncRegistration::NetworkState input);
};
-// blink::WebSyncRegistration::PowerState <=>
-// content::BackgroundSyncPowerState
-
-template <>
-struct CONTENT_EXPORT TypeConverter<blink::WebSyncRegistration::PowerState,
- content::BackgroundSyncPowerState> {
- static blink::WebSyncRegistration::PowerState Convert(
- content::BackgroundSyncPowerState input);
-};
-
-template <>
-struct CONTENT_EXPORT TypeConverter<content::BackgroundSyncPowerState,
- blink::WebSyncRegistration::PowerState> {
- static content::BackgroundSyncPowerState Convert(
- blink::WebSyncRegistration::PowerState input);
-};
-
// blink::WebSyncRegistration <=>
-// content::SyncRegistration
+// content::mojom::SyncRegistration
template <>
-struct CONTENT_EXPORT TypeConverter<scoped_ptr<blink::WebSyncRegistration>,
- content::SyncRegistrationPtr> {
- static scoped_ptr<blink::WebSyncRegistration> Convert(
- const content::SyncRegistrationPtr& input);
+struct CONTENT_EXPORT TypeConverter<std::unique_ptr<blink::WebSyncRegistration>,
+ content::mojom::SyncRegistrationPtr> {
+ static std::unique_ptr<blink::WebSyncRegistration> Convert(
+ const content::mojom::SyncRegistrationPtr& input);
};
template <>
-struct CONTENT_EXPORT TypeConverter<content::SyncRegistrationPtr,
- blink::WebSyncRegistration> {
- static content::SyncRegistrationPtr Convert(
+struct CONTENT_EXPORT TypeConverter<content::mojom::SyncRegistrationPtr,
+ blink::WebSyncRegistration> {
+ static content::mojom::SyncRegistrationPtr Convert(
const blink::WebSyncRegistration& input);
};
// blink::WebServiceWorkerContextProxy::LastChanceOption <=>
-// content::BackgroundSyncEventLastChance
+// content::mojom::BackgroundSyncEventLastChance
template <>
struct CONTENT_EXPORT
TypeConverter<blink::WebServiceWorkerContextProxy::LastChanceOption,
- content::BackgroundSyncEventLastChance> {
+ content::mojom::BackgroundSyncEventLastChance> {
static blink::WebServiceWorkerContextProxy::LastChanceOption Convert(
- content::BackgroundSyncEventLastChance input);
+ content::mojom::BackgroundSyncEventLastChance input);
};
template <>
struct CONTENT_EXPORT
- TypeConverter<content::BackgroundSyncEventLastChance,
+ TypeConverter<content::mojom::BackgroundSyncEventLastChance,
blink::WebServiceWorkerContextProxy::LastChanceOption> {
- static content::BackgroundSyncEventLastChance Convert(
+ static content::mojom::BackgroundSyncEventLastChance Convert(
blink::WebServiceWorkerContextProxy::LastChanceOption input);
};
diff --git a/chromium/content/child/background_sync/background_sync_type_converters_unittest.cc b/chromium/content/child/background_sync/background_sync_type_converters_unittest.cc
index 89b192526e3..15270478f50 100644
--- a/chromium/content/child/background_sync/background_sync_type_converters_unittest.cc
+++ b/chromium/content/child/background_sync/background_sync_type_converters_unittest.cc
@@ -1,3 +1,4 @@
+
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -9,171 +10,78 @@
namespace mojo {
namespace {
-TEST(BackgroundSyncTypeConverterTest, TestBlinkToMojoPeriodicityConversions) {
- ASSERT_EQ(blink::WebSyncRegistration::PeriodicityPeriodic,
- ConvertTo<blink::WebSyncRegistration::Periodicity>(
- content::BACKGROUND_SYNC_PERIODICITY_PERIODIC));
- ASSERT_EQ(blink::WebSyncRegistration::PeriodicityOneShot,
- ConvertTo<blink::WebSyncRegistration::Periodicity>(
- content::BACKGROUND_SYNC_PERIODICITY_ONE_SHOT));
-}
-
-TEST(BackgroundSyncTypeConverterTest, TestMojoToBlinkPeriodicityConversions) {
- ASSERT_EQ(content::BACKGROUND_SYNC_PERIODICITY_PERIODIC,
- ConvertTo<content::BackgroundSyncPeriodicity>(
- blink::WebSyncRegistration::PeriodicityPeriodic));
- ASSERT_EQ(content::BACKGROUND_SYNC_PERIODICITY_ONE_SHOT,
- ConvertTo<content::BackgroundSyncPeriodicity>(
- blink::WebSyncRegistration::PeriodicityOneShot));
-}
-
TEST(BackgroundSyncTypeConverterTest, TestBlinkToMojoNetworkStateConversions) {
ASSERT_EQ(blink::WebSyncRegistration::NetworkStateAny,
- ConvertTo<blink::WebSyncRegistration::NetworkState>(
- content::BACKGROUND_SYNC_NETWORK_STATE_ANY));
+ ConvertTo<blink::WebSyncRegistration::NetworkState>(
+ content::mojom::BackgroundSyncNetworkState::ANY));
ASSERT_EQ(blink::WebSyncRegistration::NetworkStateAvoidCellular,
- ConvertTo<blink::WebSyncRegistration::NetworkState>(
- content::BACKGROUND_SYNC_NETWORK_STATE_AVOID_CELLULAR));
+ ConvertTo<blink::WebSyncRegistration::NetworkState>(
+ content::mojom::BackgroundSyncNetworkState::AVOID_CELLULAR));
ASSERT_EQ(blink::WebSyncRegistration::NetworkStateOnline,
- ConvertTo<blink::WebSyncRegistration::NetworkState>(
- content::BACKGROUND_SYNC_NETWORK_STATE_ONLINE));
+ ConvertTo<blink::WebSyncRegistration::NetworkState>(
+ content::mojom::BackgroundSyncNetworkState::ONLINE));
}
TEST(BackgroundSyncTypeConverterTest, TestMojoToBlinkNetworkStateConversions) {
- ASSERT_EQ(content::BACKGROUND_SYNC_NETWORK_STATE_ANY,
- ConvertTo<content::BackgroundSyncNetworkState>(
- blink::WebSyncRegistration::NetworkStateAny));
- ASSERT_EQ(content::BACKGROUND_SYNC_NETWORK_STATE_AVOID_CELLULAR,
- ConvertTo<content::BackgroundSyncNetworkState>(
- blink::WebSyncRegistration::NetworkStateAvoidCellular));
- ASSERT_EQ(content::BACKGROUND_SYNC_NETWORK_STATE_ONLINE,
- ConvertTo<content::BackgroundSyncNetworkState>(
- blink::WebSyncRegistration::NetworkStateOnline));
-}
-
-TEST(BackgroundSyncTypeConverterTest, TestBlinkToMojoPowerStateConversions) {
- ASSERT_EQ(blink::WebSyncRegistration::PowerStateAuto,
- ConvertTo<blink::WebSyncRegistration::PowerState>(
- content::BACKGROUND_SYNC_POWER_STATE_AUTO));
- ASSERT_EQ(blink::WebSyncRegistration::PowerStateAvoidDraining,
- ConvertTo<blink::WebSyncRegistration::PowerState>(
- content::BACKGROUND_SYNC_POWER_STATE_AVOID_DRAINING));
-}
-
-TEST(BackgroundSyncTypeConverterTest, TestMojoToBlinkPowerStateConversions) {
- ASSERT_EQ(content::BACKGROUND_SYNC_POWER_STATE_AUTO,
- ConvertTo<content::BackgroundSyncPowerState>(
- blink::WebSyncRegistration::PowerStateAuto));
- ASSERT_EQ(content::BACKGROUND_SYNC_POWER_STATE_AVOID_DRAINING,
- ConvertTo<content::BackgroundSyncPowerState>(
- blink::WebSyncRegistration::PowerStateAvoidDraining));
+ ASSERT_EQ(content::mojom::BackgroundSyncNetworkState::ANY,
+ ConvertTo<content::mojom::BackgroundSyncNetworkState>(
+ blink::WebSyncRegistration::NetworkStateAny));
+ ASSERT_EQ(content::mojom::BackgroundSyncNetworkState::AVOID_CELLULAR,
+ ConvertTo<content::mojom::BackgroundSyncNetworkState>(
+ blink::WebSyncRegistration::NetworkStateAvoidCellular));
+ ASSERT_EQ(content::mojom::BackgroundSyncNetworkState::ONLINE,
+ ConvertTo<content::mojom::BackgroundSyncNetworkState>(
+ blink::WebSyncRegistration::NetworkStateOnline));
}
TEST(BackgroundSyncTypeConverterTest, TestDefaultBlinkToMojoConversion) {
blink::WebSyncRegistration in;
- content::SyncRegistrationPtr out =
- ConvertTo<content::SyncRegistrationPtr>(in);
+ content::mojom::SyncRegistrationPtr out =
+ ConvertTo<content::mojom::SyncRegistrationPtr>(in);
- ASSERT_EQ(blink::WebSyncRegistration::UNREGISTERED_SYNC_ID, out->handle_id);
- ASSERT_EQ(content::BACKGROUND_SYNC_PERIODICITY_ONE_SHOT, out->periodicity);
+ ASSERT_EQ(blink::WebSyncRegistration::UNREGISTERED_SYNC_ID, out->id);
ASSERT_EQ("", out->tag);
- ASSERT_EQ(0UL, out->min_period_ms);
- ASSERT_EQ(content::BACKGROUND_SYNC_NETWORK_STATE_ONLINE, out->network_state);
- ASSERT_EQ(content::BACKGROUND_SYNC_POWER_STATE_AUTO, out->power_state);
-}
-
-TEST(BackgroundSyncTypeConverterTest, TestFullPeriodicBlinkToMojoConversion) {
- blink::WebSyncRegistration in(
- 7, blink::WebSyncRegistration::PeriodicityPeriodic, "BlinkToMojo",
- 12340000, blink::WebSyncRegistration::NetworkStateAvoidCellular,
- blink::WebSyncRegistration::PowerStateAvoidDraining);
- content::SyncRegistrationPtr out =
- ConvertTo<content::SyncRegistrationPtr>(in);
-
- ASSERT_EQ(7, out->handle_id);
- ASSERT_EQ(content::BACKGROUND_SYNC_PERIODICITY_PERIODIC, out->periodicity);
- ASSERT_EQ("BlinkToMojo", out->tag);
- ASSERT_EQ(12340000UL, out->min_period_ms);
- ASSERT_EQ(content::BACKGROUND_SYNC_NETWORK_STATE_AVOID_CELLULAR,
+ ASSERT_EQ(content::mojom::BackgroundSyncNetworkState::ONLINE,
out->network_state);
- ASSERT_EQ(content::BACKGROUND_SYNC_POWER_STATE_AVOID_DRAINING,
- out->power_state);
}
-TEST(BackgroundSyncTypeConverterTest, TestFullOneShotBlinkToMojoConversion) {
+TEST(BackgroundSyncTypeConverterTest, TestFullBlinkToMojoConversion) {
blink::WebSyncRegistration in(
- 7, blink::WebSyncRegistration::PeriodicityOneShot, "BlinkToMojo",
- 12340000, blink::WebSyncRegistration::NetworkStateAvoidCellular,
- blink::WebSyncRegistration::PowerStateAvoidDraining);
- content::SyncRegistrationPtr out =
- ConvertTo<content::SyncRegistrationPtr>(in);
-
- ASSERT_EQ(7, out->handle_id);
- ASSERT_EQ(content::BACKGROUND_SYNC_PERIODICITY_ONE_SHOT, out->periodicity);
+ 7, "BlinkToMojo", blink::WebSyncRegistration::NetworkStateAvoidCellular);
+ content::mojom::SyncRegistrationPtr out =
+ ConvertTo<content::mojom::SyncRegistrationPtr>(in);
+
+ ASSERT_EQ(7, out->id);
ASSERT_EQ("BlinkToMojo", out->tag);
- ASSERT_EQ(12340000UL, out->min_period_ms);
- ASSERT_EQ(content::BACKGROUND_SYNC_NETWORK_STATE_AVOID_CELLULAR,
+ ASSERT_EQ(content::mojom::BackgroundSyncNetworkState::AVOID_CELLULAR,
out->network_state);
- ASSERT_EQ(content::BACKGROUND_SYNC_POWER_STATE_AVOID_DRAINING,
- out->power_state);
}
TEST(BackgroundSyncTypeConverterTest, TestDefaultMojoToBlinkConversion) {
- content::SyncRegistrationPtr in(
- content::SyncRegistration::New());
- scoped_ptr<blink::WebSyncRegistration> out =
- ConvertTo<scoped_ptr<blink::WebSyncRegistration>>(in);
+ content::mojom::SyncRegistrationPtr in(
+ content::mojom::SyncRegistration::New());
+ std::unique_ptr<blink::WebSyncRegistration> out =
+ ConvertTo<std::unique_ptr<blink::WebSyncRegistration>>(in);
ASSERT_EQ(blink::WebSyncRegistration::UNREGISTERED_SYNC_ID, out->id);
- ASSERT_EQ(blink::WebSyncRegistration::PeriodicityOneShot, out->periodicity);
ASSERT_EQ("",out->tag);
- ASSERT_EQ(0UL, out->minPeriodMs);
ASSERT_EQ(blink::WebSyncRegistration::NetworkStateOnline, out->networkState);
- ASSERT_EQ(blink::WebSyncRegistration::PowerStateAuto, out->powerState);
-}
-
-TEST(BackgroundSyncTypeConverterTest, TestFullPeriodicMojoToBlinkConversion) {
- content::SyncRegistrationPtr in(
- content::SyncRegistration::New());
- in->handle_id = 41;
- in->periodicity = content::BACKGROUND_SYNC_PERIODICITY_PERIODIC;
- in->tag = mojo::String("MojoToBlink");
- in->min_period_ms = 43210000;
- in->network_state = content::BACKGROUND_SYNC_NETWORK_STATE_AVOID_CELLULAR;
- in->power_state = content::BACKGROUND_SYNC_POWER_STATE_AVOID_DRAINING;
- scoped_ptr<blink::WebSyncRegistration> out =
- ConvertTo<scoped_ptr<blink::WebSyncRegistration>>(in);
-
- ASSERT_EQ(41, out->id);
- ASSERT_EQ(blink::WebSyncRegistration::PeriodicityPeriodic, out->periodicity);
- ASSERT_EQ("MojoToBlink", out->tag.utf8());
- ASSERT_EQ(43210000UL, out->minPeriodMs);
- ASSERT_EQ(blink::WebSyncRegistration::NetworkStateAvoidCellular,
- out->networkState);
- ASSERT_EQ(blink::WebSyncRegistration::PowerStateAvoidDraining,
- out->powerState);
}
-TEST(BackgroundSyncTypeConverterTest, TestFullOneShotMojoToBlinkConversion) {
- content::SyncRegistrationPtr in(
- content::SyncRegistration::New());
- in->handle_id = 41;
- in->periodicity = content::BACKGROUND_SYNC_PERIODICITY_ONE_SHOT;
+TEST(BackgroundSyncTypeConverterTest, TestFullMojoToBlinkConversion) {
+ content::mojom::SyncRegistrationPtr in(
+ content::mojom::SyncRegistration::New());
+ in->id = 41;
in->tag = mojo::String("MojoToBlink");
- in->min_period_ms = 43210000;
- in->network_state = content::BACKGROUND_SYNC_NETWORK_STATE_AVOID_CELLULAR;
- in->power_state = content::BACKGROUND_SYNC_POWER_STATE_AVOID_DRAINING;
- scoped_ptr<blink::WebSyncRegistration> out =
- ConvertTo<scoped_ptr<blink::WebSyncRegistration>>(in);
+ in->network_state =
+ content::mojom::BackgroundSyncNetworkState::AVOID_CELLULAR;
+ std::unique_ptr<blink::WebSyncRegistration> out =
+ ConvertTo<std::unique_ptr<blink::WebSyncRegistration>>(in);
ASSERT_EQ(41, out->id);
- ASSERT_EQ(blink::WebSyncRegistration::PeriodicityOneShot, out->periodicity);
ASSERT_EQ("MojoToBlink", out->tag.utf8());
- ASSERT_EQ(43210000UL, out->minPeriodMs);
ASSERT_EQ(blink::WebSyncRegistration::NetworkStateAvoidCellular,
out->networkState);
- ASSERT_EQ(blink::WebSyncRegistration::PowerStateAvoidDraining,
- out->powerState);
}
} // anonymous namespace
diff --git a/chromium/content/child/blink_platform_impl.cc b/chromium/content/child/blink_platform_impl.cc
index 0b7f0a7237b..8c973f7693c 100644
--- a/chromium/content/child/blink_platform_impl.cc
+++ b/chromium/content/child/blink_platform_impl.cc
@@ -6,16 +6,16 @@
#include <math.h>
+#include <memory>
#include <vector>
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/location.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
+#include "base/memory/ptr_util.h"
#include "base/memory/singleton.h"
-#include "base/metrics/histogram.h"
-#include "base/metrics/sparse_histogram.h"
+#include "base/metrics/user_metrics_action.h"
#include "base/rand_util.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
@@ -43,7 +43,6 @@
#include "content/child/child_thread_impl.h"
#include "content/child/content_child_helpers.h"
#include "content/child/geofencing/web_geofencing_provider_impl.h"
-#include "content/child/navigator_connect/service_port_provider.h"
#include "content/child/notifications/notification_dispatcher.h"
#include "content/child/notifications/notification_manager.h"
#include "content/child/permissions/permission_dispatcher.h"
@@ -51,26 +50,21 @@
#include "content/child/push_messaging/push_dispatcher.h"
#include "content/child/push_messaging/push_provider.h"
#include "content/child/thread_safe_sender.h"
-#include "content/child/web_discardable_memory_impl.h"
-#include "content/child/web_memory_dump_provider_adapter.h"
-#include "content/child/web_process_memory_dump_impl.h"
#include "content/child/web_url_loader_impl.h"
#include "content/child/web_url_request_util.h"
#include "content/child/websocket_bridge.h"
#include "content/child/worker_thread_registry.h"
#include "content/public/common/content_client.h"
#include "net/base/data_url.h"
-#include "net/base/ip_address_number.h"
+#include "net/base/ip_address.h"
#include "net/base/net_errors.h"
#include "net/base/port_util.h"
-#include "third_party/WebKit/public/platform/WebConvertableToTraceFormat.h"
#include "third_party/WebKit/public/platform/WebData.h"
#include "third_party/WebKit/public/platform/WebFloatPoint.h"
#include "third_party/WebKit/public/platform/WebMemoryDumpProvider.h"
+#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h"
-#include "third_party/WebKit/public/platform/WebWaitableEvent.h"
-#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
#include "ui/base/layout.h"
#include "ui/events/gestures/blink/web_gesture_curve_impl.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
@@ -89,94 +83,6 @@ namespace content {
namespace {
-class WebWaitableEventImpl : public blink::WebWaitableEvent {
- public:
- WebWaitableEventImpl(ResetPolicy policy, InitialState state) {
- bool manual_reset = policy == ResetPolicy::Manual;
- bool initially_signaled = state == InitialState::Signaled;
- impl_.reset(new base::WaitableEvent(manual_reset, initially_signaled));
- }
- ~WebWaitableEventImpl() override {}
-
- void reset() override { impl_->Reset(); }
- void wait() override { impl_->Wait(); }
- void signal() override { impl_->Signal(); }
-
- base::WaitableEvent* impl() {
- return impl_.get();
- }
-
- private:
- scoped_ptr<base::WaitableEvent> impl_;
- DISALLOW_COPY_AND_ASSIGN(WebWaitableEventImpl);
-};
-
-// A simple class to cache the memory usage for a given amount of time.
-class MemoryUsageCache {
- public:
- // Retrieves the Singleton.
- static MemoryUsageCache* GetInstance() {
- return base::Singleton<MemoryUsageCache>::get();
- }
-
- MemoryUsageCache() : memory_value_(0) { Init(); }
- ~MemoryUsageCache() {}
-
- void Init() {
- const unsigned int kCacheSeconds = 1;
- cache_valid_time_ = base::TimeDelta::FromSeconds(kCacheSeconds);
- }
-
- // Returns true if the cached value is fresh.
- // Returns false if the cached value is stale, or if |cached_value| is NULL.
- bool IsCachedValueValid(size_t* cached_value) {
- base::AutoLock scoped_lock(lock_);
- if (!cached_value)
- return false;
- if (base::Time::Now() - last_updated_time_ > cache_valid_time_)
- return false;
- *cached_value = memory_value_;
- return true;
- };
-
- // Setter for |memory_value_|, refreshes |last_updated_time_|.
- void SetMemoryValue(const size_t value) {
- base::AutoLock scoped_lock(lock_);
- memory_value_ = value;
- last_updated_time_ = base::Time::Now();
- }
-
- private:
- // The cached memory value.
- size_t memory_value_;
-
- // How long the cached value should remain valid.
- base::TimeDelta cache_valid_time_;
-
- // The last time the cached value was updated.
- base::Time last_updated_time_;
-
- base::Lock lock_;
-};
-
-class ConvertableToTraceFormatWrapper
- : public base::trace_event::ConvertableToTraceFormat {
- public:
- // We move a reference pointer from |convertable| to |convertable_|,
- // rather than copying, for thread safety. https://crbug.com/478149
- explicit ConvertableToTraceFormatWrapper(
- blink::WebConvertableToTraceFormat& convertable) {
- convertable_.moveFrom(convertable);
- }
- void AppendAsTraceFormat(std::string* out) const override {
- *out += convertable_.asTraceFormat().utf8();
- }
-
- private:
- ~ConvertableToTraceFormatWrapper() override {}
-
- blink::WebConvertableToTraceFormat convertable_;
-};
} // namespace
@@ -200,6 +106,8 @@ static int ToMessageID(WebLocalizedString::Name name) {
return IDS_AX_DATE_TIME_FIELD_EMPTY_VALUE_TEXT;
case WebLocalizedString::AXDayOfMonthFieldText:
return IDS_AX_DAY_OF_MONTH_FIELD_TEXT;
+ case WebLocalizedString::AXDefaultActionVerb:
+ return IDS_AX_DEFAULT_ACTION_VERB;
case WebLocalizedString::AXHeadingText:
return IDS_AX_ROLE_HEADING;
case WebLocalizedString::AXHourFieldText:
@@ -290,6 +198,8 @@ static int ToMessageID(WebLocalizedString::Name name) {
return IDS_AX_MINUTE_FIELD_TEXT;
case WebLocalizedString::AXMonthFieldText:
return IDS_AX_MONTH_FIELD_TEXT;
+ case WebLocalizedString::AXPopUpButtonActionVerb:
+ return IDS_AX_POP_UP_BUTTON_ACTION_VERB;
case WebLocalizedString::AXRadioButtonActionVerb:
return IDS_AX_RADIO_BUTTON_ACTION_VERB;
case WebLocalizedString::AXSecondFieldText:
@@ -316,6 +226,8 @@ static int ToMessageID(WebLocalizedString::Name name) {
return IDS_FORM_DATE_FORMAT_YEAR;
case WebLocalizedString::DetailsLabel:
return IDS_DETAILS_WITHOUT_SUMMARY_LABEL;
+ case WebLocalizedString::DownloadButtonLabel:
+ return IDS_DOWNLOAD_BUTTON_LABEL;
case WebLocalizedString::FileButtonChooseFileLabel:
return IDS_FORM_FILE_BUTTON_LABEL;
case WebLocalizedString::FileButtonChooseMultipleFilesLabel:
@@ -486,7 +398,7 @@ void BlinkPlatformImpl::InternalInit() {
void BlinkPlatformImpl::WaitUntilWebThreadTLSUpdate(
scheduler::WebThreadBase* thread) {
base::WaitableEvent event(false, false);
- thread->TaskRunner()->PostTask(
+ thread->GetTaskRunner()->PostTask(
FROM_HERE,
base::Bind(&BlinkPlatformImpl::UpdateWebThreadTLS, base::Unretained(this),
base::Unretained(thread), base::Unretained(&event)));
@@ -509,8 +421,7 @@ WebURLLoader* BlinkPlatformImpl::createURLLoader() {
// data URLs to bypass the ResourceDispatcher.
return new WebURLLoaderImpl(
child_thread ? child_thread->resource_dispatcher() : NULL,
- make_scoped_ptr(new scheduler::WebTaskRunnerImpl(
- base::ThreadTaskRunnerHandle::Get())));
+ base::WrapUnique(currentThread()->getWebTaskRunner()->clone()));
}
blink::WebSocketHandle* BlinkPlatformImpl::createWebSocketHandle() {
@@ -518,12 +429,7 @@ blink::WebSocketHandle* BlinkPlatformImpl::createWebSocketHandle() {
}
WebString BlinkPlatformImpl::userAgent() {
- CR_DEFINE_STATIC_LOCAL(
- blink::WebString, user_agent,
- (blink::WebString::fromUTF8(GetContentClient()->GetUserAgent())));
- DCHECK(user_agent ==
- blink::WebString::fromUTF8(GetContentClient()->GetUserAgent()));
- return user_agent;
+ return blink::WebString::fromUTF8(GetContentClient()->GetUserAgent());
}
WebData BlinkPlatformImpl::parseDataURL(const WebURL& url,
@@ -546,10 +452,10 @@ WebURLError BlinkPlatformImpl::cancelledError(
bool BlinkPlatformImpl::isReservedIPAddress(
const blink::WebString& host) const {
- net::IPAddressNumber address;
- if (!net::ParseURLHostnameToNumber(host.utf8(), &address))
+ net::IPAddress address;
+ if (!net::ParseURLHostnameToAddress(host.utf8(), &address))
return false;
- return net::IsIPAddressReserved(address);
+ return address.IsReserved();
}
bool BlinkPlatformImpl::portAllowed(const blink::WebURL& url) const {
@@ -561,8 +467,17 @@ bool BlinkPlatformImpl::portAllowed(const blink::WebURL& url) const {
return net::IsPortAllowedForScheme(gurl.EffectiveIntPort(), gurl.scheme());
}
+bool BlinkPlatformImpl::parseMultipartHeadersFromBody(
+ const char* bytes,
+ size_t size,
+ blink::WebURLResponse* response,
+ size_t* end) const {
+ return WebURLLoaderImpl::ParseMultipartHeadersFromBody(
+ bytes, size, response, end);
+}
+
blink::WebThread* BlinkPlatformImpl::createThread(const char* name) {
- scoped_ptr<WebThreadImplForWorkerScheduler> thread(
+ std::unique_ptr<WebThreadImplForWorkerScheduler> thread(
new WebThreadImplForWorkerScheduler(name));
thread->Init();
WaitUntilWebThreadTLSUpdate(thread.get());
@@ -580,161 +495,9 @@ blink::WebThread* BlinkPlatformImpl::currentThread() {
return static_cast<blink::WebThread*>(current_thread_slot_.Get());
}
-void BlinkPlatformImpl::yieldCurrentThread() {
- base::PlatformThread::YieldCurrentThread();
-}
-
-blink::WebWaitableEvent* BlinkPlatformImpl::createWaitableEvent(
- blink::WebWaitableEvent::ResetPolicy policy,
- blink::WebWaitableEvent::InitialState state) {
- return new WebWaitableEventImpl(policy, state);
-}
-
-blink::WebWaitableEvent* BlinkPlatformImpl::waitMultipleEvents(
- const blink::WebVector<blink::WebWaitableEvent*>& web_events) {
- std::vector<base::WaitableEvent*> events;
- for (size_t i = 0; i < web_events.size(); ++i)
- events.push_back(static_cast<WebWaitableEventImpl*>(web_events[i])->impl());
- size_t idx = base::WaitableEvent::WaitMany(events.data(), events.size());
- DCHECK_LT(idx, web_events.size());
- return web_events[idx];
-}
-
-void BlinkPlatformImpl::decrementStatsCounter(const char* name) {
-}
-
-void BlinkPlatformImpl::incrementStatsCounter(const char* name) {
-}
-
-void BlinkPlatformImpl::histogramCustomCounts(
- const char* name, int sample, int min, int max, int bucket_count) {
- // Copied from histogram macro, but without the static variable caching
- // the histogram because name is dynamic.
- base::HistogramBase* counter =
- base::Histogram::FactoryGet(name, min, max, bucket_count,
- base::HistogramBase::kUmaTargetedHistogramFlag);
- DCHECK_EQ(name, counter->histogram_name());
- counter->Add(sample);
-}
-
-void BlinkPlatformImpl::histogramEnumeration(
- const char* name, int sample, int boundary_value) {
- // Copied from histogram macro, but without the static variable caching
- // the histogram because name is dynamic.
- base::HistogramBase* counter =
- base::LinearHistogram::FactoryGet(name, 1, boundary_value,
- boundary_value + 1, base::HistogramBase::kUmaTargetedHistogramFlag);
- DCHECK_EQ(name, counter->histogram_name());
- counter->Add(sample);
-}
-
-void BlinkPlatformImpl::histogramSparse(const char* name, int sample) {
- // For sparse histograms, we can use the macro, as it does not incorporate a
- // static.
- UMA_HISTOGRAM_SPARSE_SLOWLY(name, sample);
-}
-
-const unsigned char* BlinkPlatformImpl::getTraceCategoryEnabledFlag(
- const char* category_group) {
- return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group);
-}
-
-blink::Platform::TraceEventAPIAtomicWord*
-BlinkPlatformImpl::getTraceSamplingState(const unsigned thread_bucket) {
- switch (thread_bucket) {
- case 0:
- return reinterpret_cast<blink::Platform::TraceEventAPIAtomicWord*>(
- &TRACE_EVENT_API_THREAD_BUCKET(0));
- case 1:
- return reinterpret_cast<blink::Platform::TraceEventAPIAtomicWord*>(
- &TRACE_EVENT_API_THREAD_BUCKET(1));
- case 2:
- return reinterpret_cast<blink::Platform::TraceEventAPIAtomicWord*>(
- &TRACE_EVENT_API_THREAD_BUCKET(2));
- default:
- NOTREACHED() << "Unknown thread bucket type.";
- }
- return NULL;
-}
-
-static_assert(
- sizeof(blink::Platform::TraceEventHandle) ==
- sizeof(base::trace_event::TraceEventHandle),
- "TraceEventHandle types must be same size");
-
-blink::Platform::TraceEventHandle BlinkPlatformImpl::addTraceEvent(
- char phase,
- const unsigned char* category_group_enabled,
- const char* name,
- unsigned long long id,
- unsigned long long bind_id,
- double timestamp,
- int num_args,
- const char** arg_names,
- const unsigned char* arg_types,
- const unsigned long long* arg_values,
- blink::WebConvertableToTraceFormat* convertable_values,
- unsigned int flags) {
- scoped_refptr<base::trace_event::ConvertableToTraceFormat>
- convertable_wrappers[2];
- if (convertable_values) {
- size_t size = std::min(static_cast<size_t>(num_args),
- arraysize(convertable_wrappers));
- for (size_t i = 0; i < size; ++i) {
- if (arg_types[i] == TRACE_VALUE_TYPE_CONVERTABLE) {
- convertable_wrappers[i] =
- new ConvertableToTraceFormatWrapper(convertable_values[i]);
- }
- }
- }
- base::TimeTicks timestamp_tt =
- base::TimeTicks() + base::TimeDelta::FromSecondsD(timestamp);
- base::trace_event::TraceEventHandle handle =
- TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_THREAD_ID_AND_TIMESTAMP(
- phase, category_group_enabled, name, id, bind_id,
- base::PlatformThread::CurrentId(), timestamp_tt, num_args, arg_names,
- arg_types, arg_values, convertable_wrappers, flags);
- blink::Platform::TraceEventHandle result;
- memcpy(&result, &handle, sizeof(result));
- return result;
-}
-
-void BlinkPlatformImpl::updateTraceEventDuration(
- const unsigned char* category_group_enabled,
- const char* name,
- TraceEventHandle handle) {
- base::trace_event::TraceEventHandle traceEventHandle;
- memcpy(&traceEventHandle, &handle, sizeof(handle));
- TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(
- category_group_enabled, name, traceEventHandle);
-}
-
-void BlinkPlatformImpl::registerMemoryDumpProvider(
- blink::WebMemoryDumpProvider* wmdp, const char* name) {
- WebMemoryDumpProviderAdapter* wmdp_adapter =
- new WebMemoryDumpProviderAdapter(wmdp);
- bool did_insert =
- memory_dump_providers_.add(wmdp, make_scoped_ptr(wmdp_adapter)).second;
- if (!did_insert)
- return;
- wmdp_adapter->set_is_registered(true);
- base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider(
- wmdp_adapter, name, base::ThreadTaskRunnerHandle::Get());
-}
-
-void BlinkPlatformImpl::unregisterMemoryDumpProvider(
- blink::WebMemoryDumpProvider* wmdp) {
- scoped_ptr<WebMemoryDumpProviderAdapter> wmdp_adapter =
- memory_dump_providers_.take_and_erase(wmdp);
- if (!wmdp_adapter)
- return;
- base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
- wmdp_adapter.get());
- wmdp_adapter->set_is_registered(false);
-}
-
-blink::WebProcessMemoryDump* BlinkPlatformImpl::createProcessMemoryDump() {
- return new WebProcessMemoryDumpImpl();
+void BlinkPlatformImpl::recordAction(const blink::UserMetricsAction& name) {
+ if (ChildThread* child_thread = ChildThread::Get())
+ child_thread->RecordComputedAction(name.action());
}
blink::Platform::WebMemoryAllocatorDumpGuid
@@ -747,14 +510,14 @@ void BlinkPlatformImpl::addTraceLogEnabledStateObserver(
TraceLogEnabledStateObserver* observer) {
TraceLogObserverAdapter* adapter = new TraceLogObserverAdapter(observer);
bool did_insert =
- trace_log_observers_.add(observer, make_scoped_ptr(adapter)).second;
+ trace_log_observers_.add(observer, base::WrapUnique(adapter)).second;
DCHECK(did_insert);
base::trace_event::TraceLog::GetInstance()->AddEnabledStateObserver(adapter);
}
void BlinkPlatformImpl::removeTraceLogEnabledStateObserver(
TraceLogEnabledStateObserver* observer) {
- scoped_ptr<TraceLogObserverAdapter> adapter =
+ std::unique_ptr<TraceLogObserverAdapter> adapter =
trace_log_observers_.take_and_erase(observer);
DCHECK(adapter);
DCHECK(base::trace_event::TraceLog::GetInstance()->HasEnabledStateObserver(
@@ -983,12 +746,6 @@ const DataResource kDataResources[] = {
{"InspectorOverlayPage.html",
IDR_INSPECTOR_OVERLAY_PAGE_HTML,
ui::SCALE_FACTOR_NONE},
- {"InjectedScriptSource.js",
- IDR_INSPECTOR_INJECTED_SCRIPT_SOURCE_JS,
- ui::SCALE_FACTOR_NONE},
- {"DebuggerScriptSource.js",
- IDR_INSPECTOR_DEBUGGER_SCRIPT_SOURCE_JS,
- ui::SCALE_FACTOR_NONE},
{"DocumentExecCommand.js",
IDR_PRIVATE_SCRIPT_DOCUMENTEXECCOMMAND_JS,
ui::SCALE_FACTOR_NONE},
@@ -1088,15 +845,6 @@ WebString BlinkPlatformImpl::queryLocalizedString(
GetContentClient()->GetLocalizedString(message_id), values, NULL);
}
-double BlinkPlatformImpl::currentTimeSeconds() {
- return base::Time::Now().ToDoubleT();
-}
-
-double BlinkPlatformImpl::monotonicallyIncreasingTimeSeconds() {
- return base::TimeTicks::Now().ToInternalValue() /
- static_cast<double>(base::Time::kMicrosecondsPerSecond);
-}
-
blink::WebThread* BlinkPlatformImpl::compositorThread() const {
return compositor_thread_;
}
@@ -1146,11 +894,6 @@ blink::WebPushProvider* BlinkPlatformImpl::pushProvider() {
push_dispatcher_.get());
}
-blink::WebServicePortProvider* BlinkPlatformImpl::createServicePortProvider(
- blink::WebServicePortProviderClient* client) {
- return new ServicePortProvider(client, main_thread_task_runner_);
-}
-
blink::WebPermissionClient* BlinkPlatformImpl::permissionClient() {
if (!permission_client_.get())
return nullptr;
@@ -1203,7 +946,7 @@ long long BlinkPlatformImpl::databaseGetFileSize(
}
long long BlinkPlatformImpl::databaseGetSpaceAvailableForOrigin(
- const blink::WebString& origin_identifier) {
+ const blink::WebSecurityOrigin& origin) {
return 0;
}
@@ -1220,43 +963,14 @@ blink::WebString BlinkPlatformImpl::signedPublicKeyAndChallengeString(
return blink::WebString("");
}
-static size_t getMemoryUsageMB(bool bypass_cache) {
- size_t current_mem_usage = 0;
- MemoryUsageCache* mem_usage_cache_singleton = MemoryUsageCache::GetInstance();
- if (!bypass_cache &&
- mem_usage_cache_singleton->IsCachedValueValid(&current_mem_usage))
- return current_mem_usage;
-
- current_mem_usage = GetMemoryUsageKB() >> 10;
- mem_usage_cache_singleton->SetMemoryValue(current_mem_usage);
- return current_mem_usage;
-}
-
-size_t BlinkPlatformImpl::memoryUsageMB() {
- return getMemoryUsageMB(false);
-}
-
size_t BlinkPlatformImpl::actualMemoryUsageMB() {
- return getMemoryUsageMB(true);
-}
-
-size_t BlinkPlatformImpl::physicalMemoryMB() {
- return static_cast<size_t>(base::SysInfo::AmountOfPhysicalMemoryMB());
-}
-
-size_t BlinkPlatformImpl::virtualMemoryLimitMB() {
- return static_cast<size_t>(base::SysInfo::AmountOfVirtualMemoryMB());
+ return GetMemoryUsageKB() >> 10;
}
size_t BlinkPlatformImpl::numberOfProcessors() {
return static_cast<size_t>(base::SysInfo::NumberOfProcessors());
}
-blink::WebDiscardableMemory*
-BlinkPlatformImpl::allocateAndLockDiscardableMemory(size_t bytes) {
- return content::WebDiscardableMemoryImpl::CreateLockedMemory(bytes).release();
-}
-
size_t BlinkPlatformImpl::maxDecodedImageBytes() {
#if defined(OS_ANDROID)
if (base::SysInfo::IsLowEndDevice()) {
diff --git a/chromium/content/child/blink_platform_impl.h b/chromium/content/child/blink_platform_impl.h
index ea44ffc3a73..1b045874685 100644
--- a/chromium/content/child/blink_platform_impl.h
+++ b/chromium/content/child/blink_platform_impl.h
@@ -51,7 +51,6 @@ class ThreadSafeSender;
class TraceLogObserverAdapter;
class WebCryptoImpl;
class WebGeofencingProviderImpl;
-class WebMemoryDumpProviderAdapter;
class CONTENT_EXPORT BlinkPlatformImpl
: NON_EXPORTED_BASE(public blink::Platform) {
@@ -73,7 +72,7 @@ class CONTENT_EXPORT BlinkPlatformImpl
const blink::WebString& vfs_file_name) override;
long long databaseGetFileSize(const blink::WebString& vfs_file_name) override;
long long databaseGetSpaceAvailableForOrigin(
- const blink::WebString& origin_identifier) override;
+ const blink::WebSecurityOrigin& origin) override;
bool databaseSetFileSize(const blink::WebString& vfs_file_name,
long long size) override;
blink::WebString signedPublicKeyAndChallengeString(
@@ -81,14 +80,9 @@ class CONTENT_EXPORT BlinkPlatformImpl
const blink::WebString& challenge,
const blink::WebURL& url,
const blink::WebURL& top_origin) override;
- size_t memoryUsageMB() override;
size_t actualMemoryUsageMB() override;
- size_t physicalMemoryMB() override;
- size_t virtualMemoryLimitMB() override;
size_t numberOfProcessors() override;
- blink::WebDiscardableMemory* allocateAndLockDiscardableMemory(
- size_t bytes) override;
size_t maxDecodedImageBytes() override;
uint32_t getUniqueIdForProcess() override;
blink::WebURLLoader* createURLLoader() override;
@@ -100,50 +94,14 @@ class CONTENT_EXPORT BlinkPlatformImpl
blink::WebURLError cancelledError(const blink::WebURL& url) const override;
bool isReservedIPAddress(const blink::WebString& host) const override;
bool portAllowed(const blink::WebURL& url) const override;
+ bool parseMultipartHeadersFromBody(const char* bytes,
+ size_t size,
+ blink::WebURLResponse* response,
+ size_t* end) const override;
+
blink::WebThread* createThread(const char* name) override;
blink::WebThread* currentThread() override;
- void yieldCurrentThread() override;
- blink::WebWaitableEvent* createWaitableEvent(
- blink::WebWaitableEvent::ResetPolicy policy,
- blink::WebWaitableEvent::InitialState state) override;
- blink::WebWaitableEvent* waitMultipleEvents(
- const blink::WebVector<blink::WebWaitableEvent*>& events) override;
- void decrementStatsCounter(const char* name) override;
- void incrementStatsCounter(const char* name) override;
- void histogramCustomCounts(const char* name,
- int sample,
- int min,
- int max,
- int bucket_count) override;
- void histogramEnumeration(const char* name,
- int sample,
- int boundary_value) override;
- void histogramSparse(const char* name, int sample) override;
- const unsigned char* getTraceCategoryEnabledFlag(
- const char* category_name) override;
- TraceEventAPIAtomicWord* getTraceSamplingState(
- const unsigned thread_bucket) override;
- TraceEventHandle addTraceEvent(
- char phase,
- const unsigned char* category_group_enabled,
- const char* name,
- unsigned long long id,
- unsigned long long bind_id,
- double timestamp,
- int num_args,
- const char** arg_names,
- const unsigned char* arg_types,
- const unsigned long long* arg_values,
- blink::WebConvertableToTraceFormat* convertable_values,
- unsigned int flags) override;
- void updateTraceEventDuration(const unsigned char* category_group_enabled,
- const char* name,
- TraceEventHandle) override;
- void registerMemoryDumpProvider(blink::WebMemoryDumpProvider* wmdp,
- const char* name) override;
- void unregisterMemoryDumpProvider(
- blink::WebMemoryDumpProvider* wmdp) override;
- blink::WebProcessMemoryDump* createProcessMemoryDump() override;
+ void recordAction(const blink::UserMetricsAction&) override;
blink::Platform::WebMemoryAllocatorDumpGuid createWebMemoryAllocatorDumpGuid(
const blink::WebString& guidStr) override;
void addTraceLogEnabledStateObserver(
@@ -164,8 +122,6 @@ class CONTENT_EXPORT BlinkPlatformImpl
const blink::WebString& value1,
const blink::WebString& value2) override;
void suddenTerminationChanged(bool enabled) override {}
- double currentTimeSeconds() override;
- double monotonicallyIncreasingTimeSeconds() override;
blink::WebThread* compositorThread() const override;
blink::WebGestureCurve* createFlingAnimationCurve(
blink::WebGestureDevice device_source,
@@ -177,8 +133,6 @@ class CONTENT_EXPORT BlinkPlatformImpl
blink::WebGeofencingProvider* geofencingProvider() override;
blink::WebNotificationManager* notificationManager() override;
blink::WebPushProvider* pushProvider() override;
- blink::WebServicePortProvider* createServicePortProvider(
- blink::WebServicePortProviderClient*) override;
blink::WebPermissionClient* permissionClient() override;
blink::WebSyncProvider* backgroundSyncProvider() override;
@@ -204,19 +158,16 @@ class CONTENT_EXPORT BlinkPlatformImpl
WebFallbackThemeEngineImpl fallback_theme_engine_;
base::ThreadLocalStorage::Slot current_thread_slot_;
webcrypto::WebCryptoImpl web_crypto_;
- scoped_ptr<WebGeofencingProviderImpl> geofencing_provider_;
- base::ScopedPtrHashMap<blink::WebMemoryDumpProvider*,
- scoped_ptr<WebMemoryDumpProviderAdapter>>
- memory_dump_providers_;
+ std::unique_ptr<WebGeofencingProviderImpl> geofencing_provider_;
base::ScopedPtrHashMap<blink::Platform::TraceLogEnabledStateObserver*,
- scoped_ptr<TraceLogObserverAdapter>>
+ std::unique_ptr<TraceLogObserverAdapter>>
trace_log_observers_;
scoped_refptr<ThreadSafeSender> thread_safe_sender_;
scoped_refptr<NotificationDispatcher> notification_dispatcher_;
scoped_refptr<PushDispatcher> push_dispatcher_;
- scoped_ptr<PermissionDispatcher> permission_client_;
- scoped_ptr<BackgroundSyncProvider> main_thread_sync_provider_;
+ std::unique_ptr<PermissionDispatcher> permission_client_;
+ std::unique_ptr<BackgroundSyncProvider> main_thread_sync_provider_;
scheduler::WebThreadBase* compositor_thread_;
};
diff --git a/chromium/content/child/blob_storage/blob_consolidation.cc b/chromium/content/child/blob_storage/blob_consolidation.cc
index a2b0925d5d1..c912699d375 100644
--- a/chromium/content/child/blob_storage/blob_consolidation.cc
+++ b/chromium/content/child/blob_storage/blob_consolidation.cc
@@ -35,6 +35,9 @@ BlobConsolidation::ConsolidatedItem::ConsolidatedItem(DataElement::Type type,
expected_modification_time(0) {
}
+BlobConsolidation::ConsolidatedItem::ConsolidatedItem(
+ const ConsolidatedItem& other) = default;
+
BlobConsolidation::BlobConsolidation() : total_memory_(0) {
}
@@ -80,6 +83,7 @@ void BlobConsolidation::AddBlobItem(const std::string& uuid,
ConsolidatedItem(DataElement::TYPE_BLOB, offset, length));
ConsolidatedItem& item = consolidated_items_.back();
item.blob_uuid = uuid;
+ referenced_blobs_.insert(uuid);
}
void BlobConsolidation::AddFileSystemItem(const GURL& url,
diff --git a/chromium/content/child/blob_storage/blob_consolidation.h b/chromium/content/child/blob_storage/blob_consolidation.h
index c261b3cbeea..7c581d4cf95 100644
--- a/chromium/content/child/blob_storage/blob_consolidation.h
+++ b/chromium/content/child/blob_storage/blob_consolidation.h
@@ -8,12 +8,13 @@
#include <stddef.h>
#include <stdint.h>
+#include <memory>
+#include <set>
#include <string>
#include <vector>
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
#include "storage/common/data_element.h"
#include "third_party/WebKit/public/platform/WebThreadSafeData.h"
@@ -45,6 +46,7 @@ class CONTENT_EXPORT BlobConsolidation {
ConsolidatedItem(storage::DataElement::Type type,
uint64_t offset,
uint64_t length);
+ ConsolidatedItem(const ConsolidatedItem& other);
~ConsolidatedItem();
storage::DataElement::Type type;
@@ -82,6 +84,11 @@ class CONTENT_EXPORT BlobConsolidation {
return consolidated_items_;
}
+ // These are all of the blobs referenced in the construction of this blob.
+ const std::set<std::string> referenced_blobs() const {
+ return referenced_blobs_;
+ }
+
size_t total_memory() const { return total_memory_; }
// Reads memory from the given item into the given buffer. Returns:
@@ -98,6 +105,7 @@ class CONTENT_EXPORT BlobConsolidation {
private:
size_t total_memory_;
+ std::set<std::string> referenced_blobs_;
std::vector<ConsolidatedItem> consolidated_items_;
DISALLOW_COPY_AND_ASSIGN(BlobConsolidation);
diff --git a/chromium/content/child/blob_storage/blob_message_filter.cc b/chromium/content/child/blob_storage/blob_message_filter.cc
new file mode 100644
index 00000000000..19491d655fd
--- /dev/null
+++ b/chromium/content/child/blob_storage/blob_message_filter.cc
@@ -0,0 +1,61 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/child/blob_storage/blob_message_filter.h"
+
+#include "content/child/blob_storage/blob_transport_controller.h"
+#include "content/child/thread_safe_sender.h"
+#include "content/common/fileapi/webblob_messages.h"
+#include "ipc/ipc_message.h"
+#include "ipc/ipc_sender.h"
+#include "storage/common/blob_storage/blob_item_bytes_request.h"
+
+namespace content {
+
+BlobMessageFilter::BlobMessageFilter()
+ : IPC::MessageFilter(), sender_(nullptr) {}
+
+BlobMessageFilter::~BlobMessageFilter() {}
+
+void BlobMessageFilter::OnFilterAdded(IPC::Sender* sender) {
+ sender_ = sender;
+}
+
+bool BlobMessageFilter::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(BlobMessageFilter, message)
+ IPC_MESSAGE_HANDLER(BlobStorageMsg_RequestMemoryItem, OnRequestMemoryItem)
+ IPC_MESSAGE_HANDLER(BlobStorageMsg_CancelBuildingBlob, OnCancelBuildingBlob)
+ IPC_MESSAGE_HANDLER(BlobStorageMsg_DoneBuildingBlob, OnDoneBuildingBlob)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+bool BlobMessageFilter::GetSupportedMessageClasses(
+ std::vector<uint32_t>* supported_message_classes) const {
+ supported_message_classes->push_back(BlobMsgStart);
+ return true;
+}
+
+void BlobMessageFilter::OnRequestMemoryItem(
+ const std::string& uuid,
+ const std::vector<storage::BlobItemBytesRequest>& requests,
+ std::vector<base::SharedMemoryHandle> memory_handles,
+ const std::vector<IPC::PlatformFileForTransit>& file_handles) {
+ BlobTransportController::GetInstance()->OnMemoryRequest(
+ uuid, requests, &memory_handles, file_handles, sender_);
+}
+
+void BlobMessageFilter::OnCancelBuildingBlob(
+ const std::string& uuid,
+ storage::IPCBlobCreationCancelCode code) {
+ BlobTransportController::GetInstance()->OnCancel(uuid, code);
+}
+
+void BlobMessageFilter::OnDoneBuildingBlob(const std::string& uuid) {
+ BlobTransportController::GetInstance()->OnDone(uuid);
+}
+
+} // namespace content
diff --git a/chromium/content/child/blob_storage/blob_message_filter.h b/chromium/content/child/blob_storage/blob_message_filter.h
new file mode 100644
index 00000000000..26266658a22
--- /dev/null
+++ b/chromium/content/child/blob_storage/blob_message_filter.h
@@ -0,0 +1,63 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_CHILD_BLOB_STORAGE_BLOB_MESSAGE_FILTER_H_
+#define CONTENT_CHILD_BLOB_STORAGE_BLOB_MESSAGE_FILTER_H_
+
+#include <stddef.h>
+
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/shared_memory.h"
+#include "ipc/ipc_platform_file.h"
+#include "ipc/message_filter.h"
+#include "storage/common/blob_storage/blob_storage_constants.h"
+
+namespace IPC {
+class Sender;
+class Message;
+}
+
+namespace storage {
+struct BlobItemBytesRequest;
+}
+
+namespace content {
+
+// MessageFilter that handles Blob IPCs and delegates them to the
+// BlobTransportController singleton. Created on the render thread, and then
+// operated on by the IO thread.
+class BlobMessageFilter : public IPC::MessageFilter {
+ public:
+ BlobMessageFilter();
+
+ void OnFilterAdded(IPC::Sender* sender) override;
+ bool OnMessageReceived(const IPC::Message& message) override;
+ bool GetSupportedMessageClasses(
+ std::vector<uint32_t>* supported_message_classes) const override;
+
+ protected:
+ ~BlobMessageFilter() override;
+
+ private:
+ void OnRequestMemoryItem(
+ const std::string& uuid,
+ const std::vector<storage::BlobItemBytesRequest>& requests,
+ std::vector<base::SharedMemoryHandle> memory_handles,
+ const std::vector<IPC::PlatformFileForTransit>& file_handles);
+
+ void OnCancelBuildingBlob(const std::string& uuid,
+ storage::IPCBlobCreationCancelCode code);
+
+ void OnDoneBuildingBlob(const std::string& uuid);
+
+ IPC::Sender* sender_;
+
+ DISALLOW_COPY_AND_ASSIGN(BlobMessageFilter);
+};
+
+} // namespace content
+#endif // CONTENT_CHILD_BLOB_STORAGE_BLOB_MESSAGE_FILTER_H_
diff --git a/chromium/content/child/blob_storage/blob_transport_controller.cc b/chromium/content/child/blob_storage/blob_transport_controller.cc
index cfd2c05df12..0bcadbc85d3 100644
--- a/chromium/content/child/blob_storage/blob_transport_controller.cc
+++ b/chromium/content/child/blob_storage/blob_transport_controller.cc
@@ -10,13 +10,17 @@
#include "base/lazy_instance.h"
#include "base/memory/scoped_vector.h"
#include "base/memory/shared_memory.h"
+#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "content/child/blob_storage/blob_consolidation.h"
+#include "content/child/child_process.h"
#include "content/child/thread_safe_sender.h"
+#include "content/common/fileapi/webblob_messages.h"
#include "ipc/ipc_sender.h"
#include "storage/common/blob_storage/blob_item_bytes_request.h"
#include "storage/common/blob_storage/blob_item_bytes_response.h"
#include "storage/common/data_element.h"
+#include "third_party/WebKit/public/platform/Platform.h"
using base::SharedMemory;
using base::SharedMemoryHandle;
@@ -24,6 +28,7 @@ using storage::BlobItemBytesRequest;
using storage::BlobItemBytesResponse;
using storage::IPCBlobItemRequestStrategy;
using storage::DataElement;
+using storage::kBlobStorageIPCThresholdBytes;
namespace content {
@@ -33,29 +38,56 @@ using ConsolidatedItem = BlobConsolidation::ConsolidatedItem;
using ReadStatus = BlobConsolidation::ReadStatus;
namespace {
-const size_t kLargeThresholdBytes = 250 * 1024;
-static base::LazyInstance<BlobTransportController> g_controller =
+static base::LazyInstance<BlobTransportController>::Leaky g_controller =
LAZY_INSTANCE_INITIALIZER;
+
+// This keeps the process alive while blobs are being transferred.
+// These need to be called on the main thread.
+void IncChildProcessRefCount() {
+ blink::Platform::current()->suddenTerminationChanged(false);
+ ChildProcess::current()->AddRefProcess();
+}
+
+void DecChildProcessRefCount() {
+ blink::Platform::current()->suddenTerminationChanged(true);
+ ChildProcess::current()->ReleaseProcess();
+}
} // namespace
BlobTransportController* BlobTransportController::GetInstance() {
return g_controller.Pointer();
}
-BlobTransportController::~BlobTransportController() {}
-
+// static
void BlobTransportController::InitiateBlobTransfer(
const std::string& uuid,
- const std::string& type,
- scoped_ptr<BlobConsolidation> consolidation,
- IPC::Sender* sender) {
- BlobConsolidation* consolidation_ptr = consolidation.get();
- blob_storage_.insert(std::make_pair(uuid, std::move(consolidation)));
+ const std::string& content_type,
+ std::unique_ptr<BlobConsolidation> consolidation,
+ scoped_refptr<ThreadSafeSender> sender,
+ base::SingleThreadTaskRunner* io_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> main_runner) {
+ if (main_runner->BelongsToCurrentThread()) {
+ IncChildProcessRefCount();
+ } else {
+ main_runner->PostTask(FROM_HERE, base::Bind(&IncChildProcessRefCount));
+ }
+
std::vector<storage::DataElement> descriptions;
- GetDescriptions(consolidation_ptr, kLargeThresholdBytes, &descriptions);
- // TODO(dmurph): Uncomment when IPC messages are added.
- // sender->Send(new BlobStorageMsg_StartBuildingBlob(uuid, type,
- // descriptions));
+ std::set<std::string> referenced_blobs = consolidation->referenced_blobs();
+ BlobTransportController::GetDescriptions(
+ consolidation.get(), kBlobStorageIPCThresholdBytes, &descriptions);
+ // I post the task first to make sure that we store our consolidation before
+ // we get a request back from the browser.
+ io_runner->PostTask(
+ FROM_HERE,
+ base::Bind(&BlobTransportController::StoreBlobDataForRequests,
+ base::Unretained(BlobTransportController::GetInstance()), uuid,
+ base::Passed(std::move(consolidation)),
+ base::Passed(std::move(main_runner))));
+ // TODO(dmurph): Merge register and start messages.
+ sender->Send(new BlobStorageMsg_RegisterBlobUUID(uuid, content_type, "",
+ referenced_blobs));
+ sender->Send(new BlobStorageMsg_StartBuildingBlob(uuid, descriptions));
}
void BlobTransportController::OnMemoryRequest(
@@ -85,25 +117,14 @@ void BlobTransportController::OnMemoryRequest(
break;
}
- // TODO(dmurph): Uncomment when IPC messages are added.
- // sender->Send(new BlobStorageMsg_MemoryItemResponse(uuid, responses));
+ sender->Send(new BlobStorageMsg_MemoryItemResponse(uuid, responses));
}
void BlobTransportController::OnCancel(
const std::string& uuid,
storage::IPCBlobCreationCancelCode code) {
- DVLOG(1) << "Received blob cancel for blob " << uuid << " with reason:";
- switch (code) {
- case IPCBlobCreationCancelCode::UNKNOWN:
- DVLOG(1) << "Unknown.";
- break;
- case IPCBlobCreationCancelCode::OUT_OF_MEMORY:
- DVLOG(1) << "Out of Memory.";
- break;
- case IPCBlobCreationCancelCode::FILE_WRITE_FAILED:
- DVLOG(1) << "File Write Failed (Invalid cancel reason!).";
- break;
- }
+ DVLOG(1) << "Received blob cancel for blob " << uuid
+ << " with code: " << static_cast<int>(code);
ReleaseBlobConsolidation(uuid);
}
@@ -111,20 +132,7 @@ void BlobTransportController::OnDone(const std::string& uuid) {
ReleaseBlobConsolidation(uuid);
}
-void BlobTransportController::Clear() {
- blob_storage_.clear();
-}
-
-BlobTransportController::BlobTransportController() {}
-
-void BlobTransportController::CancelBlobTransfer(const std::string& uuid,
- IPCBlobCreationCancelCode code,
- IPC::Sender* sender) {
- // TODO(dmurph): Uncomment when IPC messages are added.
- // sender->Send(new BlobStorageMsg_CancelBuildingBlob(uuid, code));
- ReleaseBlobConsolidation(uuid);
-}
-
+// static
void BlobTransportController::GetDescriptions(
BlobConsolidation* consolidation,
size_t max_data_population,
@@ -178,6 +186,28 @@ void BlobTransportController::GetDescriptions(
}
}
+BlobTransportController::BlobTransportController() {}
+
+BlobTransportController::~BlobTransportController() {}
+
+void BlobTransportController::ClearForTesting() {
+ if (!blob_storage_.empty() && main_thread_runner_) {
+ main_thread_runner_->PostTask(FROM_HERE,
+ base::Bind(&DecChildProcessRefCount));
+ }
+ blob_storage_.clear();
+}
+
+void BlobTransportController::StoreBlobDataForRequests(
+ const std::string& uuid,
+ std::unique_ptr<BlobConsolidation> consolidation,
+ scoped_refptr<base::SingleThreadTaskRunner> main_runner) {
+ if (!main_thread_runner_.get()) {
+ main_thread_runner_ = std::move(main_runner);
+ }
+ blob_storage_[uuid] = std::move(consolidation);
+}
+
BlobTransportController::ResponsesStatus BlobTransportController::GetResponses(
const std::string& uuid,
const std::vector<BlobItemBytesRequest>& requests,
@@ -225,7 +255,7 @@ BlobTransportController::ResponsesStatus BlobTransportController::GetResponses(
if (!memory) {
SharedMemoryHandle& handle = (*memory_handles)[request.handle_index];
DCHECK(SharedMemory::IsHandleValid(handle));
- scoped_ptr<SharedMemory> shared_memory(
+ std::unique_ptr<SharedMemory> shared_memory(
new SharedMemory(handle, false));
if (!shared_memory->Map(request.size))
return ResponsesStatus::SHARED_MEMORY_MAP_FAILED;
@@ -255,7 +285,10 @@ BlobTransportController::ResponsesStatus BlobTransportController::GetResponses(
void BlobTransportController::ReleaseBlobConsolidation(
const std::string& uuid) {
- blob_storage_.erase(uuid);
+ if (blob_storage_.erase(uuid)) {
+ main_thread_runner_->PostTask(FROM_HERE,
+ base::Bind(&DecChildProcessRefCount));
+ }
}
} // namespace content
diff --git a/chromium/content/child/blob_storage/blob_transport_controller.h b/chromium/content/child/blob_storage/blob_transport_controller.h
index 4a2ef0a49ec..c9c62ce55ba 100644
--- a/chromium/content/child/blob_storage/blob_transport_controller.h
+++ b/chromium/content/child/blob_storage/blob_transport_controller.h
@@ -8,13 +8,13 @@
#include <stddef.h>
#include <map>
+#include <memory>
#include <string>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory_handle.h"
#include "content/common/content_export.h"
#include "ipc/ipc_platform_file.h"
@@ -23,6 +23,7 @@
namespace base {
template <typename T>
struct DefaultLazyInstanceTraits;
+class SingleThreadTaskRunner;
}
namespace storage {
@@ -38,6 +39,7 @@ class Sender;
namespace content {
class BlobConsolidation;
+class ThreadSafeSender;
// This class is used to manage all the asynchronous transporation of blobs from
// the Renderer to the Browser process, where it's handling the Renderer side.
@@ -54,11 +56,17 @@ class CONTENT_EXPORT BlobTransportController {
static BlobTransportController* GetInstance();
// This kicks off a blob transfer to the browser thread, which involves
- // sending an IPC message and storing the blob consolidation object.
- void InitiateBlobTransfer(const std::string& uuid,
- const std::string& type,
- scoped_ptr<BlobConsolidation> consolidation,
- IPC::Sender* sender);
+ // sending an IPC message and storing the blob consolidation object. Designed
+ // to be called by the main thread or a worker thread.
+ // This also calls ChildProcess::AddRefProcess to keep our process around
+ // while we transfer.
+ static void InitiateBlobTransfer(
+ const std::string& uuid,
+ const std::string& content_type,
+ std::unique_ptr<BlobConsolidation> consolidation,
+ scoped_refptr<ThreadSafeSender> sender,
+ base::SingleThreadTaskRunner* io_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> main_runner);
// This responds to the request using the sender.
void OnMemoryRequest(
@@ -73,21 +81,28 @@ class CONTENT_EXPORT BlobTransportController {
void OnDone(const std::string& uuid);
- // Clears all internal state for testing and such.
- void Clear();
-
bool IsTransporting(const std::string& uuid) {
return blob_storage_.find(uuid) != blob_storage_.end();
}
- ~BlobTransportController();
-
private:
+ friend class BlobTransportControllerTest;
FRIEND_TEST_ALL_PREFIXES(BlobTransportControllerTest, Descriptions);
FRIEND_TEST_ALL_PREFIXES(BlobTransportControllerTest, Responses);
FRIEND_TEST_ALL_PREFIXES(BlobTransportControllerTest, SharedMemory);
FRIEND_TEST_ALL_PREFIXES(BlobTransportControllerTest, ResponsesErrors);
+ static void GetDescriptions(BlobConsolidation* consolidation,
+ size_t max_data_population,
+ std::vector<storage::DataElement>* out);
+
+ BlobTransportController();
+ ~BlobTransportController();
+
+ // Clears all internal state. If our map wasn't previously empty, then we call
+ // ChildProcess::ReleaseProcess to release our previous reference.
+ void ClearForTesting();
+
enum class ResponsesStatus {
BLOB_NOT_FOUND,
SHARED_MEMORY_MAP_FAILED,
@@ -95,17 +110,10 @@ class CONTENT_EXPORT BlobTransportController {
};
friend struct base::DefaultLazyInstanceTraits<BlobTransportController>;
- BlobTransportController();
-
- // Sends the IPC to cancel the blob transfer, and releases the blob from
- // internal storage.
- void CancelBlobTransfer(const std::string& uuid,
- storage::IPCBlobCreationCancelCode code,
- IPC::Sender* sender);
-
- void GetDescriptions(BlobConsolidation* consolidation,
- size_t max_data_population,
- std::vector<storage::DataElement>* out);
+ void StoreBlobDataForRequests(
+ const std::string& uuid,
+ std::unique_ptr<BlobConsolidation> consolidation,
+ scoped_refptr<base::SingleThreadTaskRunner> main_runner);
ResponsesStatus GetResponses(
const std::string& uuid,
@@ -114,9 +122,13 @@ class CONTENT_EXPORT BlobTransportController {
const std::vector<IPC::PlatformFileForTransit>& file_handles,
std::vector<storage::BlobItemBytesResponse>* output);
+ // Deletes the consolidation, and if we removed the last consolidation from
+ // our map, we call ChildProcess::ReleaseProcess to release our previous
+ // reference.
void ReleaseBlobConsolidation(const std::string& uuid);
- std::map<std::string, scoped_ptr<BlobConsolidation>> blob_storage_;
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner_;
+ std::map<std::string, std::unique_ptr<BlobConsolidation>> blob_storage_;
DISALLOW_COPY_AND_ASSIGN(BlobTransportController);
};
diff --git a/chromium/content/child/blob_storage/blob_transport_controller_unittest.cc b/chromium/content/child/blob_storage/blob_transport_controller_unittest.cc
index 1d281364569..08120fcaca7 100644
--- a/chromium/content/child/blob_storage/blob_transport_controller_unittest.cc
+++ b/chromium/content/child/blob_storage/blob_transport_controller_unittest.cc
@@ -7,8 +7,16 @@
#include <stddef.h>
#include <stdint.h>
+#include "base/memory/ptr_util.h"
#include "base/memory/shared_memory.h"
+#include "base/test/test_simple_task_runner.h"
+#include "base/tuple.h"
#include "content/child/blob_storage/blob_consolidation.h"
+#include "content/child/thread_safe_sender.h"
+#include "content/common/fileapi/webblob_messages.h"
+#include "ipc/ipc_sender.h"
+#include "ipc/ipc_sync_message_filter.h"
+#include "ipc/ipc_test_sink.h"
#include "storage/common/blob_storage/blob_item_bytes_request.h"
#include "storage/common/blob_storage/blob_item_bytes_response.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -21,6 +29,29 @@ using storage::DataElement;
namespace content {
namespace {
+class OtherThreadTestSimpleTaskRunner : public base::TestSimpleTaskRunner {
+ public:
+ bool RunsTasksOnCurrentThread() const override { return false; }
+
+ protected:
+ ~OtherThreadTestSimpleTaskRunner() override {}
+};
+
+class BlobTransportControllerTestSender : public ThreadSafeSender {
+ public:
+ explicit BlobTransportControllerTestSender(IPC::TestSink* ipc_sink)
+ : ThreadSafeSender(nullptr, nullptr), ipc_sink_(ipc_sink) {}
+
+ bool Send(IPC::Message* message) override { return ipc_sink_->Send(message); }
+
+ private:
+ ~BlobTransportControllerTestSender() override {}
+
+ IPC::TestSink* ipc_sink_;
+
+ DISALLOW_COPY_AND_ASSIGN(BlobTransportControllerTestSender);
+};
+
BlobItemBytesResponse ResponseWithData(size_t request_number,
const std::string& str) {
BlobItemBytesResponse response(request_number);
@@ -56,9 +87,46 @@ static blink::WebThreadSafeData CreateData(const std::string& str) {
class BlobTransportControllerTest : public testing::Test {
public:
- void SetUp() override { BlobTransportController::GetInstance()->Clear(); }
-
- void TearDown() override { BlobTransportController::GetInstance()->Clear(); }
+ BlobTransportControllerTest()
+ : io_thread_runner_(new base::TestSimpleTaskRunner()),
+ main_thread_runner_(new OtherThreadTestSimpleTaskRunner()) {}
+
+ void SetUp() override {
+ sender_ = new BlobTransportControllerTestSender(&sink_);
+ BlobTransportController::GetInstance()->ClearForTesting();
+ }
+
+ void ExpectRegisterAndStartMessage(const std::string& expected_uuid,
+ const std::string& expected_content_type,
+ std::vector<DataElement>* descriptions) {
+ const IPC::Message* register_message =
+ sink_.GetUniqueMessageMatching(BlobStorageMsg_RegisterBlobUUID::ID);
+ const IPC::Message* start_message =
+ sink_.GetUniqueMessageMatching(BlobStorageMsg_StartBuildingBlob::ID);
+ ASSERT_TRUE(register_message);
+ ASSERT_TRUE(start_message);
+ base::Tuple<std::string, std::string, std::string, std::set<std::string>>
+ register_contents;
+ base::Tuple<std::string, std::vector<DataElement>> start_contents;
+ BlobStorageMsg_RegisterBlobUUID::Read(register_message, &register_contents);
+ BlobStorageMsg_StartBuildingBlob::Read(start_message, &start_contents);
+ EXPECT_EQ(expected_uuid, base::get<0>(register_contents));
+ EXPECT_EQ(expected_uuid, base::get<0>(start_contents));
+ EXPECT_EQ(expected_content_type, base::get<1>(register_contents));
+ if (descriptions)
+ *descriptions = base::get<1>(start_contents);
+ // We don't have dispositions from the renderer.
+ EXPECT_TRUE(base::get<2>(register_contents).empty());
+ }
+
+ void TearDown() override {
+ BlobTransportController::GetInstance()->ClearForTesting();
+ }
+
+ IPC::TestSink sink_;
+ scoped_refptr<BlobTransportControllerTestSender> sender_;
+ scoped_refptr<base::TestSimpleTaskRunner> io_thread_runner_;
+ scoped_refptr<OtherThreadTestSimpleTaskRunner> main_thread_runner_;
};
TEST_F(BlobTransportControllerTest, Descriptions) {
@@ -66,10 +134,9 @@ TEST_F(BlobTransportControllerTest, Descriptions) {
const std::string KRefBlobUUID = "refuuid";
const std::string kBadBlobUUID = "uuuidBad";
const size_t kShortcutSize = 11;
- BlobTransportController* holder = BlobTransportController::GetInstance();
// The first two data elements should be combined and the data shortcut.
- scoped_ptr<BlobConsolidation> consolidation(new BlobConsolidation());
+ std::unique_ptr<BlobConsolidation> consolidation(new BlobConsolidation());
consolidation->AddBlobItem(KRefBlobUUID, 10, 10);
consolidation->AddDataItem(CreateData("Hello"));
consolidation->AddDataItem(CreateData("Hello2"));
@@ -77,7 +144,8 @@ TEST_F(BlobTransportControllerTest, Descriptions) {
consolidation->AddDataItem(CreateData("Hello3"));
std::vector<DataElement> out;
- holder->GetDescriptions(consolidation.get(), kShortcutSize, &out);
+ BlobTransportController::GetDescriptions(consolidation.get(), kShortcutSize,
+ &out);
std::vector<DataElement> expected;
expected.push_back(MakeBlobElement(KRefBlobUUID, 10, 10));
@@ -103,8 +171,7 @@ TEST_F(BlobTransportControllerTest, Responses) {
consolidation->AddDataItem(CreateData("Hello3"));
// See the above test for the expected descriptions layout.
- holder->blob_storage_.insert(
- std::make_pair(kBlobUUID, make_scoped_ptr(consolidation)));
+ holder->blob_storage_[kBlobUUID] = base::WrapUnique(consolidation);
std::vector<BlobItemBytesRequest> requests;
std::vector<base::SharedMemoryHandle> memory_handles;
@@ -162,8 +229,7 @@ TEST_F(BlobTransportControllerTest, SharedMemory) {
consolidation->AddDataItem(CreateData("Hello3"));
// See the above test for the expected descriptions layout.
- holder->blob_storage_.insert(
- std::make_pair(kBlobUUID, make_scoped_ptr(consolidation)));
+ holder->blob_storage_[kBlobUUID] = base::WrapUnique(consolidation);
std::vector<BlobItemBytesRequest> requests;
std::vector<base::SharedMemoryHandle> memory_handles;
@@ -199,24 +265,60 @@ TEST_F(BlobTransportControllerTest, SharedMemory) {
TEST_F(BlobTransportControllerTest, TestPublicMethods) {
const std::string kBlobUUID = "uuid";
+ const std::string kBlobContentType = "content_type";
+ const std::string kBlob2UUID = "uuid2";
+ const std::string kBlob2ContentType = "content_type2";
const std::string KRefBlobUUID = "refuuid";
- const std::string kBadBlobUUID = "uuuidBad";
+ std::vector<DataElement> message_descriptions;
BlobTransportController* holder = BlobTransportController::GetInstance();
BlobConsolidation* consolidation = new BlobConsolidation();
consolidation->AddBlobItem(KRefBlobUUID, 10, 10);
- holder->InitiateBlobTransfer(kBlobUUID, "", make_scoped_ptr(consolidation),
- nullptr);
- holder->OnCancel(kBlobUUID,
- storage::IPCBlobCreationCancelCode::OUT_OF_MEMORY);
+ BlobTransportController::InitiateBlobTransfer(
+ kBlobUUID, kBlobContentType, base::WrapUnique(consolidation), sender_,
+ io_thread_runner_.get(), main_thread_runner_);
+ // Check that we have the 'increase ref' pending task.
+ EXPECT_TRUE(main_thread_runner_->HasPendingTask());
+ // Check that we have the 'store' pending task.
+ EXPECT_TRUE(io_thread_runner_->HasPendingTask());
+ // Check that we've sent the data.
+ ExpectRegisterAndStartMessage(kBlobUUID, kBlobContentType,
+ &message_descriptions);
+ main_thread_runner_->ClearPendingTasks();
+
+ // Check that we got the correct start message.
EXPECT_FALSE(holder->IsTransporting(kBlobUUID));
+ io_thread_runner_->RunPendingTasks();
+ EXPECT_TRUE(holder->IsTransporting(kBlobUUID));
+ base::Tuple<std::string, std::vector<DataElement>> message_contents;
+ EXPECT_EQ(MakeBlobElement(KRefBlobUUID, 10, 10), message_descriptions[0]);
- consolidation = new BlobConsolidation();
- consolidation->AddBlobItem(KRefBlobUUID, 10, 10);
- holder->InitiateBlobTransfer(kBlobUUID, "", make_scoped_ptr(consolidation),
- nullptr);
- holder->OnDone(kBlobUUID);
+ holder->OnCancel(kBlobUUID,
+ storage::IPCBlobCreationCancelCode::OUT_OF_MEMORY);
EXPECT_FALSE(holder->IsTransporting(kBlobUUID));
+ // Check we have the 'decrease ref' task.
+ EXPECT_TRUE(main_thread_runner_->HasPendingTask());
+ main_thread_runner_->ClearPendingTasks();
+ sink_.ClearMessages();
+
+ // Add the second.
+ BlobConsolidation* consolidation2 = new BlobConsolidation();
+ consolidation2->AddBlobItem(KRefBlobUUID, 10, 10);
+ BlobTransportController::InitiateBlobTransfer(
+ kBlob2UUID, kBlob2ContentType, base::WrapUnique(consolidation2), sender_,
+ io_thread_runner_.get(), main_thread_runner_);
+ EXPECT_TRUE(main_thread_runner_->HasPendingTask());
+ main_thread_runner_->ClearPendingTasks();
+ sink_.ClearMessages();
+
+ io_thread_runner_->RunPendingTasks();
+ EXPECT_TRUE(holder->IsTransporting(kBlob2UUID));
+
+ // Finish the second one.
+ holder->OnDone(kBlob2UUID);
+ EXPECT_FALSE(holder->IsTransporting(kBlob2UUID));
+ EXPECT_TRUE(main_thread_runner_->HasPendingTask());
+ main_thread_runner_->ClearPendingTasks();
}
TEST_F(BlobTransportControllerTest, ResponsesErrors) {
@@ -229,8 +331,7 @@ TEST_F(BlobTransportControllerTest, ResponsesErrors) {
BlobConsolidation* consolidation = new BlobConsolidation();
consolidation->AddBlobItem(KRefBlobUUID, 10, 10);
- holder->blob_storage_.insert(
- std::make_pair(kBlobUUID, make_scoped_ptr(consolidation)));
+ holder->blob_storage_[kBlobUUID] = base::WrapUnique(consolidation);
std::vector<BlobItemBytesRequest> requests;
std::vector<base::SharedMemoryHandle> memory_handles;
diff --git a/chromium/content/child/browser_font_resource_trusted.cc b/chromium/content/child/browser_font_resource_trusted.cc
index 979da68c23a..30bae9f179b 100644
--- a/chromium/content/child/browser_font_resource_trusted.cc
+++ b/chromium/content/child/browser_font_resource_trusted.cc
@@ -20,10 +20,10 @@
#include "third_party/WebKit/public/platform/WebCanvas.h"
#include "third_party/WebKit/public/platform/WebFloatPoint.h"
#include "third_party/WebKit/public/platform/WebFloatRect.h"
+#include "third_party/WebKit/public/platform/WebFont.h"
+#include "third_party/WebKit/public/platform/WebFontDescription.h"
#include "third_party/WebKit/public/platform/WebRect.h"
-#include "third_party/WebKit/public/web/WebFont.h"
-#include "third_party/WebKit/public/web/WebFontDescription.h"
-#include "third_party/WebKit/public/web/WebTextRun.h"
+#include "third_party/WebKit/public/platform/WebTextRun.h"
#include "third_party/icu/source/common/unicode/ubidi.h"
#include "third_party/skia/include/core/SkRect.h"
@@ -277,7 +277,7 @@ PP_Bool BrowserFontResource_Trusted::Describe(
// While converting the other way in PPFontDescToWebFontDesc we validated
// that the enums can be casted.
- WebFontDescription web_desc = font_->fontDescription();
+ WebFontDescription web_desc = font_->getFontDescription();
description->face = StringVar::StringToPPVar(base::UTF16ToUTF8(
base::StringPiece16(web_desc.family)));
description->family =
diff --git a/chromium/content/child/browser_font_resource_trusted.h b/chromium/content/child/browser_font_resource_trusted.h
index 3595bdde544..2e399badca7 100644
--- a/chromium/content/child/browser_font_resource_trusted.h
+++ b/chromium/content/child/browser_font_resource_trusted.h
@@ -5,10 +5,10 @@
#ifndef CONTENT_CHILD_BROWSER_FONT_RESOURCE_TRUSTED_H_
#define CONTENT_CHILD_BROWSER_FONT_RESOURCE_TRUSTED_H_
+#include <memory>
#include <string>
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "ppapi/c/pp_bool.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_resource.h"
@@ -68,7 +68,7 @@ class BrowserFontResource_Trusted
const PP_Rect* clip);
private:
- scoped_ptr<blink::WebFont> font_;
+ std::unique_ptr<blink::WebFont> font_;
DISALLOW_COPY_AND_ASSIGN(BrowserFontResource_Trusted);
};
diff --git a/chromium/content/child/child_discardable_shared_memory_manager.cc b/chromium/content/child/child_discardable_shared_memory_manager.cc
index 7bb268cc39f..e798ea7f8ff 100644
--- a/chromium/content/child/child_discardable_shared_memory_manager.cc
+++ b/chromium/content/child/child_discardable_shared_memory_manager.cc
@@ -4,6 +4,7 @@
#include "content/child/child_discardable_shared_memory_manager.h"
+#include <algorithm>
#include <utility>
#include "base/atomic_sequence_num.h"
@@ -12,6 +13,7 @@
#include "base/macros.h"
#include "base/memory/discardable_memory.h"
#include "base/memory/discardable_shared_memory.h"
+#include "base/memory/ptr_util.h"
#include "base/metrics/histogram.h"
#include "base/process/memory.h"
#include "base/process/process_metrics.h"
@@ -33,7 +35,7 @@ base::StaticAtomicSequenceNumber g_next_discardable_shared_memory_id;
class DiscardableMemoryImpl : public base::DiscardableMemory {
public:
DiscardableMemoryImpl(ChildDiscardableSharedMemoryManager* manager,
- scoped_ptr<DiscardableSharedMemoryHeap::Span> span)
+ std::unique_ptr<DiscardableSharedMemoryHeap::Span> span)
: manager_(manager), span_(std::move(span)), is_locked_(true) {}
~DiscardableMemoryImpl() override {
@@ -72,7 +74,7 @@ class DiscardableMemoryImpl : public base::DiscardableMemory {
private:
ChildDiscardableSharedMemoryManager* const manager_;
- scoped_ptr<DiscardableSharedMemoryHeap::Span> span_;
+ std::unique_ptr<DiscardableSharedMemoryHeap::Span> span_;
bool is_locked_;
DISALLOW_COPY_AND_ASSIGN(DiscardableMemoryImpl);
@@ -103,12 +105,13 @@ ChildDiscardableSharedMemoryManager::~ChildDiscardableSharedMemoryManager() {
MemoryUsageChanged(0, 0);
}
-scoped_ptr<base::DiscardableMemory>
+std::unique_ptr<base::DiscardableMemory>
ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(
size_t size) {
base::AutoLock lock(lock_);
- DCHECK_NE(size, 0u);
+ // TODO(reveman): Temporary diagnostics for http://crbug.com/577786.
+ CHECK_NE(size, 0u);
UMA_HISTOGRAM_CUSTOM_COUNTS("Memory.DiscardableAllocationSize",
size / 1024, // In KB
@@ -117,7 +120,9 @@ ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(
50);
// Round up to multiple of page size.
- size_t pages = (size + base::GetPageSize() - 1) / base::GetPageSize();
+ size_t pages =
+ std::max((size + base::GetPageSize() - 1) / base::GetPageSize(),
+ static_cast<size_t>(1));
// Default allocation size in pages.
size_t allocation_pages = kAllocationSize / base::GetPageSize();
@@ -134,7 +139,7 @@ ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(
size_t heap_size_prior_to_releasing_purged_memory = heap_.GetSize();
for (;;) {
// Search free lists for suitable span.
- scoped_ptr<DiscardableSharedMemoryHeap::Span> free_span =
+ std::unique_ptr<DiscardableSharedMemoryHeap::Span> free_span =
heap_.SearchFreeLists(pages, slack);
if (!free_span.get())
break;
@@ -159,7 +164,7 @@ ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(
// at least one span from the free lists.
MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists());
- return make_scoped_ptr(
+ return base::WrapUnique(
new DiscardableMemoryImpl(this, std::move(free_span)));
}
@@ -179,18 +184,18 @@ ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(
g_next_discardable_shared_memory_id.GetNext();
// Ask parent process to allocate a new discardable shared memory segment.
- scoped_ptr<base::DiscardableSharedMemory> shared_memory(
+ std::unique_ptr<base::DiscardableSharedMemory> shared_memory(
AllocateLockedDiscardableSharedMemory(allocation_size_in_bytes, new_id));
// Create span for allocated memory.
- scoped_ptr<DiscardableSharedMemoryHeap::Span> new_span(heap_.Grow(
+ std::unique_ptr<DiscardableSharedMemoryHeap::Span> new_span(heap_.Grow(
std::move(shared_memory), allocation_size_in_bytes, new_id,
base::Bind(&SendDeletedDiscardableSharedMemoryMessage, sender_, new_id)));
new_span->set_is_locked(true);
// Unlock and insert any left over memory into free lists.
if (pages < pages_to_allocate) {
- scoped_ptr<DiscardableSharedMemoryHeap::Span> leftover =
+ std::unique_ptr<DiscardableSharedMemoryHeap::Span> leftover =
heap_.Split(new_span.get(), pages);
leftover->shared_memory()->Unlock(
leftover->start() * base::GetPageSize() -
@@ -202,7 +207,7 @@ ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(
MemoryUsageChanged(heap_.GetSize(), heap_.GetSizeOfFreeLists());
- return make_scoped_ptr(new DiscardableMemoryImpl(this, std::move(new_span)));
+ return base::WrapUnique(new DiscardableMemoryImpl(this, std::move(new_span)));
}
bool ChildDiscardableSharedMemoryManager::OnMemoryDump(
@@ -266,7 +271,7 @@ void ChildDiscardableSharedMemoryManager::UnlockSpan(
}
void ChildDiscardableSharedMemoryManager::ReleaseSpan(
- scoped_ptr<DiscardableSharedMemoryHeap::Span> span) {
+ std::unique_ptr<DiscardableSharedMemoryHeap::Span> span) {
base::AutoLock lock(lock_);
// Delete span instead of merging it into free lists if memory is gone.
@@ -288,7 +293,7 @@ ChildDiscardableSharedMemoryManager::CreateMemoryAllocatorDump(
return heap_.CreateMemoryAllocatorDump(span, name, pmd);
}
-scoped_ptr<base::DiscardableSharedMemory>
+std::unique_ptr<base::DiscardableSharedMemory>
ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory(
size_t size,
DiscardableSharedMemoryId id) {
@@ -301,7 +306,7 @@ ChildDiscardableSharedMemoryManager::AllocateLockedDiscardableSharedMemory(
sender_->Send(
new ChildProcessHostMsg_SyncAllocateLockedDiscardableSharedMemory(
size, id, &handle));
- scoped_ptr<base::DiscardableSharedMemory> memory(
+ std::unique_ptr<base::DiscardableSharedMemory> memory(
new base::DiscardableSharedMemory(handle));
if (!memory->Map(size))
base::TerminateBecauseOutOfMemory(size);
diff --git a/chromium/content/child/child_discardable_shared_memory_manager.h b/chromium/content/child/child_discardable_shared_memory_manager.h
index 8a37593e980..4a645fa0975 100644
--- a/chromium/content/child/child_discardable_shared_memory_manager.h
+++ b/chromium/content/child/child_discardable_shared_memory_manager.h
@@ -29,7 +29,7 @@ class CONTENT_EXPORT ChildDiscardableSharedMemoryManager
~ChildDiscardableSharedMemoryManager() override;
// Overridden from base::DiscardableMemoryAllocator:
- scoped_ptr<base::DiscardableMemory> AllocateLockedDiscardableMemory(
+ std::unique_ptr<base::DiscardableMemory> AllocateLockedDiscardableMemory(
size_t size) override;
// Overridden from base::trace_event::MemoryDumpProvider:
@@ -41,7 +41,7 @@ class CONTENT_EXPORT ChildDiscardableSharedMemoryManager
bool LockSpan(DiscardableSharedMemoryHeap::Span* span);
void UnlockSpan(DiscardableSharedMemoryHeap::Span* span);
- void ReleaseSpan(scoped_ptr<DiscardableSharedMemoryHeap::Span> span);
+ void ReleaseSpan(std::unique_ptr<DiscardableSharedMemoryHeap::Span> span);
base::trace_event::MemoryAllocatorDump* CreateMemoryAllocatorDump(
DiscardableSharedMemoryHeap::Span* span,
@@ -49,7 +49,7 @@ class CONTENT_EXPORT ChildDiscardableSharedMemoryManager
base::trace_event::ProcessMemoryDump* pmd) const;
private:
- scoped_ptr<base::DiscardableSharedMemory>
+ std::unique_ptr<base::DiscardableSharedMemory>
AllocateLockedDiscardableSharedMemory(size_t size,
DiscardableSharedMemoryId id);
void MemoryUsageChanged(size_t new_bytes_allocated,
diff --git a/chromium/content/child/child_gpu_memory_buffer_manager.cc b/chromium/content/child/child_gpu_memory_buffer_manager.cc
index e88b6bd4b59..c636b508372 100644
--- a/chromium/content/child/child_gpu_memory_buffer_manager.cc
+++ b/chromium/content/child/child_gpu_memory_buffer_manager.cc
@@ -8,7 +8,7 @@
#include "content/common/child_process_messages.h"
#include "content/common/generic_shared_memory_id_generator.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
+#include "gpu/ipc/client/gpu_memory_buffer_impl.h"
namespace content {
namespace {
@@ -31,10 +31,12 @@ ChildGpuMemoryBufferManager::ChildGpuMemoryBufferManager(
ChildGpuMemoryBufferManager::~ChildGpuMemoryBufferManager() {
}
-scoped_ptr<gfx::GpuMemoryBuffer>
+std::unique_ptr<gfx::GpuMemoryBuffer>
ChildGpuMemoryBufferManager::AllocateGpuMemoryBuffer(const gfx::Size& size,
gfx::BufferFormat format,
- gfx::BufferUsage usage) {
+ gfx::BufferUsage usage,
+ int32_t surface_id) {
+ DCHECK_EQ(0, surface_id);
TRACE_EVENT2("renderer",
"ChildGpuMemoryBufferManager::AllocateGpuMemoryBuffer",
"width",
@@ -50,9 +52,11 @@ ChildGpuMemoryBufferManager::AllocateGpuMemoryBuffer(const gfx::Size& size,
if (!success || handle.is_null())
return nullptr;
- scoped_ptr<GpuMemoryBufferImpl> buffer(GpuMemoryBufferImpl::CreateFromHandle(
- handle, size, format, usage,
- base::Bind(&DeletedGpuMemoryBuffer, sender_, handle.id)));
+ std::unique_ptr<gpu::GpuMemoryBufferImpl> buffer(
+ gpu::GpuMemoryBufferImpl::CreateFromHandle(
+ handle, size, format, usage,
+ base::Bind(&DeletedGpuMemoryBuffer, base::RetainedRef(sender_),
+ handle.id)));
if (!buffer) {
sender_->Send(new ChildProcessHostMsg_DeletedGpuMemoryBuffer(
handle.id, gpu::SyncToken()));
@@ -62,7 +66,7 @@ ChildGpuMemoryBufferManager::AllocateGpuMemoryBuffer(const gfx::Size& size,
return std::move(buffer);
}
-scoped_ptr<gfx::GpuMemoryBuffer>
+std::unique_ptr<gfx::GpuMemoryBuffer>
ChildGpuMemoryBufferManager::CreateGpuMemoryBufferFromHandle(
const gfx::GpuMemoryBufferHandle& handle,
const gfx::Size& size,
@@ -74,14 +78,14 @@ ChildGpuMemoryBufferManager::CreateGpuMemoryBufferFromHandle(
gfx::GpuMemoryBuffer*
ChildGpuMemoryBufferManager::GpuMemoryBufferFromClientBuffer(
ClientBuffer buffer) {
- return GpuMemoryBufferImpl::FromClientBuffer(buffer);
+ return gpu::GpuMemoryBufferImpl::FromClientBuffer(buffer);
}
void ChildGpuMemoryBufferManager::SetDestructionSyncToken(
gfx::GpuMemoryBuffer* buffer,
const gpu::SyncToken& sync_token) {
- static_cast<GpuMemoryBufferImpl*>(buffer)
- ->set_destruction_sync_token(sync_token);
+ static_cast<gpu::GpuMemoryBufferImpl*>(buffer)->set_destruction_sync_token(
+ sync_token);
}
} // namespace content
diff --git a/chromium/content/child/child_gpu_memory_buffer_manager.h b/chromium/content/child/child_gpu_memory_buffer_manager.h
index d8ad35af1f0..97801f3a89f 100644
--- a/chromium/content/child/child_gpu_memory_buffer_manager.h
+++ b/chromium/content/child/child_gpu_memory_buffer_manager.h
@@ -17,11 +17,12 @@ class ChildGpuMemoryBufferManager : public gpu::GpuMemoryBufferManager {
~ChildGpuMemoryBufferManager() override;
// Overridden from gpu::GpuMemoryBufferManager:
- scoped_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer(
+ std::unique_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer(
const gfx::Size& size,
gfx::BufferFormat format,
- gfx::BufferUsage usage) override;
- scoped_ptr<gfx::GpuMemoryBuffer> CreateGpuMemoryBufferFromHandle(
+ gfx::BufferUsage usage,
+ int32_t surface_id) override;
+ std::unique_ptr<gfx::GpuMemoryBuffer> CreateGpuMemoryBufferFromHandle(
const gfx::GpuMemoryBufferHandle& handle,
const gfx::Size& size,
gfx::BufferFormat format) override;
diff --git a/chromium/content/child/child_histogram_message_filter.cc b/chromium/content/child/child_histogram_message_filter.cc
index dbf2dd22be1..911848f86f3 100644
--- a/chromium/content/child/child_histogram_message_filter.cc
+++ b/chromium/content/child/child_histogram_message_filter.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/location.h"
#include "base/metrics/histogram_delta_serialization.h"
+#include "base/metrics/persistent_histogram_allocator.h"
#include "base/single_thread_task_runner.h"
#include "content/child/child_process.h"
#include "content/common/child_process_messages.h"
@@ -35,13 +36,29 @@ bool ChildHistogramMessageFilter::OnMessageReceived(
const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(ChildHistogramMessageFilter, message)
- IPC_MESSAGE_HANDLER(ChildProcessMsg_GetChildHistogramData,
+ IPC_MESSAGE_HANDLER(ChildProcessMsg_SetHistogramMemory,
+ OnSetHistogramMemory)
+ IPC_MESSAGE_HANDLER(ChildProcessMsg_GetChildNonPersistentHistogramData,
OnGetChildHistogramData)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
+void ChildHistogramMessageFilter::OnSetHistogramMemory(
+ const base::SharedMemoryHandle& memory_handle,
+ int memory_size) {
+ // This message must be received only once. Multiple calls to create a global
+ // allocator will cause a CHECK() failure.
+ base::GlobalHistogramAllocator::CreateWithSharedMemoryHandle(memory_handle,
+ memory_size);
+
+ base::PersistentHistogramAllocator* global_allocator =
+ base::GlobalHistogramAllocator::Get();
+ if (global_allocator)
+ global_allocator->CreateTrackingHistograms(global_allocator->Name());
+}
+
void ChildHistogramMessageFilter::SendHistograms(int sequence_number) {
io_task_runner_->PostTask(
FROM_HERE, base::Bind(&ChildHistogramMessageFilter::UploadAllHistograms,
@@ -53,13 +70,23 @@ void ChildHistogramMessageFilter::OnGetChildHistogramData(int sequence_number) {
}
void ChildHistogramMessageFilter::UploadAllHistograms(int sequence_number) {
+ // If a persistent allocator is in use, it needs to occasionally update
+ // some internal histograms. An upload is happening so this is a good time.
+ base::PersistentHistogramAllocator* global_allocator =
+ base::GlobalHistogramAllocator::Get();
+ if (global_allocator)
+ global_allocator->UpdateTrackingHistograms();
+
if (!histogram_delta_serialization_) {
histogram_delta_serialization_.reset(
new base::HistogramDeltaSerialization("ChildProcess"));
}
std::vector<std::string> deltas;
- histogram_delta_serialization_->PrepareAndSerializeDeltas(&deltas);
+ // "false" to PerpareAndSerializeDeltas() indicates to *not* include
+ // histograms held in persistent storage on the assumption that they will be
+ // visible to the recipient through other means.
+ histogram_delta_serialization_->PrepareAndSerializeDeltas(&deltas, false);
sender_->Send(
new ChildProcessHostMsg_ChildHistogramData(sequence_number, deltas));
diff --git a/chromium/content/child/child_histogram_message_filter.h b/chromium/content/child/child_histogram_message_filter.h
index e035e3ad705..ff374298d58 100644
--- a/chromium/content/child/child_histogram_message_filter.h
+++ b/chromium/content/child/child_histogram_message_filter.h
@@ -5,11 +5,12 @@
#ifndef CONTENT_CHILD_CHILD_HISTOGRAM_MESSAGE_FILTER_H_
#define CONTENT_CHILD_CHILD_HISTOGRAM_MESSAGE_FILTER_H_
+#include <memory>
#include <string>
#include <vector>
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
+#include "base/memory/shared_memory.h"
#include "ipc/message_filter.h"
namespace base {
@@ -36,9 +37,11 @@ class ChildHistogramMessageFilter : public IPC::MessageFilter {
~ChildHistogramMessageFilter() override;
// Message handlers.
- virtual void OnGetChildHistogramData(int sequence_number);
+ void OnSetHistogramMemory(const base::SharedMemoryHandle& memory_handle,
+ int memory_size);
+ void OnGetChildHistogramData(int sequence_number);
- // Extract snapshot data and then send it off the the Browser process.
+ // Extract snapshot data and then send it off to the Browser process.
// Send only a delta to what we have already sent.
void UploadAllHistograms(int sequence_number);
@@ -47,7 +50,8 @@ class ChildHistogramMessageFilter : public IPC::MessageFilter {
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
// Prepares histogram deltas for transmission.
- scoped_ptr<base::HistogramDeltaSerialization> histogram_delta_serialization_;
+ std::unique_ptr<base::HistogramDeltaSerialization>
+ histogram_delta_serialization_;
DISALLOW_COPY_AND_ASSIGN(ChildHistogramMessageFilter);
};
diff --git a/chromium/content/child/child_process.cc b/chromium/content/child/child_process.cc
index 7cd842377c0..6d50239f14b 100644
--- a/chromium/content/child/child_process.cc
+++ b/chromium/content/child/child_process.cc
@@ -34,7 +34,9 @@ base::LazyInstance<base::ThreadLocalPointer<ChildProcess> > g_lazy_tls =
LAZY_INSTANCE_INITIALIZER;
}
-ChildProcess::ChildProcess()
+ChildProcess::ChildProcess() : ChildProcess(base::ThreadPriority::NORMAL) {}
+
+ChildProcess::ChildProcess(base::ThreadPriority io_thread_priority)
: ref_count_(0),
shutdown_event_(true, false),
io_thread_("Chrome_ChildIOThread") {
@@ -45,7 +47,10 @@ ChildProcess::ChildProcess()
// We can't recover from failing to start the IO thread.
base::Thread::Options thread_options(base::MessageLoop::TYPE_IO, 0);
+ thread_options.priority = io_thread_priority;
#if defined(OS_ANDROID)
+ // TODO(reveman): Remove this in favor of setting it explicitly for each type
+ // of process.
thread_options.priority = base::ThreadPriority::DISPLAY;
#endif
CHECK(io_thread_.StartWithOptions(thread_options));
diff --git a/chromium/content/child/child_process.h b/chromium/content/child/child_process.h
index a579aaf5e95..82ec7dd325b 100644
--- a/chromium/content/child/child_process.h
+++ b/chromium/content/child/child_process.h
@@ -5,8 +5,9 @@
#ifndef CONTENT_CHILD_CHILD_PROCESS_H_
#define CONTENT_CHILD_CHILD_PROCESS_H_
+#include <memory>
+
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
#include "content/common/content_export.h"
@@ -33,6 +34,7 @@ class CONTENT_EXPORT ChildProcess {
// Child processes should have an object that derives from this class.
// Normally you would immediately call set_main_thread after construction.
ChildProcess();
+ explicit ChildProcess(base::ThreadPriority io_thread_priority);
virtual ~ChildProcess();
// May be NULL if the main thread hasn't been set explicitly.
@@ -61,6 +63,9 @@ class CONTENT_EXPORT ChildProcess {
// itself down when the ref count reaches 0.
// For example, in the renderer process, generally each tab managed by this
// process will hold a reference to the process, and release when closed.
+ // However for renderer processes specifically, there is also fast shutdown
+ // code path initiated by the browser process. The process refcount does
+ // not influence fast shutdown. See blink::Platform::suddenTerminationChanged.
void AddRefProcess();
void ReleaseProcess();
@@ -81,7 +86,7 @@ class CONTENT_EXPORT ChildProcess {
// NOTE: make sure that main_thread_ is listed after shutdown_event_, since
// it depends on it (indirectly through IPC::SyncChannel). Same for
// io_thread_.
- scoped_ptr<ChildThreadImpl> main_thread_;
+ std::unique_ptr<ChildThreadImpl> main_thread_;
DISALLOW_COPY_AND_ASSIGN(ChildProcess);
};
diff --git a/chromium/content/child/child_shared_bitmap_manager.cc b/chromium/content/child/child_shared_bitmap_manager.cc
index d83d431d4e2..daa46279bb7 100644
--- a/chromium/content/child/child_shared_bitmap_manager.cc
+++ b/chromium/content/child/child_shared_bitmap_manager.cc
@@ -5,9 +5,11 @@
#include "content/child/child_shared_bitmap_manager.h"
#include <stddef.h>
+
#include <utility>
#include "base/debug/alias.h"
+#include "base/memory/ptr_util.h"
#include "base/process/memory.h"
#include "base/process/process_metrics.h"
#include "build/build_config.h"
@@ -30,7 +32,7 @@ class ChildSharedBitmap : public SharedMemoryBitmap {
sender_(sender) {}
ChildSharedBitmap(scoped_refptr<ThreadSafeSender> sender,
- scoped_ptr<base::SharedMemory> shared_memory_holder,
+ std::unique_ptr<base::SharedMemory> shared_memory_holder,
const cc::SharedBitmapId& id)
: ChildSharedBitmap(sender, shared_memory_holder.get(), id) {
shared_memory_holder_ = std::move(shared_memory_holder);
@@ -42,7 +44,7 @@ class ChildSharedBitmap : public SharedMemoryBitmap {
private:
scoped_refptr<ThreadSafeSender> sender_;
- scoped_ptr<base::SharedMemory> shared_memory_holder_;
+ std::unique_ptr<base::SharedMemory> shared_memory_holder_;
};
// Collect extra information for debugging bitmap creation failures.
@@ -52,7 +54,7 @@ void CollectMemoryUsageAndDie(const gfx::Size& size, size_t alloc_size) {
int height = size.height();
DWORD last_error = GetLastError();
- scoped_ptr<base::ProcessMetrics> metrics(
+ std::unique_ptr<base::ProcessMetrics> metrics(
base::ProcessMetrics::CreateProcessMetrics(
base::GetCurrentProcessHandle()));
@@ -83,9 +85,9 @@ ChildSharedBitmapManager::ChildSharedBitmapManager(
ChildSharedBitmapManager::~ChildSharedBitmapManager() {}
-scoped_ptr<cc::SharedBitmap> ChildSharedBitmapManager::AllocateSharedBitmap(
- const gfx::Size& size) {
- scoped_ptr<SharedMemoryBitmap> bitmap = AllocateSharedMemoryBitmap(size);
+std::unique_ptr<cc::SharedBitmap>
+ChildSharedBitmapManager::AllocateSharedBitmap(const gfx::Size& size) {
+ std::unique_ptr<SharedMemoryBitmap> bitmap = AllocateSharedMemoryBitmap(size);
#if defined(OS_POSIX)
// Close file descriptor to avoid running out.
if (bitmap)
@@ -94,21 +96,21 @@ scoped_ptr<cc::SharedBitmap> ChildSharedBitmapManager::AllocateSharedBitmap(
return std::move(bitmap);
}
-scoped_ptr<SharedMemoryBitmap>
+std::unique_ptr<SharedMemoryBitmap>
ChildSharedBitmapManager::AllocateSharedMemoryBitmap(const gfx::Size& size) {
TRACE_EVENT2("renderer",
"ChildSharedBitmapManager::AllocateSharedMemoryBitmap", "width",
size.width(), "height", size.height());
size_t memory_size;
if (!cc::SharedBitmap::SizeInBytes(size, &memory_size))
- return scoped_ptr<SharedMemoryBitmap>();
+ return std::unique_ptr<SharedMemoryBitmap>();
cc::SharedBitmapId id = cc::SharedBitmap::GenerateId();
- scoped_ptr<base::SharedMemory> memory;
+ std::unique_ptr<base::SharedMemory> memory;
#if defined(OS_POSIX)
base::SharedMemoryHandle handle;
sender_->Send(new ChildProcessHostMsg_SyncAllocateSharedBitmap(
memory_size, id, &handle));
- memory = make_scoped_ptr(new base::SharedMemory(handle, false));
+ memory = base::WrapUnique(new base::SharedMemory(handle, false));
if (!memory->Map(memory_size))
CollectMemoryUsageAndDie(size, memory_size);
#else
@@ -123,28 +125,29 @@ ChildSharedBitmapManager::AllocateSharedMemoryBitmap(const gfx::Size& size) {
sender_->Send(new ChildProcessHostMsg_AllocatedSharedBitmap(
memory_size, handle_to_send, id));
#endif
- return make_scoped_ptr(new ChildSharedBitmap(sender_, std::move(memory), id));
+ return base::WrapUnique(
+ new ChildSharedBitmap(sender_, std::move(memory), id));
}
-scoped_ptr<cc::SharedBitmap> ChildSharedBitmapManager::GetSharedBitmapFromId(
- const gfx::Size&,
- const cc::SharedBitmapId&) {
+std::unique_ptr<cc::SharedBitmap>
+ChildSharedBitmapManager::GetSharedBitmapFromId(const gfx::Size&,
+ const cc::SharedBitmapId&) {
NOTREACHED();
- return scoped_ptr<cc::SharedBitmap>();
+ return std::unique_ptr<cc::SharedBitmap>();
}
-scoped_ptr<cc::SharedBitmap> ChildSharedBitmapManager::GetBitmapForSharedMemory(
- base::SharedMemory* mem) {
+std::unique_ptr<cc::SharedBitmap>
+ChildSharedBitmapManager::GetBitmapForSharedMemory(base::SharedMemory* mem) {
cc::SharedBitmapId id = cc::SharedBitmap::GenerateId();
base::SharedMemoryHandle handle_to_send = mem->handle();
#if defined(OS_POSIX)
if (!mem->ShareToProcess(base::GetCurrentProcessHandle(), &handle_to_send))
- return scoped_ptr<cc::SharedBitmap>();
+ return std::unique_ptr<cc::SharedBitmap>();
#endif
sender_->Send(new ChildProcessHostMsg_AllocatedSharedBitmap(
mem->mapped_size(), handle_to_send, id));
- return make_scoped_ptr(new ChildSharedBitmap(sender_, mem, id));
+ return base::WrapUnique(new ChildSharedBitmap(sender_, mem, id));
}
} // namespace content
diff --git a/chromium/content/child/child_shared_bitmap_manager.h b/chromium/content/child/child_shared_bitmap_manager.h
index 792ed4591e5..feb065bb92a 100644
--- a/chromium/content/child/child_shared_bitmap_manager.h
+++ b/chromium/content/child/child_shared_bitmap_manager.h
@@ -7,9 +7,10 @@
#include <stdint.h>
+#include <memory>
+
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory.h"
#include "cc/resources/shared_bitmap_manager.h"
#include "content/child/thread_safe_sender.h"
@@ -34,15 +35,15 @@ class ChildSharedBitmapManager : public cc::SharedBitmapManager {
~ChildSharedBitmapManager() override;
// cc::SharedBitmapManager implementation.
- scoped_ptr<cc::SharedBitmap> AllocateSharedBitmap(
+ std::unique_ptr<cc::SharedBitmap> AllocateSharedBitmap(
const gfx::Size& size) override;
- scoped_ptr<cc::SharedBitmap> GetSharedBitmapFromId(
+ std::unique_ptr<cc::SharedBitmap> GetSharedBitmapFromId(
const gfx::Size&,
const cc::SharedBitmapId&) override;
- scoped_ptr<cc::SharedBitmap> GetBitmapForSharedMemory(
+ std::unique_ptr<cc::SharedBitmap> GetBitmapForSharedMemory(
base::SharedMemory* mem);
- scoped_ptr<SharedMemoryBitmap> AllocateSharedMemoryBitmap(
+ std::unique_ptr<SharedMemoryBitmap> AllocateSharedMemoryBitmap(
const gfx::Size& size);
private:
diff --git a/chromium/content/child/child_thread_impl.cc b/chromium/content/child/child_thread_impl.cc
index 5f5b949601a..733d538df65 100644
--- a/chromium/content/child/child_thread_impl.cc
+++ b/chromium/content/child/child_thread_impl.cc
@@ -18,6 +18,7 @@
#include "base/macros.h"
#include "base/message_loop/timer_slack.h"
#include "base/metrics/field_trial.h"
+#include "base/metrics/histogram_macros.h"
#include "base/process/process.h"
#include "base/process/process_handle.h"
#include "base/single_thread_task_runner.h"
@@ -27,6 +28,7 @@
#include "base/synchronization/lock.h"
#include "base/thread_task_runner_handle.h"
#include "base/threading/thread_local.h"
+#include "base/timer/elapsed_timer.h"
#include "base/tracked_objects.h"
#include "build/build_config.h"
#include "components/tracing/child_trace_message_filter.h"
@@ -52,8 +54,9 @@
#include "content/child/websocket_dispatcher.h"
#include "content/common/child_process_messages.h"
#include "content/common/in_process_child_thread_params.h"
-#include "content/common/mojo/mojo_messages.h"
+#include "content/common/mojo/mojo_shell_connection_impl.h"
#include "content/public/common/content_switches.h"
+#include "content/public/common/mojo_channel_switches.h"
#include "ipc/attachment_broker.h"
#include "ipc/attachment_broker_unprivileged.h"
#include "ipc/ipc_logging.h"
@@ -62,18 +65,13 @@
#include "ipc/ipc_sync_channel.h"
#include "ipc/ipc_sync_message_filter.h"
#include "ipc/mojo/ipc_channel_mojo.h"
-#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
-
-#if defined(TCMALLOC_TRACE_MEMORY_SUPPORTED)
-#include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
-#endif
+#include "ipc/mojo/scoped_ipc_support.h"
+#include "mojo/edk/embedder/embedder.h"
+#include "mojo/edk/embedder/platform_channel_pair.h"
-#if defined(USE_OZONE)
-#include "ui/ozone/public/client_native_pixmap_factory.h"
-#endif
-
-#if defined(MOJO_SHELL_CLIENT)
-#include "content/common/mojo/mojo_shell_connection_impl.h"
+#if defined(OS_POSIX)
+#include "base/posix/global_descriptors.h"
+#include "content/public/common/content_descriptors.h"
#endif
using tracked_objects::ThreadData;
@@ -113,7 +111,8 @@ class WaitAndExitDelegate : public base::PlatformThread::Delegate {
};
bool CreateWaitAndExitThread(base::TimeDelta duration) {
- scoped_ptr<WaitAndExitDelegate> delegate(new WaitAndExitDelegate(duration));
+ std::unique_ptr<WaitAndExitDelegate> delegate(
+ new WaitAndExitDelegate(duration));
const bool thread_created =
base::PlatformThread::CreateNonJoinable(0, delegate.get());
@@ -173,31 +172,6 @@ class SuicideOnChannelErrorFilter : public IPC::MessageFilter {
#endif // OS(POSIX)
-#if defined(USE_OZONE)
-class ClientNativePixmapFactoryFilter : public IPC::MessageFilter {
- public:
- // Overridden from IPC::MessageFilter:
- bool OnMessageReceived(const IPC::Message& message) override {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(ClientNativePixmapFactoryFilter, message)
- IPC_MESSAGE_HANDLER(ChildProcessMsg_InitializeClientNativePixmapFactory,
- OnInitializeClientNativePixmapFactory)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
- }
-
- protected:
- ~ClientNativePixmapFactoryFilter() override {}
-
- void OnInitializeClientNativePixmapFactory(
- const base::FileDescriptor& device_fd) {
- ui::ClientNativePixmapFactory::GetInstance()->Initialize(
- base::ScopedFD(device_fd.fd));
- }
-};
-#endif
-
#if defined(OS_ANDROID)
// A class that allows for triggering a clean shutdown from another
// thread through draining the main thread's msg loop.
@@ -252,6 +226,23 @@ void QuitClosure::PostQuitFromNonMainThread() {
base::LazyInstance<QuitClosure> g_quit_closure = LAZY_INSTANCE_INITIALIZER;
#endif
+void InitializeMojoIPCChannel() {
+ mojo::edk::ScopedPlatformHandle platform_channel;
+#if defined(OS_WIN)
+ platform_channel =
+ mojo::edk::PlatformChannelPair::PassClientHandleFromParentProcess(
+ *base::CommandLine::ForCurrentProcess());
+#elif defined(OS_POSIX)
+ platform_channel.reset(mojo::edk::PlatformHandle(
+ base::GlobalDescriptors::GetInstance()->Get(kMojoIPCChannel)));
+#endif
+ // Mojo isn't supported on all child process types.
+ // TODO(crbug.com/604282): Support Mojo in the remaining processes.
+ if (!platform_channel.is_valid())
+ return;
+ mojo::edk::SetParentPipeHandle(std::move(platform_channel));
+}
+
} // namespace
ChildThread* ChildThread::Get() {
@@ -264,6 +255,8 @@ ChildThreadImpl::Options::Options()
use_mojo_channel(false) {
}
+ChildThreadImpl::Options::Options(const Options& other) = default;
+
ChildThreadImpl::Options::~Options() {
}
@@ -275,6 +268,7 @@ ChildThreadImpl::Options::Builder::InBrowserProcess(
const InProcessChildThreadParams& params) {
options_.browser_process_io_runner = params.io_runner();
options_.channel_name = params.channel_name();
+ options_.in_process_message_pipe_handle = params.handle();
return *this;
}
@@ -312,7 +306,7 @@ bool ChildThreadImpl::ChildThreadMessageRouter::Send(IPC::Message* msg) {
bool ChildThreadImpl::ChildThreadMessageRouter::RouteMessage(
const IPC::Message& msg) {
- bool handled = MessageRouter::RouteMessage(msg);
+ bool handled = IPC::MessageRouter::RouteMessage(msg);
#if defined(OS_ANDROID)
if (!handled && msg.is_sync()) {
IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg);
@@ -342,15 +336,20 @@ scoped_refptr<base::SequencedTaskRunner> ChildThreadImpl::GetIOTaskRunner() {
return ChildProcess::current()->io_task_runner();
}
-void ChildThreadImpl::ConnectChannel(bool use_mojo_channel) {
+void ChildThreadImpl::ConnectChannel(bool use_mojo_channel,
+ mojo::ScopedMessagePipeHandle handle) {
bool create_pipe_now = true;
if (use_mojo_channel) {
VLOG(1) << "Mojo is enabled on child";
- scoped_refptr<base::SequencedTaskRunner> io_task_runner = GetIOTaskRunner();
- DCHECK(io_task_runner);
- channel_->Init(
- IPC::ChannelMojo::CreateClientFactory(io_task_runner, channel_name_),
- create_pipe_now);
+ if (!IsInBrowserProcess()) {
+ DCHECK(!handle.is_valid());
+ handle = mojo::edk::CreateChildMessagePipe(
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kMojoChannelToken));
+ }
+ DCHECK(handle.is_valid());
+ channel_->Init(IPC::ChannelMojo::CreateClientFactory(std::move(handle)),
+ create_pipe_now);
return;
}
@@ -371,14 +370,7 @@ void ChildThreadImpl::Init(const Options& options) {
IPC::Logging::GetInstance();
#endif
-#if USE_ATTACHMENT_BROKER
- // The only reason a global would already exist is if the thread is being run
- // in the browser process because of a command line switch.
- if (!IPC::AttachmentBroker::GetGlobal()) {
- attachment_broker_.reset(
- IPC::AttachmentBrokerUnprivileged::CreateBroker().release());
- }
-#endif
+ IPC::AttachmentBrokerUnprivileged::CreateBrokerIfNeeded();
channel_ =
IPC::SyncChannel::Create(this, ChildProcess::current()->io_task_runner(),
@@ -388,7 +380,18 @@ void ChildThreadImpl::Init(const Options& options) {
IPC::Logging::GetInstance()->SetIPCSender(this);
#endif
- mojo_ipc_support_.reset(new IPC::ScopedIPCSupport(GetIOTaskRunner()));
+ if (!IsInBrowserProcess()) {
+ // Don't double-initialize IPC support in single-process mode.
+ mojo_ipc_support_.reset(new IPC::ScopedIPCSupport(GetIOTaskRunner()));
+ InitializeMojoIPCChannel();
+ }
+
+ if (MojoShellConnectionImpl::Get()) {
+ base::ElapsedTimer timer;
+ MojoShellConnectionImpl::Get()->BindToRequestFromCommandLine();
+ UMA_HISTOGRAM_TIMES("Mojo.Shell.ChildConnectionTime", timer.Elapsed());
+ }
+
mojo_application_.reset(new MojoApplication(GetIOTaskRunner()));
sync_message_filter_ = channel_->CreateSyncMessageFilter();
@@ -435,8 +438,8 @@ void ChildThreadImpl::Init(const Options& options) {
// In single process mode we may already have a power monitor
if (!base::PowerMonitor::Get()) {
- scoped_ptr<PowerMonitorBroadcastSource> power_monitor_source(
- new PowerMonitorBroadcastSource());
+ std::unique_ptr<PowerMonitorBroadcastSource> power_monitor_source(
+ new PowerMonitorBroadcastSource());
channel_->AddFilter(power_monitor_source->GetMessageFilter());
power_monitor_.reset(
@@ -450,18 +453,17 @@ void ChildThreadImpl::Init(const Options& options) {
channel_->AddFilter(new SuicideOnChannelErrorFilter());
#endif
-#if defined(USE_OZONE)
- channel_->AddFilter(new ClientNativePixmapFactoryFilter());
-#endif
-
// Add filters passed here via options.
for (auto startup_filter : options.startup_filters) {
channel_->AddFilter(startup_filter);
}
- ConnectChannel(options.use_mojo_channel);
- if (attachment_broker_)
- attachment_broker_->DesignateBrokerCommunicationChannel(channel_.get());
+ IPC::AttachmentBroker* broker = IPC::AttachmentBroker::GetGlobal();
+ if (broker && !broker->IsPrivilegedBroker())
+ broker->RegisterBrokerCommunicationChannel(channel_.get());
+ ConnectChannel(
+ options.use_mojo_channel,
+ mojo::MakeScopedHandle(options.in_process_message_pipe_handle));
int connection_timeout = kConnectionTimeoutS;
std::string connection_override =
@@ -497,6 +499,10 @@ ChildThreadImpl::~ChildThreadImpl() {
IPC::Logging::GetInstance()->SetIPCSender(NULL);
#endif
+ IPC::AttachmentBroker* broker = IPC::AttachmentBroker::GetGlobal();
+ if (broker && !broker->IsPrivilegedBroker())
+ broker->DeregisterBrokerCommunicationChannel(channel_.get());
+
channel_->RemoveFilter(histogram_message_filter_.get());
channel_->RemoveFilter(sync_message_filter_.get());
@@ -518,8 +524,9 @@ void ChildThreadImpl::Shutdown() {
file_system_dispatcher_.reset();
quota_dispatcher_.reset();
WebFileSystemImpl::DeleteThreadSpecificInstance();
- // ChildDiscardableSharedMemoryManager has to be destroyed while
- // |thread_safe_sender_| and |message_loop_| are still valid.
+}
+
+void ChildThreadImpl::ShutdownDiscardableSharedMemoryManager() {
discardable_shared_memory_manager_.reset();
}
@@ -552,34 +559,35 @@ void ChildThreadImpl::ReleaseCachedFonts() {
}
#endif
-MessageRouter* ChildThreadImpl::GetRouter() {
+void ChildThreadImpl::RecordAction(const base::UserMetricsAction& action) {
+ NOTREACHED();
+}
+
+void ChildThreadImpl::RecordComputedAction(const std::string& action) {
+ NOTREACHED();
+}
+
+IPC::MessageRouter* ChildThreadImpl::GetRouter() {
DCHECK(base::MessageLoop::current() == message_loop());
return &router_;
}
-scoped_ptr<base::SharedMemory> ChildThreadImpl::AllocateSharedMemory(
+std::unique_ptr<base::SharedMemory> ChildThreadImpl::AllocateSharedMemory(
size_t buf_size) {
DCHECK(base::MessageLoop::current() == message_loop());
return AllocateSharedMemory(buf_size, this);
}
// static
-scoped_ptr<base::SharedMemory> ChildThreadImpl::AllocateSharedMemory(
+std::unique_ptr<base::SharedMemory> ChildThreadImpl::AllocateSharedMemory(
size_t buf_size,
IPC::Sender* sender) {
- scoped_ptr<base::SharedMemory> shared_buf;
-#if defined(OS_WIN)
- shared_buf.reset(new base::SharedMemory);
- if (!shared_buf->CreateAnonymous(buf_size)) {
- NOTREACHED();
- return nullptr;
- }
-#else
- // On POSIX, we need to ask the browser to create the shared memory for us,
- // since this is blocked by the sandbox.
+ std::unique_ptr<base::SharedMemory> shared_buf;
+ // Ask the browser to create the shared memory, since this is blocked by the
+ // sandbox on most platforms.
base::SharedMemoryHandle shared_mem_handle;
if (sender->Send(new ChildProcessHostMsg_SyncAllocateSharedMemory(
- buf_size, &shared_mem_handle))) {
+ buf_size, &shared_mem_handle))) {
if (base::SharedMemory::IsHandleValid(shared_mem_handle)) {
shared_buf.reset(new base::SharedMemory(shared_mem_handle, false));
} else {
@@ -590,7 +598,6 @@ scoped_ptr<base::SharedMemory> ChildThreadImpl::AllocateSharedMemory(
// Send is allowed to fail during shutdown. Return null in this case.
return nullptr;
}
-#endif
return shared_buf;
}
@@ -621,10 +628,6 @@ bool ChildThreadImpl::OnMessageReceived(const IPC::Message& msg) {
OnProfilingPhaseCompleted)
IPC_MESSAGE_HANDLER(ChildProcessMsg_SetProcessBackgrounded,
OnProcessBackgrounded)
- IPC_MESSAGE_HANDLER(MojoMsg_BindExternalMojoShellHandle,
- OnBindExternalMojoShellHandle)
- IPC_MESSAGE_HANDLER(ChildProcessMsg_SetMojoParentPipeHandle,
- OnSetMojoParentPipeHandle)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -679,28 +682,6 @@ void ChildThreadImpl::OnProfilingPhaseCompleted(int profiling_phase) {
ThreadData::OnProfilingPhaseCompleted(profiling_phase);
}
-void ChildThreadImpl::OnBindExternalMojoShellHandle(
- const IPC::PlatformFileForTransit& file) {
-#if defined(MOJO_SHELL_CLIENT)
-#if defined(OS_POSIX)
- base::PlatformFile handle = file.fd;
-#elif defined(OS_WIN)
- base::PlatformFile handle = file;
-#endif
- mojo::ScopedMessagePipeHandle message_pipe =
- mojo_shell_channel_init_.Init(handle, GetIOTaskRunner());
- DCHECK(message_pipe.is_valid());
- MojoShellConnectionImpl::Get()->BindToMessagePipe(std::move(message_pipe));
-#endif // defined(MOJO_SHELL_CLIENT)
-}
-
-void ChildThreadImpl::OnSetMojoParentPipeHandle(
- const IPC::PlatformFileForTransit& file) {
- mojo::embedder::SetParentPipeHandle(
- mojo::embedder::ScopedPlatformHandle(mojo::embedder::PlatformHandle(
- IPC::PlatformFileForTransitToPlatformFile(file))));
-}
-
ChildThreadImpl* ChildThreadImpl::current() {
return g_lazy_tls.Pointer()->Get();
}
diff --git a/chromium/content/child/child_thread_impl.h b/chromium/content/child/child_thread_impl.h
index 68a4d2b502e..fec7da76906 100644
--- a/chromium/content/child/child_thread_impl.h
+++ b/chromium/content/child/child_thread_impl.h
@@ -8,10 +8,10 @@
#include <stddef.h>
#include <stdint.h>
+#include <memory>
#include <string>
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory.h"
#include "base/memory/weak_ptr.h"
#include "base/power_monitor/power_monitor.h"
@@ -20,18 +20,16 @@
#include "build/build_config.h"
#include "content/child/mojo/mojo_application.h"
#include "content/common/content_export.h"
-#include "content/common/message_router.h"
-#include "content/common/mojo/channel_init.h"
#include "content/public/child/child_thread.h"
#include "ipc/ipc_message.h" // For IPC_MESSAGE_LOG_ENABLED.
#include "ipc/ipc_platform_file.h"
+#include "ipc/message_router.h"
namespace base {
class MessageLoop;
} // namespace base
namespace IPC {
-class AttachmentBrokerUnprivileged;
class MessageFilter;
class ScopedIPCSupport;
class SyncChannel;
@@ -80,6 +78,7 @@ class CONTENT_EXPORT ChildThreadImpl
// should be joined in Shutdown().
~ChildThreadImpl() override;
virtual void Shutdown();
+ void ShutdownDiscardableSharedMemoryManager();
// IPC::Sender implementation:
bool Send(IPC::Message* msg) override;
@@ -89,20 +88,22 @@ class CONTENT_EXPORT ChildThreadImpl
void PreCacheFont(const LOGFONT& log_font) override;
void ReleaseCachedFonts() override;
#endif
+ void RecordAction(const base::UserMetricsAction& action) override;
+ void RecordComputedAction(const std::string& action) override;
IPC::SyncChannel* channel() { return channel_.get(); }
- MessageRouter* GetRouter();
+ IPC::MessageRouter* GetRouter();
// Allocates a block of shared memory of the given size. Returns NULL on
// failure.
// Note: On posix, this requires a sync IPC to the browser process,
// but on windows the child process directly allocates the block.
- scoped_ptr<base::SharedMemory> AllocateSharedMemory(size_t buf_size);
+ std::unique_ptr<base::SharedMemory> AllocateSharedMemory(size_t buf_size);
// A static variant that can be called on background threads provided
// the |sender| passed in is safe to use on background threads.
- static scoped_ptr<base::SharedMemory> AllocateSharedMemory(
+ static std::unique_ptr<base::SharedMemory> AllocateSharedMemory(
size_t buf_size,
IPC::Sender* sender);
@@ -203,7 +204,7 @@ class CONTENT_EXPORT ChildThreadImpl
scoped_refptr<base::SequencedTaskRunner> GetIOTaskRunner();
private:
- class ChildThreadMessageRouter : public MessageRouter {
+ class ChildThreadMessageRouter : public IPC::MessageRouter {
public:
// |sender| must outlive this object.
explicit ChildThreadMessageRouter(IPC::Sender* sender);
@@ -220,27 +221,25 @@ class CONTENT_EXPORT ChildThreadImpl
// We create the channel first without connecting it so we can add filters
// prior to any messages being received, then connect it afterwards.
- void ConnectChannel(bool use_mojo_channel);
+ void ConnectChannel(bool use_mojo_channel,
+ mojo::ScopedMessagePipeHandle handle);
// IPC message handlers.
void OnShutdown();
void OnSetProfilerStatus(tracked_objects::ThreadData::Status status);
void OnGetChildProfilerData(int sequence_number, int current_profiling_phase);
void OnProfilingPhaseCompleted(int profiling_phase);
- void OnBindExternalMojoShellHandle(const IPC::PlatformFileForTransit& file);
- void OnSetMojoParentPipeHandle(const IPC::PlatformFileForTransit& file);
#ifdef IPC_MESSAGE_LOG_ENABLED
void OnSetIPCLoggingEnabled(bool enable);
#endif
void EnsureConnected();
- scoped_ptr<IPC::ScopedIPCSupport> mojo_ipc_support_;
- scoped_ptr<MojoApplication> mojo_application_;
+ std::unique_ptr<IPC::ScopedIPCSupport> mojo_ipc_support_;
+ std::unique_ptr<MojoApplication> mojo_application_;
std::string channel_name_;
- scoped_ptr<IPC::AttachmentBrokerUnprivileged> attachment_broker_;
- scoped_ptr<IPC::SyncChannel> channel_;
+ std::unique_ptr<IPC::SyncChannel> channel_;
// Allows threads other than the main thread to send sync messages.
scoped_refptr<IPC::SyncMessageFilter> sync_message_filter_;
@@ -252,9 +251,9 @@ class CONTENT_EXPORT ChildThreadImpl
ChildThreadMessageRouter router_;
// Handles resource loads for this process.
- scoped_ptr<ResourceDispatcher> resource_dispatcher_;
+ std::unique_ptr<ResourceDispatcher> resource_dispatcher_;
- scoped_ptr<WebSocketDispatcher> websocket_dispatcher_;
+ std::unique_ptr<WebSocketDispatcher> websocket_dispatcher_;
// The OnChannelError() callback was invoked - the channel is dead, don't
// attempt to communicate.
@@ -262,9 +261,9 @@ class CONTENT_EXPORT ChildThreadImpl
base::MessageLoop* message_loop_;
- scoped_ptr<FileSystemDispatcher> file_system_dispatcher_;
+ std::unique_ptr<FileSystemDispatcher> file_system_dispatcher_;
- scoped_ptr<QuotaDispatcher> quota_dispatcher_;
+ std::unique_ptr<QuotaDispatcher> quota_dispatcher_;
scoped_refptr<ChildHistogramMessageFilter> histogram_message_filter_;
@@ -278,27 +277,26 @@ class CONTENT_EXPORT ChildThreadImpl
scoped_refptr<PushDispatcher> push_dispatcher_;
- scoped_ptr<ChildSharedBitmapManager> shared_bitmap_manager_;
+ std::unique_ptr<ChildSharedBitmapManager> shared_bitmap_manager_;
- scoped_ptr<ChildGpuMemoryBufferManager> gpu_memory_buffer_manager_;
+ std::unique_ptr<ChildGpuMemoryBufferManager> gpu_memory_buffer_manager_;
- scoped_ptr<ChildDiscardableSharedMemoryManager>
+ std::unique_ptr<ChildDiscardableSharedMemoryManager>
discardable_shared_memory_manager_;
- scoped_ptr<base::PowerMonitor> power_monitor_;
+ std::unique_ptr<base::PowerMonitor> power_monitor_;
scoped_refptr<ChildMessageFilter> geofencing_message_filter_;
scoped_refptr<base::SequencedTaskRunner> browser_process_io_runner_;
- ChannelInit mojo_shell_channel_init_;
-
base::WeakPtrFactory<ChildThreadImpl> channel_connected_factory_;
DISALLOW_COPY_AND_ASSIGN(ChildThreadImpl);
};
struct ChildThreadImpl::Options {
+ Options(const Options& other);
~Options();
class Builder;
@@ -307,6 +305,7 @@ struct ChildThreadImpl::Options {
bool use_mojo_channel;
scoped_refptr<base::SequencedTaskRunner> browser_process_io_runner;
std::vector<IPC::MessageFilter*> startup_filters;
+ mojo::MessagePipeHandle in_process_message_pipe_handle;
private:
Options();
diff --git a/chromium/content/child/child_thread_impl_browsertest.cc b/chromium/content/child/child_thread_impl_browsertest.cc
index d357b5edf2b..de921299277 100644
--- a/chromium/content/child/child_thread_impl_browsertest.cc
+++ b/chromium/content/child/child_thread_impl_browsertest.cc
@@ -15,12 +15,12 @@
#include "base/time/time.h"
#include "content/child/child_discardable_shared_memory_manager.h"
#include "content/child/child_gpu_memory_buffer_manager.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
#include "content/common/host_discardable_shared_memory_manager.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
+#include "gpu/ipc/client/gpu_memory_buffer_impl.h"
#include "ui/gfx/buffer_format_util.h"
#include "url/gurl.h"
@@ -67,7 +67,7 @@ class ChildThreadImplBrowserTest : public ContentBrowserTest {
IN_PROC_BROWSER_TEST_F(ChildThreadImplBrowserTest, LockDiscardableMemory) {
const size_t kSize = 1024 * 1024; // 1MiB.
- scoped_ptr<base::DiscardableMemory> memory =
+ std::unique_ptr<base::DiscardableMemory> memory =
child_discardable_shared_memory_manager()
->AllocateLockedDiscardableMemory(kSize);
@@ -91,7 +91,7 @@ IN_PROC_BROWSER_TEST_F(ChildThreadImplBrowserTest,
ScopedVector<base::DiscardableMemory> instances;
for (size_t i = 0; i < kNumberOfInstances; ++i) {
- scoped_ptr<base::DiscardableMemory> memory =
+ std::unique_ptr<base::DiscardableMemory> memory =
child_discardable_shared_memory_manager()
->AllocateLockedDiscardableMemory(kLargeSize);
ASSERT_TRUE(memory);
@@ -106,7 +106,7 @@ IN_PROC_BROWSER_TEST_F(ChildThreadImplBrowserTest,
ReleaseFreeDiscardableMemory) {
const size_t kSize = 1024 * 1024; // 1MiB.
- scoped_ptr<base::DiscardableMemory> memory =
+ std::unique_ptr<base::DiscardableMemory> memory =
child_discardable_shared_memory_manager()
->AllocateLockedDiscardableMemory(kSize);
@@ -156,9 +156,10 @@ IN_PROC_BROWSER_TEST_P(ChildThreadImplGpuMemoryBufferBrowserTest,
gfx::BufferFormat format = ::testing::get<1>(GetParam());
gfx::Size buffer_size(4, 4);
- scoped_ptr<gfx::GpuMemoryBuffer> buffer =
+ std::unique_ptr<gfx::GpuMemoryBuffer> buffer =
child_gpu_memory_buffer_manager()->AllocateGpuMemoryBuffer(
- buffer_size, format, gfx::BufferUsage::GPU_READ_CPU_READ_WRITE);
+ buffer_size, format, gfx::BufferUsage::GPU_READ_CPU_READ_WRITE,
+ 0 /* surface_id */);
ASSERT_TRUE(buffer);
EXPECT_EQ(format, buffer->GetFormat());
@@ -174,7 +175,7 @@ IN_PROC_BROWSER_TEST_P(ChildThreadImplGpuMemoryBufferBrowserTest,
gfx::RowSizeForBufferFormat(buffer_size.width(), format, plane);
EXPECT_GT(row_size_in_bytes, 0u);
- scoped_ptr<char[]> data(new char[row_size_in_bytes]);
+ std::unique_ptr<char[]> data(new char[row_size_in_bytes]);
memset(data.get(), 0x2a + plane, row_size_in_bytes);
size_t height = buffer_size.height() /
gfx::SubsamplingFactorForBufferFormat(format, plane);
diff --git a/chromium/content/child/content_child_helpers.cc b/chromium/content/child/content_child_helpers.cc
index 4398bc067ae..7ddeb4d16a9 100644
--- a/chromium/content/child/content_child_helpers.cc
+++ b/chromium/content/child/content_child_helpers.cc
@@ -6,8 +6,9 @@
#include <stdint.h>
+#include <memory>
+
#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
#include "base/process/process_metrics.h"
#include "build/build_config.h"
#include "v8/include/v8.h"
@@ -18,6 +19,12 @@
namespace content {
+// TODO(primiano): get rid of this file together with --memory-metrics.
+// This function is both misplaced and misnamed. If useful, this should
+// be moved to base/process/process_metrics.h. Regardless the name,
+// though, this provides only a partial and misleading value.
+// Unfortunately some telemetry benchmark rely on it and these need to
+// be refactored before getting rid of this. See crbug.com/581365 .
#if defined(OS_LINUX) || defined(OS_ANDROID)
size_t GetMemoryUsageKB() {
struct mallinfo minfo = mallinfo();
@@ -39,7 +46,7 @@ size_t GetMemoryUsageKB() {
}
#elif defined(OS_MACOSX)
size_t GetMemoryUsageKB() {
- scoped_ptr<base::ProcessMetrics> process_metrics(
+ std::unique_ptr<base::ProcessMetrics> process_metrics(
// The default port provider is sufficient to get data for the current
// process.
base::ProcessMetrics::CreateProcessMetrics(
@@ -48,7 +55,7 @@ size_t GetMemoryUsageKB() {
}
#else
size_t GetMemoryUsageKB() {
- scoped_ptr<base::ProcessMetrics> process_metrics(
+ std::unique_ptr<base::ProcessMetrics> process_metrics(
base::ProcessMetrics::CreateProcessMetrics(
base::GetCurrentProcessHandle()));
return process_metrics->GetPagefileUsage() >> 10;
diff --git a/chromium/content/child/db_message_filter.cc b/chromium/content/child/db_message_filter.cc
index 9bd9af4d08b..9e65a38fc05 100644
--- a/chromium/content/child/db_message_filter.cc
+++ b/chromium/content/child/db_message_filter.cc
@@ -5,13 +5,28 @@
#include "content/child/db_message_filter.h"
#include "content/common/database_messages.h"
+#include "storage/common/database/database_identifier.h"
+#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/web/WebDatabase.h"
+using blink::WebSecurityOrigin;
using blink::WebString;
namespace content {
+namespace {
+
+// TODO(jsbell): Pass url::Origin over IPC instead of database identifier/GURL.
+// https://crbug.com/591482
+WebSecurityOrigin OriginFromIdentifier(const std::string& identifier) {
+ return WebSecurityOrigin::create(
+ storage::GetOriginFromIdentifier(identifier));
+}
+
+} // namespace
+
DBMessageFilter::DBMessageFilter() {
}
@@ -34,27 +49,27 @@ void DBMessageFilter::OnDatabaseUpdateSize(const std::string& origin_identifier,
const base::string16& database_name,
int64_t database_size) {
blink::WebDatabase::updateDatabaseSize(
- WebString::fromUTF8(origin_identifier), database_name, database_size);
+ OriginFromIdentifier(origin_identifier), database_name, database_size);
}
void DBMessageFilter::OnDatabaseUpdateSpaceAvailable(
const std::string& origin_identifier,
int64_t space_available) {
blink::WebDatabase::updateSpaceAvailable(
- WebString::fromUTF8(origin_identifier), space_available);
+ OriginFromIdentifier(origin_identifier), space_available);
}
void DBMessageFilter::OnDatabaseResetSpaceAvailable(
const std::string& origin_identifier) {
blink::WebDatabase::resetSpaceAvailable(
- WebString::fromUTF8(origin_identifier));
+ OriginFromIdentifier(origin_identifier));
}
void DBMessageFilter::OnDatabaseCloseImmediately(
const std::string& origin_identifier,
const base::string16& database_name) {
blink::WebDatabase::closeDatabaseImmediately(
- WebString::fromUTF8(origin_identifier), database_name);
+ OriginFromIdentifier(origin_identifier), database_name);
}
} // namespace content
diff --git a/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.cc b/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.cc
index 7ec2a42451b..58d10551b9b 100644
--- a/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.cc
+++ b/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.cc
@@ -12,9 +12,10 @@
#include "base/win/iat_patch_function.h"
#include "base/win/windows_version.h"
#include "content/child/dwrite_font_proxy/dwrite_font_proxy_win.h"
-#include "content/common/font_warmup_win.h"
+#include "content/child/font_warmup_win.h"
#include "skia/ext/fontmgr_default_win.h"
#include "third_party/WebKit/public/web/win/WebFontRendering.h"
+#include "third_party/skia/include/ports/SkFontMgr.h"
#include "third_party/skia/include/ports/SkTypeface_win.h"
namespace mswr = Microsoft::WRL;
@@ -58,52 +59,26 @@ void CreateDirectWriteFactory(IDWriteFactory** factory) {
reinterpret_cast<IUnknown**>(factory))));
}
-HRESULT STDMETHODCALLTYPE StubFontCollection(IDWriteFactory* factory,
- IDWriteFontCollection** col,
- BOOL checkUpdates) {
- DCHECK(g_font_collection);
- g_font_collection.CopyTo(col);
- return S_OK;
-}
-
-// Copied from content/common/font_warmup_win.cc
-void PatchDWriteFactory(IDWriteFactory* factory) {
- const unsigned int kGetSystemFontCollectionVTableIndex = 3;
-
- PROC* vtable = *reinterpret_cast<PROC**>(factory);
- PROC* function_ptr = &vtable[kGetSystemFontCollectionVTableIndex];
- void* stub_function = &StubFontCollection;
- base::win::ModifyCode(function_ptr, &stub_function, sizeof(PROC));
-}
-
-// Needed as a function for Bind()
-IPC::Sender* GetSenderOverride() {
- return g_sender_override;
-}
-
} // namespace
-void InitializeDWriteFontProxy(
- const base::Callback<IPC::Sender*(void)>& sender) {
+void InitializeDWriteFontProxy() {
mswr::ComPtr<IDWriteFactory> factory;
CreateDirectWriteFactory(&factory);
if (!g_font_collection) {
- if (g_sender_override) {
- mswr::MakeAndInitialize<DWriteFontCollectionProxy>(
- &g_font_collection, factory.Get(), base::Bind(&GetSenderOverride));
- } else {
- mswr::MakeAndInitialize<DWriteFontCollectionProxy>(&g_font_collection,
- factory.Get(), sender);
- }
+ mswr::MakeAndInitialize<DWriteFontCollectionProxy>(
+ &g_font_collection, factory.Get(), g_sender_override);
}
- PatchDWriteFactory(factory.Get());
+ sk_sp<SkFontMgr> skia_font_manager(
+ SkFontMgr_New_DirectWrite(factory.Get(), g_font_collection.Get()));
+ blink::WebFontRendering::setSkiaFontManager(skia_font_manager.get());
- blink::WebFontRendering::setDirectWriteFactory(factory.Get());
- SkFontMgr* skia_font_manager = SkFontMgr_New_DirectWrite(factory.Get());
- SetDefaultSkiaFactory(skia_font_manager);
+ // Add an extra ref for SetDefaultSkiaFactory, which keeps a ref but doesn't
+ // addref.
+ skia_font_manager->ref();
+ SetDefaultSkiaFactory(skia_font_manager.get());
}
void UninitializeDWriteFontProxy() {
diff --git a/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.h b/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.h
index e346cb01684..68f8b6dfa48 100644
--- a/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.h
+++ b/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.h
@@ -11,10 +11,8 @@
namespace content {
-// Initializes the dwrite font proxy, using the specified callback to obtain
-// the sender to be used for sending IPC messages to the browser process.
-CONTENT_EXPORT void InitializeDWriteFontProxy(
- const base::Callback<IPC::Sender*(void)>& sender);
+// Initializes the dwrite font proxy.
+CONTENT_EXPORT void InitializeDWriteFontProxy();
// Uninitialize the dwrite font proxy. This is safe to call even if the proxy
// has not been initialized. After this, calls to load fonts may fail.
diff --git a/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc b/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc
index 521adea74ab..d99296ee126 100644
--- a/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc
+++ b/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.cc
@@ -16,6 +16,7 @@
#include "base/win/scoped_handle.h"
#include "content/child/dwrite_font_proxy/dwrite_localized_strings_win.h"
#include "content/common/dwrite_font_proxy_messages.h"
+#include "content/public/child/child_thread.h"
#include "ipc/ipc_sender.h"
namespace mswr = Microsoft::WRL;
@@ -41,7 +42,7 @@ enum DirectWriteLoadFamilyResult {
const char kFontKeyName[] = "font_key_name";
void LogLoadFamilyResult(DirectWriteLoadFamilyResult result) {
- UMA_HISTOGRAM_ENUMERATION("DirectWrite.Fonts.Proxy.LoadFamily", result,
+ UMA_HISTOGRAM_ENUMERATION("DirectWrite.Fonts.Proxy.LoadFamilyResult", result,
LOAD_FAMILY_MAX_VALUE);
}
@@ -69,7 +70,7 @@ HRESULT DWriteFontCollectionProxy::FindFamilyName(const WCHAR* family_name,
return S_OK;
}
- if (!sender_.Run()->Send(
+ if (!GetSender()->Send(
new DWriteFontProxyMsg_FindFamily(name, &family_index))) {
return E_FAIL;
}
@@ -113,7 +114,7 @@ UINT32 DWriteFontCollectionProxy::GetFontFamilyCount() {
TRACE_EVENT0("dwrite", "FontProxy::GetFontFamilyCount");
uint32_t family_count = 0;
- if (!sender_.Run()->Send(
+ if (!GetSender()->Send(
new DWriteFontProxyMsg_GetFamilyCount(&family_count))) {
return 0;
}
@@ -128,9 +129,13 @@ HRESULT DWriteFontCollectionProxy::GetFontFromFontFace(
DCHECK(font);
for (const auto& family : families_) {
- if (family && family->GetFontFromFontFace(font_face, font))
+ if (family && family->GetFontFromFontFace(font_face, font)) {
return S_OK;
+ }
}
+ // If the font came from our collection, at least one family should match
+ DCHECK(false);
+
return E_FAIL;
}
@@ -139,22 +144,24 @@ HRESULT DWriteFontCollectionProxy::CreateEnumeratorFromKey(
const void* collection_key,
UINT32 collection_key_size,
IDWriteFontFileEnumerator** font_file_enumerator) {
- if (!collection_key || collection_key_size != sizeof(uint32_t))
+ if (!collection_key || collection_key_size != sizeof(uint32_t)) {
return E_INVALIDARG;
+ }
TRACE_EVENT0("dwrite", "FontProxy::LoadingFontFiles");
const uint32_t* family_index =
reinterpret_cast<const uint32_t*>(collection_key);
- if (*family_index >= GetFontFamilyCount())
+ if (*family_index >= GetFontFamilyCount()) {
return E_INVALIDARG;
+ }
// If we already loaded the family we should reuse the existing collection.
DCHECK(!families_[*family_index]->IsLoaded());
std::vector<base::string16> file_names;
- if (!sender_.Run()->Send(
+ if (!GetSender()->Send(
new DWriteFontProxyMsg_GetFontFiles(*family_index, &file_names))) {
return E_FAIL;
}
@@ -162,8 +169,10 @@ HRESULT DWriteFontCollectionProxy::CreateEnumeratorFromKey(
HRESULT hr = mswr::MakeAndInitialize<FontFileEnumerator>(
font_file_enumerator, factory, this, &file_names);
- if (!SUCCEEDED(hr))
+ if (!SUCCEEDED(hr)) {
+ DCHECK(false);
return E_FAIL;
+ }
return S_OK;
}
@@ -172,8 +181,9 @@ HRESULT DWriteFontCollectionProxy::CreateStreamFromKey(
const void* font_file_reference_key,
UINT32 font_file_reference_key_size,
IDWriteFontFileStream** font_file_stream) {
- if (!font_file_reference_key)
+ if (!font_file_reference_key) {
return E_FAIL;
+ }
const base::char16* file_name =
reinterpret_cast<const base::char16*>(font_file_reference_key);
@@ -181,25 +191,28 @@ HRESULT DWriteFontCollectionProxy::CreateStreamFromKey(
size_t file_name_size =
static_cast<size_t>(font_file_reference_key_size) / sizeof(base::char16);
- if (file_name_size == 0 || file_name[file_name_size - 1] != L'\0')
+ if (file_name_size == 0 || file_name[file_name_size - 1] != L'\0') {
return E_FAIL;
+ }
TRACE_EVENT0("dwrite", "FontFileEnumerator::CreateStreamFromKey");
mswr::ComPtr<IDWriteFontFileStream> stream;
- if (!SUCCEEDED(mswr::MakeAndInitialize<FontFileStream>(&stream, file_name)))
+ if (!SUCCEEDED(mswr::MakeAndInitialize<FontFileStream>(&stream, file_name))) {
+ DCHECK(false);
return E_FAIL;
+ }
*font_file_stream = stream.Detach();
return S_OK;
}
HRESULT DWriteFontCollectionProxy::RuntimeClassInitialize(
IDWriteFactory* factory,
- const base::Callback<IPC::Sender*(void)>& sender) {
+ IPC::Sender* sender_override) {
DCHECK(factory);
factory_ = factory;
- sender_ = sender;
+ sender_override_ = sender_override;
HRESULT hr = factory->RegisterFontCollectionLoader(this);
DCHECK(SUCCEEDED(hr));
@@ -234,7 +247,7 @@ bool DWriteFontCollectionProxy::LoadFamilyNames(
TRACE_EVENT0("dwrite", "FontProxy::LoadFamilyNames");
std::vector<std::pair<base::string16, base::string16>> strings;
- if (!sender_.Run()->Send(
+ if (!GetSender()->Send(
new DWriteFontProxyMsg_GetFamilyNames(family_index, &strings))) {
return false;
}
@@ -250,8 +263,9 @@ bool DWriteFontCollectionProxy::CreateFamily(UINT32 family_index) {
return true;
UINT32 family_count = GetFontFamilyCount();
- if (family_index >= family_count)
+ if (family_index >= family_count) {
return false;
+ }
if (families_.size() < family_count)
families_.resize(family_count);
@@ -266,6 +280,10 @@ bool DWriteFontCollectionProxy::CreateFamily(UINT32 family_index) {
return true;
}
+IPC::Sender* DWriteFontCollectionProxy::GetSender() {
+ return sender_override_ ? sender_override_ : ChildThread::Get();
+}
+
DWriteFontFamilyProxy::DWriteFontFamilyProxy() = default;
DWriteFontFamilyProxy::~DWriteFontFamilyProxy() = default;
@@ -292,8 +310,9 @@ UINT32 DWriteFontFamilyProxy::GetFontCount() {
HRESULT DWriteFontFamilyProxy::GetFont(UINT32 index, IDWriteFont** font) {
DCHECK(font);
- if (index >= GetFontCount())
+ if (index >= GetFontCount()) {
return E_INVALIDARG;
+ }
if (!LoadFamily())
return E_FAIL;
@@ -440,16 +459,19 @@ FontFileEnumerator::~FontFileEnumerator() = default;
HRESULT FontFileEnumerator::GetCurrentFontFile(IDWriteFontFile** file) {
DCHECK(file);
- if (current_file_ >= file_names_.size())
+ if (current_file_ >= file_names_.size()) {
return E_FAIL;
+ }
TRACE_EVENT0("dwrite", "FontFileEnumerator::GetCurrentFontFile (memmap)");
// CreateCustomFontFileReference ends up calling
// DWriteFontCollectionProxy::CreateStreamFromKey.
- return factory_->CreateCustomFontFileReference(
+ HRESULT hr = factory_->CreateCustomFontFileReference(
reinterpret_cast<const void*>(file_names_[current_file_].c_str()),
(file_names_[current_file_].length() + 1) * sizeof(base::char16),
loader_.Get() /*IDWriteFontFileLoader*/, file);
+ DCHECK(SUCCEEDED(hr));
+ return hr;
}
HRESULT FontFileEnumerator::MoveNext(BOOL* has_current_file) {
diff --git a/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.h b/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.h
index bdee58f8d76..63d1f54316b 100644
--- a/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.h
+++ b/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win.h
@@ -64,8 +64,7 @@ class CONTENT_EXPORT DWriteFontCollectionProxy
IDWriteFontFileStream** font_file_stream) override;
HRESULT STDMETHODCALLTYPE
- RuntimeClassInitialize(IDWriteFactory* factory,
- const base::Callback<IPC::Sender*(void)>& sender);
+ RuntimeClassInitialize(IDWriteFactory* factory, IPC::Sender* sender_override);
void Unregister();
@@ -77,11 +76,13 @@ class CONTENT_EXPORT DWriteFontCollectionProxy
bool CreateFamily(UINT32 family_index);
private:
+ IPC::Sender* GetSender();
+
Microsoft::WRL::ComPtr<IDWriteFactory> factory_;
std::vector<Microsoft::WRL::ComPtr<DWriteFontFamilyProxy>> families_;
std::map<base::string16, UINT32> family_names_;
UINT32 family_count_ = UINT_MAX;
- base::Callback<IPC::Sender*(void)> sender_;
+ IPC::Sender* sender_override_;
DISALLOW_ASSIGN(DWriteFontCollectionProxy);
};
diff --git a/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win_unittest.cc b/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win_unittest.cc
index 0756b9f2573..88c02eeb003 100644
--- a/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win_unittest.cc
+++ b/chromium/content/child/dwrite_font_proxy/dwrite_font_proxy_win_unittest.cc
@@ -8,8 +8,9 @@
#include <shlobj.h>
#include <wrl.h>
+#include <memory>
+
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "content/common/dwrite_font_proxy_messages.h"
#include "content/common/view_messages.h"
#include "content/test/dwrite_font_fake_sender_win.h"
@@ -47,8 +48,7 @@ class DWriteFontProxyUnitTest : public testing::Test {
fake_collection_ = new FakeFontCollection();
SetupFonts(fake_collection_.get());
mswr::MakeAndInitialize<DWriteFontCollectionProxy>(
- &collection_, factory.Get(),
- base::Bind(&FakeFontCollection::GetTrackingSender, fake_collection_));
+ &collection_, factory.Get(), fake_collection_->GetTrackingSender());
}
~DWriteFontProxyUnitTest() override {
diff --git a/chromium/content/child/fileapi/webfilesystem_impl.cc b/chromium/content/child/fileapi/webfilesystem_impl.cc
index 75b1ec0e7c5..141b5de7426 100644
--- a/chromium/content/child/fileapi/webfilesystem_impl.cc
+++ b/chromium/content/child/fileapi/webfilesystem_impl.cc
@@ -103,8 +103,7 @@ void CallDispatcherOnMainThread(
main_thread_task_runner->PostTask(
FROM_HERE,
base::Bind(&CallDispatcherOnMainThread<Method, Params>,
- main_thread_task_runner, method, params,
- scoped_refptr<WaitableCallbackResults>()));
+ main_thread_task_runner, method, params, nullptr));
if (!waitable_results)
return;
waitable_results->WaitAndRun();
@@ -424,10 +423,10 @@ void WebFileSystemImpl::openFileSystem(
static_cast<storage::FileSystemType>(type),
base::Bind(&OpenFileSystemCallbackAdapter,
base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- waitable_results),
+ base::RetainedRef(waitable_results)),
base::Bind(&StatusCallbackAdapter,
base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- waitable_results)),
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -442,10 +441,10 @@ void WebFileSystemImpl::resolveURL(
MakeTuple(GURL(filesystem_url),
base::Bind(&ResolveURLCallbackAdapter,
base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- waitable_results),
+ base::RetainedRef(waitable_results)),
base::Bind(&StatusCallbackAdapter,
base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- waitable_results)),
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -462,7 +461,7 @@ void WebFileSystemImpl::deleteFileSystem(
static_cast<storage::FileSystemType>(type),
base::Bind(&StatusCallbackAdapter,
base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- waitable_results)),
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -478,7 +477,7 @@ void WebFileSystemImpl::move(
MakeTuple(GURL(src_path), GURL(dest_path),
base::Bind(&StatusCallbackAdapter,
base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- waitable_results)),
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -494,7 +493,7 @@ void WebFileSystemImpl::copy(
MakeTuple(GURL(src_path), GURL(dest_path),
base::Bind(&StatusCallbackAdapter,
base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- waitable_results)),
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -509,7 +508,7 @@ void WebFileSystemImpl::remove(
MakeTuple(GURL(path), false /* recursive */,
base::Bind(&StatusCallbackAdapter,
base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- waitable_results)),
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -524,7 +523,7 @@ void WebFileSystemImpl::removeRecursively(
MakeTuple(GURL(path), true /* recursive */,
base::Bind(&StatusCallbackAdapter,
base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- waitable_results)),
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -536,12 +535,13 @@ void WebFileSystemImpl::readMetadata(
MaybeCreateWaitableResults(callbacks, callbacks_id);
CallDispatcherOnMainThread(
main_thread_task_runner_, &FileSystemDispatcher::ReadMetadata,
- MakeTuple(GURL(path), base::Bind(&ReadMetadataCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(),
- callbacks_id, waitable_results),
+ MakeTuple(GURL(path),
+ base::Bind(&ReadMetadataCallbackAdapter,
+ base::ThreadTaskRunnerHandle::Get(), callbacks_id,
+ base::RetainedRef(waitable_results)),
base::Bind(&StatusCallbackAdapter,
base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- waitable_results)),
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -557,7 +557,7 @@ void WebFileSystemImpl::createFile(
MakeTuple(GURL(path), exclusive,
base::Bind(&StatusCallbackAdapter,
base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- waitable_results)),
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -573,7 +573,7 @@ void WebFileSystemImpl::createDirectory(
MakeTuple(GURL(path), exclusive, false /* recursive */,
base::Bind(&StatusCallbackAdapter,
base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- waitable_results)),
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -588,7 +588,7 @@ void WebFileSystemImpl::fileExists(
MakeTuple(GURL(path), false /* directory */,
base::Bind(&StatusCallbackAdapter,
base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- waitable_results)),
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -603,7 +603,7 @@ void WebFileSystemImpl::directoryExists(
MakeTuple(GURL(path), true /* directory */,
base::Bind(&StatusCallbackAdapter,
base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- waitable_results)),
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -615,12 +615,13 @@ int WebFileSystemImpl::readDirectory(
MaybeCreateWaitableResults(callbacks, callbacks_id);
CallDispatcherOnMainThread(
main_thread_task_runner_, &FileSystemDispatcher::ReadDirectory,
- MakeTuple(GURL(path), base::Bind(&ReadDirectoryCallbackAdapter,
- base::ThreadTaskRunnerHandle::Get(),
- callbacks_id, waitable_results),
+ MakeTuple(GURL(path),
+ base::Bind(&ReadDirectoryCallbackAdapter,
+ base::ThreadTaskRunnerHandle::Get(), callbacks_id,
+ base::RetainedRef(waitable_results)),
base::Bind(&StatusCallbackAdapter,
base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- waitable_results)),
+ base::RetainedRef(waitable_results))),
waitable_results.get());
return callbacks_id;
}
@@ -637,11 +638,11 @@ void WebFileSystemImpl::createFileWriter(
MakeTuple(GURL(path),
base::Bind(&CreateFileWriterCallbackAdapter,
base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- waitable_results, main_thread_task_runner_,
- GURL(path), client),
+ base::RetainedRef(waitable_results),
+ main_thread_task_runner_, GURL(path), client),
base::Bind(&StatusCallbackAdapter,
base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- waitable_results)),
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
@@ -656,10 +657,11 @@ void WebFileSystemImpl::createSnapshotFileAndReadMetadata(
MakeTuple(GURL(path),
base::Bind(&CreateSnapshotFileCallbackAdapter,
base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- waitable_results, main_thread_task_runner_),
+ base::RetainedRef(waitable_results),
+ main_thread_task_runner_),
base::Bind(&StatusCallbackAdapter,
base::ThreadTaskRunnerHandle::Get(), callbacks_id,
- waitable_results)),
+ base::RetainedRef(waitable_results))),
waitable_results.get());
}
diff --git a/chromium/content/child/fileapi/webfilewriter_base_unittest.cc b/chromium/content/child/fileapi/webfilewriter_base_unittest.cc
index 686cd4ee53f..94ad8178564 100644
--- a/chromium/content/child/fileapi/webfilewriter_base_unittest.cc
+++ b/chromium/content/child/fileapi/webfilewriter_base_unittest.cc
@@ -6,9 +6,10 @@
#include <stdint.h>
+#include <memory>
+
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -178,7 +179,7 @@ class FileWriterTest : public testing::Test,
fail_error_received_ = static_cast<blink::WebFileError>(0);
}
- scoped_ptr<TestableFileWriter> testable_writer_;
+ std::unique_ptr<TestableFileWriter> testable_writer_;
bool delete_in_client_callback_;
// Observed WebFileWriterClient artifacts.
diff --git a/chromium/content/child/fileapi/webfilewriter_impl.cc b/chromium/content/child/fileapi/webfilewriter_impl.cc
index c62044e9c49..350f7fb07e8 100644
--- a/chromium/content/child/fileapi/webfilewriter_impl.cc
+++ b/chromium/content/child/fileapi/webfilewriter_impl.cc
@@ -122,7 +122,7 @@ class WebFileWriterImpl::WriterBridge
const bool running_on_worker_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
int written_bytes_;
- scoped_ptr<base::WaitableEvent> waitable_event_;
+ std::unique_ptr<base::WaitableEvent> waitable_event_;
base::Closure results_closure_;
};
diff --git a/chromium/content/common/font_warmup_win.cc b/chromium/content/child/font_warmup_win.cc
index cdd1d0f2dba..e3c07115ff0 100644
--- a/chromium/content/common/font_warmup_win.cc
+++ b/chromium/content/child/font_warmup_win.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/common/font_warmup_win.h"
+#include "content/child/font_warmup_win.h"
#include <dwrite.h>
#include <stdint.h>
@@ -22,12 +22,9 @@
#include "base/trace_event/trace_event.h"
#include "base/win/iat_patch_function.h"
#include "base/win/windows_version.h"
-#include "content/public/common/dwrite_font_platform_win.h"
#include "ppapi/shared_impl/proxy_lock.h"
#include "skia/ext/fontmgr_default_win.h"
#include "skia/ext/refptr.h"
-#include "third_party/WebKit/public/web/win/WebFontRendering.h"
-#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/ports/SkFontMgr.h"
#include "third_party/skia/include/ports/SkTypeface_win.h"
@@ -99,55 +96,6 @@ NTSTATUS WINAPI NtALpcConnectPortPatch(HANDLE* port_handle,
return STATUS_ACCESS_DENIED;
}
-// Windows-only DirectWrite support. These warm up the DirectWrite paths
-// before sandbox lock down to allow Skia access to the Font Manager service.
-void CreateDirectWriteFactory(IDWriteFactory** factory) {
- typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc;
- HMODULE dwrite_dll = LoadLibraryW(L"dwrite.dll");
- // TODO(scottmg): Temporary code to track crash in http://crbug.com/387867.
- if (!dwrite_dll) {
- DWORD load_library_get_last_error = GetLastError();
- base::debug::Alias(&dwrite_dll);
- base::debug::Alias(&load_library_get_last_error);
- CHECK(false);
- }
-
- PatchServiceManagerCalls();
-
- DWriteCreateFactoryProc dwrite_create_factory_proc =
- reinterpret_cast<DWriteCreateFactoryProc>(
- GetProcAddress(dwrite_dll, "DWriteCreateFactory"));
- // TODO(scottmg): Temporary code to track crash in http://crbug.com/387867.
- if (!dwrite_create_factory_proc) {
- DWORD get_proc_address_get_last_error = GetLastError();
- base::debug::Alias(&dwrite_create_factory_proc);
- base::debug::Alias(&get_proc_address_get_last_error);
- CHECK(false);
- }
- CHECK(SUCCEEDED(dwrite_create_factory_proc(
- DWRITE_FACTORY_TYPE_ISOLATED, __uuidof(IDWriteFactory),
- reinterpret_cast<IUnknown**>(factory))));
-}
-
-HRESULT STDMETHODCALLTYPE StubFontCollection(IDWriteFactory* factory,
- IDWriteFontCollection** col,
- BOOL checkUpdates) {
- // We always return pre-created font collection from here.
- IDWriteFontCollection* custom_collection = GetCustomFontCollection(factory);
- DCHECK(custom_collection != nullptr);
- *col = custom_collection;
- return S_OK;
-}
-
-void PatchDWriteFactory(IDWriteFactory* factory) {
- const unsigned int kGetSystemFontCollectionVTableIndex = 3;
-
- PROC* vtable = *reinterpret_cast<PROC**>(factory);
- PROC* function_ptr = &vtable[kGetSystemFontCollectionVTableIndex];
- void* stub_function = &StubFontCollection;
- base::win::ModifyCode(function_ptr, &stub_function, sizeof(PROC));
-}
-
// Class to fake out a DC or a Font object. Maintains a reference to a
// SkTypeFace to emulate the simple operation of a DC and Font.
class FakeGdiObject : public base::RefCountedThreadSafe<FakeGdiObject> {
@@ -465,33 +413,9 @@ void PatchServiceManagerCalls() {
DCHECK(patched == 0);
}
-void DoPreSandboxWarmupForTypeface(SkTypeface* typeface) {
- SkPaint paint_warmup;
- paint_warmup.setTypeface(typeface);
- wchar_t glyph = L'S';
- paint_warmup.measureText(&glyph, 2);
-}
-
-SkFontMgr* GetPreSandboxWarmupFontMgr() {
- if (!g_warmup_fontmgr) {
- IDWriteFactory* factory;
- CreateDirectWriteFactory(&factory);
-
- GetCustomFontCollection(factory);
-
- PatchDWriteFactory(factory);
-
- blink::WebFontRendering::setDirectWriteFactory(factory);
- g_warmup_fontmgr = SkFontMgr_New_DirectWrite(factory);
- }
- return g_warmup_fontmgr;
-}
-
GdiFontPatchData* PatchGdiFontEnumeration(const base::FilePath& path) {
- if (ShouldUseDirectWriteFontProxyFieldTrial() && !g_warmup_fontmgr)
+ if (!g_warmup_fontmgr)
g_warmup_fontmgr = SkFontMgr_New_DirectWrite();
- // If not using the font proxy, we assume |g_warmup_fontmgr| is already
- // initialized before this function is called.
DCHECK(g_warmup_fontmgr);
return new GdiFontPatchDataImpl(path);
}
@@ -508,19 +432,4 @@ void SetPreSandboxWarmupFontMgrForTesting(SkFontMgr* fontmgr) {
g_warmup_fontmgr = fontmgr;
}
-void WarmupDirectWrite() {
- TRACE_EVENT0("startup", "content::WarmupDirectWrite");
-
- // The objects used here are intentionally not freed as we want the Skia
- // code to use these objects after warmup.
- SetDefaultSkiaFactory(GetPreSandboxWarmupFontMgr());
-
- // We need to warm up *some* font for DirectWrite. Note that we don't use
- // a monospace as would be nice in an attempt to avoid a small startup time
- // regression, see http://crbug.com/463613.
- skia::RefPtr<SkTypeface> hud_typeface = skia::AdoptRef(
- GetPreSandboxWarmupFontMgr()->legacyCreateTypeface("Times New Roman", 0));
- DoPreSandboxWarmupForTypeface(hud_typeface.get());
-}
-
} // namespace content
diff --git a/chromium/content/common/font_warmup_win.h b/chromium/content/child/font_warmup_win.h
index 8539b9ec0b2..9bbdaae4119 100644
--- a/chromium/content/common/font_warmup_win.h
+++ b/chromium/content/child/font_warmup_win.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_COMMON_FONT_WARMUP_WIN_H_
-#define CONTENT_COMMON_FONT_WARMUP_WIN_H_
+#ifndef CONTENT_CHILD_FONT_WARMUP_WIN_H_
+#define CONTENT_CHILD_FONT_WARMUP_WIN_H_
#include <stddef.h>
@@ -16,14 +16,6 @@ class SkTypeface;
namespace content {
-// Make necessary calls to cache the data for a given font, used before
-// sandbox lockdown.
-CONTENT_EXPORT void DoPreSandboxWarmupForTypeface(SkTypeface* typeface);
-
-// Get the shared font manager used during pre-sandbox warmup for DirectWrite
-// fonts.
-CONTENT_EXPORT SkFontMgr* GetPreSandboxWarmupFontMgr();
-
class GdiFontPatchData {
public:
virtual ~GdiFontPatchData() {}
@@ -50,9 +42,6 @@ CONTENT_EXPORT void ResetEmulatedGdiHandlesForTesting();
// for testing the implementation.
CONTENT_EXPORT void SetPreSandboxWarmupFontMgrForTesting(SkFontMgr* fontmgr);
-// Warmup the direct write font manager for content processes.
-CONTENT_EXPORT void WarmupDirectWrite();
-
// Directwrite connects to the font cache service to retrieve information about
// fonts installed on the system etc. This works well outside the sandbox and
// within the sandbox as long as the lpc connection maintained by the current
@@ -73,4 +62,4 @@ CONTENT_EXPORT void PatchServiceManagerCalls();
} // namespace content
-#endif // CONTENT_COMMON_FONT_WARMUP_WIN_H_
+#endif // CONTENT_CHILD_FONT_WARMUP_WIN_H_
diff --git a/chromium/content/common/font_warmup_win_unittest.cc b/chromium/content/child/font_warmup_win_unittest.cc
index 362373fd25f..91c0c84393c 100644
--- a/chromium/content/common/font_warmup_win_unittest.cc
+++ b/chromium/content/child/font_warmup_win_unittest.cc
@@ -2,16 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/common/font_warmup_win.h"
+#include "content/child/font_warmup_win.h"
#include <stddef.h>
#include <stdint.h>
+#include <memory>
#include <vector>
#include "base/files/file_path.h"
#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
#include "base/sys_byteorder.h"
#include "base/win/windows_version.h"
#include "skia/ext/refptr.h"
@@ -254,7 +254,7 @@ TEST(GDIFontEmulationTest, CreateDeleteDCSuccess) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
TestSkFontMgr fontmgr;
- scoped_ptr<GdiFontPatchData> patch_data(SetupTest());
+ std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_FALSE(!patch_data);
HDC hdc = CreateCompatibleDC(0);
@@ -268,7 +268,7 @@ TEST(GDIFontEmulationTest, CreateUniqueDCSuccess) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
TestSkFontMgr fontmgr;
- scoped_ptr<GdiFontPatchData> patch_data(SetupTest());
+ std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
HDC hdc1 = CreateCompatibleDC(0);
@@ -286,7 +286,7 @@ TEST(GDIFontEmulationTest, CreateFontSuccess) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
TestSkFontMgr fontmgr;
- scoped_ptr<GdiFontPatchData> patch_data(SetupTest());
+ std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
LOGFONTW logfont = {0};
InitLogFont(&logfont, kTestFontFamilyW);
@@ -300,7 +300,7 @@ TEST(GDIFontEmulationTest, CreateFontFailure) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
TestSkFontMgr fontmgr;
- scoped_ptr<GdiFontPatchData> patch_data(SetupTest());
+ std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
LOGFONTW logfont = {0};
InitLogFont(&logfont, kTestFontFamilyInvalid);
@@ -312,7 +312,7 @@ TEST(GDIFontEmulationTest, EnumFontFamilySuccess) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
TestSkFontMgr fontmgr;
- scoped_ptr<GdiFontPatchData> patch_data(SetupTest());
+ std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
HDC hdc = CreateCompatibleDC(0);
EXPECT_NE(hdc, nullptr);
@@ -327,7 +327,7 @@ TEST(GDIFontEmulationTest, EnumFontFamilyFailure) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
TestSkFontMgr fontmgr;
- scoped_ptr<GdiFontPatchData> patch_data(SetupTest());
+ std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
HDC hdc = CreateCompatibleDC(0);
EXPECT_NE(hdc, nullptr);
@@ -342,7 +342,7 @@ TEST(GDIFontEmulationTest, DeleteDCFailure) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
TestSkFontMgr fontmgr;
- scoped_ptr<GdiFontPatchData> patch_data(SetupTest());
+ std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
HDC hdc = reinterpret_cast<HDC>(0x55667788);
EXPECT_FALSE(DeleteDC(hdc));
@@ -352,7 +352,7 @@ TEST(GDIFontEmulationTest, DeleteObjectFailure) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
TestSkFontMgr fontmgr;
- scoped_ptr<GdiFontPatchData> patch_data(SetupTest());
+ std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
HFONT font = reinterpret_cast<HFONT>(0x88aabbcc);
EXPECT_FALSE(DeleteObject(font));
@@ -362,7 +362,7 @@ TEST(GDIFontEmulationTest, GetFontDataSizeSuccess) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
TestSkFontMgr fontmgr;
- scoped_ptr<GdiFontPatchData> patch_data(SetupTest());
+ std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
HDC hdc = CreateCompatibleDC(0);
EXPECT_NE(hdc, nullptr);
@@ -382,7 +382,7 @@ TEST(GDIFontEmulationTest, GetFontDataInvalidTagSuccess) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
TestSkFontMgr fontmgr;
- scoped_ptr<GdiFontPatchData> patch_data(SetupTest());
+ std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
HDC hdc = CreateCompatibleDC(0);
EXPECT_NE(hdc, nullptr);
@@ -401,7 +401,7 @@ TEST(GDIFontEmulationTest, GetFontDataInvalidFontSuccess) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
TestSkFontMgr fontmgr;
- scoped_ptr<GdiFontPatchData> patch_data(SetupTest());
+ std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
HDC hdc = CreateCompatibleDC(0);
EXPECT_NE(hdc, nullptr);
@@ -414,7 +414,7 @@ TEST(GDIFontEmulationTest, GetFontDataDataSuccess) {
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return;
TestSkFontMgr fontmgr;
- scoped_ptr<GdiFontPatchData> patch_data(SetupTest());
+ std::unique_ptr<GdiFontPatchData> patch_data(SetupTest());
EXPECT_NE(patch_data, nullptr);
HDC hdc = CreateCompatibleDC(0);
EXPECT_NE(hdc, nullptr);
diff --git a/chromium/content/child/ftp_directory_listing_response_delegate.cc b/chromium/content/child/ftp_directory_listing_response_delegate.cc
index 5bf21a75680..0a24bbf1941 100644
--- a/chromium/content/child/ftp_directory_listing_response_delegate.cc
+++ b/chromium/content/child/ftp_directory_listing_response_delegate.cc
@@ -63,10 +63,10 @@ FtpDirectoryListingResponseDelegate::FtpDirectoryListingResponseDelegate(
const WebURLResponse& response)
: client_(client),
loader_(loader) {
- if (response.extraData()) {
+ if (response.getExtraData()) {
// extraData can be NULL during tests.
WebURLResponseExtraDataImpl* extra_data =
- static_cast<WebURLResponseExtraDataImpl*>(response.extraData());
+ static_cast<WebURLResponseExtraDataImpl*>(response.getExtraData());
extra_data->set_is_ftp_directory_listing(true);
}
Init(response.url());
@@ -111,8 +111,9 @@ void FtpDirectoryListingResponseDelegate::OnCompletedRequest() {
}
void FtpDirectoryListingResponseDelegate::Init(const GURL& response_url) {
- net::UnescapeRule::Type unescape_rules = net::UnescapeRule::SPACES |
- net::UnescapeRule::URL_SPECIAL_CHARS;
+ net::UnescapeRule::Type unescape_rules =
+ net::UnescapeRule::SPACES |
+ net::UnescapeRule::URL_SPECIAL_CHARS_EXCEPT_PATH_SEPARATORS;
std::string unescaped_path = net::UnescapeURLComponent(response_url.path(),
unescape_rules);
SendDataToClient(net::GetDirectoryListingHeader(
diff --git a/chromium/content/child/geofencing/geofencing_dispatcher.cc b/chromium/content/child/geofencing/geofencing_dispatcher.cc
index fcc746cbe50..7342e11ad9e 100644
--- a/chromium/content/child/geofencing/geofencing_dispatcher.cc
+++ b/chromium/content/child/geofencing/geofencing_dispatcher.cc
@@ -7,8 +7,9 @@
#include <stddef.h>
#include <stdint.h>
+#include <memory>
+
#include "base/lazy_instance.h"
-#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/thread_task_runner_handle.h"
#include "content/child/service_worker/web_service_worker_registration_impl.h"
diff --git a/chromium/content/child/geofencing/geofencing_dispatcher.h b/chromium/content/child/geofencing/geofencing_dispatcher.h
index 951c0f881e6..bc9986bb9ad 100644
--- a/chromium/content/child/geofencing/geofencing_dispatcher.h
+++ b/chromium/content/child/geofencing/geofencing_dispatcher.h
@@ -6,12 +6,12 @@
#define CONTENT_CHILD_GEOFENCING_GEOFENCING_DISPATCHER_H_
#include <map>
+#include <memory>
#include <string>
#include "base/id_map.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "content/common/geofencing_types.h"
#include "content/public/child/worker_thread.h"
#include "third_party/WebKit/public/platform/WebGeofencingProvider.h"
diff --git a/chromium/content/child/indexed_db/indexed_db_dispatcher.cc b/chromium/content/child/indexed_db/indexed_db_dispatcher.cc
index 809aa582621..53113b1916d 100644
--- a/chromium/content/child/indexed_db/indexed_db_dispatcher.cc
+++ b/chromium/content/child/indexed_db/indexed_db_dispatcher.cc
@@ -88,7 +88,6 @@ WebIDBMetadata IndexedDBDispatcher::ConvertMetadata(
web_metadata.id = idb_metadata.id;
web_metadata.name = idb_metadata.name;
web_metadata.version = idb_metadata.version;
- web_metadata.intVersion = idb_metadata.int_version;
web_metadata.maxObjectStoreId = idb_metadata.max_object_store_id;
web_metadata.objectStores =
WebVector<WebIDBMetadata::ObjectStore>(idb_metadata.object_stores.size());
@@ -152,8 +151,8 @@ void IndexedDBDispatcher::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksUpgradeNeeded, OnUpgradeNeeded)
IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksForcedClose,
OnForcedClose)
- IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksIntVersionChange,
- OnIntVersionChange)
+ IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksVersionChange,
+ OnVersionChange)
IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksAbort, OnAbort)
IPC_MESSAGE_HANDLER(IndexedDBMsg_DatabaseCallbacksComplete, OnComplete)
IPC_MESSAGE_UNHANDLED(handled = false)
@@ -176,7 +175,7 @@ void IndexedDBDispatcher::RequestIDBCursorAdvance(
// Reset all cursor prefetch caches except for this cursor.
ResetCursorPrefetchCaches(transaction_id, ipc_cursor_id);
- scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
+ std::unique_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
int32_t ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
Send(new IndexedDBHostMsg_CursorAdvance(
@@ -192,7 +191,7 @@ void IndexedDBDispatcher::RequestIDBCursorContinue(
// Reset all cursor prefetch caches except for this cursor.
ResetCursorPrefetchCaches(transaction_id, ipc_cursor_id);
- scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
+ std::unique_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
int32_t ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
Send(new IndexedDBHostMsg_CursorContinue(
@@ -203,7 +202,7 @@ void IndexedDBDispatcher::RequestIDBCursorPrefetch(
int n,
WebIDBCallbacks* callbacks_ptr,
int32_t ipc_cursor_id) {
- scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
+ std::unique_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
int32_t ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
Send(new IndexedDBHostMsg_CursorPrefetch(
@@ -223,9 +222,9 @@ void IndexedDBDispatcher::RequestIDBFactoryOpen(
int64_t transaction_id,
WebIDBCallbacks* callbacks_ptr,
WebIDBDatabaseCallbacks* database_callbacks_ptr,
- const std::string& database_identifier) {
- scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
- scoped_ptr<WebIDBDatabaseCallbacks> database_callbacks(
+ const GURL& origin) {
+ std::unique_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
+ std::unique_ptr<WebIDBDatabaseCallbacks> database_callbacks(
database_callbacks_ptr);
IndexedDBHostMsg_FactoryOpen_Params params;
@@ -233,7 +232,7 @@ void IndexedDBDispatcher::RequestIDBFactoryOpen(
params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
params.ipc_database_callbacks_id =
pending_database_callbacks_.Add(database_callbacks.release());
- params.database_identifier = database_identifier;
+ params.origin = origin;
params.name = name;
params.transaction_id = transaction_id;
params.version = version;
@@ -242,26 +241,26 @@ void IndexedDBDispatcher::RequestIDBFactoryOpen(
void IndexedDBDispatcher::RequestIDBFactoryGetDatabaseNames(
WebIDBCallbacks* callbacks_ptr,
- const std::string& database_identifier) {
- scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
+ const GURL& origin) {
+ std::unique_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
IndexedDBHostMsg_FactoryGetDatabaseNames_Params params;
params.ipc_thread_id = CurrentWorkerId();
params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
- params.database_identifier = database_identifier;
+ params.origin = origin;
Send(new IndexedDBHostMsg_FactoryGetDatabaseNames(params));
}
void IndexedDBDispatcher::RequestIDBFactoryDeleteDatabase(
const base::string16& name,
WebIDBCallbacks* callbacks_ptr,
- const std::string& database_identifier) {
- scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
+ const GURL& origin) {
+ std::unique_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
IndexedDBHostMsg_FactoryDeleteDatabase_Params params;
params.ipc_thread_id = CurrentWorkerId();
params.ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
- params.database_identifier = database_identifier;
+ params.origin = origin;
params.name = name;
Send(new IndexedDBHostMsg_FactoryDeleteDatabase(params));
}
@@ -287,7 +286,7 @@ void IndexedDBDispatcher::RequestIDBDatabaseCreateTransaction(
WebIDBDatabaseCallbacks* database_callbacks_ptr,
WebVector<long long> object_store_ids,
blink::WebIDBTransactionMode mode) {
- scoped_ptr<WebIDBDatabaseCallbacks> database_callbacks(
+ std::unique_ptr<WebIDBDatabaseCallbacks> database_callbacks(
database_callbacks_ptr);
IndexedDBHostMsg_DatabaseCreateTransaction_Params params;
params.ipc_thread_id = CurrentWorkerId();
@@ -477,7 +476,7 @@ void IndexedDBDispatcher::RequestIDBDatabaseClear(
int64_t object_store_id,
WebIDBCallbacks* callbacks_ptr) {
ResetCursorPrefetchCaches(transaction_id, kAllCursors);
- scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
+ std::unique_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
int32_t ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
Send(new IndexedDBHostMsg_DatabaseClear(CurrentWorkerId(),
ipc_callbacks_id,
@@ -781,10 +780,10 @@ void IndexedDBDispatcher::OnForcedClose(int32_t ipc_thread_id,
callbacks->onForcedClose();
}
-void IndexedDBDispatcher::OnIntVersionChange(int32_t ipc_thread_id,
- int32_t ipc_database_callbacks_id,
- int64_t old_version,
- int64_t new_version) {
+void IndexedDBDispatcher::OnVersionChange(int32_t ipc_thread_id,
+ int32_t ipc_database_callbacks_id,
+ int64_t old_version,
+ int64_t new_version) {
DCHECK_EQ(ipc_thread_id, CurrentWorkerId());
WebIDBDatabaseCallbacks* callbacks =
pending_database_callbacks_.Lookup(ipc_database_callbacks_id);
diff --git a/chromium/content/child/indexed_db/indexed_db_dispatcher.h b/chromium/content/child/indexed_db/indexed_db_dispatcher.h
index 993349d4707..a69f20ebbc9 100644
--- a/chromium/content/child/indexed_db/indexed_db_dispatcher.h
+++ b/chromium/content/child/indexed_db/indexed_db_dispatcher.h
@@ -25,6 +25,7 @@
#include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBCallbacks.h"
#include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseCallbacks.h"
#include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBTypes.h"
+#include "url/gurl.h"
struct IndexedDBDatabaseMetadata;
struct IndexedDBMsg_CallbacksSuccessCursorContinue_Params;
@@ -73,20 +74,19 @@ class CONTENT_EXPORT IndexedDBDispatcher : public WorkerThread::Observer {
// This method is virtual so it can be overridden in unit tests.
virtual bool Send(IPC::Message* msg);
- void RequestIDBFactoryGetDatabaseNames(
- blink::WebIDBCallbacks* callbacks,
- const std::string& database_identifier);
+ void RequestIDBFactoryGetDatabaseNames(blink::WebIDBCallbacks* callbacks,
+ const GURL& origin);
void RequestIDBFactoryOpen(const base::string16& name,
int64_t version,
int64_t transaction_id,
blink::WebIDBCallbacks* callbacks,
blink::WebIDBDatabaseCallbacks* database_callbacks,
- const std::string& database_identifier);
+ const GURL& origin);
void RequestIDBFactoryDeleteDatabase(const base::string16& name,
blink::WebIDBCallbacks* callbacks,
- const std::string& database_identifier);
+ const GURL& origin);
// This method is virtual so it can be overridden in unit tests.
virtual void RequestIDBCursorAdvance(unsigned long count,
@@ -195,7 +195,7 @@ class CONTENT_EXPORT IndexedDBDispatcher : public WorkerThread::Observer {
template <typename T>
void init_params(T* params, blink::WebIDBCallbacks* callbacks_ptr) {
- scoped_ptr<blink::WebIDBCallbacks> callbacks(callbacks_ptr);
+ std::unique_ptr<blink::WebIDBCallbacks> callbacks(callbacks_ptr);
params->ipc_thread_id = CurrentWorkerId();
params->ipc_callbacks_id = pending_callbacks_.Add(callbacks.release());
}
@@ -242,10 +242,10 @@ class CONTENT_EXPORT IndexedDBDispatcher : public WorkerThread::Observer {
int32_t ipc_database_id,
int64_t transaction_id);
void OnForcedClose(int32_t ipc_thread_id, int32_t ipc_database_id);
- void OnIntVersionChange(int32_t ipc_thread_id,
- int32_t ipc_database_id,
- int64_t old_version,
- int64_t new_version);
+ void OnVersionChange(int32_t ipc_thread_id,
+ int32_t ipc_database_id,
+ int64_t old_version,
+ int64_t new_version);
// Reset cursor prefetch caches for all cursors except exception_cursor_id.
void ResetCursorPrefetchCaches(int64_t transaction_id,
diff --git a/chromium/content/child/indexed_db/indexed_db_dispatcher_unittest.cc b/chromium/content/child/indexed_db/indexed_db_dispatcher_unittest.cc
index e9a0cc911cc..03b880870da 100644
--- a/chromium/content/child/indexed_db/indexed_db_dispatcher_unittest.cc
+++ b/chromium/content/child/indexed_db/indexed_db_dispatcher_unittest.cc
@@ -2,15 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "content/child/indexed_db/indexed_db_dispatcher.h"
+
#include <stddef.h>
#include <stdint.h>
+#include <memory>
+
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
#include "base/values.h"
-#include "content/child/indexed_db/indexed_db_dispatcher.h"
#include "content/child/indexed_db/mock_webidbcallbacks.h"
#include "content/child/indexed_db/webidbcursor_impl.h"
#include "content/child/thread_safe_sender.h"
@@ -153,15 +155,16 @@ TEST_F(IndexedDBDispatcherTest, CursorTransactionId) {
// First case: successful cursor open.
{
- scoped_ptr<WebIDBCursor> cursor;
+ std::unique_ptr<WebIDBCursor> cursor;
EXPECT_EQ(0UL, dispatcher.cursor_transaction_ids_.size());
auto callbacks = new StrictMock<MockWebIDBCallbacks>();
// Reference first param (cursor) to keep it alive.
// TODO(cmumford): Cleanup (and below) once std::addressof() is allowed.
ON_CALL(*callbacks, onSuccess(testing::A<WebIDBCursor*>(), _, _, _))
- .WillByDefault(WithArgs<0>(Invoke(&cursor.operator=(nullptr),
- &scoped_ptr<WebIDBCursor>::reset)));
+ .WillByDefault(
+ WithArgs<0>(Invoke(&cursor.operator=(nullptr),
+ &std::unique_ptr<WebIDBCursor>::reset)));
EXPECT_CALL(*callbacks, onSuccess(testing::A<WebIDBCursor*>(), _, _, _))
.Times(1);
@@ -252,7 +255,7 @@ class MockCursor : public WebIDBCursorImpl {
} // namespace
TEST_F(IndexedDBDispatcherTest, CursorReset) {
- scoped_ptr<WebIDBCursor> cursor;
+ std::unique_ptr<WebIDBCursor> cursor;
MockDispatcher dispatcher(thread_safe_sender_.get());
const int32_t ipc_database_id = 0;
@@ -266,14 +269,12 @@ TEST_F(IndexedDBDispatcherTest, CursorReset) {
const int cursor2_transaction_id = 2;
const int other_transaction_id = 3;
- scoped_ptr<MockCursor> cursor1(
- new MockCursor(WebIDBCursorImpl::kInvalidCursorId,
- cursor1_transaction_id,
+ std::unique_ptr<MockCursor> cursor1(
+ new MockCursor(WebIDBCursorImpl::kInvalidCursorId, cursor1_transaction_id,
thread_safe_sender_.get()));
- scoped_ptr<MockCursor> cursor2(
- new MockCursor(WebIDBCursorImpl::kInvalidCursorId,
- cursor2_transaction_id,
+ std::unique_ptr<MockCursor> cursor2(
+ new MockCursor(WebIDBCursorImpl::kInvalidCursorId, cursor2_transaction_id,
thread_safe_sender_.get()));
dispatcher.cursors_[cursor1_ipc_id] = cursor1.get();
diff --git a/chromium/content/child/indexed_db/webidbcursor_impl.cc b/chromium/content/child/indexed_db/webidbcursor_impl.cc
index fb1c3bbb19c..946b08ddfc0 100644
--- a/chromium/content/child/indexed_db/webidbcursor_impl.cc
+++ b/chromium/content/child/indexed_db/webidbcursor_impl.cc
@@ -54,7 +54,7 @@ void WebIDBCursorImpl::advance(unsigned long count,
WebIDBCallbacks* callbacks_ptr) {
IndexedDBDispatcher* dispatcher =
IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
- scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
+ std::unique_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
if (count <= prefetch_keys_.size()) {
CachedAdvance(count, callbacks.get());
return;
@@ -74,7 +74,7 @@ void WebIDBCursorImpl::continueFunction(const WebIDBKey& key,
WebIDBCallbacks* callbacks_ptr) {
IndexedDBDispatcher* dispatcher =
IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
- scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
+ std::unique_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
if (key.keyType() == blink::WebIDBKeyTypeNull &&
primary_key.keyType() == blink::WebIDBKeyTypeNull) {
diff --git a/chromium/content/child/indexed_db/webidbcursor_impl_unittest.cc b/chromium/content/child/indexed_db/webidbcursor_impl_unittest.cc
index 053542b8a78..e2031ff3c00 100644
--- a/chromium/content/child/indexed_db/webidbcursor_impl_unittest.cc
+++ b/chromium/content/child/indexed_db/webidbcursor_impl_unittest.cc
@@ -2,17 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "content/child/indexed_db/webidbcursor_impl.h"
+
#include <stddef.h>
#include <stdint.h>
+#include <memory>
+
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
+#include "base/memory/ptr_util.h"
#include "base/thread_task_runner_handle.h"
#include "base/values.h"
#include "content/child/indexed_db/indexed_db_dispatcher.h"
#include "content/child/indexed_db/indexed_db_key_builders.h"
#include "content/child/indexed_db/mock_webidbcallbacks.h"
-#include "content/child/indexed_db/webidbcursor_impl.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/indexed_db/indexed_db_key.h"
#include "ipc/ipc_sync_message_filter.h"
@@ -96,7 +99,7 @@ class MockDispatcher : public IndexedDBDispatcher {
int advance_calls_;
int continue_calls_;
int32_t destroyed_cursor_id_;
- scoped_ptr<WebIDBCallbacks> callbacks_;
+ std::unique_ptr<WebIDBCallbacks> callbacks_;
};
class MockContinueCallbacks : public StrictMock<MockWebIDBCallbacks> {
@@ -137,14 +140,14 @@ class WebIDBCursorImplTest : public testing::Test {
thread_safe_sender_ = new ThreadSafeSender(
base::ThreadTaskRunnerHandle::Get(), new MockSyncMessageFilter);
dispatcher_ =
- make_scoped_ptr(new MockDispatcher(thread_safe_sender_.get()));
+ base::WrapUnique(new MockDispatcher(thread_safe_sender_.get()));
}
protected:
base::MessageLoop message_loop_;
WebIDBKey null_key_;
scoped_refptr<ThreadSafeSender> thread_safe_sender_;
- scoped_ptr<MockDispatcher> dispatcher_;
+ std::unique_ptr<MockDispatcher> dispatcher_;
private:
DISALLOW_COPY_AND_ASSIGN(WebIDBCursorImplTest);
diff --git a/chromium/content/child/indexed_db/webidbfactory_impl.cc b/chromium/content/child/indexed_db/webidbfactory_impl.cc
index 4ed0316ef99..770f1328c7a 100644
--- a/chromium/content/child/indexed_db/webidbfactory_impl.cc
+++ b/chromium/content/child/indexed_db/webidbfactory_impl.cc
@@ -5,13 +5,15 @@
#include "content/child/indexed_db/webidbfactory_impl.h"
#include "content/child/indexed_db/indexed_db_dispatcher.h"
+#include "content/child/storage_util.h"
#include "content/child/thread_safe_sender.h"
-#include "third_party/WebKit/public/platform/WebCString.h"
+#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/platform/WebString.h"
using blink::WebIDBCallbacks;
using blink::WebIDBDatabase;
using blink::WebIDBDatabaseCallbacks;
+using blink::WebSecurityOrigin;
using blink::WebString;
namespace content {
@@ -22,11 +24,11 @@ WebIDBFactoryImpl::WebIDBFactoryImpl(ThreadSafeSender* thread_safe_sender)
WebIDBFactoryImpl::~WebIDBFactoryImpl() {}
void WebIDBFactoryImpl::getDatabaseNames(WebIDBCallbacks* callbacks,
- const WebString& database_identifier) {
+ const WebSecurityOrigin& origin) {
IndexedDBDispatcher* dispatcher =
IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
- dispatcher->RequestIDBFactoryGetDatabaseNames(callbacks,
- database_identifier.utf8());
+ dispatcher->RequestIDBFactoryGetDatabaseNames(
+ callbacks, WebSecurityOriginToGURL(origin));
}
void WebIDBFactoryImpl::open(const WebString& name,
@@ -34,24 +36,22 @@ void WebIDBFactoryImpl::open(const WebString& name,
long long transaction_id,
WebIDBCallbacks* callbacks,
WebIDBDatabaseCallbacks* database_callbacks,
- const WebString& database_identifier) {
+ const WebSecurityOrigin& origin) {
IndexedDBDispatcher* dispatcher =
IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
- dispatcher->RequestIDBFactoryOpen(name,
- version,
- transaction_id,
- callbacks,
+
+ dispatcher->RequestIDBFactoryOpen(name, version, transaction_id, callbacks,
database_callbacks,
- database_identifier.utf8());
+ WebSecurityOriginToGURL(origin));
}
void WebIDBFactoryImpl::deleteDatabase(const WebString& name,
WebIDBCallbacks* callbacks,
- const WebString& database_identifier) {
+ const WebSecurityOrigin& origin) {
IndexedDBDispatcher* dispatcher =
IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
- dispatcher->RequestIDBFactoryDeleteDatabase(
- name, callbacks, database_identifier.utf8());
+ dispatcher->RequestIDBFactoryDeleteDatabase(name, callbacks,
+ WebSecurityOriginToGURL(origin));
}
} // namespace content
diff --git a/chromium/content/child/indexed_db/webidbfactory_impl.h b/chromium/content/child/indexed_db/webidbfactory_impl.h
index ad5b8ecad8b..7e2fca92496 100644
--- a/chromium/content/child/indexed_db/webidbfactory_impl.h
+++ b/chromium/content/child/indexed_db/webidbfactory_impl.h
@@ -12,6 +12,7 @@
#include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBFactory.h"
namespace blink {
+class WebSecurityOrigin;
class WebString;
}
@@ -25,16 +26,16 @@ class WebIDBFactoryImpl : public blink::WebIDBFactory {
// See WebIDBFactory.h for documentation on these functions.
void getDatabaseNames(blink::WebIDBCallbacks* callbacks,
- const blink::WebString& database_identifier) override;
+ const blink::WebSecurityOrigin& origin) override;
void open(const blink::WebString& name,
long long version,
long long transaction_id,
blink::WebIDBCallbacks* callbacks,
blink::WebIDBDatabaseCallbacks* databaseCallbacks,
- const blink::WebString& database_identifier) override;
+ const blink::WebSecurityOrigin& origin) override;
void deleteDatabase(const blink::WebString& name,
blink::WebIDBCallbacks* callbacks,
- const blink::WebString& database_identifier) override;
+ const blink::WebSecurityOrigin& origin) override;
private:
scoped_refptr<ThreadSafeSender> thread_safe_sender_;
diff --git a/chromium/content/child/mojo/mojo_application.cc b/chromium/content/child/mojo/mojo_application.cc
index cfa0e435aca..cd369d3d541 100644
--- a/chromium/content/child/mojo/mojo_application.cc
+++ b/chromium/content/child/mojo/mojo_application.cc
@@ -39,22 +39,22 @@ void MojoApplication::OnActivate(
#if defined(OS_POSIX)
base::PlatformFile handle = file.fd;
#elif defined(OS_WIN)
- base::PlatformFile handle = file;
+ base::PlatformFile handle = file.GetHandle();
#endif
- mojo::ScopedMessagePipeHandle message_pipe =
+ mojo::ScopedMessagePipeHandle pipe =
channel_init_.Init(handle, io_task_runner_);
- DCHECK(message_pipe.is_valid());
+ DCHECK(pipe.is_valid());
- ApplicationSetupPtr application_setup;
+ mojom::ApplicationSetupPtr application_setup;
application_setup.Bind(
- mojo::InterfacePtrInfo<ApplicationSetup>(std::move(message_pipe), 0u));
+ mojo::InterfacePtrInfo<mojom::ApplicationSetup>(std::move(pipe), 0u));
- mojo::ServiceProviderPtr services;
- mojo::ServiceProviderPtr exposed_services;
+ mojo::shell::mojom::InterfaceProviderPtr services;
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services;
service_registry_.Bind(GetProxy(&exposed_services));
- application_setup->ExchangeServiceProviders(GetProxy(&services),
- std::move(exposed_services));
+ application_setup->ExchangeInterfaceProviders(GetProxy(&services),
+ std::move(exposed_services));
service_registry_.BindRemoteServiceProvider(std::move(services));
}
diff --git a/chromium/content/child/mojo/mojo_application.h b/chromium/content/child/mojo/mojo_application.h
index cdd3608e71a..5303a30bc2e 100644
--- a/chromium/content/child/mojo/mojo_application.h
+++ b/chromium/content/child/mojo/mojo_application.h
@@ -38,9 +38,7 @@ class MojoApplication {
void OnActivate(const IPC::PlatformFileForTransit& file);
scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
-
ChannelInit channel_init_;
-
ServiceRegistryImpl service_registry_;
DISALLOW_COPY_AND_ASSIGN(MojoApplication);
diff --git a/chromium/content/child/mojo/type_converters.h b/chromium/content/child/mojo/type_converters.h
index 180cadb6f54..1a9a5bb9527 100644
--- a/chromium/content/child/mojo/type_converters.h
+++ b/chromium/content/child/mojo/type_converters.h
@@ -6,6 +6,7 @@
#include <utility>
#include "mojo/public/cpp/bindings/array.h"
+#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebVector.h"
namespace mojo {
@@ -20,4 +21,11 @@ struct TypeConverter<Array<T>, blink::WebVector<U>> {
}
};
+template <>
+struct TypeConverter<String, blink::WebString> {
+ static String Convert(const blink::WebString& web_string) {
+ return String(web_string.utf8());
+ }
+};
+
} // namespace mojo
diff --git a/chromium/content/child/multipart_response_delegate.cc b/chromium/content/child/multipart_response_delegate.cc
deleted file mode 100644
index a37014ac9b7..00000000000
--- a/chromium/content/child/multipart_response_delegate.cc
+++ /dev/null
@@ -1,394 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/child/multipart_response_delegate.h"
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "net/base/net_util.h"
-#include "net/http/http_response_headers.h"
-#include "net/http/http_util.h"
-#include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/platform/WebURL.h"
-#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
-
-using blink::WebHTTPHeaderVisitor;
-using blink::WebString;
-using blink::WebURLLoader;
-using blink::WebURLLoaderClient;
-using blink::WebURLResponse;
-
-namespace content {
-
-namespace {
-
-// The list of response headers that we do not copy from the original
-// response when generating a WebURLResponse for a MIME payload.
-const char* kReplaceHeaders[] = {
- "content-type",
- "content-length",
- "content-disposition",
- "content-range",
- "range",
- "set-cookie"
-};
-
-class HeaderCopier : public WebHTTPHeaderVisitor {
- public:
- HeaderCopier(WebURLResponse* response)
- : response_(response) {
- }
- void visitHeader(const WebString& name, const WebString& value) override {
- const std::string& name_utf8 = name.utf8();
- for (size_t i = 0; i < arraysize(kReplaceHeaders); ++i) {
- if (base::LowerCaseEqualsASCII(name_utf8, kReplaceHeaders[i]))
- return;
- }
- response_->setHTTPHeaderField(name, value);
- }
- private:
- WebURLResponse* response_;
-};
-
-} // namespace
-
-MultipartResponseDelegate::MultipartResponseDelegate(
- WebURLLoaderClient* client,
- WebURLLoader* loader,
- const WebURLResponse& response,
- const std::string& boundary)
- : client_(client),
- loader_(loader),
- original_response_(response),
- encoded_data_length_(0),
- boundary_("--"),
- first_received_data_(true),
- processing_headers_(false),
- stop_sending_(false),
- has_sent_first_response_(false) {
- // Some servers report a boundary prefixed with "--". See bug 5786.
- if (base::StartsWith(boundary, "--", base::CompareCase::SENSITIVE)) {
- boundary_.assign(boundary);
- } else {
- boundary_.append(boundary);
- }
-}
-
-void MultipartResponseDelegate::OnReceivedData(const char* data,
- int data_len,
- int encoded_data_length) {
- // stop_sending_ means that we've already received the final boundary token.
- // The server should stop sending us data at this point, but if it does, we
- // just throw it away.
- if (stop_sending_)
- return;
-
- data_.append(data, data_len);
- encoded_data_length_ += encoded_data_length;
- if (first_received_data_) {
- // Some servers don't send a boundary token before the first chunk of
- // data. We handle this case anyway (Gecko does too).
- first_received_data_ = false;
-
- // Eat leading \r\n
- int pos = PushOverLine(data_, 0);
- if (pos)
- data_ = data_.substr(pos);
-
- if (data_.length() < boundary_.length() + 2) {
- // We don't have enough data yet to make a boundary token. Just wait
- // until the next chunk of data arrives.
- first_received_data_ = true;
- return;
- }
-
- if (0 != data_.compare(0, boundary_.length(), boundary_)) {
- data_ = boundary_ + "\n" + data_;
- }
- }
- DCHECK(!first_received_data_);
-
- // Headers
- if (processing_headers_) {
- // Eat leading \r\n
- int pos = PushOverLine(data_, 0);
- if (pos)
- data_ = data_.substr(pos);
-
- if (ParseHeaders()) {
- // Successfully parsed headers.
- processing_headers_ = false;
- } else {
- // Get more data before trying again.
- return;
- }
- }
- DCHECK(!processing_headers_);
-
- size_t boundary_pos;
- while ((boundary_pos = FindBoundary()) != std::string::npos) {
- if (client_) {
- // Strip out trailing \n\r characters in the buffer preceding the
- // boundary on the same lines as Firefox.
- size_t data_length = boundary_pos;
- if (boundary_pos > 0 && data_[boundary_pos - 1] == '\n') {
- data_length--;
- if (boundary_pos > 1 && data_[boundary_pos - 2] == '\r') {
- data_length--;
- }
- }
- if (data_length > 0) {
- // Send the last data chunk.
- client_->didReceiveData(loader_,
- data_.data(),
- static_cast<int>(data_length),
- encoded_data_length_);
- encoded_data_length_ = 0;
- }
- }
- size_t boundary_end_pos = boundary_pos + boundary_.length();
- if (boundary_end_pos < data_.length() && '-' == data_[boundary_end_pos]) {
- // This was the last boundary so we can stop processing.
- stop_sending_ = true;
- data_.clear();
- return;
- }
-
- // We can now throw out data up through the boundary
- int offset = PushOverLine(data_, boundary_end_pos);
- data_ = data_.substr(boundary_end_pos + offset);
-
- // Ok, back to parsing headers
- if (!ParseHeaders()) {
- processing_headers_ = true;
- break;
- }
- }
-
- // At this point, we should send over any data we have, but keep enough data
- // buffered to handle a boundary that may have been truncated.
- if (!processing_headers_ && data_.length() > boundary_.length()) {
- // If the last character is a new line character, go ahead and just send
- // everything we have buffered. This matches an optimization in Gecko.
- int send_length = data_.length() - boundary_.length();
- if (data_[data_.length() - 1] == '\n')
- send_length = data_.length();
- if (client_)
- client_->didReceiveData(loader_,
- data_.data(),
- send_length,
- encoded_data_length_);
- data_ = data_.substr(send_length);
- encoded_data_length_ = 0;
- }
-}
-
-void MultipartResponseDelegate::OnCompletedRequest() {
- // If we have any pending data and we're not in a header, go ahead and send
- // it to WebCore.
- if (!processing_headers_ && !data_.empty() && !stop_sending_ && client_) {
- client_->didReceiveData(loader_,
- data_.data(),
- static_cast<int>(data_.length()),
- encoded_data_length_);
- encoded_data_length_ = 0;
- }
-}
-
-int MultipartResponseDelegate::PushOverLine(const std::string& data,
- size_t pos) {
- int offset = 0;
- if (pos < data.length() && (data[pos] == '\r' || data[pos] == '\n')) {
- ++offset;
- if (pos + 1 < data.length() && data[pos + 1] == '\n')
- ++offset;
- }
- return offset;
-}
-
-bool MultipartResponseDelegate::ParseHeaders() {
- int headers_end_pos = net::HttpUtil::LocateEndOfAdditionalHeaders(
- data_.c_str(), data_.size(), 0);
-
- if (headers_end_pos < 0)
- return false;
-
- // Eat headers and prepend a status line as is required by
- // HttpResponseHeaders.
- std::string headers("HTTP/1.1 200 OK\r\n");
- headers.append(data_, 0, headers_end_pos);
- data_ = data_.substr(headers_end_pos);
-
- scoped_refptr<net::HttpResponseHeaders> response_headers =
- new net::HttpResponseHeaders(
- net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.size()));
-
- // Create a WebURLResponse based on the original set of headers + the
- // replacement headers. We only replace the same few headers that gecko
- // does. See netwerk/streamconv/converters/nsMultiMixedConv.cpp.
- WebURLResponse response(original_response_.url());
-
- std::string mime_type;
- response_headers->GetMimeType(&mime_type);
- response.setMIMEType(WebString::fromUTF8(mime_type));
-
- std::string charset;
- response_headers->GetCharset(&charset);
- response.setTextEncodingName(WebString::fromUTF8(charset));
-
- // Copy the response headers from the original response.
- HeaderCopier copier(&response);
- original_response_.visitHTTPHeaderFields(&copier);
-
- // Replace original headers with multipart headers listed in kReplaceHeaders.
- for (size_t i = 0; i < arraysize(kReplaceHeaders); ++i) {
- std::string name(kReplaceHeaders[i]);
- std::string value;
- void* iterator = nullptr;
- while (response_headers->EnumerateHeader(&iterator, name, &value)) {
- response.addHTTPHeaderField(WebString::fromLatin1(name),
- WebString::fromLatin1(value));
- }
- }
- // To avoid recording every multipart load as a separate visit in
- // the history database, we want to keep track of whether the response
- // is part of a multipart payload. We do want to record the first visit,
- // so we only set isMultipartPayload to true after the first visit.
- response.setIsMultipartPayload(has_sent_first_response_);
- has_sent_first_response_ = true;
- // Send the response!
- if (client_)
- client_->didReceiveResponse(loader_, response);
-
- return true;
-}
-
-// Boundaries are supposed to be preceeded with --, but it looks like gecko
-// doesn't require the dashes to exist. See nsMultiMixedConv::FindToken.
-size_t MultipartResponseDelegate::FindBoundary() {
- size_t boundary_pos = data_.find(boundary_);
- if (boundary_pos != std::string::npos) {
- // Back up over -- for backwards compat
- // TODO(tc): Don't we only want to do this once? Gecko code doesn't seem
- // to care.
- if (boundary_pos >= 2) {
- if ('-' == data_[boundary_pos - 1] && '-' == data_[boundary_pos - 2]) {
- boundary_pos -= 2;
- boundary_ = "--" + boundary_;
- }
- }
- }
- return boundary_pos;
-}
-
-bool MultipartResponseDelegate::ReadMultipartBoundary(
- const WebURLResponse& response,
- std::string* multipart_boundary) {
- std::string content_type =
- response.httpHeaderField(WebString::fromUTF8("Content-Type")).utf8();
-
- size_t boundary_start_offset = content_type.find("boundary=");
- if (boundary_start_offset == std::string::npos)
- return false;
-
- boundary_start_offset += strlen("boundary=");
-
- size_t boundary_end_offset = content_type.find(';', boundary_start_offset);
-
- if (boundary_end_offset == std::string::npos)
- boundary_end_offset = content_type.length();
-
- size_t boundary_length = boundary_end_offset - boundary_start_offset;
-
- *multipart_boundary =
- content_type.substr(boundary_start_offset, boundary_length);
- // The byte range response can have quoted boundary strings. This is legal
- // as per MIME specifications. Individual data fragements however don't
- // contain quoted boundary strings.
- base::TrimString(*multipart_boundary, "\"", multipart_boundary);
- return true;
-}
-
-bool MultipartResponseDelegate::ReadContentRanges(
- const WebURLResponse& response,
- int64_t* content_range_lower_bound,
- int64_t* content_range_upper_bound,
- int64_t* content_range_instance_size) {
- std::string content_range = response.httpHeaderField("Content-Range").utf8();
- if (content_range.empty()) {
- content_range = response.httpHeaderField("Range").utf8();
- }
-
- if (content_range.empty()) {
- DLOG(WARNING) << "Failed to read content range from response.";
- return false;
- }
-
- size_t byte_range_lower_bound_start_offset = content_range.find(" ");
- if (byte_range_lower_bound_start_offset == std::string::npos) {
- return false;
- }
-
- // Skip over the initial space.
- byte_range_lower_bound_start_offset++;
-
- // Find the lower bound.
- size_t byte_range_lower_bound_end_offset =
- content_range.find("-", byte_range_lower_bound_start_offset);
- if (byte_range_lower_bound_end_offset == std::string::npos) {
- return false;
- }
-
- size_t byte_range_lower_bound_characters =
- byte_range_lower_bound_end_offset - byte_range_lower_bound_start_offset;
- std::string byte_range_lower_bound =
- content_range.substr(byte_range_lower_bound_start_offset,
- byte_range_lower_bound_characters);
-
- // Find the upper bound.
- size_t byte_range_upper_bound_start_offset =
- byte_range_lower_bound_end_offset + 1;
-
- size_t byte_range_upper_bound_end_offset =
- content_range.find("/", byte_range_upper_bound_start_offset);
- if (byte_range_upper_bound_end_offset == std::string::npos) {
- return false;
- }
-
- size_t byte_range_upper_bound_characters =
- byte_range_upper_bound_end_offset - byte_range_upper_bound_start_offset;
- std::string byte_range_upper_bound =
- content_range.substr(byte_range_upper_bound_start_offset,
- byte_range_upper_bound_characters);
-
- // Find the instance size.
- size_t byte_range_instance_size_start_offset =
- byte_range_upper_bound_end_offset + 1;
-
- size_t byte_range_instance_size_end_offset =
- content_range.length();
-
- size_t byte_range_instance_size_characters =
- byte_range_instance_size_end_offset -
- byte_range_instance_size_start_offset;
- std::string byte_range_instance_size =
- content_range.substr(byte_range_instance_size_start_offset,
- byte_range_instance_size_characters);
-
- if (!base::StringToInt64(byte_range_lower_bound, content_range_lower_bound))
- return false;
- if (!base::StringToInt64(byte_range_upper_bound, content_range_upper_bound))
- return false;
- if (!base::StringToInt64(byte_range_instance_size,
- content_range_instance_size)) {
- return false;
- }
- return true;
-}
-
-} // namespace content
diff --git a/chromium/content/child/multipart_response_delegate.h b/chromium/content/child/multipart_response_delegate.h
deleted file mode 100644
index b76afdb4c2e..00000000000
--- a/chromium/content/child/multipart_response_delegate.h
+++ /dev/null
@@ -1,153 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// A delegate class of WebURLLoaderImpl that handles multipart/x-mixed-replace
-// data. We special case multipart/x-mixed-replace because WebCore expects a
-// separate didReceiveResponse for each new message part.
-//
-// Most of the logic and edge case handling are based on the Mozilla's
-// implementation in netwerk/streamconv/converters/nsMultiMixedConv.cpp.
-// This seems like a derivative work, so here's the original license:
-
-/* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either the GNU General Public License Version 2 or later (the "GPL"), or
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
-
-#ifndef CONTENT_CHILD_MULTIPART_RESPONSE_DELEGATE_H_
-#define CONTENT_CHILD_MULTIPART_RESPONSE_DELEGATE_H_
-
-#include <string>
-
-#include <stddef.h>
-
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebURLResponse.h"
-
-namespace blink {
-class WebURLLoader;
-class WebURLLoaderClient;
-}
-
-namespace content {
-
-class CONTENT_EXPORT MultipartResponseDelegate {
- public:
- MultipartResponseDelegate(blink::WebURLLoaderClient* client,
- blink::WebURLLoader* loader,
- const blink::WebURLResponse& response,
- const std::string& boundary);
-
- // Passed through from ResourceHandleInternal
- void OnReceivedData(const char* data, int data_len, int encoded_data_length);
- void OnCompletedRequest();
-
- // The request has been canceled, so stop making calls to the client.
- void Cancel() {
- client_ = NULL;
- loader_ = NULL;
- }
-
- // Returns the multi part boundary string from the Content-type header
- // in the response.
- // Returns true on success.
- static bool ReadMultipartBoundary(const blink::WebURLResponse& response,
- std::string* multipart_boundary);
-
- // Returns the lower and higher content ranges from an individual multipart
- // in a multipart response.
- // Returns true on success.
- static bool ReadContentRanges(const blink::WebURLResponse& response,
- int64_t* content_range_lower_bound,
- int64_t* content_range_upper_bound,
- int64_t* content_range_instance_size);
-
- private:
- friend class MultipartResponseDelegateTester; // For unittests.
-
- // Pointers to the client and associated loader so we can make callbacks as
- // we parse pieces of data.
- blink::WebURLLoaderClient* client_;
- blink::WebURLLoader* loader_;
-
- // The original resource response for this request. We use this as a
- // starting point for each parts response.
- blink::WebURLResponse original_response_;
-
- // Checks to see if data[pos] character is a line break; handles crlf, lflf,
- // lf, or cr. Returns the number of characters to skip over (0, 1 or 2).
- int PushOverLine(const std::string& data, size_t pos);
-
- // Tries to parse http headers from the start of data_. Returns true if it
- // succeeds and sends a didReceiveResponse to m_client. Returns false if
- // the header is incomplete (in which case we just wait for more data).
- bool ParseHeaders();
-
- // Find the next boundary in data_. Returns std::string::npos if there's no
- // full token.
- size_t FindBoundary();
-
- // Transferred data size accumulated between client callbacks.
- int encoded_data_length_;
-
- // A temporary buffer to hold data between reads for multipart data that
- // gets split in the middle of a header.
- std::string data_;
-
- // Multipart boundary token
- std::string boundary_;
-
- // true until we get our first on received data call
- bool first_received_data_;
-
- // true if we're truncated in the middle of a header
- bool processing_headers_;
-
- // true when we're done sending information. At that point, we stop
- // processing AddData requests.
- bool stop_sending_;
-
- // true after we've sent our first response to the WebURLLoaderClient.
- bool has_sent_first_response_;
-
- DISALLOW_COPY_AND_ASSIGN(MultipartResponseDelegate);
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_MULTIPART_RESPONSE_DELEGATE_H_
diff --git a/chromium/content/child/multipart_response_delegate_unittest.cc b/chromium/content/child/multipart_response_delegate_unittest.cc
deleted file mode 100644
index a6076cff250..00000000000
--- a/chromium/content/child/multipart_response_delegate_unittest.cc
+++ /dev/null
@@ -1,680 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/child/multipart_response_delegate.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <vector>
-
-#include "base/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/platform/WebURL.h"
-#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
-#include "third_party/WebKit/public/platform/WebURLResponse.h"
-
-using blink::WebString;
-using blink::WebURL;
-using blink::WebURLError;
-using blink::WebURLLoader;
-using blink::WebURLLoaderClient;
-using blink::WebURLRequest;
-using blink::WebURLResponse;
-using std::string;
-
-namespace content {
-
-class MultipartResponseDelegateTester {
- public:
- MultipartResponseDelegateTester(MultipartResponseDelegate* delegate)
- : delegate_(delegate) {
- }
-
- int PushOverLine(const std::string& data, size_t pos) {
- return delegate_->PushOverLine(data, pos);
- }
-
- bool ParseHeaders() { return delegate_->ParseHeaders(); }
- size_t FindBoundary() { return delegate_->FindBoundary(); }
- std::string& boundary() { return delegate_->boundary_; }
- std::string& data() { return delegate_->data_; }
-
- private:
- MultipartResponseDelegate* delegate_;
-};
-
-namespace {
-
-class MultipartResponseTest : public testing::Test {
-};
-
-class MockWebURLLoaderClient : public WebURLLoaderClient {
- public:
- MockWebURLLoaderClient() { Reset(); }
-
- void willFollowRedirect(WebURLLoader*,
- WebURLRequest&,
- const WebURLResponse&) override {}
- void didSendData(WebURLLoader*,
- unsigned long long,
- unsigned long long) override {}
-
- void didReceiveResponse(WebURLLoader* loader,
- const WebURLResponse& response) override {
- ++received_response_;
- response_ = response;
- data_.clear();
- }
- void didReceiveData(blink::WebURLLoader* loader,
- const char* data,
- int data_length,
- int encoded_data_length) override {
- ++received_data_;
- data_.append(data, data_length);
- total_encoded_data_length_ += encoded_data_length;
- }
- void didFinishLoading(WebURLLoader*,
- double finishTime,
- int64_t total_encoded_data_length) override {}
- void didFail(WebURLLoader*, const WebURLError&) override {}
-
- void Reset() {
- received_response_ = received_data_ = total_encoded_data_length_ = 0;
- data_.clear();
- response_.reset();
- }
-
- string GetResponseHeader(const char* name) const {
- return string(response_.httpHeaderField(WebString::fromUTF8(name)).utf8());
- }
-
- int received_response_, received_data_, total_encoded_data_length_;
- string data_;
- WebURLResponse response_;
-};
-
-// We can't put this in an anonymous function because it's a friend class for
-// access to private members.
-TEST(MultipartResponseTest, Functions) {
- // PushOverLine tests
-
- WebURLResponse response;
- response.initialize();
- response.setMIMEType("multipart/x-mixed-replace");
- response.setHTTPHeaderField("Foo", "Bar");
- response.setHTTPHeaderField("Content-type", "text/plain");
- MockWebURLLoaderClient client;
- MultipartResponseDelegate delegate(&client, NULL, response, "bound");
- MultipartResponseDelegateTester delegate_tester(&delegate);
-
- struct {
- const char* input;
- const int position;
- const int expected;
- } line_tests[] = {
- { "Line", 0, 0 },
- { "Line", 2, 0 },
- { "Line", 10, 0 },
- { "\r\nLine", 0, 2 },
- { "\nLine", 0, 1 },
- { "\n\nLine", 0, 2 },
- { "\rLine", 0, 1 },
- { "Line\r\nLine", 4, 2 },
- { "Line\nLine", 4, 1 },
- { "Line\n\nLine", 4, 2 },
- { "Line\rLine", 4, 1 },
- { "Line\r\rLine", 4, 1 },
- };
- for (size_t i = 0; i < arraysize(line_tests); ++i) {
- EXPECT_EQ(line_tests[i].expected,
- delegate_tester.PushOverLine(line_tests[i].input,
- line_tests[i].position));
- }
-
- // ParseHeaders tests
- struct {
- const char* data;
- const bool rv;
- const int received_response_calls;
- const char* newdata;
- } header_tests[] = {
- { "This is junk", false, 0, "This is junk" },
- { "Foo: bar\nBaz:\n\nAfter:\n", true, 1, "After:\n" },
- { "Foo: bar\nBaz:\n", false, 0, "Foo: bar\nBaz:\n" },
- { "Foo: bar\r\nBaz:\r\n\r\nAfter:\r\n", true, 1, "After:\r\n" },
- { "Foo: bar\r\nBaz:\r\n", false, 0, "Foo: bar\r\nBaz:\r\n" },
- { "Foo: bar\nBaz:\r\n\r\nAfter:\n\n", true, 1, "After:\n\n" },
- { "Foo: bar\r\nBaz:\n", false, 0, "Foo: bar\r\nBaz:\n" },
- { "\r\n", true, 1, "" },
- };
- for (size_t i = 0; i < arraysize(header_tests); ++i) {
- client.Reset();
- delegate_tester.data().assign(header_tests[i].data);
- EXPECT_EQ(header_tests[i].rv,
- delegate_tester.ParseHeaders());
- EXPECT_EQ(header_tests[i].received_response_calls,
- client.received_response_);
- EXPECT_EQ(string(header_tests[i].newdata),
- delegate_tester.data());
- }
- // Test that the resource response is filled in correctly when parsing
- // headers.
- client.Reset();
- string test_header("content-type: image/png\ncontent-length: 10\n\n");
- delegate_tester.data().assign(test_header);
- EXPECT_TRUE(delegate_tester.ParseHeaders());
- EXPECT_TRUE(delegate_tester.data().length() == 0);
- EXPECT_EQ(string("image/png"), client.GetResponseHeader("Content-Type"));
- EXPECT_EQ(string("10"), client.GetResponseHeader("content-length"));
- // This header is passed from the original request.
- EXPECT_EQ(string("Bar"), client.GetResponseHeader("foo"));
-
- // Make sure we parse the right mime-type if a charset is provided.
- client.Reset();
- string test_header2("content-type: text/html; charset=utf-8\n\n");
- delegate_tester.data().assign(test_header2);
- EXPECT_TRUE(delegate_tester.ParseHeaders());
- EXPECT_TRUE(delegate_tester.data().length() == 0);
- EXPECT_EQ(string("text/html; charset=utf-8"),
- client.GetResponseHeader("Content-Type"));
- EXPECT_EQ(string("utf-8"),
- string(client.response_.textEncodingName().utf8()));
-
- // FindBoundary tests
- struct {
- const char* boundary;
- const char* data;
- const size_t position;
- } boundary_tests[] = {
- { "bound", "bound", 0 },
- { "bound", "--bound", 0 },
- { "bound", "junkbound", 4 },
- { "bound", "junk--bound", 4 },
- { "foo", "bound", string::npos },
- { "bound", "--boundbound", 0 },
- };
- for (size_t i = 0; i < arraysize(boundary_tests); ++i) {
- delegate_tester.boundary().assign(boundary_tests[i].boundary);
- delegate_tester.data().assign(boundary_tests[i].data);
- EXPECT_EQ(boundary_tests[i].position,
- delegate_tester.FindBoundary());
- }
-}
-
-TEST(MultipartResponseTest, MissingBoundaries) {
- WebURLResponse response;
- response.initialize();
- response.setMIMEType("multipart/x-mixed-replace");
- response.setHTTPHeaderField("Foo", "Bar");
- response.setHTTPHeaderField("Content-type", "text/plain");
- MockWebURLLoaderClient client;
- MultipartResponseDelegate delegate(&client, NULL, response, "bound");
-
- // No start boundary
- string no_start_boundary(
- "Content-type: text/plain\n\n"
- "This is a sample response\n"
- "--bound--"
- "ignore junk after end token --bound\n\nTest2\n");
- delegate.OnReceivedData(no_start_boundary.c_str(),
- static_cast<int>(no_start_boundary.length()),
- static_cast<int>(no_start_boundary.length()));
- EXPECT_EQ(1, client.received_response_);
- EXPECT_EQ(1, client.received_data_);
- EXPECT_EQ(string("This is a sample response"), client.data_);
- EXPECT_EQ(static_cast<int>(no_start_boundary.length()),
- client.total_encoded_data_length_);
-
- delegate.OnCompletedRequest();
- EXPECT_EQ(1, client.received_response_);
- EXPECT_EQ(1, client.received_data_);
-
- // No end boundary
- client.Reset();
- MultipartResponseDelegate delegate2(&client, NULL, response, "bound");
- string no_end_boundary(
- "bound\nContent-type: text/plain\n\n"
- "This is a sample response\n");
- delegate2.OnReceivedData(no_end_boundary.c_str(),
- static_cast<int>(no_end_boundary.length()),
- static_cast<int>(no_end_boundary.length()));
- EXPECT_EQ(1, client.received_response_);
- EXPECT_EQ(1, client.received_data_);
- EXPECT_EQ("This is a sample response\n", client.data_);
- EXPECT_EQ(static_cast<int>(no_end_boundary.length()),
- client.total_encoded_data_length_);
-
- delegate2.OnCompletedRequest();
- EXPECT_EQ(1, client.received_response_);
- EXPECT_EQ(1, client.received_data_);
- EXPECT_EQ(string("This is a sample response\n"), client.data_);
- EXPECT_EQ(static_cast<int>(no_end_boundary.length()),
- client.total_encoded_data_length_);
-
- // Neither boundary
- client.Reset();
- MultipartResponseDelegate delegate3(&client, NULL, response, "bound");
- string no_boundaries(
- "Content-type: text/plain\n\n"
- "This is a sample response\n");
- delegate3.OnReceivedData(no_boundaries.c_str(),
- static_cast<int>(no_boundaries.length()),
- static_cast<int>(no_boundaries.length()));
- EXPECT_EQ(1, client.received_response_);
- EXPECT_EQ(1, client.received_data_);
- EXPECT_EQ("This is a sample response\n", client.data_);
- EXPECT_EQ(static_cast<int>(no_boundaries.length()),
- client.total_encoded_data_length_);
-
- delegate3.OnCompletedRequest();
- EXPECT_EQ(1, client.received_response_);
- EXPECT_EQ(1, client.received_data_);
- EXPECT_EQ(string("This is a sample response\n"), client.data_);
- EXPECT_EQ(static_cast<int>(no_boundaries.length()),
- client.total_encoded_data_length_);
-}
-
-TEST(MultipartResponseTest, MalformedBoundary) {
- // Some servers send a boundary that is prefixed by "--". See bug 5786.
-
- WebURLResponse response;
- response.initialize();
- response.setMIMEType("multipart/x-mixed-replace");
- response.setHTTPHeaderField("Foo", "Bar");
- response.setHTTPHeaderField("Content-type", "text/plain");
- MockWebURLLoaderClient client;
- MultipartResponseDelegate delegate(&client, NULL, response, "--bound");
-
- string data(
- "--bound\n"
- "Content-type: text/plain\n\n"
- "This is a sample response\n"
- "--bound--"
- "ignore junk after end token --bound\n\nTest2\n");
- delegate.OnReceivedData(data.c_str(),
- static_cast<int>(data.length()),
- static_cast<int>(data.length()));
- EXPECT_EQ(1, client.received_response_);
- EXPECT_EQ(1, client.received_data_);
- EXPECT_EQ(string("This is a sample response"), client.data_);
- EXPECT_EQ(static_cast<int>(data.length()), client.total_encoded_data_length_);
-
- delegate.OnCompletedRequest();
- EXPECT_EQ(1, client.received_response_);
- EXPECT_EQ(1, client.received_data_);
-}
-
-
-// Used in for tests that break the data in various places.
-struct TestChunk {
- const int start_pos; // offset in data
- const int end_pos; // end offset in data
- const int expected_responses;
- const int expected_received_data;
- const char* expected_data;
- const int expected_encoded_data_length;
-};
-
-void VariousChunkSizesTest(const TestChunk chunks[], int chunks_size,
- int responses, int received_data,
- const char* completed_data,
- int completed_encoded_data_length) {
- const string data(
- "--bound\n" // 0-7
- "Content-type: image/png\n\n" // 8-32
- "datadatadatadatadata" // 33-52
- "--bound\n" // 53-60
- "Content-type: image/jpg\n\n" // 61-85
- "foofoofoofoofoo" // 86-100
- "--bound--"); // 101-109
-
- WebURLResponse response;
- response.initialize();
- response.setMIMEType("multipart/x-mixed-replace");
- MockWebURLLoaderClient client;
- MultipartResponseDelegate delegate(&client, NULL, response, "bound");
-
- for (int i = 0; i < chunks_size; ++i) {
- ASSERT_TRUE(chunks[i].start_pos < chunks[i].end_pos);
- string chunk = data.substr(chunks[i].start_pos,
- chunks[i].end_pos - chunks[i].start_pos);
- delegate.OnReceivedData(
- chunk.c_str(),
- static_cast<int>(chunk.length()),
- static_cast<int>(chunk.length()));
- EXPECT_EQ(chunks[i].expected_responses, client.received_response_);
- EXPECT_EQ(chunks[i].expected_received_data, client.received_data_);
- EXPECT_EQ(string(chunks[i].expected_data), client.data_);
- EXPECT_EQ(chunks[i].expected_encoded_data_length,
- client.total_encoded_data_length_);
- }
- // Check final state
- delegate.OnCompletedRequest();
- EXPECT_EQ(responses, client.received_response_);
- EXPECT_EQ(received_data, client.received_data_);
- string completed_data_string(completed_data);
- EXPECT_EQ(completed_data_string, client.data_);
- EXPECT_EQ(completed_encoded_data_length, client.total_encoded_data_length_);
-}
-
-TEST(MultipartResponseTest, BreakInBoundary) {
- // Break in the first boundary
- const TestChunk bound1[] = {
- { 0, 4, 0, 0, "", 0 },
- { 4, 110, 2, 2, "foofoofoofoofoo", 110 },
- };
- VariousChunkSizesTest(bound1, arraysize(bound1),
- 2, 2, "foofoofoofoofoo", 110);
-
- // Break in first and second
- const TestChunk bound2[] = {
- { 0, 4, 0, 0, "", 0 },
- { 4, 55, 1, 1, "datadatadatadat", 55 },
- { 55, 65, 1, 2, "datadatadatadatadata", 65 },
- { 65, 110, 2, 3, "foofoofoofoofoo", 110 },
- };
- VariousChunkSizesTest(bound2, arraysize(bound2),
- 2, 3, "foofoofoofoofoo", 110);
-
- // Break in second only
- const TestChunk bound3[] = {
- { 0, 55, 1, 1, "datadatadatadat", 55 },
- { 55, 110, 2, 3, "foofoofoofoofoo", 110 },
- };
- VariousChunkSizesTest(bound3, arraysize(bound3),
- 2, 3, "foofoofoofoofoo", 110);
-}
-
-TEST(MultipartResponseTest, BreakInHeaders) {
- // Break in first header
- const TestChunk header1[] = {
- { 0, 10, 0, 0, "", 0 },
- { 10, 35, 1, 0, "", 0 },
- { 35, 110, 2, 2, "foofoofoofoofoo", 110 },
- };
- VariousChunkSizesTest(header1, arraysize(header1),
- 2, 2, "foofoofoofoofoo", 110);
-
- // Break in both headers
- const TestChunk header2[] = {
- { 0, 10, 0, 0, "", 0 },
- { 10, 65, 1, 1, "datadatadatadatadata", 65 },
- { 65, 110, 2, 2, "foofoofoofoofoo", 110 },
- };
- VariousChunkSizesTest(header2, arraysize(header2),
- 2, 2, "foofoofoofoofoo", 110);
-
- // Break at end of a header
- const TestChunk header3[] = {
- { 0, 33, 1, 0, "", 0 },
- { 33, 65, 1, 1, "datadatadatadatadata", 65 },
- { 65, 110, 2, 2, "foofoofoofoofoo", 110 },
- };
- VariousChunkSizesTest(header3, arraysize(header3),
- 2, 2, "foofoofoofoofoo", 110);
-}
-
-TEST(MultipartResponseTest, BreakInData) {
- // All data as one chunk
- const TestChunk data1[] = {
- { 0, 110, 2, 2, "foofoofoofoofoo", 110 },
- };
- VariousChunkSizesTest(data1, arraysize(data1),
- 2, 2, "foofoofoofoofoo", 110);
-
- // breaks in data segment
- const TestChunk data2[] = {
- { 0, 35, 1, 0, "", 0 },
- { 35, 65, 1, 1, "datadatadatadatadata", 65 },
- { 65, 90, 2, 1, "", 65 },
- { 90, 110, 2, 2, "foofoofoofoofoo", 110 },
- };
- VariousChunkSizesTest(data2, arraysize(data2),
- 2, 2, "foofoofoofoofoo", 110);
-
- // Incomplete send
- const TestChunk data3[] = {
- { 0, 35, 1, 0, "", 0 },
- { 35, 90, 2, 1, "", 90 },
- };
- VariousChunkSizesTest(data3, arraysize(data3),
- 2, 2, "foof", 90);
-}
-
-TEST(MultipartResponseTest, SmallChunk) {
- WebURLResponse response;
- response.initialize();
- response.setMIMEType("multipart/x-mixed-replace");
- response.setHTTPHeaderField("Content-type", "text/plain");
- MockWebURLLoaderClient client;
- MultipartResponseDelegate delegate(&client, NULL, response, "bound");
-
- // Test chunks of size 1, 2, and 0.
- string data(
- "--boundContent-type: text/plain\n\n"
- "\n--boundContent-type: text/plain\n\n"
- "\n\n--boundContent-type: text/plain\n\n"
- "--boundContent-type: text/plain\n\n"
- "end--bound--");
- delegate.OnReceivedData(data.c_str(),
- static_cast<int>(data.length()),
- static_cast<int>(data.length()));
- EXPECT_EQ(4, client.received_response_);
- EXPECT_EQ(2, client.received_data_);
- EXPECT_EQ(string("end"), client.data_);
- EXPECT_EQ(static_cast<int>(data.length()), client.total_encoded_data_length_);
-
- delegate.OnCompletedRequest();
- EXPECT_EQ(4, client.received_response_);
- EXPECT_EQ(2, client.received_data_);
-}
-
-TEST(MultipartResponseTest, MultipleBoundaries) {
- // Test multiple boundaries back to back
- WebURLResponse response;
- response.initialize();
- response.setMIMEType("multipart/x-mixed-replace");
- MockWebURLLoaderClient client;
- MultipartResponseDelegate delegate(&client, NULL, response, "bound");
-
- string data("--bound\r\n\r\n--bound\r\n\r\nfoofoo--bound--");
- delegate.OnReceivedData(data.c_str(),
- static_cast<int>(data.length()),
- static_cast<int>(data.length()));
- EXPECT_EQ(2, client.received_response_);
- EXPECT_EQ(1, client.received_data_);
- EXPECT_EQ(string("foofoo"), client.data_);
- EXPECT_EQ(static_cast<int>(data.length()), client.total_encoded_data_length_);
-}
-
-TEST(MultipartResponseTest, MultipartByteRangeParsingTest) {
- // Test multipart/byteranges based boundary parsing.
- WebURLResponse response1;
- response1.initialize();
- response1.setMIMEType("multipart/x-mixed-replace");
- response1.setHTTPHeaderField("Content-Length", "200");
- response1.setHTTPHeaderField("Content-type",
- "multipart/byteranges; boundary=--bound--");
-
- std::string multipart_boundary;
- bool result = MultipartResponseDelegate::ReadMultipartBoundary(
- response1, &multipart_boundary);
- EXPECT_EQ(result, true);
- EXPECT_EQ(string("--bound--"),
- multipart_boundary);
-
- WebURLResponse response2;
- response2.initialize();
- response2.setMIMEType("image/png");
-
- response2.setHTTPHeaderField("Content-Length", "300");
- response2.setHTTPHeaderField("Last-Modified",
- "Mon, 04 Apr 2005 20:36:01 GMT");
- response2.setHTTPHeaderField("Date", "Thu, 11 Sep 2008 18:21:42 GMT");
-
- multipart_boundary.clear();
- result = MultipartResponseDelegate::ReadMultipartBoundary(
- response2, &multipart_boundary);
- EXPECT_EQ(result, false);
-
- WebURLResponse response3;
- response3.initialize();
- response3.setMIMEType("multipart/byteranges");
-
- response3.setHTTPHeaderField("Content-Length", "300");
- response3.setHTTPHeaderField("Last-Modified",
- "Mon, 04 Apr 2005 20:36:01 GMT");
- response3.setHTTPHeaderField("Date", "Thu, 11 Sep 2008 18:21:42 GMT");
- response3.setHTTPHeaderField("Content-type", "multipart/byteranges");
-
- multipart_boundary.clear();
- result = MultipartResponseDelegate::ReadMultipartBoundary(
- response3, &multipart_boundary);
- EXPECT_EQ(result, false);
- EXPECT_EQ(multipart_boundary.length(), 0U);
-
- WebURLResponse response4;
- response4.initialize();
- response4.setMIMEType("multipart/byteranges");
- response4.setHTTPHeaderField("Content-Length", "200");
- response4.setHTTPHeaderField("Content-type",
- "multipart/byteranges; boundary=--bound--; charSet=utf8");
-
- multipart_boundary.clear();
-
- result = MultipartResponseDelegate::ReadMultipartBoundary(
- response4, &multipart_boundary);
- EXPECT_EQ(result, true);
- EXPECT_EQ(string("--bound--"), multipart_boundary);
-
- WebURLResponse response5;
- response5.initialize();
- response5.setMIMEType("multipart/byteranges");
- response5.setHTTPHeaderField("Content-Length", "200");
- response5.setHTTPHeaderField("Content-type",
- "multipart/byteranges; boundary=\"--bound--\"; charSet=utf8");
-
- multipart_boundary.clear();
-
- result = MultipartResponseDelegate::ReadMultipartBoundary(
- response5, &multipart_boundary);
- EXPECT_EQ(result, true);
- EXPECT_EQ(string("--bound--"), multipart_boundary);
-}
-
-TEST(MultipartResponseTest, MultipartContentRangesTest) {
- WebURLResponse response1;
- response1.initialize();
- response1.setMIMEType("application/pdf");
- response1.setHTTPHeaderField("Content-Length", "200"); // Ignored!
- // Use intentionally >32bit values to check they are handled correctly.
- response1.setHTTPHeaderField("Content-Range",
- "bytes 5000000000-5000000050/6000000000");
-
- int64_t content_range_lower_bound = 0;
- int64_t content_range_upper_bound = 0;
- int64_t content_range_instance_size = 0;
-
- bool result = MultipartResponseDelegate::ReadContentRanges(
- response1, &content_range_lower_bound,
- &content_range_upper_bound,
- &content_range_instance_size);
-
- EXPECT_EQ(result, true);
- EXPECT_EQ(content_range_lower_bound, 5e9);
- EXPECT_EQ(content_range_upper_bound, 5e9+50);
- EXPECT_EQ(content_range_instance_size, 6e9);
-
- WebURLResponse response2;
- response2.initialize();
- response2.setMIMEType("application/pdf");
- response2.setHTTPHeaderField("Content-Length", "200");
- response2.setHTTPHeaderField("Content-Range", "bytes 1000/1050");
-
- content_range_lower_bound = 0;
- content_range_upper_bound = 0;
- content_range_instance_size = 0;
-
- result = MultipartResponseDelegate::ReadContentRanges(
- response2, &content_range_lower_bound,
- &content_range_upper_bound,
- &content_range_instance_size);
-
- EXPECT_EQ(result, false);
-
- WebURLResponse response3;
- response3.initialize();
- response3.setMIMEType("application/pdf");
- response3.setHTTPHeaderField("Content-Length", "200");
- response3.setHTTPHeaderField("Range", "bytes 1000-1050/5000");
-
- content_range_lower_bound = 0;
- content_range_upper_bound = 0;
- content_range_instance_size = 0;
-
- result = MultipartResponseDelegate::ReadContentRanges(
- response3, &content_range_lower_bound,
- &content_range_upper_bound,
- &content_range_instance_size);
-
- EXPECT_EQ(result, true);
- EXPECT_EQ(content_range_lower_bound, 1000);
- EXPECT_EQ(content_range_upper_bound, 1050);
-
- WebURLResponse response4;
- response4.initialize();
- response4.setMIMEType("application/pdf");
- response4.setHTTPHeaderField("Content-Length", "200");
-
- content_range_lower_bound = 0;
- content_range_upper_bound = 0;
- content_range_instance_size = 0;
-
- result = MultipartResponseDelegate::ReadContentRanges(
- response4, &content_range_lower_bound,
- &content_range_upper_bound,
- &content_range_instance_size);
-
- EXPECT_EQ(result, false);
-}
-
-TEST(MultipartResponseTest, MultipartPayloadSet) {
- WebURLResponse response;
- response.initialize();
- response.setMIMEType("multipart/x-mixed-replace");
- MockWebURLLoaderClient client;
- MultipartResponseDelegate delegate(&client, NULL, response, "bound");
-
- string data(
- "--bound\n"
- "Content-type: text/plain\n\n"
- "response data\n"
- "--bound\n");
- delegate.OnReceivedData(data.c_str(),
- static_cast<int>(data.length()),
- static_cast<int>(data.length()));
- EXPECT_EQ(1, client.received_response_);
- EXPECT_EQ(string("response data"), client.data_);
- EXPECT_EQ(static_cast<int>(data.length()), client.total_encoded_data_length_);
- EXPECT_FALSE(client.response_.isMultipartPayload());
-
- string data2(
- "Content-type: text/plain\n\n"
- "response data2\n"
- "--bound\n");
- delegate.OnReceivedData(data2.c_str(),
- static_cast<int>(data2.length()),
- static_cast<int>(data2.length()));
- EXPECT_EQ(2, client.received_response_);
- EXPECT_EQ(string("response data2"), client.data_);
- EXPECT_EQ(static_cast<int>(data.length()) + static_cast<int>(data2.length()),
- client.total_encoded_data_length_);
- EXPECT_TRUE(client.response_.isMultipartPayload());
-}
-
-} // namespace
-
-} // namespace content
diff --git a/chromium/content/child/navigator_connect/OWNERS b/chromium/content/child/navigator_connect/OWNERS
deleted file mode 100644
index 1b10b3436d9..00000000000
--- a/chromium/content/child/navigator_connect/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-mek@chromium.org
diff --git a/chromium/content/child/navigator_connect/service_port_dispatcher_impl.cc b/chromium/content/child/navigator_connect/service_port_dispatcher_impl.cc
deleted file mode 100644
index bc002a99c34..00000000000
--- a/chromium/content/child/navigator_connect/service_port_dispatcher_impl.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/child/navigator_connect/service_port_dispatcher_impl.h"
-
-#include <utility>
-
-#include "base/trace_event/trace_event.h"
-#include "mojo/common/common_type_converters.h"
-#include "mojo/common/url_type_converters.h"
-#include "third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextProxy.h"
-
-namespace content {
-
-namespace {
-
-class WebConnectCallbacksImpl
- : public blink::WebServicePortConnectEventCallbacks {
- public:
- WebConnectCallbacksImpl(
- const ServicePortDispatcher::ConnectCallback& callback)
- : callback_(callback) {}
-
- ~WebConnectCallbacksImpl() override {}
-
- void onSuccess(const blink::WebServicePort& port) override {
- callback_.Run(SERVICE_PORT_CONNECT_RESULT_ACCEPT,
- mojo::String::From<base::string16>(port.name),
- mojo::String::From<base::string16>(port.data));
- }
-
- void onError() override {
- callback_.Run(SERVICE_PORT_CONNECT_RESULT_REJECT, mojo::String(""),
- mojo::String(""));
- }
-
- private:
- ServicePortDispatcher::ConnectCallback callback_;
-};
-
-} // namespace
-
-void ServicePortDispatcherImpl::Create(
- base::WeakPtr<blink::WebServiceWorkerContextProxy> proxy,
- mojo::InterfaceRequest<ServicePortDispatcher> request) {
- new ServicePortDispatcherImpl(proxy, std::move(request));
-}
-
-ServicePortDispatcherImpl::~ServicePortDispatcherImpl() {
- WorkerThread::RemoveObserver(this);
-}
-
-ServicePortDispatcherImpl::ServicePortDispatcherImpl(
- base::WeakPtr<blink::WebServiceWorkerContextProxy> proxy,
- mojo::InterfaceRequest<ServicePortDispatcher> request)
- : binding_(this, std::move(request)), proxy_(proxy) {
- WorkerThread::AddObserver(this);
-}
-
-void ServicePortDispatcherImpl::WillStopCurrentWorkerThread() {
- delete this;
-}
-
-void ServicePortDispatcherImpl::Connect(const mojo::String& target_url,
- const mojo::String& origin,
- int32_t port_id,
- const ConnectCallback& callback) {
- if (!proxy_) {
- callback.Run(SERVICE_PORT_CONNECT_RESULT_REJECT, mojo::String(""),
- mojo::String(""));
- return;
- }
- TRACE_EVENT0("ServiceWorker", "ServicePortDispatcherImpl::Connect");
- proxy_->dispatchServicePortConnectEvent(new WebConnectCallbacksImpl(callback),
- target_url.To<GURL>(),
- origin.To<base::string16>(), port_id);
-}
-
-} // namespace content
diff --git a/chromium/content/child/navigator_connect/service_port_dispatcher_impl.h b/chromium/content/child/navigator_connect/service_port_dispatcher_impl.h
deleted file mode 100644
index f0bf91e3ddb..00000000000
--- a/chromium/content/child/navigator_connect/service_port_dispatcher_impl.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_CHILD_NAVIGATOR_CONNECT_SERVICE_PORT_DISPATCHER_IMPL_H_
-#define CONTENT_CHILD_NAVIGATOR_CONNECT_SERVICE_PORT_DISPATCHER_IMPL_H_
-
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "content/common/service_port_service.mojom.h"
-#include "content/public/child/worker_thread.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
-
-namespace blink {
-class WebServiceWorkerContextProxy;
-}
-
-namespace content {
-
-// Mojo service that dispatches ServicePort related events to a service worker.
-// Instances are always created on a worker thread, and all methods are only
-// called on that same thread. Lifetime of this class is tied to both the mojo
-// channel and the lifetime of the worker thread. If either the channel is
-// disconnected or the worker thread stops the instance deletes itself.
-class ServicePortDispatcherImpl : public ServicePortDispatcher,
- public WorkerThread::Observer {
- public:
- static void Create(base::WeakPtr<blink::WebServiceWorkerContextProxy> proxy,
- mojo::InterfaceRequest<ServicePortDispatcher> request);
-
- ~ServicePortDispatcherImpl() override;
-
- private:
- ServicePortDispatcherImpl(
- base::WeakPtr<blink::WebServiceWorkerContextProxy> proxy,
- mojo::InterfaceRequest<ServicePortDispatcher> request);
-
- // WorkerThread::Observer implementation.
- void WillStopCurrentWorkerThread() override;
-
- // ServicePortDispatcher implementation.
- void Connect(const mojo::String& target_url,
- const mojo::String& origin,
- int32_t port_id,
- const ConnectCallback& callback) override;
-
- mojo::StrongBinding<ServicePortDispatcher> binding_;
- base::WeakPtr<blink::WebServiceWorkerContextProxy> proxy_;
-
- DISALLOW_COPY_AND_ASSIGN(ServicePortDispatcherImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_NAVIGATOR_CONNECT_SERVICE_PORT_DISPATCHER_IMPL_H_
diff --git a/chromium/content/child/navigator_connect/service_port_provider.cc b/chromium/content/child/navigator_connect/service_port_provider.cc
deleted file mode 100644
index 79bf8a5897b..00000000000
--- a/chromium/content/child/navigator_connect/service_port_provider.cc
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/child/navigator_connect/service_port_provider.h"
-
-#include <utility>
-
-#include "base/lazy_instance.h"
-#include "base/single_thread_task_runner.h"
-#include "base/task_runner_util.h"
-#include "content/child/child_thread_impl.h"
-#include "content/child/webmessageportchannel_impl.h"
-#include "content/common/message_port_messages.h"
-#include "content/common/service_port_type_converters.h"
-#include "content/public/common/navigator_connect_client.h"
-#include "mojo/common/common_type_converters.h"
-#include "third_party/WebKit/public/platform/WebURL.h"
-#include "third_party/WebKit/public/platform/modules/navigator_services/WebServicePortProviderClient.h"
-
-namespace content {
-
-namespace {
-
-void ConnectToServiceOnMainThread(
- mojo::InterfaceRequest<ServicePortService> ptr) {
- ChildThreadImpl::current()->service_registry()->ConnectToRemoteService(
- std::move(ptr));
-}
-
-} // namespace
-
-ServicePortProvider::ServicePortProvider(
- blink::WebServicePortProviderClient* client,
- const scoped_refptr<base::SingleThreadTaskRunner>& main_loop)
- : client_(client), binding_(this), main_loop_(main_loop) {
- DCHECK(client_);
- AddRef();
-}
-
-void ServicePortProvider::destroy() {
- Release();
-}
-
-void ServicePortProvider::connect(
- const blink::WebURL& target_url,
- const blink::WebString& origin,
- blink::WebServicePortConnectCallbacks* raw_callbacks) {
- scoped_ptr<blink::WebServicePortConnectCallbacks> callbacks(raw_callbacks);
- // base::Unretained is safe here, as the mojo channel will be deleted (and
- // will wipe its callbacks) before 'this' is deleted.
- GetServicePortServicePtr()->Connect(
- target_url.string().utf8(), origin.utf8(),
- base::Bind(&ServicePortProvider::OnConnectResult, base::Unretained(this),
- base::Passed(&callbacks)));
-}
-
-void ServicePortProvider::postMessage(
- blink::WebServicePortID port_id,
- const blink::WebString& message,
- blink::WebMessagePortChannelArray* channels) {
- // TODO(mek): If necesary, handle sending messages as values for system
- // services.
-
- // Have to extract IDs for the transferred MessagePorts on the main thread
- // to make sure all ports have been fully initialized. Actually sending the
- // message can safely be done on this thread, and using mojo, since there
- // shouldn't be any other IPCs where ordering matters.
- scoped_ptr<blink::WebMessagePortChannelArray> channel_array(channels);
- base::PostTaskAndReplyWithResult(
- main_loop_.get(), FROM_HERE,
- base::Bind(
- &WebMessagePortChannelImpl::ExtractMessagePortIDsWithoutQueueing,
- base::Passed(&channel_array)),
- base::Bind(&ServicePortProvider::PostMessageToBrowser, this, port_id,
- // We cast WebString to string16 before crossing threads.
- // for thread-safety.
- static_cast<base::string16>(message)));
-}
-
-void ServicePortProvider::closePort(blink::WebServicePortID port_id) {
- GetServicePortServicePtr()->ClosePort(port_id);
-}
-
-void ServicePortProvider::PostMessageToPort(
- int32_t port_id,
- const mojo::String& message,
- mojo::Array<MojoTransferredMessagePortPtr> ports,
- mojo::Array<int32_t> new_routing_ids) {
- client_->postMessage(port_id, message.To<base::string16>(),
- WebMessagePortChannelImpl::CreatePorts(
- ports.To<std::vector<TransferredMessagePort>>(),
- new_routing_ids.To<std::vector<int>>(), main_loop_));
-}
-
-ServicePortProvider::~ServicePortProvider() {
-}
-
-void ServicePortProvider::PostMessageToBrowser(
- int port_id,
- const base::string16& message,
- const std::vector<TransferredMessagePort> ports) {
- GetServicePortServicePtr()->PostMessageToPort(
- port_id, mojo::String::From(message),
- mojo::Array<MojoTransferredMessagePortPtr>::From(ports));
-}
-
-void ServicePortProvider::OnConnectResult(
- scoped_ptr<blink::WebServicePortConnectCallbacks> callbacks,
- ServicePortConnectResult result,
- int32_t port_id) {
- if (result == SERVICE_PORT_CONNECT_RESULT_ACCEPT) {
- callbacks->onSuccess(port_id);
- } else {
- callbacks->onError();
- }
-}
-
-ServicePortServicePtr& ServicePortProvider::GetServicePortServicePtr() {
- if (!service_port_service_.get()) {
- mojo::InterfaceRequest<ServicePortService> request =
- mojo::GetProxy(&service_port_service_);
- main_loop_->PostTask(FROM_HERE, base::Bind(&ConnectToServiceOnMainThread,
- base::Passed(&request)));
-
- // Setup channel for browser to post events back to this class.
- ServicePortServiceClientPtr client_ptr;
- binding_.Bind(GetProxy(&client_ptr));
- service_port_service_->SetClient(std::move(client_ptr));
- }
- return service_port_service_;
-}
-
-} // namespace content
diff --git a/chromium/content/child/navigator_connect/service_port_provider.h b/chromium/content/child/navigator_connect/service_port_provider.h
deleted file mode 100644
index c84439197b8..00000000000
--- a/chromium/content/child/navigator_connect/service_port_provider.h
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_CHILD_NAVIGATOR_CONNECT_SERVICE_PORT_PROVIDER_H_
-#define CONTENT_CHILD_NAVIGATOR_CONNECT_SERVICE_PORT_PROVIDER_H_
-
-#include <stdint.h>
-
-#include "base/compiler_specific.h"
-#include "base/id_map.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "content/child/worker_thread_registry.h"
-#include "content/common/service_port_service.mojom.h"
-#include "mojo/public/cpp/bindings/binding.h"
-#include "third_party/WebKit/public/platform/modules/navigator_services/WebServicePortProvider.h"
-
-class GURL;
-
-namespace base {
-class SingleThreadTaskRunner;
-}
-
-namespace blink {
-class WebServicePortProviderClient;
-class WebString;
-}
-
-namespace IPC {
-class Message;
-}
-
-namespace content {
-class ServiceRegistry;
-struct TransferredMessagePort;
-
-// Main entry point for the navigator.services API in a child process. This
-// implementes the blink API and passes calls on to the browser process, as
-// well as receives events from the browser process to pass back on to blink.
-// One instance of this class is created for each ServicePortCollection, the
-// instance lives on the worker thread it is associated with, and is
-// conceptually owned by the ServicePortCollection in blink. Refcounted because
-// some operations might require asynchronous operations that require this class
-// to potentially stick around for a bit longer after a ServicePortCollection is
-// destroyed.
-// Uses mojo to communicate with the browser process.
-class ServicePortProvider
- : public blink::WebServicePortProvider,
- public ServicePortServiceClient,
- public base::RefCountedThreadSafe<ServicePortProvider> {
- public:
- ServicePortProvider(
- blink::WebServicePortProviderClient* client,
- const scoped_refptr<base::SingleThreadTaskRunner>& main_loop);
-
- // WebServicePortProvider implementation.
- void destroy() override;
- void connect(const blink::WebURL& target_url,
- const blink::WebString& origin,
- blink::WebServicePortConnectCallbacks* callbacks) override;
- void postMessage(blink::WebServicePortID port_id,
- const blink::WebString& message,
- blink::WebMessagePortChannelArray* channels) override;
- void closePort(blink::WebServicePortID port_id) override;
-
- // ServicePortServiceClient implementation.
- void PostMessageToPort(int32_t port_id,
- const mojo::String& message,
- mojo::Array<MojoTransferredMessagePortPtr> ports,
- mojo::Array<int32_t> new_routing_ids) override;
-
- private:
- ~ServicePortProvider() override;
- friend class base::RefCountedThreadSafe<ServicePortProvider>;
-
- void PostMessageToBrowser(int port_id,
- const base::string16& message,
- const std::vector<TransferredMessagePort> ports);
-
- void OnConnectResult(
- scoped_ptr<blink::WebServicePortConnectCallbacks> callbacks,
- ServicePortConnectResult result,
- int32_t port_id);
-
- blink::WebServicePortProviderClient* client_;
-
- // Helper method that returns an initialized ServicePortServicePtr.
- ServicePortServicePtr& GetServicePortServicePtr();
- mojo::Binding<ServicePortServiceClient> binding_;
-
- ServicePortServicePtr service_port_service_;
-
- scoped_refptr<base::SingleThreadTaskRunner> main_loop_;
-
- DISALLOW_COPY_AND_ASSIGN(ServicePortProvider);
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_NAVIGATOR_CONNECT_SERVICE_PORT_PROVIDER_H_
diff --git a/chromium/content/child/notifications/notification_data_conversions.cc b/chromium/content/child/notifications/notification_data_conversions.cc
index 63f570f7388..be49a7a0a84 100644
--- a/chromium/content/child/notifications/notification_data_conversions.cc
+++ b/chromium/content/child/notifications/notification_data_conversions.cc
@@ -7,6 +7,8 @@
#include <stddef.h>
#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
+#include "third_party/WebKit/public/platform/URLConversion.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/WebVector.h"
@@ -38,17 +40,35 @@ PlatformNotificationData ToPlatformNotificationData(
platform_data.lang = base::UTF16ToUTF8(base::StringPiece16(web_data.lang));
platform_data.body = web_data.body;
platform_data.tag = base::UTF16ToUTF8(base::StringPiece16(web_data.tag));
- platform_data.icon = GURL(web_data.icon.string());
+ platform_data.icon = blink::WebStringToGURL(web_data.icon.string());
+ platform_data.badge = blink::WebStringToGURL(web_data.badge.string());
platform_data.vibration_pattern.assign(web_data.vibrate.begin(),
web_data.vibrate.end());
+ platform_data.timestamp = base::Time::FromJsTime(web_data.timestamp);
+ platform_data.renotify = web_data.renotify;
platform_data.silent = web_data.silent;
platform_data.require_interaction = web_data.requireInteraction;
platform_data.data.assign(web_data.data.begin(), web_data.data.end());
platform_data.actions.resize(web_data.actions.size());
for (size_t i = 0; i < web_data.actions.size(); ++i) {
+ switch (web_data.actions[i].type) {
+ case blink::WebNotificationAction::Button:
+ platform_data.actions[i].type =
+ PLATFORM_NOTIFICATION_ACTION_TYPE_BUTTON;
+ break;
+ case blink::WebNotificationAction::Text:
+ platform_data.actions[i].type = PLATFORM_NOTIFICATION_ACTION_TYPE_TEXT;
+ break;
+ default:
+ NOTREACHED() << "Unknown notification action type: "
+ << web_data.actions[i].type;
+ }
platform_data.actions[i].action =
base::UTF16ToUTF8(base::StringPiece16(web_data.actions[i].action));
platform_data.actions[i].title = web_data.actions[i].title;
+ platform_data.actions[i].icon =
+ blink::WebStringToGURL(web_data.actions[i].icon.string());
+ platform_data.actions[i].placeholder = web_data.actions[i].placeholder;
}
return platform_data;
@@ -75,7 +95,10 @@ WebNotificationData ToWebNotificationData(
web_data.body = platform_data.body;
web_data.tag = blink::WebString::fromUTF8(platform_data.tag);
web_data.icon = blink::WebURL(platform_data.icon);
+ web_data.badge = blink::WebURL(platform_data.badge);
web_data.vibrate = platform_data.vibration_pattern;
+ web_data.timestamp = platform_data.timestamp.ToJsTime();
+ web_data.renotify = platform_data.renotify;
web_data.silent = platform_data.silent;
web_data.requireInteraction = platform_data.require_interaction;
web_data.data = platform_data.data;
@@ -83,9 +106,22 @@ WebNotificationData ToWebNotificationData(
platform_data.actions.size());
web_data.actions.swap(resized);
for (size_t i = 0; i < platform_data.actions.size(); ++i) {
+ switch (platform_data.actions[i].type) {
+ case PLATFORM_NOTIFICATION_ACTION_TYPE_BUTTON:
+ web_data.actions[i].type = blink::WebNotificationAction::Button;
+ break;
+ case PLATFORM_NOTIFICATION_ACTION_TYPE_TEXT:
+ web_data.actions[i].type = blink::WebNotificationAction::Text;
+ break;
+ default:
+ NOTREACHED() << "Unknown platform data type: "
+ << platform_data.actions[i].type;
+ }
web_data.actions[i].action =
blink::WebString::fromUTF8(platform_data.actions[i].action);
web_data.actions[i].title = platform_data.actions[i].title;
+ web_data.actions[i].icon = blink::WebURL(platform_data.actions[i].icon);
+ web_data.actions[i].placeholder = platform_data.actions[i].placeholder;
}
return web_data;
diff --git a/chromium/content/child/notifications/notification_data_conversions_unittest.cc b/chromium/content/child/notifications/notification_data_conversions_unittest.cc
index 5c6a5decb3b..01daee19979 100644
--- a/chromium/content/child/notifications/notification_data_conversions_unittest.cc
+++ b/chromium/content/child/notifications/notification_data_conversions_unittest.cc
@@ -23,12 +23,17 @@ const char kNotificationLang[] = "nl";
const char kNotificationBody[] = "Hello, world!";
const char kNotificationTag[] = "my_tag";
const char kNotificationIconUrl[] = "https://example.com/icon.png";
+const char kNotificationBadgeUrl[] = "https://example.com/badge.png";
const int kNotificationVibrationPattern[] = {100, 200, 300};
+const double kNotificationTimestamp = 621046800.;
const unsigned char kNotificationData[] = {0xdf, 0xff, 0x0, 0x0, 0xff, 0xdf};
const char kAction1Name[] = "btn1";
const char kAction1Title[] = "Button 1";
+const char kAction1IconUrl[] = "https://example.com/action_icon_1.png";
+const char kAction1Placeholder[] = "Run into the... friendliness pellets.";
const char kAction2Name[] = "btn2";
const char kAction2Title[] = "Button 2";
+const char kAction2IconUrl[] = "https://example.com/action_icon_2.png";
TEST(NotificationDataConversionsTest, ToPlatformNotificationData) {
blink::WebNotificationData web_data;
@@ -38,8 +43,11 @@ TEST(NotificationDataConversionsTest, ToPlatformNotificationData) {
web_data.body = blink::WebString::fromUTF8(kNotificationBody);
web_data.tag = blink::WebString::fromUTF8(kNotificationTag);
web_data.icon = blink::WebURL(GURL(kNotificationIconUrl));
+ web_data.badge = blink::WebURL(GURL(kNotificationBadgeUrl));
web_data.vibrate = blink::WebVector<int>(
kNotificationVibrationPattern, arraysize(kNotificationVibrationPattern));
+ web_data.timestamp = kNotificationTimestamp;
+ web_data.renotify = true;
web_data.silent = true;
web_data.requireInteraction = true;
web_data.data =
@@ -47,10 +55,17 @@ TEST(NotificationDataConversionsTest, ToPlatformNotificationData) {
web_data.actions =
blink::WebVector<blink::WebNotificationAction>(static_cast<size_t>(2));
+ web_data.actions[0].type = blink::WebNotificationAction::Button;
web_data.actions[0].action = blink::WebString::fromUTF8(kAction1Name);
web_data.actions[0].title = blink::WebString::fromUTF8(kAction1Title);
+ web_data.actions[0].icon = blink::WebURL(GURL(kAction1IconUrl));
+ web_data.actions[0].placeholder =
+ blink::WebString::fromUTF8(kAction1Placeholder);
+ web_data.actions[1].type = blink::WebNotificationAction::Text;
web_data.actions[1].action = blink::WebString::fromUTF8(kAction2Name);
web_data.actions[1].title = blink::WebString::fromUTF8(kAction2Title);
+ web_data.actions[1].icon = blink::WebURL(GURL(kAction2IconUrl));
+ web_data.actions[1].placeholder = blink::WebString();
PlatformNotificationData platform_data = ToPlatformNotificationData(web_data);
EXPECT_EQ(base::ASCIIToUTF16(kNotificationTitle), platform_data.title);
@@ -60,20 +75,33 @@ TEST(NotificationDataConversionsTest, ToPlatformNotificationData) {
EXPECT_EQ(base::ASCIIToUTF16(kNotificationBody), platform_data.body);
EXPECT_EQ(kNotificationTag, platform_data.tag);
EXPECT_EQ(kNotificationIconUrl, platform_data.icon.spec());
+ EXPECT_EQ(kNotificationBadgeUrl, platform_data.badge.spec());
+ EXPECT_TRUE(platform_data.renotify);
EXPECT_TRUE(platform_data.silent);
EXPECT_TRUE(platform_data.require_interaction);
EXPECT_THAT(platform_data.vibration_pattern,
testing::ElementsAreArray(kNotificationVibrationPattern));
+ EXPECT_DOUBLE_EQ(kNotificationTimestamp, platform_data.timestamp.ToJsTime());
ASSERT_EQ(web_data.data.size(), platform_data.data.size());
for (size_t i = 0; i < web_data.data.size(); ++i)
EXPECT_EQ(web_data.data[i], platform_data.data[i]);
ASSERT_EQ(web_data.actions.size(), platform_data.actions.size());
+ EXPECT_EQ(PLATFORM_NOTIFICATION_ACTION_TYPE_BUTTON,
+ platform_data.actions[0].type);
EXPECT_EQ(kAction1Name, platform_data.actions[0].action);
EXPECT_EQ(base::ASCIIToUTF16(kAction1Title), platform_data.actions[0].title);
+ EXPECT_EQ(kAction1IconUrl, platform_data.actions[0].icon.spec());
+ EXPECT_EQ(base::ASCIIToUTF16(kAction1Placeholder),
+ platform_data.actions[0].placeholder.string());
+ EXPECT_FALSE(platform_data.actions[0].placeholder.is_null());
+ EXPECT_EQ(PLATFORM_NOTIFICATION_ACTION_TYPE_TEXT,
+ platform_data.actions[1].type);
EXPECT_EQ(kAction2Name, platform_data.actions[1].action);
EXPECT_EQ(base::ASCIIToUTF16(kAction2Title), platform_data.actions[1].title);
+ EXPECT_EQ(kAction2IconUrl, platform_data.actions[1].icon.spec());
+ EXPECT_TRUE(platform_data.actions[1].placeholder.is_null());
}
TEST(NotificationDataConversionsTest, ToWebNotificationData) {
@@ -91,15 +119,25 @@ TEST(NotificationDataConversionsTest, ToWebNotificationData) {
platform_data.body = base::ASCIIToUTF16(kNotificationBody);
platform_data.tag = kNotificationTag;
platform_data.icon = GURL(kNotificationIconUrl);
+ platform_data.badge = GURL(kNotificationBadgeUrl);
platform_data.vibration_pattern = vibration_pattern;
+ platform_data.timestamp = base::Time::FromJsTime(kNotificationTimestamp);
+ platform_data.renotify = true;
platform_data.silent = true;
platform_data.require_interaction = true;
platform_data.data = developer_data;
platform_data.actions.resize(2);
+ platform_data.actions[0].type = PLATFORM_NOTIFICATION_ACTION_TYPE_BUTTON;
platform_data.actions[0].action = kAction1Name;
platform_data.actions[0].title = base::ASCIIToUTF16(kAction1Title);
+ platform_data.actions[0].icon = GURL(kAction1IconUrl);
+ platform_data.actions[0].placeholder =
+ base::NullableString16(base::ASCIIToUTF16(kAction1Placeholder), false);
+ platform_data.actions[1].type = PLATFORM_NOTIFICATION_ACTION_TYPE_TEXT;
platform_data.actions[1].action = kAction2Name;
platform_data.actions[1].title = base::ASCIIToUTF16(kAction2Title);
+ platform_data.actions[1].icon = GURL(kAction2IconUrl);
+ platform_data.actions[1].placeholder = base::NullableString16();
blink::WebNotificationData web_data = ToWebNotificationData(platform_data);
EXPECT_EQ(kNotificationTitle, web_data.title);
@@ -109,11 +147,14 @@ TEST(NotificationDataConversionsTest, ToWebNotificationData) {
EXPECT_EQ(kNotificationBody, web_data.body);
EXPECT_EQ(kNotificationTag, web_data.tag);
EXPECT_EQ(kNotificationIconUrl, web_data.icon.string());
+ EXPECT_EQ(kNotificationBadgeUrl, web_data.badge.string());
ASSERT_EQ(vibration_pattern.size(), web_data.vibrate.size());
for (size_t i = 0; i < vibration_pattern.size(); ++i)
EXPECT_EQ(vibration_pattern[i], web_data.vibrate[i]);
+ EXPECT_DOUBLE_EQ(kNotificationTimestamp, web_data.timestamp);
+ EXPECT_TRUE(web_data.renotify);
EXPECT_TRUE(web_data.silent);
EXPECT_TRUE(web_data.requireInteraction);
@@ -122,10 +163,16 @@ TEST(NotificationDataConversionsTest, ToWebNotificationData) {
EXPECT_EQ(developer_data[i], web_data.data[i]);
ASSERT_EQ(platform_data.actions.size(), web_data.actions.size());
+ EXPECT_EQ(blink::WebNotificationAction::Button, web_data.actions[0].type);
EXPECT_EQ(kAction1Name, web_data.actions[0].action);
EXPECT_EQ(kAction1Title, web_data.actions[0].title);
+ EXPECT_EQ(kAction1IconUrl, web_data.actions[0].icon.string());
+ EXPECT_EQ(kAction1Placeholder, web_data.actions[0].placeholder);
+ EXPECT_EQ(blink::WebNotificationAction::Text, web_data.actions[1].type);
EXPECT_EQ(kAction2Name, web_data.actions[1].action);
EXPECT_EQ(kAction2Title, web_data.actions[1].title);
+ EXPECT_EQ(kAction2IconUrl, web_data.actions[1].icon.string());
+ EXPECT_TRUE(web_data.actions[1].placeholder.isNull());
}
TEST(NotificationDataConversionsTest, NotificationDataDirectionality) {
@@ -159,4 +206,41 @@ TEST(NotificationDataConversionsTest, NotificationDataDirectionality) {
}
}
+TEST(NotificationDataConversionsTest, TimeEdgeCaseValueBehaviour) {
+ {
+ blink::WebNotificationData web_data;
+ web_data.timestamp =
+ static_cast<double>(std::numeric_limits<unsigned long long>::max());
+
+ blink::WebNotificationData copied_data =
+ ToWebNotificationData(ToPlatformNotificationData(web_data));
+ EXPECT_NE(web_data.timestamp, copied_data.timestamp);
+ }
+ {
+ blink::WebNotificationData web_data;
+ web_data.timestamp =
+ static_cast<double>(9211726771200000000ull); // January 1, 293878
+
+ blink::WebNotificationData copied_data =
+ ToWebNotificationData(ToPlatformNotificationData(web_data));
+ EXPECT_NE(web_data.timestamp, copied_data.timestamp);
+ }
+ {
+ blink::WebNotificationData web_data;
+ web_data.timestamp = 0;
+
+ blink::WebNotificationData copied_data =
+ ToWebNotificationData(ToPlatformNotificationData(web_data));
+ EXPECT_EQ(web_data.timestamp, copied_data.timestamp);
+ }
+ {
+ blink::WebNotificationData web_data;
+ web_data.timestamp = 0;
+
+ blink::WebNotificationData copied_data =
+ ToWebNotificationData(ToPlatformNotificationData(web_data));
+ EXPECT_EQ(web_data.timestamp, copied_data.timestamp);
+ }
+}
+
} // namespace content
diff --git a/chromium/content/child/notifications/notification_image_loader.cc b/chromium/content/child/notifications/notification_image_loader.cc
index 4eed91fa3be..4ad37f85994 100644
--- a/chromium/content/child/notifications/notification_image_loader.cc
+++ b/chromium/content/child/notifications/notification_image_loader.cc
@@ -4,9 +4,11 @@
#include "content/child/notifications/notification_image_loader.h"
+#include "base/bind.h"
+#include "base/location.h"
#include "base/logging.h"
-#include "base/thread_task_runner_handle.h"
-#include "content/child/child_thread_impl.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/single_thread_task_runner.h"
#include "content/child/image_decoder.h"
#include "third_party/WebKit/public/platform/Platform.h"
#include "third_party/WebKit/public/platform/WebURL.h"
@@ -23,24 +25,22 @@ namespace content {
NotificationImageLoader::NotificationImageLoader(
const ImageLoadCompletedCallback& callback,
- const scoped_refptr<base::SingleThreadTaskRunner>& worker_task_runner)
+ const scoped_refptr<base::SingleThreadTaskRunner>& worker_task_runner,
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner)
: callback_(callback),
worker_task_runner_(worker_task_runner),
- notification_id_(0),
+ main_task_runner_(main_task_runner),
completed_(false) {}
NotificationImageLoader::~NotificationImageLoader() {
- if (main_thread_task_runner_)
- DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
}
-void NotificationImageLoader::StartOnMainThread(int notification_id,
- const GURL& image_url) {
- DCHECK(ChildThreadImpl::current());
+void NotificationImageLoader::StartOnMainThread(const GURL& image_url) {
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
DCHECK(!url_loader_);
- main_thread_task_runner_ = base::ThreadTaskRunnerHandle::Get();
- notification_id_ = notification_id;
+ start_time_ = base::TimeTicks::Now();
WebURL image_web_url(image_url);
WebURLRequest request(image_web_url);
@@ -66,6 +66,9 @@ void NotificationImageLoader::didFinishLoading(
int64_t total_encoded_data_length) {
DCHECK(!completed_);
+ UMA_HISTOGRAM_LONG_TIMES("Notifications.Icon.LoadFinishTime",
+ base::TimeTicks::Now() - start_time_);
+
RunCallbackOnWorkerThread();
}
@@ -74,6 +77,9 @@ void NotificationImageLoader::didFail(WebURLLoader* loader,
if (completed_)
return;
+ UMA_HISTOGRAM_LONG_TIMES("Notifications.Icon.LoadFailTime",
+ base::TimeTicks::Now() - start_time_);
+
RunCallbackOnWorkerThread();
}
@@ -84,15 +90,18 @@ void NotificationImageLoader::RunCallbackOnWorkerThread() {
SkBitmap icon = GetDecodedImage();
if (worker_task_runner_->BelongsToCurrentThread()) {
- callback_.Run(notification_id_, icon);
+ callback_.Run(icon);
} else {
- worker_task_runner_->PostTask(
- FROM_HERE, base::Bind(callback_, notification_id_, icon));
+ worker_task_runner_->PostTask(FROM_HERE, base::Bind(callback_, icon));
}
}
SkBitmap NotificationImageLoader::GetDecodedImage() const {
DCHECK(completed_);
+
+ UMA_HISTOGRAM_CUSTOM_COUNTS("Notifications.Icon.FileSize", buffer_.size(), 1,
+ 10000000 /* ~10mb */, 50);
+
if (buffer_.empty())
return SkBitmap();
@@ -101,8 +110,8 @@ SkBitmap NotificationImageLoader::GetDecodedImage() const {
}
void NotificationImageLoader::DeleteOnCorrectThread() const {
- if (!ChildThreadImpl::current()) {
- main_thread_task_runner_->DeleteSoon(FROM_HERE, this);
+ if (!main_task_runner_->BelongsToCurrentThread()) {
+ main_task_runner_->DeleteSoon(FROM_HERE, this);
return;
}
diff --git a/chromium/content/child/notifications/notification_image_loader.h b/chromium/content/child/notifications/notification_image_loader.h
index 33297c973d0..96405f147ff 100644
--- a/chromium/content/child/notifications/notification_image_loader.h
+++ b/chromium/content/child/notifications/notification_image_loader.h
@@ -7,13 +7,14 @@
#include <stdint.h>
+#include <memory>
#include <vector>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/sequenced_task_runner_helpers.h"
+#include "base/time/time.h"
#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
class GURL;
@@ -33,6 +34,10 @@ namespace content {
struct NotificationImageLoaderDeleter;
+// The |image| may be empty if the request failed or the image data could not be
+// decoded.
+using ImageLoadCompletedCallback = base::Callback<void(const SkBitmap& image)>;
+
// Downloads the image associated with a notification and decodes the received
// image. This must be completed before notifications are shown to the user.
// Image downloaders must not be re-used for multiple notifications.
@@ -43,16 +48,15 @@ class NotificationImageLoader
: public blink::WebURLLoaderClient,
public base::RefCountedThreadSafe<NotificationImageLoader,
NotificationImageLoaderDeleter> {
- using ImageLoadCompletedCallback = base::Callback<void(int, const SkBitmap&)>;
-
public:
NotificationImageLoader(
const ImageLoadCompletedCallback& callback,
- const scoped_refptr<base::SingleThreadTaskRunner>& worker_task_runner);
+ const scoped_refptr<base::SingleThreadTaskRunner>& worker_task_runner,
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner);
// Asynchronously starts loading |image_url| using a Blink WebURLLoader. Must
// only be called on the main thread.
- void StartOnMainThread(int notification_id, const GURL& image_url);
+ void StartOnMainThread(const GURL& image_url);
// blink::WebURLLoaderClient implementation.
void didReceiveData(blink::WebURLLoader* loader,
@@ -88,15 +92,16 @@ class NotificationImageLoader
ImageLoadCompletedCallback callback_;
scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner_;
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
- int notification_id_;
bool completed_;
- scoped_ptr<blink::WebURLLoader> url_loader_;
+ std::unique_ptr<blink::WebURLLoader> url_loader_;
std::vector<uint8_t> buffer_;
+ base::TimeTicks start_time_;
+
DISALLOW_COPY_AND_ASSIGN(NotificationImageLoader);
};
diff --git a/chromium/content/child/notifications/notification_manager.cc b/chromium/content/child/notifications/notification_manager.cc
index 30d28eed966..8961f7a656d 100644
--- a/chromium/content/child/notifications/notification_manager.cc
+++ b/chromium/content/child/notifications/notification_manager.cc
@@ -4,7 +4,6 @@
#include "content/child/notifications/notification_manager.h"
-#include <cmath>
#include <utility>
#include "base/lazy_instance.h"
@@ -17,10 +16,11 @@
#include "content/child/service_worker/web_service_worker_registration_impl.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/notification_constants.h"
+#include "content/public/common/notification_resources.h"
#include "content/public/common/platform_notification_data.h"
+#include "third_party/WebKit/public/platform/URLConversion.h"
#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/platform/modules/notifications/WebNotificationDelegate.h"
-#include "third_party/skia/include/core/SkBitmap.h"
using blink::WebNotificationPermission;
@@ -31,6 +31,20 @@ int CurrentWorkerId() {
return WorkerThread::GetCurrentId();
}
+// Checks whether |notification_data| specifies any non-empty resources that
+// need to be fetched.
+bool HasResourcesToFetch(const blink::WebNotificationData& notification_data) {
+ if (!notification_data.icon.isEmpty())
+ return true;
+ if (!notification_data.badge.isEmpty())
+ return true;
+ for (const auto& action : notification_data.actions) {
+ if (!action.icon.isEmpty())
+ return true;
+ }
+ return false;
+}
+
} // namespace
static base::LazyInstance<base::ThreadLocalPointer<NotificationManager>>::Leaky
@@ -42,7 +56,7 @@ NotificationManager::NotificationManager(
NotificationDispatcher* notification_dispatcher)
: thread_safe_sender_(thread_safe_sender),
notification_dispatcher_(notification_dispatcher),
- pending_notifications_(main_thread_task_runner) {
+ notifications_tracker_(main_thread_task_runner) {
g_notification_manager_tls.Pointer()->Set(this);
}
@@ -72,15 +86,18 @@ void NotificationManager::show(
const blink::WebSecurityOrigin& origin,
const blink::WebNotificationData& notification_data,
blink::WebNotificationDelegate* delegate) {
- if (notification_data.icon.isEmpty()) {
- DisplayPageNotification(origin, notification_data, delegate, SkBitmap());
+ DCHECK_EQ(0u, notification_data.actions.size());
+
+ if (!HasResourcesToFetch(notification_data)) {
+ DisplayPageNotification(origin, notification_data, delegate,
+ NotificationResources());
return;
}
- pending_notifications_.FetchPageNotificationResources(
+ notifications_tracker_.FetchResources(
notification_data, delegate,
base::Bind(&NotificationManager::DisplayPageNotification,
- base::Unretained(this), // this owns |pending_notifications_|
+ base::Unretained(this), // this owns |notifications_tracker_|
origin, notification_data, delegate));
}
@@ -90,12 +107,14 @@ void NotificationManager::showPersistent(
blink::WebServiceWorkerRegistration* service_worker_registration,
blink::WebNotificationShowCallbacks* callbacks) {
DCHECK(service_worker_registration);
+
int64_t service_worker_registration_id =
static_cast<WebServiceWorkerRegistrationImpl*>(
service_worker_registration)
->registration_id();
- scoped_ptr<blink::WebNotificationShowCallbacks> owned_callbacks(callbacks);
+ std::unique_ptr<blink::WebNotificationShowCallbacks> owned_callbacks(
+ callbacks);
// Verify that the author-provided payload size does not exceed our limit.
// This is an implementation-defined limit to prevent abuse of notification
@@ -106,25 +125,34 @@ void NotificationManager::showPersistent(
// is outside of the boundaries set by the specification, but it gives authors
// an indication that something has gone wrong.
size_t author_data_size = notification_data.data.size();
- UMA_HISTOGRAM_MEMORY_KB("Notifications.AuthorDataSizeKB",
- static_cast<int>(ceil(author_data_size / 1024.0)));
+
+ UMA_HISTOGRAM_COUNTS_1000("Notifications.AuthorDataSize", author_data_size);
if (author_data_size > PlatformNotificationData::kMaximumDeveloperDataSize) {
owned_callbacks->onError();
return;
}
- if (notification_data.icon.isEmpty()) {
- DisplayPersistentNotification(origin, notification_data,
- service_worker_registration_id,
- std::move(owned_callbacks), SkBitmap());
+ if (!HasResourcesToFetch(notification_data)) {
+ NotificationResources notification_resources;
+
+ // Action indices are expected to have a corresponding icon bitmap, which
+ // may be empty when the developer provided no (or an invalid) icon.
+ if (!notification_data.actions.isEmpty()) {
+ notification_resources.action_icons.resize(
+ notification_data.actions.size());
+ }
+
+ DisplayPersistentNotification(
+ origin, notification_data, service_worker_registration_id,
+ std::move(owned_callbacks), notification_resources);
return;
}
- pending_notifications_.FetchPersistentNotificationResources(
- notification_data,
+ notifications_tracker_.FetchResources(
+ notification_data, nullptr /* delegate */,
base::Bind(&NotificationManager::DisplayPersistentNotification,
- base::Unretained(this), // this owns |pending_notifications_|
+ base::Unretained(this), // this owns |notifications_tracker_|
origin, notification_data, service_worker_registration_id,
base::Passed(&owned_callbacks)));
}
@@ -157,7 +185,7 @@ void NotificationManager::getNotifications(
}
void NotificationManager::close(blink::WebNotificationDelegate* delegate) {
- if (pending_notifications_.CancelPageNotificationFetches(delegate))
+ if (notifications_tracker_.CancelResourceFetches(delegate))
return;
for (auto& iter : active_page_notifications_) {
@@ -182,12 +210,12 @@ void NotificationManager::closePersistent(
// TODO(mkwst): This is potentially doing the wrong thing with unique
// origins. Perhaps also 'file:', 'blob:' and 'filesystem:'. See
// https://crbug.com/490074 for detail.
- GURL(origin.toString()), persistent_notification_id));
+ blink::WebStringToGURL(origin.toString()), persistent_notification_id));
}
void NotificationManager::notifyDelegateDestroyed(
blink::WebNotificationDelegate* delegate) {
- if (pending_notifications_.CancelPageNotificationFetches(delegate))
+ if (notifications_tracker_.CancelResourceFetches(delegate))
return;
for (auto& iter : active_page_notifications_) {
@@ -207,7 +235,7 @@ WebNotificationPermission NotificationManager::checkPermission(
// origins. Perhaps also 'file:', 'blob:' and 'filesystem:'. See
// https://crbug.com/490074 for detail.
thread_safe_sender_->Send(new PlatformNotificationHostMsg_CheckPermission(
- GURL(origin.toString()), &permission));
+ blink::WebStringToGURL(origin.toString()), &permission));
return permission;
}
@@ -303,7 +331,10 @@ void NotificationManager::DisplayPageNotification(
const blink::WebSecurityOrigin& origin,
const blink::WebNotificationData& notification_data,
blink::WebNotificationDelegate* delegate,
- const SkBitmap& icon) {
+ const NotificationResources& notification_resources) {
+ DCHECK_EQ(0u, notification_data.actions.size());
+ DCHECK_EQ(0u, notification_resources.action_icons.size());
+
int notification_id =
notification_dispatcher_->GenerateNotificationId(CurrentWorkerId());
@@ -312,16 +343,19 @@ void NotificationManager::DisplayPageNotification(
// origins. Perhaps also 'file:', 'blob:' and 'filesystem:'. See
// https://crbug.com/490074 for detail.
thread_safe_sender_->Send(new PlatformNotificationHostMsg_Show(
- notification_id, GURL(origin.toString()), icon,
- ToPlatformNotificationData(notification_data)));
+ notification_id, blink::WebStringToGURL(origin.toString()),
+ ToPlatformNotificationData(notification_data), notification_resources));
}
void NotificationManager::DisplayPersistentNotification(
const blink::WebSecurityOrigin& origin,
const blink::WebNotificationData& notification_data,
int64_t service_worker_registration_id,
- scoped_ptr<blink::WebNotificationShowCallbacks> callbacks,
- const SkBitmap& icon) {
+ std::unique_ptr<blink::WebNotificationShowCallbacks> callbacks,
+ const NotificationResources& notification_resources) {
+ DCHECK_EQ(notification_data.actions.size(),
+ notification_resources.action_icons.size());
+
// TODO(peter): GenerateNotificationId is more of a request id. Consider
// renaming the method in the NotificationDispatcher if this makes sense.
int request_id =
@@ -334,8 +368,9 @@ void NotificationManager::DisplayPersistentNotification(
// origins. Perhaps also 'file:', 'blob:' and 'filesystem:'. See
// https://crbug.com/490074 for detail.
thread_safe_sender_->Send(new PlatformNotificationHostMsg_ShowPersistent(
- request_id, service_worker_registration_id, GURL(origin.toString()), icon,
- ToPlatformNotificationData(notification_data)));
+ request_id, service_worker_registration_id,
+ blink::WebStringToGURL(origin.toString()),
+ ToPlatformNotificationData(notification_data), notification_resources));
}
} // namespace content
diff --git a/chromium/content/child/notifications/notification_manager.h b/chromium/content/child/notifications/notification_manager.h
index 8eb64690bb4..0f383fa5073 100644
--- a/chromium/content/child/notifications/notification_manager.h
+++ b/chromium/content/child/notifications/notification_manager.h
@@ -22,10 +22,9 @@
#include "content/public/child/worker_thread.h"
#include "third_party/WebKit/public/platform/modules/notifications/WebNotificationManager.h"
-class SkBitmap;
-
namespace content {
+struct NotificationResources;
struct PlatformNotificationData;
class ThreadSafeSender;
@@ -91,7 +90,7 @@ class NotificationManager : public blink::WebNotificationManager,
const blink::WebSecurityOrigin& origin,
const blink::WebNotificationData& notification_data,
blink::WebNotificationDelegate* delegate,
- const SkBitmap& icon);
+ const NotificationResources& notification_resources);
// To be called when a persistent notification is ready to be displayed. Will
// inform the browser process about all available data. The |callbacks| will
@@ -101,15 +100,15 @@ class NotificationManager : public blink::WebNotificationManager,
const blink::WebSecurityOrigin& origin,
const blink::WebNotificationData& notification_data,
int64_t service_worker_registration_id,
- scoped_ptr<blink::WebNotificationShowCallbacks> callbacks,
- const SkBitmap& icon);
+ std::unique_ptr<blink::WebNotificationShowCallbacks> callbacks,
+ const NotificationResources& notification_resources);
scoped_refptr<ThreadSafeSender> thread_safe_sender_;
scoped_refptr<NotificationDispatcher> notification_dispatcher_;
// Tracker which stores all pending Notifications, both page and persistent
// ones, until all their associated resources have been fetched.
- PendingNotificationsTracker pending_notifications_;
+ PendingNotificationsTracker notifications_tracker_;
// Tracks pending requests for getting a list of notifications.
IDMap<blink::WebNotificationGetCallbacks, IDMapOwnPointer>
diff --git a/chromium/content/child/notifications/pending_notification.cc b/chromium/content/child/notifications/pending_notification.cc
new file mode 100644
index 00000000000..c6365f84b5f
--- /dev/null
+++ b/chromium/content/child/notifications/pending_notification.cc
@@ -0,0 +1,123 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/child/notifications/pending_notification.h"
+
+#include <algorithm>
+
+#include "base/barrier_closure.h"
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/location.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/thread_task_runner_handle.h"
+#include "content/common/notification_constants.h"
+#include "content/public/common/notification_resources.h"
+#include "skia/ext/image_operations.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace {
+
+// Scales down |icon| to fit within |max_size_px| if its width or height is
+// larger than |max_size_px| and returns the result. Otherwise does nothing and
+// returns |icon| unchanged.
+SkBitmap ScaleDownIfNeeded(const SkBitmap& icon, int max_size_px) {
+ if (icon.width() > max_size_px || icon.height() > max_size_px) {
+ SCOPED_UMA_HISTOGRAM_TIMER("Notifications.Icon.ScaleDownTime");
+ return skia::ImageOperations::Resize(icon,
+ skia::ImageOperations::RESIZE_BEST,
+ std::min(icon.width(), max_size_px),
+ std::min(icon.height(), max_size_px));
+ }
+ return icon;
+}
+
+} // namespace
+
+PendingNotification::PendingNotification(
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner)
+ : main_task_runner_(main_task_runner), weak_factory_(this) {}
+
+PendingNotification::~PendingNotification() {}
+
+void PendingNotification::FetchResources(
+ const blink::WebNotificationData& notification_data,
+ const base::Closure& fetches_finished_callback) {
+ // TODO(mvanouwerkerk): Add a timeout mechanism: crbug.com/579137
+
+ size_t num_actions = notification_data.actions.size();
+ action_icons_.resize(num_actions);
+
+ size_t num_closures = 2 /* notification icon and badge */ + num_actions;
+ fetches_finished_barrier_closure_ =
+ base::BarrierClosure(num_closures, fetches_finished_callback);
+
+ FetchImageResource(notification_data.icon,
+ base::Bind(&PendingNotification::DidFetchNotificationIcon,
+ weak_factory_.GetWeakPtr()));
+ FetchImageResource(notification_data.badge,
+ base::Bind(&PendingNotification::DidFetchBadge,
+ weak_factory_.GetWeakPtr()));
+ for (size_t i = 0; i < num_actions; i++) {
+ FetchImageResource(notification_data.actions[i].icon,
+ base::Bind(&PendingNotification::DidFetchActionIcon,
+ weak_factory_.GetWeakPtr(), i));
+ }
+}
+
+NotificationResources PendingNotification::GetResources() const {
+ NotificationResources resources;
+ resources.notification_icon = notification_icon_;
+ resources.badge = badge_;
+ resources.action_icons = action_icons_;
+ return resources;
+}
+
+void PendingNotification::FetchImageResource(
+ const blink::WebURL& image_web_url,
+ const ImageLoadCompletedCallback& image_callback) {
+ if (image_web_url.isEmpty()) {
+ image_callback.Run(SkBitmap());
+ return;
+ }
+
+ // Explicitly convert the WebURL to a GURL before passing it to a different
+ // thread. This is important because WebURLs must not be passed between
+ // threads, and per base::Bind() semantics conversion would otherwise be done
+ // on the receiving thread.
+ GURL image_gurl(image_web_url);
+
+ scoped_refptr<NotificationImageLoader> image_loader(
+ new NotificationImageLoader(image_callback,
+ base::ThreadTaskRunnerHandle::Get(),
+ main_task_runner_));
+ image_loaders_.push_back(image_loader);
+ main_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&NotificationImageLoader::StartOnMainThread,
+ image_loader, image_gurl));
+}
+
+void PendingNotification::DidFetchNotificationIcon(const SkBitmap& bitmap) {
+ notification_icon_ =
+ ScaleDownIfNeeded(bitmap, kPlatformNotificationMaxIconSizePx);
+ fetches_finished_barrier_closure_.Run();
+}
+
+void PendingNotification::DidFetchBadge(const SkBitmap& bitmap) {
+ badge_ = ScaleDownIfNeeded(bitmap, kPlatformNotificationMaxBadgeSizePx);
+ fetches_finished_barrier_closure_.Run();
+}
+
+void PendingNotification::DidFetchActionIcon(size_t action_index,
+ const SkBitmap& bitmap) {
+ DCHECK_LT(action_index, action_icons_.size());
+
+ action_icons_[action_index] =
+ ScaleDownIfNeeded(bitmap, kPlatformNotificationMaxActionIconSizePx);
+ fetches_finished_barrier_closure_.Run();
+}
+
+} // namespace content
diff --git a/chromium/content/child/notifications/pending_notification.h b/chromium/content/child/notifications/pending_notification.h
new file mode 100644
index 00000000000..dc7036bf004
--- /dev/null
+++ b/chromium/content/child/notifications/pending_notification.h
@@ -0,0 +1,78 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_CHILD_NOTIFICATIONS_PENDING_NOTIFICATION_H_
+#define CONTENT_CHILD_NOTIFICATIONS_PENDING_NOTIFICATION_H_
+
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "content/child/notifications/notification_image_loader.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
+#include "third_party/WebKit/public/platform/modules/notifications/WebNotificationData.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace content {
+
+struct NotificationResources;
+
+// Stores the information associated with a pending notification, and fetches
+// resources for it on the main thread.
+class PendingNotification {
+ public:
+ explicit PendingNotification(
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner);
+ ~PendingNotification();
+
+ // Fetches all resources asynchronously on the main thread.
+ void FetchResources(const blink::WebNotificationData& notification_data,
+ const base::Closure& fetches_finished_callback);
+
+ // Returns a new NotificationResources populated with the resources that have
+ // been fetched.
+ NotificationResources GetResources() const;
+
+ private:
+ // Fetches an image using |image_web_url| asynchronously on the main thread.
+ // The |image_callback| will be called on the worker thread.
+ void FetchImageResource(const blink::WebURL& image_web_url,
+ const ImageLoadCompletedCallback& image_callback);
+
+ // To be called on the worker thread when the notification icon has been
+ // fetched.
+ void DidFetchNotificationIcon(const SkBitmap& bitmap);
+
+ // To be called on the worker thread when the badge has been fetched.
+ void DidFetchBadge(const SkBitmap& bitmap);
+
+ // To be called on the worker thread when an action icon has been fetched.
+ void DidFetchActionIcon(size_t action_index, const SkBitmap& bitmap);
+
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+
+ SkBitmap notification_icon_;
+
+ SkBitmap badge_;
+
+ std::vector<SkBitmap> action_icons_;
+
+ base::Closure fetches_finished_barrier_closure_;
+
+ std::vector<scoped_refptr<NotificationImageLoader>> image_loaders_;
+
+ base::WeakPtrFactory<PendingNotification> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(PendingNotification);
+};
+
+} // namespace content
+
+#endif // CONTENT_CHILD_NOTIFICATIONS_PENDING_NOTIFICATION_H_
diff --git a/chromium/content/child/notifications/pending_notifications_tracker.cc b/chromium/content/child/notifications/pending_notifications_tracker.cc
index 2ee031d4b67..bfe7dd3a362 100644
--- a/chromium/content/child/notifications/pending_notifications_tracker.cc
+++ b/chromium/content/child/notifications/pending_notifications_tracker.cc
@@ -4,59 +4,49 @@
#include "content/child/notifications/pending_notifications_tracker.h"
+#include <memory>
+
#include "base/bind.h"
-#include "base/location.h"
-#include "base/thread_task_runner_handle.h"
-#include "content/child/notifications/notification_image_loader.h"
-#include "content/child/notifications/notification_manager.h"
-#include "third_party/WebKit/public/platform/modules/notifications/WebNotificationData.h"
-#include "third_party/skia/include/core/SkBitmap.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "content/child/notifications/pending_notification.h"
+#include "content/public/common/notification_resources.h"
namespace content {
-// Stores the information associated with a pending notification.
-struct PendingNotificationsTracker::PendingNotification {
- PendingNotification(
- const scoped_refptr<NotificationImageLoader>& image_loader,
- const NotificationResourcesFetchedCallback& callback)
- : image_loader(image_loader), callback(callback) {}
-
- scoped_refptr<NotificationImageLoader> image_loader;
- NotificationResourcesFetchedCallback callback;
-};
-
PendingNotificationsTracker::PendingNotificationsTracker(
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner)
- : main_thread_task_runner_(main_thread_task_runner), weak_factory_(this) {}
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner)
+ : next_notification_id_(0), main_task_runner_(main_task_runner) {}
PendingNotificationsTracker::~PendingNotificationsTracker() {}
-void PendingNotificationsTracker::FetchPageNotificationResources(
+void PendingNotificationsTracker::FetchResources(
const blink::WebNotificationData& notification_data,
blink::WebNotificationDelegate* delegate,
- const NotificationResourcesFetchedCallback& callback) {
- delegate_to_pending_id_map_[delegate] = FetchNotificationResources(
- notification_data, callback,
- new NotificationImageLoader(
- base::Bind(&PendingNotificationsTracker::DidFetchPageNotification,
- weak_factory_.GetWeakPtr(), delegate),
- base::ThreadTaskRunnerHandle::Get()));
-}
+ const ResourcesCallback& resources_callback) {
+ int32_t notification_id = next_notification_id_++;
-void PendingNotificationsTracker::FetchPersistentNotificationResources(
- const blink::WebNotificationData& notification_data,
- const NotificationResourcesFetchedCallback& callback) {
- FetchNotificationResources(
- notification_data, callback,
- new NotificationImageLoader(
- base::Bind(
- &PendingNotificationsTracker::DidFetchPersistentNotification,
- weak_factory_.GetWeakPtr()),
- base::ThreadTaskRunnerHandle::Get()));
+ if (delegate)
+ delegate_to_pending_id_map_[delegate] = notification_id;
+
+ base::Closure fetches_finished_callback = base::Bind(
+ &PendingNotificationsTracker::FetchesFinished,
+ base::Unretained(this) /* The pending notifications are owned by this. */,
+ delegate, notification_id, resources_callback);
+
+ std::unique_ptr<PendingNotification> pending_notification(
+ new PendingNotification(main_task_runner_));
+ pending_notification->FetchResources(notification_data,
+ fetches_finished_callback);
+
+ pending_notifications_.AddWithID(pending_notification.release(),
+ notification_id);
}
-bool PendingNotificationsTracker::CancelPageNotificationFetches(
+bool PendingNotificationsTracker::CancelResourceFetches(
blink::WebNotificationDelegate* delegate) {
+ DCHECK(delegate);
+
auto iter = delegate_to_pending_id_map_.find(delegate);
if (iter == delegate_to_pending_id_map_.end())
return false;
@@ -67,44 +57,19 @@ bool PendingNotificationsTracker::CancelPageNotificationFetches(
return true;
}
-void PendingNotificationsTracker::DidFetchPageNotification(
+void PendingNotificationsTracker::FetchesFinished(
blink::WebNotificationDelegate* delegate,
- int notification_id,
- const SkBitmap& icon) {
- PendingNotification* pending_notification =
- pending_notifications_.Lookup(notification_id);
- DCHECK(pending_notification);
-
- pending_notification->callback.Run(icon);
-
- delegate_to_pending_id_map_.erase(delegate);
- pending_notifications_.Remove(notification_id);
-}
-
-void PendingNotificationsTracker::DidFetchPersistentNotification(
- int notification_id, const SkBitmap& icon) {
+ int32_t notification_id,
+ const ResourcesCallback& resources_callback) {
PendingNotification* pending_notification =
pending_notifications_.Lookup(notification_id);
DCHECK(pending_notification);
- pending_notification->callback.Run(icon);
+ resources_callback.Run(pending_notification->GetResources());
+ if (delegate)
+ delegate_to_pending_id_map_.erase(delegate);
pending_notifications_.Remove(notification_id);
}
-int PendingNotificationsTracker::FetchNotificationResources(
- const blink::WebNotificationData& notification_data,
- const NotificationResourcesFetchedCallback& callback,
- const scoped_refptr<NotificationImageLoader>& image_loader) {
- int notification_id = pending_notifications_.Add(
- new PendingNotification(image_loader, callback));
-
- main_thread_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&NotificationImageLoader::StartOnMainThread, image_loader,
- notification_id, GURL(notification_data.icon)));
-
- return notification_id;
-}
-
} // namespace content
diff --git a/chromium/content/child/notifications/pending_notifications_tracker.h b/chromium/content/child/notifications/pending_notifications_tracker.h
index 53aa32104be..91a7e890734 100644
--- a/chromium/content/child/notifications/pending_notifications_tracker.h
+++ b/chromium/content/child/notifications/pending_notifications_tracker.h
@@ -7,14 +7,11 @@
#include <map>
+#include "base/callback_forward.h"
#include "base/id_map.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "third_party/WebKit/public/platform/modules/notifications/WebNotificationManager.h"
-
-class SkBitmap;
+#include "content/common/content_export.h"
namespace base {
class SingleThreadTaskRunner;
@@ -27,77 +24,58 @@ class WebNotificationDelegate;
namespace content {
-class NotificationImageLoader;
-class NotificationManager;
-
-// Type definition for the callback signature which is to be invoked when the
-// resources associated with a notification have been fetched.
-using NotificationResourcesFetchedCallback =
- base::Callback<void(const SkBitmap&)>;
+class PendingNotification;
+class PendingNotificationsTrackerTest;
+struct NotificationResources;
-// Tracks all aspects of all pending Web Notifications. Most notably, it's in
-// charge of ensuring that all resource fetches associated with the notification
-// are completed as expected. The data associated with the notifications is
-// stored in this class, to maintain thread integrity of their members.
-//
+// Tracks all pending Web Notifications as PendingNotification instances. The
+// pending notifications (and their associated data) are stored in this class.
// The pending notification tracker is owned by the NotificationManager, and
// lives on the thread that manager has been associated with.
-class PendingNotificationsTracker {
+class CONTENT_EXPORT PendingNotificationsTracker {
public:
explicit PendingNotificationsTracker(
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner);
+ const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner);
~PendingNotificationsTracker();
- // Adds a page notification to the tracker. Resource fetches for the
- // notification will be started on asynchronously the main thread.
- void FetchPageNotificationResources(
- const blink::WebNotificationData& notification_data,
- blink::WebNotificationDelegate* delegate,
- const NotificationResourcesFetchedCallback& callback);
+ // Type definition for the callback signature which is to be invoked when the
+ // resources associated with a notification have been fetched.
+ using ResourcesCallback = base::Callback<void(const NotificationResources&)>;
- // Adds a persistent notification to the tracker. Resource fetches for the
- // notification will be started asynchronously on the main thread.
- void FetchPersistentNotificationResources(
- const blink::WebNotificationData& notification_data,
- const NotificationResourcesFetchedCallback& callback);
+ // Adds a pending notification for which to fetch resources. The |delegate|
+ // may be null, but non-null values can be used to cancel the fetches.
+ // Resource fetches will be started asynchronously on the main thread.
+ void FetchResources(const blink::WebNotificationData& notification_data,
+ blink::WebNotificationDelegate* delegate,
+ const ResourcesCallback& resources_callback);
- // Cancels all pending and in-fligth fetches for the page notification
- // identified by |delegate|. Returns if the notification was cancelled.
- bool CancelPageNotificationFetches(blink::WebNotificationDelegate* delegate);
+ // Cancels all pending and in-flight fetches for the notification identified
+ // by |delegate|, which may not be null. Returns whether the notification was
+ // cancelled.
+ bool CancelResourceFetches(blink::WebNotificationDelegate* delegate);
private:
- // To be called on the worker thread when the pending page notification
- // identified by |notification_id| has finished fetching the icon.
- void DidFetchPageNotification(blink::WebNotificationDelegate* delegate,
- int notification_id,
- const SkBitmap& icon);
-
- // To be called on the worker thread when the pending persistent notification
- // identified by |notification_id| has finished fetching the icon.
- void DidFetchPersistentNotification(int notification_id,
- const SkBitmap& icon);
-
- // Common code for starting to fetch resources associated with any kind of
- // notification. Will return the id of the pending notification as allocated
- // in the |pending_notifications_| map.
- int FetchNotificationResources(
- const blink::WebNotificationData& notification_data,
- const NotificationResourcesFetchedCallback& callback,
- const scoped_refptr<NotificationImageLoader>& image_loader);
-
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
-
- struct PendingNotification;
-
- // List of the notifications whose resources are still being fetched.
+ friend class PendingNotificationsTrackerTest;
+
+ // To be called on the worker thread when the pending notification
+ // identified by |notification_id| has finished fetching the resources. The
+ // |delegate| may be null.
+ void FetchesFinished(blink::WebNotificationDelegate* delegate,
+ int notification_id,
+ const ResourcesCallback& resources_callback);
+
+ // Used to generate ids for tracking pending notifications.
+ int32_t next_notification_id_;
+
+ scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
+
+ // The notifications whose resources are still being fetched.
IDMap<PendingNotification, IDMapOwnPointer> pending_notifications_;
// In order to be able to cancel pending page notifications by delegate, store
// a mapping of the delegate to the pending notification id as well.
std::map<blink::WebNotificationDelegate*, int> delegate_to_pending_id_map_;
- base::WeakPtrFactory<PendingNotificationsTracker> weak_factory_;
-
DISALLOW_COPY_AND_ASSIGN(PendingNotificationsTracker);
};
diff --git a/chromium/content/child/notifications/pending_notifications_tracker_unittest.cc b/chromium/content/child/notifications/pending_notifications_tracker_unittest.cc
new file mode 100644
index 00000000000..35c61a79d87
--- /dev/null
+++ b/chromium/content/child/notifications/pending_notifications_tracker_unittest.cc
@@ -0,0 +1,299 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/child/notifications/pending_notifications_tracker.h"
+
+#include <memory>
+#include <vector>
+
+#include "base/base_paths.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/location.h"
+#include "base/macros.h"
+#include "base/message_loop/message_loop.h"
+#include "base/path_service.h"
+#include "base/run_loop.h"
+#include "base/thread_task_runner_handle.h"
+#include "content/common/notification_constants.h"
+#include "content/public/common/notification_resources.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/Platform.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
+#include "third_party/WebKit/public/platform/WebURLError.h"
+#include "third_party/WebKit/public/platform/WebURLLoaderMockFactory.h"
+#include "third_party/WebKit/public/platform/WebURLResponse.h"
+#include "third_party/WebKit/public/platform/modules/notifications/WebNotificationData.h"
+#include "third_party/WebKit/public/platform/modules/notifications/WebNotificationDelegate.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace {
+
+const char kBaseUrl[] = "http://test.com/";
+const char kIcon48x48[] = "48x48.png";
+const char kIcon100x100[] = "100x100.png";
+const char kIcon110x110[] = "110x110.png";
+const char kIcon120x120[] = "120x120.png";
+const char kIcon500x500[] = "500x500.png";
+
+class FakeNotificationDelegate : public blink::WebNotificationDelegate {
+ public:
+ void dispatchClickEvent() override {}
+ void dispatchShowEvent() override {}
+ void dispatchErrorEvent() override {}
+ void dispatchCloseEvent() override {}
+};
+
+} // namespace
+
+class PendingNotificationsTrackerTest : public testing::Test {
+ public:
+ PendingNotificationsTrackerTest()
+ : tracker_(new PendingNotificationsTracker(
+ base::ThreadTaskRunnerHandle::Get())) {}
+
+ ~PendingNotificationsTrackerTest() override {
+ GetURLLoaderMockFactory()->unregisterAllURLs();
+ }
+
+ void DidFetchResources(size_t index, const NotificationResources& resources) {
+ if (resources_.size() < index + 1)
+ resources_.resize(index + 1);
+ resources_[index] = resources;
+ }
+
+ protected:
+ PendingNotificationsTracker* tracker() { return tracker_.get(); }
+
+ size_t CountResources() { return resources_.size(); }
+
+ NotificationResources* GetResources(size_t index) {
+ DCHECK_LT(index, resources_.size());
+ return &resources_[index];
+ }
+
+ size_t CountPendingNotifications() {
+ return tracker_->pending_notifications_.size();
+ }
+
+ size_t CountDelegates() {
+ return tracker_->delegate_to_pending_id_map_.size();
+ }
+
+ blink::WebURLLoaderMockFactory* GetURLLoaderMockFactory() {
+ return blink::Platform::current()->getURLLoaderMockFactory();
+ }
+
+ // Registers a mocked url. When fetched, |file_name| will be loaded from the
+ // test data directory.
+ blink::WebURL RegisterMockedURL(const std::string& file_name) {
+ blink::WebURL url(GURL(kBaseUrl + file_name));
+
+ blink::WebURLResponse response(url);
+ response.setMIMEType("image/png");
+ response.setHTTPStatusCode(200);
+
+ base::FilePath file_path;
+ base::PathService::Get(base::DIR_SOURCE_ROOT, &file_path);
+ file_path = file_path.Append(FILE_PATH_LITERAL("content"))
+ .Append(FILE_PATH_LITERAL("test"))
+ .Append(FILE_PATH_LITERAL("data"))
+ .Append(FILE_PATH_LITERAL("notifications"))
+ .AppendASCII(file_name);
+ file_path = base::MakeAbsoluteFilePath(file_path);
+ blink::WebString string_file_path =
+ blink::WebString::fromUTF8(file_path.MaybeAsASCII());
+
+ GetURLLoaderMockFactory()->registerURL(url, response, string_file_path);
+
+ return url;
+ }
+
+ // Registers a mocked url that will fail to be fetched, with a 404 error.
+ blink::WebURL RegisterMockedErrorURL(const std::string& file_name) {
+ blink::WebURL url(GURL(kBaseUrl + file_name));
+
+ blink::WebURLResponse response(url);
+ response.setMIMEType("image/png");
+ response.setHTTPStatusCode(404);
+
+ blink::WebURLError error;
+ error.reason = 404;
+
+ GetURLLoaderMockFactory()->registerErrorURL(url, response, error);
+ return url;
+ }
+
+ private:
+ base::MessageLoop message_loop_;
+ std::unique_ptr<PendingNotificationsTracker> tracker_;
+ std::vector<NotificationResources> resources_;
+
+ DISALLOW_COPY_AND_ASSIGN(PendingNotificationsTrackerTest);
+};
+
+TEST_F(PendingNotificationsTrackerTest, OneNotificationMultipleResources) {
+ blink::WebNotificationData notification_data;
+ notification_data.icon = RegisterMockedURL(kIcon100x100);
+ notification_data.badge = RegisterMockedURL(kIcon48x48);
+ notification_data.actions =
+ blink::WebVector<blink::WebNotificationAction>(static_cast<size_t>(2));
+ notification_data.actions[0].icon = RegisterMockedURL(kIcon110x110);
+ notification_data.actions[1].icon = RegisterMockedURL(kIcon120x120);
+
+ tracker()->FetchResources(
+ notification_data, nullptr /* delegate */,
+ base::Bind(&PendingNotificationsTrackerTest::DidFetchResources,
+ base::Unretained(this), 0 /* index */));
+
+ ASSERT_EQ(1u, CountPendingNotifications());
+ ASSERT_EQ(0u, CountResources());
+
+ base::RunLoop().RunUntilIdle();
+ GetURLLoaderMockFactory()->serveAsynchronousRequests();
+
+ ASSERT_EQ(0u, CountPendingNotifications());
+ ASSERT_EQ(1u, CountResources());
+
+ NotificationResources* resources = GetResources(0u);
+
+ ASSERT_FALSE(resources->notification_icon.drawsNothing());
+ ASSERT_EQ(100, resources->notification_icon.width());
+
+ ASSERT_FALSE(resources->badge.drawsNothing());
+ ASSERT_EQ(48, resources->badge.width());
+
+ ASSERT_EQ(2u, resources->action_icons.size());
+ ASSERT_FALSE(resources->action_icons[0].drawsNothing());
+ ASSERT_EQ(110, resources->action_icons[0].width());
+ ASSERT_FALSE(resources->action_icons[1].drawsNothing());
+ ASSERT_EQ(120, resources->action_icons[1].width());
+}
+
+TEST_F(PendingNotificationsTrackerTest, LargeIconsAreScaledDown) {
+ blink::WebNotificationData notification_data;
+ notification_data.icon = RegisterMockedURL(kIcon500x500);
+ notification_data.badge = notification_data.icon;
+ notification_data.actions =
+ blink::WebVector<blink::WebNotificationAction>(static_cast<size_t>(1));
+ notification_data.actions[0].icon = notification_data.icon;
+
+ tracker()->FetchResources(
+ notification_data, nullptr /* delegate */,
+ base::Bind(&PendingNotificationsTrackerTest::DidFetchResources,
+ base::Unretained(this), 0 /* index */));
+
+ ASSERT_EQ(1u, CountPendingNotifications());
+ ASSERT_EQ(0u, CountResources());
+
+ base::RunLoop().RunUntilIdle();
+ GetURLLoaderMockFactory()->serveAsynchronousRequests();
+
+ ASSERT_EQ(0u, CountPendingNotifications());
+ ASSERT_EQ(1u, CountResources());
+
+ NotificationResources* resources = GetResources(0u);
+
+ ASSERT_FALSE(resources->notification_icon.drawsNothing());
+ ASSERT_EQ(kPlatformNotificationMaxIconSizePx,
+ resources->notification_icon.width());
+ ASSERT_EQ(kPlatformNotificationMaxIconSizePx,
+ resources->notification_icon.height());
+
+ ASSERT_FALSE(resources->badge.drawsNothing());
+ ASSERT_EQ(kPlatformNotificationMaxBadgeSizePx, resources->badge.width());
+ ASSERT_EQ(kPlatformNotificationMaxBadgeSizePx, resources->badge.height());
+
+ ASSERT_EQ(1u, resources->action_icons.size());
+ ASSERT_FALSE(resources->action_icons[0].drawsNothing());
+ ASSERT_EQ(kPlatformNotificationMaxActionIconSizePx,
+ resources->action_icons[0].width());
+ ASSERT_EQ(kPlatformNotificationMaxActionIconSizePx,
+ resources->action_icons[0].height());
+}
+
+TEST_F(PendingNotificationsTrackerTest, TwoNotifications) {
+ blink::WebNotificationData notification_data;
+ notification_data.icon = RegisterMockedURL(kIcon100x100);
+
+ blink::WebNotificationData notification_data_2;
+ notification_data_2.icon = RegisterMockedURL(kIcon110x110);
+
+ tracker()->FetchResources(
+ notification_data, nullptr /* delegate */,
+ base::Bind(&PendingNotificationsTrackerTest::DidFetchResources,
+ base::Unretained(this), 0 /* index */));
+
+ tracker()->FetchResources(
+ notification_data_2, nullptr /* delegate */,
+ base::Bind(&PendingNotificationsTrackerTest::DidFetchResources,
+ base::Unretained(this), 1 /* index */));
+
+ ASSERT_EQ(2u, CountPendingNotifications());
+ ASSERT_EQ(0u, CountResources());
+
+ base::RunLoop().RunUntilIdle();
+ GetURLLoaderMockFactory()->serveAsynchronousRequests();
+
+ ASSERT_EQ(0u, CountPendingNotifications());
+ ASSERT_EQ(2u, CountResources());
+
+ ASSERT_FALSE(GetResources(0u)->notification_icon.drawsNothing());
+ ASSERT_EQ(100, GetResources(0u)->notification_icon.width());
+
+ ASSERT_FALSE(GetResources(1u)->notification_icon.drawsNothing());
+ ASSERT_EQ(110, GetResources(1u)->notification_icon.width());
+}
+
+TEST_F(PendingNotificationsTrackerTest, FetchError) {
+ blink::WebNotificationData notification_data;
+ notification_data.icon = RegisterMockedErrorURL(kIcon100x100);
+
+ tracker()->FetchResources(
+ notification_data, nullptr /* delegate */,
+ base::Bind(&PendingNotificationsTrackerTest::DidFetchResources,
+ base::Unretained(this), 0 /* index */));
+
+ ASSERT_EQ(1u, CountPendingNotifications());
+ ASSERT_EQ(0u, CountResources());
+
+ base::RunLoop().RunUntilIdle();
+ GetURLLoaderMockFactory()->serveAsynchronousRequests();
+
+ ASSERT_EQ(0u, CountPendingNotifications());
+ ASSERT_EQ(1u, CountResources());
+
+ ASSERT_TRUE(GetResources(0u)->notification_icon.drawsNothing());
+}
+
+TEST_F(PendingNotificationsTrackerTest, CancelFetches) {
+ blink::WebNotificationData notification_data;
+ notification_data.icon = RegisterMockedURL(kIcon100x100);
+
+ FakeNotificationDelegate delegate;
+
+ tracker()->FetchResources(
+ notification_data, &delegate,
+ base::Bind(&PendingNotificationsTrackerTest::DidFetchResources,
+ base::Unretained(this), 0 /* index */));
+
+ ASSERT_EQ(1u, CountPendingNotifications());
+ ASSERT_EQ(1u, CountDelegates());
+ ASSERT_EQ(0u, CountResources());
+
+ base::RunLoop().RunUntilIdle();
+ tracker()->CancelResourceFetches(&delegate);
+
+ ASSERT_EQ(0u, CountPendingNotifications());
+ ASSERT_EQ(0u, CountDelegates());
+ ASSERT_EQ(0u, CountResources());
+}
+
+} // namespace content
diff --git a/chromium/content/child/npapi/DEPS b/chromium/content/child/npapi/DEPS
deleted file mode 100644
index d07f4aff2e5..00000000000
--- a/chromium/content/child/npapi/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
- "+printing",
- "+ui/base",
-]
diff --git a/chromium/content/child/npapi/OWNERS b/chromium/content/child/npapi/OWNERS
deleted file mode 100644
index bd012ea1626..00000000000
--- a/chromium/content/child/npapi/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-ananta@chromium.org
-bauerb@chromium.org
diff --git a/chromium/content/child/npapi/np_channel_base.cc b/chromium/content/child/npapi/np_channel_base.cc
deleted file mode 100644
index 55527ef45ce..00000000000
--- a/chromium/content/child/npapi/np_channel_base.cc
+++ /dev/null
@@ -1,393 +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/child/npapi/np_channel_base.h"
-
-#include <stddef.h>
-
-#include "base/auto_reset.h"
-#include "base/containers/hash_tables.h"
-#include "base/files/scoped_file.h"
-#include "base/lazy_instance.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/threading/thread_local.h"
-#include "build/build_config.h"
-#include "ipc/ipc_sync_message.h"
-
-#if defined(OS_POSIX)
-#include "base/files/file_util.h"
-#include "ipc/ipc_channel_posix.h"
-#endif
-
-namespace content {
-
-namespace {
-
-typedef base::hash_map<std::string, scoped_refptr<NPChannelBase> > ChannelMap;
-
-struct ChannelGlobals {
- ChannelMap channel_map;
- scoped_refptr<NPChannelBase> current_channel;
-};
-
-#if defined(OS_ANDROID)
-// Workaround for http://crbug.com/298179 - NPChannelBase is only intended
-// for use on one thread per process. Using TLS to store the globals removes the
-// worst thread hostility in this class, especially needed for webview which
-// runs in single-process mode. TODO(joth): Make a complete fix, most likely
-// as part of addressing http://crbug.com/258510.
-base::LazyInstance<base::ThreadLocalPointer<ChannelGlobals> >::Leaky
- g_channels_tls_ptr = LAZY_INSTANCE_INITIALIZER;
-
-ChannelGlobals* GetChannelGlobals() {
- ChannelGlobals* globals = g_channels_tls_ptr.Get().Get();
- if (!globals) {
- globals = new ChannelGlobals;
- g_channels_tls_ptr.Get().Set(globals);
- }
- return globals;
-}
-
-#else
-
-base::LazyInstance<ChannelGlobals>::Leaky g_channels_globals =
- LAZY_INSTANCE_INITIALIZER;
-
-ChannelGlobals* GetChannelGlobals() { return g_channels_globals.Pointer(); }
-
-#endif // OS_ANDROID
-
-ChannelMap* GetChannelMap() {
- return &GetChannelGlobals()->channel_map;
-}
-
-} // namespace
-
-NPChannelBase* NPChannelBase::GetChannel(
- const IPC::ChannelHandle& channel_handle,
- IPC::Channel::Mode mode,
- ChannelFactory factory,
- base::SingleThreadTaskRunner* ipc_task_runner,
- bool create_pipe_now,
- base::WaitableEvent* shutdown_event) {
-#if defined(OS_POSIX)
- // On POSIX the channel_handle conveys an FD (socket) which is duped by the
- // kernel during the IPC message exchange (via the SCM_RIGHTS mechanism).
- // Ensure we do not leak this FD.
- base::ScopedFD fd(channel_handle.socket.auto_close ?
- channel_handle.socket.fd : -1);
-#endif
-
- scoped_refptr<NPChannelBase> channel;
- std::string channel_key = channel_handle.name;
- ChannelMap::const_iterator iter = GetChannelMap()->find(channel_key);
- if (iter == GetChannelMap()->end()) {
- channel = factory();
- } else {
- channel = iter->second;
- }
-
- DCHECK(channel.get() != NULL);
-
- if (!channel->channel_valid()) {
- channel->channel_handle_ = channel_handle;
-#if defined(OS_POSIX)
- ignore_result(fd.release());
-#endif
- if (mode & IPC::Channel::MODE_SERVER_FLAG) {
- channel->channel_handle_.name =
- IPC::Channel::GenerateVerifiedChannelID(channel_key);
- }
- channel->mode_ = mode;
- if (channel->Init(ipc_task_runner, create_pipe_now, shutdown_event)) {
- (*GetChannelMap())[channel_key] = channel;
- } else {
- channel = NULL;
- }
- }
-
- return channel.get();
-}
-
-void NPChannelBase::Broadcast(IPC::Message* message) {
- for (ChannelMap::iterator iter = GetChannelMap()->begin();
- iter != GetChannelMap()->end();
- ++iter) {
- iter->second->Send(new IPC::Message(*message));
- }
- delete message;
-}
-
-NPChannelBase::NPChannelBase()
- : mode_(IPC::Channel::MODE_NONE),
- non_npobject_count_(0),
- peer_pid_(0),
- in_remove_route_(false),
- default_owner_(NULL),
- channel_valid_(false),
- in_unblock_dispatch_(0),
- send_unblocking_only_during_unblock_dispatch_(false) {
-}
-
-NPChannelBase::~NPChannelBase() {
- // TODO(wez): Establish why these would ever be non-empty at teardown.
- //DCHECK(npobject_listeners_.empty());
- //DCHECK(proxy_map_.empty());
- //DCHECK(stub_map_.empty());
- DCHECK(owner_to_route_.empty());
- DCHECK(route_to_owner_.empty());
-}
-
-NPChannelBase* NPChannelBase::GetCurrentChannel() {
- return GetChannelGlobals()->current_channel.get();
-}
-
-void NPChannelBase::CleanupChannels() {
- // Make a copy of the references as we can't iterate the map since items will
- // be removed from it as we clean them up.
- std::vector<scoped_refptr<NPChannelBase> > channels;
- for (ChannelMap::const_iterator iter = GetChannelMap()->begin();
- iter != GetChannelMap()->end();
- ++iter) {
- channels.push_back(iter->second);
- }
-
- for (size_t i = 0; i < channels.size(); ++i)
- channels[i]->CleanUp();
-
- // This will clean up channels added to the map for which subsequent
- // AddRoute wasn't called
- GetChannelMap()->clear();
-}
-
-NPObjectBase* NPChannelBase::GetNPObjectListenerForRoute(int route_id) {
- ListenerMap::iterator iter = npobject_listeners_.find(route_id);
- if (iter == npobject_listeners_.end()) {
- DLOG(WARNING) << "Invalid route id passed in:" << route_id;
- return NULL;
- }
- return iter->second;
-}
-
-base::WaitableEvent* NPChannelBase::GetModalDialogEvent(int render_view_id) {
- return NULL;
-}
-
-bool NPChannelBase::Init(base::SingleThreadTaskRunner* ipc_task_runner,
- bool create_pipe_now,
- base::WaitableEvent* shutdown_event) {
-#if defined(OS_POSIX)
- // Attempting to initialize with an invalid channel handle.
- // See http://crbug.com/97285 for details.
- if (mode_ == IPC::Channel::MODE_CLIENT && -1 == channel_handle_.socket.fd)
- return false;
-#endif
-
- channel_ =
- IPC::SyncChannel::Create(channel_handle_, mode_, this, ipc_task_runner,
- create_pipe_now, shutdown_event);
-
-#if defined(OS_POSIX)
- // Check the validity of fd for bug investigation. Remove after fixed.
- // See crbug.com/97285 for details.
- if (mode_ == IPC::Channel::MODE_SERVER)
- CHECK_NE(-1, channel_->GetClientFileDescriptor());
-#endif
-
- channel_valid_ = true;
- return true;
-}
-
-bool NPChannelBase::Send(IPC::Message* message) {
- if (!channel_) {
- VLOG(1) << "Channel is NULL; dropping message";
- delete message;
- return false;
- }
-
- if (send_unblocking_only_during_unblock_dispatch_ &&
- in_unblock_dispatch_ == 0 &&
- message->is_sync()) {
- message->set_unblock(false);
- }
-
- return channel_->Send(message);
-}
-
-int NPChannelBase::Count() {
- return static_cast<int>(GetChannelMap()->size());
-}
-
-bool NPChannelBase::OnMessageReceived(const IPC::Message& message) {
- // Push this channel as the current channel being processed. This also forms
- // a stack of scoped_refptr avoiding ourselves (or any instance higher
- // up the callstack) from being deleted while processing a message.
- base::AutoReset<scoped_refptr<NPChannelBase> > keep_alive(
- &GetChannelGlobals()->current_channel, this);
-
- bool handled;
- if (message.should_unblock())
- in_unblock_dispatch_++;
- if (message.routing_id() == MSG_ROUTING_CONTROL) {
- handled = OnControlMessageReceived(message);
- } else {
- handled = router_.RouteMessage(message);
- if (!handled && message.is_sync()) {
- // The listener has gone away, so we must respond or else the caller will
- // hang waiting for a reply.
- IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message);
- reply->set_reply_error();
- Send(reply);
- }
- }
- if (message.should_unblock())
- in_unblock_dispatch_--;
-
- return handled;
-}
-
-void NPChannelBase::OnChannelConnected(int32_t peer_pid) {
- peer_pid_ = peer_pid;
-}
-
-void NPChannelBase::AddRoute(int route_id,
- IPC::Listener* listener,
- NPObjectBase* npobject) {
- if (npobject) {
- npobject_listeners_[route_id] = npobject;
- } else {
- non_npobject_count_++;
- }
-
- router_.AddRoute(route_id, listener);
-}
-
-void NPChannelBase::RemoveRoute(int route_id) {
- router_.RemoveRoute(route_id);
-
- ListenerMap::iterator iter = npobject_listeners_.find(route_id);
- if (iter != npobject_listeners_.end()) {
- // This was an NPObject proxy or stub, it's not involved in the refcounting.
-
- // If this RemoveRoute call from the NPObject is a result of us calling
- // OnChannelError below, don't call erase() here because that'll corrupt
- // the iterator below.
- if (in_remove_route_) {
- iter->second = NULL;
- } else {
- npobject_listeners_.erase(iter);
- }
-
- return;
- }
-
- non_npobject_count_--;
- DCHECK(non_npobject_count_ >= 0);
-
- if (!non_npobject_count_) {
- base::AutoReset<bool> auto_reset_in_remove_route(&in_remove_route_, true);
- for (ListenerMap::iterator npobj_iter = npobject_listeners_.begin();
- npobj_iter != npobject_listeners_.end(); ++npobj_iter) {
- if (npobj_iter->second) {
- npobj_iter->second->GetChannelListener()->OnChannelError();
- }
- }
-
- for (ChannelMap::iterator iter = GetChannelMap()->begin();
- iter != GetChannelMap()->end(); ++iter) {
- if (iter->second.get() == this) {
- GetChannelMap()->erase(iter);
- return;
- }
- }
-
- NOTREACHED();
- }
-}
-
-bool NPChannelBase::OnControlMessageReceived(const IPC::Message& msg) {
- NOTREACHED() <<
- "should override in subclass if you care about control messages";
- return false;
-}
-
-void NPChannelBase::OnChannelError() {
- channel_valid_ = false;
-
- // TODO(shess): http://crbug.com/97285
- // Once an error is seen on a channel, remap the channel to prevent
- // it from being vended again. Keep the channel in the map so
- // RemoveRoute() can clean things up correctly.
- for (ChannelMap::iterator iter = GetChannelMap()->begin();
- iter != GetChannelMap()->end(); ++iter) {
- if (iter->second.get() == this) {
- // Insert new element before invalidating |iter|.
- (*GetChannelMap())[iter->first + "-error"] = iter->second;
- GetChannelMap()->erase(iter);
- break;
- }
- }
-}
-
-void NPChannelBase::AddMappingForNPObjectProxy(int route_id,
- NPObject* object) {
- proxy_map_[route_id] = object;
-}
-
-void NPChannelBase::RemoveMappingForNPObjectProxy(int route_id) {
- proxy_map_.erase(route_id);
-}
-
-void NPChannelBase::AddMappingForNPObjectStub(int route_id,
- NPObject* object) {
- DCHECK(object != NULL);
- stub_map_[object] = route_id;
-}
-
-void NPChannelBase::RemoveMappingForNPObjectStub(int route_id,
- NPObject* object) {
- DCHECK(object != NULL);
- stub_map_.erase(object);
-}
-
-void NPChannelBase::AddMappingForNPObjectOwner(int route_id,
- struct _NPP* owner) {
- DCHECK(owner != NULL);
- route_to_owner_[route_id] = owner;
- owner_to_route_[owner] = route_id;
-}
-
-void NPChannelBase::SetDefaultNPObjectOwner(struct _NPP* owner) {
- DCHECK(owner != NULL);
- default_owner_ = owner;
-}
-
-void NPChannelBase::RemoveMappingForNPObjectOwner(int route_id) {
- DCHECK(route_to_owner_.find(route_id) != route_to_owner_.end());
- owner_to_route_.erase(route_to_owner_[route_id]);
- route_to_owner_.erase(route_id);
-}
-
-NPObject* NPChannelBase::GetExistingNPObjectProxy(int route_id) {
- ProxyMap::iterator iter = proxy_map_.find(route_id);
- return iter != proxy_map_.end() ? iter->second : NULL;
-}
-
-int NPChannelBase::GetExistingRouteForNPObjectStub(NPObject* npobject) {
- StubMap::iterator iter = stub_map_.find(npobject);
- return iter != stub_map_.end() ? iter->second : MSG_ROUTING_NONE;
-}
-
-NPP NPChannelBase::GetExistingNPObjectOwner(int route_id) {
- RouteToOwnerMap::iterator iter = route_to_owner_.find(route_id);
- return iter != route_to_owner_.end() ? iter->second : default_owner_;
-}
-
-int NPChannelBase::GetExistingRouteForNPObjectOwner(NPP owner) {
- OwnerToRouteMap::iterator iter = owner_to_route_.find(owner);
- return iter != owner_to_route_.end() ? iter->second : MSG_ROUTING_NONE;
-}
-
-} // namespace content
diff --git a/chromium/content/child/npapi/np_channel_base.h b/chromium/content/child/npapi/np_channel_base.h
deleted file mode 100644
index ff77bd233e5..00000000000
--- a/chromium/content/child/npapi/np_channel_base.h
+++ /dev/null
@@ -1,200 +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_CHILD_NPAPI_NP_CHANNEL_BASE_H_
-#define CONTENT_CHILD_NPAPI_NP_CHANNEL_BASE_H_
-
-#include <stdint.h>
-
-#include <string>
-
-#include "base/containers/hash_tables.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/process/process.h"
-#include "content/child/npapi/npobject_base.h"
-#include "content/common/message_router.h"
-#include "ipc/ipc_channel_handle.h"
-#include "ipc/ipc_sync_channel.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}
-
-namespace content {
-
-// Encapsulates an IPC channel between a renderer and another process. Used to
-// proxy access to NP objects.
-class NPChannelBase : public IPC::Listener,
- public IPC::Sender,
- public base::RefCountedThreadSafe<NPChannelBase> {
- public:
-
- // WebPlugin[Delegate] call these on construction and destruction to setup
- // the routing and manage lifetime of this object (they pass NULL for
- // npobject). These are also called by NPObjectProxy and NPObjectStub (which
- // pass themselves for npobject). However the latter don't control the
- // lifetime of this object because we don't want a leak of an NPObject to
- // keep the channel around longer than necessary.
- void AddRoute(int route_id, IPC::Listener* listener, NPObjectBase* npobject);
- void RemoveRoute(int route_id);
-
- void AddMappingForNPObjectProxy(int route_id, NPObject* object);
- void RemoveMappingForNPObjectProxy(int route_id);
-
- void AddMappingForNPObjectStub(int route_id, NPObject* object);
- void RemoveMappingForNPObjectStub(int route_id, NPObject* object);
-
- void AddMappingForNPObjectOwner(int route_id, struct _NPP* owner);
- void SetDefaultNPObjectOwner(struct _NPP* owner);
- void RemoveMappingForNPObjectOwner(int route_id);
-
- NPObject* GetExistingNPObjectProxy(int route_id);
- int GetExistingRouteForNPObjectStub(NPObject* npobject);
- struct _NPP* GetExistingNPObjectOwner(int route_id);
- int GetExistingRouteForNPObjectOwner(struct _NPP* owner);
-
- // IPC::Sender implementation:
- bool Send(IPC::Message* msg) override;
-
- base::ProcessId peer_pid() { return channel_->GetPeerPID(); }
- IPC::ChannelHandle channel_handle() const { return channel_handle_; }
-
- // Returns the number of open NPObject channels in this process.
- static int Count();
-
- // Returns a new route id.
- virtual int GenerateRouteID() = 0;
-
- // Returns whether the channel is valid or not. A channel is invalid
- // if it is disconnected due to a channel error.
- bool channel_valid() {
- return channel_valid_;
- }
-
- // Returns the most recent NPChannelBase to have received a message
- // in this process.
- static NPChannelBase* GetCurrentChannel();
-
- static void CleanupChannels();
-
- // Returns the NPObjectBase object for the route id passed in.
- // Returns NULL on failure.
- NPObjectBase* GetNPObjectListenerForRoute(int route_id);
-
- // Returns the event that's set when a call to the renderer causes a modal
- // dialog to come up. The default implementation returns NULL. Derived
- // classes should override this method if this functionality is required.
- virtual base::WaitableEvent* GetModalDialogEvent(int render_view_id);
-
- protected:
- typedef NPChannelBase* (*ChannelFactory)();
-
- friend class base::RefCountedThreadSafe<NPChannelBase>;
-
- ~NPChannelBase() override;
-
- // Returns a NPChannelBase derived object for the given channel name.
- // If an existing channel exists returns that object, otherwise creates a
- // new one. Even though on creation the object is refcounted, each caller
- // must still ref count the returned value. When there are no more routes
- // on the channel and its ref count is 0, the object deletes itself.
- static NPChannelBase* GetChannel(
- const IPC::ChannelHandle& channel_handle,
- IPC::Channel::Mode mode,
- ChannelFactory factory,
- base::SingleThreadTaskRunner* ipc_task_runner,
- bool create_pipe_now,
- base::WaitableEvent* shutdown_event);
-
- // Sends a message to all instances.
- static void Broadcast(IPC::Message* message);
-
- // Called on the worker thread
- NPChannelBase();
-
- virtual void CleanUp() { }
-
- // Implemented by derived classes to handle control messages
- virtual bool OnControlMessageReceived(const IPC::Message& msg);
-
- // IPC::Listener implementation:
- bool OnMessageReceived(const IPC::Message& msg) override;
- void OnChannelConnected(int32_t peer_pid) override;
- void OnChannelError() override;
-
- void set_send_unblocking_only_during_unblock_dispatch() {
- send_unblocking_only_during_unblock_dispatch_ = true;
- }
-
- virtual bool Init(base::SingleThreadTaskRunner* ipc_task_runner,
- bool create_pipe_now,
- base::WaitableEvent* shutdown_event);
-
- scoped_ptr<IPC::SyncChannel> channel_;
- IPC::ChannelHandle channel_handle_;
-
- private:
- IPC::Channel::Mode mode_;
- // This tracks the number of routes registered without an NPObject. It's used
- // to manage the lifetime of this object. See comment for AddRoute() and
- // RemoveRoute().
- int non_npobject_count_;
- int peer_pid_;
-
- // true when in the middle of a RemoveRoute call
- bool in_remove_route_;
-
- // Keep track of all the registered NPObjects proxies/stubs so that when the
- // channel is closed we can inform them.
- typedef base::hash_map<int, NPObjectBase*> ListenerMap;
- ListenerMap npobject_listeners_;
-
- typedef base::hash_map<int, NPObject*> ProxyMap;
- ProxyMap proxy_map_;
-
- typedef base::hash_map<NPObject*, int> StubMap;
- StubMap stub_map_;
-
- typedef base::hash_map<struct _NPP*, int> OwnerToRouteMap;
- OwnerToRouteMap owner_to_route_;
-
- typedef base::hash_map<int, struct _NPP*> RouteToOwnerMap;
- RouteToOwnerMap route_to_owner_;
-
- // Used on the plugin side to represent any object received that does
- // not belong to a plugin instance.
- struct _NPP* default_owner_;
-
- // Used to implement message routing functionality to WebPlugin[Delegate]
- // objects
- MessageRouter router_;
-
- // A channel is invalid if it is disconnected as a result of a channel
- // error. This flag is used to indicate the same.
- bool channel_valid_;
-
- // Track whether we're dispatching a message with the unblock flag; works like
- // a refcount, 0 when we're not.
- int in_unblock_dispatch_;
-
- // If true, sync messages will only be marked as unblocking if the channel is
- // in the middle of dispatching an unblocking message. The non-renderer
- // process wants to avoid setting the unblock flag on its sync messages
- // unless necessary, since it can potentially introduce reentrancy into
- // WebKit in ways that it doesn't expect (i.e. causing layout during paint).
- // However to avoid deadlock, we must ensure that any message that's sent as
- // a result of a sync call from the renderer must unblock the renderer. We
- // additionally have to do this for async messages from the renderer that
- // have the unblock flag set, since they could be followed by a sync message
- // that won't get dispatched until the call to the renderer is complete.
- bool send_unblocking_only_during_unblock_dispatch_;
-
- DISALLOW_COPY_AND_ASSIGN(NPChannelBase);
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_NPAPI_NP_CHANNEL_BASE_H_
diff --git a/chromium/content/child/npapi/npobject_base.h b/chromium/content/child/npapi/npobject_base.h
deleted file mode 100644
index 9897139b095..00000000000
--- a/chromium/content/child/npapi/npobject_base.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Base interface used by NPChannelBase and implemented by NPObjectProxy and
-// NPObjectStub.
-
-#ifndef CONTENT_CHILD_NPAPI_NPOBJECT_BASE_H_
-#define CONTENT_CHILD_NPAPI_NPOBJECT_BASE_H_
-
-#include "ipc/ipc_listener.h"
-#include "third_party/npapi/bindings/npruntime.h"
-
-struct NPObject;
-
-namespace content {
-
-class NPObjectBase {
- public:
- virtual ~NPObjectBase() {}
-
- // Returns the underlying NPObject handled by this NPObjectBase instance.
- virtual NPObject* GetUnderlyingNPObject() = 0;
-
- // Returns the channel listener for this NPObjectBase instance.
- virtual IPC::Listener* GetChannelListener() = 0;
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_NPAPI_NPOBJECT_BASE_H_
diff --git a/chromium/content/child/npapi/npobject_proxy.cc b/chromium/content/child/npapi/npobject_proxy.cc
deleted file mode 100644
index 45dc68d665e..00000000000
--- a/chromium/content/child/npapi/npobject_proxy.cc
+++ /dev/null
@@ -1,509 +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/child/npapi/npobject_proxy.h"
-
-#include "content/child/npapi/np_channel_base.h"
-#include "content/child/npapi/npobject_util.h"
-#include "content/child/plugin_messages.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
-
-#if defined(ENABLE_PLUGINS)
-#include "content/child/npapi/plugin_instance.h"
-#endif
-
-using blink::WebBindings;
-
-namespace content {
-
-struct NPObjectWrapper {
- NPObject object;
- NPObjectProxy* proxy;
-};
-
-NPClass NPObjectProxy::npclass_proxy_ = {
- NP_CLASS_STRUCT_VERSION,
- NPObjectProxy::NPAllocate,
- NPObjectProxy::NPDeallocate,
- NPObjectProxy::NPPInvalidate,
- NPObjectProxy::NPHasMethod,
- NPObjectProxy::NPInvoke,
- NPObjectProxy::NPInvokeDefault,
- NPObjectProxy::NPHasProperty,
- NPObjectProxy::NPGetProperty,
- NPObjectProxy::NPSetProperty,
- NPObjectProxy::NPRemoveProperty,
- NPObjectProxy::NPNEnumerate,
- NPObjectProxy::NPNConstruct
-};
-
-NPObjectProxy* NPObjectProxy::GetProxy(NPObject* object) {
- NPObjectProxy* proxy = NULL;
-
- // Wrapper exists only for NPObjects that we had created.
- if (&npclass_proxy_ == object->_class) {
- NPObjectWrapper* wrapper = reinterpret_cast<NPObjectWrapper*>(object);
- proxy = wrapper->proxy;
- }
-
- return proxy;
-}
-
-NPObject* NPObjectProxy::GetUnderlyingNPObject() {
- return NULL;
-}
-
-IPC::Listener* NPObjectProxy::GetChannelListener() {
- return static_cast<IPC::Listener*>(this);
-}
-
-NPObjectProxy::NPObjectProxy(
- NPChannelBase* channel,
- int route_id,
- int render_view_id,
- const GURL& page_url)
- : channel_(channel),
- route_id_(route_id),
- render_view_id_(render_view_id),
- page_url_(page_url) {
- channel_->AddRoute(route_id, this, this);
-}
-
-NPObjectProxy::~NPObjectProxy() {
- if (channel_.get()) {
- // This NPObjectProxy instance is now invalid and should not be reused for
- // requests initiated by plugins. We may receive requests for the
- // same NPObject in the context of the outgoing NPObjectMsg_Release call.
- // We should be creating new NPObjectProxy instances to wrap these
- // NPObjects.
- channel_->RemoveMappingForNPObjectProxy(route_id_);
- channel_->RemoveRoute(route_id_);
- Send(new NPObjectMsg_Release(route_id_));
- }
-}
-
-NPObject* NPObjectProxy::Create(NPChannelBase* channel,
- int route_id,
- int render_view_id,
- const GURL& page_url,
- NPP owner) {
- NPObjectWrapper* obj = reinterpret_cast<NPObjectWrapper*>(
- WebBindings::createObject(owner, &npclass_proxy_));
- obj->proxy = new NPObjectProxy(channel, route_id, render_view_id, page_url);
- channel->AddMappingForNPObjectProxy(route_id, &obj->object);
- return reinterpret_cast<NPObject*>(obj);
-}
-
-bool NPObjectProxy::Send(IPC::Message* msg) {
- if (channel_.get())
- return channel_->Send(msg);
-
- delete msg;
- return false;
-}
-
-NPObject* NPObjectProxy::NPAllocate(NPP, NPClass*) {
- return reinterpret_cast<NPObject*>(new NPObjectWrapper);
-}
-
-void NPObjectProxy::NPDeallocate(NPObject* npObj) {
- NPObjectWrapper* obj = reinterpret_cast<NPObjectWrapper*>(npObj);
- delete obj->proxy;
- delete obj;
-}
-
-bool NPObjectProxy::OnMessageReceived(const IPC::Message& msg) {
- NOTREACHED();
- return false;
-}
-
-void NPObjectProxy::OnChannelError() {
- // Release our ref count of the plugin channel object, as it addrefs the
- // process.
- channel_ = NULL;
-}
-
-bool NPObjectProxy::NPHasMethod(NPObject *obj,
- NPIdentifier name) {
- if (obj == NULL)
- return false;
-
- bool result = false;
- NPObjectProxy* proxy = GetProxy(obj);
-
- if (!proxy) {
- return obj->_class->hasMethod(obj, name);
- }
-
- NPIdentifier_Param name_param;
- CreateNPIdentifierParam(name, &name_param);
-
- proxy->Send(new NPObjectMsg_HasMethod(proxy->route_id(), name_param,
- &result));
- return result;
-}
-
-bool NPObjectProxy::NPInvoke(NPObject *obj,
- NPIdentifier name,
- const NPVariant *args,
- uint32_t arg_count,
- NPVariant *result) {
- return NPInvokePrivate(0, obj, false, name, args, arg_count, result);
-}
-
-bool NPObjectProxy::NPInvokeDefault(NPObject *npobj,
- const NPVariant *args,
- uint32_t arg_count,
- NPVariant *result) {
- return NPInvokePrivate(0, npobj, true, 0, args, arg_count, result);
-}
-
-bool NPObjectProxy::NPInvokePrivate(NPP npp,
- NPObject *obj,
- bool is_default,
- NPIdentifier name,
- const NPVariant *args,
- uint32_t arg_count,
- NPVariant *np_result) {
- if (obj == NULL)
- return false;
-
- NPObjectProxy* proxy = GetProxy(obj);
- if (!proxy) {
- if (is_default) {
- return obj->_class->invokeDefault(obj, args, arg_count, np_result);
- } else {
- return obj->_class->invoke(obj, name, args, arg_count, np_result);
- }
- }
-
- bool result = false;
- int render_view_id = proxy->render_view_id_;
- NPIdentifier_Param name_param;
- if (is_default) {
- // The data won't actually get used, but set it so we don't send random
- // data.
- name_param.identifier = NULL;
- } else {
- CreateNPIdentifierParam(name, &name_param);
- }
-
- // Note: This instance can get destroyed in the context of
- // Send so addref the channel in this scope.
- scoped_refptr<NPChannelBase> channel_copy = proxy->channel_;
- std::vector<NPVariant_Param> args_param;
- for (unsigned int i = 0; i < arg_count; ++i) {
- NPVariant_Param param;
- CreateNPVariantParam(args[i],
- channel_copy.get(),
- &param,
- false,
- render_view_id,
- proxy->page_url_);
- args_param.push_back(param);
- }
-
- NPVariant_Param param_result;
- NPObjectMsg_Invoke* msg = new NPObjectMsg_Invoke(
- proxy->route_id_, is_default, name_param, args_param, &param_result,
- &result);
-
- // If we're in the plugin process and this invoke leads to a dialog box, the
- // plugin will hang the window hierarchy unless we pump the window message
- // queue while waiting for a reply. We need to do this to simulate what
- // happens when everything runs in-process (while calling MessageBox window
- // messages are pumped).
- if (IsPluginProcess() && proxy->channel()) {
- msg->set_pump_messages_event(
- proxy->channel()->GetModalDialogEvent(render_view_id));
- }
-
- GURL page_url = proxy->page_url_;
- proxy->Send(msg);
-
- // Send may delete proxy.
- proxy = NULL;
-
- if (!result)
- return false;
-
- CreateNPVariant(
- param_result, channel_copy.get(), np_result, render_view_id, page_url);
- return true;
-}
-
-bool NPObjectProxy::NPHasProperty(NPObject *obj,
- NPIdentifier name) {
- if (obj == NULL)
- return false;
-
- bool result = false;
- NPObjectProxy* proxy = GetProxy(obj);
- if (!proxy) {
- return obj->_class->hasProperty(obj, name);
- }
-
- NPIdentifier_Param name_param;
- CreateNPIdentifierParam(name, &name_param);
-
- NPVariant_Param param;
- proxy->Send(new NPObjectMsg_HasProperty(
- proxy->route_id(), name_param, &result));
-
- // Send may delete proxy.
- proxy = NULL;
-
- return result;
-}
-
-bool NPObjectProxy::NPGetProperty(NPObject *obj,
- NPIdentifier name,
- NPVariant *np_result) {
- // Please refer to http://code.google.com/p/chromium/issues/detail?id=2556,
- // which was a crash in the XStandard plugin during plugin shutdown. The
- // crash occured because the plugin requests the plugin script object,
- // which fails. The plugin does not check the result of the operation and
- // invokes NPN_GetProperty on a NULL object which lead to the crash. If
- // we observe similar crashes in other methods in the future, these null
- // checks may have to be replicated in the other methods in this class.
- if (obj == NULL)
- return false;
-
- NPObjectProxy* proxy = GetProxy(obj);
- if (!proxy) {
- return obj->_class->getProperty(obj, name, np_result);
- }
-
- bool result = false;
- int render_view_id = proxy->render_view_id_;
- NPIdentifier_Param name_param;
- CreateNPIdentifierParam(name, &name_param);
-
- NPVariant_Param param;
- scoped_refptr<NPChannelBase> channel(proxy->channel_);
-
- GURL page_url = proxy->page_url_;
- proxy->Send(new NPObjectMsg_GetProperty(
- proxy->route_id(), name_param, &param, &result));
- // Send may delete proxy.
- proxy = NULL;
- if (!result)
- return false;
-
- CreateNPVariant(
- param, channel.get(), np_result, render_view_id, page_url);
-
- return true;
-}
-
-bool NPObjectProxy::NPSetProperty(NPObject *obj,
- NPIdentifier name,
- const NPVariant *value) {
- if (obj == NULL)
- return false;
-
- NPObjectProxy* proxy = GetProxy(obj);
- if (!proxy) {
- return obj->_class->setProperty(obj, name, value);
- }
-
- bool result = false;
- int render_view_id = proxy->render_view_id_;
- NPIdentifier_Param name_param;
- CreateNPIdentifierParam(name, &name_param);
-
- NPVariant_Param value_param;
- CreateNPVariantParam(
- *value, proxy->channel(), &value_param, false, render_view_id,
- proxy->page_url_);
-
- proxy->Send(new NPObjectMsg_SetProperty(
- proxy->route_id(), name_param, value_param, &result));
- // Send may delete proxy.
- proxy = NULL;
-
- return result;
-}
-
-bool NPObjectProxy::NPRemoveProperty(NPObject *obj,
- NPIdentifier name) {
- if (obj == NULL)
- return false;
-
- bool result = false;
- NPObjectProxy* proxy = GetProxy(obj);
- if (!proxy) {
- return obj->_class->removeProperty(obj, name);
- }
-
- NPIdentifier_Param name_param;
- CreateNPIdentifierParam(name, &name_param);
-
- NPVariant_Param param;
- proxy->Send(new NPObjectMsg_RemoveProperty(
- proxy->route_id(), name_param, &result));
- // Send may delete proxy.
- proxy = NULL;
-
- return result;
-}
-
-void NPObjectProxy::NPPInvalidate(NPObject *obj) {
- if (obj == NULL)
- return;
-
- NPObjectProxy* proxy = GetProxy(obj);
- if (!proxy) {
- obj->_class->invalidate(obj);
- return;
- }
-
- proxy->Send(new NPObjectMsg_Invalidate(proxy->route_id()));
- // Send may delete proxy.
- proxy = NULL;
-}
-
-bool NPObjectProxy::NPNEnumerate(NPObject *obj,
- NPIdentifier **value,
- uint32_t *count) {
- if (obj == NULL)
- return false;
-
- bool result = false;
- NPObjectProxy* proxy = GetProxy(obj);
- if (!proxy) {
- if (obj->_class->structVersion >= NP_CLASS_STRUCT_VERSION_ENUM) {
- return obj->_class->enumerate(obj, value, count);
- } else {
- return false;
- }
- }
-
- std::vector<NPIdentifier_Param> value_param;
- proxy->Send(new NPObjectMsg_Enumeration(
- proxy->route_id(), &value_param, &result));
- // Send may delete proxy.
- proxy = NULL;
-
- if (!result)
- return false;
-
- *count = static_cast<unsigned int>(value_param.size());
- *value = static_cast<NPIdentifier *>(malloc(sizeof(NPIdentifier) * *count));
- for (unsigned int i = 0; i < *count; ++i)
- (*value)[i] = CreateNPIdentifier(value_param[i]);
-
- return true;
-}
-
-bool NPObjectProxy::NPNConstruct(NPObject *obj,
- const NPVariant *args,
- uint32_t arg_count,
- NPVariant *np_result) {
- if (obj == NULL)
- return false;
-
- NPObjectProxy* proxy = GetProxy(obj);
- if (!proxy) {
- if (obj->_class->structVersion >= NP_CLASS_STRUCT_VERSION_CTOR) {
- return obj->_class->construct(obj, args, arg_count, np_result);
- } else {
- return false;
- }
- }
-
- bool result = false;
- int render_view_id = proxy->render_view_id_;
-
- // Note: This instance can get destroyed in the context of
- // Send so addref the channel in this scope.
- scoped_refptr<NPChannelBase> channel_copy = proxy->channel_;
- std::vector<NPVariant_Param> args_param;
- for (unsigned int i = 0; i < arg_count; ++i) {
- NPVariant_Param param;
- CreateNPVariantParam(args[i],
- channel_copy.get(),
- &param,
- false,
- render_view_id,
- proxy->page_url_);
- args_param.push_back(param);
- }
-
- NPVariant_Param param_result;
- NPObjectMsg_Construct* msg = new NPObjectMsg_Construct(
- proxy->route_id_, args_param, &param_result, &result);
-
- // See comment in NPObjectProxy::NPInvokePrivate.
- if (IsPluginProcess() && proxy->channel()) {
- msg->set_pump_messages_event(
- proxy->channel()->GetModalDialogEvent(proxy->render_view_id_));
- }
-
- GURL page_url = proxy->page_url_;
- proxy->Send(msg);
-
- // Send may delete proxy.
- proxy = NULL;
-
- if (!result)
- return false;
-
- CreateNPVariant(
- param_result, channel_copy.get(), np_result, render_view_id, page_url);
- return true;
-}
-
-bool NPObjectProxy::NPNEvaluate(NPP npp,
- NPObject *obj,
- NPString *script,
- NPVariant *result_var) {
- NPObjectProxy* proxy = GetProxy(obj);
- if (!proxy) {
- return false;
- }
-
- bool result = false;
- int render_view_id = proxy->render_view_id_;
- bool popups_allowed = false;
-
-#if defined(ENABLE_PLUGINS)
- if (npp) {
- PluginInstance* plugin_instance =
- reinterpret_cast<PluginInstance*>(npp->ndata);
- if (plugin_instance)
- popups_allowed = plugin_instance->popups_allowed();
- }
-#endif
-
- NPVariant_Param result_param;
- std::string script_str = std::string(
- script->UTF8Characters, script->UTF8Length);
-
- NPObjectMsg_Evaluate* msg = new NPObjectMsg_Evaluate(proxy->route_id(),
- script_str,
- popups_allowed,
- &result_param,
- &result);
-
- // See comment in NPObjectProxy::NPInvokePrivate.
- if (IsPluginProcess() && proxy->channel()) {
- msg->set_pump_messages_event(
- proxy->channel()->GetModalDialogEvent(render_view_id));
- }
- scoped_refptr<NPChannelBase> channel(proxy->channel_);
-
- GURL page_url = proxy->page_url_;
- proxy->Send(msg);
- // Send may delete proxy.
- proxy = NULL;
- if (!result)
- return false;
-
- CreateNPVariant(
- result_param, channel.get(), result_var, render_view_id, page_url);
- return true;
-}
-
-} // namespace content
diff --git a/chromium/content/child/npapi/npobject_proxy.h b/chromium/content/child/npapi/npobject_proxy.h
deleted file mode 100644
index 93ceac7b9e9..00000000000
--- a/chromium/content/child/npapi/npobject_proxy.h
+++ /dev/null
@@ -1,130 +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 proxy for NPObject that sends all calls to the object to an NPObjectStub
-// running in a different process.
-
-#ifndef CONTENT_CHILD_NPAPI_NPOBJECT_PROXY_H_
-#define CONTENT_CHILD_NPAPI_NPOBJECT_PROXY_H_
-
-#include <stdint.h>
-
-#include "base/memory/ref_counted.h"
-#include "content/child/npapi/npobject_base.h"
-#include "ipc/ipc_listener.h"
-#include "ipc/ipc_sender.h"
-#include "third_party/npapi/bindings/npruntime.h"
-#include "ui/gfx/native_widget_types.h"
-#include "url/gurl.h"
-
-struct NPObject;
-
-namespace content {
-class NPChannelBase;
-
-// When running a plugin in a different process from the renderer, we need to
-// proxy calls to NPObjects across process boundaries. This happens both ways,
-// as a plugin can get an NPObject for the window, and a page can get an
-// NPObject for the plugin. In the process that interacts with the NPobject we
-// give it an NPObjectProxy instead. All calls to it are sent across an IPC
-// channel (specifically, a NPChannelBase). The NPObjectStub on the other
-// side translates the IPC messages into calls to the actual NPObject, and
-// returns the marshalled result.
-class NPObjectProxy : public IPC::Listener,
- public IPC::Sender,
- public NPObjectBase {
- public:
- ~NPObjectProxy() override;
-
- static NPObject* Create(NPChannelBase* channel,
- int route_id,
- int render_view_id,
- const GURL& page_url,
- NPP owner);
-
- // IPC::Sender implementation:
- bool Send(IPC::Message* msg) override;
- int route_id() { return route_id_; }
- NPChannelBase* channel() { return channel_.get(); }
-
- // The next 9 functions are called on NPObjects from the plugin and browser.
- static bool NPHasMethod(NPObject *obj,
- NPIdentifier name);
- static bool NPInvoke(NPObject *obj,
- NPIdentifier name,
- const NPVariant *args,
- uint32_t arg_count,
- NPVariant *result);
- static bool NPInvokeDefault(NPObject *npobj,
- const NPVariant *args,
- uint32_t arg_count,
- NPVariant *result);
- static bool NPHasProperty(NPObject *obj,
- NPIdentifier name);
- static bool NPGetProperty(NPObject *obj,
- NPIdentifier name,
- NPVariant *result);
- static bool NPSetProperty(NPObject *obj,
- NPIdentifier name,
- const NPVariant *value);
- static bool NPRemoveProperty(NPObject *obj,
- NPIdentifier name);
- static bool NPNEnumerate(NPObject *obj,
- NPIdentifier **value,
- uint32_t *count);
- static bool NPNConstruct(NPObject *npobj,
- const NPVariant *args,
- uint32_t arg_count,
- NPVariant *result);
-
- // The next two functions are only called on NPObjects from the browser.
- static bool NPNEvaluate(NPP npp,
- NPObject *obj,
- NPString *script,
- NPVariant *result);
-
- static bool NPInvokePrivate(NPP npp,
- NPObject *obj,
- bool is_default,
- NPIdentifier name,
- const NPVariant *args,
- uint32_t arg_count,
- NPVariant *result);
-
- static NPObjectProxy* GetProxy(NPObject* object);
- static const NPClass* npclass() { return &npclass_proxy_; }
-
- // NPObjectBase implementation.
- NPObject* GetUnderlyingNPObject() override;
-
- IPC::Listener* GetChannelListener() override;
-
- private:
- NPObjectProxy(NPChannelBase* channel,
- int route_id,
- int render_view_id,
- const GURL& page_url);
-
- // IPC::Listener implementation:
- bool OnMessageReceived(const IPC::Message& msg) override;
- void OnChannelError() override;
-
- static NPObject* NPAllocate(NPP, NPClass*);
- static void NPDeallocate(NPObject* npObj);
-
- // This function is only caled on NPObjects from the plugin.
- static void NPPInvalidate(NPObject *obj);
- static NPClass npclass_proxy_;
-
- scoped_refptr<NPChannelBase> channel_;
- int route_id_;
- int render_view_id_;
-
- // The url of the main frame hosting the plugin.
- GURL page_url_;
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_NPAPI_NPOBJECT_PROXY_H_
diff --git a/chromium/content/child/npapi/npobject_stub.cc b/chromium/content/child/npapi/npobject_stub.cc
deleted file mode 100644
index a8f512809eb..00000000000
--- a/chromium/content/child/npapi/npobject_stub.cc
+++ /dev/null
@@ -1,424 +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/child/npapi/npobject_stub.h"
-
-#include "build/build_config.h"
-#include "content/child/npapi/np_channel_base.h"
-#include "content/child/npapi/npobject_util.h"
-#include "content/child/plugin_messages.h"
-#include "content/public/common/content_client.h"
-#include "content/public/common/content_switches.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
-#include "third_party/npapi/bindings/npapi.h"
-#include "third_party/npapi/bindings/npruntime.h"
-
-#if defined(OS_WIN)
-#include "base/command_line.h"
-#include "content/common/plugin_constants_win.h"
-#endif
-
-using blink::WebBindings;
-
-namespace content {
-
-NPObjectStub::NPObjectStub(
- NPObject* npobject,
- NPChannelBase* channel,
- int route_id,
- int render_view_id,
- const GURL& page_url)
- : npobject_(npobject),
- channel_(channel),
- route_id_(route_id),
- render_view_id_(render_view_id),
- page_url_(page_url) {
- channel_->AddMappingForNPObjectStub(route_id, npobject);
- channel_->AddRoute(route_id, this, this);
-
- // We retain the object just as PluginHost does if everything was in-process.
- WebBindings::retainObject(npobject_);
-}
-
-NPObjectStub::~NPObjectStub() {
- channel_->RemoveRoute(route_id_);
- DCHECK(!npobject_);
-}
-
-void NPObjectStub::DeleteSoon() {
- if (npobject_) {
- channel_->RemoveMappingForNPObjectStub(route_id_, npobject_);
-
- // We need to NULL npobject_ prior to calling releaseObject() to avoid
- // problems with re-entrancy. See http://crbug.com/94179#c17 for more
- // details on how this can happen.
- NPObject* npobject = npobject_;
- npobject_ = NULL;
-
- WebBindings::releaseObject(npobject);
-
- base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
- }
-}
-
-bool NPObjectStub::Send(IPC::Message* msg) {
- return channel_->Send(msg);
-}
-
-NPObject* NPObjectStub::GetUnderlyingNPObject() {
- return npobject_;
-}
-
-IPC::Listener* NPObjectStub::GetChannelListener() {
- return static_cast<IPC::Listener*>(this);
-}
-
-bool NPObjectStub::OnMessageReceived(const IPC::Message& msg) {
- GetContentClient()->SetActiveURL(page_url_);
- if (!npobject_) {
- if (msg.is_sync()) {
- // The object could be garbage because the frame has gone away, so
- // just send an error reply to the caller.
- IPC::Message* reply = IPC::SyncMessage::GenerateReply(&msg);
- reply->set_reply_error();
- Send(reply);
- }
-
- return true;
- }
-
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(NPObjectStub, msg)
- IPC_MESSAGE_HANDLER_DELAY_REPLY(NPObjectMsg_Release, OnRelease);
- IPC_MESSAGE_HANDLER(NPObjectMsg_HasMethod, OnHasMethod);
- IPC_MESSAGE_HANDLER_DELAY_REPLY(NPObjectMsg_Invoke, OnInvoke);
- IPC_MESSAGE_HANDLER(NPObjectMsg_HasProperty, OnHasProperty);
- IPC_MESSAGE_HANDLER(NPObjectMsg_GetProperty, OnGetProperty);
- IPC_MESSAGE_HANDLER_DELAY_REPLY(NPObjectMsg_SetProperty, OnSetProperty);
- IPC_MESSAGE_HANDLER(NPObjectMsg_RemoveProperty, OnRemoveProperty);
- IPC_MESSAGE_HANDLER(NPObjectMsg_Invalidate, OnInvalidate);
- IPC_MESSAGE_HANDLER(NPObjectMsg_Enumeration, OnEnumeration);
- IPC_MESSAGE_HANDLER_DELAY_REPLY(NPObjectMsg_Construct, OnConstruct);
- IPC_MESSAGE_HANDLER_DELAY_REPLY(NPObjectMsg_Evaluate, OnEvaluate);
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- DCHECK(handled);
- return handled;
-}
-
-void NPObjectStub::OnChannelError() {
- DeleteSoon();
-}
-
-void NPObjectStub::OnRelease(IPC::Message* reply_msg) {
- Send(reply_msg);
- DeleteSoon();
-}
-
-void NPObjectStub::OnHasMethod(const NPIdentifier_Param& name,
- bool* result) {
- NPIdentifier id = CreateNPIdentifier(name);
- // If we're in the plugin process, then the stub is holding onto an NPObject
- // from the plugin, so all function calls on it need to go through the
- // functions in NPClass. If we're in the renderer process, then we just call
- // the NPN_ functions.
- if (IsPluginProcess()) {
- if (npobject_->_class->hasMethod) {
- *result = npobject_->_class->hasMethod(npobject_, id);
- } else {
- *result = false;
- }
- } else {
- *result = WebBindings::hasMethod(0, npobject_, id);
- }
-}
-
-void NPObjectStub::OnInvoke(bool is_default,
- const NPIdentifier_Param& method,
- const std::vector<NPVariant_Param>& args,
- IPC::Message* reply_msg) {
- bool return_value = false;
- NPVariant_Param result_param;
- NPVariant result_var;
-
- VOID_TO_NPVARIANT(result_var);
- result_param.type = NPVARIANT_PARAM_VOID;
-
- int arg_count = static_cast<int>(args.size());
- NPVariant* args_var = new NPVariant[arg_count];
- for (int i = 0; i < arg_count; ++i) {
- if (!CreateNPVariant(args[i],
- channel_.get(),
- &(args_var[i]),
- render_view_id_,
- page_url_)) {
- NPObjectMsg_Invoke::WriteReplyParams(
- reply_msg, result_param, return_value);
- channel_->Send(reply_msg);
- delete[] args_var;
- return;
- }
- }
-
- if (is_default) {
- if (IsPluginProcess()) {
- if (npobject_->_class->invokeDefault) {
- return_value = npobject_->_class->invokeDefault(
- npobject_, args_var, arg_count, &result_var);
- } else {
- return_value = false;
- }
- } else {
- return_value = WebBindings::invokeDefault(
- 0, npobject_, args_var, arg_count, &result_var);
- }
- } else {
- NPIdentifier id = CreateNPIdentifier(method);
- if (IsPluginProcess()) {
- if (npobject_->_class->invoke) {
- return_value = npobject_->_class->invoke(
- npobject_, id, args_var, arg_count, &result_var);
- } else {
- return_value = false;
- }
- } else {
- return_value = WebBindings::invoke(
- 0, npobject_, id, args_var, arg_count, &result_var);
- }
- }
-
- for (int i = 0; i < arg_count; ++i)
- WebBindings::releaseVariantValue(&(args_var[i]));
-
- delete[] args_var;
-
- CreateNPVariantParam(result_var,
- channel_.get(),
- &result_param,
- true,
- render_view_id_,
- page_url_);
- NPObjectMsg_Invoke::WriteReplyParams(reply_msg, result_param, return_value);
- channel_->Send(reply_msg);
-}
-
-void NPObjectStub::OnHasProperty(const NPIdentifier_Param& name,
- bool* result) {
- NPIdentifier id = CreateNPIdentifier(name);
- if (IsPluginProcess()) {
- if (npobject_->_class->hasProperty) {
- *result = npobject_->_class->hasProperty(npobject_, id);
- } else {
- *result = false;
- }
- } else {
- *result = WebBindings::hasProperty(0, npobject_, id);
- }
-}
-
-void NPObjectStub::OnGetProperty(const NPIdentifier_Param& name,
- NPVariant_Param* property,
- bool* result) {
- NPVariant result_var;
- VOID_TO_NPVARIANT(result_var);
- NPIdentifier id = CreateNPIdentifier(name);
-
- if (IsPluginProcess()) {
- if (npobject_->_class->getProperty) {
- *result = npobject_->_class->getProperty(npobject_, id, &result_var);
- } else {
- *result = false;
- }
- } else {
- *result = WebBindings::getProperty(0, npobject_, id, &result_var);
- }
-
- CreateNPVariantParam(
- result_var, channel_.get(), property, true, render_view_id_, page_url_);
-}
-
-void NPObjectStub::OnSetProperty(const NPIdentifier_Param& name,
- const NPVariant_Param& property,
- IPC::Message* reply_msg) {
- bool result = false;
- NPIdentifier id = CreateNPIdentifier(name);
- NPVariant property_var;
- if (!CreateNPVariant(property,
- channel_.get(),
- &property_var,
- render_view_id_,
- page_url_)) {
- NPObjectMsg_SetProperty::WriteReplyParams(reply_msg, result);
- channel_->Send(reply_msg);
- return;
- }
-
- if (IsPluginProcess()) {
- if (npobject_->_class->setProperty) {
-#if defined(OS_WIN)
- static base::FilePath plugin_path =
- base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
- switches::kPluginPath);
- static std::wstring filename = base::ToLowerASCII(
- plugin_path.BaseName().value());
- static NPIdentifier fullscreen =
- WebBindings::getStringIdentifier("fullScreen");
- if (filename == kNewWMPPlugin && id == fullscreen) {
- // Workaround for bug 15985, which is if Flash causes WMP to go
- // full screen a deadlock can occur when WMP calls SetFocus.
- NPObjectMsg_SetProperty::WriteReplyParams(reply_msg, true);
- Send(reply_msg);
- reply_msg = NULL;
- }
-#endif
- result = npobject_->_class->setProperty(npobject_, id, &property_var);
- } else {
- result = false;
- }
- } else {
- result = WebBindings::setProperty(0, npobject_, id, &property_var);
- }
-
- WebBindings::releaseVariantValue(&property_var);
-
- if (reply_msg) {
- NPObjectMsg_SetProperty::WriteReplyParams(reply_msg, result);
- Send(reply_msg);
- }
-}
-
-void NPObjectStub::OnRemoveProperty(const NPIdentifier_Param& name,
- bool* result) {
- NPIdentifier id = CreateNPIdentifier(name);
- if (IsPluginProcess()) {
- if (npobject_->_class->removeProperty) {
- *result = npobject_->_class->removeProperty(npobject_, id);
- } else {
- *result = false;
- }
- } else {
- *result = WebBindings::removeProperty(0, npobject_, id);
- }
-}
-
-void NPObjectStub::OnInvalidate() {
- if (!IsPluginProcess()) {
- NOTREACHED() << "Should only be called on NPObjects in the plugin";
- return;
- }
-
- if (!npobject_->_class->invalidate)
- return;
-
- npobject_->_class->invalidate(npobject_);
-}
-
-void NPObjectStub::OnEnumeration(std::vector<NPIdentifier_Param>* value,
- bool* result) {
- NPIdentifier* value_np = NULL;
- unsigned int count = 0;
- if (!IsPluginProcess()) {
- *result = WebBindings::enumerate(0, npobject_, &value_np, &count);
- } else {
- if (npobject_->_class->structVersion < NP_CLASS_STRUCT_VERSION_ENUM ||
- !npobject_->_class->enumerate) {
- *result = false;
- return;
- }
-
- *result = npobject_->_class->enumerate(npobject_, &value_np, &count);
- }
-
- if (!*result)
- return;
-
- for (unsigned int i = 0; i < count; ++i) {
- NPIdentifier_Param param;
- CreateNPIdentifierParam(value_np[i], &param);
- value->push_back(param);
- }
-
- free(value_np);
-}
-
-void NPObjectStub::OnConstruct(const std::vector<NPVariant_Param>& args,
- IPC::Message* reply_msg) {
- bool return_value = false;
- NPVariant_Param result_param;
- NPVariant result_var;
-
- VOID_TO_NPVARIANT(result_var);
-
- int arg_count = static_cast<int>(args.size());
- NPVariant* args_var = new NPVariant[arg_count];
- for (int i = 0; i < arg_count; ++i) {
- if (!CreateNPVariant(args[i],
- channel_.get(),
- &(args_var[i]),
- render_view_id_,
- page_url_)) {
- NPObjectMsg_Invoke::WriteReplyParams(
- reply_msg, result_param, return_value);
- channel_->Send(reply_msg);
- delete[] args_var;
- return;
- }
- }
-
- if (IsPluginProcess()) {
- if (npobject_->_class->structVersion >= NP_CLASS_STRUCT_VERSION_CTOR &&
- npobject_->_class->construct) {
- return_value = npobject_->_class->construct(
- npobject_, args_var, arg_count, &result_var);
- } else {
- return_value = false;
- }
- } else {
- return_value = WebBindings::construct(
- 0, npobject_, args_var, arg_count, &result_var);
- }
-
- for (int i = 0; i < arg_count; ++i)
- WebBindings::releaseVariantValue(&(args_var[i]));
-
- delete[] args_var;
-
- CreateNPVariantParam(result_var,
- channel_.get(),
- &result_param,
- true,
- render_view_id_,
- page_url_);
- NPObjectMsg_Invoke::WriteReplyParams(reply_msg, result_param, return_value);
- channel_->Send(reply_msg);
-}
-
-void NPObjectStub::OnEvaluate(const std::string& script,
- bool popups_allowed,
- IPC::Message* reply_msg) {
- if (IsPluginProcess()) {
- NOTREACHED() << "Should only be called on NPObjects in the renderer";
- return;
- }
-
- NPVariant result_var;
- NPString script_string;
- script_string.UTF8Characters = script.c_str();
- script_string.UTF8Length = static_cast<unsigned int>(script.length());
-
- bool return_value = WebBindings::evaluateHelper(0, popups_allowed, npobject_,
- &script_string, &result_var);
-
- NPVariant_Param result_param;
- CreateNPVariantParam(result_var,
- channel_.get(),
- &result_param,
- true,
- render_view_id_,
- page_url_);
- NPObjectMsg_Evaluate::WriteReplyParams(reply_msg, result_param, return_value);
- channel_->Send(reply_msg);
-}
-
-} // namespace content
diff --git a/chromium/content/child/npapi/npobject_stub.h b/chromium/content/child/npapi/npobject_stub.h
deleted file mode 100644
index 81cec4287fa..00000000000
--- a/chromium/content/child/npapi/npobject_stub.h
+++ /dev/null
@@ -1,99 +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 class that receives IPC messages from an NPObjectProxy and calls the real
-// NPObject.
-
-#ifndef CONTENT_CHILD_NPAPI_NPOBJECT_STUB_H_
-#define CONTENT_CHILD_NPAPI_NPOBJECT_STUB_H_
-
-#include <vector>
-
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "content/child/npapi/npobject_base.h"
-#include "ipc/ipc_listener.h"
-#include "ipc/ipc_sender.h"
-#include "url/gurl.h"
-
-struct NPObject;
-
-namespace content {
-class NPChannelBase;
-struct NPIdentifier_Param;
-struct NPVariant_Param;
-
-// This wraps an NPObject and converts IPC messages from NPObjectProxy to calls
-// to the object. The results are marshalled back. See npobject_proxy.h for
-// more information.
-class NPObjectStub : public IPC::Listener,
- public IPC::Sender,
- public base::SupportsWeakPtr<NPObjectStub>,
- public NPObjectBase {
- public:
- NPObjectStub(NPObject* npobject,
- NPChannelBase* channel,
- int route_id,
- int render_view_id,
- const GURL& page_url);
- ~NPObjectStub() override;
-
- // Schedules tear-down of this stub. The underlying NPObject reference is
- // released, and further invokations from the IPC channel will fail once this
- // call has returned. Deletion of the stub is deferred to the main loop, in
- // case it is touched as the stack unwinds. DeleteSoon() is safe to call
- // more than once, until control returns to the main loop.
- void DeleteSoon();
-
- // IPC::Sender implementation:
- bool Send(IPC::Message* msg) override;
-
- // NPObjectBase implementation.
- NPObject* GetUnderlyingNPObject() override;
- IPC::Listener* GetChannelListener() override;
-
- private:
- // IPC::Listener implementation:
- bool OnMessageReceived(const IPC::Message& message) override;
- void OnChannelError() override;
-
- // message handlers
- void OnRelease(IPC::Message* reply_msg);
- void OnHasMethod(const NPIdentifier_Param& name,
- bool* result);
- void OnInvoke(bool is_default,
- const NPIdentifier_Param& method,
- const std::vector<NPVariant_Param>& args,
- IPC::Message* reply_msg);
- void OnHasProperty(const NPIdentifier_Param& name,
- bool* result);
- void OnGetProperty(const NPIdentifier_Param& name,
- NPVariant_Param* property,
- bool* result);
- void OnSetProperty(const NPIdentifier_Param& name,
- const NPVariant_Param& property,
- IPC::Message* reply_msg);
- void OnRemoveProperty(const NPIdentifier_Param& name,
- bool* result);
- void OnInvalidate();
- void OnEnumeration(std::vector<NPIdentifier_Param>* value,
- bool* result);
- void OnConstruct(const std::vector<NPVariant_Param>& args,
- IPC::Message* reply_msg);
- void OnEvaluate(const std::string& script, bool popups_allowed,
- IPC::Message* reply_msg);
-
- private:
- NPObject* npobject_;
- scoped_refptr<NPChannelBase> channel_;
- int route_id_;
- int render_view_id_;
-
- // The url of the main frame hosting the plugin.
- GURL page_url_;
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_NPAPI_NPOBJECT_STUB_H_
diff --git a/chromium/content/child/npapi/npobject_util.cc b/chromium/content/child/npapi/npobject_util.cc
deleted file mode 100644
index aeb66ae3700..00000000000
--- a/chromium/content/child/npapi/npobject_util.cc
+++ /dev/null
@@ -1,310 +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/child/npapi/npobject_util.h"
-
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-
-#include "base/strings/string_util.h"
-#include "content/child/npapi/np_channel_base.h"
-#include "content/child/npapi/npobject_proxy.h"
-#include "content/child/npapi/plugin_host.h"
-#include "content/child/plugin_messages.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
-#include "third_party/npapi/bindings/nphostapi.h"
-
-using blink::WebBindings;
-
-namespace content {
-
-// true if the current process is a plugin process, false otherwise.
-static bool g_plugin_process;
-
-namespace {
-#if defined(ENABLE_PLUGINS)
-// The next 7 functions are called by the plugin code when it's using the
-// NPObject. Plugins always ignore the functions in NPClass (except allocate
-// and deallocate), and instead just use the function pointers that were
-// passed in NPInitialize.
-// When the renderer interacts with an NPObject from the plugin, it of course
-// uses the function pointers in its NPClass structure.
-static bool NPN_HasMethodPatch(NPP npp,
- NPObject *npobj,
- NPIdentifier methodName) {
- return NPObjectProxy::NPHasMethod(npobj, methodName);
-}
-
-static bool NPN_InvokePatch(NPP npp, NPObject *npobj,
- NPIdentifier methodName,
- const NPVariant *args,
- uint32_t argCount,
- NPVariant *result) {
- return NPObjectProxy::NPInvokePrivate(npp, npobj, false, methodName, args,
- argCount, result);
-}
-
-static bool NPN_InvokeDefaultPatch(NPP npp,
- NPObject *npobj,
- const NPVariant *args,
- uint32_t argCount,
- NPVariant *result) {
- return NPObjectProxy::NPInvokePrivate(npp, npobj, true, 0, args, argCount,
- result);
-}
-
-static bool NPN_HasPropertyPatch(NPP npp,
- NPObject *npobj,
- NPIdentifier propertyName) {
- return NPObjectProxy::NPHasProperty(npobj, propertyName);
-}
-
-static bool NPN_GetPropertyPatch(NPP npp,
- NPObject *npobj,
- NPIdentifier propertyName,
- NPVariant *result) {
- return NPObjectProxy::NPGetProperty(npobj, propertyName, result);
-}
-
-static bool NPN_SetPropertyPatch(NPP npp,
- NPObject *npobj,
- NPIdentifier propertyName,
- const NPVariant *value) {
- return NPObjectProxy::NPSetProperty(npobj, propertyName, value);
-}
-
-static bool NPN_RemovePropertyPatch(NPP npp,
- NPObject *npobj,
- NPIdentifier propertyName) {
- return NPObjectProxy::NPRemoveProperty(npobj, propertyName);
-}
-
-static bool NPN_EvaluatePatch(NPP npp,
- NPObject *npobj,
- NPString *script,
- NPVariant *result) {
- return NPObjectProxy::NPNEvaluate(npp, npobj, script, result);
-}
-
-
-static void NPN_SetExceptionPatch(NPObject *obj, const NPUTF8 *message) {
- std::string message_str(message);
- if (IsPluginProcess()) {
- NPChannelBase* renderer_channel = NPChannelBase::GetCurrentChannel();
- if (renderer_channel)
- renderer_channel->Send(new PluginHostMsg_SetException(message_str));
- } else {
- WebBindings::setException(obj, message_str.c_str());
- }
-}
-
-static bool NPN_EnumeratePatch(NPP npp, NPObject *obj,
- NPIdentifier **identifier, uint32_t *count) {
- return NPObjectProxy::NPNEnumerate(obj, identifier, count);
-}
-
-// The overrided table of functions provided to the plugin.
-NPNetscapeFuncs *GetHostFunctions() {
- static bool init = false;
- static NPNetscapeFuncs host_funcs;
- if (init)
- return &host_funcs;
-
- memset(&host_funcs, 0, sizeof(host_funcs));
- host_funcs.invoke = NPN_InvokePatch;
- host_funcs.invokeDefault = NPN_InvokeDefaultPatch;
- host_funcs.evaluate = NPN_EvaluatePatch;
- host_funcs.getproperty = NPN_GetPropertyPatch;
- host_funcs.setproperty = NPN_SetPropertyPatch;
- host_funcs.removeproperty = NPN_RemovePropertyPatch;
- host_funcs.hasproperty = NPN_HasPropertyPatch;
- host_funcs.hasmethod = NPN_HasMethodPatch;
- host_funcs.setexception = NPN_SetExceptionPatch;
- host_funcs.enumerate = NPN_EnumeratePatch;
-
- init = true;
- return &host_funcs;
-}
-
-#endif // defined(ENABLE_PLUGINS)
-}
-
-#if defined(ENABLE_PLUGINS)
-void PatchNPNFunctions() {
- g_plugin_process = true;
- NPNetscapeFuncs* funcs = GetHostFunctions();
- PluginHost::Singleton()->PatchNPNetscapeFuncs(funcs);
-}
-#endif
-
-bool IsPluginProcess() {
- return g_plugin_process;
-}
-
-void CreateNPIdentifierParam(NPIdentifier id, NPIdentifier_Param* param) {
- param->identifier = id;
-}
-
-NPIdentifier CreateNPIdentifier(const NPIdentifier_Param& param) {
- return param.identifier;
-}
-
-void CreateNPVariantParam(const NPVariant& variant,
- NPChannelBase* channel,
- NPVariant_Param* param,
- bool release,
- int render_view_id,
- const GURL& page_url) {
- switch (variant.type) {
- case NPVariantType_Void:
- param->type = NPVARIANT_PARAM_VOID;
- break;
- case NPVariantType_Null:
- param->type = NPVARIANT_PARAM_NULL;
- break;
- case NPVariantType_Bool:
- param->type = NPVARIANT_PARAM_BOOL;
- param->bool_value = variant.value.boolValue;
- break;
- case NPVariantType_Int32:
- param->type = NPVARIANT_PARAM_INT;
- param->int_value = variant.value.intValue;
- break;
- case NPVariantType_Double:
- param->type = NPVARIANT_PARAM_DOUBLE;
- param->double_value = variant.value.doubleValue;
- break;
- case NPVariantType_String:
- param->type = NPVARIANT_PARAM_STRING;
- if (variant.value.stringValue.UTF8Length) {
- param->string_value.assign(variant.value.stringValue.UTF8Characters,
- variant.value.stringValue.UTF8Length);
- }
- break;
- case NPVariantType_Object: {
- if (variant.value.objectValue->_class == NPObjectProxy::npclass()) {
- param->type = NPVARIANT_PARAM_RECEIVER_OBJECT_ROUTING_ID;
- NPObjectProxy* proxy =
- NPObjectProxy::GetProxy(variant.value.objectValue);
- DCHECK(proxy);
- param->npobject_routing_id = proxy->route_id();
- // Don't release, because our original variant is the same as our proxy.
- release = false;
- } else {
- // The channel could be NULL if there was a channel error. The caller's
- // Send call will fail anyways.
- if (channel) {
- // NPObjectStub adds its own reference to the NPObject it owns, so if
- // we were supposed to release the corresponding variant
- // (release==true), we should still do that.
- param->type = NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID;
- int route_id = channel->GetExistingRouteForNPObjectStub(
- variant.value.objectValue);
- if (route_id != MSG_ROUTING_NONE) {
- param->npobject_routing_id = route_id;
- } else {
- route_id = channel->GenerateRouteID();
- new NPObjectStub(
- variant.value.objectValue, channel, route_id, render_view_id,
- page_url);
- param->npobject_routing_id = route_id;
- }
-
- // Include the object's owner, should be the result of
- // _NPN_GetObjectOwner, but we don't have that.
- NPP owner = 0;
- param->npobject_owner_id =
- channel->GetExistingRouteForNPObjectOwner(owner);
- } else {
- param->type = NPVARIANT_PARAM_VOID;
- }
- }
- break;
- }
- default:
- NOTREACHED();
- }
-
- if (release)
- WebBindings::releaseVariantValue(const_cast<NPVariant*>(&variant));
-}
-
-bool CreateNPVariant(const NPVariant_Param& param,
- NPChannelBase* channel,
- NPVariant* result,
- int render_view_id,
- const GURL& page_url) {
- switch (param.type) {
- case NPVARIANT_PARAM_VOID:
- result->type = NPVariantType_Void;
- break;
- case NPVARIANT_PARAM_NULL:
- result->type = NPVariantType_Null;
- break;
- case NPVARIANT_PARAM_BOOL:
- result->type = NPVariantType_Bool;
- result->value.boolValue = param.bool_value;
- break;
- case NPVARIANT_PARAM_INT:
- result->type = NPVariantType_Int32;
- result->value.intValue = param.int_value;
- break;
- case NPVARIANT_PARAM_DOUBLE:
- result->type = NPVariantType_Double;
- result->value.doubleValue = param.double_value;
- break;
- case NPVARIANT_PARAM_STRING: {
- result->type = NPVariantType_String;
- void* buffer = malloc(param.string_value.size());
- size_t size = param.string_value.size();
- result->value.stringValue.UTF8Characters = static_cast<NPUTF8*>(buffer);
- memcpy(buffer, param.string_value.c_str(), size);
- result->value.stringValue.UTF8Length = static_cast<int>(size);
- break;
- }
- case NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID: {
- result->type = NPVariantType_Object;
- NPObject* object =
- channel->GetExistingNPObjectProxy(param.npobject_routing_id);
- if (object) {
- WebBindings::retainObject(object);
- result->value.objectValue = object;
- } else {
- NPP owner =
- channel->GetExistingNPObjectOwner(param.npobject_owner_id);
- // TODO(wez): Once NPObject tracking lands in Blink, check |owner| and
- // return NPVariantType_Void if it is NULL.
- result->value.objectValue =
- NPObjectProxy::Create(channel,
- param.npobject_routing_id,
- render_view_id,
- page_url,
- owner);
- }
- break;
- }
- case NPVARIANT_PARAM_RECEIVER_OBJECT_ROUTING_ID: {
- NPObjectBase* npobject_base =
- channel->GetNPObjectListenerForRoute(param.npobject_routing_id);
- if (!npobject_base) {
- DLOG(WARNING) << "Invalid routing id passed in"
- << param.npobject_routing_id;
- return false;
- }
-
- DCHECK(npobject_base->GetUnderlyingNPObject() != NULL);
-
- result->type = NPVariantType_Object;
- result->value.objectValue = npobject_base->GetUnderlyingNPObject();
- WebBindings::retainObject(result->value.objectValue);
- break;
- }
- default:
- NOTREACHED();
- }
- return true;
-}
-
-} // namespace content
diff --git a/chromium/content/child/npapi/npobject_util.h b/chromium/content/child/npapi/npobject_util.h
deleted file mode 100644
index 97a848289c2..00000000000
--- a/chromium/content/child/npapi/npobject_util.h
+++ /dev/null
@@ -1,74 +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.
-//
-// Helper functions that are used by the NPObject proxy and stub.
-
-#ifndef CONTENT_CHILD_NPAPI_NPOBJECT_UTIL_H_
-#define CONTENT_CHILD_NPAPI_NPOBJECT_UTIL_H_
-
-#include "build/build_config.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-
-#include "content/child/npapi/npobject_stub.h"
-
-class GURL;
-
-struct _NPVariant;
-
-typedef _NPVariant NPVariant;
-typedef void *NPIdentifier;
-
-namespace content {
-class NPChannelBase;
-struct NPIdentifier_Param;
-struct NPVariant_Param;
-
-// Needs to be called early in the plugin process lifetime, before any
-// plugin instances are initialized.
-void PatchNPNFunctions();
-
-// Returns true if the current process is a plugin process, or false otherwise.
-bool IsPluginProcess();
-
-// Creates an object similar to NPIdentifier that can be marshalled.
-void CreateNPIdentifierParam(NPIdentifier id, NPIdentifier_Param* param);
-
-// Creates an NPIdentifier from the marshalled object.
-NPIdentifier CreateNPIdentifier(const NPIdentifier_Param& param);
-
-// Creates an object similar to NPVariant that can be marshalled.
-// If the containing NPObject happens to be an NPObject, then a stub
-// is created around it and param holds the routing id for it.
-// If release is true, the NPVariant object is released (except if
-// it contains an NPObject, since the stub will manage its lifetime).
-void CreateNPVariantParam(const NPVariant& variant,
- NPChannelBase* channel,
- NPVariant_Param* param,
- bool release,
- int render_view_id,
- const GURL& page_url);
-
-// Creates an NPVariant from the marshalled object.
-// Returns true on success.
-bool CreateNPVariant(const NPVariant_Param& param,
- NPChannelBase* channel,
- NPVariant* result,
- int render_view_id,
- const GURL& page_url);
-
-#if defined(OS_WIN)
-// Given a plugin's HWND, returns an event associated with the WebContentsImpl
-// that's set when inside a messagebox. This tells the plugin process that
-// the message queue should be pumped (as what would happen if everything was
-// in-process). This avoids deadlocks when a plugin invokes javascript that
-// causes a message box to come up.
-HANDLE GetMessageBoxEvent(HWND hwnd);
-#endif // defined(OS_WIN)
-
-} // namespace content
-
-#endif // CONTENT_CHILD_NPAPI_NPOBJECT_UTIL_H_
diff --git a/chromium/content/child/npapi/npruntime_util.cc b/chromium/content/child/npapi/npruntime_util.cc
deleted file mode 100644
index 2f80fa17953..00000000000
--- a/chromium/content/child/npapi/npruntime_util.cc
+++ /dev/null
@@ -1,54 +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/child/npapi/npruntime_util.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "base/pickle.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
-
-using blink::WebBindings;
-
-namespace content {
-
-bool SerializeNPIdentifier(NPIdentifier identifier, base::Pickle* pickle) {
- const NPUTF8* string;
- int32_t number;
- bool is_string;
- WebBindings::extractIdentifierData(identifier, string, number, is_string);
-
- if (!pickle->WriteBool(is_string))
- return false;
- if (is_string) {
- // Write the null byte for efficiency on the other end.
- return pickle->WriteData(string, strlen(string) + 1);
- }
- return pickle->WriteInt(number);
-}
-
-bool DeserializeNPIdentifier(base::PickleIterator* pickle_iter,
- NPIdentifier* identifier) {
- bool is_string;
- if (!pickle_iter->ReadBool(&is_string))
- return false;
-
- if (is_string) {
- const char* data;
- int data_len;
- if (!pickle_iter->ReadData(&data, &data_len))
- return false;
- DCHECK_EQ((static_cast<size_t>(data_len)), strlen(data) + 1);
- *identifier = WebBindings::getStringIdentifier(data);
- } else {
- int number;
- if (!pickle_iter->ReadInt(&number))
- return false;
- *identifier = WebBindings::getIntIdentifier(number);
- }
- return true;
-}
-
-} // namespace content
diff --git a/chromium/content/child/npapi/npruntime_util.h b/chromium/content/child/npapi/npruntime_util.h
deleted file mode 100644
index f0ddabba620..00000000000
--- a/chromium/content/child/npapi/npruntime_util.h
+++ /dev/null
@@ -1,24 +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_CHILD_NPAPI_NPRUNTIME_UTIL_H_
-#define CONTENT_CHILD_NPAPI_NPRUNTIME_UTIL_H_
-
-#include "third_party/npapi/bindings/npruntime.h"
-
-namespace base {
-class Pickle;
-class PickleIterator;
-}
-
-namespace content {
-
-// Efficiently serialize/deserialize a NPIdentifier
-bool SerializeNPIdentifier(NPIdentifier identifier, base::Pickle* pickle);
-bool DeserializeNPIdentifier(base::PickleIterator* pickle_iter,
- NPIdentifier* identifier);
-
-} // namespace content
-
-#endif // CONTENT_CHILD_NPAPI_NPRUNTIME_UTIL_H_
diff --git a/chromium/content/child/npapi/plugin_host.cc b/chromium/content/child/npapi/plugin_host.cc
deleted file mode 100644
index 47467ae6bc0..00000000000
--- a/chromium/content/child/npapi/plugin_host.cc
+++ /dev/null
@@ -1,938 +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/child/npapi/plugin_host.h"
-
-#include <stddef.h>
-#include <string.h>
-
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_util.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
-#include "content/child/npapi/plugin_instance.h"
-#include "content/child/npapi/plugin_lib.h"
-#include "content/child/npapi/webplugin_delegate.h"
-#include "content/public/common/content_client.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/user_agent.h"
-#include "content/public/common/webplugininfo.h"
-#include "net/base/filename_util.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
-#include "third_party/WebKit/public/web/WebKit.h"
-#include "third_party/npapi/bindings/npruntime.h"
-#include "ui/gl/gl_implementation.h"
-#include "ui/gl/gl_surface.h"
-
-using blink::WebBindings;
-
-// Declarations for stub implementations of deprecated functions, which are no
-// longer listed in npapi.h.
-extern "C" {
-void* NPN_GetJavaEnv();
-void* NPN_GetJavaPeer(NPP);
-}
-
-namespace content {
-
-// Finds a PluginInstance from an NPP.
-// The caller must take a reference if needed.
-static PluginInstance* FindInstance(NPP id) {
- if (id == NULL) {
- return NULL;
- }
- return reinterpret_cast<PluginInstance*>(id->ndata);
-}
-
-#if defined(OS_MACOSX)
-// Returns true if Core Animation plugins are supported. This requires that the
-// OS supports shared accelerated surfaces via IOSurface. This is true on Snow
-// Leopard and higher.
-static bool SupportsCoreAnimationPlugins() {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableCoreAnimationPlugins))
- return false;
- // We also need to be running with desktop GL and not the software
- // OSMesa renderer in order to share accelerated surfaces between
- // processes. Because on MacOS we lazy-initialize GLSurface in the
- // renderer process here, ensure we're not also initializing GL somewhere
- // else, and that we only do this once.
- static gfx::GLImplementation implementation = gfx::kGLImplementationNone;
- if (implementation == gfx::kGLImplementationNone) {
- // Not initialized yet.
- DCHECK_EQ(implementation, gfx::GetGLImplementation())
- << "GL already initialized by someone else to: "
- << gfx::GetGLImplementation();
- if (!gfx::GLSurface::InitializeOneOff()) {
- return false;
- }
- implementation = gfx::GetGLImplementation();
- }
- return (implementation == gfx::kGLImplementationDesktopGL);
-}
-#endif
-
-PluginHost::PluginHost() {
- InitializeHostFuncs();
-}
-
-PluginHost::~PluginHost() {
-}
-
-PluginHost *PluginHost::Singleton() {
- CR_DEFINE_STATIC_LOCAL(scoped_refptr<PluginHost>, singleton, ());
- if (singleton.get() == NULL) {
- singleton = new PluginHost();
- }
-
- DCHECK(singleton.get() != NULL);
- return singleton.get();
-}
-
-void PluginHost::InitializeHostFuncs() {
- memset(&host_funcs_, 0, sizeof(host_funcs_));
- host_funcs_.size = sizeof(host_funcs_);
- host_funcs_.version = (NP_VERSION_MAJOR << 8) | (NP_VERSION_MINOR);
-
- // The "basic" functions
- host_funcs_.geturl = &NPN_GetURL;
- host_funcs_.posturl = &NPN_PostURL;
- host_funcs_.requestread = &NPN_RequestRead;
- host_funcs_.newstream = &NPN_NewStream;
- host_funcs_.write = &NPN_Write;
- host_funcs_.destroystream = &NPN_DestroyStream;
- host_funcs_.status = &NPN_Status;
- host_funcs_.uagent = &NPN_UserAgent;
- host_funcs_.memalloc = &NPN_MemAlloc;
- host_funcs_.memfree = &NPN_MemFree;
- host_funcs_.memflush = &NPN_MemFlush;
- host_funcs_.reloadplugins = &NPN_ReloadPlugins;
-
- // Stubs for deprecated Java functions
- host_funcs_.getJavaEnv = &NPN_GetJavaEnv;
- host_funcs_.getJavaPeer = &NPN_GetJavaPeer;
-
- // Advanced functions we implement
- host_funcs_.geturlnotify = &NPN_GetURLNotify;
- host_funcs_.posturlnotify = &NPN_PostURLNotify;
- host_funcs_.getvalue = &NPN_GetValue;
- host_funcs_.setvalue = &NPN_SetValue;
- host_funcs_.invalidaterect = &NPN_InvalidateRect;
- host_funcs_.invalidateregion = &NPN_InvalidateRegion;
- host_funcs_.forceredraw = &NPN_ForceRedraw;
-
- // These come from the Javascript Engine
- host_funcs_.getstringidentifier = WebBindings::getStringIdentifier;
- host_funcs_.getstringidentifiers = WebBindings::getStringIdentifiers;
- host_funcs_.getintidentifier = WebBindings::getIntIdentifier;
- host_funcs_.identifierisstring = WebBindings::identifierIsString;
- host_funcs_.utf8fromidentifier = WebBindings::utf8FromIdentifier;
- host_funcs_.intfromidentifier = WebBindings::intFromIdentifier;
- host_funcs_.createobject = WebBindings::createObject;
- host_funcs_.retainobject = WebBindings::retainObject;
- host_funcs_.releaseobject = WebBindings::releaseObject;
- host_funcs_.invoke = WebBindings::invoke;
- host_funcs_.invokeDefault = WebBindings::invokeDefault;
- host_funcs_.evaluate = WebBindings::evaluate;
- host_funcs_.getproperty = WebBindings::getProperty;
- host_funcs_.setproperty = WebBindings::setProperty;
- host_funcs_.removeproperty = WebBindings::removeProperty;
- host_funcs_.hasproperty = WebBindings::hasProperty;
- host_funcs_.hasmethod = WebBindings::hasMethod;
- host_funcs_.releasevariantvalue = WebBindings::releaseVariantValue;
- host_funcs_.setexception = WebBindings::setException;
- host_funcs_.pushpopupsenabledstate = NPN_PushPopupsEnabledState;
- host_funcs_.poppopupsenabledstate = NPN_PopPopupsEnabledState;
- host_funcs_.enumerate = WebBindings::enumerate;
- host_funcs_.pluginthreadasynccall = NPN_PluginThreadAsyncCall;
- host_funcs_.construct = WebBindings::construct;
- host_funcs_.getvalueforurl = NPN_GetValueForURL;
- host_funcs_.setvalueforurl = NPN_SetValueForURL;
- host_funcs_.getauthenticationinfo = NPN_GetAuthenticationInfo;
- host_funcs_.scheduletimer = NPN_ScheduleTimer;
- host_funcs_.unscheduletimer = NPN_UnscheduleTimer;
- host_funcs_.popupcontextmenu = NPN_PopUpContextMenu;
- host_funcs_.convertpoint = NPN_ConvertPoint;
- host_funcs_.handleevent = NPN_HandleEvent;
- host_funcs_.unfocusinstance = NPN_UnfocusInstance;
- host_funcs_.urlredirectresponse = NPN_URLRedirectResponse;
-}
-
-void PluginHost::PatchNPNetscapeFuncs(NPNetscapeFuncs* overrides) {
- // When running in the plugin process, we need to patch the NPN functions
- // that the plugin calls to interact with NPObjects that we give. Otherwise
- // the plugin will call the v8 NPN functions, which won't work since we have
- // an NPObjectProxy and not a real v8 implementation.
- if (overrides->invoke)
- host_funcs_.invoke = overrides->invoke;
-
- if (overrides->invokeDefault)
- host_funcs_.invokeDefault = overrides->invokeDefault;
-
- if (overrides->evaluate)
- host_funcs_.evaluate = overrides->evaluate;
-
- if (overrides->getproperty)
- host_funcs_.getproperty = overrides->getproperty;
-
- if (overrides->setproperty)
- host_funcs_.setproperty = overrides->setproperty;
-
- if (overrides->removeproperty)
- host_funcs_.removeproperty = overrides->removeproperty;
-
- if (overrides->hasproperty)
- host_funcs_.hasproperty = overrides->hasproperty;
-
- if (overrides->hasmethod)
- host_funcs_.hasmethod = overrides->hasmethod;
-
- if (overrides->setexception)
- host_funcs_.setexception = overrides->setexception;
-
- if (overrides->enumerate)
- host_funcs_.enumerate = overrides->enumerate;
-}
-
-bool PluginHost::SetPostData(const char* buf,
- uint32_t length,
- std::vector<std::string>* names,
- std::vector<std::string>* values,
- std::vector<char>* body) {
- // Use a state table to do the parsing. Whitespace must be
- // trimmed after the fact if desired. In our case, we actually
- // don't care about the whitespace, because we're just going to
- // pass this back into another POST. This function strips out the
- // "Content-length" header and does not append it to the request.
-
- //
- // This parser takes action only on state changes.
- //
- // Transition table:
- // : \n NULL Other
- // 0 GetHeader 1 2 4 0
- // 1 GetValue 1 0 3 1
- // 2 GetData 2 2 3 2
- // 3 DONE
- // 4 ERR
- //
- enum { INPUT_COLON=0, INPUT_NEWLINE, INPUT_NULL, INPUT_OTHER };
- enum { GETNAME, GETVALUE, GETDATA, DONE, ERR };
- int statemachine[3][4] = { { GETVALUE, GETDATA, GETDATA, GETNAME },
- { GETVALUE, GETNAME, DONE, GETVALUE },
- { GETDATA, GETDATA, DONE, GETDATA } };
- std::string name, value;
- const char* ptr = static_cast<const char*>(buf);
- const char* start = ptr;
- int state = GETNAME; // initial state
- bool done = false;
- bool err = false;
- do {
- int input;
-
- // Translate the current character into an input
- // for the state table.
- switch (*ptr) {
- case ':' :
- input = INPUT_COLON;
- break;
- case '\n':
- input = INPUT_NEWLINE;
- break;
- case 0 :
- input = INPUT_NULL;
- break;
- default :
- input = INPUT_OTHER;
- break;
- }
-
- int newstate = statemachine[state][input];
-
- // Take action based on the new state.
- if (state != newstate) {
- switch (newstate) {
- case GETNAME:
- // Got a value.
- value = std::string(start, ptr - start);
- base::TrimWhitespaceASCII(value, base::TRIM_ALL, &value);
- // If the name field is empty, we'll skip this header
- // but we won't error out.
- if (!name.empty() && name != "content-length") {
- names->push_back(name);
- values->push_back(value);
- }
- start = ptr + 1;
- break;
- case GETVALUE:
- // Got a header.
- name = base::ToLowerASCII(base::StringPiece(start, ptr - start));
- base::TrimWhitespaceASCII(name, base::TRIM_ALL, &name);
- start = ptr + 1;
- break;
- case GETDATA: {
- // Finished headers, now get body
- if (*ptr)
- start = ptr + 1;
- size_t previous_size = body->size();
- size_t new_body_size = length - static_cast<int>(start - buf);
- body->resize(previous_size + new_body_size);
- if (!body->empty())
- memcpy(&body->front() + previous_size, start, new_body_size);
- done = true;
- break;
- }
- case ERR:
- // error
- err = true;
- done = true;
- break;
- }
- }
- state = newstate;
- ptr++;
- } while (!done);
-
- return !err;
-}
-
-} // namespace content
-
-extern "C" {
-
-using content::FindInstance;
-using content::PluginHost;
-using content::PluginInstance;
-using content::WebPlugin;
-
-// Allocates memory from the host's memory space.
-void* NPN_MemAlloc(uint32_t size) {
- // Note: We must use the same allocator/deallocator
- // that is used by the javascript library, as some of the
- // JS APIs will pass memory to the plugin which the plugin
- // will attempt to free.
- return malloc(size);
-}
-
-// Deallocates memory from the host's memory space
-void NPN_MemFree(void* ptr) {
- if (ptr != NULL && ptr != reinterpret_cast<void*>(-1))
- free(ptr);
-}
-
-// Requests that the host free a specified amount of memory.
-uint32_t NPN_MemFlush(uint32_t size) {
- // This is not relevant on Windows; MAC specific
- return size;
-}
-
-// This is for dynamic discovery of new plugins.
-// Should force a re-scan of the plugins directory to load new ones.
-void NPN_ReloadPlugins(NPBool reload_pages) {
- blink::resetPluginCache(reload_pages ? true : false);
-}
-
-// Requests a range of bytes for a seekable stream.
-NPError NPN_RequestRead(NPStream* stream, NPByteRange* range_list) {
- return NPERR_GENERIC_ERROR;
-}
-
-NPError NPN_GetURLNotify(NPP id,
- const char* url,
- const char* target,
- void* notify_data) {
- return NPERR_GENERIC_ERROR;
-}
-
-NPError NPN_GetURL(NPP id, const char* url, const char* target) {
- return NPERR_GENERIC_ERROR;
-}
-
-NPError NPN_PostURLNotify(NPP id,
- const char* url,
- const char* target,
- uint32_t len,
- const char* buf,
- NPBool file,
- void* notify_data) {
- return NPERR_GENERIC_ERROR;
-}
-
-NPError NPN_PostURL(NPP id,
- const char* url,
- const char* target,
- uint32_t len,
- const char* buf,
- NPBool file) {
- return NPERR_GENERIC_ERROR;
-}
-
-NPError NPN_NewStream(NPP id,
- NPMIMEType type,
- const char* target,
- NPStream** stream) {
- // Requests creation of a new data stream produced by the plugin,
- // consumed by the browser.
- //
- // Browser should put this stream into a window target.
- //
- // TODO: implement me
- DVLOG(1) << "NPN_NewStream is not implemented yet.";
- return NPERR_GENERIC_ERROR;
-}
-
-int32_t NPN_Write(NPP id, NPStream* stream, int32_t len, void* buffer) {
- // Writes data to an existing Plugin-created stream.
-
- // TODO: implement me
- DVLOG(1) << "NPN_Write is not implemented yet.";
- return NPERR_GENERIC_ERROR;
-}
-
-NPError NPN_DestroyStream(NPP id, NPStream* stream, NPReason reason) {
- // Destroys a stream (could be created by plugin or browser).
- //
- // Reasons:
- // NPRES_DONE - normal completion
- // NPRES_USER_BREAK - user terminated
- // NPRES_NETWORK_ERROR - network error (all errors fit here?)
- //
- //
-
- scoped_refptr<PluginInstance> plugin(FindInstance(id));
- if (plugin.get() == NULL) {
- NOTREACHED();
- return NPERR_GENERIC_ERROR;
- }
-
- return plugin->NPP_DestroyStream(stream, reason);
-}
-
-const char* NPN_UserAgent(NPP id) {
-#if defined(OS_WIN)
- // Flash passes in a null id during the NP_initialize call. We need to
- // default to the Mozilla user agent if we don't have an NPP instance or
- // else Flash won't request windowless mode.
- bool use_mozilla_user_agent = true;
- if (id) {
- scoped_refptr<PluginInstance> plugin = FindInstance(id);
- if (plugin.get() && !plugin->use_mozilla_user_agent())
- use_mozilla_user_agent = false;
- }
-
- if (use_mozilla_user_agent)
- return "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9a1) "
- "Gecko/20061103 Firefox/2.0a1";
-#endif
-
- // Provide a consistent user-agent string with memory that lasts
- // long enough for the caller to read it.
- static base::LazyInstance<std::string>::Leaky leaky_user_agent =
- LAZY_INSTANCE_INITIALIZER;
- if (leaky_user_agent == NULL)
- leaky_user_agent.Get() = content::GetContentClient()->GetUserAgent();
- return leaky_user_agent.Get().c_str();
-}
-
-void NPN_Status(NPP id, const char* message) {
- // Displays a message on the status line of the browser window.
-
- // TODO: implement me
- DVLOG(1) << "NPN_Status is not implemented yet.";
-}
-
-void NPN_InvalidateRect(NPP id, NPRect *invalidRect) {
- // Invalidates specified drawing area prior to repainting or refreshing a
- // windowless plugin
-
- // Before a windowless plugin can refresh part of its drawing area, it must
- // first invalidate it. This function causes the NPP_HandleEvent method to
- // pass an update event or a paint message to the plugin. After calling
- // this method, the plugin receives a paint message asynchronously.
-
- // The browser redraws invalid areas of the document and any windowless
- // plugins at regularly timed intervals. To force a paint message, the
- // plugin can call NPN_ForceRedraw after calling this method.
-
- scoped_refptr<PluginInstance> plugin(FindInstance(id));
- if (plugin.get() && plugin->webplugin()) {
- if (invalidRect) {
-#if defined(OS_WIN)
- if (!plugin->windowless()) {
- RECT rect = {0};
- rect.left = invalidRect->left;
- rect.right = invalidRect->right;
- rect.top = invalidRect->top;
- rect.bottom = invalidRect->bottom;
- ::InvalidateRect(plugin->window_handle(), &rect, false);
- return;
- }
-#endif
- gfx::Rect rect(invalidRect->left,
- invalidRect->top,
- invalidRect->right - invalidRect->left,
- invalidRect->bottom - invalidRect->top);
- plugin->webplugin()->InvalidateRect(rect);
- } else {
- plugin->webplugin()->Invalidate();
- }
- }
-}
-
-void NPN_InvalidateRegion(NPP id, NPRegion invalidRegion) {
- // Invalidates a specified drawing region prior to repainting
- // or refreshing a window-less plugin.
- //
- // Similar to NPN_InvalidateRect.
-
- // TODO: this is overkill--add platform-specific region handling (at the
- // very least, fetch the region's bounding box and pass it to InvalidateRect).
- scoped_refptr<PluginInstance> plugin(FindInstance(id));
- DCHECK(plugin.get() != NULL);
- if (plugin.get() && plugin->webplugin())
- plugin->webplugin()->Invalidate();
-}
-
-void NPN_ForceRedraw(NPP id) {
- // Forces repaint for a windowless plugin.
- //
- // We deliberately do not implement this; we don't want plugins forcing
- // synchronous paints.
-}
-
-NPError NPN_GetValue(NPP id, NPNVariable variable, void* value) {
- // Allows the plugin to query the browser for information
- //
- // Variables:
- // NPNVxDisplay (unix only)
- // NPNVxtAppContext (unix only)
- // NPNVnetscapeWindow (win only) - Gets the native window on which the
- // plugin drawing occurs, returns HWND
- // NPNVjavascriptEnabledBool: tells whether Javascript is enabled
- // NPNVasdEnabledBool: tells whether SmartUpdate is enabled
- // NPNVOfflineBool: tells whether offline-mode is enabled
-
- NPError rv = NPERR_GENERIC_ERROR;
-
- switch (static_cast<int>(variable)) {
- case NPNVWindowNPObject: {
- scoped_refptr<PluginInstance> plugin(FindInstance(id));
- if (!plugin.get()) {
- NOTREACHED();
- return NPERR_INVALID_INSTANCE_ERROR;
- }
- NPObject *np_object = plugin->webplugin()->GetWindowScriptNPObject();
- // Return value is expected to be retained, as
- // described here:
- // <http://www.mozilla.org/projects/plugins/npruntime.html#browseraccess>
- if (np_object) {
- WebBindings::retainObject(np_object);
- void **v = (void **)value;
- *v = np_object;
- rv = NPERR_NO_ERROR;
- } else {
- NOTREACHED();
- }
- break;
- }
- case NPNVPluginElementNPObject: {
- scoped_refptr<PluginInstance> plugin(FindInstance(id));
- if (!plugin.get()) {
- NOTREACHED();
- return NPERR_INVALID_INSTANCE_ERROR;
- }
- NPObject *np_object = plugin->webplugin()->GetPluginElement();
- // Return value is expected to be retained, as
- // described here:
- // <http://www.mozilla.org/projects/plugins/npruntime.html#browseraccess>
- if (np_object) {
- WebBindings::retainObject(np_object);
- void** v = static_cast<void**>(value);
- *v = np_object;
- rv = NPERR_NO_ERROR;
- } else {
- NOTREACHED();
- }
- break;
- }
- #if !defined(OS_MACOSX) // OS X doesn't have windowed plugins.
- case NPNVnetscapeWindow: {
- scoped_refptr<PluginInstance> plugin = FindInstance(id);
- if (!plugin.get()) {
- NOTREACHED();
- return NPERR_INVALID_INSTANCE_ERROR;
- }
- gfx::PluginWindowHandle handle = plugin->window_handle();
- *((void**)value) = (void*)handle;
- rv = NPERR_NO_ERROR;
- break;
- }
- #endif
- case NPNVjavascriptEnabledBool: {
- // yes, JS is enabled.
- *((void**)value) = (void*)1;
- rv = NPERR_NO_ERROR;
- break;
- }
- case NPNVSupportsWindowless: {
- NPBool* supports_windowless = reinterpret_cast<NPBool*>(value);
- *supports_windowless = true;
- rv = NPERR_NO_ERROR;
- break;
- }
- case NPNVprivateModeBool: {
- NPBool* private_mode = reinterpret_cast<NPBool*>(value);
- scoped_refptr<PluginInstance> plugin(FindInstance(id));
- if (!plugin.get()) {
- NOTREACHED();
- return NPERR_INVALID_INSTANCE_ERROR;
- }
- *private_mode = plugin->webplugin()->IsOffTheRecord();
- rv = NPERR_NO_ERROR;
- break;
- }
- #if defined(OS_MACOSX)
- case NPNVpluginDrawingModel: {
- // return the drawing model that was negotiated when we initialized.
- scoped_refptr<PluginInstance> plugin(FindInstance(id));
- if (!plugin.get()) {
- NOTREACHED();
- return NPERR_INVALID_INSTANCE_ERROR;
- }
- *reinterpret_cast<int*>(value) = plugin->drawing_model();
- rv = NPERR_NO_ERROR;
- break;
- }
- case NPNVsupportsCoreGraphicsBool:
- case NPNVsupportsCocoaBool: {
- // These drawing and event models are always supported.
- NPBool* supports_model = reinterpret_cast<NPBool*>(value);
- *supports_model = true;
- rv = NPERR_NO_ERROR;
- break;
- }
- case NPNVsupportsInvalidatingCoreAnimationBool:
- case NPNVsupportsCoreAnimationBool: {
- NPBool* supports_model = reinterpret_cast<NPBool*>(value);
- *supports_model = content::SupportsCoreAnimationPlugins();
- rv = NPERR_NO_ERROR;
- break;
- }
-#ifndef NP_NO_CARBON
- case NPNVsupportsCarbonBool:
-#endif
-#ifndef NP_NO_QUICKDRAW
- case NPNVsupportsQuickDrawBool:
-#endif
- case NPNVsupportsOpenGLBool: {
- // These models are never supported. OpenGL was never widely supported,
- // and QuickDraw and Carbon have been deprecated for quite some time.
- NPBool* supports_model = reinterpret_cast<NPBool*>(value);
- *supports_model = false;
- rv = NPERR_NO_ERROR;
- break;
- }
- case NPNVsupportsCompositingCoreAnimationPluginsBool: {
- NPBool* supports_compositing = reinterpret_cast<NPBool*>(value);
- *supports_compositing = content::SupportsCoreAnimationPlugins();
- rv = NPERR_NO_ERROR;
- break;
- }
- case NPNVsupportsUpdatedCocoaTextInputBool: {
- // We support the clarifications to the Cocoa IME event spec.
- NPBool* supports_update = reinterpret_cast<NPBool*>(value);
- *supports_update = true;
- rv = NPERR_NO_ERROR;
- break;
- }
- #endif // OS_MACOSX
- default:
- DVLOG(1) << "NPN_GetValue(" << variable << ") is not implemented yet.";
- break;
- }
- return rv;
-}
-
-NPError NPN_SetValue(NPP id, NPPVariable variable, void* value) {
- // Allows the plugin to set various modes
-
- scoped_refptr<PluginInstance> plugin(FindInstance(id));
- if (!plugin.get()) {
- NOTREACHED();
- return NPERR_INVALID_INSTANCE_ERROR;
- }
- switch(variable) {
- case NPPVpluginWindowBool: {
- // Sets windowless mode for display of the plugin
- // Note: the documentation at
- // http://developer.mozilla.org/en/docs/NPN_SetValue is wrong. When
- // value is NULL, the mode is set to true. This is the same way Mozilla
- // works.
- plugin->set_windowless(value == 0);
- return NPERR_NO_ERROR;
- }
- case NPPVpluginTransparentBool: {
- // Sets transparent mode for display of the plugin
- //
- // Transparent plugins require the browser to paint the background
- // before having the plugin paint. By default, windowless plugins
- // are transparent. Making a windowless plugin opaque means that
- // the plugin does not require the browser to paint the background.
- bool mode = (value != 0);
- plugin->set_transparent(mode);
- return NPERR_NO_ERROR;
- }
- case NPPVjavascriptPushCallerBool:
- // Specifies whether you are pushing or popping the JSContext off.
- // the stack
- // TODO: implement me
- DVLOG(1) << "NPN_SetValue(NPPVJavascriptPushCallerBool) is not "
- "implemented.";
- return NPERR_GENERIC_ERROR;
- case NPPVpluginKeepLibraryInMemory:
- // Tells browser that plugin library should live longer than usual.
- // TODO: implement me
- DVLOG(1) << "NPN_SetValue(NPPVpluginKeepLibraryInMemory) is not "
- "implemented.";
- return NPERR_GENERIC_ERROR;
- #if defined(OS_MACOSX)
- case NPPVpluginDrawingModel: {
- intptr_t model = reinterpret_cast<intptr_t>(value);
- if (model == NPDrawingModelCoreGraphics ||
- ((model == NPDrawingModelInvalidatingCoreAnimation ||
- model == NPDrawingModelCoreAnimation) &&
- content::SupportsCoreAnimationPlugins())) {
- plugin->set_drawing_model(static_cast<NPDrawingModel>(model));
- return NPERR_NO_ERROR;
- }
- return NPERR_GENERIC_ERROR;
- }
- case NPPVpluginEventModel: {
- // Only the Cocoa event model is supported.
- intptr_t model = reinterpret_cast<intptr_t>(value);
- if (model == NPEventModelCocoa) {
- plugin->set_event_model(static_cast<NPEventModel>(model));
- return NPERR_NO_ERROR;
- }
- return NPERR_GENERIC_ERROR;
- }
- #endif
- default:
- // TODO: implement me
- DVLOG(1) << "NPN_SetValue(" << variable << ") is not implemented.";
- break;
- }
-
- NOTREACHED();
- return NPERR_GENERIC_ERROR;
-}
-
-void* NPN_GetJavaEnv() {
- // TODO: implement me
- DVLOG(1) << "NPN_GetJavaEnv is not implemented.";
- return NULL;
-}
-
-void* NPN_GetJavaPeer(NPP) {
- // TODO: implement me
- DVLOG(1) << "NPN_GetJavaPeer is not implemented.";
- return NULL;
-}
-
-void NPN_PushPopupsEnabledState(NPP id, NPBool enabled) {
- scoped_refptr<PluginInstance> plugin(FindInstance(id));
- if (plugin.get())
- plugin->PushPopupsEnabledState(enabled ? true : false);
-}
-
-void NPN_PopPopupsEnabledState(NPP id) {
- scoped_refptr<PluginInstance> plugin(FindInstance(id));
- if (plugin.get())
- plugin->PopPopupsEnabledState();
-}
-
-void NPN_PluginThreadAsyncCall(NPP id,
- void (*func)(void*),
- void* user_data) {
- scoped_refptr<PluginInstance> plugin(FindInstance(id));
- if (plugin.get())
- plugin->PluginThreadAsyncCall(func, user_data);
-}
-
-NPError NPN_GetValueForURL(NPP id,
- NPNURLVariable variable,
- const char* url,
- char** value,
- uint32_t* len) {
- if (!id)
- return NPERR_INVALID_PARAM;
-
- if (!url || !*url || !len)
- return NPERR_INVALID_URL;
-
- *len = 0;
- std::string result;
-
- switch (variable) {
- case NPNURLVProxy: {
- result = "DIRECT";
- scoped_refptr<PluginInstance> plugin(FindInstance(id));
- if (!plugin.get())
- return NPERR_GENERIC_ERROR;
-
- WebPlugin* webplugin = plugin->webplugin();
- if (!webplugin)
- return NPERR_GENERIC_ERROR;
-
- if (!webplugin->FindProxyForUrl(GURL(std::string(url)), &result))
- return NPERR_GENERIC_ERROR;
- break;
- }
- case NPNURLVCookie: {
- scoped_refptr<PluginInstance> plugin(FindInstance(id));
- if (!plugin.get())
- return NPERR_GENERIC_ERROR;
-
- WebPlugin* webplugin = plugin->webplugin();
- if (!webplugin)
- return NPERR_GENERIC_ERROR;
-
- // Bypass third-party cookie blocking by using the url as the
- // first_party_for_cookies.
- GURL cookies_url((std::string(url)));
- result = webplugin->GetCookies(cookies_url, cookies_url);
- break;
- }
- default:
- return NPERR_GENERIC_ERROR;
- }
-
- // Allocate this using the NPAPI allocator. The plugin will call
- // NPN_Free to free this.
- *value = static_cast<char*>(NPN_MemAlloc(result.length() + 1));
- base::strlcpy(*value, result.c_str(), result.length() + 1);
- *len = result.length();
-
- return NPERR_NO_ERROR;
-}
-
-NPError NPN_SetValueForURL(NPP id,
- NPNURLVariable variable,
- const char* url,
- const char* value,
- uint32_t len) {
- if (!id)
- return NPERR_INVALID_PARAM;
-
- if (!url || !*url)
- return NPERR_INVALID_URL;
-
- switch (variable) {
- case NPNURLVCookie: {
- scoped_refptr<PluginInstance> plugin(FindInstance(id));
- if (!plugin.get())
- return NPERR_GENERIC_ERROR;
-
- WebPlugin* webplugin = plugin->webplugin();
- if (!webplugin)
- return NPERR_GENERIC_ERROR;
-
- std::string cookie(value, len);
- GURL cookies_url((std::string(url)));
- webplugin->SetCookie(cookies_url, cookies_url, cookie);
- return NPERR_NO_ERROR;
- }
- case NPNURLVProxy:
- // We don't support setting proxy values, fall through...
- break;
- default:
- // Fall through and return an error...
- break;
- }
-
- return NPERR_GENERIC_ERROR;
-}
-
-NPError NPN_GetAuthenticationInfo(NPP id,
- const char* protocol,
- const char* host,
- int32_t port,
- const char* scheme,
- const char* realm,
- char** username,
- uint32_t* ulen,
- char** password,
- uint32_t* plen) {
- if (!id || !protocol || !host || !scheme || !realm || !username ||
- !ulen || !password || !plen)
- return NPERR_INVALID_PARAM;
-
- // TODO: implement me (bug 23928)
- return NPERR_GENERIC_ERROR;
-}
-
-uint32_t NPN_ScheduleTimer(NPP id,
- uint32_t interval,
- NPBool repeat,
- void (*func)(NPP id, uint32_t timer_id)) {
- scoped_refptr<PluginInstance> plugin(FindInstance(id));
- if (!plugin.get())
- return 0;
-
- return plugin->ScheduleTimer(interval, repeat, func);
-}
-
-void NPN_UnscheduleTimer(NPP id, uint32_t timer_id) {
- scoped_refptr<PluginInstance> plugin(FindInstance(id));
- if (plugin.get())
- plugin->UnscheduleTimer(timer_id);
-}
-
-NPError NPN_PopUpContextMenu(NPP id, NPMenu* menu) {
- if (!menu)
- return NPERR_INVALID_PARAM;
-
- scoped_refptr<PluginInstance> plugin(FindInstance(id));
- if (plugin.get()) {
- return plugin->PopUpContextMenu(menu);
- }
- NOTREACHED();
- return NPERR_GENERIC_ERROR;
-}
-
-NPBool NPN_ConvertPoint(NPP id, double sourceX, double sourceY,
- NPCoordinateSpace sourceSpace,
- double *destX, double *destY,
- NPCoordinateSpace destSpace) {
- scoped_refptr<PluginInstance> plugin(FindInstance(id));
- if (plugin.get()) {
- return plugin->ConvertPoint(
- sourceX, sourceY, sourceSpace, destX, destY, destSpace);
- }
- NOTREACHED();
- return false;
-}
-
-NPBool NPN_HandleEvent(NPP id, void *event, NPBool handled) {
- // TODO: Implement advanced key handling: http://crbug.com/46578
- NOTIMPLEMENTED();
- return false;
-}
-
-NPBool NPN_UnfocusInstance(NPP id, NPFocusDirection direction) {
- // TODO: Implement advanced key handling: http://crbug.com/46578
- NOTIMPLEMENTED();
- return false;
-}
-
-void NPN_URLRedirectResponse(NPP instance, void* notify_data, NPBool allow) {
-}
-
-} // extern "C"
diff --git a/chromium/content/child/npapi/plugin_host.h b/chromium/content/child/npapi/plugin_host.h
deleted file mode 100644
index 5db27e85415..00000000000
--- a/chromium/content/child/npapi/plugin_host.h
+++ /dev/null
@@ -1,63 +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.
-
-// TODO: Need mechanism to cleanup the static instance
-
-#ifndef CONTENT_CHILD_NPAPI_PLUGIN_HOST_H_
-#define CONTENT_CHILD_NPAPI_PLUGIN_HOST_H_
-
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "third_party/npapi/bindings/npapi.h"
-#include "third_party/npapi/bindings/nphostapi.h"
-
-namespace content {
-
-// The Plugin Host implements the NPN_xxx functions for NPAPI plugins.
-// These are the functions exposed from the Plugin Host for use
-// by the Plugin.
-//
-// The PluginHost is managed as a singleton. This isn't strictly
-// necessary, but since the callback functions are all global C
-// functions, there is really no point in having per-instance PluginHosts.
-class PluginHost : public base::RefCounted<PluginHost> {
- public:
- // Access the single PluginHost instance. Callers
- // must call deref() when finished with the object.
- static PluginHost* Singleton();
-
- // The table of functions provided to the plugin.
- NPNetscapeFuncs* host_functions() { return &host_funcs_; }
-
- // Helper function for parsing post headers, and applying attributes
- // to the stream. NPAPI post data include headers + data combined.
- // This function parses it out and adds it to the stream in a WebKit
- // style.
- static bool SetPostData(const char* buf,
- uint32_t length,
- std::vector<std::string>* names,
- std::vector<std::string>* values,
- std::vector<char>* body);
-
- void PatchNPNetscapeFuncs(NPNetscapeFuncs* overrides);
-
- private:
- friend class base::RefCounted<PluginHost>;
-
- virtual ~PluginHost();
-
- PluginHost();
- void InitializeHostFuncs();
- NPNetscapeFuncs host_funcs_;
- DISALLOW_COPY_AND_ASSIGN(PluginHost);
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_NPAPI_PLUGIN_HOST_H_
diff --git a/chromium/content/child/npapi/plugin_instance.cc b/chromium/content/child/npapi/plugin_instance.cc
deleted file mode 100644
index d353196d7f9..00000000000
--- a/chromium/content/child/npapi/plugin_instance.cc
+++ /dev/null
@@ -1,430 +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/child/npapi/plugin_instance.h"
-
-#include <string.h>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/location.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/thread_task_runner_handle.h"
-#include "build/build_config.h"
-#include "content/child/npapi/plugin_host.h"
-#include "content/child/npapi/plugin_lib.h"
-#include "content/child/npapi/webplugin.h"
-#include "content/child/npapi/webplugin_delegate.h"
-#include "content/child/npapi/webplugin_resource_client.h"
-#include "content/public/common/content_constants.h"
-#include "content/public/common/content_switches.h"
-#include "net/base/escape.h"
-
-#if defined(OS_MACOSX)
-#include <ApplicationServices/ApplicationServices.h>
-#endif
-
-namespace content {
-
-PluginInstance::PluginInstance(PluginLib* plugin, const std::string& mime_type)
- : plugin_(plugin),
- npp_(0),
- host_(PluginHost::Singleton()),
- npp_functions_(plugin->functions()),
- window_handle_(0),
- windowless_(false),
- transparent_(true),
- webplugin_(0),
- mime_type_(mime_type),
- use_mozilla_user_agent_(false),
-#if defined (OS_MACOSX)
-#ifdef NP_NO_QUICKDRAW
- drawing_model_(NPDrawingModelCoreGraphics),
-#else
- drawing_model_(NPDrawingModelQuickDraw),
-#endif
-#ifdef NP_NO_CARBON
- event_model_(NPEventModelCocoa),
-#else
- event_model_(NPEventModelCarbon),
-#endif
- currently_handled_event_(NULL),
-#endif
- task_runner_(base::ThreadTaskRunnerHandle::Get()),
- load_manually_(false),
- next_timer_id_(1) {
- npp_ = new NPP_t();
- npp_->ndata = 0;
- npp_->pdata = 0;
-
- if (mime_type_ == kFlashPluginSwfMimeType)
- transparent_ = false;
-
- memset(&zero_padding_, 0, sizeof(zero_padding_));
-}
-
-PluginInstance::~PluginInstance() {
- if (npp_ != 0) {
- delete npp_;
- npp_ = 0;
- }
-
- if (plugin_.get())
- plugin_->CloseInstance();
-}
-
-bool PluginInstance::Start(const GURL& url,
- char** const param_names,
- char** const param_values,
- int param_count,
- bool load_manually) {
- load_manually_ = load_manually;
- unsigned short mode = load_manually_ ? NP_FULL : NP_EMBED;
- npp_->ndata = this;
-
- NPError err = NPP_New(mode, param_count,
- const_cast<char **>(param_names), const_cast<char **>(param_values));
- return err == NPERR_NO_ERROR;
-}
-
-NPObject *PluginInstance::GetPluginScriptableObject() {
- NPObject *value = NULL;
- NPError error = NPP_GetValue(NPPVpluginScriptableNPObject, &value);
- if (error != NPERR_NO_ERROR || value == NULL)
- return NULL;
- return value;
-}
-
-bool PluginInstance::GetFormValue(base::string16* value) {
- // Plugins will allocate memory for the return value by using NPN_MemAlloc().
- char *plugin_value = NULL;
- NPError error = NPP_GetValue(NPPVformValue, &plugin_value);
- if (error != NPERR_NO_ERROR || !plugin_value) {
- return false;
- }
- // Assumes the result is UTF8 text, as Firefox does.
- *value = base::UTF8ToUTF16(plugin_value);
- host_->host_functions()->memfree(plugin_value);
- return true;
-}
-
-unsigned PluginInstance::GetBackingTextureId() {
- // By default the plugin instance is not backed by an OpenGL texture.
- return 0;
-}
-
-// NPAPI methods
-NPError PluginInstance::NPP_New(unsigned short mode,
- short argc,
- char* argn[],
- char* argv[]) {
- DCHECK(npp_functions_ != 0);
- DCHECK(npp_functions_->newp != 0);
- DCHECK(argc >= 0);
-
- if (npp_functions_->newp != 0) {
- return npp_functions_->newp(
- (NPMIMEType)mime_type_.c_str(), npp_, mode, argc, argn, argv, NULL);
- }
- return NPERR_INVALID_FUNCTABLE_ERROR;
-}
-
-void PluginInstance::NPP_Destroy() {
- DCHECK(npp_functions_ != 0);
- DCHECK(npp_functions_->destroy != 0);
-
- if (npp_functions_->destroy != 0) {
- NPSavedData *savedData = 0;
- npp_functions_->destroy(npp_, &savedData);
-
- // TODO: Support savedData. Technically, these need to be
- // saved on a per-URL basis, and then only passed
- // to new instances of the plugin at the same URL.
- // Sounds like a huge security risk. When we do support
- // these, we should pass them back to the PluginLib
- // to be stored there.
- DCHECK(savedData == 0);
- }
-
- for (unsigned int file_index = 0; file_index < files_created_.size();
- file_index++) {
- base::DeleteFile(files_created_[file_index], false);
- }
-
- // Ensure that no timer callbacks are invoked after NPP_Destroy.
- timers_.clear();
-}
-
-NPError PluginInstance::NPP_SetWindow(NPWindow* window) {
- DCHECK(npp_functions_ != 0);
- DCHECK(npp_functions_->setwindow != 0);
-
- if (npp_functions_->setwindow != 0) {
- return npp_functions_->setwindow(npp_, window);
- }
- return NPERR_INVALID_FUNCTABLE_ERROR;
-}
-
-NPError PluginInstance::NPP_NewStream(NPMIMEType type,
- NPStream* stream,
- NPBool seekable,
- unsigned short* stype) {
- DCHECK(npp_functions_ != 0);
- DCHECK(npp_functions_->newstream != 0);
- if (npp_functions_->newstream != 0) {
- return npp_functions_->newstream(npp_, type, stream, seekable, stype);
- }
- return NPERR_INVALID_FUNCTABLE_ERROR;
-}
-
-NPError PluginInstance::NPP_DestroyStream(NPStream* stream, NPReason reason) {
- DCHECK(npp_functions_ != 0);
- DCHECK(npp_functions_->destroystream != 0);
-
- if (stream == NULL || (stream->ndata == NULL))
- return NPERR_INVALID_INSTANCE_ERROR;
-
- if (npp_functions_->destroystream != 0) {
- NPError result = npp_functions_->destroystream(npp_, stream, reason);
- stream->ndata = NULL;
- return result;
- }
- return NPERR_INVALID_FUNCTABLE_ERROR;
-}
-
-int PluginInstance::NPP_WriteReady(NPStream* stream) {
- DCHECK(npp_functions_ != 0);
- DCHECK(npp_functions_->writeready != 0);
- if (npp_functions_->writeready != 0) {
- return npp_functions_->writeready(npp_, stream);
- }
- return 0;
-}
-
-int PluginInstance::NPP_Write(NPStream* stream,
- int offset,
- int len,
- void* buffer) {
- DCHECK(npp_functions_ != 0);
- DCHECK(npp_functions_->write != 0);
- if (npp_functions_->write != 0) {
- return npp_functions_->write(npp_, stream, offset, len, buffer);
- }
- return 0;
-}
-
-void PluginInstance::NPP_StreamAsFile(NPStream* stream, const char* fname) {
- DCHECK(npp_functions_ != 0);
- DCHECK(npp_functions_->asfile != 0);
- if (npp_functions_->asfile != 0) {
- npp_functions_->asfile(npp_, stream, fname);
- }
-
- // Creating a temporary FilePath instance on the stack as the explicit
- // FilePath constructor with StringType as an argument causes a compiler
- // error when invoked via vector push back.
- base::FilePath file_name = base::FilePath::FromUTF8Unsafe(fname);
- files_created_.push_back(file_name);
-}
-
-NPError PluginInstance::NPP_GetValue(NPPVariable variable, void* value) {
- DCHECK(npp_functions_ != 0);
- // getvalue is NULL for Shockwave
- if (npp_functions_->getvalue != 0) {
- return npp_functions_->getvalue(npp_, variable, value);
- }
- return NPERR_INVALID_FUNCTABLE_ERROR;
-}
-
-NPError PluginInstance::NPP_SetValue(NPNVariable variable, void* value) {
- DCHECK(npp_functions_ != 0);
- if (npp_functions_->setvalue != 0) {
- return npp_functions_->setvalue(npp_, variable, value);
- }
- return NPERR_INVALID_FUNCTABLE_ERROR;
-}
-
-short PluginInstance::NPP_HandleEvent(void* event) {
- DCHECK(npp_functions_ != 0);
- DCHECK(npp_functions_->event != 0);
- if (npp_functions_->event != 0) {
- return npp_functions_->event(npp_, (void*)event);
- }
- return false;
-}
-
-bool PluginInstance::NPP_Print(NPPrint* platform_print) {
- DCHECK(npp_functions_ != 0);
- if (npp_functions_->print != 0) {
- npp_functions_->print(npp_, platform_print);
- return true;
- }
- return false;
-}
-
-
-void PluginInstance::PluginThreadAsyncCall(void (*func)(void*),
- void* user_data) {
- task_runner_->PostTask(
- FROM_HERE, base::Bind(&PluginInstance::OnPluginThreadAsyncCall, this,
- func, user_data));
-}
-
-void PluginInstance::OnPluginThreadAsyncCall(void (*func)(void*),
- void* user_data) {
- // Do not invoke the callback if NPP_Destroy has already been invoked.
- if (webplugin_)
- func(user_data);
-}
-
-uint32_t PluginInstance::ScheduleTimer(uint32_t interval,
- NPBool repeat,
- void (*func)(NPP id,
- uint32_t timer_id)) {
- // Use next timer id.
- uint32_t timer_id;
- timer_id = next_timer_id_;
- ++next_timer_id_;
- DCHECK(next_timer_id_ != 0);
-
- // Record timer interval and repeat.
- TimerInfo info;
- info.interval = interval;
- info.repeat = repeat ? true : false;
- timers_[timer_id] = info;
-
- // Schedule the callback.
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&PluginInstance::OnTimerCall, this, func, npp_, timer_id),
- base::TimeDelta::FromMilliseconds(interval));
- return timer_id;
-}
-
-void PluginInstance::UnscheduleTimer(uint32_t timer_id) {
- // Remove info about the timer.
- TimerMap::iterator it = timers_.find(timer_id);
- if (it != timers_.end())
- timers_.erase(it);
-}
-
-#if !defined(OS_MACOSX)
-NPError PluginInstance::PopUpContextMenu(NPMenu* menu) {
- NOTIMPLEMENTED();
- return NPERR_GENERIC_ERROR;
-}
-#endif
-
-void PluginInstance::OnTimerCall(void (*func)(NPP id, uint32_t timer_id),
- NPP id,
- uint32_t timer_id) {
- // Do not invoke callback if the timer has been unscheduled.
- TimerMap::iterator it = timers_.find(timer_id);
- if (it == timers_.end())
- return;
-
- // Get all information about the timer before invoking the callback. The
- // callback might unschedule the timer.
- TimerInfo info = it->second;
-
- func(id, timer_id);
-
- // If the timer was unscheduled by the callback, just free up the timer id.
- if (timers_.find(timer_id) == timers_.end())
- return;
-
- // Reschedule repeating timers after invoking the callback so callback is not
- // re-entered if it pumps the message loop.
- if (info.repeat) {
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&PluginInstance::OnTimerCall, this, func, npp_, timer_id),
- base::TimeDelta::FromMilliseconds(info.interval));
- } else {
- timers_.erase(it);
- }
-}
-
-void PluginInstance::PushPopupsEnabledState(bool enabled) {
- popups_enabled_stack_.push(enabled);
-}
-
-void PluginInstance::PopPopupsEnabledState() {
- popups_enabled_stack_.pop();
-}
-
-bool PluginInstance::ConvertPoint(double source_x, double source_y,
- NPCoordinateSpace source_space,
- double* dest_x, double* dest_y,
- NPCoordinateSpace dest_space) {
-#if defined(OS_MACOSX)
- CGRect main_display_bounds = CGDisplayBounds(CGMainDisplayID());
-
- double flipped_screen_x = source_x;
- double flipped_screen_y = source_y;
- switch(source_space) {
- case NPCoordinateSpacePlugin:
- flipped_screen_x += plugin_origin_.x();
- flipped_screen_y += plugin_origin_.y();
- break;
- case NPCoordinateSpaceWindow:
- flipped_screen_x += containing_window_frame_.x();
- flipped_screen_y = containing_window_frame_.height() - source_y +
- containing_window_frame_.y();
- break;
- case NPCoordinateSpaceFlippedWindow:
- flipped_screen_x += containing_window_frame_.x();
- flipped_screen_y += containing_window_frame_.y();
- break;
- case NPCoordinateSpaceScreen:
- flipped_screen_y = main_display_bounds.size.height - flipped_screen_y;
- break;
- case NPCoordinateSpaceFlippedScreen:
- break;
- default:
- NOTREACHED();
- return false;
- }
-
- double target_x = flipped_screen_x;
- double target_y = flipped_screen_y;
- switch(dest_space) {
- case NPCoordinateSpacePlugin:
- target_x -= plugin_origin_.x();
- target_y -= plugin_origin_.y();
- break;
- case NPCoordinateSpaceWindow:
- target_x -= containing_window_frame_.x();
- target_y -= containing_window_frame_.y();
- target_y = containing_window_frame_.height() - target_y;
- break;
- case NPCoordinateSpaceFlippedWindow:
- target_x -= containing_window_frame_.x();
- target_y -= containing_window_frame_.y();
- break;
- case NPCoordinateSpaceScreen:
- target_y = main_display_bounds.size.height - flipped_screen_y;
- break;
- case NPCoordinateSpaceFlippedScreen:
- break;
- default:
- NOTREACHED();
- return false;
- }
-
- if (dest_x)
- *dest_x = target_x;
- if (dest_y)
- *dest_y = target_y;
- return true;
-#else
- NOTIMPLEMENTED();
- return false;
-#endif
-}
-
-} // namespace content
diff --git a/chromium/content/child/npapi/plugin_instance.h b/chromium/content/child/npapi/plugin_instance.h
deleted file mode 100644
index 2cf931e36e9..00000000000
--- a/chromium/content/child/npapi/plugin_instance.h
+++ /dev/null
@@ -1,293 +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.
-
-// TODO: Need to deal with NPAPI's NPSavedData.
-// I haven't seen plugins use it yet.
-
-#ifndef CONTENT_CHILD_NPAPI_PLUGIN_INSTANCE_H_
-#define CONTENT_CHILD_NPAPI_PLUGIN_INSTANCE_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <stack>
-#include <string>
-#include <vector>
-
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "build/build_config.h"
-#include "third_party/npapi/bindings/npapi.h"
-#include "third_party/npapi/bindings/nphostapi.h"
-#include "ui/gfx/geometry/point.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/native_widget_types.h"
-#include "url/gurl.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}
-
-namespace content {
-
-class PluginLib;
-class PluginHost;
-class WebPlugin;
-class WebPluginResourceClient;
-
-#if defined(OS_MACOSX)
-class ScopedCurrentPluginEvent;
-#endif
-
-// A PluginInstance is an active, running instance of a Plugin.
-// A single plugin may have many PluginInstances.
-class PluginInstance : public base::RefCountedThreadSafe<PluginInstance> {
- public:
- // Create a new instance of a plugin. The PluginInstance
- // will hold a reference to the plugin.
- PluginInstance(PluginLib* plugin, const std::string &mime_type);
-
- // Activates the instance by calling NPP_New.
- // This should be called after our instance is all
- // setup from the host side and we are ready to receive
- // requests from the plugin. We must not call any
- // functions on the plugin instance until start has
- // been called.
- //
- // url: The instance URL.
- // param_names: the list of names of attributes passed via the
- // element.
- // param_values: the list of values corresponding to param_names
- // param_count: number of attributes
- // load_manually: if true indicates that the plugin data would be passed
- // from webkit. if false indicates that the plugin should
- // download the data.
- // This also controls whether the plugin is instantiated as
- // a full page plugin (NP_FULL) or embedded (NP_EMBED)
- //
- bool Start(const GURL& url,
- char** const param_names,
- char** const param_values,
- int param_count,
- bool load_manually);
-
- // NPAPI's instance identifier for this instance
- NPP npp() { return npp_; }
-
- // Get/Set for the instance's window handle.
- gfx::PluginWindowHandle window_handle() const { return window_handle_; }
- void set_window_handle(gfx::PluginWindowHandle value) {
- window_handle_ = value;
- }
-
- // Get/Set whether this instance is in Windowless mode.
- // Default is false.
- bool windowless() { return windowless_; }
- void set_windowless(bool value) { windowless_ = value; }
-
- // Get/Set whether this instance is transparent. This only applies to
- // windowless plugins. Transparent plugins require that webkit paint the
- // background.
- // Default is true for all plugins other than Flash. For Flash, we default to
- // opaque since it always tells us if it's transparent during NPP_New.
- bool transparent() { return transparent_; }
- void set_transparent(bool value) { transparent_ = value; }
-
- // Get/Set the WebPlugin associated with this instance
- WebPlugin* webplugin() { return webplugin_; }
- void set_web_plugin(WebPlugin* webplugin) {
- webplugin_ = webplugin;
- }
-
- // Get the mimeType for this plugin stream
- const std::string &mime_type() { return mime_type_; }
-
- PluginLib* plugin_lib() { return plugin_.get(); }
-
-#if defined(OS_MACOSX)
- // Get/Set the Mac NPAPI drawing and event models
- NPDrawingModel drawing_model() { return drawing_model_; }
- void set_drawing_model(NPDrawingModel value) { drawing_model_ = value; }
- NPEventModel event_model() { return event_model_; }
- void set_event_model(NPEventModel value) { event_model_ = value; }
- // Updates the instance's tracking of the location of the plugin location
- // relative to the upper left of the screen.
- void set_plugin_origin(const gfx::Point& origin) { plugin_origin_ = origin; }
- // Updates the instance's tracking of the frame of the containing window
- // relative to the upper left of the screen.
- void set_window_frame(const gfx::Rect& frame) {
- containing_window_frame_ = frame;
- }
-#endif
-
- // Returns the WebPluginResourceClient object for a stream that has become
- // seekable.
- WebPluginResourceClient* GetRangeRequest(int id);
-
- // Have the plugin create its script object.
- NPObject* GetPluginScriptableObject();
-
- // Returns the form value of this instance.
- bool GetFormValue(base::string16* value);
-
- // If true, send the Mozilla user agent instead of Chrome's to the plugin.
- bool use_mozilla_user_agent() { return use_mozilla_user_agent_; }
- void set_use_mozilla_user_agent() { use_mozilla_user_agent_ = true; }
-
- // If the plugin instance is backed by a texture, return its ID in the
- // compositor's namespace. Otherwise return 0. Returns 0 by default.
- unsigned GetBackingTextureId();
-
- // Helper that implements NPN_PluginThreadAsyncCall semantics
- void PluginThreadAsyncCall(void (*func)(void *),
- void* userData);
-
- uint32_t ScheduleTimer(uint32_t interval,
- NPBool repeat,
- void (*func)(NPP id, uint32_t timer_id));
-
- void UnscheduleTimer(uint32_t timer_id);
-
- bool ConvertPoint(double source_x, double source_y,
- NPCoordinateSpace source_space,
- double* dest_x, double* dest_y,
- NPCoordinateSpace dest_space);
-
- NPError PopUpContextMenu(NPMenu* menu);
-
- //
- // NPAPI methods for calling the Plugin Instance
- //
- NPError NPP_New(unsigned short, short, char *[], char *[]);
- NPError NPP_SetWindow(NPWindow*);
- NPError NPP_NewStream(NPMIMEType, NPStream*, NPBool, unsigned short*);
- NPError NPP_DestroyStream(NPStream*, NPReason);
- int NPP_WriteReady(NPStream*);
- int NPP_Write(NPStream*, int, int, void*);
- void NPP_StreamAsFile(NPStream*, const char*);
- void NPP_URLNotify(const char*, NPReason, void*);
- NPError NPP_GetValue(NPPVariable, void*);
- NPError NPP_SetValue(NPNVariable, void*);
- short NPP_HandleEvent(void*);
- void NPP_Destroy();
- bool NPP_Print(NPPrint* platform_print);
- void NPP_URLRedirectNotify(const char* url, int32_t status,
- void* notify_data);
-
- void SendJavaScriptStream(const GURL& url,
- const std::string& result,
- bool success);
-
- void PushPopupsEnabledState(bool enabled);
- void PopPopupsEnabledState();
-
- bool popups_allowed() const {
- return popups_enabled_stack_.empty() ? false : popups_enabled_stack_.top();
- }
-
- private:
- friend class base::RefCountedThreadSafe<PluginInstance>;
-
-#if defined(OS_MACOSX)
- friend class ScopedCurrentPluginEvent;
- // Sets the event that the plugin is currently handling. The object is not
- // owned or copied, so the caller must call this again with NULL before the
- // event pointer becomes invalid. Clients use ScopedCurrentPluginEvent rather
- // than calling this directly.
- void set_currently_handled_event(NPCocoaEvent* event) {
- currently_handled_event_ = event;
- }
-#endif
-
- ~PluginInstance();
- void OnPluginThreadAsyncCall(void (*func)(void *), void* userData);
- void OnTimerCall(void (*func)(NPP id, uint32_t timer_id),
- NPP id,
- uint32_t timer_id);
-
- // This is a hack to get the real player plugin to work with chrome
- // The real player plugin dll(nppl3260) when loaded by firefox is loaded via
- // the NS COM API which is analogous to win32 COM. So the NPAPI functions in
- // the plugin are invoked via an interface by firefox. The plugin instance
- // handle which is passed to every NPAPI method is owned by the real player
- // plugin, i.e. it expects the ndata member to point to a structure which
- // it knows about. Eventually it dereferences this structure and compares
- // a member variable at offset 0x24(Version 6.0.11.2888) /2D (Version
- // 6.0.11.3088) with 0 and on failing this check, takes a different code
- // path which causes a crash. Safari and Opera work with version 6.0.11.2888
- // by chance as their ndata structure contains a 0 at the location which real
- // player checks:(. They crash with version 6.0.11.3088 as well. The
- // following member just adds a 96 byte padding to our PluginInstance class
- // which is passed in the ndata member. This magic number works correctly on
- // Vista with UAC on or off :(.
- // NOTE: Please dont change the ordering of the member variables
- // New members should be added after this padding array.
- // TODO(iyengar) : Disassemble the Realplayer ndata structure and look into
- // the possiblity of conforming to it (http://b/issue?id=936667). We
- // could also log a bug with Real, which would save the effort.
- uint8_t zero_padding_[96];
- scoped_refptr<PluginLib> plugin_;
- NPP npp_;
- scoped_refptr<PluginHost> host_;
- NPPluginFuncs* npp_functions_;
- gfx::PluginWindowHandle window_handle_;
- bool windowless_;
- bool transparent_;
- WebPlugin* webplugin_;
- std::string mime_type_;
- bool use_mozilla_user_agent_;
-#if defined(OS_MACOSX)
- NPDrawingModel drawing_model_;
- NPEventModel event_model_;
- gfx::Point plugin_origin_;
- gfx::Rect containing_window_frame_;
- NPCocoaEvent* currently_handled_event_; // weak
-#endif
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
- // This flag if true indicates that the plugin data would be passed from
- // webkit. if false indicates that the plugin should download the data.
- bool load_manually_;
-
- // Stack indicating if popups are to be enabled for the outgoing
- // NPN_GetURL/NPN_GetURLNotify calls.
- std::stack<bool> popups_enabled_stack_;
-
- // List of files created for the current plugin instance. File names are
- // added to the list every time the NPP_StreamAsFile function is called.
- std::vector<base::FilePath> files_created_;
-
- // Next unusued timer id.
- uint32_t next_timer_id_;
-
- // Map of timer id to settings for timer.
- struct TimerInfo {
- uint32_t interval;
- bool repeat;
- };
- typedef std::map<uint32_t, TimerInfo> TimerMap;
- TimerMap timers_;
-
- DISALLOW_COPY_AND_ASSIGN(PluginInstance);
-};
-
-#if defined(OS_MACOSX)
-// Helper to simplify correct usage of set_currently_handled_event.
-// Instantiating will set |instance|'s currently handled to |event| for the
-// lifetime of the object, then NULL when it goes out of scope.
-class ScopedCurrentPluginEvent {
- public:
- ScopedCurrentPluginEvent(PluginInstance* instance, NPCocoaEvent* event);
- ~ScopedCurrentPluginEvent();
-
- private:
- scoped_refptr<PluginInstance> instance_;
- DISALLOW_COPY_AND_ASSIGN(ScopedCurrentPluginEvent);
-};
-#endif
-
-} // namespace content
-
-#endif // CONTENT_CHILD_NPAPI_PLUGIN_INSTANCE_H_
diff --git a/chromium/content/child/npapi/plugin_instance_mac.mm b/chromium/content/child/npapi/plugin_instance_mac.mm
deleted file mode 100644
index bc8edb2295b..00000000000
--- a/chromium/content/child/npapi/plugin_instance_mac.mm
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <AppKit/AppKit.h>
-
-#include "base/logging.h"
-#include "build/build_config.h"
-#include "content/child/npapi/plugin_instance.h"
-
-// When C++ exceptions are disabled, the C++ library defines |try| and
-// |catch| so as to allow exception-expecting C++ code to build properly when
-// language support for exceptions is not present. These macros interfere
-// with the use of |@try| and |@catch| in Objective-C files such as this one.
-// Undefine these macros here, after everything has been #included, since
-// there will be no C++ uses and only Objective-C uses from this point on.
-#undef try
-#undef catch
-
-namespace content {
-
-NPError PluginInstance::PopUpContextMenu(NPMenu* menu) {
- if (!currently_handled_event_)
- return NPERR_GENERIC_ERROR;
-
- CGRect main_display_bounds = CGDisplayBounds(CGMainDisplayID());
- NSPoint screen_point = NSMakePoint(
- plugin_origin_.x() + currently_handled_event_->data.mouse.pluginX,
- plugin_origin_.y() + currently_handled_event_->data.mouse.pluginY);
- // Plugin offsets are upper-left based, so flip vertically for Cocoa.
- screen_point.y = main_display_bounds.size.height - screen_point.y;
-
- NSMenu* nsmenu = reinterpret_cast<NSMenu*>(menu);
- NPError return_val = NPERR_NO_ERROR;
- @try {
- [nsmenu popUpMenuPositioningItem:nil atLocation:screen_point inView:nil];
- }
- @catch (NSException* e) {
- NSLog(@"Caught exception while handling PopUpContextMenu: %@", e);
- return_val = NPERR_GENERIC_ERROR;
- }
-
- return return_val;
-}
-
-ScopedCurrentPluginEvent::ScopedCurrentPluginEvent(PluginInstance* instance,
- NPCocoaEvent* event)
- : instance_(instance) {
- instance_->set_currently_handled_event(event);
-}
-
-ScopedCurrentPluginEvent::~ScopedCurrentPluginEvent() {
- instance_->set_currently_handled_event(NULL);
-}
-
-} // namespace content
diff --git a/chromium/content/child/npapi/plugin_lib.cc b/chromium/content/child/npapi/plugin_lib.cc
deleted file mode 100644
index a472c0ae462..00000000000
--- a/chromium/content/child/npapi/plugin_lib.cc
+++ /dev/null
@@ -1,333 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/child/npapi/plugin_lib.h"
-
-#include <stddef.h>
-#include <string.h>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/string_util.h"
-#include "base/thread_task_runner_handle.h"
-#include "build/build_config.h"
-#include "content/child/npapi/plugin_host.h"
-#include "content/child/npapi/plugin_instance.h"
-#include "content/common/plugin_list.h"
-
-namespace content {
-
-// A list of all the instantiated plugins.
-static std::vector<scoped_refptr<PluginLib> >* g_loaded_libs;
-
-PluginLib* PluginLib::CreatePluginLib(const base::FilePath& filename) {
- // We can only have one PluginLib object per plugin as it controls the per
- // instance function calls (i.e. NP_Initialize and NP_Shutdown). So we keep
- // a map of PluginLib objects.
- if (!g_loaded_libs)
- g_loaded_libs = new std::vector<scoped_refptr<PluginLib> >;
-
- for (size_t i = 0; i < g_loaded_libs->size(); ++i) {
- if ((*g_loaded_libs)[i]->plugin_info().path == filename)
- return (*g_loaded_libs)[i].get();
- }
-
- WebPluginInfo info;
- if (!PluginList::Singleton()->ReadPluginInfo(filename, &info))
- return NULL;
-
- return new PluginLib(info);
-}
-
-void PluginLib::UnloadAllPlugins() {
- if (g_loaded_libs) {
- // PluginLib::Unload() can remove items from the list and even delete
- // the list when it removes the last item, so we must work with a copy
- // of the list so that we don't get the carpet removed under our feet.
- std::vector<scoped_refptr<PluginLib> > loaded_libs(*g_loaded_libs);
- for (size_t i = 0; i < loaded_libs.size(); ++i)
- loaded_libs[i]->Unload();
-
- if (g_loaded_libs && g_loaded_libs->empty()) {
- delete g_loaded_libs;
- g_loaded_libs = NULL;
- }
- }
-}
-
-void PluginLib::ShutdownAllPlugins() {
- if (g_loaded_libs) {
- for (size_t i = 0; i < g_loaded_libs->size(); ++i)
- (*g_loaded_libs)[i]->Shutdown();
- }
-}
-
-PluginLib::PluginLib(const WebPluginInfo& info)
- : web_plugin_info_(info),
- library_(NULL),
- initialized_(false),
- saved_data_(0),
- instance_count_(0),
- skip_unload_(false),
- defer_unload_(false) {
- memset(static_cast<void*>(&plugin_funcs_), 0, sizeof(plugin_funcs_));
- g_loaded_libs->push_back(make_scoped_refptr(this));
-
- memset(&entry_points_, 0, sizeof(entry_points_));
-}
-
-PluginLib::~PluginLib() {
- if (saved_data_ != 0) {
- // TODO - delete the savedData object here
- }
-}
-
-NPPluginFuncs* PluginLib::functions() {
- return &plugin_funcs_;
-}
-
-NPError PluginLib::NP_Initialize() {
- LOG_IF(ERROR, PluginList::DebugPluginLoading())
- << "PluginLib::NP_Initialize(" << web_plugin_info_.path.value()
- << "): initialized=" << initialized_;
- if (initialized_)
- return NPERR_NO_ERROR;
-
- if (!Load())
- return NPERR_MODULE_LOAD_FAILED_ERROR;
-
- PluginHost* host = PluginHost::Singleton();
- if (host == 0)
- return NPERR_GENERIC_ERROR;
-
-#if defined(OS_POSIX) && !defined(OS_MACOSX)
- NPError rv = entry_points_.np_initialize(host->host_functions(),
- &plugin_funcs_);
-#else
- NPError rv = entry_points_.np_initialize(host->host_functions());
-#if defined(OS_MACOSX)
- // On the Mac, we need to get entry points after calling np_initialize to
- // match the behavior of other browsers.
- if (rv == NPERR_NO_ERROR) {
- rv = entry_points_.np_getentrypoints(&plugin_funcs_);
- }
-#endif // OS_MACOSX
-#endif
- LOG_IF(ERROR, PluginList::DebugPluginLoading())
- << "PluginLib::NP_Initialize(" << web_plugin_info_.path.value()
- << "): result=" << rv;
- initialized_ = (rv == NPERR_NO_ERROR);
- return rv;
-}
-
-void PluginLib::NP_Shutdown(void) {
- DCHECK(initialized_);
- entry_points_.np_shutdown();
-}
-
-NPError PluginLib::NP_ClearSiteData(const char* site,
- uint64_t flags,
- uint64_t max_age) {
- DCHECK(initialized_);
- if (plugin_funcs_.clearsitedata)
- return plugin_funcs_.clearsitedata(site, flags, max_age);
- return NPERR_INVALID_FUNCTABLE_ERROR;
-}
-
-char** PluginLib::NP_GetSitesWithData() {
- DCHECK(initialized_);
- if (plugin_funcs_.getsiteswithdata)
- return plugin_funcs_.getsiteswithdata();
- return NULL;
-}
-
-void PluginLib::PreventLibraryUnload() {
- skip_unload_ = true;
-}
-
-PluginInstance* PluginLib::CreateInstance(const std::string& mime_type) {
- PluginInstance* new_instance = new PluginInstance(this, mime_type);
- instance_count_++;
- DCHECK_NE(static_cast<PluginInstance*>(NULL), new_instance);
- return new_instance;
-}
-
-void PluginLib::CloseInstance() {
- instance_count_--;
- // If a plugin is running in its own process it will get unloaded on process
- // shutdown.
- if ((instance_count_ == 0) && !defer_unload_)
- Unload();
-}
-
-bool PluginLib::Load() {
- if (library_)
- return true;
-
- bool rv = false;
- base::NativeLibrary library = 0;
- base::NativeLibraryLoadError error;
-
-#if defined(OS_WIN)
- // This is to work around a bug in the Real player recorder plugin which
- // intercepts LoadLibrary calls from chrome.dll and wraps NPAPI functions
- // provided by the plugin. It crashes if the media player plugin is being
- // loaded. Workaround is to load the dll dynamically by getting the
- // LoadLibrary API address from kernel32.dll which bypasses the recorder
- // plugin.
- if (web_plugin_info_.name.find(L"Windows Media Player") !=
- std::wstring::npos) {
- library = base::LoadNativeLibraryDynamically(web_plugin_info_.path);
- } else {
- library = base::LoadNativeLibrary(web_plugin_info_.path, &error);
- }
-#else
- library = base::LoadNativeLibrary(web_plugin_info_.path, &error);
-#endif
-
- if (!library) {
- LOG_IF(ERROR, PluginList::DebugPluginLoading())
- << "Couldn't load plugin " << web_plugin_info_.path.value() << " "
- << error.ToString();
- return rv;
- }
-
-#if defined(OS_MACOSX)
- // According to the WebKit source, QuickTime at least requires us to call
- // UseResFile on the plugin resources before loading.
- if (library->bundle_resource_ref != -1)
- UseResFile(library->bundle_resource_ref);
-#endif
-
- rv = true; // assume success now
-
- entry_points_.np_initialize =
- (NP_InitializeFunc)base::GetFunctionPointerFromNativeLibrary(library,
- "NP_Initialize");
- if (entry_points_.np_initialize == 0)
- rv = false;
-
-#if defined(OS_WIN) || defined(OS_MACOSX)
- entry_points_.np_getentrypoints =
- (NP_GetEntryPointsFunc)base::GetFunctionPointerFromNativeLibrary(
- library, "NP_GetEntryPoints");
- if (entry_points_.np_getentrypoints == 0)
- rv = false;
-#endif
-
- entry_points_.np_shutdown =
- (NP_ShutdownFunc)base::GetFunctionPointerFromNativeLibrary(library,
- "NP_Shutdown");
- if (entry_points_.np_shutdown == 0)
- rv = false;
-
- if (rv) {
- plugin_funcs_.size = sizeof(plugin_funcs_);
- plugin_funcs_.version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
-#if !defined(OS_POSIX)
- if (entry_points_.np_getentrypoints(&plugin_funcs_) != NPERR_NO_ERROR)
- rv = false;
-#else
- // On Linux and Mac, we get the plugin entry points during NP_Initialize.
-#endif
- }
-
- if (rv) {
- LOG_IF(ERROR, PluginList::DebugPluginLoading())
- << "Plugin " << web_plugin_info_.path.value()
- << " loaded successfully.";
- library_ = library;
- } else {
- LOG_IF(ERROR, PluginList::DebugPluginLoading())
- << "Plugin " << web_plugin_info_.path.value()
- << " failed to load, unloading.";
- base::UnloadNativeLibrary(library);
- }
-
- return rv;
-}
-
-// This is a helper to help perform a delayed NP_Shutdown and FreeLibrary on the
-// plugin dll.
-void FreePluginLibraryHelper(const base::FilePath& path,
- base::NativeLibrary library,
- NP_ShutdownFunc shutdown_func) {
- if (shutdown_func) {
- // Don't call NP_Shutdown if the library has been reloaded since this task
- // was posted.
- bool reloaded = false;
- if (g_loaded_libs) {
- for (size_t i = 0; i < g_loaded_libs->size(); ++i) {
- if ((*g_loaded_libs)[i]->plugin_info().path == path) {
- reloaded = true;
- break;
- }
- }
- }
- if (!reloaded)
- shutdown_func();
- }
-
- if (library) {
- // Always call base::UnloadNativeLibrary so that the system reference
- // count is decremented.
- base::UnloadNativeLibrary(library);
- }
-}
-
-void PluginLib::Unload() {
- if (library_) {
- // In case of single process mode, a plugin can delete itself
- // by executing a script. So delay the unloading of the library
- // so that the plugin will have a chance to unwind.
-/* TODO(dglazkov): Revisit when re-enabling the JSC build.
-#if USE(JSC)
- // The plugin NPAPI instances may still be around. Delay the
- // NP_Shutdown and FreeLibrary calls at least till the next
- // peek message.
- defer_unload = true;
-#endif
-*/
- if (!defer_unload_) {
- LOG_IF(ERROR, PluginList::DebugPluginLoading())
- << "Scheduling delayed unload for plugin "
- << web_plugin_info_.path.value();
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&FreePluginLibraryHelper, web_plugin_info_.path,
- skip_unload_ ? NULL : library_,
- entry_points_.np_shutdown));
- } else {
- Shutdown();
- if (!skip_unload_) {
- LOG_IF(ERROR, PluginList::DebugPluginLoading())
- << "Unloading plugin " << web_plugin_info_.path.value();
- base::UnloadNativeLibrary(library_);
- }
- }
-
- library_ = NULL;
- }
-
- for (size_t i = 0; i < g_loaded_libs->size(); ++i) {
- if ((*g_loaded_libs)[i].get() == this) {
- g_loaded_libs->erase(g_loaded_libs->begin() + i);
- break;
- }
- }
- if (g_loaded_libs->empty()) {
- delete g_loaded_libs;
- g_loaded_libs = NULL;
- }
-}
-
-void PluginLib::Shutdown() {
- if (initialized_) {
- NP_Shutdown();
- initialized_ = false;
- }
-}
-
-} // namespace content
diff --git a/chromium/content/child/npapi/plugin_lib.h b/chromium/content/child/npapi/plugin_lib.h
deleted file mode 100644
index 1228fb7f0d1..00000000000
--- a/chromium/content/child/npapi/plugin_lib.h
+++ /dev/null
@@ -1,135 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_CHILD_NPAPI_PLUGIN_LIB_H_
-#define CONTENT_CHILD_NPAPI_PLUGIN_LIB_H_
-
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/native_library.h"
-#include "build/build_config.h"
-#include "content/child/npapi/webplugin.h"
-#include "content/common/content_export.h"
-#include "content/public/common/webplugininfo.h"
-#include "third_party/npapi/bindings/nphostapi.h"
-
-namespace base {
-class FilePath;
-}
-
-namespace content {
-
-class PluginInstance;
-
-// This struct holds entry points into a plugin. The entry points are
-// slightly different between Win/Mac and Unixes. Note that the interface for
-// querying plugins is synchronous and it is preferable to use a higher-level
-// asynchronous information to query information.
-struct PluginEntryPoints {
-#if !defined(OS_POSIX) || defined(OS_MACOSX)
- NP_GetEntryPointsFunc np_getentrypoints;
-#endif
- NP_InitializeFunc np_initialize;
- NP_ShutdownFunc np_shutdown;
-};
-
-// A PluginLib is a single NPAPI Plugin Library, and is the lifecycle
-// manager for new PluginInstances.
-class CONTENT_EXPORT PluginLib : public base::RefCounted<PluginLib> {
- public:
- static PluginLib* CreatePluginLib(const base::FilePath& filename);
-
- // Unloads all the loaded plugin libraries and cleans up the plugin map.
- static void UnloadAllPlugins();
-
- // Shuts down all loaded plugin instances.
- static void ShutdownAllPlugins();
-
- // Get the Plugin's function pointer table.
- NPPluginFuncs* functions();
-
- // Creates a new instance of this plugin.
- PluginInstance* CreateInstance(const std::string& mime_type);
-
- // Called by the instance when the instance is tearing down.
- void CloseInstance();
-
- // Gets information about this plugin and the mime types that it
- // supports.
- const WebPluginInfo& plugin_info() { return web_plugin_info_; }
-
- //
- // NPAPI functions
- //
-
- // NPAPI method to initialize a Plugin.
- // Initialize can be safely called multiple times
- NPError NP_Initialize();
-
- // NPAPI method to shutdown a Plugin.
- void NP_Shutdown(void);
-
- // NPAPI method to clear locally stored data (LSO's or "Flash cookies").
- NPError NP_ClearSiteData(const char* site, uint64_t flags, uint64_t max_age);
-
- // NPAPI method to get a NULL-terminated list of all sites under which data
- // is stored.
- char** NP_GetSitesWithData();
-
- int instance_count() const { return instance_count_; }
-
- // Prevents the library code from being unload when Unload() is called (since
- // some plugins crash if unloaded).
- void PreventLibraryUnload();
-
- // Indicates whether plugin unload can be deferred.
- void set_defer_unload(bool defer_unload) {
- defer_unload_ = defer_unload;
- }
-
- // protected for testability.
- protected:
- friend class base::RefCounted<PluginLib>;
-
- // Creates a new PluginLib.
- explicit PluginLib(const WebPluginInfo& info);
-
- virtual ~PluginLib();
-
- // Attempts to load the plugin from the library.
- // Returns true if it is a legitimate plugin, false otherwise
- bool Load();
-
- // Unloads the plugin library.
- void Unload();
-
- // Shutdown the plugin library.
- void Shutdown();
-
- private:
- WebPluginInfo web_plugin_info_; // Supported mime types, description
- base::NativeLibrary library_; // The opened library reference.
- NPPluginFuncs plugin_funcs_; // The struct of plugin side functions.
- bool initialized_; // Is the plugin initialized?
- NPSavedData *saved_data_; // Persisted plugin info for NPAPI.
- int instance_count_; // Count of plugins in use.
- bool skip_unload_; // True if library_ should not be unloaded.
-
- // Function pointers to entry points into the plugin.
- PluginEntryPoints entry_points_;
-
- // Set to true if unloading of the plugin dll is to be deferred.
- bool defer_unload_;
-
- DISALLOW_COPY_AND_ASSIGN(PluginLib);
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_NPAPI_PLUGIN_LIB_H_
diff --git a/chromium/content/child/npapi/plugin_lib_unittest.cc b/chromium/content/child/npapi/plugin_lib_unittest.cc
deleted file mode 100644
index 1469828019c..00000000000
--- a/chromium/content/child/npapi/plugin_lib_unittest.cc
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/child/npapi/plugin_lib.h"
-
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-// Test the unloading of plugin libs. Bug http://crbug.com/46526 showed that
-// if UnloadAllPlugins() simply iterates through the g_loaded_libs global
-// variable, we can get a crash if no plugin libs were marked as always loaded.
-class PluginLibTest : public PluginLib {
- public:
- PluginLibTest() : PluginLib(WebPluginInfo()) {}
- using PluginLib::Unload;
-
- protected:
- ~PluginLibTest() override {}
-};
-
-TEST(PluginLibLoading, UnloadAllPlugins) {
- // For the creation of the g_loaded_libs global variable.
- ASSERT_EQ(static_cast<PluginLibTest*>(NULL),
- PluginLibTest::CreatePluginLib(base::FilePath()));
-
- // Try with a single plugin lib.
- scoped_refptr<PluginLibTest> plugin_lib1(new PluginLibTest());
- PluginLib::UnloadAllPlugins();
-
- // Need to create it again, it should have been destroyed above.
- ASSERT_EQ(static_cast<PluginLibTest*>(NULL),
- PluginLibTest::CreatePluginLib(base::FilePath()));
-
- // Try with two plugin libs.
- plugin_lib1 = new PluginLibTest();
- scoped_refptr<PluginLibTest> plugin_lib2(new PluginLibTest());
- PluginLib::UnloadAllPlugins();
-
- // Need to create it again, it should have been destroyed above.
- ASSERT_EQ(static_cast<PluginLibTest*>(NULL),
- PluginLibTest::CreatePluginLib(base::FilePath()));
-
- // Now try to manually Unload one and then UnloadAll.
- plugin_lib1 = new PluginLibTest();
- plugin_lib2 = new PluginLibTest();
- plugin_lib1->Unload();
- PluginLib::UnloadAllPlugins();
-
- // Need to create it again, it should have been destroyed above.
- ASSERT_EQ(static_cast<PluginLibTest*>(NULL),
- PluginLibTest::CreatePluginLib(base::FilePath()));
-
- // Now try to manually Unload the only one and then UnloadAll.
- plugin_lib1 = new PluginLibTest();
- plugin_lib1->Unload();
- PluginLib::UnloadAllPlugins();
-}
-
-} // namespace content
diff --git a/chromium/content/child/npapi/plugin_web_event_converter_mac.h b/chromium/content/child/npapi/plugin_web_event_converter_mac.h
deleted file mode 100644
index 7847553677f..00000000000
--- a/chromium/content/child/npapi/plugin_web_event_converter_mac.h
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_CHILD_NPAPI_PLUGIN_WEB_EVENT_CONVERTER_MAC_H_
-#define CONTENT_CHILD_NPAPI_PLUGIN_WEB_EVENT_CONVERTER_MAC_H_
-
-#include "base/macros.h"
-#include "third_party/npapi/bindings/npapi.h"
-
-namespace blink {
-class WebInputEvent;
-class WebKeyboardEvent;
-class WebMouseEvent;
-class WebMouseWheelEvent;
-}
-
-namespace content {
-
-// Utility class to translating WebInputEvent structs to equivalent structures
-// suitable for sending to Mac plugins (via NPP_HandleEvent).
-class PluginWebEventConverter {
- public:
- PluginWebEventConverter();
- virtual ~PluginWebEventConverter();
-
- // Initializes a converter for the given web event. Returns false if the event
- // could not be converted.
- bool InitWithEvent(const blink::WebInputEvent& web_event);
-
- // Returns a pointer to a plugin event--suitable for passing to
- // NPP_HandleEvent--corresponding to the the web event this converter was
- // created with. The pointer is valid only as long as this object is.
- // Returns NULL iff InitWithEvent returned false.
- NPCocoaEvent* plugin_event() { return &cocoa_event_; }
-
- private:
- // Stores a converted plugin representation of the given web event, suitable
- // for returning from plugin_event.
- // Returns true if the event was successfully converted.
- bool ConvertKeyboardEvent(const blink::WebKeyboardEvent& web_event);
- bool ConvertMouseEvent(const blink::WebMouseEvent& web_event);
- bool ConvertMouseWheelEvent(const blink::WebMouseWheelEvent& web_event);
-
- // Returns the Cocoa translation of web_event's modifiers.
- static NSUInteger CocoaModifiers(const blink::WebInputEvent& web_event);
-
- NPCocoaEvent cocoa_event_;
-
- DISALLOW_COPY_AND_ASSIGN(PluginWebEventConverter);
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_NPAPI_PLUGIN_WEB_EVENT_CONVERTER_MAC_H_
diff --git a/chromium/content/child/npapi/plugin_web_event_converter_mac.mm b/chromium/content/child/npapi/plugin_web_event_converter_mac.mm
deleted file mode 100644
index 4ddd4343e86..00000000000
--- a/chromium/content/child/npapi/plugin_web_event_converter_mac.mm
+++ /dev/null
@@ -1,189 +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.
-
-#import <Cocoa/Cocoa.h>
-#include <string.h>
-
-#include "base/logging.h"
-#include "content/child/npapi/plugin_web_event_converter_mac.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-
-using blink::WebInputEvent;
-using blink::WebKeyboardEvent;
-using blink::WebMouseEvent;
-using blink::WebMouseWheelEvent;
-
-namespace content {
-
-namespace {
-
-// Returns true if the given key is a modifier key.
-bool KeyIsModifier(int native_key_code) {
- switch (native_key_code) {
- case 55: // Left command
- case 54: // Right command
- case 58: // Left option
- case 61: // Right option
- case 59: // Left control
- case 62: // Right control
- case 56: // Left shift
- case 60: // Right shift
- case 57: // Caps lock
- return true;
- default:
- return false;
- }
-}
-
-// Returns true if the caps lock flag should be set for the given event.
-bool CapsLockIsActive(const WebInputEvent& event) {
- // Only key events have accurate information for the caps lock flag; see
- // <https://bugs.webkit.org/show_bug.cgi?id=46518>.
- // For other types, use the live state.
- if (WebInputEvent::isKeyboardEventType(event.type))
- return (event.modifiers & WebInputEvent::CapsLockOn) != 0;
- else
- return ([[NSApp currentEvent] modifierFlags] & NSAlphaShiftKeyMask) != 0;
-}
-
-} // namespace
-
-#pragma mark -
-
-PluginWebEventConverter::PluginWebEventConverter() {
-}
-
-PluginWebEventConverter::~PluginWebEventConverter() {
-}
-
-bool PluginWebEventConverter::InitWithEvent(const WebInputEvent& web_event) {
- memset(&cocoa_event_, 0, sizeof(cocoa_event_));
- if (web_event.type == WebInputEvent::MouseWheel) {
- return ConvertMouseWheelEvent(
- *static_cast<const WebMouseWheelEvent*>(&web_event));
- } else if (WebInputEvent::isMouseEventType(web_event.type)) {
- return ConvertMouseEvent(*static_cast<const WebMouseEvent*>(&web_event));
- } else if (WebInputEvent::isKeyboardEventType(web_event.type)) {
- return ConvertKeyboardEvent(
- *static_cast<const WebKeyboardEvent*>(&web_event));
- }
- DLOG(WARNING) << "Unknown event type " << web_event.type;
- return false;
-}
-
-bool PluginWebEventConverter::ConvertKeyboardEvent(
- const WebKeyboardEvent& key_event) {
- cocoa_event_.data.key.keyCode = key_event.nativeKeyCode;
-
- cocoa_event_.data.key.modifierFlags |= CocoaModifiers(key_event);
-
- // Modifier keys have their own event type, and don't get character or
- // repeat data.
- if (KeyIsModifier(key_event.nativeKeyCode)) {
- cocoa_event_.type = NPCocoaEventFlagsChanged;
- return true;
- }
-
- cocoa_event_.data.key.characters = reinterpret_cast<NPNSString*>(
- [NSString stringWithFormat:@"%S", key_event.text]);
- cocoa_event_.data.key.charactersIgnoringModifiers =
- reinterpret_cast<NPNSString*>(
- [NSString stringWithFormat:@"%S", key_event.unmodifiedText]);
-
- if (key_event.modifiers & WebInputEvent::IsAutoRepeat)
- cocoa_event_.data.key.isARepeat = true;
-
- switch (key_event.type) {
- case WebInputEvent::KeyDown:
- cocoa_event_.type = NPCocoaEventKeyDown;
- return true;
- case WebInputEvent::KeyUp:
- cocoa_event_.type = NPCocoaEventKeyUp;
- return true;
- case WebInputEvent::RawKeyDown:
- case WebInputEvent::Char:
- // May be used eventually for IME, but currently not needed.
- return false;
- default:
- NOTREACHED();
- return false;
- }
-}
-
-bool PluginWebEventConverter::ConvertMouseEvent(
- const WebMouseEvent& mouse_event) {
- cocoa_event_.data.mouse.pluginX = mouse_event.x;
- cocoa_event_.data.mouse.pluginY = mouse_event.y;
- cocoa_event_.data.mouse.modifierFlags |= CocoaModifiers(mouse_event);
- cocoa_event_.data.mouse.clickCount = mouse_event.clickCount;
- switch (mouse_event.button) {
- case WebMouseEvent::ButtonLeft:
- cocoa_event_.data.mouse.buttonNumber = 0;
- break;
- case WebMouseEvent::ButtonMiddle:
- cocoa_event_.data.mouse.buttonNumber = 2;
- break;
- case WebMouseEvent::ButtonRight:
- cocoa_event_.data.mouse.buttonNumber = 1;
- break;
- default:
- cocoa_event_.data.mouse.buttonNumber = mouse_event.button;
- break;
- }
- switch (mouse_event.type) {
- case WebInputEvent::MouseDown:
- cocoa_event_.type = NPCocoaEventMouseDown;
- return true;
- case WebInputEvent::MouseUp:
- cocoa_event_.type = NPCocoaEventMouseUp;
- return true;
- case WebInputEvent::MouseMove: {
- bool mouse_is_down =
- (mouse_event.modifiers & WebInputEvent::LeftButtonDown) ||
- (mouse_event.modifiers & WebInputEvent::RightButtonDown) ||
- (mouse_event.modifiers & WebInputEvent::MiddleButtonDown);
- cocoa_event_.type = mouse_is_down ? NPCocoaEventMouseDragged
- : NPCocoaEventMouseMoved;
- return true;
- }
- case WebInputEvent::MouseEnter:
- cocoa_event_.type = NPCocoaEventMouseEntered;
- return true;
- case WebInputEvent::MouseLeave:
- cocoa_event_.type = NPCocoaEventMouseExited;
- return true;
- default:
- NOTREACHED();
- return false;
- }
-}
-
-bool PluginWebEventConverter::ConvertMouseWheelEvent(
- const WebMouseWheelEvent& wheel_event) {
- cocoa_event_.type = NPCocoaEventScrollWheel;
- cocoa_event_.data.mouse.pluginX = wheel_event.x;
- cocoa_event_.data.mouse.pluginY = wheel_event.y;
- cocoa_event_.data.mouse.modifierFlags |= CocoaModifiers(wheel_event);
- cocoa_event_.data.mouse.deltaX = wheel_event.deltaX;
- cocoa_event_.data.mouse.deltaY = wheel_event.deltaY;
- return true;
-}
-
-NSUInteger PluginWebEventConverter::CocoaModifiers(
- const WebInputEvent& web_event) {
- NSInteger modifiers = 0;
- if (web_event.modifiers & WebInputEvent::ControlKey)
- modifiers |= NSControlKeyMask;
- if (web_event.modifiers & WebInputEvent::ShiftKey)
- modifiers |= NSShiftKeyMask;
- if (web_event.modifiers & WebInputEvent::AltKey)
- modifiers |= NSAlternateKeyMask;
- if (web_event.modifiers & WebInputEvent::MetaKey)
- modifiers |= NSCommandKeyMask;
- if (CapsLockIsActive(web_event))
- modifiers |= NSAlphaShiftKeyMask;
- return modifiers;
-}
-
-} // namespace content
diff --git a/chromium/content/child/npapi/webplugin.h b/chromium/content/child/npapi/webplugin.h
deleted file mode 100644
index 9eb0be988fe..00000000000
--- a/chromium/content/child/npapi/webplugin.h
+++ /dev/null
@@ -1,133 +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_CHILD_NPAPI_WEBPLUGIN_H_
-#define CONTENT_CHILD_NPAPI_WEBPLUGIN_H_
-
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#include "build/build_config.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gl/gpu_preference.h"
-
-// TODO(port): this typedef is obviously incorrect on non-Windows
-// platforms, but now a lot of code now accidentally depends on them
-// existing. #ifdef out these declarations and fix all the users.
-typedef void* HANDLE;
-
-class GURL;
-struct NPObject;
-
-namespace content {
-
-class WebPluginResourceClient;
-#if defined(OS_MACOSX)
-class WebPluginAcceleratedSurface;
-#endif
-
-// The WebKit side of a plugin implementation. It provides wrappers around
-// operations that need to interact with the frame and other WebCore objects.
-class WebPlugin {
- public:
- virtual ~WebPlugin() {}
-
- // Called by the plugin delegate to let the WebPlugin know if the plugin is
- // windowed (i.e. handle is not NULL) or windowless (handle is NULL). This
- // tells the WebPlugin to send mouse/keyboard events to the plugin delegate,
- // as well as the information about the HDC for paint operations.
- virtual void SetWindow(gfx::PluginWindowHandle window) = 0;
-
- // Whether input events should be sent to the delegate.
- virtual void SetAcceptsInputEvents(bool accepts) = 0;
-
- // Called by the plugin delegate to let it know that the window is being
- // destroyed.
- virtual void WillDestroyWindow(gfx::PluginWindowHandle window) = 0;
-
- // Cancels a pending request.
- virtual void CancelResource(unsigned long id) = 0;
- virtual void Invalidate() = 0;
- virtual void InvalidateRect(const gfx::Rect& rect) = 0;
-
- // Returns the NPObject for the browser's window object. Does not
- // take a reference.
- virtual NPObject* GetWindowScriptNPObject() = 0;
-
- // Returns the DOM element that loaded the plugin. Does not take a
- // reference.
- virtual NPObject* GetPluginElement() = 0;
-
- // Resolves the proxies for the url, returns true on success.
- virtual bool FindProxyForUrl(const GURL& url, std::string* proxy_list) = 0;
-
- // Cookies
- virtual void SetCookie(const GURL& url,
- const GURL& first_party_for_cookies,
- const std::string& cookie) = 0;
- virtual std::string GetCookies(const GURL& url,
- const GURL& first_party_for_cookies) = 0;
-
- // Cancels document load.
- virtual void CancelDocumentLoad() = 0;
-
- virtual void DidStartLoading() = 0;
- virtual void DidStopLoading() = 0;
-
- // Returns true iff in incognito mode.
- virtual bool IsOffTheRecord() = 0;
-
- // Called when the WebPluginResourceClient instance is deleted.
- virtual void ResourceClientDeleted(
- WebPluginResourceClient* resource_client) {}
-
- // Defers the loading of the resource identified by resource_id. This is
- // controlled by the defer parameter.
- virtual void SetDeferResourceLoading(unsigned long resource_id,
- bool defer) = 0;
-
- // Handles NPN_URLRedirectResponse calls issued by plugins in response to
- // HTTP URL redirect notifications.
- virtual void URLRedirectResponse(bool allow, int resource_id) = 0;
-
- // Returns true if the new url is a secure transition. This is to catch a
- // plugin src url transitioning from https to http.
- virtual bool CheckIfRunInsecureContent(const GURL& url) = 0;
-
-#if defined(OS_WIN)
- // |pump_messages_event| is a event handle which is used in NPP_HandleEvent
- // calls to pump messages if the plugin enters a modal loop.
- // |dummy_activation_window} is used to ensure correct keyboard activation.
- // It needs to be a child of the parent window.
- virtual void SetWindowlessData(HANDLE pump_messages_event,
- gfx::NativeViewId dummy_activation_window) = 0;
-#endif
-
-#if defined(OS_MACOSX)
- // Called to inform the WebPlugin that the plugin has gained or lost focus.
- virtual void FocusChanged(bool focused) {}
-
- // Starts plugin IME.
- virtual void StartIme() {}
-
- // Returns the accelerated surface abstraction for accelerated plugins.
- virtual WebPluginAcceleratedSurface* GetAcceleratedSurface(
- gfx::GpuPreference gpu_preference) = 0;
-
- // Core Animation plugin support. CA plugins always render through
- // the compositor.
- virtual void AcceleratedPluginEnabledRendering() = 0;
- virtual void AcceleratedPluginAllocatedIOSurface(int32_t width,
- int32_t height,
- uint32_t surface_id) = 0;
- virtual void AcceleratedPluginSwappedIOSurface() = 0;
-#endif
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_NPAPI_WEBPLUGIN_H_
diff --git a/chromium/content/child/npapi/webplugin_accelerated_surface_mac.h b/chromium/content/child/npapi/webplugin_accelerated_surface_mac.h
deleted file mode 100644
index d91f8f21c2c..00000000000
--- a/chromium/content/child/npapi/webplugin_accelerated_surface_mac.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_CHILD_NPAPI_WEBPLUGIN_ACCELERATED_SURFACE_MAC_H_
-#define CONTENT_CHILD_NPAPI_WEBPLUGIN_ACCELERATED_SURFACE_MAC_H_
-
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/native_widget_types.h"
-
-// Avoid having to include OpenGL headers here.
-typedef struct _CGLContextObject* CGLContextObj;
-
-namespace content {
-
-// Interface class for interacting with an accelerated plugin surface, used
-// for the Core Animation flavors of plugin drawing on the Mac.
-class WebPluginAcceleratedSurface {
- public:
- virtual ~WebPluginAcceleratedSurface() {}
-
- // Sets the size of the surface.
- virtual void SetSize(const gfx::Size& size) = 0;
-
- // Returns the context used to draw into this surface.
- // If initializing the surface failed, this will be NULL.
- virtual CGLContextObj context() = 0;
-
- // Readies the surface for drawing. Must be called before any drawing session.
- virtual void StartDrawing() = 0;
-
- // Ends a drawing session. Changes to the surface may not be reflected until
- // this is called.
- virtual void EndDrawing() = 0;
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_NPAPI_WEBPLUGIN_ACCELERATED_SURFACE_MAC_H_
diff --git a/chromium/content/child/npapi/webplugin_delegate.h b/chromium/content/child/npapi/webplugin_delegate.h
deleted file mode 100644
index c18eb762add..00000000000
--- a/chromium/content/child/npapi/webplugin_delegate.h
+++ /dev/null
@@ -1,96 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_CHILD_NPAPI_WEBPLUGIN_DELEGATE_H_
-#define CONTENT_CHILD_NPAPI_WEBPLUGIN_DELEGATE_H_
-
-#include <string>
-#include <vector>
-
-#include "base/strings/string16.h"
-#include "build/build_config.h"
-#include "content/common/cursors/webcursor.h"
-#include "third_party/npapi/bindings/npapi.h"
-#include "ui/gfx/native_widget_types.h"
-
-class GURL;
-class SkCanvas;
-struct NPObject;
-
-namespace blink {
-class WebInputEvent;
-}
-
-namespace gfx {
-class Rect;
-}
-
-namespace content {
-
-struct Referrer;
-class WebPluginResourceClient;
-
-// This is the interface that a plugin implementation needs to provide.
-class WebPluginDelegate {
- public:
- virtual ~WebPluginDelegate() {}
-
- // Initializes the plugin implementation with the given (UTF8) arguments.
- // Note that the lifetime of WebPlugin must be longer than this delegate.
- // If this function returns false the plugin isn't started and shouldn't be
- // called again. If this method succeeds, then the WebPlugin is valid until
- // PluginDestroyed is called.
- // The load_manually parameter if true indicates that the plugin data would
- // be passed from webkit. if false indicates that the plugin should download
- // the data. This also controls whether the plugin is instantiated as a full
- // page plugin (NP_FULL) or embedded (NP_EMBED).
- virtual bool Initialize(const GURL& url,
- const std::vector<std::string>& arg_names,
- const std::vector<std::string>& arg_values,
- bool load_manually) = 0;
-
- // Called when the WebPlugin is being destroyed. This is a signal to the
- // delegate that it should tear-down the plugin implementation and not call
- // methods on the WebPlugin again.
- virtual void PluginDestroyed() = 0;
-
- // Update the geometry of the plugin. This is a request to move the
- // plugin, relative to its containing window, to the coords given by
- // window_rect. Its contents should be clipped to the coords given
- // by clip_rect, which are relative to the origin of the plugin
- // window. The clip_rect is in plugin-relative coordinates.
- virtual void UpdateGeometry(const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect) = 0;
-
- // Tells the plugin to paint the damaged rect. |canvas| is only used for
- // windowless plugins.
- virtual void Paint(SkCanvas* canvas, const gfx::Rect& rect) = 0;
-
- // Informs the plugin that it has gained or lost focus. This is only called in
- // windowless mode.
- virtual void SetFocus(bool focused) = 0;
-
- // For windowless plugins, gives them a user event like mouse/keyboard.
- // Returns whether the event was handled. This is only called in windowsless
- // mode. See NPAPI NPP_HandleEvent for more information.
- virtual bool HandleInputEvent(const blink::WebInputEvent& event,
- WebCursor::CursorInfo* cursor) = 0;
-
- // Gets the NPObject associated with the plugin for scripting.
- virtual NPObject* GetPluginScriptableObject() = 0;
-
- // Gets the NPP instance uniquely identifying the plugin for its lifetime.
- virtual struct _NPP* GetPluginNPP() = 0;
-
- // Gets the form value associated with the plugin instance.
- // Returns false if the value is not available.
- virtual bool GetFormValue(base::string16* value) = 0;
-
- // Returns the process id of the process that is running the plugin.
- virtual int GetProcessId() = 0;
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_NPAPI_WEBPLUGIN_DELEGATE_H_
diff --git a/chromium/content/child/npapi/webplugin_delegate_impl.cc b/chromium/content/child/npapi/webplugin_delegate_impl.cc
deleted file mode 100644
index 1854ea4666a..00000000000
--- a/chromium/content/child/npapi/webplugin_delegate_impl.cc
+++ /dev/null
@@ -1,242 +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/child/npapi/webplugin_delegate_impl.h"
-
-#include <stddef.h>
-
-#include <string>
-#include <vector>
-
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/process/process_handle.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build/build_config.h"
-#include "content/child/npapi/plugin_instance.h"
-#include "content/child/npapi/plugin_lib.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-
-using blink::WebCursorInfo;
-using blink::WebInputEvent;
-
-namespace content {
-
-WebPluginDelegateImpl* WebPluginDelegateImpl::Create(
- WebPlugin* plugin,
- const base::FilePath& filename,
- const std::string& mime_type) {
- scoped_refptr<PluginLib> plugin_lib(PluginLib::CreatePluginLib(filename));
- if (plugin_lib.get() == NULL)
- return NULL;
-
- NPError err = plugin_lib->NP_Initialize();
- if (err != NPERR_NO_ERROR)
- return NULL;
-
- scoped_refptr<PluginInstance> instance(plugin_lib->CreateInstance(mime_type));
- return new WebPluginDelegateImpl(plugin, instance.get());
-}
-
-void WebPluginDelegateImpl::PluginDestroyed() {
- if (handle_event_depth_) {
- base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
- } else {
- delete this;
- }
-}
-
-bool WebPluginDelegateImpl::Initialize(
- const GURL& url,
- const std::vector<std::string>& arg_names,
- const std::vector<std::string>& arg_values,
- bool load_manually) {
- if (instance_->plugin_lib()->plugin_info().name.find(
- base::ASCIIToUTF16("QuickTime Plug-in")) != std::wstring::npos) {
- quirks_ |= PLUGIN_QUIRK_COPY_STREAM_DATA;
- }
-
- instance_->set_web_plugin(plugin_);
- if (quirks_ & PLUGIN_QUIRK_DONT_ALLOW_MULTIPLE_INSTANCES) {
- PluginLib* plugin_lib = instance()->plugin_lib();
- if (plugin_lib->instance_count() > 1) {
- return false;
- }
- }
-
- int argc = 0;
- scoped_ptr<char*[]> argn(new char*[arg_names.size()]);
- scoped_ptr<char*[]> argv(new char*[arg_names.size()]);
- for (size_t i = 0; i < arg_names.size(); ++i) {
- if (quirks_ & PLUGIN_QUIRK_NO_WINDOWLESS &&
- base::LowerCaseEqualsASCII(arg_names[i], "windowlessvideo")) {
- continue;
- }
- argn[argc] = const_cast<char*>(arg_names[i].c_str());
- argv[argc] = const_cast<char*>(arg_values[i].c_str());
- argc++;
- }
-
- creation_succeeded_ = instance_->Start(
- url, argn.get(), argv.get(), argc, load_manually);
- if (!creation_succeeded_) {
- VLOG(1) << "Couldn't start plugin instance";
- return false;
- }
-
- windowless_ = instance_->windowless();
- if (!windowless_) {
- if (!WindowedCreatePlugin()) {
- VLOG(1) << "Couldn't create windowed plugin";
- return false;
- }
- }
-
- bool should_load = PlatformInitialize();
-
- plugin_url_ = url.spec();
-
- return should_load;
-}
-
-void WebPluginDelegateImpl::DestroyInstance() {
- if (instance_.get() && (instance_->npp()->ndata != NULL)) {
- window_.window = NULL;
- if (creation_succeeded_ &&
- !(quirks_ & PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY)) {
- instance_->NPP_SetWindow(&window_);
- }
-
- instance_->NPP_Destroy();
-
- instance_->set_web_plugin(NULL);
-
- PlatformDestroyInstance();
-
- instance_ = 0;
- }
-}
-
-void WebPluginDelegateImpl::UpdateGeometry(
- const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect) {
-
- if (first_set_window_call_) {
- first_set_window_call_ = false;
- // Plugins like media player on Windows have a bug where in they handle the
- // first geometry update and ignore the rest resulting in painting issues.
- // This quirk basically ignores the first set window call sequence for
- // these plugins and has been tested for Windows plugins only.
- if (quirks_ & PLUGIN_QUIRK_IGNORE_FIRST_SETWINDOW_CALL)
- return;
- }
-
- if (windowless_) {
- WindowlessUpdateGeometry(window_rect, clip_rect);
- } else {
- WindowedUpdateGeometry(window_rect, clip_rect);
- }
-}
-
-void WebPluginDelegateImpl::SetFocus(bool focused) {
- DCHECK(windowless_);
- // This is called when internal WebKit focus (the focused element on the page)
- // changes, but plugins need to know about OS-level focus, so we have an extra
- // layer of focus tracking.
- //
- // On Windows, historically browsers did not set focus events to windowless
- // plugins when the toplevel window focus changes. Sending such focus events
- // breaks full screen mode in Flash because it will come out of full screen
- // mode when it loses focus, and its full screen window causes the browser to
- // lose focus.
- has_webkit_focus_ = focused;
-#if !defined(OS_WIN)
- if (containing_view_has_focus_)
- SetPluginHasFocus(focused);
-#else
- SetPluginHasFocus(focused);
-#endif
-}
-
-void WebPluginDelegateImpl::SetPluginHasFocus(bool focused) {
- if (focused == plugin_has_focus_)
- return;
- if (PlatformSetPluginHasFocus(focused))
- plugin_has_focus_ = focused;
-}
-
-void WebPluginDelegateImpl::SetContentAreaHasFocus(bool has_focus) {
- containing_view_has_focus_ = has_focus;
- if (!windowless_)
- return;
-#if !defined(OS_WIN) // See SetFocus above.
- SetPluginHasFocus(containing_view_has_focus_ && has_webkit_focus_);
-#endif
-}
-
-NPObject* WebPluginDelegateImpl::GetPluginScriptableObject() {
- return instance_->GetPluginScriptableObject();
-}
-
-NPP WebPluginDelegateImpl::GetPluginNPP() {
- return instance_->npp();
-}
-
-bool WebPluginDelegateImpl::GetFormValue(base::string16* value) {
- return instance_->GetFormValue(value);
-}
-
-int WebPluginDelegateImpl::GetProcessId() {
- // We are in process, so the plugin pid is this current process pid.
- return base::GetCurrentProcId();
-}
-
-base::FilePath WebPluginDelegateImpl::GetPluginPath() {
- return instance()->plugin_lib()->plugin_info().path;
-}
-
-void WebPluginDelegateImpl::WindowedUpdateGeometry(
- const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect) {
- if (WindowedReposition(window_rect, clip_rect) ||
- !windowed_did_set_window_) {
- // Let the plugin know that it has been moved
- WindowedSetWindow();
- }
-}
-
-bool WebPluginDelegateImpl::HandleInputEvent(
- const WebInputEvent& event,
- WebCursor::CursorInfo* cursor_info) {
- DCHECK(windowless_) << "events should only be received in windowless mode";
-
- bool pop_user_gesture = false;
- if (IsUserGesture(event)) {
- pop_user_gesture = true;
- instance()->PushPopupsEnabledState(true);
- }
-
- bool handled = PlatformHandleInputEvent(event, cursor_info);
-
- if (pop_user_gesture) {
- instance()->PopPopupsEnabledState();
- }
-
- return handled;
-}
-
-bool WebPluginDelegateImpl::IsUserGesture(const WebInputEvent& event) {
- switch (event.type) {
- case WebInputEvent::MouseDown:
- case WebInputEvent::MouseUp:
- case WebInputEvent::KeyDown:
- case WebInputEvent::KeyUp:
- return true;
- default:
- return false;
- }
-}
-
-} // namespace content
diff --git a/chromium/content/child/npapi/webplugin_delegate_impl.h b/chromium/content/child/npapi/webplugin_delegate_impl.h
deleted file mode 100644
index f6dae166e95..00000000000
--- a/chromium/content/child/npapi/webplugin_delegate_impl.h
+++ /dev/null
@@ -1,449 +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_CHILD_NPAPI_WEBPLUGIN_DELEGATE_IMPL_H_
-#define CONTENT_CHILD_NPAPI_WEBPLUGIN_DELEGATE_IMPL_H_
-
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/sequenced_task_runner_helpers.h"
-#include "base/timer/timer.h"
-#include "build/build_config.h"
-#include "content/child/npapi/webplugin_delegate.h"
-#include "content/common/cursors/webcursor.h"
-#include "third_party/npapi/bindings/npapi.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/native_widget_types.h"
-
-namespace base {
-class FilePath;
-}
-
-#if defined(OS_MACOSX)
-#ifdef __OBJC__
-@class CALayer;
-@class CARenderer;
-#else
-class CALayer;
-class CARenderer;
-#endif
-#endif
-
-namespace content {
-class PluginInstance;
-class WebPlugin;
-
-#if defined(OS_MACOSX)
-class WebPluginAcceleratedSurface;
-class ExternalDragTracker;
-#endif // OS_MACOSX
-
-#if defined(OS_WIN)
-class WebPluginIMEWin;
-#endif // OS_WIN
-
-// An implementation of WebPluginDelegate that runs in the plugin process,
-// proxied from the renderer by WebPluginDelegateProxy.
-class WebPluginDelegateImpl : public WebPluginDelegate {
- public:
- enum PluginQuirks {
- PLUGIN_QUIRK_SETWINDOW_TWICE = 1, // Win32
- PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE = 2, // Win32
- PLUGIN_QUIRK_DONT_CALL_WND_PROC_RECURSIVELY = 4, // Win32
- PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY = 8, // Win32
- PLUGIN_QUIRK_DONT_ALLOW_MULTIPLE_INSTANCES = 16, // Win32
- PLUGIN_QUIRK_DIE_AFTER_UNLOAD = 32, // Win32
- PLUGIN_QUIRK_PATCH_SETCURSOR = 64, // Win32
- PLUGIN_QUIRK_BLOCK_NONSTANDARD_GETURL_REQUESTS = 128, // Win32
- PLUGIN_QUIRK_WINDOWLESS_OFFSET_WINDOW_TO_DRAW = 256, // Linux
- PLUGIN_QUIRK_WINDOWLESS_INVALIDATE_AFTER_SET_WINDOW = 512, // Linux
- PLUGIN_QUIRK_NO_WINDOWLESS = 1024, // Windows
- PLUGIN_QUIRK_PATCH_REGENUMKEYEXW = 2048, // Windows
- PLUGIN_QUIRK_ALWAYS_NOTIFY_SUCCESS = 4096, // Windows
- PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE = 16384, // Windows
- PLUGIN_QUIRK_WINDOWLESS_NO_RIGHT_CLICK = 32768, // Linux
- PLUGIN_QUIRK_IGNORE_FIRST_SETWINDOW_CALL = 65536, // Windows.
- PLUGIN_QUIRK_EMULATE_IME = 131072, // Windows.
- PLUGIN_QUIRK_FAKE_WINDOW_FROM_POINT = 262144, // Windows.
- PLUGIN_QUIRK_COPY_STREAM_DATA = 524288, // All platforms
- };
-
- static WebPluginDelegateImpl* Create(WebPlugin* plugin,
- const base::FilePath& filename,
- const std::string& mime_type);
-
- // WebPluginDelegate implementation
- bool Initialize(const GURL& url,
- const std::vector<std::string>& arg_names,
- const std::vector<std::string>& arg_values,
- bool load_manually) override;
- void PluginDestroyed() override;
- void UpdateGeometry(const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect) override;
- void Paint(SkCanvas* canvas, const gfx::Rect& rect) override;
- void SetFocus(bool focused) override;
- bool HandleInputEvent(const blink::WebInputEvent& event,
- WebCursor::CursorInfo* cursor_info) override;
- NPObject* GetPluginScriptableObject() override;
- NPP GetPluginNPP() override;
- bool GetFormValue(base::string16* value) override;
- int GetProcessId() override;
- // End of WebPluginDelegate implementation.
-
- gfx::PluginWindowHandle windowed_handle() const { return windowed_handle_; }
- bool IsWindowless() const { return windowless_; }
- PluginInstance* instance() { return instance_.get(); }
- gfx::Rect GetRect() const { return window_rect_; }
- gfx::Rect GetClipRect() const { return clip_rect_; }
-
- // Returns the path for the library implementing this plugin.
- base::FilePath GetPluginPath();
-
- // Returns a combination of PluginQuirks.
- int GetQuirks() const { return quirks_; }
-
- // Informs the plugin that the view it is in has gained or lost focus.
- void SetContentAreaHasFocus(bool has_focus);
-
-#if defined(OS_WIN)
- // Informs the plugin that an IME has changed its status.
- void ImeCompositionUpdated(const base::string16& text,
- const std::vector<int>& clauses,
- const std::vector<int>& target,
- int cursor_position);
-
- // Informs the plugin that IME composition has completed./ If |text| is empty,
- // IME was cancelled.
- void ImeCompositionCompleted(const base::string16& text);
-
- // Returns the IME status retrieved from a plugin.
- bool GetIMEStatus(int* input_type, gfx::Rect* caret_rect);
-#endif
-
-#if defined(OS_MACOSX) && !defined(USE_AURA)
- // Informs the plugin that the geometry has changed, as with UpdateGeometry,
- // but also includes the new buffer context for that new geometry.
- void UpdateGeometryAndContext(const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect,
- gfx::NativeDrawingContext context);
- // Informs the delegate that the plugin called NPN_Invalidate*. Used as a
- // trigger for Core Animation drawing.
- void PluginDidInvalidate();
- // Returns the delegate currently processing events.
- static WebPluginDelegateImpl* GetActiveDelegate();
- // Informs the plugin that the window it is in has gained or lost focus.
- void SetWindowHasFocus(bool has_focus);
- // Informs the plugin that its tab or window has been hidden or shown.
- void SetContainerVisibility(bool is_visible);
- // Informs the plugin that its containing window's frame has changed.
- // Frames are in screen coordinates.
- void WindowFrameChanged(const gfx::Rect& window_frame,
- const gfx::Rect& view_frame);
- // Informs the plugin that IME composition has completed.
- // If |text| is empty, IME was cancelled.
- void ImeCompositionCompleted(const base::string16& text);
- // Informs the delegate that the plugin set a Cocoa NSCursor.
- void SetNSCursor(NSCursor* cursor);
-
- // Indicates that the windowless plugins will draw directly to the window
- // context instead of a buffer context.
- void SetNoBufferContext();
-
- // TODO(caryclark): This is a temporary workaround to allow the Darwin / Skia
- // port to share code with the Darwin / CG port. Later, this will be removed
- // and all callers will use the Paint defined above.
- void CGPaint(CGContextRef context, const gfx::Rect& rect);
-#endif // OS_MACOSX && !USE_AURA
-
- private:
- friend class base::DeleteHelper<WebPluginDelegateImpl>;
- friend class WebPluginDelegate;
-
- WebPluginDelegateImpl(WebPlugin* plugin, PluginInstance* instance);
- ~WebPluginDelegateImpl() override;
-
- // Called by Initialize() for platform-specific initialization.
- // If this returns false, the plugin shouldn't be started--see Initialize().
- bool PlatformInitialize();
-
- // Called by DestroyInstance(), used for platform-specific destruction.
- void PlatformDestroyInstance();
-
- //--------------------------
- // used for windowed plugins
- void WindowedUpdateGeometry(const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect);
- // Create the native window.
- // Returns true if the window is created (or already exists).
- // Returns false if unable to create the window.
- bool WindowedCreatePlugin();
-
- // Destroy the native window.
- void WindowedDestroyWindow();
-
- // Reposition the native window to be in sync with the given geometry.
- // Returns true if the native window has moved or been clipped differently.
- bool WindowedReposition(const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect);
-
- // Tells the plugin about the current state of the window.
- // See NPAPI NPP_SetWindow for more information.
- void WindowedSetWindow();
-
-#if defined(OS_WIN)
- // Registers the window class for our window
- ATOM RegisterNativeWindowClass();
-
- // Our WndProc functions.
- static LRESULT CALLBACK WrapperWindowProc(
- HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
- static LRESULT CALLBACK NativeWndProc(
- HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
- static LRESULT CALLBACK FlashWindowlessWndProc(
- HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
- static LRESULT CALLBACK DummyWindowProc(
- HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
-
- // Used for throttling Flash messages.
- static void ClearThrottleQueueForWindow(HWND window);
- static void OnThrottleMessage();
- static void ThrottleMessage(WNDPROC proc, HWND hwnd, UINT message,
- WPARAM wParam, LPARAM lParam);
-#endif
-
- //----------------------------
- // used for windowless plugins
- void WindowlessUpdateGeometry(const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect);
- void WindowlessPaint(gfx::NativeDrawingContext hdc, const gfx::Rect& rect);
-
- // Tells the plugin about the current state of the window.
- // See NPAPI NPP_SetWindow for more information.
- void WindowlessSetWindow();
-
- // Informs the plugin that it has gained or lost keyboard focus (on the Mac,
- // this just means window first responder status).
- void SetPluginHasFocus(bool focused);
-
- // Handles the platform specific details of setting plugin focus. Returns
- // false if the platform cancelled the focus tranfer.
- bool PlatformSetPluginHasFocus(bool focused);
-
- //-----------------------------------------
- // used for windowed and windowless plugins
-
- // Does platform-specific event handling. Arguments and return are identical
- // to HandleInputEvent.
- bool PlatformHandleInputEvent(const blink::WebInputEvent& event,
- WebCursor::CursorInfo* cursor_info);
-
- // Closes down and destroys our plugin instance.
- void DestroyInstance();
-
-
- // used for windowed plugins
- // Note: on Mac OS X, the only time the windowed handle is non-zero
- // is the case of accelerated rendering, which uses a fake window handle to
- // identify itself back to the browser. It still performs all of its
- // work offscreen.
- gfx::PluginWindowHandle windowed_handle_;
- gfx::Rect windowed_last_pos_;
-
- bool windowed_did_set_window_;
-
- // used by windowed and windowless plugins
- bool windowless_;
-
- WebPlugin* plugin_;
- scoped_refptr<PluginInstance> instance_;
-
-#if defined(OS_WIN)
- // Original wndproc before we subclassed.
- WNDPROC plugin_wnd_proc_;
-
- // Used to throttle WM_USER+1 messages in Flash.
- uint32_t last_message_;
- bool is_calling_wndproc;
-
- // An IME emulator used by a windowless plugin to retrieve IME data through
- // IMM32 functions.
- scoped_ptr<WebPluginIMEWin> plugin_ime_;
-#endif // defined(OS_WIN)
-
- NPWindow window_;
- gfx::Rect window_rect_;
- gfx::Rect clip_rect_;
- int quirks_;
-
-#if defined(OS_WIN)
- // Windowless plugins don't have keyboard focus causing issues with the
- // plugin not receiving keyboard events if the plugin enters a modal
- // loop like TrackPopupMenuEx or MessageBox, etc.
- // This is a basic issue with windows activation and focus arising due to
- // the fact that these windows are created by different threads. Activation
- // and focus are thread specific states, and if the browser has focus,
- // the plugin may not have focus.
- // To fix a majority of these activation issues we create a dummy visible
- // child window to which we set focus whenever the windowless plugin
- // receives a WM_LBUTTONDOWN/WM_RBUTTONDOWN message via NPP_HandleEvent.
-
- HWND dummy_window_for_activation_;
- HWND dummy_window_parent_;
- WNDPROC old_dummy_window_proc_;
- bool CreateDummyWindowForActivation();
-
- // Returns true if the event passed in needs to be tracked for a potential
- // modal loop.
- static bool ShouldTrackEventForModalLoops(NPEvent* event);
-
- // The message filter hook procedure, which tracks modal loops entered by
- // a plugin in the course of a NPP_HandleEvent call.
- static LRESULT CALLBACK HandleEventMessageFilterHook(int code, WPARAM wParam,
- LPARAM lParam);
-
- // TrackPopupMenu interceptor. Parameters are the same as the Win32 function
- // TrackPopupMenu.
- static BOOL WINAPI TrackPopupMenuPatch(HMENU menu, unsigned int flags, int x,
- int y, int reserved, HWND window,
- const RECT* rect);
-
- // SetCursor interceptor for windowless plugins.
- static HCURSOR WINAPI SetCursorPatch(HCURSOR cursor);
-
- // RegEnumKeyExW interceptor.
- static LONG WINAPI RegEnumKeyExWPatch(
- HKEY key, DWORD index, LPWSTR name, LPDWORD name_size, LPDWORD reserved,
- LPWSTR class_name, LPDWORD class_size, PFILETIME last_write_time);
-
- // GetProcAddress intercepter for windowless plugins.
- static FARPROC WINAPI GetProcAddressPatch(HMODULE module, LPCSTR name);
-
- // WindowFromPoint patch for Flash windowless plugins. When flash receives
- // mouse move messages it calls the WindowFromPoint API to eventually convert
- // the mouse coordinates to screen. We need to return the dummy plugin parent
- // window for Aura to ensure that these conversions occur correctly.
- static HWND WINAPI WindowFromPointPatch(POINT point);
-
- // The mouse hook proc which handles mouse capture in windowed plugins.
- static LRESULT CALLBACK MouseHookProc(int code, WPARAM wParam,
- LPARAM lParam);
-
- // Calls SetCapture/ReleaseCapture based on the message type.
- static void HandleCaptureForMessage(HWND window, UINT message);
-
-#elif defined(OS_MACOSX) && !defined(USE_AURA)
- // Sets window_rect_ to |rect|
- void SetPluginRect(const gfx::Rect& rect);
- // Sets content_area_origin to |origin|
- void SetContentAreaOrigin(const gfx::Point& origin);
- // Updates everything that depends on the plugin's absolute screen location.
- void PluginScreenLocationChanged();
- // Updates anything that depends on plugin visibility.
- void PluginVisibilityChanged();
-
- // Starts an IME session.
- void StartIme();
-
- // Informs the browser about the updated accelerated drawing surface.
- void UpdateAcceleratedSurface();
-
- // Uses a CARenderer to draw the plugin's layer in our OpenGL surface.
- void DrawLayerInSurface();
-
- bool use_buffer_context_;
- CGContextRef buffer_context_; // Weak ref.
-
- CALayer* layer_; // Used for CA drawing mode. Weak, retained by plugin.
- WebPluginAcceleratedSurface* surface_; // Weak ref.
- CARenderer* renderer_; // Renders layer_ to surface_.
- scoped_ptr<base::RepeatingTimer> redraw_timer_;
-
- // The upper-left corner of the web content area in screen coordinates,
- // relative to an upper-left (0,0).
- gfx::Point content_area_origin_;
-
- bool containing_window_has_focus_;
- bool initial_window_focus_;
- bool container_is_visible_;
- bool have_called_set_window_;
-
- gfx::Rect cached_clip_rect_;
-
- bool ime_enabled_;
- int keyup_ignore_count_;
-
- scoped_ptr<ExternalDragTracker> external_drag_tracker_;
-#endif // OS_MACOSX && !USE_AURA
-
- // Called by the message filter hook when the plugin enters a modal loop.
- void OnModalLoopEntered();
-
- // Returns true if the message passed in corresponds to a user gesture.
- static bool IsUserGesture(const blink::WebInputEvent& event);
-
- // The url with which the plugin was instantiated.
- std::string plugin_url_;
-
-#if defined(OS_WIN)
- // Indicates the end of a user gesture period.
- void OnUserGestureEnd();
-
- // Handle to the message filter hook
- HHOOK handle_event_message_filter_hook_;
-
- // Event which is set when the plugin enters a modal loop in the course
- // of a NPP_HandleEvent call.
- HANDLE handle_event_pump_messages_event_;
-
- // This flag indicates whether we started tracking a user gesture message.
- bool user_gesture_message_posted_;
-
- // Handle to the mouse hook installed for certain windowed plugins like
- // flash.
- HHOOK mouse_hook_;
-#endif
-
- // Holds the depth of the HandleEvent callstack.
- int handle_event_depth_;
-
- // Holds the current cursor set by the windowless plugin.
- WebCursor current_windowless_cursor_;
-
- // Set to true initially and indicates if this is the first npp_setwindow
- // call received by the plugin.
- bool first_set_window_call_;
-
- // True if the plugin thinks it has keyboard focus
- bool plugin_has_focus_;
- // True if the plugin element has focus within the web content, regardless of
- // whether its containing view currently has focus.
- bool has_webkit_focus_;
- // True if the containing view currently has focus.
- // Initially set to true so that plugin focus still works in environments
- // where SetContentAreaHasFocus is never called. See
- // https://bugs.webkit.org/show_bug.cgi?id=46013 for details.
- bool containing_view_has_focus_;
-
- // True if NPP_New did not return an error.
- bool creation_succeeded_;
-
-#if defined(OS_WIN)
- // Runnable Method Factory used to invoke the OnUserGestureEnd method
- // asynchronously.
- base::WeakPtrFactory<WebPluginDelegateImpl> user_gesture_msg_factory_;
-#endif
-
- DISALLOW_COPY_AND_ASSIGN(WebPluginDelegateImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_NPAPI_WEBPLUGIN_DELEGATE_IMPL_H_
diff --git a/chromium/content/child/npapi/webplugin_delegate_impl_android.cc b/chromium/content/child/npapi/webplugin_delegate_impl_android.cc
deleted file mode 100644
index ed562b3624a..00000000000
--- a/chromium/content/child/npapi/webplugin_delegate_impl_android.cc
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/child/npapi/webplugin_delegate_impl.h"
-
-#include <string.h>
-
-#include "base/logging.h"
-#include "content/child/npapi/plugin_instance.h"
-#include "content/child/npapi/webplugin.h"
-#include "content/common/cursors/webcursor.h"
-
-using blink::WebInputEvent;
-
-namespace content {
-
-WebPluginDelegateImpl::WebPluginDelegateImpl(
- WebPlugin* plugin,
- PluginInstance* instance)
- : windowed_handle_(0),
- windowed_did_set_window_(false),
- windowless_(false),
- plugin_(plugin),
- instance_(instance),
- quirks_(0),
- handle_event_depth_(0),
- first_set_window_call_(true) {
- memset(&window_, 0, sizeof(window_));
-}
-
-WebPluginDelegateImpl::~WebPluginDelegateImpl() {
-}
-
-bool WebPluginDelegateImpl::PlatformInitialize() {
- return true;
-}
-
-void WebPluginDelegateImpl::PlatformDestroyInstance() {
- // Nothing to do here.
-}
-
-void WebPluginDelegateImpl::Paint(SkCanvas* canvas, const gfx::Rect& rect) {
-}
-
-bool WebPluginDelegateImpl::WindowedCreatePlugin() {
- return false;
-}
-
-void WebPluginDelegateImpl::WindowedDestroyWindow() {
-}
-
-bool WebPluginDelegateImpl::WindowedReposition(
- const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect) {
- return false;
-}
-
-void WebPluginDelegateImpl::WindowedSetWindow() {
-}
-
-void WebPluginDelegateImpl::WindowlessUpdateGeometry(
- const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect) {
-}
-
-void WebPluginDelegateImpl::WindowlessPaint(gfx::NativeDrawingContext context,
- const gfx::Rect& damage_rect) {
-}
-
-bool WebPluginDelegateImpl::PlatformSetPluginHasFocus(bool focused) {
- return false;
-}
-
-bool WebPluginDelegateImpl::PlatformHandleInputEvent(
- const WebInputEvent& event, WebCursor::CursorInfo* cursor_info) {
- return false;
-}
-
-} // content
diff --git a/chromium/content/child/npapi/webplugin_delegate_impl_aura.cc b/chromium/content/child/npapi/webplugin_delegate_impl_aura.cc
deleted file mode 100644
index a700e7c44ca..00000000000
--- a/chromium/content/child/npapi/webplugin_delegate_impl_aura.cc
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/child/npapi/webplugin_delegate_impl.h"
-
-#include "content/child/npapi/plugin_instance.h"
-#include "content/common/cursors/webcursor.h"
-
-using blink::WebInputEvent;
-
-namespace content {
-
-WebPluginDelegateImpl::WebPluginDelegateImpl(WebPlugin* plugin,
- PluginInstance* instance) {
-}
-
-WebPluginDelegateImpl::~WebPluginDelegateImpl() {
-}
-
-bool WebPluginDelegateImpl::PlatformInitialize() {
- return true;
-}
-
-void WebPluginDelegateImpl::PlatformDestroyInstance() {
- // Nothing to do here.
-}
-
-void WebPluginDelegateImpl::Paint(SkCanvas* canvas, const gfx::Rect& rect) {
-}
-
-bool WebPluginDelegateImpl::WindowedCreatePlugin() {
- return true;
-}
-
-void WebPluginDelegateImpl::WindowedDestroyWindow() {
-}
-
-bool WebPluginDelegateImpl::WindowedReposition(
- const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect) {
- return true;
-}
-
-void WebPluginDelegateImpl::WindowedSetWindow() {
-}
-
-void WebPluginDelegateImpl::WindowlessUpdateGeometry(
- const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect) {
-}
-
-void WebPluginDelegateImpl::WindowlessPaint(gfx::NativeDrawingContext context,
- const gfx::Rect& damage_rect) {
-}
-
-bool WebPluginDelegateImpl::PlatformSetPluginHasFocus(bool focused) {
- return true;
-}
-
-bool WebPluginDelegateImpl::PlatformHandleInputEvent(
- const WebInputEvent& event, WebCursor::CursorInfo* cursor_info) {
- return false;
-}
-
-} // namespace content
diff --git a/chromium/content/child/npapi/webplugin_delegate_impl_mac.mm b/chromium/content/child/npapi/webplugin_delegate_impl_mac.mm
deleted file mode 100644
index 4a39d1d7e75..00000000000
--- a/chromium/content/child/npapi/webplugin_delegate_impl_mac.mm
+++ /dev/null
@@ -1,726 +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/child/npapi/webplugin_delegate_impl.h"
-
-#import <Cocoa/Cocoa.h>
-#import <QuartzCore/QuartzCore.h>
-#include <stdint.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <set>
-#include <string>
-
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_util.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/child/npapi/plugin_instance.h"
-#include "content/child/npapi/plugin_lib.h"
-#include "content/child/npapi/plugin_web_event_converter_mac.h"
-#include "content/child/npapi/webplugin.h"
-#include "content/child/npapi/webplugin_accelerated_surface_mac.h"
-#include "content/common/cursors/webcursor.h"
-#include "skia/ext/skia_utils_mac.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
-
-using blink::WebKeyboardEvent;
-using blink::WebInputEvent;
-using blink::WebMouseEvent;
-using blink::WebMouseWheelEvent;
-
-// Important implementation notes: The Mac definition of NPAPI, particularly
-// the distinction between windowed and windowless modes, differs from the
-// Windows and Linux definitions. Most of those differences are
-// accomodated by the WebPluginDelegate class.
-
-namespace content {
-
-namespace {
-
-const int kCoreAnimationRedrawPeriodMs = 10; // 100 Hz
-
-WebPluginDelegateImpl* g_active_delegate;
-
-// Helper to simplify correct usage of g_active_delegate. Instantiating will
-// set the active delegate to |delegate| for the lifetime of the object, then
-// NULL when it goes out of scope.
-class ScopedActiveDelegate {
- public:
- explicit ScopedActiveDelegate(WebPluginDelegateImpl* delegate) {
- g_active_delegate = delegate;
- }
- ~ScopedActiveDelegate() {
- g_active_delegate = NULL;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ScopedActiveDelegate);
-};
-
-} // namespace
-
-// Helper to build and maintain a model of a drag entering the plugin but not
-// starting there. See explanation in PlatformHandleInputEvent.
-class ExternalDragTracker {
- public:
- ExternalDragTracker() : pressed_buttons_(0) {}
-
- // Returns true if an external drag is in progress.
- bool IsDragInProgress() { return pressed_buttons_ != 0; };
-
- // Returns true if the given event appears to be related to an external drag.
- bool EventIsRelatedToDrag(const WebInputEvent& event);
-
- // Updates the tracking of whether an external drag is in progress--and if
- // so what buttons it involves--based on the given event.
- void UpdateDragStateFromEvent(const WebInputEvent& event);
-
- private:
- // Returns the mask for just the button state in a WebInputEvent's modifiers.
- static int WebEventButtonModifierMask();
-
- // The WebInputEvent modifier flags for any buttons that were down when an
- // external drag entered the plugin, and which and are still down now.
- int pressed_buttons_;
-
- DISALLOW_COPY_AND_ASSIGN(ExternalDragTracker);
-};
-
-void ExternalDragTracker::UpdateDragStateFromEvent(const WebInputEvent& event) {
- switch (event.type) {
- case WebInputEvent::MouseEnter:
- pressed_buttons_ = event.modifiers & WebEventButtonModifierMask();
- break;
- case WebInputEvent::MouseUp: {
- const WebMouseEvent* mouse_event =
- static_cast<const WebMouseEvent*>(&event);
- if (mouse_event->button == WebMouseEvent::ButtonLeft)
- pressed_buttons_ &= ~WebInputEvent::LeftButtonDown;
- if (mouse_event->button == WebMouseEvent::ButtonMiddle)
- pressed_buttons_ &= ~WebInputEvent::MiddleButtonDown;
- if (mouse_event->button == WebMouseEvent::ButtonRight)
- pressed_buttons_ &= ~WebInputEvent::RightButtonDown;
- break;
- }
- default:
- break;
- }
-}
-
-bool ExternalDragTracker::EventIsRelatedToDrag(const WebInputEvent& event) {
- const WebMouseEvent* mouse_event = static_cast<const WebMouseEvent*>(&event);
- switch (event.type) {
- case WebInputEvent::MouseUp:
- // We only care about release of buttons that were part of the drag.
- return ((mouse_event->button == WebMouseEvent::ButtonLeft &&
- (pressed_buttons_ & WebInputEvent::LeftButtonDown)) ||
- (mouse_event->button == WebMouseEvent::ButtonMiddle &&
- (pressed_buttons_ & WebInputEvent::MiddleButtonDown)) ||
- (mouse_event->button == WebMouseEvent::ButtonRight &&
- (pressed_buttons_ & WebInputEvent::RightButtonDown)));
- case WebInputEvent::MouseEnter:
- return (event.modifiers & WebEventButtonModifierMask()) != 0;
- case WebInputEvent::MouseLeave:
- case WebInputEvent::MouseMove: {
- int event_buttons = (event.modifiers & WebEventButtonModifierMask());
- return (pressed_buttons_ &&
- pressed_buttons_ == event_buttons);
- }
- default:
- return false;
- }
- return false;
-}
-
-int ExternalDragTracker::WebEventButtonModifierMask() {
- return WebInputEvent::LeftButtonDown |
- WebInputEvent::RightButtonDown |
- WebInputEvent::MiddleButtonDown;
-}
-
-#pragma mark -
-#pragma mark Core WebPluginDelegate implementation
-
-WebPluginDelegateImpl::WebPluginDelegateImpl(
- WebPlugin* plugin,
- PluginInstance* instance)
- : windowed_handle_(gfx::kNullPluginWindow),
- // all Mac plugins are "windowless" in the Windows/X11 sense
- windowless_(true),
- plugin_(plugin),
- instance_(instance),
- quirks_(0),
- use_buffer_context_(true),
- buffer_context_(NULL),
- layer_(nil),
- surface_(NULL),
- renderer_(nil),
- containing_window_has_focus_(false),
- initial_window_focus_(false),
- container_is_visible_(false),
- have_called_set_window_(false),
- ime_enabled_(false),
- keyup_ignore_count_(0),
- external_drag_tracker_(new ExternalDragTracker()),
- handle_event_depth_(0),
- first_set_window_call_(true),
- plugin_has_focus_(false),
- has_webkit_focus_(false),
- containing_view_has_focus_(true),
- creation_succeeded_(false) {
- memset(&window_, 0, sizeof(window_));
- instance->set_windowless(true);
-}
-
-WebPluginDelegateImpl::~WebPluginDelegateImpl() {
- DestroyInstance();
-}
-
-bool WebPluginDelegateImpl::PlatformInitialize() {
- // Don't set a NULL window handle on destroy for Mac plugins. This matches
- // Safari and other Mac browsers (see PluginView::stop() in PluginView.cpp,
- // where code to do so is surrounded by an #ifdef that excludes Mac OS X, or
- // destroyPlugin in WebNetscapePluginView.mm, for examples).
- quirks_ |= PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY;
-
- // Mac plugins don't expect to be unloaded, and they don't always do so
- // cleanly, so don't unload them at shutdown.
- instance()->plugin_lib()->PreventLibraryUnload();
-
-#ifndef NP_NO_CARBON
- if (instance()->event_model() == NPEventModelCarbon)
- return false;
-#endif
-
- window_.type = NPWindowTypeDrawable;
- NPDrawingModel drawing_model = instance()->drawing_model();
- switch (drawing_model) {
-#ifndef NP_NO_QUICKDRAW
- case NPDrawingModelQuickDraw:
- return false;
-#endif
- case NPDrawingModelCoreGraphics:
- break;
- case NPDrawingModelCoreAnimation:
- case NPDrawingModelInvalidatingCoreAnimation: {
- // Ask the plugin for the CALayer it created for rendering content.
- // Create a surface to host it, and request a "window" handle to identify
- // the surface.
- CALayer* layer = nil;
- NPError err = instance()->NPP_GetValue(NPPVpluginCoreAnimationLayer,
- reinterpret_cast<void*>(&layer));
- if (!err) {
- if (drawing_model == NPDrawingModelCoreAnimation) {
- // Create the timer; it will be started when we get a window handle.
- redraw_timer_.reset(new base::RepeatingTimer);
- }
- layer_ = layer;
-
- gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
- // On dual GPU systems, force the use of the discrete GPU for
- // the CARenderer underlying our Core Animation backend for
- // all plugins except Flash. For some reason Unity3D's output
- // doesn't show up if the integrated GPU is used. Safari keeps
- // even Flash 11 with Stage3D on the integrated GPU, so mirror
- // that behavior here.
- const WebPluginInfo& plugin_info =
- instance_->plugin_lib()->plugin_info();
- if (plugin_info.name.find(base::ASCIIToUTF16("Flash")) !=
- base::string16::npos)
- gpu_preference = gfx::PreferIntegratedGpu;
- surface_ = plugin_->GetAcceleratedSurface(gpu_preference);
-
- // If surface initialization fails for some reason, just continue
- // without any drawing; returning false would be a more confusing user
- // experience (since it triggers a missing plugin placeholder).
- if (surface_ && surface_->context()) {
- renderer_ = [[CARenderer rendererWithCGLContext:surface_->context()
- options:NULL] retain];
- [renderer_ setLayer:layer_];
- plugin_->AcceleratedPluginEnabledRendering();
- }
- }
- break;
- }
- default:
- NOTREACHED();
- break;
- }
-
- // Let the WebPlugin know that we are windowless, unless this is a Core
- // Animation plugin, in which case AcceleratedPluginEnabledRendering
- // calls SetWindow. Rendering breaks if SetWindow is called before
- // accelerated rendering is enabled.
- if (!layer_)
- plugin_->SetWindow(gfx::kNullPluginWindow);
-
- return true;
-}
-
-void WebPluginDelegateImpl::PlatformDestroyInstance() {
- if (redraw_timer_)
- redraw_timer_->Stop();
- [renderer_ release];
- renderer_ = nil;
- layer_ = nil;
-}
-
-void WebPluginDelegateImpl::UpdateGeometryAndContext(
- const gfx::Rect& window_rect, const gfx::Rect& clip_rect,
- CGContextRef context) {
- buffer_context_ = context;
- UpdateGeometry(window_rect, clip_rect);
-}
-
-void WebPluginDelegateImpl::Paint(SkCanvas* canvas, const gfx::Rect& rect) {
- skia::SkiaBitLocker bit_locker(canvas);
- CGContextRef context = bit_locker.cgContext();
- CGPaint(context, rect);
-}
-
-void WebPluginDelegateImpl::CGPaint(CGContextRef context,
- const gfx::Rect& rect) {
- WindowlessPaint(context, rect);
-}
-
-bool WebPluginDelegateImpl::PlatformHandleInputEvent(
- const WebInputEvent& event, WebCursor::CursorInfo* cursor_info) {
- DCHECK(cursor_info != NULL);
-
- // If an event comes in before the plugin has been set up, bail.
- if (!have_called_set_window_)
- return false;
-
- // WebKit sometimes sends spurious mouse move events when the window doesn't
- // have focus; Cocoa event model plugins don't expect to receive mouse move
- // events when they are in a background window, so drop those events.
- if (!containing_window_has_focus_ &&
- (event.type == WebInputEvent::MouseMove ||
- event.type == WebInputEvent::MouseEnter ||
- event.type == WebInputEvent::MouseLeave)) {
- return false;
- }
-
- if (WebInputEvent::isMouseEventType(event.type) ||
- event.type == WebInputEvent::MouseWheel) {
- // Check our plugin location before we send the event to the plugin, just
- // in case we somehow missed a plugin frame change.
- const WebMouseEvent* mouse_event =
- static_cast<const WebMouseEvent*>(&event);
- gfx::Point content_origin(
- mouse_event->globalX - mouse_event->x - window_rect_.x(),
- mouse_event->globalY - mouse_event->y - window_rect_.y());
- if (content_origin.x() != content_area_origin_.x() ||
- content_origin.y() != content_area_origin_.y()) {
- DLOG(WARNING) << "Stale plugin content area location: "
- << content_area_origin_.ToString() << " instead of "
- << content_origin.ToString();
- SetContentAreaOrigin(content_origin);
- }
-
- current_windowless_cursor_.GetCursorInfo(cursor_info);
- }
-
- // Per the Cocoa Plugin IME spec, plugins shoudn't receive keydown or keyup
- // events while composition is in progress. Treat them as handled, however,
- // since IME is consuming them on behalf of the plugin.
- if ((event.type == WebInputEvent::KeyDown && ime_enabled_) ||
- (event.type == WebInputEvent::KeyUp && keyup_ignore_count_)) {
- // Composition ends on a keydown, so ime_enabled_ will be false at keyup;
- // because the keydown wasn't sent to the plugin, the keyup shouldn't be
- // either (per the spec).
- if (event.type == WebInputEvent::KeyDown)
- ++keyup_ignore_count_;
- else
- --keyup_ignore_count_;
- return true;
- }
-
- ScopedActiveDelegate active_delegate(this);
-
- // Create the plugin event structure.
- scoped_ptr<PluginWebEventConverter> event_converter(
- new PluginWebEventConverter);
- if (!event_converter->InitWithEvent(event)) {
- // Silently consume any keyboard event types that aren't handled, so that
- // they don't fall through to the page.
- if (WebInputEvent::isKeyboardEventType(event.type))
- return true;
- return false;
- }
- NPCocoaEvent* plugin_event = event_converter->plugin_event();
-
- // The plugin host receives events related to drags starting outside the
- // plugin, but the NPAPI Cocoa event model spec says plugins shouldn't receive
- // them, so filter them out.
- // If WebKit adds a page capture mode (like the plugin capture mode that
- // handles drags starting inside) this can be removed.
- bool drag_related = external_drag_tracker_->EventIsRelatedToDrag(event);
- external_drag_tracker_->UpdateDragStateFromEvent(event);
- if (drag_related) {
- if (event.type == WebInputEvent::MouseUp &&
- !external_drag_tracker_->IsDragInProgress()) {
- // When an external drag ends, we need to synthesize a MouseEntered.
- NPCocoaEvent enter_event = *plugin_event;
- enter_event.type = NPCocoaEventMouseEntered;
- ScopedCurrentPluginEvent event_scope(instance(), &enter_event);
- instance()->NPP_HandleEvent(&enter_event);
- }
- return false;
- }
-
- // Send the plugin the event.
- scoped_ptr<ScopedCurrentPluginEvent> event_scope(
- new ScopedCurrentPluginEvent(instance(), plugin_event));
- int16_t handle_response = instance()->NPP_HandleEvent(plugin_event);
- bool handled = handle_response != kNPEventNotHandled;
-
- // Start IME if requested by the plugin.
- if (handled && handle_response == kNPEventStartIME &&
- event.type == WebInputEvent::KeyDown) {
- StartIme();
- ++keyup_ignore_count_;
- }
-
- // Plugins don't give accurate information about whether or not they handled
- // events, so browsers on the Mac ignore the return value.
- // Scroll events are the exception, since the Cocoa spec defines a meaning
- // for the return value.
- if (WebInputEvent::isMouseEventType(event.type)) {
- handled = true;
- } else if (WebInputEvent::isKeyboardEventType(event.type)) {
- // For Command-key events, trust the return value since eating all menu
- // shortcuts is not ideal.
- // TODO(stuartmorgan): Implement the advanced key handling spec, and trust
- // trust the key event return value from plugins that implement it.
- if (!(event.modifiers & WebInputEvent::MetaKey))
- handled = true;
- }
-
- return handled;
-}
-
-#pragma mark -
-
-void WebPluginDelegateImpl::WindowlessUpdateGeometry(
- const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect) {
- gfx::Rect old_clip_rect = clip_rect_;
- cached_clip_rect_ = clip_rect;
- if (container_is_visible_) // Remove check when cached_clip_rect_ is removed.
- clip_rect_ = clip_rect;
- bool clip_rect_changed = (clip_rect_ != old_clip_rect);
- bool window_size_changed = (window_rect.size() != window_rect_.size());
-
- if (window_rect == window_rect_ && !clip_rect_changed)
- return;
-
- if (old_clip_rect.IsEmpty() != clip_rect_.IsEmpty()) {
- PluginVisibilityChanged();
- }
-
- SetPluginRect(window_rect);
-
- if (window_size_changed || clip_rect_changed)
- WindowlessSetWindow();
-}
-
-void WebPluginDelegateImpl::WindowlessPaint(gfx::NativeDrawingContext context,
- const gfx::Rect& damage_rect) {
- // If we get a paint event before we are completely set up (e.g., a nested
- // call while the plugin is still in NPP_SetWindow), bail.
- if (!have_called_set_window_ || (use_buffer_context_ && !buffer_context_))
- return;
- DCHECK(!use_buffer_context_ || buffer_context_ == context);
-
- gfx::Rect paint_rect = damage_rect;
- if (use_buffer_context_) {
- // Plugin invalidates trigger asynchronous paints with the original
- // invalidation rect; the plugin may be resized before the paint is handled,
- // so we need to ensure that the damage rect is still sane.
- paint_rect.Intersect(
- gfx::Rect(0, 0, window_rect_.width(), window_rect_.height()));
- } else {
- // Use the actual window region when drawing directly to the window context.
- paint_rect.Intersect(window_rect_);
- }
-
- ScopedActiveDelegate active_delegate(this);
-
- CGContextSaveGState(context);
-
- if (!use_buffer_context_) {
- // Reposition the context origin so that plugins will draw at the correct
- // location in the window.
- CGContextClipToRect(context, paint_rect.ToCGRect());
- CGContextTranslateCTM(context, window_rect_.x(), window_rect_.y());
- }
-
- NPCocoaEvent paint_event;
- memset(&paint_event, 0, sizeof(NPCocoaEvent));
- paint_event.type = NPCocoaEventDrawRect;
- paint_event.data.draw.context = context;
- paint_event.data.draw.x = paint_rect.x();
- paint_event.data.draw.y = paint_rect.y();
- paint_event.data.draw.width = paint_rect.width();
- paint_event.data.draw.height = paint_rect.height();
- instance()->NPP_HandleEvent(&paint_event);
-
- if (use_buffer_context_) {
- // The backing buffer can change during the call to NPP_HandleEvent, in
- // which case the old context is (or is about to be) invalid.
- if (context == buffer_context_)
- CGContextRestoreGState(context);
- } else {
- // Always restore the context to the saved state.
- CGContextRestoreGState(context);
- }
-}
-
-void WebPluginDelegateImpl::WindowlessSetWindow() {
- if (!instance())
- return;
-
- window_.x = 0;
- window_.y = 0;
- window_.height = window_rect_.height();
- window_.width = window_rect_.width();
- window_.clipRect.left = clip_rect_.x();
- window_.clipRect.top = clip_rect_.y();
- window_.clipRect.right = clip_rect_.x() + clip_rect_.width();
- window_.clipRect.bottom = clip_rect_.y() + clip_rect_.height();
-
- NPError err = instance()->NPP_SetWindow(&window_);
-
- // Send an appropriate window focus event after the first SetWindow.
- if (!have_called_set_window_) {
- have_called_set_window_ = true;
- SetWindowHasFocus(initial_window_focus_);
- }
-
- DCHECK(err == NPERR_NO_ERROR);
-}
-
-#pragma mark -
-
-bool WebPluginDelegateImpl::WindowedCreatePlugin() {
- NOTREACHED();
- return false;
-}
-
-void WebPluginDelegateImpl::WindowedDestroyWindow() {
- NOTREACHED();
-}
-
-bool WebPluginDelegateImpl::WindowedReposition(const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect) {
- NOTREACHED();
- return false;
-}
-
-void WebPluginDelegateImpl::WindowedSetWindow() {
- NOTREACHED();
-}
-
-#pragma mark -
-#pragma mark Mac Extensions
-
-void WebPluginDelegateImpl::PluginDidInvalidate() {
- if (instance()->drawing_model() == NPDrawingModelInvalidatingCoreAnimation)
- DrawLayerInSurface();
-}
-
-WebPluginDelegateImpl* WebPluginDelegateImpl::GetActiveDelegate() {
- return g_active_delegate;
-}
-
-void WebPluginDelegateImpl::SetWindowHasFocus(bool has_focus) {
- // If we get a window focus event before calling SetWindow, just remember the
- // states (WindowlessSetWindow will then send it on the first call).
- if (!have_called_set_window_) {
- initial_window_focus_ = has_focus;
- return;
- }
-
- if (has_focus == containing_window_has_focus_)
- return;
- containing_window_has_focus_ = has_focus;
-
- ScopedActiveDelegate active_delegate(this);
- NPCocoaEvent focus_event;
- memset(&focus_event, 0, sizeof(focus_event));
- focus_event.type = NPCocoaEventWindowFocusChanged;
- focus_event.data.focus.hasFocus = has_focus;
- instance()->NPP_HandleEvent(&focus_event);
-}
-
-bool WebPluginDelegateImpl::PlatformSetPluginHasFocus(bool focused) {
- if (!have_called_set_window_)
- return false;
-
- plugin_->FocusChanged(focused);
-
- ScopedActiveDelegate active_delegate(this);
-
- NPCocoaEvent focus_event;
- memset(&focus_event, 0, sizeof(focus_event));
- focus_event.type = NPCocoaEventFocusChanged;
- focus_event.data.focus.hasFocus = focused;
- instance()->NPP_HandleEvent(&focus_event);
-
- return true;
-}
-
-void WebPluginDelegateImpl::SetContainerVisibility(bool is_visible) {
- if (is_visible == container_is_visible_)
- return;
- container_is_visible_ = is_visible;
-
- // TODO(stuartmorgan): This is a temporary workarond for
- // <http://crbug.com/34266>. When that is fixed, the cached_clip_rect_ code
- // should all be removed.
- if (is_visible) {
- clip_rect_ = cached_clip_rect_;
- } else {
- clip_rect_.set_width(0);
- clip_rect_.set_height(0);
- }
-
- // If the plugin is changing visibility, let the plugin know. If it's scrolled
- // off screen (i.e., cached_clip_rect_ is empty), then container visibility
- // doesn't change anything.
- if (!cached_clip_rect_.IsEmpty()) {
- PluginVisibilityChanged();
- WindowlessSetWindow();
- }
-
- // When the plugin become visible, send an empty invalidate. If there were any
- // pending invalidations this will trigger a paint event for the damaged
- // region, and if not it's a no-op. This is necessary since higher levels
- // that would normally do this weren't responsible for the clip_rect_ change).
- if (!clip_rect_.IsEmpty())
- instance()->webplugin()->InvalidateRect(gfx::Rect());
-}
-
-void WebPluginDelegateImpl::WindowFrameChanged(const gfx::Rect& window_frame,
- const gfx::Rect& view_frame) {
- instance()->set_window_frame(window_frame);
- SetContentAreaOrigin(gfx::Point(view_frame.x(), view_frame.y()));
-}
-
-void WebPluginDelegateImpl::ImeCompositionCompleted(
- const base::string16& text) {
- ime_enabled_ = false;
-
- // If |text| is empty this was just called to tell us composition was
- // cancelled externally (e.g., the user pressed esc).
- if (!text.empty()) {
- NPCocoaEvent text_event;
- memset(&text_event, 0, sizeof(NPCocoaEvent));
- text_event.type = NPCocoaEventTextInput;
- text_event.data.text.text =
- reinterpret_cast<NPNSString*>(base::SysUTF16ToNSString(text));
- instance()->NPP_HandleEvent(&text_event);
- }
-}
-
-void WebPluginDelegateImpl::SetNSCursor(NSCursor* cursor) {
- current_windowless_cursor_.InitFromNSCursor(cursor);
-}
-
-void WebPluginDelegateImpl::SetNoBufferContext() {
- use_buffer_context_ = false;
-}
-
-#pragma mark -
-#pragma mark Internal Tracking
-
-void WebPluginDelegateImpl::SetPluginRect(const gfx::Rect& rect) {
- bool plugin_size_changed = rect.width() != window_rect_.width() ||
- rect.height() != window_rect_.height();
- window_rect_ = rect;
- PluginScreenLocationChanged();
- if (plugin_size_changed)
- UpdateAcceleratedSurface();
-}
-
-void WebPluginDelegateImpl::SetContentAreaOrigin(const gfx::Point& origin) {
- content_area_origin_ = origin;
- PluginScreenLocationChanged();
-}
-
-void WebPluginDelegateImpl::PluginScreenLocationChanged() {
- gfx::Point plugin_origin(content_area_origin_.x() + window_rect_.x(),
- content_area_origin_.y() + window_rect_.y());
- instance()->set_plugin_origin(plugin_origin);
-}
-
-void WebPluginDelegateImpl::PluginVisibilityChanged() {
- if (instance()->drawing_model() == NPDrawingModelCoreAnimation) {
- bool plugin_visible = container_is_visible_ && !clip_rect_.IsEmpty();
- if (plugin_visible && !redraw_timer_->IsRunning()) {
- redraw_timer_->Start(FROM_HERE,
- base::TimeDelta::FromMilliseconds(kCoreAnimationRedrawPeriodMs),
- this, &WebPluginDelegateImpl::DrawLayerInSurface);
- } else if (!plugin_visible) {
- redraw_timer_->Stop();
- }
- }
-}
-
-void WebPluginDelegateImpl::StartIme() {
- if (ime_enabled_)
- return;
- ime_enabled_ = true;
- plugin_->StartIme();
-}
-
-#pragma mark -
-#pragma mark Core Animation Support
-
-void WebPluginDelegateImpl::DrawLayerInSurface() {
- // If we haven't plumbed up the surface yet, don't try to draw.
- if (!renderer_)
- return;
-
- [renderer_ beginFrameAtTime:CACurrentMediaTime() timeStamp:NULL];
- if (CGRectIsEmpty([renderer_ updateBounds])) {
- // If nothing has changed, we are done.
- [renderer_ endFrame];
- return;
- }
-
- surface_->StartDrawing();
-
- CGRect layerRect = [layer_ bounds];
- [renderer_ addUpdateRect:layerRect];
- [renderer_ render];
- [renderer_ endFrame];
-
- surface_->EndDrawing();
-}
-
-// Update the size of the surface to match the current size of the plugin.
-void WebPluginDelegateImpl::UpdateAcceleratedSurface() {
- if (!surface_ || !layer_)
- return;
-
- [CATransaction begin];
- [CATransaction setValue:[NSNumber numberWithInt:0]
- forKey:kCATransactionAnimationDuration];
- [layer_ setFrame:CGRectMake(0, 0,
- window_rect_.width(), window_rect_.height())];
- [CATransaction commit];
-
- [renderer_ setBounds:[layer_ bounds]];
- surface_->SetSize(window_rect_.size());
- // Kick off the drawing timer, if necessary.
- PluginVisibilityChanged();
-}
-
-} // namespace content
diff --git a/chromium/content/child/npapi/webplugin_delegate_impl_win.cc b/chromium/content/child/npapi/webplugin_delegate_impl_win.cc
deleted file mode 100644
index 5cd6e5c09cc..00000000000
--- a/chromium/content/child/npapi/webplugin_delegate_impl_win.cc
+++ /dev/null
@@ -1,1496 +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/child/npapi/webplugin_delegate_impl.h"
-
-#include <stdint.h>
-#include <string.h>
-
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/compiler_specific.h"
-#include "base/lazy_instance.h"
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/synchronization/lock.h"
-#include "base/version.h"
-#include "base/win/iat_patch_function.h"
-#include "base/win/registry.h"
-#include "base/win/windows_version.h"
-#include "content/child/npapi/plugin_instance.h"
-#include "content/child/npapi/plugin_lib.h"
-#include "content/child/npapi/webplugin.h"
-#include "content/child/npapi/webplugin_ime_win.h"
-#include "content/common/cursors/webcursor.h"
-#include "content/common/plugin_constants_win.h"
-#include "content/public/common/content_constants.h"
-#include "skia/ext/platform_canvas.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "ui/gfx/win/dpi.h"
-#include "ui/gfx/win/hwnd_util.h"
-
-using blink::WebKeyboardEvent;
-using blink::WebInputEvent;
-using blink::WebMouseEvent;
-
-namespace content {
-
-namespace {
-
-const wchar_t kWebPluginDelegateProperty[] = L"WebPluginDelegateProperty";
-
-// The fastest we are willing to process WM_USER+1 events for Flash.
-// Flash can easily exceed the limits of our CPU if we don't throttle it.
-// The throttle has been chosen by testing various delays and compromising
-// on acceptable Flash performance and reasonable CPU consumption.
-//
-// I'd like to make the throttle delay variable, based on the amount of
-// time currently required to paint Flash plugins. There isn't a good
-// way to count the time spent in aggregate plugin painting, however, so
-// this seems to work well enough.
-const int kFlashWMUSERMessageThrottleDelayMs = 5;
-
-// Flash displays popups in response to user clicks by posting a WM_USER
-// message to the plugin window. The handler for this message displays
-// the popup. To ensure that the popups allowed state is sent correctly
-// to the renderer we reset the popups allowed state in a timer.
-const int kWindowedPluginPopupTimerMs = 50;
-
-// The current instance of the plugin which entered the modal loop.
-WebPluginDelegateImpl* g_current_plugin_instance = NULL;
-
-typedef std::deque<MSG> ThrottleQueue;
-base::LazyInstance<ThrottleQueue> g_throttle_queue = LAZY_INSTANCE_INITIALIZER;
-
-base::LazyInstance<std::map<HWND, WNDPROC> > g_window_handle_proc_map =
- LAZY_INSTANCE_INITIALIZER;
-
-// Helper object for patching the TrackPopupMenu API.
-base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_track_popup_menu =
- LAZY_INSTANCE_INITIALIZER;
-
-// Helper object for patching the SetCursor API.
-base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_set_cursor =
- LAZY_INSTANCE_INITIALIZER;
-
-// Helper object for patching the RegEnumKeyExW API.
-base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_reg_enum_key_ex_w =
- LAZY_INSTANCE_INITIALIZER;
-
-// Helper object for patching the GetProcAddress API.
-base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_get_proc_address =
- LAZY_INSTANCE_INITIALIZER;
-
-base::LazyInstance<base::win::IATPatchFunction> g_iat_patch_window_from_point =
- LAZY_INSTANCE_INITIALIZER;
-
-// http://crbug.com/16114
-// Enforces providing a valid device context in NPWindow, so that NPP_SetWindow
-// is never called with NPNWindoTypeDrawable and NPWindow set to NULL.
-// Doing so allows removing NPP_SetWindow call during painting a windowless
-// plugin, which otherwise could trigger layout change while painting by
-// invoking NPN_Evaluate. Which would cause bad, bad crashes. Bad crashes.
-// TODO(dglazkov): If this approach doesn't produce regressions, move class to
-// webplugin_delegate_impl.h and implement for other platforms.
-class DrawableContextEnforcer {
- public:
- explicit DrawableContextEnforcer(NPWindow* window)
- : window_(window),
- disposable_dc_(window && !window->window) {
- // If NPWindow is NULL, create a device context with monochrome 1x1 surface
- // and stuff it to NPWindow.
- if (disposable_dc_)
- window_->window = CreateCompatibleDC(NULL);
- }
-
- ~DrawableContextEnforcer() {
- if (!disposable_dc_)
- return;
-
- DeleteDC(static_cast<HDC>(window_->window));
- window_->window = NULL;
- }
-
- private:
- NPWindow* window_;
- bool disposable_dc_;
-};
-
-// These are from ntddk.h
-typedef LONG NTSTATUS;
-
-#ifndef STATUS_SUCCESS
-#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
-#endif
-
-#ifndef STATUS_BUFFER_TOO_SMALL
-#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L)
-#endif
-
-typedef enum _KEY_INFORMATION_CLASS {
- KeyBasicInformation,
- KeyNodeInformation,
- KeyFullInformation,
- KeyNameInformation,
- KeyCachedInformation,
- KeyVirtualizationInformation
-} KEY_INFORMATION_CLASS;
-
-typedef struct _KEY_NAME_INFORMATION {
- ULONG NameLength;
- WCHAR Name[1];
-} KEY_NAME_INFORMATION, *PKEY_NAME_INFORMATION;
-
-typedef DWORD (__stdcall *ZwQueryKeyType)(
- HANDLE key_handle,
- int key_information_class,
- PVOID key_information,
- ULONG length,
- PULONG result_length);
-
-// Returns a key's full path.
-std::wstring GetKeyPath(HKEY key) {
- if (key == NULL)
- return L"";
-
- HMODULE dll = GetModuleHandle(L"ntdll.dll");
- if (dll == NULL)
- return L"";
-
- ZwQueryKeyType func = reinterpret_cast<ZwQueryKeyType>(
- ::GetProcAddress(dll, "ZwQueryKey"));
- if (func == NULL)
- return L"";
-
- DWORD size = 0;
- DWORD result = 0;
- result = func(key, KeyNameInformation, 0, 0, &size);
- if (result != static_cast<DWORD>(STATUS_BUFFER_TOO_SMALL))
- return L"";
-
- scoped_ptr<char[]> buffer(new char[size]);
- if (buffer.get() == NULL)
- return L"";
-
- result = func(key, KeyNameInformation, buffer.get(), size, &size);
- if (result != static_cast<DWORD>(STATUS_SUCCESS))
- return L"";
-
- KEY_NAME_INFORMATION* info =
- reinterpret_cast<KEY_NAME_INFORMATION*>(buffer.get());
- return std::wstring(info->Name, info->NameLength / sizeof(wchar_t));
-}
-
-uint32_t GetPluginMajorVersion(const WebPluginInfo& plugin_info) {
- Version plugin_version;
- WebPluginInfo::CreateVersionFromString(plugin_info.version, &plugin_version);
-
- uint32_t major_version = 0;
- if (plugin_version.IsValid())
- major_version = plugin_version.components()[0];
-
- return major_version;
-}
-
-} // namespace
-
-LRESULT CALLBACK WebPluginDelegateImpl::HandleEventMessageFilterHook(
- int code, WPARAM wParam, LPARAM lParam) {
- if (g_current_plugin_instance) {
- g_current_plugin_instance->OnModalLoopEntered();
- } else {
- NOTREACHED();
- }
- return CallNextHookEx(NULL, code, wParam, lParam);
-}
-
-LRESULT CALLBACK WebPluginDelegateImpl::MouseHookProc(
- int code, WPARAM wParam, LPARAM lParam) {
- if (code == HC_ACTION) {
- MOUSEHOOKSTRUCT* hook_struct = reinterpret_cast<MOUSEHOOKSTRUCT*>(lParam);
- if (hook_struct)
- HandleCaptureForMessage(hook_struct->hwnd, wParam);
- }
-
- return CallNextHookEx(NULL, code, wParam, lParam);
-}
-
-WebPluginDelegateImpl::WebPluginDelegateImpl(WebPlugin* plugin,
- PluginInstance* instance)
- : windowed_handle_(NULL),
- windowed_did_set_window_(false),
- windowless_(false),
- plugin_(plugin),
- instance_(instance),
- plugin_wnd_proc_(NULL),
- last_message_(0),
- is_calling_wndproc(false),
- quirks_(0),
- dummy_window_for_activation_(NULL),
- dummy_window_parent_(NULL),
- old_dummy_window_proc_(NULL),
- handle_event_message_filter_hook_(NULL),
- handle_event_pump_messages_event_(NULL),
- user_gesture_message_posted_(false),
- mouse_hook_(NULL),
- handle_event_depth_(0),
- first_set_window_call_(true),
- plugin_has_focus_(false),
- has_webkit_focus_(false),
- containing_view_has_focus_(true),
- creation_succeeded_(false),
- user_gesture_msg_factory_(this) {
- memset(&window_, 0, sizeof(window_));
-
- const WebPluginInfo& plugin_info = instance_->plugin_lib()->plugin_info();
- base::string16 filename =
- base::ToLowerASCII(plugin_info.path.BaseName().value());
-
- if (instance_->mime_type() == kFlashPluginSwfMimeType ||
- filename == kFlashPlugin) {
- // Flash only requests windowless plugins if we return a Mozilla user
- // agent.
- instance_->set_use_mozilla_user_agent();
- quirks_ |= PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE;
- quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR;
- quirks_ |= PLUGIN_QUIRK_ALWAYS_NOTIFY_SUCCESS;
- quirks_ |= PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE;
- quirks_ |= PLUGIN_QUIRK_EMULATE_IME;
- quirks_ |= PLUGIN_QUIRK_FAKE_WINDOW_FROM_POINT;
- } else if (filename == kAcrobatReaderPlugin) {
- // Check for the version number above or equal 9.
- uint32_t major_version = GetPluginMajorVersion(plugin_info);
- if (major_version >= 9) {
- quirks_ |= PLUGIN_QUIRK_DIE_AFTER_UNLOAD;
- // 9.2 needs this.
- quirks_ |= PLUGIN_QUIRK_SETWINDOW_TWICE;
- }
- quirks_ |= PLUGIN_QUIRK_BLOCK_NONSTANDARD_GETURL_REQUESTS;
- } else if (plugin_info.name.find(L"Windows Media Player") !=
- std::wstring::npos) {
- // Windows Media Player needs two NPP_SetWindow calls.
- quirks_ |= PLUGIN_QUIRK_SETWINDOW_TWICE;
-
- // Windowless mode doesn't work in the WMP NPAPI plugin.
- quirks_ |= PLUGIN_QUIRK_NO_WINDOWLESS;
-
- // The media player plugin sets its size on the first NPP_SetWindow call
- // and never updates its size. We should call the underlying NPP_SetWindow
- // only when we have the correct size.
- quirks_ |= PLUGIN_QUIRK_IGNORE_FIRST_SETWINDOW_CALL;
-
- if (filename == kOldWMPPlugin) {
- // Non-admin users on XP couldn't modify the key to force the new UI.
- quirks_ |= PLUGIN_QUIRK_PATCH_REGENUMKEYEXW;
- }
- } else if (instance_->mime_type() == "audio/x-pn-realaudio-plugin" ||
- filename == kRealPlayerPlugin) {
- quirks_ |= PLUGIN_QUIRK_DONT_CALL_WND_PROC_RECURSIVELY;
- } else if (plugin_info.name.find(L"VLC Multimedia Plugin") !=
- std::wstring::npos ||
- plugin_info.name.find(L"VLC Multimedia Plug-in") !=
- std::wstring::npos) {
- // VLC hangs on NPP_Destroy if we call NPP_SetWindow with a null window
- // handle
- quirks_ |= PLUGIN_QUIRK_DONT_SET_NULL_WINDOW_HANDLE_ON_DESTROY;
- uint32_t major_version = GetPluginMajorVersion(plugin_info);
- if (major_version == 0) {
- // VLC 0.8.6d and 0.8.6e crash if multiple instances are created.
- quirks_ |= PLUGIN_QUIRK_DONT_ALLOW_MULTIPLE_INSTANCES;
- }
- } else if (filename == kSilverlightPlugin) {
- // Explanation for this quirk can be found in
- // WebPluginDelegateImpl::Initialize.
- quirks_ |= PLUGIN_QUIRK_PATCH_SETCURSOR;
- } else if (plugin_info.name.find(L"DivX Web Player") !=
- std::wstring::npos) {
- // The divx plugin sets its size on the first NPP_SetWindow call and never
- // updates its size. We should call the underlying NPP_SetWindow only when
- // we have the correct size.
- quirks_ |= PLUGIN_QUIRK_IGNORE_FIRST_SETWINDOW_CALL;
- }
-}
-
-WebPluginDelegateImpl::~WebPluginDelegateImpl() {
- if (::IsWindow(dummy_window_for_activation_)) {
- WNDPROC current_wnd_proc = reinterpret_cast<WNDPROC>(
- GetWindowLongPtr(dummy_window_for_activation_, GWLP_WNDPROC));
- if (current_wnd_proc == DummyWindowProc) {
- SetWindowLongPtr(dummy_window_for_activation_,
- GWLP_WNDPROC,
- reinterpret_cast<LONG_PTR>(old_dummy_window_proc_));
- }
- ::DestroyWindow(dummy_window_for_activation_);
- }
-
- DestroyInstance();
-
- if (!windowless_)
- WindowedDestroyWindow();
-
- if (handle_event_pump_messages_event_) {
- CloseHandle(handle_event_pump_messages_event_);
- }
-}
-
-bool WebPluginDelegateImpl::PlatformInitialize() {
- plugin_->SetWindow(windowed_handle_);
-
- if (windowless_) {
- CreateDummyWindowForActivation();
- handle_event_pump_messages_event_ = CreateEvent(NULL, TRUE, FALSE, NULL);
- plugin_->SetWindowlessData(
- handle_event_pump_messages_event_,
- reinterpret_cast<gfx::NativeViewId>(dummy_window_for_activation_));
- }
-
- // Windowless plugins call the WindowFromPoint API and passes the result of
- // that to the TrackPopupMenu API call as the owner window. This causes the
- // API to fail as the API expects the window handle to live on the same
- // thread as the caller. It works in the other browsers as the plugin lives
- // on the browser thread. Our workaround is to intercept the TrackPopupMenu
- // API and replace the window handle with the dummy activation window.
- if (windowless_ && !g_iat_patch_track_popup_menu.Pointer()->is_patched()) {
- g_iat_patch_track_popup_menu.Pointer()->Patch(
- GetPluginPath().value().c_str(), "user32.dll", "TrackPopupMenu",
- WebPluginDelegateImpl::TrackPopupMenuPatch);
- }
-
- // Windowless plugins can set cursors by calling the SetCursor API. This
- // works because the thread inputs of the browser UI thread and the plugin
- // thread are attached. We intercept the SetCursor API for windowless
- // plugins and remember the cursor being set. This is shipped over to the
- // browser in the HandleEvent call, which ensures that the cursor does not
- // change when a windowless plugin instance changes the cursor
- // in a background tab.
- if (windowless_ && !g_iat_patch_set_cursor.Pointer()->is_patched() &&
- (quirks_ & PLUGIN_QUIRK_PATCH_SETCURSOR)) {
- g_iat_patch_set_cursor.Pointer()->Patch(
- GetPluginPath().value().c_str(), "user32.dll", "SetCursor",
- WebPluginDelegateImpl::SetCursorPatch);
- }
-
- // The windowed flash plugin has a bug which occurs when the plugin enters
- // fullscreen mode. It basically captures the mouse on WM_LBUTTONDOWN and
- // does not release capture correctly causing it to stop receiving
- // subsequent mouse events. This problem is also seen in Safari where there
- // is code to handle this in the wndproc. However the plugin subclasses the
- // window again in WM_LBUTTONDOWN before entering full screen. As a result
- // Safari does not receive the WM_LBUTTONUP message. To workaround this
- // issue we use a per thread mouse hook. This bug does not occur in Firefox
- // and opera. Firefox has code similar to Safari. It could well be a bug in
- // the flash plugin, which only occurs in webkit based browsers.
- if (quirks_ & PLUGIN_QUIRK_HANDLE_MOUSE_CAPTURE) {
- mouse_hook_ = SetWindowsHookEx(WH_MOUSE, MouseHookProc, NULL,
- GetCurrentThreadId());
- }
-
- // On XP, WMP will use its old UI unless a registry key under HKLM has the
- // name of the current process. We do it in the installer for admin users,
- // for the rest patch this function.
- if ((quirks_ & PLUGIN_QUIRK_PATCH_REGENUMKEYEXW) &&
- base::win::GetVersion() == base::win::VERSION_XP &&
- (base::win::RegKey().Open(HKEY_LOCAL_MACHINE,
- L"SOFTWARE\\Microsoft\\MediaPlayer\\ShimInclusionList\\chrome.exe",
- KEY_READ) != ERROR_SUCCESS) &&
- !g_iat_patch_reg_enum_key_ex_w.Pointer()->is_patched()) {
- g_iat_patch_reg_enum_key_ex_w.Pointer()->Patch(
- L"wmpdxm.dll", "advapi32.dll", "RegEnumKeyExW",
- WebPluginDelegateImpl::RegEnumKeyExWPatch);
- }
-
- // Flash retrieves the pointers to IMM32 functions with GetProcAddress() calls
- // and use them to retrieve IME data. We add a patch to this function so we
- // can dispatch these IMM32 calls to the WebPluginIMEWin class, which emulates
- // IMM32 functions for Flash.
- if (!g_iat_patch_get_proc_address.Pointer()->is_patched() &&
- (quirks_ & PLUGIN_QUIRK_EMULATE_IME)) {
- g_iat_patch_get_proc_address.Pointer()->Patch(
- GetPluginPath().value().c_str(), "kernel32.dll", "GetProcAddress",
- GetProcAddressPatch);
- }
-
- if (windowless_ && !g_iat_patch_window_from_point.Pointer()->is_patched() &&
- (quirks_ & PLUGIN_QUIRK_FAKE_WINDOW_FROM_POINT)) {
- g_iat_patch_window_from_point.Pointer()->Patch(
- GetPluginPath().value().c_str(), "user32.dll", "WindowFromPoint",
- WebPluginDelegateImpl::WindowFromPointPatch);
- }
-
- return true;
-}
-
-void WebPluginDelegateImpl::PlatformDestroyInstance() {
- if (!instance_->plugin_lib())
- return;
-
- // Unpatch if this is the last plugin instance.
- if (instance_->plugin_lib()->instance_count() != 1)
- return;
-
- if (g_iat_patch_set_cursor.Pointer()->is_patched())
- g_iat_patch_set_cursor.Pointer()->Unpatch();
-
- if (g_iat_patch_track_popup_menu.Pointer()->is_patched())
- g_iat_patch_track_popup_menu.Pointer()->Unpatch();
-
- if (g_iat_patch_reg_enum_key_ex_w.Pointer()->is_patched())
- g_iat_patch_reg_enum_key_ex_w.Pointer()->Unpatch();
-
- if (g_iat_patch_window_from_point.Pointer()->is_patched())
- g_iat_patch_window_from_point.Pointer()->Unpatch();
-
- if (mouse_hook_) {
- UnhookWindowsHookEx(mouse_hook_);
- mouse_hook_ = NULL;
- }
-}
-
-void WebPluginDelegateImpl::Paint(SkCanvas* canvas, const gfx::Rect& rect) {
- if (windowless_ && skia::SupportsPlatformPaint(canvas)) {
- skia::ScopedPlatformPaint scoped_platform_paint(canvas);
- HDC hdc = scoped_platform_paint.GetPlatformSurface();
- WindowlessPaint(hdc, rect);
- }
-}
-
-bool WebPluginDelegateImpl::WindowedCreatePlugin() {
- DCHECK(!windowed_handle_);
-
- RegisterNativeWindowClass();
-
- // The window will be sized and shown later.
- windowed_handle_ = CreateWindowEx(
- WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR,
- kNativeWindowClassName,
- 0,
- WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
- 0,
- 0,
- 0,
- 0,
- GetDesktopWindow(),
- 0,
- GetModuleHandle(NULL),
- 0);
- if (windowed_handle_ == 0)
- return false;
-
- // This is a tricky workaround for Issue 2673 in chromium "Flash: IME not
- // available". To use IMEs in this window, we have to make Windows attach
- // IMEs to this window (i.e. load IME DLLs, attach them to this process, and
- // add their message hooks to this window). Windows attaches IMEs while this
- // process creates a top-level window. On the other hand, to layout this
- // window correctly in the given parent window (RenderWidgetHostViewWin or
- // RenderWidgetHostViewAura), this window should be a child window of the
- // parent window. To satisfy both of the above conditions, this code once
- // creates a top-level window and change it to a child window of the parent
- // window (in the browser process).
- SetWindowLongPtr(windowed_handle_, GWL_STYLE,
- WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
-
- BOOL result = SetProp(windowed_handle_, kWebPluginDelegateProperty, this);
- DCHECK(result == TRUE) << "SetProp failed, last error = " << GetLastError();
-
- // Calling SetWindowLongPtrA here makes the window proc ASCII, which is
- // required by at least the Shockwave Director plugin.
- SetWindowLongPtrA(windowed_handle_,
- GWLP_WNDPROC,
- reinterpret_cast<LONG_PTR>(DefWindowProcA));
-
- return true;
-}
-
-void WebPluginDelegateImpl::WindowedDestroyWindow() {
- if (windowed_handle_ != NULL) {
- // Unsubclass the window.
- WNDPROC current_wnd_proc = reinterpret_cast<WNDPROC>(
- GetWindowLongPtr(windowed_handle_, GWLP_WNDPROC));
- if (current_wnd_proc == NativeWndProc) {
- SetWindowLongPtr(windowed_handle_,
- GWLP_WNDPROC,
- reinterpret_cast<LONG_PTR>(plugin_wnd_proc_));
- }
-
- plugin_->WillDestroyWindow(windowed_handle_);
-
- DestroyWindow(windowed_handle_);
- windowed_handle_ = 0;
- }
-}
-
-// Erase all messages in the queue destined for a particular window.
-// When windows are closing, callers should use this function to clear
-// the queue.
-// static
-void WebPluginDelegateImpl::ClearThrottleQueueForWindow(HWND window) {
- ThrottleQueue* throttle_queue = g_throttle_queue.Pointer();
-
- ThrottleQueue::iterator it;
- for (it = throttle_queue->begin(); it != throttle_queue->end(); ) {
- if (it->hwnd == window) {
- it = throttle_queue->erase(it);
- } else {
- it++;
- }
- }
-}
-
-// Delayed callback for processing throttled messages.
-// Throttled messages are aggregated globally across all plugins.
-// static
-void WebPluginDelegateImpl::OnThrottleMessage() {
- // The current algorithm walks the list and processes the first
- // message it finds for each plugin. It is important to service
- // all active plugins with each pass through the throttle, otherwise
- // we see video jankiness. Copy the set to notify before notifying
- // since we may re-enter OnThrottleMessage from CallWindowProc!
- ThrottleQueue* throttle_queue = g_throttle_queue.Pointer();
- ThrottleQueue notify_queue;
- std::set<HWND> processed;
-
- ThrottleQueue::iterator it = throttle_queue->begin();
- while (it != throttle_queue->end()) {
- const MSG& msg = *it;
- if (processed.find(msg.hwnd) == processed.end()) {
- processed.insert(msg.hwnd);
- notify_queue.push_back(msg);
- it = throttle_queue->erase(it);
- } else {
- it++;
- }
- }
-
- // Due to re-entrancy, we must save our queue state now. Otherwise, we may
- // self-post below, and *also* start up another delayed task when the first
- // entry is pushed onto the queue in ThrottleMessage().
- bool throttle_queue_was_empty = throttle_queue->empty();
-
- for (it = notify_queue.begin(); it != notify_queue.end(); ++it) {
- const MSG& msg = *it;
- WNDPROC proc = reinterpret_cast<WNDPROC>(msg.time);
- // It is possible that the window was closed after we queued
- // this message. This is a rare event; just verify the window
- // is alive. (see also bug 1259488)
- if (IsWindow(msg.hwnd))
- CallWindowProc(proc, msg.hwnd, msg.message, msg.wParam, msg.lParam);
- }
-
- if (!throttle_queue_was_empty) {
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&WebPluginDelegateImpl::OnThrottleMessage),
- base::TimeDelta::FromMilliseconds(kFlashWMUSERMessageThrottleDelayMs));
- }
-}
-
-// Schedule a windows message for delivery later.
-// static
-void WebPluginDelegateImpl::ThrottleMessage(WNDPROC proc, HWND hwnd,
- UINT message, WPARAM wParam,
- LPARAM lParam) {
- MSG msg;
- // Cast through uintptr_t and then DWORD to make the truncation explicit.
- msg.time = static_cast<DWORD>(reinterpret_cast<uintptr_t>(proc));
- msg.hwnd = hwnd;
- msg.message = message;
- msg.wParam = wParam;
- msg.lParam = lParam;
-
- ThrottleQueue* throttle_queue = g_throttle_queue.Pointer();
-
- throttle_queue->push_back(msg);
-
- if (throttle_queue->size() == 1) {
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&WebPluginDelegateImpl::OnThrottleMessage),
- base::TimeDelta::FromMilliseconds(kFlashWMUSERMessageThrottleDelayMs));
- }
-}
-
-// We go out of our way to find the hidden windows created by Flash for
-// windowless plugins. We throttle the rate at which they deliver messages
-// so that they will not consume outrageous amounts of CPU.
-// static
-LRESULT CALLBACK WebPluginDelegateImpl::FlashWindowlessWndProc(
- HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
- std::map<HWND, WNDPROC>::iterator index =
- g_window_handle_proc_map.Get().find(hwnd);
-
- WNDPROC old_proc = (*index).second;
- DCHECK(old_proc);
-
- switch (message) {
- case WM_NCDESTROY: {
- WebPluginDelegateImpl::ClearThrottleQueueForWindow(hwnd);
- g_window_handle_proc_map.Get().erase(index);
- break;
- }
- // Flash may flood the message queue with WM_USER+1 message causing 100% CPU
- // usage. See https://bugzilla.mozilla.org/show_bug.cgi?id=132759. We
- // prevent this by throttling the messages.
- case WM_USER + 1: {
- WebPluginDelegateImpl::ThrottleMessage(old_proc, hwnd, message, wparam,
- lparam);
- return TRUE;
- }
-
- default: {
- break;
- }
- }
- return CallWindowProc(old_proc, hwnd, message, wparam, lparam);
-}
-
-LRESULT CALLBACK WebPluginDelegateImpl::DummyWindowProc(
- HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param) {
- WebPluginDelegateImpl* delegate = reinterpret_cast<WebPluginDelegateImpl*>(
- GetProp(hwnd, kWebPluginDelegateProperty));
- CHECK(delegate);
- if (message == WM_WINDOWPOSCHANGING) {
- // We need to know when the dummy window is parented because windowless
- // plugins need the parent window for things like menus. There's no message
- // for a parent being changed, but a WM_WINDOWPOSCHANGING is sent so we
- // check every time we get it.
- // For non-aura builds, this never changes since RenderWidgetHostViewWin's
- // window is constant. For aura builds, this changes every time the tab gets
- // dragged to a new window.
- HWND parent = GetParent(hwnd);
- if (parent != delegate->dummy_window_parent_) {
- delegate->dummy_window_parent_ = parent;
-
- // Set the containing window handle as the instance window handle. This is
- // what Safari does. Not having a valid window handle causes subtle bugs
- // with plugins which retrieve the window handle and use it for things
- // like context menus. The window handle can be retrieved via
- // NPN_GetValue of NPNVnetscapeWindow.
- delegate->instance_->set_window_handle(parent);
-
- // The plugin caches the result of NPNVnetscapeWindow when we originally
- // called NPP_SetWindow, so force it to get the new value.
- delegate->WindowlessSetWindow();
- }
- } else if (message == WM_NCDESTROY) {
- RemoveProp(hwnd, kWebPluginDelegateProperty);
- }
- return CallWindowProc(
- delegate->old_dummy_window_proc_, hwnd, message, w_param, l_param);
-}
-
-// Callback for enumerating the Flash windows.
-BOOL CALLBACK EnumFlashWindows(HWND window, LPARAM arg) {
- WNDPROC wnd_proc = reinterpret_cast<WNDPROC>(arg);
- TCHAR class_name[1024];
- if (!RealGetWindowClass(window, class_name,
- sizeof(class_name)/sizeof(TCHAR))) {
- LOG(ERROR) << "RealGetWindowClass failure: " << GetLastError();
- return FALSE;
- }
-
- if (wcscmp(class_name, L"SWFlash_PlaceholderX"))
- return TRUE;
-
- WNDPROC current_wnd_proc = reinterpret_cast<WNDPROC>(
- GetWindowLongPtr(window, GWLP_WNDPROC));
- if (current_wnd_proc != wnd_proc) {
- WNDPROC old_flash_proc = reinterpret_cast<WNDPROC>(SetWindowLongPtr(
- window, GWLP_WNDPROC,
- reinterpret_cast<LONG_PTR>(wnd_proc)));
- DCHECK(old_flash_proc);
- g_window_handle_proc_map.Get()[window] = old_flash_proc;
- }
-
- return TRUE;
-}
-
-bool WebPluginDelegateImpl::CreateDummyWindowForActivation() {
- DCHECK(!dummy_window_for_activation_);
-
- dummy_window_for_activation_ = CreateWindowEx(
- 0,
- L"Static",
- kDummyActivationWindowName,
- WS_CHILD,
- 0,
- 0,
- 0,
- 0,
- // We don't know the parent of the dummy window yet, so just set it to the
- // desktop and it'll get parented by the browser.
- GetDesktopWindow(),
- 0,
- GetModuleHandle(NULL),
- 0);
-
- if (dummy_window_for_activation_ == 0)
- return false;
-
- BOOL result = SetProp(dummy_window_for_activation_,
- kWebPluginDelegateProperty, this);
- DCHECK(result == TRUE) << "SetProp failed, last error = " << GetLastError();
- old_dummy_window_proc_ = reinterpret_cast<WNDPROC>(SetWindowLongPtr(
- dummy_window_for_activation_, GWLP_WNDPROC,
- reinterpret_cast<LONG_PTR>(DummyWindowProc)));
-
- // Flash creates background windows which use excessive CPU in our
- // environment; we wrap these windows and throttle them so that they don't
- // get out of hand.
- if (!EnumThreadWindows(::GetCurrentThreadId(), EnumFlashWindows,
- reinterpret_cast<LPARAM>(
- &WebPluginDelegateImpl::FlashWindowlessWndProc))) {
- // Log that this happened. Flash will still work; it just means the
- // throttle isn't installed (and Flash will use more CPU).
- NOTREACHED();
- LOG(ERROR) << "Failed to wrap all windowless Flash windows";
- }
- return true;
-}
-
-bool WebPluginDelegateImpl::WindowedReposition(
- const gfx::Rect& window_rect_in_dip,
- const gfx::Rect& clip_rect_in_dip) {
- if (!windowed_handle_) {
- NOTREACHED();
- return false;
- }
-
- gfx::Rect window_rect = gfx::win::DIPToScreenRect(window_rect_in_dip);
- gfx::Rect clip_rect = gfx::win::DIPToScreenRect(clip_rect_in_dip);
- if (window_rect_ == window_rect && clip_rect_ == clip_rect)
- return false;
-
- // We only set the plugin's size here. Its position is moved elsewhere, which
- // allows the window moves/scrolling/clipping to be synchronized with the page
- // and other windows.
- // If the plugin window has no parent, then don't focus it because it isn't
- // being displayed anywhere. See:
- // http://code.google.com/p/chromium/issues/detail?id=32658
- if (window_rect.size() != window_rect_.size()) {
- UINT flags = SWP_NOMOVE | SWP_NOZORDER;
- if (!GetParent(windowed_handle_))
- flags |= SWP_NOACTIVATE;
- ::SetWindowPos(windowed_handle_,
- NULL,
- 0,
- 0,
- window_rect.width(),
- window_rect.height(),
- flags);
- }
-
- window_rect_ = window_rect;
- clip_rect_ = clip_rect;
-
- // Ensure that the entire window gets repainted.
- ::InvalidateRect(windowed_handle_, NULL, FALSE);
-
- return true;
-}
-
-void WebPluginDelegateImpl::WindowedSetWindow() {
- if (!instance_.get())
- return;
-
- if (!windowed_handle_) {
- NOTREACHED();
- return;
- }
-
- instance()->set_window_handle(windowed_handle_);
-
- DCHECK(!instance()->windowless());
-
- window_.clipRect.top = std::max(0, clip_rect_.y());
- window_.clipRect.left = std::max(0, clip_rect_.x());
- window_.clipRect.bottom = std::max(0, clip_rect_.y() + clip_rect_.height());
- window_.clipRect.right = std::max(0, clip_rect_.x() + clip_rect_.width());
- window_.height = window_rect_.height();
- window_.width = window_rect_.width();
- window_.x = 0;
- window_.y = 0;
-
- window_.window = windowed_handle_;
- window_.type = NPWindowTypeWindow;
-
- // Reset this flag before entering the instance in case of side-effects.
- windowed_did_set_window_ = true;
-
- instance()->NPP_SetWindow(&window_);
- if (quirks_ & PLUGIN_QUIRK_SETWINDOW_TWICE)
- instance()->NPP_SetWindow(&window_);
-
- WNDPROC current_wnd_proc = reinterpret_cast<WNDPROC>(
- GetWindowLongPtr(windowed_handle_, GWLP_WNDPROC));
- if (current_wnd_proc != NativeWndProc) {
- plugin_wnd_proc_ = reinterpret_cast<WNDPROC>(
- SetWindowLongPtr(windowed_handle_,
- GWLP_WNDPROC,
- reinterpret_cast<LONG_PTR>(NativeWndProc)));
- }
-}
-
-ATOM WebPluginDelegateImpl::RegisterNativeWindowClass() {
- static bool have_registered_window_class = false;
- if (have_registered_window_class == true)
- return true;
-
- have_registered_window_class = true;
-
- WNDCLASSEX wcex;
- wcex.cbSize = sizeof(WNDCLASSEX);
- wcex.style = CS_DBLCLKS;
- wcex.lpfnWndProc = WrapperWindowProc;
- wcex.cbClsExtra = 0;
- wcex.cbWndExtra = 0;
- wcex.hInstance = GetModuleHandle(NULL);
- wcex.hIcon = 0;
- wcex.hCursor = 0;
- // Some plugins like windows media player 11 create child windows parented
- // by our plugin window, where the media content is rendered. These plugins
- // dont implement WM_ERASEBKGND, which causes painting issues, when the
- // window where the media is rendered is moved around. DefWindowProc does
- // implement WM_ERASEBKGND correctly if we have a valid background brush.
- wcex.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW+1);
- wcex.lpszMenuName = 0;
- wcex.lpszClassName = kNativeWindowClassName;
- wcex.hIconSm = 0;
-
- return RegisterClassEx(&wcex);
-}
-
-LRESULT CALLBACK WebPluginDelegateImpl::WrapperWindowProc(
- HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
- // This is another workaround for Issue 2673 in chromium "Flash: IME not
- // available". Somehow, the CallWindowProc() function does not dispatch
- // window messages when its first parameter is a handle representing the
- // DefWindowProc() function. To avoid this problem, this code creates a
- // wrapper function which just encapsulates the DefWindowProc() function
- // and set it as the window procedure of a windowed plugin.
- return DefWindowProc(hWnd, message, wParam, lParam);
-}
-
-// Returns true if the message passed in corresponds to a user gesture.
-static bool IsUserGestureMessage(unsigned int message) {
- switch (message) {
- case WM_LBUTTONDOWN:
- case WM_LBUTTONUP:
- case WM_RBUTTONDOWN:
- case WM_RBUTTONUP:
- case WM_MBUTTONDOWN:
- case WM_MBUTTONUP:
- case WM_KEYDOWN:
- case WM_KEYUP:
- return true;
-
- default:
- break;
- }
-
- return false;
-}
-
-LRESULT CALLBACK WebPluginDelegateImpl::NativeWndProc(
- HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) {
- WebPluginDelegateImpl* delegate = reinterpret_cast<WebPluginDelegateImpl*>(
- GetProp(hwnd, kWebPluginDelegateProperty));
- if (!delegate) {
- NOTREACHED();
- return 0;
- }
-
- if (message == delegate->last_message_ &&
- delegate->GetQuirks() & PLUGIN_QUIRK_DONT_CALL_WND_PROC_RECURSIVELY &&
- delegate->is_calling_wndproc) {
- // Real may go into a state where it recursively dispatches the same event
- // when subclassed. See https://bugzilla.mozilla.org/show_bug.cgi?id=192914
- // We only do the recursive check for Real because it's possible and valid
- // for a plugin to synchronously dispatch a message to itself such that it
- // looks like it's in recursion.
- return TRUE;
- }
-
- // Flash may flood the message queue with WM_USER+1 message causing 100% CPU
- // usage. See https://bugzilla.mozilla.org/show_bug.cgi?id=132759. We
- // prevent this by throttling the messages.
- if (message == WM_USER + 1 &&
- delegate->GetQuirks() & PLUGIN_QUIRK_THROTTLE_WM_USER_PLUS_ONE) {
- WebPluginDelegateImpl::ThrottleMessage(delegate->plugin_wnd_proc_, hwnd,
- message, wparam, lparam);
- return FALSE;
- }
-
- LRESULT result;
- uint32_t old_message = delegate->last_message_;
- delegate->last_message_ = message;
-
- static UINT custom_msg = RegisterWindowMessage(kPaintMessageName);
- if (message == custom_msg) {
- // Get the invalid rect which is in screen coordinates and convert to
- // window coordinates.
- gfx::Rect invalid_rect;
- invalid_rect.set_x(static_cast<short>(LOWORD(wparam)));
- invalid_rect.set_y(static_cast<short>(HIWORD(wparam)));
- invalid_rect.set_width(static_cast<short>(LOWORD(lparam)));
- invalid_rect.set_height(static_cast<short>(HIWORD(lparam)));
-
- RECT window_rect;
- GetWindowRect(hwnd, &window_rect);
- invalid_rect.Offset(-window_rect.left, -window_rect.top);
-
- // The plugin window might have non-client area. If we don't pass in
- // RDW_FRAME then the children don't receive WM_NCPAINT messages while
- // scrolling, which causes painting problems (http://b/issue?id=923945).
- uint32_t flags = RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_FRAME;
-
- // If a plugin (like Google Earth or Java) has child windows that are hosted
- // in a different process, then RedrawWindow with UPDATENOW will
- // synchronously wait for this call to complete. Some messages are pumped
- // but not others, which could lead to a deadlock. So avoid reentrancy by
- // only synchronously calling RedrawWindow once at a time.
- if (old_message != custom_msg)
- flags |= RDW_UPDATENOW;
- RECT rect = invalid_rect.ToRECT();
- RedrawWindow(hwnd, &rect, NULL, flags);
- result = FALSE;
- } else {
- delegate->is_calling_wndproc = true;
-
- if (!delegate->user_gesture_message_posted_ &&
- IsUserGestureMessage(message)) {
- delegate->user_gesture_message_posted_ = true;
-
- delegate->instance()->PushPopupsEnabledState(true);
-
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&WebPluginDelegateImpl::OnUserGestureEnd,
- delegate->user_gesture_msg_factory_.GetWeakPtr()),
- base::TimeDelta::FromMilliseconds(kWindowedPluginPopupTimerMs));
- }
-
- HandleCaptureForMessage(hwnd, message);
-
- // Maintain a local/global stack for the g_current_plugin_instance variable
- // as this may be a nested invocation.
- WebPluginDelegateImpl* last_plugin_instance = g_current_plugin_instance;
-
- g_current_plugin_instance = delegate;
-
- result = CallWindowProc(
- delegate->plugin_wnd_proc_, hwnd, message, wparam, lparam);
-
- // The plugin instance may have been destroyed in the CallWindowProc call
- // above. This will also destroy the plugin window. Before attempting to
- // access the WebPluginDelegateImpl instance we validate if the window is
- // still valid.
- if (::IsWindow(hwnd))
- delegate->is_calling_wndproc = false;
-
- g_current_plugin_instance = last_plugin_instance;
-
- if (message == WM_NCDESTROY) {
- RemoveProp(hwnd, kWebPluginDelegateProperty);
- ClearThrottleQueueForWindow(hwnd);
- }
- }
- if (::IsWindow(hwnd))
- delegate->last_message_ = old_message;
- return result;
-}
-
-void WebPluginDelegateImpl::WindowlessUpdateGeometry(
- const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect) {
- bool window_rect_changed = (window_rect_ != window_rect);
- // Only resend to the instance if the geometry has changed.
- if (!window_rect_changed && clip_rect == clip_rect_)
- return;
-
- clip_rect_ = clip_rect;
- window_rect_ = window_rect;
-
- WindowlessSetWindow();
-
- if (window_rect_changed) {
- WINDOWPOS win_pos = {0};
- win_pos.x = window_rect_.x();
- win_pos.y = window_rect_.y();
- win_pos.cx = window_rect_.width();
- win_pos.cy = window_rect_.height();
-
- NPEvent pos_changed_event;
- pos_changed_event.event = WM_WINDOWPOSCHANGED;
- pos_changed_event.wParam = 0;
- pos_changed_event.lParam = reinterpret_cast<uintptr_t>(&win_pos);
-
- instance()->NPP_HandleEvent(&pos_changed_event);
- }
-}
-
-void WebPluginDelegateImpl::WindowlessPaint(HDC hdc,
- const gfx::Rect& damage_rect) {
- DCHECK(hdc);
-
- RECT damage_rect_win;
- damage_rect_win.left = damage_rect.x(); // + window_rect_.x();
- damage_rect_win.top = damage_rect.y(); // + window_rect_.y();
- damage_rect_win.right = damage_rect_win.left + damage_rect.width();
- damage_rect_win.bottom = damage_rect_win.top + damage_rect.height();
-
- // Save away the old HDC as this could be a nested invocation.
- void* old_dc = window_.window;
- window_.window = hdc;
-
- NPEvent paint_event;
- paint_event.event = WM_PAINT;
- paint_event.wParam = PtrToUlong(hdc);
- paint_event.lParam = reinterpret_cast<uintptr_t>(&damage_rect_win);
- instance()->NPP_HandleEvent(&paint_event);
- window_.window = old_dc;
-}
-
-void WebPluginDelegateImpl::WindowlessSetWindow() {
- if (!instance())
- return;
-
- if (window_rect_.IsEmpty()) // wait for geometry to be set.
- return;
-
- DCHECK(instance()->windowless());
-
- window_.clipRect.top = clip_rect_.y();
- window_.clipRect.left = clip_rect_.x();
- window_.clipRect.bottom = clip_rect_.y() + clip_rect_.height();
- window_.clipRect.right = clip_rect_.x() + clip_rect_.width();
- window_.height = window_rect_.height();
- window_.width = window_rect_.width();
- window_.x = window_rect_.x();
- window_.y = window_rect_.y();
- window_.type = NPWindowTypeDrawable;
- DrawableContextEnforcer enforcer(&window_);
-
- NPError err = instance()->NPP_SetWindow(&window_);
- DCHECK(err == NPERR_NO_ERROR);
-}
-
-bool WebPluginDelegateImpl::PlatformSetPluginHasFocus(bool focused) {
- DCHECK(instance()->windowless());
-
- NPEvent focus_event;
- focus_event.event = focused ? WM_SETFOCUS : WM_KILLFOCUS;
- focus_event.wParam = 0;
- focus_event.lParam = 0;
-
- instance()->NPP_HandleEvent(&focus_event);
- return true;
-}
-
-static bool NPEventFromWebMouseEvent(const WebMouseEvent& event,
- NPEvent* np_event) {
- np_event->lParam =
- static_cast<uint32_t>(MAKELPARAM(event.windowX, event.windowY));
- np_event->wParam = 0;
-
- if (event.modifiers & WebInputEvent::ControlKey)
- np_event->wParam |= MK_CONTROL;
- if (event.modifiers & WebInputEvent::ShiftKey)
- np_event->wParam |= MK_SHIFT;
- if (event.modifiers & WebInputEvent::LeftButtonDown)
- np_event->wParam |= MK_LBUTTON;
- if (event.modifiers & WebInputEvent::MiddleButtonDown)
- np_event->wParam |= MK_MBUTTON;
- if (event.modifiers & WebInputEvent::RightButtonDown)
- np_event->wParam |= MK_RBUTTON;
-
- switch (event.type) {
- case WebInputEvent::MouseMove:
- case WebInputEvent::MouseLeave:
- case WebInputEvent::MouseEnter:
- np_event->event = WM_MOUSEMOVE;
- return true;
- case WebInputEvent::MouseDown:
- switch (event.button) {
- case WebMouseEvent::ButtonLeft:
- np_event->event = WM_LBUTTONDOWN;
- break;
- case WebMouseEvent::ButtonMiddle:
- np_event->event = WM_MBUTTONDOWN;
- break;
- case WebMouseEvent::ButtonRight:
- np_event->event = WM_RBUTTONDOWN;
- break;
- case WebMouseEvent::ButtonNone:
- break;
- }
- return true;
- case WebInputEvent::MouseUp:
- switch (event.button) {
- case WebMouseEvent::ButtonLeft:
- np_event->event = WM_LBUTTONUP;
- break;
- case WebMouseEvent::ButtonMiddle:
- np_event->event = WM_MBUTTONUP;
- break;
- case WebMouseEvent::ButtonRight:
- np_event->event = WM_RBUTTONUP;
- break;
- case WebMouseEvent::ButtonNone:
- break;
- }
- return true;
- default:
- NOTREACHED();
- return false;
- }
-}
-
-static bool NPEventFromWebKeyboardEvent(const WebKeyboardEvent& event,
- NPEvent* np_event) {
- np_event->wParam = event.windowsKeyCode;
-
- switch (event.type) {
- case WebInputEvent::KeyDown:
- np_event->event = WM_KEYDOWN;
- np_event->lParam = 0;
- return true;
- case WebInputEvent::Char:
- np_event->event = WM_CHAR;
- np_event->lParam = 0;
- return true;
- case WebInputEvent::KeyUp:
- np_event->event = WM_KEYUP;
- np_event->lParam = 0x8000;
- return true;
- default:
- NOTREACHED();
- return false;
- }
-}
-
-static bool NPEventFromWebInputEvent(const WebInputEvent& event,
- NPEvent* np_event) {
- switch (event.type) {
- case WebInputEvent::MouseMove:
- case WebInputEvent::MouseLeave:
- case WebInputEvent::MouseEnter:
- case WebInputEvent::MouseDown:
- case WebInputEvent::MouseUp:
- if (event.size < sizeof(WebMouseEvent)) {
- NOTREACHED();
- return false;
- }
- return NPEventFromWebMouseEvent(
- *static_cast<const WebMouseEvent*>(&event), np_event);
- case WebInputEvent::KeyDown:
- case WebInputEvent::Char:
- case WebInputEvent::KeyUp:
- if (event.size < sizeof(WebKeyboardEvent)) {
- NOTREACHED();
- return false;
- }
- return NPEventFromWebKeyboardEvent(
- *static_cast<const WebKeyboardEvent*>(&event), np_event);
- default:
- return false;
- }
-}
-
-bool WebPluginDelegateImpl::PlatformHandleInputEvent(
- const WebInputEvent& event, WebCursor::CursorInfo* cursor_info) {
- DCHECK(cursor_info != NULL);
-
- NPEvent np_event;
- if (!NPEventFromWebInputEvent(event, &np_event)) {
- return false;
- }
-
- // Allow this plugin to access this IME emulator through IMM32 API while the
- // plugin is processing this event.
- if (GetQuirks() & PLUGIN_QUIRK_EMULATE_IME) {
- if (!plugin_ime_)
- plugin_ime_.reset(new WebPluginIMEWin);
- }
- WebPluginIMEWin::ScopedLock lock(
- event.isKeyboardEventType(event.type) ? plugin_ime_.get() : NULL);
-
- HWND last_focus_window = NULL;
-
- if (ShouldTrackEventForModalLoops(&np_event)) {
- // A windowless plugin can enter a modal loop in a NPP_HandleEvent call.
- // For e.g. Flash puts up a context menu when we right click on the
- // windowless plugin area. We detect this by setting up a message filter
- // hook pror to calling NPP_HandleEvent on the plugin and unhook on
- // return from NPP_HandleEvent. If the plugin does enter a modal loop
- // in that context we unhook on receiving the first notification in
- // the message filter hook.
- handle_event_message_filter_hook_ =
- SetWindowsHookEx(WH_MSGFILTER, HandleEventMessageFilterHook, NULL,
- GetCurrentThreadId());
- // To ensure that the plugin receives keyboard events we set focus to the
- // dummy window.
- // TODO(iyengar) We need a framework in the renderer to identify which
- // windowless plugin is under the mouse and to handle this. This would
- // also require some changes in RenderWidgetHost to detect this in the
- // WM_MOUSEACTIVATE handler and inform the renderer accordingly.
- bool valid = GetParent(dummy_window_for_activation_) != GetDesktopWindow();
- if (valid) {
- last_focus_window = ::SetFocus(dummy_window_for_activation_);
- } else {
- NOTREACHED() << "Dummy window not parented";
- }
- }
-
- bool old_task_reentrancy_state =
- base::MessageLoop::current()->NestableTasksAllowed();
-
- // Maintain a local/global stack for the g_current_plugin_instance variable
- // as this may be a nested invocation.
- WebPluginDelegateImpl* last_plugin_instance = g_current_plugin_instance;
-
- g_current_plugin_instance = this;
-
- handle_event_depth_++;
-
- bool popups_enabled = false;
-
- if (IsUserGestureMessage(np_event.event)) {
- instance()->PushPopupsEnabledState(true);
- popups_enabled = true;
- }
-
- bool ret = instance()->NPP_HandleEvent(&np_event) != 0;
-
- if (popups_enabled) {
- instance()->PopPopupsEnabledState();
- }
-
- // Flash and SilverLight always return false, even when they swallow the
- // event. Flash does this because it passes the event to its window proc,
- // which is supposed to return 0 if an event was handled. There are few
- // exceptions, such as IME, where it sometimes returns true.
- ret = true;
-
- if (np_event.event == WM_MOUSEMOVE) {
- current_windowless_cursor_.InitFromExternalCursor(GetCursor());
- // Snag a reference to the current cursor ASAP in case the plugin modified
- // it. There is a nasty race condition here with the multiprocess browser
- // as someone might be setting the cursor in the main process as well.
- current_windowless_cursor_.GetCursorInfo(cursor_info);
- }
-
- handle_event_depth_--;
-
- g_current_plugin_instance = last_plugin_instance;
-
- // We could have multiple NPP_HandleEvent calls nested together in case
- // the plugin enters a modal loop. Reset the pump messages event when
- // the outermost NPP_HandleEvent call unwinds.
- if (handle_event_depth_ == 0) {
- ResetEvent(handle_event_pump_messages_event_);
- }
-
- // If we didn't enter a modal loop, need to unhook the filter.
- if (handle_event_message_filter_hook_) {
- UnhookWindowsHookEx(handle_event_message_filter_hook_);
- handle_event_message_filter_hook_ = NULL;
- }
-
- if (::IsWindow(last_focus_window)) {
- // Restore the nestable tasks allowed state in the message loop and reset
- // the os modal loop state as the plugin returned from the TrackPopupMenu
- // API call.
- base::MessageLoop::current()->SetNestableTasksAllowed(
- old_task_reentrancy_state);
- base::MessageLoop::current()->set_os_modal_loop(false);
- // The Flash plugin at times sets focus to its hidden top level window
- // with class name SWFlash_PlaceholderX. This causes the chrome browser
- // window to receive a WM_ACTIVATEAPP message as a top level window from
- // another thread is now active. We end up in a state where the chrome
- // browser window is not active even though the user clicked on it.
- // Our workaround for this is to send over a raw
- // WM_LBUTTONDOWN/WM_LBUTTONUP combination to the last focus window, which
- // does the trick.
- if (dummy_window_for_activation_ != ::GetFocus()) {
- INPUT input_info = {0};
- input_info.type = INPUT_MOUSE;
- input_info.mi.dwFlags = MOUSEEVENTF_LEFTDOWN;
- ::SendInput(1, &input_info, sizeof(INPUT));
-
- input_info.type = INPUT_MOUSE;
- input_info.mi.dwFlags = MOUSEEVENTF_LEFTUP;
- ::SendInput(1, &input_info, sizeof(INPUT));
- } else {
- ::SetFocus(last_focus_window);
- }
- }
- return ret;
-}
-
-
-void WebPluginDelegateImpl::OnModalLoopEntered() {
- DCHECK(handle_event_pump_messages_event_ != NULL);
- SetEvent(handle_event_pump_messages_event_);
-
- base::MessageLoop::current()->SetNestableTasksAllowed(true);
- base::MessageLoop::current()->set_os_modal_loop(true);
-
- UnhookWindowsHookEx(handle_event_message_filter_hook_);
- handle_event_message_filter_hook_ = NULL;
-}
-
-bool WebPluginDelegateImpl::ShouldTrackEventForModalLoops(NPEvent* event) {
- if (event->event == WM_RBUTTONDOWN)
- return true;
- return false;
-}
-
-void WebPluginDelegateImpl::OnUserGestureEnd() {
- user_gesture_message_posted_ = false;
- instance()->PopPopupsEnabledState();
-}
-
-BOOL WINAPI WebPluginDelegateImpl::TrackPopupMenuPatch(
- HMENU menu, unsigned int flags, int x, int y, int reserved,
- HWND window, const RECT* rect) {
-
- if (g_current_plugin_instance) {
- unsigned long window_process_id = 0;
- unsigned long window_thread_id =
- GetWindowThreadProcessId(window, &window_process_id);
- // TrackPopupMenu fails if the window passed in belongs to a different
- // thread.
- if (::GetCurrentThreadId() != window_thread_id) {
- bool valid =
- GetParent(g_current_plugin_instance->dummy_window_for_activation_) !=
- GetDesktopWindow();
- if (valid) {
- window = g_current_plugin_instance->dummy_window_for_activation_;
- } else {
- NOTREACHED() << "Dummy window not parented";
- }
- }
- }
-
- BOOL result = TrackPopupMenu(menu, flags, x, y, reserved, window, rect);
- return result;
-}
-
-HCURSOR WINAPI WebPluginDelegateImpl::SetCursorPatch(HCURSOR cursor) {
- // The windowless flash plugin periodically calls SetCursor in a wndproc
- // instantiated on the plugin thread. This causes annoying cursor flicker
- // when the mouse is moved on a foreground tab, with a windowless plugin
- // instance in a background tab. We just ignore the call here.
- if (!g_current_plugin_instance) {
- HCURSOR current_cursor = GetCursor();
- if (current_cursor != cursor) {
- ::SetCursor(cursor);
- }
- return current_cursor;
- }
- return ::SetCursor(cursor);
-}
-
-LONG WINAPI WebPluginDelegateImpl::RegEnumKeyExWPatch(
- HKEY key, DWORD index, LPWSTR name, LPDWORD name_size, LPDWORD reserved,
- LPWSTR class_name, LPDWORD class_size, PFILETIME last_write_time) {
- DWORD orig_size = *name_size;
- LONG rv = RegEnumKeyExW(key, index, name, name_size, reserved, class_name,
- class_size, last_write_time);
- if (rv == ERROR_SUCCESS &&
- GetKeyPath(key).find(L"Microsoft\\MediaPlayer\\ShimInclusionList") !=
- std::wstring::npos) {
- static const wchar_t kChromeExeName[] = L"chrome.exe";
- wcsncpy_s(name, orig_size, kChromeExeName, arraysize(kChromeExeName));
- *name_size =
- std::min(orig_size, static_cast<DWORD>(arraysize(kChromeExeName)));
- }
-
- return rv;
-}
-
-void WebPluginDelegateImpl::ImeCompositionUpdated(
- const base::string16& text,
- const std::vector<int>& clauses,
- const std::vector<int>& target,
- int cursor_position) {
- if (!plugin_ime_)
- plugin_ime_.reset(new WebPluginIMEWin);
-
- plugin_ime_->CompositionUpdated(text, clauses, target, cursor_position);
- plugin_ime_->SendEvents(instance());
-}
-
-void WebPluginDelegateImpl::ImeCompositionCompleted(
- const base::string16& text) {
- if (!plugin_ime_)
- plugin_ime_.reset(new WebPluginIMEWin);
- plugin_ime_->CompositionCompleted(text);
- plugin_ime_->SendEvents(instance());
-}
-
-bool WebPluginDelegateImpl::GetIMEStatus(int* input_type,
- gfx::Rect* caret_rect) {
- if (!plugin_ime_)
- return false;
- return plugin_ime_->GetStatus(input_type, caret_rect);
-}
-
-// static
-FARPROC WINAPI WebPluginDelegateImpl::GetProcAddressPatch(HMODULE module,
- LPCSTR name) {
- FARPROC imm_function = WebPluginIMEWin::GetProcAddress(name);
- if (imm_function)
- return imm_function;
- return ::GetProcAddress(module, name);
-}
-
-HWND WINAPI WebPluginDelegateImpl::WindowFromPointPatch(POINT point) {
- HWND window = WindowFromPoint(point);
- if (::ScreenToClient(window, &point)) {
- HWND child = ChildWindowFromPoint(window, point);
- if (::IsWindow(child) &&
- ::GetProp(child, content::kPluginDummyParentProperty))
- return child;
- }
- return window;
-}
-
-void WebPluginDelegateImpl::HandleCaptureForMessage(HWND window,
- UINT message) {
- if (gfx::GetClassName(window) != base::string16(kNativeWindowClassName))
- return;
-
- switch (message) {
- case WM_LBUTTONDOWN:
- case WM_MBUTTONDOWN:
- case WM_RBUTTONDOWN:
- ::SetCapture(window);
- // As per documentation the WM_PARENTNOTIFY message is sent to the parent
- // window chain if mouse input is received by the child window. However
- // the parent receives the WM_PARENTNOTIFY message only if we doubleclick
- // on the window. We send the WM_PARENTNOTIFY message for mouse input
- // messages to the parent to indicate that user action is expected.
- ::SendMessage(::GetParent(window), WM_PARENTNOTIFY, message, 0);
- break;
-
- case WM_LBUTTONUP:
- case WM_MBUTTONUP:
- case WM_RBUTTONUP:
- ::ReleaseCapture();
- break;
-
- default:
- break;
- }
-}
-
-} // namespace content
diff --git a/chromium/content/child/npapi/webplugin_ime_win.cc b/chromium/content/child/npapi/webplugin_ime_win.cc
deleted file mode 100644
index 94d1a921cdd..00000000000
--- a/chromium/content/child/npapi/webplugin_ime_win.cc
+++ /dev/null
@@ -1,327 +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/child/npapi/webplugin_ime_win.h"
-
-#include <stddef.h>
-#include <string.h>
-
-#include <cstring>
-#include <string>
-#include <vector>
-
-#include "base/lazy_instance.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/synchronization/lock.h"
-#include "content/child/npapi/plugin_instance.h"
-#include "content/common/plugin_constants_win.h"
-
-#pragma comment(lib, "imm32.lib")
-
-namespace content {
-
-// A critical section that prevents two or more plugins from accessing a
-// WebPluginIMEWin instance through our patch function.
-base::LazyInstance<base::Lock>::Leaky
- g_webplugin_ime_lock = LAZY_INSTANCE_INITIALIZER;
-
-WebPluginIMEWin* WebPluginIMEWin::instance_ = NULL;
-
-WebPluginIMEWin::WebPluginIMEWin()
- : cursor_position_(0),
- delta_start_(0),
- composing_text_(false),
- support_ime_messages_(false),
- status_updated_(false),
- input_type_(1) {
- memset(result_clauses_, 0, sizeof(result_clauses_));
-}
-
-WebPluginIMEWin::~WebPluginIMEWin() {
-}
-
-void WebPluginIMEWin::CompositionUpdated(const base::string16& text,
- std::vector<int> clauses,
- std::vector<int> target,
- int cursor_position) {
- // Send a WM_IME_STARTCOMPOSITION message when a user starts a composition.
- NPEvent np_event;
- if (!composing_text_) {
- composing_text_ = true;
- result_text_.clear();
-
- np_event.event = WM_IME_STARTCOMPOSITION;
- np_event.wParam = 0;
- np_event.lParam = 0;
- events_.push_back(np_event);
- }
-
- // We can update the following values from this event: GCS_COMPSTR,
- // GCS_COMPATTR, GCSCOMPCLAUSE, GCS_CURSORPOS, and GCS_DELTASTART. We send a
- // WM_IME_COMPOSITION message to notify the list of updated values.
- np_event.event = WM_IME_COMPOSITION;
- np_event.wParam = 0;
- np_event.lParam = GCS_COMPSTR | GCS_COMPATTR | GCS_COMPCLAUSE |
- GCS_CURSORPOS | GCS_DELTASTART;
- events_.push_back(np_event);
-
- // Converts this event to the IMM32 data so we do not have to convert it every
- // time when a plugin call an IMM32 function.
- composition_text_ = text;
-
- // Create the composition clauses returned when a plugin calls
- // ImmGetCompositionString() with GCS_COMPCLAUSE.
- composition_clauses_.clear();
- for (size_t i = 0; i < clauses.size(); ++i)
- composition_clauses_.push_back(clauses[i]);
-
- // Create the composition attributes used by GCS_COMPATTR.
- if (target.size() == 2) {
- composition_attributes_.assign(text.length(), ATTR_CONVERTED);
- for (int i = target[0]; i < target[1]; ++i)
- composition_attributes_[i] = ATTR_TARGET_CONVERTED;
- } else {
- composition_attributes_.assign(text.length(), ATTR_INPUT);
- }
-
- cursor_position_ = cursor_position;
- delta_start_ = cursor_position;
-}
-
-void WebPluginIMEWin::CompositionCompleted(const base::string16& text) {
- composing_text_ = false;
-
- // We should update the following values when we finish a composition:
- // GCS_RESULTSTR, GCS_RESULTCLAUSE, GCS_CURSORPOS, and GCS_DELTASTART. We
- // send a WM_IME_COMPOSITION message to notify the list of updated values.
- NPEvent np_event;
- np_event.event = WM_IME_COMPOSITION;
- np_event.wParam = 0;
- np_event.lParam = GCS_CURSORPOS | GCS_DELTASTART | GCS_RESULTSTR |
- GCS_RESULTCLAUSE;
- events_.push_back(np_event);
-
- // We also send a WM_IME_ENDCOMPOSITION message after the final
- // WM_IME_COMPOSITION message (i.e. after finishing a composition).
- np_event.event = WM_IME_ENDCOMPOSITION;
- np_event.wParam = 0;
- np_event.lParam = 0;
- events_.push_back(np_event);
-
- // If the target plugin does not seem to support IME messages, we send
- // each character in IME text with a WM_CHAR message so the plugin can
- // insert the IME text.
- if (!support_ime_messages_) {
- np_event.event = WM_CHAR;
- np_event.wParam = 0;
- np_event.lParam = 0;
- for (size_t i = 0; i < result_text_.length(); ++i) {
- np_event.wParam = result_text_[i];
- events_.push_back(np_event);
- }
- }
-
- // Updated the result text and its clause. (Unlike composition clauses, a
- // result clause consists of only one region.)
- result_text_ = text;
-
- result_clauses_[0] = 0;
- result_clauses_[1] = result_text_.length();
-
- cursor_position_ = result_clauses_[1];
- delta_start_ = result_clauses_[1];
-}
-
-bool WebPluginIMEWin::SendEvents(PluginInstance* instance) {
- // We allow the patch functions to access this WebPluginIMEWin instance only
- // while we send IME events to the plugin.
- ScopedLock lock(this);
-
- bool ret = true;
- for (std::vector<NPEvent>::iterator it = events_.begin();
- it != events_.end(); ++it) {
- if (!instance->NPP_HandleEvent(&(*it)))
- ret = false;
- }
-
- events_.clear();
- return ret;
-}
-
-bool WebPluginIMEWin::GetStatus(int* input_type, gfx::Rect* caret_rect) {
- *input_type = input_type_;
- *caret_rect = caret_rect_;
- return true;
-}
-
-// static
-FARPROC WebPluginIMEWin::GetProcAddress(LPCSTR name) {
- static const struct {
- const char* name;
- FARPROC function;
- } kImm32Functions[] = {
- { "ImmAssociateContextEx",
- reinterpret_cast<FARPROC>(ImmAssociateContextEx) },
- { "ImmGetCompositionStringW",
- reinterpret_cast<FARPROC>(ImmGetCompositionStringW) },
- { "ImmGetContext", reinterpret_cast<FARPROC>(ImmGetContext) },
- { "ImmReleaseContext", reinterpret_cast<FARPROC>(ImmReleaseContext) },
- { "ImmSetCandidateWindow",
- reinterpret_cast<FARPROC>(ImmSetCandidateWindow) },
- { "ImmSetOpenStatus", reinterpret_cast<FARPROC>(ImmSetOpenStatus) },
- };
- for (size_t i = 0; i < arraysize(kImm32Functions); ++i) {
- if (!lstrcmpiA(name, kImm32Functions[i].name))
- return kImm32Functions[i].function;
- }
- return NULL;
-}
-
-void WebPluginIMEWin::Lock() {
- g_webplugin_ime_lock.Pointer()->Acquire();
- instance_ = this;
-}
-
-void WebPluginIMEWin::Unlock() {
- instance_ = NULL;
- g_webplugin_ime_lock.Pointer()->Release();
-}
-
-// static
-WebPluginIMEWin* WebPluginIMEWin::GetInstance(HIMC context) {
- return instance_ && context == reinterpret_cast<HIMC>(instance_) ?
- instance_ : NULL;
-}
-
-// static
-BOOL WINAPI WebPluginIMEWin::ImmAssociateContextEx(HWND window,
- HIMC context,
- DWORD flags) {
- WebPluginIMEWin* instance = GetInstance(context);
- if (!instance)
- return ::ImmAssociateContextEx(window, context, flags);
-
- int input_type = !context && !flags;
- instance->input_type_ = input_type;
- instance->status_updated_ = true;
- return TRUE;
-}
-
-// static
-LONG WINAPI WebPluginIMEWin::ImmGetCompositionStringW(HIMC context,
- DWORD index,
- LPVOID dst_data,
- DWORD dst_size) {
- WebPluginIMEWin* instance = GetInstance(context);
- if (!instance)
- return ::ImmGetCompositionStringW(context, index, dst_data, dst_size);
-
- const void* src_data = NULL;
- DWORD src_size = 0;
- switch (index) {
- case GCS_COMPSTR:
- src_data = instance->composition_text_.c_str();
- src_size = instance->composition_text_.length() * sizeof(wchar_t);
- break;
-
- case GCS_COMPATTR:
- src_data = instance->composition_attributes_.c_str();
- src_size = instance->composition_attributes_.length();
- break;
-
- case GCS_COMPCLAUSE:
- src_data = &instance->composition_clauses_[0];
- src_size = instance->composition_clauses_.size() * sizeof(uint32_t);
- break;
-
- case GCS_CURSORPOS:
- return instance->cursor_position_;
-
- case GCS_DELTASTART:
- return instance->delta_start_;
-
- case GCS_RESULTSTR:
- src_data = instance->result_text_.c_str();
- src_size = instance->result_text_.length() * sizeof(wchar_t);
- break;
-
- case GCS_RESULTCLAUSE:
- src_data = &instance->result_clauses_[0];
- src_size = sizeof(instance->result_clauses_);
- break;
-
- default:
- break;
- }
- if (!src_data || !src_size)
- return IMM_ERROR_NODATA;
-
- if (dst_size >= src_size)
- memcpy(dst_data, src_data, src_size);
-
- return src_size;
-}
-
-// static
-HIMC WINAPI WebPluginIMEWin::ImmGetContext(HWND window) {
- // Call the original ImmGetContext() function if the given window is the one
- // created in WebPluginDelegateImpl::WindowedCreatePlugin(). (We attached IME
- // context only with the windows created in this function.) On the other hand,
- // some windowless plugins (such as Flash) call this function with a dummy
- // window handle. We return our dummy IME context for these plugins so they
- // can use our IME emulator.
- if (IsWindow(window)) {
- wchar_t name[128];
- GetClassName(window, &name[0], arraysize(name));
- if (!wcscmp(&name[0], kNativeWindowClassName))
- return ::ImmGetContext(window);
- }
-
- WebPluginIMEWin* instance = instance_;
- if (instance)
- instance->support_ime_messages_ = true;
- return reinterpret_cast<HIMC>(instance);
-}
-
-// static
-BOOL WINAPI WebPluginIMEWin::ImmReleaseContext(HWND window, HIMC context) {
- if (!GetInstance(context))
- return ::ImmReleaseContext(window, context);
- return TRUE;
-}
-
-// static
-BOOL WINAPI WebPluginIMEWin::ImmSetCandidateWindow(HIMC context,
- CANDIDATEFORM* candidate) {
- WebPluginIMEWin* instance = GetInstance(context);
- if (!instance)
- return ::ImmSetCandidateWindow(context, candidate);
-
- gfx::Rect caret_rect(candidate->rcArea);
- if ((candidate->dwStyle & CFS_EXCLUDE) &&
- instance->caret_rect_ != caret_rect) {
- instance->caret_rect_ = caret_rect;
- instance->status_updated_ = true;
- }
- return TRUE;
-}
-
-// static
-BOOL WINAPI WebPluginIMEWin::ImmSetOpenStatus(HIMC context, BOOL open) {
- WebPluginIMEWin* instance = GetInstance(context);
- if (!instance)
- return ::ImmSetOpenStatus(context, open);
-
- int input_type = open ? 1 : 0;
- if (instance->input_type_ != input_type) {
- instance->input_type_ = input_type;
- instance->status_updated_ = true;
- }
-
- return TRUE;
-}
-
-} // namespace content
diff --git a/chromium/content/child/npapi/webplugin_ime_win.h b/chromium/content/child/npapi/webplugin_ime_win.h
deleted file mode 100644
index 006705eb87a..00000000000
--- a/chromium/content/child/npapi/webplugin_ime_win.h
+++ /dev/null
@@ -1,184 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_CHILD_NPAPI_WEBPLUGIN_IME_WIN_H_
-#define CONTENT_CHILD_NPAPI_WEBPLUGIN_IME_WIN_H_
-
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#include "base/strings/string16.h"
-#include "third_party/npapi/bindings/npapi.h"
-#include "ui/gfx/geometry/rect.h"
-
-namespace content {
-
-class PluginInstance;
-
-// A class that emulates an IME for windowless plugins. A windowless plugin
-// does not have a window. Therefore, we cannot attach an IME to a windowless
-// plugin. To allow such windowless plugins to use IMEs without any changes to
-// them, this class receives the IME data from a browser and patches IMM32
-// functions to return the IME data when a windowless plugin calls IMM32
-// functions. I would not Flash retrieves pointers to IMM32 functions with
-// GetProcAddress(), this class also needs a hook to GetProcAddress() to
-// dispatch IMM32 function calls from a plugin to this class as listed in the
-// following snippet.
-//
-// FARPROC WINAPI GetProcAddressPatch(HMODULE module, LPCSTR name) {
-// FARPROC* proc = WebPluginIMEWin::GetProcAddress(name);
-// if (proc)
-// return proc;
-// return ::GetProcAddress(module, name);
-// }
-// ...
-// app::win::IATPatchFunction get_proc_address;
-// get_proc_address.Patch(
-// GetPluginPath().value().c_str(), "kernel32.dll", "GetProcAddress",
-// GetProcAddressPatch);
-//
-// After we successfuly dispatch IMM32 calls from a plugin to this class, we
-// need to update its IME data so the class can return it to the plugin through
-// its IMM32 calls. To update the IME data, we call CompositionUpdated() or
-// CompositionCompleted() BEFORE sending an IMM32 Window message to the plugin
-// with a SendEvents() call as listed in the following snippet. (Plugins call
-// IMM32 functions when it receives IMM32 window messages. We need to update the
-// IME data of this class before sending IMM32 messages so the plugins can get
-// the latest data.)
-//
-// WebPluginIMEWin ime;
-// ...
-// base::string16 text = "composing";
-// std::vector<int> clauses;
-// clauses.push_back(0);
-// clauses.push_back(text.length());
-// std::vector<int> target;
-// ime.CompositionUpdated(text, clauses, target, text.length());
-// ime.SendEvents(instance());
-//
-// base::string16 result = "result";
-// ime.CompositionCompleted(result);
-// ime.SendEvents(instance());
-//
-// This class also provides GetStatus() so we can retrieve the IME status
-// changed by a plugin with IMM32 functions. This function is mainly used for
-// retrieving the position of a caret.
-//
-class WebPluginIMEWin {
- public:
- // A simple class that allows a plugin to access a WebPluginIMEWin instance
- // only in a scope.
- class ScopedLock {
- public:
- explicit ScopedLock(WebPluginIMEWin* instance) : instance_(instance) {
- if (instance_)
- instance_->Lock();
- }
- ~ScopedLock() {
- if (instance_)
- instance_->Unlock();
- }
-
- private:
- WebPluginIMEWin* instance_;
- };
-
- WebPluginIMEWin();
- ~WebPluginIMEWin();
-
- // Sends raw IME events sent from a browser to this IME emulator and updates
- // the list of Windows events to be sent to a plugin. A raw IME event is
- // mapped to two or more Windows events and it is not so trivial to send these
- // Windows events to a plugin. This function inserts Windows events in the
- // order expected by a plugin.
- void CompositionUpdated(const base::string16& text,
- std::vector<int> clauses,
- std::vector<int> target,
- int cursor_position);
- void CompositionCompleted(const base::string16& text);
-
- // Send all the events added in Update() to a plugin.
- bool SendEvents(PluginInstance* instance);
-
- // Retrieves the status of this IME emulator.
- bool GetStatus(int* input_type, gfx::Rect* caret_rect);
-
- // Returns the pointers to IMM32-emulation functions implemented by this
- // class. This function is used for over-writing the ones returned from
- // GetProcAddress() calls of Win32 API.
- static FARPROC GetProcAddress(const char* name);
-
- private:
- // Allow (or disallow) the patch functions to use this WebPluginIMEWin
- // instance through our patch functions. Our patch functions need a static
- // member variable |instance_| to access a WebPluginIMEWIn instance. We lock
- // this static variable to prevent two or more plugins from accessing a
- // WebPluginIMEWin instance.
- void Lock();
- void Unlock();
-
- // Retrieve the instance of this class.
- static WebPluginIMEWin* GetInstance(HIMC context);
-
- // IMM32 patch functions implemented by this class.
- static BOOL WINAPI ImmAssociateContextEx(HWND window,
- HIMC context,
- DWORD flags);
- static LONG WINAPI ImmGetCompositionStringW(HIMC context,
- DWORD index,
- LPVOID dst_data,
- DWORD dst_size);
- static HIMC WINAPI ImmGetContext(HWND window);
- static BOOL WINAPI ImmReleaseContext(HWND window, HIMC context);
- static BOOL WINAPI ImmSetCandidateWindow(HIMC context,
- CANDIDATEFORM* candidate);
- static BOOL WINAPI ImmSetOpenStatus(HIMC context, BOOL open);
-
- // a list of NPEvents to be sent to a plugin.
- std::vector<NPEvent> events_;
-
- // The return value for GCS_COMPSTR.
- base::string16 composition_text_;
-
- // The return value for GCS_RESULTSTR.
- base::string16 result_text_;
-
- // The return value for GCS_COMPATTR.
- std::string composition_attributes_;
-
- // The return value for GCS_COMPCLAUSE.
- std::vector<uint32_t> composition_clauses_;
-
- // The return value for GCS_RESULTCLAUSE.
- uint32_t result_clauses_[2];
-
- // The return value for GCS_CURSORPOS.
- int cursor_position_;
-
- // The return value for GCS_DELTASTART.
- int delta_start_;
-
- // Whether we are composing text. This variable is used for sending a
- // WM_IME_STARTCOMPOSITION message when we start composing IME text.
- bool composing_text_;
-
- // Whether a plugin supports IME messages. When a plugin cannot handle
- // IME messages, we need to send the IME text with WM_CHAR messages as Windows
- // does.
- bool support_ime_messages_;
-
- // The IME status received from a plugin.
- bool status_updated_;
- int input_type_;
- gfx::Rect caret_rect_;
-
- // The pointer to the WebPluginIMEWin instance used by patch functions.
- static WebPluginIMEWin* instance_;
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_NPAPI_WEBPLUGIN_IME_WIN_H_
diff --git a/chromium/content/child/npapi/webplugin_resource_client.h b/chromium/content/child/npapi/webplugin_resource_client.h
deleted file mode 100644
index ee2e456b618..00000000000
--- a/chromium/content/child/npapi/webplugin_resource_client.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_CHILD_NPAPI_WEBPLUGIN_RESOURCE_CLIENT_H_
-#define CONTENT_CHILD_NPAPI_WEBPLUGIN_RESOURCE_CLIENT_H_
-
-#include <stdint.h>
-
-#include <string>
-
-
-class GURL;
-
-namespace content {
-
-// Simpler version of ResourceHandleClient that lends itself to proxying.
-class WebPluginResourceClient {
- public:
- virtual ~WebPluginResourceClient() {}
-
- virtual void WillSendRequest(const GURL& url, int http_status_code) = 0;
- // The request_is_seekable parameter indicates whether byte range requests
- // can be issued for the underlying stream.
- virtual void DidReceiveResponse(const std::string& mime_type,
- const std::string& headers,
- uint32_t expected_length,
- uint32_t last_modified,
- bool request_is_seekable) = 0;
- virtual void DidReceiveData(const char* buffer, int length,
- int data_offset) = 0;
- // The resource ids passed here ensures that data for range requests
- // is cleared. This applies for seekable streams.
- virtual void DidFinishLoading(unsigned long resource_id) = 0;
- virtual void DidFail(unsigned long resource_id) = 0;
- virtual int ResourceId() = 0;
- // Tells this object that it will get responses from multiple resources.
- // This is necessary since the plugin process uses a single instance of
- // PluginStreamUrl object for multiple range requests.
- virtual void AddRangeRequestResourceId(unsigned long resource_id) { }
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_NPAPI_WEBPLUGIN_RESOURCE_CLIENT_H_
diff --git a/chromium/content/child/permissions/permission_dispatcher.cc b/chromium/content/child/permissions/permission_dispatcher.cc
index 2efb9a61c8d..3464648e4c1 100644
--- a/chromium/content/child/permissions/permission_dispatcher.cc
+++ b/chromium/content/child/permissions/permission_dispatcher.cc
@@ -12,9 +12,10 @@
#include "content/public/common/service_registry.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/modules/permissions/WebPermissionObserver.h"
-#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
using blink::WebPermissionObserver;
+using blink::mojom::PermissionName;
+using blink::mojom::PermissionStatus;
namespace content {
@@ -23,46 +24,48 @@ namespace {
PermissionName GetPermissionName(blink::WebPermissionType type) {
switch (type) {
case blink::WebPermissionTypeGeolocation:
- return PERMISSION_NAME_GEOLOCATION;
+ return PermissionName::GEOLOCATION;
case blink::WebPermissionTypeNotifications:
- return PERMISSION_NAME_NOTIFICATIONS;
+ return PermissionName::NOTIFICATIONS;
case blink::WebPermissionTypePushNotifications:
- return PERMISSION_NAME_PUSH_NOTIFICATIONS;
+ return PermissionName::PUSH_NOTIFICATIONS;
case blink::WebPermissionTypeMidiSysEx:
- return PERMISSION_NAME_MIDI_SYSEX;
+ return PermissionName::MIDI_SYSEX;
case blink::WebPermissionTypeDurableStorage:
- return PERMISSION_NAME_DURABLE_STORAGE;
+ return PermissionName::DURABLE_STORAGE;
case blink::WebPermissionTypeMidi:
- return PERMISSION_NAME_MIDI;
+ return PermissionName::MIDI;
+ case blink::WebPermissionTypeBackgroundSync:
+ return PermissionName::BACKGROUND_SYNC;
default:
// The default statement is only there to prevent compilation failures if
// WebPermissionType enum gets extended.
NOTREACHED();
- return PERMISSION_NAME_GEOLOCATION;
+ return PermissionName::GEOLOCATION;
}
}
PermissionStatus GetPermissionStatus(blink::WebPermissionStatus status) {
switch (status) {
case blink::WebPermissionStatusGranted:
- return PERMISSION_STATUS_GRANTED;
+ return PermissionStatus::GRANTED;
case blink::WebPermissionStatusDenied:
- return PERMISSION_STATUS_DENIED;
+ return PermissionStatus::DENIED;
case blink::WebPermissionStatusPrompt:
- return PERMISSION_STATUS_ASK;
+ return PermissionStatus::ASK;
}
NOTREACHED();
- return PERMISSION_STATUS_DENIED;
+ return PermissionStatus::DENIED;
}
blink::WebPermissionStatus GetWebPermissionStatus(PermissionStatus status) {
switch (status) {
- case PERMISSION_STATUS_GRANTED:
+ case PermissionStatus::GRANTED:
return blink::WebPermissionStatusGranted;
- case PERMISSION_STATUS_DENIED:
+ case PermissionStatus::DENIED:
return blink::WebPermissionStatusDenied;
- case PERMISSION_STATUS_ASK:
+ case PermissionStatus::ASK:
return blink::WebPermissionStatusPrompt;
}
@@ -79,7 +82,9 @@ bool PermissionDispatcher::IsObservable(blink::WebPermissionType type) {
return type == blink::WebPermissionTypeGeolocation ||
type == blink::WebPermissionTypeNotifications ||
type == blink::WebPermissionTypePushNotifications ||
- type == blink::WebPermissionTypeMidiSysEx;
+ type == blink::WebPermissionTypeMidiSysEx ||
+ type == blink::WebPermissionTypeMidi ||
+ type == blink::WebPermissionTypeBackgroundSync;
}
PermissionDispatcher::PermissionDispatcher(ServiceRegistry* service_registry)
@@ -130,16 +135,14 @@ void PermissionDispatcher::startListening(
RegisterObserver(observer);
- GetNextPermissionChange(type,
- origin.string().utf8(),
- observer,
+ GetNextPermissionChange(type, origin.string().utf8(), observer,
// We initialize with an arbitrary value because the
// mojo service wants a value. Worst case, the
// observer will get notified about a non-change which
// should be a no-op. After the first notification,
// GetNextPermissionChange will be called with the
// latest known value.
- PERMISSION_STATUS_ASK);
+ PermissionStatus::ASK);
}
void PermissionDispatcher::stopListening(WebPermissionObserver* observer) {
@@ -184,17 +187,14 @@ void PermissionDispatcher::StartListeningForWorker(
int worker_thread_id,
const base::Callback<void(blink::WebPermissionStatus)>& callback) {
GetPermissionServicePtr()->GetNextPermissionChange(
- GetPermissionName(type),
- origin,
+ GetPermissionName(type), origin,
// We initialize with an arbitrary value because the mojo service wants a
// value. Worst case, the observer will get notified about a non-change
// which should be a no-op. After the first notification,
// GetNextPermissionChange will be called with the latest known value.
- PERMISSION_STATUS_ASK,
+ PermissionStatus::ASK,
base::Bind(&PermissionDispatcher::OnPermissionChangedForWorker,
- base::Unretained(this),
- worker_thread_id,
- callback));
+ base::Unretained(this), worker_thread_id, callback));
}
void PermissionDispatcher::GetNextPermissionChangeForWorker(
@@ -215,23 +215,24 @@ void PermissionDispatcher::GetNextPermissionChangeForWorker(
// static
void PermissionDispatcher::RunPermissionCallbackOnWorkerThread(
- scoped_ptr<blink::WebPermissionCallback> callback,
+ std::unique_ptr<blink::WebPermissionCallback> callback,
blink::WebPermissionStatus status) {
callback->onSuccess(status);
}
void PermissionDispatcher::RunPermissionsCallbackOnWorkerThread(
- scoped_ptr<blink::WebPermissionsCallback> callback,
- scoped_ptr<blink::WebVector<blink::WebPermissionStatus>> statuses) {
- callback->onSuccess(blink::adoptWebPtr(statuses.release()));
+ std::unique_ptr<blink::WebPermissionsCallback> callback,
+ std::unique_ptr<blink::WebVector<blink::WebPermissionStatus>> statuses) {
+ callback->onSuccess(std::move(statuses));
}
-PermissionServicePtr& PermissionDispatcher::GetPermissionServicePtr() {
+blink::mojom::PermissionService*
+PermissionDispatcher::GetPermissionServicePtr() {
if (!permission_service_.get()) {
service_registry_->ConnectToRemoteService(
mojo::GetProxy(&permission_service_));
}
- return permission_service_;
+ return permission_service_.get();
}
void PermissionDispatcher::QueryPermissionInternal(
@@ -244,8 +245,8 @@ void PermissionDispatcher::QueryPermissionInternal(
// the |permission_service_| pipe will be destroyed too so OnQueryPermission
// will not be called.
uintptr_t callback_key = reinterpret_cast<uintptr_t>(callback);
- permission_callbacks_.add(callback_key,
- scoped_ptr<blink::WebPermissionCallback>(callback));
+ permission_callbacks_.add(
+ callback_key, std::unique_ptr<blink::WebPermissionCallback>(callback));
GetPermissionServicePtr()->HasPermission(
GetPermissionName(type),
@@ -266,13 +267,12 @@ void PermissionDispatcher::RequestPermissionInternal(
// the |permission_service_| pipe will be destroyed too so OnQueryPermission
// will not be called.
uintptr_t callback_key = reinterpret_cast<uintptr_t>(callback);
- permission_callbacks_.add(callback_key,
- scoped_ptr<blink::WebPermissionCallback>(callback));
+ permission_callbacks_.add(
+ callback_key, std::unique_ptr<blink::WebPermissionCallback>(callback));
GetPermissionServicePtr()->RequestPermission(
GetPermissionName(type),
origin,
- blink::WebUserGestureIndicator::isProcessingUserGesture(),
base::Bind(&PermissionDispatcher::OnPermissionResponse,
base::Unretained(this),
worker_thread_id,
@@ -289,8 +289,8 @@ void PermissionDispatcher::RequestPermissionsInternal(
// the |permission_service_| pipe will be destroyed too so OnQueryPermission
// will not be called.
uintptr_t callback_key = reinterpret_cast<uintptr_t>(callback);
- permissions_callbacks_.add(callback_key,
- scoped_ptr<blink::WebPermissionsCallback>(callback));
+ permissions_callbacks_.add(
+ callback_key, std::unique_ptr<blink::WebPermissionsCallback>(callback));
mojo::Array<PermissionName> names(types.size());
for (size_t i = 0; i < types.size(); ++i)
@@ -298,7 +298,6 @@ void PermissionDispatcher::RequestPermissionsInternal(
GetPermissionServicePtr()->RequestPermissions(
std::move(names), origin,
- blink::WebUserGestureIndicator::isProcessingUserGesture(),
base::Bind(&PermissionDispatcher::OnRequestPermissionsResponse,
base::Unretained(this), worker_thread_id, callback_key));
}
@@ -313,8 +312,8 @@ void PermissionDispatcher::RevokePermissionInternal(
// the |permission_service_| pipe will be destroyed too so OnQueryPermission
// will not be called.
uintptr_t callback_key = reinterpret_cast<uintptr_t>(callback);
- permission_callbacks_.add(callback_key,
- scoped_ptr<blink::WebPermissionCallback>(callback));
+ permission_callbacks_.add(
+ callback_key, std::unique_ptr<blink::WebPermissionCallback>(callback));
GetPermissionServicePtr()->RevokePermission(
GetPermissionName(type),
@@ -325,11 +324,10 @@ void PermissionDispatcher::RevokePermissionInternal(
callback_key));
}
-void PermissionDispatcher::OnPermissionResponse(
- int worker_thread_id,
- uintptr_t callback_key,
- PermissionStatus result) {
- scoped_ptr<blink::WebPermissionCallback> callback =
+void PermissionDispatcher::OnPermissionResponse(int worker_thread_id,
+ uintptr_t callback_key,
+ PermissionStatus result) {
+ std::unique_ptr<blink::WebPermissionCallback> callback =
permission_callbacks_.take_and_erase(callback_key);
blink::WebPermissionStatus status = GetWebPermissionStatus(result);
@@ -350,9 +348,9 @@ void PermissionDispatcher::OnRequestPermissionsResponse(
int worker_thread_id,
uintptr_t callback_key,
const mojo::Array<PermissionStatus>& result) {
- scoped_ptr<blink::WebPermissionsCallback> callback =
+ std::unique_ptr<blink::WebPermissionsCallback> callback =
permissions_callbacks_.take_and_erase(callback_key);
- scoped_ptr<blink::WebVector<blink::WebPermissionStatus>> statuses(
+ std::unique_ptr<blink::WebVector<blink::WebPermissionStatus>> statuses(
new blink::WebVector<blink::WebPermissionStatus>(result.size()));
for (size_t i = 0; i < result.size(); i++)
@@ -368,14 +366,13 @@ void PermissionDispatcher::OnRequestPermissionsResponse(
return;
}
- callback->onSuccess(blink::adoptWebPtr(statuses.release()));
+ callback->onSuccess(std::move(statuses));
}
-void PermissionDispatcher::OnPermissionChanged(
- blink::WebPermissionType type,
- const std::string& origin,
- WebPermissionObserver* observer,
- PermissionStatus status) {
+void PermissionDispatcher::OnPermissionChanged(blink::WebPermissionType type,
+ const std::string& origin,
+ WebPermissionObserver* observer,
+ PermissionStatus status) {
if (!IsObserverRegistered(observer))
return;
diff --git a/chromium/content/child/permissions/permission_dispatcher.h b/chromium/content/child/permissions/permission_dispatcher.h
index 6cec47ba5b5..e6409740631 100644
--- a/chromium/content/child/permissions/permission_dispatcher.h
+++ b/chromium/content/child/permissions/permission_dispatcher.h
@@ -5,15 +5,15 @@
#ifndef CONTENT_CHILD_PERMISSIONS_PERMISSION_DISPATCHER_H_
#define CONTENT_CHILD_PERMISSIONS_PERMISSION_DISPATCHER_H_
+#include <memory>
#include <string>
#include "base/callback_forward.h"
#include "base/containers/scoped_ptr_hash_map.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "content/child/permissions/permission_observers_registry.h"
-#include "content/common/permission_service.mojom.h"
#include "third_party/WebKit/public/platform/modules/permissions/WebPermissionClient.h"
+#include "third_party/WebKit/public/platform/modules/permissions/permission.mojom.h"
namespace content {
@@ -86,22 +86,24 @@ class PermissionDispatcher : public blink::WebPermissionClient,
const base::Callback<void(blink::WebPermissionStatus)>& callback);
private:
- using PermissionCallbackMap = base::ScopedPtrHashMap<uintptr_t,
- scoped_ptr<blink::WebPermissionCallback>>;
- using PermissionsCallbackMap = base::ScopedPtrHashMap<uintptr_t,
- scoped_ptr<blink::WebPermissionsCallback>>;
+ using PermissionCallbackMap =
+ base::ScopedPtrHashMap<uintptr_t,
+ std::unique_ptr<blink::WebPermissionCallback>>;
+ using PermissionsCallbackMap =
+ base::ScopedPtrHashMap<uintptr_t,
+ std::unique_ptr<blink::WebPermissionsCallback>>;
// Runs the given |callback| with |status| as a parameter. It has to be run
// on a worker thread.
static void RunPermissionCallbackOnWorkerThread(
- scoped_ptr<blink::WebPermissionCallback> callback,
+ std::unique_ptr<blink::WebPermissionCallback> callback,
blink::WebPermissionStatus status);
static void RunPermissionsCallbackOnWorkerThread(
- scoped_ptr<blink::WebPermissionsCallback> callback,
- scoped_ptr<blink::WebVector<blink::WebPermissionStatus>> statuses);
+ std::unique_ptr<blink::WebPermissionsCallback> callback,
+ std::unique_ptr<blink::WebVector<blink::WebPermissionStatus>> statuses);
// Helper method that returns an initialized PermissionServicePtr.
- PermissionServicePtr& GetPermissionServicePtr();
+ blink::mojom::PermissionService* GetPermissionServicePtr();
void QueryPermissionInternal(blink::WebPermissionType type,
const std::string& origin,
@@ -124,24 +126,24 @@ class PermissionDispatcher : public blink::WebPermissionClient,
// This is the callback function used for query, request and revoke.
void OnPermissionResponse(int worker_thread_id,
uintptr_t callback_key,
- PermissionStatus status);
+ blink::mojom::PermissionStatus status);
void OnRequestPermissionsResponse(
int worker_thread_id,
uintptr_t callback_key,
- const mojo::Array<PermissionStatus>& status);
+ const mojo::Array<blink::mojom::PermissionStatus>& status);
void OnPermissionChanged(blink::WebPermissionType type,
const std::string& origin,
blink::WebPermissionObserver* observer,
- PermissionStatus status);
+ blink::mojom::PermissionStatus status);
void OnPermissionChangedForWorker(
int worker_thread_id,
const base::Callback<void(blink::WebPermissionStatus)>& callback,
- PermissionStatus status);
+ blink::mojom::PermissionStatus status);
void GetNextPermissionChange(blink::WebPermissionType type,
const std::string& origin,
blink::WebPermissionObserver* observer,
- PermissionStatus current_status);
+ blink::mojom::PermissionStatus current_status);
// Pending callbacks for query(), revoke() and request() single permission.
PermissionCallbackMap permission_callbacks_;
@@ -150,7 +152,7 @@ class PermissionDispatcher : public blink::WebPermissionClient,
PermissionsCallbackMap permissions_callbacks_;
ServiceRegistry* service_registry_;
- PermissionServicePtr permission_service_;
+ blink::mojom::PermissionServicePtr permission_service_;
DISALLOW_COPY_AND_ASSIGN(PermissionDispatcher);
};
diff --git a/chromium/content/child/plugin_message_generator.cc b/chromium/content/child/plugin_message_generator.cc
deleted file mode 100644
index d490345d44e..00000000000
--- a/chromium/content/child/plugin_message_generator.cc
+++ /dev/null
@@ -1,33 +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.
-
-// Get basic type definitions.
-#define IPC_MESSAGE_IMPL
-#include "content/child/plugin_message_generator.h"
-
-// Generate constructors.
-#include "ipc/struct_constructor_macros.h"
-#include "content/child/plugin_message_generator.h"
-
-// Generate destructors.
-#include "ipc/struct_destructor_macros.h"
-#include "content/child/plugin_message_generator.h"
-
-// Generate param traits write methods.
-#include "ipc/param_traits_write_macros.h"
-namespace IPC {
-#include "content/child/plugin_message_generator.h"
-} // namespace IPC
-
-// Generate param traits read methods.
-#include "ipc/param_traits_read_macros.h"
-namespace IPC {
-#include "content/child/plugin_message_generator.h"
-} // namespace IPC
-
-// Generate param traits log methods.
-#include "ipc/param_traits_log_macros.h"
-namespace IPC {
-#include "content/child/plugin_message_generator.h"
-} // namespace IPC
diff --git a/chromium/content/child/plugin_message_generator.h b/chromium/content/child/plugin_message_generator.h
deleted file mode 100644
index 9eddea2258f..00000000000
--- a/chromium/content/child/plugin_message_generator.h
+++ /dev/null
@@ -1,7 +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.
-
-// Multiply-included file, hence no include guard.
-
-#include "content/child/plugin_messages.h"
diff --git a/chromium/content/child/plugin_messages.h b/chromium/content/child/plugin_messages.h
deleted file mode 100644
index 8cf591b3d7f..00000000000
--- a/chromium/content/child/plugin_messages.h
+++ /dev/null
@@ -1,346 +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.
-//
-// Multiply-included message file, hence no include guard.
-
-#include <stdint.h>
-
-#include "build/build_config.h"
-#include "content/child/plugin_param_traits.h"
-#include "content/common/content_export.h"
-#include "content/common/content_param_traits.h"
-#include "content/common/cursors/webcursor.h"
-#include "content/public/common/common_param_traits.h"
-#include "ipc/ipc_channel_handle.h"
-#include "ipc/ipc_message_macros.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/ipc/gfx_param_traits.h"
-#include "ui/gfx/native_widget_types.h"
-
-#if defined(OS_POSIX)
-#include "base/file_descriptor_posix.h"
-#endif
-
-#undef IPC_MESSAGE_EXPORT
-#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
-
-#define IPC_MESSAGE_START PluginMsgStart
-
-IPC_STRUCT_BEGIN(PluginMsg_Init_Params)
- IPC_STRUCT_MEMBER(GURL, url)
- IPC_STRUCT_MEMBER(GURL, page_url)
- IPC_STRUCT_MEMBER(std::vector<std::string>, arg_names)
- IPC_STRUCT_MEMBER(std::vector<std::string>, arg_values)
- IPC_STRUCT_MEMBER(bool, load_manually)
- IPC_STRUCT_MEMBER(int, host_render_view_routing_id)
-IPC_STRUCT_END()
-
-IPC_STRUCT_BEGIN(PluginMsg_DidReceiveResponseParams)
- IPC_STRUCT_MEMBER(unsigned long, id)
- IPC_STRUCT_MEMBER(std::string, mime_type)
- IPC_STRUCT_MEMBER(std::string, headers)
- IPC_STRUCT_MEMBER(uint32_t, expected_length)
- IPC_STRUCT_MEMBER(uint32_t, last_modified)
- IPC_STRUCT_MEMBER(bool, request_is_seekable)
-IPC_STRUCT_END()
-
-IPC_STRUCT_BEGIN(PluginMsg_FetchURL_Params)
- IPC_STRUCT_MEMBER(unsigned long, resource_id)
- IPC_STRUCT_MEMBER(GURL, url)
- IPC_STRUCT_MEMBER(GURL, first_party_for_cookies)
- IPC_STRUCT_MEMBER(std::string, method)
- IPC_STRUCT_MEMBER(std::vector<char>, post_data)
- IPC_STRUCT_MEMBER(GURL, referrer)
- IPC_STRUCT_MEMBER(blink::WebReferrerPolicy, referrer_policy)
- IPC_STRUCT_MEMBER(bool, notify_redirect)
- IPC_STRUCT_MEMBER(bool, is_plugin_src_load)
- IPC_STRUCT_MEMBER(int, render_frame_id)
-IPC_STRUCT_END()
-
-IPC_STRUCT_BEGIN(PluginMsg_UpdateGeometry_Param)
- IPC_STRUCT_MEMBER(gfx::Rect, window_rect)
- IPC_STRUCT_MEMBER(gfx::Rect, clip_rect)
- IPC_STRUCT_MEMBER(TransportDIB::Handle, windowless_buffer0)
- IPC_STRUCT_MEMBER(TransportDIB::Handle, windowless_buffer1)
- IPC_STRUCT_MEMBER(int, windowless_buffer_index)
-IPC_STRUCT_END()
-
-//-----------------------------------------------------------------------------
-// Plugin messages
-// These are messages sent from the renderer process to the plugin process.
-// Tells the plugin process to create a new plugin instance with the given
-// id. A corresponding WebPluginDelegateStub is created which hosts the
-// WebPluginDelegateImpl.
-IPC_SYNC_MESSAGE_CONTROL1_1(PluginMsg_CreateInstance,
- std::string /* mime_type */,
- int /* instance_id */)
-
-// The WebPluginDelegateProxy sends this to the WebPluginDelegateStub in its
-// destructor, so that the stub deletes the actual WebPluginDelegateImpl
-// object that it's hosting.
-IPC_SYNC_MESSAGE_CONTROL1_0(PluginMsg_DestroyInstance,
- int /* instance_id */)
-
-IPC_SYNC_MESSAGE_CONTROL0_1(PluginMsg_GenerateRouteID,
- int /* id */)
-
-// The messages below all map to WebPluginDelegate methods.
-IPC_SYNC_MESSAGE_ROUTED1_2(PluginMsg_Init,
- PluginMsg_Init_Params,
- bool /* transparent */,
- bool /* result */)
-
-// Used to synchronously request a paint for windowless plugins.
-IPC_SYNC_MESSAGE_ROUTED1_0(PluginMsg_Paint,
- gfx::Rect /* damaged_rect */)
-
-// Sent by the renderer after it paints from its backing store so that the
-// plugin knows it can send more invalidates.
-IPC_MESSAGE_ROUTED0(PluginMsg_DidPaint)
-
-IPC_SYNC_MESSAGE_ROUTED0_1(PluginMsg_GetPluginScriptableObject,
- int /* route_id */)
-
-// Gets the form value of the plugin instance synchronously.
-IPC_SYNC_MESSAGE_ROUTED0_2(PluginMsg_GetFormValue,
- base::string16 /* value */,
- bool /* success */)
-
-// Updates the plugin location.
-IPC_MESSAGE_ROUTED1(PluginMsg_UpdateGeometry,
- PluginMsg_UpdateGeometry_Param)
-
-// A synchronous version of above.
-IPC_SYNC_MESSAGE_ROUTED1_0(PluginMsg_UpdateGeometrySync,
- PluginMsg_UpdateGeometry_Param)
-
-IPC_SYNC_MESSAGE_ROUTED1_0(PluginMsg_SetFocus,
- bool /* focused */)
-
-IPC_SYNC_MESSAGE_ROUTED1_2(PluginMsg_HandleInputEvent,
- IPC::WebInputEventPointer /* event */,
- bool /* handled */,
- content::WebCursor /* cursor type*/)
-
-IPC_MESSAGE_ROUTED1(PluginMsg_SetContentAreaFocus,
- bool /* has_focus */)
-
-IPC_SYNC_MESSAGE_ROUTED3_0(PluginMsg_WillSendRequest,
- unsigned long /* id */,
- GURL /* url */,
- int /* http_status_code */)
-
-IPC_MESSAGE_ROUTED1(PluginMsg_DidReceiveResponse,
- PluginMsg_DidReceiveResponseParams)
-
-IPC_MESSAGE_ROUTED3(PluginMsg_DidReceiveData,
- unsigned long /* id */,
- std::vector<char> /* buffer */,
- int /* data_offset */)
-
-IPC_MESSAGE_ROUTED1(PluginMsg_DidFinishLoading,
- unsigned long /* id */)
-
-IPC_MESSAGE_ROUTED1(PluginMsg_DidFail,
- unsigned long /* id */)
-
-IPC_MESSAGE_CONTROL1(PluginMsg_SignalModalDialogEvent,
- int /* render_view_id */)
-
-IPC_MESSAGE_CONTROL1(PluginMsg_ResetModalDialogEvent,
- int /* render_view_id */)
-
-#if defined(OS_WIN)
-IPC_MESSAGE_ROUTED4(PluginMsg_ImeCompositionUpdated,
- base::string16 /* text */,
- std::vector<int> /* clauses */,
- std::vector<int>, /* target */
- int /* cursor_position */)
-
-IPC_MESSAGE_ROUTED1(PluginMsg_ImeCompositionCompleted,
- base::string16 /* text */)
-#endif
-
-#if defined(OS_MACOSX)
-IPC_MESSAGE_ROUTED1(PluginMsg_SetWindowFocus,
- bool /* has_focus */)
-
-IPC_MESSAGE_ROUTED0(PluginMsg_ContainerHidden)
-
-IPC_MESSAGE_ROUTED3(PluginMsg_ContainerShown,
- gfx::Rect /* window_frame */,
- gfx::Rect /* view_frame */,
- bool /* has_focus */)
-
-IPC_MESSAGE_ROUTED2(PluginMsg_WindowFrameChanged,
- gfx::Rect /* window_frame */,
- gfx::Rect /* view_frame */)
-
-IPC_MESSAGE_ROUTED1(PluginMsg_ImeCompositionCompleted,
- base::string16 /* text */)
-#endif
-
-//-----------------------------------------------------------------------------
-// PluginHost messages
-// These are messages sent from the plugin process to the renderer process.
-// They all map to the corresponding WebPlugin methods.
-// Sends the plugin window information to the renderer.
-// The window parameter is a handle to the window if the plugin is a windowed
-// plugin. It is NULL for windowless plugins.
-IPC_SYNC_MESSAGE_ROUTED1_0(PluginHostMsg_SetWindow,
- gfx::PluginWindowHandle /* window */)
-
-IPC_MESSAGE_ROUTED1(PluginHostMsg_CancelResource,
- int /* id */)
-
-IPC_MESSAGE_ROUTED1(PluginHostMsg_InvalidateRect,
- gfx::Rect /* rect */)
-
-IPC_SYNC_MESSAGE_ROUTED1_1(PluginHostMsg_GetWindowScriptNPObject,
- int /* route id */,
- bool /* success */)
-
-IPC_SYNC_MESSAGE_ROUTED1_1(PluginHostMsg_GetPluginElement,
- int /* route id */,
- bool /* success */)
-
-IPC_SYNC_MESSAGE_ROUTED1_2(PluginHostMsg_ResolveProxy,
- GURL /* url */,
- bool /* result */,
- std::string /* proxy list */)
-
-IPC_MESSAGE_ROUTED3(PluginHostMsg_SetCookie,
- GURL /* url */,
- GURL /* first_party_for_cookies */,
- std::string /* cookie */)
-
-IPC_SYNC_MESSAGE_ROUTED2_1(PluginHostMsg_GetCookies,
- GURL /* url */,
- GURL /* first_party_for_cookies */,
- std::string /* cookies */)
-
-IPC_MESSAGE_ROUTED0(PluginHostMsg_CancelDocumentLoad)
-
-IPC_MESSAGE_ROUTED0(PluginHostMsg_DidStartLoading)
-IPC_MESSAGE_ROUTED0(PluginHostMsg_DidStopLoading)
-
-IPC_MESSAGE_ROUTED2(PluginHostMsg_DeferResourceLoading,
- unsigned long /* resource_id */,
- bool /* defer */)
-
-IPC_SYNC_MESSAGE_CONTROL1_0(PluginHostMsg_SetException,
- std::string /* message */)
-
-IPC_MESSAGE_CONTROL0(PluginHostMsg_PluginShuttingDown)
-
-IPC_MESSAGE_ROUTED2(PluginHostMsg_URLRedirectResponse,
- bool /* allow */,
- int /* resource_id */)
-
-IPC_SYNC_MESSAGE_ROUTED1_1(PluginHostMsg_CheckIfRunInsecureContent,
- GURL /* url */,
- bool /* result */)
-
-#if defined(OS_WIN)
-// The modal_loop_pump_messages_event parameter is an event handle which is
-// passed in for windowless plugins and is used to indicate if messages
-// are to be pumped in sync calls to the plugin process. Currently used
-// in HandleEvent calls.
-IPC_SYNC_MESSAGE_ROUTED2_0(PluginHostMsg_SetWindowlessData,
- HANDLE /* modal_loop_pump_messages_event */,
- gfx::NativeViewId /* dummy_activation_window*/)
-
-// Send the IME status retrieved from a windowless plugin. A windowless plugin
-// uses the IME attached to a browser process as a renderer does. A plugin
-// sends this message to control the IME status of a browser process. I would
-// note that a plugin sends this message to a renderer process that hosts this
-// plugin (not directly to a browser process) so the renderer process can
-// update its IME status.
-IPC_MESSAGE_ROUTED2(PluginHostMsg_NotifyIMEStatus,
- int /* input_type */,
- gfx::Rect /* caret_rect */)
-#endif
-
-#if defined(OS_MACOSX)
-IPC_MESSAGE_ROUTED1(PluginHostMsg_FocusChanged,
- bool /* focused */)
-
-IPC_MESSAGE_ROUTED0(PluginHostMsg_StartIme)
-
-//----------------------------------------------------------------------
-// Core Animation plugin implementation rendering via compositor.
-
-// Notifies the renderer process that this plugin will be using the
-// accelerated rendering path.
-IPC_MESSAGE_ROUTED0(PluginHostMsg_AcceleratedPluginEnabledRendering)
-
-// Notifies the renderer process that the plugin allocated a new
-// IOSurface into which it is rendering. The renderer process forwards
-// this IOSurface to the GPU process, causing it to be bound to a
-// texture from which the compositor can render. Any previous
-// IOSurface allocated by this plugin must be implicitly released by
-// the receipt of this message.
-IPC_MESSAGE_ROUTED3(PluginHostMsg_AcceleratedPluginAllocatedIOSurface,
- int32_t /* width */,
- int32_t /* height */,
- uint32_t /* surface_id */)
-
-// Notifies the renderer process that the plugin produced a new frame
-// of content into its IOSurface, and therefore that the compositor
-// needs to redraw.
-IPC_MESSAGE_ROUTED0(PluginHostMsg_AcceleratedPluginSwappedIOSurface)
-#endif
-
-
-//-----------------------------------------------------------------------------
-// NPObject messages
-// These are messages used to marshall NPObjects. They are sent both from the
-// plugin to the renderer and from the renderer to the plugin.
-IPC_SYNC_MESSAGE_ROUTED0_0(NPObjectMsg_Release)
-
-IPC_SYNC_MESSAGE_ROUTED1_1(NPObjectMsg_HasMethod,
- content::NPIdentifier_Param /* name */,
- bool /* result */)
-
-IPC_SYNC_MESSAGE_ROUTED3_2(NPObjectMsg_Invoke,
- bool /* is_default */,
- content::NPIdentifier_Param /* method */,
- std::vector<content::NPVariant_Param> /* args */,
- content::NPVariant_Param /* result_param */,
- bool /* result */)
-
-IPC_SYNC_MESSAGE_ROUTED1_1(NPObjectMsg_HasProperty,
- content::NPIdentifier_Param /* name */,
- bool /* result */)
-
-IPC_SYNC_MESSAGE_ROUTED1_2(NPObjectMsg_GetProperty,
- content::NPIdentifier_Param /* name */,
- content::NPVariant_Param /* property */,
- bool /* result */)
-
-IPC_SYNC_MESSAGE_ROUTED2_1(NPObjectMsg_SetProperty,
- content::NPIdentifier_Param /* name */,
- content::NPVariant_Param /* property */,
- bool /* result */)
-
-IPC_SYNC_MESSAGE_ROUTED1_1(NPObjectMsg_RemoveProperty,
- content::NPIdentifier_Param /* name */,
- bool /* result */)
-
-IPC_SYNC_MESSAGE_ROUTED0_0(NPObjectMsg_Invalidate)
-
-IPC_SYNC_MESSAGE_ROUTED0_2(NPObjectMsg_Enumeration,
- std::vector<content::NPIdentifier_Param> /* value */,
- bool /* result */)
-
-IPC_SYNC_MESSAGE_ROUTED1_2(NPObjectMsg_Construct,
- std::vector<content::NPVariant_Param> /* args */,
- content::NPVariant_Param /* result_param */,
- bool /* result */)
-
-IPC_SYNC_MESSAGE_ROUTED2_2(NPObjectMsg_Evaluate,
- std::string /* script */,
- bool /* popups_allowed */,
- content::NPVariant_Param /* result_param */,
- bool /* result */)
diff --git a/chromium/content/child/plugin_param_traits.cc b/chromium/content/child/plugin_param_traits.cc
deleted file mode 100644
index 903936ad917..00000000000
--- a/chromium/content/child/plugin_param_traits.cc
+++ /dev/null
@@ -1,136 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/child/plugin_param_traits.h"
-
-#include "base/strings/string_number_conversions.h"
-#include "ipc/ipc_message_utils.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
-
-namespace content {
-
-NPIdentifier_Param::NPIdentifier_Param()
- : identifier() {
-}
-
-NPIdentifier_Param::~NPIdentifier_Param() {
-}
-
-NPVariant_Param::NPVariant_Param()
- : type(NPVARIANT_PARAM_VOID),
- bool_value(false),
- int_value(0),
- double_value(0),
- npobject_routing_id(-1),
- npobject_owner_id(-1) {
-}
-
-NPVariant_Param::~NPVariant_Param() {
-}
-
-} // namespace content
-
-using content::NPIdentifier_Param;
-using content::NPVariant_Param;
-
-namespace IPC {
-
-void ParamTraits<NPVariant_Param>::Write(Message* m, const param_type& p) {
- WriteParam(m, static_cast<int>(p.type));
- if (p.type == content::NPVARIANT_PARAM_BOOL) {
- WriteParam(m, p.bool_value);
- } else if (p.type == content::NPVARIANT_PARAM_INT) {
- WriteParam(m, p.int_value);
- } else if (p.type == content::NPVARIANT_PARAM_DOUBLE) {
- WriteParam(m, p.double_value);
- } else if (p.type == content::NPVARIANT_PARAM_STRING) {
- WriteParam(m, p.string_value);
- } else if (p.type == content::NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID ||
- p.type == content::NPVARIANT_PARAM_RECEIVER_OBJECT_ROUTING_ID) {
- // This is the routing id used to connect NPObjectProxy in the other
- // process with NPObjectStub in this process or to identify the raw
- // npobject pointer to be used in the callee process.
- WriteParam(m, p.npobject_routing_id);
- // This is a routing Id used to identify the plugin instance that owns
- // the object, for ownership-tracking purposes.
- WriteParam(m, p.npobject_owner_id);
- } else {
- DCHECK(p.type == content::NPVARIANT_PARAM_VOID ||
- p.type == content::NPVARIANT_PARAM_NULL);
- }
-}
-
-bool ParamTraits<NPVariant_Param>::Read(const Message* m,
- base::PickleIterator* iter,
- param_type* r) {
- int type;
- if (!ReadParam(m, iter, &type))
- return false;
-
- bool result = false;
- r->type = static_cast<content::NPVariant_ParamEnum>(type);
- if (r->type == content::NPVARIANT_PARAM_BOOL) {
- result = ReadParam(m, iter, &r->bool_value);
- } else if (r->type == content::NPVARIANT_PARAM_INT) {
- result = ReadParam(m, iter, &r->int_value);
- } else if (r->type == content::NPVARIANT_PARAM_DOUBLE) {
- result = ReadParam(m, iter, &r->double_value);
- } else if (r->type == content::NPVARIANT_PARAM_STRING) {
- result = ReadParam(m, iter, &r->string_value);
- } else if (r->type == content::NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID ||
- r->type == content::NPVARIANT_PARAM_RECEIVER_OBJECT_ROUTING_ID) {
- result = ReadParam(m, iter, &r->npobject_routing_id) &&
- ReadParam(m, iter, &r->npobject_owner_id);
- } else if ((r->type == content::NPVARIANT_PARAM_VOID) ||
- (r->type == content::NPVARIANT_PARAM_NULL)) {
- result = true;
- } else {
- NOTREACHED();
- }
-
- return result;
-}
-
-void ParamTraits<NPVariant_Param>::Log(const param_type& p, std::string* l) {
- l->append(
- base::StringPrintf("NPVariant_Param(%d, ", static_cast<int>(p.type)));
- if (p.type == content::NPVARIANT_PARAM_BOOL) {
- LogParam(p.bool_value, l);
- } else if (p.type == content::NPVARIANT_PARAM_INT) {
- LogParam(p.int_value, l);
- } else if (p.type == content::NPVARIANT_PARAM_DOUBLE) {
- LogParam(p.double_value, l);
- } else if (p.type == content::NPVARIANT_PARAM_STRING) {
- LogParam(p.string_value, l);
- } else if (p.type == content::NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID ||
- p.type == content::NPVARIANT_PARAM_RECEIVER_OBJECT_ROUTING_ID) {
- LogParam(p.npobject_routing_id, l);
- } else {
- l->append("<none>");
- }
- l->append(")");
-}
-
-void ParamTraits<NPIdentifier_Param>::Write(Message* m, const param_type& p) {
- content::SerializeNPIdentifier(p.identifier, m);
-}
-
-bool ParamTraits<NPIdentifier_Param>::Read(const Message* m,
- base::PickleIterator* iter,
- param_type* r) {
- return content::DeserializeNPIdentifier(iter, &r->identifier);
-}
-
-void ParamTraits<NPIdentifier_Param>::Log(const param_type& p, std::string* l) {
- if (blink::WebBindings::identifierIsString(p.identifier)) {
- NPUTF8* str = blink::WebBindings::utf8FromIdentifier(p.identifier);
- l->append(str);
- free(str);
- } else {
- l->append(base::IntToString(
- blink::WebBindings::intFromIdentifier(p.identifier)));
- }
-}
-
-} // namespace IPC
diff --git a/chromium/content/child/plugin_param_traits.h b/chromium/content/child/plugin_param_traits.h
deleted file mode 100644
index 03628c92519..00000000000
--- a/chromium/content/child/plugin_param_traits.h
+++ /dev/null
@@ -1,87 +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.
-
-// This file is used to define IPC::ParamTraits<> specializations for a number
-// of types so that they can be serialized over IPC. IPC::ParamTraits<>
-// specializations for basic types (like int and std::string) and types in the
-// 'base' project can be found in ipc/ipc_message_utils.h. This file contains
-// specializations for types that are used by the content code, and which need
-// manual serialization code. This is usually because they're not structs with
-// public members, or because the same type is being used in multiple
-// *_messages.h headers.
-
-#ifndef CONTENT_CHILD_PLUGIN_PARAM_TRAITS_H_
-#define CONTENT_CHILD_PLUGIN_PARAM_TRAITS_H_
-
-#include <string>
-
-#include "content/child/npapi/npruntime_util.h"
-#include "ipc/ipc_message.h"
-#include "ipc/ipc_param_traits.h"
-
-namespace content {
-
-// Define the NPVariant_Param struct and its enum here since it needs manual
-// serialization code.
-enum NPVariant_ParamEnum {
- NPVARIANT_PARAM_VOID,
- NPVARIANT_PARAM_NULL,
- NPVARIANT_PARAM_BOOL,
- NPVARIANT_PARAM_INT,
- NPVARIANT_PARAM_DOUBLE,
- NPVARIANT_PARAM_STRING,
- // Used when when the NPObject is running in the caller's process, so we
- // create an NPObjectProxy in the other process. To support object ownership
- // tracking the routing-Id of the NPObject's owning plugin instance is
- // passed alongside that of the object itself.
- NPVARIANT_PARAM_SENDER_OBJECT_ROUTING_ID,
- // Used when the NPObject we're sending is running in the callee's process
- // (i.e. we have an NPObjectProxy for it). In that case we want the callee
- // to just use the raw pointer.
- NPVARIANT_PARAM_RECEIVER_OBJECT_ROUTING_ID,
-};
-
-struct NPVariant_Param {
- NPVariant_Param();
- ~NPVariant_Param();
-
- NPVariant_ParamEnum type;
- bool bool_value;
- int int_value;
- double double_value;
- std::string string_value;
- int npobject_routing_id;
- int npobject_owner_id;
-};
-
-struct NPIdentifier_Param {
- NPIdentifier_Param();
- ~NPIdentifier_Param();
-
- NPIdentifier identifier;
-};
-
-} // namespace content
-
-namespace IPC {
-
-template <>
-struct ParamTraits<content::NPVariant_Param> {
- typedef content::NPVariant_Param param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
- static void Log(const param_type& p, std::string* l);
-};
-
-template <>
-struct ParamTraits<content::NPIdentifier_Param> {
- typedef content::NPIdentifier_Param param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
- static void Log(const param_type& p, std::string* l);
-};
-
-} // namespace IPC
-
-#endif // CONTENT_CHILD_PLUGIN_PARAM_TRAITS_H_
diff --git a/chromium/content/child/power_monitor_broadcast_source_unittest.cc b/chromium/content/child/power_monitor_broadcast_source_unittest.cc
index befcf246192..2930c54ea1e 100644
--- a/chromium/content/child/power_monitor_broadcast_source_unittest.cc
+++ b/chromium/content/child/power_monitor_broadcast_source_unittest.cc
@@ -17,7 +17,7 @@ class PowerMonitorBroadcastSourceTest : public testing::Test {
PowerMonitorBroadcastSourceTest() {
power_monitor_source_ = new PowerMonitorBroadcastSource();
power_monitor_.reset(new base::PowerMonitor(
- scoped_ptr<base::PowerMonitorSource>(power_monitor_source_)));
+ std::unique_ptr<base::PowerMonitorSource>(power_monitor_source_)));
}
~PowerMonitorBroadcastSourceTest() override {}
@@ -28,7 +28,7 @@ class PowerMonitorBroadcastSourceTest : public testing::Test {
private:
PowerMonitorBroadcastSource* power_monitor_source_;
- scoped_ptr<base::PowerMonitor> power_monitor_;
+ std::unique_ptr<base::PowerMonitor> power_monitor_;
DISALLOW_COPY_AND_ASSIGN(PowerMonitorBroadcastSourceTest);
};
diff --git a/chromium/content/child/process_control_impl.cc b/chromium/content/child/process_control_impl.cc
index a53c01129e6..fb0cd145981 100644
--- a/chromium/content/child/process_control_impl.cc
+++ b/chromium/content/child/process_control_impl.cc
@@ -7,9 +7,8 @@
#include <utility>
#include "base/stl_util.h"
+#include "content/common/mojo/static_loader.h"
#include "content/public/common/content_client.h"
-#include "mojo/shell/static_application_loader.h"
-#include "url/gurl.h"
namespace content {
@@ -17,30 +16,29 @@ ProcessControlImpl::ProcessControlImpl() {
}
ProcessControlImpl::~ProcessControlImpl() {
- STLDeleteValues(&url_to_loader_map_);
+ STLDeleteValues(&name_to_loader_map_);
}
void ProcessControlImpl::LoadApplication(
- const mojo::String& url,
- mojo::InterfaceRequest<mojo::Application> request,
+ const mojo::String& name,
+ mojo::InterfaceRequest<mojo::shell::mojom::ShellClient> request,
const LoadApplicationCallback& callback) {
// Only register loaders when we need it.
if (!has_registered_loaders_) {
- DCHECK(url_to_loader_map_.empty());
- RegisterApplicationLoaders(&url_to_loader_map_);
+ DCHECK(name_to_loader_map_.empty());
+ RegisterLoaders(&name_to_loader_map_);
has_registered_loaders_ = true;
}
- GURL application_url = GURL(url.To<std::string>());
- auto it = url_to_loader_map_.find(application_url);
- if (it == url_to_loader_map_.end()) {
+ auto it = name_to_loader_map_.find(name);
+ if (it == name_to_loader_map_.end()) {
callback.Run(false);
OnLoadFailed();
return;
}
callback.Run(true);
- it->second->Load(application_url, std::move(request));
+ it->second->Load(name, std::move(request));
}
} // namespace content
diff --git a/chromium/content/child/process_control_impl.h b/chromium/content/child/process_control_impl.h
index 6d85c509e26..91afa4acb7d 100644
--- a/chromium/content/child/process_control_impl.h
+++ b/chromium/content/child/process_control_impl.h
@@ -10,41 +10,39 @@
#include "base/macros.h"
#include "content/common/process_control.mojom.h"
#include "mojo/public/cpp/bindings/interface_request.h"
-#include "mojo/shell/public/interfaces/application.mojom.h"
-
-class GURL;
+#include "mojo/shell/public/interfaces/shell_client.mojom.h"
namespace mojo {
namespace shell {
-class ApplicationLoader;
+class Loader;
} // namespace shell
} // namespace mojo
namespace content {
-// Default implementation of the ProcessControl interface.
-class ProcessControlImpl : public ProcessControl {
+// Default implementation of the mojom::ProcessControl interface.
+class ProcessControlImpl : public mojom::ProcessControl {
public:
ProcessControlImpl();
~ProcessControlImpl() override;
- using URLToLoaderMap = std::map<GURL, mojo::shell::ApplicationLoader*>;
+ using NameToLoaderMap = std::map<std::string, mojo::shell::Loader*>;
- // Registers Mojo applications loaders for URLs.
- virtual void RegisterApplicationLoaders(
- URLToLoaderMap* url_to_loader_map) = 0;
+ // Registers Mojo loaders for names.
+ virtual void RegisterLoaders(NameToLoaderMap* name_to_loader_map) = 0;
// ProcessControl:
- void LoadApplication(const mojo::String& url,
- mojo::InterfaceRequest<mojo::Application> request,
- const LoadApplicationCallback& callback) override;
+ void LoadApplication(
+ const mojo::String& name,
+ mojo::InterfaceRequest<mojo::shell::mojom::ShellClient> request,
+ const LoadApplicationCallback& callback) override;
private:
// Called if a LoadApplication request fails.
virtual void OnLoadFailed() {}
bool has_registered_loaders_ = false;
- URLToLoaderMap url_to_loader_map_;
+ NameToLoaderMap name_to_loader_map_;
DISALLOW_COPY_AND_ASSIGN(ProcessControlImpl);
};
diff --git a/chromium/content/child/push_messaging/push_provider.cc b/chromium/content/child/push_messaging/push_provider.cc
index f8e807def7b..660e59b7650 100644
--- a/chromium/content/child/push_messaging/push_provider.cc
+++ b/chromium/content/child/push_messaging/push_provider.cc
@@ -4,8 +4,10 @@
#include "content/child/push_messaging/push_provider.h"
+#include <memory>
+
#include "base/lazy_instance.h"
-#include "base/memory/scoped_ptr.h"
+#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "base/threading/thread_local.h"
#include "content/child/push_messaging/push_dispatcher.h"
@@ -75,8 +77,14 @@ void PushProvider::subscribe(
subscription_callbacks_.AddWithID(callbacks, request_id);
int64_t service_worker_registration_id =
GetServiceWorkerRegistrationId(service_worker_registration);
+ PushSubscriptionOptions content_options;
+ content_options.user_visible_only = options.userVisibleOnly;
+
+ // Just treat the server key as a string of bytes and pass it to the push
+ // service.
+ content_options.sender_info = options.applicationServerKey.latin1();
thread_safe_sender_->Send(new PushMessagingHostMsg_SubscribeFromWorker(
- request_id, service_worker_registration_id, options.userVisibleOnly));
+ request_id, service_worker_registration_id, content_options));
}
void PushProvider::unsubscribe(
@@ -155,8 +163,8 @@ void PushProvider::OnSubscribeFromWorkerSuccess(
if (!callbacks)
return;
- callbacks->onSuccess(blink::adoptWebPtr(
- new blink::WebPushSubscription(endpoint, p256dh, auth)));
+ callbacks->onSuccess(
+ base::WrapUnique(new blink::WebPushSubscription(endpoint, p256dh, auth)));
subscription_callbacks_.Remove(request_id);
}
@@ -215,8 +223,8 @@ void PushProvider::OnGetSubscriptionSuccess(
if (!callbacks)
return;
- callbacks->onSuccess(blink::adoptWebPtr(
- new blink::WebPushSubscription(endpoint, p256dh, auth)));
+ callbacks->onSuccess(
+ base::WrapUnique(new blink::WebPushSubscription(endpoint, p256dh, auth)));
subscription_callbacks_.Remove(request_id);
}
diff --git a/chromium/content/child/request_extra_data.cc b/chromium/content/child/request_extra_data.cc
index 5105c3397b1..b26120bcabc 100644
--- a/chromium/content/child/request_extra_data.cc
+++ b/chromium/content/child/request_extra_data.cc
@@ -23,6 +23,7 @@ RequestExtraData::RequestExtraData()
transferred_request_child_id_(-1),
transferred_request_request_id_(-1),
service_worker_provider_id_(kInvalidServiceWorkerProviderId),
+ originated_from_service_worker_(false),
lofi_state_(LOFI_UNSPECIFIED) {
}
diff --git a/chromium/content/child/request_extra_data.h b/chromium/content/child/request_extra_data.h
index 0905789a2a0..5bb859e827c 100644
--- a/chromium/content/child/request_extra_data.h
+++ b/chromium/content/child/request_extra_data.h
@@ -90,6 +90,14 @@ class CONTENT_EXPORT RequestExtraData
int service_worker_provider_id) {
service_worker_provider_id_ = service_worker_provider_id;
}
+ // true if the request originated from within a service worker e.g. due to
+ // a fetch() in the service worker script.
+ bool originated_from_service_worker() const {
+ return originated_from_service_worker_;
+ }
+ void set_originated_from_service_worker(bool originated_from_service_worker) {
+ originated_from_service_worker_ = originated_from_service_worker;
+ }
LoFiState lofi_state() const {
return lofi_state_;
}
@@ -115,12 +123,12 @@ class CONTENT_EXPORT RequestExtraData
// PlzNavigate: |stream_override| is used to override certain parameters of
// navigation requests.
- scoped_ptr<StreamOverrideParameters> TakeStreamOverrideOwnership() {
+ std::unique_ptr<StreamOverrideParameters> TakeStreamOverrideOwnership() {
return std::move(stream_override_);
}
void set_stream_override(
- scoped_ptr<StreamOverrideParameters> stream_override) {
+ std::unique_ptr<StreamOverrideParameters> stream_override) {
stream_override_ = std::move(stream_override);
}
@@ -137,9 +145,10 @@ class CONTENT_EXPORT RequestExtraData
int transferred_request_child_id_;
int transferred_request_request_id_;
int service_worker_provider_id_;
+ bool originated_from_service_worker_;
blink::WebString custom_user_agent_;
blink::WebString requested_with_;
- scoped_ptr<StreamOverrideParameters> stream_override_;
+ std::unique_ptr<StreamOverrideParameters> stream_override_;
LoFiState lofi_state_;
DISALLOW_COPY_AND_ASSIGN(RequestExtraData);
diff --git a/chromium/content/child/request_info.h b/chromium/content/child/request_info.h
index 776b63faaa5..a5e026f9709 100644
--- a/chromium/content/child/request_info.h
+++ b/chromium/content/child/request_info.h
@@ -7,6 +7,7 @@
#include <stdint.h>
+#include <memory>
#include <string>
#include "base/macros.h"
@@ -121,7 +122,11 @@ struct CONTENT_EXPORT RequestInfo {
blink::WebURLRequest::ExtraData* extra_data;
// Optional, the specific task queue to execute loading tasks on.
- scoped_ptr<blink::WebTaskRunner> loading_web_task_runner;
+ std::unique_ptr<blink::WebTaskRunner> loading_web_task_runner;
+
+ // PlzNavigate: the stream URL to request during navigations to get access to
+ // the ResourceBody that has already been fetched by the browser process.
+ GURL resource_body_stream_url;
private:
DISALLOW_COPY_AND_ASSIGN(RequestInfo);
diff --git a/chromium/content/child/resource_dispatcher.cc b/chromium/content/child/resource_dispatcher.cc
index 30bbbe915cb..64171df0006 100644
--- a/chromium/content/child/resource_dispatcher.cc
+++ b/chromium/content/child/resource_dispatcher.cc
@@ -13,7 +13,9 @@
#include "base/debug/alias.h"
#include "base/debug/dump_without_crashing.h"
#include "base/debug/stack_trace.h"
+#include "base/feature_list.h"
#include "base/files/file_path.h"
+#include "base/memory/ptr_util.h"
#include "base/memory/shared_memory.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
@@ -26,17 +28,16 @@
#include "content/child/shared_memory_received_data_factory.h"
#include "content/child/site_isolation_stats_gatherer.h"
#include "content/child/sync_load_response.h"
-#include "content/child/threaded_data_provider.h"
#include "content/common/inter_process_time_ticks_converter.h"
#include "content/common/navigation_params.h"
#include "content/common/resource_messages.h"
#include "content/public/child/fixed_received_data.h"
#include "content/public/child/request_peer.h"
#include "content/public/child/resource_dispatcher_delegate.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/resource_response.h"
#include "content/public/common/resource_type.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/base/request_priority.h"
#include "net/http/http_response_headers.h"
@@ -156,11 +157,11 @@ void ResourceDispatcher::OnReceivedResponse(
request_info->response_start = ConsumeIOTimestamp();
if (delegate_) {
- RequestPeer* new_peer =
- delegate_->OnReceivedResponse(
- request_info->peer, response_head.mime_type, request_info->url);
- if (new_peer)
- request_info->peer = new_peer;
+ std::unique_ptr<RequestPeer> new_peer = delegate_->OnReceivedResponse(
+ std::move(request_info->peer), response_head.mime_type,
+ request_info->url);
+ DCHECK(new_peer);
+ request_info->peer = std::move(new_peer);
}
ResourceResponseInfo renderer_response_info;
@@ -220,13 +221,31 @@ void ResourceDispatcher::OnSetDataBuffer(int request_id,
request_info->buffer_size = shm_size;
}
-void ResourceDispatcher::OnReceivedDataDebug(int request_id, int data_offset) {
+void ResourceDispatcher::OnReceivedInlinedDataChunk(
+ int request_id,
+ const std::vector<char>& data,
+ int encoded_data_length) {
+ TRACE_EVENT0("loader", "ResourceDispatcher::OnReceivedInlinedDataChunk");
+ DCHECK(!data.empty());
+ DCHECK(base::FeatureList::IsEnabled(features::kOptimizeIPCForSmallResource));
+
PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
- if (request_info) {
- CHECK_GE(data_offset, 0);
- CHECK_LE(data_offset, 512 * 1024);
- request_info->data_offset = data_offset;
+ if (!request_info || data.empty())
+ return;
+
+ // Check whether this response data is compliant with our cross-site
+ // document blocking policy. We only do this for the first chunk of data.
+ if (request_info->site_isolation_metadata.get()) {
+ SiteIsolationStatsGatherer::OnReceivedFirstChunk(
+ request_info->site_isolation_metadata, data.data(), data.size());
+ request_info->site_isolation_metadata.reset();
}
+
+ DCHECK(!request_info->buffer.get());
+
+ std::unique_ptr<RequestPeer::ReceivedData> received_data(
+ new content::FixedReceivedData(data, encoded_data_length));
+ request_info->peer->OnReceivedData(std::move(received_data));
}
void ResourceDispatcher::OnReceivedData(int request_id,
@@ -239,27 +258,8 @@ void ResourceDispatcher::OnReceivedData(int request_id,
bool send_ack = true;
if (request_info && data_length > 0) {
CHECK(base::SharedMemory::IsHandleValid(request_info->buffer->handle()));
-
- // TODO(erikchen): Temporary debugging. http://crbug.com/527588.
- CHECK_GE(request_info->buffer_size, 0);
- CHECK_LE(request_info->buffer_size, 512 * 1024);
- CHECK_GE(data_length, 0);
- CHECK_LE(data_length, 512 * 1024);
-
- if (data_offset > 512 * 1024) {
- int cached_data_offset = request_info->data_offset;
- base::debug::Alias(&cached_data_offset);
- CHECK(false);
- }
-
CHECK_GE(request_info->buffer_size, data_offset + data_length);
- // Ensure that the SHM buffer remains valid for the duration of this scope.
- // It is possible for Cancel() to be called before we exit this scope.
- // SharedMemoryReceivedDataFactory stores the SHM buffer inside it.
- scoped_refptr<SharedMemoryReceivedDataFactory> factory(
- request_info->received_data_factory);
-
base::TimeTicks time_start = base::TimeTicks::Now();
const char* data_start = static_cast<char*>(request_info->buffer->memory());
@@ -275,19 +275,12 @@ void ResourceDispatcher::OnReceivedData(int request_id,
request_info->site_isolation_metadata.reset();
}
- if (request_info->threaded_data_provider) {
- // A threaded data provider will take care of its own ACKing, as the data
- // may be processed later on another thread.
- send_ack = false;
- request_info->threaded_data_provider->OnReceivedDataOnForegroundThread(
- data_ptr, data_length, encoded_data_length);
- } else {
- scoped_ptr<RequestPeer::ReceivedData> data =
- factory->Create(data_offset, data_length, encoded_data_length);
- // |data| takes care of ACKing.
- send_ack = false;
- request_info->peer->OnReceivedData(std::move(data));
- }
+ std::unique_ptr<RequestPeer::ReceivedData> data =
+ request_info->received_data_factory->Create(data_offset, data_length,
+ encoded_data_length);
+ // |data| takes care of ACKing.
+ send_ack = false;
+ request_info->peer->OnReceivedData(std::move(data));
UMA_HISTOGRAM_TIMES("ResourceDispatcher.OnReceivedDataTime",
base::TimeTicks::Now() - time_start);
@@ -366,50 +359,25 @@ void ResourceDispatcher::OnRequestComplete(
request_info->received_data_factory = nullptr;
request_info->buffer_size = 0;
- RequestPeer* peer = request_info->peer;
+ RequestPeer* peer = request_info->peer.get();
if (delegate_) {
- RequestPeer* new_peer =
- delegate_->OnRequestComplete(
- request_info->peer, request_info->resource_type,
- request_complete_data.error_code);
- if (new_peer)
- request_info->peer = new_peer;
+ std::unique_ptr<RequestPeer> new_peer = delegate_->OnRequestComplete(
+ std::move(request_info->peer), request_info->resource_type,
+ request_complete_data.error_code);
+ DCHECK(new_peer);
+ request_info->peer = std::move(new_peer);
}
base::TimeTicks renderer_completion_time = ToRendererCompletionTime(
*request_info, request_complete_data.completion_time);
- // If we have a threaded data provider, this message needs to bounce off the
- // background thread before it's returned to this thread and handled,
- // to make sure it's processed after all incoming data.
- if (request_info->threaded_data_provider) {
- request_info->threaded_data_provider->OnRequestCompleteForegroundThread(
- weak_factory_.GetWeakPtr(), request_complete_data,
- renderer_completion_time);
- return;
- }
-
// The request ID will be removed from our pending list in the destructor.
// Normally, dispatching this message causes the reference-counted request to
// die immediately.
- peer->OnCompletedRequest(request_complete_data.error_code,
- request_complete_data.was_ignored_by_handler,
- request_complete_data.exists_in_cache,
- request_complete_data.security_info,
- renderer_completion_time,
- request_complete_data.encoded_data_length);
-}
-
-void ResourceDispatcher::CompletedRequestAfterBackgroundThreadFlush(
- int request_id,
- const ResourceMsg_RequestCompleteData& request_complete_data,
- const base::TimeTicks& renderer_completion_time) {
- PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
- if (!request_info)
- return;
-
- RequestPeer* peer = request_info->peer;
+ // TODO(kinuko): Revisit here. This probably needs to call request_info->peer
+ // but the past attempt to change it seems to have caused crashes.
+ // (crbug.com/547047)
peer->OnCompletedRequest(request_complete_data.error_code,
request_complete_data.was_ignored_by_handler,
request_complete_data.exists_in_cache,
@@ -428,6 +396,11 @@ bool ResourceDispatcher::RemovePendingRequest(int request_id) {
bool release_downloaded_file = request_info->download_to_file;
ReleaseResourcesInMessageQueue(&request_info->deferred_message_queue);
+
+ // Always delete the pending_request asyncly so that cancelling the request
+ // doesn't delete the request context info while its response is still being
+ // handled.
+ main_thread_task_runner_->DeleteSoon(FROM_HERE, it->second.release());
pending_requests_.erase(it);
if (release_downloaded_file) {
@@ -451,14 +424,15 @@ void ResourceDispatcher::Cancel(int request_id) {
// |completion_time.is_null()| is a proxy for OnRequestComplete never being
// called.
// TODO(csharrison): Remove this code when crbug.com/557430 is resolved.
- // ~250,000 ERR_ABORTED coming into canary with |request_time| < 100ms. Sample
- // by .01% to get something reasonable.
+ // Sample this enough that this won't dump much more than a hundred times a
+ // day even without the static guard. The guard ensures this dumps much less
+ // frequently, because these aborts frequently come in quick succession.
const PendingRequestInfo& info = *it->second;
int64_t request_time =
(base::TimeTicks::Now() - info.request_start).InMilliseconds();
if (info.resource_type == ResourceType::RESOURCE_TYPE_MAIN_FRAME &&
info.completion_time.is_null() && request_time < 100 &&
- base::RandDouble() < .0001) {
+ base::RandDouble() < .000001) {
static bool should_dump = true;
if (should_dump) {
char url_copy[256] = {0};
@@ -504,42 +478,23 @@ void ResourceDispatcher::DidChangePriority(int request_id,
request_id, new_priority, intra_priority_value));
}
-bool ResourceDispatcher::AttachThreadedDataReceiver(
- int request_id, blink::WebThreadedDataReceiver* threaded_data_receiver) {
- PendingRequestInfo* request_info = GetPendingRequestInfo(request_id);
- DCHECK(request_info);
-
- if (request_info->buffer != NULL) {
- DCHECK(!request_info->threaded_data_provider);
- request_info->threaded_data_provider = new ThreadedDataProvider(
- request_id, threaded_data_receiver, request_info->buffer,
- request_info->buffer_size, main_thread_task_runner_);
- return true;
- }
-
- return false;
-}
-
ResourceDispatcher::PendingRequestInfo::PendingRequestInfo(
- RequestPeer* peer,
+ std::unique_ptr<RequestPeer> peer,
ResourceType resource_type,
int origin_pid,
const GURL& frame_origin,
const GURL& request_url,
bool download_to_file)
- : peer(peer),
+ : peer(std::move(peer)),
resource_type(resource_type),
origin_pid(origin_pid),
url(request_url),
frame_origin(frame_origin),
response_url(request_url),
download_to_file(download_to_file),
- request_start(base::TimeTicks::Now()) {
-}
+ request_start(base::TimeTicks::Now()) {}
ResourceDispatcher::PendingRequestInfo::~PendingRequestInfo() {
- if (threaded_data_provider)
- threaded_data_provider->Stop();
}
void ResourceDispatcher::DispatchMessage(const IPC::Message& message) {
@@ -550,7 +505,8 @@ void ResourceDispatcher::DispatchMessage(const IPC::Message& message) {
OnReceivedCachedMetadata)
IPC_MESSAGE_HANDLER(ResourceMsg_ReceivedRedirect, OnReceivedRedirect)
IPC_MESSAGE_HANDLER(ResourceMsg_SetDataBuffer, OnSetDataBuffer)
- IPC_MESSAGE_HANDLER(ResourceMsg_DataReceivedDebug, OnReceivedDataDebug)
+ IPC_MESSAGE_HANDLER(ResourceMsg_InlinedDataChunkReceived,
+ OnReceivedInlinedDataChunk)
IPC_MESSAGE_HANDLER(ResourceMsg_DataReceived, OnReceivedData)
IPC_MESSAGE_HANDLER(ResourceMsg_DataDownloaded, OnDownloadedData)
IPC_MESSAGE_HANDLER(ResourceMsg_RequestComplete, OnRequestComplete)
@@ -591,7 +547,7 @@ void ResourceDispatcher::FlushDeferredMessages(int request_id) {
void ResourceDispatcher::StartSync(const RequestInfo& request_info,
ResourceRequestBody* request_body,
SyncLoadResponse* response) {
- scoped_ptr<ResourceHostMsg_Request> request =
+ std::unique_ptr<ResourceHostMsg_Request> request =
CreateRequest(request_info, request_body, NULL);
SyncLoadResult result;
@@ -616,30 +572,27 @@ void ResourceDispatcher::StartSync(const RequestInfo& request_info,
response->devtools_info = result.devtools_info;
response->data.swap(result.data);
response->download_file_path = result.download_file_path;
+ response->socket_address = result.socket_address;
}
int ResourceDispatcher::StartAsync(const RequestInfo& request_info,
ResourceRequestBody* request_body,
- RequestPeer* peer) {
+ std::unique_ptr<RequestPeer> peer) {
GURL frame_origin;
- scoped_ptr<ResourceHostMsg_Request> request =
+ std::unique_ptr<ResourceHostMsg_Request> request =
CreateRequest(request_info, request_body, &frame_origin);
// Compute a unique request_id for this renderer process.
int request_id = MakeRequestID();
- pending_requests_[request_id] =
- make_scoped_ptr(new PendingRequestInfo(peer,
- request->resource_type,
- request->origin_pid,
- frame_origin,
- request->url,
- request_info.download_to_file));
+ pending_requests_[request_id] = base::WrapUnique(new PendingRequestInfo(
+ std::move(peer), request->resource_type, request->origin_pid,
+ frame_origin, request->url, request_info.download_to_file));
if (resource_scheduling_filter_.get() &&
request_info.loading_web_task_runner) {
resource_scheduling_filter_->SetRequestIdTaskRunner(
request_id,
- make_scoped_ptr(request_info.loading_web_task_runner->clone()));
+ base::WrapUnique(request_info.loading_web_task_runner->clone()));
}
message_sender_->Send(new ResourceHostMsg_RequestResource(
@@ -735,6 +688,8 @@ bool ResourceDispatcher::IsResourceDispatcherMessage(
case ResourceMsg_ReceivedRedirect::ID:
case ResourceMsg_SetDataBuffer::ID:
case ResourceMsg_DataReceivedDebug::ID:
+ case ResourceMsg_DataReceivedDebug2::ID:
+ case ResourceMsg_InlinedDataChunkReceived::ID:
case ResourceMsg_DataReceived::ID:
case ResourceMsg_DataDownloaded::ID:
case ResourceMsg_RequestComplete::ID:
@@ -780,11 +735,11 @@ void ResourceDispatcher::ReleaseResourcesInMessageQueue(MessageQueue* queue) {
}
}
-scoped_ptr<ResourceHostMsg_Request> ResourceDispatcher::CreateRequest(
+std::unique_ptr<ResourceHostMsg_Request> ResourceDispatcher::CreateRequest(
const RequestInfo& request_info,
ResourceRequestBody* request_body,
GURL* frame_origin) {
- scoped_ptr<ResourceHostMsg_Request> request(new ResourceHostMsg_Request);
+ std::unique_ptr<ResourceHostMsg_Request> request(new ResourceHostMsg_Request);
request->method = request_info.method;
request->url = request_info.url;
request->first_party_for_cookies = request_info.first_party_for_cookies;
@@ -844,8 +799,11 @@ scoped_ptr<ResourceHostMsg_Request> ResourceDispatcher::CreateRequest(
extra_data->transferred_request_request_id();
request->service_worker_provider_id =
extra_data->service_worker_provider_id();
+ request->originated_from_service_worker =
+ extra_data->originated_from_service_worker();
request->lofi_state = extra_data->lofi_state();
request->request_body = request_body;
+ request->resource_body_stream_url = request_info.resource_body_stream_url;
if (frame_origin)
*frame_origin = extra_data->frame_origin();
return request;
diff --git a/chromium/content/child/resource_dispatcher.h b/chromium/content/child/resource_dispatcher.h
index 8f1946e9217..c676e6956b9 100644
--- a/chromium/content/child/resource_dispatcher.h
+++ b/chromium/content/child/resource_dispatcher.h
@@ -11,12 +11,12 @@
#include <deque>
#include <map>
+#include <memory>
#include <string>
#include "base/containers/hash_tables.h"
#include "base/macros.h"
#include "base/memory/linked_ptr.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
@@ -31,10 +31,6 @@
struct ResourceHostMsg_Request;
struct ResourceMsg_RequestCompleteData;
-namespace blink {
-class WebThreadedDataReceiver;
-}
-
namespace net {
struct RedirectInfo;
}
@@ -44,7 +40,6 @@ class RequestPeer;
class ResourceDispatcherDelegate;
class ResourceRequestBody;
class ResourceSchedulingFilter;
-class ThreadedDataProvider;
struct ResourceResponseInfo;
struct RequestInfo;
struct ResourceResponseHead;
@@ -81,7 +76,7 @@ class CONTENT_EXPORT ResourceDispatcher : public IPC::Listener {
// Returns the request id.
virtual int StartAsync(const RequestInfo& request_info,
ResourceRequestBody* request_body,
- RequestPeer* peer);
+ std::unique_ptr<RequestPeer> peer);
// Removes a request from the |pending_requests_| list, returning true if the
// request was found and removed.
@@ -92,26 +87,13 @@ class CONTENT_EXPORT ResourceDispatcher : public IPC::Listener {
virtual void Cancel(int request_id);
// Toggles the is_deferred attribute for the specified request.
- void SetDefersLoading(int request_id, bool value);
+ virtual void SetDefersLoading(int request_id, bool value);
// Indicates the priority of the specified request changed.
void DidChangePriority(int request_id,
net::RequestPriority new_priority,
int intra_priority_value);
- // The provided data receiver will receive incoming resource data rather
- // than the resource bridge.
- bool AttachThreadedDataReceiver(
- int request_id, blink::WebThreadedDataReceiver* threaded_data_receiver);
-
- // If we have a ThreadedDataProvider attached, an OnRequestComplete message
- // will get bounced via the background thread and then passed to this function
- // to resume processing.
- void CompletedRequestAfterBackgroundThreadFlush(
- int request_id,
- const ResourceMsg_RequestCompleteData& request_complete_data,
- const base::TimeTicks& renderer_completion_time);
-
void set_message_sender(IPC::Sender* sender) {
DCHECK(sender);
DCHECK(pending_requests_.empty());
@@ -142,7 +124,7 @@ class CONTENT_EXPORT ResourceDispatcher : public IPC::Listener {
typedef std::deque<IPC::Message*> MessageQueue;
struct PendingRequestInfo {
- PendingRequestInfo(RequestPeer* peer,
+ PendingRequestInfo(std::unique_ptr<RequestPeer> peer,
ResourceType resource_type,
int origin_pid,
const GURL& frame_origin,
@@ -151,8 +133,7 @@ class CONTENT_EXPORT ResourceDispatcher : public IPC::Listener {
~PendingRequestInfo();
- RequestPeer* peer;
- ThreadedDataProvider* threaded_data_provider = nullptr;
+ std::unique_ptr<RequestPeer> peer;
ResourceType resource_type;
// The PID of the original process which issued this request. This gets
// non-zero only for a request proxied by another renderer, particularly
@@ -167,19 +148,16 @@ class CONTENT_EXPORT ResourceDispatcher : public IPC::Listener {
// The url of the latest response even in case of redirection.
GURL response_url;
bool download_to_file;
- scoped_ptr<IPC::Message> pending_redirect_message;
+ std::unique_ptr<IPC::Message> pending_redirect_message;
base::TimeTicks request_start;
base::TimeTicks response_start;
base::TimeTicks completion_time;
linked_ptr<base::SharedMemory> buffer;
scoped_refptr<SharedMemoryReceivedDataFactory> received_data_factory;
- scoped_ptr<SiteIsolationResponseMetaData> site_isolation_metadata;
+ std::unique_ptr<SiteIsolationResponseMetaData> site_isolation_metadata;
int buffer_size;
-
- // Debugging for https://code.google.com/p/chromium/issues/detail?id=527588.
- int data_offset = -1;
};
- using PendingRequestMap = std::map<int, scoped_ptr<PendingRequestInfo>>;
+ using PendingRequestMap = std::map<int, std::unique_ptr<PendingRequestInfo>>;
// Helper to lookup the info based on the request_id.
// May return NULL if the request as been canceled from the client side.
@@ -199,7 +177,9 @@ class CONTENT_EXPORT ResourceDispatcher : public IPC::Listener {
base::SharedMemoryHandle shm_handle,
int shm_size,
base::ProcessId renderer_pid);
- void OnReceivedDataDebug(int request_id, int data_offset);
+ void OnReceivedInlinedDataChunk(int request_id,
+ const std::vector<char>& data,
+ int encoded_data_length);
void OnReceivedData(int request_id,
int data_offset,
int data_length,
@@ -243,7 +223,7 @@ class CONTENT_EXPORT ResourceDispatcher : public IPC::Listener {
// for use on deferred message queues that are no longer needed.
static void ReleaseResourcesInMessageQueue(MessageQueue* queue);
- scoped_ptr<ResourceHostMsg_Request> CreateRequest(
+ std::unique_ptr<ResourceHostMsg_Request> CreateRequest(
const RequestInfo& request_info,
ResourceRequestBody* request_body,
GURL* frame_origin);
diff --git a/chromium/content/child/resource_dispatcher_unittest.cc b/chromium/content/child/resource_dispatcher_unittest.cc
index aafa029cf7f..1a7d58fdba6 100644
--- a/chromium/content/child/resource_dispatcher_unittest.cc
+++ b/chromium/content/child/resource_dispatcher_unittest.cc
@@ -6,12 +6,14 @@
#include <stddef.h>
#include <stdint.h>
+
+#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
+#include "base/memory/ptr_util.h"
#include "base/memory/shared_memory.h"
#include "base/message_loop/message_loop.h"
#include "base/process/process_handle.h"
@@ -22,7 +24,9 @@
#include "content/common/appcache_interfaces.h"
#include "content/common/resource_messages.h"
#include "content/common/service_worker/service_worker_types.h"
+#include "content/public/child/fixed_received_data.h"
#include "content/public/child/request_peer.h"
+#include "content/public/child/resource_dispatcher_delegate.h"
#include "content/public/common/resource_response.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
@@ -44,48 +48,44 @@ static const char kTestRedirectHeaders[] =
// to the reference data.
class TestRequestPeer : public RequestPeer {
public:
- TestRequestPeer(ResourceDispatcher* dispatcher)
- : follow_redirects_(true),
- defer_on_redirect_(false),
- seen_redirects_(0),
- cancel_on_receive_response_(false),
- received_response_(false),
- total_encoded_data_length_(0),
- total_downloaded_data_length_(0),
- complete_(false),
- dispatcher_(dispatcher),
- request_id_(0) {
- }
-
- void set_request_id(int request_id) { request_id_ = request_id; }
+ struct Context;
+ TestRequestPeer(ResourceDispatcher* dispatcher, Context* context)
+ : dispatcher_(dispatcher), context_(context) {}
void OnUploadProgress(uint64_t position, uint64_t size) override {}
bool OnReceivedRedirect(const net::RedirectInfo& redirect_info,
const ResourceResponseInfo& info) override {
- ++seen_redirects_;
- if (defer_on_redirect_)
- dispatcher_->SetDefersLoading(request_id_, true);
- return follow_redirects_;
+ EXPECT_FALSE(context_->cancelled);
+ ++context_->seen_redirects;
+ if (context_->defer_on_redirect)
+ dispatcher_->SetDefersLoading(context_->request_id, true);
+ return context_->follow_redirects;
}
void OnReceivedResponse(const ResourceResponseInfo& info) override {
- EXPECT_FALSE(received_response_);
- received_response_ = true;
- if (cancel_on_receive_response_)
- dispatcher_->Cancel(request_id_);
+ EXPECT_FALSE(context_->cancelled);
+ EXPECT_FALSE(context_->received_response);
+ context_->received_response = true;
+ if (context_->cancel_on_receive_response) {
+ dispatcher_->Cancel(context_->request_id);
+ context_->cancelled = true;
+ }
}
void OnDownloadedData(int len, int encoded_data_length) override {
- total_downloaded_data_length_ += len;
- total_encoded_data_length_ += encoded_data_length;
+ EXPECT_FALSE(context_->cancelled);
+ context_->total_downloaded_data_length += len;
+ context_->total_encoded_data_length += encoded_data_length;
}
- void OnReceivedData(scoped_ptr<ReceivedData> data) override {
- EXPECT_TRUE(received_response_);
- EXPECT_FALSE(complete_);
- data_.append(data->payload(), data->length());
- total_encoded_data_length_ += data->encoded_length();
+ void OnReceivedData(std::unique_ptr<ReceivedData> data) override {
+ if (context_->cancelled)
+ return;
+ EXPECT_TRUE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ context_->data.append(data->payload(), data->length());
+ context_->total_encoded_data_length += data->encoded_length();
}
void OnCompletedRequest(int error_code,
@@ -94,80 +94,42 @@ class TestRequestPeer : public RequestPeer {
const std::string& security_info,
const base::TimeTicks& completion_time,
int64_t total_transfer_size) override {
- EXPECT_TRUE(received_response_);
- EXPECT_FALSE(complete_);
- complete_ = true;
- }
-
- void OnReceivedCompletedResponse(const ResourceResponseInfo& info,
- scoped_ptr<ReceivedData> data,
- int error_code,
- bool was_ignored_by_handler,
- bool stale_copy_in_cache,
- const std::string& security_info,
- const base::TimeTicks& completion_time,
- int64_t total_transfer_size) override {
- bool cancel_on_receive_response = cancel_on_receive_response_;
- OnReceivedResponse(info);
- if (cancel_on_receive_response)
+ if (context_->cancelled)
return;
- if (data)
- OnReceivedData(std::move(data));
- OnCompletedRequest(error_code, was_ignored_by_handler, stale_copy_in_cache,
- security_info, completion_time, total_transfer_size);
+ EXPECT_TRUE(context_->received_response);
+ EXPECT_FALSE(context_->complete);
+ context_->complete = true;
}
- void set_follow_redirects(bool follow_redirects) {
- follow_redirects_ = follow_redirects;
- }
+ struct Context {
+ // True if should follow redirects, false if should cancel them.
+ bool follow_redirects = true;
+ // True if the request should be deferred on redirects.
+ bool defer_on_redirect = false;
- void set_defer_on_redirect(bool defer_on_redirect) {
- defer_on_redirect_ = defer_on_redirect;
- }
-
- void set_cancel_on_receive_response(bool cancel_on_receive_response) {
- cancel_on_receive_response_ = cancel_on_receive_response;
- }
+ // Number of total redirects seen.
+ int seen_redirects = 0;
- int seen_redirects() const { return seen_redirects_; }
+ bool cancel_on_receive_response = false;
+ bool received_response = false;
- bool received_response() const { return received_response_; }
+ // Data received. If downloading to file, remains empty.
+ std::string data;
- const std::string& data() const {
- return data_;
- }
- int total_encoded_data_length() const {
- return total_encoded_data_length_;
- }
- int total_downloaded_data_length() const {
- return total_downloaded_data_length_;
- }
+ // Total encoded data length, regardless of whether downloading to a file or
+ // not.
+ int total_encoded_data_length = 0;
+ // Total length when downloading to a file.
+ int total_downloaded_data_length = 0;
- bool complete() const { return complete_; }
+ bool complete = false;
+ bool cancelled = false;
+ int request_id = -1;
+ };
private:
- // True if should follow redirects, false if should cancel them.
- bool follow_redirects_;
- // True if the request should be deferred on redirects.
- bool defer_on_redirect_;
- // Number of total redirects seen.
- int seen_redirects_;
-
- bool cancel_on_receive_response_;
- bool received_response_;
-
- // Data received. If downloading to file, remains empty.
- std::string data_;
- // Total encoded data length, regardless of whether downloading to a file or
- // not.
- int total_encoded_data_length_;
- // Total length when downloading to a file.
- int total_downloaded_data_length_;
-
- bool complete_;
-
ResourceDispatcher* dispatcher_;
- int request_id_;
+ Context* context_;
DISALLOW_COPY_AND_ASSIGN(TestRequestPeer);
};
@@ -175,11 +137,15 @@ class TestRequestPeer : public RequestPeer {
// Sets up the message sender override for the unit test.
class ResourceDispatcherTest : public testing::Test, public IPC::Sender {
public:
- ResourceDispatcherTest() : dispatcher_(this, message_loop_.task_runner()) {}
+ ResourceDispatcherTest()
+ : dispatcher_(new ResourceDispatcher(this, message_loop_.task_runner())) {
+ }
~ResourceDispatcherTest() override {
STLDeleteContainerPairSecondPointers(shared_memory_map_.begin(),
shared_memory_map_.end());
+ dispatcher_.reset();
+ base::RunLoop().RunUntilIdle();
}
// Emulates IPC send operations (IPC::Sender) by adding
@@ -273,8 +239,8 @@ class ResourceDispatcherTest : public testing::Test, public IPC::Sender {
redirect_info.new_method = "GET";
redirect_info.new_url = GURL(kTestPageUrl);
redirect_info.new_first_party_for_cookies = GURL(kTestPageUrl);
- EXPECT_EQ(true, dispatcher_.OnMessageReceived(
- ResourceMsg_ReceivedRedirect(request_id, redirect_info, head)));
+ EXPECT_EQ(true, dispatcher_->OnMessageReceived(ResourceMsg_ReceivedRedirect(
+ request_id, redirect_info, head)));
}
void NotifyReceivedResponse(int request_id) {
@@ -284,9 +250,8 @@ class ResourceDispatcherTest : public testing::Test, public IPC::Sender {
head.headers = new net::HttpResponseHeaders(raw_headers);
head.mime_type = kTestPageMimeType;
head.charset = kTestPageCharset;
- EXPECT_EQ(true,
- dispatcher_.OnMessageReceived(
- ResourceMsg_ReceivedResponse(request_id, head)));
+ EXPECT_EQ(true, dispatcher_->OnMessageReceived(
+ ResourceMsg_ReceivedResponse(request_id, head)));
}
void NotifySetDataBuffer(int request_id, size_t buffer_size) {
@@ -298,9 +263,8 @@ class ResourceDispatcherTest : public testing::Test, public IPC::Sender {
base::SharedMemoryHandle duplicate_handle;
EXPECT_TRUE(shared_memory->ShareToProcess(base::GetCurrentProcessHandle(),
&duplicate_handle));
- EXPECT_TRUE(dispatcher_.OnMessageReceived(
- ResourceMsg_SetDataBuffer(request_id, duplicate_handle,
- shared_memory->requested_size(), 0)));
+ EXPECT_TRUE(dispatcher_->OnMessageReceived(ResourceMsg_SetDataBuffer(
+ request_id, duplicate_handle, shared_memory->requested_size(), 0)));
}
void NotifyDataReceived(int request_id, const std::string& data) {
@@ -308,17 +272,14 @@ class ResourceDispatcherTest : public testing::Test, public IPC::Sender {
memcpy(shared_memory_map_[request_id]->memory(), data.c_str(),
data.length());
- EXPECT_TRUE(dispatcher_.OnMessageReceived(
- ResourceMsg_DataReceivedDebug(request_id, 0)));
- EXPECT_TRUE(dispatcher_.OnMessageReceived(
+ EXPECT_TRUE(dispatcher_->OnMessageReceived(
ResourceMsg_DataReceived(request_id, 0, data.length(), data.length())));
}
void NotifyDataDownloaded(int request_id, int decoded_length,
int encoded_length) {
- EXPECT_TRUE(dispatcher_.OnMessageReceived(
- ResourceMsg_DataDownloaded(request_id, decoded_length,
- encoded_length)));
+ EXPECT_TRUE(dispatcher_->OnMessageReceived(ResourceMsg_DataDownloaded(
+ request_id, decoded_length, encoded_length)));
}
void NotifyRequestComplete(int request_id, size_t total_size) {
@@ -327,7 +288,7 @@ class ResourceDispatcherTest : public testing::Test, public IPC::Sender {
request_complete_data.was_ignored_by_handler = false;
request_complete_data.exists_in_cache = false;
request_complete_data.encoded_data_length = total_size;
- EXPECT_TRUE(dispatcher_.OnMessageReceived(
+ EXPECT_TRUE(dispatcher_->OnMessageReceived(
ResourceMsg_RequestComplete(request_id, request_complete_data)));
}
@@ -350,7 +311,18 @@ class ResourceDispatcherTest : public testing::Test, public IPC::Sender {
return request_info;
}
- ResourceDispatcher* dispatcher() { return &dispatcher_; }
+ ResourceDispatcher* dispatcher() { return dispatcher_.get(); }
+
+ int StartAsync(const RequestInfo& request_info,
+ ResourceRequestBody* request_body,
+ TestRequestPeer::Context* peer_context) {
+ std::unique_ptr<TestRequestPeer> peer(
+ new TestRequestPeer(dispatcher(), peer_context));
+ int request_id =
+ dispatcher()->StartAsync(request_info, request_body, std::move(peer));
+ peer_context->request_id = request_id;
+ return request_id;
+ }
private:
// Map of request IDs to shared memory.
@@ -358,7 +330,7 @@ class ResourceDispatcherTest : public testing::Test, public IPC::Sender {
std::vector<IPC::Message> message_queue_;
base::MessageLoop message_loop_;
- ResourceDispatcher dispatcher_;
+ std::unique_ptr<ResourceDispatcher> dispatcher_;
};
// Does a simple request and tests that the correct data is received. Simulates
@@ -368,17 +340,16 @@ TEST_F(ResourceDispatcherTest, RoundTrip) {
const size_t kFirstReceiveSize = 2;
ASSERT_LT(kFirstReceiveSize, strlen(kTestPageContents));
- scoped_ptr<RequestInfo> request_info(CreateRequestInfo(false));
- TestRequestPeer peer(dispatcher());
- int request_id = dispatcher()->StartAsync(*request_info.get(), NULL, &peer);
- peer.set_request_id(request_id);
+ std::unique_ptr<RequestInfo> request_info(CreateRequestInfo(false));
+ TestRequestPeer::Context peer_context;
+ StartAsync(*request_info.get(), NULL, &peer_context);
int id = ConsumeRequestResource();
EXPECT_EQ(0u, queued_messages());
NotifyReceivedResponse(id);
EXPECT_EQ(0u, queued_messages());
- EXPECT_TRUE(peer.received_response());
+ EXPECT_TRUE(peer_context.received_response);
NotifySetDataBuffer(id, strlen(kTestPageContents));
NotifyDataReceived(id, std::string(kTestPageContents, kFirstReceiveSize));
@@ -390,8 +361,8 @@ TEST_F(ResourceDispatcherTest, RoundTrip) {
EXPECT_EQ(0u, queued_messages());
NotifyRequestComplete(id, strlen(kTestPageContents));
- EXPECT_EQ(kTestPageContents, peer.data());
- EXPECT_TRUE(peer.complete());
+ EXPECT_EQ(kTestPageContents, peer_context.data);
+ EXPECT_TRUE(peer_context.complete);
EXPECT_EQ(0u, queued_messages());
}
@@ -400,26 +371,23 @@ TEST_F(ResourceDispatcherTest, RoundTrip) {
TEST_F(ResourceDispatcherTest, MultipleRequests) {
const char kTestPageContents2[] = "Not kTestPageContents";
- scoped_ptr<RequestInfo> request_info1(CreateRequestInfo(false));
- TestRequestPeer peer1(dispatcher());
- int request_id1 = dispatcher()->StartAsync(
- *request_info1.get(), NULL, &peer1);
- peer1.set_request_id(request_id1);
- scoped_ptr<RequestInfo> request_info2(CreateRequestInfo(false));
- TestRequestPeer peer2(dispatcher());
- int request_id2 = dispatcher()->StartAsync(
- *request_info1.get(), NULL, &peer2);
- peer2.set_request_id(request_id2);
+ std::unique_ptr<RequestInfo> request_info1(CreateRequestInfo(false));
+ TestRequestPeer::Context peer_context1;
+ StartAsync(*request_info1.get(), NULL, &peer_context1);
+
+ std::unique_ptr<RequestInfo> request_info2(CreateRequestInfo(false));
+ TestRequestPeer::Context peer_context2;
+ StartAsync(*request_info2.get(), NULL, &peer_context2);
int id1 = ConsumeRequestResource();
int id2 = ConsumeRequestResource();
EXPECT_EQ(0u, queued_messages());
NotifyReceivedResponse(id1);
- EXPECT_TRUE(peer1.received_response());
- EXPECT_FALSE(peer2.received_response());
+ EXPECT_TRUE(peer_context1.received_response);
+ EXPECT_FALSE(peer_context2.received_response);
NotifyReceivedResponse(id2);
- EXPECT_TRUE(peer2.received_response());
+ EXPECT_TRUE(peer_context2.received_response);
EXPECT_EQ(0u, queued_messages());
NotifySetDataBuffer(id2, strlen(kTestPageContents2));
@@ -431,23 +399,22 @@ TEST_F(ResourceDispatcherTest, MultipleRequests) {
EXPECT_EQ(0u, queued_messages());
NotifyRequestComplete(id1, strlen(kTestPageContents));
- EXPECT_EQ(kTestPageContents, peer1.data());
- EXPECT_TRUE(peer1.complete());
- EXPECT_FALSE(peer2.complete());
+ EXPECT_EQ(kTestPageContents, peer_context1.data);
+ EXPECT_TRUE(peer_context1.complete);
+ EXPECT_FALSE(peer_context2.complete);
NotifyRequestComplete(id2, strlen(kTestPageContents2));
- EXPECT_EQ(kTestPageContents2, peer2.data());
- EXPECT_TRUE(peer2.complete());
+ EXPECT_EQ(kTestPageContents2, peer_context2.data);
+ EXPECT_TRUE(peer_context2.complete);
EXPECT_EQ(0u, queued_messages());
}
// Tests that the cancel method prevents other messages from being received.
TEST_F(ResourceDispatcherTest, Cancel) {
- scoped_ptr<RequestInfo> request_info(CreateRequestInfo(false));
- TestRequestPeer peer(dispatcher());
- int request_id = dispatcher()->StartAsync(*request_info.get(), NULL, &peer);
- peer.set_request_id(request_id);
+ std::unique_ptr<RequestInfo> request_info(CreateRequestInfo(false));
+ TestRequestPeer::Context peer_context;
+ int request_id = StartAsync(*request_info.get(), NULL, &peer_context);
int id = ConsumeRequestResource();
EXPECT_EQ(0u, queued_messages());
@@ -463,24 +430,23 @@ TEST_F(ResourceDispatcherTest, Cancel) {
NotifyRequestComplete(id, strlen(kTestPageContents));
EXPECT_EQ(0u, queued_messages());
- EXPECT_EQ("", peer.data());
- EXPECT_FALSE(peer.received_response());
- EXPECT_FALSE(peer.complete());
+ EXPECT_EQ("", peer_context.data);
+ EXPECT_FALSE(peer_context.received_response);
+ EXPECT_FALSE(peer_context.complete);
}
// Tests that calling cancel during a callback works as expected.
TEST_F(ResourceDispatcherTest, CancelDuringCallback) {
- scoped_ptr<RequestInfo> request_info(CreateRequestInfo(false));
- TestRequestPeer peer(dispatcher());
- int request_id = dispatcher()->StartAsync(*request_info.get(), NULL, &peer);
- peer.set_request_id(request_id);
- peer.set_cancel_on_receive_response(true);
+ std::unique_ptr<RequestInfo> request_info(CreateRequestInfo(false));
+ TestRequestPeer::Context peer_context;
+ StartAsync(*request_info.get(), NULL, &peer_context);
+ peer_context.cancel_on_receive_response = true;
int id = ConsumeRequestResource();
EXPECT_EQ(0u, queued_messages());
NotifyReceivedResponse(id);
- EXPECT_TRUE(peer.received_response());
+ EXPECT_TRUE(peer_context.received_response);
// Request should have been cancelled.
ConsumeCancelRequest(id);
@@ -490,49 +456,196 @@ TEST_F(ResourceDispatcherTest, CancelDuringCallback) {
NotifyRequestComplete(id, strlen(kTestPageContents));
EXPECT_EQ(0u, queued_messages());
- EXPECT_EQ("", peer.data());
- EXPECT_FALSE(peer.complete());
+ EXPECT_EQ("", peer_context.data);
+ EXPECT_FALSE(peer_context.complete);
+}
+
+class TestResourceDispatcherDelegate : public ResourceDispatcherDelegate {
+ public:
+ TestResourceDispatcherDelegate() {}
+ ~TestResourceDispatcherDelegate() override {}
+
+ std::unique_ptr<RequestPeer> OnRequestComplete(
+ std::unique_ptr<RequestPeer> current_peer,
+ ResourceType resource_type,
+ int error_code) override {
+ return current_peer;
+ }
+
+ std::unique_ptr<RequestPeer> OnReceivedResponse(
+ std::unique_ptr<RequestPeer> current_peer,
+ const std::string& mime_type,
+ const GURL& url) override {
+ return base::WrapUnique(new WrapperPeer(std::move(current_peer)));
+ }
+
+ class WrapperPeer : public RequestPeer {
+ public:
+ explicit WrapperPeer(std::unique_ptr<RequestPeer> original_peer)
+ : original_peer_(std::move(original_peer)) {}
+
+ void OnUploadProgress(uint64_t position, uint64_t size) override {}
+
+ bool OnReceivedRedirect(const net::RedirectInfo& redirect_info,
+ const ResourceResponseInfo& info) override {
+ return false;
+ }
+
+ void OnReceivedResponse(const ResourceResponseInfo& info) override {
+ response_info_ = info;
+ }
+
+ void OnDownloadedData(int len, int encoded_data_length) override {}
+
+ void OnReceivedData(std::unique_ptr<ReceivedData> data) override {
+ data_.append(data->payload(), data->length());
+ }
+
+ void OnCompletedRequest(int error_code,
+ bool was_ignored_by_handler,
+ bool stale_copy_in_cache,
+ const std::string& security_info,
+ const base::TimeTicks& completion_time,
+ int64_t total_transfer_size) override {
+ original_peer_->OnReceivedResponse(response_info_);
+ if (!data_.empty()) {
+ original_peer_->OnReceivedData(base::WrapUnique(
+ new FixedReceivedData(data_.data(), data_.size(), -1)));
+ }
+ original_peer_->OnCompletedRequest(error_code, was_ignored_by_handler,
+ stale_copy_in_cache, security_info,
+ completion_time, total_transfer_size);
+ }
+
+ private:
+ std::unique_ptr<RequestPeer> original_peer_;
+ ResourceResponseInfo response_info_;
+ std::string data_;
+
+ DISALLOW_COPY_AND_ASSIGN(WrapperPeer);
+ };
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestResourceDispatcherDelegate);
+};
+
+TEST_F(ResourceDispatcherTest, DelegateTest) {
+ std::unique_ptr<RequestInfo> request_info(CreateRequestInfo(false));
+ TestRequestPeer::Context peer_context;
+ StartAsync(*request_info.get(), nullptr, &peer_context);
+
+ // Set the delegate that inserts a new peer in OnReceivedResponse.
+ TestResourceDispatcherDelegate delegate;
+ dispatcher()->set_delegate(&delegate);
+
+ // Run a simple round-trip.
+ const size_t kFirstReceiveSize = 2;
+ ASSERT_LT(kFirstReceiveSize, strlen(kTestPageContents));
+
+ int id = ConsumeRequestResource();
+ EXPECT_EQ(0u, queued_messages());
+
+ // The wrapper eats all messages until RequestComplete message is sent.
+ NotifyReceivedResponse(id);
+ NotifySetDataBuffer(id, strlen(kTestPageContents));
+ NotifyDataReceived(id, std::string(kTestPageContents, kFirstReceiveSize));
+ ConsumeDataReceived_ACK(id);
+ NotifyDataReceived(id, kTestPageContents + kFirstReceiveSize);
+ ConsumeDataReceived_ACK(id);
+
+ EXPECT_FALSE(peer_context.received_response);
+ EXPECT_EQ(0u, queued_messages());
+
+ // This lets the wrapper peer pass all the messages to the original
+ // peer at once.
+ NotifyRequestComplete(id, strlen(kTestPageContents));
+
+ EXPECT_TRUE(peer_context.received_response);
+ EXPECT_EQ(kTestPageContents, peer_context.data);
+ EXPECT_TRUE(peer_context.complete);
+ EXPECT_EQ(0u, queued_messages());
+}
+
+TEST_F(ResourceDispatcherTest, CancelDuringCallbackWithWrapperPeer) {
+ std::unique_ptr<RequestInfo> request_info(CreateRequestInfo(false));
+ TestRequestPeer::Context peer_context;
+ StartAsync(*request_info.get(), nullptr, &peer_context);
+ peer_context.cancel_on_receive_response = true;
+
+ // Set the delegate that inserts a new peer in OnReceivedResponse.
+ TestResourceDispatcherDelegate delegate;
+ dispatcher()->set_delegate(&delegate);
+
+ int id = ConsumeRequestResource();
+ EXPECT_EQ(0u, queued_messages());
+
+ // The wrapper eats all messages until RequestComplete message is sent.
+ NotifyReceivedResponse(id);
+ NotifySetDataBuffer(id, strlen(kTestPageContents));
+ NotifyDataReceived(id, kTestPageContents);
+ ConsumeDataReceived_ACK(id);
+
+ EXPECT_FALSE(peer_context.received_response);
+ EXPECT_EQ(0u, queued_messages());
+
+ // This lets the wrapper peer pass all the messages to the original
+ // peer at once, but the original peer cancels right after it receives
+ // the response. (This will remove pending request info from
+ // ResourceDispatcher while the wrapper peer is still running
+ // OnCompletedRequest, but it should not lead to crashes.)
+ NotifyRequestComplete(id, strlen(kTestPageContents));
+
+ EXPECT_TRUE(peer_context.received_response);
+ // Request should have been cancelled.
+ ConsumeCancelRequest(id);
+ EXPECT_TRUE(peer_context.cancelled);
+
+ // Any future messages related to the request should be ignored.
+ NotifyDataReceived(id, kTestPageContents);
+ NotifyRequestComplete(id, strlen(kTestPageContents));
+
+ EXPECT_EQ(0u, queued_messages());
+ EXPECT_EQ("", peer_context.data);
+ EXPECT_FALSE(peer_context.complete);
}
// Checks that redirects work as expected.
TEST_F(ResourceDispatcherTest, Redirect) {
- scoped_ptr<RequestInfo> request_info(CreateRequestInfo(false));
- TestRequestPeer peer(dispatcher());
- int request_id = dispatcher()->StartAsync(*request_info.get(), NULL, &peer);
- peer.set_request_id(request_id);
+ std::unique_ptr<RequestInfo> request_info(CreateRequestInfo(false));
+ TestRequestPeer::Context peer_context;
+ StartAsync(*request_info.get(), NULL, &peer_context);
int id = ConsumeRequestResource();
NotifyReceivedRedirect(id);
ConsumeFollowRedirect(id);
- EXPECT_EQ(1, peer.seen_redirects());
+ EXPECT_EQ(1, peer_context.seen_redirects);
NotifyReceivedRedirect(id);
ConsumeFollowRedirect(id);
- EXPECT_EQ(2, peer.seen_redirects());
+ EXPECT_EQ(2, peer_context.seen_redirects);
NotifyReceivedResponse(id);
- EXPECT_TRUE(peer.received_response());
+ EXPECT_TRUE(peer_context.received_response);
NotifySetDataBuffer(id, strlen(kTestPageContents));
NotifyDataReceived(id, kTestPageContents);
ConsumeDataReceived_ACK(id);
NotifyRequestComplete(id, strlen(kTestPageContents));
- EXPECT_EQ(kTestPageContents, peer.data());
- EXPECT_TRUE(peer.complete());
+ EXPECT_EQ(kTestPageContents, peer_context.data);
+ EXPECT_TRUE(peer_context.complete);
EXPECT_EQ(0u, queued_messages());
- EXPECT_EQ(2, peer.seen_redirects());
+ EXPECT_EQ(2, peer_context.seen_redirects);
}
// Tests that that cancelling during a redirect method prevents other messages
// from being received.
TEST_F(ResourceDispatcherTest, CancelDuringRedirect) {
- scoped_ptr<RequestInfo> request_info(CreateRequestInfo(false));
- TestRequestPeer peer(dispatcher());
- int request_id = dispatcher()->StartAsync(*request_info.get(), NULL, &peer);
- peer.set_request_id(request_id);
- peer.set_follow_redirects(false);
+ std::unique_ptr<RequestInfo> request_info(CreateRequestInfo(false));
+ TestRequestPeer::Context peer_context;
+ StartAsync(*request_info.get(), NULL, &peer_context);
+ peer_context.follow_redirects = false;
int id = ConsumeRequestResource();
EXPECT_EQ(0u, queued_messages());
@@ -540,7 +653,7 @@ TEST_F(ResourceDispatcherTest, CancelDuringRedirect) {
// Redirect the request, which triggers a cancellation.
NotifyReceivedRedirect(id);
ConsumeCancelRequest(id);
- EXPECT_EQ(1, peer.seen_redirects());
+ EXPECT_EQ(1, peer_context.seen_redirects);
EXPECT_EQ(0u, queued_messages());
// Any future messages related to the request should be ignored. In practice,
@@ -552,17 +665,16 @@ TEST_F(ResourceDispatcherTest, CancelDuringRedirect) {
NotifyRequestComplete(id, strlen(kTestPageContents));
EXPECT_EQ(0u, queued_messages());
- EXPECT_EQ("", peer.data());
- EXPECT_FALSE(peer.complete());
- EXPECT_EQ(1, peer.seen_redirects());
+ EXPECT_EQ("", peer_context.data);
+ EXPECT_FALSE(peer_context.complete);
+ EXPECT_EQ(1, peer_context.seen_redirects);
}
// Checks that deferring a request delays messages until it's resumed.
TEST_F(ResourceDispatcherTest, Defer) {
- scoped_ptr<RequestInfo> request_info(CreateRequestInfo(false));
- TestRequestPeer peer(dispatcher());
- int request_id = dispatcher()->StartAsync(*request_info.get(), NULL, &peer);
- peer.set_request_id(request_id);
+ std::unique_ptr<RequestInfo> request_info(CreateRequestInfo(false));
+ TestRequestPeer::Context peer_context;
+ int request_id = StartAsync(*request_info.get(), NULL, &peer_context);
int id = ConsumeRequestResource();
EXPECT_EQ(0u, queued_messages());
@@ -576,9 +688,9 @@ TEST_F(ResourceDispatcherTest, Defer) {
// None of the messages should have been processed yet, so no queued messages
// to the browser process, and no data received by the peer.
EXPECT_EQ(0u, queued_messages());
- EXPECT_EQ("", peer.data());
- EXPECT_FALSE(peer.complete());
- EXPECT_EQ(0, peer.seen_redirects());
+ EXPECT_EQ("", peer_context.data);
+ EXPECT_FALSE(peer_context.complete);
+ EXPECT_EQ(0, peer_context.seen_redirects);
// Resuming the request should asynchronously unleash the deferred messages.
dispatcher()->SetDefersLoading(request_id, false);
@@ -586,19 +698,18 @@ TEST_F(ResourceDispatcherTest, Defer) {
ConsumeDataReceived_ACK(id);
EXPECT_EQ(0u, queued_messages());
- EXPECT_TRUE(peer.received_response());
- EXPECT_EQ(kTestPageContents, peer.data());
- EXPECT_TRUE(peer.complete());
+ EXPECT_TRUE(peer_context.received_response);
+ EXPECT_EQ(kTestPageContents, peer_context.data);
+ EXPECT_TRUE(peer_context.complete);
}
// Checks that deferring a request during a redirect delays messages until it's
// resumed.
TEST_F(ResourceDispatcherTest, DeferOnRedirect) {
- scoped_ptr<RequestInfo> request_info(CreateRequestInfo(false));
- TestRequestPeer peer(dispatcher());
- int request_id = dispatcher()->StartAsync(*request_info.get(), NULL, &peer);
- peer.set_request_id(request_id);
- peer.set_defer_on_redirect(true);
+ std::unique_ptr<RequestInfo> request_info(CreateRequestInfo(false));
+ TestRequestPeer::Context peer_context;
+ int request_id = StartAsync(*request_info.get(), NULL, &peer_context);
+ peer_context.defer_on_redirect = true;
int id = ConsumeRequestResource();
EXPECT_EQ(0u, queued_messages());
@@ -614,9 +725,9 @@ TEST_F(ResourceDispatcherTest, DeferOnRedirect) {
// None of the messages should have been processed yet, so no queued messages
// to the browser process, and no data received by the peer.
EXPECT_EQ(0u, queued_messages());
- EXPECT_EQ("", peer.data());
- EXPECT_FALSE(peer.complete());
- EXPECT_EQ(1, peer.seen_redirects());
+ EXPECT_EQ("", peer_context.data);
+ EXPECT_FALSE(peer_context.complete);
+ EXPECT_EQ(1, peer_context.seen_redirects);
// Resuming the request should asynchronously unleash the deferred messages.
dispatcher()->SetDefersLoading(request_id, false);
@@ -626,18 +737,17 @@ TEST_F(ResourceDispatcherTest, DeferOnRedirect) {
ConsumeDataReceived_ACK(id);
EXPECT_EQ(0u, queued_messages());
- EXPECT_TRUE(peer.received_response());
- EXPECT_EQ(kTestPageContents, peer.data());
- EXPECT_TRUE(peer.complete());
- EXPECT_EQ(1, peer.seen_redirects());
+ EXPECT_TRUE(peer_context.received_response);
+ EXPECT_EQ(kTestPageContents, peer_context.data);
+ EXPECT_TRUE(peer_context.complete);
+ EXPECT_EQ(1, peer_context.seen_redirects);
}
// Checks that a deferred request that's cancelled doesn't receive any messages.
TEST_F(ResourceDispatcherTest, CancelDeferredRequest) {
- scoped_ptr<RequestInfo> request_info(CreateRequestInfo(false));
- TestRequestPeer peer(dispatcher());
- int request_id = dispatcher()->StartAsync(*request_info.get(), NULL, &peer);
- peer.set_request_id(request_id);
+ std::unique_ptr<RequestInfo> request_info(CreateRequestInfo(false));
+ TestRequestPeer::Context peer_context;
+ int request_id = StartAsync(*request_info.get(), NULL, &peer_context);
int id = ConsumeRequestResource();
EXPECT_EQ(0u, queued_messages());
@@ -652,16 +762,15 @@ TEST_F(ResourceDispatcherTest, CancelDeferredRequest) {
// None of the messages should have been processed.
EXPECT_EQ(0u, queued_messages());
- EXPECT_EQ("", peer.data());
- EXPECT_FALSE(peer.complete());
- EXPECT_EQ(0, peer.seen_redirects());
+ EXPECT_EQ("", peer_context.data);
+ EXPECT_FALSE(peer_context.complete);
+ EXPECT_EQ(0, peer_context.seen_redirects);
}
TEST_F(ResourceDispatcherTest, DownloadToFile) {
- scoped_ptr<RequestInfo> request_info(CreateRequestInfo(true));
- TestRequestPeer peer(dispatcher());
- int request_id = dispatcher()->StartAsync(*request_info.get(), NULL, &peer);
- peer.set_request_id(request_id);
+ std::unique_ptr<RequestInfo> request_info(CreateRequestInfo(true));
+ TestRequestPeer::Context peer_context;
+ int request_id = StartAsync(*request_info.get(), NULL, &peer_context);
const int kDownloadedIncrement = 100;
const int kEncodedIncrement = 50;
@@ -670,7 +779,7 @@ TEST_F(ResourceDispatcherTest, DownloadToFile) {
NotifyReceivedResponse(id);
EXPECT_EQ(0u, queued_messages());
- EXPECT_TRUE(peer.received_response());
+ EXPECT_TRUE(peer_context.received_response);
int expected_total_downloaded_length = 0;
int expected_total_encoded_length = 0;
@@ -680,36 +789,37 @@ TEST_F(ResourceDispatcherTest, DownloadToFile) {
expected_total_downloaded_length += kDownloadedIncrement;
expected_total_encoded_length += kEncodedIncrement;
EXPECT_EQ(expected_total_downloaded_length,
- peer.total_downloaded_data_length());
- EXPECT_EQ(expected_total_encoded_length, peer.total_encoded_data_length());
+ peer_context.total_downloaded_data_length);
+ EXPECT_EQ(expected_total_encoded_length,
+ peer_context.total_encoded_data_length);
}
NotifyRequestComplete(id, strlen(kTestPageContents));
- EXPECT_EQ("", peer.data());
- EXPECT_TRUE(peer.complete());
+ EXPECT_EQ("", peer_context.data);
+ EXPECT_TRUE(peer_context.complete);
EXPECT_EQ(0u, queued_messages());
dispatcher()->RemovePendingRequest(request_id);
ConsumeReleaseDownloadedFile(id);
EXPECT_EQ(0u, queued_messages());
EXPECT_EQ(expected_total_downloaded_length,
- peer.total_downloaded_data_length());
- EXPECT_EQ(expected_total_encoded_length, peer.total_encoded_data_length());
+ peer_context.total_downloaded_data_length);
+ EXPECT_EQ(expected_total_encoded_length,
+ peer_context.total_encoded_data_length);
}
// Make sure that when a download to file is cancelled, the file is destroyed.
TEST_F(ResourceDispatcherTest, CancelDownloadToFile) {
- scoped_ptr<RequestInfo> request_info(CreateRequestInfo(true));
- TestRequestPeer peer(dispatcher());
- int request_id = dispatcher()->StartAsync(*request_info.get(), NULL, &peer);
- peer.set_request_id(request_id);
+ std::unique_ptr<RequestInfo> request_info(CreateRequestInfo(true));
+ TestRequestPeer::Context peer_context;
+ int request_id = StartAsync(*request_info.get(), NULL, &peer_context);
int id = ConsumeRequestResource();
EXPECT_EQ(0u, queued_messages());
NotifyReceivedResponse(id);
EXPECT_EQ(0u, queued_messages());
- EXPECT_TRUE(peer.received_response());
+ EXPECT_TRUE(peer_context.received_response);
// Cancelling the request deletes the file.
dispatcher()->Cancel(request_id);
@@ -733,9 +843,9 @@ class TimeConversionTest : public ResourceDispatcherTest {
}
void PerformTest(const ResourceResponseHead& response_head) {
- scoped_ptr<RequestInfo> request_info(CreateRequestInfo(false));
- TestRequestPeer peer(dispatcher());
- dispatcher()->StartAsync(*request_info.get(), NULL, &peer);
+ std::unique_ptr<RequestInfo> request_info(CreateRequestInfo(false));
+ TestRequestPeer::Context peer_context;
+ StartAsync(*request_info.get(), NULL, &peer_context);
dispatcher()->OnMessageReceived(
ResourceMsg_ReceivedResponse(0, response_head));
diff --git a/chromium/content/child/resource_scheduling_filter.cc b/chromium/content/child/resource_scheduling_filter.cc
index 1f0a20edd4e..1cde0e6a51e 100644
--- a/chromium/content/child/resource_scheduling_filter.cc
+++ b/chromium/content/child/resource_scheduling_filter.cc
@@ -77,7 +77,8 @@ bool ResourceSchedulingFilter::OnMessageReceived(const IPC::Message& message) {
}
void ResourceSchedulingFilter::SetRequestIdTaskRunner(
- int id, scoped_ptr<blink::WebTaskRunner> web_task_runner) {
+ int id,
+ std::unique_ptr<blink::WebTaskRunner> web_task_runner) {
base::AutoLock lock(request_id_to_task_runner_map_lock_);
request_id_to_task_runner_map_.insert(
std::make_pair(id, std::move(web_task_runner)));
diff --git a/chromium/content/child/resource_scheduling_filter.h b/chromium/content/child/resource_scheduling_filter.h
index 96eb81c76e8..93d243c9023 100644
--- a/chromium/content/child/resource_scheduling_filter.h
+++ b/chromium/content/child/resource_scheduling_filter.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include <map>
+#include <memory>
#include "base/containers/hash_tables.h"
#include "base/macros.h"
@@ -39,7 +40,8 @@ class CONTENT_EXPORT ResourceSchedulingFilter : public IPC::MessageFilter {
// Sets the task runner associated with request messages with |id|.
void SetRequestIdTaskRunner(
- int id, scoped_ptr<blink::WebTaskRunner> web_task_runner);
+ int id,
+ std::unique_ptr<blink::WebTaskRunner> web_task_runner);
// Removes the task runner associated with |id|.
void ClearRequestIdTaskRunner(int id);
@@ -50,7 +52,7 @@ class CONTENT_EXPORT ResourceSchedulingFilter : public IPC::MessageFilter {
~ResourceSchedulingFilter() override;
using RequestIdToTaskRunnerMap =
- std::map<int, scoped_ptr<blink::WebTaskRunner>>;
+ std::map<int, std::unique_ptr<blink::WebTaskRunner>>;
// This lock guards |request_id_to_task_runner_map_|
base::Lock request_id_to_task_runner_map_lock_;
diff --git a/chromium/content/child/runtime_features.cc b/chromium/content/child/runtime_features.cc
index b8137582c10..dc23cc5794b 100644
--- a/chromium/content/child/runtime_features.cc
+++ b/chromium/content/child/runtime_features.cc
@@ -19,25 +19,12 @@
#include "ui/gl/gl_switches.h"
#include "ui/native_theme/native_theme_switches.h"
-#if defined(OS_ANDROID)
-#include <cpu-features.h>
-#include "base/android/build_info.h"
-#include "media/base/android/media_codec_util.h"
-#endif
-
using blink::WebRuntimeFeatures;
namespace content {
static void SetRuntimeFeatureDefaultsForPlatform() {
#if defined(OS_ANDROID)
- // MSE/EME implementation needs Android MediaCodec API.
- if (!media::MediaCodecUtil::IsMediaCodecAvailable()) {
- WebRuntimeFeatures::enableMediaSource(false);
- WebRuntimeFeatures::enablePrefixedEncryptedMedia(false);
- WebRuntimeFeatures::enableEncryptedMedia(false);
- }
-
// Android does not have support for PagePopup
WebRuntimeFeatures::enablePagePopup(false);
// Android does not yet support SharedWorker. crbug.com/154571
@@ -61,8 +48,8 @@ static void SetRuntimeFeatureDefaultsForPlatform() {
WebRuntimeFeatures::enableCompositedSelectionUpdate(true);
#endif
-#if !(defined OS_ANDROID || defined OS_CHROMEOS || defined OS_IOS)
- // Only Android, ChromeOS, and IOS support NetInfo right now.
+#if !(defined OS_ANDROID || defined OS_CHROMEOS)
+ // Only Android, ChromeOS support NetInfo right now.
WebRuntimeFeatures::enableNetworkInformation(false);
#endif
}
@@ -72,20 +59,20 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
if (command_line.HasSwitch(switches::kEnableExperimentalWebPlatformFeatures))
WebRuntimeFeatures::enableExperimentalFeatures(true);
- if (base::FeatureList::IsEnabled(features::kExperimentalFramework))
- WebRuntimeFeatures::enableExperimentalFramework(true);
+ WebRuntimeFeatures::enableExperimentalFramework(
+ base::FeatureList::IsEnabled(features::kExperimentalFramework));
if (command_line.HasSwitch(switches::kEnableWebBluetooth))
WebRuntimeFeatures::enableWebBluetooth(true);
+ if (!base::FeatureList::IsEnabled(features::kWebUsb))
+ WebRuntimeFeatures::enableWebUsb(false);
+
SetRuntimeFeatureDefaultsForPlatform();
if (command_line.HasSwitch(switches::kDisableDatabases))
WebRuntimeFeatures::enableDatabase(false);
- if (command_line.HasSwitch(switches::kDisableMediaSource))
- WebRuntimeFeatures::enableMediaSource(false);
-
if (command_line.HasSwitch(switches::kDisableNotifications)) {
WebRuntimeFeatures::enableNotifications(false);
@@ -93,21 +80,15 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
WebRuntimeFeatures::enablePushMessaging(false);
}
+ if (command_line.HasSwitch(switches::kEnableNotificationActionIcons))
+ WebRuntimeFeatures::enableNotificationActionIcons(true);
+
if (command_line.HasSwitch(switches::kDisableSharedWorkers))
WebRuntimeFeatures::enableSharedWorker(false);
- if (command_line.HasSwitch(switches::kDisableWebAudio))
- WebRuntimeFeatures::enableWebAudio(false);
-
if (command_line.HasSwitch(switches::kDisableSpeechAPI))
WebRuntimeFeatures::enableScriptedSpeech(false);
- if (command_line.HasSwitch(switches::kDisableEncryptedMedia))
- WebRuntimeFeatures::enableEncryptedMedia(false);
-
- if (command_line.HasSwitch(switches::kEnablePrefixedEncryptedMedia))
- WebRuntimeFeatures::enablePrefixedEncryptedMedia(true);
-
if (command_line.HasSwitch(switches::kDisableFileSystem))
WebRuntimeFeatures::enableFileSystem(false);
@@ -129,8 +110,27 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
if (command_line.HasSwitch(switches::kEnableWebGLDraftExtensions))
WebRuntimeFeatures::enableWebGLDraftExtensions(true);
- if (command_line.HasSwitch(switches::kEnableWebGLImageChromium))
- WebRuntimeFeatures::enableWebGLImageChromium(true);
+#if defined(OS_MACOSX)
+ bool enable_canvas_2d_image_chromium = command_line.HasSwitch(
+ switches::kEnableGpuMemoryBufferCompositorResources) &&
+ !command_line.HasSwitch(switches::kDisable2dCanvasImageChromium) &&
+ !command_line.HasSwitch(switches::kDisableGpu);
+#else
+ bool enable_canvas_2d_image_chromium = false;
+#endif
+ WebRuntimeFeatures::enableCanvas2dImageChromium(
+ enable_canvas_2d_image_chromium);
+
+#if defined(OS_MACOSX)
+ bool enable_web_gl_image_chromium = command_line.HasSwitch(
+ switches::kEnableGpuMemoryBufferCompositorResources) &&
+ !command_line.HasSwitch(switches::kDisableWebGLImageChromium) &&
+ !command_line.HasSwitch(switches::kDisableGpu);
+#else
+ bool enable_web_gl_image_chromium =
+ command_line.HasSwitch(switches::kEnableWebGLImageChromium);
+#endif
+ WebRuntimeFeatures::enableWebGLImageChromium(enable_web_gl_image_chromium);
if (command_line.HasSwitch(switches::kForceOverlayFullscreenVideo))
WebRuntimeFeatures::forceOverlayFullscreenVideo(true);
@@ -147,8 +147,8 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
WebRuntimeFeatures::enableNetworkInformation(true);
}
- if (command_line.HasSwitch(switches::kEnableCredentialManagerAPI))
- WebRuntimeFeatures::enableCredentialManagerAPI(true);
+ if (!base::FeatureList::IsEnabled(features::kCredentialManagementAPI))
+ WebRuntimeFeatures::enableCredentialManagerAPI(false);
if (command_line.HasSwitch(switches::kReducedReferrerGranularity))
WebRuntimeFeatures::enableReducedReferrerGranularity(true);
@@ -173,12 +173,32 @@ void SetRuntimeFeaturesDefaultsAndUpdateFromArgs(
if (command_line.HasSwitch(switches::kDisablePresentationAPI))
WebRuntimeFeatures::enablePresentationAPI(false);
- if (base::FeatureList::IsEnabled(features::kWebFontsIntervention))
+ if (base::FeatureList::IsEnabled(features::kWebFontsIntervention)) {
WebRuntimeFeatures::enableWebFontsIntervention(true);
+ if (command_line.HasSwitch(switches::kEnableWebFontsInterventionTrigger))
+ WebRuntimeFeatures::enableWebFontsInterventionTrigger(true);
+ }
+
+ if (base::FeatureList::IsEnabled(features::kScrollAnchoring))
+ WebRuntimeFeatures::enableScrollAnchoring(true);
if (command_line.HasSwitch(switches::kEnableSlimmingPaintV2))
WebRuntimeFeatures::enableSlimmingPaintV2(true);
+ if (base::FeatureList::IsEnabled(features::kRenderingPipelineThrottling))
+ WebRuntimeFeatures::enableRenderingPipelineThrottling(true);
+
+ // Note that it might already by true for OS_ANDROID, above. This is for
+ // non-android versions.
+ if (base::FeatureList::IsEnabled(features::kNewMediaPlaybackUi))
+ WebRuntimeFeatures::enableNewMediaPlaybackUi(true);
+
+ if (base::FeatureList::IsEnabled(features::kDocumentWriteEvaluator))
+ WebRuntimeFeatures::enableDocumentWriteEvaluator(true);
+
+ WebRuntimeFeatures::enableMediaDocumentDownloadButton(
+ base::FeatureList::IsEnabled(features::kMediaDocumentDownloadButton));
+
// Enable explicitly enabled features, and then disable explicitly disabled
// ones.
if (command_line.HasSwitch(switches::kEnableBlinkFeatures)) {
diff --git a/chromium/content/child/scoped_web_callbacks.h b/chromium/content/child/scoped_web_callbacks.h
index 0d682309d80..fac339163d6 100644
--- a/chromium/content/child/scoped_web_callbacks.h
+++ b/chromium/content/child/scoped_web_callbacks.h
@@ -5,10 +5,11 @@
#ifndef CONTENT_CHILD_SCOPED_WEB_CALLBACKS_H_
#define CONTENT_CHILD_SCOPED_WEB_CALLBACKS_H_
+#include <memory>
#include <utility>
#include "base/callback.h"
-#include "base/memory/scoped_ptr.h"
+#include "base/memory/ptr_util.h"
#include "base/move.h"
#include "third_party/WebKit/public/platform/WebCallbacks.h"
@@ -39,7 +40,7 @@
// callbacks.PassCallbacks()->onSuccess(Foo("everything is great"));
// }
//
-// void OnCallbacksDropped(scoped_ptr<FooCallbacks> callbacks) {
+// void OnCallbacksDropped(std::unique_ptr<FooCallbacks> callbacks) {
// // Ownership of the FooCallbacks is passed to this function if
// // ScopedWebCallbacks::PassCallbacks isn't called before the
// // ScopedWebCallbacks is destroyed.
@@ -70,9 +71,9 @@ class ScopedWebCallbacks {
public:
using DestructionCallback =
- base::Callback<void(scoped_ptr<CallbacksType> callbacks)>;
+ base::Callback<void(std::unique_ptr<CallbacksType> callbacks)>;
- ScopedWebCallbacks(scoped_ptr<CallbacksType> callbacks,
+ ScopedWebCallbacks(std::unique_ptr<CallbacksType> callbacks,
const DestructionCallback& destruction_callback)
: callbacks_(std::move(callbacks)),
destruction_callback_(destruction_callback) {}
@@ -90,10 +91,12 @@ class ScopedWebCallbacks {
return *this;
}
- scoped_ptr<CallbacksType> PassCallbacks() { return std::move(callbacks_); }
+ std::unique_ptr<CallbacksType> PassCallbacks() {
+ return std::move(callbacks_);
+ }
private:
- scoped_ptr<CallbacksType> callbacks_;
+ std::unique_ptr<CallbacksType> callbacks_;
DestructionCallback destruction_callback_;
};
@@ -102,7 +105,7 @@ ScopedWebCallbacks<CallbacksType> make_scoped_web_callbacks(
CallbacksType* callbacks,
const typename ScopedWebCallbacks<CallbacksType>::DestructionCallback&
destruction_callback) {
- return ScopedWebCallbacks<CallbacksType>(make_scoped_ptr(callbacks),
+ return ScopedWebCallbacks<CallbacksType>(base::WrapUnique(callbacks),
destruction_callback);
}
diff --git a/chromium/content/child/service_worker/service_worker_dispatcher.cc b/chromium/content/child/service_worker/service_worker_dispatcher.cc
index b8fd142164a..b302e539f7e 100644
--- a/chromium/content/child/service_worker/service_worker_dispatcher.cc
+++ b/chromium/content/child/service_worker/service_worker_dispatcher.cc
@@ -25,6 +25,7 @@
#include "content/public/common/content_constants.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerProviderClient.h"
+#include "url/url_constants.h"
using blink::WebServiceWorkerError;
using blink::WebServiceWorkerProvider;
@@ -110,10 +111,10 @@ void ServiceWorkerDispatcher::RegisterServiceWorker(
WebServiceWorkerRegistrationCallbacks* callbacks) {
DCHECK(callbacks);
- if (pattern.possibly_invalid_spec().size() > kMaxURLChars ||
- script_url.possibly_invalid_spec().size() > kMaxURLChars) {
- scoped_ptr<WebServiceWorkerRegistrationCallbacks>
- owned_callbacks(callbacks);
+ if (pattern.possibly_invalid_spec().size() > url::kMaxURLChars ||
+ script_url.possibly_invalid_spec().size() > url::kMaxURLChars) {
+ std::unique_ptr<WebServiceWorkerRegistrationCallbacks> owned_callbacks(
+ callbacks);
std::string error_message(kServiceWorkerRegisterErrorPrefix);
error_message += "The provided scriptURL or scope is too long.";
callbacks->onError(
@@ -161,8 +162,8 @@ void ServiceWorkerDispatcher::GetRegistration(
WebServiceWorkerGetRegistrationCallbacks* callbacks) {
DCHECK(callbacks);
- if (document_url.possibly_invalid_spec().size() > kMaxURLChars) {
- scoped_ptr<WebServiceWorkerGetRegistrationCallbacks> owned_callbacks(
+ if (document_url.possibly_invalid_spec().size() > url::kMaxURLChars) {
+ std::unique_ptr<WebServiceWorkerGetRegistrationCallbacks> owned_callbacks(
callbacks);
std::string error_message(kServiceWorkerGetRegistrationErrorPrefix);
error_message += "The provided documentURL is too long.";
@@ -266,7 +267,7 @@ void ServiceWorkerDispatcher::WillStopCurrentWorkerThread() {
scoped_refptr<WebServiceWorkerImpl>
ServiceWorkerDispatcher::GetOrCreateServiceWorker(
- scoped_ptr<ServiceWorkerHandleReference> handle_ref) {
+ std::unique_ptr<ServiceWorkerHandleReference> handle_ref) {
if (!handle_ref)
return nullptr;
@@ -311,12 +312,14 @@ scoped_refptr<WebServiceWorkerRegistrationImpl>
ServiceWorkerDispatcher::GetOrAdoptRegistration(
const ServiceWorkerRegistrationObjectInfo& info,
const ServiceWorkerVersionAttributes& attrs) {
- scoped_ptr<ServiceWorkerRegistrationHandleReference> registration_ref =
+ std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration_ref =
Adopt(info);
- scoped_ptr<ServiceWorkerHandleReference> installing_ref =
+ std::unique_ptr<ServiceWorkerHandleReference> installing_ref =
Adopt(attrs.installing);
- scoped_ptr<ServiceWorkerHandleReference> waiting_ref = Adopt(attrs.waiting);
- scoped_ptr<ServiceWorkerHandleReference> active_ref = Adopt(attrs.active);
+ std::unique_ptr<ServiceWorkerHandleReference> waiting_ref =
+ Adopt(attrs.waiting);
+ std::unique_ptr<ServiceWorkerHandleReference> active_ref =
+ Adopt(attrs.active);
RegistrationObjectMap::iterator found = registrations_.find(info.handle_id);
if (found != registrations_.end())
@@ -340,11 +343,12 @@ void ServiceWorkerDispatcher::OnAssociateRegistration(
const ServiceWorkerVersionAttributes& attrs) {
// Adopt the references sent from the browser process and pass them to the
// provider context if it exists.
- scoped_ptr<ServiceWorkerRegistrationHandleReference> registration =
+ std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration =
Adopt(info);
- scoped_ptr<ServiceWorkerHandleReference> installing = Adopt(attrs.installing);
- scoped_ptr<ServiceWorkerHandleReference> waiting = Adopt(attrs.waiting);
- scoped_ptr<ServiceWorkerHandleReference> active = Adopt(attrs.active);
+ std::unique_ptr<ServiceWorkerHandleReference> installing =
+ Adopt(attrs.installing);
+ std::unique_ptr<ServiceWorkerHandleReference> waiting = Adopt(attrs.waiting);
+ std::unique_ptr<ServiceWorkerHandleReference> active = Adopt(attrs.active);
ProviderContextMap::iterator context = provider_contexts_.find(provider_id);
if (context != provider_contexts_.end()) {
context->second->OnAssociateRegistration(
@@ -472,7 +476,7 @@ void ServiceWorkerDispatcher::OnDidGetRegistrations(
typedef blink::WebVector<blink::WebServiceWorkerRegistration::Handle*>
WebServiceWorkerRegistrationArray;
- scoped_ptr<WebServiceWorkerRegistrationArray> registrations(
+ std::unique_ptr<WebServiceWorkerRegistrationArray> registrations(
new WebServiceWorkerRegistrationArray(infos.size()));
for (size_t i = 0; i < infos.size(); ++i) {
if (infos[i].handle_id != kInvalidServiceWorkerHandleId) {
@@ -480,14 +484,14 @@ void ServiceWorkerDispatcher::OnDidGetRegistrations(
ServiceWorkerVersionAttributes attr(attrs[i]);
// WebServiceWorkerGetRegistrationsCallbacks cannot receive an array of
- // WebPassOwnPtr<WebServiceWorkerRegistration::Handle>, so create leaky
+ // std::unique_ptr<WebServiceWorkerRegistration::Handle>, so create leaky
// handles instead.
(*registrations)[i] = WebServiceWorkerRegistrationImpl::CreateLeakyHandle(
GetOrAdoptRegistration(info, attr));
}
}
- callbacks->onSuccess(blink::adoptWebPtr(registrations.release()));
+ callbacks->onSuccess(std::move(registrations));
pending_get_registrations_callbacks_.Remove(request_id);
}
@@ -651,9 +655,10 @@ void ServiceWorkerDispatcher::OnSetVersionAttributes(
// Adopt the references sent from the browser process and pass it to the
// registration if it exists.
- scoped_ptr<ServiceWorkerHandleReference> installing = Adopt(attrs.installing);
- scoped_ptr<ServiceWorkerHandleReference> waiting = Adopt(attrs.waiting);
- scoped_ptr<ServiceWorkerHandleReference> active = Adopt(attrs.active);
+ std::unique_ptr<ServiceWorkerHandleReference> installing =
+ Adopt(attrs.installing);
+ std::unique_ptr<ServiceWorkerHandleReference> waiting = Adopt(attrs.waiting);
+ std::unique_ptr<ServiceWorkerHandleReference> active = Adopt(attrs.active);
RegistrationObjectMap::iterator found =
registrations_.find(registration_handle_id);
@@ -693,7 +698,7 @@ void ServiceWorkerDispatcher::OnSetControllerServiceWorker(
// Adopt the reference sent from the browser process and pass it to the
// provider context if it exists.
- scoped_ptr<ServiceWorkerHandleReference> handle_ref = Adopt(info);
+ std::unique_ptr<ServiceWorkerHandleReference> handle_ref = Adopt(info);
ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
if (provider != provider_contexts_.end())
provider->second->OnSetControllerServiceWorker(std::move(handle_ref));
@@ -763,14 +768,14 @@ void ServiceWorkerDispatcher::RemoveServiceWorkerRegistration(
registrations_.erase(registration_handle_id);
}
-scoped_ptr<ServiceWorkerRegistrationHandleReference>
+std::unique_ptr<ServiceWorkerRegistrationHandleReference>
ServiceWorkerDispatcher::Adopt(
const ServiceWorkerRegistrationObjectInfo& info) {
return ServiceWorkerRegistrationHandleReference::Adopt(
info, thread_safe_sender_.get());
}
-scoped_ptr<ServiceWorkerHandleReference> ServiceWorkerDispatcher::Adopt(
+std::unique_ptr<ServiceWorkerHandleReference> ServiceWorkerDispatcher::Adopt(
const ServiceWorkerObjectInfo& info) {
return ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_.get());
}
diff --git a/chromium/content/child/service_worker/service_worker_dispatcher.h b/chromium/content/child/service_worker/service_worker_dispatcher.h
index f84f847cf8a..47939718055 100644
--- a/chromium/content/child/service_worker/service_worker_dispatcher.h
+++ b/chromium/content/child/service_worker/service_worker_dispatcher.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include <map>
+#include <memory>
#include <vector>
#include "base/id_map.h"
@@ -118,7 +119,7 @@ class CONTENT_EXPORT ServiceWorkerDispatcher : public WorkerThread::Observer {
// Returns the existing service worker or a newly created one with the given
// handle reference. Returns nullptr if the given reference is invalid.
scoped_refptr<WebServiceWorkerImpl> GetOrCreateServiceWorker(
- scoped_ptr<ServiceWorkerHandleReference> handle_ref);
+ std::unique_ptr<ServiceWorkerHandleReference> handle_ref);
// Returns the existing registration or a newly created one. When a new one is
// created, increments interprocess references to the registration and its
@@ -253,9 +254,9 @@ class CONTENT_EXPORT ServiceWorkerDispatcher : public WorkerThread::Observer {
// Assumes that the given object information retains an interprocess handle
// reference passed from the browser process, and adopts it.
- scoped_ptr<ServiceWorkerRegistrationHandleReference> Adopt(
+ std::unique_ptr<ServiceWorkerRegistrationHandleReference> Adopt(
const ServiceWorkerRegistrationObjectInfo& info);
- scoped_ptr<ServiceWorkerHandleReference> Adopt(
+ std::unique_ptr<ServiceWorkerHandleReference> Adopt(
const ServiceWorkerObjectInfo& info);
RegistrationCallbackMap pending_registration_callbacks_;
diff --git a/chromium/content/child/service_worker/service_worker_dispatcher_unittest.cc b/chromium/content/child/service_worker/service_worker_dispatcher_unittest.cc
index 6d6f939029b..d00644b30d2 100644
--- a/chromium/content/child/service_worker/service_worker_dispatcher_unittest.cc
+++ b/chromium/content/child/service_worker/service_worker_dispatcher_unittest.cc
@@ -94,7 +94,7 @@ class ServiceWorkerDispatcherTest : public testing::Test {
dispatcher_->OnPostMessage(params);
}
- scoped_ptr<ServiceWorkerHandleReference> Adopt(
+ std::unique_ptr<ServiceWorkerHandleReference> Adopt(
const ServiceWorkerObjectInfo& info) {
return dispatcher_->Adopt(info);
}
@@ -106,7 +106,7 @@ class ServiceWorkerDispatcherTest : public testing::Test {
private:
base::MessageLoop message_loop_;
IPC::TestSink ipc_sink_;
- scoped_ptr<ServiceWorkerDispatcher> dispatcher_;
+ std::unique_ptr<ServiceWorkerDispatcher> dispatcher_;
scoped_refptr<ServiceWorkerTestSender> sender_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerDispatcherTest);
@@ -125,16 +125,15 @@ class MockWebServiceWorkerProviderClientImpl
dispatcher_->RemoveProviderClient(provider_id_);
}
- void setController(
- blink::WebPassOwnPtr<blink::WebServiceWorker::Handle> handle,
- bool shouldNotifyControllerChange) override {
+ void setController(std::unique_ptr<blink::WebServiceWorker::Handle> handle,
+ bool shouldNotifyControllerChange) override {
// WebPassOwnPtr cannot be owned in Chromium, so drop the handle here.
// The destruction releases ServiceWorkerHandleReference.
is_set_controlled_called_ = true;
}
void dispatchMessageEvent(
- blink::WebPassOwnPtr<blink::WebServiceWorker::Handle> handle,
+ std::unique_ptr<blink::WebServiceWorker::Handle> handle,
const blink::WebString& message,
const blink::WebMessagePortChannelArray& channels) override {
// WebPassOwnPtr cannot be owned in Chromium, so drop the handle here.
@@ -294,7 +293,7 @@ TEST_F(ServiceWorkerDispatcherTest, OnSetControllerServiceWorker) {
// mock provider client. See the comment on setController() of the mock).
// In addition, the passed reference should be adopted but immediately
// released because there is no provider context to own it.
- scoped_ptr<MockWebServiceWorkerProviderClientImpl> provider_client(
+ std::unique_ptr<MockWebServiceWorkerProviderClientImpl> provider_client(
new MockWebServiceWorkerProviderClientImpl(kProviderId, dispatcher()));
ASSERT_FALSE(provider_client->is_set_controlled_called());
OnSetControllerServiceWorker(kDocumentMainThreadId, kProviderId, attrs.active,
@@ -342,7 +341,7 @@ TEST_F(ServiceWorkerDispatcherTest, OnSetControllerServiceWorker_Null) {
ServiceWorkerVersionAttributes attrs;
CreateObjectInfoAndVersionAttributes(&info, &attrs);
- scoped_ptr<MockWebServiceWorkerProviderClientImpl> provider_client(
+ std::unique_ptr<MockWebServiceWorkerProviderClientImpl> provider_client(
new MockWebServiceWorkerProviderClientImpl(kProviderId, dispatcher()));
scoped_refptr<ServiceWorkerProviderContext> provider_context(
new ServiceWorkerProviderContext(kProviderId,
@@ -383,7 +382,7 @@ TEST_F(ServiceWorkerDispatcherTest, OnPostMessage) {
ipc_sink()->GetMessageAt(0)->type());
ipc_sink()->ClearMessages();
- scoped_ptr<MockWebServiceWorkerProviderClientImpl> provider_client(
+ std::unique_ptr<MockWebServiceWorkerProviderClientImpl> provider_client(
new MockWebServiceWorkerProviderClientImpl(kProviderId, dispatcher()));
ASSERT_FALSE(provider_client->is_dispatch_message_event_called());
diff --git a/chromium/content/child/service_worker/service_worker_handle_reference.cc b/chromium/content/child/service_worker/service_worker_handle_reference.cc
index ad7395256fa..5cd79ccfa3f 100644
--- a/chromium/content/child/service_worker/service_worker_handle_reference.cc
+++ b/chromium/content/child/service_worker/service_worker_handle_reference.cc
@@ -4,28 +4,29 @@
#include "content/child/service_worker/service_worker_handle_reference.h"
+#include "base/memory/ptr_util.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/service_worker/service_worker_messages.h"
namespace content {
-scoped_ptr<ServiceWorkerHandleReference>
-ServiceWorkerHandleReference::Create(
- const ServiceWorkerObjectInfo& info,
- ThreadSafeSender* sender) {
+std::unique_ptr<ServiceWorkerHandleReference>
+ServiceWorkerHandleReference::Create(const ServiceWorkerObjectInfo& info,
+ ThreadSafeSender* sender) {
DCHECK(sender);
if (info.handle_id == kInvalidServiceWorkerHandleId)
return nullptr;
- return make_scoped_ptr(new ServiceWorkerHandleReference(info, sender, true));
+ return base::WrapUnique(new ServiceWorkerHandleReference(info, sender, true));
}
-scoped_ptr<ServiceWorkerHandleReference> ServiceWorkerHandleReference::Adopt(
- const ServiceWorkerObjectInfo& info,
- ThreadSafeSender* sender) {
+std::unique_ptr<ServiceWorkerHandleReference>
+ServiceWorkerHandleReference::Adopt(const ServiceWorkerObjectInfo& info,
+ ThreadSafeSender* sender) {
DCHECK(sender);
if (info.handle_id == kInvalidServiceWorkerHandleId)
return nullptr;
- return make_scoped_ptr(new ServiceWorkerHandleReference(info, sender, false));
+ return base::WrapUnique(
+ new ServiceWorkerHandleReference(info, sender, false));
}
ServiceWorkerHandleReference::ServiceWorkerHandleReference(
diff --git a/chromium/content/child/service_worker/service_worker_handle_reference.h b/chromium/content/child/service_worker/service_worker_handle_reference.h
index d82fb329cba..dc952848501 100644
--- a/chromium/content/child/service_worker/service_worker_handle_reference.h
+++ b/chromium/content/child/service_worker/service_worker_handle_reference.h
@@ -7,9 +7,10 @@
#include <stdint.h>
+#include <memory>
+
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_types.h"
@@ -24,13 +25,13 @@ class CONTENT_EXPORT ServiceWorkerHandleReference {
public:
// Creates a new ServiceWorkerHandleReference and increments ref-count. If
// the handle id is kInvalidServiceWorkerHandleId, returns null instead.
- static scoped_ptr<ServiceWorkerHandleReference> Create(
+ static std::unique_ptr<ServiceWorkerHandleReference> Create(
const ServiceWorkerObjectInfo& info,
ThreadSafeSender* sender);
// Creates a new ServiceWorkerHandleReference by adopting a ref-count. If
// the handle id is kInvalidServiceWorkerHandleId, returns null instead.
- static scoped_ptr<ServiceWorkerHandleReference> Adopt(
+ static std::unique_ptr<ServiceWorkerHandleReference> Adopt(
const ServiceWorkerObjectInfo& info,
ThreadSafeSender* sender);
diff --git a/chromium/content/child/service_worker/service_worker_network_provider.cc b/chromium/content/child/service_worker/service_worker_network_provider.cc
index 7ce9697b22a..dab3db75175 100644
--- a/chromium/content/child/service_worker/service_worker_network_provider.cc
+++ b/chromium/content/child/service_worker/service_worker_network_provider.cc
@@ -37,7 +37,7 @@ int GenerateProviderIdForType(const ServiceWorkerProviderType provider_type) {
void ServiceWorkerNetworkProvider::AttachToDocumentState(
base::SupportsUserData* datasource_userdata,
- scoped_ptr<ServiceWorkerNetworkProvider> network_provider) {
+ std::unique_ptr<ServiceWorkerNetworkProvider> network_provider) {
datasource_userdata->SetUserData(&kUserDataKey, network_provider.release());
}
@@ -48,7 +48,7 @@ ServiceWorkerNetworkProvider* ServiceWorkerNetworkProvider::FromDocumentState(
}
// static
-scoped_ptr<ServiceWorkerNetworkProvider>
+std::unique_ptr<ServiceWorkerNetworkProvider>
ServiceWorkerNetworkProvider::CreateForNavigation(
int route_id,
const RequestNavigationParams& request_params,
@@ -57,7 +57,7 @@ ServiceWorkerNetworkProvider::CreateForNavigation(
bool browser_side_navigation = IsBrowserSideNavigationEnabled();
bool should_create_provider_for_window = false;
int service_worker_provider_id = kInvalidServiceWorkerProviderId;
- scoped_ptr<ServiceWorkerNetworkProvider> network_provider;
+ std::unique_ptr<ServiceWorkerNetworkProvider> network_provider;
// Determine if a ServiceWorkerNetworkProvider should be created and properly
// initialized for the navigation. A default ServiceWorkerNetworkProvider
@@ -81,20 +81,20 @@ ServiceWorkerNetworkProvider::CreateForNavigation(
// Now create the ServiceWorkerNetworkProvider (with invalid id if needed).
if (should_create_provider_for_window) {
if (service_worker_provider_id == kInvalidServiceWorkerProviderId) {
- network_provider = scoped_ptr<ServiceWorkerNetworkProvider>(
+ network_provider = std::unique_ptr<ServiceWorkerNetworkProvider>(
new ServiceWorkerNetworkProvider(route_id,
SERVICE_WORKER_PROVIDER_FOR_WINDOW));
} else {
CHECK(browser_side_navigation);
DCHECK(ServiceWorkerUtils::IsBrowserAssignedProviderId(
service_worker_provider_id));
- network_provider = scoped_ptr<ServiceWorkerNetworkProvider>(
+ network_provider = std::unique_ptr<ServiceWorkerNetworkProvider>(
new ServiceWorkerNetworkProvider(route_id,
SERVICE_WORKER_PROVIDER_FOR_WINDOW,
service_worker_provider_id));
}
} else {
- network_provider = scoped_ptr<ServiceWorkerNetworkProvider>(
+ network_provider = std::unique_ptr<ServiceWorkerNetworkProvider>(
new ServiceWorkerNetworkProvider());
}
return network_provider;
diff --git a/chromium/content/child/service_worker/service_worker_network_provider.h b/chromium/content/child/service_worker/service_worker_network_provider.h
index 74a12674603..178adf5a1ce 100644
--- a/chromium/content/child/service_worker/service_worker_network_provider.h
+++ b/chromium/content/child/service_worker/service_worker_network_provider.h
@@ -7,10 +7,11 @@
#include <stdint.h>
+#include <memory>
+
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/supports_user_data.h"
#include "content/common/content_export.h"
#include "content/common/service_worker/service_worker_types.h"
@@ -37,12 +38,12 @@ class CONTENT_EXPORT ServiceWorkerNetworkProvider
// Ownership is transferred to the DocumentState.
static void AttachToDocumentState(
base::SupportsUserData* document_state,
- scoped_ptr<ServiceWorkerNetworkProvider> network_provider);
+ std::unique_ptr<ServiceWorkerNetworkProvider> network_provider);
static ServiceWorkerNetworkProvider* FromDocumentState(
base::SupportsUserData* document_state);
- static scoped_ptr<ServiceWorkerNetworkProvider> CreateForNavigation(
+ static std::unique_ptr<ServiceWorkerNetworkProvider> CreateForNavigation(
int route_id,
const RequestNavigationParams& request_params,
blink::WebSandboxFlags sandbox_flags,
diff --git a/chromium/content/child/service_worker/service_worker_provider_context.cc b/chromium/content/child/service_worker/service_worker_provider_context.cc
index 9ff307e8ec6..9aa1e16b4b2 100644
--- a/chromium/content/child/service_worker/service_worker_provider_context.cc
+++ b/chromium/content/child/service_worker/service_worker_provider_context.cc
@@ -21,16 +21,16 @@ class ServiceWorkerProviderContext::Delegate {
public:
virtual ~Delegate(){};
virtual void AssociateRegistration(
- scoped_ptr<ServiceWorkerRegistrationHandleReference> registration,
- scoped_ptr<ServiceWorkerHandleReference> installing,
- scoped_ptr<ServiceWorkerHandleReference> waiting,
- scoped_ptr<ServiceWorkerHandleReference> active) = 0;
+ std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration,
+ std::unique_ptr<ServiceWorkerHandleReference> installing,
+ std::unique_ptr<ServiceWorkerHandleReference> waiting,
+ std::unique_ptr<ServiceWorkerHandleReference> active) = 0;
virtual void DisassociateRegistration() = 0;
virtual void GetAssociatedRegistration(
ServiceWorkerRegistrationObjectInfo* info,
ServiceWorkerVersionAttributes* attrs) = 0;
virtual void SetController(
- scoped_ptr<ServiceWorkerHandleReference> controller) = 0;
+ std::unique_ptr<ServiceWorkerHandleReference> controller) = 0;
virtual ServiceWorkerHandleReference* controller() = 0;
};
@@ -44,10 +44,10 @@ class ServiceWorkerProviderContext::ControlleeDelegate
~ControlleeDelegate() override {}
void AssociateRegistration(
- scoped_ptr<ServiceWorkerRegistrationHandleReference> registration,
- scoped_ptr<ServiceWorkerHandleReference> installing,
- scoped_ptr<ServiceWorkerHandleReference> waiting,
- scoped_ptr<ServiceWorkerHandleReference> active) override {
+ std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration,
+ std::unique_ptr<ServiceWorkerHandleReference> installing,
+ std::unique_ptr<ServiceWorkerHandleReference> waiting,
+ std::unique_ptr<ServiceWorkerHandleReference> active) override {
DCHECK(!registration_);
registration_ = std::move(registration);
}
@@ -58,7 +58,7 @@ class ServiceWorkerProviderContext::ControlleeDelegate
}
void SetController(
- scoped_ptr<ServiceWorkerHandleReference> controller) override {
+ std::unique_ptr<ServiceWorkerHandleReference> controller) override {
DCHECK(registration_);
DCHECK(!controller ||
controller->handle_id() != kInvalidServiceWorkerHandleId);
@@ -76,8 +76,8 @@ class ServiceWorkerProviderContext::ControlleeDelegate
}
private:
- scoped_ptr<ServiceWorkerRegistrationHandleReference> registration_;
- scoped_ptr<ServiceWorkerHandleReference> controller_;
+ std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration_;
+ std::unique_ptr<ServiceWorkerHandleReference> controller_;
DISALLOW_COPY_AND_ASSIGN(ControlleeDelegate);
};
@@ -91,10 +91,10 @@ class ServiceWorkerProviderContext::ControllerDelegate
~ControllerDelegate() override {}
void AssociateRegistration(
- scoped_ptr<ServiceWorkerRegistrationHandleReference> registration,
- scoped_ptr<ServiceWorkerHandleReference> installing,
- scoped_ptr<ServiceWorkerHandleReference> waiting,
- scoped_ptr<ServiceWorkerHandleReference> active) override {
+ std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration,
+ std::unique_ptr<ServiceWorkerHandleReference> installing,
+ std::unique_ptr<ServiceWorkerHandleReference> waiting,
+ std::unique_ptr<ServiceWorkerHandleReference> active) override {
DCHECK(!registration_);
registration_ = std::move(registration);
installing_ = std::move(installing);
@@ -108,7 +108,7 @@ class ServiceWorkerProviderContext::ControllerDelegate
}
void SetController(
- scoped_ptr<ServiceWorkerHandleReference> controller) override {
+ std::unique_ptr<ServiceWorkerHandleReference> controller) override {
NOTREACHED();
}
@@ -131,10 +131,10 @@ class ServiceWorkerProviderContext::ControllerDelegate
}
private:
- scoped_ptr<ServiceWorkerRegistrationHandleReference> registration_;
- scoped_ptr<ServiceWorkerHandleReference> installing_;
- scoped_ptr<ServiceWorkerHandleReference> waiting_;
- scoped_ptr<ServiceWorkerHandleReference> active_;
+ std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration_;
+ std::unique_ptr<ServiceWorkerHandleReference> installing_;
+ std::unique_ptr<ServiceWorkerHandleReference> waiting_;
+ std::unique_ptr<ServiceWorkerHandleReference> active_;
DISALLOW_COPY_AND_ASSIGN(ControllerDelegate);
};
@@ -166,10 +166,10 @@ ServiceWorkerProviderContext::~ServiceWorkerProviderContext() {
}
void ServiceWorkerProviderContext::OnAssociateRegistration(
- scoped_ptr<ServiceWorkerRegistrationHandleReference> registration,
- scoped_ptr<ServiceWorkerHandleReference> installing,
- scoped_ptr<ServiceWorkerHandleReference> waiting,
- scoped_ptr<ServiceWorkerHandleReference> active) {
+ std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration,
+ std::unique_ptr<ServiceWorkerHandleReference> installing,
+ std::unique_ptr<ServiceWorkerHandleReference> waiting,
+ std::unique_ptr<ServiceWorkerHandleReference> active) {
DCHECK(main_thread_task_runner_->RunsTasksOnCurrentThread());
delegate_->AssociateRegistration(std::move(registration),
std::move(installing), std::move(waiting),
@@ -182,7 +182,7 @@ void ServiceWorkerProviderContext::OnDisassociateRegistration() {
}
void ServiceWorkerProviderContext::OnSetControllerServiceWorker(
- scoped_ptr<ServiceWorkerHandleReference> controller) {
+ std::unique_ptr<ServiceWorkerHandleReference> controller) {
DCHECK(main_thread_task_runner_->RunsTasksOnCurrentThread());
delegate_->SetController(std::move(controller));
}
diff --git a/chromium/content/child/service_worker/service_worker_provider_context.h b/chromium/content/child/service_worker/service_worker_provider_context.h
index 06561a4bd04..85e259a852b 100644
--- a/chromium/content/child/service_worker/service_worker_provider_context.h
+++ b/chromium/content/child/service_worker/service_worker_provider_context.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_CHILD_SERVICE_WORKER_SERVICE_WORKER_PROVIDER_CONTEXT_H_
#define CONTENT_CHILD_SERVICE_WORKER_SERVICE_WORKER_PROVIDER_CONTEXT_H_
+#include <memory>
#include <set>
#include <vector>
@@ -51,13 +52,13 @@ class CONTENT_EXPORT ServiceWorkerProviderContext
// Called from ServiceWorkerDispatcher.
void OnAssociateRegistration(
- scoped_ptr<ServiceWorkerRegistrationHandleReference> registration,
- scoped_ptr<ServiceWorkerHandleReference> installing,
- scoped_ptr<ServiceWorkerHandleReference> waiting,
- scoped_ptr<ServiceWorkerHandleReference> active);
+ std::unique_ptr<ServiceWorkerRegistrationHandleReference> registration,
+ std::unique_ptr<ServiceWorkerHandleReference> installing,
+ std::unique_ptr<ServiceWorkerHandleReference> waiting,
+ std::unique_ptr<ServiceWorkerHandleReference> active);
void OnDisassociateRegistration();
void OnSetControllerServiceWorker(
- scoped_ptr<ServiceWorkerHandleReference> controller);
+ std::unique_ptr<ServiceWorkerHandleReference> controller);
// Called on the worker thread. Used for initializing
// ServiceWorkerGlobalScope.
@@ -85,7 +86,7 @@ class CONTENT_EXPORT ServiceWorkerProviderContext
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
scoped_refptr<ThreadSafeSender> thread_safe_sender_;
- scoped_ptr<Delegate> delegate_;
+ std::unique_ptr<Delegate> delegate_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerProviderContext);
};
diff --git a/chromium/content/child/service_worker/service_worker_registration_handle_reference.cc b/chromium/content/child/service_worker/service_worker_registration_handle_reference.cc
index 7a9e2847ae0..9d118231d93 100644
--- a/chromium/content/child/service_worker/service_worker_registration_handle_reference.cc
+++ b/chromium/content/child/service_worker/service_worker_registration_handle_reference.cc
@@ -4,25 +4,26 @@
#include "content/child/service_worker/service_worker_registration_handle_reference.h"
+#include "base/memory/ptr_util.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/service_worker/service_worker_messages.h"
namespace content {
-scoped_ptr<ServiceWorkerRegistrationHandleReference>
+std::unique_ptr<ServiceWorkerRegistrationHandleReference>
ServiceWorkerRegistrationHandleReference::Create(
const ServiceWorkerRegistrationObjectInfo& info,
ThreadSafeSender* sender) {
- return make_scoped_ptr(new ServiceWorkerRegistrationHandleReference(
- info, sender, true));
+ return base::WrapUnique(
+ new ServiceWorkerRegistrationHandleReference(info, sender, true));
}
-scoped_ptr<ServiceWorkerRegistrationHandleReference>
+std::unique_ptr<ServiceWorkerRegistrationHandleReference>
ServiceWorkerRegistrationHandleReference::Adopt(
const ServiceWorkerRegistrationObjectInfo& info,
ThreadSafeSender* sender) {
- return make_scoped_ptr(new ServiceWorkerRegistrationHandleReference(
- info, sender, false));
+ return base::WrapUnique(
+ new ServiceWorkerRegistrationHandleReference(info, sender, false));
}
ServiceWorkerRegistrationHandleReference::
diff --git a/chromium/content/child/service_worker/service_worker_registration_handle_reference.h b/chromium/content/child/service_worker/service_worker_registration_handle_reference.h
index 5edb58a0add..8f37098e40a 100644
--- a/chromium/content/child/service_worker/service_worker_registration_handle_reference.h
+++ b/chromium/content/child/service_worker/service_worker_registration_handle_reference.h
@@ -7,9 +7,10 @@
#include <stdint.h>
+#include <memory>
+
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "content/common/service_worker/service_worker_types.h"
#include "url/gurl.h"
@@ -25,13 +26,13 @@ class ServiceWorkerRegistrationHandleReference {
public:
// Creates a new ServiceWorkerRegistrationHandleReference and increments
// ref-count.
- static scoped_ptr<ServiceWorkerRegistrationHandleReference> Create(
+ static std::unique_ptr<ServiceWorkerRegistrationHandleReference> Create(
const ServiceWorkerRegistrationObjectInfo& info,
ThreadSafeSender* sender);
// Creates a new ServiceWorkerRegistrationHandleReference by adopting a
// ref-count.
- static scoped_ptr<ServiceWorkerRegistrationHandleReference> Adopt(
+ static std::unique_ptr<ServiceWorkerRegistrationHandleReference> Adopt(
const ServiceWorkerRegistrationObjectInfo& info,
ThreadSafeSender* sender);
diff --git a/chromium/content/child/service_worker/web_service_worker_impl.cc b/chromium/content/child/service_worker/web_service_worker_impl.cc
index f38d2c0767f..8e85e3bc262 100644
--- a/chromium/content/child/service_worker/web_service_worker_impl.cc
+++ b/chromium/content/child/service_worker/web_service_worker_impl.cc
@@ -7,17 +7,23 @@
#include <utility>
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "content/child/service_worker/service_worker_dispatcher.h"
#include "content/child/service_worker/service_worker_handle_reference.h"
+#include "content/child/service_worker/web_service_worker_provider_impl.h"
#include "content/child/thread_safe_sender.h"
#include "content/child/webmessageportchannel_impl.h"
#include "content/common/service_worker/service_worker_messages.h"
+#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerProxy.h"
+#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
using blink::WebMessagePortChannel;
using blink::WebMessagePortChannelArray;
using blink::WebMessagePortChannelClient;
+using blink::WebRuntimeFeatures;
+using blink::WebSecurityOrigin;
using blink::WebString;
namespace content {
@@ -41,17 +47,27 @@ class HandleImpl : public blink::WebServiceWorker::Handle {
void SendPostMessageToWorkerOnMainThread(
ThreadSafeSender* thread_safe_sender,
int handle_id,
+ int provider_id,
const base::string16& message,
- scoped_ptr<WebMessagePortChannelArray> channels) {
- thread_safe_sender->Send(new ServiceWorkerHostMsg_PostMessageToWorker(
- handle_id, message,
- WebMessagePortChannelImpl::ExtractMessagePortIDs(std::move(channels))));
+ const url::Origin& source_origin,
+ std::unique_ptr<WebMessagePortChannelArray> channels) {
+ if (WebRuntimeFeatures::isServiceWorkerExtendableMessageEventEnabled()) {
+ thread_safe_sender->Send(new ServiceWorkerHostMsg_PostMessageToWorker(
+ handle_id, provider_id, message, source_origin,
+ WebMessagePortChannelImpl::ExtractMessagePortIDs(std::move(channels))));
+ } else {
+ thread_safe_sender->Send(
+ new ServiceWorkerHostMsg_DeprecatedPostMessageToWorker(
+ handle_id, message,
+ WebMessagePortChannelImpl::ExtractMessagePortIDs(
+ std::move(channels))));
+ }
}
} // namespace
WebServiceWorkerImpl::WebServiceWorkerImpl(
- scoped_ptr<ServiceWorkerHandleReference> handle_ref,
+ std::unique_ptr<ServiceWorkerHandleReference> handle_ref,
ThreadSafeSender* thread_safe_sender)
: handle_ref_(std::move(handle_ref)),
state_(handle_ref_->state()),
@@ -90,8 +106,13 @@ blink::WebServiceWorkerState WebServiceWorkerImpl::state() const {
return state_;
}
-void WebServiceWorkerImpl::postMessage(const WebString& message,
- WebMessagePortChannelArray* channels) {
+void WebServiceWorkerImpl::postMessage(
+ blink::WebServiceWorkerProvider* provider,
+ const WebString& message,
+ const WebSecurityOrigin& source_origin,
+ WebMessagePortChannelArray* channels) {
+ WebServiceWorkerProviderImpl* provider_impl =
+ static_cast<WebServiceWorkerProviderImpl*>(provider);
ServiceWorkerDispatcher* dispatcher =
ServiceWorkerDispatcher::GetThreadSpecificInstance();
DCHECK(dispatcher);
@@ -101,12 +122,15 @@ void WebServiceWorkerImpl::postMessage(const WebString& message,
// (with thread hopping), so we need to do the same thread hopping here not
// to overtake those messages.
dispatcher->main_thread_task_runner()->PostTask(
- FROM_HERE, base::Bind(&SendPostMessageToWorkerOnMainThread,
- thread_safe_sender_, handle_ref_->handle_id(),
- // We cast WebString to string16 before crossing
- // threads for thread-safety.
- static_cast<base::string16>(message),
- base::Passed(make_scoped_ptr(channels))));
+ FROM_HERE,
+ base::Bind(&SendPostMessageToWorkerOnMainThread,
+ base::RetainedRef(thread_safe_sender_),
+ handle_ref_->handle_id(), provider_impl->provider_id(),
+ // We cast WebString to string16 before crossing
+ // threads for thread-safety.
+ static_cast<base::string16>(message),
+ url::Origin(source_origin),
+ base::Passed(base::WrapUnique(channels))));
}
void WebServiceWorkerImpl::terminate() {
@@ -115,12 +139,12 @@ void WebServiceWorkerImpl::terminate() {
}
// static
-blink::WebPassOwnPtr<blink::WebServiceWorker::Handle>
+std::unique_ptr<blink::WebServiceWorker::Handle>
WebServiceWorkerImpl::CreateHandle(
const scoped_refptr<WebServiceWorkerImpl>& worker) {
if (!worker)
return nullptr;
- return blink::adoptWebPtr(new HandleImpl(worker));
+ return base::WrapUnique(new HandleImpl(worker));
}
WebServiceWorkerImpl::~WebServiceWorkerImpl() {
diff --git a/chromium/content/child/service_worker/web_service_worker_impl.h b/chromium/content/child/service_worker/web_service_worker_impl.h
index 02347f234e8..fcc49183c8f 100644
--- a/chromium/content/child/service_worker/web_service_worker_impl.h
+++ b/chromium/content/child/service_worker/web_service_worker_impl.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_CHILD_SERVICE_WORKER_WEB_SERVICE_WORKER_IMPL_H_
#define CONTENT_CHILD_SERVICE_WORKER_WEB_SERVICE_WORKER_IMPL_H_
+#include <memory>
#include <vector>
#include "base/compiler_specific.h"
@@ -13,7 +14,6 @@
#include "base/strings/string16.h"
#include "content/common/content_export.h"
#include "third_party/WebKit/public/platform/WebMessagePortChannel.h"
-#include "third_party/WebKit/public/platform/WebPassOwnPtr.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorker.h"
#include "third_party/WebKit/public/web/WebFrame.h"
@@ -38,7 +38,7 @@ class CONTENT_EXPORT WebServiceWorkerImpl
: NON_EXPORTED_BASE(public blink::WebServiceWorker),
public base::RefCounted<WebServiceWorkerImpl> {
public:
- WebServiceWorkerImpl(scoped_ptr<ServiceWorkerHandleReference> handle_ref,
+ WebServiceWorkerImpl(std::unique_ptr<ServiceWorkerHandleReference> handle_ref,
ThreadSafeSender* thread_safe_sender);
void OnStateChanged(blink::WebServiceWorkerState new_state);
@@ -48,20 +48,22 @@ class CONTENT_EXPORT WebServiceWorkerImpl
blink::WebServiceWorkerProxy* proxy() override;
blink::WebURL url() const override;
blink::WebServiceWorkerState state() const override;
- void postMessage(const blink::WebString& message,
+ void postMessage(blink::WebServiceWorkerProvider* provider,
+ const blink::WebString& message,
+ const blink::WebSecurityOrigin& source_origin,
blink::WebMessagePortChannelArray* channels) override;
void terminate() override;
// Creates WebServiceWorker::Handle object that owns a reference to the given
// WebServiceWorkerImpl object.
- static blink::WebPassOwnPtr<blink::WebServiceWorker::Handle> CreateHandle(
+ static std::unique_ptr<blink::WebServiceWorker::Handle> CreateHandle(
const scoped_refptr<WebServiceWorkerImpl>& worker);
private:
friend class base::RefCounted<WebServiceWorkerImpl>;
~WebServiceWorkerImpl() override;
- scoped_ptr<ServiceWorkerHandleReference> handle_ref_;
+ std::unique_ptr<ServiceWorkerHandleReference> handle_ref_;
blink::WebServiceWorkerState state_;
scoped_refptr<ThreadSafeSender> thread_safe_sender_;
blink::WebServiceWorkerProxy* proxy_;
diff --git a/chromium/content/child/service_worker/web_service_worker_registration_impl.cc b/chromium/content/child/service_worker/web_service_worker_registration_impl.cc
index a753de42848..8b40190a8ad 100644
--- a/chromium/content/child/service_worker/web_service_worker_registration_impl.cc
+++ b/chromium/content/child/service_worker/web_service_worker_registration_impl.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "content/child/service_worker/service_worker_dispatcher.h"
#include "content/child/service_worker/service_worker_registration_handle_reference.h"
#include "content/child/service_worker/web_service_worker_impl.h"
@@ -42,10 +43,13 @@ WebServiceWorkerRegistrationImpl::QueuedTask::QueuedTask(
const scoped_refptr<WebServiceWorkerImpl>& worker)
: type(type), worker(worker) {}
+WebServiceWorkerRegistrationImpl::QueuedTask::QueuedTask(
+ const QueuedTask& other) = default;
+
WebServiceWorkerRegistrationImpl::QueuedTask::~QueuedTask() {}
WebServiceWorkerRegistrationImpl::WebServiceWorkerRegistrationImpl(
- scoped_ptr<ServiceWorkerRegistrationHandleReference> handle_ref)
+ std::unique_ptr<ServiceWorkerRegistrationHandleReference> handle_ref)
: handle_ref_(std::move(handle_ref)), proxy_(nullptr) {
DCHECK(handle_ref_);
DCHECK_NE(kInvalidServiceWorkerRegistrationHandleId,
@@ -146,12 +150,12 @@ int64_t WebServiceWorkerRegistrationImpl::registration_id() const {
}
// static
-blink::WebPassOwnPtr<blink::WebServiceWorkerRegistration::Handle>
+std::unique_ptr<blink::WebServiceWorkerRegistration::Handle>
WebServiceWorkerRegistrationImpl::CreateHandle(
const scoped_refptr<WebServiceWorkerRegistrationImpl>& registration) {
if (!registration)
return nullptr;
- return blink::adoptWebPtr(new HandleImpl(registration));
+ return base::WrapUnique(new HandleImpl(registration));
}
blink::WebServiceWorkerRegistration::Handle*
diff --git a/chromium/content/child/service_worker/web_service_worker_registration_impl.h b/chromium/content/child/service_worker/web_service_worker_registration_impl.h
index 9a17908d801..499047489f4 100644
--- a/chromium/content/child/service_worker/web_service_worker_registration_impl.h
+++ b/chromium/content/child/service_worker/web_service_worker_registration_impl.h
@@ -7,6 +7,7 @@
#include <stdint.h>
+#include <memory>
#include <vector>
#include "base/compiler_specific.h"
@@ -38,7 +39,7 @@ class CONTENT_EXPORT WebServiceWorkerRegistrationImpl
public base::RefCounted<WebServiceWorkerRegistrationImpl> {
public:
explicit WebServiceWorkerRegistrationImpl(
- scoped_ptr<ServiceWorkerRegistrationHandleReference> handle_ref);
+ std::unique_ptr<ServiceWorkerRegistrationHandleReference> handle_ref);
void SetInstalling(const scoped_refptr<WebServiceWorkerImpl>& service_worker);
void SetWaiting(const scoped_refptr<WebServiceWorkerImpl>& service_worker);
@@ -62,7 +63,7 @@ class CONTENT_EXPORT WebServiceWorkerRegistrationImpl
// Creates WebServiceWorkerRegistrationHandle object that owns a reference to
// the given WebServiceWorkerRegistrationImpl object.
- static blink::WebPassOwnPtr<WebServiceWorkerRegistrationHandle> CreateHandle(
+ static std::unique_ptr<WebServiceWorkerRegistrationHandle> CreateHandle(
const scoped_refptr<WebServiceWorkerRegistrationImpl>& registration);
// Same with CreateHandle(), but returns a raw pointer to the handle w/ its
@@ -86,6 +87,7 @@ class CONTENT_EXPORT WebServiceWorkerRegistrationImpl
struct QueuedTask {
QueuedTask(QueuedTaskType type,
const scoped_refptr<WebServiceWorkerImpl>& worker);
+ QueuedTask(const QueuedTask& other);
~QueuedTask();
QueuedTaskType type;
scoped_refptr<WebServiceWorkerImpl> worker;
@@ -93,7 +95,7 @@ class CONTENT_EXPORT WebServiceWorkerRegistrationImpl
void RunQueuedTasks();
- scoped_ptr<ServiceWorkerRegistrationHandleReference> handle_ref_;
+ std::unique_ptr<ServiceWorkerRegistrationHandleReference> handle_ref_;
blink::WebServiceWorkerRegistrationProxy* proxy_;
std::vector<QueuedTask> queued_tasks_;
diff --git a/chromium/content/child/shared_memory_data_consumer_handle.cc b/chromium/content/child/shared_memory_data_consumer_handle.cc
index b7e4d11cbe5..6766fe867ae 100644
--- a/chromium/content/child/shared_memory_data_consumer_handle.cc
+++ b/chromium/content/child/shared_memory_data_consumer_handle.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
@@ -24,7 +25,7 @@ class DelegateThreadSafeReceivedData final
: public RequestPeer::ThreadSafeReceivedData {
public:
explicit DelegateThreadSafeReceivedData(
- scoped_ptr<RequestPeer::ReceivedData> data)
+ std::unique_ptr<RequestPeer::ReceivedData> data)
: data_(std::move(data)),
task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
~DelegateThreadSafeReceivedData() override {
@@ -39,7 +40,7 @@ class DelegateThreadSafeReceivedData final
int encoded_length() const override { return data_->encoded_length(); }
private:
- scoped_ptr<RequestPeer::ReceivedData> data_;
+ std::unique_ptr<RequestPeer::ReceivedData> data_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
DISALLOW_COPY_AND_ASSIGN(DelegateThreadSafeReceivedData);
@@ -93,7 +94,7 @@ class SharedMemoryDataConsumerHandle::Context final
lock_.AssertAcquired();
return queue_.front();
}
- void Push(scoped_ptr<RequestPeer::ThreadSafeReceivedData> data) {
+ void Push(std::unique_ptr<RequestPeer::ThreadSafeReceivedData> data) {
lock_.AssertAcquired();
queue_.push_back(data.release());
}
@@ -255,7 +256,7 @@ class SharedMemoryDataConsumerHandle::Context final
// |result_| stores the ultimate state of this handle if it has. Otherwise,
// |Ok| is set.
Result result_;
- // TODO(yhirano): Use std::deque<scoped_ptr<ThreadSafeReceivedData>>
+ // TODO(yhirano): Use std::deque<std::unique_ptr<ThreadSafeReceivedData>>
// once it is allowed.
std::deque<RequestPeer::ThreadSafeReceivedData*> queue_;
size_t first_offset_;
@@ -287,7 +288,7 @@ SharedMemoryDataConsumerHandle::Writer::~Writer() {
}
void SharedMemoryDataConsumerHandle::Writer::AddData(
- scoped_ptr<RequestPeer::ReceivedData> data) {
+ std::unique_ptr<RequestPeer::ReceivedData> data) {
if (!data->length()) {
// We omit empty data.
return;
@@ -302,12 +303,12 @@ void SharedMemoryDataConsumerHandle::Writer::AddData(
}
needs_notification = context_->IsEmpty();
- scoped_ptr<RequestPeer::ThreadSafeReceivedData> data_to_pass;
+ std::unique_ptr<RequestPeer::ThreadSafeReceivedData> data_to_pass;
if (mode_ == kApplyBackpressure) {
data_to_pass =
- make_scoped_ptr(new DelegateThreadSafeReceivedData(std::move(data)));
+ base::WrapUnique(new DelegateThreadSafeReceivedData(std::move(data)));
} else {
- data_to_pass = make_scoped_ptr(new FixedReceivedData(data.get()));
+ data_to_pass = base::WrapUnique(new FixedReceivedData(data.get()));
}
context_->Push(std::move(data_to_pass));
}
@@ -449,14 +450,13 @@ Result SharedMemoryDataConsumerHandle::ReaderImpl::endRead(size_t read_size) {
SharedMemoryDataConsumerHandle::SharedMemoryDataConsumerHandle(
BackpressureMode mode,
- scoped_ptr<Writer>* writer)
- : SharedMemoryDataConsumerHandle(mode, base::Closure(), writer) {
-}
+ std::unique_ptr<Writer>* writer)
+ : SharedMemoryDataConsumerHandle(mode, base::Closure(), writer) {}
SharedMemoryDataConsumerHandle::SharedMemoryDataConsumerHandle(
BackpressureMode mode,
const base::Closure& on_reader_detached,
- scoped_ptr<Writer>* writer)
+ std::unique_ptr<Writer>* writer)
: context_(new Context(on_reader_detached)) {
writer->reset(new Writer(context_, mode));
}
@@ -467,9 +467,9 @@ SharedMemoryDataConsumerHandle::~SharedMemoryDataConsumerHandle() {
context_->ClearIfNecessary();
}
-scoped_ptr<blink::WebDataConsumerHandle::Reader>
+std::unique_ptr<blink::WebDataConsumerHandle::Reader>
SharedMemoryDataConsumerHandle::ObtainReader(Client* client) {
- return make_scoped_ptr(obtainReaderInternal(client));
+ return base::WrapUnique(obtainReaderInternal(client));
}
SharedMemoryDataConsumerHandle::ReaderImpl*
diff --git a/chromium/content/child/shared_memory_data_consumer_handle.h b/chromium/content/child/shared_memory_data_consumer_handle.h
index aa33482e563..4da9fd1a00a 100644
--- a/chromium/content/child/shared_memory_data_consumer_handle.h
+++ b/chromium/content/child/shared_memory_data_consumer_handle.h
@@ -7,10 +7,11 @@
#include <stddef.h>
+#include <memory>
+
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
#include "content/public/child/request_peer.h"
#include "third_party/WebKit/public/platform/WebDataConsumerHandle.h"
@@ -35,7 +36,7 @@ class CONTENT_EXPORT SharedMemoryDataConsumerHandle final
~Writer();
// Note: Writer assumes |AddData| is not called in a client's didGetReadable
// callback. There isn't such assumption for |Close| and |Fail|.
- void AddData(scoped_ptr<RequestPeer::ReceivedData> data);
+ void AddData(std::unique_ptr<RequestPeer::ReceivedData> data);
void Close();
// TODO(yhirano): Consider providing error code.
void Fail();
@@ -69,7 +70,7 @@ class CONTENT_EXPORT SharedMemoryDataConsumerHandle final
// Creates a handle and a writer associated with the handle. The created
// writer should be used on the calling thread.
SharedMemoryDataConsumerHandle(BackpressureMode mode,
- scoped_ptr<Writer>* writer);
+ std::unique_ptr<Writer>* writer);
// |on_reader_detached| will be called aynchronously on the calling thread
// when the reader (including the handle) is detached (i.e. both the handle
// and the reader are destructed). The callback will be reset in the internal
@@ -77,10 +78,10 @@ class CONTENT_EXPORT SharedMemoryDataConsumerHandle final
// and the callback will never be called.
SharedMemoryDataConsumerHandle(BackpressureMode mode,
const base::Closure& on_reader_detached,
- scoped_ptr<Writer>* writer);
+ std::unique_ptr<Writer>* writer);
~SharedMemoryDataConsumerHandle() override;
- scoped_ptr<Reader> ObtainReader(Client* client);
+ std::unique_ptr<Reader> ObtainReader(Client* client);
private:
ReaderImpl* obtainReaderInternal(Client* client) override;
diff --git a/chromium/content/child/shared_memory_data_consumer_handle_unittest.cc b/chromium/content/child/shared_memory_data_consumer_handle_unittest.cc
index 5694d588bff..1fd31078ac8 100644
--- a/chromium/content/child/shared_memory_data_consumer_handle_unittest.cc
+++ b/chromium/content/child/shared_memory_data_consumer_handle_unittest.cc
@@ -6,6 +6,7 @@
#include <stddef.h>
#include <string.h>
+
#include <string>
#include <utility>
#include <vector>
@@ -14,6 +15,7 @@
#include "base/callback.h"
#include "base/location.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/task_runner.h"
@@ -125,7 +127,7 @@ class ThreadedSharedMemoryDataConsumerHandleTest : public ::testing::Test {
class ReadDataOperation final {
public:
typedef WebDataConsumerHandle::Result Result;
- ReadDataOperation(scoped_ptr<SharedMemoryDataConsumerHandle> handle,
+ ReadDataOperation(std::unique_ptr<SharedMemoryDataConsumerHandle> handle,
base::MessageLoop* main_message_loop,
const base::Closure& on_done)
: handle_(std::move(handle)),
@@ -167,9 +169,9 @@ class ThreadedSharedMemoryDataConsumerHandleTest : public ::testing::Test {
}
private:
- scoped_ptr<SharedMemoryDataConsumerHandle> handle_;
- scoped_ptr<WebDataConsumerHandle::Reader> reader_;
- scoped_ptr<WebDataConsumerHandle::Client> client_;
+ std::unique_ptr<SharedMemoryDataConsumerHandle> handle_;
+ std::unique_ptr<WebDataConsumerHandle::Reader> reader_;
+ std::unique_ptr<WebDataConsumerHandle::Client> client_;
base::MessageLoop* main_message_loop_;
base::Closure on_done_;
std::string result_;
@@ -181,8 +183,8 @@ class ThreadedSharedMemoryDataConsumerHandleTest : public ::testing::Test {
}
StrictMock<MockClient> client_;
- scoped_ptr<SharedMemoryDataConsumerHandle> handle_;
- scoped_ptr<Writer> writer_;
+ std::unique_ptr<SharedMemoryDataConsumerHandle> handle_;
+ std::unique_ptr<Writer> writer_;
base::MessageLoop loop_;
};
@@ -192,13 +194,13 @@ class SharedMemoryDataConsumerHandleTest
void SetUp() override {
handle_.reset(new SharedMemoryDataConsumerHandle(GetParam(), &writer_));
}
- scoped_ptr<FixedReceivedData> NewFixedData(const char* s) {
- return make_scoped_ptr(new FixedReceivedData(s, strlen(s), strlen(s)));
+ std::unique_ptr<FixedReceivedData> NewFixedData(const char* s) {
+ return base::WrapUnique(new FixedReceivedData(s, strlen(s), strlen(s)));
}
StrictMock<MockClient> client_;
- scoped_ptr<SharedMemoryDataConsumerHandle> handle_;
- scoped_ptr<Writer> writer_;
+ std::unique_ptr<SharedMemoryDataConsumerHandle> handle_;
+ std::unique_ptr<Writer> writer_;
base::MessageLoop loop_;
};
@@ -896,18 +898,18 @@ TEST(SharedMemoryDataConsumerHandleBackpressureTest, Read) {
Result result;
size_t size;
- scoped_ptr<Writer> writer;
- auto handle = make_scoped_ptr(
+ std::unique_ptr<Writer> writer;
+ auto handle = base::WrapUnique(
new SharedMemoryDataConsumerHandle(kApplyBackpressure, &writer));
scoped_refptr<Logger> logger(new Logger);
writer->AddData(
- make_scoped_ptr(new LoggingFixedReceivedData("data1", "Once ", logger)));
+ base::WrapUnique(new LoggingFixedReceivedData("data1", "Once ", logger)));
writer->AddData(
- make_scoped_ptr(new LoggingFixedReceivedData("data2", "upon ", logger)));
+ base::WrapUnique(new LoggingFixedReceivedData("data2", "upon ", logger)));
writer->AddData(
- make_scoped_ptr(new LoggingFixedReceivedData("data3", "a ", logger)));
+ base::WrapUnique(new LoggingFixedReceivedData("data3", "a ", logger)));
writer->AddData(
- make_scoped_ptr(new LoggingFixedReceivedData("data4", "time ", logger)));
+ base::WrapUnique(new LoggingFixedReceivedData("data4", "time ", logger)));
auto reader = handle->ObtainReader(nullptr);
logger->Add("1");
@@ -941,16 +943,16 @@ TEST(SharedMemoryDataConsumerHandleBackpressureTest, CloseAndReset) {
Result result;
size_t size;
- scoped_ptr<Writer> writer;
- auto handle = make_scoped_ptr(
+ std::unique_ptr<Writer> writer;
+ auto handle = base::WrapUnique(
new SharedMemoryDataConsumerHandle(kApplyBackpressure, &writer));
scoped_refptr<Logger> logger(new Logger);
writer->AddData(
- make_scoped_ptr(new LoggingFixedReceivedData("data1", "Once ", logger)));
+ base::WrapUnique(new LoggingFixedReceivedData("data1", "Once ", logger)));
writer->AddData(
- make_scoped_ptr(new LoggingFixedReceivedData("data2", "upon ", logger)));
+ base::WrapUnique(new LoggingFixedReceivedData("data2", "upon ", logger)));
writer->AddData(
- make_scoped_ptr(new LoggingFixedReceivedData("data3", "a ", logger)));
+ base::WrapUnique(new LoggingFixedReceivedData("data3", "a ", logger)));
auto reader = handle->ObtainReader(nullptr);
logger->Add("1");
@@ -977,17 +979,17 @@ TEST(SharedMemoryDataConsumerHandleBackpressureTest, CloseAndReset) {
TEST(SharedMemoryDataConsumerHandleWithoutBackpressureTest, AddData) {
base::MessageLoop loop;
- scoped_ptr<Writer> writer;
- auto handle = make_scoped_ptr(
+ std::unique_ptr<Writer> writer;
+ auto handle = base::WrapUnique(
new SharedMemoryDataConsumerHandle(kDoNotApplyBackpressure, &writer));
scoped_refptr<Logger> logger(new Logger);
logger->Add("1");
writer->AddData(
- make_scoped_ptr(new LoggingFixedReceivedData("data1", "Once ", logger)));
+ base::WrapUnique(new LoggingFixedReceivedData("data1", "Once ", logger)));
logger->Add("2");
writer->AddData(
- make_scoped_ptr(new LoggingFixedReceivedData("data2", "upon ", logger)));
+ base::WrapUnique(new LoggingFixedReceivedData("data2", "upon ", logger)));
logger->Add("3");
EXPECT_EQ(
@@ -1001,7 +1003,7 @@ TEST(SharedMemoryDataConsumerHandleWithoutBackpressureTest, AddData) {
TEST_F(ThreadedSharedMemoryDataConsumerHandleTest, Read) {
base::RunLoop run_loop;
- auto operation = make_scoped_ptr(new ReadDataOperation(
+ auto operation = base::WrapUnique(new ReadDataOperation(
std::move(handle_), &loop_, run_loop.QuitClosure()));
scoped_refptr<Logger> logger(new Logger);
@@ -1014,15 +1016,15 @@ TEST_F(ThreadedSharedMemoryDataConsumerHandleTest, Read) {
logger->Add("1");
writer_->AddData(
- make_scoped_ptr(new LoggingFixedReceivedData("data1", "Once ", logger)));
+ base::WrapUnique(new LoggingFixedReceivedData("data1", "Once ", logger)));
writer_->AddData(
- make_scoped_ptr(new LoggingFixedReceivedData("data2", "upon ", logger)));
- writer_->AddData(make_scoped_ptr(
+ base::WrapUnique(new LoggingFixedReceivedData("data2", "upon ", logger)));
+ writer_->AddData(base::WrapUnique(
new LoggingFixedReceivedData("data3", "a time ", logger)));
+ writer_->AddData(base::WrapUnique(
+ new LoggingFixedReceivedData("data4", "there ", logger)));
writer_->AddData(
- make_scoped_ptr(new LoggingFixedReceivedData("data4", "there ", logger)));
- writer_->AddData(
- make_scoped_ptr(new LoggingFixedReceivedData("data5", "was ", logger)));
+ base::WrapUnique(new LoggingFixedReceivedData("data5", "was ", logger)));
writer_->Close();
logger->Add("2");
diff --git a/chromium/content/child/shared_memory_received_data_factory.cc b/chromium/content/child/shared_memory_received_data_factory.cc
index 49e805ef7d6..4bfbb3e495b 100644
--- a/chromium/content/child/shared_memory_received_data_factory.cc
+++ b/chromium/content/child/shared_memory_received_data_factory.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "content/common/resource_messages.h"
#include "ipc/ipc_sender.h"
@@ -61,15 +62,15 @@ SharedMemoryReceivedDataFactory::~SharedMemoryReceivedDataFactory() {
SendAck(released_tickets_.size());
}
-scoped_ptr<RequestPeer::ReceivedData> SharedMemoryReceivedDataFactory::Create(
- int offset,
- int length,
- int encoded_length) {
+std::unique_ptr<RequestPeer::ReceivedData>
+SharedMemoryReceivedDataFactory::Create(int offset,
+ int length,
+ int encoded_length) {
const char* start = static_cast<char*>(memory_->memory());
const char* payload = start + offset;
TicketId id = id_++;
- return make_scoped_ptr(
+ return base::WrapUnique(
new SharedMemoryReceivedData(payload, length, encoded_length, this, id));
}
diff --git a/chromium/content/child/shared_memory_received_data_factory.h b/chromium/content/child/shared_memory_received_data_factory.h
index e27f7cacb76..c60514eb939 100644
--- a/chromium/content/child/shared_memory_received_data_factory.h
+++ b/chromium/content/child/shared_memory_received_data_factory.h
@@ -8,12 +8,12 @@
#include <stddef.h>
#include <stdint.h>
+#include <memory>
#include <vector>
#include "base/macros.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory.h"
#include "content/common/content_export.h"
#include "content/public/child/request_peer.h"
@@ -31,9 +31,9 @@ class CONTENT_EXPORT SharedMemoryReceivedDataFactory final
int request_id,
linked_ptr<base::SharedMemory> memory);
- scoped_ptr<RequestPeer::ReceivedData> Create(int offset,
- int length,
- int encoded_length);
+ std::unique_ptr<RequestPeer::ReceivedData> Create(int offset,
+ int length,
+ int encoded_length);
// Stops this factory. After calling this function, releasing issued data
// won't send ack signal to the browser process.
diff --git a/chromium/content/child/shared_memory_received_data_factory_unittest.cc b/chromium/content/child/shared_memory_received_data_factory_unittest.cc
index 77ab7c69466..05b6bed7ee8 100644
--- a/chromium/content/child/shared_memory_received_data_factory_unittest.cc
+++ b/chromium/content/child/shared_memory_received_data_factory_unittest.cc
@@ -59,7 +59,7 @@ class SharedMemoryReceivedDataFactoryTest : public ::testing::Test {
}
static const size_t memory_size = 4 * 1024;
- scoped_ptr<MockSender> sender_;
+ std::unique_ptr<MockSender> sender_;
int request_id_;
linked_ptr<base::SharedMemory> memory_;
scoped_refptr<SharedMemoryReceivedDataFactory> factory_;
@@ -72,7 +72,7 @@ TEST_F(SharedMemoryReceivedDataFactoryTest, Create) {
EXPECT_CALL(*sender_, SendAck(request_id_));
EXPECT_CALL(checkpoint, Call(1));
- scoped_ptr<ReceivedData> data = factory_->Create(12, 34, 56);
+ std::unique_ptr<ReceivedData> data = factory_->Create(12, 34, 56);
const char* memory_start = static_cast<const char*>(memory_->memory());
ASSERT_TRUE(data);
@@ -96,9 +96,9 @@ TEST_F(SharedMemoryReceivedDataFactoryTest, CreateMultiple) {
EXPECT_CALL(*sender_, SendAck(request_id_));
EXPECT_CALL(checkpoint, Call(3));
- scoped_ptr<ReceivedData> data1 = factory_->Create(0, 1, 1);
- scoped_ptr<ReceivedData> data2 = factory_->Create(1, 1, 1);
- scoped_ptr<ReceivedData> data3 = factory_->Create(2, 1, 1);
+ std::unique_ptr<ReceivedData> data1 = factory_->Create(0, 1, 1);
+ std::unique_ptr<ReceivedData> data2 = factory_->Create(1, 1, 1);
+ std::unique_ptr<ReceivedData> data3 = factory_->Create(2, 1, 1);
EXPECT_TRUE(data1);
EXPECT_TRUE(data2);
@@ -124,9 +124,9 @@ TEST_F(SharedMemoryReceivedDataFactoryTest, ReclaimOutOfOrder) {
EXPECT_CALL(*sender_, SendAck(request_id_));
EXPECT_CALL(checkpoint, Call(3));
- scoped_ptr<ReceivedData> data1 = factory_->Create(0, 1, 1);
- scoped_ptr<ReceivedData> data2 = factory_->Create(1, 1, 1);
- scoped_ptr<ReceivedData> data3 = factory_->Create(2, 1, 1);
+ std::unique_ptr<ReceivedData> data1 = factory_->Create(0, 1, 1);
+ std::unique_ptr<ReceivedData> data2 = factory_->Create(1, 1, 1);
+ std::unique_ptr<ReceivedData> data3 = factory_->Create(2, 1, 1);
EXPECT_TRUE(data1);
EXPECT_TRUE(data2);
@@ -156,12 +156,12 @@ TEST_F(SharedMemoryReceivedDataFactoryTest, ReclaimOutOfOrderPartially) {
EXPECT_CALL(*sender_, SendAck(request_id_));
EXPECT_CALL(checkpoint, Call(4));
- scoped_ptr<ReceivedData> data1 = factory_->Create(0, 1, 1);
- scoped_ptr<ReceivedData> data2 = factory_->Create(1, 1, 1);
- scoped_ptr<ReceivedData> data3 = factory_->Create(2, 1, 1);
- scoped_ptr<ReceivedData> data4 = factory_->Create(3, 1, 1);
- scoped_ptr<ReceivedData> data5 = factory_->Create(4, 1, 1);
- scoped_ptr<ReceivedData> data6 = factory_->Create(5, 1, 1);
+ std::unique_ptr<ReceivedData> data1 = factory_->Create(0, 1, 1);
+ std::unique_ptr<ReceivedData> data2 = factory_->Create(1, 1, 1);
+ std::unique_ptr<ReceivedData> data3 = factory_->Create(2, 1, 1);
+ std::unique_ptr<ReceivedData> data4 = factory_->Create(3, 1, 1);
+ std::unique_ptr<ReceivedData> data5 = factory_->Create(4, 1, 1);
+ std::unique_ptr<ReceivedData> data6 = factory_->Create(5, 1, 1);
EXPECT_TRUE(data1);
EXPECT_TRUE(data2);
@@ -194,12 +194,12 @@ TEST_F(SharedMemoryReceivedDataFactoryTest, Stop) {
EXPECT_CALL(checkpoint, Call(2));
EXPECT_CALL(checkpoint, Call(3));
- scoped_ptr<ReceivedData> data1 = factory_->Create(0, 1, 1);
- scoped_ptr<ReceivedData> data2 = factory_->Create(1, 1, 1);
- scoped_ptr<ReceivedData> data3 = factory_->Create(2, 1, 1);
- scoped_ptr<ReceivedData> data4 = factory_->Create(3, 1, 1);
- scoped_ptr<ReceivedData> data5 = factory_->Create(4, 1, 1);
- scoped_ptr<ReceivedData> data6 = factory_->Create(5, 1, 1);
+ std::unique_ptr<ReceivedData> data1 = factory_->Create(0, 1, 1);
+ std::unique_ptr<ReceivedData> data2 = factory_->Create(1, 1, 1);
+ std::unique_ptr<ReceivedData> data3 = factory_->Create(2, 1, 1);
+ std::unique_ptr<ReceivedData> data4 = factory_->Create(3, 1, 1);
+ std::unique_ptr<ReceivedData> data5 = factory_->Create(4, 1, 1);
+ std::unique_ptr<ReceivedData> data6 = factory_->Create(5, 1, 1);
EXPECT_TRUE(data1);
EXPECT_TRUE(data2);
diff --git a/chromium/content/child/shared_worker_devtools_agent.cc b/chromium/content/child/shared_worker_devtools_agent.cc
index 5ec392128fc..b0698f37166 100644
--- a/chromium/content/child/shared_worker_devtools_agent.cc
+++ b/chromium/content/child/shared_worker_devtools_agent.cc
@@ -9,7 +9,6 @@
#include "content/child/child_thread_impl.h"
#include "content/common/devtools_messages.h"
#include "ipc/ipc_channel.h"
-#include "third_party/WebKit/public/platform/WebCString.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/web/WebSharedWorker.h"
diff --git a/chromium/content/child/simple_webmimeregistry_impl.cc b/chromium/content/child/simple_webmimeregistry_impl.cc
index d65a0ccfe4e..994b17ed2bf 100644
--- a/chromium/content/child/simple_webmimeregistry_impl.cc
+++ b/chromium/content/child/simple_webmimeregistry_impl.cc
@@ -9,7 +9,9 @@
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "components/mime_util/mime_util.h"
+#include "media/base/mime_util.h"
#include "net/base/mime_util.h"
+#include "third_party/WebKit/public/platform/FilePathConversion.h"
#include "third_party/WebKit/public/platform/WebString.h"
using blink::WebString;
@@ -62,8 +64,7 @@ WebMimeRegistry::SupportsType
// see TestShellWebMimeRegistryImpl.
WebMimeRegistry::SupportsType SimpleWebMimeRegistryImpl::supportsMediaMIMEType(
const WebString& mime_type,
- const WebString& codecs,
- const WebString& key_system) {
+ const WebString& codecs) {
// Media features are only supported at the content/renderer/ layer.
return IsNotSupported;
}
@@ -72,7 +73,8 @@ bool SimpleWebMimeRegistryImpl::supportsMediaSourceMIMEType(
const WebString& mime_type,
const WebString& codecs) {
// Media features are only supported at the content/renderer layer.
- return false;
+ const std::string mime_type_ascii = ToASCIIOrEmpty(mime_type);
+ return media::IsSupportedMediaMimeType(mime_type_ascii);
}
WebMimeRegistry::SupportsType
@@ -87,7 +89,7 @@ WebString SimpleWebMimeRegistryImpl::mimeTypeForExtension(
const WebString& file_extension) {
std::string mime_type;
net::GetMimeTypeFromExtension(
- base::FilePath::FromUTF16Unsafe(file_extension).value(), &mime_type);
+ blink::WebStringToFilePath(file_extension).value(), &mime_type);
return WebString::fromUTF8(mime_type);
}
@@ -95,7 +97,7 @@ WebString SimpleWebMimeRegistryImpl::wellKnownMimeTypeForExtension(
const WebString& file_extension) {
std::string mime_type;
net::GetWellKnownMimeTypeFromExtension(
- base::FilePath::FromUTF16Unsafe(file_extension).value(), &mime_type);
+ blink::WebStringToFilePath(file_extension).value(), &mime_type);
return WebString::fromUTF8(mime_type);
}
diff --git a/chromium/content/child/simple_webmimeregistry_impl.h b/chromium/content/child/simple_webmimeregistry_impl.h
index 17ca37aab24..30a1fb7564e 100644
--- a/chromium/content/child/simple_webmimeregistry_impl.h
+++ b/chromium/content/child/simple_webmimeregistry_impl.h
@@ -34,7 +34,6 @@ class CONTENT_EXPORT SimpleWebMimeRegistryImpl :
const blink::WebString&) override;
blink::WebMimeRegistry::SupportsType supportsMediaMIMEType(
const blink::WebString&,
- const blink::WebString&,
const blink::WebString&) override;
bool supportsMediaSourceMIMEType(const blink::WebString&,
const blink::WebString&) override;
diff --git a/chromium/content/child/site_isolation_stats_gatherer.cc b/chromium/content/child/site_isolation_stats_gatherer.cc
index f38ea385f76..b05101d01b7 100644
--- a/chromium/content/child/site_isolation_stats_gatherer.cc
+++ b/chromium/content/child/site_isolation_stats_gatherer.cc
@@ -53,7 +53,7 @@ void IncrementHistogramEnum(const std::string& name,
void HistogramCountBlockedResponse(
const std::string& bucket_prefix,
- const scoped_ptr<SiteIsolationResponseMetaData>& resp_data,
+ const std::unique_ptr<SiteIsolationResponseMetaData>& resp_data,
bool nosniff_block) {
std::string block_label(nosniff_block ? ".NoSniffBlocked" : ".Blocked");
IncrementHistogramCount(bucket_prefix + block_label);
@@ -96,7 +96,7 @@ void SiteIsolationStatsGatherer::SetEnabled(bool enabled) {
g_stats_gathering_enabled = enabled;
}
-scoped_ptr<SiteIsolationResponseMetaData>
+std::unique_ptr<SiteIsolationResponseMetaData>
SiteIsolationStatsGatherer::OnReceivedResponse(
const GURL& frame_origin,
const GURL& response_url,
@@ -150,7 +150,7 @@ SiteIsolationStatsGatherer::OnReceivedResponse(
std::string no_sniff;
info.headers->EnumerateHeader(NULL, "x-content-type-options", &no_sniff);
- scoped_ptr<SiteIsolationResponseMetaData> resp_data(
+ std::unique_ptr<SiteIsolationResponseMetaData> resp_data(
new SiteIsolationResponseMetaData);
resp_data->frame_origin = frame_origin.spec();
resp_data->response_url = response_url;
@@ -163,7 +163,7 @@ SiteIsolationStatsGatherer::OnReceivedResponse(
}
bool SiteIsolationStatsGatherer::OnReceivedFirstChunk(
- const scoped_ptr<SiteIsolationResponseMetaData>& resp_data,
+ const std::unique_ptr<SiteIsolationResponseMetaData>& resp_data,
const char* raw_data,
int raw_length) {
if (!g_stats_gathering_enabled)
diff --git a/chromium/content/child/site_isolation_stats_gatherer.h b/chromium/content/child/site_isolation_stats_gatherer.h
index 4530a16f127..36173193335 100644
--- a/chromium/content/child/site_isolation_stats_gatherer.h
+++ b/chromium/content/child/site_isolation_stats_gatherer.h
@@ -5,11 +5,11 @@
#ifndef CONTENT_CHILD_SITE_ISOLATION_STATS_GATHERER_H_
#define CONTENT_CHILD_SITE_ISOLATION_STATS_GATHERER_H_
+#include <memory>
#include <string>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/strings/string_piece.h"
#include "content/common/content_export.h"
#include "content/common/cross_site_document_classifier.h"
@@ -69,7 +69,7 @@ class CONTENT_EXPORT SiteIsolationStatsGatherer {
// Returns any bookkeeping data about the HTTP header information for the
// request identified by |request_id|. Any data returned should then be
// passed to OnReceivedFirstChunk() with the first data chunk.
- static scoped_ptr<SiteIsolationResponseMetaData> OnReceivedResponse(
+ static std::unique_ptr<SiteIsolationResponseMetaData> OnReceivedResponse(
const GURL& frame_origin,
const GURL& response_url,
ResourceType resource_type,
@@ -81,7 +81,7 @@ class CONTENT_EXPORT SiteIsolationStatsGatherer {
// kinds of UMA data stats. This function is called only if the length of
// received data is non-zero.
static bool OnReceivedFirstChunk(
- const scoped_ptr<SiteIsolationResponseMetaData>& resp_data,
+ const std::unique_ptr<SiteIsolationResponseMetaData>& resp_data,
const char* payload,
int length);
diff --git a/chromium/content/child/storage_util.cc b/chromium/content/child/storage_util.cc
new file mode 100644
index 00000000000..6e440bf96e8
--- /dev/null
+++ b/chromium/content/child/storage_util.cc
@@ -0,0 +1,26 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/child/storage_util.h"
+
+#include "third_party/WebKit/public/platform/URLConversion.h"
+#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
+#include "url/gurl.h"
+
+namespace content {
+
+GURL WebSecurityOriginToGURL(const blink::WebSecurityOrigin& security_origin) {
+ // "file:///" URLs navigated to by the user may have "isLocal" set,
+ // which stringify as "null" by default. Previous code that sent
+ // origins from Blink to Chromium via DatabaseIdentifier would ignore
+ // this, so we mimic that behavior here.
+ // TODO(jsbell): Eliminate this. https://crbug.com/591482
+ if (security_origin.protocol().utf8() == "file" &&
+ security_origin.host().utf8() == "" && security_origin.port() == 0) {
+ return GURL("file:///");
+ }
+ return blink::WebStringToGURL(security_origin.toString());
+}
+
+} // namespace content
diff --git a/chromium/content/child/storage_util.h b/chromium/content/child/storage_util.h
new file mode 100644
index 00000000000..e6f51a90c08
--- /dev/null
+++ b/chromium/content/child/storage_util.h
@@ -0,0 +1,24 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_CHILD_STORAGE_UTIL_H_
+#define CONTENT_CHILD_STORAGE_UTIL_H_
+
+class GURL;
+
+namespace blink {
+class WebSecurityOrigin;
+} // namespace blink
+
+namespace content {
+
+// Storage APIs rely on GURLs to identify the origin, with some special cases.
+// New uses of this function should be avoided; url::Origin should be used
+// instead.
+// TODO(jsbell): Eliminate this. https://crbug.com/591482
+GURL WebSecurityOriginToGURL(const blink::WebSecurityOrigin& origin);
+
+} // namespace content
+
+#endif // CONTENT_CHILD_STORAGE_UTIL_H_
diff --git a/chromium/content/child/threaded_data_provider.cc b/chromium/content/child/threaded_data_provider.cc
deleted file mode 100644
index 91d385b81ef..00000000000
--- a/chromium/content/child/threaded_data_provider.cc
+++ /dev/null
@@ -1,349 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/child/threaded_data_provider.h"
-
-#include <stddef.h>
-
-#include "base/location.h"
-#include "base/single_thread_task_runner.h"
-#include "components/scheduler/child/webthread_impl_for_worker_scheduler.h"
-#include "content/child/child_process.h"
-#include "content/child/child_thread_impl.h"
-#include "content/child/resource_dispatcher.h"
-#include "content/child/thread_safe_sender.h"
-#include "content/common/resource_messages.h"
-#include "ipc/ipc_sync_channel.h"
-#include "third_party/WebKit/public/platform/WebThread.h"
-#include "third_party/WebKit/public/platform/WebThreadedDataReceiver.h"
-
-namespace content {
-
-namespace {
-
-class DataProviderMessageFilter : public IPC::MessageFilter {
- public:
- DataProviderMessageFilter(
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
- const scheduler::WebThreadImplForWorkerScheduler& background_thread,
- const base::WeakPtr<ThreadedDataProvider>&
- background_thread_resource_provider,
- const base::WeakPtr<ThreadedDataProvider>& main_thread_resource_provider,
- int request_id);
-
- // IPC::ChannelProxy::MessageFilter
- void OnFilterAdded(IPC::Sender* sender) final;
- bool OnMessageReceived(const IPC::Message& message) final;
-
- private:
- ~DataProviderMessageFilter() override {}
-
- void OnReceivedData(int request_id, int data_offset, int data_length,
- int encoded_data_length);
-
- const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
- const scheduler::WebThreadImplForWorkerScheduler& background_thread_;
- // This weakptr can only be dereferenced on the background thread.
- base::WeakPtr<ThreadedDataProvider>
- background_thread_resource_provider_;
- // This weakptr can only be dereferenced on the main thread.
- base::WeakPtr<ThreadedDataProvider>
- main_thread_resource_provider_;
- int request_id_;
-};
-
-DataProviderMessageFilter::DataProviderMessageFilter(
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
- const scheduler::WebThreadImplForWorkerScheduler& background_thread,
- const base::WeakPtr<ThreadedDataProvider>&
- background_thread_resource_provider,
- const base::WeakPtr<ThreadedDataProvider>& main_thread_resource_provider,
- int request_id)
- : io_task_runner_(io_task_runner),
- main_thread_task_runner_(main_thread_task_runner),
- background_thread_(background_thread),
- background_thread_resource_provider_(background_thread_resource_provider),
- main_thread_resource_provider_(main_thread_resource_provider),
- request_id_(request_id) {
- DCHECK(main_thread_task_runner_.get());
-}
-
-void DataProviderMessageFilter::OnFilterAdded(IPC::Sender* sender) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
-
- main_thread_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&ThreadedDataProvider::OnResourceMessageFilterAddedMainThread,
- main_thread_resource_provider_));
-}
-
-bool DataProviderMessageFilter::OnMessageReceived(
- const IPC::Message& message) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
-
- if (message.type() != ResourceMsg_DataReceived::ID)
- return false;
-
- int request_id;
-
- base::PickleIterator iter(message);
- if (!iter.ReadInt(&request_id)) {
- NOTREACHED() << "malformed resource message";
- return true;
- }
-
- if (request_id == request_id_) {
- ResourceMsg_DataReceived::Schema::Param arg;
- if (ResourceMsg_DataReceived::Read(&message, &arg)) {
- OnReceivedData(base::get<0>(arg), base::get<1>(arg),
- base::get<2>(arg), base::get<3>(arg));
- return true;
- }
- }
-
- return false;
-}
-
-void DataProviderMessageFilter::OnReceivedData(int request_id,
- int data_offset,
- int data_length,
- int encoded_data_length) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- background_thread_.TaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(&ThreadedDataProvider::OnReceivedDataOnBackgroundThread,
- background_thread_resource_provider_, data_offset, data_length,
- encoded_data_length));
-}
-
-} // anonymous namespace
-
-ThreadedDataProvider::ThreadedDataProvider(
- int request_id,
- blink::WebThreadedDataReceiver* threaded_data_receiver,
- linked_ptr<base::SharedMemory> shm_buffer,
- int shm_size,
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner)
- : request_id_(request_id),
- shm_buffer_(shm_buffer),
- shm_size_(shm_size),
- background_thread_(
- static_cast<scheduler::WebThreadImplForWorkerScheduler&>(
- *threaded_data_receiver->backgroundThread())),
- ipc_channel_(ChildThreadImpl::current()->channel()),
- threaded_data_receiver_(threaded_data_receiver),
- resource_filter_active_(false),
- main_thread_task_runner_(main_thread_task_runner),
- main_thread_weak_factory_(this) {
- DCHECK(ChildThreadImpl::current());
- DCHECK(ipc_channel_);
- DCHECK(threaded_data_receiver_);
- DCHECK(main_thread_task_runner_.get());
-
- background_thread_weak_factory_.reset(
- new base::WeakPtrFactory<ThreadedDataProvider>(this));
-
- filter_ = new DataProviderMessageFilter(
- ChildProcess::current()->io_task_runner(), main_thread_task_runner_,
- background_thread_, background_thread_weak_factory_->GetWeakPtr(),
- main_thread_weak_factory_.GetWeakPtr(), request_id);
-
- ChildThreadImpl::current()->channel()->AddFilter(filter_.get());
-}
-
-ThreadedDataProvider::~ThreadedDataProvider() {
- DCHECK(ChildThreadImpl::current());
-
- ChildThreadImpl::current()->channel()->RemoveFilter(filter_.get());
-
- delete threaded_data_receiver_;
-}
-
-void ThreadedDataProvider::DestructOnMainThread() {
- DCHECK(ChildThreadImpl::current());
-
- // The ThreadedDataProvider must be destructed on the main thread to
- // be threadsafe when removing the message filter and releasing the shared
- // memory buffer.
- delete this;
-}
-
-void ThreadedDataProvider::Stop() {
- DCHECK(ChildThreadImpl::current());
-
- // Make sure we don't get called by on the main thread anymore via weak
- // pointers we've passed to the filter.
- main_thread_weak_factory_.InvalidateWeakPtrs();
-
- blink::WebThread* current_background_thread =
- threaded_data_receiver_->backgroundThread();
-
- // We can't destroy this instance directly; we need to bounce a message over
- // to the background thread and back to make sure nothing else will access it
- // there, before we can destruct it. We also need to make sure the background
- // thread is still alive, since Blink could have shut down at this point
- // and freed the thread.
- if (current_background_thread) {
- // We should never end up with a different parser thread than from when the
- // ThreadedDataProvider gets created.
- DCHECK(current_background_thread ==
- static_cast<scheduler::WebThreadImplForWorkerScheduler*>(
- &background_thread_));
- background_thread_.TaskRunner()->PostTask(
- FROM_HERE, base::Bind(&ThreadedDataProvider::StopOnBackgroundThread,
- base::Unretained(this)));
- }
-}
-
-void ThreadedDataProvider::StopOnBackgroundThread() {
- DCHECK(background_thread_.isCurrentThread());
- DCHECK(background_thread_weak_factory_);
-
- // When this happens, the provider should no longer be called on the
- // background thread as it's about to be destroyed on the main thread.
- // Destructing the weak pointer factory means invalidating the weak pointers
- // which means no callbacks from the filter will happen and nothing else will
- // use this instance on the background thread.
- background_thread_weak_factory_.reset(NULL);
- main_thread_task_runner_->PostTask(FROM_HERE,
- base::Bind(&ThreadedDataProvider::DestructOnMainThread,
- base::Unretained(this)));
-}
-
-void ThreadedDataProvider::OnRequestCompleteForegroundThread(
- base::WeakPtr<ResourceDispatcher> resource_dispatcher,
- const ResourceMsg_RequestCompleteData& request_complete_data,
- const base::TimeTicks& renderer_completion_time) {
- DCHECK(ChildThreadImpl::current());
-
- background_thread_.TaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(&ThreadedDataProvider::OnRequestCompleteBackgroundThread,
- base::Unretained(this), resource_dispatcher,
- request_complete_data, renderer_completion_time));
-}
-
-void ThreadedDataProvider::OnRequestCompleteBackgroundThread(
- base::WeakPtr<ResourceDispatcher> resource_dispatcher,
- const ResourceMsg_RequestCompleteData& request_complete_data,
- const base::TimeTicks& renderer_completion_time) {
- DCHECK(background_thread_.isCurrentThread());
-
- main_thread_task_runner_->PostTask(FROM_HERE,
- base::Bind(
- &ResourceDispatcher::CompletedRequestAfterBackgroundThreadFlush,
- resource_dispatcher,
- request_id_,
- request_complete_data,
- renderer_completion_time));
-}
-
-void ThreadedDataProvider::OnResourceMessageFilterAddedMainThread() {
- DCHECK(ChildThreadImpl::current());
- DCHECK(background_thread_weak_factory_);
-
- // We bounce this message from the I/O thread via the main thread and then
- // to our background thread, following the same path as incoming data before
- // our filter gets added, to make sure there's nothing still incoming.
- background_thread_.TaskRunner()->PostTask(
- FROM_HERE,
- base::Bind(
- &ThreadedDataProvider::OnResourceMessageFilterAddedBackgroundThread,
- background_thread_weak_factory_->GetWeakPtr()));
-}
-
-void ThreadedDataProvider::OnResourceMessageFilterAddedBackgroundThread() {
- DCHECK(background_thread_.isCurrentThread());
- resource_filter_active_ = true;
-
- // At this point we know no more data is going to arrive from the main thread,
- // so we can process any data we've received directly from the I/O thread
- // in the meantime.
- if (!queued_data_.empty()) {
- std::vector<QueuedSharedMemoryData>::iterator iter = queued_data_.begin();
- for (; iter != queued_data_.end(); ++iter) {
- ForwardAndACKData(iter->data, iter->length, iter->encoded_length);
- }
-
- queued_data_.clear();
- }
-}
-
-void ThreadedDataProvider::OnReceivedDataOnBackgroundThread(
- int data_offset, int data_length, int encoded_data_length) {
- DCHECK(background_thread_.isCurrentThread());
- DCHECK(shm_buffer_ != NULL);
-
- CHECK_GE(shm_size_, data_offset + data_length);
- const char* data_ptr = static_cast<char*>(shm_buffer_->memory());
- CHECK(data_ptr);
- CHECK(data_ptr + data_offset);
-
- if (resource_filter_active_) {
- ForwardAndACKData(data_ptr + data_offset, data_length, encoded_data_length);
- } else {
- // There's a brief interval between the point where we know the filter
- // has been installed on the I/O thread, and when we know for sure there's
- // no more data coming in from the main thread (from before the filter
- // got added). If we get any data during that interval, we need to queue
- // it until we're certain we've processed all the main thread data to make
- // sure we forward (and ACK) everything in the right order.
- QueuedSharedMemoryData queued_data;
- queued_data.data = data_ptr + data_offset;
- queued_data.length = data_length;
- queued_data.encoded_length = encoded_data_length;
- queued_data_.push_back(queued_data);
- }
-}
-
-void ThreadedDataProvider::OnReceivedDataOnForegroundThread(
- const char* data, int data_length, int encoded_data_length) {
- DCHECK(ChildThreadImpl::current());
-
- background_thread_.TaskRunner()->PostTask(
- FROM_HERE, base::Bind(&ThreadedDataProvider::ForwardAndACKData,
- base::Unretained(this), data, data_length,
- encoded_data_length));
-}
-
-void ThreadedDataProvider::ForwardAndACKData(const char* data,
- int data_length,
- int encoded_data_length) {
- DCHECK(background_thread_.isCurrentThread());
-
- threaded_data_receiver_->acceptData(data, data_length);
-
- scoped_ptr<std::vector<char>> data_copy;
- if (threaded_data_receiver_->needsMainthreadDataCopy()) {
- data_copy.reset(new std::vector<char>(data, data + data_length));
- }
-
- main_thread_task_runner_->PostTask(FROM_HERE,
- base::Bind(&ThreadedDataProvider::DataNotifyForegroundThread,
- base::Unretained(this),
- base::Passed(&data_copy),
- data_length,
- encoded_data_length));
-
- ipc_channel_->Send(new ResourceHostMsg_DataReceived_ACK(request_id_));
-}
-
-void ThreadedDataProvider::DataNotifyForegroundThread(
- scoped_ptr<std::vector<char> > data_copy,
- int data_length,
- int encoded_data_length) {
- if (data_copy) {
- DCHECK(threaded_data_receiver_->needsMainthreadDataCopy());
- DCHECK_EQ((size_t)data_length, data_copy->size());
- }
-
- threaded_data_receiver_->acceptMainthreadDataNotification(
- (data_copy && !data_copy->empty()) ? &data_copy->front() : NULL,
- data_length, encoded_data_length);
-}
-
-} // namespace content
diff --git a/chromium/content/child/threaded_data_provider.h b/chromium/content/child/threaded_data_provider.h
deleted file mode 100644
index 4bebeb48c3f..00000000000
--- a/chromium/content/child/threaded_data_provider.h
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_CHILD_THREADED_DATA_PROVIDER_H_
-#define CONTENT_CHILD_THREADED_DATA_PROVIDER_H_
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/memory/linked_ptr.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/shared_memory.h"
-#include "base/memory/weak_ptr.h"
-#include "ipc/ipc_channel.h"
-#include "ipc/message_filter.h"
-
-struct ResourceMsg_RequestCompleteData;
-
-namespace blink {
-class WebThreadedDataReceiver;
-}
-
-namespace IPC {
-class SyncChannel;
-}
-
-namespace scheduler {
-class WebThreadImplForWorkerScheduler;
-}
-
-namespace content {
-class ResourceDispatcher;
-
-class ThreadedDataProvider {
- public:
- ThreadedDataProvider(
- int request_id,
- blink::WebThreadedDataReceiver* threaded_data_receiver,
- linked_ptr<base::SharedMemory> shm_buffer,
- int shm_size,
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_);
-
- // Any destruction of this class has to bounce via the background thread to
- // ensure all data is flushed; call Stop() to start this process.
- void Stop();
- void OnReceivedDataOnBackgroundThread(int data_offset,
- int data_length,
- int encoded_data_length);
-
- void OnReceivedDataOnForegroundThread(const char* data,
- int data_length,
- int encoded_data_length);
-
- void OnResourceMessageFilterAddedMainThread();
- void OnRequestCompleteForegroundThread(
- base::WeakPtr<ResourceDispatcher> resource_dispatcher,
- const ResourceMsg_RequestCompleteData& request_complete_data,
- const base::TimeTicks& renderer_completion_time);
-
- private:
- ~ThreadedDataProvider();
- void DestructOnMainThread();
-
- void StopOnBackgroundThread();
- void OnResourceMessageFilterAddedBackgroundThread();
- void OnRequestCompleteBackgroundThread(
- base::WeakPtr<ResourceDispatcher> resource_dispatcher,
- const ResourceMsg_RequestCompleteData& request_complete_data,
- const base::TimeTicks& renderer_completion_time);
- void ForwardAndACKData(const char* data,
- int data_length,
- int encoded_data_length);
- void DataNotifyForegroundThread(
- scoped_ptr<std::vector<char> > data_copy,
- int data_length,
- int encoded_data_length);
-
- scoped_refptr<IPC::MessageFilter> filter_;
- int request_id_;
- linked_ptr<base::SharedMemory> shm_buffer_;
- int shm_size_;
- scoped_ptr<base::WeakPtrFactory<ThreadedDataProvider> >
- background_thread_weak_factory_;
- scheduler::WebThreadImplForWorkerScheduler& background_thread_;
- IPC::SyncChannel* ipc_channel_;
- blink::WebThreadedDataReceiver* threaded_data_receiver_;
- bool resource_filter_active_;
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
-
- struct QueuedSharedMemoryData {
- const char* data;
- int length;
- int encoded_length;
- };
- std::vector<QueuedSharedMemoryData> queued_data_;
-
- base::WeakPtrFactory<ThreadedDataProvider>
- main_thread_weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(ThreadedDataProvider);
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_THREADED_DATA_PROVIDER_H_
diff --git a/chromium/content/child/v8_value_converter_impl.cc b/chromium/content/child/v8_value_converter_impl.cc
index 1d4fe41bdb4..c37160fe597 100644
--- a/chromium/content/child/v8_value_converter_impl.cc
+++ b/chromium/content/child/v8_value_converter_impl.cc
@@ -8,12 +8,12 @@
#include <stdint.h>
#include <cmath>
+#include <memory>
#include <string>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
#include "base/values.h"
#include "third_party/WebKit/public/web/WebArrayBuffer.h"
#include "third_party/WebKit/public/web/WebArrayBufferConverter.h"
@@ -230,6 +230,9 @@ v8::Local<v8::Value> V8ValueConverterImpl::ToV8Array(
const base::ListValue* val) const {
v8::Local<v8::Array> result(v8::Array::New(isolate, val->GetSize()));
+ // TODO(robwu): Callers should pass in the context.
+ v8::Local<v8::Context> context = isolate->GetCurrentContext();
+
for (size_t i = 0; i < val->GetSize(); ++i) {
const base::Value* child = NULL;
CHECK(val->Get(i, &child));
@@ -238,10 +241,10 @@ v8::Local<v8::Value> V8ValueConverterImpl::ToV8Array(
ToV8ValueImpl(isolate, creation_context, child);
CHECK(!child_v8.IsEmpty());
- v8::TryCatch try_catch(isolate);
- result->Set(static_cast<uint32_t>(i), child_v8);
- if (try_catch.HasCaught())
- LOG(ERROR) << "Setter for index " << i << " threw an exception.";
+ v8::Maybe<bool> maybe =
+ result->CreateDataProperty(context, static_cast<uint32_t>(i), child_v8);
+ if (!maybe.IsJust() || !maybe.FromJust())
+ LOG(ERROR) << "Failed to set value at index " << i;
}
return result;
@@ -253,6 +256,9 @@ v8::Local<v8::Value> V8ValueConverterImpl::ToV8Object(
const base::DictionaryValue* val) const {
v8::Local<v8::Object> result(v8::Object::New(isolate));
+ // TODO(robwu): Callers should pass in the context.
+ v8::Local<v8::Context> context = isolate->GetCurrentContext();
+
for (base::DictionaryValue::Iterator iter(*val);
!iter.IsAtEnd(); iter.Advance()) {
const std::string& key = iter.key();
@@ -260,15 +266,13 @@ v8::Local<v8::Value> V8ValueConverterImpl::ToV8Object(
ToV8ValueImpl(isolate, creation_context, &iter.value());
CHECK(!child_v8.IsEmpty());
- v8::TryCatch try_catch(isolate);
- result->Set(
- v8::String::NewFromUtf8(
- isolate, key.c_str(), v8::String::kNormalString, key.length()),
+ v8::Maybe<bool> maybe = result->CreateDataProperty(
+ context,
+ v8::String::NewFromUtf8(isolate, key.c_str(), v8::String::kNormalString,
+ key.length()),
child_v8);
- if (try_catch.HasCaught()) {
- LOG(ERROR) << "Setter for property " << key.c_str() << " threw an "
- << "exception.";
- }
+ if (!maybe.IsJust() || !maybe.FromJust())
+ LOG(ERROR) << "Failed to set property with key " << key;
}
return result;
@@ -376,7 +380,7 @@ base::Value* V8ValueConverterImpl::FromV8Array(
if (!state->UpdateAndCheckUniqueness(val))
return base::Value::CreateNullValue().release();
- scoped_ptr<v8::Context::Scope> scope;
+ std::unique_ptr<v8::Context::Scope> scope;
// If val was created in a different context than our current one, change to
// that context, but change back after val is converted.
if (!val->CreationContext().IsEmpty() &&
@@ -434,9 +438,9 @@ base::Value* V8ValueConverterImpl::FromV8ArrayBuffer(
char* data = NULL;
size_t length = 0;
- scoped_ptr<blink::WebArrayBuffer> array_buffer(
+ std::unique_ptr<blink::WebArrayBuffer> array_buffer(
blink::WebArrayBufferConverter::createFromV8Value(val, isolate));
- scoped_ptr<blink::WebArrayBufferView> view;
+ std::unique_ptr<blink::WebArrayBufferView> view;
if (array_buffer) {
data = reinterpret_cast<char*>(array_buffer->data());
length = array_buffer->byteLength();
@@ -461,7 +465,7 @@ base::Value* V8ValueConverterImpl::FromV8Object(
if (!state->UpdateAndCheckUniqueness(val))
return base::Value::CreateNullValue().release();
- scoped_ptr<v8::Context::Scope> scope;
+ std::unique_ptr<v8::Context::Scope> scope;
// If val was created in a different context than our current one, change to
// that context, but change back after val is converted.
if (!val->CreationContext().IsEmpty() &&
@@ -496,7 +500,7 @@ base::Value* V8ValueConverterImpl::FromV8Object(
if (val->InternalFieldCount())
return new base::DictionaryValue();
- scoped_ptr<base::DictionaryValue> result(new base::DictionaryValue());
+ std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
v8::Local<v8::Array> property_names(val->GetOwnPropertyNames());
for (uint32_t i = 0; i < property_names->Length(); ++i) {
@@ -521,7 +525,8 @@ base::Value* V8ValueConverterImpl::FromV8Object(
child_v8 = v8::Null(isolate);
}
- scoped_ptr<base::Value> child(FromV8ValueImpl(state, child_v8, isolate));
+ std::unique_ptr<base::Value> child(
+ FromV8ValueImpl(state, child_v8, isolate));
if (!child)
// JSON.stringify skips properties whose values don't serialize, for
// example undefined and functions. Emulate that behavior.
diff --git a/chromium/content/child/v8_value_converter_impl_unittest.cc b/chromium/content/child/v8_value_converter_impl_unittest.cc
index 311fa7f4aa7..3387f4fc4cd 100644
--- a/chromium/content/child/v8_value_converter_impl_unittest.cc
+++ b/chromium/content/child/v8_value_converter_impl_unittest.cc
@@ -2,17 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "content/child/v8_value_converter_impl.h"
+
#include <stddef.h>
#include <stdint.h>
#include <cmath>
+#include <memory>
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
#include "base/test/values_test_util.h"
#include "base/values.h"
-#include "content/child/v8_value_converter_impl.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "v8/include/v8.h"
@@ -103,6 +104,26 @@ class V8ValueConverterImplTest : public testing::Test {
return std::string(*utf8, utf8.length());
}
+ int32_t GetInt(v8::Local<v8::Object> value, const std::string& key) {
+ v8::Local<v8::Int32> temp =
+ value->Get(v8::String::NewFromUtf8(isolate_, key.c_str()))
+ .As<v8::Int32>();
+ if (temp.IsEmpty()) {
+ ADD_FAILURE();
+ return -1;
+ }
+ return temp->Value();
+ }
+
+ int32_t GetInt(v8::Local<v8::Object> value, uint32_t index) {
+ v8::Local<v8::Int32> temp = value->Get(index).As<v8::Int32>();
+ if (temp.IsEmpty()) {
+ ADD_FAILURE();
+ return -1;
+ }
+ return temp->Value();
+ }
+
bool IsNull(base::DictionaryValue* value, const std::string& key) {
base::Value* child = NULL;
if (!value->Get(key, &child)) {
@@ -143,10 +164,10 @@ class V8ValueConverterImplTest : public testing::Test {
void TestWeirdType(const V8ValueConverterImpl& converter,
v8::Local<v8::Value> val,
base::Value::Type expected_type,
- scoped_ptr<base::Value> expected_value) {
+ std::unique_ptr<base::Value> expected_value) {
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
- scoped_ptr<base::Value> raw(converter.FromV8Value(val, context));
+ std::unique_ptr<base::Value> raw(converter.FromV8Value(val, context));
if (expected_value) {
ASSERT_TRUE(raw.get());
@@ -158,7 +179,7 @@ class V8ValueConverterImplTest : public testing::Test {
v8::Local<v8::Object> object(v8::Object::New(isolate_));
object->Set(v8::String::NewFromUtf8(isolate_, "test"), val);
- scoped_ptr<base::DictionaryValue> dictionary(
+ std::unique_ptr<base::DictionaryValue> dictionary(
static_cast<base::DictionaryValue*>(
converter.FromV8Value(object, context)));
ASSERT_TRUE(dictionary.get());
@@ -174,7 +195,7 @@ class V8ValueConverterImplTest : public testing::Test {
v8::Local<v8::Array> array(v8::Array::New(isolate_));
array->Set(0, val);
- scoped_ptr<base::ListValue> list(
+ std::unique_ptr<base::ListValue> list(
static_cast<base::ListValue*>(converter.FromV8Value(array, context)));
ASSERT_TRUE(list.get());
if (expected_value) {
@@ -198,7 +219,7 @@ class V8ValueConverterImplTest : public testing::Test {
};
TEST_F(V8ValueConverterImplTest, BasicRoundTrip) {
- scoped_ptr<base::Value> original_root = base::test::ParseJson(
+ std::unique_ptr<base::Value> original_root = base::test::ParseJson(
"{ \n"
" \"null\": null, \n"
" \"true\": true, \n"
@@ -260,13 +281,14 @@ TEST_F(V8ValueConverterImplTest, BasicRoundTrip) {
EXPECT_TRUE(v8_object->Get(v8::String::NewFromUtf8(isolate_, "empty-list"))
->IsArray());
- scoped_ptr<base::Value> new_root(converter.FromV8Value(v8_object, context));
+ std::unique_ptr<base::Value> new_root(
+ converter.FromV8Value(v8_object, context));
EXPECT_NE(original_root.get(), new_root.get());
EXPECT_TRUE(original_root->Equals(new_root.get()));
}
TEST_F(V8ValueConverterImplTest, KeysWithDots) {
- scoped_ptr<base::Value> original =
+ std::unique_ptr<base::Value> original =
base::test::ParseJson("{ \"foo.bar\": \"baz\" }");
v8::HandleScope handle_scope(isolate_);
@@ -275,9 +297,8 @@ TEST_F(V8ValueConverterImplTest, KeysWithDots) {
v8::Context::Scope context_scope(context);
V8ValueConverterImpl converter;
- scoped_ptr<base::Value> copy(
- converter.FromV8Value(
- converter.ToV8Value(original.get(), context), context));
+ std::unique_ptr<base::Value> copy(converter.FromV8Value(
+ converter.ToV8Value(original.get(), context), context));
EXPECT_TRUE(original->Equals(copy.get()));
}
@@ -287,6 +308,8 @@ TEST_F(V8ValueConverterImplTest, ObjectExceptions) {
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
v8::Context::Scope context_scope(context);
+ v8::MicrotasksScope microtasks(
+ isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks);
// Set up objects to throw when reading or writing 'foo'.
const char* source =
@@ -305,7 +328,7 @@ TEST_F(V8ValueConverterImplTest, ObjectExceptions) {
// Converting from v8 value should replace the foo property with null.
V8ValueConverterImpl converter;
- scoped_ptr<base::DictionaryValue> converted(
+ std::unique_ptr<base::DictionaryValue> converted(
static_cast<base::DictionaryValue*>(
converter.FromV8Value(object, context)));
EXPECT_TRUE(converted.get());
@@ -315,12 +338,13 @@ TEST_F(V8ValueConverterImplTest, ObjectExceptions) {
EXPECT_EQ(1u, converted->size());
EXPECT_EQ("bar", GetString(converted.get(), "bar"));
- // Converting to v8 value should drop the foo property.
+ // Converting to v8 value should not trigger the setter.
converted->SetString("foo", "foo");
v8::Local<v8::Object> copy =
converter.ToV8Value(converted.get(), context).As<v8::Object>();
EXPECT_FALSE(copy.IsEmpty());
EXPECT_EQ(2u, copy->GetPropertyNames()->Length());
+ EXPECT_EQ("foo", GetString(copy, "foo"));
EXPECT_EQ("bar", GetString(copy, "bar"));
}
@@ -329,6 +353,8 @@ TEST_F(V8ValueConverterImplTest, ArrayExceptions) {
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
v8::Context::Scope context_scope(context);
+ v8::MicrotasksScope microtasks(
+ isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks);
const char* source = "(function() {"
"var arr = [];"
@@ -347,20 +373,23 @@ TEST_F(V8ValueConverterImplTest, ArrayExceptions) {
// Converting from v8 value should replace the first item with null.
V8ValueConverterImpl converter;
- scoped_ptr<base::ListValue> converted(static_cast<base::ListValue*>(
- converter.FromV8Value(array, context)));
+ std::unique_ptr<base::ListValue> converted(
+ static_cast<base::ListValue*>(converter.FromV8Value(array, context)));
ASSERT_TRUE(converted.get());
// http://code.google.com/p/v8/issues/detail?id=1342
EXPECT_EQ(2u, converted->GetSize());
EXPECT_TRUE(IsNull(converted.get(), 0));
- // Converting to v8 value should drop the first item and leave a hole.
+ // Converting to v8 value should not be affected by the getter/setter
+ // because the setters/getters are defined on the array instance, not
+ // on the Array's prototype.
converted.reset(static_cast<base::ListValue*>(
base::test::ParseJson("[ \"foo\", \"bar\" ]").release()));
v8::Local<v8::Array> copy =
converter.ToV8Value(converted.get(), context).As<v8::Array>();
ASSERT_FALSE(copy.IsEmpty());
EXPECT_EQ(2u, copy->Length());
+ EXPECT_EQ("foo", GetString(copy, 0));
EXPECT_EQ("bar", GetString(copy, 1));
}
@@ -374,30 +403,23 @@ TEST_F(V8ValueConverterImplTest, WeirdTypes) {
v8::String::NewFromUtf8(isolate_, "."), v8::RegExp::kNone));
V8ValueConverterImpl converter;
- TestWeirdType(converter,
- v8::Undefined(isolate_),
+ TestWeirdType(converter, v8::Undefined(isolate_),
base::Value::TYPE_NULL, // Arbitrary type, result is NULL.
- scoped_ptr<base::Value>());
- TestWeirdType(converter,
- v8::Date::New(isolate_, 1000),
- base::Value::TYPE_DICTIONARY,
- scoped_ptr<base::Value>(new base::DictionaryValue()));
- TestWeirdType(converter,
- regex,
+ std::unique_ptr<base::Value>());
+ TestWeirdType(converter, v8::Date::New(isolate_, 1000),
base::Value::TYPE_DICTIONARY,
- scoped_ptr<base::Value>(new base::DictionaryValue()));
+ std::unique_ptr<base::Value>(new base::DictionaryValue()));
+ TestWeirdType(converter, regex, base::Value::TYPE_DICTIONARY,
+ std::unique_ptr<base::Value>(new base::DictionaryValue()));
converter.SetDateAllowed(true);
- TestWeirdType(converter,
- v8::Date::New(isolate_, 1000),
+ TestWeirdType(converter, v8::Date::New(isolate_, 1000),
base::Value::TYPE_DOUBLE,
- scoped_ptr<base::Value>(new base::FundamentalValue(1.0)));
+ std::unique_ptr<base::Value>(new base::FundamentalValue(1.0)));
converter.SetRegExpAllowed(true);
- TestWeirdType(converter,
- regex,
- base::Value::TYPE_STRING,
- scoped_ptr<base::Value>(new base::StringValue("/./")));
+ TestWeirdType(converter, regex, base::Value::TYPE_STRING,
+ std::unique_ptr<base::Value>(new base::StringValue("/./")));
}
TEST_F(V8ValueConverterImplTest, Prototype) {
@@ -405,6 +427,8 @@ TEST_F(V8ValueConverterImplTest, Prototype) {
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
v8::Context::Scope context_scope(context);
+ v8::MicrotasksScope microtasks(
+ isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks);
const char* source = "(function() {"
"Object.prototype.foo = 'foo';"
@@ -417,18 +441,160 @@ TEST_F(V8ValueConverterImplTest, Prototype) {
ASSERT_FALSE(object.IsEmpty());
V8ValueConverterImpl converter;
- scoped_ptr<base::DictionaryValue> result(
+ std::unique_ptr<base::DictionaryValue> result(
static_cast<base::DictionaryValue*>(
converter.FromV8Value(object, context)));
ASSERT_TRUE(result.get());
EXPECT_EQ(0u, result->size());
}
+TEST_F(V8ValueConverterImplTest, ObjectPrototypeSetter) {
+ std::unique_ptr<base::Value> original =
+ base::test::ParseJson("{ \"foo\": \"good value\" }");
+
+ v8::HandleScope handle_scope(isolate_);
+ v8::Local<v8::Context> context =
+ v8::Local<v8::Context>::New(isolate_, context_);
+ v8::Context::Scope context_scope(context);
+ v8::MicrotasksScope microtasks(isolate_,
+ v8::MicrotasksScope::kDoNotRunMicrotasks);
+
+ const char* source =
+ "var result = { getters: 0, setters: 0 };"
+ "Object.defineProperty(Object.prototype, 'foo', {"
+ " get() { ++result.getters; return 'bogus'; },"
+ " set() { ++result.setters; },"
+ "});"
+ "result;";
+
+ const char* source_sanity =
+ "({}).foo = 'Trigger setter';"
+ "({}).foo;";
+
+ v8::Local<v8::Script> script(
+ v8::Script::Compile(v8::String::NewFromUtf8(isolate_, source)));
+ v8::Local<v8::Object> result = script->Run().As<v8::Object>();
+ ASSERT_FALSE(result.IsEmpty());
+
+ // Sanity checks: the getters/setters are normally triggered.
+ v8::Script::Compile(v8::String::NewFromUtf8(isolate_, source_sanity))->Run();
+ EXPECT_EQ(1, GetInt(result, "getters"));
+ EXPECT_EQ(1, GetInt(result, "setters"));
+
+ V8ValueConverterImpl converter;
+ v8::Local<v8::Object> converted =
+ converter.ToV8Value(original.get(), context).As<v8::Object>();
+ EXPECT_FALSE(converted.IsEmpty());
+
+ // Getters/setters shouldn't be triggered.
+ EXPECT_EQ(1, GetInt(result, "getters"));
+ EXPECT_EQ(1, GetInt(result, "setters"));
+
+ EXPECT_EQ(1u, converted->GetPropertyNames()->Length());
+ EXPECT_EQ("good value", GetString(converted, "foo"));
+
+ // Getters/setters shouldn't be triggered while accessing existing values.
+ EXPECT_EQ(1, GetInt(result, "getters"));
+ EXPECT_EQ(1, GetInt(result, "setters"));
+
+ // Repeat the same exercise with a dictionary without the key.
+ base::DictionaryValue missing_key_dict;
+ missing_key_dict.SetString("otherkey", "hello");
+ v8::Local<v8::Object> converted2 =
+ converter.ToV8Value(&missing_key_dict, context).As<v8::Object>();
+ EXPECT_FALSE(converted2.IsEmpty());
+
+ // Getters/setters shouldn't be triggered.
+ EXPECT_EQ(1, GetInt(result, "getters"));
+ EXPECT_EQ(1, GetInt(result, "setters"));
+
+ EXPECT_EQ(1u, converted2->GetPropertyNames()->Length());
+ EXPECT_EQ("hello", GetString(converted2, "otherkey"));
+
+ // Missing key = should trigger getter upon access.
+ EXPECT_EQ("bogus", GetString(converted2, "foo"));
+ EXPECT_EQ(2, GetInt(result, "getters"));
+ EXPECT_EQ(1, GetInt(result, "setters"));
+}
+
+TEST_F(V8ValueConverterImplTest, ArrayPrototypeSetter) {
+ std::unique_ptr<base::Value> original =
+ base::test::ParseJson("[100, 200, 300]");
+
+ v8::HandleScope handle_scope(isolate_);
+ v8::Local<v8::Context> context =
+ v8::Local<v8::Context>::New(isolate_, context_);
+ v8::Context::Scope context_scope(context);
+ v8::MicrotasksScope microtasks(isolate_,
+ v8::MicrotasksScope::kDoNotRunMicrotasks);
+
+ const char* source =
+ "var result = { getters: 0, setters: 0 };"
+ "Object.defineProperty(Array.prototype, '1', {"
+ " get() { ++result.getters; return 1337; },"
+ " set() { ++result.setters; },"
+ "});"
+ "result;";
+
+ const char* source_sanity =
+ "[][1] = 'Trigger setter';"
+ "[][1];";
+
+ v8::Local<v8::Script> script(
+ v8::Script::Compile(v8::String::NewFromUtf8(isolate_, source)));
+ v8::Local<v8::Object> result = script->Run().As<v8::Object>();
+ ASSERT_FALSE(result.IsEmpty());
+
+ // Sanity checks: the getters/setters are normally triggered.
+ v8::Script::Compile(v8::String::NewFromUtf8(isolate_, source_sanity))->Run();
+ EXPECT_EQ(1, GetInt(result, "getters"));
+ EXPECT_EQ(1, GetInt(result, "setters"));
+
+ V8ValueConverterImpl converter;
+ v8::Local<v8::Array> converted =
+ converter.ToV8Value(original.get(), context).As<v8::Array>();
+ EXPECT_FALSE(converted.IsEmpty());
+
+ // Getters/setters shouldn't be triggered during the conversion.
+ EXPECT_EQ(1, GetInt(result, "getters"));
+ EXPECT_EQ(1, GetInt(result, "setters"));
+
+ EXPECT_EQ(3u, converted->Length());
+ EXPECT_EQ(100, GetInt(converted, 0));
+ EXPECT_EQ(200, GetInt(converted, 1));
+ EXPECT_EQ(300, GetInt(converted, 2));
+
+ // Getters/setters shouldn't be triggered while accessing existing values.
+ EXPECT_EQ(1, GetInt(result, "getters"));
+ EXPECT_EQ(1, GetInt(result, "setters"));
+
+ // Try again, using an array without the index.
+ base::ListValue one_item_list;
+ one_item_list.Append(new base::FundamentalValue(123456));
+ v8::Local<v8::Array> converted2 =
+ converter.ToV8Value(&one_item_list, context).As<v8::Array>();
+ EXPECT_FALSE(converted2.IsEmpty());
+
+ // Getters/setters shouldn't be triggered during the conversion.
+ EXPECT_EQ(1, GetInt(result, "getters"));
+ EXPECT_EQ(1, GetInt(result, "setters"));
+
+ EXPECT_EQ(1u, converted2->Length());
+ EXPECT_EQ(123456, GetInt(converted2, 0));
+
+ // Accessing missing index 1 triggers the getter.
+ EXPECT_EQ(1337, GetInt(converted2, 1));
+ EXPECT_EQ(2, GetInt(result, "getters"));
+ EXPECT_EQ(1, GetInt(result, "setters"));
+}
+
TEST_F(V8ValueConverterImplTest, StripNullFromObjects) {
v8::HandleScope handle_scope(isolate_);
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
v8::Context::Scope context_scope(context);
+ v8::MicrotasksScope microtasks(
+ isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks);
const char* source = "(function() {"
"return { foo: undefined, bar: null };"
@@ -442,7 +608,7 @@ TEST_F(V8ValueConverterImplTest, StripNullFromObjects) {
V8ValueConverterImpl converter;
converter.SetStripNullFromObjects(true);
- scoped_ptr<base::DictionaryValue> result(
+ std::unique_ptr<base::DictionaryValue> result(
static_cast<base::DictionaryValue*>(
converter.FromV8Value(object, context)));
ASSERT_TRUE(result.get());
@@ -463,7 +629,7 @@ TEST_F(V8ValueConverterImplTest, RecursiveObjects) {
v8::String::NewFromUtf8(isolate_, "bar"));
object->Set(v8::String::NewFromUtf8(isolate_, "obj"), object);
- scoped_ptr<base::DictionaryValue> object_result(
+ std::unique_ptr<base::DictionaryValue> object_result(
static_cast<base::DictionaryValue*>(
converter.FromV8Value(object, context)));
ASSERT_TRUE(object_result.get());
@@ -475,7 +641,7 @@ TEST_F(V8ValueConverterImplTest, RecursiveObjects) {
array->Set(0, v8::String::NewFromUtf8(isolate_, "1"));
array->Set(1, array);
- scoped_ptr<base::ListValue> list_result(
+ std::unique_ptr<base::ListValue> list_result(
static_cast<base::ListValue*>(converter.FromV8Value(array, context)));
ASSERT_TRUE(list_result.get());
EXPECT_EQ(2u, list_result->GetSize());
@@ -487,6 +653,8 @@ TEST_F(V8ValueConverterImplTest, WeirdProperties) {
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
v8::Context::Scope context_scope(context);
+ v8::MicrotasksScope microtasks(
+ isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks);
const char* source = "(function() {"
"return {"
@@ -505,9 +673,9 @@ TEST_F(V8ValueConverterImplTest, WeirdProperties) {
ASSERT_FALSE(object.IsEmpty());
V8ValueConverterImpl converter;
- scoped_ptr<base::Value> actual(converter.FromV8Value(object, context));
+ std::unique_ptr<base::Value> actual(converter.FromV8Value(object, context));
- scoped_ptr<base::Value> expected = base::test::ParseJson(
+ std::unique_ptr<base::Value> expected = base::test::ParseJson(
"{ \n"
" \"1\": \"foo\", \n"
" \"2\": \"bar\", \n"
@@ -525,6 +693,8 @@ TEST_F(V8ValueConverterImplTest, ArrayGetters) {
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
v8::Context::Scope context_scope(context);
+ v8::MicrotasksScope microtasks(
+ isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks);
const char* source = "(function() {"
"var a = [0];"
@@ -538,7 +708,7 @@ TEST_F(V8ValueConverterImplTest, ArrayGetters) {
ASSERT_FALSE(array.IsEmpty());
V8ValueConverterImpl converter;
- scoped_ptr<base::ListValue> result(
+ std::unique_ptr<base::ListValue> result(
static_cast<base::ListValue*>(converter.FromV8Value(array, context)));
ASSERT_TRUE(result.get());
EXPECT_EQ(2u, result->GetSize());
@@ -549,6 +719,8 @@ TEST_F(V8ValueConverterImplTest, UndefinedValueBehavior) {
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
v8::Context::Scope context_scope(context);
+ v8::MicrotasksScope microtasks(
+ isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks);
v8::Local<v8::Object> object;
{
@@ -585,17 +757,18 @@ TEST_F(V8ValueConverterImplTest, UndefinedValueBehavior) {
V8ValueConverterImpl converter;
- scoped_ptr<base::Value> actual_object(
+ std::unique_ptr<base::Value> actual_object(
converter.FromV8Value(object, context));
EXPECT_TRUE(base::Value::Equals(
base::test::ParseJson("{ \"bar\": null }").get(), actual_object.get()));
// Everything is null because JSON stringification preserves array length.
- scoped_ptr<base::Value> actual_array(converter.FromV8Value(array, context));
+ std::unique_ptr<base::Value> actual_array(
+ converter.FromV8Value(array, context));
EXPECT_TRUE(base::Value::Equals(
base::test::ParseJson("[ null, null, null ]").get(), actual_array.get()));
- scoped_ptr<base::Value> actual_sparse_array(
+ std::unique_ptr<base::Value> actual_sparse_array(
converter.FromV8Value(sparse_array, context));
EXPECT_TRUE(
base::Value::Equals(base::test::ParseJson("[ null, null, null ]").get(),
@@ -621,11 +794,12 @@ TEST_F(V8ValueConverterImplTest, ObjectsWithClashingIdentityHash) {
root->Set(3, v8::Local<v8::Object>(v8::Array::New(isolate_, 0)));
// The expected base::Value result.
- scoped_ptr<base::Value> expected = base::test::ParseJson("[{},{},[],[]]");
+ std::unique_ptr<base::Value> expected =
+ base::test::ParseJson("[{},{},[],[]]");
ASSERT_TRUE(expected.get());
// The actual result.
- scoped_ptr<base::Value> value(converter.FromV8Value(root, context));
+ std::unique_ptr<base::Value> value(converter.FromV8Value(root, context));
ASSERT_TRUE(value.get());
EXPECT_TRUE(expected->Equals(value.get()));
@@ -647,7 +821,7 @@ TEST_F(V8ValueConverterImplTest, DetectCycles) {
expected_list.Append(base::Value::CreateNullValue());
// The actual result.
- scoped_ptr<base::Value> actual_list(
+ std::unique_ptr<base::Value> actual_list(
converter.FromV8Value(recursive_array, context));
ASSERT_TRUE(actual_list.get());
@@ -668,7 +842,7 @@ TEST_F(V8ValueConverterImplTest, DetectCycles) {
expected_dictionary.Set(key, base::Value::CreateNullValue());
// The actual result.
- scoped_ptr<base::Value> actual_dictionary(
+ std::unique_ptr<base::Value> actual_dictionary(
converter.FromV8Value(recursive_object, context));
ASSERT_TRUE(actual_dictionary.get());
@@ -695,7 +869,8 @@ TEST_F(V8ValueConverterImplTest, MaxRecursionDepth) {
}
V8ValueConverterImpl converter;
- scoped_ptr<base::Value> value(converter.FromV8Value(deep_object, context));
+ std::unique_ptr<base::Value> value(
+ converter.FromV8Value(deep_object, context));
ASSERT_TRUE(value);
// Expected depth is kMaxRecursionDepth in v8_value_converter_impl.cc.
@@ -753,7 +928,7 @@ class V8ValueConverterOverridingStrategyForTesting
static base::Value* NewReferenceValue() {
return new base::StringValue("strategy");
}
- scoped_ptr<base::Value> reference_value_;
+ std::unique_ptr<base::Value> reference_value_;
};
TEST_F(V8ValueConverterImplTest, StrategyOverrides) {
@@ -767,19 +942,21 @@ TEST_F(V8ValueConverterImplTest, StrategyOverrides) {
converter.SetStrategy(&strategy);
v8::Local<v8::Object> object(v8::Object::New(isolate_));
- scoped_ptr<base::Value> object_value(converter.FromV8Value(object, context));
+ std::unique_ptr<base::Value> object_value(
+ converter.FromV8Value(object, context));
ASSERT_TRUE(object_value);
EXPECT_TRUE(
base::Value::Equals(strategy.reference_value(), object_value.get()));
v8::Local<v8::Array> array(v8::Array::New(isolate_));
- scoped_ptr<base::Value> array_value(converter.FromV8Value(array, context));
+ std::unique_ptr<base::Value> array_value(
+ converter.FromV8Value(array, context));
ASSERT_TRUE(array_value);
EXPECT_TRUE(
base::Value::Equals(strategy.reference_value(), array_value.get()));
v8::Local<v8::ArrayBuffer> array_buffer(v8::ArrayBuffer::New(isolate_, 0));
- scoped_ptr<base::Value> array_buffer_value(
+ std::unique_ptr<base::Value> array_buffer_value(
converter.FromV8Value(array_buffer, context));
ASSERT_TRUE(array_buffer_value);
EXPECT_TRUE(base::Value::Equals(strategy.reference_value(),
@@ -787,20 +964,21 @@ TEST_F(V8ValueConverterImplTest, StrategyOverrides) {
v8::Local<v8::ArrayBufferView> array_buffer_view(
v8::Uint8Array::New(array_buffer, 0, 0));
- scoped_ptr<base::Value> array_buffer_view_value(
+ std::unique_ptr<base::Value> array_buffer_view_value(
converter.FromV8Value(array_buffer_view, context));
ASSERT_TRUE(array_buffer_view_value);
EXPECT_TRUE(base::Value::Equals(strategy.reference_value(),
array_buffer_view_value.get()));
v8::Local<v8::Number> number(v8::Number::New(isolate_, 0.0));
- scoped_ptr<base::Value> number_value(converter.FromV8Value(number, context));
+ std::unique_ptr<base::Value> number_value(
+ converter.FromV8Value(number, context));
ASSERT_TRUE(number_value);
EXPECT_TRUE(
base::Value::Equals(strategy.reference_value(), number_value.get()));
v8::Local<v8::Primitive> undefined(v8::Undefined(isolate_));
- scoped_ptr<base::Value> undefined_value(
+ std::unique_ptr<base::Value> undefined_value(
converter.FromV8Value(undefined, context));
ASSERT_TRUE(undefined_value);
EXPECT_TRUE(
@@ -847,16 +1025,20 @@ TEST_F(V8ValueConverterImplTest, StrategyBypass) {
converter.SetStrategy(&strategy);
v8::Local<v8::Object> object(v8::Object::New(isolate_));
- scoped_ptr<base::Value> object_value(converter.FromV8Value(object, context));
+ std::unique_ptr<base::Value> object_value(
+ converter.FromV8Value(object, context));
ASSERT_TRUE(object_value);
- scoped_ptr<base::Value> reference_object_value(base::test::ParseJson("{}"));
+ std::unique_ptr<base::Value> reference_object_value(
+ base::test::ParseJson("{}"));
EXPECT_TRUE(
base::Value::Equals(reference_object_value.get(), object_value.get()));
v8::Local<v8::Array> array(v8::Array::New(isolate_));
- scoped_ptr<base::Value> array_value(converter.FromV8Value(array, context));
+ std::unique_ptr<base::Value> array_value(
+ converter.FromV8Value(array, context));
ASSERT_TRUE(array_value);
- scoped_ptr<base::Value> reference_array_value(base::test::ParseJson("[]"));
+ std::unique_ptr<base::Value> reference_array_value(
+ base::test::ParseJson("[]"));
EXPECT_TRUE(
base::Value::Equals(reference_array_value.get(), array_value.get()));
@@ -864,14 +1046,16 @@ TEST_F(V8ValueConverterImplTest, StrategyBypass) {
// this requires having blink to be initialized.
v8::Local<v8::Number> number(v8::Number::New(isolate_, 0.0));
- scoped_ptr<base::Value> number_value(converter.FromV8Value(number, context));
+ std::unique_ptr<base::Value> number_value(
+ converter.FromV8Value(number, context));
ASSERT_TRUE(number_value);
- scoped_ptr<base::Value> reference_number_value(base::test::ParseJson("0"));
+ std::unique_ptr<base::Value> reference_number_value(
+ base::test::ParseJson("0"));
EXPECT_TRUE(
base::Value::Equals(reference_number_value.get(), number_value.get()));
v8::Local<v8::Primitive> undefined(v8::Undefined(isolate_));
- scoped_ptr<base::Value> undefined_value(
+ std::unique_ptr<base::Value> undefined_value(
converter.FromV8Value(undefined, context));
EXPECT_FALSE(undefined_value);
}
diff --git a/chromium/content/child/web_data_consumer_handle_impl.cc b/chromium/content/child/web_data_consumer_handle_impl.cc
index f4ded9d70e3..f8986f099ae 100644
--- a/chromium/content/child/web_data_consumer_handle_impl.cc
+++ b/chromium/content/child/web_data_consumer_handle_impl.cc
@@ -5,12 +5,14 @@
#include "content/child/web_data_consumer_handle_impl.h"
#include <stdint.h>
+
#include <limits>
#include <utility>
#include "base/bind.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "mojo/public/c/system/types.h"
namespace content {
@@ -127,9 +129,9 @@ WebDataConsumerHandleImpl::WebDataConsumerHandleImpl(Handle handle)
WebDataConsumerHandleImpl::~WebDataConsumerHandleImpl() {
}
-scoped_ptr<blink::WebDataConsumerHandle::Reader>
+std::unique_ptr<blink::WebDataConsumerHandle::Reader>
WebDataConsumerHandleImpl::ObtainReader(Client* client) {
- return make_scoped_ptr(obtainReaderInternal(client));
+ return base::WrapUnique(obtainReaderInternal(client));
}
WebDataConsumerHandleImpl::ReaderImpl*
diff --git a/chromium/content/child/web_data_consumer_handle_impl.h b/chromium/content/child/web_data_consumer_handle_impl.h
index 1e26bdad106..5eb1aca2b60 100644
--- a/chromium/content/child/web_data_consumer_handle_impl.h
+++ b/chromium/content/child/web_data_consumer_handle_impl.h
@@ -7,7 +7,8 @@
#include <stddef.h>
-#include "base/memory/scoped_ptr.h"
+#include <memory>
+
#include "content/common/content_export.h"
#include "mojo/message_pump/handle_watcher.h"
#include "mojo/public/cpp/system/data_pipe.h"
@@ -43,7 +44,7 @@ class CONTENT_EXPORT WebDataConsumerHandleImpl final
mojo::common::HandleWatcher handle_watcher_;
Client* client_;
};
- scoped_ptr<Reader> ObtainReader(Client* client);
+ std::unique_ptr<Reader> ObtainReader(Client* client);
explicit WebDataConsumerHandleImpl(Handle handle);
~WebDataConsumerHandleImpl() override;
diff --git a/chromium/content/child/web_data_consumer_handle_impl_unittest.cc b/chromium/content/child/web_data_consumer_handle_impl_unittest.cc
index 747d8d86b44..2f75a2319ba 100644
--- a/chromium/content/child/web_data_consumer_handle_impl_unittest.cc
+++ b/chromium/content/child/web_data_consumer_handle_impl_unittest.cc
@@ -6,13 +6,15 @@
#include <stddef.h>
#include <stdint.h>
+
#include <algorithm>
+#include <memory>
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/location.h"
-#include "base/memory/scoped_ptr.h"
+#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
@@ -103,9 +105,9 @@ class ReadDataOperation : public ReadDataOperationBase {
}
private:
- scoped_ptr<WebDataConsumerHandleImpl> handle_;
- scoped_ptr<WebDataConsumerHandle::Reader> reader_;
- scoped_ptr<WebDataConsumerHandle::Client> client_;
+ std::unique_ptr<WebDataConsumerHandleImpl> handle_;
+ std::unique_ptr<WebDataConsumerHandle::Reader> reader_;
+ std::unique_ptr<WebDataConsumerHandle::Client> client_;
base::MessageLoop* main_message_loop_;
base::Closure on_done_;
std::string result_;
@@ -169,9 +171,9 @@ class TwoPhaseReadDataOperation : public ReadDataOperationBase {
}
private:
- scoped_ptr<WebDataConsumerHandleImpl> handle_;
- scoped_ptr<WebDataConsumerHandle::Reader> reader_;
- scoped_ptr<WebDataConsumerHandle::Client> client_;
+ std::unique_ptr<WebDataConsumerHandleImpl> handle_;
+ std::unique_ptr<WebDataConsumerHandle::Reader> reader_;
+ std::unique_ptr<WebDataConsumerHandle::Client> client_;
base::MessageLoop* main_message_loop_;
base::Closure on_done_;
std::string result_;
@@ -229,7 +231,7 @@ class WebDataConsumerHandleImplTest : public ::testing::Test {
TEST_F(WebDataConsumerHandleImplTest, ReadData) {
base::RunLoop run_loop;
- auto operation = make_scoped_ptr(new ReadDataOperation(
+ auto operation = base::WrapUnique(new ReadDataOperation(
std::move(consumer_), &message_loop_, run_loop.QuitClosure()));
base::Thread t("DataConsumerHandle test thread");
@@ -250,7 +252,7 @@ TEST_F(WebDataConsumerHandleImplTest, ReadData) {
TEST_F(WebDataConsumerHandleImplTest, TwoPhaseReadData) {
base::RunLoop run_loop;
- auto operation = make_scoped_ptr(new TwoPhaseReadDataOperation(
+ auto operation = base::WrapUnique(new TwoPhaseReadDataOperation(
std::move(consumer_), &message_loop_, run_loop.QuitClosure()));
base::Thread t("DataConsumerHandle test thread");
diff --git a/chromium/content/child/web_database_observer_impl.cc b/chromium/content/child/web_database_observer_impl.cc
index 8209f88e219..0172152e1d4 100644
--- a/chromium/content/child/web_database_observer_impl.cc
+++ b/chromium/content/child/web_database_observer_impl.cc
@@ -9,11 +9,14 @@
#include "base/single_thread_task_runner.h"
#include "base/strings/string16.h"
#include "base/thread_task_runner_handle.h"
+#include "content/child/storage_util.h"
#include "content/common/database_messages.h"
-#include "third_party/WebKit/public/platform/WebCString.h"
+#include "storage/common/database/database_identifier.h"
+#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/sqlite/sqlite3.h"
+using blink::WebSecurityOrigin;
using blink::WebString;
namespace content {
@@ -53,6 +56,13 @@ int DetermineHistogramResult(int websql_error, int sqlite_error) {
callsite, kCallsiteHistogramSize); \
} \
} while (0)
+
+// TODO(jsbell): Replace with use of url::Origin end-to-end.
+// https://crbug.com/591482
+std::string GetIdentifierFromOrigin(const WebSecurityOrigin& origin) {
+ return storage::GetIdentifierFromOrigin(WebSecurityOriginToGURL(origin));
+}
+
} // namespace
WebDatabaseObserverImpl::WebDatabaseObserverImpl(IPC::SyncMessageFilter* sender)
@@ -67,40 +77,35 @@ WebDatabaseObserverImpl::~WebDatabaseObserverImpl() {
}
void WebDatabaseObserverImpl::databaseOpened(
- const WebString& origin_identifier,
+ const WebSecurityOrigin& origin,
const WebString& database_name,
const WebString& database_display_name,
unsigned long estimated_size) {
- open_connections_->AddOpenConnection(origin_identifier.utf8(),
- database_name);
+ const std::string origin_identifier = GetIdentifierFromOrigin(origin);
+ open_connections_->AddOpenConnection(origin_identifier, database_name);
sender_->Send(new DatabaseHostMsg_Opened(
- origin_identifier.utf8(), database_name,
- database_display_name, estimated_size));
+ origin_identifier, database_name, database_display_name, estimated_size));
}
-void WebDatabaseObserverImpl::databaseModified(
- const WebString& origin_identifier,
- const WebString& database_name) {
- sender_->Send(new DatabaseHostMsg_Modified(
- origin_identifier.utf8(), database_name));
+void WebDatabaseObserverImpl::databaseModified(const WebSecurityOrigin& origin,
+ const WebString& database_name) {
+ sender_->Send(new DatabaseHostMsg_Modified(GetIdentifierFromOrigin(origin),
+ database_name));
}
-void WebDatabaseObserverImpl::databaseClosed(
- const WebString& origin_identifier,
- const WebString& database_name) {
+void WebDatabaseObserverImpl::databaseClosed(const WebSecurityOrigin& origin,
+ const WebString& database_name) {
DCHECK(!main_thread_task_runner_->RunsTasksOnCurrentThread());
+ const std::string origin_identifier = GetIdentifierFromOrigin(origin);
main_thread_task_runner_->PostTask(
FROM_HERE,
- base::Bind(
- base::IgnoreResult(&IPC::SyncMessageFilter::Send),
- sender_,
- new DatabaseHostMsg_Closed(origin_identifier.utf8(), database_name)));
- open_connections_->RemoveOpenConnection(origin_identifier.utf8(),
- database_name);
+ base::Bind(base::IgnoreResult(&IPC::SyncMessageFilter::Send), sender_,
+ new DatabaseHostMsg_Closed(origin_identifier, database_name)));
+ open_connections_->RemoveOpenConnection(origin_identifier, database_name);
}
void WebDatabaseObserverImpl::reportOpenDatabaseResult(
- const WebString& origin_identifier,
+ const WebSecurityOrigin& origin,
const WebString& database_name,
int callsite,
int websql_error,
@@ -108,7 +113,7 @@ void WebDatabaseObserverImpl::reportOpenDatabaseResult(
double call_time) {
UMA_HISTOGRAM_WEBSQL_RESULT("OpenResult", callsite,
websql_error, sqlite_error);
- HandleSqliteError(origin_identifier, database_name, sqlite_error);
+ HandleSqliteError(origin, database_name, sqlite_error);
if (websql_error == kWebSQLSuccess && sqlite_error == SQLITE_OK) {
UMA_HISTOGRAM_TIMES("websql.Async.OpenTime.Success",
@@ -120,50 +125,57 @@ void WebDatabaseObserverImpl::reportOpenDatabaseResult(
}
void WebDatabaseObserverImpl::reportChangeVersionResult(
- const WebString& origin_identifier,
+ const WebSecurityOrigin& origin,
const WebString& database_name,
- int callsite, int websql_error, int sqlite_error) {
+ int callsite,
+ int websql_error,
+ int sqlite_error) {
UMA_HISTOGRAM_WEBSQL_RESULT("ChangeVersionResult", callsite,
websql_error, sqlite_error);
- HandleSqliteError(origin_identifier, database_name, sqlite_error);
+ HandleSqliteError(origin, database_name, sqlite_error);
}
void WebDatabaseObserverImpl::reportStartTransactionResult(
- const WebString& origin_identifier,
+ const WebSecurityOrigin& origin,
const WebString& database_name,
- int callsite, int websql_error, int sqlite_error) {
+ int callsite,
+ int websql_error,
+ int sqlite_error) {
UMA_HISTOGRAM_WEBSQL_RESULT("BeginResult", callsite,
websql_error, sqlite_error);
- HandleSqliteError(origin_identifier, database_name, sqlite_error);
+ HandleSqliteError(origin, database_name, sqlite_error);
}
void WebDatabaseObserverImpl::reportCommitTransactionResult(
- const WebString& origin_identifier,
+ const WebSecurityOrigin& origin,
const WebString& database_name,
- int callsite, int websql_error, int sqlite_error) {
+ int callsite,
+ int websql_error,
+ int sqlite_error) {
UMA_HISTOGRAM_WEBSQL_RESULT("CommitResult", callsite,
websql_error, sqlite_error);
- HandleSqliteError(origin_identifier, database_name, sqlite_error);
+ HandleSqliteError(origin, database_name, sqlite_error);
}
void WebDatabaseObserverImpl::reportExecuteStatementResult(
- const WebString& origin_identifier,
+ const WebSecurityOrigin& origin,
const WebString& database_name,
- int callsite, int websql_error, int sqlite_error) {
+ int callsite,
+ int websql_error,
+ int sqlite_error) {
UMA_HISTOGRAM_WEBSQL_RESULT("StatementResult", callsite,
websql_error, sqlite_error);
- HandleSqliteError(origin_identifier, database_name, sqlite_error);
+ HandleSqliteError(origin, database_name, sqlite_error);
}
void WebDatabaseObserverImpl::reportVacuumDatabaseResult(
- const WebString& origin_identifier,
+ const WebSecurityOrigin& origin,
const WebString& database_name,
int sqlite_error) {
int result = DetermineHistogramResult(-1, sqlite_error);
UMA_HISTOGRAM_ENUMERATION("websql.Async.VacuumResult",
result, kResultHistogramSize);
-
- HandleSqliteError(origin_identifier, database_name, sqlite_error);
+ HandleSqliteError(origin, database_name, sqlite_error);
}
bool WebDatabaseObserverImpl::WaitForAllDatabasesToClose(
@@ -172,18 +184,15 @@ bool WebDatabaseObserverImpl::WaitForAllDatabasesToClose(
return open_connections_->WaitForAllDatabasesToClose(timeout);
}
-void WebDatabaseObserverImpl::HandleSqliteError(
- const WebString& origin_identifier,
- const WebString& database_name,
- int error) {
+void WebDatabaseObserverImpl::HandleSqliteError(const WebSecurityOrigin& origin,
+ const WebString& database_name,
+ int error) {
// We filter out errors which the backend doesn't act on to avoid
// a unnecessary ipc traffic, this method can get called at a fairly
// high frequency (per-sqlstatement).
if (error == SQLITE_CORRUPT || error == SQLITE_NOTADB) {
sender_->Send(new DatabaseHostMsg_HandleSqliteError(
- origin_identifier.utf8(),
- database_name,
- error));
+ GetIdentifierFromOrigin(origin), database_name, error));
}
}
diff --git a/chromium/content/child/web_database_observer_impl.h b/chromium/content/child/web_database_observer_impl.h
index ff283fb32ed..236ae8537c9 100644
--- a/chromium/content/child/web_database_observer_impl.h
+++ b/chromium/content/child/web_database_observer_impl.h
@@ -22,48 +22,48 @@ class WebDatabaseObserverImpl : public blink::WebDatabaseObserver {
explicit WebDatabaseObserverImpl(IPC::SyncMessageFilter* sender);
virtual ~WebDatabaseObserverImpl();
- void databaseOpened(const blink::WebString& origin_identifier,
+ void databaseOpened(const blink::WebSecurityOrigin& origin,
const blink::WebString& database_name,
const blink::WebString& database_display_name,
unsigned long estimated_size) override;
- void databaseModified(const blink::WebString& origin_identifier,
+ void databaseModified(const blink::WebSecurityOrigin& origin,
const blink::WebString& database_name) override;
- void databaseClosed(const blink::WebString& origin_identifier,
+ void databaseClosed(const blink::WebSecurityOrigin& origin,
const blink::WebString& database_name) override;
- void reportOpenDatabaseResult(const blink::WebString& origin_identifier,
+ void reportOpenDatabaseResult(const blink::WebSecurityOrigin& origin,
const blink::WebString& database_name,
int callsite,
int websql_error,
int sqlite_error,
double call_time) override;
- void reportChangeVersionResult(const blink::WebString& origin_identifier,
+ void reportChangeVersionResult(const blink::WebSecurityOrigin& origin,
const blink::WebString& database_name,
int callsite,
int websql_error,
int sqlite_error) override;
- void reportStartTransactionResult(const blink::WebString& origin_identifier,
+ void reportStartTransactionResult(const blink::WebSecurityOrigin& origin,
const blink::WebString& database_name,
int callsite,
int websql_error,
int sqlite_error) override;
- void reportCommitTransactionResult(const blink::WebString& origin_identifier,
+ void reportCommitTransactionResult(const blink::WebSecurityOrigin& origin,
const blink::WebString& database_name,
int callsite,
int websql_error,
int sqlite_error) override;
- void reportExecuteStatementResult(const blink::WebString& origin_identifier,
+ void reportExecuteStatementResult(const blink::WebSecurityOrigin& origin,
const blink::WebString& database_name,
int callsite,
int websql_error,
int sqlite_error) override;
- void reportVacuumDatabaseResult(const blink::WebString& origin_identifier,
+ void reportVacuumDatabaseResult(const blink::WebSecurityOrigin& origin,
const blink::WebString& database_name,
int sqlite_error) override;
bool WaitForAllDatabasesToClose(base::TimeDelta timeout);
private:
- void HandleSqliteError(const blink::WebString& origin_identifier,
+ void HandleSqliteError(const blink::WebSecurityOrigin& origin,
const blink::WebString& database_name,
int error);
diff --git a/chromium/content/child/web_discardable_memory_impl.cc b/chromium/content/child/web_discardable_memory_impl.cc
deleted file mode 100644
index a92083c937d..00000000000
--- a/chromium/content/child/web_discardable_memory_impl.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/child/web_discardable_memory_impl.h"
-
-#include <utility>
-
-#include "base/memory/discardable_memory.h"
-#include "base/memory/discardable_memory_allocator.h"
-#include "content/child/web_process_memory_dump_impl.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-
-namespace content {
-
-WebDiscardableMemoryImpl::~WebDiscardableMemoryImpl() {}
-
-// static
-scoped_ptr<WebDiscardableMemoryImpl>
-WebDiscardableMemoryImpl::CreateLockedMemory(size_t size) {
- return make_scoped_ptr(new WebDiscardableMemoryImpl(
- base::DiscardableMemoryAllocator::GetInstance()
- ->AllocateLockedDiscardableMemory(size)));
-}
-
-bool WebDiscardableMemoryImpl::lock() {
- return discardable_->Lock();
-}
-
-void WebDiscardableMemoryImpl::unlock() {
- discardable_->Unlock();
-}
-
-void* WebDiscardableMemoryImpl::data() {
- return discardable_->data();
-}
-
-blink::WebMemoryAllocatorDump*
-WebDiscardableMemoryImpl::createMemoryAllocatorDump(
- const blink::WebString& name,
- blink::WebProcessMemoryDump* wpmd) const {
- return static_cast<content::WebProcessMemoryDumpImpl*>(wpmd)
- ->CreateDiscardableMemoryAllocatorDump(name.utf8(), discardable_.get());
-}
-
-WebDiscardableMemoryImpl::WebDiscardableMemoryImpl(
- scoped_ptr<base::DiscardableMemory> memory)
- : discardable_(std::move(memory)) {}
-
-} // namespace content
diff --git a/chromium/content/child/web_discardable_memory_impl.h b/chromium/content/child/web_discardable_memory_impl.h
deleted file mode 100644
index dcde8be687f..00000000000
--- a/chromium/content/child/web_discardable_memory_impl.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_CHILD_WEB_DISCARDABLE_MEMORY_IMPL_H_
-#define CONTENT_CHILD_WEB_DISCARDABLE_MEMORY_IMPL_H_
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "third_party/WebKit/public/platform/WebDiscardableMemory.h"
-
-namespace base {
-class DiscardableMemory;
-}
-
-namespace content {
-
-// Implementation of WebDiscardableMemory that is responsible for allocating
-// discardable memory.
-class WebDiscardableMemoryImpl : public blink::WebDiscardableMemory {
- public:
- ~WebDiscardableMemoryImpl() override;
-
- static scoped_ptr<WebDiscardableMemoryImpl> CreateLockedMemory(size_t size);
-
- // blink::WebDiscardableMemory:
- bool lock() override;
- void unlock() override;
- void* data() override;
- blink::WebMemoryAllocatorDump* createMemoryAllocatorDump(
- const blink::WebString& name,
- blink::WebProcessMemoryDump* wpmd) const override;
-
- private:
- WebDiscardableMemoryImpl(scoped_ptr<base::DiscardableMemory> memory);
-
- scoped_ptr<base::DiscardableMemory> discardable_;
-
- DISALLOW_COPY_AND_ASSIGN(WebDiscardableMemoryImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_WEB_DISCARDABLE_MEMORY_IMPL_H_
diff --git a/chromium/content/child/web_memory_allocator_dump_impl.cc b/chromium/content/child/web_memory_allocator_dump_impl.cc
deleted file mode 100644
index af9b57e4d9c..00000000000
--- a/chromium/content/child/web_memory_allocator_dump_impl.cc
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/child/web_memory_allocator_dump_impl.h"
-
-#include "base/trace_event/memory_allocator_dump.h"
-
-namespace content {
-
-WebMemoryAllocatorDumpImpl::WebMemoryAllocatorDumpImpl(
- base::trace_event::MemoryAllocatorDump* memory_allocator_dump)
- : memory_allocator_dump_(memory_allocator_dump),
- guid_(memory_allocator_dump->guid().ToUint64()) {
-}
-
-WebMemoryAllocatorDumpImpl::~WebMemoryAllocatorDumpImpl() {
-}
-
-void WebMemoryAllocatorDumpImpl::addScalar(const char* name,
- const char* units,
- uint64_t value) {
- memory_allocator_dump_->AddScalar(name, units, value);
-}
-
-void WebMemoryAllocatorDumpImpl::addScalarF(const char* name,
- const char* units,
- double value) {
- memory_allocator_dump_->AddScalarF(name, units, value);
-}
-
-void WebMemoryAllocatorDumpImpl::addString(const char* name,
- const char* units,
- const blink::WebString& value) {
- memory_allocator_dump_->AddString(name, units, value.utf8());
-}
-
-blink::WebMemoryAllocatorDumpGuid WebMemoryAllocatorDumpImpl::guid() const {
- return guid_;
-}
-} // namespace content
diff --git a/chromium/content/child/web_memory_allocator_dump_impl.h b/chromium/content/child/web_memory_allocator_dump_impl.h
deleted file mode 100644
index d9724035203..00000000000
--- a/chromium/content/child/web_memory_allocator_dump_impl.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_CHILD_WEB_MEMORY_ALLOCATOR_DUMP_IMPL_H_
-#define CONTENT_CHILD_WEB_MEMORY_ALLOCATOR_DUMP_IMPL_H_
-
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "third_party/WebKit/public/platform/WebMemoryAllocatorDump.h"
-
-namespace base {
-namespace trace_event {
-class MemoryAllocatorDump;
-} // namespace base
-} // namespace trace_event
-
-namespace content {
-
-// Implements the blink::WebMemoryAllocatorDump interface by means of proxying
-// the Add*() calls to the underlying base::trace_event::MemoryAllocatorDump
-// instance.
-class WebMemoryAllocatorDumpImpl : public blink::WebMemoryAllocatorDump {
- public:
- explicit WebMemoryAllocatorDumpImpl(
- base::trace_event::MemoryAllocatorDump* memory_allocator_dump);
- ~WebMemoryAllocatorDumpImpl() override;
-
- // blink::WebMemoryAllocatorDump implementation.
- void addScalar(const char* name, const char* units, uint64_t value) override;
- void addScalarF(const char* name, const char* units, double value) override;
- void addString(const char* name,
- const char* units,
- const blink::WebString& value) override;
-
- blink::WebMemoryAllocatorDumpGuid guid() const override;
-
- private:
- base::trace_event::MemoryAllocatorDump* memory_allocator_dump_; // Not owned.
- blink::WebMemoryAllocatorDumpGuid guid_;
-
- DISALLOW_COPY_AND_ASSIGN(WebMemoryAllocatorDumpImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_WEB_MEMORY_ALLOCATOR_DUMP_IMPL_H_
diff --git a/chromium/content/child/web_memory_dump_provider_adapter.cc b/chromium/content/child/web_memory_dump_provider_adapter.cc
deleted file mode 100644
index 860424c0f37..00000000000
--- a/chromium/content/child/web_memory_dump_provider_adapter.cc
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/child/web_memory_dump_provider_adapter.h"
-
-#include <stddef.h>
-
-#include "base/containers/hash_tables.h"
-#include "base/lazy_instance.h"
-#include "base/synchronization/lock.h"
-#include "base/trace_event/heap_profiler_allocation_context.h"
-#include "base/trace_event/heap_profiler_allocation_context_tracker.h"
-#include "base/trace_event/heap_profiler_allocation_register.h"
-#include "base/trace_event/heap_profiler_heap_dump_writer.h"
-#include "base/trace_event/process_memory_dump.h"
-#include "base/trace_event/trace_event_argument.h"
-#include "base/trace_event/trace_event_memory_overhead.h"
-#include "content/child/web_process_memory_dump_impl.h"
-#include "third_party/WebKit/public/platform/WebMemoryDumpProvider.h"
-
-using namespace base;
-using namespace base::trace_event;
-
-namespace {
-
-// TODO(ruuda): Move these into the dump providers once Blink can depend on
-// base. See https://crbug.com/548254.
-AllocationRegister* g_allocation_register = nullptr;
-LazyInstance<Lock>::Leaky g_allocation_register_lock =
- LAZY_INSTANCE_INITIALIZER;
-bool g_heap_profiling_enabled = false;
-
-void ReportAllocation(void* address, size_t size, const char* type_name) {
- AllocationContext context = AllocationContextTracker::GetContextSnapshot();
- context.type_name = type_name;
- AutoLock lock(g_allocation_register_lock.Get());
-
- if (g_allocation_register)
- g_allocation_register->Insert(address, size, context);
-}
-
-void ReportFree(void* address) {
- AutoLock lock(g_allocation_register_lock.Get());
-
- if (g_allocation_register)
- g_allocation_register->Remove(address);
-}
-
-} // namespace
-
-namespace content {
-
-WebMemoryDumpProviderAdapter::WebMemoryDumpProviderAdapter(
- blink::WebMemoryDumpProvider* wmdp)
- : web_memory_dump_provider_(wmdp), is_registered_(false) {
-}
-
-WebMemoryDumpProviderAdapter::~WebMemoryDumpProviderAdapter() {
- DCHECK(!is_registered_);
-}
-
-bool WebMemoryDumpProviderAdapter::OnMemoryDump(
- const base::trace_event::MemoryDumpArgs& args,
- base::trace_event::ProcessMemoryDump* pmd) {
- blink::WebMemoryDumpLevelOfDetail level;
- switch (args.level_of_detail) {
- case base::trace_event::MemoryDumpLevelOfDetail::LIGHT:
- level = blink::WebMemoryDumpLevelOfDetail::Light;
- break;
- case base::trace_event::MemoryDumpLevelOfDetail::DETAILED:
- level = blink::WebMemoryDumpLevelOfDetail::Detailed;
- break;
- default:
- NOTREACHED();
- return false;
- }
- WebProcessMemoryDumpImpl web_pmd_impl(args.level_of_detail, pmd);
-
- if (args.level_of_detail == MemoryDumpLevelOfDetail::DETAILED &&
- web_memory_dump_provider_->supportsHeapProfiling() &&
- g_heap_profiling_enabled) {
- TraceEventMemoryOverhead overhead;
- hash_map<AllocationContext, size_t> bytes_by_context;
- {
- AutoLock lock(g_allocation_register_lock.Get());
- for (const auto& alloc_size : *g_allocation_register)
- bytes_by_context[alloc_size.context] += alloc_size.size;
-
- g_allocation_register->EstimateTraceMemoryOverhead(&overhead);
- }
-
- scoped_refptr<TracedValue> heap_dump = ExportHeapDump(
- bytes_by_context, pmd->session_state()->stack_frame_deduplicator(),
- pmd->session_state()->type_name_deduplicator());
- pmd->AddHeapDump("partition_alloc", heap_dump);
- overhead.DumpInto("tracing/heap_profiler", pmd);
- }
-
- return web_memory_dump_provider_->onMemoryDump(level, &web_pmd_impl);
-}
-
-void WebMemoryDumpProviderAdapter::OnHeapProfilingEnabled(bool enabled) {
- if (!web_memory_dump_provider_->supportsHeapProfiling())
- return;
-
- if (enabled) {
- {
- AutoLock lock(g_allocation_register_lock.Get());
- if (!g_allocation_register)
- g_allocation_register = new AllocationRegister();
- }
-
- // Make this dump provider call the global hooks on every allocation / free.
- // TODO(ruuda): Because bookkeeping is done here in the adapter, and not in
- // the dump providers themselves, all dump providers in Blink share the
- // same global allocation register. At the moment this is not a problem,
- // because the only dump provider that supports heap profiling is the
- // PartitionAlloc dump provider. When Blink can depend on base and this
- // glue layer is removed, dump providers can have their own instance of the
- // allocation register. Tracking bug: https://crbug.com/548254.
- web_memory_dump_provider_->onHeapProfilingEnabled(ReportAllocation,
- ReportFree);
- } else {
- web_memory_dump_provider_->onHeapProfilingEnabled(nullptr, nullptr);
- }
-
- g_heap_profiling_enabled = enabled;
-}
-
-} // namespace content
diff --git a/chromium/content/child/web_memory_dump_provider_adapter.h b/chromium/content/child/web_memory_dump_provider_adapter.h
deleted file mode 100644
index b1c0813869a..00000000000
--- a/chromium/content/child/web_memory_dump_provider_adapter.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_CHILD_WEB_MEMORY_DUMP_PROVIDER_ADAPTER_H_
-#define CONTENT_CHILD_WEB_MEMORY_DUMP_PROVIDER_ADAPTER_H_
-
-#include "base/macros.h"
-#include "base/trace_event/memory_dump_provider.h"
-
-namespace blink {
-class WebMemoryDumpProvider;
-} // namespace blink
-
-namespace content {
-
-// Adapter class which makes it possible to register a WebMemoryDumpProvider (
-// from blink) to base::trace_event::MemoryDumpManager, which expects a
-// MemoryDumpProvider instead.
-// This is essentially proxying the OnMemoryDump from chromium base to blink.
-class WebMemoryDumpProviderAdapter
- : public base::trace_event::MemoryDumpProvider {
- public:
- explicit WebMemoryDumpProviderAdapter(blink::WebMemoryDumpProvider* wmdp);
- ~WebMemoryDumpProviderAdapter() override;
-
- // base::trace_event::MemoryDumpProvider implementation.
- bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
- base::trace_event::ProcessMemoryDump* pmd) override;
-
- void OnHeapProfilingEnabled(bool enabled) override;
-
- bool is_registered() const { return is_registered_; }
- void set_is_registered(bool is_registered) { is_registered_ = is_registered; }
-
- private:
- // The underlying WebMemoryDumpProvider instance to which the OnMemoryDump()
- // calls will be proxied to.
- blink::WebMemoryDumpProvider* web_memory_dump_provider_; // Not owned.
-
- // True iff this has been registered with the MDM (and not unregistered yet).
- bool is_registered_;
-
- DISALLOW_COPY_AND_ASSIGN(WebMemoryDumpProviderAdapter);
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_WEB_MEMORY_DUMP_PROVIDER_ADAPTER_H_
diff --git a/chromium/content/child/web_process_memory_dump_impl.cc b/chromium/content/child/web_process_memory_dump_impl.cc
deleted file mode 100644
index c8c3ca78617..00000000000
--- a/chromium/content/child/web_process_memory_dump_impl.cc
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/child/web_process_memory_dump_impl.h"
-
-#include <stddef.h>
-
-#include "base/memory/discardable_memory.h"
-#include "base/trace_event/process_memory_dump.h"
-#include "content/child/web_memory_allocator_dump_impl.h"
-#include "skia/ext/skia_trace_memory_dump_impl.h"
-
-namespace content {
-
-WebProcessMemoryDumpImpl::WebProcessMemoryDumpImpl()
- : owned_process_memory_dump_(
- new base::trace_event::ProcessMemoryDump(nullptr)),
- process_memory_dump_(owned_process_memory_dump_.get()),
- level_of_detail_(base::trace_event::MemoryDumpLevelOfDetail::DETAILED) {}
-
-WebProcessMemoryDumpImpl::WebProcessMemoryDumpImpl(
- base::trace_event::MemoryDumpLevelOfDetail level_of_detail,
- base::trace_event::ProcessMemoryDump* process_memory_dump)
- : process_memory_dump_(process_memory_dump),
- level_of_detail_(level_of_detail) {}
-
-WebProcessMemoryDumpImpl::~WebProcessMemoryDumpImpl() {
-}
-
-blink::WebMemoryAllocatorDump*
-WebProcessMemoryDumpImpl::createMemoryAllocatorDump(
- const blink::WebString& absolute_name) {
- // Get a MemoryAllocatorDump from the base/ object.
- base::trace_event::MemoryAllocatorDump* memory_allocator_dump =
- process_memory_dump_->CreateAllocatorDump(absolute_name.utf8());
-
- return createWebMemoryAllocatorDump(memory_allocator_dump);
-}
-
-blink::WebMemoryAllocatorDump*
-WebProcessMemoryDumpImpl::createMemoryAllocatorDump(
- const blink::WebString& absolute_name,
- blink::WebMemoryAllocatorDumpGuid guid) {
- // Get a MemoryAllocatorDump from the base/ object with given guid.
- base::trace_event::MemoryAllocatorDump* memory_allocator_dump =
- process_memory_dump_->CreateAllocatorDump(
- absolute_name.utf8(),
- base::trace_event::MemoryAllocatorDumpGuid(guid));
- return createWebMemoryAllocatorDump(memory_allocator_dump);
-}
-
-blink::WebMemoryAllocatorDump*
-WebProcessMemoryDumpImpl::createWebMemoryAllocatorDump(
- base::trace_event::MemoryAllocatorDump* memory_allocator_dump) {
- if (!memory_allocator_dump)
- return nullptr;
-
- // Wrap it and return to blink.
- WebMemoryAllocatorDumpImpl* web_memory_allocator_dump_impl =
- new WebMemoryAllocatorDumpImpl(memory_allocator_dump);
-
- // memory_allocator_dumps_ will take ownership of
- // |web_memory_allocator_dumpd_impl|.
- memory_allocator_dumps_.set(memory_allocator_dump,
- make_scoped_ptr(web_memory_allocator_dump_impl));
- return web_memory_allocator_dump_impl;
-}
-
-blink::WebMemoryAllocatorDump* WebProcessMemoryDumpImpl::getMemoryAllocatorDump(
- const blink::WebString& absolute_name) const {
- // Retrieve the base MemoryAllocatorDump object and then reverse lookup
- // its wrapper.
- base::trace_event::MemoryAllocatorDump* memory_allocator_dump =
- process_memory_dump_->GetAllocatorDump(absolute_name.utf8());
- if (!memory_allocator_dump)
- return nullptr;
-
- // The only case of (memory_allocator_dump && !web_memory_allocator_dump)
- // is something from blink trying to get a MAD that was created from chromium,
- // which is an odd use case.
- blink::WebMemoryAllocatorDump* web_memory_allocator_dump =
- memory_allocator_dumps_.get(memory_allocator_dump);
- DCHECK(web_memory_allocator_dump);
- return web_memory_allocator_dump;
-}
-
-void WebProcessMemoryDumpImpl::clear() {
- // Clear all the WebMemoryAllocatorDump wrappers.
- memory_allocator_dumps_.clear();
-
- // Clear the actual MemoryAllocatorDump objects from the underlying PMD.
- process_memory_dump_->Clear();
-}
-
-void WebProcessMemoryDumpImpl::takeAllDumpsFrom(
- blink::WebProcessMemoryDump* other) {
- auto other_impl = static_cast<WebProcessMemoryDumpImpl*>(other);
- // WebProcessMemoryDumpImpl is a container of WebMemoryAllocatorDump(s) which
- // in turn are wrappers of base::trace_event::MemoryAllocatorDump(s).
- // In order to expose the move and ownership transfer semantics of the
- // underlying ProcessMemoryDump, we need to:
-
- // 1) Move and transfer the ownership of the wrapped
- // base::trace_event::MemoryAllocatorDump(s) instances.
- process_memory_dump_->TakeAllDumpsFrom(other_impl->process_memory_dump_);
-
- // 2) Move and transfer the ownership of the WebMemoryAllocatorDump wrappers.
- const size_t expected_final_size = memory_allocator_dumps_.size() +
- other_impl->memory_allocator_dumps_.size();
- while (!other_impl->memory_allocator_dumps_.empty()) {
- auto first_entry = other_impl->memory_allocator_dumps_.begin();
- base::trace_event::MemoryAllocatorDump* memory_allocator_dump =
- first_entry->first;
- memory_allocator_dumps_.set(
- memory_allocator_dump,
- other_impl->memory_allocator_dumps_.take_and_erase(first_entry));
- }
- DCHECK_EQ(expected_final_size, memory_allocator_dumps_.size());
- DCHECK(other_impl->memory_allocator_dumps_.empty());
-}
-
-void WebProcessMemoryDumpImpl::addOwnershipEdge(
- blink::WebMemoryAllocatorDumpGuid source,
- blink::WebMemoryAllocatorDumpGuid target,
- int importance) {
- process_memory_dump_->AddOwnershipEdge(
- base::trace_event::MemoryAllocatorDumpGuid(source),
- base::trace_event::MemoryAllocatorDumpGuid(target), importance);
-}
-
-void WebProcessMemoryDumpImpl::addOwnershipEdge(
- blink::WebMemoryAllocatorDumpGuid source,
- blink::WebMemoryAllocatorDumpGuid target) {
- process_memory_dump_->AddOwnershipEdge(
- base::trace_event::MemoryAllocatorDumpGuid(source),
- base::trace_event::MemoryAllocatorDumpGuid(target));
-}
-
-void WebProcessMemoryDumpImpl::addSuballocation(
- blink::WebMemoryAllocatorDumpGuid source,
- const blink::WebString& target_node_name) {
- process_memory_dump_->AddSuballocation(
- base::trace_event::MemoryAllocatorDumpGuid(source),
- target_node_name.utf8());
-}
-
-SkTraceMemoryDump* WebProcessMemoryDumpImpl::createDumpAdapterForSkia(
- const blink::WebString& dump_name_prefix) {
- sk_trace_dump_list_.push_back(new skia::SkiaTraceMemoryDumpImpl(
- dump_name_prefix.utf8(), level_of_detail_, process_memory_dump_));
- return sk_trace_dump_list_.back();
-}
-
-blink::WebMemoryAllocatorDump*
-WebProcessMemoryDumpImpl::CreateDiscardableMemoryAllocatorDump(
- const std::string& name,
- base::DiscardableMemory* discardable) {
- base::trace_event::MemoryAllocatorDump* dump =
- discardable->CreateMemoryAllocatorDump(name.c_str(),
- process_memory_dump_);
- return createWebMemoryAllocatorDump(dump);
-}
-
-} // namespace content
diff --git a/chromium/content/child/web_process_memory_dump_impl.h b/chromium/content/child/web_process_memory_dump_impl.h
deleted file mode 100644
index ff351434ea9..00000000000
--- a/chromium/content/child/web_process_memory_dump_impl.h
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_CHILD_WEB_PROCESS_MEMORY_DUMP_IMPL_H_
-#define CONTENT_CHILD_WEB_PROCESS_MEMORY_DUMP_IMPL_H_
-
-#include "base/containers/scoped_ptr_hash_map.h"
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/scoped_vector.h"
-#include "base/trace_event/memory_dump_request_args.h"
-#include "content/common/content_export.h"
-#include "third_party/WebKit/public/platform/WebProcessMemoryDump.h"
-
-namespace base {
-class DiscardableMemory;
-namespace trace_event {
-class MemoryAllocatorDump;
-class ProcessMemoryDump;
-} // namespace base
-} // namespace trace_event
-
-namespace skia {
-class SkiaTraceMemoryDumpImpl;
-} // namespace skia
-
-namespace content {
-
-class WebMemoryAllocatorDumpImpl;
-
-// Implements the blink::WebProcessMemoryDump interface by means of proxying the
-// calls to createMemoryAllocatorDump() to the underlying
-// base::trace_event::ProcessMemoryDump instance.
-class CONTENT_EXPORT WebProcessMemoryDumpImpl final
- : public NON_EXPORTED_BASE(blink::WebProcessMemoryDump) {
- public:
- // Creates a standalone WebProcessMemoryDumpImp, which owns the underlying
- // ProcessMemoryDump.
- WebProcessMemoryDumpImpl();
-
- // Wraps (without owning) an existing ProcessMemoryDump.
- explicit WebProcessMemoryDumpImpl(
- base::trace_event::MemoryDumpLevelOfDetail level_of_detail,
- base::trace_event::ProcessMemoryDump* process_memory_dump);
-
- ~WebProcessMemoryDumpImpl() override;
-
- // blink::WebProcessMemoryDump implementation.
- blink::WebMemoryAllocatorDump* createMemoryAllocatorDump(
- const blink::WebString& absolute_name) override;
- blink::WebMemoryAllocatorDump* createMemoryAllocatorDump(
- const blink::WebString& absolute_name,
- blink::WebMemoryAllocatorDumpGuid guid) override;
- blink::WebMemoryAllocatorDump* getMemoryAllocatorDump(
- const blink::WebString& absolute_name) const override;
- void clear() override;
- void takeAllDumpsFrom(blink::WebProcessMemoryDump* other) override;
- void addOwnershipEdge(blink::WebMemoryAllocatorDumpGuid source,
- blink::WebMemoryAllocatorDumpGuid target,
- int importance) override;
- void addOwnershipEdge(blink::WebMemoryAllocatorDumpGuid source,
- blink::WebMemoryAllocatorDumpGuid target) override;
- void addSuballocation(blink::WebMemoryAllocatorDumpGuid source,
- const blink::WebString& target_node_name) override;
- SkTraceMemoryDump* createDumpAdapterForSkia(
- const blink::WebString& dump_name_prefix) override;
-
- const base::trace_event::ProcessMemoryDump* process_memory_dump() const {
- return process_memory_dump_;
- }
-
- blink::WebMemoryAllocatorDump* CreateDiscardableMemoryAllocatorDump(
- const std::string& name,
- base::DiscardableMemory* discardable);
-
- private:
- FRIEND_TEST_ALL_PREFIXES(WebProcessMemoryDumpImplTest, IntegrationTest);
-
- blink::WebMemoryAllocatorDump* createWebMemoryAllocatorDump(
- base::trace_event::MemoryAllocatorDump* memory_allocator_dump);
-
- // Only for the case of ProcessMemoryDump being owned (i.e. the default ctor).
- scoped_ptr<base::trace_event::ProcessMemoryDump> owned_process_memory_dump_;
-
- // The underlying ProcessMemoryDump instance to which the
- // createMemoryAllocatorDump() calls will be proxied to.
- base::trace_event::ProcessMemoryDump* process_memory_dump_; // Not owned.
-
- // TODO(ssid): Remove it once this information is added to ProcessMemoryDump.
- base::trace_event::MemoryDumpLevelOfDetail level_of_detail_;
-
- // Reverse index of MemoryAllocatorDump -> WebMemoryAllocatorDumpImpl wrapper.
- // By design WebMemoryDumpProvider(s) are not supposed to hold the pointer
- // to the WebProcessMemoryDump passed as argument of the onMemoryDump() call.
- // Those pointers are valid only within the scope of the call and can be
- // safely torn down once the WebProcessMemoryDumpImpl itself is destroyed.
- base::ScopedPtrHashMap<base::trace_event::MemoryAllocatorDump*,
- scoped_ptr<WebMemoryAllocatorDumpImpl>>
- memory_allocator_dumps_;
-
- // Stores SkTraceMemoryDump for the current ProcessMemoryDump.
- ScopedVector<skia::SkiaTraceMemoryDumpImpl> sk_trace_dump_list_;
-
- DISALLOW_COPY_AND_ASSIGN(WebProcessMemoryDumpImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_CHILD_WEB_PROCESS_MEMORY_DUMP_IMPL_H_
diff --git a/chromium/content/child/web_process_memory_dump_impl_unittest.cc b/chromium/content/child/web_process_memory_dump_impl_unittest.cc
deleted file mode 100644
index 98860ff3af1..00000000000
--- a/chromium/content/child/web_process_memory_dump_impl_unittest.cc
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/child/web_process_memory_dump_impl.h"
-
-#include "base/trace_event/memory_allocator_dump.h"
-#include "base/trace_event/process_memory_dump.h"
-#include "base/trace_event/trace_event_argument.h"
-#include "base/values.h"
-#include "content/child/web_memory_allocator_dump_impl.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-// Tests that the Chromium<>Blink plumbing that exposes the MemoryInfra classes
-// behaves correctly, performs the right transfers of memory ownerships and
-// doesn't leak objects.
-TEST(WebProcessMemoryDumpImplTest, IntegrationTest) {
- scoped_refptr<base::trace_event::TracedValue> traced_value(
- new base::trace_event::TracedValue());
-
- scoped_ptr<WebProcessMemoryDumpImpl> wpmd1(new WebProcessMemoryDumpImpl());
- auto wmad1 = wpmd1->createMemoryAllocatorDump("1/1");
- auto wmad2 = wpmd1->createMemoryAllocatorDump("1/2");
- ASSERT_EQ(wmad1, wpmd1->getMemoryAllocatorDump("1/1"));
- ASSERT_EQ(wmad2, wpmd1->getMemoryAllocatorDump("1/2"));
-
- scoped_ptr<WebProcessMemoryDumpImpl> wpmd2(new WebProcessMemoryDumpImpl());
- wpmd2->createMemoryAllocatorDump("2/1");
- wpmd2->createMemoryAllocatorDump("2/2");
-
- wpmd1->takeAllDumpsFrom(wpmd2.get());
-
- // Make sure that wpmd2 still owns its own PMD, even if empty.
- ASSERT_NE(static_cast<base::trace_event::ProcessMemoryDump*>(nullptr),
- wpmd2->process_memory_dump_);
- ASSERT_EQ(wpmd2->owned_process_memory_dump_.get(),
- wpmd2->process_memory_dump());
- ASSERT_TRUE(wpmd2->process_memory_dump()->allocator_dumps().empty());
-
- // Make sure that wpmd2 is still usable after it has been emptied.
- auto wmad = wpmd2->createMemoryAllocatorDump("2/new");
- wmad->addScalar("attr_name", "bytes", 42);
- wmad->addScalarF("attr_name_2", "rate", 42.0f);
- ASSERT_EQ(1u, wpmd2->process_memory_dump()->allocator_dumps().size());
- auto mad = wpmd2->process_memory_dump()->GetAllocatorDump("2/new");
- ASSERT_NE(static_cast<base::trace_event::MemoryAllocatorDump*>(nullptr), mad);
- ASSERT_EQ(wmad, wpmd2->getMemoryAllocatorDump("2/new"));
-
- // Check that the attributes are propagated correctly.
- auto raw_attrs = mad->attributes_for_testing()->ToBaseValue();
- base::DictionaryValue* attrs = nullptr;
- ASSERT_TRUE(raw_attrs->GetAsDictionary(&attrs));
- base::DictionaryValue* attr = nullptr;
- ASSERT_TRUE(attrs->GetDictionary("attr_name", &attr));
- std::string attr_value;
- ASSERT_TRUE(attr->GetString("type", &attr_value));
- ASSERT_EQ(base::trace_event::MemoryAllocatorDump::kTypeScalar, attr_value);
- ASSERT_TRUE(attr->GetString("units", &attr_value));
- ASSERT_EQ("bytes", attr_value);
-
- ASSERT_TRUE(attrs->GetDictionary("attr_name_2", &attr));
- ASSERT_TRUE(attr->GetString("type", &attr_value));
- ASSERT_EQ(base::trace_event::MemoryAllocatorDump::kTypeScalar, attr_value);
- ASSERT_TRUE(attr->GetString("units", &attr_value));
- ASSERT_EQ("rate", attr_value);
- ASSERT_TRUE(attr->HasKey("value"));
-
- // Check that AsValueInto() doesn't cause a crash.
- wpmd2->process_memory_dump()->AsValueInto(traced_value.get());
-
- // Free the |wpmd2| to check that the memory ownership of the two MAD(s)
- // has been transferred to |wpmd1|.
- wpmd2.reset();
-
- // Now check that |wpmd1| has been effectively merged.
- ASSERT_EQ(4u, wpmd1->process_memory_dump()->allocator_dumps().size());
- ASSERT_EQ(1u, wpmd1->process_memory_dump()->allocator_dumps().count("1/1"));
- ASSERT_EQ(1u, wpmd1->process_memory_dump()->allocator_dumps().count("1/2"));
- ASSERT_EQ(1u, wpmd1->process_memory_dump()->allocator_dumps().count("2/1"));
- ASSERT_EQ(1u, wpmd1->process_memory_dump()->allocator_dumps().count("1/2"));
-
- // Check that also the WMAD wrappers got merged.
- blink::WebMemoryAllocatorDump* null_wmad = nullptr;
- ASSERT_NE(null_wmad, wpmd1->getMemoryAllocatorDump("1/1"));
- ASSERT_NE(null_wmad, wpmd1->getMemoryAllocatorDump("1/2"));
- ASSERT_NE(null_wmad, wpmd1->getMemoryAllocatorDump("2/1"));
- ASSERT_NE(null_wmad, wpmd1->getMemoryAllocatorDump("2/2"));
-
- // Check that AsValueInto() doesn't cause a crash.
- traced_value = new base::trace_event::TracedValue();
- wpmd1->process_memory_dump()->AsValueInto(traced_value.get());
-
- // Check that clear() actually works.
- wpmd1->clear();
- ASSERT_TRUE(wpmd1->process_memory_dump()->allocator_dumps().empty());
- ASSERT_EQ(nullptr, wpmd1->process_memory_dump()->GetAllocatorDump("1/1"));
- ASSERT_EQ(nullptr, wpmd1->process_memory_dump()->GetAllocatorDump("2/1"));
-
- // Check that AsValueInto() doesn't cause a crash.
- traced_value = new base::trace_event::TracedValue();
- wpmd1->process_memory_dump()->AsValueInto(traced_value.get());
-
- // Check if a WebMemoryAllocatorDump created with guid, has correct guid.
- blink::WebMemoryAllocatorDumpGuid guid =
- base::trace_event::MemoryAllocatorDumpGuid("id_1").ToUint64();
- auto wmad3 = wpmd1->createMemoryAllocatorDump("1/3", guid);
- ASSERT_EQ(wmad3->guid(), guid);
- ASSERT_EQ(wmad3, wpmd1->getMemoryAllocatorDump("1/3"));
-
- // Check that AddOwnershipEdge is propagated correctly.
- auto wmad4 = wpmd1->createMemoryAllocatorDump("1/4");
- wpmd1->addOwnershipEdge(wmad4->guid(), guid);
- auto allocator_dumps_edges =
- wpmd1->process_memory_dump()->allocator_dumps_edges();
- ASSERT_EQ(1u, allocator_dumps_edges.size());
- ASSERT_EQ(wmad4->guid(), allocator_dumps_edges[0].source.ToUint64());
- ASSERT_EQ(guid, allocator_dumps_edges[0].target.ToUint64());
-
- wpmd1.reset();
-}
-
-} // namespace content
diff --git a/chromium/content/child/web_url_loader_impl.cc b/chromium/content/child/web_url_loader_impl.cc
index b6fdd6a9393..2a8a3563cfb 100644
--- a/chromium/content/child/web_url_loader_impl.cc
+++ b/chromium/content/child/web_url_loader_impl.cc
@@ -5,14 +5,17 @@
#include "content/child/web_url_loader_impl.h"
#include <stdint.h>
+
#include <algorithm>
+#include <memory>
#include <string>
#include <utility>
+#include <vector>
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
+#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
@@ -21,7 +24,6 @@
#include "components/scheduler/child/web_task_runner_impl.h"
#include "content/child/child_thread_impl.h"
#include "content/child/ftp_directory_listing_response_delegate.h"
-#include "content/child/multipart_response_delegate.h"
#include "content/child/request_extra_data.h"
#include "content/child/request_info.h"
#include "content/child/resource_dispatcher.h"
@@ -36,9 +38,13 @@
#include "content/public/child/fixed_received_data.h"
#include "content/public/child/request_peer.h"
#include "content/public/common/browser_side_navigation_policy.h"
+#include "content/public/common/signed_certificate_timestamp_id_and_status.h"
+#include "content/public/common/ssl_status.h"
#include "net/base/data_url.h"
#include "net/base/filename_util.h"
#include "net/base/net_errors.h"
+#include "net/cert/cert_status_flags.h"
+#include "net/cert/sct_status_flags.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "net/ssl/ssl_cipher_suite_names.h"
@@ -78,6 +84,17 @@ namespace content {
namespace {
+// The list of response headers that we do not copy from the original
+// response when generating a WebURLResponse for a MIME payload.
+const char* const kReplaceHeaders[] = {
+ "content-type",
+ "content-length",
+ "content-disposition",
+ "content-range",
+ "range",
+ "set-cookie"
+};
+
using HeadersVector = ResourceDevToolsInfo::HeadersVector;
// Converts timing data from |load_timing| to the format used by WebKit.
@@ -237,29 +254,53 @@ void SetSecurityStyleAndDetails(const GURL& url,
response->setSecurityStyle(securityStyle);
- blink::WebString protocol_string = blink::WebString::fromUTF8(protocol);
- blink::WebString cipher_string = blink::WebString::fromUTF8(cipher);
- blink::WebString key_exchange_string =
- blink::WebString::fromUTF8(key_exchange);
- blink::WebString mac_string = blink::WebString::fromUTF8(mac);
- response->setSecurityDetails(protocol_string, key_exchange_string,
- cipher_string, mac_string,
- ssl_status.cert_id);
+ SignedCertificateTimestampIDStatusList sct_list =
+ ssl_status.signed_certificate_timestamp_ids;
+
+ size_t num_unknown_scts = 0;
+ size_t num_invalid_scts = 0;
+ size_t num_valid_scts = 0;
+
+ SignedCertificateTimestampIDStatusList::iterator iter;
+ for (iter = sct_list.begin(); iter < sct_list.end(); ++iter) {
+ switch (iter->status) {
+ case net::ct::SCT_STATUS_LOG_UNKNOWN:
+ num_unknown_scts++;
+ break;
+ case net::ct::SCT_STATUS_INVALID:
+ num_invalid_scts++;
+ break;
+ case net::ct::SCT_STATUS_OK:
+ num_valid_scts++;
+ break;
+ case net::ct::SCT_STATUS_NONE:
+ case net::ct::SCT_STATUS_MAX:
+ // These enum values do not represent SCTs that are taken into account
+ // for CT compliance calculations, so we ignore them.
+ break;
+ }
+ }
+
+ blink::WebURLResponse::WebSecurityDetails webSecurityDetails(
+ WebString::fromUTF8(protocol), WebString::fromUTF8(key_exchange),
+ WebString::fromUTF8(cipher), WebString::fromUTF8(mac),
+ ssl_status.cert_id, num_unknown_scts, num_invalid_scts, num_valid_scts);
+
+ response->setSecurityDetails(webSecurityDetails);
}
} // namespace
-// WebURLLoaderImpl::Context --------------------------------------------------
-
// This inner class exists since the WebURLLoader may be deleted while inside a
// call to WebURLLoaderClient. Refcounting is to keep the context from being
// deleted if it may have work to do after calling into the client.
-class WebURLLoaderImpl::Context : public base::RefCounted<Context>,
- public RequestPeer {
+class WebURLLoaderImpl::Context : public base::RefCounted<Context> {
public:
+ using ReceivedData = RequestPeer::ReceivedData;
+
Context(WebURLLoaderImpl* loader,
ResourceDispatcher* resource_dispatcher,
- scoped_ptr<blink::WebTaskRunner> task_runner);
+ std::unique_ptr<blink::WebTaskRunner> task_runner);
WebURLLoaderClient* client() const { return client_; }
void set_client(WebURLLoaderClient* client) { client_ = client; }
@@ -268,38 +309,27 @@ class WebURLLoaderImpl::Context : public base::RefCounted<Context>,
void SetDefersLoading(bool value);
void DidChangePriority(WebURLRequest::Priority new_priority,
int intra_priority_value);
- bool AttachThreadedDataReceiver(
- blink::WebThreadedDataReceiver* threaded_data_receiver);
void Start(const WebURLRequest& request,
SyncLoadResponse* sync_load_response);
- void SetWebTaskRunner(scoped_ptr<blink::WebTaskRunner> task_runner);
+ void SetWebTaskRunner(std::unique_ptr<blink::WebTaskRunner> task_runner);
- // RequestPeer methods:
- void OnUploadProgress(uint64_t position, uint64_t size) override;
+ void OnUploadProgress(uint64_t position, uint64_t size);
bool OnReceivedRedirect(const net::RedirectInfo& redirect_info,
- const ResourceResponseInfo& info) override;
- void OnReceivedResponse(const ResourceResponseInfo& info) override;
- void OnDownloadedData(int len, int encoded_data_length) override;
- void OnReceivedData(scoped_ptr<ReceivedData> data) override;
- void OnReceivedCachedMetadata(const char* data, int len) override;
+ const ResourceResponseInfo& info);
+ void OnReceivedResponse(const ResourceResponseInfo& info);
+ void OnDownloadedData(int len, int encoded_data_length);
+ void OnReceivedData(std::unique_ptr<ReceivedData> data);
+ void OnReceivedCachedMetadata(const char* data, int len);
void OnCompletedRequest(int error_code,
bool was_ignored_by_handler,
bool stale_copy_in_cache,
const std::string& security_info,
const base::TimeTicks& completion_time,
- int64_t total_transfer_size) override;
- void OnReceivedCompletedResponse(const ResourceResponseInfo& info,
- scoped_ptr<ReceivedData> data,
- int error_code,
- bool was_ignored_by_handler,
- bool stale_copy_in_cache,
- const std::string& security_info,
- const base::TimeTicks& completion_time,
- int64_t total_transfer_size) override;
+ int64_t total_transfer_size);
private:
friend class base::RefCounted<Context>;
- ~Context() override;
+ ~Context();
class HandleDataURLTask : public blink::WebTaskRunner::Task {
public:
@@ -324,21 +354,49 @@ class WebURLLoaderImpl::Context : public base::RefCounted<Context>,
WebURLRequest request_;
WebURLLoaderClient* client_;
ResourceDispatcher* resource_dispatcher_;
- scoped_ptr<blink::WebTaskRunner> web_task_runner_;
+ std::unique_ptr<blink::WebTaskRunner> web_task_runner_;
WebReferrerPolicy referrer_policy_;
- scoped_ptr<FtpDirectoryListingResponseDelegate> ftp_listing_delegate_;
- scoped_ptr<MultipartResponseDelegate> multipart_delegate_;
- scoped_ptr<StreamOverrideParameters> stream_override_;
- scoped_ptr<SharedMemoryDataConsumerHandle::Writer> body_stream_writer_;
+ std::unique_ptr<FtpDirectoryListingResponseDelegate> ftp_listing_delegate_;
+ std::unique_ptr<StreamOverrideParameters> stream_override_;
+ std::unique_ptr<SharedMemoryDataConsumerHandle::Writer> body_stream_writer_;
enum DeferState {NOT_DEFERRING, SHOULD_DEFER, DEFERRED_DATA};
DeferState defers_loading_;
int request_id_;
};
+// A thin wrapper class for Context to ensure its lifetime while it is
+// handling IPC messages coming from ResourceDispatcher. Owns one ref to
+// Context and held by ResourceDispatcher.
+class WebURLLoaderImpl::RequestPeerImpl : public RequestPeer {
+ public:
+ explicit RequestPeerImpl(Context* context);
+
+ // RequestPeer methods:
+ void OnUploadProgress(uint64_t position, uint64_t size) override;
+ bool OnReceivedRedirect(const net::RedirectInfo& redirect_info,
+ const ResourceResponseInfo& info) override;
+ void OnReceivedResponse(const ResourceResponseInfo& info) override;
+ void OnDownloadedData(int len, int encoded_data_length) override;
+ void OnReceivedData(std::unique_ptr<ReceivedData> data) override;
+ void OnReceivedCachedMetadata(const char* data, int len) override;
+ void OnCompletedRequest(int error_code,
+ bool was_ignored_by_handler,
+ bool stale_copy_in_cache,
+ const std::string& security_info,
+ const base::TimeTicks& completion_time,
+ int64_t total_transfer_size) override;
+
+ private:
+ scoped_refptr<Context> context_;
+ DISALLOW_COPY_AND_ASSIGN(RequestPeerImpl);
+};
+
+// WebURLLoaderImpl::Context --------------------------------------------------
+
WebURLLoaderImpl::Context::Context(
WebURLLoaderImpl* loader,
ResourceDispatcher* resource_dispatcher,
- scoped_ptr<blink::WebTaskRunner> web_task_runner)
+ std::unique_ptr<blink::WebTaskRunner> web_task_runner)
: loader_(loader),
client_(NULL),
resource_dispatcher_(resource_dispatcher),
@@ -357,11 +415,8 @@ void WebURLLoaderImpl::Context::Cancel() {
if (body_stream_writer_)
body_stream_writer_->Fail();
- // Ensure that we do not notify the multipart delegate anymore as it has
+ // Ensure that we do not notify the delegate anymore as it has
// its own pointer to the client.
- if (multipart_delegate_)
- multipart_delegate_->Cancel();
- // Ditto for the ftp delegate.
if (ftp_listing_delegate_)
ftp_listing_delegate_->Cancel();
@@ -397,39 +452,18 @@ void WebURLLoaderImpl::Context::DidChangePriority(
}
}
-bool WebURLLoaderImpl::Context::AttachThreadedDataReceiver(
- blink::WebThreadedDataReceiver* threaded_data_receiver) {
- if (request_id_ != -1) {
- return resource_dispatcher_->AttachThreadedDataReceiver(
- request_id_, threaded_data_receiver);
- }
-
- return false;
-}
-
void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
SyncLoadResponse* sync_load_response) {
DCHECK(request_id_ == -1);
request_ = request; // Save the request.
- if (request.extraData()) {
+ if (request.getExtraData()) {
RequestExtraData* extra_data =
- static_cast<RequestExtraData*>(request.extraData());
+ static_cast<RequestExtraData*>(request.getExtraData());
stream_override_ = extra_data->TakeStreamOverrideOwnership();
}
GURL url = request.url();
- // PlzNavigate: during navigation, the renderer should request a stream which
- // contains the body of the response. The request has already been made by the
- // browser.
- if (stream_override_.get()) {
- CHECK(IsBrowserSideNavigationEnabled());
- DCHECK(!sync_load_response);
- DCHECK_NE(WebURLRequest::FrameTypeNone, request.frameType());
- DCHECK_EQ("GET", request.httpMethod().latin1());
- url = stream_override_->stream_url;
- }
-
if (CanHandleDataURLRequestLocally()) {
if (sync_load_response) {
// This is a sync load. Do the work now.
@@ -452,7 +486,7 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
// tests load HTML directly through a data url which will be handled by the
// block above.
DCHECK(!IsBrowserSideNavigationEnabled() || stream_override_.get() ||
- request.frameType() == WebURLRequest::FrameTypeNone);
+ request.getFrameType() == WebURLRequest::FrameTypeNone);
GURL referrer_url(
request.httpHeaderField(WebString::fromUTF8("Referer")).latin1());
@@ -475,7 +509,8 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
request_info.load_flags = GetLoadFlagsForWebURLRequest(request);
request_info.enable_load_timing = true;
request_info.enable_upload_progress = request.reportUploadProgress();
- if (request.requestContext() == WebURLRequest::RequestContextXMLHttpRequest &&
+ if (request.getRequestContext() ==
+ WebURLRequest::RequestContextXMLHttpRequest &&
(url.has_username() || url.has_password())) {
request_info.do_not_prompt_for_login = true;
}
@@ -485,7 +520,7 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
request_info.requestor_pid = request.requestorProcessID();
request_info.request_type = WebURLRequestToResourceType(request);
request_info.priority =
- ConvertWebKitPriorityToNetPriority(request.priority());
+ ConvertWebKitPriorityToNetPriority(request.getPriority());
request_info.appcache_host_id = request.appCacheHostID();
request_info.routing_id = request.requestorID();
request_info.download_to_file = request.downloadToFile();
@@ -502,25 +537,40 @@ void WebURLLoaderImpl::Context::Start(const WebURLRequest& request,
GetRequestContextTypeForWebURLRequest(request);
request_info.fetch_frame_type =
GetRequestContextFrameTypeForWebURLRequest(request);
- request_info.extra_data = request.extraData();
+ request_info.extra_data = request.getExtraData();
request_info.report_raw_headers = request.reportRawHeaders();
request_info.loading_web_task_runner.reset(web_task_runner_->clone());
scoped_refptr<ResourceRequestBody> request_body =
GetRequestBodyForWebURLRequest(request).get();
+ // PlzNavigate: during navigation, the renderer should request a stream which
+ // contains the body of the response. The network request has already been
+ // made by the browser.
+ if (stream_override_.get()) {
+ CHECK(IsBrowserSideNavigationEnabled());
+ DCHECK(!sync_load_response);
+ DCHECK_NE(WebURLRequest::FrameTypeNone, request.getFrameType());
+ request_info.resource_body_stream_url = stream_override_->stream_url;
+ }
+
if (sync_load_response) {
+ DCHECK(defers_loading_ == NOT_DEFERRING);
resource_dispatcher_->StartSync(
request_info, request_body.get(), sync_load_response);
return;
}
request_id_ = resource_dispatcher_->StartAsync(
- request_info, request_body.get(), this);
+ request_info, request_body.get(),
+ base::WrapUnique(new WebURLLoaderImpl::RequestPeerImpl(this)));
+
+ if (defers_loading_ != NOT_DEFERRING)
+ resource_dispatcher_->SetDefersLoading(request_id_, true);
}
void WebURLLoaderImpl::Context::SetWebTaskRunner(
- scoped_ptr<blink::WebTaskRunner> web_task_runner) {
+ std::unique_ptr<blink::WebTaskRunner> web_task_runner) {
web_task_runner_ = std::move(web_task_runner);
}
@@ -547,9 +597,6 @@ bool WebURLLoaderImpl::Context::OnReceivedRedirect(
!info.was_fetched_via_service_worker,
&new_request);
- // Protect from deletion during call to willFollowRedirect.
- scoped_refptr<Context> protect(this);
-
client_->willFollowRedirect(loader_, new_request, response);
request_ = new_request;
@@ -599,11 +646,19 @@ void WebURLLoaderImpl::Context::OnReceivedResponse(
response.setMIMEType("text/html");
}
}
+ if (info.headers.get() && info.mime_type == "multipart/x-mixed-replace") {
+ std::string content_type;
+ info.headers->EnumerateHeader(NULL, "content-type", &content_type);
- // Prevent |this| from being destroyed if the client destroys the loader,
- // ether in didReceiveResponse, or when the multipart/ftp delegate calls into
- // it.
- scoped_refptr<Context> protect(this);
+ std::string mime_type;
+ std::string charset;
+ bool had_charset = false;
+ std::string boundary;
+ net::HttpUtil::ParseContentType(content_type, &mime_type, &charset,
+ &had_charset, &boundary);
+ base::TrimString(boundary, " \"", &boundary);
+ response.setMultipartBoundary(boundary.data(), boundary.size());
+ }
if (request_.useStreamOnResponse()) {
SharedMemoryDataConsumerHandle::BackpressureMode mode =
@@ -613,7 +668,7 @@ void WebURLLoaderImpl::Context::OnReceivedResponse(
mode = SharedMemoryDataConsumerHandle::kApplyBackpressure;
}
- auto read_handle = make_scoped_ptr(new SharedMemoryDataConsumerHandle(
+ auto read_handle = base::WrapUnique(new SharedMemoryDataConsumerHandle(
mode, base::Bind(&Context::CancelBodyStreaming, this),
&body_stream_writer_));
@@ -637,27 +692,7 @@ void WebURLLoaderImpl::Context::OnReceivedResponse(
return;
DCHECK(!ftp_listing_delegate_.get());
- DCHECK(!multipart_delegate_.get());
- if (info.headers.get() && info.mime_type == "multipart/x-mixed-replace") {
- std::string content_type;
- info.headers->EnumerateHeader(NULL, "content-type", &content_type);
-
- std::string mime_type;
- std::string charset;
- bool had_charset = false;
- std::string boundary;
- net::HttpUtil::ParseContentType(content_type, &mime_type, &charset,
- &had_charset, &boundary);
- base::TrimString(boundary, " \"", &boundary);
-
- // If there's no boundary, just handle the request normally. In the gecko
- // code, nsMultiMixedConv::OnStartRequest throws an exception.
- if (!boundary.empty()) {
- multipart_delegate_.reset(
- new MultipartResponseDelegate(client_, loader_, response, boundary));
- }
- } else if (info.mime_type == "text/vnd.chromium.ftp-dir" &&
- !show_raw_listing) {
+ if (info.mime_type == "text/vnd.chromium.ftp-dir" && !show_raw_listing) {
ftp_listing_delegate_.reset(
new FtpDirectoryListingResponseDelegate(client_, loader_, response));
}
@@ -669,7 +704,8 @@ void WebURLLoaderImpl::Context::OnDownloadedData(int len,
client_->didDownloadData(loader_, len, encoded_data_length);
}
-void WebURLLoaderImpl::Context::OnReceivedData(scoped_ptr<ReceivedData> data) {
+void WebURLLoaderImpl::Context::OnReceivedData(
+ std::unique_ptr<ReceivedData> data) {
const char* payload = data->payload();
int data_length = data->length();
int encoded_data_length = data->encoded_length();
@@ -678,29 +714,16 @@ void WebURLLoaderImpl::Context::OnReceivedData(scoped_ptr<ReceivedData> data) {
if (ftp_listing_delegate_) {
// The FTP listing delegate will make the appropriate calls to
- // client_->didReceiveData and client_->didReceiveResponse. Since the
- // delegate may want to do work after sending data to the delegate, keep
- // |this| and the delegate alive until it's finished handling the data.
- scoped_refptr<Context> protect(this);
+ // client_->didReceiveData and client_->didReceiveResponse.
ftp_listing_delegate_->OnReceivedData(payload, data_length);
- } else if (multipart_delegate_) {
- // The multipart delegate will make the appropriate calls to
- // client_->didReceiveData and client_->didReceiveResponse. Since the
- // delegate may want to do work after sending data to the delegate, keep
- // |this| and the delegate alive until it's finished handling the data.
- scoped_refptr<Context> protect(this);
- multipart_delegate_->OnReceivedData(payload, data_length,
- encoded_data_length);
} else {
- scoped_refptr<Context> protect(this);
// We dispatch the data even when |useStreamOnResponse()| is set, in order
// to make Devtools work.
client_->didReceiveData(loader_, payload, data_length, encoded_data_length);
if (request_.useStreamOnResponse()) {
- // We don't support ftp_listening_delegate_ and multipart_delegate_ for
- // now.
- // TODO(yhirano): Support ftp listening and multipart.
+ // We don't support ftp_listening_delegate_ for now.
+ // TODO(yhirano): Support ftp listening.
body_stream_writer_->AddData(std::move(data));
}
}
@@ -719,18 +742,9 @@ void WebURLLoaderImpl::Context::OnCompletedRequest(
const std::string& security_info,
const base::TimeTicks& completion_time,
int64_t total_transfer_size) {
- // The WebURLLoaderImpl may be deleted in any of the calls to the client or
- // the delegates below (As they also may call in to the client). Keep |this|
- // alive in that case, to avoid a crash. If that happens, the request will be
- // cancelled and |client_| will be set to NULL.
- scoped_refptr<Context> protect(this);
-
if (ftp_listing_delegate_) {
ftp_listing_delegate_->OnCompletedRequest();
ftp_listing_delegate_.reset(NULL);
- } else if (multipart_delegate_) {
- multipart_delegate_->OnCompletedRequest();
- multipart_delegate_.reset(NULL);
}
if (body_stream_writer_ && error_code != net::OK)
@@ -751,28 +765,9 @@ void WebURLLoaderImpl::Context::OnCompletedRequest(
}
}
-void WebURLLoaderImpl::Context::OnReceivedCompletedResponse(
- const ResourceResponseInfo& info,
- scoped_ptr<ReceivedData> data,
- int error_code,
- bool was_ignored_by_handler,
- bool stale_copy_in_cache,
- const std::string& security_info,
- const base::TimeTicks& completion_time,
- int64_t total_transfer_size) {
- scoped_refptr<Context> protect(this);
-
- OnReceivedResponse(info);
- if (data)
- OnReceivedData(std::move(data));
- OnCompletedRequest(error_code, was_ignored_by_handler, stale_copy_in_cache,
- security_info, completion_time, total_transfer_size);
-}
-
WebURLLoaderImpl::Context::~Context() {
// We must be already cancelled at this point.
- // TODO(kinuko): Replace this with DCHECK once we make sure this is safe.
- CHECK_LT(request_id_, 0);
+ DCHECK_LT(request_id_, 0);
}
void WebURLLoaderImpl::Context::CancelBodyStreaming() {
@@ -782,9 +777,6 @@ void WebURLLoaderImpl::Context::CancelBodyStreaming() {
if (ftp_listing_delegate_) {
ftp_listing_delegate_->OnCompletedRequest();
ftp_listing_delegate_.reset(NULL);
- } else if (multipart_delegate_) {
- multipart_delegate_->OnCompletedRequest();
- multipart_delegate_.reset(NULL);
}
if (body_stream_writer_) {
@@ -813,7 +805,7 @@ bool WebURLLoaderImpl::Context::CanHandleDataURLRequestLocally() const {
// Data url requests from object tags may need to be intercepted as streams
// and so need to be sent to the browser.
- if (request_.requestContext() == WebURLRequest::RequestContextObject)
+ if (request_.getRequestContext() == WebURLRequest::RequestContextObject)
return false;
// Optimize for the case where we can handle a data URL locally. We must
@@ -828,12 +820,12 @@ bool WebURLLoaderImpl::Context::CanHandleDataURLRequestLocally() const {
// to the browser. In tests resource_dispatcher_ can be null, and test pages
// need to be loaded locally.
if (resource_dispatcher_ &&
- request_.frameType() == WebURLRequest::FrameTypeTopLevel)
+ request_.getFrameType() == WebURLRequest::FrameTypeTopLevel)
return false;
#endif
- if (request_.frameType() != WebURLRequest::FrameTypeTopLevel &&
- request_.frameType() != WebURLRequest::FrameTypeNested)
+ if (request_.getFrameType() != WebURLRequest::FrameTypeTopLevel &&
+ request_.getFrameType() != WebURLRequest::FrameTypeNested)
return true;
std::string mime_type, unused_charset;
@@ -860,18 +852,68 @@ void WebURLLoaderImpl::Context::HandleDataURL() {
OnReceivedResponse(info);
if (!data.empty())
OnReceivedData(
- make_scoped_ptr(new FixedReceivedData(data.data(), data.size(), 0)));
+ base::WrapUnique(new FixedReceivedData(data.data(), data.size(), 0)));
}
OnCompletedRequest(error_code, false, false, info.security_info,
base::TimeTicks::Now(), 0);
}
+// WebURLLoaderImpl::RequestPeerImpl ------------------------------------------
+
+WebURLLoaderImpl::RequestPeerImpl::RequestPeerImpl(Context* context)
+ : context_(context) {}
+
+void WebURLLoaderImpl::RequestPeerImpl::OnUploadProgress(uint64_t position,
+ uint64_t size) {
+ context_->OnUploadProgress(position, size);
+}
+
+bool WebURLLoaderImpl::RequestPeerImpl::OnReceivedRedirect(
+ const net::RedirectInfo& redirect_info,
+ const ResourceResponseInfo& info) {
+ return context_->OnReceivedRedirect(redirect_info, info);
+}
+
+void WebURLLoaderImpl::RequestPeerImpl::OnReceivedResponse(
+ const ResourceResponseInfo& info) {
+ context_->OnReceivedResponse(info);
+}
+
+void WebURLLoaderImpl::RequestPeerImpl::OnDownloadedData(
+ int len,
+ int encoded_data_length) {
+ context_->OnDownloadedData(len, encoded_data_length);
+}
+
+void WebURLLoaderImpl::RequestPeerImpl::OnReceivedData(
+ std::unique_ptr<ReceivedData> data) {
+ context_->OnReceivedData(std::move(data));
+}
+
+void WebURLLoaderImpl::RequestPeerImpl::OnReceivedCachedMetadata(
+ const char* data,
+ int len) {
+ context_->OnReceivedCachedMetadata(data, len);
+}
+
+void WebURLLoaderImpl::RequestPeerImpl::OnCompletedRequest(
+ int error_code,
+ bool was_ignored_by_handler,
+ bool stale_copy_in_cache,
+ const std::string& security_info,
+ const base::TimeTicks& completion_time,
+ int64_t total_transfer_size) {
+ context_->OnCompletedRequest(error_code, was_ignored_by_handler,
+ stale_copy_in_cache, security_info,
+ completion_time, total_transfer_size);
+}
+
// WebURLLoaderImpl -----------------------------------------------------------
WebURLLoaderImpl::WebURLLoaderImpl(
ResourceDispatcher* resource_dispatcher,
- scoped_ptr<blink::WebTaskRunner> web_task_runner)
+ std::unique_ptr<blink::WebTaskRunner> web_task_runner)
: context_(
new Context(this, resource_dispatcher, std::move(web_task_runner))) {}
@@ -895,7 +937,7 @@ void WebURLLoaderImpl::PopulateURLResponse(const GURL& url,
response->setWasCached(!info.load_timing.request_start_time.is_null() &&
info.response_time < info.load_timing.request_start_time);
response->setRemoteIPAddress(
- WebString::fromUTF8(info.socket_address.host()));
+ WebString::fromUTF8(info.socket_address.HostForURL()));
response->setRemotePort(info.socket_address.port());
response->setConnectionID(info.load_timing.socket_log_id);
response->setConnectionReused(info.load_timing.socket_reused);
@@ -907,6 +949,10 @@ void WebURLLoaderImpl::PopulateURLResponse(const GURL& url,
response->setServiceWorkerResponseType(info.response_type_via_service_worker);
response->setOriginalURLViaServiceWorker(
info.original_url_via_service_worker);
+ response->setCacheStorageCacheName(
+ info.is_in_cache_storage
+ ? blink::WebString::fromUTF8(info.cache_storage_cache_name)
+ : blink::WebString());
SetSecurityStyleAndDetails(url, info.security_info, response,
report_security_info);
@@ -1003,7 +1049,7 @@ void WebURLLoaderImpl::PopulateURLResponse(const GURL& url,
response->setLastModifiedDate(time_val.ToDoubleT());
// Build up the header map.
- void* iter = NULL;
+ size_t iter = 0;
std::string name;
while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
response->addHTTPHeaderField(WebString::fromLatin1(name),
@@ -1024,12 +1070,12 @@ void WebURLLoaderImpl::PopulateURLRequestForRedirect(
redirect_info.new_first_party_for_cookies);
new_request->setDownloadToFile(request.downloadToFile());
new_request->setUseStreamOnResponse(request.useStreamOnResponse());
- new_request->setRequestContext(request.requestContext());
- new_request->setFrameType(request.frameType());
+ new_request->setRequestContext(request.getRequestContext());
+ new_request->setFrameType(request.getFrameType());
new_request->setSkipServiceWorker(skip_service_worker);
new_request->setShouldResetAppCache(request.shouldResetAppCache());
- new_request->setFetchRequestMode(request.fetchRequestMode());
- new_request->setFetchCredentialsMode(request.fetchCredentialsMode());
+ new_request->setFetchRequestMode(request.getFetchRequestMode());
+ new_request->setFetchCredentialsMode(request.getFetchCredentialsMode());
new_request->setHTTPReferrer(WebString::fromUTF8(redirect_info.new_referrer),
referrer_policy);
@@ -1088,16 +1134,59 @@ void WebURLLoaderImpl::didChangePriority(WebURLRequest::Priority new_priority,
context_->DidChangePriority(new_priority, intra_priority_value);
}
-bool WebURLLoaderImpl::attachThreadedDataReceiver(
- blink::WebThreadedDataReceiver* threaded_data_receiver) {
- return context_->AttachThreadedDataReceiver(threaded_data_receiver);
-}
-
void WebURLLoaderImpl::setLoadingTaskRunner(
blink::WebTaskRunner* loading_task_runner) {
// There's no guarantee on the lifetime of |loading_task_runner| so we take a
// copy.
- context_->SetWebTaskRunner(make_scoped_ptr(loading_task_runner->clone()));
+ context_->SetWebTaskRunner(base::WrapUnique(loading_task_runner->clone()));
+}
+
+// This function is implemented here because it uses net functions. it is
+// tested in
+// third_party/WebKit/Source/core/fetch/MultipartImageResourceParserTest.cpp.
+bool WebURLLoaderImpl::ParseMultipartHeadersFromBody(
+ const char* bytes,
+ size_t size,
+ blink::WebURLResponse* response,
+ size_t* end) {
+ int headers_end_pos =
+ net::HttpUtil::LocateEndOfAdditionalHeaders(bytes, size, 0);
+
+ if (headers_end_pos < 0)
+ return false;
+
+ *end = headers_end_pos;
+ // Eat headers and prepend a status line as is required by
+ // HttpResponseHeaders.
+ std::string headers("HTTP/1.1 200 OK\r\n");
+ headers.append(bytes, headers_end_pos);
+
+ scoped_refptr<net::HttpResponseHeaders> response_headers =
+ new net::HttpResponseHeaders(
+ net::HttpUtil::AssembleRawHeaders(headers.c_str(), headers.size()));
+
+ std::string mime_type;
+ response_headers->GetMimeType(&mime_type);
+ response->setMIMEType(WebString::fromUTF8(mime_type));
+
+ std::string charset;
+ response_headers->GetCharset(&charset);
+ response->setTextEncodingName(WebString::fromUTF8(charset));
+
+ // Copy headers listed in kReplaceHeaders to the response.
+ for (size_t i = 0; i < arraysize(kReplaceHeaders); ++i) {
+ std::string name(kReplaceHeaders[i]);
+ std::string value;
+ WebString webStringName(WebString::fromLatin1(name));
+ size_t iterator = 0;
+
+ response->clearHTTPHeaderField(webStringName);
+ while (response_headers->EnumerateHeader(&iterator, name, &value)) {
+ response->addHTTPHeaderField(webStringName,
+ WebString::fromLatin1(value));
+ }
+ }
+ return true;
}
} // namespace content
diff --git a/chromium/content/child/web_url_loader_impl.h b/chromium/content/child/web_url_loader_impl.h
index b31b57e3c7e..d1f4f81064f 100644
--- a/chromium/content/child/web_url_loader_impl.h
+++ b/chromium/content/child/web_url_loader_impl.h
@@ -39,7 +39,7 @@ class CONTENT_EXPORT WebURLLoaderImpl
// Takes ownership of |web_task_runner|.
WebURLLoaderImpl(ResourceDispatcher* resource_dispatcher,
- scoped_ptr<blink::WebTaskRunner> web_task_runner);
+ std::unique_ptr<blink::WebTaskRunner> web_task_runner);
~WebURLLoaderImpl() override;
static void PopulateURLResponse(const GURL& url,
@@ -66,12 +66,17 @@ class CONTENT_EXPORT WebURLLoaderImpl
void setDefersLoading(bool value) override;
void didChangePriority(blink::WebURLRequest::Priority new_priority,
int intra_priority_value) override;
- bool attachThreadedDataReceiver(
- blink::WebThreadedDataReceiver* threaded_data_receiver) override;
void setLoadingTaskRunner(blink::WebTaskRunner* loading_task_runner) override;
+ // This is a utility function for multipart image resources.
+ static bool ParseMultipartHeadersFromBody(const char* bytes,
+ size_t size,
+ blink::WebURLResponse* response,
+ size_t* end);
+
private:
class Context;
+ class RequestPeerImpl;
scoped_refptr<Context> context_;
DISALLOW_COPY_AND_ASSIGN(WebURLLoaderImpl);
diff --git a/chromium/content/child/web_url_loader_impl_unittest.cc b/chromium/content/child/web_url_loader_impl_unittest.cc
index 10676a0a8ae..ac54c49a11b 100644
--- a/chromium/content/child/web_url_loader_impl_unittest.cc
+++ b/chromium/content/child/web_url_loader_impl_unittest.cc
@@ -6,16 +6,21 @@
#include <stdint.h>
#include <string.h>
+
#include <utility>
#include <vector>
#include "base/command_line.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
+#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
+#include "components/scheduler/child/scheduler_tqm_delegate_impl.h"
#include "components/scheduler/child/web_task_runner_impl.h"
+#include "components/scheduler/child/worker_scheduler.h"
#include "content/child/request_extra_data.h"
#include "content/child/request_info.h"
#include "content/child/resource_dispatcher.h"
@@ -23,6 +28,7 @@
#include "content/public/child/request_peer.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/resource_response_info.h"
+#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
@@ -49,27 +55,12 @@ const char kFtpDirListing[] =
"drwxr-xr-x 3 ftp ftp 4096 May 15 18:11 goat\n"
"drwxr-xr-x 3 ftp ftp 4096 May 15 18:11 hat";
-const char kMultipartResponseMimeType[] = "multipart/x-mixed-replace";
-const char kMultipartResponseHeaders[] =
- "HTTP/1.0 200 Peachy\r\n"
- "Content-Type: multipart/x-mixed-replace; boundary=boundary\r\n\r\n";
-// Simple multipart response. Imporant details for the tests are that it
-// contains multiple chunks, and that it doesn't end with a boundary, so will
-// send data in OnResponseComplete. Also, it will resolve to kTestData.
-const char kMultipartResponse[] =
- "--boundary\n"
- "Content-type: text/html\n\n"
- "bl"
- "--boundary\n"
- "Content-type: text/html\n\n"
- "ah!";
-
class TestResourceDispatcher : public ResourceDispatcher {
public:
TestResourceDispatcher() :
ResourceDispatcher(nullptr, nullptr),
- peer_(NULL),
- canceled_(false) {
+ canceled_(false),
+ defers_loading_(false) {
}
~TestResourceDispatcher() override {}
@@ -78,10 +69,11 @@ class TestResourceDispatcher : public ResourceDispatcher {
int StartAsync(const RequestInfo& request_info,
ResourceRequestBody* request_body,
- RequestPeer* peer) override {
+ std::unique_ptr<RequestPeer> peer) override {
EXPECT_FALSE(peer_);
- peer_ = peer;
+ peer_ = std::move(peer);
url_ = request_info.url;
+ stream_url_ = request_info.resource_body_stream_url;
return 1;
}
@@ -90,30 +82,35 @@ class TestResourceDispatcher : public ResourceDispatcher {
canceled_ = true;
}
- RequestPeer* peer() { return peer_; }
+ RequestPeer* peer() { return peer_.get(); }
bool canceled() { return canceled_; }
const GURL& url() { return url_; }
+ const GURL& stream_url() { return stream_url_; }
+
+ void SetDefersLoading(int request_id, bool value) override {
+ defers_loading_ = value;
+ }
+ bool defers_loading() const { return defers_loading_; }
private:
- RequestPeer* peer_;
+ std::unique_ptr<RequestPeer> peer_;
bool canceled_;
+ bool defers_loading_;
GURL url_;
+ GURL stream_url_;
DISALLOW_COPY_AND_ASSIGN(TestResourceDispatcher);
};
class TestWebURLLoaderClient : public blink::WebURLLoaderClient {
public:
- TestWebURLLoaderClient(
- ResourceDispatcher* dispatcher,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
- : loader_(
- new WebURLLoaderImpl(
- dispatcher,
- make_scoped_ptr(new scheduler::WebTaskRunnerImpl(task_runner)))),
- expect_multipart_response_(false),
+ TestWebURLLoaderClient(ResourceDispatcher* dispatcher,
+ scoped_refptr<scheduler::TaskQueue> task_runner)
+ : loader_(new WebURLLoaderImpl(
+ dispatcher,
+ base::WrapUnique(new scheduler::WebTaskRunnerImpl(task_runner)))),
delete_on_receive_redirect_(false),
delete_on_receive_response_(false),
delete_on_receive_data_(false),
@@ -152,9 +149,7 @@ class TestWebURLLoaderClient : public blink::WebURLLoaderClient {
const blink::WebURLResponse& response) override {
EXPECT_TRUE(loader_);
EXPECT_EQ(loader_.get(), loader);
-
- // Only multipart requests may receive multiple response headers.
- EXPECT_TRUE(expect_multipart_response_ || !did_receive_response_);
+ EXPECT_FALSE(did_receive_response_);
did_receive_response_ = true;
response_ = response;
@@ -222,8 +217,6 @@ class TestWebURLLoaderClient : public blink::WebURLLoaderClient {
loader_.reset();
}
- void set_expect_multipart_response() { expect_multipart_response_ = true; }
-
void set_delete_on_receive_redirect() { delete_on_receive_redirect_ = true; }
void set_delete_on_receive_response() { delete_on_receive_response_ = true; }
void set_delete_on_receive_data() { delete_on_receive_data_ = true; }
@@ -238,9 +231,7 @@ class TestWebURLLoaderClient : public blink::WebURLLoaderClient {
const blink::WebURLResponse& response() const { return response_; }
private:
- scoped_ptr<WebURLLoaderImpl> loader_;
-
- bool expect_multipart_response_;
+ std::unique_ptr<WebURLLoaderImpl> loader_;
bool delete_on_receive_redirect_;
bool delete_on_receive_response_;
@@ -261,7 +252,15 @@ class TestWebURLLoaderClient : public blink::WebURLLoaderClient {
class WebURLLoaderImplTest : public testing::Test {
public:
explicit WebURLLoaderImplTest()
- : client_(&dispatcher_, message_loop_.task_runner()) {}
+ : worker_scheduler_(scheduler::WorkerScheduler::Create(
+ scheduler::SchedulerTqmDelegateImpl::Create(
+ &message_loop_,
+ base::WrapUnique(new base::DefaultTickClock())))) {
+ worker_scheduler_->Init();
+ client_.reset(new TestWebURLLoaderClient(
+ &dispatcher_, worker_scheduler_->DefaultTaskRunner()));
+ }
+
~WebURLLoaderImplTest() override {}
void DoStartAsyncRequest() {
@@ -293,7 +292,7 @@ class WebURLLoaderImplTest : public testing::Test {
// Assumes it is called only once for a request.
void DoReceiveData() {
EXPECT_EQ("", client()->received_data());
- peer()->OnReceivedData(make_scoped_ptr(new FixedReceivedData(
+ peer()->OnReceivedData(base::WrapUnique(new FixedReceivedData(
kTestData, strlen(kTestData), strlen(kTestData))));
EXPECT_EQ(kTestData, client()->received_data());
}
@@ -308,23 +307,6 @@ class WebURLLoaderImplTest : public testing::Test {
EXPECT_EQ("", client()->error().domain.utf8());
}
- void DoReceiveCompletedResponse() {
- EXPECT_FALSE(client()->did_receive_response());
- EXPECT_EQ("", client()->received_data());
- EXPECT_FALSE(client()->did_finish());
-
- peer()->OnReceivedCompletedResponse(
- content::ResourceResponseInfo(),
- make_scoped_ptr(new FixedReceivedData(kTestData, strlen(kTestData),
- strlen(kTestData))),
- net::OK, false, false, "", base::TimeTicks(), strlen(kTestData));
-
- EXPECT_TRUE(client()->did_receive_response());
- EXPECT_EQ(kTestData, client()->received_data());
- EXPECT_EQ(net::OK, client()->error().reason);
- EXPECT_EQ("", client()->error().domain.utf8());
- }
-
void DoFailRequest() {
EXPECT_FALSE(client()->did_finish());
peer()->OnCompletedRequest(net::ERR_FAILED, false, false, "",
@@ -343,40 +325,24 @@ class WebURLLoaderImplTest : public testing::Test {
}
void DoReceiveDataFtp() {
- peer()->OnReceivedData(make_scoped_ptr(new FixedReceivedData(
+ peer()->OnReceivedData(base::WrapUnique(new FixedReceivedData(
kFtpDirListing, strlen(kFtpDirListing), strlen(kFtpDirListing))));
// The FTP delegate should modify the data the client sees.
EXPECT_NE(kFtpDirListing, client()->received_data());
}
- void DoReceiveResponseMultipart() {
- EXPECT_FALSE(client()->did_receive_response());
- content::ResourceResponseInfo response_info;
- response_info.headers = new net::HttpResponseHeaders(
- net::HttpUtil::AssembleRawHeaders(kMultipartResponseHeaders,
- strlen(kMultipartResponseHeaders)));
- response_info.mime_type = kMultipartResponseMimeType;
- peer()->OnReceivedResponse(response_info);
- EXPECT_TRUE(client()->did_receive_response());
- }
-
- void DoReceiveDataMultipart() {
- peer()->OnReceivedData(make_scoped_ptr(
- new FixedReceivedData(kMultipartResponse, strlen(kMultipartResponse),
- strlen(kMultipartResponse))));
- // Multipart delegate should modify the data the client sees.
- EXPECT_NE(kMultipartResponse, client()->received_data());
- }
-
- TestWebURLLoaderClient* client() { return &client_; }
+ TestWebURLLoaderClient* client() { return client_.get(); }
TestResourceDispatcher* dispatcher() { return &dispatcher_; }
RequestPeer* peer() { return dispatcher()->peer(); }
base::MessageLoop* message_loop() { return &message_loop_; }
private:
base::MessageLoop message_loop_;
+ // WorkerScheduler is needed because WebURLLoaderImpl needs a
+ // scheduler::TaskQueue.
+ std::unique_ptr<scheduler::WorkerScheduler> worker_scheduler_;
TestResourceDispatcher dispatcher_;
- TestWebURLLoaderClient client_;
+ std::unique_ptr<TestWebURLLoaderClient> client_;
};
TEST_F(WebURLLoaderImplTest, Success) {
@@ -406,13 +372,6 @@ TEST_F(WebURLLoaderImplTest, Failure) {
EXPECT_FALSE(dispatcher()->canceled());
}
-TEST_F(WebURLLoaderImplTest, ReceiveCompletedResponse) {
- DoStartAsyncRequest();
- DoReceiveCompletedResponse();
- EXPECT_FALSE(dispatcher()->canceled());
- EXPECT_EQ(kTestData, client()->received_data());
-}
-
// The client may delete the WebURLLoader during any callback from the loader.
// These tests make sure that doesn't result in a crash.
TEST_F(WebURLLoaderImplTest, DeleteOnReceiveRedirect) {
@@ -548,6 +507,13 @@ TEST_F(WebURLLoaderImplTest, DataURLDefersLoading) {
EXPECT_EQ("", client()->error().domain.utf8());
}
+TEST_F(WebURLLoaderImplTest, DefersLoadingBeforeStart) {
+ client()->loader()->setDefersLoading(true);
+ EXPECT_FALSE(dispatcher()->defers_loading());
+ DoStartAsyncRequest();
+ EXPECT_TRUE(dispatcher()->defers_loading());
+}
+
// FTP integration tests. These are focused more on safe deletion than correct
// parsing of FTP responses.
@@ -605,90 +571,19 @@ TEST_F(WebURLLoaderImplTest, FtpDeleteOnFail) {
DoFailRequest();
}
-// Multipart integration tests. These are focused more on safe deletion than
-// correct parsing of Multipart responses.
-
-TEST_F(WebURLLoaderImplTest, Multipart) {
- client()->set_expect_multipart_response();
- DoStartAsyncRequest();
- DoReceiveResponseMultipart();
- DoReceiveDataMultipart();
- DoCompleteRequest();
- EXPECT_EQ(kTestData, client()->received_data());
- EXPECT_FALSE(dispatcher()->canceled());
-}
-
-TEST_F(WebURLLoaderImplTest, MultipartDeleteOnReceiveFirstResponse) {
- client()->set_expect_multipart_response();
- client()->set_delete_on_receive_response();
- DoStartAsyncRequest();
- DoReceiveResponseMultipart();
- EXPECT_EQ("", client()->received_data());
-}
-
-TEST_F(WebURLLoaderImplTest, MultipartDeleteOnReceiveSecondResponse) {
- client()->set_expect_multipart_response();
- DoStartAsyncRequest();
- DoReceiveResponseMultipart();
- client()->set_delete_on_receive_response();
- DoReceiveDataMultipart();
- EXPECT_EQ("", client()->received_data());
-}
-
-TEST_F(WebURLLoaderImplTest, MultipartDeleteOnReceiveFirstData) {
- client()->set_expect_multipart_response();
- client()->set_delete_on_receive_data();
- DoStartAsyncRequest();
- DoReceiveResponseMultipart();
- DoReceiveDataMultipart();
- EXPECT_EQ("bl", client()->received_data());
-}
-
-TEST_F(WebURLLoaderImplTest, MultipartDeleteOnReceiveMoreData) {
- client()->set_expect_multipart_response();
- DoStartAsyncRequest();
- DoReceiveResponseMultipart();
- DoReceiveDataMultipart();
- // For multipart responses, the delegate may send some data when notified
- // of a request completing.
- client()->set_delete_on_receive_data();
- peer()->OnCompletedRequest(net::OK, false, false, "", base::TimeTicks(),
- strlen(kTestData));
- EXPECT_FALSE(client()->did_finish());
- EXPECT_EQ(kTestData, client()->received_data());
-}
-
-TEST_F(WebURLLoaderImplTest, MultipartDeleteFinish) {
- client()->set_expect_multipart_response();
- client()->set_delete_on_finish();
- DoStartAsyncRequest();
- DoReceiveResponseMultipart();
- DoReceiveDataMultipart();
- DoCompleteRequest();
- EXPECT_EQ(kTestData, client()->received_data());
-}
-
-TEST_F(WebURLLoaderImplTest, MultipartDeleteFail) {
- client()->set_expect_multipart_response();
- client()->set_delete_on_fail();
- DoStartAsyncRequest();
- DoReceiveResponseMultipart();
- DoReceiveDataMultipart();
- DoFailRequest();
-}
-
// PlzNavigate: checks that the stream override parameters provided on
// navigation commit are properly applied.
TEST_F(WebURLLoaderImplTest, BrowserSideNavigationCommit) {
// Initialize the request and the stream override.
+ const GURL kNavigationURL = GURL(kTestURL);
const GURL kStreamURL = GURL("http://bar");
const std::string kMimeType = "text/html";
blink::WebURLRequest request;
request.initialize();
- request.setURL(GURL(kTestURL));
+ request.setURL(kNavigationURL);
request.setFrameType(blink::WebURLRequest::FrameTypeTopLevel);
request.setRequestContext(blink::WebURLRequest::RequestContextFrame);
- scoped_ptr<StreamOverrideParameters> stream_override(
+ std::unique_ptr<StreamOverrideParameters> stream_override(
new StreamOverrideParameters());
stream_override->stream_url = kStreamURL;
stream_override->response.mime_type = kMimeType;
@@ -700,9 +595,10 @@ TEST_F(WebURLLoaderImplTest, BrowserSideNavigationCommit) {
client()->loader()->loadAsynchronously(request, client());
- // The stream url should have been requestead instead of the request url.
+ // The stream url should have been added to the RequestInfo.
ASSERT_TRUE(peer());
- EXPECT_EQ(kStreamURL, dispatcher()->url());
+ EXPECT_EQ(kNavigationURL, dispatcher()->url());
+ EXPECT_EQ(kStreamURL, dispatcher()->stream_url());
EXPECT_FALSE(client()->did_receive_response());
peer()->OnReceivedResponse(content::ResourceResponseInfo());
@@ -718,5 +614,32 @@ TEST_F(WebURLLoaderImplTest, BrowserSideNavigationCommit) {
EXPECT_EQ(kTestData, client()->received_data());
}
+TEST_F(WebURLLoaderImplTest, ResponseIPAddress) {
+ GURL url("http://example.test/");
+
+ struct TestCase {
+ const char* ip;
+ const char* expected;
+ } cases[] = {
+ {"127.0.0.1", "127.0.0.1"},
+ {"123.123.123.123", "123.123.123.123"},
+ {"::1", "[::1]"},
+ {"2001:0db8:85a3:0000:0000:8a2e:0370:7334",
+ "[2001:0db8:85a3:0000:0000:8a2e:0370:7334]"},
+ {"2001:db8:85a3:0:0:8a2e:370:7334", "[2001:db8:85a3:0:0:8a2e:370:7334]"},
+ {"2001:db8:85a3::8a2e:370:7334", "[2001:db8:85a3::8a2e:370:7334]"},
+ {"::ffff:192.0.2.128", "[::ffff:192.0.2.128]"}};
+
+ for (const auto& test : cases) {
+ SCOPED_TRACE(test.ip);
+ content::ResourceResponseInfo info;
+ info.socket_address = net::HostPortPair(test.ip, 443);
+ blink::WebURLResponse response;
+ response.initialize();
+ WebURLLoaderImpl::PopulateURLResponse(url, info, &response, true);
+ EXPECT_EQ(test.expected, response.remoteIPAddress().utf8());
+ };
+}
+
} // namespace
} // namespace content
diff --git a/chromium/content/child/web_url_request_util.cc b/chromium/content/child/web_url_request_util.cc
index 167725a09fd..5f14fbb4d9a 100644
--- a/chromium/content/child/web_url_request_util.cc
+++ b/chromium/content/child/web_url_request_util.cc
@@ -13,12 +13,15 @@
#include "base/strings/string_util.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
+#include "third_party/WebKit/public/platform/FilePathConversion.h"
+#include "third_party/WebKit/public/platform/WebCachePolicy.h"
#include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/WebURLError.h"
#include "third_party/WebKit/public/platform/WebURLRequest.h"
+using blink::WebCachePolicy;
using blink::WebHTTPBody;
using blink::WebString;
using blink::WebURLRequest;
@@ -33,7 +36,7 @@ const char kThrottledErrorDescription[] =
class HeaderFlattener : public blink::WebHTTPHeaderVisitor {
public:
- HeaderFlattener() : has_accept_header_(false) {}
+ HeaderFlattener() {}
void visitHeader(const WebString& name, const WebString& value) override {
// Headers are latin1.
@@ -45,47 +48,35 @@ class HeaderFlattener : public blink::WebHTTPHeaderVisitor {
if (base::LowerCaseEqualsASCII(name_latin1, "referer"))
return;
- if (base::LowerCaseEqualsASCII(name_latin1, "accept"))
- has_accept_header_ = true;
-
if (!buffer_.empty())
buffer_.append("\r\n");
buffer_.append(name_latin1 + ": " + value_latin1);
}
const std::string& GetBuffer() {
- // In some cases, WebKit doesn't add an Accept header, but not having the
- // header confuses some web servers. See bug 808613.
- if (!has_accept_header_) {
- if (!buffer_.empty())
- buffer_.append("\r\n");
- buffer_.append("Accept: */*");
- has_accept_header_ = true;
- }
return buffer_;
}
private:
std::string buffer_;
- bool has_accept_header_;
};
} // namespace
ResourceType WebURLRequestToResourceType(const WebURLRequest& request) {
- WebURLRequest::RequestContext requestContext = request.requestContext();
- if (request.frameType() != WebURLRequest::FrameTypeNone) {
+ WebURLRequest::RequestContext requestContext = request.getRequestContext();
+ if (request.getFrameType() != WebURLRequest::FrameTypeNone) {
DCHECK(requestContext == WebURLRequest::RequestContextForm ||
requestContext == WebURLRequest::RequestContextFrame ||
requestContext == WebURLRequest::RequestContextHyperlink ||
requestContext == WebURLRequest::RequestContextIframe ||
requestContext == WebURLRequest::RequestContextInternal ||
requestContext == WebURLRequest::RequestContextLocation);
- if (request.frameType() == WebURLRequest::FrameTypeTopLevel ||
- request.frameType() == WebURLRequest::FrameTypeAuxiliary) {
+ if (request.getFrameType() == WebURLRequest::FrameTypeTopLevel ||
+ request.getFrameType() == WebURLRequest::FrameTypeAuxiliary) {
return RESOURCE_TYPE_MAIN_FRAME;
}
- if (request.frameType() == WebURLRequest::FrameTypeNested)
+ if (request.getFrameType() == WebURLRequest::FrameTypeNested)
return RESOURCE_TYPE_SUB_FRAME;
NOTREACHED();
return RESOURCE_TYPE_SUB_RESOURCE;
@@ -196,21 +187,20 @@ std::string GetWebURLRequestHeaders(const blink::WebURLRequest& request) {
int GetLoadFlagsForWebURLRequest(const blink::WebURLRequest& request) {
int load_flags = net::LOAD_NORMAL;
GURL url = request.url();
- switch (request.cachePolicy()) {
- case WebURLRequest::ReloadIgnoringCacheData:
- // Required by LayoutTests/http/tests/misc/refresh-headers.php
+ switch (request.getCachePolicy()) {
+ case WebCachePolicy::ValidatingCacheData:
load_flags |= net::LOAD_VALIDATE_CACHE;
break;
- case WebURLRequest::ReloadBypassingCache:
+ case WebCachePolicy::BypassingCache:
load_flags |= net::LOAD_BYPASS_CACHE;
break;
- case WebURLRequest::ReturnCacheDataElseLoad:
+ case WebCachePolicy::ReturnCacheDataElseLoad:
load_flags |= net::LOAD_PREFERRING_CACHE;
break;
- case WebURLRequest::ReturnCacheDataDontLoad:
+ case WebCachePolicy::ReturnCacheDataDontLoad:
load_flags |= net::LOAD_ONLY_FROM_CACHE;
break;
- case WebURLRequest::UseProtocolCachePolicy:
+ case WebCachePolicy::UseProtocolCachePolicy:
break;
default:
NOTREACHED();
@@ -256,11 +246,11 @@ scoped_refptr<ResourceRequestBody> GetRequestBodyForWebURLRequest(
case WebHTTPBody::Element::TypeFile:
if (element.fileLength == -1) {
request_body->AppendFileRange(
- base::FilePath::FromUTF16Unsafe(element.filePath), 0,
+ blink::WebStringToFilePath(element.filePath), 0,
std::numeric_limits<uint64_t>::max(), base::Time());
} else {
request_body->AppendFileRange(
- base::FilePath::FromUTF16Unsafe(element.filePath),
+ blink::WebStringToFilePath(element.filePath),
static_cast<uint64_t>(element.fileStart),
static_cast<uint64_t>(element.fileLength),
base::Time::FromDoubleT(element.modificationTime));
@@ -286,138 +276,138 @@ scoped_refptr<ResourceRequestBody> GetRequestBodyForWebURLRequest(
return request_body;
}
-#define STATIC_ASSERT_MATCHING_ENUMS(content_name, blink_name) \
- static_assert( \
- static_cast<int>(content_name) == static_cast<int>(blink_name), \
- "mismatching enums: " #content_name)
-
-STATIC_ASSERT_MATCHING_ENUMS(FETCH_REQUEST_MODE_SAME_ORIGIN,
- WebURLRequest::FetchRequestModeSameOrigin);
-STATIC_ASSERT_MATCHING_ENUMS(FETCH_REQUEST_MODE_NO_CORS,
- WebURLRequest::FetchRequestModeNoCORS);
-STATIC_ASSERT_MATCHING_ENUMS(FETCH_REQUEST_MODE_CORS,
- WebURLRequest::FetchRequestModeCORS);
-STATIC_ASSERT_MATCHING_ENUMS(
- FETCH_REQUEST_MODE_CORS_WITH_FORCED_PREFLIGHT,
- WebURLRequest::FetchRequestModeCORSWithForcedPreflight);
-STATIC_ASSERT_MATCHING_ENUMS(FETCH_REQUEST_MODE_NAVIGATE,
- WebURLRequest::FetchRequestModeNavigate);
+#define STATIC_ASSERT_ENUM(a, b) \
+ static_assert(static_cast<int>(a) == static_cast<int>(b), \
+ "mismatching enums: " #a)
+
+STATIC_ASSERT_ENUM(FETCH_REQUEST_MODE_SAME_ORIGIN,
+ WebURLRequest::FetchRequestModeSameOrigin);
+STATIC_ASSERT_ENUM(FETCH_REQUEST_MODE_NO_CORS,
+ WebURLRequest::FetchRequestModeNoCORS);
+STATIC_ASSERT_ENUM(FETCH_REQUEST_MODE_CORS,
+ WebURLRequest::FetchRequestModeCORS);
+STATIC_ASSERT_ENUM(FETCH_REQUEST_MODE_CORS_WITH_FORCED_PREFLIGHT,
+ WebURLRequest::FetchRequestModeCORSWithForcedPreflight);
+STATIC_ASSERT_ENUM(FETCH_REQUEST_MODE_NAVIGATE,
+ WebURLRequest::FetchRequestModeNavigate);
FetchRequestMode GetFetchRequestModeForWebURLRequest(
const blink::WebURLRequest& request) {
- return static_cast<FetchRequestMode>(request.fetchRequestMode());
+ return static_cast<FetchRequestMode>(request.getFetchRequestMode());
}
-STATIC_ASSERT_MATCHING_ENUMS(FETCH_CREDENTIALS_MODE_OMIT,
- WebURLRequest::FetchCredentialsModeOmit);
-STATIC_ASSERT_MATCHING_ENUMS(FETCH_CREDENTIALS_MODE_SAME_ORIGIN,
- WebURLRequest::FetchCredentialsModeSameOrigin);
-STATIC_ASSERT_MATCHING_ENUMS(FETCH_CREDENTIALS_MODE_INCLUDE,
- WebURLRequest::FetchCredentialsModeInclude);
+STATIC_ASSERT_ENUM(FETCH_CREDENTIALS_MODE_OMIT,
+ WebURLRequest::FetchCredentialsModeOmit);
+STATIC_ASSERT_ENUM(FETCH_CREDENTIALS_MODE_SAME_ORIGIN,
+ WebURLRequest::FetchCredentialsModeSameOrigin);
+STATIC_ASSERT_ENUM(FETCH_CREDENTIALS_MODE_INCLUDE,
+ WebURLRequest::FetchCredentialsModeInclude);
+STATIC_ASSERT_ENUM(FETCH_CREDENTIALS_MODE_PASSWORD,
+ WebURLRequest::FetchCredentialsModePassword);
FetchCredentialsMode GetFetchCredentialsModeForWebURLRequest(
const blink::WebURLRequest& request) {
- return static_cast<FetchCredentialsMode>(request.fetchCredentialsMode());
+ return static_cast<FetchCredentialsMode>(request.getFetchCredentialsMode());
}
-STATIC_ASSERT_MATCHING_ENUMS(FetchRedirectMode::FOLLOW_MODE,
- WebURLRequest::FetchRedirectModeFollow);
-STATIC_ASSERT_MATCHING_ENUMS(FetchRedirectMode::ERROR_MODE,
- WebURLRequest::FetchRedirectModeError);
-STATIC_ASSERT_MATCHING_ENUMS(FetchRedirectMode::MANUAL_MODE,
- WebURLRequest::FetchRedirectModeManual);
+STATIC_ASSERT_ENUM(FetchRedirectMode::FOLLOW_MODE,
+ WebURLRequest::FetchRedirectModeFollow);
+STATIC_ASSERT_ENUM(FetchRedirectMode::ERROR_MODE,
+ WebURLRequest::FetchRedirectModeError);
+STATIC_ASSERT_ENUM(FetchRedirectMode::MANUAL_MODE,
+ WebURLRequest::FetchRedirectModeManual);
FetchRedirectMode GetFetchRedirectModeForWebURLRequest(
const blink::WebURLRequest& request) {
- return static_cast<FetchRedirectMode>(request.fetchRedirectMode());
+ return static_cast<FetchRedirectMode>(request.getFetchRedirectMode());
}
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_FRAME_TYPE_AUXILIARY,
- WebURLRequest::FrameTypeAuxiliary);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_FRAME_TYPE_NESTED,
- WebURLRequest::FrameTypeNested);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_FRAME_TYPE_NONE,
- WebURLRequest::FrameTypeNone);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL,
- WebURLRequest::FrameTypeTopLevel);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_FRAME_TYPE_AUXILIARY,
+ WebURLRequest::FrameTypeAuxiliary);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_FRAME_TYPE_NESTED,
+ WebURLRequest::FrameTypeNested);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_FRAME_TYPE_NONE,
+ WebURLRequest::FrameTypeNone);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL,
+ WebURLRequest::FrameTypeTopLevel);
RequestContextFrameType GetRequestContextFrameTypeForWebURLRequest(
const blink::WebURLRequest& request) {
- return static_cast<RequestContextFrameType>(request.frameType());
+ return static_cast<RequestContextFrameType>(request.getFrameType());
}
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_UNSPECIFIED,
- WebURLRequest::RequestContextUnspecified);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_AUDIO,
- WebURLRequest::RequestContextAudio);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_BEACON,
- WebURLRequest::RequestContextBeacon);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_CSP_REPORT,
- WebURLRequest::RequestContextCSPReport);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_DOWNLOAD,
- WebURLRequest::RequestContextDownload);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_EMBED,
- WebURLRequest::RequestContextEmbed);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_EVENT_SOURCE,
- WebURLRequest::RequestContextEventSource);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_FAVICON,
- WebURLRequest::RequestContextFavicon);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_FETCH,
- WebURLRequest::RequestContextFetch);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_FONT,
- WebURLRequest::RequestContextFont);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_FORM,
- WebURLRequest::RequestContextForm);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_FRAME,
- WebURLRequest::RequestContextFrame);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_HYPERLINK,
- WebURLRequest::RequestContextHyperlink);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_IFRAME,
- WebURLRequest::RequestContextIframe);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_IMAGE,
- WebURLRequest::RequestContextImage);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_IMAGE_SET,
- WebURLRequest::RequestContextImageSet);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_IMPORT,
- WebURLRequest::RequestContextImport);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_INTERNAL,
- WebURLRequest::RequestContextInternal);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_LOCATION,
- WebURLRequest::RequestContextLocation);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_MANIFEST,
- WebURLRequest::RequestContextManifest);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_OBJECT,
- WebURLRequest::RequestContextObject);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_PING,
- WebURLRequest::RequestContextPing);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_PLUGIN,
- WebURLRequest::RequestContextPlugin);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_PREFETCH,
- WebURLRequest::RequestContextPrefetch);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_SCRIPT,
- WebURLRequest::RequestContextScript);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_SERVICE_WORKER,
- WebURLRequest::RequestContextServiceWorker);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_SHARED_WORKER,
- WebURLRequest::RequestContextSharedWorker);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_SUBRESOURCE,
- WebURLRequest::RequestContextSubresource);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_STYLE,
- WebURLRequest::RequestContextStyle);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_TRACK,
- WebURLRequest::RequestContextTrack);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_VIDEO,
- WebURLRequest::RequestContextVideo);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_WORKER,
- WebURLRequest::RequestContextWorker);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_XML_HTTP_REQUEST,
- WebURLRequest::RequestContextXMLHttpRequest);
-STATIC_ASSERT_MATCHING_ENUMS(REQUEST_CONTEXT_TYPE_XSLT,
- WebURLRequest::RequestContextXSLT);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_UNSPECIFIED,
+ WebURLRequest::RequestContextUnspecified);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_AUDIO,
+ WebURLRequest::RequestContextAudio);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_BEACON,
+ WebURLRequest::RequestContextBeacon);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_CSP_REPORT,
+ WebURLRequest::RequestContextCSPReport);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_DOWNLOAD,
+ WebURLRequest::RequestContextDownload);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_EMBED,
+ WebURLRequest::RequestContextEmbed);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_EVENT_SOURCE,
+ WebURLRequest::RequestContextEventSource);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_FAVICON,
+ WebURLRequest::RequestContextFavicon);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_FETCH,
+ WebURLRequest::RequestContextFetch);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_FONT,
+ WebURLRequest::RequestContextFont);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_FORM,
+ WebURLRequest::RequestContextForm);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_FRAME,
+ WebURLRequest::RequestContextFrame);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_HYPERLINK,
+ WebURLRequest::RequestContextHyperlink);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_IFRAME,
+ WebURLRequest::RequestContextIframe);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_IMAGE,
+ WebURLRequest::RequestContextImage);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_IMAGE_SET,
+ WebURLRequest::RequestContextImageSet);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_IMPORT,
+ WebURLRequest::RequestContextImport);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_INTERNAL,
+ WebURLRequest::RequestContextInternal);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_LOCATION,
+ WebURLRequest::RequestContextLocation);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_MANIFEST,
+ WebURLRequest::RequestContextManifest);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_OBJECT,
+ WebURLRequest::RequestContextObject);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_PING,
+ WebURLRequest::RequestContextPing);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_PLUGIN,
+ WebURLRequest::RequestContextPlugin);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_PREFETCH,
+ WebURLRequest::RequestContextPrefetch);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_SCRIPT,
+ WebURLRequest::RequestContextScript);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_SERVICE_WORKER,
+ WebURLRequest::RequestContextServiceWorker);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_SHARED_WORKER,
+ WebURLRequest::RequestContextSharedWorker);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_SUBRESOURCE,
+ WebURLRequest::RequestContextSubresource);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_STYLE,
+ WebURLRequest::RequestContextStyle);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_TRACK,
+ WebURLRequest::RequestContextTrack);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_VIDEO,
+ WebURLRequest::RequestContextVideo);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_WORKER,
+ WebURLRequest::RequestContextWorker);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_XML_HTTP_REQUEST,
+ WebURLRequest::RequestContextXMLHttpRequest);
+STATIC_ASSERT_ENUM(REQUEST_CONTEXT_TYPE_XSLT,
+ WebURLRequest::RequestContextXSLT);
RequestContextType GetRequestContextTypeForWebURLRequest(
const blink::WebURLRequest& request) {
- return static_cast<RequestContextType>(request.requestContext());
+ return static_cast<RequestContextType>(request.getRequestContext());
}
blink::WebURLError CreateWebURLError(const blink::WebURL& unreachable_url,
diff --git a/chromium/content/child/webblobregistry_impl.cc b/chromium/content/child/webblobregistry_impl.cc
index ecdc0fcf4b9..afc7ae28a73 100644
--- a/chromium/content/child/webblobregistry_impl.cc
+++ b/chromium/content/child/webblobregistry_impl.cc
@@ -4,16 +4,22 @@
#include "content/child/webblobregistry_impl.h"
+#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/guid.h"
+#include "base/location.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory.h"
#include "base/message_loop/message_loop.h"
+#include "base/numerics/safe_conversions.h"
#include "base/trace_event/trace_event.h"
+#include "content/child/blob_storage/blob_consolidation.h"
+#include "content/child/blob_storage/blob_transport_controller.h"
#include "content/child/child_thread_impl.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/fileapi/webblob_messages.h"
+#include "storage/common/blob_storage/blob_storage_constants.h"
+#include "third_party/WebKit/public/platform/FilePathConversion.h"
#include "third_party/WebKit/public/platform/WebBlobData.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebThreadSafeData.h"
@@ -28,15 +34,13 @@ using storage::DataElement;
namespace content {
-namespace {
-
-const size_t kLargeThresholdBytes = 250 * 1024;
-const size_t kMaxSharedMemoryBytes = 10 * 1024 * 1024;
-
-} // namespace
-
-WebBlobRegistryImpl::WebBlobRegistryImpl(ThreadSafeSender* sender)
- : sender_(sender) {
+WebBlobRegistryImpl::WebBlobRegistryImpl(
+ scoped_refptr<base::SingleThreadTaskRunner> io_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> main_runner,
+ scoped_refptr<ThreadSafeSender> sender)
+ : io_runner_(std::move(io_runner)),
+ main_runner_(std::move(main_runner)),
+ sender_(std::move(sender)) {
// Record a dummy trace event on startup so the 'Storage' category shows up
// in the chrome://tracing viewer.
TRACE_EVENT0("Blob", "Init");
@@ -47,14 +51,15 @@ WebBlobRegistryImpl::~WebBlobRegistryImpl() {
blink::WebBlobRegistry::Builder* WebBlobRegistryImpl::createBuilder(
const blink::WebString& uuid,
- const blink::WebString& contentType) {
- return new BuilderImpl(uuid, contentType, sender_.get());
+ const blink::WebString& content_type) {
+ return new BuilderImpl(uuid, content_type, sender_.get(), io_runner_,
+ main_runner_);
}
void WebBlobRegistryImpl::registerBlobData(const blink::WebString& uuid,
const blink::WebBlobData& data) {
TRACE_EVENT0("Blob", "Registry::RegisterBlob");
- scoped_ptr<Builder> builder(createBuilder(uuid, data.contentType()));
+ std::unique_ptr<Builder> builder(createBuilder(uuid, data.contentType()));
// This is temporary until we move to createBuilder() as our blob creation
// method.
@@ -133,15 +138,16 @@ void WebBlobRegistryImpl::addDataToStream(const WebURL& url,
DCHECK(ChildThreadImpl::current());
if (length == 0)
return;
- if (length < kLargeThresholdBytes) {
+ if (length < storage::kBlobStorageIPCThresholdBytes) {
DataElement item;
item.SetToBytes(data, length);
sender_->Send(new StreamHostMsg_AppendBlobDataItem(url, item));
} else {
// We handle larger amounts of data via SharedMemory instead of
// writing it directly to the IPC channel.
- size_t shared_memory_size = std::min(length, kMaxSharedMemoryBytes);
- scoped_ptr<base::SharedMemory> shared_memory(
+ size_t shared_memory_size =
+ std::min(length, storage::kBlobStorageMaxSharedMemoryBytes);
+ std::unique_ptr<base::SharedMemory> shared_memory(
ChildThreadImpl::AllocateSharedMemory(shared_memory_size,
sender_.get()));
CHECK(shared_memory.get());
@@ -154,7 +160,8 @@ void WebBlobRegistryImpl::addDataToStream(const WebURL& url,
size_t chunk_size = std::min(remaining_bytes, shared_memory_size);
memcpy(shared_memory->memory(), current_ptr, chunk_size);
sender_->Send(new StreamHostMsg_SyncAppendSharedMemory(
- url, shared_memory->handle(), chunk_size));
+ url, shared_memory->handle(),
+ base::checked_cast<uint32_t>(chunk_size)));
remaining_bytes -= chunk_size;
current_ptr += chunk_size;
}
@@ -184,22 +191,28 @@ void WebBlobRegistryImpl::unregisterStreamURL(const WebURL& url) {
WebBlobRegistryImpl::BuilderImpl::BuilderImpl(
const blink::WebString& uuid,
const blink::WebString& content_type,
- ThreadSafeSender* sender)
- : uuid_(uuid.utf8()), content_type_(content_type.utf8()), sender_(sender) {
-}
+ ThreadSafeSender* sender,
+ scoped_refptr<base::SingleThreadTaskRunner> io_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> main_runner)
+ : uuid_(uuid.utf8()),
+ content_type_(content_type.utf8()),
+ consolidation_(new BlobConsolidation()),
+ sender_(sender),
+ io_runner_(std::move(io_runner)),
+ main_runner_(std::move(main_runner)) {}
WebBlobRegistryImpl::BuilderImpl::~BuilderImpl() {
}
void WebBlobRegistryImpl::BuilderImpl::appendData(
const WebThreadSafeData& data) {
- consolidation_.AddDataItem(data);
+ consolidation_->AddDataItem(data);
}
void WebBlobRegistryImpl::BuilderImpl::appendBlob(const WebString& uuid,
uint64_t offset,
uint64_t length) {
- consolidation_.AddBlobItem(uuid.utf8(), offset, length);
+ consolidation_->AddBlobItem(uuid.utf8(), offset, length);
}
void WebBlobRegistryImpl::BuilderImpl::appendFile(
@@ -207,9 +220,8 @@ void WebBlobRegistryImpl::BuilderImpl::appendFile(
uint64_t offset,
uint64_t length,
double expected_modification_time) {
- consolidation_.AddFileItem(
- base::FilePath::FromUTF16Unsafe(base::string16(path)), offset, length,
- expected_modification_time);
+ consolidation_->AddFileItem(blink::WebStringToFilePath(path), offset, length,
+ expected_modification_time);
}
void WebBlobRegistryImpl::BuilderImpl::appendFileSystemURL(
@@ -218,92 +230,14 @@ void WebBlobRegistryImpl::BuilderImpl::appendFileSystemURL(
uint64_t length,
double expected_modification_time) {
DCHECK(GURL(fileSystemURL).SchemeIsFileSystem());
- consolidation_.AddFileSystemItem(GURL(fileSystemURL), offset, length,
- expected_modification_time);
+ consolidation_->AddFileSystemItem(GURL(fileSystemURL), offset, length,
+ expected_modification_time);
}
void WebBlobRegistryImpl::BuilderImpl::build() {
- sender_->Send(new BlobHostMsg_StartBuilding(uuid_));
- const auto& items = consolidation_.consolidated_items();
-
- // We still need a buffer to hold the continuous block of data so the
- // DataElement can hold it.
- size_t buffer_size = 0;
- scoped_ptr<char[]> buffer;
- for (size_t i = 0; i < items.size(); i++) {
- const BlobConsolidation::ConsolidatedItem& item = items[i];
- DataElement element;
- // NOTE: length == -1 when we want to use the whole file. This
- // only happens when we are creating a file object in Blink, and the file
- // object is the only item in the 'blob'. If we use that file blob to
- // create another blob, it is sent here as a 'file' item and not a blob,
- // and the correct size is populated.
- // static_cast<uint64_t>(-1) == kuint64max, which is what DataElement uses
- // to specificy "use the whole file".
- switch (item.type) {
- case DataElement::TYPE_BYTES:
- if (item.length > kLargeThresholdBytes) {
- SendOversizedDataForBlob(i);
- break;
- }
- if (buffer_size < item.length) {
- buffer.reset(new char[item.length]);
- buffer_size = item.length;
- }
- consolidation_.ReadMemory(i, 0, item.length, buffer.get());
- element.SetToSharedBytes(buffer.get(), item.length);
- sender_->Send(new BlobHostMsg_AppendBlobDataItem(uuid_, element));
- break;
- case DataElement::TYPE_FILE:
- element.SetToFilePathRange(
- item.path, item.offset, item.length,
- base::Time::FromDoubleT(item.expected_modification_time));
- sender_->Send(new BlobHostMsg_AppendBlobDataItem(uuid_, element));
- break;
- case DataElement::TYPE_BLOB:
- element.SetToBlobRange(item.blob_uuid, item.offset, item.length);
- sender_->Send(new BlobHostMsg_AppendBlobDataItem(uuid_, element));
- break;
- case DataElement::TYPE_FILE_FILESYSTEM:
- element.SetToFileSystemUrlRange(
- item.filesystem_url, item.offset, item.length,
- base::Time::FromDoubleT(item.expected_modification_time));
- sender_->Send(new BlobHostMsg_AppendBlobDataItem(uuid_, element));
- break;
- default:
- NOTREACHED();
- }
- }
- sender_->Send(new BlobHostMsg_FinishBuilding(uuid_, content_type_));
-}
-
-void WebBlobRegistryImpl::BuilderImpl::SendOversizedDataForBlob(
- size_t consolidated_item_index) {
- TRACE_EVENT0("Blob", "Registry::SendOversizedBlobData");
- const BlobConsolidation::ConsolidatedItem& item =
- consolidation_.consolidated_items()[consolidated_item_index];
- // We handle larger amounts of data via SharedMemory instead of
- // writing it directly to the IPC channel.
-
- size_t data_size = item.length;
- size_t shared_memory_size = std::min(data_size, kMaxSharedMemoryBytes);
- scoped_ptr<base::SharedMemory> shared_memory(
- ChildThreadImpl::AllocateSharedMemory(shared_memory_size, sender_.get()));
- CHECK(shared_memory.get());
- const bool mapped = shared_memory->Map(shared_memory_size);
- CHECK(mapped) << "Unable to map shared memory.";
-
- size_t offset = 0;
- while (data_size) {
- TRACE_EVENT0("Blob", "Registry::SendOversizedBlobItem");
- size_t chunk_size = std::min(data_size, shared_memory_size);
- consolidation_.ReadMemory(consolidated_item_index, offset, chunk_size,
- shared_memory->memory());
- sender_->Send(new BlobHostMsg_SyncAppendSharedMemory(
- uuid_, shared_memory->handle(), chunk_size));
- data_size -= chunk_size;
- offset += chunk_size;
- }
+ BlobTransportController::InitiateBlobTransfer(
+ uuid_, content_type_, std::move(consolidation_), sender_,
+ io_runner_.get(), main_runner_);
}
} // namespace content
diff --git a/chromium/content/child/webblobregistry_impl.h b/chromium/content/child/webblobregistry_impl.h
index 53c98849cd2..ff414608546 100644
--- a/chromium/content/child/webblobregistry_impl.h
+++ b/chromium/content/child/webblobregistry_impl.h
@@ -2,17 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_CHILD_WEBBLOBREGISTRY_IMPL_H_
-#define CONTENT_CHILD_WEBBLOBREGISTRY_IMPL_H_
+#ifndef CONTENT_CHILD_BLOB_STORAGE_WEBBLOBREGISTRY_IMPL_H_
+#define CONTENT_CHILD_BLOB_STORAGE_WEBBLOBREGISTRY_IMPL_H_
#include <stddef.h>
#include <stdint.h>
+#include <memory>
#include <string>
#include <vector>
#include "base/memory/ref_counted.h"
-#include "content/child/blob_storage/blob_consolidation.h"
+#include "base/single_thread_task_runner.h"
#include "storage/common/data_element.h"
#include "third_party/WebKit/public/platform/WebBlobRegistry.h"
@@ -25,11 +26,14 @@ class DataElement;
}
namespace content {
+class BlobConsolidation;
class ThreadSafeSender;
class WebBlobRegistryImpl : public blink::WebBlobRegistry {
public:
- explicit WebBlobRegistryImpl(ThreadSafeSender* sender);
+ WebBlobRegistryImpl(scoped_refptr<base::SingleThreadTaskRunner> io_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> main_runner,
+ scoped_refptr<ThreadSafeSender> sender);
~WebBlobRegistryImpl() override;
// TODO(dmurph): remove this after moving to createBuilder. crbug.com/504583
@@ -64,8 +68,10 @@ class WebBlobRegistryImpl : public blink::WebBlobRegistry {
class BuilderImpl : public blink::WebBlobRegistry::Builder {
public:
BuilderImpl(const blink::WebString& uuid,
- const blink::WebString& contentType,
- ThreadSafeSender* sender);
+ const blink::WebString& content_type,
+ ThreadSafeSender* sender,
+ scoped_refptr<base::SingleThreadTaskRunner> io_runner,
+ scoped_refptr<base::SingleThreadTaskRunner> main_runner);
~BuilderImpl() override;
void appendData(const blink::WebThreadSafeData&) override;
@@ -84,18 +90,19 @@ class WebBlobRegistryImpl : public blink::WebBlobRegistry {
void build() override;
private:
- // Sends data that is larger than the threshold.
- void SendOversizedDataForBlob(size_t consolidated_item_index);
-
const std::string uuid_;
const std::string content_type_;
- BlobConsolidation consolidation_;
+ std::unique_ptr<BlobConsolidation> consolidation_;
scoped_refptr<ThreadSafeSender> sender_;
+ scoped_refptr<base::SingleThreadTaskRunner> io_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> main_runner_;
};
+ scoped_refptr<base::SingleThreadTaskRunner> io_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> main_runner_;
scoped_refptr<ThreadSafeSender> sender_;
};
} // namespace content
-#endif // CONTENT_CHILD_WEBBLOBREGISTRY_IMPL_H_
+#endif // CONTENT_CHILD_BLOB_STORAGE_WEBBLOBREGISTRY_IMPL_H_
diff --git a/chromium/content/child/webfallbackthemeengine_impl.h b/chromium/content/child/webfallbackthemeengine_impl.h
index aa100d6fff9..b0a4bceca4a 100644
--- a/chromium/content/child/webfallbackthemeengine_impl.h
+++ b/chromium/content/child/webfallbackthemeengine_impl.h
@@ -5,8 +5,9 @@
#ifndef CONTENT_CHILD_WEBFALLBACKTHEMEENGINE_IMPL_H_
#define CONTENT_CHILD_WEBFALLBACKTHEMEENGINE_IMPL_H_
+#include <memory>
+
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "third_party/WebKit/public/platform/WebFallbackThemeEngine.h"
namespace content {
@@ -29,7 +30,7 @@ class WebFallbackThemeEngineImpl : public blink::WebFallbackThemeEngine {
private:
class WebFallbackNativeTheme;
- scoped_ptr<WebFallbackNativeTheme> theme_;
+ std::unique_ptr<WebFallbackNativeTheme> theme_;
DISALLOW_COPY_AND_ASSIGN(WebFallbackThemeEngineImpl);
};
diff --git a/chromium/content/child/webfileutilities_impl.cc b/chromium/content/child/webfileutilities_impl.cc
index 72ddc73d9d6..268ed091060 100644
--- a/chromium/content/child/webfileutilities_impl.cc
+++ b/chromium/content/child/webfileutilities_impl.cc
@@ -10,6 +10,7 @@
#include "content/child/file_info_util.h"
#include "net/base/file_stream.h"
#include "net/base/filename_util.h"
+#include "third_party/WebKit/public/platform/FilePathConversion.h"
#include "third_party/WebKit/public/platform/WebFileInfo.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h"
@@ -32,7 +33,7 @@ bool WebFileUtilitiesImpl::getFileInfo(const WebString& path,
return false;
}
base::File::Info file_info;
- if (!base::GetFileInfo(base::FilePath::FromUTF16Unsafe(path),
+ if (!base::GetFileInfo(blink::WebStringToFilePath(path),
reinterpret_cast<base::File::Info*>(&file_info)))
return false;
@@ -42,15 +43,15 @@ bool WebFileUtilitiesImpl::getFileInfo(const WebString& path,
}
WebString WebFileUtilitiesImpl::directoryName(const WebString& path) {
- return base::FilePath::FromUTF16Unsafe(path).DirName().AsUTF16Unsafe();
+ return blink::WebStringToFilePath(path).DirName().AsUTF16Unsafe();
}
WebString WebFileUtilitiesImpl::baseName(const WebString& path) {
- return base::FilePath::FromUTF16Unsafe(path).BaseName().AsUTF16Unsafe();
+ return blink::WebStringToFilePath(path).BaseName().AsUTF16Unsafe();
}
blink::WebURL WebFileUtilitiesImpl::filePathToURL(const WebString& path) {
- return net::FilePathToFileURL(base::FilePath::FromUTF16Unsafe(path));
+ return net::FilePathToFileURL(blink::WebStringToFilePath(path));
}
} // namespace content
diff --git a/chromium/content/child/webmessageportchannel_impl.cc b/chromium/content/child/webmessageportchannel_impl.cc
index 6fdd08c3b2d..66a66ba1329 100644
--- a/chromium/content/child/webmessageportchannel_impl.cc
+++ b/chromium/content/child/webmessageportchannel_impl.cc
@@ -87,7 +87,7 @@ void WebMessagePortChannelImpl::CreatePair(
// static
std::vector<TransferredMessagePort>
WebMessagePortChannelImpl::ExtractMessagePortIDs(
- scoped_ptr<WebMessagePortChannelArray> channels) {
+ std::unique_ptr<WebMessagePortChannelArray> channels) {
std::vector<TransferredMessagePort> message_ports;
if (channels)
message_ports = ExtractMessagePortIDs(*channels);
@@ -117,7 +117,7 @@ WebMessagePortChannelImpl::ExtractMessagePortIDs(
// static
std::vector<TransferredMessagePort>
WebMessagePortChannelImpl::ExtractMessagePortIDsWithoutQueueing(
- scoped_ptr<WebMessagePortChannelArray> channels) {
+ std::unique_ptr<WebMessagePortChannelArray> channels) {
if (!channels)
return std::vector<TransferredMessagePort>();
@@ -175,30 +175,30 @@ void WebMessagePortChannelImpl::postMessage(
const WebString& message_as_string,
WebMessagePortChannelArray* channels_ptr) {
MessagePortMessage message(message_as_string);
- scoped_ptr<WebMessagePortChannelArray> channels(channels_ptr);
+ std::unique_ptr<WebMessagePortChannelArray> channels(channels_ptr);
if (send_messages_as_values_) {
blink::WebSerializedScriptValue serialized_value =
blink::WebSerializedScriptValue::fromString(message_as_string);
v8::Local<v8::Value> v8_value = serialized_value.deserialize();
- scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
+ std::unique_ptr<V8ValueConverter> converter(V8ValueConverter::create());
converter->SetDateAllowed(true);
converter->SetRegExpAllowed(true);
- scoped_ptr<base::Value> message_as_value(converter->FromV8Value(
+ std::unique_ptr<base::Value> message_as_value(converter->FromV8Value(
v8_value, v8::Isolate::GetCurrent()->GetCurrentContext()));
message = MessagePortMessage(std::move(message_as_value));
}
if (!main_thread_task_runner_->BelongsToCurrentThread()) {
main_thread_task_runner_->PostTask(
- FROM_HERE, base::Bind(&WebMessagePortChannelImpl::PostMessage, this,
+ FROM_HERE, base::Bind(&WebMessagePortChannelImpl::SendPostMessage, this,
message, base::Passed(std::move(channels))));
} else {
- PostMessage(message, std::move(channels));
+ SendPostMessage(message, std::move(channels));
}
}
-void WebMessagePortChannelImpl::PostMessage(
+void WebMessagePortChannelImpl::SendPostMessage(
const MessagePortMessage& message,
- scoped_ptr<WebMessagePortChannelArray> channels) {
+ std::unique_ptr<WebMessagePortChannelArray> channels) {
IPC::Message* msg = new MessagePortHostMsg_PostMessage(
message_port_id_, message, ExtractMessagePortIDs(std::move(channels)));
Send(msg);
@@ -217,7 +217,7 @@ bool WebMessagePortChannelImpl::tryGetMessage(
v8::HandleScope handle_scope(client_->scriptIsolate());
v8::Context::Scope context_scope(
client_->scriptContextForMessageConversion());
- scoped_ptr<V8ValueConverter> converter(V8ValueConverter::create());
+ std::unique_ptr<V8ValueConverter> converter(V8ValueConverter::create());
converter->SetDateAllowed(true);
converter->SetRegExpAllowed(true);
v8::Local<v8::Value> v8_value = converter->ToV8Value(
@@ -350,6 +350,8 @@ void WebMessagePortChannelImpl::OnMessagesQueued() {
WebMessagePortChannelImpl::Message::Message() {}
+WebMessagePortChannelImpl::Message::Message(const Message& other) = default;
+
WebMessagePortChannelImpl::Message::~Message() {}
} // namespace content
diff --git a/chromium/content/child/webmessageportchannel_impl.h b/chromium/content/child/webmessageportchannel_impl.h
index b5c8e7bf454..939186e66f0 100644
--- a/chromium/content/child/webmessageportchannel_impl.h
+++ b/chromium/content/child/webmessageportchannel_impl.h
@@ -5,12 +5,12 @@
#ifndef CONTENT_CHILD_WEBMESSAGEPORTCHANNEL_IMPL_H_
#define CONTENT_CHILD_WEBMESSAGEPORTCHANNEL_IMPL_H_
+#include <memory>
#include <queue>
#include <vector>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/strings/string16.h"
#include "base/synchronization/lock.h"
#include "content/public/common/message_port_types.h"
@@ -49,7 +49,7 @@ class WebMessagePortChannelImpl
// Extracts port IDs for passing on to the browser process, and queues any
// received messages.
static std::vector<TransferredMessagePort> ExtractMessagePortIDs(
- scoped_ptr<blink::WebMessagePortChannelArray> channels);
+ std::unique_ptr<blink::WebMessagePortChannelArray> channels);
// Extracts port IDs for passing on to the browser process, and queues any
// received messages.
@@ -63,7 +63,7 @@ class WebMessagePortChannelImpl
// does not share ordering guarentees with regular IPC.
static std::vector<TransferredMessagePort>
ExtractMessagePortIDsWithoutQueueing(
- scoped_ptr<blink::WebMessagePortChannelArray> channels);
+ std::unique_ptr<blink::WebMessagePortChannelArray> channels);
// Creates WebMessagePortChannelImpl instances for port IDs passed in from the
// browser process.
@@ -93,8 +93,9 @@ class WebMessagePortChannelImpl
void Init();
void Entangle(scoped_refptr<WebMessagePortChannelImpl> channel);
void Send(IPC::Message* message);
- void PostMessage(const MessagePortMessage& message,
- scoped_ptr<blink::WebMessagePortChannelArray> channels);
+ void SendPostMessage(
+ const MessagePortMessage& message,
+ std::unique_ptr<blink::WebMessagePortChannelArray> channels);
// IPC::Listener implementation.
bool OnMessageReceived(const IPC::Message& message) override;
@@ -106,6 +107,7 @@ class WebMessagePortChannelImpl
struct Message {
Message();
+ Message(const Message& other);
~Message();
MessagePortMessage message;
diff --git a/chromium/content/child/webthemeengine_impl_android.cc b/chromium/content/child/webthemeengine_impl_android.cc
index 83db469f047..7db2ef43174 100644
--- a/chromium/content/child/webthemeengine_impl_android.cc
+++ b/chromium/content/child/webthemeengine_impl_android.cc
@@ -5,6 +5,7 @@
#include "content/child/webthemeengine_impl_android.h"
#include "base/logging.h"
+#include "base/sys_info.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/platform/WebRect.h"
#include "third_party/WebKit/public/platform/WebSize.h"
@@ -17,8 +18,17 @@ using blink::WebThemeEngine;
namespace content {
-static ui::NativeTheme::Part NativeThemePart(
- WebThemeEngine::Part part) {
+namespace {
+ const int kVersionLollipop = 5;
+
+ int getMajorVersion() {
+ int major, minor, bugfix;
+ base::SysInfo::OperatingSystemVersionNumbers(&major, &minor, &bugfix);
+ return major;
+ }
+}
+
+static ui::NativeTheme::Part NativeThemePart(WebThemeEngine::Part part) {
switch (part) {
case WebThemeEngine::PartScrollbarDownArrow:
return ui::NativeTheme::kScrollbarDownArrow;
@@ -59,8 +69,7 @@ static ui::NativeTheme::Part NativeThemePart(
}
}
-static ui::NativeTheme::State NativeThemeState(
- WebThemeEngine::State state) {
+static ui::NativeTheme::State NativeThemeState(WebThemeEngine::State state) {
switch (state) {
case WebThemeEngine::StateDisabled:
return ui::NativeTheme::kDisabled;
@@ -163,6 +172,18 @@ blink::WebSize WebThemeEngineImpl::getSize(WebThemeEngine::Part part) {
NativeThemePart(part), ui::NativeTheme::kNormal, extra);
}
+void WebThemeEngineImpl::getOverlayScrollbarStyle(ScrollbarStyle* style) {
+ if (getMajorVersion() >= kVersionLollipop) {
+ style->thumbThickness = 4;
+ style->scrollbarMargin = 0;
+ style->color = SkColorSetARGB(128, 64, 64, 64);
+ } else {
+ style->thumbThickness = 3;
+ style->scrollbarMargin = 3;
+ style->color = SkColorSetARGB(128, 128, 128, 128);
+ }
+}
+
void WebThemeEngineImpl::paint(
blink::WebCanvas* canvas,
WebThemeEngine::Part part,
diff --git a/chromium/content/child/webthemeengine_impl_android.h b/chromium/content/child/webthemeengine_impl_android.h
index 3483ab5f2ce..9fa6a1333c7 100644
--- a/chromium/content/child/webthemeengine_impl_android.h
+++ b/chromium/content/child/webthemeengine_impl_android.h
@@ -13,6 +13,8 @@ class WebThemeEngineImpl : public blink::WebThemeEngine {
public:
// WebThemeEngine methods:
blink::WebSize getSize(blink::WebThemeEngine::Part) override;
+ void getOverlayScrollbarStyle(
+ blink::WebThemeEngine::ScrollbarStyle*) override;
void paint(blink::WebCanvas* canvas,
blink::WebThemeEngine::Part part,
blink::WebThemeEngine::State state,
diff --git a/chromium/content/child/worker_thread_registry.cc b/chromium/content/child/worker_thread_registry.cc
index 274987b630e..8c52ea00239 100644
--- a/chromium/content/child/worker_thread_registry.cc
+++ b/chromium/content/child/worker_thread_registry.cc
@@ -4,11 +4,12 @@
#include "content/child/worker_thread_registry.h"
+#include <memory>
+
#include "base/callback.h"
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
#include "base/observer_list.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
diff --git a/chromium/content/common/BUILD.gn b/chromium/content/common/BUILD.gn
index 0a7e72e321d..cc769b07c45 100644
--- a/chromium/content/common/BUILD.gn
+++ b/chromium/content/common/BUILD.gn
@@ -126,21 +126,16 @@ if (is_mac) {
}
source_set("common") {
- # Only the public target should depend on this. All other targets (even
- # internal content ones) should depend on the public one.
- visibility = [ "//content/public/common:common_sources" ]
+ # Targets external to content should always link to the public API.
+ # In addition, targets outside of the content component (shell and tests)
+ # must not link to this because it will duplicate the code in the component
+ # build.
+ visibility = [ "//content/*" ]
sources = rebase_path(content_common_gypi_values.private_common_sources,
".",
"//content")
- # These files are only built in a GN build because they bring in
- # dependencies that don't build with GYP.
- sources += [
- "mojo/mojo_shell_connection_impl.cc",
- "mojo/mojo_shell_connection_impl.h",
- ]
-
configs += [
"//content:content_implementation",
"//build/config:precompiled_headers",
@@ -148,69 +143,77 @@ source_set("common") {
]
public_deps = [
+ ":mojo_bindings",
"//gpu/command_buffer/common",
"//ipc",
"//third_party/WebKit/public:blink_headers",
]
deps = [
"//base",
+ "//base/third_party/dynamic_annotations",
"//build/util:webkit_version",
+ "//cc",
+ "//cc/blink",
+ "//cc/surfaces",
"//components/mus/public/interfaces",
"//components/tracing",
"//components/tracing:startup_tracing",
+ "//device/bluetooth",
+
+ # TODO: the dependency on gl_in_process_context should be decoupled from
+ # content and moved to android_webview. See crbug.com/365797.
+ "//gpu",
+ "//gpu/blink",
+ "//gpu/command_buffer/client:gl_in_process_context",
+ "//gpu/command_buffer/client:gles2_c_lib",
+ "//gpu/command_buffer/client:gles2_cmd_helper",
+ "//gpu/command_buffer/client:gles2_implementation",
"//gpu/command_buffer/client:gles2_interface",
"//gpu/command_buffer/common:gles2_utils",
- "//mojo/converters/network",
- "//mojo/runner/child:lib",
+ "//gpu/command_buffer/service",
+ "//gpu/ipc/client",
+ "//gpu/ipc/common",
+
+ # TODO(markdittmer): This should be removed once content/common/gpu/media
+ # is refactored into media/ipc.
+ "//gpu/ipc/service",
+ "//gpu/skia_bindings",
+ "//ipc",
+ "//ipc/mojo",
+ "//media",
+ "//media:shared_memory_support",
+ "//media/gpu/ipc/client",
+ "//media/gpu/ipc/common",
+ "//media/midi",
+ "//mojo/common:common_base",
+ "//mojo/edk/system",
+ "//mojo/shell",
"//mojo/shell/public/cpp",
+ "//mojo/shell/public/interfaces",
+ "//mojo/shell/runner/common",
"//net",
+ "//sandbox",
"//skia",
+ "//storage/common",
+ "//third_party/WebKit/public:blink",
+ "//third_party/boringssl",
"//third_party/icu",
"//third_party/libjingle",
+ "//third_party/webrtc/base:rtc_base",
"//ui/accessibility",
"//ui/base",
"//ui/base/ime",
- "//ui/events/ipc:events_ipc",
+ "//ui/events/ipc",
"//ui/gfx",
"//ui/gfx/geometry",
"//ui/gfx/ipc",
+ "//ui/gfx/ipc/skia",
+ "//ui/gl",
"//ui/shell_dialogs",
"//url",
+ "//url/ipc:url_ipc",
]
- if (!is_ios) {
- deps += [
- "//cc",
- "//device/bluetooth",
- "//ipc",
- "//ipc/mojo",
-
- # TODO: the dependency on gl_in_process_context should be decoupled from
- # content and moved to android_webview. See crbug.com/365797.
- ":mojo_bindings",
- "//gpu/blink",
- "//gpu/command_buffer/client:gl_in_process_context",
- "//gpu/command_buffer/client:gles2_c_lib",
- "//gpu/command_buffer/client:gles2_cmd_helper",
- "//gpu/command_buffer/client:gles2_implementation",
- "//gpu/command_buffer/service",
- "//gpu/ipc",
- "//gpu/skia_bindings",
- "//media",
- "//media:shared_memory_support",
- "//media/midi",
- "//mojo/common:common_base",
- "//mojo/environment:chromium",
- "//mojo/shell/public/interfaces",
- "//sandbox",
- "//storage/common",
- "//third_party/WebKit/public:blink",
- "//third_party/boringssl",
- "//third_party/mojo/src/mojo/edk/system",
- "//ui/gl",
- ]
- }
-
defines = []
include_dirs = []
libs = []
@@ -227,17 +230,13 @@ source_set("common") {
if (is_mac) {
sources += [
- "gpu/client/gpu_memory_buffer_impl_io_surface.cc",
- "gpu/client/gpu_memory_buffer_impl_io_surface.h",
- "gpu/gpu_memory_buffer_factory_io_surface.cc",
- "gpu/gpu_memory_buffer_factory_io_surface.h",
"gpu/media/vt_mac.h",
"gpu/media/vt_video_decode_accelerator_mac.cc",
"gpu/media/vt_video_decode_accelerator_mac.h",
+ "gpu/media/vt_video_encode_accelerator_mac.cc",
+ "gpu/media/vt_video_encode_accelerator_mac.h",
] + get_target_outputs(":libvt_generate_stubs")
- sources -= [ "plugin_list_posix.cc" ]
-
deps += [
":libvt_generate_stubs",
"//content:resources",
@@ -248,6 +247,9 @@ source_set("common") {
]
lib_dirs = [ "$mac_sdk_path/usr/lib" ]
libs += [
+ "AVFoundation.framework",
+ "CoreMedia.framework",
+ "CoreVideo.framework",
"IOSurface.framework",
"OpenGL.framework",
"QuartzCore.framework",
@@ -256,13 +258,6 @@ source_set("common") {
}
if (is_android) {
- sources += [
- "gpu/client/gpu_memory_buffer_impl_surface_texture.cc",
- "gpu/client/gpu_memory_buffer_impl_surface_texture.h",
- "gpu/gpu_memory_buffer_factory_surface_texture.cc",
- "gpu/gpu_memory_buffer_factory_surface_texture.h",
- ]
-
deps += [
"//content/public/android:common_aidl",
"//content/public/android:jni",
@@ -278,26 +273,12 @@ source_set("common") {
deps += [ "//ppapi/proxy:ipc_sources" ]
}
- if (is_ios) {
- sources -= [ "user_agent.cc" ]
- assert(false, "Need to add lots of conditions here")
- }
-
if (use_ozone) {
- configs += [ "//ui/ozone:vgem_map" ]
-
- deps += [
- "//ui/ozone:ozone",
- "//ui/ozone:ozone_base",
- ]
+ deps += [ "//ui/ozone" ]
} else {
sources -= [
"cursors/webcursor_ozone.cc",
"font_list_ozone.cc",
- "gpu/client/gpu_memory_buffer_impl_ozone_native_pixmap.cc",
- "gpu/client/gpu_memory_buffer_impl_ozone_native_pixmap.h",
- "gpu/gpu_memory_buffer_factory_ozone_native_pixmap.cc",
- "gpu/gpu_memory_buffer_factory_ozone_native_pixmap.h",
]
}
@@ -320,17 +301,6 @@ source_set("common") {
sources -= [ "font_list_pango.cc" ]
}
- if (use_x11) {
- configs += [
- "//build/config/linux:xcomposite",
- "//third_party/khronos:khronos_headers",
- ]
-
- if (current_cpu != "arm" || !is_chromeos) {
- sources += [ "gpu/x_util.h" ]
- }
- }
-
if (enable_plugins) {
deps += [ "//ppapi/shared_impl" ]
} else {
@@ -344,7 +314,6 @@ source_set("common") {
"pepper_renderer_instance_data.h",
"plugin_list.cc",
"plugin_list.h",
- "plugin_list_posix.cc",
"sandbox_util.cc",
]
}
@@ -373,16 +342,14 @@ source_set("common") {
]
}
- if (enable_mojo_media == "gpu") {
- deps += [ "//media/mojo/services:application" ]
+ if (mojo_media_host == "gpu") {
+ deps += [ "//media/mojo/services:cdm_service" ]
}
}
if (is_chromeos) {
sources += [
"gpu/media/accelerated_video_decoder.h",
- "gpu/media/gpu_arc_video_service.cc",
- "gpu/media/gpu_arc_video_service.h",
"gpu/media/h264_decoder.cc",
"gpu/media/h264_decoder.h",
"gpu/media/h264_dpb.cc",
@@ -396,7 +363,6 @@ source_set("common") {
"gpu/media/vp9_picture.cc",
"gpu/media/vp9_picture.h",
]
- deps += [ "//components/arc" ]
if (use_v4lplugin) {
defines += [ "USE_LIBV4L2" ]
sources += get_target_outputs(":libv4l2_generate_stubs")
@@ -531,30 +497,50 @@ source_set("common") {
}
}
+# See comment at the top of //content/BUILD.gn for how this works.
+group("for_content_tests") {
+ visibility = [ "//content/test/*" ]
+ if (!is_component_build) {
+ public_deps = [
+ ":common",
+ ]
+ }
+}
+
mojom("mojo_bindings") {
+ # This interface is internal to content. However, this is not exported from
+ # the content component shared library. Code in content but outside of the
+ # content component (content/test or content/shell) should link to this
+ # directly.
+ visibility = [ "//content/*" ]
+
sources = [
"application_setup.mojom",
"background_sync_service.mojom",
- "geolocation_service.mojom",
"image_downloader/image_downloader.mojom",
- "permission_service.mojom",
+ "leveldb_wrapper.mojom",
"presentation/presentation_service.mojom",
"process_control.mojom",
"render_frame_setup.mojom",
"render_widget_window_tree_client_factory.mojom",
- "service_port_service.mojom",
"service_worker/embedded_worker_setup.mojom",
+ "storage_partition_service.mojom",
"vr_service.mojom",
"wake_lock_service.mojom",
]
import_dirs = [ "//mojo/services" ]
- deps = [
+ typemaps = [ "//url/mojo/origin.typemap" ]
+
+ public_deps = [
+ "//components/leveldb/public/interfaces",
"//components/mus/public/interfaces",
"//content/public/common:mojo_bindings",
"//mojo/shell/public/interfaces",
"//skia/public/interfaces",
+ "//third_party/WebKit/public:mojo_bindings",
"//ui/mojo/geometry:interfaces",
+ "//url/mojo:url_mojom_origin",
]
}
diff --git a/chromium/content/common/DEPS b/chromium/content/common/DEPS
index 3ba16c40dc2..caf3f5d1ead 100644
--- a/chromium/content/common/DEPS
+++ b/chromium/content/common/DEPS
@@ -6,7 +6,7 @@ include_rules = [
# No inclusion of WebKit from the browser, other than strictly enum/POD,
# header-only types, and some selected common code.
"-third_party/WebKit",
- "+third_party/WebKit/public/platform/WebBatteryStatus.h",
+ "+third_party/WebKit/public/platform/WebAddressSpace.h",
"+third_party/WebKit/public/platform/WebCircularGeofencingRegion.h",
"+third_party/WebKit/public/platform/WebCString.h",
"+third_party/WebKit/public/platform/modules/device_orientation/WebDeviceMotionData.h",
@@ -65,10 +65,3 @@ include_rules = [
"+third_party/WebKit/public/web/mac/WebScrollbarTheme.h",
"+third_party/WebKit/public/web/win/WebFontRendering.h"
]
-
-specific_include_rules = {
-# Java bridge code passes NPAPI types to the browser process. Crazy!
- "java_bridge_messages\.h": [
- "+content/child"
- ]
-}
diff --git a/chromium/content/common/OWNERS b/chromium/content/common/OWNERS
index df1d46c544f..8ded209736c 100644
--- a/chromium/content/common/OWNERS
+++ b/chromium/content/common/OWNERS
@@ -72,8 +72,17 @@ per-file *font_config_ipc_linux*=wfh@chromium.org
# Changes to Mojo interfaces require a security review to avoid
# introducing new sandbox escapes.
per-file *.mojom=set noparent
+per-file *.mojom=dcheng@chromium.org
+per-file *.mojom=inferno@chromium.org
+per-file *.mojom=jln@chromium.org
+per-file *.mojom=jschuh@chromium.org
+per-file *.mojom=kenrb@chromium.org
+per-file *.mojom=mkwst@chromium.org
+per-file *.mojom=nasko@chromium.org
per-file *.mojom=palmer@chromium.org
per-file *.mojom=tsepez@chromium.org
+per-file *.mojom=wfh@chromium.org
+
# Accessibility
per-file accessibility_node_data.*=dmazzoni@chromium.org
@@ -91,3 +100,7 @@ per-file cc_messages_perftest.cc=danakj@chromium.org
# DirectWrite
per-file dwrite_font_platform_win*=scottmg@chromium.org
per-file font_warmup_win.cc=scottmg@chromium.org
+
+# Web Notifications
+per-file notification_constants.h=peter@chromium.org
+per-file notification_constants.h=mvanouwerkerk@chromium.org
diff --git a/chromium/content/common/accelerated_surface_buffers_swapped_params_mac.cc b/chromium/content/common/accelerated_surface_buffers_swapped_params_mac.cc
new file mode 100644
index 00000000000..c9eb1d204ce
--- /dev/null
+++ b/chromium/content/common/accelerated_surface_buffers_swapped_params_mac.cc
@@ -0,0 +1,14 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/accelerated_surface_buffers_swapped_params_mac.h"
+
+namespace content {
+AcceleratedSurfaceBuffersSwappedParams::AcceleratedSurfaceBuffersSwappedParams()
+ : surface_id(0), ca_context_id(0), scale_factor(1.f) {}
+
+AcceleratedSurfaceBuffersSwappedParams::
+ ~AcceleratedSurfaceBuffersSwappedParams() {}
+
+} // namespace content
diff --git a/chromium/content/common/accelerated_surface_buffers_swapped_params_mac.h b/chromium/content/common/accelerated_surface_buffers_swapped_params_mac.h
new file mode 100644
index 00000000000..71fb4ffd777
--- /dev/null
+++ b/chromium/content/common/accelerated_surface_buffers_swapped_params_mac.h
@@ -0,0 +1,28 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_ACCELERATED_SURFACE_BUFFERS_SWAPPED_PARAMS_MAC_H_
+#define CONTENT_COMMON_ACCELERATED_SURFACE_BUFFERS_SWAPPED_PARAMS_MAC_H_
+
+#include "ui/base/cocoa/remote_layer_api.h"
+#include "ui/events/latency_info.h"
+#include "ui/gfx/mac/io_surface.h"
+
+namespace content {
+
+struct AcceleratedSurfaceBuffersSwappedParams {
+ AcceleratedSurfaceBuffersSwappedParams();
+ ~AcceleratedSurfaceBuffersSwappedParams();
+
+ int32_t surface_id;
+ CAContextID ca_context_id;
+ gfx::ScopedRefCountedIOSurfaceMachPort io_surface;
+ gfx::Size size;
+ float scale_factor;
+ std::vector<ui::LatencyInfo> latency_info;
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_ACCELERATED_SURFACE_BUFFERS_SWAPPED_PARAMS_MAC_H_
diff --git a/chromium/content/common/accessibility_messages.h b/chromium/content/common/accessibility_messages.h
index f30b5e41660..2a300eab93a 100644
--- a/chromium/content/common/accessibility_messages.h
+++ b/chromium/content/common/accessibility_messages.h
@@ -8,7 +8,6 @@
#include "content/common/ax_content_node_data.h"
#include "content/common/content_export.h"
#include "content/common/view_message_enums.h"
-#include "content/public/common/common_param_traits.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_message_utils.h"
#include "ipc/ipc_param_traits.h"
@@ -16,6 +15,7 @@
#include "third_party/WebKit/public/web/WebAXEnums.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/ax_tree_update.h"
+#include "ui/gfx/transform.h"
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
@@ -30,6 +30,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::AXContentNodeData)
IPC_STRUCT_TRAITS_MEMBER(role)
IPC_STRUCT_TRAITS_MEMBER(state)
IPC_STRUCT_TRAITS_MEMBER(location)
+ IPC_STRUCT_TRAITS_MEMBER(transform)
IPC_STRUCT_TRAITS_MEMBER(string_attributes)
IPC_STRUCT_TRAITS_MEMBER(int_attributes)
IPC_STRUCT_TRAITS_MEMBER(float_attributes)
@@ -43,12 +44,14 @@ IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(content::AXContentTreeData)
IPC_STRUCT_TRAITS_MEMBER(tree_id)
IPC_STRUCT_TRAITS_MEMBER(parent_tree_id)
+ IPC_STRUCT_TRAITS_MEMBER(focused_tree_id)
IPC_STRUCT_TRAITS_MEMBER(url)
IPC_STRUCT_TRAITS_MEMBER(title)
IPC_STRUCT_TRAITS_MEMBER(mimetype)
IPC_STRUCT_TRAITS_MEMBER(doctype)
IPC_STRUCT_TRAITS_MEMBER(loaded)
IPC_STRUCT_TRAITS_MEMBER(loading_progress)
+ IPC_STRUCT_TRAITS_MEMBER(focus_id)
IPC_STRUCT_TRAITS_MEMBER(sel_anchor_object_id)
IPC_STRUCT_TRAITS_MEMBER(sel_anchor_offset)
IPC_STRUCT_TRAITS_MEMBER(sel_focus_object_id)
@@ -156,8 +159,13 @@ IPC_MESSAGE_ROUTED2(AccessibilityMsg_SetValue,
int /* object id */,
base::string16 /* Value */)
-// Determine the accessibility object under a given point and reply with
-// a AccessibilityHostMsg_HitTestResult with the same id.
+// Determine the accessibility object under a given point.
+//
+// If the target is an object with a child frame (like if the hit test
+// result is an iframe element), it responds with
+// AccessibilityHostMsg_ChildFrameHitTestResult so that the
+// hit test can be performed recursively on the child frame. Otherwise
+// it fires an accessibility event of type ui::AX_EVENT_HOVER on the target.
IPC_MESSAGE_ROUTED1(AccessibilityMsg_HitTest,
gfx::Point /* location to test */)
@@ -210,11 +218,16 @@ IPC_MESSAGE_ROUTED1(
AccessibilityHostMsg_LocationChanges,
std::vector<AccessibilityHostMsg_LocationChangeParams>)
-// Sent to update the browser of the location of accessibility objects.
+// Sent to update the browser of Find In Page results.
IPC_MESSAGE_ROUTED1(
AccessibilityHostMsg_FindInPageResult,
AccessibilityHostMsg_FindInPageResultParams)
+// Sent in response to AccessibilityMsg_HitTest.
+IPC_MESSAGE_ROUTED2(AccessibilityHostMsg_ChildFrameHitTestResult,
+ gfx::Point /* location tested */,
+ int /* node id of result */)
+
// Sent in response to AccessibilityMsg_SnapshotTree. The callback id that was
// passed to the request will be returned in |callback_id|, along with
// a standalone snapshot of the accessibility tree.
diff --git a/chromium/content/common/android/address_parser_internal.cc b/chromium/content/common/android/address_parser_internal.cc
index 4f114a3f106..9892bd853fb 100644
--- a/chromium/content/common/android/address_parser_internal.cc
+++ b/chromium/content/common/android/address_parser_internal.cc
@@ -77,6 +77,8 @@ Word::Word(const base::string16::const_iterator& begin,
DCHECK(begin <= end);
}
+Word::Word(const Word& other) = default;
+
HouseNumberParser::HouseNumberParser() {
}
diff --git a/chromium/content/common/android/address_parser_internal.h b/chromium/content/common/android/address_parser_internal.h
index 5defd08de2a..60c1483fc03 100644
--- a/chromium/content/common/android/address_parser_internal.h
+++ b/chromium/content/common/android/address_parser_internal.h
@@ -28,6 +28,7 @@ struct CONTENT_EXPORT Word {
Word();
Word(const base::string16::const_iterator& begin,
const base::string16::const_iterator& end);
+ Word(const Word& other);
};
// Exposed for tests.
diff --git a/chromium/content/common/android/media_metadata_android.cc b/chromium/content/common/android/media_metadata_android.cc
new file mode 100644
index 00000000000..0bd15631758
--- /dev/null
+++ b/chromium/content/common/android/media_metadata_android.cc
@@ -0,0 +1,33 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/android/media_metadata_android.h"
+
+#include "base/android/jni_string.h"
+#include "content/public/common/media_metadata.h"
+#include "jni/MediaMetadata_jni.h"
+
+namespace content {
+
+// static
+base::android::ScopedJavaLocalRef<jobject>
+MediaMetadataAndroid::CreateJavaObject(
+ JNIEnv* env, const MediaMetadata& metadata) {
+ ScopedJavaLocalRef<jstring> j_title(
+ base::android::ConvertUTF16ToJavaString(env, metadata.title));
+ ScopedJavaLocalRef<jstring> j_artist(
+ base::android::ConvertUTF16ToJavaString(env, metadata.artist));
+ ScopedJavaLocalRef<jstring> j_album(
+ base::android::ConvertUTF16ToJavaString(env, metadata.album));
+
+ return Java_MediaMetadata_create(
+ env, j_title.obj(), j_artist.obj(), j_album.obj());
+}
+
+// static
+bool MediaMetadataAndroid::Register(JNIEnv* env) {
+ return RegisterNativesImpl(env);
+}
+
+} // namespace content
diff --git a/chromium/content/common/android/media_metadata_android.h b/chromium/content/common/android/media_metadata_android.h
new file mode 100644
index 00000000000..e580e53af0f
--- /dev/null
+++ b/chromium/content/common/android/media_metadata_android.h
@@ -0,0 +1,29 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_ANDROID_MEDIA_METADATA_ANDROID_H_
+#define CONTENT_COMMON_ANDROID_MEDIA_METADATA_ANDROID_H_
+
+#include <jni.h>
+
+#include "base/android/scoped_java_ref.h"
+
+namespace content {
+
+struct MediaMetadata;
+
+class MediaMetadataAndroid {
+ public:
+ static base::android::ScopedJavaLocalRef<jobject> CreateJavaObject(
+ JNIEnv* env, const MediaMetadata& metadata);
+
+ static bool Register(JNIEnv* env);
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(MediaMetadataAndroid);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_ANDROID_MEDIA_METADATA_ANDROID_H_
diff --git a/chromium/content/common/android/surface_texture_manager.cc b/chromium/content/common/android/surface_texture_manager.cc
deleted file mode 100644
index c2cb6eeb983..00000000000
--- a/chromium/content/common/android/surface_texture_manager.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/android/surface_texture_manager.h"
-
-#include "base/logging.h"
-
-namespace content {
-namespace {
-
-SurfaceTextureManager* g_instance = NULL;
-
-} // namespace
-
-// static
-SurfaceTextureManager* SurfaceTextureManager::GetInstance() {
- DCHECK(g_instance);
- return g_instance;
-}
-
-// static
-void SurfaceTextureManager::SetInstance(SurfaceTextureManager* instance) {
- DCHECK(!g_instance || !instance);
- g_instance = instance;
-}
-
-} // namespace content
diff --git a/chromium/content/common/android/surface_texture_manager.h b/chromium/content/common/android/surface_texture_manager.h
deleted file mode 100644
index 30a17dc9e15..00000000000
--- a/chromium/content/common/android/surface_texture_manager.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_ANDROID_SURFACE_TEXTURE_MANAGER_H_
-#define CONTENT_COMMON_ANDROID_SURFACE_TEXTURE_MANAGER_H_
-
-#include "content/common/content_export.h"
-#include "ui/gfx/native_widget_types.h"
-
-namespace gfx {
-class SurfaceTexture;
-}
-
-namespace content {
-
-class CONTENT_EXPORT SurfaceTextureManager {
- public:
- static SurfaceTextureManager* GetInstance();
- static void SetInstance(SurfaceTextureManager* instance);
-
- // Register a surface texture for use in another process.
- virtual void RegisterSurfaceTexture(int surface_texture_id,
- int client_id,
- gfx::SurfaceTexture* surface_texture) = 0;
-
- // Unregister a surface texture previously registered for use in another
- // process.
- virtual void UnregisterSurfaceTexture(int surface_texture_id,
- int client_id) = 0;
-
- // Acquire native widget for a registered surface texture.
- virtual gfx::AcceleratedWidget AcquireNativeWidgetForSurfaceTexture(
- int surface_texture_id) = 0;
-
- protected:
- virtual ~SurfaceTextureManager() {}
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_ANDROID_SURFACE_TEXTURE_MANAGER_H_
diff --git a/chromium/content/common/android/surface_texture_peer.cc b/chromium/content/common/android/surface_texture_peer.cc
deleted file mode 100644
index a6fade45e69..00000000000
--- a/chromium/content/common/android/surface_texture_peer.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/android/surface_texture_peer.h"
-
-#include "base/logging.h"
-
-namespace content {
-
-namespace {
-SurfaceTexturePeer* g_instance_ = NULL;
-} // namespace
-
-SurfaceTexturePeer::SurfaceTexturePeer() {
-}
-
-SurfaceTexturePeer::~SurfaceTexturePeer() {
-}
-
-// static
-SurfaceTexturePeer* SurfaceTexturePeer::GetInstance() {
- DCHECK(g_instance_);
- return g_instance_;
-}
-
-// static
-void SurfaceTexturePeer::InitInstance(SurfaceTexturePeer* instance) {
- DCHECK(!g_instance_);
- g_instance_ = instance;
-}
-
-} // namespace content
diff --git a/chromium/content/common/android/surface_texture_peer.h b/chromium/content/common/android/surface_texture_peer.h
deleted file mode 100644
index 0afe3efcf53..00000000000
--- a/chromium/content/common/android/surface_texture_peer.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_ANDROID_SURFACE_TEXTURE_PEER_H_
-#define CONTENT_COMMON_ANDROID_SURFACE_TEXTURE_PEER_H_
-
-#include "base/macros.h"
-#include "base/process/process.h"
-#include "ui/gl/android/surface_texture.h"
-
-namespace content {
-
-class SurfaceTexturePeer {
- public:
- static SurfaceTexturePeer* GetInstance();
-
- static void InitInstance(SurfaceTexturePeer* instance);
-
- // Establish the producer end for the given surface texture in another
- // process.
- virtual void EstablishSurfaceTexturePeer(
- base::ProcessHandle pid,
- scoped_refptr<gfx::SurfaceTexture> surface_texture,
- int primary_id,
- int secondary_id) = 0;
-
- protected:
- SurfaceTexturePeer();
- virtual ~SurfaceTexturePeer();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SurfaceTexturePeer);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_ANDROID_SURFACE_TEXTURE_PEER_H_
diff --git a/chromium/content/common/android/sync_compositor_messages.cc b/chromium/content/common/android/sync_compositor_messages.cc
index f44415f375f..1423091bd74 100644
--- a/chromium/content/common/android/sync_compositor_messages.cc
+++ b/chromium/content/common/android/sync_compositor_messages.cc
@@ -8,6 +8,7 @@ namespace content {
SyncCompositorCommonBrowserParams::SyncCompositorCommonBrowserParams()
: bytes_limit(0u),
+ output_surface_id_for_returned_resources(0u),
update_root_scroll_offset(false),
begin_frame_source_paused(false) {}
@@ -44,9 +45,9 @@ SyncCompositorCommonRendererParams::SyncCompositorCommonRendererParams()
min_page_scale_factor(0.f),
max_page_scale_factor(0.f),
need_animate_scroll(false),
- need_invalidate(false),
+ need_invalidate_count(0u),
need_begin_frame(false),
- did_activate_pending_tree(false) {}
+ did_activate_pending_tree_count(0u) {}
SyncCompositorCommonRendererParams::~SyncCompositorCommonRendererParams() {}
diff --git a/chromium/content/common/android/sync_compositor_messages.h b/chromium/content/common/android/sync_compositor_messages.h
index a91440764b8..0ec4bf4cec5 100644
--- a/chromium/content/common/android/sync_compositor_messages.h
+++ b/chromium/content/common/android/sync_compositor_messages.h
@@ -14,6 +14,7 @@
#include "content/common/input/input_event_ack_state.h"
#include "ipc/ipc_message_macros.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/scroll_offset.h"
#ifndef CONTENT_COMMON_ANDROID_SYNC_COMPOSITOR_MESSAGES_H_
@@ -25,7 +26,8 @@ struct SyncCompositorCommonBrowserParams {
SyncCompositorCommonBrowserParams();
~SyncCompositorCommonBrowserParams();
- size_t bytes_limit;
+ uint32_t bytes_limit;
+ uint32_t output_surface_id_for_returned_resources;
cc::CompositorFrameAck ack;
gfx::ScrollOffset root_scroll_offset;
bool update_root_scroll_offset;
@@ -54,7 +56,7 @@ struct SyncCompositorDemandDrawHwParams {
struct SyncCompositorSetSharedMemoryParams {
SyncCompositorSetSharedMemoryParams();
- size_t buffer_size;
+ uint32_t buffer_size;
base::SharedMemoryHandle shm_handle;
};
@@ -79,9 +81,9 @@ struct SyncCompositorCommonRendererParams {
float min_page_scale_factor;
float max_page_scale_factor;
bool need_animate_scroll;
- bool need_invalidate;
+ uint32_t need_invalidate_count;
bool need_begin_frame;
- bool did_activate_pending_tree;
+ uint32_t did_activate_pending_tree_count;
};
} // namespace content
@@ -96,6 +98,7 @@ struct SyncCompositorCommonRendererParams {
IPC_STRUCT_TRAITS_BEGIN(content::SyncCompositorCommonBrowserParams)
IPC_STRUCT_TRAITS_MEMBER(bytes_limit)
+ IPC_STRUCT_TRAITS_MEMBER(output_surface_id_for_returned_resources)
IPC_STRUCT_TRAITS_MEMBER(ack)
IPC_STRUCT_TRAITS_MEMBER(root_scroll_offset)
IPC_STRUCT_TRAITS_MEMBER(update_root_scroll_offset)
@@ -131,12 +134,14 @@ IPC_STRUCT_TRAITS_BEGIN(content::SyncCompositorCommonRendererParams)
IPC_STRUCT_TRAITS_MEMBER(min_page_scale_factor)
IPC_STRUCT_TRAITS_MEMBER(max_page_scale_factor)
IPC_STRUCT_TRAITS_MEMBER(need_animate_scroll)
- IPC_STRUCT_TRAITS_MEMBER(need_invalidate)
+ IPC_STRUCT_TRAITS_MEMBER(need_invalidate_count)
IPC_STRUCT_TRAITS_MEMBER(need_begin_frame)
- IPC_STRUCT_TRAITS_MEMBER(did_activate_pending_tree)
+ IPC_STRUCT_TRAITS_MEMBER(did_activate_pending_tree_count)
IPC_STRUCT_TRAITS_END()
// Messages sent from the browser to the renderer.
+// Synchronous IPCs are allowed here to the renderer compositor thread. See
+// design doc https://goo.gl/Tn81FW and crbug.com/526842 for details.
IPC_SYNC_MESSAGE_ROUTED2_2(SyncCompositorMsg_HandleInputEvent,
content::SyncCompositorCommonBrowserParams,
@@ -149,15 +154,15 @@ IPC_SYNC_MESSAGE_ROUTED2_1(SyncCompositorMsg_BeginFrame,
cc::BeginFrameArgs,
content::SyncCompositorCommonRendererParams)
-IPC_SYNC_MESSAGE_ROUTED2_1(SyncCompositorMsg_ComputeScroll,
- content::SyncCompositorCommonBrowserParams,
- base::TimeTicks,
- content::SyncCompositorCommonRendererParams)
+IPC_MESSAGE_ROUTED2(SyncCompositorMsg_ComputeScroll,
+ content::SyncCompositorCommonBrowserParams,
+ base::TimeTicks);
-IPC_SYNC_MESSAGE_ROUTED2_2(SyncCompositorMsg_DemandDrawHw,
+IPC_SYNC_MESSAGE_ROUTED2_3(SyncCompositorMsg_DemandDrawHw,
content::SyncCompositorCommonBrowserParams,
content::SyncCompositorDemandDrawHwParams,
content::SyncCompositorCommonRendererParams,
+ uint32_t /* output_surface_id */,
cc::CompositorFrame)
IPC_SYNC_MESSAGE_ROUTED2_2(SyncCompositorMsg_SetSharedMemory,
@@ -178,6 +183,12 @@ IPC_SYNC_MESSAGE_ROUTED2_3(SyncCompositorMsg_DemandDrawSw,
IPC_MESSAGE_ROUTED1(SyncCompositorMsg_UpdateState,
content::SyncCompositorCommonBrowserParams)
+IPC_SYNC_MESSAGE_ROUTED3_1(SyncCompositorMsg_ZoomBy,
+ content::SyncCompositorCommonBrowserParams,
+ float /* delta */,
+ gfx::Point /* anchor */,
+ content::SyncCompositorCommonRendererParams)
+
// -----------------------------------------------------------------------------
// Messages sent from the renderer to the browser.
diff --git a/chromium/content/common/appcache_interfaces.cc b/chromium/content/common/appcache_interfaces.cc
index af0d8c16883..8342a364f0f 100644
--- a/chromium/content/common/appcache_interfaces.cc
+++ b/chromium/content/common/appcache_interfaces.cc
@@ -31,6 +31,8 @@ AppCacheInfo::AppCacheInfo()
is_complete(false) {
}
+AppCacheInfo::AppCacheInfo(const AppCacheInfo& other) = default;
+
AppCacheInfo::~AppCacheInfo() {
}
@@ -46,6 +48,9 @@ AppCacheResourceInfo::AppCacheResourceInfo()
response_id(kAppCacheNoResponseId) {
}
+AppCacheResourceInfo::AppCacheResourceInfo(const AppCacheResourceInfo& other) =
+ default;
+
AppCacheResourceInfo::~AppCacheResourceInfo() {
}
diff --git a/chromium/content/common/appcache_interfaces.h b/chromium/content/common/appcache_interfaces.h
index 8ba2da072b9..12cc7c11d5d 100644
--- a/chromium/content/common/appcache_interfaces.h
+++ b/chromium/content/common/appcache_interfaces.h
@@ -62,6 +62,7 @@ enum AppCacheErrorReason {
// Type to hold information about a single appcache resource.
struct CONTENT_EXPORT AppCacheResourceInfo {
AppCacheResourceInfo();
+ AppCacheResourceInfo(const AppCacheResourceInfo& other);
~AppCacheResourceInfo();
GURL url;
diff --git a/chromium/content/common/appcache_messages.h b/chromium/content/common/appcache_messages.h
index 7e74848e4dd..95964f71c9d 100644
--- a/chromium/content/common/appcache_messages.h
+++ b/chromium/content/common/appcache_messages.h
@@ -9,6 +9,7 @@
#include <stdint.h>
#include "content/common/appcache_interfaces.h"
+#include "url/ipc/url_param_traits.h"
#define IPC_MESSAGE_START AppCacheMsgStart
diff --git a/chromium/content/common/application_setup.mojom b/chromium/content/common/application_setup.mojom
index df45c5ac22f..8fb0e174c88 100644
--- a/chromium/content/common/application_setup.mojom
+++ b/chromium/content/common/application_setup.mojom
@@ -2,11 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-module content;
+module content.mojom;
-import "mojo/shell/public/interfaces/service_provider.mojom";
+import "mojo/shell/public/interfaces/interface_provider.mojom";
interface ApplicationSetup {
- ExchangeServiceProviders(mojo.ServiceProvider& services,
- mojo.ServiceProvider exposed_services);
+ ExchangeInterfaceProviders(
+ mojo.shell.mojom.InterfaceProvider& remote_interfaces,
+ mojo.shell.mojom.InterfaceProvider local_interfaces);
};
diff --git a/chromium/content/common/ax_content_node_data.cc b/chromium/content/common/ax_content_node_data.cc
index fda36683ca4..d528727aa87 100644
--- a/chromium/content/common/ax_content_node_data.cc
+++ b/chromium/content/common/ax_content_node_data.cc
@@ -33,6 +33,8 @@ typename std::vector<std::pair<FirstType, SecondType>>::const_iterator
AXContentNodeData::AXContentNodeData() {
}
+AXContentNodeData::AXContentNodeData(const AXContentNodeData& other) = default;
+
AXContentNodeData::~AXContentNodeData() {
}
diff --git a/chromium/content/common/ax_content_node_data.h b/chromium/content/common/ax_content_node_data.h
index 00849cdae6a..93ab7191942 100644
--- a/chromium/content/common/ax_content_node_data.h
+++ b/chromium/content/common/ax_content_node_data.h
@@ -28,6 +28,7 @@ enum AXContentIntAttribute {
// content-layer-specific AX attributes.
struct CONTENT_EXPORT AXContentNodeData : public ui::AXNodeData {
AXContentNodeData();
+ AXContentNodeData(const AXContentNodeData& other);
~AXContentNodeData() override;
bool HasContentIntAttribute(AXContentIntAttribute attribute) const;
diff --git a/chromium/content/common/background_sync_service.mojom b/chromium/content/common/background_sync_service.mojom
index d1b0cd1089c..cceb58c31b3 100644
--- a/chromium/content/common/background_sync_service.mojom
+++ b/chromium/content/common/background_sync_service.mojom
@@ -2,10 +2,9 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-module content;
+module content.mojom;
import "content/public/common/background_sync.mojom";
-import "content/public/common/permission_status.mojom";
import "content/public/common/service_worker_event_status.mojom";
enum BackgroundSyncError {
@@ -14,17 +13,14 @@ enum BackgroundSyncError {
NOT_FOUND,
NO_SERVICE_WORKER,
NOT_ALLOWED,
- MAX=NOT_ALLOWED
+ PERMISSION_DENIED,
+ MAX=PERMISSION_DENIED
};
enum BackgroundSyncState {
PENDING,
FIRING,
- UNREGISTERED_WHILE_FIRING,
REREGISTERED_WHILE_FIRING,
- FAILED,
- SUCCESS,
- UNREGISTERED
};
enum BackgroundSyncEventLastChance {
@@ -33,28 +29,14 @@ enum BackgroundSyncEventLastChance {
};
interface BackgroundSyncService {
- Register(SyncRegistration options, int64 service_worker_registration_id,
- bool requested_from_service_worker)
+ Register(SyncRegistration options, int64 service_worker_registration_id)
=> (BackgroundSyncError err, SyncRegistration options);
- GetRegistration(BackgroundSyncPeriodicity periodicity, string tag,
- int64 service_worker_registration_id)
- => (BackgroundSyncError err, SyncRegistration? registration);
- GetRegistrations(BackgroundSyncPeriodicity periodicity,
- int64 service_worker_registration_id)
+ GetRegistrations(int64 service_worker_registration_id)
=> (BackgroundSyncError err, array<SyncRegistration> registrations);
- Unregister(int64 handle_id, int64 service_worker_registration_id)
- => (BackgroundSyncError err);
- GetPermissionStatus(BackgroundSyncPeriodicity periodicity,
- int64 service_worker_registration_id)
- => (BackgroundSyncError err, PermissionStatus status);
- DuplicateRegistrationHandle(int64 handle_id)
- => (BackgroundSyncError err, SyncRegistration? registration);
- ReleaseRegistration(int64 handle_id);
- NotifyWhenFinished(int64 handle_id) => (BackgroundSyncError err, BackgroundSyncState final_status);
};
interface BackgroundSyncServiceClient {
- Sync(int64 handle_id, BackgroundSyncEventLastChance last_chance)
+ Sync(string tag, BackgroundSyncEventLastChance last_chance)
=> (ServiceWorkerEventStatus status);
};
diff --git a/chromium/content/common/bluetooth/bluetooth_messages.h b/chromium/content/common/bluetooth/bluetooth_messages.h
index df7695d67f4..68b51e34f61 100644
--- a/chromium/content/common/bluetooth/bluetooth_messages.h
+++ b/chromium/content/common/bluetooth/bluetooth_messages.h
@@ -129,13 +129,12 @@ IPC_MESSAGE_CONTROL3(BluetoothMsg_RequestDeviceError,
blink::WebBluetoothError /* result */)
// Informs the renderer that the connection request |request_id| succeeded.
-IPC_MESSAGE_CONTROL3(BluetoothMsg_ConnectGATTSuccess,
+IPC_MESSAGE_CONTROL2(BluetoothMsg_GATTServerConnectSuccess,
int /* thread_id */,
- int /* request_id */,
- std::string /* device_id */)
+ int /* request_id */)
// Informs the renderer that the connection request |request_id| failed.
-IPC_MESSAGE_CONTROL3(BluetoothMsg_ConnectGATTError,
+IPC_MESSAGE_CONTROL3(BluetoothMsg_GATTServerConnectError,
int /* thread_id */,
int /* request_id */,
blink::WebBluetoothError /* result */)
@@ -165,6 +164,23 @@ IPC_MESSAGE_CONTROL3(BluetoothMsg_GetCharacteristicError,
int /* request_id */,
blink::WebBluetoothError /* result */)
+// Informs the renderer that the multiple-characteristic request |request_id|
+// succeeded.
+IPC_MESSAGE_CONTROL5(
+ BluetoothMsg_GetCharacteristicsSuccess,
+ int /* thread_id */,
+ int /* request_id */,
+ std::vector<std::string> /* characteristics_instance_ids */,
+ std::vector<std::string> /* characteristics_uuids */,
+ std::vector<uint32_t> /* characteristics_properties */)
+
+// Informs the renderer that the multiple-characteristic request |request_id|
+// failed.
+IPC_MESSAGE_CONTROL3(BluetoothMsg_GetCharacteristicsError,
+ int /* thread_id */,
+ int /* request_id */,
+ blink::WebBluetoothError /* result */)
+
// Informs the renderer that the value has been read.
IPC_MESSAGE_CONTROL3(BluetoothMsg_ReadCharacteristicValueSuccess,
int /* thread_id */,
@@ -177,19 +193,6 @@ IPC_MESSAGE_CONTROL3(BluetoothMsg_ReadCharacteristicValueError,
int /* request_id */,
blink::WebBluetoothError /* result */)
-// Informs the renderer that the value has been successfully written to
-// the characteristic.
-IPC_MESSAGE_CONTROL2(BluetoothMsg_WriteCharacteristicValueSuccess,
- int /* thread_id */,
- int /* request_id */)
-
-// Informs the renderer that an error occurred while writing a value to a
-// characteristic.
-IPC_MESSAGE_CONTROL3(BluetoothMsg_WriteCharacteristicValueError,
- int /* thread_id */,
- int /* request_id */,
- blink::WebBluetoothError /* result */)
-
// Informs the renderer that the user has successfully subscribed to
// notifications from the device.
IPC_MESSAGE_CONTROL2(BluetoothMsg_StartNotificationsSuccess,
@@ -226,12 +229,18 @@ IPC_MESSAGE_CONTROL5(BluetoothHostMsg_RequestDevice,
std::vector<device::BluetoothUUID> /* optional_services */)
// Connects to a bluetooth device.
-IPC_MESSAGE_CONTROL4(BluetoothHostMsg_ConnectGATT,
+IPC_MESSAGE_CONTROL4(BluetoothHostMsg_GATTServerConnect,
int /* thread_id */,
int /* request_id */,
int /* frame_routing_id */,
std::string /* device_id */)
+// Disconnect from a device.
+IPC_MESSAGE_CONTROL3(BluetoothHostMsg_GATTServerDisconnect,
+ int /* thread_id */,
+ int /* frame_routing_id */,
+ std::string /* device_id */)
+
// Gets primary service from bluetooth device.
IPC_MESSAGE_CONTROL5(BluetoothHostMsg_GetPrimaryService,
int /* thread_id */,
@@ -248,20 +257,20 @@ IPC_MESSAGE_CONTROL5(BluetoothHostMsg_GetCharacteristic,
std::string /* service_instance_id */,
std::string /* characteristic_uuid */)
-// Reads the characteristics value from a bluetooth device.
-IPC_MESSAGE_CONTROL4(BluetoothHostMsg_ReadValue,
+// Gets GATT Characteristics within a GATT Service.
+IPC_MESSAGE_CONTROL5(BluetoothHostMsg_GetCharacteristics,
int /* thread_id */,
int /* request_id */,
int /* frame_routing_id */,
- std::string /* characteristic_instance_id */)
+ std::string /* service_instance_id */,
+ std::string /* characteristics_uuid */)
-// Writes a value to a bluetooth device's characteristic.
-IPC_MESSAGE_CONTROL5(BluetoothHostMsg_WriteValue,
+// Reads the characteristics value from a bluetooth device.
+IPC_MESSAGE_CONTROL4(BluetoothHostMsg_ReadValue,
int /* thread_id */,
int /* request_id */,
int /* frame_routing_id */,
- std::string /* characteristic_instance_id */,
- std::vector<uint8_t> /* value */)
+ std::string /* characteristic_instance_id */)
// Subscribes to notifications from a device's characteristic.
IPC_MESSAGE_CONTROL4(BluetoothHostMsg_StartNotifications,
diff --git a/chromium/content/common/bluetooth/bluetooth_scan_filter.cc b/chromium/content/common/bluetooth/bluetooth_scan_filter.cc
index 3ab22aedfa3..2c5a7cb87a9 100644
--- a/chromium/content/common/bluetooth/bluetooth_scan_filter.cc
+++ b/chromium/content/common/bluetooth/bluetooth_scan_filter.cc
@@ -9,6 +9,9 @@ namespace content {
BluetoothScanFilter::BluetoothScanFilter() : services() {
}
+BluetoothScanFilter::BluetoothScanFilter(const BluetoothScanFilter& other) =
+ default;
+
BluetoothScanFilter::~BluetoothScanFilter() {
}
diff --git a/chromium/content/common/bluetooth/bluetooth_scan_filter.h b/chromium/content/common/bluetooth/bluetooth_scan_filter.h
index 257274729d3..6c0bb3374e1 100644
--- a/chromium/content/common/bluetooth/bluetooth_scan_filter.h
+++ b/chromium/content/common/bluetooth/bluetooth_scan_filter.h
@@ -17,6 +17,7 @@ namespace content {
// blink::WebBluetoothScanFilter.
struct CONTENT_EXPORT BluetoothScanFilter {
BluetoothScanFilter();
+ BluetoothScanFilter(const BluetoothScanFilter& other);
~BluetoothScanFilter();
std::vector<device::BluetoothUUID> services;
diff --git a/chromium/content/common/browser_plugin/browser_plugin_messages.h b/chromium/content/common/browser_plugin/browser_plugin_messages.h
index 1a264ce04a8..eef580508a6 100644
--- a/chromium/content/common/browser_plugin/browser_plugin_messages.h
+++ b/chromium/content/common/browser_plugin/browser_plugin_messages.h
@@ -12,8 +12,6 @@
#include "content/common/content_param_traits.h"
#include "content/common/cursors/webcursor.h"
#include "content/common/edit_command.h"
-#include "content/common/frame_param_macros.h"
-#include "content/public/common/common_param_traits.h"
#include "content/public/common/drop_data.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_message_macros.h"
@@ -27,7 +25,7 @@
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/ipc/gfx_param_traits.h"
-#include "url/gurl.h"
+#include "ui/gfx/ipc/skia/gfx_skia_param_traits.h"
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
@@ -112,18 +110,10 @@ IPC_MESSAGE_CONTROL3(BrowserPluginHostMsg_SetFocus,
blink::WebFocusType /* focus_type */)
// Sends an input event to the guest.
-IPC_MESSAGE_CONTROL3(BrowserPluginHostMsg_HandleInputEvent,
+IPC_MESSAGE_CONTROL2(BrowserPluginHostMsg_HandleInputEvent,
int /* browser_plugin_instance_id */,
- gfx::Rect /* guest_window_rect */,
IPC::WebInputEventPointer /* event */)
-// Notify the guest renderer that some resources given to the embededer
-// are not used any more.
-IPC_MESSAGE_CONTROL2(
- BrowserPluginHostMsg_ReclaimCompositorResources,
- int /* browser_plugin_instance_id */,
- FrameHostMsg_ReclaimCompositorResources_Params /* params */)
-
// Tells the guest it has been shown or hidden.
IPC_MESSAGE_CONTROL2(BrowserPluginHostMsg_SetVisibility,
int /* browser_plugin_instance_id */,
@@ -185,10 +175,6 @@ IPC_MESSAGE_CONTROL2(BrowserPluginMsg_SetCursor,
int /* browser_plugin_instance_id */,
content::WebCursor /* cursor */)
-IPC_MESSAGE_CONTROL2(BrowserPluginMsg_CompositorFrameSwapped,
- int /* browser_plugin_instance_id */,
- FrameMsg_CompositorFrameSwapped_Params /* params */)
-
IPC_MESSAGE_CONTROL5(BrowserPluginMsg_SetChildFrameSurface,
int /* browser_plugin_instance_id */,
cc::SurfaceId /* surface_id */,
@@ -205,8 +191,3 @@ IPC_MESSAGE_CONTROL2(BrowserPluginMsg_SetMouseLock,
IPC_MESSAGE_CONTROL2(BrowserPluginMsg_SetTooltipText,
int /* browser_plugin_instance_id */,
base::string16 /* tooltip_text */)
-
-// Acknowledge that we presented an ubercomp frame.
-IPC_MESSAGE_CONTROL2(BrowserPluginHostMsg_CompositorFrameSwappedACK,
- int /* browser_plugin_instance_id */,
- FrameHostMsg_CompositorFrameSwappedACK_Params /* params */)
diff --git a/chromium/content/common/buffer_presented_params_mac.cc b/chromium/content/common/buffer_presented_params_mac.cc
new file mode 100644
index 00000000000..795dc08fa4b
--- /dev/null
+++ b/chromium/content/common/buffer_presented_params_mac.cc
@@ -0,0 +1,13 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/buffer_presented_params_mac.h"
+
+namespace content {
+
+BufferPresentedParams::BufferPresentedParams() : surface_id(0) {}
+
+BufferPresentedParams::~BufferPresentedParams() {}
+
+} // namespace content
diff --git a/chromium/content/common/buffer_presented_params_mac.h b/chromium/content/common/buffer_presented_params_mac.h
new file mode 100644
index 00000000000..29e0dabf1b4
--- /dev/null
+++ b/chromium/content/common/buffer_presented_params_mac.h
@@ -0,0 +1,23 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_BUFFER_PRESENTED_PARAMS_MAC_H_
+#define CONTENT_COMMON_BUFFER_PRESENTED_PARAMS_MAC_H_
+
+#include "base/time/time.h"
+
+namespace content {
+
+struct BufferPresentedParams {
+ BufferPresentedParams();
+ ~BufferPresentedParams();
+
+ int32_t surface_id;
+ base::TimeTicks vsync_timebase;
+ base::TimeDelta vsync_interval;
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_BUFFER_PRESENTED_PARAMS_MAC_H_
diff --git a/chromium/content/common/cache_storage/cache_storage_messages.h b/chromium/content/common/cache_storage/cache_storage_messages.h
index 277f960ee6e..82fe7552d6c 100644
--- a/chromium/content/common/cache_storage/cache_storage_messages.h
+++ b/chromium/content/common/cache_storage/cache_storage_messages.h
@@ -13,7 +13,7 @@
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_param_traits.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerCacheError.h"
-#include "url/gurl.h"
+#include "url/origin.h"
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
@@ -51,30 +51,30 @@ IPC_ENUM_TRAITS_MAX_VALUE(blink::WebServiceWorkerCacheError,
IPC_MESSAGE_CONTROL4(CacheStorageHostMsg_CacheStorageHas,
int /* thread_id */,
int /* request_id */,
- GURL /* origin */,
+ url::Origin /* origin */,
base::string16 /* fetch_store_name */)
IPC_MESSAGE_CONTROL4(CacheStorageHostMsg_CacheStorageOpen,
int /* thread_id */,
int /* request_id */,
- GURL /* origin */,
+ url::Origin /* origin */,
base::string16 /* fetch_store_name */)
IPC_MESSAGE_CONTROL4(CacheStorageHostMsg_CacheStorageDelete,
int /* thread_id */,
int /* request_id */,
- GURL /* origin */,
+ url::Origin /* origin */,
base::string16 /* fetch_store_name */)
IPC_MESSAGE_CONTROL3(CacheStorageHostMsg_CacheStorageKeys,
int /* thread_id */,
int /* request_id */,
- GURL /* origin */)
+ url::Origin /* origin */)
IPC_MESSAGE_CONTROL5(CacheStorageHostMsg_CacheStorageMatch,
int /* thread_id */,
int /* request_id */,
- GURL /* origin */,
+ url::Origin /* origin */,
content::ServiceWorkerFetchRequest,
content::CacheStorageCacheQueryParams)
diff --git a/chromium/content/common/cache_storage/cache_storage_types.cc b/chromium/content/common/cache_storage/cache_storage_types.cc
index c2e5175d693..198e6eaf300 100644
--- a/chromium/content/common/cache_storage/cache_storage_types.cc
+++ b/chromium/content/common/cache_storage/cache_storage_types.cc
@@ -13,4 +13,7 @@ CacheStorageCacheQueryParams::CacheStorageCacheQueryParams()
CacheStorageBatchOperation::CacheStorageBatchOperation() {
}
+CacheStorageBatchOperation::CacheStorageBatchOperation(
+ const CacheStorageBatchOperation& other) = default;
+
} // namespace content
diff --git a/chromium/content/common/cache_storage/cache_storage_types.h b/chromium/content/common/cache_storage/cache_storage_types.h
index bd292966c0e..22e91c0636a 100644
--- a/chromium/content/common/cache_storage/cache_storage_types.h
+++ b/chromium/content/common/cache_storage/cache_storage_types.h
@@ -39,6 +39,7 @@ enum CacheStorageCacheOperationType {
// A single batch operation for the Cache API.
struct CONTENT_EXPORT CacheStorageBatchOperation {
CacheStorageBatchOperation();
+ CacheStorageBatchOperation(const CacheStorageBatchOperation& other);
CacheStorageCacheOperationType operation_type;
ServiceWorkerFetchRequest request;
@@ -53,7 +54,9 @@ enum CacheStorageError {
CACHE_STORAGE_ERROR_EXISTS,
CACHE_STORAGE_ERROR_STORAGE,
CACHE_STORAGE_ERROR_NOT_FOUND,
- CACHE_STORAGE_ERROR_LAST = CACHE_STORAGE_ERROR_NOT_FOUND
+ CACHE_STORAGE_ERROR_QUOTA_EXCEEDED,
+ CACHE_STORAGE_ERROR_CACHE_NAME_NOT_FOUND,
+ CACHE_STORAGE_ERROR_LAST = CACHE_STORAGE_ERROR_CACHE_NAME_NOT_FOUND
};
} // namespace content
diff --git a/chromium/content/common/cc_messages.cc b/chromium/content/common/cc_messages.cc
index 70729469c7c..f5c688ebd36 100644
--- a/chromium/content/common/cc_messages.cc
+++ b/chromium/content/common/cc_messages.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include <utility>
+#include "base/numerics/safe_conversions.h"
#include "cc/output/compositor_frame.h"
#include "cc/output/filter_operations.h"
#include "cc/quads/draw_quad.h"
@@ -15,12 +16,11 @@
#include "content/public/common/common_param_traits.h"
#include "third_party/skia/include/core/SkData.h"
#include "third_party/skia/include/core/SkFlattenableSerialization.h"
-#include "ui/gfx/transform.h"
namespace IPC {
-void ParamTraits<cc::FilterOperation>::Write(
- Message* m, const param_type& p) {
+void ParamTraits<cc::FilterOperation>::Write(base::Pickle* m,
+ const param_type& p) {
WriteParam(m, p.type());
switch (p.type()) {
case cc::FilterOperation::GRAYSCALE:
@@ -57,7 +57,7 @@ void ParamTraits<cc::FilterOperation>::Write(
}
}
-bool ParamTraits<cc::FilterOperation>::Read(const Message* m,
+bool ParamTraits<cc::FilterOperation>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
cc::FilterOperation::FilterType type;
@@ -184,18 +184,18 @@ void ParamTraits<cc::FilterOperation>::Log(
l->append(")");
}
-void ParamTraits<cc::FilterOperations>::Write(
- Message* m, const param_type& p) {
- WriteParam(m, p.size());
+void ParamTraits<cc::FilterOperations>::Write(base::Pickle* m,
+ const param_type& p) {
+ WriteParam(m, base::checked_cast<uint32_t>(p.size()));
for (std::size_t i = 0; i < p.size(); ++i) {
WriteParam(m, p.at(i));
}
}
-bool ParamTraits<cc::FilterOperations>::Read(const Message* m,
+bool ParamTraits<cc::FilterOperations>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
- size_t count;
+ uint32_t count;
if (!ReadParam(m, iter, &count))
return false;
@@ -219,19 +219,18 @@ void ParamTraits<cc::FilterOperations>::Log(
l->append(")");
}
-void ParamTraits<skia::RefPtr<SkImageFilter> >::Write(
- Message* m, const param_type& p) {
+void ParamTraits<skia::RefPtr<SkImageFilter>>::Write(base::Pickle* m,
+ const param_type& p) {
SkImageFilter* filter = p.get();
if (filter) {
- skia::RefPtr<SkData> data =
- skia::AdoptRef(SkValidatingSerializeFlattenable(filter));
+ sk_sp<SkData> data(SkValidatingSerializeFlattenable(filter));
m->WriteData(static_cast<const char*>(data->data()), data->size());
} else {
m->WriteData(0, 0);
}
}
-bool ParamTraits<skia::RefPtr<SkImageFilter>>::Read(const Message* m,
+bool ParamTraits<skia::RefPtr<SkImageFilter>>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
const char* data = 0;
@@ -255,55 +254,13 @@ void ParamTraits<skia::RefPtr<SkImageFilter> >::Log(
l->append(")");
}
-void ParamTraits<gfx::Transform>::Write(
- Message* m, const param_type& p) {
-#ifdef SK_MSCALAR_IS_FLOAT
- float column_major_data[16];
- p.matrix().asColMajorf(column_major_data);
-#else
- double column_major_data[16];
- p.matrix().asColMajord(column_major_data);
-#endif
- m->WriteBytes(&column_major_data, sizeof(SkMScalar) * 16);
-}
-
-bool ParamTraits<gfx::Transform>::Read(const Message* m,
- base::PickleIterator* iter,
- param_type* r) {
- const char* column_major_data;
- if (!iter->ReadBytes(&column_major_data, sizeof(SkMScalar) * 16))
- return false;
- r->matrix().setColMajor(
- reinterpret_cast<const SkMScalar*>(column_major_data));
- return true;
-}
-
-void ParamTraits<gfx::Transform>::Log(
- const param_type& p, std::string* l) {
-#ifdef SK_MSCALAR_IS_FLOAT
- float row_major_data[16];
- p.matrix().asRowMajorf(row_major_data);
-#else
- double row_major_data[16];
- p.matrix().asRowMajord(row_major_data);
-#endif
- l->append("(");
- for (int i = 0; i < 16; ++i) {
- if (i > 0)
- l->append(", ");
- LogParam(row_major_data[i], l);
- }
- l->append(") ");
-}
-
-void ParamTraits<cc::RenderPass>::Write(
- Message* m, const param_type& p) {
+void ParamTraits<cc::RenderPass>::Write(base::Pickle* m, const param_type& p) {
WriteParam(m, p.id);
WriteParam(m, p.output_rect);
WriteParam(m, p.damage_rect);
WriteParam(m, p.transform_to_root_target);
WriteParam(m, p.has_transparent_background);
- WriteParam(m, p.quad_list.size());
+ WriteParam(m, base::checked_cast<uint32_t>(p.quad_list.size()));
cc::SharedQuadStateList::ConstIterator shared_quad_state_iter =
p.shared_quad_state_list.begin();
@@ -390,7 +347,7 @@ static size_t ReserveSizeForRenderPassWrite(const cc::RenderPass& p) {
}
template <typename QuadType>
-static cc::DrawQuad* ReadDrawQuad(const Message* m,
+static cc::DrawQuad* ReadDrawQuad(const base::Pickle* m,
base::PickleIterator* iter,
cc::RenderPass* render_pass) {
QuadType* quad = render_pass->CreateAndAppendDrawQuad<QuadType>();
@@ -399,7 +356,7 @@ static cc::DrawQuad* ReadDrawQuad(const Message* m,
return quad;
}
-bool ParamTraits<cc::RenderPass>::Read(const Message* m,
+bool ParamTraits<cc::RenderPass>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* p) {
cc::RenderPassId id;
@@ -407,7 +364,7 @@ bool ParamTraits<cc::RenderPass>::Read(const Message* m,
gfx::Rect damage_rect;
gfx::Transform transform_to_root_target;
bool has_transparent_background;
- size_t quad_list_size;
+ uint32_t quad_list_size;
if (!ReadParam(m, iter, &id) || !ReadParam(m, iter, &output_rect) ||
!ReadParam(m, iter, &damage_rect) ||
@@ -422,7 +379,7 @@ bool ParamTraits<cc::RenderPass>::Read(const Message* m,
transform_to_root_target,
has_transparent_background);
- for (size_t i = 0; i < quad_list_size; ++i) {
+ for (uint32_t i = 0; i < quad_list_size; ++i) {
cc::DrawQuad::Material material;
base::PickleIterator temp_iter = *iter;
if (!ReadParam(m, &temp_iter, &material))
@@ -566,7 +523,7 @@ namespace {
};
}
-void ParamTraits<cc::CompositorFrame>::Write(Message* m,
+void ParamTraits<cc::CompositorFrame>::Write(base::Pickle* m,
const param_type& p) {
WriteParam(m, p.metadata);
if (p.delegated_frame_data) {
@@ -581,7 +538,7 @@ void ParamTraits<cc::CompositorFrame>::Write(Message* m,
}
}
-bool ParamTraits<cc::CompositorFrame>::Read(const Message* m,
+bool ParamTraits<cc::CompositorFrame>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* p) {
if (!ReadParam(m, iter, &p->metadata))
@@ -622,7 +579,7 @@ void ParamTraits<cc::CompositorFrame>::Log(const param_type& p,
l->append(")");
}
-void ParamTraits<cc::CompositorFrameAck>::Write(Message* m,
+void ParamTraits<cc::CompositorFrameAck>::Write(base::Pickle* m,
const param_type& p) {
WriteParam(m, p.resources);
if (p.gl_frame_data) {
@@ -633,7 +590,7 @@ void ParamTraits<cc::CompositorFrameAck>::Write(Message* m,
}
}
-bool ParamTraits<cc::CompositorFrameAck>::Read(const Message* m,
+bool ParamTraits<cc::CompositorFrameAck>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* p) {
if (!ReadParam(m, iter, &p->resources))
@@ -667,7 +624,7 @@ void ParamTraits<cc::CompositorFrameAck>::Log(const param_type& p,
l->append(")");
}
-void ParamTraits<cc::DelegatedFrameData>::Write(Message* m,
+void ParamTraits<cc::DelegatedFrameData>::Write(base::Pickle* m,
const param_type& p) {
DCHECK_NE(0u, p.render_pass_list.size());
@@ -681,15 +638,16 @@ void ParamTraits<cc::DelegatedFrameData>::Write(Message* m,
WriteParam(m, p.device_scale_factor);
WriteParam(m, p.resource_list);
- WriteParam(m, p.render_pass_list.size());
+ WriteParam(m, base::checked_cast<uint32_t>(p.render_pass_list.size()));
for (const auto& pass : p.render_pass_list) {
- WriteParam(m, pass->quad_list.size());
- WriteParam(m, pass->shared_quad_state_list.size());
+ WriteParam(m, base::checked_cast<uint32_t>(pass->quad_list.size()));
+ WriteParam(m, base::checked_cast<uint32_t>(
+ pass->shared_quad_state_list.size()));
WriteParam(m, *pass);
}
}
-bool ParamTraits<cc::DelegatedFrameData>::Read(const Message* m,
+bool ParamTraits<cc::DelegatedFrameData>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* p) {
if (!ReadParam(m, iter, &p->device_scale_factor))
@@ -701,21 +659,23 @@ bool ParamTraits<cc::DelegatedFrameData>::Read(const Message* m,
std::set<cc::RenderPassId> pass_set;
- size_t num_render_passes;
+ uint32_t num_render_passes;
if (!ReadParam(m, iter, &p->resource_list) ||
!ReadParam(m, iter, &num_render_passes) ||
num_render_passes > kMaxRenderPasses || num_render_passes == 0)
return false;
- for (size_t i = 0; i < num_render_passes; ++i) {
- size_t quad_list_size;
- size_t shared_quad_state_list_size;
+ for (uint32_t i = 0; i < num_render_passes; ++i) {
+ uint32_t quad_list_size;
+ uint32_t shared_quad_state_list_size;
if (!ReadParam(m, iter, &quad_list_size) ||
!ReadParam(m, iter, &shared_quad_state_list_size) ||
quad_list_size > kMaxQuadListSize ||
shared_quad_state_list_size > kMaxSharedQuadStateListSize)
return false;
scoped_ptr<cc::RenderPass> render_pass =
- cc::RenderPass::Create(shared_quad_state_list_size, quad_list_size);
+ cc::RenderPass::Create(
+ static_cast<size_t>(shared_quad_state_list_size),
+ static_cast<size_t>(quad_list_size));
if (!ReadParam(m, iter, render_pass.get()))
return false;
// Validate that each RenderPassDrawQuad points at a valid RenderPass
@@ -748,7 +708,7 @@ void ParamTraits<cc::DelegatedFrameData>::Log(const param_type& p,
l->append("])");
}
-void ParamTraits<cc::DrawQuad::Resources>::Write(Message* m,
+void ParamTraits<cc::DrawQuad::Resources>::Write(base::Pickle* m,
const param_type& p) {
DCHECK_LE(p.count, cc::DrawQuad::Resources::kMaxResourceIdCount);
WriteParam(m, p.count);
@@ -756,7 +716,7 @@ void ParamTraits<cc::DrawQuad::Resources>::Write(Message* m,
WriteParam(m, p.ids[i]);
}
-bool ParamTraits<cc::DrawQuad::Resources>::Read(const Message* m,
+bool ParamTraits<cc::DrawQuad::Resources>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* p) {
if (!ReadParam(m, iter, &p->count))
@@ -789,7 +749,7 @@ void ParamTraits<cc::DrawQuad::Resources>::Log(const param_type& p,
}
void ParamTraits<cc::StreamVideoDrawQuad::OverlayResources>::Write(
- Message* m,
+ base::Pickle* m,
const param_type& p) {
for (size_t i = 0; i < cc::DrawQuad::Resources::kMaxResourceIdCount; ++i) {
WriteParam(m, p.size_in_pixels[i]);
@@ -797,7 +757,7 @@ void ParamTraits<cc::StreamVideoDrawQuad::OverlayResources>::Write(
}
bool ParamTraits<cc::StreamVideoDrawQuad::OverlayResources>::Read(
- const Message* m,
+ const base::Pickle* m,
base::PickleIterator* iter,
param_type* p) {
for (size_t i = 0; i < cc::DrawQuad::Resources::kMaxResourceIdCount; ++i) {
@@ -820,7 +780,7 @@ void ParamTraits<cc::StreamVideoDrawQuad::OverlayResources>::Log(
}
void ParamTraits<cc::TextureDrawQuad::OverlayResources>::Write(
- Message* m,
+ base::Pickle* m,
const param_type& p) {
for (size_t i = 0; i < cc::DrawQuad::Resources::kMaxResourceIdCount; ++i) {
WriteParam(m, p.size_in_pixels[i]);
@@ -828,7 +788,7 @@ void ParamTraits<cc::TextureDrawQuad::OverlayResources>::Write(
}
bool ParamTraits<cc::TextureDrawQuad::OverlayResources>::Read(
- const Message* m,
+ const base::Pickle* m,
base::PickleIterator* iter,
param_type* p) {
for (size_t i = 0; i < cc::DrawQuad::Resources::kMaxResourceIdCount; ++i) {
diff --git a/chromium/content/common/cc_messages.h b/chromium/content/common/cc_messages.h
index 9f2e84ece39..0a6c213ae98 100644
--- a/chromium/content/common/cc_messages.h
+++ b/chromium/content/common/cc_messages.h
@@ -28,9 +28,10 @@
#include "cc/surfaces/surface_id.h"
#include "cc/surfaces/surface_sequence.h"
#include "content/common/content_export.h"
-#include "gpu/ipc/gpu_command_buffer_traits.h"
+#include "gpu/ipc/common/gpu_command_buffer_traits.h"
#include "ipc/ipc_message_macros.h"
#include "ui/gfx/ipc/gfx_param_traits.h"
+#include "ui/gfx/ipc/skia/gfx_skia_param_traits.h"
#ifndef CONTENT_COMMON_CC_MESSAGES_H_
#define CONTENT_COMMON_CC_MESSAGES_H_
@@ -48,88 +49,100 @@ namespace IPC {
template <>
struct ParamTraits<cc::FilterOperation> {
typedef cc::FilterOperation param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct ParamTraits<cc::FilterOperations> {
typedef cc::FilterOperations param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct ParamTraits<skia::RefPtr<SkImageFilter> > {
typedef skia::RefPtr<SkImageFilter> param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
- static void Log(const param_type& p, std::string* l);
-};
-
-template <>
-struct ParamTraits<gfx::Transform> {
- typedef gfx::Transform param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct CONTENT_EXPORT ParamTraits<cc::RenderPass> {
typedef cc::RenderPass param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template<>
struct CONTENT_EXPORT ParamTraits<cc::CompositorFrame> {
typedef cc::CompositorFrame param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* p);
static void Log(const param_type& p, std::string* l);
};
template<>
struct CONTENT_EXPORT ParamTraits<cc::CompositorFrameAck> {
typedef cc::CompositorFrameAck param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* p);
static void Log(const param_type& p, std::string* l);
};
template<>
struct CONTENT_EXPORT ParamTraits<cc::DelegatedFrameData> {
typedef cc::DelegatedFrameData param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* p);
static void Log(const param_type& p, std::string* l);
};
template <>
struct CONTENT_EXPORT ParamTraits<cc::DrawQuad::Resources> {
typedef cc::DrawQuad::Resources param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* p);
static void Log(const param_type& p, std::string* l);
};
template <>
struct CONTENT_EXPORT ParamTraits<cc::StreamVideoDrawQuad::OverlayResources> {
typedef cc::StreamVideoDrawQuad::OverlayResources param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* p);
static void Log(const param_type& p, std::string* l);
};
template <>
struct CONTENT_EXPORT ParamTraits<cc::TextureDrawQuad::OverlayResources> {
typedef cc::TextureDrawQuad::OverlayResources param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* p);
static void Log(const param_type& p, std::string* l);
};
@@ -246,6 +259,8 @@ IPC_STRUCT_TRAITS_BEGIN(cc::YUVVideoDrawQuad)
IPC_STRUCT_TRAITS_MEMBER(ya_tex_size)
IPC_STRUCT_TRAITS_MEMBER(uv_tex_size)
IPC_STRUCT_TRAITS_MEMBER(color_space)
+ IPC_STRUCT_TRAITS_MEMBER(resource_offset)
+ IPC_STRUCT_TRAITS_MEMBER(resource_multiplier)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(cc::SharedQuadState)
diff --git a/chromium/content/common/cc_messages_unittest.cc b/chromium/content/common/cc_messages_unittest.cc
index 799c39ff450..423bfffaa6b 100644
--- a/chromium/content/common/cc_messages_unittest.cc
+++ b/chromium/content/common/cc_messages_unittest.cc
@@ -433,7 +433,7 @@ TEST_F(CCMessagesTest, AllQuads) {
arbitrary_rect1_inside_rect1, arbitrary_bool1, arbitrary_rectf1,
arbitrary_rectf2, arbitrary_size1, arbitrary_size2, arbitrary_resourceid1,
arbitrary_resourceid2, arbitrary_resourceid3, arbitrary_resourceid4,
- arbitrary_color_space);
+ arbitrary_color_space, arbitrary_float1, arbitrary_float2);
pass_cmp->CopyFromAndAppendDrawQuad(yuvvideo_in,
yuvvideo_in->shared_quad_state);
@@ -617,8 +617,14 @@ TEST_F(CCMessagesTest, UnusedSharedQuadStates) {
TEST_F(CCMessagesTest, Resources) {
IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
gfx::Size arbitrary_size(757, 1281);
- gpu::SyncToken arbitrary_token1(71234838);
- gpu::SyncToken arbitrary_token2(53589793);
+ gpu::SyncToken arbitrary_token1(gpu::CommandBufferNamespace::GPU_IO, 0,
+ gpu::CommandBufferId::FromUnsafeValue(0x123),
+ 71234838);
+ arbitrary_token1.SetVerifyFlush();
+ gpu::SyncToken arbitrary_token2(gpu::CommandBufferNamespace::GPU_IO, 0,
+ gpu::CommandBufferId::FromUnsafeValue(0x123),
+ 53589793);
+ arbitrary_token2.SetVerifyFlush();
GLbyte arbitrary_mailbox1[GL_MAILBOX_SIZE_CHROMIUM] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2,
diff --git a/chromium/content/common/child_process_host_impl.cc b/chromium/content/common/child_process_host_impl.cc
index d69d5352a28..1aa93b52987 100644
--- a/chromium/content/common/child_process_host_impl.cc
+++ b/chromium/content/common/child_process_host_impl.cc
@@ -11,6 +11,7 @@
#include "base/files/file_path.h"
#include "base/hash.h"
#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
#include "base/numerics/safe_math.h"
#include "base/path_service.h"
@@ -21,10 +22,10 @@
#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
#include "build/build_config.h"
#include "content/common/child_process_messages.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h"
#include "content/public/common/child_process_host_delegate.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
+#include "gpu/ipc/client/gpu_memory_buffer_impl_shared_memory.h"
#include "ipc/attachment_broker.h"
#include "ipc/attachment_broker_privileged.h"
#include "ipc/ipc_channel.h"
@@ -88,7 +89,7 @@ ChildProcessHostImpl::ChildProcessHostImpl(ChildProcessHostDelegate* delegate)
#endif
#if USE_ATTACHMENT_BROKER
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MACOSX)
// On Mac, the privileged AttachmentBroker needs a reference to the Mach port
// Provider, which is only available in the chrome/ module. The attachment
// broker must already be created.
@@ -97,7 +98,7 @@ ChildProcessHostImpl::ChildProcessHostImpl(ChildProcessHostDelegate* delegate)
// Construct the privileged attachment broker early in the life cycle of a
// child process.
IPC::AttachmentBrokerPrivileged::CreateBrokerIfNeeded();
-#endif // defined(OS_MACOSX) && !defined(OS_IOS)
+#endif // defined(OS_MACOSX)
#endif // USE_ATTACHMENT_BROKER
}
@@ -132,12 +133,17 @@ void ChildProcessHostImpl::ForceShutdown() {
std::string ChildProcessHostImpl::CreateChannel() {
channel_id_ = IPC::Channel::GenerateVerifiedChannelID(std::string());
channel_ = IPC::Channel::CreateServer(channel_id_, this);
- if (!channel_->Connect())
- return std::string();
#if USE_ATTACHMENT_BROKER
IPC::AttachmentBroker::GetGlobal()->RegisterCommunicationChannel(
- channel_.get());
+ channel_.get(), base::MessageLoopForIO::current()->task_runner());
+#endif
+ if (!channel_->Connect()) {
+#if USE_ATTACHMENT_BROKER
+ IPC::AttachmentBroker::GetGlobal()->DeregisterCommunicationChannel(
+ channel_.get());
#endif
+ return std::string();
+ }
for (size_t i = 0; i < filters_.size(); ++i)
filters_[i]->OnFilterAdded(channel_.get());
@@ -316,8 +322,8 @@ void ChildProcessHostImpl::OnAllocateGpuMemoryBuffer(
// AllocateForChildProcess() will check if |width| and |height| are valid
// and handle failure in a controlled way when not. We just need to make
// sure |usage| is supported here.
- if (GpuMemoryBufferImplSharedMemory::IsUsageSupported(usage)) {
- *handle = GpuMemoryBufferImplSharedMemory::AllocateForChildProcess(
+ if (gpu::GpuMemoryBufferImplSharedMemory::IsUsageSupported(usage)) {
+ *handle = gpu::GpuMemoryBufferImplSharedMemory::AllocateForChildProcess(
id, gfx::Size(width, height), format, peer_process_.Handle());
}
}
diff --git a/chromium/content/common/child_process_messages.h b/chromium/content/common/child_process_messages.h
index b4ee49f122d..fd5fac49351 100644
--- a/chromium/content/common/child_process_messages.h
+++ b/chromium/content/common/child_process_messages.h
@@ -16,12 +16,20 @@
#include "build/build_config.h"
#include "cc/resources/shared_bitmap_manager.h"
#include "content/common/content_export.h"
+#include "content/common/content_param_traits_macros.h"
+#include "content/common/gpu_process_launch_causes.h"
#include "content/common/host_discardable_shared_memory_manager.h"
#include "gpu/command_buffer/common/sync_token.h"
+#include "gpu/ipc/common/gpu_param_traits_macros.h"
+#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_platform_file.h"
#include "ui/gfx/gpu_memory_buffer.h"
#include "ui/gfx/ipc/gfx_param_traits.h"
+#include "ui/gfx/ipc/skia/gfx_skia_param_traits.h"
+
+IPC_ENUM_TRAITS_MAX_VALUE(content::CauseForGpuLaunch,
+ content::CAUSE_FOR_GPU_LAUNCH_MAX_ENUM - 1)
IPC_ENUM_TRAITS_MAX_VALUE(tracked_objects::ThreadData::Status,
tracked_objects::ThreadData::STATUS_LAST)
@@ -62,26 +70,6 @@ IPC_STRUCT_TRAITS_BEGIN(tracked_objects::ProcessDataSnapshot)
IPC_STRUCT_TRAITS_MEMBER(process_id)
IPC_STRUCT_TRAITS_END()
-IPC_ENUM_TRAITS_MAX_VALUE(gfx::GpuMemoryBufferType,
- gfx::GPU_MEMORY_BUFFER_TYPE_LAST)
-
-IPC_STRUCT_TRAITS_BEGIN(gfx::GpuMemoryBufferHandle)
- IPC_STRUCT_TRAITS_MEMBER(id)
- IPC_STRUCT_TRAITS_MEMBER(type)
- IPC_STRUCT_TRAITS_MEMBER(handle)
- IPC_STRUCT_TRAITS_MEMBER(offset)
- IPC_STRUCT_TRAITS_MEMBER(stride)
-#if defined(USE_OZONE)
- IPC_STRUCT_TRAITS_MEMBER(native_pixmap_handle)
-#elif defined(OS_MACOSX)
- IPC_STRUCT_TRAITS_MEMBER(mach_port)
-#endif
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(gfx::GpuMemoryBufferId)
- IPC_STRUCT_TRAITS_MEMBER(id)
-IPC_STRUCT_TRAITS_END()
-
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
@@ -114,8 +102,16 @@ IPC_MESSAGE_CONTROL2(ChildProcessMsg_GetChildProfilerData,
IPC_MESSAGE_CONTROL1(ChildProcessMsg_ProfilingPhaseCompleted,
int /* profiling_phase */)
+// Sent to set the shared memory buffer to be used for storing histograms that
+// are to be reported by the browser process to UMA. The following message
+// (GetChildNonPersistentHistogramData) will return any histograms created
+// before this message is received but not any histograms created afterward.
+IPC_MESSAGE_CONTROL2(ChildProcessMsg_SetHistogramMemory,
+ base::SharedMemoryHandle /* shm_handle */,
+ int /* shm_size */)
+
// Send to all the child processes to send back histogram data.
-IPC_MESSAGE_CONTROL1(ChildProcessMsg_GetChildHistogramData,
+IPC_MESSAGE_CONTROL1(ChildProcessMsg_GetChildNonPersistentHistogramData,
int /* sequence_number */)
// Sent to child processes to tell them to enter or leave background mode.
@@ -126,15 +122,22 @@ IPC_MESSAGE_CONTROL1(ChildProcessMsg_SetProcessBackgrounded,
IPC_MESSAGE_CONTROL1(ChildProcessMsg_SetMojoParentPipeHandle,
IPC::PlatformFileForTransit /* handle */)
-#if defined(USE_OZONE)
-// Sent to child processes to initialize ClientNativePixmapFactory using
-// a device file descriptor.
-IPC_MESSAGE_CONTROL1(ChildProcessMsg_InitializeClientNativePixmapFactory,
- base::FileDescriptor /* device_fd */)
-#endif
////////////////////////////////////////////////////////////////////////////////
// Messages sent from the child process to the browser.
+// A renderer sends this when it wants to create a connection to the GPU
+// process. The browser will create the GPU process if necessary, and will
+// return a handle to the channel via a GpuChannelEstablished message.
+IPC_SYNC_MESSAGE_CONTROL1_3(ChildProcessHostMsg_EstablishGpuChannel,
+ content::CauseForGpuLaunch,
+ int /* client id */,
+ IPC::ChannelHandle /* handle to channel */,
+ gpu::GPUInfo /* stats about GPU process*/)
+
+// A renderer sends this when it wants to know whether a gpu process exists.
+IPC_SYNC_MESSAGE_CONTROL0_1(ChildProcessHostMsg_HasGpuProcess,
+ bool /* result */)
+
IPC_MESSAGE_CONTROL0(ChildProcessHostMsg_ShutdownRequest)
// Send back profiler data (ThreadData in tracked_objects).
diff --git a/chromium/content/common/child_process_sandbox_support_impl_linux.h b/chromium/content/common/child_process_sandbox_support_impl_linux.h
index 97221f6e838..e2e973d9771 100644
--- a/chromium/content/common/child_process_sandbox_support_impl_linux.h
+++ b/chromium/content/common/child_process_sandbox_support_impl_linux.h
@@ -30,8 +30,9 @@ void GetFallbackFontForCharacter(const int32_t character,
// |size_and_style| stores the bold setting in its least-significant bit, the
// italic setting in its second-least-significant bit, and holds the requested
// size in pixels into its remaining bits.
-// TODO(derat): Update WebSandboxSupport's getRenderStyleForStrike() method to
-// pass the style and size separately instead of packing them into an int.
+// TODO(derat): Update WebSandboxSupport's getWebFontRenderStyleForStrike()
+// method to pass the style and size separately instead of packing them into an
+// int.
void GetRenderStyleForStrike(const char* family,
int size_and_style,
blink::WebFontRenderStyle* out);
diff --git a/chromium/content/common/clipboard_messages.h b/chromium/content/common/clipboard_messages.h
index 00a198c1f6a..36877f0a241 100644
--- a/chromium/content/common/clipboard_messages.h
+++ b/chromium/content/common/clipboard_messages.h
@@ -10,13 +10,16 @@
#include <string>
#include <vector>
+#include "build/build_config.h"
#include "base/memory/shared_memory.h"
#include "base/strings/string16.h"
#include "build/build_config.h"
#include "content/common/clipboard_format.h"
-#include "content/public/common/common_param_traits.h"
+#include "content/common/content_export.h"
#include "ipc/ipc_message_macros.h"
+#include "ipc/param_traits_macros.h"
#include "ui/base/clipboard/clipboard.h"
+#include "url/ipc/url_param_traits.h"
// Singly-included section for types and/or struct declarations.
#ifndef CONTENT_COMMON_CLIPBOARD_MESSAGES_H_
diff --git a/chromium/content/common/common.sb b/chromium/content/common/common.sb
index 1d9a8ac1c89..49c654c35fd 100644
--- a/chromium/content/common/common.sb
+++ b/chromium/content/common/common.sb
@@ -16,7 +16,6 @@
; Define constants for all of the parameter strings passed in.
(define disable-sandbox-denial-logging "DISABLE_SANDBOX_DENIAL_LOGGING")
(define enable-logging "ENABLE_LOGGING")
-(define component-build-workaround "COMPONENT_BUILD_WORKAROUND")
(define permitted-dir "PERMITTED_DIR")
(define homedir-as-literal "USER_HOMEDIR_AS_LITERAL")
(define lion-or-later "LION_OR_LATER")
@@ -50,9 +49,3 @@
; Allow direct access to /dev/urandom, similar to Linux/POSIX, to allow
; third party code (eg: bits of Adobe Flash and NSS) to function properly.
(allow file-read-data file-read-metadata (literal "/dev/urandom"))
-
-; Enables reading file metadata for the Chrome bundle and its parent paths.
-; https://crbug.com/127465
-(if (and (param-defined? component-build-workaround)
- (param-true? component-build-workaround))
- (allow file-read-metadata ))
diff --git a/chromium/content/common/common_param_traits_unittest.cc b/chromium/content/common/common_param_traits_unittest.cc
index 03c19a08731..546834bd9fb 100644
--- a/chromium/content/common/common_param_traits_unittest.cc
+++ b/chromium/content/common/common_param_traits_unittest.cc
@@ -20,68 +20,7 @@
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/ipc/gfx_param_traits.h"
-#include "url/gurl.h"
-
-// Tests that serialize/deserialize correctly understand each other
-TEST(IPCMessageTest, Serialize) {
- const char* serialize_cases[] = {
- "http://www.google.com/",
- "http://user:pass@host.com:888/foo;bar?baz#nop",
- };
-
- for (size_t i = 0; i < arraysize(serialize_cases); i++) {
- GURL input(serialize_cases[i]);
- IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
- IPC::ParamTraits<GURL>::Write(&msg, input);
-
- GURL output;
- base::PickleIterator iter(msg);
- EXPECT_TRUE(IPC::ParamTraits<GURL>::Read(&msg, &iter, &output));
-
- // We want to test each component individually to make sure its range was
- // correctly serialized and deserialized, not just the spec.
- EXPECT_EQ(input.possibly_invalid_spec(), output.possibly_invalid_spec());
- EXPECT_EQ(input.is_valid(), output.is_valid());
- EXPECT_EQ(input.scheme(), output.scheme());
- EXPECT_EQ(input.username(), output.username());
- EXPECT_EQ(input.password(), output.password());
- EXPECT_EQ(input.host(), output.host());
- EXPECT_EQ(input.port(), output.port());
- EXPECT_EQ(input.path(), output.path());
- EXPECT_EQ(input.query(), output.query());
- EXPECT_EQ(input.ref(), output.ref());
- }
-
- // Test an excessively long GURL.
- {
- const std::string url = std::string("http://example.org/").append(
- content::kMaxURLChars + 1, 'a');
- GURL input(url.c_str());
- IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
- IPC::ParamTraits<GURL>::Write(&msg, input);
-
- GURL output;
- base::PickleIterator iter(msg);
- EXPECT_TRUE(IPC::ParamTraits<GURL>::Read(&msg, &iter, &output));
- EXPECT_TRUE(output.is_empty());
- }
-
- // Test an invalid GURL.
- {
- IPC::Message msg;
- msg.WriteString("#inva://idurl/");
- GURL output;
- base::PickleIterator iter(msg);
- EXPECT_FALSE(IPC::ParamTraits<GURL>::Read(&msg, &iter, &output));
- }
-
- // Also test the corrupt case.
- IPC::Message msg(1, 2, IPC::Message::PRIORITY_NORMAL);
- msg.WriteInt(99);
- GURL output;
- base::PickleIterator iter(msg);
- EXPECT_FALSE(IPC::ParamTraits<GURL>::Read(&msg, &iter, &output));
-}
+#include "ui/gfx/ipc/skia/gfx_skia_param_traits.h"
// Tests std::pair serialization
TEST(IPCMessageTest, Pair) {
diff --git a/chromium/content/common/content_constants_internal.cc b/chromium/content/common/content_constants_internal.cc
index 7b8b68ae3f7..ec623ac2c4b 100644
--- a/chromium/content/common/content_constants_internal.cc
+++ b/chromium/content/common/content_constants_internal.cc
@@ -18,16 +18,11 @@ const int64_t kHungRendererDelayMs = 30000;
const int64_t kNewContentRenderingDelayMs = 4000;
-const uint16_t kMaxPluginSideLength = 1 << 15;
-// 8m pixels.
-const uint32_t kMaxPluginSize = 8 << 20;
-
// 20MiB
const size_t kMaxLengthOfDataURLString = 1024 * 1024 * 20;
const int kTraceEventBrowserProcessSortIndex = -6;
const int kTraceEventRendererProcessSortIndex = -5;
-const int kTraceEventPluginProcessSortIndex = -4;
const int kTraceEventPpapiProcessSortIndex = -3;
const int kTraceEventPpapiBrokerProcessSortIndex = -2;
const int kTraceEventGpuProcessSortIndex = -1;
diff --git a/chromium/content/common/content_constants_internal.h b/chromium/content/common/content_constants_internal.h
index 46f351b401c..a3584b0d8b4 100644
--- a/chromium/content/common/content_constants_internal.h
+++ b/chromium/content/common/content_constants_internal.h
@@ -19,19 +19,12 @@ CONTENT_EXPORT extern const int64_t kHungRendererDelayMs;
// before clearing previously displayed graphics.
extern const int64_t kNewContentRenderingDelayMs;
-// The maximum plugin width and height.
-extern const uint16_t kMaxPluginSideLength;
-// The maximum plugin size, defined as the number of pixels occupied by the
-// plugin.
-extern const uint32_t kMaxPluginSize;
-
// The maximum length of string as data url.
extern const size_t kMaxLengthOfDataURLString;
// Constants used to organize content processes in about:tracing.
CONTENT_EXPORT extern const int kTraceEventBrowserProcessSortIndex;
CONTENT_EXPORT extern const int kTraceEventRendererProcessSortIndex;
-CONTENT_EXPORT extern const int kTraceEventPluginProcessSortIndex;
CONTENT_EXPORT extern const int kTraceEventPpapiProcessSortIndex;
CONTENT_EXPORT extern const int kTraceEventPpapiBrokerProcessSortIndex;
CONTENT_EXPORT extern const int kTraceEventGpuProcessSortIndex;
diff --git a/chromium/content/common/content_message_generator.h b/chromium/content/common/content_message_generator.h
index 3d49ab228a3..c26352d010c 100644
--- a/chromium/content/common/content_message_generator.h
+++ b/chromium/content/common/content_message_generator.h
@@ -28,7 +28,7 @@
#include "content/common/frame_messages.h"
#include "content/common/gamepad_messages.h"
#include "content/common/geofencing_messages.h"
-#include "content/common/gpu/gpu_messages.h"
+#include "content/common/gpu_host_messages.h"
#include "content/common/indexed_db/indexed_db_messages.h"
#include "content/common/input_messages.h"
#include "content/common/manifest_manager_messages.h"
@@ -36,20 +36,20 @@
#include "content/common/media/audio_messages.h"
// TODO(xhwang): Move this to a new ifdef block.
#include "content/common/media/cdm_messages.h"
+#include "content/common/media/media_player_delegate_messages.h"
#include "content/common/media/media_stream_messages.h"
#include "content/common/media/media_stream_track_metrics_host_messages.h"
#include "content/common/media/midi_messages.h"
#include "content/common/media/peer_connection_tracker_messages.h"
#include "content/common/media/video_capture_messages.h"
#include "content/common/media/webrtc_identity_messages.h"
-#include "content/common/memory_benchmark_messages.h"
#include "content/common/memory_messages.h"
#include "content/common/message_port_messages.h"
#include "content/common/mime_registry_messages.h"
#include "content/common/mojo/mojo_messages.h"
+#include "content/common/page_messages.h"
#include "content/common/pepper_messages.h"
#include "content/common/platform_notification_messages.h"
-#include "content/common/plugin_process_messages.h"
#include "content/common/power_monitor_messages.h"
#include "content/common/push_messaging_messages.h"
#include "content/common/quota_messages.h"
@@ -74,6 +74,7 @@
#include "content/common/gin_java_bridge_messages.h"
#include "content/common/media/media_player_messages_android.h"
#include "content/common/media/media_session_messages_android.h"
+#include "content/common/media/surface_view_manager_messages_android.h"
#endif // defined(OS_ANDROID)
#if defined(OS_WIN)
diff --git a/chromium/content/common/content_param_traits.cc b/chromium/content/common/content_param_traits.cc
index 0c60380e281..07e1a239bfd 100644
--- a/chromium/content/common/content_param_traits.cc
+++ b/chromium/content/common/content_param_traits.cc
@@ -12,11 +12,12 @@
namespace IPC {
-void ParamTraits<WebInputEventPointer>::Write(Message* m, const param_type& p) {
+void ParamTraits<WebInputEventPointer>::Write(base::Pickle* m,
+ const param_type& p) {
m->WriteData(reinterpret_cast<const char*>(p), p->size);
}
-bool ParamTraits<WebInputEventPointer>::Read(const Message* m,
+bool ParamTraits<WebInputEventPointer>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
const char* data;
diff --git a/chromium/content/common/content_param_traits.h b/chromium/content/common/content_param_traits.h
index e90a14bd05c..61107aa06e1 100644
--- a/chromium/content/common/content_param_traits.h
+++ b/chromium/content/common/content_param_traits.h
@@ -27,12 +27,10 @@ namespace IPC {
template <>
struct ParamTraits<content::WebCursor> {
typedef content::WebCursor param_type;
- static void Write(Message* m, const param_type& p) {
- p.Serialize(m);
- }
- static bool Read(const Message* m,
+ static void Write(base::Pickle* m, const param_type& p) { p.Serialize(m); }
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
- param_type* r) {
+ param_type* r) {
return r->Deserialize(iter);
}
static void Log(const param_type& p, std::string* l) {
@@ -44,9 +42,11 @@ typedef const blink::WebInputEvent* WebInputEventPointer;
template <>
struct ParamTraits<WebInputEventPointer> {
typedef WebInputEventPointer param_type;
- static void Write(Message* m, const param_type& p);
+ static void Write(base::Pickle* m, const param_type& p);
// Note: upon read, the event has the lifetime of the message.
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
diff --git a/chromium/content/common/content_param_traits_macros.h b/chromium/content/common/content_param_traits_macros.h
index 762436de718..753947bf530 100644
--- a/chromium/content/common/content_param_traits_macros.h
+++ b/chromium/content/common/content_param_traits_macros.h
@@ -14,11 +14,13 @@
#include "content/public/common/request_context_type.h"
#include "content/public/common/resource_type.h"
#include "ipc/ipc_message_macros.h"
+#include "third_party/WebKit/public/platform/WebAddressSpace.h"
#include "third_party/WebKit/public/platform/WebPageVisibilityState.h"
#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
#include "third_party/WebKit/public/web/WebContentSecurityPolicy.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "third_party/WebKit/public/web/WebSharedWorkerCreationContextType.h"
+#include "ui/gfx/gpu_memory_buffer.h"
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
@@ -33,6 +35,7 @@ IPC_ENUM_TRAITS_MAX_VALUE(content::RequestContextFrameType,
content::REQUEST_CONTEXT_FRAME_TYPE_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(blink::WebContentSecurityPolicyType,
blink::WebContentSecurityPolicyTypeLast)
+IPC_ENUM_TRAITS_MAX_VALUE(blink::WebAddressSpace, blink::WebAddressSpaceLast)
IPC_ENUM_TRAITS_MAX_VALUE(blink::WebSharedWorkerCreationContextType,
blink::WebSharedWorkerCreationContextTypeLast)
IPC_ENUM_TRAITS_MIN_MAX_VALUE(blink::WebInputEvent::Type,
diff --git a/chromium/content/common/content_switches_internal.cc b/chromium/content/common/content_switches_internal.cc
index f496c504f59..d0d5ec7e933 100644
--- a/chromium/content/common/content_switches_internal.cc
+++ b/chromium/content/common/content_switches_internal.cc
@@ -20,9 +20,9 @@ namespace content {
namespace {
-#if defined(OS_WIN)
-static bool g_win32k_renderer_lockdown_disabled = false;
-#endif
+bool IsUseZoomForDSFEnabledByDefault() {
+ return false;
+}
} // namespace
@@ -30,29 +30,13 @@ bool IsPinchToZoomEnabled() {
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
- // --disable-pinch should always disable pinch
- if (command_line.HasSwitch(switches::kDisablePinch))
- return false;
-
-#if defined(OS_WIN)
- return base::win::GetVersion() >= base::win::VERSION_WIN8;
-#elif defined(OS_CHROMEOS)
- return true;
-#else
- return command_line.HasSwitch(switches::kEnableViewport) ||
- command_line.HasSwitch(switches::kEnablePinch);
-#endif
+ // Enable pinch everywhere unless it's been explicitly disabled.
+ return !command_line.HasSwitch(switches::kDisablePinch);
}
#if defined(OS_WIN)
-void DisableWin32kRendererLockdown() {
- g_win32k_renderer_lockdown_disabled = true;
-}
-
bool IsWin32kRendererLockdownEnabled() {
- if (g_win32k_renderer_lockdown_disabled)
- return false;
if (base::win::GetVersion() < base::win::VERSION_WIN8)
return false;
if (!gfx::win::ShouldUseDirectWrite())
@@ -84,8 +68,15 @@ V8CacheOptions GetV8CacheOptions() {
}
bool IsUseZoomForDSFEnabled() {
- static bool enabled = base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableUseZoomForDSF);
+ static bool use_zoom_for_dsf_enabled_by_default =
+ IsUseZoomForDSFEnabledByDefault();
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ bool enabled =
+ (command_line->HasSwitch(switches::kEnableUseZoomForDSF) ||
+ use_zoom_for_dsf_enabled_by_default) &&
+ command_line->GetSwitchValueASCII(
+ switches::kEnableUseZoomForDSF) != "false";
+
return enabled;
}
diff --git a/chromium/content/common/content_switches_internal.h b/chromium/content/common/content_switches_internal.h
index 990070c4ccd..aacd9426e58 100644
--- a/chromium/content/common/content_switches_internal.h
+++ b/chromium/content/common/content_switches_internal.h
@@ -6,21 +6,19 @@
#define CONTENT_COMMON_CONTENT_SWITCHES_INTERNAL_H_
#include "build/build_config.h"
+#include "content/common/content_export.h"
#include "content/public/common/web_preferences.h"
namespace content {
bool IsPinchToZoomEnabled();
#if defined(OS_WIN)
-// Disables Win32k Renderer lockdown for any future renderer child processes.
-void DisableWin32kRendererLockdown();
-
// Returns whether Win32k Renderer lockdown is enabled or not.
bool IsWin32kRendererLockdownEnabled();
#endif
V8CacheOptions GetV8CacheOptions();
-bool IsUseZoomForDSFEnabled();
+CONTENT_EXPORT bool IsUseZoomForDSFEnabled();
} // namespace content
diff --git a/chromium/content/common/database_identifier_unittest.cc b/chromium/content/common/database_identifier_unittest.cc
index f866b7639ef..dac125a9bba 100644
--- a/chromium/content/common/database_identifier_unittest.cc
+++ b/chromium/content/common/database_identifier_unittest.cc
@@ -35,6 +35,9 @@ TEST(DatabaseIdentifierTest, CreateIdentifierFromOrigin) {
{"data:", "__0"},
{"about:blank", "__0"},
{"non-standard://foobar.com", "__0"},
+ {"http://[::1]:8080", "http_[__1]_8080"},
+ {"http://[3ffe:2a00:100:7031::1]", "http_[3ffe_2a00_100_7031__1]_0"},
+ {"http://[::ffff:8190:3426]", "http_[__ffff_8190_3426]_0"},
};
for (size_t i = 0; i < arraysize(cases); ++i) {
@@ -203,6 +206,13 @@ TEST(DatabaseIdentifierTest, ExtractOriginDataFromIdentifier) {
{"http_dot.com_0", "http", "dot.com", 0, GURL("http://dot.com"), false},
{"http_escaped%3Dfun.com_0", "http", "escaped%3dfun.com", 0,
GURL("http://escaped%3dfun.com"), false},
+ {"http_[__1]_8080",
+ "http", "[::1]", 8080, GURL("http://[::1]:8080"), false},
+ {"http_[3ffe_2a00_100_7031__1]_0",
+ "http", "[3ffe:2a00:100:7031::1]", 0,
+ GURL("http://[3ffe:2a00:100:7031::1]"), false},
+ {"http_[__ffff_8190_3426]_0",
+ "http", "[::ffff:8190:3426]", 0, GURL("http://[::ffff:8190:3426]"), false},
};
for (size_t i = 0; i < arraysize(valid_cases); ++i) {
@@ -245,5 +255,33 @@ TEST(DatabaseIdentifierTest, ExtractOriginDataFromIdentifier) {
}
}
+static GURL ToAndFromOriginIdentifier(const GURL origin_url) {
+ std::string id = storage::GetIdentifierFromOrigin(origin_url);
+ return storage::GetOriginFromIdentifier(id);
+}
+
+static void TestValidOriginIdentifier(bool expected_result,
+ const std::string& id) {
+ EXPECT_EQ(expected_result,
+ storage::IsValidOriginIdentifier(id));
+}
+
+TEST(DatabaseIdentifierTest, OriginIdentifiers) {
+ const GURL kFileOrigin(GURL("file:///").GetOrigin());
+ const GURL kHttpOrigin(GURL("http://bar/").GetOrigin());
+ EXPECT_EQ(kFileOrigin, ToAndFromOriginIdentifier(kFileOrigin));
+ EXPECT_EQ(kHttpOrigin, ToAndFromOriginIdentifier(kHttpOrigin));
+}
+
+TEST(DatabaseIdentifierTest, IsValidOriginIdentifier) {
+ TestValidOriginIdentifier(true, "http_bar_0");
+ TestValidOriginIdentifier(false, "");
+ TestValidOriginIdentifier(false, "bad..id");
+ TestValidOriginIdentifier(false, "bad/id");
+ TestValidOriginIdentifier(false, "bad\\id");
+ TestValidOriginIdentifier(false, "http_bad:0_2");
+ TestValidOriginIdentifier(false, std::string("bad\0id", 6));
+}
+
} // namespace
} // namespace content
diff --git a/chromium/content/common/devtools_messages.h b/chromium/content/common/devtools_messages.h
index 7edc617df96..4c7c24a089d 100644
--- a/chromium/content/common/devtools_messages.h
+++ b/chromium/content/common/devtools_messages.h
@@ -43,7 +43,6 @@
#include <string>
#include "content/common/content_export.h"
-#include "content/public/common/common_param_traits.h"
#include "content/public/common/console_message_level.h"
#include "ipc/ipc_message_macros.h"
@@ -103,6 +102,19 @@ IPC_MESSAGE_ROUTED2(DevToolsAgentMsg_InspectElement,
int /* x */,
int /* y */)
+// ACK for DevToolsAgentHostMsg_RequestNewWindow message.
+IPC_MESSAGE_ROUTED1(DevToolsAgentMsg_RequestNewWindow_ACK,
+ bool /* success */)
+
+//-----------------------------------------------------------------------------
+// These are messages sent from renderer's DevToolsAgent to browser.
+
+// Requests new DevTools window being opened for frame in the same process
+// with given routing id.
+IPC_MESSAGE_ROUTED1(DevToolsAgentHostMsg_RequestNewWindow,
+ int /* frame_route_id */)
+
+
//-----------------------------------------------------------------------------
// These are messages sent from the browser to the renderer.
diff --git a/chromium/content/common/discardable_shared_memory_heap.cc b/chromium/content/common/discardable_shared_memory_heap.cc
index 263f83b24ad..3e39216cbc1 100644
--- a/chromium/content/common/discardable_shared_memory_heap.cc
+++ b/chromium/content/common/discardable_shared_memory_heap.cc
@@ -418,12 +418,14 @@ void DiscardableSharedMemoryHeap::OnMemoryDump(
// to avoid double-counting segments when both browser and child process emit
// them. In the special case of single-process-mode, this will be the only
// dumper active and the single ownership edge will become a no-op in the UI.
+ // The global dump is created as a weak dump so that the segment is removed if
+ // the browser does not dump it (segment was purged).
const uint64_t tracing_process_id =
base::trace_event::MemoryDumpManager::GetInstance()
->GetTracingProcessId();
base::trace_event::MemoryAllocatorDumpGuid shared_segment_guid =
GetSegmentGUIDForTracing(tracing_process_id, segment_id);
- pmd->CreateSharedGlobalAllocatorDump(shared_segment_guid);
+ pmd->CreateWeakSharedGlobalAllocatorDump(shared_segment_guid);
// The size is added to the global dump so that it gets propagated to both the
// dumps associated.
diff --git a/chromium/content/common/dom_storage/dom_storage_messages.h b/chromium/content/common/dom_storage/dom_storage_messages.h
index 7fd4426a766..59d22c9641b 100644
--- a/chromium/content/common/dom_storage/dom_storage_messages.h
+++ b/chromium/content/common/dom_storage/dom_storage_messages.h
@@ -7,11 +7,11 @@
#include <stdint.h>
#include "content/common/dom_storage/dom_storage_types.h"
-#include "content/public/common/common_param_traits.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_param_traits.h"
#include "third_party/WebKit/public/platform/WebStorageArea.h"
#include "url/gurl.h"
+#include "url/ipc/url_param_traits.h"
#define IPC_MESSAGE_START DOMStorageMsgStart
diff --git a/chromium/content/common/drag_messages.h b/chromium/content/common/drag_messages.h
index 455bbffa067..8d2fd772370 100644
--- a/chromium/content/common/drag_messages.h
+++ b/chromium/content/common/drag_messages.h
@@ -6,7 +6,6 @@
// Multiply-included message file, hence no include guard.
#include "content/common/drag_event_source_info.h"
-#include "content/public/common/common_param_traits.h"
#include "content/public/common/drop_data.h"
#include "ipc/ipc_message_macros.h"
#include "third_party/WebKit/public/web/WebDragOperation.h"
diff --git a/chromium/content/common/dwrite_font_platform_win.cc b/chromium/content/common/dwrite_font_platform_win.cc
deleted file mode 100644
index 56140f421aa..00000000000
--- a/chromium/content/common/dwrite_font_platform_win.cc
+++ /dev/null
@@ -1,1282 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/public/common/dwrite_font_platform_win.h"
-
-#include <windows.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#include <dwrite.h>
-#include <wrl/implements.h>
-#include <wrl/wrappers/corewrappers.h>
-
-#include <limits>
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/command_line.h"
-#include "base/debug/alias.h"
-#include "base/debug/crash_logging.h"
-#include "base/files/file_enumerator.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/memory_mapped_file.h"
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/shared_memory.h"
-#include "base/metrics/field_trial.h"
-#include "base/metrics/histogram.h"
-#include "base/path_service.h"
-#include "base/process/process_handle.h"
-#include "base/stl_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/synchronization/lock.h"
-#include "base/time/time.h"
-#include "base/trace_event/trace_event.h"
-#include "base/win/registry.h"
-#include "base/win/scoped_comptr.h"
-#include "content/public/common/content_switches.h"
-
-namespace {
-
-// Font Cache implementation short story:
-// Due to our sandboxing restrictions, we cannot connect to Windows font cache
-// service from Renderer and need to use DirectWrite isolated font loading
-// mechanism.
-// DirectWrite needs to be initialized before any of the API could be used.
-// During initialization DirectWrite loads all font files and populates
-// internal cache, we refer this phase as enumeration and we are trying
-// to optimize this phase in our cache approach. Using cache during
-// initialization will help improve on startup latency in each renderer
-// instance.
-// During enumeration DirectWrite reads various fragments from .ttf/.ttc
-// font files. Our assumption is that these fragments are being read to
-// cache information such as font families, supported sizes etc.
-// For reading fragments DirectWrite calls ReadFragment of our FontFileStream
-// implementation with parameters start_offset and length. We cache these
-// parameters along with associated data chunk.
-// Here is small example of how segments are read
-// start_offset: 0, length: 16
-// start_offset: 0, length: 12
-// start_offset: 0, length: 117
-// For better cache management we collapse segments if they overlap or are
-// adjacent.
-
-namespace mswr = Microsoft::WRL;
-
-const char kFontKeyName[] = "font_key_name";
-
-// We use this value to determine whether to cache file fragments
-// or not. In our trials we observed that for some font files
-// direct write ends up reading almost entire file during enumeration
-// phase. If we don't use this percentile formula we will end up
-// increasing significant cache size by caching entire file contents
-// for some of the font files.
-const double kMaxPercentileOfFontFileSizeToCache = 0.6;
-
-// With current implementation we map entire shared section into memory during
-// renderer startup. This causes increase in working set of Chrome. As first
-// step we want to see if caching is really improving any performance for our
-// users, so we are putting arbitrary limit on cache file size. There are
-// multiple ways we can tune our working size, like mapping only required part
-// of section at any given time.
-const double kArbitraryCacheFileSizeLimit = (30 * 1024 * 1024);
-
-// We have chosen current font file length arbitrarily. In our logic
-// if we don't find file we are looking for in cache we end up loading
-// that file directly from system fonts folder.
-const unsigned int kMaxFontFileNameLength = 34;
-
-const DWORD kCacheFileVersion = 103;
-const DWORD kFileSignature = 0x4D4F5243; // CROM
-const DWORD kMagicCompletionSignature = 0x454E4F44; // DONE
-
-const DWORD kUndefinedDWORDS = 36;
-
-// Make sure that all structure sizes align with 8 byte boundary otherwise
-// dr. memory test may complain.
-#pragma pack(push, 8)
-// Cache file header, includes signature, completion bits and version.
-struct CacheFileHeader {
- CacheFileHeader() {
- file_signature = kFileSignature;
- magic_completion_signature = 0;
- version = kCacheFileVersion;
- ::ZeroMemory(undefined, sizeof(undefined));
- }
-
- DWORD file_signature;
- DWORD magic_completion_signature;
- DWORD version;
- BYTE undefined[kUndefinedDWORDS];
-};
-
-// Entry for a particular font file within this cache.
-struct CacheFileEntry {
- CacheFileEntry() {
- file_size = 0;
- entry_count = 0;
- ::ZeroMemory(file_name, sizeof(file_name));
- }
-
- UINT64 file_size;
- DWORD entry_count;
- wchar_t file_name[kMaxFontFileNameLength];
-};
-
-// Offsets or data chunks that are cached for particular font file.
-struct CacheFileOffsetEntry {
- CacheFileOffsetEntry() {
- start_offset = 0;
- length = 0;
- }
-
- UINT64 start_offset;
- UINT64 length;
- /* BYTE blob_[]; // Place holder for the blob that follows. */
-};
-#pragma pack(pop)
-
-bool ValidateFontCacheHeader(CacheFileHeader* header) {
- return (header->file_signature == kFileSignature &&
- header->magic_completion_signature == kMagicCompletionSignature &&
- header->version == kCacheFileVersion);
-}
-
-class FontCacheWriter;
-
-// This class implements main interface required for loading custom font
-// collection as specified by DirectWrite. We also use this class for storing
-// some state information as this is one of the centralized entity.
-class FontCollectionLoader
- : public mswr::RuntimeClass<mswr::RuntimeClassFlags<mswr::ClassicCom>,
- IDWriteFontCollectionLoader> {
- public:
- FontCollectionLoader()
- : in_collection_building_mode_(false),
- create_static_cache_(false) {}
-
- ~FontCollectionLoader() override;
-
- HRESULT RuntimeClassInitialize() {
- return S_OK;
- }
-
- // IDWriteFontCollectionLoader methods.
- HRESULT STDMETHODCALLTYPE
- CreateEnumeratorFromKey(IDWriteFactory* factory,
- void const* key,
- UINT32 key_size,
- IDWriteFontFileEnumerator** file_enumerator) override;
-
- // Does all the initialization for required loading fonts from registry.
- static HRESULT Initialize(IDWriteFactory* factory);
-
- // Returns font cache map size.
- UINT32 GetFontMapSize();
-
- // Returns font name string when given font index.
- base::string16 GetFontNameFromKey(UINT32 idx);
-
- // Loads internal structure with fonts from registry.
- bool LoadFontListFromRegistry();
-
- // Loads restricted web safe fonts as fallback method to registry fonts.
- bool LoadRestrictedFontList();
-
- // Puts class in collection building mode. In collection building mode
- // we use static cache if it is available as a look aside buffer.
- void EnableCollectionBuildingMode(bool enable);
-
- // Returns current state of collection building.
- bool InCollectionBuildingMode();
-
- // Loads static cache file.
- bool LoadCacheFile();
-
- // Unloads cache file and related data.
- void UnloadCacheFile();
-
- // Puts class in static cache creating mode. In this mode we record all
- // direct write requests and store chunks of font data.
- void EnterStaticCacheMode(const WCHAR* file_name);
-
- // Gets out of static cache building mode.
- void LeaveStaticCacheMode();
-
- // Returns if class is currently in static cache building mode.
- bool IsBuildStaticCacheMode();
-
- // Validates cache file for consistency.
- bool ValidateCacheFile(base::File* file);
-
- private:
- // Structure to represent each chunk within font file that we load in memory.
- struct CacheTableOffsetEntry {
- UINT64 start_offset;
- UINT64 length;
- BYTE* inside_file_ptr;
- };
-
- typedef std::vector<CacheTableOffsetEntry> OffsetVector;
-
- // Structure representing each font entry with cache.
- struct CacheTableEntry {
- UINT64 file_size;
- OffsetVector offset_entries;
- };
-
- public:
- // Returns whether file we have particular font entry within cache or not.
- bool IsFileCached(UINT32 font_key);
- // Returns cache fragment corresponding to specific font key.
- void* GetCachedFragment(UINT32 font_key, UINT64 start_offset, UINT64 length);
- // Returns actual font file size at the time of caching.
- UINT64 GetCachedFileSize(UINT32 font_key);
-
- // Returns instance of font cache writer. This class manages actual font
- // file format.
- FontCacheWriter* GetFontCacheWriter();
-
- private:
- // Functions validates and loads cache into internal map.
- bool ValidateAndLoadCacheMap();
-
- mswr::ComPtr<IDWriteFontFileLoader> file_loader_;
-
- std::vector<base::string16> reg_fonts_;
- bool in_collection_building_mode_;
- bool create_static_cache_;
- scoped_ptr<base::SharedMemory> cache_;
- scoped_ptr<FontCacheWriter> cache_writer_;
-
- typedef std::map<base::string16, CacheTableEntry*> CacheMap;
- CacheMap cache_map_;
-
- DISALLOW_COPY_AND_ASSIGN(FontCollectionLoader);
-};
-
-mswr::ComPtr<FontCollectionLoader> g_font_loader;
-base::win::ScopedHandle g_shared_font_cache;
-
-// Class responsible for handling font cache file format details as well as
-// tracking various cache region requests by direct write.
-class FontCacheWriter {
- public:
- FontCacheWriter() : count_font_entries_ignored_(0), cookie_counter_(0) {}
-
- ~FontCacheWriter() {
- if (static_cache_.get()) {
- static_cache_->Close();
- }
- }
-
- public:
- // Holds data related to individual region as requested by direct write.
- struct CacheRegion {
- UINT64 start_offset;
- UINT64 length;
- const BYTE* ptr;
- /* BYTE blob_[]; // Place holder for the blob that follows. */
- };
-
- // Function to create static font cache file.
- bool Create(const wchar_t* file_name) {
- static_cache_.reset(new base::File(base::FilePath(file_name),
- base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_WRITE |
- base::File::FLAG_EXCLUSIVE_WRITE));
- if (!static_cache_->IsValid()) {
- static_cache_.reset();
- return false;
- }
- CacheFileHeader header;
-
- // At offset 0 write cache version
- static_cache_->Write(0,
- reinterpret_cast<const char*>(&header),
- sizeof(header));
-
- static_cache_->Flush();
- return true;
- }
-
- // Closes static font cache file. Also writes completion signature to mark
- // it as completely written.
- void Close() {
- if (static_cache_.get()) {
- CacheFileHeader header;
- header.magic_completion_signature = kMagicCompletionSignature;
- // At offset 0 write cache version
- int bytes_written = static_cache_->Write(0,
- reinterpret_cast<const char*>(&header),
- sizeof(header));
- DCHECK_NE(bytes_written, -1);
-
- UMA_HISTOGRAM_MEMORY_KB("DirectWrite.Fonts.BuildCache.File.Size",
- static_cache_->GetLength() / 1024);
-
- UMA_HISTOGRAM_COUNTS("DirectWrite.Fonts.BuildCache.Ignored",
- count_font_entries_ignored_);
-
- static_cache_->Close();
- static_cache_.reset(NULL);
- }
- }
-
- private:
- typedef std::vector<CacheRegion> RegionVector;
-
- // Structure to track various regions requested by direct write for particular
- // font file.
- struct FontEntryInternal {
- FontEntryInternal(const wchar_t* name, UINT64 size)
- : file_name(name),
- file_size(size) {
- }
-
- base::string16 file_name;
- UINT64 file_size;
- RegionVector regions;
- };
-
- public:
- // Starts up new font entry to be tracked, returns cookie to identify this
- // particular entry.
- UINT NewFontEntry(const wchar_t* file_name, UINT64 file_size) {
- base::AutoLock lock(lock_);
- UINT old_counter = cookie_counter_;
- FontEntryInternal* font_entry = new FontEntryInternal(file_name, file_size);
- cookie_map_[cookie_counter_].reset(font_entry);
- cookie_counter_++;
- return old_counter;
- }
-
- // AddRegion function lets caller add various regions to be cached for
- // particular font file. Once enumerating that particular font file is done
- // (based on uniquely identifying cookie) changes could be committed using
- // CommitFontEntry
- bool AddRegion(UINT64 cookie, UINT64 start, UINT64 length, const BYTE* ptr) {
- base::AutoLock lock(lock_);
- if (cookie_map_.find(cookie) == cookie_map_.end())
- return false;
- RegionVector& regions = cookie_map_[cookie].get()->regions;
- CacheRegion region;
- region.start_offset = start;
- region.length = length;
- region.ptr = ptr;
- regions.push_back(region);
- return true;
- }
-
- // Function which commits after merging all collected regions into cache file.
- bool CommitFontEntry(UINT cookie) {
- base::AutoLock lock(lock_);
- if (cookie_map_.find(cookie) == cookie_map_.end())
- return false;
-
- // We will skip writing entries beyond allowed limit. Following condition
- // doesn't enforce hard file size. We need to write complete font entry.
- int64_t length = static_cache_->GetLength();
- if (length == -1 || length >= kArbitraryCacheFileSizeLimit) {
- count_font_entries_ignored_++;
- return false;
- }
-
- FontEntryInternal* font_entry = cookie_map_[cookie].get();
- RegionVector& regions = font_entry->regions;
- std::sort(regions.begin(), regions.end(), SortCacheRegions);
-
- // At this point, we have collected all regions to be cached. These regions
- // are tuples of start, length, data for particular data segment.
- // These tuples can overlap.
- // e.g. (0, 12, data), (0, 117, data), (21, 314, data), (335, 15, data)
- // In this case as you can see first three segments overlap and
- // 4th is adjacent. If we cache them individually then we will end up
- // caching duplicate data, so we merge these segments together to find
- // superset for the cache. In above example our algorithm should
- // produce (cache) single segment starting at offset 0 with length 350.
- RegionVector merged_regions;
- RegionVector::iterator iter;
- int idx = 0;
- for (iter = regions.begin(); iter != regions.end(); iter++) {
- if (iter == regions.begin()) {
- merged_regions.push_back(*iter);
- continue;
- }
- CacheRegion& base_region = merged_regions[idx];
- if (IsOverlap(&base_region, &(*iter))) {
- UINT64 end1 = base_region.start_offset + base_region.length;
- UINT64 end2 = iter->start_offset + iter->length;
- if (base_region.start_offset > iter->start_offset) {
- base_region.start_offset = iter->start_offset;
- base_region.ptr = iter->ptr;
- }
- base_region.length = std::max(end1, end2) - base_region.start_offset;
- } else {
- merged_regions.push_back(*iter);
- idx++;
- }
- }
-
- UINT64 total_merged_cache_in_bytes = 0;
- for (iter = merged_regions.begin(); iter != merged_regions.end(); iter++) {
- total_merged_cache_in_bytes += iter->length;
- }
-
- // We want to adjust following parameter based on experiments. But general
- // logic here is that if we are going to end up caching most of the contents
- // for a file (e.g. simsunb.ttf > 90%) then we should avoid caching that
- // file.
- double percentile = static_cast<double>(total_merged_cache_in_bytes) /
- font_entry->file_size;
- if (percentile > kMaxPercentileOfFontFileSizeToCache) {
- count_font_entries_ignored_++;
- return false;
- }
-
- CacheFileEntry entry;
- wcsncpy_s(entry.file_name, kMaxFontFileNameLength,
- font_entry->file_name.c_str(), _TRUNCATE);
- entry.file_size = font_entry->file_size;
- entry.entry_count = merged_regions.size();
- static_cache_->WriteAtCurrentPos(
- reinterpret_cast<const char*>(&entry),
- sizeof(entry));
- for (iter = merged_regions.begin(); iter != merged_regions.end(); iter++) {
- CacheFileOffsetEntry offset_entry;
- offset_entry.start_offset = iter->start_offset;
- offset_entry.length = iter->length;
- static_cache_->WriteAtCurrentPos(
- reinterpret_cast<const char*>(&offset_entry),
- sizeof(offset_entry));
- static_cache_->WriteAtCurrentPos(
- reinterpret_cast<const char*>(iter->ptr),
- iter->length);
- }
- return true;
- }
-
- private:
- // This is the count of font entries that we reject based on size to be
- // cached.
- unsigned int count_font_entries_ignored_;
- scoped_ptr<base::File> static_cache_;
- std::map<UINT, scoped_ptr<FontEntryInternal>> cookie_map_;
- UINT cookie_counter_;
-
- // Lock is required to protect internal data structures and access to file,
- // According to MSDN documentation on ReadFileFragment and based on our
- // experiments so far, there is possibility of ReadFileFragment getting called
- // from multiple threads.
- base::Lock lock_;
-
- // Function checks if two regions overlap or are adjacent.
- bool IsOverlap(CacheRegion* region1, CacheRegion* region2) {
- return
- !((region1->start_offset + region1->length) < region2->start_offset ||
- region1->start_offset > (region2->start_offset + region2->length));
- }
-
- // Function to sort cached regions.
- static bool SortCacheRegions(const CacheRegion& region1,
- const CacheRegion& region2) {
- return
- region1.start_offset == region2.start_offset ?
- region1.length < region2.length :
- region1.start_offset < region2.start_offset;
- }
-
- DISALLOW_COPY_AND_ASSIGN(FontCacheWriter);
-};
-
-// Class implements IDWriteFontFileStream interface as required by direct write.
-class FontFileStream
- : public mswr::RuntimeClass<mswr::RuntimeClassFlags<mswr::ClassicCom>,
- IDWriteFontFileStream> {
- public:
- // IDWriteFontFileStream methods.
- HRESULT STDMETHODCALLTYPE ReadFileFragment(
- void const** fragment_start,
- UINT64 file_offset,
- UINT64 fragment_size,
- void** context) override {
- if (cached_data_) {
- *fragment_start = g_font_loader->GetCachedFragment(font_key_,
- file_offset,
- fragment_size);
- if (*fragment_start == NULL) {
- DCHECK(false);
- }
- *context = NULL;
- return *fragment_start != NULL ? S_OK : E_FAIL;
- }
- if (!memory_.get() || !memory_->IsValid() ||
- file_offset >= memory_->length() ||
- (file_offset + fragment_size) > memory_->length())
- return E_FAIL;
-
- *fragment_start = static_cast<BYTE const*>(memory_->data()) +
- static_cast<size_t>(file_offset);
- *context = NULL;
- if (g_font_loader->IsBuildStaticCacheMode()) {
- FontCacheWriter* cache_writer = g_font_loader->GetFontCacheWriter();
- cache_writer->AddRegion(writer_cookie_,
- file_offset,
- fragment_size,
- static_cast<const BYTE*>(*fragment_start));
- }
- return S_OK;
- }
-
- void STDMETHODCALLTYPE ReleaseFileFragment(void* context) override {}
-
- HRESULT STDMETHODCALLTYPE GetFileSize(UINT64* file_size) override {
- if (cached_data_) {
- *file_size = g_font_loader->GetCachedFileSize(font_key_);
- return S_OK;
- }
-
- if (!memory_.get() || !memory_->IsValid())
- return E_FAIL;
-
- *file_size = memory_->length();
- return S_OK;
- }
-
- HRESULT STDMETHODCALLTYPE GetLastWriteTime(UINT64* last_write_time) override {
- if (cached_data_) {
- *last_write_time = 0;
- return S_OK;
- }
-
- if (!memory_.get() || !memory_->IsValid())
- return E_FAIL;
-
- // According to MSDN article http://goo.gl/rrSYzi the "last modified time"
- // is used by DirectWrite font selection algorithms to determine whether
- // one font resource is more up to date than another one.
- // So by returning 0 we are assuming that it will treat all fonts to be
- // equally up to date.
- // TODO(shrikant): We should further investigate this.
- *last_write_time = 0;
- return S_OK;
- }
-
- FontFileStream() : font_key_(0), cached_data_(false) {}
-
- HRESULT RuntimeClassInitialize(UINT32 font_key) {
- if (g_font_loader->InCollectionBuildingMode() &&
- g_font_loader->IsFileCached(font_key)) {
- cached_data_ = true;
- font_key_ = font_key;
- return S_OK;
- }
-
- base::FilePath path;
- PathService::Get(base::DIR_WINDOWS_FONTS, &path);
- base::string16 font_key_name(g_font_loader->GetFontNameFromKey(font_key));
- path = path.Append(font_key_name.c_str());
- memory_.reset(new base::MemoryMappedFile());
-
- // Put some debug information on stack.
- WCHAR font_name[MAX_PATH];
- path.value().copy(font_name, arraysize(font_name));
- base::debug::Alias(font_name);
-
- if (!memory_->Initialize(path)) {
- memory_.reset();
- return E_FAIL;
- }
-
- font_key_ = font_key;
-
- base::debug::SetCrashKeyValue(kFontKeyName,
- base::WideToUTF8(font_key_name));
-
- if (g_font_loader->IsBuildStaticCacheMode()) {
- FontCacheWriter* cache_writer = g_font_loader->GetFontCacheWriter();
- writer_cookie_ = cache_writer->NewFontEntry(font_key_name.c_str(),
- memory_->length());
- }
- return S_OK;
- }
-
- ~FontFileStream() override {
- if (g_font_loader->IsBuildStaticCacheMode()) {
- FontCacheWriter* cache_writer = g_font_loader->GetFontCacheWriter();
- cache_writer->CommitFontEntry(writer_cookie_);
- }
- }
-
- private:
- UINT32 font_key_;
- scoped_ptr<base::MemoryMappedFile> memory_;
- bool cached_data_;
- UINT writer_cookie_;
-
- DISALLOW_COPY_AND_ASSIGN(FontFileStream);
-};
-
-// Implements IDWriteFontFileLoader as required by FontFileLoader.
-class FontFileLoader
- : public mswr::RuntimeClass<mswr::RuntimeClassFlags<mswr::ClassicCom>,
- IDWriteFontFileLoader> {
- public:
- // IDWriteFontFileLoader methods.
- HRESULT STDMETHODCALLTYPE
- CreateStreamFromKey(void const* ref_key,
- UINT32 ref_key_size,
- IDWriteFontFileStream** stream) override {
- if (ref_key_size != sizeof(UINT32))
- return E_FAIL;
-
- UINT32 font_key = *static_cast<const UINT32*>(ref_key);
- mswr::ComPtr<FontFileStream> font_stream;
- HRESULT hr = mswr::MakeAndInitialize<FontFileStream>(&font_stream,
- font_key);
- if (SUCCEEDED(hr)) {
- *stream = font_stream.Detach();
- return S_OK;
- }
- return E_FAIL;
- }
-
- FontFileLoader() {}
- ~FontFileLoader() override {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FontFileLoader);
-};
-
-// Implements IDWriteFontFileEnumerator as required by direct write.
-class FontFileEnumerator
- : public mswr::RuntimeClass<mswr::RuntimeClassFlags<mswr::ClassicCom>,
- IDWriteFontFileEnumerator> {
- public:
- // IDWriteFontFileEnumerator methods.
- HRESULT STDMETHODCALLTYPE MoveNext(BOOL* has_current_file) override {
- *has_current_file = FALSE;
-
- if (current_file_)
- current_file_.ReleaseAndGetAddressOf();
-
- if (font_idx_ < g_font_loader->GetFontMapSize()) {
- HRESULT hr =
- factory_->CreateCustomFontFileReference(&font_idx_,
- sizeof(UINT32),
- file_loader_.Get(),
- current_file_.GetAddressOf());
- DCHECK(SUCCEEDED(hr));
- *has_current_file = TRUE;
- font_idx_++;
- }
- return S_OK;
- }
-
- HRESULT STDMETHODCALLTYPE
- GetCurrentFontFile(IDWriteFontFile** font_file) override {
- if (!current_file_) {
- *font_file = NULL;
- return E_FAIL;
- }
-
- *font_file = current_file_.Detach();
- return S_OK;
- }
-
- FontFileEnumerator(const void* keys,
- UINT32 buffer_size,
- IDWriteFactory* factory,
- IDWriteFontFileLoader* file_loader)
- : factory_(factory), file_loader_(file_loader), font_idx_(0) {}
-
- ~FontFileEnumerator() override {}
-
- mswr::ComPtr<IDWriteFactory> factory_;
- mswr::ComPtr<IDWriteFontFile> current_file_;
- mswr::ComPtr<IDWriteFontFileLoader> file_loader_;
- UINT32 font_idx_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FontFileEnumerator);
-};
-
-// IDWriteFontCollectionLoader methods.
-HRESULT STDMETHODCALLTYPE FontCollectionLoader::CreateEnumeratorFromKey(
- IDWriteFactory* factory,
- void const* key,
- UINT32 key_size,
- IDWriteFontFileEnumerator** file_enumerator) {
- *file_enumerator = mswr::Make<FontFileEnumerator>(
- key, key_size, factory, file_loader_.Get()).Detach();
- return S_OK;
-}
-
-// static
-HRESULT FontCollectionLoader::Initialize(IDWriteFactory* factory) {
- DCHECK(g_font_loader == NULL);
-
- HRESULT result;
- result = mswr::MakeAndInitialize<FontCollectionLoader>(&g_font_loader);
- if (FAILED(result) || !g_font_loader) {
- DCHECK(false);
- return E_FAIL;
- }
-
- CHECK(g_font_loader->LoadFontListFromRegistry());
-
- g_font_loader->file_loader_ = mswr::Make<FontFileLoader>().Detach();
-
- factory->RegisterFontFileLoader(g_font_loader->file_loader_.Get());
- factory->RegisterFontCollectionLoader(g_font_loader.Get());
-
- return S_OK;
-}
-
-FontCollectionLoader::~FontCollectionLoader() {
- STLDeleteContainerPairSecondPointers(cache_map_.begin(), cache_map_.end());
-}
-
-UINT32 FontCollectionLoader::GetFontMapSize() {
- return reg_fonts_.size();
-}
-
-base::string16 FontCollectionLoader::GetFontNameFromKey(UINT32 idx) {
- DCHECK(idx < reg_fonts_.size());
- return reg_fonts_[idx];
-}
-
-const base::FilePath::CharType* kFontExtensionsToIgnore[] {
- FILE_PATH_LITERAL(".FON"), // Bitmap or vector
- FILE_PATH_LITERAL(".PFM"), // Adobe Type 1
- FILE_PATH_LITERAL(".PFB"), // Adobe Type 1
-};
-
-const wchar_t* kFontsToIgnore[] = {
- // "Gill Sans Ultra Bold" turns into an Ultra Bold weight "Gill Sans" in
- // DirectWrite, but most users don't have any other weights. The regular
- // weight font is named "Gill Sans MT", but that ends up in a different
- // family with that name. On Mac, there's a "Gill Sans" with various weights,
- // so CSS authors use { 'font-family': 'Gill Sans', 'Gill Sans MT', ... } and
- // because of the DirectWrite family futzing, they end up with an Ultra Bold
- // font, when they just wanted "Gill Sans". Mozilla implemented a more
- // complicated hack where they effectively rename the Ultra Bold font to
- // "Gill Sans MT Ultra Bold", but because the Ultra Bold font is so ugly
- // anyway, we simply ignore it. See
- // http://www.microsoft.com/typography/fonts/font.aspx?FMID=978 for a picture
- // of the font, and the file name. We also ignore "Gill Sans Ultra Bold
- // Condensed".
- L"gilsanub.ttf",
- L"gillubcd.ttf",
-};
-
-bool FontCollectionLoader::LoadFontListFromRegistry() {
- const wchar_t kFontsRegistry[] =
- L"Software\\Microsoft\\Windows NT\\CurrentVersion\\Fonts";
- CHECK(reg_fonts_.empty());
- base::win::RegKey regkey;
- if (regkey.Open(HKEY_LOCAL_MACHINE, kFontsRegistry, KEY_READ) !=
- ERROR_SUCCESS) {
- return false;
- }
-
- base::FilePath system_font_path;
- PathService::Get(base::DIR_WINDOWS_FONTS, &system_font_path);
-
- base::string16 name;
- base::string16 value;
- for (DWORD idx = 0; idx < regkey.GetValueCount(); idx++) {
- if (regkey.GetValueNameAt(idx, &name) == ERROR_SUCCESS &&
- regkey.ReadValue(name.c_str(), &value) == ERROR_SUCCESS) {
- base::FilePath path(value.c_str());
- // We need to check if path in registry is absolute, if it is then
- // we check if it is same as DIR_WINDOWS_FONTS otherwise we ignore.
- bool absolute = path.IsAbsolute();
- if (absolute &&
- !base::FilePath::CompareEqualIgnoreCase(system_font_path.value(),
- path.DirName().value())) {
- continue;
- }
-
- // Ignore if path ends with a separator.
- if (path.EndsWithSeparator())
- continue;
-
- if (absolute)
- value = path.BaseName().value();
-
- bool should_ignore = false;
- for (const auto& ignore : kFontsToIgnore) {
- if (base::FilePath::CompareEqualIgnoreCase(value, ignore)) {
- should_ignore = true;
- break;
- }
- }
- // DirectWrite doesn't support bitmap/vector fonts and Adobe type 1
- // fonts, we will ignore those font extensions.
- // MSDN article: http://goo.gl/TfCOA
- if (!should_ignore) {
- for (const auto& ignore : kFontExtensionsToIgnore) {
- if (path.MatchesExtension(ignore)) {
- should_ignore = true;
- break;
- }
- }
- }
-
- if (!should_ignore)
- reg_fonts_.push_back(value.c_str());
- }
- }
- UMA_HISTOGRAM_COUNTS("DirectWrite.Fonts.Loaded", reg_fonts_.size());
- UMA_HISTOGRAM_COUNTS("DirectWrite.Fonts.Ignored",
- regkey.GetValueCount() - reg_fonts_.size());
- return true;
-}
-
-// This list is mainly based on prefs/prefs_tab_helper.cc kFontDefaults.
-const wchar_t* kRestrictedFontSet[] = {
- // These are the "Web Safe" fonts.
- L"times.ttf", // IDS_STANDARD_FONT_FAMILY
- L"timesbd.ttf", // IDS_STANDARD_FONT_FAMILY
- L"timesbi.ttf", // IDS_STANDARD_FONT_FAMILY
- L"timesi.ttf", // IDS_STANDARD_FONT_FAMILY
- L"cour.ttf", // IDS_FIXED_FONT_FAMILY
- L"courbd.ttf", // IDS_FIXED_FONT_FAMILY
- L"courbi.ttf", // IDS_FIXED_FONT_FAMILY
- L"couri.ttf", // IDS_FIXED_FONT_FAMILY
- L"consola.ttf", // IDS_FIXED_FONT_FAMILY_ALT_WIN
- L"consolab.ttf", // IDS_FIXED_FONT_FAMILY_ALT_WIN
- L"consolai.ttf", // IDS_FIXED_FONT_FAMILY_ALT_WIN
- L"consolaz.ttf", // IDS_FIXED_FONT_FAMILY_ALT_WIN
- L"arial.ttf", // IDS_SANS_SERIF_FONT_FAMILY
- L"arialbd.ttf", // IDS_SANS_SERIF_FONT_FAMILY
- L"arialbi.ttf", // IDS_SANS_SERIF_FONT_FAMILY
- L"ariali.ttf", // IDS_SANS_SERIF_FONT_FAMILY
- L"comic.ttf", // IDS_CURSIVE_FONT_FAMILY
- L"comicbd.ttf", // IDS_CURSIVE_FONT_FAMILY
- L"comici.ttf", // IDS_CURSIVE_FONT_FAMILY
- L"comicz.ttf", // IDS_CURSIVE_FONT_FAMILY
- L"impact.ttf", // IDS_FANTASY_FONT_FAMILY
- L"georgia.ttf",
- L"georgiab.ttf",
- L"georgiai.ttf",
- L"georgiaz.ttf",
- L"trebuc.ttf",
- L"trebucbd.ttf",
- L"trebucbi.ttf",
- L"trebucit.ttf",
- L"verdana.ttf",
- L"verdanab.ttf",
- L"verdanai.ttf",
- L"verdanaz.ttf",
- L"segoeui.ttf", // IDS_PICTOGRAPH_FONT_FAMILY
- L"segoeuib.ttf", // IDS_PICTOGRAPH_FONT_FAMILY
- L"segoeuii.ttf", // IDS_PICTOGRAPH_FONT_FAMILY
- L"msgothic.ttc", // IDS_STANDARD_FONT_FAMILY_JAPANESE
- L"msmincho.ttc", // IDS_SERIF_FONT_FAMILY_JAPANESE
- L"gulim.ttc", // IDS_FIXED_FONT_FAMILY_KOREAN
- L"batang.ttc", // IDS_SERIF_FONT_FAMILY_KOREAN
- L"simsun.ttc", // IDS_STANDARD_FONT_FAMILY_SIMPLIFIED_HAN
- L"mingliu.ttc", // IDS_SERIF_FONT_FAMILY_TRADITIONAL_HAN
-
- // These are from the Blink fallback list.
- L"david.ttf", // USCRIPT_HEBREW
- L"davidbd.ttf", // USCRIPT_HEBREW
- L"euphemia.ttf", // USCRIPT_CANADIAN_ABORIGINAL
- L"gautami.ttf", // USCRIPT_TELUGU
- L"gautamib.ttf", // USCRIPT_TELUGU
- L"latha.ttf", // USCRIPT_TAMIL
- L"lathab.ttf", // USCRIPT_TAMIL
- L"mangal.ttf", // USCRIPT_DEVANAGARI
- L"mangalb.ttf", // USCRIPT_DEVANAGARI
- L"monbaiti.ttf", // USCRIPT_MONGOLIAN
- L"mvboli.ttf", // USCRIPT_THAANA
- L"plantc.ttf", // USCRIPT_CHEROKEE
- L"raavi.ttf", // USCRIPT_GURMUKHI
- L"raavib.ttf", // USCRIPT_GURMUKHI
- L"shruti.ttf", // USCRIPT_GUJARATI
- L"shrutib.ttf", // USCRIPT_GUJARATI
- L"sylfaen.ttf", // USCRIPT_GEORGIAN and USCRIPT_ARMENIAN
- L"tahoma.ttf", // USCRIPT_ARABIC,
- L"tahomabd.ttf", // USCRIPT_ARABIC,
- L"tunga.ttf", // USCRIPT_KANNADA
- L"tungab.ttf", // USCRIPT_KANNADA
- L"vrinda.ttf", // USCRIPT_BENGALI
- L"vrindab.ttf", // USCRIPT_BENGALI
-};
-
-bool FontCollectionLoader::LoadRestrictedFontList() {
- reg_fonts_.clear();
- reg_fonts_.assign(kRestrictedFontSet,
- kRestrictedFontSet + _countof(kRestrictedFontSet));
- return true;
-}
-
-void FontCollectionLoader::EnableCollectionBuildingMode(bool enable) {
- in_collection_building_mode_ = enable;
-}
-
-bool FontCollectionLoader::InCollectionBuildingMode() {
- return in_collection_building_mode_;
-}
-
-bool FontCollectionLoader::IsFileCached(UINT32 font_key) {
- if (!cache_.get() || cache_->memory() == NULL) {
- return false;
- }
- CacheMap::iterator iter = cache_map_.find(
- GetFontNameFromKey(font_key).c_str());
- return iter != cache_map_.end();
-}
-
-bool FontCollectionLoader::LoadCacheFile() {
- TRACE_EVENT0("startup", "FontCollectionLoader::LoadCacheFile");
-
- std::string font_cache_handle_string =
- base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kFontCacheSharedHandle);
- if (font_cache_handle_string.empty())
- return false;
-
- unsigned int handle_uint;
- base::StringToUint(font_cache_handle_string, &handle_uint);
- DCHECK(handle_uint);
- if (handle_uint > static_cast<unsigned int>(std::numeric_limits<long>::max()))
- return false;
- base::SharedMemoryHandle font_cache_handle(LongToHandle(handle_uint),
- base::GetCurrentProcId());
-
- base::SharedMemory* shared_mem = new base::SharedMemory(
- font_cache_handle, true);
- // Map the cache file into memory.
- shared_mem->Map(0);
-
- cache_.reset(shared_mem);
-
- if (base::StartsWith(base::FieldTrialList::FindFullName("LightSpeed"),
- "PrefetchDWriteFontCache",
- base::CompareCase::SENSITIVE)) {
- // Prefetch the cache, to avoid unordered IO when it is used.
- // PrefetchVirtualMemory() is loaded dynamically because it is only
- // available from Win8.
- decltype(PrefetchVirtualMemory)* prefetch_virtual_memory =
- reinterpret_cast<decltype(PrefetchVirtualMemory)*>(::GetProcAddress(
- ::GetModuleHandle(L"kernel32.dll"), "PrefetchVirtualMemory"));
- if (prefetch_virtual_memory != NULL) {
- WIN32_MEMORY_RANGE_ENTRY memory_range;
- memory_range.VirtualAddress = shared_mem->memory();
- memory_range.NumberOfBytes = shared_mem->mapped_size();
- prefetch_virtual_memory(::GetCurrentProcess(), 1, &memory_range, 0);
- }
- }
-
- if (!ValidateAndLoadCacheMap()) {
- cache_.reset();
- return false;
- }
-
- return true;
-}
-
-void FontCollectionLoader::UnloadCacheFile() {
- cache_.reset();
- STLDeleteContainerPairSecondPointers(cache_map_.begin(), cache_map_.end());
- cache_map_.clear();
-}
-
-void FontCollectionLoader::EnterStaticCacheMode(const WCHAR* file_name) {
- cache_writer_.reset(new FontCacheWriter());
- if (cache_writer_->Create(file_name))
- create_static_cache_ = true;
-}
-
-void FontCollectionLoader::LeaveStaticCacheMode() {
- cache_writer_->Close();
- cache_writer_.reset(NULL);
- create_static_cache_ = false;
-}
-
-bool FontCollectionLoader::IsBuildStaticCacheMode() {
- return create_static_cache_;
-}
-
-bool FontCollectionLoader::ValidateAndLoadCacheMap() {
- BYTE* mem_file_start = static_cast<BYTE*>(cache_->memory());
- BYTE* mem_file_end = mem_file_start + cache_->mapped_size();
-
- BYTE* current_ptr = mem_file_start;
- CacheFileHeader* file_header =
- reinterpret_cast<CacheFileHeader*>(current_ptr);
- if (!ValidateFontCacheHeader(file_header))
- return false;
-
- current_ptr = current_ptr + sizeof(CacheFileHeader);
- if (current_ptr >= mem_file_end)
- return false;
-
- while ((current_ptr + sizeof(CacheFileEntry)) < mem_file_end) {
- CacheFileEntry* entry = reinterpret_cast<CacheFileEntry*>(current_ptr);
- current_ptr += sizeof(CacheFileEntry);
- WCHAR file_name[kMaxFontFileNameLength];
- wcsncpy_s(file_name,
- kMaxFontFileNameLength,
- entry->file_name,
- _TRUNCATE);
- CacheTableEntry* table_entry = NULL;
- CacheMap::iterator iter = cache_map_.find(file_name);
- if (iter == cache_map_.end()) {
- table_entry = new CacheTableEntry();
- cache_map_[file_name] = table_entry;
- } else {
- table_entry = iter->second;
- }
- table_entry->file_size = entry->file_size;
- for (DWORD idx = 0;
- (current_ptr + sizeof(CacheFileOffsetEntry)) < mem_file_end &&
- idx < entry->entry_count;
- idx++) {
- CacheFileOffsetEntry* offset_entry =
- reinterpret_cast<CacheFileOffsetEntry*>(current_ptr);
- CacheTableOffsetEntry table_offset_entry;
- table_offset_entry.start_offset = offset_entry->start_offset;
- table_offset_entry.length = offset_entry->length;
- table_offset_entry.inside_file_ptr =
- current_ptr + sizeof(CacheFileOffsetEntry);
- table_entry->offset_entries.push_back(table_offset_entry);
- current_ptr += sizeof(CacheFileOffsetEntry);
- current_ptr += offset_entry->length;
- }
- }
-
- return true;
-}
-
-void* FontCollectionLoader::GetCachedFragment(UINT32 font_key,
- UINT64 start_offset,
- UINT64 length) {
- UINT64 just_past_end = start_offset + length;
- CacheMap::iterator iter = cache_map_.find(
- GetFontNameFromKey(font_key).c_str());
- if (iter != cache_map_.end()) {
- CacheTableEntry* entry = iter->second;
- OffsetVector::iterator offset_iter = entry->offset_entries.begin();
- while (offset_iter != entry->offset_entries.end()) {
- UINT64 available_just_past_end =
- offset_iter->start_offset + offset_iter->length;
- if (offset_iter->start_offset <= start_offset &&
- just_past_end <= available_just_past_end) {
- return offset_iter->inside_file_ptr +
- (start_offset - offset_iter->start_offset);
- }
- offset_iter++;
- }
- }
- return NULL;
-}
-
-UINT64 FontCollectionLoader::GetCachedFileSize(UINT32 font_key) {
- CacheMap::iterator iter = cache_map_.find(
- GetFontNameFromKey(font_key).c_str());
- if (iter != cache_map_.end()) {
- return iter->second->file_size;
- }
- return 0;
-}
-
-FontCacheWriter* FontCollectionLoader::GetFontCacheWriter() {
- return cache_writer_.get();
-}
-
-} // namespace
-
-namespace content {
-
-const char kFontCacheSharedSectionName[] = "ChromeDWriteFontCache";
-
-mswr::ComPtr<IDWriteFontCollection> g_font_collection;
-
-IDWriteFontCollection* GetCustomFontCollection(IDWriteFactory* factory) {
- if (g_font_collection.Get() != NULL)
- return g_font_collection.Get();
-
- TRACE_EVENT0("startup", "content::GetCustomFontCollection");
-
- base::TimeTicks start_tick = base::TimeTicks::Now();
-
- FontCollectionLoader::Initialize(factory);
-
- bool cache_file_loaded = g_font_loader->LoadCacheFile();
-
- // Arbitrary threshold to stop loading enormous number of fonts. Usual
- // side effect of loading large number of fonts results in renderer getting
- // killed as it appears to hang.
- const UINT32 kMaxFontThreshold = 1750;
- HRESULT hr = E_FAIL;
- if (cache_file_loaded ||
- g_font_loader->GetFontMapSize() < kMaxFontThreshold) {
- g_font_loader->EnableCollectionBuildingMode(true);
- hr = factory->CreateCustomFontCollection(
- g_font_loader.Get(), NULL, 0, g_font_collection.GetAddressOf());
- g_font_loader->UnloadCacheFile();
- g_font_loader->EnableCollectionBuildingMode(false);
- }
- bool loading_restricted = false;
- if (FAILED(hr) || !g_font_collection.Get()) {
- loading_restricted = true;
- // We will try here just one more time with restricted font set.
- g_font_loader->LoadRestrictedFontList();
- hr = factory->CreateCustomFontCollection(
- g_font_loader.Get(), NULL, 0, g_font_collection.GetAddressOf());
- }
-
- base::TimeDelta time_delta = base::TimeTicks::Now() - start_tick;
- int64_t delta = time_delta.ToInternalValue();
- base::debug::Alias(&delta);
- UINT32 size = g_font_loader->GetFontMapSize();
- base::debug::Alias(&size);
- base::debug::Alias(&loading_restricted);
-
- CHECK(SUCCEEDED(hr));
- CHECK(g_font_collection.Get() != NULL);
-
- if (cache_file_loaded)
- UMA_HISTOGRAM_TIMES("DirectWrite.Fonts.LoadTime.Cached", time_delta);
- else
- UMA_HISTOGRAM_TIMES("DirectWrite.Fonts.LoadTime", time_delta);
-
- base::debug::ClearCrashKey(kFontKeyName);
-
- return g_font_collection.Get();
-}
-
-bool BuildFontCacheInternal(const WCHAR* file_name) {
- typedef decltype(DWriteCreateFactory)* DWriteCreateFactoryProc;
- HMODULE dwrite_dll = LoadLibraryW(L"dwrite.dll");
- if (!dwrite_dll) {
- DWORD load_library_get_last_error = GetLastError();
- base::debug::Alias(&dwrite_dll);
- base::debug::Alias(&load_library_get_last_error);
- CHECK(false);
- }
-
- DWriteCreateFactoryProc dwrite_create_factory_proc =
- reinterpret_cast<DWriteCreateFactoryProc>(
- GetProcAddress(dwrite_dll, "DWriteCreateFactory"));
-
- if (!dwrite_create_factory_proc) {
- DWORD get_proc_address_get_last_error = GetLastError();
- base::debug::Alias(&dwrite_create_factory_proc);
- base::debug::Alias(&get_proc_address_get_last_error);
- CHECK(false);
- }
-
- mswr::ComPtr<IDWriteFactory> factory;
-
- CHECK(SUCCEEDED(
- dwrite_create_factory_proc(
- DWRITE_FACTORY_TYPE_ISOLATED,
- __uuidof(IDWriteFactory),
- reinterpret_cast<IUnknown**>(factory.GetAddressOf()))));
-
- base::TimeTicks start_tick = base::TimeTicks::Now();
-
- FontCollectionLoader::Initialize(factory.Get());
-
- g_font_loader->EnterStaticCacheMode(file_name);
-
- mswr::ComPtr<IDWriteFontCollection> font_collection;
-
- HRESULT hr = E_FAIL;
- g_font_loader->EnableCollectionBuildingMode(true);
- hr = factory->CreateCustomFontCollection(
- g_font_loader.Get(), NULL, 0, font_collection.GetAddressOf());
- g_font_loader->EnableCollectionBuildingMode(false);
-
- bool loading_restricted = false;
- if (FAILED(hr) || !font_collection.Get()) {
- loading_restricted = true;
- // We will try here just one more time with restricted font set.
- g_font_loader->LoadRestrictedFontList();
- hr = factory->CreateCustomFontCollection(
- g_font_loader.Get(), NULL, 0, font_collection.GetAddressOf());
- }
-
- g_font_loader->LeaveStaticCacheMode();
-
- base::TimeDelta time_delta = base::TimeTicks::Now() - start_tick;
- int64_t delta = time_delta.ToInternalValue();
- base::debug::Alias(&delta);
- UINT32 size = g_font_loader->GetFontMapSize();
- base::debug::Alias(&size);
- base::debug::Alias(&loading_restricted);
-
- CHECK(SUCCEEDED(hr));
- CHECK(font_collection.Get() != NULL);
-
- base::debug::ClearCrashKey(kFontKeyName);
-
- return true;
-}
-
-bool ValidateFontCacheFile(base::File* file) {
- DCHECK(file != NULL);
- CacheFileHeader file_header;
- if (file->Read(0, reinterpret_cast<char*>(&file_header), sizeof(file_header))
- == -1) {
- return false;
- }
- return ValidateFontCacheHeader(&file_header);
-}
-
-bool LoadFontCache(const base::FilePath& path) {
- scoped_ptr<base::File> file(new base::File(path,
- base::File::FLAG_OPEN | base::File::FLAG_READ));
- if (!file->IsValid())
- return false;
-
- if (!ValidateFontCacheFile(file.get()))
- return false;
-
- base::string16 name(base::ASCIIToUTF16(content::kFontCacheSharedSectionName));
- name.append(base::UintToString16(base::GetCurrentProcId()));
- HANDLE mapping = ::CreateFileMapping(
- file->GetPlatformFile(),
- NULL,
- PAGE_READONLY,
- 0,
- 0,
- name.c_str());
- if (mapping == INVALID_HANDLE_VALUE)
- return false;
-
- if (::GetLastError() == ERROR_ALREADY_EXISTS) {
- CloseHandle(mapping);
- // We crash here, as no one should have created this mapping except Chrome.
- CHECK(false);
- return false;
- }
-
- DCHECK(!g_shared_font_cache.IsValid());
- g_shared_font_cache.Set(mapping);
-
- return true;
-}
-
-bool BuildFontCache(const base::FilePath& file) {
- return BuildFontCacheInternal(file.value().c_str());
-}
-
-bool ShouldUseDirectWriteFontProxyFieldTrial() {
- return base::StartsWith(
- base::FieldTrialList::FindFullName("DirectWriteFontProxy"),
- "UseDirectWriteFontProxy", base::CompareCase::SENSITIVE);
-}
-
-} // namespace content
diff --git a/chromium/content/common/dwrite_font_platform_win_unittest.cc b/chromium/content/common/dwrite_font_platform_win_unittest.cc
deleted file mode 100644
index 4e517feedf6..00000000000
--- a/chromium/content/common/dwrite_font_platform_win_unittest.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/public/common/dwrite_font_platform_win.h"
-
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/logging.h"
-#include "base/path_service.h"
-#include "content/public/common/content_paths.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/gfx/win/direct_write.h"
-
-namespace content {
-
-class DWriteFontCacheTest : public testing::Test {
- public:
- DWriteFontCacheTest() { }
-
- void SetUp() override {
- base::FilePath data_path;
- ASSERT_TRUE(PathService::Get(content::DIR_TEST_DATA, &data_path));
- arial_cache_path_ =
- data_path.AppendASCII("font/dwrite_font_cache_arial.dat");
-
- corrupt_cache_path_ =
- data_path.AppendASCII("font/dwrite_font_cache_corrupt.dat");
-
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- cache_file_path_ = temp_dir_.path().AppendASCII("dwrite_font_cache.dat");
- }
-
- protected:
- base::FilePath arial_cache_path_;
- base::FilePath corrupt_cache_path_;
- base::ScopedTempDir temp_dir_;
- base::FilePath cache_file_path_;
-};
-
-TEST_F(DWriteFontCacheTest, BuildCacheTest) {
- if (gfx::win::ShouldUseDirectWrite()) {
- DLOG(INFO) << __FUNCTION__ << ": " << cache_file_path_.value().c_str();
- EXPECT_TRUE(BuildFontCache(cache_file_path_));
- ASSERT_TRUE(base::PathExists(cache_file_path_));
- }
-}
-
-TEST_F(DWriteFontCacheTest, ValidCacheTest) {
- if (gfx::win::ShouldUseDirectWrite()) {
- DLOG(INFO) << __FUNCTION__ << ": " << arial_cache_path_.value().c_str();
- scoped_ptr<base::File> file(new base::File(arial_cache_path_,
- base::File::FLAG_OPEN | base::File::FLAG_READ));
- ASSERT_TRUE(file->IsValid());
-
- EXPECT_TRUE(ValidateFontCacheFile(file.get()));
- }
-}
-
-TEST_F(DWriteFontCacheTest, CorruptCacheTest) {
- if (gfx::win::ShouldUseDirectWrite()) {
- DLOG(INFO) << __FUNCTION__ << ": " << corrupt_cache_path_.value().c_str();
- scoped_ptr<base::File> file(new base::File(corrupt_cache_path_,
- base::File::FLAG_OPEN | base::File::FLAG_READ));
- ASSERT_TRUE(file->IsValid());
-
- EXPECT_FALSE(ValidateFontCacheFile(file.get()));
- }
-}
-
-} // content
diff --git a/chromium/content/common/establish_channel_params.cc b/chromium/content/common/establish_channel_params.cc
new file mode 100644
index 00000000000..6ca5ac6a7bc
--- /dev/null
+++ b/chromium/content/common/establish_channel_params.cc
@@ -0,0 +1,18 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/establish_channel_params.h"
+
+namespace content {
+
+EstablishChannelParams::EstablishChannelParams()
+ : client_id(0),
+ client_tracing_id(0),
+ preempts(false),
+ allow_view_command_buffers(false),
+ allow_real_time_streams(false) {}
+
+EstablishChannelParams::~EstablishChannelParams() {}
+
+} // namespace content
diff --git a/chromium/content/common/establish_channel_params.h b/chromium/content/common/establish_channel_params.h
new file mode 100644
index 00000000000..f77b1bd8e48
--- /dev/null
+++ b/chromium/content/common/establish_channel_params.h
@@ -0,0 +1,27 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_ESTABLISH_CHANNEL_PARAMS_H_
+#define CONTENT_COMMON_ESTABLISH_CHANNEL_PARAMS_H_
+
+#include <stdint.h>
+
+#include "content/common/content_export.h"
+
+namespace content {
+
+struct CONTENT_EXPORT EstablishChannelParams {
+ EstablishChannelParams();
+ ~EstablishChannelParams();
+
+ int client_id;
+ uint64_t client_tracing_id;
+ bool preempts;
+ bool allow_view_command_buffers;
+ bool allow_real_time_streams;
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_ESTABLISH_CHANNEL_PARAMS_H_
diff --git a/chromium/content/common/experiments/api_key.cc b/chromium/content/common/experiments/api_key.cc
deleted file mode 100644
index 9199d5d776f..00000000000
--- a/chromium/content/common/experiments/api_key.cc
+++ /dev/null
@@ -1,144 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/experiments/api_key.h"
-
-#include <openssl/curve25519.h>
-
-#include <vector>
-
-#include "base/base64.h"
-#include "base/macros.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/time/time.h"
-#include "url/origin.h"
-
-namespace content {
-
-namespace {
-
-// This is the default public key used for validating signatures.
-// TODO(iclelland): Move this to the embedder, and provide a mechanism to allow
-// for multiple signing keys. https://crbug.com/543220
-static const uint8_t kPublicKey[] = {
- 0x7c, 0xc4, 0xb8, 0x9a, 0x93, 0xba, 0x6e, 0xe2, 0xd0, 0xfd, 0x03,
- 0x1d, 0xfb, 0x32, 0x66, 0xc7, 0x3b, 0x72, 0xfd, 0x54, 0x3a, 0x07,
- 0x51, 0x14, 0x66, 0xaa, 0x02, 0x53, 0x4e, 0x33, 0xa1, 0x15,
-};
-
-const char* kApiKeyFieldSeparator = "|";
-
-} // namespace
-
-ApiKey::~ApiKey() {}
-
-scoped_ptr<ApiKey> ApiKey::Parse(const std::string& key_text) {
- if (key_text.empty()) {
- return nullptr;
- }
-
- // API Key should resemble:
- // signature|origin|api_name|expiry_timestamp
- // TODO(iclelland): Add version code to API key format to identify key algo
- // https://crbug.com/570684
- std::vector<std::string> parts =
- SplitString(key_text, kApiKeyFieldSeparator, base::KEEP_WHITESPACE,
- base::SPLIT_WANT_ALL);
- if (parts.size() != 4) {
- return nullptr;
- }
-
- const std::string& signature = parts[0];
- const std::string& origin_string = parts[1];
- const std::string& api_name = parts[2];
- const std::string& expiry_string = parts[3];
-
- uint64_t expiry_timestamp;
- if (!base::StringToUint64(expiry_string, &expiry_timestamp)) {
- return nullptr;
- }
-
- // Ensure that the origin is a valid (non-unique) origin URL
- GURL origin_url(origin_string);
- if (url::Origin(origin_url).unique()) {
- return nullptr;
- }
-
- // signed data is (origin + "|" + api_name + "|" + expiry).
- std::string data = key_text.substr(signature.length() + 1);
-
- return make_scoped_ptr(
- new ApiKey(signature, data, origin_url, api_name, expiry_timestamp));
-}
-
-ApiKey::ApiKey(const std::string& signature,
- const std::string& data,
- const GURL& origin,
- const std::string& api_name,
- uint64_t expiry_timestamp)
- : signature_(signature),
- data_(data),
- origin_(origin),
- api_name_(api_name),
- expiry_timestamp_(expiry_timestamp) {}
-
-bool ApiKey::IsAppropriate(const std::string& origin,
- const std::string& api_name) const {
- return ValidateOrigin(origin) && ValidateApiName(api_name);
-}
-
-bool ApiKey::IsValid(const base::Time& now) const {
- // TODO(iclelland): Allow for multiple signing keys, and iterate over all
- // active keys here. https://crbug.com/543220
- return ValidateDate(now) &&
- ValidateSignature(base::StringPiece(
- reinterpret_cast<const char*>(kPublicKey), arraysize(kPublicKey)));
-}
-
-bool ApiKey::ValidateOrigin(const std::string& origin) const {
- return GURL(origin) == origin_;
-}
-
-bool ApiKey::ValidateApiName(const std::string& api_name) const {
- return base::EqualsCaseInsensitiveASCII(api_name, api_name_);
-}
-
-bool ApiKey::ValidateDate(const base::Time& now) const {
- base::Time expiry_time = base::Time::FromDoubleT((double)expiry_timestamp_);
- return expiry_time > now;
-}
-
-bool ApiKey::ValidateSignature(const base::StringPiece& public_key) const {
- return ValidateSignature(signature_, data_, public_key);
-}
-
-// static
-bool ApiKey::ValidateSignature(const std::string& signature_text,
- const std::string& data,
- const base::StringPiece& public_key) {
- // Public key must be 32 bytes long for Ed25519.
- CHECK_EQ(public_key.length(), 32UL);
-
- std::string signature;
- // signature_text is base64-encoded; decode first.
- if (!base::Base64Decode(signature_text, &signature)) {
- return false;
- }
-
- // Signature must be 64 bytes long
- if (signature.length() != 64) {
- return false;
- }
-
- int result = ED25519_verify(
- reinterpret_cast<const uint8_t*>(data.data()), data.length(),
- reinterpret_cast<const uint8_t*>(signature.data()),
- reinterpret_cast<const uint8_t*>(public_key.data()));
- return (result != 0);
-}
-
-} // namespace content
diff --git a/chromium/content/common/experiments/api_key.h b/chromium/content/common/experiments/api_key.h
deleted file mode 100644
index 1ad575a15e9..00000000000
--- a/chromium/content/common/experiments/api_key.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_EXPERIMENTS_API_KEY_H_
-#define CONTENT_COMMON_EXPERIMENTS_API_KEY_H_
-
-#include <string>
-
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_piece.h"
-#include "base/time/time.h"
-#include "content/common/content_export.h"
-#include "url/gurl.h"
-
-namespace content {
-
-// The Experimental Framework (EF) provides limited access to experimental APIs,
-// on a per-origin basis. This class defines the API key data structure, used
-// to securely provide access to an experimental API.
-//
-// Experimental APIs are defined by string names, provided by the implementers.
-// The EF code does not maintain an enum or constant list for experiment names.
-// Instead, the EF validates the name provided by the API implementation against
-// any provided API keys.
-//
-// More documentation on the key format can be found at
-// https://docs.google.com/document/d/1v5fi0EUV_QHckVHVF2K4P72iNywnrJtNhNZ6i2NPt0M
-
-class CONTENT_EXPORT ApiKey {
- public:
- ~ApiKey();
-
- // Returns a key object if the string represents a well-formed key, or
- // nullptr otherwise. (This does not mean that the key is valid, just that it
- // can be parsed.)
- static scoped_ptr<ApiKey> Parse(const std::string& key_text);
-
- // Returns true if this API is appropriate for use by the given origin, for
- // the given API name. This does not check whether the signature is valid, or
- // whether the key itself has expired.
- bool IsAppropriate(const std::string& origin,
- const std::string& apiName) const;
-
- // Returns true if this API key has a valid signature, and has not expired.
- bool IsValid(const base::Time& now) const;
-
- std::string signature() { return signature_; }
- std::string data() { return data_; }
- GURL origin() { return origin_; }
- std::string api_name() { return api_name_; }
- uint64_t expiry_timestamp() { return expiry_timestamp_; }
-
- protected:
- friend class ApiKeyTest;
-
- bool ValidateOrigin(const std::string& origin) const;
- bool ValidateApiName(const std::string& api_name) const;
- bool ValidateDate(const base::Time& now) const;
- bool ValidateSignature(const base::StringPiece& public_key) const;
-
- static bool ValidateSignature(const std::string& signature_text,
- const std::string& data,
- const base::StringPiece& public_key);
-
- private:
- ApiKey(const std::string& signature,
- const std::string& data,
- const GURL& origin,
- const std::string& api_name,
- uint64_t expiry_timestamp);
-
- // The base64-encoded-signature portion of the key. For the key to be valid,
- // this must be a valid signature for the data portion of the key, as verified
- // by the public key in api_key.cc.
- std::string signature_;
-
- // The portion of the key string which is signed, and whose signature is
- // contained in the signature_ member.
- std::string data_;
-
- // The origin for which this key is valid. Must be a secure origin.
- GURL origin_;
-
- // The name of the API experiment which this key enables.
- std::string api_name_;
-
- // The time until which this key should be considered valid, in UTC, as
- // seconds since the Unix epoch.
- uint64_t expiry_timestamp_;
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_EXPERIMENTS_API_KEY_H_
diff --git a/chromium/content/common/experiments/api_key_unittest.cc b/chromium/content/common/experiments/api_key_unittest.cc
deleted file mode 100644
index a70ffcc92cf..00000000000
--- a/chromium/content/common/experiments/api_key_unittest.cc
+++ /dev/null
@@ -1,191 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/experiments/api_key.h"
-
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/strings/string_util.h"
-#include "base/test/simple_test_clock.h"
-#include "base/time/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-namespace {
-
-// This is a sample public key for testing the API. The corresponding private
-// key (use this to generate new samples for this test file) is:
-//
-// 0x83, 0x67, 0xf4, 0xcd, 0x2a, 0x1f, 0x0e, 0x04, 0x0d, 0x43, 0x13,
-// 0x4c, 0x67, 0xc4, 0xf4, 0x28, 0xc9, 0x90, 0x15, 0x02, 0xe2, 0xba,
-// 0xfd, 0xbb, 0xfa, 0xbc, 0x92, 0x76, 0x8a, 0x2c, 0x4b, 0xc7, 0x75,
-// 0x10, 0xac, 0xf9, 0x3a, 0x1c, 0xb8, 0xa9, 0x28, 0x70, 0xd2, 0x9a,
-// 0xd0, 0x0b, 0x59, 0xe1, 0xac, 0x2b, 0xb7, 0xd5, 0xca, 0x1f, 0x64,
-// 0x90, 0x08, 0x8e, 0xa8, 0xe0, 0x56, 0x3a, 0x04, 0xd0
-const uint8_t kTestPublicKey[] = {
- 0x75, 0x10, 0xac, 0xf9, 0x3a, 0x1c, 0xb8, 0xa9, 0x28, 0x70, 0xd2,
- 0x9a, 0xd0, 0x0b, 0x59, 0xe1, 0xac, 0x2b, 0xb7, 0xd5, 0xca, 0x1f,
- 0x64, 0x90, 0x08, 0x8e, 0xa8, 0xe0, 0x56, 0x3a, 0x04, 0xd0,
-};
-
-// This is a good key, signed with the above test private key.
-const char* kSampleAPIKey =
- "UsEO0cNxoUtBnHDJdGPWTlXuLENjXcEIPL7Bs7sbvicPCcvAtyqhQuTJ9h/u1R3VZpWigtI+S"
- "dUwk7Dyk/qbDw==|https://valid.example.com|Frobulate|1458766277";
-const char* kExpectedAPIKeySignature =
- "UsEO0cNxoUtBnHDJdGPWTlXuLENjXcEIPL7Bs7sbvicPCcvAtyqhQuTJ9h/u1R3VZpWigtI+S"
- "dUwk7Dyk/qbDw==";
-const char* kExpectedAPIKeyData =
- "https://valid.example.com|Frobulate|1458766277";
-const char* kExpectedAPIName = "Frobulate";
-const char* kExpectedOrigin = "https://valid.example.com";
-const uint64_t kExpectedExpiry = 1458766277;
-
-// The key should not be valid for this origin, or for this API.
-const char* kInvalidOrigin = "https://invalid.example.com";
-const char* kInsecureOrigin = "http://valid.example.com";
-const char* kInvalidAPIName = "Grokalyze";
-
-// The key should be valid if the current time is kValidTimestamp or earlier.
-double kValidTimestamp = 1458766276.0;
-
-// The key should be invalid if the current time is kInvalidTimestamp or later.
-double kInvalidTimestamp = 1458766278.0;
-
-// Well-formed API key with an invalid signature.
-const char* kInvalidSignatureAPIKey =
- "CO8hDne98QeFeOJ0DbRZCBN3uE0nyaPgaLlkYhSWnbRoDfEAg+TXELaYfQPfEvKYFauBg/hnx"
- "mba765hz0mXMc==|https://valid.example.com|Frobulate|1458766277";
-
-// Various ill-formed API keys. These should all fail to parse.
-const char* kInvalidAPIKeys[] = {
- // Invalid - only one part
- "abcde",
- // Not enough parts
- "https://valid.example.com|APIName|1458766277",
- // Delimiter in API Name
- "Signature|https://valid.example.com|API|Name|1458766277",
- // Extra string field
- "Signature|https://valid.example.com|APIName|1458766277|SomethingElse",
- // Extra numeric field
- "Signature|https://valid.example.com|APIName|1458766277|1458766277",
- // Non-numeric expiry timestamp
- "Signature|https://valid.example.com|APIName|abcdefghij",
- "Signature|https://valid.example.com|APIName|1458766277x",
- // Negative expiry timestamp
- "Signature|https://valid.example.com|APIName|-1458766277",
- // Origin not a proper origin URL
- "Signature|abcdef|APIName|1458766277",
- "Signature|data:text/plain,abcdef|APIName|1458766277",
- "Signature|javascript:alert(1)|APIName|1458766277"};
-const size_t kNumInvalidAPIKeys = arraysize(kInvalidAPIKeys);
-
-} // namespace
-
-class ApiKeyTest : public testing::Test {
- public:
- ApiKeyTest()
- : public_key_(
- base::StringPiece(reinterpret_cast<const char*>(kTestPublicKey),
- arraysize(kTestPublicKey))) {}
-
- protected:
- bool ValidateOrigin(ApiKey* api_key, const char* origin) {
- return api_key->ValidateOrigin(origin);
- }
-
- bool ValidateApiName(ApiKey* api_key, const char* api_name) {
- return api_key->ValidateApiName(api_name);
- }
-
- bool ValidateDate(ApiKey* api_key, const base::Time& now) {
- return api_key->ValidateDate(now);
- }
-
- bool ValidateSignature(ApiKey* api_key, const base::StringPiece& public_key) {
- return api_key->ValidateSignature(public_key);
- }
-
- const base::StringPiece& public_key() { return public_key_; };
-
- private:
- base::StringPiece public_key_;
-};
-
-TEST_F(ApiKeyTest, ParseEmptyString) {
- scoped_ptr<ApiKey> empty_key = ApiKey::Parse("");
- EXPECT_FALSE(empty_key);
-}
-
-TEST_F(ApiKeyTest, ParseInvalidStrings) {
- for (size_t i = 0; i < kNumInvalidAPIKeys; ++i) {
- scoped_ptr<ApiKey> empty_key = ApiKey::Parse(kInvalidAPIKeys[i]);
- EXPECT_FALSE(empty_key) << "Invalid API Key should not parse: "
- << kInvalidAPIKeys[i];
- }
-}
-
-TEST_F(ApiKeyTest, ParseValidKeyString) {
- scoped_ptr<ApiKey> key = ApiKey::Parse(kSampleAPIKey);
- ASSERT_TRUE(key);
- EXPECT_EQ(kExpectedAPIName, key->api_name());
- EXPECT_EQ(kExpectedAPIKeySignature, key->signature());
- EXPECT_EQ(kExpectedAPIKeyData, key->data());
- EXPECT_EQ(GURL(kExpectedOrigin), key->origin());
- EXPECT_EQ(kExpectedExpiry, key->expiry_timestamp());
-}
-
-TEST_F(ApiKeyTest, ValidateValidKey) {
- scoped_ptr<ApiKey> key = ApiKey::Parse(kSampleAPIKey);
- ASSERT_TRUE(key);
- EXPECT_TRUE(ValidateOrigin(key.get(), kExpectedOrigin));
- EXPECT_FALSE(ValidateOrigin(key.get(), kInvalidOrigin));
- EXPECT_FALSE(ValidateOrigin(key.get(), kInsecureOrigin));
- EXPECT_TRUE(ValidateApiName(key.get(), kExpectedAPIName));
- EXPECT_FALSE(ValidateApiName(key.get(), kInvalidAPIName));
- EXPECT_TRUE(
- ValidateDate(key.get(), base::Time::FromDoubleT(kValidTimestamp)));
- EXPECT_FALSE(
- ValidateDate(key.get(), base::Time::FromDoubleT(kInvalidTimestamp)));
-}
-
-TEST_F(ApiKeyTest, KeyIsAppropriateForOriginAndAPI) {
- scoped_ptr<ApiKey> key = ApiKey::Parse(kSampleAPIKey);
- ASSERT_TRUE(key);
- EXPECT_TRUE(key->IsAppropriate(kExpectedOrigin, kExpectedAPIName));
- EXPECT_TRUE(key->IsAppropriate(kExpectedOrigin,
- base::ToUpperASCII(kExpectedAPIName)));
- EXPECT_TRUE(key->IsAppropriate(kExpectedOrigin,
- base::ToLowerASCII(kExpectedAPIName)));
- EXPECT_FALSE(key->IsAppropriate(kInvalidOrigin, kExpectedAPIName));
- EXPECT_FALSE(key->IsAppropriate(kInsecureOrigin, kExpectedAPIName));
- EXPECT_FALSE(key->IsAppropriate(kExpectedOrigin, kInvalidAPIName));
-}
-
-TEST_F(ApiKeyTest, ValidateValidSignature) {
- scoped_ptr<ApiKey> key = ApiKey::Parse(kSampleAPIKey);
- ASSERT_TRUE(key);
- EXPECT_TRUE(ValidateSignature(key.get(), public_key()));
-}
-
-TEST_F(ApiKeyTest, ValidateInvalidSignature) {
- scoped_ptr<ApiKey> key = ApiKey::Parse(kInvalidSignatureAPIKey);
- ASSERT_TRUE(key);
- EXPECT_FALSE(ValidateSignature(key.get(), public_key()));
-}
-
-TEST_F(ApiKeyTest, ValidateSignatureOnWrongKey) {
- scoped_ptr<ApiKey> key = ApiKey::Parse(kSampleAPIKey);
- ASSERT_TRUE(key);
- // Signature will be invalid if tested against the real public key
- EXPECT_FALSE(key->IsValid(base::Time::FromDoubleT(kValidTimestamp)));
-}
-
-TEST_F(ApiKeyTest, ValidateWhenNotExpired) {
- scoped_ptr<ApiKey> key = ApiKey::Parse(kSampleAPIKey);
- ASSERT_TRUE(key);
-}
-
-} // namespace content
diff --git a/chromium/content/common/fileapi/webblob_messages.h b/chromium/content/common/fileapi/webblob_messages.h
index a836fd4f5ae..85dbf8c976c 100644
--- a/chromium/content/common/fileapi/webblob_messages.h
+++ b/chromium/content/common/fileapi/webblob_messages.h
@@ -7,29 +7,81 @@
#include <stddef.h>
+#include <set>
+
+#include "base/memory/shared_memory.h"
#include "content/common/content_export.h"
-#include "content/public/common/common_param_traits.h"
#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_utils.h"
+#include "ipc/ipc_param_traits.h"
+#include "ipc/ipc_platform_file.h"
+#include "storage/common/blob_storage/blob_item_bytes_request.h"
+#include "storage/common/blob_storage/blob_item_bytes_response.h"
+#include "storage/common/blob_storage/blob_storage_constants.h"
#include "storage/common/data_element.h"
+#include "url/ipc/url_param_traits.h"
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
#define IPC_MESSAGE_START BlobMsgStart
-// Blob messages sent from the renderer to the browser.
-
-IPC_MESSAGE_CONTROL1(BlobHostMsg_StartBuilding,
- std::string /*uuid */)
-IPC_MESSAGE_CONTROL2(BlobHostMsg_AppendBlobDataItem,
+// Trait definitions for async blob transport messages.
+
+IPC_ENUM_TRAITS_MAX_VALUE(storage::IPCBlobItemRequestStrategy,
+ storage::IPCBlobItemRequestStrategy::LAST)
+IPC_ENUM_TRAITS_MAX_VALUE(storage::IPCBlobCreationCancelCode,
+ storage::IPCBlobCreationCancelCode::LAST)
+
+IPC_STRUCT_TRAITS_BEGIN(storage::BlobItemBytesRequest)
+ IPC_STRUCT_TRAITS_MEMBER(request_number)
+ IPC_STRUCT_TRAITS_MEMBER(transport_strategy)
+ IPC_STRUCT_TRAITS_MEMBER(renderer_item_index)
+ IPC_STRUCT_TRAITS_MEMBER(renderer_item_offset)
+ IPC_STRUCT_TRAITS_MEMBER(size)
+ IPC_STRUCT_TRAITS_MEMBER(handle_index)
+ IPC_STRUCT_TRAITS_MEMBER(handle_offset)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(storage::BlobItemBytesResponse)
+ IPC_STRUCT_TRAITS_MEMBER(request_number)
+ IPC_STRUCT_TRAITS_MEMBER(inline_data)
+ IPC_STRUCT_TRAITS_MEMBER(time_file_modified)
+IPC_STRUCT_TRAITS_END()
+
+// This message is to tell the browser that we will be building a blob.
+IPC_MESSAGE_CONTROL4(BlobStorageMsg_RegisterBlobUUID,
std::string /* uuid */,
- storage::DataElement)
-IPC_SYNC_MESSAGE_CONTROL3_0(BlobHostMsg_SyncAppendSharedMemory,
- std::string /*uuid*/,
- base::SharedMemoryHandle,
- size_t /* buffer size */)
-IPC_MESSAGE_CONTROL2(BlobHostMsg_FinishBuilding,
+ std::string /* content_type */,
+ std::string /* content_disposition */,
+ std::set<std::string> /* referenced_blob_uuids */)
+
+// The DataElements are used to:
+// * describe & transport non-memory resources (blobs, files, etc)
+// * describe the size of memory items
+// * 'shortcut' transport the memory up to the IPC limit so the browser can use
+// it if it's not currently full.
+// See https://bit.ly/BlobStorageRefactor
+IPC_MESSAGE_CONTROL2(BlobStorageMsg_StartBuildingBlob,
std::string /* uuid */,
- std::string /* content_type */)
+ std::vector<storage::DataElement> /* item_descriptions */)
+
+IPC_MESSAGE_CONTROL4(
+ BlobStorageMsg_RequestMemoryItem,
+ std::string /* uuid */,
+ std::vector<storage::BlobItemBytesRequest> /* requests */,
+ std::vector<base::SharedMemoryHandle> /* memory_handles */,
+ std::vector<IPC::PlatformFileForTransit> /* file_handles */)
+
+IPC_MESSAGE_CONTROL2(
+ BlobStorageMsg_MemoryItemResponse,
+ std::string /* uuid */,
+ std::vector<storage::BlobItemBytesResponse> /* responses */)
+
+IPC_MESSAGE_CONTROL2(BlobStorageMsg_CancelBuildingBlob,
+ std::string /* uuid */,
+ storage::IPCBlobCreationCancelCode /* code */)
+
+IPC_MESSAGE_CONTROL1(BlobStorageMsg_DoneBuildingBlob, std::string /* uuid */)
IPC_MESSAGE_CONTROL1(BlobHostMsg_IncrementRefCount,
std::string /* uuid */)
@@ -57,7 +109,7 @@ IPC_MESSAGE_CONTROL2(StreamHostMsg_AppendBlobDataItem,
IPC_SYNC_MESSAGE_CONTROL3_0(StreamHostMsg_SyncAppendSharedMemory,
GURL /* url */,
base::SharedMemoryHandle,
- size_t /* buffer size */)
+ uint32_t /* buffer size */)
// Flushes contents buffered in the stream.
IPC_MESSAGE_CONTROL1(StreamHostMsg_Flush,
diff --git a/chromium/content/common/font_config_ipc_linux.cc b/chromium/content/common/font_config_ipc_linux.cc
index d1dd8ca187f..294bcf83fbf 100644
--- a/chromium/content/common/font_config_ipc_linux.cc
+++ b/chromium/content/common/font_config_ipc_linux.cc
@@ -13,9 +13,12 @@
#include <sys/uio.h>
#include <unistd.h>
+#include <functional>
+
#include "base/files/file_util.h"
#include "base/files/memory_mapped_file.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/pickle.h"
#include "base/posix/unix_domain_socket_linux.h"
#include "base/threading/thread_restrictions.h"
@@ -26,13 +29,12 @@
#include "third_party/skia/include/core/SkStream.h"
#include "third_party/skia/include/core/SkTypeface.h"
+namespace content {
-namespace BASE_HASH_NAMESPACE {
-
-std::size_t hash<SkFontConfigInterface::FontIdentity>::operator()(
+std::size_t SkFontConfigInterfaceFontIdentityHash::operator()(
const SkFontConfigInterface::FontIdentity& sp) const {
- hash<std::string> stringhash;
- hash<int> inthash;
+ std::hash<std::string> stringhash;
+ std::hash<int> inthash;
size_t r = inthash(sp.fID);
r = r * 41 + inthash(sp.fTTCIndex);
r = r * 41 + stringhash(sp.fString.c_str());
@@ -42,10 +44,6 @@ std::size_t hash<SkFontConfigInterface::FontIdentity>::operator()(
return r;
}
-} // namespace BASE_HASH_NAMESPACE
-
-namespace content {
-
// Wikpedia's main country selection page activates 21 fallback fonts,
// doubling this we should be on the generous side as an upper bound,
// but nevertheless not have the mapped typefaces cache grow excessively.
diff --git a/chromium/content/common/font_config_ipc_linux.h b/chromium/content/common/font_config_ipc_linux.h
index 472c2f1aab4..5e969cd2f12 100644
--- a/chromium/content/common/font_config_ipc_linux.h
+++ b/chromium/content/common/font_config_ipc_linux.h
@@ -20,18 +20,14 @@
class SkString;
-namespace BASE_HASH_NAMESPACE {
-template <>
-struct hash<SkFontConfigInterface::FontIdentity> {
- std::size_t operator()(const SkFontConfigInterface::FontIdentity& sp) const;
-};
-}
-
namespace content {
+struct SkFontConfigInterfaceFontIdentityHash {
+ std::size_t operator()(const SkFontConfigInterface::FontIdentity& sp) const;
+};
// FontConfig implementation for Skia that proxies out of process to get out
-// of the sandbox. See http://code.google.com/p/chromium/wiki/LinuxSandboxIPC
+// of the sandbox. See https://chromium.googlesource.com/chromium/src/+/master/docs/linux_sandbox_ipc.md
class FontConfigIPC : public SkFontConfigInterface {
public:
explicit FontConfigIPC(int fd);
@@ -74,7 +70,9 @@ class FontConfigIPC : public SkFontConfigInterface {
// ttc-indices or styles but the same fontconfig interface id. Since the usage
// frequency of ttc indices is very low, and style is not used by clients of
// this API, this seems okay.
- base::HashingMRUCache<FontIdentity, skia::RefPtr<SkTypeface>>
+ base::HashingMRUCache<FontIdentity,
+ skia::RefPtr<SkTypeface>,
+ SkFontConfigInterfaceFontIdentityHash>
mapped_typefaces_;
DISALLOW_COPY_AND_ASSIGN(FontConfigIPC);
diff --git a/chromium/content/common/font_list_win.cc b/chromium/content/common/font_list_win.cc
index 2e07efa0689..62717ec3d24 100644
--- a/chromium/content/common/font_list_win.cc
+++ b/chromium/content/common/font_list_win.cc
@@ -50,7 +50,7 @@ scoped_ptr<base::ListValue> GetFontList_SlowBlocking() {
font_item->Append(new base::StringValue(*iter));
font_list->Append(font_item);
}
- return font_list.Pass();
+ return font_list;
}
} // namespace content
diff --git a/chromium/content/common/frame_message_enums.h b/chromium/content/common/frame_message_enums.h
index b93120607f5..27e98433c75 100644
--- a/chromium/content/common/frame_message_enums.h
+++ b/chromium/content/common/frame_message_enums.h
@@ -10,11 +10,11 @@
struct FrameMsg_Navigate_Type {
public:
enum Value {
- // Reload the page.
+ // Reload the page, validating cache entries.
RELOAD,
- // Reload the page, ignoring any cache entries.
- RELOAD_IGNORING_CACHE,
+ // Reload the page, bypassing any cache entries.
+ RELOAD_BYPASSING_CACHE,
// Reload the page using the original request URL.
RELOAD_ORIGINAL_REQUEST_URL,
diff --git a/chromium/content/common/frame_messages.h b/chromium/content/common/frame_messages.h
index 18892e8df15..7d1f562997a 100644
--- a/chromium/content/common/frame_messages.h
+++ b/chromium/content/common/frame_messages.h
@@ -19,7 +19,6 @@
#include "content/common/content_export.h"
#include "content/common/content_param_traits.h"
#include "content/common/frame_message_enums.h"
-#include "content/common/frame_param.h"
#include "content/common/frame_replication_state.h"
#include "content/common/navigation_gesture.h"
#include "content/common/navigation_params.h"
@@ -35,14 +34,19 @@
#include "content/public/common/page_importance_signals.h"
#include "content/public/common/page_state.h"
#include "content/public/common/resource_response.h"
+#include "content/public/common/stop_find_action.h"
#include "content/public/common/three_d_api_types.h"
#include "content/public/common/transition_element.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_platform_file.h"
#include "third_party/WebKit/public/platform/WebFocusType.h"
+#include "third_party/WebKit/public/web/WebFindOptions.h"
#include "third_party/WebKit/public/web/WebFrameOwnerProperties.h"
#include "third_party/WebKit/public/web/WebTreeScopeType.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/ipc/gfx_param_traits.h"
+#include "ui/gfx/ipc/skia/gfx_skia_param_traits.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -54,8 +58,10 @@
#ifndef CONTENT_COMMON_FRAME_MESSAGES_H_
#define CONTENT_COMMON_FRAME_MESSAGES_H_
-using FrameMsg_GetSerializedHtmlWithLocalLinks_Map =
+using FrameMsg_GetSerializedHtmlWithLocalLinks_UrlMap =
std::map<GURL, base::FilePath>;
+using FrameMsg_GetSerializedHtmlWithLocalLinks_FrameRoutingIdMap =
+ std::map<int, base::FilePath>;
using FrameMsg_SerializeAsMHTML_FrameRoutingIdToContentIdMap =
std::map<int, std::string>;
@@ -84,6 +90,8 @@ IPC_ENUM_TRAITS_MAX_VALUE(blink::WebContextMenuData::InputFieldType,
IPC_ENUM_TRAITS_MAX_VALUE(blink::WebFocusType, blink::WebFocusTypeLast)
IPC_ENUM_TRAITS_MAX_VALUE(blink::WebFrameOwnerProperties::ScrollingMode,
blink::WebFrameOwnerProperties::ScrollingMode::Last)
+IPC_ENUM_TRAITS_MAX_VALUE(content::StopFindAction,
+ content::STOP_FIND_ACTION_LAST)
IPC_ENUM_TRAITS(blink::WebSandboxFlags) // Bitmask.
IPC_ENUM_TRAITS_MAX_VALUE(blink::WebTreeScopeType,
blink::WebTreeScopeType::Last)
@@ -92,6 +100,12 @@ IPC_ENUM_TRAITS_MIN_MAX_VALUE(content::LoFiState,
content::LOFI_UNSPECIFIED,
content::LOFI_ON)
+IPC_STRUCT_TRAITS_BEGIN(blink::WebFindOptions)
+ IPC_STRUCT_TRAITS_MEMBER(forward)
+ IPC_STRUCT_TRAITS_MEMBER(matchCase)
+ IPC_STRUCT_TRAITS_MEMBER(findNext)
+IPC_STRUCT_TRAITS_END()
+
IPC_STRUCT_TRAITS_BEGIN(content::ColorSuggestion)
IPC_STRUCT_TRAITS_MEMBER(color)
IPC_STRUCT_TRAITS_MEMBER(label)
@@ -208,6 +222,9 @@ IPC_STRUCT_BEGIN_WITH_PARENT(FrameHostMsg_DidCommitProvisionalLoad_Params,
// Whether this commit created a new entry.
IPC_STRUCT_MEMBER(bool, did_create_new_entry)
+ // Whether this commit should replace the current entry.
+ IPC_STRUCT_MEMBER(bool, should_replace_current_entry)
+
// Information regarding the security of the connection (empty if the
// connection was not secure).
IPC_STRUCT_MEMBER(std::string, security_info)
@@ -274,6 +291,13 @@ IPC_STRUCT_BEGIN_WITH_PARENT(FrameHostMsg_DidCommitProvisionalLoad_Params,
// True if the document for the load is enforcing strict mixed content
// checking.
IPC_STRUCT_MEMBER(bool, should_enforce_strict_mixed_content_checking)
+
+ // True if the document for the load is a unique origin that should be
+ // considered potentially trustworthy.
+ IPC_STRUCT_MEMBER(bool, has_potentially_trustworthy_unique_origin)
+
+ // True if the navigation originated as an srcdoc attribute.
+ IPC_STRUCT_MEMBER(bool, is_srcdoc)
IPC_STRUCT_END()
IPC_STRUCT_BEGIN(FrameMsg_PostMessage_Params)
@@ -314,10 +338,10 @@ IPC_STRUCT_TRAITS_BEGIN(content::CommonNavigationParams)
IPC_STRUCT_TRAITS_MEMBER(history_url_for_data_url)
IPC_STRUCT_TRAITS_MEMBER(lofi_state)
IPC_STRUCT_TRAITS_MEMBER(navigation_start)
+ IPC_STRUCT_TRAITS_MEMBER(method)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(content::BeginNavigationParams)
- IPC_STRUCT_TRAITS_MEMBER(method)
IPC_STRUCT_TRAITS_MEMBER(headers)
IPC_STRUCT_TRAITS_MEMBER(load_flags)
IPC_STRUCT_TRAITS_MEMBER(has_user_gesture)
@@ -326,7 +350,6 @@ IPC_STRUCT_TRAITS_BEGIN(content::BeginNavigationParams)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(content::StartNavigationParams)
- IPC_STRUCT_TRAITS_MEMBER(is_post)
IPC_STRUCT_TRAITS_MEMBER(extra_headers)
IPC_STRUCT_TRAITS_MEMBER(browser_initiated_post_data)
#if defined(OS_ANDROID)
@@ -363,6 +386,10 @@ IPC_STRUCT_TRAITS_BEGIN(content::FrameReplicationState)
IPC_STRUCT_TRAITS_MEMBER(origin)
IPC_STRUCT_TRAITS_MEMBER(sandbox_flags)
IPC_STRUCT_TRAITS_MEMBER(name)
+ IPC_STRUCT_TRAITS_MEMBER(unique_name)
+ IPC_STRUCT_TRAITS_MEMBER(scope)
+ IPC_STRUCT_TRAITS_MEMBER(should_enforce_strict_mixed_content_checking)
+ IPC_STRUCT_TRAITS_MEMBER(has_potentially_trustworthy_unique_origin)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_BEGIN(FrameMsg_NewFrame_WidgetParams)
@@ -490,6 +517,26 @@ IPC_STRUCT_BEGIN(FrameMsg_SerializeAsMHTML_Params)
IPC_STRUCT_MEMBER(bool, is_last_frame)
IPC_STRUCT_END()
+// This message is used to send hittesting data from the renderer in order
+// to perform hittesting on the browser process.
+IPC_STRUCT_BEGIN(FrameHostMsg_HittestData_Params)
+ // |surface_id| represents the surface used by this remote frame.
+ IPC_STRUCT_MEMBER(cc::SurfaceId, surface_id)
+
+ // If |ignored_for_hittest| then this surface should be ignored during
+ // hittesting.
+ IPC_STRUCT_MEMBER(bool, ignored_for_hittest)
+IPC_STRUCT_END()
+
+IPC_STRUCT_BEGIN(FrameHostMsg_CreateChildFrame_Params)
+ IPC_STRUCT_MEMBER(int32_t, parent_routing_id)
+ IPC_STRUCT_MEMBER(blink::WebTreeScopeType, scope)
+ IPC_STRUCT_MEMBER(std::string, frame_name)
+ IPC_STRUCT_MEMBER(std::string, frame_unique_name)
+ IPC_STRUCT_MEMBER(blink::WebSandboxFlags, sandbox_flags)
+ IPC_STRUCT_MEMBER(blink::WebFrameOwnerProperties, frame_owner_properties)
+IPC_STRUCT_END()
+
#if defined(OS_MACOSX) || defined(OS_ANDROID)
// This message is used for supporting popup menus on Mac OS X and Android using
// native controls. See the FrameHostMsg_ShowPopup message.
@@ -530,15 +577,6 @@ IPC_STRUCT_TRAITS_END()
// -----------------------------------------------------------------------------
// Messages sent from the browser to the renderer.
-// Notifies the embedding frame that a new CompositorFrame is ready to be
-// presented. When the frame finishes presenting, a matching
-// FrameHostMsg_CompositorFrameSwappedACK should be sent back to the
-// RenderViewHost that was produced the CompositorFrame.
-//
-// This is used in the ubercomp compositing path.
-IPC_MESSAGE_ROUTED1(FrameMsg_CompositorFrameSwapped,
- FrameMsg_CompositorFrameSwapped_Params /* params */)
-
IPC_MESSAGE_ROUTED4(FrameMsg_SetChildFrameSurface,
cc::SurfaceId /* surface_id */,
gfx::Size /* frame_size */,
@@ -554,6 +592,10 @@ IPC_MESSAGE_ROUTED0(FrameMsg_ChildFrameProcessGone)
IPC_MESSAGE_ROUTED1(FrameMsg_ContextMenuClosed,
content::CustomContextMenuContext /* custom_context */)
+// Reloads all the Lo-Fi images in the RenderFrame. Ignores the cache and
+// reloads from the network.
+IPC_MESSAGE_ROUTED0(FrameMsg_ReloadLoFiImages)
+
// Executes custom context menu action that was provided from Blink.
IPC_MESSAGE_ROUTED2(FrameMsg_CustomContextMenuAction,
content::CustomContextMenuContext /* custom_context */,
@@ -685,10 +727,10 @@ IPC_MESSAGE_ROUTED1(FrameMsg_HideTransitionElements,
IPC_MESSAGE_ROUTED1(FrameMsg_ShowTransitionElements,
std::string /* css_selector */)
-// Tells the renderer to reload the frame, optionally ignoring the cache while
+// Tells the renderer to reload the frame, optionally bypassing the cache while
// doing so.
IPC_MESSAGE_ROUTED1(FrameMsg_Reload,
- bool /* ignore_cache */)
+ bool /* bypass_cache */)
// Notifies the color chooser client that the user selected a color.
IPC_MESSAGE_ROUTED2(FrameMsg_DidChooseColorResponse, unsigned, SkColor)
@@ -703,7 +745,7 @@ IPC_MESSAGE_ROUTED0(FrameMsg_DeleteProxy)
// Request the text surrounding the selection with a |max_length|. The response
// will be sent via FrameHostMsg_TextSurroundingSelectionResponse.
IPC_MESSAGE_ROUTED1(FrameMsg_TextSurroundingSelectionRequest,
- size_t /* max_length */)
+ uint32_t /* max_length */)
// Tells the renderer to insert a link to the specified stylesheet. This is
// needed to support navigation transitions.
@@ -721,7 +763,9 @@ IPC_MESSAGE_ROUTED1(FrameMsg_DidUpdateSandboxFlags, blink::WebSandboxFlags)
// Update a proxy's window.name property. Used when the frame's name is
// changed in another process.
-IPC_MESSAGE_ROUTED1(FrameMsg_DidUpdateName, std::string /* name */)
+IPC_MESSAGE_ROUTED2(FrameMsg_DidUpdateName,
+ std::string /* name */,
+ std::string /* unique_name */)
// Update a proxy's replicated enforcement of strict mixed content
// checking. Used when the frame's mixed content setting is changed in
@@ -731,7 +775,9 @@ IPC_MESSAGE_ROUTED1(FrameMsg_EnforceStrictMixedContentChecking,
// Update a proxy's replicated origin. Used when the frame is navigated to a
// new origin.
-IPC_MESSAGE_ROUTED1(FrameMsg_DidUpdateOrigin, url::Origin /* origin */)
+IPC_MESSAGE_ROUTED2(FrameMsg_DidUpdateOrigin,
+ url::Origin /* origin */,
+ bool /* is potentially trustworthy unique origin */)
// Notifies this frame or proxy that it is now focused. This is used to
// support cross-process focused frame changes.
@@ -746,6 +792,17 @@ IPC_MESSAGE_ROUTED1(FrameMsg_SetTextTrackSettings,
IPC_MESSAGE_ROUTED1(FrameMsg_PostMessageEvent, FrameMsg_PostMessage_Params)
#if defined(OS_ANDROID)
+// Sent when the browser wants the bounding boxes of the current find matches.
+//
+// If match rects are already cached on the browser side, |current_version|
+// should be the version number from the FrameHostMsg_FindMatchRects_Reply
+// they came in, so the renderer can tell if it needs to send updated rects.
+// Otherwise just pass -1 to always receive the list of rects.
+//
+// There must be an active search string (it is probably most useful to call
+// this immediately after a FrameHostMsg_Find_Reply message arrives with
+// final_update set to true).
+IPC_MESSAGE_ROUTED1(FrameMsg_FindMatchRects, int /* current_version */)
// External popup menus.
IPC_MESSAGE_ROUTED2(FrameMsg_SelectPopupMenuItems,
@@ -785,8 +842,9 @@ IPC_MESSAGE_ROUTED0(FrameMsg_GetSavableResourceLinks)
// Get html data by serializing the target frame and replacing all resource
// links with a path to the local copy passed in the message payload.
-IPC_MESSAGE_ROUTED1(FrameMsg_GetSerializedHtmlWithLocalLinks,
- FrameMsg_GetSerializedHtmlWithLocalLinks_Map)
+IPC_MESSAGE_ROUTED2(FrameMsg_GetSerializedHtmlWithLocalLinks,
+ FrameMsg_GetSerializedHtmlWithLocalLinks_UrlMap,
+ FrameMsg_GetSerializedHtmlWithLocalLinks_FrameRoutingIdMap)
// Serialize target frame and its resources into MHTML and write it into the
// provided destination file handle. Note that when serializing multiple
@@ -806,12 +864,30 @@ IPC_MESSAGE_ROUTED2(FrameMsg_AdvanceFocus,
blink::WebFocusType /* type */,
int32_t /* source_routing_id */)
+// Sent when the user wants to search for a word on the page (find-in-page).
+IPC_MESSAGE_ROUTED3(FrameMsg_Find,
+ int /* request_id */,
+ base::string16 /* search_text */,
+ blink::WebFindOptions)
+
+// This message notifies the renderer that the user has closed the find-in-page
+// window (and what action to take regarding the selection).
+IPC_MESSAGE_ROUTED1(FrameMsg_StopFinding, content::StopFindAction /* action */)
+
#if defined(ENABLE_PLUGINS)
// Notifies the renderer of updates to the Plugin Power Saver origin whitelist.
IPC_MESSAGE_ROUTED1(FrameMsg_UpdatePluginContentOriginWhitelist,
std::set<url::Origin> /* origin_whitelist */)
#endif // defined(ENABLE_PLUGINS)
+// Used to instruct the RenderFrame to go into "view source" mode. This should
+// only be sent to the main frame.
+IPC_MESSAGE_ROUTED0(FrameMsg_EnableViewSourceMode)
+
+// Tells the frame to suppress any further modal dialogs. This ensures that no
+// ScopedPageLoadDeferrer is on the stack for SwapOut.
+IPC_MESSAGE_ROUTED0(FrameMsg_SuppressFurtherDialogs)
+
// -----------------------------------------------------------------------------
// Messages sent from the renderer to the browser.
@@ -827,14 +903,9 @@ IPC_MESSAGE_ROUTED4(FrameHostMsg_AddMessageToConsole,
//
// Each of these messages will have a corresponding FrameHostMsg_Detach message
// sent when the frame is detached from the DOM.
-IPC_SYNC_MESSAGE_CONTROL5_1(
- FrameHostMsg_CreateChildFrame,
- int32_t /* parent_routing_id */,
- blink::WebTreeScopeType /* scope */,
- std::string /* frame_name */,
- blink::WebSandboxFlags /* sandbox flags */,
- blink::WebFrameOwnerProperties /* frame_owner_properties */,
- int32_t /* new_routing_id */)
+IPC_SYNC_MESSAGE_CONTROL1_1(FrameHostMsg_CreateChildFrame,
+ FrameHostMsg_CreateChildFrame_Params,
+ int32_t /* new_routing_id */)
// Sent by the renderer to the parent RenderFrameHost when a child frame is
// detached from the DOM.
@@ -873,9 +944,6 @@ IPC_MESSAGE_ROUTED4(FrameHostMsg_DidFailLoadWithError,
base::string16 /* error_description */,
bool /* was_ignored_by_handler */)
-// Sent when the renderer decides to ignore a navigation.
-IPC_MESSAGE_ROUTED0(FrameHostMsg_DidDropNavigation)
-
// Sent when the renderer starts loading the page. |to_different_document| will
// be true unless the load is a fragment navigation, or triggered by
// history.pushState/replaceState.
@@ -889,7 +957,9 @@ IPC_MESSAGE_ROUTED0(FrameHostMsg_DidStopLoading)
IPC_MESSAGE_ROUTED1(FrameHostMsg_UpdateState, content::PageState /* state */)
// Sent when the frame changes its window.name.
-IPC_MESSAGE_ROUTED1(FrameHostMsg_DidChangeName, std::string /* name */)
+IPC_MESSAGE_ROUTED2(FrameHostMsg_DidChangeName,
+ std::string /* name */,
+ std::string /* unique_name */)
// Sent when the frame starts enforcing strict mixed content
// checking. Sending this information in DidCommitProvisionalLoad isn't
@@ -898,6 +968,13 @@ IPC_MESSAGE_ROUTED1(FrameHostMsg_DidChangeName, std::string /* name */)
// checking to be enforced.
IPC_MESSAGE_ROUTED0(FrameHostMsg_EnforceStrictMixedContentChecking)
+// Sent when the frame is set to a unique origin. TODO(estark): this IPC
+// only exists to support dynamic sandboxing via a CSP delivered in a
+// <meta> tag. This is not supposed to be allowed per the CSP spec and
+// should be ripped out. https://crbug.com/594645
+IPC_MESSAGE_ROUTED1(FrameHostMsg_UpdateToUniqueOrigin,
+ bool /* is potentially trustworthy unique origin */)
+
// Sent when the renderer changed the progress of a load.
IPC_MESSAGE_ROUTED1(FrameHostMsg_DidChangeLoadProgress,
double /* load_progress */)
@@ -994,14 +1071,6 @@ IPC_SYNC_MESSAGE_CONTROL3_1(FrameHostMsg_Are3DAPIsBlocked,
content::ThreeDAPIType /* requester */,
bool /* blocked */)
-// Sent by the renderer process to indicate that a context was lost by
-// client 3D content (Pepper 3D, WebGL) running on the page at the
-// given URL.
-IPC_MESSAGE_CONTROL3(FrameHostMsg_DidLose3DContext,
- GURL /* top_origin_url */,
- content::ThreeDAPIType /* context_type */,
- int /* arb_robustness_status_code */)
-
#if defined(ENABLE_PLUGINS)
// Notification sent from a renderer to the browser that a Pepper plugin
// instance is created in the DOM.
@@ -1054,18 +1123,6 @@ IPC_SYNC_MESSAGE_CONTROL4_3(FrameHostMsg_GetPluginInfo,
IPC_MESSAGE_ROUTED1(FrameHostMsg_PluginContentOriginAllowed,
url::Origin /* content_origin */)
-// A renderer sends this to the browser process when it wants to
-// create a plugin. The browser will create the plugin process if
-// necessary, and will return a handle to the channel on success.
-// On error an empty string is returned.
-IPC_SYNC_MESSAGE_CONTROL4_2(FrameHostMsg_OpenChannelToPlugin,
- int /* render_frame_id */,
- GURL /* url */,
- GURL /* page_url */,
- std::string /* mime_type */,
- IPC::ChannelHandle /* channel_handle */,
- content::WebPluginInfo /* info */)
-
// A renderer sends this to the browser process when it wants to create a ppapi
// plugin. The browser will create the plugin process if necessary, and will
// return a handle to the channel on success.
@@ -1138,12 +1195,6 @@ IPC_MESSAGE_CONTROL3(FrameHostMsg_PluginInstanceThrottleStateChange,
bool /* is_throttled */)
#endif // defined(ENABLE_PLUGINS)
-// Acknowledge that we presented an ubercomp frame.
-//
-// See FrameMsg_CompositorFrameSwapped
-IPC_MESSAGE_ROUTED1(FrameHostMsg_CompositorFrameSwappedACK,
- FrameHostMsg_CompositorFrameSwappedACK_Params /* params */)
-
// Satisfies a Surface destruction dependency associated with |sequence|.
IPC_MESSAGE_ROUTED1(FrameHostMsg_SatisfySequence,
cc::SurfaceSequence /* sequence */)
@@ -1165,9 +1216,6 @@ IPC_MESSAGE_ROUTED3(FrameHostMsg_BeforeUnload_ACK,
// Indicates that the current frame has swapped out, after a SwapOut message.
IPC_MESSAGE_ROUTED0(FrameHostMsg_SwapOut_ACK)
-IPC_MESSAGE_ROUTED1(FrameHostMsg_ReclaimCompositorResources,
- FrameHostMsg_ReclaimCompositorResources_Params /* params */)
-
// Forwards an input event to a child.
// TODO(nick): Temporary bridge, revisit once the browser process can route
// input directly to subframes. http://crbug.com/339659
@@ -1214,9 +1262,8 @@ IPC_SYNC_MESSAGE_ROUTED4_2(FrameHostMsg_RunJavaScriptMessage,
// Displays a dialog to confirm that the user wants to navigate away from the
// page. Replies true if yes, and false otherwise. The reply string is ignored,
// but is included so that we can use OnJavaScriptMessageBoxClosed.
-IPC_SYNC_MESSAGE_ROUTED3_2(FrameHostMsg_RunBeforeUnloadConfirm,
+IPC_SYNC_MESSAGE_ROUTED2_2(FrameHostMsg_RunBeforeUnloadConfirm,
GURL, /* in - originating frame URL */
- base::string16 /* in - alert message */,
bool /* in - is a reload */,
bool /* out - success */,
base::string16 /* out - This is ignored.*/)
@@ -1235,16 +1282,6 @@ IPC_MESSAGE_ROUTED2(FrameHostMsg_SetSelectedColorInColorChooser,
int /* id */,
SkColor /* color */)
-// Notifies the browser that media has started/stopped playing.
-IPC_MESSAGE_ROUTED4(FrameHostMsg_MediaPlayingNotification,
- int64_t /* player_cookie, distinguishes instances */,
- bool /* has_video */,
- bool /* has_audio */,
- bool /* is_remote */)
-
-IPC_MESSAGE_ROUTED1(FrameHostMsg_MediaPausedNotification,
- int64_t /* player_cookie, distinguishes instances */)
-
// Notify browser the theme color has been changed.
IPC_MESSAGE_ROUTED1(FrameHostMsg_DidChangeThemeColor,
SkColor /* theme_color */)
@@ -1253,8 +1290,8 @@ IPC_MESSAGE_ROUTED1(FrameHostMsg_DidChangeThemeColor,
// |endOffset| are the offsets of the selection in the returned |content|.
IPC_MESSAGE_ROUTED3(FrameHostMsg_TextSurroundingSelectionResponse,
base::string16, /* content */
- size_t, /* startOffset */
- size_t /* endOffset */)
+ uint32_t, /* startOffset */
+ uint32_t/* endOffset */)
// Register a new handler for URL requests with the given scheme.
IPC_MESSAGE_ROUTED4(FrameHostMsg_RegisterProtocolHandler,
@@ -1361,6 +1398,22 @@ IPC_MESSAGE_ROUTED2(FrameHostMsg_AdvanceFocus,
blink::WebFocusType /* type */,
int32_t /* source_routing_id */)
+// Result of string search in the document.
+// Response to FrameMsg_Find with the results of the requested find-in-page
+// search, the number of matches found and the selection rect (in screen
+// coordinates) for the string found. If |final_update| is false, it signals
+// that this is not the last Find_Reply message - more will be sent as the
+// scoping effort continues.
+IPC_MESSAGE_ROUTED5(FrameHostMsg_Find_Reply,
+ int /* request_id */,
+ int /* number of matches */,
+ gfx::Rect /* selection_rect */,
+ int /* active_match_ordinal */,
+ bool /* final_update */)
+
+// Sends hittesting data needed to perform hittesting on the browser process.
+IPC_MESSAGE_ROUTED1(FrameHostMsg_HittestData, FrameHostMsg_HittestData_Params)
+
#if defined(OS_MACOSX) || defined(OS_ANDROID)
// Message to show/hide a popup menu using native controls.
@@ -1370,6 +1423,28 @@ IPC_MESSAGE_ROUTED0(FrameHostMsg_HidePopup)
#endif
+#if defined(OS_ANDROID)
+// Response to FrameMsg_FindMatchRects.
+//
+// |version| will contain the current version number of the renderer's find
+// match list (incremented whenever they change), which should be passed in the
+// next call to FrameMsg_FindMatchRects.
+//
+// |rects| will either contain a list of the enclosing rects of all matches
+// found by the most recent Find operation, or will be empty if |version| is not
+// greater than the |current_version| passed to FrameMsg_FindMatchRects (hence
+// your locally cached rects should still be valid). The rect coords will be
+// custom normalized fractions of the document size. The rects will be sorted by
+// frame traversal order starting in the main frame, then by dom order.
+//
+// |active_rect| will contain the bounding box of the active find-in-page match
+// marker, in similarly normalized coords (or an empty rect if there isn't one).
+IPC_MESSAGE_ROUTED3(FrameHostMsg_FindMatchRects_Reply,
+ int /* version */,
+ std::vector<gfx::RectF> /* rects */,
+ gfx::RectF /* active_rect */)
+#endif
+
// Adding a new message? Stick to the sort order above: first platform
// independent FrameMsg, then ifdefs for platform specific FrameMsg, then
// platform independent FrameHostMsg, then ifdefs for platform specific
diff --git a/chromium/content/common/frame_param.cc b/chromium/content/common/frame_param.cc
deleted file mode 100644
index dbeaaa72023..00000000000
--- a/chromium/content/common/frame_param.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/frame_param.h"
-#include "content/common/cc_messages.h"
-
-#define IPC_MESSAGE_IMPL
-#include "content/common/frame_param_macros.h"
-
-// Generate constructors.
-#include "ipc/struct_constructor_macros.h"
-#undef CONTENT_COMMON_FRAME_PARAM_MACROS_H_
-#include "content/common/frame_param_macros.h"
-
-// Generate destructors.
-#include "ipc/struct_destructor_macros.h"
-#undef CONTENT_COMMON_FRAME_PARAM_MACROS_H_
-#include "content/common/frame_param_macros.h"
-
-// Generate param traits write methods.
-#include "ipc/param_traits_write_macros.h"
-namespace IPC {
-#undef CONTENT_COMMON_FRAME_PARAM_MACROS_H_
-#include "content/common/frame_param_macros.h"
-} // namespace IPC
-
-// Generate param traits read methods.
-#include "ipc/param_traits_read_macros.h"
-namespace IPC {
-#undef CONTENT_COMMON_FRAME_PARAM_MACROS_H_
-#include "content/common/frame_param_macros.h"
-} // namespace IPC
-
-// Generate param traits log methods.
-#include "ipc/param_traits_log_macros.h"
-namespace IPC {
-#undef CONTENT_COMMON_FRAME_PARAM_MACROS_H_
-#include "content/common/frame_param_macros.h"
-} // namespace IPC
diff --git a/chromium/content/common/frame_param.h b/chromium/content/common/frame_param.h
deleted file mode 100644
index 29c4010d2aa..00000000000
--- a/chromium/content/common/frame_param.h
+++ /dev/null
@@ -1,10 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_FRAME_PARAM_H_
-#define CONTENT_COMMON_FRAME_PARAM_H_
-
-#include "content/common/frame_param_macros.h"
-
-#endif // CONTENT_COMMON_FRAME_PARAM_H_
diff --git a/chromium/content/common/frame_param_macros.h b/chromium/content/common/frame_param_macros.h
deleted file mode 100644
index fd2256d7eec..00000000000
--- a/chromium/content/common/frame_param_macros.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Allows for sharing of IPC param structures between BrowserPlugin code and
-// RenderFrame code. All these should be folded directly back into the IPCs in
-// frame_messages.h once BrowserPlugin has been fully converted over to use
-// the RenderFrame infrastructure.
-//
-// TODO(ajwong): Remove once BrowserPlugin has been converted to use
-// RenderFrames. http://crbug.com/330264
-
-#ifndef CONTENT_COMMON_FRAME_PARAM_MACROS_H_
-#define CONTENT_COMMON_FRAME_PARAM_MACROS_H_
-
-#include <stdint.h>
-
-#include "cc/output/compositor_frame.h"
-#include "cc/output/compositor_frame_ack.h"
-#include "content/public/common/common_param_traits.h"
-#include "ipc/ipc_message_macros.h"
-#include "ui/gfx/ipc/gfx_param_traits.h"
-
-#undef IPC_MESSAGE_EXPORT
-#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
-
-IPC_STRUCT_BEGIN(FrameMsg_BuffersSwapped_Params)
- IPC_STRUCT_MEMBER(int, gpu_host_id)
- IPC_STRUCT_MEMBER(int, gpu_route_id)
- IPC_STRUCT_MEMBER(gpu::Mailbox, mailbox)
- IPC_STRUCT_MEMBER(gfx::Size, size)
-IPC_STRUCT_END()
-
-IPC_STRUCT_BEGIN(FrameMsg_CompositorFrameSwapped_Params)
- // Specifies which RenderWidget produced the CompositorFrame.
- IPC_STRUCT_MEMBER(int, producing_host_id)
- IPC_STRUCT_MEMBER(int, producing_route_id)
-
- IPC_STRUCT_MEMBER(cc::CompositorFrame, frame)
- IPC_STRUCT_MEMBER(uint32_t, output_surface_id)
- IPC_STRUCT_MEMBER(base::SharedMemoryHandle, shared_memory_handle)
-IPC_STRUCT_END()
-
-IPC_STRUCT_BEGIN(FrameHostMsg_CompositorFrameSwappedACK_Params)
- // Specifies which RenderWidget produced the CompositorFrame.
- IPC_STRUCT_MEMBER(int, producing_host_id)
- IPC_STRUCT_MEMBER(int, producing_route_id)
-
- IPC_STRUCT_MEMBER(uint32_t, output_surface_id)
- IPC_STRUCT_MEMBER(cc::CompositorFrameAck, ack)
-IPC_STRUCT_END()
-
-IPC_STRUCT_BEGIN(FrameHostMsg_ReclaimCompositorResources_Params)
- IPC_STRUCT_MEMBER(int, route_id)
- IPC_STRUCT_MEMBER(uint32_t, output_surface_id)
- IPC_STRUCT_MEMBER(int, renderer_host_id)
- IPC_STRUCT_MEMBER(cc::CompositorFrameAck, ack)
-IPC_STRUCT_END()
-
-#endif // CONTENT_COMMON_FRAME_PARAM_MACROS_H_
diff --git a/chromium/content/common/frame_replication_state.cc b/chromium/content/common/frame_replication_state.cc
index 0046466d7f1..00e835f5b92 100644
--- a/chromium/content/common/frame_replication_state.cc
+++ b/chromium/content/common/frame_replication_state.cc
@@ -11,19 +11,28 @@ namespace content {
FrameReplicationState::FrameReplicationState()
: sandbox_flags(blink::WebSandboxFlags::None),
scope(blink::WebTreeScopeType::Document),
- should_enforce_strict_mixed_content_checking(false) {}
+ should_enforce_strict_mixed_content_checking(false),
+ has_potentially_trustworthy_unique_origin(false) {}
FrameReplicationState::FrameReplicationState(
blink::WebTreeScopeType scope,
const std::string& name,
+ const std::string& unique_name,
blink::WebSandboxFlags sandbox_flags,
- bool should_enforce_strict_mixed_content_checking)
+ bool should_enforce_strict_mixed_content_checking,
+ bool has_potentially_trustworthy_unique_origin)
: origin(),
sandbox_flags(sandbox_flags),
name(name),
+ unique_name(unique_name),
scope(scope),
should_enforce_strict_mixed_content_checking(
- should_enforce_strict_mixed_content_checking) {}
+ should_enforce_strict_mixed_content_checking),
+ has_potentially_trustworthy_unique_origin(
+ has_potentially_trustworthy_unique_origin) {}
+
+FrameReplicationState::FrameReplicationState(
+ const FrameReplicationState& other) = default;
FrameReplicationState::~FrameReplicationState() {
}
diff --git a/chromium/content/common/frame_replication_state.h b/chromium/content/common/frame_replication_state.h
index 88978490e3f..f6373491a19 100644
--- a/chromium/content/common/frame_replication_state.h
+++ b/chromium/content/common/frame_replication_state.h
@@ -21,8 +21,11 @@ struct CONTENT_EXPORT FrameReplicationState {
FrameReplicationState();
FrameReplicationState(blink::WebTreeScopeType scope,
const std::string& name,
+ const std::string& unique_name,
blink::WebSandboxFlags sandbox_flags,
- bool should_enforce_strict_mixed_content_checking);
+ bool should_enforce_strict_mixed_content_checking,
+ bool has_potentially_trustworthy_unique_origin);
+ FrameReplicationState(const FrameReplicationState& other);
~FrameReplicationState();
// Current origin of the frame. This field is updated whenever a frame
@@ -37,20 +40,21 @@ struct CONTENT_EXPORT FrameReplicationState {
// compromized renderer.
url::Origin origin;
- // Current sandbox flags of the frame. |sandbox_flags| are initialized for
- // new child frames using the value of the <iframe> element's "sandbox"
- // attribute. They are updated dynamically whenever a parent frame updates an
- // <iframe>'s sandbox attribute via JavaScript.
+ // Sandbox flags currently in effect for the frame. |sandbox_flags| are
+ // initialized for new child frames using the value of the <iframe> element's
+ // "sandbox" attribute, combined with any sandbox flags in effect for the
+ // parent frame.
//
- // Updates to |sandbox_flags| are sent to proxies, but only after a
- // subsequent navigation of the (sandboxed) frame, since the flags only take
- // effect on navigation (see also FrameTreeNode::effective_sandbox_flags_).
- // The proxies need updated flags so that they can be inherited properly if a
- // proxy ever becomes a parent of a local frame.
+ // When a parent frame updates an <iframe>'s sandbox attribute via
+ // JavaScript, |sandbox_flags| are updated only after the child frame commits
+ // a navigation that makes the updated flags take effect. This is also the
+ // point at which updates are sent to proxies (see
+ // CommitPendingSandboxFlags()). The proxies need updated flags so that they
+ // can be inherited properly if a proxy ever becomes a parent of a local
+ // frame.
blink::WebSandboxFlags sandbox_flags;
- // The assigned name of the frame. This name can be empty, unlike the unique
- // name generated internally in the DOM tree.
+ // The assigned name of the frame (see WebFrame::assignedName()).
//
// |name| is set when a new child frame is created using the value of the
// <iframe> element's "name" attribute (see
@@ -62,6 +66,19 @@ struct CONTENT_EXPORT FrameReplicationState {
// frame using its updated name (e.g., using window.open(url, frame_name)).
std::string name;
+ // Unique name of the frame (see WebFrame::uniqueName()).
+ //
+ // |unique_name| is used in heuristics that try to identify the same frame
+ // across different, unrelated navigations (i.e. to refer to the frame
+ // when going back/forward in session history OR when refering to the frame
+ // in layout tests results).
+ //
+ // |unique_name| needs to be replicated to ensure that unique name for a given
+ // frame is the same across all renderers - without replication a renderer
+ // might arrive at a different value when recalculating the unique name from
+ // scratch.
+ std::string unique_name;
+
// Whether the frame is in a document tree or a shadow tree, per the Shadow
// DOM spec: https://w3c.github.io/webcomponents/spec/shadow/
// Note: This should really be const, as it can never change once a frame is
@@ -75,6 +92,10 @@ struct CONTENT_EXPORT FrameReplicationState {
// frames live in different processes.
bool should_enforce_strict_mixed_content_checking;
+ // True if a frame's origin is unique and should be considered potentially
+ // trustworthy.
+ bool has_potentially_trustworthy_unique_origin;
+
// TODO(alexmos): Eventually, this structure can also hold other state that
// needs to be replicated, such as frame sizing info.
};
diff --git a/chromium/content/common/gamepad_param_traits.cc b/chromium/content/common/gamepad_param_traits.cc
index 095154d8e4e..5a343fa1e06 100644
--- a/chromium/content/common/gamepad_param_traits.cc
+++ b/chromium/content/common/gamepad_param_traits.cc
@@ -33,13 +33,11 @@ void LogWebUCharString(
namespace IPC {
-void ParamTraits<WebGamepad>::Write(
- Message* m,
- const WebGamepad& p) {
+void ParamTraits<WebGamepad>::Write(base::Pickle* m, const WebGamepad& p) {
m->WriteData(reinterpret_cast<const char*>(&p), sizeof(WebGamepad));
}
-bool ParamTraits<WebGamepad>::Read(const Message* m,
+bool ParamTraits<WebGamepad>::Read(const base::Pickle* m,
base::PickleIterator* iter,
WebGamepad* p) {
int length;
diff --git a/chromium/content/common/gamepad_param_traits.h b/chromium/content/common/gamepad_param_traits.h
index 212c3063150..99576803b62 100644
--- a/chromium/content/common/gamepad_param_traits.h
+++ b/chromium/content/common/gamepad_param_traits.h
@@ -10,6 +10,7 @@
#include "ipc/ipc_param_traits.h"
namespace base {
+class Pickle;
class PickleIterator;
}
@@ -22,8 +23,8 @@ class Message;
template <>
struct ParamTraits<blink::WebGamepad> {
typedef blink::WebGamepad param_type;
- static void Write(Message* m, const blink::WebGamepad& p);
- static bool Read(const Message* m,
+ static void Write(base::Pickle* m, const blink::WebGamepad& p);
+ static bool Read(const base::Pickle* m,
base::PickleIterator* iter,
blink::WebGamepad* p);
static void Log(const blink::WebGamepad& p, std::string* l);
diff --git a/chromium/content/common/geolocation_service.mojom b/chromium/content/common/geolocation_service.mojom
deleted file mode 100644
index a9c4e488646..00000000000
--- a/chromium/content/common/geolocation_service.mojom
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module content;
-
-import "content/public/common/mojo_geoposition.mojom";
-
-// The Geolocation service provides updates on the device's location. By
-// default, it provides updates with low accuracy, but |SetHighAccuracy()| may
-// be called to change this.
-interface GeolocationService {
- SetHighAccuracy(bool high_accuracy);
-
- // Position is reported once it changes or immediately (to report the initial
- // position) if this is the first call to QueryNextPosition on this instance.
- // Position updates may be throttled by the service. Overlapping calls to
- // this method are prohibited and will be treated as a connection error.
- QueryNextPosition() => (MojoGeoposition geoposition);
-};
diff --git a/chromium/content/common/gpu/DEPS b/chromium/content/common/gpu/DEPS
index 2c01d5f2d7b..56ee2c3e9b8 100644
--- a/chromium/content/common/gpu/DEPS
+++ b/chromium/content/common/gpu/DEPS
@@ -2,9 +2,6 @@ include_rules = [
"+gpu/command_buffer",
"+libEGL",
"+libGLESv2",
- "+media/video/jpeg_decode_accelerator.h",
- "+media/video/video_decode_accelerator.h",
- "+media/video/video_encode_accelerator.h",
"+skia",
"+third_party/mesa",
]
diff --git a/chromium/content/common/gpu/ca_layer_partial_damage_tree_mac.h b/chromium/content/common/gpu/ca_layer_partial_damage_tree_mac.h
deleted file mode 100644
index f52000d6ddf..00000000000
--- a/chromium/content/common/gpu/ca_layer_partial_damage_tree_mac.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_CA_LAYER_PARTIAL_DAMAGE_TREE_MAC_H_
-#define CONTENT_COMMON_GPU_CA_LAYER_PARTIAL_DAMAGE_TREE_MAC_H_
-
-#include <IOSurface/IOSurface.h>
-#include <QuartzCore/QuartzCore.h>
-#include <deque>
-
-#include "base/mac/scoped_cftyperef.h"
-#include "base/memory/scoped_ptr.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/rect_f.h"
-
-namespace content {
-
-class CALayerPartialDamageTree {
- public:
- CALayerPartialDamageTree(bool allow_partial_swap,
- base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
- const gfx::Rect& pixel_frame_rect);
- ~CALayerPartialDamageTree();
-
- base::ScopedCFTypeRef<IOSurfaceRef> RootLayerIOSurface();
- void CommitCALayers(CALayer* superlayer,
- scoped_ptr<CALayerPartialDamageTree> old_tree,
- float scale_factor,
- const gfx::Rect& pixel_damage_rect);
-
- private:
- class OverlayPlane;
-
- // This will populate |partial_damage_planes_|, potentially re-using the
- // CALayers and |partial_damage_planes_| from |old_tree|. After this function
- // completes, the back() of |partial_damage_planes_| is the plane that will
- // be updated this frame (and if it is empty, then the root plane will be
- // updated).
- void UpdatePartialDamagePlanes(CALayerPartialDamageTree* old_tree,
- const gfx::Rect& pixel_damage_rect);
-
- void UpdateRootAndPartialDamagePlanes(
- scoped_ptr<CALayerPartialDamageTree> old_tree,
- const gfx::Rect& pixel_damage_rect);
-
- void UpdateCALayers(CALayer* superlayer, float scale_factor);
-
- const bool allow_partial_swap_;
- scoped_ptr<OverlayPlane> root_plane_;
- std::deque<scoped_ptr<OverlayPlane>> partial_damage_planes_;
-};
-
-} // content
-
-#endif // CONTENT_COMMON_GPU_CA_LAYER_PARTIAL_DAMAGE_TREE_MAC_H_
diff --git a/chromium/content/common/gpu/ca_layer_partial_damage_tree_mac.mm b/chromium/content/common/gpu/ca_layer_partial_damage_tree_mac.mm
deleted file mode 100644
index f42738947a0..00000000000
--- a/chromium/content/common/gpu/ca_layer_partial_damage_tree_mac.mm
+++ /dev/null
@@ -1,287 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/ca_layer_partial_damage_tree_mac.h"
-
-#include "base/command_line.h"
-#include "base/mac/scoped_nsobject.h"
-#include "base/mac/sdk_forward_declarations.h"
-#include "base/trace_event/trace_event.h"
-#include "ui/base/ui_base_switches.h"
-#include "ui/gfx/transform.h"
-
-@interface CALayer(Private)
--(void)setContentsChanged;
-@end
-
-namespace content {
-namespace {
-
-// When selecting a CALayer to re-use for partial damage, this is the maximum
-// fraction of the merged layer's pixels that may be not-updated by the swap
-// before we consider the CALayer to not be a good enough match, and create a
-// new one.
-const float kMaximumPartialDamageWasteFraction = 1.2f;
-
-// The maximum number of partial damage layers that may be created before we
-// give up and remove them all (doing full damage in the process).
-const size_t kMaximumPartialDamageLayers = 8;
-
-} // namespace
-
-class CALayerPartialDamageTree::OverlayPlane {
- public:
- OverlayPlane(base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
- const gfx::Rect& pixel_frame_rect,
- const gfx::RectF& contents_rect)
- : io_surface(io_surface),
- contents_rect(contents_rect),
- pixel_frame_rect(pixel_frame_rect),
- layer_needs_update(true) {}
-
- ~OverlayPlane() {
- [ca_layer setContents:nil];
- [ca_layer removeFromSuperlayer];
- ca_layer.reset();
- }
-
- const base::ScopedCFTypeRef<IOSurfaceRef> io_surface;
- const gfx::RectF contents_rect;
- const gfx::Rect pixel_frame_rect;
- bool layer_needs_update;
- base::scoped_nsobject<CALayer> ca_layer;
-
- void TakeCALayerFrom(OverlayPlane* other_plane) {
- ca_layer.swap(other_plane->ca_layer);
- }
-
- void UpdateProperties(float scale_factor) {
- if (layer_needs_update) {
- [ca_layer setOpaque:YES];
-
- id new_contents = static_cast<id>(io_surface.get());
- if ([ca_layer contents] == new_contents)
- [ca_layer setContentsChanged];
- else
- [ca_layer setContents:new_contents];
- [ca_layer setContentsRect:contents_rect.ToCGRect()];
-
- [ca_layer setAnchorPoint:CGPointZero];
-
- if ([ca_layer respondsToSelector:(@selector(setContentsScale:))])
- [ca_layer setContentsScale:scale_factor];
- gfx::RectF dip_frame_rect = gfx::RectF(pixel_frame_rect);
- dip_frame_rect.Scale(1 / scale_factor);
- [ca_layer setBounds:CGRectMake(0, 0, dip_frame_rect.width(),
- dip_frame_rect.height())];
- [ca_layer
- setPosition:CGPointMake(dip_frame_rect.x(), dip_frame_rect.y())];
- }
- static bool show_borders =
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kShowMacOverlayBorders);
- if (show_borders) {
- base::ScopedCFTypeRef<CGColorRef> color;
- if (!layer_needs_update) {
- // Green represents contents that are unchanged across frames.
- color.reset(CGColorCreateGenericRGB(0, 1, 0, 1));
- } else {
- // Red represents damaged contents.
- color.reset(CGColorCreateGenericRGB(1, 0, 0, 1));
- }
- [ca_layer setBorderWidth:1];
- [ca_layer setBorderColor:color];
- }
- layer_needs_update = false;
- }
-
- private:
-};
-
-void CALayerPartialDamageTree::UpdatePartialDamagePlanes(
- CALayerPartialDamageTree* old_tree,
- const gfx::Rect& pixel_damage_rect) {
- // Don't create partial damage layers if partial swap is disabled.
- if (!allow_partial_swap_)
- return;
- // Only create partial damage layers when building on top of an existing tree.
- if (!old_tree)
- return;
- // If the frame size has changed, discard all of the old partial damage
- // layers.
- if (old_tree->root_plane_->pixel_frame_rect != root_plane_->pixel_frame_rect)
- return;
- // If there is full damage, discard all of the old partial damage layers.
- if (pixel_damage_rect == root_plane_->pixel_frame_rect)
- return;
-
- // If there is no damage, don't change anything.
- if (pixel_damage_rect.IsEmpty()) {
- std::swap(partial_damage_planes_, old_tree->partial_damage_planes_);
- return;
- }
-
- // Find the last partial damage plane to re-use the CALayer from. Grow the
- // new rect for this layer to include this damage, and all nearby partial
- // damage layers.
- scoped_ptr<OverlayPlane> plane_for_swap;
- {
- auto plane_to_reuse_iter = old_tree->partial_damage_planes_.end();
- gfx::Rect plane_to_reuse_enlarged_pixel_damage_rect;
-
- for (auto old_plane_iter = old_tree->partial_damage_planes_.begin();
- old_plane_iter != old_tree->partial_damage_planes_.end();
- ++old_plane_iter) {
- gfx::Rect enlarged_pixel_damage_rect =
- (*old_plane_iter)->pixel_frame_rect;
- enlarged_pixel_damage_rect.Union(pixel_damage_rect);
-
- // Compute the fraction of the pixels that would not be updated by this
- // swap. If it is too big, try another layer.
- float waste_fraction = enlarged_pixel_damage_rect.size().GetArea() * 1.f /
- pixel_damage_rect.size().GetArea();
- if (waste_fraction > kMaximumPartialDamageWasteFraction)
- continue;
-
- plane_to_reuse_iter = old_plane_iter;
- plane_to_reuse_enlarged_pixel_damage_rect.Union(
- enlarged_pixel_damage_rect);
- }
- if (plane_to_reuse_iter != old_tree->partial_damage_planes_.end()) {
- gfx::RectF enlarged_contents_rect =
- gfx::RectF(plane_to_reuse_enlarged_pixel_damage_rect);
- enlarged_contents_rect.Scale(1. / root_plane_->pixel_frame_rect.width(),
- 1. / root_plane_->pixel_frame_rect.height());
-
- plane_for_swap.reset(new OverlayPlane(
- root_plane_->io_surface, plane_to_reuse_enlarged_pixel_damage_rect,
- enlarged_contents_rect));
-
- plane_for_swap->TakeCALayerFrom((*plane_to_reuse_iter).get());
- if (*plane_to_reuse_iter != old_tree->partial_damage_planes_.back()) {
- CALayer* superlayer = [plane_for_swap->ca_layer superlayer];
- [plane_for_swap->ca_layer removeFromSuperlayer];
- [superlayer addSublayer:plane_for_swap->ca_layer];
- }
- }
- }
-
- // If we haven't found an appropriate layer to re-use, create a new one, if
- // we haven't already created too many.
- if (!plane_for_swap.get() &&
- old_tree->partial_damage_planes_.size() < kMaximumPartialDamageLayers) {
- gfx::RectF contents_rect = gfx::RectF(pixel_damage_rect);
- contents_rect.Scale(1. / root_plane_->pixel_frame_rect.width(),
- 1. / root_plane_->pixel_frame_rect.height());
- plane_for_swap.reset(new OverlayPlane(root_plane_->io_surface,
- pixel_damage_rect, contents_rect));
- }
-
- // And if we still don't have a layer, do full damage.
- if (!plane_for_swap.get())
- return;
-
- // Walk all old partial damage planes. Remove anything that is now completely
- // covered, and move everything else into the new |partial_damage_planes_|.
- for (auto& old_plane : old_tree->partial_damage_planes_) {
- if (!old_plane.get())
- continue;
- // Intersect the planes' frames with the new root plane to ensure that
- // they don't get kept alive inappropriately.
- gfx::Rect old_plane_frame_rect = old_plane->pixel_frame_rect;
- old_plane_frame_rect.Intersect(root_plane_->pixel_frame_rect);
-
- bool old_plane_covered_by_swap = false;
- if (plane_for_swap.get() &&
- plane_for_swap->pixel_frame_rect.Contains(old_plane_frame_rect)) {
- old_plane_covered_by_swap = true;
- }
- if (!old_plane_covered_by_swap) {
- DCHECK(old_plane->ca_layer);
- partial_damage_planes_.push_back(std::move(old_plane));
- }
- }
-
- partial_damage_planes_.push_back(std::move(plane_for_swap));
-}
-
-void CALayerPartialDamageTree::UpdateRootAndPartialDamagePlanes(
- scoped_ptr<CALayerPartialDamageTree> old_tree,
- const gfx::Rect& pixel_damage_rect) {
- // First update the partial damage tree.
- UpdatePartialDamagePlanes(old_tree.get(), pixel_damage_rect);
- if (old_tree) {
- if (partial_damage_planes_.empty()) {
- // If there are no partial damage planes, then we will be updating the
- // root layer. Take the CALayer from the old tree.
- root_plane_->TakeCALayerFrom(old_tree->root_plane_.get());
- } else {
- // If there is a partial damage tree, then just take the old plane
- // from the previous frame, so that there is no update to it.
- root_plane_.swap(old_tree->root_plane_);
- }
- }
-}
-
-void CALayerPartialDamageTree::UpdateCALayers(CALayer* superlayer,
- float scale_factor) {
- if (!allow_partial_swap_) {
- DCHECK(partial_damage_planes_.empty());
- return;
- }
-
- // Allocate and update CALayers for the backbuffer and partial damage layers.
- if (!root_plane_->ca_layer) {
- DCHECK(partial_damage_planes_.empty());
- root_plane_->ca_layer.reset([[CALayer alloc] init]);
- [superlayer setSublayers:nil];
- [superlayer addSublayer:root_plane_->ca_layer];
- }
- // Excessive logging to debug white screens (crbug.com/583805).
- // TODO(ccameron): change this back to a DLOG.
- if ([root_plane_->ca_layer superlayer] != superlayer) {
- LOG(ERROR) << "CALayerPartialDamageTree root layer not attached to tree.";
- }
- for (auto& plane : partial_damage_planes_) {
- if (!plane->ca_layer) {
- DCHECK(plane == partial_damage_planes_.back());
- plane->ca_layer.reset([[CALayer alloc] init]);
- }
- if (![plane->ca_layer superlayer]) {
- DCHECK(plane == partial_damage_planes_.back());
- [superlayer addSublayer:plane->ca_layer];
- }
- }
- root_plane_->UpdateProperties(scale_factor);
- for (auto& plane : partial_damage_planes_)
- plane->UpdateProperties(scale_factor);
-}
-
-CALayerPartialDamageTree::CALayerPartialDamageTree(
- bool allow_partial_swap,
- base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
- const gfx::Rect& pixel_frame_rect)
- : allow_partial_swap_(allow_partial_swap) {
- root_plane_.reset(
- new OverlayPlane(io_surface, pixel_frame_rect, gfx::RectF(0, 0, 1, 1)));
-}
-
-CALayerPartialDamageTree::~CALayerPartialDamageTree() {}
-
-base::ScopedCFTypeRef<IOSurfaceRef>
-CALayerPartialDamageTree::RootLayerIOSurface() {
- return root_plane_->io_surface;
-}
-
-void CALayerPartialDamageTree::CommitCALayers(
- CALayer* superlayer,
- scoped_ptr<CALayerPartialDamageTree> old_tree,
- float scale_factor,
- const gfx::Rect& pixel_damage_rect) {
- TRACE_EVENT0("gpu", "CALayerPartialDamageTree::CommitCALayers");
- UpdateRootAndPartialDamagePlanes(std::move(old_tree), pixel_damage_rect);
- UpdateCALayers(superlayer, scale_factor);
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/ca_layer_tree_mac.h b/chromium/content/common/gpu/ca_layer_tree_mac.h
deleted file mode 100644
index d20bdb0d8be..00000000000
--- a/chromium/content/common/gpu/ca_layer_tree_mac.h
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_CA_LAYER_TREE_MAC_H_
-#define CONTENT_COMMON_GPU_CA_LAYER_TREE_MAC_H_
-
-#include <IOSurface/IOSurface.h>
-#include <QuartzCore/QuartzCore.h>
-#include <deque>
-#include <vector>
-
-#include "base/mac/scoped_cftyperef.h"
-#include "base/mac/scoped_nsobject.h"
-#include "base/memory/scoped_ptr.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/rect_f.h"
-#include "ui/gfx/transform.h"
-
-namespace content {
-
-// The CALayerTree will construct a hierarchy of CALayers from a linear list,
-// using the algorithm and structure referenced described in
-// https://docs.google.com/document/d/1DtSN9zzvCF44_FQPM7ie01UxGHagQ66zfF5L9HnigQY/edit?usp=sharing
-class CALayerTree {
- public:
- CALayerTree();
-
- // This will remove all CALayers from this tree from their superlayer.
- ~CALayerTree();
-
- // Append the description of a new CALayer to the tree. This will not
- // create any new CALayers until CommitScheduledCALayers is called. This
- // cannot be called anymore after CommitScheduledCALayers has been called.
- bool ScheduleCALayer(bool is_clipped,
- const gfx::Rect& clip_rect,
- unsigned sorting_context_id,
- const gfx::Transform& transform,
- base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
- const gfx::RectF& contents_rect,
- const gfx::Rect& rect,
- unsigned background_color,
- unsigned edge_aa_mask,
- float opacity);
-
- // Create a CALayer tree for the scheduled layers, and set |superlayer| to
- // have only this tree as its sublayers. If |old_tree| is non-null, then try
- // to re-use the CALayers of |old_tree| as much as possible. |old_tree| will
- // be destroyed at the end of the function, and any CALayers in it which were
- // not re-used by |this| will be removed from the CALayer hierarchy.
- void CommitScheduledCALayers(CALayer* superlayer,
- scoped_ptr<CALayerTree> old_tree,
- float scale_factor);
-
- private:
- struct RootLayer;
- struct ClipAndSortingLayer;
- struct TransformLayer;
- struct ContentLayer;
-
- struct RootLayer {
- RootLayer();
-
- // This will remove |ca_layer| from its superlayer, if |ca_layer| is
- // non-nil.
- ~RootLayer();
-
- // Append a new content layer, without modifying the actual CALayer
- // structure.
- bool AddContentLayer(bool is_clipped,
- const gfx::Rect& clip_rect,
- unsigned sorting_context_id,
- const gfx::Transform& transform,
- base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
- const gfx::RectF& contents_rect,
- const gfx::Rect& rect,
- unsigned background_color,
- unsigned edge_aa_mask,
- float opacity);
-
- // Allocate CALayers for this layer and its children, and set their
- // properties appropriately. Re-use the CALayers from |old_layer| if
- // possible. If re-using a CALayer from |old_layer|, reset its |ca_layer|
- // to nil, so that its destructor will not remove an active CALayer.
- void CommitToCA(CALayer* superlayer,
- RootLayer* old_layer,
- float scale_factor);
-
- std::vector<ClipAndSortingLayer> clip_and_sorting_layers;
- base::scoped_nsobject<CALayer> ca_layer;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(RootLayer);
- };
- struct ClipAndSortingLayer {
- ClipAndSortingLayer(bool is_clipped,
- gfx::Rect clip_rect,
- unsigned sorting_context_id,
- bool is_singleton_sorting_context);
- ClipAndSortingLayer(ClipAndSortingLayer&& layer);
-
- // See the behavior of RootLayer for the effects of these functions on the
- // |ca_layer| member and |old_layer| argument.
- ~ClipAndSortingLayer();
- void AddContentLayer(const gfx::Transform& transform,
- base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
- const gfx::RectF& contents_rect,
- const gfx::Rect& rect,
- unsigned background_color,
- unsigned edge_aa_mask,
- float opacity);
- void CommitToCA(CALayer* superlayer,
- ClipAndSortingLayer* old_layer,
- float scale_factor);
-
- std::vector<TransformLayer> transform_layers;
- bool is_clipped = false;
- gfx::Rect clip_rect;
- unsigned sorting_context_id = 0;
- bool is_singleton_sorting_context = false;
- base::scoped_nsobject<CALayer> ca_layer;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ClipAndSortingLayer);
- };
- struct TransformLayer {
- TransformLayer(const gfx::Transform& transform);
- TransformLayer(TransformLayer&& layer);
-
- // See the behavior of RootLayer for the effects of these functions on the
- // |ca_layer| member and |old_layer| argument.
- ~TransformLayer();
- void AddContentLayer(base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
- const gfx::RectF& contents_rect,
- const gfx::Rect& rect,
- unsigned background_color,
- unsigned edge_aa_mask,
- float opacity);
- void CommitToCA(CALayer* superlayer,
- TransformLayer* old_layer,
- float scale_factor);
-
- gfx::Transform transform;
- std::vector<ContentLayer> content_layers;
- base::scoped_nsobject<CALayer> ca_layer;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TransformLayer);
- };
- struct ContentLayer {
- ContentLayer(base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
- const gfx::RectF& contents_rect,
- const gfx::Rect& rect,
- unsigned background_color,
- unsigned edge_aa_mask,
- float opacity);
- ContentLayer(ContentLayer&& layer);
-
- // See the behavior of RootLayer for the effects of these functions on the
- // |ca_layer| member and |old_layer| argument.
- ~ContentLayer();
- void CommitToCA(CALayer* parent,
- ContentLayer* old_layer,
- float scale_factor);
-
- const base::ScopedCFTypeRef<IOSurfaceRef> io_surface;
- gfx::RectF contents_rect;
- gfx::Rect rect;
- unsigned background_color = 0;
- // Note that the CoreAnimation edge antialiasing mask is not the same as
- // the edge antialiasing mask passed to the constructor.
- CAEdgeAntialiasingMask ca_edge_aa_mask = 0;
- float opacity = 1;
- base::scoped_nsobject<CALayer> ca_layer;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ContentLayer);
- };
-
- RootLayer root_layer_;
- float scale_factor_ = 1;
- bool has_committed_ = false;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CALayerTree);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_CA_LAYER_TREE_MAC_H_
diff --git a/chromium/content/common/gpu/ca_layer_tree_mac.mm b/chromium/content/common/gpu/ca_layer_tree_mac.mm
deleted file mode 100644
index 8c7d93886a5..00000000000
--- a/chromium/content/common/gpu/ca_layer_tree_mac.mm
+++ /dev/null
@@ -1,455 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/ca_layer_tree_mac.h"
-
-#include "base/command_line.h"
-#include "base/mac/sdk_forward_declarations.h"
-#include "base/trace_event/trace_event.h"
-#include "gpu/GLES2/gl2extchromium.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "ui/base/cocoa/animation_utils.h"
-#include "ui/base/ui_base_switches.h"
-#include "ui/gfx/geometry/dip_util.h"
-
-namespace content {
-
-CALayerTree::CALayerTree() {}
-CALayerTree::~CALayerTree() {}
-
-bool CALayerTree::ScheduleCALayer(
- bool is_clipped,
- const gfx::Rect& clip_rect,
- unsigned sorting_context_id,
- const gfx::Transform& transform,
- base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
- const gfx::RectF& contents_rect,
- const gfx::Rect& rect,
- unsigned background_color,
- unsigned edge_aa_mask,
- float opacity) {
- // Excessive logging to debug white screens (crbug.com/583805).
- // TODO(ccameron): change this back to a DLOG.
- if (has_committed_) {
- LOG(ERROR) << "ScheduleCALayer called after CommitScheduledCALayers.";
- return false;
- }
- return root_layer_.AddContentLayer(is_clipped, clip_rect, sorting_context_id,
- transform, io_surface, contents_rect, rect,
- background_color, edge_aa_mask, opacity);
-}
-
-void CALayerTree::CommitScheduledCALayers(CALayer* superlayer,
- scoped_ptr<CALayerTree> old_tree,
- float scale_factor) {
- TRACE_EVENT0("gpu", "CALayerTree::CommitScheduledCALayers");
- RootLayer* old_root_layer = nullptr;
- if (old_tree) {
- DCHECK(old_tree->has_committed_);
- if (old_tree->scale_factor_ == scale_factor)
- old_root_layer = &old_tree->root_layer_;
- }
-
- root_layer_.CommitToCA(superlayer, old_root_layer, scale_factor);
- // If there are any extra CALayers in |old_tree| that were not stolen by this
- // tree, they will be removed from the CALayer tree in this deallocation.
- old_tree.reset();
- has_committed_ = true;
- scale_factor_ = scale_factor;
-}
-
-CALayerTree::RootLayer::RootLayer() {}
-
-// Note that for all destructors, the the CALayer will have been reset to nil if
-// another layer has taken it.
-CALayerTree::RootLayer::~RootLayer() {
- [ca_layer removeFromSuperlayer];
-}
-
-CALayerTree::ClipAndSortingLayer::ClipAndSortingLayer(
- bool is_clipped,
- gfx::Rect clip_rect,
- unsigned sorting_context_id,
- bool is_singleton_sorting_context)
- : is_clipped(is_clipped),
- clip_rect(clip_rect),
- sorting_context_id(sorting_context_id),
- is_singleton_sorting_context(is_singleton_sorting_context) {}
-
-CALayerTree::ClipAndSortingLayer::ClipAndSortingLayer(
- ClipAndSortingLayer&& layer)
- : transform_layers(std::move(layer.transform_layers)),
- is_clipped(layer.is_clipped),
- clip_rect(layer.clip_rect),
- sorting_context_id(layer.sorting_context_id),
- is_singleton_sorting_context(
- layer.is_singleton_sorting_context),
- ca_layer(layer.ca_layer) {
- // Ensure that the ca_layer be reset, so that when the destructor is called,
- // the layer hierarchy is unaffected.
- // TODO(ccameron): Add a move constructor for scoped_nsobject to do this
- // automatically.
- layer.ca_layer.reset();
-}
-
-CALayerTree::ClipAndSortingLayer::~ClipAndSortingLayer() {
- [ca_layer removeFromSuperlayer];
-}
-
-CALayerTree::TransformLayer::TransformLayer(const gfx::Transform& transform)
- : transform(transform) {}
-
-CALayerTree::TransformLayer::TransformLayer(TransformLayer&& layer)
- : transform(layer.transform),
- content_layers(std::move(layer.content_layers)),
- ca_layer(layer.ca_layer) {
- layer.ca_layer.reset();
-}
-
-CALayerTree::TransformLayer::~TransformLayer() {
- [ca_layer removeFromSuperlayer];
-}
-
-CALayerTree::ContentLayer::ContentLayer(
- base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
- const gfx::RectF& contents_rect,
- const gfx::Rect& rect,
- unsigned background_color,
- unsigned edge_aa_mask,
- float opacity)
- : io_surface(io_surface),
- contents_rect(contents_rect),
- rect(rect),
- background_color(background_color),
- ca_edge_aa_mask(0),
- opacity(opacity) {
- // Because the root layer has setGeometryFlipped:YES, there is some ambiguity
- // about what exactly top and bottom mean. This ambiguity is resolved in
- // different ways for solid color CALayers and for CALayers that have content
- // (surprise!). For CALayers with IOSurface content, the top edge in the AA
- // mask refers to what appears as the bottom edge on-screen. For CALayers
- // without content (solid color layers), the top edge in the AA mask is the
- // top edge on-screen.
- // http://crbug.com/567946
- if (edge_aa_mask & GL_CA_LAYER_EDGE_LEFT_CHROMIUM)
- ca_edge_aa_mask |= kCALayerLeftEdge;
- if (edge_aa_mask & GL_CA_LAYER_EDGE_RIGHT_CHROMIUM)
- ca_edge_aa_mask |= kCALayerRightEdge;
- if (io_surface) {
- if (edge_aa_mask & GL_CA_LAYER_EDGE_TOP_CHROMIUM)
- ca_edge_aa_mask |= kCALayerBottomEdge;
- if (edge_aa_mask & GL_CA_LAYER_EDGE_BOTTOM_CHROMIUM)
- ca_edge_aa_mask |= kCALayerTopEdge;
- } else {
- if (edge_aa_mask & GL_CA_LAYER_EDGE_TOP_CHROMIUM)
- ca_edge_aa_mask |= kCALayerTopEdge;
- if (edge_aa_mask & GL_CA_LAYER_EDGE_BOTTOM_CHROMIUM)
- ca_edge_aa_mask |= kCALayerBottomEdge;
- }
-
- // Ensure that the IOSurface be in use as soon as it is added to a
- // ContentLayer, so that, by the time that the call to SwapBuffers completes,
- // all IOSurfaces that can be used as CALayer contents in the future will be
- // marked as InUse.
- if (io_surface)
- IOSurfaceIncrementUseCount(io_surface);
-}
-
-CALayerTree::ContentLayer::ContentLayer(ContentLayer&& layer)
- : io_surface(layer.io_surface),
- contents_rect(layer.contents_rect),
- rect(layer.rect),
- background_color(layer.background_color),
- ca_edge_aa_mask(layer.ca_edge_aa_mask),
- opacity(layer.opacity),
- ca_layer(layer.ca_layer) {
- DCHECK(!layer.ca_layer);
- layer.ca_layer.reset();
- // See remarks in the non-move constructor.
- if (io_surface)
- IOSurfaceIncrementUseCount(io_surface);
-}
-
-CALayerTree::ContentLayer::~ContentLayer() {
- [ca_layer removeFromSuperlayer];
- // By the time the destructor is called, the IOSurface will have been passed
- // to the WindowServer, and will remain InUse by the WindowServer as long as
- // is needed to avoid recycling bugs.
- if (io_surface)
- IOSurfaceDecrementUseCount(io_surface);
-}
-
-bool CALayerTree::RootLayer::AddContentLayer(
- bool is_clipped,
- const gfx::Rect& clip_rect,
- unsigned sorting_context_id,
- const gfx::Transform& transform,
- base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
- const gfx::RectF& contents_rect,
- const gfx::Rect& rect,
- unsigned background_color,
- unsigned edge_aa_mask,
- float opacity) {
- bool needs_new_clip_and_sorting_layer = true;
-
- // In sorting_context_id 0, all quads are listed in back-to-front order.
- // This is accomplished by having the CALayers be siblings of each other.
- // If a quad has a 3D transform, it is necessary to put it in its own sorting
- // context, so that it will not intersect with quads before and after it.
- bool is_singleton_sorting_context =
- !sorting_context_id && !transform.IsFlat();
-
- if (!clip_and_sorting_layers.empty()) {
- ClipAndSortingLayer& current_layer = clip_and_sorting_layers.back();
- // It is in error to change the clipping settings within a non-zero sorting
- // context. The result will be incorrect layering and intersection.
- if (sorting_context_id &&
- current_layer.sorting_context_id == sorting_context_id &&
- (current_layer.is_clipped != is_clipped ||
- current_layer.clip_rect != clip_rect)) {
- // Excessive logging to debug white screens (crbug.com/583805).
- // TODO(ccameron): change this back to a DLOG.
- LOG(ERROR) << "CALayer changed clip inside non-zero sorting context.";
- return false;
- }
- if (!is_singleton_sorting_context &&
- !current_layer.is_singleton_sorting_context &&
- current_layer.is_clipped == is_clipped &&
- current_layer.clip_rect == clip_rect &&
- current_layer.sorting_context_id == sorting_context_id) {
- needs_new_clip_and_sorting_layer = false;
- }
- }
- if (needs_new_clip_and_sorting_layer) {
- clip_and_sorting_layers.push_back(
- ClipAndSortingLayer(is_clipped, clip_rect, sorting_context_id,
- is_singleton_sorting_context));
- }
- clip_and_sorting_layers.back().AddContentLayer(
- transform, io_surface, contents_rect, rect, background_color,
- edge_aa_mask, opacity);
- return true;
-}
-
-void CALayerTree::ClipAndSortingLayer::AddContentLayer(
- const gfx::Transform& transform,
- base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
- const gfx::RectF& contents_rect,
- const gfx::Rect& rect,
- unsigned background_color,
- unsigned edge_aa_mask,
- float opacity) {
- bool needs_new_transform_layer = true;
- if (!transform_layers.empty()) {
- const TransformLayer& current_layer = transform_layers.back();
- if (current_layer.transform == transform)
- needs_new_transform_layer = false;
- }
- if (needs_new_transform_layer)
- transform_layers.push_back(TransformLayer(transform));
- transform_layers.back().AddContentLayer(
- io_surface, contents_rect, rect, background_color, edge_aa_mask, opacity);
-}
-
-void CALayerTree::TransformLayer::AddContentLayer(
- base::ScopedCFTypeRef<IOSurfaceRef> io_surface,
- const gfx::RectF& contents_rect,
- const gfx::Rect& rect,
- unsigned background_color,
- unsigned edge_aa_mask,
- float opacity) {
- content_layers.push_back(ContentLayer(io_surface, contents_rect, rect,
- background_color, edge_aa_mask,
- opacity));
-}
-
-void CALayerTree::RootLayer::CommitToCA(CALayer* superlayer,
- RootLayer* old_layer,
- float scale_factor) {
- if (old_layer) {
- DCHECK(old_layer->ca_layer);
- std::swap(ca_layer, old_layer->ca_layer);
- } else {
- ca_layer.reset([[CALayer alloc] init]);
- [ca_layer setAnchorPoint:CGPointZero];
- [superlayer setSublayers:nil];
- [superlayer addSublayer:ca_layer];
- [superlayer setBorderWidth:0];
- }
- // Excessive logging to debug white screens (crbug.com/583805).
- // TODO(ccameron): change this back to a DCHECK.
- if ([ca_layer superlayer] != superlayer) {
- LOG(ERROR) << "CALayerTree root layer not attached to tree.";
- }
-
- for (size_t i = 0; i < clip_and_sorting_layers.size(); ++i) {
- ClipAndSortingLayer* old_clip_and_sorting_layer = nullptr;
- if (old_layer && i < old_layer->clip_and_sorting_layers.size()) {
- old_clip_and_sorting_layer = &old_layer->clip_and_sorting_layers[i];
- }
- clip_and_sorting_layers[i].CommitToCA(
- ca_layer.get(), old_clip_and_sorting_layer, scale_factor);
- }
-}
-
-void CALayerTree::ClipAndSortingLayer::CommitToCA(
- CALayer* superlayer,
- ClipAndSortingLayer* old_layer,
- float scale_factor) {
- bool update_is_clipped = true;
- bool update_clip_rect = true;
- if (old_layer) {
- DCHECK(old_layer->ca_layer);
- std::swap(ca_layer, old_layer->ca_layer);
- update_is_clipped = old_layer->is_clipped != is_clipped;
- update_clip_rect = old_layer->clip_rect != clip_rect;
- } else {
- ca_layer.reset([[CALayer alloc] init]);
- [ca_layer setAnchorPoint:CGPointZero];
- [superlayer addSublayer:ca_layer];
- }
- // Excessive logging to debug white screens (crbug.com/583805).
- // TODO(ccameron): change this back to a DCHECK.
- if ([ca_layer superlayer] != superlayer) {
- LOG(ERROR) << "CALayerTree root layer not attached to tree.";
- }
-
- if (update_is_clipped)
- [ca_layer setMasksToBounds:is_clipped];
-
- if (update_clip_rect) {
- if (is_clipped) {
- gfx::RectF dip_clip_rect = gfx::RectF(clip_rect);
- dip_clip_rect.Scale(1 / scale_factor);
- [ca_layer setPosition:CGPointMake(dip_clip_rect.x(), dip_clip_rect.y())];
- [ca_layer setBounds:CGRectMake(0, 0, dip_clip_rect.width(),
- dip_clip_rect.height())];
- [ca_layer
- setSublayerTransform:CATransform3DMakeTranslation(
- -dip_clip_rect.x(), -dip_clip_rect.y(), 0)];
- } else {
- [ca_layer setPosition:CGPointZero];
- [ca_layer setBounds:CGRectZero];
- [ca_layer setSublayerTransform:CATransform3DIdentity];
- }
- }
-
- for (size_t i = 0; i < transform_layers.size(); ++i) {
- TransformLayer* old_transform_layer = nullptr;
- if (old_layer && i < old_layer->transform_layers.size())
- old_transform_layer = &old_layer->transform_layers[i];
- transform_layers[i].CommitToCA(ca_layer.get(), old_transform_layer,
- scale_factor);
- }
-}
-
-void CALayerTree::TransformLayer::CommitToCA(CALayer* superlayer,
- TransformLayer* old_layer,
- float scale_factor) {
- bool update_transform = true;
- if (old_layer) {
- DCHECK(old_layer->ca_layer);
- std::swap(ca_layer, old_layer->ca_layer);
- update_transform = old_layer->transform != transform;
- } else {
- ca_layer.reset([[CATransformLayer alloc] init]);
- [superlayer addSublayer:ca_layer];
- }
- DCHECK_EQ([ca_layer superlayer], superlayer);
-
- if (update_transform) {
- gfx::Transform pre_scale;
- gfx::Transform post_scale;
- pre_scale.Scale(1 / scale_factor, 1 / scale_factor);
- post_scale.Scale(scale_factor, scale_factor);
- gfx::Transform conjugated_transform = pre_scale * transform * post_scale;
-
- CATransform3D ca_transform;
- conjugated_transform.matrix().asColMajord(&ca_transform.m11);
- [ca_layer setTransform:ca_transform];
- }
-
- for (size_t i = 0; i < content_layers.size(); ++i) {
- ContentLayer* old_content_layer = nullptr;
- if (old_layer && i < old_layer->content_layers.size())
- old_content_layer = &old_layer->content_layers[i];
- content_layers[i].CommitToCA(ca_layer.get(), old_content_layer,
- scale_factor);
- }
-}
-
-void CALayerTree::ContentLayer::CommitToCA(CALayer* superlayer,
- ContentLayer* old_layer,
- float scale_factor) {
- bool update_contents = true;
- bool update_contents_rect = true;
- bool update_rect = true;
- bool update_background_color = true;
- bool update_ca_edge_aa_mask = true;
- bool update_opacity = true;
- if (old_layer) {
- DCHECK(old_layer->ca_layer);
- std::swap(ca_layer, old_layer->ca_layer);
- update_contents = old_layer->io_surface != io_surface;
- update_contents_rect = old_layer->contents_rect != contents_rect;
- update_rect = old_layer->rect != rect;
- update_background_color = old_layer->background_color != background_color;
- update_ca_edge_aa_mask = old_layer->ca_edge_aa_mask != ca_edge_aa_mask;
- update_opacity = old_layer->opacity != opacity;
- } else {
- ca_layer.reset([[CALayer alloc] init]);
- [ca_layer setAnchorPoint:CGPointZero];
- [superlayer addSublayer:ca_layer];
- }
- DCHECK_EQ([ca_layer superlayer], superlayer);
- bool update_anything = update_contents || update_contents_rect ||
- update_rect || update_background_color ||
- update_ca_edge_aa_mask || update_opacity;
-
- if (update_contents) {
- [ca_layer setContents:static_cast<id>(io_surface.get())];
- if ([ca_layer respondsToSelector:(@selector(setContentsScale:))])
- [ca_layer setContentsScale:scale_factor];
- }
- if (update_contents_rect)
- [ca_layer setContentsRect:contents_rect.ToCGRect()];
- if (update_rect) {
- gfx::RectF dip_rect = gfx::RectF(rect);
- dip_rect.Scale(1 / scale_factor);
- [ca_layer setPosition:CGPointMake(dip_rect.x(), dip_rect.y())];
- [ca_layer setBounds:CGRectMake(0, 0, dip_rect.width(), dip_rect.height())];
- }
- if (update_background_color) {
- CGFloat rgba_color_components[4] = {
- SkColorGetR(background_color) / 255.,
- SkColorGetG(background_color) / 255.,
- SkColorGetB(background_color) / 255.,
- SkColorGetA(background_color) / 255.,
- };
- base::ScopedCFTypeRef<CGColorRef> srgb_background_color(CGColorCreate(
- CGColorSpaceCreateWithName(kCGColorSpaceSRGB), rgba_color_components));
- [ca_layer setBackgroundColor:srgb_background_color];
- }
- if (update_ca_edge_aa_mask)
- [ca_layer setEdgeAntialiasingMask:ca_edge_aa_mask];
- if (update_opacity)
- [ca_layer setOpacity:opacity];
-
- static bool show_borders = base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kShowMacOverlayBorders);
- if (show_borders) {
- base::ScopedCFTypeRef<CGColorRef> color;
- if (update_anything) {
- // Pink represents a CALayer that changed this frame.
- color.reset(CGColorCreateGenericRGB(1, 0, 1, 1));
- } else {
- // Grey represents a CALayer that has not changed.
- color.reset(CGColorCreateGenericRGB(0, 0, 0, 0.1));
- }
- [ca_layer setBorderWidth:1];
- [ca_layer setBorderColor:color];
- }
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/child_window_surface_win.cc b/chromium/content/common/gpu/child_window_surface_win.cc
deleted file mode 100644
index 738caea87ad..00000000000
--- a/chromium/content/common/gpu/child_window_surface_win.cc
+++ /dev/null
@@ -1,214 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/child_window_surface_win.h"
-
-#include "base/compiler_specific.h"
-#include "base/win/scoped_hdc.h"
-#include "base/win/wrapped_window_proc.h"
-#include "content/common/gpu/gpu_channel_manager.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "ui/base/win/hidden_window.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gfx/win/hwnd_util.h"
-#include "ui/gl/egl_util.h"
-#include "ui/gl/gl_context.h"
-#include "ui/gl/gl_surface_egl.h"
-#include "ui/gl/scoped_make_current.h"
-
-namespace content {
-
-namespace {
-
-ATOM g_window_class;
-
-LRESULT CALLBACK IntermediateWindowProc(HWND window,
- UINT message,
- WPARAM w_param,
- LPARAM l_param) {
- switch (message) {
- case WM_ERASEBKGND:
- // Prevent windows from erasing the background.
- return 1;
- case WM_PAINT:
- PAINTSTRUCT paint;
- if (BeginPaint(window, &paint)) {
- ChildWindowSurfaceWin* window_surface =
- reinterpret_cast<ChildWindowSurfaceWin*>(
- gfx::GetWindowUserData(window));
- DCHECK(window_surface);
-
- // Wait to clear the contents until a GL draw occurs, as otherwise an
- // unsightly black flash may happen if the GL contents are still
- // transparent.
- window_surface->InvalidateWindowRect(gfx::Rect(paint.rcPaint));
- EndPaint(window, &paint);
- }
- return 0;
- default:
- return DefWindowProc(window, message, w_param, l_param);
- }
-}
-
-void InitializeWindowClass() {
- if (g_window_class)
- return;
-
- WNDCLASSEX intermediate_class;
- base::win::InitializeWindowClass(
- L"Intermediate D3D Window",
- &base::win::WrappedWindowProc<IntermediateWindowProc>, CS_OWNDC, 0, 0,
- nullptr, reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)), nullptr,
- nullptr, nullptr, &intermediate_class);
- g_window_class = RegisterClassEx(&intermediate_class);
- if (!g_window_class) {
- LOG(ERROR) << "RegisterClass failed.";
- return;
- }
-}
-}
-
-ChildWindowSurfaceWin::ChildWindowSurfaceWin(GpuChannelManager* manager,
- HWND parent_window)
- : gfx::NativeViewGLSurfaceEGL(0),
- parent_window_(parent_window),
- manager_(manager) {
- // Don't use EGL_ANGLE_window_fixed_size so that we can avoid recreating the
- // window surface, which can cause flicker on DirectComposition.
- enable_fixed_size_angle_ = false;
-}
-
-EGLConfig ChildWindowSurfaceWin::GetConfig() {
- if (!config_) {
- int alpha_size = alpha_ ? 8 : EGL_DONT_CARE;
-
- EGLint config_attribs[] = {EGL_ALPHA_SIZE,
- alpha_size,
- EGL_BLUE_SIZE,
- 8,
- EGL_GREEN_SIZE,
- 8,
- EGL_RED_SIZE,
- 8,
- EGL_RENDERABLE_TYPE,
- EGL_OPENGL_ES2_BIT,
- EGL_SURFACE_TYPE,
- EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
- EGL_NONE};
-
- EGLDisplay display = GetHardwareDisplay();
- EGLint num_configs;
- if (!eglChooseConfig(display, config_attribs, &config_, 1, &num_configs)) {
- LOG(ERROR) << "eglChooseConfig failed with error "
- << ui::GetLastEGLErrorString();
- return NULL;
- }
- }
-
- return config_;
-}
-
-bool ChildWindowSurfaceWin::InitializeNativeWindow() {
- if (window_)
- return true;
- InitializeWindowClass();
- DCHECK(g_window_class);
-
- RECT windowRect;
- GetClientRect(parent_window_, &windowRect);
-
- window_ = CreateWindowEx(
- WS_EX_NOPARENTNOTIFY, reinterpret_cast<wchar_t*>(g_window_class), L"",
- WS_CHILDWINDOW | WS_DISABLED | WS_VISIBLE, 0, 0,
- windowRect.right - windowRect.left, windowRect.bottom - windowRect.top,
- ui::GetHiddenWindow(), NULL, NULL, NULL);
- gfx::SetWindowUserData(window_, this);
- manager_->Send(new GpuHostMsg_AcceleratedSurfaceCreatedChildWindow(
- parent_window_, window_));
- return true;
-}
-
-bool ChildWindowSurfaceWin::Resize(const gfx::Size& size,
- float scale_factor,
- bool has_alpha) {
- if (!SupportsPostSubBuffer()) {
- if (!MoveWindow(window_, 0, 0, size.width(), size.height(), FALSE)) {
- return false;
- }
- return gfx::NativeViewGLSurfaceEGL::Resize(size, scale_factor, has_alpha);
- } else {
- if (size == GetSize() && has_alpha == alpha_)
- return true;
-
- if (!MoveWindow(window_, 0, 0, size.width(), size.height(), FALSE)) {
- return false;
- }
- size_ = size;
- if (has_alpha == alpha_) {
- // A 0-size PostSubBuffer doesn't swap but forces the swap chain to resize
- // to match the window.
- PostSubBuffer(0, 0, 0, 0);
- } else {
- alpha_ = has_alpha;
- config_ = nullptr;
-
- scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current;
- gfx::GLContext* current_context = gfx::GLContext::GetCurrent();
- bool was_current = current_context && current_context->IsCurrent(this);
- if (was_current) {
- scoped_make_current.reset(
- new ui::ScopedMakeCurrent(current_context, this));
- current_context->ReleaseCurrent(this);
- }
-
- Destroy();
-
- if (!Initialize()) {
- LOG(ERROR) << "Failed to resize window.";
- return false;
- }
- }
- return true;
- }
-}
-
-gfx::SwapResult ChildWindowSurfaceWin::SwapBuffers() {
- gfx::SwapResult result = NativeViewGLSurfaceEGL::SwapBuffers();
- ClearInvalidContents();
- return result;
-}
-
-gfx::SwapResult ChildWindowSurfaceWin::PostSubBuffer(int x,
- int y,
- int width,
- int height) {
- gfx::SwapResult result =
- NativeViewGLSurfaceEGL::PostSubBuffer(x, y, width, height);
- ClearInvalidContents();
- return result;
-}
-
-void ChildWindowSurfaceWin::InvalidateWindowRect(const gfx::Rect& rect) {
- rect_to_clear_.Union(rect);
-}
-
-void ChildWindowSurfaceWin::ClearInvalidContents() {
- if (!rect_to_clear_.IsEmpty()) {
- base::win::ScopedGetDC dc(window_);
-
- RECT rect = rect_to_clear_.ToRECT();
-
- // DirectComposition composites with the contents under the SwapChain,
- // so ensure that's cleared. GDI treats black as transparent.
- FillRect(dc, &rect, reinterpret_cast<HBRUSH>(GetStockObject(BLACK_BRUSH)));
- rect_to_clear_ = gfx::Rect();
- }
-}
-
-ChildWindowSurfaceWin::~ChildWindowSurfaceWin() {
- gfx::SetWindowUserData(window_, nullptr);
- DestroyWindow(window_);
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/child_window_surface_win.h b/chromium/content/common/gpu/child_window_surface_win.h
deleted file mode 100644
index 83acd88ae49..00000000000
--- a/chromium/content/common/gpu/child_window_surface_win.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_CHILD_WINDOW_SURFACE_WIN_H_
-#define CONTENT_COMMON_GPU_CHILD_WINDOW_SURFACE_WIN_H_
-#include "ui/gl/gl_surface_egl.h"
-
-#include <windows.h>
-
-namespace content {
-
-class GpuChannelManager;
-
-class ChildWindowSurfaceWin : public gfx::NativeViewGLSurfaceEGL {
- public:
- ChildWindowSurfaceWin(GpuChannelManager* manager, HWND parent_window);
-
- // GLSurface implementation.
- EGLConfig GetConfig() override;
- bool Resize(const gfx::Size& size,
- float scale_factor,
- bool has_alpha) override;
- bool InitializeNativeWindow() override;
- gfx::SwapResult SwapBuffers() override;
- gfx::SwapResult PostSubBuffer(int x, int y, int width, int height) override;
-
- void InvalidateWindowRect(const gfx::Rect& rect);
-
- protected:
- ~ChildWindowSurfaceWin() override;
-
- private:
- void ClearInvalidContents();
-
- HWND parent_window_;
- GpuChannelManager* manager_;
- gfx::Rect rect_to_clear_;
-
- DISALLOW_COPY_AND_ASSIGN(ChildWindowSurfaceWin);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_CHILD_WINDOW_SURFACE_WIN_H_
diff --git a/chromium/content/common/gpu/client/DEPS b/chromium/content/common/gpu/client/DEPS
index 1aea6635f14..409909c2df0 100644
--- a/chromium/content/common/gpu/client/DEPS
+++ b/chromium/content/common/gpu/client/DEPS
@@ -1,10 +1,3 @@
include_rules = [
"+cc/blink",
]
-
-specific_include_rules = {
- # Tests can make use of content/browser/ infrastructure.
- ".*browsertest\.cc": [
- "+content/browser"
- ]
-}
diff --git a/chromium/content/common/gpu/client/command_buffer_metrics.cc b/chromium/content/common/gpu/client/command_buffer_metrics.cc
index 38590c36c08..2ff84f8b1f8 100644
--- a/chromium/content/common/gpu/client/command_buffer_metrics.cc
+++ b/chromium/content/common/gpu/client/command_buffer_metrics.cc
@@ -75,7 +75,7 @@ CommandBufferContextLostReason GetContextLostReason(
void RecordContextLost(CommandBufferContextType type,
CommandBufferContextLostReason reason) {
switch (type) {
- case BROWSER_COMPOSITOR_ONSCREEN_CONTEXT:
+ case DISPLAY_COMPOSITOR_ONSCREEN_CONTEXT:
UMA_HISTOGRAM_ENUMERATION("GPU.ContextLost.BrowserCompositor", reason,
CONTEXT_LOST_REASON_MAX_ENUM);
break;
@@ -124,8 +124,8 @@ std::string CommandBufferContextTypeToString(CommandBufferContextType type) {
switch (type) {
case OFFSCREEN_CONTEXT_FOR_TESTING:
return "Context-For-Testing";
- case BROWSER_COMPOSITOR_ONSCREEN_CONTEXT:
- return "Compositor";
+ case DISPLAY_COMPOSITOR_ONSCREEN_CONTEXT:
+ return "DisplayCompositor";
case BROWSER_OFFSCREEN_MAINTHREAD_CONTEXT:
return "Offscreen-MainThread";
case BROWSER_WORKER_CONTEXT:
diff --git a/chromium/content/common/gpu/client/command_buffer_metrics.h b/chromium/content/common/gpu/client/command_buffer_metrics.h
index 0b4790cd4b0..0cd62bb2209 100644
--- a/chromium/content/common/gpu/client/command_buffer_metrics.h
+++ b/chromium/content/common/gpu/client/command_buffer_metrics.h
@@ -12,7 +12,7 @@
namespace content {
enum CommandBufferContextType {
- BROWSER_COMPOSITOR_ONSCREEN_CONTEXT,
+ DISPLAY_COMPOSITOR_ONSCREEN_CONTEXT,
BROWSER_OFFSCREEN_MAINTHREAD_CONTEXT,
BROWSER_WORKER_CONTEXT,
RENDER_COMPOSITOR_CONTEXT,
diff --git a/chromium/content/common/gpu/client/command_buffer_proxy_impl.cc b/chromium/content/common/gpu/client/command_buffer_proxy_impl.cc
deleted file mode 100644
index 1b5d14b2ff4..00000000000
--- a/chromium/content/common/gpu/client/command_buffer_proxy_impl.cc
+++ /dev/null
@@ -1,820 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/client/command_buffer_proxy_impl.h"
-
-#include <utility>
-#include <vector>
-
-#include "base/callback.h"
-#include "base/logging.h"
-#include "base/memory/shared_memory.h"
-#include "base/stl_util.h"
-#include "base/trace_event/trace_event.h"
-#include "content/common/child_process_messages.h"
-#include "content/common/gpu/client/gpu_channel_host.h"
-#include "content/common/gpu/client/gpu_video_decode_accelerator_host.h"
-#include "content/common/gpu/client/gpu_video_encode_accelerator_host.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "content/common/view_messages.h"
-#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
-#include "gpu/command_buffer/common/cmd_buffer_common.h"
-#include "gpu/command_buffer/common/command_buffer_shared.h"
-#include "gpu/command_buffer/common/gpu_memory_allocation.h"
-#include "gpu/command_buffer/common/sync_token.h"
-#include "gpu/command_buffer/service/image_factory.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gl/gl_bindings.h"
-
-namespace content {
-
-namespace {
-
-uint64_t CommandBufferProxyID(int channel_id, int32_t route_id) {
- return (static_cast<uint64_t>(channel_id) << 32) | route_id;
-}
-
-} // namespace
-
-CommandBufferProxyImpl::CommandBufferProxyImpl(GpuChannelHost* channel,
- int32_t route_id,
- int32_t stream_id)
- : lock_(nullptr),
- channel_(channel),
- command_buffer_id_(CommandBufferProxyID(channel->channel_id(), route_id)),
- route_id_(route_id),
- stream_id_(stream_id),
- flush_count_(0),
- last_put_offset_(-1),
- last_barrier_put_offset_(-1),
- next_fence_sync_release_(1),
- flushed_fence_sync_release_(0),
- verified_fence_sync_release_(0),
- next_signal_id_(0),
- weak_this_(AsWeakPtr()),
- callback_thread_(base::ThreadTaskRunnerHandle::Get()) {
- DCHECK(channel);
- DCHECK(stream_id);
-}
-
-CommandBufferProxyImpl::~CommandBufferProxyImpl() {
- FOR_EACH_OBSERVER(DeletionObserver,
- deletion_observers_,
- OnWillDeleteImpl());
- if (channel_) {
- channel_->DestroyCommandBuffer(this);
- channel_ = nullptr;
- }
-}
-
-bool CommandBufferProxyImpl::OnMessageReceived(const IPC::Message& message) {
- scoped_ptr<base::AutoLock> lock;
- if (lock_)
- lock.reset(new base::AutoLock(*lock_));
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(CommandBufferProxyImpl, message)
- IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_Destroyed, OnDestroyed);
- IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_ConsoleMsg, OnConsoleMessage);
- IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SignalAck,
- OnSignalAck);
- IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SwapBuffersCompleted,
- OnSwapBuffersCompleted);
- IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_UpdateVSyncParameters,
- OnUpdateVSyncParameters);
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
-
- if (!handled) {
- DLOG(ERROR) << "Gpu process sent invalid message.";
- InvalidGpuMessage();
- }
- return handled;
-}
-
-void CommandBufferProxyImpl::OnChannelError() {
- scoped_ptr<base::AutoLock> lock;
- if (lock_)
- lock.reset(new base::AutoLock(*lock_));
-
- gpu::error::ContextLostReason context_lost_reason =
- gpu::error::kGpuChannelLost;
- if (shared_state_shm_ && shared_state_shm_->memory()) {
- TryUpdateState();
- // The GPU process might have intentionally been crashed
- // (exit_on_context_lost), so try to find out the original reason.
- if (last_state_.error == gpu::error::kLostContext)
- context_lost_reason = last_state_.context_lost_reason;
- }
- OnDestroyed(context_lost_reason, gpu::error::kLostContext);
-}
-
-void CommandBufferProxyImpl::OnDestroyed(gpu::error::ContextLostReason reason,
- gpu::error::Error error) {
- CheckLock();
- // Prevent any further messages from being sent.
- if (channel_) {
- channel_->DestroyCommandBuffer(this);
- channel_ = nullptr;
- }
-
- // When the client sees that the context is lost, they should delete this
- // CommandBufferProxyImpl and create a new one.
- last_state_.error = error;
- last_state_.context_lost_reason = reason;
-
- if (!context_lost_callback_.is_null()) {
- context_lost_callback_.Run();
- // Avoid calling the error callback more than once.
- context_lost_callback_.Reset();
- }
-}
-
-void CommandBufferProxyImpl::OnConsoleMessage(
- const GPUCommandBufferConsoleMessage& message) {
- if (!console_message_callback_.is_null()) {
- console_message_callback_.Run(message.message, message.id);
- }
-}
-
-void CommandBufferProxyImpl::AddDeletionObserver(DeletionObserver* observer) {
- scoped_ptr<base::AutoLock> lock;
- if (lock_)
- lock.reset(new base::AutoLock(*lock_));
- deletion_observers_.AddObserver(observer);
-}
-
-void CommandBufferProxyImpl::RemoveDeletionObserver(
- DeletionObserver* observer) {
- scoped_ptr<base::AutoLock> lock;
- if (lock_)
- lock.reset(new base::AutoLock(*lock_));
- deletion_observers_.RemoveObserver(observer);
-}
-
-void CommandBufferProxyImpl::OnSignalAck(uint32_t id) {
- SignalTaskMap::iterator it = signal_tasks_.find(id);
- if (it == signal_tasks_.end()) {
- DLOG(ERROR) << "Gpu process sent invalid SignalAck.";
- InvalidGpuMessage();
- return;
- }
- base::Closure callback = it->second;
- signal_tasks_.erase(it);
- callback.Run();
-}
-
-void CommandBufferProxyImpl::SetContextLostCallback(
- const base::Closure& callback) {
- CheckLock();
- context_lost_callback_ = callback;
-}
-
-bool CommandBufferProxyImpl::Initialize() {
- TRACE_EVENT0("gpu", "CommandBufferProxyImpl::Initialize");
- shared_state_shm_.reset(channel_->factory()->AllocateSharedMemory(
- sizeof(*shared_state())).release());
- if (!shared_state_shm_)
- return false;
-
- if (!shared_state_shm_->Map(sizeof(*shared_state())))
- return false;
-
- shared_state()->Initialize();
-
- // This handle is owned by the GPU process and must be passed to it or it
- // will leak. In otherwords, do not early out on error between here and the
- // sending of the Initialize IPC below.
- base::SharedMemoryHandle handle =
- channel_->ShareToGpuProcess(shared_state_shm_->handle());
- if (!base::SharedMemory::IsHandleValid(handle))
- return false;
-
- bool result = false;
- if (!Send(new GpuCommandBufferMsg_Initialize(
- route_id_, handle, &result, &capabilities_))) {
- LOG(ERROR) << "Could not send GpuCommandBufferMsg_Initialize.";
- return false;
- }
-
- if (!result) {
- LOG(ERROR) << "Failed to initialize command buffer service.";
- return false;
- }
-
- capabilities_.image = true;
-
- return true;
-}
-
-gpu::CommandBuffer::State CommandBufferProxyImpl::GetLastState() {
- return last_state_;
-}
-
-int32_t CommandBufferProxyImpl::GetLastToken() {
- TryUpdateState();
- return last_state_.token;
-}
-
-void CommandBufferProxyImpl::Flush(int32_t put_offset) {
- CheckLock();
- if (last_state_.error != gpu::error::kNoError)
- return;
-
- TRACE_EVENT1("gpu",
- "CommandBufferProxyImpl::Flush",
- "put_offset",
- put_offset);
-
- bool put_offset_changed = last_put_offset_ != put_offset;
- last_put_offset_ = put_offset;
- last_barrier_put_offset_ = put_offset;
-
- if (channel_) {
- const uint32_t flush_id = channel_->OrderingBarrier(
- route_id_, stream_id_, put_offset, ++flush_count_, latency_info_,
- put_offset_changed, true);
- if (put_offset_changed) {
- DCHECK(flush_id);
- const uint64_t fence_sync_release = next_fence_sync_release_ - 1;
- if (fence_sync_release > flushed_fence_sync_release_) {
- flushed_fence_sync_release_ = fence_sync_release;
- flushed_release_flush_id_.push(
- std::make_pair(fence_sync_release, flush_id));
- }
- }
- }
-
- if (put_offset_changed)
- latency_info_.clear();
-}
-
-void CommandBufferProxyImpl::OrderingBarrier(int32_t put_offset) {
- if (last_state_.error != gpu::error::kNoError)
- return;
-
- TRACE_EVENT1("gpu", "CommandBufferProxyImpl::OrderingBarrier", "put_offset",
- put_offset);
-
- bool put_offset_changed = last_barrier_put_offset_ != put_offset;
- last_barrier_put_offset_ = put_offset;
-
- if (channel_) {
- const uint32_t flush_id = channel_->OrderingBarrier(
- route_id_, stream_id_, put_offset, ++flush_count_, latency_info_,
- put_offset_changed, false);
- if (put_offset_changed) {
- DCHECK(flush_id);
- const uint64_t fence_sync_release = next_fence_sync_release_ - 1;
- if (fence_sync_release > flushed_fence_sync_release_) {
- flushed_fence_sync_release_ = fence_sync_release;
- flushed_release_flush_id_.push(
- std::make_pair(fence_sync_release, flush_id));
- }
- }
- }
-
- if (put_offset_changed)
- latency_info_.clear();
-}
-
-void CommandBufferProxyImpl::SetLatencyInfo(
- const std::vector<ui::LatencyInfo>& latency_info) {
- CheckLock();
- for (size_t i = 0; i < latency_info.size(); i++)
- latency_info_.push_back(latency_info[i]);
-}
-
-void CommandBufferProxyImpl::SetSwapBuffersCompletionCallback(
- const SwapBuffersCompletionCallback& callback) {
- CheckLock();
- swap_buffers_completion_callback_ = callback;
-}
-
-void CommandBufferProxyImpl::SetUpdateVSyncParametersCallback(
- const UpdateVSyncParametersCallback& callback) {
- CheckLock();
- update_vsync_parameters_completion_callback_ = callback;
-}
-
-void CommandBufferProxyImpl::WaitForTokenInRange(int32_t start, int32_t end) {
- CheckLock();
- TRACE_EVENT2("gpu",
- "CommandBufferProxyImpl::WaitForToken",
- "start",
- start,
- "end",
- end);
- TryUpdateState();
- if (!InRange(start, end, last_state_.token) &&
- last_state_.error == gpu::error::kNoError) {
- gpu::CommandBuffer::State state;
- if (Send(new GpuCommandBufferMsg_WaitForTokenInRange(
- route_id_, start, end, &state)))
- OnUpdateState(state);
- }
- if (!InRange(start, end, last_state_.token) &&
- last_state_.error == gpu::error::kNoError) {
- DLOG(ERROR) << "GPU state invalid after WaitForTokenInRange.";
- InvalidGpuReply();
- }
-}
-
-void CommandBufferProxyImpl::WaitForGetOffsetInRange(int32_t start,
- int32_t end) {
- CheckLock();
- TRACE_EVENT2("gpu",
- "CommandBufferProxyImpl::WaitForGetOffset",
- "start",
- start,
- "end",
- end);
- TryUpdateState();
- if (!InRange(start, end, last_state_.get_offset) &&
- last_state_.error == gpu::error::kNoError) {
- gpu::CommandBuffer::State state;
- if (Send(new GpuCommandBufferMsg_WaitForGetOffsetInRange(
- route_id_, start, end, &state)))
- OnUpdateState(state);
- }
- if (!InRange(start, end, last_state_.get_offset) &&
- last_state_.error == gpu::error::kNoError) {
- DLOG(ERROR) << "GPU state invalid after WaitForGetOffsetInRange.";
- InvalidGpuReply();
- }
-}
-
-void CommandBufferProxyImpl::SetGetBuffer(int32_t shm_id) {
- CheckLock();
- if (last_state_.error != gpu::error::kNoError)
- return;
-
- Send(new GpuCommandBufferMsg_SetGetBuffer(route_id_, shm_id));
- last_put_offset_ = -1;
-}
-
-scoped_refptr<gpu::Buffer> CommandBufferProxyImpl::CreateTransferBuffer(
- size_t size,
- int32_t* id) {
- CheckLock();
- *id = -1;
-
- if (last_state_.error != gpu::error::kNoError)
- return NULL;
-
- int32_t new_id = channel_->ReserveTransferBufferId();
-
- scoped_ptr<base::SharedMemory> shared_memory(
- channel_->factory()->AllocateSharedMemory(size));
- if (!shared_memory) {
- if (last_state_.error == gpu::error::kNoError)
- last_state_.error = gpu::error::kOutOfBounds;
- return NULL;
- }
-
- DCHECK(!shared_memory->memory());
- if (!shared_memory->Map(size)) {
- if (last_state_.error == gpu::error::kNoError)
- last_state_.error = gpu::error::kOutOfBounds;
- return NULL;
- }
-
- // This handle is owned by the GPU process and must be passed to it or it
- // will leak. In otherwords, do not early out on error between here and the
- // sending of the RegisterTransferBuffer IPC below.
- base::SharedMemoryHandle handle =
- channel_->ShareToGpuProcess(shared_memory->handle());
- if (!base::SharedMemory::IsHandleValid(handle)) {
- if (last_state_.error == gpu::error::kNoError)
- last_state_.error = gpu::error::kLostContext;
- return NULL;
- }
-
- if (!Send(new GpuCommandBufferMsg_RegisterTransferBuffer(route_id_,
- new_id,
- handle,
- size))) {
- return NULL;
- }
-
- *id = new_id;
- scoped_refptr<gpu::Buffer> buffer(
- gpu::MakeBufferFromSharedMemory(std::move(shared_memory), size));
- return buffer;
-}
-
-void CommandBufferProxyImpl::DestroyTransferBuffer(int32_t id) {
- CheckLock();
- if (last_state_.error != gpu::error::kNoError)
- return;
-
- Send(new GpuCommandBufferMsg_DestroyTransferBuffer(route_id_, id));
-}
-
-gpu::Capabilities CommandBufferProxyImpl::GetCapabilities() {
- return capabilities_;
-}
-
-int32_t CommandBufferProxyImpl::CreateImage(ClientBuffer buffer,
- size_t width,
- size_t height,
- unsigned internal_format) {
- CheckLock();
- if (last_state_.error != gpu::error::kNoError)
- return -1;
-
- int32_t new_id = channel_->ReserveImageId();
-
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager =
- channel_->gpu_memory_buffer_manager();
- gfx::GpuMemoryBuffer* gpu_memory_buffer =
- gpu_memory_buffer_manager->GpuMemoryBufferFromClientBuffer(buffer);
- DCHECK(gpu_memory_buffer);
-
- // This handle is owned by the GPU process and must be passed to it or it
- // will leak. In otherwords, do not early out on error between here and the
- // sending of the CreateImage IPC below.
- bool requires_sync_token = false;
- gfx::GpuMemoryBufferHandle handle =
- channel_->ShareGpuMemoryBufferToGpuProcess(gpu_memory_buffer->GetHandle(),
- &requires_sync_token);
-
- uint64_t image_fence_sync = 0;
- if (requires_sync_token) {
- image_fence_sync = GenerateFenceSyncRelease();
-
- // Make sure fence syncs were flushed before CreateImage() was called.
- DCHECK_LE(image_fence_sync - 1, flushed_fence_sync_release_);
- }
-
- DCHECK(gpu::ImageFactory::IsGpuMemoryBufferFormatSupported(
- gpu_memory_buffer->GetFormat(), capabilities_));
- DCHECK(gpu::ImageFactory::IsImageSizeValidForGpuMemoryBufferFormat(
- gfx::Size(width, height), gpu_memory_buffer->GetFormat()));
- DCHECK(gpu::ImageFactory::IsImageFormatCompatibleWithGpuMemoryBufferFormat(
- internal_format, gpu_memory_buffer->GetFormat()));
-
- GpuCommandBufferMsg_CreateImage_Params params;
- params.id = new_id;
- params.gpu_memory_buffer = handle;
- params.size = gfx::Size(width, height);
- params.format = gpu_memory_buffer->GetFormat();
- params.internal_format = internal_format;
- params.image_release_count = image_fence_sync;
-
- if (!Send(new GpuCommandBufferMsg_CreateImage(route_id_, params)))
- return -1;
-
- if (image_fence_sync) {
- gpu::SyncToken sync_token(GetNamespaceID(), GetExtraCommandBufferData(),
- GetCommandBufferID(), image_fence_sync);
-
- // Force a synchronous IPC to validate sync token.
- EnsureWorkVisible();
- sync_token.SetVerifyFlush();
-
- gpu_memory_buffer_manager->SetDestructionSyncToken(gpu_memory_buffer,
- sync_token);
- }
-
- return new_id;
-}
-
-void CommandBufferProxyImpl::DestroyImage(int32_t id) {
- CheckLock();
- if (last_state_.error != gpu::error::kNoError)
- return;
-
- Send(new GpuCommandBufferMsg_DestroyImage(route_id_, id));
-}
-
-int32_t CommandBufferProxyImpl::CreateGpuMemoryBufferImage(
- size_t width,
- size_t height,
- unsigned internal_format,
- unsigned usage) {
- CheckLock();
- scoped_ptr<gfx::GpuMemoryBuffer> buffer(
- channel_->gpu_memory_buffer_manager()->AllocateGpuMemoryBuffer(
- gfx::Size(width, height),
- gpu::ImageFactory::DefaultBufferFormatForImageFormat(internal_format),
- gfx::BufferUsage::SCANOUT));
- if (!buffer)
- return -1;
-
- return CreateImage(buffer->AsClientBuffer(), width, height, internal_format);
-}
-
-uint32_t CommandBufferProxyImpl::CreateStreamTexture(uint32_t texture_id) {
- CheckLock();
- if (last_state_.error != gpu::error::kNoError)
- return 0;
-
- int32_t stream_id = channel_->GenerateRouteID();
- bool succeeded = false;
- Send(new GpuCommandBufferMsg_CreateStreamTexture(
- route_id_, texture_id, stream_id, &succeeded));
- if (!succeeded) {
- DLOG(ERROR) << "GpuCommandBufferMsg_CreateStreamTexture returned failure";
- return 0;
- }
- return stream_id;
-}
-
-void CommandBufferProxyImpl::SetLock(base::Lock* lock) {
- lock_ = lock;
-}
-
-bool CommandBufferProxyImpl::IsGpuChannelLost() {
- return !channel_ || channel_->IsLost();
-}
-
-void CommandBufferProxyImpl::EnsureWorkVisible() {
- if (channel_)
- channel_->ValidateFlushIDReachedServer(stream_id_, true);
-}
-
-gpu::CommandBufferNamespace CommandBufferProxyImpl::GetNamespaceID() const {
- return gpu::CommandBufferNamespace::GPU_IO;
-}
-
-uint64_t CommandBufferProxyImpl::GetCommandBufferID() const {
- return command_buffer_id_;
-}
-
-int32_t CommandBufferProxyImpl::GetExtraCommandBufferData() const {
- return stream_id_;
-}
-
-uint64_t CommandBufferProxyImpl::GenerateFenceSyncRelease() {
- return next_fence_sync_release_++;
-}
-
-bool CommandBufferProxyImpl::IsFenceSyncRelease(uint64_t release) {
- return release != 0 && release < next_fence_sync_release_;
-}
-
-bool CommandBufferProxyImpl::IsFenceSyncFlushed(uint64_t release) {
- return release != 0 && release <= flushed_fence_sync_release_;
-}
-
-bool CommandBufferProxyImpl::IsFenceSyncFlushReceived(uint64_t release) {
- CheckLock();
- if (last_state_.error != gpu::error::kNoError)
- return false;
-
- if (release <= verified_fence_sync_release_)
- return true;
-
- // Check if we have actually flushed the fence sync release.
- if (release <= flushed_fence_sync_release_) {
- DCHECK(!flushed_release_flush_id_.empty());
- // Check if it has already been validated by another context.
- UpdateVerifiedReleases(channel_->GetHighestValidatedFlushID(stream_id_));
- if (release <= verified_fence_sync_release_)
- return true;
-
- // Has not been validated, validate it now.
- UpdateVerifiedReleases(
- channel_->ValidateFlushIDReachedServer(stream_id_, false));
- return release <= verified_fence_sync_release_;
- }
-
- return false;
-}
-
-void CommandBufferProxyImpl::SignalSyncToken(const gpu::SyncToken& sync_token,
- const base::Closure& callback) {
- CheckLock();
- if (last_state_.error != gpu::error::kNoError)
- return;
-
- uint32_t signal_id = next_signal_id_++;
- if (!Send(new GpuCommandBufferMsg_SignalSyncToken(route_id_,
- sync_token,
- signal_id))) {
- return;
- }
-
- signal_tasks_.insert(std::make_pair(signal_id, callback));
-}
-
-bool CommandBufferProxyImpl::CanWaitUnverifiedSyncToken(
- const gpu::SyncToken* sync_token) {
- // Can only wait on an unverified sync token if it is from the same channel.
- const uint64_t token_channel = sync_token->command_buffer_id() >> 32;
- const uint64_t channel = command_buffer_id_ >> 32;
- if (sync_token->namespace_id() != gpu::CommandBufferNamespace::GPU_IO ||
- token_channel != channel) {
- return false;
- }
-
- // If waiting on a different stream, flush pending commands on that stream.
- const int32_t release_stream_id = sync_token->extra_data_field();
- if (release_stream_id == 0)
- return false;
-
- if (release_stream_id != stream_id_)
- channel_->FlushPendingStream(release_stream_id);
-
- return true;
-}
-
-uint32_t CommandBufferProxyImpl::InsertSyncPoint() {
- CheckLock();
- if (last_state_.error != gpu::error::kNoError)
- return 0;
-
- uint32_t sync_point = 0;
- Send(new GpuCommandBufferMsg_InsertSyncPoint(route_id_, true, &sync_point));
- return sync_point;
-}
-
-uint32_t CommandBufferProxyImpl::InsertFutureSyncPoint() {
- CheckLock();
- if (last_state_.error != gpu::error::kNoError)
- return 0;
-
- uint32_t sync_point = 0;
- Send(new GpuCommandBufferMsg_InsertSyncPoint(route_id_, false, &sync_point));
- return sync_point;
-}
-
-void CommandBufferProxyImpl::RetireSyncPoint(uint32_t sync_point) {
- CheckLock();
- if (last_state_.error != gpu::error::kNoError)
- return;
-
- Send(new GpuCommandBufferMsg_RetireSyncPoint(route_id_, sync_point));
-}
-
-void CommandBufferProxyImpl::SignalSyncPoint(uint32_t sync_point,
- const base::Closure& callback) {
- CheckLock();
- if (last_state_.error != gpu::error::kNoError)
- return;
-
- uint32_t signal_id = next_signal_id_++;
- if (!Send(new GpuCommandBufferMsg_SignalSyncPoint(route_id_,
- sync_point,
- signal_id))) {
- return;
- }
-
- signal_tasks_.insert(std::make_pair(signal_id, callback));
-}
-
-void CommandBufferProxyImpl::SignalQuery(uint32_t query,
- const base::Closure& callback) {
- CheckLock();
- if (last_state_.error != gpu::error::kNoError)
- return;
-
- // Signal identifiers are hidden, so nobody outside of this class will see
- // them. (And thus, they cannot save them.) The IDs themselves only last
- // until the callback is invoked, which will happen as soon as the GPU
- // catches upwith the command buffer.
- // A malicious caller trying to create a collision by making next_signal_id
- // would have to make calls at an astounding rate (300B/s) and even if they
- // could do that, all they would do is to prevent some callbacks from getting
- // called, leading to stalled threads and/or memory leaks.
- uint32_t signal_id = next_signal_id_++;
- if (!Send(new GpuCommandBufferMsg_SignalQuery(route_id_,
- query,
- signal_id))) {
- return;
- }
-
- signal_tasks_.insert(std::make_pair(signal_id, callback));
-}
-
-bool CommandBufferProxyImpl::ProduceFrontBuffer(const gpu::Mailbox& mailbox) {
- CheckLock();
- if (last_state_.error != gpu::error::kNoError)
- return false;
-
- return Send(new GpuCommandBufferMsg_ProduceFrontBuffer(route_id_, mailbox));
-}
-
-scoped_ptr<media::VideoDecodeAccelerator>
-CommandBufferProxyImpl::CreateVideoDecoder() {
- if (!channel_)
- return scoped_ptr<media::VideoDecodeAccelerator>();
- return scoped_ptr<media::VideoDecodeAccelerator>(
- new GpuVideoDecodeAcceleratorHost(channel_, this));
-}
-
-scoped_ptr<media::VideoEncodeAccelerator>
-CommandBufferProxyImpl::CreateVideoEncoder() {
- if (!channel_)
- return scoped_ptr<media::VideoEncodeAccelerator>();
- return scoped_ptr<media::VideoEncodeAccelerator>(
- new GpuVideoEncodeAcceleratorHost(channel_, this));
-}
-
-gpu::error::Error CommandBufferProxyImpl::GetLastError() {
- return last_state_.error;
-}
-
-bool CommandBufferProxyImpl::Send(IPC::Message* msg) {
- // Caller should not intentionally send a message if the context is lost.
- DCHECK(last_state_.error == gpu::error::kNoError);
-
- if (channel_) {
- if (channel_->Send(msg)) {
- return true;
- } else {
- // Flag the command buffer as lost. Defer deleting the channel until
- // OnChannelError is called after returning to the message loop in case
- // it is referenced elsewhere.
- DVLOG(1) << "CommandBufferProxyImpl::Send failed. Losing context.";
- last_state_.error = gpu::error::kLostContext;
- return false;
- }
- }
-
- // Callee takes ownership of message, regardless of whether Send is
- // successful. See IPC::Sender.
- delete msg;
- return false;
-}
-
-void CommandBufferProxyImpl::OnUpdateState(
- const gpu::CommandBuffer::State& state) {
- // Handle wraparound. It works as long as we don't have more than 2B state
- // updates in flight across which reordering occurs.
- if (state.generation - last_state_.generation < 0x80000000U)
- last_state_ = state;
-}
-
-void CommandBufferProxyImpl::SetOnConsoleMessageCallback(
- const GpuConsoleMessageCallback& callback) {
- CheckLock();
- console_message_callback_ = callback;
-}
-
-void CommandBufferProxyImpl::TryUpdateState() {
- if (last_state_.error == gpu::error::kNoError)
- shared_state()->Read(&last_state_);
-}
-
-void CommandBufferProxyImpl::UpdateVerifiedReleases(uint32_t verified_flush) {
- while (!flushed_release_flush_id_.empty()) {
- const std::pair<uint64_t, uint32_t>& front_item =
- flushed_release_flush_id_.front();
- if (front_item.second > verified_flush)
- break;
- verified_fence_sync_release_ = front_item.first;
- flushed_release_flush_id_.pop();
- }
-}
-
-gpu::CommandBufferSharedState* CommandBufferProxyImpl::shared_state() const {
- return reinterpret_cast<gpu::CommandBufferSharedState*>(
- shared_state_shm_->memory());
-}
-
-void CommandBufferProxyImpl::OnSwapBuffersCompleted(
- const std::vector<ui::LatencyInfo>& latency_info,
- gfx::SwapResult result) {
- if (!swap_buffers_completion_callback_.is_null()) {
- if (!ui::LatencyInfo::Verify(
- latency_info, "CommandBufferProxyImpl::OnSwapBuffersCompleted")) {
- swap_buffers_completion_callback_.Run(std::vector<ui::LatencyInfo>(),
- result);
- return;
- }
- swap_buffers_completion_callback_.Run(latency_info, result);
- }
-}
-
-void CommandBufferProxyImpl::OnUpdateVSyncParameters(base::TimeTicks timebase,
- base::TimeDelta interval) {
- if (!update_vsync_parameters_completion_callback_.is_null())
- update_vsync_parameters_completion_callback_.Run(timebase, interval);
-}
-
-void CommandBufferProxyImpl::InvalidGpuMessage() {
- LOG(ERROR) << "Received invalid message from the GPU process.";
- OnDestroyed(gpu::error::kInvalidGpuMessage, gpu::error::kLostContext);
-}
-
-void CommandBufferProxyImpl::InvalidGpuReply() {
- CheckLock();
- LOG(ERROR) << "Received invalid reply from the GPU process.";
- last_state_.error = gpu::error::kLostContext;
- last_state_.context_lost_reason = gpu::error::kInvalidGpuMessage;
- callback_thread_->PostTask(
- FROM_HERE,
- base::Bind(&CommandBufferProxyImpl::InvalidGpuReplyOnClientThread,
- weak_this_));
-}
-
-void CommandBufferProxyImpl::InvalidGpuReplyOnClientThread() {
- scoped_ptr<base::AutoLock> lock;
- if (lock_)
- lock.reset(new base::AutoLock(*lock_));
- OnDestroyed(gpu::error::kInvalidGpuMessage, gpu::error::kLostContext);
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/client/command_buffer_proxy_impl.h b/chromium/content/common/gpu/client/command_buffer_proxy_impl.h
deleted file mode 100644
index 17589a7538e..00000000000
--- a/chromium/content/common/gpu/client/command_buffer_proxy_impl.h
+++ /dev/null
@@ -1,279 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_CLIENT_COMMAND_BUFFER_PROXY_IMPL_H_
-#define CONTENT_COMMON_GPU_CLIENT_COMMAND_BUFFER_PROXY_IMPL_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <map>
-#include <queue>
-#include <string>
-
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/containers/hash_tables.h"
-#include "base/containers/scoped_ptr_hash_map.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
-#include "gpu/command_buffer/client/gpu_control.h"
-#include "gpu/command_buffer/common/command_buffer.h"
-#include "gpu/command_buffer/common/command_buffer_shared.h"
-#include "gpu/command_buffer/common/gpu_memory_allocation.h"
-#include "ipc/ipc_listener.h"
-#include "ui/events/latency_info.h"
-#include "ui/gfx/swap_result.h"
-
-struct GPUCommandBufferConsoleMessage;
-
-namespace base {
-class SharedMemory;
-}
-
-namespace gpu {
-struct Mailbox;
-struct SyncToken;
-}
-
-namespace media {
-class VideoDecodeAccelerator;
-class VideoEncodeAccelerator;
-}
-
-namespace content {
-class GpuChannelHost;
-
-// Client side proxy that forwards messages synchronously to a
-// CommandBufferStub.
-class CommandBufferProxyImpl
- : public gpu::CommandBuffer,
- public gpu::GpuControl,
- public IPC::Listener,
- public base::SupportsWeakPtr<CommandBufferProxyImpl> {
- public:
- class DeletionObserver {
- public:
- // Called during the destruction of the CommandBufferProxyImpl.
- virtual void OnWillDeleteImpl() = 0;
-
- protected:
- virtual ~DeletionObserver() {}
- };
-
- typedef base::Callback<void(
- const std::string& msg, int id)> GpuConsoleMessageCallback;
-
- CommandBufferProxyImpl(GpuChannelHost* channel,
- int32_t route_id,
- int32_t stream_id);
- ~CommandBufferProxyImpl() override;
-
- // Sends an IPC message to create a GpuVideoDecodeAccelerator. Creates and
- // returns it as an owned pointer to a media::VideoDecodeAccelerator. Returns
- // NULL on failure to create the GpuVideoDecodeAcceleratorHost.
- // Note that the GpuVideoDecodeAccelerator may still fail to be created in
- // the GPU process, even if this returns non-NULL. In this case the VDA client
- // is notified of an error later, after Initialize().
- scoped_ptr<media::VideoDecodeAccelerator> CreateVideoDecoder();
-
- // Sends an IPC message to create a GpuVideoEncodeAccelerator. Creates and
- // returns it as an owned pointer to a media::VideoEncodeAccelerator. Returns
- // NULL on failure to create the GpuVideoEncodeAcceleratorHost.
- // Note that the GpuVideoEncodeAccelerator may still fail to be created in
- // the GPU process, even if this returns non-NULL. In this case the VEA client
- // is notified of an error later, after Initialize();
- scoped_ptr<media::VideoEncodeAccelerator> CreateVideoEncoder();
-
- // IPC::Listener implementation:
- bool OnMessageReceived(const IPC::Message& message) override;
- void OnChannelError() override;
-
- // CommandBuffer implementation:
- bool Initialize() override;
- State GetLastState() override;
- int32_t GetLastToken() override;
- void Flush(int32_t put_offset) override;
- void OrderingBarrier(int32_t put_offset) override;
- void WaitForTokenInRange(int32_t start, int32_t end) override;
- void WaitForGetOffsetInRange(int32_t start, int32_t end) override;
- void SetGetBuffer(int32_t shm_id) override;
- scoped_refptr<gpu::Buffer> CreateTransferBuffer(size_t size,
- int32_t* id) override;
- void DestroyTransferBuffer(int32_t id) override;
-
- // gpu::GpuControl implementation:
- gpu::Capabilities GetCapabilities() override;
- int32_t CreateImage(ClientBuffer buffer,
- size_t width,
- size_t height,
- unsigned internal_format) override;
- void DestroyImage(int32_t id) override;
- int32_t CreateGpuMemoryBufferImage(size_t width,
- size_t height,
- unsigned internal_format,
- unsigned usage) override;
- uint32_t InsertSyncPoint() override;
- uint32_t InsertFutureSyncPoint() override;
- void RetireSyncPoint(uint32_t sync_point) override;
- void SignalSyncPoint(uint32_t sync_point,
- const base::Closure& callback) override;
- void SignalQuery(uint32_t query, const base::Closure& callback) override;
- void SetLock(base::Lock* lock) override;
- bool IsGpuChannelLost() override;
- void EnsureWorkVisible() override;
- gpu::CommandBufferNamespace GetNamespaceID() const override;
- uint64_t GetCommandBufferID() const override;
- int32_t GetExtraCommandBufferData() const override;
- uint64_t GenerateFenceSyncRelease() override;
- bool IsFenceSyncRelease(uint64_t release) override;
- bool IsFenceSyncFlushed(uint64_t release) override;
- bool IsFenceSyncFlushReceived(uint64_t release) override;
- void SignalSyncToken(const gpu::SyncToken& sync_token,
- const base::Closure& callback) override;
- bool CanWaitUnverifiedSyncToken(const gpu::SyncToken* sync_token) override;
-
- bool ProduceFrontBuffer(const gpu::Mailbox& mailbox);
- void SetContextLostCallback(const base::Closure& callback);
-
- void AddDeletionObserver(DeletionObserver* observer);
- void RemoveDeletionObserver(DeletionObserver* observer);
-
- bool EnsureBackbuffer();
-
- void SetOnConsoleMessageCallback(
- const GpuConsoleMessageCallback& callback);
-
- void SetLatencyInfo(const std::vector<ui::LatencyInfo>& latency_info);
- using SwapBuffersCompletionCallback =
- base::Callback<void(const std::vector<ui::LatencyInfo>& latency_info,
- gfx::SwapResult result)>;
- void SetSwapBuffersCompletionCallback(
- const SwapBuffersCompletionCallback& callback);
-
- using UpdateVSyncParametersCallback =
- base::Callback<void(base::TimeTicks timebase, base::TimeDelta interval)>;
- void SetUpdateVSyncParametersCallback(
- const UpdateVSyncParametersCallback& callback);
-
- // TODO(apatrick): this is a temporary optimization while skia is calling
- // ContentGLContext::MakeCurrent prior to every GL call. It saves returning 6
- // ints redundantly when only the error is needed for the
- // CommandBufferProxyImpl implementation.
- gpu::error::Error GetLastError() override;
-
- int32_t route_id() const { return route_id_; }
-
- int32_t stream_id() const { return stream_id_; }
-
- GpuChannelHost* channel() const { return channel_; }
-
- base::SharedMemoryHandle GetSharedStateHandle() const {
- return shared_state_shm_->handle();
- }
- uint32_t CreateStreamTexture(uint32_t texture_id);
-
- private:
- typedef std::map<int32_t, scoped_refptr<gpu::Buffer>> TransferBufferMap;
- typedef base::hash_map<uint32_t, base::Closure> SignalTaskMap;
-
- void CheckLock() {
- if (lock_)
- lock_->AssertAcquired();
- }
-
- // Send an IPC message over the GPU channel. This is private to fully
- // encapsulate the channel; all callers of this function must explicitly
- // verify that the context has not been lost.
- bool Send(IPC::Message* msg);
-
- // Message handlers:
- void OnUpdateState(const gpu::CommandBuffer::State& state);
- void OnDestroyed(gpu::error::ContextLostReason reason,
- gpu::error::Error error);
- void OnConsoleMessage(const GPUCommandBufferConsoleMessage& message);
- void OnSignalAck(uint32_t id);
- void OnSwapBuffersCompleted(const std::vector<ui::LatencyInfo>& latency_info,
- gfx::SwapResult result);
- void OnUpdateVSyncParameters(base::TimeTicks timebase,
- base::TimeDelta interval);
-
- // Try to read an updated copy of the state from shared memory.
- void TryUpdateState();
-
- // Updates the highest verified release fence sync.
- void UpdateVerifiedReleases(uint32_t verified_flush);
-
- // Loses the context after we received an invalid message from the GPU
- // process. Will call the lost context callback reentrantly if any.
- void InvalidGpuMessage();
-
- // Loses the context after we received an invalid reply from the GPU
- // process. Will post a task to call the lost context callback if any.
- void InvalidGpuReply();
-
- void InvalidGpuReplyOnClientThread();
-
- // The shared memory area used to update state.
- gpu::CommandBufferSharedState* shared_state() const;
-
- base::Lock* lock_;
-
- // Unowned list of DeletionObservers.
- base::ObserverList<DeletionObserver> deletion_observers_;
-
- // The last cached state received from the service.
- State last_state_;
-
- // The shared memory area used to update state.
- scoped_ptr<base::SharedMemory> shared_state_shm_;
-
- // |*this| is owned by |*channel_| and so is always outlived by it, so using a
- // raw pointer is ok.
- GpuChannelHost* channel_;
- const uint64_t command_buffer_id_;
- const int32_t route_id_;
- const int32_t stream_id_;
- uint32_t flush_count_;
- int32_t last_put_offset_;
- int32_t last_barrier_put_offset_;
-
- // Next generated fence sync.
- uint64_t next_fence_sync_release_;
-
- // Unverified flushed fence syncs with their corresponding flush id.
- std::queue<std::pair<uint64_t, uint32_t>> flushed_release_flush_id_;
-
- // Last flushed fence sync release, same as last item in queue if not empty.
- uint64_t flushed_fence_sync_release_;
-
- // Last verified fence sync.
- uint64_t verified_fence_sync_release_;
-
- base::Closure context_lost_callback_;
-
- GpuConsoleMessageCallback console_message_callback_;
-
- // Tasks to be invoked in SignalSyncPoint responses.
- uint32_t next_signal_id_;
- SignalTaskMap signal_tasks_;
-
- gpu::Capabilities capabilities_;
-
- std::vector<ui::LatencyInfo> latency_info_;
-
- SwapBuffersCompletionCallback swap_buffers_completion_callback_;
- UpdateVSyncParametersCallback update_vsync_parameters_completion_callback_;
-
- base::WeakPtr<CommandBufferProxyImpl> weak_this_;
- scoped_refptr<base::SequencedTaskRunner> callback_thread_;
-
- DISALLOW_COPY_AND_ASSIGN(CommandBufferProxyImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_CLIENT_COMMAND_BUFFER_PROXY_IMPL_H_
diff --git a/chromium/content/common/gpu/client/context_provider_command_buffer.cc b/chromium/content/common/gpu/client/context_provider_command_buffer.cc
index 2560d78067b..7ef9e73294e 100644
--- a/chromium/content/common/gpu/client/context_provider_command_buffer.cc
+++ b/chromium/content/common/gpu/client/context_provider_command_buffer.cc
@@ -12,7 +12,7 @@
#include "base/callback_helpers.h"
#include "base/strings/stringprintf.h"
#include "cc/output/managed_memory_policy.h"
-#include "content/common/gpu/client/grcontext_for_webgraphicscontext3d.h"
+#include "content/common/gpu/client/grcontext_for_gles2_interface.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "third_party/skia/include/gpu/GrContext.h"
@@ -23,11 +23,11 @@ class ContextProviderCommandBuffer::LostContextCallbackProxy
public:
explicit LostContextCallbackProxy(ContextProviderCommandBuffer* provider)
: provider_(provider) {
- provider_->WebContext3DNoChecks()->setContextLostCallback(this);
+ provider_->context3d_->setContextLostCallback(this);
}
~LostContextCallbackProxy() override {
- provider_->WebContext3DNoChecks()->setContextLostCallback(NULL);
+ provider_->context3d_->setContextLostCallback(NULL);
}
void onContextLost() override { provider_->OnLostContext(); }
@@ -49,12 +49,11 @@ ContextProviderCommandBuffer::Create(
ContextProviderCommandBuffer::ContextProviderCommandBuffer(
scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context3d,
CommandBufferContextType type)
- : context_type_(type),
+ : context3d_(std::move(context3d)),
+ context_type_(type),
debug_name_(CommandBufferContextTypeToString(type)) {
- gr_interface_ = skia::AdoptRef(
- new GrGLInterfaceForWebGraphicsContext3D(std::move(context3d)));
DCHECK(main_thread_checker_.CalledOnValidThread());
- DCHECK(gr_interface_->WebContext3D());
+ DCHECK(context3d_);
context_thread_checker_.DetachFromThread();
}
@@ -63,52 +62,42 @@ ContextProviderCommandBuffer::~ContextProviderCommandBuffer() {
context_thread_checker_.CalledOnValidThread());
// Destroy references to the context3d_ before leaking it.
- if (WebContext3DNoChecks()->GetCommandBufferProxy())
- WebContext3DNoChecks()->GetCommandBufferProxy()->SetLock(nullptr);
+ if (context3d_->GetCommandBufferProxy())
+ context3d_->GetCommandBufferProxy()->SetLock(nullptr);
lost_context_callback_proxy_.reset();
}
-
-CommandBufferProxyImpl* ContextProviderCommandBuffer::GetCommandBufferProxy() {
- return WebContext3DNoChecks()->GetCommandBufferProxy();
+gpu::CommandBufferProxyImpl*
+ContextProviderCommandBuffer::GetCommandBufferProxy() {
+ return context3d_->GetCommandBufferProxy();
}
WebGraphicsContext3DCommandBufferImpl*
ContextProviderCommandBuffer::WebContext3D() {
- DCHECK(gr_interface_);
- DCHECK(gr_interface_->WebContext3D());
+ DCHECK(context3d_);
DCHECK(lost_context_callback_proxy_); // Is bound to thread.
DCHECK(context_thread_checker_.CalledOnValidThread());
- return WebContext3DNoChecks();
-}
-
-WebGraphicsContext3DCommandBufferImpl*
- ContextProviderCommandBuffer::WebContext3DNoChecks() {
- DCHECK(gr_interface_);
- return static_cast<WebGraphicsContext3DCommandBufferImpl*>(
- gr_interface_->WebContext3D());
+ return context3d_.get();
}
bool ContextProviderCommandBuffer::BindToCurrentThread() {
// This is called on the thread the context will be used.
DCHECK(context_thread_checker_.CalledOnValidThread());
- DCHECK(gr_interface_ && gr_interface_->WebContext3D());
if (lost_context_callback_proxy_)
return true;
- WebContext3DNoChecks()->SetContextType(context_type_);
- if (!WebContext3DNoChecks()->InitializeOnCurrentThread())
+ context3d_->SetContextType(context_type_);
+ if (!context3d_->InitializeOnCurrentThread())
return false;
- gr_interface_->BindToCurrentThread();
InitializeCapabilities();
std::string unique_context_name =
- base::StringPrintf("%s-%p", debug_name_.c_str(), WebContext3DNoChecks());
- WebContext3DNoChecks()->traceBeginCHROMIUM("gpu_toplevel",
- unique_context_name.c_str());
+ base::StringPrintf("%s-%p", debug_name_.c_str(), context3d_.get());
+ context3d_->GetGLInterface()->TraceBeginCHROMIUM("gpu_toplevel",
+ unique_context_name.c_str());
lost_context_callback_proxy_.reset(new LostContextCallbackProxy(this));
return true;
@@ -119,13 +108,15 @@ void ContextProviderCommandBuffer::DetachFromThread() {
}
gpu::gles2::GLES2Interface* ContextProviderCommandBuffer::ContextGL() {
+ DCHECK(context3d_);
DCHECK(lost_context_callback_proxy_); // Is bound to thread.
+ DCHECK(context_thread_checker_.CalledOnValidThread());
- return WebContext3D()->GetImplementation();
+ return context3d_->GetImplementation();
}
gpu::ContextSupport* ContextProviderCommandBuffer::ContextSupport() {
- return WebContext3DNoChecks()->GetContextSupport();
+ return context3d_->GetContextSupport();
}
class GrContext* ContextProviderCommandBuffer::GrContext() {
@@ -135,7 +126,8 @@ class GrContext* ContextProviderCommandBuffer::GrContext() {
if (gr_context_)
return gr_context_->get();
- gr_context_.reset(new GrContextForWebGraphicsContext3D(gr_interface_));
+ gr_context_.reset(
+ new GrContextForGLES2Interface(context3d_->GetGLInterface()));
// If GlContext is already lost, also abandon the new GrContext.
if (gr_context_->get() &&
@@ -154,7 +146,8 @@ void ContextProviderCommandBuffer::InvalidateGrContext(uint32_t state) {
}
void ContextProviderCommandBuffer::SetupLock() {
- WebContext3D()->GetCommandBufferProxy()->SetLock(&context_lock_);
+ DCHECK(context3d_);
+ context3d_->GetCommandBufferProxy()->SetLock(&context_lock_);
}
base::Lock* ContextProviderCommandBuffer::GetLock() {
@@ -187,9 +180,9 @@ void ContextProviderCommandBuffer::OnLostContext() {
void ContextProviderCommandBuffer::InitializeCapabilities() {
Capabilities caps;
- caps.gpu = WebContext3DNoChecks()->GetImplementation()->capabilities();
+ caps.gpu = context3d_->GetImplementation()->capabilities();
- size_t mapped_memory_limit = WebContext3DNoChecks()->GetMappedMemoryLimit();
+ size_t mapped_memory_limit = context3d_->GetMappedMemoryLimit();
caps.max_transfer_buffer_usage_bytes =
mapped_memory_limit == WebGraphicsContext3DCommandBufferImpl::kNoLimit
? std::numeric_limits<size_t>::max() : mapped_memory_limit;
diff --git a/chromium/content/common/gpu/client/context_provider_command_buffer.h b/chromium/content/common/gpu/client/context_provider_command_buffer.h
index 564e76c4040..65b0e50dc7e 100644
--- a/chromium/content/common/gpu/client/context_provider_command_buffer.h
+++ b/chromium/content/common/gpu/client/context_provider_command_buffer.h
@@ -16,12 +16,10 @@
#include "content/common/content_export.h"
#include "content/common/gpu/client/command_buffer_metrics.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
-#include "skia/ext/refptr.h"
namespace content {
-class GrContextForWebGraphicsContext3D;
-class GrGLInterfaceForWebGraphicsContext3D;
+class GrContextForGLES2Interface;
// Implementation of cc::ContextProvider that provides a
// WebGraphicsContext3DCommandBufferImpl context and a GrContext.
@@ -32,7 +30,7 @@ class CONTENT_EXPORT ContextProviderCommandBuffer
scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context3d,
CommandBufferContextType type);
- CommandBufferProxyImpl* GetCommandBufferProxy();
+ gpu::CommandBufferProxyImpl* GetCommandBufferProxy();
// cc_blink::ContextProviderWebContext implementation.
WebGraphicsContext3DCommandBufferImpl* WebContext3D() override;
@@ -60,14 +58,13 @@ class CONTENT_EXPORT ContextProviderCommandBuffer
void OnLostContext();
private:
- WebGraphicsContext3DCommandBufferImpl* WebContext3DNoChecks();
void InitializeCapabilities();
base::ThreadChecker main_thread_checker_;
base::ThreadChecker context_thread_checker_;
- skia::RefPtr<GrGLInterfaceForWebGraphicsContext3D> gr_interface_;
- scoped_ptr<GrContextForWebGraphicsContext3D> gr_context_;
+ scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context3d_;
+ scoped_ptr<GrContextForGLES2Interface> gr_context_;
cc::ContextProvider::Capabilities capabilities_;
CommandBufferContextType context_type_;
@@ -78,7 +75,6 @@ class CONTENT_EXPORT ContextProviderCommandBuffer
base::Lock context_lock_;
class LostContextCallbackProxy;
- friend class LostContextCallbackProxy;
scoped_ptr<LostContextCallbackProxy> lost_context_callback_proxy_;
};
diff --git a/chromium/content/common/gpu/client/gl_helper_benchmark.cc b/chromium/content/common/gpu/client/gl_helper_benchmark.cc
deleted file mode 100644
index 9e751b37852..00000000000
--- a/chromium/content/common/gpu/client/gl_helper_benchmark.cc
+++ /dev/null
@@ -1,310 +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 looks like a unit test, but it contains benchmarks and test
-// utilities intended for manual evaluation of the scalers in
-// gl_helper*. These tests produce output in the form of files and printouts,
-// but cannot really "fail". There is no point in making these tests part
-// of any test automation run.
-
-#include <stddef.h>
-#include <stdio.h>
-#include <cmath>
-#include <string>
-#include <vector>
-
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <GLES2/gl2extchromium.h>
-
-#include "base/at_exit.h"
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/macros.h"
-#include "base/strings/stringprintf.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "content/common/gpu/client/gl_helper.h"
-#include "content/common/gpu/client/gl_helper_scaling.h"
-#include "content/public/test/unittest_test_suite.h"
-#include "content/test/content_test_suite.h"
-#include "gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkTypes.h"
-#include "ui/gfx/codec/png_codec.h"
-#include "ui/gl/gl_surface.h"
-
-#if defined(OS_MACOSX)
-#include "base/mac/scoped_nsautorelease_pool.h"
-#endif
-
-namespace content {
-
-using blink::WebGLId;
-using blink::WebGraphicsContext3D;
-
-content::GLHelper::ScalerQuality kQualities[] = {
- content::GLHelper::SCALER_QUALITY_BEST,
- content::GLHelper::SCALER_QUALITY_GOOD,
- content::GLHelper::SCALER_QUALITY_FAST,
-};
-
-const char *kQualityNames[] = {
- "best",
- "good",
- "fast",
-};
-
-class GLHelperTest : public testing::Test {
- protected:
- void SetUp() override {
- WebGraphicsContext3D::Attributes attributes;
- bool lose_context_when_out_of_memory = false;
- context_ = gpu_blink::WebGraphicsContext3DInProcessCommandBufferImpl::
- CreateOffscreenContext(attributes, lose_context_when_out_of_memory);
- context_->InitializeOnCurrentThread();
-
- helper_.reset(
- new content::GLHelper(context_->GetGLInterface(),
- context_->GetContextSupport()));
- helper_scaling_.reset(new content::GLHelperScaling(
- context_->GetGLInterface(),
- helper_.get()));
- }
-
- void TearDown() override {
- helper_scaling_.reset(NULL);
- helper_.reset(NULL);
- context_.reset(NULL);
- }
-
-
- void LoadPngFileToSkBitmap(const base::FilePath& filename,
- SkBitmap* bitmap) {
- std::string compressed;
- base::ReadFileToString(base::MakeAbsoluteFilePath(filename), &compressed);
- ASSERT_TRUE(compressed.size());
- ASSERT_TRUE(gfx::PNGCodec::Decode(
- reinterpret_cast<const unsigned char*>(compressed.data()),
- compressed.size(), bitmap));
- }
-
- // Save the image to a png file. Used to create the initial test files.
- void SaveToFile(SkBitmap* bitmap, const base::FilePath& filename) {
- std::vector<unsigned char> compressed;
- ASSERT_TRUE(gfx::PNGCodec::Encode(
- static_cast<unsigned char*>(bitmap->getPixels()),
- gfx::PNGCodec::FORMAT_BGRA,
- gfx::Size(bitmap->width(), bitmap->height()),
- static_cast<int>(bitmap->rowBytes()),
- true,
- std::vector<gfx::PNGCodec::Comment>(),
- &compressed));
- ASSERT_TRUE(compressed.size());
- FILE* f = base::OpenFile(filename, "wb");
- ASSERT_TRUE(f);
- ASSERT_EQ(fwrite(&*compressed.begin(), 1, compressed.size(), f),
- compressed.size());
- base::CloseFile(f);
- }
-
- scoped_ptr<gpu_blink::WebGraphicsContext3DInProcessCommandBufferImpl>
- context_;
- scoped_ptr<content::GLHelper> helper_;
- scoped_ptr<content::GLHelperScaling> helper_scaling_;
- std::deque<GLHelperScaling::ScaleOp> x_ops_, y_ops_;
-};
-
-
-TEST_F(GLHelperTest, ScaleBenchmark) {
- int output_sizes[] = { 1920, 1080,
- 1249, 720, // Output size on pixel
- 256, 144 };
- int input_sizes[] = { 3200, 2040,
- 2560, 1476, // Pixel tab size
- 1920, 1080,
- 1280, 720,
- 800, 480,
- 256, 144 };
-
- for (size_t q = 0; q < arraysize(kQualities); q++) {
- for (size_t outsize = 0;
- outsize < arraysize(output_sizes);
- outsize += 2) {
- for (size_t insize = 0;
- insize < arraysize(input_sizes);
- insize += 2) {
- WebGLId src_texture = context_->createTexture();
- WebGLId dst_texture = context_->createTexture();
- WebGLId framebuffer = context_->createFramebuffer();
- const gfx::Size src_size(input_sizes[insize],
- input_sizes[insize + 1]);
- const gfx::Size dst_size(output_sizes[outsize],
- output_sizes[outsize + 1]);
- SkBitmap input;
- input.allocN32Pixels(src_size.width(), src_size.height());
-
- SkBitmap output_pixels;
- output_pixels.allocN32Pixels(dst_size.width(), dst_size.height());
-
- context_->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
- context_->bindTexture(GL_TEXTURE_2D, dst_texture);
- context_->texImage2D(GL_TEXTURE_2D,
- 0,
- GL_RGBA,
- dst_size.width(),
- dst_size.height(),
- 0,
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- 0);
- context_->bindTexture(GL_TEXTURE_2D, src_texture);
- context_->texImage2D(GL_TEXTURE_2D,
- 0,
- GL_RGBA,
- src_size.width(),
- src_size.height(),
- 0,
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- input.getPixels());
-
- gfx::Rect src_subrect(0, 0,
- src_size.width(), src_size.height());
- scoped_ptr<content::GLHelper::ScalerInterface> scaler(
- helper_->CreateScaler(kQualities[q],
- src_size,
- src_subrect,
- dst_size,
- false,
- false));
- // Scale once beforehand before we start measuring.
- scaler->Scale(src_texture, dst_texture);
- context_->finish();
-
- base::TimeTicks start_time = base::TimeTicks::Now();
- int iterations = 0;
- base::TimeTicks end_time;
- while (true) {
- for (int i = 0; i < 50; i++) {
- iterations++;
- scaler->Scale(src_texture, dst_texture);
- context_->flush();
- }
- context_->finish();
- end_time = base::TimeTicks::Now();
- if (iterations > 2000) {
- break;
- }
- if ((end_time - start_time).InMillisecondsF() > 1000) {
- break;
- }
- }
- context_->deleteTexture(dst_texture);
- context_->deleteTexture(src_texture);
- context_->deleteFramebuffer(framebuffer);
-
- std::string name;
- name = base::StringPrintf("scale_%dx%d_to_%dx%d_%s",
- src_size.width(),
- src_size.height(),
- dst_size.width(),
- dst_size.height(),
- kQualityNames[q]);
-
- float ms = (end_time - start_time).InMillisecondsF() / iterations;
- printf("*RESULT gpu_scale_time: %s=%.2f ms\n", name.c_str(), ms);
- }
- }
- }
-}
-
-// This is more of a test utility than a test.
-// Put an PNG image called "testimage.png" in your
-// current directory, then run this test. It will
-// create testoutput_Q_P.png, where Q is the scaling
-// mode and P is the scaling percentage taken from
-// the table below.
-TEST_F(GLHelperTest, DISABLED_ScaleTestImage) {
- int percents[] = {
- 230,
- 180,
- 150,
- 110,
- 90,
- 70,
- 50,
- 49,
- 40,
- 20,
- 10,
- };
-
- SkBitmap input;
- LoadPngFileToSkBitmap(base::FilePath(
- FILE_PATH_LITERAL("testimage.png")), &input);
-
- WebGLId framebuffer = context_->createFramebuffer();
- WebGLId src_texture = context_->createTexture();
- const gfx::Size src_size(input.width(), input.height());
- context_->bindFramebuffer(GL_FRAMEBUFFER, framebuffer);
- context_->bindTexture(GL_TEXTURE_2D, src_texture);
- context_->texImage2D(GL_TEXTURE_2D,
- 0,
- GL_RGBA,
- src_size.width(),
- src_size.height(),
- 0,
- GL_RGBA,
- GL_UNSIGNED_BYTE,
- input.getPixels());
-
- for (size_t q = 0; q < arraysize(kQualities); q++) {
- for (size_t p = 0; p < arraysize(percents); p++) {
- const gfx::Size dst_size(input.width() * percents[p] / 100,
- input.height() * percents[p] / 100);
- WebGLId dst_texture = helper_->CopyAndScaleTexture(
- src_texture,
- src_size,
- dst_size,
- false,
- kQualities[q]);
-
- SkBitmap output_pixels;
- output_pixels.allocN32Pixels(dst_size.width(), dst_size.height());
-
- helper_->ReadbackTextureSync(
- dst_texture,
- gfx::Rect(0, 0,
- dst_size.width(),
- dst_size.height()),
- static_cast<unsigned char *>(output_pixels.getPixels()),
- kN32_SkColorType);
- context_->deleteTexture(dst_texture);
- std::string filename = base::StringPrintf("testoutput_%s_%d.ppm",
- kQualityNames[q],
- percents[p]);
- VLOG(0) << "Writing " << filename;
- SaveToFile(&output_pixels, base::FilePath::FromUTF8Unsafe(filename));
- }
- }
- context_->deleteTexture(src_texture);
- context_->deleteFramebuffer(framebuffer);
-}
-
-} // namespace
-
-// These tests needs to run against a proper GL environment, so we
-// need to set it up before we can run the tests.
-int main(int argc, char** argv) {
- base::CommandLine::Init(argc, argv);
- base::TestSuite* suite = new content::ContentTestSuite(argc, argv);
-#if defined(OS_MACOSX)
- base::mac::ScopedNSAutoreleasePool pool;
-#endif
- gfx::GLSurface::InitializeOneOff();
-
- return content::UnitTestTestSuite(suite).Run();
-}
diff --git a/chromium/content/common/gpu/client/gpu_channel_host.cc b/chromium/content/common/gpu/client/gpu_channel_host.cc
deleted file mode 100644
index 25328f45399..00000000000
--- a/chromium/content/common/gpu/client/gpu_channel_host.cc
+++ /dev/null
@@ -1,552 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/client/gpu_channel_host.h"
-
-#include <algorithm>
-#include <utility>
-
-#include "base/atomic_sequence_num.h"
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/single_thread_task_runner.h"
-#include "base/thread_task_runner_handle.h"
-#include "base/threading/thread_restrictions.h"
-#include "base/trace_event/trace_event.h"
-#include "build/build_config.h"
-#include "content/common/gpu/client/command_buffer_proxy_impl.h"
-#include "content/common/gpu/client/gpu_jpeg_decode_accelerator_host.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "ipc/ipc_sync_message_filter.h"
-#include "url/gurl.h"
-
-#if defined(OS_WIN) || defined(OS_MACOSX)
-#include "content/public/common/sandbox_init.h"
-#endif
-
-using base::AutoLock;
-
-namespace content {
-namespace {
-
-// Global atomic to generate unique transfer buffer IDs.
-base::StaticAtomicSequenceNumber g_next_transfer_buffer_id;
-
-} // namespace
-
-GpuChannelHost::StreamFlushInfo::StreamFlushInfo()
- : next_stream_flush_id(1),
- flushed_stream_flush_id(0),
- verified_stream_flush_id(0),
- flush_pending(false),
- route_id(MSG_ROUTING_NONE),
- put_offset(0),
- flush_count(0),
- flush_id(0) {}
-
-GpuChannelHost::StreamFlushInfo::~StreamFlushInfo() {}
-
-// static
-scoped_refptr<GpuChannelHost> GpuChannelHost::Create(
- GpuChannelHostFactory* factory,
- int channel_id,
- const gpu::GPUInfo& gpu_info,
- const IPC::ChannelHandle& channel_handle,
- base::WaitableEvent* shutdown_event,
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager) {
- DCHECK(factory->IsMainThread());
- scoped_refptr<GpuChannelHost> host =
- new GpuChannelHost(factory, channel_id, gpu_info,
- gpu_memory_buffer_manager);
- host->Connect(channel_handle, shutdown_event);
- return host;
-}
-
-GpuChannelHost::GpuChannelHost(
- GpuChannelHostFactory* factory,
- int channel_id,
- const gpu::GPUInfo& gpu_info,
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager)
- : factory_(factory),
- channel_id_(channel_id),
- gpu_info_(gpu_info),
- gpu_memory_buffer_manager_(gpu_memory_buffer_manager) {
- next_image_id_.GetNext();
- next_route_id_.GetNext();
- next_stream_id_.GetNext();
-}
-
-void GpuChannelHost::Connect(const IPC::ChannelHandle& channel_handle,
- base::WaitableEvent* shutdown_event) {
- DCHECK(factory_->IsMainThread());
- // Open a channel to the GPU process. We pass NULL as the main listener here
- // since we need to filter everything to route it to the right thread.
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner =
- factory_->GetIOThreadTaskRunner();
- channel_ =
- IPC::SyncChannel::Create(channel_handle, IPC::Channel::MODE_CLIENT, NULL,
- io_task_runner.get(), true, shutdown_event);
-
- sync_filter_ = channel_->CreateSyncMessageFilter();
-
- channel_filter_ = new MessageFilter();
-
- // Install the filter last, because we intercept all leftover
- // messages.
- channel_->AddFilter(channel_filter_.get());
-}
-
-bool GpuChannelHost::Send(IPC::Message* msg) {
- // Callee takes ownership of message, regardless of whether Send is
- // successful. See IPC::Sender.
- scoped_ptr<IPC::Message> message(msg);
- // The GPU process never sends synchronous IPCs so clear the unblock flag to
- // preserve order.
- message->set_unblock(false);
-
- // Currently we need to choose between two different mechanisms for sending.
- // On the main thread we use the regular channel Send() method, on another
- // thread we use SyncMessageFilter. We also have to be careful interpreting
- // IsMainThread() since it might return false during shutdown,
- // impl we are actually calling from the main thread (discard message then).
- //
- // TODO: Can we just always use sync_filter_ since we setup the channel
- // without a main listener?
- if (factory_->IsMainThread()) {
- // channel_ is only modified on the main thread, so we don't need to take a
- // lock here.
- if (!channel_) {
- DVLOG(1) << "GpuChannelHost::Send failed: Channel already destroyed";
- return false;
- }
- // http://crbug.com/125264
- base::ThreadRestrictions::ScopedAllowWait allow_wait;
- bool result = channel_->Send(message.release());
- if (!result)
- DVLOG(1) << "GpuChannelHost::Send failed: Channel::Send failed";
- return result;
- }
-
- bool result = sync_filter_->Send(message.release());
- return result;
-}
-
-uint32_t GpuChannelHost::OrderingBarrier(
- int32_t route_id,
- int32_t stream_id,
- int32_t put_offset,
- uint32_t flush_count,
- const std::vector<ui::LatencyInfo>& latency_info,
- bool put_offset_changed,
- bool do_flush) {
- AutoLock lock(context_lock_);
- StreamFlushInfo& flush_info = stream_flush_info_[stream_id];
- if (flush_info.flush_pending && flush_info.route_id != route_id)
- InternalFlush(&flush_info);
-
- if (put_offset_changed) {
- const uint32_t flush_id = flush_info.next_stream_flush_id++;
- flush_info.flush_pending = true;
- flush_info.route_id = route_id;
- flush_info.put_offset = put_offset;
- flush_info.flush_count = flush_count;
- flush_info.flush_id = flush_id;
- flush_info.latency_info.insert(flush_info.latency_info.end(),
- latency_info.begin(), latency_info.end());
-
- if (do_flush)
- InternalFlush(&flush_info);
-
- return flush_id;
- }
- return 0;
-}
-
-void GpuChannelHost::FlushPendingStream(int32_t stream_id) {
- AutoLock lock(context_lock_);
- auto flush_info_iter = stream_flush_info_.find(stream_id);
- if (flush_info_iter == stream_flush_info_.end())
- return;
-
- StreamFlushInfo& flush_info = flush_info_iter->second;
- if (flush_info.flush_pending)
- InternalFlush(&flush_info);
-}
-
-void GpuChannelHost::InternalFlush(StreamFlushInfo* flush_info) {
- context_lock_.AssertAcquired();
- DCHECK(flush_info);
- DCHECK(flush_info->flush_pending);
- DCHECK_LT(flush_info->flushed_stream_flush_id, flush_info->flush_id);
- Send(new GpuCommandBufferMsg_AsyncFlush(
- flush_info->route_id, flush_info->put_offset, flush_info->flush_count,
- flush_info->latency_info));
- flush_info->latency_info.clear();
- flush_info->flush_pending = false;
-
- flush_info->flushed_stream_flush_id = flush_info->flush_id;
-}
-
-scoped_ptr<CommandBufferProxyImpl> GpuChannelHost::CreateViewCommandBuffer(
- int32_t surface_id,
- CommandBufferProxyImpl* share_group,
- int32_t stream_id,
- GpuStreamPriority stream_priority,
- const std::vector<int32_t>& attribs,
- const GURL& active_url,
- gfx::GpuPreference gpu_preference) {
- DCHECK(!share_group || (stream_id == share_group->stream_id()));
- TRACE_EVENT1("gpu",
- "GpuChannelHost::CreateViewCommandBuffer",
- "surface_id",
- surface_id);
-
- GPUCreateCommandBufferConfig init_params;
- init_params.share_group_id =
- share_group ? share_group->route_id() : MSG_ROUTING_NONE;
- init_params.stream_id = stream_id;
- init_params.stream_priority = stream_priority;
- init_params.attribs = attribs;
- init_params.active_url = active_url;
- init_params.gpu_preference = gpu_preference;
-
- int32_t route_id = GenerateRouteID();
-
- CreateCommandBufferResult result = factory_->CreateViewCommandBuffer(
- surface_id, init_params, route_id);
- if (result != CREATE_COMMAND_BUFFER_SUCCEEDED) {
- LOG(ERROR) << "GpuChannelHost::CreateViewCommandBuffer failed.";
-
- if (result == CREATE_COMMAND_BUFFER_FAILED_AND_CHANNEL_LOST) {
- // The GPU channel needs to be considered lost. The caller will
- // then set up a new connection, and the GPU channel and any
- // view command buffers will all be associated with the same GPU
- // process.
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner =
- factory_->GetIOThreadTaskRunner();
- io_task_runner->PostTask(
- FROM_HERE, base::Bind(&GpuChannelHost::MessageFilter::OnChannelError,
- channel_filter_.get()));
- }
-
- return NULL;
- }
-
- scoped_ptr<CommandBufferProxyImpl> command_buffer =
- make_scoped_ptr(new CommandBufferProxyImpl(this, route_id, stream_id));
- AddRoute(route_id, command_buffer->AsWeakPtr());
-
- return command_buffer;
-}
-
-scoped_ptr<CommandBufferProxyImpl> GpuChannelHost::CreateOffscreenCommandBuffer(
- const gfx::Size& size,
- CommandBufferProxyImpl* share_group,
- int32_t stream_id,
- GpuStreamPriority stream_priority,
- const std::vector<int32_t>& attribs,
- const GURL& active_url,
- gfx::GpuPreference gpu_preference) {
- DCHECK(!share_group || (stream_id == share_group->stream_id()));
- TRACE_EVENT0("gpu", "GpuChannelHost::CreateOffscreenCommandBuffer");
-
- GPUCreateCommandBufferConfig init_params;
- init_params.share_group_id =
- share_group ? share_group->route_id() : MSG_ROUTING_NONE;
- init_params.stream_id = stream_id;
- init_params.stream_priority = stream_priority;
- init_params.attribs = attribs;
- init_params.active_url = active_url;
- init_params.gpu_preference = gpu_preference;
-
- int32_t route_id = GenerateRouteID();
-
- bool succeeded = false;
- if (!Send(new GpuChannelMsg_CreateOffscreenCommandBuffer(
- size, init_params, route_id, &succeeded))) {
- LOG(ERROR) << "Failed to send GpuChannelMsg_CreateOffscreenCommandBuffer.";
- return NULL;
- }
-
- if (!succeeded) {
- LOG(ERROR)
- << "GpuChannelMsg_CreateOffscreenCommandBuffer returned failure.";
- return NULL;
- }
-
- scoped_ptr<CommandBufferProxyImpl> command_buffer =
- make_scoped_ptr(new CommandBufferProxyImpl(this, route_id, stream_id));
- AddRoute(route_id, command_buffer->AsWeakPtr());
-
- return command_buffer;
-}
-
-scoped_ptr<media::JpegDecodeAccelerator> GpuChannelHost::CreateJpegDecoder(
- media::JpegDecodeAccelerator::Client* client) {
- TRACE_EVENT0("gpu", "GpuChannelHost::CreateJpegDecoder");
-
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner =
- factory_->GetIOThreadTaskRunner();
- int32_t route_id = GenerateRouteID();
- scoped_ptr<GpuJpegDecodeAcceleratorHost> decoder(
- new GpuJpegDecodeAcceleratorHost(this, route_id, io_task_runner));
- if (!decoder->Initialize(client)) {
- return nullptr;
- }
-
- // The reply message of jpeg decoder should run on IO thread.
- io_task_runner->PostTask(FROM_HERE,
- base::Bind(&GpuChannelHost::MessageFilter::AddRoute,
- channel_filter_.get(), route_id,
- decoder->GetReceiver(), io_task_runner));
-
- return std::move(decoder);
-}
-
-void GpuChannelHost::DestroyCommandBuffer(
- CommandBufferProxyImpl* command_buffer) {
- TRACE_EVENT0("gpu", "GpuChannelHost::DestroyCommandBuffer");
-
- int32_t route_id = command_buffer->route_id();
- int32_t stream_id = command_buffer->stream_id();
- Send(new GpuChannelMsg_DestroyCommandBuffer(route_id));
- RemoveRoute(route_id);
-
- AutoLock lock(context_lock_);
- StreamFlushInfo& flush_info = stream_flush_info_[stream_id];
- if (flush_info.flush_pending && flush_info.route_id == route_id)
- flush_info.flush_pending = false;
-}
-
-void GpuChannelHost::DestroyChannel() {
- DCHECK(factory_->IsMainThread());
- AutoLock lock(context_lock_);
- channel_.reset();
-}
-
-void GpuChannelHost::AddRoute(
- int route_id, base::WeakPtr<IPC::Listener> listener) {
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner =
- factory_->GetIOThreadTaskRunner();
- io_task_runner->PostTask(FROM_HERE,
- base::Bind(&GpuChannelHost::MessageFilter::AddRoute,
- channel_filter_.get(), route_id, listener,
- base::ThreadTaskRunnerHandle::Get()));
-}
-
-void GpuChannelHost::RemoveRoute(int route_id) {
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner =
- factory_->GetIOThreadTaskRunner();
- io_task_runner->PostTask(
- FROM_HERE, base::Bind(&GpuChannelHost::MessageFilter::RemoveRoute,
- channel_filter_.get(), route_id));
-}
-
-base::SharedMemoryHandle GpuChannelHost::ShareToGpuProcess(
- base::SharedMemoryHandle source_handle) {
- if (IsLost())
- return base::SharedMemory::NULLHandle();
-
-#if defined(OS_WIN) || defined(OS_MACOSX)
- // Windows and Mac need to explicitly duplicate the handle out to another
- // process.
- base::SharedMemoryHandle target_handle;
- base::ProcessId peer_pid;
- {
- AutoLock lock(context_lock_);
- if (!channel_)
- return base::SharedMemory::NULLHandle();
- peer_pid = channel_->GetPeerPID();
- }
- bool success = BrokerDuplicateSharedMemoryHandle(source_handle, peer_pid,
- &target_handle);
- if (!success)
- return base::SharedMemory::NULLHandle();
-
- return target_handle;
-#else
- return base::SharedMemory::DuplicateHandle(source_handle);
-#endif // defined(OS_WIN) || defined(OS_MACOSX)
-}
-
-int32_t GpuChannelHost::ReserveTransferBufferId() {
- // 0 is a reserved value.
- return g_next_transfer_buffer_id.GetNext() + 1;
-}
-
-gfx::GpuMemoryBufferHandle GpuChannelHost::ShareGpuMemoryBufferToGpuProcess(
- const gfx::GpuMemoryBufferHandle& source_handle,
- bool* requires_sync_point) {
- switch (source_handle.type) {
- case gfx::SHARED_MEMORY_BUFFER: {
- gfx::GpuMemoryBufferHandle handle;
- handle.type = gfx::SHARED_MEMORY_BUFFER;
- handle.handle = ShareToGpuProcess(source_handle.handle);
- handle.offset = source_handle.offset;
- handle.stride = source_handle.stride;
- *requires_sync_point = false;
- return handle;
- }
- case gfx::IO_SURFACE_BUFFER:
- case gfx::SURFACE_TEXTURE_BUFFER:
- case gfx::OZONE_NATIVE_PIXMAP:
- *requires_sync_point = true;
- return source_handle;
- default:
- NOTREACHED();
- return gfx::GpuMemoryBufferHandle();
- }
-}
-
-int32_t GpuChannelHost::ReserveImageId() {
- return next_image_id_.GetNext();
-}
-
-int32_t GpuChannelHost::GenerateRouteID() {
- return next_route_id_.GetNext();
-}
-
-int32_t GpuChannelHost::GenerateStreamID() {
- const int32_t stream_id = next_stream_id_.GetNext();
- DCHECK_NE(0, stream_id);
- DCHECK_NE(kDefaultStreamId, stream_id);
- return stream_id;
-}
-
-uint32_t GpuChannelHost::ValidateFlushIDReachedServer(int32_t stream_id,
- bool force_validate) {
- // Store what flush ids we will be validating for all streams.
- base::hash_map<int32_t, uint32_t> validate_flushes;
- uint32_t flushed_stream_flush_id = 0;
- uint32_t verified_stream_flush_id = 0;
- {
- AutoLock lock(context_lock_);
- for (const auto& iter : stream_flush_info_) {
- const int32_t iter_stream_id = iter.first;
- const StreamFlushInfo& flush_info = iter.second;
- if (iter_stream_id == stream_id) {
- flushed_stream_flush_id = flush_info.flushed_stream_flush_id;
- verified_stream_flush_id = flush_info.verified_stream_flush_id;
- }
-
- if (flush_info.flushed_stream_flush_id >
- flush_info.verified_stream_flush_id) {
- validate_flushes.insert(
- std::make_pair(iter_stream_id, flush_info.flushed_stream_flush_id));
- }
- }
- }
-
- if (!force_validate && flushed_stream_flush_id == verified_stream_flush_id) {
- // Current stream has no unverified flushes.
- return verified_stream_flush_id;
- }
-
- if (Send(new GpuChannelMsg_Nop())) {
- // Update verified flush id for all streams.
- uint32_t highest_flush_id = 0;
- AutoLock lock(context_lock_);
- for (const auto& iter : validate_flushes) {
- const int32_t validated_stream_id = iter.first;
- const uint32_t validated_flush_id = iter.second;
- StreamFlushInfo& flush_info = stream_flush_info_[validated_stream_id];
- if (flush_info.verified_stream_flush_id < validated_flush_id) {
- flush_info.verified_stream_flush_id = validated_flush_id;
- }
-
- if (validated_stream_id == stream_id)
- highest_flush_id = flush_info.verified_stream_flush_id;
- }
-
- return highest_flush_id;
- }
-
- return 0;
-}
-
-uint32_t GpuChannelHost::GetHighestValidatedFlushID(int32_t stream_id) {
- AutoLock lock(context_lock_);
- StreamFlushInfo& flush_info = stream_flush_info_[stream_id];
- return flush_info.verified_stream_flush_id;
-}
-
-GpuChannelHost::~GpuChannelHost() {
-#if DCHECK_IS_ON()
- AutoLock lock(context_lock_);
- DCHECK(!channel_)
- << "GpuChannelHost::DestroyChannel must be called before destruction.";
-#endif
-}
-
-GpuChannelHost::MessageFilter::ListenerInfo::ListenerInfo() {}
-
-GpuChannelHost::MessageFilter::ListenerInfo::~ListenerInfo() {}
-
-GpuChannelHost::MessageFilter::MessageFilter()
- : lost_(false) {
-}
-
-GpuChannelHost::MessageFilter::~MessageFilter() {}
-
-void GpuChannelHost::MessageFilter::AddRoute(
- int32_t route_id,
- base::WeakPtr<IPC::Listener> listener,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
- DCHECK(listeners_.find(route_id) == listeners_.end());
- DCHECK(task_runner);
- ListenerInfo info;
- info.listener = listener;
- info.task_runner = task_runner;
- listeners_[route_id] = info;
-}
-
-void GpuChannelHost::MessageFilter::RemoveRoute(int32_t route_id) {
- listeners_.erase(route_id);
-}
-
-bool GpuChannelHost::MessageFilter::OnMessageReceived(
- const IPC::Message& message) {
- // Never handle sync message replies or we will deadlock here.
- if (message.is_reply())
- return false;
-
- auto it = listeners_.find(message.routing_id());
- if (it == listeners_.end())
- return false;
-
- const ListenerInfo& info = it->second;
- info.task_runner->PostTask(
- FROM_HERE,
- base::Bind(base::IgnoreResult(&IPC::Listener::OnMessageReceived),
- info.listener, message));
- return true;
-}
-
-void GpuChannelHost::MessageFilter::OnChannelError() {
- // Set the lost state before signalling the proxies. That way, if they
- // themselves post a task to recreate the context, they will not try to re-use
- // this channel host.
- {
- AutoLock lock(lock_);
- lost_ = true;
- }
-
- // Inform all the proxies that an error has occurred. This will be reported
- // via OpenGL as a lost context.
- for (const auto& kv : listeners_) {
- const ListenerInfo& info = kv.second;
- info.task_runner->PostTask(
- FROM_HERE, base::Bind(&IPC::Listener::OnChannelError, info.listener));
- }
-
- listeners_.clear();
-}
-
-bool GpuChannelHost::MessageFilter::IsLost() const {
- AutoLock lock(lock_);
- return lost_;
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_channel_host.h b/chromium/content/common/gpu/client/gpu_channel_host.h
deleted file mode 100644
index bf7b3894c21..00000000000
--- a/chromium/content/common/gpu/client/gpu_channel_host.h
+++ /dev/null
@@ -1,318 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_CLIENT_GPU_CHANNEL_HOST_H_
-#define CONTENT_COMMON_GPU_CLIENT_GPU_CHANNEL_HOST_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#include "base/atomic_sequence_num.h"
-#include "base/containers/scoped_ptr_hash_map.h"
-#include "base/macros.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/common/content_export.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
-#include "content/common/gpu/gpu_result_codes.h"
-#include "content/common/gpu/gpu_stream_priority.h"
-#include "content/common/message_router.h"
-#include "gpu/config/gpu_info.h"
-#include "ipc/ipc_channel_handle.h"
-#include "ipc/ipc_sync_channel.h"
-#include "ipc/message_filter.h"
-#include "media/video/jpeg_decode_accelerator.h"
-#include "ui/events/latency_info.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/gpu_memory_buffer.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gl/gpu_preference.h"
-
-class GURL;
-class TransportTextureService;
-struct GPUCreateCommandBufferConfig;
-
-namespace base {
-class MessageLoop;
-class WaitableEvent;
-}
-
-namespace IPC {
-class SyncMessageFilter;
-}
-
-namespace media {
-class JpegDecodeAccelerator;
-class VideoDecodeAccelerator;
-class VideoEncodeAccelerator;
-}
-
-namespace gpu {
-class GpuMemoryBufferManager;
-}
-
-namespace content {
-class CommandBufferProxyImpl;
-class GpuChannelHost;
-
-class CONTENT_EXPORT GpuChannelHostFactory {
- public:
- virtual ~GpuChannelHostFactory() {}
-
- virtual bool IsMainThread() = 0;
- virtual scoped_refptr<base::SingleThreadTaskRunner>
- GetIOThreadTaskRunner() = 0;
- virtual scoped_ptr<base::SharedMemory> AllocateSharedMemory(size_t size) = 0;
- virtual CreateCommandBufferResult CreateViewCommandBuffer(
- int32_t surface_id,
- const GPUCreateCommandBufferConfig& init_params,
- int32_t route_id) = 0;
-};
-
-// Encapsulates an IPC channel between the client and one GPU process.
-// On the GPU process side there's a corresponding GpuChannel.
-// Every method can be called on any thread with a message loop, except for the
-// IO thread.
-class GpuChannelHost : public IPC::Sender,
- public base::RefCountedThreadSafe<GpuChannelHost> {
- public:
- // Must be called on the main thread (as defined by the factory).
- static scoped_refptr<GpuChannelHost> Create(
- GpuChannelHostFactory* factory,
- int channel_id,
- const gpu::GPUInfo& gpu_info,
- const IPC::ChannelHandle& channel_handle,
- base::WaitableEvent* shutdown_event,
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager);
-
- static const int32_t kDefaultStreamId = -1;
- static const GpuStreamPriority kDefaultStreamPriority =
- GpuStreamPriority::NORMAL;
-
- bool IsLost() const {
- DCHECK(channel_filter_.get());
- return channel_filter_->IsLost();
- }
-
- int channel_id() const { return channel_id_; }
-
- // The GPU stats reported by the GPU process.
- const gpu::GPUInfo& gpu_info() const { return gpu_info_; }
-
- // IPC::Sender implementation:
- bool Send(IPC::Message* msg) override;
-
- // Set an ordering barrier. AsyncFlushes any pending barriers on other
- // routes. Combines multiple OrderingBarriers into a single AsyncFlush.
- // Returns the flush ID for the stream or 0 if put offset was not changed.
- uint32_t OrderingBarrier(int32_t route_id,
- int32_t stream_id,
- int32_t put_offset,
- uint32_t flush_count,
- const std::vector<ui::LatencyInfo>& latency_info,
- bool put_offset_changed,
- bool do_flush);
-
- void FlushPendingStream(int32_t stream_id);
-
- // Create and connect to a command buffer in the GPU process.
- scoped_ptr<CommandBufferProxyImpl> CreateViewCommandBuffer(
- int32_t surface_id,
- CommandBufferProxyImpl* share_group,
- int32_t stream_id,
- GpuStreamPriority stream_priority,
- const std::vector<int32_t>& attribs,
- const GURL& active_url,
- gfx::GpuPreference gpu_preference);
-
- // Create and connect to a command buffer in the GPU process.
- scoped_ptr<CommandBufferProxyImpl> CreateOffscreenCommandBuffer(
- const gfx::Size& size,
- CommandBufferProxyImpl* share_group,
- int32_t stream_id,
- GpuStreamPriority stream_priority,
- const std::vector<int32_t>& attribs,
- const GURL& active_url,
- gfx::GpuPreference gpu_preference);
-
- // Creates a JPEG decoder in the GPU process.
- scoped_ptr<media::JpegDecodeAccelerator> CreateJpegDecoder(
- media::JpegDecodeAccelerator::Client* client);
-
- // Destroy a command buffer created by this channel.
- void DestroyCommandBuffer(CommandBufferProxyImpl* command_buffer);
-
- // Destroy this channel. Must be called on the main thread, before
- // destruction.
- void DestroyChannel();
-
- // Add a route for the current message loop.
- void AddRoute(int route_id, base::WeakPtr<IPC::Listener> listener);
- void RemoveRoute(int route_id);
-
- GpuChannelHostFactory* factory() const { return factory_; }
-
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager() const {
- return gpu_memory_buffer_manager_;
- }
-
- // Returns a handle to the shared memory that can be sent via IPC to the
- // GPU process. The caller is responsible for ensuring it is closed. Returns
- // an invalid handle on failure.
- base::SharedMemoryHandle ShareToGpuProcess(
- base::SharedMemoryHandle source_handle);
-
- // Reserve one unused transfer buffer ID.
- int32_t ReserveTransferBufferId();
-
- // Returns a GPU memory buffer handle to the buffer that can be sent via
- // IPC to the GPU process. The caller is responsible for ensuring it is
- // closed. Returns an invalid handle on failure.
- gfx::GpuMemoryBufferHandle ShareGpuMemoryBufferToGpuProcess(
- const gfx::GpuMemoryBufferHandle& source_handle,
- bool* requires_sync_point);
-
- // Reserve one unused image ID.
- int32_t ReserveImageId();
-
- // Generate a route ID guaranteed to be unique for this channel.
- int32_t GenerateRouteID();
-
- // Generate a stream ID guaranteed to be unique for this channel.
- int32_t GenerateStreamID();
-
- // Sends a synchronous nop to the server which validate that all previous IPC
- // messages have been received. Once the synchronous nop has been sent to the
- // server all previous flushes will all be marked as validated, including
- // flushes for other streams on the same channel. Once a validation has been
- // sent, it will return the highest validated flush id for the stream.
- // If the validation fails (which can only happen upon context lost), the
- // highest validated flush id will not change. If no flush ID were ever
- // validated then it will return 0 (Note the lowest valid flush ID is 1).
- uint32_t ValidateFlushIDReachedServer(int32_t stream_id, bool force_validate);
-
- // Returns the highest validated flush ID for a given stream.
- uint32_t GetHighestValidatedFlushID(int32_t stream_id);
-
- private:
- friend class base::RefCountedThreadSafe<GpuChannelHost>;
-
- // A filter used internally to route incoming messages from the IO thread
- // to the correct message loop. It also maintains some shared state between
- // all the contexts.
- class MessageFilter : public IPC::MessageFilter {
- public:
- MessageFilter();
-
- // Called on the IO thread.
- void AddRoute(int32_t route_id,
- base::WeakPtr<IPC::Listener> listener,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
- // Called on the IO thread.
- void RemoveRoute(int32_t route_id);
-
- // IPC::MessageFilter implementation
- // (called on the IO thread):
- bool OnMessageReceived(const IPC::Message& msg) override;
- void OnChannelError() override;
-
- // The following methods can be called on any thread.
-
- // Whether the channel is lost.
- bool IsLost() const;
-
- private:
- struct ListenerInfo {
- ListenerInfo();
- ~ListenerInfo();
-
- base::WeakPtr<IPC::Listener> listener;
- scoped_refptr<base::SingleThreadTaskRunner> task_runner;
- };
-
- ~MessageFilter() override;
-
- // Threading notes: |listeners_| is only accessed on the IO thread. Every
- // other field is protected by |lock_|.
- base::hash_map<int32_t, ListenerInfo> listeners_;
-
- // Protects all fields below this one.
- mutable base::Lock lock_;
-
- // Whether the channel has been lost.
- bool lost_;
- };
-
- struct StreamFlushInfo {
- StreamFlushInfo();
- ~StreamFlushInfo();
-
- // These are global per stream.
- uint32_t next_stream_flush_id;
- uint32_t flushed_stream_flush_id;
- uint32_t verified_stream_flush_id;
-
- // These are local per context.
- bool flush_pending;
- int32_t route_id;
- int32_t put_offset;
- uint32_t flush_count;
- uint32_t flush_id;
- std::vector<ui::LatencyInfo> latency_info;
- };
-
- GpuChannelHost(GpuChannelHostFactory* factory,
- int channel_id,
- const gpu::GPUInfo& gpu_info,
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager);
- ~GpuChannelHost() override;
- void Connect(const IPC::ChannelHandle& channel_handle,
- base::WaitableEvent* shutdown_event);
- bool InternalSend(IPC::Message* msg);
- void InternalFlush(StreamFlushInfo* flush_info);
-
- // Threading notes: all fields are constant during the lifetime of |this|
- // except:
- // - |next_image_id_|, atomic type
- // - |next_route_id_|, atomic type
- // - |next_stream_id_|, atomic type
- // - |channel_| and |stream_flush_info_|, protected by |context_lock_|
- GpuChannelHostFactory* const factory_;
-
- const int channel_id_;
- const gpu::GPUInfo gpu_info_;
-
- scoped_refptr<MessageFilter> channel_filter_;
-
- gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager_;
-
- // A filter for sending messages from thread other than the main thread.
- scoped_refptr<IPC::SyncMessageFilter> sync_filter_;
-
- // Image IDs are allocated in sequence.
- base::AtomicSequenceNumber next_image_id_;
-
- // Route IDs are allocated in sequence.
- base::AtomicSequenceNumber next_route_id_;
-
- // Stream IDs are allocated in sequence.
- base::AtomicSequenceNumber next_stream_id_;
-
- // Protects channel_ and stream_flush_info_.
- mutable base::Lock context_lock_;
- scoped_ptr<IPC::SyncChannel> channel_;
- base::hash_map<int32_t, StreamFlushInfo> stream_flush_info_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuChannelHost);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_CLIENT_GPU_CHANNEL_HOST_H_
diff --git a/chromium/content/common/gpu/client/gpu_context_tests.h b/chromium/content/common/gpu/client/gpu_context_tests.h
index 8810789d076..9687c4a057e 100644
--- a/chromium/content/common/gpu/client/gpu_context_tests.h
+++ b/chromium/content/common/gpu/client/gpu_context_tests.h
@@ -10,6 +10,7 @@
#include "base/run_loop.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/context_support.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/sync_token.h"
namespace {
@@ -30,32 +31,39 @@ class SignalTest : public ContextTestBase {
}
// These tests should time out if the callback doesn't get called.
- void TestSignalQuery(blink::WebGLId query) {
+ void TestSignalQuery(GLuint query) {
base::RunLoop run_loop;
context_support_->SignalQuery(
- query,
- base::Bind(
- &RunOnlyOnce, run_loop.QuitClosure(), base::Owned(new int(0))));
+ query, base::Bind(&RunOnlyOnce, run_loop.QuitClosure(),
+ base::Owned(new int(0))));
run_loop.Run();
}
};
CONTEXT_TEST_F(SignalTest, BasicSignalSyncTokenTest) {
- if (!context_)
+#if defined(OS_WIN)
+ // The IPC version of ContextTestBase::SetUpOnMainThread does not succeed on
+ // some platforms.
+ if (!gl_)
return;
+#endif
- const blink::WGC3Duint64 fence_sync = context_->insertFenceSyncCHROMIUM();
- context_->shallowFlushCHROMIUM();
+ const GLuint64 fence_sync = gl_->InsertFenceSyncCHROMIUM();
+ gl_->ShallowFlushCHROMIUM();
gpu::SyncToken sync_token;
- ASSERT_TRUE(context_->genSyncTokenCHROMIUM(fence_sync, sync_token.GetData()));
+ gl_->GenSyncTokenCHROMIUM(fence_sync, sync_token.GetData());
TestSignalSyncToken(sync_token);
};
CONTEXT_TEST_F(SignalTest, EmptySignalSyncTokenTest) {
- if (!context_)
+#if defined(OS_WIN)
+ // The IPC version of ContextTestBase::SetUpOnMainThread does not succeed on
+ // some platforms.
+ if (!gl_)
return;
+#endif
// Signalling something that doesn't exist should run the callback
// immediately.
@@ -64,42 +72,59 @@ CONTEXT_TEST_F(SignalTest, EmptySignalSyncTokenTest) {
};
CONTEXT_TEST_F(SignalTest, InvalidSignalSyncTokenTest) {
- if (!context_)
+#if defined(OS_WIN)
+ // The IPC version of ContextTestBase::SetUpOnMainThread does not succeed on
+ // some platforms.
+ if (!gl_)
return;
+#endif
// Signalling something that doesn't exist should run the callback
// immediately.
- gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO,
- 0,
- 1297824234,
+ gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO, 0,
+ gpu::CommandBufferId::FromUnsafeValue(1297824234),
9123743439);
TestSignalSyncToken(sync_token);
};
CONTEXT_TEST_F(SignalTest, BasicSignalQueryTest) {
- if (!context_)
+#if defined(OS_WIN)
+ // The IPC version of ContextTestBase::SetUpOnMainThread does not succeed on
+ // some platforms.
+ if (!gl_)
return;
+#endif
- unsigned query = context_->createQueryEXT();
- context_->beginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, query);
- context_->finish();
- context_->endQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM);
+ unsigned query;
+ gl_->GenQueriesEXT(1, &query);
+ gl_->BeginQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM, query);
+ gl_->Finish();
+ gl_->EndQueryEXT(GL_COMMANDS_ISSUED_CHROMIUM);
TestSignalQuery(query);
- context_->deleteQueryEXT(query);
+ gl_->DeleteQueriesEXT(1, &query);
};
CONTEXT_TEST_F(SignalTest, SignalQueryUnboundTest) {
- if (!context_)
+#if defined(OS_WIN)
+ // The IPC version of ContextTestBase::SetUpOnMainThread does not succeed on
+ // some platforms.
+ if (!gl_)
return;
+#endif
- blink::WebGLId query = context_->createQueryEXT();
+ GLuint query;
+ gl_->GenQueriesEXT(1, &query);
TestSignalQuery(query);
- context_->deleteQueryEXT(query);
+ gl_->DeleteQueriesEXT(1, &query);
};
CONTEXT_TEST_F(SignalTest, InvalidSignalQueryUnboundTest) {
- if (!context_)
+#if defined(OS_WIN)
+ // The IPC version of ContextTestBase::SetUpOnMainThread does not succeed on
+ // some platforms.
+ if (!gl_)
return;
+#endif
// Signalling something that doesn't exist should run the callback
// immediately.
@@ -110,5 +135,4 @@ CONTEXT_TEST_F(SignalTest, InvalidSignalQueryUnboundTest) {
TestSignalQuery(928729082);
TestSignalQuery(928729081);
};
-
};
diff --git a/chromium/content/common/gpu/client/gpu_in_process_context_tests.cc b/chromium/content/common/gpu/client/gpu_in_process_context_tests.cc
index 6e740572211..c8f0d3f293f 100644
--- a/chromium/content/common/gpu/client/gpu_in_process_context_tests.cc
+++ b/chromium/content/common/gpu/client/gpu_in_process_context_tests.cc
@@ -7,32 +7,50 @@
#include <string>
#include <vector>
-#include "content/public/test/unittest_test_suite.h"
-#include "gpu/blink/webgraphicscontext3d_in_process_command_buffer_impl.h"
+#include "gpu/command_buffer/client/gl_in_process_context.h"
+#include "gpu/command_buffer/client/gles2_implementation.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/gl_surface.h"
namespace {
-using gpu_blink::WebGraphicsContext3DInProcessCommandBufferImpl;
-
class ContextTestBase : public testing::Test {
public:
void SetUp() override {
- blink::WebGraphicsContext3D::Attributes attributes;
- bool lose_context_when_out_of_memory = false;
- typedef WebGraphicsContext3DInProcessCommandBufferImpl WGC3DIPCBI;
- context_ = WGC3DIPCBI::CreateOffscreenContext(
- attributes, lose_context_when_out_of_memory);
- context_->InitializeOnCurrentThread();
- context_support_ = context_->GetContextSupport();
+ gpu::gles2::ContextCreationAttribHelper attributes;
+ attributes.alpha_size = 8;
+ attributes.depth_size = 24;
+ attributes.red_size = 8;
+ attributes.green_size = 8;
+ attributes.blue_size = 8;
+ attributes.stencil_size = 8;
+ attributes.samples = 4;
+ attributes.sample_buffers = 1;
+ attributes.bind_generates_resource = false;
+
+ context_.reset(gpu::GLInProcessContext::Create(
+ nullptr, /* service */
+ nullptr, /* surface */
+ true, /* offscreen */
+ gfx::kNullAcceleratedWidget, /* window */
+ gfx::Size(1, 1), /* size */
+ nullptr, /* share_context */
+ attributes, gfx::PreferDiscreteGpu,
+ ::gpu::GLInProcessContextSharedMemoryLimits(),
+ nullptr, /* gpu_memory_buffer_manager */
+ nullptr /* image_factory */));
+ gl_ = context_->GetImplementation();
+ context_support_ = context_->GetImplementation();
}
void TearDown() override { context_.reset(NULL); }
protected:
- scoped_ptr<WebGraphicsContext3DInProcessCommandBufferImpl> context_;
+ gpu::gles2::GLES2Interface* gl_;
gpu::ContextSupport* context_support_;
+
+ private:
+ scoped_ptr<gpu::GLInProcessContext> context_;
};
} // namespace
diff --git a/chromium/content/common/gpu/client/gpu_jpeg_decode_accelerator_host.cc b/chromium/content/common/gpu/client/gpu_jpeg_decode_accelerator_host.cc
deleted file mode 100644
index eac971b43b7..00000000000
--- a/chromium/content/common/gpu/client/gpu_jpeg_decode_accelerator_host.cc
+++ /dev/null
@@ -1,204 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/client/gpu_jpeg_decode_accelerator_host.h"
-
-#include <stddef.h>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/shared_memory_handle.h"
-#include "base/memory/weak_ptr.h"
-#include "base/synchronization/waitable_event.h"
-#include "build/build_config.h"
-#include "content/common/gpu/client/gpu_channel_host.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "ipc/ipc_listener.h"
-#include "ipc/ipc_message_macros.h"
-#include "ipc/ipc_message_utils.h"
-
-namespace content {
-
-// Class to receive AcceleratedJpegDecoderHostMsg_DecodeAck IPC message on IO
-// thread. This does very similar what MessageFilter usually does. It is not
-// MessageFilter because GpuChannelHost doesn't support AddFilter.
-class GpuJpegDecodeAcceleratorHost::Receiver : public IPC::Listener,
- public base::NonThreadSafe {
- public:
- Receiver(Client* client,
- const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
- : client_(client),
- io_task_runner_(io_task_runner),
- weak_factory_for_io_(this) {
- DCHECK(CalledOnValidThread());
- }
-
- ~Receiver() override { DCHECK(CalledOnValidThread()); }
-
- void InvalidateWeakPtr(base::WaitableEvent* event) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
- weak_factory_for_io_.InvalidateWeakPtrs();
- event->Signal();
- }
-
- // IPC::Listener implementation.
- void OnChannelError() override {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
-
- OnDecodeAck(kInvalidBitstreamBufferId, PLATFORM_FAILURE);
- }
-
- bool OnMessageReceived(const IPC::Message& msg) override {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
-
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(GpuJpegDecodeAcceleratorHost::Receiver, msg)
- IPC_MESSAGE_HANDLER(AcceleratedJpegDecoderHostMsg_DecodeAck, OnDecodeAck)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- DCHECK(handled);
- return handled;
- }
-
- base::WeakPtr<IPC::Listener> AsWeakPtrForIO() {
- return weak_factory_for_io_.GetWeakPtr();
- }
-
- private:
- void OnDecodeAck(int32_t bitstream_buffer_id, Error error) {
- DCHECK(io_task_runner_->BelongsToCurrentThread());
-
- if (!client_)
- return;
-
- if (error == media::JpegDecodeAccelerator::NO_ERRORS) {
- client_->VideoFrameReady(bitstream_buffer_id);
- } else {
- // Only NotifyError once.
- // Client::NotifyError() may trigger deletion of |this| (on another
- // thread), so calling it needs to be the last thing done on this stack!
- media::JpegDecodeAccelerator::Client* client = nullptr;
- std::swap(client, client_);
- client->NotifyError(bitstream_buffer_id, error);
- }
- }
-
- Client* client_;
-
- // GPU IO task runner.
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
-
- // Weak pointers will be invalidated on IO thread.
- base::WeakPtrFactory<Receiver> weak_factory_for_io_;
-
- DISALLOW_COPY_AND_ASSIGN(Receiver);
-};
-
-GpuJpegDecodeAcceleratorHost::GpuJpegDecodeAcceleratorHost(
- GpuChannelHost* channel,
- int32_t route_id,
- const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
- : channel_(channel),
- decoder_route_id_(route_id),
- io_task_runner_(io_task_runner) {
- DCHECK(channel_);
- DCHECK_NE(decoder_route_id_, MSG_ROUTING_NONE);
-}
-
-GpuJpegDecodeAcceleratorHost::~GpuJpegDecodeAcceleratorHost() {
- DCHECK(CalledOnValidThread());
- Send(new AcceleratedJpegDecoderMsg_Destroy(decoder_route_id_));
-
- if (receiver_) {
- channel_->RemoveRoute(decoder_route_id_);
-
- // Invalidate weak ptr of |receiver_|. After that, no more messages will be
- // routed to |receiver_| on IO thread.
- base::WaitableEvent event(false, false);
- io_task_runner_->PostTask(FROM_HERE,
- base::Bind(&Receiver::InvalidateWeakPtr,
- base::Unretained(receiver_.get()),
- base::Unretained(&event)));
- event.Wait();
- }
-}
-
-bool GpuJpegDecodeAcceleratorHost::Initialize(
- media::JpegDecodeAccelerator::Client* client) {
- DCHECK(CalledOnValidThread());
-
- bool succeeded = false;
- // This cannot be on IO thread because the msg is synchronous.
- Send(new GpuMsg_CreateJpegDecoder(decoder_route_id_, &succeeded));
-
- if (!succeeded) {
- DLOG(ERROR) << "Send(GpuMsg_CreateJpegDecoder()) failed";
- return false;
- }
-
- receiver_.reset(new Receiver(client, io_task_runner_));
-
- return true;
-}
-
-void GpuJpegDecodeAcceleratorHost::Decode(
- const media::BitstreamBuffer& bitstream_buffer,
- const scoped_refptr<media::VideoFrame>& video_frame) {
- DCHECK(CalledOnValidThread());
-
- DCHECK(
- base::SharedMemory::IsHandleValid(video_frame->shared_memory_handle()));
-
- base::SharedMemoryHandle input_handle =
- channel_->ShareToGpuProcess(bitstream_buffer.handle());
- if (!base::SharedMemory::IsHandleValid(input_handle)) {
- DLOG(ERROR) << "Failed to duplicate handle of BitstreamBuffer";
- return;
- }
- base::SharedMemoryHandle output_handle =
- channel_->ShareToGpuProcess(video_frame->shared_memory_handle());
- if (!base::SharedMemory::IsHandleValid(output_handle)) {
- DLOG(ERROR) << "Failed to duplicate handle of VideoFrame";
-#if defined(OS_POSIX) && !(defined(OS_MACOSX) && !defined(OS_IOS))
- if (input_handle.auto_close) {
- // Defer closing task to the ScopedFD.
- base::ScopedFD(input_handle.fd);
- }
-#else
- // TODO(kcwu) fix the handle leak after crbug.com/493414 resolved.
-#endif
- return;
- }
-
- size_t output_buffer_size = media::VideoFrame::AllocationSize(
- video_frame->format(), video_frame->coded_size());
-
- AcceleratedJpegDecoderMsg_Decode_Params decode_params;
- decode_params.coded_size = video_frame->coded_size();
- decode_params.input_buffer_id = bitstream_buffer.id();
- decode_params.input_buffer_handle = input_handle;
- decode_params.input_buffer_size = bitstream_buffer.size();
- decode_params.output_video_frame_handle = output_handle;
- decode_params.output_buffer_size = output_buffer_size;
- Send(new AcceleratedJpegDecoderMsg_Decode(decoder_route_id_, decode_params));
-}
-
-bool GpuJpegDecodeAcceleratorHost::IsSupported() {
- return channel_->gpu_info().jpeg_decode_accelerator_supported;
-}
-
-void GpuJpegDecodeAcceleratorHost::Send(IPC::Message* message) {
- DCHECK(CalledOnValidThread());
-
- if (!channel_->Send(message)) {
- DLOG(ERROR) << "Send(" << message->type() << ") failed";
- }
-}
-
-base::WeakPtr<IPC::Listener> GpuJpegDecodeAcceleratorHost::GetReceiver() {
- return receiver_->AsWeakPtrForIO();
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_jpeg_decode_accelerator_host.h b/chromium/content/common/gpu/client/gpu_jpeg_decode_accelerator_host.h
deleted file mode 100644
index 53465f3aee7..00000000000
--- a/chromium/content/common/gpu/client/gpu_jpeg_decode_accelerator_host.h
+++ /dev/null
@@ -1,73 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_CLIENT_GPU_JPEG_DECODE_ACCELERATOR_HOST_H_
-#define CONTENT_COMMON_GPU_CLIENT_GPU_JPEG_DECODE_ACCELERATOR_HOST_H_
-
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/threading/non_thread_safe.h"
-#include "media/video/jpeg_decode_accelerator.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}
-
-namespace IPC {
-class Listener;
-class Message;
-}
-
-namespace content {
-class GpuChannelHost;
-
-// This class is used to talk to JpegDecodeAccelerator in the GPU process
-// through IPC messages.
-class GpuJpegDecodeAcceleratorHost : public media::JpegDecodeAccelerator,
- public base::NonThreadSafe {
- public:
- // VideoCaptureGpuJpegDecoder owns |this| and |channel|. And
- // VideoCaptureGpuJpegDecoder delete |this| before |channel|. So |this| is
- // guaranteed not to outlive |channel|.
- GpuJpegDecodeAcceleratorHost(
- GpuChannelHost* channel,
- int32_t route_id,
- const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
- ~GpuJpegDecodeAcceleratorHost() override;
-
- // media::JpegDecodeAccelerator implementation.
- // |client| is called on the IO thread, but is never called into after the
- // GpuJpegDecodeAcceleratorHost is destroyed.
- bool Initialize(media::JpegDecodeAccelerator::Client* client) override;
- void Decode(const media::BitstreamBuffer& bitstream_buffer,
- const scoped_refptr<media::VideoFrame>& video_frame) override;
- bool IsSupported() override;
-
- base::WeakPtr<IPC::Listener> GetReceiver();
-
- private:
- class Receiver;
-
- void Send(IPC::Message* message);
-
- // Unowned reference to the GpuChannelHost to send IPC messages to the GPU
- // process.
- GpuChannelHost* channel_;
-
- // Route ID for the associated decoder in the GPU process.
- int32_t decoder_route_id_;
-
- // GPU IO task runner.
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
-
- scoped_ptr<Receiver> receiver_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuJpegDecodeAcceleratorHost);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_CLIENT_GPU_JPEG_DECODE_ACCELERATOR_HOST_H_
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl.cc
deleted file mode 100644
index 5c6571aaf66..00000000000
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl.cc
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
-
-#include "base/logging.h"
-#include "build/build_config.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h"
-
-#if defined(OS_MACOSX)
-#include "content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h"
-#endif
-
-#if defined(OS_ANDROID)
-#include "content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.h"
-#endif
-
-#if defined(USE_OZONE)
-#include "content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_pixmap.h"
-#endif
-
-namespace content {
-
-GpuMemoryBufferImpl::GpuMemoryBufferImpl(gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- const DestructionCallback& callback)
- : id_(id),
- size_(size),
- format_(format),
- callback_(callback),
- mapped_(false) {}
-
-GpuMemoryBufferImpl::~GpuMemoryBufferImpl() {
- DCHECK(!mapped_);
- callback_.Run(destruction_sync_token_);
-}
-
-// static
-scoped_ptr<GpuMemoryBufferImpl> GpuMemoryBufferImpl::CreateFromHandle(
- const gfx::GpuMemoryBufferHandle& handle,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- const DestructionCallback& callback) {
- switch (handle.type) {
- case gfx::SHARED_MEMORY_BUFFER:
- return GpuMemoryBufferImplSharedMemory::CreateFromHandle(
- handle, size, format, usage, callback);
-#if defined(OS_MACOSX)
- case gfx::IO_SURFACE_BUFFER:
- return GpuMemoryBufferImplIOSurface::CreateFromHandle(
- handle, size, format, usage, callback);
-#endif
-#if defined(OS_ANDROID)
- case gfx::SURFACE_TEXTURE_BUFFER:
- return GpuMemoryBufferImplSurfaceTexture::CreateFromHandle(
- handle, size, format, usage, callback);
-#endif
-#if defined(USE_OZONE)
- case gfx::OZONE_NATIVE_PIXMAP:
- return GpuMemoryBufferImplOzoneNativePixmap::CreateFromHandle(
- handle, size, format, usage, callback);
-#endif
- default:
- NOTREACHED();
- return nullptr;
- }
-}
-
-// static
-GpuMemoryBufferImpl* GpuMemoryBufferImpl::FromClientBuffer(
- ClientBuffer buffer) {
- return reinterpret_cast<GpuMemoryBufferImpl*>(buffer);
-}
-
-gfx::Size GpuMemoryBufferImpl::GetSize() const {
- return size_;
-}
-
-gfx::BufferFormat GpuMemoryBufferImpl::GetFormat() const {
- return format_;
-}
-
-gfx::GpuMemoryBufferId GpuMemoryBufferImpl::GetId() const {
- return id_;
-}
-
-ClientBuffer GpuMemoryBufferImpl::AsClientBuffer() {
- return reinterpret_cast<ClientBuffer>(this);
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl.h b/chromium/content/common/gpu/client/gpu_memory_buffer_impl.h
deleted file mode 100644
index 954a87535fd..00000000000
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_H_
-#define CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_H_
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/common/content_export.h"
-#include "gpu/command_buffer/common/sync_token.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/gpu_memory_buffer.h"
-
-namespace content {
-
-// Provides common implementation of a GPU memory buffer.
-class CONTENT_EXPORT GpuMemoryBufferImpl : public gfx::GpuMemoryBuffer {
- public:
- typedef base::Callback<void(const gpu::SyncToken& sync)> DestructionCallback;
-
- ~GpuMemoryBufferImpl() override;
-
- // Creates an instance from the given |handle|. |size| and |internalformat|
- // should match what was used to allocate the |handle|. |callback| is
- // called when instance is deleted, which is not necessarily on the same
- // thread as this function was called on and instance was created on.
- static scoped_ptr<GpuMemoryBufferImpl> CreateFromHandle(
- const gfx::GpuMemoryBufferHandle& handle,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- const DestructionCallback& callback);
-
- // Type-checking upcast routine. Returns an NULL on failure.
- static GpuMemoryBufferImpl* FromClientBuffer(ClientBuffer buffer);
-
- // Overridden from gfx::GpuMemoryBuffer:
- gfx::Size GetSize() const override;
- gfx::BufferFormat GetFormat() const override;
- gfx::GpuMemoryBufferId GetId() const override;
- ClientBuffer AsClientBuffer() override;
-
- void set_destruction_sync_token(const gpu::SyncToken& sync_token) {
- destruction_sync_token_ = sync_token;
- }
-
- protected:
- GpuMemoryBufferImpl(gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- const DestructionCallback& callback);
-
- const gfx::GpuMemoryBufferId id_;
- const gfx::Size size_;
- const gfx::BufferFormat format_;
- const DestructionCallback callback_;
- bool mapped_;
- gpu::SyncToken destruction_sync_token_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_H_
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.cc
deleted file mode 100644
index b6038cf72da..00000000000
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.cc
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h"
-
-#include "base/logging.h"
-#include "content/common/gpu/gpu_memory_buffer_factory_io_surface.h"
-#include "ui/gfx/buffer_format_util.h"
-#include "ui/gfx/mac/io_surface.h"
-
-namespace content {
-namespace {
-
-uint32_t LockFlags(gfx::BufferUsage usage) {
- switch (usage) {
- case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE:
- return kIOSurfaceLockAvoidSync;
- case gfx::BufferUsage::GPU_READ:
- case gfx::BufferUsage::SCANOUT:
- case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE_PERSISTENT:
- return 0;
- }
- NOTREACHED();
- return 0;
-}
-
-void NoOp() {
-}
-
-} // namespace
-
-GpuMemoryBufferImplIOSurface::GpuMemoryBufferImplIOSurface(
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- const DestructionCallback& callback,
- IOSurfaceRef io_surface,
- uint32_t lock_flags)
- : GpuMemoryBufferImpl(id, size, format, callback),
- io_surface_(io_surface),
- lock_flags_(lock_flags) {}
-
-GpuMemoryBufferImplIOSurface::~GpuMemoryBufferImplIOSurface() {
-}
-
-// static
-scoped_ptr<GpuMemoryBufferImplIOSurface>
-GpuMemoryBufferImplIOSurface::CreateFromHandle(
- const gfx::GpuMemoryBufferHandle& handle,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- const DestructionCallback& callback) {
- base::ScopedCFTypeRef<IOSurfaceRef> io_surface(
- IOSurfaceLookupFromMachPort(handle.mach_port.get()));
- if (!io_surface)
- return nullptr;
-
- return make_scoped_ptr(
- new GpuMemoryBufferImplIOSurface(handle.id, size, format, callback,
- io_surface.release(), LockFlags(usage)));
-}
-
-// static
-bool GpuMemoryBufferImplIOSurface::IsConfigurationSupported(
- gfx::BufferFormat format,
- gfx::BufferUsage usage) {
- return GpuMemoryBufferFactoryIOSurface::
- IsGpuMemoryBufferConfigurationSupported(format, usage);
-}
-
-// static
-base::Closure GpuMemoryBufferImplIOSurface::AllocateForTesting(
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- gfx::GpuMemoryBufferHandle* handle) {
- base::ScopedCFTypeRef<IOSurfaceRef> io_surface(
- gfx::CreateIOSurface(size, format));
- DCHECK(io_surface);
- gfx::GpuMemoryBufferId kBufferId(1);
- handle->type = gfx::IO_SURFACE_BUFFER;
- handle->id = kBufferId;
- handle->mach_port.reset(IOSurfaceCreateMachPort(io_surface));
- return base::Bind(&NoOp);
-}
-
-bool GpuMemoryBufferImplIOSurface::Map() {
- DCHECK(!mapped_);
- IOReturn status = IOSurfaceLock(io_surface_, lock_flags_, NULL);
- DCHECK_NE(status, kIOReturnCannotLock);
- mapped_ = true;
- return true;
-}
-
-void* GpuMemoryBufferImplIOSurface::memory(size_t plane) {
- DCHECK(mapped_);
- DCHECK_LT(plane, gfx::NumberOfPlanesForBufferFormat(format_));
- return IOSurfaceGetBaseAddressOfPlane(io_surface_, plane);
-}
-
-void GpuMemoryBufferImplIOSurface::Unmap() {
- DCHECK(mapped_);
- IOSurfaceUnlock(io_surface_, lock_flags_, NULL);
- mapped_ = false;
-}
-
-bool GpuMemoryBufferImplIOSurface::IsInUseByMacOSWindowServer() const {
- return IOSurfaceIsInUse(io_surface_);
-}
-
-int GpuMemoryBufferImplIOSurface::stride(size_t plane) const {
- DCHECK_LT(plane, gfx::NumberOfPlanesForBufferFormat(format_));
- return IOSurfaceGetBytesPerRowOfPlane(io_surface_, plane);
-}
-
-gfx::GpuMemoryBufferHandle GpuMemoryBufferImplIOSurface::GetHandle() const {
- gfx::GpuMemoryBufferHandle handle;
- handle.type = gfx::IO_SURFACE_BUFFER;
- handle.id = id_;
- return handle;
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h
deleted file mode 100644
index 8883cc1a3e2..00000000000
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_IO_SURFACE_H_
-#define CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_IO_SURFACE_H_
-
-#include <IOSurface/IOSurface.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#include "base/mac/scoped_cftyperef.h"
-#include "base/macros.h"
-#include "content/common/content_export.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
-
-namespace content {
-
-// Implementation of GPU memory buffer based on IO surfaces.
-class CONTENT_EXPORT GpuMemoryBufferImplIOSurface : public GpuMemoryBufferImpl {
- public:
- ~GpuMemoryBufferImplIOSurface() override;
-
- static scoped_ptr<GpuMemoryBufferImplIOSurface> CreateFromHandle(
- const gfx::GpuMemoryBufferHandle& handle,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- const DestructionCallback& callback);
-
- static bool IsConfigurationSupported(gfx::BufferFormat format,
- gfx::BufferUsage usage);
-
- static base::Closure AllocateForTesting(const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- gfx::GpuMemoryBufferHandle* handle);
-
- // Overridden from gfx::GpuMemoryBuffer:
- bool Map() override;
- void* memory(size_t plane) override;
- void Unmap() override;
- bool IsInUseByMacOSWindowServer() const override;
- int stride(size_t plane) const override;
- gfx::GpuMemoryBufferHandle GetHandle() const override;
-
- private:
- GpuMemoryBufferImplIOSurface(gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- const DestructionCallback& callback,
- IOSurfaceRef io_surface,
- uint32_t lock_flags);
-
- base::ScopedCFTypeRef<IOSurfaceRef> io_surface_;
- uint32_t lock_flags_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferImplIOSurface);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_IO_SURFACE_H_
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface_unittest.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface_unittest.cc
deleted file mode 100644
index 83edce6c3e7..00000000000
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_io_surface_unittest.cc
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/client/gpu_memory_buffer_impl_io_surface.h"
-#include "content/test/gpu_memory_buffer_impl_test_template.h"
-
-namespace content {
-namespace {
-
-INSTANTIATE_TYPED_TEST_CASE_P(GpuMemoryBufferImplIOSurface,
- GpuMemoryBufferImplTest,
- GpuMemoryBufferImplIOSurface);
-
-} // namespace
-} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_pixmap.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_pixmap.cc
deleted file mode 100644
index c0303555ad9..00000000000
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_pixmap.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_pixmap.h"
-
-#include <utility>
-
-#include "content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.h"
-#include "ui/gfx/buffer_format_util.h"
-#include "ui/ozone/public/client_native_pixmap_factory.h"
-#include "ui/ozone/public/native_pixmap.h"
-#include "ui/ozone/public/ozone_platform.h"
-#include "ui/ozone/public/surface_factory_ozone.h"
-
-namespace content {
-namespace {
-
-void FreeNativePixmapForTesting(scoped_refptr<ui::NativePixmap> native_pixmap) {
- // Nothing to do here. |native_pixmap| will be freed when this function
- // returns and reference count drops to 0.
-}
-
-} // namespace
-
-GpuMemoryBufferImplOzoneNativePixmap::GpuMemoryBufferImplOzoneNativePixmap(
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- const DestructionCallback& callback,
- scoped_ptr<ui::ClientNativePixmap> pixmap)
- : GpuMemoryBufferImpl(id, size, format, callback),
- pixmap_(std::move(pixmap)) {}
-
-GpuMemoryBufferImplOzoneNativePixmap::~GpuMemoryBufferImplOzoneNativePixmap() {}
-
-// static
-scoped_ptr<GpuMemoryBufferImplOzoneNativePixmap>
-GpuMemoryBufferImplOzoneNativePixmap::CreateFromHandle(
- const gfx::GpuMemoryBufferHandle& handle,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- const DestructionCallback& callback) {
- scoped_ptr<ui::ClientNativePixmap> native_pixmap =
- ui::ClientNativePixmapFactory::GetInstance()->ImportFromHandle(
- handle.native_pixmap_handle, size, usage);
- DCHECK(native_pixmap);
- return make_scoped_ptr(new GpuMemoryBufferImplOzoneNativePixmap(
- handle.id, size, format, callback, std::move(native_pixmap)));
-}
-
-// static
-bool GpuMemoryBufferImplOzoneNativePixmap::IsConfigurationSupported(
- gfx::BufferFormat format,
- gfx::BufferUsage usage) {
- return GpuMemoryBufferFactoryOzoneNativePixmap::
- IsGpuMemoryBufferConfigurationSupported(format, usage);
-}
-
-// static
-base::Closure GpuMemoryBufferImplOzoneNativePixmap::AllocateForTesting(
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- gfx::GpuMemoryBufferHandle* handle) {
- DCHECK(IsConfigurationSupported(format, usage));
- scoped_refptr<ui::NativePixmap> pixmap =
- ui::OzonePlatform::GetInstance()
- ->GetSurfaceFactoryOzone()
- ->CreateNativePixmap(gfx::kNullPluginWindow, size, format, usage);
- handle->type = gfx::OZONE_NATIVE_PIXMAP;
- handle->native_pixmap_handle = pixmap->ExportHandle();
- return base::Bind(&FreeNativePixmapForTesting, pixmap);
-}
-
-bool GpuMemoryBufferImplOzoneNativePixmap::Map() {
- DCHECK(!mapped_);
- if (!pixmap_->Map())
- return false;
- mapped_ = true;
- return mapped_;
-}
-
-void* GpuMemoryBufferImplOzoneNativePixmap::memory(size_t plane) {
- DCHECK(mapped_);
- DCHECK_LT(plane, gfx::NumberOfPlanesForBufferFormat(format_));
- return pixmap_->Map();
-}
-
-void GpuMemoryBufferImplOzoneNativePixmap::Unmap() {
- DCHECK(mapped_);
- pixmap_->Unmap();
- mapped_ = false;
-}
-
-int GpuMemoryBufferImplOzoneNativePixmap::stride(size_t plane) const {
- DCHECK_LT(plane, gfx::NumberOfPlanesForBufferFormat(format_));
- int stride;
- pixmap_->GetStride(&stride);
- return stride;
-}
-
-gfx::GpuMemoryBufferHandle GpuMemoryBufferImplOzoneNativePixmap::GetHandle()
- const {
- gfx::GpuMemoryBufferHandle handle;
- handle.type = gfx::OZONE_NATIVE_PIXMAP;
- handle.id = id_;
- return handle;
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_pixmap.h b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_pixmap.h
deleted file mode 100644
index aa073e111e3..00000000000
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_pixmap.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_OZONE_NATIVE_PIXMAP_H_
-#define CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_OZONE_NATIVE_PIXMAP_H_
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "content/common/content_export.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
-
-namespace ui {
-class ClientNativePixmap;
-}
-
-namespace content {
-
-// Implementation of GPU memory buffer based on Ozone native pixmap.
-class CONTENT_EXPORT GpuMemoryBufferImplOzoneNativePixmap
- : public GpuMemoryBufferImpl {
- public:
- ~GpuMemoryBufferImplOzoneNativePixmap() override;
-
- static scoped_ptr<GpuMemoryBufferImplOzoneNativePixmap> CreateFromHandle(
- const gfx::GpuMemoryBufferHandle& handle,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- const DestructionCallback& callback);
-
- static bool IsConfigurationSupported(gfx::BufferFormat format,
- gfx::BufferUsage usage);
-
- static base::Closure AllocateForTesting(const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- gfx::GpuMemoryBufferHandle* handle);
-
- // Overridden from gfx::GpuMemoryBuffer:
- bool Map() override;
- void* memory(size_t plane) override;
- void Unmap() override;
- int stride(size_t plane) const override;
- gfx::GpuMemoryBufferHandle GetHandle() const override;
-
- private:
- GpuMemoryBufferImplOzoneNativePixmap(
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- const DestructionCallback& callback,
- scoped_ptr<ui::ClientNativePixmap> native_pixmap);
-
- scoped_ptr<ui::ClientNativePixmap> pixmap_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferImplOzoneNativePixmap);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_OZONE_NATIVE_PIXMAP_H_
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_pixmap_unittest.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_pixmap_unittest.cc
deleted file mode 100644
index 08295c5186e..00000000000
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_pixmap_unittest.cc
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/client/gpu_memory_buffer_impl_ozone_native_pixmap.h"
-#include "content/test/gpu_memory_buffer_impl_test_template.h"
-
-namespace content {
-namespace {
-
-INSTANTIATE_TYPED_TEST_CASE_P(GpuMemoryBufferImplOzoneNativePixmap,
- GpuMemoryBufferImplTest,
- GpuMemoryBufferImplOzoneNativePixmap);
-
-} // namespace
-} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.cc
deleted file mode 100644
index 83781ae8553..00000000000
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.cc
+++ /dev/null
@@ -1,224 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h"
-
-#include <stdint.h>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/numerics/safe_math.h"
-#include "base/process/memory.h"
-#include "ui/gfx/buffer_format_util.h"
-#include "ui/gl/gl_bindings.h"
-
-namespace content {
-namespace {
-
-void Noop() {}
-
-} // namespace
-
-GpuMemoryBufferImplSharedMemory::GpuMemoryBufferImplSharedMemory(
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- const DestructionCallback& callback,
- scoped_ptr<base::SharedMemory> shared_memory,
- size_t offset,
- int stride)
- : GpuMemoryBufferImpl(id, size, format, callback),
- shared_memory_(std::move(shared_memory)),
- offset_(offset),
- stride_(stride) {
- DCHECK(IsSizeValidForFormat(size, format));
-}
-
-GpuMemoryBufferImplSharedMemory::~GpuMemoryBufferImplSharedMemory() {
-}
-
-// static
-scoped_ptr<GpuMemoryBufferImplSharedMemory>
-GpuMemoryBufferImplSharedMemory::Create(gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- const DestructionCallback& callback) {
- size_t buffer_size = 0u;
- if (!gfx::BufferSizeForBufferFormatChecked(size, format, &buffer_size))
- return nullptr;
-
- scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory());
- if (!shared_memory->CreateAndMapAnonymous(buffer_size))
- return nullptr;
-
- return make_scoped_ptr(new GpuMemoryBufferImplSharedMemory(
- id, size, format, callback, std::move(shared_memory), 0,
- gfx::RowSizeForBufferFormat(size.width(), format, 0)));
-}
-
-// static
-gfx::GpuMemoryBufferHandle
-GpuMemoryBufferImplSharedMemory::AllocateForChildProcess(
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- base::ProcessHandle child_process) {
- size_t buffer_size = 0u;
- if (!gfx::BufferSizeForBufferFormatChecked(size, format, &buffer_size))
- return gfx::GpuMemoryBufferHandle();
-
- base::SharedMemory shared_memory;
- if (!shared_memory.CreateAnonymous(buffer_size))
- return gfx::GpuMemoryBufferHandle();
-
- gfx::GpuMemoryBufferHandle handle;
- handle.type = gfx::SHARED_MEMORY_BUFFER;
- handle.id = id;
- handle.offset = 0;
- handle.stride = static_cast<int32_t>(
- gfx::RowSizeForBufferFormat(size.width(), format, 0));
- shared_memory.GiveToProcess(child_process, &handle.handle);
- return handle;
-}
-
-// static
-scoped_ptr<GpuMemoryBufferImplSharedMemory>
-GpuMemoryBufferImplSharedMemory::CreateFromHandle(
- const gfx::GpuMemoryBufferHandle& handle,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- const DestructionCallback& callback) {
- DCHECK(base::SharedMemory::IsHandleValid(handle.handle));
-
- return make_scoped_ptr(new GpuMemoryBufferImplSharedMemory(
- handle.id, size, format, callback,
- make_scoped_ptr(new base::SharedMemory(handle.handle, false)),
- handle.offset, handle.stride));
-}
-
-// static
-bool GpuMemoryBufferImplSharedMemory::IsUsageSupported(gfx::BufferUsage usage) {
- switch (usage) {
- case gfx::BufferUsage::GPU_READ:
- case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE:
- case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE_PERSISTENT:
- return true;
- case gfx::BufferUsage::SCANOUT:
- return false;
- }
- NOTREACHED();
- return false;
-}
-
-// static
-bool GpuMemoryBufferImplSharedMemory::IsConfigurationSupported(
- gfx::BufferFormat format,
- gfx::BufferUsage usage) {
- return IsUsageSupported(usage);
-}
-
-// static
-bool GpuMemoryBufferImplSharedMemory::IsSizeValidForFormat(
- const gfx::Size& size,
- gfx::BufferFormat format) {
- switch (format) {
- case gfx::BufferFormat::ATC:
- case gfx::BufferFormat::ATCIA:
- case gfx::BufferFormat::DXT1:
- case gfx::BufferFormat::DXT5:
- case gfx::BufferFormat::ETC1:
- // Compressed images must have a width and height that's evenly divisible
- // by the block size.
- return size.width() % 4 == 0 && size.height() % 4 == 0;
- case gfx::BufferFormat::R_8:
- case gfx::BufferFormat::RGBA_4444:
- case gfx::BufferFormat::RGBA_8888:
- case gfx::BufferFormat::RGBX_8888:
- case gfx::BufferFormat::BGRA_8888:
- case gfx::BufferFormat::BGRX_8888:
- return true;
- case gfx::BufferFormat::YUV_420:
- case gfx::BufferFormat::YUV_420_BIPLANAR: {
- size_t num_planes = gfx::NumberOfPlanesForBufferFormat(format);
- for (size_t i = 0; i < num_planes; ++i) {
- size_t factor = gfx::SubsamplingFactorForBufferFormat(format, i);
- if (size.width() % factor || size.height() % factor)
- return false;
- }
- return true;
- }
- case gfx::BufferFormat::UYVY_422:
- return size.width() % 2 == 0;
- }
-
- NOTREACHED();
- return false;
-}
-
-// static
-base::Closure GpuMemoryBufferImplSharedMemory::AllocateForTesting(
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- gfx::GpuMemoryBufferHandle* handle) {
- base::SharedMemory shared_memory;
- bool rv = shared_memory.CreateAnonymous(
- gfx::BufferSizeForBufferFormat(size, format));
- DCHECK(rv);
- handle->type = gfx::SHARED_MEMORY_BUFFER;
- handle->offset = 0;
- handle->stride = static_cast<int32_t>(
- gfx::RowSizeForBufferFormat(size.width(), format, 0));
- handle->handle = base::SharedMemory::DuplicateHandle(shared_memory.handle());
- return base::Bind(&Noop);
-}
-
-bool GpuMemoryBufferImplSharedMemory::Map() {
- DCHECK(!mapped_);
-
- // Map the buffer first time Map() is called then keep it mapped for the
- // lifetime of the buffer. This avoids mapping the buffer unless necessary.
- if (!shared_memory_->memory()) {
- DCHECK_EQ(static_cast<size_t>(stride_),
- gfx::RowSizeForBufferFormat(size_.width(), format_, 0));
- size_t buffer_size = gfx::BufferSizeForBufferFormat(size_, format_);
- // Note: offset_ != 0 is not common use-case. To keep it simple we
- // map offset + buffer_size here but this can be avoided using MapAt().
- size_t map_size = offset_ + buffer_size;
- if (!shared_memory_->Map(map_size))
- base::TerminateBecauseOutOfMemory(map_size);
- }
- mapped_ = true;
- return true;
-}
-
-void* GpuMemoryBufferImplSharedMemory::memory(size_t plane) {
- DCHECK(mapped_);
- DCHECK_LT(plane, gfx::NumberOfPlanesForBufferFormat(format_));
- return reinterpret_cast<uint8_t*>(shared_memory_->memory()) + offset_ +
- gfx::BufferOffsetForBufferFormat(size_, format_, plane);
-}
-
-void GpuMemoryBufferImplSharedMemory::Unmap() {
- DCHECK(mapped_);
- mapped_ = false;
-}
-
-int GpuMemoryBufferImplSharedMemory::stride(size_t plane) const {
- DCHECK_LT(plane, gfx::NumberOfPlanesForBufferFormat(format_));
- return gfx::RowSizeForBufferFormat(size_.width(), format_, plane);
-}
-
-gfx::GpuMemoryBufferHandle GpuMemoryBufferImplSharedMemory::GetHandle() const {
- gfx::GpuMemoryBufferHandle handle;
- handle.type = gfx::SHARED_MEMORY_BUFFER;
- handle.id = id_;
- handle.offset = offset_;
- handle.stride = stride_;
- handle.handle = shared_memory_->handle();
- return handle;
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h
deleted file mode 100644
index 9416cbb31e1..00000000000
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_SHARED_MEMORY_H_
-#define CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_SHARED_MEMORY_H_
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "content/common/content_export.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
-
-namespace content {
-
-// Implementation of GPU memory buffer based on shared memory.
-class CONTENT_EXPORT GpuMemoryBufferImplSharedMemory
- : public GpuMemoryBufferImpl {
- public:
- ~GpuMemoryBufferImplSharedMemory() override;
-
- static scoped_ptr<GpuMemoryBufferImplSharedMemory> Create(
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- const DestructionCallback& callback);
-
- static gfx::GpuMemoryBufferHandle AllocateForChildProcess(
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- base::ProcessHandle child_process);
-
- static scoped_ptr<GpuMemoryBufferImplSharedMemory> CreateFromHandle(
- const gfx::GpuMemoryBufferHandle& handle,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- const DestructionCallback& callback);
-
- static bool IsUsageSupported(gfx::BufferUsage usage);
- static bool IsConfigurationSupported(gfx::BufferFormat format,
- gfx::BufferUsage usage);
- static bool IsSizeValidForFormat(const gfx::Size& size,
- gfx::BufferFormat format);
-
- static base::Closure AllocateForTesting(const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- gfx::GpuMemoryBufferHandle* handle);
-
- // Overridden from gfx::GpuMemoryBuffer:
- bool Map() override;
- void* memory(size_t plane) override;
- void Unmap() override;
- int stride(size_t plane) const override;
- gfx::GpuMemoryBufferHandle GetHandle() const override;
-
- private:
- GpuMemoryBufferImplSharedMemory(gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- const DestructionCallback& callback,
- scoped_ptr<base::SharedMemory> shared_memory,
- size_t offset,
- int stride);
-
- scoped_ptr<base::SharedMemory> shared_memory_;
- size_t offset_;
- int stride_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferImplSharedMemory);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_SHARED_MEMORY_H_
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory_unittest.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory_unittest.cc
deleted file mode 100644
index 251e16c4a3a..00000000000
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_shared_memory_unittest.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/client/gpu_memory_buffer_impl_shared_memory.h"
-#include "content/test/gpu_memory_buffer_impl_test_template.h"
-
-namespace content {
-namespace {
-
-INSTANTIATE_TYPED_TEST_CASE_P(GpuMemoryBufferImplSharedMemory,
- GpuMemoryBufferImplTest,
- GpuMemoryBufferImplSharedMemory);
-
-void BufferDestroyed(bool* destroyed, const gpu::SyncToken& sync_token) {
- *destroyed = true;
-}
-
-TEST(GpuMemoryBufferImplSharedMemoryTest, Create) {
- const gfx::GpuMemoryBufferId kBufferId(1);
-
- gfx::Size buffer_size(8, 8);
-
- for (auto format : gfx::GetBufferFormatsForTesting()) {
- bool destroyed = false;
- scoped_ptr<GpuMemoryBufferImplSharedMemory> buffer(
- GpuMemoryBufferImplSharedMemory::Create(
- kBufferId, buffer_size, format,
- base::Bind(&BufferDestroyed, base::Unretained(&destroyed))));
- ASSERT_TRUE(buffer);
- EXPECT_EQ(buffer->GetFormat(), format);
-
- // Check if destruction callback is executed when deleting the buffer.
- buffer.reset();
- ASSERT_TRUE(destroyed);
- }
-}
-
-} // namespace
-} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.cc
deleted file mode 100644
index 64de624c155..00000000000
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.cc
+++ /dev/null
@@ -1,151 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.h"
-
-#include "base/logging.h"
-#include "base/trace_event/trace_event.h"
-#include "content/common/android/surface_texture_manager.h"
-#include "content/common/gpu/gpu_memory_buffer_factory_surface_texture.h"
-#include "ui/gfx/buffer_format_util.h"
-#include "ui/gl/android/surface_texture.h"
-#include "ui/gl/gl_bindings.h"
-
-namespace content {
-namespace {
-
-int WindowFormat(gfx::BufferFormat format) {
- switch (format) {
- case gfx::BufferFormat::RGBA_8888:
- return WINDOW_FORMAT_RGBA_8888;
- case gfx::BufferFormat::ATC:
- case gfx::BufferFormat::ATCIA:
- case gfx::BufferFormat::DXT1:
- case gfx::BufferFormat::DXT5:
- case gfx::BufferFormat::ETC1:
- case gfx::BufferFormat::R_8:
- case gfx::BufferFormat::RGBA_4444:
- case gfx::BufferFormat::RGBX_8888:
- case gfx::BufferFormat::BGRX_8888:
- case gfx::BufferFormat::BGRA_8888:
- case gfx::BufferFormat::YUV_420:
- case gfx::BufferFormat::YUV_420_BIPLANAR:
- case gfx::BufferFormat::UYVY_422:
- NOTREACHED();
- return 0;
- }
-
- NOTREACHED();
- return 0;
-}
-
-void FreeSurfaceTextureForTesting(
- scoped_refptr<gfx::SurfaceTexture> surface_texture,
- gfx::GpuMemoryBufferId id) {
- SurfaceTextureManager::GetInstance()->UnregisterSurfaceTexture(id.id, 0);
-}
-
-} // namespace
-
-GpuMemoryBufferImplSurfaceTexture::GpuMemoryBufferImplSurfaceTexture(
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- const DestructionCallback& callback,
- ANativeWindow* native_window)
- : GpuMemoryBufferImpl(id, size, format, callback),
- native_window_(native_window) {}
-
-GpuMemoryBufferImplSurfaceTexture::~GpuMemoryBufferImplSurfaceTexture() {
- ANativeWindow_release(native_window_);
-}
-
-// static
-scoped_ptr<GpuMemoryBufferImplSurfaceTexture>
-GpuMemoryBufferImplSurfaceTexture::CreateFromHandle(
- const gfx::GpuMemoryBufferHandle& handle,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- const DestructionCallback& callback) {
- ANativeWindow* native_window =
- SurfaceTextureManager::GetInstance()
- ->AcquireNativeWidgetForSurfaceTexture(handle.id.id);
- if (!native_window)
- return nullptr;
-
- ANativeWindow_setBuffersGeometry(
- native_window, size.width(), size.height(), WindowFormat(format));
-
- return make_scoped_ptr(new GpuMemoryBufferImplSurfaceTexture(
- handle.id, size, format, callback, native_window));
-}
-
-// static
-bool GpuMemoryBufferImplSurfaceTexture::IsConfigurationSupported(
- gfx::BufferFormat format,
- gfx::BufferUsage usage) {
- return GpuMemoryBufferFactorySurfaceTexture::
- IsGpuMemoryBufferConfigurationSupported(format, usage);
-}
-
-// static
-base::Closure GpuMemoryBufferImplSurfaceTexture::AllocateForTesting(
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- gfx::GpuMemoryBufferHandle* handle) {
- scoped_refptr<gfx::SurfaceTexture> surface_texture =
- gfx::SurfaceTexture::Create(0);
- DCHECK(surface_texture);
- const gfx::GpuMemoryBufferId kBufferId(1);
- SurfaceTextureManager::GetInstance()->RegisterSurfaceTexture(
- kBufferId.id, 0, surface_texture.get());
- handle->type = gfx::SURFACE_TEXTURE_BUFFER;
- handle->id = kBufferId;
- return base::Bind(&FreeSurfaceTextureForTesting, surface_texture, kBufferId);
-}
-
-bool GpuMemoryBufferImplSurfaceTexture::Map() {
- TRACE_EVENT0("gpu", "GpuMemoryBufferImplSurfaceTexture::Map");
- DCHECK(!mapped_);
- DCHECK(native_window_);
- if (ANativeWindow_lock(native_window_, &buffer_, NULL)) {
- DPLOG(ERROR) << "ANativeWindow_lock failed";
- return false;
- }
- DCHECK_LE(size_.width(), buffer_.stride);
- mapped_ = true;
- return true;
-}
-
-void* GpuMemoryBufferImplSurfaceTexture::memory(size_t plane) {
- TRACE_EVENT0("gpu", "GpuMemoryBufferImplSurfaceTexture::memory");
- DCHECK(mapped_);
- DCHECK_EQ(0u, plane);
- return buffer_.bits;
-}
-
-void GpuMemoryBufferImplSurfaceTexture::Unmap() {
- TRACE_EVENT0("gpu", "GpuMemoryBufferImplSurfaceTexture::Unmap");
- DCHECK(mapped_);
- ANativeWindow_unlockAndPost(native_window_);
- mapped_ = false;
-}
-
-int GpuMemoryBufferImplSurfaceTexture::stride(size_t plane) const {
- DCHECK(mapped_);
- DCHECK_EQ(0u, plane);
- return gfx::RowSizeForBufferFormat(buffer_.stride, format_, 0);
-}
-
-gfx::GpuMemoryBufferHandle
-GpuMemoryBufferImplSurfaceTexture::GetHandle() const {
- gfx::GpuMemoryBufferHandle handle;
- handle.type = gfx::SURFACE_TEXTURE_BUFFER;
- handle.id = id_;
- return handle;
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.h b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.h
deleted file mode 100644
index 1613c63134b..00000000000
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_SURFACE_TEXTURE_H_
-#define CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_SURFACE_TEXTURE_H_
-
-#include <android/native_window.h>
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "content/common/content_export.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
-
-namespace content {
-
-// Implementation of GPU memory buffer based on SurfaceTextures.
-class CONTENT_EXPORT GpuMemoryBufferImplSurfaceTexture
- : public GpuMemoryBufferImpl {
- public:
- ~GpuMemoryBufferImplSurfaceTexture() override;
-
- static scoped_ptr<GpuMemoryBufferImplSurfaceTexture> CreateFromHandle(
- const gfx::GpuMemoryBufferHandle& handle,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- const DestructionCallback& callback);
-
- static bool IsConfigurationSupported(gfx::BufferFormat format,
- gfx::BufferUsage usage);
-
- static base::Closure AllocateForTesting(const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- gfx::GpuMemoryBufferHandle* handle);
-
- // Overridden from gfx::GpuMemoryBuffer:
- bool Map() override;
- void* memory(size_t plane) override;
- void Unmap() override;
- int stride(size_t plane) const override;
- gfx::GpuMemoryBufferHandle GetHandle() const override;
-
- private:
- GpuMemoryBufferImplSurfaceTexture(gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- const DestructionCallback& callback,
- ANativeWindow* native_window);
-
- ANativeWindow* native_window_;
- ANativeWindow_Buffer buffer_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferImplSurfaceTexture);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_CLIENT_GPU_MEMORY_BUFFER_IMPL_SURFACE_TEXTURE_H_
diff --git a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture_unittest.cc b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture_unittest.cc
index 1cd513df3ac..a3edc70bd8b 100644
--- a/chromium/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture_unittest.cc
+++ b/chromium/content/common/gpu/client/gpu_memory_buffer_impl_surface_texture_unittest.cc
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/common/gpu/client/gpu_memory_buffer_impl_surface_texture.h"
-#include "content/test/gpu_memory_buffer_impl_test_template.h"
+#include "gpu/ipc/client/gpu_memory_buffer_impl_surface_texture.h"
+#include "gpu/ipc/client/gpu_memory_buffer_impl_test_template.h"
-namespace content {
+namespace gpu {
namespace {
INSTANTIATE_TYPED_TEST_CASE_P(GpuMemoryBufferImplSurfaceTexture,
@@ -13,4 +13,4 @@ INSTANTIATE_TYPED_TEST_CASE_P(GpuMemoryBufferImplSurfaceTexture,
GpuMemoryBufferImplSurfaceTexture);
} // namespace
-} // namespace content
+} // namespace gpu
diff --git a/chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.cc b/chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.cc
deleted file mode 100644
index 19a336b9ca3..00000000000
--- a/chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.cc
+++ /dev/null
@@ -1,292 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/client/gpu_video_decode_accelerator_host.h"
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/message_loop/message_loop.h"
-#include "build/build_config.h"
-#include "content/common/gpu/client/gpu_channel_host.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "content/common/view_messages.h"
-#include "ipc/ipc_message_macros.h"
-#include "ipc/ipc_message_utils.h"
-
-#if defined(OS_WIN)
-#include "content/public/common/sandbox_init.h"
-#endif // OS_WIN
-
-using media::VideoDecodeAccelerator;
-namespace content {
-
-GpuVideoDecodeAcceleratorHost::GpuVideoDecodeAcceleratorHost(
- GpuChannelHost* channel,
- CommandBufferProxyImpl* impl)
- : channel_(channel),
- decoder_route_id_(MSG_ROUTING_NONE),
- client_(NULL),
- impl_(impl),
- weak_this_factory_(this) {
- DCHECK(channel_);
- DCHECK(impl_);
- impl_->AddDeletionObserver(this);
-}
-
-GpuVideoDecodeAcceleratorHost::~GpuVideoDecodeAcceleratorHost() {
- DCHECK(CalledOnValidThread());
-
- if (channel_ && decoder_route_id_ != MSG_ROUTING_NONE)
- channel_->RemoveRoute(decoder_route_id_);
- if (impl_)
- impl_->RemoveDeletionObserver(this);
-}
-
-bool GpuVideoDecodeAcceleratorHost::OnMessageReceived(const IPC::Message& msg) {
- DCHECK(CalledOnValidThread());
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(GpuVideoDecodeAcceleratorHost, msg)
- IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_CdmAttached,
- OnCdmAttached)
- IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed,
- OnBitstreamBufferProcessed)
- IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers,
- OnProvidePictureBuffer)
- IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_PictureReady,
- OnPictureReady)
- IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_FlushDone,
- OnFlushDone)
- IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ResetDone,
- OnResetDone)
- IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_ErrorNotification,
- OnNotifyError)
- IPC_MESSAGE_HANDLER(AcceleratedVideoDecoderHostMsg_DismissPictureBuffer,
- OnDismissPictureBuffer)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- DCHECK(handled);
- // See OnNotifyError for why |this| mustn't be used after OnNotifyError might
- // have been called above.
- return handled;
-}
-
-void GpuVideoDecodeAcceleratorHost::OnChannelError() {
- DCHECK(CalledOnValidThread());
- if (channel_) {
- if (decoder_route_id_ != MSG_ROUTING_NONE)
- channel_->RemoveRoute(decoder_route_id_);
- channel_ = NULL;
- }
- DLOG(ERROR) << "OnChannelError()";
- PostNotifyError(PLATFORM_FAILURE);
-}
-
-bool GpuVideoDecodeAcceleratorHost::Initialize(const Config& config,
- Client* client) {
- DCHECK(CalledOnValidThread());
- client_ = client;
-
- if (!impl_)
- return false;
-
- int32_t route_id = channel_->GenerateRouteID();
- channel_->AddRoute(route_id, weak_this_factory_.GetWeakPtr());
-
- bool succeeded = false;
- Send(new GpuCommandBufferMsg_CreateVideoDecoder(impl_->route_id(), config,
- route_id, &succeeded));
-
- if (!succeeded) {
- DLOG(ERROR) << "Send(GpuCommandBufferMsg_CreateVideoDecoder()) failed";
- PostNotifyError(PLATFORM_FAILURE);
- channel_->RemoveRoute(route_id);
- return false;
- }
- decoder_route_id_ = route_id;
- return true;
-}
-
-void GpuVideoDecodeAcceleratorHost::SetCdm(int cdm_id) {
- DCHECK(CalledOnValidThread());
- if (!channel_)
- return;
- Send(new AcceleratedVideoDecoderMsg_SetCdm(decoder_route_id_, cdm_id));
-}
-
-void GpuVideoDecodeAcceleratorHost::Decode(
- const media::BitstreamBuffer& bitstream_buffer) {
- DCHECK(CalledOnValidThread());
- if (!channel_)
- return;
-
- base::SharedMemoryHandle handle = channel_->ShareToGpuProcess(
- bitstream_buffer.handle());
- if (!base::SharedMemory::IsHandleValid(handle)) {
- NOTREACHED() << "Failed to duplicate buffer handler";
- return;
- }
-
- AcceleratedVideoDecoderMsg_Decode_Params params;
- params.bitstream_buffer_id = bitstream_buffer.id();
- params.buffer_handle = handle;
- params.size = bitstream_buffer.size();
- params.presentation_timestamp = bitstream_buffer.presentation_timestamp();
- params.key_id = bitstream_buffer.key_id();
- params.iv = bitstream_buffer.iv();
- params.subsamples = bitstream_buffer.subsamples();
-
- Send(new AcceleratedVideoDecoderMsg_Decode(decoder_route_id_, params));
-}
-
-void GpuVideoDecodeAcceleratorHost::AssignPictureBuffers(
- const std::vector<media::PictureBuffer>& buffers) {
- DCHECK(CalledOnValidThread());
- if (!channel_)
- return;
- // Rearrange data for IPC command.
- std::vector<int32_t> buffer_ids;
- std::vector<uint32_t> texture_ids;
- for (uint32_t i = 0; i < buffers.size(); i++) {
- const media::PictureBuffer& buffer = buffers[i];
- if (buffer.size() != picture_buffer_dimensions_) {
- DLOG(ERROR) << "buffer.size() invalid: expected "
- << picture_buffer_dimensions_.ToString()
- << ", got " << buffer.size().ToString();
- PostNotifyError(INVALID_ARGUMENT);
- return;
- }
- texture_ids.push_back(buffer.texture_id());
- buffer_ids.push_back(buffer.id());
- }
- Send(new AcceleratedVideoDecoderMsg_AssignPictureBuffers(
- decoder_route_id_, buffer_ids, texture_ids));
-}
-
-void GpuVideoDecodeAcceleratorHost::ReusePictureBuffer(
- int32_t picture_buffer_id) {
- DCHECK(CalledOnValidThread());
- if (!channel_)
- return;
- Send(new AcceleratedVideoDecoderMsg_ReusePictureBuffer(
- decoder_route_id_, picture_buffer_id));
-}
-
-void GpuVideoDecodeAcceleratorHost::Flush() {
- DCHECK(CalledOnValidThread());
- if (!channel_)
- return;
- Send(new AcceleratedVideoDecoderMsg_Flush(decoder_route_id_));
-}
-
-void GpuVideoDecodeAcceleratorHost::Reset() {
- DCHECK(CalledOnValidThread());
- if (!channel_)
- return;
- Send(new AcceleratedVideoDecoderMsg_Reset(decoder_route_id_));
-}
-
-void GpuVideoDecodeAcceleratorHost::Destroy() {
- DCHECK(CalledOnValidThread());
- if (channel_)
- Send(new AcceleratedVideoDecoderMsg_Destroy(decoder_route_id_));
- client_ = NULL;
- delete this;
-}
-
-void GpuVideoDecodeAcceleratorHost::OnWillDeleteImpl() {
- DCHECK(CalledOnValidThread());
- impl_ = NULL;
-
- // The CommandBufferProxyImpl is going away; error out this VDA.
- OnChannelError();
-}
-
-void GpuVideoDecodeAcceleratorHost::PostNotifyError(Error error) {
- DCHECK(CalledOnValidThread());
- DVLOG(2) << "PostNotifyError(): error=" << error;
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&GpuVideoDecodeAcceleratorHost::OnNotifyError,
- weak_this_factory_.GetWeakPtr(), error));
-}
-
-void GpuVideoDecodeAcceleratorHost::Send(IPC::Message* message) {
- DCHECK(CalledOnValidThread());
- uint32_t message_type = message->type();
- if (!channel_->Send(message)) {
- DLOG(ERROR) << "Send(" << message_type << ") failed";
- PostNotifyError(PLATFORM_FAILURE);
- }
-}
-
-void GpuVideoDecodeAcceleratorHost::OnCdmAttached(bool success) {
- DCHECK(CalledOnValidThread());
- if (client_)
- client_->NotifyCdmAttached(success);
-}
-
-void GpuVideoDecodeAcceleratorHost::OnBitstreamBufferProcessed(
- int32_t bitstream_buffer_id) {
- DCHECK(CalledOnValidThread());
- if (client_)
- client_->NotifyEndOfBitstreamBuffer(bitstream_buffer_id);
-}
-
-void GpuVideoDecodeAcceleratorHost::OnProvidePictureBuffer(
- uint32_t num_requested_buffers,
- const gfx::Size& dimensions,
- uint32_t texture_target) {
- DCHECK(CalledOnValidThread());
- picture_buffer_dimensions_ = dimensions;
- if (client_) {
- client_->ProvidePictureBuffers(
- num_requested_buffers, dimensions, texture_target);
- }
-}
-
-void GpuVideoDecodeAcceleratorHost::OnDismissPictureBuffer(
- int32_t picture_buffer_id) {
- DCHECK(CalledOnValidThread());
- if (client_)
- client_->DismissPictureBuffer(picture_buffer_id);
-}
-
-void GpuVideoDecodeAcceleratorHost::OnPictureReady(
- int32_t picture_buffer_id,
- int32_t bitstream_buffer_id,
- const gfx::Rect& visible_rect,
- bool allow_overlay) {
- DCHECK(CalledOnValidThread());
- if (!client_)
- return;
- media::Picture picture(picture_buffer_id, bitstream_buffer_id, visible_rect,
- allow_overlay);
- client_->PictureReady(picture);
-}
-
-void GpuVideoDecodeAcceleratorHost::OnFlushDone() {
- DCHECK(CalledOnValidThread());
- if (client_)
- client_->NotifyFlushDone();
-}
-
-void GpuVideoDecodeAcceleratorHost::OnResetDone() {
- DCHECK(CalledOnValidThread());
- if (client_)
- client_->NotifyResetDone();
-}
-
-void GpuVideoDecodeAcceleratorHost::OnNotifyError(uint32_t error) {
- DCHECK(CalledOnValidThread());
- if (!client_)
- return;
- weak_this_factory_.InvalidateWeakPtrs();
-
- // Client::NotifyError() may Destroy() |this|, so calling it needs to be the
- // last thing done on this stack!
- media::VideoDecodeAccelerator::Client* client = NULL;
- std::swap(client, client_);
- client->NotifyError(static_cast<media::VideoDecodeAccelerator::Error>(error));
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.h b/chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.h
deleted file mode 100644
index 5e4ba9df1f6..00000000000
--- a/chromium/content/common/gpu/client/gpu_video_decode_accelerator_host.h
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_CLIENT_GPU_VIDEO_DECODE_ACCELERATOR_HOST_H_
-#define CONTENT_COMMON_GPU_CLIENT_GPU_VIDEO_DECODE_ACCELERATOR_HOST_H_
-
-#include <stdint.h>
-
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/threading/non_thread_safe.h"
-#include "content/common/gpu/client/command_buffer_proxy_impl.h"
-#include "ipc/ipc_listener.h"
-#include "media/video/video_decode_accelerator.h"
-#include "ui/gfx/geometry/size.h"
-
-namespace content {
-class GpuChannelHost;
-
-// This class is used to talk to VideoDecodeAccelerator in the Gpu process
-// through IPC messages.
-class GpuVideoDecodeAcceleratorHost
- : public IPC::Listener,
- public media::VideoDecodeAccelerator,
- public CommandBufferProxyImpl::DeletionObserver,
- public base::NonThreadSafe {
- public:
- // |this| is guaranteed not to outlive |channel| and |impl|. (See comments
- // for |channel_| and |impl_|.)
- GpuVideoDecodeAcceleratorHost(GpuChannelHost* channel,
- CommandBufferProxyImpl* impl);
-
- // IPC::Listener implementation.
- void OnChannelError() override;
- bool OnMessageReceived(const IPC::Message& message) override;
-
- // media::VideoDecodeAccelerator implementation.
- bool Initialize(const Config& config, Client* client) override;
- void SetCdm(int cdm_id) override;
- void Decode(const media::BitstreamBuffer& bitstream_buffer) override;
- void AssignPictureBuffers(
- const std::vector<media::PictureBuffer>& buffers) override;
- void ReusePictureBuffer(int32_t picture_buffer_id) override;
- void Flush() override;
- void Reset() override;
- void Destroy() override;
-
- // CommandBufferProxyImpl::DeletionObserver implemetnation.
- void OnWillDeleteImpl() override;
-
- private:
- // Only Destroy() should be deleting |this|.
- ~GpuVideoDecodeAcceleratorHost() override;
-
- // Notify |client_| of an error. Posts a task to avoid re-entrancy.
- void PostNotifyError(Error);
-
- void Send(IPC::Message* message);
-
- // IPC handlers, proxying media::VideoDecodeAccelerator::Client for the GPU
- // process. Should not be called directly.
- void OnCdmAttached(bool success);
- void OnBitstreamBufferProcessed(int32_t bitstream_buffer_id);
- void OnProvidePictureBuffer(uint32_t num_requested_buffers,
- const gfx::Size& dimensions,
- uint32_t texture_target);
- void OnDismissPictureBuffer(int32_t picture_buffer_id);
- void OnPictureReady(int32_t picture_buffer_id,
- int32_t bitstream_buffer_id,
- const gfx::Rect& visible_rect,
- bool allow_overlay);
- void OnFlushDone();
- void OnResetDone();
- void OnNotifyError(uint32_t error);
-
- // Unowned reference to the GpuChannelHost to send IPC messages to the GPU
- // process. |channel_| outlives |impl_|, so the reference is always valid as
- // long as it is not NULL.
- GpuChannelHost* channel_;
-
- // Route ID for the associated decoder in the GPU process.
- int32_t decoder_route_id_;
-
- // The client that will receive callbacks from the decoder.
- Client* client_;
-
- // Unowned reference to the CommandBufferProxyImpl that created us. |this|
- // registers as a DeletionObserver of |impl_|, the so reference is always
- // valid as long as it is not NULL.
- CommandBufferProxyImpl* impl_;
-
- // Requested dimensions of the buffer, from ProvidePictureBuffers().
- gfx::Size picture_buffer_dimensions_;
-
- // WeakPtr factory for posting tasks back to itself.
- base::WeakPtrFactory<GpuVideoDecodeAcceleratorHost> weak_this_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuVideoDecodeAcceleratorHost);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_CLIENT_GPU_VIDEO_DECODE_ACCELERATOR_HOST_H_
diff --git a/chromium/content/common/gpu/client/gpu_video_encode_accelerator_host.cc b/chromium/content/common/gpu/client/gpu_video_encode_accelerator_host.cc
deleted file mode 100644
index 9002490e1dd..00000000000
--- a/chromium/content/common/gpu/client/gpu_video_encode_accelerator_host.cc
+++ /dev/null
@@ -1,323 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/client/gpu_video_encode_accelerator_host.h"
-
-#include "base/location.h"
-#include "base/logging.h"
-#include "content/common/gpu/client/gpu_channel_host.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "content/common/gpu/media/gpu_video_accelerator_util.h"
-#include "media/base/video_frame.h"
-#include "media/video/video_encode_accelerator.h"
-#include "ui/gfx/gpu_memory_buffer.h"
-
-namespace content {
-
-GpuVideoEncodeAcceleratorHost::GpuVideoEncodeAcceleratorHost(
- GpuChannelHost* channel,
- CommandBufferProxyImpl* impl)
- : channel_(channel),
- encoder_route_id_(MSG_ROUTING_NONE),
- client_(NULL),
- impl_(impl),
- next_frame_id_(0),
- weak_this_factory_(this) {
- DCHECK(channel_);
- DCHECK(impl_);
- impl_->AddDeletionObserver(this);
-}
-
-GpuVideoEncodeAcceleratorHost::~GpuVideoEncodeAcceleratorHost() {
- DCHECK(CalledOnValidThread());
- if (channel_ && encoder_route_id_ != MSG_ROUTING_NONE)
- channel_->RemoveRoute(encoder_route_id_);
- if (impl_)
- impl_->RemoveDeletionObserver(this);
-}
-
-bool GpuVideoEncodeAcceleratorHost::OnMessageReceived(
- const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(GpuVideoEncodeAcceleratorHost, message)
- IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_RequireBitstreamBuffers,
- OnRequireBitstreamBuffers)
- IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_NotifyInputDone,
- OnNotifyInputDone)
- IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_BitstreamBufferReady,
- OnBitstreamBufferReady)
- IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderHostMsg_NotifyError,
- OnNotifyError)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- DCHECK(handled);
- // See OnNotifyError for why |this| mustn't be used after OnNotifyError might
- // have been called above.
- return handled;
-}
-
-void GpuVideoEncodeAcceleratorHost::OnChannelError() {
- DCHECK(CalledOnValidThread());
- if (channel_) {
- if (encoder_route_id_ != MSG_ROUTING_NONE)
- channel_->RemoveRoute(encoder_route_id_);
- channel_ = NULL;
- }
- PostNotifyError(FROM_HERE, kPlatformFailureError, "OnChannelError()");
-}
-
-media::VideoEncodeAccelerator::SupportedProfiles
-GpuVideoEncodeAcceleratorHost::GetSupportedProfiles() {
- DCHECK(CalledOnValidThread());
- if (!channel_)
- return media::VideoEncodeAccelerator::SupportedProfiles();
- return GpuVideoAcceleratorUtil::ConvertGpuToMediaEncodeProfiles(
- channel_->gpu_info().video_encode_accelerator_supported_profiles);
-}
-
-bool GpuVideoEncodeAcceleratorHost::Initialize(
- media::VideoPixelFormat input_format,
- const gfx::Size& input_visible_size,
- media::VideoCodecProfile output_profile,
- uint32_t initial_bitrate,
- Client* client) {
- DCHECK(CalledOnValidThread());
- client_ = client;
- if (!impl_) {
- DLOG(ERROR) << "impl_ destroyed";
- return false;
- }
-
- int32_t route_id = channel_->GenerateRouteID();
- channel_->AddRoute(route_id, weak_this_factory_.GetWeakPtr());
-
- bool succeeded = false;
- Send(new GpuCommandBufferMsg_CreateVideoEncoder(
- impl_->route_id(), input_format, input_visible_size, output_profile,
- initial_bitrate, route_id, &succeeded));
- if (!succeeded) {
- DLOG(ERROR) << "Send(GpuCommandBufferMsg_CreateVideoEncoder()) failed";
- channel_->RemoveRoute(route_id);
- return false;
- }
- encoder_route_id_ = route_id;
- return true;
-}
-
-void GpuVideoEncodeAcceleratorHost::Encode(
- const scoped_refptr<media::VideoFrame>& frame,
- bool force_keyframe) {
- DCHECK(CalledOnValidThread());
- DCHECK_EQ(media::PIXEL_FORMAT_I420, frame->format());
- if (!channel_)
- return;
-
- switch (frame->storage_type()) {
- case media::VideoFrame::STORAGE_SHMEM:
- EncodeSharedMemoryFrame(frame, force_keyframe);
- break;
- case media::VideoFrame::STORAGE_GPU_MEMORY_BUFFERS:
- EncodeGpuMemoryBufferFrame(frame, force_keyframe);
- break;
- default:
- PostNotifyError(FROM_HERE, kPlatformFailureError,
- "Encode(): cannot encode frame with invalid handles");
- return;
- }
-
- frame_map_[next_frame_id_] = frame;
-
- // Mask against 30 bits, to avoid (undefined) wraparound on signed integer.
- next_frame_id_ = (next_frame_id_ + 1) & 0x3FFFFFFF;
-}
-
-void GpuVideoEncodeAcceleratorHost::UseOutputBitstreamBuffer(
- const media::BitstreamBuffer& buffer) {
- DCHECK(CalledOnValidThread());
- if (!channel_)
- return;
-
- base::SharedMemoryHandle handle =
- channel_->ShareToGpuProcess(buffer.handle());
- if (!base::SharedMemory::IsHandleValid(handle)) {
- PostNotifyError(
- FROM_HERE, kPlatformFailureError,
- base::StringPrintf("UseOutputBitstreamBuffer(): failed to duplicate "
- "buffer handle for GPU process: buffer.id()=%d",
- buffer.id()));
- return;
- }
- Send(new AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer(
- encoder_route_id_, buffer.id(), handle, buffer.size()));
-}
-
-void GpuVideoEncodeAcceleratorHost::RequestEncodingParametersChange(
- uint32_t bitrate,
- uint32_t framerate) {
- DCHECK(CalledOnValidThread());
- if (!channel_)
- return;
-
- Send(new AcceleratedVideoEncoderMsg_RequestEncodingParametersChange(
- encoder_route_id_, bitrate, framerate));
-}
-
-void GpuVideoEncodeAcceleratorHost::Destroy() {
- DCHECK(CalledOnValidThread());
- if (channel_)
- Send(new AcceleratedVideoEncoderMsg_Destroy(encoder_route_id_));
- client_ = NULL;
- delete this;
-}
-
-void GpuVideoEncodeAcceleratorHost::OnWillDeleteImpl() {
- DCHECK(CalledOnValidThread());
- impl_ = NULL;
-
- // The CommandBufferProxyImpl is going away; error out this VEA.
- OnChannelError();
-}
-
-void GpuVideoEncodeAcceleratorHost::EncodeGpuMemoryBufferFrame(
- const scoped_refptr<media::VideoFrame>& frame,
- bool force_keyframe){
- DCHECK_EQ(media::VideoFrame::NumPlanes(media::PIXEL_FORMAT_I420),
- frame->gpu_memory_buffer_handles().size());
- AcceleratedVideoEncoderMsg_Encode_Params2 params;
- params.frame_id = next_frame_id_;
- params.timestamp = frame->timestamp();
- bool requires_sync_point = false;
- for (const auto& handle : frame->gpu_memory_buffer_handles()) {
- gfx::GpuMemoryBufferHandle new_handle =
- channel_->ShareGpuMemoryBufferToGpuProcess(handle,
- &requires_sync_point);
- if (new_handle.is_null()) {
- PostNotifyError(FROM_HERE, kPlatformFailureError,
- "EncodeGpuMemoryBufferFrame(): failed to share gpu "
- "memory buffer handle for gpu process");
- return;
- }
- params.gpu_memory_buffer_handles.push_back(new_handle);
- }
- params.size = frame->coded_size();
- params.force_keyframe = force_keyframe;
-
- Send(new AcceleratedVideoEncoderMsg_Encode2(encoder_route_id_, params));
-}
-
-void GpuVideoEncodeAcceleratorHost::EncodeSharedMemoryFrame(
- const scoped_refptr<media::VideoFrame>& frame,
- bool force_keyframe){
- if (!base::SharedMemory::IsHandleValid(frame->shared_memory_handle())) {
- PostNotifyError(FROM_HERE, kPlatformFailureError,
- "EncodeSharedMemory(): cannot encode frame with invalid "
- "shared memory handle");
- return;
- }
-
- AcceleratedVideoEncoderMsg_Encode_Params params;
- params.frame_id = next_frame_id_;
- params.timestamp = frame->timestamp();
- params.buffer_handle =
- channel_->ShareToGpuProcess(frame->shared_memory_handle());
- if (!base::SharedMemory::IsHandleValid(params.buffer_handle)) {
- PostNotifyError(FROM_HERE, kPlatformFailureError,
- "Encode(): failed to duplicate shared memory buffer handle "
- "for GPU process");
- return;
- }
- params.buffer_offset =
- base::checked_cast<uint32_t>(frame->shared_memory_offset());
- params.buffer_size =
- media::VideoFrame::AllocationSize(frame->format(), frame->coded_size());
- params.force_keyframe = force_keyframe;
-
- Send(new AcceleratedVideoEncoderMsg_Encode(encoder_route_id_, params));
-}
-
-void GpuVideoEncodeAcceleratorHost::PostNotifyError(
- const tracked_objects::Location& location, Error error,
- const std::string& message) {
- DCHECK(CalledOnValidThread());
- DLOG(ERROR) << "Error from " << location.function_name()
- << "(" << location.file_name() << ":"
- << location.line_number() << ") "
- << message << " (error = " << error << ")";
- // Post the error notification back to this thread, to avoid re-entrancy.
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&GpuVideoEncodeAcceleratorHost::OnNotifyError,
- weak_this_factory_.GetWeakPtr(), error));
-}
-
-void GpuVideoEncodeAcceleratorHost::Send(IPC::Message* message) {
- DCHECK(CalledOnValidThread());
- uint32_t message_type = message->type();
- if (!channel_->Send(message)) {
- PostNotifyError(FROM_HERE, kPlatformFailureError,
- base::StringPrintf("Send(%d) failed", message_type));
- }
-}
-
-void GpuVideoEncodeAcceleratorHost::OnRequireBitstreamBuffers(
- uint32_t input_count,
- const gfx::Size& input_coded_size,
- uint32_t output_buffer_size) {
- DCHECK(CalledOnValidThread());
- DVLOG(2) << "OnRequireBitstreamBuffers(): input_count=" << input_count
- << ", input_coded_size=" << input_coded_size.ToString()
- << ", output_buffer_size=" << output_buffer_size;
- if (client_) {
- client_->RequireBitstreamBuffers(
- input_count, input_coded_size, output_buffer_size);
- }
-}
-
-void GpuVideoEncodeAcceleratorHost::OnNotifyInputDone(int32_t frame_id) {
- DCHECK(CalledOnValidThread());
- DVLOG(3) << "OnNotifyInputDone(): frame_id=" << frame_id;
- // Fun-fact: std::hash_map is not spec'd to be re-entrant; since freeing a
- // frame can trigger a further encode to be kicked off and thus an .insert()
- // back into the map, we separate the frame's dtor running from the .erase()
- // running by holding on to the frame temporarily. This isn't "just
- // theoretical" - Android's std::hash_map crashes if we don't do this.
- scoped_refptr<media::VideoFrame> frame = frame_map_[frame_id];
- if (!frame_map_.erase(frame_id)) {
- DLOG(ERROR) << "OnNotifyInputDone(): "
- "invalid frame_id=" << frame_id;
- // See OnNotifyError for why this needs to be the last thing in this
- // function.
- OnNotifyError(kPlatformFailureError);
- return;
- }
- frame = NULL; // Not necessary but nice to be explicit; see fun-fact above.
-}
-
-void GpuVideoEncodeAcceleratorHost::OnBitstreamBufferReady(
- int32_t bitstream_buffer_id,
- uint32_t payload_size,
- bool key_frame) {
- DCHECK(CalledOnValidThread());
- DVLOG(3) << "OnBitstreamBufferReady(): "
- "bitstream_buffer_id=" << bitstream_buffer_id
- << ", payload_size=" << payload_size
- << ", key_frame=" << key_frame;
- if (client_)
- client_->BitstreamBufferReady(bitstream_buffer_id, payload_size, key_frame);
-}
-
-void GpuVideoEncodeAcceleratorHost::OnNotifyError(Error error) {
- DCHECK(CalledOnValidThread());
- DVLOG(2) << "OnNotifyError(): error=" << error;
- if (!client_)
- return;
- weak_this_factory_.InvalidateWeakPtrs();
-
- // Client::NotifyError() may Destroy() |this|, so calling it needs to be the
- // last thing done on this stack!
- media::VideoEncodeAccelerator::Client* client = NULL;
- std::swap(client_, client);
- client->NotifyError(error);
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/client/gpu_video_encode_accelerator_host.h b/chromium/content/common/gpu/client/gpu_video_encode_accelerator_host.h
deleted file mode 100644
index 38995938259..00000000000
--- a/chromium/content/common/gpu/client/gpu_video_encode_accelerator_host.h
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_CLIENT_GPU_VIDEO_ENCODE_ACCELERATOR_HOST_H_
-#define CONTENT_COMMON_GPU_CLIENT_GPU_VIDEO_ENCODE_ACCELERATOR_HOST_H_
-
-#include <stdint.h>
-
-#include <vector>
-
-#include "base/containers/hash_tables.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/threading/non_thread_safe.h"
-#include "content/common/gpu/client/command_buffer_proxy_impl.h"
-#include "gpu/config/gpu_info.h"
-#include "ipc/ipc_listener.h"
-#include "media/video/video_encode_accelerator.h"
-
-namespace gfx {
-struct GpuMemoryBufferHandle;
-class Size;
-} // namespace gfx
-
-namespace media {
-class VideoFrame;
-} // namespace media
-
-namespace tracked_objects {
-class Location;
-} // namespace tracked_objects
-
-namespace content {
-class GpuChannelHost;
-
-// This class is the renderer-side host for the VideoEncodeAccelerator in the
-// GPU process, coordinated over IPC.
-class GpuVideoEncodeAcceleratorHost
- : public IPC::Listener,
- public media::VideoEncodeAccelerator,
- public CommandBufferProxyImpl::DeletionObserver,
- public base::NonThreadSafe {
- public:
- // |this| is guaranteed not to outlive |channel| and |impl|. (See comments
- // for |channel_| and |impl_|.)
- GpuVideoEncodeAcceleratorHost(GpuChannelHost* channel,
- CommandBufferProxyImpl* impl);
-
- // IPC::Listener implementation.
- bool OnMessageReceived(const IPC::Message& message) override;
- void OnChannelError() override;
-
- // media::VideoEncodeAccelerator implementation.
- SupportedProfiles GetSupportedProfiles() override;
- bool Initialize(media::VideoPixelFormat input_format,
- const gfx::Size& input_visible_size,
- media::VideoCodecProfile output_profile,
- uint32_t initial_bitrate,
- Client* client) override;
- void Encode(const scoped_refptr<media::VideoFrame>& frame,
- bool force_keyframe) override;
- void UseOutputBitstreamBuffer(const media::BitstreamBuffer& buffer) override;
- void RequestEncodingParametersChange(uint32_t bitrate,
- uint32_t framerate_num) override;
- void Destroy() override;
-
- // CommandBufferProxyImpl::DeletionObserver implementation.
- void OnWillDeleteImpl() override;
-
- private:
- // Only Destroy() should be deleting |this|.
- ~GpuVideoEncodeAcceleratorHost() override;
-
- // Encode specific video frame types.
- void EncodeGpuMemoryBufferFrame(const scoped_refptr<media::VideoFrame>& frame,
- bool force_keyframe);
- void EncodeSharedMemoryFrame(const scoped_refptr<media::VideoFrame>& frame,
- bool force_keyframe);
-
- // Notify |client_| of an error. Posts a task to avoid re-entrancy.
- void PostNotifyError(const tracked_objects::Location& location,
- Error error, const std::string& message);
-
- void Send(IPC::Message* message);
-
- // IPC handlers, proxying media::VideoEncodeAccelerator::Client for the GPU
- // process. Should not be called directly.
- void OnRequireBitstreamBuffers(uint32_t input_count,
- const gfx::Size& input_coded_size,
- uint32_t output_buffer_size);
- void OnNotifyInputDone(int32_t frame_id);
- void OnBitstreamBufferReady(int32_t bitstream_buffer_id,
- uint32_t payload_size,
- bool key_frame);
- void OnNotifyError(Error error);
-
- // Unowned reference to the GpuChannelHost to send IPC messages to the GPU
- // process. |channel_| outlives |impl_|, so the reference is always valid as
- // long as it is not NULL.
- GpuChannelHost* channel_;
-
- // Route ID for the associated encoder in the GPU process.
- int32_t encoder_route_id_;
-
- // The client that will receive callbacks from the encoder.
- Client* client_;
-
- // Unowned reference to the CommandBufferProxyImpl that created us. |this|
- // registers as a DeletionObserver of |impl_|, so the reference is always
- // valid as long as it is not NULL.
- CommandBufferProxyImpl* impl_;
-
- // media::VideoFrames sent to the encoder.
- // base::IDMap not used here, since that takes pointers, not scoped_refptr.
- typedef base::hash_map<int32_t, scoped_refptr<media::VideoFrame>> FrameMap;
- FrameMap frame_map_;
-
- // ID serial number for the next frame to send to the GPU process.
- int32_t next_frame_id_;
-
- // WeakPtr factory for posting tasks back to itself.
- base::WeakPtrFactory<GpuVideoEncodeAcceleratorHost> weak_this_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuVideoEncodeAcceleratorHost);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_CLIENT_GPU_VIDEO_ENCODE_ACCELERATOR_HOST_H_
diff --git a/chromium/content/common/gpu/client/grcontext_for_gles2_interface.cc b/chromium/content/common/gpu/client/grcontext_for_gles2_interface.cc
new file mode 100644
index 00000000000..cebdfd7745c
--- /dev/null
+++ b/chromium/content/common/gpu/client/grcontext_for_gles2_interface.cc
@@ -0,0 +1,62 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/gpu/client/grcontext_for_gles2_interface.h"
+
+#include <stddef.h>
+#include <string.h>
+#include <utility>
+
+#include "base/lazy_instance.h"
+#include "base/macros.h"
+#include "base/trace_event/trace_event.h"
+#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/skia_bindings/gl_bindings_skia_cmd_buffer.h"
+#include "third_party/skia/include/gpu/GrContext.h"
+#include "third_party/skia/include/gpu/gl/GrGLInterface.h"
+
+namespace content {
+
+GrContextForGLES2Interface::GrContextForGLES2Interface(
+ gpu::gles2::GLES2Interface* gl) {
+ sk_sp<GrGLInterface> interface(
+ skia_bindings::CreateGLES2InterfaceBindings(gl));
+ gr_context_ =
+ sk_sp<GrContext>(GrContext::Create(kOpenGL_GrBackend,
+ // GrContext takes ownership of |interface|.
+ reinterpret_cast<GrBackendContext>(interface.get())));
+ if (gr_context_) {
+ // The limit of the number of GPU resources we hold in the GrContext's
+ // GPU cache.
+ static const int kMaxGaneshResourceCacheCount = 2048;
+ // The limit of the bytes allocated toward GPU resources in the GrContext's
+ // GPU cache.
+ static const size_t kMaxGaneshResourceCacheBytes = 96 * 1024 * 1024;
+
+ gr_context_->setResourceCacheLimits(kMaxGaneshResourceCacheCount,
+ kMaxGaneshResourceCacheBytes);
+ }
+}
+
+GrContextForGLES2Interface::~GrContextForGLES2Interface() {
+ // At this point the GLES2Interface is going to be destroyed, so have
+ // the GrContext clean up and not try to use it anymore.
+ if (gr_context_)
+ gr_context_->releaseResourcesAndAbandonContext();
+}
+
+void GrContextForGLES2Interface::OnLostContext() {
+ if (gr_context_)
+ gr_context_->abandonContext();
+}
+
+void GrContextForGLES2Interface::FreeGpuResources() {
+ if (gr_context_) {
+ TRACE_EVENT_INSTANT0("gpu", "GrContext::freeGpuResources",
+ TRACE_EVENT_SCOPE_THREAD);
+ gr_context_->freeGpuResources();
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/client/grcontext_for_gles2_interface.h b/chromium/content/common/gpu/client/grcontext_for_gles2_interface.h
new file mode 100644
index 00000000000..354092a9592
--- /dev/null
+++ b/chromium/content/common/gpu/client/grcontext_for_gles2_interface.h
@@ -0,0 +1,42 @@
+// 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_COMMON_GPU_CLIENT_GRCONTEXT_FOR_GLES2_INTERFACE_H_
+#define CONTENT_COMMON_GPU_CLIENT_GRCONTEXT_FOR_GLES2_INTERFACE_H_
+
+#include "base/macros.h"
+#include "third_party/skia/include/core/SkRefCnt.h"
+
+class GrContext;
+
+namespace gpu {
+namespace gles2 {
+class GLES2Interface;
+}
+}
+
+namespace content {
+
+// This class binds an offscreen GrContext to an offscreen context3d. The
+// context3d is used by the GrContext so must be valid as long as this class
+// is alive.
+class GrContextForGLES2Interface {
+ public:
+ explicit GrContextForGLES2Interface(gpu::gles2::GLES2Interface* gl);
+ virtual ~GrContextForGLES2Interface();
+
+ GrContext* get() { return gr_context_.get(); }
+
+ void OnLostContext();
+ void FreeGpuResources();
+
+ private:
+ sk_sp<class GrContext> gr_context_;
+
+ DISALLOW_COPY_AND_ASSIGN(GrContextForGLES2Interface);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_CLIENT_GRCONTEXT_FOR_GLES2_INTERFACE_H_
diff --git a/chromium/content/common/gpu/client/grcontext_for_webgraphicscontext3d.cc b/chromium/content/common/gpu/client/grcontext_for_webgraphicscontext3d.cc
deleted file mode 100644
index 5cd4944db68..00000000000
--- a/chromium/content/common/gpu/client/grcontext_for_webgraphicscontext3d.cc
+++ /dev/null
@@ -1,108 +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/common/gpu/client/grcontext_for_webgraphicscontext3d.h"
-
-#include <stddef.h>
-#include <string.h>
-#include <utility>
-
-#include "base/lazy_instance.h"
-#include "base/macros.h"
-#include "base/trace_event/trace_event.h"
-#include "gpu/blink/webgraphicscontext3d_impl.h"
-#include "gpu/command_buffer/client/gles2_lib.h"
-#include "gpu/skia_bindings/gl_bindings_skia_cmd_buffer.h"
-#include "third_party/skia/include/gpu/GrContext.h"
-
-using gpu_blink::WebGraphicsContext3DImpl;
-
-namespace content {
-
-namespace {
-
-// Singleton used to initialize and terminate the gles2 library.
-class GLES2Initializer {
- public:
- GLES2Initializer() { gles2::Initialize(); }
-
- ~GLES2Initializer() { gles2::Terminate(); }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(GLES2Initializer);
-};
-
-base::LazyInstance<GLES2Initializer> g_gles2_initializer =
- LAZY_INSTANCE_INITIALIZER;
-
-void BindWebGraphicsContext3DGLContextCallback(const GrGLInterface* interface) {
- gles2::SetGLContext(static_cast<const GrGLInterfaceForWebGraphicsContext3D*>(
- interface)->WebContext3D()->GetGLInterface());
-}
-
-} // namespace anonymous
-
-GrContextForWebGraphicsContext3D::GrContextForWebGraphicsContext3D(
- skia::RefPtr<GrGLInterfaceForWebGraphicsContext3D> gr_interface) {
- if (!gr_interface || !gr_interface->WebContext3D())
- return;
-
- // Ensure the gles2 library is initialized first in a thread safe way.
- g_gles2_initializer.Get();
- gles2::SetGLContext(gr_interface->WebContext3D()->GetGLInterface());
-
- skia_bindings::InitCommandBufferSkiaGLBinding(gr_interface.get());
-
- gr_interface->fCallback = BindWebGraphicsContext3DGLContextCallback;
-
- gr_context_ = skia::AdoptRef(GrContext::Create(
- kOpenGL_GrBackend,
- reinterpret_cast<GrBackendContext>(gr_interface.get())));
- if (gr_context_) {
- // The limit of the number of GPU resources we hold in the GrContext's
- // GPU cache.
- static const int kMaxGaneshResourceCacheCount = 2048;
- // The limit of the bytes allocated toward GPU resources in the GrContext's
- // GPU cache.
- static const size_t kMaxGaneshResourceCacheBytes = 96 * 1024 * 1024;
-
- gr_context_->setResourceCacheLimits(kMaxGaneshResourceCacheCount,
- kMaxGaneshResourceCacheBytes);
- }
-}
-
-GrContextForWebGraphicsContext3D::~GrContextForWebGraphicsContext3D() {
-}
-
-void GrContextForWebGraphicsContext3D::OnLostContext() {
- if (gr_context_)
- gr_context_->abandonContext();
-}
-
-void GrContextForWebGraphicsContext3D::FreeGpuResources() {
- if (gr_context_) {
- TRACE_EVENT_INSTANT0("gpu", "GrContext::freeGpuResources", \
- TRACE_EVENT_SCOPE_THREAD);
- gr_context_->freeGpuResources();
- }
-}
-
-GrGLInterfaceForWebGraphicsContext3D::GrGLInterfaceForWebGraphicsContext3D(
- scoped_ptr<gpu_blink::WebGraphicsContext3DImpl> context3d)
- : context3d_(std::move(context3d)) {}
-
-void GrGLInterfaceForWebGraphicsContext3D::BindToCurrentThread() {
- context_thread_checker_.DetachFromThread();
-}
-
-GrGLInterfaceForWebGraphicsContext3D::~GrGLInterfaceForWebGraphicsContext3D() {
- DCHECK(context_thread_checker_.CalledOnValidThread());
-#if !defined(NDEBUG)
- // Set all the function pointers to zero, in order to crash if function
- // pointers are used after free.
- memset(&fFunctions, 0, sizeof(GrGLInterface::Functions));
-#endif
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/client/grcontext_for_webgraphicscontext3d.h b/chromium/content/common/gpu/client/grcontext_for_webgraphicscontext3d.h
deleted file mode 100644
index 7597f906a58..00000000000
--- a/chromium/content/common/gpu/client/grcontext_for_webgraphicscontext3d.h
+++ /dev/null
@@ -1,66 +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_COMMON_GPU_CLIENT_GRCONTEXT_FOR_WEBGRAPHICSCONTEXT3D_H_
-#define CONTENT_COMMON_GPU_CLIENT_GRCONTEXT_FOR_WEBGRAPHICSCONTEXT3D_H_
-
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/threading/thread_checker.h"
-#include "skia/ext/refptr.h"
-#include "third_party/skia/include/gpu/gl/GrGLInterface.h"
-
-class GrContext;
-
-namespace gpu_blink {
-class WebGraphicsContext3DImpl;
-}
-
-namespace content {
-
-// Wrap WebGraphicsContext3DImpl into a GrGLInterface object, which allows
-// the WebGraphicsContext3DImpl to be jointly refcounted (indirectly)
-// by the GrContext and the context provider. This makes it legal for the
-// GrContext to be invoked when it outlives the context provider that created
-// it. By doing this we no longer have to worry about use after free errors
-// caused a lack of consideration for object destruction order.
-class GrGLInterfaceForWebGraphicsContext3D final : public GrGLInterface {
- public:
- GrGLInterfaceForWebGraphicsContext3D(
- scoped_ptr<gpu_blink::WebGraphicsContext3DImpl> context3d);
- ~GrGLInterfaceForWebGraphicsContext3D() final;
-
- void BindToCurrentThread();
-
- gpu_blink::WebGraphicsContext3DImpl* WebContext3D() const {
- return context3d_.get();
- }
- private:
- base::ThreadChecker context_thread_checker_;
- scoped_ptr<gpu_blink::WebGraphicsContext3DImpl> context3d_;
-};
-
-// This class binds an offscreen GrContext to an offscreen context3d. The
-// context3d is used by the GrContext so must be valid as long as this class
-// is alive.
-class GrContextForWebGraphicsContext3D {
- public:
- explicit GrContextForWebGraphicsContext3D(
- skia::RefPtr<GrGLInterfaceForWebGraphicsContext3D> context3d);
- virtual ~GrContextForWebGraphicsContext3D();
-
- GrContext* get() { return gr_context_.get(); }
-
- void OnLostContext();
- void FreeGpuResources();
-
- private:
- skia::RefPtr<class GrContext> gr_context_;
-
- DISALLOW_COPY_AND_ASSIGN(GrContextForWebGraphicsContext3D);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_CLIENT_GRCONTEXT_FOR_WEBGRAPHICSCONTEXT3D_H_
diff --git a/chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc b/chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc
index f7783397057..708a3da8ee0 100644
--- a/chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc
+++ b/chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc
@@ -23,22 +23,19 @@
#include "base/metrics/histogram.h"
#include "base/profiler/scoped_tracker.h"
#include "base/trace_event/trace_event.h"
-#include "content/common/gpu/client/gpu_channel_host.h"
-#include "content/public/common/content_constants.h"
-#include "content/public/common/content_switches.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_cmd_helper.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "gpu/command_buffer/client/gles2_trace_implementation.h"
+#include "gpu/command_buffer/client/gpu_switches.h"
#include "gpu/command_buffer/client/transfer_buffer.h"
#include "gpu/command_buffer/common/constants.h"
#include "gpu/command_buffer/common/gpu_memory_allocation.h"
#include "gpu/command_buffer/common/mailbox.h"
+#include "gpu/ipc/client/gpu_channel_host.h"
#include "gpu/skia_bindings/gl_bindings_skia_cmd_buffer.h"
#include "third_party/skia/include/core/SkTypes.h"
-using blink::WGC3Denum;
-
namespace content {
namespace {
@@ -46,14 +43,15 @@ namespace {
static base::LazyInstance<base::Lock>::Leaky
g_default_share_groups_lock = LAZY_INSTANCE_INITIALIZER;
-typedef std::map<GpuChannelHost*,
- scoped_refptr<WebGraphicsContext3DCommandBufferImpl::ShareGroup> >
+typedef std::map<
+ gpu::GpuChannelHost*,
+ scoped_refptr<WebGraphicsContext3DCommandBufferImpl::ShareGroup>>
ShareGroupMap;
static base::LazyInstance<ShareGroupMap> g_default_share_groups =
LAZY_INSTANCE_INITIALIZER;
scoped_refptr<WebGraphicsContext3DCommandBufferImpl::ShareGroup>
- GetDefaultShareGroupForHost(GpuChannelHost* host) {
+GetDefaultShareGroupForHost(gpu::GpuChannelHost* host) {
base::AutoLock lock(g_default_share_groups_lock.Get());
ShareGroupMap& share_groups = g_default_share_groups.Get();
@@ -84,34 +82,38 @@ WebGraphicsContext3DCommandBufferImpl::ShareGroup::~ShareGroup() {
}
WebGraphicsContext3DCommandBufferImpl::WebGraphicsContext3DCommandBufferImpl(
- int surface_id,
+ gpu::SurfaceHandle surface_handle,
const GURL& active_url,
- GpuChannelHost* host,
- const Attributes& attributes,
- bool lose_context_when_out_of_memory,
+ gpu::GpuChannelHost* host,
+ const gpu::gles2::ContextCreationAttribHelper& attributes,
+ gfx::GpuPreference gpu_preference,
+ bool share_resources,
+ bool automatic_flushes,
const SharedMemoryLimits& limits,
WebGraphicsContext3DCommandBufferImpl* share_context)
- : lose_context_when_out_of_memory_(lose_context_when_out_of_memory),
+ : automatic_flushes_(automatic_flushes),
attributes_(attributes),
- visible_(false),
host_(host),
- surface_id_(surface_id),
+ surface_handle_(surface_handle),
active_url_(active_url),
- context_type_(CONTEXT_TYPE_UNKNOWN),
- gpu_preference_(attributes.preferDiscreteGPU ? gfx::PreferDiscreteGpu
- : gfx::PreferIntegratedGpu),
+ gpu_preference_(gpu_preference),
mem_limits_(limits),
weak_ptr_factory_(this) {
- if (attributes_.webGL)
- context_type_ = OFFSCREEN_CONTEXT_FOR_WEBGL;
+ switch (attributes.context_type) {
+ case gpu::gles2::CONTEXT_TYPE_OPENGLES2:
+ case gpu::gles2::CONTEXT_TYPE_OPENGLES3:
+ context_type_ = CONTEXT_TYPE_UNKNOWN;
+ case gpu::gles2::CONTEXT_TYPE_WEBGL1:
+ case gpu::gles2::CONTEXT_TYPE_WEBGL2:
+ context_type_ = OFFSCREEN_CONTEXT_FOR_WEBGL;
+ }
if (share_context) {
- DCHECK(!attributes_.shareResources);
+ DCHECK(!share_resources);
share_group_ = share_context->share_group_;
+ } else if (share_resources) {
+ share_group_ = GetDefaultShareGroupForHost(host);
} else {
- share_group_ = attributes_.shareResources
- ? GetDefaultShareGroupForHost(host)
- : scoped_refptr<WebGraphicsContext3DCommandBufferImpl::ShareGroup>(
- new ShareGroup());
+ share_group_ = make_scoped_refptr(new ShareGroup);
}
}
@@ -138,7 +140,7 @@ bool WebGraphicsContext3DCommandBufferImpl::MaybeInitializeGL() {
FROM_HERE_WITH_EXPLICIT_FUNCTION(
"125248 WebGraphicsContext3DCommandBufferImpl::MaybeInitializeGL"));
- if (!CreateContext(surface_id_ != 0)) {
+ if (!CreateContext()) {
Destroy();
initialize_failed_ = true;
@@ -157,44 +159,31 @@ bool WebGraphicsContext3DCommandBufferImpl::MaybeInitializeGL() {
real_gl_->TraceBeginCHROMIUM("WebGraphicsContext3D",
"CommandBufferContext");
- visible_ = true;
initialized_ = true;
return true;
}
bool WebGraphicsContext3DCommandBufferImpl::InitializeCommandBuffer(
- bool onscreen, WebGraphicsContext3DCommandBufferImpl* share_context) {
+ WebGraphicsContext3DCommandBufferImpl* share_context) {
if (!host_.get())
return false;
- CommandBufferProxyImpl* share_group_command_buffer = NULL;
+ gpu::CommandBufferProxyImpl* share_group_command_buffer = NULL;
if (share_context) {
share_group_command_buffer = share_context->GetCommandBufferProxy();
}
- ::gpu::gles2::ContextCreationAttribHelper attribs_for_gles2;
- ConvertAttributes(attributes_, &attribs_for_gles2);
- attribs_for_gles2.lose_context_when_out_of_memory =
- lose_context_when_out_of_memory_;
- DCHECK(attribs_for_gles2.buffer_preserved);
- std::vector<int32_t> attribs;
- attribs_for_gles2.Serialize(&attribs);
+ DCHECK(attributes_.buffer_preserved);
+ std::vector<int32_t> serialized_attributes;
+ attributes_.Serialize(&serialized_attributes);
// Create a proxy to a command buffer in the GPU process.
- if (onscreen) {
- command_buffer_ =
- host_->CreateViewCommandBuffer(surface_id_, share_group_command_buffer,
- GpuChannelHost::kDefaultStreamId,
- GpuChannelHost::kDefaultStreamPriority,
- attribs, active_url_, gpu_preference_);
- } else {
- command_buffer_ = host_->CreateOffscreenCommandBuffer(
- gfx::Size(1, 1), share_group_command_buffer,
- GpuChannelHost::kDefaultStreamId,
- GpuChannelHost::kDefaultStreamPriority, attribs, active_url_,
- gpu_preference_);
- }
+ command_buffer_ = host_->CreateCommandBuffer(
+ surface_handle_, gfx::Size(), share_group_command_buffer,
+ gpu::GpuChannelHost::kDefaultStreamId,
+ gpu::GpuChannelHost::kDefaultStreamPriority, serialized_attributes,
+ active_url_, gpu_preference_);
if (!command_buffer_) {
DLOG(ERROR) << "GpuChannelHost failed to create command buffer.";
@@ -213,7 +202,7 @@ bool WebGraphicsContext3DCommandBufferImpl::InitializeCommandBuffer(
return result;
}
-bool WebGraphicsContext3DCommandBufferImpl::CreateContext(bool onscreen) {
+bool WebGraphicsContext3DCommandBufferImpl::CreateContext() {
TRACE_EVENT0("gpu", "WebGfxCtx3DCmdBfrImpl::CreateContext");
scoped_refptr<gpu::gles2::ShareGroup> gles2_share_group;
@@ -225,7 +214,7 @@ bool WebGraphicsContext3DCommandBufferImpl::CreateContext(bool onscreen) {
share_group_lock.reset(new base::AutoLock(share_group_->lock()));
share_context = share_group_->GetAnyContextLocked();
- if (!InitializeCommandBuffer(onscreen, share_context)) {
+ if (!InitializeCommandBuffer(share_context)) {
LOG(ERROR) << "Failed to initialize command buffer.";
return false;
}
@@ -243,7 +232,7 @@ bool WebGraphicsContext3DCommandBufferImpl::CreateContext(bool onscreen) {
return false;
}
- if (attributes_.noAutomaticFlushes)
+ if (!automatic_flushes_)
gles2_helper_->SetAutomaticFlushes(false);
// Create a transfer buffer used to copy resources between the renderer
// process and the GPU process.
@@ -251,15 +240,17 @@ bool WebGraphicsContext3DCommandBufferImpl::CreateContext(bool onscreen) {
DCHECK(host_.get());
- // Create the object exposing the OpenGL API.
- const bool bind_generates_resources = false;
+ const bool bind_generates_resource = attributes_.bind_generates_resource;
+ const bool lose_context_when_out_of_memory =
+ attributes_.lose_context_when_out_of_memory;
const bool support_client_side_arrays = false;
+ // Create the object exposing the OpenGL API.
real_gl_.reset(new gpu::gles2::GLES2Implementation(
gles2_helper_.get(), gles2_share_group.get(), transfer_buffer_.get(),
- bind_generates_resources, lose_context_when_out_of_memory_,
+ bind_generates_resource, lose_context_when_out_of_memory,
support_client_side_arrays, command_buffer_.get()));
- setGLInterface(real_gl_.get());
+ SetGLInterface(real_gl_.get());
if (!real_gl_->Initialize(
mem_limits_.start_transfer_buffer_size,
@@ -276,7 +267,7 @@ bool WebGraphicsContext3DCommandBufferImpl::CreateContext(bool onscreen) {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableGpuClientTracing)) {
trace_gl_.reset(new gpu::gles2::GLES2TraceImplementation(GetGLInterface()));
- setGLInterface(trace_gl_.get());
+ SetGLInterface(trace_gl_.get());
}
return true;
}
@@ -306,7 +297,7 @@ void WebGraphicsContext3DCommandBufferImpl::Destroy() {
// issued on this context might not be visible to other contexts in the
// share group.
gl->Flush();
- setGLInterface(NULL);
+ SetGLInterface(nullptr);
}
trace_gl_.reset();
@@ -316,7 +307,7 @@ void WebGraphicsContext3DCommandBufferImpl::Destroy() {
real_gl_.reset();
command_buffer_.reset();
- host_ = NULL;
+ host_ = nullptr;
}
gpu::ContextSupport*
@@ -336,9 +327,11 @@ bool WebGraphicsContext3DCommandBufferImpl::IsCommandBufferContextLost() {
// static
WebGraphicsContext3DCommandBufferImpl*
WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
- GpuChannelHost* host,
- const WebGraphicsContext3D::Attributes& attributes,
- bool lose_context_when_out_of_memory,
+ gpu::GpuChannelHost* host,
+ const gpu::gles2::ContextCreationAttribHelper& attributes,
+ gfx::GpuPreference gpu_preference,
+ bool share_resources,
+ bool automatic_flushes,
const GURL& active_url,
const SharedMemoryLimits& limits,
WebGraphicsContext3DCommandBufferImpl* share_context) {
@@ -349,13 +342,8 @@ WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
return NULL;
return new WebGraphicsContext3DCommandBufferImpl(
- 0,
- active_url,
- host,
- attributes,
- lose_context_when_out_of_memory,
- limits,
- share_context);
+ gpu::kNullSurfaceHandle, active_url, host, attributes, gpu_preference,
+ share_resources, automatic_flushes, limits, share_context);
}
void WebGraphicsContext3DCommandBufferImpl::OnContextLost() {
diff --git a/chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h b/chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h
index b556c1bcdf5..1bbd7202eb6 100644
--- a/chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h
+++ b/chromium/content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h
@@ -18,17 +18,19 @@
#include "base/synchronization/lock.h"
#include "content/common/content_export.h"
#include "content/common/gpu/client/command_buffer_metrics.h"
-#include "content/common/gpu/client/command_buffer_proxy_impl.h"
#include "gpu/blink/webgraphicscontext3d_impl.h"
+#include "gpu/command_buffer/common/gles2_cmd_utils.h"
+#include "gpu/ipc/client/command_buffer_proxy_impl.h"
+#include "gpu/ipc/common/surface_handle.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "third_party/WebKit/public/platform/WebString.h"
-#include "ui/gfx/native_widget_types.h"
#include "ui/gl/gpu_preference.h"
#include "url/gurl.h"
namespace gpu {
class ContextSupport;
+class GpuChannelHost;
class TransferBuffer;
namespace gles2 {
@@ -39,7 +41,6 @@ class GLES2Interface;
}
namespace content {
-class GpuChannelHost;
const size_t kDefaultCommandBufferSize = 1024 * 1024;
const size_t kDefaultStartTransferBufferSize = 1 * 1024 * 1024;
@@ -108,17 +109,19 @@ class WebGraphicsContext3DCommandBufferImpl
};
WebGraphicsContext3DCommandBufferImpl(
- int surface_id,
+ gpu::SurfaceHandle surface_handle,
const GURL& active_url,
- GpuChannelHost* host,
- const Attributes& attributes,
- bool lose_context_when_out_of_memory,
+ gpu::GpuChannelHost* host,
+ const gpu::gles2::ContextCreationAttribHelper& attributes,
+ gfx::GpuPreference gpu_preference,
+ bool share_resources,
+ bool automatic_flushes,
const SharedMemoryLimits& limits,
WebGraphicsContext3DCommandBufferImpl* share_context);
~WebGraphicsContext3DCommandBufferImpl() override;
- CommandBufferProxyImpl* GetCommandBufferProxy() {
+ gpu::CommandBufferProxyImpl* GetCommandBufferProxy() {
return command_buffer_.get();
}
@@ -135,13 +138,15 @@ class WebGraphicsContext3DCommandBufferImpl
// Create & initialize a WebGraphicsContext3DCommandBufferImpl. Return NULL
// on any failure.
static CONTENT_EXPORT WebGraphicsContext3DCommandBufferImpl*
- CreateOffscreenContext(
- GpuChannelHost* host,
- const WebGraphicsContext3D::Attributes& attributes,
- bool lose_context_when_out_of_memory,
- const GURL& active_url,
- const SharedMemoryLimits& limits,
- WebGraphicsContext3DCommandBufferImpl* share_context);
+ CreateOffscreenContext(
+ gpu::GpuChannelHost* host,
+ const gpu::gles2::ContextCreationAttribHelper& attributes,
+ gfx::GpuPreference gpu_preference,
+ bool share_resources,
+ bool automatic_flushes,
+ const GURL& active_url,
+ const SharedMemoryLimits& limits,
+ WebGraphicsContext3DCommandBufferImpl* share_context);
size_t GetMappedMemoryLimit() {
return mem_limits_.mapped_memory_reclaim_limit;
@@ -166,7 +171,7 @@ class WebGraphicsContext3DCommandBufferImpl
// thread).
bool MaybeInitializeGL();
- bool InitializeCommandBuffer(bool onscreen,
+ bool InitializeCommandBuffer(
WebGraphicsContext3DCommandBufferImpl* share_context);
void Destroy();
@@ -178,30 +183,28 @@ class WebGraphicsContext3DCommandBufferImpl
//
// NOTE: on Mac OS X, this entry point is only used to set up the
// accelerated compositor's output. On this platform, we actually pass
- // a gfx::PluginWindowHandle in place of the gfx::NativeViewId,
+ // a gpu::SurfaceHandle in place of the gfx::NativeViewId,
// because the facility to allocate a fake PluginWindowHandle is
// already in place. We could add more entry points and messages to
// allocate both fake PluginWindowHandles and NativeViewIds and map
// from fake NativeViewIds to PluginWindowHandles, but this seems like
// unnecessary complexity at the moment.
- bool CreateContext(bool onscreen);
+ bool CreateContext();
virtual void OnContextLost();
- bool lose_context_when_out_of_memory_;
- blink::WebGraphicsContext3D::Attributes attributes_;
-
- bool visible_;
+ bool automatic_flushes_;
+ gpu::gles2::ContextCreationAttribHelper attributes_;
// State needed by MaybeInitializeGL.
- scoped_refptr<GpuChannelHost> host_;
- int32_t surface_id_;
+ scoped_refptr<gpu::GpuChannelHost> host_;
+ gpu::SurfaceHandle surface_handle_;
GURL active_url_;
CommandBufferContextType context_type_;
gfx::GpuPreference gpu_preference_;
- scoped_ptr<CommandBufferProxyImpl> command_buffer_;
+ scoped_ptr<gpu::CommandBufferProxyImpl> command_buffer_;
scoped_ptr<gpu::gles2::GLES2CmdHelper> gles2_helper_;
scoped_ptr<gpu::TransferBuffer> transfer_buffer_;
scoped_ptr<gpu::gles2::GLES2Implementation> real_gl_;
diff --git a/chromium/content/common/gpu/gpu_channel.cc b/chromium/content/common/gpu/gpu_channel.cc
deleted file mode 100644
index e3f920d96b0..00000000000
--- a/chromium/content/common/gpu/gpu_channel.cc
+++ /dev/null
@@ -1,1086 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/gpu_channel.h"
-
-#include <utility>
-
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-
-#include <algorithm>
-#include <deque>
-#include <set>
-#include <vector>
-
-#include "base/atomicops.h"
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/location.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
-#include "base/strings/string_util.h"
-#include "base/synchronization/lock.h"
-#include "base/thread_task_runner_handle.h"
-#include "base/timer/timer.h"
-#include "base/trace_event/memory_dump_manager.h"
-#include "base/trace_event/process_memory_dump.h"
-#include "base/trace_event/trace_event.h"
-#include "build/build_config.h"
-#include "content/common/gpu/gpu_channel_manager.h"
-#include "content/common/gpu/gpu_memory_buffer_factory.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "content/common/gpu/media/gpu_jpeg_decode_accelerator.h"
-#include "content/public/common/content_switches.h"
-#include "gpu/command_buffer/common/mailbox.h"
-#include "gpu/command_buffer/common/value_state.h"
-#include "gpu/command_buffer/service/gpu_scheduler.h"
-#include "gpu/command_buffer/service/image_factory.h"
-#include "gpu/command_buffer/service/mailbox_manager.h"
-#include "gpu/command_buffer/service/sync_point_manager.h"
-#include "gpu/command_buffer/service/valuebuffer_manager.h"
-#include "ipc/ipc_channel.h"
-#include "ipc/message_filter.h"
-#include "ui/gl/gl_context.h"
-#include "ui/gl/gl_image_shared_memory.h"
-#include "ui/gl/gl_surface.h"
-
-#if defined(OS_POSIX)
-#include "ipc/ipc_channel_posix.h"
-#endif
-
-namespace content {
-namespace {
-
-// Number of milliseconds between successive vsync. Many GL commands block
-// on vsync, so thresholds for preemption should be multiples of this.
-const int64_t kVsyncIntervalMs = 17;
-
-// Amount of time that we will wait for an IPC to be processed before
-// preempting. After a preemption, we must wait this long before triggering
-// another preemption.
-const int64_t kPreemptWaitTimeMs = 2 * kVsyncIntervalMs;
-
-// Once we trigger a preemption, the maximum duration that we will wait
-// before clearing the preemption.
-const int64_t kMaxPreemptTimeMs = kVsyncIntervalMs;
-
-// Stop the preemption once the time for the longest pending IPC drops
-// below this threshold.
-const int64_t kStopPreemptThresholdMs = kVsyncIntervalMs;
-
-} // anonymous namespace
-
-scoped_refptr<GpuChannelMessageQueue> GpuChannelMessageQueue::Create(
- const base::WeakPtr<GpuChannel>& gpu_channel,
- base::SingleThreadTaskRunner* task_runner,
- gpu::SyncPointManager* sync_point_manager) {
- return new GpuChannelMessageQueue(gpu_channel, task_runner,
- sync_point_manager);
-}
-
-scoped_refptr<gpu::SyncPointOrderData>
-GpuChannelMessageQueue::GetSyncPointOrderData() {
- return sync_point_order_data_;
-}
-
-GpuChannelMessageQueue::GpuChannelMessageQueue(
- const base::WeakPtr<GpuChannel>& gpu_channel,
- base::SingleThreadTaskRunner* task_runner,
- gpu::SyncPointManager* sync_point_manager)
- : enabled_(true),
- sync_point_order_data_(gpu::SyncPointOrderData::Create()),
- gpu_channel_(gpu_channel),
- task_runner_(task_runner),
- sync_point_manager_(sync_point_manager) {}
-
-GpuChannelMessageQueue::~GpuChannelMessageQueue() {
- DCHECK(channel_messages_.empty());
-}
-
-uint32_t GpuChannelMessageQueue::GetUnprocessedOrderNum() const {
- return sync_point_order_data_->unprocessed_order_num();
-}
-
-uint32_t GpuChannelMessageQueue::GetProcessedOrderNum() const {
- return sync_point_order_data_->processed_order_num();
-}
-
-void GpuChannelMessageQueue::PushBackMessage(const IPC::Message& message) {
- base::AutoLock auto_lock(channel_messages_lock_);
- if (enabled_)
- PushMessageHelper(make_scoped_ptr(new GpuChannelMessage(message)));
-}
-
-bool GpuChannelMessageQueue::GenerateSyncPointMessage(
- const IPC::Message& message,
- bool retire_sync_point,
- uint32_t* sync_point) {
- DCHECK_EQ((uint32_t)GpuCommandBufferMsg_InsertSyncPoint::ID, message.type());
- DCHECK(sync_point);
- base::AutoLock auto_lock(channel_messages_lock_);
- if (enabled_) {
- *sync_point = sync_point_manager_->GenerateSyncPoint();
-
- scoped_ptr<GpuChannelMessage> msg(new GpuChannelMessage(message));
- msg->retire_sync_point = retire_sync_point;
- msg->sync_point = *sync_point;
-
- PushMessageHelper(std::move(msg));
- return true;
- }
- return false;
-}
-
-bool GpuChannelMessageQueue::HasQueuedMessages() const {
- base::AutoLock auto_lock(channel_messages_lock_);
- return !channel_messages_.empty();
-}
-
-base::TimeTicks GpuChannelMessageQueue::GetNextMessageTimeTick() const {
- base::AutoLock auto_lock(channel_messages_lock_);
- if (!channel_messages_.empty())
- return channel_messages_.front()->time_received;
- return base::TimeTicks();
-}
-
-GpuChannelMessage* GpuChannelMessageQueue::GetNextMessage() const {
- base::AutoLock auto_lock(channel_messages_lock_);
- if (!channel_messages_.empty()) {
- DCHECK_GT(channel_messages_.front()->order_number,
- sync_point_order_data_->processed_order_num());
- DCHECK_LE(channel_messages_.front()->order_number,
- sync_point_order_data_->unprocessed_order_num());
-
- return channel_messages_.front();
- }
- return nullptr;
-}
-
-void GpuChannelMessageQueue::BeginMessageProcessing(
- const GpuChannelMessage* msg) {
- sync_point_order_data_->BeginProcessingOrderNumber(msg->order_number);
-}
-
-void GpuChannelMessageQueue::PauseMessageProcessing(
- const GpuChannelMessage* msg) {
- sync_point_order_data_->PauseProcessingOrderNumber(msg->order_number);
-}
-
-bool GpuChannelMessageQueue::MessageProcessed() {
- base::AutoLock auto_lock(channel_messages_lock_);
- DCHECK(!channel_messages_.empty());
- scoped_ptr<GpuChannelMessage> msg(channel_messages_.front());
- channel_messages_.pop_front();
- sync_point_order_data_->FinishProcessingOrderNumber(msg->order_number);
- return !channel_messages_.empty();
-}
-
-void GpuChannelMessageQueue::DeleteAndDisableMessages() {
- {
- base::AutoLock auto_lock(channel_messages_lock_);
- DCHECK(enabled_);
- enabled_ = false;
- }
-
- // We guarantee that the queues will no longer be modified after enabled_
- // is set to false, it is now safe to modify the queue without the lock.
- // All public facing modifying functions check enabled_ while all
- // private modifying functions DCHECK(enabled_) to enforce this.
- while (!channel_messages_.empty()) {
- scoped_ptr<GpuChannelMessage> msg(channel_messages_.front());
- channel_messages_.pop_front();
- // This needs to clean up both GpuCommandBufferMsg_InsertSyncPoint and
- // GpuCommandBufferMsg_RetireSyncPoint messages, safer to just check
- // if we have a sync point number here.
- if (msg->sync_point)
- sync_point_manager_->RetireSyncPoint(msg->sync_point);
- }
-
- if (sync_point_order_data_) {
- sync_point_order_data_->Destroy();
- sync_point_order_data_ = nullptr;
- }
-}
-
-void GpuChannelMessageQueue::ScheduleHandleMessage() {
- task_runner_->PostTask(FROM_HERE,
- base::Bind(&GpuChannel::HandleMessage, gpu_channel_));
-}
-
-void GpuChannelMessageQueue::PushMessageHelper(
- scoped_ptr<GpuChannelMessage> msg) {
- channel_messages_lock_.AssertAcquired();
- DCHECK(enabled_);
-
- msg->order_number = sync_point_order_data_->GenerateUnprocessedOrderNumber(
- sync_point_manager_);
- msg->time_received = base::TimeTicks::Now();
-
- bool had_messages = !channel_messages_.empty();
- channel_messages_.push_back(msg.release());
- if (!had_messages)
- ScheduleHandleMessage();
-}
-
-GpuChannelMessageFilter::GpuChannelMessageFilter(
- const base::WeakPtr<GpuChannel>& gpu_channel,
- GpuChannelMessageQueue* message_queue,
- base::SingleThreadTaskRunner* task_runner,
- gpu::PreemptionFlag* preempting_flag,
- bool future_sync_points)
- : preemption_state_(IDLE),
- gpu_channel_(gpu_channel),
- message_queue_(message_queue),
- sender_(nullptr),
- peer_pid_(base::kNullProcessId),
- task_runner_(task_runner),
- preempting_flag_(preempting_flag),
- a_stub_is_descheduled_(false),
- future_sync_points_(future_sync_points) {}
-
-GpuChannelMessageFilter::~GpuChannelMessageFilter() {}
-
-void GpuChannelMessageFilter::OnFilterAdded(IPC::Sender* sender) {
- DCHECK(!sender_);
- sender_ = sender;
- timer_ = make_scoped_ptr(new base::OneShotTimer);
- for (scoped_refptr<IPC::MessageFilter>& filter : channel_filters_) {
- filter->OnFilterAdded(sender_);
- }
-}
-
-void GpuChannelMessageFilter::OnFilterRemoved() {
- DCHECK(sender_);
- for (scoped_refptr<IPC::MessageFilter>& filter : channel_filters_) {
- filter->OnFilterRemoved();
- }
- sender_ = nullptr;
- peer_pid_ = base::kNullProcessId;
- timer_ = nullptr;
-}
-
-void GpuChannelMessageFilter::OnChannelConnected(int32_t peer_pid) {
- DCHECK(peer_pid_ == base::kNullProcessId);
- peer_pid_ = peer_pid;
- for (scoped_refptr<IPC::MessageFilter>& filter : channel_filters_) {
- filter->OnChannelConnected(peer_pid);
- }
-}
-
-void GpuChannelMessageFilter::OnChannelError() {
- for (scoped_refptr<IPC::MessageFilter>& filter : channel_filters_) {
- filter->OnChannelError();
- }
-}
-
-void GpuChannelMessageFilter::OnChannelClosing() {
- for (scoped_refptr<IPC::MessageFilter>& filter : channel_filters_) {
- filter->OnChannelClosing();
- }
-}
-
-void GpuChannelMessageFilter::AddChannelFilter(
- scoped_refptr<IPC::MessageFilter> filter) {
- channel_filters_.push_back(filter);
- if (sender_)
- filter->OnFilterAdded(sender_);
- if (peer_pid_ != base::kNullProcessId)
- filter->OnChannelConnected(peer_pid_);
-}
-
-void GpuChannelMessageFilter::RemoveChannelFilter(
- scoped_refptr<IPC::MessageFilter> filter) {
- if (sender_)
- filter->OnFilterRemoved();
- channel_filters_.erase(
- std::find(channel_filters_.begin(), channel_filters_.end(), filter));
-}
-
-bool GpuChannelMessageFilter::OnMessageReceived(const IPC::Message& message) {
- DCHECK(sender_);
-
- if (message.should_unblock() || message.is_reply()) {
- DLOG(ERROR) << "Unexpected message type";
- return true;
- }
-
- if (message.type() == GpuChannelMsg_Nop::ID) {
- IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message);
- Send(reply);
- return true;
- }
-
- for (scoped_refptr<IPC::MessageFilter>& filter : channel_filters_) {
- if (filter->OnMessageReceived(message)) {
- return true;
- }
- }
-
- bool handled = false;
- if ((message.type() == GpuCommandBufferMsg_RetireSyncPoint::ID) &&
- !future_sync_points_) {
- DLOG(ERROR) << "Untrusted client should not send "
- "GpuCommandBufferMsg_RetireSyncPoint message";
- return true;
- }
-
- if (message.type() == GpuCommandBufferMsg_InsertSyncPoint::ID) {
- base::Tuple<bool> params;
- IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message);
- if (!GpuCommandBufferMsg_InsertSyncPoint::ReadSendParam(&message,
- &params)) {
- reply->set_reply_error();
- Send(reply);
- return true;
- }
- bool retire_sync_point = base::get<0>(params);
- if (!future_sync_points_ && !retire_sync_point) {
- DLOG(ERROR) << "Untrusted contexts can't create future sync points";
- reply->set_reply_error();
- Send(reply);
- return true;
- }
-
- // Message queue must handle the entire sync point generation because the
- // message queue could be disabled from the main thread during generation.
- uint32_t sync_point = 0u;
- if (!message_queue_->GenerateSyncPointMessage(message, retire_sync_point,
- &sync_point)) {
- DLOG(ERROR) << "GpuChannel has been destroyed.";
- reply->set_reply_error();
- Send(reply);
- return true;
- }
-
- DCHECK_NE(sync_point, 0u);
- GpuCommandBufferMsg_InsertSyncPoint::WriteReplyParams(reply, sync_point);
- Send(reply);
- handled = true;
- }
-
- // Forward all other messages to the GPU Channel.
- if (!handled) {
- if (message.type() == GpuCommandBufferMsg_WaitForTokenInRange::ID ||
- message.type() == GpuCommandBufferMsg_WaitForGetOffsetInRange::ID) {
- task_runner_->PostTask(FROM_HERE,
- base::Bind(&GpuChannel::HandleOutOfOrderMessage,
- gpu_channel_, message));
- } else {
- message_queue_->PushBackMessage(message);
- }
- handled = true;
- }
-
- UpdatePreemptionState();
- return handled;
-}
-
-void GpuChannelMessageFilter::OnMessageProcessed() {
- UpdatePreemptionState();
-}
-
-void GpuChannelMessageFilter::UpdateStubSchedulingState(
- bool a_stub_is_descheduled) {
- a_stub_is_descheduled_ = a_stub_is_descheduled;
- UpdatePreemptionState();
-}
-
-bool GpuChannelMessageFilter::Send(IPC::Message* message) {
- return sender_->Send(message);
-}
-
-void GpuChannelMessageFilter::UpdatePreemptionState() {
- switch (preemption_state_) {
- case IDLE:
- if (preempting_flag_.get() && message_queue_->HasQueuedMessages())
- TransitionToWaiting();
- break;
- case WAITING:
- // A timer will transition us to CHECKING.
- DCHECK(timer_->IsRunning());
- break;
- case CHECKING: {
- base::TimeTicks time_tick = message_queue_->GetNextMessageTimeTick();
- if (!time_tick.is_null()) {
- base::TimeDelta time_elapsed = base::TimeTicks::Now() - time_tick;
- if (time_elapsed.InMilliseconds() < kPreemptWaitTimeMs) {
- // Schedule another check for when the IPC may go long.
- timer_->Start(FROM_HERE,
- base::TimeDelta::FromMilliseconds(kPreemptWaitTimeMs) -
- time_elapsed,
- this, &GpuChannelMessageFilter::UpdatePreemptionState);
- } else {
- if (a_stub_is_descheduled_)
- TransitionToWouldPreemptDescheduled();
- else
- TransitionToPreempting();
- }
- }
- } break;
- case PREEMPTING:
- // A TransitionToIdle() timer should always be running in this state.
- DCHECK(timer_->IsRunning());
- if (a_stub_is_descheduled_)
- TransitionToWouldPreemptDescheduled();
- else
- TransitionToIdleIfCaughtUp();
- break;
- case WOULD_PREEMPT_DESCHEDULED:
- // A TransitionToIdle() timer should never be running in this state.
- DCHECK(!timer_->IsRunning());
- if (!a_stub_is_descheduled_)
- TransitionToPreempting();
- else
- TransitionToIdleIfCaughtUp();
- break;
- default:
- NOTREACHED();
- }
-}
-
-void GpuChannelMessageFilter::TransitionToIdleIfCaughtUp() {
- DCHECK(preemption_state_ == PREEMPTING ||
- preemption_state_ == WOULD_PREEMPT_DESCHEDULED);
- base::TimeTicks next_tick = message_queue_->GetNextMessageTimeTick();
- if (next_tick.is_null()) {
- TransitionToIdle();
- } else {
- base::TimeDelta time_elapsed = base::TimeTicks::Now() - next_tick;
- if (time_elapsed.InMilliseconds() < kStopPreemptThresholdMs)
- TransitionToIdle();
- }
-}
-
-void GpuChannelMessageFilter::TransitionToIdle() {
- DCHECK(preemption_state_ == PREEMPTING ||
- preemption_state_ == WOULD_PREEMPT_DESCHEDULED);
- // Stop any outstanding timer set to force us from PREEMPTING to IDLE.
- timer_->Stop();
-
- preemption_state_ = IDLE;
- preempting_flag_->Reset();
- TRACE_COUNTER_ID1("gpu", "GpuChannel::Preempting", this, 0);
-
- UpdatePreemptionState();
-}
-
-void GpuChannelMessageFilter::TransitionToWaiting() {
- DCHECK_EQ(preemption_state_, IDLE);
- DCHECK(!timer_->IsRunning());
-
- preemption_state_ = WAITING;
- timer_->Start(FROM_HERE,
- base::TimeDelta::FromMilliseconds(kPreemptWaitTimeMs), this,
- &GpuChannelMessageFilter::TransitionToChecking);
-}
-
-void GpuChannelMessageFilter::TransitionToChecking() {
- DCHECK_EQ(preemption_state_, WAITING);
- DCHECK(!timer_->IsRunning());
-
- preemption_state_ = CHECKING;
- max_preemption_time_ = base::TimeDelta::FromMilliseconds(kMaxPreemptTimeMs);
- UpdatePreemptionState();
-}
-
-void GpuChannelMessageFilter::TransitionToPreempting() {
- DCHECK(preemption_state_ == CHECKING ||
- preemption_state_ == WOULD_PREEMPT_DESCHEDULED);
- DCHECK(!a_stub_is_descheduled_);
-
- // Stop any pending state update checks that we may have queued
- // while CHECKING.
- if (preemption_state_ == CHECKING)
- timer_->Stop();
-
- preemption_state_ = PREEMPTING;
- preempting_flag_->Set();
- TRACE_COUNTER_ID1("gpu", "GpuChannel::Preempting", this, 1);
-
- timer_->Start(FROM_HERE, max_preemption_time_, this,
- &GpuChannelMessageFilter::TransitionToIdle);
-
- UpdatePreemptionState();
-}
-
-void GpuChannelMessageFilter::TransitionToWouldPreemptDescheduled() {
- DCHECK(preemption_state_ == CHECKING || preemption_state_ == PREEMPTING);
- DCHECK(a_stub_is_descheduled_);
-
- if (preemption_state_ == CHECKING) {
- // Stop any pending state update checks that we may have queued
- // while CHECKING.
- timer_->Stop();
- } else {
- // Stop any TransitionToIdle() timers that we may have queued
- // while PREEMPTING.
- timer_->Stop();
- max_preemption_time_ = timer_->desired_run_time() - base::TimeTicks::Now();
- if (max_preemption_time_ < base::TimeDelta()) {
- TransitionToIdle();
- return;
- }
- }
-
- preemption_state_ = WOULD_PREEMPT_DESCHEDULED;
- preempting_flag_->Reset();
- TRACE_COUNTER_ID1("gpu", "GpuChannel::Preempting", this, 0);
-
- UpdatePreemptionState();
-}
-
-GpuChannel::StreamState::StreamState(int32_t id, GpuStreamPriority priority)
- : id_(id), priority_(priority) {}
-
-GpuChannel::StreamState::~StreamState() {}
-
-void GpuChannel::StreamState::AddRoute(int32_t route_id) {
- routes_.insert(route_id);
-}
-void GpuChannel::StreamState::RemoveRoute(int32_t route_id) {
- routes_.erase(route_id);
-}
-
-bool GpuChannel::StreamState::HasRoute(int32_t route_id) const {
- return routes_.find(route_id) != routes_.end();
-}
-
-bool GpuChannel::StreamState::HasRoutes() const {
- return !routes_.empty();
-}
-
-GpuChannel::GpuChannel(GpuChannelManager* gpu_channel_manager,
- gpu::SyncPointManager* sync_point_manager,
- GpuWatchdog* watchdog,
- gfx::GLShareGroup* share_group,
- gpu::gles2::MailboxManager* mailbox,
- gpu::PreemptionFlag* preempting_flag,
- base::SingleThreadTaskRunner* task_runner,
- base::SingleThreadTaskRunner* io_task_runner,
- int client_id,
- uint64_t client_tracing_id,
- bool allow_future_sync_points,
- bool allow_real_time_streams)
- : gpu_channel_manager_(gpu_channel_manager),
- sync_point_manager_(sync_point_manager),
- channel_id_(IPC::Channel::GenerateVerifiedChannelID("gpu")),
- preempting_flag_(preempting_flag),
- client_id_(client_id),
- client_tracing_id_(client_tracing_id),
- task_runner_(task_runner),
- io_task_runner_(io_task_runner),
- share_group_(share_group),
- mailbox_manager_(mailbox),
- subscription_ref_set_(new gpu::gles2::SubscriptionRefSet),
- pending_valuebuffer_state_(new gpu::ValueStateMap),
- watchdog_(watchdog),
- num_stubs_descheduled_(0),
- allow_future_sync_points_(allow_future_sync_points),
- allow_real_time_streams_(allow_real_time_streams),
- weak_factory_(this) {
- DCHECK(gpu_channel_manager);
- DCHECK(client_id);
-
- message_queue_ = GpuChannelMessageQueue::Create(
- weak_factory_.GetWeakPtr(), task_runner, sync_point_manager);
-
- filter_ = new GpuChannelMessageFilter(
- weak_factory_.GetWeakPtr(), message_queue_.get(), task_runner,
- preempting_flag, allow_future_sync_points);
-
- subscription_ref_set_->AddObserver(this);
-}
-
-GpuChannel::~GpuChannel() {
- // Clear stubs first because of dependencies.
- stubs_.clear();
-
- message_queue_->DeleteAndDisableMessages();
-
- subscription_ref_set_->RemoveObserver(this);
- if (preempting_flag_.get())
- preempting_flag_->Reset();
-}
-
-IPC::ChannelHandle GpuChannel::Init(base::WaitableEvent* shutdown_event) {
- DCHECK(shutdown_event);
- DCHECK(!channel_);
-
- IPC::ChannelHandle channel_handle(channel_id_);
-
- channel_ =
- IPC::SyncChannel::Create(channel_handle, IPC::Channel::MODE_SERVER, this,
- io_task_runner_, false, shutdown_event);
-
-#if defined(OS_POSIX)
- // On POSIX, pass the renderer-side FD. Also mark it as auto-close so
- // that it gets closed after it has been sent.
- base::ScopedFD renderer_fd = channel_->TakeClientFileDescriptor();
- DCHECK(renderer_fd.is_valid());
- channel_handle.socket = base::FileDescriptor(std::move(renderer_fd));
-#endif
-
- channel_->AddFilter(filter_.get());
-
- return channel_handle;
-}
-
-base::ProcessId GpuChannel::GetClientPID() const {
- return channel_->GetPeerPID();
-}
-
-uint32_t GpuChannel::GetProcessedOrderNum() const {
- return message_queue_->GetProcessedOrderNum();
-}
-
-uint32_t GpuChannel::GetUnprocessedOrderNum() const {
- return message_queue_->GetUnprocessedOrderNum();
-}
-
-bool GpuChannel::OnMessageReceived(const IPC::Message& message) {
- // All messages should be pushed to channel_messages_ and handled separately.
- NOTREACHED();
- return false;
-}
-
-void GpuChannel::OnChannelError() {
- gpu_channel_manager_->RemoveChannel(client_id_);
-}
-
-bool GpuChannel::Send(IPC::Message* message) {
- // The GPU process must never send a synchronous IPC message to the renderer
- // process. This could result in deadlock.
- DCHECK(!message->is_sync());
-
- DVLOG(1) << "sending message @" << message << " on channel @" << this
- << " with type " << message->type();
-
- if (!channel_) {
- delete message;
- return false;
- }
-
- return channel_->Send(message);
-}
-
-void GpuChannel::OnAddSubscription(unsigned int target) {
- gpu_channel_manager()->Send(
- new GpuHostMsg_AddSubscription(client_id_, target));
-}
-
-void GpuChannel::OnRemoveSubscription(unsigned int target) {
- gpu_channel_manager()->Send(
- new GpuHostMsg_RemoveSubscription(client_id_, target));
-}
-
-void GpuChannel::OnStubSchedulingChanged(GpuCommandBufferStub* stub,
- bool scheduled) {
- bool a_stub_was_descheduled = num_stubs_descheduled_ > 0;
- if (scheduled) {
- num_stubs_descheduled_--;
- ScheduleHandleMessage();
- } else {
- num_stubs_descheduled_++;
- }
- DCHECK_LE(num_stubs_descheduled_, stubs_.size());
- bool a_stub_is_descheduled = num_stubs_descheduled_ > 0;
-
- if (a_stub_is_descheduled != a_stub_was_descheduled) {
- if (preempting_flag_.get()) {
- io_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&GpuChannelMessageFilter::UpdateStubSchedulingState,
- filter_, a_stub_is_descheduled));
- }
- }
-}
-
-CreateCommandBufferResult GpuChannel::CreateViewCommandBuffer(
- const gfx::GLSurfaceHandle& window,
- const GPUCreateCommandBufferConfig& init_params,
- int32_t route_id) {
- TRACE_EVENT1("gpu", "GpuChannel::CreateViewCommandBuffer", "route_id",
- route_id);
-
- int32_t share_group_id = init_params.share_group_id;
- GpuCommandBufferStub* share_group = stubs_.get(share_group_id);
-
- if (!share_group && share_group_id != MSG_ROUTING_NONE)
- return CREATE_COMMAND_BUFFER_FAILED;
-
- int32_t stream_id = init_params.stream_id;
- GpuStreamPriority stream_priority = init_params.stream_priority;
-
- if (share_group && stream_id != share_group->stream_id())
- return CREATE_COMMAND_BUFFER_FAILED;
-
- if (!allow_real_time_streams_ &&
- stream_priority == GpuStreamPriority::REAL_TIME)
- return CREATE_COMMAND_BUFFER_FAILED;
-
- auto stream_it = streams_.find(stream_id);
- if (stream_it != streams_.end() &&
- stream_priority != GpuStreamPriority::INHERIT &&
- stream_priority != stream_it->second.priority()) {
- return CREATE_COMMAND_BUFFER_FAILED;
- }
-
- bool offscreen = false;
- scoped_ptr<GpuCommandBufferStub> stub(new GpuCommandBufferStub(
- this, sync_point_manager_, task_runner_.get(), share_group, window,
- mailbox_manager_.get(), preempted_flag_.get(),
- subscription_ref_set_.get(), pending_valuebuffer_state_.get(),
- gfx::Size(), disallowed_features_, init_params.attribs,
- init_params.gpu_preference, stream_id, route_id, offscreen, watchdog_,
- init_params.active_url));
-
- if (!router_.AddRoute(route_id, stub.get())) {
- DLOG(ERROR) << "GpuChannel::CreateViewCommandBuffer(): "
- "failed to add route";
- return CREATE_COMMAND_BUFFER_FAILED_AND_CHANNEL_LOST;
- }
-
- if (stream_it != streams_.end()) {
- stream_it->second.AddRoute(route_id);
- } else {
- StreamState stream(stream_id, stream_priority);
- stream.AddRoute(route_id);
- streams_.insert(std::make_pair(stream_id, stream));
- }
-
- stubs_.set(route_id, std::move(stub));
- return CREATE_COMMAND_BUFFER_SUCCEEDED;
-}
-
-GpuCommandBufferStub* GpuChannel::LookupCommandBuffer(int32_t route_id) {
- return stubs_.get(route_id);
-}
-
-void GpuChannel::LoseAllContexts() {
- gpu_channel_manager_->LoseAllContexts();
-}
-
-void GpuChannel::MarkAllContextsLost() {
- for (auto& kv : stubs_)
- kv.second->MarkContextLost();
-}
-
-bool GpuChannel::AddRoute(int32_t route_id, IPC::Listener* listener) {
- return router_.AddRoute(route_id, listener);
-}
-
-void GpuChannel::RemoveRoute(int32_t route_id) {
- router_.RemoveRoute(route_id);
-}
-
-void GpuChannel::SetPreemptByFlag(
- scoped_refptr<gpu::PreemptionFlag> preempted_flag) {
- DCHECK(stubs_.empty());
- preempted_flag_ = preempted_flag;
-}
-
-void GpuChannel::OnDestroy() {
- TRACE_EVENT0("gpu", "GpuChannel::OnDestroy");
- gpu_channel_manager_->RemoveChannel(client_id_);
-}
-
-bool GpuChannel::OnControlMessageReceived(const IPC::Message& msg) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(GpuChannel, msg)
- IPC_MESSAGE_HANDLER(GpuChannelMsg_CreateOffscreenCommandBuffer,
- OnCreateOffscreenCommandBuffer)
- IPC_MESSAGE_HANDLER(GpuChannelMsg_DestroyCommandBuffer,
- OnDestroyCommandBuffer)
- IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuMsg_CreateJpegDecoder,
- OnCreateJpegDecoder)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- DCHECK(handled) << msg.type();
- return handled;
-}
-
-scoped_refptr<gpu::SyncPointOrderData> GpuChannel::GetSyncPointOrderData() {
- return message_queue_->GetSyncPointOrderData();
-}
-
-void GpuChannel::HandleMessage() {
- // If we have been preempted by another channel, just post a task to wake up.
- if (preempted_flag_ && preempted_flag_->IsSet()) {
- ScheduleHandleMessage();
- return;
- }
-
- GpuChannelMessage* m = message_queue_->GetNextMessage();
-
- // TODO(sunnyps): This could be a DCHECK maybe?
- if (!m)
- return;
-
- const IPC::Message& message = m->message;
- message_queue_->BeginMessageProcessing(m);
- int32_t routing_id = message.routing_id();
- GpuCommandBufferStub* stub = stubs_.get(routing_id);
-
- DCHECK(!stub || stub->IsScheduled());
-
- DVLOG(1) << "received message @" << &message << " on channel @" << this
- << " with type " << message.type();
-
- bool handled = false;
-
- if (routing_id == MSG_ROUTING_CONTROL) {
- handled = OnControlMessageReceived(message);
- } else if (message.type() == GpuCommandBufferMsg_InsertSyncPoint::ID) {
- // TODO(dyen): Temporary handling of old sync points.
- // This must ensure that the sync point will be retired. Normally we'll
- // find the stub based on the routing ID, and associate the sync point
- // with it, but if that fails for any reason (channel or stub already
- // deleted, invalid routing id), we need to retire the sync point
- // immediately.
- if (stub) {
- stub->InsertSyncPoint(m->sync_point, m->retire_sync_point);
- } else {
- sync_point_manager_->RetireSyncPoint(m->sync_point);
- }
- handled = true;
- } else {
- handled = router_.RouteMessage(message);
- }
-
- // Respond to sync messages even if router failed to route.
- if (!handled && message.is_sync()) {
- IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message);
- reply->set_reply_error();
- Send(reply);
- handled = true;
- }
-
- // A command buffer may be descheduled or preempted but only in the middle of
- // a flush. In this case we should not pop the message from the queue.
- if (stub && stub->HasUnprocessedCommands()) {
- DCHECK_EQ((uint32_t)GpuCommandBufferMsg_AsyncFlush::ID, message.type());
- message_queue_->PauseMessageProcessing(m);
- // If the stub is still scheduled then we were preempted and need to
- // schedule a wakeup otherwise some other event will wake us up e.g. sync
- // point completion. No DCHECK for preemption flag because that can change
- // any time.
- if (stub->IsScheduled())
- ScheduleHandleMessage();
- return;
- }
-
- if (message_queue_->MessageProcessed())
- ScheduleHandleMessage();
-
- if (preempting_flag_) {
- io_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&GpuChannelMessageFilter::OnMessageProcessed, filter_));
- }
-}
-
-void GpuChannel::ScheduleHandleMessage() {
- task_runner_->PostTask(FROM_HERE, base::Bind(&GpuChannel::HandleMessage,
- weak_factory_.GetWeakPtr()));
-}
-
-void GpuChannel::HandleOutOfOrderMessage(const IPC::Message& msg) {
- switch (msg.type()) {
- case GpuCommandBufferMsg_WaitForGetOffsetInRange::ID:
- case GpuCommandBufferMsg_WaitForTokenInRange::ID:
- router_.RouteMessage(msg);
- break;
- default:
- NOTREACHED();
- }
-}
-
-#if defined(OS_ANDROID)
-const GpuCommandBufferStub* GpuChannel::GetOneStub() const {
- for (const auto& kv : stubs_) {
- const GpuCommandBufferStub* stub = kv.second;
- if (stub->decoder() && !stub->decoder()->WasContextLost())
- return stub;
- }
- return nullptr;
-}
-#endif
-
-void GpuChannel::OnCreateOffscreenCommandBuffer(
- const gfx::Size& size,
- const GPUCreateCommandBufferConfig& init_params,
- int32_t route_id,
- bool* succeeded) {
- TRACE_EVENT1("gpu", "GpuChannel::OnCreateOffscreenCommandBuffer", "route_id",
- route_id);
-
- int32_t share_group_id = init_params.share_group_id;
- GpuCommandBufferStub* share_group = stubs_.get(share_group_id);
-
- if (!share_group && share_group_id != MSG_ROUTING_NONE) {
- *succeeded = false;
- return;
- }
-
- int32_t stream_id = init_params.stream_id;
- GpuStreamPriority stream_priority = init_params.stream_priority;
-
- if (share_group && stream_id != share_group->stream_id()) {
- *succeeded = false;
- return;
- }
-
- if (!allow_real_time_streams_ &&
- stream_priority == GpuStreamPriority::REAL_TIME) {
- *succeeded = false;
- return;
- }
-
- auto stream_it = streams_.find(stream_id);
- if (stream_it != streams_.end() &&
- stream_priority != GpuStreamPriority::INHERIT &&
- stream_priority != stream_it->second.priority()) {
- *succeeded = false;
- return;
- }
-
- bool offscreen = true;
- scoped_ptr<GpuCommandBufferStub> stub(new GpuCommandBufferStub(
- this, sync_point_manager_, task_runner_.get(), share_group,
- gfx::GLSurfaceHandle(), mailbox_manager_.get(), preempted_flag_.get(),
- subscription_ref_set_.get(), pending_valuebuffer_state_.get(), size,
- disallowed_features_, init_params.attribs, init_params.gpu_preference,
- init_params.stream_id, route_id, offscreen, watchdog_,
- init_params.active_url));
-
- if (!router_.AddRoute(route_id, stub.get())) {
- DLOG(ERROR) << "GpuChannel::OnCreateOffscreenCommandBuffer(): "
- "failed to add route";
- *succeeded = false;
- return;
- }
-
- if (stream_it != streams_.end()) {
- stream_it->second.AddRoute(route_id);
- } else {
- StreamState stream(stream_id, stream_priority);
- stream.AddRoute(route_id);
- streams_.insert(std::make_pair(stream_id, stream));
- }
-
- stubs_.set(route_id, std::move(stub));
- *succeeded = true;
-}
-
-void GpuChannel::OnDestroyCommandBuffer(int32_t route_id) {
- TRACE_EVENT1("gpu", "GpuChannel::OnDestroyCommandBuffer",
- "route_id", route_id);
-
- scoped_ptr<GpuCommandBufferStub> stub = stubs_.take_and_erase(route_id);
-
- if (!stub)
- return;
-
- router_.RemoveRoute(route_id);
-
- int32_t stream_id = stub->stream_id();
- auto stream_it = streams_.find(stream_id);
- DCHECK(stream_it != streams_.end());
- stream_it->second.RemoveRoute(route_id);
- if (!stream_it->second.HasRoutes())
- streams_.erase(stream_it);
-
- // In case the renderer is currently blocked waiting for a sync reply from the
- // stub, we need to make sure to reschedule the GpuChannel here.
- if (!stub->IsScheduled()) {
- // This stub won't get a chance to reschedule, so update the count now.
- OnStubSchedulingChanged(stub.get(), true);
- }
-}
-
-void GpuChannel::OnCreateJpegDecoder(int32_t route_id,
- IPC::Message* reply_msg) {
- if (!jpeg_decoder_) {
- jpeg_decoder_.reset(new GpuJpegDecodeAccelerator(this, io_task_runner_));
- }
- jpeg_decoder_->AddClient(route_id, reply_msg);
-}
-
-void GpuChannel::CacheShader(const std::string& key,
- const std::string& shader) {
- gpu_channel_manager_->Send(
- new GpuHostMsg_CacheShader(client_id_, key, shader));
-}
-
-void GpuChannel::AddFilter(IPC::MessageFilter* filter) {
- io_task_runner_->PostTask(
- FROM_HERE, base::Bind(&GpuChannelMessageFilter::AddChannelFilter,
- filter_, make_scoped_refptr(filter)));
-}
-
-void GpuChannel::RemoveFilter(IPC::MessageFilter* filter) {
- io_task_runner_->PostTask(
- FROM_HERE, base::Bind(&GpuChannelMessageFilter::RemoveChannelFilter,
- filter_, make_scoped_refptr(filter)));
-}
-
-uint64_t GpuChannel::GetMemoryUsage() {
- // Collect the unique memory trackers in use by the |stubs_|.
- std::set<gpu::gles2::MemoryTracker*> unique_memory_trackers;
- for (auto& kv : stubs_)
- unique_memory_trackers.insert(kv.second->GetMemoryTracker());
-
- // Sum the memory usage for all unique memory trackers.
- uint64_t size = 0;
- for (auto* tracker : unique_memory_trackers) {
- size += gpu_channel_manager()->gpu_memory_manager()->GetTrackerMemoryUsage(
- tracker);
- }
-
- return size;
-}
-
-scoped_refptr<gl::GLImage> GpuChannel::CreateImageForGpuMemoryBuffer(
- const gfx::GpuMemoryBufferHandle& handle,
- const gfx::Size& size,
- gfx::BufferFormat format,
- uint32_t internalformat) {
- switch (handle.type) {
- case gfx::SHARED_MEMORY_BUFFER: {
- if (!base::IsValueInRangeForNumericType<size_t>(handle.stride))
- return nullptr;
- scoped_refptr<gl::GLImageSharedMemory> image(
- new gl::GLImageSharedMemory(size, internalformat));
- if (!image->Initialize(handle.handle, handle.id, format, handle.offset,
- handle.stride)) {
- return nullptr;
- }
-
- return image;
- }
- default: {
- GpuChannelManager* manager = gpu_channel_manager();
- if (!manager->gpu_memory_buffer_factory())
- return nullptr;
-
- return manager->gpu_memory_buffer_factory()
- ->AsImageFactory()
- ->CreateImageForGpuMemoryBuffer(handle,
- size,
- format,
- internalformat,
- client_id_);
- }
- }
-}
-
-void GpuChannel::HandleUpdateValueState(
- unsigned int target, const gpu::ValueState& state) {
- pending_valuebuffer_state_->UpdateState(target, state);
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/gpu_channel.h b/chromium/content/common/gpu/gpu_channel.h
deleted file mode 100644
index 319f81d40ed..00000000000
--- a/chromium/content/common/gpu/gpu_channel.h
+++ /dev/null
@@ -1,485 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_GPU_CHANNEL_H_
-#define CONTENT_COMMON_GPU_GPU_CHANNEL_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <string>
-
-#include "base/containers/hash_tables.h"
-#include "base/containers/scoped_ptr_hash_map.h"
-#include "base/macros.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/trace_event/memory_dump_provider.h"
-#include "build/build_config.h"
-#include "content/common/content_export.h"
-#include "content/common/gpu/gpu_command_buffer_stub.h"
-#include "content/common/gpu/gpu_memory_manager.h"
-#include "content/common/gpu/gpu_result_codes.h"
-#include "content/common/gpu/gpu_stream_priority.h"
-#include "content/common/message_router.h"
-#include "gpu/command_buffer/service/valuebuffer_manager.h"
-#include "ipc/ipc_sync_channel.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gl/gl_share_group.h"
-#include "ui/gl/gpu_preference.h"
-
-struct GPUCreateCommandBufferConfig;
-
-namespace base {
-class WaitableEvent;
-}
-
-namespace gpu {
-class PreemptionFlag;
-class SyncPointOrderData;
-class SyncPointManager;
-union ValueState;
-class ValueStateMap;
-namespace gles2 {
-class SubscriptionRefSet;
-}
-}
-
-namespace IPC {
-class MessageFilter;
-}
-
-namespace content {
-class GpuChannelManager;
-class GpuChannelMessageFilter;
-class GpuChannelMessageQueue;
-class GpuJpegDecodeAccelerator;
-class GpuWatchdog;
-
-// Encapsulates an IPC channel between the GPU process and one renderer
-// process. On the renderer side there's a corresponding GpuChannelHost.
-class CONTENT_EXPORT GpuChannel
- : public IPC::Listener,
- public IPC::Sender,
- public gpu::gles2::SubscriptionRefSet::Observer {
- public:
- // Takes ownership of the renderer process handle.
- GpuChannel(GpuChannelManager* gpu_channel_manager,
- gpu::SyncPointManager* sync_point_manager,
- GpuWatchdog* watchdog,
- gfx::GLShareGroup* share_group,
- gpu::gles2::MailboxManager* mailbox_manager,
- gpu::PreemptionFlag* preempting_flag,
- base::SingleThreadTaskRunner* task_runner,
- base::SingleThreadTaskRunner* io_task_runner,
- int client_id,
- uint64_t client_tracing_id,
- bool allow_future_sync_points,
- bool allow_real_time_streams);
- ~GpuChannel() override;
-
- // Initializes the IPC channel. Caller takes ownership of the client FD in
- // the returned handle and is responsible for closing it.
- virtual IPC::ChannelHandle Init(base::WaitableEvent* shutdown_event);
-
- // Get the GpuChannelManager that owns this channel.
- GpuChannelManager* gpu_channel_manager() const {
- return gpu_channel_manager_;
- }
-
- const std::string& channel_id() const { return channel_id_; }
-
- virtual base::ProcessId GetClientPID() const;
-
- int client_id() const { return client_id_; }
-
- uint64_t client_tracing_id() const { return client_tracing_id_; }
-
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner() const {
- return io_task_runner_;
- }
-
- // IPC::Listener implementation:
- bool OnMessageReceived(const IPC::Message& msg) override;
- void OnChannelError() override;
-
- // IPC::Sender implementation:
- bool Send(IPC::Message* msg) override;
-
- // SubscriptionRefSet::Observer implementation
- void OnAddSubscription(unsigned int target) override;
- void OnRemoveSubscription(unsigned int target) override;
-
- // This is called when a command buffer transitions between scheduled and
- // descheduled states. When any stub is descheduled, we stop preempting
- // other channels.
- void OnStubSchedulingChanged(GpuCommandBufferStub* stub, bool scheduled);
-
- CreateCommandBufferResult CreateViewCommandBuffer(
- const gfx::GLSurfaceHandle& window,
- const GPUCreateCommandBufferConfig& init_params,
- int32_t route_id);
-
- gfx::GLShareGroup* share_group() const { return share_group_.get(); }
-
- GpuCommandBufferStub* LookupCommandBuffer(int32_t route_id);
-
- void LoseAllContexts();
- void MarkAllContextsLost();
-
- // Called to add a listener for a particular message routing ID.
- // Returns true if succeeded.
- bool AddRoute(int32_t route_id, IPC::Listener* listener);
-
- // Called to remove a listener for a particular message routing ID.
- void RemoveRoute(int32_t route_id);
-
- void SetPreemptingFlag(gpu::PreemptionFlag* flag);
-
- // If |preemption_flag->IsSet()|, any stub on this channel
- // should stop issuing GL commands. Setting this to NULL stops deferral.
- void SetPreemptByFlag(
- scoped_refptr<gpu::PreemptionFlag> preemption_flag);
-
- void CacheShader(const std::string& key, const std::string& shader);
-
- void AddFilter(IPC::MessageFilter* filter);
- void RemoveFilter(IPC::MessageFilter* filter);
-
- uint64_t GetMemoryUsage();
-
- scoped_refptr<gl::GLImage> CreateImageForGpuMemoryBuffer(
- const gfx::GpuMemoryBufferHandle& handle,
- const gfx::Size& size,
- gfx::BufferFormat format,
- uint32_t internalformat);
-
- bool allow_future_sync_points() const { return allow_future_sync_points_; }
-
- void HandleUpdateValueState(unsigned int target,
- const gpu::ValueState& state);
-
- // Visible for testing.
- const gpu::ValueStateMap* pending_valuebuffer_state() const {
- return pending_valuebuffer_state_.get();
- }
-
- // Visible for testing.
- GpuChannelMessageFilter* filter() const { return filter_.get(); }
-
- // Returns the global order number for the last processed IPC message.
- uint32_t GetProcessedOrderNum() const;
-
- // Returns the global order number for the last unprocessed IPC message.
- uint32_t GetUnprocessedOrderNum() const;
-
- // Returns the shared sync point global order data.
- scoped_refptr<gpu::SyncPointOrderData> GetSyncPointOrderData();
-
- void HandleMessage();
-
- // Some messages such as WaitForGetOffsetInRange and WaitForTokenInRange are
- // processed as soon as possible because the client is blocked until they
- // are completed.
- void HandleOutOfOrderMessage(const IPC::Message& msg);
-
-#if defined(OS_ANDROID)
- const GpuCommandBufferStub* GetOneStub() const;
-#endif
-
- protected:
- // The message filter on the io thread.
- scoped_refptr<GpuChannelMessageFilter> filter_;
-
- // Map of routing id to command buffer stub.
- base::ScopedPtrHashMap<int32_t, scoped_ptr<GpuCommandBufferStub>> stubs_;
-
- private:
- class StreamState {
- public:
- StreamState(int32_t id, GpuStreamPriority priority);
- ~StreamState();
-
- int32_t id() const { return id_; }
- GpuStreamPriority priority() const { return priority_; }
-
- void AddRoute(int32_t route_id);
- void RemoveRoute(int32_t route_id);
- bool HasRoute(int32_t route_id) const;
- bool HasRoutes() const;
-
- private:
- int32_t id_;
- GpuStreamPriority priority_;
- base::hash_set<int32_t> routes_;
- };
-
- void OnDestroy();
-
- bool OnControlMessageReceived(const IPC::Message& msg);
-
- void ScheduleHandleMessage();
-
- // Message handlers.
- void OnCreateOffscreenCommandBuffer(
- const gfx::Size& size,
- const GPUCreateCommandBufferConfig& init_params,
- int32_t route_id,
- bool* succeeded);
- void OnDestroyCommandBuffer(int32_t route_id);
- void OnCreateJpegDecoder(int32_t route_id, IPC::Message* reply_msg);
-
- // The lifetime of objects of this class is managed by a GpuChannelManager.
- // The GpuChannelManager destroy all the GpuChannels that they own when they
- // are destroyed. So a raw pointer is safe.
- GpuChannelManager* gpu_channel_manager_;
-
- // Sync point manager. Outlives the channel and is guaranteed to outlive the
- // message loop.
- gpu::SyncPointManager* sync_point_manager_;
-
- scoped_ptr<IPC::SyncChannel> channel_;
-
- // Uniquely identifies the channel within this GPU process.
- std::string channel_id_;
-
- // Used to implement message routing functionality to CommandBuffer objects
- MessageRouter router_;
-
- // Whether the processing of IPCs on this channel is stalled and we should
- // preempt other GpuChannels.
- scoped_refptr<gpu::PreemptionFlag> preempting_flag_;
-
- // If non-NULL, all stubs on this channel should stop processing GL
- // commands (via their GpuScheduler) when preempted_flag_->IsSet()
- scoped_refptr<gpu::PreemptionFlag> preempted_flag_;
-
- scoped_refptr<GpuChannelMessageQueue> message_queue_;
-
- // The id of the client who is on the other side of the channel.
- int client_id_;
-
- // The tracing ID used for memory allocations associated with this client.
- uint64_t client_tracing_id_;
-
- // The task runners for the main thread and the io thread.
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
-
- // The share group that all contexts associated with a particular renderer
- // process use.
- scoped_refptr<gfx::GLShareGroup> share_group_;
-
- scoped_refptr<gpu::gles2::MailboxManager> mailbox_manager_;
-
- scoped_refptr<gpu::gles2::SubscriptionRefSet> subscription_ref_set_;
-
- scoped_refptr<gpu::ValueStateMap> pending_valuebuffer_state_;
-
- scoped_ptr<GpuJpegDecodeAccelerator> jpeg_decoder_;
-
- gpu::gles2::DisallowedFeatures disallowed_features_;
- GpuWatchdog* watchdog_;
-
- size_t num_stubs_descheduled_;
-
- // Map of stream id to stream state.
- base::hash_map<int32_t, StreamState> streams_;
-
- bool allow_future_sync_points_;
- bool allow_real_time_streams_;
-
- // Member variables should appear before the WeakPtrFactory, to ensure
- // that any WeakPtrs to Controller are invalidated before its members
- // variable's destructors are executed, rendering them invalid.
- base::WeakPtrFactory<GpuChannel> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuChannel);
-};
-
-// This filter does three things:
-// - it counts and timestamps each message forwarded to the channel
-// so that we can preempt other channels if a message takes too long to
-// process. To guarantee fairness, we must wait a minimum amount of time
-// before preempting and we limit the amount of time that we can preempt in
-// one shot (see constants above).
-// - it handles the GpuCommandBufferMsg_InsertSyncPoint message on the IO
-// thread, generating the sync point ID and responding immediately, and then
-// posting a task to insert the GpuCommandBufferMsg_RetireSyncPoint message
-// into the channel's queue.
-// - it generates mailbox names for clients of the GPU process on the IO thread.
-class GpuChannelMessageFilter : public IPC::MessageFilter {
- public:
- GpuChannelMessageFilter(const base::WeakPtr<GpuChannel>& gpu_channel,
- GpuChannelMessageQueue* message_queue,
- base::SingleThreadTaskRunner* task_runner,
- gpu::PreemptionFlag* preempting_flag,
- bool future_sync_points);
-
- // IPC::MessageFilter implementation.
- void OnFilterAdded(IPC::Sender* sender) override;
- void OnFilterRemoved() override;
- void OnChannelConnected(int32_t peer_pid) override;
- void OnChannelError() override;
- void OnChannelClosing() override;
- bool OnMessageReceived(const IPC::Message& message) override;
-
- void AddChannelFilter(scoped_refptr<IPC::MessageFilter> filter);
- void RemoveChannelFilter(scoped_refptr<IPC::MessageFilter> filter);
-
- void OnMessageProcessed();
-
- void UpdateStubSchedulingState(bool a_stub_is_descheduled);
-
- bool Send(IPC::Message* message);
-
- protected:
- ~GpuChannelMessageFilter() override;
-
- private:
- enum PreemptionState {
- // Either there's no other channel to preempt, there are no messages
- // pending processing, or we just finished preempting and have to wait
- // before preempting again.
- IDLE,
- // We are waiting kPreemptWaitTimeMs before checking if we should preempt.
- WAITING,
- // We can preempt whenever any IPC processing takes more than
- // kPreemptWaitTimeMs.
- CHECKING,
- // We are currently preempting (i.e. no stub is descheduled).
- PREEMPTING,
- // We would like to preempt, but some stub is descheduled.
- WOULD_PREEMPT_DESCHEDULED,
- };
-
- void UpdatePreemptionState();
-
- void TransitionToIdleIfCaughtUp();
- void TransitionToIdle();
- void TransitionToWaiting();
- void TransitionToChecking();
- void TransitionToPreempting();
- void TransitionToWouldPreemptDescheduled();
-
- PreemptionState preemption_state_;
-
- // Maximum amount of time that we can spend in PREEMPTING.
- // It is reset when we transition to IDLE.
- base::TimeDelta max_preemption_time_;
-
- base::WeakPtr<GpuChannel> gpu_channel_;
- // The message_queue_ is used to handle messages on the main thread.
- scoped_refptr<GpuChannelMessageQueue> message_queue_;
- IPC::Sender* sender_;
- base::ProcessId peer_pid_;
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- scoped_refptr<gpu::PreemptionFlag> preempting_flag_;
- std::vector<scoped_refptr<IPC::MessageFilter>> channel_filters_;
-
- // This timer is created and destroyed on the IO thread.
- scoped_ptr<base::OneShotTimer> timer_;
-
- bool a_stub_is_descheduled_;
-
- // True if this channel can create future sync points.
- bool future_sync_points_;
-};
-
-struct GpuChannelMessage {
- uint32_t order_number;
- base::TimeTicks time_received;
- IPC::Message message;
-
- // TODO(dyen): Temporary sync point data, remove once new sync point lands.
- bool retire_sync_point;
- uint32_t sync_point;
-
- GpuChannelMessage(const IPC::Message& msg)
- : order_number(0),
- time_received(base::TimeTicks()),
- message(msg),
- retire_sync_point(false),
- sync_point(0) {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(GpuChannelMessage);
-};
-
-class GpuChannelMessageQueue
- : public base::RefCountedThreadSafe<GpuChannelMessageQueue> {
- public:
- static scoped_refptr<GpuChannelMessageQueue> Create(
- const base::WeakPtr<GpuChannel>& gpu_channel,
- base::SingleThreadTaskRunner* task_runner,
- gpu::SyncPointManager* sync_point_manager);
-
- scoped_refptr<gpu::SyncPointOrderData> GetSyncPointOrderData();
-
- // Returns the global order number for the last unprocessed IPC message.
- uint32_t GetUnprocessedOrderNum() const;
-
- // Returns the global order number for the last unprocessed IPC message.
- uint32_t GetProcessedOrderNum() const;
-
- bool HasQueuedMessages() const;
-
- base::TimeTicks GetNextMessageTimeTick() const;
-
- GpuChannelMessage* GetNextMessage() const;
-
- // Should be called before a message begins to be processed.
- void BeginMessageProcessing(const GpuChannelMessage* msg);
-
- // Should be called if a message began processing but did not finish.
- void PauseMessageProcessing(const GpuChannelMessage* msg);
-
- // Should be called after a message returned by GetNextMessage is processed.
- // Returns true if there are more messages on the queue.
- bool MessageProcessed();
-
- void PushBackMessage(const IPC::Message& message);
-
- bool GenerateSyncPointMessage(const IPC::Message& message,
- bool retire_sync_point,
- uint32_t* sync_point_number);
-
- void DeleteAndDisableMessages();
-
- private:
- friend class base::RefCountedThreadSafe<GpuChannelMessageQueue>;
-
- GpuChannelMessageQueue(const base::WeakPtr<GpuChannel>& gpu_channel,
- base::SingleThreadTaskRunner* task_runner,
- gpu::SyncPointManager* sync_point_manager);
- ~GpuChannelMessageQueue();
-
- void ScheduleHandleMessage();
-
- void PushMessageHelper(scoped_ptr<GpuChannelMessage> msg);
-
- bool enabled_;
-
- // Both deques own the messages.
- std::deque<GpuChannelMessage*> channel_messages_;
-
- // This lock protects enabled_ and channel_messages_.
- mutable base::Lock channel_messages_lock_;
-
- // Keeps track of sync point related state such as message order numbers.
- scoped_refptr<gpu::SyncPointOrderData> sync_point_order_data_;
-
- base::WeakPtr<GpuChannel> gpu_channel_;
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- gpu::SyncPointManager* sync_point_manager_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuChannelMessageQueue);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_GPU_CHANNEL_H_
diff --git a/chromium/content/common/gpu/gpu_channel_manager.cc b/chromium/content/common/gpu/gpu_channel_manager.cc
deleted file mode 100644
index 8f59e90345d..00000000000
--- a/chromium/content/common/gpu/gpu_channel_manager.cc
+++ /dev/null
@@ -1,380 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/gpu_channel_manager.h"
-
-#include <algorithm>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/location.h"
-#include "base/single_thread_task_runner.h"
-#include "base/thread_task_runner_handle.h"
-#include "build/build_config.h"
-#include "content/common/gpu/gpu_channel.h"
-#include "content/common/gpu/gpu_memory_buffer_factory.h"
-#include "content/common/gpu/gpu_memory_manager.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "content/common/message_router.h"
-#include "content/public/common/content_switches.h"
-#include "gpu/command_buffer/common/value_state.h"
-#include "gpu/command_buffer/service/feature_info.h"
-#include "gpu/command_buffer/service/gpu_switches.h"
-#include "gpu/command_buffer/service/mailbox_manager.h"
-#include "gpu/command_buffer/service/memory_program_cache.h"
-#include "gpu/command_buffer/service/shader_translator_cache.h"
-#include "gpu/command_buffer/service/sync_point_manager.h"
-#include "ipc/message_filter.h"
-#include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_share_group.h"
-
-#if defined(OS_CHROMEOS)
-#include "content/common/gpu/media/gpu_arc_video_service.h"
-#endif
-
-namespace content {
-
-namespace {
-#if defined(OS_ANDROID)
-// Amount of time we expect the GPU to stay powered up without being used.
-const int kMaxGpuIdleTimeMs = 40;
-// Maximum amount of time we keep pinging the GPU waiting for the client to
-// draw.
-const int kMaxKeepAliveTimeMs = 200;
-#endif
-
-}
-
-GpuChannelManager::GpuChannelManager(
- IPC::SyncChannel* channel,
- GpuWatchdog* watchdog,
- base::SingleThreadTaskRunner* task_runner,
- base::SingleThreadTaskRunner* io_task_runner,
- base::WaitableEvent* shutdown_event,
- gpu::SyncPointManager* sync_point_manager,
- GpuMemoryBufferFactory* gpu_memory_buffer_factory)
- : task_runner_(task_runner),
- io_task_runner_(io_task_runner),
- channel_(channel),
- watchdog_(watchdog),
- shutdown_event_(shutdown_event),
- share_group_(new gfx::GLShareGroup),
- mailbox_manager_(gpu::gles2::MailboxManager::Create()),
- gpu_memory_manager_(this),
- sync_point_manager_(sync_point_manager),
- sync_point_client_waiter_(
- sync_point_manager->CreateSyncPointClientWaiter()),
- gpu_memory_buffer_factory_(gpu_memory_buffer_factory),
- weak_factory_(this) {
- DCHECK(task_runner);
- DCHECK(io_task_runner);
- const base::CommandLine* command_line =
- base::CommandLine::ForCurrentProcess();
- if (command_line->HasSwitch(switches::kUIPrioritizeInGpuProcess))
- preemption_flag_ = new gpu::PreemptionFlag;
-}
-
-GpuChannelManager::~GpuChannelManager() {
- // Destroy channels before anything else because of dependencies.
- gpu_channels_.clear();
- if (default_offscreen_surface_.get()) {
- default_offscreen_surface_->Destroy();
- default_offscreen_surface_ = NULL;
- }
-}
-
-gpu::gles2::ProgramCache* GpuChannelManager::program_cache() {
- if (!program_cache_.get() &&
- (gfx::g_driver_gl.ext.b_GL_ARB_get_program_binary ||
- gfx::g_driver_gl.ext.b_GL_OES_get_program_binary) &&
- !base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableGpuProgramCache)) {
- program_cache_.reset(new gpu::gles2::MemoryProgramCache());
- }
- return program_cache_.get();
-}
-
-gpu::gles2::ShaderTranslatorCache*
-GpuChannelManager::shader_translator_cache() {
- if (!shader_translator_cache_.get())
- shader_translator_cache_ = new gpu::gles2::ShaderTranslatorCache;
- return shader_translator_cache_.get();
-}
-
-gpu::gles2::FramebufferCompletenessCache*
-GpuChannelManager::framebuffer_completeness_cache() {
- if (!framebuffer_completeness_cache_.get())
- framebuffer_completeness_cache_ =
- new gpu::gles2::FramebufferCompletenessCache;
- return framebuffer_completeness_cache_.get();
-}
-
-void GpuChannelManager::RemoveChannel(int client_id) {
- Send(new GpuHostMsg_DestroyChannel(client_id));
- gpu_channels_.erase(client_id);
-}
-
-int GpuChannelManager::GenerateRouteID() {
- static int last_id = 0;
- return ++last_id;
-}
-
-void GpuChannelManager::AddRoute(int32_t routing_id, IPC::Listener* listener) {
- router_.AddRoute(routing_id, listener);
-}
-
-void GpuChannelManager::RemoveRoute(int32_t routing_id) {
- router_.RemoveRoute(routing_id);
-}
-
-GpuChannel* GpuChannelManager::LookupChannel(int32_t client_id) const {
- const auto& it = gpu_channels_.find(client_id);
- return it != gpu_channels_.end() ? it->second : nullptr;
-}
-
-bool GpuChannelManager::OnControlMessageReceived(const IPC::Message& msg) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(GpuChannelManager, msg)
- IPC_MESSAGE_HANDLER(GpuMsg_EstablishChannel, OnEstablishChannel)
- IPC_MESSAGE_HANDLER(GpuMsg_CloseChannel, OnCloseChannel)
- IPC_MESSAGE_HANDLER(GpuMsg_CreateViewCommandBuffer,
- OnCreateViewCommandBuffer)
- IPC_MESSAGE_HANDLER(GpuMsg_DestroyGpuMemoryBuffer, OnDestroyGpuMemoryBuffer)
-#if defined(OS_CHROMEOS)
- IPC_MESSAGE_HANDLER(GpuMsg_CreateArcVideoAcceleratorChannel,
- OnCreateArcVideoAcceleratorChannel)
-#endif
- IPC_MESSAGE_HANDLER(GpuMsg_LoadedShader, OnLoadedShader)
- IPC_MESSAGE_HANDLER(GpuMsg_UpdateValueState, OnUpdateValueState)
-#if defined(OS_ANDROID)
- IPC_MESSAGE_HANDLER(GpuMsg_WakeUpGpu, OnWakeUpGpu);
-#endif
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-bool GpuChannelManager::OnMessageReceived(const IPC::Message& msg) {
- if (msg.routing_id() == MSG_ROUTING_CONTROL)
- return OnControlMessageReceived(msg);
-
- return router_.RouteMessage(msg);
-}
-
-bool GpuChannelManager::Send(IPC::Message* msg) {
- return channel_->Send(msg);
-}
-
-scoped_ptr<GpuChannel> GpuChannelManager::CreateGpuChannel(
- int client_id,
- uint64_t client_tracing_id,
- bool preempts,
- bool allow_future_sync_points,
- bool allow_real_time_streams) {
- return make_scoped_ptr(new GpuChannel(
- this, sync_point_manager(), watchdog_, share_group(), mailbox_manager(),
- preempts ? preemption_flag() : nullptr, task_runner_.get(),
- io_task_runner_.get(), client_id, client_tracing_id,
- allow_future_sync_points, allow_real_time_streams));
-}
-
-void GpuChannelManager::OnEstablishChannel(
- const GpuMsg_EstablishChannel_Params& params) {
- DCHECK(!params.preempts || !params.preempted);
- scoped_ptr<GpuChannel> channel(CreateGpuChannel(
- params.client_id, params.client_tracing_id, params.preempts,
- params.allow_future_sync_points, params.allow_real_time_streams));
- if (params.preempted)
- channel->SetPreemptByFlag(preemption_flag_.get());
- IPC::ChannelHandle channel_handle = channel->Init(shutdown_event_);
-
- gpu_channels_.set(params.client_id, std::move(channel));
-
- Send(new GpuHostMsg_ChannelEstablished(channel_handle));
-}
-
-void GpuChannelManager::OnCloseChannel(
- const IPC::ChannelHandle& channel_handle) {
- for (auto it = gpu_channels_.begin(); it != gpu_channels_.end(); ++it) {
- if (it->second->channel_id() == channel_handle.name) {
- gpu_channels_.erase(it);
- return;
- }
- }
-}
-
-void GpuChannelManager::OnCreateViewCommandBuffer(
- const gfx::GLSurfaceHandle& window,
- int32_t client_id,
- const GPUCreateCommandBufferConfig& init_params,
- int32_t route_id) {
- CreateCommandBufferResult result = CREATE_COMMAND_BUFFER_FAILED;
-
- auto it = gpu_channels_.find(client_id);
- if (it != gpu_channels_.end()) {
- result = it->second->CreateViewCommandBuffer(window, init_params, route_id);
- }
-
- Send(new GpuHostMsg_CommandBufferCreated(result));
-}
-
-void GpuChannelManager::DestroyGpuMemoryBuffer(
- gfx::GpuMemoryBufferId id,
- int client_id) {
- io_task_runner_->PostTask(
- FROM_HERE, base::Bind(&GpuChannelManager::DestroyGpuMemoryBufferOnIO,
- base::Unretained(this), id, client_id));
-}
-
-void GpuChannelManager::DestroyGpuMemoryBufferOnIO(
- gfx::GpuMemoryBufferId id,
- int client_id) {
- gpu_memory_buffer_factory_->DestroyGpuMemoryBuffer(id, client_id);
-}
-
-void GpuChannelManager::OnDestroyGpuMemoryBuffer(
- gfx::GpuMemoryBufferId id,
- int client_id,
- const gpu::SyncToken& sync_token) {
- if (sync_token.HasData()) {
- scoped_refptr<gpu::SyncPointClientState> release_state =
- sync_point_manager()->GetSyncPointClientState(
- sync_token.namespace_id(), sync_token.command_buffer_id());
- if (release_state) {
- sync_point_client_waiter_->WaitOutOfOrder(
- release_state.get(), sync_token.release_count(),
- base::Bind(&GpuChannelManager::DestroyGpuMemoryBuffer,
- base::Unretained(this), id, client_id));
- return;
- }
- }
-
- // No sync token or invalid sync token, destroy immediately.
- DestroyGpuMemoryBuffer(id, client_id);
-}
-
-#if defined(OS_CHROMEOS)
-void GpuChannelManager::OnCreateArcVideoAcceleratorChannel() {
- if (!gpu_arc_video_service_) {
- gpu_arc_video_service_.reset(
- new GpuArcVideoService(shutdown_event_, io_task_runner_));
- }
-
- gpu_arc_video_service_->CreateChannel(
- base::Bind(&GpuChannelManager::ArcVideoAcceleratorChannelCreated,
- weak_factory_.GetWeakPtr()));
-}
-
-void GpuChannelManager::ArcVideoAcceleratorChannelCreated(
- const IPC::ChannelHandle& handle) {
- Send(new GpuHostMsg_ArcVideoAcceleratorChannelCreated(handle));
-}
-
-void GpuChannelManager::OnShutdownArcVideoService() {
- gpu_arc_video_service_.reset();
-}
-#endif
-
-void GpuChannelManager::OnUpdateValueState(
- int client_id, unsigned int target, const gpu::ValueState& state) {
- // Only pass updated state to the channel corresponding to the
- // render_widget_host where the event originated.
- auto it = gpu_channels_.find(client_id);
- if (it != gpu_channels_.end())
- it->second->HandleUpdateValueState(target, state);
-}
-
-void GpuChannelManager::OnLoadedShader(const std::string& program_proto) {
- if (program_cache())
- program_cache()->LoadProgram(program_proto);
-}
-
-uint32_t GpuChannelManager::GetUnprocessedOrderNum() const {
- uint32_t unprocessed_order_num = 0;
- for (auto& kv : gpu_channels_) {
- unprocessed_order_num =
- std::max(unprocessed_order_num, kv.second->GetUnprocessedOrderNum());
- }
- return unprocessed_order_num;
-}
-
-uint32_t GpuChannelManager::GetProcessedOrderNum() const {
- uint32_t processed_order_num = 0;
- for (auto& kv : gpu_channels_) {
- processed_order_num =
- std::max(processed_order_num, kv.second->GetProcessedOrderNum());
- }
- return processed_order_num;
-}
-
-void GpuChannelManager::LoseAllContexts() {
- for (auto& kv : gpu_channels_) {
- kv.second->MarkAllContextsLost();
- }
- task_runner_->PostTask(FROM_HERE,
- base::Bind(&GpuChannelManager::OnLoseAllContexts,
- weak_factory_.GetWeakPtr()));
-}
-
-void GpuChannelManager::OnLoseAllContexts() {
- gpu_channels_.clear();
-}
-
-gfx::GLSurface* GpuChannelManager::GetDefaultOffscreenSurface() {
- if (!default_offscreen_surface_.get()) {
- default_offscreen_surface_ =
- gfx::GLSurface::CreateOffscreenGLSurface(gfx::Size());
- }
- return default_offscreen_surface_.get();
-}
-
-#if defined(OS_ANDROID)
-void GpuChannelManager::DidAccessGpu() {
- last_gpu_access_time_ = base::TimeTicks::Now();
-}
-
-void GpuChannelManager::OnWakeUpGpu() {
- begin_wake_up_time_ = base::TimeTicks::Now();
- ScheduleWakeUpGpu();
-}
-
-void GpuChannelManager::ScheduleWakeUpGpu() {
- base::TimeTicks now = base::TimeTicks::Now();
- TRACE_EVENT2("gpu", "GpuChannelManager::ScheduleWakeUp",
- "idle_time", (now - last_gpu_access_time_).InMilliseconds(),
- "keep_awake_time", (now - begin_wake_up_time_).InMilliseconds());
- if (now - last_gpu_access_time_ <
- base::TimeDelta::FromMilliseconds(kMaxGpuIdleTimeMs))
- return;
- if (now - begin_wake_up_time_ >
- base::TimeDelta::FromMilliseconds(kMaxKeepAliveTimeMs))
- return;
-
- DoWakeUpGpu();
-
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE, base::Bind(&GpuChannelManager::ScheduleWakeUpGpu,
- weak_factory_.GetWeakPtr()),
- base::TimeDelta::FromMilliseconds(kMaxGpuIdleTimeMs));
-}
-
-void GpuChannelManager::DoWakeUpGpu() {
- const GpuCommandBufferStub* stub = nullptr;
- for (const auto& kv : gpu_channels_) {
- const GpuChannel* channel = kv.second;
- stub = channel->GetOneStub();
- if (stub) {
- DCHECK(stub->decoder());
- break;
- }
- }
- if (!stub || !stub->decoder()->MakeCurrent())
- return;
- glFinish();
- DidAccessGpu();
-}
-#endif
-
-} // namespace content
diff --git a/chromium/content/common/gpu/gpu_channel_manager.h b/chromium/content/common/gpu/gpu_channel_manager.h
deleted file mode 100644
index f195a55c27e..00000000000
--- a/chromium/content/common/gpu/gpu_channel_manager.h
+++ /dev/null
@@ -1,227 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_GPU_CHANNEL_MANAGER_H_
-#define CONTENT_COMMON_GPU_GPU_CHANNEL_MANAGER_H_
-
-#include <stdint.h>
-
-#include <deque>
-#include <string>
-#include <vector>
-
-#include "base/containers/scoped_ptr_hash_map.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "build/build_config.h"
-#include "content/common/content_export.h"
-#include "content/common/content_param_traits.h"
-#include "content/common/gpu/gpu_memory_manager.h"
-#include "content/common/message_router.h"
-#include "ipc/ipc_listener.h"
-#include "ipc/ipc_sender.h"
-#include "ui/gfx/gpu_memory_buffer.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gl/gl_surface.h"
-
-namespace base {
-class WaitableEvent;
-}
-
-namespace gfx {
-class GLShareGroup;
-}
-
-namespace gpu {
-class PreemptionFlag;
-class SyncPointClient;
-class SyncPointManager;
-struct SyncToken;
-union ValueState;
-namespace gles2 {
-class FramebufferCompletenessCache;
-class MailboxManager;
-class ProgramCache;
-class ShaderTranslatorCache;
-}
-}
-
-namespace IPC {
-struct ChannelHandle;
-class SyncChannel;
-}
-
-struct GPUCreateCommandBufferConfig;
-struct GpuMsg_EstablishChannel_Params;
-
-namespace content {
-#if defined(OS_CHROMEOS)
-class GpuArcVideoService;
-#endif
-class GpuChannel;
-class GpuMemoryBufferFactory;
-class GpuWatchdog;
-
-// A GpuChannelManager is a thread responsible for issuing rendering commands
-// managing the lifetimes of GPU channels and forwarding IPC requests from the
-// browser process to them based on the corresponding renderer ID.
-class CONTENT_EXPORT GpuChannelManager : public IPC::Listener,
- public IPC::Sender {
- public:
- GpuChannelManager(IPC::SyncChannel* channel,
- GpuWatchdog* watchdog,
- base::SingleThreadTaskRunner* task_runner,
- base::SingleThreadTaskRunner* io_task_runner,
- base::WaitableEvent* shutdown_event,
- gpu::SyncPointManager* sync_point_manager,
- GpuMemoryBufferFactory* gpu_memory_buffer_factory);
- ~GpuChannelManager() override;
-
- // Remove the channel for a particular renderer.
- void RemoveChannel(int client_id);
-
- // Listener overrides.
- bool OnMessageReceived(const IPC::Message& msg) override;
-
- // Sender overrides.
- bool Send(IPC::Message* msg) override;
-
- void LoseAllContexts();
-
- int GenerateRouteID();
- void AddRoute(int32_t routing_id, IPC::Listener* listener);
- void RemoveRoute(int32_t routing_id);
-
- gpu::gles2::ProgramCache* program_cache();
- gpu::gles2::ShaderTranslatorCache* shader_translator_cache();
- gpu::gles2::FramebufferCompletenessCache* framebuffer_completeness_cache();
-
- GpuMemoryManager* gpu_memory_manager() { return &gpu_memory_manager_; }
-
- GpuChannel* LookupChannel(int32_t client_id) const;
-
- gfx::GLSurface* GetDefaultOffscreenSurface();
-
- GpuMemoryBufferFactory* gpu_memory_buffer_factory() {
- return gpu_memory_buffer_factory_;
- }
-
- // Returns the maximum order number for unprocessed IPC messages across all
- // channels.
- uint32_t GetUnprocessedOrderNum() const;
-
- // Returns the maximum order number for processed IPC messages across all
- // channels.
- uint32_t GetProcessedOrderNum() const;
-
-#if defined(OS_ANDROID)
- void DidAccessGpu();
-#endif
-
- protected:
- virtual scoped_ptr<GpuChannel> CreateGpuChannel(int client_id,
- uint64_t client_tracing_id,
- bool preempts,
- bool allow_future_sync_points,
- bool allow_real_time_streams);
-
- gpu::SyncPointManager* sync_point_manager() const {
- return sync_point_manager_;
- }
-
- gfx::GLShareGroup* share_group() const { return share_group_.get(); }
- gpu::gles2::MailboxManager* mailbox_manager() const {
- return mailbox_manager_.get();
- }
- gpu::PreemptionFlag* preemption_flag() const {
- return preemption_flag_.get();
- }
-
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
-
- // These objects manage channels to individual renderer processes there is
- // one channel for each renderer process that has connected to this GPU
- // process.
- base::ScopedPtrHashMap<int32_t, scoped_ptr<GpuChannel>> gpu_channels_;
-
- private:
- // Message handlers.
- bool OnControlMessageReceived(const IPC::Message& msg);
- void OnEstablishChannel(const GpuMsg_EstablishChannel_Params& params);
- void OnCloseChannel(const IPC::ChannelHandle& channel_handle);
- void OnVisibilityChanged(int32_t render_view_id,
- int32_t client_id,
- bool visible);
- void OnCreateViewCommandBuffer(
- const gfx::GLSurfaceHandle& window,
- int32_t client_id,
- const GPUCreateCommandBufferConfig& init_params,
- int32_t route_id);
- void OnLoadedShader(const std::string& shader);
- void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id, int client_id);
- void DestroyGpuMemoryBufferOnIO(gfx::GpuMemoryBufferId id, int client_id);
- void OnDestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
- int client_id,
- const gpu::SyncToken& sync_token);
-#if defined(OS_CHROMEOS)
- void OnCreateArcVideoAcceleratorChannel();
- void ArcVideoAcceleratorChannelCreated(const IPC::ChannelHandle& handle);
- void OnShutdownArcVideoService();
-#endif
-
- void OnUpdateValueState(int client_id,
- unsigned int target,
- const gpu::ValueState& state);
-#if defined(OS_ANDROID)
- void OnWakeUpGpu();
- void ScheduleWakeUpGpu();
- void DoWakeUpGpu();
-#endif
- void OnLoseAllContexts();
-
- // Used to send and receive IPC messages from the browser process.
- IPC::SyncChannel* const channel_;
- MessageRouter router_;
-
- GpuWatchdog* watchdog_;
-
- base::WaitableEvent* shutdown_event_;
-
- scoped_refptr<gfx::GLShareGroup> share_group_;
- scoped_refptr<gpu::gles2::MailboxManager> mailbox_manager_;
- scoped_refptr<gpu::PreemptionFlag> preemption_flag_;
- GpuMemoryManager gpu_memory_manager_;
- // SyncPointManager guaranteed to outlive running MessageLoop.
- gpu::SyncPointManager* sync_point_manager_;
- scoped_ptr<gpu::SyncPointClient> sync_point_client_waiter_;
- scoped_ptr<gpu::gles2::ProgramCache> program_cache_;
- scoped_refptr<gpu::gles2::ShaderTranslatorCache> shader_translator_cache_;
- scoped_refptr<gpu::gles2::FramebufferCompletenessCache>
- framebuffer_completeness_cache_;
- scoped_refptr<gfx::GLSurface> default_offscreen_surface_;
-#if defined(OS_CHROMEOS)
- scoped_ptr<GpuArcVideoService> gpu_arc_video_service_;
-#endif
- GpuMemoryBufferFactory* const gpu_memory_buffer_factory_;
-#if defined(OS_ANDROID)
- // Last time we know the GPU was powered on. Global for tracking across all
- // transport surfaces.
- base::TimeTicks last_gpu_access_time_;
- base::TimeTicks begin_wake_up_time_;
-#endif
-
- // Member variables should appear before the WeakPtrFactory, to ensure
- // that any WeakPtrs to Controller are invalidated before its members
- // variable's destructors are executed, rendering them invalid.
- base::WeakPtrFactory<GpuChannelManager> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuChannelManager);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_GPU_CHANNEL_MANAGER_H_
diff --git a/chromium/content/common/gpu/gpu_channel_manager_unittest.cc b/chromium/content/common/gpu/gpu_channel_manager_unittest.cc
deleted file mode 100644
index bef694808e8..00000000000
--- a/chromium/content/common/gpu/gpu_channel_manager_unittest.cc
+++ /dev/null
@@ -1,120 +0,0 @@
-// Copyright (c) 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "content/common/gpu/gpu_channel.h"
-#include "content/common/gpu/gpu_channel_manager.h"
-#include "content/common/gpu/gpu_channel_test_common.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "gpu/command_buffer/common/value_state.h"
-#include "gpu/command_buffer/service/gl_utils.h"
-#include "gpu/command_buffer/service/valuebuffer_manager.h"
-#include "ipc/ipc_test_sink.h"
-
-using gpu::gles2::ValuebufferManager;
-using gpu::ValueState;
-
-namespace content {
-
-class GpuChannelManagerTest : public GpuChannelTestCommon {
- public:
- GpuChannelManagerTest() : GpuChannelTestCommon() {}
- ~GpuChannelManagerTest() override {}
-};
-
-TEST_F(GpuChannelManagerTest, EstablishChannel) {
- int32_t kClientId = 1;
- uint64_t kClientTracingId = 1;
-
- ASSERT_TRUE(channel_manager());
-
- GpuMsg_EstablishChannel_Params params;
- params.client_id = kClientId;
- params.client_tracing_id = kClientTracingId;
- params.preempts = false;
- params.preempted = false;
- params.allow_future_sync_points = false;
- params.allow_real_time_streams = false;
- EXPECT_TRUE(
- channel_manager()->OnMessageReceived(GpuMsg_EstablishChannel(params)));
- EXPECT_EQ((size_t)1, sink()->message_count());
- const IPC::Message* msg =
- sink()->GetUniqueMessageMatching(GpuHostMsg_ChannelEstablished::ID);
- ASSERT_TRUE(msg);
- base::Tuple<IPC::ChannelHandle> handle;
- ASSERT_TRUE(GpuHostMsg_ChannelEstablished::Read(msg, &handle));
- EXPECT_NE("", base::get<0>(handle).name);
- sink()->ClearMessages();
-
- GpuChannel* channel = channel_manager()->LookupChannel(kClientId);
- ASSERT_TRUE(channel);
- EXPECT_EQ(base::get<0>(handle).name, channel->channel_id());
-}
-
-TEST_F(GpuChannelManagerTest, SecureValueStateForwarding) {
- int32_t kClientId1 = 111;
- uint64_t kClientTracingId1 = 11111;
- int32_t kClientId2 = 222;
- uint64_t kClientTracingId2 = 22222;
- ValueState value_state1;
- value_state1.int_value[0] = 1111;
- value_state1.int_value[1] = 0;
- value_state1.int_value[2] = 0;
- value_state1.int_value[3] = 0;
- ValueState value_state2;
- value_state2.int_value[0] = 3333;
- value_state2.int_value[1] = 0;
- value_state2.int_value[2] = 0;
- value_state2.int_value[3] = 0;
-
- ASSERT_TRUE(channel_manager());
-
- // Initialize gpu channels
- GpuMsg_EstablishChannel_Params params;
- params.client_id = kClientId1;
- params.client_tracing_id = kClientTracingId1;
- params.preempts = false;
- params.preempted = false;
- params.allow_future_sync_points = false;
- params.allow_real_time_streams = false;
- EXPECT_TRUE(
- channel_manager()->OnMessageReceived(GpuMsg_EstablishChannel(params)));
- GpuChannel* channel1 = channel_manager()->LookupChannel(kClientId1);
- ASSERT_TRUE(channel1);
-
- params.client_id = kClientId2;
- params.client_tracing_id = kClientTracingId2;
- EXPECT_TRUE(
- channel_manager()->OnMessageReceived(GpuMsg_EstablishChannel(params)));
- GpuChannel* channel2 = channel_manager()->LookupChannel(kClientId2);
- ASSERT_TRUE(channel2);
-
- EXPECT_NE(channel1, channel2);
-
- // Make sure value states are only accessible by proper channels
- channel_manager()->OnMessageReceived(GpuMsg_UpdateValueState(
- kClientId1, GL_MOUSE_POSITION_CHROMIUM, value_state1));
- channel_manager()->OnMessageReceived(GpuMsg_UpdateValueState(
- kClientId2, GL_MOUSE_POSITION_CHROMIUM, value_state2));
-
- const gpu::ValueStateMap* pending_value_buffer_state1 =
- channel1->pending_valuebuffer_state();
- const gpu::ValueStateMap* pending_value_buffer_state2 =
- channel2->pending_valuebuffer_state();
- EXPECT_NE(pending_value_buffer_state1, pending_value_buffer_state2);
-
- const ValueState* state1 =
- pending_value_buffer_state1->GetState(GL_MOUSE_POSITION_CHROMIUM);
- const ValueState* state2 =
- pending_value_buffer_state2->GetState(GL_MOUSE_POSITION_CHROMIUM);
- EXPECT_NE(state1, state2);
-
- EXPECT_EQ(state1->int_value[0], value_state1.int_value[0]);
- EXPECT_EQ(state2->int_value[0], value_state2.int_value[0]);
- EXPECT_NE(state1->int_value[0], state2->int_value[0]);
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/gpu_channel_test_common.cc b/chromium/content/common/gpu/gpu_channel_test_common.cc
deleted file mode 100644
index 7fe03759fc9..00000000000
--- a/chromium/content/common/gpu/gpu_channel_test_common.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright (c) 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/gpu_channel_test_common.h"
-
-#include "base/test/test_simple_task_runner.h"
-#include "base/thread_task_runner_handle.h"
-#include "gpu/command_buffer/service/sync_point_manager.h"
-#include "ipc/ipc_test_sink.h"
-
-namespace content {
-
-TestGpuChannelManager::TestGpuChannelManager(
- IPC::TestSink* sink,
- base::SingleThreadTaskRunner* task_runner,
- base::SingleThreadTaskRunner* io_task_runner,
- gpu::SyncPointManager* sync_point_manager,
- GpuMemoryBufferFactory* gpu_memory_buffer_factory)
- : GpuChannelManager(nullptr,
- nullptr,
- task_runner,
- io_task_runner,
- nullptr,
- sync_point_manager,
- gpu_memory_buffer_factory),
- sink_(sink) {}
-
-TestGpuChannelManager::~TestGpuChannelManager() {
- // Clear gpu channels here so that any IPC messages sent are handled using the
- // overridden Send method.
- gpu_channels_.clear();
-}
-
-bool TestGpuChannelManager::Send(IPC::Message* msg) {
- return sink_->Send(msg);
-}
-
-scoped_ptr<GpuChannel> TestGpuChannelManager::CreateGpuChannel(
- int client_id,
- uint64_t client_tracing_id,
- bool preempts,
- bool allow_future_sync_points,
- bool allow_real_time_streams) {
- return make_scoped_ptr(new TestGpuChannel(
- sink_, this, sync_point_manager(), share_group(), mailbox_manager(),
- preempts ? preemption_flag() : nullptr, task_runner_.get(),
- io_task_runner_.get(), client_id, client_tracing_id,
- allow_future_sync_points, allow_real_time_streams));
-}
-
-TestGpuChannel::TestGpuChannel(IPC::TestSink* sink,
- GpuChannelManager* gpu_channel_manager,
- gpu::SyncPointManager* sync_point_manager,
- gfx::GLShareGroup* share_group,
- gpu::gles2::MailboxManager* mailbox_manager,
- gpu::PreemptionFlag* preempting_flag,
- base::SingleThreadTaskRunner* task_runner,
- base::SingleThreadTaskRunner* io_task_runner,
- int client_id,
- uint64_t client_tracing_id,
- bool allow_future_sync_points,
- bool allow_real_time_streams)
- : GpuChannel(gpu_channel_manager,
- sync_point_manager,
- nullptr,
- share_group,
- mailbox_manager,
- preempting_flag,
- task_runner,
- io_task_runner,
- client_id,
- client_tracing_id,
- allow_future_sync_points,
- allow_real_time_streams),
- sink_(sink) {}
-
-TestGpuChannel::~TestGpuChannel() {
- // Call stubs here so that any IPC messages sent are handled using the
- // overridden Send method.
- stubs_.clear();
-}
-
-base::ProcessId TestGpuChannel::GetClientPID() const {
- return base::kNullProcessId;
-}
-
-IPC::ChannelHandle TestGpuChannel::Init(base::WaitableEvent* shutdown_event) {
- filter_->OnFilterAdded(sink_);
- return IPC::ChannelHandle(channel_id());
-}
-
-bool TestGpuChannel::Send(IPC::Message* msg) {
- DCHECK(!msg->is_sync());
- return sink_->Send(msg);
-}
-
-// TODO(sunnyps): Use a mock memory buffer factory when necessary.
-GpuChannelTestCommon::GpuChannelTestCommon()
- : sink_(new IPC::TestSink),
- task_runner_(new base::TestSimpleTaskRunner),
- io_task_runner_(new base::TestSimpleTaskRunner),
- sync_point_manager_(new gpu::SyncPointManager(false)),
- channel_manager_(new TestGpuChannelManager(sink_.get(),
- task_runner_.get(),
- io_task_runner_.get(),
- sync_point_manager_.get(),
- nullptr)) {}
-
-GpuChannelTestCommon::~GpuChannelTestCommon() {}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/gpu_channel_test_common.h b/chromium/content/common/gpu/gpu_channel_test_common.h
deleted file mode 100644
index ed2243531dd..00000000000
--- a/chromium/content/common/gpu/gpu_channel_test_common.h
+++ /dev/null
@@ -1,93 +0,0 @@
-// Copyright (c) 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stdint.h>
-
-#include "base/memory/scoped_ptr.h"
-#include "content/common/gpu/gpu_channel.h"
-#include "content/common/gpu/gpu_channel_manager.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-class TestSimpleTaskRunner;
-} // namespace base
-
-namespace IPC {
-class TestSink;
-} // namespace IPC
-
-namespace content {
-
-class SyncPointManager;
-
-class TestGpuChannelManager : public GpuChannelManager {
- public:
- TestGpuChannelManager(IPC::TestSink* sink,
- base::SingleThreadTaskRunner* task_runner,
- base::SingleThreadTaskRunner* io_task_runner,
- gpu::SyncPointManager* sync_point_manager,
- GpuMemoryBufferFactory* gpu_memory_buffer_factory);
- ~TestGpuChannelManager() override;
-
- // IPC::Sender implementation.
- bool Send(IPC::Message* msg) override;
-
- protected:
- scoped_ptr<GpuChannel> CreateGpuChannel(
- int client_id,
- uint64_t client_tracing_id,
- bool preempts,
- bool allow_future_sync_points,
- bool allow_real_time_streams) override;
-
- private:
- IPC::TestSink* const sink_;
-};
-
-class TestGpuChannel : public GpuChannel {
- public:
- TestGpuChannel(IPC::TestSink* sink,
- GpuChannelManager* gpu_channel_manager,
- gpu::SyncPointManager* sync_point_manager,
- gfx::GLShareGroup* share_group,
- gpu::gles2::MailboxManager* mailbox_manager,
- gpu::PreemptionFlag* preempting_flag,
- base::SingleThreadTaskRunner* task_runner,
- base::SingleThreadTaskRunner* io_task_runner,
- int client_id,
- uint64_t client_tracing_id,
- bool allow_future_sync_points,
- bool allow_real_time_streams);
- ~TestGpuChannel() override;
-
- base::ProcessId GetClientPID() const override;
-
- IPC::ChannelHandle Init(base::WaitableEvent* shutdown_event) override;
-
- // IPC::Sender implementation.
- bool Send(IPC::Message* msg) override;
-
- private:
- IPC::TestSink* const sink_;
-};
-
-class GpuChannelTestCommon : public testing::Test {
- public:
- GpuChannelTestCommon();
- ~GpuChannelTestCommon() override;
-
- protected:
- IPC::TestSink* sink() { return sink_.get(); }
- GpuChannelManager* channel_manager() { return channel_manager_.get(); }
- base::TestSimpleTaskRunner* task_runner() { return task_runner_.get(); }
-
- private:
- scoped_ptr<IPC::TestSink> sink_;
- scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
- scoped_refptr<base::TestSimpleTaskRunner> io_task_runner_;
- scoped_ptr<gpu::SyncPointManager> sync_point_manager_;
- scoped_ptr<GpuChannelManager> channel_manager_;
-};
-
-} // namespace content
diff --git a/chromium/content/common/gpu/gpu_channel_unittest.cc b/chromium/content/common/gpu/gpu_channel_unittest.cc
deleted file mode 100644
index d7a376aef76..00000000000
--- a/chromium/content/common/gpu/gpu_channel_unittest.cc
+++ /dev/null
@@ -1,329 +0,0 @@
-// Copyright (c) 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stdint.h>
-
-#include "base/test/test_simple_task_runner.h"
-#include "content/common/gpu/gpu_channel.h"
-#include "content/common/gpu/gpu_channel_manager.h"
-#include "content/common/gpu/gpu_channel_test_common.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "ipc/ipc_test_sink.h"
-
-namespace content {
-
-class GpuChannelTest : public GpuChannelTestCommon {
- public:
- GpuChannelTest() : GpuChannelTestCommon() {}
- ~GpuChannelTest() override {}
-
- GpuChannel* CreateChannel(int32_t client_id, bool allow_real_time_streams) {
- DCHECK(channel_manager());
- uint64_t kClientTracingId = 1;
- GpuMsg_EstablishChannel_Params params;
- params.client_id = client_id;
- params.client_tracing_id = kClientTracingId;
- params.preempts = false;
- params.preempted = false;
- params.allow_future_sync_points = false;
- params.allow_real_time_streams = allow_real_time_streams;
- EXPECT_TRUE(
- channel_manager()->OnMessageReceived(GpuMsg_EstablishChannel(params)));
- return channel_manager()->LookupChannel(client_id);
- }
-};
-
-TEST_F(GpuChannelTest, CreateViewCommandBuffer) {
- int32_t kClientId = 1;
- GpuChannel* channel = CreateChannel(kClientId, false);
- ASSERT_TRUE(channel);
-
- gfx::GLSurfaceHandle surface_handle;
- int32_t kRouteId = 1;
- GPUCreateCommandBufferConfig init_params;
- init_params.share_group_id = MSG_ROUTING_NONE;
- init_params.stream_id = 0;
- init_params.stream_priority = GpuStreamPriority::NORMAL;
- init_params.attribs = std::vector<int>();
- init_params.active_url = GURL();
- init_params.gpu_preference = gfx::PreferIntegratedGpu;
- channel_manager()->OnMessageReceived(GpuMsg_CreateViewCommandBuffer(
- surface_handle, kClientId, init_params, kRouteId));
-
- const IPC::Message* msg =
- sink()->GetUniqueMessageMatching(GpuHostMsg_CommandBufferCreated::ID);
- ASSERT_TRUE(msg);
-
- base::Tuple<CreateCommandBufferResult> result;
- ASSERT_TRUE(GpuHostMsg_CommandBufferCreated::Read(msg, &result));
-
- EXPECT_EQ(CREATE_COMMAND_BUFFER_SUCCEEDED, base::get<0>(result));
-
- sink()->ClearMessages();
-
- GpuCommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId);
- ASSERT_TRUE(stub);
-}
-
-TEST_F(GpuChannelTest, IncompatibleStreamIds) {
- int32_t kClientId = 1;
- GpuChannel* channel = CreateChannel(kClientId, false);
- ASSERT_TRUE(channel);
-
- // Create first context.
- int32_t kRouteId1 = 1;
- int32_t kStreamId1 = 1;
- GPUCreateCommandBufferConfig init_params;
- init_params.share_group_id = MSG_ROUTING_NONE;
- init_params.stream_id = kStreamId1;
- init_params.stream_priority = GpuStreamPriority::NORMAL;
- init_params.attribs = std::vector<int>();
- init_params.active_url = GURL();
- init_params.gpu_preference = gfx::PreferIntegratedGpu;
- channel_manager()->OnMessageReceived(GpuMsg_CreateViewCommandBuffer(
- gfx::GLSurfaceHandle(), kClientId, init_params, kRouteId1));
-
- const IPC::Message* msg =
- sink()->GetUniqueMessageMatching(GpuHostMsg_CommandBufferCreated::ID);
- ASSERT_TRUE(msg);
-
- base::Tuple<CreateCommandBufferResult> result;
- ASSERT_TRUE(GpuHostMsg_CommandBufferCreated::Read(msg, &result));
-
- EXPECT_EQ(CREATE_COMMAND_BUFFER_SUCCEEDED, base::get<0>(result));
-
- sink()->ClearMessages();
-
- GpuCommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId1);
- ASSERT_TRUE(stub);
-
- // Create second context in same share group but different stream.
- int32_t kRouteId2 = 2;
- int32_t kStreamId2 = 2;
-
- init_params.share_group_id = kRouteId1;
- init_params.stream_id = kStreamId2;
- init_params.stream_priority = GpuStreamPriority::NORMAL;
- init_params.attribs = std::vector<int>();
- init_params.active_url = GURL();
- init_params.gpu_preference = gfx::PreferIntegratedGpu;
- channel_manager()->OnMessageReceived(GpuMsg_CreateViewCommandBuffer(
- gfx::GLSurfaceHandle(), kClientId, init_params, kRouteId2));
-
- msg = sink()->GetUniqueMessageMatching(GpuHostMsg_CommandBufferCreated::ID);
- ASSERT_TRUE(msg);
-
- ASSERT_TRUE(GpuHostMsg_CommandBufferCreated::Read(msg, &result));
-
- EXPECT_EQ(CREATE_COMMAND_BUFFER_FAILED, base::get<0>(result));
-
- sink()->ClearMessages();
-
- stub = channel->LookupCommandBuffer(kRouteId2);
- ASSERT_FALSE(stub);
-}
-
-TEST_F(GpuChannelTest, IncompatibleStreamPriorities) {
- int32_t kClientId = 1;
- GpuChannel* channel = CreateChannel(kClientId, false);
- ASSERT_TRUE(channel);
-
- // Create first context.
- int32_t kRouteId1 = 1;
- int32_t kStreamId1 = 1;
- GpuStreamPriority kStreamPriority1 = GpuStreamPriority::NORMAL;
- GPUCreateCommandBufferConfig init_params;
- init_params.share_group_id = MSG_ROUTING_NONE;
- init_params.stream_id = kStreamId1;
- init_params.stream_priority = kStreamPriority1;
- init_params.attribs = std::vector<int>();
- init_params.active_url = GURL();
- init_params.gpu_preference = gfx::PreferIntegratedGpu;
- channel_manager()->OnMessageReceived(GpuMsg_CreateViewCommandBuffer(
- gfx::GLSurfaceHandle(), kClientId, init_params, kRouteId1));
-
- const IPC::Message* msg =
- sink()->GetUniqueMessageMatching(GpuHostMsg_CommandBufferCreated::ID);
- ASSERT_TRUE(msg);
-
- base::Tuple<CreateCommandBufferResult> result;
- ASSERT_TRUE(GpuHostMsg_CommandBufferCreated::Read(msg, &result));
-
- EXPECT_EQ(CREATE_COMMAND_BUFFER_SUCCEEDED, base::get<0>(result));
-
- sink()->ClearMessages();
-
- GpuCommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId1);
- ASSERT_TRUE(stub);
-
- // Create second context in same share group but different stream.
- int32_t kRouteId2 = 2;
- int32_t kStreamId2 = kStreamId1;
- GpuStreamPriority kStreamPriority2 = GpuStreamPriority::LOW;
-
- init_params.share_group_id = MSG_ROUTING_NONE;
- init_params.stream_id = kStreamId2;
- init_params.stream_priority = kStreamPriority2;
- init_params.attribs = std::vector<int>();
- init_params.active_url = GURL();
- init_params.gpu_preference = gfx::PreferIntegratedGpu;
- channel_manager()->OnMessageReceived(GpuMsg_CreateViewCommandBuffer(
- gfx::GLSurfaceHandle(), kClientId, init_params, kRouteId2));
-
- msg = sink()->GetUniqueMessageMatching(GpuHostMsg_CommandBufferCreated::ID);
- ASSERT_TRUE(msg);
-
- ASSERT_TRUE(GpuHostMsg_CommandBufferCreated::Read(msg, &result));
-
- EXPECT_EQ(CREATE_COMMAND_BUFFER_FAILED, base::get<0>(result));
-
- sink()->ClearMessages();
-
- stub = channel->LookupCommandBuffer(kRouteId2);
- ASSERT_FALSE(stub);
-}
-
-TEST_F(GpuChannelTest, StreamLifetime) {
- int32_t kClientId = 1;
- GpuChannel* channel = CreateChannel(kClientId, false);
- ASSERT_TRUE(channel);
-
- // Create first context.
- int32_t kRouteId1 = 1;
- int32_t kStreamId1 = 1;
- GpuStreamPriority kStreamPriority1 = GpuStreamPriority::NORMAL;
- GPUCreateCommandBufferConfig init_params;
- init_params.share_group_id = MSG_ROUTING_NONE;
- init_params.stream_id = kStreamId1;
- init_params.stream_priority = kStreamPriority1;
- init_params.attribs = std::vector<int>();
- init_params.active_url = GURL();
- init_params.gpu_preference = gfx::PreferIntegratedGpu;
- channel_manager()->OnMessageReceived(GpuMsg_CreateViewCommandBuffer(
- gfx::GLSurfaceHandle(), kClientId, init_params, kRouteId1));
-
- const IPC::Message* msg =
- sink()->GetUniqueMessageMatching(GpuHostMsg_CommandBufferCreated::ID);
- ASSERT_TRUE(msg);
-
- base::Tuple<CreateCommandBufferResult> result;
- ASSERT_TRUE(GpuHostMsg_CommandBufferCreated::Read(msg, &result));
-
- EXPECT_EQ(CREATE_COMMAND_BUFFER_SUCCEEDED, base::get<0>(result));
-
- sink()->ClearMessages();
-
- GpuCommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId1);
- ASSERT_TRUE(stub);
-
- {
- // GpuChannelHost always calls set_unblock(false) on messages sent to the
- // GPU process.
- IPC::Message m = GpuChannelMsg_DestroyCommandBuffer(kRouteId1);
- m.set_unblock(false);
- EXPECT_TRUE(channel->filter()->OnMessageReceived(m));
- task_runner()->RunPendingTasks();
- }
-
- stub = channel->LookupCommandBuffer(kRouteId1);
- ASSERT_FALSE(stub);
-
- // Create second context in same share group but different stream.
- int32_t kRouteId2 = 2;
- int32_t kStreamId2 = 2;
- GpuStreamPriority kStreamPriority2 = GpuStreamPriority::LOW;
-
- init_params.share_group_id = MSG_ROUTING_NONE;
- init_params.stream_id = kStreamId2;
- init_params.stream_priority = kStreamPriority2;
- init_params.attribs = std::vector<int>();
- init_params.active_url = GURL();
- init_params.gpu_preference = gfx::PreferIntegratedGpu;
- channel_manager()->OnMessageReceived(GpuMsg_CreateViewCommandBuffer(
- gfx::GLSurfaceHandle(), kClientId, init_params, kRouteId2));
-
- msg = sink()->GetUniqueMessageMatching(GpuHostMsg_CommandBufferCreated::ID);
- ASSERT_TRUE(msg);
-
- ASSERT_TRUE(GpuHostMsg_CommandBufferCreated::Read(msg, &result));
-
- EXPECT_EQ(CREATE_COMMAND_BUFFER_SUCCEEDED, base::get<0>(result));
-
- sink()->ClearMessages();
-
- stub = channel->LookupCommandBuffer(kRouteId2);
- ASSERT_TRUE(stub);
-}
-
-TEST_F(GpuChannelTest, RealTimeStreamsDisallowed) {
- int32_t kClientId = 1;
- bool allow_real_time_streams = false;
- GpuChannel* channel = CreateChannel(kClientId, allow_real_time_streams);
- ASSERT_TRUE(channel);
-
- // Create first context.
- int32_t kRouteId = 1;
- int32_t kStreamId = 1;
- GpuStreamPriority kStreamPriority = GpuStreamPriority::REAL_TIME;
- GPUCreateCommandBufferConfig init_params;
- init_params.share_group_id = MSG_ROUTING_NONE;
- init_params.stream_id = kStreamId;
- init_params.stream_priority = kStreamPriority;
- init_params.attribs = std::vector<int>();
- init_params.active_url = GURL();
- init_params.gpu_preference = gfx::PreferIntegratedGpu;
- channel_manager()->OnMessageReceived(GpuMsg_CreateViewCommandBuffer(
- gfx::GLSurfaceHandle(), kClientId, init_params, kRouteId));
-
- const IPC::Message* msg =
- sink()->GetUniqueMessageMatching(GpuHostMsg_CommandBufferCreated::ID);
- ASSERT_TRUE(msg);
-
- base::Tuple<CreateCommandBufferResult> result;
- ASSERT_TRUE(GpuHostMsg_CommandBufferCreated::Read(msg, &result));
-
- EXPECT_EQ(CREATE_COMMAND_BUFFER_FAILED, base::get<0>(result));
-
- sink()->ClearMessages();
-
- GpuCommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId);
- ASSERT_FALSE(stub);
-}
-
-TEST_F(GpuChannelTest, RealTimeStreamsAllowed) {
- int32_t kClientId = 1;
- bool allow_real_time_streams = true;
- GpuChannel* channel = CreateChannel(kClientId, allow_real_time_streams);
- ASSERT_TRUE(channel);
-
- // Create first context.
- int32_t kRouteId = 1;
- int32_t kStreamId = 1;
- GpuStreamPriority kStreamPriority = GpuStreamPriority::REAL_TIME;
- GPUCreateCommandBufferConfig init_params;
- init_params.share_group_id = MSG_ROUTING_NONE;
- init_params.stream_id = kStreamId;
- init_params.stream_priority = kStreamPriority;
- init_params.attribs = std::vector<int>();
- init_params.active_url = GURL();
- init_params.gpu_preference = gfx::PreferIntegratedGpu;
- channel_manager()->OnMessageReceived(GpuMsg_CreateViewCommandBuffer(
- gfx::GLSurfaceHandle(), kClientId, init_params, kRouteId));
-
- const IPC::Message* msg =
- sink()->GetUniqueMessageMatching(GpuHostMsg_CommandBufferCreated::ID);
- ASSERT_TRUE(msg);
-
- base::Tuple<CreateCommandBufferResult> result;
- ASSERT_TRUE(GpuHostMsg_CommandBufferCreated::Read(msg, &result));
-
- EXPECT_EQ(CREATE_COMMAND_BUFFER_SUCCEEDED, base::get<0>(result));
-
- sink()->ClearMessages();
-
- GpuCommandBufferStub* stub = channel->LookupCommandBuffer(kRouteId);
- ASSERT_TRUE(stub);
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/gpu_command_buffer_stub.cc b/chromium/content/common/gpu/gpu_command_buffer_stub.cc
deleted file mode 100644
index 58bfa6a4fb9..00000000000
--- a/chromium/content/common/gpu/gpu_command_buffer_stub.cc
+++ /dev/null
@@ -1,1269 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/gpu_command_buffer_stub.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/command_line.h"
-#include "base/hash.h"
-#include "base/json/json_writer.h"
-#include "base/macros.h"
-#include "base/memory/shared_memory.h"
-#include "base/time/time.h"
-#include "base/trace_event/trace_event.h"
-#include "build/build_config.h"
-#include "content/common/gpu/gpu_channel.h"
-#include "content/common/gpu/gpu_channel_manager.h"
-#include "content/common/gpu/gpu_memory_manager.h"
-#include "content/common/gpu/gpu_memory_tracking.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "content/common/gpu/gpu_watchdog.h"
-#include "content/common/gpu/image_transport_surface.h"
-#include "content/common/gpu/media/gpu_video_decode_accelerator.h"
-#include "content/common/gpu/media/gpu_video_encode_accelerator.h"
-#include "content/public/common/content_client.h"
-#include "content/public/common/content_switches.h"
-#include "gpu/command_buffer/common/constants.h"
-#include "gpu/command_buffer/common/mailbox.h"
-#include "gpu/command_buffer/common/sync_token.h"
-#include "gpu/command_buffer/service/gl_context_virtual.h"
-#include "gpu/command_buffer/service/gl_state_restorer_impl.h"
-#include "gpu/command_buffer/service/image_factory.h"
-#include "gpu/command_buffer/service/image_manager.h"
-#include "gpu/command_buffer/service/logger.h"
-#include "gpu/command_buffer/service/mailbox_manager.h"
-#include "gpu/command_buffer/service/memory_tracking.h"
-#include "gpu/command_buffer/service/query_manager.h"
-#include "gpu/command_buffer/service/sync_point_manager.h"
-#include "gpu/command_buffer/service/transfer_buffer_manager.h"
-#include "gpu/command_buffer/service/valuebuffer_manager.h"
-#include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_switches.h"
-
-#if defined(OS_WIN)
-#include "base/win/win_util.h"
-#include "content/public/common/sandbox_init.h"
-#endif
-
-#if defined(OS_ANDROID)
-#include "content/common/gpu/stream_texture_android.h"
-#endif
-
-namespace content {
-struct WaitForCommandState {
- WaitForCommandState(int32_t start, int32_t end, IPC::Message* reply)
- : start(start), end(end), reply(reply) {}
-
- int32_t start;
- int32_t end;
- scoped_ptr<IPC::Message> reply;
-};
-
-namespace {
-
-// The GpuCommandBufferMemoryTracker class provides a bridge between the
-// ContextGroup's memory type managers and the GpuMemoryManager class.
-class GpuCommandBufferMemoryTracker : public gpu::gles2::MemoryTracker {
- public:
- explicit GpuCommandBufferMemoryTracker(GpuChannel* channel,
- uint64_t share_group_tracing_guid)
- : tracking_group_(
- channel->gpu_channel_manager()
- ->gpu_memory_manager()
- ->CreateTrackingGroup(channel->GetClientPID(), this)),
- client_tracing_id_(channel->client_tracing_id()),
- client_id_(channel->client_id()),
- share_group_tracing_guid_(share_group_tracing_guid) {}
-
- void TrackMemoryAllocatedChange(
- size_t old_size, size_t new_size) override {
- tracking_group_->TrackMemoryAllocatedChange(
- old_size, new_size);
- }
-
- bool EnsureGPUMemoryAvailable(size_t size_needed) override {
- return tracking_group_->EnsureGPUMemoryAvailable(size_needed);
- };
-
- uint64_t ClientTracingId() const override { return client_tracing_id_; }
- int ClientId() const override { return client_id_; }
- uint64_t ShareGroupTracingGUID() const override {
- return share_group_tracing_guid_;
- }
-
- private:
- ~GpuCommandBufferMemoryTracker() override {}
- scoped_ptr<GpuMemoryTrackingGroup> tracking_group_;
- const uint64_t client_tracing_id_;
- const int client_id_;
- const uint64_t share_group_tracing_guid_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuCommandBufferMemoryTracker);
-};
-
-// FastSetActiveURL will shortcut the expensive call to SetActiveURL when the
-// url_hash matches.
-void FastSetActiveURL(const GURL& url, size_t url_hash) {
- // Leave the previously set URL in the empty case -- empty URLs are given by
- // BlinkPlatformImpl::createOffscreenGraphicsContext3D. Hopefully the
- // onscreen context URL was set previously and will show up even when a crash
- // occurs during offscreen command processing.
- if (url.is_empty())
- return;
- static size_t g_last_url_hash = 0;
- if (url_hash != g_last_url_hash) {
- g_last_url_hash = url_hash;
- GetContentClient()->SetActiveURL(url);
- }
-}
-
-// The first time polling a fence, delay some extra time to allow other
-// stubs to process some work, or else the timing of the fences could
-// allow a pattern of alternating fast and slow frames to occur.
-const int64_t kHandleMoreWorkPeriodMs = 2;
-const int64_t kHandleMoreWorkPeriodBusyMs = 1;
-
-// Prevents idle work from being starved.
-const int64_t kMaxTimeSinceIdleMs = 10;
-
-class DevToolsChannelData : public base::trace_event::ConvertableToTraceFormat {
- public:
- static scoped_refptr<base::trace_event::ConvertableToTraceFormat>
- CreateForChannel(GpuChannel* channel);
-
- void AppendAsTraceFormat(std::string* out) const override {
- std::string tmp;
- base::JSONWriter::Write(*value_, &tmp);
- *out += tmp;
- }
-
- private:
- explicit DevToolsChannelData(base::Value* value) : value_(value) {}
- ~DevToolsChannelData() override {}
- scoped_ptr<base::Value> value_;
- DISALLOW_COPY_AND_ASSIGN(DevToolsChannelData);
-};
-
-scoped_refptr<base::trace_event::ConvertableToTraceFormat>
-DevToolsChannelData::CreateForChannel(GpuChannel* channel) {
- scoped_ptr<base::DictionaryValue> res(new base::DictionaryValue);
- res->SetInteger("renderer_pid", channel->GetClientPID());
- res->SetDouble("used_bytes", channel->GetMemoryUsage());
- return new DevToolsChannelData(res.release());
-}
-
-void RunOnThread(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- const base::Closure& callback) {
- if (task_runner->BelongsToCurrentThread()) {
- callback.Run();
- } else {
- task_runner->PostTask(FROM_HERE, callback);
- }
-}
-
-uint64_t GetCommandBufferID(int channel_id, int32_t route_id) {
- return (static_cast<uint64_t>(channel_id) << 32) | route_id;
-}
-
-} // namespace
-
-GpuCommandBufferStub::GpuCommandBufferStub(
- GpuChannel* channel,
- gpu::SyncPointManager* sync_point_manager,
- base::SingleThreadTaskRunner* task_runner,
- GpuCommandBufferStub* share_group,
- const gfx::GLSurfaceHandle& handle,
- gpu::gles2::MailboxManager* mailbox_manager,
- gpu::PreemptionFlag* preempt_by_flag,
- gpu::gles2::SubscriptionRefSet* subscription_ref_set,
- gpu::ValueStateMap* pending_valuebuffer_state,
- const gfx::Size& size,
- const gpu::gles2::DisallowedFeatures& disallowed_features,
- const std::vector<int32_t>& attribs,
- gfx::GpuPreference gpu_preference,
- int32_t stream_id,
- int32_t route_id,
- bool offscreen,
- GpuWatchdog* watchdog,
- const GURL& active_url)
- : channel_(channel),
- sync_point_manager_(sync_point_manager),
- task_runner_(task_runner),
- initialized_(false),
- handle_(handle),
- initial_size_(size),
- disallowed_features_(disallowed_features),
- requested_attribs_(attribs),
- gpu_preference_(gpu_preference),
- use_virtualized_gl_context_(false),
- command_buffer_id_(GetCommandBufferID(channel->client_id(), route_id)),
- stream_id_(stream_id),
- route_id_(route_id),
- offscreen_(offscreen),
- last_flush_count_(0),
- watchdog_(watchdog),
- waiting_for_sync_point_(false),
- previous_processed_num_(0),
- preemption_flag_(preempt_by_flag),
- active_url_(active_url) {
- active_url_hash_ = base::Hash(active_url.possibly_invalid_spec());
- FastSetActiveURL(active_url_, active_url_hash_);
-
- gpu::gles2::ContextCreationAttribHelper attrib_parser;
- attrib_parser.Parse(requested_attribs_);
-
- if (share_group) {
- context_group_ = share_group->context_group_;
- DCHECK(context_group_->bind_generates_resource() ==
- attrib_parser.bind_generates_resource);
- } else {
- context_group_ = new gpu::gles2::ContextGroup(
- mailbox_manager,
- new GpuCommandBufferMemoryTracker(channel, command_buffer_id_),
- channel_->gpu_channel_manager()->shader_translator_cache(),
- channel_->gpu_channel_manager()->framebuffer_completeness_cache(), NULL,
- subscription_ref_set, pending_valuebuffer_state,
- attrib_parser.bind_generates_resource);
- }
-
-// Virtualize PreferIntegratedGpu contexts by default on OS X to prevent
-// performance regressions when enabling FCM.
-// http://crbug.com/180463
-#if defined(OS_MACOSX)
- if (gpu_preference_ == gfx::PreferIntegratedGpu)
- use_virtualized_gl_context_ = true;
-#endif
-
- use_virtualized_gl_context_ |=
- context_group_->feature_info()->workarounds().use_virtualized_gl_contexts;
-
- // MailboxManagerSync synchronization correctness currently depends on having
- // only a single context. See crbug.com/510243 for details.
- use_virtualized_gl_context_ |= mailbox_manager->UsesSync();
-
- if (offscreen && initial_size_.IsEmpty()) {
- // If we're an offscreen surface with zero width and/or height, set to a
- // non-zero size so that we have a complete framebuffer for operations like
- // glClear.
- initial_size_ = gfx::Size(1, 1);
- }
-}
-
-GpuCommandBufferStub::~GpuCommandBufferStub() {
- Destroy();
-}
-
-GpuMemoryManager* GpuCommandBufferStub::GetMemoryManager() const {
- return channel()->gpu_channel_manager()->gpu_memory_manager();
-}
-
-bool GpuCommandBufferStub::OnMessageReceived(const IPC::Message& message) {
- TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"),
- "GPUTask",
- "data",
- DevToolsChannelData::CreateForChannel(channel()));
- FastSetActiveURL(active_url_, active_url_hash_);
-
- bool have_context = false;
- // Ensure the appropriate GL context is current before handling any IPC
- // messages directed at the command buffer. This ensures that the message
- // handler can assume that the context is current (not necessary for
- // RetireSyncPoint or WaitSyncPoint).
- if (decoder_.get() &&
- message.type() != GpuCommandBufferMsg_SetGetBuffer::ID &&
- message.type() != GpuCommandBufferMsg_WaitForTokenInRange::ID &&
- message.type() != GpuCommandBufferMsg_WaitForGetOffsetInRange::ID &&
- message.type() != GpuCommandBufferMsg_RegisterTransferBuffer::ID &&
- message.type() != GpuCommandBufferMsg_DestroyTransferBuffer::ID &&
- message.type() != GpuCommandBufferMsg_RetireSyncPoint::ID &&
- message.type() != GpuCommandBufferMsg_SignalSyncPoint::ID) {
- if (!MakeCurrent())
- return false;
- have_context = true;
- }
-
- // Always use IPC_MESSAGE_HANDLER_DELAY_REPLY for synchronous message handlers
- // here. This is so the reply can be delayed if the scheduler is unscheduled.
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(GpuCommandBufferStub, message)
- IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_Initialize,
- OnInitialize);
- IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_SetGetBuffer,
- OnSetGetBuffer);
- IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_ProduceFrontBuffer,
- OnProduceFrontBuffer);
- IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_WaitForTokenInRange,
- OnWaitForTokenInRange);
- IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_WaitForGetOffsetInRange,
- OnWaitForGetOffsetInRange);
- IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_AsyncFlush, OnAsyncFlush);
- IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_RegisterTransferBuffer,
- OnRegisterTransferBuffer);
- IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_DestroyTransferBuffer,
- OnDestroyTransferBuffer);
- IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_CreateVideoDecoder,
- OnCreateVideoDecoder)
- IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuCommandBufferMsg_CreateVideoEncoder,
- OnCreateVideoEncoder)
- IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_RetireSyncPoint,
- OnRetireSyncPoint)
- IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SignalSyncPoint,
- OnSignalSyncPoint)
- IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SignalSyncToken,
- OnSignalSyncToken)
- IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_SignalQuery,
- OnSignalQuery)
- IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_CreateImage, OnCreateImage);
- IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_DestroyImage, OnDestroyImage);
- IPC_MESSAGE_HANDLER(GpuCommandBufferMsg_CreateStreamTexture,
- OnCreateStreamTexture)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
-
- CheckCompleteWaits();
-
- // Ensure that any delayed work that was created will be handled.
- if (have_context) {
- if (scheduler_)
- scheduler_->ProcessPendingQueries();
- ScheduleDelayedWork(
- base::TimeDelta::FromMilliseconds(kHandleMoreWorkPeriodMs));
- }
-
- DCHECK(handled);
- return handled;
-}
-
-bool GpuCommandBufferStub::Send(IPC::Message* message) {
- return channel_->Send(message);
-}
-
-bool GpuCommandBufferStub::IsScheduled() {
- return (!scheduler_.get() || scheduler_->scheduled());
-}
-
-void GpuCommandBufferStub::PollWork() {
- // Post another delayed task if we have not yet reached the time at which
- // we should process delayed work.
- base::TimeTicks current_time = base::TimeTicks::Now();
- DCHECK(!process_delayed_work_time_.is_null());
- if (process_delayed_work_time_ > current_time) {
- task_runner_->PostDelayedTask(
- FROM_HERE, base::Bind(&GpuCommandBufferStub::PollWork, AsWeakPtr()),
- process_delayed_work_time_ - current_time);
- return;
- }
- process_delayed_work_time_ = base::TimeTicks();
-
- PerformWork();
-}
-
-void GpuCommandBufferStub::PerformWork() {
- TRACE_EVENT0("gpu", "GpuCommandBufferStub::PerformWork");
-
- FastSetActiveURL(active_url_, active_url_hash_);
- if (decoder_.get() && !MakeCurrent())
- return;
-
- if (scheduler_) {
- uint32_t current_unprocessed_num =
- channel()->gpu_channel_manager()->GetUnprocessedOrderNum();
- // We're idle when no messages were processed or scheduled.
- bool is_idle = (previous_processed_num_ == current_unprocessed_num);
- if (!is_idle && !last_idle_time_.is_null()) {
- base::TimeDelta time_since_idle =
- base::TimeTicks::Now() - last_idle_time_;
- base::TimeDelta max_time_since_idle =
- base::TimeDelta::FromMilliseconds(kMaxTimeSinceIdleMs);
-
- // Force idle when it's been too long since last time we were idle.
- if (time_since_idle > max_time_since_idle)
- is_idle = true;
- }
-
- if (is_idle) {
- last_idle_time_ = base::TimeTicks::Now();
- scheduler_->PerformIdleWork();
- }
-
- scheduler_->ProcessPendingQueries();
- }
-
- ScheduleDelayedWork(
- base::TimeDelta::FromMilliseconds(kHandleMoreWorkPeriodBusyMs));
-}
-
-bool GpuCommandBufferStub::HasUnprocessedCommands() {
- if (command_buffer_) {
- gpu::CommandBuffer::State state = command_buffer_->GetLastState();
- return command_buffer_->GetPutOffset() != state.get_offset &&
- !gpu::error::IsError(state.error);
- }
- return false;
-}
-
-void GpuCommandBufferStub::ScheduleDelayedWork(base::TimeDelta delay) {
- bool has_more_work = scheduler_.get() && (scheduler_->HasPendingQueries() ||
- scheduler_->HasMoreIdleWork());
- if (!has_more_work) {
- last_idle_time_ = base::TimeTicks();
- return;
- }
-
- base::TimeTicks current_time = base::TimeTicks::Now();
- // |process_delayed_work_time_| is set if processing of delayed work is
- // already scheduled. Just update the time if already scheduled.
- if (!process_delayed_work_time_.is_null()) {
- process_delayed_work_time_ = current_time + delay;
- return;
- }
-
- // Idle when no messages are processed between now and when
- // PollWork is called.
- previous_processed_num_ =
- channel()->gpu_channel_manager()->GetProcessedOrderNum();
- if (last_idle_time_.is_null())
- last_idle_time_ = current_time;
-
- // IsScheduled() returns true after passing all unschedule fences
- // and this is when we can start performing idle work. Idle work
- // is done synchronously so we can set delay to 0 and instead poll
- // for more work at the rate idle work is performed. This also ensures
- // that idle work is done as efficiently as possible without any
- // unnecessary delays.
- if (scheduler_.get() && scheduler_->scheduled() &&
- scheduler_->HasMoreIdleWork()) {
- delay = base::TimeDelta();
- }
-
- process_delayed_work_time_ = current_time + delay;
- task_runner_->PostDelayedTask(
- FROM_HERE, base::Bind(&GpuCommandBufferStub::PollWork, AsWeakPtr()),
- delay);
-}
-
-bool GpuCommandBufferStub::MakeCurrent() {
- if (decoder_->MakeCurrent())
- return true;
- DLOG(ERROR) << "Context lost because MakeCurrent failed.";
- command_buffer_->SetContextLostReason(decoder_->GetContextLostReason());
- command_buffer_->SetParseError(gpu::error::kLostContext);
- CheckContextLost();
- return false;
-}
-
-void GpuCommandBufferStub::Destroy() {
- if (wait_for_token_) {
- Send(wait_for_token_->reply.release());
- wait_for_token_.reset();
- }
- if (wait_for_get_offset_) {
- Send(wait_for_get_offset_->reply.release());
- wait_for_get_offset_.reset();
- }
-
- if (initialized_) {
- GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager();
- if (handle_.is_null() && !active_url_.is_empty()) {
- gpu_channel_manager->Send(
- new GpuHostMsg_DidDestroyOffscreenContext(active_url_));
- }
- }
-
- while (!sync_points_.empty())
- OnRetireSyncPoint(sync_points_.front());
-
- if (decoder_)
- decoder_->set_engine(NULL);
-
- // The scheduler has raw references to the decoder and the command buffer so
- // destroy it before those.
- scheduler_.reset();
-
- sync_point_client_.reset();
-
- bool have_context = false;
- if (decoder_ && decoder_->GetGLContext()) {
- // Try to make the context current regardless of whether it was lost, so we
- // don't leak resources.
- have_context = decoder_->GetGLContext()->MakeCurrent(surface_.get());
- }
- FOR_EACH_OBSERVER(DestructionObserver,
- destruction_observers_,
- OnWillDestroyStub());
-
- if (decoder_) {
- decoder_->Destroy(have_context);
- decoder_.reset();
- }
-
- command_buffer_.reset();
-
- // Remove this after crbug.com/248395 is sorted out.
- surface_ = NULL;
-}
-
-void GpuCommandBufferStub::OnInitializeFailed(IPC::Message* reply_message) {
- Destroy();
- GpuCommandBufferMsg_Initialize::WriteReplyParams(
- reply_message, false, gpu::Capabilities());
- Send(reply_message);
-}
-
-void GpuCommandBufferStub::OnInitialize(
- base::SharedMemoryHandle shared_state_handle,
- IPC::Message* reply_message) {
- TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnInitialize");
- DCHECK(!command_buffer_.get());
-
- scoped_ptr<base::SharedMemory> shared_state_shm(
- new base::SharedMemory(shared_state_handle, false));
-
- command_buffer_.reset(new gpu::CommandBufferService(
- context_group_->transfer_buffer_manager()));
-
- bool result = command_buffer_->Initialize();
- DCHECK(result);
-
- GpuChannelManager* manager = channel_->gpu_channel_manager();
- DCHECK(manager);
-
- decoder_.reset(::gpu::gles2::GLES2Decoder::Create(context_group_.get()));
- scheduler_.reset(new gpu::GpuScheduler(command_buffer_.get(),
- decoder_.get(),
- decoder_.get()));
- sync_point_client_ = sync_point_manager_->CreateSyncPointClient(
- channel_->GetSyncPointOrderData(), gpu::CommandBufferNamespace::GPU_IO,
- command_buffer_id_);
-
- if (preemption_flag_.get())
- scheduler_->SetPreemptByFlag(preemption_flag_);
-
- decoder_->set_engine(scheduler_.get());
-
- if (!handle_.is_null()) {
- surface_ = ImageTransportSurface::CreateSurface(
- channel_->gpu_channel_manager(),
- this,
- handle_);
- } else {
- surface_ = manager->GetDefaultOffscreenSurface();
- }
-
- if (!surface_.get()) {
- DLOG(ERROR) << "Failed to create surface.";
- OnInitializeFailed(reply_message);
- return;
- }
-
- scoped_refptr<gfx::GLContext> context;
- if (use_virtualized_gl_context_ && channel_->share_group()) {
- context = channel_->share_group()->GetSharedContext();
- if (!context.get()) {
- context = gfx::GLContext::CreateGLContext(
- channel_->share_group(),
- channel_->gpu_channel_manager()->GetDefaultOffscreenSurface(),
- gpu_preference_);
- if (!context.get()) {
- DLOG(ERROR) << "Failed to create shared context for virtualization.";
- OnInitializeFailed(reply_message);
- return;
- }
- channel_->share_group()->SetSharedContext(context.get());
- }
- // This should be a non-virtual GL context.
- DCHECK(context->GetHandle());
- context = new gpu::GLContextVirtual(
- channel_->share_group(), context.get(), decoder_->AsWeakPtr());
- if (!context->Initialize(surface_.get(), gpu_preference_)) {
- // TODO(sievers): The real context created above for the default
- // offscreen surface might not be compatible with this surface.
- // Need to adjust at least GLX to be able to create the initial context
- // with a config that is compatible with onscreen and offscreen surfaces.
- context = NULL;
-
- DLOG(ERROR) << "Failed to initialize virtual GL context.";
- OnInitializeFailed(reply_message);
- return;
- }
- }
- if (!context.get()) {
- context = gfx::GLContext::CreateGLContext(
- channel_->share_group(), surface_.get(), gpu_preference_);
- }
- if (!context.get()) {
- DLOG(ERROR) << "Failed to create context.";
- OnInitializeFailed(reply_message);
- return;
- }
-
- if (!context->MakeCurrent(surface_.get())) {
- LOG(ERROR) << "Failed to make context current.";
- OnInitializeFailed(reply_message);
- return;
- }
-
- if (!context->GetGLStateRestorer()) {
- context->SetGLStateRestorer(
- new gpu::GLStateRestorerImpl(decoder_->AsWeakPtr()));
- }
-
- if (!context_group_->has_program_cache() &&
- !context_group_->feature_info()->workarounds().disable_program_cache) {
- context_group_->set_program_cache(
- channel_->gpu_channel_manager()->program_cache());
- }
-
- // Initialize the decoder with either the view or pbuffer GLContext.
- if (!decoder_->Initialize(surface_, context, offscreen_, initial_size_,
- disallowed_features_, requested_attribs_)) {
- DLOG(ERROR) << "Failed to initialize decoder.";
- OnInitializeFailed(reply_message);
- return;
- }
-
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableGPUServiceLogging)) {
- decoder_->set_log_commands(true);
- }
-
- decoder_->GetLogger()->SetMsgCallback(
- base::Bind(&GpuCommandBufferStub::SendConsoleMessage,
- base::Unretained(this)));
- decoder_->SetShaderCacheCallback(
- base::Bind(&GpuCommandBufferStub::SendCachedShader,
- base::Unretained(this)));
- decoder_->SetWaitSyncPointCallback(
- base::Bind(&GpuCommandBufferStub::OnWaitSyncPoint,
- base::Unretained(this)));
- decoder_->SetFenceSyncReleaseCallback(base::Bind(
- &GpuCommandBufferStub::OnFenceSyncRelease, base::Unretained(this)));
- decoder_->SetWaitFenceSyncCallback(base::Bind(
- &GpuCommandBufferStub::OnWaitFenceSync, base::Unretained(this)));
-
- command_buffer_->SetPutOffsetChangeCallback(
- base::Bind(&GpuCommandBufferStub::PutChanged, base::Unretained(this)));
- command_buffer_->SetGetBufferChangeCallback(
- base::Bind(&gpu::GpuScheduler::SetGetBuffer,
- base::Unretained(scheduler_.get())));
- command_buffer_->SetParseErrorCallback(
- base::Bind(&GpuCommandBufferStub::OnParseError, base::Unretained(this)));
- scheduler_->SetSchedulingChangedCallback(base::Bind(
- &GpuCommandBufferStub::OnSchedulingChanged, base::Unretained(this)));
-
- if (watchdog_) {
- scheduler_->SetCommandProcessedCallback(
- base::Bind(&GpuCommandBufferStub::OnCommandProcessed,
- base::Unretained(this)));
- }
-
- const size_t kSharedStateSize = sizeof(gpu::CommandBufferSharedState);
- if (!shared_state_shm->Map(kSharedStateSize)) {
- DLOG(ERROR) << "Failed to map shared state buffer.";
- OnInitializeFailed(reply_message);
- return;
- }
- command_buffer_->SetSharedStateBuffer(gpu::MakeBackingFromSharedMemory(
- std::move(shared_state_shm), kSharedStateSize));
-
- gpu::Capabilities capabilities = decoder_->GetCapabilities();
- capabilities.future_sync_points = channel_->allow_future_sync_points();
-
- GpuCommandBufferMsg_Initialize::WriteReplyParams(
- reply_message, true, capabilities);
- Send(reply_message);
-
- if (handle_.is_null() && !active_url_.is_empty()) {
- manager->Send(new GpuHostMsg_DidCreateOffscreenContext(
- active_url_));
- }
-
- initialized_ = true;
-}
-
-void GpuCommandBufferStub::OnCreateStreamTexture(uint32_t texture_id,
- int32_t stream_id,
- bool* succeeded) {
-#if defined(OS_ANDROID)
- *succeeded = StreamTexture::Create(this, texture_id, stream_id);
-#else
- *succeeded = false;
-#endif
-}
-
-void GpuCommandBufferStub::SetLatencyInfoCallback(
- const LatencyInfoCallback& callback) {
- latency_info_callback_ = callback;
-}
-
-int32_t GpuCommandBufferStub::GetRequestedAttribute(int attr) const {
- // The command buffer is pairs of enum, value
- // search for the requested attribute, return the value.
- for (std::vector<int32_t>::const_iterator it = requested_attribs_.begin();
- it != requested_attribs_.end(); ++it) {
- if (*it++ == attr) {
- return *it;
- }
- }
- return -1;
-}
-
-void GpuCommandBufferStub::OnSetGetBuffer(int32_t shm_id,
- IPC::Message* reply_message) {
- TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnSetGetBuffer");
- if (command_buffer_)
- command_buffer_->SetGetBuffer(shm_id);
- Send(reply_message);
-}
-
-void GpuCommandBufferStub::OnProduceFrontBuffer(const gpu::Mailbox& mailbox) {
- TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnProduceFrontBuffer");
- if (!decoder_) {
- LOG(ERROR) << "Can't produce front buffer before initialization.";
- return;
- }
-
- decoder_->ProduceFrontBuffer(mailbox);
-}
-
-void GpuCommandBufferStub::OnParseError() {
- TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnParseError");
- DCHECK(command_buffer_.get());
- gpu::CommandBuffer::State state = command_buffer_->GetLastState();
- IPC::Message* msg = new GpuCommandBufferMsg_Destroyed(
- route_id_, state.context_lost_reason, state.error);
- msg->set_unblock(true);
- Send(msg);
-
- // Tell the browser about this context loss as well, so it can
- // determine whether client APIs like WebGL need to be immediately
- // blocked from automatically running.
- GpuChannelManager* gpu_channel_manager = channel_->gpu_channel_manager();
- gpu_channel_manager->Send(new GpuHostMsg_DidLoseContext(
- handle_.is_null(), state.context_lost_reason, active_url_));
-
- CheckContextLost();
-}
-
-void GpuCommandBufferStub::OnSchedulingChanged(bool scheduled) {
- TRACE_EVENT1("gpu", "GpuCommandBufferStub::OnSchedulingChanged", "scheduled",
- scheduled);
- channel_->OnStubSchedulingChanged(this, scheduled);
-}
-
-void GpuCommandBufferStub::OnWaitForTokenInRange(int32_t start,
- int32_t end,
- IPC::Message* reply_message) {
- TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnWaitForTokenInRange");
- DCHECK(command_buffer_.get());
- CheckContextLost();
- if (wait_for_token_)
- LOG(ERROR) << "Got WaitForToken command while currently waiting for token.";
- wait_for_token_ =
- make_scoped_ptr(new WaitForCommandState(start, end, reply_message));
- CheckCompleteWaits();
-}
-
-void GpuCommandBufferStub::OnWaitForGetOffsetInRange(
- int32_t start,
- int32_t end,
- IPC::Message* reply_message) {
- TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnWaitForGetOffsetInRange");
- DCHECK(command_buffer_.get());
- CheckContextLost();
- if (wait_for_get_offset_) {
- LOG(ERROR)
- << "Got WaitForGetOffset command while currently waiting for offset.";
- }
- wait_for_get_offset_ =
- make_scoped_ptr(new WaitForCommandState(start, end, reply_message));
- CheckCompleteWaits();
-}
-
-void GpuCommandBufferStub::CheckCompleteWaits() {
- if (wait_for_token_ || wait_for_get_offset_) {
- gpu::CommandBuffer::State state = command_buffer_->GetLastState();
- if (wait_for_token_ &&
- (gpu::CommandBuffer::InRange(
- wait_for_token_->start, wait_for_token_->end, state.token) ||
- state.error != gpu::error::kNoError)) {
- ReportState();
- GpuCommandBufferMsg_WaitForTokenInRange::WriteReplyParams(
- wait_for_token_->reply.get(), state);
- Send(wait_for_token_->reply.release());
- wait_for_token_.reset();
- }
- if (wait_for_get_offset_ &&
- (gpu::CommandBuffer::InRange(wait_for_get_offset_->start,
- wait_for_get_offset_->end,
- state.get_offset) ||
- state.error != gpu::error::kNoError)) {
- ReportState();
- GpuCommandBufferMsg_WaitForGetOffsetInRange::WriteReplyParams(
- wait_for_get_offset_->reply.get(), state);
- Send(wait_for_get_offset_->reply.release());
- wait_for_get_offset_.reset();
- }
- }
-}
-
-void GpuCommandBufferStub::OnAsyncFlush(
- int32_t put_offset,
- uint32_t flush_count,
- const std::vector<ui::LatencyInfo>& latency_info) {
- TRACE_EVENT1(
- "gpu", "GpuCommandBufferStub::OnAsyncFlush", "put_offset", put_offset);
- DCHECK(command_buffer_);
-
- // We received this message out-of-order. This should not happen but is here
- // to catch regressions. Ignore the message.
- DVLOG_IF(0, flush_count - last_flush_count_ >= 0x8000000U)
- << "Received a Flush message out-of-order";
-
- if (flush_count > last_flush_count_ &&
- ui::LatencyInfo::Verify(latency_info,
- "GpuCommandBufferStub::OnAsyncFlush") &&
- !latency_info_callback_.is_null()) {
- latency_info_callback_.Run(latency_info);
- }
-
- last_flush_count_ = flush_count;
- gpu::CommandBuffer::State pre_state = command_buffer_->GetLastState();
- command_buffer_->Flush(put_offset);
- gpu::CommandBuffer::State post_state = command_buffer_->GetLastState();
-
- if (pre_state.get_offset != post_state.get_offset)
- ReportState();
-
-#if defined(OS_ANDROID)
- GpuChannelManager* manager = channel_->gpu_channel_manager();
- manager->DidAccessGpu();
-#endif
-}
-
-void GpuCommandBufferStub::OnRegisterTransferBuffer(
- int32_t id,
- base::SharedMemoryHandle transfer_buffer,
- uint32_t size) {
- TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnRegisterTransferBuffer");
-
- // Take ownership of the memory and map it into this process.
- // This validates the size.
- scoped_ptr<base::SharedMemory> shared_memory(
- new base::SharedMemory(transfer_buffer, false));
- if (!shared_memory->Map(size)) {
- DVLOG(0) << "Failed to map shared memory.";
- return;
- }
-
- if (command_buffer_) {
- command_buffer_->RegisterTransferBuffer(
- id, gpu::MakeBackingFromSharedMemory(std::move(shared_memory), size));
- }
-}
-
-void GpuCommandBufferStub::OnDestroyTransferBuffer(int32_t id) {
- TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnDestroyTransferBuffer");
-
- if (command_buffer_)
- command_buffer_->DestroyTransferBuffer(id);
-}
-
-void GpuCommandBufferStub::OnCommandProcessed() {
- if (watchdog_)
- watchdog_->CheckArmed();
-}
-
-void GpuCommandBufferStub::ReportState() { command_buffer_->UpdateState(); }
-
-void GpuCommandBufferStub::PutChanged() {
- FastSetActiveURL(active_url_, active_url_hash_);
- scheduler_->PutChanged();
-}
-
-void GpuCommandBufferStub::OnCreateVideoDecoder(
- const media::VideoDecodeAccelerator::Config& config,
- int32_t decoder_route_id,
- IPC::Message* reply_message) {
- TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnCreateVideoDecoder");
- GpuVideoDecodeAccelerator* decoder = new GpuVideoDecodeAccelerator(
- decoder_route_id, this, channel_->io_task_runner());
- decoder->Initialize(config, reply_message);
- // decoder is registered as a DestructionObserver of this stub and will
- // self-delete during destruction of this stub.
-}
-
-void GpuCommandBufferStub::OnCreateVideoEncoder(
- media::VideoPixelFormat input_format,
- const gfx::Size& input_visible_size,
- media::VideoCodecProfile output_profile,
- uint32_t initial_bitrate,
- int32_t encoder_route_id,
- IPC::Message* reply_message) {
- TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnCreateVideoEncoder");
- GpuVideoEncodeAccelerator* encoder =
- new GpuVideoEncodeAccelerator(encoder_route_id, this);
- encoder->Initialize(input_format,
- input_visible_size,
- output_profile,
- initial_bitrate,
- reply_message);
- // encoder is registered as a DestructionObserver of this stub and will
- // self-delete during destruction of this stub.
-}
-
-void GpuCommandBufferStub::InsertSyncPoint(uint32_t sync_point, bool retire) {
- sync_points_.push_back(sync_point);
- if (retire) {
- OnMessageReceived(
- GpuCommandBufferMsg_RetireSyncPoint(route_id_, sync_point));
- }
-}
-
-void GpuCommandBufferStub::OnRetireSyncPoint(uint32_t sync_point) {
- DCHECK(!sync_points_.empty() && sync_points_.front() == sync_point);
- sync_points_.pop_front();
-
- gpu::gles2::MailboxManager* mailbox_manager =
- context_group_->mailbox_manager();
- if (mailbox_manager->UsesSync() && MakeCurrent()) {
- // Old sync points are global and do not have a command buffer ID,
- // We can simply use the global sync point number as the release count with
- // 0 for the command buffer ID (under normal circumstances 0 is invalid so
- // will not be used) until the old sync points are replaced.
- gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO, 0, 0,
- sync_point);
- mailbox_manager->PushTextureUpdates(sync_token);
- }
-
- sync_point_manager_->RetireSyncPoint(sync_point);
-}
-
-bool GpuCommandBufferStub::OnWaitSyncPoint(uint32_t sync_point) {
- DCHECK(!waiting_for_sync_point_);
- DCHECK(scheduler_->scheduled());
- if (!sync_point)
- return true;
- if (sync_point_manager_->IsSyncPointRetired(sync_point)) {
- // Old sync points are global and do not have a command buffer ID,
- // We can simply use the global sync point number as the release count with
- // 0 for the command buffer ID (under normal circumstances 0 is invalid so
- // will not be used) until the old sync points are replaced.
- PullTextureUpdates(gpu::CommandBufferNamespace::GPU_IO, 0, sync_point);
- return true;
- }
-
- TRACE_EVENT_ASYNC_BEGIN1("gpu", "WaitSyncPoint", this, "GpuCommandBufferStub",
- this);
-
- waiting_for_sync_point_ = true;
- sync_point_manager_->AddSyncPointCallback(
- sync_point,
- base::Bind(&RunOnThread, task_runner_,
- base::Bind(&GpuCommandBufferStub::OnWaitSyncPointCompleted,
- this->AsWeakPtr(), sync_point)));
-
- if (!waiting_for_sync_point_)
- return true;
-
- scheduler_->SetScheduled(false);
- return false;
-}
-
-void GpuCommandBufferStub::OnWaitSyncPointCompleted(uint32_t sync_point) {
- DCHECK(waiting_for_sync_point_);
- TRACE_EVENT_ASYNC_END1("gpu", "WaitSyncPoint", this, "GpuCommandBufferStub",
- this);
- // Old sync points are global and do not have a command buffer ID,
- // We can simply use the global sync point number as the release count with
- // 0 for the command buffer ID (under normal circumstances 0 is invalid so
- // will not be used) until the old sync points are replaced.
- PullTextureUpdates(gpu::CommandBufferNamespace::GPU_IO, 0, sync_point);
- waiting_for_sync_point_ = false;
- scheduler_->SetScheduled(true);
-}
-
-void GpuCommandBufferStub::PullTextureUpdates(
- gpu::CommandBufferNamespace namespace_id,
- uint64_t command_buffer_id,
- uint32_t release) {
- gpu::gles2::MailboxManager* mailbox_manager =
- context_group_->mailbox_manager();
- if (mailbox_manager->UsesSync() && MakeCurrent()) {
- gpu::SyncToken sync_token(namespace_id, 0, command_buffer_id, release);
- mailbox_manager->PullTextureUpdates(sync_token);
- }
-}
-
-void GpuCommandBufferStub::OnSignalSyncPoint(uint32_t sync_point, uint32_t id) {
- sync_point_manager_->AddSyncPointCallback(
- sync_point,
- base::Bind(&GpuCommandBufferStub::OnSignalAck, this->AsWeakPtr(), id));
-}
-
-void GpuCommandBufferStub::OnSignalSyncToken(const gpu::SyncToken& sync_token,
- uint32_t id) {
- scoped_refptr<gpu::SyncPointClientState> release_state =
- sync_point_manager_->GetSyncPointClientState(
- sync_token.namespace_id(), sync_token.command_buffer_id());
-
- if (release_state) {
- sync_point_client_->Wait(release_state.get(), sync_token.release_count(),
- base::Bind(&GpuCommandBufferStub::OnSignalAck,
- this->AsWeakPtr(), id));
- } else {
- OnSignalAck(id);
- }
-}
-
-void GpuCommandBufferStub::OnSignalAck(uint32_t id) {
- Send(new GpuCommandBufferMsg_SignalAck(route_id_, id));
-}
-
-void GpuCommandBufferStub::OnSignalQuery(uint32_t query_id, uint32_t id) {
- if (decoder_) {
- gpu::gles2::QueryManager* query_manager = decoder_->GetQueryManager();
- if (query_manager) {
- gpu::gles2::QueryManager::Query* query =
- query_manager->GetQuery(query_id);
- if (query) {
- query->AddCallback(
- base::Bind(&GpuCommandBufferStub::OnSignalAck,
- this->AsWeakPtr(),
- id));
- return;
- }
- }
- }
- // Something went wrong, run callback immediately.
- OnSignalAck(id);
-}
-
-void GpuCommandBufferStub::OnFenceSyncRelease(uint64_t release) {
- if (sync_point_client_->client_state()->IsFenceSyncReleased(release)) {
- DLOG(ERROR) << "Fence Sync has already been released.";
- return;
- }
-
- gpu::gles2::MailboxManager* mailbox_manager =
- context_group_->mailbox_manager();
- if (mailbox_manager->UsesSync() && MakeCurrent()) {
- gpu::SyncToken sync_token(gpu::CommandBufferNamespace::GPU_IO, 0,
- command_buffer_id_, release);
- mailbox_manager->PushTextureUpdates(sync_token);
- }
-
- sync_point_client_->ReleaseFenceSync(release);
-}
-
-bool GpuCommandBufferStub::OnWaitFenceSync(
- gpu::CommandBufferNamespace namespace_id,
- uint64_t command_buffer_id,
- uint64_t release) {
- DCHECK(!waiting_for_sync_point_);
- DCHECK(scheduler_->scheduled());
-
- scoped_refptr<gpu::SyncPointClientState> release_state =
- sync_point_manager_->GetSyncPointClientState(namespace_id,
- command_buffer_id);
-
- if (!release_state)
- return true;
-
- if (release_state->IsFenceSyncReleased(release)) {
- PullTextureUpdates(namespace_id, command_buffer_id, release);
- return true;
- }
-
- TRACE_EVENT_ASYNC_BEGIN1("gpu", "WaitFenceSync", this, "GpuCommandBufferStub",
- this);
- waiting_for_sync_point_ = true;
- sync_point_client_->WaitNonThreadSafe(
- release_state.get(), release, task_runner_,
- base::Bind(&GpuCommandBufferStub::OnWaitFenceSyncCompleted,
- this->AsWeakPtr(), namespace_id, command_buffer_id, release));
-
- if (!waiting_for_sync_point_)
- return true;
-
- scheduler_->SetScheduled(false);
- return false;
-}
-
-void GpuCommandBufferStub::OnWaitFenceSyncCompleted(
- gpu::CommandBufferNamespace namespace_id,
- uint64_t command_buffer_id,
- uint64_t release) {
- DCHECK(waiting_for_sync_point_);
- TRACE_EVENT_ASYNC_END1("gpu", "WaitFenceSync", this, "GpuCommandBufferStub",
- this);
- PullTextureUpdates(namespace_id, command_buffer_id, release);
- waiting_for_sync_point_ = false;
- scheduler_->SetScheduled(true);
-}
-
-void GpuCommandBufferStub::OnCreateImage(
- const GpuCommandBufferMsg_CreateImage_Params& params) {
- TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnCreateImage");
- const int32_t id = params.id;
- const gfx::GpuMemoryBufferHandle& handle = params.gpu_memory_buffer;
- const gfx::Size& size = params.size;
- const gfx::BufferFormat& format = params.format;
- const uint32_t internalformat = params.internal_format;
- const uint64_t image_release_count = params.image_release_count;
-
- if (!decoder_)
- return;
-
- gpu::gles2::ImageManager* image_manager = decoder_->GetImageManager();
- DCHECK(image_manager);
- if (image_manager->LookupImage(id)) {
- LOG(ERROR) << "Image already exists with same ID.";
- return;
- }
-
- if (!gpu::ImageFactory::IsGpuMemoryBufferFormatSupported(
- format, decoder_->GetCapabilities())) {
- LOG(ERROR) << "Format is not supported.";
- return;
- }
-
- if (!gpu::ImageFactory::IsImageSizeValidForGpuMemoryBufferFormat(size,
- format)) {
- LOG(ERROR) << "Invalid image size for format.";
- return;
- }
-
- if (!gpu::ImageFactory::IsImageFormatCompatibleWithGpuMemoryBufferFormat(
- internalformat, format)) {
- LOG(ERROR) << "Incompatible image format.";
- return;
- }
-
- scoped_refptr<gl::GLImage> image = channel()->CreateImageForGpuMemoryBuffer(
- handle, size, format, internalformat);
- if (!image.get())
- return;
-
- image_manager->AddImage(image.get(), id);
- if (image_release_count) {
- sync_point_client_->ReleaseFenceSync(image_release_count);
- }
-}
-
-void GpuCommandBufferStub::OnDestroyImage(int32_t id) {
- TRACE_EVENT0("gpu", "GpuCommandBufferStub::OnDestroyImage");
-
- if (!decoder_)
- return;
-
- gpu::gles2::ImageManager* image_manager = decoder_->GetImageManager();
- DCHECK(image_manager);
- if (!image_manager->LookupImage(id)) {
- LOG(ERROR) << "Image with ID doesn't exist.";
- return;
- }
-
- image_manager->RemoveImage(id);
-}
-
-void GpuCommandBufferStub::SendConsoleMessage(int32_t id,
- const std::string& message) {
- GPUCommandBufferConsoleMessage console_message;
- console_message.id = id;
- console_message.message = message;
- IPC::Message* msg = new GpuCommandBufferMsg_ConsoleMsg(
- route_id_, console_message);
- msg->set_unblock(true);
- Send(msg);
-}
-
-void GpuCommandBufferStub::SendCachedShader(
- const std::string& key, const std::string& shader) {
- channel_->CacheShader(key, shader);
-}
-
-void GpuCommandBufferStub::AddDestructionObserver(
- DestructionObserver* observer) {
- destruction_observers_.AddObserver(observer);
-}
-
-void GpuCommandBufferStub::RemoveDestructionObserver(
- DestructionObserver* observer) {
- destruction_observers_.RemoveObserver(observer);
-}
-
-const gpu::gles2::FeatureInfo* GpuCommandBufferStub::GetFeatureInfo() const {
- return context_group_->feature_info();
-}
-
-gpu::gles2::MemoryTracker* GpuCommandBufferStub::GetMemoryTracker() const {
- return context_group_->memory_tracker();
-}
-
-bool GpuCommandBufferStub::CheckContextLost() {
- DCHECK(command_buffer_);
- gpu::CommandBuffer::State state = command_buffer_->GetLastState();
- bool was_lost = state.error == gpu::error::kLostContext;
-
- if (was_lost) {
- bool was_lost_by_robustness =
- decoder_ && decoder_->WasContextLostByRobustnessExtension();
-
- // Work around issues with recovery by allowing a new GPU process to launch.
- if ((was_lost_by_robustness ||
- context_group_->feature_info()->workarounds().exit_on_context_lost) &&
- !base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kSingleProcess) &&
- !base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kInProcessGPU)) {
- LOG(ERROR) << "Exiting GPU process because some drivers cannot recover"
- << " from problems.";
-#if defined(OS_WIN)
- base::win::SetShouldCrashOnProcessDetach(false);
-#endif
- exit(0);
- }
-
- // Lose all other contexts if the reset was triggered by the robustness
- // extension instead of being synthetic.
- if (was_lost_by_robustness &&
- (gfx::GLContext::LosesAllContextsOnContextLost() ||
- use_virtualized_gl_context_)) {
- channel_->LoseAllContexts();
- }
- }
-
- CheckCompleteWaits();
- return was_lost;
-}
-
-void GpuCommandBufferStub::MarkContextLost() {
- if (!command_buffer_ ||
- command_buffer_->GetLastState().error == gpu::error::kLostContext)
- return;
-
- command_buffer_->SetContextLostReason(gpu::error::kUnknown);
- if (decoder_)
- decoder_->MarkContextLost(gpu::error::kUnknown);
- command_buffer_->SetParseError(gpu::error::kLostContext);
-}
-
-void GpuCommandBufferStub::SendSwapBuffersCompleted(
- const std::vector<ui::LatencyInfo>& latency_info,
- gfx::SwapResult result) {
- Send(new GpuCommandBufferMsg_SwapBuffersCompleted(route_id_, latency_info,
- result));
-}
-
-void GpuCommandBufferStub::SendUpdateVSyncParameters(base::TimeTicks timebase,
- base::TimeDelta interval) {
- Send(new GpuCommandBufferMsg_UpdateVSyncParameters(route_id_, timebase,
- interval));
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/gpu_command_buffer_stub.h b/chromium/content/common/gpu/gpu_command_buffer_stub.h
deleted file mode 100644
index a9374d7b0ec..00000000000
--- a/chromium/content/common/gpu/gpu_command_buffer_stub.h
+++ /dev/null
@@ -1,307 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_GPU_COMMAND_BUFFER_STUB_H_
-#define CONTENT_COMMON_GPU_GPU_COMMAND_BUFFER_STUB_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <deque>
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
-#include "base/time/time.h"
-#include "content/common/content_export.h"
-#include "content/common/gpu/gpu_memory_manager.h"
-#include "gpu/command_buffer/common/constants.h"
-#include "gpu/command_buffer/common/gpu_memory_allocation.h"
-#include "gpu/command_buffer/service/command_buffer_service.h"
-#include "gpu/command_buffer/service/context_group.h"
-#include "gpu/command_buffer/service/gpu_scheduler.h"
-#include "ipc/ipc_listener.h"
-#include "ipc/ipc_sender.h"
-#include "media/video/video_decode_accelerator.h"
-#include "ui/events/latency_info.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/gpu_memory_buffer.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gfx/swap_result.h"
-#include "ui/gl/gl_surface.h"
-#include "ui/gl/gpu_preference.h"
-#include "url/gurl.h"
-
-namespace gpu {
-struct Mailbox;
-struct SyncToken;
-class SyncPointClient;
-class SyncPointManager;
-class ValueStateMap;
-namespace gles2 {
-class MailboxManager;
-class SubscriptionRefSet;
-}
-}
-
-struct GpuCommandBufferMsg_CreateImage_Params;
-
-namespace content {
-
-class GpuChannel;
-class GpuVideoDecodeAccelerator;
-class GpuVideoEncodeAccelerator;
-class GpuWatchdog;
-struct WaitForCommandState;
-
-class GpuCommandBufferStub
- : public IPC::Listener,
- public IPC::Sender,
- public base::SupportsWeakPtr<GpuCommandBufferStub> {
- public:
- class DestructionObserver {
- public:
- // Called in Destroy(), before the context/surface are released.
- virtual void OnWillDestroyStub() = 0;
-
- protected:
- virtual ~DestructionObserver() {}
- };
-
- typedef base::Callback<void(const std::vector<ui::LatencyInfo>&)>
- LatencyInfoCallback;
-
- GpuCommandBufferStub(
- GpuChannel* channel,
- gpu::SyncPointManager* sync_point_manager,
- base::SingleThreadTaskRunner* task_runner,
- GpuCommandBufferStub* share_group,
- const gfx::GLSurfaceHandle& handle,
- gpu::gles2::MailboxManager* mailbox_manager,
- gpu::PreemptionFlag* preempt_by_flag,
- gpu::gles2::SubscriptionRefSet* subscription_ref_set,
- gpu::ValueStateMap* pending_valuebuffer_state,
- const gfx::Size& size,
- const gpu::gles2::DisallowedFeatures& disallowed_features,
- const std::vector<int32_t>& attribs,
- gfx::GpuPreference gpu_preference,
- int32_t stream_id,
- int32_t route_id,
- bool offscreen,
- GpuWatchdog* watchdog,
- const GURL& active_url);
-
- ~GpuCommandBufferStub() override;
-
- // IPC::Listener implementation:
- bool OnMessageReceived(const IPC::Message& message) override;
-
- // IPC::Sender implementation:
- bool Send(IPC::Message* msg) override;
-
- gpu::gles2::MemoryTracker* GetMemoryTracker() const;
-
- // Whether this command buffer can currently handle IPC messages.
- bool IsScheduled();
-
- // Whether there are commands in the buffer that haven't been processed.
- bool HasUnprocessedCommands();
-
- gpu::gles2::GLES2Decoder* decoder() const { return decoder_.get(); }
- gpu::GpuScheduler* scheduler() const { return scheduler_.get(); }
- GpuChannel* channel() const { return channel_; }
-
- // Unique command buffer ID for this command buffer stub.
- uint64_t command_buffer_id() const { return command_buffer_id_; }
-
- // Identifies the various GpuCommandBufferStubs in the GPU process belonging
- // to the same renderer process.
- int32_t route_id() const { return route_id_; }
-
- // Identifies the stream for this command buffer.
- int32_t stream_id() const { return stream_id_; }
-
- gfx::GpuPreference gpu_preference() { return gpu_preference_; }
-
- int32_t GetRequestedAttribute(int attr) const;
-
- // Sends a message to the console.
- void SendConsoleMessage(int32_t id, const std::string& message);
-
- void SendCachedShader(const std::string& key, const std::string& shader);
-
- gfx::GLSurface* surface() const { return surface_.get(); }
-
- void AddDestructionObserver(DestructionObserver* observer);
- void RemoveDestructionObserver(DestructionObserver* observer);
-
- // Associates a sync point to this stub. When the stub is destroyed, it will
- // retire all sync points that haven't been previously retired.
- void InsertSyncPoint(uint32_t sync_point, bool retire);
-
- void SetLatencyInfoCallback(const LatencyInfoCallback& callback);
-
- void MarkContextLost();
-
- const gpu::gles2::FeatureInfo* GetFeatureInfo() const;
-
- void SendSwapBuffersCompleted(
- const std::vector<ui::LatencyInfo>& latency_info,
- gfx::SwapResult result);
- void SendUpdateVSyncParameters(base::TimeTicks timebase,
- base::TimeDelta interval);
-
- private:
- GpuMemoryManager* GetMemoryManager() const;
-
- void Destroy();
-
- bool MakeCurrent();
-
- // Cleans up and sends reply if OnInitialize failed.
- void OnInitializeFailed(IPC::Message* reply_message);
-
- // Message handlers:
- void OnInitialize(base::SharedMemoryHandle shared_state_shm,
- IPC::Message* reply_message);
- void OnSetGetBuffer(int32_t shm_id, IPC::Message* reply_message);
- void OnProduceFrontBuffer(const gpu::Mailbox& mailbox);
- void OnGetState(IPC::Message* reply_message);
- void OnWaitForTokenInRange(int32_t start,
- int32_t end,
- IPC::Message* reply_message);
- void OnWaitForGetOffsetInRange(int32_t start,
- int32_t end,
- IPC::Message* reply_message);
- void OnAsyncFlush(int32_t put_offset,
- uint32_t flush_count,
- const std::vector<ui::LatencyInfo>& latency_info);
- void OnRegisterTransferBuffer(int32_t id,
- base::SharedMemoryHandle transfer_buffer,
- uint32_t size);
- void OnDestroyTransferBuffer(int32_t id);
- void OnGetTransferBuffer(int32_t id, IPC::Message* reply_message);
-
- void OnCreateVideoDecoder(const media::VideoDecodeAccelerator::Config& config,
- int32_t route_id,
- IPC::Message* reply_message);
- void OnCreateVideoEncoder(media::VideoPixelFormat input_format,
- const gfx::Size& input_visible_size,
- media::VideoCodecProfile output_profile,
- uint32_t initial_bitrate,
- int32_t route_id,
- IPC::Message* reply_message);
-
- void OnEnsureBackbuffer();
-
- void OnRetireSyncPoint(uint32_t sync_point);
- bool OnWaitSyncPoint(uint32_t sync_point);
- void OnWaitSyncPointCompleted(uint32_t sync_point);
- void OnSignalSyncPoint(uint32_t sync_point, uint32_t id);
- void OnSignalSyncToken(const gpu::SyncToken& sync_token, uint32_t id);
- void OnSignalAck(uint32_t id);
- void OnSignalQuery(uint32_t query, uint32_t id);
-
- void OnFenceSyncRelease(uint64_t release);
- bool OnWaitFenceSync(gpu::CommandBufferNamespace namespace_id,
- uint64_t command_buffer_id,
- uint64_t release);
- void OnWaitFenceSyncCompleted(gpu::CommandBufferNamespace namespace_id,
- uint64_t command_buffer_id,
- uint64_t release);
-
- void OnCreateImage(const GpuCommandBufferMsg_CreateImage_Params& params);
- void OnDestroyImage(int32_t id);
- void OnCreateStreamTexture(uint32_t texture_id,
- int32_t stream_id,
- bool* succeeded);
-
- void OnCommandProcessed();
- void OnParseError();
- void OnSchedulingChanged(bool scheduled);
-
- void ReportState();
-
- // Wrapper for GpuScheduler::PutChanged that sets the crash report URL.
- void PutChanged();
-
- // Poll the command buffer to execute work.
- void PollWork();
- void PerformWork();
-
- // Schedule processing of delayed work. This updates the time at which
- // delayed work should be processed. |process_delayed_work_time_| is
- // updated to current time + delay. Call this after processing some amount
- // of delayed work.
- void ScheduleDelayedWork(base::TimeDelta delay);
-
- bool CheckContextLost();
- void CheckCompleteWaits();
- void PullTextureUpdates(gpu::CommandBufferNamespace namespace_id,
- uint64_t command_buffer_id,
- uint32_t release);
-
- // The lifetime of objects of this class is managed by a GpuChannel. The
- // GpuChannels destroy all the GpuCommandBufferStubs that they own when they
- // are destroyed. So a raw pointer is safe.
- GpuChannel* channel_;
-
- // Outlives the stub.
- gpu::SyncPointManager* sync_point_manager_;
-
- // Task runner for main thread.
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
- // The group of contexts that share namespaces with this context.
- scoped_refptr<gpu::gles2::ContextGroup> context_group_;
-
- bool initialized_;
- gfx::GLSurfaceHandle handle_;
- gfx::Size initial_size_;
- gpu::gles2::DisallowedFeatures disallowed_features_;
- std::vector<int32_t> requested_attribs_;
- gfx::GpuPreference gpu_preference_;
- bool use_virtualized_gl_context_;
- const uint64_t command_buffer_id_;
- const int32_t stream_id_;
- const int32_t route_id_;
- const bool offscreen_;
- uint32_t last_flush_count_;
-
- scoped_ptr<gpu::CommandBufferService> command_buffer_;
- scoped_ptr<gpu::gles2::GLES2Decoder> decoder_;
- scoped_ptr<gpu::GpuScheduler> scheduler_;
- scoped_ptr<gpu::SyncPointClient> sync_point_client_;
- scoped_refptr<gfx::GLSurface> surface_;
-
- GpuWatchdog* watchdog_;
-
- base::ObserverList<DestructionObserver> destruction_observers_;
-
- // A queue of sync points associated with this stub.
- std::deque<uint32_t> sync_points_;
- bool waiting_for_sync_point_;
-
- base::TimeTicks process_delayed_work_time_;
- uint32_t previous_processed_num_;
- base::TimeTicks last_idle_time_;
-
- scoped_refptr<gpu::PreemptionFlag> preemption_flag_;
-
- LatencyInfoCallback latency_info_callback_;
-
- GURL active_url_;
- size_t active_url_hash_;
-
- scoped_ptr<WaitForCommandState> wait_for_token_;
- scoped_ptr<WaitForCommandState> wait_for_get_offset_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuCommandBufferStub);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_GPU_COMMAND_BUFFER_STUB_H_
diff --git a/chromium/content/common/gpu/gpu_config.h b/chromium/content/common/gpu/gpu_config.h
deleted file mode 100644
index 74d5ee05b86..00000000000
--- a/chromium/content/common/gpu/gpu_config.h
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_GPU_CONFIG_H_
-#define CONTENT_COMMON_GPU_GPU_CONFIG_H_
-
-// This file declares common preprocessor configuration for the GPU process.
-
-#include "build/build_config.h"
-
-#endif // CONTENT_COMMON_GPU_GPU_CONFIG_H_
diff --git a/chromium/content/common/gpu/gpu_memory_buffer_factory.cc b/chromium/content/common/gpu/gpu_memory_buffer_factory.cc
deleted file mode 100644
index 8469e162178..00000000000
--- a/chromium/content/common/gpu/gpu_memory_buffer_factory.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/gpu_memory_buffer_factory.h"
-
-#include "base/logging.h"
-#include "build/build_config.h"
-
-#if defined(OS_MACOSX)
-#include "content/common/gpu/gpu_memory_buffer_factory_io_surface.h"
-#endif
-
-#if defined(OS_ANDROID)
-#include "content/common/gpu/gpu_memory_buffer_factory_surface_texture.h"
-#endif
-
-#if defined(USE_OZONE)
-#include "content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.h"
-#endif
-
-namespace content {
-
-// static
-gfx::GpuMemoryBufferType GpuMemoryBufferFactory::GetNativeType() {
-#if defined(OS_MACOSX)
- return gfx::IO_SURFACE_BUFFER;
-#endif
-#if defined(OS_ANDROID)
- return gfx::SURFACE_TEXTURE_BUFFER;
-#endif
-#if defined(USE_OZONE)
- return gfx::OZONE_NATIVE_PIXMAP;
-#endif
- return gfx::EMPTY_BUFFER;
-}
-
-// static
-scoped_ptr<GpuMemoryBufferFactory> GpuMemoryBufferFactory::CreateNativeType() {
-#if defined(OS_MACOSX)
- return make_scoped_ptr(new GpuMemoryBufferFactoryIOSurface);
-#endif
-#if defined(OS_ANDROID)
- return make_scoped_ptr(new GpuMemoryBufferFactorySurfaceTexture);
-#endif
-#if defined(USE_OZONE)
- return make_scoped_ptr(new GpuMemoryBufferFactoryOzoneNativePixmap);
-#endif
- NOTREACHED();
- return nullptr;
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/gpu_memory_buffer_factory.h b/chromium/content/common/gpu/gpu_memory_buffer_factory.h
deleted file mode 100644
index 77a50f2775c..00000000000
--- a/chromium/content/common/gpu/gpu_memory_buffer_factory.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_GPU_MEMORY_BUFFER_FACTORY_H_
-#define CONTENT_COMMON_GPU_GPU_MEMORY_BUFFER_FACTORY_H_
-
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/common/content_export.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/gpu_memory_buffer.h"
-#include "ui/gfx/native_widget_types.h"
-
-namespace gpu {
-class ImageFactory;
-}
-
-namespace content {
-
-class CONTENT_EXPORT GpuMemoryBufferFactory {
- public:
- virtual ~GpuMemoryBufferFactory() {}
-
- // Returns the native GPU memory buffer factory type. Returns EMPTY_BUFFER
- // type if native buffers are not supported.
- static gfx::GpuMemoryBufferType GetNativeType();
-
- // Creates a new factory instance for native GPU memory buffers.
- static scoped_ptr<GpuMemoryBufferFactory> CreateNativeType();
-
- // Creates a new GPU memory buffer instance. A valid handle is returned on
- // success. It can be called on any thread.
- virtual gfx::GpuMemoryBufferHandle CreateGpuMemoryBuffer(
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- int client_id,
- gfx::PluginWindowHandle surface_handle) = 0;
-
- // Creates a new GPU memory buffer instance from an existing handle. A valid
- // handle is returned on success. It can be called on any thread.
- virtual gfx::GpuMemoryBufferHandle CreateGpuMemoryBufferFromHandle(
- const gfx::GpuMemoryBufferHandle& handle,
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- int client_id) = 0;
-
- // Destroys GPU memory buffer identified by |id|.
- // It can be called on any thread.
- virtual void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
- int client_id) = 0;
-
- // Type-checking downcast routine.
- virtual gpu::ImageFactory* AsImageFactory() = 0;
-
- protected:
- GpuMemoryBufferFactory() {}
-
- private:
- DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferFactory);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_GPU_MEMORY_BUFFER_FACTORY_H_
diff --git a/chromium/content/common/gpu/gpu_memory_buffer_factory_io_surface.cc b/chromium/content/common/gpu/gpu_memory_buffer_factory_io_surface.cc
deleted file mode 100644
index 49fab37b596..00000000000
--- a/chromium/content/common/gpu/gpu_memory_buffer_factory_io_surface.cc
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/gpu_memory_buffer_factory_io_surface.h"
-
-#include <vector>
-
-#include "base/logging.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
-#include "ui/gfx/buffer_format_util.h"
-#include "ui/gfx/mac/io_surface.h"
-#include "ui/gl/gl_image_io_surface.h"
-
-namespace content {
-
-GpuMemoryBufferFactoryIOSurface::GpuMemoryBufferFactoryIOSurface() {
-}
-
-GpuMemoryBufferFactoryIOSurface::~GpuMemoryBufferFactoryIOSurface() {
-}
-
-// static
-bool GpuMemoryBufferFactoryIOSurface::IsGpuMemoryBufferConfigurationSupported(
- gfx::BufferFormat format,
- gfx::BufferUsage usage) {
- switch (usage) {
- case gfx::BufferUsage::GPU_READ:
- case gfx::BufferUsage::SCANOUT:
- return format == gfx::BufferFormat::BGRA_8888 ||
- format == gfx::BufferFormat::RGBA_8888;
- case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE:
- case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE_PERSISTENT:
- return format == gfx::BufferFormat::R_8 ||
- format == gfx::BufferFormat::BGRA_8888 ||
- format == gfx::BufferFormat::UYVY_422 ||
- format == gfx::BufferFormat::YUV_420_BIPLANAR;
- }
- NOTREACHED();
- return false;
-}
-
-gfx::GpuMemoryBufferHandle
-GpuMemoryBufferFactoryIOSurface::CreateGpuMemoryBuffer(
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- int client_id,
- gfx::PluginWindowHandle surface_handle) {
- base::ScopedCFTypeRef<IOSurfaceRef> io_surface(
- gfx::CreateIOSurface(size, format));
- if (!io_surface)
- return gfx::GpuMemoryBufferHandle();
-
- {
- base::AutoLock lock(io_surfaces_lock_);
-
- IOSurfaceMapKey key(id, client_id);
- DCHECK(io_surfaces_.find(key) == io_surfaces_.end());
- io_surfaces_[key] = io_surface;
- }
-
- gfx::GpuMemoryBufferHandle handle;
- handle.type = gfx::IO_SURFACE_BUFFER;
- handle.id = id;
- handle.mach_port.reset(IOSurfaceCreateMachPort(io_surface));
- return handle;
-}
-
-gfx::GpuMemoryBufferHandle
-GpuMemoryBufferFactoryIOSurface::CreateGpuMemoryBufferFromHandle(
- const gfx::GpuMemoryBufferHandle& handle,
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- int client_id) {
- NOTIMPLEMENTED();
- return gfx::GpuMemoryBufferHandle();
-}
-
-void GpuMemoryBufferFactoryIOSurface::DestroyGpuMemoryBuffer(
- gfx::GpuMemoryBufferId id,
- int client_id) {
- {
- base::AutoLock lock(io_surfaces_lock_);
-
- IOSurfaceMapKey key(id, client_id);
- DCHECK(io_surfaces_.find(key) != io_surfaces_.end());
- io_surfaces_.erase(key);
- }
-}
-
-gpu::ImageFactory* GpuMemoryBufferFactoryIOSurface::AsImageFactory() {
- return this;
-}
-
-scoped_refptr<gl::GLImage>
-GpuMemoryBufferFactoryIOSurface::CreateImageForGpuMemoryBuffer(
- const gfx::GpuMemoryBufferHandle& handle,
- const gfx::Size& size,
- gfx::BufferFormat format,
- unsigned internalformat,
- int client_id) {
- base::AutoLock lock(io_surfaces_lock_);
-
- DCHECK_EQ(handle.type, gfx::IO_SURFACE_BUFFER);
- IOSurfaceMapKey key(handle.id, client_id);
- IOSurfaceMap::iterator it = io_surfaces_.find(key);
- if (it == io_surfaces_.end())
- return scoped_refptr<gl::GLImage>();
-
- scoped_refptr<gl::GLImageIOSurface> image(
- new gl::GLImageIOSurface(size, internalformat));
- if (!image->Initialize(it->second.get(), handle.id, format))
- return scoped_refptr<gl::GLImage>();
-
- return image;
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/gpu_memory_buffer_factory_io_surface.h b/chromium/content/common/gpu/gpu_memory_buffer_factory_io_surface.h
deleted file mode 100644
index d2fd00dbe3d..00000000000
--- a/chromium/content/common/gpu/gpu_memory_buffer_factory_io_surface.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_GPU_MEMORY_BUFFER_FACTORY_IO_SURFACE_H_
-#define CONTENT_COMMON_GPU_GPU_MEMORY_BUFFER_FACTORY_IO_SURFACE_H_
-
-#include <utility>
-
-#include <IOSurface/IOSurface.h>
-
-#include "base/containers/hash_tables.h"
-#include "base/mac/scoped_cftyperef.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/synchronization/lock.h"
-#include "content/common/content_export.h"
-#include "content/common/gpu/gpu_memory_buffer_factory.h"
-#include "gpu/command_buffer/service/image_factory.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/gpu_memory_buffer.h"
-#include "ui/gfx/mac/io_surface.h"
-
-namespace gl {
-class GLImage;
-}
-
-namespace content {
-
-class CONTENT_EXPORT GpuMemoryBufferFactoryIOSurface
- : public GpuMemoryBufferFactory,
- public gpu::ImageFactory {
- public:
- GpuMemoryBufferFactoryIOSurface();
- ~GpuMemoryBufferFactoryIOSurface() override;
-
- static bool IsGpuMemoryBufferConfigurationSupported(gfx::BufferFormat format,
- gfx::BufferUsage usage);
-
- // Overridden from GpuMemoryBufferFactory:
- gfx::GpuMemoryBufferHandle CreateGpuMemoryBuffer(
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- int client_id,
- gfx::PluginWindowHandle surface_handle) override;
- gfx::GpuMemoryBufferHandle CreateGpuMemoryBufferFromHandle(
- const gfx::GpuMemoryBufferHandle& handle,
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- int client_id) override;
- void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
- int client_id) override;
- gpu::ImageFactory* AsImageFactory() override;
-
- // Overridden from gpu::ImageFactory:
- scoped_refptr<gl::GLImage> CreateImageForGpuMemoryBuffer(
- const gfx::GpuMemoryBufferHandle& handle,
- const gfx::Size& size,
- gfx::BufferFormat format,
- unsigned internalformat,
- int client_id) override;
-
- private:
- typedef std::pair<gfx::IOSurfaceId, int> IOSurfaceMapKey;
- typedef base::hash_map<IOSurfaceMapKey, base::ScopedCFTypeRef<IOSurfaceRef>>
- IOSurfaceMap;
- // TOOD(reveman): Remove |io_surfaces_| and allow IOSurface backed GMBs to be
- // used with any GPU process by passing a mach_port to CreateImageCHROMIUM.
- IOSurfaceMap io_surfaces_;
- base::Lock io_surfaces_lock_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferFactoryIOSurface);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_GPU_MEMORY_BUFFER_FACTORY_IO_SURFACE_H_
diff --git a/chromium/content/common/gpu/gpu_memory_buffer_factory_io_surface_unittest.cc b/chromium/content/common/gpu/gpu_memory_buffer_factory_io_surface_unittest.cc
deleted file mode 100644
index 7f4a13257f4..00000000000
--- a/chromium/content/common/gpu/gpu_memory_buffer_factory_io_surface_unittest.cc
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/gpu_memory_buffer_factory_io_surface.h"
-#include "content/test/gpu_memory_buffer_factory_test_template.h"
-
-namespace content {
-namespace {
-
-INSTANTIATE_TYPED_TEST_CASE_P(GpuMemoryBufferFactoryIOSurface,
- GpuMemoryBufferFactoryTest,
- GpuMemoryBufferFactoryIOSurface);
-
-} // namespace
-} // namespace content
diff --git a/chromium/content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.cc b/chromium/content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.cc
deleted file mode 100644
index 69fdd3085cb..00000000000
--- a/chromium/content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.cc
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.h"
-
-#include "ui/gl/gl_image_ozone_native_pixmap.h"
-#include "ui/ozone/public/client_native_pixmap.h"
-#include "ui/ozone/public/client_native_pixmap_factory.h"
-#include "ui/ozone/public/ozone_platform.h"
-#include "ui/ozone/public/surface_factory_ozone.h"
-
-namespace content {
-
-GpuMemoryBufferFactoryOzoneNativePixmap::
- GpuMemoryBufferFactoryOzoneNativePixmap() {}
-
-GpuMemoryBufferFactoryOzoneNativePixmap::
- ~GpuMemoryBufferFactoryOzoneNativePixmap() {}
-
-// static
-bool GpuMemoryBufferFactoryOzoneNativePixmap::
- IsGpuMemoryBufferConfigurationSupported(gfx::BufferFormat format,
- gfx::BufferUsage usage) {
- if (!ui::ClientNativePixmapFactory::GetInstance()) {
- // unittests don't have to set ClientNativePixmapFactory.
- return false;
- }
- return ui::ClientNativePixmapFactory::GetInstance()->IsConfigurationSupported(
- format, usage);
-}
-
-gfx::GpuMemoryBufferHandle
-GpuMemoryBufferFactoryOzoneNativePixmap::CreateGpuMemoryBuffer(
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- int client_id,
- gfx::PluginWindowHandle surface_handle) {
- scoped_refptr<ui::NativePixmap> pixmap =
- ui::OzonePlatform::GetInstance()
- ->GetSurfaceFactoryOzone()
- ->CreateNativePixmap(surface_handle, size, format, usage);
- if (!pixmap.get()) {
- DLOG(ERROR) << "Failed to create pixmap " << size.width() << "x"
- << size.height() << " format " << static_cast<int>(format)
- << ", usage " << static_cast<int>(usage);
- return gfx::GpuMemoryBufferHandle();
- }
-
- gfx::GpuMemoryBufferHandle new_handle;
- new_handle.type = gfx::OZONE_NATIVE_PIXMAP;
- new_handle.id = id;
- new_handle.native_pixmap_handle = pixmap->ExportHandle();
-
- {
- base::AutoLock lock(native_pixmaps_lock_);
- NativePixmapMapKey key(id.id, client_id);
- DCHECK(native_pixmaps_.find(key) == native_pixmaps_.end());
- native_pixmaps_[key] = pixmap;
- }
-
- return new_handle;
-}
-
-gfx::GpuMemoryBufferHandle
-GpuMemoryBufferFactoryOzoneNativePixmap::CreateGpuMemoryBufferFromHandle(
- const gfx::GpuMemoryBufferHandle& handle,
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- int client_id) {
- scoped_refptr<ui::NativePixmap> pixmap =
- ui::OzonePlatform::GetInstance()
- ->GetSurfaceFactoryOzone()
- ->CreateNativePixmapFromHandle(handle.native_pixmap_handle);
- if (!pixmap.get()) {
- DLOG(ERROR) << "Failed to create pixmap from handle";
- return gfx::GpuMemoryBufferHandle();
- }
-
- gfx::GpuMemoryBufferHandle new_handle;
- new_handle.type = gfx::OZONE_NATIVE_PIXMAP;
- new_handle.id = id;
- new_handle.native_pixmap_handle = pixmap->ExportHandle();
-
- {
- base::AutoLock lock(native_pixmaps_lock_);
- NativePixmapMapKey key(id.id, client_id);
- DCHECK(native_pixmaps_.find(key) == native_pixmaps_.end());
- native_pixmaps_[key] = pixmap;
- }
-
- return new_handle;
-}
-
-void GpuMemoryBufferFactoryOzoneNativePixmap::DestroyGpuMemoryBuffer(
- gfx::GpuMemoryBufferId id,
- int client_id) {
- base::AutoLock lock(native_pixmaps_lock_);
- auto it = native_pixmaps_.find(NativePixmapMapKey(id.id, client_id));
- DCHECK(it != native_pixmaps_.end());
- native_pixmaps_.erase(it);
-}
-
-gpu::ImageFactory* GpuMemoryBufferFactoryOzoneNativePixmap::AsImageFactory() {
- return this;
-}
-
-scoped_refptr<gl::GLImage>
-GpuMemoryBufferFactoryOzoneNativePixmap::CreateImageForGpuMemoryBuffer(
- const gfx::GpuMemoryBufferHandle& handle,
- const gfx::Size& size,
- gfx::BufferFormat format,
- unsigned internalformat,
- int client_id) {
- DCHECK_EQ(handle.type, gfx::OZONE_NATIVE_PIXMAP);
- scoped_refptr<ui::NativePixmap> pixmap;
- {
- base::AutoLock lock(native_pixmaps_lock_);
- NativePixmapMap::iterator it =
- native_pixmaps_.find(NativePixmapMapKey(handle.id.id, client_id));
- if (it == native_pixmaps_.end()) {
- return nullptr;
- }
- pixmap = it->second;
- }
-
- scoped_refptr<gfx::GLImageOzoneNativePixmap> image(
- new gfx::GLImageOzoneNativePixmap(size, internalformat));
- if (!image->Initialize(pixmap.get(), format)) {
- LOG(ERROR) << "Failed to create GLImage";
- return nullptr;
- }
- return image;
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.h b/chromium/content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.h
deleted file mode 100644
index f9ea0d25b80..00000000000
--- a/chromium/content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.h
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_GPU_MEMORY_BUFFER_FACTORY_OZONE_NATIVE_PIXMAP_H_
-#define CONTENT_COMMON_GPU_GPU_MEMORY_BUFFER_FACTORY_OZONE_NATIVE_PIXMAP_H_
-
-#include "base/containers/hash_tables.h"
-#include "base/macros.h"
-#include "base/synchronization/lock.h"
-#include "content/common/content_export.h"
-#include "content/common/gpu/gpu_memory_buffer_factory.h"
-#include "gpu/command_buffer/service/image_factory.h"
-#include "ui/ozone/public/native_pixmap.h"
-
-namespace gl {
-class GLImage;
-}
-
-namespace content {
-
-class CONTENT_EXPORT GpuMemoryBufferFactoryOzoneNativePixmap
- : public GpuMemoryBufferFactory,
- public gpu::ImageFactory {
- public:
- GpuMemoryBufferFactoryOzoneNativePixmap();
- ~GpuMemoryBufferFactoryOzoneNativePixmap() override;
-
- static bool IsGpuMemoryBufferConfigurationSupported(gfx::BufferFormat format,
- gfx::BufferUsage usage);
-
- // Overridden from GpuMemoryBufferFactory:
- gfx::GpuMemoryBufferHandle CreateGpuMemoryBuffer(
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- int client_id,
- gfx::PluginWindowHandle surface_handle) override;
- gfx::GpuMemoryBufferHandle CreateGpuMemoryBufferFromHandle(
- const gfx::GpuMemoryBufferHandle& handle,
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- int client_id) override;
- void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
- int client_id) override;
- gpu::ImageFactory* AsImageFactory() override;
-
- // Overridden from gpu::ImageFactory:
- scoped_refptr<gl::GLImage> CreateImageForGpuMemoryBuffer(
- const gfx::GpuMemoryBufferHandle& handle,
- const gfx::Size& size,
- gfx::BufferFormat format,
- unsigned internalformat,
- int client_id) override;
-
- private:
- using NativePixmapMapKey = std::pair<int, int>;
- using NativePixmapMap =
- base::hash_map<NativePixmapMapKey, scoped_refptr<ui::NativePixmap>>;
- NativePixmapMap native_pixmaps_;
- base::Lock native_pixmaps_lock_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuMemoryBufferFactoryOzoneNativePixmap);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_GPU_MEMORY_BUFFER_FACTORY_OZONE_NATIVE_PIXMAP_H_
diff --git a/chromium/content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap_unittest.cc b/chromium/content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap_unittest.cc
deleted file mode 100644
index bdb974702d9..00000000000
--- a/chromium/content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap_unittest.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.h"
-#include "content/test/gpu_memory_buffer_factory_test_template.h"
-
-namespace content {
-namespace {
-
-INSTANTIATE_TYPED_TEST_CASE_P(GpuMemoryBufferFactoryOzoneNativePixmap,
- GpuMemoryBufferFactoryTest,
- GpuMemoryBufferFactoryOzoneNativePixmap);
-
-INSTANTIATE_TYPED_TEST_CASE_P(GpuMemoryBufferFactoryOzoneNativePixmap,
- GpuMemoryBufferFactoryImportTest,
- GpuMemoryBufferFactoryOzoneNativePixmap);
-
-} // namespace
-} // namespace content
diff --git a/chromium/content/common/gpu/gpu_memory_buffer_factory_surface_texture.cc b/chromium/content/common/gpu/gpu_memory_buffer_factory_surface_texture.cc
deleted file mode 100644
index a4cf15ed30e..00000000000
--- a/chromium/content/common/gpu/gpu_memory_buffer_factory_surface_texture.cc
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/gpu_memory_buffer_factory_surface_texture.h"
-
-#include "content/common/android/surface_texture_manager.h"
-#include "ui/gl/android/surface_texture.h"
-#include "ui/gl/gl_image_surface_texture.h"
-
-namespace content {
-
-GpuMemoryBufferFactorySurfaceTexture::GpuMemoryBufferFactorySurfaceTexture() {
-}
-
-GpuMemoryBufferFactorySurfaceTexture::~GpuMemoryBufferFactorySurfaceTexture() {
-}
-
-// static
-bool GpuMemoryBufferFactorySurfaceTexture::
- IsGpuMemoryBufferConfigurationSupported(gfx::BufferFormat format,
- gfx::BufferUsage usage) {
- switch (usage) {
- case gfx::BufferUsage::GPU_READ:
- case gfx::BufferUsage::SCANOUT:
- case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE_PERSISTENT:
- return false;
- case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE:
- return format == gfx::BufferFormat::RGBA_8888;
- }
- NOTREACHED();
- return false;
-}
-
-gfx::GpuMemoryBufferHandle
-GpuMemoryBufferFactorySurfaceTexture::CreateGpuMemoryBuffer(
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- int client_id,
- gfx::PluginWindowHandle surface_handle) {
- // Note: this needs to be 0 as the surface texture implemenation will take
- // ownership of the texture and call glDeleteTextures when the GPU service
- // attaches the surface texture to a real texture id. glDeleteTextures
- // silently ignores 0.
- const int kDummyTextureId = 0;
- scoped_refptr<gfx::SurfaceTexture> surface_texture =
- gfx::SurfaceTexture::Create(kDummyTextureId);
- if (!surface_texture.get())
- return gfx::GpuMemoryBufferHandle();
-
- SurfaceTextureManager::GetInstance()->RegisterSurfaceTexture(
- id.id, client_id, surface_texture.get());
-
- {
- base::AutoLock lock(surface_textures_lock_);
-
- SurfaceTextureMapKey key(id.id, client_id);
- DCHECK(surface_textures_.find(key) == surface_textures_.end());
- surface_textures_[key] = surface_texture;
- }
-
- gfx::GpuMemoryBufferHandle handle;
- handle.type = gfx::SURFACE_TEXTURE_BUFFER;
- handle.id = id;
- return handle;
-}
-
-gfx::GpuMemoryBufferHandle
-GpuMemoryBufferFactorySurfaceTexture::CreateGpuMemoryBufferFromHandle(
- const gfx::GpuMemoryBufferHandle& handle,
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- int client_id) {
- NOTIMPLEMENTED();
- return gfx::GpuMemoryBufferHandle();
-}
-
-void GpuMemoryBufferFactorySurfaceTexture::DestroyGpuMemoryBuffer(
- gfx::GpuMemoryBufferId id,
- int client_id) {
- {
- base::AutoLock lock(surface_textures_lock_);
-
- SurfaceTextureMapKey key(id.id, client_id);
- DCHECK(surface_textures_.find(key) != surface_textures_.end());
- surface_textures_.erase(key);
- }
-
- SurfaceTextureManager::GetInstance()->UnregisterSurfaceTexture(id.id,
- client_id);
-}
-
-gpu::ImageFactory* GpuMemoryBufferFactorySurfaceTexture::AsImageFactory() {
- return this;
-}
-
-scoped_refptr<gl::GLImage>
-GpuMemoryBufferFactorySurfaceTexture::CreateImageForGpuMemoryBuffer(
- const gfx::GpuMemoryBufferHandle& handle,
- const gfx::Size& size,
- gfx::BufferFormat format,
- unsigned internalformat,
- int client_id) {
- base::AutoLock lock(surface_textures_lock_);
-
- DCHECK_EQ(handle.type, gfx::SURFACE_TEXTURE_BUFFER);
-
- SurfaceTextureMapKey key(handle.id.id, client_id);
- SurfaceTextureMap::iterator it = surface_textures_.find(key);
- if (it == surface_textures_.end())
- return scoped_refptr<gl::GLImage>();
-
- scoped_refptr<gl::GLImageSurfaceTexture> image(
- new gl::GLImageSurfaceTexture(size));
- if (!image->Initialize(it->second.get()))
- return scoped_refptr<gl::GLImage>();
-
- return image;
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/gpu_memory_buffer_factory_surface_texture.h b/chromium/content/common/gpu/gpu_memory_buffer_factory_surface_texture.h
deleted file mode 100644
index b9eda55dcbd..00000000000
--- a/chromium/content/common/gpu/gpu_memory_buffer_factory_surface_texture.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_GPU_MEMORY_BUFFER_FACTORY_SURFACE_TEXTURE_H_
-#define CONTENT_COMMON_GPU_GPU_MEMORY_BUFFER_FACTORY_SURFACE_TEXTURE_H_
-
-#include <utility>
-
-#include "base/containers/hash_tables.h"
-#include "base/memory/ref_counted.h"
-#include "base/synchronization/lock.h"
-#include "content/common/content_export.h"
-#include "content/common/gpu/gpu_memory_buffer_factory.h"
-#include "gpu/command_buffer/service/image_factory.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/gpu_memory_buffer.h"
-
-namespace gfx {
-class SurfaceTexture;
-}
-
-namespace gl {
-class GLImage;
-}
-
-namespace content {
-
-class CONTENT_EXPORT GpuMemoryBufferFactorySurfaceTexture
- : public GpuMemoryBufferFactory,
- public gpu::ImageFactory {
- public:
- GpuMemoryBufferFactorySurfaceTexture();
- ~GpuMemoryBufferFactorySurfaceTexture() override;
-
- static bool IsGpuMemoryBufferConfigurationSupported(gfx::BufferFormat format,
- gfx::BufferUsage usage);
-
- // Overridden from GpuMemoryBufferFactory:
- gfx::GpuMemoryBufferHandle CreateGpuMemoryBuffer(
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- gfx::BufferUsage usage,
- int client_id,
- gfx::PluginWindowHandle surface_handle) override;
- gfx::GpuMemoryBufferHandle CreateGpuMemoryBufferFromHandle(
- const gfx::GpuMemoryBufferHandle& handle,
- gfx::GpuMemoryBufferId id,
- const gfx::Size& size,
- gfx::BufferFormat format,
- int client_id) override;
- void DestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
- int client_id) override;
- gpu::ImageFactory* AsImageFactory() override;
-
- // Overridden from gpu::ImageFactory:
- scoped_refptr<gl::GLImage> CreateImageForGpuMemoryBuffer(
- const gfx::GpuMemoryBufferHandle& handle,
- const gfx::Size& size,
- gfx::BufferFormat format,
- unsigned internalformat,
- int client_id) override;
-
- private:
- typedef std::pair<int, int> SurfaceTextureMapKey;
- typedef base::hash_map<SurfaceTextureMapKey,
- scoped_refptr<gfx::SurfaceTexture>> SurfaceTextureMap;
- SurfaceTextureMap surface_textures_;
- base::Lock surface_textures_lock_;
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_GPU_MEMORY_BUFFER_FACTORY_SURFACE_TEXTURE_H_
diff --git a/chromium/content/common/gpu/gpu_memory_buffer_factory_surface_texture_unittest.cc b/chromium/content/common/gpu/gpu_memory_buffer_factory_surface_texture_unittest.cc
deleted file mode 100644
index 683860fee17..00000000000
--- a/chromium/content/common/gpu/gpu_memory_buffer_factory_surface_texture_unittest.cc
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/gpu_memory_buffer_factory_surface_texture.h"
-#include "content/test/gpu_memory_buffer_factory_test_template.h"
-
-namespace content {
-namespace {
-
-INSTANTIATE_TYPED_TEST_CASE_P(GpuMemoryBufferFactorySurfaceTexture,
- GpuMemoryBufferFactoryTest,
- GpuMemoryBufferFactorySurfaceTexture);
-
-} // namespace
-} // namespace content
diff --git a/chromium/content/common/gpu/gpu_memory_manager.cc b/chromium/content/common/gpu/gpu_memory_manager.cc
deleted file mode 100644
index 4b9eb7c2888..00000000000
--- a/chromium/content/common/gpu/gpu_memory_manager.cc
+++ /dev/null
@@ -1,124 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/gpu_memory_manager.h"
-
-#include <algorithm>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/message_loop/message_loop.h"
-#include "base/process/process_handle.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/trace_event/trace_event.h"
-#include "content/common/gpu/gpu_channel_manager.h"
-#include "content/common/gpu/gpu_memory_tracking.h"
-#include "content/common/gpu/gpu_memory_uma_stats.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "gpu/command_buffer/common/gpu_memory_allocation.h"
-#include "gpu/command_buffer/service/gpu_switches.h"
-
-using gpu::MemoryAllocation;
-
-namespace content {
-namespace {
-
-const uint64_t kBytesAllocatedStep = 16 * 1024 * 1024;
-
-void TrackValueChanged(uint64_t old_size,
- uint64_t new_size,
- uint64_t* total_size) {
- DCHECK(new_size > old_size || *total_size >= (old_size - new_size));
- *total_size += (new_size - old_size);
-}
-
-}
-
-GpuMemoryManager::GpuMemoryManager(GpuChannelManager* channel_manager)
- : channel_manager_(channel_manager),
- bytes_allocated_current_(0),
- bytes_allocated_historical_max_(0) {}
-
-GpuMemoryManager::~GpuMemoryManager() {
- DCHECK(tracking_groups_.empty());
- DCHECK(!bytes_allocated_current_);
-}
-
-void GpuMemoryManager::TrackMemoryAllocatedChange(
- GpuMemoryTrackingGroup* tracking_group,
- uint64_t old_size,
- uint64_t new_size) {
- TrackValueChanged(old_size, new_size, &tracking_group->size_);
- TrackValueChanged(old_size, new_size, &bytes_allocated_current_);
-
- if (GetCurrentUsage() > bytes_allocated_historical_max_ +
- kBytesAllocatedStep) {
- bytes_allocated_historical_max_ = GetCurrentUsage();
- // If we're blowing into new memory usage territory, spam the browser
- // process with the most up-to-date information about our memory usage.
- SendUmaStatsToBrowser();
- }
-}
-
-bool GpuMemoryManager::EnsureGPUMemoryAvailable(uint64_t /* size_needed */) {
- // TODO: Check if there is enough space. Lose contexts until there is.
- return true;
-}
-
-uint64_t GpuMemoryManager::GetTrackerMemoryUsage(
- gpu::gles2::MemoryTracker* tracker) const {
- TrackingGroupMap::const_iterator tracking_group_it =
- tracking_groups_.find(tracker);
- DCHECK(tracking_group_it != tracking_groups_.end());
- return tracking_group_it->second->GetSize();
-}
-
-GpuMemoryTrackingGroup* GpuMemoryManager::CreateTrackingGroup(
- base::ProcessId pid, gpu::gles2::MemoryTracker* memory_tracker) {
- GpuMemoryTrackingGroup* tracking_group = new GpuMemoryTrackingGroup(
- pid, memory_tracker, this);
- DCHECK(!tracking_groups_.count(tracking_group->GetMemoryTracker()));
- tracking_groups_.insert(std::make_pair(tracking_group->GetMemoryTracker(),
- tracking_group));
- return tracking_group;
-}
-
-void GpuMemoryManager::OnDestroyTrackingGroup(
- GpuMemoryTrackingGroup* tracking_group) {
- DCHECK(tracking_groups_.count(tracking_group->GetMemoryTracker()));
- tracking_groups_.erase(tracking_group->GetMemoryTracker());
-}
-
-void GpuMemoryManager::GetVideoMemoryUsageStats(
- GPUVideoMemoryUsageStats* video_memory_usage_stats) const {
- // For each context group, assign its memory usage to its PID
- video_memory_usage_stats->process_map.clear();
- for (TrackingGroupMap::const_iterator i =
- tracking_groups_.begin(); i != tracking_groups_.end(); ++i) {
- const GpuMemoryTrackingGroup* tracking_group = i->second;
- video_memory_usage_stats->process_map[
- tracking_group->GetPid()].video_memory += tracking_group->GetSize();
- }
-
- // Assign the total across all processes in the GPU process
- video_memory_usage_stats->process_map[
- base::GetCurrentProcId()].video_memory = GetCurrentUsage();
- video_memory_usage_stats->process_map[
- base::GetCurrentProcId()].has_duplicates = true;
-
- video_memory_usage_stats->bytes_allocated = GetCurrentUsage();
- video_memory_usage_stats->bytes_allocated_historical_max =
- bytes_allocated_historical_max_;
-}
-
-void GpuMemoryManager::SendUmaStatsToBrowser() {
- if (!channel_manager_)
- return;
- GPUMemoryUmaStats params;
- params.bytes_allocated_current = GetCurrentUsage();
- params.bytes_allocated_max = bytes_allocated_historical_max_;
- params.context_group_count = tracking_groups_.size();
- channel_manager_->Send(new GpuHostMsg_GpuMemoryUmaStats(params));
-}
-} // namespace content
diff --git a/chromium/content/common/gpu/gpu_memory_manager.h b/chromium/content/common/gpu/gpu_memory_manager.h
deleted file mode 100644
index 7de22e5aa78..00000000000
--- a/chromium/content/common/gpu/gpu_memory_manager.h
+++ /dev/null
@@ -1,78 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_GPU_MEMORY_MANAGER_H_
-#define CONTENT_COMMON_GPU_GPU_MEMORY_MANAGER_H_
-
-#include <stdint.h>
-
-#include <list>
-#include <map>
-
-#include "base/cancelable_callback.h"
-#include "base/containers/hash_tables.h"
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "content/common/content_export.h"
-#include "content/public/common/gpu_memory_stats.h"
-#include "gpu/command_buffer/common/gpu_memory_allocation.h"
-#include "gpu/command_buffer/service/memory_tracking.h"
-
-namespace content {
-
-class GpuChannelManager;
-class GpuMemoryTrackingGroup;
-
-class CONTENT_EXPORT GpuMemoryManager :
- public base::SupportsWeakPtr<GpuMemoryManager> {
- public:
- explicit GpuMemoryManager(GpuChannelManager* channel_manager);
- ~GpuMemoryManager();
-
- // Retrieve GPU Resource consumption statistics for the task manager
- void GetVideoMemoryUsageStats(
- content::GPUVideoMemoryUsageStats* video_memory_usage_stats) const;
-
- GpuMemoryTrackingGroup* CreateTrackingGroup(
- base::ProcessId pid, gpu::gles2::MemoryTracker* memory_tracker);
-
- uint64_t GetTrackerMemoryUsage(gpu::gles2::MemoryTracker* tracker) const;
-
- private:
- friend class GpuMemoryManagerTest;
- friend class GpuMemoryTrackingGroup;
- friend class GpuMemoryManagerClientState;
-
- typedef std::map<gpu::gles2::MemoryTracker*, GpuMemoryTrackingGroup*>
- TrackingGroupMap;
-
- // Send memory usage stats to the browser process.
- void SendUmaStatsToBrowser();
-
- // Get the current number of bytes allocated.
- uint64_t GetCurrentUsage() const { return bytes_allocated_current_; }
-
- // GpuMemoryTrackingGroup interface
- void TrackMemoryAllocatedChange(GpuMemoryTrackingGroup* tracking_group,
- uint64_t old_size,
- uint64_t new_size);
- void OnDestroyTrackingGroup(GpuMemoryTrackingGroup* tracking_group);
- bool EnsureGPUMemoryAvailable(uint64_t size_needed);
-
- GpuChannelManager* channel_manager_;
-
- // All context groups' tracking structures
- TrackingGroupMap tracking_groups_;
-
- // The current total memory usage, and historical maximum memory usage
- uint64_t bytes_allocated_current_;
- uint64_t bytes_allocated_historical_max_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuMemoryManager);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_GPU_MEMORY_MANAGER_H_
diff --git a/chromium/content/common/gpu/gpu_memory_tracking.cc b/chromium/content/common/gpu/gpu_memory_tracking.cc
deleted file mode 100644
index 6fa447b5b87..00000000000
--- a/chromium/content/common/gpu/gpu_memory_tracking.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/gpu_memory_tracking.h"
-
-#include "content/common/gpu/gpu_memory_manager.h"
-
-namespace content {
-
-GpuMemoryTrackingGroup::GpuMemoryTrackingGroup(
- base::ProcessId pid,
- gpu::gles2::MemoryTracker* memory_tracker,
- GpuMemoryManager* memory_manager)
- : pid_(pid),
- size_(0),
- hibernated_(false),
- memory_tracker_(memory_tracker),
- memory_manager_(memory_manager) {
-}
-
-GpuMemoryTrackingGroup::~GpuMemoryTrackingGroup() {
- memory_manager_->OnDestroyTrackingGroup(this);
-}
-
-void GpuMemoryTrackingGroup::TrackMemoryAllocatedChange(uint64_t old_size,
- uint64_t new_size) {
- memory_manager_->TrackMemoryAllocatedChange(
- this, old_size, new_size);
-}
-
-bool GpuMemoryTrackingGroup::EnsureGPUMemoryAvailable(uint64_t size_needed) {
- return memory_manager_->EnsureGPUMemoryAvailable(size_needed);
-}
-
-
-} // namespace content
diff --git a/chromium/content/common/gpu/gpu_memory_tracking.h b/chromium/content/common/gpu/gpu_memory_tracking.h
deleted file mode 100644
index 28892832f96..00000000000
--- a/chromium/content/common/gpu/gpu_memory_tracking.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_GPU_MEMORY_TRACKING_H_
-#define CONTENT_COMMON_GPU_GPU_MEMORY_TRACKING_H_
-
-#include <stdint.h>
-
-#include "base/process/process.h"
-#include "content/common/content_export.h"
-#include "gpu/command_buffer/service/memory_tracking.h"
-
-namespace content {
-
-class GpuMemoryManager;
-
-// All decoders in a context group point to a single GpuMemoryTrackingGroup,
-// which tracks GPU resource consumption for the entire context group.
-class CONTENT_EXPORT GpuMemoryTrackingGroup {
- public:
- ~GpuMemoryTrackingGroup();
- void TrackMemoryAllocatedChange(uint64_t old_size, uint64_t new_size);
- bool EnsureGPUMemoryAvailable(uint64_t size_needed);
- base::ProcessId GetPid() const {
- return pid_;
- }
- uint64_t GetSize() const { return size_; }
- gpu::gles2::MemoryTracker* GetMemoryTracker() const {
- return memory_tracker_;
- }
-
- private:
- friend class GpuMemoryManager;
-
- GpuMemoryTrackingGroup(base::ProcessId pid,
- gpu::gles2::MemoryTracker* memory_tracker,
- GpuMemoryManager* memory_manager);
-
- base::ProcessId pid_;
- uint64_t size_;
-
- // Set and used only during the Manage function, to determine which
- // non-surface clients should be hibernated.
- bool hibernated_;
-
- gpu::gles2::MemoryTracker* memory_tracker_;
- GpuMemoryManager* memory_manager_;
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_GPU_MEMORY_TRACKING_H_
diff --git a/chromium/content/common/gpu/gpu_memory_uma_stats.h b/chromium/content/common/gpu/gpu_memory_uma_stats.h
deleted file mode 100644
index 15d874f195c..00000000000
--- a/chromium/content/common/gpu/gpu_memory_uma_stats.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_GPU_MEMORY_UMA_STATS_H_
-#define CONTENT_COMMON_GPU_GPU_MEMORY_UMA_STATS_H_
-
-#include <stddef.h>
-
-namespace content {
-
-// Memory usage statistics send periodically to the browser process to report
-// in UMA histograms if the GPU process crashes.
-struct GPUMemoryUmaStats {
- GPUMemoryUmaStats()
- : bytes_allocated_current(0),
- bytes_allocated_max(0),
- context_group_count(0) {
- }
-
- // The number of bytes currently allocated.
- size_t bytes_allocated_current;
-
- // The maximum number of bytes ever allocated at once.
- size_t bytes_allocated_max;
-
- // The number of context groups.
- size_t context_group_count;
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_GPU_MEMORY_UMA_STATS_H_
diff --git a/chromium/content/common/gpu/gpu_messages.h b/chromium/content/common/gpu/gpu_messages.h
deleted file mode 100644
index cfe01a347a7..00000000000
--- a/chromium/content/common/gpu/gpu_messages.h
+++ /dev/null
@@ -1,878 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Multiply-included message file, hence no include guard here, but see below
-// for a much smaller-than-usual include guard section.
-
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#include "base/memory/shared_memory.h"
-#include "build/build_config.h"
-#include "content/common/content_export.h"
-#include "content/common/content_param_traits.h"
-#include "content/common/gpu/gpu_memory_uma_stats.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
-#include "content/common/gpu/gpu_result_codes.h"
-#include "content/common/gpu/gpu_stream_priority.h"
-#include "content/public/common/common_param_traits.h"
-#include "content/public/common/gpu_memory_stats.h"
-#include "gpu/command_buffer/common/capabilities.h"
-#include "gpu/command_buffer/common/command_buffer.h"
-#include "gpu/command_buffer/common/constants.h"
-#include "gpu/command_buffer/common/gpu_memory_allocation.h"
-#include "gpu/command_buffer/common/mailbox.h"
-#include "gpu/command_buffer/common/sync_token.h"
-#include "gpu/command_buffer/common/value_state.h"
-#include "gpu/config/gpu_info.h"
-#include "gpu/ipc/gpu_command_buffer_traits.h"
-#include "ipc/ipc_channel_handle.h"
-#include "ipc/ipc_message_macros.h"
-#include "media/base/decrypt_config.h"
-#include "media/base/video_types.h"
-#include "media/video/jpeg_decode_accelerator.h"
-#include "media/video/video_decode_accelerator.h"
-#include "media/video/video_encode_accelerator.h"
-#include "ui/events/latency_info.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/gpu_memory_buffer.h"
-#include "ui/gfx/ipc/gfx_param_traits.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gfx/swap_result.h"
-#include "ui/gl/gpu_preference.h"
-
-#if defined(OS_ANDROID)
-#include "content/common/android/surface_texture_peer.h"
-#elif defined(OS_MACOSX)
-#include "ui/base/cocoa/remote_layer_api.h"
-#include "ui/gfx/mac/io_surface.h"
-#endif
-
-#undef IPC_MESSAGE_EXPORT
-#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
-
-#define IPC_MESSAGE_START GpuMsgStart
-
-IPC_ENUM_TRAITS_MAX_VALUE(content::CauseForGpuLaunch,
- content::CAUSE_FOR_GPU_LAUNCH_MAX_ENUM - 1)
-IPC_ENUM_TRAITS_MAX_VALUE(content::CreateCommandBufferResult,
- content::CREATE_COMMAND_BUFFER_RESULT_LAST)
-IPC_ENUM_TRAITS_MAX_VALUE(gfx::GpuPreference,
- gfx::GpuPreferenceLast)
-IPC_ENUM_TRAITS_MAX_VALUE(content::GpuStreamPriority,
- content::GpuStreamPriority::LAST)
-IPC_ENUM_TRAITS_MAX_VALUE(gfx::SurfaceType,
- gfx::SURFACE_TYPE_LAST)
-IPC_ENUM_TRAITS_MAX_VALUE(gfx::SwapResult, gfx::SwapResult::SWAP_RESULT_LAST)
-IPC_ENUM_TRAITS_MAX_VALUE(gpu::MemoryAllocation::PriorityCutoff,
- gpu::MemoryAllocation::CUTOFF_LAST)
-IPC_ENUM_TRAITS_MAX_VALUE(gpu::error::ContextLostReason,
- gpu::error::kContextLostReasonLast)
-IPC_ENUM_TRAITS_MAX_VALUE(media::JpegDecodeAccelerator::Error,
- media::JpegDecodeAccelerator::LARGEST_ERROR_ENUM)
-IPC_ENUM_TRAITS_MAX_VALUE(media::VideoEncodeAccelerator::Error,
- media::VideoEncodeAccelerator::kErrorMax)
-IPC_ENUM_TRAITS_MIN_MAX_VALUE(media::VideoCodecProfile,
- media::VIDEO_CODEC_PROFILE_MIN,
- media::VIDEO_CODEC_PROFILE_MAX)
-IPC_ENUM_TRAITS_MIN_MAX_VALUE(gpu::CollectInfoResult,
- gpu::kCollectInfoNone,
- gpu::kCollectInfoFatalFailure)
-IPC_ENUM_TRAITS_MIN_MAX_VALUE(gpu::VideoCodecProfile,
- gpu::VIDEO_CODEC_PROFILE_MIN,
- gpu::VIDEO_CODEC_PROFILE_MAX)
-
-IPC_STRUCT_BEGIN(GPUCreateCommandBufferConfig)
- IPC_STRUCT_MEMBER(int32_t, share_group_id)
- IPC_STRUCT_MEMBER(int32_t, stream_id)
- IPC_STRUCT_MEMBER(content::GpuStreamPriority, stream_priority)
- IPC_STRUCT_MEMBER(std::vector<int>, attribs)
- IPC_STRUCT_MEMBER(GURL, active_url)
- IPC_STRUCT_MEMBER(gfx::GpuPreference, gpu_preference)
-IPC_STRUCT_END()
-
-IPC_STRUCT_BEGIN(GpuMsg_EstablishChannel_Params)
- IPC_STRUCT_MEMBER(int, client_id)
- IPC_STRUCT_MEMBER(uint64_t, client_tracing_id)
- IPC_STRUCT_MEMBER(bool, preempts)
- IPC_STRUCT_MEMBER(bool, preempted)
- IPC_STRUCT_MEMBER(bool, allow_future_sync_points)
- IPC_STRUCT_MEMBER(bool, allow_real_time_streams)
-IPC_STRUCT_END()
-
-IPC_STRUCT_BEGIN(GpuMsg_CreateGpuMemoryBuffer_Params)
- IPC_STRUCT_MEMBER(gfx::GpuMemoryBufferId, id)
- IPC_STRUCT_MEMBER(gfx::Size, size)
- IPC_STRUCT_MEMBER(gfx::BufferFormat, format)
- IPC_STRUCT_MEMBER(gfx::BufferUsage, usage)
- IPC_STRUCT_MEMBER(int32_t, client_id)
- IPC_STRUCT_MEMBER(gfx::PluginWindowHandle, surface_handle)
-IPC_STRUCT_END()
-
-IPC_STRUCT_BEGIN(GpuMsg_CreateGpuMemoryBufferFromHandle_Params)
- IPC_STRUCT_MEMBER(gfx::GpuMemoryBufferHandle, handle)
- IPC_STRUCT_MEMBER(gfx::GpuMemoryBufferId, id)
- IPC_STRUCT_MEMBER(gfx::Size, size)
- IPC_STRUCT_MEMBER(gfx::BufferFormat, format)
- IPC_STRUCT_MEMBER(int32_t, client_id)
-IPC_STRUCT_END()
-
-#if defined(OS_MACOSX)
-IPC_STRUCT_BEGIN(GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params)
- IPC_STRUCT_MEMBER(int32_t, surface_id)
- // Only one of ca_context_id or io_surface may be non-0.
- IPC_STRUCT_MEMBER(CAContextID, ca_context_id)
- IPC_STRUCT_MEMBER(gfx::ScopedRefCountedIOSurfaceMachPort, io_surface)
- IPC_STRUCT_MEMBER(int32_t, route_id)
- IPC_STRUCT_MEMBER(gfx::Size, size)
- IPC_STRUCT_MEMBER(float, scale_factor)
- IPC_STRUCT_MEMBER(std::vector<ui::LatencyInfo>, latency_info)
-IPC_STRUCT_END()
-
-IPC_STRUCT_BEGIN(AcceleratedSurfaceMsg_BufferPresented_Params)
- // The vsync parameters, to synchronize presentation with the display.
- IPC_STRUCT_MEMBER(base::TimeTicks, vsync_timebase)
- IPC_STRUCT_MEMBER(base::TimeDelta, vsync_interval)
-IPC_STRUCT_END()
-#endif
-
-IPC_STRUCT_BEGIN(AcceleratedJpegDecoderMsg_Decode_Params)
- IPC_STRUCT_MEMBER(int32_t, input_buffer_id)
- IPC_STRUCT_MEMBER(gfx::Size, coded_size)
- IPC_STRUCT_MEMBER(base::SharedMemoryHandle, input_buffer_handle)
- IPC_STRUCT_MEMBER(uint32_t, input_buffer_size)
- IPC_STRUCT_MEMBER(base::SharedMemoryHandle, output_video_frame_handle)
- IPC_STRUCT_MEMBER(uint32_t, output_buffer_size)
-IPC_STRUCT_END()
-
-IPC_STRUCT_BEGIN(AcceleratedVideoDecoderMsg_Decode_Params)
- IPC_STRUCT_MEMBER(int32_t, bitstream_buffer_id)
- IPC_STRUCT_MEMBER(base::SharedMemoryHandle, buffer_handle)
- IPC_STRUCT_MEMBER(uint32_t, size)
- IPC_STRUCT_MEMBER(base::TimeDelta, presentation_timestamp)
- IPC_STRUCT_MEMBER(std::string, key_id)
- IPC_STRUCT_MEMBER(std::string, iv)
- IPC_STRUCT_MEMBER(std::vector<media::SubsampleEntry>, subsamples)
-IPC_STRUCT_END()
-
-IPC_STRUCT_BEGIN(AcceleratedVideoEncoderMsg_Encode_Params)
- IPC_STRUCT_MEMBER(int32_t, frame_id)
- IPC_STRUCT_MEMBER(base::TimeDelta, timestamp)
- IPC_STRUCT_MEMBER(base::SharedMemoryHandle, buffer_handle)
- IPC_STRUCT_MEMBER(uint32_t, buffer_offset)
- IPC_STRUCT_MEMBER(uint32_t, buffer_size)
- IPC_STRUCT_MEMBER(bool, force_keyframe)
-IPC_STRUCT_END()
-
-IPC_STRUCT_BEGIN(AcceleratedVideoEncoderMsg_Encode_Params2)
- IPC_STRUCT_MEMBER(int32_t, frame_id)
- IPC_STRUCT_MEMBER(base::TimeDelta, timestamp)
- IPC_STRUCT_MEMBER(std::vector<gfx::GpuMemoryBufferHandle>,
- gpu_memory_buffer_handles)
- IPC_STRUCT_MEMBER(gfx::Size, size)
- IPC_STRUCT_MEMBER(bool, force_keyframe)
-IPC_STRUCT_END()
-
-IPC_STRUCT_BEGIN(GPUCommandBufferConsoleMessage)
- IPC_STRUCT_MEMBER(int32_t, id)
- IPC_STRUCT_MEMBER(std::string, message)
-IPC_STRUCT_END()
-
-#if defined(OS_ANDROID)
-IPC_STRUCT_BEGIN(GpuStreamTextureMsg_MatrixChanged_Params)
- IPC_STRUCT_MEMBER(float, m00)
- IPC_STRUCT_MEMBER(float, m01)
- IPC_STRUCT_MEMBER(float, m02)
- IPC_STRUCT_MEMBER(float, m03)
- IPC_STRUCT_MEMBER(float, m10)
- IPC_STRUCT_MEMBER(float, m11)
- IPC_STRUCT_MEMBER(float, m12)
- IPC_STRUCT_MEMBER(float, m13)
- IPC_STRUCT_MEMBER(float, m20)
- IPC_STRUCT_MEMBER(float, m21)
- IPC_STRUCT_MEMBER(float, m22)
- IPC_STRUCT_MEMBER(float, m23)
- IPC_STRUCT_MEMBER(float, m30)
- IPC_STRUCT_MEMBER(float, m31)
- IPC_STRUCT_MEMBER(float, m32)
- IPC_STRUCT_MEMBER(float, m33)
-IPC_STRUCT_END()
-#endif
-
-IPC_STRUCT_BEGIN(GpuCommandBufferMsg_CreateImage_Params)
- IPC_STRUCT_MEMBER(int32_t, id)
- IPC_STRUCT_MEMBER(gfx::GpuMemoryBufferHandle, gpu_memory_buffer)
- IPC_STRUCT_MEMBER(gfx::Size, size)
- IPC_STRUCT_MEMBER(gfx::BufferFormat, format)
- IPC_STRUCT_MEMBER(uint32_t, internal_format)
- IPC_STRUCT_MEMBER(uint64_t, image_release_count)
-IPC_STRUCT_END()
-
-IPC_STRUCT_TRAITS_BEGIN(gpu::DxDiagNode)
- IPC_STRUCT_TRAITS_MEMBER(values)
- IPC_STRUCT_TRAITS_MEMBER(children)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(gpu::GPUInfo::GPUDevice)
- IPC_STRUCT_TRAITS_MEMBER(vendor_id)
- IPC_STRUCT_TRAITS_MEMBER(device_id)
- IPC_STRUCT_TRAITS_MEMBER(active)
- IPC_STRUCT_TRAITS_MEMBER(vendor_string)
- IPC_STRUCT_TRAITS_MEMBER(device_string)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(media::VideoDecodeAccelerator::Config)
- IPC_STRUCT_TRAITS_MEMBER(profile)
- IPC_STRUCT_TRAITS_MEMBER(is_encrypted)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(gpu::VideoDecodeAcceleratorSupportedProfile)
- IPC_STRUCT_TRAITS_MEMBER(profile)
- IPC_STRUCT_TRAITS_MEMBER(max_resolution)
- IPC_STRUCT_TRAITS_MEMBER(min_resolution)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(gpu::VideoDecodeAcceleratorCapabilities)
- IPC_STRUCT_TRAITS_MEMBER(supported_profiles)
- IPC_STRUCT_TRAITS_MEMBER(flags)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(gpu::VideoEncodeAcceleratorSupportedProfile)
- IPC_STRUCT_TRAITS_MEMBER(profile)
- IPC_STRUCT_TRAITS_MEMBER(max_resolution)
- IPC_STRUCT_TRAITS_MEMBER(max_framerate_numerator)
- IPC_STRUCT_TRAITS_MEMBER(max_framerate_denominator)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(gpu::GPUInfo)
- IPC_STRUCT_TRAITS_MEMBER(initialization_time)
- IPC_STRUCT_TRAITS_MEMBER(optimus)
- IPC_STRUCT_TRAITS_MEMBER(amd_switchable)
- IPC_STRUCT_TRAITS_MEMBER(lenovo_dcute)
- IPC_STRUCT_TRAITS_MEMBER(gpu)
- IPC_STRUCT_TRAITS_MEMBER(secondary_gpus)
- IPC_STRUCT_TRAITS_MEMBER(adapter_luid)
- IPC_STRUCT_TRAITS_MEMBER(driver_vendor)
- IPC_STRUCT_TRAITS_MEMBER(driver_version)
- IPC_STRUCT_TRAITS_MEMBER(driver_date)
- IPC_STRUCT_TRAITS_MEMBER(pixel_shader_version)
- IPC_STRUCT_TRAITS_MEMBER(vertex_shader_version)
- IPC_STRUCT_TRAITS_MEMBER(max_msaa_samples)
- IPC_STRUCT_TRAITS_MEMBER(machine_model_name)
- IPC_STRUCT_TRAITS_MEMBER(machine_model_version)
- IPC_STRUCT_TRAITS_MEMBER(gl_version)
- IPC_STRUCT_TRAITS_MEMBER(gl_vendor)
- IPC_STRUCT_TRAITS_MEMBER(gl_renderer)
- IPC_STRUCT_TRAITS_MEMBER(gl_extensions)
- IPC_STRUCT_TRAITS_MEMBER(gl_ws_vendor)
- IPC_STRUCT_TRAITS_MEMBER(gl_ws_version)
- IPC_STRUCT_TRAITS_MEMBER(gl_ws_extensions)
- IPC_STRUCT_TRAITS_MEMBER(gl_reset_notification_strategy)
- IPC_STRUCT_TRAITS_MEMBER(can_lose_context)
- IPC_STRUCT_TRAITS_MEMBER(software_rendering)
- IPC_STRUCT_TRAITS_MEMBER(direct_rendering)
- IPC_STRUCT_TRAITS_MEMBER(sandboxed)
- IPC_STRUCT_TRAITS_MEMBER(process_crash_count)
- IPC_STRUCT_TRAITS_MEMBER(in_process_gpu)
- IPC_STRUCT_TRAITS_MEMBER(basic_info_state)
- IPC_STRUCT_TRAITS_MEMBER(context_info_state)
-#if defined(OS_WIN)
- IPC_STRUCT_TRAITS_MEMBER(dx_diagnostics_info_state)
- IPC_STRUCT_TRAITS_MEMBER(dx_diagnostics)
-#endif
- IPC_STRUCT_TRAITS_MEMBER(video_decode_accelerator_capabilities)
- IPC_STRUCT_TRAITS_MEMBER(video_encode_accelerator_supported_profiles)
- IPC_STRUCT_TRAITS_MEMBER(jpeg_decode_accelerator_supported)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(content::GPUVideoMemoryUsageStats::ProcessStats)
- IPC_STRUCT_TRAITS_MEMBER(video_memory)
- IPC_STRUCT_TRAITS_MEMBER(has_duplicates)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(content::GPUVideoMemoryUsageStats)
- IPC_STRUCT_TRAITS_MEMBER(process_map)
- IPC_STRUCT_TRAITS_MEMBER(bytes_allocated)
- IPC_STRUCT_TRAITS_MEMBER(bytes_allocated_historical_max)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(content::GPUMemoryUmaStats)
- IPC_STRUCT_TRAITS_MEMBER(bytes_allocated_current)
- IPC_STRUCT_TRAITS_MEMBER(bytes_allocated_max)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(gpu::MemoryAllocation)
- IPC_STRUCT_TRAITS_MEMBER(bytes_limit_when_visible)
- IPC_STRUCT_TRAITS_MEMBER(priority_cutoff_when_visible)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(gfx::GLSurfaceHandle)
- IPC_STRUCT_TRAITS_MEMBER(handle)
- IPC_STRUCT_TRAITS_MEMBER(transport_type)
-IPC_STRUCT_TRAITS_END()
-
-IPC_STRUCT_TRAITS_BEGIN(media::SubsampleEntry)
- IPC_STRUCT_TRAITS_MEMBER(clear_bytes)
- IPC_STRUCT_TRAITS_MEMBER(cypher_bytes)
-IPC_STRUCT_TRAITS_END()
-
-//------------------------------------------------------------------------------
-// GPU Messages
-// These are messages from the browser to the GPU process.
-
-// Tells the GPU process to initialize itself. The browser explicitly
-// requests this be done so that we are guaranteed that the channel is set
-// up between the browser and GPU process before doing any work that might
-// potentially crash the GPU process. Detection of the child process
-// exiting abruptly is predicated on having the IPC channel set up.
-IPC_MESSAGE_CONTROL0(GpuMsg_Initialize)
-
-// Tells the GPU process to shutdown itself.
-IPC_MESSAGE_CONTROL0(GpuMsg_Finalize)
-
-// Tells the GPU process to create a new channel for communication with a
-// given client. The channel name is returned in a
-// GpuHostMsg_ChannelEstablished message. The client ID is passed so that
-// the GPU process reuses an existing channel to that process if it exists.
-// This ID is a unique opaque identifier generated by the browser process.
-// The client_tracing_id is a unique ID used for the purposes of tracing.
-IPC_MESSAGE_CONTROL1(GpuMsg_EstablishChannel,
- GpuMsg_EstablishChannel_Params /* params */)
-
-// Tells the GPU process to close the channel identified by IPC channel
-// handle. If no channel can be identified, do nothing.
-IPC_MESSAGE_CONTROL1(GpuMsg_CloseChannel,
- IPC::ChannelHandle /* channel_handle */)
-
-// Tells the GPU process to create a new command buffer that renders directly
-// to a native view. A corresponding GpuCommandBufferStub is created.
-IPC_MESSAGE_CONTROL4(GpuMsg_CreateViewCommandBuffer,
- gfx::GLSurfaceHandle, /* compositing_surface */
- int32_t, /* client_id */
- GPUCreateCommandBufferConfig, /* init_params */
- int32_t /* route_id */)
-
-// Tells the GPU process to create a new gpu memory buffer.
-IPC_MESSAGE_CONTROL1(GpuMsg_CreateGpuMemoryBuffer,
- GpuMsg_CreateGpuMemoryBuffer_Params)
-
-// Tells the GPU process to create a new gpu memory buffer from an existing
-// handle.
-IPC_MESSAGE_CONTROL1(GpuMsg_CreateGpuMemoryBufferFromHandle,
- GpuMsg_CreateGpuMemoryBufferFromHandle_Params)
-
-// Tells the GPU process to destroy buffer.
-IPC_MESSAGE_CONTROL3(GpuMsg_DestroyGpuMemoryBuffer,
- gfx::GpuMemoryBufferId, /* id */
- int32_t, /* client_id */
- gpu::SyncToken /* sync_token */)
-
-// Create and initialize a hardware jpeg decoder using the specified route_id.
-// Created decoders should be freed with AcceleratedJpegDecoderMsg_Destroy when
-// no longer needed.
-IPC_SYNC_MESSAGE_CONTROL1_1(GpuMsg_CreateJpegDecoder,
- int32_t /* route_id */,
- bool /* succeeded */)
-
-// Tells the GPU process to create a context for collecting graphics card
-// information.
-IPC_MESSAGE_CONTROL0(GpuMsg_CollectGraphicsInfo)
-
-// Tells the GPU process to report video_memory information for the task manager
-IPC_MESSAGE_CONTROL0(GpuMsg_GetVideoMemoryUsageStats)
-
-#if defined(OS_MACOSX)
-// Tells the GPU process that the browser process has handled the swap
-// buffers or post sub-buffer request.
-IPC_MESSAGE_ROUTED1(AcceleratedSurfaceMsg_BufferPresented,
- AcceleratedSurfaceMsg_BufferPresented_Params)
-#endif
-
-#if defined(OS_ANDROID)
-// Tells the GPU process to wake up the GPU because we're about to draw.
-IPC_MESSAGE_CONTROL0(GpuMsg_WakeUpGpu)
-#endif
-
-// Tells the GPU process to remove all contexts.
-IPC_MESSAGE_CONTROL0(GpuMsg_Clean)
-
-// Tells the GPU process to crash.
-IPC_MESSAGE_CONTROL0(GpuMsg_Crash)
-
-// Tells the GPU process to hang.
-IPC_MESSAGE_CONTROL0(GpuMsg_Hang)
-
-// Tells the GPU process to disable the watchdog thread.
-IPC_MESSAGE_CONTROL0(GpuMsg_DisableWatchdog)
-
-// Tells the GPU process that the browser has seen a GPU switch.
-IPC_MESSAGE_CONTROL0(GpuMsg_GpuSwitched)
-
-// Sends an input event to the gpu service.
-IPC_MESSAGE_CONTROL3(GpuMsg_UpdateValueState,
- int, /* client_id */
- unsigned int, /* target */
- gpu::ValueState /* valuestate */)
-
-//------------------------------------------------------------------------------
-// GPU Host Messages
-// These are messages to the browser.
-
-// A renderer sends this when it wants to create a connection to the GPU
-// process. The browser will create the GPU process if necessary, and will
-// return a handle to the channel via a GpuChannelEstablished message.
-IPC_SYNC_MESSAGE_CONTROL1_3(GpuHostMsg_EstablishGpuChannel,
- content::CauseForGpuLaunch,
- int /* client id */,
- IPC::ChannelHandle /* handle to channel */,
- gpu::GPUInfo /* stats about GPU process*/)
-
-// Response from GPU to a GputMsg_Initialize message.
-IPC_MESSAGE_CONTROL2(GpuHostMsg_Initialized,
- bool /* result */,
- ::gpu::GPUInfo /* gpu_info */)
-
-// Response from GPU to a GpuHostMsg_EstablishChannel message.
-IPC_MESSAGE_CONTROL1(GpuHostMsg_ChannelEstablished,
- IPC::ChannelHandle /* channel_handle */)
-
-// Message from GPU to notify to destroy the channel.
-IPC_MESSAGE_CONTROL1(GpuHostMsg_DestroyChannel, int32_t /* client_id */)
-
-// Message to cache the given shader information.
-IPC_MESSAGE_CONTROL3(GpuHostMsg_CacheShader,
- int32_t /* client_id */,
- std::string /* key */,
- std::string /* shader */)
-
-// Message to the GPU that a shader was loaded from disk.
-IPC_MESSAGE_CONTROL1(GpuMsg_LoadedShader,
- std::string /* encoded shader */)
-
-// Respond from GPU to a GpuMsg_CreateViewCommandBuffer message.
-IPC_MESSAGE_CONTROL1(GpuHostMsg_CommandBufferCreated,
- content::CreateCommandBufferResult /* result */)
-
-// Response from GPU to a GpuMsg_CreateGpuMemoryBuffer message.
-IPC_MESSAGE_CONTROL1(GpuHostMsg_GpuMemoryBufferCreated,
- gfx::GpuMemoryBufferHandle /* handle */)
-
-// Response from GPU to a GpuMsg_CollectGraphicsInfo.
-IPC_MESSAGE_CONTROL1(GpuHostMsg_GraphicsInfoCollected,
- gpu::GPUInfo /* GPU logging stats */)
-
-// Response from GPU to a GpuMsg_GetVideoMemory.
-IPC_MESSAGE_CONTROL1(GpuHostMsg_VideoMemoryUsageStats,
- content::GPUVideoMemoryUsageStats /* GPU memory stats */)
-
-// Message from GPU to add a GPU log message to the about:gpu page.
-IPC_MESSAGE_CONTROL3(GpuHostMsg_OnLogMessage,
- int /*severity*/,
- std::string /* header */,
- std::string /* message */)
-
-
-#if defined(OS_MACOSX)
-// Tells the browser that an accelerated surface has swapped.
-IPC_MESSAGE_CONTROL1(GpuHostMsg_AcceleratedSurfaceBuffersSwapped,
- GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params)
-#endif
-
-#if defined(OS_WIN)
-IPC_MESSAGE_CONTROL2(GpuHostMsg_AcceleratedSurfaceCreatedChildWindow,
- gfx::PluginWindowHandle /* parent_window */,
- gfx::PluginWindowHandle /* child_window */)
-#endif
-
-IPC_MESSAGE_CONTROL1(GpuHostMsg_DidCreateOffscreenContext,
- GURL /* url */)
-
-IPC_MESSAGE_CONTROL3(GpuHostMsg_DidLoseContext,
- bool /* offscreen */,
- gpu::error::ContextLostReason /* reason */,
- GURL /* url */)
-
-IPC_MESSAGE_CONTROL1(GpuHostMsg_DidDestroyOffscreenContext,
- GURL /* url */)
-
-// Tells the browser about GPU memory usage statistics for UMA logging.
-IPC_MESSAGE_CONTROL1(GpuHostMsg_GpuMemoryUmaStats,
- content::GPUMemoryUmaStats /* GPU memory UMA stats */)
-
-// Tells the browser that a context has subscribed to a new target and
-// the browser should start sending the corresponding information
-IPC_MESSAGE_CONTROL2(GpuHostMsg_AddSubscription,
- int32_t /* client_id */,
- unsigned int /* target */)
-
-// Tells the browser that no contexts are subscribed to the target anymore
-// so the browser should stop sending the corresponding information
-IPC_MESSAGE_CONTROL2(GpuHostMsg_RemoveSubscription,
- int32_t /* client_id */,
- unsigned int /* target */)
-
-//------------------------------------------------------------------------------
-// GPU Channel Messages
-// These are messages from a renderer process to the GPU process.
-
-// Tells the GPU process to create a new command buffer that renders to an
-// offscreen frame buffer.
-IPC_SYNC_MESSAGE_CONTROL3_1(GpuChannelMsg_CreateOffscreenCommandBuffer,
- gfx::Size, /* size */
- GPUCreateCommandBufferConfig, /* init_params */
- int32_t, /* route_id */
- bool /* succeeded */)
-
-// The CommandBufferProxy sends this to the GpuCommandBufferStub in its
-// destructor, so that the stub deletes the actual CommandBufferService
-// object that it's hosting.
-IPC_SYNC_MESSAGE_CONTROL1_0(GpuChannelMsg_DestroyCommandBuffer,
- int32_t /* instance_id */)
-
-// Simple NOP message which can be used as fence to ensure all previous sent
-// messages have been received.
-IPC_SYNC_MESSAGE_CONTROL0_0(GpuChannelMsg_Nop)
-
-#if defined(OS_ANDROID)
-//------------------------------------------------------------------------------
-// Stream Texture Messages
-// Tells the GPU process create and send the java surface texture object to
-// the renderer process through the binder thread.
-IPC_MESSAGE_ROUTED2(GpuStreamTextureMsg_EstablishPeer,
- int32_t, /* primary_id */
- int32_t /* secondary_id */)
-
-// Tells the GPU process to set the size of StreamTexture from the given
-// stream Id.
-IPC_MESSAGE_ROUTED1(GpuStreamTextureMsg_SetSize,
- gfx::Size /* size */)
-
-// Tells the service-side instance to start sending frame available
-// notifications.
-IPC_MESSAGE_ROUTED0(GpuStreamTextureMsg_StartListening)
-
-// Inform the renderer that a new frame is available.
-IPC_MESSAGE_ROUTED0(GpuStreamTextureMsg_FrameAvailable)
-
-// Inform the renderer process that the transform matrix has changed.
-IPC_MESSAGE_ROUTED1(GpuStreamTextureMsg_MatrixChanged,
- GpuStreamTextureMsg_MatrixChanged_Params /* params */)
-#endif
-
-//------------------------------------------------------------------------------
-// GPU Command Buffer Messages
-// These are messages between a renderer process to the GPU process relating to
-// a single OpenGL context.
-// Initialize a command buffer with the given number of command entries.
-// Returns the shared memory handle for the command buffer mapped to the
-// calling process.
-IPC_SYNC_MESSAGE_ROUTED1_2(GpuCommandBufferMsg_Initialize,
- base::SharedMemoryHandle /* shared_state */,
- bool /* result */,
- gpu::Capabilities /* capabilities */)
-
-// Sets the shared memory buffer used for commands.
-IPC_SYNC_MESSAGE_ROUTED1_0(GpuCommandBufferMsg_SetGetBuffer,
- int32_t /* shm_id */)
-
-// Produces the front buffer into a mailbox. This allows another context to draw
-// the output of this context.
-IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_ProduceFrontBuffer,
- gpu::Mailbox /* mailbox */)
-
-// Wait until the token is in a specific range, inclusive.
-IPC_SYNC_MESSAGE_ROUTED2_1(GpuCommandBufferMsg_WaitForTokenInRange,
- int32_t /* start */,
- int32_t /* end */,
- gpu::CommandBuffer::State /* state */)
-
-// Wait until the get offset is in a specific range, inclusive.
-IPC_SYNC_MESSAGE_ROUTED2_1(GpuCommandBufferMsg_WaitForGetOffsetInRange,
- int32_t /* start */,
- int32_t /* end */,
- gpu::CommandBuffer::State /* state */)
-
-// Asynchronously synchronize the put and get offsets of both processes.
-// Caller passes its current put offset. Current state (including get offset)
-// is returned in shared memory. The input latency info for the current
-// frame is also sent to the GPU process.
-IPC_MESSAGE_ROUTED3(GpuCommandBufferMsg_AsyncFlush,
- int32_t /* put_offset */,
- uint32_t /* flush_count */,
- std::vector<ui::LatencyInfo> /* latency_info */)
-
-// Sent by the GPU process to display messages in the console.
-IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_ConsoleMsg,
- GPUCommandBufferConsoleMessage /* msg */)
-
-// Register an existing shared memory transfer buffer. The id that can be
-// used to identify the transfer buffer from a command buffer.
-IPC_MESSAGE_ROUTED3(GpuCommandBufferMsg_RegisterTransferBuffer,
- int32_t /* id */,
- base::SharedMemoryHandle /* transfer_buffer */,
- uint32_t /* size */)
-
-// Destroy a previously created transfer buffer.
-IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_DestroyTransferBuffer, int32_t /* id */)
-
-// Create and initialize a hardware video decoder using the specified route_id.
-// Created decoders should be freed with AcceleratedVideoDecoderMsg_Destroy when
-// no longer needed.
-IPC_SYNC_MESSAGE_ROUTED2_1(GpuCommandBufferMsg_CreateVideoDecoder,
- media::VideoDecodeAccelerator::Config, /* config */
- int32_t, /* route_id */
- bool /* succeeded */)
-
-// Create and initialize a hardware video encoder using the specified route_id.
-// Created encoders should be freed with AcceleratedVideoEncoderMsg_Destroy when
-// no longer needed.
-IPC_SYNC_MESSAGE_ROUTED5_1(GpuCommandBufferMsg_CreateVideoEncoder,
- media::VideoPixelFormat /* input_format */,
- gfx::Size /* input_visible_size */,
- media::VideoCodecProfile /* output_profile */,
- uint32_t /* initial_bitrate */,
- int32_t, /* route_id */
- bool /* succeeded */)
-
-// Tells the proxy that there was an error and the command buffer had to be
-// destroyed for some reason.
-IPC_MESSAGE_ROUTED2(GpuCommandBufferMsg_Destroyed,
- gpu::error::ContextLostReason, /* reason */
- gpu::error::Error /* error */)
-
-// Tells the browser that SwapBuffers returned and passes latency info
-IPC_MESSAGE_ROUTED2(GpuCommandBufferMsg_SwapBuffersCompleted,
- std::vector<ui::LatencyInfo> /* latency_info */,
- gfx::SwapResult /* result */)
-
-// Tells the browser about updated parameters for vsync alignment.
-IPC_MESSAGE_ROUTED2(GpuCommandBufferMsg_UpdateVSyncParameters,
- base::TimeTicks /* timebase */,
- base::TimeDelta /* interval */)
-
-// Inserts a sync point into the channel. This is handled on the IO thread, so
-// can be expected to be reasonably fast, but the sync point is actually
-// retired in order with respect to the other calls. The sync point is shared
-// across channels.
-IPC_SYNC_MESSAGE_ROUTED1_1(GpuCommandBufferMsg_InsertSyncPoint,
- bool /* retire */,
- uint32_t /* sync_point */)
-
-// Retires the sync point.
-IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_RetireSyncPoint,
- uint32_t /* sync_point */)
-
-// Makes this command buffer signal when a sync point is reached, by sending
-// back a GpuCommandBufferMsg_SignalSyncPointAck message with the same
-// signal_id.
-IPC_MESSAGE_ROUTED2(GpuCommandBufferMsg_SignalSyncPoint,
- uint32_t /* sync_point */,
- uint32_t /* signal_id */)
-
-IPC_MESSAGE_ROUTED2(GpuCommandBufferMsg_SignalSyncToken,
- gpu::SyncToken /* sync_token */,
- uint32_t /* signal_id */)
-
-// Makes this command buffer signal when a query is reached, by sending
-// back a GpuCommandBufferMsg_SignalSyncPointAck message with the same
-// signal_id.
-IPC_MESSAGE_ROUTED2(GpuCommandBufferMsg_SignalQuery,
- uint32_t /* query */,
- uint32_t /* signal_id */)
-
-// Response to SignalSyncPoint, SignalSyncToken, and SignalQuery.
-IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_SignalAck, uint32_t /* signal_id */)
-
-// Create an image from an existing gpu memory buffer. The id that can be
-// used to identify the image from a command buffer.
-IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_CreateImage,
- GpuCommandBufferMsg_CreateImage_Params /* params */)
-
-// Destroy a previously created image.
-IPC_MESSAGE_ROUTED1(GpuCommandBufferMsg_DestroyImage, int32_t /* id */)
-
-// Attaches an external image stream to the client texture.
-IPC_SYNC_MESSAGE_ROUTED2_1(GpuCommandBufferMsg_CreateStreamTexture,
- uint32_t, /* client_texture_id */
- int32_t, /* stream_id */
- bool /* succeeded */)
-
-//------------------------------------------------------------------------------
-// Accelerated Video Decoder Messages
-// These messages are sent from Renderer process to GPU process.
-
-// Set a CDM on the decoder to handle encrypted buffers.
-IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderMsg_SetCdm,
- int32_t) /* CDM ID */
-
-// Send input buffer for decoding.
-IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderMsg_Decode,
- AcceleratedVideoDecoderMsg_Decode_Params)
-
-// Give the texture IDs for the textures the decoder will use for output.
-IPC_MESSAGE_ROUTED2(AcceleratedVideoDecoderMsg_AssignPictureBuffers,
- std::vector<int32_t>, /* Picture buffer ID */
- std::vector<uint32_t>) /* Texture ID */
-
-// Send from Renderer process to the GPU process to recycle the given picture
-// buffer for further decoding.
-IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderMsg_ReusePictureBuffer,
- int32_t) /* Picture buffer ID */
-
-// Send flush request to the decoder.
-IPC_MESSAGE_ROUTED0(AcceleratedVideoDecoderMsg_Flush)
-
-// Send reset request to the decoder.
-IPC_MESSAGE_ROUTED0(AcceleratedVideoDecoderMsg_Reset)
-
-// Send destroy request to the decoder.
-IPC_MESSAGE_ROUTED0(AcceleratedVideoDecoderMsg_Destroy)
-
-//------------------------------------------------------------------------------
-// Accelerated Video Decoder Host Messages
-// These messages are sent from GPU process to Renderer process.
-// Inform AcceleratedVideoDecoderHost that AcceleratedVideoDecoder has been
-// created.
-
-// Notify the CDM setting result.
-IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderHostMsg_CdmAttached,
- bool) /* success */
-
-// Accelerated video decoder has consumed input buffer from transfer buffer.
-IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderHostMsg_BitstreamBufferProcessed,
- int32_t) /* Processed buffer ID */
-
-// Allocate video frames for output of the hardware video decoder.
-IPC_MESSAGE_ROUTED3(AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers,
- int32_t, /* Number of video frames to generate */
- gfx::Size, /* Requested size of buffer */
- uint32_t) /* Texture target */
-
-// Decoder reports that a picture is ready and buffer does not need to be passed
-// back to the decoder.
-IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderHostMsg_DismissPictureBuffer,
- int32_t) /* Picture buffer ID */
-
-// Decoder reports that a picture is ready.
-IPC_MESSAGE_ROUTED4(AcceleratedVideoDecoderHostMsg_PictureReady,
- int32_t, /* Picture buffer ID */
- int32_t, /* Bitstream buffer ID */
- gfx::Rect, /* Visible rectangle */
- bool) /* Buffer is HW overlay capable */
-
-// Confirm decoder has been flushed.
-IPC_MESSAGE_ROUTED0(AcceleratedVideoDecoderHostMsg_FlushDone)
-
-// Confirm decoder has been reset.
-IPC_MESSAGE_ROUTED0(AcceleratedVideoDecoderHostMsg_ResetDone)
-
-// Video decoder has encountered an error.
-IPC_MESSAGE_ROUTED1(AcceleratedVideoDecoderHostMsg_ErrorNotification,
- uint32_t) /* Error ID */
-
-//------------------------------------------------------------------------------
-// Accelerated Video Encoder Messages
-// These messages are sent from the Renderer process to GPU process.
-
-// Queue a video frame to the encoder to encode. |frame_id| will be returned
-// by AcceleratedVideoEncoderHostMsg_NotifyInputDone.
-IPC_MESSAGE_ROUTED1(AcceleratedVideoEncoderMsg_Encode,
- AcceleratedVideoEncoderMsg_Encode_Params)
-
-// Queue a GpuMemoryBuffer backed video frame to the encoder to encode.
-// |frame_id| will be returned by
-// AcceleratedVideoEncoderHostMsg_NotifyInputDone.
-IPC_MESSAGE_ROUTED1(AcceleratedVideoEncoderMsg_Encode2,
- AcceleratedVideoEncoderMsg_Encode_Params2)
-
-// Queue a buffer to the encoder for use in returning output. |buffer_id| will
-// be returned by AcceleratedVideoEncoderHostMsg_BitstreamBufferReady.
-IPC_MESSAGE_ROUTED3(AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer,
- int32_t /* buffer_id */,
- base::SharedMemoryHandle /* buffer_handle */,
- uint32_t /* buffer_size */)
-
-// Request a runtime encoding parameter change.
-IPC_MESSAGE_ROUTED2(AcceleratedVideoEncoderMsg_RequestEncodingParametersChange,
- uint32_t /* bitrate */,
- uint32_t /* framerate */)
-
-//------------------------------------------------------------------------------
-// Accelerated Video Encoder Host Messages
-// These messages are sent from GPU process to Renderer process.
-
-// Notify renderer of the input/output buffer requirements of the encoder.
-IPC_MESSAGE_ROUTED3(AcceleratedVideoEncoderHostMsg_RequireBitstreamBuffers,
- uint32_t /* input_count */,
- gfx::Size /* input_coded_size */,
- uint32_t /* output_buffer_size */)
-
-// Notify the renderer that the encoder has finished using an input buffer.
-// There is no congruent entry point in the media::VideoEncodeAccelerator
-// interface, in VEA this same done condition is indicated by dropping the
-// reference to the media::VideoFrame passed to VEA::Encode().
-IPC_MESSAGE_ROUTED1(AcceleratedVideoEncoderHostMsg_NotifyInputDone,
- int32_t /* frame_id */)
-
-// Notify the renderer that an output buffer has been filled with encoded data.
-IPC_MESSAGE_ROUTED3(AcceleratedVideoEncoderHostMsg_BitstreamBufferReady,
- int32_t /* bitstream_buffer_id */,
- uint32_t /* payload_size */,
- bool /* key_frame */)
-
-// Report error condition.
-IPC_MESSAGE_ROUTED1(AcceleratedVideoEncoderHostMsg_NotifyError,
- media::VideoEncodeAccelerator::Error /* error */)
-
-// Send destroy request to the encoder.
-IPC_MESSAGE_ROUTED0(AcceleratedVideoEncoderMsg_Destroy)
-
-//------------------------------------------------------------------------------
-// Accelerated JPEG Decoder Messages
-// These messages are sent from the Browser process to GPU process.
-
-// Decode one JPEG image from shared memory |input_buffer_handle| with size
-// |input_buffer_size|. The input buffer is associated with |input_buffer_id|
-// and the size of JPEG image is |coded_size|. Decoded I420 frame data will
-// be put onto shared memory associated with |output_video_frame_handle|
-// with size limit |output_buffer_size|.
-IPC_MESSAGE_ROUTED1(AcceleratedJpegDecoderMsg_Decode,
- AcceleratedJpegDecoderMsg_Decode_Params)
-
-// Send destroy request to the decoder.
-IPC_MESSAGE_ROUTED0(AcceleratedJpegDecoderMsg_Destroy)
-
-//------------------------------------------------------------------------------
-// Accelerated JPEG Decoder Host Messages
-// These messages are sent from the GPU process to Browser process.
-//
-// Report decode status.
-IPC_MESSAGE_ROUTED2(AcceleratedJpegDecoderHostMsg_DecodeAck,
- int32_t, /* bitstream_buffer_id */
- media::JpegDecodeAccelerator::Error /* error */)
-
-#if defined(OS_CHROMEOS)
-//------------------------------------------------------------------------------
-// Arc Video Accelerator Messages
-// These messages are sent from the Browser process to GPU process.
-
-// Tells the GPU process to create a new channel for communication with
-// ArcVideoAccelerator. The channel is returned using
-// GpuHostMsg_ArcVideoAcceleratorChannelCreated message.
-IPC_MESSAGE_CONTROL0(GpuMsg_CreateArcVideoAcceleratorChannel)
-
-// Tells the GPU process to shutdown arc video service and terminate all
-// instances of ArcVideoAccelerator.
-IPC_MESSAGE_CONTROL0(GpuMsg_ShutdownArcVideoService)
-
-//------------------------------------------------------------------------------
-// Arc Video Accelerator Host Messages
-// These messages are sent from the GPU process to Browser process.
-
-// Response from GPU to a GpuMsg_CreateArcVideoAcceleratorChannel message.
-IPC_MESSAGE_CONTROL1(GpuHostMsg_ArcVideoAcceleratorChannelCreated,
- IPC::ChannelHandle /* handle to channel */)
-#endif
diff --git a/chromium/content/common/gpu/gpu_result_codes.h b/chromium/content/common/gpu/gpu_result_codes.h
deleted file mode 100644
index 11f4272a2ae..00000000000
--- a/chromium/content/common/gpu/gpu_result_codes.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_GPU_RESULT_CODES_H_
-#define CONTENT_COMMON_GPU_GPU_RESULT_CODES_H_
-
-namespace content {
-
-enum CreateCommandBufferResult {
- CREATE_COMMAND_BUFFER_SUCCEEDED,
- CREATE_COMMAND_BUFFER_FAILED,
- CREATE_COMMAND_BUFFER_FAILED_AND_CHANNEL_LOST,
- CREATE_COMMAND_BUFFER_RESULT_LAST =
- CREATE_COMMAND_BUFFER_FAILED_AND_CHANNEL_LOST
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_GPU_RESULT_CODES_H_
diff --git a/chromium/content/common/gpu/gpu_stream_priority.h b/chromium/content/common/gpu/gpu_stream_priority.h
deleted file mode 100644
index 089fb97e04e..00000000000
--- a/chromium/content/common/gpu/gpu_stream_priority.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_GPU_STREAM_PRIORITY_H_
-#define CONTENT_COMMON_GPU_GPU_STREAM_PRIORITY_H_
-
-namespace content {
-
-enum class GpuStreamPriority {
- REAL_TIME,
- NORMAL,
- LOW,
- INHERIT,
- LAST = INHERIT
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_GPU_STREAM_PRIORITY_H_
diff --git a/chromium/content/common/gpu/gpu_surface_lookup.cc b/chromium/content/common/gpu/gpu_surface_lookup.cc
deleted file mode 100644
index 61bbc045e5c..00000000000
--- a/chromium/content/common/gpu/gpu_surface_lookup.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/gpu_surface_lookup.h"
-
-#include "base/logging.h"
-
-namespace content {
-namespace {
-GpuSurfaceLookup* g_instance = NULL;
-} // anonymous namespace
-
-// static
-GpuSurfaceLookup* GpuSurfaceLookup::GetInstance() {
- DCHECK(g_instance);
- return g_instance;
-}
-
-// static
-void GpuSurfaceLookup::InitInstance(GpuSurfaceLookup* lookup) {
- DCHECK(!g_instance || !lookup);
- g_instance = lookup;
-}
-
-#if defined(OS_ANDROID)
-gfx::ScopedJavaSurface GpuSurfaceLookup::AcquireJavaSurface(int surface_id) {
- NOTIMPLEMENTED();
- return gfx::ScopedJavaSurface();
-}
-#endif
-
-} // namespace content
diff --git a/chromium/content/common/gpu/gpu_surface_lookup.h b/chromium/content/common/gpu/gpu_surface_lookup.h
deleted file mode 100644
index c47e7e37901..00000000000
--- a/chromium/content/common/gpu/gpu_surface_lookup.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_GPU_SURFACE_LOOKUP_H_
-#define CONTENT_COMMON_GPU_GPU_SURFACE_LOOKUP_H_
-
-#include "base/macros.h"
-#include "content/common/content_export.h"
-#include "ui/gfx/native_widget_types.h"
-
-#if defined(OS_ANDROID)
-#include "ui/gl/android/scoped_java_surface.h"
-#endif
-
-namespace content {
-
-// This class provides an interface to look up window surface handles
-// that cannot be sent through the IPC channel.
-class CONTENT_EXPORT GpuSurfaceLookup {
- public:
- GpuSurfaceLookup() { }
- virtual ~GpuSurfaceLookup() { }
-
- static GpuSurfaceLookup* GetInstance();
- static void InitInstance(GpuSurfaceLookup* lookup);
-
- virtual gfx::AcceleratedWidget AcquireNativeWidget(int surface_id) = 0;
-
-#if defined(OS_ANDROID)
- virtual gfx::ScopedJavaSurface AcquireJavaSurface(int surface_id);
-#endif
-
- private:
- DISALLOW_COPY_AND_ASSIGN(GpuSurfaceLookup);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_GPU_SURFACE_LOOKUP_H_
diff --git a/chromium/content/common/gpu/gpu_watchdog.h b/chromium/content/common/gpu/gpu_watchdog.h
deleted file mode 100644
index 069aeb72737..00000000000
--- a/chromium/content/common/gpu/gpu_watchdog.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_GPU_WATCHDOG_H_
-#define CONTENT_COMMON_GPU_GPU_WATCHDOG_H_
-
-#include "base/macros.h"
-
-namespace content {
-
-// Interface for objects that monitor the a GPUProcessor's progress. The
-// GPUProcessor will regularly invoke CheckArmed.
-class GpuWatchdog {
- public:
- virtual void CheckArmed() = 0;
-
- protected:
- GpuWatchdog() {}
- virtual ~GpuWatchdog() {};
-
- private:
- DISALLOW_COPY_AND_ASSIGN(GpuWatchdog);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_GPU_WATCHDOG_H_
diff --git a/chromium/content/common/gpu/image_transport_surface.cc b/chromium/content/common/gpu/image_transport_surface.cc
deleted file mode 100644
index 192ec9620b6..00000000000
--- a/chromium/content/common/gpu/image_transport_surface.cc
+++ /dev/null
@@ -1,302 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/image_transport_surface.h"
-
-#include <stddef.h>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/command_line.h"
-#include "base/trace_event/trace_event.h"
-#include "build/build_config.h"
-#include "content/common/gpu/gpu_channel.h"
-#include "content/common/gpu/gpu_channel_manager.h"
-#include "content/common/gpu/gpu_command_buffer_stub.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "gpu/command_buffer/service/sync_point_manager.h"
-#include "ui/gfx/vsync_provider.h"
-#include "ui/gl/gl_context.h"
-#include "ui/gl/gl_implementation.h"
-#include "ui/gl/gl_switches.h"
-
-namespace content {
-
-ImageTransportSurface::ImageTransportSurface() {}
-
-ImageTransportSurface::~ImageTransportSurface() {}
-
-scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateSurface(
- GpuChannelManager* manager,
- GpuCommandBufferStub* stub,
- const gfx::GLSurfaceHandle& handle) {
- scoped_refptr<gfx::GLSurface> surface;
- if (handle.transport_type == gfx::NULL_TRANSPORT) {
- surface = manager->GetDefaultOffscreenSurface();
- } else {
- surface = CreateNativeSurface(manager, stub, handle);
- if (!surface.get() || !surface->Initialize())
- return NULL;
- }
-
- return surface;
-}
-
-ImageTransportHelper::ImageTransportHelper(ImageTransportSurface* surface,
- GpuChannelManager* manager,
- GpuCommandBufferStub* stub,
- gfx::PluginWindowHandle handle)
- : surface_(surface),
- manager_(manager),
- stub_(stub->AsWeakPtr()),
- handle_(handle) {
- route_id_ = manager_->GenerateRouteID();
- manager_->AddRoute(route_id_, this);
-}
-
-ImageTransportHelper::~ImageTransportHelper() {
- if (stub_.get()) {
- stub_->SetLatencyInfoCallback(
- base::Callback<void(const std::vector<ui::LatencyInfo>&)>());
- }
- manager_->RemoveRoute(route_id_);
-}
-
-bool ImageTransportHelper::Initialize() {
- gpu::gles2::GLES2Decoder* decoder = Decoder();
-
- if (!decoder)
- return false;
-
- stub_->SetLatencyInfoCallback(
- base::Bind(&ImageTransportHelper::SetLatencyInfo,
- base::Unretained(this)));
-
- return true;
-}
-
-bool ImageTransportHelper::OnMessageReceived(const IPC::Message& message) {
-#if defined(OS_MACOSX)
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(ImageTransportHelper, message)
- IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_BufferPresented,
- OnBufferPresented)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-#else
- NOTREACHED();
- return false;
-#endif
-}
-
-#if defined(OS_MACOSX)
-void ImageTransportHelper::SendAcceleratedSurfaceBuffersSwapped(
- GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params) {
- // TRACE_EVENT for gpu tests:
- TRACE_EVENT_INSTANT2("test_gpu", "SwapBuffers",
- TRACE_EVENT_SCOPE_THREAD,
- "GLImpl", static_cast<int>(gfx::GetGLImplementation()),
- "width", params.size.width());
- // On mac, handle_ is a surface id. See
- // GpuProcessTransportFactory::CreatePerCompositorData
- params.surface_id = handle_;
- params.route_id = route_id_;
- manager_->Send(new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params));
-}
-#endif
-
-bool ImageTransportHelper::MakeCurrent() {
- gpu::gles2::GLES2Decoder* decoder = Decoder();
- if (!decoder)
- return false;
- return decoder->MakeCurrent();
-}
-
-void ImageTransportHelper::SetSwapInterval(gfx::GLContext* context) {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableGpuVsync))
- context->ForceSwapIntervalZero(true);
- else
- context->SetSwapInterval(1);
-}
-
-gpu::gles2::GLES2Decoder* ImageTransportHelper::Decoder() {
- if (!stub_.get())
- return NULL;
- return stub_->decoder();
-}
-
-#if defined(OS_MACOSX)
-void ImageTransportHelper::OnBufferPresented(
- const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
- surface_->OnBufferPresented(params);
-}
-#endif
-
-void ImageTransportHelper::SetLatencyInfo(
- const std::vector<ui::LatencyInfo>& latency_info) {
- surface_->SetLatencyInfo(latency_info);
-}
-
-PassThroughImageTransportSurface::PassThroughImageTransportSurface(
- GpuChannelManager* manager,
- GpuCommandBufferStub* stub,
- gfx::GLSurface* surface)
- : GLSurfaceAdapter(surface),
- did_set_swap_interval_(false),
- weak_ptr_factory_(this) {
- helper_.reset(new ImageTransportHelper(this,
- manager,
- stub,
- gfx::kNullPluginWindow));
-}
-
-bool PassThroughImageTransportSurface::Initialize() {
- // The surface is assumed to have already been initialized.
- return helper_->Initialize();
-}
-
-void PassThroughImageTransportSurface::Destroy() {
- GLSurfaceAdapter::Destroy();
-}
-
-void PassThroughImageTransportSurface::SetLatencyInfo(
- const std::vector<ui::LatencyInfo>& latency_info) {
- for (size_t i = 0; i < latency_info.size(); i++)
- latency_info_.push_back(latency_info[i]);
-}
-
-gfx::SwapResult PassThroughImageTransportSurface::SwapBuffers() {
- scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers();
- gfx::SwapResult result = gfx::GLSurfaceAdapter::SwapBuffers();
- FinishSwapBuffers(std::move(latency_info), result);
- return result;
-}
-
-void PassThroughImageTransportSurface::SwapBuffersAsync(
- const GLSurface::SwapCompletionCallback& callback) {
- scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers();
-
- // We use WeakPtr here to avoid manual management of life time of an instance
- // of this class. Callback will not be called once the instance of this class
- // is destroyed. However, this also means that the callback can be run on
- // the calling thread only.
- gfx::GLSurfaceAdapter::SwapBuffersAsync(base::Bind(
- &PassThroughImageTransportSurface::FinishSwapBuffersAsync,
- weak_ptr_factory_.GetWeakPtr(), base::Passed(&latency_info), callback));
-}
-
-gfx::SwapResult PassThroughImageTransportSurface::PostSubBuffer(int x,
- int y,
- int width,
- int height) {
- scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers();
- gfx::SwapResult result =
- gfx::GLSurfaceAdapter::PostSubBuffer(x, y, width, height);
- FinishSwapBuffers(std::move(latency_info), result);
- return result;
-}
-
-void PassThroughImageTransportSurface::PostSubBufferAsync(
- int x,
- int y,
- int width,
- int height,
- const GLSurface::SwapCompletionCallback& callback) {
- scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers();
- gfx::GLSurfaceAdapter::PostSubBufferAsync(
- x, y, width, height,
- base::Bind(&PassThroughImageTransportSurface::FinishSwapBuffersAsync,
- weak_ptr_factory_.GetWeakPtr(), base::Passed(&latency_info),
- callback));
-}
-
-gfx::SwapResult PassThroughImageTransportSurface::CommitOverlayPlanes() {
- scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers();
- gfx::SwapResult result = gfx::GLSurfaceAdapter::CommitOverlayPlanes();
- FinishSwapBuffers(std::move(latency_info), result);
- return result;
-}
-
-void PassThroughImageTransportSurface::CommitOverlayPlanesAsync(
- const GLSurface::SwapCompletionCallback& callback) {
- scoped_ptr<std::vector<ui::LatencyInfo>> latency_info = StartSwapBuffers();
- gfx::GLSurfaceAdapter::CommitOverlayPlanesAsync(base::Bind(
- &PassThroughImageTransportSurface::FinishSwapBuffersAsync,
- weak_ptr_factory_.GetWeakPtr(), base::Passed(&latency_info), callback));
-}
-
-bool PassThroughImageTransportSurface::OnMakeCurrent(gfx::GLContext* context) {
- if (!did_set_swap_interval_) {
- ImageTransportHelper::SetSwapInterval(context);
- did_set_swap_interval_ = true;
- }
- return true;
-}
-
-#if defined(OS_MACOSX)
-void PassThroughImageTransportSurface::OnBufferPresented(
- const AcceleratedSurfaceMsg_BufferPresented_Params& /* params */) {
- NOTREACHED();
-}
-#endif
-
-gfx::Size PassThroughImageTransportSurface::GetSize() {
- return GLSurfaceAdapter::GetSize();
-}
-
-PassThroughImageTransportSurface::~PassThroughImageTransportSurface() {}
-
-void PassThroughImageTransportSurface::SendVSyncUpdateIfAvailable() {
- gfx::VSyncProvider* vsync_provider = GetVSyncProvider();
- if (vsync_provider) {
- vsync_provider->GetVSyncParameters(
- base::Bind(&GpuCommandBufferStub::SendUpdateVSyncParameters,
- helper_->stub()->AsWeakPtr()));
- }
-}
-
-scoped_ptr<std::vector<ui::LatencyInfo>>
-PassThroughImageTransportSurface::StartSwapBuffers() {
- // GetVsyncValues before SwapBuffers to work around Mali driver bug:
- // crbug.com/223558.
- SendVSyncUpdateIfAvailable();
-
- base::TimeTicks swap_time = base::TimeTicks::Now();
- for (auto& latency : latency_info_) {
- latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0, swap_time, 1);
- }
-
- scoped_ptr<std::vector<ui::LatencyInfo>> latency_info(
- new std::vector<ui::LatencyInfo>());
- latency_info->swap(latency_info_);
-
- return latency_info;
-}
-
-void PassThroughImageTransportSurface::FinishSwapBuffers(
- scoped_ptr<std::vector<ui::LatencyInfo>> latency_info,
- gfx::SwapResult result) {
- base::TimeTicks swap_ack_time = base::TimeTicks::Now();
- for (auto& latency : *latency_info) {
- latency.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0,
- swap_ack_time, 1);
- }
-
- helper_->stub()->SendSwapBuffersCompleted(*latency_info, result);
-}
-
-void PassThroughImageTransportSurface::FinishSwapBuffersAsync(
- scoped_ptr<std::vector<ui::LatencyInfo>> latency_info,
- GLSurface::SwapCompletionCallback callback,
- gfx::SwapResult result) {
- FinishSwapBuffers(std::move(latency_info), result);
- callback.Run(result);
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/image_transport_surface.h b/chromium/content/common/gpu/image_transport_surface.h
deleted file mode 100644
index bfb68928cf6..00000000000
--- a/chromium/content/common/gpu/image_transport_surface.h
+++ /dev/null
@@ -1,224 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_IMAGE_TRANSPORT_SURFACE_H_
-#define CONTENT_COMMON_GPU_IMAGE_TRANSPORT_SURFACE_H_
-
-#include <stdint.h>
-
-#include <vector>
-
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "build/build_config.h"
-#include "content/common/content_export.h"
-#include "ipc/ipc_listener.h"
-#include "ipc/ipc_message.h"
-#include "ui/events/latency_info.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gfx/swap_result.h"
-#include "ui/gl/gl_surface.h"
-
-#if defined(OS_MACOSX)
-struct AcceleratedSurfaceMsg_BufferPresented_Params;
-struct GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params;
-#endif
-
-namespace gfx {
-class GLSurface;
-}
-
-namespace gpu {
-class PreemptionFlag;
-namespace gles2 {
-class GLES2Decoder;
-}
-}
-
-namespace content {
-class GpuChannelManager;
-class GpuCommandBufferStub;
-
-// The GPU process is agnostic as to how it displays results. On some platforms
-// it renders directly to window. On others it renders offscreen and transports
-// the results to the browser process to display. This file provides a simple
-// framework for making the offscreen path seem more like the onscreen path.
-//
-// The ImageTransportSurface class defines an simple interface for events that
-// should be responded to. The factory returns an offscreen surface that looks
-// a lot like an onscreen surface to the GPU process.
-//
-// The ImageTransportSurfaceHelper provides some glue to the outside world:
-// making sure outside events reach the ImageTransportSurface and
-// allowing the ImageTransportSurface to send events to the outside world.
-
-class ImageTransportSurface {
- public:
- ImageTransportSurface();
-
-#if defined(OS_MACOSX)
- virtual void OnBufferPresented(
- const AcceleratedSurfaceMsg_BufferPresented_Params& params) = 0;
-#endif
- virtual void SetLatencyInfo(
- const std::vector<ui::LatencyInfo>& latency_info) = 0;
-
- // Creates a surface with the given attributes.
- static scoped_refptr<gfx::GLSurface> CreateSurface(
- GpuChannelManager* manager,
- GpuCommandBufferStub* stub,
- const gfx::GLSurfaceHandle& handle);
-
-#if defined(OS_MACOSX)
- CONTENT_EXPORT static void SetAllowOSMesaForTesting(bool allow);
-#endif
-
- virtual gfx::Size GetSize() = 0;
-
- protected:
- virtual ~ImageTransportSurface();
-
- private:
- // Creates the appropriate native surface depending on the GL implementation.
- // This will be implemented separately by each platform.
- //
- // This will not be called for texture transport surfaces which are
- // cross-platform. The platform implementation should only create the
- // surface and should not initialize it. On failure, a null scoped_refptr
- // should be returned.
- static scoped_refptr<gfx::GLSurface> CreateNativeSurface(
- GpuChannelManager* manager,
- GpuCommandBufferStub* stub,
- const gfx::GLSurfaceHandle& handle);
-
- DISALLOW_COPY_AND_ASSIGN(ImageTransportSurface);
-};
-
-class ImageTransportHelper
- : public IPC::Listener,
- public base::SupportsWeakPtr<ImageTransportHelper> {
- public:
- // Takes weak pointers to objects that outlive the helper.
- ImageTransportHelper(ImageTransportSurface* surface,
- GpuChannelManager* manager,
- GpuCommandBufferStub* stub,
- gfx::PluginWindowHandle handle);
- ~ImageTransportHelper() override;
-
- bool Initialize();
-
- // IPC::Listener implementation:
- bool OnMessageReceived(const IPC::Message& message) override;
-
- // Helper send functions. Caller fills in the surface specific params
- // like size and surface id. The helper fills in the rest.
-#if defined(OS_MACOSX)
- void SendAcceleratedSurfaceBuffersSwapped(
- GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params);
-#endif
-
- // Make the surface's context current.
- bool MakeCurrent();
-
- // Set the default swap interval on the surface.
- static void SetSwapInterval(gfx::GLContext* context);
-
- GpuChannelManager* manager() const { return manager_; }
- GpuCommandBufferStub* stub() const { return stub_.get(); }
-
- private:
- gpu::gles2::GLES2Decoder* Decoder();
-
- // IPC::Message handlers.
-#if defined(OS_MACOSX)
- void OnBufferPresented(
- const AcceleratedSurfaceMsg_BufferPresented_Params& params);
-#endif
-
- // Backbuffer resize callback.
- void Resize(gfx::Size size, float scale_factor);
-
- void SetLatencyInfo(const std::vector<ui::LatencyInfo>& latency_info);
-
- // Weak pointers that point to objects that outlive this helper.
- ImageTransportSurface* surface_;
- GpuChannelManager* manager_;
-
- base::WeakPtr<GpuCommandBufferStub> stub_;
- int32_t route_id_;
- gfx::PluginWindowHandle handle_;
-
- DISALLOW_COPY_AND_ASSIGN(ImageTransportHelper);
-};
-
-// An implementation of ImageTransportSurface that implements GLSurface through
-// GLSurfaceAdapter, thereby forwarding GLSurface methods through to it.
-class PassThroughImageTransportSurface
- : public gfx::GLSurfaceAdapter,
- public ImageTransportSurface {
- public:
- PassThroughImageTransportSurface(GpuChannelManager* manager,
- GpuCommandBufferStub* stub,
- gfx::GLSurface* surface);
-
- // GLSurface implementation.
- bool Initialize() override;
- void Destroy() override;
- gfx::SwapResult SwapBuffers() override;
- void SwapBuffersAsync(const SwapCompletionCallback& callback) override;
- gfx::SwapResult PostSubBuffer(int x, int y, int width, int height) override;
- void PostSubBufferAsync(int x,
- int y,
- int width,
- int height,
- const SwapCompletionCallback& callback) override;
- gfx::SwapResult CommitOverlayPlanes() override;
- void CommitOverlayPlanesAsync(
- const SwapCompletionCallback& callback) override;
- bool OnMakeCurrent(gfx::GLContext* context) override;
-
- // ImageTransportSurface implementation.
-#if defined(OS_MACOSX)
- void OnBufferPresented(
- const AcceleratedSurfaceMsg_BufferPresented_Params& params) override;
-#endif
- gfx::Size GetSize() override;
- void SetLatencyInfo(
- const std::vector<ui::LatencyInfo>& latency_info) override;
-
- protected:
- ~PassThroughImageTransportSurface() override;
-
- // If updated vsync parameters can be determined, send this information to
- // the browser.
- virtual void SendVSyncUpdateIfAvailable();
-
- scoped_ptr<std::vector<ui::LatencyInfo>> StartSwapBuffers();
- void FinishSwapBuffers(scoped_ptr<std::vector<ui::LatencyInfo>> latency_info,
- gfx::SwapResult result);
- void FinishSwapBuffersAsync(
- scoped_ptr<std::vector<ui::LatencyInfo>> latency_info,
- GLSurface::SwapCompletionCallback callback,
- gfx::SwapResult result);
-
- ImageTransportHelper* GetHelper() { return helper_.get(); }
-
- private:
- scoped_ptr<ImageTransportHelper> helper_;
- bool did_set_swap_interval_;
- std::vector<ui::LatencyInfo> latency_info_;
- base::WeakPtrFactory<PassThroughImageTransportSurface> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(PassThroughImageTransportSurface);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_IMAGE_TRANSPORT_SURFACE_H_
diff --git a/chromium/content/common/gpu/image_transport_surface_android.cc b/chromium/content/common/gpu/image_transport_surface_android.cc
deleted file mode 100644
index 79a16c0bbdf..00000000000
--- a/chromium/content/common/gpu/image_transport_surface_android.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/image_transport_surface.h"
-
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "content/common/gpu/gpu_channel.h"
-#include "content/common/gpu/gpu_channel_manager.h"
-#include "content/common/gpu/gpu_command_buffer_stub.h"
-#include "content/common/gpu/gpu_surface_lookup.h"
-#include "content/public/common/content_switches.h"
-#include "ui/gl/gl_surface_egl.h"
-
-namespace content {
-
-// static
-scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(
- GpuChannelManager* manager,
- GpuCommandBufferStub* stub,
- const gfx::GLSurfaceHandle& handle) {
- DCHECK(GpuSurfaceLookup::GetInstance());
- DCHECK_EQ(handle.transport_type, gfx::NATIVE_DIRECT);
- ANativeWindow* window =
- GpuSurfaceLookup::GetInstance()->AcquireNativeWidget(handle.handle);
- if (!window) {
- LOG(WARNING) << "Failed to acquire native widget.";
- return scoped_refptr<gfx::GLSurface>();
- }
- scoped_refptr<gfx::GLSurface> surface =
- new gfx::NativeViewGLSurfaceEGL(window);
- bool initialize_success = surface->Initialize();
- ANativeWindow_release(window);
- if (!initialize_success)
- return scoped_refptr<gfx::GLSurface>();
-
- return scoped_refptr<gfx::GLSurface>(
- new PassThroughImageTransportSurface(manager, stub, surface.get()));
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/image_transport_surface_linux.cc b/chromium/content/common/gpu/image_transport_surface_linux.cc
deleted file mode 100644
index db36efea135..00000000000
--- a/chromium/content/common/gpu/image_transport_surface_linux.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/image_transport_surface.h"
-
-namespace content {
-
-// static
-scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(
- GpuChannelManager* manager,
- GpuCommandBufferStub* stub,
- const gfx::GLSurfaceHandle& handle) {
- DCHECK(handle.handle);
- DCHECK(handle.transport_type == gfx::NATIVE_DIRECT);
- scoped_refptr<gfx::GLSurface> surface;
-#if defined(USE_OZONE)
- surface = gfx::GLSurface::CreateSurfacelessViewGLSurface(handle.handle);
-#endif
- if (!surface)
- surface = gfx::GLSurface::CreateViewGLSurface(handle.handle);
- if (!surface)
- return surface;
- return scoped_refptr<gfx::GLSurface>(new PassThroughImageTransportSurface(
- manager, stub, surface.get()));
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/image_transport_surface_mac.mm b/chromium/content/common/gpu/image_transport_surface_mac.mm
deleted file mode 100644
index 1059589b084..00000000000
--- a/chromium/content/common/gpu/image_transport_surface_mac.mm
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/image_transport_surface.h"
-
-#include "base/macros.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gl/gl_context.h"
-#include "ui/gl/gl_implementation.h"
-#include "ui/gl/gl_surface_osmesa.h"
-
-namespace content {
-
-scoped_refptr<gfx::GLSurface> ImageTransportSurfaceCreateNativeSurface(
- GpuChannelManager* manager,
- GpuCommandBufferStub* stub,
- gfx::PluginWindowHandle handle);
-
-namespace {
-
-// A subclass of GLSurfaceOSMesa that doesn't print an error message when
-// SwapBuffers() is called.
-class DRTSurfaceOSMesa : public gfx::GLSurfaceOSMesa {
- public:
- // Size doesn't matter, the surface is resized to the right size later.
- DRTSurfaceOSMesa()
- : GLSurfaceOSMesa(gfx::OSMesaSurfaceFormatRGBA, gfx::Size(1, 1)) {}
-
- // Implement a subset of GLSurface.
- gfx::SwapResult SwapBuffers() override;
-
- private:
- ~DRTSurfaceOSMesa() override {}
- DISALLOW_COPY_AND_ASSIGN(DRTSurfaceOSMesa);
-};
-
-gfx::SwapResult DRTSurfaceOSMesa::SwapBuffers() {
- return gfx::SwapResult::SWAP_ACK;
-}
-
-bool g_allow_os_mesa = false;
-
-} // namespace
-
-// static
-scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(
- GpuChannelManager* manager,
- GpuCommandBufferStub* stub,
- const gfx::GLSurfaceHandle& surface_handle) {
- DCHECK(surface_handle.transport_type == gfx::NATIVE_DIRECT ||
- surface_handle.transport_type == gfx::NULL_TRANSPORT);
-
- switch (gfx::GetGLImplementation()) {
- case gfx::kGLImplementationDesktopGL:
- case gfx::kGLImplementationDesktopGLCoreProfile:
- case gfx::kGLImplementationAppleGL:
- return ImageTransportSurfaceCreateNativeSurface(manager, stub,
- surface_handle.handle);
- default:
- // Content shell in DRT mode spins up a gpu process which needs an
- // image transport surface, but that surface isn't used to read pixel
- // baselines. So this is mostly a dummy surface.
- if (!g_allow_os_mesa) {
- NOTREACHED();
- return scoped_refptr<gfx::GLSurface>();
- }
- scoped_refptr<gfx::GLSurface> surface(new DRTSurfaceOSMesa());
- if (!surface.get() || !surface->Initialize())
- return surface;
- return scoped_refptr<gfx::GLSurface>(new PassThroughImageTransportSurface(
- manager, stub, surface.get()));
- }
-}
-
-// static
-void ImageTransportSurface::SetAllowOSMesaForTesting(bool allow) {
- g_allow_os_mesa = allow;
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/image_transport_surface_overlay_mac.h b/chromium/content/common/gpu/image_transport_surface_overlay_mac.h
deleted file mode 100644
index 2103bbf7108..00000000000
--- a/chromium/content/common/gpu/image_transport_surface_overlay_mac.h
+++ /dev/null
@@ -1,148 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_IMAGE_TRANSPORT_SURFACE_OVERLAY_MAC_H_
-#define CONTENT_COMMON_GPU_IMAGE_TRANSPORT_SURFACE_OVERLAY_MAC_H_
-
-#include <list>
-#include <vector>
-
-#import "base/mac/scoped_nsobject.h"
-#include "base/timer/timer.h"
-#include "content/common/gpu/gpu_command_buffer_stub.h"
-#include "content/common/gpu/image_transport_surface.h"
-#include "ui/gl/gl_surface.h"
-#include "ui/gl/gpu_switching_observer.h"
-
-@class CAContext;
-@class CALayer;
-
-namespace content {
-
-class CALayerTree;
-class CALayerPartialDamageTree;
-
-class ImageTransportSurfaceOverlayMac : public gfx::GLSurface,
- public ImageTransportSurface,
- public ui::GpuSwitchingObserver {
- public:
- ImageTransportSurfaceOverlayMac(GpuChannelManager* manager,
- GpuCommandBufferStub* stub,
- gfx::PluginWindowHandle handle);
-
- // GLSurface implementation
- bool Initialize() override;
- void Destroy() override;
- bool Resize(const gfx::Size& size,
- float scale_factor,
- bool has_alpha) override;
- bool IsOffscreen() override;
- gfx::SwapResult SwapBuffers() override;
- gfx::SwapResult PostSubBuffer(int x, int y, int width, int height) override;
- bool SupportsPostSubBuffer() override;
- gfx::Size GetSize() override;
- void* GetHandle() override;
- bool OnMakeCurrent(gfx::GLContext* context) override;
- bool SetBackbufferAllocation(bool allocated) override;
- bool ScheduleOverlayPlane(int z_order,
- gfx::OverlayTransform transform,
- gl::GLImage* image,
- const gfx::Rect& bounds_rect,
- const gfx::RectF& crop_rect) override;
- bool ScheduleCALayer(gl::GLImage* contents_image,
- const gfx::RectF& contents_rect,
- float opacity,
- unsigned background_color,
- unsigned edge_aa_mask,
- const gfx::RectF& rect,
- bool is_clipped,
- const gfx::RectF& clip_rect,
- const gfx::Transform& transform,
- int sorting_context_id) override;
- bool IsSurfaceless() const override;
-
- // ImageTransportSurface implementation
- void OnBufferPresented(
- const AcceleratedSurfaceMsg_BufferPresented_Params& params) override;
- void SetLatencyInfo(const std::vector<ui::LatencyInfo>&) override;
-
- // ui::GpuSwitchingObserver implementation.
- void OnGpuSwitched() override;
-
- private:
- class PendingSwap;
- class OverlayPlane;
-
- ~ImageTransportSurfaceOverlayMac() override;
-
- gfx::SwapResult SwapBuffersInternal(const gfx::Rect& pixel_damage_rect);
-
- // Returns true if the front of |pending_swaps_| has completed, or has timed
- // out by |now|.
- bool IsFirstPendingSwapReadyToDisplay(
- const base::TimeTicks& now);
- // Sets the CALayer contents to the IOSurface for the front of
- // |pending_swaps_|, and removes it from the queue.
- void DisplayFirstPendingSwapImmediately();
- // Force that all of |pending_swaps_| displayed immediately, and the list be
- // cleared.
- void DisplayAndClearAllPendingSwaps();
- // Callback issued during the next vsync period ofter a SwapBuffers call,
- // to check if the swap is completed, and display the frame. Note that if
- // another SwapBuffers happens before this callback, the pending swap will
- // be tested at that time, too.
- void CheckPendingSwapsCallback();
- // Function to post the above callback. The argument |now| is passed as an
- // argument to avoid redundant calls to base::TimeTicks::Now.
- void PostCheckPendingSwapsCallbackIfNeeded(const base::TimeTicks& now);
-
- // Return the time of |interval_fraction| of the way through the next
- // vsync period that starts after |from|. If the vsync parameters are not
- // valid then return |from|.
- base::TimeTicks GetNextVSyncTimeAfter(
- const base::TimeTicks& from, double interval_fraction);
-
- scoped_ptr<ImageTransportHelper> helper_;
- bool use_remote_layer_api_;
- base::scoped_nsobject<CAContext> ca_context_;
- base::scoped_nsobject<CALayer> ca_root_layer_;
-
- gfx::Size pixel_size_;
- float scale_factor_;
- std::vector<ui::LatencyInfo> latency_info_;
-
- // The renderer ID that all contexts made current to this surface should be
- // targeting.
- GLint gl_renderer_id_;
-
- // Planes that have been scheduled, but have not had a subsequent SwapBuffers
- // call made yet.
- scoped_ptr<CALayerPartialDamageTree> pending_partial_damage_tree_;
- scoped_ptr<CALayerTree> pending_ca_layer_tree_;
-
- // A queue of all frames that have been created by SwapBuffersInternal but
- // have not yet been displayed. This queue is checked at the beginning of
- // every swap and also by a callback.
- std::deque<linked_ptr<PendingSwap>> pending_swaps_;
-
- // The planes that are currently being displayed on the screen.
- scoped_ptr<CALayerPartialDamageTree> current_partial_damage_tree_;
- scoped_ptr<CALayerTree> current_ca_layer_tree_;
-
- // The time of the last swap was issued. If this is more than two vsyncs, then
- // use the simpler non-smooth animation path.
- base::TimeTicks last_swap_time_;
-
- // The vsync information provided by the browser.
- bool vsync_parameters_valid_;
- base::TimeTicks vsync_timebase_;
- base::TimeDelta vsync_interval_;
-
- base::Timer display_pending_swap_timer_;
- base::WeakPtrFactory<ImageTransportSurfaceOverlayMac> weak_factory_;
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_IMAGE_TRANSPORT_SURFACE_OVERLAY_MAC_H_
diff --git a/chromium/content/common/gpu/image_transport_surface_overlay_mac.mm b/chromium/content/common/gpu/image_transport_surface_overlay_mac.mm
deleted file mode 100644
index 1b0e3372e2d..00000000000
--- a/chromium/content/common/gpu/image_transport_surface_overlay_mac.mm
+++ /dev/null
@@ -1,522 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/image_transport_surface_overlay_mac.h"
-
-#include <CoreGraphics/CoreGraphics.h>
-#include <IOSurface/IOSurface.h>
-#include <OpenGL/CGLRenderers.h>
-#include <OpenGL/CGLTypes.h>
-#include <OpenGL/gl.h>
-#include <stddef.h>
-
-#include <algorithm>
-
-// This type consistently causes problem on Mac, and needs to be dealt with
-// in a systemic way.
-// http://crbug.com/517208
-#ifndef GL_OES_EGL_image
-typedef void* GLeglImageOES;
-#endif
-
-#include "base/mac/scoped_cftyperef.h"
-#include "base/trace_event/trace_event.h"
-#include "content/common/gpu/ca_layer_partial_damage_tree_mac.h"
-#include "content/common/gpu/ca_layer_tree_mac.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "ui/accelerated_widget_mac/io_surface_context.h"
-#include "ui/base/cocoa/animation_utils.h"
-#include "ui/base/cocoa/remote_layer_api.h"
-#include "ui/gfx/geometry/rect_conversions.h"
-#include "ui/gfx/transform.h"
-#include "ui/gl/gl_context.h"
-#include "ui/gl/gl_fence.h"
-#include "ui/gl/gl_image_io_surface.h"
-#include "ui/gl/gpu_switching_manager.h"
-#include "ui/gl/scoped_api.h"
-#include "ui/gl/scoped_cgl.h"
-
-namespace {
-
-// Don't let a frame draw until 5% of the way through the next vsync interval
-// after the call to SwapBuffers. This slight offset is to ensure that skew
-// doesn't result in the frame being presented to the previous vsync interval.
-const double kVSyncIntervalFractionForEarliestDisplay = 0.05;
-
-// After doing a glFlush and putting in a fence in SwapBuffers, post a task to
-// query the fence 50% of the way through the next vsync interval. If we are
-// trying to animate smoothly, then want to query the fence at the next
-// SwapBuffers. For this reason we schedule the callback for a long way into
-// the next frame.
-const double kVSyncIntervalFractionForDisplayCallback = 0.5;
-
-// If swaps arrive regularly and nearly at the vsync rate, then attempt to
-// make animation smooth (each frame is shown for one vsync interval) by sending
-// them to the window server only when their GL work completes. If frames are
-// not coming in with each vsync, then just throw them at the window server as
-// they come.
-const double kMaximumVSyncsBetweenSwapsForSmoothAnimation = 1.5;
-
-void CheckGLErrors(const char* msg) {
- GLenum gl_error;
- while ((gl_error = glGetError()) != GL_NO_ERROR) {
- LOG(ERROR) << "OpenGL error hit " << msg << ": " << gl_error;
- }
-}
-
-void IOSurfaceContextNoOp(scoped_refptr<ui::IOSurfaceContext>) {
-}
-
-} // namespace
-
-@interface CALayer(Private)
--(void)setContentsChanged;
-@end
-
-namespace content {
-
-scoped_refptr<gfx::GLSurface> ImageTransportSurfaceCreateNativeSurface(
- GpuChannelManager* manager,
- GpuCommandBufferStub* stub,
- gfx::PluginWindowHandle handle) {
- return new ImageTransportSurfaceOverlayMac(manager, stub, handle);
-}
-
-class ImageTransportSurfaceOverlayMac::PendingSwap {
- public:
- PendingSwap() {}
- ~PendingSwap() { DCHECK(!gl_fence); }
-
- gfx::Size pixel_size;
- float scale_factor;
- gfx::Rect pixel_damage_rect;
-
- scoped_ptr<CALayerPartialDamageTree> partial_damage_tree;
- scoped_ptr<CALayerTree> ca_layer_tree;
- std::vector<ui::LatencyInfo> latency_info;
-
- // A fence object, and the CGL context it was issued in.
- base::ScopedTypeRef<CGLContextObj> cgl_context;
- scoped_ptr<gfx::GLFence> gl_fence;
-
- // The earliest time that this frame may be drawn. A frame is not allowed
- // to draw until a fraction of the way through the vsync interval after its
- // This extra latency is to allow wiggle-room for smoothness.
- base::TimeTicks earliest_display_time_allowed;
-
- // The time that this will wake up and draw, if a following swap does not
- // cause it to draw earlier.
- base::TimeTicks target_display_time;
-};
-
-ImageTransportSurfaceOverlayMac::ImageTransportSurfaceOverlayMac(
- GpuChannelManager* manager,
- GpuCommandBufferStub* stub,
- gfx::PluginWindowHandle handle)
- : use_remote_layer_api_(ui::RemoteLayerAPISupported()),
- scale_factor_(1),
- gl_renderer_id_(0),
- vsync_parameters_valid_(false),
- display_pending_swap_timer_(true, false),
- weak_factory_(this) {
- helper_.reset(new ImageTransportHelper(this, manager, stub, handle));
- ui::GpuSwitchingManager::GetInstance()->AddObserver(this);
-}
-
-ImageTransportSurfaceOverlayMac::~ImageTransportSurfaceOverlayMac() {
- ui::GpuSwitchingManager::GetInstance()->RemoveObserver(this);
- Destroy();
-}
-
-bool ImageTransportSurfaceOverlayMac::Initialize() {
- if (!helper_->Initialize())
- return false;
-
- // Create the CAContext to send this to the GPU process, and the layer for
- // the context.
- if (use_remote_layer_api_) {
- CGSConnectionID connection_id = CGSMainConnectionID();
- ca_context_.reset([
- [CAContext contextWithCGSConnection:connection_id options:@{}] retain]);
- ca_root_layer_.reset([[CALayer alloc] init]);
- [ca_root_layer_ setGeometryFlipped:YES];
- [ca_root_layer_ setOpaque:YES];
- [ca_context_ setLayer:ca_root_layer_];
- }
- return true;
-}
-
-void ImageTransportSurfaceOverlayMac::Destroy() {
- DisplayAndClearAllPendingSwaps();
-
- current_partial_damage_tree_.reset();
- current_ca_layer_tree_.reset();
-}
-
-bool ImageTransportSurfaceOverlayMac::IsOffscreen() {
- return false;
-}
-
-gfx::SwapResult ImageTransportSurfaceOverlayMac::SwapBuffersInternal(
- const gfx::Rect& pixel_damage_rect) {
- TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::SwapBuffersInternal");
-
- // Use the same concept of 'now' for the entire function. The duration of
- // this function only affect the result if this function lasts across a vsync
- // boundary, in which case smooth animation is out the window anyway.
- const base::TimeTicks now = base::TimeTicks::Now();
-
- // Decide if the frame should be drawn immediately, or if we should wait until
- // its work finishes before drawing immediately.
- bool display_immediately = false;
- if (vsync_parameters_valid_ &&
- now - last_swap_time_ >
- kMaximumVSyncsBetweenSwapsForSmoothAnimation * vsync_interval_) {
- display_immediately = true;
- }
- last_swap_time_ = now;
-
- // If the previous swap is ready to display, do it before flushing the
- // new swap. It is desirable to always be hitting this path when trying to
- // animate smoothly with vsync.
- if (!pending_swaps_.empty()) {
- if (IsFirstPendingSwapReadyToDisplay(now))
- DisplayFirstPendingSwapImmediately();
- }
-
- // The remainder of the function will populate the PendingSwap structure and
- // then enqueue it.
- linked_ptr<PendingSwap> new_swap(new PendingSwap);
- new_swap->pixel_size = pixel_size_;
- new_swap->scale_factor = scale_factor_;
- new_swap->pixel_damage_rect = pixel_damage_rect;
- new_swap->partial_damage_tree.swap(pending_partial_damage_tree_);
- new_swap->ca_layer_tree.swap(pending_ca_layer_tree_);
- new_swap->latency_info.swap(latency_info_);
-
- // A flush is required to ensure that all content appears in the layer.
- {
- gfx::ScopedSetGLToRealGLApi scoped_set_gl_api;
- TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::glFlush");
- CheckGLErrors("before flushing frame");
- new_swap->cgl_context.reset(CGLGetCurrentContext(),
- base::scoped_policy::RETAIN);
- if (gfx::GLFence::IsSupported() && !display_immediately)
- new_swap->gl_fence.reset(gfx::GLFence::Create());
- else
- glFlush();
- CheckGLErrors("while flushing frame");
- }
-
- // Compute the deadlines for drawing this frame.
- if (display_immediately) {
- new_swap->earliest_display_time_allowed = now;
- new_swap->target_display_time = now;
- } else {
- new_swap->earliest_display_time_allowed =
- GetNextVSyncTimeAfter(now, kVSyncIntervalFractionForEarliestDisplay);
- new_swap->target_display_time =
- GetNextVSyncTimeAfter(now, kVSyncIntervalFractionForDisplayCallback);
- }
-
- pending_swaps_.push_back(new_swap);
- if (display_immediately)
- DisplayFirstPendingSwapImmediately();
- else
- PostCheckPendingSwapsCallbackIfNeeded(now);
- return gfx::SwapResult::SWAP_ACK;
-}
-
-bool ImageTransportSurfaceOverlayMac::IsFirstPendingSwapReadyToDisplay(
- const base::TimeTicks& now) {
- DCHECK(!pending_swaps_.empty());
- linked_ptr<PendingSwap> swap = pending_swaps_.front();
-
- // Frames are disallowed from drawing until the vsync interval after their
- // swap is issued.
- if (now < swap->earliest_display_time_allowed)
- return false;
-
- // If we've passed that marker, then wait for the work behind the fence to
- // complete.
- if (swap->gl_fence) {
- gfx::ScopedSetGLToRealGLApi scoped_set_gl_api;
- gfx::ScopedCGLSetCurrentContext scoped_set_current(swap->cgl_context);
-
- CheckGLErrors("before waiting on fence");
- if (!swap->gl_fence->HasCompleted()) {
- TRACE_EVENT0("gpu", "ImageTransportSurfaceOverlayMac::ClientWait");
- swap->gl_fence->ClientWait();
- }
- swap->gl_fence.reset();
- CheckGLErrors("after waiting on fence");
- }
- return true;
-}
-
-void ImageTransportSurfaceOverlayMac::DisplayFirstPendingSwapImmediately() {
- TRACE_EVENT0("gpu",
- "ImageTransportSurfaceOverlayMac::DisplayFirstPendingSwapImmediately");
- DCHECK(!pending_swaps_.empty());
- linked_ptr<PendingSwap> swap = pending_swaps_.front();
-
- // If there is a fence for this object, delete it.
- if (swap->gl_fence) {
- gfx::ScopedSetGLToRealGLApi scoped_set_gl_api;
- gfx::ScopedCGLSetCurrentContext scoped_set_current(swap->cgl_context);
-
- CheckGLErrors("before deleting active fence");
- swap->gl_fence.reset();
- CheckGLErrors("while deleting active fence");
- }
-
- // Update the CALayer hierarchy.
- {
- gfx::RectF pixel_damage_rect = gfx::RectF(swap->pixel_damage_rect);
- ScopedCAActionDisabler disabler;
- if (swap->ca_layer_tree) {
- swap->ca_layer_tree->CommitScheduledCALayers(
- ca_root_layer_.get(), std::move(current_ca_layer_tree_),
- swap->scale_factor);
- current_ca_layer_tree_.swap(swap->ca_layer_tree);
- current_partial_damage_tree_.reset();
- } else if (swap->partial_damage_tree) {
- swap->partial_damage_tree->CommitCALayers(
- ca_root_layer_.get(), std::move(current_partial_damage_tree_),
- swap->scale_factor, swap->pixel_damage_rect);
- current_partial_damage_tree_.swap(swap->partial_damage_tree);
- current_ca_layer_tree_.reset();
- } else {
- TRACE_EVENT0("gpu", "Blank frame: No overlays or CALayers");
- [ca_root_layer_ setSublayers:nil];
- current_partial_damage_tree_.reset();
- current_ca_layer_tree_.reset();
- }
- swap->ca_layer_tree.reset();
- swap->partial_damage_tree.reset();
- }
-
- // Update the latency info to reflect the swap time.
- base::TimeTicks swap_time = base::TimeTicks::Now();
- for (auto latency_info : swap->latency_info) {
- latency_info.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_GPU_SWAP_BUFFER_COMPONENT, 0, 0, swap_time, 1);
- latency_info.AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_TERMINATED_FRAME_SWAP_COMPONENT, 0, 0,
- swap_time, 1);
- }
-
- // Send acknowledgement to the browser.
- GpuHostMsg_AcceleratedSurfaceBuffersSwapped_Params params;
- if (use_remote_layer_api_) {
- params.ca_context_id = [ca_context_ contextId];
- } else if (current_partial_damage_tree_) {
- params.io_surface.reset(IOSurfaceCreateMachPort(
- current_partial_damage_tree_->RootLayerIOSurface()));
- }
- params.size = swap->pixel_size;
- params.scale_factor = swap->scale_factor;
- params.latency_info.swap(swap->latency_info);
- helper_->SendAcceleratedSurfaceBuffersSwapped(params);
-
- // Remove this from the queue, and reset any callback timers.
- pending_swaps_.pop_front();
-}
-
-void ImageTransportSurfaceOverlayMac::DisplayAndClearAllPendingSwaps() {
- TRACE_EVENT0("gpu",
- "ImageTransportSurfaceOverlayMac::DisplayAndClearAllPendingSwaps");
- while (!pending_swaps_.empty())
- DisplayFirstPendingSwapImmediately();
-}
-
-void ImageTransportSurfaceOverlayMac::CheckPendingSwapsCallback() {
- TRACE_EVENT0("gpu",
- "ImageTransportSurfaceOverlayMac::CheckPendingSwapsCallback");
-
- if (pending_swaps_.empty())
- return;
-
- const base::TimeTicks now = base::TimeTicks::Now();
- if (IsFirstPendingSwapReadyToDisplay(now))
- DisplayFirstPendingSwapImmediately();
- PostCheckPendingSwapsCallbackIfNeeded(now);
-}
-
-void ImageTransportSurfaceOverlayMac::PostCheckPendingSwapsCallbackIfNeeded(
- const base::TimeTicks& now) {
- TRACE_EVENT0("gpu",
- "ImageTransportSurfaceOverlayMac::PostCheckPendingSwapsCallbackIfNeeded");
-
- if (pending_swaps_.empty()) {
- display_pending_swap_timer_.Stop();
- } else {
- display_pending_swap_timer_.Start(
- FROM_HERE,
- pending_swaps_.front()->target_display_time - now,
- base::Bind(&ImageTransportSurfaceOverlayMac::CheckPendingSwapsCallback,
- weak_factory_.GetWeakPtr()));
- }
-}
-
-gfx::SwapResult ImageTransportSurfaceOverlayMac::SwapBuffers() {
- return SwapBuffersInternal(
- gfx::Rect(0, 0, pixel_size_.width(), pixel_size_.height()));
-}
-
-gfx::SwapResult ImageTransportSurfaceOverlayMac::PostSubBuffer(int x,
- int y,
- int width,
- int height) {
- return SwapBuffersInternal(gfx::Rect(x, y, width, height));
-}
-
-bool ImageTransportSurfaceOverlayMac::SupportsPostSubBuffer() {
- return true;
-}
-
-gfx::Size ImageTransportSurfaceOverlayMac::GetSize() {
- return gfx::Size();
-}
-
-void* ImageTransportSurfaceOverlayMac::GetHandle() {
- return nullptr;
-}
-
-bool ImageTransportSurfaceOverlayMac::OnMakeCurrent(gfx::GLContext* context) {
- // Ensure that the context is on the appropriate GL renderer. The GL renderer
- // will generally only change when the GPU changes.
- if (gl_renderer_id_ && context)
- context->share_group()->SetRendererID(gl_renderer_id_);
- return true;
-}
-
-bool ImageTransportSurfaceOverlayMac::SetBackbufferAllocation(bool allocated) {
- if (!allocated) {
- DisplayAndClearAllPendingSwaps();
- last_swap_time_ = base::TimeTicks();
- }
- return true;
-}
-
-bool ImageTransportSurfaceOverlayMac::ScheduleOverlayPlane(
- int z_order,
- gfx::OverlayTransform transform,
- gl::GLImage* image,
- const gfx::Rect& pixel_frame_rect,
- const gfx::RectF& crop_rect) {
- if (transform != gfx::OVERLAY_TRANSFORM_NONE) {
- DLOG(ERROR) << "Invalid overlay plane transform.";
- return false;
- }
- if (z_order) {
- DLOG(ERROR) << "Invalid non-zero Z order.";
- return false;
- }
- if (pending_partial_damage_tree_) {
- DLOG(ERROR) << "Only one overlay per swap is allowed.";
- return false;
- }
- pending_partial_damage_tree_.reset(new CALayerPartialDamageTree(
- use_remote_layer_api_,
- static_cast<gl::GLImageIOSurface*>(image)->io_surface(),
- pixel_frame_rect));
- return true;
-}
-
-bool ImageTransportSurfaceOverlayMac::ScheduleCALayer(
- gl::GLImage* contents_image,
- const gfx::RectF& contents_rect,
- float opacity,
- unsigned background_color,
- unsigned edge_aa_mask,
- const gfx::RectF& rect,
- bool is_clipped,
- const gfx::RectF& clip_rect,
- const gfx::Transform& transform,
- int sorting_context_id) {
- base::ScopedCFTypeRef<IOSurfaceRef> io_surface;
- if (contents_image) {
- io_surface =
- static_cast<gl::GLImageIOSurface*>(contents_image)->io_surface();
- }
- if (!pending_ca_layer_tree_)
- pending_ca_layer_tree_.reset(new CALayerTree);
- return pending_ca_layer_tree_->ScheduleCALayer(
- is_clipped, gfx::ToEnclosingRect(clip_rect), sorting_context_id,
- transform, io_surface, contents_rect, gfx::ToEnclosingRect(rect),
- background_color, edge_aa_mask, opacity);
-}
-
-bool ImageTransportSurfaceOverlayMac::IsSurfaceless() const {
- return true;
-}
-
-void ImageTransportSurfaceOverlayMac::OnBufferPresented(
- const AcceleratedSurfaceMsg_BufferPresented_Params& params) {
- vsync_timebase_ = params.vsync_timebase;
- vsync_interval_ = params.vsync_interval;
- vsync_parameters_valid_ = (vsync_interval_ != base::TimeDelta());
-
- // Compute |vsync_timebase_| to be the first vsync after time zero.
- if (vsync_parameters_valid_) {
- vsync_timebase_ -=
- vsync_interval_ *
- ((vsync_timebase_ - base::TimeTicks()) / vsync_interval_);
- }
-}
-
-bool ImageTransportSurfaceOverlayMac::Resize(const gfx::Size& pixel_size,
- float scale_factor,
- bool has_alpha) {
- // Flush through any pending frames.
- DisplayAndClearAllPendingSwaps();
- pixel_size_ = pixel_size;
- scale_factor_ = scale_factor;
- return true;
-}
-
-void ImageTransportSurfaceOverlayMac::SetLatencyInfo(
- const std::vector<ui::LatencyInfo>& latency_info) {
- latency_info_.insert(
- latency_info_.end(), latency_info.begin(), latency_info.end());
-}
-
-void ImageTransportSurfaceOverlayMac::OnGpuSwitched() {
- // Create a new context, and use the GL renderer ID that the new context gets.
- scoped_refptr<ui::IOSurfaceContext> context_on_new_gpu =
- ui::IOSurfaceContext::Get(ui::IOSurfaceContext::kCALayerContext);
- if (!context_on_new_gpu)
- return;
- GLint context_renderer_id = -1;
- if (CGLGetParameter(context_on_new_gpu->cgl_context(),
- kCGLCPCurrentRendererID,
- &context_renderer_id) != kCGLNoError) {
- LOG(ERROR) << "Failed to create test context after GPU switch";
- return;
- }
- gl_renderer_id_ = context_renderer_id & kCGLRendererIDMatchingMask;
-
- // Post a task holding a reference to the new GL context. The reason for
- // this is to avoid creating-then-destroying the context for every image
- // transport surface that is observing the GPU switch.
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&IOSurfaceContextNoOp, context_on_new_gpu));
-}
-
-base::TimeTicks ImageTransportSurfaceOverlayMac::GetNextVSyncTimeAfter(
- const base::TimeTicks& from, double interval_fraction) {
- if (!vsync_parameters_valid_)
- return from;
-
- // Compute the previous vsync time.
- base::TimeTicks previous_vsync =
- vsync_interval_ * ((from - vsync_timebase_) / vsync_interval_) +
- vsync_timebase_;
-
- // Return |interval_fraction| through the next vsync.
- return previous_vsync + (1 + interval_fraction) * vsync_interval_;
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/image_transport_surface_win.cc b/chromium/content/common/gpu/image_transport_surface_win.cc
deleted file mode 100644
index 15f43d2a00f..00000000000
--- a/chromium/content/common/gpu/image_transport_surface_win.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/image_transport_surface.h"
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/compiler_specific.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/win/windows_version.h"
-#include "content/common/gpu/child_window_surface_win.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "content/public/common/content_switches.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_context.h"
-#include "ui/gl/gl_implementation.h"
-#include "ui/gl/gl_surface_egl.h"
-#include "ui/gl/vsync_provider_win.h"
-
-namespace content {
-
-// static
-scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface(
- GpuChannelManager* manager,
- GpuCommandBufferStub* stub,
- const gfx::GLSurfaceHandle& handle) {
- DCHECK(handle.handle);
- DCHECK_EQ(handle.transport_type, gfx::NATIVE_DIRECT);
-
- scoped_refptr<gfx::GLSurface> surface;
- if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2 &&
- gfx::GLSurfaceEGL::IsDirectCompositionSupported()) {
- scoped_refptr<ChildWindowSurfaceWin> egl_surface(
- new ChildWindowSurfaceWin(manager, handle.handle));
- surface = egl_surface;
-
- // TODO(jbauman): Get frame statistics from DirectComposition
- scoped_ptr<gfx::VSyncProvider> vsync_provider(
- new gfx::VSyncProviderWin(handle.handle));
- if (!egl_surface->Initialize(std::move(vsync_provider)))
- return nullptr;
- } else {
- surface = gfx::GLSurface::CreateViewGLSurface(handle.handle);
- }
-
- return scoped_refptr<gfx::GLSurface>(new PassThroughImageTransportSurface(
- manager, stub, surface.get()));
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/media/OWNERS b/chromium/content/common/gpu/media/OWNERS
index 633a1877529..9999d737345 100644
--- a/chromium/content/common/gpu/media/OWNERS
+++ b/chromium/content/common/gpu/media/OWNERS
@@ -2,3 +2,16 @@ dalecurtis@chromium.org
posciak@chromium.org
sandersd@chromium.org
wuchengli@chromium.org
+
+# For security review of IPC message files.
+per-file *_messages*.h=set noparent
+per-file *_messages*.h=dcheng@chromium.org
+per-file *_messages*.h=inferno@chromium.org
+per-file *_messages*.h=jln@chromium.org
+per-file *_messages*.h=jschuh@chromium.org
+per-file *_messages*.h=kenrb@chromium.org
+per-file *_messages*.h=mkwst@chromium.org
+per-file *_messages*.h=nasko@chromium.org
+per-file *_messages*.h=palmer@chromium.org
+per-file *_messages*.h=tsepez@chromium.org
+per-file *_messages*.h=wfh@chromium.org
diff --git a/chromium/content/common/gpu/media/android_copying_backing_strategy.cc b/chromium/content/common/gpu/media/android_copying_backing_strategy.cc
index f80a16f3d72..b5216154829 100644
--- a/chromium/content/common/gpu/media/android_copying_backing_strategy.cc
+++ b/chromium/content/common/gpu/media/android_copying_backing_strategy.cc
@@ -8,6 +8,7 @@
#include "base/logging.h"
#include "base/trace_event/trace_event.h"
#include "content/common/gpu/media/avda_return_on_failure.h"
+#include "gpu/command_buffer/service/context_group.h"
#include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
#include "media/base/limits.h"
@@ -17,24 +18,47 @@
namespace content {
-const static GLfloat kIdentityMatrix[16] = {1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
- 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 1.0f};
-
-AndroidCopyingBackingStrategy::AndroidCopyingBackingStrategy()
- : state_provider_(nullptr), surface_texture_id_(0), media_codec_(nullptr) {}
+AndroidCopyingBackingStrategy::AndroidCopyingBackingStrategy(
+ AVDAStateProvider* state_provider)
+ : state_provider_(state_provider),
+ surface_texture_id_(0),
+ media_codec_(nullptr) {}
AndroidCopyingBackingStrategy::~AndroidCopyingBackingStrategy() {}
-void AndroidCopyingBackingStrategy::Initialize(
- AVDAStateProvider* state_provider) {
- state_provider_ = state_provider;
+gfx::ScopedJavaSurface AndroidCopyingBackingStrategy::Initialize(
+ int surface_view_id) {
+ if (surface_view_id != media::VideoDecodeAccelerator::Config::kNoSurfaceID) {
+ LOG(ERROR) << "The copying strategy should not be initialized with a "
+ "surface id.";
+ return gfx::ScopedJavaSurface();
+ }
+
+ // Create a texture and attach the SurfaceTexture to it.
+ glGenTextures(1, &surface_texture_id_);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, surface_texture_id_);
+
+ // Note that the target will be correctly sized, so nearest filtering is all
+ // that's needed.
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
+ state_provider_->GetGlDecoder()->RestoreTextureUnitBindings(0);
+ state_provider_->GetGlDecoder()->RestoreActiveTexture();
+
+ surface_texture_ = gfx::SurfaceTexture::Create(surface_texture_id_);
+
+ return gfx::ScopedJavaSurface(surface_texture_.get());
}
void AndroidCopyingBackingStrategy::Cleanup(
bool have_context,
const AndroidVideoDecodeAccelerator::OutputBufferMap&) {
DCHECK(state_provider_->ThreadChecker().CalledOnValidThread());
+
if (copier_)
copier_->Destroy();
@@ -42,26 +66,17 @@ void AndroidCopyingBackingStrategy::Cleanup(
glDeleteTextures(1, &surface_texture_id_);
}
+scoped_refptr<gfx::SurfaceTexture>
+AndroidCopyingBackingStrategy::GetSurfaceTexture() const {
+ return surface_texture_;
+}
+
uint32_t AndroidCopyingBackingStrategy::GetTextureTarget() const {
return GL_TEXTURE_2D;
}
-scoped_refptr<gfx::SurfaceTexture>
-AndroidCopyingBackingStrategy::CreateSurfaceTexture() {
- glGenTextures(1, &surface_texture_id_);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_EXTERNAL_OES, surface_texture_id_);
-
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- state_provider_->GetGlDecoder()->RestoreTextureUnitBindings(0);
- state_provider_->GetGlDecoder()->RestoreActiveTexture();
-
- surface_texture_ = gfx::SurfaceTexture::Create(surface_texture_id_);
-
- return surface_texture_;
+gfx::Size AndroidCopyingBackingStrategy::GetPictureBufferSize() const {
+ return state_provider_->GetSize();
}
void AndroidCopyingBackingStrategy::UseCodecBufferForPictureBuffer(
@@ -99,16 +114,19 @@ void AndroidCopyingBackingStrategy::UseCodecBufferForPictureBuffer(
surface_texture_->UpdateTexImage();
}
- float transfrom_matrix[16];
- surface_texture_->GetTransformMatrix(transfrom_matrix);
+ float transform_matrix[16];
+ surface_texture_->GetTransformMatrix(transform_matrix);
- uint32_t picture_buffer_texture_id = picture_buffer.texture_id();
+ DCHECK_LE(1u, picture_buffer.texture_ids().size());
+ uint32_t picture_buffer_texture_id = picture_buffer.texture_ids()[0];
// Defer initializing the CopyTextureCHROMIUMResourceManager until it is
// needed because it takes 10s of milliseconds to initialize.
if (!copier_) {
copier_.reset(new gpu::CopyTextureCHROMIUMResourceManager());
- copier_->Initialize(state_provider_->GetGlDecoder().get());
+ copier_->Initialize(state_provider_->GetGlDecoder().get(),
+ state_provider_->GetGlDecoder()->GetContextGroup()->
+ feature_info()->feature_flags());
}
// Here, we copy |surface_texture_id_| to the picture buffer instead of
@@ -118,13 +136,11 @@ void AndroidCopyingBackingStrategy::UseCodecBufferForPictureBuffer(
// attached.
// 2. SurfaceTexture requires us to apply a transform matrix when we show
// the texture.
- // TODO(hkuang): get the StreamTexture transform matrix in GPU process
- // instead of using default matrix crbug.com/226218.
copier_->DoCopyTextureWithTransform(
state_provider_->GetGlDecoder().get(), GL_TEXTURE_EXTERNAL_OES,
surface_texture_id_, GL_TEXTURE_2D, picture_buffer_texture_id,
state_provider_->GetSize().width(), state_provider_->GetSize().height(),
- false, false, false, kIdentityMatrix);
+ true, false, false, transform_matrix);
}
void AndroidCopyingBackingStrategy::CodecChanged(
@@ -140,4 +156,37 @@ void AndroidCopyingBackingStrategy::OnFrameAvailable() {
// instead preserve the old behavior.
}
+bool AndroidCopyingBackingStrategy::ArePicturesOverlayable() {
+ return false;
+}
+
+void AndroidCopyingBackingStrategy::UpdatePictureBufferSize(
+ media::PictureBuffer* picture_buffer,
+ const gfx::Size& new_size) {
+ // This strategy uses 2D textures who's allocated memory is dependent on the
+ // size. To update size in all places, we must:
+ // 1) Update the PictureBuffer meta-data
+ picture_buffer->set_size(new_size);
+
+ // 2) Update the GL texture via glTexImage2D. This step assumes the caller
+ // has made our GL context current.
+ DCHECK_LE(1u, picture_buffer->texture_ids().size());
+ glBindTexture(GL_TEXTURE_2D, picture_buffer->texture_ids()[0]);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, new_size.width(), new_size.height(),
+ 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+ state_provider_->GetGlDecoder()->RestoreActiveTextureUnitBinding(
+ GL_TEXTURE_2D);
+
+ // 3) Update the CHROMIUM Texture's size.
+ gpu::gles2::TextureRef* texture_ref =
+ state_provider_->GetTextureForPicture(*picture_buffer);
+ RETURN_IF_NULL(texture_ref);
+ gpu::gles2::TextureManager* texture_manager =
+ state_provider_->GetGlDecoder()->GetContextGroup()->texture_manager();
+ RETURN_IF_NULL(texture_manager);
+ texture_manager->SetLevelInfo(texture_ref, GetTextureTarget(), 0, GL_RGBA,
+ new_size.width(), new_size.height(), 1, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect(new_size));
+}
+
} // namespace content
diff --git a/chromium/content/common/gpu/media/android_copying_backing_strategy.h b/chromium/content/common/gpu/media/android_copying_backing_strategy.h
index 17b096aecd5..8980404dfdb 100644
--- a/chromium/content/common/gpu/media/android_copying_backing_strategy.h
+++ b/chromium/content/common/gpu/media/android_copying_backing_strategy.h
@@ -28,21 +28,25 @@ class AVDAStateProvider;
class CONTENT_EXPORT AndroidCopyingBackingStrategy
: public AndroidVideoDecodeAccelerator::BackingStrategy {
public:
- AndroidCopyingBackingStrategy();
+ explicit AndroidCopyingBackingStrategy(AVDAStateProvider* state_provider);
~AndroidCopyingBackingStrategy() override;
// AndroidVideoDecodeAccelerator::BackingStrategy
- void Initialize(AVDAStateProvider*) override;
+ gfx::ScopedJavaSurface Initialize(int surface_view_id) override;
void Cleanup(bool have_context,
const AndroidVideoDecodeAccelerator::OutputBufferMap&) override;
+ scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture() const override;
uint32_t GetTextureTarget() const override;
- scoped_refptr<gfx::SurfaceTexture> CreateSurfaceTexture() override;
+ gfx::Size GetPictureBufferSize() const override;
void UseCodecBufferForPictureBuffer(int32_t codec_buffer_index,
const media::PictureBuffer&) override;
void CodecChanged(
media::VideoCodecBridge*,
const AndroidVideoDecodeAccelerator::OutputBufferMap&) override;
void OnFrameAvailable() override;
+ bool ArePicturesOverlayable() override;
+ void UpdatePictureBufferSize(media::PictureBuffer* picture_buffer,
+ const gfx::Size& new_size) override;
private:
// Used for copy the texture from surface texture to picture buffers.
diff --git a/chromium/content/common/gpu/media/android_deferred_rendering_backing_strategy.cc b/chromium/content/common/gpu/media/android_deferred_rendering_backing_strategy.cc
index 660785eea90..3e62629745d 100644
--- a/chromium/content/common/gpu/media/android_deferred_rendering_backing_strategy.cc
+++ b/chromium/content/common/gpu/media/android_deferred_rendering_backing_strategy.cc
@@ -4,30 +4,41 @@
#include "content/common/gpu/media/android_deferred_rendering_backing_strategy.h"
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+
+#include "base/android/build_info.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
-#include "content/common/gpu/gpu_channel.h"
#include "content/common/gpu/media/avda_codec_image.h"
#include "content/common/gpu/media/avda_return_on_failure.h"
#include "content/common/gpu/media/avda_shared_state.h"
+#include "gpu/command_buffer/service/context_group.h"
+#include "gpu/command_buffer/service/gl_stream_texture_image.h"
+#include "gpu/command_buffer/service/gles2_cmd_copy_texture_chromium.h"
#include "gpu/command_buffer/service/texture_manager.h"
+#include "gpu/ipc/common/gpu_surface_lookup.h"
+#include "gpu/ipc/service/gpu_channel.h"
#include "ui/gl/android/surface_texture.h"
+#include "ui/gl/egl_util.h"
#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_surface_egl.h"
+#include "ui/gl/scoped_binders.h"
+#include "ui/gl/scoped_make_current.h"
namespace content {
AndroidDeferredRenderingBackingStrategy::
- AndroidDeferredRenderingBackingStrategy()
- : state_provider_(nullptr), media_codec_(nullptr) {}
+ AndroidDeferredRenderingBackingStrategy(AVDAStateProvider* state_provider)
+ : state_provider_(state_provider), media_codec_(nullptr) {}
AndroidDeferredRenderingBackingStrategy::
~AndroidDeferredRenderingBackingStrategy() {}
-void AndroidDeferredRenderingBackingStrategy::Initialize(
- AVDAStateProvider* state_provider) {
- state_provider_ = state_provider;
+gfx::ScopedJavaSurface AndroidDeferredRenderingBackingStrategy::Initialize(
+ int surface_view_id) {
shared_state_ = new AVDASharedState();
// Create a texture for the SurfaceTexture to use. We don't attach it here
@@ -36,6 +47,27 @@ void AndroidDeferredRenderingBackingStrategy::Initialize(
glGenTextures(1, &service_id);
DCHECK(service_id);
shared_state_->set_surface_texture_service_id(service_id);
+
+ gfx::ScopedJavaSurface surface;
+ if (surface_view_id != media::VideoDecodeAccelerator::Config::kNoSurfaceID) {
+ surface = gpu::GpuSurfaceLookup::GetInstance()->AcquireJavaSurface(
+ surface_view_id);
+ } else {
+ if (DoesSurfaceTextureDetachWork()) {
+ // Create a detached SurfaceTexture. Detaching it will silently fail to
+ // delete texture 0.
+ surface_texture_ = gfx::SurfaceTexture::Create(0);
+ surface_texture_->DetachFromGLContext();
+ } else {
+ // Detach doesn't work so well on all platforms. Just attach the
+ // SurfaceTexture here, and probably context switch later.
+ surface_texture_ = gfx::SurfaceTexture::Create(service_id);
+ shared_state_->DidAttachSurfaceTexture();
+ }
+ surface = gfx::ScopedJavaSurface(surface_texture_.get());
+ }
+
+ return surface;
}
void AndroidDeferredRenderingBackingStrategy::Cleanup(
@@ -50,6 +82,11 @@ void AndroidDeferredRenderingBackingStrategy::Cleanup(
for (const std::pair<int, media::PictureBuffer>& entry : buffers)
SetImageForPicture(entry.second, nullptr);
+ // If we're rendering to a SurfaceTexture we can make a copy of the current
+ // front buffer so that the PictureBuffer textures are still valid.
+ if (surface_texture_ && have_context && ShouldCopyPictures())
+ CopySurfaceTextureToPictures(buffers);
+
// Now that no AVDACodecImages refer to the SurfaceTexture's texture, delete
// the texture name.
GLuint service_id = shared_state_->surface_texture_service_id();
@@ -57,38 +94,35 @@ void AndroidDeferredRenderingBackingStrategy::Cleanup(
glDeleteTextures(1, &service_id);
}
-uint32_t AndroidDeferredRenderingBackingStrategy::GetTextureTarget() const {
- return GL_TEXTURE_EXTERNAL_OES;
-}
-
scoped_refptr<gfx::SurfaceTexture>
-AndroidDeferredRenderingBackingStrategy::CreateSurfaceTexture() {
- // AVDACodecImage will handle attaching this to a texture later.
- surface_texture_ = gfx::SurfaceTexture::Create(0);
- // Detach from our GL context so that the GLImages can attach. It will
- // silently fail to delete texture 0.
- surface_texture_->DetachFromGLContext();
-
+AndroidDeferredRenderingBackingStrategy::GetSurfaceTexture() const {
return surface_texture_;
}
-gpu::gles2::TextureRef*
-AndroidDeferredRenderingBackingStrategy::GetTextureForPicture(
- const media::PictureBuffer& picture_buffer) {
- RETURN_NULL_IF_NULL(state_provider_->GetGlDecoder());
- gpu::gles2::TextureManager* texture_manager =
- state_provider_->GetGlDecoder()->GetContextGroup()->texture_manager();
- RETURN_NULL_IF_NULL(texture_manager);
- gpu::gles2::TextureRef* texture_ref =
- texture_manager->GetTexture(picture_buffer.internal_texture_id());
- RETURN_NULL_IF_NULL(texture_ref);
+uint32_t AndroidDeferredRenderingBackingStrategy::GetTextureTarget() const {
+ // If we're using a surface texture, then we need an external texture target
+ // to sample from it. If not, then we'll use 2D transparent textures to draw
+ // a transparent hole through which to see the SurfaceView. This is normally
+ // needed only for the devtools inspector, since the overlay mechanism handles
+ // it otherwise.
+ return surface_texture_ ? GL_TEXTURE_EXTERNAL_OES : GL_TEXTURE_2D;
+}
- return texture_ref;
+gfx::Size AndroidDeferredRenderingBackingStrategy::GetPictureBufferSize()
+ const {
+ // For SurfaceView, request a 1x1 2D texture to reduce memory during
+ // initialization. For SurfaceTexture, allocate a picture buffer that is the
+ // actual frame size. Note that it will be an external texture anyway, so it
+ // doesn't allocate an image of that size. However, it's still important to
+ // get the coded size right, so that VideoLayerImpl doesn't try to scale the
+ // texture when building the quad for it.
+ return surface_texture_ ? state_provider_->GetSize() : gfx::Size(1, 1);
}
AVDACodecImage* AndroidDeferredRenderingBackingStrategy::GetImageForPicture(
const media::PictureBuffer& picture_buffer) {
- gpu::gles2::TextureRef* texture_ref = GetTextureForPicture(picture_buffer);
+ gpu::gles2::TextureRef* texture_ref =
+ state_provider_->GetTextureForPicture(picture_buffer);
RETURN_NULL_IF_NULL(texture_ref);
gl::GLImage* image =
texture_ref->texture()->GetLevelImage(GetTextureTarget(), 0);
@@ -97,8 +131,9 @@ AVDACodecImage* AndroidDeferredRenderingBackingStrategy::GetImageForPicture(
void AndroidDeferredRenderingBackingStrategy::SetImageForPicture(
const media::PictureBuffer& picture_buffer,
- const scoped_refptr<gl::GLImage>& image) {
- gpu::gles2::TextureRef* texture_ref = GetTextureForPicture(picture_buffer);
+ const scoped_refptr<gpu::gles2::GLStreamTextureImage>& image) {
+ gpu::gles2::TextureRef* texture_ref =
+ state_provider_->GetTextureForPicture(picture_buffer);
RETURN_IF_NULL(texture_ref);
gpu::gles2::TextureManager* texture_manager =
@@ -120,15 +155,25 @@ void AndroidDeferredRenderingBackingStrategy::SetImageForPicture(
shared_state_->surface_texture_service_id());
static_cast<AVDACodecImage*>(image.get())
- ->setTexture(texture_ref->texture());
+ ->SetTexture(texture_ref->texture());
} else {
// Clear the unowned service_id, so that this texture is no longer going
// to depend on the surface texture at all.
texture_ref->texture()->SetUnownedServiceId(0);
}
- texture_manager->SetLevelImage(texture_ref, GetTextureTarget(), 0,
- image.get(), gpu::gles2::Texture::UNBOUND);
+ // For SurfaceTexture we set the image to UNBOUND so that the implementation
+ // will call CopyTexImage, which is where AVDACodecImage updates the
+ // SurfaceTexture to the right frame.
+ // For SurfaceView we set the image to be BOUND because ScheduleOverlayPlane
+ // expects it. If something tries to sample from this texture it won't work,
+ // but there's no way to sample from a SurfaceView anyway, so it doesn't
+ // matter. The only way to use this texture is to schedule it as an overlay.
+ const gpu::gles2::Texture::ImageState image_state =
+ surface_texture_ ? gpu::gles2::Texture::UNBOUND
+ : gpu::gles2::Texture::BOUND;
+ texture_manager->SetLevelStreamTextureImage(texture_ref, GetTextureTarget(),
+ 0, image.get(), image_state);
}
void AndroidDeferredRenderingBackingStrategy::UseCodecBufferForPictureBuffer(
@@ -139,36 +184,53 @@ void AndroidDeferredRenderingBackingStrategy::UseCodecBufferForPictureBuffer(
// Notify the AVDACodecImage for picture_buffer that it should use the
// decoded buffer codec_buf_index to render this frame.
- AVDACodecImage* avImage = GetImageForPicture(picture_buffer);
- RETURN_IF_NULL(avImage);
- DCHECK_EQ(avImage->GetMediaCodecBufferIndex(), -1);
+ AVDACodecImage* avda_image = GetImageForPicture(picture_buffer);
+ RETURN_IF_NULL(avda_image);
+ DCHECK_EQ(avda_image->GetMediaCodecBufferIndex(), -1);
// Note that this is not a race, since we do not re-use a PictureBuffer
// until after the CC is done drawing it.
- avImage->SetMediaCodecBufferIndex(codec_buf_index);
- avImage->SetSize(state_provider_->GetSize());
+ avda_image->SetMediaCodecBufferIndex(codec_buf_index);
+ avda_image->SetSize(state_provider_->GetSize());
}
void AndroidDeferredRenderingBackingStrategy::AssignOnePictureBuffer(
- const media::PictureBuffer& picture_buffer) {
+ const media::PictureBuffer& picture_buffer,
+ bool have_context) {
// Attach a GLImage to each texture that will use the surface texture.
// We use a refptr here in case SetImageForPicture fails.
- scoped_refptr<gl::GLImage> gl_image(
+ scoped_refptr<gpu::gles2::GLStreamTextureImage> gl_image =
new AVDACodecImage(shared_state_, media_codec_,
- state_provider_->GetGlDecoder(), surface_texture_));
+ state_provider_->GetGlDecoder(), surface_texture_);
SetImageForPicture(picture_buffer, gl_image);
+
+ if (!surface_texture_ && have_context) {
+ // To make devtools work, we're using a 2D texture. Make it transparent,
+ // so that it draws a hole for the SV to show through. This is only
+ // because devtools draws and reads back, which skips overlay processing.
+ // It's unclear why devtools renders twice -- once normally, and once
+ // including a readback layer. The result is that the device screen
+ // flashes as we alternately draw the overlay hole and this texture,
+ // unless we make the texture transparent.
+ static const uint8_t rgba[] = {0, 0, 0, 0};
+ const gfx::Size size(1, 1);
+ DCHECK_LE(1u, picture_buffer.texture_ids().size());
+ glBindTexture(GL_TEXTURE_2D, picture_buffer.texture_ids()[0]);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, rgba);
+ }
}
void AndroidDeferredRenderingBackingStrategy::ReleaseCodecBufferForPicture(
const media::PictureBuffer& picture_buffer) {
- AVDACodecImage* avImage = GetImageForPicture(picture_buffer);
+ AVDACodecImage* avda_image = GetImageForPicture(picture_buffer);
// See if there is a media codec buffer still attached to this image.
- const int32_t codec_buffer = avImage->GetMediaCodecBufferIndex();
+ const int32_t codec_buffer = avda_image->GetMediaCodecBufferIndex();
if (codec_buffer >= 0) {
// PictureBuffer wasn't displayed, so release the buffer.
media_codec_->ReleaseOutputBuffer(codec_buffer, false);
- avImage->SetMediaCodecBufferIndex(-1);
+ avda_image->SetMediaCodecBufferIndex(-1);
}
}
@@ -181,18 +243,6 @@ void AndroidDeferredRenderingBackingStrategy::ReuseOnePictureBuffer(
ReleaseCodecBufferForPicture(picture_buffer);
}
-void AndroidDeferredRenderingBackingStrategy::DismissOnePictureBuffer(
- const media::PictureBuffer& picture_buffer) {
- // If there is an outstanding codec buffer attached to this image, then
- // release it.
- ReleaseCodecBufferForPicture(picture_buffer);
-
- // This makes sure that the Texture no longer refers to the codec or to the
- // SurfaceTexture's service_id. That's important, so that it doesn't refer
- // to the texture by name after we've deleted it.
- SetImageForPicture(picture_buffer, nullptr);
-}
-
void AndroidDeferredRenderingBackingStrategy::CodecChanged(
media::VideoCodecBridge* codec,
const AndroidVideoDecodeAccelerator::OutputBufferMap& buffers) {
@@ -200,9 +250,9 @@ void AndroidDeferredRenderingBackingStrategy::CodecChanged(
// doesn't know about them.
media_codec_ = codec;
for (const std::pair<int, media::PictureBuffer>& entry : buffers) {
- AVDACodecImage* avImage = GetImageForPicture(entry.second);
- avImage->SetMediaCodec(codec);
- avImage->SetMediaCodecBufferIndex(-1);
+ AVDACodecImage* avda_image = GetImageForPicture(entry.second);
+ avda_image->SetMediaCodec(codec);
+ avda_image->SetMediaCodecBufferIndex(-1);
}
}
@@ -210,4 +260,163 @@ void AndroidDeferredRenderingBackingStrategy::OnFrameAvailable() {
shared_state_->SignalFrameAvailable();
}
+bool AndroidDeferredRenderingBackingStrategy::ArePicturesOverlayable() {
+ // SurfaceView frames are always overlayable because that's the only way to
+ // display them.
+ return !surface_texture_;
+}
+
+void AndroidDeferredRenderingBackingStrategy::UpdatePictureBufferSize(
+ media::PictureBuffer* picture_buffer,
+ const gfx::Size& new_size) {
+ // This strategy uses EGL images which manage the texture size for us. We
+ // simply update the PictureBuffer meta-data and leave the texture as-is.
+ picture_buffer->set_size(new_size);
+}
+
+void AndroidDeferredRenderingBackingStrategy::CopySurfaceTextureToPictures(
+ const AndroidVideoDecodeAccelerator::OutputBufferMap& buffers) {
+ DVLOG(3) << __FUNCTION__;
+
+ // Don't try to copy if the SurfaceTexture was never attached because that
+ // means it was never updated.
+ if (!shared_state_->surface_texture_is_attached())
+ return;
+
+ gpu::gles2::GLES2Decoder* gl_decoder = state_provider_->GetGlDecoder().get();
+ if (!gl_decoder)
+ return;
+
+ const gfx::Size size = state_provider_->GetSize();
+
+ // Create a 2D texture to hold a copy of the SurfaceTexture's front buffer.
+ GLuint tmp_texture_id;
+ glGenTextures(1, &tmp_texture_id);
+ {
+ gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, tmp_texture_id);
+ // The target texture's size will exactly match the source.
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+ }
+
+
+
+ float transform_matrix[16];
+ surface_texture_->GetTransformMatrix(transform_matrix);
+
+ gpu::CopyTextureCHROMIUMResourceManager copier;
+ copier.Initialize(
+ gl_decoder,
+ gl_decoder->GetContextGroup()->feature_info()->feature_flags());
+ copier.DoCopyTextureWithTransform(gl_decoder, GL_TEXTURE_EXTERNAL_OES,
+ shared_state_->surface_texture_service_id(),
+ GL_TEXTURE_2D, tmp_texture_id, size.width(),
+ size.height(), true, false, false,
+ transform_matrix);
+
+ // Create an EGLImage from the 2D texture we just copied into. By associating
+ // the EGLImage with the PictureBuffer textures they will remain valid even
+ // after we delete the 2D texture and EGLImage.
+ const EGLImageKHR egl_image = eglCreateImageKHR(
+ gfx::GLSurfaceEGL::GetHardwareDisplay(), eglGetCurrentContext(),
+ EGL_GL_TEXTURE_2D_KHR, reinterpret_cast<EGLClientBuffer>(tmp_texture_id),
+ nullptr /* attrs */);
+
+ glDeleteTextures(1, &tmp_texture_id);
+ DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+
+ if (egl_image == EGL_NO_IMAGE_KHR) {
+ DLOG(ERROR) << "Failed creating EGLImage: " << ui::GetLastEGLErrorString();
+ return;
+ }
+
+ for (const std::pair<int, media::PictureBuffer>& entry : buffers) {
+ gpu::gles2::TextureRef* texture_ref =
+ state_provider_->GetTextureForPicture(entry.second);
+ if (!texture_ref)
+ continue;
+ gfx::ScopedTextureBinder texture_binder(
+ GL_TEXTURE_EXTERNAL_OES, texture_ref->texture()->service_id());
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_image);
+ DCHECK_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+ }
+
+ EGLBoolean result =
+ eglDestroyImageKHR(gfx::GLSurfaceEGL::GetHardwareDisplay(), egl_image);
+ if (result == EGL_FALSE) {
+ DLOG(ERROR) << "Error destroying EGLImage: "
+ << ui::GetLastEGLErrorString();
+ }
+}
+
+bool AndroidDeferredRenderingBackingStrategy::DoesSurfaceTextureDetachWork()
+ const {
+ bool surface_texture_detach_works = true;
+ if (gpu::gles2::GLES2Decoder* gl_decoder =
+ state_provider_->GetGlDecoder().get()) {
+ if (gpu::gles2::ContextGroup* group = gl_decoder->GetContextGroup()) {
+ if (gpu::gles2::FeatureInfo* feature_info = group->feature_info()) {
+ surface_texture_detach_works =
+ !feature_info->workarounds().surface_texture_cant_detach;
+ }
+ }
+ }
+
+ // As a special case, the MicroMax A114 doesn't get the workaround, even
+ // though it should. Hardcode it here until we get a device and figure out
+ // why. crbug.com/591600
+ if (base::android::BuildInfo::GetInstance()->sdk_int() <= 18) { // JB
+ const std::string brand(
+ base::ToLowerASCII(base::android::BuildInfo::GetInstance()->brand()));
+ if (brand == "micromax") {
+ const std::string model(
+ base::ToLowerASCII(base::android::BuildInfo::GetInstance()->model()));
+ if (model.find("a114") != std::string::npos)
+ surface_texture_detach_works = false;
+ }
+ }
+
+ return surface_texture_detach_works;
+}
+
+bool AndroidDeferredRenderingBackingStrategy::ShouldCopyPictures() const {
+ // Mali + <= KitKat crashes when we try to do this. We don't know if it's
+ // due to detaching a surface texture, but it's the same set of devices.
+ if (!DoesSurfaceTextureDetachWork())
+ return false;
+
+ // Other devices are unreliable for other reasons (e.g., EGLImage).
+ if (gpu::gles2::GLES2Decoder* gl_decoder =
+ state_provider_->GetGlDecoder().get()) {
+ if (gpu::gles2::ContextGroup* group = gl_decoder->GetContextGroup()) {
+ if (gpu::gles2::FeatureInfo* feature_info = group->feature_info()) {
+ return !feature_info->workarounds().avda_dont_copy_pictures;
+ }
+ }
+ }
+
+ // Samsung Galaxy Tab A, J3, and J1 Mini all like to crash on Lollipop in
+ // glEGLImageTargetTexture2DOES . Exact models were SM-T280, SM-J320F,
+ // and SM-j105H.
+ if (base::android::BuildInfo::GetInstance()->sdk_int() <= 22) { // L MR1
+ const std::string brand(
+ base::ToLowerASCII(base::android::BuildInfo::GetInstance()->brand()));
+ if (brand == "samsung") {
+ const std::string model(
+ base::ToLowerASCII(base::android::BuildInfo::GetInstance()->model()));
+ if (model.find("sm-t280") != std::string::npos ||
+ model.find("sm-j320f") != std::string::npos ||
+ model.find("sm-j105") != std::string::npos)
+ return false;
+ }
+ }
+
+ // Assume so.
+ return true;
+}
+
} // namespace content
diff --git a/chromium/content/common/gpu/media/android_deferred_rendering_backing_strategy.h b/chromium/content/common/gpu/media/android_deferred_rendering_backing_strategy.h
index 6fc1873cf5a..733b25b0a45 100644
--- a/chromium/content/common/gpu/media/android_deferred_rendering_backing_strategy.h
+++ b/chromium/content/common/gpu/media/android_deferred_rendering_backing_strategy.h
@@ -17,6 +17,7 @@ class GLImage;
namespace gpu {
namespace gles2 {
+class GLStreamTextureImage;
class TextureRef;
}
}
@@ -33,42 +34,61 @@ class AVDASharedState;
class CONTENT_EXPORT AndroidDeferredRenderingBackingStrategy
: public AndroidVideoDecodeAccelerator::BackingStrategy {
public:
- AndroidDeferredRenderingBackingStrategy();
+ explicit AndroidDeferredRenderingBackingStrategy(
+ AVDAStateProvider* state_provider);
~AndroidDeferredRenderingBackingStrategy() override;
// AndroidVideoDecodeAccelerator::BackingStrategy
- void Initialize(AVDAStateProvider*) override;
+ gfx::ScopedJavaSurface Initialize(int surface_view_id) override;
void Cleanup(bool have_context,
const AndroidVideoDecodeAccelerator::OutputBufferMap&) override;
+ scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture() const override;
uint32_t GetTextureTarget() const override;
- scoped_refptr<gfx::SurfaceTexture> CreateSurfaceTexture() override;
+ gfx::Size GetPictureBufferSize() const override;
void UseCodecBufferForPictureBuffer(int32_t codec_buffer_index,
const media::PictureBuffer&) override;
- void AssignOnePictureBuffer(const media::PictureBuffer&) override;
+ void AssignOnePictureBuffer(const media::PictureBuffer&, bool) override;
void ReuseOnePictureBuffer(const media::PictureBuffer&) override;
- void DismissOnePictureBuffer(const media::PictureBuffer&) override;
void CodecChanged(
media::VideoCodecBridge*,
const AndroidVideoDecodeAccelerator::OutputBufferMap&) override;
void OnFrameAvailable() override;
+ bool ArePicturesOverlayable() override;
+ void UpdatePictureBufferSize(media::PictureBuffer* picture_buffer,
+ const gfx::Size& new_size) override;
private:
// Release any codec buffer that is associated with the given picture buffer
// back to the codec. It is okay if there is no such buffer.
void ReleaseCodecBufferForPicture(const media::PictureBuffer& picture_buffer);
- // Return the TextureRef for a given PictureBuffer's texture.
- gpu::gles2::TextureRef* GetTextureForPicture(const media::PictureBuffer&);
-
// Return the AVDACodecImage for a given PictureBuffer's texture.
AVDACodecImage* GetImageForPicture(const media::PictureBuffer&);
- void SetImageForPicture(const media::PictureBuffer& picture_buffer,
- const scoped_refptr<gl::GLImage>& image);
+ void SetImageForPicture(
+ const media::PictureBuffer& picture_buffer,
+ const scoped_refptr<gpu::gles2::GLStreamTextureImage>& image);
+
+ // Make a copy of the SurfaceTexture's front buffer and associate all given
+ // picture buffer textures with it. The picture buffer textures will not
+ // dependend on |this|, the SurfaceTexture, the MediaCodec or the VDA, so it's
+ // used to back the picture buffers when the VDA is being destroyed.
+ void CopySurfaceTextureToPictures(
+ const AndroidVideoDecodeAccelerator::OutputBufferMap& buffers);
+
+ // Return true if and only if the surface_texture_cant_detach workaround is
+ // not set.
+ bool DoesSurfaceTextureDetachWork() const;
+
+ // Return true if and only if CopySurfaceTextureToPictures is expected to work
+ // on this device.
+ bool ShouldCopyPictures() const;
scoped_refptr<AVDASharedState> shared_state_;
AVDAStateProvider* state_provider_;
+ // The SurfaceTexture to render to. Non-null after Initialize() if
+ // we're not rendering to a SurfaceView.
scoped_refptr<gfx::SurfaceTexture> surface_texture_;
media::VideoCodecBridge* media_codec_;
diff --git a/chromium/content/common/gpu/media/android_video_decode_accelerator.cc b/chromium/content/common/gpu/media/android_video_decode_accelerator.cc
index 832d8dca218..e4f45ca73b3 100644
--- a/chromium/content/common/gpu/media/android_video_decode_accelerator.cc
+++ b/chromium/content/common/gpu/media/android_video_decode_accelerator.cc
@@ -7,21 +7,30 @@
#include <stddef.h>
#include "base/android/build_info.h"
+#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
+#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
+#include "base/task_runner_util.h"
+#include "base/threading/thread_checker.h"
#include "base/trace_event/trace_event.h"
-#include "content/common/gpu/gpu_channel.h"
#include "content/common/gpu/media/android_copying_backing_strategy.h"
#include "content/common/gpu/media/android_deferred_rendering_backing_strategy.h"
+#include "content/common/gpu/media/avda_return_on_failure.h"
+#include "content/common/gpu/media/shared_memory_region.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
+#include "gpu/command_buffer/service/mailbox_manager.h"
+#include "gpu/ipc/service/gpu_channel.h"
+#include "media/base/android/media_codec_bridge.h"
+#include "media/base/android/media_codec_util.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/bitstream_buffer.h"
#include "media/base/limits.h"
-#include "media/base/media_switches.h"
+#include "media/base/media.h"
#include "media/base/timestamp_constants.h"
#include "media/base/video_decoder_config.h"
#include "media/video/picture.h"
@@ -30,7 +39,6 @@
#include "ui/gl/gl_bindings.h"
#if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
-#include "media/base/media_keys.h"
#include "media/mojo/services/mojo_cdm_service.h"
#endif
@@ -92,6 +100,23 @@ static inline const base::TimeDelta IdleTimerTimeOut() {
return base::TimeDelta::FromSeconds(1);
}
+// Time between when we notice an error, and when we actually notify somebody.
+// This is to prevent codec errors caused by SurfaceView fullscreen transitions
+// from breaking the pipeline, if we're about to be reset anyway.
+static inline const base::TimeDelta ErrorPostingDelay() {
+ return base::TimeDelta::FromSeconds(2);
+}
+
+// For RecordFormatChangedMetric.
+enum FormatChangedValue {
+ CodecInitialized = false,
+ MissingFormatChanged = true
+};
+
+static inline void RecordFormatChangedMetric(FormatChangedValue value) {
+ UMA_HISTOGRAM_BOOLEAN("Media.AVDA.MissingFormatChanged", !!value);
+}
+
// Handle OnFrameAvailable callbacks safely. Since they occur asynchronously,
// we take care that the AVDA that wants them still exists. A WeakPtr to
// the AVDA would be preferable, except that OnFrameAvailable callbacks can
@@ -143,34 +168,166 @@ class AndroidVideoDecodeAccelerator::OnFrameAvailableHandler
DISALLOW_COPY_AND_ASSIGN(OnFrameAvailableHandler);
};
+// Helper class to share an IO timer for DoIOTask() execution; prevents each
+// AVDA instance from starting its own high frequency timer. The intuition
+// behind this is that, if we're waiting for long enough, then either (a)
+// MediaCodec is broken or (b) MediaCodec is waiting on us to change state
+// (e.g., get new demuxed data / get a free picture buffer / return an output
+// buffer to MediaCodec). This is inherently a race, since we don't know if
+// MediaCodec is broken or just slow. Since the MediaCodec API doesn't let
+// us wait on MediaCodec state changes prior to L, we more or less have to
+// time out or keep polling forever in some common cases.
+class AVDATimerManager {
+ public:
+ // Make sure that the construction thread is started for |avda_instance|.
+ bool StartThread(AndroidVideoDecodeAccelerator* avda_instance) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (thread_avda_instances_.empty()) {
+ if (!construction_thread_.Start()) {
+ LOG(ERROR) << "Failed to start construction thread.";
+ return false;
+ }
+ }
+
+ thread_avda_instances_.insert(avda_instance);
+ return true;
+ }
+
+ // |avda_instance| will no longer need the construction thread. Stop the
+ // thread if this is the last instance.
+ void StopThread(AndroidVideoDecodeAccelerator* avda_instance) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ thread_avda_instances_.erase(avda_instance);
+ if (thread_avda_instances_.empty())
+ construction_thread_.Stop();
+ }
+
+ // Request periodic callback of |avda_instance|->DoIOTask(). Does nothing if
+ // the instance is already registered and the timer started. The first request
+ // will start the repeating timer on an interval of DecodePollDelay().
+ void StartTimer(AndroidVideoDecodeAccelerator* avda_instance) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ timer_avda_instances_.insert(avda_instance);
+
+ // If the timer is running, StopTimer() might have been called earlier, if
+ // so remove the instance from the pending erasures.
+ if (timer_running_)
+ pending_erase_.erase(avda_instance);
+
+ if (io_timer_.IsRunning())
+ return;
+ io_timer_.Start(FROM_HERE, DecodePollDelay(), this,
+ &AVDATimerManager::RunTimer);
+ }
+
+ // Stop callbacks to |avda_instance|->DoIOTask(). Does nothing if the instance
+ // is not registered. If there are no instances left, the repeating timer will
+ // be stopped.
+ void StopTimer(AndroidVideoDecodeAccelerator* avda_instance) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // If the timer is running, defer erasures to avoid iterator invalidation.
+ if (timer_running_) {
+ pending_erase_.insert(avda_instance);
+ return;
+ }
+
+ timer_avda_instances_.erase(avda_instance);
+ if (timer_avda_instances_.empty())
+ io_timer_.Stop();
+ }
+
+ // Eventually, we should run the timer on this thread. For now, we just keep
+ // it as a convenience for construction.
+ scoped_refptr<base::SingleThreadTaskRunner> ConstructionTaskRunner() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return construction_thread_.task_runner();
+ }
+
+ private:
+ friend struct base::DefaultLazyInstanceTraits<AVDATimerManager>;
+
+ AVDATimerManager() : construction_thread_("AVDAThread") {}
+ ~AVDATimerManager() { NOTREACHED(); }
+
+ void RunTimer() {
+ {
+ // Call out to all AVDA instances, some of which may attempt to remove
+ // themselves from the list during this operation; those removals will be
+ // deferred until after all iterations are complete.
+ base::AutoReset<bool> scoper(&timer_running_, true);
+ for (auto* avda : timer_avda_instances_)
+ avda->DoIOTask(false);
+ }
+
+ // Take care of any deferred erasures.
+ for (auto* avda : pending_erase_)
+ StopTimer(avda);
+ pending_erase_.clear();
+
+ // TODO(dalecurtis): We may want to consider chunking this if task execution
+ // takes too long for the combined timer.
+ }
+
+ // All AVDA instances that would like us to poll DoIOTask.
+ std::set<AndroidVideoDecodeAccelerator*> timer_avda_instances_;
+
+ // All AVDA instances that might like to use the construction thread.
+ std::set<AndroidVideoDecodeAccelerator*> thread_avda_instances_;
+
+ // Since we can't delete while iterating when using a set, defer erasure until
+ // after iteration complete.
+ bool timer_running_ = false;
+ std::set<AndroidVideoDecodeAccelerator*> pending_erase_;
+
+ // Repeating timer responsible for draining pending IO to the codecs.
+ base::RepeatingTimer io_timer_;
+
+ base::Thread construction_thread_;
+
+ base::ThreadChecker thread_checker_;
+
+ DISALLOW_COPY_AND_ASSIGN(AVDATimerManager);
+};
+
+static base::LazyInstance<AVDATimerManager>::Leaky g_avda_timer =
+ LAZY_INSTANCE_INITIALIZER;
+
+AndroidVideoDecodeAccelerator::CodecConfig::CodecConfig() {}
+
+AndroidVideoDecodeAccelerator::CodecConfig::~CodecConfig() {}
+
AndroidVideoDecodeAccelerator::AndroidVideoDecodeAccelerator(
- const base::WeakPtr<gpu::gles2::GLES2Decoder> decoder,
- const base::Callback<bool(void)>& make_context_current)
+ const MakeGLContextCurrentCallback& make_context_current_cb,
+ const GetGLES2DecoderCallback& get_gles2_decoder_cb)
: client_(NULL),
- make_context_current_(make_context_current),
- codec_(media::kCodecH264),
+ make_context_current_cb_(make_context_current_cb),
+ get_gles2_decoder_cb_(get_gles2_decoder_cb),
is_encrypted_(false),
- needs_protected_surface_(false),
state_(NO_ERROR),
picturebuffers_requested_(false),
- gl_decoder_(decoder),
+ media_drm_bridge_cdm_context_(nullptr),
cdm_registration_id_(0),
- weak_this_factory_(this) {
- if (UseDeferredRenderingStrategy())
- strategy_.reset(new AndroidDeferredRenderingBackingStrategy());
- else
- strategy_.reset(new AndroidCopyingBackingStrategy());
-}
+ pending_input_buf_index_(-1),
+ error_sequence_token_(0),
+ defer_errors_(false),
+ deferred_initialization_pending_(false),
+ weak_this_factory_(this) {}
AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() {
DCHECK(thread_checker_.CalledOnValidThread());
+ g_avda_timer.Pointer()->StopTimer(this);
+ g_avda_timer.Pointer()->StopThread(this);
#if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
- if (cdm_) {
- DCHECK(cdm_registration_id_);
- static_cast<media::MediaDrmBridge*>(cdm_.get())
- ->UnregisterPlayer(cdm_registration_id_);
- }
+ if (!media_drm_bridge_cdm_context_)
+ return;
+
+ DCHECK(cdm_registration_id_);
+ media_drm_bridge_cdm_context_->UnregisterPlayer(cdm_registration_id_);
#endif // defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
}
@@ -182,76 +339,130 @@ bool AndroidVideoDecodeAccelerator::Initialize(const Config& config,
DVLOG(1) << __FUNCTION__ << ": " << config.AsHumanReadableString();
+ if (make_context_current_cb_.is_null() || get_gles2_decoder_cb_.is_null()) {
+ NOTREACHED() << "GL callbacks are required for this VDA";
+ return false;
+ }
+
DCHECK(client);
client_ = client;
- codec_ = VideoCodecProfileToVideoCodec(config.profile);
+ codec_config_ = new CodecConfig();
+ codec_config_->codec_ = VideoCodecProfileToVideoCodec(config.profile);
+ codec_config_->initial_expected_coded_size_ =
+ config.initial_expected_coded_size;
is_encrypted_ = config.is_encrypted;
- bool profile_supported = codec_ == media::kCodecVP8 ||
- codec_ == media::kCodecVP9 ||
- codec_ == media::kCodecH264;
+ bool profile_supported = codec_config_->codec_ == media::kCodecVP8 ||
+ codec_config_->codec_ == media::kCodecVP9 ||
+ codec_config_->codec_ == media::kCodecH264;
+
+ // We signalled that we support deferred initialization, so see if the client
+ // does also.
+ deferred_initialization_pending_ = config.is_deferred_initialization_allowed;
if (!profile_supported) {
LOG(ERROR) << "Unsupported profile: " << config.profile;
return false;
}
+ // For encrypted streams we postpone configuration until MediaCrypto is
+ // available.
+ DCHECK(!is_encrypted_ || deferred_initialization_pending_);
+
// Only use MediaCodec for VP8/9 if it's likely backed by hardware
// or if the stream is encrypted.
- if ((codec_ == media::kCodecVP8 || codec_ == media::kCodecVP9) &&
- !is_encrypted_) {
- if (media::VideoCodecBridge::IsKnownUnaccelerated(
- codec_, media::MEDIA_CODEC_DECODER)) {
- DVLOG(1) << "Initialization failed: "
- << (codec_ == media::kCodecVP8 ? "vp8" : "vp9")
- << " is not hardware accelerated";
- return false;
- }
+ if ((codec_config_->codec_ == media::kCodecVP8 ||
+ codec_config_->codec_ == media::kCodecVP9) &&
+ !is_encrypted_ &&
+ media::VideoCodecBridge::IsKnownUnaccelerated(
+ codec_config_->codec_, media::MEDIA_CODEC_DECODER)) {
+ DVLOG(1) << "Initialization failed: "
+ << (codec_config_->codec_ == media::kCodecVP8 ? "vp8" : "vp9")
+ << " is not hardware accelerated";
+ return false;
}
- if (!make_context_current_.Run()) {
+ auto gles_decoder = get_gles2_decoder_cb_.Run();
+ if (!gles_decoder) {
+ LOG(ERROR) << "Failed to get gles2 decoder instance.";
+ return false;
+ }
+
+ const gpu::GpuPreferences& gpu_preferences =
+ gles_decoder->GetContextGroup()->gpu_preferences();
+
+ if (UseDeferredRenderingStrategy(gpu_preferences)) {
+ // TODO(liberato, watk): Figure out what we want to do about zero copy for
+ // fullscreen external SurfaceView in WebView. http://crbug.com/582170.
+ DCHECK(!gles_decoder->GetContextGroup()->mailbox_manager()->UsesSync());
+ DVLOG(1) << __FUNCTION__ << ", using deferred rendering strategy.";
+ strategy_.reset(new AndroidDeferredRenderingBackingStrategy(this));
+ } else {
+ DVLOG(1) << __FUNCTION__ << ", using copy back strategy.";
+ strategy_.reset(new AndroidCopyingBackingStrategy(this));
+ }
+
+ if (!make_context_current_cb_.Run()) {
LOG(ERROR) << "Failed to make this decoder's GL context current.";
return false;
}
- if (!gl_decoder_) {
- LOG(ERROR) << "Failed to get gles2 decoder instance.";
+ codec_config_->surface_ = strategy_->Initialize(config.surface_id);
+ if (codec_config_->surface_.IsEmpty()) {
+ LOG(ERROR) << "Failed to initialize the backing strategy. The returned "
+ "Java surface is empty.";
return false;
}
- strategy_->Initialize(this);
+ // TODO(watk,liberato): move this into the strategy.
+ scoped_refptr<gfx::SurfaceTexture> surface_texture =
+ strategy_->GetSurfaceTexture();
+ if (surface_texture) {
+ on_frame_available_handler_ =
+ new OnFrameAvailableHandler(this, surface_texture);
+ }
- surface_texture_ = strategy_->CreateSurfaceTexture();
- on_frame_available_handler_ =
- new OnFrameAvailableHandler(this, surface_texture_);
+ // Start the thread for async configuration, even if we don't need it now.
+ // ResetCodecState might rebuild the codec later, for example.
+ if (!g_avda_timer.Pointer()->StartThread(this)) {
+ LOG(ERROR) << "Failed to start thread for AVDA timer";
+ return false;
+ }
- // For encrypted streams we postpone configuration until MediaCrypto is
- // available.
+ // If we are encrypted, then we aren't able to create the codec yet.
if (is_encrypted_)
return true;
- return ConfigureMediaCodec();
+ if (deferred_initialization_pending_) {
+ ConfigureMediaCodecAsynchronously();
+ return true;
+ }
+
+ // If the client doesn't support deferred initialization (WebRTC), then we
+ // should complete it now and return a meaningful result.
+ return ConfigureMediaCodecSynchronously();
}
void AndroidVideoDecodeAccelerator::SetCdm(int cdm_id) {
DVLOG(2) << __FUNCTION__ << ": " << cdm_id;
#if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
- using media::MediaDrmBridge;
-
DCHECK(client_) << "SetCdm() must be called after Initialize().";
- if (cdm_) {
+ if (media_drm_bridge_cdm_context_) {
NOTREACHED() << "We do not support resetting CDM.";
- NotifyCdmAttached(false);
+ NotifyInitializationComplete(false);
return;
}
- cdm_ = media::MojoCdmService::GetCdm(cdm_id);
- DCHECK(cdm_);
+ // Store the CDM to hold a reference to it.
+ cdm_for_reference_holding_only_ = media::MojoCdmService::LegacyGetCdm(cdm_id);
+ DCHECK(cdm_for_reference_holding_only_);
- // On Android platform the MediaKeys will be its subclass MediaDrmBridge.
- MediaDrmBridge* drm_bridge = static_cast<MediaDrmBridge*>(cdm_.get());
+ // On Android platform the CdmContext must be a MediaDrmBridgeCdmContext.
+ media_drm_bridge_cdm_context_ = static_cast<media::MediaDrmBridgeCdmContext*>(
+ cdm_for_reference_holding_only_->GetCdmContext());
+ DCHECK(media_drm_bridge_cdm_context_);
// Register CDM callbacks. The callbacks registered will be posted back to
// this thread via BindToCurrentLoop.
@@ -261,31 +472,30 @@ void AndroidVideoDecodeAccelerator::SetCdm(int cdm_id) {
// destructed as well. So the |cdm_unset_cb| will never have a chance to be
// called.
// TODO(xhwang): Remove |cdm_unset_cb| after it's not used on all platforms.
- cdm_registration_id_ =
- drm_bridge->RegisterPlayer(media::BindToCurrentLoop(base::Bind(
- &AndroidVideoDecodeAccelerator::OnKeyAdded,
- weak_this_factory_.GetWeakPtr())),
- base::Bind(&base::DoNothing));
+ cdm_registration_id_ = media_drm_bridge_cdm_context_->RegisterPlayer(
+ media::BindToCurrentLoop(
+ base::Bind(&AndroidVideoDecodeAccelerator::OnKeyAdded,
+ weak_this_factory_.GetWeakPtr())),
+ base::Bind(&base::DoNothing));
- drm_bridge->SetMediaCryptoReadyCB(media::BindToCurrentLoop(
+ media_drm_bridge_cdm_context_->SetMediaCryptoReadyCB(media::BindToCurrentLoop(
base::Bind(&AndroidVideoDecodeAccelerator::OnMediaCryptoReady,
weak_this_factory_.GetWeakPtr())));
- // Postpone NotifyCdmAttached() call till we create the MediaCodec after
- // OnMediaCryptoReady().
-
+// Postpone NotifyInitializationComplete() call till we create the MediaCodec
+// after OnMediaCryptoReady().
#else
NOTIMPLEMENTED();
- NotifyCdmAttached(false);
+ NotifyInitializationComplete(false);
#endif // !defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
}
-void AndroidVideoDecodeAccelerator::DoIOTask() {
+void AndroidVideoDecodeAccelerator::DoIOTask(bool start_timer) {
DCHECK(thread_checker_.CalledOnValidThread());
TRACE_EVENT0("media", "AVDA::DoIOTask");
- if (state_ == ERROR) {
+ if (state_ == ERROR || state_ == WAITING_FOR_CODEC) {
return;
}
@@ -293,49 +503,69 @@ void AndroidVideoDecodeAccelerator::DoIOTask() {
while (DequeueOutput())
did_work = true;
- ManageTimer(did_work);
+ ManageTimer(did_work || start_timer);
}
bool AndroidVideoDecodeAccelerator::QueueInput() {
DCHECK(thread_checker_.CalledOnValidThread());
TRACE_EVENT0("media", "AVDA::QueueInput");
+ base::AutoReset<bool> auto_reset(&defer_errors_, true);
if (bitstreams_notified_in_advance_.size() > kMaxBitstreamsNotifiedInAdvance)
return false;
if (pending_bitstream_buffers_.empty())
return false;
+ if (state_ == WAITING_FOR_KEY)
+ return false;
- int input_buf_index = 0;
- media::MediaCodecStatus status =
- media_codec_->DequeueInputBuffer(NoWaitTimeOut(), &input_buf_index);
+ int input_buf_index = pending_input_buf_index_;
- if (status == media::MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER)
- return false;
- if (status == media::MEDIA_CODEC_ERROR) {
- POST_ERROR(PLATFORM_FAILURE, "Failed to DequeueInputBuffer");
- return false;
+ // Do not dequeue a new input buffer if we failed with MEDIA_CODEC_NO_KEY.
+ // That status does not return this buffer back to the pool of
+ // available input buffers. We have to reuse it in QueueSecureInputBuffer().
+ if (input_buf_index == -1) {
+ media::MediaCodecStatus status =
+ media_codec_->DequeueInputBuffer(NoWaitTimeOut(), &input_buf_index);
+ switch (status) {
+ case media::MEDIA_CODEC_DEQUEUE_INPUT_AGAIN_LATER:
+ return false;
+ case media::MEDIA_CODEC_ERROR:
+ POST_ERROR(PLATFORM_FAILURE, "Failed to DequeueInputBuffer");
+ return false;
+ case media::MEDIA_CODEC_OK:
+ break;
+ default:
+ NOTREACHED() << "Unknown DequeueInputBuffer status " << status;
+ return false;
+ }
}
- DCHECK_EQ(status, media::MEDIA_CODEC_OK);
- base::Time queued_time = pending_bitstream_buffers_.front().second;
- UMA_HISTOGRAM_TIMES("Media.AVDA.InputQueueTime",
- base::Time::Now() - queued_time);
- media::BitstreamBuffer bitstream_buffer =
- pending_bitstream_buffers_.front().first;
+ DCHECK_NE(input_buf_index, -1);
+
+ media::BitstreamBuffer bitstream_buffer = pending_bitstream_buffers_.front();
if (bitstream_buffer.id() == -1) {
pending_bitstream_buffers_.pop();
TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount",
pending_bitstream_buffers_.size());
+ DCHECK_NE(state_, ERROR);
+ state_ = WAITING_FOR_EOS;
media_codec_->QueueEOS(input_buf_index);
return true;
}
- scoped_ptr<base::SharedMemory> shm(
- new base::SharedMemory(bitstream_buffer.handle(), true));
- if (!shm->Map(bitstream_buffer.size())) {
- POST_ERROR(UNREADABLE_INPUT, "Failed to SharedMemory::Map()");
- return false;
+ scoped_ptr<SharedMemoryRegion> shm;
+
+ if (pending_input_buf_index_ == -1) {
+ // When |pending_input_buf_index_| is not -1, the buffer is already dequeued
+ // from MediaCodec, filled with data and bitstream_buffer.handle() is
+ // closed.
+ shm.reset(new SharedMemoryRegion(bitstream_buffer, true));
+
+ if (!shm->Map()) {
+ POST_ERROR(UNREADABLE_INPUT, "Failed to SharedMemoryRegion::Map()");
+ return false;
+ }
}
const base::TimeDelta presentation_timestamp =
@@ -351,12 +581,16 @@ bool AndroidVideoDecodeAccelerator::QueueInput() {
// result in them finding the right timestamp.
bitstream_buffers_in_decoder_[presentation_timestamp] = bitstream_buffer.id();
- const uint8_t* memory = static_cast<const uint8_t*>(shm->memory());
+ // Notice that |memory| will be null if we repeatedly enqueue the same buffer,
+ // this happens after MEDIA_CODEC_NO_KEY.
+ const uint8_t* memory =
+ shm ? static_cast<const uint8_t*>(shm->memory()) : nullptr;
const std::string& key_id = bitstream_buffer.key_id();
const std::string& iv = bitstream_buffer.iv();
const std::vector<media::SubsampleEntry>& subsamples =
bitstream_buffer.subsamples();
+ media::MediaCodecStatus status;
if (key_id.empty() || iv.empty()) {
status = media_codec_->QueueInputBuffer(input_buf_index, memory,
bitstream_buffer.size(),
@@ -372,24 +606,18 @@ bool AndroidVideoDecodeAccelerator::QueueInput() {
<< " status:" << status;
if (status == media::MEDIA_CODEC_NO_KEY) {
- // Keep trying to enqueue the front pending buffer.
- //
- // TODO(timav): Figure out whether stopping the pipeline in response to
- // this error and restarting it in OnKeyAdded() has significant benefits
- // (e.g. saving power).
+ // Keep trying to enqueue the same input buffer.
+ // The buffer is owned by us (not the MediaCodec) and is filled with data.
DVLOG(1) << "QueueSecureInputBuffer failed: NO_KEY";
- return true;
+ pending_input_buf_index_ = input_buf_index;
+ state_ = WAITING_FOR_KEY;
+ return false;
}
+ pending_input_buf_index_ = -1;
pending_bitstream_buffers_.pop();
TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount",
pending_bitstream_buffers_.size());
-
- if (status != media::MEDIA_CODEC_OK) {
- POST_ERROR(PLATFORM_FAILURE, "Failed to QueueInputBuffer: " << status);
- return false;
- }
-
// We should call NotifyEndOfBitstreamBuffer(), when no more decoded output
// will be returned from the bitstream buffer. However, MediaCodec API is
// not enough to guarantee it.
@@ -403,12 +631,18 @@ bool AndroidVideoDecodeAccelerator::QueueInput() {
weak_this_factory_.GetWeakPtr(), bitstream_buffer.id()));
bitstreams_notified_in_advance_.push_back(bitstream_buffer.id());
+ if (status != media::MEDIA_CODEC_OK) {
+ POST_ERROR(PLATFORM_FAILURE, "Failed to QueueInputBuffer: " << status);
+ return false;
+ }
+
return true;
}
bool AndroidVideoDecodeAccelerator::DequeueOutput() {
DCHECK(thread_checker_.CalledOnValidThread());
TRACE_EVENT0("media", "AVDA::DequeueOutput");
+ base::AutoReset<bool> auto_reset(&defer_errors_, true);
if (picturebuffers_requested_ && output_picture_buffers_.empty())
return false;
@@ -432,10 +666,6 @@ bool AndroidVideoDecodeAccelerator::DequeueOutput() {
"presentation_timestamp (ms)",
presentation_timestamp.InMilliseconds());
- DVLOG(3) << "AVDA::DequeueOutput: pts:" << presentation_timestamp
- << " buf_index:" << buf_index << " offset:" << offset
- << " size:" << size << " eos:" << eos;
-
switch (status) {
case media::MEDIA_CODEC_ERROR:
POST_ERROR(PLATFORM_FAILURE, "DequeueOutputBuffer failed.");
@@ -445,23 +675,30 @@ bool AndroidVideoDecodeAccelerator::DequeueOutput() {
return false;
case media::MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: {
- if (!output_picture_buffers_.empty()) {
- // TODO(chcunningham): This will likely dismiss a handful of decoded
- // frames that have not yet been drawn and returned to us for re-use.
- // Consider a more complicated design that would wait for them to be
- // drawn before dismissing.
- DismissPictureBuffers();
+ if (media_codec_->GetOutputSize(&size_) != media::MEDIA_CODEC_OK) {
+ POST_ERROR(PLATFORM_FAILURE, "GetOutputSize failed.");
+ return false;
+ }
+ DVLOG(3) << __FUNCTION__
+ << " OUTPUT_FORMAT_CHANGED, new size: " << size_.ToString();
+
+ // Don't request picture buffers if we already have some. This avoids
+ // having to dismiss the existing buffers which may actively reference
+ // decoded images. Breaking their connection to the decoded image will
+ // cause rendering of black frames. Instead, we let the existing
+ // PictureBuffers live on and we simply update their size the next time
+ // they're attachted to an image of the new resolution. See the
+ // size update in |SendDecodedFrameToClient| and https://crbug/587994.
+ if (output_picture_buffers_.empty() && !picturebuffers_requested_) {
+ picturebuffers_requested_ = true;
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(&AndroidVideoDecodeAccelerator::RequestPictureBuffers,
+ weak_this_factory_.GetWeakPtr()));
+ return false;
}
- picturebuffers_requested_ = true;
- int32_t width, height;
- media_codec_->GetOutputFormat(&width, &height);
- size_ = gfx::Size(width, height);
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&AndroidVideoDecodeAccelerator::RequestPictureBuffers,
- weak_this_factory_.GetWeakPtr()));
- return false;
+ return true;
}
case media::MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED:
@@ -469,6 +706,9 @@ bool AndroidVideoDecodeAccelerator::DequeueOutput() {
case media::MEDIA_CODEC_OK:
DCHECK_GE(buf_index, 0);
+ DVLOG(3) << __FUNCTION__ << ": pts:" << presentation_timestamp
+ << " buf_index:" << buf_index << " offset:" << offset
+ << " size:" << size << " eos:" << eos;
break;
default:
@@ -478,12 +718,36 @@ bool AndroidVideoDecodeAccelerator::DequeueOutput() {
} while (buf_index < 0);
if (eos) {
- DVLOG(3) << "AVDA::DequeueOutput: Resetting codec state after EOS";
+ DVLOG(3) << __FUNCTION__ << ": Resetting codec state after EOS";
+
+ // If we were waiting for an EOS, clear the state and reset the MediaCodec
+ // as normal. Otherwise, enter the ERROR state which will force destruction
+ // of MediaCodec during ResetCodecState().
+ //
+ // Some Android platforms seem to send an EOS buffer even when we're not
+ // expecting it. In this case, destroy and reset the codec but don't notify
+ // flush done since it violates the state machine. http://crbug.com/585959.
+ const bool was_waiting_for_eos = state_ == WAITING_FOR_EOS;
+ state_ = was_waiting_for_eos ? NO_ERROR : ERROR;
+
ResetCodecState();
+ // |media_codec_| might still be null.
+ if (was_waiting_for_eos) {
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyFlushDone,
+ weak_this_factory_.GetWeakPtr()));
+ }
+ return false;
+ }
- base::MessageLoop::current()->PostTask(
- FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyFlushDone,
- weak_this_factory_.GetWeakPtr()));
+ if (!picturebuffers_requested_) {
+ // If, somehow, we get a decoded frame back before a FORMAT_CHANGED
+ // message, then we might not have any picture buffers to use. This
+ // isn't supposed to happen (see EncodeDecodeTest.java#617).
+ // Log a metric to see how common this is.
+ RecordFormatChangedMetric(FormatChangedValue::MissingFormatChanged);
+ media_codec_->ReleaseOutputBuffer(buf_index, false);
+ POST_ERROR(PLATFORM_FAILURE, "Dequeued buffers before FORMAT_CHANGED.");
return false;
}
@@ -515,7 +779,7 @@ bool AndroidVideoDecodeAccelerator::DequeueOutput() {
// correction and provides a non-decreasing timestamp sequence, which might
// result in timestamp duplicates. Discard the frame if we cannot get the
// corresponding buffer id.
- DVLOG(3) << "AVDA::DequeueOutput: Releasing buffer with unexpected PTS: "
+ DVLOG(3) << __FUNCTION__ << ": Releasing buffer with unexpected PTS: "
<< presentation_timestamp;
media_codec_->ReleaseOutputBuffer(buf_index, false);
}
@@ -532,7 +796,7 @@ void AndroidVideoDecodeAccelerator::SendDecodedFrameToClient(
DCHECK(!free_picture_ids_.empty());
TRACE_EVENT0("media", "AVDA::SendDecodedFrameToClient");
- if (!make_context_current_.Run()) {
+ if (!make_context_current_cb_.Run()) {
POST_ERROR(PLATFORM_FAILURE, "Failed to make the GL context current.");
return;
}
@@ -541,46 +805,71 @@ void AndroidVideoDecodeAccelerator::SendDecodedFrameToClient(
free_picture_ids_.pop();
TRACE_COUNTER1("media", "AVDA::FreePictureIds", free_picture_ids_.size());
- OutputBufferMap::const_iterator i =
- output_picture_buffers_.find(picture_buffer_id);
+ const auto& i = output_picture_buffers_.find(picture_buffer_id);
if (i == output_picture_buffers_.end()) {
POST_ERROR(PLATFORM_FAILURE,
"Can't find PictureBuffer id: " << picture_buffer_id);
return;
}
+ bool size_changed = false;
+ if (i->second.size() != size_) {
+ // Size may have changed due to resolution change since the last time this
+ // PictureBuffer was used.
+ strategy_->UpdatePictureBufferSize(&i->second, size_);
+ size_changed = true;
+ }
+
// Connect the PictureBuffer to the decoded frame, via whatever
// mechanism the strategy likes.
strategy_->UseCodecBufferForPictureBuffer(codec_buffer_index, i->second);
+ const bool allow_overlay = strategy_->ArePicturesOverlayable();
+
+ media::Picture picture(picture_buffer_id, bitstream_id, gfx::Rect(size_),
+ allow_overlay);
+ picture.set_size_changed(size_changed);
+
base::MessageLoop::current()->PostTask(
FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyPictureReady,
- weak_this_factory_.GetWeakPtr(),
- media::Picture(picture_buffer_id, bitstream_id,
- gfx::Rect(size_), false)));
+ weak_this_factory_.GetWeakPtr(), picture));
}
void AndroidVideoDecodeAccelerator::Decode(
const media::BitstreamBuffer& bitstream_buffer) {
DCHECK(thread_checker_.CalledOnValidThread());
- if (bitstream_buffer.id() != -1 && bitstream_buffer.size() == 0) {
+
+ if (bitstream_buffer.id() >= 0 && bitstream_buffer.size() > 0) {
+ DecodeBuffer(bitstream_buffer);
+ return;
+ }
+
+ if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle()))
+ base::SharedMemory::CloseHandle(bitstream_buffer.handle());
+
+ if (bitstream_buffer.id() < 0) {
+ POST_ERROR(INVALID_ARGUMENT,
+ "Invalid bistream_buffer, id: " << bitstream_buffer.id());
+ } else {
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&AndroidVideoDecodeAccelerator::NotifyEndOfBitstreamBuffer,
weak_this_factory_.GetWeakPtr(), bitstream_buffer.id()));
- return;
}
+}
- pending_bitstream_buffers_.push(
- std::make_pair(bitstream_buffer, base::Time::Now()));
+void AndroidVideoDecodeAccelerator::DecodeBuffer(
+ const media::BitstreamBuffer& bitstream_buffer) {
+ pending_bitstream_buffers_.push(bitstream_buffer);
TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount",
pending_bitstream_buffers_.size());
- DoIOTask();
+ DoIOTask(true);
}
void AndroidVideoDecodeAccelerator::RequestPictureBuffers() {
- client_->ProvidePictureBuffers(kNumPictureBuffers, size_,
+ client_->ProvidePictureBuffers(kNumPictureBuffers, 1,
+ strategy_->GetPictureBufferSize(),
strategy_->GetTextureTarget());
}
@@ -595,8 +884,12 @@ void AndroidVideoDecodeAccelerator::AssignPictureBuffers(
return;
}
+ const bool have_context = make_context_current_cb_.Run();
+ LOG_IF(WARNING, !have_context)
+ << "Failed to make GL context current for Assign, continuing.";
+
for (size_t i = 0; i < buffers.size(); ++i) {
- if (buffers[i].size() != size_) {
+ if (buffers[i].size() != strategy_->GetPictureBufferSize()) {
POST_ERROR(INVALID_ARGUMENT,
"Invalid picture buffer size assigned. Wanted "
<< size_.ToString() << ", but got "
@@ -606,29 +899,17 @@ void AndroidVideoDecodeAccelerator::AssignPictureBuffers(
int32_t id = buffers[i].id();
output_picture_buffers_.insert(std::make_pair(id, buffers[i]));
free_picture_ids_.push(id);
- // Since the client might be re-using |picture_buffer_id| values, forget
- // about previously-dismissed IDs now. See ReusePictureBuffer() comment
- // about "zombies" for why we maintain this set in the first place.
- dismissed_picture_ids_.erase(id);
- strategy_->AssignOnePictureBuffer(buffers[i]);
+ strategy_->AssignOnePictureBuffer(buffers[i], have_context);
}
TRACE_COUNTER1("media", "AVDA::FreePictureIds", free_picture_ids_.size());
-
- DoIOTask();
+ DoIOTask(true);
}
void AndroidVideoDecodeAccelerator::ReusePictureBuffer(
int32_t picture_buffer_id) {
DCHECK(thread_checker_.CalledOnValidThread());
- // This ReusePictureBuffer() might have been in a pipe somewhere (queued in
- // IPC, or in a PostTask either at the sender or receiver) when we sent a
- // DismissPictureBuffer() for this |picture_buffer_id|. Account for such
- // potential "zombie" IDs here.
- if (dismissed_picture_ids_.erase(picture_buffer_id))
- return;
-
free_picture_ids_.push(picture_buffer_id);
TRACE_COUNTER1("media", "AVDA::FreePictureIds", free_picture_ids_.size());
@@ -641,58 +922,139 @@ void AndroidVideoDecodeAccelerator::ReusePictureBuffer(
}
strategy_->ReuseOnePictureBuffer(i->second);
-
- DoIOTask();
+ DoIOTask(true);
}
void AndroidVideoDecodeAccelerator::Flush() {
DCHECK(thread_checker_.CalledOnValidThread());
- Decode(media::BitstreamBuffer(-1, base::SharedMemoryHandle(), 0));
+ DecodeBuffer(media::BitstreamBuffer(-1, base::SharedMemoryHandle(), 0));
}
-bool AndroidVideoDecodeAccelerator::ConfigureMediaCodec() {
+void AndroidVideoDecodeAccelerator::ConfigureMediaCodecAsynchronously() {
DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(surface_texture_.get());
- TRACE_EVENT0("media", "AVDA::ConfigureMediaCodec");
- gfx::ScopedJavaSurface surface(surface_texture_.get());
+ // It's probably okay just to return here, since the codec will be configured
+ // asynchronously. It's unclear that any state for the new request could
+ // be different, unless somebody modifies |codec_config_| while we're already
+ // waiting for a codec. One shouldn't do that for thread safety.
+ DCHECK_NE(state_, WAITING_FOR_CODEC);
+
+ state_ = WAITING_FOR_CODEC;
+
+ // Tell the strategy that we're changing codecs. The codec itself could be
+ // used normally, since we don't replace it until we're back on the main
+ // thread. However, if we're using an output surface, then the incoming codec
+ // might access that surface while the main thread is drawing. Telling the
+ // strategy to forget the codec avoids this.
+ if (media_codec_) {
+ media_codec_.reset();
+ strategy_->CodecChanged(nullptr, output_picture_buffers_);
+ }
+
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner =
+ g_avda_timer.Pointer()->ConstructionTaskRunner();
+ CHECK(task_runner);
+
+ base::PostTaskAndReplyWithResult(
+ task_runner.get(), FROM_HERE,
+ base::Bind(&AndroidVideoDecodeAccelerator::ConfigureMediaCodecOnAnyThread,
+ codec_config_),
+ base::Bind(&AndroidVideoDecodeAccelerator::OnCodecConfigured,
+ weak_this_factory_.GetWeakPtr()));
+}
+
+bool AndroidVideoDecodeAccelerator::ConfigureMediaCodecSynchronously() {
+ state_ = WAITING_FOR_CODEC;
+ scoped_ptr<media::VideoCodecBridge> media_codec =
+ ConfigureMediaCodecOnAnyThread(codec_config_);
+ OnCodecConfigured(std::move(media_codec));
+ return !!media_codec_;
+}
+
+scoped_ptr<media::VideoCodecBridge>
+AndroidVideoDecodeAccelerator::ConfigureMediaCodecOnAnyThread(
+ scoped_refptr<CodecConfig> codec_config) {
+ TRACE_EVENT0("media", "AVDA::ConfigureMediaCodec");
- jobject media_crypto = media_crypto_ ? media_crypto_->obj() : nullptr;
+ jobject media_crypto = codec_config->media_crypto_
+ ? codec_config->media_crypto_->obj()
+ : nullptr;
// |needs_protected_surface_| implies encrypted stream.
- DCHECK(!needs_protected_surface_ || media_crypto);
+ DCHECK(!codec_config->needs_protected_surface_ || media_crypto);
+
+ return scoped_ptr<media::VideoCodecBridge>(
+ media::VideoCodecBridge::CreateDecoder(
+ codec_config->codec_, codec_config->needs_protected_surface_,
+ codec_config->initial_expected_coded_size_,
+ codec_config->surface_.j_surface().obj(), media_crypto, true));
+}
+
+void AndroidVideoDecodeAccelerator::OnCodecConfigured(
+ scoped_ptr<media::VideoCodecBridge> media_codec) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK_EQ(state_, WAITING_FOR_CODEC);
+
+ media_codec_ = std::move(media_codec);
+
+ // Record one instance of the codec being initialized.
+ RecordFormatChangedMetric(FormatChangedValue::CodecInitialized);
- // Pass a dummy 320x240 canvas size and let the codec signal the real size
- // when it's known from the bitstream.
- media_codec_.reset(media::VideoCodecBridge::CreateDecoder(
- codec_, needs_protected_surface_, gfx::Size(320, 240),
- surface.j_surface().obj(), media_crypto));
strategy_->CodecChanged(media_codec_.get(), output_picture_buffers_);
+
+ // If we are supposed to notify that initialization is complete, then do so
+ // now. Otherwise, this is a reconfiguration.
+ if (deferred_initialization_pending_) {
+ NotifyInitializationComplete(!!media_codec_);
+ deferred_initialization_pending_ = false;
+ }
+
if (!media_codec_) {
- LOG(ERROR) << "Failed to create MediaCodec instance.";
- return false;
+ POST_ERROR(PLATFORM_FAILURE, "Failed to create MediaCodec.");
+ return;
}
+ state_ = NO_ERROR;
+
ManageTimer(true);
- return true;
}
void AndroidVideoDecodeAccelerator::ResetCodecState() {
DCHECK(thread_checker_.CalledOnValidThread());
+
+ // If there is already a reset in flight, then that counts. This can really
+ // only happen if somebody calls Reset.
+ if (state_ == WAITING_FOR_CODEC)
+ return;
+
bitstream_buffers_in_decoder_.clear();
- // We don't dismiss picture buffers here since we might not get a format
- // changed message to re-request them, such as during a seek. In that case,
- // we want to reuse the existing buffers. However, we're about to invalidate
- // all the output buffers, so we must be sure that the strategy no longer
- // refers to them.
+ if (pending_input_buf_index_ != -1) {
+ // The data for that index exists in the input buffer, but corresponding
+ // shm block been deleted. Check that it is safe to flush the coec, i.e.
+ // |pending_bitstream_buffers_| is empty.
+ // TODO(timav): keep shm block for that buffer and remove this restriction.
+ DCHECK(pending_bitstream_buffers_.empty());
+ pending_input_buf_index_ = -1;
+ }
+
+ if (state_ == WAITING_FOR_KEY)
+ state_ = NO_ERROR;
+
+ // We might increment error_sequence_token here to cancel any delayed errors,
+ // but right now it's unclear that it's safe to do so. If we are in an error
+ // state because of a codec error, then it would be okay. Otherwise, it's
+ // less obvious that we are exiting the error state. Since deferred errors
+ // are only intended for fullscreen transitions right now, we take the more
+ // conservative approach and let the errors post.
+ // TODO(liberato): revisit this once we sort out the error state a bit more.
// When codec is not in error state we can quickly reset (internally calls
// flush()) for JB-MR2 and beyond. Prior to JB-MR2, flush() had several bugs
- // (b/8125974, b/8347958) so we must stop() and reconfigure MediaCodec. The
- // full reconfigure is much slower and may cause visible freezing if done
- // mid-stream.
+ // (b/8125974, b/8347958) so we must delete the MediaCodec and create a new
+ // one. The full reconfigure is much slower and may cause visible freezing if
+ // done mid-stream.
if (state_ == NO_ERROR &&
base::android::BuildInfo::GetInstance()->sdk_int() >= 18) {
DVLOG(3) << __FUNCTION__ << " Doing fast MediaCodec reset (flush).";
@@ -702,37 +1064,21 @@ void AndroidVideoDecodeAccelerator::ResetCodecState() {
strategy_->CodecChanged(media_codec_.get(), output_picture_buffers_);
} else {
DVLOG(3) << __FUNCTION__
- << " Doing slow MediaCodec reset (stop/re-configure).";
- io_timer_.Stop();
- media_codec_->Stop();
+ << " Deleting the MediaCodec and creating a new one.";
+ g_avda_timer.Pointer()->StopTimer(this);
// Changing the codec will also notify the strategy to forget about any
// output buffers it has currently.
- ConfigureMediaCodec();
state_ = NO_ERROR;
+ ConfigureMediaCodecAsynchronously();
}
}
-void AndroidVideoDecodeAccelerator::DismissPictureBuffers() {
- DCHECK(thread_checker_.CalledOnValidThread());
- DVLOG(3) << __FUNCTION__;
-
- for (const auto& pb : output_picture_buffers_) {
- strategy_->DismissOnePictureBuffer(pb.second);
- client_->DismissPictureBuffer(pb.first);
- dismissed_picture_ids_.insert(pb.first);
- }
- output_picture_buffers_.clear();
- std::queue<int32_t> empty;
- std::swap(free_picture_ids_, empty);
- picturebuffers_requested_ = false;
-}
-
void AndroidVideoDecodeAccelerator::Reset() {
DCHECK(thread_checker_.CalledOnValidThread());
TRACE_EVENT0("media", "AVDA::Reset");
while (!pending_bitstream_buffers_.empty()) {
- int32_t bitstream_buffer_id = pending_bitstream_buffers_.front().first.id();
+ int32_t bitstream_buffer_id = pending_bitstream_buffers_.front().id();
pending_bitstream_buffers_.pop();
if (bitstream_buffer_id != -1) {
@@ -745,8 +1091,13 @@ void AndroidVideoDecodeAccelerator::Reset() {
TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", 0);
bitstreams_notified_in_advance_.clear();
+ // Any error that is waiting to post can be ignored.
+ error_sequence_token_++;
+
ResetCodecState();
+ // Note that |media_codec_| might not yet be ready, but we can still post
+ // this anyway.
base::MessageLoop::current()->PostTask(
FROM_HERE, base::Bind(&AndroidVideoDecodeAccelerator::NotifyResetDone,
weak_this_factory_.GetWeakPtr()));
@@ -755,11 +1106,12 @@ void AndroidVideoDecodeAccelerator::Reset() {
void AndroidVideoDecodeAccelerator::Destroy() {
DCHECK(thread_checker_.CalledOnValidThread());
- bool have_context = make_context_current_.Run();
+ bool have_context = make_context_current_cb_.Run();
if (!have_context)
LOG(WARNING) << "Failed make GL context current for Destroy, continuing.";
- strategy_->Cleanup(have_context, output_picture_buffers_);
+ if (strategy_)
+ strategy_->Cleanup(have_context, output_picture_buffers_);
// If we have an OnFrameAvailable handler, tell it that we're going away.
if (on_frame_available_handler_) {
@@ -767,15 +1119,20 @@ void AndroidVideoDecodeAccelerator::Destroy() {
on_frame_available_handler_ = nullptr;
}
+ // Note that async codec construction might still be in progress. In that
+ // case, the codec will be deleted when it completes once we invalidate all
+ // our weak refs.
weak_this_factory_.InvalidateWeakPtrs();
if (media_codec_) {
- io_timer_.Stop();
- media_codec_->Stop();
+ g_avda_timer.Pointer()->StopTimer(this);
+ media_codec_.reset();
}
delete this;
}
-bool AndroidVideoDecodeAccelerator::CanDecodeOnIOThread() {
+bool AndroidVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread(
+ const base::WeakPtr<Client>& decode_client,
+ const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) {
return false;
}
@@ -790,7 +1147,29 @@ const base::ThreadChecker& AndroidVideoDecodeAccelerator::ThreadChecker()
base::WeakPtr<gpu::gles2::GLES2Decoder>
AndroidVideoDecodeAccelerator::GetGlDecoder() const {
- return gl_decoder_;
+ return get_gles2_decoder_cb_.Run();
+}
+
+gpu::gles2::TextureRef* AndroidVideoDecodeAccelerator::GetTextureForPicture(
+ const media::PictureBuffer& picture_buffer) {
+ auto gles_decoder = GetGlDecoder();
+ RETURN_ON_FAILURE(this, gles_decoder, "Failed to get GL decoder",
+ ILLEGAL_STATE, nullptr);
+ RETURN_ON_FAILURE(this, gles_decoder->GetContextGroup(),
+ "Null gles_decoder->GetContextGroup()", ILLEGAL_STATE,
+ nullptr);
+ gpu::gles2::TextureManager* texture_manager =
+ gles_decoder->GetContextGroup()->texture_manager();
+ RETURN_ON_FAILURE(this, texture_manager, "Null texture_manager",
+ ILLEGAL_STATE, nullptr);
+
+ DCHECK_LE(1u, picture_buffer.internal_texture_ids().size());
+ gpu::gles2::TextureRef* texture_ref =
+ texture_manager->GetTexture(picture_buffer.internal_texture_ids()[0]);
+ RETURN_ON_FAILURE(this, texture_manager, "Null texture_ref", ILLEGAL_STATE,
+ nullptr);
+
+ return texture_ref;
}
void AndroidVideoDecodeAccelerator::OnFrameAvailable() {
@@ -802,20 +1181,24 @@ void AndroidVideoDecodeAccelerator::OnFrameAvailable() {
void AndroidVideoDecodeAccelerator::PostError(
const ::tracked_objects::Location& from_here,
media::VideoDecodeAccelerator::Error error) {
- base::MessageLoop::current()->PostTask(
- from_here, base::Bind(&AndroidVideoDecodeAccelerator::NotifyError,
- weak_this_factory_.GetWeakPtr(), error));
+ base::MessageLoop::current()->PostDelayedTask(
+ from_here,
+ base::Bind(&AndroidVideoDecodeAccelerator::NotifyError,
+ weak_this_factory_.GetWeakPtr(), error, error_sequence_token_),
+ (defer_errors_ ? ErrorPostingDelay() : base::TimeDelta()));
state_ = ERROR;
}
void AndroidVideoDecodeAccelerator::OnMediaCryptoReady(
- media::MediaDrmBridge::JavaObjectPtr media_crypto,
+ media::MediaDrmBridgeCdmContext::JavaObjectPtr media_crypto,
bool needs_protected_surface) {
DVLOG(1) << __FUNCTION__;
if (!media_crypto) {
LOG(ERROR) << "MediaCrypto is not available, can't play encrypted stream.";
- NotifyCdmAttached(false);
+ cdm_for_reference_holding_only_ = nullptr;
+ media_drm_bridge_cdm_context_ = nullptr;
+ NotifyInitializationComplete(false);
return;
}
@@ -825,23 +1208,24 @@ void AndroidVideoDecodeAccelerator::OnMediaCryptoReady(
// is not created yet.
DCHECK(!media_codec_);
- media_crypto_ = std::move(media_crypto);
- needs_protected_surface_ = needs_protected_surface;
+ codec_config_->media_crypto_ = std::move(media_crypto);
+ codec_config_->needs_protected_surface_ = needs_protected_surface;
// After receiving |media_crypto_| we can configure MediaCodec.
- const bool success = ConfigureMediaCodec();
- NotifyCdmAttached(success);
+ ConfigureMediaCodecAsynchronously();
}
void AndroidVideoDecodeAccelerator::OnKeyAdded() {
DVLOG(1) << __FUNCTION__;
- // TODO(timav): Figure out whether stopping the pipeline in response to
- // NO_KEY error and restarting it here has significant benefits (e.g. saving
- // power). Right now do nothing here.
+
+ if (state_ == WAITING_FOR_KEY)
+ state_ = NO_ERROR;
+
+ DoIOTask(true);
}
-void AndroidVideoDecodeAccelerator::NotifyCdmAttached(bool success) {
- client_->NotifyCdmAttached(success);
+void AndroidVideoDecodeAccelerator::NotifyInitializationComplete(bool success) {
+ client_->NotifyInitializationComplete(success);
}
void AndroidVideoDecodeAccelerator::NotifyPictureReady(
@@ -863,7 +1247,13 @@ void AndroidVideoDecodeAccelerator::NotifyResetDone() {
}
void AndroidVideoDecodeAccelerator::NotifyError(
- media::VideoDecodeAccelerator::Error error) {
+ media::VideoDecodeAccelerator::Error error,
+ int token) {
+ DVLOG(1) << __FUNCTION__ << ": error: " << error << " token: " << token
+ << " current: " << error_sequence_token_;
+ if (token != error_sequence_token_)
+ return;
+
client_->NotifyError(error);
}
@@ -871,45 +1261,72 @@ void AndroidVideoDecodeAccelerator::ManageTimer(bool did_work) {
bool should_be_running = true;
base::TimeTicks now = base::TimeTicks::Now();
- if (!did_work) {
+ if (!did_work && !most_recent_work_.is_null()) {
// Make sure that we have done work recently enough, else stop the timer.
- if (now - most_recent_work_ > IdleTimerTimeOut())
+ if (now - most_recent_work_ > IdleTimerTimeOut()) {
+ most_recent_work_ = base::TimeTicks();
should_be_running = false;
+ }
} else {
most_recent_work_ = now;
}
- if (should_be_running && !io_timer_.IsRunning()) {
- io_timer_.Start(FROM_HERE, DecodePollDelay(), this,
- &AndroidVideoDecodeAccelerator::DoIOTask);
- } else if (!should_be_running && io_timer_.IsRunning()) {
- io_timer_.Stop();
- }
+ if (should_be_running)
+ g_avda_timer.Pointer()->StartTimer(this);
+ else
+ g_avda_timer.Pointer()->StopTimer(this);
}
// static
-bool AndroidVideoDecodeAccelerator::UseDeferredRenderingStrategy() {
- return base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableUnifiedMediaPipeline);
+bool AndroidVideoDecodeAccelerator::UseDeferredRenderingStrategy(
+ const gpu::GpuPreferences& gpu_preferences) {
+ // TODO(liberato, watk): Figure out what we want to do about zero copy for
+ // fullscreen external SurfaceView in WebView. http://crbug.com/582170.
+ return !gpu_preferences.enable_threaded_texture_mailboxes;
}
// static
media::VideoDecodeAccelerator::Capabilities
-AndroidVideoDecodeAccelerator::GetCapabilities() {
+AndroidVideoDecodeAccelerator::GetCapabilities(
+ const gpu::GpuPreferences& gpu_preferences) {
Capabilities capabilities;
SupportedProfiles& profiles = capabilities.supported_profiles;
- SupportedProfile profile;
-
- profile.profile = media::VP8PROFILE_ANY;
- profile.min_resolution.SetSize(0, 0);
- profile.max_resolution.SetSize(1920, 1088);
- profiles.push_back(profile);
+ if (media::MediaCodecUtil::IsVp8DecoderAvailable()) {
+ SupportedProfile profile;
+ profile.profile = media::VP8PROFILE_ANY;
+ profile.min_resolution.SetSize(0, 0);
+ profile.max_resolution.SetSize(1920, 1088);
+ // If we know MediaCodec will just create a software codec, prefer our
+ // internal software decoder instead. It's more up to date and secured
+ // within the renderer sandbox. However if the content is encrypted, we
+ // must use MediaCodec anyways since MediaDrm offers no way to decrypt
+ // the buffers and let us use our internal software decoders.
+ profile.encrypted_only = media::VideoCodecBridge::IsKnownUnaccelerated(
+ media::kCodecVP8, media::MEDIA_CODEC_DECODER);
+ profiles.push_back(profile);
+ }
- profile.profile = media::VP9PROFILE_ANY;
- profile.min_resolution.SetSize(0, 0);
- profile.max_resolution.SetSize(1920, 1088);
- profiles.push_back(profile);
+ if (media::MediaCodecUtil::IsVp9DecoderAvailable()) {
+ SupportedProfile profile;
+ profile.min_resolution.SetSize(0, 0);
+ profile.max_resolution.SetSize(1920, 1088);
+ // If we know MediaCodec will just create a software codec, prefer our
+ // internal software decoder instead. It's more up to date and secured
+ // within the renderer sandbox. However if the content is encrypted, we
+ // must use MediaCodec anyways since MediaDrm offers no way to decrypt
+ // the buffers and let us use our internal software decoders.
+ profile.encrypted_only = media::VideoCodecBridge::IsKnownUnaccelerated(
+ media::kCodecVP9, media::MEDIA_CODEC_DECODER);
+ profile.profile = media::VP9PROFILE_PROFILE0;
+ profiles.push_back(profile);
+ profile.profile = media::VP9PROFILE_PROFILE1;
+ profiles.push_back(profile);
+ profile.profile = media::VP9PROFILE_PROFILE2;
+ profiles.push_back(profile);
+ profile.profile = media::VP9PROFILE_PROFILE3;
+ profiles.push_back(profile);
+ }
for (const auto& supported_profile : kSupportedH264Profiles) {
SupportedProfile profile;
@@ -922,9 +1339,15 @@ AndroidVideoDecodeAccelerator::GetCapabilities() {
profiles.push_back(profile);
}
- if (UseDeferredRenderingStrategy()) {
- capabilities.flags = media::VideoDecodeAccelerator::Capabilities::
+ capabilities.flags = media::VideoDecodeAccelerator::Capabilities::
+ SUPPORTS_DEFERRED_INITIALIZATION;
+ if (UseDeferredRenderingStrategy(gpu_preferences)) {
+ capabilities.flags |= media::VideoDecodeAccelerator::Capabilities::
NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE;
+ if (media::MediaCodecUtil::IsSurfaceViewOutputSupported()) {
+ capabilities.flags |= media::VideoDecodeAccelerator::Capabilities::
+ SUPPORTS_EXTERNAL_OUTPUT_SURFACE;
+ }
}
return capabilities;
diff --git a/chromium/content/common/gpu/media/android_video_decode_accelerator.h b/chromium/content/common/gpu/media/android_video_decode_accelerator.h
index 1dd6816a72d..1e0543d3fc5 100644
--- a/chromium/content/common/gpu/media/android_video_decode_accelerator.h
+++ b/chromium/content/common/gpu/media/android_video_decode_accelerator.h
@@ -18,11 +18,14 @@
#include "base/timer/timer.h"
#include "content/common/content_export.h"
#include "content/common/gpu/media/avda_state_provider.h"
+#include "content/common/gpu/media/gpu_video_decode_accelerator_helpers.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
-#include "media/base/android/media_drm_bridge.h"
+#include "gpu/command_buffer/service/gpu_preferences.h"
+#include "media/base/android/media_drm_bridge_cdm_context.h"
#include "media/base/android/sdk_media_codec_bridge.h"
#include "media/base/media_keys.h"
#include "media/video/video_decode_accelerator.h"
+#include "ui/gl/android/scoped_java_surface.h"
namespace gfx {
class SurfaceTexture;
@@ -39,7 +42,7 @@ class CONTENT_EXPORT AndroidVideoDecodeAccelerator
: public media::VideoDecodeAccelerator,
public AVDAStateProvider {
public:
- typedef std::map<int32_t, media::PictureBuffer> OutputBufferMap;
+ using OutputBufferMap = std::map<int32_t, media::PictureBuffer>;
// A BackingStrategy is responsible for making a PictureBuffer's texture
// contain the image that a MediaCodec decoder buffer tells it to.
@@ -47,20 +50,26 @@ class CONTENT_EXPORT AndroidVideoDecodeAccelerator
public:
virtual ~BackingStrategy() {}
- // Called after the state provider is given, but before any other
- // calls to the BackingStrategy.
- virtual void Initialize(AVDAStateProvider* provider) = 0;
+ // Must be called before anything else. If surface_view_id is not equal to
+ // |kNoSurfaceID| it refers to a SurfaceView that the strategy must render
+ // to.
+ // Returns the Java surface to configure MediaCodec with.
+ virtual gfx::ScopedJavaSurface Initialize(int surface_view_id) = 0;
// Called before the AVDA does any Destroy() work. This will be
// the last call that the BackingStrategy receives.
virtual void Cleanup(bool have_context,
const OutputBufferMap& buffer_map) = 0;
+ // This returns the SurfaceTexture created by Initialize, or nullptr if
+ // the strategy was initialized with a SurfaceView.
+ virtual scoped_refptr<gfx::SurfaceTexture> GetSurfaceTexture() const = 0;
+
// Return the GL texture target that the PictureBuffer textures use.
virtual uint32_t GetTextureTarget() const = 0;
- // Create and return a surface texture for the MediaCodec to use.
- virtual scoped_refptr<gfx::SurfaceTexture> CreateSurfaceTexture() = 0;
+ // Return the size to use when requesting picture buffers.
+ virtual gfx::Size GetPictureBufferSize() const = 0;
// Make the provided PictureBuffer draw the image that is represented by
// the decoded output buffer at codec_buffer_index.
@@ -70,16 +79,13 @@ class CONTENT_EXPORT AndroidVideoDecodeAccelerator
// Notify strategy that a picture buffer has been assigned.
virtual void AssignOnePictureBuffer(
- const media::PictureBuffer& picture_buffer) {}
+ const media::PictureBuffer& picture_buffer,
+ bool have_context) {}
// Notify strategy that a picture buffer has been reused.
virtual void ReuseOnePictureBuffer(
const media::PictureBuffer& picture_buffer) {}
- // Notify strategy that we are about to dismiss a picture buffer.
- virtual void DismissOnePictureBuffer(
- const media::PictureBuffer& picture_buffer) {}
-
// Notify strategy that we have a new android MediaCodec instance. This
// happens when we're starting up or re-configuring mid-stream. Any
// previously provided codec should no longer be referenced.
@@ -91,11 +97,22 @@ class CONTENT_EXPORT AndroidVideoDecodeAccelerator
// Notify the strategy that a frame is available. This callback can happen
// on any thread at any time.
virtual void OnFrameAvailable() = 0;
+
+ // Whether the pictures produced by this backing strategy are overlayable.
+ virtual bool ArePicturesOverlayable() = 0;
+
+ // Size may have changed due to resolution change since the last time this
+ // PictureBuffer was used. Update the size of the picture buffer to
+ // |new_size| and also update any size-dependent state (e.g. size of
+ // associated texture). Callers should set the correct GL context prior to
+ // calling.
+ virtual void UpdatePictureBufferSize(media::PictureBuffer* picture_buffer,
+ const gfx::Size& new_size) = 0;
};
AndroidVideoDecodeAccelerator(
- const base::WeakPtr<gpu::gles2::GLES2Decoder> decoder,
- const base::Callback<bool(void)>& make_context_current);
+ const MakeGLContextCurrentCallback& make_context_current_cb,
+ const GetGLES2DecoderCallback& get_gles2_decoder_cb);
~AndroidVideoDecodeAccelerator() override;
@@ -109,31 +126,98 @@ class CONTENT_EXPORT AndroidVideoDecodeAccelerator
void Flush() override;
void Reset() override;
void Destroy() override;
- bool CanDecodeOnIOThread() override;
+ bool TryToSetupDecodeOnSeparateThread(
+ const base::WeakPtr<Client>& decode_client,
+ const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner)
+ override;
// AVDAStateProvider implementation:
const gfx::Size& GetSize() const override;
const base::ThreadChecker& ThreadChecker() const override;
base::WeakPtr<gpu::gles2::GLES2Decoder> GetGlDecoder() const override;
+ gpu::gles2::TextureRef* GetTextureForPicture(
+ const media::PictureBuffer& picture_buffer) override;
void PostError(const ::tracked_objects::Location& from_here,
media::VideoDecodeAccelerator::Error error) override;
- static media::VideoDecodeAccelerator::Capabilities GetCapabilities();
+ static media::VideoDecodeAccelerator::Capabilities GetCapabilities(
+ const gpu::GpuPreferences& gpu_preferences);
// Notifies about SurfaceTexture::OnFrameAvailable. This can happen on any
// thread at any time!
void OnFrameAvailable();
private:
+ friend class AVDATimerManager;
+
+ // TODO(timav): evaluate the need for more states in the AVDA state machine.
enum State {
NO_ERROR,
ERROR,
+ // Set when we are asynchronously constructing the codec. Will transition
+ // to NO_ERROR or ERROR depending on success.
+ WAITING_FOR_CODEC,
+ // Set when we have a codec, but it doesn't yet have a key.
+ WAITING_FOR_KEY,
+ WAITING_FOR_EOS,
};
- static const base::TimeDelta kDecodePollDelay;
+ // Configuration info for MediaCodec.
+ // This is used to shuttle configuration info between threads without needing
+ // to worry about the lifetime of the AVDA instance. All of these should not
+ // be modified while |state_| is WAITING_FOR_CODEC.
+ class CodecConfig : public base::RefCountedThreadSafe<CodecConfig> {
+ public:
+ CodecConfig();
+
+ // Codec type. Used when we configure media codec.
+ media::VideoCodec codec_ = media::kUnknownVideoCodec;
+
+ // Whether encryption scheme requires to use protected surface.
+ bool needs_protected_surface_ = false;
+
+ // The surface that MediaCodec is configured to output to. It's created by
+ // the backing strategy.
+ gfx::ScopedJavaSurface surface_;
+
+ // The MediaCrypto object is used in the MediaCodec.configure() in case of
+ // an encrypted stream.
+ media::MediaDrmBridgeCdmContext::JavaObjectPtr media_crypto_;
+
+ // Initial coded size. The actual size might change at any time, so this
+ // is only a hint.
+ gfx::Size initial_expected_coded_size_;
+
+ protected:
+ friend class base::RefCountedThreadSafe<CodecConfig>;
+ virtual ~CodecConfig();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(CodecConfig);
+ };
// Configures |media_codec_| with the given codec parameters from the client.
- bool ConfigureMediaCodec();
+ // This configuration will (probably) not be complete before this call
+ // returns. Multiple calls before completion will be ignored. |state_|
+ // must be NO_ERROR or WAITING_FOR_CODEC. Note that, once you call this,
+ // you should be careful to avoid modifying members of |codec_config_| until
+ // |state_| is no longer WAITING_FOR_CODEC.
+ void ConfigureMediaCodecAsynchronously();
+
+ // Like ConfigureMediaCodecAsynchronously, but synchronous. Returns true if
+ // and only if |media_codec_| is non-null. Since all configuration is done
+ // synchronously, there is no concern with modifying |codec_config_| after
+ // this returns.
+ bool ConfigureMediaCodecSynchronously();
+
+ // Instantiate a media codec using |codec_config|.
+ // This may be called on any thread.
+ static scoped_ptr<media::VideoCodecBridge> ConfigureMediaCodecOnAnyThread(
+ scoped_refptr<CodecConfig> codec_config);
+
+ // Called on the main thread to update |media_codec_| and complete codec
+ // configuration. |media_codec| will be null if configuration failed.
+ void OnCodecConfigured(scoped_ptr<media::VideoCodecBridge> media_codec);
// Sends the decoded frame specified by |codec_buffer_index| to the client.
void SendDecodedFrameToClient(int32_t codec_buffer_index,
@@ -142,7 +226,7 @@ class CONTENT_EXPORT AndroidVideoDecodeAccelerator
// Does pending IO tasks if any. Once this is called, it polls |media_codec_|
// until it finishes pending tasks. For the polling, |kDecodePollDelay| is
// used.
- void DoIOTask();
+ void DoIOTask(bool start_timer);
// Feeds input data to |media_codec_|. This checks
// |pending_bitstream_buffers_| and queues a buffer to |media_codec_|.
@@ -157,15 +241,20 @@ class CONTENT_EXPORT AndroidVideoDecodeAccelerator
// Requests picture buffers from the client.
void RequestPictureBuffers();
+ // Decode the content in the |bitstream_buffer|. Note that a
+ // |bitstream_buffer| of id as -1 indicates a flush command.
+ void DecodeBuffer(const media::BitstreamBuffer& bitstream_buffer);
+
// This callback is called after CDM obtained a MediaCrypto object.
- void OnMediaCryptoReady(media::MediaDrmBridge::JavaObjectPtr media_crypto,
- bool needs_protected_surface);
+ void OnMediaCryptoReady(
+ media::MediaDrmBridgeCdmContext::JavaObjectPtr media_crypto,
+ bool needs_protected_surface);
// This callback is called when a new key is added to CDM.
void OnKeyAdded();
- // Notifies the client of the CDM setting result.
- void NotifyCdmAttached(bool success);
+ // Notifies the client of the result of deferred initialization.
+ void NotifyInitializationComplete(bool success);
// Notifies the client about the availability of a picture.
void NotifyPictureReady(const media::Picture& picture);
@@ -181,7 +270,12 @@ class CONTENT_EXPORT AndroidVideoDecodeAccelerator
void NotifyResetDone();
// Notifies about decoding errors.
- void NotifyError(media::VideoDecodeAccelerator::Error error);
+ // Note: you probably don't want to call this directly. Use PostError or
+ // RETURN_ON_FAILURE, since we can defer error reporting to keep the pipeline
+ // from breaking. NotifyError will do so immediately, PostError may wait.
+ // |token| has to match |error_sequence_token_|, or else it's assumed to be
+ // from a post that's prior to a previous reset, and ignored.
+ void NotifyError(media::VideoDecodeAccelerator::Error error, int token);
// Start or stop our work-polling timer based on whether we did any work, and
// how long it has been since we've done work. Calling this with true will
@@ -194,12 +288,9 @@ class CONTENT_EXPORT AndroidVideoDecodeAccelerator
// is still valid and should be processed.
void ResetCodecState();
- // Dismiss all |output_picture_buffers_| in preparation for requesting new
- // ones.
- void DismissPictureBuffers();
-
// Return true if and only if we should use deferred rendering.
- static bool UseDeferredRenderingStrategy();
+ static bool UseDeferredRenderingStrategy(
+ const gpu::GpuPreferences& gpu_preferences);
// Used to DCHECK that we are called on the correct thread.
base::ThreadChecker thread_checker_;
@@ -208,17 +299,14 @@ class CONTENT_EXPORT AndroidVideoDecodeAccelerator
Client* client_;
// Callback to set the correct gl context.
- base::Callback<bool(void)> make_context_current_;
+ MakeGLContextCurrentCallback make_context_current_cb_;
- // Codec type. Used when we configure media codec.
- media::VideoCodec codec_;
+ // Callback to get the GLES2Decoder instance.
+ GetGLES2DecoderCallback get_gles2_decoder_cb_;
// Whether the stream is encrypted.
bool is_encrypted_;
- // Whether encryption scheme requires to use protected surface.
- bool needs_protected_surface_;
-
// The current state of this class. For now, this is used only for setting
// error state.
State state_;
@@ -231,17 +319,9 @@ class CONTENT_EXPORT AndroidVideoDecodeAccelerator
// decoded frames to the client.
std::queue<int32_t> free_picture_ids_;
- // Picture buffer ids which have been dismissed and not yet re-assigned. Used
- // to ignore ReusePictureBuffer calls that were in flight when the
- // DismissPictureBuffer call was made.
- std::set<int32_t> dismissed_picture_ids_;
-
// The low-level decoder which Android SDK provides.
scoped_ptr<media::VideoCodecBridge> media_codec_;
- // A container of texture. Used to set a texture to |media_codec_|.
- scoped_refptr<gfx::SurfaceTexture> surface_texture_;
-
// Set to true after requesting picture buffers to the client.
bool picturebuffers_requested_;
@@ -249,11 +329,8 @@ class CONTENT_EXPORT AndroidVideoDecodeAccelerator
gfx::Size size_;
// Encoded bitstream buffers to be passed to media codec, queued until an
- // input buffer is available, along with the time when they were first
- // enqueued.
- typedef std::queue<std::pair<media::BitstreamBuffer, base::Time> >
- PendingBitstreamBuffers;
- PendingBitstreamBuffers pending_bitstream_buffers_;
+ // input buffer is available.
+ std::queue<media::BitstreamBuffer> pending_bitstream_buffers_;
// A map of presentation timestamp to bitstream buffer id for the bitstream
// buffers that have been submitted to the decoder but haven't yet produced an
@@ -265,12 +342,6 @@ class CONTENT_EXPORT AndroidVideoDecodeAccelerator
// NotifyEndOfBitstreamBuffer() before getting output from the bitstream.
std::list<int32_t> bitstreams_notified_in_advance_;
- // Owner of the GL context. Used to restore the context state.
- base::WeakPtr<gpu::gles2::GLES2Decoder> gl_decoder_;
-
- // Repeating timer responsible for draining pending IO to the codec.
- base::RepeatingTimer io_timer_;
-
// Backing strategy that we'll use to connect PictureBuffers to frames.
scoped_ptr<BackingStrategy> strategy_;
@@ -283,16 +354,33 @@ class CONTENT_EXPORT AndroidVideoDecodeAccelerator
// CDM related stuff.
- // Holds a ref-count to the CDM.
- scoped_refptr<media::MediaKeys> cdm_;
+ // Holds a ref-count to the CDM to avoid using the CDM after it's destroyed.
+ scoped_refptr<media::MediaKeys> cdm_for_reference_holding_only_;
+
+ media::MediaDrmBridgeCdmContext* media_drm_bridge_cdm_context_;
// MediaDrmBridge requires registration/unregistration of the player, this
// registration id is used for this.
int cdm_registration_id_;
- // The MediaCrypto object is used in the MediaCodec.configure() in case of
- // an encrypted stream.
- media::MediaDrmBridge::JavaObjectPtr media_crypto_;
+ // Configuration that we use for MediaCodec.
+ // Do not update any of its members while |state_| is WAITING_FOR_CODEC.
+ scoped_refptr<CodecConfig> codec_config_;
+
+ // Index of the dequeued and filled buffer that we keep trying to enqueue.
+ // Such buffer appears in MEDIA_CODEC_NO_KEY processing.
+ int pending_input_buf_index_;
+
+ // Monotonically increasing value that is used to prevent old, delayed errors
+ // from being sent after a reset.
+ int error_sequence_token_;
+
+ // PostError will defer sending an error if and only if this is true.
+ bool defer_errors_;
+
+ // True if and only if VDA initialization is deferred, and we have not yet
+ // called NotifyInitializationComplete.
+ bool deferred_initialization_pending_;
// WeakPtrFactory for posting tasks back to |this|.
base::WeakPtrFactory<AndroidVideoDecodeAccelerator> weak_this_factory_;
diff --git a/chromium/content/common/gpu/media/android_video_decode_accelerator_unittest.cc b/chromium/content/common/gpu/media/android_video_decode_accelerator_unittest.cc
index 3cd79157162..d21ad9e58a8 100644
--- a/chromium/content/common/gpu/media/android_video_decode_accelerator_unittest.cc
+++ b/chromium/content/common/gpu/media/android_video_decode_accelerator_unittest.cc
@@ -27,13 +27,15 @@ bool MockMakeContextCurrent() {
return true;
}
+static base::WeakPtr<gpu::gles2::GLES2Decoder> MockGetGLES2Decoder(
+ const base::WeakPtr<gpu::gles2::GLES2Decoder>& decoder) {
+ return decoder;
+}
+
} // namespace
namespace content {
-// TODO(felipeg): Add more unit tests to test the ordinary behavior of
-// AndroidVideoDecodeAccelerator.
-// http://crbug.com/178647
class MockVideoDecodeAcceleratorClient
: public media::VideoDecodeAccelerator::Client {
public:
@@ -42,6 +44,7 @@ class MockVideoDecodeAcceleratorClient
// VideoDecodeAccelerator::Client implementation.
void ProvidePictureBuffers(uint32_t requested_num_of_buffers,
+ uint32_t textures_per_buffer,
const gfx::Size& dimensions,
uint32_t texture_target) override {}
void DismissPictureBuffer(int32_t picture_buffer_id) override {}
@@ -60,8 +63,6 @@ class AndroidVideoDecodeAcceleratorTest : public testing::Test {
void SetUp() override {
JNIEnv* env = base::android::AttachCurrentThread();
media::RegisterJni(env);
- // TODO(felipeg): fix GL bindings, so that the decoder can perform GL
- // calls.
// Start message loop because
// AndroidVideoDecodeAccelerator::ConfigureMediaCodec() starts a timer task.
@@ -72,15 +73,19 @@ class AndroidVideoDecodeAcceleratorTest : public testing::Test {
scoped_ptr<MockVideoDecodeAcceleratorClient> client(
new MockVideoDecodeAcceleratorClient());
accelerator_.reset(new AndroidVideoDecodeAccelerator(
- decoder->AsWeakPtr(), base::Bind(&MockMakeContextCurrent)));
+ base::Bind(&MockMakeContextCurrent),
+ base::Bind(&MockGetGLES2Decoder, decoder->AsWeakPtr())));
}
bool Configure(media::VideoCodec codec) {
AndroidVideoDecodeAccelerator* accelerator =
static_cast<AndroidVideoDecodeAccelerator*>(accelerator_.get());
- accelerator->surface_texture_ = gfx::SurfaceTexture::Create(0);
- accelerator->codec_ = codec;
- return accelerator->ConfigureMediaCodec();
+ scoped_refptr<gfx::SurfaceTexture> surface_texture =
+ gfx::SurfaceTexture::Create(0);
+ accelerator->codec_config_->surface_ =
+ gfx::ScopedJavaSurface(surface_texture.get());
+ accelerator->codec_config_->codec_ = codec;
+ return accelerator->ConfigureMediaCodecSynchronously();
}
private:
diff --git a/chromium/content/common/gpu/media/android_video_encode_accelerator.cc b/chromium/content/common/gpu/media/android_video_encode_accelerator.cc
index eb383081d7f..ac2ff39e9b7 100644
--- a/chromium/content/common/gpu/media/android_video_encode_accelerator.cc
+++ b/chromium/content/common/gpu/media/android_video_encode_accelerator.cc
@@ -7,13 +7,12 @@
#include <set>
#include "base/bind.h"
-#include "base/command_line.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
-#include "content/common/gpu/gpu_channel.h"
-#include "content/public/common/content_switches.h"
+#include "content/common/gpu/media/shared_memory_region.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
+#include "gpu/ipc/service/gpu_channel.h"
#include "media/base/android/media_codec_util.h"
#include "media/base/bitstream_buffer.h"
#include "media/base/limits.h"
@@ -95,8 +94,6 @@ static bool GetSupportedColorFormatForMime(const std::string& mime,
AndroidVideoEncodeAccelerator::AndroidVideoEncodeAccelerator()
: num_buffers_at_codec_(0),
- num_output_buffers_(-1),
- output_buffers_capacity_(0),
last_set_bitrate_(0) {}
AndroidVideoEncodeAccelerator::~AndroidVideoEncodeAccelerator() {
@@ -107,12 +104,6 @@ media::VideoEncodeAccelerator::SupportedProfiles
AndroidVideoEncodeAccelerator::GetSupportedProfiles() {
SupportedProfiles profiles;
-#if defined(ENABLE_WEBRTC)
- const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
- if (cmd_line->HasSwitch(switches::kDisableWebRtcHWEncoding))
- return profiles;
-#endif
-
const struct {
const media::VideoCodec codec;
const media::VideoCodecProfile profile;
@@ -123,6 +114,11 @@ AndroidVideoEncodeAccelerator::GetSupportedProfiles() {
};
for (const auto& supported_codec : kSupportedCodecs) {
+ if (supported_codec.codec == media::kCodecVP8 &&
+ !media::MediaCodecUtil::IsVp8EncoderAvailable()) {
+ continue;
+ }
+
if (VideoCodecBridge::IsKnownUnaccelerated(supported_codec.codec,
media::MEDIA_CODEC_ENCODER)) {
continue;
@@ -164,17 +160,24 @@ bool AndroidVideoEncodeAccelerator::Initialize(
std::string mime_type;
media::VideoCodec codec;
+ // The client should be prepared to feed at least this many frames into the
+ // encoder before being returned any output frames, since the encoder may
+ // need to hold onto some subset of inputs as reference pictures.
+ uint32_t frame_input_count;
if (output_profile == media::VP8PROFILE_ANY) {
codec = media::kCodecVP8;
mime_type = "video/x-vnd.on2.vp8";
+ frame_input_count = 1;
} else if (output_profile == media::H264PROFILE_BASELINE ||
output_profile == media::H264PROFILE_MAIN) {
codec = media::kCodecH264;
mime_type = "video/avc";
+ frame_input_count = 30;
} else {
return false;
}
+ frame_size_ = input_visible_size;
last_set_bitrate_ = initial_bitrate;
// Only consider using MediaCodec if it's likely backed by hardware.
@@ -202,15 +205,16 @@ bool AndroidVideoEncodeAccelerator::Initialize(
return false;
}
- num_output_buffers_ = media_codec_->GetOutputBuffersCount();
- output_buffers_capacity_ = media_codec_->GetOutputBuffersCapacity();
+ // Conservative upper bound for output buffer size: decoded size + 2KB.
+ const size_t output_buffer_capacity =
+ VideoFrame::AllocationSize(format, input_visible_size) + 2048;
base::MessageLoop::current()->PostTask(
FROM_HERE,
base::Bind(&VideoEncodeAccelerator::Client::RequireBitstreamBuffers,
client_ptr_factory_->GetWeakPtr(),
- num_output_buffers_,
+ frame_input_count,
input_visible_size,
- output_buffers_capacity_));
+ output_buffer_capacity));
return true;
}
@@ -238,7 +242,8 @@ void AndroidVideoEncodeAccelerator::Encode(
DCHECK(thread_checker_.CalledOnValidThread());
RETURN_ON_FAILURE(frame->format() == media::PIXEL_FORMAT_I420,
"Unexpected format", kInvalidArgumentError);
-
+ RETURN_ON_FAILURE(frame->visible_rect().size() == frame_size_,
+ "Unexpected resolution", kInvalidArgumentError);
// MediaCodec doesn't have a way to specify stride for non-Packed formats, so
// we insist on being called with packed frames and no cropping :(
RETURN_ON_FAILURE(frame->row_bytes(VideoFrame::kYPlane) ==
@@ -260,9 +265,6 @@ void AndroidVideoEncodeAccelerator::UseOutputBitstreamBuffer(
const media::BitstreamBuffer& buffer) {
DVLOG(3) << __PRETTY_FUNCTION__ << ": bitstream_buffer_id=" << buffer.id();
DCHECK(thread_checker_.CalledOnValidThread());
- RETURN_ON_FAILURE(buffer.size() >= media_codec_->GetOutputBuffersCapacity(),
- "Output buffers too small!",
- kInvalidArgumentError);
available_bitstream_buffers_.push_back(buffer);
DoIOTask();
}
@@ -331,7 +333,9 @@ void AndroidVideoEncodeAccelerator::QueueInput() {
uint8_t* buffer = NULL;
size_t capacity = 0;
- media_codec_->GetInputBuffer(input_buf_index, &buffer, &capacity);
+ status = media_codec_->GetInputBuffer(input_buf_index, &buffer, &capacity);
+ RETURN_ON_FAILURE(status == media::MEDIA_CODEC_OK, "GetInputBuffer failed.",
+ kPlatformFailureError);
size_t queued_size =
VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420, frame->coded_size());
@@ -373,21 +377,6 @@ void AndroidVideoEncodeAccelerator::QueueInput() {
pending_frames_.pop();
}
-bool AndroidVideoEncodeAccelerator::DoOutputBuffersSuffice() {
- // If this returns false ever, then the VEA::Client interface will need to
- // grow a DismissBitstreamBuffer() call, and VEA::Client impls will have to be
- // prepared to field multiple requests to RequireBitstreamBuffers().
- int count = media_codec_->GetOutputBuffersCount();
- size_t capacity = media_codec_->GetOutputBuffersCapacity();
- bool ret = count <= num_output_buffers_ &&
- capacity <= output_buffers_capacity_;
- LOG_IF(ERROR, !ret) << "Need more/bigger buffers; before: "
- << num_output_buffers_ << "x" << output_buffers_capacity_
- << ", now: " << count << "x" << capacity;
- UMA_HISTOGRAM_BOOLEAN("Media.AVEA.OutputBuffersSuffice", ret);
- return ret;
-}
-
void AndroidVideoEncodeAccelerator::DequeueOutput() {
if (!client_ptr_factory_->GetWeakPtr() ||
available_bitstream_buffers_.empty() || num_buffers_at_codec_ == 0) {
@@ -410,13 +399,14 @@ void AndroidVideoEncodeAccelerator::DequeueOutput() {
// Unreachable because of previous statement, but included for clarity.
return;
- case media::MEDIA_CODEC_OUTPUT_FORMAT_CHANGED: // Fall-through.
- case media::MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED:
- RETURN_ON_FAILURE(DoOutputBuffersSuffice(),
- "Bitstream now requires more/larger buffers",
+ case media::MEDIA_CODEC_OUTPUT_FORMAT_CHANGED:
+ RETURN_ON_FAILURE(false, "Unexpected output format change",
kPlatformFailureError);
break;
+ case media::MEDIA_CODEC_OUTPUT_BUFFERS_CHANGED:
+ break;
+
case media::MEDIA_CODEC_OK:
DCHECK_GE(buf_index, 0);
break;
@@ -429,17 +419,17 @@ void AndroidVideoEncodeAccelerator::DequeueOutput() {
media::BitstreamBuffer bitstream_buffer = available_bitstream_buffers_.back();
available_bitstream_buffers_.pop_back();
- scoped_ptr<base::SharedMemory> shm(
- new base::SharedMemory(bitstream_buffer.handle(), false));
- RETURN_ON_FAILURE(shm->Map(bitstream_buffer.size()),
- "Failed to map SHM",
- kPlatformFailureError);
- RETURN_ON_FAILURE(size <= shm->mapped_size(),
- "Encoded buffer too large: " << size << ">"
- << shm->mapped_size(),
+ scoped_ptr<SharedMemoryRegion> shm(
+ new SharedMemoryRegion(bitstream_buffer, false));
+ RETURN_ON_FAILURE(shm->Map(), "Failed to map SHM", kPlatformFailureError);
+ RETURN_ON_FAILURE(size <= shm->size(),
+ "Encoded buffer too large: " << size << ">" << shm->size(),
kPlatformFailureError);
- media_codec_->CopyFromOutputBuffer(buf_index, offset, shm->memory(), size);
+ media::MediaCodecStatus status = media_codec_->CopyFromOutputBuffer(
+ buf_index, offset, shm->memory(), size);
+ RETURN_ON_FAILURE(status == media::MEDIA_CODEC_OK,
+ "CopyFromOutputBuffer failed", kPlatformFailureError);
media_codec_->ReleaseOutputBuffer(buf_index, false);
--num_buffers_at_codec_;
diff --git a/chromium/content/common/gpu/media/android_video_encode_accelerator.h b/chromium/content/common/gpu/media/android_video_encode_accelerator.h
index 426360dca7c..0de3d1866b1 100644
--- a/chromium/content/common/gpu/media/android_video_encode_accelerator.h
+++ b/chromium/content/common/gpu/media/android_video_encode_accelerator.h
@@ -67,9 +67,6 @@ class CONTENT_EXPORT AndroidVideoEncodeAccelerator
void QueueInput();
void DequeueOutput();
- // Returns true if we don't need more or bigger output buffers.
- bool DoOutputBuffersSuffice();
-
// Start & stop |io_timer_| if the time seems right.
void MaybeStartIOTimer();
void MaybeStopIOTimer();
@@ -103,9 +100,9 @@ class CONTENT_EXPORT AndroidVideoEncodeAccelerator
// appearing to move forward.
base::TimeDelta fake_input_timestamp_;
- // Number of requested output buffers and their capacity.
- int num_output_buffers_; // -1 until RequireBitstreamBuffers.
- size_t output_buffers_capacity_; // 0 until RequireBitstreamBuffers.
+ // Resolution of input stream. Set once in initialization and not allowed to
+ // change after.
+ gfx::Size frame_size_;
uint32_t last_set_bitrate_; // In bps.
diff --git a/chromium/content/common/gpu/media/avda_codec_image.cc b/chromium/content/common/gpu/media/avda_codec_image.cc
index 1df753d167e..5830433cdf2 100644
--- a/chromium/content/common/gpu/media/avda_codec_image.cc
+++ b/chromium/content/common/gpu/media/avda_codec_image.cc
@@ -24,16 +24,17 @@ AVDACodecImage::AVDACodecImage(
const base::WeakPtr<gpu::gles2::GLES2Decoder>& decoder,
const scoped_refptr<gfx::SurfaceTexture>& surface_texture)
: shared_state_(shared_state),
- codec_buffer_index_(-1),
+ codec_buffer_index_(kInvalidCodecBufferIndex),
media_codec_(codec),
decoder_(decoder),
surface_texture_(surface_texture),
detach_surface_texture_on_destruction_(false),
- texture_(0),
- need_shader_info_(true),
- texmatrix_uniform_location_(-1) {
+ texture_(0) {
+ // Default to a sane guess of "flip Y", just in case we can't get
+ // the matrix on the first call.
memset(gl_matrix_, 0, sizeof(gl_matrix_));
- gl_matrix_[0] = gl_matrix_[5] = gl_matrix_[10] = gl_matrix_[15] = 1.0f;
+ gl_matrix_[0] = gl_matrix_[10] = gl_matrix_[15] = 1.0f;
+ gl_matrix_[5] = -1.0f;
}
AVDACodecImage::~AVDACodecImage() {}
@@ -55,38 +56,35 @@ bool AVDACodecImage::BindTexImage(unsigned target) {
void AVDACodecImage::ReleaseTexImage(unsigned target) {}
bool AVDACodecImage::CopyTexImage(unsigned target) {
+ if (!surface_texture_)
+ return false;
+
if (target != GL_TEXTURE_EXTERNAL_OES)
return false;
- // Verify that the currently bound texture is the right one. If we're not
- // copying to a Texture that shares our service_id, then we can't do much.
- // This will force a copy.
- // TODO(liberato): Fall back to a copy that uses the texture matrix.
GLint bound_service_id = 0;
glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id);
+ // We insist that the currently bound texture is the right one. We could
+ // make a new glimage from a 2D image.
if (bound_service_id != shared_state_->surface_texture_service_id())
return false;
- // Attach the surface texture to our GL context if needed.
+ // If the surface texture isn't attached yet, then attach it. Note that this
+ // will be to the texture in |shared_state_|, because of the checks above.
if (!shared_state_->surface_texture_is_attached())
AttachSurfaceTextureToContext();
- // Make sure that we have the right image in the front buffer.
- UpdateSurfaceTexture();
-
- InstallTextureMatrix();
-
- // TODO(liberato): Handle the texture matrix properly.
- // Either we can update the shader with it or we can move all of the logic
- // to updateTexImage() to the right place in the cc to send it to the shader.
- // For now, we just skip it. crbug.com/530681
+ // Make sure that we have the right image in the front buffer. Note that the
+ // bound_service_id is guaranteed to be equal to the surface texture's client
+ // texture id, so we can skip preserving it if the right context is current.
+ UpdateSurfaceTexture(kDontRestoreBindings);
// By setting image state to UNBOUND instead of COPIED we ensure that
// CopyTexImage() is called each time the surface texture is used for drawing.
// It would be nice if we could do this via asking for the currently bound
// Texture, but the active unit never seems to change.
- texture_->SetLevelImage(GL_TEXTURE_EXTERNAL_OES, 0, this,
- gpu::gles2::Texture::UNBOUND);
+ texture_->SetLevelStreamTextureImage(GL_TEXTURE_EXTERNAL_OES, 0, this,
+ gpu::gles2::Texture::UNBOUND);
return true;
}
@@ -102,16 +100,29 @@ bool AVDACodecImage::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
gfx::OverlayTransform transform,
const gfx::Rect& bounds_rect,
const gfx::RectF& crop_rect) {
- return false;
+ // This should only be called when we're rendering to a SurfaceView.
+ if (surface_texture_) {
+ DVLOG(1) << "Invalid call to ScheduleOverlayPlane; this image is "
+ "SurfaceTexture backed.";
+ return false;
+ }
+
+ if (codec_buffer_index_ != kInvalidCodecBufferIndex) {
+ media_codec_->ReleaseOutputBuffer(codec_buffer_index_, true);
+ codec_buffer_index_ = kInvalidCodecBufferIndex;
+ }
+ return true;
}
void AVDACodecImage::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd,
uint64_t process_tracing_id,
const std::string& dump_name) {}
-void AVDACodecImage::UpdateSurfaceTexture() {
+void AVDACodecImage::UpdateSurfaceTexture(RestoreBindingsMode mode) {
+ DCHECK(surface_texture_);
+
// Render via the media codec if needed.
- if (codec_buffer_index_ <= -1 || !media_codec_)
+ if (!IsCodecBufferOutstanding())
return;
// The decoder buffer is still pending.
@@ -123,15 +134,24 @@ void AVDACodecImage::UpdateSurfaceTexture() {
}
// Don't bother to check if we're rendered again.
- codec_buffer_index_ = -1;
+ codec_buffer_index_ = kInvalidCodecBufferIndex;
// Swap the rendered image to the front.
- scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current;
- if (!shared_state_->context()->IsCurrent(NULL)) {
- scoped_make_current.reset(new ui::ScopedMakeCurrent(
- shared_state_->context(), shared_state_->surface()));
- }
+ scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current = MakeCurrentIfNeeded();
+
+ // If we changed contexts, then we always want to restore it, since the caller
+ // doesn't know that we're switching contexts.
+ if (scoped_make_current)
+ mode = kDoRestoreBindings;
+
+ // Save the current binding if requested.
+ GLint bound_service_id = 0;
+ if (mode == kDoRestoreBindings)
+ glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id);
+
surface_texture_->UpdateTexImage();
+ if (mode == kDoRestoreBindings)
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, bound_service_id);
// Helpfully, this is already column major.
surface_texture_->GetTransformMatrix(gl_matrix_);
@@ -153,16 +173,19 @@ void AVDACodecImage::SetMediaCodec(media::MediaCodecBridge* codec) {
media_codec_ = codec;
}
-void AVDACodecImage::setTexture(gpu::gles2::Texture* texture) {
+void AVDACodecImage::SetTexture(gpu::gles2::Texture* texture) {
texture_ = texture;
}
void AVDACodecImage::AttachSurfaceTextureToContext() {
+ DCHECK(surface_texture_);
+
+ // We assume that the currently bound texture is the intended one.
+
// Attach the surface texture to the first context we're bound on, so that
// no context switch is needed later.
-
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
@@ -170,35 +193,48 @@ void AVDACodecImage::AttachSurfaceTextureToContext() {
// We could do this earlier, but SurfaceTexture has context affinity, and we
// don't want to require a context switch.
surface_texture_->AttachToGLContext();
- shared_state_->did_attach_surface_texture();
-}
-
-void AVDACodecImage::InstallTextureMatrix() {
- // glUseProgram() has been run already -- just modify the uniform.
- // Updating this via VideoFrameProvider::Client::DidUpdateMatrix() would
- // be a better solution, except that we'd definitely miss a frame at this
- // point in drawing.
- // Our current method assumes that we'll end up being a stream resource,
- // and that the program has a texMatrix uniform that does what we want.
- if (need_shader_info_) {
- GLint program_id = -1;
- glGetIntegerv(GL_CURRENT_PROGRAM, &program_id);
-
- if (program_id >= 0) {
- // This is memorized from cc/output/shader.cc .
- const char* uniformName = "texMatrix";
- texmatrix_uniform_location_ =
- glGetUniformLocation(program_id, uniformName);
- DCHECK(texmatrix_uniform_location_ != -1);
- }
+ shared_state_->DidAttachSurfaceTexture();
+}
- // Only try once.
- need_shader_info_ = false;
+scoped_ptr<ui::ScopedMakeCurrent> AVDACodecImage::MakeCurrentIfNeeded() {
+ DCHECK(shared_state_->context());
+ scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current;
+ if (!shared_state_->context()->IsCurrent(NULL)) {
+ scoped_make_current.reset(new ui::ScopedMakeCurrent(
+ shared_state_->context(), shared_state_->surface()));
}
- if (texmatrix_uniform_location_ >= 0) {
- glUniformMatrix4fv(texmatrix_uniform_location_, 1, false, gl_matrix_);
+ return scoped_make_current;
+}
+
+void AVDACodecImage::GetTextureMatrix(float matrix[16]) {
+ if (IsCodecBufferOutstanding() && shared_state_ && surface_texture_) {
+ // Our current matrix may be stale. Update it if possible.
+ if (!shared_state_->surface_texture_is_attached()) {
+ // Don't attach the surface texture permanently. Perhaps we should
+ // just attach the surface texture in avda and be done with it.
+ GLuint service_id = 0;
+ glGenTextures(1, &service_id);
+ GLint bound_service_id = 0;
+ glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &bound_service_id);
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, service_id);
+ AttachSurfaceTextureToContext();
+ UpdateSurfaceTexture(kDontRestoreBindings);
+ // Detach the surface texture, which deletes the generated texture.
+ surface_texture_->DetachFromGLContext();
+ shared_state_->DidDetachSurfaceTexture();
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, bound_service_id);
+ } else {
+ // Surface texture is already attached, so just update it.
+ UpdateSurfaceTexture(kDoRestoreBindings);
+ }
}
+
+ memcpy(matrix, gl_matrix_, sizeof(gl_matrix_));
+}
+
+bool AVDACodecImage::IsCodecBufferOutstanding() const {
+ return codec_buffer_index_ != kInvalidCodecBufferIndex && media_codec_;
}
} // namespace content
diff --git a/chromium/content/common/gpu/media/avda_codec_image.h b/chromium/content/common/gpu/media/avda_codec_image.h
index ef0456a9fba..46547e478c8 100644
--- a/chromium/content/common/gpu/media/avda_codec_image.h
+++ b/chromium/content/common/gpu/media/avda_codec_image.h
@@ -9,13 +9,17 @@
#include "base/macros.h"
#include "content/common/gpu/media/avda_shared_state.h"
-#include "ui/gl/gl_image.h"
+#include "gpu/command_buffer/service/gl_stream_texture_image.h"
+
+namespace ui {
+class ScopedMakeCurrent;
+}
namespace content {
-// GLImage that renders MediaCodec buffers to a SurfaceTexture as needed
-// in order to draw them.
-class AVDACodecImage : public gl::GLImage {
+// GLImage that renders MediaCodec buffers to a SurfaceTexture or SurfaceView as
+// needed in order to draw them.
+class AVDACodecImage : public gpu::gles2::GLStreamTextureImage {
public:
AVDACodecImage(const scoped_refptr<AVDASharedState>&,
media::VideoCodecBridge* codec,
@@ -44,6 +48,8 @@ class AVDACodecImage : public gl::GLImage {
void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd,
uint64_t process_tracing_id,
const std::string& dump_name) override;
+ // gpu::gles2::GLStreamTextureMatrix implementation
+ void GetTextureMatrix(float xform[16]) override;
public:
// Decoded buffer index that has the image for us to display.
@@ -58,24 +64,42 @@ class AVDACodecImage : public gl::GLImage {
void SetMediaCodec(media::MediaCodecBridge* codec);
- void setTexture(gpu::gles2::Texture* texture);
+ void SetTexture(gpu::gles2::Texture* texture);
private:
- // Make sure that the surface texture's front buffer is current.
- void UpdateSurfaceTexture();
-
- // Attach the surface texture to our GL context, with a texture that we
- // create for it.
+ enum { kInvalidCodecBufferIndex = -1 };
+
+ // Make sure that the surface texture's front buffer is current. This will
+ // save / restore the current context. It will optionally restore the texture
+ // bindings in the surface texture's context, based on |mode|. This is
+ // intended as a hint if we don't need to change contexts. If we do need to
+ // change contexts, then we'll always preserve the texture bindings in the
+ // both contexts. In other words, the caller is telling us whether it's
+ // okay to change the binding in the current context.
+ enum RestoreBindingsMode { kDontRestoreBindings, kDoRestoreBindings };
+ void UpdateSurfaceTexture(RestoreBindingsMode mode);
+
+ // Attach the surface texture to our GL context to whatever texture is bound
+ // on the active unit.
void AttachSurfaceTextureToContext();
- // Install the current texture matrix into the shader.
- void InstallTextureMatrix();
+ // Make shared_state_->context() current if it isn't already.
+ scoped_ptr<ui::ScopedMakeCurrent> MakeCurrentIfNeeded();
+
+ // Return whether or not the current context is in the same share group as
+ // |surface_texture_|'s client texture.
+ // TODO(liberato): is this needed?
+ bool IsCorrectShareGroup() const;
+
+ // Return whether there is a codec buffer that we haven't rendered yet. Will
+ // return false also if there's no codec or we otherwise can't update.
+ bool IsCodecBufferOutstanding() const;
// Shared state between the AVDA and all AVDACodecImages.
scoped_refptr<AVDASharedState> shared_state_;
- // Codec's buffer index that we should render to the surface texture,
- // or <0 if none.
+ // The MediaCodec buffer index that we should render. Only valid if not equal
+ // to |kInvalidCodecBufferIndex|.
int codec_buffer_index_;
// Our image size.
@@ -86,6 +110,8 @@ class AVDACodecImage : public gl::GLImage {
const base::WeakPtr<gpu::gles2::GLES2Decoder> decoder_;
+ // The SurfaceTexture to render to. This is null when rendering to a
+ // SurfaceView.
const scoped_refptr<gfx::SurfaceTexture> surface_texture_;
// Should we detach |surface_texture_| from its GL context when we are
@@ -95,12 +121,6 @@ class AVDACodecImage : public gl::GLImage {
// The texture that we're attached to.
gpu::gles2::Texture* texture_;
- // Have we cached |texmatrix_uniform_location_| yet?
- bool need_shader_info_;
-
- // Uniform ID of the texture matrix in the shader.
- GLint texmatrix_uniform_location_;
-
// Texture matrix of the front buffer of the surface texture.
float gl_matrix_[16];
diff --git a/chromium/content/common/gpu/media/avda_shared_state.cc b/chromium/content/common/gpu/media/avda_shared_state.cc
index c182bf05385..7746254fee9 100644
--- a/chromium/content/common/gpu/media/avda_shared_state.cc
+++ b/chromium/content/common/gpu/media/avda_shared_state.cc
@@ -4,6 +4,7 @@
#include "content/common/gpu/media/avda_shared_state.h"
+#include "base/time/time.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/scoped_make_current.h"
@@ -21,10 +22,13 @@ void AVDASharedState::SignalFrameAvailable() {
}
void AVDASharedState::WaitForFrameAvailable() {
- frame_available_event_.Wait();
+ // 10msec covers >99.9% of cases, so just wait for up to that much before
+ // giving up. If an error occurs, we might not ever get a notification.
+ const base::TimeDelta max_wait_time(base::TimeDelta::FromMilliseconds(10));
+ frame_available_event_.TimedWait(max_wait_time);
}
-void AVDASharedState::did_attach_surface_texture() {
+void AVDASharedState::DidAttachSurfaceTexture() {
context_ = gfx::GLContext::GetCurrent();
surface_ = gfx::GLSurface::GetCurrent();
DCHECK(context_);
@@ -33,4 +37,10 @@ void AVDASharedState::did_attach_surface_texture() {
surface_texture_is_attached_ = true;
}
+void AVDASharedState::DidDetachSurfaceTexture() {
+ context_ = nullptr;
+ surface_ = nullptr;
+ surface_texture_is_attached_ = false;
+}
+
} // namespace content
diff --git a/chromium/content/common/gpu/media/avda_shared_state.h b/chromium/content/common/gpu/media/avda_shared_state.h
index eb62681fcd5..5f80c44d729 100644
--- a/chromium/content/common/gpu/media/avda_shared_state.h
+++ b/chromium/content/common/gpu/media/avda_shared_state.h
@@ -50,10 +50,19 @@ class AVDASharedState : public base::RefCounted<AVDASharedState> {
return surface_texture_is_attached_;
}
+ // TODO(liberato): move the surface texture here and make these calls
+ // attach / detach it also. There are several changes going on in avda
+ // concurrently, so I don't want to change that until the dust settles.
+ // AVDACodecImage would no longer hold the surface texture.
+
// Call this when the SurfaceTexture is attached to a GL context. This will
// update surface_texture_is_attached(), and set the context() and surface()
// to match.
- void did_attach_surface_texture();
+ void DidAttachSurfaceTexture();
+
+ // Call this when the SurfaceTexture is detached from its GL context. This
+ // will cause us to forget the last binding.
+ void DidDetachSurfaceTexture();
private:
// Platform gl texture Id for |surface_texture_|. This will be zero if
diff --git a/chromium/content/common/gpu/media/avda_state_provider.h b/chromium/content/common/gpu/media/avda_state_provider.h
index 2c84f2ed04a..e7dfac62ded 100644
--- a/chromium/content/common/gpu/media/avda_state_provider.h
+++ b/chromium/content/common/gpu/media/avda_state_provider.h
@@ -8,6 +8,7 @@
#include "base/compiler_specific.h"
#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
+#include "gpu/command_buffer/service/texture_manager.h"
#include "media/video/video_decode_accelerator.h"
namespace gfx {
@@ -36,6 +37,8 @@ class AVDAStateProvider {
virtual const gfx::Size& GetSize() const = 0;
virtual const base::ThreadChecker& ThreadChecker() const = 0;
virtual base::WeakPtr<gpu::gles2::GLES2Decoder> GetGlDecoder() const = 0;
+ virtual gpu::gles2::TextureRef* GetTextureForPicture(
+ const media::PictureBuffer& picture_buffer) = 0;
// Helper function to report an error condition and stop decoding.
// This will post NotifyError(), and transition to the error state.
diff --git a/chromium/content/common/gpu/media/dxva_video_decode_accelerator_win.cc b/chromium/content/common/gpu/media/dxva_video_decode_accelerator_win.cc
index 40a3239cb25..e55c9009720 100644
--- a/chromium/content/common/gpu/media/dxva_video_decode_accelerator_win.cc
+++ b/chromium/content/common/gpu/media/dxva_video_decode_accelerator_win.cc
@@ -21,7 +21,6 @@
#include "base/base_paths_win.h"
#include "base/bind.h"
#include "base/callback.h"
-#include "base/command_line.h"
#include "base/debug/alias.h"
#include "base/file_version_info.h"
#include "base/files/file_path.h"
@@ -34,15 +33,14 @@
#include "base/trace_event/trace_event.h"
#include "base/win/windows_version.h"
#include "build/build_config.h"
-#include "content/public/common/content_switches.h"
#include "media/base/win/mf_initializer.h"
#include "media/video/video_decode_accelerator.h"
#include "third_party/angle/include/EGL/egl.h"
#include "third_party/angle/include/EGL/eglext.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_fence.h"
#include "ui/gl/gl_surface_egl.h"
-#include "ui/gl/gl_switches.h"
namespace {
@@ -113,6 +111,91 @@ DEFINE_GUID(CLSID_VideoProcessorMFT,
DEFINE_GUID(MF_XVP_PLAYBACK_MODE, 0x3c5d293f, 0xad67, 0x4e29, 0xaf, 0x12,
0xcf, 0x3e, 0x23, 0x8a, 0xcc, 0xe9);
+// Defines the GUID for the Intel H264 DXVA device.
+static const GUID DXVA2_Intel_ModeH264_E = {
+ 0x604F8E68, 0x4951, 0x4c54,{ 0x88, 0xFE, 0xAB, 0xD2, 0x5C, 0x15, 0xB3, 0xD6}
+};
+
+// R600, R700, Evergreen and Cayman AMD cards. These support DXVA via UVD3
+// or earlier, and don't handle resolutions higher than 1920 x 1088 well.
+static const DWORD g_AMDUVD3GPUList[] = {
+ 0x9400, 0x9401, 0x9402, 0x9403, 0x9405, 0x940a, 0x940b, 0x940f, 0x94c0,
+ 0x94c1, 0x94c3, 0x94c4, 0x94c5, 0x94c6, 0x94c7, 0x94c8, 0x94c9, 0x94cb,
+ 0x94cc, 0x94cd, 0x9580, 0x9581, 0x9583, 0x9586, 0x9587, 0x9588, 0x9589,
+ 0x958a, 0x958b, 0x958c, 0x958d, 0x958e, 0x958f, 0x9500, 0x9501, 0x9504,
+ 0x9505, 0x9506, 0x9507, 0x9508, 0x9509, 0x950f, 0x9511, 0x9515, 0x9517,
+ 0x9519, 0x95c0, 0x95c2, 0x95c4, 0x95c5, 0x95c6, 0x95c7, 0x95c9, 0x95cc,
+ 0x95cd, 0x95ce, 0x95cf, 0x9590, 0x9591, 0x9593, 0x9595, 0x9596, 0x9597,
+ 0x9598, 0x9599, 0x959b, 0x9610, 0x9611, 0x9612, 0x9613, 0x9614, 0x9615,
+ 0x9616, 0x9710, 0x9711, 0x9712, 0x9713, 0x9714, 0x9715, 0x9440, 0x9441,
+ 0x9442, 0x9443, 0x9444, 0x9446, 0x944a, 0x944b, 0x944c, 0x944e, 0x9450,
+ 0x9452, 0x9456, 0x945a, 0x945b, 0x945e, 0x9460, 0x9462, 0x946a, 0x946b,
+ 0x947a, 0x947b, 0x9480, 0x9487, 0x9488, 0x9489, 0x948a, 0x948f, 0x9490,
+ 0x9491, 0x9495, 0x9498, 0x949c, 0x949e, 0x949f, 0x9540, 0x9541, 0x9542,
+ 0x954e, 0x954f, 0x9552, 0x9553, 0x9555, 0x9557, 0x955f, 0x94a0, 0x94a1,
+ 0x94a3, 0x94b1, 0x94b3, 0x94b4, 0x94b5, 0x94b9, 0x68e0, 0x68e1, 0x68e4,
+ 0x68e5, 0x68e8, 0x68e9, 0x68f1, 0x68f2, 0x68f8, 0x68f9, 0x68fa, 0x68fe,
+ 0x68c0, 0x68c1, 0x68c7, 0x68c8, 0x68c9, 0x68d8, 0x68d9, 0x68da, 0x68de,
+ 0x68a0, 0x68a1, 0x68a8, 0x68a9, 0x68b0, 0x68b8, 0x68b9, 0x68ba, 0x68be,
+ 0x68bf, 0x6880, 0x6888, 0x6889, 0x688a, 0x688c, 0x688d, 0x6898, 0x6899,
+ 0x689b, 0x689e, 0x689c, 0x689d, 0x9802, 0x9803, 0x9804, 0x9805, 0x9806,
+ 0x9807, 0x9808, 0x9809, 0x980a, 0x9640, 0x9641, 0x9647, 0x9648, 0x964a,
+ 0x964b, 0x964c, 0x964e, 0x964f, 0x9642, 0x9643, 0x9644, 0x9645, 0x9649,
+ 0x6720, 0x6721, 0x6722, 0x6723, 0x6724, 0x6725, 0x6726, 0x6727, 0x6728,
+ 0x6729, 0x6738, 0x6739, 0x673e, 0x6740, 0x6741, 0x6742, 0x6743, 0x6744,
+ 0x6745, 0x6746, 0x6747, 0x6748, 0x6749, 0x674a, 0x6750, 0x6751, 0x6758,
+ 0x6759, 0x675b, 0x675d, 0x675f, 0x6840, 0x6841, 0x6842, 0x6843, 0x6849,
+ 0x6850, 0x6858, 0x6859, 0x6760, 0x6761, 0x6762, 0x6763, 0x6764, 0x6765,
+ 0x6766, 0x6767, 0x6768, 0x6770, 0x6771, 0x6772, 0x6778, 0x6779, 0x677b,
+ 0x6700, 0x6701, 0x6702, 0x6703, 0x6704, 0x6705, 0x6706, 0x6707, 0x6708,
+ 0x6709, 0x6718, 0x6719, 0x671c, 0x671d, 0x671f, 0x683D, 0x9900, 0x9901,
+ 0x9903, 0x9904, 0x9905, 0x9906, 0x9907, 0x9908, 0x9909, 0x990a, 0x990b,
+ 0x990c, 0x990d, 0x990e, 0x990f, 0x9910, 0x9913, 0x9917, 0x9918, 0x9919,
+ 0x9990, 0x9991, 0x9992, 0x9993, 0x9994, 0x9995, 0x9996, 0x9997, 0x9998,
+ 0x9999, 0x999a, 0x999b, 0x999c, 0x999d, 0x99a0, 0x99a2, 0x99a4,
+};
+
+// Legacy Intel GPUs (Second generation) which have trouble with resolutions
+// higher than 1920 x 1088
+static const DWORD g_IntelLegacyGPUList[] = {
+ 0x102, 0x106, 0x116, 0x126,
+};
+
+// Provides scoped access to the underlying buffer in an IMFMediaBuffer
+// instance.
+class MediaBufferScopedPointer {
+ public:
+ MediaBufferScopedPointer(IMFMediaBuffer* media_buffer)
+ : media_buffer_(media_buffer),
+ buffer_(nullptr),
+ max_length_(0),
+ current_length_(0) {
+ HRESULT hr = media_buffer_->Lock(&buffer_, &max_length_, &current_length_);
+ CHECK(SUCCEEDED(hr));
+ }
+
+ ~MediaBufferScopedPointer() {
+ HRESULT hr = media_buffer_->Unlock();
+ CHECK(SUCCEEDED(hr));
+ }
+
+ uint8_t* get() {
+ return buffer_;
+ }
+
+ DWORD current_length() const {
+ return current_length_;
+ }
+
+ private:
+ base::win::ScopedComPtr<IMFMediaBuffer> media_buffer_;
+ uint8_t* buffer_;
+ DWORD max_length_;
+ DWORD current_length_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaBufferScopedPointer);
+};
+
} // namespace
namespace content {
@@ -122,7 +205,10 @@ static const media::VideoCodecProfile kSupportedProfiles[] = {
media::H264PROFILE_MAIN,
media::H264PROFILE_HIGH,
media::VP8PROFILE_ANY,
- media::VP9PROFILE_ANY
+ media::VP9PROFILE_PROFILE0,
+ media::VP9PROFILE_PROFILE1,
+ media::VP9PROFILE_PROFILE2,
+ media::VP9PROFILE_PROFILE3
};
CreateDXGIDeviceManager DXVAVideoDecodeAccelerator::create_dxgi_device_manager_
@@ -162,10 +248,16 @@ enum {
kFlushDecoderSurfaceTimeoutMs = 1,
// Maximum iterations where we try to flush the d3d device.
kMaxIterationsForD3DFlush = 4,
+ // Maximum iterations where we try to flush the ANGLE device before reusing
+ // the texture.
+ kMaxIterationsForANGLEReuseFlush = 16,
// We only request 5 picture buffers from the client which are used to hold
// the decoded samples. These buffers are then reused when the client tells
// us that it is done with the buffer.
kNumPictureBuffers = 5,
+ // The keyed mutex should always be released before the other thread
+ // attempts to acquire it, so AcquireSync should always return immediately.
+ kAcquireSyncWaitMs = 0,
};
static IMFSample* CreateEmptySample() {
@@ -177,8 +269,9 @@ static IMFSample* CreateEmptySample() {
// Creates a Media Foundation sample with one buffer of length |buffer_length|
// on a |align|-byte boundary. Alignment must be a perfect power of 2 or 0.
-static IMFSample* CreateEmptySampleWithBuffer(int buffer_length, int align) {
- CHECK_GT(buffer_length, 0);
+static IMFSample* CreateEmptySampleWithBuffer(uint32_t buffer_length,
+ int align) {
+ CHECK_GT(buffer_length, 0U);
base::win::ScopedComPtr<IMFSample> sample;
sample.Attach(CreateEmptySample());
@@ -209,11 +302,11 @@ static IMFSample* CreateEmptySampleWithBuffer(int buffer_length, int align) {
// |min_size| specifies the minimum size of the buffer (might be required by
// the decoder for input). If no alignment is required, provide 0.
static IMFSample* CreateInputSample(const uint8_t* stream,
- int size,
- int min_size,
+ uint32_t size,
+ uint32_t min_size,
int alignment) {
CHECK(stream);
- CHECK_GT(size, 0);
+ CHECK_GT(size, 0U);
base::win::ScopedComPtr<IMFSample> sample;
sample.Attach(CreateEmptySampleWithBuffer(std::max(min_size, size),
alignment));
@@ -230,28 +323,16 @@ static IMFSample* CreateInputSample(const uint8_t* stream,
RETURN_ON_HR_FAILURE(hr, "Failed to lock buffer", NULL);
CHECK_EQ(current_length, 0u);
- CHECK_GE(static_cast<int>(max_length), size);
+ CHECK_GE(max_length, size);
memcpy(destination, stream, size);
- hr = buffer->Unlock();
- RETURN_ON_HR_FAILURE(hr, "Failed to unlock buffer", NULL);
-
hr = buffer->SetCurrentLength(size);
RETURN_ON_HR_FAILURE(hr, "Failed to set buffer length", NULL);
- return sample.Detach();
-}
-
-static IMFSample* CreateSampleFromInputBuffer(
- const media::BitstreamBuffer& bitstream_buffer,
- DWORD stream_size,
- DWORD alignment) {
- base::SharedMemory shm(bitstream_buffer.handle(), true);
- RETURN_ON_FAILURE(shm.Map(bitstream_buffer.size()),
- "Failed in base::SharedMemory::Map", NULL);
+ hr = buffer->Unlock();
+ RETURN_ON_HR_FAILURE(hr, "Failed to unlock buffer", NULL);
- return CreateInputSample(reinterpret_cast<const uint8_t*>(shm.memory()),
- bitstream_buffer.size(), stream_size, alignment);
+ return sample.Detach();
}
// Helper function to create a COM object instance from a DLL. The alternative
@@ -289,55 +370,188 @@ template<class T>
base::win::ScopedComPtr<T> QueryDeviceObjectFromANGLE(int object_type) {
base::win::ScopedComPtr<T> device_object;
- EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay();
+ EGLDisplay egl_display = nullptr;
intptr_t egl_device = 0;
intptr_t device = 0;
+ {
+ TRACE_EVENT0("gpu", "QueryDeviceObjectFromANGLE. GetHardwareDisplay");
+ egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay();
+ }
+
RETURN_ON_FAILURE(
gfx::GLSurfaceEGL::HasEGLExtension("EGL_EXT_device_query"),
"EGL_EXT_device_query missing",
device_object);
- PFNEGLQUERYDISPLAYATTRIBEXTPROC QueryDisplayAttribEXT =
- reinterpret_cast<PFNEGLQUERYDISPLAYATTRIBEXTPROC>(eglGetProcAddress(
- "eglQueryDisplayAttribEXT"));
+ PFNEGLQUERYDISPLAYATTRIBEXTPROC QueryDisplayAttribEXT = nullptr;
- RETURN_ON_FAILURE(
- QueryDisplayAttribEXT,
- "Failed to get the eglQueryDisplayAttribEXT function from ANGLE",
- device_object);
+ {
+ TRACE_EVENT0("gpu", "QueryDeviceObjectFromANGLE. eglGetProcAddress");
- PFNEGLQUERYDEVICEATTRIBEXTPROC QueryDeviceAttribEXT =
- reinterpret_cast<PFNEGLQUERYDEVICEATTRIBEXTPROC>(eglGetProcAddress(
- "eglQueryDeviceAttribEXT"));
+ QueryDisplayAttribEXT =
+ reinterpret_cast<PFNEGLQUERYDISPLAYATTRIBEXTPROC>(eglGetProcAddress(
+ "eglQueryDisplayAttribEXT"));
- RETURN_ON_FAILURE(
- QueryDeviceAttribEXT,
- "Failed to get the eglQueryDeviceAttribEXT function from ANGLE",
- device_object);
+ RETURN_ON_FAILURE(
+ QueryDisplayAttribEXT,
+ "Failed to get the eglQueryDisplayAttribEXT function from ANGLE",
+ device_object);
+ }
- RETURN_ON_FAILURE(
- QueryDisplayAttribEXT(egl_display, EGL_DEVICE_EXT, &egl_device),
- "The eglQueryDisplayAttribEXT function failed to get the EGL device",
- device_object);
+ PFNEGLQUERYDEVICEATTRIBEXTPROC QueryDeviceAttribEXT = nullptr;
+
+ {
+ TRACE_EVENT0("gpu", "QueryDeviceObjectFromANGLE. eglGetProcAddress");
+
+ QueryDeviceAttribEXT =
+ reinterpret_cast<PFNEGLQUERYDEVICEATTRIBEXTPROC>(eglGetProcAddress(
+ "eglQueryDeviceAttribEXT"));
+
+ RETURN_ON_FAILURE(
+ QueryDeviceAttribEXT,
+ "Failed to get the eglQueryDeviceAttribEXT function from ANGLE",
+ device_object);
+ }
+
+ {
+ TRACE_EVENT0("gpu", "QueryDeviceObjectFromANGLE. QueryDisplayAttribEXT");
+
+ RETURN_ON_FAILURE(
+ QueryDisplayAttribEXT(egl_display, EGL_DEVICE_EXT, &egl_device),
+ "The eglQueryDisplayAttribEXT function failed to get the EGL device",
+ device_object);
+ }
RETURN_ON_FAILURE(
egl_device,
"Failed to get the EGL device",
device_object);
- RETURN_ON_FAILURE(
- QueryDeviceAttribEXT(
- reinterpret_cast<EGLDeviceEXT>(egl_device), object_type, &device),
- "The eglQueryDeviceAttribEXT function failed to get the device",
- device_object);
+ {
+ TRACE_EVENT0("gpu", "QueryDeviceObjectFromANGLE. QueryDisplayAttribEXT");
- RETURN_ON_FAILURE(device, "Failed to get the ANGLE device", device_object);
+ RETURN_ON_FAILURE(
+ QueryDeviceAttribEXT(
+ reinterpret_cast<EGLDeviceEXT>(egl_device), object_type, &device),
+ "The eglQueryDeviceAttribEXT function failed to get the device",
+ device_object);
+
+ RETURN_ON_FAILURE(device, "Failed to get the ANGLE device", device_object);
+ }
device_object = reinterpret_cast<T*>(device);
return device_object;
}
+H264ConfigChangeDetector::H264ConfigChangeDetector()
+ : last_sps_id_(0),
+ last_pps_id_(0),
+ config_changed_(false),
+ pending_config_changed_(false) {
+}
+
+H264ConfigChangeDetector::~H264ConfigChangeDetector() {
+}
+
+bool H264ConfigChangeDetector::DetectConfig(const uint8_t* stream,
+ unsigned int size) {
+ std::vector<uint8_t> sps;
+ std::vector<uint8_t> pps;
+ media::H264NALU nalu;
+ bool idr_seen = false;
+
+ if (!parser_.get())
+ parser_.reset(new media::H264Parser);
+
+ parser_->SetStream(stream, size);
+ config_changed_ = false;
+
+ while (true) {
+ media::H264Parser::Result result = parser_->AdvanceToNextNALU(&nalu);
+
+ if (result == media::H264Parser::kEOStream)
+ break;
+
+ if (result == media::H264Parser::kUnsupportedStream) {
+ DLOG(ERROR) << "Unsupported H.264 stream";
+ return false;
+ }
+
+ if (result != media::H264Parser::kOk) {
+ DLOG(ERROR) << "Failed to parse H.264 stream";
+ return false;
+ }
+
+ switch (nalu.nal_unit_type) {
+ case media::H264NALU::kSPS:
+ result = parser_->ParseSPS(&last_sps_id_);
+ if (result == media::H264Parser::kUnsupportedStream) {
+ DLOG(ERROR) << "Unsupported SPS";
+ return false;
+ }
+
+ if (result != media::H264Parser::kOk) {
+ DLOG(ERROR) << "Could not parse SPS";
+ return false;
+ }
+
+ sps.assign(nalu.data, nalu.data + nalu.size);
+ break;
+
+ case media::H264NALU::kPPS:
+ result = parser_->ParsePPS(&last_pps_id_);
+ if (result == media::H264Parser::kUnsupportedStream) {
+ DLOG(ERROR) << "Unsupported PPS";
+ return false;
+ }
+ if (result != media::H264Parser::kOk) {
+ DLOG(ERROR) << "Could not parse PPS";
+ return false;
+ }
+ pps.assign(nalu.data, nalu.data + nalu.size);
+ break;
+
+ case media::H264NALU::kIDRSlice:
+ idr_seen = true;
+ // If we previously detected a configuration change, and see an IDR
+ // slice next time around, we need to flag a configuration change.
+ if (pending_config_changed_) {
+ config_changed_ = true;
+ pending_config_changed_ = false;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (!sps.empty() && sps != last_sps_) {
+ if (!last_sps_.empty()) {
+ // Flag configuration changes after we see an IDR slice.
+ if (idr_seen) {
+ config_changed_ = true;
+ } else {
+ pending_config_changed_ = true;
+ }
+ }
+ last_sps_.swap(sps);
+ }
+
+ if (!pps.empty() && pps != last_pps_) {
+ if (!last_pps_.empty()) {
+ // Flag configuration changes after we see an IDR slice.
+ if (idr_seen) {
+ config_changed_ = true;
+ } else {
+ pending_config_changed_ = true;
+ }
+ }
+ last_pps_.swap(pps);
+ }
+ return true;
+}
// Maintains information about a DXVA picture buffer, i.e. whether it is
// available for rendering, the texture information, etc.
@@ -349,7 +563,11 @@ struct DXVAVideoDecodeAccelerator::DXVAPictureBuffer {
EGLConfig egl_config);
~DXVAPictureBuffer();
- void ReusePictureBuffer();
+ bool InitializeTexture(const DXVAVideoDecodeAccelerator& decoder,
+ bool use_rgb);
+
+ bool ReusePictureBuffer();
+ void ResetReuseFence();
// Copies the output sample data to the picture buffer provided by the
// client.
// The dest_surface parameter contains the decoded bits.
@@ -375,20 +593,37 @@ struct DXVAVideoDecodeAccelerator::DXVAPictureBuffer {
return picture_buffer_.size();
}
+ bool waiting_to_reuse() const { return waiting_to_reuse_; }
+
+ gfx::GLFence* reuse_fence() { return reuse_fence_.get(); }
+
// Called when the source surface |src_surface| is copied to the destination
// |dest_surface|
- void CopySurfaceComplete(IDirect3DSurface9* src_surface,
+ bool CopySurfaceComplete(IDirect3DSurface9* src_surface,
IDirect3DSurface9* dest_surface);
private:
explicit DXVAPictureBuffer(const media::PictureBuffer& buffer);
bool available_;
+
+ // This is true if the decoder is currently waiting on the fence before
+ // reusing the buffer.
+ bool waiting_to_reuse_;
media::PictureBuffer picture_buffer_;
EGLSurface decoding_surface_;
+ scoped_ptr<gfx::GLFence> reuse_fence_;
+
+ HANDLE texture_share_handle_;
base::win::ScopedComPtr<IDirect3DTexture9> decoding_texture_;
base::win::ScopedComPtr<ID3D11Texture2D> dx11_decoding_texture_;
+ base::win::ScopedComPtr<IDXGIKeyedMutex> egl_keyed_mutex_;
+ base::win::ScopedComPtr<IDXGIKeyedMutex> dx11_keyed_mutex_;
+
+ // This is the last value that was used to release the keyed mutex.
+ uint64_t keyed_mutex_value_;
+
// The following |IDirect3DSurface9| interface pointers are used to hold
// references on the surfaces during the course of a StretchRect operation
// to copy the source surface to the target. The references are released
@@ -422,6 +657,9 @@ DXVAVideoDecodeAccelerator::DXVAPictureBuffer::Create(
eglGetConfigAttrib(egl_display, egl_config, EGL_BIND_TO_TEXTURE_RGB,
&use_rgb);
+ if (!picture_buffer->InitializeTexture(decoder, !!use_rgb))
+ return linked_ptr<DXVAPictureBuffer>(nullptr);
+
EGLint attrib_list[] = {
EGL_WIDTH, buffer.size().width(),
EGL_HEIGHT, buffer.size().height(),
@@ -430,59 +668,84 @@ DXVAVideoDecodeAccelerator::DXVAPictureBuffer::Create(
EGL_NONE
};
- picture_buffer->decoding_surface_ = eglCreatePbufferSurface(
- egl_display,
- egl_config,
- attrib_list);
+ picture_buffer->decoding_surface_ = eglCreatePbufferFromClientBuffer(
+ egl_display, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE,
+ picture_buffer->texture_share_handle_, egl_config, attrib_list);
RETURN_ON_FAILURE(picture_buffer->decoding_surface_,
"Failed to create surface",
linked_ptr<DXVAPictureBuffer>(NULL));
+ if (decoder.d3d11_device_ && decoder.use_keyed_mutex_) {
+ void* keyed_mutex = nullptr;
+ EGLBoolean ret = eglQuerySurfacePointerANGLE(
+ egl_display, picture_buffer->decoding_surface_,
+ EGL_DXGI_KEYED_MUTEX_ANGLE, &keyed_mutex);
+ RETURN_ON_FAILURE(keyed_mutex && ret == EGL_TRUE,
+ "Failed to query ANGLE keyed mutex",
+ linked_ptr<DXVAPictureBuffer>(nullptr));
+ picture_buffer->egl_keyed_mutex_ = base::win::ScopedComPtr<IDXGIKeyedMutex>(
+ static_cast<IDXGIKeyedMutex*>(keyed_mutex));
+ }
+ picture_buffer->use_rgb_ = !!use_rgb;
+ return picture_buffer;
+}
- HANDLE share_handle = NULL;
- EGLBoolean ret = eglQuerySurfacePointerANGLE(
- egl_display,
- picture_buffer->decoding_surface_,
- EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE,
- &share_handle);
+bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::InitializeTexture(
+ const DXVAVideoDecodeAccelerator& decoder,
+ bool use_rgb) {
+ DCHECK(!texture_share_handle_);
+ if (decoder.d3d11_device_) {
+ D3D11_TEXTURE2D_DESC desc;
+ desc.Width = picture_buffer_.size().width();
+ desc.Height = picture_buffer_.size().height();
+ desc.MipLevels = 1;
+ desc.ArraySize = 1;
+ desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
+ desc.SampleDesc.Count = 1;
+ desc.SampleDesc.Quality = 0;
+ desc.Usage = D3D11_USAGE_DEFAULT;
+ desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
+ desc.CPUAccessFlags = 0;
+ desc.MiscFlags = decoder.use_keyed_mutex_
+ ? D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX
+ : D3D11_RESOURCE_MISC_SHARED;
+
+ HRESULT hr = decoder.d3d11_device_->CreateTexture2D(
+ &desc, nullptr, dx11_decoding_texture_.Receive());
+ RETURN_ON_HR_FAILURE(hr, "Failed to create texture", false);
+ if (decoder.use_keyed_mutex_) {
+ hr = dx11_keyed_mutex_.QueryFrom(dx11_decoding_texture_.get());
+ RETURN_ON_HR_FAILURE(hr, "Failed to get keyed mutex", false);
+ }
- RETURN_ON_FAILURE(share_handle && ret == EGL_TRUE,
- "Failed to query ANGLE surface pointer",
- linked_ptr<DXVAPictureBuffer>(NULL));
+ base::win::ScopedComPtr<IDXGIResource> resource;
+ hr = resource.QueryFrom(dx11_decoding_texture_.get());
+ DCHECK(SUCCEEDED(hr));
+ hr = resource->GetSharedHandle(&texture_share_handle_);
+ RETURN_ON_FAILURE(SUCCEEDED(hr) && texture_share_handle_,
+ "Failed to query shared handle", false);
- HRESULT hr = E_FAIL;
- if (decoder.d3d11_device_) {
- base::win::ScopedComPtr<ID3D11Resource> resource;
- hr = decoder.d3d11_device_->OpenSharedResource(
- share_handle,
- __uuidof(ID3D11Resource),
- reinterpret_cast<void**>(resource.Receive()));
- RETURN_ON_HR_FAILURE(hr, "Failed to open shared resource",
- linked_ptr<DXVAPictureBuffer>(NULL));
- hr = picture_buffer->dx11_decoding_texture_.QueryFrom(resource.get());
} else {
+ HRESULT hr = E_FAIL;
hr = decoder.d3d9_device_ex_->CreateTexture(
- buffer.size().width(),
- buffer.size().height(),
- 1,
- D3DUSAGE_RENDERTARGET,
- use_rgb ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8,
- D3DPOOL_DEFAULT,
- picture_buffer->decoding_texture_.Receive(),
- &share_handle);
- }
- RETURN_ON_HR_FAILURE(hr, "Failed to create texture",
- linked_ptr<DXVAPictureBuffer>(NULL));
- picture_buffer->use_rgb_ = !!use_rgb;
- return picture_buffer;
+ picture_buffer_.size().width(), picture_buffer_.size().height(), 1,
+ D3DUSAGE_RENDERTARGET, use_rgb ? D3DFMT_X8R8G8B8 : D3DFMT_A8R8G8B8,
+ D3DPOOL_DEFAULT, decoding_texture_.Receive(), &texture_share_handle_);
+ RETURN_ON_HR_FAILURE(hr, "Failed to create texture", false);
+ RETURN_ON_FAILURE(texture_share_handle_, "Failed to query shared handle",
+ false);
+ }
+ return true;
}
DXVAVideoDecodeAccelerator::DXVAPictureBuffer::DXVAPictureBuffer(
const media::PictureBuffer& buffer)
: available_(true),
+ waiting_to_reuse_(false),
picture_buffer_(buffer),
decoding_surface_(NULL),
- use_rgb_(true) {
-}
+ texture_share_handle_(nullptr),
+ keyed_mutex_value_(0),
+ use_rgb_(true) {}
DXVAVideoDecodeAccelerator::DXVAPictureBuffer::~DXVAPictureBuffer() {
if (decoding_surface_) {
@@ -500,7 +763,7 @@ DXVAVideoDecodeAccelerator::DXVAPictureBuffer::~DXVAPictureBuffer() {
}
}
-void DXVAVideoDecodeAccelerator::DXVAPictureBuffer::ReusePictureBuffer() {
+bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::ReusePictureBuffer() {
DCHECK(decoding_surface_);
EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay();
eglReleaseTexImage(
@@ -510,7 +773,21 @@ void DXVAVideoDecodeAccelerator::DXVAPictureBuffer::ReusePictureBuffer() {
decoder_surface_.Release();
target_surface_.Release();
decoder_dx11_texture_.Release();
+ waiting_to_reuse_ = false;
set_available(true);
+ if (egl_keyed_mutex_) {
+ HRESULT hr = egl_keyed_mutex_->ReleaseSync(++keyed_mutex_value_);
+ RETURN_ON_FAILURE(hr == S_OK, "Could not release sync mutex", false);
+ }
+ return true;
+}
+
+void DXVAVideoDecodeAccelerator::DXVAPictureBuffer::ResetReuseFence() {
+ if (!reuse_fence_ || !reuse_fence_->ResetSupported())
+ reuse_fence_.reset(gfx::GLFence::Create());
+ else
+ reuse_fence_->ResetState();
+ waiting_to_reuse_ = true;
}
bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::
@@ -525,8 +802,9 @@ bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::
// when we receive a notification that the copy was completed or when the
// DXVAPictureBuffer instance is destroyed.
decoder_dx11_texture_ = dx11_texture;
- decoder->CopyTexture(dx11_texture, dx11_decoding_texture_.get(), NULL,
- id(), input_buffer_id);
+ decoder->CopyTexture(dx11_texture, dx11_decoding_texture_.get(),
+ dx11_keyed_mutex_, keyed_mutex_value_, NULL, id(),
+ input_buffer_id);
return true;
}
D3DSURFACE_DESC surface_desc;
@@ -566,7 +844,7 @@ bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::
return true;
}
-void DXVAVideoDecodeAccelerator::DXVAPictureBuffer::CopySurfaceComplete(
+bool DXVAVideoDecodeAccelerator::DXVAPictureBuffer::CopySurfaceComplete(
IDirect3DSurface9* src_surface,
IDirect3DSurface9* dest_surface) {
DCHECK(!available());
@@ -574,7 +852,7 @@ void DXVAVideoDecodeAccelerator::DXVAPictureBuffer::CopySurfaceComplete(
GLint current_texture = 0;
glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
- glBindTexture(GL_TEXTURE_2D, picture_buffer_.texture_id());
+ glBindTexture(GL_TEXTURE_2D, picture_buffer_.texture_ids()[0]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -587,6 +865,12 @@ void DXVAVideoDecodeAccelerator::DXVAPictureBuffer::CopySurfaceComplete(
DCHECK(decoder_dx11_texture_.get());
decoder_dx11_texture_.Release();
}
+ if (egl_keyed_mutex_) {
+ keyed_mutex_value_++;
+ HRESULT result =
+ egl_keyed_mutex_->AcquireSync(keyed_mutex_value_, kAcquireSyncWaitMs);
+ RETURN_ON_FAILURE(result == S_OK, "Could not acquire sync mutex", false);
+ }
EGLDisplay egl_display = gfx::GLSurfaceEGL::GetHardwareDisplay();
eglBindTexImage(
@@ -596,6 +880,7 @@ void DXVAVideoDecodeAccelerator::DXVAPictureBuffer::CopySurfaceComplete(
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glBindTexture(GL_TEXTURE_2D, current_texture);
+ return true;
}
DXVAVideoDecodeAccelerator::PendingSampleInfo::PendingSampleInfo(
@@ -608,8 +893,9 @@ DXVAVideoDecodeAccelerator::PendingSampleInfo::PendingSampleInfo(
DXVAVideoDecodeAccelerator::PendingSampleInfo::~PendingSampleInfo() {}
DXVAVideoDecodeAccelerator::DXVAVideoDecodeAccelerator(
- const base::Callback<bool(void)>& make_context_current,
- gfx::GLContext* gl_context)
+ const GetGLContextCallback& get_gl_context_cb,
+ const MakeGLContextCurrentCallback& make_context_current_cb,
+ bool enable_accelerated_vpx_decode)
: client_(NULL),
dev_manager_reset_token_(0),
dx11_dev_manager_reset_token_(0),
@@ -618,14 +904,16 @@ DXVAVideoDecodeAccelerator::DXVAVideoDecodeAccelerator(
pictures_requested_(false),
inputs_before_decode_(0),
sent_drain_message_(false),
- make_context_current_(make_context_current),
+ get_gl_context_cb_(get_gl_context_cb),
+ make_context_current_cb_(make_context_current_cb),
codec_(media::kUnknownVideoCodec),
decoder_thread_("DXVAVideoDecoderThread"),
pending_flush_(false),
use_dx11_(false),
+ use_keyed_mutex_(false),
dx11_video_format_converter_media_type_needs_init_(true),
- gl_context_(gl_context),
using_angle_device_(false),
+ enable_accelerated_vpx_decode_(enable_accelerated_vpx_decode),
weak_this_factory_(this) {
weak_ptr_ = weak_this_factory_.GetWeakPtr();
memset(&input_stream_info_, 0, sizeof(input_stream_info_));
@@ -638,6 +926,11 @@ DXVAVideoDecodeAccelerator::~DXVAVideoDecodeAccelerator() {
bool DXVAVideoDecodeAccelerator::Initialize(const Config& config,
Client* client) {
+ if (get_gl_context_cb_.is_null() || make_context_current_cb_.is_null()) {
+ NOTREACHED() << "GL callbacks are required for this VDA";
+ return false;
+ }
+
if (config.is_encrypted) {
NOTREACHED() << "Encrypted streams are not supported for this VDA";
return false;
@@ -695,6 +988,10 @@ bool DXVAVideoDecodeAccelerator::Initialize(const Config& config,
PLATFORM_FAILURE,
false);
+ RETURN_AND_NOTIFY_ON_FAILURE(gfx::GLFence::IsSupported(),
+ "GL fences are unsupported", PLATFORM_FAILURE,
+ false);
+
State state = GetState();
RETURN_AND_NOTIFY_ON_FAILURE((state == kUninitialized),
"Initialize: invalid state: " << state, ILLEGAL_STATE, false);
@@ -717,6 +1014,10 @@ bool DXVAVideoDecodeAccelerator::Initialize(const Config& config,
"Send MFT_MESSAGE_NOTIFY_START_OF_STREAM notification failed",
PLATFORM_FAILURE, false);
+ config_ = config;
+
+ config_change_detector_.reset(new H264ConfigChangeDetector);
+
SetState(kNormal);
StartDecoderThread();
@@ -883,15 +1184,28 @@ void DXVAVideoDecodeAccelerator::Decode(
const media::BitstreamBuffer& bitstream_buffer) {
DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
+ // SharedMemory will take over the ownership of handle.
+ base::SharedMemory shm(bitstream_buffer.handle(), true);
+
State state = GetState();
RETURN_AND_NOTIFY_ON_FAILURE((state == kNormal || state == kStopped ||
state == kFlushing),
"Invalid state: " << state, ILLEGAL_STATE,);
+ if (bitstream_buffer.id() < 0) {
+ RETURN_AND_NOTIFY_ON_FAILURE(
+ false, "Invalid bitstream_buffer, id: " << bitstream_buffer.id(),
+ INVALID_ARGUMENT, );
+ }
base::win::ScopedComPtr<IMFSample> sample;
- sample.Attach(CreateSampleFromInputBuffer(bitstream_buffer,
- input_stream_info_.cbSize,
- input_stream_info_.cbAlignment));
+ RETURN_AND_NOTIFY_ON_FAILURE(shm.Map(bitstream_buffer.size()),
+ "Failed in base::SharedMemory::Map",
+ PLATFORM_FAILURE, );
+
+ sample.Attach(CreateInputSample(
+ reinterpret_cast<const uint8_t*>(shm.memory()), bitstream_buffer.size(),
+ std::min<uint32_t>(bitstream_buffer.size(), input_stream_info_.cbSize),
+ input_stream_info_.cbAlignment));
RETURN_AND_NOTIFY_ON_FAILURE(sample.get(), "Failed to create input sample",
PLATFORM_FAILURE, );
@@ -919,6 +1233,7 @@ void DXVAVideoDecodeAccelerator::AssignPictureBuffers(
// and mark these buffers as available for use.
for (size_t buffer_index = 0; buffer_index < buffers.size();
++buffer_index) {
+ DCHECK_LE(1u, buffers[buffer_index].texture_ids().size());
linked_ptr<DXVAPictureBuffer> picture_buffer =
DXVAPictureBuffer::Create(*this, buffers[buffer_index], egl_config_);
RETURN_AND_NOTIFY_ON_FAILURE(picture_buffer.get(),
@@ -956,17 +1271,70 @@ void DXVAVideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_buffer_id) {
// us that we can now recycle this picture buffer, so if we were waiting to
// dispose of it we now can.
if (it == output_picture_buffers_.end()) {
- it = stale_output_picture_buffers_.find(picture_buffer_id);
- RETURN_AND_NOTIFY_ON_FAILURE(it != stale_output_picture_buffers_.end(),
- "Invalid picture id: " << picture_buffer_id, INVALID_ARGUMENT,);
- main_thread_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer,
- weak_this_factory_.GetWeakPtr(), picture_buffer_id));
+ if (!stale_output_picture_buffers_.empty()) {
+ it = stale_output_picture_buffers_.find(picture_buffer_id);
+ RETURN_AND_NOTIFY_ON_FAILURE(it != stale_output_picture_buffers_.end(),
+ "Invalid picture id: " << picture_buffer_id, INVALID_ARGUMENT,);
+ main_thread_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer,
+ weak_this_factory_.GetWeakPtr(), picture_buffer_id));
+ }
+ return;
+ }
+
+ if (it->second->available() || it->second->waiting_to_reuse())
+ return;
+
+ if (use_keyed_mutex_ || using_angle_device_) {
+ RETURN_AND_NOTIFY_ON_FAILURE(it->second->ReusePictureBuffer(),
+ "Failed to reuse picture buffer",
+ PLATFORM_FAILURE, );
+
+ ProcessPendingSamples();
+ if (pending_flush_) {
+ decoder_thread_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushInternal,
+ base::Unretained(this)));
+ }
+ } else {
+ RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(),
+ "Failed to make context current",
+ PLATFORM_FAILURE, );
+ it->second->ResetReuseFence();
+
+ WaitForOutputBuffer(picture_buffer_id, 0);
+ }
+}
+
+void DXVAVideoDecodeAccelerator::WaitForOutputBuffer(int32_t picture_buffer_id,
+ int count) {
+ DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
+ OutputBuffers::iterator it = output_picture_buffers_.find(picture_buffer_id);
+ if (it == output_picture_buffers_.end())
+ return;
+
+ DXVAPictureBuffer* picture_buffer = it->second.get();
+
+ DCHECK(!picture_buffer->available());
+ DCHECK(picture_buffer->waiting_to_reuse());
+
+ gfx::GLFence* fence = picture_buffer->reuse_fence();
+ RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(),
+ "Failed to make context current",
+ PLATFORM_FAILURE, );
+ if (count <= kMaxIterationsForANGLEReuseFlush && !fence->HasCompleted()) {
+ main_thread_task_runner_->PostDelayedTask(
+ FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::WaitForOutputBuffer,
+ weak_this_factory_.GetWeakPtr(),
+ picture_buffer_id, count + 1),
+ base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs));
return;
}
+ RETURN_AND_NOTIFY_ON_FAILURE(picture_buffer->ReusePictureBuffer(),
+ "Failed to reuse picture buffer",
+ PLATFORM_FAILURE, );
- it->second->ReusePictureBuffer();
ProcessPendingSamples();
if (pending_flush_) {
decoder_thread_task_runner_->PostTask(
@@ -1046,7 +1414,9 @@ void DXVAVideoDecodeAccelerator::Destroy() {
delete this;
}
-bool DXVAVideoDecodeAccelerator::CanDecodeOnIOThread() {
+bool DXVAVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread(
+ const base::WeakPtr<Client>& decode_client,
+ const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) {
return false;
}
@@ -1057,17 +1427,19 @@ GLenum DXVAVideoDecodeAccelerator::GetSurfaceInternalFormat() const {
// static
media::VideoDecodeAccelerator::SupportedProfiles
DXVAVideoDecodeAccelerator::GetSupportedProfiles() {
+ TRACE_EVENT0("gpu,startup",
+ "DXVAVideoDecodeAccelerator::GetSupportedProfiles");
+
// TODO(henryhsu): Need to ensure the profiles are actually supported.
SupportedProfiles profiles;
for (const auto& supported_profile : kSupportedProfiles) {
+ std::pair<int, int> min_resolution = GetMinResolution(supported_profile);
+ std::pair<int, int> max_resolution = GetMaxResolution(supported_profile);
+
SupportedProfile profile;
profile.profile = supported_profile;
- // Windows Media Foundation H.264 decoding does not support decoding videos
- // with any dimension smaller than 48 pixels:
- // http://msdn.microsoft.com/en-us/library/windows/desktop/dd797815
- profile.min_resolution.SetSize(48, 48);
- // Use 1088 to account for 16x16 macroblocks.
- profile.max_resolution.SetSize(1920, 1088);
+ profile.min_resolution.SetSize(min_resolution.first, min_resolution.second);
+ profile.max_resolution.SetSize(max_resolution.first, max_resolution.second);
profiles.push_back(profile);
}
return profiles;
@@ -1077,17 +1449,224 @@ DXVAVideoDecodeAccelerator::GetSupportedProfiles() {
void DXVAVideoDecodeAccelerator::PreSandboxInitialization() {
::LoadLibrary(L"MFPlat.dll");
::LoadLibrary(L"msmpeg2vdec.dll");
+ ::LoadLibrary(L"mf.dll");
+ ::LoadLibrary(L"dxva2.dll");
if (base::win::GetVersion() > base::win::VERSION_WIN7) {
LoadLibrary(L"msvproc.dll");
} else {
- LoadLibrary(L"dxva2.dll");
#if defined(ENABLE_DX11_FOR_WIN7)
LoadLibrary(L"mshtmlmedia.dll");
#endif
}
}
+// static
+std::pair<int, int> DXVAVideoDecodeAccelerator::GetMinResolution(
+ media::VideoCodecProfile profile) {
+ TRACE_EVENT0("gpu,startup",
+ "DXVAVideoDecodeAccelerator::GetMinResolution");
+ std::pair<int, int> min_resolution;
+ if (profile >= media::H264PROFILE_BASELINE &&
+ profile <= media::H264PROFILE_HIGH) {
+ // Windows Media Foundation H.264 decoding does not support decoding videos
+ // with any dimension smaller than 48 pixels:
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/dd797815
+ min_resolution = std::make_pair(48, 48);
+ } else {
+ // TODO(ananta)
+ // Detect this properly for VP8/VP9 profiles.
+ min_resolution = std::make_pair(16, 16);
+ }
+ return min_resolution;
+}
+
+// static
+std::pair<int, int> DXVAVideoDecodeAccelerator::GetMaxResolution(
+ const media::VideoCodecProfile profile) {
+ TRACE_EVENT0("gpu,startup",
+ "DXVAVideoDecodeAccelerator::GetMaxResolution");
+ std::pair<int, int> max_resolution;
+ if (profile >= media::H264PROFILE_BASELINE &&
+ profile <= media::H264PROFILE_HIGH) {
+ max_resolution = GetMaxH264Resolution();
+ } else {
+ // TODO(ananta)
+ // Detect this properly for VP8/VP9 profiles.
+ max_resolution = std::make_pair(4096, 2160);
+ }
+ return max_resolution;
+}
+
+std::pair<int, int> DXVAVideoDecodeAccelerator::GetMaxH264Resolution() {
+ TRACE_EVENT0("gpu,startup",
+ "DXVAVideoDecodeAccelerator::GetMaxH264Resolution");
+ // The H.264 resolution detection operation is expensive. This static flag
+ // allows us to run the detection once.
+ static bool resolution_detected = false;
+ // Use 1088 to account for 16x16 macroblocks.
+ static std::pair<int, int> max_resolution = std::make_pair(1920, 1088);
+ if (resolution_detected)
+ return max_resolution;
+
+ resolution_detected = true;
+
+ // On Windows 7 the maximum resolution supported by media foundation is
+ // 1920 x 1088.
+ if (base::win::GetVersion() == base::win::VERSION_WIN7)
+ return max_resolution;
+
+ // To detect if a driver supports the desired resolutions, we try and create
+ // a DXVA decoder instance for that resolution and profile. If that succeeds
+ // we assume that the driver supports H/W H.264 decoding for that resolution.
+ HRESULT hr = E_FAIL;
+ base::win::ScopedComPtr<ID3D11Device> device;
+
+ {
+ TRACE_EVENT0("gpu,startup",
+ "GetMaxH264Resolution. QueryDeviceObjectFromANGLE");
+
+ device = QueryDeviceObjectFromANGLE<ID3D11Device>(EGL_D3D11_DEVICE_ANGLE);
+ if (!device.get())
+ return max_resolution;
+ }
+
+ base::win::ScopedComPtr<ID3D11VideoDevice> video_device;
+ hr = device.QueryInterface(IID_ID3D11VideoDevice,
+ video_device.ReceiveVoid());
+ if (FAILED(hr))
+ return max_resolution;
+
+ GUID decoder_guid = {};
+
+ {
+ TRACE_EVENT0("gpu,startup",
+ "GetMaxH264Resolution. H.264 guid search begin");
+ // Enumerate supported video profiles and look for the H264 profile.
+ bool found = false;
+ UINT profile_count = video_device->GetVideoDecoderProfileCount();
+ for (UINT profile_idx = 0; profile_idx < profile_count; profile_idx++) {
+ GUID profile_id = {};
+ hr = video_device->GetVideoDecoderProfile(profile_idx, &profile_id);
+ if (SUCCEEDED(hr) &&
+ (profile_id == DXVA2_ModeH264_E ||
+ profile_id == DXVA2_Intel_ModeH264_E)) {
+ decoder_guid = profile_id;
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ return max_resolution;
+ }
+
+ // Legacy AMD drivers with UVD3 or earlier and some Intel GPU's crash while
+ // creating surfaces larger than 1920 x 1088.
+ if (IsLegacyGPU(device.get()))
+ return max_resolution;
+
+ // We look for the following resolutions in the driver.
+ // TODO(ananta)
+ // Look into whether this list needs to be expanded.
+ static std::pair<int, int> resolution_array[] = {
+ // Use 1088 to account for 16x16 macroblocks.
+ std::make_pair(1920, 1088),
+ std::make_pair(2560, 1440),
+ std::make_pair(3840, 2160),
+ std::make_pair(4096, 2160),
+ std::make_pair(4096, 2304),
+ };
+
+ {
+ TRACE_EVENT0("gpu,startup",
+ "GetMaxH264Resolution. Resolution search begin");
+
+ for (size_t res_idx = 0; res_idx < arraysize(resolution_array);
+ res_idx++) {
+ D3D11_VIDEO_DECODER_DESC desc = {};
+ desc.Guid = decoder_guid;
+ desc.SampleWidth = resolution_array[res_idx].first;
+ desc.SampleHeight = resolution_array[res_idx].second;
+ desc.OutputFormat = DXGI_FORMAT_NV12;
+ UINT config_count = 0;
+ hr = video_device->GetVideoDecoderConfigCount(&desc, &config_count);
+ if (FAILED(hr) || config_count == 0)
+ return max_resolution;
+
+ D3D11_VIDEO_DECODER_CONFIG config = {};
+ hr = video_device->GetVideoDecoderConfig(&desc, 0, &config);
+ if (FAILED(hr))
+ return max_resolution;
+
+ base::win::ScopedComPtr<ID3D11VideoDecoder> video_decoder;
+ hr = video_device->CreateVideoDecoder(&desc, &config,
+ video_decoder.Receive());
+ if (!video_decoder.get())
+ return max_resolution;
+
+ max_resolution = resolution_array[res_idx];
+ }
+ }
+ return max_resolution;
+}
+
+// static
+bool DXVAVideoDecodeAccelerator::IsLegacyGPU(ID3D11Device* device) {
+ static const int kAMDGPUId1 = 0x1002;
+ static const int kAMDGPUId2 = 0x1022;
+ static const int kIntelGPU = 0x8086;
+
+ static bool legacy_gpu = true;
+ // This flag ensures that we determine the GPU type once.
+ static bool legacy_gpu_determined = false;
+
+ if (legacy_gpu_determined)
+ return legacy_gpu;
+
+ legacy_gpu_determined = true;
+
+ base::win::ScopedComPtr<IDXGIDevice> dxgi_device;
+ HRESULT hr = dxgi_device.QueryFrom(device);
+ if (FAILED(hr))
+ return legacy_gpu;
+
+ base::win::ScopedComPtr<IDXGIAdapter> adapter;
+ hr = dxgi_device->GetAdapter(adapter.Receive());
+ if (FAILED(hr))
+ return legacy_gpu;
+
+ DXGI_ADAPTER_DESC adapter_desc = {};
+ hr = adapter->GetDesc(&adapter_desc);
+ if (FAILED(hr))
+ return legacy_gpu;
+
+ // We check if the device is an Intel or an AMD device and whether it is in
+ // the global list defined by the g_AMDUVD3GPUList and g_IntelLegacyGPUList
+ // arrays above. If yes then the device is treated as a legacy device.
+ if ((adapter_desc.VendorId == kAMDGPUId1) ||
+ adapter_desc.VendorId == kAMDGPUId2) {
+ {
+ TRACE_EVENT0("gpu,startup",
+ "DXVAVideoDecodeAccelerator::IsLegacyGPU. AMD check");
+ for (size_t i = 0; i < arraysize(g_AMDUVD3GPUList); i++) {
+ if (adapter_desc.DeviceId == g_AMDUVD3GPUList[i])
+ return legacy_gpu;
+ }
+ }
+ } else if (adapter_desc.VendorId == kIntelGPU) {
+ {
+ TRACE_EVENT0("gpu,startup",
+ "DXVAVideoDecodeAccelerator::IsLegacyGPU. Intel check");
+ for (size_t i = 0; i < arraysize(g_IntelLegacyGPUList); i++) {
+ if (adapter_desc.DeviceId == g_IntelLegacyGPUList[i])
+ return legacy_gpu;
+ }
+ }
+ }
+ legacy_gpu = false;
+ return legacy_gpu;
+}
+
bool DXVAVideoDecodeAccelerator::InitDecoder(media::VideoCodecProfile profile) {
HMODULE decoder_dll = NULL;
@@ -1104,24 +1683,26 @@ bool DXVAVideoDecodeAccelerator::InitDecoder(media::VideoCodecProfile profile) {
"msmpeg2vdec.dll required for decoding is not loaded",
false);
- // Check version of DLL, version 6.7.7140 is blacklisted due to high crash
+ // Check version of DLL, version 6.1.7140 is blacklisted due to high crash
// rates in browsers loading that DLL. If that is the version installed we
// fall back to software decoding. See crbug/403440.
- FileVersionInfo* version_info =
- FileVersionInfo::CreateFileVersionInfoForModule(decoder_dll);
+ scoped_ptr<FileVersionInfo> version_info(
+ FileVersionInfo::CreateFileVersionInfoForModule(decoder_dll));
RETURN_ON_FAILURE(version_info,
"unable to get version of msmpeg2vdec.dll",
false);
base::string16 file_version = version_info->file_version();
RETURN_ON_FAILURE(file_version.find(L"6.1.7140") == base::string16::npos,
- "blacklisted version of msmpeg2vdec.dll 6.7.7140",
+ "blacklisted version of msmpeg2vdec.dll 6.1.7140",
false);
codec_ = media::kCodecH264;
clsid = __uuidof(CMSH264DecoderMFT);
- } else if ((profile == media::VP8PROFILE_ANY ||
- profile == media::VP9PROFILE_ANY) &&
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableAcceleratedVpxDecode)) {
+ } else if (enable_accelerated_vpx_decode_ &&
+ (profile == media::VP8PROFILE_ANY ||
+ profile == media::VP9PROFILE_PROFILE0 ||
+ profile == media::VP9PROFILE_PROFILE1 ||
+ profile == media::VP9PROFILE_PROFILE2 ||
+ profile == media::VP9PROFILE_PROFILE3)) {
int program_files_key = base::DIR_PROGRAM_FILES;
if (base::win::OSInfo::GetInstance()->wow64_status() ==
base::win::OSInfo::WOW64_ENABLED) {
@@ -1230,19 +1811,24 @@ bool DXVAVideoDecodeAccelerator::CheckDecoderDxvaSupport() {
DVLOG(1) << "Failed to set Low latency mode on decoder. Error: " << hr;
}
+ auto gl_context = get_gl_context_cb_.Run();
+ RETURN_ON_FAILURE(gl_context, "Couldn't get GL context", false);
+
// The decoder should use DX11 iff
// 1. The underlying H/W decoder supports it.
// 2. We have a pointer to the MFCreateDXGIDeviceManager function needed for
// this. This should always be true for Windows 8+.
// 3. ANGLE is using DX11.
- DCHECK(gl_context_);
if (create_dxgi_device_manager_ &&
- (gl_context_->GetGLRenderer().find("Direct3D11") !=
- std::string::npos)) {
+ (gl_context->GetGLRenderer().find("Direct3D11") != std::string::npos)) {
UINT32 dx11_aware = 0;
attributes->GetUINT32(MF_SA_D3D11_AWARE, &dx11_aware);
use_dx11_ = !!dx11_aware;
}
+
+ use_keyed_mutex_ =
+ use_dx11_ && gfx::GLSurfaceEGL::HasEGLExtension("EGL_ANGLE_keyed_mutex");
+
return true;
}
@@ -1436,8 +2022,9 @@ void DXVAVideoDecodeAccelerator::ProcessPendingSamples() {
if (!output_picture_buffers_.size())
return;
- RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_.Run(),
- "Failed to make context current", PLATFORM_FAILURE,);
+ RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(),
+ "Failed to make context current",
+ PLATFORM_FAILURE, );
OutputBuffers::iterator index;
@@ -1449,7 +2036,6 @@ void DXVAVideoDecodeAccelerator::ProcessPendingSamples() {
PendingSampleInfo* pending_sample = NULL;
{
base::AutoLock lock(decoder_lock_);
-
PendingSampleInfo& sample_info = pending_output_samples_.front();
if (sample_info.picture_buffer_id != -1)
continue;
@@ -1533,13 +2119,22 @@ void DXVAVideoDecodeAccelerator::Invalidate() {
if (GetState() == kUninitialized)
return;
+ // Best effort to make the GL context current.
+ make_context_current_cb_.Run();
+
decoder_thread_.Stop();
weak_this_factory_.InvalidateWeakPtrs();
output_picture_buffers_.clear();
stale_output_picture_buffers_.clear();
pending_output_samples_.clear();
- pending_input_buffers_.clear();
+ // We want to continue processing pending input after detecting a config
+ // change.
+ if (GetState() != kConfigChange)
+ pending_input_buffers_.clear();
decoder_.Release();
+ pictures_requested_ = false;
+
+ config_change_detector_.reset();
if (use_dx11_) {
if (video_format_converter_mft_.get()) {
@@ -1552,6 +2147,7 @@ void DXVAVideoDecodeAccelerator::Invalidate() {
d3d11_device_manager_.Release();
d3d11_query_.Release();
dx11_video_format_converter_media_type_needs_init_ = true;
+ multi_threaded_.Release();
} else {
d3d9_.Release();
d3d9_device_ex_.Release();
@@ -1591,10 +2187,8 @@ void DXVAVideoDecodeAccelerator::RequestPictureBuffers(int width, int height) {
DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
// This task could execute after the decoder has been torn down.
if (GetState() != kUninitialized && client_) {
- client_->ProvidePictureBuffers(
- kNumPictureBuffers,
- gfx::Size(width, height),
- GL_TEXTURE_2D);
+ client_->ProvidePictureBuffers(kNumPictureBuffers, 1,
+ gfx::Size(width, height), GL_TEXTURE_2D);
}
}
@@ -1706,13 +2300,31 @@ void DXVAVideoDecodeAccelerator::DecodeInternal(
return;
}
+ // Check if the resolution, bit rate, etc changed in the stream. If yes we
+ // reinitialize the decoder to ensure that the stream decodes correctly.
+ bool config_changed = false;
+
+ HRESULT hr = CheckConfigChanged(sample.get(), &config_changed);
+ RETURN_AND_NOTIFY_ON_HR_FAILURE(hr, "Failed to check video stream config",
+ PLATFORM_FAILURE,);
+
+ if (config_changed) {
+ pending_input_buffers_.push_back(sample);
+ main_thread_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&DXVAVideoDecodeAccelerator::ConfigChanged,
+ weak_this_factory_.GetWeakPtr(),
+ config_));
+ return;
+ }
+
if (!inputs_before_decode_) {
TRACE_EVENT_ASYNC_BEGIN0("gpu", "DXVAVideoDecodeAccelerator.Decoding",
this);
}
inputs_before_decode_++;
- HRESULT hr = decoder_->ProcessInput(0, sample.get(), 0);
+ hr = decoder_->ProcessInput(0, sample.get(), 0);
// As per msdn if the decoder returns MF_E_NOTACCEPTING then it means that it
// has enough data to produce one or more output samples. In this case the
// recommended options are to
@@ -1790,7 +2402,7 @@ void DXVAVideoDecodeAccelerator::HandleResolutionChanged(int width,
main_thread_task_runner_->PostTask(
FROM_HERE,
base::Bind(&DXVAVideoDecodeAccelerator::DismissStaleBuffers,
- weak_this_factory_.GetWeakPtr()));
+ weak_this_factory_.GetWeakPtr(), false));
main_thread_task_runner_->PostTask(
FROM_HERE,
@@ -1800,13 +2412,17 @@ void DXVAVideoDecodeAccelerator::HandleResolutionChanged(int width,
height));
}
-void DXVAVideoDecodeAccelerator::DismissStaleBuffers() {
+void DXVAVideoDecodeAccelerator::DismissStaleBuffers(bool force) {
+ RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(),
+ "Failed to make context current",
+ PLATFORM_FAILURE, );
+
OutputBuffers::iterator index;
for (index = output_picture_buffers_.begin();
index != output_picture_buffers_.end();
++index) {
- if (index->second->available()) {
+ if (force || index->second->available()) {
DVLOG(1) << "Dismissing picture id: " << index->second->id();
client_->DismissPictureBuffer(index->second->id());
} else {
@@ -1821,6 +2437,10 @@ void DXVAVideoDecodeAccelerator::DismissStaleBuffers() {
void DXVAVideoDecodeAccelerator::DeferredDismissStaleBuffer(
int32_t picture_buffer_id) {
+ RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(),
+ "Failed to make context current",
+ PLATFORM_FAILURE, );
+
OutputBuffers::iterator it = stale_output_picture_buffers_.find(
picture_buffer_id);
DCHECK(it != stale_output_picture_buffers_.end());
@@ -1935,13 +2555,15 @@ void DXVAVideoDecodeAccelerator::CopySurfaceComplete(
if (picture_buffer->available())
return;
- RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_.Run(),
- "Failed to make context current", PLATFORM_FAILURE,);
+ RETURN_AND_NOTIFY_ON_FAILURE(make_context_current_cb_.Run(),
+ "Failed to make context current",
+ PLATFORM_FAILURE, );
DCHECK(!output_picture_buffers_.empty());
- picture_buffer->CopySurfaceComplete(src_surface,
- dest_surface);
+ bool result = picture_buffer->CopySurfaceComplete(src_surface, dest_surface);
+ RETURN_AND_NOTIFY_ON_FAILURE(result, "Failed to complete copying surface",
+ PLATFORM_FAILURE, );
NotifyPictureReady(picture_buffer->id(), input_buffer_id);
@@ -1964,11 +2586,14 @@ void DXVAVideoDecodeAccelerator::CopySurfaceComplete(
base::Unretained(this)));
}
-void DXVAVideoDecodeAccelerator::CopyTexture(ID3D11Texture2D* src_texture,
- ID3D11Texture2D* dest_texture,
- IMFSample* video_frame,
- int picture_buffer_id,
- int input_buffer_id) {
+void DXVAVideoDecodeAccelerator::CopyTexture(
+ ID3D11Texture2D* src_texture,
+ ID3D11Texture2D* dest_texture,
+ base::win::ScopedComPtr<IDXGIKeyedMutex> dest_keyed_mutex,
+ uint64_t keyed_mutex_value,
+ IMFSample* video_frame,
+ int picture_buffer_id,
+ int input_buffer_id) {
HRESULT hr = E_FAIL;
DCHECK(use_dx11_);
@@ -2005,14 +2630,11 @@ void DXVAVideoDecodeAccelerator::CopyTexture(ID3D11Texture2D* src_texture,
}
decoder_thread_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&DXVAVideoDecodeAccelerator::CopyTexture,
- base::Unretained(this),
- src_texture,
- dest_texture,
- input_sample_for_conversion.Detach(),
- picture_buffer_id,
- input_buffer_id));
+ FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopyTexture,
+ base::Unretained(this), src_texture, dest_texture,
+ dest_keyed_mutex, keyed_mutex_value,
+ input_sample_for_conversion.Detach(),
+ picture_buffer_id, input_buffer_id));
return;
}
@@ -2023,6 +2645,13 @@ void DXVAVideoDecodeAccelerator::CopyTexture(ID3D11Texture2D* src_texture,
DCHECK(video_format_converter_mft_.get());
+ if (dest_keyed_mutex) {
+ HRESULT hr =
+ dest_keyed_mutex->AcquireSync(keyed_mutex_value, kAcquireSyncWaitMs);
+ RETURN_AND_NOTIFY_ON_FAILURE(
+ hr == S_OK, "D3D11 failed to acquire keyed mutex for texture.",
+ PLATFORM_FAILURE, );
+ }
// The video processor MFT requires output samples to be allocated by the
// caller. We create a sample with a buffer backed with the ID3D11Texture2D
// interface exposed by ANGLE. This works nicely as this ensures that the
@@ -2077,18 +2706,27 @@ void DXVAVideoDecodeAccelerator::CopyTexture(ID3D11Texture2D* src_texture,
"Failed to convert output sample format.", PLATFORM_FAILURE,);
}
- d3d11_device_context_->Flush();
- d3d11_device_context_->End(d3d11_query_.get());
+ if (dest_keyed_mutex) {
+ HRESULT hr = dest_keyed_mutex->ReleaseSync(keyed_mutex_value + 1);
+ RETURN_AND_NOTIFY_ON_FAILURE(hr == S_OK, "Failed to release keyed mutex.",
+ PLATFORM_FAILURE, );
- decoder_thread_task_runner_->PostDelayedTask(
- FROM_HERE,
- base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder,
- base::Unretained(this), 0,
- reinterpret_cast<IDirect3DSurface9*>(NULL),
- reinterpret_cast<IDirect3DSurface9*>(NULL),
- picture_buffer_id, input_buffer_id),
- base::TimeDelta::FromMilliseconds(
- kFlushDecoderSurfaceTimeoutMs));
+ main_thread_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::CopySurfaceComplete,
+ weak_this_factory_.GetWeakPtr(), nullptr, nullptr,
+ picture_buffer_id, input_buffer_id));
+ } else {
+ d3d11_device_context_->Flush();
+ d3d11_device_context_->End(d3d11_query_.get());
+
+ decoder_thread_task_runner_->PostDelayedTask(
+ FROM_HERE, base::Bind(&DXVAVideoDecodeAccelerator::FlushDecoder,
+ base::Unretained(this), 0,
+ reinterpret_cast<IDirect3DSurface9*>(NULL),
+ reinterpret_cast<IDirect3DSurface9*>(NULL),
+ picture_buffer_id, input_buffer_id),
+ base::TimeDelta::FromMilliseconds(kFlushDecoderSurfaceTimeoutMs));
+ }
}
void DXVAVideoDecodeAccelerator::FlushDecoder(
@@ -2290,12 +2928,6 @@ bool DXVAVideoDecodeAccelerator::SetTransformOutputType(
RETURN_ON_HR_FAILURE(hr, "Failed to set media type attributes", false);
}
hr = transform->SetOutputType(0, media_type.get(), 0); // No flags
- if (FAILED(hr)) {
- base::debug::Alias(&hr);
- // TODO(ananta)
- // Remove this CHECK when this stabilizes in the field.
- CHECK(false);
- }
RETURN_ON_HR_FAILURE(hr, "Failed to set output type", false);
return true;
}
@@ -2304,4 +2936,39 @@ bool DXVAVideoDecodeAccelerator::SetTransformOutputType(
return false;
}
+HRESULT DXVAVideoDecodeAccelerator::CheckConfigChanged(
+ IMFSample* sample, bool* config_changed) {
+ if (codec_ != media::kCodecH264)
+ return S_FALSE;
+
+ base::win::ScopedComPtr<IMFMediaBuffer> buffer;
+ HRESULT hr = sample->GetBufferByIndex(0, buffer.Receive());
+ RETURN_ON_HR_FAILURE(hr, "Failed to get buffer from input sample", hr);
+
+ MediaBufferScopedPointer scoped_media_buffer(buffer.get());
+
+ if (!config_change_detector_->DetectConfig(
+ scoped_media_buffer.get(),
+ scoped_media_buffer.current_length())) {
+ RETURN_ON_HR_FAILURE(E_FAIL, "Failed to detect H.264 stream config",
+ E_FAIL);
+ }
+ *config_changed = config_change_detector_->config_changed();
+ return S_OK;
+}
+
+void DXVAVideoDecodeAccelerator::ConfigChanged(
+ const Config& config) {
+ DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
+
+ SetState(kConfigChange);
+ DismissStaleBuffers(true);
+ Invalidate();
+ Initialize(config_, client_);
+ decoder_thread_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&DXVAVideoDecodeAccelerator::DecodePendingInputBuffers,
+ base::Unretained(this)));
+}
+
} // namespace content
diff --git a/chromium/content/common/gpu/media/dxva_video_decode_accelerator_win.h b/chromium/content/common/gpu/media/dxva_video_decode_accelerator_win.h
index d3aeda62c9b..01c15e62430 100644
--- a/chromium/content/common/gpu/media/dxva_video_decode_accelerator_win.h
+++ b/chromium/content/common/gpu/media/dxva_video_decode_accelerator_win.h
@@ -7,6 +7,7 @@
#include <d3d11.h>
#include <d3d9.h>
+#include <initguid.h>
#include <stdint.h>
// Work around bug in this header by disabling the relevant warning for it.
// https://connect.microsoft.com/VisualStudio/feedback/details/911260/dxva2api-h-in-win8-sdk-triggers-c4201-with-w4
@@ -29,6 +30,8 @@
#include "base/threading/thread.h"
#include "base/win/scoped_comptr.h"
#include "content/common/content_export.h"
+#include "content/common/gpu/media/gpu_video_decode_accelerator_helpers.h"
+#include "media/filters/h264_parser.h"
#include "media/video/video_decode_accelerator.h"
interface IMFSample;
@@ -44,6 +47,43 @@ typedef HRESULT (WINAPI* CreateDXGIDeviceManager)(
namespace content {
+// Provides functionality to detect H.264 stream configuration changes.
+// TODO(ananta)
+// Move this to a common place so that all VDA's can use this.
+class H264ConfigChangeDetector {
+ public:
+ H264ConfigChangeDetector();
+ ~H264ConfigChangeDetector();
+
+ // Detects stream configuration changes.
+ // Returns false on failure.
+ bool DetectConfig(const uint8_t* stream, unsigned int size);
+
+ bool config_changed() const {
+ return config_changed_;
+ }
+
+ private:
+ // These fields are used to track the SPS/PPS in the H.264 bitstream and
+ // are eventually compared against the SPS/PPS in the bitstream to detect
+ // a change.
+ int last_sps_id_;
+ std::vector<uint8_t> last_sps_;
+ int last_pps_id_;
+ std::vector<uint8_t> last_pps_;
+ // Set to true if we detect a stream configuration change.
+ bool config_changed_;
+ // We want to indicate configuration changes only after we see IDR slices.
+ // This flag tracks that we potentially have a configuration change which
+ // we want to honor after we see an IDR slice.
+ bool pending_config_changed_;
+
+ scoped_ptr<media::H264Parser> parser_;
+
+ DISALLOW_COPY_AND_ASSIGN(H264ConfigChangeDetector);
+};
+
+
// Class to provide a DXVA 2.0 based accelerator using the Microsoft Media
// foundation APIs via the VideoDecodeAccelerator interface.
// This class lives on a single thread and DCHECKs that it is never accessed
@@ -57,12 +97,14 @@ class CONTENT_EXPORT DXVAVideoDecodeAccelerator
kResetting, // upon received Reset(), before ResetDone()
kStopped, // upon output EOS received.
kFlushing, // upon flush request received.
+ kConfigChange, // stream configuration change detected.
};
// Does not take ownership of |client| which must outlive |*this|.
- explicit DXVAVideoDecodeAccelerator(
- const base::Callback<bool(void)>& make_context_current,
- gfx::GLContext* gl_context);
+ DXVAVideoDecodeAccelerator(
+ const GetGLContextCallback& get_gl_context_cb,
+ const MakeGLContextCurrentCallback& make_context_current_cb,
+ bool enable_accelerated_vpx_decode);
~DXVAVideoDecodeAccelerator() override;
// media::VideoDecodeAccelerator implementation.
@@ -74,7 +116,10 @@ class CONTENT_EXPORT DXVAVideoDecodeAccelerator
void Flush() override;
void Reset() override;
void Destroy() override;
- bool CanDecodeOnIOThread() override;
+ bool TryToSetupDecodeOnSeparateThread(
+ const base::WeakPtr<Client>& decode_client,
+ const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner)
+ override;
GLenum GetSurfaceInternalFormat() const override;
static media::VideoDecodeAccelerator::SupportedProfiles
@@ -87,6 +132,23 @@ class CONTENT_EXPORT DXVAVideoDecodeAccelerator
typedef void* EGLConfig;
typedef void* EGLSurface;
+ // Returns the minimum resolution for the |profile| passed in.
+ static std::pair<int, int> GetMinResolution(
+ const media::VideoCodecProfile profile);
+
+ // Returns the maximum resolution for the |profile| passed in.
+ static std::pair<int, int> GetMaxResolution(
+ const media::VideoCodecProfile profile);
+
+ // Returns the maximum resolution for H264 video.
+ static std::pair<int, int> GetMaxH264Resolution();
+
+ // Certain AMD GPU drivers like R600, R700, Evergreen and Cayman and
+ // some second generation Intel GPU drivers crash if we create a video
+ // device with a resolution higher then 1920 x 1088. This function
+ // checks if the GPU is in this list and if yes returns true.
+ static bool IsLegacyGPU(ID3D11Device* device);
+
// Creates and initializes an instance of the D3D device and the
// corresponding device manager. The device manager instance is eventually
// passed to the IMFTransform interface implemented by the decoder.
@@ -178,7 +240,7 @@ class CONTENT_EXPORT DXVAVideoDecodeAccelerator
typedef std::map<int32_t, linked_ptr<DXVAPictureBuffer>> OutputBuffers;
// Tells the client to dismiss the stale picture buffers passed in.
- void DismissStaleBuffers();
+ void DismissStaleBuffers(bool force);
// Called after the client indicates we can recycle a stale picture buffer.
void DeferredDismissStaleBuffer(int32_t picture_buffer_id);
@@ -191,10 +253,6 @@ class CONTENT_EXPORT DXVAVideoDecodeAccelerator
// the decoder thread. Thread safe.
State GetState();
- // Worker function for the Decoder Reset functionality. Executes on the
- // decoder thread and queues tasks on the main thread as needed.
- void ResetHelper();
-
// Starts the thread used for decoding.
void StartDecoderThread();
@@ -222,6 +280,8 @@ class CONTENT_EXPORT DXVAVideoDecodeAccelerator
// is the sample containing the frame to be copied.
void CopyTexture(ID3D11Texture2D* src_texture,
ID3D11Texture2D* dest_texture,
+ base::win::ScopedComPtr<IDXGIKeyedMutex> dest_keyed_mutex,
+ uint64_t keyed_mutex_value,
IMFSample* video_frame,
int picture_buffer_id,
int input_buffer_id);
@@ -235,6 +295,10 @@ class CONTENT_EXPORT DXVAVideoDecodeAccelerator
int picture_buffer_id,
int input_buffer_id);
+ // Polls to wait for GPU commands to be finished on the picture buffer
+ // before reusing it.
+ void WaitForOutputBuffer(int32_t picture_buffer_id, int count);
+
// Initializes the DX11 Video format converter media types.
// Returns true on success.
bool InitializeDX11VideoFormatConverterMediaType(int width, int height);
@@ -257,6 +321,18 @@ class CONTENT_EXPORT DXVAVideoDecodeAccelerator
int width,
int height);
+ // Checks if the resolution, bitrate etc of the stream changed. We do this
+ // by keeping track of the SPS/PPS frames and if they change we assume
+ // that the configuration changed.
+ // Returns S_OK or S_FALSE on succcess.
+ // The |config_changed| parameter is set to true if we detect a change in the
+ // stream.
+ HRESULT CheckConfigChanged(IMFSample* sample, bool* config_changed);
+
+ // Called when we detect a stream configuration change. We reinitialize the
+ // decoder here.
+ void ConfigChanged(const Config& config);
+
// To expose client callbacks from VideoDecodeAccelerator.
media::VideoDecodeAccelerator::Client* client_;
@@ -340,8 +416,10 @@ class CONTENT_EXPORT DXVAVideoDecodeAccelerator
typedef std::list<base::win::ScopedComPtr<IMFSample>> PendingInputs;
PendingInputs pending_input_buffers_;
+ // Callback to get current GLContext.
+ GetGLContextCallback get_gl_context_cb_;
// Callback to set the correct gl context.
- base::Callback<bool(void)> make_context_current_;
+ MakeGLContextCurrentCallback make_context_current_cb_;
// Which codec we are decoding with hardware acceleration.
media::VideoCodec codec_;
@@ -373,16 +451,30 @@ class CONTENT_EXPORT DXVAVideoDecodeAccelerator
// H/W decoding.
bool use_dx11_;
+ // True if we should use DXGI keyed mutexes to synchronize between the two
+ // contexts.
+ bool use_keyed_mutex_;
+
// Set to true if the DX11 video format converter input media types need to
// be initialized. Defaults to true.
bool dx11_video_format_converter_media_type_needs_init_;
- // The GLContext to be used by the decoder.
- scoped_refptr<gfx::GLContext> gl_context_;
-
// Set to true if we are sharing ANGLE's device.
bool using_angle_device_;
+ // Enables experimental hardware acceleration for VP8/VP9 video decoding.
+ const bool enable_accelerated_vpx_decode_;
+
+ // The media foundation H.264 decoder has problems handling changes like
+ // resolution change, bitrate change etc. If we reinitialize the decoder
+ // when these changes occur then, the decoder works fine. The
+ // H264ConfigChangeDetector class provides functionality to check if the
+ // stream configuration changed.
+ scoped_ptr<H264ConfigChangeDetector> config_change_detector_;
+
+ // Contains the initialization parameters for the video.
+ Config config_;
+
// WeakPtrFactory for posting tasks back to |this|.
base::WeakPtrFactory<DXVAVideoDecodeAccelerator> weak_this_factory_;
diff --git a/chromium/content/common/gpu/media/fake_video_decode_accelerator.cc b/chromium/content/common/gpu/media/fake_video_decode_accelerator.cc
index 7524dd18ebf..01ac07dcd3b 100644
--- a/chromium/content/common/gpu/media/fake_video_decode_accelerator.cc
+++ b/chromium/content/common/gpu/media/fake_video_decode_accelerator.cc
@@ -29,17 +29,14 @@ static const unsigned int kNumBuffers = media::limits::kMaxVideoFrames +
(media::limits::kMaxVideoFrames & 1u);
FakeVideoDecodeAccelerator::FakeVideoDecodeAccelerator(
- gfx::GLContext* gl,
- gfx::Size size,
- const base::Callback<bool(void)>& make_context_current)
+ const gfx::Size& size,
+ const MakeGLContextCurrentCallback& make_context_current_cb)
: child_task_runner_(base::ThreadTaskRunnerHandle::Get()),
client_(NULL),
- make_context_current_(make_context_current),
- gl_(gl),
+ make_context_current_cb_(make_context_current_cb),
frame_buffer_size_(size),
flushing_(false),
- weak_this_factory_(this) {
-}
+ weak_this_factory_(this) {}
FakeVideoDecodeAccelerator::~FakeVideoDecodeAccelerator() {
}
@@ -59,14 +56,23 @@ bool FakeVideoDecodeAccelerator::Initialize(const Config& config,
// V4L2VideoDecodeAccelerator waits until first decode call to ask for buffers
// This class asks for it on initialization instead.
client_ = client;
- client_->ProvidePictureBuffers(kNumBuffers,
- frame_buffer_size_,
+ client_->ProvidePictureBuffers(kNumBuffers, 1, frame_buffer_size_,
kDefaultTextureTarget);
return true;
}
void FakeVideoDecodeAccelerator::Decode(
const media::BitstreamBuffer& bitstream_buffer) {
+ // We won't really read from the bitstream_buffer, close the handle.
+ if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle()))
+ base::SharedMemory::CloseHandle(bitstream_buffer.handle());
+
+ if (bitstream_buffer.id() < 0) {
+ LOG(ERROR) << "Invalid bitstream: id=" << bitstream_buffer.id();
+ client_->NotifyError(INVALID_ARGUMENT);
+ return;
+ }
+
int bitstream_buffer_id = bitstream_buffer.id();
queued_bitstream_ids_.push(bitstream_buffer_id);
child_task_runner_->PostTask(
@@ -93,12 +99,13 @@ void FakeVideoDecodeAccelerator::AssignPictureBuffers(
memset(black_data.get(),
0,
frame_buffer_size_.width() * frame_buffer_size_.height() * 4);
- if (!make_context_current_.Run()) {
+ if (!make_context_current_cb_.Run()) {
LOG(ERROR) << "ReusePictureBuffer(): could not make context current";
return;
}
for (size_t index = 0; index < buffers.size(); ++index) {
- glBindTexture(GL_TEXTURE_2D, buffers[index].texture_id());
+ DCHECK_LE(1u, buffers[index].texture_ids().size());
+ glBindTexture(GL_TEXTURE_2D, buffers[index].texture_ids()[0]);
// Every other frame white and the rest black.
uint8_t* data = index % 2 ? white_data.get() : black_data.get();
glTexImage2D(GL_TEXTURE_2D,
@@ -152,8 +159,10 @@ void FakeVideoDecodeAccelerator::Destroy() {
delete this;
}
-bool FakeVideoDecodeAccelerator::CanDecodeOnIOThread() {
- return true;
+bool FakeVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread(
+ const base::WeakPtr<Client>& decode_client,
+ const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) {
+ return false;
}
void FakeVideoDecodeAccelerator::DoPictureReady() {
diff --git a/chromium/content/common/gpu/media/fake_video_decode_accelerator.h b/chromium/content/common/gpu/media/fake_video_decode_accelerator.h
index 7dcbfda2e77..10d47822b45 100644
--- a/chromium/content/common/gpu/media/fake_video_decode_accelerator.h
+++ b/chromium/content/common/gpu/media/fake_video_decode_accelerator.h
@@ -13,6 +13,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
+#include "content/common/gpu/media/gpu_video_decode_accelerator_helpers.h"
#include "media/video/video_decode_accelerator.h"
#include "ui/gfx/geometry/size_f.h"
#include "ui/gl/gl_context.h"
@@ -23,9 +24,8 @@ class CONTENT_EXPORT FakeVideoDecodeAccelerator
: public media::VideoDecodeAccelerator {
public:
FakeVideoDecodeAccelerator(
- gfx::GLContext* gl,
- gfx::Size size,
- const base::Callback<bool(void)>& make_context_current);
+ const gfx::Size& size,
+ const MakeGLContextCurrentCallback& make_context_current_cb);
~FakeVideoDecodeAccelerator() override;
bool Initialize(const Config& config, Client* client) override;
@@ -36,7 +36,10 @@ class CONTENT_EXPORT FakeVideoDecodeAccelerator
void Flush() override;
void Reset() override;
void Destroy() override;
- bool CanDecodeOnIOThread() override;
+ bool TryToSetupDecodeOnSeparateThread(
+ const base::WeakPtr<Client>& decode_client,
+ const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner)
+ override;
private:
void DoPictureReady();
@@ -49,8 +52,7 @@ class CONTENT_EXPORT FakeVideoDecodeAccelerator
Client* client_;
// Make our context current before running any GL entry points.
- base::Callback<bool(void)> make_context_current_;
- gfx::GLContext* gl_;
+ MakeGLContextCurrentCallback make_context_current_cb_;
// Output picture size.
gfx::Size frame_buffer_size_;
diff --git a/chromium/content/common/gpu/media/gpu_arc_video_service.cc b/chromium/content/common/gpu/media/gpu_arc_video_service.cc
deleted file mode 100644
index 91d36980ad1..00000000000
--- a/chromium/content/common/gpu/media/gpu_arc_video_service.cc
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/media/gpu_arc_video_service.h"
-
-#include "base/logging.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "ipc/ipc_listener.h"
-#include "ipc/ipc_message_macros.h"
-#include "ipc/ipc_sync_channel.h"
-
-namespace content {
-
-// TODO(kcwu) implement ArcVideoAccelerator::Client.
-class GpuArcVideoService::AcceleratorStub : public IPC::Listener,
- public IPC::Sender {
- public:
- // |owner| outlives AcceleratorStub.
- explicit AcceleratorStub(GpuArcVideoService* owner) : owner_(owner) {}
-
- ~AcceleratorStub() override {
- DCHECK(thread_checker_.CalledOnValidThread());
- channel_->Close();
- }
-
- IPC::ChannelHandle CreateChannel(
- base::WaitableEvent* shutdown_event,
- const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) {
- IPC::ChannelHandle handle =
- IPC::Channel::GenerateVerifiedChannelID("arc-video");
- channel_ = IPC::SyncChannel::Create(handle, IPC::Channel::MODE_SERVER, this,
- io_task_runner, false, shutdown_event);
- base::ScopedFD client_fd = channel_->TakeClientFileDescriptor();
- DCHECK(client_fd.is_valid());
- handle.socket = base::FileDescriptor(std::move(client_fd));
- return handle;
- }
-
- // IPC::Sender implementation:
- bool Send(IPC::Message* msg) override {
- DCHECK(msg);
- return channel_->Send(msg);
- }
-
- // IPC::Listener implementation:
- void OnChannelError() override {
- DCHECK(thread_checker_.CalledOnValidThread());
- // RemoveClient will delete |this|.
- owner_->RemoveClient(this);
- }
-
- // IPC::Listener implementation:
- bool OnMessageReceived(const IPC::Message& msg) override {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- // TODO(kcwu) Add handlers here.
- return false;
- }
-
- private:
- base::ThreadChecker thread_checker_;
- GpuArcVideoService* const owner_;
- scoped_ptr<IPC::SyncChannel> channel_;
-};
-
-GpuArcVideoService::GpuArcVideoService(
- base::WaitableEvent* shutdown_event,
- const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
- : shutdown_event_(shutdown_event), io_task_runner_(io_task_runner) {}
-
-GpuArcVideoService::~GpuArcVideoService() {}
-
-void GpuArcVideoService::CreateChannel(const CreateChannelCallback& callback) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- scoped_ptr<AcceleratorStub> stub(new AcceleratorStub(this));
-
- IPC::ChannelHandle handle =
- stub->CreateChannel(shutdown_event_, io_task_runner_);
- accelerator_stubs_[stub.get()] = std::move(stub);
-
- callback.Run(handle);
-}
-
-void GpuArcVideoService::RemoveClient(AcceleratorStub* stub) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- accelerator_stubs_.erase(stub);
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/media/gpu_arc_video_service.h b/chromium/content/common/gpu/media/gpu_arc_video_service.h
deleted file mode 100644
index 131150c9f94..00000000000
--- a/chromium/content/common/gpu/media/gpu_arc_video_service.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_MEDIA_GPU_ARC_VIDEO_SERVICE_H_
-#define CONTENT_COMMON_GPU_MEDIA_GPU_ARC_VIDEO_SERVICE_H_
-
-#include <map>
-
-#include "base/callback.h"
-#include "base/threading/thread_checker.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-class WaitableEvent;
-}
-
-namespace IPC {
-struct ChannelHandle;
-}
-
-namespace content {
-
-// GpuArcVideoService manages life-cycle and IPC message translation for
-// ArcVideoAccelerator.
-//
-// For each creation request from GpuChannelManager, GpuArcVideoService will
-// create a new IPC channel.
-class GpuArcVideoService {
- public:
- class AcceleratorStub;
- using CreateChannelCallback = base::Callback<void(const IPC::ChannelHandle&)>;
-
- // |shutdown_event| should signal an event when this process is about to be
- // shut down in order to notify our new IPC channel to terminate.
- GpuArcVideoService(
- base::WaitableEvent* shutdown_event,
- const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
-
- // Upon deletion, all ArcVideoAccelerator will be deleted and the associated
- // IPC channels are closed.
- ~GpuArcVideoService();
-
- // Creates a new accelerator stub. The creation result will be sent back via
- // |callback|.
- void CreateChannel(const CreateChannelCallback& callback);
-
- // Removes the reference of |stub| (and trigger deletion) from this class.
- void RemoveClient(AcceleratorStub* stub);
-
- private:
- base::ThreadChecker thread_checker_;
-
- // Shutdown event of GPU process.
- base::WaitableEvent* shutdown_event_;
-
- // GPU io thread task runner.
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
-
- // Bookkeeping all accelerator stubs.
- std::map<AcceleratorStub*, scoped_ptr<AcceleratorStub>> accelerator_stubs_;
-
- DISALLOW_COPY_AND_ASSIGN(GpuArcVideoService);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_MEDIA_GPU_ARC_VIDEO_SERVICE_H_
diff --git a/chromium/content/common/gpu/media/gpu_jpeg_decode_accelerator.cc b/chromium/content/common/gpu/media/gpu_jpeg_decode_accelerator.cc
index 7408e46d927..3e256073e84 100644
--- a/chromium/content/common/gpu/media/gpu_jpeg_decode_accelerator.cc
+++ b/chromium/content/common/gpu/media/gpu_jpeg_decode_accelerator.cc
@@ -13,13 +13,14 @@
#include "base/memory/shared_memory.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
+#include "base/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
-#include "content/common/gpu/gpu_channel.h"
-#include "content/common/gpu/gpu_messages.h"
+#include "gpu/ipc/service/gpu_channel.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/message_filter.h"
#include "media/filters/jpeg_parser.h"
+#include "media/gpu/ipc/common/media_messages.h"
#include "ui/gfx/geometry/size.h"
#if defined(OS_CHROMEOS)
@@ -41,12 +42,6 @@ void DecodeFinished(scoped_ptr<base::SharedMemory> shm) {
}
bool VerifyDecodeParams(const AcceleratedJpegDecoderMsg_Decode_Params& params) {
- if (params.input_buffer_id < 0) {
- LOG(ERROR) << "BitstreamBuffer id " << params.input_buffer_id
- << " out of range";
- return false;
- }
-
const int kJpegMaxDimension = UINT16_MAX;
if (params.coded_size.IsEmpty() ||
params.coded_size.width() > kJpegMaxDimension ||
@@ -55,11 +50,6 @@ bool VerifyDecodeParams(const AcceleratedJpegDecoderMsg_Decode_Params& params) {
return false;
}
- if (!base::SharedMemory::IsHandleValid(params.input_buffer_handle)) {
- LOG(ERROR) << "invalid input_buffer_handle";
- return false;
- }
-
if (!base::SharedMemory::IsHandleValid(params.output_video_frame_handle)) {
LOG(ERROR) << "invalid output_video_frame_handle";
return false;
@@ -163,13 +153,12 @@ class GpuJpegDecodeAccelerator::MessageFilter : public IPC::MessageFilter {
void AddClientOnIOThread(int32_t route_id,
Client* client,
- IPC::Message* reply_msg) {
+ base::Callback<void(bool)> response) {
DCHECK(io_task_runner_->BelongsToCurrentThread());
DCHECK(client_map_.count(route_id) == 0);
client_map_[route_id] = client;
- GpuMsg_CreateJpegDecoder::WriteReplyParams(reply_msg, true);
- SendOnIOThread(reply_msg);
+ response.Run(true);
}
void OnDestroyOnIOThread(const int32_t* route_id) {
@@ -208,34 +197,28 @@ class GpuJpegDecodeAccelerator::MessageFilter : public IPC::MessageFilter {
if (!VerifyDecodeParams(params)) {
NotifyDecodeStatusOnIOThread(
- *route_id, params.input_buffer_id,
+ *route_id, params.input_buffer.id(),
media::JpegDecodeAccelerator::INVALID_ARGUMENT);
- if (base::SharedMemory::IsHandleValid(params.input_buffer_handle))
- base::SharedMemory::CloseHandle(params.input_buffer_handle);
if (base::SharedMemory::IsHandleValid(params.output_video_frame_handle))
base::SharedMemory::CloseHandle(params.output_video_frame_handle);
return;
}
// For handles in |params|, from now on, |params.output_video_frame_handle|
- // is taken cared by scoper. |params.input_buffer_handle| need to be closed
- // manually for early exits.
+ // is taken cared by scoper. |params.input_buffer.handle()| need to be
+ // closed manually for early exits.
scoped_ptr<base::SharedMemory> output_shm(
new base::SharedMemory(params.output_video_frame_handle, false));
if (!output_shm->Map(params.output_buffer_size)) {
LOG(ERROR) << "Could not map output shared memory for input buffer id "
- << params.input_buffer_id;
+ << params.input_buffer.id();
NotifyDecodeStatusOnIOThread(
- *route_id, params.input_buffer_id,
+ *route_id, params.input_buffer.id(),
media::JpegDecodeAccelerator::PLATFORM_FAILURE);
- base::SharedMemory::CloseHandle(params.input_buffer_handle);
+ base::SharedMemory::CloseHandle(params.input_buffer.handle());
return;
}
- media::BitstreamBuffer input_buffer(params.input_buffer_id,
- params.input_buffer_handle,
- params.input_buffer_size);
-
uint8_t* shm_memory = static_cast<uint8_t*>(output_shm->memory());
scoped_refptr<media::VideoFrame> frame =
media::VideoFrame::WrapExternalSharedMemory(
@@ -250,11 +233,11 @@ class GpuJpegDecodeAccelerator::MessageFilter : public IPC::MessageFilter {
base::TimeDelta()); // timestamp
if (!frame.get()) {
LOG(ERROR) << "Could not create VideoFrame for input buffer id "
- << params.input_buffer_id;
+ << params.input_buffer.id();
NotifyDecodeStatusOnIOThread(
- *route_id, params.input_buffer_id,
+ *route_id, params.input_buffer.id(),
media::JpegDecodeAccelerator::PLATFORM_FAILURE);
- base::SharedMemory::CloseHandle(params.input_buffer_handle);
+ base::SharedMemory::CloseHandle(params.input_buffer.handle());
return;
}
frame->AddDestructionObserver(
@@ -262,7 +245,7 @@ class GpuJpegDecodeAccelerator::MessageFilter : public IPC::MessageFilter {
DCHECK_GT(client_map_.count(*route_id), 0u);
Client* client = client_map_[*route_id];
- client->Decode(input_buffer, frame);
+ client->Decode(params.input_buffer, frame);
}
protected:
@@ -309,7 +292,7 @@ class GpuJpegDecodeAccelerator::MessageFilter : public IPC::MessageFilter {
};
GpuJpegDecodeAccelerator::GpuJpegDecodeAccelerator(
- GpuChannel* channel,
+ gpu::GpuChannel* channel,
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
: channel_(channel),
child_task_runner_(base::ThreadTaskRunnerHandle::Get()),
@@ -325,7 +308,7 @@ GpuJpegDecodeAccelerator::~GpuJpegDecodeAccelerator() {
}
void GpuJpegDecodeAccelerator::AddClient(int32_t route_id,
- IPC::Message* reply_msg) {
+ base::Callback<void(bool)> response) {
DCHECK(CalledOnValidThread());
// When adding non-chromeos platforms, VideoCaptureGpuJpegDecoder::Initialize
@@ -350,8 +333,7 @@ void GpuJpegDecodeAccelerator::AddClient(int32_t route_id,
if (!accelerator) {
DLOG(ERROR) << "JPEG accelerator Initialize failed";
- GpuMsg_CreateJpegDecoder::WriteReplyParams(reply_msg, false);
- Send(reply_msg);
+ response.Run(false);
return;
}
client->set_accelerator(std::move(accelerator));
@@ -372,7 +354,7 @@ void GpuJpegDecodeAccelerator::AddClient(int32_t route_id,
// here instead of making the code unnecessary complicated.
io_task_runner_->PostTask(
FROM_HERE, base::Bind(&MessageFilter::AddClientOnIOThread, filter_,
- route_id, client.release(), reply_msg));
+ route_id, client.release(), response));
}
void GpuJpegDecodeAccelerator::NotifyDecodeStatus(
diff --git a/chromium/content/common/gpu/media/gpu_jpeg_decode_accelerator.h b/chromium/content/common/gpu/media/gpu_jpeg_decode_accelerator.h
index 0fc316e026f..680dac578e0 100644
--- a/chromium/content/common/gpu/media/gpu_jpeg_decode_accelerator.h
+++ b/chromium/content/common/gpu/media/gpu_jpeg_decode_accelerator.h
@@ -20,9 +20,11 @@ namespace base {
class SingleThreadTaskRunner;
}
-namespace content {
+namespace gpu {
class GpuChannel;
+}
+namespace content {
class GpuJpegDecodeAccelerator
: public IPC::Sender,
public base::NonThreadSafe,
@@ -30,11 +32,11 @@ class GpuJpegDecodeAccelerator
public:
// |channel| must outlive this object.
GpuJpegDecodeAccelerator(
- GpuChannel* channel,
+ gpu::GpuChannel* channel,
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
~GpuJpegDecodeAccelerator() override;
- void AddClient(int32_t route_id, IPC::Message* reply_msg);
+ void AddClient(int32_t route_id, base::Callback<void(bool)> response);
void NotifyDecodeStatus(int32_t route_id,
int32_t bitstream_buffer_id,
@@ -61,10 +63,10 @@ class GpuJpegDecodeAccelerator
static scoped_ptr<media::JpegDecodeAccelerator> CreateVaapiJDA(
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
- // The lifetime of objects of this class is managed by a GpuChannel. The
+ // The lifetime of objects of this class is managed by a gpu::GpuChannel. The
// GpuChannels destroy all the GpuJpegDecodeAccelerator that they own when
// they are destroyed. So a raw pointer is safe.
- GpuChannel* channel_;
+ gpu::GpuChannel* channel_;
// The message filter to run JpegDecodeAccelerator::Decode on IO thread.
scoped_refptr<MessageFilter> filter_;
diff --git a/chromium/content/common/gpu/media/gpu_video_accelerator_util.cc b/chromium/content/common/gpu/media/gpu_video_accelerator_util.cc
deleted file mode 100644
index 7692fddc40a..00000000000
--- a/chromium/content/common/gpu/media/gpu_video_accelerator_util.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/gpu/media/gpu_video_accelerator_util.h"
-
-namespace content {
-
-// Make sure the enum values of media::VideoCodecProfile and
-// gpu::VideoCodecProfile match.
-#define STATIC_ASSERT_ENUM_MATCH(name) \
- static_assert( \
- media::name == static_cast<media::VideoCodecProfile>(gpu::name), \
- #name " value must match in media and gpu.")
-
-STATIC_ASSERT_ENUM_MATCH(VIDEO_CODEC_PROFILE_UNKNOWN);
-STATIC_ASSERT_ENUM_MATCH(VIDEO_CODEC_PROFILE_MIN);
-STATIC_ASSERT_ENUM_MATCH(H264PROFILE_BASELINE);
-STATIC_ASSERT_ENUM_MATCH(H264PROFILE_MAIN);
-STATIC_ASSERT_ENUM_MATCH(H264PROFILE_EXTENDED);
-STATIC_ASSERT_ENUM_MATCH(H264PROFILE_HIGH);
-STATIC_ASSERT_ENUM_MATCH(H264PROFILE_HIGH10PROFILE);
-STATIC_ASSERT_ENUM_MATCH(H264PROFILE_HIGH422PROFILE);
-STATIC_ASSERT_ENUM_MATCH(H264PROFILE_HIGH444PREDICTIVEPROFILE);
-STATIC_ASSERT_ENUM_MATCH(H264PROFILE_SCALABLEBASELINE);
-STATIC_ASSERT_ENUM_MATCH(H264PROFILE_SCALABLEHIGH);
-STATIC_ASSERT_ENUM_MATCH(H264PROFILE_STEREOHIGH);
-STATIC_ASSERT_ENUM_MATCH(H264PROFILE_MULTIVIEWHIGH);
-STATIC_ASSERT_ENUM_MATCH(VP8PROFILE_ANY);
-STATIC_ASSERT_ENUM_MATCH(VP9PROFILE_ANY);
-STATIC_ASSERT_ENUM_MATCH(VIDEO_CODEC_PROFILE_MAX);
-
-// static
-media::VideoDecodeAccelerator::Capabilities
-GpuVideoAcceleratorUtil::ConvertGpuToMediaDecodeCapabilities(
- const gpu::VideoDecodeAcceleratorCapabilities& gpu_capabilities) {
- media::VideoDecodeAccelerator::Capabilities capabilities;
- capabilities.supported_profiles =
- ConvertGpuToMediaDecodeProfiles(gpu_capabilities.supported_profiles);
- capabilities.flags = gpu_capabilities.flags;
- return capabilities;
-}
-
-// static
-media::VideoDecodeAccelerator::SupportedProfiles
-GpuVideoAcceleratorUtil::ConvertGpuToMediaDecodeProfiles(const
- gpu::VideoDecodeAcceleratorSupportedProfiles& gpu_profiles) {
- media::VideoDecodeAccelerator::SupportedProfiles profiles;
- for (const auto& gpu_profile : gpu_profiles) {
- media::VideoDecodeAccelerator::SupportedProfile profile;
- profile.profile =
- static_cast<media::VideoCodecProfile>(gpu_profile.profile);
- profile.max_resolution = gpu_profile.max_resolution;
- profile.min_resolution = gpu_profile.min_resolution;
- profiles.push_back(profile);
- }
- return profiles;
-}
-
-// static
-gpu::VideoDecodeAcceleratorCapabilities
-GpuVideoAcceleratorUtil::ConvertMediaToGpuDecodeCapabilities(
- const media::VideoDecodeAccelerator::Capabilities& media_capabilities) {
- gpu::VideoDecodeAcceleratorCapabilities capabilities;
- capabilities.supported_profiles =
- ConvertMediaToGpuDecodeProfiles(media_capabilities.supported_profiles);
- capabilities.flags = media_capabilities.flags;
- return capabilities;
-}
-
-// static
-gpu::VideoDecodeAcceleratorSupportedProfiles
-GpuVideoAcceleratorUtil::ConvertMediaToGpuDecodeProfiles(const
- media::VideoDecodeAccelerator::SupportedProfiles& media_profiles) {
- gpu::VideoDecodeAcceleratorSupportedProfiles profiles;
- for (const auto& media_profile : media_profiles) {
- gpu::VideoDecodeAcceleratorSupportedProfile profile;
- profile.profile =
- static_cast<gpu::VideoCodecProfile>(media_profile.profile);
- profile.max_resolution = media_profile.max_resolution;
- profile.min_resolution = media_profile.min_resolution;
- profiles.push_back(profile);
- }
- return profiles;
-}
-
-// static
-media::VideoEncodeAccelerator::SupportedProfiles
-GpuVideoAcceleratorUtil::ConvertGpuToMediaEncodeProfiles(const
- gpu::VideoEncodeAcceleratorSupportedProfiles& gpu_profiles) {
- media::VideoEncodeAccelerator::SupportedProfiles profiles;
- for (const auto& gpu_profile : gpu_profiles) {
- media::VideoEncodeAccelerator::SupportedProfile profile;
- profile.profile =
- static_cast<media::VideoCodecProfile>(gpu_profile.profile);
- profile.max_resolution = gpu_profile.max_resolution;
- profile.max_framerate_numerator = gpu_profile.max_framerate_numerator;
- profile.max_framerate_denominator = gpu_profile.max_framerate_denominator;
- profiles.push_back(profile);
- }
- return profiles;
-}
-
-// static
-gpu::VideoEncodeAcceleratorSupportedProfiles
-GpuVideoAcceleratorUtil::ConvertMediaToGpuEncodeProfiles(const
- media::VideoEncodeAccelerator::SupportedProfiles& media_profiles) {
- gpu::VideoEncodeAcceleratorSupportedProfiles profiles;
- for (const auto& media_profile : media_profiles) {
- gpu::VideoEncodeAcceleratorSupportedProfile profile;
- profile.profile =
- static_cast<gpu::VideoCodecProfile>(media_profile.profile);
- profile.max_resolution = media_profile.max_resolution;
- profile.max_framerate_numerator = media_profile.max_framerate_numerator;
- profile.max_framerate_denominator = media_profile.max_framerate_denominator;
- profiles.push_back(profile);
- }
- return profiles;
-}
-
-// static
-void GpuVideoAcceleratorUtil::InsertUniqueDecodeProfiles(
- const media::VideoDecodeAccelerator::SupportedProfiles& new_profiles,
- media::VideoDecodeAccelerator::SupportedProfiles* media_profiles) {
- for (const auto& profile : new_profiles) {
- bool duplicate = false;
- for (const auto& media_profile : *media_profiles) {
- if (media_profile.profile == profile.profile) {
- duplicate = true;
- break;
- }
- }
- if (!duplicate)
- media_profiles->push_back(profile);
- }
-}
-
-// static
-void GpuVideoAcceleratorUtil::InsertUniqueEncodeProfiles(
- const media::VideoEncodeAccelerator::SupportedProfiles& new_profiles,
- media::VideoEncodeAccelerator::SupportedProfiles* media_profiles) {
- for (const auto& profile : new_profiles) {
- bool duplicate = false;
- for (const auto& media_profile : *media_profiles) {
- if (media_profile.profile == profile.profile) {
- duplicate = true;
- break;
- }
- }
- if (!duplicate)
- media_profiles->push_back(profile);
- }
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/media/gpu_video_accelerator_util.h b/chromium/content/common/gpu/media/gpu_video_accelerator_util.h
deleted file mode 100644
index e39034e191e..00000000000
--- a/chromium/content/common/gpu/media/gpu_video_accelerator_util.h
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_MEDIA_GPU_VIDEO_ACCELERATOR_UTIL_H_
-#define CONTENT_COMMON_GPU_MEDIA_GPU_VIDEO_ACCELERATOR_UTIL_H_
-
-#include <vector>
-
-#include "gpu/config/gpu_info.h"
-#include "media/video/video_decode_accelerator.h"
-#include "media/video/video_encode_accelerator.h"
-
-namespace content {
-
-class GpuVideoAcceleratorUtil {
- public:
- // Convert decoder gpu capabilities to media capabilities.
- static media::VideoDecodeAccelerator::Capabilities
- ConvertGpuToMediaDecodeCapabilities(
- const gpu::VideoDecodeAcceleratorCapabilities& gpu_capabilities);
-
- // Convert decoder gpu profiles to media profiles.
- static media::VideoDecodeAccelerator::SupportedProfiles
- ConvertGpuToMediaDecodeProfiles(const
- gpu::VideoDecodeAcceleratorSupportedProfiles& gpu_profiles);
-
- // Convert decoder media capabilities to gpu capabilities.
- static gpu::VideoDecodeAcceleratorCapabilities
- ConvertMediaToGpuDecodeCapabilities(
- const media::VideoDecodeAccelerator::Capabilities& media_capabilities);
-
- // Convert decoder media profiles to gpu profiles.
- static gpu::VideoDecodeAcceleratorSupportedProfiles
- ConvertMediaToGpuDecodeProfiles(const
- media::VideoDecodeAccelerator::SupportedProfiles& media_profiles);
-
- // Convert encoder gpu profiles to media profiles.
- static media::VideoEncodeAccelerator::SupportedProfiles
- ConvertGpuToMediaEncodeProfiles(const
- gpu::VideoEncodeAcceleratorSupportedProfiles& gpu_profiles);
-
- // Convert encoder media profiles to gpu profiles.
- static gpu::VideoEncodeAcceleratorSupportedProfiles
- ConvertMediaToGpuEncodeProfiles(const
- media::VideoEncodeAccelerator::SupportedProfiles& media_profiles);
-
- // Insert |new_profiles| into |media_profiles|, ensuring no duplicates are
- // inserted.
- static void InsertUniqueDecodeProfiles(
- const media::VideoDecodeAccelerator::SupportedProfiles& new_profiles,
- media::VideoDecodeAccelerator::SupportedProfiles* media_profiles);
-
- // Insert |new_profiles| into |media_profiles|, ensuring no duplicates are
- // inserted.
- static void InsertUniqueEncodeProfiles(
- const media::VideoEncodeAccelerator::SupportedProfiles& new_profiles,
- media::VideoEncodeAccelerator::SupportedProfiles* media_profiles);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_MEDIA_GPU_VIDEO_ACCELERATOR_UTIL_H_
diff --git a/chromium/content/common/gpu/media/gpu_video_decode_accelerator.cc b/chromium/content/common/gpu/media/gpu_video_decode_accelerator.cc
index 5424a5ff32d..3d30266f05a 100644
--- a/chromium/content/common/gpu/media/gpu_video_decode_accelerator.cc
+++ b/chromium/content/common/gpu/media/gpu_video_decode_accelerator.cc
@@ -7,7 +7,6 @@
#include <vector>
#include "base/bind.h"
-#include "base/command_line.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
@@ -15,47 +14,36 @@
#include "base/stl_util.h"
#include "base/thread_task_runner_handle.h"
#include "build/build_config.h"
-
-#include "content/common/gpu/gpu_channel.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "content/common/gpu/media/gpu_video_accelerator_util.h"
-#include "content/public/common/content_switches.h"
+#include "content/common/gpu/media/gpu_video_decode_accelerator_factory_impl.h"
#include "gpu/command_buffer/common/command_buffer.h"
+#include "gpu/command_buffer/service/gpu_preferences.h"
+#include "gpu/ipc/service/gpu_channel.h"
+#include "gpu/ipc/service/gpu_channel_manager.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_message_utils.h"
#include "ipc/message_filter.h"
#include "media/base/limits.h"
+#include "media/gpu/ipc/common/gpu_video_accelerator_util.h"
+#include "media/gpu/ipc/common/media_messages.h"
+#include "ui/gfx/geometry/size.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_image.h"
-#include "ui/gl/gl_surface_egl.h"
-
-#if defined(OS_WIN)
-#include "base/win/windows_version.h"
-#include "content/common/gpu/media/dxva_video_decode_accelerator_win.h"
-#elif defined(OS_MACOSX)
-#include "content/common/gpu/media/vt_video_decode_accelerator_mac.h"
-#elif defined(OS_CHROMEOS)
-#if defined(USE_V4L2_CODEC)
-#include "content/common/gpu/media/v4l2_device.h"
-#include "content/common/gpu/media/v4l2_slice_video_decode_accelerator.h"
-#include "content/common/gpu/media/v4l2_video_decode_accelerator.h"
-#endif
-#if defined(ARCH_CPU_X86_FAMILY)
-#include "content/common/gpu/media/vaapi_video_decode_accelerator.h"
-#include "ui/gl/gl_implementation.h"
-#endif
-#elif defined(USE_OZONE)
-#include "media/ozone/media_ozone_platform.h"
-#elif defined(OS_ANDROID)
-#include "content/common/gpu/media/android_video_decode_accelerator.h"
-#endif
-
-#include "ui/gfx/geometry/size.h"
namespace content {
+namespace {
+static gfx::GLContext* GetGLContext(
+ const base::WeakPtr<gpu::GpuCommandBufferStub>& stub) {
+ if (!stub) {
+ DLOG(ERROR) << "Stub is gone; no GLContext.";
+ return nullptr;
+ }
+
+ return stub->decoder()->GetGLContext();
+}
+
static bool MakeDecoderContextCurrent(
- const base::WeakPtr<GpuCommandBufferStub> stub) {
+ const base::WeakPtr<gpu::GpuCommandBufferStub>& stub) {
if (!stub) {
DLOG(ERROR) << "Stub is gone; won't MakeCurrent().";
return false;
@@ -69,6 +57,43 @@ static bool MakeDecoderContextCurrent(
return true;
}
+#if (defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)) || defined(OS_MACOSX)
+static bool BindImage(const base::WeakPtr<gpu::GpuCommandBufferStub>& stub,
+ uint32_t client_texture_id,
+ uint32_t texture_target,
+ const scoped_refptr<gl::GLImage>& image,
+ bool can_bind_to_sampler) {
+ if (!stub) {
+ DLOG(ERROR) << "Stub is gone; won't BindImage().";
+ return false;
+ }
+
+ gpu::gles2::GLES2Decoder* command_decoder = stub->decoder();
+ gpu::gles2::TextureManager* texture_manager =
+ command_decoder->GetContextGroup()->texture_manager();
+ gpu::gles2::TextureRef* ref = texture_manager->GetTexture(client_texture_id);
+ if (ref) {
+ texture_manager->SetLevelImage(ref, texture_target, 0, image.get(),
+ can_bind_to_sampler
+ ? gpu::gles2::Texture::BOUND
+ : gpu::gles2::Texture::UNBOUND);
+ }
+
+ return true;
+}
+#endif
+
+static base::WeakPtr<gpu::gles2::GLES2Decoder> GetGLES2Decoder(
+ const base::WeakPtr<gpu::GpuCommandBufferStub>& stub) {
+ if (!stub) {
+ DLOG(ERROR) << "Stub is gone; no GLES2Decoder.";
+ return base::WeakPtr<gpu::gles2::GLES2Decoder>();
+ }
+
+ return stub->decoder()->AsWeakPtr();
+}
+} // anonymous namespace
+
// DebugAutoLock works like AutoLock but only acquires the lock when
// DCHECK is on.
#if DCHECK_IS_ON()
@@ -103,7 +128,7 @@ class GpuVideoDecodeAccelerator::MessageFilter : public IPC::MessageFilter {
IPC_BEGIN_MESSAGE_MAP(MessageFilter, msg)
IPC_MESSAGE_FORWARD(AcceleratedVideoDecoderMsg_Decode, owner_,
GpuVideoDecodeAccelerator::OnDecode)
- IPC_MESSAGE_UNHANDLED(return false;)
+ IPC_MESSAGE_UNHANDLED(return false)
IPC_END_MESSAGE_MAP()
return true;
}
@@ -129,19 +154,25 @@ class GpuVideoDecodeAccelerator::MessageFilter : public IPC::MessageFilter {
GpuVideoDecodeAccelerator::GpuVideoDecodeAccelerator(
int32_t host_route_id,
- GpuCommandBufferStub* stub,
+ gpu::GpuCommandBufferStub* stub,
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
: host_route_id_(host_route_id),
stub_(stub),
texture_target_(0),
+ textures_per_buffer_(0),
filter_removed_(true, false),
child_task_runner_(base::ThreadTaskRunnerHandle::Get()),
io_task_runner_(io_task_runner),
weak_factory_for_io_(this) {
DCHECK(stub_);
stub_->AddDestructionObserver(this);
- make_context_current_ =
+ get_gl_context_cb_ = base::Bind(&GetGLContext, stub_->AsWeakPtr());
+ make_context_current_cb_ =
base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr());
+#if (defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)) || defined(OS_MACOSX)
+ bind_image_cb_ = base::Bind(&BindImage, stub_->AsWeakPtr());
+#endif
+ get_gles2_decoder_cb_ = base::Bind(&GetGLES2Decoder, stub_->AsWeakPtr());
}
GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() {
@@ -152,41 +183,10 @@ GpuVideoDecodeAccelerator::~GpuVideoDecodeAccelerator() {
// static
gpu::VideoDecodeAcceleratorCapabilities
-GpuVideoDecodeAccelerator::GetCapabilities() {
- media::VideoDecodeAccelerator::Capabilities capabilities;
- const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
- if (cmd_line->HasSwitch(switches::kDisableAcceleratedVideoDecode))
- return gpu::VideoDecodeAcceleratorCapabilities();
-
- // Query supported profiles for each VDA. The order of querying VDAs should
- // be the same as the order of initializing VDAs. Then the returned profile
- // can be initialized by corresponding VDA successfully.
-#if defined(OS_WIN)
- capabilities.supported_profiles =
- DXVAVideoDecodeAccelerator::GetSupportedProfiles();
-#elif defined(OS_CHROMEOS)
- media::VideoDecodeAccelerator::SupportedProfiles vda_profiles;
-#if defined(USE_V4L2_CODEC)
- vda_profiles = V4L2VideoDecodeAccelerator::GetSupportedProfiles();
- GpuVideoAcceleratorUtil::InsertUniqueDecodeProfiles(
- vda_profiles, &capabilities.supported_profiles);
- vda_profiles = V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles();
- GpuVideoAcceleratorUtil::InsertUniqueDecodeProfiles(
- vda_profiles, &capabilities.supported_profiles);
-#endif
-#if defined(ARCH_CPU_X86_FAMILY)
- vda_profiles = VaapiVideoDecodeAccelerator::GetSupportedProfiles();
- GpuVideoAcceleratorUtil::InsertUniqueDecodeProfiles(
- vda_profiles, &capabilities.supported_profiles);
-#endif
-#elif defined(OS_MACOSX)
- capabilities.supported_profiles =
- VTVideoDecodeAccelerator::GetSupportedProfiles();
-#elif defined(OS_ANDROID)
- capabilities = AndroidVideoDecodeAccelerator::GetCapabilities();
-#endif
- return GpuVideoAcceleratorUtil::ConvertMediaToGpuDecodeCapabilities(
- capabilities);
+GpuVideoDecodeAccelerator::GetCapabilities(
+ const gpu::GpuPreferences& gpu_preferences) {
+ return GpuVideoDecodeAcceleratorFactoryImpl::GetDecoderCapabilities(
+ gpu_preferences);
}
bool GpuVideoDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) {
@@ -209,14 +209,16 @@ bool GpuVideoDecodeAccelerator::OnMessageReceived(const IPC::Message& msg) {
return handled;
}
-void GpuVideoDecodeAccelerator::NotifyCdmAttached(bool success) {
- if (!Send(new AcceleratedVideoDecoderHostMsg_CdmAttached(host_route_id_,
- success)))
- DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_CdmAttached) failed";
+void GpuVideoDecodeAccelerator::NotifyInitializationComplete(bool success) {
+ if (!Send(new AcceleratedVideoDecoderHostMsg_InitializationComplete(
+ host_route_id_, success)))
+ DLOG(ERROR)
+ << "Send(AcceleratedVideoDecoderHostMsg_InitializationComplete) failed";
}
void GpuVideoDecodeAccelerator::ProvidePictureBuffers(
uint32_t requested_num_of_buffers,
+ uint32_t textures_per_buffer,
const gfx::Size& dimensions,
uint32_t texture_target) {
if (dimensions.width() > media::limits::kMaxDimension ||
@@ -226,14 +228,13 @@ void GpuVideoDecodeAccelerator::ProvidePictureBuffers(
return;
}
if (!Send(new AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers(
- host_route_id_,
- requested_num_of_buffers,
- dimensions,
- texture_target))) {
+ host_route_id_, requested_num_of_buffers, textures_per_buffer,
+ dimensions, texture_target))) {
DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_ProvidePictureBuffers) "
<< "failed";
}
texture_dimensions_ = dimensions;
+ textures_per_buffer_ = textures_per_buffer;
texture_target_ = texture_target;
}
@@ -265,7 +266,7 @@ void GpuVideoDecodeAccelerator::PictureReady(
if (!Send(new AcceleratedVideoDecoderHostMsg_PictureReady(
host_route_id_, picture.picture_buffer_id(),
picture.bitstream_buffer_id(), picture.visible_rect(),
- picture.allow_overlay()))) {
+ picture.allow_overlay(), picture.size_changed()))) {
DLOG(ERROR) << "Send(AcceleratedVideoDecoderHostMsg_PictureReady) failed";
}
}
@@ -327,161 +328,51 @@ bool GpuVideoDecodeAccelerator::Send(IPC::Message* message) {
return stub_->channel()->Send(message);
}
-void GpuVideoDecodeAccelerator::Initialize(
- const media::VideoDecodeAccelerator::Config& config,
- IPC::Message* init_done_msg) {
+bool GpuVideoDecodeAccelerator::Initialize(
+ const media::VideoDecodeAccelerator::Config& config) {
DCHECK(!video_decode_accelerator_);
- if (!stub_->channel()->AddRoute(host_route_id_, this)) {
+ if (!stub_->channel()->AddRoute(host_route_id_, stub_->stream_id(), this)) {
DLOG(ERROR) << "Initialize(): failed to add route";
- SendCreateDecoderReply(init_done_msg, false);
+ return false;
}
#if !defined(OS_WIN)
// Ensure we will be able to get a GL context at all before initializing
// non-Windows VDAs.
- if (!make_context_current_.Run()) {
- SendCreateDecoderReply(init_done_msg, false);
- return;
- }
+ if (!make_context_current_cb_.Run())
+ return false;
#endif
- // Array of Create..VDA() function pointers, maybe applicable to the current
- // platform. This list is ordered by priority of use and it should be the
- // same as the order of querying supported profiles of VDAs.
- const GpuVideoDecodeAccelerator::CreateVDAFp create_vda_fps[] = {
- &GpuVideoDecodeAccelerator::CreateDXVAVDA,
- &GpuVideoDecodeAccelerator::CreateV4L2VDA,
- &GpuVideoDecodeAccelerator::CreateV4L2SliceVDA,
- &GpuVideoDecodeAccelerator::CreateVaapiVDA,
- &GpuVideoDecodeAccelerator::CreateVTVDA,
- &GpuVideoDecodeAccelerator::CreateOzoneVDA,
- &GpuVideoDecodeAccelerator::CreateAndroidVDA};
-
- for (const auto& create_vda_function : create_vda_fps) {
- video_decode_accelerator_ = (this->*create_vda_function)();
- if (!video_decode_accelerator_ ||
- !video_decode_accelerator_->Initialize(config, this))
- continue;
-
- if (video_decode_accelerator_->CanDecodeOnIOThread()) {
- filter_ = new MessageFilter(this, host_route_id_);
- stub_->channel()->AddFilter(filter_.get());
- }
- SendCreateDecoderReply(init_done_msg, true);
- return;
- }
- video_decode_accelerator_.reset();
- LOG(ERROR) << "HW video decode not available for profile " << config.profile
- << (config.is_encrypted ? " with encryption" : "");
- SendCreateDecoderReply(init_done_msg, false);
-}
+ scoped_ptr<GpuVideoDecodeAcceleratorFactoryImpl> vda_factory =
+ GpuVideoDecodeAcceleratorFactoryImpl::CreateWithGLES2Decoder(
+ get_gl_context_cb_, make_context_current_cb_, bind_image_cb_,
+ get_gles2_decoder_cb_);
-scoped_ptr<media::VideoDecodeAccelerator>
-GpuVideoDecodeAccelerator::CreateDXVAVDA() {
- scoped_ptr<media::VideoDecodeAccelerator> decoder;
-#if defined(OS_WIN)
- if (base::win::GetVersion() >= base::win::VERSION_WIN7) {
- DVLOG(0) << "Initializing DXVA HW decoder for windows.";
- decoder.reset(new DXVAVideoDecodeAccelerator(make_context_current_,
- stub_->decoder()->GetGLContext()));
- } else {
- NOTIMPLEMENTED() << "HW video decode acceleration not available.";
+ if (!vda_factory) {
+ LOG(ERROR) << "Failed creating the VDA factory";
+ return false;
}
-#endif
- return decoder;
-}
-scoped_ptr<media::VideoDecodeAccelerator>
-GpuVideoDecodeAccelerator::CreateV4L2VDA() {
- scoped_ptr<media::VideoDecodeAccelerator> decoder;
-#if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
- scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder);
- if (device.get()) {
- decoder.reset(new V4L2VideoDecodeAccelerator(
- gfx::GLSurfaceEGL::GetHardwareDisplay(),
- stub_->decoder()->GetGLContext()->GetHandle(),
- weak_factory_for_io_.GetWeakPtr(),
- make_context_current_,
- device,
- io_task_runner_));
+ const gpu::GpuPreferences& gpu_preferences =
+ stub_->channel()->gpu_channel_manager()->gpu_preferences();
+ video_decode_accelerator_ =
+ vda_factory->CreateVDA(this, config, gpu_preferences);
+ if (!video_decode_accelerator_) {
+ LOG(ERROR) << "HW video decode not available for profile " << config.profile
+ << (config.is_encrypted ? " with encryption" : "");
+ return false;
}
-#endif
- return decoder;
-}
-scoped_ptr<media::VideoDecodeAccelerator>
-GpuVideoDecodeAccelerator::CreateV4L2SliceVDA() {
- scoped_ptr<media::VideoDecodeAccelerator> decoder;
-#if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
- scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder);
- if (device.get()) {
- decoder.reset(new V4L2SliceVideoDecodeAccelerator(
- device,
- gfx::GLSurfaceEGL::GetHardwareDisplay(),
- stub_->decoder()->GetGLContext()->GetHandle(),
- weak_factory_for_io_.GetWeakPtr(),
- make_context_current_,
- io_task_runner_));
+ // Attempt to set up performing decoding tasks on IO thread, if supported by
+ // the VDA.
+ if (video_decode_accelerator_->TryToSetupDecodeOnSeparateThread(
+ weak_factory_for_io_.GetWeakPtr(), io_task_runner_)) {
+ filter_ = new MessageFilter(this, host_route_id_);
+ stub_->channel()->AddFilter(filter_.get());
}
-#endif
- return decoder;
-}
-void GpuVideoDecodeAccelerator::BindImage(uint32_t client_texture_id,
- uint32_t texture_target,
- scoped_refptr<gl::GLImage> image) {
- gpu::gles2::GLES2Decoder* command_decoder = stub_->decoder();
- gpu::gles2::TextureManager* texture_manager =
- command_decoder->GetContextGroup()->texture_manager();
- gpu::gles2::TextureRef* ref = texture_manager->GetTexture(client_texture_id);
- if (ref) {
- texture_manager->SetLevelImage(ref, texture_target, 0, image.get(),
- gpu::gles2::Texture::BOUND);
- }
-}
-
-scoped_ptr<media::VideoDecodeAccelerator>
-GpuVideoDecodeAccelerator::CreateVaapiVDA() {
- scoped_ptr<media::VideoDecodeAccelerator> decoder;
-#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
- decoder.reset(new VaapiVideoDecodeAccelerator(
- make_context_current_, base::Bind(&GpuVideoDecodeAccelerator::BindImage,
- base::Unretained(this))));
-#endif
- return decoder;
-}
-
-scoped_ptr<media::VideoDecodeAccelerator>
-GpuVideoDecodeAccelerator::CreateVTVDA() {
- scoped_ptr<media::VideoDecodeAccelerator> decoder;
-#if defined(OS_MACOSX)
- decoder.reset(new VTVideoDecodeAccelerator(
- make_context_current_, base::Bind(&GpuVideoDecodeAccelerator::BindImage,
- base::Unretained(this))));
-#endif
- return decoder;
-}
-
-scoped_ptr<media::VideoDecodeAccelerator>
-GpuVideoDecodeAccelerator::CreateOzoneVDA() {
- scoped_ptr<media::VideoDecodeAccelerator> decoder;
-#if !defined(OS_CHROMEOS) && defined(USE_OZONE)
- media::MediaOzonePlatform* platform =
- media::MediaOzonePlatform::GetInstance();
- decoder.reset(platform->CreateVideoDecodeAccelerator(make_context_current_));
-#endif
- return decoder;
-}
-
-scoped_ptr<media::VideoDecodeAccelerator>
-GpuVideoDecodeAccelerator::CreateAndroidVDA() {
- scoped_ptr<media::VideoDecodeAccelerator> decoder;
-#if defined(OS_ANDROID)
- decoder.reset(new AndroidVideoDecodeAccelerator(stub_->decoder()->AsWeakPtr(),
- make_context_current_));
-#endif
- return decoder;
+ return true;
}
void GpuVideoDecodeAccelerator::OnSetCdm(int cdm_id) {
@@ -489,40 +380,17 @@ void GpuVideoDecodeAccelerator::OnSetCdm(int cdm_id) {
video_decode_accelerator_->SetCdm(cdm_id);
}
-// Runs on IO thread if video_decode_accelerator_->CanDecodeOnIOThread() is
-// true, otherwise on the main thread.
+// Runs on IO thread if VDA::TryToSetupDecodeOnSeparateThread() succeeded,
+// otherwise on the main thread.
void GpuVideoDecodeAccelerator::OnDecode(
- const AcceleratedVideoDecoderMsg_Decode_Params& params) {
+ const media::BitstreamBuffer& bitstream_buffer) {
DCHECK(video_decode_accelerator_);
- if (params.bitstream_buffer_id < 0) {
- DLOG(ERROR) << "BitstreamBuffer id " << params.bitstream_buffer_id
- << " out of range";
- if (child_task_runner_->BelongsToCurrentThread()) {
- NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT);
- } else {
- child_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&GpuVideoDecodeAccelerator::NotifyError,
- base::Unretained(this),
- media::VideoDecodeAccelerator::INVALID_ARGUMENT));
- }
- return;
- }
-
- media::BitstreamBuffer bitstream_buffer(params.bitstream_buffer_id,
- params.buffer_handle, params.size,
- params.presentation_timestamp);
- if (!params.key_id.empty()) {
- bitstream_buffer.SetDecryptConfig(
- media::DecryptConfig(params.key_id, params.iv, params.subsamples));
- }
-
video_decode_accelerator_->Decode(bitstream_buffer);
}
void GpuVideoDecodeAccelerator::OnAssignPictureBuffers(
const std::vector<int32_t>& buffer_ids,
- const std::vector<uint32_t>& texture_ids) {
+ const std::vector<media::PictureBuffer::TextureIds>& texture_ids) {
if (buffer_ids.size() != texture_ids.size()) {
NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT);
return;
@@ -540,51 +408,65 @@ void GpuVideoDecodeAccelerator::OnAssignPictureBuffers(
NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT);
return;
}
- gpu::gles2::TextureRef* texture_ref = texture_manager->GetTexture(
- texture_ids[i]);
- if (!texture_ref) {
- DLOG(ERROR) << "Failed to find texture id " << texture_ids[i];
- NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT);
- return;
- }
- gpu::gles2::Texture* info = texture_ref->texture();
- if (info->target() != texture_target_) {
- DLOG(ERROR) << "Texture target mismatch for texture id "
- << texture_ids[i];
+ media::PictureBuffer::TextureIds buffer_texture_ids = texture_ids[i];
+ media::PictureBuffer::TextureIds service_ids;
+ if (buffer_texture_ids.size() != textures_per_buffer_) {
+ DLOG(ERROR) << "Requested " << textures_per_buffer_
+ << " textures per picture buffer, got "
+ << buffer_texture_ids.size();
NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT);
return;
}
- if (texture_target_ == GL_TEXTURE_EXTERNAL_OES ||
- texture_target_ == GL_TEXTURE_RECTANGLE_ARB) {
- // These textures have their dimensions defined by the underlying storage.
- // Use |texture_dimensions_| for this size.
- texture_manager->SetLevelInfo(
- texture_ref, texture_target_, 0, GL_RGBA, texture_dimensions_.width(),
- texture_dimensions_.height(), 1, 0, GL_RGBA, 0, gfx::Rect());
- } else {
- // For other targets, texture dimensions should already be defined.
- GLsizei width = 0, height = 0;
- info->GetLevelSize(texture_target_, 0, &width, &height, nullptr);
- if (width != texture_dimensions_.width() ||
- height != texture_dimensions_.height()) {
- DLOG(ERROR) << "Size mismatch for texture id " << texture_ids[i];
+ for (size_t j = 0; j < textures_per_buffer_; j++) {
+ gpu::gles2::TextureRef* texture_ref =
+ texture_manager->GetTexture(buffer_texture_ids[j]);
+ if (!texture_ref) {
+ DLOG(ERROR) << "Failed to find texture id " << buffer_texture_ids[j];
NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT);
return;
}
-
- // TODO(dshwang): after moving to D3D11, remove this. crbug.com/438691
- GLenum format =
- video_decode_accelerator_.get()->GetSurfaceInternalFormat();
- if (format != GL_RGBA) {
- texture_manager->SetLevelInfo(texture_ref, texture_target_, 0, format,
- width, height, 1, 0, format, 0,
- gfx::Rect());
+ gpu::gles2::Texture* info = texture_ref->texture();
+ if (info->target() != texture_target_) {
+ DLOG(ERROR) << "Texture target mismatch for texture id "
+ << buffer_texture_ids[j];
+ NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT);
+ return;
+ }
+ if (texture_target_ == GL_TEXTURE_EXTERNAL_OES ||
+ texture_target_ == GL_TEXTURE_RECTANGLE_ARB) {
+ // These textures have their dimensions defined by the underlying
+ // storage.
+ // Use |texture_dimensions_| for this size.
+ texture_manager->SetLevelInfo(texture_ref, texture_target_, 0, GL_RGBA,
+ texture_dimensions_.width(),
+ texture_dimensions_.height(), 1, 0,
+ GL_RGBA, 0, gfx::Rect());
+ } else {
+ // For other targets, texture dimensions should already be defined.
+ GLsizei width = 0, height = 0;
+ info->GetLevelSize(texture_target_, 0, &width, &height, nullptr);
+ if (width != texture_dimensions_.width() ||
+ height != texture_dimensions_.height()) {
+ DLOG(ERROR) << "Size mismatch for texture id "
+ << buffer_texture_ids[j];
+ NotifyError(media::VideoDecodeAccelerator::INVALID_ARGUMENT);
+ return;
+ }
+
+ // TODO(dshwang): after moving to D3D11, remove this. crbug.com/438691
+ GLenum format =
+ video_decode_accelerator_.get()->GetSurfaceInternalFormat();
+ if (format != GL_RGBA) {
+ texture_manager->SetLevelInfo(texture_ref, texture_target_, 0, format,
+ width, height, 1, 0, format, 0,
+ gfx::Rect());
+ }
}
+ service_ids.push_back(texture_ref->service_id());
+ textures.push_back(texture_ref);
}
buffers.push_back(media::PictureBuffer(buffer_ids[i], texture_dimensions_,
- texture_ref->service_id(),
- texture_ids[i]));
- textures.push_back(texture_ref);
+ service_ids, buffer_texture_ids));
}
video_decode_accelerator_->AssignPictureBuffers(buffers);
DebugAutoLock auto_lock(debug_uncleared_textures_lock_);
@@ -637,10 +519,4 @@ void GpuVideoDecodeAccelerator::SetTextureCleared(
uncleared_textures_.erase(it);
}
-void GpuVideoDecodeAccelerator::SendCreateDecoderReply(IPC::Message* message,
- bool succeeded) {
- GpuCommandBufferMsg_CreateVideoDecoder::WriteReplyParams(message, succeeded);
- Send(message);
-}
-
} // namespace content
diff --git a/chromium/content/common/gpu/media/gpu_video_decode_accelerator.h b/chromium/content/common/gpu/media/gpu_video_decode_accelerator.h
index eb6459b37c3..47859d957f9 100644
--- a/chromium/content/common/gpu/media/gpu_video_decode_accelerator.h
+++ b/chromium/content/common/gpu/media/gpu_video_decode_accelerator.h
@@ -15,15 +15,19 @@
#include "base/memory/ref_counted.h"
#include "base/memory/shared_memory.h"
#include "base/synchronization/waitable_event.h"
-#include "content/common/gpu/gpu_command_buffer_stub.h"
+#include "content/common/gpu/media/gpu_video_decode_accelerator_helpers.h"
#include "gpu/command_buffer/service/texture_manager.h"
#include "gpu/config/gpu_info.h"
+#include "gpu/ipc/service/gpu_command_buffer_stub.h"
+#include "gpu/ipc/service/gpu_command_buffer_stub.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
#include "media/video/video_decode_accelerator.h"
#include "ui/gfx/geometry/size.h"
-struct AcceleratedVideoDecoderMsg_Decode_Params;
+namespace gpu {
+struct GpuPreferences;
+} // namespace gpu
namespace content {
@@ -31,27 +35,29 @@ class GpuVideoDecodeAccelerator
: public IPC::Listener,
public IPC::Sender,
public media::VideoDecodeAccelerator::Client,
- public GpuCommandBufferStub::DestructionObserver {
+ public gpu::GpuCommandBufferStub::DestructionObserver {
public:
// Each of the arguments to the constructor must outlive this object.
// |stub->decoder()| will be made current around any operation that touches
// the underlying VDA so that it can make GL calls safely.
GpuVideoDecodeAccelerator(
int32_t host_route_id,
- GpuCommandBufferStub* stub,
+ gpu::GpuCommandBufferStub* stub,
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
// Static query for the capabilities, which includes the supported profiles.
// This query calls the appropriate platform-specific version. The returned
// capabilities will not contain duplicate supported profile entries.
- static gpu::VideoDecodeAcceleratorCapabilities GetCapabilities();
+ static gpu::VideoDecodeAcceleratorCapabilities GetCapabilities(
+ const gpu::GpuPreferences& gpu_preferences);
// IPC::Listener implementation.
bool OnMessageReceived(const IPC::Message& message) override;
// media::VideoDecodeAccelerator::Client implementation.
- void NotifyCdmAttached(bool success) override;
+ void NotifyInitializationComplete(bool success) override;
void ProvidePictureBuffers(uint32_t requested_num_of_buffers,
+ uint32_t textures_per_buffer,
const gfx::Size& dimensions,
uint32_t texture_target) override;
void DismissPictureBuffer(int32_t picture_buffer_id) override;
@@ -69,33 +75,22 @@ class GpuVideoDecodeAccelerator
// Initialize VDAs from the set of VDAs supported for current platform until
// one of them succeeds for given |config|. Send the |init_done_msg| when
- // done. filter_ is passed to GpuCommandBufferStub channel only if the chosen
- // VDA can decode on IO thread.
- void Initialize(const media::VideoDecodeAccelerator::Config& config,
- IPC::Message* init_done_msg);
+ // done. filter_ is passed to gpu::GpuCommandBufferStub channel only if the
+ // chosen VDA can decode on IO thread.
+ bool Initialize(const media::VideoDecodeAccelerator::Config& config);
private:
- typedef scoped_ptr<media::VideoDecodeAccelerator>(
- GpuVideoDecodeAccelerator::*CreateVDAFp)();
-
class MessageFilter;
- scoped_ptr<media::VideoDecodeAccelerator> CreateDXVAVDA();
- scoped_ptr<media::VideoDecodeAccelerator> CreateV4L2VDA();
- scoped_ptr<media::VideoDecodeAccelerator> CreateV4L2SliceVDA();
- scoped_ptr<media::VideoDecodeAccelerator> CreateVaapiVDA();
- scoped_ptr<media::VideoDecodeAccelerator> CreateVTVDA();
- scoped_ptr<media::VideoDecodeAccelerator> CreateOzoneVDA();
- scoped_ptr<media::VideoDecodeAccelerator> CreateAndroidVDA();
-
// We only allow self-delete, from OnWillDestroyStub(), after cleanup there.
~GpuVideoDecodeAccelerator() override;
// Handlers for IPC messages.
void OnSetCdm(int cdm_id);
- void OnDecode(const AcceleratedVideoDecoderMsg_Decode_Params& params);
- void OnAssignPictureBuffers(const std::vector<int32_t>& buffer_ids,
- const std::vector<uint32_t>& texture_ids);
+ void OnDecode(const media::BitstreamBuffer& bitstream_buffer);
+ void OnAssignPictureBuffers(
+ const std::vector<int32_t>& buffer_ids,
+ const std::vector<media::PictureBuffer::TextureIds>& texture_ids);
void OnReusePictureBuffer(int32_t picture_buffer_id);
void OnFlush();
void OnReset();
@@ -107,28 +102,28 @@ class GpuVideoDecodeAccelerator
// Sets the texture to cleared.
void SetTextureCleared(const media::Picture& picture);
- // Helper for replying to the creation request.
- void SendCreateDecoderReply(IPC::Message* message, bool succeeded);
-
- // Helper to bind |image| to the texture specified by |client_texture_id|.
- void BindImage(uint32_t client_texture_id,
- uint32_t texture_target,
- scoped_refptr<gl::GLImage> image);
-
// Route ID to communicate with the host.
const int32_t host_route_id_;
- // Unowned pointer to the underlying GpuCommandBufferStub. |this| is
+ // Unowned pointer to the underlying gpu::GpuCommandBufferStub. |this| is
// registered as a DestuctionObserver of |stub_| and will self-delete when
// |stub_| is destroyed.
- GpuCommandBufferStub* const stub_;
+ gpu::GpuCommandBufferStub* const stub_;
// The underlying VideoDecodeAccelerator.
scoped_ptr<media::VideoDecodeAccelerator> video_decode_accelerator_;
+ // Callback to return current GLContext, if available.
+ GetGLContextCallback get_gl_context_cb_;
+
// Callback for making the relevant context current for GL calls.
- // Returns false if failed.
- base::Callback<bool(void)> make_context_current_;
+ MakeGLContextCurrentCallback make_context_current_cb_;
+
+ // Callback to bind a GLImage to a given texture id and target.
+ BindGLImageCallback bind_image_cb_;
+
+ // Callback to return a WeakPtr to GLES2Decoder.
+ GetGLES2DecoderCallback get_gles2_decoder_cb_;
// The texture dimensions as requested by ProvidePictureBuffers().
gfx::Size texture_dimensions_;
@@ -136,6 +131,10 @@ class GpuVideoDecodeAccelerator
// The texture target as requested by ProvidePictureBuffers().
uint32_t texture_target_;
+ // The number of textures per picture buffer as requests by
+ // ProvidePictureBuffers()
+ uint32_t textures_per_buffer_;
+
// The message filter to run VDA::Decode on IO thread if VDA supports it.
scoped_refptr<MessageFilter> filter_;
diff --git a/chromium/content/common/gpu/media/gpu_video_decode_accelerator_factory_impl.cc b/chromium/content/common/gpu/media/gpu_video_decode_accelerator_factory_impl.cc
new file mode 100644
index 00000000000..048314863d9
--- /dev/null
+++ b/chromium/content/common/gpu/media/gpu_video_decode_accelerator_factory_impl.cc
@@ -0,0 +1,242 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/gpu/media/gpu_video_decode_accelerator_factory_impl.h"
+
+#include "content/common/gpu/media/gpu_video_decode_accelerator.h"
+#include "gpu/command_buffer/service/gpu_preferences.h"
+#include "media/gpu/ipc/common/gpu_video_accelerator_util.h"
+
+#if defined(OS_WIN)
+#include "base/win/windows_version.h"
+#include "content/common/gpu/media/dxva_video_decode_accelerator_win.h"
+#elif defined(OS_MACOSX)
+#include "content/common/gpu/media/vt_video_decode_accelerator_mac.h"
+#elif defined(OS_CHROMEOS)
+#if defined(USE_V4L2_CODEC)
+#include "content/common/gpu/media/v4l2_device.h"
+#include "content/common/gpu/media/v4l2_slice_video_decode_accelerator.h"
+#include "content/common/gpu/media/v4l2_video_decode_accelerator.h"
+#include "ui/gl/gl_surface_egl.h"
+#endif
+#if defined(ARCH_CPU_X86_FAMILY)
+#include "content/common/gpu/media/vaapi_video_decode_accelerator.h"
+#include "ui/gl/gl_implementation.h"
+#endif
+#elif defined(OS_ANDROID)
+#include "content/common/gpu/media/android_video_decode_accelerator.h"
+#endif
+
+namespace content {
+
+namespace {
+static base::WeakPtr<gpu::gles2::GLES2Decoder> GetEmptyGLES2Decoder() {
+ NOTREACHED() << "VDA requests a GLES2Decoder, but client did not provide it";
+ return base::WeakPtr<gpu::gles2::GLES2Decoder>();
+}
+}
+
+// static
+scoped_ptr<GpuVideoDecodeAcceleratorFactoryImpl>
+GpuVideoDecodeAcceleratorFactoryImpl::Create(
+ const GetGLContextCallback& get_gl_context_cb,
+ const MakeGLContextCurrentCallback& make_context_current_cb,
+ const BindGLImageCallback& bind_image_cb) {
+ return make_scoped_ptr(new GpuVideoDecodeAcceleratorFactoryImpl(
+ get_gl_context_cb, make_context_current_cb, bind_image_cb,
+ base::Bind(&GetEmptyGLES2Decoder)));
+}
+
+// static
+scoped_ptr<GpuVideoDecodeAcceleratorFactoryImpl>
+GpuVideoDecodeAcceleratorFactoryImpl::CreateWithGLES2Decoder(
+ const GetGLContextCallback& get_gl_context_cb,
+ const MakeGLContextCurrentCallback& make_context_current_cb,
+ const BindGLImageCallback& bind_image_cb,
+ const GetGLES2DecoderCallback& get_gles2_decoder_cb) {
+ return make_scoped_ptr(new GpuVideoDecodeAcceleratorFactoryImpl(
+ get_gl_context_cb, make_context_current_cb, bind_image_cb,
+ get_gles2_decoder_cb));
+}
+
+// static
+gpu::VideoDecodeAcceleratorCapabilities
+GpuVideoDecodeAcceleratorFactoryImpl::GetDecoderCapabilities(
+ const gpu::GpuPreferences& gpu_preferences) {
+ media::VideoDecodeAccelerator::Capabilities capabilities;
+ if (gpu_preferences.disable_accelerated_video_decode)
+ return gpu::VideoDecodeAcceleratorCapabilities();
+
+ // Query VDAs for their capabilities and construct a set of supported
+ // profiles for current platform. This must be done in the same order as in
+ // CreateVDA(), as we currently preserve additional capabilities (such as
+ // resolutions supported) only for the first VDA supporting the given codec
+ // profile (instead of calculating a superset).
+ // TODO(posciak,henryhsu): improve this so that we choose a superset of
+ // resolutions and other supported profile parameters.
+#if defined(OS_WIN)
+ capabilities.supported_profiles =
+ DXVAVideoDecodeAccelerator::GetSupportedProfiles();
+#elif defined(OS_CHROMEOS)
+ media::VideoDecodeAccelerator::SupportedProfiles vda_profiles;
+#if defined(USE_V4L2_CODEC)
+ vda_profiles = V4L2VideoDecodeAccelerator::GetSupportedProfiles();
+ media::GpuVideoAcceleratorUtil::InsertUniqueDecodeProfiles(
+ vda_profiles, &capabilities.supported_profiles);
+ vda_profiles = V4L2SliceVideoDecodeAccelerator::GetSupportedProfiles();
+ media::GpuVideoAcceleratorUtil::InsertUniqueDecodeProfiles(
+ vda_profiles, &capabilities.supported_profiles);
+#endif
+#if defined(ARCH_CPU_X86_FAMILY)
+ vda_profiles = VaapiVideoDecodeAccelerator::GetSupportedProfiles();
+ media::GpuVideoAcceleratorUtil::InsertUniqueDecodeProfiles(
+ vda_profiles, &capabilities.supported_profiles);
+#endif
+#elif defined(OS_MACOSX)
+ capabilities.supported_profiles =
+ VTVideoDecodeAccelerator::GetSupportedProfiles();
+#elif defined(OS_ANDROID)
+ capabilities =
+ AndroidVideoDecodeAccelerator::GetCapabilities(gpu_preferences);
+#endif
+ return media::GpuVideoAcceleratorUtil::ConvertMediaToGpuDecodeCapabilities(
+ capabilities);
+}
+
+scoped_ptr<media::VideoDecodeAccelerator>
+GpuVideoDecodeAcceleratorFactoryImpl::CreateVDA(
+ media::VideoDecodeAccelerator::Client* client,
+ const media::VideoDecodeAccelerator::Config& config,
+ const gpu::GpuPreferences& gpu_preferences) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (gpu_preferences.disable_accelerated_video_decode)
+ return nullptr;
+
+ // Array of Create..VDA() function pointers, potentially usable on current
+ // platform. This list is ordered by priority, from most to least preferred,
+ // if applicable. This list must be in the same order as the querying order
+ // in GetDecoderCapabilities() above.
+ using CreateVDAFp = scoped_ptr<media::VideoDecodeAccelerator> (
+ GpuVideoDecodeAcceleratorFactoryImpl::*)(const gpu::GpuPreferences&)
+ const;
+ const CreateVDAFp create_vda_fps[] = {
+#if defined(OS_WIN)
+ &GpuVideoDecodeAcceleratorFactoryImpl::CreateDXVAVDA,
+#endif
+#if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
+ &GpuVideoDecodeAcceleratorFactoryImpl::CreateV4L2VDA,
+ &GpuVideoDecodeAcceleratorFactoryImpl::CreateV4L2SVDA,
+#endif
+#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
+ &GpuVideoDecodeAcceleratorFactoryImpl::CreateVaapiVDA,
+#endif
+#if defined(OS_MACOSX)
+ &GpuVideoDecodeAcceleratorFactoryImpl::CreateVTVDA,
+#endif
+#if defined(OS_ANDROID)
+ &GpuVideoDecodeAcceleratorFactoryImpl::CreateAndroidVDA,
+#endif
+ };
+
+ scoped_ptr<media::VideoDecodeAccelerator> vda;
+
+ for (const auto& create_vda_function : create_vda_fps) {
+ vda = (this->*create_vda_function)(gpu_preferences);
+ if (vda && vda->Initialize(config, client))
+ return vda;
+ }
+
+ return nullptr;
+}
+
+#if defined(OS_WIN)
+scoped_ptr<media::VideoDecodeAccelerator>
+GpuVideoDecodeAcceleratorFactoryImpl::CreateDXVAVDA(
+ const gpu::GpuPreferences& gpu_preferences) const {
+ scoped_ptr<media::VideoDecodeAccelerator> decoder;
+ if (base::win::GetVersion() >= base::win::VERSION_WIN7) {
+ DVLOG(0) << "Initializing DXVA HW decoder for windows.";
+ decoder.reset(new DXVAVideoDecodeAccelerator(
+ get_gl_context_cb_, make_context_current_cb_,
+ gpu_preferences.enable_accelerated_vpx_decode));
+ }
+ return decoder;
+}
+#endif
+
+#if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
+scoped_ptr<media::VideoDecodeAccelerator>
+GpuVideoDecodeAcceleratorFactoryImpl::CreateV4L2VDA(
+ const gpu::GpuPreferences& gpu_preferences) const {
+ scoped_ptr<media::VideoDecodeAccelerator> decoder;
+ scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder);
+ if (device.get()) {
+ decoder.reset(new V4L2VideoDecodeAccelerator(
+ gfx::GLSurfaceEGL::GetHardwareDisplay(), get_gl_context_cb_,
+ make_context_current_cb_, device));
+ }
+ return decoder;
+}
+
+scoped_ptr<media::VideoDecodeAccelerator>
+GpuVideoDecodeAcceleratorFactoryImpl::CreateV4L2SVDA(
+ const gpu::GpuPreferences& gpu_preferences) const {
+ scoped_ptr<media::VideoDecodeAccelerator> decoder;
+ scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder);
+ if (device.get()) {
+ decoder.reset(new V4L2SliceVideoDecodeAccelerator(
+ device, gfx::GLSurfaceEGL::GetHardwareDisplay(), get_gl_context_cb_,
+ make_context_current_cb_));
+ }
+ return decoder;
+}
+#endif
+
+#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
+scoped_ptr<media::VideoDecodeAccelerator>
+GpuVideoDecodeAcceleratorFactoryImpl::CreateVaapiVDA(
+ const gpu::GpuPreferences& gpu_preferences) const {
+ scoped_ptr<media::VideoDecodeAccelerator> decoder;
+ decoder.reset(new VaapiVideoDecodeAccelerator(make_context_current_cb_,
+ bind_image_cb_));
+ return decoder;
+}
+#endif
+
+#if defined(OS_MACOSX)
+scoped_ptr<media::VideoDecodeAccelerator>
+GpuVideoDecodeAcceleratorFactoryImpl::CreateVTVDA(
+ const gpu::GpuPreferences& gpu_preferences) const {
+ scoped_ptr<media::VideoDecodeAccelerator> decoder;
+ decoder.reset(
+ new VTVideoDecodeAccelerator(make_context_current_cb_, bind_image_cb_));
+ return decoder;
+}
+#endif
+
+#if defined(OS_ANDROID)
+scoped_ptr<media::VideoDecodeAccelerator>
+GpuVideoDecodeAcceleratorFactoryImpl::CreateAndroidVDA(
+ const gpu::GpuPreferences& gpu_preferences) const {
+ scoped_ptr<media::VideoDecodeAccelerator> decoder;
+ decoder.reset(new AndroidVideoDecodeAccelerator(make_context_current_cb_,
+ get_gles2_decoder_cb_));
+ return decoder;
+}
+#endif
+
+GpuVideoDecodeAcceleratorFactoryImpl::GpuVideoDecodeAcceleratorFactoryImpl(
+ const GetGLContextCallback& get_gl_context_cb,
+ const MakeGLContextCurrentCallback& make_context_current_cb,
+ const BindGLImageCallback& bind_image_cb,
+ const GetGLES2DecoderCallback& get_gles2_decoder_cb)
+ : get_gl_context_cb_(get_gl_context_cb),
+ make_context_current_cb_(make_context_current_cb),
+ bind_image_cb_(bind_image_cb),
+ get_gles2_decoder_cb_(get_gles2_decoder_cb) {}
+
+GpuVideoDecodeAcceleratorFactoryImpl::~GpuVideoDecodeAcceleratorFactoryImpl() {}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/media/gpu_video_decode_accelerator_factory_impl.h b/chromium/content/common/gpu/media/gpu_video_decode_accelerator_factory_impl.h
new file mode 100644
index 00000000000..2d4c10b8c32
--- /dev/null
+++ b/chromium/content/common/gpu/media/gpu_video_decode_accelerator_factory_impl.h
@@ -0,0 +1,123 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_GPU_MEDIA_GPU_VIDEO_DECODE_ACCELERATOR_FACTORY_IMPL_H_
+#define CONTENT_COMMON_GPU_MEDIA_GPU_VIDEO_DECODE_ACCELERATOR_FACTORY_IMPL_H_
+
+#include "base/callback.h"
+#include "base/threading/thread_checker.h"
+#include "content/common/content_export.h"
+#include "gpu/command_buffer/service/gpu_preferences.h"
+#include "gpu/config/gpu_info.h"
+#include "media/video/video_decode_accelerator.h"
+
+namespace gfx {
+class GLContext;
+}
+
+namespace gl {
+class GLImage;
+}
+
+namespace gpu {
+struct GpuPreferences;
+
+namespace gles2 {
+class GLES2Decoder;
+}
+}
+
+namespace content {
+
+// TODO(posciak): this class should be an implementation of
+// content::GpuVideoDecodeAcceleratorFactory, however that can only be achieved
+// once this is moved out of content/common, see crbug.com/597150 and related.
+class CONTENT_EXPORT GpuVideoDecodeAcceleratorFactoryImpl {
+public:
+ ~GpuVideoDecodeAcceleratorFactoryImpl();
+
+ // Return current GLContext.
+ using GetGLContextCallback = base::Callback<gfx::GLContext*(void)>;
+
+ // Make the applicable GL context current. To be called by VDAs before
+ // executing any GL calls. Return true on success, false otherwise.
+ using MakeGLContextCurrentCallback = base::Callback<bool(void)>;
+
+ // Bind |image| to |client_texture_id| given |texture_target|. If
+ // |can_bind_to_sampler| is true, then the image may be used as a sampler
+ // directly, otherwise a copy to a staging buffer is required.
+ // Return true on success, false otherwise.
+ using BindGLImageCallback =
+ base::Callback<bool(uint32_t client_texture_id,
+ uint32_t texture_target,
+ const scoped_refptr<gl::GLImage>& image,
+ bool can_bind_to_sampler)>;
+
+ // Return a WeakPtr to a GLES2Decoder, if one is available.
+ using GetGLES2DecoderCallback =
+ base::Callback<base::WeakPtr<gpu::gles2::GLES2Decoder>(void)>;
+
+ static scoped_ptr<GpuVideoDecodeAcceleratorFactoryImpl> Create(
+ const GetGLContextCallback& get_gl_context_cb,
+ const MakeGLContextCurrentCallback& make_context_current_cb,
+ const BindGLImageCallback& bind_image_cb);
+
+ static scoped_ptr<GpuVideoDecodeAcceleratorFactoryImpl>
+ CreateWithGLES2Decoder(
+ const GetGLContextCallback& get_gl_context_cb,
+ const MakeGLContextCurrentCallback& make_context_current_cb,
+ const BindGLImageCallback& bind_image_cb,
+ const GetGLES2DecoderCallback& get_gles2_decoder_cb);
+
+ static gpu::VideoDecodeAcceleratorCapabilities GetDecoderCapabilities(
+ const gpu::GpuPreferences& gpu_preferences);
+
+ scoped_ptr<media::VideoDecodeAccelerator> CreateVDA(
+ media::VideoDecodeAccelerator::Client* client,
+ const media::VideoDecodeAccelerator::Config& config,
+ const gpu::GpuPreferences& gpu_preferences);
+
+ private:
+ GpuVideoDecodeAcceleratorFactoryImpl(
+ const GetGLContextCallback& get_gl_context_cb,
+ const MakeGLContextCurrentCallback& make_context_current_cb,
+ const BindGLImageCallback& bind_image_cb,
+ const GetGLES2DecoderCallback& get_gles2_decoder_cb);
+
+#if defined(OS_WIN)
+ scoped_ptr<media::VideoDecodeAccelerator> CreateDXVAVDA(
+ const gpu::GpuPreferences& gpu_preferences) const;
+#endif
+#if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
+ scoped_ptr<media::VideoDecodeAccelerator> CreateV4L2VDA(
+ const gpu::GpuPreferences& gpu_preferences) const;
+ scoped_ptr<media::VideoDecodeAccelerator> CreateV4L2SVDA(
+ const gpu::GpuPreferences& gpu_preferences) const;
+#endif
+#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
+ scoped_ptr<media::VideoDecodeAccelerator> CreateVaapiVDA(
+ const gpu::GpuPreferences& gpu_preferences) const;
+#endif
+#if defined(OS_MACOSX)
+ scoped_ptr<media::VideoDecodeAccelerator> CreateVTVDA(
+ const gpu::GpuPreferences& gpu_preferences) const;
+#endif
+#if defined(OS_ANDROID)
+ scoped_ptr<media::VideoDecodeAccelerator> CreateAndroidVDA(
+ const gpu::GpuPreferences& gpu_preferences) const;
+#endif
+
+ const GetGLContextCallback get_gl_context_cb_;
+ const MakeGLContextCurrentCallback make_context_current_cb_;
+ const BindGLImageCallback bind_image_cb_;
+ const GetGLES2DecoderCallback get_gles2_decoder_cb_;
+
+ base::ThreadChecker thread_checker_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(GpuVideoDecodeAcceleratorFactoryImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_MEDIA_GPU_VIDEO_DECODE_ACCELERATOR_FACTORY_IMPL_H_
diff --git a/chromium/content/common/gpu/media/gpu_video_decode_accelerator_helpers.h b/chromium/content/common/gpu/media/gpu_video_decode_accelerator_helpers.h
new file mode 100644
index 00000000000..1717f592603
--- /dev/null
+++ b/chromium/content/common/gpu/media/gpu_video_decode_accelerator_helpers.h
@@ -0,0 +1,59 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_GPU_MEDIA_GPU_VIDEO_DECODE_ACCELERATOR_HELPERS_H_
+#define CONTENT_COMMON_GPU_MEDIA_GPU_VIDEO_DECODE_ACCELERATOR_HELPERS_H_
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+
+namespace gfx {
+class GLContext;
+}
+
+namespace gl {
+class GLImage;
+}
+
+namespace gpu {
+namespace gles2 {
+class GLES2Decoder;
+}
+}
+
+namespace content {
+
+// Helpers/defines for specific VideoDecodeAccelerator implementations in GPU
+// process. Which callbacks are required depends on the implementation.
+//
+// Note that these callbacks may be called more than once, and so must own/share
+// ownership of any objects bound to them.
+//
+// Unless specified otherwise, these callbacks must be executed on the GPU Child
+// thread (i.e. the thread which the VDAs are initialized on).
+
+// Return current GLContext.
+using GetGLContextCallback = base::Callback<gfx::GLContext*(void)>;
+
+// Make the applicable GL context current. To be called by VDAs before
+// executing any GL calls. Return true on success, false otherwise.
+using MakeGLContextCurrentCallback = base::Callback<bool(void)>;
+
+// Bind |image| to |client_texture_id| given |texture_target|. If
+// |can_bind_to_sampler| is true, then the image may be used as a sampler
+// directly, otherwise a copy to a staging buffer is required.
+// Return true on success, false otherwise.
+using BindGLImageCallback =
+ base::Callback<bool(uint32_t client_texture_id,
+ uint32_t texture_target,
+ const scoped_refptr<gl::GLImage>& image,
+ bool can_bind_to_sampler)>;
+
+// Return a WeakPtr to a GLES2Decoder, if one is available.
+using GetGLES2DecoderCallback =
+ base::Callback<base::WeakPtr<gpu::gles2::GLES2Decoder>(void)>;
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_MEDIA_GPU_VIDEO_DECODE_ACCELERATOR_HELPERS_H_
diff --git a/chromium/content/common/gpu/media/gpu_video_encode_accelerator.cc b/chromium/content/common/gpu/media/gpu_video_encode_accelerator.cc
index 7dd9a082b1d..7b1457e88f1 100644
--- a/chromium/content/common/gpu/media/gpu_video_encode_accelerator.cc
+++ b/chromium/content/common/gpu/media/gpu_video_encode_accelerator.cc
@@ -11,15 +11,15 @@
#include "base/numerics/safe_math.h"
#include "base/sys_info.h"
#include "build/build_config.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
-#include "content/common/gpu/gpu_channel.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "content/common/gpu/media/gpu_video_accelerator_util.h"
-#include "content/public/common/content_switches.h"
+#include "gpu/ipc/client/gpu_memory_buffer_impl.h"
+#include "gpu/ipc/service/gpu_channel.h"
+#include "gpu/ipc/service/gpu_channel_manager.h"
#include "ipc/ipc_message_macros.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/limits.h"
#include "media/base/video_frame.h"
+#include "media/gpu/ipc/common/gpu_video_accelerator_util.h"
+#include "media/gpu/ipc/common/media_messages.h"
#if defined(OS_CHROMEOS)
#if defined(USE_V4L2_CODEC)
@@ -30,20 +30,14 @@
#endif
#elif defined(OS_ANDROID) && defined(ENABLE_WEBRTC)
#include "content/common/gpu/media/android_video_encode_accelerator.h"
+#elif defined(OS_MACOSX)
+#include "content/common/gpu/media/vt_video_encode_accelerator_mac.h"
#endif
namespace content {
-namespace {
-
-// Allocation and destruction of buffer are done on the Browser process, so we
-// don't need to handle synchronization here.
-void DestroyGpuMemoryBuffer(const gpu::SyncToken& sync_token) {}
-
-} // namespace
-
static bool MakeDecoderContextCurrent(
- const base::WeakPtr<GpuCommandBufferStub> stub) {
+ const base::WeakPtr<gpu::GpuCommandBufferStub> stub) {
if (!stub) {
DLOG(ERROR) << "Stub is gone; won't MakeCurrent().";
return false;
@@ -57,8 +51,9 @@ static bool MakeDecoderContextCurrent(
return true;
}
-GpuVideoEncodeAccelerator::GpuVideoEncodeAccelerator(int32_t host_route_id,
- GpuCommandBufferStub* stub)
+GpuVideoEncodeAccelerator::GpuVideoEncodeAccelerator(
+ int32_t host_route_id,
+ gpu::GpuCommandBufferStub* stub)
: host_route_id_(host_route_id),
stub_(stub),
input_format_(media::PIXEL_FORMAT_UNKNOWN),
@@ -75,12 +70,11 @@ GpuVideoEncodeAccelerator::~GpuVideoEncodeAccelerator() {
DCHECK(!encoder_);
}
-void GpuVideoEncodeAccelerator::Initialize(
+bool GpuVideoEncodeAccelerator::Initialize(
media::VideoPixelFormat input_format,
const gfx::Size& input_visible_size,
media::VideoCodecProfile output_profile,
- uint32_t initial_bitrate,
- IPC::Message* init_done_msg) {
+ uint32_t initial_bitrate) {
DVLOG(2) << "GpuVideoEncodeAccelerator::Initialize(): "
"input_format=" << input_format
<< ", input_visible_size=" << input_visible_size.ToString()
@@ -88,11 +82,10 @@ void GpuVideoEncodeAccelerator::Initialize(
<< ", initial_bitrate=" << initial_bitrate;
DCHECK(!encoder_);
- if (!stub_->channel()->AddRoute(host_route_id_, this)) {
+ if (!stub_->channel()->AddRoute(host_route_id_, stub_->stream_id(), this)) {
DLOG(ERROR) << "GpuVideoEncodeAccelerator::Initialize(): "
"failed to add route";
- SendCreateEncoderReply(init_done_msg, false);
- return;
+ return false;
}
if (input_visible_size.width() > media::limits::kMaxDimension ||
@@ -101,12 +94,14 @@ void GpuVideoEncodeAccelerator::Initialize(
DLOG(ERROR) << "GpuVideoEncodeAccelerator::Initialize(): "
"input_visible_size " << input_visible_size.ToString()
<< " too large";
- SendCreateEncoderReply(init_done_msg, false);
- return;
+ return false;
}
- std::vector<GpuVideoEncodeAccelerator::CreateVEAFp>
- create_vea_fps = CreateVEAFps();
+ const gpu::GpuPreferences& gpu_preferences =
+ stub_->channel()->gpu_channel_manager()->gpu_preferences();
+
+ std::vector<GpuVideoEncodeAccelerator::CreateVEAFp> create_vea_fps =
+ CreateVEAFps(gpu_preferences);
// Try all possible encoders and use the first successful encoder.
for (size_t i = 0; i < create_vea_fps.size(); ++i) {
encoder_ = (*create_vea_fps[i])();
@@ -117,14 +112,13 @@ void GpuVideoEncodeAccelerator::Initialize(
this)) {
input_format_ = input_format;
input_visible_size_ = input_visible_size;
- SendCreateEncoderReply(init_done_msg, true);
- return;
+ return true;
}
}
encoder_.reset();
DLOG(ERROR)
<< "GpuVideoEncodeAccelerator::Initialize(): VEA initialization failed";
- SendCreateEncoderReply(init_done_msg, false);
+ return false;
}
bool GpuVideoEncodeAccelerator::OnMessageReceived(const IPC::Message& message) {
@@ -176,10 +170,11 @@ void GpuVideoEncodeAccelerator::OnWillDestroyStub() {
// static
gpu::VideoEncodeAcceleratorSupportedProfiles
-GpuVideoEncodeAccelerator::GetSupportedProfiles() {
+GpuVideoEncodeAccelerator::GetSupportedProfiles(
+ const gpu::GpuPreferences& gpu_preferences) {
media::VideoEncodeAccelerator::SupportedProfiles profiles;
- std::vector<GpuVideoEncodeAccelerator::CreateVEAFp>
- create_vea_fps = CreateVEAFps();
+ std::vector<GpuVideoEncodeAccelerator::CreateVEAFp> create_vea_fps =
+ CreateVEAFps(gpu_preferences);
for (size_t i = 0; i < create_vea_fps.size(); ++i) {
scoped_ptr<media::VideoEncodeAccelerator>
@@ -188,55 +183,73 @@ GpuVideoEncodeAccelerator::GetSupportedProfiles() {
continue;
media::VideoEncodeAccelerator::SupportedProfiles vea_profiles =
encoder->GetSupportedProfiles();
- GpuVideoAcceleratorUtil::InsertUniqueEncodeProfiles(
- vea_profiles, &profiles);
+ media::GpuVideoAcceleratorUtil::InsertUniqueEncodeProfiles(vea_profiles,
+ &profiles);
}
- return GpuVideoAcceleratorUtil::ConvertMediaToGpuEncodeProfiles(profiles);
+ return media::GpuVideoAcceleratorUtil::ConvertMediaToGpuEncodeProfiles(
+ profiles);
}
// static
std::vector<GpuVideoEncodeAccelerator::CreateVEAFp>
-GpuVideoEncodeAccelerator::CreateVEAFps() {
+GpuVideoEncodeAccelerator::CreateVEAFps(
+ const gpu::GpuPreferences& gpu_preferences) {
std::vector<GpuVideoEncodeAccelerator::CreateVEAFp> create_vea_fps;
+#if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
create_vea_fps.push_back(&GpuVideoEncodeAccelerator::CreateV4L2VEA);
- create_vea_fps.push_back(&GpuVideoEncodeAccelerator::CreateVaapiVEA);
- create_vea_fps.push_back(&GpuVideoEncodeAccelerator::CreateAndroidVEA);
+#endif
+#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
+ if (!gpu_preferences.disable_vaapi_accelerated_video_encode)
+ create_vea_fps.push_back(&GpuVideoEncodeAccelerator::CreateVaapiVEA);
+#endif
+#if defined(OS_ANDROID) && defined(ENABLE_WEBRTC)
+ if (!gpu_preferences.disable_web_rtc_hw_encoding)
+ create_vea_fps.push_back(&GpuVideoEncodeAccelerator::CreateAndroidVEA);
+#endif
+#if defined(OS_MACOSX)
+ create_vea_fps.push_back(&GpuVideoEncodeAccelerator::CreateVTVEA);
+#endif
return create_vea_fps;
}
+#if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
// static
scoped_ptr<media::VideoEncodeAccelerator>
GpuVideoEncodeAccelerator::CreateV4L2VEA() {
scoped_ptr<media::VideoEncodeAccelerator> encoder;
-#if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kEncoder);
if (device)
encoder.reset(new V4L2VideoEncodeAccelerator(device));
-#endif
return encoder;
}
+#endif
+#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
// static
scoped_ptr<media::VideoEncodeAccelerator>
GpuVideoEncodeAccelerator::CreateVaapiVEA() {
- scoped_ptr<media::VideoEncodeAccelerator> encoder;
-#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
- const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
- if (!cmd_line->HasSwitch(switches::kDisableVaapiAcceleratedVideoEncode))
- encoder.reset(new VaapiVideoEncodeAccelerator());
-#endif
- return encoder;
+ return make_scoped_ptr<media::VideoEncodeAccelerator>(
+ new VaapiVideoEncodeAccelerator());
}
+#endif
+#if defined(OS_ANDROID) && defined(ENABLE_WEBRTC)
// static
scoped_ptr<media::VideoEncodeAccelerator>
GpuVideoEncodeAccelerator::CreateAndroidVEA() {
- scoped_ptr<media::VideoEncodeAccelerator> encoder;
-#if defined(OS_ANDROID) && defined(ENABLE_WEBRTC)
- encoder.reset(new AndroidVideoEncodeAccelerator());
+ return make_scoped_ptr<media::VideoEncodeAccelerator>(
+ new AndroidVideoEncodeAccelerator());
+}
#endif
- return encoder;
+
+#if defined(OS_MACOSX)
+// static
+scoped_ptr<media::VideoEncodeAccelerator>
+GpuVideoEncodeAccelerator::CreateVTVEA() {
+ return make_scoped_ptr<media::VideoEncodeAccelerator>(
+ new VTVideoEncodeAccelerator());
}
+#endif
void GpuVideoEncodeAccelerator::OnEncode(
const AcceleratedVideoEncoderMsg_Encode_Params& params) {
@@ -315,79 +328,8 @@ void GpuVideoEncodeAccelerator::OnEncode2(
<< params.frame_id << ", size=" << params.size.ToString()
<< ", force_keyframe=" << params.force_keyframe << ", handle type="
<< params.gpu_memory_buffer_handles[0].type;
- DCHECK_EQ(media::PIXEL_FORMAT_I420, input_format_);
- DCHECK_EQ(media::VideoFrame::NumPlanes(input_format_),
- params.gpu_memory_buffer_handles.size());
-
- bool map_result = true;
- uint8_t* data[media::VideoFrame::kMaxPlanes];
- int32_t strides[media::VideoFrame::kMaxPlanes];
- ScopedVector<gfx::GpuMemoryBuffer> buffers;
- const auto& handles = params.gpu_memory_buffer_handles;
- for (size_t i = 0; i < handles.size(); ++i) {
- const size_t width =
- media::VideoFrame::Columns(i, input_format_, params.size.width());
- const size_t height =
- media::VideoFrame::Rows(i, input_format_, params.size.height());
- scoped_ptr<gfx::GpuMemoryBuffer> buffer =
- GpuMemoryBufferImpl::CreateFromHandle(
- handles[i], gfx::Size(width, height), gfx::BufferFormat::R_8,
- gfx::BufferUsage::GPU_READ_CPU_READ_WRITE,
- media::BindToCurrentLoop(base::Bind(&DestroyGpuMemoryBuffer)));
-
- // TODO(emircan): Refactor such that each frame is mapped once.
- // See http://crbug/536938.
- if (!buffer.get() || !buffer->Map()) {
- map_result = false;
- continue;
- }
-
- data[i] = reinterpret_cast<uint8_t*>(buffer->memory(0));
- strides[i] = buffer->stride(0);
- buffers.push_back(buffer.release());
- }
-
- if (!map_result) {
- DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnEncode2(): "
- << "failed to map buffers";
- NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
- return;
- }
-
- if (!encoder_)
- return;
-
- if (params.frame_id < 0) {
- DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnEncode2(): invalid frame_id="
- << params.frame_id;
- NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
- return;
- }
-
- scoped_refptr<media::VideoFrame> frame =
- media::VideoFrame::WrapExternalYuvData(
- input_format_,
- input_coded_size_,
- gfx::Rect(input_visible_size_),
- input_visible_size_,
- strides[media::VideoFrame::kYPlane],
- strides[media::VideoFrame::kUPlane],
- strides[media::VideoFrame::kVPlane],
- data[media::VideoFrame::kYPlane],
- data[media::VideoFrame::kUPlane],
- data[media::VideoFrame::kVPlane],
- params.timestamp);
- if (!frame.get()) {
- DLOG(ERROR) << "GpuVideoEncodeAccelerator::OnEncode2(): "
- << "could not create a frame";
- NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
- return;
- }
- frame->AddDestructionObserver(media::BindToCurrentLoop(
- base::Bind(&GpuVideoEncodeAccelerator::EncodeFrameFinished2,
- weak_this_factory_.GetWeakPtr(), params.frame_id,
- base::Passed(&buffers))));
- encoder_->Encode(frame, params.force_keyframe);
+ // Encoding GpuMemoryBuffer backed frames is not supported.
+ NOTREACHED();
}
void GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer(
@@ -439,25 +381,8 @@ void GpuVideoEncodeAccelerator::EncodeFrameFinished(
// Just let |shm| fall out of scope.
}
-void GpuVideoEncodeAccelerator::EncodeFrameFinished2(
- int32_t frame_id,
- ScopedVector<gfx::GpuMemoryBuffer> buffers) {
- // TODO(emircan): Consider calling Unmap() in dtor.
- for (const auto& buffer : buffers)
- buffer->Unmap();
- Send(new AcceleratedVideoEncoderHostMsg_NotifyInputDone(host_route_id_,
- frame_id));
- // Just let |buffers| fall out of scope.
-}
-
void GpuVideoEncodeAccelerator::Send(IPC::Message* message) {
stub_->channel()->Send(message);
}
-void GpuVideoEncodeAccelerator::SendCreateEncoderReply(IPC::Message* message,
- bool succeeded) {
- GpuCommandBufferMsg_CreateVideoEncoder::WriteReplyParams(message, succeeded);
- Send(message);
-}
-
} // namespace content
diff --git a/chromium/content/common/gpu/media/gpu_video_encode_accelerator.h b/chromium/content/common/gpu/media/gpu_video_encode_accelerator.h
index ecc14f28e99..2c2db293db3 100644
--- a/chromium/content/common/gpu/media/gpu_video_encode_accelerator.h
+++ b/chromium/content/common/gpu/media/gpu_video_encode_accelerator.h
@@ -13,8 +13,8 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
-#include "content/common/gpu/gpu_command_buffer_stub.h"
#include "gpu/config/gpu_info.h"
+#include "gpu/ipc/service/gpu_command_buffer_stub.h"
#include "ipc/ipc_listener.h"
#include "media/video/video_encode_accelerator.h"
#include "ui/gfx/geometry/size.h"
@@ -26,6 +26,10 @@ namespace base {
class SharedMemory;
} // namespace base
+namespace gpu {
+struct GpuPreferences;
+} // namespace gpu
+
namespace content {
// This class encapsulates the GPU process view of a VideoEncodeAccelerator,
@@ -34,18 +38,18 @@ namespace content {
class GpuVideoEncodeAccelerator
: public IPC::Listener,
public media::VideoEncodeAccelerator::Client,
- public GpuCommandBufferStub::DestructionObserver {
+ public gpu::GpuCommandBufferStub::DestructionObserver {
public:
- GpuVideoEncodeAccelerator(int32_t host_route_id, GpuCommandBufferStub* stub);
+ GpuVideoEncodeAccelerator(int32_t host_route_id,
+ gpu::GpuCommandBufferStub* stub);
~GpuVideoEncodeAccelerator() override;
// Initialize this accelerator with the given parameters and send
// |init_done_msg| when complete.
- void Initialize(media::VideoPixelFormat input_format,
+ bool Initialize(media::VideoPixelFormat input_format,
const gfx::Size& input_visible_size,
media::VideoCodecProfile output_profile,
- uint32_t initial_bitrate,
- IPC::Message* init_done_msg);
+ uint32_t initial_bitrate);
// IPC::Listener implementation
bool OnMessageReceived(const IPC::Message& message) override;
@@ -59,23 +63,34 @@ class GpuVideoEncodeAccelerator
bool key_frame) override;
void NotifyError(media::VideoEncodeAccelerator::Error error) override;
- // GpuCommandBufferStub::DestructionObserver implementation.
+ // gpu::GpuCommandBufferStub::DestructionObserver implementation.
void OnWillDestroyStub() override;
// Static query for supported profiles. This query calls the appropriate
// platform-specific version. The returned supported profiles vector will
// not contain duplicates.
- static gpu::VideoEncodeAcceleratorSupportedProfiles GetSupportedProfiles();
+ static gpu::VideoEncodeAcceleratorSupportedProfiles GetSupportedProfiles(
+ const gpu::GpuPreferences& gpu_preferences);
private:
typedef scoped_ptr<media::VideoEncodeAccelerator>(*CreateVEAFp)();
// Return a set of VEA Create function pointers applicable to the current
// platform.
- static std::vector<CreateVEAFp> CreateVEAFps();
+ static std::vector<CreateVEAFp> CreateVEAFps(
+ const gpu::GpuPreferences& gpu_preferences);
+#if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
static scoped_ptr<media::VideoEncodeAccelerator> CreateV4L2VEA();
+#endif
+#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
static scoped_ptr<media::VideoEncodeAccelerator> CreateVaapiVEA();
+#endif
+#if defined(OS_ANDROID) && defined(ENABLE_WEBRTC)
static scoped_ptr<media::VideoEncodeAccelerator> CreateAndroidVEA();
+#endif
+#if defined(OS_MACOSX)
+ static scoped_ptr<media::VideoEncodeAccelerator> CreateVTVEA();
+#endif
// IPC handlers, proxying media::VideoEncodeAccelerator for the renderer
// process.
@@ -90,19 +105,15 @@ class GpuVideoEncodeAccelerator
void EncodeFrameFinished(int32_t frame_id,
scoped_ptr<base::SharedMemory> shm);
- void EncodeFrameFinished2(int32_t frame_id,
- ScopedVector<gfx::GpuMemoryBuffer> buffers);
void Send(IPC::Message* message);
- // Helper for replying to the creation request.
- void SendCreateEncoderReply(IPC::Message* message, bool succeeded);
// Route ID to communicate with the host.
const uint32_t host_route_id_;
- // Unowned pointer to the underlying GpuCommandBufferStub. |this| is
+ // Unowned pointer to the underlying gpu::GpuCommandBufferStub. |this| is
// registered as a DestuctionObserver of |stub_| and will self-delete when
// |stub_| is destroyed.
- GpuCommandBufferStub* const stub_;
+ gpu::GpuCommandBufferStub* const stub_;
// Owned pointer to the underlying VideoEncodeAccelerator.
scoped_ptr<media::VideoEncodeAccelerator> encoder_;
diff --git a/chromium/content/common/gpu/media/media_channel.cc b/chromium/content/common/gpu/media/media_channel.cc
new file mode 100644
index 00000000000..7baeba075e4
--- /dev/null
+++ b/chromium/content/common/gpu/media/media_channel.cc
@@ -0,0 +1,145 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/gpu/media/media_channel.h"
+
+#include "content/common/gpu/media/gpu_video_decode_accelerator.h"
+#include "content/common/gpu/media/gpu_video_encode_accelerator.h"
+#include "gpu/ipc/service/gpu_channel.h"
+#include "media/gpu/ipc/common/media_messages.h"
+
+namespace content {
+
+namespace {
+
+void SendCreateJpegDecoderResult(
+ scoped_ptr<IPC::Message> reply_message,
+ scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
+ base::WeakPtr<gpu::GpuChannel> channel,
+ scoped_refptr<gpu::GpuChannelMessageFilter> filter,
+ bool result) {
+ GpuChannelMsg_CreateJpegDecoder::WriteReplyParams(reply_message.get(),
+ result);
+ if (io_task_runner->BelongsToCurrentThread()) {
+ filter->Send(reply_message.release());
+ } else if (channel) {
+ channel->Send(reply_message.release());
+ }
+}
+
+} // namespace
+
+class MediaChannelDispatchHelper {
+ public:
+ MediaChannelDispatchHelper(MediaChannel* channel, int32_t routing_id)
+ : channel_(channel), routing_id_(routing_id) {}
+
+ bool Send(IPC::Message* msg) { return channel_->Send(msg); }
+
+ void OnCreateVideoDecoder(const media::VideoDecodeAccelerator::Config& config,
+ int32_t decoder_route_id,
+ IPC::Message* reply_message) {
+ channel_->OnCreateVideoDecoder(routing_id_, config, decoder_route_id,
+ reply_message);
+ }
+
+ void OnCreateVideoEncoder(const media::CreateVideoEncoderParams& params,
+ IPC::Message* reply_message) {
+ channel_->OnCreateVideoEncoder(routing_id_, params, reply_message);
+ }
+
+ private:
+ MediaChannel* const channel_;
+ const int32_t routing_id_;
+ DISALLOW_COPY_AND_ASSIGN(MediaChannelDispatchHelper);
+};
+
+MediaChannel::MediaChannel(gpu::GpuChannel* channel) : channel_(channel) {}
+
+MediaChannel::~MediaChannel() {}
+
+bool MediaChannel::Send(IPC::Message* msg) {
+ return channel_->Send(msg);
+}
+
+bool MediaChannel::OnMessageReceived(const IPC::Message& message) {
+ MediaChannelDispatchHelper helper(this, message.routing_id());
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(MediaChannel, message)
+ IPC_MESSAGE_FORWARD_DELAY_REPLY(
+ GpuCommandBufferMsg_CreateVideoDecoder, &helper,
+ MediaChannelDispatchHelper::OnCreateVideoDecoder)
+ IPC_MESSAGE_FORWARD_DELAY_REPLY(
+ GpuCommandBufferMsg_CreateVideoEncoder, &helper,
+ MediaChannelDispatchHelper::OnCreateVideoEncoder)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(GpuChannelMsg_CreateJpegDecoder,
+ OnCreateJpegDecoder)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void MediaChannel::OnCreateJpegDecoder(int32_t route_id,
+ IPC::Message* reply_msg) {
+ scoped_ptr<IPC::Message> msg(reply_msg);
+ if (!jpeg_decoder_) {
+ jpeg_decoder_.reset(
+ new GpuJpegDecodeAccelerator(channel_, channel_->io_task_runner()));
+ }
+ jpeg_decoder_->AddClient(
+ route_id, base::Bind(&SendCreateJpegDecoderResult, base::Passed(&msg),
+ channel_->io_task_runner(), channel_->AsWeakPtr(),
+ make_scoped_refptr(channel_->filter())));
+}
+
+void MediaChannel::OnCreateVideoDecoder(
+ int32_t command_buffer_route_id,
+ const media::VideoDecodeAccelerator::Config& config,
+ int32_t decoder_route_id,
+ IPC::Message* reply_message) {
+ TRACE_EVENT0("gpu", "MediaChannel::OnCreateVideoDecoder");
+ gpu::GpuCommandBufferStub* stub =
+ channel_->LookupCommandBuffer(command_buffer_route_id);
+ if (!stub) {
+ reply_message->set_reply_error();
+ Send(reply_message);
+ return;
+ }
+ GpuVideoDecodeAccelerator* decoder = new GpuVideoDecodeAccelerator(
+ decoder_route_id, stub, stub->channel()->io_task_runner());
+ bool succeeded = decoder->Initialize(config);
+ GpuCommandBufferMsg_CreateVideoDecoder::WriteReplyParams(reply_message,
+ succeeded);
+ Send(reply_message);
+
+ // decoder is registered as a DestructionObserver of this stub and will
+ // self-delete during destruction of this stub.
+}
+
+void MediaChannel::OnCreateVideoEncoder(
+ int32_t command_buffer_route_id,
+ const media::CreateVideoEncoderParams& params,
+ IPC::Message* reply_message) {
+ TRACE_EVENT0("gpu", "MediaChannel::OnCreateVideoEncoder");
+ gpu::GpuCommandBufferStub* stub =
+ channel_->LookupCommandBuffer(command_buffer_route_id);
+ if (!stub) {
+ reply_message->set_reply_error();
+ Send(reply_message);
+ return;
+ }
+ GpuVideoEncodeAccelerator* encoder =
+ new GpuVideoEncodeAccelerator(params.encoder_route_id, stub);
+ bool succeeded =
+ encoder->Initialize(params.input_format, params.input_visible_size,
+ params.output_profile, params.initial_bitrate);
+ GpuCommandBufferMsg_CreateVideoEncoder::WriteReplyParams(reply_message,
+ succeeded);
+ Send(reply_message);
+
+ // encoder is registered as a DestructionObserver of this stub and will
+ // self-delete during destruction of this stub.
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/media/media_channel.h b/chromium/content/common/gpu/media/media_channel.h
new file mode 100644
index 00000000000..7cfe0378587
--- /dev/null
+++ b/chromium/content/common/gpu/media/media_channel.h
@@ -0,0 +1,57 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_GPU_MEDIA_MEDIA_CHANNEL_H_
+#define CONTENT_COMMON_GPU_MEDIA_MEDIA_CHANNEL_H_
+
+#include "content/common/gpu/media/gpu_jpeg_decode_accelerator.h"
+#include "ipc/ipc_listener.h"
+#include "ipc/ipc_sender.h"
+#include "media/video/video_decode_accelerator.h"
+
+namespace media {
+struct CreateVideoEncoderParams;
+}
+
+namespace gpu {
+class GpuChannel;
+class GpuCommandBufferStub;
+}
+
+namespace content {
+
+class MediaChannelDispatchHelper;
+
+class MediaChannel : public IPC::Listener, public IPC::Sender {
+ public:
+ explicit MediaChannel(gpu::GpuChannel* channel);
+ ~MediaChannel() override;
+
+ // IPC::Sender implementation:
+ bool Send(IPC::Message* msg) override;
+
+ private:
+ friend class MediaChannelDispatchHelper;
+
+ // IPC::Listener implementation:
+ bool OnMessageReceived(const IPC::Message& message) override;
+
+ // Message handlers.
+ void OnCreateJpegDecoder(int32_t route_id, IPC::Message* reply_msg);
+ void OnCreateVideoDecoder(int32_t command_buffer_route_id,
+ const media::VideoDecodeAccelerator::Config& config,
+ int32_t route_id,
+ IPC::Message* reply_message);
+ void OnCreateVideoEncoder(int32_t command_buffer_route_id,
+ const media::CreateVideoEncoderParams& params,
+ IPC::Message* reply_message);
+
+ gpu::GpuChannel* const channel_;
+ scoped_ptr<GpuJpegDecodeAccelerator> jpeg_decoder_;
+ DISALLOW_COPY_AND_ASSIGN(MediaChannel);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_MEDIA_MEDIA_CHANNEL_H_
diff --git a/chromium/content/common/gpu/media/media_service.cc b/chromium/content/common/gpu/media/media_service.cc
new file mode 100644
index 00000000000..89ec8b1fe50
--- /dev/null
+++ b/chromium/content/common/gpu/media/media_service.cc
@@ -0,0 +1,40 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/gpu/media/media_service.h"
+
+#include <utility>
+
+#include "content/common/gpu/media/gpu_video_decode_accelerator.h"
+#include "content/common/gpu/media/gpu_video_encode_accelerator.h"
+#include "content/common/gpu/media/media_channel.h"
+#include "gpu/ipc/service/gpu_channel.h"
+#include "gpu/ipc/service/gpu_channel_manager.h"
+#include "ipc/ipc_message_macros.h"
+#include "ipc/param_traits_macros.h"
+
+namespace content {
+
+MediaService::MediaService(gpu::GpuChannelManager* channel_manager)
+ : channel_manager_(channel_manager) {}
+
+MediaService::~MediaService() {}
+
+void MediaService::AddChannel(int32_t client_id) {
+ gpu::GpuChannel* gpu_channel = channel_manager_->LookupChannel(client_id);
+ DCHECK(gpu_channel);
+ scoped_ptr<MediaChannel> media_channel(new MediaChannel(gpu_channel));
+ gpu_channel->SetUnhandledMessageListener(media_channel.get());
+ media_channels_.set(client_id, std::move(media_channel));
+}
+
+void MediaService::RemoveChannel(int32_t client_id) {
+ media_channels_.erase(client_id);
+}
+
+void MediaService::DestroyAllChannels() {
+ media_channels_.clear();
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/media/media_service.h b/chromium/content/common/gpu/media/media_service.h
new file mode 100644
index 00000000000..15dca82260a
--- /dev/null
+++ b/chromium/content/common/gpu/media/media_service.h
@@ -0,0 +1,42 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_GPU_MEDIA_MEDIA_SERVICE_H_
+#define CONTENT_COMMON_GPU_MEDIA_MEDIA_SERVICE_H_
+
+#include <stdint.h>
+
+#include "base/containers/scoped_ptr_hash_map.h"
+#include "base/macros.h"
+#include "ipc/ipc_listener.h"
+#include "ipc/ipc_sender.h"
+#include "media/video/video_decode_accelerator.h"
+
+namespace gpu {
+class GpuChannel;
+class GpuChannelManager;
+}
+
+namespace content {
+
+class MediaChannel;
+
+class MediaService {
+ public:
+ MediaService(gpu::GpuChannelManager* channel_manager);
+ ~MediaService();
+
+ void AddChannel(int32_t client_id);
+ void RemoveChannel(int32_t client_id);
+ void DestroyAllChannels();
+
+ private:
+ gpu::GpuChannelManager* const channel_manager_;
+ base::ScopedPtrHashMap<int32_t, scoped_ptr<MediaChannel>> media_channels_;
+ DISALLOW_COPY_AND_ASSIGN(MediaService);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_MEDIA_MEDIA_SERVICE_H_
diff --git a/chromium/content/common/gpu/media/rendering_helper.cc b/chromium/content/common/gpu/media/rendering_helper.cc
index 85bfe0a840d..2a19428b2d0 100644
--- a/chromium/content/common/gpu/media/rendering_helper.cc
+++ b/chromium/content/common/gpu/media/rendering_helper.cc
@@ -160,6 +160,9 @@ RenderingHelperParams::RenderingHelperParams()
: rendering_fps(0), warm_up_iterations(0), render_as_thumbnails(false) {
}
+RenderingHelperParams::RenderingHelperParams(
+ const RenderingHelperParams& other) = default;
+
RenderingHelperParams::~RenderingHelperParams() {}
VideoFrameTexture::VideoFrameTexture(uint32_t texture_target,
@@ -179,6 +182,9 @@ RenderingHelper::RenderedVideo::RenderedVideo()
: is_flushing(false), frames_to_drop(0) {
}
+RenderingHelper::RenderedVideo::RenderedVideo(const RenderedVideo& other) =
+ default;
+
RenderingHelper::RenderedVideo::~RenderedVideo() {
}
@@ -665,12 +671,8 @@ void RenderingHelper::DeleteTexture(uint32_t texture_id) {
CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR);
}
-scoped_refptr<gfx::GLContext> RenderingHelper::GetGLContext() {
- return gl_context_;
-}
-
-void* RenderingHelper::GetGLContextHandle() {
- return gl_context_->GetHandle();
+gfx::GLContext* RenderingHelper::GetGLContext() {
+ return gl_context_.get();
}
void* RenderingHelper::GetGLDisplay() {
diff --git a/chromium/content/common/gpu/media/rendering_helper.h b/chromium/content/common/gpu/media/rendering_helper.h
index 8a6c28bd3f7..250d382ac61 100644
--- a/chromium/content/common/gpu/media/rendering_helper.h
+++ b/chromium/content/common/gpu/media/rendering_helper.h
@@ -54,6 +54,7 @@ class VideoFrameTexture : public base::RefCounted<VideoFrameTexture> {
struct RenderingHelperParams {
RenderingHelperParams();
+ RenderingHelperParams(const RenderingHelperParams& other);
~RenderingHelperParams();
// The rendering FPS.
@@ -135,10 +136,7 @@ class RenderingHelper {
void* GetGLDisplay();
// Get the GL context.
- scoped_refptr<gfx::GLContext> GetGLContext();
-
- // Get the platform specific handle to the OpenGL context.
- void* GetGLContextHandle();
+ gfx::GLContext* GetGLContext();
// Get rendered thumbnails as RGB.
// Sets alpha_solid to true if the alpha channel is entirely 0xff.
@@ -165,6 +163,7 @@ class RenderingHelper {
std::queue<scoped_refptr<VideoFrameTexture> > pending_frames;
RenderedVideo();
+ RenderedVideo(const RenderedVideo& other);
~RenderedVideo();
};
diff --git a/chromium/content/common/gpu/media/shared_memory_region.cc b/chromium/content/common/gpu/media/shared_memory_region.cc
new file mode 100644
index 00000000000..4ee6a242578
--- /dev/null
+++ b/chromium/content/common/gpu/media/shared_memory_region.cc
@@ -0,0 +1,42 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/sys_info.h"
+#include "content/common/gpu/media/shared_memory_region.h"
+
+namespace content {
+
+SharedMemoryRegion::SharedMemoryRegion(const base::SharedMemoryHandle& handle,
+ off_t offset,
+ size_t size,
+ bool read_only)
+ : shm_(handle, read_only),
+ offset_(offset),
+ size_(size),
+ alignment_size_(offset % base::SysInfo::VMAllocationGranularity()) {
+ DCHECK_GE(offset_, 0) << "Invalid offset: " << offset_;
+}
+
+SharedMemoryRegion::SharedMemoryRegion(
+ const media::BitstreamBuffer& bitstream_buffer,
+ bool read_only)
+ : SharedMemoryRegion(bitstream_buffer.handle(),
+ bitstream_buffer.offset(),
+ bitstream_buffer.size(),
+ read_only) {}
+
+bool SharedMemoryRegion::Map() {
+ if (offset_ < 0) {
+ DVLOG(1) << "Invalid offset: " << offset_;
+ return false;
+ }
+ return shm_.MapAt(offset_ - alignment_size_, size_ + alignment_size_);
+}
+
+void* SharedMemoryRegion::memory() {
+ int8_t* addr = reinterpret_cast<int8_t*>(shm_.memory());
+ return addr ? addr + alignment_size_ : nullptr;
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/media/shared_memory_region.h b/chromium/content/common/gpu/media/shared_memory_region.h
new file mode 100644
index 00000000000..f7c5db29982
--- /dev/null
+++ b/chromium/content/common/gpu/media/shared_memory_region.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_GPU_MEDIA_SHARED_MEMORY_REGION_H_
+#define CONTENT_COMMON_GPU_MEDIA_SHARED_MEMORY_REGION_H_
+
+#include "base/memory/shared_memory.h"
+#include "media/base/bitstream_buffer.h"
+
+namespace content {
+
+// Helper class to access a region of a SharedMemory. Different from
+// SharedMemory, in which the |offset| of function MapAt() must be aligned to
+// the value of |SysInfo::VMAllocationGranularity()|, the |offset| of a
+// SharedMemoryRegion needs not to be aligned, this class hides the details
+// and returns the mapped address of the given offset.
+class SharedMemoryRegion {
+ public:
+ // Creates a SharedMemoryRegion.
+ // The mapped memory region begins at |offset| bytes from the start of the
+ // shared memory and the length is |size|. It will take the ownership of
+ // the |handle| and release the resource when being destroyed. Different
+ // from SharedMemory, the |offset| needs not to be aligned to the value of
+ // |SysInfo::VMAllocationGranularity()|.
+ SharedMemoryRegion(const base::SharedMemoryHandle& handle,
+ off_t offset,
+ size_t size,
+ bool read_only);
+
+ // Creates a SharedMemoryRegion from the given |bistream_buffer|.
+ SharedMemoryRegion(const media::BitstreamBuffer& bitstream_buffer,
+ bool read_only);
+
+ // Maps the shared memory into the caller's address space.
+ // Return true on success, false otherwise.
+ bool Map();
+
+ // Gets a pointer to the mapped region if it has been mapped via Map().
+ // Returns |nullptr| if it is not mapped. The returned pointer points
+ // to the memory at the offset previously passed to the constructor.
+ void* memory();
+
+ size_t size() const { return size_; }
+
+ private:
+ base::SharedMemory shm_;
+ off_t offset_;
+ size_t size_;
+ size_t alignment_size_;
+
+ DISALLOW_COPY_AND_ASSIGN(SharedMemoryRegion);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_MEDIA_SHARED_MEMORY_REGION_H_
diff --git a/chromium/content/common/gpu/media/v4l2_image_processor.cc b/chromium/content/common/gpu/media/v4l2_image_processor.cc
index f0cf3977774..340a1484335 100644
--- a/chromium/content/common/gpu/media/v4l2_image_processor.cc
+++ b/chromium/content/common/gpu/media/v4l2_image_processor.cc
@@ -468,24 +468,22 @@ void V4L2ImageProcessor::Enqueue() {
}
}
- // TODO(posciak): Fix this to be non-Exynos specific.
- // Exynos GSC is liable to race conditions if more than one output buffer is
- // simultaneously enqueued, so enqueue just one.
- if (output_buffer_queued_count_ == 0 && !free_output_buffers_.empty()) {
- const int old_outputs_queued = output_buffer_queued_count_;
+ const int old_outputs_queued = output_buffer_queued_count_;
+ while (!free_output_buffers_.empty()) {
if (!EnqueueOutputRecord())
return;
- if (old_outputs_queued == 0 && output_buffer_queued_count_ != 0) {
- // We just started up a previously empty queue.
- // Queue state changed; signal interrupt.
- if (!device_->SetDevicePollInterrupt())
- return;
- // Start VIDIOC_STREAMON if we haven't yet.
- if (!output_streamon_) {
- __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
- IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type);
- output_streamon_ = true;
- }
+ }
+
+ if (old_outputs_queued == 0 && output_buffer_queued_count_ != 0) {
+ // We just started up a previously empty queue.
+ // Queue state changed; signal interrupt.
+ if (!device_->SetDevicePollInterrupt())
+ return;
+ // Start VIDIOC_STREAMON if we haven't yet.
+ if (!output_streamon_) {
+ __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+ IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type);
+ output_streamon_ = true;
}
}
DCHECK_LE(output_buffer_queued_count_, 1);
diff --git a/chromium/content/common/gpu/media/v4l2_jpeg_decode_accelerator.cc b/chromium/content/common/gpu/media/v4l2_jpeg_decode_accelerator.cc
index 06091a36b4d..0121eadbc09 100644
--- a/chromium/content/common/gpu/media/v4l2_jpeg_decode_accelerator.cc
+++ b/chromium/content/common/gpu/media/v4l2_jpeg_decode_accelerator.cc
@@ -112,10 +112,11 @@ V4L2JpegDecodeAccelerator::BufferRecord::~BufferRecord() {
}
V4L2JpegDecodeAccelerator::JobRecord::JobRecord(
- media::BitstreamBuffer bitstream_buffer,
+ const media::BitstreamBuffer& bitstream_buffer,
scoped_refptr<media::VideoFrame> video_frame)
- : bitstream_buffer(bitstream_buffer), out_frame(video_frame) {
-}
+ : bitstream_buffer_id(bitstream_buffer.id()),
+ shm(bitstream_buffer, true),
+ out_frame(video_frame) {}
V4L2JpegDecodeAccelerator::JobRecord::~JobRecord() {
}
@@ -233,6 +234,14 @@ void V4L2JpegDecodeAccelerator::Decode(
<< ", size=" << bitstream_buffer.size();
DCHECK(io_task_runner_->BelongsToCurrentThread());
+ if (bitstream_buffer.id() < 0) {
+ LOG(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id();
+ if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle()))
+ base::SharedMemory::CloseHandle(bitstream_buffer.handle());
+ PostNotifyError(bitstream_buffer.id(), INVALID_ARGUMENT);
+ return;
+ }
+
if (video_frame->format() != media::PIXEL_FORMAT_I420) {
PostNotifyError(bitstream_buffer.id(), UNSUPPORTED_JPEG);
return;
@@ -260,11 +269,9 @@ bool V4L2JpegDecodeAccelerator::IsSupported() {
void V4L2JpegDecodeAccelerator::DecodeTask(scoped_ptr<JobRecord> job_record) {
DCHECK(decoder_task_runner_->BelongsToCurrentThread());
- job_record->shm.reset(
- new base::SharedMemory(job_record->bitstream_buffer.handle(), true));
- if (!job_record->shm->Map(job_record->bitstream_buffer.size())) {
+ if (!job_record->shm.Map()) {
PLOG(ERROR) << __func__ << ": could not map bitstream_buffer";
- PostNotifyError(job_record->bitstream_buffer.id(), UNREADABLE_INPUT);
+ PostNotifyError(job_record->bitstream_buffer_id, UNREADABLE_INPUT);
return;
}
input_jobs_.push(make_linked_ptr(job_record.release()));
@@ -288,7 +295,7 @@ bool V4L2JpegDecodeAccelerator::ShouldRecreateInputBuffers() {
linked_ptr<JobRecord> job_record = input_jobs_.front();
// Check input buffer size is enough
return (input_buffer_map_.empty() ||
- (job_record->bitstream_buffer.size() + sizeof(kDefaultDhtSeg)) >
+ (job_record->shm.size() + sizeof(kDefaultDhtSeg)) >
input_buffer_map_.front().length);
}
@@ -333,8 +340,7 @@ bool V4L2JpegDecodeAccelerator::CreateInputBuffers() {
// The input image may miss huffman table. We didn't parse the image before,
// so we create more to avoid the situation of not enough memory.
// Reserve twice size to avoid recreating input buffer frequently.
- size_t reserve_size =
- (job_record->bitstream_buffer.size() + sizeof(kDefaultDhtSeg)) * 2;
+ size_t reserve_size = (job_record->shm.size() + sizeof(kDefaultDhtSeg)) * 2;
struct v4l2_format format;
memset(&format, 0, sizeof(format));
format.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
@@ -711,17 +717,16 @@ void V4L2JpegDecodeAccelerator::Dequeue() {
// V4L2_PIX_FMT_YUV420.
if (!CopyOutputImage(output_buffer_pixelformat_, output_record.address,
output_buffer_coded_size_, job_record->out_frame)) {
- PostNotifyError(job_record->bitstream_buffer.id(), PLATFORM_FAILURE);
+ PostNotifyError(job_record->bitstream_buffer_id, PLATFORM_FAILURE);
return;
}
DVLOG(3) << "Decoding finished, returning bitstream buffer, id="
- << job_record->bitstream_buffer.id();
+ << job_record->bitstream_buffer_id;
child_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&V4L2JpegDecodeAccelerator::VideoFrameReady, weak_ptr_,
- job_record->bitstream_buffer.id()));
+ FROM_HERE, base::Bind(&V4L2JpegDecodeAccelerator::VideoFrameReady,
+ weak_ptr_, job_record->bitstream_buffer_id));
}
}
}
@@ -819,10 +824,9 @@ bool V4L2JpegDecodeAccelerator::EnqueueInputRecord() {
DCHECK(!input_record.at_device);
// It will add default huffman segment if it's missing.
- if (!AddHuffmanTable(job_record->shm->memory(),
- job_record->bitstream_buffer.size(),
+ if (!AddHuffmanTable(job_record->shm.memory(), job_record->shm.size(),
input_record.address, input_record.length)) {
- PostNotifyError(job_record->bitstream_buffer.id(), PARSE_JPEG_FAILED);
+ PostNotifyError(job_record->bitstream_buffer_id, PARSE_JPEG_FAILED);
return false;
}
@@ -836,8 +840,9 @@ bool V4L2JpegDecodeAccelerator::EnqueueInputRecord() {
running_jobs_.push(job_record);
free_input_buffers_.pop_back();
- DVLOG(3) << __func__ << ": enqueued frame id="
- << job_record->bitstream_buffer.id() << " to device.";
+ DVLOG(3) << __func__
+ << ": enqueued frame id=" << job_record->bitstream_buffer_id
+ << " to device.";
return true;
}
diff --git a/chromium/content/common/gpu/media/v4l2_jpeg_decode_accelerator.h b/chromium/content/common/gpu/media/v4l2_jpeg_decode_accelerator.h
index 435808012ec..bef33b22c10 100644
--- a/chromium/content/common/gpu/media/v4l2_jpeg_decode_accelerator.h
+++ b/chromium/content/common/gpu/media/v4l2_jpeg_decode_accelerator.h
@@ -18,6 +18,7 @@
#include "base/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "content/common/content_export.h"
+#include "content/common/gpu/media/shared_memory_region.h"
#include "content/common/gpu/media/v4l2_device.h"
#include "media/base/bitstream_buffer.h"
#include "media/base/video_frame.h"
@@ -58,16 +59,16 @@ class CONTENT_EXPORT V4L2JpegDecodeAccelerator
// the time of submission we may not have one available (and don't need one
// to submit input to the device).
struct JobRecord {
- JobRecord(media::BitstreamBuffer bitstream_buffer,
+ JobRecord(const media::BitstreamBuffer& bitstream_buffer,
scoped_refptr<media::VideoFrame> video_frame);
~JobRecord();
- // Input image buffer.
- media::BitstreamBuffer bitstream_buffer;
+ // Input image buffer ID.
+ int32_t bitstream_buffer_id;
+ // Memory mapped from |bitstream_buffer|.
+ SharedMemoryRegion shm;
// Output frame buffer.
scoped_refptr<media::VideoFrame> out_frame;
- // Memory mapped from |bitstream_buffer|.
- scoped_ptr<base::SharedMemory> shm;
};
void EnqueueInput();
diff --git a/chromium/content/common/gpu/media/v4l2_slice_video_decode_accelerator.cc b/chromium/content/common/gpu/media/v4l2_slice_video_decode_accelerator.cc
index 4c3b724daa5..80087232b65 100644
--- a/chromium/content/common/gpu/media/v4l2_slice_video_decode_accelerator.cc
+++ b/chromium/content/common/gpu/media/v4l2_slice_video_decode_accelerator.cc
@@ -19,9 +19,11 @@
#include "base/macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/stringprintf.h"
+#include "content/common/gpu/media/shared_memory_region.h"
#include "content/common/gpu/media/v4l2_slice_video_decode_accelerator.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/media_switches.h"
+#include "ui/gl/gl_context.h"
#include "ui/gl/scoped_binders.h"
#define LOGF(level) LOG(level) << __FUNCTION__ << "(): "
@@ -169,14 +171,12 @@ struct V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef {
BitstreamBufferRef(
base::WeakPtr<VideoDecodeAccelerator::Client>& client,
const scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner,
- base::SharedMemory* shm,
- size_t size,
+ SharedMemoryRegion* shm,
int32_t input_id);
~BitstreamBufferRef();
const base::WeakPtr<VideoDecodeAccelerator::Client> client;
const scoped_refptr<base::SingleThreadTaskRunner> client_task_runner;
- const scoped_ptr<base::SharedMemory> shm;
- const size_t size;
+ const scoped_ptr<SharedMemoryRegion> shm;
off_t bytes_used;
const int32_t input_id;
};
@@ -184,13 +184,11 @@ struct V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef {
V4L2SliceVideoDecodeAccelerator::BitstreamBufferRef::BitstreamBufferRef(
base::WeakPtr<VideoDecodeAccelerator::Client>& client,
const scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner,
- base::SharedMemory* shm,
- size_t size,
+ SharedMemoryRegion* shm,
int32_t input_id)
: client(client),
client_task_runner(client_task_runner),
shm(shm),
- size(size),
bytes_used(0),
input_id(input_id) {}
@@ -382,15 +380,11 @@ V4L2VP8Picture::~V4L2VP8Picture() {
V4L2SliceVideoDecodeAccelerator::V4L2SliceVideoDecodeAccelerator(
const scoped_refptr<V4L2Device>& device,
EGLDisplay egl_display,
- EGLContext egl_context,
- const base::WeakPtr<Client>& io_client,
- const base::Callback<bool(void)>& make_context_current,
- const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
+ const GetGLContextCallback& get_gl_context_cb,
+ const MakeGLContextCurrentCallback& make_context_current_cb)
: input_planes_count_(0),
output_planes_count_(0),
child_task_runner_(base::ThreadTaskRunnerHandle::Get()),
- io_task_runner_(io_task_runner),
- io_client_(io_client),
device_(device),
decoder_thread_("V4L2SliceVideoDecodeAcceleratorThread"),
device_poll_thread_("V4L2SliceVideoDecodeAcceleratorDevicePollThread"),
@@ -406,9 +400,9 @@ V4L2SliceVideoDecodeAccelerator::V4L2SliceVideoDecodeAccelerator(
surface_set_change_pending_(false),
picture_clearing_count_(0),
pictures_assigned_(false, false),
- make_context_current_(make_context_current),
egl_display_(egl_display),
- egl_context_(egl_context),
+ get_gl_context_cb_(get_gl_context_cb),
+ make_context_current_cb_(make_context_current_cb),
weak_this_factory_(this) {
weak_this_ = weak_this_factory_.GetWeakPtr();
}
@@ -444,6 +438,11 @@ bool V4L2SliceVideoDecodeAccelerator::Initialize(const Config& config,
DCHECK(child_task_runner_->BelongsToCurrentThread());
DCHECK_EQ(state_, kUninitialized);
+ if (get_gl_context_cb_.is_null() || make_context_current_cb_.is_null()) {
+ NOTREACHED() << "GL callbacks are required for this VDA";
+ return false;
+ }
+
if (config.is_encrypted) {
NOTREACHED() << "Encrypted streams are not supported for this VDA";
return false;
@@ -459,6 +458,14 @@ bool V4L2SliceVideoDecodeAccelerator::Initialize(const Config& config,
client_ptr_factory_.reset(
new base::WeakPtrFactory<VideoDecodeAccelerator::Client>(client));
client_ = client_ptr_factory_->GetWeakPtr();
+ // If we haven't been set up to decode on separate thread via
+ // TryToSetupDecodeOnSeparateThread(), use the main thread/client for
+ // decode tasks.
+ if (!decode_task_runner_) {
+ decode_task_runner_ = child_task_runner_;
+ DCHECK(!decode_client_);
+ decode_client_ = client_;
+ }
video_profile_ = config.profile;
@@ -485,7 +492,7 @@ bool V4L2SliceVideoDecodeAccelerator::Initialize(const Config& config,
}
// We need the context to be initialized to query extensions.
- if (!make_context_current_.Run()) {
+ if (!make_context_current_cb_.Run()) {
LOG(ERROR) << "Initialize(): could not make context current";
return false;
}
@@ -750,7 +757,7 @@ bool V4L2SliceVideoDecodeAccelerator::CreateOutputBuffers() {
child_task_runner_->PostTask(
FROM_HERE,
base::Bind(&VideoDecodeAccelerator::Client::ProvidePictureBuffers,
- client_, num_pictures, coded_size_,
+ client_, num_pictures, 1, coded_size_,
device_->GetTextureTarget()));
// Wait for the client to call AssignPictureBuffers() on the Child thread.
@@ -1182,7 +1189,15 @@ void V4L2SliceVideoDecodeAccelerator::Decode(
const media::BitstreamBuffer& bitstream_buffer) {
DVLOGF(3) << "input_id=" << bitstream_buffer.id()
<< ", size=" << bitstream_buffer.size();
- DCHECK(io_task_runner_->BelongsToCurrentThread());
+ DCHECK(decode_task_runner_->BelongsToCurrentThread());
+
+ if (bitstream_buffer.id() < 0) {
+ LOG(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id();
+ if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle()))
+ base::SharedMemory::CloseHandle(bitstream_buffer.handle());
+ NOTIFY_ERROR(INVALID_ARGUMENT);
+ return;
+ }
decoder_thread_task_runner_->PostTask(
FROM_HERE, base::Bind(&V4L2SliceVideoDecodeAccelerator::DecodeTask,
@@ -1196,10 +1211,9 @@ void V4L2SliceVideoDecodeAccelerator::DecodeTask(
DCHECK(decoder_thread_task_runner_->BelongsToCurrentThread());
scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef(
- io_client_, io_task_runner_,
- new base::SharedMemory(bitstream_buffer.handle(), true),
- bitstream_buffer.size(), bitstream_buffer.id()));
- if (!bitstream_record->shm->Map(bitstream_buffer.size())) {
+ decode_client_, decode_task_runner_,
+ new SharedMemoryRegion(bitstream_buffer, true), bitstream_buffer.id()));
+ if (!bitstream_record->shm->Map()) {
LOGF(ERROR) << "Could not map bitstream_buffer";
NOTIFY_ERROR(UNREADABLE_INPUT);
return;
@@ -1231,7 +1245,7 @@ bool V4L2SliceVideoDecodeAccelerator::TrySetNewBistreamBuffer() {
const uint8_t* const data = reinterpret_cast<const uint8_t*>(
decoder_current_bitstream_buffer_->shm->memory());
- const size_t data_size = decoder_current_bitstream_buffer_->size;
+ const size_t data_size = decoder_current_bitstream_buffer_->shm->size();
decoder_->SetStream(data, data_size);
return true;
@@ -1442,8 +1456,9 @@ void V4L2SliceVideoDecodeAccelerator::AssignPictureBuffers(
return;
}
- if (!make_context_current_.Run()) {
- DLOG(ERROR) << "could not make context current";
+ gfx::GLContext* gl_context = get_gl_context_cb_.Run();
+ if (!gl_context || !make_context_current_cb_.Run()) {
+ DLOG(ERROR) << "No GL context";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
}
@@ -1481,13 +1496,10 @@ void V4L2SliceVideoDecodeAccelerator::AssignPictureBuffers(
DCHECK_EQ(output_record.picture_id, -1);
DCHECK_EQ(output_record.cleared, false);
- EGLImageKHR egl_image = device_->CreateEGLImage(egl_display_,
- egl_context_,
- buffers[i].texture_id(),
- coded_size_,
- i,
- output_format_fourcc_,
- output_planes_count_);
+ DCHECK_LE(1u, buffers[i].texture_ids().size());
+ EGLImageKHR egl_image = device_->CreateEGLImage(
+ egl_display_, gl_context->GetHandle(), buffers[i].texture_ids()[0],
+ buffers[i].size(), i, output_format_fourcc_, output_planes_count_);
if (egl_image == EGL_NO_IMAGE_KHR) {
LOGF(ERROR) << "Could not create EGLImageKHR";
// Ownership of EGLImages allocated in previous iterations of this loop
@@ -1511,7 +1523,7 @@ void V4L2SliceVideoDecodeAccelerator::ReusePictureBuffer(
DCHECK(child_task_runner_->BelongsToCurrentThread());
DVLOGF(4) << "picture_buffer_id=" << picture_buffer_id;
- if (!make_context_current_.Run()) {
+ if (!make_context_current_cb_.Run()) {
LOGF(ERROR) << "could not make context current";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
@@ -1587,7 +1599,7 @@ void V4L2SliceVideoDecodeAccelerator::FlushTask() {
// which - when reached - will trigger flush sequence.
decoder_input_queue_.push(
linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef(
- io_client_, io_task_runner_, nullptr, 0, kFlushBufferId)));
+ decode_client_, decode_task_runner_, nullptr, kFlushBufferId)));
return;
}
@@ -2501,12 +2513,14 @@ void V4L2SliceVideoDecodeAccelerator::SendPictureReady() {
bool cleared = pending_picture_ready_.front().cleared;
const media::Picture& picture = pending_picture_ready_.front().picture;
if (cleared && picture_clearing_count_ == 0) {
- DVLOGF(4) << "Posting picture ready to IO for: "
+ DVLOGF(4) << "Posting picture ready to decode task runner for: "
<< picture.picture_buffer_id();
- // This picture is cleared. Post it to IO thread to reduce latency. This
- // should be the case after all pictures are cleared at the beginning.
- io_task_runner_->PostTask(
- FROM_HERE, base::Bind(&Client::PictureReady, io_client_, picture));
+ // This picture is cleared. It can be posted to a thread different than
+ // the main GPU thread to reduce latency. This should be the case after
+ // all pictures are cleared at the beginning.
+ decode_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&Client::PictureReady, decode_client_, picture));
pending_picture_ready_.pop();
} else if (!cleared || resetting_or_flushing) {
DVLOGF(3) << "cleared=" << pending_picture_ready_.front().cleared
@@ -2544,7 +2558,11 @@ void V4L2SliceVideoDecodeAccelerator::PictureCleared() {
SendPictureReady();
}
-bool V4L2SliceVideoDecodeAccelerator::CanDecodeOnIOThread() {
+bool V4L2SliceVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread(
+ const base::WeakPtr<Client>& decode_client,
+ const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) {
+ decode_client_ = decode_client_;
+ decode_task_runner_ = decode_task_runner;
return true;
}
diff --git a/chromium/content/common/gpu/media/v4l2_slice_video_decode_accelerator.h b/chromium/content/common/gpu/media/v4l2_slice_video_decode_accelerator.h
index dd72eb7a6dd..cc11da302a1 100644
--- a/chromium/content/common/gpu/media/v4l2_slice_video_decode_accelerator.h
+++ b/chromium/content/common/gpu/media/v4l2_slice_video_decode_accelerator.h
@@ -19,6 +19,7 @@
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
#include "content/common/content_export.h"
+#include "content/common/gpu/media/gpu_video_decode_accelerator_helpers.h"
#include "content/common/gpu/media/h264_decoder.h"
#include "content/common/gpu/media/v4l2_device.h"
#include "content/common/gpu/media/vp8_decoder.h"
@@ -38,10 +39,8 @@ class CONTENT_EXPORT V4L2SliceVideoDecodeAccelerator
V4L2SliceVideoDecodeAccelerator(
const scoped_refptr<V4L2Device>& device,
EGLDisplay egl_display,
- EGLContext egl_context,
- const base::WeakPtr<Client>& io_client_,
- const base::Callback<bool(void)>& make_context_current,
- const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
+ const GetGLContextCallback& get_gl_context_cb,
+ const MakeGLContextCurrentCallback& make_context_current_cb);
~V4L2SliceVideoDecodeAccelerator() override;
// media::VideoDecodeAccelerator implementation.
@@ -53,7 +52,10 @@ class CONTENT_EXPORT V4L2SliceVideoDecodeAccelerator
void Flush() override;
void Reset() override;
void Destroy() override;
- bool CanDecodeOnIOThread() override;
+ bool TryToSetupDecodeOnSeparateThread(
+ const base::WeakPtr<Client>& decode_client,
+ const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner)
+ override;
static media::VideoDecodeAccelerator::SupportedProfiles
GetSupportedProfiles();
@@ -282,8 +284,8 @@ class CONTENT_EXPORT V4L2SliceVideoDecodeAccelerator
// GPU Child thread task runner.
const scoped_refptr<base::SingleThreadTaskRunner> child_task_runner_;
- // IO thread task runner.
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
+ // Task runner Decode() and PictureReady() run on.
+ scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner_;
// WeakPtr<> pointing to |this| for use in posting tasks from the decoder or
// device worker threads back to the child thread.
@@ -295,8 +297,8 @@ class CONTENT_EXPORT V4L2SliceVideoDecodeAccelerator
scoped_ptr<base::WeakPtrFactory<VideoDecodeAccelerator::Client>>
client_ptr_factory_;
base::WeakPtr<VideoDecodeAccelerator::Client> client_;
- // Callbacks to |io_client_| must be executed on |io_task_runner_|.
- base::WeakPtr<Client> io_client_;
+ // Callbacks to |decode_client_| must be executed on |decode_task_runner_|.
+ base::WeakPtr<Client> decode_client_;
// V4L2 device in use.
scoped_refptr<V4L2Device> device_;
@@ -381,12 +383,13 @@ class CONTENT_EXPORT V4L2SliceVideoDecodeAccelerator
// to avoid races with potential Reset requests.
base::WaitableEvent pictures_assigned_;
- // Make the GL context current callback.
- base::Callback<bool(void)> make_context_current_;
-
// EGL state
EGLDisplay egl_display_;
- EGLContext egl_context_;
+
+ // Callback to get current GLContext.
+ GetGLContextCallback get_gl_context_cb_;
+ // Callback to set the correct gl context.
+ MakeGLContextCurrentCallback make_context_current_cb_;
// The WeakPtrFactory for |weak_this_|.
base::WeakPtrFactory<V4L2SliceVideoDecodeAccelerator> weak_this_factory_;
diff --git a/chromium/content/common/gpu/media/v4l2_video_decode_accelerator.cc b/chromium/content/common/gpu/media/v4l2_video_decode_accelerator.cc
index f9311257ed7..719dbf7a80f 100644
--- a/chromium/content/common/gpu/media/v4l2_video_decode_accelerator.cc
+++ b/chromium/content/common/gpu/media/v4l2_video_decode_accelerator.cc
@@ -15,16 +15,17 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/macros.h"
-#include "base/memory/shared_memory.h"
#include "base/message_loop/message_loop.h"
#include "base/numerics/safe_conversions.h"
#include "base/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
+#include "content/common/gpu/media/shared_memory_region.h"
#include "content/common/gpu/media/v4l2_video_decode_accelerator.h"
#include "media/base/media_switches.h"
#include "media/filters/h264_parser.h"
#include "ui/gfx/geometry/rect.h"
+#include "ui/gl/gl_context.h"
#include "ui/gl/scoped_binders.h"
#define NOTIFY_ERROR(x) \
@@ -65,14 +66,12 @@ struct V4L2VideoDecodeAccelerator::BitstreamBufferRef {
BitstreamBufferRef(
base::WeakPtr<Client>& client,
scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner,
- base::SharedMemory* shm,
- size_t size,
+ scoped_ptr<SharedMemoryRegion> shm,
int32_t input_id);
~BitstreamBufferRef();
const base::WeakPtr<Client> client;
const scoped_refptr<base::SingleThreadTaskRunner> client_task_runner;
- const scoped_ptr<base::SharedMemory> shm;
- const size_t size;
+ const scoped_ptr<SharedMemoryRegion> shm;
size_t bytes_used;
const int32_t input_id;
};
@@ -94,13 +93,11 @@ struct V4L2VideoDecodeAccelerator::PictureRecord {
V4L2VideoDecodeAccelerator::BitstreamBufferRef::BitstreamBufferRef(
base::WeakPtr<Client>& client,
scoped_refptr<base::SingleThreadTaskRunner>& client_task_runner,
- base::SharedMemory* shm,
- size_t size,
+ scoped_ptr<SharedMemoryRegion> shm,
int32_t input_id)
: client(client),
client_task_runner(client_task_runner),
- shm(shm),
- size(size),
+ shm(std::move(shm)),
bytes_used(0),
input_id(input_id) {}
@@ -157,14 +154,10 @@ V4L2VideoDecodeAccelerator::PictureRecord::~PictureRecord() {}
V4L2VideoDecodeAccelerator::V4L2VideoDecodeAccelerator(
EGLDisplay egl_display,
- EGLContext egl_context,
- const base::WeakPtr<Client>& io_client,
- const base::Callback<bool(void)>& make_context_current,
- const scoped_refptr<V4L2Device>& device,
- const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
+ const GetGLContextCallback& get_gl_context_cb,
+ const MakeGLContextCurrentCallback& make_context_current_cb,
+ const scoped_refptr<V4L2Device>& device)
: child_task_runner_(base::ThreadTaskRunnerHandle::Get()),
- io_task_runner_(io_task_runner),
- io_client_(io_client),
decoder_thread_("V4L2DecoderThread"),
decoder_state_(kUninitialized),
device_(device),
@@ -184,9 +177,9 @@ V4L2VideoDecodeAccelerator::V4L2VideoDecodeAccelerator(
picture_clearing_count_(0),
pictures_assigned_(false, false),
device_poll_thread_("V4L2DevicePollThread"),
- make_context_current_(make_context_current),
egl_display_(egl_display),
- egl_context_(egl_context),
+ get_gl_context_cb_(get_gl_context_cb),
+ make_context_current_cb_(make_context_current_cb),
video_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN),
output_format_fourcc_(0),
weak_this_factory_(this) {
@@ -212,6 +205,11 @@ bool V4L2VideoDecodeAccelerator::Initialize(const Config& config,
DCHECK(child_task_runner_->BelongsToCurrentThread());
DCHECK_EQ(decoder_state_, kUninitialized);
+ if (get_gl_context_cb_.is_null() || make_context_current_cb_.is_null()) {
+ NOTREACHED() << "GL callbacks are required for this VDA";
+ return false;
+ }
+
if (config.is_encrypted) {
NOTREACHED() << "Encrypted streams are not supported for this VDA";
return false;
@@ -226,6 +224,14 @@ bool V4L2VideoDecodeAccelerator::Initialize(const Config& config,
client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client));
client_ = client_ptr_factory_->GetWeakPtr();
+ // If we haven't been set up to decode on separate thread via
+ // TryToSetupDecodeOnSeparateThread(), use the main thread/client for
+ // decode tasks.
+ if (!decode_task_runner_) {
+ decode_task_runner_ = child_task_runner_;
+ DCHECK(!decode_client_);
+ decode_client_ = client_;
+ }
video_profile_ = config.profile;
@@ -235,7 +241,7 @@ bool V4L2VideoDecodeAccelerator::Initialize(const Config& config,
}
// We need the context to be initialized to query extensions.
- if (!make_context_current_.Run()) {
+ if (!make_context_current_cb_.Run()) {
LOG(ERROR) << "Initialize(): could not make context current";
return false;
}
@@ -253,16 +259,9 @@ bool V4L2VideoDecodeAccelerator::Initialize(const Config& config,
const __u32 kCapsRequired = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps);
if ((caps.capabilities & kCapsRequired) != kCapsRequired) {
- // This cap combination is deprecated, but some older drivers may still be
- // returning it.
- const __u32 kCapsRequiredCompat = V4L2_CAP_VIDEO_CAPTURE_MPLANE |
- V4L2_CAP_VIDEO_OUTPUT_MPLANE |
- V4L2_CAP_STREAMING;
- if ((caps.capabilities & kCapsRequiredCompat) != kCapsRequiredCompat) {
- LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP"
- ", caps check failed: 0x" << std::hex << caps.capabilities;
- return false;
- }
+ LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP"
+ ", caps check failed: 0x" << std::hex << caps.capabilities;
+ return false;
}
if (!SetupFormats())
@@ -303,7 +302,15 @@ void V4L2VideoDecodeAccelerator::Decode(
const media::BitstreamBuffer& bitstream_buffer) {
DVLOG(1) << "Decode(): input_id=" << bitstream_buffer.id()
<< ", size=" << bitstream_buffer.size();
- DCHECK(io_task_runner_->BelongsToCurrentThread());
+ DCHECK(decode_task_runner_->BelongsToCurrentThread());
+
+ if (bitstream_buffer.id() < 0) {
+ LOG(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id();
+ if (base::SharedMemory::IsHandleValid(bitstream_buffer.handle()))
+ base::SharedMemory::CloseHandle(bitstream_buffer.handle());
+ NOTIFY_ERROR(INVALID_ARGUMENT);
+ return;
+ }
// DecodeTask() will take care of running a DecodeBufferTask().
decoder_thread_.message_loop()->PostTask(FROM_HERE, base::Bind(
@@ -327,7 +334,8 @@ void V4L2VideoDecodeAccelerator::AssignPictureBuffers(
return;
}
- if (!make_context_current_.Run()) {
+ gfx::GLContext* gl_context = get_gl_context_cb_.Run();
+ if (!gl_context || !make_context_current_cb_.Run()) {
LOG(ERROR) << "AssignPictureBuffers(): could not make context current";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
@@ -365,14 +373,11 @@ void V4L2VideoDecodeAccelerator::AssignPictureBuffers(
DCHECK_EQ(output_record.egl_sync, EGL_NO_SYNC_KHR);
DCHECK_EQ(output_record.picture_id, -1);
DCHECK_EQ(output_record.cleared, false);
+ DCHECK_LE(1u, buffers[i].texture_ids().size());
- EGLImageKHR egl_image = device_->CreateEGLImage(egl_display_,
- egl_context_,
- buffers[i].texture_id(),
- coded_size_,
- i,
- output_format_fourcc_,
- output_planes_count_);
+ EGLImageKHR egl_image = device_->CreateEGLImage(
+ egl_display_, gl_context->GetHandle(), buffers[i].texture_ids()[0],
+ coded_size_, i, output_format_fourcc_, output_planes_count_);
if (egl_image == EGL_NO_IMAGE_KHR) {
LOG(ERROR) << "AssignPictureBuffers(): could not create EGLImageKHR";
// Ownership of EGLImages allocated in previous iterations of this loop
@@ -397,7 +402,7 @@ void V4L2VideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_buffer_id) {
// Must be run on child thread, as we'll insert a sync in the EGL context.
DCHECK(child_task_runner_->BelongsToCurrentThread());
- if (!make_context_current_.Run()) {
+ if (!make_context_current_cb_.Run()) {
LOG(ERROR) << "ReusePictureBuffer(): could not make context current";
NOTIFY_ERROR(PLATFORM_FAILURE);
return;
@@ -458,7 +463,13 @@ void V4L2VideoDecodeAccelerator::Destroy() {
delete this;
}
-bool V4L2VideoDecodeAccelerator::CanDecodeOnIOThread() { return true; }
+bool V4L2VideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread(
+ const base::WeakPtr<Client>& decode_client,
+ const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) {
+ decode_client_ = decode_client_;
+ decode_task_runner_ = decode_task_runner;
+ return true;
+}
// static
media::VideoDecodeAccelerator::SupportedProfiles
@@ -480,10 +491,11 @@ void V4L2VideoDecodeAccelerator::DecodeTask(
bitstream_buffer.id());
scoped_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef(
- io_client_, io_task_runner_,
- new base::SharedMemory(bitstream_buffer.handle(), true),
- bitstream_buffer.size(), bitstream_buffer.id()));
- if (!bitstream_record->shm->Map(bitstream_buffer.size())) {
+ decode_client_, decode_task_runner_,
+ scoped_ptr<SharedMemoryRegion>(
+ new SharedMemoryRegion(bitstream_buffer, true)),
+ bitstream_buffer.id()));
+ if (!bitstream_record->shm->Map()) {
LOG(ERROR) << "Decode(): could not map bitstream_buffer";
NOTIFY_ERROR(UNREADABLE_INPUT);
return;
@@ -542,54 +554,51 @@ void V4L2VideoDecodeAccelerator::DecodeBufferTask() {
// Setup to use the next buffer.
decoder_current_bitstream_buffer_.reset(buffer_ref.release());
decoder_input_queue_.pop();
- DVLOG(3) << "DecodeBufferTask(): reading input_id="
- << decoder_current_bitstream_buffer_->input_id
- << ", addr=" << (decoder_current_bitstream_buffer_->shm ?
- decoder_current_bitstream_buffer_->shm->memory() :
- NULL)
- << ", size=" << decoder_current_bitstream_buffer_->size;
+ const auto& shm = decoder_current_bitstream_buffer_->shm;
+ if (shm) {
+ DVLOG(3) << "DecodeBufferTask(): reading input_id="
+ << decoder_current_bitstream_buffer_->input_id
+ << ", addr=" << shm->memory() << ", size=" << shm->size();
+ } else {
+ DCHECK_EQ(decoder_current_bitstream_buffer_->input_id, kFlushBufferId);
+ DVLOG(3) << "DecodeBufferTask(): reading input_id=kFlushBufferId";
+ }
}
bool schedule_task = false;
- const size_t size = decoder_current_bitstream_buffer_->size;
size_t decoded_size = 0;
- if (size == 0) {
- const int32_t input_id = decoder_current_bitstream_buffer_->input_id;
- if (input_id >= 0) {
- // This is a buffer queued from the client that has zero size. Skip.
+ const auto& shm = decoder_current_bitstream_buffer_->shm;
+ if (!shm) {
+ // This is a dummy buffer, queued to flush the pipe. Flush.
+ DCHECK_EQ(decoder_current_bitstream_buffer_->input_id, kFlushBufferId);
+ // Enqueue a buffer guaranteed to be empty. To do that, we flush the
+ // current input, enqueue no data to the next frame, then flush that down.
+ schedule_task = true;
+ if (decoder_current_input_buffer_ != -1 &&
+ input_buffer_map_[decoder_current_input_buffer_].input_id !=
+ kFlushBufferId)
+ schedule_task = FlushInputFrame();
+
+ if (schedule_task && AppendToInputFrame(NULL, 0) && FlushInputFrame()) {
+ DVLOG(2) << "DecodeBufferTask(): enqueued flush buffer";
+ decoder_partial_frame_pending_ = false;
schedule_task = true;
} else {
- // This is a buffer of zero size, queued to flush the pipe. Flush.
- DCHECK_EQ(decoder_current_bitstream_buffer_->shm.get(),
- static_cast<base::SharedMemory*>(NULL));
- // Enqueue a buffer guaranteed to be empty. To do that, we flush the
- // current input, enqueue no data to the next frame, then flush that down.
- schedule_task = true;
- if (decoder_current_input_buffer_ != -1 &&
- input_buffer_map_[decoder_current_input_buffer_].input_id !=
- kFlushBufferId)
- schedule_task = FlushInputFrame();
-
- if (schedule_task && AppendToInputFrame(NULL, 0) && FlushInputFrame()) {
- DVLOG(2) << "DecodeBufferTask(): enqueued flush buffer";
- decoder_partial_frame_pending_ = false;
- schedule_task = true;
- } else {
- // If we failed to enqueue the empty buffer (due to pipeline
- // backpressure), don't advance the bitstream buffer queue, and don't
- // schedule the next task. This bitstream buffer queue entry will get
- // reprocessed when the pipeline frees up.
- schedule_task = false;
- }
+ // If we failed to enqueue the empty buffer (due to pipeline
+ // backpressure), don't advance the bitstream buffer queue, and don't
+ // schedule the next task. This bitstream buffer queue entry will get
+ // reprocessed when the pipeline frees up.
+ schedule_task = false;
}
+ } else if (shm->size() == 0) {
+ // This is a buffer queued from the client that has zero size. Skip.
+ schedule_task = true;
} else {
// This is a buffer queued from the client, with actual contents. Decode.
const uint8_t* const data =
- reinterpret_cast<const uint8_t*>(
- decoder_current_bitstream_buffer_->shm->memory()) +
+ reinterpret_cast<const uint8_t*>(shm->memory()) +
decoder_current_bitstream_buffer_->bytes_used;
const size_t data_size =
- decoder_current_bitstream_buffer_->size -
- decoder_current_bitstream_buffer_->bytes_used;
+ shm->size() - decoder_current_bitstream_buffer_->bytes_used;
if (!AdvanceFrameFragment(data, data_size, &decoded_size)) {
NOTIFY_ERROR(UNREADABLE_INPUT);
return;
@@ -618,8 +627,8 @@ void V4L2VideoDecodeAccelerator::DecodeBufferTask() {
if (schedule_task) {
decoder_current_bitstream_buffer_->bytes_used += decoded_size;
- if (decoder_current_bitstream_buffer_->bytes_used ==
- decoder_current_bitstream_buffer_->size) {
+ if ((shm ? shm->size() : 0) ==
+ decoder_current_bitstream_buffer_->bytes_used) {
// Our current bitstream buffer is done; return it.
int32_t input_id = decoder_current_bitstream_buffer_->input_id;
DVLOG(3) << "DecodeBufferTask(): finished input_id=" << input_id;
@@ -1023,14 +1032,7 @@ bool V4L2VideoDecodeAccelerator::DequeueResolutionChangeEvent() {
while (device_->Ioctl(VIDIOC_DQEVENT, &ev) == 0) {
if (ev.type == V4L2_EVENT_SOURCE_CHANGE) {
- uint32_t changes = ev.u.src_change.changes;
- // We used to define source change was always resolution change. The union
- // |ev.u| is not used and it is zero by default. When using the upstream
- // version of the resolution event change, we also need to check
- // |ev.u.src_change.changes| to know what is changed. For API backward
- // compatibility, event is treated as resolution change when all bits in
- // |ev.u.src_change.changes| are cleared.
- if (changes == 0 || (changes & V4L2_EVENT_SRC_CH_RESOLUTION)) {
+ if (ev.u.src_change.changes & V4L2_EVENT_SRC_CH_RESOLUTION) {
DVLOG(3)
<< "DequeueResolutionChangeEvent(): got resolution change event.";
return true;
@@ -1282,7 +1284,7 @@ void V4L2VideoDecodeAccelerator::FlushTask() {
// Queue up an empty buffer -- this triggers the flush.
decoder_input_queue_.push(
linked_ptr<BitstreamBufferRef>(new BitstreamBufferRef(
- io_client_, io_task_runner_, NULL, 0, kFlushBufferId)));
+ decode_client_, decode_task_runner_, nullptr, kFlushBufferId)));
decoder_flushing_ = true;
SendPictureReady(); // Send all pending PictureReady.
@@ -1886,9 +1888,9 @@ bool V4L2VideoDecodeAccelerator::CreateOutputBuffers() {
<< "buffer_count=" << buffer_count
<< ", coded_size=" << coded_size_.ToString();
child_task_runner_->PostTask(
- FROM_HERE, base::Bind(&Client::ProvidePictureBuffers, client_,
- buffer_count, coded_size_,
- device_->GetTextureTarget()));
+ FROM_HERE,
+ base::Bind(&Client::ProvidePictureBuffers, client_, buffer_count, 1,
+ coded_size_, device_->GetTextureTarget()));
// Wait for the client to call AssignPictureBuffers() on the Child thread.
// We do this, because if we continue decoding without finishing buffer
@@ -2005,10 +2007,12 @@ void V4L2VideoDecodeAccelerator::SendPictureReady() {
bool cleared = pending_picture_ready_.front().cleared;
const media::Picture& picture = pending_picture_ready_.front().picture;
if (cleared && picture_clearing_count_ == 0) {
- // This picture is cleared. Post it to IO thread to reduce latency. This
- // should be the case after all pictures are cleared at the beginning.
- io_task_runner_->PostTask(
- FROM_HERE, base::Bind(&Client::PictureReady, io_client_, picture));
+ // This picture is cleared. It can be posted to a thread different than
+ // the main GPU thread to reduce latency. This should be the case after
+ // all pictures are cleared at the beginning.
+ decode_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&Client::PictureReady, decode_client_, picture));
pending_picture_ready_.pop();
} else if (!cleared || resetting_or_flushing) {
DVLOG(3) << "SendPictureReady()"
diff --git a/chromium/content/common/gpu/media/v4l2_video_decode_accelerator.h b/chromium/content/common/gpu/media/v4l2_video_decode_accelerator.h
index 3d06665e344..cb749569241 100644
--- a/chromium/content/common/gpu/media/v4l2_video_decode_accelerator.h
+++ b/chromium/content/common/gpu/media/v4l2_video_decode_accelerator.h
@@ -23,6 +23,7 @@
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread.h"
#include "content/common/content_export.h"
+#include "content/common/gpu/media/gpu_video_decode_accelerator_helpers.h"
#include "content/common/gpu/media/v4l2_device.h"
#include "media/base/limits.h"
#include "media/base/video_decoder_config.h"
@@ -78,11 +79,9 @@ class CONTENT_EXPORT V4L2VideoDecodeAccelerator
public:
V4L2VideoDecodeAccelerator(
EGLDisplay egl_display,
- EGLContext egl_context,
- const base::WeakPtr<Client>& io_client_,
- const base::Callback<bool(void)>& make_context_current,
- const scoped_refptr<V4L2Device>& device,
- const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
+ const GetGLContextCallback& get_gl_context_cb,
+ const MakeGLContextCurrentCallback& make_context_current_cb,
+ const scoped_refptr<V4L2Device>& device);
~V4L2VideoDecodeAccelerator() override;
// media::VideoDecodeAccelerator implementation.
@@ -95,7 +94,10 @@ class CONTENT_EXPORT V4L2VideoDecodeAccelerator
void Flush() override;
void Reset() override;
void Destroy() override;
- bool CanDecodeOnIOThread() override;
+ bool TryToSetupDecodeOnSeparateThread(
+ const base::WeakPtr<Client>& decode_client,
+ const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner)
+ override;
static media::VideoDecodeAccelerator::SupportedProfiles
GetSupportedProfiles();
@@ -316,8 +318,8 @@ class CONTENT_EXPORT V4L2VideoDecodeAccelerator
// Our original calling task runner for the child thread.
scoped_refptr<base::SingleThreadTaskRunner> child_task_runner_;
- // Task runner of the IO thread.
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
+ // Task runner Decode() and PictureReady() run on.
+ scoped_refptr<base::SingleThreadTaskRunner> decode_task_runner_;
// WeakPtr<> pointing to |this| for use in posting tasks from the decoder or
// device worker threads back to the child thread. Because the worker threads
@@ -332,8 +334,8 @@ class CONTENT_EXPORT V4L2VideoDecodeAccelerator
// child_task_runner_.
scoped_ptr<base::WeakPtrFactory<Client> > client_ptr_factory_;
base::WeakPtr<Client> client_;
- // Callbacks to |io_client_| must be executed on |io_task_runner_|.
- base::WeakPtr<Client> io_client_;
+ // Callbacks to |decode_client_| must be executed on |decode_task_runner_|.
+ base::WeakPtr<Client> decode_client_;
//
// Decoder state, owned and operated by decoder_thread_.
@@ -438,12 +440,13 @@ class CONTENT_EXPORT V4L2VideoDecodeAccelerator
// Other state, held by the child (main) thread.
//
- // Make our context current before running any EGL entry points.
- base::Callback<bool(void)> make_context_current_;
-
// EGL state
EGLDisplay egl_display_;
- EGLContext egl_context_;
+
+ // Callback to get current GLContext.
+ GetGLContextCallback get_gl_context_cb_;
+ // Callback to set the correct gl context.
+ MakeGLContextCurrentCallback make_context_current_cb_;
// The codec we'll be decoding for.
media::VideoCodecProfile video_profile_;
diff --git a/chromium/content/common/gpu/media/v4l2_video_encode_accelerator.cc b/chromium/content/common/gpu/media/v4l2_video_encode_accelerator.cc
index 98f4e48db35..d724d8dea40 100644
--- a/chromium/content/common/gpu/media/v4l2_video_encode_accelerator.cc
+++ b/chromium/content/common/gpu/media/v4l2_video_encode_accelerator.cc
@@ -17,8 +17,8 @@
#include "base/numerics/safe_conversions.h"
#include "base/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
+#include "content/common/gpu/media/shared_memory_region.h"
#include "content/common/gpu/media/v4l2_video_encode_accelerator.h"
-#include "content/public/common/content_switches.h"
#include "media/base/bitstream_buffer.h"
#define NOTIFY_ERROR(x) \
@@ -51,13 +51,10 @@
namespace content {
struct V4L2VideoEncodeAccelerator::BitstreamBufferRef {
- BitstreamBufferRef(int32_t id,
- scoped_ptr<base::SharedMemory> shm,
- size_t size)
- : id(id), shm(std::move(shm)), size(size) {}
+ BitstreamBufferRef(int32_t id, scoped_ptr<SharedMemoryRegion> shm)
+ : id(id), shm(std::move(shm)) {}
const int32_t id;
- const scoped_ptr<base::SharedMemory> shm;
- const size_t size;
+ const scoped_ptr<SharedMemoryRegion> shm;
};
V4L2VideoEncodeAccelerator::InputRecord::InputRecord() : at_device(false) {
@@ -128,20 +125,13 @@ bool V4L2VideoEncodeAccelerator::Initialize(
const __u32 kCapsRequired = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps);
if ((caps.capabilities & kCapsRequired) != kCapsRequired) {
- // This cap combination is deprecated, but some older drivers may still be
- // returning it.
- const __u32 kCapsRequiredCompat = V4L2_CAP_VIDEO_CAPTURE_MPLANE |
- V4L2_CAP_VIDEO_OUTPUT_MPLANE |
- V4L2_CAP_STREAMING;
- if ((caps.capabilities & kCapsRequiredCompat) != kCapsRequiredCompat) {
- LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP: "
- "caps check failed: 0x" << std::hex << caps.capabilities;
- return false;
- }
+ LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP: "
+ "caps check failed: 0x" << std::hex << caps.capabilities;
+ return false;
}
if (!SetFormats(input_format, output_profile)) {
- LOG(ERROR) << "Failed setting up formats";
+ DLOG(ERROR) << "Failed setting up formats";
return false;
}
@@ -231,15 +221,14 @@ void V4L2VideoEncodeAccelerator::UseOutputBitstreamBuffer(
return;
}
- scoped_ptr<base::SharedMemory> shm(
- new base::SharedMemory(buffer.handle(), false));
- if (!shm->Map(buffer.size())) {
+ scoped_ptr<SharedMemoryRegion> shm(new SharedMemoryRegion(buffer, false));
+ if (!shm->Map()) {
NOTIFY_ERROR(kPlatformFailureError);
return;
}
scoped_ptr<BitstreamBufferRef> buffer_ref(
- new BitstreamBufferRef(buffer.id(), std::move(shm), buffer.size()));
+ new BitstreamBufferRef(buffer.id(), std::move(shm)));
encoder_thread_.message_loop()->PostTask(
FROM_HERE,
base::Bind(&V4L2VideoEncodeAccelerator::UseOutputBitstreamBufferTask,
@@ -318,7 +307,13 @@ V4L2VideoEncodeAccelerator::GetSupportedProfiles() {
profiles.push_back(profile);
break;
case V4L2_PIX_FMT_VP9:
- profile.profile = media::VP9PROFILE_ANY;
+ profile.profile = media::VP9PROFILE_PROFILE0;
+ profiles.push_back(profile);
+ profile.profile = media::VP9PROFILE_PROFILE1;
+ profiles.push_back(profile);
+ profile.profile = media::VP9PROFILE_PROFILE2;
+ profiles.push_back(profile);
+ profile.profile = media::VP9PROFILE_PROFILE3;
profiles.push_back(profile);
break;
}
@@ -365,13 +360,21 @@ void V4L2VideoEncodeAccelerator::EncodeTask(
std::vector<struct v4l2_ext_control> ctrls;
struct v4l2_ext_control ctrl;
memset(&ctrl, 0, sizeof(ctrl));
- ctrl.id = V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE;
- ctrl.value = V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_I_FRAME;
+ ctrl.id = V4L2_CID_MPEG_VIDEO_FORCE_KEY_FRAME;
ctrls.push_back(ctrl);
if (!SetExtCtrls(ctrls)) {
- LOG(ERROR) << "Failed requesting keyframe";
- NOTIFY_ERROR(kPlatformFailureError);
- return;
+ // Some platforms still use the old control. Fallback before they are
+ // updated.
+ ctrls.clear();
+ memset(&ctrl, 0, sizeof(ctrl));
+ ctrl.id = V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE;
+ ctrl.value = V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_I_FRAME;
+ ctrls.push_back(ctrl);
+ if (!SetExtCtrls(ctrls)) {
+ LOG(ERROR) << "Failed requesting keyframe";
+ NOTIFY_ERROR(kPlatformFailureError);
+ return;
+ }
}
}
}
@@ -893,7 +896,7 @@ bool V4L2VideoEncodeAccelerator::NegotiateInputFormat(
uint32_t input_format_fourcc =
V4L2Device::VideoPixelFormatToV4L2PixFmt(input_format);
if (!input_format_fourcc) {
- LOG(ERROR) << "Unsupported input format";
+ LOG(ERROR) << "Unsupported input format" << input_format_fourcc;
return false;
}
@@ -913,8 +916,10 @@ bool V4L2VideoEncodeAccelerator::NegotiateInputFormat(
input_format_fourcc = device_->PreferredInputFormat();
input_format =
V4L2Device::V4L2PixFmtToVideoPixelFormat(input_format_fourcc);
- if (input_format == media::PIXEL_FORMAT_UNKNOWN)
+ if (input_format == media::PIXEL_FORMAT_UNKNOWN) {
+ LOG(ERROR) << "Unsupported input format" << input_format_fourcc;
return false;
+ }
input_planes_count = media::VideoFrame::NumPlanes(input_format);
DCHECK_LE(input_planes_count, static_cast<size_t>(VIDEO_MAX_PLANES));
@@ -930,9 +935,14 @@ bool V4L2VideoEncodeAccelerator::NegotiateInputFormat(
DCHECK_EQ(format.fmt.pix_mp.num_planes, input_planes_count);
}
- // Take device-adjusted sizes for allocated size.
+ // Take device-adjusted sizes for allocated size. If the size is adjusted
+ // down, it means the input is too big and the hardware does not support it.
input_allocated_size_ = V4L2Device::CodedSizeFromV4L2Format(format);
- DCHECK(gfx::Rect(input_allocated_size_).Contains(gfx::Rect(visible_size_)));
+ if (!gfx::Rect(input_allocated_size_).Contains(gfx::Rect(visible_size_))) {
+ DVLOG(1) << "Input size too big " << visible_size_.ToString()
+ << ", adjusted to " << input_allocated_size_.ToString();
+ return false;
+ }
device_input_format_ = input_format;
input_planes_count_ = input_planes_count;
@@ -1031,30 +1041,35 @@ bool V4L2VideoEncodeAccelerator::InitControls() {
ctrls.push_back(ctrl);
}
- // Enable "tight" bitrate mode. For this to work properly, frame- and mb-level
- // bitrate controls have to be enabled as well.
+ // Enable macroblock-level bitrate control.
memset(&ctrl, 0, sizeof(ctrl));
- ctrl.id = V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF;
+ ctrl.id = V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE;
ctrl.value = 1;
ctrls.push_back(ctrl);
- // Force bitrate control to average over a GOP (for tight bitrate
- // tolerance).
+ // Disable periodic key frames.
memset(&ctrl, 0, sizeof(ctrl));
- ctrl.id = V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT;
- ctrl.value = 1;
+ ctrl.id = V4L2_CID_MPEG_VIDEO_GOP_SIZE;
+ ctrl.value = 0;
ctrls.push_back(ctrl);
- // Enable macroblock-level bitrate control.
+ // Ignore return value as these controls are optional.
+ SetExtCtrls(ctrls);
+
+ // Optional Exynos specific controls.
+ ctrls.clear();
+ // Enable "tight" bitrate mode. For this to work properly, frame- and mb-level
+ // bitrate controls have to be enabled as well.
memset(&ctrl, 0, sizeof(ctrl));
- ctrl.id = V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE;
+ ctrl.id = V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF;
ctrl.value = 1;
ctrls.push_back(ctrl);
- // Disable periodic key frames.
+ // Force bitrate control to average over a GOP (for tight bitrate
+ // tolerance).
memset(&ctrl, 0, sizeof(ctrl));
- ctrl.id = V4L2_CID_MPEG_VIDEO_GOP_SIZE;
- ctrl.value = 0;
+ ctrl.id = V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT;
+ ctrl.value = 1;
ctrls.push_back(ctrl);
// Ignore return value as these controls are optional.
diff --git a/chromium/content/common/gpu/media/vaapi_drm_picture.cc b/chromium/content/common/gpu/media/vaapi_drm_picture.cc
index f20716426fd..ab5a4f28b1a 100644
--- a/chromium/content/common/gpu/media/vaapi_drm_picture.cc
+++ b/chromium/content/common/gpu/media/vaapi_drm_picture.cc
@@ -27,16 +27,16 @@ namespace content {
VaapiDrmPicture::VaapiDrmPicture(
const scoped_refptr<VaapiWrapper>& vaapi_wrapper,
- const base::Callback<bool(void)>& make_context_current,
+ const MakeGLContextCurrentCallback& make_context_current_cb,
int32_t picture_buffer_id,
uint32_t texture_id,
const gfx::Size& size)
: VaapiPicture(picture_buffer_id, texture_id, size),
vaapi_wrapper_(vaapi_wrapper),
- make_context_current_(make_context_current) {}
+ make_context_current_cb_(make_context_current_cb) {}
VaapiDrmPicture::~VaapiDrmPicture() {
- if (gl_image_ && make_context_current_.Run()) {
+ if (gl_image_ && make_context_current_cb_.Run()) {
gl_image_->ReleaseTexImage(GL_TEXTURE_EXTERNAL_OES);
gl_image_->Destroy(true);
@@ -67,7 +67,7 @@ bool VaapiDrmPicture::Initialize() {
pixmap_->SetProcessingCallback(
base::Bind(&VaapiWrapper::ProcessPixmap, vaapi_wrapper_));
- if (!make_context_current_.Run())
+ if (!make_context_current_cb_.Run())
return false;
gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_EXTERNAL_OES,
diff --git a/chromium/content/common/gpu/media/vaapi_drm_picture.h b/chromium/content/common/gpu/media/vaapi_drm_picture.h
index 066192b25ca..7f5fc8a1780 100644
--- a/chromium/content/common/gpu/media/vaapi_drm_picture.h
+++ b/chromium/content/common/gpu/media/vaapi_drm_picture.h
@@ -11,7 +11,6 @@
#include <stdint.h>
-#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
@@ -35,7 +34,7 @@ class VaapiWrapper;
class VaapiDrmPicture : public VaapiPicture {
public:
VaapiDrmPicture(const scoped_refptr<VaapiWrapper>& vaapi_wrapper,
- const base::Callback<bool(void)>& make_context_current,
+ const MakeGLContextCurrentCallback& make_context_current_cb,
int32_t picture_buffer_id,
uint32_t texture_id,
const gfx::Size& size);
@@ -52,7 +51,7 @@ class VaapiDrmPicture : public VaapiPicture {
private:
scoped_refptr<VaapiWrapper> vaapi_wrapper_;
- base::Callback<bool(void)> make_context_current_;
+ MakeGLContextCurrentCallback make_context_current_cb_;
// Ozone buffer, the storage of the EGLImage and the VASurface.
scoped_refptr<ui::NativePixmap> pixmap_;
diff --git a/chromium/content/common/gpu/media/vaapi_jpeg_decode_accelerator.cc b/chromium/content/common/gpu/media/vaapi_jpeg_decode_accelerator.cc
index 8efb362180d..a0cbc6e059d 100644
--- a/chromium/content/common/gpu/media/vaapi_jpeg_decode_accelerator.cc
+++ b/chromium/content/common/gpu/media/vaapi_jpeg_decode_accelerator.cc
@@ -13,8 +13,9 @@
#include "base/metrics/histogram.h"
#include "base/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
-#include "content/common/gpu/gpu_channel.h"
+#include "content/common/gpu/media/shared_memory_region.h"
#include "content/common/gpu/media/vaapi_picture.h"
+#include "gpu/ipc/service/gpu_channel.h"
#include "media/base/video_frame.h"
#include "media/filters/jpeg_parser.h"
#include "third_party/libyuv/include/libyuv.h"
@@ -76,10 +77,10 @@ static unsigned int VaSurfaceFormatForJpeg(
} // namespace
VaapiJpegDecodeAccelerator::DecodeRequest::DecodeRequest(
- const media::BitstreamBuffer& bitstream_buffer,
- scoped_ptr<base::SharedMemory> shm,
+ int32_t bitstream_buffer_id,
+ scoped_ptr<SharedMemoryRegion> shm,
const scoped_refptr<media::VideoFrame>& video_frame)
- : bitstream_buffer(bitstream_buffer),
+ : bitstream_buffer_id(bitstream_buffer_id),
shm(std::move(shm)),
video_frame(video_frame) {}
@@ -226,9 +227,9 @@ void VaapiJpegDecodeAccelerator::DecodeTask(
media::JpegParseResult parse_result;
if (!media::ParseJpegPicture(
reinterpret_cast<const uint8_t*>(request->shm->memory()),
- request->bitstream_buffer.size(), &parse_result)) {
+ request->shm->size(), &parse_result)) {
DLOG(ERROR) << "ParseJpegPicture failed";
- NotifyErrorFromDecoderThread(request->bitstream_buffer.id(),
+ NotifyErrorFromDecoderThread(request->bitstream_buffer_id,
PARSE_JPEG_FAILED);
return;
}
@@ -237,7 +238,7 @@ void VaapiJpegDecodeAccelerator::DecodeTask(
VaSurfaceFormatForJpeg(parse_result.frame_header);
if (!new_va_rt_format) {
DLOG(ERROR) << "Unsupported subsampling";
- NotifyErrorFromDecoderThread(request->bitstream_buffer.id(),
+ NotifyErrorFromDecoderThread(request->bitstream_buffer_id,
UNSUPPORTED_JPEG);
return;
}
@@ -255,7 +256,7 @@ void VaapiJpegDecodeAccelerator::DecodeTask(
if (!vaapi_wrapper_->CreateSurfaces(va_rt_format_, new_coded_size, 1,
&va_surfaces)) {
LOG(ERROR) << "Create VA surface failed";
- NotifyErrorFromDecoderThread(request->bitstream_buffer.id(),
+ NotifyErrorFromDecoderThread(request->bitstream_buffer_id,
PLATFORM_FAILURE);
return;
}
@@ -266,15 +267,15 @@ void VaapiJpegDecodeAccelerator::DecodeTask(
if (!VaapiJpegDecoder::Decode(vaapi_wrapper_.get(), parse_result,
va_surface_id_)) {
LOG(ERROR) << "Decode JPEG failed";
- NotifyErrorFromDecoderThread(request->bitstream_buffer.id(),
+ NotifyErrorFromDecoderThread(request->bitstream_buffer_id,
PLATFORM_FAILURE);
return;
}
- if (!OutputPicture(va_surface_id_, request->bitstream_buffer.id(),
+ if (!OutputPicture(va_surface_id_, request->bitstream_buffer_id,
request->video_frame)) {
LOG(ERROR) << "Output picture failed";
- NotifyErrorFromDecoderThread(request->bitstream_buffer.id(),
+ NotifyErrorFromDecoderThread(request->bitstream_buffer_id,
PLATFORM_FAILURE);
return;
}
@@ -289,17 +290,25 @@ void VaapiJpegDecodeAccelerator::Decode(
DVLOG(4) << "Mapping new input buffer id: " << bitstream_buffer.id()
<< " size: " << bitstream_buffer.size();
- scoped_ptr<base::SharedMemory> shm(
- new base::SharedMemory(bitstream_buffer.handle(), true));
- if (!shm->Map(bitstream_buffer.size())) {
+ // SharedMemoryRegion will take over the |bitstream_buffer.handle()|.
+ scoped_ptr<SharedMemoryRegion> shm(
+ new SharedMemoryRegion(bitstream_buffer, true));
+
+ if (bitstream_buffer.id() < 0) {
+ LOG(ERROR) << "Invalid bitstream_buffer, id: " << bitstream_buffer.id();
+ NotifyErrorFromDecoderThread(bitstream_buffer.id(), INVALID_ARGUMENT);
+ return;
+ }
+
+ if (!shm->Map()) {
LOG(ERROR) << "Failed to map input buffer";
NotifyErrorFromDecoderThread(bitstream_buffer.id(), UNREADABLE_INPUT);
return;
}
scoped_ptr<DecodeRequest> request(
- new DecodeRequest(bitstream_buffer, std::move(shm), video_frame));
+ new DecodeRequest(bitstream_buffer.id(), std::move(shm), video_frame));
decoder_task_runner_->PostTask(
FROM_HERE, base::Bind(&VaapiJpegDecodeAccelerator::DecodeTask,
diff --git a/chromium/content/common/gpu/media/vaapi_jpeg_decode_accelerator.h b/chromium/content/common/gpu/media/vaapi_jpeg_decode_accelerator.h
index 7d78a5503e9..232b04de829 100644
--- a/chromium/content/common/gpu/media/vaapi_jpeg_decode_accelerator.h
+++ b/chromium/content/common/gpu/media/vaapi_jpeg_decode_accelerator.h
@@ -15,6 +15,7 @@
#include "base/threading/non_thread_safe.h"
#include "base/threading/thread.h"
#include "content/common/content_export.h"
+#include "content/common/gpu/media/shared_memory_region.h"
#include "content/common/gpu/media/vaapi_jpeg_decoder.h"
#include "content/common/gpu/media/vaapi_wrapper.h"
#include "media/base/bitstream_buffer.h"
@@ -47,13 +48,13 @@ class CONTENT_EXPORT VaapiJpegDecodeAccelerator
// An input buffer and the corresponding output video frame awaiting
// consumption, provided by the client.
struct DecodeRequest {
- DecodeRequest(const media::BitstreamBuffer& bitstream_buffer,
- scoped_ptr<base::SharedMemory> shm,
+ DecodeRequest(int32_t bitstream_buffer_id,
+ scoped_ptr<SharedMemoryRegion> shm,
const scoped_refptr<media::VideoFrame>& video_frame);
~DecodeRequest();
- media::BitstreamBuffer bitstream_buffer;
- scoped_ptr<base::SharedMemory> shm;
+ int32_t bitstream_buffer_id;
+ scoped_ptr<SharedMemoryRegion> shm;
scoped_refptr<media::VideoFrame> video_frame;
};
diff --git a/chromium/content/common/gpu/media/vaapi_picture.cc b/chromium/content/common/gpu/media/vaapi_picture.cc
index 5222bd23504..cdf8c355974 100644
--- a/chromium/content/common/gpu/media/vaapi_picture.cc
+++ b/chromium/content/common/gpu/media/vaapi_picture.cc
@@ -18,16 +18,16 @@ namespace content {
// static
linked_ptr<VaapiPicture> VaapiPicture::CreatePicture(
const scoped_refptr<VaapiWrapper>& vaapi_wrapper,
- const base::Callback<bool(void)> make_context_current,
+ const MakeGLContextCurrentCallback& make_context_current_cb,
int32_t picture_buffer_id,
uint32_t texture_id,
const gfx::Size& size) {
linked_ptr<VaapiPicture> picture;
#if defined(USE_X11)
- picture.reset(new VaapiTFPPicture(vaapi_wrapper, make_context_current,
+ picture.reset(new VaapiTFPPicture(vaapi_wrapper, make_context_current_cb,
picture_buffer_id, texture_id, size));
#elif defined(USE_OZONE)
- picture.reset(new VaapiDrmPicture(vaapi_wrapper, make_context_current,
+ picture.reset(new VaapiDrmPicture(vaapi_wrapper, make_context_current_cb,
picture_buffer_id, texture_id, size));
#endif // USE_X11
diff --git a/chromium/content/common/gpu/media/vaapi_picture.h b/chromium/content/common/gpu/media/vaapi_picture.h
index 921f80344ec..4bd51e11620 100644
--- a/chromium/content/common/gpu/media/vaapi_picture.h
+++ b/chromium/content/common/gpu/media/vaapi_picture.h
@@ -12,11 +12,11 @@
#include <stdint.h>
-#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/linked_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/threading/non_thread_safe.h"
+#include "content/common/gpu/media/gpu_video_decode_accelerator_helpers.h"
#include "ui/gfx/geometry/size.h"
namespace gl {
@@ -52,10 +52,10 @@ class VaapiPicture : public base::NonThreadSafe {
// Create a VaapiPicture of |size| to be associated with
// |picture_buffer_id| and bound to |texture_id|.
- // |make_context_current| is provided for the GL operations.
+ // |make_context_current_cb| is provided for the GL operations.
static linked_ptr<VaapiPicture> CreatePicture(
const scoped_refptr<VaapiWrapper>& vaapi_wrapper,
- const base::Callback<bool(void)> make_context_current,
+ const MakeGLContextCurrentCallback& make_context_current_cb,
int32_t picture_buffer_id,
uint32_t texture_id,
const gfx::Size& size);
diff --git a/chromium/content/common/gpu/media/vaapi_tfp_picture.cc b/chromium/content/common/gpu/media/vaapi_tfp_picture.cc
index 3de593b62fd..074ba98ed73 100644
--- a/chromium/content/common/gpu/media/vaapi_tfp_picture.cc
+++ b/chromium/content/common/gpu/media/vaapi_tfp_picture.cc
@@ -14,18 +14,18 @@ namespace content {
VaapiTFPPicture::VaapiTFPPicture(
const scoped_refptr<VaapiWrapper>& vaapi_wrapper,
- const base::Callback<bool(void)> make_context_current,
+ const MakeGLContextCurrentCallback& make_context_current_cb,
int32_t picture_buffer_id,
uint32_t texture_id,
const gfx::Size& size)
: VaapiPicture(picture_buffer_id, texture_id, size),
vaapi_wrapper_(vaapi_wrapper),
- make_context_current_(make_context_current),
+ make_context_current_cb_(make_context_current_cb),
x_display_(gfx::GetXDisplay()),
x_pixmap_(0) {}
VaapiTFPPicture::~VaapiTFPPicture() {
- if (glx_image_.get() && make_context_current_.Run()) {
+ if (glx_image_.get() && make_context_current_cb_.Run()) {
glx_image_->ReleaseTexImage(GL_TEXTURE_2D);
glx_image_->Destroy(true);
DCHECK_EQ(glGetError(), static_cast<GLenum>(GL_NO_ERROR));
@@ -36,7 +36,7 @@ VaapiTFPPicture::~VaapiTFPPicture() {
}
bool VaapiTFPPicture::Initialize() {
- if (!make_context_current_.Run())
+ if (!make_context_current_cb_.Run())
return false;
XWindowAttributes win_attr;
diff --git a/chromium/content/common/gpu/media/vaapi_tfp_picture.h b/chromium/content/common/gpu/media/vaapi_tfp_picture.h
index 3b66e10800b..5ef35653202 100644
--- a/chromium/content/common/gpu/media/vaapi_tfp_picture.h
+++ b/chromium/content/common/gpu/media/vaapi_tfp_picture.h
@@ -11,7 +11,6 @@
#include <stdint.h>
-#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "content/common/gpu/media/vaapi_picture.h"
@@ -34,7 +33,7 @@ class VaapiWrapper;
class VaapiTFPPicture : public VaapiPicture {
public:
VaapiTFPPicture(const scoped_refptr<VaapiWrapper>& vaapi_wrapper,
- const base::Callback<bool(void)> make_context_current,
+ const MakeGLContextCurrentCallback& make_context_current_cb,
int32_t picture_buffer_id,
uint32_t texture_id,
const gfx::Size& size);
@@ -50,7 +49,7 @@ class VaapiTFPPicture : public VaapiPicture {
private:
scoped_refptr<VaapiWrapper> vaapi_wrapper_;
- base::Callback<bool(void)> make_context_current_;
+ MakeGLContextCurrentCallback make_context_current_cb_;
Display* x_display_;
Pixmap x_pixmap_;
diff --git a/chromium/content/common/gpu/media/vaapi_video_decode_accelerator.cc b/chromium/content/common/gpu/media/vaapi_video_decode_accelerator.cc
index 271a0f7a1c9..d8caeec94da 100644
--- a/chromium/content/common/gpu/media/vaapi_video_decode_accelerator.cc
+++ b/chromium/content/common/gpu/media/vaapi_video_decode_accelerator.cc
@@ -14,12 +14,12 @@
#include "base/strings/string_util.h"
#include "base/synchronization/waitable_event.h"
#include "base/trace_event/trace_event.h"
-#include "content/common/gpu/gpu_channel.h"
#include "content/common/gpu/media/accelerated_video_decoder.h"
#include "content/common/gpu/media/h264_decoder.h"
#include "content/common/gpu/media/vaapi_picture.h"
#include "content/common/gpu/media/vp8_decoder.h"
#include "content/common/gpu/media/vp9_decoder.h"
+#include "gpu/ipc/service/gpu_channel.h"
#include "media/base/bind_to_current_loop.h"
#include "media/video/picture.h"
#include "third_party/libva/va/va_dec_vp8.h"
@@ -256,8 +256,7 @@ class VaapiVideoDecodeAccelerator::VaapiVP9Accelerator
DISALLOW_COPY_AND_ASSIGN(VaapiVP9Accelerator);
};
-VaapiVideoDecodeAccelerator::InputBuffer::InputBuffer() : id(0), size(0) {
-}
+VaapiVideoDecodeAccelerator::InputBuffer::InputBuffer() : id(0) {}
VaapiVideoDecodeAccelerator::InputBuffer::~InputBuffer() {
}
@@ -293,11 +292,9 @@ VaapiPicture* VaapiVideoDecodeAccelerator::PictureById(
}
VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator(
- const base::Callback<bool(void)>& make_context_current,
- const base::Callback<void(uint32_t, uint32_t, scoped_refptr<gl::GLImage>)>&
- bind_image)
- : make_context_current_(make_context_current),
- state_(kUninitialized),
+ const MakeGLContextCurrentCallback& make_context_current_cb,
+ const BindGLImageCallback& bind_image_cb)
+ : state_(kUninitialized),
input_ready_(&lock_),
surfaces_available_(&lock_),
message_loop_(base::MessageLoop::current()),
@@ -307,7 +304,8 @@ VaapiVideoDecodeAccelerator::VaapiVideoDecodeAccelerator(
finish_flush_pending_(false),
awaiting_va_surfaces_recycle_(false),
requested_num_pics_(0),
- bind_image_(bind_image),
+ make_context_current_cb_(make_context_current_cb),
+ bind_image_cb_(bind_image_cb),
weak_this_factory_(this) {
weak_this_ = weak_this_factory_.GetWeakPtr();
va_surface_release_cb_ = media::BindToCurrentLoop(
@@ -322,6 +320,11 @@ bool VaapiVideoDecodeAccelerator::Initialize(const Config& config,
Client* client) {
DCHECK_EQ(message_loop_, base::MessageLoop::current());
+ if (make_context_current_cb_.is_null() || bind_image_cb_.is_null()) {
+ NOTREACHED() << "GL callbacks are required for this VDA";
+ return false;
+ }
+
if (config.is_encrypted) {
NOTREACHED() << "Encrypted streams are not supported for this VDA";
return false;
@@ -447,10 +450,10 @@ void VaapiVideoDecodeAccelerator::MapAndQueueNewInputBuffer(
DVLOG(4) << "Mapping new input buffer id: " << bitstream_buffer.id()
<< " size: " << (int)bitstream_buffer.size();
- scoped_ptr<base::SharedMemory> shm(
- new base::SharedMemory(bitstream_buffer.handle(), true));
- RETURN_AND_NOTIFY_ON_FAILURE(shm->Map(bitstream_buffer.size()),
- "Failed to map input buffer", UNREADABLE_INPUT,);
+ scoped_ptr<SharedMemoryRegion> shm(
+ new SharedMemoryRegion(bitstream_buffer, true));
+ RETURN_AND_NOTIFY_ON_FAILURE(shm->Map(), "Failed to map input buffer",
+ UNREADABLE_INPUT, );
base::AutoLock auto_lock(lock_);
@@ -458,7 +461,6 @@ void VaapiVideoDecodeAccelerator::MapAndQueueNewInputBuffer(
linked_ptr<InputBuffer> input_buffer(new InputBuffer());
input_buffer->shm.reset(shm.release());
input_buffer->id = bitstream_buffer.id();
- input_buffer->size = bitstream_buffer.size();
++num_stream_bufs_at_decoder_;
TRACE_COUNTER1("Video Decoder", "Stream buffers at decoder",
@@ -497,13 +499,12 @@ bool VaapiVideoDecodeAccelerator::GetInputBuffer_Locked() {
curr_input_buffer_ = input_buffers_.front();
input_buffers_.pop();
- DVLOG(4) << "New current bitstream buffer, id: "
- << curr_input_buffer_->id
- << " size: " << curr_input_buffer_->size;
+ DVLOG(4) << "New current bitstream buffer, id: " << curr_input_buffer_->id
+ << " size: " << curr_input_buffer_->shm->size();
decoder_->SetStream(
static_cast<uint8_t*>(curr_input_buffer_->shm->memory()),
- curr_input_buffer_->size);
+ curr_input_buffer_->shm->size());
return true;
default:
@@ -663,7 +664,7 @@ void VaapiVideoDecodeAccelerator::TryFinishSurfaceSetChange() {
message_loop_->PostTask(
FROM_HERE,
base::Bind(&Client::ProvidePictureBuffers, client_, requested_num_pics_,
- requested_pic_size_, VaapiPicture::GetGLTextureTarget()));
+ 1, requested_pic_size_, VaapiPicture::GetGLTextureTarget()));
}
void VaapiVideoDecodeAccelerator::Decode(
@@ -673,6 +674,12 @@ void VaapiVideoDecodeAccelerator::Decode(
TRACE_EVENT1("Video Decoder", "VAVDA::Decode", "Buffer id",
bitstream_buffer.id());
+ RETURN_AND_NOTIFY_ON_FAILURE(
+ bitstream_buffer.id() >= 0 &&
+ base::SharedMemory::IsHandleValid(bitstream_buffer.handle()),
+ "Invalid bitstream_buffer, id: " << bitstream_buffer.id(),
+ INVALID_ARGUMENT, );
+
// We got a new input buffer from the client, map it and queue for later use.
MapAndQueueNewInputBuffer(bitstream_buffer);
@@ -734,18 +741,22 @@ void VaapiVideoDecodeAccelerator::AssignPictureBuffers(
DCHECK_EQ(va_surface_ids.size(), buffers.size());
for (size_t i = 0; i < buffers.size(); ++i) {
+ DCHECK_LE(1u, buffers[i].texture_ids().size());
DVLOG(2) << "Assigning picture id: " << buffers[i].id()
- << " to texture id: " << buffers[i].texture_id()
+ << " to texture id: " << buffers[i].texture_ids()[0]
<< " VASurfaceID: " << va_surface_ids[i];
linked_ptr<VaapiPicture> picture(VaapiPicture::CreatePicture(
- vaapi_wrapper_, make_context_current_, buffers[i].id(),
- buffers[i].texture_id(), requested_pic_size_));
+ vaapi_wrapper_, make_context_current_cb_, buffers[i].id(),
+ buffers[i].texture_ids()[0], requested_pic_size_));
scoped_refptr<gl::GLImage> image = picture->GetImageToBind();
if (image) {
- bind_image_.Run(buffers[i].internal_texture_id(),
- VaapiPicture::GetGLTextureTarget(), image);
+ DCHECK_LE(1u, buffers[i].internal_texture_ids().size());
+ RETURN_AND_NOTIFY_ON_FAILURE(
+ bind_image_cb_.Run(buffers[i].internal_texture_ids()[0],
+ VaapiPicture::GetGLTextureTarget(), image, true),
+ "Failed to bind image", PLATFORM_FAILURE, );
}
RETURN_AND_NOTIFY_ON_FAILURE(
@@ -960,7 +971,9 @@ void VaapiVideoDecodeAccelerator::Destroy() {
delete this;
}
-bool VaapiVideoDecodeAccelerator::CanDecodeOnIOThread() {
+bool VaapiVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread(
+ const base::WeakPtr<Client>& decode_client,
+ const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) {
return false;
}
diff --git a/chromium/content/common/gpu/media/vaapi_video_decode_accelerator.h b/chromium/content/common/gpu/media/vaapi_video_decode_accelerator.h
index 11cc082a627..f9cfb90376c 100644
--- a/chromium/content/common/gpu/media/vaapi_video_decode_accelerator.h
+++ b/chromium/content/common/gpu/media/vaapi_video_decode_accelerator.h
@@ -20,13 +20,14 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/linked_ptr.h"
-#include "base/memory/shared_memory.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/synchronization/condition_variable.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread.h"
#include "content/common/content_export.h"
+#include "content/common/gpu/media/gpu_video_decode_accelerator_helpers.h"
+#include "content/common/gpu/media/shared_memory_region.h"
#include "content/common/gpu/media/vaapi_wrapper.h"
#include "media/base/bitstream_buffer.h"
#include "media/video/picture.h"
@@ -55,9 +56,9 @@ class CONTENT_EXPORT VaapiVideoDecodeAccelerator
class VaapiDecodeSurface;
VaapiVideoDecodeAccelerator(
- const base::Callback<bool(void)>& make_context_current,
- const base::Callback<
- void(uint32_t, uint32_t, scoped_refptr<gl::GLImage>)>& bind_image);
+ const MakeGLContextCurrentCallback& make_context_current_cb,
+ const BindGLImageCallback& bind_image_cb);
+
~VaapiVideoDecodeAccelerator() override;
// media::VideoDecodeAccelerator implementation.
@@ -69,7 +70,10 @@ class CONTENT_EXPORT VaapiVideoDecodeAccelerator
void Flush() override;
void Reset() override;
void Destroy() override;
- bool CanDecodeOnIOThread() override;
+ bool TryToSetupDecodeOnSeparateThread(
+ const base::WeakPtr<Client>& decode_client,
+ const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner)
+ override;
static media::VideoDecodeAccelerator::SupportedProfiles
GetSupportedProfiles();
@@ -180,10 +184,6 @@ class CONTENT_EXPORT VaapiVideoDecodeAccelerator
// available.
scoped_refptr<VaapiDecodeSurface> CreateSurface();
-
- // Client-provided GL state.
- base::Callback<bool(void)> make_context_current_;
-
// VAVDA state.
enum State {
// Initialize() not called yet or failed.
@@ -210,8 +210,7 @@ class CONTENT_EXPORT VaapiVideoDecodeAccelerator
~InputBuffer();
int32_t id;
- size_t size;
- scoped_ptr<base::SharedMemory> shm;
+ scoped_ptr<SharedMemoryRegion> shm;
};
// Queue for incoming input buffers.
@@ -305,10 +304,11 @@ class CONTENT_EXPORT VaapiVideoDecodeAccelerator
size_t requested_num_pics_;
gfx::Size requested_pic_size_;
- // Binds the provided GLImage to a givenr client texture ID & texture target
- // combination in GLES.
- base::Callback<void(uint32_t, uint32_t, scoped_refptr<gl::GLImage>)>
- bind_image_;
+ // Callback to make GL context current.
+ MakeGLContextCurrentCallback make_context_current_cb_;
+
+ // Callback to bind a GLImage to a given texture.
+ BindGLImageCallback bind_image_cb_;
// The WeakPtrFactory for |weak_this_|.
base::WeakPtrFactory<VaapiVideoDecodeAccelerator> weak_this_factory_;
diff --git a/chromium/content/common/gpu/media/vaapi_video_encode_accelerator.cc b/chromium/content/common/gpu/media/vaapi_video_encode_accelerator.cc
index 049cd7a5547..520d411e21b 100644
--- a/chromium/content/common/gpu/media/vaapi_video_encode_accelerator.cc
+++ b/chromium/content/common/gpu/media/vaapi_video_encode_accelerator.cc
@@ -13,6 +13,7 @@
#include "base/metrics/histogram.h"
#include "base/numerics/safe_conversions.h"
#include "content/common/gpu/media/h264_dpb.h"
+#include "content/common/gpu/media/shared_memory_region.h"
#include "media/base/bind_to_current_loop.h"
#include "third_party/libva/va/va_enc_h264.h"
@@ -100,13 +101,10 @@ struct VaapiVideoEncodeAccelerator::InputFrameRef {
};
struct VaapiVideoEncodeAccelerator::BitstreamBufferRef {
- BitstreamBufferRef(int32_t id,
- scoped_ptr<base::SharedMemory> shm,
- size_t size)
- : id(id), shm(std::move(shm)), size(size) {}
+ BitstreamBufferRef(int32_t id, scoped_ptr<SharedMemoryRegion> shm)
+ : id(id), shm(std::move(shm)) {}
const int32_t id;
- const scoped_ptr<base::SharedMemory> shm;
- const size_t size;
+ const scoped_ptr<SharedMemoryRegion> shm;
};
media::VideoEncodeAccelerator::SupportedProfiles
@@ -176,9 +174,19 @@ bool VaapiVideoEncodeAccelerator::Initialize(
client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client));
client_ = client_ptr_factory_->GetWeakPtr();
- if (output_profile < media::H264PROFILE_BASELINE ||
- output_profile > media::H264PROFILE_MAIN) {
- DVLOGF(1) << "Unsupported output profile: " << output_profile;
+ const SupportedProfiles& profiles = GetSupportedProfiles();
+ auto profile = find_if(profiles.begin(), profiles.end(),
+ [output_profile](const SupportedProfile& profile) {
+ return profile.profile == output_profile;
+ });
+ if (profile == profiles.end()) {
+ DVLOGF(1) << "Unsupported output profile " << output_profile;
+ return false;
+ }
+ if (input_visible_size.width() > profile->max_resolution.width() ||
+ input_visible_size.height() > profile->max_resolution.height()) {
+ DVLOGF(1) << "Input size too big: " << input_visible_size.ToString()
+ << ", max supported size: " << profile->max_resolution.ToString();
return false;
}
@@ -546,11 +554,8 @@ void VaapiVideoEncodeAccelerator::TryToReturnBitstreamBuffer() {
size_t data_size = 0;
if (!vaapi_wrapper_->DownloadAndDestroyCodedBuffer(
- encode_job->coded_buffer,
- encode_job->input_surface->id(),
- target_data,
- buffer->size,
- &data_size)) {
+ encode_job->coded_buffer, encode_job->input_surface->id(),
+ target_data, buffer->shm->size(), &data_size)) {
NOTIFY_ERROR(kPlatformFailureError, "Failed downloading coded buffer");
return;
}
@@ -669,15 +674,14 @@ void VaapiVideoEncodeAccelerator::UseOutputBitstreamBuffer(
return;
}
- scoped_ptr<base::SharedMemory> shm(
- new base::SharedMemory(buffer.handle(), false));
- if (!shm->Map(buffer.size())) {
+ scoped_ptr<SharedMemoryRegion> shm(new SharedMemoryRegion(buffer, false));
+ if (!shm->Map()) {
NOTIFY_ERROR(kPlatformFailureError, "Failed mapping shared memory.");
return;
}
scoped_ptr<BitstreamBufferRef> buffer_ref(
- new BitstreamBufferRef(buffer.id(), std::move(shm), buffer.size()));
+ new BitstreamBufferRef(buffer.id(), std::move(shm)));
encoder_thread_task_runner_->PostTask(
FROM_HERE,
diff --git a/chromium/content/common/gpu/media/vaapi_wrapper.cc b/chromium/content/common/gpu/media/vaapi_wrapper.cc
index db38f32f7f8..19303e1e6d6 100644
--- a/chromium/content/common/gpu/media/vaapi_wrapper.cc
+++ b/chromium/content/common/gpu/media/vaapi_wrapper.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
-#include "base/command_line.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/numerics/safe_conversions.h"
@@ -18,7 +17,6 @@
// Auto-generated for dlopen libva libraries
#include "content/common/gpu/media/va_stubs.h"
#include "content/common/gpu/media/vaapi_picture.h"
-#include "content/public/common/content_switches.h"
#include "third_party/libyuv/include/libyuv.h"
#include "ui/gl/gl_bindings.h"
#if defined(USE_X11)
@@ -127,7 +125,9 @@ static const ProfileMap kProfileMap[] = {
// media::H264PROFILE_HIGH*.
{media::H264PROFILE_HIGH, VAProfileH264High},
{media::VP8PROFILE_ANY, VAProfileVP8Version0_3},
- {media::VP9PROFILE_ANY, VAProfileVP9Profile0},
+ // TODO(servolk): Need to add VP9 profiles 1,2,3 here after rolling
+ // third_party/libva to 1.7. crbug.com/598118
+ {media::VP9PROFILE_PROFILE0, VAProfileVP9Profile0},
};
static std::vector<VAConfigAttrib> GetRequiredAttribs(
@@ -214,10 +214,6 @@ scoped_refptr<VaapiWrapper> VaapiWrapper::CreateForVideoCodec(
media::VideoEncodeAccelerator::SupportedProfiles
VaapiWrapper::GetSupportedEncodeProfiles() {
media::VideoEncodeAccelerator::SupportedProfiles profiles;
- const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
- if (cmd_line->HasSwitch(switches::kDisableVaapiAcceleratedVideoEncode))
- return profiles;
-
std::vector<ProfileInfo> encode_profile_infos =
profile_infos_.Get().GetSupportedProfileInfosForCodecMode(kEncode);
@@ -369,11 +365,8 @@ bool VaapiWrapper::VaInitialize(const base::Closure& report_error_to_uma_cb) {
return false;
}
- VAStatus va_res = VA_STATUS_SUCCESS;
- if (!va_display_state->Initialize(&va_res)) {
- VA_LOG_ON_ERROR(va_res, "vaInitialize failed");
+ if (!va_display_state->Initialize())
return false;
- }
va_display_ = va_display_state->va_display();
return true;
@@ -1218,7 +1211,7 @@ VaapiWrapper::VADisplayState::VADisplayState()
VaapiWrapper::VADisplayState::~VADisplayState() {}
-bool VaapiWrapper::VADisplayState::Initialize(VAStatus* status) {
+bool VaapiWrapper::VADisplayState::Initialize() {
va_lock_.AssertAcquired();
if (refcount_++ == 0) {
#if defined(USE_X11)
@@ -1232,9 +1225,12 @@ bool VaapiWrapper::VADisplayState::Initialize(VAStatus* status) {
return false;
}
- *status = vaInitialize(va_display_, &major_version_, &minor_version_);
- if (*status != VA_STATUS_SUCCESS)
+ VAStatus va_res =
+ vaInitialize(va_display_, &major_version_, &minor_version_);
+ if (va_res != VA_STATUS_SUCCESS) {
+ LOG(WARNING) << "vaInitialize failed: " << vaErrorStr(va_res);
return false;
+ }
va_initialized_ = true;
DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_;
diff --git a/chromium/content/common/gpu/media/vaapi_wrapper.h b/chromium/content/common/gpu/media/vaapi_wrapper.h
index 7f14b49be11..4394bc36b92 100644
--- a/chromium/content/common/gpu/media/vaapi_wrapper.h
+++ b/chromium/content/common/gpu/media/vaapi_wrapper.h
@@ -247,7 +247,7 @@ class CONTENT_EXPORT VaapiWrapper
~VADisplayState();
// |va_lock_| must be held on entry.
- bool Initialize(VAStatus* status);
+ bool Initialize();
void Deinitialize(VAStatus* status);
base::Lock* va_lock() { return &va_lock_; }
diff --git a/chromium/content/common/gpu/media/video_decode_accelerator_unittest.cc b/chromium/content/common/gpu/media/video_decode_accelerator_unittest.cc
index 36466304a3c..91339668867 100644
--- a/chromium/content/common/gpu/media/video_decode_accelerator_unittest.cc
+++ b/chromium/content/common/gpu/media/video_decode_accelerator_unittest.cc
@@ -47,9 +47,10 @@
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "content/common/gpu/media/fake_video_decode_accelerator.h"
+#include "content/common/gpu/media/gpu_video_decode_accelerator_factory_impl.h"
#include "content/common/gpu/media/rendering_helper.h"
#include "content/common/gpu/media/video_accelerator_unittest_helpers.h"
-#include "content/public/common/content_switches.h"
+#include "gpu/command_buffer/service/gpu_preferences.h"
#include "media/filters/h264_parser.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/codec/png_codec.h"
@@ -334,6 +335,7 @@ class GLRenderingVDAClient
// VideoDecodeAccelerator::Client implementation.
// The heart of the Client.
void ProvidePictureBuffers(uint32_t requested_num_of_buffers,
+ uint32_t textures_per_buffer,
const gfx::Size& dimensions,
uint32_t texture_target) override;
void DismissPictureBuffer(int32_t picture_buffer_id) override;
@@ -359,16 +361,6 @@ class GLRenderingVDAClient
private:
typedef std::map<int32_t, scoped_refptr<TextureRef>> TextureRefMap;
- scoped_ptr<media::VideoDecodeAccelerator> CreateFakeVDA();
- scoped_ptr<media::VideoDecodeAccelerator> CreateDXVAVDA();
- scoped_ptr<media::VideoDecodeAccelerator> CreateV4L2VDA();
- scoped_ptr<media::VideoDecodeAccelerator> CreateV4L2SliceVDA();
- scoped_ptr<media::VideoDecodeAccelerator> CreateVaapiVDA();
-
- void BindImage(uint32_t client_texture_id,
- uint32_t texture_target,
- scoped_refptr<gl::GLImage> image);
-
void SetState(ClientState new_state);
void FinishInitialization();
void ReturnPicture(int32_t picture_buffer_id);
@@ -401,8 +393,10 @@ class GLRenderingVDAClient
int next_bitstream_buffer_id_;
ClientStateNotification<ClientState>* note_;
scoped_ptr<VideoDecodeAccelerator> decoder_;
- scoped_ptr<base::WeakPtrFactory<VideoDecodeAccelerator> >
- weak_decoder_factory_;
+ base::WeakPtr<VideoDecodeAccelerator> weak_vda_;
+ scoped_ptr<base::WeakPtrFactory<VideoDecodeAccelerator>>
+ weak_vda_ptr_factory_;
+ scoped_ptr<GpuVideoDecodeAcceleratorFactoryImpl> vda_factory_;
int remaining_play_throughs_;
int reset_after_frame_num_;
int delete_decoder_state_;
@@ -440,9 +434,23 @@ class GLRenderingVDAClient
int32_t next_picture_buffer_id_;
+ base::WeakPtr<GLRenderingVDAClient> weak_this_;
+ base::WeakPtrFactory<GLRenderingVDAClient> weak_this_factory_;
+
DISALLOW_IMPLICIT_CONSTRUCTORS(GLRenderingVDAClient);
};
+static bool DoNothingReturnTrue() {
+ return true;
+}
+
+static bool DummyBindImage(uint32_t client_texture_id,
+ uint32_t texture_target,
+ const scoped_refptr<gl::GLImage>& image,
+ bool can_bind_to_sampler) {
+ return true;
+}
+
GLRenderingVDAClient::GLRenderingVDAClient(
size_t window_id,
RenderingHelper* rendering_helper,
@@ -483,7 +491,8 @@ GLRenderingVDAClient::GLRenderingVDAClient(
delay_reuse_after_frame_num_(delay_reuse_after_frame_num),
decode_calls_per_second_(decode_calls_per_second),
render_as_thumbnails_(render_as_thumbnails),
- next_picture_buffer_id_(1) {
+ next_picture_buffer_id_(1),
+ weak_this_factory_(this) {
LOG_ASSERT(num_in_flight_decodes > 0);
LOG_ASSERT(num_play_throughs > 0);
// |num_in_flight_decodes_| is unsupported if |decode_calls_per_second_| > 0.
@@ -494,6 +503,8 @@ GLRenderingVDAClient::GLRenderingVDAClient(
profile_ = (profile != media::VIDEO_CODEC_PROFILE_UNKNOWN
? profile
: media::H264PROFILE_BASELINE);
+
+ weak_this_ = weak_this_factory_.GetWeakPtr();
}
GLRenderingVDAClient::~GLRenderingVDAClient() {
@@ -502,119 +513,49 @@ GLRenderingVDAClient::~GLRenderingVDAClient() {
SetState(CS_DESTROYED);
}
-static bool DoNothingReturnTrue() { return true; }
+void GLRenderingVDAClient::CreateAndStartDecoder() {
+ LOG_ASSERT(decoder_deleted());
+ LOG_ASSERT(!decoder_.get());
-scoped_ptr<media::VideoDecodeAccelerator>
-GLRenderingVDAClient::CreateFakeVDA() {
- scoped_ptr<media::VideoDecodeAccelerator> decoder;
if (fake_decoder_) {
- decoder.reset(new FakeVideoDecodeAccelerator(
- static_cast<gfx::GLContext*> (rendering_helper_->GetGLContextHandle()),
- frame_size_,
- base::Bind(&DoNothingReturnTrue)));
- }
- return decoder;
-}
-
-scoped_ptr<media::VideoDecodeAccelerator>
-GLRenderingVDAClient::CreateDXVAVDA() {
- scoped_ptr<media::VideoDecodeAccelerator> decoder;
-#if defined(OS_WIN)
- if (base::win::GetVersion() >= base::win::VERSION_WIN7)
- decoder.reset(
- new DXVAVideoDecodeAccelerator(
- base::Bind(&DoNothingReturnTrue),
- rendering_helper_->GetGLContext().get()));
-#endif
- return decoder;
-}
-
-scoped_ptr<media::VideoDecodeAccelerator>
-GLRenderingVDAClient::CreateV4L2VDA() {
- scoped_ptr<media::VideoDecodeAccelerator> decoder;
-#if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
- scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder);
- if (device.get()) {
- base::WeakPtr<VideoDecodeAccelerator::Client> weak_client = AsWeakPtr();
- decoder.reset(new V4L2VideoDecodeAccelerator(
- static_cast<EGLDisplay>(rendering_helper_->GetGLDisplay()),
- static_cast<EGLContext>(rendering_helper_->GetGLContextHandle()),
- weak_client, base::Bind(&DoNothingReturnTrue), device,
- base::ThreadTaskRunnerHandle::Get()));
- }
-#endif
- return decoder;
-}
+ decoder_.reset(new FakeVideoDecodeAccelerator(
+ frame_size_, base::Bind(&DoNothingReturnTrue)));
+ LOG_ASSERT(decoder_->Initialize(profile_, this));
+ } else {
+ if (!vda_factory_) {
+ vda_factory_ = GpuVideoDecodeAcceleratorFactoryImpl::Create(
+ base::Bind(&RenderingHelper::GetGLContext,
+ base::Unretained(rendering_helper_)),
+ base::Bind(&DoNothingReturnTrue), base::Bind(&DummyBindImage));
+ LOG_ASSERT(vda_factory_);
+ }
-scoped_ptr<media::VideoDecodeAccelerator>
-GLRenderingVDAClient::CreateV4L2SliceVDA() {
- scoped_ptr<media::VideoDecodeAccelerator> decoder;
-#if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
- scoped_refptr<V4L2Device> device = V4L2Device::Create(V4L2Device::kDecoder);
- if (device.get()) {
- base::WeakPtr<VideoDecodeAccelerator::Client> weak_client = AsWeakPtr();
- decoder.reset(new V4L2SliceVideoDecodeAccelerator(
- device, static_cast<EGLDisplay>(rendering_helper_->GetGLDisplay()),
- static_cast<EGLContext>(rendering_helper_->GetGLContextHandle()),
- weak_client, base::Bind(&DoNothingReturnTrue),
- base::ThreadTaskRunnerHandle::Get()));
+ VideoDecodeAccelerator::Config config(profile_);
+ gpu::GpuPreferences gpu_preferences;
+ decoder_ = vda_factory_->CreateVDA(this, config, gpu_preferences);
}
-#endif
- return decoder;
-}
-scoped_ptr<media::VideoDecodeAccelerator>
-GLRenderingVDAClient::CreateVaapiVDA() {
- scoped_ptr<media::VideoDecodeAccelerator> decoder;
-#if defined(OS_CHROMEOS) && defined(ARCH_CPU_X86_FAMILY)
- decoder.reset(new VaapiVideoDecodeAccelerator(
- base::Bind(&DoNothingReturnTrue),
- base::Bind(&GLRenderingVDAClient::BindImage, base::Unretained(this))));
-#endif
- return decoder;
-}
+ LOG_ASSERT(decoder_) << "Failed creating a VDA";
-void GLRenderingVDAClient::BindImage(uint32_t client_texture_id,
- uint32_t texture_target,
- scoped_refptr<gl::GLImage> image) {}
+ decoder_->TryToSetupDecodeOnSeparateThread(
+ weak_this_, base::ThreadTaskRunnerHandle::Get());
-void GLRenderingVDAClient::CreateAndStartDecoder() {
- LOG_ASSERT(decoder_deleted());
- LOG_ASSERT(!decoder_.get());
-
- VideoDecodeAccelerator::Client* client = this;
-
- scoped_ptr<media::VideoDecodeAccelerator> decoders[] = {
- CreateFakeVDA(),
- CreateDXVAVDA(),
- CreateV4L2VDA(),
- CreateV4L2SliceVDA(),
- CreateVaapiVDA(),
- };
+ weak_vda_ptr_factory_.reset(
+ new base::WeakPtrFactory<VideoDecodeAccelerator>(decoder_.get()));
+ weak_vda_ = weak_vda_ptr_factory_->GetWeakPtr();
- for (size_t i = 0; i < arraysize(decoders); ++i) {
- if (!decoders[i])
- continue;
- decoder_ = std::move(decoders[i]);
- weak_decoder_factory_.reset(
- new base::WeakPtrFactory<VideoDecodeAccelerator>(decoder_.get()));
- if (decoder_->Initialize(profile_, client)) {
- SetState(CS_DECODER_SET);
- FinishInitialization();
- return;
- }
- }
- // Decoders are all initialize failed.
- LOG(ERROR) << "VideoDecodeAccelerator::Initialize() failed";
- LOG_ASSERT(false);
+ SetState(CS_DECODER_SET);
+ FinishInitialization();
}
void GLRenderingVDAClient::ProvidePictureBuffers(
uint32_t requested_num_of_buffers,
+ uint32_t textures_per_buffer,
const gfx::Size& dimensions,
uint32_t texture_target) {
if (decoder_deleted())
return;
+ LOG_ASSERT(textures_per_buffer == 1u);
std::vector<media::PictureBuffer> buffers;
requested_num_of_buffers += kExtraPictureBuffers;
@@ -637,8 +578,9 @@ void GLRenderingVDAClient::ProvidePictureBuffers(
texture_id))))
.second);
- buffers.push_back(
- media::PictureBuffer(picture_buffer_id, dimensions, texture_id));
+ media::PictureBuffer::TextureIds ids;
+ ids.push_back(texture_id);
+ buffers.push_back(media::PictureBuffer(picture_buffer_id, dimensions, ids));
}
decoder_->AssignPictureBuffers(buffers);
}
@@ -710,10 +652,8 @@ void GLRenderingVDAClient::ReturnPicture(int32_t picture_buffer_id) {
if (num_decoded_frames_ > delay_reuse_after_frame_num_) {
base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&VideoDecodeAccelerator::ReusePictureBuffer,
- weak_decoder_factory_->GetWeakPtr(),
- picture_buffer_id),
+ FROM_HERE, base::Bind(&VideoDecodeAccelerator::ReusePictureBuffer,
+ weak_vda_, picture_buffer_id),
kReuseDelay);
} else {
decoder_->ReusePictureBuffer(picture_buffer_id);
@@ -835,7 +775,7 @@ void GLRenderingVDAClient::FinishInitialization() {
void GLRenderingVDAClient::DeleteDecoder() {
if (decoder_deleted())
return;
- weak_decoder_factory_.reset();
+ weak_vda_ptr_factory_->InvalidateWeakPtrs();
decoder_.reset();
STLClearObject(&encoded_data_);
active_textures_.clear();
@@ -1196,17 +1136,6 @@ class VideoDecodeAcceleratorParamTest
base::Tuple<int, int, int, ResetPoint, ClientState, bool, bool> > {
};
-// Helper so that gtest failures emit a more readable version of the tuple than
-// its byte representation.
-::std::ostream& operator<<(
- ::std::ostream& os,
- const base::Tuple<int, int, int, ResetPoint, ClientState, bool, bool>& t) {
- return os << base::get<0>(t) << ", " << base::get<1>(t) << ", "
- << base::get<2>(t) << ", " << base::get<3>(t) << ", "
- << base::get<4>(t) << ", " << base::get<5>(t) << ", "
- << base::get<6>(t);
-}
-
// Wait for |note| to report a state and if it's not |expected_state| then
// assert |client| has deleted its decoder.
static void AssertWaitForStateOrDeleted(
diff --git a/chromium/content/common/gpu/media/video_encode_accelerator_unittest.cc b/chromium/content/common/gpu/media/video_encode_accelerator_unittest.cc
index 9224e89c72f..09f1c63ed23 100644
--- a/chromium/content/common/gpu/media/video_encode_accelerator_unittest.cc
+++ b/chromium/content/common/gpu/media/video_encode_accelerator_unittest.cc
@@ -55,6 +55,8 @@
// Status has been defined as int in Xlib.h.
#undef Status
#endif // defined(ARCH_CPU_X86_FAMILY)
+#elif defined(OS_MACOSX)
+#include "content/common/gpu/media/vt_video_encode_accelerator_mac.h"
#else
#error The VideoEncodeAcceleratorUnittest is not supported on this platform.
#endif
@@ -126,7 +128,11 @@ const unsigned int kLoggedLatencyPercentiles[] = {50, 75, 95};
// of the stream.
// Bitrate is only forced for tests that test bitrate.
const char* g_default_in_filename = "bear_320x192_40frames.yuv";
+#if !defined(OS_MACOSX)
const char* g_default_in_parameters = ":320:192:1:out.h264:200000";
+#else
+const char* g_default_in_parameters = ":320:192:0:out.h264:200000";
+#endif
// Enabled by including a --fake_encoder flag to the command line invoking the
// test.
@@ -623,8 +629,8 @@ class VideoFrameQualityValidator {
private:
void InitializeCB(bool success);
- void DecodeDone(media::VideoDecoder::Status status);
- void FlushDone(media::VideoDecoder::Status status);
+ void DecodeDone(media::DecodeStatus status);
+ void FlushDone(media::DecodeStatus status);
void VerifyOutputFrame(const scoped_refptr<media::VideoFrame>& output_frame);
void Decode();
@@ -670,16 +676,18 @@ void VideoFrameQualityValidator::Initialize(const gfx::Size& coded_size,
if (IsVP8(profile_))
config.Initialize(media::kCodecVP8, media::VP8PROFILE_ANY, kInputFormat,
media::COLOR_SPACE_UNSPECIFIED, coded_size, visible_size,
- natural_size, media::EmptyExtraData(), false);
+ natural_size, media::EmptyExtraData(),
+ media::Unencrypted());
else if (IsH264(profile_))
config.Initialize(media::kCodecH264, media::H264PROFILE_MAIN, kInputFormat,
media::COLOR_SPACE_UNSPECIFIED, coded_size, visible_size,
- natural_size, media::EmptyExtraData(), false);
+ natural_size, media::EmptyExtraData(),
+ media::Unencrypted());
else
LOG_ASSERT(0) << "Invalid profile " << profile_;
decoder_->Initialize(
- config, false, media::SetCdmReadyCB(),
+ config, false, nullptr,
base::Bind(&VideoFrameQualityValidator::InitializeCB,
base::Unretained(this)),
base::Bind(&VideoFrameQualityValidator::VerifyOutputFrame,
@@ -704,9 +712,8 @@ void VideoFrameQualityValidator::AddOriginalFrame(
original_frames_.push(frame);
}
-void VideoFrameQualityValidator::DecodeDone(
- media::VideoDecoder::Status status) {
- if (status == media::VideoDecoder::kOk) {
+void VideoFrameQualityValidator::DecodeDone(media::DecodeStatus status) {
+ if (status == media::DecodeStatus::OK) {
decoder_state_ = INITIALIZED;
Decode();
} else {
@@ -716,7 +723,7 @@ void VideoFrameQualityValidator::DecodeDone(
}
}
-void VideoFrameQualityValidator::FlushDone(media::VideoDecoder::Status status) {
+void VideoFrameQualityValidator::FlushDone(media::DecodeStatus status) {
flush_complete_cb_.Run();
}
@@ -810,6 +817,7 @@ class VEAClient : public VideoEncodeAccelerator::Client {
scoped_ptr<media::VideoEncodeAccelerator> CreateFakeVEA();
scoped_ptr<media::VideoEncodeAccelerator> CreateV4L2VEA();
scoped_ptr<media::VideoEncodeAccelerator> CreateVaapiVEA();
+ scoped_ptr<media::VideoEncodeAccelerator> CreateVTVEA();
void SetState(ClientState new_state);
@@ -1071,6 +1079,14 @@ scoped_ptr<media::VideoEncodeAccelerator> VEAClient::CreateVaapiVEA() {
return encoder;
}
+scoped_ptr<media::VideoEncodeAccelerator> VEAClient::CreateVTVEA() {
+ scoped_ptr<media::VideoEncodeAccelerator> encoder;
+#if defined(OS_MACOSX)
+ encoder.reset(new VTVideoEncodeAccelerator());
+#endif
+ return encoder;
+}
+
void VEAClient::CreateEncoder() {
DCHECK(thread_checker_.CalledOnValidThread());
LOG_ASSERT(!has_encoder());
@@ -1078,7 +1094,8 @@ void VEAClient::CreateEncoder() {
scoped_ptr<media::VideoEncodeAccelerator> encoders[] = {
CreateFakeVEA(),
CreateV4L2VEA(),
- CreateVaapiVEA()
+ CreateVaapiVEA(),
+ CreateVTVEA()
};
DVLOG(1) << "Profile: " << test_stream_->requested_profile
@@ -1649,6 +1666,7 @@ TEST_P(VideoEncodeAcceleratorTest, TestSimpleEncode) {
encoder_thread.Stop();
}
+#if !defined(OS_MACOSX)
INSTANTIATE_TEST_CASE_P(
SimpleEncode,
VideoEncodeAcceleratorTest,
@@ -1693,6 +1711,26 @@ INSTANTIATE_TEST_CASE_P(
base::MakeTuple(3, false, 0, false, false, false, false, false),
base::MakeTuple(3, false, 0, true, false, false, true, false),
base::MakeTuple(3, false, 0, true, false, true, false, false)));
+#else
+INSTANTIATE_TEST_CASE_P(
+ SimpleEncode,
+ VideoEncodeAcceleratorTest,
+ ::testing::Values(
+ base::MakeTuple(1, true, 0, false, false, false, false, false),
+ base::MakeTuple(1, true, 0, false, false, false, false, true)));
+
+INSTANTIATE_TEST_CASE_P(
+ EncoderPerf,
+ VideoEncodeAcceleratorTest,
+ ::testing::Values(
+ base::MakeTuple(1, false, 0, false, true, false, false, false)));
+
+INSTANTIATE_TEST_CASE_P(
+ MultipleEncoders,
+ VideoEncodeAcceleratorTest,
+ ::testing::Values(
+ base::MakeTuple(3, false, 0, false, false, false, false, false)));
+#endif
// TODO(posciak): more tests:
// - async FeedEncoderWithOutput
diff --git a/chromium/content/common/gpu/media/vt_video_decode_accelerator_mac.cc b/chromium/content/common/gpu/media/vt_video_decode_accelerator_mac.cc
index e74e6f64d55..1571e834620 100644
--- a/chromium/content/common/gpu/media/vt_video_decode_accelerator_mac.cc
+++ b/chromium/content/common/gpu/media/vt_video_decode_accelerator_mac.cc
@@ -10,7 +10,6 @@
#include <stddef.h>
#include "base/bind.h"
-#include "base/command_line.h"
#include "base/logging.h"
#include "base/mac/mac_logging.h"
#include "base/macros.h"
@@ -20,7 +19,6 @@
#include "base/thread_task_runner_handle.h"
#include "base/version.h"
#include "content/common/gpu/media/vt_video_decode_accelerator_mac.h"
-#include "content/public/common/content_switches.h"
#include "media/base/limits.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_image_io_surface.h"
@@ -46,7 +44,11 @@ static const media::VideoCodecProfile kSupportedProfiles[] = {
media::H264PROFILE_MAIN,
media::H264PROFILE_EXTENDED,
media::H264PROFILE_HIGH,
- media::H264PROFILE_HIGH10PROFILE,
+ // TODO(hubbe): Try to re-enable this again somehow. Currently it seems
+ // that some codecs fail to check the profile during initialization and
+ // then fail on the first frame decode, which currently results in a
+ // pipeline failure.
+ // media::H264PROFILE_HIGH10PROFILE,
media::H264PROFILE_SCALABLEBASELINE,
media::H264PROFILE_SCALABLEHIGH,
media::H264PROFILE_STEREOHIGH,
@@ -72,9 +74,9 @@ static base::ScopedCFTypeRef<CFMutableDictionaryRef>
BuildImageConfig(CMVideoDimensions coded_dimensions) {
base::ScopedCFTypeRef<CFMutableDictionaryRef> image_config;
- // 4:2:2 is used over the native 4:2:0 because only 4:2:2 can be directly
- // bound to a texture by CGLTexImageIOSurface2D().
- int32_t pixel_format = kCVPixelFormatType_422YpCbCr8;
+ // Note that 4:2:0 textures cannot be used directly as RGBA in OpenGL, but are
+ // lower power than 4:2:2 when composited directly by CoreAnimation.
+ int32_t pixel_format = kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange;
#define CFINT(i) CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &i)
base::ScopedCFTypeRef<CFNumberRef> cf_pixel_format(CFINT(pixel_format));
base::ScopedCFTypeRef<CFNumberRef> cf_width(CFINT(coded_dimensions.width));
@@ -86,7 +88,7 @@ BuildImageConfig(CMVideoDimensions coded_dimensions) {
image_config.reset(
CFDictionaryCreateMutable(
kCFAllocatorDefault,
- 4, // capacity
+ 3, // capacity
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks));
if (!image_config.get())
@@ -96,8 +98,6 @@ BuildImageConfig(CMVideoDimensions coded_dimensions) {
cf_pixel_format);
CFDictionarySetValue(image_config, kCVPixelBufferWidthKey, cf_width);
CFDictionarySetValue(image_config, kCVPixelBufferHeightKey, cf_height);
- CFDictionarySetValue(image_config, kCVPixelBufferOpenGLCompatibilityKey,
- kCFBooleanTrue);
return image_config;
}
@@ -175,11 +175,6 @@ static bool CreateVideoToolboxSession(const uint8_t* sps, size_t sps_size,
// session fails, hardware decoding will be disabled (Initialize() will always
// return false).
static bool InitializeVideoToolboxInternal() {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableAcceleratedVideoDecode)) {
- return false;
- }
-
if (!IsVtInitialized()) {
// CoreVideo is also required, but the loader stops after the first path is
// loaded. Instead we rely on the transitive dependency from VideoToolbox to
@@ -255,6 +250,8 @@ static void OutputThunk(
VTVideoDecodeAccelerator::Task::Task(TaskType type) : type(type) {
}
+VTVideoDecodeAccelerator::Task::Task(const Task& other) = default;
+
VTVideoDecodeAccelerator::Task::~Task() {
}
@@ -291,11 +288,10 @@ bool VTVideoDecodeAccelerator::FrameOrder::operator()(
}
VTVideoDecodeAccelerator::VTVideoDecodeAccelerator(
- const base::Callback<bool(void)>& make_context_current,
- const base::Callback<void(uint32_t, uint32_t, scoped_refptr<gl::GLImage>)>&
- bind_image)
- : make_context_current_(make_context_current),
- bind_image_(bind_image),
+ const MakeGLContextCurrentCallback& make_context_current_cb,
+ const BindGLImageCallback& bind_image_cb)
+ : make_context_current_cb_(make_context_current_cb),
+ bind_image_cb_(bind_image_cb),
client_(nullptr),
state_(STATE_DECODING),
format_(nullptr),
@@ -307,7 +303,6 @@ VTVideoDecodeAccelerator::VTVideoDecodeAccelerator(
gpu_task_runner_(base::ThreadTaskRunnerHandle::Get()),
decoder_thread_("VTDecoderThread"),
weak_this_factory_(this) {
- DCHECK(!make_context_current_.is_null());
callback_.decompressionOutputCallback = OutputThunk;
callback_.decompressionOutputRefCon = this;
weak_this_ = weak_this_factory_.GetWeakPtr();
@@ -321,6 +316,11 @@ bool VTVideoDecodeAccelerator::Initialize(const Config& config,
Client* client) {
DCHECK(gpu_thread_checker_.CalledOnValidThread());
+ if (make_context_current_cb_.is_null() || bind_image_cb_.is_null()) {
+ NOTREACHED() << "GL callbacks are required for this VDA";
+ return false;
+ }
+
if (config.is_encrypted) {
NOTREACHED() << "Encrypted streams are not supported for this VDA";
return false;
@@ -622,23 +622,21 @@ void VTVideoDecodeAccelerator::DecodeTask(
config_changed_ = true;
}
if (config_changed_) {
- if (last_sps_.empty()) {
- config_changed_ = false;
- DLOG(ERROR) << "Invalid configuration; no SPS";
- NotifyError(INVALID_ARGUMENT, SFT_INVALID_STREAM);
- return;
- }
- if (last_pps_.empty()) {
- config_changed_ = false;
- DLOG(ERROR) << "Invalid configuration; no PPS";
- NotifyError(INVALID_ARGUMENT, SFT_INVALID_STREAM);
- return;
- }
-
// Only reconfigure at IDRs to avoid corruption.
if (frame->is_idr) {
config_changed_ = false;
+ if (last_sps_.empty()) {
+ DLOG(ERROR) << "Invalid configuration; no SPS";
+ NotifyError(INVALID_ARGUMENT, SFT_INVALID_STREAM);
+ return;
+ }
+ if (last_pps_.empty()) {
+ DLOG(ERROR) << "Invalid configuration; no PPS";
+ NotifyError(INVALID_ARGUMENT, SFT_INVALID_STREAM);
+ return;
+ }
+
// ConfigureDecoder() calls NotifyError() on failure.
if (!ConfigureDecoder())
return;
@@ -825,6 +823,13 @@ void VTVideoDecodeAccelerator::FlushDone(TaskType type) {
void VTVideoDecodeAccelerator::Decode(const media::BitstreamBuffer& bitstream) {
DCHECK(gpu_thread_checker_.CalledOnValidThread());
+ if (bitstream.id() < 0) {
+ DLOG(ERROR) << "Invalid bitstream, id: " << bitstream.id();
+ if (base::SharedMemory::IsHandleValid(bitstream.handle()))
+ base::SharedMemory::CloseHandle(bitstream.handle());
+ NotifyError(INVALID_ARGUMENT, SFT_INVALID_STREAM);
+ return;
+ }
DCHECK_EQ(0u, assigned_bitstream_ids_.count(bitstream.id()));
assigned_bitstream_ids_.insert(bitstream.id());
Frame* frame = new Frame(bitstream.id());
@@ -842,10 +847,12 @@ void VTVideoDecodeAccelerator::AssignPictureBuffers(
DCHECK(!picture_info_map_.count(picture.id()));
assigned_picture_ids_.insert(picture.id());
available_picture_ids_.push_back(picture.id());
+ DCHECK_LE(1u, picture.internal_texture_ids().size());
+ DCHECK_LE(1u, picture.texture_ids().size());
picture_info_map_.insert(std::make_pair(
picture.id(),
- make_scoped_ptr(new PictureInfo(picture.internal_texture_id(),
- picture.texture_id()))));
+ make_scoped_ptr(new PictureInfo(picture.internal_texture_ids()[0],
+ picture.texture_ids()[0]))));
}
// Pictures are not marked as uncleared until after this method returns, and
@@ -859,7 +866,7 @@ void VTVideoDecodeAccelerator::ReusePictureBuffer(int32_t picture_id) {
DCHECK(gpu_thread_checker_.CalledOnValidThread());
DCHECK(picture_info_map_.count(picture_id));
PictureInfo* picture_info = picture_info_map_.find(picture_id)->second.get();
- DCHECK_EQ(CFGetRetainCount(picture_info->cv_image), 1);
+ DCHECK_EQ(CFGetRetainCount(picture_info->cv_image), 2);
picture_info->cv_image.reset();
picture_info->gl_image->Destroy(false);
picture_info->gl_image = nullptr;
@@ -1002,8 +1009,8 @@ bool VTVideoDecodeAccelerator::ProcessFrame(const Frame& frame) {
// Request new pictures.
picture_size_ = frame.coded_size;
- client_->ProvidePictureBuffers(
- kNumPictureBuffers, coded_size_, GL_TEXTURE_RECTANGLE_ARB);
+ client_->ProvidePictureBuffers(kNumPictureBuffers, 1, coded_size_,
+ GL_TEXTURE_RECTANGLE_ARB);
return false;
}
if (!SendFrame(frame))
@@ -1026,47 +1033,27 @@ bool VTVideoDecodeAccelerator::SendFrame(const Frame& frame) {
DCHECK(!picture_info->cv_image);
DCHECK(!picture_info->gl_image);
- if (!make_context_current_.Run()) {
+ if (!make_context_current_cb_.Run()) {
DLOG(ERROR) << "Failed to make GL context current";
NotifyError(PLATFORM_FAILURE, SFT_PLATFORM_ERROR);
return false;
}
- IOSurfaceRef surface = CVPixelBufferGetIOSurface(frame.image.get());
- if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGLCoreProfile)
- glEnable(GL_TEXTURE_RECTANGLE_ARB);
- gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_RECTANGLE_ARB,
- picture_info->service_texture_id);
- CGLContextObj cgl_context =
- static_cast<CGLContextObj>(gfx::GLContext::GetCurrent()->GetHandle());
- CGLError status = CGLTexImageIOSurface2D(
- cgl_context, // ctx
- GL_TEXTURE_RECTANGLE_ARB, // target
- GL_RGB, // internal_format
- frame.coded_size.width(), // width
- frame.coded_size.height(), // height
- GL_YCBCR_422_APPLE, // format
- GL_UNSIGNED_SHORT_8_8_APPLE, // type
- surface, // io_surface
- 0); // plane
- if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGLCoreProfile)
- glDisable(GL_TEXTURE_RECTANGLE_ARB);
- if (status != kCGLNoError) {
- NOTIFY_STATUS("CGLTexImageIOSurface2D()", status, SFT_PLATFORM_ERROR);
- return false;
- }
-
- bool allow_overlay = false;
scoped_refptr<gl::GLImageIOSurface> gl_image(
new gl::GLImageIOSurface(frame.coded_size, GL_BGRA_EXT));
- if (gl_image->Initialize(surface, gfx::GenericSharedMemoryId(),
- gfx::BufferFormat::BGRA_8888)) {
- allow_overlay = true;
- } else {
- gl_image = nullptr;
+ if (!gl_image->InitializeWithCVPixelBuffer(
+ frame.image.get(), gfx::GenericSharedMemoryId(),
+ gfx::BufferFormat::YUV_420_BIPLANAR)) {
+ NOTIFY_STATUS("Failed to initialize GLImageIOSurface", PLATFORM_FAILURE,
+ SFT_PLATFORM_ERROR);
+ }
+
+ if (!bind_image_cb_.Run(picture_info->client_texture_id,
+ GL_TEXTURE_RECTANGLE_ARB, gl_image, false)) {
+ DLOG(ERROR) << "Failed to bind image";
+ NotifyError(PLATFORM_FAILURE, SFT_PLATFORM_ERROR);
+ return false;
}
- bind_image_.Run(picture_info->client_texture_id, GL_TEXTURE_RECTANGLE_ARB,
- gl_image);
// Assign the new image(s) to the the picture info.
picture_info->gl_image = gl_image;
@@ -1080,7 +1067,7 @@ bool VTVideoDecodeAccelerator::SendFrame(const Frame& frame) {
// coded size and fix it.
client_->PictureReady(media::Picture(picture_id, frame.bitstream_id,
gfx::Rect(frame.coded_size),
- allow_overlay));
+ true));
return true;
}
@@ -1143,7 +1130,9 @@ void VTVideoDecodeAccelerator::Destroy() {
QueueFlush(TASK_DESTROY);
}
-bool VTVideoDecodeAccelerator::CanDecodeOnIOThread() {
+bool VTVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread(
+ const base::WeakPtr<Client>& decode_client,
+ const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) {
return false;
}
diff --git a/chromium/content/common/gpu/media/vt_video_decode_accelerator_mac.h b/chromium/content/common/gpu/media/vt_video_decode_accelerator_mac.h
index 2d222163823..22fc8b1d6ad 100644
--- a/chromium/content/common/gpu/media/vt_video_decode_accelerator_mac.h
+++ b/chromium/content/common/gpu/media/vt_video_decode_accelerator_mac.h
@@ -17,6 +17,7 @@
#include "base/message_loop/message_loop.h"
#include "base/threading/thread.h"
#include "base/threading/thread_checker.h"
+#include "content/common/gpu/media/gpu_video_decode_accelerator_helpers.h"
#include "content/common/gpu/media/vt_mac.h"
#include "media/filters/h264_parser.h"
#include "media/video/h264_poc.h"
@@ -35,9 +36,9 @@ bool InitializeVideoToolbox();
class VTVideoDecodeAccelerator : public media::VideoDecodeAccelerator {
public:
explicit VTVideoDecodeAccelerator(
- const base::Callback<bool(void)>& make_context_current,
- const base::Callback<
- void(uint32_t, uint32_t, scoped_refptr<gl::GLImage>)>& bind_image);
+ const MakeGLContextCurrentCallback& make_context_current_cb,
+ const BindGLImageCallback& bind_image_cb);
+
~VTVideoDecodeAccelerator() override;
// VideoDecodeAccelerator implementation.
@@ -49,7 +50,10 @@ class VTVideoDecodeAccelerator : public media::VideoDecodeAccelerator {
void Flush() override;
void Reset() override;
void Destroy() override;
- bool CanDecodeOnIOThread() override;
+ bool TryToSetupDecodeOnSeparateThread(
+ const base::WeakPtr<Client>& decode_client,
+ const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner)
+ override;
// Called by OutputThunk() when VideoToolbox finishes decoding a frame.
void Output(
@@ -114,6 +118,7 @@ class VTVideoDecodeAccelerator : public media::VideoDecodeAccelerator {
struct Task {
Task(TaskType type);
+ Task(const Task& other);
~Task();
TaskType type;
@@ -189,9 +194,9 @@ class VTVideoDecodeAccelerator : public media::VideoDecodeAccelerator {
//
// GPU thread state.
//
- base::Callback<bool(void)> make_context_current_;
- base::Callback<void(uint32_t, uint32_t, scoped_refptr<gl::GLImage>)>
- bind_image_;
+ MakeGLContextCurrentCallback make_context_current_cb_;
+ BindGLImageCallback bind_image_cb_;
+
media::VideoDecodeAccelerator::Client* client_;
State state_;
diff --git a/chromium/content/common/gpu/media/vt_video_encode_accelerator_mac.cc b/chromium/content/common/gpu/media/vt_video_encode_accelerator_mac.cc
new file mode 100644
index 00000000000..71c80ef3a9f
--- /dev/null
+++ b/chromium/content/common/gpu/media/vt_video_encode_accelerator_mac.cc
@@ -0,0 +1,552 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/gpu/media/vt_video_encode_accelerator_mac.h"
+
+#include "base/thread_task_runner_handle.h"
+#include "media/base/mac/coremedia_glue.h"
+#include "media/base/mac/corevideo_glue.h"
+#include "media/base/mac/video_frame_mac.h"
+
+namespace content {
+
+namespace {
+
+// TODO(emircan): Check if we can find the actual system capabilities via
+// creating VTCompressionSessions with varying requirements.
+// See crbug.com/584784.
+const size_t kBitsPerByte = 8;
+const size_t kDefaultResolutionWidth = 640;
+const size_t kDefaultResolutionHeight = 480;
+const size_t kMaxFrameRateNumerator = 30;
+const size_t kMaxFrameRateDenominator = 1;
+const size_t kMaxResolutionWidth = 4096;
+const size_t kMaxResolutionHeight = 2160;
+const size_t kNumInputBuffers = 3;
+
+} // namespace
+
+struct VTVideoEncodeAccelerator::InProgressFrameEncode {
+ InProgressFrameEncode(base::TimeDelta rtp_timestamp,
+ base::TimeTicks ref_time)
+ : timestamp(rtp_timestamp), reference_time(ref_time) {}
+ const base::TimeDelta timestamp;
+ const base::TimeTicks reference_time;
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(InProgressFrameEncode);
+};
+
+struct VTVideoEncodeAccelerator::EncodeOutput {
+ EncodeOutput(VTEncodeInfoFlags info_flags, CMSampleBufferRef sbuf)
+ : info(info_flags), sample_buffer(sbuf, base::scoped_policy::RETAIN) {}
+ const VTEncodeInfoFlags info;
+ const base::ScopedCFTypeRef<CMSampleBufferRef> sample_buffer;
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(EncodeOutput);
+};
+
+struct VTVideoEncodeAccelerator::BitstreamBufferRef {
+ BitstreamBufferRef(int32_t id,
+ scoped_ptr<base::SharedMemory> shm,
+ size_t size)
+ : id(id), shm(std::move(shm)), size(size) {}
+ const int32_t id;
+ const scoped_ptr<base::SharedMemory> shm;
+ const size_t size;
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(BitstreamBufferRef);
+};
+
+VTVideoEncodeAccelerator::VTVideoEncodeAccelerator()
+ : client_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+ encoder_thread_("VTEncoderThread"),
+ encoder_task_weak_factory_(this) {
+ encoder_weak_ptr_ = encoder_task_weak_factory_.GetWeakPtr();
+}
+
+VTVideoEncodeAccelerator::~VTVideoEncodeAccelerator() {
+ DVLOG(3) << __FUNCTION__;
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ Destroy();
+ DCHECK(!encoder_thread_.IsRunning());
+ DCHECK(!encoder_task_weak_factory_.HasWeakPtrs());
+}
+
+media::VideoEncodeAccelerator::SupportedProfiles
+VTVideoEncodeAccelerator::GetSupportedProfiles() {
+ DVLOG(3) << __FUNCTION__;
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ SupportedProfiles profiles;
+ // Check if HW encoder is supported initially.
+ videotoolbox_glue_ = VideoToolboxGlue::Get();
+ if (!videotoolbox_glue_) {
+ DLOG(ERROR) << "Failed creating VideoToolbox glue.";
+ return profiles;
+ }
+ const bool rv = CreateCompressionSession(
+ media::video_toolbox::DictionaryWithKeysAndValues(nullptr, nullptr, 0),
+ gfx::Size(kDefaultResolutionWidth, kDefaultResolutionHeight), true);
+ DestroyCompressionSession();
+ if (!rv) {
+ VLOG(1)
+ << "Hardware encode acceleration is not available on this platform.";
+ return profiles;
+ }
+
+ SupportedProfile profile;
+ profile.profile = media::H264PROFILE_BASELINE;
+ profile.max_framerate_numerator = kMaxFrameRateNumerator;
+ profile.max_framerate_denominator = kMaxFrameRateDenominator;
+ profile.max_resolution = gfx::Size(kMaxResolutionWidth, kMaxResolutionHeight);
+ profiles.push_back(profile);
+ return profiles;
+}
+
+bool VTVideoEncodeAccelerator::Initialize(
+ media::VideoPixelFormat format,
+ const gfx::Size& input_visible_size,
+ media::VideoCodecProfile output_profile,
+ uint32_t initial_bitrate,
+ Client* client) {
+ DVLOG(3) << __FUNCTION__
+ << ": input_format=" << media::VideoPixelFormatToString(format)
+ << ", input_visible_size=" << input_visible_size.ToString()
+ << ", output_profile=" << output_profile
+ << ", initial_bitrate=" << initial_bitrate;
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(client);
+
+ if (media::PIXEL_FORMAT_I420 != format) {
+ DLOG(ERROR) << "Input format not supported= "
+ << media::VideoPixelFormatToString(format);
+ return false;
+ }
+ if (media::H264PROFILE_BASELINE != output_profile) {
+ DLOG(ERROR) << "Output profile not supported= "
+ << output_profile;
+ return false;
+ }
+
+ videotoolbox_glue_ = VideoToolboxGlue::Get();
+ if (!videotoolbox_glue_) {
+ DLOG(ERROR) << "Failed creating VideoToolbox glue.";
+ return false;
+ }
+
+ client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client));
+ client_ = client_ptr_factory_->GetWeakPtr();
+ input_visible_size_ = input_visible_size;
+ frame_rate_ = kMaxFrameRateNumerator / kMaxFrameRateDenominator;
+ target_bitrate_ = initial_bitrate;
+ bitstream_buffer_size_ = input_visible_size.GetArea();
+
+ if (!encoder_thread_.Start()) {
+ DLOG(ERROR) << "Failed spawning encoder thread.";
+ return false;
+ }
+ encoder_thread_task_runner_ = encoder_thread_.task_runner();
+
+ if (!ResetCompressionSession()) {
+ DLOG(ERROR) << "Failed creating compression session.";
+ return false;
+ }
+
+ client_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&Client::RequireBitstreamBuffers, client_, kNumInputBuffers,
+ input_visible_size_, bitstream_buffer_size_));
+ return true;
+}
+
+void VTVideoEncodeAccelerator::Encode(
+ const scoped_refptr<media::VideoFrame>& frame,
+ bool force_keyframe) {
+ DVLOG(3) << __FUNCTION__;
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ encoder_thread_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&VTVideoEncodeAccelerator::EncodeTask,
+ base::Unretained(this), frame, force_keyframe));
+}
+
+void VTVideoEncodeAccelerator::UseOutputBitstreamBuffer(
+ const media::BitstreamBuffer& buffer) {
+ DVLOG(3) << __FUNCTION__ << ": buffer size=" << buffer.size();
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (buffer.size() < bitstream_buffer_size_) {
+ DLOG(ERROR) << "Output BitstreamBuffer isn't big enough: " << buffer.size()
+ << " vs. " << bitstream_buffer_size_;
+ client_->NotifyError(kInvalidArgumentError);
+ return;
+ }
+
+ scoped_ptr<base::SharedMemory> shm(
+ new base::SharedMemory(buffer.handle(), false));
+ if (!shm->Map(buffer.size())) {
+ DLOG(ERROR) << "Failed mapping shared memory.";
+ client_->NotifyError(kPlatformFailureError);
+ return;
+ }
+
+ scoped_ptr<BitstreamBufferRef> buffer_ref(
+ new BitstreamBufferRef(buffer.id(), std::move(shm), buffer.size()));
+
+ encoder_thread_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&VTVideoEncodeAccelerator::UseOutputBitstreamBufferTask,
+ base::Unretained(this), base::Passed(&buffer_ref)));
+}
+
+void VTVideoEncodeAccelerator::RequestEncodingParametersChange(
+ uint32_t bitrate,
+ uint32_t framerate) {
+ DVLOG(3) << __FUNCTION__ << ": bitrate=" << bitrate
+ << ": framerate=" << framerate;
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ encoder_thread_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&VTVideoEncodeAccelerator::RequestEncodingParametersChangeTask,
+ base::Unretained(this), bitrate, framerate));
+}
+
+void VTVideoEncodeAccelerator::Destroy() {
+ DVLOG(3) << __FUNCTION__;
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ // Cancel all callbacks.
+ client_ptr_factory_.reset();
+
+ if (encoder_thread_.IsRunning()) {
+ encoder_thread_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&VTVideoEncodeAccelerator::DestroyTask,
+ base::Unretained(this)));
+ encoder_thread_.Stop();
+ } else {
+ DestroyTask();
+ }
+}
+
+void VTVideoEncodeAccelerator::EncodeTask(
+ const scoped_refptr<media::VideoFrame>& frame,
+ bool force_keyframe) {
+ DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread());
+ DCHECK(compression_session_);
+ DCHECK(frame);
+
+ // TODO(emircan): See if we can eliminate a copy here by using
+ // CVPixelBufferPool for the allocation of incoming VideoFrames.
+ base::ScopedCFTypeRef<CVPixelBufferRef> pixel_buffer =
+ media::WrapVideoFrameInCVPixelBuffer(*frame);
+ base::ScopedCFTypeRef<CFDictionaryRef> frame_props =
+ media::video_toolbox::DictionaryWithKeyValue(
+ videotoolbox_glue_->kVTEncodeFrameOptionKey_ForceKeyFrame(),
+ force_keyframe ? kCFBooleanTrue : kCFBooleanFalse);
+
+ base::TimeTicks ref_time;
+ if (!frame->metadata()->GetTimeTicks(
+ media::VideoFrameMetadata::REFERENCE_TIME, &ref_time)) {
+ ref_time = base::TimeTicks::Now();
+ }
+ auto timestamp_cm = CoreMediaGlue::CMTimeMake(
+ frame->timestamp().InMicroseconds(), USEC_PER_SEC);
+ // Wrap information we'll need after the frame is encoded in a heap object.
+ // We'll get the pointer back from the VideoToolbox completion callback.
+ scoped_ptr<InProgressFrameEncode> request(new InProgressFrameEncode(
+ frame->timestamp(), ref_time));
+
+ // We can pass the ownership of |request| to the encode callback if
+ // successful. Otherwise let it fall out of scope.
+ OSStatus status = videotoolbox_glue_->VTCompressionSessionEncodeFrame(
+ compression_session_, pixel_buffer, timestamp_cm,
+ CoreMediaGlue::CMTime{0, 0, 0, 0}, frame_props,
+ reinterpret_cast<void*>(request.get()), nullptr);
+ if (status != noErr) {
+ DLOG(ERROR) << " VTCompressionSessionEncodeFrame failed: " << status;
+ NotifyError(kPlatformFailureError);
+ } else {
+ CHECK(request.release());
+ }
+}
+
+void VTVideoEncodeAccelerator::UseOutputBitstreamBufferTask(
+ scoped_ptr<BitstreamBufferRef> buffer_ref) {
+ DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread());
+
+ // If there is already EncodeOutput waiting, copy its output first.
+ if (!encoder_output_queue_.empty()) {
+ scoped_ptr<VTVideoEncodeAccelerator::EncodeOutput> encode_output =
+ std::move(encoder_output_queue_.front());
+ encoder_output_queue_.pop_front();
+ ReturnBitstreamBuffer(std::move(encode_output), std::move(buffer_ref));
+ return;
+ }
+
+ bitstream_buffer_queue_.push_back(std::move(buffer_ref));
+}
+
+void VTVideoEncodeAccelerator::RequestEncodingParametersChangeTask(
+ uint32_t bitrate,
+ uint32_t framerate) {
+ DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread());
+
+ frame_rate_ = framerate > 1 ? framerate : 1;
+ target_bitrate_ = bitrate > 1 ? bitrate : 1;
+
+ if (!compression_session_) {
+ NotifyError(kPlatformFailureError);
+ return;
+ }
+
+ media::video_toolbox::SessionPropertySetter session_property_setter(
+ compression_session_, videotoolbox_glue_);
+ // TODO(emircan): See crbug.com/425352.
+ bool rv = session_property_setter.Set(
+ videotoolbox_glue_->kVTCompressionPropertyKey_AverageBitRate(),
+ target_bitrate_);
+ rv &= session_property_setter.Set(
+ videotoolbox_glue_->kVTCompressionPropertyKey_ExpectedFrameRate(),
+ frame_rate_);
+ rv &= session_property_setter.Set(
+ videotoolbox_glue_->kVTCompressionPropertyKey_DataRateLimits(),
+ media::video_toolbox::ArrayWithIntegerAndFloat(
+ target_bitrate_ / kBitsPerByte, 1.0f));
+ DLOG_IF(ERROR, !rv) << "Couldn't change session encoding parameters.";
+}
+
+void VTVideoEncodeAccelerator::DestroyTask() {
+ DCHECK(thread_checker_.CalledOnValidThread() ||
+ (encoder_thread_.IsRunning() &&
+ encoder_thread_task_runner_->BelongsToCurrentThread()));
+
+ // Cancel all encoder thread callbacks.
+ encoder_task_weak_factory_.InvalidateWeakPtrs();
+
+ // This call blocks until all pending frames are flushed out.
+ DestroyCompressionSession();
+}
+
+void VTVideoEncodeAccelerator::NotifyError(
+ media::VideoEncodeAccelerator::Error error) {
+ DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread());
+ client_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&Client::NotifyError, client_, error));
+}
+
+// static
+void VTVideoEncodeAccelerator::CompressionCallback(void* encoder_opaque,
+ void* request_opaque,
+ OSStatus status,
+ VTEncodeInfoFlags info,
+ CMSampleBufferRef sbuf) {
+ // This function may be called asynchronously, on a different thread from the
+ // one that calls VTCompressionSessionEncodeFrame.
+ DVLOG(3) << __FUNCTION__;
+
+ auto encoder = reinterpret_cast<VTVideoEncodeAccelerator*>(encoder_opaque);
+ DCHECK(encoder);
+
+ // Release InProgressFrameEncode, since we don't have support to return
+ // timestamps at this point.
+ scoped_ptr<InProgressFrameEncode> request(
+ reinterpret_cast<InProgressFrameEncode*>(request_opaque));
+ request.reset();
+
+ // EncodeOutput holds onto CMSampleBufferRef when posting task between
+ // threads.
+ scoped_ptr<EncodeOutput> encode_output(new EncodeOutput(info, sbuf));
+
+ // This method is NOT called on |encoder_thread_|, so we still need to
+ // post a task back to it to do work.
+ encoder->encoder_thread_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&VTVideoEncodeAccelerator::CompressionCallbackTask,
+ encoder->encoder_weak_ptr_, status,
+ base::Passed(&encode_output)));
+}
+
+void VTVideoEncodeAccelerator::CompressionCallbackTask(
+ OSStatus status,
+ scoped_ptr<EncodeOutput> encode_output) {
+ DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread());
+
+ if (status != noErr) {
+ DLOG(ERROR) << " encode failed: " << status;
+ NotifyError(kPlatformFailureError);
+ return;
+ }
+
+ // If there isn't any BitstreamBuffer to copy into, add it to a queue for
+ // later use.
+ if (bitstream_buffer_queue_.empty()) {
+ encoder_output_queue_.push_back(std::move(encode_output));
+ return;
+ }
+
+ scoped_ptr<VTVideoEncodeAccelerator::BitstreamBufferRef> buffer_ref =
+ std::move(bitstream_buffer_queue_.front());
+ bitstream_buffer_queue_.pop_front();
+ ReturnBitstreamBuffer(std::move(encode_output), std::move(buffer_ref));
+}
+
+void VTVideoEncodeAccelerator::ReturnBitstreamBuffer(
+ scoped_ptr<EncodeOutput> encode_output,
+ scoped_ptr<VTVideoEncodeAccelerator::BitstreamBufferRef> buffer_ref) {
+ DVLOG(3) << __FUNCTION__;
+ DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread());
+
+ if (encode_output->info & VideoToolboxGlue::kVTEncodeInfo_FrameDropped) {
+ DVLOG(2) << " frame dropped";
+ client_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&Client::BitstreamBufferReady, client_,
+ buffer_ref->id, 0, false));
+ return;
+ }
+
+ auto sample_attachments = static_cast<CFDictionaryRef>(CFArrayGetValueAtIndex(
+ CoreMediaGlue::CMSampleBufferGetSampleAttachmentsArray(
+ encode_output->sample_buffer.get(), true),
+ 0));
+ const bool keyframe =
+ !CFDictionaryContainsKey(sample_attachments,
+ CoreMediaGlue::kCMSampleAttachmentKey_NotSync());
+
+ size_t used_buffer_size = 0;
+ const bool copy_rv = media::video_toolbox::CopySampleBufferToAnnexBBuffer(
+ encode_output->sample_buffer.get(), keyframe, buffer_ref->size,
+ reinterpret_cast<char*>(buffer_ref->shm->memory()), &used_buffer_size);
+ if (!copy_rv) {
+ DLOG(ERROR) << "Cannot copy output from SampleBuffer to AnnexBBuffer.";
+ used_buffer_size = 0;
+ }
+
+ client_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&Client::BitstreamBufferReady, client_,
+ buffer_ref->id, used_buffer_size, keyframe));
+}
+
+bool VTVideoEncodeAccelerator::ResetCompressionSession() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ DestroyCompressionSession();
+
+ CFTypeRef attributes_keys[] = {
+ kCVPixelBufferOpenGLCompatibilityKey,
+ kCVPixelBufferIOSurfacePropertiesKey,
+ kCVPixelBufferPixelFormatTypeKey
+ };
+ const int format[] = {
+ CoreVideoGlue::kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange};
+ CFTypeRef attributes_values[] = {
+ kCFBooleanTrue,
+ media::video_toolbox::DictionaryWithKeysAndValues(nullptr, nullptr, 0)
+ .release(),
+ media::video_toolbox::ArrayWithIntegers(format, arraysize(format))
+ .release()};
+ const base::ScopedCFTypeRef<CFDictionaryRef> attributes =
+ media::video_toolbox::DictionaryWithKeysAndValues(
+ attributes_keys, attributes_values, arraysize(attributes_keys));
+ for (auto& v : attributes_values)
+ CFRelease(v);
+
+ bool session_rv =
+ CreateCompressionSession(attributes, input_visible_size_, false);
+ if (!session_rv) {
+ DestroyCompressionSession();
+ return false;
+ }
+
+ const bool configure_rv = ConfigureCompressionSession();
+ if (configure_rv)
+ RequestEncodingParametersChange(target_bitrate_, frame_rate_);
+ return configure_rv;
+}
+
+bool VTVideoEncodeAccelerator::CreateCompressionSession(
+ base::ScopedCFTypeRef<CFDictionaryRef> attributes,
+ const gfx::Size& input_size,
+ bool require_hw_encoding) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ std::vector<CFTypeRef> encoder_keys;
+ std::vector<CFTypeRef> encoder_values;
+ if (require_hw_encoding) {
+ encoder_keys.push_back(videotoolbox_glue_
+ ->kVTVideoEncoderSpecification_RequireHardwareAcceleratedVideoEncoder());
+ encoder_values.push_back(kCFBooleanTrue);
+ } else {
+ encoder_keys.push_back(videotoolbox_glue_
+ ->kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder());
+ encoder_values.push_back(kCFBooleanTrue);
+ }
+ base::ScopedCFTypeRef<CFDictionaryRef> encoder_spec =
+ media::video_toolbox::DictionaryWithKeysAndValues(
+ encoder_keys.data(), encoder_values.data(), encoder_keys.size());
+
+ // Create the compression session.
+ // Note that the encoder object is given to the compression session as the
+ // callback context using a raw pointer. The C API does not allow us to use a
+ // smart pointer, nor is this encoder ref counted. However, this is still
+ // safe, because we 1) we own the compression session and 2) we tear it down
+ // safely. When destructing the encoder, the compression session is flushed
+ // and invalidated. Internally, VideoToolbox will join all of its threads
+ // before returning to the client. Therefore, when control returns to us, we
+ // are guaranteed that the output callback will not execute again.
+ OSStatus status = videotoolbox_glue_->VTCompressionSessionCreate(
+ kCFAllocatorDefault,
+ input_size.width(),
+ input_size.height(),
+ CoreMediaGlue::kCMVideoCodecType_H264,
+ encoder_spec,
+ attributes,
+ nullptr /* compressedDataAllocator */,
+ &VTVideoEncodeAccelerator::CompressionCallback,
+ reinterpret_cast<void*>(this),
+ compression_session_.InitializeInto());
+ if (status != noErr) {
+ DLOG(ERROR) << " VTCompressionSessionCreate failed: " << status;
+ return false;
+ }
+ DVLOG(3) << " VTCompressionSession created with HW encode: "
+ << require_hw_encoding << ", input size=" << input_size.ToString();
+ return true;
+}
+
+bool VTVideoEncodeAccelerator::ConfigureCompressionSession() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(compression_session_);
+
+ media::video_toolbox::SessionPropertySetter session_property_setter(
+ compression_session_, videotoolbox_glue_);
+ bool rv = true;
+ rv &= session_property_setter.Set(
+ videotoolbox_glue_->kVTCompressionPropertyKey_ProfileLevel(),
+ videotoolbox_glue_->kVTProfileLevel_H264_Baseline_AutoLevel());
+ rv &= session_property_setter.Set(
+ videotoolbox_glue_->kVTCompressionPropertyKey_RealTime(), true);
+ rv &= session_property_setter.Set(
+ videotoolbox_glue_->kVTCompressionPropertyKey_AllowFrameReordering(),
+ false);
+ DLOG_IF(ERROR, !rv) << " Setting session property failed.";
+ return rv;
+}
+
+void VTVideoEncodeAccelerator::DestroyCompressionSession() {
+ DCHECK(thread_checker_.CalledOnValidThread() ||
+ (encoder_thread_.IsRunning() &&
+ encoder_thread_task_runner_->BelongsToCurrentThread()));
+
+ if (compression_session_) {
+ videotoolbox_glue_->VTCompressionSessionInvalidate(compression_session_);
+ compression_session_.reset();
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/common/gpu/media/vt_video_encode_accelerator_mac.h b/chromium/content/common/gpu/media/vt_video_encode_accelerator_mac.h
new file mode 100644
index 00000000000..aa4b37ed22d
--- /dev/null
+++ b/chromium/content/common/gpu/media/vt_video_encode_accelerator_mac.h
@@ -0,0 +1,142 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_GPU_MEDIA_VT_VIDEO_ENCODE_ACCELERATOR_MAC_H_
+#define CONTENT_COMMON_GPU_MEDIA_VT_VIDEO_ENCODE_ACCELERATOR_MAC_H_
+
+#include "base/mac/scoped_cftyperef.h"
+#include "content/common/content_export.h"
+#include "media/base/mac/videotoolbox_glue.h"
+#include "media/base/mac/videotoolbox_helpers.h"
+#include "media/video/video_encode_accelerator.h"
+
+namespace content {
+
+// VideoToolbox.framework implementation of the VideoEncodeAccelerator
+// interface for MacOSX. VideoToolbox makes no guarantees that it is thread
+// safe, so this object is pinned to the thread on which it is constructed.
+class CONTENT_EXPORT VTVideoEncodeAccelerator
+ : public media::VideoEncodeAccelerator {
+ public:
+ VTVideoEncodeAccelerator();
+ ~VTVideoEncodeAccelerator() override;
+
+ // media::VideoEncodeAccelerator implementation.
+ media::VideoEncodeAccelerator::SupportedProfiles GetSupportedProfiles()
+ override;
+ bool Initialize(media::VideoPixelFormat format,
+ const gfx::Size& input_visible_size,
+ media::VideoCodecProfile output_profile,
+ uint32_t initial_bitrate,
+ Client* client) override;
+ void Encode(const scoped_refptr<media::VideoFrame>& frame,
+ bool force_keyframe) override;
+ void UseOutputBitstreamBuffer(const media::BitstreamBuffer& buffer) override;
+ void RequestEncodingParametersChange(uint32_t bitrate,
+ uint32_t framerate) override;
+ void Destroy() override;
+
+ private:
+ using CMSampleBufferRef = CoreMediaGlue::CMSampleBufferRef;
+ using VTCompressionSessionRef = VideoToolboxGlue::VTCompressionSessionRef;
+ using VTEncodeInfoFlags = VideoToolboxGlue::VTEncodeInfoFlags;
+
+ // Holds the associated data of a video frame being processed.
+ struct InProgressFrameEncode;
+
+ // Holds output buffers coming from the encoder.
+ struct EncodeOutput;
+
+ // Holds output buffers coming from the client ready to be filled.
+ struct BitstreamBufferRef;
+
+ // Encoding tasks to be run on |encoder_thread_|.
+ void EncodeTask(const scoped_refptr<media::VideoFrame>& frame,
+ bool force_keyframe);
+ void UseOutputBitstreamBufferTask(scoped_ptr<BitstreamBufferRef> buffer_ref);
+ void RequestEncodingParametersChangeTask(uint32_t bitrate,
+ uint32_t framerate);
+ void DestroyTask();
+
+ // Helper function to notify the client of an error on |client_task_runner_|.
+ void NotifyError(media::VideoEncodeAccelerator::Error error);
+
+ // Compression session callback function to handle compressed frames.
+ static void CompressionCallback(void* encoder_opaque,
+ void* request_opaque,
+ OSStatus status,
+ VTEncodeInfoFlags info,
+ CMSampleBufferRef sbuf);
+ void CompressionCallbackTask(OSStatus status,
+ scoped_ptr<EncodeOutput> encode_output);
+
+ // Copy CMSampleBuffer into a BitstreamBuffer and return it to the |client_|.
+ void ReturnBitstreamBuffer(
+ scoped_ptr<EncodeOutput> encode_output,
+ scoped_ptr<VTVideoEncodeAccelerator::BitstreamBufferRef> buffer_ref);
+
+ // Reset the encoder's compression session by destroying the existing one
+ // using DestroyCompressionSession() and creating a new one. The new session
+ // is configured using ConfigureCompressionSession().
+ bool ResetCompressionSession();
+
+ // Create a compression session, with HW encoder enforced if
+ // |require_hw_encoding| is set.
+ bool CreateCompressionSession(
+ base::ScopedCFTypeRef<CFDictionaryRef> attributes,
+ const gfx::Size& input_size,
+ bool require_hw_encoding);
+
+ // Configure the current compression session using current encoder settings.
+ bool ConfigureCompressionSession();
+
+ // Destroy the current compression session if any. Blocks until all pending
+ // frames have been flushed out (similar to EmitFrames without doing any
+ // encoding work).
+ void DestroyCompressionSession();
+
+ // VideoToolboxGlue provides access to VideoToolbox at runtime.
+ const VideoToolboxGlue* videotoolbox_glue_;
+ base::ScopedCFTypeRef<VTCompressionSessionRef> compression_session_;
+
+ gfx::Size input_visible_size_;
+ size_t bitstream_buffer_size_;
+ int32_t frame_rate_;
+ int32_t target_bitrate_;
+
+ // Bitstream buffers ready to be used to return encoded output as a FIFO.
+ std::deque<scoped_ptr<BitstreamBufferRef>> bitstream_buffer_queue_;
+
+ // EncodeOutput needs to be copied into a BitstreamBufferRef as a FIFO.
+ std::deque<scoped_ptr<EncodeOutput>> encoder_output_queue_;
+
+ // Our original calling task runner for the child thread.
+ const scoped_refptr<base::SingleThreadTaskRunner> client_task_runner_;
+
+ // To expose client callbacks from VideoEncodeAccelerator.
+ // NOTE: all calls to this object *MUST* be executed on
+ // |client_task_runner_|.
+ base::WeakPtr<Client> client_;
+ scoped_ptr<base::WeakPtrFactory<Client> > client_ptr_factory_;
+
+ // Thread checker to enforce that this object is used on a specific thread.
+ // It is pinned on |client_task_runner_| thread.
+ base::ThreadChecker thread_checker_;
+
+ // This thread services tasks posted from the VEA API entry points by the
+ // GPU child thread and CompressionCallback() posted from device thread.
+ base::Thread encoder_thread_;
+ scoped_refptr<base::SingleThreadTaskRunner> encoder_thread_task_runner_;
+
+ // Declared last to ensure that all weak pointers are invalidated before
+ // other destructors run.
+ base::WeakPtr<VTVideoEncodeAccelerator> encoder_weak_ptr_;
+ base::WeakPtrFactory<VTVideoEncodeAccelerator> encoder_task_weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(VTVideoEncodeAccelerator);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_GPU_MEDIA_VT_VIDEO_ENCODE_ACCELERATOR_MAC_H_
diff --git a/chromium/content/common/gpu/stream_texture_android.cc b/chromium/content/common/gpu/stream_texture_android.cc
deleted file mode 100644
index 17d841d8eb1..00000000000
--- a/chromium/content/common/gpu/stream_texture_android.cc
+++ /dev/null
@@ -1,386 +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/common/gpu/stream_texture_android.h"
-
-#include <string.h>
-
-#include "base/bind.h"
-#include "base/strings/stringize_macros.h"
-#include "content/common/android/surface_texture_peer.h"
-#include "content/common/gpu/gpu_channel.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "gpu/command_buffer/service/context_group.h"
-#include "gpu/command_buffer/service/context_state.h"
-#include "gpu/command_buffer/service/gles2_cmd_decoder.h"
-#include "gpu/command_buffer/service/texture_manager.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gl/gl_context.h"
-#include "ui/gl/gl_helper.h"
-#include "ui/gl/scoped_binders.h"
-#include "ui/gl/scoped_make_current.h"
-
-namespace content {
-
-using gpu::gles2::ContextGroup;
-using gpu::gles2::GLES2Decoder;
-using gpu::gles2::TextureManager;
-using gpu::gles2::TextureRef;
-
-// static
-bool StreamTexture::Create(GpuCommandBufferStub* owner_stub,
- uint32_t client_texture_id,
- int stream_id) {
- GLES2Decoder* decoder = owner_stub->decoder();
- TextureManager* texture_manager =
- decoder->GetContextGroup()->texture_manager();
- TextureRef* texture = texture_manager->GetTexture(client_texture_id);
-
- if (texture && (!texture->texture()->target() ||
- texture->texture()->target() == GL_TEXTURE_EXTERNAL_OES)) {
-
- // TODO: Ideally a valid image id was returned to the client so that
- // it could then call glBindTexImage2D() for doing the following.
- scoped_refptr<gl::GLImage> gl_image(
- new StreamTexture(owner_stub, stream_id, texture->service_id()));
- gfx::Size size = gl_image->GetSize();
- texture_manager->SetTarget(texture, GL_TEXTURE_EXTERNAL_OES);
- texture_manager->SetLevelInfo(texture, GL_TEXTURE_EXTERNAL_OES, 0, GL_RGBA,
- size.width(), size.height(), 1, 0, GL_RGBA,
- GL_UNSIGNED_BYTE, gfx::Rect(size));
- texture_manager->SetLevelImage(texture, GL_TEXTURE_EXTERNAL_OES, 0,
- gl_image.get(),
- gpu::gles2::Texture::UNBOUND);
- return true;
- }
-
- return false;
-}
-
-StreamTexture::StreamTexture(GpuCommandBufferStub* owner_stub,
- int32_t route_id,
- uint32_t texture_id)
- : surface_texture_(gfx::SurfaceTexture::Create(texture_id)),
- size_(0, 0),
- has_valid_frame_(false),
- has_pending_frame_(false),
- owner_stub_(owner_stub),
- route_id_(route_id),
- has_listener_(false),
- texture_id_(texture_id),
- framebuffer_(0),
- vertex_shader_(0),
- fragment_shader_(0),
- program_(0),
- vertex_buffer_(0),
- u_xform_location_(-1),
- weak_factory_(this) {
- owner_stub->AddDestructionObserver(this);
- memset(current_matrix_, 0, sizeof(current_matrix_));
- owner_stub->channel()->AddRoute(route_id, this);
- surface_texture_->SetFrameAvailableCallback(base::Bind(
- &StreamTexture::OnFrameAvailable, weak_factory_.GetWeakPtr()));
-}
-
-StreamTexture::~StreamTexture() {
- if (owner_stub_) {
- owner_stub_->RemoveDestructionObserver(this);
- owner_stub_->channel()->RemoveRoute(route_id_);
- }
-}
-
-void StreamTexture::OnWillDestroyStub() {
- owner_stub_->RemoveDestructionObserver(this);
- owner_stub_->channel()->RemoveRoute(route_id_);
-
- if (framebuffer_) {
- scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current(MakeStubCurrent());
-
- glDeleteProgram(program_);
- glDeleteShader(vertex_shader_);
- glDeleteShader(fragment_shader_);
- glDeleteBuffersARB(1, &vertex_buffer_);
- glDeleteFramebuffersEXT(1, &framebuffer_);
- program_ = 0;
- vertex_shader_ = 0;
- fragment_shader_ = 0;
- vertex_buffer_ = 0;
- framebuffer_ = 0;
- u_xform_location_ = -1;
- }
-
- owner_stub_ = NULL;
-
- // If the owner goes away, there is no need to keep the SurfaceTexture around.
- // The GL texture will keep working regardless with the currently bound frame.
- surface_texture_ = NULL;
-}
-
-void StreamTexture::Destroy(bool have_context) {
- NOTREACHED();
-}
-
-scoped_ptr<ui::ScopedMakeCurrent> StreamTexture::MakeStubCurrent() {
- scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current;
- bool needs_make_current =
- !owner_stub_->decoder()->GetGLContext()->IsCurrent(NULL);
- // On Android we should not have to perform a real context switch here when
- // using virtual contexts.
- DCHECK(!needs_make_current ||
- !owner_stub_->decoder()
- ->GetContextGroup()
- ->feature_info()
- ->workarounds()
- .use_virtualized_gl_contexts);
- if (needs_make_current) {
- scoped_make_current.reset(new ui::ScopedMakeCurrent(
- owner_stub_->decoder()->GetGLContext(), owner_stub_->surface()));
- }
- return scoped_make_current;
-}
-
-void StreamTexture::UpdateTexImage() {
- DCHECK(surface_texture_.get());
- DCHECK(owner_stub_);
-
- if (!has_pending_frame_) return;
-
- scoped_ptr<ui::ScopedMakeCurrent> scoped_make_current(MakeStubCurrent());
-
- surface_texture_->UpdateTexImage();
-
- has_valid_frame_ = true;
- has_pending_frame_ = false;
-
- float mtx[16];
- surface_texture_->GetTransformMatrix(mtx);
-
- if (memcmp(current_matrix_, mtx, sizeof(mtx)) != 0) {
- memcpy(current_matrix_, mtx, sizeof(mtx));
-
- if (has_listener_) {
- GpuStreamTextureMsg_MatrixChanged_Params params;
- memcpy(&params.m00, mtx, sizeof(mtx));
- owner_stub_->channel()->Send(
- new GpuStreamTextureMsg_MatrixChanged(route_id_, params));
- }
- }
-
- if (scoped_make_current.get()) {
- // UpdateTexImage() implies glBindTexture().
- // The cmd decoder takes care of restoring the binding for this GLImage as
- // far as the current context is concerned, but if we temporarily change
- // it, we have to keep the state intact in *that* context also.
- const gpu::gles2::ContextState* state =
- owner_stub_->decoder()->GetContextState();
- const gpu::gles2::TextureUnit& active_unit =
- state->texture_units[state->active_texture_unit];
- glBindTexture(GL_TEXTURE_EXTERNAL_OES,
- active_unit.bound_texture_external_oes.get()
- ? active_unit.bound_texture_external_oes->service_id()
- : 0);
- }
-}
-
-bool StreamTexture::CopyTexImage(unsigned target) {
- if (target == GL_TEXTURE_2D) {
- glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size_.width(), size_.height(), 0,
- GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
- return CopyTexSubImage(GL_TEXTURE_2D, gfx::Point(), gfx::Rect(size_));
- }
-
- if (target != GL_TEXTURE_EXTERNAL_OES)
- return false;
-
- if (!owner_stub_ || !surface_texture_.get())
- return true;
-
- GLint texture_id;
- glGetIntegerv(GL_TEXTURE_BINDING_EXTERNAL_OES, &texture_id);
- DCHECK(texture_id);
-
- // The following code only works if we're being asked to copy into
- // |texture_id_|. Copying into a different texture is not supported.
- if (static_cast<unsigned>(texture_id) != texture_id_)
- return false;
-
- UpdateTexImage();
-
- TextureManager* texture_manager =
- owner_stub_->decoder()->GetContextGroup()->texture_manager();
- gpu::gles2::Texture* texture =
- texture_manager->GetTextureForServiceId(texture_id_);
- if (texture) {
- // By setting image state to UNBOUND instead of COPIED we ensure that
- // CopyTexImage() is called each time the surface texture is used for
- // drawing.
- texture->SetLevelImage(GL_TEXTURE_EXTERNAL_OES, 0, this,
- gpu::gles2::Texture::UNBOUND);
- }
-
- return true;
-}
-
-void StreamTexture::OnFrameAvailable() {
- has_pending_frame_ = true;
- if (has_listener_ && owner_stub_) {
- owner_stub_->channel()->Send(
- new GpuStreamTextureMsg_FrameAvailable(route_id_));
- }
-}
-
-gfx::Size StreamTexture::GetSize() {
- return size_;
-}
-
-unsigned StreamTexture::GetInternalFormat() {
- return GL_RGBA;
-}
-
-bool StreamTexture::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(StreamTexture, message)
- IPC_MESSAGE_HANDLER(GpuStreamTextureMsg_StartListening, OnStartListening)
- IPC_MESSAGE_HANDLER(GpuStreamTextureMsg_EstablishPeer, OnEstablishPeer)
- IPC_MESSAGE_HANDLER(GpuStreamTextureMsg_SetSize, OnSetSize)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
-
- DCHECK(handled);
- return handled;
-}
-
-void StreamTexture::OnStartListening() {
- DCHECK(!has_listener_);
- has_listener_ = true;
-}
-
-void StreamTexture::OnEstablishPeer(int32_t primary_id, int32_t secondary_id) {
- if (!owner_stub_)
- return;
-
- base::ProcessHandle process = owner_stub_->channel()->GetClientPID();
-
- SurfaceTexturePeer::GetInstance()->EstablishSurfaceTexturePeer(
- process, surface_texture_, primary_id, secondary_id);
-}
-
-bool StreamTexture::BindTexImage(unsigned target) {
- NOTREACHED();
- return false;
-}
-
-void StreamTexture::ReleaseTexImage(unsigned target) {
- NOTREACHED();
-}
-
-bool StreamTexture::CopyTexSubImage(unsigned target,
- const gfx::Point& offset,
- const gfx::Rect& rect) {
- if (target != GL_TEXTURE_2D)
- return false;
-
- if (!owner_stub_ || !surface_texture_.get())
- return true;
-
- if (!offset.IsOrigin()) {
- LOG(ERROR) << "Non-origin offset is not supported";
- return false;
- }
-
- if (rect != gfx::Rect(size_)) {
- LOG(ERROR) << "Sub-rectangle is not supported";
- return false;
- }
-
- GLint target_texture = 0;
- glGetIntegerv(GL_TEXTURE_BINDING_2D, &target_texture);
- DCHECK(target_texture);
-
- UpdateTexImage();
-
- if (!framebuffer_) {
- glGenFramebuffersEXT(1, &framebuffer_);
-
- // This vertex shader introduces a y flip before applying the stream
- // texture matrix. This is required because the stream texture matrix
- // Android provides is intended to be used in a y-up coordinate system,
- // whereas Chromium expects y-down.
-
- // clang-format off
- const char kVertexShader[] = STRINGIZE(
- attribute vec2 a_position;
- varying vec2 v_texCoord;
- uniform mat4 u_xform;
- void main() {
- gl_Position = vec4(a_position.x, a_position.y, 0.0, 1.0);
- vec2 uv_untransformed = a_position * vec2(0.5, -0.5) + vec2(0.5, 0.5);
- v_texCoord = (u_xform * vec4(uv_untransformed, 0.0, 1.0)).xy;
- }
- );
- const char kFragmentShader[] =
- "#extension GL_OES_EGL_image_external : require\n" STRINGIZE(
- precision mediump float;
- uniform samplerExternalOES a_texture;
- varying vec2 v_texCoord;
- void main() {
- gl_FragColor = texture2D(a_texture, v_texCoord);
- }
- );
- // clang-format on
-
- vertex_buffer_ = gfx::GLHelper::SetupQuadVertexBuffer();
- vertex_shader_ = gfx::GLHelper::LoadShader(GL_VERTEX_SHADER, kVertexShader);
- fragment_shader_ =
- gfx::GLHelper::LoadShader(GL_FRAGMENT_SHADER, kFragmentShader);
- program_ = gfx::GLHelper::SetupProgram(vertex_shader_, fragment_shader_);
- gfx::ScopedUseProgram use_program(program_);
- int sampler_location = glGetUniformLocation(program_, "a_texture");
- DCHECK_NE(-1, sampler_location);
- glUniform1i(sampler_location, 0);
- u_xform_location_ = glGetUniformLocation(program_, "u_xform");
- DCHECK_NE(-1, u_xform_location_);
- }
-
- gfx::ScopedActiveTexture active_texture(GL_TEXTURE0);
- // UpdateTexImage() call below will bind the surface texture to
- // TEXTURE_EXTERNAL_OES. This scoped texture binder will restore the current
- // binding before this function returns.
- gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_EXTERNAL_OES, texture_id_);
-
- {
- gfx::ScopedFrameBufferBinder framebuffer_binder(framebuffer_);
- gfx::ScopedViewport viewport(0, 0, size_.width(), size_.height());
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D, target_texture, 0);
- DCHECK_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
- glCheckFramebufferStatusEXT(GL_FRAMEBUFFER));
- gfx::ScopedUseProgram use_program(program_);
-
- glUniformMatrix4fv(u_xform_location_, 1, false, current_matrix_);
- gfx::GLHelper::DrawQuad(vertex_buffer_);
-
- // Detach the output texture from the fbo.
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
- GL_TEXTURE_2D, 0, 0);
- }
- return true;
-}
-
-bool StreamTexture::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
- int z_order,
- gfx::OverlayTransform transform,
- const gfx::Rect& bounds_rect,
- const gfx::RectF& crop_rect) {
- NOTREACHED();
- return false;
-}
-
-void StreamTexture::OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd,
- uint64_t process_tracing_id,
- const std::string& dump_name) {
- // TODO(ericrk): Add OnMemoryDump for GLImages. crbug.com/514914
-}
-
-} // namespace content
diff --git a/chromium/content/common/gpu/stream_texture_android.h b/chromium/content/common/gpu/stream_texture_android.h
deleted file mode 100644
index e19fc1b321a..00000000000
--- a/chromium/content/common/gpu/stream_texture_android.h
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_STREAM_TEXTURE_ANDROID_H_
-#define CONTENT_COMMON_GPU_STREAM_TEXTURE_ANDROID_H_
-
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "content/common/gpu/gpu_command_buffer_stub.h"
-#include "ipc/ipc_listener.h"
-#include "ui/gl/android/surface_texture.h"
-#include "ui/gl/gl_image.h"
-
-namespace ui {
-class ScopedMakeCurrent;
-}
-
-namespace gfx {
-class Size;
-}
-
-namespace content {
-
-class StreamTexture : public gl::GLImage,
- public IPC::Listener,
- public GpuCommandBufferStub::DestructionObserver {
- public:
- static bool Create(GpuCommandBufferStub* owner_stub,
- uint32_t client_texture_id,
- int stream_id);
-
- private:
- StreamTexture(GpuCommandBufferStub* owner_stub,
- int32_t route_id,
- uint32_t texture_id);
- ~StreamTexture() override;
-
- // gl::GLImage implementation:
- void Destroy(bool have_context) override;
- gfx::Size GetSize() override;
- unsigned GetInternalFormat() override;
- bool BindTexImage(unsigned target) override;
- void ReleaseTexImage(unsigned target) override;
- bool CopyTexImage(unsigned target) override;
- bool CopyTexSubImage(unsigned target,
- const gfx::Point& offset,
- const gfx::Rect& rect) override;
- bool ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
- int z_order,
- gfx::OverlayTransform transform,
- const gfx::Rect& bounds_rect,
- const gfx::RectF& crop_rect) override;
- void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd,
- uint64_t process_tracing_id,
- const std::string& dump_name) override;
-
- // GpuCommandBufferStub::DestructionObserver implementation.
- void OnWillDestroyStub() override;
-
- scoped_ptr<ui::ScopedMakeCurrent> MakeStubCurrent();
-
- void UpdateTexImage();
-
- // Called when a new frame is available for the SurfaceTexture.
- void OnFrameAvailable();
-
- // IPC::Listener implementation:
- bool OnMessageReceived(const IPC::Message& message) override;
-
- // IPC message handlers:
- void OnStartListening();
- void OnEstablishPeer(int32_t primary_id, int32_t secondary_id);
- void OnSetSize(const gfx::Size& size) { size_ = size; }
-
- scoped_refptr<gfx::SurfaceTexture> surface_texture_;
-
- // Current transform matrix of the surface texture.
- float current_matrix_[16];
-
- // Current size of the surface texture.
- gfx::Size size_;
-
- // Whether we ever bound a valid frame.
- bool has_valid_frame_;
-
- // Whether a new frame is available that we should update to.
- bool has_pending_frame_;
-
- GpuCommandBufferStub* owner_stub_;
- int32_t route_id_;
- bool has_listener_;
- uint32_t texture_id_;
-
- unsigned framebuffer_;
- unsigned vertex_shader_;
- unsigned fragment_shader_;
- unsigned program_;
- unsigned vertex_buffer_;
- int u_xform_location_;
-
- base::WeakPtrFactory<StreamTexture> weak_factory_;
- DISALLOW_COPY_AND_ASSIGN(StreamTexture);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_GPU_STREAM_TEXTURE_ANDROID_H_
diff --git a/chromium/content/common/gpu/x_util.h b/chromium/content/common/gpu/x_util.h
deleted file mode 100644
index 99687566356..00000000000
--- a/chromium/content/common/gpu/x_util.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_GPU_X_UTIL_H_
-#define CONTENT_COMMON_GPU_X_UTIL_H_
-
-// Some X-Windows specific stuff. This can be included on any platform, and will
-// be a NOP on non-Linux ones.
-
-#include "build/build_config.h"
-#include "content/common/gpu/gpu_config.h"
-
-#if defined(USE_X11)
-
-namespace content {
-
-// Forward declares ------------------------------------------------------------
-//
-// X Windows headers do a lot of evil stuff, like "#define Status int" which
-// will cause many problems when combined with our other header files (like
-// ones that define a class local enum called "Status."
-//
-// These definitions are not Kosher, but allow us to remove this dependency and
-// actually compile X at all.
-
-typedef unsigned long XID;
-
-extern "C" {
-
-typedef struct _XDisplay Display;
-typedef struct __GLXcontextRec *GLXContext;
-
-} // extern "C"
-
-} // namespace content
-
-#endif // USE_X11
-
-#endif // CONTENT_COMMON_GPU_X_UTIL_H_
diff --git a/chromium/content/common/gpu_host_messages.h b/chromium/content/common/gpu_host_messages.h
new file mode 100644
index 00000000000..0705be08955
--- /dev/null
+++ b/chromium/content/common/gpu_host_messages.h
@@ -0,0 +1,300 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Multiply-included message file, hence no include guard here, but see below
+// for a much smaller-than-usual include guard section.
+
+#include "build/build_config.h"
+#include "content/common/content_export.h"
+#include "content/common/establish_channel_params.h"
+#include "gpu/command_buffer/common/sync_token.h"
+#include "gpu/command_buffer/common/value_state.h"
+#include "gpu/command_buffer/service/gpu_preferences.h"
+#include "gpu/config/gpu_info.h"
+#include "gpu/ipc/common/gpu_command_buffer_traits.h"
+#include "gpu/ipc/common/gpu_memory_uma_stats.h"
+#include "gpu/ipc/common/gpu_param_traits.h"
+#include "gpu/ipc/common/memory_stats.h"
+#include "gpu/ipc/common/surface_handle.h"
+#include "ipc/ipc_channel_handle.h"
+#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_start.h"
+#include "ui/events/ipc/latency_info_param_traits.h"
+#include "ui/gfx/gpu_memory_buffer.h"
+#include "ui/gfx/ipc/gfx_param_traits.h"
+#include "ui/gfx/ipc/skia/gfx_skia_param_traits.h"
+#include "url/gurl.h"
+#include "url/ipc/url_param_traits.h"
+
+#if defined(OS_MACOSX)
+#include "content/common/accelerated_surface_buffers_swapped_params_mac.h"
+#include "content/common/buffer_presented_params_mac.h"
+#include "ui/base/cocoa/remote_layer_api.h"
+#include "ui/gfx/mac/io_surface.h"
+#endif
+
+#undef IPC_MESSAGE_EXPORT
+#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
+
+#define IPC_MESSAGE_START GpuMsgStart
+
+IPC_STRUCT_TRAITS_BEGIN(gpu::GPUMemoryUmaStats)
+ IPC_STRUCT_TRAITS_MEMBER(bytes_allocated_current)
+ IPC_STRUCT_TRAITS_MEMBER(bytes_allocated_max)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(gpu::VideoMemoryUsageStats)
+ IPC_STRUCT_TRAITS_MEMBER(process_map)
+ IPC_STRUCT_TRAITS_MEMBER(bytes_allocated)
+ IPC_STRUCT_TRAITS_MEMBER(bytes_allocated_historical_max)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(gpu::VideoMemoryUsageStats::ProcessStats)
+ IPC_STRUCT_TRAITS_MEMBER(video_memory)
+ IPC_STRUCT_TRAITS_MEMBER(has_duplicates)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_BEGIN(GpuMsg_CreateGpuMemoryBuffer_Params)
+ IPC_STRUCT_MEMBER(gfx::GpuMemoryBufferId, id)
+ IPC_STRUCT_MEMBER(gfx::Size, size)
+ IPC_STRUCT_MEMBER(gfx::BufferFormat, format)
+ IPC_STRUCT_MEMBER(gfx::BufferUsage, usage)
+ IPC_STRUCT_MEMBER(int32_t, client_id)
+ IPC_STRUCT_MEMBER(gpu::SurfaceHandle, surface_handle)
+IPC_STRUCT_END()
+
+IPC_STRUCT_BEGIN(GpuMsg_CreateGpuMemoryBufferFromHandle_Params)
+ IPC_STRUCT_MEMBER(gfx::GpuMemoryBufferHandle, handle)
+ IPC_STRUCT_MEMBER(gfx::GpuMemoryBufferId, id)
+ IPC_STRUCT_MEMBER(gfx::Size, size)
+ IPC_STRUCT_MEMBER(gfx::BufferFormat, format)
+ IPC_STRUCT_MEMBER(int32_t, client_id)
+IPC_STRUCT_END()
+
+IPC_STRUCT_TRAITS_BEGIN(content::EstablishChannelParams)
+ IPC_STRUCT_TRAITS_MEMBER(client_id)
+ IPC_STRUCT_TRAITS_MEMBER(client_tracing_id)
+ IPC_STRUCT_TRAITS_MEMBER(preempts)
+ IPC_STRUCT_TRAITS_MEMBER(allow_view_command_buffers)
+ IPC_STRUCT_TRAITS_MEMBER(allow_real_time_streams)
+IPC_STRUCT_TRAITS_END()
+
+#if defined(OS_MACOSX)
+IPC_STRUCT_TRAITS_BEGIN(content::AcceleratedSurfaceBuffersSwappedParams)
+ IPC_STRUCT_TRAITS_MEMBER(surface_id)
+ // Only one of ca_context_id or io_surface may be non-0.
+ IPC_STRUCT_TRAITS_MEMBER(ca_context_id)
+ IPC_STRUCT_TRAITS_MEMBER(io_surface)
+ IPC_STRUCT_TRAITS_MEMBER(size)
+ IPC_STRUCT_TRAITS_MEMBER(scale_factor)
+ IPC_STRUCT_TRAITS_MEMBER(latency_info)
+IPC_STRUCT_TRAITS_END()
+
+IPC_STRUCT_TRAITS_BEGIN(content::BufferPresentedParams)
+ // The vsync parameters, to synchronize presentation with the display.
+ IPC_STRUCT_TRAITS_MEMBER(surface_id)
+ IPC_STRUCT_TRAITS_MEMBER(vsync_timebase)
+ IPC_STRUCT_TRAITS_MEMBER(vsync_interval)
+IPC_STRUCT_TRAITS_END()
+#endif
+
+IPC_STRUCT_TRAITS_BEGIN(gpu::GpuPreferences)
+ IPC_STRUCT_TRAITS_MEMBER(single_process)
+ IPC_STRUCT_TRAITS_MEMBER(in_process_gpu)
+ IPC_STRUCT_TRAITS_MEMBER(ui_prioritize_in_gpu_process)
+ IPC_STRUCT_TRAITS_MEMBER(disable_accelerated_video_decode)
+#if defined(OS_CHROMEOS)
+ IPC_STRUCT_TRAITS_MEMBER(disable_vaapi_accelerated_video_encode)
+#endif
+#if defined(ENABLE_WEBRTC)
+ IPC_STRUCT_TRAITS_MEMBER(disable_web_rtc_hw_encoding)
+#endif
+#if defined(OS_WIN)
+ IPC_STRUCT_TRAITS_MEMBER(enable_accelerated_vpx_decode)
+#endif
+ IPC_STRUCT_TRAITS_MEMBER(compile_shader_always_succeeds)
+ IPC_STRUCT_TRAITS_MEMBER(disable_gl_error_limit)
+ IPC_STRUCT_TRAITS_MEMBER(disable_glsl_translator)
+ IPC_STRUCT_TRAITS_MEMBER(disable_gpu_driver_bug_workarounds)
+ IPC_STRUCT_TRAITS_MEMBER(disable_shader_name_hashing)
+ IPC_STRUCT_TRAITS_MEMBER(enable_gpu_command_logging)
+ IPC_STRUCT_TRAITS_MEMBER(enable_gpu_debugging)
+ IPC_STRUCT_TRAITS_MEMBER(enable_gpu_service_logging_gpu)
+ IPC_STRUCT_TRAITS_MEMBER(disable_gpu_program_cache)
+ IPC_STRUCT_TRAITS_MEMBER(enforce_gl_minimums)
+ IPC_STRUCT_TRAITS_MEMBER(force_gpu_mem_available)
+ IPC_STRUCT_TRAITS_MEMBER(gpu_program_cache_size)
+ IPC_STRUCT_TRAITS_MEMBER(disable_gpu_shader_disk_cache)
+ IPC_STRUCT_TRAITS_MEMBER(enable_share_group_async_texture_upload)
+ IPC_STRUCT_TRAITS_MEMBER(enable_subscribe_uniform_extension)
+ IPC_STRUCT_TRAITS_MEMBER(enable_threaded_texture_mailboxes)
+ IPC_STRUCT_TRAITS_MEMBER(gl_shader_interm_output)
+ IPC_STRUCT_TRAITS_MEMBER(emulate_shader_precision)
+ IPC_STRUCT_TRAITS_MEMBER(enable_gpu_service_logging)
+ IPC_STRUCT_TRAITS_MEMBER(enable_gpu_service_tracing)
+ IPC_STRUCT_TRAITS_MEMBER(enable_unsafe_es3_apis)
+IPC_STRUCT_TRAITS_END()
+
+//------------------------------------------------------------------------------
+// GPU Messages
+// These are messages from the browser to the GPU process.
+
+// Tells the GPU process to initialize itself. The browser explicitly
+// requests this be done so that we are guaranteed that the channel is set
+// up between the browser and GPU process before doing any work that might
+// potentially crash the GPU process. Detection of the child process
+// exiting abruptly is predicated on having the IPC channel set up.
+IPC_MESSAGE_CONTROL1(GpuMsg_Initialize,
+ gpu::GpuPreferences /* gpu_prefernces */)
+
+// Tells the GPU process to shutdown itself.
+IPC_MESSAGE_CONTROL0(GpuMsg_Finalize)
+
+// Tells the GPU process to create a new channel for communication with a
+// given client. The channel name is returned in a
+// GpuHostMsg_ChannelEstablished message. The client ID is passed so
+// that the GPU process reuses an existing channel to that process if it exists.
+// This ID is a unique opaque identifier generated by the browser process.
+// The client_tracing_id is a unique ID used for the purposes of tracing.
+IPC_MESSAGE_CONTROL1(GpuMsg_EstablishChannel,
+ content::EstablishChannelParams /* params */)
+
+// Tells the GPU process to close the channel identified by |client_id|.
+// If no channel can be identified, do nothing.
+IPC_MESSAGE_CONTROL1(GpuMsg_CloseChannel, int32_t /* client_id */)
+
+// Tells the GPU process to create a new gpu memory buffer.
+IPC_MESSAGE_CONTROL1(GpuMsg_CreateGpuMemoryBuffer,
+ GpuMsg_CreateGpuMemoryBuffer_Params)
+
+// Tells the GPU process to create a new gpu memory buffer from an existing
+// handle.
+IPC_MESSAGE_CONTROL1(GpuMsg_CreateGpuMemoryBufferFromHandle,
+ GpuMsg_CreateGpuMemoryBufferFromHandle_Params)
+
+// Tells the GPU process to destroy buffer.
+IPC_MESSAGE_CONTROL3(GpuMsg_DestroyGpuMemoryBuffer,
+ gfx::GpuMemoryBufferId, /* id */
+ int32_t, /* client_id */
+ gpu::SyncToken /* sync_token */)
+
+// Tells the GPU process to create a context for collecting graphics card
+// information.
+IPC_MESSAGE_CONTROL0(GpuMsg_CollectGraphicsInfo)
+
+// Tells the GPU process to report video_memory information for the task manager
+IPC_MESSAGE_CONTROL0(GpuMsg_GetVideoMemoryUsageStats)
+
+#if defined(OS_MACOSX)
+// Tells the GPU process that the browser process has handled the swap
+// buffers or post sub-buffer request.
+IPC_MESSAGE_CONTROL1(AcceleratedSurfaceMsg_BufferPresented,
+ content::BufferPresentedParams)
+#endif
+
+#if defined(OS_ANDROID)
+// Tells the GPU process to wake up the GPU because we're about to draw.
+IPC_MESSAGE_CONTROL0(GpuMsg_WakeUpGpu)
+#endif
+
+// Tells the GPU process to remove all contexts.
+IPC_MESSAGE_CONTROL0(GpuMsg_Clean)
+
+// Tells the GPU process to crash.
+IPC_MESSAGE_CONTROL0(GpuMsg_Crash)
+
+// Tells the GPU process to hang.
+IPC_MESSAGE_CONTROL0(GpuMsg_Hang)
+
+// Tells the GPU process to disable the watchdog thread.
+IPC_MESSAGE_CONTROL0(GpuMsg_DisableWatchdog)
+
+// Tells the GPU process that the browser has seen a GPU switch.
+IPC_MESSAGE_CONTROL0(GpuMsg_GpuSwitched)
+
+// Sends an input event to the gpu service.
+IPC_MESSAGE_CONTROL3(GpuMsg_UpdateValueState,
+ int, /* client_id */
+ unsigned int, /* target */
+ gpu::ValueState /* valuestate */)
+
+//------------------------------------------------------------------------------
+// GPU Host Messages
+// These are messages to the browser.
+
+// Response from GPU to a GputMsg_Initialize message.
+IPC_MESSAGE_CONTROL2(GpuHostMsg_Initialized,
+ bool /* result */,
+ ::gpu::GPUInfo /* gpu_info */)
+
+// Response from GPU to a GpuHostMsg_EstablishChannel message.
+IPC_MESSAGE_CONTROL1(GpuHostMsg_ChannelEstablished,
+ IPC::ChannelHandle /* channel_handle */)
+
+// Message from GPU to notify to destroy the channel.
+IPC_MESSAGE_CONTROL1(GpuHostMsg_DestroyChannel, int32_t /* client_id */)
+
+// Message to cache the given shader information.
+IPC_MESSAGE_CONTROL3(GpuHostMsg_CacheShader,
+ int32_t /* client_id */,
+ std::string /* key */,
+ std::string /* shader */)
+
+// Message to the GPU that a shader was loaded from disk.
+IPC_MESSAGE_CONTROL1(GpuMsg_LoadedShader, std::string /* encoded shader */)
+
+// Response from GPU to a GpuMsg_CreateGpuMemoryBuffer message.
+IPC_MESSAGE_CONTROL1(GpuHostMsg_GpuMemoryBufferCreated,
+ gfx::GpuMemoryBufferHandle /* handle */)
+
+// Response from GPU to a GpuMsg_CollectGraphicsInfo.
+IPC_MESSAGE_CONTROL1(GpuHostMsg_GraphicsInfoCollected,
+ gpu::GPUInfo /* GPU logging stats */)
+
+// Response from GPU to a GpuMsg_GetVideoMemory.
+IPC_MESSAGE_CONTROL1(GpuHostMsg_VideoMemoryUsageStats,
+ gpu::VideoMemoryUsageStats /* GPU memory stats */)
+
+#if defined(OS_MACOSX)
+// Tells the browser that an accelerated surface has swapped.
+IPC_MESSAGE_CONTROL1(GpuHostMsg_AcceleratedSurfaceBuffersSwapped,
+ content::AcceleratedSurfaceBuffersSwappedParams)
+#endif
+
+#if defined(OS_WIN)
+IPC_MESSAGE_CONTROL2(GpuHostMsg_AcceleratedSurfaceCreatedChildWindow,
+ gpu::SurfaceHandle /* parent_window */,
+ gpu::SurfaceHandle /* child_window */)
+#endif
+
+IPC_MESSAGE_CONTROL1(GpuHostMsg_DidCreateOffscreenContext, GURL /* url */)
+
+IPC_MESSAGE_CONTROL3(GpuHostMsg_DidLoseContext,
+ bool /* offscreen */,
+ gpu::error::ContextLostReason /* reason */,
+ GURL /* url */)
+
+IPC_MESSAGE_CONTROL1(GpuHostMsg_DidDestroyOffscreenContext, GURL /* url */)
+
+// Tells the browser about GPU memory usage statistics for UMA logging.
+IPC_MESSAGE_CONTROL1(GpuHostMsg_GpuMemoryUmaStats,
+ gpu::GPUMemoryUmaStats /* GPU memory UMA stats */)
+
+// Tells the browser that a context has subscribed to a new target and
+// the browser should start sending the corresponding information
+IPC_MESSAGE_CONTROL2(GpuHostMsg_AddSubscription,
+ int32_t /* client_id */,
+ unsigned int /* target */)
+
+// Tells the browser that no contexts are subscribed to the target anymore
+// so the browser should stop sending the corresponding information
+IPC_MESSAGE_CONTROL2(GpuHostMsg_RemoveSubscription,
+ int32_t /* client_id */,
+ unsigned int /* target */)
+
+// Message from GPU to add a GPU log message to the about:gpu page.
+IPC_MESSAGE_CONTROL3(GpuHostMsg_OnLogMessage,
+ int /*severity*/,
+ std::string /* header */,
+ std::string /* message */)
diff --git a/chromium/content/common/gpu/gpu_process_launch_causes.h b/chromium/content/common/gpu_process_launch_causes.h
index 1c280761ef9..b7acd351152 100644
--- a/chromium/content/common/gpu/gpu_process_launch_causes.h
+++ b/chromium/content/common/gpu_process_launch_causes.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_COMMON_GPU_GPU_PROCESS_LAUNCH_CAUSES_H_
-#define CONTENT_COMMON_GPU_GPU_PROCESS_LAUNCH_CAUSES_H_
+#ifndef CONTENT_COMMON_GPU_PROCESS_LAUNCH_CAUSES_H_
+#define CONTENT_COMMON_GPU_PROCESS_LAUNCH_CAUSES_H_
namespace content {
@@ -23,7 +23,7 @@ enum CauseForGpuLaunch {
CAUSE_FOR_GPU_LAUNCH_GPU_MEMORY_BUFFER_ALLOCATE,
CAUSE_FOR_GPU_LAUNCH_JPEGDECODEACCELERATOR_INITIALIZE,
CAUSE_FOR_GPU_LAUNCH_MOJO_SETUP,
- CAUSE_FOR_GPU_LAUNCH_ARCVIDEOACCELERATOR,
+ CAUSE_FOR_GPU_LAUNCH_GET_GPU_SERVICE_REGISTRY,
// All new values should be inserted above this point so that
// existing values continue to match up with those in histograms.xml.
@@ -32,4 +32,4 @@ enum CauseForGpuLaunch {
} // namespace content
-#endif // CONTENT_COMMON_GPU_GPU_PROCESS_LAUNCH_CAUSES_H_
+#endif // CONTENT_COMMON_GPU_PROCESS_LAUNCH_CAUSES_H_
diff --git a/chromium/content/common/host_discardable_shared_memory_manager.cc b/chromium/content/common/host_discardable_shared_memory_manager.cc
index 7a6d480d295..d8d141cdaa8 100644
--- a/chromium/content/common/host_discardable_shared_memory_manager.cc
+++ b/chromium/content/common/host_discardable_shared_memory_manager.cc
@@ -15,6 +15,7 @@
#include "base/macros.h"
#include "base/memory/discardable_memory.h"
#include "base/numerics/safe_math.h"
+#include "base/process/memory.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/sys_info.h"
@@ -190,6 +191,9 @@ HostDiscardableSharedMemoryManager::current() {
scoped_ptr<base::DiscardableMemory>
HostDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(
size_t size) {
+ // TODO(reveman): Temporary diagnostics for http://crbug.com/577786.
+ CHECK_NE(size, 0u);
+
DiscardableSharedMemoryId new_id =
g_next_discardable_shared_memory_id.GetNext();
base::ProcessHandle current_process_handle = base::GetCurrentProcessHandle();
@@ -200,10 +204,10 @@ HostDiscardableSharedMemoryManager::AllocateLockedDiscardableMemory(
AllocateLockedDiscardableSharedMemory(current_process_handle,
ChildProcessHost::kInvalidUniqueID,
size, new_id, &handle);
- CHECK(base::SharedMemory::IsHandleValid(handle));
scoped_ptr<base::DiscardableSharedMemory> memory(
new base::DiscardableSharedMemory(handle));
- CHECK(memory->Map(size));
+ if (!memory->Map(size))
+ base::TerminateBecauseOutOfMemory(size);
// Close file descriptor to avoid running out.
memory->Close();
return make_scoped_ptr(new DiscardableMemoryImpl(
diff --git a/chromium/content/common/host_discardable_shared_memory_manager.h b/chromium/content/common/host_discardable_shared_memory_manager.h
index 3965f1d4c5f..834afe75b3d 100644
--- a/chromium/content/common/host_discardable_shared_memory_manager.h
+++ b/chromium/content/common/host_discardable_shared_memory_manager.h
@@ -18,6 +18,7 @@
#include "base/memory/discardable_shared_memory.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory.h"
#include "base/memory/weak_ptr.h"
#include "base/process/process_handle.h"
diff --git a/chromium/content/common/host_shared_bitmap_manager.cc b/chromium/content/common/host_shared_bitmap_manager.cc
index d41ec392be5..e666f9b18c4 100644
--- a/chromium/content/common/host_shared_bitmap_manager.cc
+++ b/chromium/content/common/host_shared_bitmap_manager.cc
@@ -202,13 +202,8 @@ bool HostSharedBitmapManager::ChildAllocatedSharedBitmap(
new BitmapData(process_handle, buffer_size));
handle_map_[id] = data;
-#if defined(OS_WIN)
- data->memory = make_scoped_ptr(
- new base::SharedMemory(handle, false, data->process_handle));
-#else
data->memory =
make_scoped_ptr(new base::SharedMemory(handle, false));
-#endif
data->memory->Map(data->buffer_size);
data->memory->Close();
return true;
diff --git a/chromium/content/common/id_type.h b/chromium/content/common/id_type.h
deleted file mode 100644
index cc25fa5ac29..00000000000
--- a/chromium/content/common/id_type.h
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_ID_TYPE_H_
-#define CONTENT_COMMON_ID_TYPE_H_
-
-#include <stdint.h>
-#include <ostream>
-#include <type_traits>
-
-#include "base/containers/hash_tables.h"
-
-// IdType32<>, IdType64<>, etc. wrap an integer id in a custom, type-safe type.
-//
-// IdType32<Foo> is an alternative to int, for a class Foo with methods like:
-//
-// int GetId() { return id_; };
-// static Foo* FromId(int id) { return g_all_foos_by_id[id]; }
-//
-// Such methods are a standard means of safely referring to objects across
-// thread and process boundaries. But if a nearby class Bar also represents
-// its IDs as a bare int, horrific mixups are possible -- one example, of many,
-// is http://crrev.com/365437. IdType<> offers compile-time protection against
-// such mishaps, since IdType32<Foo> is incompatible with IdType32<Bar>, even
-// though both just compile down to an int32_t.
-//
-// Templates in this file:
-// IdType32<T> / IdTypeU32<T>: Signed / unsigned 32-bit IDs
-// IdType64<T> / IdTypeU64<T>: Signed / unsigned 64-bit IDs
-// IdType<>: For when you need a different underlying type or
-// a default/invalid value other than zero.
-//
-// IdType32<Foo> behaves just like an int32_t in the following aspects:
-// - it can be used as a key in std::map and/or base::hash_map;
-// - it can be used as an argument to DCHECK_EQ or streamed to LOG(ERROR);
-// - it has the same memory footprint and runtime overhead as int32_t;
-// - it can be copied by memcpy.
-//
-// IdType32<Foo> has the following differences from a bare int32_t:
-// - it forces coercions to go through GetUnsafeValue and FromUnsafeValue;
-// - it restricts the set of available operations (i.e. no multiplication);
-// - it ensures initialization to zero and allows checking against
-// default-initialized values via is_null method.
-
-namespace content {
-
-template <typename TypeMarker, typename WrappedType, WrappedType kInvalidValue>
-class IdType {
- public:
- IdType() : value_(kInvalidValue) {}
- bool is_null() const { return value_ == kInvalidValue; }
-
- static IdType FromUnsafeValue(WrappedType value) { return IdType(value); }
- WrappedType GetUnsafeValue() const { return value_; }
-
- IdType(const IdType& other) = default;
- IdType& operator=(const IdType& other) = default;
-
- bool operator==(const IdType& other) const { return value_ == other.value_; }
- bool operator!=(const IdType& other) const { return value_ != other.value_; }
- bool operator<(const IdType& other) const { return value_ < other.value_; }
-
- protected:
- explicit IdType(WrappedType val) : value_(val) {}
-
- private:
- // In theory WrappedType could be any type that supports ==, <, <<, std::hash,
- // etc., but to make things simpler (both for users and for maintainers) we
- // explicitly restrict the design space to integers. This means the users
- // can safely assume that IdType is relatively small and cheap to copy
- // and the maintainers don't have to worry about WrappedType being a complex
- // type (i.e. std::string or std::pair or a move-only type).
- using IntegralWrappedType =
- typename std::enable_if<std::is_integral<WrappedType>::value,
- WrappedType>::type;
- IntegralWrappedType value_;
-};
-
-// Type aliases for convenience:
-template <typename TypeMarker>
-using IdType32 = IdType<TypeMarker, int32_t, 0>;
-template <typename TypeMarker>
-using IdTypeU32 = IdType<TypeMarker, uint32_t, 0>;
-template <typename TypeMarker>
-using IdType64 = IdType<TypeMarker, int64_t, 0>;
-template <typename TypeMarker>
-using IdTypeU64 = IdType<TypeMarker, uint64_t, 0>;
-
-template <typename TypeMarker, typename WrappedType, WrappedType kInvalidValue>
-std::ostream& operator<<(
- std::ostream& stream,
- const IdType<TypeMarker, WrappedType, kInvalidValue>& id) {
- return stream << id.GetUnsafeValue();
-}
-
-} // namespace content
-
-namespace BASE_HASH_NAMESPACE {
-
-template <typename TypeMarker, typename WrappedType, WrappedType kInvalidValue>
-struct hash<content::IdType<TypeMarker, WrappedType, kInvalidValue>> {
- using argument_type = content::IdType<TypeMarker, WrappedType, kInvalidValue>;
- using result_type = std::size_t;
- result_type operator()(const argument_type& id) const {
- return BASE_HASH_NAMESPACE::hash<WrappedType>()(id.GetUnsafeValue());
- }
-};
-
-} // namespace BASE_HASH_NAMESPACE
-
-#endif // CONTENT_COMMON_ID_TYPE_H_
diff --git a/chromium/content/common/id_type_unittest.cc b/chromium/content/common/id_type_unittest.cc
deleted file mode 100644
index aa596d4cdc3..00000000000
--- a/chromium/content/common/id_type_unittest.cc
+++ /dev/null
@@ -1,205 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <limits>
-#include <map>
-#include <sstream>
-#include <string>
-#include <type_traits>
-
-#include "base/containers/hash_tables.h"
-#include "content/common/id_type.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace content {
-
-namespace {
-
-class Foo;
-using FooId = IdType<Foo, int, 0>;
-
-class Bar;
-using BarId = IdType<Bar, int, 0>;
-
-class AnotherIdMarker;
-class DerivedId : public IdType<AnotherIdMarker, int, 0> {
- public:
- explicit DerivedId(int unsafe_value)
- : IdType<AnotherIdMarker, int, 0>(unsafe_value) {}
-};
-
-} // namespace
-
-TEST(IdType, DefaultValueIsInvalid) {
- FooId foo_id;
- EXPECT_TRUE(foo_id.is_null());
-}
-
-TEST(IdType, NormalValueIsValid) {
- FooId foo_id = FooId::FromUnsafeValue(123);
- EXPECT_FALSE(foo_id.is_null());
-}
-
-TEST(IdType, OutputStreamTest) {
- FooId foo_id = FooId::FromUnsafeValue(123);
-
- std::ostringstream ss;
- ss << foo_id;
- EXPECT_EQ("123", ss.str());
-}
-
-TEST(IdType, IdType32) {
- IdType32<Foo> id;
-
- EXPECT_EQ(0, id.GetUnsafeValue());
- static_assert(sizeof(int32_t) == sizeof(id), "");
-}
-
-TEST(IdType, IdTypeU32) {
- IdTypeU32<Foo> id;
-
- EXPECT_EQ(0u, id.GetUnsafeValue());
- static_assert(sizeof(uint32_t) == sizeof(id), "");
-}
-
-TEST(IdType, IdType64) {
- IdType64<Foo> id;
-
- EXPECT_EQ(0, id.GetUnsafeValue());
- static_assert(sizeof(int64_t) == sizeof(id), "");
-}
-
-TEST(IdType, IdTypeU64) {
- IdTypeU64<Foo> id;
-
- EXPECT_EQ(0u, id.GetUnsafeValue());
- static_assert(sizeof(uint64_t) == sizeof(id), "");
-}
-
-TEST(IdType, DerivedClasses) {
- DerivedId derived_id(456);
-
- std::ostringstream ss;
- ss << derived_id;
- EXPECT_EQ("456", ss.str());
-
- std::map<DerivedId, std::string> ordered_map;
- ordered_map[derived_id] = "blah";
- EXPECT_EQ(ordered_map[derived_id], "blah");
-
- // TODO(lukasza): Enable std::unordered_map and base::hash_map for DerivedId.
- // Ideally this should be possible without having to repeat std::hash<...>
- // specialization for each derived class (but then SFINAE + std::enable_if +
- // std::is_base_of doesn't seem to work for std::hash because std::hash only
- // has a single template parameter?).
- // std::unordered_map<DerivedId, std::string> unordered_map;
- // unordered_map[derived_id] = "blah2";
- // EXPECT_EQ(unordered_map[derived_id], "blah2");
-}
-
-TEST(IdType, StaticAsserts) {
- static_assert(!std::is_constructible<FooId, int>::value,
- "Should be impossible to construct FooId from a raw integer.");
- static_assert(!std::is_convertible<int, FooId>::value,
- "Should be impossible to convert a raw integer into FooId.");
-
- static_assert(!std::is_constructible<FooId, BarId>::value,
- "Should be impossible to construct FooId from a BarId.");
- static_assert(!std::is_convertible<BarId, FooId>::value,
- "Should be impossible to convert a BarId into FooId.");
-
- // The presence of a custom default constructor means that FooId is not a
- // "trivial" class and therefore is not a POD type (unlike an int32_t).
- // At the same time FooId has almost all of the properties of a POD type:
- // - is "trivially copyable" (i.e. is memcpy-able),
- // - has "standard layout" (i.e. interops with things expecting C layout).
- // See http://stackoverflow.com/a/7189821 for more info about these
- // concepts.
- static_assert(std::is_standard_layout<FooId>::value,
- "FooId should have standard layout. "
- "See http://stackoverflow.com/a/7189821 for more info.");
- static_assert(sizeof(FooId) == sizeof(int),
- "FooId should be the same size as the raw integer it wraps.");
- // TODO(lukasza): Enable these once <type_traits> supports all the standard
- // C++11 equivalents (i.e. std::is_trivially_copyable instead of the
- // non-standard std::has_trivial_copy_assign).
- // static_assert(std::has_trivial_copy_constructor<FooId>::value,
- // "FooId should have a trivial copy constructor.");
- // static_assert(std::has_trivial_copy_assign<FooId>::value,
- // "FooId should have a trivial copy assignment operator.");
- // static_assert(std::has_trivial_destructor<FooId>::value,
- // "FooId should have a trivial destructor.");
-}
-
-class IdTypeSpecificValueTest : public ::testing::TestWithParam<int> {
- protected:
- FooId test_id() { return FooId::FromUnsafeValue(GetParam()); }
-
- FooId other_id() {
- if (GetParam() != std::numeric_limits<int>::max())
- return FooId::FromUnsafeValue(GetParam() + 1);
- else
- return FooId::FromUnsafeValue(std::numeric_limits<int>::min());
- }
-};
-
-TEST_P(IdTypeSpecificValueTest, ComparisonToSelf) {
- EXPECT_TRUE(test_id() == test_id());
- EXPECT_FALSE(test_id() != test_id());
- EXPECT_FALSE(test_id() < test_id());
-}
-
-TEST_P(IdTypeSpecificValueTest, ComparisonToOther) {
- EXPECT_FALSE(test_id() == other_id());
- EXPECT_TRUE(test_id() != other_id());
-}
-
-TEST_P(IdTypeSpecificValueTest, UnsafeValueRoundtrips) {
- int original_value = GetParam();
- FooId id = FooId::FromUnsafeValue(original_value);
- int final_value = id.GetUnsafeValue();
- EXPECT_EQ(original_value, final_value);
-}
-
-TEST_P(IdTypeSpecificValueTest, Copying) {
- FooId original = test_id();
-
- FooId copy_via_constructor(original);
- EXPECT_EQ(original, copy_via_constructor);
-
- FooId copy_via_assignment;
- copy_via_assignment = original;
- EXPECT_EQ(original, copy_via_assignment);
-}
-
-TEST_P(IdTypeSpecificValueTest, BaseHashmap) {
- base::hash_map<FooId, std::string> map;
-
- map[test_id()] = "test_id";
- map[other_id()] = "other_id";
-
- EXPECT_EQ(map[test_id()], "test_id");
- EXPECT_EQ(map[other_id()], "other_id");
-}
-
-TEST_P(IdTypeSpecificValueTest, StdMap) {
- std::map<FooId, std::string> map;
-
- map[test_id()] = "test_id";
- map[other_id()] = "other_id";
-
- EXPECT_EQ(map[test_id()], "test_id");
- EXPECT_EQ(map[other_id()], "other_id");
-}
-
-INSTANTIATE_TEST_CASE_P(,
- IdTypeSpecificValueTest,
- ::testing::Values(std::numeric_limits<int>::min(),
- -1,
- 0,
- 1,
- 123,
- std::numeric_limits<int>::max()));
-
-} // namespace content
diff --git a/chromium/content/common/image_downloader/image_downloader.mojom b/chromium/content/common/image_downloader/image_downloader.mojom
index 7f3d289949d..b6ea34edd25 100644
--- a/chromium/content/common/image_downloader/image_downloader.mojom
+++ b/chromium/content/common/image_downloader/image_downloader.mojom
@@ -2,27 +2,20 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-module image_downloader;
+module content.mojom;
import "skia/public/interfaces/bitmap.mojom";
import "ui/mojo/geometry/geometry.mojom";
-struct DownloadRequest {
- string url;
- bool is_favicon;
- uint32 max_bitmap_size;
- bool bypass_cache;
-};
-
-struct DownloadResult {
- int32 http_status_code;
- array<skia.Bitmap> images;
- array<mojo.Size> original_image_sizes;
-};
-
interface ImageDownloader {
// Fetch and decode an image from a given URL.
// Returns the decoded images, or http_status_code to indicate error.
// Each call is independent, overlapping calls are possible.
- DownloadImage(DownloadRequest request) => (DownloadResult result);
+ DownloadImage(string url,
+ bool is_favicon,
+ uint32 max_bitmap_size,
+ bool bypass_cache)
+ => (int32 http_status_code,
+ array<skia.mojom.Bitmap> images,
+ array<mojo.Size> original_image_sizes);
};
diff --git a/chromium/content/common/in_process_child_thread_params.cc b/chromium/content/common/in_process_child_thread_params.cc
index 13e93902da6..84157997e06 100644
--- a/chromium/content/common/in_process_child_thread_params.cc
+++ b/chromium/content/common/in_process_child_thread_params.cc
@@ -8,9 +8,12 @@ namespace content {
InProcessChildThreadParams::InProcessChildThreadParams(
const std::string& channel_name,
- scoped_refptr<base::SequencedTaskRunner> io_runner)
- : channel_name_(channel_name), io_runner_(io_runner) {
-}
+ scoped_refptr<base::SequencedTaskRunner> io_runner,
+ mojo::MessagePipeHandle handle)
+ : channel_name_(channel_name), io_runner_(io_runner), handle_(handle) {}
+
+InProcessChildThreadParams::InProcessChildThreadParams(
+ const InProcessChildThreadParams& other) = default;
InProcessChildThreadParams::~InProcessChildThreadParams() {
}
diff --git a/chromium/content/common/in_process_child_thread_params.h b/chromium/content/common/in_process_child_thread_params.h
index 938a6ef0806..73838db02d5 100644
--- a/chromium/content/common/in_process_child_thread_params.h
+++ b/chromium/content/common/in_process_child_thread_params.h
@@ -10,6 +10,7 @@
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner.h"
#include "content/common/content_export.h"
+#include "mojo/public/cpp/system/message_pipe.h"
namespace content {
@@ -20,17 +21,21 @@ class CONTENT_EXPORT InProcessChildThreadParams {
public:
InProcessChildThreadParams(
const std::string& channel_name,
- scoped_refptr<base::SequencedTaskRunner> io_runner);
+ scoped_refptr<base::SequencedTaskRunner> io_runner,
+ mojo::MessagePipeHandle handle = mojo::MessagePipeHandle());
+ InProcessChildThreadParams(const InProcessChildThreadParams& other);
~InProcessChildThreadParams();
const std::string& channel_name() const { return channel_name_; }
scoped_refptr<base::SequencedTaskRunner> io_runner() const {
return io_runner_;
}
+ mojo::MessagePipeHandle handle() const { return handle_; }
private:
std::string channel_name_;
scoped_refptr<base::SequencedTaskRunner> io_runner_;
+ mojo::MessagePipeHandle handle_;
};
} // namespace content
diff --git a/chromium/content/common/indexed_db/indexed_db_messages.h b/chromium/content/common/indexed_db/indexed_db_messages.h
index d360454f499..f0ec336ad9c 100644
--- a/chromium/content/common/indexed_db/indexed_db_messages.h
+++ b/chromium/content/common/indexed_db/indexed_db_messages.h
@@ -47,8 +47,8 @@ IPC_STRUCT_BEGIN(IndexedDBHostMsg_FactoryGetDatabaseNames_Params)
// The response should have these ids.
IPC_STRUCT_MEMBER(int32_t, ipc_thread_id)
IPC_STRUCT_MEMBER(int32_t, ipc_callbacks_id)
- // The string id of the origin doing the initiating.
- IPC_STRUCT_MEMBER(std::string, database_identifier)
+ // The origin doing the initiating.
+ IPC_STRUCT_MEMBER(GURL, origin)
IPC_STRUCT_END()
// Used to open an indexed database.
@@ -59,8 +59,8 @@ IPC_STRUCT_BEGIN(IndexedDBHostMsg_FactoryOpen_Params)
IPC_STRUCT_MEMBER(int32_t, ipc_callbacks_id)
// Identifier for database callbacks
IPC_STRUCT_MEMBER(int32_t, ipc_database_callbacks_id)
- // The string id of the origin doing the initiating.
- IPC_STRUCT_MEMBER(std::string, database_identifier)
+ // The origin doing the initiating.
+ IPC_STRUCT_MEMBER(GURL, origin)
// The name of the database.
IPC_STRUCT_MEMBER(base::string16, name)
// The transaction id used if a database upgrade is needed.
@@ -74,8 +74,8 @@ IPC_STRUCT_BEGIN(IndexedDBHostMsg_FactoryDeleteDatabase_Params)
// The response should have these ids.
IPC_STRUCT_MEMBER(int32_t, ipc_thread_id)
IPC_STRUCT_MEMBER(int32_t, ipc_callbacks_id)
- // The string id of the origin doing the initiating.
- IPC_STRUCT_MEMBER(std::string, database_identifier)
+ // The origin doing the initiating.
+ IPC_STRUCT_MEMBER(GURL, origin)
// The name of the database.
IPC_STRUCT_MEMBER(base::string16, name)
IPC_STRUCT_END()
@@ -341,8 +341,7 @@ IPC_STRUCT_END()
IPC_STRUCT_BEGIN(IndexedDBDatabaseMetadata)
IPC_STRUCT_MEMBER(int64_t, id)
IPC_STRUCT_MEMBER(base::string16, name)
- IPC_STRUCT_MEMBER(base::string16, version)
- IPC_STRUCT_MEMBER(int64_t, int_version)
+ IPC_STRUCT_MEMBER(int64_t, version)
IPC_STRUCT_MEMBER(int64_t, max_object_store_id)
IPC_STRUCT_MEMBER(std::vector<IndexedDBObjectStoreMetadata>, object_stores)
IPC_STRUCT_END()
@@ -424,7 +423,7 @@ IPC_MESSAGE_CONTROL1(IndexedDBMsg_CallbacksUpgradeNeeded,
IPC_MESSAGE_CONTROL2(IndexedDBMsg_DatabaseCallbacksForcedClose,
int32_t, /* ipc_thread_id */
int32_t) /* ipc_database_callbacks_id */
-IPC_MESSAGE_CONTROL4(IndexedDBMsg_DatabaseCallbacksIntVersionChange,
+IPC_MESSAGE_CONTROL4(IndexedDBMsg_DatabaseCallbacksVersionChange,
int32_t, /* ipc_thread_id */
int32_t, /* ipc_database_callbacks_id */
int64_t, /* old_version */
diff --git a/chromium/content/common/indexed_db/indexed_db_param_traits.cc b/chromium/content/common/indexed_db/indexed_db_param_traits.cc
index 9ca0ceceeac..c684e9f24d7 100644
--- a/chromium/content/common/indexed_db/indexed_db_param_traits.cc
+++ b/chromium/content/common/indexed_db/indexed_db_param_traits.cc
@@ -30,7 +30,7 @@ using blink::WebIDBKeyTypeString;
namespace IPC {
-void ParamTraits<IndexedDBKey>::Write(Message* m, const param_type& p) {
+void ParamTraits<IndexedDBKey>::Write(base::Pickle* m, const param_type& p) {
WriteParam(m, static_cast<int>(p.type()));
switch (p.type()) {
case WebIDBKeyTypeArray:
@@ -58,7 +58,7 @@ void ParamTraits<IndexedDBKey>::Write(Message* m, const param_type& p) {
}
}
-bool ParamTraits<IndexedDBKey>::Read(const Message* m,
+bool ParamTraits<IndexedDBKey>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
int type;
@@ -153,7 +153,8 @@ void ParamTraits<IndexedDBKey>::Log(const param_type& p, std::string* l) {
l->append(")");
}
-void ParamTraits<IndexedDBKeyPath>::Write(Message* m, const param_type& p) {
+void ParamTraits<IndexedDBKeyPath>::Write(base::Pickle* m,
+ const param_type& p) {
WriteParam(m, static_cast<int>(p.type()));
switch (p.type()) {
case WebIDBKeyPathTypeArray:
@@ -170,7 +171,7 @@ void ParamTraits<IndexedDBKeyPath>::Write(Message* m, const param_type& p) {
}
}
-bool ParamTraits<IndexedDBKeyPath>::Read(const Message* m,
+bool ParamTraits<IndexedDBKeyPath>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
int type;
@@ -230,14 +231,15 @@ void ParamTraits<IndexedDBKeyPath>::Log(const param_type& p, std::string* l) {
l->append(")");
}
-void ParamTraits<IndexedDBKeyRange>::Write(Message* m, const param_type& p) {
+void ParamTraits<IndexedDBKeyRange>::Write(base::Pickle* m,
+ const param_type& p) {
WriteParam(m, p.lower());
WriteParam(m, p.upper());
WriteParam(m, p.lower_open());
WriteParam(m, p.upper_open());
}
-bool ParamTraits<IndexedDBKeyRange>::Read(const Message* m,
+bool ParamTraits<IndexedDBKeyRange>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
IndexedDBKey lower;
diff --git a/chromium/content/common/indexed_db/indexed_db_param_traits.h b/chromium/content/common/indexed_db/indexed_db_param_traits.h
index 8f6eeb20bee..e11b2830743 100644
--- a/chromium/content/common/indexed_db/indexed_db_param_traits.h
+++ b/chromium/content/common/indexed_db/indexed_db_param_traits.h
@@ -21,24 +21,30 @@ namespace IPC {
template <>
struct ParamTraits<content::IndexedDBKey> {
typedef content::IndexedDBKey param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct ParamTraits<content::IndexedDBKeyRange> {
typedef content::IndexedDBKeyRange param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct ParamTraits<content::IndexedDBKeyPath> {
typedef content::IndexedDBKeyPath param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
diff --git a/chromium/content/common/input/event_with_latency_info.h b/chromium/content/common/input/event_with_latency_info.h
new file mode 100644
index 00000000000..24742a3baeb
--- /dev/null
+++ b/chromium/content/common/input/event_with_latency_info.h
@@ -0,0 +1,63 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_INPUT_EVENT_WITH_LATENCY_INFO_H_
+#define CONTENT_COMMON_INPUT_EVENT_WITH_LATENCY_INFO_H_
+
+#include "ui/events/latency_info.h"
+
+#include "content/common/input/web_input_event_traits.h"
+
+namespace blink {
+class WebGestureEvent;
+class WebMouseEvent;
+class WebMouseWheelEvent;
+class WebTouchEvent;
+}
+
+namespace content {
+
+template <typename T>
+class EventWithLatencyInfo {
+ public:
+ T event;
+ mutable ui::LatencyInfo latency;
+
+ explicit EventWithLatencyInfo(const T& e) : event(e) {}
+
+ EventWithLatencyInfo(const T& e, const ui::LatencyInfo& l)
+ : event(e), latency(l) {}
+
+ EventWithLatencyInfo() {}
+
+ bool CanCoalesceWith(const EventWithLatencyInfo& other)
+ const WARN_UNUSED_RESULT {
+ return WebInputEventTraits::CanCoalesce(other.event, event);
+ }
+
+ void CoalesceWith(const EventWithLatencyInfo& other) {
+ // |other| should be a newer event than |this|.
+ if (other.latency.trace_id() >= 0 && latency.trace_id() >= 0)
+ DCHECK_GT(other.latency.trace_id(), latency.trace_id());
+ WebInputEventTraits::Coalesce(other.event, &event);
+ // When coalescing two input events, we keep the oldest LatencyInfo
+ // for Telemetry latency tests, since it will represent the longest
+ // latency.
+ other.latency = latency;
+ other.latency.set_coalesced();
+ }
+};
+
+typedef EventWithLatencyInfo<blink::WebGestureEvent>
+ GestureEventWithLatencyInfo;
+typedef EventWithLatencyInfo<blink::WebMouseWheelEvent>
+ MouseWheelEventWithLatencyInfo;
+typedef EventWithLatencyInfo<blink::WebMouseEvent>
+ MouseEventWithLatencyInfo;
+typedef EventWithLatencyInfo<blink::WebTouchEvent>
+ TouchEventWithLatencyInfo;
+
+} // namespace content
+
+#endif // CONTENT_COMMON_INPUT_EVENT_WITH_LATENCY_INFO_H_
diff --git a/chromium/content/browser/renderer_host/event_with_latency_info_unittest.cc b/chromium/content/common/input/event_with_latency_info_unittest.cc
index 42d490f8ad3..8ae533dd605 100644
--- a/chromium/content/browser/renderer_host/event_with_latency_info_unittest.cc
+++ b/chromium/content/common/input/event_with_latency_info_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/browser/renderer_host/event_with_latency_info.h"
+#include "content/common/input/event_with_latency_info.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
@@ -61,8 +61,6 @@ TEST_F(EventWithLatencyInfoTest, TimestampCoalescingForMouseEvent) {
mouse_0.CoalesceWith(mouse_1);
// Coalescing WebMouseEvent preserves newer timestamp.
EXPECT_EQ(10.0, mouse_0.event.timeStampSeconds);
- ASSERT_EQ(1u, mouse_0.latency.coalesced_events_size());
- EXPECT_EQ(5.0, mouse_0.latency.timestamps_of_coalesced_events()[0]);
}
TEST_F(EventWithLatencyInfoTest, TimestampCoalescingForMouseWheelEvent) {
@@ -73,8 +71,6 @@ TEST_F(EventWithLatencyInfoTest, TimestampCoalescingForMouseWheelEvent) {
mouse_wheel_0.CoalesceWith(mouse_wheel_1);
// Coalescing WebMouseWheelEvent preserves newer timestamp.
EXPECT_EQ(10.0, mouse_wheel_0.event.timeStampSeconds);
- ASSERT_EQ(1u, mouse_wheel_0.latency.coalesced_events_size());
- EXPECT_EQ(5.0, mouse_wheel_0.latency.timestamps_of_coalesced_events()[0]);
}
TEST_F(EventWithLatencyInfoTest, TimestampCoalescingForTouchEvent) {
@@ -87,8 +83,6 @@ TEST_F(EventWithLatencyInfoTest, TimestampCoalescingForTouchEvent) {
touch_0.CoalesceWith(touch_1);
// Coalescing WebTouchEvent preserves newer timestamp.
EXPECT_EQ(10.0, touch_0.event.timeStampSeconds);
- ASSERT_EQ(1u, touch_0.latency.coalesced_events_size());
- EXPECT_EQ(5.0, touch_0.latency.timestamps_of_coalesced_events()[0]);
}
TEST_F(EventWithLatencyInfoTest, TimestampCoalescingForGestureEvent) {
@@ -101,8 +95,27 @@ TEST_F(EventWithLatencyInfoTest, TimestampCoalescingForGestureEvent) {
scroll_0.CoalesceWith(scroll_1);
// Coalescing WebGestureEvent preserves newer timestamp.
EXPECT_EQ(10.0, scroll_0.event.timeStampSeconds);
- ASSERT_EQ(1u, scroll_0.latency.coalesced_events_size());
- EXPECT_EQ(5.0, scroll_0.latency.timestamps_of_coalesced_events()[0]);
+}
+
+TEST_F(EventWithLatencyInfoTest, LatencyInfoCoalescing) {
+ MouseEventWithLatencyInfo mouse_0 = CreateMouseEvent(
+ WebInputEvent::MouseMove, 5.0);
+ mouse_0.latency.AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 0, base::TimeTicks(), 1);
+ MouseEventWithLatencyInfo mouse_1 = CreateMouseEvent(
+ WebInputEvent::MouseMove, 10.0);
+
+ ASSERT_TRUE(mouse_0.CanCoalesceWith(mouse_1));
+
+ ui::LatencyInfo::LatencyComponent component;
+ EXPECT_FALSE(mouse_1.latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, &component));
+
+ mouse_0.CoalesceWith(mouse_1);
+
+ // Coalescing WebMouseEvent preservers older LatencyInfo.
+ EXPECT_TRUE(mouse_1.latency.FindLatency(
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, &component));
}
} // namespace
diff --git a/chromium/content/common/input/input_event_ack_state.h b/chromium/content/common/input/input_event_ack_state.h
index 5b9c706e6b4..c8e8f833b86 100644
--- a/chromium/content/common/input/input_event_ack_state.h
+++ b/chromium/content/common/input/input_event_ack_state.h
@@ -14,7 +14,8 @@ enum InputEventAckState {
INPUT_EVENT_ACK_STATE_NOT_CONSUMED,
INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS,
INPUT_EVENT_ACK_STATE_IGNORED,
- INPUT_EVENT_ACK_STATE_MAX = INPUT_EVENT_ACK_STATE_IGNORED
+ INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING,
+ INPUT_EVENT_ACK_STATE_MAX = INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING
};
} // namespace content
diff --git a/chromium/content/common/input/input_event_dispatch_type.h b/chromium/content/common/input/input_event_dispatch_type.h
new file mode 100644
index 00000000000..ea802ff2c81
--- /dev/null
+++ b/chromium/content/common/input/input_event_dispatch_type.h
@@ -0,0 +1,26 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_INPUT_INPUT_EVENT_DISPATCH_TYPE_H_
+#define CONTENT_COMMON_INPUT_INPUT_EVENT_DISPATCH_TYPE_H_
+
+namespace content {
+
+enum InputEventDispatchType {
+ // Dispatch a blocking event. Sender is waiting on an ACK.
+ DISPATCH_TYPE_BLOCKING,
+ // Dispatch a blocking event and notify main thread as well. This type
+ // should only be sent from the compositor to main thread.
+ DISPATCH_TYPE_BLOCKING_NOTIFY_MAIN,
+ // Dispatch a non-blocking event. Sender will not receive an ACK.
+ DISPATCH_TYPE_NON_BLOCKING,
+ // Dispatch a non-blocking event and notify main thread as well. This type
+ // should only be sent from the compositor to main thread.
+ DISPATCH_TYPE_NON_BLOCKING_NOTIFY_MAIN,
+ DISPATCH_TYPE_MAX = DISPATCH_TYPE_NON_BLOCKING_NOTIFY_MAIN
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_INPUT_INPUT_EVENT_DISPATCH_TYPE_H_
diff --git a/chromium/content/common/input/input_event_utils.cc b/chromium/content/common/input/input_event_utils.cc
new file mode 100644
index 00000000000..31669ed3ca3
--- /dev/null
+++ b/chromium/content/common/input/input_event_utils.cc
@@ -0,0 +1,17 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/input/input_event_utils.h"
+
+#include "base/command_line.h"
+#include "content/public/common/content_switches.h"
+
+namespace content {
+
+bool UseGestureBasedWheelScrolling() {
+ base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
+ return !cmd->HasSwitch(switches::kDisableWheelGestures);
+}
+
+} // namespace content
diff --git a/chromium/content/common/input/input_event_utils.h b/chromium/content/common/input/input_event_utils.h
new file mode 100644
index 00000000000..c1a61ce2444
--- /dev/null
+++ b/chromium/content/common/input/input_event_utils.h
@@ -0,0 +1,17 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_INPUT_INPUT_EVENT_UTILS_H_
+#define CONTENT_RENDERER_INPUT_INPUT_EVENT_UTILS_H_
+
+#include "content/common/content_export.h"
+#include "content/public/common/content_switches.h"
+
+namespace content {
+
+CONTENT_EXPORT bool UseGestureBasedWheelScrolling();
+
+}; // namespace content
+
+#endif // CONTENT_RENDERER_INPUT_INPUT_EVENT_UTILS_H_
diff --git a/chromium/content/common/input/input_param_traits.cc b/chromium/content/common/input/input_param_traits.cc
index 0402f433c5e..076d54ace06 100644
--- a/chromium/content/common/input/input_param_traits.cc
+++ b/chromium/content/common/input/input_param_traits.cc
@@ -8,6 +8,7 @@
#include "content/common/content_param_traits.h"
#include "content/common/input/synthetic_pinch_gesture_params.h"
+#include "content/common/input/synthetic_pointer_action_params.h"
#include "content/common/input/synthetic_smooth_drag_gesture_params.h"
#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
#include "content/common/input/web_input_event_traits.h"
@@ -17,7 +18,7 @@ namespace IPC {
namespace {
template <typename GestureType>
scoped_ptr<content::SyntheticGestureParams> ReadGestureParams(
- const Message* m,
+ const base::Pickle* m,
base::PickleIterator* iter) {
scoped_ptr<GestureType> gesture_params(new GestureType);
if (!ReadParam(m, iter, gesture_params.get()))
@@ -27,7 +28,7 @@ scoped_ptr<content::SyntheticGestureParams> ReadGestureParams(
}
} // namespace
-void ParamTraits<content::ScopedWebInputEvent>::Write(Message* m,
+void ParamTraits<content::ScopedWebInputEvent>::Write(base::Pickle* m,
const param_type& p) {
bool valid_web_event = !!p;
WriteParam(m, valid_web_event);
@@ -35,7 +36,7 @@ void ParamTraits<content::ScopedWebInputEvent>::Write(Message* m,
WriteParam(m, static_cast<WebInputEventPointer>(p.get()));
}
-bool ParamTraits<content::ScopedWebInputEvent>::Read(const Message* m,
+bool ParamTraits<content::ScopedWebInputEvent>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* p) {
bool valid_web_event = false;
@@ -55,7 +56,7 @@ void ParamTraits<content::ScopedWebInputEvent>::Log(const param_type& p,
LogParam(static_cast<WebInputEventPointer>(p.get()), l);
}
-void ParamTraits<content::SyntheticGesturePacket>::Write(Message* m,
+void ParamTraits<content::SyntheticGesturePacket>::Write(base::Pickle* m,
const param_type& p) {
DCHECK(p.gesture_params());
WriteParam(m, p.gesture_params()->GetGestureType());
@@ -76,11 +77,15 @@ void ParamTraits<content::SyntheticGesturePacket>::Write(Message* m,
WriteParam(m, *content::SyntheticTapGestureParams::Cast(
p.gesture_params()));
break;
+ case content::SyntheticGestureParams::POINTER_ACTION:
+ WriteParam(
+ m, *content::SyntheticPointerActionParams::Cast(p.gesture_params()));
+ break;
}
}
bool ParamTraits<content::SyntheticGesturePacket>::Read(
- const Message* m,
+ const base::Pickle* m,
base::PickleIterator* iter,
param_type* p) {
content::SyntheticGestureParams::GestureType gesture_type;
@@ -105,6 +110,11 @@ bool ParamTraits<content::SyntheticGesturePacket>::Read(
gesture_params =
ReadGestureParams<content::SyntheticTapGestureParams>(m, iter);
break;
+ case content::SyntheticGestureParams::POINTER_ACTION: {
+ gesture_params =
+ ReadGestureParams<content::SyntheticPointerActionParams>(m, iter);
+ break;
+ }
default:
return false;
}
@@ -138,6 +148,10 @@ void ParamTraits<content::SyntheticGesturePacket>::Log(const param_type& p,
*content::SyntheticTapGestureParams::Cast(p.gesture_params()),
l);
break;
+ case content::SyntheticGestureParams::POINTER_ACTION:
+ LogParam(*content::SyntheticPointerActionParams::Cast(p.gesture_params()),
+ l);
+ break;
}
}
diff --git a/chromium/content/common/input/input_param_traits.h b/chromium/content/common/input/input_param_traits.h
index 9f5b1cec36c..1c204c3bc31 100644
--- a/chromium/content/common/input/input_param_traits.h
+++ b/chromium/content/common/input/input_param_traits.h
@@ -18,16 +18,20 @@ namespace IPC {
template <>
struct CONTENT_EXPORT ParamTraits<content::ScopedWebInputEvent> {
typedef content::ScopedWebInputEvent param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template<>
struct CONTENT_EXPORT ParamTraits<content::SyntheticGesturePacket> {
typedef content::SyntheticGesturePacket param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
diff --git a/chromium/content/common/input/input_param_traits_unittest.cc b/chromium/content/common/input/input_param_traits_unittest.cc
index 0dd2b3d1441..1935f9ca945 100644
--- a/chromium/content/common/input/input_param_traits_unittest.cc
+++ b/chromium/content/common/input/input_param_traits_unittest.cc
@@ -10,6 +10,7 @@
#include "content/common/input/input_event.h"
#include "content/common/input/synthetic_gesture_params.h"
#include "content/common/input/synthetic_pinch_gesture_params.h"
+#include "content/common/input/synthetic_pointer_action_params.h"
#include "content/common/input/synthetic_smooth_drag_gesture_params.h"
#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
#include "content/common/input_messages.h"
@@ -77,6 +78,22 @@ class InputParamTraitsTest : public testing::Test {
EXPECT_EQ(a->duration_ms, b->duration_ms);
}
+ static void Compare(const SyntheticPointerActionParams* a,
+ const SyntheticPointerActionParams* b) {
+ EXPECT_EQ(a->gesture_source_type, b->gesture_source_type);
+ EXPECT_EQ(a->pointer_action_type(), b->pointer_action_type());
+ if (a->pointer_action_type() ==
+ SyntheticPointerActionParams::PointerActionType::PRESS ||
+ a->pointer_action_type() ==
+ SyntheticPointerActionParams::PointerActionType::MOVE) {
+ EXPECT_EQ(a->position(), b->position());
+ }
+ if (a->pointer_action_type() !=
+ SyntheticPointerActionParams::PointerActionType::PROCESS) {
+ EXPECT_EQ(a->index(), b->index());
+ }
+ }
+
static void Compare(const SyntheticGesturePacket* a,
const SyntheticGesturePacket* b) {
ASSERT_EQ(!!a, !!b);
@@ -102,6 +119,10 @@ class InputParamTraitsTest : public testing::Test {
Compare(SyntheticTapGestureParams::Cast(a->gesture_params()),
SyntheticTapGestureParams::Cast(b->gesture_params()));
break;
+ case SyntheticGestureParams::POINTER_ACTION:
+ Compare(SyntheticPointerActionParams::Cast(a->gesture_params()),
+ SyntheticPointerActionParams::Cast(b->gesture_params()));
+ break;
}
}
@@ -250,5 +271,44 @@ TEST_F(InputParamTraitsTest, SyntheticTapGestureParams) {
Verify(packet_in);
}
+TEST_F(InputParamTraitsTest, SyntheticPointerActionParamsMove) {
+ scoped_ptr<SyntheticPointerActionParams> gesture_params(
+ new SyntheticPointerActionParams(
+ SyntheticPointerActionParams::PointerActionType::MOVE));
+ gesture_params->gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ gesture_params->set_position(gfx::PointF(356, 287));
+ gesture_params->set_index(0);
+ ASSERT_EQ(SyntheticGestureParams::POINTER_ACTION,
+ gesture_params->GetGestureType());
+ SyntheticGesturePacket packet_in;
+ packet_in.set_gesture_params(std::move(gesture_params));
+ Verify(packet_in);
+}
+
+TEST_F(InputParamTraitsTest, SyntheticPointerActionParamsRelease) {
+ scoped_ptr<SyntheticPointerActionParams> gesture_params(
+ new SyntheticPointerActionParams(
+ SyntheticPointerActionParams::PointerActionType::RELEASE));
+ gesture_params->gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ gesture_params->set_index(0);
+ ASSERT_EQ(SyntheticGestureParams::POINTER_ACTION,
+ gesture_params->GetGestureType());
+ SyntheticGesturePacket packet_in;
+ packet_in.set_gesture_params(std::move(gesture_params));
+ Verify(packet_in);
+}
+
+TEST_F(InputParamTraitsTest, SyntheticPointerActionParamsProcess) {
+ scoped_ptr<SyntheticPointerActionParams> gesture_params(
+ new SyntheticPointerActionParams(
+ SyntheticPointerActionParams::PointerActionType::PROCESS));
+ gesture_params->gesture_source_type = SyntheticGestureParams::TOUCH_INPUT;
+ ASSERT_EQ(SyntheticGestureParams::POINTER_ACTION,
+ gesture_params->GetGestureType());
+ SyntheticGesturePacket packet_in;
+ packet_in.set_gesture_params(std::move(gesture_params));
+ Verify(packet_in);
+}
+
} // namespace
} // namespace content
diff --git a/chromium/content/common/input/synthetic_gesture_params.h b/chromium/content/common/input/synthetic_gesture_params.h
index 1c40ca98fd2..5ece4db2996 100644
--- a/chromium/content/common/input/synthetic_gesture_params.h
+++ b/chromium/content/common/input/synthetic_gesture_params.h
@@ -48,8 +48,10 @@ struct CONTENT_EXPORT SyntheticGestureParams {
SMOOTH_DRAG_GESTURE,
PINCH_GESTURE,
TAP_GESTURE,
- SYNTHETIC_GESTURE_TYPE_MAX = TAP_GESTURE
+ POINTER_ACTION,
+ SYNTHETIC_GESTURE_TYPE_MAX = POINTER_ACTION
};
+
virtual GestureType GetGestureType() const = 0;
// Returns true if the specific gesture source type is supported on this
diff --git a/chromium/content/common/input/synthetic_pointer_action_params.cc b/chromium/content/common/input/synthetic_pointer_action_params.cc
new file mode 100644
index 00000000000..593413b9822
--- /dev/null
+++ b/chromium/content/common/input/synthetic_pointer_action_params.cc
@@ -0,0 +1,48 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/input/synthetic_pointer_action_params.h"
+
+namespace content {
+
+SyntheticPointerActionParams::SyntheticPointerActionParams()
+ : pointer_action_type_(PointerActionType::NOT_INITIALIZED), index_(-1) {}
+
+SyntheticPointerActionParams::SyntheticPointerActionParams(
+ PointerActionType type)
+ : pointer_action_type_(type), index_(-1) {}
+
+SyntheticPointerActionParams::SyntheticPointerActionParams(
+ const SyntheticPointerActionParams& other)
+ : SyntheticGestureParams(other),
+ pointer_action_type_(other.pointer_action_type()) {
+ switch (other.pointer_action_type()) {
+ case PointerActionType::PRESS:
+ case PointerActionType::MOVE:
+ index_ = other.index();
+ position_ = other.position();
+ break;
+ case PointerActionType::RELEASE:
+ index_ = other.index();
+ break;
+ default:
+ break;
+ }
+}
+
+SyntheticPointerActionParams::~SyntheticPointerActionParams() {}
+
+SyntheticGestureParams::GestureType
+SyntheticPointerActionParams::GetGestureType() const {
+ return POINTER_ACTION;
+}
+
+const SyntheticPointerActionParams* SyntheticPointerActionParams::Cast(
+ const SyntheticGestureParams* gesture_params) {
+ DCHECK(gesture_params);
+ DCHECK_EQ(POINTER_ACTION, gesture_params->GetGestureType());
+ return static_cast<const SyntheticPointerActionParams*>(gesture_params);
+}
+
+} // namespace content
diff --git a/chromium/content/common/input/synthetic_pointer_action_params.h b/chromium/content/common/input/synthetic_pointer_action_params.h
new file mode 100644
index 00000000000..fe6c9f9b4a3
--- /dev/null
+++ b/chromium/content/common/input/synthetic_pointer_action_params.h
@@ -0,0 +1,86 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_INPUT_SYNTHETIC_POINTER_ACTION_PARAMS_H_
+#define CONTENT_COMMON_INPUT_SYNTHETIC_POINTER_ACTION_PARAMS_H_
+
+#include "base/logging.h"
+#include "content/common/content_export.h"
+#include "content/common/input/input_param_traits.h"
+#include "content/common/input/synthetic_gesture_params.h"
+#include "ui/gfx/geometry/point_f.h"
+
+namespace ipc_fuzzer {
+template <class T>
+struct FuzzTraits;
+} // namespace ipc_fuzzer
+
+namespace content {
+
+struct CONTENT_EXPORT SyntheticPointerActionParams
+ : public SyntheticGestureParams {
+ public:
+ // Actions are queued up until we receive a PROCESS action, at which point
+ // we'll dispatch all queued events.
+ enum class PointerActionType {
+ NOT_INITIALIZED,
+ PRESS,
+ MOVE,
+ RELEASE,
+ PROCESS,
+ POINTER_ACTION_TYPE_MAX = PROCESS
+ };
+
+ SyntheticPointerActionParams();
+ explicit SyntheticPointerActionParams(PointerActionType type);
+ SyntheticPointerActionParams(const SyntheticPointerActionParams& other);
+ ~SyntheticPointerActionParams() override;
+
+ GestureType GetGestureType() const override;
+
+ static const SyntheticPointerActionParams* Cast(
+ const SyntheticGestureParams* gesture_params);
+
+ void set_pointer_action_type(PointerActionType pointer_action_type) {
+ pointer_action_type_ = pointer_action_type;
+ }
+
+ void set_index(int index) {
+ DCHECK(pointer_action_type_ != PointerActionType::PROCESS);
+ index_ = index;
+ }
+
+ void set_position(const gfx::PointF& position) {
+ DCHECK(pointer_action_type_ == PointerActionType::PRESS ||
+ pointer_action_type_ == PointerActionType::MOVE);
+ position_ = position;
+ }
+
+ PointerActionType pointer_action_type() const { return pointer_action_type_; }
+
+ int index() const {
+ DCHECK(pointer_action_type_ != PointerActionType::PROCESS);
+ return index_;
+ }
+
+ gfx::PointF position() const {
+ DCHECK(pointer_action_type_ == PointerActionType::PRESS ||
+ pointer_action_type_ == PointerActionType::MOVE);
+ return position_;
+ }
+
+ private:
+ friend struct IPC::ParamTraits<content::SyntheticPointerActionParams>;
+ friend struct ipc_fuzzer::FuzzTraits<content::SyntheticPointerActionParams>;
+
+ PointerActionType pointer_action_type_;
+ // Pass a position value when sending a press or move action.
+ gfx::PointF position_;
+ // Pass an index value except if the pointer_action_type_ is PROCESS.
+ int index_;
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_INPUT_SYNTHETIC_POINTER_ACTION_PARAMS_H_
diff --git a/chromium/content/common/input/synthetic_web_input_event_builders.cc b/chromium/content/common/input/synthetic_web_input_event_builders.cc
index e2e17febb95..c68c689c09b 100644
--- a/chromium/content/common/input/synthetic_web_input_event_builders.cc
+++ b/chromium/content/common/input/synthetic_web_input_event_builders.cc
@@ -61,8 +61,21 @@ WebMouseWheelEvent SyntheticWebMouseWheelEventBuilder::Build(float x,
float dy,
int modifiers,
bool precise) {
+ return Build(x, y, 0, 0, dx, dy, modifiers, precise);
+}
+
+WebMouseWheelEvent SyntheticWebMouseWheelEventBuilder::Build(float x,
+ float y,
+ float global_x,
+ float global_y,
+ float dx,
+ float dy,
+ int modifiers,
+ bool precise) {
WebMouseWheelEvent result;
result.type = WebInputEvent::MouseWheel;
+ result.globalX = global_x;
+ result.globalY = global_y;
result.x = x;
result.y = y;
result.deltaX = dx;
@@ -171,7 +184,7 @@ void SyntheticWebTouchEvent::ResetPoints() {
}
touchesLength = point;
type = WebInputEvent::Undefined;
- causesScrollingIfUncanceled = false;
+ movedBeyondSlopRegion = false;
uniqueTouchEventId = ui::GetNextTouchEventId();
}
@@ -198,7 +211,7 @@ void SyntheticWebTouchEvent::MovePoint(int index, float x, float y) {
CHECK_LT(index, touchesLengthCap);
// Always set this bit to avoid otherwise unexpected touchmove suppression.
// The caller can opt-out explicitly, if necessary.
- causesScrollingIfUncanceled = true;
+ movedBeyondSlopRegion = true;
WebTouchPoint& point = touches[index];
point.position.x = point.screenPosition.x = x;
point.position.y = point.screenPosition.y = y;
diff --git a/chromium/content/common/input/synthetic_web_input_event_builders.h b/chromium/content/common/input/synthetic_web_input_event_builders.h
index ef1a1694bb7..e865e9b23ce 100644
--- a/chromium/content/common/input/synthetic_web_input_event_builders.h
+++ b/chromium/content/common/input/synthetic_web_input_event_builders.h
@@ -32,6 +32,14 @@ class CONTENT_EXPORT SyntheticWebMouseWheelEventBuilder {
float dy,
int modifiers,
bool precise);
+ static blink::WebMouseWheelEvent Build(float x,
+ float y,
+ float global_x,
+ float global_y,
+ float dx,
+ float dy,
+ int modifiers,
+ bool precise);
};
class CONTENT_EXPORT SyntheticWebKeyboardEventBuilder {
diff --git a/chromium/content/common/input/web_input_event_queue.h b/chromium/content/common/input/web_input_event_queue.h
new file mode 100644
index 00000000000..fa85bd4f773
--- /dev/null
+++ b/chromium/content/common/input/web_input_event_queue.h
@@ -0,0 +1,79 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_INPUT_WEB_INPUT_EVENT_QUEUE_H_
+#define CONTENT_COMMON_INPUT_WEB_INPUT_EVENT_QUEUE_H_
+
+#include <deque>
+
+#include "base/memory/scoped_ptr.h"
+
+namespace content {
+
+enum class WebInputEventQueueState { ITEM_PENDING, ITEM_NOT_PENDING };
+
+// WebInputEventQueue is a coalescing queue with the addition of a state
+// variable that represents whether an item is pending to be processed.
+// The desired usage sending with this queue is:
+// if (queue.state() == WebInputEventQueueState::ITEM_PENDING) {
+// queue.Queue(T);
+// } else {
+// send T
+// queue.set_state(WebInputEventQueueState::ITEM_PENDING);
+// }
+//
+// Processing the event response:
+// if (!queue.empty()) {
+// T = queue.Pop();
+// send T now
+// } else {
+// queue.set_state(WebInputEventQueueState::ITEM_NOT_PENDING);
+// }
+//
+template <typename T>
+class WebInputEventQueue {
+ public:
+ WebInputEventQueue() : state_(WebInputEventQueueState::ITEM_NOT_PENDING) {}
+
+ // Adds an event to the queue. The event may be coalesced with previously
+ // queued events.
+ void Queue(const T& event) {
+ if (!queue_.empty()) {
+ scoped_ptr<T>& last_event = queue_.back();
+ if (last_event->CanCoalesceWith(event)) {
+ last_event->CoalesceWith(event);
+ return;
+ }
+ }
+ queue_.emplace_back(scoped_ptr<T>(new T(event)));
+ }
+
+ scoped_ptr<T> Pop() {
+ scoped_ptr<T> result;
+ if (!queue_.empty()) {
+ result.reset(queue_.front().release());
+ queue_.pop_front();
+ }
+ return result;
+ }
+
+ bool empty() const { return queue_.empty(); }
+
+ size_t size() const { return queue_.size(); }
+
+ void set_state(WebInputEventQueueState state) { state_ = state; }
+
+ WebInputEventQueueState state() const WARN_UNUSED_RESULT { return state_; }
+
+ private:
+ typedef std::deque<scoped_ptr<T>> EventQueue;
+ EventQueue queue_;
+ WebInputEventQueueState state_;
+
+ DISALLOW_COPY_AND_ASSIGN(WebInputEventQueue);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_INPUT_WEB_INPUT_EVENT_QUEUE_H_
diff --git a/chromium/content/common/input/web_input_event_traits.cc b/chromium/content/common/input/web_input_event_traits.cc
index 1008c549ef6..3aed966c5b6 100644
--- a/chromium/content/common/input/web_input_event_traits.cc
+++ b/chromium/content/common/input/web_input_event_traits.cc
@@ -111,10 +111,10 @@ void ApppendTouchPointDetails(const WebTouchPoint& point, std::string* result) {
void ApppendEventDetails(const WebTouchEvent& event, std::string* result) {
StringAppendF(result,
- "{\n Touches: %u, Cancelable: %d, CausesScrolling: %d,"
+ "{\n Touches: %u, DispatchType: %d, CausesScrolling: %d,"
" uniqueTouchEventId: %u\n[\n",
- event.touchesLength, event.cancelable,
- event.causesScrollingIfUncanceled, event.uniqueTouchEventId);
+ event.touchesLength, event.dispatchType,
+ event.movedBeyondSlopRegion, event.uniqueTouchEventId);
for (unsigned i = 0; i < event.touchesLength; ++i)
ApppendTouchPointDetails(event.touches[i], result);
result->append(" ]\n}");
@@ -199,6 +199,23 @@ int GetIndexOfTouchID(const WebTouchEvent& event, int id) {
return kInvalidTouchIndex;
}
+WebInputEvent::DispatchType MergeDispatchTypes(
+ WebInputEvent::DispatchType type_1,
+ WebInputEvent::DispatchType type_2) {
+ static_assert(WebInputEvent::DispatchType::Blocking <
+ WebInputEvent::DispatchType::EventNonBlocking,
+ "Enum not ordered correctly");
+ static_assert(WebInputEvent::DispatchType::EventNonBlocking <
+ WebInputEvent::DispatchType::ListenersNonBlockingPassive,
+ "Enum not ordered correctly");
+ static_assert(
+ WebInputEvent::DispatchType::ListenersNonBlockingPassive <
+ WebInputEvent::DispatchType::ListenersForcedNonBlockingPassive,
+ "Enum not ordered correctly");
+ return static_cast<WebInputEvent::DispatchType>(
+ std::min(static_cast<int>(type_1), static_cast<int>(type_2)));
+}
+
bool CanCoalesce(const WebTouchEvent& event_to_coalesce,
const WebTouchEvent& event) {
if (event.type != event_to_coalesce.type ||
@@ -240,7 +257,9 @@ void Coalesce(const WebTouchEvent& event_to_coalesce, WebTouchEvent* event) {
if (old_event.touches[i_old].state == blink::WebTouchPoint::StateMoved)
event->touches[i].state = blink::WebTouchPoint::StateMoved;
}
- event->causesScrollingIfUncanceled |= old_event.causesScrollingIfUncanceled;
+ event->movedBeyondSlopRegion |= old_event.movedBeyondSlopRegion;
+ event->dispatchType = MergeDispatchTypes(old_event.dispatchType,
+ event_to_coalesce.dispatchType);
}
bool CanCoalesce(const WebGestureEvent& event_to_coalesce,
@@ -466,8 +485,7 @@ void WebInputEventTraits::Coalesce(const WebInputEvent& event_to_coalesce,
Apply(WebInputEventCoalesce(), event->type, event_to_coalesce, event);
}
-bool WebInputEventTraits::WillReceiveAckFromRenderer(
- const WebInputEvent& event) {
+bool WebInputEventTraits::ShouldBlockEventStream(const WebInputEvent& event) {
switch (event.type) {
case WebInputEvent::MouseDown:
case WebInputEvent::MouseUp:
@@ -482,11 +500,24 @@ bool WebInputEventTraits::WillReceiveAckFromRenderer(
case WebInputEvent::GestureTapCancel:
case WebInputEvent::GesturePinchBegin:
case WebInputEvent::GesturePinchEnd:
+ return false;
+
+ // TouchCancel should always be non-blocking.
case WebInputEvent::TouchCancel:
+ DCHECK_NE(WebInputEvent::Blocking,
+ static_cast<const WebTouchEvent&>(event).dispatchType);
return false;
+
+ // Touch start and touch end indicate whether they are non-blocking
+ // (aka uncancelable) on the event.
case WebInputEvent::TouchStart:
case WebInputEvent::TouchEnd:
- return static_cast<const WebTouchEvent&>(event).cancelable;
+ return static_cast<const WebTouchEvent&>(event).dispatchType ==
+ WebInputEvent::Blocking;
+
+ // Touch move events may be non-blocking but are always explicitly
+ // acknowledge by the renderer so they block the event stream.
+ case WebInputEvent::TouchMove:
default:
return true;
}
diff --git a/chromium/content/common/input/web_input_event_traits.h b/chromium/content/common/input/web_input_event_traits.h
index 008439c9e28..2f9ca8c5232 100644
--- a/chromium/content/common/input/web_input_event_traits.h
+++ b/chromium/content/common/input/web_input_event_traits.h
@@ -27,7 +27,7 @@ class CONTENT_EXPORT WebInputEventTraits {
const blink::WebInputEvent& event);
static void Coalesce(const blink::WebInputEvent& event_to_coalesce,
blink::WebInputEvent* event);
- static bool WillReceiveAckFromRenderer(const blink::WebInputEvent& event);
+ static bool ShouldBlockEventStream(const blink::WebInputEvent& event);
// Return uniqueTouchEventId for WebTouchEvent, otherwise return 0.
static uint32_t GetUniqueTouchEventId(const blink::WebInputEvent& event);
diff --git a/chromium/content/common/input/web_input_event_traits_unittest.cc b/chromium/content/common/input/web_input_event_traits_unittest.cc
index 6ae3d936616..1daf80dcf1a 100644
--- a/chromium/content/common/input/web_input_event_traits_unittest.cc
+++ b/chromium/content/common/input/web_input_event_traits_unittest.cc
@@ -124,6 +124,34 @@ TEST_F(WebInputEventTraitsTest, TouchEventCoalescing) {
ASSERT_EQ(0, touch1.touches[1].id);
EXPECT_EQ(WebTouchPoint::StateMoved, touch1.touches[0].state);
EXPECT_EQ(WebTouchPoint::StateMoved, touch1.touches[1].state);
+
+ // Touch moves with different dispatchTypes coalesce.
+ touch0 = CreateTouch(WebInputEvent::TouchMove, 2);
+ touch0.dispatchType = WebInputEvent::DispatchType::Blocking;
+ touch1 = CreateTouch(WebInputEvent::TouchMove, 2);
+ touch1.dispatchType = WebInputEvent::DispatchType::EventNonBlocking;
+ touch0.touches[0] = touch1.touches[1] =
+ CreateTouchPoint(WebTouchPoint::StateMoved, 1);
+ touch0.touches[1] = touch1.touches[0] =
+ CreateTouchPoint(WebTouchPoint::StateMoved, 0);
+ EXPECT_TRUE(WebInputEventTraits::CanCoalesce(touch0, touch1));
+ WebInputEventTraits::Coalesce(touch0, &touch1);
+ ASSERT_EQ(WebInputEvent::DispatchType::Blocking, touch1.dispatchType);
+
+ touch0 = CreateTouch(WebInputEvent::TouchMove, 2);
+ touch0.dispatchType =
+ WebInputEvent::DispatchType::ListenersForcedNonBlockingPassive;
+ touch1 = CreateTouch(WebInputEvent::TouchMove, 2);
+ touch1.dispatchType =
+ WebInputEvent::DispatchType::ListenersNonBlockingPassive;
+ touch0.touches[0] = touch1.touches[1] =
+ CreateTouchPoint(WebTouchPoint::StateMoved, 1);
+ touch0.touches[1] = touch1.touches[0] =
+ CreateTouchPoint(WebTouchPoint::StateMoved, 0);
+ EXPECT_TRUE(WebInputEventTraits::CanCoalesce(touch0, touch1));
+ WebInputEventTraits::Coalesce(touch0, &touch1);
+ ASSERT_EQ(WebInputEvent::DispatchType::ListenersNonBlockingPassive,
+ touch1.dispatchType);
}
TEST_F(WebInputEventTraitsTest, PinchEventCoalescing) {
diff --git a/chromium/content/common/input/web_touch_event_traits.cc b/chromium/content/common/input/web_touch_event_traits.cc
index 175bf78ef41..77aa00f7069 100644
--- a/chromium/content/common/input/web_touch_event_traits.cc
+++ b/chromium/content/common/input/web_touch_event_traits.cc
@@ -52,7 +52,9 @@ void WebTouchEventTraits::ResetType(WebInputEvent::Type type,
WebTouchEvent* event) {
DCHECK(WebInputEvent::isTouchEventType(type));
event->type = type;
- event->cancelable = (type != WebInputEvent::TouchCancel);
+ event->dispatchType = type == WebInputEvent::TouchCancel
+ ? WebInputEvent::EventNonBlocking
+ : WebInputEvent::Blocking;
event->timeStampSeconds = timestamp_sec;
}
diff --git a/chromium/content/common/input_messages.h b/chromium/content/common/input_messages.h
index a511d018458..e83a77bac4e 100644
--- a/chromium/content/common/input_messages.h
+++ b/chromium/content/common/input_messages.h
@@ -15,15 +15,16 @@
#include "content/common/input/input_event.h"
#include "content/common/input/input_event_ack.h"
#include "content/common/input/input_event_ack_state.h"
+#include "content/common/input/input_event_dispatch_type.h"
#include "content/common/input/input_param_traits.h"
#include "content/common/input/synthetic_gesture_packet.h"
#include "content/common/input/synthetic_gesture_params.h"
#include "content/common/input/synthetic_pinch_gesture_params.h"
+#include "content/common/input/synthetic_pointer_action_params.h"
#include "content/common/input/synthetic_smooth_drag_gesture_params.h"
#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
#include "content/common/input/synthetic_tap_gesture_params.h"
#include "content/common/input/touch_action.h"
-#include "content/public/common/common_param_traits.h"
#include "ipc/ipc_message_macros.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/events/ipc/latency_info_param_traits.h"
@@ -31,6 +32,7 @@
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/vector2d_f.h"
#include "ui/gfx/ipc/gfx_param_traits.h"
+#include "ui/gfx/ipc/skia/gfx_skia_param_traits.h"
#include "ui/gfx/range/range.h"
#undef IPC_MESSAGE_EXPORT
@@ -48,6 +50,12 @@ IPC_ENUM_TRAITS_MAX_VALUE(
IPC_ENUM_TRAITS_MAX_VALUE(
content::SyntheticGestureParams::GestureType,
content::SyntheticGestureParams::SYNTHETIC_GESTURE_TYPE_MAX)
+IPC_ENUM_TRAITS_MAX_VALUE(
+ content::SyntheticPointerActionParams::PointerActionType,
+ content::SyntheticPointerActionParams::PointerActionType::
+ POINTER_ACTION_TYPE_MAX)
+IPC_ENUM_TRAITS_MAX_VALUE(content::InputEventDispatchType,
+ content::InputEventDispatchType::DISPATCH_TYPE_MAX)
IPC_ENUM_TRAITS_VALIDATE(content::TouchAction, (
value >= 0 &&
value <= content::TOUCH_ACTION_MAX &&
@@ -105,6 +113,13 @@ IPC_STRUCT_TRAITS_BEGIN(content::SyntheticTapGestureParams)
IPC_STRUCT_TRAITS_MEMBER(duration_ms)
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_TRAITS_BEGIN(content::SyntheticPointerActionParams)
+ IPC_STRUCT_TRAITS_PARENT(content::SyntheticGestureParams)
+ IPC_STRUCT_TRAITS_MEMBER(pointer_action_type_)
+ IPC_STRUCT_TRAITS_MEMBER(index_)
+ IPC_STRUCT_TRAITS_MEMBER(position_)
+IPC_STRUCT_TRAITS_END()
+
IPC_STRUCT_TRAITS_BEGIN(content::InputEventAck)
IPC_STRUCT_TRAITS_MEMBER(type)
IPC_STRUCT_TRAITS_MEMBER(state)
@@ -114,9 +129,10 @@ IPC_STRUCT_TRAITS_BEGIN(content::InputEventAck)
IPC_STRUCT_TRAITS_END()
// Sends an input event to the render widget.
-IPC_MESSAGE_ROUTED2(InputMsg_HandleInputEvent,
+IPC_MESSAGE_ROUTED3(InputMsg_HandleInputEvent,
IPC::WebInputEventPointer /* event */,
- ui::LatencyInfo /* latency_info */)
+ ui::LatencyInfo /* latency_info */,
+ content::InputEventDispatchType)
// Sends the cursor visibility state to the render widget.
IPC_MESSAGE_ROUTED1(InputMsg_CursorVisibilityChange,
@@ -136,10 +152,11 @@ IPC_MESSAGE_ROUTED2(InputMsg_ExtendSelectionAndDelete,
int /* after */)
// This message sends a string being composed with an input method.
-IPC_MESSAGE_ROUTED4(
+IPC_MESSAGE_ROUTED5(
InputMsg_ImeSetComposition,
base::string16, /* text */
std::vector<blink::WebCompositionUnderline>, /* underlines */
+ gfx::Range /* replacement_range */,
int, /* selectiont_start */
int /* selection_end */)
@@ -242,6 +259,8 @@ IPC_MESSAGE_ROUTED3(InputMsg_ActivateNearestFindResult,
// otherwise a race condition can happen.
IPC_MESSAGE_ROUTED0(InputMsg_ImeEventAck)
+// Request from browser to update text input state.
+IPC_MESSAGE_ROUTED0(InputMsg_RequestTextInputStateUpdate)
#endif
IPC_MESSAGE_ROUTED0(InputMsg_SyntheticGestureCompleted)
diff --git a/chromium/content/common/leveldb_wrapper.mojom b/chromium/content/common/leveldb_wrapper.mojom
new file mode 100644
index 00000000000..0035ebc5558
--- /dev/null
+++ b/chromium/content/common/leveldb_wrapper.mojom
@@ -0,0 +1,51 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module content.mojom;
+
+import "components/leveldb/public/interfaces/leveldb.mojom";
+
+// Gives information about changes to a LevelDB database.
+// Note that observer methods are called before the callbacks for the
+// LevelDBWrapper methods are run.
+interface LevelDBObserver {
+ KeyAdded(array<uint8> key, array<uint8> value, string source);
+ KeyChanged(array<uint8> key, array<uint8> new_value, array<uint8> old_value,
+ string source);
+ KeyDeleted(array<uint8> key, array<uint8> old_value, string source);
+ AllDeleted(string source);
+
+ // Since the GetAll call is synchronous, observers need this asynchronously
+ // delivered notification to avoid applying changes to the returned array
+ // that it already contains.
+ GetAllComplete(string source);
+};
+
+struct KeyValue {
+ array<uint8> key;
+ array<uint8> value;
+};
+
+// A wrapper around leveldb that supports giving notifications when values
+// change.
+interface LevelDBWrapper {
+ // Sets the database entry for |key| to |value|. Returns OK on success.
+ Put(array<uint8> key, array<uint8> value, string source) => (bool success);
+
+ // Remove the database entry (if any) for |key|. Returns OK on success, and a
+ // non-OK status on error. It is not an error if |key| did not exist in the
+ // database.
+ Delete(array<uint8> key, string source) => (bool success);
+
+ // Removes all the entries.
+ DeleteAll(string source) => (bool success);
+
+ // Returns the value of the |key|.
+ Get(array<uint8> key) => (bool success, array<uint8> value);
+
+ // Only used with small databases. Returns all key/value pairs.
+ [Sync]
+ GetAll(string source)
+ => (leveldb.DatabaseError status, array<KeyValue> data);
+};
diff --git a/chromium/content/common/mac/attributed_string_coder.h b/chromium/content/common/mac/attributed_string_coder.h
index 971088e856f..6976d4e0a4d 100644
--- a/chromium/content/common/mac/attributed_string_coder.h
+++ b/chromium/content/common/mac/attributed_string_coder.h
@@ -21,6 +21,11 @@ class NSAttributedString;
class NSDictionary;
#endif
+namespace base {
+class Pickle;
+class PickleIterator;
+}
+
namespace mac {
// This class will serialize the font information of an NSAttributedString so
@@ -100,16 +105,20 @@ namespace IPC {
template <>
struct ParamTraits<mac::AttributedStringCoder::EncodedString> {
typedef mac::AttributedStringCoder::EncodedString param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct ParamTraits<mac::AttributedStringCoder::FontAttribute> {
typedef mac::AttributedStringCoder::FontAttribute param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
diff --git a/chromium/content/common/mac/attributed_string_coder.mm b/chromium/content/common/mac/attributed_string_coder.mm
index 85ceeb3655e..f8fa6b05271 100644
--- a/chromium/content/common/mac/attributed_string_coder.mm
+++ b/chromium/content/common/mac/attributed_string_coder.mm
@@ -122,13 +122,14 @@ namespace IPC {
using mac::AttributedStringCoder;
void ParamTraits<AttributedStringCoder::EncodedString>::Write(
- Message* m, const param_type& p) {
+ base::Pickle* m,
+ const param_type& p) {
WriteParam(m, p.string());
WriteParam(m, p.attributes());
}
bool ParamTraits<AttributedStringCoder::EncodedString>::Read(
- const Message* m,
+ const base::Pickle* m,
base::PickleIterator* iter,
param_type* p) {
bool success = true;
@@ -147,13 +148,14 @@ void ParamTraits<AttributedStringCoder::EncodedString>::Log(
}
void ParamTraits<AttributedStringCoder::FontAttribute>::Write(
- Message* m, const param_type& p) {
+ base::Pickle* m,
+ const param_type& p) {
WriteParam(m, p.font_descriptor());
WriteParam(m, p.effective_range());
}
bool ParamTraits<AttributedStringCoder::FontAttribute>::Read(
- const Message* m,
+ const base::Pickle* m,
base::PickleIterator* iter,
param_type* p) {
bool success = true;
diff --git a/chromium/content/common/media/OWNERS b/chromium/content/common/media/OWNERS
index 9d38af2734e..bd15b3e0625 100644
--- a/chromium/content/common/media/OWNERS
+++ b/chromium/content/common/media/OWNERS
@@ -1,9 +1,5 @@
-dalecurtis@chromium.org
-ddorwin@chromium.org
-jrummell@chromium.org
-sandersd@chromium.org
+file://media/OWNERS
tommi@chromium.org
-xhwang@chromium.org
# For security review of IPC message files.
per-file *_messages*.h=set noparent
diff --git a/chromium/content/common/media/audio_messages.h b/chromium/content/common/media/audio_messages.h
index 35e159c4f5e..7731dd6448a 100644
--- a/chromium/content/common/media/audio_messages.h
+++ b/chromium/content/common/media/audio_messages.h
@@ -17,6 +17,7 @@
#include "media/audio/audio_input_ipc.h"
#include "media/audio/audio_output_ipc.h"
#include "media/audio/audio_parameters.h"
+#include "media/gpu/ipc/common/media_param_traits.h"
#include "url/origin.h"
#undef IPC_MESSAGE_EXPORT
diff --git a/chromium/content/common/media/media_param_traits.cc b/chromium/content/common/media/media_param_traits.cc
index 5d5020c9654..07d630b2779 100644
--- a/chromium/content/common/media/media_param_traits.cc
+++ b/chromium/content/common/media/media_param_traits.cc
@@ -12,6 +12,7 @@
#include "media/audio/point.h"
#include "media/base/limits.h"
#include "ui/gfx/ipc/gfx_param_traits.h"
+#include "ui/gfx/ipc/skia/gfx_skia_param_traits.h"
using media::AudioParameters;
using media::ChannelLayout;
@@ -19,7 +20,7 @@ using media::VideoCaptureFormat;
namespace IPC {
-void ParamTraits<AudioParameters>::Write(Message* m,
+void ParamTraits<AudioParameters>::Write(base::Pickle* m,
const AudioParameters& p) {
WriteParam(m, p.format());
WriteParam(m, p.channel_layout());
@@ -31,7 +32,7 @@ void ParamTraits<AudioParameters>::Write(Message* m,
WriteParam(m, p.mic_positions());
}
-bool ParamTraits<AudioParameters>::Read(const Message* m,
+bool ParamTraits<AudioParameters>::Read(const base::Pickle* m,
base::PickleIterator* iter,
AudioParameters* r) {
AudioParameters::Format format;
@@ -63,7 +64,7 @@ void ParamTraits<AudioParameters>::Log(const AudioParameters& p,
l->append(base::StringPrintf("<AudioParameters>"));
}
-void ParamTraits<VideoCaptureFormat>::Write(Message* m,
+void ParamTraits<VideoCaptureFormat>::Write(base::Pickle* m,
const VideoCaptureFormat& p) {
WriteParam(m, p.frame_size);
WriteParam(m, p.frame_rate);
@@ -71,7 +72,7 @@ void ParamTraits<VideoCaptureFormat>::Write(Message* m,
WriteParam(m, p.pixel_storage);
}
-bool ParamTraits<VideoCaptureFormat>::Read(const Message* m,
+bool ParamTraits<VideoCaptureFormat>::Read(const base::Pickle* m,
base::PickleIterator* iter,
VideoCaptureFormat* r) {
if (!ReadParam(m, iter, &r->frame_size) ||
diff --git a/chromium/content/common/media/media_param_traits.h b/chromium/content/common/media/media_param_traits.h
index f035b402c69..70675edba3e 100644
--- a/chromium/content/common/media/media_param_traits.h
+++ b/chromium/content/common/media/media_param_traits.h
@@ -19,16 +19,20 @@ namespace IPC {
template <>
struct CONTENT_EXPORT ParamTraits<media::AudioParameters> {
typedef media::AudioParameters param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct CONTENT_EXPORT ParamTraits<media::VideoCaptureFormat> {
typedef media::VideoCaptureFormat param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
diff --git a/chromium/content/common/media/media_player_delegate_messages.h b/chromium/content/common/media/media_player_delegate_messages.h
new file mode 100644
index 00000000000..98d5d47ee94
--- /dev/null
+++ b/chromium/content/common/media/media_player_delegate_messages.h
@@ -0,0 +1,51 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// IPC messages for interactions between the WebMediaPlayerDelegate in the
+// renderer process and MediaWebContentsObserver in the browser process.
+// Multiply-included message file, hence no include guard.
+
+#include <stdint.h>
+
+#include "base/time/time.h"
+#include "content/common/content_export.h"
+#include "ipc/ipc_message_macros.h"
+
+#undef IPC_MESSAGE_EXPORT
+#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
+#define IPC_MESSAGE_START MediaPlayerDelegateMsgStart
+
+// ----------------------------------------------------------------------------
+// Messages from the browser to the renderer requesting playback state changes.
+// ----------------------------------------------------------------------------
+
+IPC_MESSAGE_ROUTED1(MediaPlayerDelegateMsg_Pause,
+ int /* delegate_id, distinguishes instances */)
+
+IPC_MESSAGE_ROUTED1(MediaPlayerDelegateMsg_Play,
+ int /* delegate_id, distinguishes instances */)
+
+IPC_MESSAGE_ROUTED0(MediaPlayerDelegateMsg_SuspendAllMediaPlayers)
+
+IPC_MESSAGE_ROUTED2(MediaPlayerDelegateMsg_UpdateVolumeMultiplier,
+ int /* delegate_id, distinguishes instances */,
+ double /* multiplier */)
+
+// ----------------------------------------------------------------------------
+// Messages from the renderer notifying the browser of playback state changes.
+// ----------------------------------------------------------------------------
+
+IPC_MESSAGE_ROUTED1(MediaPlayerDelegateHostMsg_OnMediaDestroyed,
+ int /* delegate_id, distinguishes instances */)
+
+IPC_MESSAGE_ROUTED2(MediaPlayerDelegateHostMsg_OnMediaPaused,
+ int /* delegate_id, distinguishes instances */,
+ bool /* reached end of stream */)
+
+IPC_MESSAGE_ROUTED5(MediaPlayerDelegateHostMsg_OnMediaPlaying,
+ int /* delegate_id, distinguishes instances */,
+ bool /* has_video */,
+ bool /* has_audio */,
+ bool /* is_remote */,
+ base::TimeDelta /* duration */)
diff --git a/chromium/content/common/media/media_player_messages_android.h b/chromium/content/common/media/media_player_messages_android.h
index b4e0ba6ebd4..0aab6d85a5d 100644
--- a/chromium/content/common/media/media_player_messages_android.h
+++ b/chromium/content/common/media/media_player_messages_android.h
@@ -9,7 +9,9 @@
#include "content/common/content_export.h"
#include "ipc/ipc_message_macros.h"
#include "media/base/android/demuxer_stream_player_params.h"
+#include "media/base/decrypt_config.h"
#include "media/blink/renderer_media_player_interface.h"
+#include "media/gpu/ipc/common/media_param_traits.h"
#include "ui/gfx/geometry/rect_f.h"
#include "url/gurl.h"
@@ -68,6 +70,8 @@ IPC_STRUCT_BEGIN(MediaPlayerHostMsg_Initialize_Params)
IPC_STRUCT_MEMBER(GURL, first_party_for_cookies)
IPC_STRUCT_MEMBER(GURL, frame_url)
IPC_STRUCT_MEMBER(bool, allow_credentials)
+ IPC_STRUCT_MEMBER(int, delegate_id)
+ IPC_STRUCT_MEMBER(int, media_session_id)
IPC_STRUCT_END()
// Chrome for Android seek message sequence is:
@@ -193,6 +197,10 @@ IPC_MESSAGE_ROUTED2(MediaPlayerMsg_ConnectedToRemoteDevice,
IPC_MESSAGE_ROUTED1(MediaPlayerMsg_DisconnectedFromRemoteDevice,
int /* player_id */)
+// The remote playback device selection has been cancelled.
+IPC_MESSAGE_ROUTED1(MediaPlayerMsg_CancelledRemotePlaybackRequest,
+ int /* player_id */)
+
// The availability of remote devices has changed
IPC_MESSAGE_ROUTED2(MediaPlayerMsg_RemoteRouteAvailabilityChanged,
int /* player_id */,
diff --git a/chromium/content/common/media/media_session_messages_android.h b/chromium/content/common/media/media_session_messages_android.h
index 18a63844d70..266ee273bcf 100644
--- a/chromium/content/common/media/media_session_messages_android.h
+++ b/chromium/content/common/media/media_session_messages_android.h
@@ -7,12 +7,19 @@
#include "content/common/android/gin_java_bridge_errors.h"
#include "content/common/content_export.h"
+#include "content/public/common/media_metadata.h"
#include "ipc/ipc_message_macros.h"
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
#define IPC_MESSAGE_START MediaSessionMsgStart
+IPC_STRUCT_TRAITS_BEGIN(content::MediaMetadata)
+ IPC_STRUCT_TRAITS_MEMBER(title)
+ IPC_STRUCT_TRAITS_MEMBER(artist)
+ IPC_STRUCT_TRAITS_MEMBER(album)
+IPC_STRUCT_TRAITS_END()
+
// Messages for notifying the render process of media session status -------
IPC_MESSAGE_ROUTED2(MediaSessionMsg_DidActivate,
@@ -30,3 +37,7 @@ IPC_MESSAGE_ROUTED2(MediaSessionHostMsg_Activate,
IPC_MESSAGE_ROUTED2(MediaSessionHostMsg_Deactivate,
int /* session_id */,
int /* request_id */)
+
+IPC_MESSAGE_ROUTED2(MediaSessionHostMsg_SetMetadata,
+ int /* request_id*/,
+ content::MediaMetadata /* metadata */)
diff --git a/chromium/content/common/media/media_stream_options.cc b/chromium/content/common/media/media_stream_options.cc
index c942f460986..1b2b1e2750a 100644
--- a/chromium/content/common/media/media_stream_options.cc
+++ b/chromium/content/common/media/media_stream_options.cc
@@ -27,6 +27,8 @@ TrackControls::TrackControls()
TrackControls::TrackControls(bool request)
: requested(request) {}
+TrackControls::TrackControls(const TrackControls& other) = default;
+
TrackControls::~TrackControls() {}
StreamControls::StreamControls()
diff --git a/chromium/content/common/media/media_stream_options.h b/chromium/content/common/media/media_stream_options.h
index 4d61d579221..b815c602cdf 100644
--- a/chromium/content/common/media/media_stream_options.h
+++ b/chromium/content/common/media/media_stream_options.h
@@ -36,6 +36,7 @@ struct CONTENT_EXPORT TrackControls {
public:
TrackControls();
TrackControls(bool request);
+ TrackControls(const TrackControls& other);
~TrackControls();
bool requested;
diff --git a/chromium/content/common/media/surface_view_manager_messages_android.h b/chromium/content/common/media/surface_view_manager_messages_android.h
new file mode 100644
index 00000000000..72426c2539d
--- /dev/null
+++ b/chromium/content/common/media/surface_view_manager_messages_android.h
@@ -0,0 +1,26 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// IPC messages for surface view manager.
+// Multiply-included message file, hence no include guard.
+
+#include "content/common/content_export.h"
+#include "ipc/ipc_message_macros.h"
+#include "ui/gfx/geometry/size.h"
+
+#undef IPC_MESSAGE_EXPORT
+#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
+#define IPC_MESSAGE_START SurfaceViewManagerMsgStart
+
+// Message sent from the renderer to the browser
+
+IPC_MESSAGE_ROUTED1(SurfaceViewManagerHostMsg_CreateFullscreenSurface,
+ gfx::Size /* video_natural_size */)
+IPC_MESSAGE_ROUTED1(SurfaceViewManagerHostMsg_NaturalSizeChanged,
+ gfx::Size /* size */)
+
+// Message sent from the browser to the renderer
+
+IPC_MESSAGE_ROUTED1(SurfaceViewManagerMsg_FullscreenSurfaceCreated,
+ int /* surface_id */)
diff --git a/chromium/content/common/media/video_capture_messages.h b/chromium/content/common/media/video_capture_messages.h
index be1a179bda6..5241898beb2 100644
--- a/chromium/content/common/media/video_capture_messages.h
+++ b/chromium/content/common/media/video_capture_messages.h
@@ -19,7 +19,6 @@ IPC_ENUM_TRAITS_MAX_VALUE(content::VideoCaptureState,
content::VIDEO_CAPTURE_STATE_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(media::ResolutionChangePolicy,
media::RESOLUTION_POLICY_LAST)
-IPC_ENUM_TRAITS_MAX_VALUE(media::VideoPixelFormat, media::PIXEL_FORMAT_MAX)
IPC_ENUM_TRAITS_MAX_VALUE(media::VideoFrame::StorageType,
media::VideoFrame::STORAGE_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(media::VideoPixelStorage, media::PIXEL_STORAGE_MAX)
@@ -108,6 +107,11 @@ IPC_MESSAGE_CONTROL3(VideoCaptureHostMsg_Resume,
media::VideoCaptureSessionId, /* session_id */
media::VideoCaptureParams /* params */)
+// Requests that the video capturer send a frame "soon" (e.g., to resolve
+// picture loss or quality issues).
+IPC_MESSAGE_CONTROL1(VideoCaptureHostMsg_RequestRefreshFrame,
+ int /* device_id */)
+
// Close the video capture specified by |device_id|.
IPC_MESSAGE_CONTROL1(VideoCaptureHostMsg_Stop,
int /* device_id */)
diff --git a/chromium/content/common/memory_benchmark_messages.h b/chromium/content/common/memory_benchmark_messages.h
deleted file mode 100644
index 3955630496a..00000000000
--- a/chromium/content/common/memory_benchmark_messages.h
+++ /dev/null
@@ -1,15 +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.
-
-// IPC messages for memory benchmark.
-// Multiply-included message file, hence no include guard.
-
-#include <string>
-
-#include "ipc/ipc_message_macros.h"
-
-#define IPC_MESSAGE_START MemoryBenchmarkMsgStart
-
-IPC_MESSAGE_CONTROL1(MemoryBenchmarkHostMsg_HeapProfilerDump,
- std::string /* dump reason */)
diff --git a/chromium/content/common/message_router.cc b/chromium/content/common/message_router.cc
deleted file mode 100644
index ac6361e4fe6..00000000000
--- a/chromium/content/common/message_router.cc
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/message_router.h"
-
-#include "ipc/ipc_message.h"
-
-namespace content {
-
-MessageRouter::MessageRouter() {
-}
-
-MessageRouter::~MessageRouter() {
-}
-
-bool MessageRouter::OnControlMessageReceived(const IPC::Message& msg) {
- NOTREACHED() <<
- "should override in subclass if you care about control messages";
- return false;
-}
-
-bool MessageRouter::Send(IPC::Message* msg) {
- NOTREACHED() <<
- "should override in subclass if you care about sending messages";
- return false;
-}
-
-bool MessageRouter::AddRoute(int32_t routing_id, IPC::Listener* listener) {
- if (routes_.Lookup(routing_id)) {
- DLOG(ERROR) << "duplicate routing ID";
- return false;
- }
- routes_.AddWithID(listener, routing_id);
- return true;
-}
-
-void MessageRouter::RemoveRoute(int32_t routing_id) {
- routes_.Remove(routing_id);
-}
-
-bool MessageRouter::OnMessageReceived(const IPC::Message& msg) {
- if (msg.routing_id() == MSG_ROUTING_CONTROL)
- return OnControlMessageReceived(msg);
-
- return RouteMessage(msg);
-}
-
-bool MessageRouter::RouteMessage(const IPC::Message& msg) {
- IPC::Listener* listener = routes_.Lookup(msg.routing_id());
- if (!listener)
- return false;
-
- return listener->OnMessageReceived(msg);
-}
-
-} // namespace content
diff --git a/chromium/content/common/message_router.h b/chromium/content/common/message_router.h
deleted file mode 100644
index fea73252b35..00000000000
--- a/chromium/content/common/message_router.h
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_MESSAGE_ROUTER_H_
-#define CONTENT_COMMON_MESSAGE_ROUTER_H_
-
-#include <stdint.h>
-
-#include "base/id_map.h"
-#include "base/macros.h"
-#include "content/common/content_export.h"
-#include "ipc/ipc_listener.h"
-#include "ipc/ipc_sender.h"
-
-// The MessageRouter handles all incoming messages sent to it by routing them
-// to the correct listener. Routing is based on the Message's routing ID.
-// Since routing IDs are typically assigned asynchronously by the browser
-// process, the MessageRouter has the notion of pending IDs for listeners that
-// have not yet been assigned a routing ID.
-//
-// When a message arrives, the routing ID is used to index the set of routes to
-// find a listener. If a listener is found, then the message is passed to it.
-// Otherwise, the message is ignored if its routing ID is not equal to
-// MSG_ROUTING_CONTROL.
-//
-// The MessageRouter supports the IPC::Sender interface for outgoing messages,
-// but does not define a meaningful implementation of it. The subclass of
-// MessageRouter is intended to provide that if appropriate.
-//
-// The MessageRouter can be used as a concrete class provided its Send method
-// is not called and it does not receive any control messages.
-
-namespace content {
-
-class CONTENT_EXPORT MessageRouter : public IPC::Listener, public IPC::Sender {
- public:
- MessageRouter();
- ~MessageRouter() override;
-
- // Implemented by subclasses to handle control messages
- virtual bool OnControlMessageReceived(const IPC::Message& msg);
-
- // IPC::Listener implementation:
- bool OnMessageReceived(const IPC::Message& msg) override;
-
- // Like OnMessageReceived, except it only handles routed messages. Returns
- // true if the message was dispatched, or false if there was no listener for
- // that route id.
- virtual bool RouteMessage(const IPC::Message& msg);
-
- // IPC::Sender implementation:
- bool Send(IPC::Message* msg) override;
-
- // Called to add a listener for a particular message routing ID.
- // Returns true if succeeded.
- bool AddRoute(int32_t routing_id, IPC::Listener* listener);
-
- // Called to remove a listener for a particular message routing ID.
- void RemoveRoute(int32_t routing_id);
-
- private:
- // A list of all listeners with assigned routing IDs.
- IDMap<IPC::Listener> routes_;
-
- DISALLOW_COPY_AND_ASSIGN(MessageRouter);
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_MESSAGE_ROUTER_H_
diff --git a/chromium/content/common/mojo/DEPS b/chromium/content/common/mojo/DEPS
index c70d064e525..0f2f39efd65 100644
--- a/chromium/content/common/mojo/DEPS
+++ b/chromium/content/common/mojo/DEPS
@@ -1,6 +1,5 @@
include_rules = [
- "+mojo/shell/public/cpp",
- "+mojo/shell/public/interfaces",
"+mojo/converters/network",
- "+mojo/runner/child",
+ "+mojo/edk/embedder",
+ "+mojo/shell",
]
diff --git a/chromium/content/common/mojo/channel_init.cc b/chromium/content/common/mojo/channel_init.cc
index 967fb10be60..c8172ab2cd3 100644
--- a/chromium/content/common/mojo/channel_init.cc
+++ b/chromium/content/common/mojo/channel_init.cc
@@ -8,55 +8,25 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/command_line.h"
#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
+#include "base/task_runner.h"
#include "base/thread_task_runner_handle.h"
-#include "third_party/mojo/src/mojo/edk/embedder/embedder.h"
+#include "mojo/edk/embedder/embedder.h"
namespace content {
-ChannelInit::ChannelInit() : channel_info_(nullptr), weak_factory_(this) {}
+ChannelInit::ChannelInit() {}
-ChannelInit::~ChannelInit() {
- if (channel_info_)
- mojo::embedder::DestroyChannel(channel_info_,
- base::Bind(&base::DoNothing), nullptr);
-}
+ChannelInit::~ChannelInit() {}
mojo::ScopedMessagePipeHandle ChannelInit::Init(
base::PlatformFile file,
scoped_refptr<base::TaskRunner> io_thread_task_runner) {
- scoped_ptr<IPC::ScopedIPCSupport> ipc_support(
- new IPC::ScopedIPCSupport(io_thread_task_runner));
- mojo::ScopedMessagePipeHandle message_pipe = mojo::embedder::CreateChannel(
- mojo::embedder::ScopedPlatformHandle(
- mojo::embedder::PlatformHandle(file)),
- base::Bind(&ChannelInit::OnCreatedChannel, weak_factory_.GetWeakPtr(),
- base::Passed(&ipc_support)),
- base::ThreadTaskRunnerHandle::Get());
- return message_pipe;
-}
-
-void ChannelInit::WillDestroySoon() {
- if (channel_info_)
- mojo::embedder::WillDestroyChannelSoon(channel_info_);
-}
-
-// static
-void ChannelInit::OnCreatedChannel(
- base::WeakPtr<ChannelInit> self,
- scoped_ptr<IPC::ScopedIPCSupport> ipc_support,
- mojo::embedder::ChannelInfo* channel) {
- // If |self| was already destroyed, shut the channel down.
- if (!self) {
- mojo::embedder::DestroyChannel(channel,
- base::Bind(&base::DoNothing), nullptr);
- return;
- }
-
- DCHECK(!self->channel_info_);
- self->channel_info_ = channel;
- self->ipc_support_ = std::move(ipc_support);
+ return mojo::edk::CreateMessagePipe(
+ mojo::edk::ScopedPlatformHandle(mojo::edk::PlatformHandle(file)));
}
} // namespace content
diff --git a/chromium/content/common/mojo/channel_init.h b/chromium/content/common/mojo/channel_init.h
index acdc5752c95..6b9daae2dd0 100644
--- a/chromium/content/common/mojo/channel_init.h
+++ b/chromium/content/common/mojo/channel_init.h
@@ -8,11 +8,8 @@
#include "base/files/file.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
-#include "ipc/mojo/scoped_ipc_support.h"
#include "mojo/public/cpp/system/message_pipe.h"
-#include "third_party/mojo/src/mojo/edk/embedder/channel_info_forward.h"
namespace base {
class TaskRunner;
@@ -22,35 +19,20 @@ namespace content {
// ChannelInit handles creation and destruction of the Mojo channel. It is not
// thread-safe, but may be used on any single thread with a MessageLoop.
+//
+// TODO(rockot): Get rid of this class ASAP (i.e. once the patch which includes
+// this TODO has stuck for a bit) since it's no longer necessary.
class CONTENT_EXPORT ChannelInit {
public:
ChannelInit();
~ChannelInit();
- // Initializes the channel. This takes ownership of |file|. Returns the
- // primordial MessagePipe for the channel.
+ // Initializes the channel. This takes ownership of |file|.
mojo::ScopedMessagePipeHandle Init(
base::PlatformFile file,
scoped_refptr<base::TaskRunner> io_thread_task_runner);
- // Notifies the channel that we (hence it) will soon be destroyed.
- void WillDestroySoon();
-
private:
- // Invoked on the thread on which this object lives once the channel has been
- // established. This is a static method that takes a weak pointer to self,
- // since we want to destroy the channel if we were destroyed first.
- static void OnCreatedChannel(
- base::WeakPtr<ChannelInit> self,
- scoped_ptr<IPC::ScopedIPCSupport> ipc_support,
- mojo::embedder::ChannelInfo* channel);
-
- // If non-null the channel has been established.
- mojo::embedder::ChannelInfo* channel_info_;
-
- scoped_ptr<IPC::ScopedIPCSupport> ipc_support_;
- base::WeakPtrFactory<ChannelInit> weak_factory_;
-
DISALLOW_COPY_AND_ASSIGN(ChannelInit);
};
diff --git a/chromium/content/common/mojo/current_thread_loader.cc b/chromium/content/common/mojo/current_thread_loader.cc
new file mode 100644
index 00000000000..eb64b150863
--- /dev/null
+++ b/chromium/content/common/mojo/current_thread_loader.cc
@@ -0,0 +1,25 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/mojo/current_thread_loader.h"
+
+namespace content {
+
+CurrentThreadLoader::CurrentThreadLoader(const ApplicationFactory& factory)
+ : factory_(factory) {}
+
+CurrentThreadLoader::~CurrentThreadLoader() {}
+
+void CurrentThreadLoader::Load(const std::string& name,
+ mojo::shell::mojom::ShellClientRequest request) {
+ if (!shell_client_) {
+ shell_client_ = factory_.Run();
+ factory_ = ApplicationFactory();
+ }
+
+ connections_.push_back(make_scoped_ptr(
+ new mojo::ShellConnection(shell_client_.get(), std::move(request))));
+}
+
+} // namespace content
diff --git a/chromium/content/common/mojo/current_thread_loader.h b/chromium/content/common/mojo/current_thread_loader.h
new file mode 100644
index 00000000000..e5e6e35de2c
--- /dev/null
+++ b/chromium/content/common/mojo/current_thread_loader.h
@@ -0,0 +1,46 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_MOJO_CURRENT_THREAD_LOADER_H_
+#define CONTENT_COMMON_MOJO_CURRENT_THREAD_LOADER_H_
+
+#include <vector>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "mojo/shell/loader.h"
+#include "mojo/shell/public/cpp/shell_client.h"
+#include "mojo/shell/public/cpp/shell_connection.h"
+
+namespace content {
+
+// A Loader which loads a single type of app from a mojo::ShellClientFactory on
+// the current thread.
+class CurrentThreadLoader : public mojo::shell::Loader {
+ public:
+ using ApplicationFactory = base::Callback<scoped_ptr<mojo::ShellClient>()>;
+
+ explicit CurrentThreadLoader(const ApplicationFactory& factory);
+ ~CurrentThreadLoader() override;
+
+ // mojo::shell::Loader:
+ void Load(const std::string& name,
+ mojo::shell::mojom::ShellClientRequest request) override;
+
+ private:
+ // The factory used to create new instances of the application delegate. This
+ // is called exactly once since all connections share a single client.
+ ApplicationFactory factory_;
+
+ // Our shared shell client, passed to each connection.
+ scoped_ptr<mojo::ShellClient> shell_client_;
+
+ std::vector<scoped_ptr<mojo::ShellConnection>> connections_;
+
+ DISALLOW_COPY_AND_ASSIGN(CurrentThreadLoader);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_MOJO_CURRENT_THREAD_LOADER_H_
diff --git a/chromium/content/common/mojo/mojo_messages.h b/chromium/content/common/mojo/mojo_messages.h
index 4ed553641ee..1232902be37 100644
--- a/chromium/content/common/mojo/mojo_messages.h
+++ b/chromium/content/common/mojo/mojo_messages.h
@@ -20,8 +20,3 @@
// Mojo IPC is bootstrapped over Chrome IPC via this message.
IPC_MESSAGE_CONTROL1(MojoMsg_Activate,
IPC::PlatformFileForTransit /* handle */)
-
-// Mojo IPC to an external shell is bootstrapped over Chrome IPC via this
-// message.
-IPC_MESSAGE_CONTROL1(MojoMsg_BindExternalMojoShellHandle,
- IPC::PlatformFileForTransit /* handle */)
diff --git a/chromium/content/common/mojo/mojo_shell_connection_impl.cc b/chromium/content/common/mojo/mojo_shell_connection_impl.cc
index 34bf88a4766..5214096007a 100644
--- a/chromium/content/common/mojo/mojo_shell_connection_impl.cc
+++ b/chromium/content/common/mojo/mojo_shell_connection_impl.cc
@@ -8,15 +8,19 @@
#include "base/command_line.h"
#include "base/lazy_instance.h"
+#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/threading/thread_local.h"
-#include "mojo/converters/network/network_type_converters.h"
-#include "mojo/runner/child/runner_connection.h"
-#include "mojo/shell/public/cpp/application_delegate.h"
-#include "mojo/shell/public/cpp/application_impl.h"
+#include "content/public/common/content_switches.h"
+#include "mojo/edk/embedder/embedder.h"
+#include "mojo/edk/embedder/platform_channel_pair.h"
+#include "mojo/shell/public/cpp/shell_client.h"
+#include "mojo/shell/public/cpp/shell_connection.h"
+#include "mojo/shell/runner/common/client_util.h"
namespace content {
namespace {
+
using MojoShellConnectionPtr =
base::ThreadLocalPointer<MojoShellConnectionImpl>;
@@ -24,69 +28,115 @@ using MojoShellConnectionPtr =
base::LazyInstance<MojoShellConnectionPtr>::Leaky lazy_tls_ptr =
LAZY_INSTANCE_INITIALIZER;
+MojoShellConnection::Factory* mojo_shell_connection_factory = nullptr;
+
} // namespace
bool IsRunningInMojoShell() {
- return base::CommandLine::ForCurrentProcess()->HasSwitch(
- "mojo-platform-channel-handle");
+ return mojo_shell_connection_factory ||
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ mojo::edk::PlatformChannelPair::kMojoPlatformChannelHandleSwitch);
+}
+
+bool ShouldWaitForShell() {
+ return mojo_shell_connection_factory ||
+ (IsRunningInMojoShell() &&
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kWaitForMojoShell));
+}
+
+// static
+bool MojoShellConnectionImpl::CreateUsingFactory() {
+ if (mojo_shell_connection_factory) {
+ DCHECK(!lazy_tls_ptr.Pointer()->Get());
+ mojo_shell_connection_factory->Run();
+ DCHECK(lazy_tls_ptr.Pointer()->Get());
+ return true;
+ }
+ return false;
}
// static
void MojoShellConnectionImpl::Create() {
DCHECK(!lazy_tls_ptr.Pointer()->Get());
- MojoShellConnectionImpl* connection = new MojoShellConnectionImpl;
+ MojoShellConnectionImpl* connection =
+ new MojoShellConnectionImpl(true /* external */);
lazy_tls_ptr.Pointer()->Set(connection);
}
// static
+void MojoShellConnection::Create(mojo::shell::mojom::ShellClientRequest request,
+ bool is_external) {
+ DCHECK(!lazy_tls_ptr.Pointer()->Get());
+ MojoShellConnectionImpl* connection =
+ new MojoShellConnectionImpl(is_external);
+ lazy_tls_ptr.Pointer()->Set(connection);
+ connection->shell_connection_.reset(
+ new mojo::ShellConnection(connection, std::move(request)));
+ if (is_external)
+ connection->WaitForShellIfNecessary();
+}
+
+// static
+void MojoShellConnection::SetFactoryForTest(Factory* factory) {
+ DCHECK(!lazy_tls_ptr.Pointer()->Get());
+ mojo_shell_connection_factory = factory;
+}
+
+// static
MojoShellConnectionImpl* MojoShellConnectionImpl::Get() {
+ // Assume that if a mojo_shell_connection_factory was set that it did not
+ // create a MojoShellConnectionImpl.
return static_cast<MojoShellConnectionImpl*>(MojoShellConnection::Get());
}
-void MojoShellConnectionImpl::BindToCommandLinePlatformChannel() {
- DCHECK(IsRunningInMojoShell());
- if (initialized_)
- return;
- WaitForShell(mojo::ScopedMessagePipeHandle());
+void MojoShellConnectionImpl::BindToRequestFromCommandLine() {
+ DCHECK(!shell_connection_);
+ shell_connection_.reset(new mojo::ShellConnection(
+ this, mojo::shell::GetShellClientRequestFromCommandLine()));
+ WaitForShellIfNecessary();
}
-void MojoShellConnectionImpl::BindToMessagePipe(
- mojo::ScopedMessagePipeHandle handle) {
- if (initialized_)
- return;
- WaitForShell(std::move(handle));
-}
+MojoShellConnectionImpl::MojoShellConnectionImpl(bool external)
+ : external_(external) {}
-MojoShellConnectionImpl::MojoShellConnectionImpl() : initialized_(false) {}
MojoShellConnectionImpl::~MojoShellConnectionImpl() {
STLDeleteElements(&listeners_);
}
-void MojoShellConnectionImpl::WaitForShell(
- mojo::ScopedMessagePipeHandle handle) {
- mojo::InterfaceRequest<mojo::Application> application_request;
- runner_connection_.reset(mojo::runner::RunnerConnection::ConnectToRunner(
- &application_request, std::move(handle)));
- application_impl_.reset(
- new mojo::ApplicationImpl(this, std::move(application_request)));
- application_impl_->WaitForInitialize();
+void MojoShellConnectionImpl::WaitForShellIfNecessary() {
+ // TODO(rockot): Remove this. http://crbug.com/594852.
+ if (ShouldWaitForShell()) {
+ base::RunLoop wait_loop;
+ shell_connection_->set_initialize_handler(wait_loop.QuitClosure());
+ wait_loop.Run();
+ }
}
-void MojoShellConnectionImpl::Initialize(mojo::ApplicationImpl* application) {
- initialized_ = true;
+void MojoShellConnectionImpl::Initialize(mojo::Connector* connector,
+ const mojo::Identity& identity,
+ uint32_t id) {
}
-bool MojoShellConnectionImpl::ConfigureIncomingConnection(
- mojo::ApplicationConnection* connection) {
+bool MojoShellConnectionImpl::AcceptConnection(mojo::Connection* connection) {
bool found = false;
for (auto listener : listeners_)
- found |= listener->ConfigureIncomingConnection(connection);
+ found |= listener->AcceptConnection(connection);
return found;
}
-mojo::ApplicationImpl* MojoShellConnectionImpl::GetApplication() {
- DCHECK(initialized_);
- return application_impl_.get();
+mojo::Connector* MojoShellConnectionImpl::GetConnector() {
+ DCHECK(shell_connection_);
+ return shell_connection_->connector();
+}
+
+bool MojoShellConnectionImpl::UsingExternalShell() const {
+ return external_;
+}
+
+void MojoShellConnectionImpl::SetConnectionLostClosure(
+ const base::Closure& closure) {
+ shell_connection_->set_connection_lost_closure(closure);
}
void MojoShellConnectionImpl::AddListener(Listener* listener) {
diff --git a/chromium/content/common/mojo/mojo_shell_connection_impl.h b/chromium/content/common/mojo/mojo_shell_connection_impl.h
index 3f7ecfa05fc..3f1a188eb55 100644
--- a/chromium/content/common/mojo/mojo_shell_connection_impl.h
+++ b/chromium/content/common/mojo/mojo_shell_connection_impl.h
@@ -11,13 +11,9 @@
#include "base/memory/scoped_ptr.h"
#include "content/public/common/mojo_shell_connection.h"
#include "mojo/public/cpp/system/message_pipe.h"
-#include "mojo/shell/public/cpp/application_delegate.h"
-
-namespace mojo {
-namespace runner {
-class RunnerConnection;
-}
-}
+#include "mojo/shell/public/cpp/shell.h"
+#include "mojo/shell/public/cpp/shell_client.h"
+#include "mojo/shell/public/cpp/shell_connection.h"
namespace content {
@@ -25,8 +21,12 @@ namespace content {
bool IsRunningInMojoShell();
class MojoShellConnectionImpl : public MojoShellConnection,
- public mojo::ApplicationDelegate {
+ public mojo::ShellClient {
public:
+ // Creates the MojoShellConnection using MojoShellConnection::Factory. Returns
+ // true if a factory was set and the connection was created, false otherwise.
+ static bool CreateUsingFactory();
+
// Creates an instance of this class and stuffs it in TLS on the calling
// thread. Retrieve it using MojoShellConnection::Get().
static void Create();
@@ -36,37 +36,33 @@ class MojoShellConnectionImpl : public MojoShellConnection,
// Mojo shell).
static MojoShellConnectionImpl* Get();
- // Blocks the calling thread until calling GetApplication() will return an
- // Initialized() application with a bound ShellPtr. This call is a no-op
- // if the connection has already been initialized.
- void BindToCommandLinePlatformChannel();
-
- // Same as BindToCommandLinePlatformChannel(), but receives a |handle| instead
- // of looking for one on the command line.
- void BindToMessagePipe(mojo::ScopedMessagePipeHandle handle);
+ // Binds the shell connection to a ShellClientFactory request pipe from the
+ // command line. This must only be called once.
+ void BindToRequestFromCommandLine();
private:
- MojoShellConnectionImpl();
+ friend class MojoShellConnection;
+
+ explicit MojoShellConnectionImpl(bool external);
~MojoShellConnectionImpl() override;
- // mojo::ApplicationDelegate:
- void Initialize(mojo::ApplicationImpl* application) override;
- bool ConfigureIncomingConnection(
- mojo::ApplicationConnection* connection) override;
+ void WaitForShellIfNecessary();
+
+ // mojo::ShellClient:
+ void Initialize(mojo::Connector* connector,
+ const mojo::Identity& identity,
+ uint32_t id) override;
+ bool AcceptConnection(mojo::Connection* connection) override;
// MojoShellConnection:
- mojo::ApplicationImpl* GetApplication() override;
+ mojo::Connector* GetConnector() override;
+ bool UsingExternalShell() const override;
+ void SetConnectionLostClosure(const base::Closure& closure) override;
void AddListener(Listener* listener) override;
void RemoveListener(Listener* listener) override;
- // Blocks the calling thread until a connection to the spawning shell is
- // established, an Application request from it is bound, and the Initialize()
- // method on that application is called.
- void WaitForShell(mojo::ScopedMessagePipeHandle handle);
-
- bool initialized_;
- scoped_ptr<mojo::runner::RunnerConnection> runner_connection_;
- scoped_ptr<mojo::ApplicationImpl> application_impl_;
+ const bool external_;
+ scoped_ptr<mojo::ShellConnection> shell_connection_;
std::vector<Listener*> listeners_;
DISALLOW_COPY_AND_ASSIGN(MojoShellConnectionImpl);
diff --git a/chromium/content/common/mojo/service_registry_impl.cc b/chromium/content/common/mojo/service_registry_impl.cc
index a55864f92ea..b26c60990be 100644
--- a/chromium/content/common/mojo/service_registry_impl.cc
+++ b/chromium/content/common/mojo/service_registry_impl.cc
@@ -21,27 +21,26 @@ ServiceRegistryImpl::~ServiceRegistryImpl() {
}
void ServiceRegistryImpl::Bind(
- mojo::InterfaceRequest<mojo::ServiceProvider> request) {
+ mojo::shell::mojom::InterfaceProviderRequest request) {
binding_.Bind(std::move(request));
binding_.set_connection_error_handler(base::Bind(
&ServiceRegistryImpl::OnConnectionError, base::Unretained(this)));
}
void ServiceRegistryImpl::BindRemoteServiceProvider(
- mojo::ServiceProviderPtr service_provider) {
+ mojo::shell::mojom::InterfaceProviderPtr service_provider) {
CHECK(!remote_provider_);
remote_provider_ = std::move(service_provider);
while (!pending_connects_.empty()) {
- remote_provider_->ConnectToService(
+ remote_provider_->GetInterface(
mojo::String::From(pending_connects_.front().first),
mojo::ScopedMessagePipeHandle(pending_connects_.front().second));
pending_connects_.pop();
}
}
-void ServiceRegistryImpl::AddService(
- const std::string& service_name,
- const base::Callback<void(mojo::ScopedMessagePipeHandle)> service_factory) {
+void ServiceRegistryImpl::AddService(const std::string& service_name,
+ const ServiceFactory service_factory) {
service_factories_[service_name] = service_factory;
}
@@ -52,15 +51,31 @@ void ServiceRegistryImpl::RemoveService(const std::string& service_name) {
void ServiceRegistryImpl::ConnectToRemoteService(
const base::StringPiece& service_name,
mojo::ScopedMessagePipeHandle handle) {
+ auto override_it = service_overrides_.find(service_name.as_string());
+ if (override_it != service_overrides_.end()) {
+ override_it->second.Run(std::move(handle));
+ return;
+ }
+
if (!remote_provider_) {
pending_connects_.push(
std::make_pair(service_name.as_string(), handle.release()));
return;
}
- remote_provider_->ConnectToService(
+ remote_provider_->GetInterface(
mojo::String::From(service_name.as_string()), std::move(handle));
}
+void ServiceRegistryImpl::AddServiceOverrideForTesting(
+ const std::string& service_name,
+ const ServiceFactory& factory) {
+ service_overrides_[service_name] = factory;
+}
+
+void ServiceRegistryImpl::ClearServiceOverridesForTesting() {
+ service_overrides_.clear();
+}
+
bool ServiceRegistryImpl::IsBound() const {
return binding_.is_bound();
}
@@ -69,12 +84,10 @@ base::WeakPtr<ServiceRegistry> ServiceRegistryImpl::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
-void ServiceRegistryImpl::ConnectToService(
+void ServiceRegistryImpl::GetInterface(
const mojo::String& name,
mojo::ScopedMessagePipeHandle client_handle) {
- std::map<std::string,
- base::Callback<void(mojo::ScopedMessagePipeHandle)> >::iterator it =
- service_factories_.find(name);
+ auto it = service_factories_.find(name);
if (it == service_factories_.end())
return;
diff --git a/chromium/content/common/mojo/service_registry_impl.h b/chromium/content/common/mojo/service_registry_impl.h
index 5e4fd73fd91..807924cb1e3 100644
--- a/chromium/content/common/mojo/service_registry_impl.h
+++ b/chromium/content/common/mojo/service_registry_impl.h
@@ -16,53 +16,60 @@
#include "content/public/common/service_registry.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/system/core.h"
-#include "mojo/shell/public/interfaces/service_provider.mojom.h"
+#include "mojo/shell/public/interfaces/interface_provider.mojom.h"
namespace content {
class CONTENT_EXPORT ServiceRegistryImpl
: public ServiceRegistry,
- public NON_EXPORTED_BASE(mojo::ServiceProvider) {
+ public NON_EXPORTED_BASE(mojo::shell::mojom::InterfaceProvider) {
public:
+ using ServiceFactory = base::Callback<void(mojo::ScopedMessagePipeHandle)>;
+
ServiceRegistryImpl();
~ServiceRegistryImpl() override;
// Binds this ServiceProvider implementation to a message pipe endpoint.
- void Bind(mojo::InterfaceRequest<mojo::ServiceProvider> request);
+ void Bind(mojo::shell::mojom::InterfaceProviderRequest request);
// Binds to a remote ServiceProvider. This will expose added services to the
// remote ServiceProvider with the corresponding handle and enable
// ConnectToRemoteService to provide access to services exposed by the remote
// ServiceProvider.
- void BindRemoteServiceProvider(mojo::ServiceProviderPtr service_provider);
+ void BindRemoteServiceProvider(
+ mojo::shell::mojom::InterfaceProviderPtr service_provider);
// ServiceRegistry overrides.
void AddService(const std::string& service_name,
- const base::Callback<void(mojo::ScopedMessagePipeHandle)>
- service_factory) override;
+ const ServiceFactory service_factory) override;
void RemoveService(const std::string& service_name) override;
void ConnectToRemoteService(const base::StringPiece& service_name,
mojo::ScopedMessagePipeHandle handle) override;
+ void AddServiceOverrideForTesting(
+ const std::string& service_name,
+ const ServiceFactory& service_factory) override;
+ void ClearServiceOverridesForTesting() override;
bool IsBound() const;
base::WeakPtr<ServiceRegistry> GetWeakPtr();
private:
- // mojo::ServiceProvider overrides.
- void ConnectToService(const mojo::String& name,
- mojo::ScopedMessagePipeHandle client_handle) override;
+ // mojo::InterfaceProvider overrides.
+ void GetInterface(const mojo::String& name,
+ mojo::ScopedMessagePipeHandle client_handle) override;
void OnConnectionError();
- mojo::Binding<mojo::ServiceProvider> binding_;
- mojo::ServiceProviderPtr remote_provider_;
+ mojo::Binding<mojo::shell::mojom::InterfaceProvider> binding_;
+ mojo::shell::mojom::InterfaceProviderPtr remote_provider_;
- std::map<std::string, base::Callback<void(mojo::ScopedMessagePipeHandle)> >
- service_factories_;
+ std::map<std::string, ServiceFactory> service_factories_;
std::queue<std::pair<std::string, mojo::MessagePipeHandle> >
pending_connects_;
+ std::map<std::string, ServiceFactory> service_overrides_;
+
base::WeakPtrFactory<ServiceRegistry> weak_factory_;
};
diff --git a/chromium/content/common/mojo/static_loader.cc b/chromium/content/common/mojo/static_loader.cc
new file mode 100644
index 00000000000..107c9135456
--- /dev/null
+++ b/chromium/content/common/mojo/static_loader.cc
@@ -0,0 +1,93 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/mojo/static_loader.h"
+
+#include <utility>
+
+#include "base/bind.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/task_runner.h"
+#include "base/thread_task_runner_handle.h"
+#include "base/threading/simple_thread.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "mojo/shell/public/cpp/application_runner.h"
+#include "mojo/shell/public/cpp/shell_client.h"
+#include "mojo/shell/public/interfaces/shell_client.mojom.h"
+
+namespace content {
+
+namespace {
+
+class RunnerThread : public base::SimpleThread {
+ public:
+ RunnerThread(const std::string& name,
+ mojo::shell::mojom::ShellClientRequest request,
+ scoped_refptr<base::TaskRunner> exit_task_runner,
+ const base::Closure& exit_callback,
+ const StaticLoader::ApplicationFactory& factory)
+ : base::SimpleThread("Mojo Application: " + name),
+ request_(std::move(request)),
+ exit_task_runner_(exit_task_runner),
+ exit_callback_(exit_callback),
+ factory_(factory) {}
+
+ void Run() override {
+ scoped_ptr<mojo::ApplicationRunner> runner(
+ new mojo::ApplicationRunner(factory_.Run().release()));
+ runner->Run(request_.PassMessagePipe().release().value(),
+ false /* init_base */);
+ exit_task_runner_->PostTask(FROM_HERE, exit_callback_);
+ }
+
+ private:
+ mojo::shell::mojom::ShellClientRequest request_;
+ scoped_refptr<base::TaskRunner> exit_task_runner_;
+ base::Closure exit_callback_;
+ StaticLoader::ApplicationFactory factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(RunnerThread);
+};
+
+} // namespace
+
+StaticLoader::StaticLoader(const ApplicationFactory& factory)
+ : StaticLoader(factory, base::Closure()) {
+}
+
+StaticLoader::StaticLoader(const ApplicationFactory& factory,
+ const base::Closure& quit_callback)
+ : factory_(factory), quit_callback_(quit_callback), weak_factory_(this) {
+}
+
+StaticLoader::~StaticLoader() {
+ if (thread_)
+ StopAppThread();
+}
+
+void StaticLoader::Load(const std::string& name,
+ mojo::shell::mojom::ShellClientRequest request) {
+ if (thread_)
+ return;
+
+ // If the application's thread quits on its own before this loader dies, we
+ // reset the Thread object, allowing future Load requests to be fulfilled
+ // with a new app instance.
+ auto exit_callback = base::Bind(&StaticLoader::StopAppThread,
+ weak_factory_.GetWeakPtr());
+ thread_.reset(new RunnerThread(name, std::move(request),
+ base::ThreadTaskRunnerHandle::Get(),
+ exit_callback, factory_));
+ thread_->Start();
+}
+
+void StaticLoader::StopAppThread() {
+ thread_->Join();
+ thread_.reset();
+ if (!quit_callback_.is_null())
+ quit_callback_.Run();
+}
+
+} // namespace content
diff --git a/chromium/content/common/mojo/static_loader.h b/chromium/content/common/mojo/static_loader.h
new file mode 100644
index 00000000000..318366d805a
--- /dev/null
+++ b/chromium/content/common/mojo/static_loader.h
@@ -0,0 +1,66 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_MOJO_STATIC_APPLICATION_LOADER_H_
+#define CONTENT_COMMON_MOJO_STATIC_APPLICATION_LOADER_H_
+
+#include <list>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "mojo/shell/loader.h"
+
+namespace base {
+class SimpleThread;
+}
+
+namespace mojo {
+class ShellClient;
+}
+
+namespace content {
+
+// An Loader which loads a single type of app from a given
+// mojo::ShellClientFactory. A Load() request is fulfilled by creating an
+// instance of the app on a new thread. Only one instance of the app will run at
+// a time. Any Load requests received while the app is running will be dropped.
+class StaticLoader : public mojo::shell::Loader {
+ public:
+ using ApplicationFactory = base::Callback<scoped_ptr<mojo::ShellClient>()>;
+
+ // Constructs a static loader for |factory|.
+ explicit StaticLoader(const ApplicationFactory& factory);
+
+ // Constructs a static loader for |factory| with a closure that will be called
+ // when the loaded application quits.
+ StaticLoader(const ApplicationFactory& factory,
+ const base::Closure& quit_callback);
+
+ ~StaticLoader() override;
+
+ // mojo::shell::Loader:
+ void Load(const std::string& name,
+ mojo::shell::mojom::ShellClientRequest request) override;
+
+ private:
+ void StopAppThread();
+
+ // The factory used t create new instances of the application delegate.
+ ApplicationFactory factory_;
+
+ // If not null, this is run when the loaded application quits.
+ base::Closure quit_callback_;
+
+ // Thread for the application if currently running.
+ scoped_ptr<base::SimpleThread> thread_;
+
+ base::WeakPtrFactory<StaticLoader> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(StaticLoader);
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_MOJO_STATIC_APPLICATION_LOADER_H_
diff --git a/chromium/content/common/navigation_params.cc b/chromium/content/common/navigation_params.cc
index da6f5901f47..f09cccfebbf 100644
--- a/chromium/content/common/navigation_params.cc
+++ b/chromium/content/common/navigation_params.cc
@@ -7,6 +7,7 @@
#include "build/build_config.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/common/browser_side_navigation_policy.h"
+#include "content/public/common/url_constants.h"
namespace content {
@@ -14,12 +15,13 @@ namespace content {
bool ShouldMakeNetworkRequestForURL(const GURL& url) {
CHECK(IsBrowserSideNavigationEnabled());
- // Data URLs, Javascript URLs and about:blank should not send a request to the
- // network stack.
+ // Data URLs, Javascript URLs, about:blank, srcdoc should not send a request
+ // to the network stack.
// TODO(clamy): same document navigations should not send requests to the
// network stack. Neither should pushState/popState.
return !url.SchemeIs(url::kDataScheme) && url != GURL(url::kAboutBlankURL) &&
- !url.SchemeIs(url::kJavaScriptScheme);
+ !url.SchemeIs(url::kJavaScriptScheme) && !url.is_empty() &&
+ url != GURL(content::kAboutSrcDocURL);
}
CommonNavigationParams::CommonNavigationParams()
@@ -29,8 +31,8 @@ CommonNavigationParams::CommonNavigationParams()
should_replace_current_entry(false),
report_type(FrameMsg_UILoadMetricsReportType::NO_REPORT),
lofi_state(LOFI_UNSPECIFIED),
- navigation_start(base::TimeTicks::Now()) {
-}
+ navigation_start(base::TimeTicks::Now()),
+ method("GET") {}
CommonNavigationParams::CommonNavigationParams(
const GURL& url,
@@ -44,7 +46,8 @@ CommonNavigationParams::CommonNavigationParams(
const GURL& base_url_for_data_url,
const GURL& history_url_for_data_url,
LoFiState lofi_state,
- const base::TimeTicks& navigation_start)
+ const base::TimeTicks& navigation_start,
+ std::string method)
: url(url),
referrer(referrer),
transition(transition),
@@ -56,8 +59,11 @@ CommonNavigationParams::CommonNavigationParams(
base_url_for_data_url(base_url_for_data_url),
history_url_for_data_url(history_url_for_data_url),
lofi_state(lofi_state),
- navigation_start(navigation_start) {
-}
+ navigation_start(navigation_start),
+ method(method) {}
+
+CommonNavigationParams::CommonNavigationParams(
+ const CommonNavigationParams& other) = default;
CommonNavigationParams::~CommonNavigationParams() {
}
@@ -69,21 +75,22 @@ BeginNavigationParams::BeginNavigationParams()
request_context_type(REQUEST_CONTEXT_TYPE_LOCATION) {}
BeginNavigationParams::BeginNavigationParams(
- std::string method,
std::string headers,
int load_flags,
bool has_user_gesture,
bool skip_service_worker,
RequestContextType request_context_type)
- : method(method),
- headers(headers),
+ : headers(headers),
load_flags(load_flags),
has_user_gesture(has_user_gesture),
skip_service_worker(skip_service_worker),
request_context_type(request_context_type) {}
+BeginNavigationParams::BeginNavigationParams(
+ const BeginNavigationParams& other) = default;
+
StartNavigationParams::StartNavigationParams()
- : is_post(false),
+ :
#if defined(OS_ANDROID)
has_user_gesture(false),
#endif
@@ -92,7 +99,6 @@ StartNavigationParams::StartNavigationParams()
}
StartNavigationParams::StartNavigationParams(
- bool is_post,
const std::string& extra_headers,
const std::vector<unsigned char>& browser_initiated_post_data,
#if defined(OS_ANDROID)
@@ -100,8 +106,7 @@ StartNavigationParams::StartNavigationParams(
#endif
int transferred_request_child_id,
int transferred_request_request_id)
- : is_post(is_post),
- extra_headers(extra_headers),
+ : extra_headers(extra_headers),
browser_initiated_post_data(browser_initiated_post_data),
#if defined(OS_ANDROID)
has_user_gesture(has_user_gesture),
@@ -110,6 +115,9 @@ StartNavigationParams::StartNavigationParams(
transferred_request_request_id(transferred_request_request_id) {
}
+StartNavigationParams::StartNavigationParams(
+ const StartNavigationParams& other) = default;
+
StartNavigationParams::~StartNavigationParams() {
}
@@ -164,6 +172,9 @@ RequestNavigationParams::RequestNavigationParams(
should_create_service_worker(false),
service_worker_provider_id(kInvalidServiceWorkerProviderId) {}
+RequestNavigationParams::RequestNavigationParams(
+ const RequestNavigationParams& other) = default;
+
RequestNavigationParams::~RequestNavigationParams() {
}
diff --git a/chromium/content/common/navigation_params.h b/chromium/content/common/navigation_params.h
index 414319d73e3..d2f83e756c1 100644
--- a/chromium/content/common/navigation_params.h
+++ b/chromium/content/common/navigation_params.h
@@ -59,7 +59,9 @@ struct CONTENT_EXPORT CommonNavigationParams {
const GURL& base_url_for_data_url,
const GURL& history_url_for_data_url,
LoFiState lofi_state,
- const base::TimeTicks& navigation_start);
+ const base::TimeTicks& navigation_start,
+ std::string method);
+ CommonNavigationParams(const CommonNavigationParams& other);
~CommonNavigationParams();
// The URL to navigate to.
@@ -113,6 +115,9 @@ struct CONTENT_EXPORT CommonNavigationParams {
// PlzNavigate: For renderer initiated navigations, this will be set on the
// renderer side and sent with FrameHostMsg_BeginNavigation.
base::TimeTicks navigation_start;
+
+ // The request method: GET, POST, etc.
+ std::string method;
};
// Provided by the renderer ----------------------------------------------------
@@ -128,15 +133,12 @@ struct CONTENT_EXPORT BeginNavigationParams {
// TODO(clamy): See if it is possible to reuse this in
// ResourceMsg_Request_Params.
BeginNavigationParams();
- BeginNavigationParams(std::string method,
- std::string headers,
+ BeginNavigationParams(std::string headers,
int load_flags,
bool has_user_gesture,
bool skip_service_worker,
RequestContextType request_context_type);
-
- // The request method: GET, POST, etc.
- std::string method;
+ BeginNavigationParams(const BeginNavigationParams& other);
// Additional HTTP request headers.
std::string headers;
@@ -171,7 +173,6 @@ struct CONTENT_EXPORT BeginNavigationParams {
struct CONTENT_EXPORT StartNavigationParams {
StartNavigationParams();
StartNavigationParams(
- bool is_post,
const std::string& extra_headers,
const std::vector<unsigned char>& browser_initiated_post_data,
#if defined(OS_ANDROID)
@@ -179,11 +180,9 @@ struct CONTENT_EXPORT StartNavigationParams {
#endif
int transferred_request_child_id,
int transferred_request_request_id);
+ StartNavigationParams(const StartNavigationParams& other);
~StartNavigationParams();
- // Whether the navigation is a POST request (as opposed to a GET).
- bool is_post;
-
// Extra headers (separated by \n) to send during the request.
std::string extra_headers;
@@ -224,6 +223,7 @@ struct CONTENT_EXPORT RequestNavigationParams {
int current_history_list_length,
bool is_view_source,
bool should_clear_history_list);
+ RequestNavigationParams(const RequestNavigationParams& other);
~RequestNavigationParams();
// Whether or not the user agent override string should be used.
diff --git a/chromium/content/common/net/url_request_service_worker_data.cc b/chromium/content/common/net/url_request_service_worker_data.cc
new file mode 100644
index 00000000000..cbf2a875494
--- /dev/null
+++ b/chromium/content/common/net/url_request_service_worker_data.cc
@@ -0,0 +1,17 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/net/url_request_service_worker_data.h"
+
+namespace content {
+
+URLRequestServiceWorkerData::URLRequestServiceWorkerData() {}
+
+URLRequestServiceWorkerData::~URLRequestServiceWorkerData() {}
+
+// static
+const void* URLRequestServiceWorkerData::kUserDataKey =
+ static_cast<const void*>(&URLRequestServiceWorkerData::kUserDataKey);
+
+} // namespace content
diff --git a/chromium/content/common/net/url_request_service_worker_data.h b/chromium/content/common/net/url_request_service_worker_data.h
new file mode 100644
index 00000000000..4d72321d0a6
--- /dev/null
+++ b/chromium/content/common/net/url_request_service_worker_data.h
@@ -0,0 +1,28 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_NET_URL_REQUEST_SERVICE_WORKER_DATA_H_
+#define CONTENT_COMMON_NET_URL_REQUEST_SERVICE_WORKER_DATA_H_
+
+#include "base/supports_user_data.h"
+
+namespace content {
+
+// Used to annotate all URLRequests for which the request originated in the
+// Service Worker and for initial Service Worker script loads.
+// Summarized this includes requests due to:
+// - fetching Service Worker script itself for installation,
+// - importing other scripts from within a Service Worker script,
+// - calling fetch() from within a Service Worker script.
+class URLRequestServiceWorkerData : public base::SupportsUserData::Data {
+ public:
+ URLRequestServiceWorkerData();
+ ~URLRequestServiceWorkerData() override;
+
+ static const void* kUserDataKey;
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_NET_URL_REQUEST_SERVICE_WORKER_DATA_H_
diff --git a/chromium/content/common/notification_constants.h b/chromium/content/common/notification_constants.h
index 6ca8ad62e59..2573a6eb8f8 100644
--- a/chromium/content/common/notification_constants.h
+++ b/chromium/content/common/notification_constants.h
@@ -12,6 +12,18 @@ namespace content {
// Maximum number of actions on a Platform Notification.
static const size_t kPlatformNotificationMaxActions = 2;
+// The maximum reasonable notification icon size, scaled from dip units to
+// pixels using the largest supported scaling factor.
+static const int kPlatformNotificationMaxIconSizePx = 320; // 80 dip * 4
+
+// The maximum reasonable badge size, scaled from dip units to pixels using the
+// largest supported scaling factor.
+static const int kPlatformNotificationMaxBadgeSizePx = 96; // 24 dip * 4
+
+// The maximum reasonable action icon size, scaled from dip units to
+// pixels using the largest supported scaling factor.
+static const int kPlatformNotificationMaxActionIconSizePx = 128; // 32 dip * 4
+
} // namespace content
#endif // CONTENT_COMMON_NOTIFICATION_CONSTANTS_H_
diff --git a/chromium/content/common/one_writer_seqlock_unittest.cc b/chromium/content/common/one_writer_seqlock_unittest.cc
index 8e69812c9e2..84d5156a7bd 100644
--- a/chromium/content/common/one_writer_seqlock_unittest.cc
+++ b/chromium/content/common/one_writer_seqlock_unittest.cc
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
#include "base/threading/platform_thread.h"
+#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace base {
@@ -60,7 +61,12 @@ class BasicSeqLockTestThread : public PlatformThread::Delegate {
DISALLOW_COPY_AND_ASSIGN(BasicSeqLockTestThread);
};
-TEST(OneWriterSeqLockTest, ManyThreads) {
+#if defined(OS_ANDROID)
+#define MAYBE_ManyThreads FLAKY_ManyThreads
+#else
+#define MAYBE_ManyThreads ManyThreads
+#endif
+TEST(OneWriterSeqLockTest, MAYBE_ManyThreads) {
content::OneWriterSeqLock seqlock;
TestData data = { 0, 0, 0 };
base::AtomicRefCount ready = 0;
diff --git a/chromium/content/common/origin_trials/trial_token.cc b/chromium/content/common/origin_trials/trial_token.cc
new file mode 100644
index 00000000000..0a137edc68b
--- /dev/null
+++ b/chromium/content/common/origin_trials/trial_token.cc
@@ -0,0 +1,193 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/origin_trials/trial_token.h"
+
+#include <openssl/curve25519.h>
+
+#include <vector>
+
+#include "base/base64.h"
+#include "base/big_endian.h"
+#include "base/json/json_reader.h"
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "base/strings/string_piece.h"
+#include "base/time/time.h"
+#include "base/values.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace content {
+
+namespace {
+
+// Version is a 1-byte field at offset 0.
+const size_t kVersionOffset = 0;
+const size_t kVersionSize = 1;
+
+// These constants define the Version 2 field sizes and offsets.
+const size_t kSignatureOffset = kVersionOffset + kVersionSize;
+const size_t kSignatureSize = 64;
+const size_t kPayloadLengthOffset = kSignatureOffset + kSignatureSize;
+const size_t kPayloadLengthSize = 4;
+const size_t kPayloadOffset = kPayloadLengthOffset + kPayloadLengthSize;
+
+// Version 2 is the only token version currently supported. Version 1 was
+// introduced in Chrome M50, and removed in M51. There were no experiments
+// enabled in the stable M50 release which would have used those tokens.
+const uint8_t kVersion2 = 2;
+
+} // namespace
+
+TrialToken::~TrialToken() {}
+
+// static
+std::unique_ptr<TrialToken> TrialToken::From(const std::string& token_text,
+ base::StringPiece public_key) {
+ std::unique_ptr<std::string> token_payload = Extract(token_text, public_key);
+ if (!token_payload) {
+ return nullptr;
+ }
+ return Parse(*token_payload);
+}
+
+bool TrialToken::IsValidForFeature(const url::Origin& origin,
+ base::StringPiece feature_name,
+ const base::Time& now) const {
+ return ValidateOrigin(origin) && ValidateFeatureName(feature_name) &&
+ ValidateDate(now);
+}
+
+std::unique_ptr<std::string> TrialToken::Extract(
+ const std::string& token_payload,
+ base::StringPiece public_key) {
+ if (token_payload.empty()) {
+ return nullptr;
+ }
+
+ // Token is base64-encoded; decode first.
+ std::string token_contents;
+ if (!base::Base64Decode(token_payload, &token_contents)) {
+ return nullptr;
+ }
+
+ // Only version 2 currently supported.
+ if (token_contents.length() < (kVersionOffset + kVersionSize)) {
+ return nullptr;
+ }
+ uint8_t version = token_contents[kVersionOffset];
+ if (version != kVersion2) {
+ return nullptr;
+ }
+
+ // Token must be large enough to contain a version, signature, and payload
+ // length.
+ if (token_contents.length() < (kPayloadLengthOffset + kPayloadLengthSize)) {
+ return nullptr;
+ }
+
+ // Extract the length of the signed data (Big-endian).
+ uint32_t payload_length;
+ base::ReadBigEndian(&(token_contents[kPayloadLengthOffset]), &payload_length);
+
+ // Validate that the stated length matches the actual payload length.
+ if (payload_length != token_contents.length() - kPayloadOffset) {
+ return nullptr;
+ }
+
+ // Extract the version-specific contents of the token.
+ const char* token_bytes = token_contents.data();
+ base::StringPiece version_piece(token_bytes + kVersionOffset, kVersionSize);
+ base::StringPiece signature(token_bytes + kSignatureOffset, kSignatureSize);
+ base::StringPiece payload_piece(token_bytes + kPayloadLengthOffset,
+ kPayloadLengthSize + payload_length);
+
+ // The data which is covered by the signature is (version + length + payload).
+ std::string signed_data =
+ version_piece.as_string() + payload_piece.as_string();
+
+ // Validate the signature on the data before proceeding.
+ if (!TrialToken::ValidateSignature(signature, signed_data, public_key)) {
+ return nullptr;
+ }
+
+ // Return just the payload, as a new string.
+ return base::WrapUnique(
+ new std::string(token_contents, kPayloadOffset, payload_length));
+}
+
+std::unique_ptr<TrialToken> TrialToken::Parse(const std::string& token_json) {
+ std::unique_ptr<base::DictionaryValue> datadict =
+ base::DictionaryValue::From(base::JSONReader::Read(token_json));
+ if (!datadict) {
+ return nullptr;
+ }
+
+ std::string origin_string;
+ std::string feature_name;
+ int expiry_timestamp = 0;
+ datadict->GetString("origin", &origin_string);
+ datadict->GetString("feature", &feature_name);
+ datadict->GetInteger("expiry", &expiry_timestamp);
+
+ // Ensure that the origin is a valid (non-unique) origin URL.
+ url::Origin origin = url::Origin(GURL(origin_string));
+ if (origin.unique()) {
+ return nullptr;
+ }
+
+ // Ensure that the feature name is a valid string.
+ if (feature_name.empty()) {
+ return nullptr;
+ }
+
+ // Ensure that the expiry timestamp is a valid (positive) integer.
+ if (expiry_timestamp <= 0) {
+ return nullptr;
+ }
+
+ return base::WrapUnique(
+ new TrialToken(origin, feature_name, expiry_timestamp));
+}
+
+bool TrialToken::ValidateOrigin(const url::Origin& origin) const {
+ return origin == origin_;
+}
+
+bool TrialToken::ValidateFeatureName(base::StringPiece feature_name) const {
+ return feature_name == feature_name_;
+}
+
+bool TrialToken::ValidateDate(const base::Time& now) const {
+ return expiry_time_ > now;
+}
+
+// static
+bool TrialToken::ValidateSignature(base::StringPiece signature,
+ const std::string& data,
+ base::StringPiece public_key) {
+ // Public key must be 32 bytes long for Ed25519.
+ CHECK_EQ(public_key.length(), 32UL);
+
+ // Signature must be 64 bytes long.
+ if (signature.length() != 64) {
+ return false;
+ }
+
+ int result = ED25519_verify(
+ reinterpret_cast<const uint8_t*>(data.data()), data.length(),
+ reinterpret_cast<const uint8_t*>(signature.data()),
+ reinterpret_cast<const uint8_t*>(public_key.data()));
+ return (result != 0);
+}
+
+TrialToken::TrialToken(const url::Origin& origin,
+ const std::string& feature_name,
+ uint64_t expiry_timestamp)
+ : origin_(origin),
+ feature_name_(feature_name),
+ expiry_time_(base::Time::FromDoubleT(expiry_timestamp)) {}
+
+} // namespace content
diff --git a/chromium/content/common/origin_trials/trial_token.h b/chromium/content/common/origin_trials/trial_token.h
new file mode 100644
index 00000000000..fa05e3713b5
--- /dev/null
+++ b/chromium/content/common/origin_trials/trial_token.h
@@ -0,0 +1,90 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_ORIGIN_TRIALS_TRIAL_TOKEN_H_
+#define CONTENT_COMMON_ORIGIN_TRIALS_TRIAL_TOKEN_H_
+
+#include <memory>
+#include <string>
+
+#include "base/strings/string_piece.h"
+#include "base/time/time.h"
+#include "content/common/content_export.h"
+#include "url/origin.h"
+
+namespace content {
+
+// The Experimental Framework (EF) provides limited access to experimental
+// features, on a per-origin basis (origin trials). This class defines the trial
+// token data structure, used to securely provide access to an experimental
+// feature.
+//
+// Features are defined by string names, provided by the implementers. The EF
+// code does not maintain an enum or constant list for feature names. Instead,
+// the EF validates the name provided by the feature implementation against any
+// provided tokens.
+//
+// More documentation on the token format can be found at
+// https://docs.google.com/document/d/1v5fi0EUV_QHckVHVF2K4P72iNywnrJtNhNZ6i2NPt0M
+
+class CONTENT_EXPORT TrialToken {
+ public:
+ ~TrialToken();
+
+ // Returns a token object if the string represents a signed well-formed token,
+ // or nullptr otherwise. (This does not mean that the token is currently
+ // valid, or appropriate for a given origin / feature, just that it is
+ // correctly formatted and signed by the supplied public key, and can be
+ // parsed.)
+ static std::unique_ptr<TrialToken> From(const std::string& token_text,
+ base::StringPiece public_key);
+
+ // Returns true if this token is appropriate for use by the given origin,
+ // for the given feature name, and has not yet expired.
+ bool IsValidForFeature(const url::Origin& origin,
+ base::StringPiece feature_name,
+ const base::Time& now) const;
+
+ url::Origin origin() { return origin_; }
+ std::string feature_name() { return feature_name_; }
+ base::Time expiry_time() { return expiry_time_; }
+
+ protected:
+ friend class TrialTokenTest;
+
+ // Returns the payload of a signed token, or nullptr if the token is not
+ // properly signed, or is not well-formed.
+ static std::unique_ptr<std::string> Extract(const std::string& token_text,
+ base::StringPiece public_key);
+
+ // Returns a token object if the string represents a well-formed JSON token
+ // payload, or nullptr otherwise.
+ static std::unique_ptr<TrialToken> Parse(const std::string& token_json);
+
+ bool ValidateOrigin(const url::Origin& origin) const;
+ bool ValidateFeatureName(base::StringPiece feature_name) const;
+ bool ValidateDate(const base::Time& now) const;
+
+ static bool ValidateSignature(base::StringPiece signature_text,
+ const std::string& data,
+ base::StringPiece public_key);
+
+ private:
+ TrialToken(const url::Origin& origin,
+ const std::string& feature_name,
+ uint64_t expiry_timestamp);
+
+ // The origin for which this token is valid. Must be a secure origin.
+ url::Origin origin_;
+
+ // The name of the experimental feature which this token enables.
+ std::string feature_name_;
+
+ // The time until which this token should be considered valid.
+ base::Time expiry_time_;
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_ORIGIN_TRIALS_TRIAL_TOKEN_H_
diff --git a/chromium/content/common/origin_trials/trial_token_unittest.cc b/chromium/content/common/origin_trials/trial_token_unittest.cc
new file mode 100644
index 00000000000..ebb5b05a4cf
--- /dev/null
+++ b/chromium/content/common/origin_trials/trial_token_unittest.cc
@@ -0,0 +1,300 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/origin_trials/trial_token.h"
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_util.h"
+#include "base/test/simple_test_clock.h"
+#include "base/time/time.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace {
+
+// This is a sample public key for testing the API. The corresponding private
+// key (use this to generate new samples for this test file) is:
+//
+// 0x83, 0x67, 0xf4, 0xcd, 0x2a, 0x1f, 0x0e, 0x04, 0x0d, 0x43, 0x13,
+// 0x4c, 0x67, 0xc4, 0xf4, 0x28, 0xc9, 0x90, 0x15, 0x02, 0xe2, 0xba,
+// 0xfd, 0xbb, 0xfa, 0xbc, 0x92, 0x76, 0x8a, 0x2c, 0x4b, 0xc7, 0x75,
+// 0x10, 0xac, 0xf9, 0x3a, 0x1c, 0xb8, 0xa9, 0x28, 0x70, 0xd2, 0x9a,
+// 0xd0, 0x0b, 0x59, 0xe1, 0xac, 0x2b, 0xb7, 0xd5, 0xca, 0x1f, 0x64,
+// 0x90, 0x08, 0x8e, 0xa8, 0xe0, 0x56, 0x3a, 0x04, 0xd0
+const uint8_t kTestPublicKey[] = {
+ 0x75, 0x10, 0xac, 0xf9, 0x3a, 0x1c, 0xb8, 0xa9, 0x28, 0x70, 0xd2,
+ 0x9a, 0xd0, 0x0b, 0x59, 0xe1, 0xac, 0x2b, 0xb7, 0xd5, 0xca, 0x1f,
+ 0x64, 0x90, 0x08, 0x8e, 0xa8, 0xe0, 0x56, 0x3a, 0x04, 0xd0,
+};
+
+// This is a valid, but incorrect, public key for testing signatures against.
+// The corresponding private key is:
+//
+// 0x21, 0xee, 0xfa, 0x81, 0x6a, 0xff, 0xdf, 0xb8, 0xc1, 0xdd, 0x75,
+// 0x05, 0x04, 0x29, 0x68, 0x67, 0x60, 0x85, 0x91, 0xd0, 0x50, 0x16,
+// 0x0a, 0xcf, 0xa2, 0x37, 0xa3, 0x2e, 0x11, 0x7a, 0x17, 0x96, 0x50,
+// 0x07, 0x4d, 0x76, 0x55, 0x56, 0x42, 0x17, 0x2d, 0x8a, 0x9c, 0x47,
+// 0x96, 0x25, 0xda, 0x70, 0xaa, 0xb9, 0xfd, 0x53, 0x5d, 0x51, 0x3e,
+// 0x16, 0xab, 0xb4, 0x86, 0xea, 0xf3, 0x35, 0xc6, 0xca
+const uint8_t kTestPublicKey2[] = {
+ 0x50, 0x07, 0x4d, 0x76, 0x55, 0x56, 0x42, 0x17, 0x2d, 0x8a, 0x9c,
+ 0x47, 0x96, 0x25, 0xda, 0x70, 0xaa, 0xb9, 0xfd, 0x53, 0x5d, 0x51,
+ 0x3e, 0x16, 0xab, 0xb4, 0x86, 0xea, 0xf3, 0x35, 0xc6, 0xca,
+};
+
+// This is a good trial token, signed with the above test private key.
+// Generate this token with the command (in tools/origin_trials):
+// generate_token.py valid.example.com Frobulate --expire-timestamp=1458766277
+const char* kSampleToken =
+ "Ap+Q/Qm0ELadZql+dlEGSwnAVsFZKgCEtUZg8idQC3uekkIeSZIY1tftoYdrwhqj"
+ "7FO5L22sNvkZZnacLvmfNwsAAABZeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5l"
+ "eGFtcGxlLmNvbTo0NDMiLCAiZmVhdHVyZSI6ICJGcm9idWxhdGUiLCAiZXhwaXJ5"
+ "IjogMTQ1ODc2NjI3N30=";
+
+const char* kExpectedFeatureName = "Frobulate";
+const char* kExpectedOrigin = "https://valid.example.com";
+const uint64_t kExpectedExpiry = 1458766277;
+
+// The token should not be valid for this origin, or for this feature.
+const char* kInvalidOrigin = "https://invalid.example.com";
+const char* kInsecureOrigin = "http://valid.example.com";
+const char* kInvalidFeatureName = "Grokalyze";
+
+// The token should be valid if the current time is kValidTimestamp or earlier.
+double kValidTimestamp = 1458766276.0;
+
+// The token should be invalid if the current time is kInvalidTimestamp or
+// later.
+double kInvalidTimestamp = 1458766278.0;
+
+// Well-formed trial token with an invalid signature.
+const char* kInvalidSignatureToken =
+ "AYeNXSDktgG9p4ns5B1WKsLq2TytMxfR4whfbi+oyT0rXyzh+qXYfxbDMGmyjU2Z"
+ "lEJ16vQObMXJoOaYUqd8xwkAAABZeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5l"
+ "eGFtcGxlLmNvbTo0NDMiLCAiZmVhdHVyZSI6ICJGcm9idWxhdGUiLCAiZXhwaXJ5"
+ "IjogMTQ1ODc2NjI3N30=";
+
+// Trial token truncated in the middle of the length field; too short to
+// possibly be valid.
+const char kTruncatedToken[] =
+ "Ap+Q/Qm0ELadZql+dlEGSwnAVsFZKgCEtUZg8idQC3uekkIeSZIY1tftoYdrwhqj"
+ "7FO5L22sNvkZZnacLvmfNwsA";
+
+// Trial token with an incorrectly-declared length, but with a valid signature.
+const char kIncorrectLengthToken[] =
+ "Ao06eNl/CZuM88qurWKX4RfoVEpHcVHWxdOTrEXZkaC1GUHyb/8L4sthADiVWdc9"
+ "kXFyF1BW5bbraqp6MBVr3wEAAABaeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5l"
+ "eGFtcGxlLmNvbTo0NDMiLCAiZmVhdHVyZSI6ICJGcm9idWxhdGUiLCAiZXhwaXJ5"
+ "IjogMTQ1ODc2NjI3N30=";
+
+// Trial token with a misidentified version (42).
+const char kIncorrectVersionToken[] =
+ "KlH8wVLT5o59uDvlJESorMDjzgWnvG1hmIn/GiT9Ng3f45ratVeiXCNTeaJheOaG"
+ "A6kX4ir4Amv8aHVC+OJHZQkAAABZeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5l"
+ "eGFtcGxlLmNvbTo0NDMiLCAiZmVhdHVyZSI6ICJGcm9idWxhdGUiLCAiZXhwaXJ5"
+ "IjogMTQ1ODc2NjI3N30=";
+
+const char kSampleTokenJSON[] =
+ "{\"origin\": \"https://valid.example.com:443\", \"feature\": "
+ "\"Frobulate\", \"expiry\": 1458766277}";
+
+// Various ill-formed trial tokens. These should all fail to parse.
+const char* kInvalidTokens[] = {
+ // Invalid - Not JSON at all
+ "abcde",
+ // Invalid JSON
+ "{",
+ // Not an object
+ "\"abcde\"",
+ "123.4",
+ "[0, 1, 2]",
+ // Missing keys
+ "{}",
+ "{\"something\": 1}",
+ "{\"origin\": \"https://a.a\"}",
+ "{\"origin\": \"https://a.a\", \"feature\": \"a\"}"
+ "{\"origin\": \"https://a.a\", \"expiry\": 1458766277}",
+ "{\"feature\": \"FeatureName\", \"expiry\": 1458766277}",
+ // Incorrect types
+ "{\"origin\": 1, \"feature\": \"a\", \"expiry\": 1458766277}",
+ "{\"origin\": \"https://a.a\", \"feature\": 1, \"expiry\": 1458766277}",
+ "{\"origin\": \"https://a.a\", \"feature\": \"a\", \"expiry\": \"1\"}",
+ // Negative expiry timestamp
+ "{\"origin\": \"https://a.a\", \"feature\": \"a\", \"expiry\": -1}",
+ // Origin not a proper origin URL
+ "{\"origin\": \"abcdef\", \"feature\": \"a\", \"expiry\": 1458766277}",
+ "{\"origin\": \"data:text/plain,abcdef\", \"feature\": \"a\", \"expiry\": "
+ "1458766277}",
+ "{\"origin\": \"javascript:alert(1)\", \"feature\": \"a\", \"expiry\": "
+ "1458766277}"};
+
+} // namespace
+
+class TrialTokenTest : public testing::TestWithParam<const char*> {
+ public:
+ TrialTokenTest()
+ : expected_origin_(GURL(kExpectedOrigin)),
+ invalid_origin_(GURL(kInvalidOrigin)),
+ insecure_origin_(GURL(kInsecureOrigin)),
+ expected_expiry_(base::Time::FromDoubleT(kExpectedExpiry)),
+ valid_timestamp_(base::Time::FromDoubleT(kValidTimestamp)),
+ invalid_timestamp_(base::Time::FromDoubleT(kInvalidTimestamp)),
+ correct_public_key_(
+ base::StringPiece(reinterpret_cast<const char*>(kTestPublicKey),
+ arraysize(kTestPublicKey))),
+ incorrect_public_key_(
+ base::StringPiece(reinterpret_cast<const char*>(kTestPublicKey2),
+ arraysize(kTestPublicKey2))) {}
+
+ protected:
+ std::unique_ptr<std::string> Extract(const std::string& token_text,
+ base::StringPiece public_key) {
+ return TrialToken::Extract(token_text, public_key);
+ }
+ std::unique_ptr<TrialToken> Parse(const std::string& token_payload) {
+ return TrialToken::Parse(token_payload);
+ }
+
+ bool ValidateOrigin(TrialToken* token, const url::Origin origin) {
+ return token->ValidateOrigin(origin);
+ }
+
+ bool ValidateFeatureName(TrialToken* token, const char* feature_name) {
+ return token->ValidateFeatureName(feature_name);
+ }
+
+ bool ValidateDate(TrialToken* token, const base::Time& now) {
+ return token->ValidateDate(now);
+ }
+
+ base::StringPiece correct_public_key() { return correct_public_key_; }
+ base::StringPiece incorrect_public_key() { return incorrect_public_key_; }
+
+ const url::Origin expected_origin_;
+ const url::Origin invalid_origin_;
+ const url::Origin insecure_origin_;
+
+ const base::Time expected_expiry_;
+ const base::Time valid_timestamp_;
+ const base::Time invalid_timestamp_;
+
+ private:
+ base::StringPiece correct_public_key_;
+ base::StringPiece incorrect_public_key_;
+};
+
+// Test the extraction of the signed payload from token strings. This includes
+// checking the included version identifier, payload length, and cryptographic
+// signature.
+
+// Test verification of signature and extraction of token JSON from signed
+// token.
+TEST_F(TrialTokenTest, ValidateValidSignature) {
+ std::unique_ptr<std::string> token_payload =
+ Extract(kSampleToken, correct_public_key());
+ ASSERT_TRUE(token_payload);
+ EXPECT_STREQ(kSampleTokenJSON, token_payload.get()->c_str());
+}
+
+TEST_F(TrialTokenTest, ValidateInvalidSignature) {
+ std::unique_ptr<std::string> token_payload =
+ Extract(kInvalidSignatureToken, correct_public_key());
+ ASSERT_FALSE(token_payload);
+}
+
+TEST_F(TrialTokenTest, ValidateSignatureWithIncorrectKey) {
+ std::unique_ptr<std::string> token_payload =
+ Extract(kSampleToken, incorrect_public_key());
+ ASSERT_FALSE(token_payload);
+}
+
+TEST_F(TrialTokenTest, ValidateEmptyToken) {
+ std::unique_ptr<std::string> token_payload =
+ Extract("", correct_public_key());
+ ASSERT_FALSE(token_payload);
+}
+
+TEST_F(TrialTokenTest, ValidateShortToken) {
+ std::unique_ptr<std::string> token_payload =
+ Extract(kTruncatedToken, correct_public_key());
+ ASSERT_FALSE(token_payload);
+}
+
+TEST_F(TrialTokenTest, ValidateUnsupportedVersion) {
+ std::unique_ptr<std::string> token_payload =
+ Extract(kIncorrectVersionToken, correct_public_key());
+ ASSERT_FALSE(token_payload);
+}
+
+TEST_F(TrialTokenTest, ValidateSignatureWithIncorrectLength) {
+ std::unique_ptr<std::string> token_payload =
+ Extract(kIncorrectLengthToken, correct_public_key());
+ ASSERT_FALSE(token_payload);
+}
+
+// Test parsing of fields from JSON token.
+
+TEST_F(TrialTokenTest, ParseEmptyString) {
+ std::unique_ptr<TrialToken> empty_token = Parse("");
+ EXPECT_FALSE(empty_token);
+}
+
+TEST_P(TrialTokenTest, ParseInvalidString) {
+ std::unique_ptr<TrialToken> empty_token = Parse(GetParam());
+ EXPECT_FALSE(empty_token) << "Invalid trial token should not parse.";
+}
+
+INSTANTIATE_TEST_CASE_P(, TrialTokenTest, ::testing::ValuesIn(kInvalidTokens));
+
+TEST_F(TrialTokenTest, ParseValidToken) {
+ std::unique_ptr<TrialToken> token = Parse(kSampleTokenJSON);
+ ASSERT_TRUE(token);
+ EXPECT_EQ(kExpectedFeatureName, token->feature_name());
+ EXPECT_EQ(expected_origin_, token->origin());
+ EXPECT_EQ(expected_expiry_, token->expiry_time());
+}
+
+TEST_F(TrialTokenTest, ValidateValidToken) {
+ std::unique_ptr<TrialToken> token = Parse(kSampleTokenJSON);
+ ASSERT_TRUE(token);
+ EXPECT_TRUE(ValidateOrigin(token.get(), expected_origin_));
+ EXPECT_FALSE(ValidateOrigin(token.get(), invalid_origin_));
+ EXPECT_FALSE(ValidateOrigin(token.get(), insecure_origin_));
+ EXPECT_TRUE(ValidateFeatureName(token.get(), kExpectedFeatureName));
+ EXPECT_FALSE(ValidateFeatureName(token.get(), kInvalidFeatureName));
+ EXPECT_FALSE(ValidateFeatureName(
+ token.get(), base::ToUpperASCII(kExpectedFeatureName).c_str()));
+ EXPECT_FALSE(ValidateFeatureName(
+ token.get(), base::ToLowerASCII(kExpectedFeatureName).c_str()));
+ EXPECT_TRUE(ValidateDate(token.get(), valid_timestamp_));
+ EXPECT_FALSE(ValidateDate(token.get(), invalid_timestamp_));
+}
+
+TEST_F(TrialTokenTest, TokenIsValidForFeature) {
+ std::unique_ptr<TrialToken> token = Parse(kSampleTokenJSON);
+ ASSERT_TRUE(token);
+ EXPECT_TRUE(token->IsValidForFeature(expected_origin_, kExpectedFeatureName,
+ valid_timestamp_));
+ EXPECT_FALSE(token->IsValidForFeature(
+ expected_origin_, base::ToUpperASCII(kExpectedFeatureName),
+ valid_timestamp_));
+ EXPECT_FALSE(token->IsValidForFeature(
+ expected_origin_, base::ToLowerASCII(kExpectedFeatureName),
+ valid_timestamp_));
+ EXPECT_FALSE(token->IsValidForFeature(invalid_origin_, kExpectedFeatureName,
+ valid_timestamp_));
+ EXPECT_FALSE(token->IsValidForFeature(insecure_origin_, kExpectedFeatureName,
+ valid_timestamp_));
+ EXPECT_FALSE(token->IsValidForFeature(expected_origin_, kInvalidFeatureName,
+ valid_timestamp_));
+ EXPECT_FALSE(token->IsValidForFeature(expected_origin_, kExpectedFeatureName,
+ invalid_timestamp_));
+}
+
+} // namespace content
diff --git a/chromium/content/common/origin_trials/trial_token_validator.cc b/chromium/content/common/origin_trials/trial_token_validator.cc
new file mode 100644
index 00000000000..6eef75a5e9a
--- /dev/null
+++ b/chromium/content/common/origin_trials/trial_token_validator.cc
@@ -0,0 +1,30 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/origin_trials/trial_token_validator.h"
+
+#include "base/time/time.h"
+#include "content/common/origin_trials/trial_token.h"
+#include "content/public/common/content_client.h"
+
+namespace content {
+
+bool TrialTokenValidator::ValidateToken(const std::string& token,
+ const url::Origin& origin,
+ base::StringPiece feature_name) {
+ // TODO(iclelland): Allow for multiple signing keys, and iterate over all
+ // active keys here. https://crbug.com/543220
+ ContentClient* content_client = GetContentClient();
+ base::StringPiece public_key = content_client->GetOriginTrialPublicKey();
+ if (public_key.empty()) {
+ return false;
+ }
+ std::unique_ptr<TrialToken> trial_token = TrialToken::From(token, public_key);
+
+ return trial_token &&
+ trial_token->IsValidForFeature(origin, feature_name,
+ base::Time::Now());
+}
+
+} // namespace content
diff --git a/chromium/content/common/origin_trials/trial_token_validator.h b/chromium/content/common/origin_trials/trial_token_validator.h
new file mode 100644
index 00000000000..a8406350d71
--- /dev/null
+++ b/chromium/content/common/origin_trials/trial_token_validator.h
@@ -0,0 +1,26 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_ORIGIN_TRIALS_TRIAL_TOKEN_VALIDATOR_H_
+#define CONTENT_COMMON_ORIGIN_TRIALS_TRIAL_TOKEN_VALIDATOR_H_
+
+#include <string>
+#include "base/strings/string_piece.h"
+#include "content/common/content_export.h"
+#include "url/origin.h"
+
+namespace content {
+
+namespace TrialTokenValidator {
+
+// This method is thread-safe.
+CONTENT_EXPORT bool ValidateToken(const std::string& token,
+ const url::Origin& origin,
+ base::StringPiece feature_name);
+
+} // namespace TrialTokenValidator
+
+} // namespace content
+
+#endif // CONTENT_COMMON_ORIGIN_TRIALS_TRIAL_TOKEN_VALIDATOR_H_
diff --git a/chromium/content/common/origin_trials/trial_token_validator_unittest.cc b/chromium/content/common/origin_trials/trial_token_validator_unittest.cc
new file mode 100644
index 00000000000..59011e785f2
--- /dev/null
+++ b/chromium/content/common/origin_trials/trial_token_validator_unittest.cc
@@ -0,0 +1,160 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/origin_trials/trial_token_validator.h"
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/strings/string_util.h"
+#include "base/test/simple_test_clock.h"
+#include "base/time/time.h"
+#include "content/public/common/content_client.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace content {
+
+namespace {
+
+// This is a sample public key for testing the API. The corresponding private
+// key (use this to generate new samples for this test file) is:
+//
+// 0x83, 0x67, 0xf4, 0xcd, 0x2a, 0x1f, 0x0e, 0x04, 0x0d, 0x43, 0x13,
+// 0x4c, 0x67, 0xc4, 0xf4, 0x28, 0xc9, 0x90, 0x15, 0x02, 0xe2, 0xba,
+// 0xfd, 0xbb, 0xfa, 0xbc, 0x92, 0x76, 0x8a, 0x2c, 0x4b, 0xc7, 0x75,
+// 0x10, 0xac, 0xf9, 0x3a, 0x1c, 0xb8, 0xa9, 0x28, 0x70, 0xd2, 0x9a,
+// 0xd0, 0x0b, 0x59, 0xe1, 0xac, 0x2b, 0xb7, 0xd5, 0xca, 0x1f, 0x64,
+// 0x90, 0x08, 0x8e, 0xa8, 0xe0, 0x56, 0x3a, 0x04, 0xd0
+const uint8_t kTestPublicKey[] = {
+ 0x75, 0x10, 0xac, 0xf9, 0x3a, 0x1c, 0xb8, 0xa9, 0x28, 0x70, 0xd2,
+ 0x9a, 0xd0, 0x0b, 0x59, 0xe1, 0xac, 0x2b, 0xb7, 0xd5, 0xca, 0x1f,
+ 0x64, 0x90, 0x08, 0x8e, 0xa8, 0xe0, 0x56, 0x3a, 0x04, 0xd0,
+};
+
+// 0x21, 0xee, 0xfa, 0x81, 0x6a, 0xff, 0xdf, 0xb8, 0xc1, 0xdd, 0x75,
+// 0x05, 0x04, 0x29, 0x68, 0x67, 0x60, 0x85, 0x91, 0xd0, 0x50, 0x16,
+// 0x0a, 0xcf, 0xa2, 0x37, 0xa3, 0x2e, 0x11, 0x7a, 0x17, 0x96, 0x50,
+// 0x07, 0x4d, 0x76, 0x55, 0x56, 0x42, 0x17, 0x2d, 0x8a, 0x9c, 0x47,
+// 0x96, 0x25, 0xda, 0x70, 0xaa, 0xb9, 0xfd, 0x53, 0x5d, 0x51, 0x3e,
+// 0x16, 0xab, 0xb4, 0x86, 0xea, 0xf3, 0x35, 0xc6, 0xca
+const uint8_t kTestPublicKey2[] = {
+ 0x50, 0x07, 0x4d, 0x76, 0x55, 0x56, 0x42, 0x17, 0x2d, 0x8a, 0x9c,
+ 0x47, 0x96, 0x25, 0xda, 0x70, 0xaa, 0xb9, 0xfd, 0x53, 0x5d, 0x51,
+ 0x3e, 0x16, 0xab, 0xb4, 0x86, 0xea, 0xf3, 0x35, 0xc6, 0xca,
+};
+
+// This is a good trial token, signed with the above test private key.
+// TODO(iclelland): This token expires in 2033. Update it or find a way
+// to autogenerate it before then.
+// Generate this token with the command (in tools/origin_trials):
+// generate_token.py valid.example.com Frobulate --expire-timestamp=2000000000
+const char kSampleToken[] =
+ "AuR/1mg+/w5ROLN54Ok20rApK3opgR7Tq9ZfzhATQmnCa+BtPA1RRw4Nigf336r+"
+ "O4fM3Sa+MEd+5JcIgSZafw8AAABZeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5l"
+ "eGFtcGxlLmNvbTo0NDMiLCAiZmVhdHVyZSI6ICJGcm9idWxhdGUiLCAiZXhwaXJ5"
+ "IjogMjAwMDAwMDAwMH0=";
+
+// The token should be valid for this origin and for this feature.
+const char kAppropriateOrigin[] = "https://valid.example.com";
+const char kAppropriateFeatureName[] = "Frobulate";
+
+const char kInappropriateFeatureName[] = "Grokalyze";
+const char kInappropriateOrigin[] = "https://invalid.example.com";
+const char kInsecureOrigin[] = "http://valid.example.com";
+
+// Well-formed trial token with an invalid signature.
+// This token is a corruption of the above valid token.
+const char kInvalidSignatureToken[] =
+ "AuR/1mg+/w5ROLN54Ok20rApK3opgR7Tq9ZfzhATQmnCa+BtPA1RRw4Nigf336r+"
+ "RrOtlAwa0gPqqn+A8GTD3AQAAABZeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5l"
+ "eGFtcGxlLmNvbTo0NDMiLCAiZmVhdHVyZSI6ICJGcm9idWxhdGUiLCAiZXhwaXJ5"
+ "IjogMjAwMDAwMDAwMH0=";
+
+// Well-formed, but expired, trial token. (Expired in 2001)
+// Generate this token with the command (in tools/origin_trials):
+// generate_token.py valid.example.com Frobulate --expire-timestamp=1000000000
+const char kExpiredToken[] =
+ "AmHPUIXMaXe9jWW8kJeDFXolVjT93p4XMnK4+jMYd2pjqtFcYB1bUmdD8PunQKM+"
+ "RrOtlAwa0gPqqn+A8GTD3AQAAABZeyJvcmlnaW4iOiAiaHR0cHM6Ly92YWxpZC5l"
+ "eGFtcGxlLmNvbTo0NDMiLCAiZmVhdHVyZSI6ICJGcm9idWxhdGUiLCAiZXhwaXJ5"
+ "IjogMTAwMDAwMDAwMH0=";
+
+const char kUnparsableToken[] = "abcde";
+
+class TestContentClient : public ContentClient {
+ public:
+ base::StringPiece GetOriginTrialPublicKey() override {
+ return base::StringPiece(reinterpret_cast<const char*>(key_),
+ arraysize(kTestPublicKey));
+ }
+ void SetOriginTrialPublicKey(const uint8_t* key) { key_ = key; }
+ const uint8_t* key_ = nullptr;
+};
+
+} // namespace
+
+class TrialTokenValidatorTest : public testing::Test {
+ public:
+ TrialTokenValidatorTest()
+ : appropriate_origin_(GURL(kAppropriateOrigin)),
+ inappropriate_origin_(GURL(kInappropriateOrigin)),
+ insecure_origin_(GURL(kInsecureOrigin)) {
+ SetPublicKey(kTestPublicKey);
+ SetContentClient(&test_content_client_);
+ }
+
+ ~TrialTokenValidatorTest() override { SetContentClient(nullptr); }
+
+ void SetPublicKey(const uint8_t* key) {
+ test_content_client_.SetOriginTrialPublicKey(key);
+ }
+
+ const url::Origin appropriate_origin_;
+ const url::Origin inappropriate_origin_;
+ const url::Origin insecure_origin_;
+
+ private:
+ TestContentClient test_content_client_;
+};
+
+TEST_F(TrialTokenValidatorTest, ValidateValidToken) {
+ EXPECT_TRUE(TrialTokenValidator::ValidateToken(
+ kSampleToken, appropriate_origin_, kAppropriateFeatureName));
+}
+
+TEST_F(TrialTokenValidatorTest, ValidateInappropriateOrigin) {
+ EXPECT_FALSE(TrialTokenValidator::ValidateToken(
+ kSampleToken, inappropriate_origin_, kAppropriateFeatureName));
+ EXPECT_FALSE(TrialTokenValidator::ValidateToken(
+ kSampleToken, insecure_origin_, kAppropriateFeatureName));
+}
+
+TEST_F(TrialTokenValidatorTest, ValidateInappropriateFeature) {
+ EXPECT_FALSE(TrialTokenValidator::ValidateToken(
+ kSampleToken, appropriate_origin_, kInappropriateFeatureName));
+}
+
+TEST_F(TrialTokenValidatorTest, ValidateInvalidSignature) {
+ EXPECT_FALSE(TrialTokenValidator::ValidateToken(
+ kInvalidSignatureToken, appropriate_origin_, kAppropriateFeatureName));
+}
+
+TEST_F(TrialTokenValidatorTest, ValidateUnparsableToken) {
+ EXPECT_FALSE(TrialTokenValidator::ValidateToken(
+ kUnparsableToken, appropriate_origin_, kAppropriateFeatureName));
+}
+
+TEST_F(TrialTokenValidatorTest, ValidateExpiredToken) {
+ EXPECT_FALSE(TrialTokenValidator::ValidateToken(
+ kExpiredToken, appropriate_origin_, kAppropriateFeatureName));
+}
+
+TEST_F(TrialTokenValidatorTest, ValidateValidTokenWithIncorrectKey) {
+ SetPublicKey(kTestPublicKey2);
+ EXPECT_FALSE(TrialTokenValidator::ValidateToken(
+ kSampleToken, appropriate_origin_, kAppropriateFeatureName));
+}
+
+} // namespace content
diff --git a/chromium/content/common/origin_util.cc b/chromium/content/common/origin_util.cc
index 9c6b6310f22..4dfdc6ce8ca 100644
--- a/chromium/content/common/origin_util.cc
+++ b/chromium/content/common/origin_util.cc
@@ -8,7 +8,7 @@
#include "base/macros.h"
#include "base/stl_util.h"
#include "content/public/common/content_client.h"
-#include "net/base/net_util.h"
+#include "net/base/url_util.h"
#include "url/gurl.h"
namespace content {
diff --git a/chromium/content/common/p2p_messages.h b/chromium/content/common/p2p_messages.h
index 24daee51f07..9725b257cff 100644
--- a/chromium/content/common/p2p_messages.h
+++ b/chromium/content/common/p2p_messages.h
@@ -11,6 +11,7 @@
#include "content/common/content_export.h"
#include "content/common/p2p_socket_type.h"
#include "ipc/ipc_message_macros.h"
+#include "net/base/ip_address.h"
#include "net/base/network_interfaces.h"
#include "third_party/webrtc/base/asyncpacketsocket.h"
@@ -62,8 +63,8 @@ IPC_STRUCT_TRAITS_END()
IPC_MESSAGE_CONTROL3(P2PMsg_NetworkListChanged,
net::NetworkInterfaceList /* networks */,
- net::IPAddressNumber /* default_ipv4_local_address */,
- net::IPAddressNumber /* default_ipv6_local_address */)
+ net::IPAddress /* default_ipv4_local_address */,
+ net::IPAddress /* default_ipv6_local_address */)
IPC_MESSAGE_CONTROL2(P2PMsg_GetHostAddressResult,
int32_t /* request_id */,
diff --git a/chromium/content/common/page_messages.h b/chromium/content/common/page_messages.h
new file mode 100644
index 00000000000..284c134508b
--- /dev/null
+++ b/chromium/content/common/page_messages.h
@@ -0,0 +1,25 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ipc/ipc_message_macros.h"
+
+// IPC messages for page-level actions.
+// Multiply-included message file, hence no include guard.
+
+#undef IPC_MESSAGE_EXPORT
+#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
+
+#define IPC_MESSAGE_START PageMsgStart
+
+// Messages sent from the browser to the renderer.
+
+IPC_MESSAGE_ROUTED1(PageMsg_UpdateWindowScreenRect,
+ gfx::Rect /* window_screen_rect */)
+
+// -----------------------------------------------------------------------------
+// Messages sent from the renderer to the browser.
+
+// Adding a new message? Stick to the sort order above: first platform
+// independent PageMsg, then ifdefs for platform specific PageMsg, then platform
+// independent PageHostMsg, then ifdefs for platform specific PageHostMsg.
diff --git a/chromium/content/common/page_state_serialization.cc b/chromium/content/common/page_state_serialization.cc
index 53ddf098d16..b9670c2f244 100644
--- a/chromium/content/common/page_state_serialization.cc
+++ b/chromium/content/common/page_state_serialization.cc
@@ -606,8 +606,7 @@ void ReadFrameState(SerializeObject* obj, bool is_top,
float device_scale_factor = g_device_scale_factor_for_testing;
if (!device_scale_factor) {
device_scale_factor =
- gfx::Screen::GetNativeScreen()->GetPrimaryDisplay().
- device_scale_factor();
+ gfx::Screen::GetScreen()->GetPrimaryDisplay().device_scale_factor();
}
state->scroll_offset =
gfx::Point(state->scroll_offset.x() / state->page_scale_factor,
@@ -672,6 +671,9 @@ ExplodedHttpBodyElement::ExplodedHttpBodyElement()
file_modification_time(std::numeric_limits<double>::quiet_NaN()) {
}
+ExplodedHttpBodyElement::ExplodedHttpBodyElement(
+ const ExplodedHttpBodyElement& other) = default;
+
ExplodedHttpBodyElement::~ExplodedHttpBodyElement() {
}
diff --git a/chromium/content/common/page_state_serialization.h b/chromium/content/common/page_state_serialization.h
index 9b6773c2303..24d81981ef8 100644
--- a/chromium/content/common/page_state_serialization.h
+++ b/chromium/content/common/page_state_serialization.h
@@ -32,6 +32,7 @@ struct CONTENT_EXPORT ExplodedHttpBodyElement {
std::string blob_uuid;
ExplodedHttpBodyElement();
+ ExplodedHttpBodyElement(const ExplodedHttpBodyElement& other);
~ExplodedHttpBodyElement();
};
diff --git a/chromium/content/common/pepper_plugin_list.cc b/chromium/content/common/pepper_plugin_list.cc
index ea24ff7eb97..610670e20b2 100644
--- a/chromium/content/common/pepper_plugin_list.cc
+++ b/chromium/content/common/pepper_plugin_list.cc
@@ -54,7 +54,8 @@ void ComputePluginsFromCommandLine(std::vector<PepperPluginInfo>* plugins) {
// plugin-entry =
// <file-path> +
// ["#" + <name> + ["#" + <description> + ["#" + <version>]]] +
- // *1( LWS + ";" + LWS + <mime-type> )
+ // *1( LWS + ";" + LWS + <mime-type-data> )
+ // mime-type-data = <mime-type> + [ LWS + "#" + LWS + <extension> ]
std::vector<std::string> modules = base::SplitString(
value, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
@@ -105,8 +106,14 @@ void ComputePluginsFromCommandLine(std::vector<PepperPluginInfo>* plugins) {
if (name_parts.size() > 3)
plugin.version = name_parts[3];
for (size_t j = 1; j < parts.size(); ++j) {
- WebPluginMimeType mime_type(parts[j],
- std::string(),
+ std::vector<std::string> mime_parts = base::SplitString(
+ parts[j], "#", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ DCHECK_GE(mime_parts.size(), 1u);
+ std::string mime_extension;
+ if (mime_parts.size() > 1)
+ mime_extension = mime_parts[1];
+ WebPluginMimeType mime_type(mime_parts[0],
+ mime_extension,
plugin.description);
plugin.mime_types.push_back(mime_type);
}
diff --git a/chromium/content/common/permission_service.mojom b/chromium/content/common/permission_service.mojom
deleted file mode 100644
index 5a6178793c5..00000000000
--- a/chromium/content/common/permission_service.mojom
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module content;
-
-import "content/public/common/permission_status.mojom";
-
-enum PermissionName {
- GEOLOCATION,
- NOTIFICATIONS,
- PUSH_NOTIFICATIONS,
- MIDI,
- MIDI_SYSEX,
- PROTECTED_MEDIA_IDENTIFIER,
- DURABLE_STORAGE,
- AUDIO_CAPTURE,
- VIDEO_CAPTURE,
-};
-
-// The Permission service provides permission handling capabilities by exposing
-// methods to check, request, and revoke permissions. It also allows a client to
-// start listening to permission changes.
-interface PermissionService {
- HasPermission(PermissionName permission, string origin)
- => (PermissionStatus status);
- RequestPermission(PermissionName permission, string origin, bool user_gesture)
- => (PermissionStatus status);
- RequestPermissions(array<PermissionName> permission, string origin, bool user_gesture)
- => (array<PermissionStatus> statuses);
- RevokePermission(PermissionName permission, string origin)
- => (PermissionStatus status);
-
- // Runs the callback next time there is a permission status change for the
- // given { permission, origin }. Callers of this method will have to call it
- // again if they want to keep listening to the changes. To prevent race
- // conditions, the caller must pass the last known value.
- GetNextPermissionChange(PermissionName permission,
- string origin,
- PermissionStatus last_known_status)
- => (PermissionStatus status);
-};
diff --git a/chromium/content/common/platform_notification_messages.h b/chromium/content/common/platform_notification_messages.h
index 8b8d7dad421..5e5d8bb65f7 100644
--- a/chromium/content/common/platform_notification_messages.h
+++ b/chromium/content/common/platform_notification_messages.h
@@ -10,6 +10,7 @@
#include <utility>
#include <vector>
+#include "content/public/common/notification_resources.h"
#include "content/public/common/platform_notification_data.h"
#include "ipc/ipc_message_macros.h"
#include "third_party/WebKit/public/platform/modules/notifications/WebNotificationPermission.h"
@@ -35,9 +36,15 @@ IPC_ENUM_TRAITS_MAX_VALUE(
content::PlatformNotificationData::Direction,
content::PlatformNotificationData::DIRECTION_LAST)
+IPC_ENUM_TRAITS_MAX_VALUE(content::PlatformNotificationActionType,
+ content::PLATFORM_NOTIFICATION_ACTION_TYPE_TEXT)
+
IPC_STRUCT_TRAITS_BEGIN(content::PlatformNotificationAction)
+ IPC_STRUCT_TRAITS_MEMBER(type)
IPC_STRUCT_TRAITS_MEMBER(action)
IPC_STRUCT_TRAITS_MEMBER(title)
+ IPC_STRUCT_TRAITS_MEMBER(icon)
+ IPC_STRUCT_TRAITS_MEMBER(placeholder)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(content::PlatformNotificationData)
@@ -47,13 +54,22 @@ IPC_STRUCT_TRAITS_BEGIN(content::PlatformNotificationData)
IPC_STRUCT_TRAITS_MEMBER(body)
IPC_STRUCT_TRAITS_MEMBER(tag)
IPC_STRUCT_TRAITS_MEMBER(icon)
+ IPC_STRUCT_TRAITS_MEMBER(badge)
IPC_STRUCT_TRAITS_MEMBER(vibration_pattern)
+ IPC_STRUCT_TRAITS_MEMBER(timestamp)
+ IPC_STRUCT_TRAITS_MEMBER(renotify)
IPC_STRUCT_TRAITS_MEMBER(silent)
IPC_STRUCT_TRAITS_MEMBER(require_interaction)
IPC_STRUCT_TRAITS_MEMBER(data)
IPC_STRUCT_TRAITS_MEMBER(actions)
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_TRAITS_BEGIN(content::NotificationResources)
+ IPC_STRUCT_TRAITS_MEMBER(notification_icon)
+ IPC_STRUCT_TRAITS_MEMBER(badge)
+ IPC_STRUCT_TRAITS_MEMBER(action_icons)
+IPC_STRUCT_TRAITS_END()
+
// Messages sent from the browser to the renderer.
// Informs the renderer that the browser has displayed the notification.
@@ -84,18 +100,20 @@ IPC_MESSAGE_CONTROL2(PlatformNotificationMsg_DidGetNotifications,
// Messages sent from the renderer to the browser.
-IPC_MESSAGE_CONTROL4(PlatformNotificationHostMsg_Show,
- int /* notification_id */,
- GURL /* origin */,
- SkBitmap /* icon */,
- content::PlatformNotificationData /* notification_data */)
-
-IPC_MESSAGE_CONTROL5(PlatformNotificationHostMsg_ShowPersistent,
- int /* request_id */,
- int64_t /* service_worker_registration_id */,
- GURL /* origin */,
- SkBitmap /* icon */,
- content::PlatformNotificationData /* notification_data */)
+IPC_MESSAGE_CONTROL4(
+ PlatformNotificationHostMsg_Show,
+ int /* notification_id */,
+ GURL /* origin */,
+ content::PlatformNotificationData /* notification_data */,
+ content::NotificationResources /* notification_resources */)
+
+IPC_MESSAGE_CONTROL5(
+ PlatformNotificationHostMsg_ShowPersistent,
+ int /* request_id */,
+ int64_t /* service_worker_registration_id */,
+ GURL /* origin */,
+ content::PlatformNotificationData /* notification_data */,
+ content::NotificationResources /* notification_resources */)
IPC_MESSAGE_CONTROL4(PlatformNotificationHostMsg_GetNotifications,
int /* request_id */,
diff --git a/chromium/content/common/plugin_constants_win.cc b/chromium/content/common/plugin_constants_win.cc
deleted file mode 100644
index 026885677e2..00000000000
--- a/chromium/content/common/plugin_constants_win.cc
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/plugin_constants_win.h"
-
-namespace content {
-
-const base::char16 kNativeWindowClassName[] = L"NativeWindowClass";
-const base::char16 kWrapperNativeWindowClassName[] =
- L"WrapperNativeWindowClass";
-const base::char16 kDummyActivationWindowName[] = L"DummyWindowForActivation";
-const base::char16 kPaintMessageName[] = L"Chrome_CustomPaintil";
-const base::char16 kRegistryMozillaPlugins[] = L"SOFTWARE\\MozillaPlugins";
-const base::char16 kMozillaActiveXPlugin[] = L"npmozax.dll";
-const base::char16 kNewWMPPlugin[] = L"np-mswmp.dll";
-const base::char16 kOldWMPPlugin[] = L"npdsplay.dll";
-const base::char16 kYahooApplicationStatePlugin[] = L"npystate.dll";
-const base::char16 kWanWangProtocolHandlerPlugin[] = L"npww.dll";
-const base::char16 kFlashPlugin[] = L"npswf32.dll";
-const base::char16 kAcrobatReaderPlugin[] = L"nppdf32.dll";
-const base::char16 kRealPlayerPlugin[] = L"nppl3260.dll";
-const base::char16 kSilverlightPlugin[] = L"npctrl.dll";
-const base::char16 kJavaPlugin1[] = L"npjp2.dll";
-const base::char16 kJavaPlugin2[] = L"npdeploytk.dll";
-const char kGPUPluginMimeType[] = "application/vnd.google.chrome.gpu-plugin";
-const base::char16 kPluginDummyParentProperty[] = L"NPAPIPluginDummyParent";
-
-} // namespace content
diff --git a/chromium/content/common/plugin_constants_win.h b/chromium/content/common/plugin_constants_win.h
deleted file mode 100644
index 2269592d5ae..00000000000
--- a/chromium/content/common/plugin_constants_win.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_PLUGIN_CONSTANTS_WIN_H_
-#define CONTENT_COMMON_PLUGIN_CONSTANTS_WIN_H_
-
-#include "base/strings/string16.h"
-#include "build/build_config.h"
-
-#if !defined(OS_WIN)
-#error "Windows-only header"
-#endif
-
-namespace content {
-
-// The window class name for a plugin window.
-extern const base::char16 kNativeWindowClassName[];
-
-// The name of the window class name for the wrapper HWND around the actual
-// plugin window that's used when running in multi-process mode. This window
-// is created on the browser UI thread.
-extern const base::char16 kWrapperNativeWindowClassName[];
-
-extern const base::char16 kDummyActivationWindowName[];
-
-// The name of the custom window message that the browser uses to tell the
-// plugin process to paint a window.
-extern const base::char16 kPaintMessageName[];
-
-// The name of the registry key which NPAPI plugins update on installation.
-extern const base::char16 kRegistryMozillaPlugins[];
-
-extern const base::char16 kMozillaActiveXPlugin[];
-extern const base::char16 kNewWMPPlugin[];
-extern const base::char16 kOldWMPPlugin[];
-extern const base::char16 kYahooApplicationStatePlugin[];
-extern const base::char16 kWanWangProtocolHandlerPlugin[];
-extern const base::char16 kFlashPlugin[];
-extern const base::char16 kAcrobatReaderPlugin[];
-extern const base::char16 kRealPlayerPlugin[];
-extern const base::char16 kSilverlightPlugin[];
-extern const base::char16 kJavaPlugin1[];
-extern const base::char16 kJavaPlugin2[];
-
-extern const char kGPUPluginMimeType[];
-
-extern const base::char16 kPluginDummyParentProperty[];
-
-} // namespace content
-
-#endif // CONTENT_COMMON_PLUGIN_CONSTANTS_WIN_H_
diff --git a/chromium/content/common/plugin_list.cc b/chromium/content/common/plugin_list.cc
index 80438818181..eff0f66b269 100644
--- a/chromium/content/common/plugin_list.cc
+++ b/chromium/content/common/plugin_list.cc
@@ -20,10 +20,6 @@
#include "net/base/mime_util.h"
#include "url/gurl.h"
-#if defined(OS_WIN)
-#include "content/common/plugin_constants_win.h"
-#endif
-
namespace content {
namespace {
@@ -37,42 +33,11 @@ PluginList* PluginList::Singleton() {
return g_singleton.Pointer();
}
-// static
-bool PluginList::DebugPluginLoading() {
- return base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDebugPluginLoading);
-}
-
-void PluginList::DisablePluginsDiscovery() {
- plugins_discovery_disabled_ = true;
-}
-
void PluginList::RefreshPlugins() {
base::AutoLock lock(lock_);
loading_state_ = LOADING_STATE_NEEDS_REFRESH;
}
-void PluginList::AddExtraPluginPath(const base::FilePath& plugin_path) {
- // Chrome OS only loads plugins from /opt/google/chrome/plugins.
-#if !defined(OS_CHROMEOS)
- base::AutoLock lock(lock_);
- extra_plugin_paths_.push_back(plugin_path);
-#endif
-}
-
-void PluginList::RemoveExtraPluginPath(const base::FilePath& plugin_path) {
- base::AutoLock lock(lock_);
- RemoveExtraPluginPathLocked(plugin_path);
-}
-
-void PluginList::AddExtraPluginDir(const base::FilePath& plugin_dir) {
- // Chrome OS only loads plugins from /opt/google/chrome/plugins.
-#if !defined(OS_CHROMEOS)
- base::AutoLock lock(lock_);
- extra_plugin_dirs_.push_back(plugin_dir);
-#endif
-}
-
void PluginList::RegisterInternalPlugin(const WebPluginInfo& info,
bool add_at_beginning) {
base::AutoLock lock(lock_);
@@ -114,70 +79,18 @@ void PluginList::GetInternalPlugins(
bool PluginList::ReadPluginInfo(const base::FilePath& filename,
WebPluginInfo* info) {
- {
- base::AutoLock lock(lock_);
- for (size_t i = 0; i < internal_plugins_.size(); ++i) {
- if (filename == internal_plugins_[i].path) {
- *info = internal_plugins_[i];
- return true;
- }
- }
- }
-
- return PluginList::ReadWebPluginInfo(filename, info);
-}
-
-// static
-bool PluginList::ParseMimeTypes(
- const std::string& mime_types_str,
- const std::string& file_extensions_str,
- const base::string16& mime_type_descriptions_str,
- std::vector<WebPluginMimeType>* parsed_mime_types) {
- std::vector<std::string> mime_types = base::SplitString(
- mime_types_str, "|", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- std::vector<std::string> file_extensions = base::SplitString(
- file_extensions_str, "|", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- std::vector<base::string16> descriptions = base::SplitString(
- mime_type_descriptions_str, base::string16(1, '|'), base::TRIM_WHITESPACE,
- base::SPLIT_WANT_ALL);
-
- parsed_mime_types->clear();
-
- if (mime_types.empty())
- return false;
-
- for (size_t i = 0; i < mime_types.size(); ++i) {
- WebPluginMimeType mime_type;
- mime_type.mime_type = base::ToLowerASCII(mime_types[i]);
- if (file_extensions.size() > i) {
- mime_type.file_extensions = base::SplitString(
- file_extensions[i], ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- }
-
- if (descriptions.size() > i) {
- mime_type.description = descriptions[i];
-
- // On Windows, the description likely has a list of file extensions
- // embedded in it (e.g. "SurfWriter file (*.swr)"). Remove an extension
- // list from the description if it is present.
- size_t ext = mime_type.description.find(base::ASCIIToUTF16("(*"));
- if (ext != base::string16::npos) {
- if (ext > 1 && mime_type.description[ext - 1] == ' ')
- ext--;
-
- mime_type.description.erase(ext);
- }
+ base::AutoLock lock(lock_);
+ for (const auto& plugin : internal_plugins_) {
+ if (filename == plugin.path) {
+ *info = plugin;
+ return true;
}
-
- parsed_mime_types->push_back(mime_type);
}
-
- return true;
+ return false;
}
PluginList::PluginList()
- : loading_state_(LOADING_STATE_NEEDS_REFRESH),
- plugins_discovery_disabled_(false) {
+ : loading_state_(LOADING_STATE_NEEDS_REFRESH) {
}
bool PluginList::PrepareForPluginLoading() {
@@ -189,7 +102,7 @@ bool PluginList::PrepareForPluginLoading() {
return true;
}
-void PluginList::LoadPlugins(bool include_npapi) {
+void PluginList::LoadPlugins() {
if (!PrepareForPluginLoading())
return;
@@ -203,7 +116,7 @@ void PluginList::LoadPlugins(bool include_npapi) {
will_load_callback.Run();
std::vector<base::FilePath> plugin_paths;
- GetPluginPathsToLoad(&plugin_paths, include_npapi);
+ GetPluginPathsToLoad(&plugin_paths);
for (std::vector<base::FilePath>::const_iterator it = plugin_paths.begin();
it != plugin_paths.end();
@@ -219,41 +132,30 @@ bool PluginList::LoadPluginIntoPluginList(
const base::FilePath& path,
std::vector<WebPluginInfo>* plugins,
WebPluginInfo* plugin_info) {
- LOG_IF(ERROR, PluginList::DebugPluginLoading())
- << "Loading plugin " << path.value();
if (!ReadPluginInfo(path, plugin_info))
return false;
- if (!ShouldLoadPluginUsingPluginList(*plugin_info, plugins))
- return false;
-
-#if defined(OS_WIN) && !defined(NDEBUG)
- if (path.BaseName().value() != L"npspy.dll") // Make an exception for NPSPY
-#endif
- {
- for (size_t i = 0; i < plugin_info->mime_types.size(); ++i) {
- // TODO: don't load global handlers for now.
- // WebKit hands to the Plugin before it tries
- // to handle mimeTypes on its own.
- const std::string &mime_type = plugin_info->mime_types[i].mime_type;
- if (mime_type == "*")
- return false;
- }
+ // TODO(piman): Do we still need this after NPAPI removal?
+ for (size_t i = 0; i < plugin_info->mime_types.size(); ++i) {
+ // TODO: don't load global handlers for now.
+ // WebKit hands to the Plugin before it tries
+ // to handle mimeTypes on its own.
+ const std::string &mime_type = plugin_info->mime_types[i].mime_type;
+ if (mime_type == "*")
+ return false;
}
plugins->push_back(*plugin_info);
return true;
}
-void PluginList::GetPluginPathsToLoad(std::vector<base::FilePath>* plugin_paths,
- bool include_npapi) {
+void PluginList::GetPluginPathsToLoad(
+ std::vector<base::FilePath>* plugin_paths) {
// Don't want to hold the lock while loading new plugins, so we don't block
// other methods if they're called on other threads.
std::vector<base::FilePath> extra_plugin_paths;
- std::vector<base::FilePath> extra_plugin_dirs;
{
base::AutoLock lock(lock_);
extra_plugin_paths = extra_plugin_paths_;
- extra_plugin_dirs = extra_plugin_dirs_;
}
for (size_t i = 0; i < extra_plugin_paths.size(); ++i) {
@@ -264,22 +166,6 @@ void PluginList::GetPluginPathsToLoad(std::vector<base::FilePath>* plugin_paths,
}
plugin_paths->push_back(path);
}
-
- if (include_npapi) {
- // A bit confusingly, this function is used to load Pepper plugins as well.
- // Those are all internal plugins so we have to use extra_plugin_paths.
- for (size_t i = 0; i < extra_plugin_dirs.size(); ++i)
- GetPluginsInDir(extra_plugin_dirs[i], plugin_paths);
-
- std::vector<base::FilePath> directories_to_scan;
- GetPluginDirectories(&directories_to_scan);
- for (size_t i = 0; i < directories_to_scan.size(); ++i)
- GetPluginsInDir(directories_to_scan[i], plugin_paths);
-
-#if defined(OS_WIN)
- GetPluginPathsFromRegistry(plugin_paths);
-#endif
- }
}
void PluginList::SetPlugins(const std::vector<WebPluginInfo>& plugins) {
@@ -298,9 +184,8 @@ void PluginList::set_will_load_plugins_callback(const base::Closure& callback) {
will_load_plugins_callback_ = callback;
}
-void PluginList::GetPlugins(std::vector<WebPluginInfo>* plugins,
- bool include_npapi) {
- LoadPlugins(include_npapi);
+void PluginList::GetPlugins(std::vector<WebPluginInfo>* plugins) {
+ LoadPlugins();
base::AutoLock lock(lock_);
plugins->insert(plugins->end(), plugins_list_.begin(), plugins_list_.end());
}
@@ -317,14 +202,13 @@ void PluginList::GetPluginInfoArray(
const std::string& mime_type,
bool allow_wildcard,
bool* use_stale,
- bool include_npapi,
std::vector<WebPluginInfo>* info,
std::vector<std::string>* actual_mime_types) {
DCHECK(mime_type == base::ToLowerASCII(mime_type));
DCHECK(info);
if (!use_stale)
- LoadPlugins(include_npapi);
+ LoadPlugins();
base::AutoLock lock(lock_);
if (use_stale)
*use_stale = (loading_state_ != LOADING_STATE_UP_TO_DATE);
diff --git a/chromium/content/common/plugin_list.h b/chromium/content/common/plugin_list.h
index 0b31ab0d7e1..b18b061043b 100644
--- a/chromium/content/common/plugin_list.h
+++ b/chromium/content/common/plugin_list.h
@@ -40,35 +40,16 @@ class CONTENT_EXPORT PluginList {
// Gets the one instance of the PluginList.
static PluginList* Singleton();
- // Returns true if we're in debug-plugin-loading mode. This is controlled
- // by a command line switch.
- static bool DebugPluginLoading();
-
// Returns true if the plugin supports |mime_type|. |mime_type| should be all
// lower case.
static bool SupportsType(const WebPluginInfo& plugin,
const std::string& mime_type,
bool allow_wildcard);
- // Disables discovery of third_party plugins in standard places next time
- // plugins are loaded.
- void DisablePluginsDiscovery();
-
// Cause the plugin list to refresh next time they are accessed, regardless
// of whether they are already loaded.
void RefreshPlugins();
- // Add/Remove an extra plugin to load when we actually do the loading. Must
- // be called before the plugins have been loaded.
- void AddExtraPluginPath(const base::FilePath& plugin_path);
- void RemoveExtraPluginPath(const base::FilePath& plugin_path);
-
- // Same as above, but specifies a directory in which to search for plugins.
- void AddExtraPluginDir(const base::FilePath& plugin_dir);
-
- // Get the ordered list of directories from which to load plugins
- void GetPluginDirectories(std::vector<base::FilePath>* plugin_dirs);
-
// Register an internal plugin with the specified plugin information.
// An internal plugin must be registered before it can
// be loaded using PluginList::LoadPlugin().
@@ -90,19 +71,8 @@ class CONTENT_EXPORT PluginList {
bool ReadPluginInfo(const base::FilePath& filename,
WebPluginInfo* info);
- // In Windows plugins, the mime types are passed as a specially formatted list
- // of strings. This function parses those strings into a WebPluginMimeType
- // vector.
- // TODO(evan): move this code into plugin_list_win.
- static bool ParseMimeTypes(
- const std::string& mime_types,
- const std::string& file_extensions,
- const base::string16& mime_type_descriptions,
- std::vector<WebPluginMimeType>* parsed_mime_types);
-
// Get all the plugins synchronously, loading them if necessary.
- void GetPlugins(std::vector<WebPluginInfo>* plugins,
- bool include_npapi);
+ void GetPlugins(std::vector<WebPluginInfo>* plugins);
// Copies the list of plugins into |plugins| without loading them.
// Returns true if the list of plugins is up-to-date.
@@ -124,7 +94,6 @@ class CONTENT_EXPORT PluginList {
const std::string& mime_type,
bool allow_wildcard,
bool* use_stale,
- bool include_npapi,
std::vector<WebPluginInfo>* info,
std::vector<std::string>* actual_mime_types);
@@ -138,8 +107,7 @@ class CONTENT_EXPORT PluginList {
// using a different instance of this class.
// Computes a list of all plugins to potentially load from all sources.
- void GetPluginPathsToLoad(std::vector<base::FilePath>* plugin_paths,
- bool include_npapi);
+ void GetPluginPathsToLoad(std::vector<base::FilePath>* plugin_paths);
// Signals that plugin loading will start. This method should be called before
// loading plugins with a different instance of this class. Returns false if
@@ -155,12 +123,6 @@ class CONTENT_EXPORT PluginList {
virtual ~PluginList();
- // Creates a WebPluginInfo structure given a plugin's path. On success
- // returns true, with the information being put into "info".
- // Returns false if the library couldn't be found, or if it's not a plugin.
- static bool ReadWebPluginInfo(const base::FilePath& filename,
- WebPluginInfo* info);
-
private:
enum LoadingState {
LOADING_STATE_NEEDS_REFRESH,
@@ -174,18 +136,7 @@ class CONTENT_EXPORT PluginList {
PluginList();
// Load all plugins from the default plugins directory.
- void LoadPlugins(bool include_npapi);
-
- // Walks a directory and produces a list of all the plugins to potentially
- // load in that directory.
- void GetPluginsInDir(const base::FilePath& path,
- std::vector<base::FilePath>* plugins);
-
- // Returns true if we should load the given plugin, or false otherwise.
- // |plugins| is the list of plugins we have crawled in the current plugin
- // loading run.
- bool ShouldLoadPluginUsingPluginList(const WebPluginInfo& info,
- std::vector<WebPluginInfo>* plugins);
+ void LoadPlugins();
// Returns true if the given plugin supports a given file extension.
// |extension| should be all lower case. If |mime_type| is not NULL, it will
@@ -200,16 +151,6 @@ class CONTENT_EXPORT PluginList {
void RemoveExtraPluginPathLocked(const base::FilePath& plugin_path);
//
- // Command-line switches
- //
-
-#if defined(OS_WIN)
- // Gets plugin paths registered under HKCU\Software\MozillaPlugins and
- // HKLM\Software\MozillaPlugins.
- void GetPluginPathsFromRegistry(std::vector<base::FilePath>* plugins);
-#endif
-
- //
// Internals
//
@@ -221,9 +162,6 @@ class CONTENT_EXPORT PluginList {
// Extra plugin paths that we want to search when loading.
std::vector<base::FilePath> extra_plugin_paths_;
- // Extra plugin directories that we want to search when loading.
- std::vector<base::FilePath> extra_plugin_dirs_;
-
// Holds information about internal plugins.
std::vector<WebPluginInfo> internal_plugins_;
@@ -237,10 +175,6 @@ class CONTENT_EXPORT PluginList {
// accessed on multiple threads.
base::Lock lock_;
- // Flag indicating whether third_party plugins will be searched for
- // in common places.
- bool plugins_discovery_disabled_;
-
DISALLOW_COPY_AND_ASSIGN(PluginList);
};
diff --git a/chromium/content/common/plugin_list_mac.mm b/chromium/content/common/plugin_list_mac.mm
deleted file mode 100644
index b3d726c0d70..00000000000
--- a/chromium/content/common/plugin_list_mac.mm
+++ /dev/null
@@ -1,307 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/plugin_list.h"
-
-#import <Carbon/Carbon.h>
-#import <Foundation/Foundation.h>
-
-#include "base/files/file_enumerator.h"
-#include "base/files/file_util.h"
-#include "base/mac/mac_util.h"
-#include "base/mac/scoped_cftyperef.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/native_library.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-
-using base::ScopedCFTypeRef;
-
-namespace content {
-
-namespace {
-
-void GetPluginCommonDirectory(std::vector<base::FilePath>* plugin_dirs,
- bool user) {
- // Note that there are no NSSearchPathDirectory constants for these
- // directories so we can't use Cocoa's NSSearchPathForDirectoriesInDomains().
- // Interestingly, Safari hard-codes the location (see
- // WebKit/WebKit/mac/Plugins/WebPluginDatabase.mm's +_defaultPlugInPaths).
- FSRef ref;
- OSErr err = FSFindFolder(user ? kUserDomain : kLocalDomain,
- kInternetPlugInFolderType, false, &ref);
-
- if (err)
- return;
-
- plugin_dirs->push_back(base::FilePath(base::mac::PathFromFSRef(ref)));
-}
-
-// Returns true if the plugin should be prevented from loading.
-bool IsBlacklistedPlugin(const WebPluginInfo& info) {
- // We blacklist Gears by included MIME type, since that is more stable than
- // its name. Be careful about adding any more plugins to this list though,
- // since it's easy to accidentally blacklist plugins that support lots of
- // MIME types.
- for (const WebPluginMimeType& mime : info.mime_types) {
- // The Gears plugin is Safari-specific, so don't load it.
- if (mime.mime_type == "application/x-googlegears")
- return true;
- }
-
- // Versions of Flip4Mac 2.3 before 2.3.6 often hang the renderer, so don't
- // load them.
- if (base::StartsWith(info.name,
- base::ASCIIToUTF16("Flip4Mac Windows Media"),
- base::CompareCase::INSENSITIVE_ASCII) &&
- base::StartsWith(info.version, base::ASCIIToUTF16("2.3"),
- base::CompareCase::SENSITIVE)) {
- std::vector<base::StringPiece16> components = base::SplitStringPiece(
- info.version, base::ASCIIToUTF16("."), base::TRIM_WHITESPACE,
- base::SPLIT_WANT_ALL);
- int bugfix_version = 0;
- return (components.size() >= 3 &&
- base::StringToInt(components[2], &bugfix_version) &&
- bugfix_version < 6);
- }
-
- return false;
-}
-
-NSDictionary* GetMIMETypes(CFBundleRef bundle) {
- NSString* mime_filename =
- (NSString*)CFBundleGetValueForInfoDictionaryKey(bundle,
- CFSTR("WebPluginMIMETypesFilename"));
-
- if (mime_filename) {
-
- // get the file
-
- NSString* mime_path =
- [NSString stringWithFormat:@"%@/Library/Preferences/%@",
- NSHomeDirectory(), mime_filename];
- NSDictionary* mime_file_dict =
- [NSDictionary dictionaryWithContentsOfFile:mime_path];
-
- // is it valid?
-
- bool valid_file = false;
- if (mime_file_dict) {
- NSString* l10n_name =
- [mime_file_dict objectForKey:@"WebPluginLocalizationName"];
- NSString* preferred_l10n = [[NSLocale currentLocale] localeIdentifier];
- if ([l10n_name isEqualToString:preferred_l10n])
- valid_file = true;
- }
-
- if (valid_file)
- return [mime_file_dict objectForKey:@"WebPluginMIMETypes"];
-
- // dammit, I didn't want to have to do this
-
- typedef void (*CreateMIMETypesPrefsPtr)(void);
- CreateMIMETypesPrefsPtr create_prefs_file =
- (CreateMIMETypesPrefsPtr)CFBundleGetFunctionPointerForName(
- bundle, CFSTR("BP_CreatePluginMIMETypesPreferences"));
- if (!create_prefs_file)
- return nil;
- create_prefs_file();
-
- // one more time
-
- mime_file_dict = [NSDictionary dictionaryWithContentsOfFile:mime_path];
- if (mime_file_dict)
- return [mime_file_dict objectForKey:@"WebPluginMIMETypes"];
- else
- return nil;
-
- } else {
- return (NSDictionary*)CFBundleGetValueForInfoDictionaryKey(bundle,
- CFSTR("WebPluginMIMETypes"));
- }
-}
-
-bool ReadPlistPluginInfo(const base::FilePath& filename, CFBundleRef bundle,
- WebPluginInfo* info) {
- NSDictionary* mime_types = GetMIMETypes(bundle);
- if (!mime_types)
- return false; // no type info here; try elsewhere
-
- for (NSString* mime_type in [mime_types allKeys]) {
- NSDictionary* mime_dict = [mime_types objectForKey:mime_type];
- NSNumber* type_enabled = [mime_dict objectForKey:@"WebPluginTypeEnabled"];
- NSString* mime_desc = [mime_dict objectForKey:@"WebPluginTypeDescription"];
- NSArray* mime_exts = [mime_dict objectForKey:@"WebPluginExtensions"];
-
- // Skip any disabled types.
- if (type_enabled && ![type_enabled boolValue])
- continue;
-
- WebPluginMimeType mime;
- mime.mime_type = base::SysNSStringToUTF8([mime_type lowercaseString]);
- // Remove PDF from the list of types handled by QuickTime, since it provides
- // a worse experience than just downloading the PDF.
- if (mime.mime_type == "application/pdf" &&
- base::StartsWith(filename.BaseName().value(), "QuickTime",
- base::CompareCase::INSENSITIVE_ASCII)) {
- continue;
- }
-
- if (mime_desc)
- mime.description = base::SysNSStringToUTF16(mime_desc);
- for (NSString* ext in mime_exts)
- mime.file_extensions.push_back(
- base::SysNSStringToUTF8([ext lowercaseString]));
-
- info->mime_types.push_back(mime);
- }
-
- NSString* plugin_name =
- (NSString*)CFBundleGetValueForInfoDictionaryKey(bundle,
- CFSTR("WebPluginName"));
- NSString* plugin_vers =
- (NSString*)CFBundleGetValueForInfoDictionaryKey(bundle,
- CFSTR("CFBundleShortVersionString"));
- NSString* plugin_desc =
- (NSString*)CFBundleGetValueForInfoDictionaryKey(bundle,
- CFSTR("WebPluginDescription"));
-
- if (plugin_name)
- info->name = base::SysNSStringToUTF16(plugin_name);
- else
- info->name = base::UTF8ToUTF16(filename.BaseName().value());
- info->path = filename;
- if (plugin_vers)
- info->version = base::SysNSStringToUTF16(plugin_vers);
- if (plugin_desc)
- info->desc = base::SysNSStringToUTF16(plugin_desc);
- else
- info->desc = base::UTF8ToUTF16(filename.BaseName().value());
-
- return true;
-}
-
-} // namespace
-
-bool PluginList::ReadWebPluginInfo(const base::FilePath &filename,
- WebPluginInfo* info) {
- // There are three ways to get information about plugin capabilities:
- // 1) a set of Info.plist keys, documented at
- // http://developer.apple.com/documentation/InternetWeb/Conceptual/WebKit_PluginProgTopic/Concepts/AboutPlugins.html .
- // 2) a set of STR# resources, documented at
- // https://developer.mozilla.org/En/Gecko_Plugin_API_Reference/Plug-in_Development_Overview .
- // 3) a NP_GetMIMEDescription() entry point, documented at
- // https://developer.mozilla.org/en/NP_GetMIMEDescription
- //
- // Mozilla supported (3), but WebKit never has, so no plugins rely on it. Most
- // browsers supported (2) and then added support for (1); Chromium originally
- // supported (2) and (1), but now supports only (1) as (2) is deprecated.
- //
- // For the Info.plist version, the data is formatted as follows (in text plist
- // format):
- // {
- // ... the usual plist keys ...
- // WebPluginDescription = <<plugindescription>>;
- // WebPluginMIMETypes = {
- // <<type0mimetype>> = {
- // WebPluginExtensions = (
- // <<type0fileextension0>>,
- // ...
- // <<type0fileextensionk>>,
- // );
- // WebPluginTypeDescription = <<type0description>>;
- // };
- // <<type1mimetype>> = { ... };
- // ...
- // <<typenmimetype>> = { ... };
- // };
- // WebPluginName = <<pluginname>>;
- // }
- //
- // Alternatively (and this is undocumented), rather than a WebPluginMIMETypes
- // key, there may be a WebPluginMIMETypesFilename key. If it is present, then
- // it is the name of a file in the user's preferences folder in which to find
- // the WebPluginMIMETypes key. If the key is present but the file doesn't
- // exist, we must load the plugin and call a specific function to have the
- // plugin create the file.
-
- ScopedCFTypeRef<CFURLRef> bundle_url(CFURLCreateFromFileSystemRepresentation(
- kCFAllocatorDefault, (const UInt8*)filename.value().c_str(),
- filename.value().length(), true));
- if (!bundle_url) {
- LOG_IF(ERROR, PluginList::DebugPluginLoading())
- << "PluginLib::ReadWebPluginInfo could not create bundle URL";
- return false;
- }
- ScopedCFTypeRef<CFBundleRef> bundle(CFBundleCreate(kCFAllocatorDefault,
- bundle_url.get()));
- if (!bundle) {
- LOG_IF(ERROR, PluginList::DebugPluginLoading())
- << "PluginLib::ReadWebPluginInfo could not create CFBundleRef";
- return false;
- }
-
- // preflight
-
- OSType type = 0;
- CFBundleGetPackageInfo(bundle.get(), &type, NULL);
- if (type != FOUR_CHAR_CODE('BRPL')) {
- LOG_IF(ERROR, PluginList::DebugPluginLoading())
- << "PluginLib::ReadWebPluginInfo bundle is not BRPL, is " << type;
- return false;
- }
-
- CFErrorRef error;
- Boolean would_load = CFBundlePreflightExecutable(bundle.get(), &error);
- if (!would_load) {
- ScopedCFTypeRef<CFStringRef> error_string(CFErrorCopyDescription(error));
- LOG_IF(ERROR, PluginList::DebugPluginLoading())
- << "PluginLib::ReadWebPluginInfo bundle failed preflight: "
- << base::SysCFStringRefToUTF8(error_string);
- return false;
- }
-
- // get the info
-
- if (ReadPlistPluginInfo(filename, bundle.get(), info))
- return true;
-
- // ... or not
-
- return false;
-}
-
-void PluginList::GetPluginDirectories(
- std::vector<base::FilePath>* plugin_dirs) {
- if (PluginList::plugins_discovery_disabled_)
- return;
-
- // Load from the user's area
- GetPluginCommonDirectory(plugin_dirs, true);
-
- // Load from the machine-wide area
- GetPluginCommonDirectory(plugin_dirs, false);
-}
-
-void PluginList::GetPluginsInDir(
- const base::FilePath& path, std::vector<base::FilePath>* plugins) {
- base::FileEnumerator enumerator(path,
- false, // not recursive
- base::FileEnumerator::DIRECTORIES);
- for (base::FilePath path = enumerator.Next(); !path.value().empty();
- path = enumerator.Next()) {
- plugins->push_back(path);
- }
-}
-
-bool PluginList::ShouldLoadPluginUsingPluginList(
- const WebPluginInfo& info,
- std::vector<WebPluginInfo>* plugins) {
- return !IsBlacklistedPlugin(info);
-}
-
-} // namespace content
diff --git a/chromium/content/common/plugin_list_posix.cc b/chromium/content/common/plugin_list_posix.cc
deleted file mode 100644
index 122fd59be42..00000000000
--- a/chromium/content/common/plugin_list_posix.cc
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/plugin_list.h"
-
-namespace content {
-
-bool PluginList::ReadWebPluginInfo(const base::FilePath& filename,
- WebPluginInfo* info) {
- return false;
-}
-
-void PluginList::GetPluginDirectories(
- std::vector<base::FilePath>* plugin_dirs) {
-}
-
-void PluginList::GetPluginsInDir(const base::FilePath& dir_path,
- std::vector<base::FilePath>* plugins) {
-}
-
-bool PluginList::ShouldLoadPluginUsingPluginList(
- const WebPluginInfo& info,
- std::vector<WebPluginInfo>* plugins) {
- LOG_IF(ERROR, PluginList::DebugPluginLoading())
- << "Considering " << info.path.value() << " (" << info.name << ")";
-
- if (info.type == WebPluginInfo::PLUGIN_TYPE_NPAPI) {
- NOTREACHED() << "NPAPI plugins are not supported";
- return false;
- }
-
- VLOG_IF(1, PluginList::DebugPluginLoading()) << "Using " << info.path.value();
- return true;
-}
-
-} // namespace content
diff --git a/chromium/content/common/plugin_list_unittest.cc b/chromium/content/common/plugin_list_unittest.cc
index 4b8150b499b..d28c0eb589b 100644
--- a/chromium/content/common/plugin_list_unittest.cc
+++ b/chromium/content/common/plugin_list_unittest.cc
@@ -52,7 +52,6 @@ class PluginListTest : public testing::Test {
}
void SetUp() override {
- plugin_list_.DisablePluginsDiscovery();
plugin_list_.RegisterInternalPlugin(bar_plugin_, false);
foo_plugin_.mime_types.push_back(
WebPluginMimeType(kFooMimeType, kFooFileType, std::string()));
@@ -67,7 +66,7 @@ class PluginListTest : public testing::Test {
TEST_F(PluginListTest, GetPlugins) {
std::vector<WebPluginInfo> plugins;
- plugin_list_.GetPlugins(&plugins, true);
+ plugin_list_.GetPlugins(&plugins);
EXPECT_EQ(2u, plugins.size());
EXPECT_TRUE(Contains(plugins, foo_plugin_));
EXPECT_TRUE(Contains(plugins, bar_plugin_));
@@ -82,7 +81,7 @@ TEST_F(PluginListTest, BadPluginDescription) {
// Now we should have them in the state we specified above.
plugin_list_.RefreshPlugins();
std::vector<WebPluginInfo> plugins;
- plugin_list_.GetPlugins(&plugins, true);
+ plugin_list_.GetPlugins(&plugins);
ASSERT_TRUE(Contains(plugins, plugin_3043));
}
@@ -99,7 +98,6 @@ TEST_F(PluginListTest, GetPluginInfoArray) {
"application/octet-stream",
false, // allow_wildcard
NULL, // use_stale
- false, // include_npapi
&plugins,
&actual_mime_types);
EXPECT_EQ(0u, plugins.size());
@@ -112,7 +110,6 @@ TEST_F(PluginListTest, GetPluginInfoArray) {
kFooMimeType,
false, // allow_wildcard
NULL, // use_stale
- false, // include_npapi
&plugins,
&actual_mime_types);
EXPECT_EQ(1u, plugins.size());
@@ -127,7 +124,6 @@ TEST_F(PluginListTest, GetPluginInfoArray) {
"",
false, // allow_wildcard
NULL, // use_stale
- false, // include_npapi
&plugins,
&actual_mime_types);
EXPECT_EQ(1u, plugins.size());
diff --git a/chromium/content/common/plugin_list_win.cc b/chromium/content/common/plugin_list_win.cc
deleted file mode 100644
index e96cc05698a..00000000000
--- a/chromium/content/common/plugin_list_win.cc
+++ /dev/null
@@ -1,493 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/plugin_list.h"
-
-#include <stddef.h>
-
-#include <set>
-
-#include "base/file_version_info.h"
-#include "base/file_version_info_win.h"
-#include "base/files/file_util.h"
-#include "base/files/memory_mapped_file.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/path_service.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/win/pe_image.h"
-#include "base/win/registry.h"
-#include "base/win/scoped_handle.h"
-#include "base/win/windows_version.h"
-#include "build/build_config.h"
-#include "content/common/plugin_constants_win.h"
-
-namespace content {
-namespace {
-
-const base::char16 kRegistryApps[] =
- L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths";
-const base::char16 kRegistryAcrobat[] = L"Acrobat.exe";
-const base::char16 kRegistryAcrobatReader[] = L"AcroRd32.exe";
-const base::char16 kRegistryWindowsMedia[] = L"wmplayer.exe";
-const base::char16 kRegistryQuickTime[] = L"QuickTimePlayer.exe";
-const base::char16 kRegistryPath[] = L"Path";
-const base::char16 kRegistryFirefoxInstalled[] =
- L"SOFTWARE\\Mozilla\\Mozilla Firefox";
-const base::char16 kRegistryJava[] =
- L"Software\\JavaSoft\\Java Runtime Environment";
-const base::char16 kRegistryBrowserJavaVersion[] = L"BrowserJavaVersion";
-const base::char16 kRegistryCurrentJavaVersion[] = L"CurrentVersion";
-const base::char16 kRegistryJavaHome[] = L"JavaHome";
-const base::char16 kJavaDeploy1[] = L"npdeploytk.dll";
-const base::char16 kJavaDeploy2[] = L"npdeployjava1.dll";
-
-base::FilePath AppendPluginsDir(const base::FilePath& path) {
- return path.AppendASCII("plugins");
-}
-
-// Gets the directory where the application data and libraries exist. This
-// may be a versioned subdirectory, or it may be the same directory as the
-// GetExeDirectory(), depending on the embedder's implementation.
-// Path is an output parameter to receive the path.
-void GetAppDirectory(std::set<base::FilePath>* plugin_dirs) {
- base::FilePath app_path;
- if (!PathService::Get(base::DIR_MODULE, &app_path))
- return;
- plugin_dirs->insert(AppendPluginsDir(app_path));
-}
-
-// Gets the directory where the launching executable resides on disk.
-// Path is an output parameter to receive the path.
-void GetExeDirectory(std::set<base::FilePath>* plugin_dirs) {
- base::FilePath exe_path;
- if (!PathService::Get(base::DIR_EXE, &exe_path))
- return;
- plugin_dirs->insert(AppendPluginsDir(exe_path));
-}
-
-// Gets the installed path for a registered app.
-bool GetInstalledPath(const base::char16* app, base::FilePath* out) {
- base::string16 reg_path(kRegistryApps);
- reg_path.append(L"\\");
- reg_path.append(app);
-
- base::win::RegKey hkcu_key(HKEY_CURRENT_USER, reg_path.c_str(), KEY_READ);
- base::string16 path;
- // As of Win7 AppPaths can also be registered in HKCU: http://goo.gl/UgFOf.
- if (base::win::GetVersion() >= base::win::VERSION_WIN7 &&
- hkcu_key.ReadValue(kRegistryPath, &path) == ERROR_SUCCESS) {
- *out = base::FilePath(path);
- return true;
- } else {
- base::win::RegKey hklm_key(HKEY_LOCAL_MACHINE, reg_path.c_str(), KEY_READ);
- if (hklm_key.ReadValue(kRegistryPath, &path) == ERROR_SUCCESS) {
- *out = base::FilePath(path);
- return true;
- }
- }
-
- return false;
-}
-
-// Search the registry at the given path and detect plugin directories.
-void GetPluginsInRegistryDirectory(HKEY root_key,
- const base::string16& registry_folder,
- REGSAM wow64_access,
- std::set<base::FilePath>* plugin_dirs) {
- for (base::win::RegistryKeyIterator iter(
- root_key, registry_folder.c_str(), wow64_access);
- iter.Valid();
- ++iter) {
- // Use the registry to gather plugin across the file system.
- base::string16 reg_path = registry_folder;
- reg_path.append(L"\\");
- reg_path.append(iter.Name());
- base::win::RegKey key(root_key, reg_path.c_str(), KEY_READ | wow64_access);
-
- base::string16 path;
- if (key.ReadValue(kRegistryPath, &path) == ERROR_SUCCESS)
- plugin_dirs->insert(base::FilePath(path));
- }
-}
-
-// Enumerate through the registry key to find all installed FireFox paths.
-// FireFox 3 beta and version 2 can coexist. See bug: 1025003
-void GetFirefoxInstalledPaths(std::vector<base::FilePath>* out) {
- base::win::RegistryKeyIterator it(HKEY_LOCAL_MACHINE,
- kRegistryFirefoxInstalled,
- KEY_WOW64_32KEY);
- for (; it.Valid(); ++it) {
- base::string16 full_path = base::string16(kRegistryFirefoxInstalled) +
- L"\\" + it.Name() + L"\\Main";
- base::win::RegKey key(HKEY_LOCAL_MACHINE, full_path.c_str(), KEY_READ);
- base::string16 install_dir;
- if (key.ReadValue(L"Install Directory", &install_dir) != ERROR_SUCCESS)
- continue;
- out->push_back(base::FilePath(install_dir));
- }
-}
-
-// Get plugin directory locations from the Firefox install path. This is kind
-// of a kludge, but it helps us locate the flash player for users that
-// already have it for firefox. Not having to download yet-another-plugin
-// is a good thing.
-void GetFirefoxDirectory(std::set<base::FilePath>* plugin_dirs) {
- std::vector<base::FilePath> paths;
- GetFirefoxInstalledPaths(&paths);
- for (unsigned int i = 0; i < paths.size(); ++i) {
- plugin_dirs->insert(AppendPluginsDir(paths[i]));
- }
-
- base::FilePath firefox_app_data_plugin_path;
- if (PathService::Get(base::DIR_APP_DATA, &firefox_app_data_plugin_path)) {
- firefox_app_data_plugin_path =
- firefox_app_data_plugin_path.AppendASCII("Mozilla");
- plugin_dirs->insert(AppendPluginsDir(firefox_app_data_plugin_path));
- }
-}
-
-// Hardcoded logic to detect Acrobat plugins locations.
-void GetAcrobatDirectory(std::set<base::FilePath>* plugin_dirs) {
- base::FilePath path;
- if (!GetInstalledPath(kRegistryAcrobatReader, &path) &&
- !GetInstalledPath(kRegistryAcrobat, &path)) {
- return;
- }
-
- plugin_dirs->insert(path.Append(L"Browser"));
-}
-
-// Hardcoded logic to detect QuickTime plugin location.
-void GetQuicktimeDirectory(std::set<base::FilePath>* plugin_dirs) {
- base::FilePath path;
- if (GetInstalledPath(kRegistryQuickTime, &path))
- plugin_dirs->insert(AppendPluginsDir(path));
-}
-
-// Hardcoded logic to detect Windows Media Player plugin location.
-void GetWindowsMediaDirectory(std::set<base::FilePath>* plugin_dirs) {
- base::FilePath path;
- if (GetInstalledPath(kRegistryWindowsMedia, &path))
- plugin_dirs->insert(path);
-}
-
-// Hardcoded logic to detect Java plugin location.
-void GetJavaDirectory(std::set<base::FilePath>* plugin_dirs) {
- // Load the new NPAPI Java plugin
- // 1. Open the main JRE key under HKLM
- base::win::RegKey java_key(HKEY_LOCAL_MACHINE, kRegistryJava,
- KEY_QUERY_VALUE);
-
- // 2. Read the current Java version
- base::string16 java_version;
- if (java_key.ReadValue(kRegistryBrowserJavaVersion, &java_version) !=
- ERROR_SUCCESS) {
- java_key.ReadValue(kRegistryCurrentJavaVersion, &java_version);
- }
-
- if (!java_version.empty()) {
- java_key.OpenKey(java_version.c_str(), KEY_QUERY_VALUE);
-
- // 3. Install path of the JRE binaries is specified in "JavaHome"
- // value under the Java version key.
- base::string16 java_plugin_directory;
- if (java_key.ReadValue(kRegistryJavaHome, &java_plugin_directory) ==
- ERROR_SUCCESS) {
- // 4. The new plugin resides under the 'bin/new_plugin'
- // subdirectory.
- DCHECK(!java_plugin_directory.empty());
- java_plugin_directory.append(L"\\bin\\new_plugin");
-
- // 5. We don't know the exact name of the DLL but it's in the form
- // NP*.dll so just invoke LoadPlugins on this path.
- plugin_dirs->insert(base::FilePath(java_plugin_directory));
- }
- }
-}
-
-bool IsValid32BitImage(const base::FilePath& path) {
- base::MemoryMappedFile plugin_image;
-
- if (!plugin_image.InitializeAsImageSection(path))
- return false;
-
- base::win::PEImage image(plugin_image.data());
-
- PIMAGE_NT_HEADERS nt_headers = image.GetNTHeaders();
- return (nt_headers->FileHeader.Machine == IMAGE_FILE_MACHINE_I386);
-}
-
-// Returns true if the given plugins share at least one mime type. This is used
-// to differentiate newer versions of a plugin vs two plugins which happen to
-// have the same filename.
-bool HaveSharedMimeType(const WebPluginInfo& plugin1,
- const WebPluginInfo& plugin2) {
- for (size_t i = 0; i < plugin1.mime_types.size(); ++i) {
- for (size_t j = 0; j < plugin2.mime_types.size(); ++j) {
- if (plugin1.mime_types[i].mime_type == plugin2.mime_types[j].mime_type)
- return true;
- }
- }
-
- return false;
-}
-
-// Compares Windows style version strings (i.e. 1,2,3,4). Returns true if b's
-// version is newer than a's, or false if it's equal or older.
-bool IsNewerVersion(const base::string16& a, const base::string16& b) {
- std::vector<base::string16> a_ver = base::SplitString(
- a, base::string16(1, ','), base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- std::vector<base::string16> b_ver = base::SplitString(
- b, base::string16(1, ','), base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- if (a_ver.size() == 1 && b_ver.size() == 1) {
- a_ver = base::SplitString(
- a, base::string16(1, '.'), base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- b_ver = base::SplitString(
- b, base::string16(1, '.'), base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- }
- if (a_ver.size() != b_ver.size())
- return false;
- for (size_t i = 0; i < a_ver.size(); i++) {
- int cur_a, cur_b;
- base::StringToInt(a_ver[i], &cur_a);
- base::StringToInt(b_ver[i], &cur_b);
-
- if (cur_a > cur_b)
- return false;
- if (cur_a < cur_b)
- return true;
- }
- return false;
-}
-
-} // namespace
-
-bool PluginList::ReadWebPluginInfo(const base::FilePath& filename,
- WebPluginInfo* info) {
- // On windows, the way we get the mime types for the library is
- // to check the version information in the DLL itself. This
- // will be a string of the format: <type1>|<type2>|<type3>|...
- // For example:
- // video/quicktime|audio/aiff|image/jpeg
- scoped_ptr<FileVersionInfo> version_info(
- FileVersionInfo::CreateFileVersionInfo(filename));
- if (!version_info) {
- LOG_IF(ERROR, PluginList::DebugPluginLoading())
- << "Could not get version info for plugin "
- << filename.value();
- return false;
- }
-
- FileVersionInfoWin* version_info_win =
- static_cast<FileVersionInfoWin*>(version_info.get());
-
- info->name = version_info->product_name();
- info->desc = version_info->file_description();
- info->version = version_info->file_version();
- info->path = filename;
-
- // TODO(evan): Move the ParseMimeTypes code inline once Pepper is updated.
- if (!PluginList::ParseMimeTypes(
- base::UTF16ToASCII(version_info_win->GetStringValue(L"MIMEType")),
- base::UTF16ToASCII(version_info_win->GetStringValue(L"FileExtents")),
- version_info_win->GetStringValue(L"FileOpenName"),
- &info->mime_types)) {
- LOG_IF(ERROR, PluginList::DebugPluginLoading())
- << "Plugin " << info->name << " has bad MIME types, skipping";
- return false;
- }
-
- return true;
-}
-
-void PluginList::GetPluginDirectories(
- std::vector<base::FilePath>* plugin_dirs) {
- if (PluginList::plugins_discovery_disabled_)
- return;
-
- // We use a set for uniqueness, which we require, over order, which we do not.
- std::set<base::FilePath> dirs;
-
- // Load from the application-specific area
- GetAppDirectory(&dirs);
-
- // Load from the executable area
- GetExeDirectory(&dirs);
-
- // Load Java
- GetJavaDirectory(&dirs);
-
- // Load firefox plugins too. This is mainly to try to locate
- // a pre-installed Flash player.
- GetFirefoxDirectory(&dirs);
-
- // Firefox hard-codes the paths of some popular plugins to ensure that
- // the plugins are found. We are going to copy this as well.
- GetAcrobatDirectory(&dirs);
- GetQuicktimeDirectory(&dirs);
- GetWindowsMediaDirectory(&dirs);
-
- for (std::set<base::FilePath>::iterator i = dirs.begin(); i != dirs.end(); ++i)
- plugin_dirs->push_back(*i);
-}
-
-void PluginList::GetPluginsInDir(
- const base::FilePath& path, std::vector<base::FilePath>* plugins) {
- WIN32_FIND_DATA find_file_data;
- HANDLE find_handle;
-
- base::string16 dir = path.value();
- // FindFirstFile requires that you specify a wildcard for directories.
- dir.append(L"\\NP*.DLL");
-
- find_handle = FindFirstFile(dir.c_str(), &find_file_data);
- if (find_handle == INVALID_HANDLE_VALUE)
- return;
-
- do {
- if (!(find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
- base::FilePath filename = path.Append(find_file_data.cFileName);
- plugins->push_back(filename);
- }
- } while (FindNextFile(find_handle, &find_file_data) != 0);
-
- DCHECK(GetLastError() == ERROR_NO_MORE_FILES);
- FindClose(find_handle);
-}
-
-void PluginList::GetPluginPathsFromRegistry(
- std::vector<base::FilePath>* plugins) {
- if (PluginList::plugins_discovery_disabled_)
- return;
-
- std::set<base::FilePath> plugin_dirs;
-
- // Search for plugins from HKCU and HKLM. THis will only find plugins that
- // are correctly registered in the correct WOW64 registry hive.
- GetPluginsInRegistryDirectory(HKEY_CURRENT_USER,
- kRegistryMozillaPlugins,
- 0,
- &plugin_dirs);
- GetPluginsInRegistryDirectory(HKEY_LOCAL_MACHINE,
- kRegistryMozillaPlugins,
- 0,
- &plugin_dirs);
-
- for (std::set<base::FilePath>::iterator i = plugin_dirs.begin();
- i != plugin_dirs.end(); ++i) {
- plugins->push_back(*i);
- }
-}
-
-bool PluginList::ShouldLoadPluginUsingPluginList(
- const WebPluginInfo& info,
- std::vector<WebPluginInfo>* plugins) {
- bool should_check_version = true;
- {
- base::AutoLock lock(lock_);
- should_check_version =
- std::find(extra_plugin_paths_.begin(), extra_plugin_paths_.end(),
- info.path) == extra_plugin_paths_.end();
- }
- // Version check for plugins that are not coming from |extra_plugin_paths_|.
- if (should_check_version) {
- for (size_t j = 0; j < plugins->size(); ++j) {
- base::FilePath::StringType plugin1 =
- base::ToLowerASCII((*plugins)[j].path.BaseName().value());
- base::FilePath::StringType plugin2 =
- base::ToLowerASCII(info.path.BaseName().value());
- if ((plugin1 == plugin2 && HaveSharedMimeType((*plugins)[j], info)) ||
- (plugin1 == kJavaDeploy1 && plugin2 == kJavaDeploy2) ||
- (plugin1 == kJavaDeploy2 && plugin2 == kJavaDeploy1)) {
- if (IsNewerVersion(info.version, (*plugins)[j].version))
- return false; // We have loaded a plugin whose version is newer.
- plugins->erase(plugins->begin() + j);
- break;
- }
- }
- }
-
- // The checks below only apply to NPAPI plugins.
- if (info.type != WebPluginInfo::PLUGIN_TYPE_NPAPI)
- return true;
-
- {
- base::AutoLock lock(lock_);
- // If the plugin is in our internal list we should load it.
- for (size_t i = 0; i < internal_plugins_.size(); ++i) {
- if (info.path == internal_plugins_[i].path)
- return true;
- }
- }
-
- // Troublemakers.
- base::FilePath::StringType filename =
- base::ToLowerASCII(info.path.BaseName().value());
- // Depends on XPCOM.
- if (filename == kMozillaActiveXPlugin)
- return false;
-
- // Disable the Yahoo Application State plugin as it crashes the plugin
- // process on return from NPObjectStub::OnInvoke. Please refer to
- // http://b/issue?id=1372124 for more information.
- if (filename == kYahooApplicationStatePlugin)
- return false;
-
- // Disable the WangWang protocol handler plugin (npww.dll) as it crashes
- // chrome during shutdown. Firefox also disables this plugin.
- // Please refer to http://code.google.com/p/chromium/issues/detail?id=3953
- // for more information.
- if (filename == kWanWangProtocolHandlerPlugin)
- return false;
-
- // We only work with newer versions of the Java plugin which use NPAPI only
- // and don't depend on XPCOM.
- if (filename == kJavaPlugin1 || filename == kJavaPlugin2) {
- std::vector<base::FilePath::StringType> ver = base::SplitString(
- info.version, base::FilePath::StringType(1, '.'),
- base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- int major, minor, update;
- if (ver.size() == 4 &&
- base::StringToInt(ver[0], &major) &&
- base::StringToInt(ver[1], &minor) &&
- base::StringToInt(ver[2], &update)) {
- if (major == 6 && minor == 0 && update < 120)
- return false; // Java SE6 Update 11 or older.
- }
- }
-
- // Special WMP handling:
- // If both the new and old WMP plugins exist, only load the new one.
- if (filename == kNewWMPPlugin) {
- for (size_t j = 0; j < plugins->size(); ++j) {
- if ((*plugins)[j].path.BaseName().value() == kOldWMPPlugin) {
- plugins->erase(plugins->begin() + j);
- break;
- }
- }
-
- } else if (filename == kOldWMPPlugin) {
- for (size_t j = 0; j < plugins->size(); ++j) {
- if ((*plugins)[j].path.BaseName().value() == kNewWMPPlugin)
- return false;
- }
- }
-
- base::FilePath plugin_path(info.path);
-#if defined(ARCH_CPU_X86_64)
- // The plugin in question could be a 32 bit plugin which we cannot load.
- if (IsValid32BitImage(base::MakeAbsoluteFilePath(plugin_path)))
- return false;
-#else
- // The plugin in question could be a 64 bit plugin which we cannot load.
- if (!IsValid32BitImage(base::MakeAbsoluteFilePath(plugin_path)))
- return false;
-#endif
- return true;
-}
-
-} // namespace content
diff --git a/chromium/content/common/plugin_process_messages.h b/chromium/content/common/plugin_process_messages.h
deleted file mode 100644
index a815b55ed30..00000000000
--- a/chromium/content/common/plugin_process_messages.h
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// Multiply-included message file, hence no include guard.
-
-#include <stdint.h>
-
-#include "build/build_config.h"
-#include "content/common/content_export.h"
-#include "content/common/content_param_traits.h"
-#include "content/public/common/common_param_traits.h"
-#include "ipc/ipc_channel_handle.h"
-#include "ipc/ipc_message_macros.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/ipc/gfx_param_traits.h"
-#include "ui/gfx/native_widget_types.h"
-
-#undef IPC_MESSAGE_EXPORT
-#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
-
-#define IPC_MESSAGE_START PluginProcessMsgStart
-
-//-----------------------------------------------------------------------------
-// PluginProcess messages
-// These are messages sent from the browser to the plugin process.
-// Tells the plugin process to create a new channel for communication with a
-// given renderer. The channel name is returned in a
-// PluginProcessHostMsg_ChannelCreated message. The renderer ID is passed so
-// that the plugin process reuses an existing channel to that process if it
-// exists. This ID is a unique opaque identifier generated by the browser
-// process.
-IPC_MESSAGE_CONTROL2(PluginProcessMsg_CreateChannel,
- int /* renderer_id */,
- bool /* off_the_record */)
-
-// Tells the plugin process to notify every connected renderer of the pending
-// shutdown, so we don't mistake it for a crash.
-IPC_MESSAGE_CONTROL0(PluginProcessMsg_NotifyRenderersOfPendingShutdown)
-
-IPC_MESSAGE_CONTROL3(PluginProcessMsg_ClearSiteData,
- std::string /* site */,
- uint64_t /* flags */,
- uint64_t /* max_age */)
-
-//-----------------------------------------------------------------------------
-// PluginProcessHost messages
-// These are messages sent from the plugin process to the browser process.
-// Response to a PluginProcessMsg_CreateChannel message.
-IPC_MESSAGE_CONTROL1(PluginProcessHostMsg_ChannelCreated,
- IPC::ChannelHandle /* channel_handle */)
-
-IPC_MESSAGE_CONTROL1(PluginProcessHostMsg_ChannelDestroyed,
- int /* renderer_id */)
-
-IPC_MESSAGE_CONTROL1(PluginProcessHostMsg_ClearSiteDataResult,
- bool /* success */)
-
-#if defined(OS_WIN)
-// Destroys the given window's parent on the UI thread.
-IPC_MESSAGE_CONTROL2(PluginProcessHostMsg_PluginWindowDestroyed,
- HWND /* window */,
- HWND /* parent */)
-#endif
-
-#if defined(OS_MACOSX)
-// On Mac OS X, we need the browser to keep track of plugin windows so
-// that it can add and remove them from stacking groups, hide and show the
-// menu bar, etc. We pass the window rect for convenience so that the
-// browser can easily tell if the window is fullscreen.
-
-// Notifies the browser that the plugin has shown a window.
-IPC_MESSAGE_CONTROL3(PluginProcessHostMsg_PluginShowWindow,
- uint32_t /* window ID */,
- gfx::Rect /* window rect */,
- bool /* modal */)
-
-// Notifies the browser that the plugin has hidden a window.
-IPC_MESSAGE_CONTROL2(PluginProcessHostMsg_PluginHideWindow,
- uint32_t /* window ID */,
- gfx::Rect /* window rect */)
-
-// Notifies the browser that a plugin instance has requested a cursor
-// visibility change.
-IPC_MESSAGE_CONTROL1(PluginProcessHostMsg_PluginSetCursorVisibility,
- bool /* cursor visibility */)
-#endif
diff --git a/chromium/content/common/presentation/presentation_service.mojom b/chromium/content/common/presentation/presentation_service.mojom
index ae39815ccce..2c470a52ed3 100644
--- a/chromium/content/common/presentation/presentation_service.mojom
+++ b/chromium/content/common/presentation/presentation_service.mojom
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-module presentation;
+module content.mojom;
struct PresentationSessionInfo {
string url;
@@ -16,6 +16,12 @@ enum PresentationConnectionState {
TERMINATED
};
+enum PresentationConnectionCloseReason {
+ CONNECTION_ERROR,
+ CLOSED,
+ WENT_AWAY
+};
+
enum PresentationErrorType {
NO_AVAILABLE_SCREENS,
SESSION_REQUEST_CANCELLED,
@@ -119,6 +125,12 @@ interface PresentationServiceClient {
OnConnectionStateChanged(PresentationSessionInfo connection,
PresentationConnectionState newState);
+ // Caled when the state of |connection| started on this frame has changed to
+ // CLOSED.
+ OnConnectionClosed(PresentationSessionInfo connection,
+ PresentationConnectionCloseReason reason,
+ string message);
+
// See PresentationService::ListenForSessionMessages.
OnSessionMessagesReceived(PresentationSessionInfo sessionInfo,
array<SessionMessage> messages);
diff --git a/chromium/content/common/process_control.mojom b/chromium/content/common/process_control.mojom
index efd0adc51ce..0734a6cd264 100644
--- a/chromium/content/common/process_control.mojom
+++ b/chromium/content/common/process_control.mojom
@@ -2,11 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-module content;
+module content.mojom;
-import "mojo/shell/public/interfaces/application.mojom";
+import "mojo/shell/public/interfaces/shell_client.mojom";
interface ProcessControl {
- LoadApplication(string url, mojo.Application& request) => (bool success);
+ LoadApplication(string url,
+ mojo.shell.mojom.ShellClient& request) => (bool success);
};
diff --git a/chromium/content/common/process_type.cc b/chromium/content/common/process_type.cc
index 34019d453a6..ebce0e60141 100644
--- a/chromium/content/common/process_type.cc
+++ b/chromium/content/common/process_type.cc
@@ -15,8 +15,6 @@ std::string GetProcessTypeNameInEnglish(int type) {
return "Browser";
case PROCESS_TYPE_RENDERER:
return "Tab";
- case PROCESS_TYPE_PLUGIN:
- return "Plugin";
case PROCESS_TYPE_UTILITY:
return "Utility";
case PROCESS_TYPE_ZYGOTE:
diff --git a/chromium/content/common/push_messaging_messages.h b/chromium/content/common/push_messaging_messages.h
index 38a39e8cb11..df88b2f2a55 100644
--- a/chromium/content/common/push_messaging_messages.h
+++ b/chromium/content/common/push_messaging_messages.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include "content/public/common/push_messaging_status.h"
+#include "content/public/common/push_subscription_options.h"
#include "ipc/ipc_message_macros.h"
#include "third_party/WebKit/public/platform/modules/push_messaging/WebPushError.h"
#include "third_party/WebKit/public/platform/modules/push_messaging/WebPushPermissionStatus.h"
@@ -29,6 +30,11 @@ IPC_ENUM_TRAITS_MAX_VALUE(
blink::WebPushError::ErrorType,
blink::WebPushError::ErrorType::ErrorTypeLast)
+IPC_STRUCT_TRAITS_BEGIN(content::PushSubscriptionOptions)
+ IPC_STRUCT_TRAITS_MEMBER(user_visible_only)
+ IPC_STRUCT_TRAITS_MEMBER(sender_info)
+IPC_STRUCT_TRAITS_END()
+
// Messages sent from the browser to the child process.
IPC_MESSAGE_ROUTED4(PushMessagingMsg_SubscribeFromDocumentSuccess,
@@ -80,17 +86,16 @@ IPC_MESSAGE_CONTROL2(PushMessagingMsg_GetPermissionStatusError,
// Messages sent from the child process to the browser.
-IPC_MESSAGE_CONTROL5(PushMessagingHostMsg_SubscribeFromDocument,
+IPC_MESSAGE_CONTROL4(PushMessagingHostMsg_SubscribeFromDocument,
int32_t /* render_frame_id */,
int32_t /* request_id */,
- std::string /* sender_id */,
- bool /* user_visible */,
+ content::PushSubscriptionOptions /* options */,
int64_t /* service_worker_registration_id */)
IPC_MESSAGE_CONTROL3(PushMessagingHostMsg_SubscribeFromWorker,
int32_t /* request_id */,
int64_t /* service_worker_registration_id */,
- bool /* user_visible */)
+ content::PushSubscriptionOptions /* options */)
IPC_MESSAGE_CONTROL2(PushMessagingHostMsg_Unsubscribe,
int32_t /* request_id */,
diff --git a/chromium/content/common/render_frame_setup.mojom b/chromium/content/common/render_frame_setup.mojom
index abe4f652f32..748f733096c 100644
--- a/chromium/content/common/render_frame_setup.mojom
+++ b/chromium/content/common/render_frame_setup.mojom
@@ -2,12 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-module content;
+module content.mojom;
-import "mojo/shell/public/interfaces/service_provider.mojom";
+import "mojo/shell/public/interfaces/interface_provider.mojom";
interface RenderFrameSetup {
- ExchangeServiceProviders(int32 frame_routing_id,
- mojo.ServiceProvider& services,
- mojo.ServiceProvider exposed_services);
+ ExchangeInterfaceProviders(
+ int32 frame_routing_id,
+ mojo.shell.mojom.InterfaceProvider& remote_interfaces,
+ mojo.shell.mojom.InterfaceProvider local_interfaces);
};
diff --git a/chromium/content/common/resize_params.cc b/chromium/content/common/resize_params.cc
new file mode 100644
index 00000000000..ea9f18fb65b
--- /dev/null
+++ b/chromium/content/common/resize_params.cc
@@ -0,0 +1,20 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/common/resize_params.h"
+
+namespace content {
+
+ResizeParams::ResizeParams()
+ : top_controls_shrink_blink_size(false),
+ top_controls_height(0.f),
+ is_fullscreen_granted(false),
+ display_mode(blink::WebDisplayModeUndefined),
+ needs_resize_ack(false) {}
+
+ResizeParams::ResizeParams(const ResizeParams& other) = default;
+
+ResizeParams::~ResizeParams() {}
+
+} // namespace content
diff --git a/chromium/content/common/resize_params.h b/chromium/content/common/resize_params.h
new file mode 100644
index 00000000000..f9eb07c247d
--- /dev/null
+++ b/chromium/content/common/resize_params.h
@@ -0,0 +1,58 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_RESIZE_PARAMS_H_
+#define CONTENT_COMMON_RESIZE_PARAMS_H_
+
+#include "content/common/content_export.h"
+#include "third_party/WebKit/public/platform/WebDisplayMode.h"
+#include "third_party/WebKit/public/platform/WebScreenInfo.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace content {
+
+struct CONTENT_EXPORT ResizeParams {
+ ResizeParams();
+ ResizeParams(const ResizeParams& other);
+ ~ResizeParams();
+
+ // Information about the screen (dpi, depth, etc..).
+ blink::WebScreenInfo screen_info;
+
+ // The size of the renderer.
+ gfx::Size new_size;
+
+ // The size of the view's backing surface in non-DPI-adjusted pixels.
+ gfx::Size physical_backing_size;
+
+ // Whether or not Blink's viewport size should be shrunk by the height of the
+ // URL-bar (always false on platforms where URL-bar hiding isn't supported).
+ bool top_controls_shrink_blink_size;
+
+ // The height of the top controls (always 0 on platforms where URL-bar hiding
+ // isn't supported).
+ float top_controls_height;
+
+ // The size of the visible viewport, which may be smaller than the view if the
+ // view is partially occluded (e.g. by a virtual keyboard). The size is in
+ // DPI-adjusted pixels.
+ gfx::Size visible_viewport_size;
+
+ // The resizer rect.
+ gfx::Rect resizer_rect;
+
+ // Indicates whether tab-initiated fullscreen was granted.
+ bool is_fullscreen_granted;
+
+ // The display mode.
+ blink::WebDisplayMode display_mode;
+
+ // If set, requests the renderer to reply with a ViewHostMsg_UpdateRect
+ // with the ViewHostMsg_UpdateRect_Flags::IS_RESIZE_ACK bit set in flags.
+ bool needs_resize_ack;
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_RESIZE_PARAMS_H_
diff --git a/chromium/content/common/resource_messages.cc b/chromium/content/common/resource_messages.cc
index da92b97b09b..2c0cbe12b7b 100644
--- a/chromium/content/common/resource_messages.cc
+++ b/chromium/content/common/resource_messages.cc
@@ -9,8 +9,9 @@
namespace IPC {
-void ParamTraits<scoped_refptr<net::HttpResponseHeaders> >::Write(
- Message* m, const param_type& p) {
+void ParamTraits<scoped_refptr<net::HttpResponseHeaders>>::Write(
+ base::Pickle* m,
+ const param_type& p) {
WriteParam(m, p.get() != NULL);
if (p.get()) {
// Do not disclose Set-Cookie headers over IPC.
@@ -19,7 +20,7 @@ void ParamTraits<scoped_refptr<net::HttpResponseHeaders> >::Write(
}
bool ParamTraits<scoped_refptr<net::HttpResponseHeaders>>::Read(
- const Message* m,
+ const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
bool has_object;
@@ -35,7 +36,8 @@ void ParamTraits<scoped_refptr<net::HttpResponseHeaders> >::Log(
l->append("<HttpResponseHeaders>");
}
-void ParamTraits<storage::DataElement>::Write(Message* m, const param_type& p) {
+void ParamTraits<storage::DataElement>::Write(base::Pickle* m,
+ const param_type& p) {
WriteParam(m, static_cast<int>(p.type()));
switch (p.type()) {
case storage::DataElement::TYPE_BYTES: {
@@ -77,7 +79,7 @@ void ParamTraits<storage::DataElement>::Write(Message* m, const param_type& p) {
}
}
-bool ParamTraits<storage::DataElement>::Read(const Message* m,
+bool ParamTraits<storage::DataElement>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
int type;
@@ -160,8 +162,9 @@ void ParamTraits<storage::DataElement>::Log(const param_type& p,
l->append("<storage::DataElement>");
}
-void ParamTraits<scoped_refptr<content::ResourceDevToolsInfo> >::Write(
- Message* m, const param_type& p) {
+void ParamTraits<scoped_refptr<content::ResourceDevToolsInfo>>::Write(
+ base::Pickle* m,
+ const param_type& p) {
WriteParam(m, p.get() != NULL);
if (p.get()) {
WriteParam(m, p->http_status_code);
@@ -174,7 +177,7 @@ void ParamTraits<scoped_refptr<content::ResourceDevToolsInfo> >::Write(
}
bool ParamTraits<scoped_refptr<content::ResourceDevToolsInfo>>::Read(
- const Message* m,
+ const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
bool has_object;
@@ -203,8 +206,8 @@ void ParamTraits<scoped_refptr<content::ResourceDevToolsInfo> >::Log(
l->append(")");
}
-void ParamTraits<net::LoadTimingInfo>::Write(
- Message* m, const param_type& p) {
+void ParamTraits<net::LoadTimingInfo>::Write(base::Pickle* m,
+ const param_type& p) {
WriteParam(m, p.socket_log_id);
WriteParam(m, p.socket_reused);
WriteParam(m, p.request_start_time.is_null());
@@ -225,7 +228,7 @@ void ParamTraits<net::LoadTimingInfo>::Write(
WriteParam(m, p.receive_headers_end);
}
-bool ParamTraits<net::LoadTimingInfo>::Read(const Message* m,
+bool ParamTraits<net::LoadTimingInfo>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
bool has_no_times;
@@ -288,8 +291,8 @@ void ParamTraits<net::LoadTimingInfo>::Log(const param_type& p,
l->append(")");
}
-void ParamTraits<scoped_refptr<content::ResourceRequestBody> >::Write(
- Message* m,
+void ParamTraits<scoped_refptr<content::ResourceRequestBody>>::Write(
+ base::Pickle* m,
const param_type& p) {
WriteParam(m, p.get() != NULL);
if (p.get()) {
@@ -299,7 +302,7 @@ void ParamTraits<scoped_refptr<content::ResourceRequestBody> >::Write(
}
bool ParamTraits<scoped_refptr<content::ResourceRequestBody>>::Read(
- const Message* m,
+ const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
bool has_object;
diff --git a/chromium/content/common/resource_messages.h b/chromium/content/common/resource_messages.h
index 44e4a611fc7..9c53b361a33 100644
--- a/chromium/content/common/resource_messages.h
+++ b/chromium/content/common/resource_messages.h
@@ -39,40 +39,50 @@ namespace IPC {
template <>
struct ParamTraits<scoped_refptr<net::HttpResponseHeaders> > {
typedef scoped_refptr<net::HttpResponseHeaders> param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct CONTENT_EXPORT ParamTraits<storage::DataElement> {
typedef storage::DataElement param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct ParamTraits<scoped_refptr<content::ResourceDevToolsInfo> > {
typedef scoped_refptr<content::ResourceDevToolsInfo> param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct ParamTraits<net::LoadTimingInfo> {
typedef net::LoadTimingInfo param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct ParamTraits<scoped_refptr<content::ResourceRequestBody> > {
typedef scoped_refptr<content::ResourceRequestBody> param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
@@ -139,6 +149,8 @@ IPC_STRUCT_TRAITS_BEGIN(content::ResourceResponseInfo)
IPC_STRUCT_TRAITS_MEMBER(response_type_via_service_worker)
IPC_STRUCT_TRAITS_MEMBER(service_worker_start_time)
IPC_STRUCT_TRAITS_MEMBER(service_worker_ready_time)
+ IPC_STRUCT_TRAITS_MEMBER(is_in_cache_storage)
+ IPC_STRUCT_TRAITS_MEMBER(cache_storage_cache_name)
IPC_STRUCT_TRAITS_MEMBER(proxy_server)
IPC_STRUCT_TRAITS_MEMBER(is_using_lofi)
IPC_STRUCT_TRAITS_END()
@@ -149,6 +161,7 @@ IPC_STRUCT_TRAITS_BEGIN(net::RedirectInfo)
IPC_STRUCT_TRAITS_MEMBER(new_url)
IPC_STRUCT_TRAITS_MEMBER(new_first_party_for_cookies)
IPC_STRUCT_TRAITS_MEMBER(new_referrer)
+ IPC_STRUCT_TRAITS_MEMBER(referred_token_binding_host)
IPC_STRUCT_TRAITS_END()
// Parameters for a resource request.
@@ -213,6 +226,10 @@ IPC_STRUCT_BEGIN(ResourceHostMsg_Request)
// or kInvalidServiceWorkerProviderId.
IPC_STRUCT_MEMBER(int, service_worker_provider_id)
+ // True if the request originated from a Service Worker, e.g. due to a
+ // fetch() in the Service Worker script.
+ IPC_STRUCT_MEMBER(bool, originated_from_service_worker)
+
// True if the request should not be handled by the ServiceWorker.
IPC_STRUCT_MEMBER(bool, skip_service_worker)
@@ -284,6 +301,11 @@ IPC_STRUCT_BEGIN(ResourceHostMsg_Request)
// Whether or not to request a LoFi version of the resource or let the browser
// decide.
IPC_STRUCT_MEMBER(content::LoFiState, lofi_state)
+
+ // PlzNavigate: the stream url associated with a navigation. Used to get
+ // access to the body of the response that has already been fetched by the
+ // browser.
+ IPC_STRUCT_MEMBER(GURL, resource_body_stream_url)
IPC_STRUCT_END()
// Parameters for a ResourceMsg_RequestComplete
@@ -355,6 +377,19 @@ IPC_MESSAGE_CONTROL4(ResourceMsg_SetDataBuffer,
IPC_MESSAGE_CONTROL2(ResourceMsg_DataReceivedDebug,
int /* request_id */,
int /* data_offset */)
+IPC_MESSAGE_CONTROL4(ResourceMsg_DataReceivedDebug2,
+ int /* request_id */,
+ int /* data_offset */,
+ int /* data_length */,
+ int /* encoded_data_length */)
+
+// Sent when a chunk of data from a resource request is ready, and the resource
+// is expected to be small enough to fit in the inlined buffer.
+// The data is sent as a part of IPC message.
+IPC_MESSAGE_CONTROL3(ResourceMsg_InlinedDataChunkReceived,
+ int /* request_id */,
+ std::vector<char> /* data */,
+ int /* encoded_data_length */)
// Sent when some data from a resource request is ready. The data offset and
// length specify a byte range into the shared memory buffer provided by the
diff --git a/chromium/content/common/sandbox_init_mac.cc b/chromium/content/common/sandbox_init_mac.cc
index c49aa80685e..36a4058c35e 100644
--- a/chromium/content/common/sandbox_init_mac.cc
+++ b/chromium/content/common/sandbox_init_mac.cc
@@ -53,8 +53,7 @@ bool GetSandboxTypeFromCommandLine(int* sandbox_type,
if (command_line.HasSwitch(switches::kDisableGpuSandbox))
return false;
*sandbox_type = SANDBOX_TYPE_GPU;
- } else if ((process_type == switches::kPluginProcess) ||
- (process_type == switches::kPpapiBrokerProcess)) {
+ } else if (process_type == switches::kPpapiBrokerProcess) {
return false;
} else if (process_type == switches::kPpapiPluginProcess) {
*sandbox_type = SANDBOX_TYPE_PPAPI;
@@ -75,12 +74,4 @@ bool InitializeSandbox() {
return InitializeSandbox(sandbox_type, allowed_dir);
}
-bool BrokerDuplicateSharedMemoryHandle(
- const base::SharedMemoryHandle& source_handle,
- base::ProcessId target_process_id,
- base::SharedMemoryHandle* target_handle) {
- *target_handle = base::SharedMemory::DuplicateHandle(source_handle);
- return base::SharedMemory::IsHandleValid(*target_handle);
-}
-
} // namespace content
diff --git a/chromium/content/common/sandbox_init_win.cc b/chromium/content/common/sandbox_init_win.cc
index 78c1fef251d..16e3e4afbd4 100644
--- a/chromium/content/common/sandbox_init_win.cc
+++ b/chromium/content/common/sandbox_init_win.cc
@@ -42,19 +42,4 @@ bool InitializeSandbox(sandbox::SandboxInterfaceInfo* sandbox_info) {
return InitTargetServices(target_services);
}
-bool BrokerDuplicateSharedMemoryHandle(
- const base::SharedMemoryHandle& source_handle,
- base::ProcessId target_process_id,
- base::SharedMemoryHandle* target_handle) {
- HANDLE duped_handle;
- if (!BrokerDuplicateHandle(
- source_handle.GetHandle(), target_process_id, &duped_handle,
- FILE_MAP_READ | FILE_MAP_WRITE | SECTION_QUERY, 0)) {
- return false;
- }
-
- *target_handle = base::SharedMemoryHandle(duped_handle, target_process_id);
- return true;
-}
-
} // namespace content
diff --git a/chromium/content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.cc b/chromium/content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.cc
index c3b1605fc7d..5f9813f5808 100644
--- a/chromium/content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.cc
+++ b/chromium/content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.cc
@@ -4,17 +4,51 @@
#include "content/common/sandbox_linux/android/sandbox_bpf_base_policy_android.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <linux/net.h>
+#include <sys/socket.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include "build/build_config.h"
#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
+using sandbox::bpf_dsl::AllOf;
using sandbox::bpf_dsl::Allow;
+using sandbox::bpf_dsl::AnyOf;
+using sandbox::bpf_dsl::Arg;
+using sandbox::bpf_dsl::BoolExpr;
+using sandbox::bpf_dsl::If;
+using sandbox::bpf_dsl::Error;
using sandbox::bpf_dsl::ResultExpr;
namespace content {
+#ifndef SOCK_CLOEXEC
+#define SOCK_CLOEXEC O_CLOEXEC
+#endif
+
+#ifndef SOCK_NONBLOCK
+#define SOCK_NONBLOCK O_NONBLOCK
+#endif
+
+namespace {
+
+// Restricts the arguments to sys_socket() to AF_UNIX. Returns a BoolExpr that
+// evaluates to true if the syscall should be allowed.
+BoolExpr RestrictSocketArguments(const Arg<int>& domain,
+ const Arg<int>& type,
+ const Arg<int>& protocol) {
+ const int kSockFlags = SOCK_CLOEXEC | SOCK_NONBLOCK;
+ return AllOf(domain == AF_UNIX,
+ AnyOf((type & ~kSockFlags) == SOCK_DGRAM,
+ (type & ~kSockFlags) == SOCK_STREAM),
+ protocol == 0);
+}
+
+} // namespace
+
SandboxBPFBasePolicyAndroid::SandboxBPFBasePolicyAndroid()
: SandboxBPFBasePolicy() {}
@@ -27,11 +61,19 @@ ResultExpr SandboxBPFBasePolicyAndroid::EvaluateSyscall(int sysno) const {
// TODO(rsesek): restrict clone parameters.
case __NR_clone:
case __NR_epoll_pwait:
+ case __NR_fdatasync:
case __NR_flock:
+ case __NR_fsync:
+ case __NR_ftruncate:
+#if defined(__i386__) || defined(__arm__) || defined(__mips__)
+ case __NR_ftruncate64:
+#endif
#if defined(__x86_64__) || defined(__aarch64__)
case __NR_newfstatat:
+ case __NR_getdents64:
#elif defined(__i386__) || defined(__arm__) || defined(__mips__)
case __NR_fstatat64:
+ case __NR_getdents:
#endif
case __NR_getpriority:
case __NR_ioctl:
@@ -46,7 +88,11 @@ ResultExpr SandboxBPFBasePolicyAndroid::EvaluateSyscall(int sysno) const {
#endif
case __NR_openat:
case __NR_pread64:
+ case __NR_pwrite64:
case __NR_rt_sigtimedwait:
+ case __NR_sched_getparam:
+ case __NR_sched_getscheduler:
+ case __NR_sched_setscheduler:
case __NR_setpriority:
case __NR_set_tid_address:
case __NR_sigaltstack:
@@ -56,10 +102,49 @@ ResultExpr SandboxBPFBasePolicyAndroid::EvaluateSyscall(int sysno) const {
case __NR_getrlimit:
#endif
case __NR_uname:
+
+ // Permit socket operations so that renderers can connect to logd and
+ // debuggerd. The arguments to socket() are further restricted below.
+ // Note that on i386, both of these calls map to __NR_socketcall, which
+ // is demultiplexed below.
+#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || \
+ defined(__mips__)
+ case __NR_getsockopt:
+ case __NR_connect:
+ case __NR_socket:
+#endif
+
+ // Ptrace is allowed so the Breakpad Microdumper can fork in a renderer
+ // and then ptrace the parent.
+ case __NR_ptrace:
override_and_allow = true;
break;
}
+#if defined(__x86_64__) || defined(__arm__) || defined(__aarch64__) || \
+ defined(__mips__)
+ if (sysno == __NR_socket) {
+ const Arg<int> domain(0);
+ const Arg<int> type(1);
+ const Arg<int> protocol(2);
+ return If(RestrictSocketArguments(domain, type, protocol), Allow())
+ .Else(Error(EPERM));
+ }
+#elif defined(__i386__)
+ if (sysno == __NR_socketcall) {
+ const Arg<int> socketcall(0);
+ const Arg<int> domain(1);
+ const Arg<int> type(2);
+ const Arg<int> protocol(3);
+ return If(socketcall == SYS_CONNECT, Allow())
+ .ElseIf(AllOf(socketcall == SYS_SOCKET,
+ RestrictSocketArguments(domain, type, protocol)),
+ Allow())
+ .ElseIf(socketcall == SYS_GETSOCKOPT, Allow())
+ .Else(Error(EPERM));
+ }
+#endif
+
if (override_and_allow)
return Allow();
diff --git a/chromium/content/common/sandbox_linux/bpf_renderer_policy_linux.cc b/chromium/content/common/sandbox_linux/bpf_renderer_policy_linux.cc
index e799273919a..b6a960ceef3 100644
--- a/chromium/content/common/sandbox_linux/bpf_renderer_policy_linux.cc
+++ b/chromium/content/common/sandbox_linux/bpf_renderer_policy_linux.cc
@@ -15,8 +15,17 @@
#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
#include "sandbox/linux/system_headers/linux_syscalls.h"
-#if defined(USE_VGEM_MAP)
-#include <libdrm/vgem_drm.h>
+#if defined(OS_CHROMEOS)
+// TODO(vignatti): replace the local definitions below with #include
+// <linux/dma-buf.h> once kernel version 4.6 becomes widely used.
+#include <linux/types.h>
+
+struct local_dma_buf_sync {
+ __u64 flags;
+};
+#define LOCAL_DMA_BUF_BASE 'b'
+#define LOCAL_DMA_BUF_IOCTL_SYNC \
+ _IOW(LOCAL_DMA_BUF_BASE, 0, struct local_dma_buf_sync)
#endif
using sandbox::SyscallSets;
@@ -34,12 +43,9 @@ ResultExpr RestrictIoctl() {
return Switch(request)
.SANDBOX_BPF_DSL_CASES((static_cast<unsigned long>(TCGETS), FIONREAD),
Allow())
-#if defined(USE_VGEM_MAP)
- // Type of DRM_IOCTL_XXX is unsigned long on IA and unsigned int on ARM.
+#if defined(OS_CHROMEOS)
.SANDBOX_BPF_DSL_CASES(
- (static_cast<unsigned long>(DRM_IOCTL_GEM_CLOSE),
- DRM_IOCTL_VGEM_MODE_MAP_DUMB, DRM_IOCTL_PRIME_FD_TO_HANDLE),
- Allow())
+ (static_cast<unsigned long>(LOCAL_DMA_BUF_IOCTL_SYNC)), Allow())
#endif
.Default(sandbox::CrashSIGSYSIoctl());
}
@@ -60,7 +66,8 @@ ResultExpr RendererProcessPolicy::EvaluateSyscall(int sysno) const {
// Allow the system calls below.
case __NR_fdatasync:
case __NR_fsync:
-#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \
+ defined(__aarch64__)
case __NR_getrlimit:
#endif
#if defined(__i386__) || defined(__arm__)
diff --git a/chromium/content/common/sandbox_linux/bpf_utility_policy_linux.cc b/chromium/content/common/sandbox_linux/bpf_utility_policy_linux.cc
index 3ead1c899d2..13367964e64 100644
--- a/chromium/content/common/sandbox_linux/bpf_utility_policy_linux.cc
+++ b/chromium/content/common/sandbox_linux/bpf_utility_policy_linux.cc
@@ -32,7 +32,8 @@ ResultExpr UtilityProcessPolicy::EvaluateSyscall(int sysno) const {
// Allow the system calls below.
case __NR_fdatasync:
case __NR_fsync:
-#if defined(__i386__) || defined(__x86_64__)
+#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \
+ defined(__aarch64__)
case __NR_getrlimit:
#endif
#if defined(__i386__) || defined(__arm__)
diff --git a/chromium/content/common/sandbox_linux/sandbox_linux.h b/chromium/content/common/sandbox_linux/sandbox_linux.h
index 0a80479799f..7ce723b3771 100644
--- a/chromium/content/common/sandbox_linux/sandbox_linux.h
+++ b/chromium/content/common/sandbox_linux/sandbox_linux.h
@@ -42,7 +42,7 @@ namespace content {
class LinuxSandbox {
public:
// This is a list of sandbox IPC methods which the renderer may send to the
- // sandbox host. See http://code.google.com/p/chromium/wiki/LinuxSandboxIPC
+ // sandbox host. See https://chromium.googlesource.com/chromium/src/+/master/docs/linux_sandbox_ipc.md
// This isn't the full list, values < 32 are reserved for methods called from
// Skia.
enum LinuxSandboxIPCMethods {
diff --git a/chromium/content/common/sandbox_mac.h b/chromium/content/common/sandbox_mac.h
index bac23f0df8c..afda387549f 100644
--- a/chromium/content/common/sandbox_mac.h
+++ b/chromium/content/common/sandbox_mac.h
@@ -50,9 +50,6 @@ class CONTENT_EXPORT SandboxCompiler {
bool CompileAndApplyProfile(std::string* error);
private:
- // Frees all of the system resources allocated for the sandbox.
- void FreeSandboxResources(void* profile, void* params, char* error);
-
// Storage of the key/value pairs of strings that are used in the sandbox
// profile.
std::map<std::string, std::string> params_map_;
diff --git a/chromium/content/common/sandbox_mac.mm b/chromium/content/common/sandbox_mac.mm
index ca915a739e8..6a7f2cfcc74 100644
--- a/chromium/content/common/sandbox_mac.mm
+++ b/chromium/content/common/sandbox_mac.mm
@@ -47,14 +47,10 @@ extern "C" {
void CGSSetDenyWindowServerConnections(bool);
void CGSShutdownServerConnections();
-void* sandbox_create_params();
-int sandbox_set_param(void* params, const char* key, const char* value);
-void* sandbox_compile_string(const char* profile_str,
- void* params,
- char** error);
-int sandbox_apply(void* profile);
-void sandbox_free_params(void* params);
-void sandbox_free_profile(void* profile);
+int sandbox_init_with_parameters(const char* profile,
+ uint64_t flags,
+ const char* const parameters[],
+ char** errorbuf);
};
namespace content {
@@ -68,14 +64,6 @@ struct SandboxTypeToResourceIDMapping {
int sandbox_profile_resource_id;
};
-// This is the internal definition of the structure used by sandbox parameters
-// on OS X 10.6.
-struct SandboxParams {
- void* buf;
- size_t count;
- size_t size;
-};
-
// Mapping from sandbox process types to resource IDs containing the sandbox
// profile for all process types known to content.
SandboxTypeToResourceIDMapping kDefaultSandboxTypeToResourceIDMapping[] = {
@@ -153,58 +141,27 @@ bool SandboxCompiler::InsertStringParam(const std::string& key,
return params_map_.insert(std::make_pair(key, value)).second;
}
-void SandboxCompiler::FreeSandboxResources(void* profile,
- void* params,
- char* error) {
- if (error)
- sandbox_free_error(error);
- if (params)
- sandbox_free_params(params);
- if (profile)
- sandbox_free_profile(profile);
-}
-
bool SandboxCompiler::CompileAndApplyProfile(std::string* error) {
char* error_internal = nullptr;
- void* profile = nullptr;
- void* params = nullptr;
-
- if (!params_map_.empty()) {
- if (base::mac::IsOSSnowLeopard()) {
- // This is a workaround for 10.6, see crbug.com/509114.
- // Check that there is no integer overflow.
- base::CheckedNumeric<size_t> checked_size = params_map_.size();
- checked_size *= 2;
- if (!checked_size.IsValid())
- return false;
-
- SandboxParams* internal_params =
- static_cast<SandboxParams*>(malloc(sizeof(SandboxParams)));
- internal_params->buf = calloc(checked_size.ValueOrDie(), sizeof(void*));
- internal_params->count = 0;
- internal_params->size = checked_size.ValueOrDie();
- params = internal_params;
- } else {
- params = sandbox_create_params();
- if (!params)
- return false;
- }
+ std::vector<const char*> params;
- for (const auto& kv : params_map_)
- sandbox_set_param(params, kv.first.c_str(), kv.second.c_str());
+ for (const auto& kv : params_map_) {
+ params.push_back(kv.first.c_str());
+ params.push_back(kv.second.c_str());
}
+ // The parameters array must be null terminated.
+ params.push_back(static_cast<const char*>(0));
- profile =
- sandbox_compile_string(profile_str_.c_str(), params, &error_internal);
- if (!profile) {
+ if (sandbox_init_with_parameters(profile_str_.c_str(), 0, params.data(),
+ &error_internal)) {
error->assign(error_internal);
- FreeSandboxResources(profile, params, error_internal);
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ sandbox_free_error(error_internal);
+#pragma clang diagnostic pop
return false;
}
-
- int result = sandbox_apply(profile);
- FreeSandboxResources(profile, params, error_internal);
- return result == 0;
+ return true;
}
// static
@@ -534,16 +491,6 @@ bool Sandbox::EnableSandbox(int sandbox_type,
if (!compiler.InsertBooleanParam("ELCAP_OR_LATER", elcap_or_later))
return false;
-#if defined(COMPONENT_BUILD)
- // dlopen() fails without file-read-metadata access if the executable image
- // contains LC_RPATH load commands. The components build uses those.
- // See http://crbug.com/127465
- if (base::mac::IsOSSnowLeopard()) {
- if (!compiler.InsertBooleanParam("COMPONENT_BUILD_WORKAROUND", true))
- return false;
- }
-#endif
-
// Initialize sandbox.
std::string error_str;
bool success = compiler.CompileAndApplyProfile(&error_str);
diff --git a/chromium/content/common/sandbox_mac_diraccess_unittest.mm b/chromium/content/common/sandbox_mac_diraccess_unittest.mm
index 17be671801a..205e1cbc0b9 100644
--- a/chromium/content/common/sandbox_mac_diraccess_unittest.mm
+++ b/chromium/content/common/sandbox_mac_diraccess_unittest.mm
@@ -13,6 +13,7 @@ extern "C" {
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/process/kill.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
diff --git a/chromium/content/common/sandbox_mac_system_access_unittest.mm b/chromium/content/common/sandbox_mac_system_access_unittest.mm
index 02980715609..b37b967d2b9 100644
--- a/chromium/content/common/sandbox_mac_system_access_unittest.mm
+++ b/chromium/content/common/sandbox_mac_system_access_unittest.mm
@@ -9,11 +9,13 @@
#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/logging.h"
+#include "base/memory/ref_counted.h"
#include "base/strings/sys_string_conversions.h"
#include "content/common/sandbox_mac.h"
#include "content/common/sandbox_mac_unittest_helper.h"
#include "crypto/openssl_util.h"
#include "testing/gtest/include/gtest/gtest.h"
+#import "ui/base/clipboard/clipboard_util_mac.h"
namespace content {
@@ -69,15 +71,16 @@ void MacSandboxedClipboardTestCase::SetTestData(const char* test_data) {
}
TEST_F(MacSandboxTest, ClipboardAccess) {
- NSPasteboard* pb = [NSPasteboard pasteboardWithUniqueName];
- EXPECT_EQ([[pb types] count], 0U);
+ scoped_refptr<ui::UniquePasteboard> pb = new ui::UniquePasteboard;
+ ASSERT_TRUE(pb->get());
+ EXPECT_EQ([[pb->get() types] count], 0U);
- std::string pasteboard_name = base::SysNSStringToUTF8([pb name]);
+ std::string pasteboard_name = base::SysNSStringToUTF8([pb->get() name]);
EXPECT_TRUE(RunTestInAllSandboxTypes("MacSandboxedClipboardTestCase",
pasteboard_name.c_str()));
// After executing the test, the clipboard should still be empty.
- EXPECT_EQ([[pb types] count], 0U);
+ EXPECT_EQ([[pb->get() types] count], 0U);
}
//--------------------- File Access Sandboxing ----------------------
diff --git a/chromium/content/common/sandbox_util.cc b/chromium/content/common/sandbox_util.cc
index 4b1dcef4a91..75b3977f4d6 100644
--- a/chromium/content/common/sandbox_util.cc
+++ b/chromium/content/common/sandbox_util.cc
@@ -6,6 +6,7 @@
#include "build/build_config.h"
#include "content/public/common/sandbox_init.h"
+#include "ipc/ipc_platform_file.h"
#if defined(OS_POSIX)
#include <unistd.h>
@@ -17,30 +18,7 @@ IPC::PlatformFileForTransit BrokerGetFileHandleForProcess(
base::PlatformFile handle,
base::ProcessId target_process_id,
bool should_close_source) {
- IPC::PlatformFileForTransit out_handle;
-#if defined(OS_WIN)
- DWORD options = DUPLICATE_SAME_ACCESS;
- if (should_close_source)
- options |= DUPLICATE_CLOSE_SOURCE;
- if (!content::BrokerDuplicateHandle(handle, target_process_id, &out_handle,
- 0, options)) {
- out_handle = IPC::InvalidPlatformFileForTransit();
- }
-#elif defined(OS_POSIX)
- // If asked to close the source, we can simply re-use the source fd instead of
- // dup()ing and close()ing.
- // When we're not closing the source, we need to duplicate the handle and take
- // ownership of that. The reason is that this function is often used to
- // generate IPC messages, and the handle must remain valid until it's sent to
- // the other process from the I/O thread. Without the dup, calling code might
- // close the source handle before the message is sent, creating a race
- // condition.
- int fd = should_close_source ? handle : ::dup(handle);
- out_handle = base::FileDescriptor(fd, true);
-#else
- #error Not implemented.
-#endif
- return out_handle;
+ return IPC::GetPlatformFileForTransit(handle, should_close_source);
}
} // namespace content
diff --git a/chromium/content/common/sandbox_win.cc b/chromium/content/common/sandbox_win.cc
index 92a5a241f57..fe266227ad8 100644
--- a/chromium/content/common/sandbox_win.cc
+++ b/chromium/content/common/sandbox_win.cc
@@ -32,7 +32,6 @@
#include "content/common/content_switches_internal.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
-#include "content/public/common/dwrite_font_platform_win.h"
#include "content/public/common/sandbox_init.h"
#include "content/public/common/sandboxed_process_launcher_delegate.h"
#include "sandbox/win/src/process_mitigations.h"
@@ -403,7 +402,6 @@ bool AddPolicyForSandboxedProcess(sandbox::TargetPolicy* policy) {
if (result != sandbox::SBOX_ALL_OK)
return false;
-
sandbox::TokenLevel initial_token = sandbox::USER_UNPROTECTED;
if (base::win::GetVersion() > base::win::VERSION_XP) {
// On 2003/Vista the initial token has to be restricted if the main
@@ -415,6 +413,7 @@ bool AddPolicyForSandboxedProcess(sandbox::TargetPolicy* policy) {
// Prevents the renderers from manipulating low-integrity processes.
policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_UNTRUSTED);
policy->SetIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
+ policy->SetLockdownDefaultDacl();
if (sandbox::SBOX_ALL_OK != policy->SetAlternateDesktop(true)) {
DLOG(WARNING) << "Failed to apply desktop security to the renderer";
@@ -665,7 +664,8 @@ bool InitTargetServices(sandbox::TargetServices* target_services) {
base::Process StartSandboxedProcess(
SandboxedProcessLauncherDelegate* delegate,
- base::CommandLine* cmd_line) {
+ base::CommandLine* cmd_line,
+ const base::HandlesToInheritVector& handles_to_inherit) {
DCHECK(delegate);
const base::CommandLine& browser_command_line =
*base::CommandLine::ForCurrentProcess();
@@ -684,20 +684,41 @@ base::Process StartSandboxedProcess(
if ((!delegate->ShouldSandbox()) ||
browser_command_line.HasSwitch(switches::kNoSandbox) ||
cmd_line->HasSwitch(switches::kNoSandbox)) {
- base::Process process =
- base::LaunchProcess(*cmd_line, base::LaunchOptions());
+ base::LaunchOptions options;
+
+ base::HandlesToInheritVector handles = handles_to_inherit;
+ if (!handles_to_inherit.empty()) {
+ options.inherit_handles = true;
+ options.handles_to_inherit = &handles;
+ }
+ base::Process process = base::LaunchProcess(*cmd_line, options);
+
// TODO(rvargas) crbug.com/417532: Don't share a raw handle.
g_broker_services->AddTargetPeer(process.Handle());
- return process.Pass();
+ return process;
}
sandbox::TargetPolicy* policy = g_broker_services->CreatePolicy();
- sandbox::MitigationFlags mitigations = sandbox::MITIGATION_HEAP_TERMINATE |
- sandbox::MITIGATION_BOTTOM_UP_ASLR |
- sandbox::MITIGATION_DEP |
- sandbox::MITIGATION_DEP_NO_ATL_THUNK |
- sandbox::MITIGATION_SEHOP;
+ // Add any handles to be inherited to the policy.
+ for (HANDLE handle : handles_to_inherit)
+ policy->AddHandleToShare(handle);
+
+ // Pre-startup mitigations.
+ sandbox::MitigationFlags mitigations =
+ sandbox::MITIGATION_HEAP_TERMINATE |
+ sandbox::MITIGATION_BOTTOM_UP_ASLR |
+ sandbox::MITIGATION_DEP |
+ sandbox::MITIGATION_DEP_NO_ATL_THUNK |
+ sandbox::MITIGATION_SEHOP |
+ sandbox::MITIGATION_NONSYSTEM_FONT_DISABLE |
+ sandbox::MITIGATION_IMAGE_LOAD_NO_REMOTE |
+ sandbox::MITIGATION_IMAGE_LOAD_NO_LOW_LABEL;
+#if !defined(NACL_WIN64)
+ // Don't block font loading with GDI.
+ if (!gfx::win::ShouldUseDirectWrite())
+ mitigations ^= sandbox::MITIGATION_NONSYSTEM_FONT_DISABLE;
+#endif
if (policy->SetProcessMitigations(mitigations) != sandbox::SBOX_ALL_OK)
return base::Process();
@@ -710,6 +731,7 @@ base::Process StartSandboxedProcess(
}
#endif
+ // Post-startup mitigations.
mitigations = sandbox::MITIGATION_STRICT_HANDLE_CHECKS |
sandbox::MITIGATION_DLL_SEARCH_ORDER;
@@ -724,6 +746,9 @@ base::Process StartSandboxedProcess(
}
#if !defined(NACL_WIN64)
+ // NOTE: This is placed at function scope so that it stays alive through
+ // process launch.
+ base::SharedMemory direct_write_font_cache_section;
if (type_str == switches::kRendererProcess ||
type_str == switches::kPpapiPluginProcess) {
if (gfx::win::ShouldUseDirectWrite()) {
@@ -732,25 +757,6 @@ base::Process StartSandboxedProcess(
true,
sandbox::TargetPolicy::FILES_ALLOW_READONLY,
policy);
-
- if (!ShouldUseDirectWriteFontProxyFieldTrial()) {
- // If DirectWrite is enabled for font rendering then open the font
- // cache section which is created by the browser and pass the handle to
- // the renderer process. This is needed because renderer processes on
- // Windows 8+ may be running in an AppContainer sandbox and hence their
- // kernel object namespace may be partitioned.
- std::string name(content::kFontCacheSharedSectionName);
- name.append(base::UintToString(base::GetCurrentProcId()));
-
- base::SharedMemory direct_write_font_cache_section;
- if (direct_write_font_cache_section.Open(name, true)) {
- void* shared_handle = policy->AddHandleToShare(
- direct_write_font_cache_section.handle().GetHandle());
- cmd_line->AppendSwitchASCII(
- switches::kFontCacheSharedHandle,
- base::UintToString(base::win::HandleToUint32(shared_handle)));
- }
- }
}
}
#endif
diff --git a/chromium/content/common/service_port_service.mojom b/chromium/content/common/service_port_service.mojom
deleted file mode 100644
index d5bbb58a497..00000000000
--- a/chromium/content/common/service_port_service.mojom
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module content;
-
-enum ServicePortConnectResult {
- ACCEPT,
- REJECT
-};
-
-struct MojoTransferredMessagePort {
- int32 id;
- bool send_messages_as_values;
-};
-
-interface ServicePortService {
- SetClient(ServicePortServiceClient client);
-
- Connect(string target_url, string origin)
- => (ServicePortConnectResult result, int32 port_id);
-
- PostMessageToPort(int32 port_id, string message,
- array<MojoTransferredMessagePort> ports);
- ClosePort(int32 port_id);
-};
-
-interface ServicePortServiceClient {
- PostMessageToPort(int32 port_id, string message,
- array<MojoTransferredMessagePort> ports,
- array<int32> new_routing_ids);
-};
-
-interface ServicePortDispatcher {
- Connect(string target_url, string origin, int32 port_id)
- => (ServicePortConnectResult result, string name, string data);
-};
diff --git a/chromium/content/common/service_port_type_converters.cc b/chromium/content/common/service_port_type_converters.cc
deleted file mode 100644
index c07a946a972..00000000000
--- a/chromium/content/common/service_port_type_converters.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/service_port_type_converters.h"
-
-namespace mojo {
-
-// static
-content::TransferredMessagePort
-TypeConverter<content::TransferredMessagePort,
- content::MojoTransferredMessagePortPtr>::
- Convert(const content::MojoTransferredMessagePortPtr& input) {
- content::TransferredMessagePort output;
- output.id = input->id;
- output.send_messages_as_values = input->send_messages_as_values;
- return output;
-}
-
-// static
-content::MojoTransferredMessagePortPtr
-TypeConverter<content::MojoTransferredMessagePortPtr,
- content::TransferredMessagePort>::
- Convert(const content::TransferredMessagePort& input) {
- content::MojoTransferredMessagePortPtr output(
- content::MojoTransferredMessagePort::New());
- output->id = input.id;
- output->send_messages_as_values = input.send_messages_as_values;
- return output;
-}
-
-} // namespace mojo
diff --git a/chromium/content/common/service_port_type_converters.h b/chromium/content/common/service_port_type_converters.h
deleted file mode 100644
index 70e01f9329c..00000000000
--- a/chromium/content/common/service_port_type_converters.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_COMMON_SERVICE_PORT_TYPE_CONVERTERS_H_
-#define CONTENT_COMMON_SERVICE_PORT_TYPE_CONVERTERS_H_
-
-#include "content/common/content_export.h"
-#include "content/common/service_port_service.mojom.h"
-#include "content/public/common/message_port_types.h"
-#include "mojo/public/cpp/bindings/type_converter.h"
-
-namespace mojo {
-
-template <>
-struct CONTENT_EXPORT TypeConverter<content::TransferredMessagePort,
- content::MojoTransferredMessagePortPtr> {
- static content::TransferredMessagePort Convert(
- const content::MojoTransferredMessagePortPtr& input);
-};
-
-template <>
-struct CONTENT_EXPORT TypeConverter<content::MojoTransferredMessagePortPtr,
- content::TransferredMessagePort> {
- static content::MojoTransferredMessagePortPtr Convert(
- const content::TransferredMessagePort& input);
-};
-
-} // namespace mojo
-
-#endif // CONTENT_COMMON_SERVICE_PORT_TYPE_CONVERTERS_H_
diff --git a/chromium/content/common/service_worker/embedded_worker_messages.h b/chromium/content/common/service_worker/embedded_worker_messages.h
index fc9f02ea343..86fb48c8507 100644
--- a/chromium/content/common/service_worker/embedded_worker_messages.h
+++ b/chromium/content/common/service_worker/embedded_worker_messages.h
@@ -8,6 +8,7 @@
#include <string>
+#include "content/common/service_worker/embedded_worker_settings.h"
#include "content/public/common/web_preferences.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_message_macros.h"
@@ -19,6 +20,11 @@
#define IPC_MESSAGE_START EmbeddedWorkerMsgStart
+IPC_STRUCT_TRAITS_BEGIN(content::EmbeddedWorkerSettings)
+ IPC_STRUCT_TRAITS_MEMBER(v8_cache_options)
+ IPC_STRUCT_TRAITS_MEMBER(data_saver_enabled)
+IPC_STRUCT_TRAITS_END()
+
// Parameters structure for EmbeddedWorkerMsg_StartWorker.
IPC_STRUCT_BEGIN(EmbeddedWorkerMsg_StartWorker_Params)
IPC_STRUCT_MEMBER(int, embedded_worker_id)
@@ -26,8 +32,10 @@ IPC_STRUCT_BEGIN(EmbeddedWorkerMsg_StartWorker_Params)
IPC_STRUCT_MEMBER(GURL, scope)
IPC_STRUCT_MEMBER(GURL, script_url)
IPC_STRUCT_MEMBER(int, worker_devtools_agent_route_id)
+ IPC_STRUCT_MEMBER(bool, pause_after_download)
IPC_STRUCT_MEMBER(bool, wait_for_debugger)
- IPC_STRUCT_MEMBER(content::V8CacheOptions, v8_cache_options)
+ IPC_STRUCT_MEMBER(bool, is_installed)
+ IPC_STRUCT_MEMBER(content::EmbeddedWorkerSettings, settings)
IPC_STRUCT_END()
// Parameters structure for EmbeddedWorkerHostMsg_ReportConsoleMessage.
@@ -45,6 +53,11 @@ IPC_STRUCT_END()
IPC_MESSAGE_CONTROL1(EmbeddedWorkerMsg_StartWorker,
EmbeddedWorkerMsg_StartWorker_Params /* params */)
+// Browser -> Renderer message to resume a worker that has been started
+// with the pause_after_download option.
+IPC_MESSAGE_CONTROL1(EmbeddedWorkerMsg_ResumeAfterDownload,
+ int /* embedded_worker_id */)
+
// Browser -> Renderer message to stop (terminate) the embedded worker.
IPC_MESSAGE_CONTROL1(EmbeddedWorkerMsg_StopWorker,
int /* embedded_worker_id */)
diff --git a/chromium/content/common/service_worker/embedded_worker_settings.h b/chromium/content/common/service_worker/embedded_worker_settings.h
new file mode 100644
index 00000000000..2014dae91c4
--- /dev/null
+++ b/chromium/content/common/service_worker/embedded_worker_settings.h
@@ -0,0 +1,19 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_COMMON_SERVICE_WORKER_EMBEDDED_WORKER_SETTINGS_H_
+#define CONTENT_COMMON_SERVICE_WORKER_EMBEDDED_WORKER_SETTINGS_H_
+
+#include "content/public/common/web_preferences.h"
+
+namespace content {
+
+struct EmbeddedWorkerSettings {
+ content::V8CacheOptions v8_cache_options;
+ bool data_saver_enabled;
+};
+
+} // namespace content
+
+#endif // CONTENT_COMMON_SERVICE_WORKER_EMBEDDED_WORKER_SETTINGS_H_
diff --git a/chromium/content/common/service_worker/embedded_worker_setup.mojom b/chromium/content/common/service_worker/embedded_worker_setup.mojom
index 4a748541c1e..ad4583d1c64 100644
--- a/chromium/content/common/service_worker/embedded_worker_setup.mojom
+++ b/chromium/content/common/service_worker/embedded_worker_setup.mojom
@@ -2,12 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-module content;
+module content.mojom;
-import "mojo/shell/public/interfaces/service_provider.mojom";
+import "mojo/shell/public/interfaces/interface_provider.mojom";
interface EmbeddedWorkerSetup {
- ExchangeServiceProviders(int32 thread_id,
- mojo.ServiceProvider& services,
- mojo.ServiceProvider exposed_services);
+ ExchangeInterfaceProviders(
+ int32 thread_id,
+ mojo.shell.mojom.InterfaceProvider& remote_interfaces,
+ mojo.shell.mojom.InterfaceProvider local_interfaces);
};
diff --git a/chromium/content/common/service_worker/service_worker_client_info.cc b/chromium/content/common/service_worker/service_worker_client_info.cc
index c864369c039..a412fa0b7de 100644
--- a/chromium/content/common/service_worker/service_worker_client_info.cc
+++ b/chromium/content/common/service_worker/service_worker_client_info.cc
@@ -10,25 +10,32 @@
namespace content {
ServiceWorkerClientInfo::ServiceWorkerClientInfo()
- : page_visibility_state(blink::WebPageVisibilityStateLast),
- is_focused(false),
- frame_type(REQUEST_CONTEXT_FRAME_TYPE_LAST),
- client_type(blink::WebServiceWorkerClientTypeLast),
- last_focus_time(base::TimeTicks()) {}
+ : ServiceWorkerClientInfo(std::string(),
+ blink::WebPageVisibilityStateLast,
+ false,
+ GURL(),
+ REQUEST_CONTEXT_FRAME_TYPE_LAST,
+ base::TimeTicks(),
+ blink::WebServiceWorkerClientTypeLast) {}
ServiceWorkerClientInfo::ServiceWorkerClientInfo(
+ const std::string& client_uuid,
blink::WebPageVisibilityState page_visibility_state,
bool is_focused,
const GURL& url,
RequestContextFrameType frame_type,
base::TimeTicks last_focus_time,
blink::WebServiceWorkerClientType client_type)
- : page_visibility_state(page_visibility_state),
+ : client_uuid(client_uuid),
+ page_visibility_state(page_visibility_state),
is_focused(is_focused),
url(url),
frame_type(frame_type),
- client_type(client_type),
- last_focus_time(last_focus_time) {}
+ last_focus_time(last_focus_time),
+ client_type(client_type) {}
+
+ServiceWorkerClientInfo::ServiceWorkerClientInfo(
+ const ServiceWorkerClientInfo& other) = default;
bool ServiceWorkerClientInfo::IsEmpty() const {
return page_visibility_state == blink::WebPageVisibilityStateLast &&
diff --git a/chromium/content/common/service_worker/service_worker_client_info.h b/chromium/content/common/service_worker/service_worker_client_info.h
index 1c81fe34816..93bfdf447a2 100644
--- a/chromium/content/common/service_worker/service_worker_client_info.h
+++ b/chromium/content/common/service_worker/service_worker_client_info.h
@@ -20,12 +20,14 @@ namespace content {
// constructor to fill the properties.
struct ServiceWorkerClientInfo {
ServiceWorkerClientInfo();
- ServiceWorkerClientInfo(blink::WebPageVisibilityState page_visibility_state,
+ ServiceWorkerClientInfo(const std::string& client_uuid,
+ blink::WebPageVisibilityState page_visibility_state,
bool is_focused,
const GURL& url,
RequestContextFrameType frame_type,
base::TimeTicks last_focus_time,
blink::WebServiceWorkerClientType client_type);
+ ServiceWorkerClientInfo(const ServiceWorkerClientInfo& other);
// Returns whether the instance is empty.
bool IsEmpty() const;
@@ -39,8 +41,8 @@ struct ServiceWorkerClientInfo {
bool is_focused;
GURL url;
RequestContextFrameType frame_type;
- blink::WebServiceWorkerClientType client_type;
base::TimeTicks last_focus_time;
+ blink::WebServiceWorkerClientType client_type;
};
} // namespace content
diff --git a/chromium/content/common/service_worker/service_worker_messages.h b/chromium/content/common/service_worker/service_worker_messages.h
index 8ba0e58e7f0..41698cff41e 100644
--- a/chromium/content/common/service_worker/service_worker_messages.h
+++ b/chromium/content/common/service_worker/service_worker_messages.h
@@ -14,8 +14,8 @@
#include "content/common/service_worker/service_worker_status_code.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/common/message_port_types.h"
-#include "content/public/common/navigator_connect_client.h"
#include "content/public/common/platform_notification_data.h"
+#include "content/public/common/push_event_payload.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_param_traits.h"
#include "third_party/WebKit/public/platform/WebCircularGeofencingRegion.h"
@@ -23,6 +23,7 @@
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerError.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerEventResult.h"
#include "url/gurl.h"
+#include "url/origin.h"
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
@@ -50,6 +51,14 @@ IPC_ENUM_TRAITS_MAX_VALUE(blink::WebServiceWorkerClientType,
IPC_ENUM_TRAITS_MAX_VALUE(content::ServiceWorkerProviderType,
content::SERVICE_WORKER_PROVIDER_TYPE_LAST)
+IPC_ENUM_TRAITS_MAX_VALUE(content::ServiceWorkerFetchType,
+ content::ServiceWorkerFetchType::LAST)
+
+IPC_STRUCT_TRAITS_BEGIN(content::ExtendableMessageEventSource)
+ IPC_STRUCT_TRAITS_MEMBER(client_info)
+ IPC_STRUCT_TRAITS_MEMBER(service_worker_info)
+IPC_STRUCT_TRAITS_END()
+
IPC_STRUCT_TRAITS_BEGIN(content::ServiceWorkerFetchRequest)
IPC_STRUCT_TRAITS_MEMBER(mode)
IPC_STRUCT_TRAITS_MEMBER(is_main_resource_load)
@@ -65,6 +74,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::ServiceWorkerFetchRequest)
IPC_STRUCT_TRAITS_MEMBER(redirect_mode)
IPC_STRUCT_TRAITS_MEMBER(client_id)
IPC_STRUCT_TRAITS_MEMBER(is_reload)
+ IPC_STRUCT_TRAITS_MEMBER(fetch_type)
IPC_STRUCT_TRAITS_END()
IPC_ENUM_TRAITS_MAX_VALUE(content::ServiceWorkerFetchEventResult,
@@ -80,6 +90,9 @@ IPC_STRUCT_TRAITS_BEGIN(content::ServiceWorkerResponse)
IPC_STRUCT_TRAITS_MEMBER(blob_size)
IPC_STRUCT_TRAITS_MEMBER(stream_url)
IPC_STRUCT_TRAITS_MEMBER(error)
+ IPC_STRUCT_TRAITS_MEMBER(response_time)
+ IPC_STRUCT_TRAITS_MEMBER(is_in_cache_storage)
+ IPC_STRUCT_TRAITS_MEMBER(cache_storage_cache_name)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(content::ServiceWorkerObjectInfo)
@@ -115,6 +128,14 @@ IPC_STRUCT_TRAITS_BEGIN(content::ServiceWorkerClientQueryOptions)
IPC_STRUCT_TRAITS_MEMBER(include_uncontrolled)
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_BEGIN(ServiceWorkerMsg_ExtendableMessageEvent_Params)
+ IPC_STRUCT_MEMBER(base::string16, message)
+ IPC_STRUCT_MEMBER(url::Origin, source_origin)
+ IPC_STRUCT_MEMBER(std::vector<content::TransferredMessagePort>, message_ports)
+ IPC_STRUCT_MEMBER(std::vector<int>, new_routing_ids)
+ IPC_STRUCT_MEMBER(content::ExtendableMessageEventSource, source)
+IPC_STRUCT_END()
+
IPC_STRUCT_BEGIN(ServiceWorkerMsg_MessageToDocument_Params)
IPC_STRUCT_MEMBER(int, thread_id)
IPC_STRUCT_MEMBER(int, provider_id)
@@ -127,10 +148,9 @@ IPC_STRUCT_END()
IPC_ENUM_TRAITS_MAX_VALUE(blink::WebGeofencingEventType,
blink::WebGeofencingEventTypeLast)
-IPC_STRUCT_TRAITS_BEGIN(content::NavigatorConnectClient)
- IPC_STRUCT_TRAITS_MEMBER(target_url)
- IPC_STRUCT_TRAITS_MEMBER(origin)
- IPC_STRUCT_TRAITS_MEMBER(message_port_id)
+IPC_STRUCT_TRAITS_BEGIN(content::PushEventPayload)
+ IPC_STRUCT_TRAITS_MEMBER(data)
+ IPC_STRUCT_TRAITS_MEMBER(is_null)
IPC_STRUCT_TRAITS_END()
//---------------------------------------------------------------------------
@@ -171,10 +191,21 @@ IPC_MESSAGE_CONTROL3(ServiceWorkerHostMsg_GetRegistrationForReady,
int /* request_id */,
int /* provider_id */)
-// Sends a 'message' event to a service worker (renderer->browser).
-IPC_MESSAGE_CONTROL3(
+// Sends ExtendableMessageEvent to a service worker (renderer->browser).
+IPC_MESSAGE_CONTROL5(
ServiceWorkerHostMsg_PostMessageToWorker,
int /* handle_id */,
+ int /* provider_id */,
+ base::string16 /* message */,
+ url::Origin /* source_origin */,
+ std::vector<content::TransferredMessagePort> /* sent_message_ports */)
+
+// Sends MessageEvent to a service worker (renderer->browser).
+// TODO(nhiroki): Remove this after ExtendableMessageEvent is enabled by
+// default (crbug.com/543198).
+IPC_MESSAGE_CONTROL3(
+ ServiceWorkerHostMsg_DeprecatedPostMessageToWorker,
+ int /* handle_id */,
base::string16 /* message */,
std::vector<content::TransferredMessagePort> /* sent_message_ports */)
@@ -231,12 +262,19 @@ IPC_MESSAGE_ROUTED2(ServiceWorkerHostMsg_InstallEventFinished,
IPC_MESSAGE_ROUTED2(ServiceWorkerHostMsg_ActivateEventFinished,
int /* request_id */,
blink::WebServiceWorkerEventResult)
+IPC_MESSAGE_ROUTED2(ServiceWorkerHostMsg_ExtendableMessageEventFinished,
+ int /* request_id */,
+ blink::WebServiceWorkerEventResult)
IPC_MESSAGE_ROUTED3(ServiceWorkerHostMsg_FetchEventFinished,
int /* request_id */,
content::ServiceWorkerFetchEventResult,
content::ServiceWorkerResponse)
-IPC_MESSAGE_ROUTED1(ServiceWorkerHostMsg_NotificationClickEventFinished,
- int /* request_id */)
+IPC_MESSAGE_ROUTED2(ServiceWorkerHostMsg_NotificationClickEventFinished,
+ int /* request_id */,
+ blink::WebServiceWorkerEventResult)
+IPC_MESSAGE_ROUTED2(ServiceWorkerHostMsg_NotificationCloseEventFinished,
+ int /* request_id */,
+ blink::WebServiceWorkerEventResult)
IPC_MESSAGE_ROUTED2(ServiceWorkerHostMsg_PushEventFinished,
int /* request_id */,
blink::WebServiceWorkerEventResult)
@@ -248,12 +286,17 @@ IPC_MESSAGE_ROUTED2(ServiceWorkerHostMsg_GeofencingEventFinished,
// Routed to the target ServiceWorkerVersion.
IPC_MESSAGE_ROUTED0(ServiceWorkerHostMsg_Pong)
+// Asks the browser to retrieve client of the sender ServiceWorker.
+IPC_MESSAGE_ROUTED2(ServiceWorkerHostMsg_GetClient,
+ int /* request_id */,
+ std::string /* client_uuid */)
+
// Asks the browser to retrieve clients of the sender ServiceWorker.
IPC_MESSAGE_ROUTED2(ServiceWorkerHostMsg_GetClients,
int /* request_id */,
content::ServiceWorkerClientQueryOptions)
-// Sends a 'message' event to a client (renderer->browser).
+// Sends MessageEvent to a client (renderer->browser).
IPC_MESSAGE_ROUTED3(
ServiceWorkerHostMsg_PostMessageToClient,
std::string /* uuid */,
@@ -297,8 +340,9 @@ IPC_MESSAGE_ROUTED1(ServiceWorkerHostMsg_ClaimClients,
// Informs the browser of new foreign fetch subscopes this worker wants to
// handle. Should only be sent while an install event is being handled.
-IPC_MESSAGE_ROUTED1(ServiceWorkerHostMsg_RegisterForeignFetchScopes,
- std::vector<GURL> /* sub_scopes */)
+IPC_MESSAGE_ROUTED2(ServiceWorkerHostMsg_RegisterForeignFetchScopes,
+ std::vector<GURL> /* sub_scopes */,
+ std::vector<url::Origin> /* origins */)
//---------------------------------------------------------------------------
// Messages sent from the browser to the child process.
@@ -425,7 +469,7 @@ IPC_MESSAGE_CONTROL4(ServiceWorkerMsg_SetControllerServiceWorker,
content::ServiceWorkerObjectInfo,
bool /* should_notify_controllerchange */)
-// Sends a 'message' event to a client document (browser->renderer).
+// Sends MessageEvent to a client document (browser->renderer).
IPC_MESSAGE_CONTROL1(ServiceWorkerMsg_MessageToDocument,
ServiceWorkerMsg_MessageToDocument_Params)
@@ -434,6 +478,9 @@ IPC_MESSAGE_CONTROL1(ServiceWorkerMsg_InstallEvent,
int /* request_id */)
IPC_MESSAGE_CONTROL1(ServiceWorkerMsg_ActivateEvent,
int /* request_id */)
+IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_ExtendableMessageEvent,
+ int /* request_id */,
+ ServiceWorkerMsg_ExtendableMessageEvent_Params)
IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_FetchEvent,
int /* request_id */,
content::ServiceWorkerFetchRequest)
@@ -442,25 +489,27 @@ IPC_MESSAGE_CONTROL4(ServiceWorkerMsg_NotificationClickEvent,
int64_t /* persistent_notification_id */,
content::PlatformNotificationData /* notification_data */,
int /* action_index */)
+IPC_MESSAGE_CONTROL3(ServiceWorkerMsg_NotificationCloseEvent,
+ int /* request_id */,
+ int64_t /* persistent_notification_id */,
+ content::PlatformNotificationData /* notification_data */)
IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_PushEvent,
int /* request_id */,
- std::string /* data */)
+ content::PushEventPayload /* data */)
IPC_MESSAGE_CONTROL4(ServiceWorkerMsg_GeofencingEvent,
int /* request_id */,
blink::WebGeofencingEventType /* event_type */,
std::string /* region_id */,
blink::WebCircularGeofencingRegion /* region */)
+
+// TODO(nhiroki): Remove this after ExtendableMessageEvent is enabled by
+// default (crbug.com/543198).
IPC_MESSAGE_CONTROL3(
ServiceWorkerMsg_MessageToWorker,
base::string16 /* message */,
std::vector<content::TransferredMessagePort> /* sent_message_ports */,
std::vector<int> /* new_routing_ids */)
-IPC_MESSAGE_CONTROL4(
- ServiceWorkerMsg_CrossOriginMessageToWorker,
- content::NavigatorConnectClient /* client */,
- base::string16 /* message */,
- std::vector<content::TransferredMessagePort> /* sent_message_ports */,
- std::vector<int> /* new_routing_ids */)
+
IPC_MESSAGE_CONTROL1(ServiceWorkerMsg_DidSkipWaiting,
int /* request_id */)
IPC_MESSAGE_CONTROL1(ServiceWorkerMsg_DidClaimClients,
@@ -473,6 +522,11 @@ IPC_MESSAGE_CONTROL3(ServiceWorkerMsg_ClaimClientsError,
// Sent via EmbeddedWorker to Ping the worker, expecting a Pong in response.
IPC_MESSAGE_CONTROL0(ServiceWorkerMsg_Ping)
+// Sent via EmbeddedWorker as a response of GetClient.
+IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_DidGetClient,
+ int /* request_id */,
+ content::ServiceWorkerClientInfo)
+
// Sent via EmbeddedWorker as a response of GetClients.
IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_DidGetClients,
int /* request_id */,
diff --git a/chromium/content/common/service_worker/service_worker_status_code.h b/chromium/content/common/service_worker/service_worker_status_code.h
index 3dff585c4b2..24be8167310 100644
--- a/chromium/content/common/service_worker/service_worker_status_code.h
+++ b/chromium/content/common/service_worker/service_worker_status_code.h
@@ -10,69 +10,74 @@
namespace content {
// Generic service worker operation statuses.
-// This enum is used in UMA histograms, so don't change the order or remove
-// entries.
+// This enum is used in UMA histograms. Append-only.
enum ServiceWorkerStatusCode {
// Operation succeeded.
- SERVICE_WORKER_OK,
+ SERVICE_WORKER_OK = 0,
// Generic operation error (more specific error code should be used in
// general).
- SERVICE_WORKER_ERROR_FAILED,
+ SERVICE_WORKER_ERROR_FAILED = 1,
// Operation was aborted (e.g. due to context or child process shutdown).
- SERVICE_WORKER_ERROR_ABORT,
+ SERVICE_WORKER_ERROR_ABORT = 2,
// Starting a new service worker script context failed.
- SERVICE_WORKER_ERROR_START_WORKER_FAILED,
+ SERVICE_WORKER_ERROR_START_WORKER_FAILED = 3,
// Could not find a renderer process to run a service worker.
- SERVICE_WORKER_ERROR_PROCESS_NOT_FOUND,
+ SERVICE_WORKER_ERROR_PROCESS_NOT_FOUND = 4,
// Generic error code to indicate the specified item is not found.
- SERVICE_WORKER_ERROR_NOT_FOUND,
+ SERVICE_WORKER_ERROR_NOT_FOUND = 5,
// Generic error code to indicate the specified item already exists.
- SERVICE_WORKER_ERROR_EXISTS,
+ SERVICE_WORKER_ERROR_EXISTS = 6,
// Install event handling failed.
- SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED,
+ SERVICE_WORKER_ERROR_INSTALL_WORKER_FAILED = 7,
// Activate event handling failed.
- SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED,
+ SERVICE_WORKER_ERROR_ACTIVATE_WORKER_FAILED = 8,
// Sending an IPC to the worker failed (often due to child process is
// terminated).
- SERVICE_WORKER_ERROR_IPC_FAILED,
+ SERVICE_WORKER_ERROR_IPC_FAILED = 9,
// Operation is failed by network issue.
- SERVICE_WORKER_ERROR_NETWORK,
+ SERVICE_WORKER_ERROR_NETWORK = 10,
// Operation is failed by security issue.
- SERVICE_WORKER_ERROR_SECURITY,
+ SERVICE_WORKER_ERROR_SECURITY = 11,
// Event handling failed (event.waitUntil Promise rejected).
- SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED,
+ SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED = 12,
// An error triggered by invalid worker state.
- SERVICE_WORKER_ERROR_STATE,
+ SERVICE_WORKER_ERROR_STATE = 13,
// The Service Worker took too long to finish a task.
- SERVICE_WORKER_ERROR_TIMEOUT,
+ SERVICE_WORKER_ERROR_TIMEOUT = 14,
// An error occurred during initial script evaluation.
- SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED,
+ SERVICE_WORKER_ERROR_SCRIPT_EVALUATE_FAILED = 15,
// Generic error to indicate failure to read/write the disk cache.
- SERVICE_WORKER_ERROR_DISK_CACHE,
+ SERVICE_WORKER_ERROR_DISK_CACHE = 16,
// The worker is in REDUNDANT state.
- SERVICE_WORKER_ERROR_REDUNDANT,
+ SERVICE_WORKER_ERROR_REDUNDANT = 17,
- // The worker was disallowed.
- SERVICE_WORKER_ERROR_DISALLOWED,
+ // The worker was disallowed (by ContentClient: e.g., due to
+ // browser settings).
+ SERVICE_WORKER_ERROR_DISALLOWED = 18,
- SERVICE_WORKER_ERROR_MAX_VALUE
+ // Obsolete.
+ // SERVICE_WORKER_ERROR_DISABLED_WORKER = 19,
+
+ // Add new status codes here.
+
+ SERVICE_WORKER_ERROR_MAX_VALUE = 20
};
CONTENT_EXPORT const char* ServiceWorkerStatusToString(
diff --git a/chromium/content/common/service_worker/service_worker_type_converters.cc b/chromium/content/common/service_worker/service_worker_type_converters.cc
index 735f529a932..b752e142772 100644
--- a/chromium/content/common/service_worker/service_worker_type_converters.cc
+++ b/chromium/content/common/service_worker/service_worker_type_converters.cc
@@ -12,14 +12,14 @@ namespace mojo {
// static cast.
content::ServiceWorkerStatusCode
TypeConverter<content::ServiceWorkerStatusCode,
- content::ServiceWorkerEventStatus>::
- Convert(content::ServiceWorkerEventStatus status) {
+ content::mojom::ServiceWorkerEventStatus>::
+ Convert(content::mojom::ServiceWorkerEventStatus status) {
content::ServiceWorkerStatusCode status_code;
- if (status == content::SERVICE_WORKER_EVENT_STATUS_COMPLETED) {
+ if (status == content::mojom::ServiceWorkerEventStatus::COMPLETED) {
status_code = content::SERVICE_WORKER_OK;
- } else if (status == content::SERVICE_WORKER_EVENT_STATUS_REJECTED) {
+ } else if (status == content::mojom::ServiceWorkerEventStatus::REJECTED) {
status_code = content::SERVICE_WORKER_ERROR_EVENT_WAITUNTIL_REJECTED;
- } else if (status == content::SERVICE_WORKER_EVENT_STATUS_ABORTED) {
+ } else if (status == content::mojom::ServiceWorkerEventStatus::ABORTED) {
status_code = content::SERVICE_WORKER_ERROR_ABORT;
} else {
// We received an unexpected value back. This can theoretically happen as
diff --git a/chromium/content/common/service_worker/service_worker_type_converters.h b/chromium/content/common/service_worker/service_worker_type_converters.h
index 42606e34dc9..4c43fdaf8c0 100644
--- a/chromium/content/common/service_worker/service_worker_type_converters.h
+++ b/chromium/content/common/service_worker/service_worker_type_converters.h
@@ -12,9 +12,9 @@ namespace mojo {
template <>
struct CONTENT_EXPORT TypeConverter<content::ServiceWorkerStatusCode,
- content::ServiceWorkerEventStatus> {
+ content::mojom::ServiceWorkerEventStatus> {
static content::ServiceWorkerStatusCode Convert(
- content::ServiceWorkerEventStatus status);
+ content::mojom::ServiceWorkerEventStatus status);
};
} // namespace
diff --git a/chromium/content/common/service_worker/service_worker_types.cc b/chromium/content/common/service_worker/service_worker_types.cc
index e9ff0b96319..a320c29725a 100644
--- a/chromium/content/common/service_worker/service_worker_types.cc
+++ b/chromium/content/common/service_worker/service_worker_types.cc
@@ -27,7 +27,8 @@ ServiceWorkerFetchRequest::ServiceWorkerFetchRequest()
blob_size(0),
credentials_mode(FETCH_CREDENTIALS_MODE_OMIT),
redirect_mode(FetchRedirectMode::FOLLOW_MODE),
- is_reload(false) {}
+ is_reload(false),
+ fetch_type(ServiceWorkerFetchType::FETCH) {}
ServiceWorkerFetchRequest::ServiceWorkerFetchRequest(
const GURL& url,
@@ -46,7 +47,11 @@ ServiceWorkerFetchRequest::ServiceWorkerFetchRequest(
referrer(referrer),
credentials_mode(FETCH_CREDENTIALS_MODE_OMIT),
redirect_mode(FetchRedirectMode::FOLLOW_MODE),
- is_reload(is_reload) {}
+ is_reload(is_reload),
+ fetch_type(ServiceWorkerFetchType::FETCH) {}
+
+ServiceWorkerFetchRequest::ServiceWorkerFetchRequest(
+ const ServiceWorkerFetchRequest& other) = default;
ServiceWorkerFetchRequest::~ServiceWorkerFetchRequest() {}
@@ -54,8 +59,7 @@ ServiceWorkerResponse::ServiceWorkerResponse()
: status_code(0),
response_type(blink::WebServiceWorkerResponseTypeOpaque),
blob_size(0),
- error(blink::WebServiceWorkerResponseErrorUnknown) {
-}
+ error(blink::WebServiceWorkerResponseErrorUnknown) {}
ServiceWorkerResponse::ServiceWorkerResponse(
const GURL& url,
@@ -66,7 +70,10 @@ ServiceWorkerResponse::ServiceWorkerResponse(
const std::string& blob_uuid,
uint64_t blob_size,
const GURL& stream_url,
- blink::WebServiceWorkerResponseError error)
+ blink::WebServiceWorkerResponseError error,
+ base::Time response_time,
+ bool is_in_cache_storage,
+ const std::string& cache_storage_cache_name)
: url(url),
status_code(status_code),
status_text(status_text),
@@ -75,7 +82,13 @@ ServiceWorkerResponse::ServiceWorkerResponse(
blob_uuid(blob_uuid),
blob_size(blob_size),
stream_url(stream_url),
- error(error) {}
+ error(error),
+ response_time(response_time),
+ is_in_cache_storage(is_in_cache_storage),
+ cache_storage_cache_name(cache_storage_cache_name) {}
+
+ServiceWorkerResponse::ServiceWorkerResponse(
+ const ServiceWorkerResponse& other) = default;
ServiceWorkerResponse::~ServiceWorkerResponse() {}
@@ -84,6 +97,11 @@ ServiceWorkerObjectInfo::ServiceWorkerObjectInfo()
state(blink::WebServiceWorkerStateUnknown),
version_id(kInvalidServiceWorkerVersionId) {}
+bool ServiceWorkerObjectInfo::IsValid() const {
+ return handle_id != kInvalidServiceWorkerHandleId &&
+ version_id != kInvalidServiceWorkerVersionId;
+}
+
ServiceWorkerRegistrationObjectInfo::ServiceWorkerRegistrationObjectInfo()
: handle_id(kInvalidServiceWorkerRegistrationHandleId),
registration_id(kInvalidServiceWorkerRegistrationId) {
@@ -94,4 +112,14 @@ ServiceWorkerClientQueryOptions::ServiceWorkerClientQueryOptions()
include_uncontrolled(false) {
}
+ExtendableMessageEventSource::ExtendableMessageEventSource() {}
+
+ExtendableMessageEventSource::ExtendableMessageEventSource(
+ const ServiceWorkerClientInfo& client_info)
+ : client_info(client_info) {}
+
+ExtendableMessageEventSource::ExtendableMessageEventSource(
+ const ServiceWorkerObjectInfo& service_worker_info)
+ : service_worker_info(service_worker_info) {}
+
} // namespace content
diff --git a/chromium/content/common/service_worker/service_worker_types.h b/chromium/content/common/service_worker/service_worker_types.h
index d3a9f8f2a99..81f7d4f7d50 100644
--- a/chromium/content/common/service_worker/service_worker_types.h
+++ b/chromium/content/common/service_worker/service_worker_types.h
@@ -11,7 +11,9 @@
#include <string>
#include "base/strings/string_util.h"
+#include "base/time/time.h"
#include "content/common/content_export.h"
+#include "content/common/service_worker/service_worker_client_info.h"
#include "content/public/common/referrer.h"
#include "content/public/common/request_context_frame_type.h"
#include "content/public/common/request_context_type.h"
@@ -87,7 +89,8 @@ enum FetchCredentialsMode {
FETCH_CREDENTIALS_MODE_OMIT,
FETCH_CREDENTIALS_MODE_SAME_ORIGIN,
FETCH_CREDENTIALS_MODE_INCLUDE,
- FETCH_CREDENTIALS_MODE_LAST = FETCH_CREDENTIALS_MODE_INCLUDE
+ FETCH_CREDENTIALS_MODE_PASSWORD,
+ FETCH_CREDENTIALS_MODE_LAST = FETCH_CREDENTIALS_MODE_PASSWORD
};
enum class FetchRedirectMode {
@@ -106,6 +109,12 @@ enum ServiceWorkerFetchEventResult {
SERVICE_WORKER_FETCH_EVENT_LAST = SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE
};
+enum class ServiceWorkerFetchType {
+ FETCH,
+ FOREIGN_FETCH,
+ LAST = FOREIGN_FETCH
+};
+
struct ServiceWorkerCaseInsensitiveCompare {
bool operator()(const std::string& lhs, const std::string& rhs) const {
return base::CompareCaseInsensitiveASCII(lhs, rhs) < 0;
@@ -123,6 +132,7 @@ struct CONTENT_EXPORT ServiceWorkerFetchRequest {
const ServiceWorkerHeaderMap& headers,
const Referrer& referrer,
bool is_reload);
+ ServiceWorkerFetchRequest(const ServiceWorkerFetchRequest& other);
~ServiceWorkerFetchRequest();
FetchRequestMode mode;
@@ -139,6 +149,7 @@ struct CONTENT_EXPORT ServiceWorkerFetchRequest {
FetchRedirectMode redirect_mode;
std::string client_id;
bool is_reload;
+ ServiceWorkerFetchType fetch_type;
};
// Represents a response to a fetch.
@@ -152,7 +163,11 @@ struct CONTENT_EXPORT ServiceWorkerResponse {
const std::string& blob_uuid,
uint64_t blob_size,
const GURL& stream_url,
- blink::WebServiceWorkerResponseError error);
+ blink::WebServiceWorkerResponseError error,
+ base::Time response_time,
+ bool is_in_cache_storage,
+ const std::string& cache_storage_cache_name);
+ ServiceWorkerResponse(const ServiceWorkerResponse& other);
~ServiceWorkerResponse();
GURL url;
@@ -164,11 +179,19 @@ struct CONTENT_EXPORT ServiceWorkerResponse {
uint64_t blob_size;
GURL stream_url;
blink::WebServiceWorkerResponseError error;
+ base::Time response_time;
+ bool is_in_cache_storage = false;
+ std::string cache_storage_cache_name;
};
// Represents initialization info for a WebServiceWorker object.
struct CONTENT_EXPORT ServiceWorkerObjectInfo {
ServiceWorkerObjectInfo();
+
+ // Returns whether the instance is valid. A valid instance has valid
+ // |handle_id| and |version_id|.
+ bool IsValid() const;
+
int handle_id;
GURL url;
blink::WebServiceWorkerState state;
@@ -218,6 +241,18 @@ struct ServiceWorkerClientQueryOptions {
bool include_uncontrolled;
};
+struct ExtendableMessageEventSource {
+ ExtendableMessageEventSource();
+ explicit ExtendableMessageEventSource(
+ const ServiceWorkerClientInfo& client_info);
+ explicit ExtendableMessageEventSource(
+ const ServiceWorkerObjectInfo& service_worker_info);
+
+ // Exactly one of these infos should be valid.
+ ServiceWorkerClientInfo client_info;
+ ServiceWorkerObjectInfo service_worker_info;
+};
+
} // namespace content
#endif // CONTENT_COMMON_SERVICE_WORKER_SERVICE_WORKER_TYPES_H_
diff --git a/chromium/content/common/service_worker/service_worker_utils.cc b/chromium/content/common/service_worker/service_worker_utils.cc
index 62f197528f1..3a4971fc4ec 100644
--- a/chromium/content/common/service_worker/service_worker_utils.cc
+++ b/chromium/content/common/service_worker/service_worker_utils.cc
@@ -8,6 +8,7 @@
#include "base/logging.h"
#include "base/strings/string_util.h"
+#include "content/public/common/origin_util.h"
namespace content {
@@ -30,12 +31,16 @@ bool PathContainsDisallowedCharacter(const GURL& url) {
return false;
}
+bool AllOriginsMatch(const GURL& url_a, const GURL& url_b, const GURL& url_c) {
+ return url_a.GetOrigin() == url_b.GetOrigin() &&
+ url_a.GetOrigin() == url_c.GetOrigin();
+}
+
} // namespace
// static
bool ServiceWorkerUtils::ScopeMatches(const GURL& scope, const GURL& url) {
DCHECK(!scope.has_ref());
- DCHECK(!url.has_ref());
return base::StartsWith(url.spec(), scope.spec(),
base::CompareCase::SENSITIVE);
}
@@ -104,6 +109,19 @@ bool ServiceWorkerUtils::ContainsDisallowedCharacter(
return false;
}
+// static
+bool ServiceWorkerUtils::CanRegisterServiceWorker(const GURL& context_url,
+ const GURL& pattern,
+ const GURL& script_url) {
+ DCHECK(context_url.is_valid());
+ DCHECK(pattern.is_valid());
+ DCHECK(script_url.is_valid());
+ return AllOriginsMatch(context_url, pattern, script_url) &&
+ OriginCanAccessServiceWorkers(context_url) &&
+ OriginCanAccessServiceWorkers(pattern) &&
+ OriginCanAccessServiceWorkers(script_url);
+}
+
bool LongestScopeMatcher::MatchLongest(const GURL& scope) {
if (!ServiceWorkerUtils::ScopeMatches(scope, url_))
return false;
diff --git a/chromium/content/common/service_worker/service_worker_utils.h b/chromium/content/common/service_worker/service_worker_utils.h
index 8538b5ea304..5be59c0aa80 100644
--- a/chromium/content/common/service_worker/service_worker_utils.h
+++ b/chromium/content/common/service_worker/service_worker_utils.h
@@ -40,6 +40,10 @@ class ServiceWorkerUtils {
const GURL& script_url,
std::string* error_message);
+ static bool CanRegisterServiceWorker(const GURL& context_url,
+ const GURL& pattern,
+ const GURL& script_url);
+
// PlzNavigate
// Returns true if the |provider_id| was assigned by the browser process.
static bool IsBrowserAssignedProviderId(int provider_id) {
diff --git a/chromium/content/common/service_worker/service_worker_utils_unittest.cc b/chromium/content/common/service_worker/service_worker_utils_unittest.cc
index f8ab571682d..393c36ce158 100644
--- a/chromium/content/common/service_worker/service_worker_utils_unittest.cc
+++ b/chromium/content/common/service_worker/service_worker_utils_unittest.cc
@@ -38,6 +38,8 @@ TEST(ServiceWorkerUtilsTest, ScopeMatches) {
ASSERT_FALSE(ServiceWorkerUtils::ScopeMatches(
GURL("http://www.example.com/"),
GURL("https://www.example.com/page.html")));
+ ASSERT_TRUE(ServiceWorkerUtils::ScopeMatches(
+ GURL("http://www.example.com/"), GURL("http://www.example.com/#a")));
ASSERT_FALSE(ServiceWorkerUtils::ScopeMatches(GURL("http://www.example.com/"),
GURL("http://www.foo.com/")));
diff --git a/chromium/content/common/site_isolation_policy.cc b/chromium/content/common/site_isolation_policy.cc
index 60288700ca7..b25741b3b39 100644
--- a/chromium/content/common/site_isolation_policy.cc
+++ b/chromium/content/common/site_isolation_policy.cc
@@ -6,6 +6,7 @@
#include "base/command_line.h"
#include "base/lazy_instance.h"
+#include "content/public/common/browser_plugin_guest_mode.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
@@ -14,9 +15,10 @@ namespace content {
// static
bool SiteIsolationPolicy::AreCrossProcessFramesPossible() {
- return base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kSitePerProcess) ||
- GetContentClient()->IsSupplementarySiteIsolationModeEnabled();
+ return UseDedicatedProcessesForAllSites() ||
+ IsTopDocumentIsolationEnabled() ||
+ GetContentClient()->IsSupplementarySiteIsolationModeEnabled() ||
+ BrowserPluginGuestMode::UseCrossProcessFramesForGuests();
}
// static
@@ -26,6 +28,16 @@ bool SiteIsolationPolicy::UseDedicatedProcessesForAllSites() {
}
// static
+bool SiteIsolationPolicy::IsTopDocumentIsolationEnabled() {
+ // --site-per-process trumps --top-document-isolation.
+ if (UseDedicatedProcessesForAllSites())
+ return false;
+
+ return base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kTopDocumentIsolation);
+}
+
+// static
bool SiteIsolationPolicy::UseSubframeNavigationEntries() {
// Enable the new navigation history behavior if any manner of site isolation
// is active.
@@ -33,9 +45,4 @@ bool SiteIsolationPolicy::UseSubframeNavigationEntries() {
return AreCrossProcessFramesPossible() || IsBrowserSideNavigationEnabled();
}
-// static
-bool SiteIsolationPolicy::IsSwappedOutStateForbidden() {
- return true;
-}
-
} // namespace content
diff --git a/chromium/content/common/site_isolation_policy.h b/chromium/content/common/site_isolation_policy.h
index 69b6c5e4cf4..c6d6e6132aa 100644
--- a/chromium/content/common/site_isolation_policy.h
+++ b/chromium/content/common/site_isolation_policy.h
@@ -37,23 +37,16 @@ class CONTENT_EXPORT SiteIsolationPolicy {
// Returns true if every site should be placed in a dedicated process.
static bool UseDedicatedProcessesForAllSites();
+ // Returns true if third-party subframes of a page should be kept in a
+ // different process from the main frame.
+ static bool IsTopDocumentIsolationEnabled();
+
// Returns true if navigation and history code should maintain per-frame
// navigation entries. This is an in-progress feature related to site
// isolation, so the return value is currently tied to --site-per-process.
// TODO(creis, avi): Make this the default, and eliminate this.
static bool UseSubframeNavigationEntries();
- // Returns true if we are currently in a mode where the swapped out state
- // should not be used. Currently (as an implementation strategy) swapped out
- // is forbidden under --site-per-process, but our goal is to eliminate the
- // mode entirely. In code that deals with the swapped out state, prefer calls
- // to this function over consulting the switches directly. It will be easier
- // to grep, and easier to rip out.
- //
- // TODO(nasko): When swappedout:// is eliminated entirely, this function
- // should be removed and its callers cleaned up.
- static bool IsSwappedOutStateForbidden();
-
private:
SiteIsolationPolicy(); // Not instantiable.
diff --git a/chromium/content/common/storage_partition_service.mojom b/chromium/content/common/storage_partition_service.mojom
new file mode 100644
index 00000000000..3338658618d
--- /dev/null
+++ b/chromium/content/common/storage_partition_service.mojom
@@ -0,0 +1,15 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module content.mojom;
+
+import "content/common/leveldb_wrapper.mojom";
+import "url/mojo/origin.mojom";
+
+// Returns services related to the current storage partition.
+interface StoragePartitionService {
+ OpenLocalStorage(url.mojom.Origin origin,
+ LevelDBObserver observer,
+ LevelDBWrapper& database);
+};
diff --git a/chromium/content/common/swapped_out_messages.cc b/chromium/content/common/swapped_out_messages.cc
index 7980014711d..718dd08e49a 100644
--- a/chromium/content/common/swapped_out_messages.cc
+++ b/chromium/content/common/swapped_out_messages.cc
@@ -9,7 +9,6 @@
#include "content/common/input_messages.h"
#include "content/common/view_messages.h"
#include "content/public/common/content_client.h"
-#include "content/shell/common/shell_messages.h"
namespace content {
@@ -40,8 +39,6 @@ bool SwappedOutMessages::CanSendWhileSwappedOut(const IPC::Message* msg) {
// Frame detach must occur after the RenderView has swapped out.
case FrameHostMsg_Detach::ID:
case FrameHostMsg_DomOperationResponse::ID:
- case FrameHostMsg_CompositorFrameSwappedACK::ID:
- case FrameHostMsg_ReclaimCompositorResources::ID:
// Input events propagate from parent to child.
case FrameHostMsg_ForwardInputEvent::ID:
case FrameHostMsg_InitializeChildFrame::ID:
@@ -50,8 +47,8 @@ bool SwappedOutMessages::CanSendWhileSwappedOut(const IPC::Message* msg) {
case FrameHostMsg_DidAssignPageId::ID:
// A swapped-out frame's opener might be updated with window.open.
case FrameHostMsg_DidChangeOpener::ID:
- // Used in layout tests; handled in BlinkTestController.
- case ShellViewHostMsg_PrintMessage::ID:
+ // For handling pop-ups from cross-site frames.
+ case ViewHostMsg_CreateWidget::ID:
return true;
default:
break;
diff --git a/chromium/content/common/text_input_client_messages.h b/chromium/content/common/text_input_client_messages.h
index 70da1d8916e..f66196cc6c5 100644
--- a/chromium/content/common/text_input_client_messages.h
+++ b/chromium/content/common/text_input_client_messages.h
@@ -48,7 +48,7 @@ IPC_MESSAGE_ROUTED1(TextInputClientMsg_StringAtPoint, gfx::Point)
// Reply message for TextInputClientMsg_CharacterIndexForPoint.
IPC_MESSAGE_ROUTED1(TextInputClientReplyMsg_GotCharacterIndexForPoint,
- size_t /* character index */)
+ uint32_t /* character index */)
// Reply message for TextInputClientMsg_FirstRectForCharacterRange.
IPC_MESSAGE_ROUTED1(TextInputClientReplyMsg_GotFirstRectForRange,
diff --git a/chromium/content/common/url_schemes.cc b/chromium/content/common/url_schemes.cc
index 6d4c58c699f..c985e854ae1 100644
--- a/chromium/content/common/url_schemes.cc
+++ b/chromium/content/common/url_schemes.cc
@@ -18,35 +18,37 @@
namespace {
-void AddStandardSchemeHelper(const url::SchemeWithType& scheme) {
- url::AddStandardScheme(scheme.scheme, scheme.type);
-}
-
} // namespace
namespace content {
-void RegisterContentSchemes(bool lock_standard_schemes) {
+void RegisterContentSchemes(bool lock_schemes) {
std::vector<url::SchemeWithType> additional_standard_schemes;
+ std::vector<url::SchemeWithType> additional_referrer_schemes;
std::vector<std::string> additional_savable_schemes;
+
GetContentClient()->AddAdditionalSchemes(&additional_standard_schemes,
+ &additional_referrer_schemes,
&additional_savable_schemes);
url::AddStandardScheme(kChromeDevToolsScheme, url::SCHEME_WITHOUT_PORT);
url::AddStandardScheme(kChromeUIScheme, url::SCHEME_WITHOUT_PORT);
url::AddStandardScheme(kGuestScheme, url::SCHEME_WITHOUT_PORT);
url::AddStandardScheme(kMetadataScheme, url::SCHEME_WITHOUT_AUTHORITY);
- std::for_each(additional_standard_schemes.begin(),
- additional_standard_schemes.end(),
- AddStandardSchemeHelper);
-
- // Prevent future modification of the standard schemes list. This is to
- // prevent accidental creation of data races in the program. AddStandardScheme
- // isn't threadsafe so must be called when GURL isn't used on any other
- // thread. This is really easy to mess up, so we say that all calls to
- // AddStandardScheme in Chrome must be inside this function.
- if (lock_standard_schemes)
- url::LockStandardSchemes();
+
+ for (const url::SchemeWithType& scheme : additional_standard_schemes)
+ url::AddStandardScheme(scheme.scheme, scheme.type);
+
+ for (const url::SchemeWithType& scheme : additional_referrer_schemes)
+ url::AddReferrerScheme(scheme.scheme, scheme.type);
+
+ // Prevent future modification of the scheme lists. This is to prevent
+ // accidental creation of data races in the program. Add*Scheme aren't
+ // threadsafe so must be called when GURL isn't used on any other thread. This
+ // is really easy to mess up, so we say that all calls to Add*Scheme in Chrome
+ // must be inside this function.
+ if (lock_schemes)
+ url::LockSchemeRegistries();
// We rely on the above lock to protect this part from being invoked twice.
if (!additional_savable_schemes.empty()) {
diff --git a/chromium/content/common/url_schemes.h b/chromium/content/common/url_schemes.h
index 571c660f217..1441c9c9ab0 100644
--- a/chromium/content/common/url_schemes.h
+++ b/chromium/content/common/url_schemes.h
@@ -10,16 +10,16 @@
namespace content {
// Note: ContentMainRunner calls this method internally as part of main
-// initialziation, so this function generally should not be called by
+// initialization, so this function generally should not be called by
// embedders. It's exported to facilitate test harnesses that do not
// utilize ContentMainRunner and that do not wish to lock the set
// of standard schemes at init time.
//
-// Called near the beginning of startup to register URL schemes that should
-// be parsed as "standard" with the src/url/ library. Optionally, the set
-// of standard schemes is locked down. The embedder can add additional
-// schemes by overriding the ContentClient::AddAdditionalSchemes method.
-CONTENT_EXPORT void RegisterContentSchemes(bool lock_standard_schemes);
+// Called near the beginning of startup to register URL schemes that should be
+// parsed as "standard" or "referrer" with the src/url/ library. Optionally, the
+// sets of schemes are locked down. The embedder can add additional schemes by
+// overriding the ContentClient::AddAdditionalSchemes method.
+CONTENT_EXPORT void RegisterContentSchemes(bool lock_schemes);
} // namespace content
diff --git a/chromium/content/common/utility_messages.h b/chromium/content/common/utility_messages.h
index a76986ede7c..6a43e5a1f2d 100644
--- a/chromium/content/common/utility_messages.h
+++ b/chromium/content/common/utility_messages.h
@@ -4,15 +4,7 @@
// Multiply-included message file, so no include guard.
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#include "build/build_config.h"
#include "content/common/content_export.h"
-#include "content/public/common/common_param_traits.h"
-#include "content/public/common/webplugininfo.h"
#include "ipc/ipc_message_macros.h"
#undef IPC_MESSAGE_EXPORT
@@ -28,27 +20,3 @@ IPC_MESSAGE_CONTROL0(UtilityMsg_BatchMode_Started)
// Tells the utility process that it can shutdown.
IPC_MESSAGE_CONTROL0(UtilityMsg_BatchMode_Finished)
-
-#if defined(OS_POSIX) && defined(ENABLE_PLUGINS)
-// Tells the utility process to load each plugin in the order specified by the
-// vector. It will respond after each load with the WebPluginInfo.
-IPC_MESSAGE_CONTROL1(UtilityMsg_LoadPlugins,
- std::vector<base::FilePath> /* plugin paths */)
-#endif
-
-//------------------------------------------------------------------------------
-// Utility process host messages:
-// These are messages from the utility process to the browser.
-
-#if defined(OS_POSIX) && defined(ENABLE_PLUGINS)
-// Notifies the browser when a plugin failed to load so the two processes can
-// keep the canonical list in sync.
-IPC_SYNC_MESSAGE_CONTROL2_0(UtilityHostMsg_LoadPluginFailed,
- uint32_t /* index in the vector */,
- base::FilePath /* path of plugin */)
-
-// Notifies the browser that a plugin in the vector sent by it has been loaded.
-IPC_SYNC_MESSAGE_CONTROL2_0(UtilityHostMsg_LoadedPlugin,
- uint32_t /* index in the vector */,
- content::WebPluginInfo /* plugin info */)
-#endif
diff --git a/chromium/content/common/view_messages.h b/chromium/content/common/view_messages.h
index 5b5e578b7dd..324bdef3c51 100644
--- a/chromium/content/common/view_messages.h
+++ b/chromium/content/common/view_messages.h
@@ -22,8 +22,8 @@
#include "content/common/frame_replication_state.h"
#include "content/common/media/media_param_traits.h"
#include "content/common/navigation_gesture.h"
+#include "content/common/resize_params.h"
#include "content/common/view_message_enums.h"
-#include "content/common/webplugin_geometry.h"
#include "content/public/common/common_param_traits.h"
#include "content/public/common/favicon_url.h"
#include "content/public/common/file_chooser_file_info.h"
@@ -34,7 +34,6 @@
#include "content/public/common/page_zoom.h"
#include "content/public/common/referrer.h"
#include "content/public/common/renderer_preferences.h"
-#include "content/public/common/stop_find_action.h"
#include "content/public/common/three_d_api_types.h"
#include "content/public/common/window_container_type.h"
#include "ipc/ipc_channel_handle.h"
@@ -49,7 +48,6 @@
#include "third_party/WebKit/public/platform/WebScreenInfo.h"
#include "third_party/WebKit/public/platform/modules/screen_orientation/WebScreenOrientationType.h"
#include "third_party/WebKit/public/web/WebDeviceEmulationParams.h"
-#include "third_party/WebKit/public/web/WebFindOptions.h"
#include "third_party/WebKit/public/web/WebMediaPlayerAction.h"
#include "third_party/WebKit/public/web/WebPluginAction.h"
#include "third_party/WebKit/public/web/WebPopupType.h"
@@ -66,6 +64,7 @@
#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/geometry/vector2d_f.h"
#include "ui/gfx/ipc/gfx_param_traits.h"
+#include "ui/gfx/ipc/skia/gfx_skia_param_traits.h"
#include "ui/gfx/range/range.h"
#if defined(OS_MACOSX)
@@ -111,8 +110,6 @@ IPC_ENUM_TRAITS_MAX_VALUE(gfx::FontRenderParams::SubpixelRendering,
gfx::FontRenderParams::SUBPIXEL_RENDERING_MAX)
IPC_ENUM_TRAITS_MAX_VALUE(content::TapMultipleTargetsStrategy,
content::TAP_MULTIPLE_TARGETS_STRATEGY_MAX)
-IPC_ENUM_TRAITS_MAX_VALUE(content::StopFindAction,
- content::STOP_FIND_ACTION_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(content::ThreeDAPIType,
content::THREE_D_API_TYPE_LAST)
IPC_ENUM_TRAITS_MAX_VALUE(media::MediaLogEvent::Type,
@@ -128,12 +125,6 @@ IPC_ENUM_TRAITS_MAX_VALUE(
IPC_ENUM_TRAITS_MAX_VALUE(blink::ScrollerStyle, blink::ScrollerStyleOverlay)
#endif
-IPC_STRUCT_TRAITS_BEGIN(blink::WebFindOptions)
- IPC_STRUCT_TRAITS_MEMBER(forward)
- IPC_STRUCT_TRAITS_MEMBER(matchCase)
- IPC_STRUCT_TRAITS_MEMBER(findNext)
-IPC_STRUCT_TRAITS_END()
-
IPC_STRUCT_TRAITS_BEGIN(blink::WebMediaPlayerAction)
IPC_STRUCT_TRAITS_MEMBER(type)
IPC_STRUCT_TRAITS_MEMBER(enable)
@@ -170,6 +161,8 @@ IPC_STRUCT_TRAITS_BEGIN(blink::WebDeviceEmulationParams)
IPC_STRUCT_TRAITS_MEMBER(fitToView)
IPC_STRUCT_TRAITS_MEMBER(offset)
IPC_STRUCT_TRAITS_MEMBER(scale)
+ IPC_STRUCT_TRAITS_MEMBER(screenOrientationAngle)
+ IPC_STRUCT_TRAITS_MEMBER(screenOrientationType)
IPC_STRUCT_TRAITS_END()
IPC_STRUCT_TRAITS_BEGIN(blink::WebScreenInfo)
@@ -183,6 +176,19 @@ IPC_STRUCT_TRAITS_BEGIN(blink::WebScreenInfo)
IPC_STRUCT_TRAITS_MEMBER(orientationAngle)
IPC_STRUCT_TRAITS_END()
+IPC_STRUCT_TRAITS_BEGIN(content::ResizeParams)
+ IPC_STRUCT_TRAITS_MEMBER(screen_info)
+ IPC_STRUCT_TRAITS_MEMBER(new_size)
+ IPC_STRUCT_TRAITS_MEMBER(physical_backing_size)
+ IPC_STRUCT_TRAITS_MEMBER(top_controls_shrink_blink_size)
+ IPC_STRUCT_TRAITS_MEMBER(top_controls_height)
+ IPC_STRUCT_TRAITS_MEMBER(visible_viewport_size)
+ IPC_STRUCT_TRAITS_MEMBER(resizer_rect)
+ IPC_STRUCT_TRAITS_MEMBER(is_fullscreen_granted)
+ IPC_STRUCT_TRAITS_MEMBER(display_mode)
+ IPC_STRUCT_TRAITS_MEMBER(needs_resize_ack)
+IPC_STRUCT_TRAITS_END()
+
IPC_STRUCT_TRAITS_BEGIN(content::MenuItem)
IPC_STRUCT_TRAITS_MEMBER(label)
IPC_STRUCT_TRAITS_MEMBER(tool_tip)
@@ -279,15 +285,6 @@ IPC_STRUCT_TRAITS_BEGIN(content::RendererPreferences)
IPC_STRUCT_TRAITS_MEMBER(default_font_size)
IPC_STRUCT_TRAITS_END()
-IPC_STRUCT_TRAITS_BEGIN(content::WebPluginGeometry)
- IPC_STRUCT_TRAITS_MEMBER(window)
- IPC_STRUCT_TRAITS_MEMBER(window_rect)
- IPC_STRUCT_TRAITS_MEMBER(clip_rect)
- IPC_STRUCT_TRAITS_MEMBER(cutout_rects)
- IPC_STRUCT_TRAITS_MEMBER(rects_valid)
- IPC_STRUCT_TRAITS_MEMBER(visible)
-IPC_STRUCT_TRAITS_END()
-
IPC_STRUCT_TRAITS_BEGIN(media::MediaLogEvent)
IPC_STRUCT_TRAITS_MEMBER(id)
IPC_STRUCT_TRAITS_MEMBER(type)
@@ -382,6 +379,9 @@ IPC_STRUCT_BEGIN(ViewHostMsg_CreateWorker_Params)
// RenderFrame routing id used to send messages back to the parent.
IPC_STRUCT_MEMBER(int, render_frame_route_id)
+ // Address space of the context that created the worker.
+ IPC_STRUCT_MEMBER(blink::WebAddressSpace, creation_address_space)
+
// The type (secure or nonsecure) of the context that created the worker.
IPC_STRUCT_MEMBER(blink::WebSharedWorkerCreationContextType,
creation_context_type)
@@ -460,10 +460,6 @@ IPC_STRUCT_BEGIN(ViewHostMsg_UpdateRect_Params)
// view size.
IPC_STRUCT_MEMBER(gfx::Size, view_size)
- // New window locations for plugin child windows.
- IPC_STRUCT_MEMBER(std::vector<content::WebPluginGeometry>,
- plugin_window_moves)
-
// The following describes the various bits that may be set in flags:
//
// ViewHostMsg_UpdateRect_Flags::IS_RESIZE_ACK
@@ -479,34 +475,6 @@ IPC_STRUCT_BEGIN(ViewHostMsg_UpdateRect_Params)
IPC_STRUCT_MEMBER(int, flags)
IPC_STRUCT_END()
-IPC_STRUCT_BEGIN(ViewMsg_Resize_Params)
- // Information about the screen (dpi, depth, etc..).
- IPC_STRUCT_MEMBER(blink::WebScreenInfo, screen_info)
- // The size of the renderer.
- IPC_STRUCT_MEMBER(gfx::Size, new_size)
- // The size of the view's backing surface in non-DPI-adjusted pixels.
- IPC_STRUCT_MEMBER(gfx::Size, physical_backing_size)
- // Whether or not Blink's viewport size should be shrunk by the height of the
- // URL-bar (always false on platforms where URL-bar hiding isn't supported).
- IPC_STRUCT_MEMBER(bool, top_controls_shrink_blink_size)
- // The height of the top controls (always 0 on platforms where URL-bar hiding
- // isn't supported).
- IPC_STRUCT_MEMBER(float, top_controls_height)
- // The size of the visible viewport, which may be smaller than the view if the
- // view is partially occluded (e.g. by a virtual keyboard). The size is in
- // DPI-adjusted pixels.
- IPC_STRUCT_MEMBER(gfx::Size, visible_viewport_size)
- // The resizer rect.
- IPC_STRUCT_MEMBER(gfx::Rect, resizer_rect)
- // Indicates whether tab-initiated fullscreen was granted.
- IPC_STRUCT_MEMBER(bool, is_fullscreen_granted)
- // The display mode.
- IPC_STRUCT_MEMBER(blink::WebDisplayMode, display_mode)
- // If set, requests the renderer to reply with a ViewHostMsg_UpdateRect
- // with the ViewHostMsg_UpdateRect_Flags::IS_RESIZE_ACK bit set in flags.
- IPC_STRUCT_MEMBER(bool, needs_resize_ack)
-IPC_STRUCT_END()
-
IPC_STRUCT_BEGIN(ViewMsg_New_Params)
// Renderer-wide preferences.
IPC_STRUCT_MEMBER(content::RendererPreferences, renderer_preferences)
@@ -558,7 +526,7 @@ IPC_STRUCT_BEGIN(ViewMsg_New_Params)
IPC_STRUCT_MEMBER(int32_t, next_page_id)
// The initial renderer size.
- IPC_STRUCT_MEMBER(ViewMsg_Resize_Params, initial_size)
+ IPC_STRUCT_MEMBER(content::ResizeParams, initial_size)
// Whether to enable auto-resize.
IPC_STRUCT_MEMBER(bool, enable_auto_resize)
@@ -577,7 +545,6 @@ IPC_STRUCT_BEGIN(ViewMsg_UpdateScrollbarTheme_Params)
IPC_STRUCT_MEMBER(bool, jump_on_track_click)
IPC_STRUCT_MEMBER(blink::ScrollerStyle, preferred_scroller_style)
IPC_STRUCT_MEMBER(bool, redraw)
- IPC_STRUCT_MEMBER(bool, scroll_animation_enabled)
IPC_STRUCT_MEMBER(blink::WebScrollbarButtonsPlacement, button_placement)
IPC_STRUCT_END()
#endif
@@ -642,8 +609,7 @@ IPC_MESSAGE_ROUTED0(ViewMsg_Close)
// the view's current size. The generated ViewHostMsg_UpdateRect message will
// have the IS_RESIZE_ACK flag set. It also receives the resizer rect so that
// we don't have to fetch it every time WebKit asks for it.
-IPC_MESSAGE_ROUTED1(ViewMsg_Resize,
- ViewMsg_Resize_Params /* params */)
+IPC_MESSAGE_ROUTED1(ViewMsg_Resize, content::ResizeParams /* params */)
// Enables device emulation. See WebDeviceEmulationParams for description.
IPC_MESSAGE_ROUTED1(ViewMsg_EnableDeviceEmulation,
@@ -684,17 +650,6 @@ IPC_MESSAGE_ROUTED2(ViewMsg_ShowContextMenu,
ui::MenuSourceType,
gfx::Point /* location where menu should be shown */)
-// Sent when the user wants to search for a word on the page (find in page).
-IPC_MESSAGE_ROUTED3(ViewMsg_Find,
- int /* request_id */,
- base::string16 /* search_text */,
- blink::WebFindOptions)
-
-// This message notifies the renderer that the user has closed the FindInPage
-// window (and what action to take regarding the selection).
-IPC_MESSAGE_ROUTED1(ViewMsg_StopFinding,
- content::StopFindAction /* action */)
-
// Copies the image at location x, y to the clipboard (if there indeed is an
// image at that location).
IPC_MESSAGE_ROUTED2(ViewMsg_CopyImageAt,
@@ -779,11 +734,6 @@ IPC_MESSAGE_ROUTED2(ViewMsg_EnumerateDirectoryResponse,
int /* request_id */,
std::vector<base::FilePath> /* files_in_directory */)
-// Tells the renderer to suppress any further modal dialogs until it receives a
-// corresponding ViewMsg_SwapOut message. This ensures that no
-// PageGroupLoadDeferrer is on the stack for SwapOut.
-IPC_MESSAGE_ROUTED0(ViewMsg_SuppressDialogsUntilSwapOut)
-
// Instructs the renderer to close the current page, including running the
// onunload event handler.
//
@@ -867,6 +817,10 @@ IPC_MESSAGE_CONTROL2(ViewMsg_NetworkConnectionChanged,
net::NetworkChangeNotifier::ConnectionType /* type */,
double /* max bandwidth mbps */)
+// Sent by the browser to synchronize with the next compositor frame. Used only
+// for tests.
+IPC_MESSAGE_ROUTED1(ViewMsg_WaitForNextFrameForTests, int /* routing_id */)
+
#if defined(ENABLE_PLUGINS)
// Reply to ViewHostMsg_OpenChannelToPpapiBroker
// Tells the renderer that the channel to the broker has been created.
@@ -886,9 +840,6 @@ IPC_MESSAGE_CONTROL1(ViewMsg_PurgePluginListCache,
bool /* reload_pages */)
#endif
-// Used to instruct the RenderView to go into "view source" mode.
-IPC_MESSAGE_ROUTED0(ViewMsg_EnableViewSourceMode)
-
// An acknowledge to ViewHostMsg_MultipleTargetsTouched to notify the renderer
// process to release the magnified image.
IPC_MESSAGE_ROUTED1(ViewMsg_ReleaseDisambiguationPopupBitmap,
@@ -914,19 +865,6 @@ IPC_MESSAGE_CONTROL3(ViewMsg_SystemColorsChanged,
IPC_MESSAGE_CONTROL1(ViewMsg_SetWebKitSharedTimersSuspended,
bool /* suspend */)
-// Sent when the browser wants the bounding boxes of the current find matches.
-//
-// If match rects are already cached on the browser side, |current_version|
-// should be the version number from the ViewHostMsg_FindMatchRects_Reply
-// they came in, so the renderer can tell if it needs to send updated rects.
-// Otherwise just pass -1 to always receive the list of rects.
-//
-// There must be an active search string (it is probably most useful to call
-// this immediately after a ViewHostMsg_Find_Reply message arrives with
-// final_update set to true).
-IPC_MESSAGE_ROUTED1(ViewMsg_FindMatchRects,
- int /* current_version */)
-
// Notifies the renderer whether hiding/showing the top controls is enabled
// and whether or not to animate to the proper state.
IPC_MESSAGE_ROUTED3(ViewMsg_UpdateTopControlsState,
@@ -940,26 +878,6 @@ IPC_MESSAGE_ROUTED0(ViewMsg_ShowImeIfNeeded)
// ViewHostMsg_SmartClipDataExtracted IPC.
IPC_MESSAGE_ROUTED1(ViewMsg_ExtractSmartClipData,
gfx::Rect /* rect */)
-
-#elif defined(OS_MACOSX)
-// Let the RenderView know its window has changed visibility.
-IPC_MESSAGE_ROUTED1(ViewMsg_SetWindowVisibility,
- bool /* visibile */)
-
-// Let the RenderView know its window's frame has changed.
-IPC_MESSAGE_ROUTED2(ViewMsg_WindowFrameChanged,
- gfx::Rect /* window frame */,
- gfx::Rect /* content view frame */)
-
-// Message sent from the browser to the renderer when the user starts or stops
-// resizing the view.
-IPC_MESSAGE_ROUTED1(ViewMsg_SetInLiveResize,
- bool /* enable */)
-
-// Tell the renderer that plugin IME has completed.
-IPC_MESSAGE_ROUTED2(ViewMsg_PluginImeCompositionCompleted,
- base::string16 /* text */,
- int /* plugin_id */)
#endif
// Sent by the browser as a reply to ViewHostMsg_SwapCompositorFrame.
@@ -1071,19 +989,6 @@ IPC_MESSAGE_ROUTED0(ViewHostMsg_UpdateScreenRects_ACK)
IPC_MESSAGE_ROUTED1(ViewHostMsg_RequestMove,
gfx::Rect /* position */)
-// Result of string search in the page.
-// Response to ViewMsg_Find with the results of the requested find-in-page
-// search, the number of matches found and the selection rect (in screen
-// coordinates) for the string found. If |final_update| is false, it signals
-// that this is not the last Find_Reply message - more will be sent as the
-// scoping effort continues.
-IPC_MESSAGE_ROUTED5(ViewHostMsg_Find_Reply,
- int /* request_id */,
- int /* number of matches */,
- gfx::Rect /* selection_rect */,
- int /* active_match_ordinal */,
- bool /* final_update */)
-
// Indicates that the render view has been closed in respose to a
// Close message.
IPC_MESSAGE_CONTROL1(ViewHostMsg_Close_ACK,
@@ -1127,14 +1032,6 @@ IPC_MESSAGE_ROUTED2(ViewHostMsg_FocusedNodeChanged,
IPC_MESSAGE_ROUTED1(ViewHostMsg_SetCursor, content::WebCursor)
-#if defined(OS_WIN)
-IPC_MESSAGE_ROUTED1(ViewHostMsg_WindowlessPluginDummyWindowCreated,
- gfx::NativeViewId /* dummy_activation_window */)
-
-IPC_MESSAGE_ROUTED1(ViewHostMsg_WindowlessPluginDummyWindowDestroyed,
- gfx::NativeViewId /* dummy_activation_window */)
-#endif
-
// Get the list of proxies to use for |url|, as a semicolon delimited list
// of "<TYPE> <HOST>:<PORT>" | "DIRECT".
IPC_SYNC_MESSAGE_CONTROL1_2(ViewHostMsg_ResolveProxy,
@@ -1221,7 +1118,7 @@ IPC_MESSAGE_ROUTED2(ViewHostMsg_SetTooltipText,
// text in the document.
IPC_MESSAGE_ROUTED3(ViewHostMsg_SelectionChanged,
base::string16 /* text covers the selection range */,
- size_t /* the offset of the text in the document */,
+ uint32_t /* the offset of the text in the document */,
gfx::Range /* selection range in the document */)
// Notification that the selection bounds have changed.
@@ -1363,27 +1260,10 @@ IPC_MESSAGE_ROUTED0(ViewHostMsg_DidFirstPaintAfterLoad)
IPC_MESSAGE_ROUTED1(ViewHostMsg_ForwardCompositorProto,
std::vector<uint8_t> /* proto */)
-#if defined(OS_ANDROID)
-// Response to ViewMsg_FindMatchRects.
-//
-// |version| will contain the current version number of the renderer's find
-// match list (incremented whenever they change), which should be passed in the
-// next call to ViewMsg_FindMatchRects.
-//
-// |rects| will either contain a list of the enclosing rects of all matches
-// found by the most recent Find operation, or will be empty if |version| is not
-// greater than the |current_version| passed to ViewMsg_FindMatchRects (hence
-// your locally cached rects should still be valid). The rect coords will be
-// custom normalized fractions of the document size. The rects will be sorted by
-// frame traversal order starting in the main frame, then by dom order.
-//
-// |active_rect| will contain the bounding box of the active find-in-page match
-// marker, in similarly normalized coords (or an empty rect if there isn't one).
-IPC_MESSAGE_ROUTED3(ViewHostMsg_FindMatchRects_Reply,
- int /* version */,
- std::vector<gfx::RectF> /* rects */,
- gfx::RectF /* active_rect */)
+// Sent in reply to ViewMsg_WaitForNextFrameForTests.
+IPC_MESSAGE_ROUTED0(ViewHostMsg_WaitForNextFrameForTests_ACK)
+#if defined(OS_ANDROID)
// Start an android intent with the given URI.
IPC_MESSAGE_ROUTED2(ViewHostMsg_StartContentIntent,
GURL /* content_url */,
@@ -1402,14 +1282,6 @@ IPC_MESSAGE_ROUTED2(ViewHostMsg_ShowUnhandledTapUIIfNeeded,
int /* y */)
#elif defined(OS_MACOSX)
-// Informs the browser that a plugin has gained or lost focus.
-IPC_MESSAGE_ROUTED2(ViewHostMsg_PluginFocusChanged,
- bool, /* focused */
- int /* plugin_id */)
-
-// Instructs the browser to start plugin IME.
-IPC_MESSAGE_ROUTED0(ViewHostMsg_StartPluginIme)
-
// Receives content of a web page as plain text.
IPC_MESSAGE_ROUTED1(ViewMsg_GetRenderedTextCompleted, std::string)
#endif
diff --git a/chromium/content/common/vr_service.mojom b/chromium/content/common/vr_service.mojom
index 2d81ec70a11..5e90880a519 100644
--- a/chromium/content/common/vr_service.mojom
+++ b/chromium/content/common/vr_service.mojom
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-module content;
+module content.mojom;
struct VRVector3 {
float x;
diff --git a/chromium/content/common/wake_lock_service.mojom b/chromium/content/common/wake_lock_service.mojom
index 3d6e6d896c9..452d9342cda 100644
--- a/chromium/content/common/wake_lock_service.mojom
+++ b/chromium/content/common/wake_lock_service.mojom
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-module content;
+module content.mojom;
// WebLockService receives per-frame wake lock preference from its client.
interface WakeLockService {
diff --git a/chromium/content/common/webplugin_geometry.cc b/chromium/content/common/webplugin_geometry.cc
deleted file mode 100644
index ff290d20001..00000000000
--- a/chromium/content/common/webplugin_geometry.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/common/webplugin_geometry.h"
-
-namespace content {
-
-WebPluginGeometry::WebPluginGeometry()
- : window(gfx::kNullPluginWindow),
- rects_valid(false),
- visible(false) {
-}
-
-WebPluginGeometry::~WebPluginGeometry() {
-}
-
-bool WebPluginGeometry::Equals(const WebPluginGeometry& rhs) const {
- return window == rhs.window &&
- window_rect == rhs.window_rect &&
- clip_rect == rhs.clip_rect &&
- cutout_rects == rhs.cutout_rects &&
- rects_valid == rhs.rects_valid &&
- visible == rhs.visible;
-}
-
-} // namespace content
diff --git a/chromium/content/common/webplugin_geometry.h b/chromium/content/common/webplugin_geometry.h
deleted file mode 100644
index 7f727a1317e..00000000000
--- a/chromium/content/common/webplugin_geometry.h
+++ /dev/null
@@ -1,46 +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_COMMON_WEBPLUGIN_GEOMETRY_H_
-#define CONTENT_COMMON_WEBPLUGIN_GEOMETRY_H_
-
-#include <vector>
-
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/native_widget_types.h"
-
-namespace content {
-
-// Describes the new location for a plugin window.
-struct WebPluginGeometry {
- WebPluginGeometry();
- ~WebPluginGeometry();
-
- bool Equals(const WebPluginGeometry& rhs) const;
-
- // On Windows, this is the plugin window in the plugin process.
- // On X11, this is the XID of the plugin-side GtkPlug containing the
- // GtkSocket hosting the actual plugin window.
- //
- // On Mac OS X, all of the plugin types are currently "windowless"
- // (window == 0) except for the special case of the GPU plugin,
- // which currently performs rendering on behalf of the Pepper 3D API
- // and WebGL. The GPU plugin uses a simple integer for the
- // PluginWindowHandle which is used to map to a side data structure
- // containing information about the plugin. Soon this plugin will be
- // generalized, at which point this mechanism will be rethought or
- // removed.
- gfx::PluginWindowHandle window;
- gfx::Rect window_rect;
- // Clip rect (include) and cutouts (excludes), relative to
- // window_rect origin.
- gfx::Rect clip_rect;
- std::vector<gfx::Rect> cutout_rects;
- bool rects_valid;
- bool visible;
-};
-
-} // namespace content
-
-#endif // CONTENT_COMMON_WEBPLUGIN_GEOMETRY_H_
diff --git a/chromium/content/common/websocket_messages.h b/chromium/content/common/websocket_messages.h
index e0af254960e..383eb5a1f4a 100644
--- a/chromium/content/common/websocket_messages.h
+++ b/chromium/content/common/websocket_messages.h
@@ -73,6 +73,23 @@ IPC_MESSAGE_ROUTED4(WebSocketHostMsg_AddChannelRequest,
url::Origin /* origin */,
int /* render_frame_id */)
+// Send a complete binary WebSocket message consisting of the Blob identified by
+// |uuid|. The message will be split into frames as necessary. |expected_size|
+// must match the browser's idea of the size of the Blob to prevent flow control
+// from becoming desynchronised. If it does not match the connection will be
+// terminated with a WebSocketMsg_NotifyFailure message. On success, the browser
+// will have consumed |expected_size| bytes of flow control send quota and the
+// renderer needs to subtract that from its running total of flow control send
+// quota. See the design doc at
+// https://docs.google.com/document/d/1CDiXB9pBumhFVVfmIn1CRI6v6byxyqWu2urEE9xp714/edit
+// SendFrame or SendBlob IPCs must not be sent by the renderer until the
+// BlobSendComplete message has been received from the browser. The renderer
+// should retain a reference to the Blob until either a BlobSendComplete or
+// NotifyFailure IPC is received.
+IPC_MESSAGE_ROUTED2(WebSocketHostMsg_SendBlob,
+ std::string /* uuid */,
+ uint64_t /* expected_size */)
+
// WebSocket messages sent from the browser to the renderer.
// Respond to an AddChannelRequest. |selected_protocol| is the sub-protocol the
@@ -111,6 +128,11 @@ IPC_MESSAGE_ROUTED1(WebSocketMsg_NotifyFinishOpeningHandshake,
IPC_MESSAGE_ROUTED1(WebSocketMsg_NotifyFailure,
std::string /* message */)
+// Indicates tbat the current Blob has finished sending. The renderer can
+// release its reference on the Blob, and may now use SendFrame or SendBlob to
+// send more messages.
+IPC_MESSAGE_ROUTED0(WebSocketMsg_BlobSendComplete)
+
// WebSocket messages that can be sent in either direction.
// Send a non-control frame to the channel.
@@ -136,6 +158,14 @@ IPC_MESSAGE_ROUTED3(WebSocketMsg_SendFrame,
// Both sides start a new channel with a quota of 0, and must wait for a
// FlowControl message before calling SendFrame. The total available quota on
// one side must never exceed 0x7FFFFFFFFFFFFFFF tokens.
+//
+// During "blob sending mode", ie. between the renderer sending a
+// WebSocketHostMsg_SendBlob IPC and receiving a WebSocketMsg_BlobSendComplete
+// IPC, quota is used up in the browser process to send the blob, but
+// FlowControl IPCs for that quota are still sent to the renderer. The render
+// process needs to take into account that quota equal to the size of the Blob
+// has already been used when calculating how much send quota it has left after
+// receiving BlobSendComplete.
IPC_MESSAGE_ROUTED1(WebSocketMsg_FlowControl, int64_t /* quota */)
// Drop the channel.
diff --git a/chromium/content/common/worker_messages.h b/chromium/content/common/worker_messages.h
index 60f1a4a9d10..e49ce80e525 100644
--- a/chromium/content/common/worker_messages.h
+++ b/chromium/content/common/worker_messages.h
@@ -41,6 +41,7 @@ IPC_STRUCT_BEGIN(WorkerProcessMsg_CreateWorker_Params)
IPC_STRUCT_MEMBER(base::string16, name)
IPC_STRUCT_MEMBER(base::string16, content_security_policy)
IPC_STRUCT_MEMBER(blink::WebContentSecurityPolicyType, security_policy_type)
+ IPC_STRUCT_MEMBER(blink::WebAddressSpace, creation_address_space)
IPC_STRUCT_MEMBER(bool, pause_on_start)
IPC_STRUCT_MEMBER(int, route_id)
IPC_STRUCT_END()
@@ -55,16 +56,6 @@ IPC_MESSAGE_CONTROL1(WorkerProcessMsg_CreateWorker,
// WorkerProcessHost messages
// These are messages sent from the worker process to the browser process.
-// Sent by the worker process to check whether access to web databases is
-// allowed.
-IPC_SYNC_MESSAGE_CONTROL5_1(WorkerProcessHostMsg_AllowDatabase,
- int /* worker_route_id */,
- GURL /* origin url */,
- base::string16 /* database name */,
- base::string16 /* database display name */,
- unsigned long /* estimated size */,
- bool /* result */)
-
// Sent by the worker process to check whether access to file system is allowed.
IPC_SYNC_MESSAGE_CONTROL2_1(WorkerProcessHostMsg_RequestFileSystemAccessSync,
int /* worker_route_id */,
diff --git a/chromium/content/content.gni b/chromium/content/content.gni
deleted file mode 100644
index e0834a3c56e..00000000000
--- a/chromium/content/content.gni
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-if (is_win) {
- directxsdk_exists =
- exec_script("//build/dir_exists.py",
- [ rebase_path("//third_party/directxsdk", root_build_dir) ],
- "trim string") == "True"
-} else {
- directxsdk_exists = false
-}
diff --git a/chromium/content/content.gyp b/chromium/content/content.gyp
index ecf8e4d3e11..2221d0312cf 100644
--- a/chromium/content/content.gyp
+++ b/chromium/content/content.gyp
@@ -6,7 +6,6 @@
'variables': {
'chromium_code': 1, # Use higher warning level.
'chromium_enable_vtune_jit_for_v8%': 0, # enable the vtune support for V8 engine.
- 'directxsdk_exists': '<!pymod_do_main(dir_exists ../third_party/directxsdk)',
},
'target_defaults': {
'defines': ['CONTENT_IMPLEMENTATION'],
@@ -21,13 +20,77 @@
}],
],
},
- 'conditions': [
- ['OS != "ios"', {
+ 'targets': [
+ {
+ # GN version: //content/public/common:features
+ 'target_name': 'common_features',
'includes': [
- '../build/win_precompile.gypi',
- 'content_resources.gypi',
+ '../build/buildflag_header.gypi',
+ '../third_party/webrtc/build/common.gypi',
],
- }],
+ 'conditions': [
+ # This conditional looks insane, but without it |rtc_use_h264| is not
+ # recognized as defined. Might have something to do with scopes. Moving
+ # the inclusion of third_party/webrtc/build/common.gypi to outside of
+ # 'targets' is not an option, then we get compile errors.
+ # TODO(hbos): crbug.com/584219
+ ['1==1', {
+ 'variables': {
+ 'buildflag_header_path': 'content/public/common/features.h',
+ 'buildflag_flags': [
+ 'RTC_USE_H264=<(rtc_use_h264)',
+ ],
+ },
+ }],
+ ],
+ },
+ {
+ # GN version: //content/public/common:feature_h264_with_openh264_ffmpeg
+ 'target_name': 'feature_h264_with_openh264_ffmpeg',
+ 'type': 'static_library',
+ 'include_dirs': [ '<@(DEPTH)' ],
+ 'dependencies': [
+ 'common_features',
+ ],
+ 'sources': [
+ 'public/common/feature_h264_with_openh264_ffmpeg.cc',
+ 'public/common/feature_h264_with_openh264_ffmpeg.h',
+ ],
+ },
+ {
+ # GN version: //content/public/app:browser_manifest
+ 'target_name': 'content_app_browser_manifest',
+ 'type': 'none',
+ 'variables': {
+ 'application_type': 'exe',
+ 'application_name': 'content_browser',
+ 'source_manifest': '<(DEPTH)/content/public/app/mojo/content_browser_manifest.json',
+ },
+ 'includes': [
+ '../mojo/public/mojo_application_manifest.gypi',
+ ],
+ 'hard_dependency': 1,
+ },
+ {
+ # GN version: //content/public/app:renderer_manifest
+ 'target_name': 'content_app_renderer_manifest',
+ 'type': 'none',
+ 'variables': {
+ 'application_type': 'exe',
+ 'application_name': 'content_renderer',
+ 'source_manifest': '<(DEPTH)/content/public/app/mojo/content_renderer_manifest.json',
+ },
+ 'includes': [
+ '../mojo/public/mojo_application_manifest.gypi',
+ ],
+ 'hard_dependency': 1,
+ },
+ ],
+ 'includes': [
+ '../build/win_precompile.gypi',
+ 'content_resources.gypi',
+ ],
+ 'conditions': [
['OS == "win"', {
'targets': [
{
@@ -64,23 +127,16 @@
'type': 'none',
'dependencies': [
'content_browser',
+ 'content_child',
'content_common',
+ 'content_gpu',
+ 'content_ppapi_plugin',
+ 'content_renderer',
+ 'content_utility',
],
'export_dependent_settings': [
'content_common',
],
- 'conditions': [
- ['OS != "ios"', {
- 'dependencies': [
- 'content_child',
- 'content_gpu',
- 'content_plugin',
- 'content_ppapi_plugin',
- 'content_renderer',
- 'content_utility',
- ],
- }],
- ],
},
{
# GN version: //content/app:browser
@@ -154,6 +210,8 @@
],
'dependencies': [
'content_common',
+ 'content_gpu',
+ 'content_resources',
],
'export_dependent_settings': [
'content_common',
@@ -166,15 +224,9 @@
}],
['OS=="android"', {
'dependencies': [
- 'content_gpu',
'content_utility',
],
}],
- ['OS != "ios"', {
- 'dependencies': [
- 'content_resources',
- ],
- }],
],
},
{
@@ -182,114 +234,94 @@
'target_name': 'content_common',
'type': 'static_library',
'variables': { 'enable_wexit_time_destructors': 1, },
+ 'dependencies': [
+ 'content_resources',
+ ],
'includes': [
'content_common.gypi',
],
- 'conditions': [
- ['OS != "ios"', {
- 'dependencies': [
- 'content_resources',
- ],
- }],
- ],
# Disable c4267 warnings until we fix size_t to int truncations.
'msvs_disabled_warnings': [ 4267, ],
},
- ],
- 'conditions': [
- ['OS != "ios"', {
- 'targets': [
- {
+ {
# GN version: //content/child and //content/public/child
- 'target_name': 'content_child',
- 'type': 'static_library',
- 'variables': { 'enable_wexit_time_destructors': 1, },
- 'includes': [
- 'content_child.gypi',
- ],
- 'dependencies': [
- 'content_resources',
- ],
- # Disable c4267 warnings until we fix size_t to int truncations.
- 'msvs_disabled_warnings': [ 4267, ],
- },
- {
- # GN version: //content/gpu
- 'target_name': 'content_gpu',
- 'type': 'static_library',
- 'variables': { 'enable_wexit_time_destructors': 1, },
- 'includes': [
- 'content_gpu.gypi',
- ],
- 'dependencies': [
- 'content_child',
- 'content_common',
- ],
- },
- {
- # GN version: //content/plugin and //content/public/plugin
- 'target_name': 'content_plugin',
- 'type': 'static_library',
- 'variables': { 'enable_wexit_time_destructors': 1, },
- 'includes': [
- 'content_plugin.gypi',
- ],
- 'dependencies': [
- 'content_child',
- 'content_common',
- ],
- },
- {
- # GN version: //content/ppapi_plugin
- 'target_name': 'content_ppapi_plugin',
- 'type': 'static_library',
- 'variables': { 'enable_wexit_time_destructors': 1, },
- 'includes': [
- 'content_ppapi_plugin.gypi',
- ],
- # Disable c4267 warnings until we fix size_t to int truncations.
- 'msvs_disabled_warnings': [ 4267, ],
- },
- {
- # GN version: //content/renderer and //content/public/renderer
- 'target_name': 'content_renderer',
- 'type': 'static_library',
- 'variables': { 'enable_wexit_time_destructors': 1, },
- 'includes': [
- 'content_renderer.gypi',
- ],
- 'dependencies': [
- 'content_child',
- 'content_common',
- 'content_resources',
- ],
- 'export_dependent_settings': [
- 'content_common',
- ],
- 'conditions': [
- ['chromium_enable_vtune_jit_for_v8==1', {
- 'dependencies': [
- '../v8/src/third_party/vtune/v8vtune.gyp:v8_vtune',
- ],
- }],
- ],
- },
- {
- # GN version: //content/utility and //content/public/utility
- 'target_name': 'content_utility',
- 'type': 'static_library',
- 'variables': { 'enable_wexit_time_destructors': 1, },
- 'includes': [
- 'content_utility.gypi',
- ],
+ 'target_name': 'content_child',
+ 'type': 'static_library',
+ 'variables': { 'enable_wexit_time_destructors': 1, },
+ 'includes': [
+ 'content_child.gypi',
+ ],
+ 'dependencies': [
+ 'content_resources',
+ ],
+ # Disable c4267 warnings until we fix size_t to int truncations.
+ 'msvs_disabled_warnings': [ 4267, ],
+ },
+ {
+ # GN version: //content/gpu
+ 'target_name': 'content_gpu',
+ 'type': 'static_library',
+ 'variables': { 'enable_wexit_time_destructors': 1, },
+ 'includes': [
+ 'content_gpu.gypi',
+ ],
+ 'dependencies': [
+ 'content_child',
+ 'content_common',
+ ],
+ },
+ {
+ # GN version: //content/ppapi_plugin
+ 'target_name': 'content_ppapi_plugin',
+ 'type': 'static_library',
+ 'variables': { 'enable_wexit_time_destructors': 1, },
+ 'includes': [
+ 'content_ppapi_plugin.gypi',
+ ],
+ # Disable c4267 warnings until we fix size_t to int truncations.
+ 'msvs_disabled_warnings': [ 4267, ],
+ },
+ {
+ # GN version: //content/renderer and //content/public/renderer
+ 'target_name': 'content_renderer',
+ 'type': 'static_library',
+ 'variables': { 'enable_wexit_time_destructors': 1, },
+ 'includes': [
+ 'content_renderer.gypi',
+ ],
+ 'dependencies': [
+ '../third_party/webrtc/modules/modules.gyp:webrtc_h264',
+ 'common_features',
+ 'content_child',
+ 'content_common',
+ 'content_gpu',
+ 'content_resources',
+ ],
+ 'export_dependent_settings': [
+ 'content_common',
+ ],
+ 'conditions': [
+ ['chromium_enable_vtune_jit_for_v8==1', {
'dependencies': [
- 'content_child',
- 'content_common',
- 'content_common_mojo_bindings.gyp:content_common_mojo_bindings',
+ '../v8/src/third_party/vtune/v8vtune.gyp:v8_vtune',
],
- },
+ }],
],
- }],
+ },
+ {
+ # GN version: //content/utility and //content/public/utility
+ 'target_name': 'content_utility',
+ 'type': 'static_library',
+ 'variables': { 'enable_wexit_time_destructors': 1, },
+ 'includes': [
+ 'content_utility.gypi',
+ ],
+ 'dependencies': [
+ 'content_child',
+ 'content_common',
+ 'content_common_mojo_bindings.gyp:content_common_mojo_bindings',
+ ],
+ },
],
},
{ # component != static_library
@@ -300,6 +332,8 @@
'type': 'shared_library',
'variables': { 'enable_wexit_time_destructors': 1, },
'dependencies': [
+ '../third_party/webrtc/modules/modules.gyp:webrtc_h264',
+ 'common_features',
'content_resources',
],
'conditions': [
@@ -315,7 +349,6 @@
'content_child.gypi',
'content_common.gypi',
'content_gpu.gypi',
- 'content_plugin.gypi',
'content_ppapi_plugin.gypi',
'content_renderer.gypi',
'content_utility.gypi',
@@ -360,7 +393,10 @@
# GN version: //content/common and //content/public/common
'target_name': 'content_common',
'type': 'none',
- 'dependencies': ['content', 'content_resources'],
+ 'dependencies': [
+ 'content',
+ 'content_resources'
+ ],
# Disable c4267 warnings until we fix size_t to int truncations.
'msvs_disabled_warnings': [ 4267, ],
'export_dependent_settings': ['content'],
@@ -378,12 +414,6 @@
'dependencies': ['content'],
},
{
- # GN version: //content/plugin
- 'target_name': 'content_plugin',
- 'type': 'none',
- 'dependencies': ['content'],
- },
- {
# GN version: //content/ppapi_plugin
'target_name': 'content_ppapi_plugin',
'type': 'none',
@@ -434,9 +464,9 @@
'../media/media.gyp:media_java',
'../mojo/mojo_base.gyp:mojo_application_bindings',
'../mojo/mojo_base.gyp:mojo_system_java',
+ '../mojo/mojo_public.gyp:mojo_bindings_java',
'../net/net.gyp:net',
'../skia/skia.gyp:skia_mojo',
- '../third_party/mojo/mojo_public.gyp:mojo_bindings_java',
'../ui/android/ui_android.gyp:ui_java',
'../ui/touch_selection/ui_touch_selection.gyp:selection_event_type_java',
'../ui/touch_selection/ui_touch_selection.gyp:touch_handle_orientation_java',
diff --git a/chromium/content/content_app.gypi b/chromium/content/content_app.gypi
index 4de603bb7c9..2ed4ed7fd97 100644
--- a/chromium/content/content_app.gypi
+++ b/chromium/content/content_app.gypi
@@ -10,13 +10,15 @@
'../base/base.gyp:base',
'../base/base.gyp:base_i18n',
'../crypto/crypto.gyp:crypto',
- '../mojo/mojo_base.gyp:mojo_environment_chromium',
- '../third_party/mojo/mojo_edk.gyp:mojo_system_impl',
+ '../mojo/mojo_edk.gyp:mojo_system_impl',
'../ui/base/ui_base.gyp:ui_base',
'../ui/gfx/gfx.gyp:gfx',
'../ui/gfx/gfx.gyp:gfx_geometry',
'content_common_mojo_bindings.gyp:content_common_mojo_bindings',
],
+ 'export_dependent_settings': [
+ 'content_common_mojo_bindings.gyp:content_common_mojo_bindings',
+ ],
'sources': [
'app/android/app_jni_registrar.cc',
'app/android/app_jni_registrar.h',
@@ -25,6 +27,7 @@
'app/android/content_jni_onload.cc',
'app/android/content_main.cc',
'app/android/content_main.h',
+ 'app/android/download_main.cc',
'app/android/library_loader_hooks.cc',
'app/android/library_loader_hooks.h',
'app/content_main.cc',
@@ -40,12 +43,6 @@
'public/app/content_main_runner.h',
],
'conditions': [
- ['((OS=="linux" and os_posix==1 and use_aura==1) or OS=="android") and use_allocator!="none"', {
- 'dependencies': [
- # This is needed by app/content_main_runner.cc
- '../base/allocator/allocator.gyp:allocator',
- ],
- }],
['OS=="android"', {
'sources!': [
'app/content_main.cc',
@@ -53,6 +50,8 @@
'dependencies': [
'content.gyp:content_jni_headers',
'../build/android/ndk.gyp:cpu_features',
+ '../device/usb/usb.gyp:device_usb',
+ '../gpu/gpu.gyp:gpu_ipc_common',
'../skia/skia.gyp:skia',
'../ui/android/ui_android.gyp:ui_android',
],
diff --git a/chromium/content/content_browser.gypi b/chromium/content/content_browser.gypi
index 4369cda28c2..57bc508d2e3 100644
--- a/chromium/content/content_browser.gypi
+++ b/chromium/content/content_browser.gypi
@@ -5,27 +5,48 @@
{
'dependencies': [
'../base/base.gyp:base_static',
+ '../cc/cc.gyp:cc',
+ '../cc/cc.gyp:cc_surfaces',
+ '../components/leveldb/leveldb.gyp:leveldb_lib',
+ '../components/mime_util/mime_util.gyp:mime_util',
+ '../components/profile_service/profile_service.gyp:profile_service_lib',
+ '../components/scheduler/scheduler.gyp:scheduler_common',
'../components/url_formatter/url_formatter.gyp:url_formatter',
'../crypto/crypto.gyp:crypto',
'../device/battery/battery.gyp:device_battery',
'../device/battery/battery.gyp:device_battery_mojo_bindings',
+ '../device/bluetooth/bluetooth.gyp:device_bluetooth',
+ '../device/usb/usb.gyp:device_usb',
'../device/vibration/vibration.gyp:device_vibration',
'../device/vibration/vibration.gyp:device_vibration_mojo_bindings',
+ '../gin/gin.gyp:gin',
'../google_apis/google_apis.gyp:google_apis',
+ '../gpu/gpu.gyp:gpu',
+ '../gpu/gpu.gyp:gpu_ipc_client',
+ '../gpu/gpu.gyp:gpu_ipc_common',
'../mojo/mojo_base.gyp:mojo_application_base',
'../mojo/mojo_base.gyp:mojo_geometry_lib',
'../mojo/mojo_base.gyp:mojo_url_type_converters',
- '../mojo/mojo_services.gyp:network_service_bindings_lib',
- '../mojo/mojo_services.gyp:updater_bindings_lib',
+ '../mojo/mojo_base.gyp:tracing_service',
+ '../mojo/mojo_base.gyp:tracing_service_lib',
+ '../mojo/mojo_public.gyp:mojo_cpp_bindings',
+ '../mojo/mojo_public.gyp:mojo_js_bindings',
+ '../mojo/mojo_shell.gyp:mojo_runner_common_lib',
+ '../mojo/mojo_shell.gyp:mojo_runner_host_lib',
'../mojo/mojo_shell.gyp:mojo_shell_lib',
- '../mojo/mojo_shell.gyp:mojo_fetcher_lib',
+ '../net/net.gyp:http_server',
'../net/net.gyp:net',
'../net/net.gyp:net_extras',
+ '../sandbox/sandbox.gyp:sandbox',
'../skia/skia.gyp:skia',
'../skia/skia.gyp:skia_mojo',
'../sql/sql.gyp:sql',
+ '../storage/storage_browser.gyp:storage',
+ '../storage/storage_common.gyp:storage_common',
+ '../third_party/angle/src/angle.gyp:commit_id',
'../third_party/kasko/kasko.gyp:kasko_features',
- '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
+ '../third_party/leveldatabase/leveldatabase.gyp:leveldatabase',
+ '../third_party/libyuv/libyuv.gyp:libyuv',
'../third_party/re2/re2.gyp:re2',
'../third_party/zlib/google/zip.gyp:zip',
'../third_party/zlib/zlib.gyp:zlib',
@@ -34,6 +55,8 @@
'../ui/accessibility/accessibility.gyp:ax_gen',
'../ui/base/ui_base.gyp:ui_base',
'../ui/base/ime/ui_base_ime.gyp:ui_base_ime',
+ '../ui/display/display.gyp:display',
+ '../ui/events/blink/events_blink.gyp:events_blink',
'../ui/events/events.gyp:events',
'../ui/events/events.gyp:events_base',
'../ui/events/events.gyp:gesture_detection',
@@ -41,14 +64,22 @@
'../ui/gfx/gfx.gyp:gfx_geometry',
'../ui/resources/ui_resources.gyp:ui_resources',
'../ui/snapshot/snapshot.gyp:snapshot',
+ '../ui/surface/surface.gyp:surface',
+ '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection',
+ '../url/ipc/url_ipc.gyp:url_ipc',
+ 'app/resources/content_resources.gyp:content_resources',
+ 'app/strings/content_strings.gyp:content_strings',
'browser/background_sync/background_sync_proto.gyp:background_sync_proto',
'browser/cache_storage/cache_storage_proto.gyp:cache_storage_proto',
+ 'browser/devtools/devtools_resources.gyp:devtools_resources',
+ 'browser/devtools/devtools.gyp:devtools_protocol_handler',
'browser/notifications/notification_proto.gyp:notification_proto',
'browser/service_worker/service_worker_proto.gyp:service_worker_proto',
'browser/speech/proto/speech_proto.gyp:speech_proto',
'content_common_mojo_bindings.gyp:content_common_mojo_bindings',
],
'export_dependent_settings': [
+ '../mojo/mojo_public.gyp:mojo_cpp_bindings',
'../ui/accessibility/accessibility.gyp:ax_gen',
# The public content API headers directly include Blink API headers, so we
# have to export the blink header settings so that relative paths in these
@@ -65,6 +96,7 @@
'variables': {
'public_browser_sources': [
'public/browser/access_token_store.h',
+ 'public/browser/android/service_registry_android.h',
'public/browser/android/browser_media_player_manager_register.cc',
'public/browser/android/browser_media_player_manager_register.h',
'public/browser/android/compositor.h',
@@ -76,6 +108,7 @@
'public/browser/android/download_controller_android.cc',
'public/browser/android/download_controller_android.h',
'public/browser/android/external_video_surface_container.h',
+ 'public/browser/android/synchronous_compositor.cc',
'public/browser/android/synchronous_compositor.h',
'public/browser/android/synchronous_compositor_client.h',
'public/browser/appcache_service.h',
@@ -114,7 +147,6 @@
'public/browser/browser_thread.h',
'public/browser/browser_thread_delegate.h',
'public/browser/browser_url_handler.h',
- 'public/browser/arc_video_host_delegate.h',
'public/browser/cache_storage_context.h',
'public/browser/cache_storage_usage_info.h',
'public/browser/cert_store.h',
@@ -138,7 +170,6 @@
'public/browser/devtools_manager_delegate.h',
'public/browser/dom_storage_context.h',
'public/browser/download_danger_type.h',
- 'public/browser/download_destination_observer.h',
'public/browser/download_interrupt_reason_values.h',
'public/browser/download_interrupt_reasons.h',
'public/browser/download_item.h',
@@ -158,6 +189,10 @@
'public/browser/global_request_id.h',
'public/browser/gpu_data_manager.h',
'public/browser/gpu_data_manager_observer.h',
+ 'public/browser/gpu_service_registry.cc',
+ 'public/browser/gpu_service_registry.h',
+ 'public/browser/gpu_utils.cc',
+ 'public/browser/gpu_utils.h',
'public/browser/histogram_fetcher.h',
'public/browser/host_zoom_map.h',
'public/browser/indexed_db_context.h',
@@ -176,6 +211,8 @@
'public/browser/media_capture_devices.h',
'public/browser/media_device_id.cc',
'public/browser/media_device_id.h',
+ 'public/browser/memory_pressure_controller.cc',
+ 'public/browser/memory_pressure_controller.h',
'public/browser/message_port_delegate.h',
'public/browser/message_port_provider.h',
'public/browser/mojo_app_connection.h',
@@ -190,8 +227,6 @@
'public/browser/navigation_throttle.cc',
'public/browser/navigation_throttle.h',
'public/browser/navigation_type.h',
- 'public/browser/navigator_connect_context.h',
- 'public/browser/navigator_connect_service_factory.h',
'public/browser/notification_database_data.h',
'public/browser/notification_details.h',
'public/browser/notification_event_dispatcher.h',
@@ -236,6 +271,7 @@
'public/browser/render_widget_host_view_mac_delegate.h',
'public/browser/resource_context.h',
'public/browser/resource_controller.h',
+ 'public/browser/resource_dispatcher_host.cc',
'public/browser/resource_dispatcher_host.h',
'public/browser/resource_dispatcher_host_delegate.cc',
'public/browser/resource_dispatcher_host_delegate.h',
@@ -302,6 +338,7 @@
'public/browser/worker_service.h',
'public/browser/worker_service_observer.h',
'public/browser/zoom_level_delegate.h',
+ 'public/browser/zygote_handle_linux.h',
'public/browser/zygote_host_linux.h',
],
'private_browser_sources': [
@@ -343,6 +380,7 @@
'browser/accessibility/browser_accessibility_manager_win.h',
'browser/accessibility/browser_accessibility_state_impl.cc',
'browser/accessibility/browser_accessibility_state_impl.h',
+ 'browser/accessibility/browser_accessibility_state_impl_mac.mm',
'browser/accessibility/browser_accessibility_state_impl_win.cc',
'browser/accessibility/browser_accessibility_win.cc',
'browser/accessibility/browser_accessibility_win.h',
@@ -367,7 +405,8 @@
'browser/android/devtools_auth.cc',
'browser/android/in_process_surface_texture_manager.cc',
'browser/android/in_process_surface_texture_manager.h',
- 'public/browser/android/download_controller_android.h',
+ 'browser/android/service_registry_android_impl.cc',
+ 'browser/android/service_registry_android_impl.h',
'browser/android/url_request_content_job.cc',
'browser/android/url_request_content_job.h',
'browser/appcache/appcache.cc',
@@ -425,12 +464,8 @@
'browser/background_sync/background_sync_metrics.h',
'browser/background_sync/background_sync_network_observer.cc',
'browser/background_sync/background_sync_network_observer.h',
- 'browser/background_sync/background_sync_power_observer.cc',
- 'browser/background_sync/background_sync_power_observer.h',
'browser/background_sync/background_sync_registration.cc',
'browser/background_sync/background_sync_registration.h',
- 'browser/background_sync/background_sync_registration_handle.cc',
- 'browser/background_sync/background_sync_registration_handle.h',
'browser/background_sync/background_sync_registration_options.cc',
'browser/background_sync/background_sync_registration_options.h',
'browser/background_sync/background_sync_service_impl.cc',
@@ -438,14 +473,20 @@
'browser/background_sync/background_sync_status.h',
'browser/bad_message.cc',
'browser/bad_message.h',
+ 'browser/blob_storage/blob_dispatcher_host.cc',
+ 'browser/blob_storage/blob_dispatcher_host.h',
'browser/bluetooth/bluetooth_allowed_devices_map.cc',
'browser/bluetooth/bluetooth_allowed_devices_map.h',
+ 'browser/bluetooth/bluetooth_blacklist.cc',
+ 'browser/bluetooth/bluetooth_blacklist.h',
'browser/bluetooth/bluetooth_dispatcher_host.cc',
'browser/bluetooth/bluetooth_dispatcher_host.h',
'browser/bluetooth/bluetooth_metrics.cc',
'browser/bluetooth/bluetooth_metrics.h',
'browser/bluetooth/first_device_bluetooth_chooser.cc',
'browser/bluetooth/first_device_bluetooth_chooser.h',
+ 'browser/bluetooth/web_bluetooth_service_impl.cc',
+ 'browser/bluetooth/web_bluetooth_service_impl.h',
'browser/bootstrap_sandbox_manager_mac.cc',
'browser/bootstrap_sandbox_manager_mac.h',
'browser/browser_child_process_host_impl.cc',
@@ -503,10 +544,17 @@
'browser/cocoa/system_hotkey_helper_mac.mm',
'browser/cocoa/system_hotkey_map.h',
'browser/cocoa/system_hotkey_map.mm',
- 'browser/device_monitor_mac.h',
- 'browser/device_monitor_mac.mm',
- 'browser/device_monitor_udev.cc',
- 'browser/device_monitor_udev.h',
+ # NOTE: These files are here instead of in compositor_browser_sources
+ # because the latter is not built on Android, whereas these files are
+ # needed on all platforms.
+ 'browser/compositor/gl_helper.cc',
+ 'browser/compositor/gl_helper.h',
+ 'browser/compositor/gl_helper_readback_support.cc',
+ 'browser/compositor/gl_helper_readback_support.h',
+ 'browser/compositor/gl_helper_scaling.cc',
+ 'browser/compositor/gl_helper_scaling.h',
+ 'browser/compositor/surface_utils.cc',
+ 'browser/compositor/surface_utils.h',
'browser/device_sensors/ambient_light_mac.cc',
'browser/device_sensors/ambient_light_mac.h',
'browser/device_sensors/data_fetcher_shared_memory.h',
@@ -527,6 +575,8 @@
'browser/device_sensors/device_orientation_absolute_message_filter.h',
'browser/device_sensors/device_orientation_message_filter.cc',
'browser/device_sensors/device_orientation_message_filter.h',
+ 'browser/device_sensors/device_sensor_message_filter.cc',
+ 'browser/device_sensors/device_sensor_message_filter.h',
'browser/device_sensors/device_sensors_consts.h',
'browser/device_sensors/sensor_manager_android.cc',
'browser/device_sensors/sensor_manager_android.h',
@@ -552,9 +602,9 @@
'browser/devtools/forwarding_agent_host.h',
'browser/devtools/protocol/color_picker.cc',
'browser/devtools/protocol/color_picker.h',
- 'browser/devtools/protocol/devtools_protocol_delegate.h',
'browser/devtools/protocol/devtools_protocol_client.cc',
'browser/devtools/protocol/devtools_protocol_client.h',
+ 'browser/devtools/protocol/devtools_protocol_delegate.h',
'browser/devtools/protocol/dom_handler.cc',
'browser/devtools/protocol/dom_handler.h',
'browser/devtools/protocol/emulation_handler.cc',
@@ -628,6 +678,7 @@
'browser/download/base_file_win.cc',
'browser/download/download_create_info.cc',
'browser/download/download_create_info.h',
+ 'browser/download/download_destination_observer.h',
'browser/download/download_file.h',
'browser/download/download_file_factory.cc',
'browser/download/download_file_factory.h',
@@ -678,8 +729,6 @@
'browser/download/save_types.h',
'browser/download/url_downloader.cc',
'browser/download/url_downloader.h',
- 'browser/fileapi/blob_storage_host.cc',
- 'browser/fileapi/blob_storage_host.h',
'browser/fileapi/browser_file_system_helper.cc',
'browser/fileapi/browser_file_system_helper.h',
'browser/fileapi/chrome_blob_storage_context.cc',
@@ -746,9 +795,11 @@
'browser/frame_host/render_widget_host_view_child_frame.h',
'browser/frame_host/render_widget_host_view_guest.cc',
'browser/frame_host/render_widget_host_view_guest.h',
+ 'browser/frame_host/traced_frame_tree_node.cc',
+ 'browser/frame_host/traced_frame_tree_node.h',
'browser/gamepad/gamepad_consumer.h',
- 'browser/gamepad/gamepad_data_fetcher.h',
'browser/gamepad/gamepad_data_fetcher.cc',
+ 'browser/gamepad/gamepad_data_fetcher.h',
'browser/gamepad/gamepad_platform_data_fetcher.h',
'browser/gamepad/gamepad_platform_data_fetcher_android.cc',
'browser/gamepad/gamepad_platform_data_fetcher_android.h',
@@ -915,6 +966,8 @@
'browser/indexed_db/leveldb/leveldb_transaction.h',
'browser/indexed_db/leveldb/leveldb_write_batch.cc',
'browser/indexed_db/leveldb/leveldb_write_batch.h',
+ 'browser/leveldb_wrapper_impl.cc',
+ 'browser/leveldb_wrapper_impl.h',
'browser/loader/async_resource_handler.cc',
'browser/loader/async_resource_handler.h',
'browser/loader/async_revalidation_driver.cc',
@@ -987,13 +1040,10 @@
'browser/media/android/browser_media_player_manager.h',
'browser/media/android/browser_media_session_manager.cc',
'browser/media/android/browser_media_session_manager.h',
+ 'browser/media/android/browser_surface_view_manager.cc',
+ 'browser/media/android/browser_surface_view_manager.h',
'browser/media/android/media_resource_getter_impl.cc',
'browser/media/android/media_resource_getter_impl.h',
- 'browser/media/android/media_session.cc',
- 'browser/media/android/media_session.h',
- 'browser/media/android/media_session_observer.h',
- 'browser/media/android/media_session_uma_helper.cc',
- 'browser/media/android/media_session_uma_helper.h',
'browser/media/android/media_throttler.cc',
'browser/media/android/media_throttler.h',
'browser/media/android/media_web_contents_observer_android.cc',
@@ -1011,6 +1061,10 @@
'browser/media/capture/cursor_renderer.h',
'browser/media/capture/cursor_renderer_aura.cc',
'browser/media/capture/cursor_renderer_aura.h',
+ 'browser/media/capture/cursor_renderer_mac.mm',
+ 'browser/media/capture/cursor_renderer_mac.h',
+ 'browser/media/capture/desktop_capture_device_uma_types.cc',
+ 'browser/media/capture/desktop_capture_device_uma_types.h',
'browser/media/capture/web_contents_audio_input_stream.cc',
'browser/media/capture/web_contents_audio_input_stream.h',
'browser/media/capture/web_contents_audio_muter.cc',
@@ -1019,9 +1073,12 @@
'browser/media/capture/web_contents_tracker.h',
'browser/media/capture/web_contents_video_capture_device.cc',
'browser/media/capture/web_contents_video_capture_device.h',
+ 'browser/media/capture/window_activity_tracker.cc',
'browser/media/capture/window_activity_tracker.h',
'browser/media/capture/window_activity_tracker_aura.cc',
'browser/media/capture/window_activity_tracker_aura.h',
+ 'browser/media/capture/window_activity_tracker_mac.h',
+ 'browser/media/capture/window_activity_tracker_mac.mm',
'browser/media/media_internals.cc',
'browser/media/media_internals.h',
'browser/media/media_internals_handler.cc',
@@ -1034,14 +1091,27 @@
'browser/media/media_web_contents_observer.h',
'browser/media/midi_host.cc',
'browser/media/midi_host.h',
- 'browser/media/webrtc_identity_store.cc',
- 'browser/media/webrtc_identity_store.h',
- 'browser/media/webrtc_identity_store_backend.cc',
- 'browser/media/webrtc_identity_store_backend.h',
+ 'browser/media/session/media_session.cc',
+ 'browser/media/session/media_session.h',
+ 'browser/media/session/media_session_controller.cc',
+ 'browser/media/session/media_session_controller.h',
+ 'browser/media/session/media_session_controllers_manager.cc',
+ 'browser/media/session/media_session_controllers_manager.h',
+ 'browser/media/session/media_session_delegate.h',
+ 'browser/media/session/media_session_delegate_android.cc',
+ 'browser/media/session/media_session_delegate_android.h',
+ 'browser/media/session/media_session_delegate_default.cc',
+ 'browser/media/session/media_session_observer.h',
+ 'browser/media/session/media_session_uma_helper.cc',
+ 'browser/media/session/media_session_uma_helper.h',
+ 'browser/media/webrtc/webrtc_identity_store.cc',
+ 'browser/media/webrtc/webrtc_identity_store.h',
+ 'browser/media/webrtc/webrtc_identity_store_backend.cc',
+ 'browser/media/webrtc/webrtc_identity_store_backend.h',
'browser/memory/memory_message_filter.cc',
'browser/memory/memory_message_filter.h',
- 'browser/memory/memory_pressure_controller.cc',
- 'browser/memory/memory_pressure_controller.h',
+ 'browser/memory/memory_pressure_controller_impl.cc',
+ 'browser/memory/memory_pressure_controller_impl.h',
'browser/message_port_message_filter.cc',
'browser/message_port_message_filter.h',
'browser/message_port_provider.cc',
@@ -1049,20 +1119,18 @@
'browser/message_port_service.h',
'browser/mime_registry_message_filter.cc',
'browser/mime_registry_message_filter.h',
+ 'browser/mojo/constants.cc',
+ 'browser/mojo/constants.h',
'browser/mojo/mojo_app_connection_impl.cc',
'browser/mojo/mojo_app_connection_impl.h',
'browser/mojo/mojo_application_host.cc',
'browser/mojo/mojo_application_host.h',
+ 'browser/mojo/mojo_child_connection.cc',
+ 'browser/mojo/mojo_child_connection.h',
'browser/mojo/mojo_shell_context.cc',
'browser/mojo/mojo_shell_context.h',
'browser/mojo/service_registrar_android.cc',
'browser/mojo/service_registrar_android.h',
- 'browser/mojo/service_registry_android.cc',
- 'browser/mojo/service_registry_android.h',
- 'browser/navigator_connect/navigator_connect_context_impl.cc',
- 'browser/navigator_connect/navigator_connect_context_impl.h',
- 'browser/navigator_connect/service_port_service_impl.cc',
- 'browser/navigator_connect/service_port_service_impl.h',
'browser/net/browser_online_state_observer.cc',
'browser/net/browser_online_state_observer.h',
'browser/net/network_errors_listing_ui.cc',
@@ -1144,8 +1212,6 @@
'browser/renderer_host/frame_metadata_util.h',
'browser/renderer_host/gamepad_browser_message_filter.cc',
'browser/renderer_host/gamepad_browser_message_filter.h',
- 'browser/renderer_host/gpu_message_filter.cc',
- 'browser/renderer_host/gpu_message_filter.h',
'browser/renderer_host/input/gesture_event_queue.cc',
'browser/renderer_host/input/gesture_event_queue.h',
'browser/renderer_host/input/input_ack_handler.h',
@@ -1157,6 +1223,8 @@
'browser/renderer_host/input/input_router_impl.h',
'browser/renderer_host/input/motion_event_web.cc',
'browser/renderer_host/input/motion_event_web.h',
+ 'browser/renderer_host/input/mouse_wheel_event_queue.cc',
+ 'browser/renderer_host/input/mouse_wheel_event_queue.h',
'browser/renderer_host/input/mouse_wheel_rails_filter_mac.cc',
'browser/renderer_host/input/mouse_wheel_rails_filter_mac.h',
'browser/renderer_host/input/render_widget_host_latency_tracker.cc',
@@ -1190,12 +1258,12 @@
'browser/renderer_host/input/synthetic_smooth_scroll_gesture.h',
'browser/renderer_host/input/synthetic_tap_gesture.cc',
'browser/renderer_host/input/synthetic_tap_gesture.h',
+ 'browser/renderer_host/input/synthetic_touch_pointer.cc',
+ 'browser/renderer_host/input/synthetic_touch_pointer.h',
'browser/renderer_host/input/synthetic_touchpad_pinch_gesture.cc',
'browser/renderer_host/input/synthetic_touchpad_pinch_gesture.h',
'browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.cc',
'browser/renderer_host/input/synthetic_touchscreen_pinch_gesture.h',
- 'browser/renderer_host/input/synthetic_touch_pointer.cc',
- 'browser/renderer_host/input/synthetic_touch_pointer.h',
'browser/renderer_host/input/tap_suppression_controller.cc',
'browser/renderer_host/input/tap_suppression_controller.h',
'browser/renderer_host/input/tap_suppression_controller_client.h',
@@ -1265,8 +1333,6 @@
'browser/renderer_host/media/video_capture_host.h',
'browser/renderer_host/media/video_capture_manager.cc',
'browser/renderer_host/media/video_capture_manager.h',
- 'browser/renderer_host/memory_benchmark_message_filter.cc',
- 'browser/renderer_host/memory_benchmark_message_filter.h',
'browser/renderer_host/native_web_keyboard_event_aura.cc',
'browser/renderer_host/native_web_keyboard_event_mac.mm',
'browser/renderer_host/overscroll_configuration.cc',
@@ -1299,6 +1365,8 @@
'browser/renderer_host/render_widget_host_view_aura.h',
'browser/renderer_host/render_widget_host_view_base.cc',
'browser/renderer_host/render_widget_host_view_base.h',
+ 'browser/renderer_host/render_widget_host_view_base_observer.cc',
+ 'browser/renderer_host/render_widget_host_view_base_observer.h',
'browser/renderer_host/render_widget_host_view_mac.h',
'browser/renderer_host/render_widget_host_view_mac.mm',
'browser/renderer_host/render_widget_host_view_mac_dictionary_helper.h',
@@ -1322,6 +1390,8 @@
'browser/renderer_host/web_input_event_aurawin.cc',
'browser/renderer_host/webmenurunner_mac.h',
'browser/renderer_host/webmenurunner_mac.mm',
+ 'browser/renderer_host/websocket_blob_sender.cc',
+ 'browser/renderer_host/websocket_blob_sender.h',
'browser/renderer_host/websocket_dispatcher_host.cc',
'browser/renderer_host/websocket_dispatcher_host.h',
'browser/renderer_host/websocket_host.cc',
@@ -1332,6 +1402,8 @@
'browser/resource_context_impl.h',
'browser/safe_util_win.cc',
'browser/safe_util_win.h',
+ 'browser/screen_orientation/screen_orientation_delegate_win.cc',
+ 'browser/screen_orientation/screen_orientation_delegate_win.h',
'browser/screen_orientation/screen_orientation_dispatcher_host_impl.cc',
'browser/screen_orientation/screen_orientation_dispatcher_host_impl.h',
'browser/service_worker/embedded_worker_instance.cc',
@@ -1340,6 +1412,8 @@
'browser/service_worker/embedded_worker_registry.h',
'browser/service_worker/foreign_fetch_request_handler.cc',
'browser/service_worker/foreign_fetch_request_handler.h',
+ 'browser/service_worker/link_header_support.cc',
+ 'browser/service_worker/link_header_support.h',
'browser/service_worker/service_worker_cache_writer.cc',
'browser/service_worker/service_worker_cache_writer.h',
'browser/service_worker/service_worker_client_utils.cc',
@@ -1486,8 +1560,6 @@
'browser/streams/stream_url_request_job.cc',
'browser/streams/stream_url_request_job.h',
'browser/streams/stream_write_observer.h',
- 'browser/system_message_window_win.cc',
- 'browser/system_message_window_win.h',
'browser/theme_helper_mac.h',
'browser/theme_helper_mac.mm',
'browser/time_zone_monitor.cc',
@@ -1504,14 +1576,10 @@
'browser/tracing/background_tracing_manager_impl.h',
'browser/tracing/background_tracing_rule.cc',
'browser/tracing/background_tracing_rule.h',
- 'browser/tracing/battor_power_trace_provider.cc',
- 'browser/tracing/battor_power_trace_provider.h',
'browser/tracing/etw_system_event_consumer_win.cc',
'browser/tracing/etw_system_event_consumer_win.h',
'browser/tracing/file_tracing_provider_impl.cc',
'browser/tracing/file_tracing_provider_impl.h',
- 'browser/tracing/power_tracing_agent.cc',
- 'browser/tracing/power_tracing_agent.h',
'browser/tracing/trace_message_filter.cc',
'browser/tracing/trace_message_filter.h',
'browser/tracing/tracing_controller_impl.cc',
@@ -1519,8 +1587,6 @@
'browser/tracing/tracing_controller_impl_data_sinks.cc',
'browser/tracing/tracing_ui.cc',
'browser/tracing/tracing_ui.h',
- 'browser/udev_linux.cc',
- 'browser/udev_linux.h',
'browser/user_metrics.cc',
'browser/utility_process_host_impl.cc',
'browser/utility_process_host_impl.h',
@@ -1572,6 +1638,9 @@
'browser/webui/web_ui_impl.cc',
'browser/webui/web_ui_impl.h',
'browser/webui/web_ui_message_handler.cc',
+ 'browser/zygote_host/zygote_communication_linux.cc',
+ 'browser/zygote_host/zygote_communication_linux.h',
+ 'browser/zygote_host/zygote_handle_linux.cc',
'browser/zygote_host/zygote_host_impl_linux.cc',
'browser/zygote_host/zygote_host_impl_linux.h',
'zygote/zygote_linux.cc',
@@ -1579,6 +1648,28 @@
'zygote/zygote_main_linux.cc',
],
'android_browser_sources': [
+ 'browser/accessibility/accessibility_tree_formatter_android.cc',
+ 'browser/accessibility/browser_accessibility_android.cc',
+ 'browser/accessibility/browser_accessibility_android.h',
+ 'browser/accessibility/browser_accessibility_manager_android.cc',
+ 'browser/accessibility/browser_accessibility_manager_android.h',
+ 'browser/android/composited_touch_handle_drawable.cc',
+ 'browser/android/composited_touch_handle_drawable.h',
+ 'browser/android/content_view_core_impl.cc',
+ 'browser/android/content_view_core_impl.h',
+ 'browser/android/content_view_core_impl_observer.h',
+ 'browser/android/content_view_render_view.cc',
+ 'browser/android/content_view_render_view.h',
+ 'browser/android/content_view_statics.cc',
+ 'browser/android/content_view_statics.h',
+ 'browser/android/date_time_chooser_android.cc',
+ 'browser/android/date_time_chooser_android.h',
+ 'browser/android/deferred_download_observer.cc',
+ 'browser/android/deferred_download_observer.h',
+ 'browser/android/download_controller_android_impl.cc',
+ 'browser/android/download_controller_android_impl.h',
+ 'browser/android/interstitial_page_delegate_android.cc',
+ 'browser/android/interstitial_page_delegate_android.h',
'browser/android/java/gin_java_bound_object.cc',
'browser/android/java/gin_java_bound_object.h',
'browser/android/java/gin_java_bound_object_delegate.cc',
@@ -1599,6 +1690,36 @@
'browser/android/java/java_type.h',
'browser/android/java/jni_helper.cc',
'browser/android/java/jni_helper.h',
+ 'browser/android/load_url_params.cc',
+ 'browser/android/load_url_params.h',
+ 'browser/android/overscroll_controller_android.cc',
+ 'browser/android/overscroll_controller_android.h',
+ 'browser/android/popup_touch_handle_drawable.cc',
+ 'browser/android/popup_touch_handle_drawable.h',
+ 'browser/android/tracing_controller_android.cc',
+ 'browser/android/tracing_controller_android.h',
+ 'browser/android/web_contents_observer_proxy.cc',
+ 'browser/android/web_contents_observer_proxy.h',
+ 'browser/compositor/browser_compositor_overlay_candidate_validator_android.cc',
+ 'browser/compositor/browser_compositor_overlay_candidate_validator_android.h',
+ 'browser/power_save_blocker_android.cc',
+ 'browser/renderer_host/compositor_impl_android.cc',
+ 'browser/renderer_host/compositor_impl_android.h',
+ 'browser/renderer_host/ime_adapter_android.cc',
+ 'browser/renderer_host/ime_adapter_android.h',
+ 'browser/renderer_host/input/synthetic_gesture_target_android.cc',
+ 'browser/renderer_host/input/synthetic_gesture_target_android.h',
+ 'browser/renderer_host/native_web_keyboard_event_android.cc',
+ 'browser/renderer_host/render_widget_host_view_android.cc',
+ 'browser/renderer_host/render_widget_host_view_android.h',
+ 'browser/screen_orientation/screen_orientation_delegate_android.cc',
+ 'browser/screen_orientation/screen_orientation_delegate_android.h',
+ 'browser/screen_orientation/screen_orientation_message_filter_android.cc',
+ 'browser/screen_orientation/screen_orientation_message_filter_android.h',
+ 'browser/web_contents/web_contents_android.cc',
+ 'browser/web_contents/web_contents_android.h',
+ 'browser/web_contents/web_contents_view_android.cc',
+ 'browser/web_contents/web_contents_view_android.h',
],
'android_in_process_browser_sources': [
'browser/android/in_process/context_provider_in_process.cc',
@@ -1609,6 +1730,8 @@
'browser/android/in_process/synchronous_compositor_impl.h',
'browser/android/in_process/synchronous_compositor_registry_in_proc.cc',
'browser/android/in_process/synchronous_compositor_registry_in_proc.h',
+ 'browser/android/in_process/synchronous_compositor_renderer_statics.cc',
+ 'browser/android/in_process/synchronous_compositor_renderer_statics.h',
'browser/android/in_process/synchronous_input_event_filter.cc',
'browser/android/in_process/synchronous_input_event_filter.h',
'browser/android/synchronous_compositor_base.cc',
@@ -1616,59 +1739,7 @@
'browser/android/synchronous_compositor_host.cc',
'browser/android/synchronous_compositor_host.h',
],
- 'android_non_aura_browser_sources': [
- 'browser/accessibility/accessibility_tree_formatter_android.cc',
- 'browser/accessibility/browser_accessibility_android.cc',
- 'browser/accessibility/browser_accessibility_android.h',
- 'browser/accessibility/browser_accessibility_manager_android.cc',
- 'browser/accessibility/browser_accessibility_manager_android.h',
- 'browser/android/composited_touch_handle_drawable.cc',
- 'browser/android/composited_touch_handle_drawable.h',
- 'browser/android/content_view_core_impl.cc',
- 'browser/android/content_view_core_impl.h',
- 'browser/android/content_view_render_view.cc',
- 'browser/android/content_view_render_view.h',
- 'browser/android/content_view_statics.cc',
- 'browser/android/content_view_statics.h',
- 'browser/android/date_time_chooser_android.cc',
- 'browser/android/date_time_chooser_android.h',
- 'browser/android/deferred_download_observer.cc',
- 'browser/android/deferred_download_observer.h',
- 'browser/android/download_controller_android_impl.cc',
- 'browser/android/download_controller_android_impl.h',
- 'browser/android/interstitial_page_delegate_android.cc',
- 'browser/android/interstitial_page_delegate_android.h',
- 'browser/android/load_url_params.cc',
- 'browser/android/load_url_params.h',
- 'browser/android/overscroll_controller_android.cc',
- 'browser/android/overscroll_controller_android.h',
- 'browser/android/popup_touch_handle_drawable.cc',
- 'browser/android/popup_touch_handle_drawable.h',
- 'browser/android/tracing_controller_android.cc',
- 'browser/android/tracing_controller_android.h',
- 'browser/android/web_contents_observer_proxy.cc',
- 'browser/android/web_contents_observer_proxy.h',
- 'browser/compositor/browser_compositor_overlay_candidate_validator_android.cc',
- 'browser/compositor/browser_compositor_overlay_candidate_validator_android.h',
- 'browser/power_save_blocker_android.cc',
- 'browser/renderer_host/compositor_impl_android.cc',
- 'browser/renderer_host/compositor_impl_android.h',
- 'browser/renderer_host/ime_adapter_android.cc',
- 'browser/renderer_host/ime_adapter_android.h',
- 'browser/renderer_host/input/synthetic_gesture_target_android.cc',
- 'browser/renderer_host/input/synthetic_gesture_target_android.h',
- 'browser/renderer_host/native_web_keyboard_event_android.cc',
- 'browser/renderer_host/render_widget_host_view_android.cc',
- 'browser/renderer_host/render_widget_host_view_android.h',
- 'browser/screen_orientation/screen_orientation_delegate_android.cc',
- 'browser/screen_orientation/screen_orientation_delegate_android.h',
- 'browser/screen_orientation/screen_orientation_message_filter_android.cc',
- 'browser/screen_orientation/screen_orientation_message_filter_android.h',
- 'browser/web_contents/web_contents_android.cc',
- 'browser/web_contents/web_contents_android.h',
- 'browser/web_contents/web_contents_view_android.cc',
- 'browser/web_contents/web_contents_view_android.h',
- ],
+
'auralinux_browser_sources': [
'browser/accessibility/accessibility_tree_formatter_auralinux.cc',
'browser/accessibility/browser_accessibility_auralinux.cc',
@@ -1677,13 +1748,13 @@
'browser/accessibility/browser_accessibility_manager_auralinux.h',
],
'webrtc_browser_sources': [
- 'browser/media/webrtc_internals.cc',
- 'browser/media/webrtc_internals.h',
- 'browser/media/webrtc_internals_message_handler.cc',
- 'browser/media/webrtc_internals_message_handler.h',
- 'browser/media/webrtc_internals_ui.cc',
- 'browser/media/webrtc_internals_ui.h',
- 'browser/media/webrtc_internals_ui_observer.h',
+ 'browser/media/webrtc/webrtc_internals.cc',
+ 'browser/media/webrtc/webrtc_internals.h',
+ 'browser/media/webrtc/webrtc_internals_message_handler.cc',
+ 'browser/media/webrtc/webrtc_internals_message_handler.h',
+ 'browser/media/webrtc/webrtc_internals_ui.cc',
+ 'browser/media/webrtc/webrtc_internals_ui.h',
+ 'browser/media/webrtc/webrtc_internals_ui_observer.h',
'browser/renderer_host/media/peer_connection_tracker_host.cc',
'browser/renderer_host/media/peer_connection_tracker_host.h',
'browser/renderer_host/media/webrtc_identity_service_host.cc',
@@ -1705,18 +1776,12 @@
'browser/compositor/browser_compositor_output_surface.cc',
'browser/compositor/browser_compositor_output_surface.h',
'browser/compositor/browser_compositor_overlay_candidate_validator.h',
- 'browser/compositor/browser_compositor_overlay_candidate_validator_android.cc',
- 'browser/compositor/browser_compositor_overlay_candidate_validator_android.h',
'browser/compositor/browser_compositor_overlay_candidate_validator_mac.h',
'browser/compositor/browser_compositor_overlay_candidate_validator_mac.mm',
'browser/compositor/browser_compositor_overlay_candidate_validator_ozone.cc',
'browser/compositor/browser_compositor_overlay_candidate_validator_ozone.h',
- 'browser/compositor/browser_compositor_view_mac.h',
- 'browser/compositor/browser_compositor_view_mac.mm',
'browser/compositor/buffer_queue.cc',
'browser/compositor/buffer_queue.h',
- 'browser/compositor/delegated_frame_host.cc',
- 'browser/compositor/delegated_frame_host.h',
'browser/compositor/gpu_browser_compositor_output_surface.cc',
'browser/compositor/gpu_browser_compositor_output_surface.h',
'browser/compositor/gpu_process_transport_factory.cc',
@@ -1733,8 +1798,6 @@
'browser/compositor/reflector_impl.h',
'browser/compositor/reflector_texture.cc',
'browser/compositor/reflector_texture.h',
- 'browser/compositor/resize_lock.cc',
- 'browser/compositor/resize_lock.h',
'browser/compositor/software_browser_compositor_output_surface.cc',
'browser/compositor/software_browser_compositor_output_surface.h',
'browser/compositor/software_output_device_mac.h',
@@ -1746,6 +1809,12 @@
'browser/compositor/software_output_device_x11.cc',
'browser/compositor/software_output_device_x11.h',
'browser/context_factory.cc',
+ 'browser/renderer_host/browser_compositor_view_mac.h',
+ 'browser/renderer_host/browser_compositor_view_mac.mm',
+ 'browser/renderer_host/delegated_frame_host.cc',
+ 'browser/renderer_host/delegated_frame_host.h',
+ 'browser/renderer_host/resize_lock.cc',
+ 'browser/renderer_host/resize_lock.h',
],
'plugin_browser_sources': [
'browser/pepper_flash_settings_helper_impl.cc',
@@ -1754,11 +1823,6 @@
'browser/plugin_content_origin_whitelist.h',
'browser/plugin_data_remover_impl.cc',
'browser/plugin_data_remover_impl.h',
- 'browser/plugin_loader_posix.cc',
- 'browser/plugin_loader_posix.h',
- 'browser/plugin_process_host.cc',
- 'browser/plugin_process_host.h',
- 'browser/plugin_process_host_mac.cc',
'browser/plugin_service_impl.cc',
'browser/plugin_service_impl.h',
'browser/ppapi_plugin_process_host.cc',
@@ -1846,43 +1910,6 @@
'browser/gamepad/gamepad_platform_data_fetcher.cc',
]
}],
- ['OS=="ios"', {
- 'sources/': [
- # iOS only needs a small portion of content; exclude all the
- # implementation, and re-include what is used.
- ['exclude', '\\.(cc|mm)$'],
- ['include', '^public/browser/navigation_details\\.cc$'],
- ['include', '^public/browser/page_navigator\\.cc$'],
- ['include', '^browser/browser_context\\.cc$'],
- ],
- }, { # OS!="ios"
- 'dependencies': [
- 'app/resources/content_resources.gyp:content_resources',
- 'app/strings/content_strings.gyp:content_strings',
- 'browser/devtools/devtools_resources.gyp:devtools_resources',
- 'browser/devtools/devtools.gyp:devtools_protocol_handler',
- '../cc/cc.gyp:cc',
- '../cc/cc.gyp:cc_surfaces',
- '../components/mime_util/mime_util.gyp:mime_util',
- '../components/scheduler/scheduler.gyp:scheduler_common',
- '../device/bluetooth/bluetooth.gyp:device_bluetooth',
- '../device/usb/usb.gyp:device_usb',
- '../gin/gin.gyp:gin',
- '../net/net.gyp:http_server',
- '../storage/storage_browser.gyp:storage',
- '../storage/storage_common.gyp:storage_common',
- '../third_party/angle/src/angle.gyp:commit_id',
- '../third_party/leveldatabase/leveldatabase.gyp:leveldatabase',
- '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
- '../third_party/mojo/mojo_public.gyp:mojo_js_bindings',
- '../ui/events/blink/events_blink.gyp:events_blink',
- '../ui/surface/surface.gyp:surface',
- '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection',
- ],
- 'export_dependent_settings': [
- '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
- ],
- }],
['debug_devtools==1', {
'defines': [
'DEBUG_DEVTOOLS=1',
@@ -1893,17 +1920,12 @@
'../printing/printing.gyp:printing',
],
}],
- ['OS!="ios" and chrome_multiple_dll!=1', {
+ ['chrome_multiple_dll!=1', {
'dependencies': [
'../third_party/WebKit/public/blink.gyp:blink',
],
}],
- ['OS!="ios"', {
- 'dependencies': [
- '../sandbox/sandbox.gyp:sandbox',
- ],
- }],
- ['OS!="android" and OS!="ios"', {
+ ['OS!="android"', {
'dependencies': [
'browser/tracing/tracing_resources.gyp:tracing_resources',
'../ui/compositor/compositor.gyp:compositor',
@@ -1914,15 +1936,13 @@
['exclude', '^public/browser/context_factory.h'],
]
}],
- ['OS!="ios"', {
- 'sources': [
- 'browser/compositor/surface_utils.cc',
- 'browser/compositor/surface_utils.h',
- ]
- }],
- ['OS!="ios"', {
+ ['(use_udev==1 and os_posix==1) or OS=="mac" or OS=="win"', {
'dependencies': [
- '../third_party/libyuv/libyuv.gyp:libyuv',
+ '../tools/battor_agent/battor_agent.gyp:battor_agent_lib',
+ ],
+ 'sources': [
+ 'browser/tracing/power_tracing_agent.cc',
+ 'browser/tracing/power_tracing_agent.h',
],
}],
['enable_webrtc==1', {
@@ -1942,8 +1962,6 @@
'sources': [
'browser/media/capture/desktop_capture_device.cc',
'browser/media/capture/desktop_capture_device.h',
- 'browser/media/capture/desktop_capture_device_uma_types.cc',
- 'browser/media/capture/desktop_capture_device_uma_types.h',
],
'dependencies': [
'../third_party/webrtc/modules/modules.gyp:desktop_capture',
@@ -1980,6 +1998,7 @@
'-ldinput8.lib',
'-ldwmapi.lib',
'-ldxguid.lib',
+ '-limm32.lib',
'-lsensorsapi.lib',
'-lportabledeviceguids.lib',
],
@@ -1999,6 +2018,7 @@
'../build/linux/system.gyp:atk',
'../build/linux/system.gyp:gconf',
'../build/linux/system.gyp:glib',
+ '../build/linux/system.gyp:xscrnsaver',
],
'variables': {
'clang_warning_flags': [
@@ -2013,14 +2033,11 @@
['use_udev == 1', {
'dependencies': [
'../device/udev_linux/udev.gyp:udev_linux',
+ '../media/media.gyp:media',
],
}, {
'sources!': [
- 'browser/device_monitor_udev.cc',
- 'browser/device_monitor_udev.h',
'browser/gamepad/gamepad_platform_data_fetcher_linux.cc',
- 'browser/udev_linux.cc',
- 'browser/udev_linux.h',
],
}],
['OS=="linux" and use_aura==1', {
@@ -2070,25 +2087,21 @@
['exclude', '^browser/tracing/trace_uploader\\.(cc|h)$'],
['exclude', '^browser/tracing/tracing_ui\\.(cc|h)$'],
],
- 'sources': [ '<@(android_browser_sources)', ],
+ 'sources': [
+ '<@(android_browser_sources)',
+ '<@(android_in_process_browser_sources)',
+ ],
'sources!': [
'browser/browser_ipc_logging.cc',
'browser/geolocation/device_data_provider.cc',
'browser/geolocation/empty_device_data_provider.cc',
'browser/geolocation/wifi_data_provider_common.cc',
+ 'browser/media/session/media_session_delegate_default.cc',
'browser/power_usage_monitor_impl.cc',
'browser/power_usage_monitor_impl.h',
+ 'browser/renderer_host/begin_frame_observer_proxy.cc',
'browser/renderer_host/native_web_keyboard_event.cc',
- ],
- 'conditions': [
- ['use_aura == 0', {
- 'sources': [
- '<@(android_in_process_browser_sources)',
- '<@(android_non_aura_browser_sources)',
- ],
- 'sources!': [ 'browser/renderer_host/begin_frame_observer_proxy.cc', ],
- }],
- ],
+ ]
}],
['OS=="mac"', {
'sources/': [
@@ -2098,26 +2111,17 @@
'browser/geolocation/empty_wifi_data_provider.cc',
],
'dependencies': [
+ '../media/media.gyp:media',
'../third_party/mozilla/mozilla.gyp:mozilla',
'../third_party/sudden_motion_sensor/sudden_motion_sensor.gyp:sudden_motion_sensor',
'../ui/accelerated_widget_mac/accelerated_widget_mac.gyp:accelerated_widget_mac',
],
- 'link_settings': {
- 'libraries': [
- '$(SDKROOT)/usr/lib/libbsm.dylib',
- ],
- },
}],
['chromeos==1', {
'dependencies': [
'../build/linux/system.gyp:dbus',
'../chromeos/chromeos.gyp:chromeos',
'../chromeos/chromeos.gyp:power_manager_proto',
- '../components/components.gyp:arc',
- ],
- 'sources': [
- 'browser/gpu/gpu_arc_video_service_host.cc',
- 'browser/gpu/gpu_arc_video_service_host.h',
],
'sources!': [
'browser/device_sensors/data_fetcher_shared_memory_default.cc',
diff --git a/chromium/content/content_browsertests.isolate b/chromium/content/content_browsertests.isolate
index 575a558148a..e4583b5b414 100644
--- a/chromium/content/content_browsertests.isolate
+++ b/chromium/content/content_browsertests.isolate
@@ -92,7 +92,6 @@
'variables': {
'files': [
'<(PRODUCT_DIR)/Content Shell.app/',
- '<(PRODUCT_DIR)/plugins/test_netscape_plugin.plugin/',
'<(PRODUCT_DIR)/ppapi_tests.plugin/Contents/MacOS/ppapi_tests',
],
},
@@ -105,7 +104,6 @@
'<(PRODUCT_DIR)/Content Shell.app.dSYM/',
'<(PRODUCT_DIR)/content_browsertests.dSYM/',
'<(PRODUCT_DIR)/ppapi_tests.plugin.dSYM/',
- '<(PRODUCT_DIR)/test_netscape_plugin.plugin.dSYM/',
],
},
}],
@@ -113,7 +111,6 @@
'variables': {
'files': [
'<(PRODUCT_DIR)/osmesa.dll',
- '<(PRODUCT_DIR)/plugins/np_test_netscape_plugin.dll',
'<(PRODUCT_DIR)/ppapi_tests.dll',
],
},
diff --git a/chromium/content/content_browsertests_apk.isolate b/chromium/content/content_browsertests_apk.isolate
index da10e3aba0b..1452eb07331 100644
--- a/chromium/content/content_browsertests_apk.isolate
+++ b/chromium/content/content_browsertests_apk.isolate
@@ -10,6 +10,8 @@
'variables': {
'command': [
'<(PRODUCT_DIR)/bin/run_content_browsertests',
+ '--logcat-output-dir', '${ISOLATED_OUTDIR}/logcats',
+ '-v',
],
'files': [
'../base/base.isolate',
diff --git a/chromium/content/content_child.gypi b/chromium/content/content_child.gypi
index bf17bcf9bc3..02e21375b79 100644
--- a/chromium/content/content_child.gypi
+++ b/chromium/content/content_child.gypi
@@ -1,4 +1,3 @@
-# Copyright 2013 The Chromium 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,17 +5,26 @@
'dependencies': [
'../base/base.gyp:base',
'../components/mime_util/mime_util.gyp:mime_util',
+ '../components/scheduler/scheduler.gyp:scheduler',
'../components/tracing.gyp:tracing',
'../components/webcrypto/webcrypto.gyp:webcrypto',
- '../mojo/mojo_base.gyp:mojo_environment_chromium',
+ '../ipc/ipc.gyp:ipc',
'../mojo/mojo_base.gyp:mojo_common_lib',
- '../mojo/mojo_base.gyp:mojo_message_pump_lib',
+ '../mojo/mojo_public.gyp:mojo_message_pump_lib',
+ '../mojo/mojo_shell.gyp:mojo_runner_common_lib',
'../skia/skia.gyp:skia',
+ '../storage/storage_common.gyp:storage_common',
+ '../third_party/WebKit/public/blink.gyp:blink',
+ '../third_party/WebKit/public/blink_resources.gyp:blink_image_resources',
+ '../third_party/WebKit/public/blink_resources.gyp:blink_resources',
'../ui/base/ui_base.gyp:ui_base',
'../ui/events/events.gyp:gestures_blink',
'../ui/gfx/gfx.gyp:gfx',
'../ui/gfx/gfx.gyp:gfx_geometry',
'../url/url.gyp:url_lib',
+ '../url/ipc/url_ipc.gyp:url_ipc',
+ 'app/resources/content_resources.gyp:content_resources',
+ 'app/strings/content_strings.gyp:content_strings',
'content_common_mojo_bindings.gyp:content_common_mojo_bindings',
],
'include_dirs': [
@@ -54,6 +62,8 @@
'child/blink_platform_impl.h',
'child/blob_storage/blob_consolidation.cc',
'child/blob_storage/blob_consolidation.h',
+ 'child/blob_storage/blob_message_filter.cc',
+ 'child/blob_storage/blob_message_filter.h',
'child/blob_storage/blob_transport_controller.cc',
'child/blob_storage/blob_transport_controller.h',
'child/browser_font_resource_trusted.cc',
@@ -96,6 +106,8 @@
'child/fileapi/webfilewriter_base.h',
'child/fileapi/webfilewriter_impl.cc',
'child/fileapi/webfilewriter_impl.h',
+ 'child/font_warmup_win.cc',
+ 'child/font_warmup_win.h',
'child/ftp_directory_listing_response_delegate.cc',
'child/ftp_directory_listing_response_delegate.h',
'child/geofencing/geofencing_dispatcher.cc',
@@ -123,12 +135,6 @@
'child/mojo/mojo_application.cc',
'child/mojo/mojo_application.h',
'child/mojo/type_converters.h',
- 'child/multipart_response_delegate.cc',
- 'child/multipart_response_delegate.h',
- 'child/navigator_connect/service_port_dispatcher_impl.cc',
- 'child/navigator_connect/service_port_dispatcher_impl.h',
- 'child/navigator_connect/service_port_provider.cc',
- 'child/navigator_connect/service_port_provider.h',
'child/notifications/notification_data_conversions.cc',
'child/notifications/notification_data_conversions.h',
'child/notifications/notification_dispatcher.cc',
@@ -137,51 +143,16 @@
'child/notifications/notification_image_loader.h',
'child/notifications/notification_manager.cc',
'child/notifications/notification_manager.h',
+ 'child/notifications/pending_notification.cc',
+ 'child/notifications/pending_notification.h',
'child/notifications/pending_notifications_tracker.cc',
'child/notifications/pending_notifications_tracker.h',
- 'child/npapi/np_channel_base.cc',
- 'child/npapi/np_channel_base.h',
- 'child/npapi/npobject_base.h',
- 'child/npapi/npobject_proxy.cc',
- 'child/npapi/npobject_proxy.h',
- 'child/npapi/npobject_stub.cc',
- 'child/npapi/npobject_stub.h',
- 'child/npapi/npobject_util.cc',
- 'child/npapi/npobject_util.h',
- 'child/npapi/npruntime_util.cc',
- 'child/npapi/npruntime_util.h',
- 'child/npapi/plugin_host.cc',
- 'child/npapi/plugin_host.h',
- 'child/npapi/plugin_instance.cc',
- 'child/npapi/plugin_instance.h',
- 'child/npapi/plugin_instance_mac.mm',
- 'child/npapi/plugin_lib.cc',
- 'child/npapi/plugin_lib.h',
- 'child/npapi/plugin_web_event_converter_mac.h',
- 'child/npapi/plugin_web_event_converter_mac.mm',
- 'child/npapi/webplugin.h',
- 'child/npapi/webplugin_accelerated_surface_mac.h',
- 'child/npapi/webplugin_delegate.h',
- 'child/npapi/webplugin_delegate_impl.cc',
- 'child/npapi/webplugin_delegate_impl.h',
- 'child/npapi/webplugin_delegate_impl_android.cc',
- 'child/npapi/webplugin_delegate_impl_aura.cc',
- 'child/npapi/webplugin_delegate_impl_mac.mm',
- 'child/npapi/webplugin_delegate_impl_win.cc',
- 'child/npapi/webplugin_ime_win.cc',
- 'child/npapi/webplugin_ime_win.h',
- 'child/npapi/webplugin_resource_client.h',
'child/permissions/permission_dispatcher.cc',
'child/permissions/permission_dispatcher.h',
'child/permissions/permission_dispatcher_thread_proxy.cc',
'child/permissions/permission_dispatcher_thread_proxy.h',
'child/permissions/permission_observers_registry.cc',
'child/permissions/permission_observers_registry.h',
- 'child/plugin_message_generator.cc',
- 'child/plugin_message_generator.h',
- 'child/plugin_messages.h',
- 'child/plugin_param_traits.cc',
- 'child/plugin_param_traits.h',
'child/power_monitor_broadcast_source.cc',
'child/power_monitor_broadcast_source.h',
'child/process_control_impl.cc',
@@ -207,10 +178,6 @@
'child/scoped_child_process_reference.cc',
'child/scoped_child_process_reference.h',
'child/scoped_web_callbacks.h',
- 'child/shared_memory_data_consumer_handle.cc',
- 'child/shared_memory_data_consumer_handle.h',
- 'child/shared_memory_received_data_factory.cc',
- 'child/shared_memory_received_data_factory.h',
'child/service_worker/service_worker_dispatcher.cc',
'child/service_worker/service_worker_dispatcher.h',
'child/service_worker/service_worker_handle_reference.cc',
@@ -229,32 +196,28 @@
'child/service_worker/web_service_worker_provider_impl.h',
'child/service_worker/web_service_worker_registration_impl.cc',
'child/service_worker/web_service_worker_registration_impl.h',
+ 'child/shared_memory_data_consumer_handle.cc',
+ 'child/shared_memory_data_consumer_handle.h',
+ 'child/shared_memory_received_data_factory.cc',
+ 'child/shared_memory_received_data_factory.h',
'child/shared_worker_devtools_agent.cc',
'child/shared_worker_devtools_agent.h',
'child/simple_webmimeregistry_impl.cc',
'child/simple_webmimeregistry_impl.h',
'child/site_isolation_stats_gatherer.cc',
'child/site_isolation_stats_gatherer.h',
+ 'child/storage_util.cc',
+ 'child/storage_util.h',
'child/sync_load_response.cc',
'child/sync_load_response.h',
'child/thread_safe_sender.cc',
'child/thread_safe_sender.h',
- 'child/threaded_data_provider.cc',
- 'child/threaded_data_provider.h',
'child/v8_value_converter_impl.cc',
'child/v8_value_converter_impl.h',
'child/web_data_consumer_handle_impl.cc',
'child/web_data_consumer_handle_impl.h',
'child/web_database_observer_impl.cc',
'child/web_database_observer_impl.h',
- 'child/web_discardable_memory_impl.cc',
- 'child/web_discardable_memory_impl.h',
- 'child/web_memory_allocator_dump_impl.cc',
- 'child/web_memory_allocator_dump_impl.h',
- 'child/web_memory_dump_provider_adapter.cc',
- 'child/web_memory_dump_provider_adapter.h',
- 'child/web_process_memory_dump_impl.cc',
- 'child/web_process_memory_dump_impl.h',
'child/web_url_loader_impl.cc',
'child/web_url_loader_impl.h',
'child/web_url_request_util.cc',
@@ -306,38 +269,6 @@
'sources!': [
'child/browser_font_resource_trusted.cc',
],
- 'sources/': [
- ['exclude', '^child/npapi/plugin_'],
- ['exclude', '^child/npapi/webplugin_'],
- ],
- }],
- ['OS=="ios"', {
- 'sources/': [
- # iOS only needs a small portion of content; exclude all the
- # implementation, and re-include what is used.
- ['exclude', '\\.(cc|mm)$'],
- ],
- }, { # OS!="ios"
- 'dependencies': [
- 'app/resources/content_resources.gyp:content_resources',
- 'app/strings/content_strings.gyp:content_strings',
- '../components/scheduler/scheduler.gyp:scheduler',
- '../storage/storage_common.gyp:storage_common',
- '../third_party/WebKit/public/blink.gyp:blink',
- '../third_party/WebKit/public/blink_resources.gyp:blink_image_resources',
- '../third_party/WebKit/public/blink_resources.gyp:blink_resources',
- '../third_party/npapi/npapi.gyp:npapi',
- ],
- }],
- ['use_aura==1', {
- 'sources!': [
- 'child/npapi/webplugin_delegate_impl_mac.mm',
- ],
- }],
- ['OS=="win"', {
- 'sources!': [
- 'child/npapi/webplugin_delegate_impl_aura.cc',
- ],
}],
],
}
diff --git a/chromium/content/content_common.gypi b/chromium/content/content_common.gypi
index c9ebbb9728c..916c724e22e 100644
--- a/chromium/content/content_common.gypi
+++ b/chromium/content/content_common.gypi
@@ -5,11 +5,41 @@
{
'dependencies': [
'../base/base.gyp:base',
+ '../cc/cc.gyp:cc',
'../components/tracing.gyp:tracing',
+ '../device/bluetooth/bluetooth.gyp:device_bluetooth',
+ '../gpu/blink/gpu_blink.gyp:gpu_blink',
'../gpu/command_buffer/command_buffer.gyp:gles2_utils',
+ '../gpu/gpu.gyp:command_buffer_service',
+ '../gpu/gpu.gyp:gles2_c_lib',
+ '../gpu/gpu.gyp:gles2_implementation',
+
+ # TODO(markdittmer): This should be removed once content/common/gpu/media
+ # is refactored into media/ipc.
+ '../gpu/gpu.gyp:gpu_ipc_service',
+
+ # TODO: the dependency on gl_in_process_context should be decoupled from
+ # content and moved to android_webview. See crbug.com/365797.
+ '../gpu/gpu.gyp:gl_in_process_context',
+ '../gpu/gpu.gyp:gpu',
+ '../gpu/skia_bindings/skia_bindings.gyp:gpu_skia_bindings',
+ '../ipc/ipc.gyp:ipc',
+ '../ipc/mojo/ipc_mojo.gyp:ipc_mojo',
+ '../media/media.gyp:media',
+ '../media/media.gyp:shared_memory_support',
+ '../media/gpu/ipc/media_ipc.gyp:media_gpu_ipc_client',
+ '../media/gpu/ipc/media_ipc.gyp:media_gpu_ipc_common',
+ '../media/midi/midi.gyp:midi',
+ '../mojo/mojo_base.gyp:mojo_application_bindings',
+ '../mojo/mojo_edk.gyp:mojo_system_impl',
+ '../mojo/mojo_public.gyp:mojo_cpp_bindings',
+ '../mojo/mojo_shell.gyp:mojo_runner_common_lib',
'../net/net.gyp:net',
'../skia/skia.gyp:skia',
+ '../storage/storage_common.gyp:storage_common',
+ '../third_party/WebKit/public/blink.gyp:blink',
'../third_party/WebKit/public/blink_headers.gyp:blink_headers',
+ '../third_party/boringssl/boringssl.gyp:boringssl',
'../third_party/icu/icu.gyp:icuuc',
'../ui/accessibility/accessibility.gyp:accessibility',
'../ui/accessibility/accessibility.gyp:ax_gen',
@@ -19,14 +49,45 @@
'../ui/gfx/gfx.gyp:gfx',
'../ui/gfx/gfx.gyp:gfx_geometry',
'../ui/gfx/ipc/gfx_ipc.gyp:gfx_ipc',
+ '../ui/gfx/ipc/skia/gfx_ipc_skia.gyp:gfx_ipc_skia',
+ '../ui/gl/gl.gyp:gl',
'../ui/shell_dialogs/shell_dialogs.gyp:shell_dialogs',
'../url/url.gyp:url_lib',
+ '../url/ipc/url_ipc.gyp:url_ipc',
+ 'content.gyp:common_features',
+ 'content_common_mojo_bindings.gyp:content_common_mojo_bindings',
],
'include_dirs': [
'..',
],
+ 'actions': [
+ {
+ 'action_name': 'generate_webkit_version',
+ 'inputs': [
+ '<(script)',
+ '<(lastchange)',
+ '<(template)',
+ ],
+ 'outputs': [
+ '<(SHARED_INTERMEDIATE_DIR)/build/util/webkit_version.h',
+ ],
+ 'action': ['python',
+ '<(script)',
+ '-f', '<(lastchange)',
+ '<(template)',
+ '<@(_outputs)',
+ ],
+ 'variables': {
+ 'script': '<(DEPTH)/build/util/version.py',
+ 'lastchange': '<(DEPTH)/build/util/LASTCHANGE.blink',
+ 'template': '<(DEPTH)/build/util/webkit_version.h.in',
+ },
+ },
+ ],
'export_dependent_settings': [
'../base/base.gyp:base',
+ '../mojo/mojo_base.gyp:mojo_application_bindings',
+ '../mojo/mojo_public.gyp:mojo_cpp_bindings',
# The public content API headers directly include Blink API headers, so we
# have to export the blink header settings so that relative paths in these
# headers resolve correctly.
@@ -68,7 +129,6 @@
'public/common/context_menu_params.h',
'public/common/drop_data.cc',
'public/common/drop_data.h',
- 'public/common/dwrite_font_platform_win.h',
'public/common/favicon_url.cc',
'public/common/favicon_url.h',
'public/common/file_chooser_file_info.cc',
@@ -79,14 +139,14 @@
'public/common/frame_navigate_params.h',
'public/common/geoposition.cc',
'public/common/geoposition.h',
- 'public/common/gpu_memory_stats.cc',
- 'public/common/gpu_memory_stats.h',
'public/common/injection_test_mac.h',
'public/common/injection_test_win.h',
'public/common/javascript_message_type.h',
'public/common/main_function_params.h',
'public/common/manifest.cc',
'public/common/manifest.h',
+ 'public/common/media_metadata.cc',
+ 'public/common/media_metadata.h',
'public/common/media_stream_request.cc',
'public/common/media_stream_request.h',
'public/common/menu_item.cc',
@@ -96,8 +156,8 @@
'public/common/mojo_channel_switches.cc',
'public/common/mojo_channel_switches.h',
'public/common/mojo_shell_connection.h',
- 'public/common/navigator_connect_client.cc',
- 'public/common/navigator_connect_client.h',
+ 'public/common/notification_resources.cc',
+ 'public/common/notification_resources.h',
'public/common/origin_util.h',
'public/common/page_state.cc',
'public/common/page_state.h',
@@ -162,8 +222,11 @@
'public/common/window_container_type.cc',
'public/common/window_container_type.h',
'public/common/zygote_fork_delegate_linux.h',
+ 'public/common/zygote_handle.h',
],
'private_common_sources': [
+ 'common/accelerated_surface_buffers_swapped_params_mac.cc',
+ 'common/accelerated_surface_buffers_swapped_params_mac.h',
'common/accessibility_messages.h',
'common/all_messages.h',
'common/android/address_parser.cc',
@@ -178,10 +241,8 @@
'common/android/gin_java_bridge_value.h',
'common/android/hash_set.cc',
'common/android/hash_set.h',
- 'common/android/surface_texture_manager.cc',
- 'common/android/surface_texture_manager.h',
- 'common/android/surface_texture_peer.cc',
- 'common/android/surface_texture_peer.h',
+ 'common/android/media_metadata_android.cc',
+ 'common/android/media_metadata_android.h',
'common/android/sync_compositor_messages.cc',
'common/android/sync_compositor_messages.h',
'common/appcache_interfaces.cc',
@@ -197,6 +258,8 @@
'common/browser_plugin/browser_plugin_constants.cc',
'common/browser_plugin/browser_plugin_constants.h',
'common/browser_plugin/browser_plugin_messages.h',
+ 'common/buffer_presented_params_mac.cc',
+ 'common/buffer_presented_params_mac.h',
'common/cache_storage/cache_storage_messages.h',
'common/cache_storage/cache_storage_types.cc',
'common/cache_storage/cache_storage_types.h',
@@ -250,14 +313,12 @@
'common/drag_event_source_info.h',
'common/drag_messages.h',
'common/drag_traits.h',
- 'common/dwrite_font_platform_win.cc',
'common/dwrite_font_proxy_messages.h',
'common/edit_command.h',
- 'common/experiments/api_key.cc',
- 'common/experiments/api_key.h',
+ 'common/establish_channel_params.cc',
+ 'common/establish_channel_params.h',
'common/file_utilities_messages.h',
'common/fileapi/file_system_messages.h',
- 'common/fileapi/webblob_messages.h',
'common/font_cache_dispatcher_win.cc',
'common/font_cache_dispatcher_win.h',
'common/font_config_ipc_linux.cc',
@@ -269,13 +330,8 @@
'common/font_list_ozone.cc',
'common/font_list_pango.cc',
'common/font_list_win.cc',
- 'common/font_warmup_win.cc',
- 'common/font_warmup_win.h',
'common/frame_message_enums.h',
'common/frame_messages.h',
- 'common/frame_param.cc',
- 'common/frame_param.h',
- 'common/frame_param_macros.h',
'common/frame_replication_state.cc',
'common/frame_replication_state.h',
'common/gamepad_hardware_buffer.h',
@@ -292,88 +348,35 @@
'common/gin_java_bridge_messages.h',
'common/gpu/client/command_buffer_metrics.cc',
'common/gpu/client/command_buffer_metrics.h',
- 'common/gpu/client/command_buffer_proxy_impl.cc',
- 'common/gpu/client/command_buffer_proxy_impl.h',
'common/gpu/client/context_provider_command_buffer.cc',
'common/gpu/client/context_provider_command_buffer.h',
- 'common/gpu/client/gl_helper.cc',
- 'common/gpu/client/gl_helper.h',
- 'common/gpu/client/gl_helper_readback_support.cc',
- 'common/gpu/client/gl_helper_readback_support.h',
- 'common/gpu/client/gl_helper_scaling.cc',
- 'common/gpu/client/gl_helper_scaling.h',
- 'common/gpu/client/gpu_channel_host.cc',
- 'common/gpu/client/gpu_channel_host.h',
- 'common/gpu/client/gpu_jpeg_decode_accelerator_host.cc',
- 'common/gpu/client/gpu_jpeg_decode_accelerator_host.h',
- 'common/gpu/client/gpu_memory_buffer_impl.cc',
- 'common/gpu/client/gpu_memory_buffer_impl.h',
- 'common/gpu/client/gpu_memory_buffer_impl_ozone_native_pixmap.cc',
- 'common/gpu/client/gpu_memory_buffer_impl_ozone_native_pixmap.h',
- 'common/gpu/client/gpu_memory_buffer_impl_shared_memory.cc',
- 'common/gpu/client/gpu_memory_buffer_impl_shared_memory.h',
- 'common/gpu/client/gpu_video_decode_accelerator_host.cc',
- 'common/gpu/client/gpu_video_decode_accelerator_host.h',
- 'common/gpu/client/gpu_video_encode_accelerator_host.cc',
- 'common/gpu/client/gpu_video_encode_accelerator_host.h',
- 'common/gpu/client/grcontext_for_webgraphicscontext3d.cc',
- 'common/gpu/client/grcontext_for_webgraphicscontext3d.h',
+ 'common/gpu/client/grcontext_for_gles2_interface.cc',
+ 'common/gpu/client/grcontext_for_gles2_interface.h',
'common/gpu/client/webgraphicscontext3d_command_buffer_impl.cc',
'common/gpu/client/webgraphicscontext3d_command_buffer_impl.h',
- 'common/gpu/ca_layer_partial_damage_tree_mac.h',
- 'common/gpu/ca_layer_partial_damage_tree_mac.mm',
- 'common/gpu/ca_layer_tree_mac.h',
- 'common/gpu/ca_layer_tree_mac.mm',
- 'common/gpu/child_window_surface_win.cc',
- 'common/gpu/child_window_surface_win.h',
- 'common/gpu/gpu_channel.cc',
- 'common/gpu/gpu_channel.h',
- 'common/gpu/gpu_channel_manager.cc',
- 'common/gpu/gpu_channel_manager.h',
- 'common/gpu/gpu_command_buffer_stub.cc',
- 'common/gpu/gpu_command_buffer_stub.h',
- 'common/gpu/gpu_config.h',
- 'common/gpu/gpu_memory_buffer_factory.cc',
- 'common/gpu/gpu_memory_buffer_factory.h',
- 'common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.cc',
- 'common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.h',
- 'common/gpu/gpu_memory_manager.cc',
- 'common/gpu/gpu_memory_manager.h',
- 'common/gpu/gpu_memory_tracking.cc',
- 'common/gpu/gpu_memory_tracking.h',
- 'common/gpu/gpu_memory_uma_stats.h',
- 'common/gpu/gpu_messages.h',
- 'common/gpu/gpu_process_launch_causes.h',
- 'common/gpu/gpu_result_codes.h',
- 'common/gpu/gpu_stream_priority.h',
- 'common/gpu/gpu_surface_lookup.cc',
- 'common/gpu/gpu_surface_lookup.h',
- 'common/gpu/gpu_watchdog.h',
- 'common/gpu/image_transport_surface.cc',
- 'common/gpu/image_transport_surface.h',
- 'common/gpu/image_transport_surface_android.cc',
- 'common/gpu/image_transport_surface_linux.cc',
- 'common/gpu/image_transport_surface_mac.mm',
- 'common/gpu/image_transport_surface_overlay_mac.h',
- 'common/gpu/image_transport_surface_overlay_mac.mm',
- 'common/gpu/image_transport_surface_win.cc',
'common/gpu/media/fake_video_decode_accelerator.cc',
'common/gpu/media/fake_video_decode_accelerator.h',
'common/gpu/media/gpu_jpeg_decode_accelerator.cc',
'common/gpu/media/gpu_jpeg_decode_accelerator.h',
- 'common/gpu/media/gpu_video_accelerator_util.cc',
- 'common/gpu/media/gpu_video_accelerator_util.h',
'common/gpu/media/gpu_video_decode_accelerator.cc',
'common/gpu/media/gpu_video_decode_accelerator.h',
+ 'common/gpu/media/gpu_video_decode_accelerator_factory_impl.cc',
+ 'common/gpu/media/gpu_video_decode_accelerator_factory_impl.h',
+ 'common/gpu/media/gpu_video_decode_accelerator_helpers.h',
'common/gpu/media/gpu_video_encode_accelerator.cc',
'common/gpu/media/gpu_video_encode_accelerator.h',
- 'common/gpu/stream_texture_android.cc',
- 'common/gpu/stream_texture_android.h',
+ 'common/gpu/media/media_channel.cc',
+ 'common/gpu/media/media_channel.h',
+ 'common/gpu/media/media_service.cc',
+ 'common/gpu/media/media_service.h',
+ 'common/gpu/media/shared_memory_region.cc',
+ 'common/gpu/media/shared_memory_region.h',
+ 'common/gpu_host_messages.h',
+ 'common/gpu_process_launch_causes.h',
'common/host_discardable_shared_memory_manager.cc',
'common/host_discardable_shared_memory_manager.h',
'common/host_shared_bitmap_manager.cc',
'common/host_shared_bitmap_manager.h',
- 'common/id_type.h',
'common/in_process_child_thread_params.cc',
'common/in_process_child_thread_params.h',
'common/indexed_db/indexed_db_constants.h',
@@ -388,14 +391,18 @@
'common/indexed_db/indexed_db_param_traits.h',
'common/input/did_overscroll_params.cc',
'common/input/did_overscroll_params.h',
+ 'common/input/event_with_latency_info.h',
'common/input/gesture_event_stream_validator.cc',
'common/input/gesture_event_stream_validator.h',
'common/input/input_event.cc',
'common/input/input_event.h',
'common/input/input_event_ack.cc',
'common/input/input_event_ack.h',
+ 'common/input/input_event_dispatch_type.h',
'common/input/input_event_stream_validator.cc',
'common/input/input_event_stream_validator.h',
+ 'common/input/input_event_utils.cc',
+ 'common/input/input_event_utils.h',
'common/input/input_param_traits.cc',
'common/input/input_param_traits.h',
'common/input/scoped_web_input_event.cc',
@@ -406,6 +413,8 @@
'common/input/synthetic_gesture_params.h',
'common/input/synthetic_pinch_gesture_params.cc',
'common/input/synthetic_pinch_gesture_params.h',
+ 'common/input/synthetic_pointer_action_params.cc',
+ 'common/input/synthetic_pointer_action_params.h',
'common/input/synthetic_smooth_drag_gesture_params.cc',
'common/input/synthetic_smooth_drag_gesture_params.h',
'common/input/synthetic_smooth_scroll_gesture_params.cc',
@@ -416,6 +425,7 @@
'common/input/synthetic_web_input_event_builders.h',
'common/input/touch_event_stream_validator.cc',
'common/input/touch_event_stream_validator.h',
+ 'common/input/web_input_event_queue.h',
'common/input/web_input_event_traits.cc',
'common/input/web_input_event_traits.h',
'common/input/web_touch_event_traits.cc',
@@ -436,6 +446,7 @@
'common/media/cdm_messages_enums.h',
'common/media/media_param_traits.cc',
'common/media/media_param_traits.h',
+ 'common/media/media_player_delegate_messages.h',
'common/media/media_player_messages_android.h',
'common/media/media_session_messages_android.h',
'common/media/media_stream_messages.h',
@@ -443,29 +454,39 @@
'common/media/media_stream_options.h',
'common/media/media_stream_track_metrics_host_messages.h',
'common/media/midi_messages.h',
+ 'common/media/surface_view_manager_messages_android.h',
'common/media/video_capture.h',
'common/media/video_capture_messages.h',
'common/media/webrtc_identity_messages.h',
- 'common/memory_benchmark_messages.h',
'common/memory_messages.h',
'common/message_port_messages.h',
- 'common/message_router.cc',
- 'common/message_router.h',
'common/mime_registry_messages.h',
'common/mojo/channel_init.cc',
'common/mojo/channel_init.h',
+ 'common/mojo/current_thread_loader.cc',
+ 'common/mojo/current_thread_loader.h',
'common/mojo/mojo_messages.h',
+ 'common/mojo/mojo_shell_connection_impl.cc',
+ 'common/mojo/mojo_shell_connection_impl.h',
'common/mojo/service_registry_impl.cc',
'common/mojo/service_registry_impl.h',
+ 'common/mojo/static_loader.cc',
+ 'common/mojo/static_loader.h',
'common/navigation_gesture.h',
'common/navigation_params.cc',
'common/navigation_params.h',
'common/net/url_fetcher.cc',
+ 'common/net/url_request_service_worker_data.cc',
+ 'common/net/url_request_service_worker_data.h',
'common/net/url_request_user_data.cc',
'common/net/url_request_user_data.h',
'common/notification_constants.h',
'common/one_writer_seqlock.cc',
'common/one_writer_seqlock.h',
+ 'common/origin_trials/trial_token.cc',
+ 'common/origin_trials/trial_token.h',
+ 'common/origin_trials/trial_token_validator.cc',
+ 'common/origin_trials/trial_token_validator.h',
'common/origin_util.cc',
'common/p2p_messages.h',
'common/page_state_serialization.cc',
@@ -479,19 +500,15 @@
'common/pepper_renderer_instance_data.cc',
'common/pepper_renderer_instance_data.h',
'common/platform_notification_messages.h',
- 'common/plugin_constants_win.cc',
- 'common/plugin_constants_win.h',
'common/plugin_list.cc',
'common/plugin_list.h',
- 'common/plugin_list_mac.mm',
- 'common/plugin_list_posix.cc',
- 'common/plugin_list_win.cc',
- 'common/plugin_process_messages.h',
'common/power_monitor_messages.h',
'common/process_type.cc',
'common/push_messaging_messages.h',
'common/quota_messages.h',
'common/render_process_messages.h',
+ 'common/resize_params.cc',
+ 'common/resize_params.h',
'common/resource_messages.cc',
'common/resource_messages.h',
'common/resource_request_body.cc',
@@ -531,9 +548,8 @@
'common/savable_url_schemes.h',
'common/screen_orientation_messages.h',
'common/send_zygote_child_ping_linux.cc',
- 'common/service_port_type_converters.cc',
- 'common/service_port_type_converters.h',
'common/service_worker/embedded_worker_messages.h',
+ 'common/service_worker/embedded_worker_settings.h',
'common/service_worker/service_worker_client_info.cc',
'common/service_worker/service_worker_client_info.h',
'common/service_worker/service_worker_messages.h',
@@ -563,8 +579,6 @@
'common/utility_messages.h',
'common/view_message_enums.h',
'common/view_messages.h',
- 'common/webplugin_geometry.cc',
- 'common/webplugin_geometry.h',
'common/websocket.cc',
'common/websocket.h',
'common/websocket_messages.h',
@@ -585,94 +599,6 @@
}],
],
'conditions': [
- ['OS=="ios"', {
- # iOS has different user-agent construction utilities, since the
- # version strings is not derived from webkit_version, and follows
- # a different format.
- 'sources!': [
- 'common/user_agent.cc',
- ],
- 'sources/': [
- # iOS only needs a small portion of content; exclude all the
- # implementation, and re-include what is used.
- ['exclude', '\\.(cc|mm)$'],
- ['include', '_ios\\.(cc|mm)$'],
- ['include', '^public/common/content_client\\.cc$'],
- ['include', '^public/common/content_constants\\.cc$'],
- ['include', '^public/common/content_switches\\.cc$'],
- ['include', '^public/common/frame_navigate_params\\.cc$'],
- ['include', '^public/common/media_stream_request\\.cc$'],
- ['include', '^public/common/page_state\\.cc$'],
- ['include', '^public/common/password_form\\.cc$'],
- ['include', '^public/common/signed_certificate_timestamp_id_and_status\\.cc$'],
- ['include', '^public/common/speech_recognition_result\\.cc$'],
- ['include', '^public/common/ssl_status\\.cc$'],
- ['include', '^public/common/url_constants\\.cc$'],
- ['include', '^common/content_paths\\.cc$'],
- ['include', '^common/media/media_stream_options\\.cc$'],
- ['include', '^common/net/url_fetcher\\.cc$'],
- ['include', '^common/net/url_request_user_data\\.cc$'],
- ['include', '^common/page_state_serialization\\.cc$'],
- ['include', '^common/savable_url_schemes\\.cc$'],
- ['include', '^common/url_schemes\\.cc$'],
- ],
- }, { # OS!="ios"
- 'dependencies': [
- '../cc/cc.gyp:cc',
- '../device/bluetooth/bluetooth.gyp:device_bluetooth',
- '../gpu/blink/gpu_blink.gyp:gpu_blink',
- '../gpu/gpu.gyp:command_buffer_service',
- '../gpu/gpu.gyp:gles2_c_lib',
- '../gpu/gpu.gyp:gles2_implementation',
- # TODO: the dependency on gl_in_process_context should be decoupled from
- # content and moved to android_webview. See crbug.com/365797.
- '../gpu/gpu.gyp:gl_in_process_context',
- '../gpu/gpu.gyp:gpu_ipc',
- '../gpu/skia_bindings/skia_bindings.gyp:gpu_skia_bindings',
- '../ipc/ipc.gyp:ipc',
- '../ipc/mojo/ipc_mojo.gyp:ipc_mojo',
- '../media/media.gyp:media',
- '../media/media.gyp:shared_memory_support',
- '../media/midi/midi.gyp:midi',
- '../mojo/mojo_base.gyp:mojo_application_bindings',
- '../mojo/mojo_base.gyp:mojo_environment_chromium',
- '../storage/storage_common.gyp:storage_common',
- '../third_party/WebKit/public/blink.gyp:blink',
- '../third_party/boringssl/boringssl.gyp:boringssl',
- '../third_party/mojo/mojo_edk.gyp:mojo_system_impl',
- '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
- '../ui/gl/gl.gyp:gl',
- 'content_common_mojo_bindings.gyp:content_common_mojo_bindings',
- ],
- 'export_dependent_settings' : [
- '../mojo/mojo_base.gyp:mojo_application_bindings',
- '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
- ],
- 'actions': [
- {
- 'action_name': 'generate_webkit_version',
- 'inputs': [
- '<(script)',
- '<(lastchange)',
- '<(template)',
- ],
- 'outputs': [
- '<(SHARED_INTERMEDIATE_DIR)/build/util/webkit_version.h',
- ],
- 'action': ['python',
- '<(script)',
- '-f', '<(lastchange)',
- '<(template)',
- '<@(_outputs)',
- ],
- 'variables': {
- 'script': '<(DEPTH)/build/util/version.py',
- 'lastchange': '<(DEPTH)/build/util/LASTCHANGE.blink',
- 'template': '<(DEPTH)/build/util/webkit_version.h.in',
- },
- },
- ],
- }],
['OS=="mac"', {
'dependencies': [
'../media/media.gyp:media',
@@ -680,19 +606,17 @@
'../ui/accelerated_widget_mac/accelerated_widget_mac.gyp:accelerated_widget_mac'
],
'sources': [
- 'common/gpu/client/gpu_memory_buffer_impl_io_surface.cc',
- 'common/gpu/client/gpu_memory_buffer_impl_io_surface.h',
- 'common/gpu/gpu_memory_buffer_factory_io_surface.cc',
- 'common/gpu/gpu_memory_buffer_factory_io_surface.h',
'common/gpu/media/vt_mac.h',
'common/gpu/media/vt_video_decode_accelerator_mac.cc',
'common/gpu/media/vt_video_decode_accelerator_mac.h',
- ],
- 'sources!': [
- 'common/plugin_list_posix.cc',
+ 'common/gpu/media/vt_video_encode_accelerator_mac.cc',
+ 'common/gpu/media/vt_video_encode_accelerator_mac.h',
],
'link_settings': {
'libraries': [
+ '$(SDKROOT)/System/Library/Frameworks/AVFoundation.framework',
+ '$(SDKROOT)/System/Library/Frameworks/CoreMedia.framework',
+ '$(SDKROOT)/System/Library/Frameworks/CoreVideo.framework',
'$(SDKROOT)/System/Library/Frameworks/IOSurface.framework',
'$(SDKROOT)/System/Library/Frameworks/QuartzCore.framework',
'$(SDKROOT)/usr/lib/libsandbox.dylib',
@@ -739,12 +663,6 @@
],
}],
['OS=="android"',{
- 'sources': [
- 'common/gpu/client/gpu_memory_buffer_impl_surface_texture.cc',
- 'common/gpu/client/gpu_memory_buffer_impl_surface_texture.h',
- 'common/gpu/gpu_memory_buffer_factory_surface_texture.cc',
- 'common/gpu/gpu_memory_buffer_factory_surface_texture.h',
- ],
'link_settings': {
'libraries': [
'-landroid', # ANativeWindow
@@ -771,11 +689,6 @@
'<(DEPTH)/build/linux/system.gyp:xcomposite',
],
}],
- ['use_x11 == 1 and (target_arch != "arm" or chromeos == 0)', {
- 'sources': [
- 'common/gpu/x_util.h',
- ],
- }],
['enable_plugins==1', {
'dependencies': [
'../ppapi/ppapi_internal.gyp:ppapi_shared',
@@ -791,7 +704,6 @@
'common/pepper_renderer_instance_data.h',
'common/plugin_list.cc',
'common/plugin_list.h',
- 'common/plugin_list_posix.cc',
'common/sandbox_util.cc',
'public/common/pepper_plugin_info.cc',
'public/common/pepper_plugin_info.h',
@@ -881,18 +793,16 @@
['chromeos==1', {
'sources': [
'common/gpu/media/accelerated_video_decoder.h',
- 'common/gpu/media/gpu_arc_video_service.cc',
- 'common/gpu/media/gpu_arc_video_service.h',
'common/gpu/media/h264_decoder.cc',
'common/gpu/media/h264_decoder.h',
'common/gpu/media/h264_dpb.cc',
'common/gpu/media/h264_dpb.h',
'common/gpu/media/vp8_decoder.cc',
'common/gpu/media/vp8_decoder.h',
- 'common/gpu/media/vp9_decoder.cc',
- 'common/gpu/media/vp9_decoder.h',
'common/gpu/media/vp8_picture.cc',
'common/gpu/media/vp8_picture.h',
+ 'common/gpu/media/vp9_decoder.cc',
+ 'common/gpu/media/vp9_decoder.h',
'common/gpu/media/vp9_picture.cc',
'common/gpu/media/vp9_picture.h',
],
@@ -1057,30 +967,6 @@
'<(DEPTH)/third_party/khronos',
],
}],
- ['OS=="win" and directxsdk_exists=="True"', {
- 'actions': [
- {
- 'action_name': 'extract_xinput',
- 'variables': {
- 'input': 'APR2007_xinput_<(winsdk_arch).cab',
- 'output': 'xinput1_3.dll',
- },
- 'inputs': [
- '../third_party/directxsdk/files/Redist/<(input)',
- ],
- 'outputs': [
- '<(PRODUCT_DIR)/<(output)',
- ],
- 'action': [
- 'python',
- '../build/extract_from_cab.py',
- '..\\third_party\\directxsdk\\files\\Redist\\<(input)',
- '<(output)',
- '<(PRODUCT_DIR)',
- ],
- },
- ]
- }],
['use_seccomp_bpf==0', {
'sources!': [
'common/sandbox_linux/android/sandbox_bpf_base_policy_android.cc',
@@ -1105,19 +991,14 @@
'dependencies': [
'../ui/ozone/ozone.gyp:ozone',
'../ui/ozone/ozone.gyp:ozone_base',
- '../ui/ozone/ozone.gyp:vgem_map',
],
'sources!': [
- 'common/gpu/client/gpu_memory_buffer_impl_linux.cc',
'common/gpu/gpu_memory_buffer_factory_linux.cc',
],
}, { # use_ozone!=1
'sources!': [
'common/cursors/webcursor_ozone.cc',
'common/font_list_ozone.cc',
- 'common/gpu/client/gpu_memory_buffer_impl_ozone.cc',
- 'common/gpu/client/gpu_memory_buffer_impl_ozone_native_pixmap.cc',
- 'common/gpu/client/gpu_memory_buffer_impl_ozone_native_pixmap.h',
'common/gpu/gpu_memory_buffer_factory_ozone.cc',
'common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.cc',
'common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap.h',
diff --git a/chromium/content/content_common_mojo_bindings.gyp b/chromium/content/content_common_mojo_bindings.gyp
index f82059615ef..8063d23cf4f 100644
--- a/chromium/content/content_common_mojo_bindings.gyp
+++ b/chromium/content/content_common_mojo_bindings.gyp
@@ -9,43 +9,53 @@
'target_name': 'content_common_mojo_bindings_mojom',
'type': 'none',
'variables': {
+ 'mojom_extra_generator_args': [
+ '--typemap', '<(DEPTH)/url/mojo/origin.typemap',
+ '--typemap', '<(DEPTH)/url/mojo/gurl.typemap',
+ ],
'mojom_files': [
# NOTE: Sources duplicated in //content/common/BUILD.gn:mojo_bindings.
'common/application_setup.mojom',
'common/background_sync_service.mojom',
- 'common/geolocation_service.mojom',
'common/image_downloader/image_downloader.mojom',
- 'common/permission_service.mojom',
+ 'common/leveldb_wrapper.mojom',
'common/presentation/presentation_service.mojom',
'common/process_control.mojom',
'common/render_frame_setup.mojom',
- 'common/service_port_service.mojom',
'common/service_worker/embedded_worker_setup.mojom',
+ 'common/storage_partition_service.mojom',
'common/vr_service.mojom',
'common/wake_lock_service.mojom',
# NOTE: Sources duplicated in
# //content/public/common/BUILD.gn:mojo_bindings.
'public/common/background_sync.mojom',
- 'public/common/mojo_geoposition.mojom',
- 'public/common/permission_status.mojom',
'public/common/service_worker_event_status.mojom',
],
},
- 'includes': [ '../third_party/mojo/mojom_bindings_generator_explicit.gypi' ],
+ 'dependencies': [
+ '../components/leveldb/leveldb.gyp:leveldb_bindings_mojom',
+ '../mojo/mojo_base.gyp:mojo_application_bindings',
+ '../mojo/mojo_public.gyp:mojo_cpp_bindings',
+ '../skia/skia.gyp:skia_mojo',
+ '../third_party/WebKit/public/blink.gyp:mojo_bindings',
+ '../ui/mojo/geometry/mojo_bindings.gyp:mojo_geometry_bindings',
+ '../url/url.gyp:url_interfaces_mojom',
+ ],
+ 'export_dependent_settings': [
+ '../url/url.gyp:url_interfaces_mojom',
+ ],
+ 'includes': [ '../mojo/mojom_bindings_generator_explicit.gypi' ],
},
{
'target_name': 'content_common_mojo_bindings',
'type': 'static_library',
- 'variables': { 'enable_wexit_time_destructors': 1, },
+ 'variables': {
+ 'enable_wexit_time_destructors': 1,
+ },
'dependencies': [
'content_common_mojo_bindings_mojom',
- '../mojo/mojo_base.gyp:mojo_application_bindings',
- '../mojo/mojo_base.gyp:mojo_environment_chromium',
- '../skia/skia.gyp:skia_mojo',
- '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
- '../ui/mojo/geometry/mojo_bindings.gyp:mojo_geometry_bindings',
- ]
+ ],
},
]
}
diff --git a/chromium/content/content_gpu.gypi b/chromium/content/content_gpu.gypi
index 5516ed441a5..57baf47c0c5 100644
--- a/chromium/content/content_gpu.gypi
+++ b/chromium/content/content_gpu.gypi
@@ -5,8 +5,12 @@
{
'dependencies': [
'../base/base.gyp:base',
+ '../gpu/gpu.gyp:command_buffer_traits',
+ '../gpu/gpu.gyp:gpu',
+ '../gpu/gpu.gyp:gpu_ipc_service',
'../skia/skia.gyp:skia',
'../ui/gl/gl.gyp:gl',
+ 'content_common_mojo_bindings.gyp:content_common_mojo_bindings',
],
'sources': [
'gpu/gpu_child_thread.cc',
@@ -20,6 +24,9 @@
'gpu/gpu_watchdog_thread.h',
'gpu/in_process_gpu_thread.cc',
'gpu/in_process_gpu_thread.h',
+ 'public/gpu/content_gpu_client.h',
+ 'public/gpu/gpu_video_decode_accelerator_factory.cc',
+ 'public/gpu/gpu_video_decode_accelerator_factory.h',
],
'include_dirs': [
'..',
diff --git a/chromium/content/content_jni.gypi b/chromium/content/content_jni.gypi
index 958e58ce91f..2f1ccf829ff 100644
--- a/chromium/content/content_jni.gypi
+++ b/chromium/content/content_jni.gypi
@@ -27,7 +27,7 @@
'public/android/java/src/org/chromium/content/browser/input/PopupTouchHandleDrawable.java',
'public/android/java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java',
'public/android/java/src/org/chromium/content/browser/LocationProviderAdapter.java',
- 'public/android/java/src/org/chromium/content/browser/MediaSession.java',
+ 'public/android/java/src/org/chromium/content/browser/MediaSessionDelegate.java',
'public/android/java/src/org/chromium/content/browser/MediaResourceGetter.java',
'public/android/java/src/org/chromium/content/browser/MediaThrottler.java',
'public/android/java/src/org/chromium/content/browser/MotionEventSynthesizer.java',
@@ -42,6 +42,7 @@
'public/android/java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java',
'public/android/java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java',
'public/android/java/src/org/chromium/content_public/browser/LoadUrlParams.java',
+ 'public/android/java/src/org/chromium/content_public/common/MediaMetadata.java',
],
'variables': {
'jni_gen_package': 'content',
diff --git a/chromium/content/content_plugin.gypi b/chromium/content/content_plugin.gypi
deleted file mode 100644
index 5d3ca951d20..00000000000
--- a/chromium/content/content_plugin.gypi
+++ /dev/null
@@ -1,46 +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.
-
-{
- 'conditions': [
- ['enable_plugins==1 and OS!="linux"', {
- 'dependencies': [
- '../skia/skia.gyp:skia',
- '../third_party/WebKit/public/blink.gyp:blink',
- '../third_party/npapi/npapi.gyp:npapi',
- ],
- 'include_dirs': [
- '<(INTERMEDIATE_DIR)',
- ],
- 'sources': [
- # All .cc, .h, .m, and .mm files under plugins except for tests and
- # mocks.
- 'plugin/plugin_channel.cc',
- 'plugin/plugin_channel.h',
- 'plugin/plugin_interpose_util_mac.h',
- 'plugin/plugin_interpose_util_mac.mm',
- 'plugin/plugin_main.cc',
- 'plugin/plugin_main_mac.mm',
- 'plugin/plugin_thread.cc',
- 'plugin/plugin_thread.h',
- 'plugin/webplugin_accelerated_surface_proxy_mac.cc',
- 'plugin/webplugin_accelerated_surface_proxy_mac.h',
- 'plugin/webplugin_delegate_stub.cc',
- 'plugin/webplugin_delegate_stub.h',
- 'plugin/webplugin_proxy.cc',
- 'plugin/webplugin_proxy.h',
- 'public/plugin/content_plugin_client.h',
- ],
- # These are layered in conditionals in the event other platforms
- # end up using this module as well.
- 'conditions': [
- ['OS=="win"', {
- 'include_dirs': [
- '<(DEPTH)/third_party/wtl/include',
- ],
- }],
- ],
- }],
- ],
-}
diff --git a/chromium/content/content_ppapi_plugin.gypi b/chromium/content/content_ppapi_plugin.gypi
index 89c200f0d3b..4e4ccd9b4b9 100644
--- a/chromium/content/content_ppapi_plugin.gypi
+++ b/chromium/content/content_ppapi_plugin.gypi
@@ -7,6 +7,7 @@
['enable_plugins==1', {
'dependencies': [
'../base/base.gyp:base',
+ '../gin/gin.gyp:gin',
'../ppapi/ppapi_internal.gyp:ppapi_ipc',
'../ui/base/ui_base.gyp:ui_base',
'../ui/gfx/gfx.gyp:gfx',
diff --git a/chromium/content/content_renderer.gypi b/chromium/content/content_renderer.gypi
index c0f6449f5a5..d31c8baa2e0 100644
--- a/chromium/content/content_renderer.gypi
+++ b/chromium/content/content_renderer.gypi
@@ -9,35 +9,33 @@
'../cc/cc.gyp:cc',
'../cc/cc.gyp:cc_proto',
'../cc/blink/cc_blink.gyp:cc_blink',
- '../components/components.gyp:startup_metric_utils_common',
- '../components/components.gyp:webusb',
'../components/scheduler/scheduler.gyp:scheduler',
'../components/url_formatter/url_formatter.gyp:url_formatter',
'../device/battery/battery.gyp:device_battery',
'../device/battery/battery.gyp:device_battery_mojo_bindings',
- '../device/devices_app/devices_app.gyp:device_usb_mojo_bindings_lib',
+ '../device/usb/usb.gyp:device_usb_mojo_bindings',
'../device/vibration/vibration.gyp:device_vibration',
'../device/vibration/vibration.gyp:device_vibration_mojo_bindings',
'../gin/gin.gyp:gin',
'../gpu/gpu.gyp:gpu',
+ '../ipc/ipc.gyp:ipc',
'../jingle/jingle.gyp:jingle_glue',
'../media/blink/media_blink.gyp:media_blink',
'../media/media.gyp:media',
'../mojo/mojo_base.gyp:mojo_application_bindings',
- '../mojo/mojo_base.gyp:mojo_environment_chromium',
'../mojo/mojo_base.gyp:mojo_geometry_lib',
'../mojo/mojo_base.gyp:mojo_url_type_converters',
+ '../mojo/mojo_edk.gyp:mojo_js_lib',
'../net/net.gyp:net',
'../skia/skia.gyp:skia',
'../skia/skia.gyp:skia_mojo',
'../storage/storage_common.gyp:storage_common',
'../third_party/WebKit/public/blink.gyp:blink',
+ '../third_party/boringssl/boringssl.gyp:boringssl',
'../third_party/icu/icu.gyp:icui18n',
'../third_party/icu/icu.gyp:icuuc',
'../third_party/libjingle/libjingle.gyp:libjingle',
'../third_party/libyuv/libyuv.gyp:libyuv',
- '../third_party/mojo/mojo_edk.gyp:mojo_js_lib',
- '../third_party/npapi/npapi.gyp:npapi',
'../third_party/widevine/cdm/widevine_cdm.gyp:widevine_cdm_version_h',
'../ui/accessibility/accessibility.gyp:accessibility',
'../ui/events/blink/events_blink.gyp:events_blink',
@@ -46,6 +44,7 @@
'../ui/gfx/gfx.gyp:gfx_geometry',
'../ui/native_theme/native_theme.gyp:native_theme',
'../ui/surface/surface.gyp:surface',
+ '../url/ipc/url_ipc.gyp:url_ipc',
'../v8/tools/gyp/v8.gyp:v8',
'content_common_mojo_bindings.gyp:content_common_mojo_bindings',
],
@@ -67,6 +66,9 @@
'public/renderer/document_state.cc',
'public/renderer/document_state.h',
'public/renderer/media_stream_audio_renderer.h',
+ 'public/renderer/media_stream_audio_sink.cc',
+ 'public/renderer/media_stream_audio_sink.h',
+ 'public/renderer/media_stream_sink.h',
'public/renderer/navigation_state.cc',
'public/renderer/navigation_state.h',
'public/renderer/pepper_plugin_instance.h',
@@ -123,8 +125,6 @@
'renderer/android/synchronous_compositor_registry.h',
'renderer/background_sync/background_sync_client_impl.cc',
'renderer/background_sync/background_sync_client_impl.h',
- 'renderer/battery_status/battery_status_dispatcher.cc',
- 'renderer/battery_status/battery_status_dispatcher.h',
'renderer/bluetooth/bluetooth_dispatcher.cc',
'renderer/bluetooth/bluetooth_dispatcher.h',
'renderer/bluetooth/bluetooth_message_filter.cc',
@@ -167,6 +167,8 @@
'renderer/devtools/devtools_cpu_throttler.cc',
'renderer/devtools/devtools_cpu_throttler.h',
'renderer/devtools/lock_free_circular_queue.h',
+ 'renderer/devtools/render_widget_screen_metrics_emulator.cc',
+ 'renderer/devtools/render_widget_screen_metrics_emulator.h',
'renderer/devtools/v8_sampling_profiler.cc',
'renderer/devtools/v8_sampling_profiler.h',
'renderer/disambiguation_popup_helper.cc',
@@ -178,6 +180,14 @@
'renderer/dom_storage/dom_storage_dispatcher.cc',
'renderer/dom_storage/dom_storage_dispatcher.h',
'renderer/dom_storage/dom_storage_proxy.h',
+ 'renderer/dom_storage/local_storage_area.cc',
+ 'renderer/dom_storage/local_storage_area.h',
+ 'renderer/dom_storage/local_storage_cached_area.cc',
+ 'renderer/dom_storage/local_storage_cached_area.h',
+ 'renderer/dom_storage/local_storage_cached_areas.cc',
+ 'renderer/dom_storage/local_storage_cached_areas.h',
+ 'renderer/dom_storage/local_storage_namespace.cc',
+ 'renderer/dom_storage/local_storage_namespace.h',
'renderer/dom_storage/webstoragearea_impl.cc',
'renderer/dom_storage/webstoragearea_impl.h',
'renderer/dom_storage/webstoragenamespace_impl.cc',
@@ -192,6 +202,8 @@
'renderer/fetchers/resource_fetcher_impl.h',
'renderer/fetchers/web_url_loader_client_impl.cc',
'renderer/fetchers/web_url_loader_client_impl.h',
+ 'renderer/frame_blame_context.cc',
+ 'renderer/frame_blame_context.h',
'renderer/gamepad_shared_memory_reader.cc',
'renderer/gamepad_shared_memory_reader.h',
'renderer/geolocation_dispatcher.cc',
@@ -215,6 +227,7 @@
'renderer/gpu/queue_message_swap_promise.h',
'renderer/gpu/render_widget_compositor.cc',
'renderer/gpu/render_widget_compositor.h',
+ 'renderer/gpu/render_widget_compositor_delegate.h',
'renderer/gpu/stream_texture_host_android.cc',
'renderer/gpu/stream_texture_host_android.h',
'renderer/history_controller.cc',
@@ -238,6 +251,8 @@
'renderer/input/input_handler_manager_client.h',
'renderer/input/input_handler_wrapper.cc',
'renderer/input/input_handler_wrapper.h',
+ 'renderer/input/main_thread_event_queue.cc',
+ 'renderer/input/main_thread_event_queue.h',
'renderer/input/main_thread_input_event_filter.cc',
'renderer/input/main_thread_input_event_filter.h',
'renderer/input/render_widget_input_handler.cc',
@@ -271,6 +286,8 @@
'renderer/media/android/renderer_media_player_manager.h',
'renderer/media/android/renderer_media_session_manager.cc',
'renderer/media/android/renderer_media_session_manager.h',
+ 'renderer/media/android/renderer_surface_view_manager.cc',
+ 'renderer/media/android/renderer_surface_view_manager.h',
'renderer/media/android/stream_texture_factory.h',
'renderer/media/android/stream_texture_factory_impl.cc',
'renderer/media/android/stream_texture_factory_impl.h',
@@ -299,10 +316,6 @@
'renderer/media/cdm/render_cdm_factory.h',
'renderer/media/media_permission_dispatcher.cc',
'renderer/media/media_permission_dispatcher.h',
- 'renderer/media/media_permission_dispatcher_impl.cc',
- 'renderer/media/media_permission_dispatcher_impl.h',
- 'renderer/media/media_permission_dispatcher_proxy.cc',
- 'renderer/media/media_permission_dispatcher_proxy.h',
'renderer/media/media_stream_audio_level_calculator.cc',
'renderer/media/media_stream_audio_level_calculator.h',
'renderer/media/media_stream_audio_track.cc',
@@ -330,6 +343,8 @@
'renderer/media/renderer_webmediaplayer_delegate.h',
'renderer/media/renderer_webmidiaccessor_impl.cc',
'renderer/media/renderer_webmidiaccessor_impl.h',
+ 'renderer/media/track_audio_renderer.cc',
+ 'renderer/media/track_audio_renderer.h',
'renderer/media/video_capture_impl.cc',
'renderer/media/video_capture_impl.h',
'renderer/media/video_capture_impl_manager.cc',
@@ -340,10 +355,10 @@
'renderer/media/webmediaplayer_ms.h',
'renderer/media/webmediaplayer_ms_compositor.cc',
'renderer/media/webmediaplayer_ms_compositor.h',
- 'renderer/memory_benchmarking_extension.cc',
- 'renderer/memory_benchmarking_extension.h',
'renderer/menu_item_builder.cc',
'renderer/menu_item_builder.h',
+ 'renderer/mojo/blink_service_registry_impl.cc',
+ 'renderer/mojo/blink_service_registry_impl.h',
'renderer/mojo/service_registry_js_wrapper.cc',
'renderer/mojo/service_registry_js_wrapper.h',
'renderer/mojo_bindings_controller.cc',
@@ -360,6 +375,8 @@
'renderer/net_info_helper.h',
'renderer/notification_permission_dispatcher.cc',
'renderer/notification_permission_dispatcher.h',
+ 'renderer/origin_trials/web_trial_token_validator_impl.cc',
+ 'renderer/origin_trials/web_trial_token_validator_impl.h',
'renderer/peripheral_content_heuristic.cc',
'renderer/peripheral_content_heuristic.h',
'renderer/presentation/presentation_connection_client.cc',
@@ -390,6 +407,7 @@
'renderer/render_widget.h',
'renderer/render_widget_fullscreen.cc',
'renderer/render_widget_fullscreen.h',
+ 'renderer/render_widget_owner_delegate.h',
'renderer/renderer_blink_platform_impl.cc',
'renderer/renderer_blink_platform_impl.h',
'renderer/renderer_clipboard_delegate.cc',
@@ -448,6 +466,8 @@
'renderer/text_input_client_observer.h',
'renderer/theme_helper_mac.h',
'renderer/theme_helper_mac.mm',
+ 'renderer/top_level_blame_context.cc',
+ 'renderer/top_level_blame_context.h',
'renderer/usb/type_converters.cc',
'renderer/usb/type_converters.h',
'renderer/usb/web_usb_client_impl.cc',
@@ -477,12 +497,6 @@
],
# Put WebRTC-related sources in the plugin+WebRTC section below.
'private_renderer_plugin_sources': [
- 'renderer/npapi/plugin_channel_host.cc',
- 'renderer/npapi/plugin_channel_host.h',
- 'renderer/npapi/webplugin_delegate_proxy.cc',
- 'renderer/npapi/webplugin_delegate_proxy.h',
- 'renderer/npapi/webplugin_impl.cc',
- 'renderer/npapi/webplugin_impl.h',
'renderer/pepper/audio_helper.cc',
'renderer/pepper/audio_helper.h',
'renderer/pepper/content_decryptor_delegate.cc',
@@ -616,12 +630,9 @@
'renderer/render_widget_fullscreen_pepper.h',
],
'public_renderer_webrtc_sources': [
- 'public/renderer/media_stream_api.cc',
- 'public/renderer/media_stream_api.h',
- 'public/renderer/media_stream_audio_sink.cc',
- 'public/renderer/media_stream_audio_sink.h',
'public/renderer/media_stream_renderer_factory.h',
- 'public/renderer/media_stream_sink.h',
+ 'public/renderer/media_stream_utils.cc',
+ 'public/renderer/media_stream_utils.h',
'public/renderer/media_stream_video_sink.cc',
'public/renderer/media_stream_video_sink.h',
'public/renderer/webrtc_log_message_delegate.h',
@@ -679,8 +690,6 @@
'renderer/media/rtc_data_channel_handler.h',
'renderer/media/rtc_dtmf_sender_handler.cc',
'renderer/media/rtc_dtmf_sender_handler.h',
- 'renderer/media/rtc_media_constraints.cc',
- 'renderer/media/rtc_media_constraints.h',
'renderer/media/rtc_peer_connection_handler.cc',
'renderer/media/rtc_peer_connection_handler.h',
'renderer/media/rtc_video_decoder.cc',
@@ -734,8 +743,6 @@
'renderer/media/webrtc_audio_renderer.h',
'renderer/media/webrtc_identity_service.cc',
'renderer/media/webrtc_identity_service.h',
- 'renderer/media/webrtc_local_audio_renderer.cc',
- 'renderer/media/webrtc_local_audio_renderer.h',
'renderer/media/webrtc_local_audio_source_provider.cc',
'renderer/media/webrtc_local_audio_source_provider.h',
'renderer/media/webrtc_local_audio_track.cc',
@@ -803,11 +810,6 @@
'renderer/webscrollbarbehavior_impl_mac.mm',
],
}],
- ['OS=="win" and win_use_allocator_shim==1', {
- 'dependencies': [
- '../base/allocator/allocator.gyp:allocator',
- ],
- }],
['OS=="android"', {
'sources': [
'renderer/external_popup_menu.cc',
@@ -838,10 +840,11 @@
['enable_webrtc==1', {
'dependencies': [
'../third_party/libjingle/libjingle.gyp:libjingle_webrtc',
- '../third_party/libjingle/libjingle.gyp:libpeerconnection',
'../third_party/webrtc/modules/modules.gyp:audio_device',
'../third_party/webrtc/modules/modules.gyp:audio_processing',
'../third_party/webrtc/p2p/p2p.gyp:libstunprober',
+ '<(DEPTH)/content/content.gyp:common_features',
+ '<(DEPTH)/content/content.gyp:feature_h264_with_openh264_ffmpeg',
'<(DEPTH)/crypto/crypto.gyp:crypto',
],
'sources': [
diff --git a/chromium/content/content_resources.grd b/chromium/content/content_resources.grd
index 99e1fa75b87..76fc74985e9 100644
--- a/chromium/content/content_resources.grd
+++ b/chromium/content/content_resources.grd
@@ -27,6 +27,9 @@
<include name="IDR_INDEXED_DB_INTERNALS_CSS" file="browser/resources/indexed_db/indexeddb_internals.css" flattenhtml="true" type="BINDATA" />
<include name="IDR_MEDIA_INTERNALS_HTML" file="browser/resources/media/media_internals.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
<include name="IDR_MEDIA_INTERNALS_JS" file="browser/resources/media/media_internals.js" flattenhtml="true" type="BINDATA" />
+ <include name="IDR_MOJO_CATALOG_MANIFEST" file="../mojo/services/catalog/manifest.json" type="BINDATA" />
+ <include name="IDR_MOJO_CONTENT_BROWSER_MANIFEST" file="${root_out_dir}/content_browser_manifest.json" use_base_dir="false" type="BINDATA" />
+ <include name="IDR_MOJO_CONTENT_RENDERER_MANIFEST" file="${root_out_dir}/content_renderer_manifest.json" use_base_dir="false" type="BINDATA" />
<include name="IDR_NETWORK_ERROR_LISTING_HTML" file="browser/resources/net/network_errors_listing.html" flattenhtml="true" allowexternalscript="true" type="BINDATA" />
<include name="IDR_NETWORK_ERROR_LISTING_JS" file="browser/resources/net/network_errors_listing.js" flattenhtml="true" type="BINDATA" />
<include name="IDR_NETWORK_ERROR_LISTING_CSS" file="browser/resources/net/network_errors_listing.css" flattenhtml="true" type="BINDATA" />
diff --git a/chromium/content/content_resources.gypi b/chromium/content/content_resources.gypi
index d61642f7d1e..01d3d03dc88 100644
--- a/chromium/content/content_resources.gypi
+++ b/chromium/content/content_resources.gypi
@@ -16,6 +16,9 @@
'action_name': 'generate_content_resources',
'variables': {
'grit_grd_file': 'content_resources.grd',
+ 'grit_additional_defines': [
+ '-E', 'root_out_dir=<(PRODUCT_DIR)',
+ ],
},
'includes': [ '../build/grit_action.gypi' ],
},
@@ -28,6 +31,11 @@
],
},
],
+ 'dependencies': [
+ '<(DEPTH)/mojo/mojo_shell.gyp:mojo_catalog_manifest',
+ 'content_app_browser_manifest',
+ 'content_app_renderer_manifest',
+ ],
},
],
}
diff --git a/chromium/content/content_shell.gypi b/chromium/content/content_shell.gypi
index 35e849bed91..6d15a673aa3 100644
--- a/chromium/content/content_shell.gypi
+++ b/chromium/content/content_shell.gypi
@@ -6,13 +6,6 @@
'variables': {
'content_shell_product_name': 'Content Shell',
'content_shell_version': '99.77.34.5',
- 'conditions': [
- ['OS=="linux"', {
- 'use_custom_freetype%': 1,
- }, {
- 'use_custom_freetype%': 0,
- }],
- ],
},
'targets': [
{
@@ -32,14 +25,13 @@
'content.gyp:content_browser',
'content.gyp:content_common',
'content.gyp:content_gpu',
- 'content.gyp:content_plugin',
'content.gyp:content_ppapi_plugin',
'content.gyp:content_renderer',
'content.gyp:content_resources',
'content.gyp:content_utility',
'content_shell_resources',
+ 'content_shell_mojo_bindings',
'content_test_mojo_bindings',
- 'copy_test_netscape_plugin',
'layouttest_support_content',
'../base/base.gyp:base',
'../base/base.gyp:base_static',
@@ -62,6 +54,7 @@
'../media/media.gyp:media',
'../net/net.gyp:net',
'../net/net.gyp:net_resources',
+ '../ppapi/ppapi_internal.gyp:blink_deprecated_test_plugin',
'../ppapi/ppapi_internal.gyp:blink_test_plugin',
'../skia/skia.gyp:skia',
'../storage/storage_browser.gyp:storage',
@@ -75,8 +68,10 @@
'../ui/gfx/gfx.gyp:gfx',
'../ui/gfx/gfx.gyp:gfx_geometry',
'../ui/gfx/ipc/gfx_ipc.gyp:gfx_ipc',
+ '../ui/gfx/ipc/skia/gfx_ipc_skia.gyp:gfx_ipc_skia',
'../ui/gl/gl.gyp:gl',
'../url/url.gyp:url_lib',
+ '../url/ipc/url_ipc.gyp:url_ipc',
'../v8/tools/gyp/v8.gyp:v8',
],
'include_dirs': [
@@ -89,6 +84,11 @@
'shell/android/shell_jni_registrar.h',
'shell/android/shell_manager.cc',
'shell/android/shell_manager.h',
+ 'shell/app/blink_test_platform_support.h',
+ 'shell/app/blink_test_platform_support_android.cc',
+ 'shell/app/blink_test_platform_support_linux.cc',
+ 'shell/app/blink_test_platform_support_mac.mm',
+ 'shell/app/blink_test_platform_support_win.cc',
'shell/app/paths_mac.h',
'shell/app/paths_mac.mm',
'shell/app/shell_crash_reporter_client.cc',
@@ -97,10 +97,12 @@
'shell/app/shell_main_delegate.h',
'shell/app/shell_main_delegate_mac.h',
'shell/app/shell_main_delegate_mac.mm',
- 'shell/browser/blink_test_controller.cc',
- 'shell/browser/blink_test_controller.h',
+ 'shell/browser/layout_test/blink_test_controller.cc',
+ 'shell/browser/layout_test/blink_test_controller.h',
'shell/browser/layout_test/layout_test_android.cc',
'shell/browser/layout_test/layout_test_android.h',
+ 'shell/browser/layout_test/layout_test_bluetooth_fake_adapter_setter_impl.cc',
+ 'shell/browser/layout_test/layout_test_bluetooth_fake_adapter_setter_impl.h',
'shell/browser/layout_test/layout_test_bluetooth_adapter_provider.cc',
'shell/browser/layout_test/layout_test_bluetooth_adapter_provider.h',
'shell/browser/layout_test/layout_test_bluetooth_chooser_factory.cc',
@@ -121,8 +123,6 @@
'shell/browser/layout_test/layout_test_javascript_dialog_manager.h',
'shell/browser/layout_test/layout_test_message_filter.cc',
'shell/browser/layout_test/layout_test_message_filter.h',
- 'shell/browser/layout_test/layout_test_navigator_connect_service_factory.cc',
- 'shell/browser/layout_test/layout_test_navigator_connect_service_factory.h',
'shell/browser/layout_test/layout_test_notification_manager.cc',
'shell/browser/layout_test/layout_test_notification_manager.h',
'shell/browser/layout_test/layout_test_permission_manager.cc',
@@ -133,8 +133,10 @@
'shell/browser/layout_test/layout_test_resource_dispatcher_host_delegate.h',
'shell/browser/layout_test/layout_test_url_request_context_getter.cc',
'shell/browser/layout_test/layout_test_url_request_context_getter.h',
- 'shell/browser/notify_done_forwarder.cc',
- 'shell/browser/notify_done_forwarder.h',
+ 'shell/browser/layout_test/notify_done_forwarder.cc',
+ 'shell/browser/layout_test/notify_done_forwarder.h',
+ 'shell/browser/layout_test/test_info_extractor.cc',
+ 'shell/browser/layout_test/test_info_extractor.h',
'shell/browser/shell.cc',
'shell/browser/shell.h',
'shell/browser/shell_access_token_store.cc',
@@ -193,8 +195,12 @@
'shell/browser/shell_web_contents_view_delegate_creator.h',
'shell/browser/shell_web_contents_view_delegate_mac.mm',
'shell/browser/shell_web_contents_view_delegate_win.cc',
+ 'shell/common/layout_test/layout_test_content_client.cc',
+ 'shell/common/layout_test/layout_test_content_client.h',
'shell/common/layout_test/layout_test_messages.cc',
'shell/common/layout_test/layout_test_messages.h',
+ 'shell/common/layout_test/layout_test_switches.cc',
+ 'shell/common/layout_test/layout_test_switches.h',
'shell/common/leak_detection_result.h',
'shell/common/shell_content_client.cc',
'shell/common/shell_content_client.h',
@@ -235,11 +241,6 @@
},
},
'conditions': [
- ['OS=="win" and win_use_allocator_shim==1', {
- 'dependencies': [
- '../base/allocator/allocator.gyp:allocator',
- ],
- }],
['OS=="win"', {
'resource_include_dirs': [
'<(SHARED_INTERMEDIATE_DIR)/content/app/strings',
@@ -262,6 +263,7 @@
['OS=="linux"', {
'dependencies': [
'../build/linux/system.gyp:fontconfig',
+ '../third_party/freetype2/freetype2.gyp:freetype2',
],
}],
['use_x11 == 1', {
@@ -281,10 +283,9 @@
'../components/components.gyp:breakpad_host',
],
}],
- ['(OS=="linux" or OS=="android") and use_allocator!="none"', {
- 'dependencies': [
- # This is needed by content/app/content_main_runner.cc
- '../base/allocator/allocator.gyp:allocator',
+ ['debug_devtools==1', {
+ 'defines': [
+ 'DEBUG_DEVTOOLS=1',
],
}],
['use_aura==1', {
@@ -324,11 +325,6 @@
'../ui/wm/wm.gyp:wm_test_support',
],
}], # chromeos==1
- ['use_custom_freetype==1', {
- 'dependencies': [
- '../third_party/freetype2/freetype2.gyp:freetype2',
- ],
- }],
['enable_plugins==0', {
'sources!': [
'shell/browser/shell_plugin_service_filter.cc',
@@ -470,11 +466,6 @@
},
},
'conditions': [
- ['OS=="win" and win_use_allocator_shim==1', {
- 'dependencies': [
- '../base/allocator/allocator.gyp:allocator',
- ],
- }],
['OS=="win"', {
'sources': [
'shell/app/shell.rc',
@@ -488,19 +479,21 @@
},
},
},
- }], # OS=="win"
- ['OS == "win"', {
'dependencies': [
'../sandbox/sandbox.gyp:sandbox',
],
+ 'conditions': [
+ ['win_console_app==1', {
+ 'defines': ['WIN_CONSOLE_APP'],
+ }, { # else win_console_app==0
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'SubSystem': '2', # Set /SUBSYSTEM:WINDOWS
+ },
+ },
+ }],
+ ],
}], # OS=="win"
- ['OS=="win" and asan==0', {
- 'msvs_settings': {
- 'VCLinkerTool': {
- 'SubSystem': '2', # Set /SUBSYSTEM:WINDOWS
- },
- },
- }], # OS=="win" and asan==0
['OS=="mac"', {
'product_name': '<(content_shell_product_name)',
'dependencies!': [
@@ -554,104 +547,25 @@
],
},
{
- 'target_name': 'test_netscape_plugin',
- 'conditions': [
- ['OS != "win" and OS != "mac"', {
- 'type': 'none',
- }, { # OS=="win" or OS=="mac"
- 'type': 'loadable_module',
- 'sources': [
- 'shell/tools/plugin/PluginObject.cpp',
- 'shell/tools/plugin/PluginObject.h',
- 'shell/tools/plugin/PluginObjectMac.mm',
- 'shell/tools/plugin/PluginTest.cpp',
- 'shell/tools/plugin/PluginTest.h',
- 'shell/tools/plugin/TestObject.cpp',
- 'shell/tools/plugin/Tests/EvaluateJSAfterRemovingPluginElement.cpp',
- 'shell/tools/plugin/Tests/FormValue.cpp',
- 'shell/tools/plugin/Tests/GetUserAgentWithNullNPPFromNPPNew.cpp',
- 'shell/tools/plugin/Tests/LeakWindowScriptableObject.cpp',
- 'shell/tools/plugin/Tests/LogNPPSetWindow.cpp',
- 'shell/tools/plugin/Tests/NPDeallocateCalledBeforeNPShutdown.cpp',
- 'shell/tools/plugin/Tests/NPPNewFails.cpp',
- 'shell/tools/plugin/Tests/NPRuntimeCallsWithNullNPP.cpp',
- 'shell/tools/plugin/Tests/NPRuntimeObjectFromDestroyedPlugin.cpp',
- 'shell/tools/plugin/Tests/NPRuntimeRemoveProperty.cpp',
- 'shell/tools/plugin/Tests/NullNPPGetValuePointer.cpp',
- 'shell/tools/plugin/Tests/PassDifferentNPPStruct.cpp',
- 'shell/tools/plugin/Tests/PluginScriptableNPObjectInvokeDefault.cpp',
- 'shell/tools/plugin/Tests/PluginScriptableObjectOverridesAllProperties.cpp',
- 'shell/tools/plugin/main.cpp',
- 'shell/tools/plugin/test_object.h',
- ],
- 'include_dirs': [
- '<(DEPTH)',
- '<(DEPTH)/content/shell/tools/plugin/',
- ],
- 'dependencies': [
- '../base/base.gyp:base',
- '../third_party/npapi/npapi.gyp:npapi',
- ],
- 'conditions': [
- ['OS=="mac"', {
- 'mac_bundle': 1,
- 'product_extension': 'plugin',
- 'link_settings': {
- 'libraries': [
- '$(SDKROOT)/System/Library/Frameworks/Carbon.framework',
- '$(SDKROOT)/System/Library/Frameworks/Cocoa.framework',
- '$(SDKROOT)/System/Library/Frameworks/QuartzCore.framework',
- ]
- },
- 'xcode_settings': {
- 'GCC_SYMBOLS_PRIVATE_EXTERN': 'NO',
- 'INFOPLIST_FILE': 'shell/tools/plugin/mac/Info.plist',
- },
- }],
- ['OS=="win"', {
- 'conditions': [
- ['MSVS_VERSION < "2015"', {
- 'defines': [
- # This seems like a hack, but this is what Safari Win does.
- # Luckily it is no longer needed/allowed with VS 2015.
- 'snprintf=_snprintf',
- ],
- }],
- ],
- 'sources': [
- 'shell/tools/plugin/win/TestNetscapePlugin.def',
- 'shell/tools/plugin/win/TestNetscapePlugin.rc',
- ],
- # The .rc file requires that the name of the dll is np_test_netscape_plugin.dll.
- 'product_name': 'np_test_netscape_plugin',
- # Disable c4267 warnings until we fix size_t to int truncations.
- 'msvs_disabled_warnings': [ 4267, ],
- }],
- ],
- }],
- ],
+ 'target_name': 'content_shell_mojo_bindings_mojom',
+ 'type': 'none',
+ 'variables': {
+ 'mojom_files': [
+ 'shell/common/layout_test/layout_test_bluetooth_fake_adapter_setter.mojom'
+ ],
+ },
+ 'includes': [
+ '../mojo/mojom_bindings_generator_explicit.gypi',
+ ],
},
{
- 'target_name': 'copy_test_netscape_plugin',
- 'type': 'none',
- 'dependencies': [
- 'test_netscape_plugin',
- ],
- 'conditions': [
- ['OS=="win"', {
- 'copies': [{
- 'destination': '<(PRODUCT_DIR)/plugins',
- 'files': ['<(PRODUCT_DIR)/np_test_netscape_plugin.dll'],
- }],
- }],
- ['OS=="mac"', {
- 'copies': [{
- 'destination': '<(PRODUCT_DIR)/plugins/',
- 'files': ['<(PRODUCT_DIR)/test_netscape_plugin.plugin/'],
- }],
- }],
- ],
- }
+ 'target_name': 'content_shell_mojo_bindings',
+ 'type': 'static_library',
+ 'dependencies': [
+ 'content_shell_mojo_bindings_mojom',
+ '../mojo/mojo_public.gyp:mojo_cpp_bindings',
+ ],
+ },
],
'conditions': [
['OS=="mac"', {
@@ -718,6 +632,7 @@
# that corresponds to Content Shell Framework.framework.
'destination': '<(PRODUCT_DIR)/$(CONTENTS_FOLDER_PATH)',
'files': [
+ '<(PRODUCT_DIR)/blink_deprecated_test_plugin.plugin',
'<(PRODUCT_DIR)/blink_test_plugin.plugin',
],
},
@@ -927,7 +842,7 @@
}],
],
},
- 'includes': [
+ 'includes': [
'../build/android/v8_external_startup_data_arch_suffix.gypi',
'../build/java_apk.gypi',
],
diff --git a/chromium/content/content_shell_and_tests.gyp b/chromium/content/content_shell_and_tests.gyp
index b3c3c4c20bf..d331767a075 100644
--- a/chromium/content/content_shell_and_tests.gyp
+++ b/chromium/content/content_shell_and_tests.gyp
@@ -19,14 +19,8 @@
],
},
'includes': [
+ '../build/win_precompile.gypi',
+ 'content_shell.gypi',
'content_tests.gypi',
],
- 'conditions': [
- ['OS != "ios"', {
- 'includes': [
- '../build/win_precompile.gypi',
- 'content_shell.gypi',
- ],
- }],
- ],
}
diff --git a/chromium/content/content_shell_test_apk.isolate b/chromium/content/content_shell_test_apk.isolate
index 46c76580a34..6f27c350f58 100644
--- a/chromium/content/content_shell_test_apk.isolate
+++ b/chromium/content/content_shell_test_apk.isolate
@@ -7,6 +7,7 @@
'variables': {
'files': [
'<(DEPTH)/content/test/data/android/',
+ '<(DEPTH)/content/test/data/media/session/',
'<(DEPTH)/net/data/ssl/certificates/crit-codeSigning-chain.pem',
'<(DEPTH)/net/data/ssl/certificates/eku-test-root.pem',
'<(DEPTH)/net/data/ssl/certificates/invalid_key_usage_cert.der',
diff --git a/chromium/content/content_shell_test_apk_run.isolate b/chromium/content/content_shell_test_apk_run.isolate
index 80624948db1..8c01eb4dd7e 100644
--- a/chromium/content/content_shell_test_apk_run.isolate
+++ b/chromium/content/content_shell_test_apk_run.isolate
@@ -10,8 +10,8 @@
'command': [
'<(PRODUCT_DIR)/bin/run_content_shell_test_apk',
'--enable-platform-mode',
- '-e', 'local', '--apk-under-test',
- '<(PRODUCT_DIR)/apks/ContentShell.apk',
+ '-e', 'local',
+ '--logcat-output-dir', '${ISOLATED_OUTDIR}/logcats',
],
'files': [
'../third_party/proguard/',
diff --git a/chromium/content/content_site_isolation_browsertests.isolate b/chromium/content/content_site_isolation_browsertests.isolate
new file mode 100644
index 00000000000..9fcfd9ac728
--- /dev/null
+++ b/chromium/content/content_site_isolation_browsertests.isolate
@@ -0,0 +1,21 @@
+# Copyright 2015 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+{
+ 'includes': [
+ 'content_browsertests.isolate',
+ ],
+ 'conditions': [
+ ['OS=="linux"', {
+ 'variables': {
+ 'command': [
+ '../testing/test_env.py',
+ '<(PRODUCT_DIR)/content_browsertests<(EXECUTABLE_SUFFIX)',
+ '--test-launcher-bot-mode',
+ '--site-per-process',
+ '--test-launcher-filter-file=../testing/buildbot/filters/site-per-process.content_browsertests.filter',
+ ],
+ },
+ }],
+ ],
+}
diff --git a/chromium/content/content_tests.gypi b/chromium/content/content_tests.gypi
index 2792d423b8e..dfd6ab7584c 100644
--- a/chromium/content/content_tests.gypi
+++ b/chromium/content/content_tests.gypi
@@ -26,11 +26,6 @@
'public/test/async_file_test_helper.h',
'public/test/background_sync_test_util.cc',
'public/test/background_sync_test_util.h',
- 'public/test/browser_test.h',
- 'public/test/browser_test_base.cc',
- 'public/test/browser_test_base.h',
- 'public/test/browser_test_utils.cc',
- 'public/test/browser_test_utils.h',
'public/test/content_test_suite_base.cc',
'public/test/content_test_suite_base.h',
'public/test/download_test_observer.cc',
@@ -63,8 +58,6 @@
'public/test/ppapi_test_utils.h',
'public/test/render_view_test.cc',
'public/test/render_view_test.h',
- 'public/test/render_widget_test.cc',
- 'public/test/render_widget_test.h',
'public/test/sandbox_file_system_test_helper.cc',
'public/test/sandbox_file_system_test_helper.h',
'public/test/test_browser_context.cc',
@@ -116,21 +109,24 @@
'test/content_browser_sanity_checker.h',
'test/content_test_suite.cc',
'test/content_test_suite.h',
- 'test/dwrite_font_fake_sender_win.h',
'test/dwrite_font_fake_sender_win.cc',
+ 'test/dwrite_font_fake_sender_win.h',
'test/fake_compositor_dependencies.cc',
'test/fake_compositor_dependencies.h',
'test/fake_plugin_service.cc',
'test/fake_plugin_service.h',
'test/fake_renderer_scheduler.cc',
'test/fake_renderer_scheduler.h',
- 'test/gpu_memory_buffer_factory_test_template.h',
+ 'test/mock_background_sync_controller.cc',
+ 'test/mock_background_sync_controller.h',
'test/mock_google_streaming_server.cc',
'test/mock_google_streaming_server.h',
'test/mock_keyboard.cc',
'test/mock_keyboard.h',
'test/mock_keyboard_driver_win.cc',
'test/mock_keyboard_driver_win.h',
+ 'test/mock_permission_manager.cc',
+ 'test/mock_permission_manager.h',
'test/mock_render_process.cc',
'test/mock_render_process.h',
'test/mock_ssl_host_state_delegate.cc',
@@ -148,6 +144,10 @@
'test/ppapi_unittest.h',
'test/render_thread_impl_browser_test_ipc_helper.cc',
'test/render_thread_impl_browser_test_ipc_helper.h',
+ 'test/test_background_sync_context_impl.cc',
+ 'test/test_background_sync_context_impl.h',
+ 'test/test_background_sync_manager.cc',
+ 'test/test_background_sync_manager.h',
'test/test_blink_web_unit_test_support.cc',
'test/test_blink_web_unit_test_support.h',
'test/test_content_browser_client.cc',
@@ -177,12 +177,6 @@
'test/web_contents_observer_sanity_checker.h',
'test/web_gesture_curve_mock.cc',
'test/web_gesture_curve_mock.h',
- 'test/web_layer_tree_view_impl_for_testing.cc',
- 'test/web_layer_tree_view_impl_for_testing.h',
- 'test/weburl_loader_mock.cc',
- 'test/weburl_loader_mock.h',
- 'test/weburl_loader_mock_factory.cc',
- 'test/weburl_loader_mock_factory.h',
],
'content_browsertests_sources': [
'app/mojo/mojo_browsertest.cc',
@@ -192,6 +186,7 @@
'browser/accessibility/accessibility_event_recorder_win.cc',
'browser/accessibility/accessibility_ipc_error_browsertest.cc',
'browser/accessibility/accessibility_mode_browsertest.cc',
+ 'browser/accessibility/hit_testing_browsertest.cc',
'browser/accessibility/cross_platform_accessibility_browsertest.cc',
'browser/accessibility/dump_accessibility_browsertest_base.cc',
'browser/accessibility/dump_accessibility_browsertest_base.h',
@@ -203,7 +198,6 @@
'browser/background_sync/background_sync_browsertest.cc',
'browser/battery_status/battery_monitor_impl_browsertest.cc',
'browser/battery_status/battery_monitor_integration_browsertest.cc',
- 'browser/bluetooth/bluetooth_allowed_devices_map_unittest.cc',
'browser/bookmarklet_browsertest.cc',
'browser/browser_side_navigation_browsertest.cc',
'browser/child_process_launcher_browsertest.cc',
@@ -223,6 +217,7 @@
'browser/frame_host/frame_tree_browsertest.cc',
'browser/frame_host/interstitial_page_impl_browsertest.cc',
'browser/frame_host/navigation_controller_impl_browsertest.cc',
+ 'browser/frame_host/navigation_handle_impl_browsertest.cc',
'browser/frame_host/render_frame_host_impl_browsertest.cc',
'browser/frame_host/render_frame_host_manager_browsertest.cc',
'browser/frame_host/render_frame_message_filter_browsertest.cc',
@@ -237,17 +232,22 @@
'browser/loader/cross_site_resource_handler_browsertest.cc',
'browser/loader/resource_dispatcher_host_browsertest.cc',
'browser/manifest/manifest_browsertest.cc',
- 'browser/media/android/media_session_browsertest.cc',
'browser/media/encrypted_media_browsertest.cc',
'browser/media/media_browsertest.cc',
'browser/media/media_browsertest.h',
'browser/media/media_canplaytype_browsertest.cc',
'browser/media/media_source_browsertest.cc',
- 'browser/memory/memory_pressure_controller_browsertest.cc',
+ 'browser/media/session/media_session_browsertest.cc',
+ 'browser/media/session/media_session_delegate_default_browsertest.cc',
+ 'browser/media/session/media_session_visibility_browsertest.cc',
+ 'browser/media/session/mock_media_session_observer.cc',
+ 'browser/media/session/mock_media_session_observer.h',
+ 'browser/memory/memory_pressure_controller_impl_browsertest.cc',
'browser/message_port_provider_browsertest.cc',
'browser/mojo_shell_browsertest.cc',
'browser/net_info_browsertest.cc',
'browser/renderer_host/input/composited_scrolling_browsertest.cc',
+ 'browser/renderer_host/input/non_blocking_event_browsertest.cc',
'browser/renderer_host/input/touch_action_browsertest.cc',
'browser/renderer_host/input/touch_input_browsertest.cc',
'browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc',
@@ -262,6 +262,7 @@
'browser/shared_worker/worker_browsertest.cc',
'browser/site_per_process_browsertest.cc',
'browser/site_per_process_browsertest.h',
+ 'browser/top_document_isolation_browsertest.cc',
'browser/tracing/background_tracing_manager_browsertest.cc',
'browser/tracing/memory_tracing_browsertest.cc',
'browser/tracing/tracing_controller_browsertest.cc',
@@ -277,6 +278,7 @@
'renderer/devtools/v8_sampling_profiler_browsertest.cc',
'renderer/gin_browsertest.cc',
'renderer/history_controller_browsertest.cc',
+ 'renderer/media/renderer_webmediaplayer_delegate_browsertest.cc',
'renderer/mouse_lock_dispatcher_browsertest.cc',
'renderer/render_frame_impl_browsertest.cc',
'renderer/render_thread_impl_browsertest.cc',
@@ -292,17 +294,17 @@
],
'content_browsertests_android_sources': [
'browser/accessibility/android_granularity_movement_browsertest.cc',
- 'browser/accessibility/android_hit_testing_browsertest.cc',
+ 'browser/media/session/media_session_delegate_android_browsertest.cc',
'shell/android/browsertests_apk/content_browser_tests_jni_onload.cc',
],
'content_browsertests_webrtc_sources': [
- 'browser/media/webrtc_audio_debug_recordings_browsertest.cc',
- 'browser/media/webrtc_browsertest.cc',
- 'browser/media/webrtc_getusermedia_browsertest.cc',
- 'browser/media/webrtc_internals_browsertest.cc',
- 'browser/media/webrtc_ip_permissions_browsertest.cc',
- 'browser/media/webrtc_media_recorder_browsertest.cc',
- 'browser/media/webrtc_webcam_browsertest.cc',
+ 'browser/media/webrtc/webrtc_audio_debug_recordings_browsertest.cc',
+ 'browser/media/webrtc/webrtc_browsertest.cc',
+ 'browser/media/webrtc/webrtc_getusermedia_browsertest.cc',
+ 'browser/media/webrtc/webrtc_internals_browsertest.cc',
+ 'browser/media/webrtc/webrtc_ip_permissions_browsertest.cc',
+ 'browser/media/webrtc/webrtc_media_recorder_browsertest.cc',
+ 'browser/media/webrtc/webrtc_webcam_browsertest.cc',
'test/webrtc_content_browsertest_base.cc',
'test/webrtc_content_browsertest_base.h',
],
@@ -364,11 +366,13 @@
'browser/appcache/mock_appcache_storage_unittest.cc',
'browser/background_sync/background_sync_manager_unittest.cc',
'browser/background_sync/background_sync_network_observer_unittest.cc',
- 'browser/background_sync/background_sync_power_observer_unittest.cc',
'browser/background_sync/background_sync_service_impl_unittest.cc',
'browser/blob_storage/blob_async_builder_host_unittest.cc',
- 'browser/blob_storage/blob_async_transport_strategy_unittest.cc',
+ 'browser/blob_storage/blob_async_transport_request_builder_unittest.cc',
+ 'browser/blob_storage/blob_dispatcher_host_unittest.cc',
'browser/blob_storage/blob_storage_registry_unittest.cc',
+ 'browser/bluetooth/bluetooth_allowed_devices_map_unittest.cc',
+ 'browser/bluetooth/bluetooth_blacklist_unittest.cc',
'browser/browser_thread_unittest.cc',
'browser/browser_url_handler_impl_unittest.cc',
'browser/byte_stream_unittest.cc',
@@ -391,6 +395,7 @@
'browser/device_sensors/sensor_manager_android_unittest.cc',
'browser/device_sensors/sensor_manager_chromeos_unittest.cc',
'browser/devtools/devtools_manager_unittest.cc',
+ 'browser/devtools/protocol/tracing_handler_unittest.cc',
'browser/devtools/shared_worker_devtools_manager_unittest.cc',
'browser/dom_storage/dom_storage_area_unittest.cc',
'browser/dom_storage/dom_storage_context_impl_unittest.cc',
@@ -503,7 +508,6 @@
'browser/loader/temporary_file_stream_unittest.cc',
'browser/loader/upload_data_stream_builder_unittest.cc',
'browser/mach_broker_mac_unittest.cc',
- 'browser/media/android/media_session_uma_helper_unittest.cc',
'browser/media/audible_metrics_unittest.cc',
'browser/media/audio_stream_monitor_unittest.cc',
'browser/media/capture/audio_mirroring_manager_unittest.cc',
@@ -512,7 +516,9 @@
'browser/media/capture/web_contents_video_capture_device_unittest.cc',
'browser/media/media_internals_unittest.cc',
'browser/media/midi_host_unittest.cc',
- 'browser/media/webrtc_identity_store_unittest.cc',
+ 'browser/media/session/media_session_controller_unittest.cc',
+ 'browser/media/session/media_session_uma_helper_unittest.cc',
+ 'browser/media/webrtc/webrtc_identity_store_unittest.cc',
'browser/net/quota_policy_cookie_store_unittest.cc',
'browser/notification_service_impl_unittest.cc',
'browser/notifications/notification_database_data_unittest.cc',
@@ -538,7 +544,6 @@
'browser/renderer_host/begin_frame_observer_proxy_unittest.cc',
'browser/renderer_host/clipboard_message_filter_unittest.cc',
'browser/renderer_host/dwrite_font_proxy_message_filter_win_unittest.cc',
- 'browser/renderer_host/event_with_latency_info_unittest.cc',
'browser/renderer_host/input/gesture_event_queue_unittest.cc',
'browser/renderer_host/input/input_router_impl_unittest.cc',
'browser/renderer_host/input/mock_input_ack_handler.cc',
@@ -546,6 +551,7 @@
'browser/renderer_host/input/mock_input_router_client.cc',
'browser/renderer_host/input/mock_input_router_client.h',
'browser/renderer_host/input/motion_event_web_unittest.cc',
+ 'browser/renderer_host/input/mouse_wheel_event_queue_unittest.cc',
'browser/renderer_host/input/mouse_wheel_rails_filter_unittest_mac.cc',
'browser/renderer_host/input/render_widget_host_latency_tracker_unittest.cc',
'browser/renderer_host/input/stylus_text_selector_unittest.cc',
@@ -554,9 +560,11 @@
'browser/renderer_host/input/touch_action_filter_unittest.cc',
'browser/renderer_host/input/touch_emulator_unittest.cc',
'browser/renderer_host/input/touch_event_queue_unittest.cc',
+ 'browser/renderer_host/input/web_input_event_builders_android_unittest.cc',
'browser/renderer_host/input/web_input_event_builders_mac_unittest.mm',
'browser/renderer_host/input/web_input_event_unittest.cc',
'browser/renderer_host/input/web_input_event_util_unittest.cc',
+ 'browser/renderer_host/media/audio_input_debug_writer_unittest.cc',
'browser/renderer_host/media/audio_input_device_manager_unittest.cc',
'browser/renderer_host/media/audio_input_sync_writer_unittest.cc',
'browser/renderer_host/media/audio_output_device_enumerator_unittest.cc',
@@ -578,11 +586,13 @@
'browser/renderer_host/render_widget_host_view_mac_unittest.mm',
'browser/renderer_host/text_input_client_mac_unittest.mm',
'browser/renderer_host/web_input_event_aura_unittest.cc',
+ 'browser/renderer_host/websocket_blob_sender_unittest.cc',
'browser/renderer_host/websocket_dispatcher_host_unittest.cc',
'browser/resolve_proxy_msg_helper_unittest.cc',
'browser/service_worker/embedded_worker_instance_unittest.cc',
'browser/service_worker/embedded_worker_test_helper.cc',
'browser/service_worker/embedded_worker_test_helper.h',
+ 'browser/service_worker/link_header_support_unittest.cc',
'browser/service_worker/service_worker_cache_writer_unittest.cc',
'browser/service_worker/service_worker_context_request_handler_unittest.cc',
'browser/service_worker/service_worker_context_unittest.cc',
@@ -609,7 +619,6 @@
'browser/storage_partition_impl_unittest.cc',
'browser/streams/stream_unittest.cc',
'browser/streams/stream_url_request_job_unittest.cc',
- 'browser/system_message_window_win_unittest.cc',
'browser/tracing/background_tracing_config_unittest.cc',
'browser/wake_lock/wake_lock_service_context_unittest.cc',
'browser/web_contents/aura/overscroll_navigation_overlay_unittest.cc',
@@ -631,12 +640,13 @@
'child/blob_storage/blob_transport_controller_unittest.cc',
'child/dwrite_font_proxy/dwrite_font_proxy_win_unittest.cc',
'child/fileapi/webfilewriter_base_unittest.cc',
+ 'child/font_warmup_win_unittest.cc',
'child/indexed_db/indexed_db_dispatcher_unittest.cc',
'child/indexed_db/mock_webidbcallbacks.cc',
'child/indexed_db/mock_webidbcallbacks.h',
'child/indexed_db/webidbcursor_impl_unittest.cc',
- 'child/multipart_response_delegate_unittest.cc',
'child/notifications/notification_data_conversions_unittest.cc',
+ 'child/notifications/pending_notifications_tracker_unittest.cc',
'child/power_monitor_broadcast_source_unittest.cc',
'child/resource_dispatcher_unittest.cc',
'child/service_worker/service_worker_dispatcher_unittest.cc',
@@ -646,7 +656,6 @@
'child/site_isolation_stats_gatherer_unittest.cc',
'child/v8_value_converter_impl_unittest.cc',
'child/web_data_consumer_handle_impl_unittest.cc',
- 'child/web_process_memory_dump_impl_unittest.cc',
'child/web_url_loader_impl_unittest.cc',
'child/worker_thread_registry_unittest.cc',
'common/android/address_parser_unittest.cc',
@@ -659,19 +668,11 @@
'common/database_identifier_unittest.cc',
'common/discardable_shared_memory_heap_unittest.cc',
'common/dom_storage/dom_storage_map_unittest.cc',
- 'common/dwrite_font_platform_win_unittest.cc',
- 'common/experiments/api_key_unittest.cc',
'common/fileapi/file_system_util_unittest.cc',
- 'common/font_warmup_win_unittest.cc',
- 'common/gpu/client/gpu_memory_buffer_impl_shared_memory_unittest.cc',
- 'common/gpu/gpu_channel_manager_unittest.cc',
- 'common/gpu/gpu_channel_test_common.cc',
- 'common/gpu/gpu_channel_test_common.h',
- 'common/gpu/gpu_channel_unittest.cc',
'common/host_discardable_shared_memory_manager_unittest.cc',
'common/host_shared_bitmap_manager_unittest.cc',
- 'common/id_type_unittest.cc',
'common/indexed_db/indexed_db_key_unittest.cc',
+ 'common/input/event_with_latency_info_unittest.cc',
'common/input/gesture_event_stream_validator_unittest.cc',
'common/input/input_param_traits_unittest.cc',
'common/input/touch_event_stream_validator_unittest.cc',
@@ -680,6 +681,8 @@
'common/mac/attributed_string_coder_unittest.mm',
'common/mac/font_descriptor_unittest.mm',
'common/one_writer_seqlock_unittest.cc',
+ 'common/origin_trials/trial_token_unittest.cc',
+ 'common/origin_trials/trial_token_validator_unittest.cc',
'common/origin_util_unittest.cc',
'common/page_state_serialization_unittest.cc',
'common/page_zoom_unittest.cc',
@@ -695,7 +698,6 @@
'common/webplugininfo_unittest.cc',
'renderer/android/email_detector_unittest.cc',
'renderer/android/phone_number_detector_unittest.cc',
- 'renderer/battery_status/battery_status_dispatcher_unittest.cc',
'renderer/bmp_image_decoder_unittest.cc',
'renderer/device_sensors/device_light_event_pump_unittest.cc',
'renderer/device_sensors/device_motion_event_pump_unittest.cc',
@@ -708,6 +710,7 @@
'renderer/gpu/render_widget_compositor_unittest.cc',
'renderer/ico_image_decoder_unittest.cc',
'renderer/input/input_event_filter_unittest.cc',
+ 'renderer/input/main_thread_event_queue_unittest.cc',
'renderer/manifest/manifest_parser_unittest.cc',
'renderer/media/android/media_info_loader_unittest.cc',
'renderer/media/audio_message_filter_unittest.cc',
@@ -741,15 +744,12 @@
],
# Put WebRTC-related sources in the plugin+WebRTC section below.
'content_unittests_plugins_sources': [
- 'browser/plugin_loader_posix_unittest.cc',
'browser/renderer_host/pepper/browser_ppapi_host_test.cc',
'browser/renderer_host/pepper/browser_ppapi_host_test.h',
'browser/renderer_host/pepper/pepper_file_system_browser_host_unittest.cc',
'browser/renderer_host/pepper/pepper_gamepad_host_unittest.cc',
'browser/renderer_host/pepper/pepper_printing_host_unittest.cc',
'browser/renderer_host/pepper/quota_reservation_unittest.cc',
- 'child/npapi/plugin_lib_unittest.cc',
- 'renderer/npapi/webplugin_impl_unittest.cc',
'renderer/pepper/event_conversion_unittest.cc',
'renderer/pepper/host_var_tracker_unittest.cc',
'renderer/pepper/mock_resource.h',
@@ -759,14 +759,13 @@
],
# WebRTC-specific sources. Put WebRTC plugin-related stuff further below.
'content_unittests_webrtc_sources': [
- 'browser/media/webrtc_internals_unittest.cc',
+ 'browser/media/webrtc/webrtc_internals_unittest.cc',
'browser/renderer_host/media/webrtc_identity_service_host_unittest.cc',
'browser/renderer_host/p2p/socket_host_tcp_server_unittest.cc',
'browser/renderer_host/p2p/socket_host_tcp_unittest.cc',
'browser/renderer_host/p2p/socket_host_test_utils.cc',
'browser/renderer_host/p2p/socket_host_test_utils.h',
'browser/renderer_host/p2p/socket_host_udp_unittest.cc',
- 'browser/renderer_host/p2p/socket_host_unittest.cc',
'renderer/media/audio_repetition_detector_unittest.cc',
'renderer/media/audio_track_recorder_unittest.cc',
'renderer/media/canvas_capture_handler_unittest.cc',
@@ -779,13 +778,14 @@
'renderer/media/media_stream_video_renderer_sink_unittest.cc',
'renderer/media/media_stream_video_source_unittest.cc',
'renderer/media/media_stream_video_track_unittest.cc',
- 'renderer/media/mock_media_constraint_factory.cc',
+ 'renderer/media/mock_constraint_factory.cc',
'renderer/media/mock_media_stream_registry.cc',
'renderer/media/mock_media_stream_registry.h',
'renderer/media/mock_media_stream_video_sink.cc',
'renderer/media/mock_media_stream_video_sink.h',
'renderer/media/mock_media_stream_video_source.cc',
'renderer/media/mock_media_stream_video_source.h',
+ 'renderer/media/peer_connection_tracker_unittest.cc',
'renderer/media/rtc_data_channel_handler_unittest.cc',
'renderer/media/rtc_peer_connection_handler_unittest.cc',
'renderer/media/rtc_video_decoder_unittest.cc',
@@ -818,18 +818,9 @@
'browser/android/java/jni_helper_unittest.cc',
'browser/android/url_request_content_job_unittest.cc',
'common/gpu/client/gpu_memory_buffer_impl_surface_texture_unittest.cc',
- 'common/gpu/gpu_memory_buffer_factory_surface_texture_unittest.cc',
'renderer/java/gin_java_bridge_value_converter_unittest.cc',
'renderer/media/android/webmediasession_android_unittest.cc',
],
- 'content_unittests_mac_sources': [
- 'common/gpu/client/gpu_memory_buffer_impl_io_surface_unittest.cc',
- 'common/gpu/gpu_memory_buffer_factory_io_surface_unittest.cc',
- ],
- 'content_unittests_ozone_sources': [
- 'common/gpu/client/gpu_memory_buffer_impl_ozone_native_pixmap_unittest.cc',
- 'common/gpu/gpu_memory_buffer_factory_ozone_native_pixmap_unittest.cc',
- ],
},
'targets': [
{
@@ -837,32 +828,64 @@
'target_name': 'test_support_content',
'type': 'static_library',
'dependencies': [
+ '../cc/blink/cc_blink.gyp:cc_blink',
+ '../cc/cc.gyp:cc',
+ '../cc/cc_tests.gyp:cc_test_support',
+ '../components/scheduler/scheduler.gyp:scheduler',
+ '../components/scheduler/scheduler.gyp:scheduler_test_support',
+ '../gpu/blink/gpu_blink.gyp:gpu_blink',
+ '../gpu/gpu.gyp:gpu_ipc_common',
+ '../gpu/gpu.gyp:gpu_ipc_service_test_support',
+ '../ipc/mojo/ipc_mojo.gyp:*',
+ '../media/blink/media_blink.gyp:media_blink',
+ '../media/media.gyp:media',
+ '../media/midi/midi.gyp:midi',
+ '../mojo/mojo_edk.gyp:mojo_common_test_support',
'../mojo/mojo_base.gyp:mojo_application_base',
- '../mojo/mojo_base.gyp:mojo_environment_chromium',
+ '../mojo/mojo_edk.gyp:mojo_system_impl',
+ '../mojo/mojo_public.gyp:mojo_cpp_bindings',
'../net/net.gyp:net_test_support',
+ '../ppapi/ppapi_internal.gyp:ppapi_host',
+ '../ppapi/ppapi_internal.gyp:ppapi_proxy',
+ '../ppapi/ppapi_internal.gyp:ppapi_shared',
+ '../ppapi/ppapi_internal.gyp:ppapi_unittest_shared',
'../skia/skia.gyp:skia',
+ '../storage/storage_browser.gyp:storage',
'../storage/storage_common.gyp:storage_common',
'../testing/gmock.gyp:gmock',
'../testing/gtest.gyp:gtest',
- '../third_party/mojo/mojo_edk.gyp:mojo_system_impl',
- '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
+ '../third_party/WebKit/public/blink.gyp:blink',
+ '../third_party/WebKit/public/blink.gyp:blink_test_support',
'../ui/accessibility/accessibility.gyp:ax_gen',
'../ui/base/ime/ui_base_ime.gyp:ui_base_ime',
'../ui/base/ui_base.gyp:ui_base',
'../ui/base/ui_base.gyp:ui_base_test_support',
+ '../ui/base/ui_base.gyp:ui_data_pack',
+ '../ui/compositor/compositor.gyp:compositor_test_support',
'../ui/events/events.gyp:dom_keycode_converter',
'../ui/events/events.gyp:events_base',
'../ui/events/events.gyp:events_test_support',
'../ui/events/events.gyp:gesture_detection',
'../ui/gfx/gfx.gyp:gfx_test_support',
'../ui/resources/ui_resources.gyp:ui_resources',
+ '../ui/surface/surface.gyp:surface',
'../url/url.gyp:url_lib',
+ '../v8/tools/gyp/v8.gyp:v8',
'browser/speech/proto/speech_proto.gyp:speech_proto',
+ 'content_test_mojo_bindings',
+ 'content.gyp:content_app_both',
'content.gyp:content_browser',
+ 'content.gyp:content_child',
'content.gyp:content_common',
+ 'content.gyp:content_gpu',
+ 'content.gyp:content_ppapi_plugin',
+ 'content.gyp:content_renderer',
+ 'content.gyp:content_utility',
+ 'content_shell_and_tests.gyp:content_shell_pak',
],
'export_dependent_settings': [
'content.gyp:content_browser',
+ '../third_party/WebKit/public/blink.gyp:blink',
],
'include_dirs': [
'..',
@@ -880,72 +903,14 @@
'test/mock_google_streaming_server.cc',
],
}],
- ['OS == "ios"', {
- 'sources/': [
- # iOS only needs a small portion of content; exclude all the
- # implementation, and re-include what is used.
- ['exclude', '\\.(cc|mm)$'],
- ['include', '_ios\\.(cc|mm)$'],
- ['include', '^public/test/mock_notification_observer\\.cc$'],
- ['include', '^public/test/mock_resource_context\\.cc$'],
- ['include', '^public/test/test_content_client_initializer\\.cc$'],
- ['include', '^public/test/test_notification_tracker\\.cc$'],
- ['include', '^public/test/test_utils\\.cc$'],
- ['include', '^public/test/unittest_test_suite\\.cc$'],
- ['include', '^test/test_content_browser_client\\.cc$'],
- ['include', '^test/test_content_client\\.cc$'],
- ],
- }, { # OS != "ios"
- 'conditions': [
- ['OS=="mac"', {
- 'copies': [{
- 'destination': '<(SHARED_INTERMEDIATE_DIR)/webkit',
- 'files': [
- 'shell/resources/missingImage.png',
- 'shell/resources/textAreaResizeCorner.png',
- ],
- }],
- }],
- ],
- 'dependencies': [
- 'content_test_mojo_bindings',
- 'content.gyp:content_app_both',
- 'content.gyp:content_child',
- 'content.gyp:content_common',
- 'content.gyp:content_gpu',
- 'content.gyp:content_plugin',
- 'content.gyp:content_ppapi_plugin',
- 'content.gyp:content_renderer',
- 'content.gyp:content_utility',
- 'content_shell_and_tests.gyp:content_shell_pak',
- '../cc/blink/cc_blink.gyp:cc_blink',
- '../cc/cc.gyp:cc',
- '../cc/cc_tests.gyp:cc_test_support',
- '../components/scheduler/scheduler.gyp:scheduler',
- '../components/scheduler/scheduler.gyp:scheduler_test_support',
- '../gpu/blink/gpu_blink.gyp:gpu_blink',
- '../ipc/mojo/ipc_mojo.gyp:*',
- '../media/blink/media_blink.gyp:media_blink',
- '../media/media.gyp:media',
- '../media/midi/midi.gyp:midi',
- '../mojo/mojo_base.gyp:mojo_application_base',
- '../mojo/mojo_base.gyp:mojo_environment_chromium',
- '../ppapi/ppapi_internal.gyp:ppapi_host',
- '../ppapi/ppapi_internal.gyp:ppapi_proxy',
- '../ppapi/ppapi_internal.gyp:ppapi_shared',
- '../ppapi/ppapi_internal.gyp:ppapi_unittest_shared',
- '../storage/storage_browser.gyp:storage',
- '../storage/storage_common.gyp:storage_common',
- '../third_party/WebKit/public/blink.gyp:blink',
- '../third_party/mojo/mojo_edk.gyp:mojo_common_test_support',
- '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
- '../ui/compositor/compositor.gyp:compositor_test_support',
- '../ui/surface/surface.gyp:surface',
- '../v8/tools/gyp/v8.gyp:v8',
- ],
- 'export_dependent_settings': [
- '../third_party/WebKit/public/blink.gyp:blink',
- ],
+ ['OS == "mac"', {
+ 'copies': [{
+ 'destination': '<(SHARED_INTERMEDIATE_DIR)/webkit',
+ 'files': [
+ 'shell/resources/missingImage.png',
+ 'shell/resources/textAreaResizeCorner.png',
+ ],
+ }],
}],
['OS == "win"', {
'dependencies': [
@@ -968,7 +933,6 @@
],
'dependencies': [
'../third_party/libjingle/libjingle.gyp:libjingle_webrtc',
- '../third_party/libjingle/libjingle.gyp:libpeerconnection',
'../third_party/webrtc/modules/modules.gyp:video_capture_module',
],
}],
@@ -1002,7 +966,7 @@
],
'dependencies': [
'../ui/compositor/compositor.gyp:compositor',
- '../third_party/libvpx_new/libvpx.gyp:libvpx_new',
+ '../third_party/libvpx/libvpx.gyp:libvpx',
],
}],
['OS=="android"', {
@@ -1012,666 +976,680 @@
'content.gyp:content_shell_assets_copy',
],
}],
- ['v8_use_external_startup_data==1 and OS!="ios"', {
+ ['v8_use_external_startup_data==1', {
'dependencies': [
'../gin/gin.gyp:gin',
],
}],
],
},
- ],
- 'conditions': [
- ['test_isolation_mode != "noop"', {
- 'targets': [
- {
- 'target_name': 'content_browsertests_run',
- 'type': 'none',
+ {
+ # GN version: //content/test:layouttest_support
+ 'target_name': 'layouttest_support_content',
+ 'type': 'static_library',
+ 'dependencies': [
+ 'content.gyp:content_renderer',
+ 'test_support_content',
+ '../components/test_runner/test_runner.gyp:test_runner',
+ '../skia/skia.gyp:skia',
+ '../ui/accessibility/accessibility.gyp:ax_gen',
+ '../ui/base/ime/ui_base_ime.gyp:ui_base_ime',
+ '../v8/tools/gyp/v8.gyp:v8',
+ ],
+ 'include_dirs': [
+ '..',
+ '<(SHARED_INTERMEDIATE_DIR)',
+ ],
+ 'sources': [ '<@(layouttest_support_content_sources)' ],
+ 'conditions': [
+ ['OS=="android"', {
'dependencies': [
- 'content_browsertests',
- ],
- 'includes': [
- '../build/isolate.gypi',
+ 'test_support_content_jni_headers',
],
+ }],
+ ],
+ },
+ {
+ # GN version: //content/test:content_unittests
+ 'target_name': 'content_unittests',
+ 'type': '<(gtest_target_type)',
+ 'dependencies': [
+ 'browser/background_sync/background_sync_proto.gyp:background_sync_proto',
+ 'browser/cache_storage/cache_storage_proto.gyp:cache_storage_proto',
+ 'browser/notifications/notification_proto.gyp:notification_proto',
+ 'browser/service_worker/service_worker_proto.gyp:service_worker_proto',
+ 'browser/speech/proto/speech_proto.gyp:speech_proto',
+ 'content.gyp:content_browser',
+ 'content.gyp:content_child',
+ 'content.gyp:content_common',
+ 'content.gyp:content_gpu',
+ 'content.gyp:content_renderer',
+ 'content.gyp:content_resources',
+ 'content_common_mojo_bindings.gyp:content_common_mojo_bindings',
+ 'test_support_content',
+ '../base/base.gyp:test_support_base',
+ '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+ '../cc/cc.gyp:cc',
+ '../cc/cc.gyp:cc_surfaces',
+ '../cc/cc_tests.gyp:cc_test_support',
+ '../crypto/crypto.gyp:crypto',
+ '../device/battery/battery.gyp:device_battery',
+ '../device/battery/battery.gyp:device_battery_mojo_bindings',
+ '../device/bluetooth/bluetooth.gyp:device_bluetooth',
+ '../gin/gin.gyp:gin',
+ '../gpu/gpu.gyp:gpu',
+ '../gpu/gpu.gyp:gpu_unittest_utils',
+ '../ipc/ipc.gyp:test_support_ipc',
+ '../media/media.gyp:media_test_support',
+ '../media/media.gyp:shared_memory_support',
+ '../mojo/mojo_edk.gyp:mojo_common_test_support',
+ '../mojo/mojo_public.gyp:mojo_cpp_bindings',
+ '../net/net.gyp:net_extras',
+ '../net/net.gyp:net_test_support',
+ '../skia/skia.gyp:skia',
+ '../sql/sql.gyp:sql',
+ '../sql/sql.gyp:test_support_sql',
+ '../storage/storage_browser.gyp:storage',
+ '../storage/storage_common.gyp:storage_common',
+ '../testing/gmock.gyp:gmock',
+ '../testing/gtest.gyp:gtest',
+ '../third_party/icu/icu.gyp:icui18n',
+ '../third_party/icu/icu.gyp:icuuc',
+ '../third_party/leveldatabase/leveldatabase.gyp:leveldatabase',
+ '../third_party/libjingle/libjingle.gyp:libjingle',
+ '../third_party/re2/re2.gyp:re2',
+ '../third_party/WebKit/public/blink.gyp:blink',
+ '../ui/accessibility/accessibility.gyp:accessibility',
+ '../ui/base/ui_base.gyp:ui_base',
+ '../ui/events/blink/events_blink.gyp:events_blink',
+ '../ui/gfx/gfx.gyp:gfx',
+ '../ui/gfx/gfx.gyp:gfx_geometry',
+ '../ui/gfx/ipc/gfx_ipc.gyp:gfx_ipc',
+ '../ui/gfx/ipc/skia/gfx_ipc_skia.gyp:gfx_ipc_skia',
+ '../ui/gl/gl.gyp:gl',
+ '../ui/gl/gl.gyp:gl_test_support',
+ ],
+ 'include_dirs': [
+ '..',
+ '<(SHARED_INTERMEDIATE_DIR)', # Needed by render_media_client_unittest.cc.
+ ],
+ 'sources': [ '<@(content_unittests_sources)' ],
+ 'conditions': [
+ ['OS != "win"', {
'sources': [
- 'content_browsertests.isolate',
+ 'browser/file_descriptor_info_impl_unittest.cc',
],
- },
- {
- 'target_name': 'content_unittests_run',
- 'type': 'none',
+ }],
+ ['OS == "mac"', {
'dependencies': [
- 'content_unittests',
+ '../third_party/ocmock/ocmock.gyp:ocmock',
],
- 'includes': [
- '../build/isolate.gypi',
+ }],
+ ['enable_plugins==1', {
+ 'sources': [ '<@(content_unittests_plugins_sources)' ],
+ }],
+ ['enable_webrtc==1', {
+ 'sources': [ '<@(content_unittests_webrtc_sources)' ],
+ 'dependencies': [
+ '../third_party/libjingle/libjingle.gyp:libjingle_webrtc',
+ '../third_party/webrtc/modules/modules.gyp:video_capture_module',
+ '../ui/shell_dialogs/shell_dialogs.gyp:shell_dialogs',
],
+ }],
+ ['enable_webrtc==1 and enable_plugins==1', {
+ 'sources': [ '<@(content_unittests_plugin_webrtc_sources)' ],
+ }],
+ ['enable_webrtc==1 and (OS=="linux" or OS=="mac" or OS=="win")', {
'sources': [
- 'content_unittests.isolate',
+ 'browser/media/capture/desktop_capture_device_unittest.cc',
],
- 'conditions': [
- ['use_x11==1', {
- 'dependencies': [
- '../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck',
- ],
- }],
+ 'dependencies': [
+ '../third_party/webrtc/modules/modules.gyp:desktop_capture',
],
- },
- {
- 'target_name': 'telemetry_base',
- 'type': 'none',
+ }],
+ ['enable_webrtc==1 and chromeos==1', {
+ 'sources': [
+ 'browser/media/capture/desktop_capture_device_aura_unittest.cc',
+ ],
+ }],
+ ['enable_web_speech==1', {
+ 'sources': [ '<@(content_unittests_speech_sources)' ],
+ }],
+ ['OS=="linux" and use_dbus==1', {
'dependencies': [
- '../tools/telemetry/telemetry.gyp:bitmaptools#host',
+ '../build/linux/system.gyp:dbus',
+ '../dbus/dbus.gyp:dbus_test_support',
],
- },
- ],
- 'conditions': [
- ['archive_gpu_tests==1', {
- 'targets': [
- {
- # GN: content/test:content_gl_tests_run
- 'target_name': 'content_gl_tests_run',
- 'type': 'none',
- 'dependencies': [
- 'content_shell_and_tests.gyp:content_gl_tests',
- ],
- 'includes': [
- '../build/isolate.gypi',
- ],
- 'sources': [
- 'content_gl_tests.isolate',
- ],
- },
+ }],
+ ['OS=="win"', {
+ 'dependencies': [
+ '../third_party/iaccessible2/iaccessible2.gyp:iaccessible2',
],
}],
- ],
- }],
- ['OS!="ios"', {
- 'targets': [
- {
- # GN version: //content/test:layouttest_support
- 'target_name': 'layouttest_support_content',
- 'type': 'static_library',
+ ['OS=="mac"', {
+ # These flags are needed to run the test on Mac.
+ # Search for comments about "xcode_settings" in chrome_tests.gypi.
+ 'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-ObjC']},
+ }],
+ ['chromeos==1', {
'dependencies': [
- 'content.gyp:content_renderer',
- 'test_support_content',
- '../components/test_runner/test_runner.gyp:test_runner',
- '../skia/skia.gyp:skia',
- '../ui/accessibility/accessibility.gyp:ax_gen',
- '../ui/base/ime/ui_base_ime.gyp:ui_base_ime',
- '../v8/tools/gyp/v8.gyp:v8',
+ '../chromeos/chromeos.gyp:chromeos',
],
- 'include_dirs': [
- '..',
- '<(SHARED_INTERMEDIATE_DIR)',
+ 'sources!': [
+ 'browser/geolocation/wifi_data_provider_linux_unittest.cc',
],
- 'sources': [ '<@(layouttest_support_content_sources)' ],
- 'conditions': [
- ['OS=="android"', {
- 'dependencies': [
- 'test_support_content_jni_headers',
- ],
- }],
+ }],
+ ['use_aura==1', {
+ 'dependencies': [
+ '../ui/aura/aura.gyp:aura',
+ '../ui/aura_extra/aura_extra.gyp:aura_extra',
+ '../ui/wm/wm.gyp:wm',
],
- },
- {
- # GN version: //content/test:content_unittests
- 'target_name': 'content_unittests',
- 'type': '<(gtest_target_type)',
+ }],
+ ['use_aura==1 or toolkit_views==1', {
'dependencies': [
- 'browser/background_sync/background_sync_proto.gyp:background_sync_proto',
- 'browser/cache_storage/cache_storage_proto.gyp:cache_storage_proto',
- 'browser/notifications/notification_proto.gyp:notification_proto',
- 'browser/service_worker/service_worker_proto.gyp:service_worker_proto',
- 'browser/speech/proto/speech_proto.gyp:speech_proto',
- 'content.gyp:content_browser',
- 'content.gyp:content_child',
- 'content.gyp:content_common',
- 'content.gyp:content_gpu',
- 'content.gyp:content_plugin',
- 'content.gyp:content_renderer',
- 'content.gyp:content_resources',
- 'content_common_mojo_bindings.gyp:content_common_mojo_bindings',
- 'test_support_content',
- '../base/base.gyp:test_support_base',
- '../base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
- '../cc/cc.gyp:cc',
- '../cc/cc.gyp:cc_surfaces',
- '../cc/cc_tests.gyp:cc_test_support',
- '../crypto/crypto.gyp:crypto',
+ '../ui/events/events.gyp:events_test_support',
+ ],
+ }],
+ ['use_aura!=1 and OS!="mac"', {
+ 'sources/': [
+ ['exclude', '^browser/compositor/'],
+ ],
+ }],
+ ['OS == "android"', {
+ 'sources': [ '<@(content_unittests_android_sources)' ],
+ 'sources!': [
+ 'browser/geolocation/network_location_provider_unittest.cc',
+ 'browser/geolocation/wifi_data_provider_common_unittest.cc',
+ 'browser/power_usage_monitor_impl_unittest.cc',
+ 'browser/renderer_host/begin_frame_observer_proxy_unittest.cc',
+ 'browser/webui/url_data_manager_backend_unittest.cc',
+ 'renderer/media/audio_track_recorder_unittest.cc',
+ 'renderer/media/media_recorder_handler_unittest.cc',
+ 'renderer/media/video_track_recorder_unittest.cc',
+ ],
+ 'dependencies': [
+ '../testing/android/native_test.gyp:native_test_native_code',
+ ],
+ 'dependencies!': [
'../device/battery/battery.gyp:device_battery',
- '../device/battery/battery.gyp:device_battery_mojo_bindings',
- '../gin/gin.gyp:gin',
- '../gpu/gpu.gyp:gpu',
- '../gpu/gpu.gyp:gpu_unittest_utils',
- '../ipc/ipc.gyp:test_support_ipc',
- '../media/media.gyp:media_test_support',
- '../media/media.gyp:shared_memory_support',
- '../mojo/mojo_base.gyp:mojo_environment_chromium',
- '../net/net.gyp:net_extras',
- '../net/net.gyp:net_test_support',
- '../skia/skia.gyp:skia',
- '../sql/sql.gyp:sql',
- '../sql/sql.gyp:test_support_sql',
- '../storage/storage_browser.gyp:storage',
- '../storage/storage_common.gyp:storage_common',
- '../testing/gmock.gyp:gmock',
- '../testing/gtest.gyp:gtest',
- '../third_party/icu/icu.gyp:icui18n',
- '../third_party/icu/icu.gyp:icuuc',
- '../third_party/leveldatabase/leveldatabase.gyp:leveldatabase',
- '../third_party/libjingle/libjingle.gyp:libjingle',
- '../third_party/mojo/mojo_edk.gyp:mojo_common_test_support',
- '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
- '../third_party/re2/re2.gyp:re2',
- '../third_party/WebKit/public/blink.gyp:blink',
- '../ui/accessibility/accessibility.gyp:accessibility',
- '../ui/base/ui_base.gyp:ui_base',
- '../ui/events/blink/events_blink.gyp:events_blink',
- '../ui/gfx/gfx.gyp:gfx',
- '../ui/gfx/gfx.gyp:gfx_geometry',
- '../ui/gfx/ipc/gfx_ipc.gyp:gfx_ipc',
- '../ui/gl/gl.gyp:gl',
- '../ui/gl/gl.gyp:gl_test_support',
],
- 'include_dirs': [
- '..',
- '<(SHARED_INTERMEDIATE_DIR)', # Needed by render_media_client_unittest.cc.
+ }, { # OS != "android"
+ 'dependencies': [
+ '../third_party/libvpx/libvpx.gyp:libvpx',
],
- 'sources': [ '<@(content_unittests_sources)' ],
- 'conditions': [
- ['OS != "win"', {
- 'sources': [
- 'browser/file_descriptor_info_impl_unittest.cc',
- ],
- }],
- ['OS == "mac"', {
- 'dependencies': [
- '../third_party/ocmock/ocmock.gyp:ocmock',
- ],
- }],
- ['enable_plugins==1', {
- 'sources': [ '<@(content_unittests_plugins_sources)' ],
- }],
- ['enable_webrtc==1', {
- 'sources': [ '<@(content_unittests_webrtc_sources)' ],
- 'dependencies': [
- '../third_party/libjingle/libjingle.gyp:libjingle_webrtc',
- '../third_party/libjingle/libjingle.gyp:libpeerconnection',
- '../third_party/webrtc/modules/modules.gyp:video_capture_module',
- ],
- }],
- ['enable_webrtc==1 and enable_plugins==1', {
- 'sources': [ '<@(content_unittests_plugin_webrtc_sources)' ],
- }],
- ['enable_webrtc==1 and (OS=="linux" or OS=="mac" or OS=="win")', {
- 'sources': [
- 'browser/media/capture/desktop_capture_device_unittest.cc',
- ],
- 'dependencies': [
- '../third_party/webrtc/modules/modules.gyp:desktop_capture',
- ],
- }],
- ['enable_webrtc==1 and chromeos==1', {
- 'sources': [
- 'browser/media/capture/desktop_capture_device_aura_unittest.cc',
- ],
- }],
- ['enable_web_speech==1', {
- 'sources': [ '<@(content_unittests_speech_sources)' ],
- }],
- ['OS=="linux" and use_dbus==1', {
- 'dependencies': [
- '../build/linux/system.gyp:dbus',
- '../dbus/dbus.gyp:dbus_test_support',
- ],
- }],
- ['OS=="win" and win_use_allocator_shim==1', {
- 'dependencies': [
- '../base/allocator/allocator.gyp:allocator',
- ],
- }],
- ['OS=="win"', {
- 'dependencies': [
- '../third_party/iaccessible2/iaccessible2.gyp:iaccessible2',
- ],
- }],
- ['OS=="mac"', {
- # These flags are needed to run the test on Mac.
- # Search for comments about "xcode_settings" in chrome_tests.gypi.
- 'xcode_settings': {'OTHER_LDFLAGS': ['-Wl,-ObjC']},
- }],
- ['chromeos==1', {
- 'dependencies': [
- '../chromeos/chromeos.gyp:chromeos',
- ],
- 'sources!': [
- 'browser/geolocation/wifi_data_provider_linux_unittest.cc',
- ],
- }],
- ['use_aura==1', {
- 'dependencies': [
- '../ui/aura/aura.gyp:aura',
- '../ui/aura_extra/aura_extra.gyp:aura_extra',
- '../ui/wm/wm.gyp:wm',
- ],
- }],
- ['use_aura==1 or toolkit_views==1', {
- 'dependencies': [
- '../ui/events/events.gyp:events_test_support',
- ],
- }],
- ['use_aura!=1 and OS!="mac"', {
- 'sources/': [
- ['exclude', '^browser/compositor/'],
- ],
- }],
- ['OS == "android"', {
- 'sources': [ '<@(content_unittests_android_sources)' ],
- 'sources!': [
- 'browser/geolocation/network_location_provider_unittest.cc',
- 'browser/geolocation/wifi_data_provider_common_unittest.cc',
- 'browser/power_usage_monitor_impl_unittest.cc',
- 'browser/renderer_host/begin_frame_observer_proxy_unittest.cc',
- 'browser/webui/url_data_manager_backend_unittest.cc',
- 'renderer/media/audio_track_recorder_unittest.cc',
- 'renderer/media/media_recorder_handler_unittest.cc',
- 'renderer/media/video_track_recorder_unittest.cc',
- ],
- 'dependencies': [
- '../testing/android/native_test.gyp:native_test_native_code',
- ],
- 'dependencies!': [
- '../device/battery/battery.gyp:device_battery',
- ],
- }, { # OS != "android"
- 'dependencies': [
- '../third_party/libvpx_new/libvpx.gyp:libvpx_new',
- ],
- }],
- ['chromecast == 1', {
- 'sources!': [
- 'renderer/media/audio_track_recorder_unittest.cc',
- 'renderer/media/media_recorder_handler_unittest.cc',
- 'renderer/media/video_track_recorder_unittest.cc',
- ],
- }],
- # Avoid windows due to non-availability of cursor resources in test.
- ['OS != "linux"', {
- 'sources!': [
- 'browser/media/capture/cursor_renderer_aura_unittest.cc',
- ],
- }],
- ['use_aura!=1 and OS!="android"', {
- 'sources!': [
- 'browser/renderer_host/input/tap_suppression_controller_unittest.cc',
- ],
- }],
- ['use_dbus==0', {
- 'sources!': [
- 'browser/geolocation/wifi_data_provider_linux_unittest.cc',
- ],
- }],
- ['OS!="win" and OS!="mac"', {
- 'sources!': [
- 'common/plugin_list_unittest.cc',
- ],
- }],
- ['use_ozone==1', {
- 'sources': [ '<@(content_unittests_ozone_sources)' ],
- 'dependencies': [
- '../ui/ozone/ozone.gyp:ozone',
- '../ui/ozone/ozone.gyp:ozone_base',
- ],
- }],
- ['OS == "mac"', {
- 'sources': [ '<@(content_unittests_mac_sources)' ],
- 'dependencies': [
- '../third_party/boringssl/boringssl.gyp:boringssl',
- ],
- }],
+ }],
+ ['chromecast == 1', {
+ 'sources!': [
+ 'renderer/media/audio_track_recorder_unittest.cc',
+ 'renderer/media/media_recorder_handler_unittest.cc',
+ 'renderer/media/video_track_recorder_unittest.cc',
],
- },
- {
- # GN version: //content/test:content_perftests
- 'target_name': 'content_perftests',
- 'type': '<(gtest_target_type)',
- 'defines!': ['CONTENT_IMPLEMENTATION'],
+ }],
+ # Avoid windows due to non-availability of cursor resources in test.
+ ['OS != "linux"', {
+ 'sources!': [
+ 'browser/media/capture/cursor_renderer_aura_unittest.cc',
+ ],
+ }],
+ ['use_aura!=1 and OS!="android"', {
+ 'sources!': [
+ 'browser/renderer_host/input/tap_suppression_controller_unittest.cc',
+ ],
+ }],
+ ['use_dbus==0', {
+ 'sources!': [
+ 'browser/geolocation/wifi_data_provider_linux_unittest.cc',
+ ],
+ }],
+ ['OS!="win" and OS!="mac"', {
+ 'sources!': [
+ 'common/plugin_list_unittest.cc',
+ ],
+ }],
+ ['use_ozone==1', {
+ 'dependencies': [
+ '../ui/ozone/ozone.gyp:ozone',
+ '../ui/ozone/ozone.gyp:ozone_base',
+ ],
+ }],
+ ['OS == "mac"', {
+ 'dependencies': [
+ '../third_party/boringssl/boringssl.gyp:boringssl',
+ ],
+ }],
+ ],
+ },
+ {
+ # GN version: //content/test:content_perftests
+ 'target_name': 'content_perftests',
+ 'type': '<(gtest_target_type)',
+ 'defines!': ['CONTENT_IMPLEMENTATION'],
+ 'dependencies': [
+ 'content.gyp:content_browser',
+ 'content.gyp:content_common',
+ 'test_support_content',
+ '../base/base.gyp:test_support_base',
+ '../cc/cc.gyp:cc',
+ '../skia/skia.gyp:skia',
+ '../testing/gtest.gyp:gtest',
+ '../testing/perf/perf_test.gyp:*',
+ '../ui/gfx/gfx.gyp:gfx',
+ '../ui/gfx/gfx.gyp:gfx_geometry',
+ ],
+ 'include_dirs': [
+ '..',
+ ],
+ 'sources': [
+ 'browser/renderer_host/input/input_router_impl_perftest.cc',
+ 'common/cc_messages_perftest.cc',
+ 'common/discardable_shared_memory_heap_perftest.cc',
+ 'test/run_all_perftests.cc',
+ ],
+ 'conditions': [
+ ['OS == "android"', {
+ 'dependencies': [
+ '../testing/android/native_test.gyp:native_test_native_code',
+ ],
+ }],
+ ],
+ },
+ {
+ # GN version: //content/test:browsertest_support
+ # content_browser_test_support can be used by targets that run
+ # content_shell based browser tests.
+ 'target_name': 'content_browser_test_support',
+ 'type': 'static_library',
+ 'dependencies': [
+ 'content_shell_lib',
+ '../skia/skia.gyp:skia',
+ '../testing/gtest.gyp:gtest',
+ '../ui/accessibility/accessibility.gyp:ax_gen',
+ '../ui/base/ime/ui_base_ime.gyp:ui_base_ime',
+ ],
+ 'export_dependent_settings': [
+ '../skia/skia.gyp:skia',
+ ],
+ 'sources': [
+ # Source list duplicated in GN build.
+ 'public/test/content_browser_test.cc',
+ 'public/test/content_browser_test.h',
+ 'public/test/content_browser_test_utils.cc',
+ 'public/test/content_browser_test_utils.h',
+ 'public/test/content_browser_test_utils_mac.mm',
+ 'test/content_browser_test_utils_internal.cc',
+ 'test/content_browser_test_utils_internal.h',
+ 'test/content_test_launcher.cc',
+ ],
+ 'include_dirs': [
+ '<(SHARED_INTERMEDIATE_DIR)',
+ ],
+ 'conditions': [
+ ['OS=="android"', {
+ 'dependencies': [
+ 'content.gyp:content_app_both',
+ ],
+ }, {
'dependencies': [
'content.gyp:content_browser',
- 'content.gyp:content_common',
- 'test_support_content',
- '../base/base.gyp:test_support_base',
- '../cc/cc.gyp:cc',
- '../skia/skia.gyp:skia',
- '../testing/gtest.gyp:gtest',
- '../testing/perf/perf_test.gyp:*',
- '../ui/gfx/gfx.gyp:gfx',
- '../ui/gfx/gfx.gyp:gfx_geometry',
],
- 'include_dirs': [
- '..',
+ }],
+ ],
+ },
+ {
+ # GN version: //content/test:browsertest_base
+ # content_browser_test_base can be used by any browser test target.
+ 'target_name': 'content_browser_test_base',
+ 'type': 'static_library',
+ 'dependencies': [
+ '../base/base.gyp:base',
+ '../net/net.gyp:net_test_support',
+ '../testing/gtest.gyp:gtest',
+ '../third_party/WebKit/public/blink.gyp:blink',
+ '../ui/accessibility/accessibility.gyp:accessibility',
+ '../ui/base/ime/ui_base_ime.gyp:ui_base_ime',
+ '../ui/base/ui_base.gyp:ui_base',
+ '../ui/base/ui_base.gyp:ui_base_test_support',
+ '../ui/events/events.gyp:events_test_support',
+ 'content.gyp:content_browser',
+ 'content.gyp:content_common',
+ ],
+ 'export_dependent_settings': [
+ 'content.gyp:content_browser',
+ '../third_party/WebKit/public/blink.gyp:blink',
+ ],
+ 'sources': [
+ # Source list duplicated in GN build.
+ 'public/test/browser_test.h',
+ 'public/test/browser_test_base.cc',
+ 'public/test/browser_test_base.h',
+ 'public/test/browser_test_utils.cc',
+ 'public/test/browser_test_utils.h',
+ ],
+ },
+ {
+ # GN version: //content/test:test_mojo_bindings
+ 'target_name': 'content_test_mojo_bindings',
+ 'type': 'static_library',
+ 'sources': [
+ 'public/test/test_mojo_service.mojom',
+ ],
+ 'includes': [ '../mojo/mojom_bindings_generator.gypi' ],
+ },
+ {
+ # GN version: //content/test:web_ui_test_mojo_bindings
+ 'target_name': 'web_ui_test_mojo_bindings',
+ 'type': 'static_library',
+ 'dependencies': [
+ '../mojo/mojo_public.gyp:mojo_cpp_bindings',
+ ],
+ 'sources': [
+ 'test/data/web_ui_test_mojo_bindings.mojom',
+ ],
+ 'includes': [ '../mojo/mojom_bindings_generator.gypi' ],
+ 'export_dependent_settings': [
+ '../mojo/mojo_public.gyp:mojo_cpp_bindings',
+ ],
+ },
+ {
+ # GN version: //content/tests:content_browsertests
+ 'target_name': 'content_browsertests',
+ 'type': '<(gtest_target_type)',
+ 'dependencies': [
+ 'browser/background_sync/background_sync_proto.gyp:background_sync_proto',
+ 'content.gyp:content_common',
+ 'content.gyp:content_gpu',
+ 'content.gyp:content_renderer',
+ 'content.gyp:content_resources',
+ 'content_browser_test_base',
+ 'content_browser_test_support',
+ 'content_common_mojo_bindings.gyp:content_common_mojo_bindings',
+ 'content_shell_lib',
+ 'content_shell_pak',
+ 'test_support_content',
+ 'web_ui_test_mojo_bindings',
+ '../base/base.gyp:test_support_base',
+ '../device/battery/battery.gyp:device_battery',
+ '../device/battery/battery.gyp:device_battery_mojo_bindings',
+ '../device/vibration/vibration.gyp:device_vibration_mojo_bindings',
+ '../gin/gin.gyp:gin',
+ '../gpu/gpu.gyp:gpu',
+ '../ipc/ipc.gyp:test_support_ipc',
+ '../media/media.gyp:media_test_support',
+ '../media/media.gyp:shared_memory_support',
+ '../mojo/mojo_base.gyp:mojo_application_base',
+ '../mojo/mojo_base.gyp:mojo_test_support',
+ '../mojo/mojo_edk.gyp:mojo_common_test_support',
+ '../mojo/mojo_edk.gyp:mojo_system_impl',
+ '../mojo/mojo_public.gyp:mojo_cpp_bindings',
+ '../mojo/mojo_public.gyp:mojo_js_bindings',
+ '../net/net.gyp:net_test_support',
+ '../ppapi/ppapi_internal.gyp:ppapi_host',
+ '../ppapi/ppapi_internal.gyp:ppapi_ipc',
+ '../ppapi/ppapi_internal.gyp:ppapi_proxy',
+ '../ppapi/ppapi_internal.gyp:ppapi_shared',
+ '../ppapi/ppapi_internal.gyp:ppapi_unittest_shared',
+ '../testing/gmock.gyp:gmock',
+ '../testing/gtest.gyp:gtest',
+ '../third_party/WebKit/public/blink.gyp:blink',
+ '../third_party/leveldatabase/leveldatabase.gyp:leveldatabase',
+ '../third_party/mesa/mesa.gyp:osmesa',
+ '../third_party/zlib/zlib.gyp:zlib',
+ '../ui/accessibility/accessibility.gyp:accessibility',
+ '../ui/base/ui_base.gyp:ui_base',
+ '../ui/gfx/gfx.gyp:gfx',
+ '../ui/gfx/gfx.gyp:gfx_geometry',
+ '../ui/gl/gl.gyp:gl',
+ '../ui/gl/gl.gyp:gl_test_support',
+ '../ui/resources/ui_resources.gyp:ui_resources',
+ '../ui/shell_dialogs/shell_dialogs.gyp:shell_dialogs',
+ '../ui/snapshot/snapshot.gyp:snapshot',
+ '../ui/accessibility/accessibility.gyp:ax_gen',
+ ],
+ 'include_dirs': [
+ '..',
+ '<(SHARED_INTERMEDIATE_DIR)', # Needed by encrypted_media_browsertest.cc
+ ],
+ 'includes': [
+ 'browser/gpu/test_support_gpu.gypi',
+ ],
+ 'defines': [
+ 'HAS_OUT_OF_PROC_TEST_RUNNER',
+ ],
+ 'sources': [ '<@(content_browsertests_sources)' ],
+ 'conditions': [
+ ['OS=="win"', {
+ 'resource_include_dirs': [
+ '<(SHARED_INTERMEDIATE_DIR)/webkit',
],
'sources': [
- 'browser/renderer_host/input/input_router_impl_perftest.cc',
- 'common/cc_messages_perftest.cc',
- 'common/discardable_shared_memory_heap_perftest.cc',
- 'test/run_all_perftests.cc',
+ '<@(content_browsertests_win_sources)',
+ 'shell/app/resource.h',
+ 'shell/app/shell.rc',
],
- 'conditions': [
- ['OS == "android"', {
- 'dependencies': [
- '../testing/android/native_test.gyp:native_test_native_code',
- ],
- }],
- ['OS=="win" and component!="shared_library" and win_use_allocator_shim==1', {
- 'dependencies': [
- '<(DEPTH)/base/allocator/allocator.gyp:allocator',
- ],
- }],
+ 'dependencies': [
+ '<(DEPTH)/content/app/strings/content_strings.gyp:content_strings',
+ '<(DEPTH)/media/media.gyp:media_features',
+ '<(DEPTH)/net/net.gyp:net_resources',
+ '<(DEPTH)/third_party/WebKit/public/blink_resources.gyp:blink_resources',
+ '<(DEPTH)/third_party/iaccessible2/iaccessible2.gyp:iaccessible2',
+ '<(DEPTH)/third_party/isimpledom/isimpledom.gyp:isimpledom',
+ ],
+ 'configurations': {
+ 'Debug_Base': {
+ 'msvs_settings': {
+ 'VCLinkerTool': {
+ 'LinkIncremental': '<(msvs_large_module_debug_link_mode)',
+ },
+ },
+ },
+ },
+ # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+ 'msvs_disabled_warnings': [ 4267, ],
+ }],
+ ['OS=="android"', {
+ 'sources': [ '<@(content_browsertests_android_sources)' ],
+ 'sources!': [
+ 'browser/battery_status/battery_monitor_impl_browsertest.cc',
+ 'browser/media/session/media_session_delegate_default_browsertest.cc',
],
- },
- {
- # GN version: //content/tests:browsertest_support
- 'target_name': 'content_browser_test_support',
- 'type': 'static_library',
'dependencies': [
+ 'content_shell_jni_headers',
'content_shell_lib',
- '../skia/skia.gyp:skia',
- '../testing/gtest.gyp:gtest',
- '../ui/accessibility/accessibility.gyp:ax_gen',
- '../ui/base/ime/ui_base_ime.gyp:ui_base_ime',
+ '../testing/android/native_test.gyp:native_test_support',
],
- 'export_dependent_settings': [
- '../skia/skia.gyp:skia',
+ 'dependencies!': [
+ '../device/battery/battery.gyp:device_battery',
+ ],
+ }],
+ ['OS=="mac"', {
+ 'dependencies': [
+ 'content_shell', # Needed for Content Shell.app's Helper.
],
'sources': [
- # Source list duplicated in GN build.
- 'public/test/content_browser_test.cc',
- 'public/test/content_browser_test.h',
- 'public/test/content_browser_test_utils.cc',
- 'public/test/content_browser_test_utils.h',
- 'public/test/content_browser_test_utils_mac.mm',
- 'test/content_browser_test_utils_internal.cc',
- 'test/content_browser_test_utils_internal.h',
- 'test/content_test_launcher.cc',
+ 'renderer/external_popup_menu_browsertest.cc',
],
- 'include_dirs': [
- '<(SHARED_INTERMEDIATE_DIR)',
+ }],
+ ['use_aura==1 or toolkit_views==1', {
+ 'dependencies': [
+ '../ui/events/events.gyp:events_test_support',
],
- 'conditions': [
- ['OS=="android"', {
- 'dependencies': [
- 'content.gyp:content_app_both',
- ],
- }, {
- 'dependencies': [
- 'content.gyp:content_browser',
- ],
- }],
+ }],
+ ['use_aura!=1 and OS!="mac"', {
+ 'sources!' :[
+ 'browser/compositor/image_transport_factory_browsertest.cc',
],
- },
- {
- # GN version: //content/test:test_mojo_bindings
- 'target_name': 'content_test_mojo_bindings',
- 'type': 'static_library',
- 'sources': [
- 'public/test/test_mojo_service.mojom',
+ }],
+ ['use_aura==1', {
+ 'dependencies': [
+ '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection',
+ '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_test_support',
+ ]}, {
+ 'sources!': [
+ 'browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc',
],
- 'includes': [ '../third_party/mojo/mojom_bindings_generator.gypi' ],
- },
+ }],
+ ['enable_webrtc==1', {
+ 'sources': [ '<@(content_browsertests_webrtc_sources)' ],
+ 'dependencies': [
+ '../testing/perf/perf_test.gyp:perf_test',
+ ],
+ }],
+ ['enable_plugins==1', {
+ 'sources': [ '<@(content_browsertests_plugins_sources)' ],
+ 'dependencies': [
+ '../ppapi/ppapi_internal.gyp:ppapi_tests',
+ ]
+ }],
+ ['enable_web_speech == 1', {
+ 'sources': [ '<@(content_browsertests_speech_sources)' ],
+ }],
+ ['branding != "Chrome"', {
+ 'sources': [ '<@(content_browsertests_unofficial_build_sources)' ],
+ }],
+ ],
+ },
+ {
+ # GN version: //content/test:content_gl_tests
+ 'target_name': 'content_gl_tests',
+ 'type': '<(gtest_target_type)',
+ 'dependencies': [
+ 'content.gyp:content_common',
+ 'test_support_content',
+ '../base/base.gyp:test_support_base',
+ '../gpu/gpu.gyp:command_buffer_common',
+ '../testing/gtest.gyp:gtest',
+ '../third_party/WebKit/public/blink.gyp:blink',
+ '../ui/base/ui_base.gyp:ui_base',
+ '../ui/gfx/gfx.gyp:gfx',
+ '../ui/gfx/gfx.gyp:gfx_geometry',
+ '../ui/gfx/gfx.gyp:gfx_test_support',
+ '../ui/gl/gl.gyp:gl',
+ '../ui/gl/gl.gyp:gl_test_support',
+ '../v8/tools/gyp/v8.gyp:v8',
+ ],
+ 'include_dirs': [
+ '..',
+ ],
+ 'sources': [
+ 'browser/compositor/gl_helper_unittest.cc',
+ 'common/gpu/client/gpu_context_tests.h',
+ 'common/gpu/client/gpu_in_process_context_tests.cc',
+ 'test/run_all_gl_tests.cc',
+ ],
+ 'conditions': [
+ ['OS=="android"', {
+ 'dependencies': [
+ '../testing/android/native_test.gyp:native_test_native_code',
+ ],
+ }, {
+ 'dependencies': [
+ # Runtime dependencis.
+ '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg',
+ '../third_party/mesa/mesa.gyp:osmesa',
+ ],
+ }],
+ ],
+ },
+ {
+ # GN version: //content/test:content_gl_benchmark
+ 'target_name': 'content_gl_benchmark',
+ 'type': '<(gtest_target_type)',
+ 'dependencies': [
+ 'content.gyp:content_common',
+ 'test_support_content',
+ '../base/base.gyp:test_support_base',
+ '../testing/gtest.gyp:gtest',
+ '../third_party/WebKit/public/blink.gyp:blink',
+ '../ui/base/ui_base.gyp:ui_base',
+ '../ui/gfx/gfx.gyp:gfx',
+ '../ui/gfx/gfx.gyp:gfx_geometry',
+ '../ui/gl/gl.gyp:gl',
+ '../ui/gl/gl.gyp:gl_test_support',
+ ],
+ 'include_dirs': [
+ '..',
+ ],
+ 'sources': [
+ 'browser/compositor/gl_helper_benchmark.cc',
+ 'test/run_gl_benchmark.cc',
+ ],
+ },
+ ],
+ 'conditions': [
+ ['test_isolation_mode != "noop"', {
+ 'targets': [
{
- # GN version: //content/test:web_ui_test_mojo_bindings
- 'target_name': 'web_ui_test_mojo_bindings',
- 'type': 'static_library',
+ # GN: //content/test:content_site_isolation_browsertests_run
+ 'target_name': 'content_site_isolation_browsertests_run',
+ 'type': 'none',
'dependencies': [
- '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
+ 'content_browsertests_run',
],
'sources': [
- 'test/data/web_ui_test_mojo_bindings.mojom',
- ],
- 'includes': [ '../third_party/mojo/mojom_bindings_generator.gypi' ],
- 'export_dependent_settings': [
- '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
+ 'content_site_isolation_browsertests.isolate',
],
},
{
- # GN version: //content/tests:content_browsertests
- 'target_name': 'content_browsertests',
- 'type': '<(gtest_target_type)',
+ 'target_name': 'content_browsertests_run',
+ 'type': 'none',
'dependencies': [
- 'browser/background_sync/background_sync_proto.gyp:background_sync_proto',
- 'content.gyp:content_common',
- 'content.gyp:content_gpu',
- 'content.gyp:content_plugin',
- 'content.gyp:content_renderer',
- 'content.gyp:content_resources',
- 'content_browser_test_support',
- 'content_common_mojo_bindings.gyp:content_common_mojo_bindings',
- 'content_shell_lib',
- 'content_shell_pak',
- 'test_support_content',
- 'web_ui_test_mojo_bindings',
- '../base/base.gyp:test_support_base',
- '../device/battery/battery.gyp:device_battery',
- '../device/battery/battery.gyp:device_battery_mojo_bindings',
- '../device/vibration/vibration.gyp:device_vibration_mojo_bindings',
- '../gin/gin.gyp:gin',
- '../gpu/gpu.gyp:gpu',
- '../ipc/ipc.gyp:test_support_ipc',
- '../media/media.gyp:media_test_support',
- '../media/media.gyp:shared_memory_support',
- '../mojo/mojo_base.gyp:mojo_application_base',
- '../mojo/mojo_base.gyp:mojo_environment_chromium',
- '../mojo/mojo_base.gyp:mojo_test_support',
- '../net/net.gyp:net_test_support',
- '../ppapi/ppapi_internal.gyp:ppapi_host',
- '../ppapi/ppapi_internal.gyp:ppapi_ipc',
- '../ppapi/ppapi_internal.gyp:ppapi_proxy',
- '../ppapi/ppapi_internal.gyp:ppapi_shared',
- '../ppapi/ppapi_internal.gyp:ppapi_unittest_shared',
- '../testing/gmock.gyp:gmock',
- '../testing/gtest.gyp:gtest',
- '../third_party/WebKit/public/blink.gyp:blink',
- '../third_party/leveldatabase/leveldatabase.gyp:leveldatabase',
- '../third_party/mesa/mesa.gyp:osmesa',
- '../third_party/mojo/mojo_edk.gyp:mojo_common_test_support',
- '../third_party/mojo/mojo_edk.gyp:mojo_system_impl',
- '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
- '../third_party/mojo/mojo_public.gyp:mojo_js_bindings',
- '../third_party/zlib/zlib.gyp:zlib',
- '../ui/accessibility/accessibility.gyp:accessibility',
- '../ui/base/ui_base.gyp:ui_base',
- '../ui/gfx/gfx.gyp:gfx',
- '../ui/gfx/gfx.gyp:gfx_geometry',
- '../ui/gl/gl.gyp:gl',
- '../ui/gl/gl.gyp:gl_test_support',
- '../ui/resources/ui_resources.gyp:ui_resources',
- '../ui/shell_dialogs/shell_dialogs.gyp:shell_dialogs',
- '../ui/snapshot/snapshot.gyp:snapshot',
- '../ui/accessibility/accessibility.gyp:ax_gen',
- ],
- 'include_dirs': [
- '..',
- '<(SHARED_INTERMEDIATE_DIR)', # Needed by encrypted_media_browsertest.cc
+ 'content_browsertests',
],
'includes': [
- 'browser/gpu/test_support_gpu.gypi',
- ],
- 'defines': [
- 'HAS_OUT_OF_PROC_TEST_RUNNER',
+ '../build/isolate.gypi',
],
- 'sources': [ '<@(content_browsertests_sources)' ],
- 'conditions': [
- ['OS=="win"', {
- 'resource_include_dirs': [
- '<(SHARED_INTERMEDIATE_DIR)/webkit',
- ],
- 'sources': [
- '<@(content_browsertests_win_sources)',
- 'shell/app/resource.h',
- 'shell/app/shell.rc',
- ],
- 'dependencies': [
- '<(DEPTH)/content/app/strings/content_strings.gyp:content_strings',
- '<(DEPTH)/media/media.gyp:media_features',
- '<(DEPTH)/net/net.gyp:net_resources',
- '<(DEPTH)/third_party/WebKit/public/blink_resources.gyp:blink_resources',
- '<(DEPTH)/third_party/iaccessible2/iaccessible2.gyp:iaccessible2',
- '<(DEPTH)/third_party/isimpledom/isimpledom.gyp:isimpledom',
- ],
- 'configurations': {
- 'Debug_Base': {
- 'msvs_settings': {
- 'VCLinkerTool': {
- 'LinkIncremental': '<(msvs_large_module_debug_link_mode)',
- },
- },
- },
- },
- # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
- 'msvs_disabled_warnings': [ 4267, ],
- }],
- ['OS=="win" and win_use_allocator_shim==1', {
- 'dependencies': [
- '../base/allocator/allocator.gyp:allocator',
- ],
- }],
- ['OS=="android"', {
- 'sources': [ '<@(content_browsertests_android_sources)' ],
- 'sources!': [
- 'browser/battery_status/battery_monitor_impl_browsertest.cc',
- ],
- 'dependencies': [
- 'content_shell_jni_headers',
- 'content_shell_lib',
- '../testing/android/native_test.gyp:native_test_support',
- ],
- 'dependencies!': [
- '../device/battery/battery.gyp:device_battery',
- ],
- }],
- ['OS=="mac"', {
- 'dependencies': [
- 'content_shell', # Needed for Content Shell.app's Helper.
- ],
- 'sources': [
- 'renderer/external_popup_menu_browsertest.cc',
- ],
- }],
- ['use_aura==1 or toolkit_views==1', {
- 'dependencies': [
- '../ui/events/events.gyp:events_test_support',
- ],
- }],
- ['use_aura!=1 and OS!="mac"', {
- 'sources!' :[
- 'browser/compositor/image_transport_factory_browsertest.cc',
- ],
- }],
- ['use_aura==1', {
- 'dependencies': [
- '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection',
- '../ui/touch_selection/ui_touch_selection.gyp:ui_touch_selection_test_support',
- ]}, {
- 'sources!': [
- 'browser/renderer_host/input/touch_selection_controller_client_aura_browsertest.cc',
- ],
- }],
- ['enable_webrtc==1', {
- 'sources': [ '<@(content_browsertests_webrtc_sources)' ],
- 'dependencies': [
- '../testing/perf/perf_test.gyp:perf_test',
- ],
- }],
- ['enable_plugins==1', {
- 'sources': [ '<@(content_browsertests_plugins_sources)' ],
- 'dependencies': [
- '../ppapi/ppapi_internal.gyp:ppapi_tests',
- ]
- }],
- ['enable_web_speech == 1', {
- 'sources': [ '<@(content_browsertests_speech_sources)' ],
- }],
- ['branding != "Chrome"', {
- 'sources': [ '<@(content_browsertests_unofficial_build_sources)' ],
- }],
+ 'sources': [
+ 'content_browsertests.isolate',
],
},
{
- # GN version: //content/test:content_gl_tests
- 'target_name': 'content_gl_tests',
- 'type': '<(gtest_target_type)',
+ 'target_name': 'content_unittests_run',
+ 'type': 'none',
'dependencies': [
- 'content.gyp:content_common',
- 'test_support_content',
- '../base/base.gyp:test_support_base',
- '../gpu/gpu.gyp:command_buffer_common',
- '../testing/gtest.gyp:gtest',
- '../third_party/WebKit/public/blink.gyp:blink',
- '../ui/base/ui_base.gyp:ui_base',
- '../ui/gfx/gfx.gyp:gfx',
- '../ui/gfx/gfx.gyp:gfx_geometry',
- '../ui/gfx/gfx.gyp:gfx_test_support',
- '../ui/gl/gl.gyp:gl',
- '../ui/gl/gl.gyp:gl_test_support',
- '../v8/tools/gyp/v8.gyp:v8',
+ 'content_unittests',
],
- 'include_dirs': [
- '..',
+ 'includes': [
+ '../build/isolate.gypi',
],
'sources': [
- 'common/gpu/client/gl_helper_unittest.cc',
- 'common/gpu/client/gpu_in_process_context_tests.cc',
+ 'content_unittests.isolate',
],
'conditions': [
- ['OS=="android"', {
- 'dependencies': [
- '../testing/android/native_test.gyp:native_test_native_code',
- ],
- }, {
- 'dependencies': [
- # Runtime dependencis.
- '../third_party/ffmpeg/ffmpeg.gyp:ffmpeg',
- '../third_party/mesa/mesa.gyp:osmesa',
- ],
- }],
- ['OS=="win" and component!="shared_library" and win_use_allocator_shim==1', {
+ ['use_x11==1', {
'dependencies': [
- '<(DEPTH)/base/allocator/allocator.gyp:allocator',
+ '../tools/xdisplaycheck/xdisplaycheck.gyp:xdisplaycheck',
],
}],
],
},
{
- # GN version: //content/test:content_gl_benchmark
- 'target_name': 'content_gl_benchmark',
- 'type': '<(gtest_target_type)',
+ 'target_name': 'telemetry_base',
+ 'type': 'none',
'dependencies': [
- 'content.gyp:content_common',
- 'test_support_content',
- '../base/base.gyp:test_support_base',
- '../testing/gtest.gyp:gtest',
- '../third_party/WebKit/public/blink.gyp:blink',
- '../ui/base/ui_base.gyp:ui_base',
- '../ui/gfx/gfx.gyp:gfx',
- '../ui/gfx/gfx.gyp:gfx_geometry',
- '../ui/gl/gl.gyp:gl',
- '../ui/gl/gl.gyp:gl_test_support',
- ],
- 'include_dirs': [
- '..',
- ],
- 'sources': [
- 'common/gpu/client/gl_helper_benchmark.cc',
+ '../third_party/catapult/telemetry/telemetry.gyp:bitmaptools#host',
],
- 'conditions': [
- ['OS=="win" and component!="shared_library" and win_use_allocator_shim==1', {
+ },
+ ],
+ 'conditions': [
+ ['archive_gpu_tests==1', {
+ 'targets': [
+ {
+ # GN: content/test:content_gl_tests_run
+ 'target_name': 'content_gl_tests_run',
+ 'type': 'none',
'dependencies': [
- '<(DEPTH)/base/allocator/allocator.gyp:allocator',
+ 'content_shell_and_tests.gyp:content_gl_tests',
],
- }],
+ 'includes': [
+ '../build/isolate.gypi',
+ ],
+ 'sources': [
+ 'content_gl_tests.isolate',
+ ],
+ },
],
- },
+ }],
],
}],
['chromeos==1 or OS=="win" or OS=="android"', {
@@ -1683,12 +1661,13 @@
'type': '<(gtest_target_type)',
'dependencies': [
'../base/base.gyp:base',
+ '../gpu/gpu.gyp:command_buffer_service',
'../media/media.gyp:media',
'../testing/gtest.gyp:gtest',
'../ui/base/ui_base.gyp:ui_base',
'../ui/gfx/gfx.gyp:gfx',
- '../ui/gfx/gfx.gyp:gfx_test_support',
'../ui/gfx/gfx.gyp:gfx_geometry',
+ '../ui/gfx/gfx.gyp:gfx_test_support',
'../ui/gl/gl.gyp:gl',
'../ui/gl/gl.gyp:gl_test_support',
'content.gyp:content',
@@ -1727,13 +1706,6 @@
'<(angle_path)/src/angle.gyp:libGLESv2',
],
}],
- ['(OS=="win" and win_use_allocator_shim==1) or '
- '(os_posix == 1 and OS != "android" and '
- ' use_allocator!="none")', {
- 'dependencies': [
- '../base/allocator/allocator.gyp:allocator',
- ],
- }],
['target_arch != "arm" and (OS=="linux" or chromeos == 1)', {
'include_dirs': [
'<(DEPTH)/third_party/libva',
@@ -1789,12 +1761,13 @@
}
]
}],
- ['chromeos==1', {
+ ['chromeos==1 or OS=="mac"', {
'targets': [
{
'target_name': 'video_encode_accelerator_unittest',
'type': 'executable',
'dependencies': [
+ 'content.gyp:content_common',
'../base/base.gyp:base',
'../media/media.gyp:media',
'../media/media.gyp:media_test_support',
@@ -1827,7 +1800,11 @@
],
}],
],
- },
+ }
+ ]
+ }],
+ ['chromeos==1', {
+ 'targets': [
{
'target_name': 'jpeg_decode_accelerator_unittest',
'type': 'executable',
@@ -2130,12 +2107,12 @@
'../device/battery/battery.gyp:device_battery_javatests',
'../media/media.gyp:media_java',
'../media/media.gyp:media_test_support',
+ '../mojo/mojo_public.gyp:mojo_public_test_interfaces',
'../net/net.gyp:net_java',
'../net/net.gyp:net_javatests',
'../net/net.gyp:net_java_test_support',
'../testing/android/on_device_instrumentation.gyp:broker_java',
'../testing/android/on_device_instrumentation.gyp:require_driver_apk',
- '../third_party/mojo/mojo_public.gyp:mojo_public_test_interfaces',
],
'variables': {
'apk_name': 'ContentShellTest',
@@ -2166,8 +2143,11 @@
'src_paths': [
'public/android/junit/',
],
+ 'test_type': 'junit',
+ 'wrapper_script_name': 'helper/<(_target_name)',
},
'includes': [
+ '../build/android/test_runner.gypi',
'../build/host_jar.gypi',
],
},
diff --git a/chromium/content/content_unittests_apk.isolate b/chromium/content/content_unittests_apk.isolate
index 6d94fd7cd36..a67e2afdda8 100644
--- a/chromium/content/content_unittests_apk.isolate
+++ b/chromium/content/content_unittests_apk.isolate
@@ -10,6 +10,7 @@
'variables': {
'command': [
'<(PRODUCT_DIR)/bin/run_content_unittests',
+ '--logcat-output-dir', '${ISOLATED_OUTDIR}/logcats',
],
'files': [
'../base/base.isolate',
diff --git a/chromium/content/content_utility.gypi b/chromium/content/content_utility.gypi
index 6eb535f54e2..a826636208a 100644
--- a/chromium/content/content_utility.gypi
+++ b/chromium/content/content_utility.gypi
@@ -9,9 +9,9 @@
'../mojo/mojo_base.gyp:mojo_application_base',
'../mojo/mojo_base.gyp:mojo_application_bindings',
'../mojo/mojo_base.gyp:mojo_common_lib',
- '../mojo/mojo_base.gyp:mojo_message_pump_lib',
+ '../mojo/mojo_public.gyp:mojo_cpp_bindings',
+ '../mojo/mojo_public.gyp:mojo_message_pump_lib',
'../mojo/mojo_shell.gyp:mojo_shell_lib',
- '../third_party/mojo/mojo_public.gyp:mojo_cpp_bindings',
'../url/url.gyp:url_lib',
],
'variables': {
diff --git a/chromium/content/gpu/BUILD.gn b/chromium/content/gpu/BUILD.gn
index 91600f1db7d..25bd889210c 100644
--- a/chromium/content/gpu/BUILD.gn
+++ b/chromium/content/gpu/BUILD.gn
@@ -3,12 +3,11 @@
# found in the LICENSE file.
import("//build/config/ui.gni")
-import("//content/content.gni")
import("//media/media_options.gni")
# See //content/BUILD.gn for how this works.
group("gpu") {
- visibility = [ "//content/*" ]
+ visibility = [ "//content/*" ] # This is an internal content API.
if (is_component_build) {
public_deps = [
@@ -22,6 +21,8 @@ group("gpu") {
}
source_set("gpu_sources") {
+ # This is an internal content API. Code outside of the content "component"
+ # (like content/test and content/shell) should depend on ":gpu" above.
visibility = [ "//content/*" ]
sources = [
@@ -42,19 +43,29 @@ source_set("gpu_sources") {
deps = [
"//base",
+ "//base/third_party/dynamic_annotations",
+ "//components/tracing",
"//content:export",
+ "//content/common",
"//content/public/child:child_sources",
+ "//content/public/common:common_sources",
+ "//gpu:gpu",
+ "//gpu/ipc/common:command_buffer_traits",
+ "//gpu/ipc/service",
+ "//ipc",
+ "//media/mojo/services:application_factory",
"//mojo/shell/public/interfaces",
"//skia",
+ "//ui/events/ipc",
+ "//ui/gfx/ipc",
"//ui/gl",
]
- public_deps = [
- "//content/common:mojo_bindings",
- ]
-
- if (enable_mojo_media == "gpu") {
- deps += [ "//media/mojo/services:application" ]
+ if (mojo_media_host == "gpu") {
+ deps += [ "//media/mojo/services:application_factory" ]
+ if (is_android) {
+ deps += [ "//media/base/android" ]
+ }
}
if (is_win) {
@@ -64,6 +75,7 @@ source_set("gpu_sources") {
]
libs = [ "setupapi.lib" ]
deps += [
+ "//sandbox",
"//third_party/angle:libEGL",
"//third_party/angle:libGLESv2",
]
@@ -76,4 +88,12 @@ source_set("gpu_sources") {
if (use_x11) {
deps += [ "//ui/events/platform/x11" ]
}
+
+ if (use_ozone) {
+ deps += [ "//ui/ozone" ]
+ }
+
+ if (enable_vulkan) {
+ deps += [ "//gpu/vulkan" ]
+ }
}
diff --git a/chromium/content/gpu/DEPS b/chromium/content/gpu/DEPS
index f9f4c04e64a..aaf089a7ec6 100644
--- a/chromium/content/gpu/DEPS
+++ b/chromium/content/gpu/DEPS
@@ -1,8 +1,10 @@
include_rules = [
"+components/tracing",
"+content/child",
+ "+content/public/gpu",
"+libEGL",
"+libGLESv2",
+ "+media/base/android",
"+media/mojo/services",
"+mojo/shell",
"+sandbox",
diff --git a/chromium/content/gpu/gpu_child_thread.cc b/chromium/content/gpu/gpu_child_thread.cc
index b9f7bc5442a..e652ca914b2 100644
--- a/chromium/content/gpu/gpu_child_thread.cc
+++ b/chromium/content/gpu/gpu_child_thread.cc
@@ -9,30 +9,51 @@
#include "base/bind.h"
#include "base/lazy_instance.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/threading/thread_local.h"
#include "base/threading/worker_pool.h"
#include "build/build_config.h"
#include "content/child/child_process.h"
#include "content/child/thread_safe_sender.h"
-#include "content/common/gpu/gpu_memory_buffer_factory.h"
-#include "content/common/gpu/gpu_messages.h"
+#include "content/common/establish_channel_params.h"
+#include "content/common/gpu/media/gpu_jpeg_decode_accelerator.h"
+#include "content/common/gpu/media/gpu_video_decode_accelerator.h"
+#include "content/common/gpu/media/gpu_video_encode_accelerator.h"
+#include "content/common/gpu/media/media_service.h"
+#include "content/common/gpu_host_messages.h"
#include "content/gpu/gpu_process_control_impl.h"
#include "content/gpu/gpu_watchdog_thread.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
+#include "content/public/gpu/content_gpu_client.h"
+#include "gpu/command_buffer/service/gpu_switches.h"
#include "gpu/config/gpu_info_collector.h"
+#include "gpu/config/gpu_switches.h"
+#include "gpu/config/gpu_util.h"
+#include "gpu/ipc/common/memory_stats.h"
+#include "gpu/ipc/service/gpu_memory_buffer_factory.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_sync_message_filter.h"
#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_switches.h"
#include "ui/gl/gpu_switching_manager.h"
+#include "url/gurl.h"
#if defined(USE_OZONE)
#include "ui/ozone/public/gpu_platform_support.h"
#include "ui/ozone/public/ozone_platform.h"
#endif
+#if defined(ENABLE_VULKAN)
+#include "gpu/vulkan/vulkan_surface.h"
+#endif
+
namespace content {
namespace {
+base::LazyInstance<base::ThreadLocalPointer<GpuChildThread>> g_lazy_tls =
+ LAZY_INSTANCE_INITIALIZER;
+
static base::LazyInstance<scoped_refptr<ThreadSafeSender> >
g_thread_safe_sender = LAZY_INSTANCE_INITIALIZER;
@@ -43,19 +64,19 @@ bool GpuProcessLogMessageHandler(int severity,
std::string header = str.substr(0, message_start);
std::string message = str.substr(message_start);
- g_thread_safe_sender.Get()->Send(new GpuHostMsg_OnLogMessage(
- severity, header, message));
+ g_thread_safe_sender.Get()->Send(
+ new GpuHostMsg_OnLogMessage(severity, header, message));
return false;
}
-// Message filter used to to handle GpuMsg_CreateGpuMemoryBuffer messages on
-// the IO thread. This allows the UI thread in the browser process to remain
+// Message filter used to to handle GpuMsg_CreateGpuMemoryBuffer messages
+// on the IO thread. This allows the UI thread in the browser process to remain
// fast at all times.
class GpuMemoryBufferMessageFilter : public IPC::MessageFilter {
public:
explicit GpuMemoryBufferMessageFilter(
- GpuMemoryBufferFactory* gpu_memory_buffer_factory)
+ gpu::GpuMemoryBufferFactory* gpu_memory_buffer_factory)
: gpu_memory_buffer_factory_(gpu_memory_buffer_factory),
sender_(nullptr) {}
@@ -72,10 +93,10 @@ class GpuMemoryBufferMessageFilter : public IPC::MessageFilter {
DCHECK(sender_);
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(GpuMemoryBufferMessageFilter, message)
- IPC_MESSAGE_HANDLER(GpuMsg_CreateGpuMemoryBuffer, OnCreateGpuMemoryBuffer)
- IPC_MESSAGE_HANDLER(GpuMsg_CreateGpuMemoryBufferFromHandle,
- OnCreateGpuMemoryBufferFromHandle)
- IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_MESSAGE_HANDLER(GpuMsg_CreateGpuMemoryBuffer, OnCreateGpuMemoryBuffer)
+ IPC_MESSAGE_HANDLER(GpuMsg_CreateGpuMemoryBufferFromHandle,
+ OnCreateGpuMemoryBufferFromHandle)
+ IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
@@ -107,12 +128,12 @@ class GpuMemoryBufferMessageFilter : public IPC::MessageFilter {
params.client_id)));
}
- GpuMemoryBufferFactory* const gpu_memory_buffer_factory_;
+ gpu::GpuMemoryBufferFactory* const gpu_memory_buffer_factory_;
IPC::Sender* sender_;
};
ChildThreadImpl::Options GetOptions(
- GpuMemoryBufferFactory* gpu_memory_buffer_factory) {
+ gpu::GpuMemoryBufferFactory* gpu_memory_buffer_factory) {
ChildThreadImpl::Options::Builder builder;
builder.AddStartupFilter(
@@ -131,12 +152,17 @@ ChildThreadImpl::Options GetOptions(
} // namespace
+// static
+GpuChildThread* GpuChildThread::current() {
+ return g_lazy_tls.Pointer()->Get();
+}
+
GpuChildThread::GpuChildThread(
GpuWatchdogThread* watchdog_thread,
bool dead_on_arrival,
const gpu::GPUInfo& gpu_info,
const DeferredMessages& deferred_messages,
- GpuMemoryBufferFactory* gpu_memory_buffer_factory,
+ gpu::GpuMemoryBufferFactory* gpu_memory_buffer_factory,
gpu::SyncPointManager* sync_point_manager)
: ChildThreadImpl(GetOptions(gpu_memory_buffer_factory)),
dead_on_arrival_(dead_on_arrival),
@@ -150,17 +176,20 @@ GpuChildThread::GpuChildThread(
target_services_ = NULL;
#endif
g_thread_safe_sender.Get() = thread_safe_sender();
+ g_lazy_tls.Pointer()->Set(this);
}
GpuChildThread::GpuChildThread(
+ const gpu::GpuPreferences& gpu_preferences,
const InProcessChildThreadParams& params,
- GpuMemoryBufferFactory* gpu_memory_buffer_factory,
+ gpu::GpuMemoryBufferFactory* gpu_memory_buffer_factory,
gpu::SyncPointManager* sync_point_manager)
: ChildThreadImpl(ChildThreadImpl::Options::Builder()
.InBrowserProcess(params)
.AddStartupFilter(new GpuMemoryBufferMessageFilter(
gpu_memory_buffer_factory))
.Build()),
+ gpu_preferences_(gpu_preferences),
dead_on_arrival_(false),
sync_point_manager_(sync_point_manager),
in_browser_process_(true),
@@ -173,10 +202,16 @@ GpuChildThread::GpuChildThread(
base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kInProcessGPU));
+#if defined(ENABLE_VULKAN)
+ // Temporary Vulkan initialization injection.
+ gpu::VulkanSurface::InitializeOneOff();
+#endif
+
if (!gfx::GLSurface::InitializeOneOff())
VLOG(1) << "gfx::GLSurface::InitializeOneOff failed";
g_thread_safe_sender.Get() = thread_safe_sender();
+ g_lazy_tls.Pointer()->Set(this);
}
GpuChildThread::~GpuChildThread() {
@@ -184,6 +219,7 @@ GpuChildThread::~GpuChildThread() {
delete deferred_messages_.front();
deferred_messages_.pop();
}
+ g_lazy_tls.Pointer()->Set(nullptr);
}
void GpuChildThread::Shutdown() {
@@ -199,6 +235,9 @@ void GpuChildThread::Init(const base::Time& process_start_time) {
// will be destroyed before GpuChildThread is destructed.
service_registry()->AddService(base::Bind(
&GpuChildThread::BindProcessControlRequest, base::Unretained(this)));
+
+ if (GetContentClient()->gpu()) // NULL in tests.
+ GetContentClient()->gpu()->RegisterMojoServices(service_registry());
}
bool GpuChildThread::Send(IPC::Message* msg) {
@@ -242,11 +281,109 @@ bool GpuChildThread::OnMessageReceived(const IPC::Message& msg) {
if (ChildThreadImpl::OnMessageReceived(msg))
return true;
- return gpu_channel_manager_.get() &&
- gpu_channel_manager_->OnMessageReceived(msg);
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(GpuChildThread, msg)
+#if defined(OS_MACOSX)
+ IPC_MESSAGE_HANDLER(AcceleratedSurfaceMsg_BufferPresented,
+ OnBufferPresented)
+#endif
+ IPC_MESSAGE_HANDLER(GpuMsg_EstablishChannel, OnEstablishChannel)
+ IPC_MESSAGE_HANDLER(GpuMsg_CloseChannel, OnCloseChannel)
+ IPC_MESSAGE_HANDLER(GpuMsg_DestroyGpuMemoryBuffer, OnDestroyGpuMemoryBuffer)
+ IPC_MESSAGE_HANDLER(GpuMsg_LoadedShader, OnLoadedShader)
+ IPC_MESSAGE_HANDLER(GpuMsg_UpdateValueState, OnUpdateValueState)
+#if defined(OS_ANDROID)
+ IPC_MESSAGE_HANDLER(GpuMsg_WakeUpGpu, OnWakeUpGpu);
+#endif
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ if (handled)
+ return true;
+
+ return false;
}
-void GpuChildThread::OnInitialize() {
+void GpuChildThread::SetActiveURL(const GURL& url) {
+ GetContentClient()->SetActiveURL(url);
+}
+
+void GpuChildThread::AddSubscription(int32_t client_id, unsigned int target) {
+ Send(new GpuHostMsg_AddSubscription(client_id, target));
+}
+
+void GpuChildThread::DidCreateOffscreenContext(const GURL& active_url) {
+ Send(new GpuHostMsg_DidCreateOffscreenContext(active_url));
+}
+
+void GpuChildThread::DidDestroyChannel(int client_id) {
+ media_service_->RemoveChannel(client_id);
+ Send(new GpuHostMsg_DestroyChannel(client_id));
+}
+
+void GpuChildThread::DidDestroyOffscreenContext(const GURL& active_url) {
+ Send(new GpuHostMsg_DidDestroyOffscreenContext(active_url));
+}
+
+void GpuChildThread::DidLoseContext(bool offscreen,
+ gpu::error::ContextLostReason reason,
+ const GURL& active_url) {
+ Send(new GpuHostMsg_DidLoseContext(offscreen, reason, active_url));
+}
+
+void GpuChildThread::GpuMemoryUmaStats(const gpu::GPUMemoryUmaStats& params) {
+ Send(new GpuHostMsg_GpuMemoryUmaStats(params));
+}
+
+void GpuChildThread::RemoveSubscription(int32_t client_id,
+ unsigned int target) {
+ Send(new GpuHostMsg_RemoveSubscription(client_id, target));
+}
+
+#if defined(OS_MACOSX)
+void GpuChildThread::SendAcceleratedSurfaceBuffersSwapped(
+ int32_t surface_id,
+ CAContextID ca_context_id,
+ const gfx::ScopedRefCountedIOSurfaceMachPort& io_surface,
+ const gfx::Size& size,
+ float scale_factor,
+ std::vector<ui::LatencyInfo> latency_info) {
+ AcceleratedSurfaceBuffersSwappedParams params;
+ params.surface_id = surface_id;
+ params.ca_context_id = ca_context_id;
+ params.io_surface = io_surface;
+ params.size = size;
+ params.scale_factor = scale_factor;
+ params.latency_info = std::move(latency_info);
+ Send(new GpuHostMsg_AcceleratedSurfaceBuffersSwapped(params));
+}
+#endif
+
+#if defined(OS_WIN)
+void GpuChildThread::SendAcceleratedSurfaceCreatedChildWindow(
+ gpu::SurfaceHandle parent_window,
+ gpu::SurfaceHandle child_window) {
+ Send(new GpuHostMsg_AcceleratedSurfaceCreatedChildWindow(parent_window,
+ child_window));
+}
+#endif
+
+void GpuChildThread::StoreShaderToDisk(int32_t client_id,
+ const std::string& key,
+ const std::string& shader) {
+ Send(new GpuHostMsg_CacheShader(client_id, key, shader));
+}
+
+void GpuChildThread::OnInitialize(const gpu::GpuPreferences& gpu_preferences) {
+ gpu_preferences_ = gpu_preferences;
+
+ gpu_info_.video_decode_accelerator_capabilities =
+ content::GpuVideoDecodeAccelerator::GetCapabilities(gpu_preferences_);
+ gpu_info_.video_encode_accelerator_supported_profiles =
+ content::GpuVideoEncodeAccelerator::GetSupportedProfiles(
+ gpu_preferences_);
+ gpu_info_.jpeg_decode_accelerator_supported =
+ content::GpuJpegDecodeAccelerator::IsSupported();
+
// Record initialization only after collecting the GPU info because that can
// take a significant amount of time.
gpu_info_.initialization_time = base::Time::Now() - process_start_time_;
@@ -262,10 +399,6 @@ void GpuChildThread::OnInitialize() {
return;
}
-#if defined(OS_ANDROID)
- base::PlatformThread::SetCurrentThreadPriority(base::ThreadPriority::DISPLAY);
-#endif
-
// We don't need to pipe log messages if we are running the GPU thread in
// the browser process.
if (!in_browser_process_)
@@ -275,12 +408,14 @@ void GpuChildThread::OnInitialize() {
// IPC messages before the sandbox has been enabled and all other necessary
// initialization has succeeded.
gpu_channel_manager_.reset(
- new GpuChannelManager(channel(), watchdog_thread_.get(),
+ new gpu::GpuChannelManager(gpu_preferences_, this, watchdog_thread_.get(),
base::ThreadTaskRunnerHandle::Get().get(),
ChildProcess::current()->io_task_runner(),
ChildProcess::current()->GetShutDownEvent(),
sync_point_manager_, gpu_memory_buffer_factory_));
+ media_service_.reset(new MediaService(gpu_channel_manager_.get()));
+
#if defined(USE_OZONE)
ui::OzonePlatform::GetInstance()
->GetGpuPlatformSupport()
@@ -345,17 +480,18 @@ void GpuChildThread::OnCollectGraphicsInfo() {
}
void GpuChildThread::OnGetVideoMemoryUsageStats() {
- GPUVideoMemoryUsageStats video_memory_usage_stats;
- if (gpu_channel_manager_)
+ gpu::VideoMemoryUsageStats video_memory_usage_stats;
+ if (gpu_channel_manager_) {
gpu_channel_manager_->gpu_memory_manager()->GetVideoMemoryUsageStats(
&video_memory_usage_stats);
+ }
Send(new GpuHostMsg_VideoMemoryUsageStats(video_memory_usage_stats));
}
void GpuChildThread::OnClean() {
DVLOG(1) << "GPU: Removing all contexts";
if (gpu_channel_manager_)
- gpu_channel_manager_->LoseAllContexts();
+ gpu_channel_manager_->DestroyAllChannels();
}
void GpuChildThread::OnCrash() {
@@ -391,8 +527,67 @@ void GpuChildThread::OnGpuSwitched() {
ui::GpuSwitchingManager::GetInstance()->NotifyGpuSwitched();
}
+#if defined(OS_MACOSX)
+void GpuChildThread::OnBufferPresented(const BufferPresentedParams& params) {
+ if (gpu_channel_manager_) {
+ gpu_channel_manager_->BufferPresented(
+ params.surface_id, params.vsync_timebase, params.vsync_interval);
+ }
+}
+#endif
+
+void GpuChildThread::OnEstablishChannel(const EstablishChannelParams& params) {
+ if (!gpu_channel_manager_)
+ return;
+
+ IPC::ChannelHandle channel_handle = gpu_channel_manager_->EstablishChannel(
+ params.client_id, params.client_tracing_id, params.preempts,
+ params.allow_view_command_buffers, params.allow_real_time_streams);
+ media_service_->AddChannel(params.client_id);
+ Send(new GpuHostMsg_ChannelEstablished(channel_handle));
+}
+
+void GpuChildThread::OnCloseChannel(int32_t client_id) {
+ if (gpu_channel_manager_)
+ gpu_channel_manager_->RemoveChannel(client_id);
+}
+
+void GpuChildThread::OnLoadedShader(const std::string& shader) {
+ if (gpu_channel_manager_)
+ gpu_channel_manager_->PopulateShaderCache(shader);
+}
+
+void GpuChildThread::OnDestroyGpuMemoryBuffer(
+ gfx::GpuMemoryBufferId id,
+ int client_id,
+ const gpu::SyncToken& sync_token) {
+ if (gpu_channel_manager_)
+ gpu_channel_manager_->DestroyGpuMemoryBuffer(id, client_id, sync_token);
+}
+
+void GpuChildThread::OnUpdateValueState(int client_id,
+ unsigned int target,
+ const gpu::ValueState& state) {
+ if (gpu_channel_manager_)
+ gpu_channel_manager_->UpdateValueState(client_id, target, state);
+}
+
+#if defined(OS_ANDROID)
+void GpuChildThread::OnWakeUpGpu() {
+ if (gpu_channel_manager_)
+ gpu_channel_manager_->WakeUpGpu();
+}
+#endif
+
+void GpuChildThread::OnLoseAllContexts() {
+ if (gpu_channel_manager_) {
+ gpu_channel_manager_->DestroyAllChannels();
+ media_service_->DestroyAllChannels();
+ }
+}
+
void GpuChildThread::BindProcessControlRequest(
- mojo::InterfaceRequest<ProcessControl> request) {
+ mojo::InterfaceRequest<mojom::ProcessControl> request) {
DVLOG(1) << "GPU: Binding ProcessControl request";
DCHECK(process_control_);
process_control_bindings_.AddBinding(process_control_.get(),
diff --git a/chromium/content/gpu/gpu_child_thread.h b/chromium/content/gpu/gpu_child_thread.h
index 816410d5774..ccc7ac9843e 100644
--- a/chromium/content/gpu/gpu_child_thread.h
+++ b/chromium/content/gpu/gpu_child_thread.h
@@ -17,17 +17,20 @@
#include "base/time/time.h"
#include "build/build_config.h"
#include "content/child/child_thread_impl.h"
-#include "content/common/gpu/gpu_channel.h"
-#include "content/common/gpu/gpu_channel_manager.h"
-#include "content/common/gpu/gpu_config.h"
-#include "content/common/gpu/x_util.h"
#include "content/common/process_control.mojom.h"
+#include "gpu/command_buffer/service/gpu_preferences.h"
#include "gpu/config/gpu_info.h"
-#include "mojo/common/weak_binding_set.h"
+#include "gpu/ipc/service/gpu_channel.h"
+#include "gpu/ipc/service/gpu_channel_manager.h"
+#include "gpu/ipc/service/gpu_channel_manager_delegate.h"
+#include "gpu/ipc/service/gpu_config.h"
+#include "gpu/ipc/service/x_util.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "ui/gfx/native_widget_types.h"
namespace gpu {
+class GpuMemoryBufferFactory;
class SyncPointManager;
}
@@ -36,27 +39,37 @@ class TargetServices;
}
namespace content {
-class GpuMemoryBufferFactory;
class GpuProcessControlImpl;
class GpuWatchdogThread;
+class MediaService;
+struct EstablishChannelParams;
+#if defined(OS_MACOSX)
+struct BufferPresentedParams;
+#endif
// The main thread of the GPU child process. There will only ever be one of
// these per process. It does process initialization and shutdown. It forwards
-// IPC messages to GpuChannelManager, which is responsible for issuing rendering
-// commands to the GPU.
-class GpuChildThread : public ChildThreadImpl {
+// IPC messages to gpu::GpuChannelManager, which is responsible for issuing
+// rendering commands to the GPU.
+class GpuChildThread : public ChildThreadImpl,
+ public gpu::GpuChannelManagerDelegate {
public:
typedef std::queue<IPC::Message*> DeferredMessages;
+ // Returns the one gpu thread for this process. Note that this can only
+ // be accessed when running on the gpu thread itself.
+ static GpuChildThread* current();
+
GpuChildThread(GpuWatchdogThread* gpu_watchdog_thread,
bool dead_on_arrival,
const gpu::GPUInfo& gpu_info,
const DeferredMessages& deferred_messages,
- GpuMemoryBufferFactory* gpu_memory_buffer_factory,
+ gpu::GpuMemoryBufferFactory* gpu_memory_buffer_factory,
gpu::SyncPointManager* sync_point_manager);
- GpuChildThread(const InProcessChildThreadParams& params,
- GpuMemoryBufferFactory* gpu_memory_buffer_factory,
+ GpuChildThread(const gpu::GpuPreferences& gpu_preferences,
+ const InProcessChildThreadParams& params,
+ gpu::GpuMemoryBufferFactory* gpu_memory_buffer_factory,
gpu::SyncPointManager* sync_point_manager);
~GpuChildThread() override;
@@ -66,14 +79,45 @@ class GpuChildThread : public ChildThreadImpl {
void Init(const base::Time& process_start_time);
void StopWatchdog();
+ gpu::GpuPreferences gpu_preferences() { return gpu_preferences_; }
+
+ private:
// ChildThread overrides.
bool Send(IPC::Message* msg) override;
bool OnControlMessageReceived(const IPC::Message& msg) override;
bool OnMessageReceived(const IPC::Message& msg) override;
- private:
+ // gpu::GpuChannelManagerDelegate implementation.
+ void SetActiveURL(const GURL& url) override;
+ void AddSubscription(int32_t client_id, unsigned int target) override;
+ void DidCreateOffscreenContext(const GURL& active_url) override;
+ void DidDestroyChannel(int client_id) override;
+ void DidDestroyOffscreenContext(const GURL& active_url) override;
+ void DidLoseContext(bool offscreen,
+ gpu::error::ContextLostReason reason,
+ const GURL& active_url) override;
+ void GpuMemoryUmaStats(const gpu::GPUMemoryUmaStats& params) override;
+ void RemoveSubscription(int32_t client_id, unsigned int target) override;
+#if defined(OS_MACOSX)
+ void SendAcceleratedSurfaceBuffersSwapped(
+ int32_t surface_id,
+ CAContextID ca_context_id,
+ const gfx::ScopedRefCountedIOSurfaceMachPort& io_surface,
+ const gfx::Size& size,
+ float scale_factor,
+ std::vector<ui::LatencyInfo> latency_info) override;
+#endif
+#if defined(OS_WIN)
+ void SendAcceleratedSurfaceCreatedChildWindow(
+ gpu::SurfaceHandle parent_window,
+ gpu::SurfaceHandle child_window) override;
+#endif
+ void StoreShaderToDisk(int32_t client_id,
+ const std::string& key,
+ const std::string& shader) override;
+
// Message handlers.
- void OnInitialize();
+ void OnInitialize(const gpu::GpuPreferences& gpu_preferences);
void OnFinalize();
void OnCollectGraphicsInfo();
void OnGetVideoMemoryUsageStats();
@@ -85,8 +129,27 @@ class GpuChildThread : public ChildThreadImpl {
void OnDisableWatchdog();
void OnGpuSwitched();
+#if defined(OS_MACOSX)
+ void OnBufferPresented(const BufferPresentedParams& params);
+#endif
+ void OnEstablishChannel(const EstablishChannelParams& params);
+ void OnCloseChannel(int32_t client_id);
+ void OnLoadedShader(const std::string& shader);
+ void OnDestroyGpuMemoryBuffer(gfx::GpuMemoryBufferId id,
+ int client_id,
+ const gpu::SyncToken& sync_token);
+ void OnUpdateValueState(int client_id,
+ unsigned int target,
+ const gpu::ValueState& state);
+#if defined(OS_ANDROID)
+ void OnWakeUpGpu();
+#endif
+ void OnLoseAllContexts();
+
void BindProcessControlRequest(
- mojo::InterfaceRequest<ProcessControl> request);
+ mojo::InterfaceRequest<mojom::ProcessControl> request);
+
+ gpu::GpuPreferences gpu_preferences_;
// Set this flag to true if a fatal error occurred before we receive the
// OnInitialize message, in which case we just declare ourselves DOA.
@@ -102,7 +165,9 @@ class GpuChildThread : public ChildThreadImpl {
// Non-owning.
gpu::SyncPointManager* sync_point_manager_;
- scoped_ptr<GpuChannelManager> gpu_channel_manager_;
+ scoped_ptr<gpu::GpuChannelManager> gpu_channel_manager_;
+
+ scoped_ptr<MediaService> media_service_;
// Information about the GPU, such as device and vendor ID.
gpu::GPUInfo gpu_info_;
@@ -113,14 +178,14 @@ class GpuChildThread : public ChildThreadImpl {
// Whether the GPU thread is running in the browser process.
bool in_browser_process_;
- // The GpuMemoryBufferFactory instance used to allocate GpuMemoryBuffers.
- GpuMemoryBufferFactory* const gpu_memory_buffer_factory_;
+ // The gpu::GpuMemoryBufferFactory instance used to allocate GpuMemoryBuffers.
+ gpu::GpuMemoryBufferFactory* const gpu_memory_buffer_factory_;
// Process control for Mojo application hosting.
scoped_ptr<GpuProcessControlImpl> process_control_;
- // Bindings to the ProcessControl impl.
- mojo::WeakBindingSet<ProcessControl> process_control_bindings_;
+ // Bindings to the mojom::ProcessControl impl.
+ mojo::BindingSet<mojom::ProcessControl> process_control_bindings_;
DISALLOW_COPY_AND_ASSIGN(GpuChildThread);
};
diff --git a/chromium/content/gpu/gpu_main.cc b/chromium/content/gpu/gpu_main.cc
index 6ab395480e8..a8c68d4d0d2 100644
--- a/chromium/content/gpu/gpu_main.cc
+++ b/chromium/content/gpu/gpu_main.cc
@@ -20,12 +20,7 @@
#include "build/build_config.h"
#include "content/child/child_process.h"
#include "content/common/content_constants_internal.h"
-#include "content/common/gpu/gpu_config.h"
-#include "content/common/gpu/gpu_memory_buffer_factory.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "content/common/gpu/media/gpu_jpeg_decode_accelerator.h"
-#include "content/common/gpu/media/gpu_video_decode_accelerator.h"
-#include "content/common/gpu/media/gpu_video_encode_accelerator.h"
+#include "content/common/gpu_host_messages.h"
#include "content/common/sandbox_linux/sandbox_linux.h"
#include "content/gpu/gpu_child_thread.h"
#include "content/gpu/gpu_process.h"
@@ -38,6 +33,9 @@
#include "gpu/config/gpu_info_collector.h"
#include "gpu/config/gpu_switches.h"
#include "gpu/config/gpu_util.h"
+#include "gpu/ipc/common/gpu_memory_buffer_support.h"
+#include "gpu/ipc/service/gpu_config.h"
+#include "gpu/ipc/service/gpu_memory_buffer_factory.h"
#include "ui/events/platform/platform_event_source.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_implementation.h"
@@ -64,7 +62,7 @@
#if defined(USE_X11)
#include "ui/base/x/x11_util.h"
-#include "ui/gfx/x/x11_switches.h"
+#include "ui/gfx/x/x11_switches.h" // nogncheck
#endif
#if defined(OS_LINUX)
@@ -121,8 +119,8 @@ bool GpuProcessLogMessageHandler(int severity,
const std::string& str) {
std::string header = str.substr(0, message_start);
std::string message = str.substr(message_start);
- deferred_messages.Get().push(new GpuHostMsg_OnLogMessage(
- severity, header, message));
+ deferred_messages.Get().push(
+ new GpuHostMsg_OnLogMessage(severity, header, message));
return false;
}
@@ -251,6 +249,11 @@ int GpuMain(const MainFunctionParams& parameters) {
VaapiWrapper::PreSandboxInitialization();
#endif
+#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
+ // Set thread priority before sandbox initialization.
+ base::PlatformThread::SetCurrentThreadPriority(base::ThreadPriority::DISPLAY);
+#endif
+
// Warm up resources that don't need access to GPUInfo.
if (WarmUpSandbox(command_line)) {
#if defined(OS_LINUX)
@@ -309,6 +312,10 @@ int GpuMain(const MainFunctionParams& parameters) {
// (Chrome OS, Android) or where workarounds may be dependent on GL_VENDOR
// and GL_RENDERER strings which are lazily computed (Linux).
if (!command_line.HasSwitch(switches::kDisableGpuDriverBugWorkarounds)) {
+ // TODO: this can not affect disabled extensions, since they're already
+ // initialized in the bindings. This should be moved before bindings
+ // initialization. However, populating GPUInfo fully works only on
+ // Android. Other platforms would need the bindings to query GL strings.
gpu::ApplyGpuDriverBugWorkarounds(
gpu_info, const_cast<base::CommandLine*>(&command_line));
}
@@ -366,26 +373,24 @@ int GpuMain(const MainFunctionParams& parameters) {
#elif defined(OS_MACOSX)
gpu_info.sandboxed = Sandbox::SandboxIsCurrentlyActive();
#endif
-
- gpu_info.video_decode_accelerator_capabilities =
- content::GpuVideoDecodeAccelerator::GetCapabilities();
- gpu_info.video_encode_accelerator_supported_profiles =
- content::GpuVideoEncodeAccelerator::GetSupportedProfiles();
- gpu_info.jpeg_decode_accelerator_supported =
- content::GpuJpegDecodeAccelerator::IsSupported();
} else {
dead_on_arrival = true;
}
logging::SetLogMessageHandler(NULL);
- scoped_ptr<GpuMemoryBufferFactory> gpu_memory_buffer_factory;
- if (GpuMemoryBufferFactory::GetNativeType() != gfx::EMPTY_BUFFER)
- gpu_memory_buffer_factory = GpuMemoryBufferFactory::CreateNativeType();
+ scoped_ptr<gpu::GpuMemoryBufferFactory> gpu_memory_buffer_factory;
+ if (gpu::GetNativeGpuMemoryBufferType() != gfx::EMPTY_BUFFER)
+ gpu_memory_buffer_factory = gpu::GpuMemoryBufferFactory::CreateNativeType();
gpu::SyncPointManager sync_point_manager(false);
- GpuProcess gpu_process;
+ base::ThreadPriority io_thread_priority = base::ThreadPriority::NORMAL;
+#if defined(OS_ANDROID) || defined(OS_CHROMEOS)
+ io_thread_priority = base::ThreadPriority::DISPLAY;
+#endif
+
+ GpuProcess gpu_process(io_thread_priority);
GpuChildThread* child_thread = new GpuChildThread(
watchdog_thread.get(), dead_on_arrival, gpu_info, deferred_messages.Get(),
diff --git a/chromium/content/gpu/gpu_process.cc b/chromium/content/gpu/gpu_process.cc
index 23906943d18..2523fd331ed 100644
--- a/chromium/content/gpu/gpu_process.cc
+++ b/chromium/content/gpu/gpu_process.cc
@@ -6,8 +6,8 @@
namespace content {
-GpuProcess::GpuProcess() {
-}
+GpuProcess::GpuProcess(base::ThreadPriority io_thread_priority)
+ : ChildProcess(io_thread_priority) {}
GpuProcess::~GpuProcess() {
}
diff --git a/chromium/content/gpu/gpu_process.h b/chromium/content/gpu/gpu_process.h
index 14754e90e5a..dbcf57759ee 100644
--- a/chromium/content/gpu/gpu_process.h
+++ b/chromium/content/gpu/gpu_process.h
@@ -12,7 +12,7 @@ namespace content {
class GpuProcess : public ChildProcess {
public:
- GpuProcess();
+ explicit GpuProcess(base::ThreadPriority io_thread_priority);
~GpuProcess() override;
private:
diff --git a/chromium/content/gpu/gpu_process_control_impl.cc b/chromium/content/gpu/gpu_process_control_impl.cc
index cb3175b8bfc..f0b2489d175 100644
--- a/chromium/content/gpu/gpu_process_control_impl.cc
+++ b/chromium/content/gpu/gpu_process_control_impl.cc
@@ -7,8 +7,12 @@
#if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
#include "base/bind.h"
#include "base/bind_helpers.h"
-#include "media/mojo/services/mojo_media_application.h"
-#include "mojo/shell/static_application_loader.h"
+#include "content/common/mojo/static_loader.h"
+#include "content/public/common/content_client.h"
+#include "media/mojo/services/mojo_media_application_factory.h"
+#if defined(OS_ANDROID)
+#include "media/base/android/media_client_android.h"
+#endif
#endif
namespace content {
@@ -17,13 +21,17 @@ GpuProcessControlImpl::GpuProcessControlImpl() {}
GpuProcessControlImpl::~GpuProcessControlImpl() {}
-void GpuProcessControlImpl::RegisterApplicationLoaders(
- URLToLoaderMap* url_to_loader_map) {
+void GpuProcessControlImpl::RegisterLoaders(
+ NameToLoaderMap* name_to_loader_map) {
#if defined(ENABLE_MOJO_MEDIA_IN_GPU_PROCESS)
- (*url_to_loader_map)[GURL("mojo:media")] =
- new mojo::shell::StaticApplicationLoader(
- base::Bind(&media::MojoMediaApplication::CreateApp),
- base::Bind(&base::DoNothing));
+#if defined(OS_ANDROID)
+ // Only set once per process instance.
+ media::SetMediaClientAndroid(GetContentClient()->GetMediaClientAndroid());
+#endif
+
+ (*name_to_loader_map)["mojo:media"] = new StaticLoader(
+ base::Bind(&media::CreateMojoMediaApplication),
+ base::Bind(&base::DoNothing));
#endif
}
diff --git a/chromium/content/gpu/gpu_process_control_impl.h b/chromium/content/gpu/gpu_process_control_impl.h
index 4353096a6fc..b886bb5fcfc 100644
--- a/chromium/content/gpu/gpu_process_control_impl.h
+++ b/chromium/content/gpu/gpu_process_control_impl.h
@@ -17,7 +17,7 @@ class GpuProcessControlImpl : public ProcessControlImpl {
~GpuProcessControlImpl() override;
// ProcessControlImpl:
- void RegisterApplicationLoaders(URLToLoaderMap* url_to_loader_map) override;
+ void RegisterLoaders(NameToLoaderMap* name_to_loader_map) override;
private:
DISALLOW_COPY_AND_ASSIGN(GpuProcessControlImpl);
diff --git a/chromium/content/gpu/gpu_watchdog_thread.cc b/chromium/content/gpu/gpu_watchdog_thread.cc
index 4cfde4f94b5..4ffec06ee57 100644
--- a/chromium/content/gpu/gpu_watchdog_thread.cc
+++ b/chromium/content/gpu/gpu_watchdog_thread.cc
@@ -11,6 +11,7 @@
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
+#include "base/debug/alias.h"
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/macros.h"
@@ -42,6 +43,8 @@ GpuWatchdogThread::GpuWatchdogThread(int timeout)
timeout_(base::TimeDelta::FromMilliseconds(timeout)),
armed_(false),
task_observer_(this),
+ use_thread_cpu_time_(true),
+ responsive_acknowledge_count_(0),
#if defined(OS_WIN)
watched_thread_handle_(0),
arm_cpu_time_(),
@@ -159,12 +162,30 @@ void GpuWatchdogThread::OnAcknowledge() {
weak_factory_.InvalidateWeakPtrs();
armed_ = false;
- if (suspended_)
+ if (suspended_) {
+ responsive_acknowledge_count_ = 0;
return;
+ }
+
+ base::Time current_time = base::Time::Now();
+
+ // The watchdog waits until at least 6 consecutive checks have returned in
+ // less than 50 ms before it will start ignoring the CPU time in determining
+ // whether to timeout. This is a compromise to allow startups that are slow
+ // due to disk contention to avoid timing out, but once the GPU process is
+ // running smoothly the watchdog will be able to detect hangs that don't use
+ // the CPU.
+ if ((current_time - check_time_) < base::TimeDelta::FromMilliseconds(50))
+ responsive_acknowledge_count_++;
+ else
+ responsive_acknowledge_count_ = 0;
+
+ if (responsive_acknowledge_count_ >= 6)
+ use_thread_cpu_time_ = false;
// If it took a long time for the acknowledgement, assume the computer was
// recently suspended.
- bool was_suspended = (base::Time::Now() > suspension_timeout_);
+ bool was_suspended = (current_time > suspension_timeout_);
// The monitored thread has responded. Post a task to check it again.
task_runner()->PostDelayedTask(
@@ -188,12 +209,16 @@ void GpuWatchdogThread::OnCheck(bool after_suspend) {
#if defined(OS_WIN)
arm_cpu_time_ = GetWatchedThreadTime();
+
+ QueryUnbiasedInterruptTime(&arm_interrupt_time_);
#endif
+ check_time_ = base::Time::Now();
+ check_timeticks_ = base::TimeTicks::Now();
// Immediately after the computer is woken up from being suspended it might
// be pretty sluggish, so allow some extra time before the next timeout.
base::TimeDelta timeout = timeout_ * (after_suspend ? 3 : 1);
- suspension_timeout_ = base::Time::Now() + timeout * 2;
+ suspension_timeout_ = check_time_ + timeout * 2;
// Post a task to the monitored thread that does nothing but wake up the
// TaskObserver. Any other tasks that are pending on the watched thread will
@@ -219,7 +244,7 @@ void GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang() {
// Defer termination until a certain amount of CPU time has elapsed on the
// watched thread.
base::TimeDelta time_since_arm = GetWatchedThreadTime() - arm_cpu_time_;
- if (time_since_arm < timeout_) {
+ if (use_thread_cpu_time_ && (time_since_arm < timeout_)) {
message_loop()->PostDelayedTask(
FROM_HERE,
base::Bind(
@@ -312,6 +337,28 @@ void GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang() {
}
#endif
+// Store variables so they're available in crash dumps to help determine the
+// cause of any hang.
+#if defined(OS_WIN)
+ ULONGLONG fire_interrupt_time;
+ QueryUnbiasedInterruptTime(&fire_interrupt_time);
+
+ // This is the time since the watchdog was armed, in 100ns intervals,
+ // ignoring time where the computer is suspended.
+ ULONGLONG interrupt_delay = fire_interrupt_time - arm_interrupt_time_;
+
+ base::debug::Alias(&interrupt_delay);
+ base::debug::Alias(&time_since_arm);
+
+ bool using_high_res_timer = base::Time::IsHighResolutionTimerInUse();
+ base::debug::Alias(&using_high_res_timer);
+#endif
+
+ base::Time current_time = base::Time::Now();
+ base::TimeTicks current_timeticks = base::TimeTicks::Now();
+ base::debug::Alias(&current_time);
+ base::debug::Alias(&current_timeticks);
+
LOG(ERROR) << "The GPU process hung. Terminating after "
<< timeout_.InMilliseconds() << " ms.";
diff --git a/chromium/content/gpu/gpu_watchdog_thread.h b/chromium/content/gpu/gpu_watchdog_thread.h
index 4370d831168..fb95eeee0a2 100644
--- a/chromium/content/gpu/gpu_watchdog_thread.h
+++ b/chromium/content/gpu/gpu_watchdog_thread.h
@@ -13,7 +13,7 @@
#include "base/threading/thread.h"
#include "base/time/time.h"
#include "build/build_config.h"
-#include "content/common/gpu/gpu_watchdog.h"
+#include "gpu/ipc/service/gpu_watchdog.h"
#include "ui/gfx/native_widget_types.h"
#if defined(USE_X11)
@@ -23,8 +23,7 @@ extern "C" {
}
#include <sys/poll.h>
#include "ui/base/x/x11_util.h"
-#include "ui/gfx/x/x11_types.h"
-
+#include "ui/gfx/x/x11_types.h" // nogncheck
#endif
namespace content {
@@ -32,7 +31,7 @@ namespace content {
// A thread that intermitently sends tasks to a group of watched message loops
// and deliberately crashes if one of them does not respond after a timeout.
class GpuWatchdogThread : public base::Thread,
- public GpuWatchdog,
+ public gpu::GpuWatchdog,
public base::PowerObserver,
public base::RefCountedThreadSafe<GpuWatchdogThread> {
public:
@@ -42,7 +41,7 @@ class GpuWatchdogThread : public base::Thread,
bool armed() const { return armed_; }
void PostAcknowledge();
- // Implement GpuWatchdog.
+ // Implement gpu::GpuWatchdog.
void CheckArmed() override;
// Must be called after a PowerMonitor has been created. Can be called from
@@ -97,9 +96,21 @@ class GpuWatchdogThread : public base::Thread,
volatile bool armed_;
GpuWatchdogTaskObserver task_observer_;
+ // True if the watchdog should wait for a certain amount of CPU to be used
+ // before killing the process.
+ bool use_thread_cpu_time_;
+
+ // The number of consecutive acknowledgements that had a latency less than
+ // 50ms.
+ int responsive_acknowledge_count_;
+
#if defined(OS_WIN)
void* watched_thread_handle_;
base::TimeDelta arm_cpu_time_;
+
+ // This measures the time that the system has been running, in units of 100
+ // ns.
+ ULONGLONG arm_interrupt_time_;
#endif
// Time after which it's assumed that the computer has been suspended since
@@ -108,6 +119,10 @@ class GpuWatchdogThread : public base::Thread,
bool suspended_;
+ // This is the time the last check was sent.
+ base::Time check_time_;
+ base::TimeTicks check_timeticks_;
+
#if defined(OS_CHROMEOS)
FILE* tty_file_;
#endif
diff --git a/chromium/content/gpu/in_process_gpu_thread.cc b/chromium/content/gpu/in_process_gpu_thread.cc
index 59a4f487e59..cb1c880df29 100644
--- a/chromium/content/gpu/in_process_gpu_thread.cc
+++ b/chromium/content/gpu/in_process_gpu_thread.cc
@@ -6,10 +6,11 @@
#include "base/time/time.h"
#include "build/build_config.h"
-#include "content/common/gpu/gpu_memory_buffer_factory.h"
#include "content/gpu/gpu_child_thread.h"
#include "content/gpu/gpu_process.h"
#include "gpu/command_buffer/service/sync_point_manager.h"
+#include "gpu/ipc/common/gpu_memory_buffer_support.h"
+#include "gpu/ipc/service/gpu_memory_buffer_factory.h"
#if defined(OS_ANDROID)
#include "base/android/jni_android.h"
@@ -19,15 +20,17 @@ namespace content {
InProcessGpuThread::InProcessGpuThread(
const InProcessChildThreadParams& params,
+ const gpu::GpuPreferences& gpu_preferences,
gpu::SyncPointManager* sync_point_manager_override)
: base::Thread("Chrome_InProcGpuThread"),
params_(params),
gpu_process_(NULL),
+ gpu_preferences_(gpu_preferences),
sync_point_manager_override_(sync_point_manager_override),
gpu_memory_buffer_factory_(
- GpuMemoryBufferFactory::GetNativeType() != gfx::EMPTY_BUFFER
- ? GpuMemoryBufferFactory::CreateNativeType()
- : nullptr) {
+ gpu::GetNativeGpuMemoryBufferType() != gfx::EMPTY_BUFFER
+ ? gpu::GpuMemoryBufferFactory::CreateNativeType()
+ : nullptr) {
if (!sync_point_manager_override_) {
sync_point_manager_.reset(new gpu::SyncPointManager(false));
sync_point_manager_override_ = sync_point_manager_.get();
@@ -39,20 +42,25 @@ InProcessGpuThread::~InProcessGpuThread() {
}
void InProcessGpuThread::Init() {
+ base::ThreadPriority io_thread_priority = base::ThreadPriority::NORMAL;
+
+#if defined(OS_ANDROID)
// Call AttachCurrentThreadWithName, before any other AttachCurrentThread()
// calls. The latter causes Java VM to assign Thread-??? to the thread name.
// Please note calls to AttachCurrentThreadWithName after AttachCurrentThread
// will not change the thread name kept in Java VM.
-#if defined(OS_ANDROID)
base::android::AttachCurrentThreadWithName(thread_name());
+ // Up the priority of the |io_thread_| on Android.
+ io_thread_priority = base::ThreadPriority::DISPLAY;
#endif
- gpu_process_ = new GpuProcess();
+ gpu_process_ = new GpuProcess(io_thread_priority);
// The process object takes ownership of the thread object, so do not
// save and delete the pointer.
GpuChildThread* child_thread = new GpuChildThread(
- params_, gpu_memory_buffer_factory_.get(), sync_point_manager_override_);
+ gpu_preferences_, params_, gpu_memory_buffer_factory_.get(),
+ sync_point_manager_override_);
// Since we are in the browser process, use the thread start time as the
// process start time.
@@ -67,8 +75,10 @@ void InProcessGpuThread::CleanUp() {
}
base::Thread* CreateInProcessGpuThread(
- const InProcessChildThreadParams& params) {
- return new InProcessGpuThread(params, nullptr);
+ const InProcessChildThreadParams& params,
+ const gpu::GpuPreferences& gpu_preferences) {
+ return new InProcessGpuThread(
+ params, gpu_preferences, nullptr);
}
} // namespace content
diff --git a/chromium/content/gpu/in_process_gpu_thread.h b/chromium/content/gpu/in_process_gpu_thread.h
index 49eda00efaf..18871270927 100644
--- a/chromium/content/gpu/in_process_gpu_thread.h
+++ b/chromium/content/gpu/in_process_gpu_thread.h
@@ -6,17 +6,20 @@
#define CONTENT_GPU_IN_PROCESS_GPU_THREAD_H_
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/threading/thread.h"
#include "content/common/content_export.h"
#include "content/common/in_process_child_thread_params.h"
+#include "gpu/command_buffer/service/gpu_preferences.h"
namespace gpu {
+class GpuMemoryBufferFactory;
class SyncPointManager;
+struct GpuPreferences;
}
namespace content {
-class GpuMemoryBufferFactory;
class GpuProcess;
// This class creates a GPU thread (instead of a GPU process), when running
@@ -24,6 +27,7 @@ class GpuProcess;
class InProcessGpuThread : public base::Thread {
public:
InProcessGpuThread(const InProcessChildThreadParams& params,
+ const gpu::GpuPreferences& gpu_preferences,
gpu::SyncPointManager* sync_point_manager_override);
~InProcessGpuThread() override;
@@ -37,19 +41,22 @@ class InProcessGpuThread : public base::Thread {
// Deleted in CleanUp() on the gpu thread, so don't use smart pointers.
GpuProcess* gpu_process_;
+ const gpu::GpuPreferences gpu_preferences_;
+
// Can be null if overridden.
scoped_ptr<gpu::SyncPointManager> sync_point_manager_;
// Non-owning.
gpu::SyncPointManager* sync_point_manager_override_;
- scoped_ptr<GpuMemoryBufferFactory> gpu_memory_buffer_factory_;
+ scoped_ptr<gpu::GpuMemoryBufferFactory> gpu_memory_buffer_factory_;
DISALLOW_COPY_AND_ASSIGN(InProcessGpuThread);
};
CONTENT_EXPORT base::Thread* CreateInProcessGpuThread(
- const InProcessChildThreadParams& params);
+ const InProcessChildThreadParams& params,
+ const gpu::GpuPreferences& gpu_preferences);
} // namespace content
diff --git a/chromium/content/plugin/BUILD.gn b/chromium/content/plugin/BUILD.gn
deleted file mode 100644
index 6e87a128b73..00000000000
--- a/chromium/content/plugin/BUILD.gn
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/config/features.gni")
-
-# This is the NPAPI plugin process. It isn't used on Linux.
-if (enable_plugins && !is_linux) {
- source_set("plugin") {
- # Only the public target should depend on this. All other targets (even
- # internal content ones) should depend on the public one.
- visibility = [ "//content/public/plugin:plugin_sources" ]
-
- sources = [
- "plugin_channel.cc",
- "plugin_channel.h",
- "plugin_interpose_util_mac.h",
- "plugin_interpose_util_mac.mm",
- "plugin_main.cc",
- "plugin_main_mac.mm",
- "plugin_thread.cc",
- "plugin_thread.h",
- "webplugin_accelerated_surface_proxy_mac.cc",
- "webplugin_accelerated_surface_proxy_mac.h",
- "webplugin_delegate_stub.cc",
- "webplugin_delegate_stub.h",
- "webplugin_proxy.cc",
- "webplugin_proxy.h",
- ]
-
- configs += [ "//content:content_implementation" ]
-
- deps = [
- "//content:export",
- "//content/public/common:common_sources",
- "//mojo/shell/public/interfaces",
- "//skia",
- "//third_party/WebKit/public:blink",
- "//third_party/npapi",
- ]
- }
-} else {
- # This way it can be unconditionally depended on.
- group("plugin") {
- }
-}
diff --git a/chromium/content/plugin/DEPS b/chromium/content/plugin/DEPS
deleted file mode 100644
index 9fc12edd0d2..00000000000
--- a/chromium/content/plugin/DEPS
+++ /dev/null
@@ -1,9 +0,0 @@
-include_rules = [
- "-chrome",
- "+content/public/plugin",
- "+content/child",
- "+sandbox/win/src",
- "+skia/ext",
- "+third_party/npapi",
-]
-
diff --git a/chromium/content/plugin/OWNERS b/chromium/content/plugin/OWNERS
deleted file mode 100644
index 10dfbb78ad9..00000000000
--- a/chromium/content/plugin/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-ananta@chromium.org
-piman@chromium.org
-stuartmorgan@chromium.org
diff --git a/chromium/content/plugin/plugin_channel.cc b/chromium/content/plugin/plugin_channel.cc
deleted file mode 100644
index 6ec87857657..00000000000
--- a/chromium/content/plugin/plugin_channel.cc
+++ /dev/null
@@ -1,331 +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/plugin/plugin_channel.h"
-
-#include <stddef.h>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/process/process_handle.h"
-#include "base/strings/string_util.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
-#include "build/build_config.h"
-#include "content/child/child_process.h"
-#include "content/child/npapi/plugin_instance.h"
-#include "content/child/npapi/webplugin_delegate_impl.h"
-#include "content/child/plugin_messages.h"
-#include "content/common/plugin_process_messages.h"
-#include "content/plugin/plugin_thread.h"
-#include "content/plugin/webplugin_delegate_stub.h"
-#include "content/plugin/webplugin_proxy.h"
-#include "content/public/common/content_switches.h"
-#include "ipc/message_filter.h"
-
-#if defined(OS_POSIX)
-#include "ipc/ipc_channel_posix.h"
-#endif
-
-namespace content {
-
-namespace {
-
-// How long we wait before releasing the plugin process.
-const int kPluginReleaseTimeMinutes = 5;
-
-} // namespace
-
-// If a sync call to the renderer results in a modal dialog, we need to have a
-// way to know so that we can run a nested message loop to simulate what would
-// happen in a single process browser and avoid deadlock.
-class PluginChannel::MessageFilter : public IPC::MessageFilter {
- public:
- MessageFilter() : sender_(NULL) { }
-
- base::WaitableEvent* GetModalDialogEvent(int render_view_id) {
- base::AutoLock auto_lock(modal_dialog_event_map_lock_);
- if (!modal_dialog_event_map_.count(render_view_id)) {
- NOTREACHED();
- return NULL;
- }
-
- return modal_dialog_event_map_[render_view_id].event;
- }
-
- // Decrement the ref count associated with the modal dialog event for the
- // given tab.
- void ReleaseModalDialogEvent(int render_view_id) {
- base::AutoLock auto_lock(modal_dialog_event_map_lock_);
- if (!modal_dialog_event_map_.count(render_view_id)) {
- NOTREACHED();
- return;
- }
-
- if (--(modal_dialog_event_map_[render_view_id].refcount))
- return;
-
- // Delete the event when the stack unwinds as it could be in use now.
- base::MessageLoop::current()->DeleteSoon(
- FROM_HERE, modal_dialog_event_map_[render_view_id].event);
- modal_dialog_event_map_.erase(render_view_id);
- }
-
- bool Send(IPC::Message* message) {
- // Need this function for the IPC_MESSAGE_HANDLER_DELAY_REPLY macro.
- return sender_->Send(message);
- }
-
- // IPC::MessageFilter:
- void OnFilterAdded(IPC::Sender* sender) override { sender_ = sender; }
-
- bool OnMessageReceived(const IPC::Message& message) override {
- IPC_BEGIN_MESSAGE_MAP(PluginChannel::MessageFilter, message)
- IPC_MESSAGE_HANDLER_DELAY_REPLY(PluginMsg_Init, OnInit)
- IPC_MESSAGE_HANDLER(PluginMsg_SignalModalDialogEvent,
- OnSignalModalDialogEvent)
- IPC_MESSAGE_HANDLER(PluginMsg_ResetModalDialogEvent,
- OnResetModalDialogEvent)
- IPC_END_MESSAGE_MAP()
- return message.type() == PluginMsg_SignalModalDialogEvent::ID ||
- message.type() == PluginMsg_ResetModalDialogEvent::ID;
- }
-
- protected:
- ~MessageFilter() override {
- // Clean up in case of renderer crash.
- for (ModalDialogEventMap::iterator i = modal_dialog_event_map_.begin();
- i != modal_dialog_event_map_.end(); ++i) {
- delete i->second.event;
- }
- }
-
- private:
- void OnInit(const PluginMsg_Init_Params& params, IPC::Message* reply_msg) {
- base::AutoLock auto_lock(modal_dialog_event_map_lock_);
- if (modal_dialog_event_map_.count(params.host_render_view_routing_id)) {
- modal_dialog_event_map_[params.host_render_view_routing_id].refcount++;
- return;
- }
-
- WaitableEventWrapper wrapper;
- wrapper.event = new base::WaitableEvent(true, false);
- wrapper.refcount = 1;
- modal_dialog_event_map_[params.host_render_view_routing_id] = wrapper;
- }
-
- void OnSignalModalDialogEvent(int render_view_id) {
- base::AutoLock auto_lock(modal_dialog_event_map_lock_);
- if (modal_dialog_event_map_.count(render_view_id))
- modal_dialog_event_map_[render_view_id].event->Signal();
- }
-
- void OnResetModalDialogEvent(int render_view_id) {
- base::AutoLock auto_lock(modal_dialog_event_map_lock_);
- if (modal_dialog_event_map_.count(render_view_id))
- modal_dialog_event_map_[render_view_id].event->Reset();
- }
-
- struct WaitableEventWrapper {
- base::WaitableEvent* event;
- int refcount; // There could be multiple plugin instances per tab.
- };
- typedef std::map<int, WaitableEventWrapper> ModalDialogEventMap;
- ModalDialogEventMap modal_dialog_event_map_;
- base::Lock modal_dialog_event_map_lock_;
-
- IPC::Sender* sender_;
-};
-
-PluginChannel* PluginChannel::GetPluginChannel(
- int renderer_id,
- base::SingleThreadTaskRunner* ipc_task_runner) {
- // Map renderer ID to a (single) channel to that process.
- std::string channel_key = base::StringPrintf(
- "%d.r%d", base::GetCurrentProcId(), renderer_id);
-
- PluginChannel* channel =
- static_cast<PluginChannel*>(NPChannelBase::GetChannel(
- channel_key, IPC::Channel::MODE_SERVER, ClassFactory, ipc_task_runner,
- false, ChildProcess::current()->GetShutDownEvent()));
-
- if (channel)
- channel->renderer_id_ = renderer_id;
-
- return channel;
-}
-
-// static
-void PluginChannel::NotifyRenderersOfPendingShutdown() {
- Broadcast(new PluginHostMsg_PluginShuttingDown());
-}
-
-bool PluginChannel::Send(IPC::Message* msg) {
- in_send_++;
- if (log_messages_) {
- VLOG(1) << "sending message @" << msg << " on channel @" << this
- << " with type " << msg->type();
- }
- bool result = NPChannelBase::Send(msg);
- in_send_--;
- return result;
-}
-
-bool PluginChannel::OnMessageReceived(const IPC::Message& msg) {
- if (log_messages_) {
- VLOG(1) << "received message @" << &msg << " on channel @" << this
- << " with type " << msg.type();
- }
- return NPChannelBase::OnMessageReceived(msg);
-}
-
-void PluginChannel::OnChannelError() {
- NPChannelBase::OnChannelError();
- CleanUp();
-}
-
-int PluginChannel::GenerateRouteID() {
- static int last_id = 0;
- return ++last_id;
-}
-
-base::WaitableEvent* PluginChannel::GetModalDialogEvent(int render_view_id) {
- return filter_->GetModalDialogEvent(render_view_id);
-}
-
-PluginChannel::~PluginChannel() {
- PluginThread::current()->Send(new PluginProcessHostMsg_ChannelDestroyed(
- renderer_id_));
- process_ref_.ReleaseWithDelay(
- base::TimeDelta::FromMinutes(kPluginReleaseTimeMinutes));
-}
-
-void PluginChannel::CleanUp() {
- // We need to clean up the stubs so that they call NPPDestroy. This will
- // also lead to them releasing their reference on this object so that it can
- // be deleted.
- for (size_t i = 0; i < plugin_stubs_.size(); ++i)
- RemoveRoute(plugin_stubs_[i]->instance_id());
-
- // Need to addref this object temporarily because otherwise removing the last
- // stub will cause the destructor of this object to be called, however at
- // that point plugin_stubs_ will have one element and its destructor will be
- // called twice.
- scoped_refptr<PluginChannel> me(this);
-
- while (!plugin_stubs_.empty()) {
- // Separate vector::erase and ~WebPluginDelegateStub.
- // See https://code.google.com/p/chromium/issues/detail?id=314088
- scoped_refptr<WebPluginDelegateStub> stub = plugin_stubs_[0];
- plugin_stubs_.erase(plugin_stubs_.begin());
- }
-}
-
-bool PluginChannel::Init(base::SingleThreadTaskRunner* ipc_task_runner,
- bool create_pipe_now,
- base::WaitableEvent* shutdown_event) {
- if (!NPChannelBase::Init(ipc_task_runner, create_pipe_now, shutdown_event))
- return false;
-
- channel_->AddFilter(filter_.get());
- return true;
-}
-
-PluginChannel::PluginChannel()
- : renderer_id_(-1),
- in_send_(0),
- incognito_(false),
- filter_(new MessageFilter()),
- npp_(new struct _NPP) {
- set_send_unblocking_only_during_unblock_dispatch();
- const base::CommandLine* command_line =
- base::CommandLine::ForCurrentProcess();
- log_messages_ = command_line->HasSwitch(switches::kLogPluginMessages);
-
- // Register |npp_| as the default owner for any object we receive via IPC.
- SetDefaultNPObjectOwner(npp_.get());
-}
-
-bool PluginChannel::OnControlMessageReceived(const IPC::Message& msg) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(PluginChannel, msg)
- IPC_MESSAGE_HANDLER(PluginMsg_CreateInstance, OnCreateInstance)
- IPC_MESSAGE_HANDLER_DELAY_REPLY(PluginMsg_DestroyInstance,
- OnDestroyInstance)
- IPC_MESSAGE_HANDLER(PluginMsg_GenerateRouteID, OnGenerateRouteID)
- IPC_MESSAGE_HANDLER(PluginProcessMsg_ClearSiteData, OnClearSiteData)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- DCHECK(handled);
- return handled;
-}
-
-void PluginChannel::OnCreateInstance(const std::string& mime_type,
- int* instance_id) {
- *instance_id = GenerateRouteID();
- scoped_refptr<WebPluginDelegateStub> stub(new WebPluginDelegateStub(
- mime_type, *instance_id, this));
- AddRoute(*instance_id, stub.get(), NULL);
- plugin_stubs_.push_back(stub);
-}
-
-void PluginChannel::OnDestroyInstance(int instance_id,
- IPC::Message* reply_msg) {
- for (size_t i = 0; i < plugin_stubs_.size(); ++i) {
- if (plugin_stubs_[i]->instance_id() == instance_id) {
- scoped_refptr<MessageFilter> filter(filter_);
- int render_view_id =
- plugin_stubs_[i]->webplugin()->host_render_view_routing_id();
- // Separate vector::erase and ~WebPluginDelegateStub.
- // See https://code.google.com/p/chromium/issues/detail?id=314088
- scoped_refptr<WebPluginDelegateStub> stub = plugin_stubs_[i];
- plugin_stubs_.erase(plugin_stubs_.begin() + i);
- stub = NULL;
-
- Send(reply_msg);
- RemoveRoute(instance_id);
- // NOTE: *this* might be deleted as a result of calling RemoveRoute.
- // Don't release the modal dialog event right away, but do it after the
- // stack unwinds since the plugin can be destroyed later if it's in use
- // right now.
- base::MessageLoop::current()->PostNonNestableTask(
- FROM_HERE,
- base::Bind(&MessageFilter::ReleaseModalDialogEvent,
- filter.get(),
- render_view_id));
- return;
- }
- }
-
- NOTREACHED() << "Couldn't find WebPluginDelegateStub to destroy";
-}
-
-void PluginChannel::OnGenerateRouteID(int* route_id) {
- *route_id = GenerateRouteID();
-}
-
-void PluginChannel::OnClearSiteData(const std::string& site,
- uint64_t flags,
- uint64_t max_age) {
- bool success = false;
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- base::FilePath path = command_line->GetSwitchValuePath(switches::kPluginPath);
- scoped_refptr<PluginLib> plugin_lib(PluginLib::CreatePluginLib(path));
- if (plugin_lib.get()) {
- NPError err = plugin_lib->NP_Initialize();
- if (err == NPERR_NO_ERROR) {
- const char* site_str = site.empty() ? NULL : site.c_str();
- err = plugin_lib->NP_ClearSiteData(site_str, flags, max_age);
- std::string site_name =
- site.empty() ? "NULL"
- : base::StringPrintf("\"%s\"", site_str);
- VLOG(1) << "NPP_ClearSiteData(" << site_name << ", " << flags << ", "
- << max_age << ") returned " << err;
- success = (err == NPERR_NO_ERROR);
- }
- }
- Send(new PluginProcessHostMsg_ClearSiteDataResult(success));
-}
-
-} // namespace content
diff --git a/chromium/content/plugin/plugin_channel.h b/chromium/content/plugin/plugin_channel.h
deleted file mode 100644
index 1f43f1ef785..00000000000
--- a/chromium/content/plugin/plugin_channel.h
+++ /dev/null
@@ -1,111 +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_PLUGIN_PLUGIN_CHANNEL_H_
-#define CONTENT_PLUGIN_PLUGIN_CHANNEL_H_
-
-#include <stdint.h>
-
-#include <vector>
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/process/process.h"
-#include "build/build_config.h"
-#include "content/child/npapi/np_channel_base.h"
-#include "content/child/scoped_child_process_reference.h"
-#include "content/plugin/webplugin_delegate_stub.h"
-
-namespace base {
-class WaitableEvent;
-}
-
-namespace content {
-
-// Encapsulates an IPC channel between the plugin process and one renderer
-// process. On the renderer side there's a corresponding PluginChannelHost.
-class PluginChannel : public NPChannelBase {
- public:
- // Get a new PluginChannel object for the current process to talk to the
- // given renderer process. The renderer ID is an opaque unique ID generated
- // by the browser.
- static PluginChannel* GetPluginChannel(
- int renderer_id,
- base::SingleThreadTaskRunner* ipc_task_runner);
-
- // Send a message to all renderers that the process is going to shutdown.
- static void NotifyRenderersOfPendingShutdown();
-
- // IPC::Listener:
- bool Send(IPC::Message* msg) override;
- bool OnMessageReceived(const IPC::Message& message) override;
- void OnChannelError() override;
-
- int renderer_id() { return renderer_id_; }
-
- int GenerateRouteID() override;
-
- // Returns the event that's set when a call to the renderer causes a modal
- // dialog to come up.
- base::WaitableEvent* GetModalDialogEvent(int render_view_id) override;
-
- bool in_send() { return in_send_ != 0; }
-
- bool incognito() { return incognito_; }
- void set_incognito(bool value) { incognito_ = value; }
-
-#if defined(OS_POSIX)
- base::ScopedFD TakeRendererFileDescriptor() {
- return channel_->TakeClientFileDescriptor();
- }
-#endif
-
- protected:
- ~PluginChannel() override;
-
- // NPChannelBase::
- void CleanUp() override;
- bool Init(base::SingleThreadTaskRunner* ipc_task_runner,
- bool create_pipe_now,
- base::WaitableEvent* shutdown_event) override;
-
- private:
- class MessageFilter;
-
- // Called on the plugin thread
- PluginChannel();
-
- bool OnControlMessageReceived(const IPC::Message& msg) override;
-
- static NPChannelBase* ClassFactory() { return new PluginChannel(); }
-
- void OnCreateInstance(const std::string& mime_type, int* instance_id);
- void OnDestroyInstance(int instance_id, IPC::Message* reply_msg);
- void OnGenerateRouteID(int* route_id);
- void OnClearSiteData(const std::string& site,
- uint64_t flags,
- uint64_t max_age);
- void OnDidAbortLoading(int render_view_id);
-
- std::vector<scoped_refptr<WebPluginDelegateStub> > plugin_stubs_;
-
- ScopedChildProcessReference process_ref_;
-
- // The id of the renderer who is on the other side of the channel.
- int renderer_id_;
-
- int in_send_; // Tracks if we're in a Send call.
- bool log_messages_; // True if we should log sent and received messages.
- bool incognito_; // True if the renderer is in incognito mode.
- scoped_refptr<MessageFilter> filter_; // Handles the modal dialog events.
-
- // Dummy NPP value used in the plugin process to represent entities other
- // that other plugin instances for the purpose of object ownership tracking.
- scoped_ptr<struct _NPP> npp_;
-
- DISALLOW_COPY_AND_ASSIGN(PluginChannel);
-};
-
-} // namespace content
-
-#endif // CONTENT_PLUGIN_PLUGIN_CHANNEL_H_
diff --git a/chromium/content/plugin/plugin_interpose_util_mac.h b/chromium/content/plugin/plugin_interpose_util_mac.h
deleted file mode 100644
index ce8effb33f9..00000000000
--- a/chromium/content/plugin/plugin_interpose_util_mac.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_PLUGIN_PLUGIN_INTERPOSE_UTIL_MAC_H_
-#define CONTENT_PLUGIN_PLUGIN_INTERPOSE_UTIL_MAC_H_
-
-namespace mac_plugin_interposing {
-
-// Swizzles methods we need to watch in order to manage process and window
-// focus correctly.
-void SetUpCocoaInterposing();
-
-} // namespace MacPluginInterpose
-
-#endif // CONTENT_PLUGIN_PLUGIN_INTERPOSE_UTIL_MAC_H_
diff --git a/chromium/content/plugin/plugin_interpose_util_mac.mm b/chromium/content/plugin/plugin_interpose_util_mac.mm
deleted file mode 100644
index 678fea294fe..00000000000
--- a/chromium/content/plugin/plugin_interpose_util_mac.mm
+++ /dev/null
@@ -1,261 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/plugin/plugin_interpose_util_mac.h"
-
-#import <AppKit/AppKit.h>
-#import <objc/runtime.h>
-#include <stdint.h>
-
-#include "content/child/npapi/webplugin_delegate_impl.h"
-#include "content/common/plugin_process_messages.h"
-#include "content/plugin/plugin_thread.h"
-
-using content::PluginThread;
-
-namespace {
-
-// Brings the plugin process to the front so that the user can see its windows.
-void SwitchToPluginProcess() {
- ProcessSerialNumber this_process, front_process;
- if ((GetCurrentProcess(&this_process) != noErr) ||
- (GetFrontProcess(&front_process) != noErr)) {
- return;
- }
-
- Boolean matched = false;
- if ((SameProcess(&this_process, &front_process, &matched) == noErr) &&
- !matched) {
- SetFrontProcess(&this_process);
- }
-}
-
-// Sends a message to the browser process to inform it that the given window
-// has been shown.
-void NotifyBrowserOfPluginShowWindow(uint32_t window_id,
- CGRect bounds,
- bool modal) {
- PluginThread* plugin_thread = PluginThread::current();
- if (plugin_thread) {
- gfx::Rect window_bounds(bounds);
- plugin_thread->Send(
- new PluginProcessHostMsg_PluginShowWindow(window_id, window_bounds,
- modal));
- }
-}
-
-// Sends a message to the browser process to inform it that the given window
-// has been hidden, and switches focus back to the browser process if there are
-// no remaining plugin windows.
-void NotifyBrowserOfPluginHideWindow(uint32_t window_id, CGRect bounds) {
- PluginThread* plugin_thread = PluginThread::current();
- if (plugin_thread) {
- gfx::Rect window_bounds(bounds);
- plugin_thread->Send(
- new PluginProcessHostMsg_PluginHideWindow(window_id, window_bounds));
- }
-}
-
-// Informs the host that the plugin has changed the cursor visibility.
-void NotifyPluginOfSetCursorVisibility(bool visibility) {
- PluginThread* plugin_thread = PluginThread::current();
- if (plugin_thread) {
- plugin_thread->Send(
- new PluginProcessHostMsg_PluginSetCursorVisibility(visibility));
- }
-}
-
-struct WindowInfo {
- uint32_t window_id;
- CGRect bounds;
- WindowInfo(NSWindow* window) {
- NSInteger window_num = [window windowNumber];
- window_id = window_num > 0 ? window_num : 0;
- bounds = NSRectToCGRect([window frame]);
- }
-};
-
-void OnPluginWindowClosed(const WindowInfo& window_info) {
- if (window_info.window_id == 0)
- return;
- NotifyBrowserOfPluginHideWindow(window_info.window_id, window_info.bounds);
-}
-
-BOOL g_waiting_for_window_number = NO;
-
-void OnPluginWindowShown(const WindowInfo& window_info, BOOL is_modal) {
- // The window id is 0 if it has never been shown (including while it is the
- // process of being shown for the first time); when that happens, we'll catch
- // it in _setWindowNumber instead.
- static BOOL s_pending_display_is_modal = NO;
- if (window_info.window_id == 0) {
- g_waiting_for_window_number = YES;
- if (is_modal)
- s_pending_display_is_modal = YES;
- return;
- }
- g_waiting_for_window_number = NO;
- if (s_pending_display_is_modal) {
- is_modal = YES;
- s_pending_display_is_modal = NO;
- }
- NotifyBrowserOfPluginShowWindow(window_info.window_id, window_info.bounds,
- is_modal);
-}
-
-} // namespace
-
-@interface NSWindow (ChromePluginUtilities)
-// Returns YES if the window is visible and actually on the screen.
-- (BOOL)chromePlugin_isWindowOnScreen;
-@end
-
-@implementation NSWindow (ChromePluginUtilities)
-
-- (BOOL)chromePlugin_isWindowOnScreen {
- if (![self isVisible])
- return NO;
- NSRect window_frame = [self frame];
- for (NSScreen* screen in [NSScreen screens]) {
- if (NSIntersectsRect(window_frame, [screen frame]))
- return YES;
- }
- return NO;
-}
-
-@end
-
-@interface NSWindow (ChromePluginInterposing)
-- (void)chromePlugin_orderOut:(id)sender;
-- (void)chromePlugin_orderFront:(id)sender;
-- (void)chromePlugin_makeKeyAndOrderFront:(id)sender;
-- (void)chromePlugin_setWindowNumber:(NSInteger)num;
-@end
-
-@implementation NSWindow (ChromePluginInterposing)
-
-- (void)chromePlugin_orderOut:(id)sender {
- WindowInfo window_info(self);
- [self chromePlugin_orderOut:sender];
- OnPluginWindowClosed(window_info);
-}
-
-- (void)chromePlugin_orderFront:(id)sender {
- [self chromePlugin_orderFront:sender];
- if ([self chromePlugin_isWindowOnScreen])
- SwitchToPluginProcess();
- OnPluginWindowShown(WindowInfo(self), NO);
-}
-
-- (void)chromePlugin_makeKeyAndOrderFront:(id)sender {
- [self chromePlugin_makeKeyAndOrderFront:sender];
- if ([self chromePlugin_isWindowOnScreen])
- SwitchToPluginProcess();
- OnPluginWindowShown(WindowInfo(self), NO);
-}
-
-- (void)chromePlugin_setWindowNumber:(NSInteger)num {
- if (!g_waiting_for_window_number || num <= 0) {
- [self chromePlugin_setWindowNumber:num];
- return;
- }
- SwitchToPluginProcess();
- [self chromePlugin_setWindowNumber:num];
- OnPluginWindowShown(WindowInfo(self), NO);
-}
-
-@end
-
-@interface NSApplication (ChromePluginInterposing)
-- (NSInteger)chromePlugin_runModalForWindow:(NSWindow*)window;
-@end
-
-@implementation NSApplication (ChromePluginInterposing)
-
-- (NSInteger)chromePlugin_runModalForWindow:(NSWindow*)window {
- SwitchToPluginProcess();
- // This is out-of-order relative to the other calls, but runModalForWindow:
- // won't return until the window closes, and the order only matters for
- // full-screen windows.
- OnPluginWindowShown(WindowInfo(window), YES);
- return [self chromePlugin_runModalForWindow:window];
-}
-
-@end
-
-@interface NSCursor (ChromePluginInterposing)
-- (void)chromePlugin_set;
-+ (void)chromePlugin_hide;
-+ (void)chromePlugin_unhide;
-@end
-
-@implementation NSCursor (ChromePluginInterposing)
-
-- (void)chromePlugin_set {
- content::WebPluginDelegateImpl* delegate =
- content::WebPluginDelegateImpl::GetActiveDelegate();
- if (delegate) {
- delegate->SetNSCursor(self);
- return;
- }
- [self chromePlugin_set];
-}
-
-+ (void)chromePlugin_hide {
- NotifyPluginOfSetCursorVisibility(false);
-}
-
-+ (void)chromePlugin_unhide {
- NotifyPluginOfSetCursorVisibility(true);
-}
-
-@end
-
-#pragma mark -
-
-static void ExchangeMethods(Class target_class,
- BOOL class_method,
- SEL original,
- SEL replacement) {
- Method m1;
- Method m2;
- if (class_method) {
- m1 = class_getClassMethod(target_class, original);
- m2 = class_getClassMethod(target_class, replacement);
- } else {
- m1 = class_getInstanceMethod(target_class, original);
- m2 = class_getInstanceMethod(target_class, replacement);
- }
- if (m1 && m2)
- method_exchangeImplementations(m1, m2);
- else
- NOTREACHED() << "Cocoa swizzling failed";
-}
-
-namespace mac_plugin_interposing {
-
-void SetUpCocoaInterposing() {
- Class nswindow_class = [NSWindow class];
- ExchangeMethods(nswindow_class, NO, @selector(orderOut:),
- @selector(chromePlugin_orderOut:));
- ExchangeMethods(nswindow_class, NO, @selector(orderFront:),
- @selector(chromePlugin_orderFront:));
- ExchangeMethods(nswindow_class, NO, @selector(makeKeyAndOrderFront:),
- @selector(chromePlugin_makeKeyAndOrderFront:));
- ExchangeMethods(nswindow_class, NO, @selector(_setWindowNumber:),
- @selector(chromePlugin_setWindowNumber:));
-
- ExchangeMethods([NSApplication class], NO, @selector(runModalForWindow:),
- @selector(chromePlugin_runModalForWindow:));
-
- Class nscursor_class = [NSCursor class];
- ExchangeMethods(nscursor_class, NO, @selector(set),
- @selector(chromePlugin_set));
- ExchangeMethods(nscursor_class, YES, @selector(hide),
- @selector(chromePlugin_hide));
- ExchangeMethods(nscursor_class, YES, @selector(unhide),
- @selector(chromePlugin_unhide));
-}
-
-} // namespace mac_plugin_interposing
diff --git a/chromium/content/plugin/plugin_main.cc b/chromium/content/plugin/plugin_main.cc
deleted file mode 100644
index 2cef8973c86..00000000000
--- a/chromium/content/plugin/plugin_main.cc
+++ /dev/null
@@ -1,71 +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 "build/build_config.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#endif
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/message_loop/message_loop.h"
-#include "base/strings/string_util.h"
-#include "base/threading/platform_thread.h"
-#include "base/timer/hi_res_timer_manager.h"
-#include "content/child/child_process.h"
-#include "content/common/content_constants_internal.h"
-#include "content/plugin/plugin_thread.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/common/main_function_params.h"
-
-#if defined(OS_WIN)
-#include "base/win/scoped_com_initializer.h"
-#include "content/public/common/injection_test_win.h"
-#include "sandbox/win/src/sandbox.h"
-#elif defined(OS_POSIX) && !defined(OS_MACOSX)
-#include "base/posix/global_descriptors.h"
-#include "ipc/ipc_descriptors.h"
-#endif
-
-namespace content {
-
-#if defined(OS_MACOSX)
-// Initializes the global Cocoa application object.
-void InitializeChromeApplication();
-#endif
-
-// main() routine for running as the plugin process.
-int PluginMain(const MainFunctionParams& parameters) {
- // The main thread of the plugin services UI.
-#if defined(OS_MACOSX)
- InitializeChromeApplication();
-#endif
- base::MessageLoopForUI main_message_loop;
- base::PlatformThread::SetName("CrPluginMain");
- base::trace_event::TraceLog::GetInstance()->SetProcessName("Plugin Process");
- base::trace_event::TraceLog::GetInstance()->SetProcessSortIndex(
- kTraceEventPluginProcessSortIndex);
-
- const base::CommandLine& parsed_command_line = parameters.command_line;
-
-#if defined(OS_WIN)
- base::win::ScopedCOMInitializer com_initializer;
-#endif
-
- if (parsed_command_line.HasSwitch(switches::kPluginStartupDialog)) {
- ChildProcess::WaitForDebugger("Plugin");
- }
-
- {
- ChildProcess plugin_process;
- plugin_process.set_main_thread(new PluginThread());
- base::HighResolutionTimerManager hi_res_timer_manager;
- base::MessageLoop::current()->Run();
- }
-
- return 0;
-}
-
-} // namespace content
diff --git a/chromium/content/plugin/plugin_main_mac.mm b/chromium/content/plugin/plugin_main_mac.mm
deleted file mode 100644
index fddaa59ba13..00000000000
--- a/chromium/content/plugin/plugin_main_mac.mm
+++ /dev/null
@@ -1,16 +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.
-
-#import <AppKit/AppKit.h>
-
-#include "content/plugin/plugin_interpose_util_mac.h"
-
-namespace content {
-
-void InitializeChromeApplication() {
- [NSApplication sharedApplication];
- mac_plugin_interposing::SetUpCocoaInterposing();
-}
-
-} // namespace content
diff --git a/chromium/content/plugin/plugin_thread.cc b/chromium/content/plugin/plugin_thread.cc
deleted file mode 100644
index 76251094fc8..00000000000
--- a/chromium/content/plugin/plugin_thread.cc
+++ /dev/null
@@ -1,160 +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/plugin/plugin_thread.h"
-
-#include "build/build_config.h"
-
-#if defined(OS_MACOSX)
-#include <CoreFoundation/CoreFoundation.h>
-#endif
-
-#include <string>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/lazy_instance.h"
-#include "base/process/process.h"
-#include "base/threading/thread_local.h"
-#include "content/child/blink_platform_impl.h"
-#include "content/child/child_process.h"
-#include "content/child/npapi/npobject_util.h"
-#include "content/child/npapi/plugin_lib.h"
-#include "content/common/plugin_process_messages.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/plugin/content_plugin_client.h"
-#include "third_party/WebKit/public/web/WebKit.h"
-#include "ipc/ipc_channel_handle.h"
-#include "ipc/message_filter.h"
-
-namespace content {
-
-namespace {
-
-class EnsureTerminateMessageFilter : public IPC::MessageFilter {
- public:
- EnsureTerminateMessageFilter() {}
-
- protected:
- ~EnsureTerminateMessageFilter() override {}
-
- // IPC::MessageFilter:
- void OnChannelError() override {
- // How long we wait before forcibly shutting down the process.
- const base::TimeDelta kPluginProcessTerminateTimeout =
- base::TimeDelta::FromSeconds(3);
- // Ensure that we don't wait indefinitely for the plugin to shutdown.
- // as the browser does not terminate plugin processes on shutdown.
- // We achieve this by posting an exit process task on the IO thread.
- base::MessageLoop::current()->PostDelayedTask(
- FROM_HERE,
- base::Bind(&EnsureTerminateMessageFilter::Terminate, this),
- kPluginProcessTerminateTimeout);
- }
-
- private:
- void Terminate() {
- base::Process::Current().Terminate(0, false);
- }
-};
-
-} // namespace
-
-static base::LazyInstance<base::ThreadLocalPointer<PluginThread> > lazy_tls =
- LAZY_INSTANCE_INITIALIZER;
-
-PluginThread::PluginThread()
- : preloaded_plugin_module_(NULL),
- forcefully_terminate_plugin_process_(false) {
- base::FilePath plugin_path =
- base::CommandLine::ForCurrentProcess()->GetSwitchValuePath(
- switches::kPluginPath);
-
- lazy_tls.Pointer()->Set(this);
-
- PatchNPNFunctions();
-
- // Preload the library to avoid loading, unloading then reloading
- preloaded_plugin_module_ = base::LoadNativeLibrary(plugin_path, NULL);
-
- scoped_refptr<PluginLib> plugin(PluginLib::CreatePluginLib(plugin_path));
- if (plugin.get()) {
- plugin->NP_Initialize();
- // For OOP plugins the plugin dll will be unloaded during process shutdown
- // time.
- plugin->set_defer_unload(true);
- }
-
- GetContentClient()->plugin()->PluginProcessStarted(
- plugin.get() ? plugin->plugin_info().name : base::string16());
-
- channel()->AddFilter(new EnsureTerminateMessageFilter());
-
- // This is needed because we call some code which uses Blink strings.
- blink_platform_impl_.reset(new BlinkPlatformImpl);
- blink::initialize(blink_platform_impl_.get());
-}
-
-PluginThread::~PluginThread() {
-}
-
-void PluginThread::SetForcefullyTerminatePluginProcess() {
- forcefully_terminate_plugin_process_ = true;
-}
-
-void PluginThread::Shutdown() {
- ChildThreadImpl::Shutdown();
-
- if (preloaded_plugin_module_) {
- base::UnloadNativeLibrary(preloaded_plugin_module_);
- preloaded_plugin_module_ = NULL;
- }
- NPChannelBase::CleanupChannels();
- PluginLib::UnloadAllPlugins();
-
- if (forcefully_terminate_plugin_process_)
- base::Process::Current().Terminate(0, /* wait= */ false);
-
- lazy_tls.Pointer()->Set(NULL);
-}
-
-PluginThread* PluginThread::current() {
- return lazy_tls.Pointer()->Get();
-}
-
-bool PluginThread::OnControlMessageReceived(const IPC::Message& msg) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(PluginThread, msg)
- IPC_MESSAGE_HANDLER(PluginProcessMsg_CreateChannel, OnCreateChannel)
- IPC_MESSAGE_HANDLER(PluginProcessMsg_NotifyRenderersOfPendingShutdown,
- OnNotifyRenderersOfPendingShutdown)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- return handled;
-}
-
-void PluginThread::OnCreateChannel(int renderer_id,
- bool incognito) {
- scoped_refptr<PluginChannel> channel(PluginChannel::GetPluginChannel(
- renderer_id, ChildProcess::current()->io_task_runner()));
- IPC::ChannelHandle channel_handle;
- if (channel.get()) {
- channel_handle.name = channel->channel_handle().name;
-#if defined(OS_POSIX)
- // On POSIX, pass the renderer-side FD.
- channel_handle.socket =
- base::FileDescriptor(channel->TakeRendererFileDescriptor());
-#endif
- channel->set_incognito(incognito);
- }
-
- Send(new PluginProcessHostMsg_ChannelCreated(channel_handle));
-}
-
-void PluginThread::OnNotifyRenderersOfPendingShutdown() {
- PluginChannel::NotifyRenderersOfPendingShutdown();
-}
-
-} // namespace content
diff --git a/chromium/content/plugin/plugin_thread.h b/chromium/content/plugin/plugin_thread.h
deleted file mode 100644
index b4152d62802..00000000000
--- a/chromium/content/plugin/plugin_thread.h
+++ /dev/null
@@ -1,65 +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_PLUGIN_PLUGIN_THREAD_H_
-#define CONTENT_PLUGIN_PLUGIN_THREAD_H_
-
-#include <stdint.h>
-
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "base/native_library.h"
-#include "build/build_config.h"
-#include "content/child/child_thread_impl.h"
-#include "content/child/npapi/plugin_lib.h"
-#include "content/plugin/plugin_channel.h"
-
-#if defined(OS_POSIX)
-#include "base/file_descriptor_posix.h"
-#endif
-
-namespace content {
-class BlinkPlatformImpl;
-
-// The PluginThread class represents a background thread where plugin instances
-// live. Communication occurs between WebPluginDelegateProxy in the renderer
-// process and WebPluginDelegateStub in this thread through IPC messages.
-class PluginThread : public ChildThreadImpl {
- public:
- PluginThread();
- ~PluginThread() override;
- void Shutdown() override;
-
- // Returns the one plugin thread.
- static PluginThread* current();
-
- // Tells the plugin thread to terminate the process forcefully instead of
- // exiting cleanly.
- void SetForcefullyTerminatePluginProcess();
-
- private:
- bool OnControlMessageReceived(const IPC::Message& msg) override;
-
- // Callback for when a channel has been created.
- void OnCreateChannel(int renderer_id, bool incognito);
- void OnPluginMessage(const std::vector<uint8_t>& data);
- void OnNotifyRenderersOfPendingShutdown();
-#if defined(OS_MACOSX)
- void OnAppActivated();
- void OnPluginFocusNotify(uint32_t instance_id);
-#endif
-
- // The plugin module which is preloaded in Init
- base::NativeLibrary preloaded_plugin_module_;
-
- bool forcefully_terminate_plugin_process_;
-
- scoped_ptr<BlinkPlatformImpl> blink_platform_impl_;
-
- DISALLOW_COPY_AND_ASSIGN(PluginThread);
-};
-
-} // namespace content
-
-#endif // CONTENT_PLUGIN_PLUGIN_THREAD_H_
diff --git a/chromium/content/plugin/webplugin_accelerated_surface_proxy_mac.cc b/chromium/content/plugin/webplugin_accelerated_surface_proxy_mac.cc
deleted file mode 100644
index a790f4702a5..00000000000
--- a/chromium/content/plugin/webplugin_accelerated_surface_proxy_mac.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.
-
-#import <OpenGL/OpenGL.h>
-#include <stdint.h>
-
-#include "content/plugin/webplugin_accelerated_surface_proxy_mac.h"
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "content/plugin/webplugin_proxy.h"
-#include "content/public/common/content_switches.h"
-#include "ui/surface/accelerated_surface_mac.h"
-#include "ui/surface/transport_dib.h"
-
-namespace content {
-
-WebPluginAcceleratedSurfaceProxy* WebPluginAcceleratedSurfaceProxy::Create(
- WebPluginProxy* plugin_proxy,
- gfx::GpuPreference gpu_preference) {
- // This code path shouldn't be taken if CA plugins are disabled
- // because the CA drawing model shouldn't be advertised.
- DCHECK(!base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableCoreAnimationPlugins));
-
- AcceleratedSurface* surface = new AcceleratedSurface;
- // It's possible for OpenGL to fail to initialize (e.g., if an incompatible
- // mode is forced via flags), so handle that gracefully.
- if (!surface->Initialize(NULL, true, gpu_preference)) {
- delete surface;
- return NULL;
- }
-
- return new WebPluginAcceleratedSurfaceProxy(plugin_proxy, surface);
-}
-
-WebPluginAcceleratedSurfaceProxy::WebPluginAcceleratedSurfaceProxy(
- WebPluginProxy* plugin_proxy,
- AcceleratedSurface* surface)
- : plugin_proxy_(plugin_proxy),
- surface_(surface) {
-}
-
-WebPluginAcceleratedSurfaceProxy::~WebPluginAcceleratedSurfaceProxy() {
- if (surface_) {
- surface_->Destroy();
- delete surface_;
- surface_ = NULL;
- }
-}
-
-void WebPluginAcceleratedSurfaceProxy::SetSize(const gfx::Size& size) {
- if (!surface_)
- return;
-
- uint32_t io_surface_id = surface_->SetSurfaceSize(size);
- // If allocation fails for some reason, still inform the plugin proxy.
- plugin_proxy_->AcceleratedPluginAllocatedIOSurface(
- size.width(), size.height(), io_surface_id);
-}
-
-CGLContextObj WebPluginAcceleratedSurfaceProxy::context() {
- return surface_ ? surface_->context() : NULL;
-}
-
-void WebPluginAcceleratedSurfaceProxy::StartDrawing() {
- if (!surface_)
- return;
-
- surface_->MakeCurrent();
- surface_->Clear(gfx::Rect(surface_->GetSize()));
-}
-
-void WebPluginAcceleratedSurfaceProxy::EndDrawing() {
- if (!surface_)
- return;
-
- surface_->SwapBuffers();
- plugin_proxy_->AcceleratedPluginSwappedIOSurface();
-}
-
-} // namespace content
diff --git a/chromium/content/plugin/webplugin_accelerated_surface_proxy_mac.h b/chromium/content/plugin/webplugin_accelerated_surface_proxy_mac.h
deleted file mode 100644
index 6de53788a7c..00000000000
--- a/chromium/content/plugin/webplugin_accelerated_surface_proxy_mac.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_PLUGIN_WEBPLUGIN_ACCELERATED_SURFACE_PROXY_MAC_H_
-#define CONTENT_PLUGIN_WEBPLUGIN_ACCELERATED_SURFACE_PROXY_MAC_H_
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "content/child/npapi/webplugin_accelerated_surface_mac.h"
-#include "ui/gl/gpu_preference.h"
-
-class AcceleratedSurface;
-
-namespace content {
-class WebPluginProxy;
-
-// Out-of-process implementation of WebPluginAcceleratedSurface that proxies
-// calls through a WebPluginProxy.
-class WebPluginAcceleratedSurfaceProxy : public WebPluginAcceleratedSurface {
- public:
- // Creates a new WebPluginAcceleratedSurfaceProxy that uses plugin_proxy
- // to proxy calls. plugin_proxy must outlive this object. Returns NULL if
- // initialization fails.
- static WebPluginAcceleratedSurfaceProxy* Create(
- WebPluginProxy* plugin_proxy,
- gfx::GpuPreference gpu_preference);
-
- ~WebPluginAcceleratedSurfaceProxy() override;
-
- // WebPluginAcceleratedSurface implementation.
- void SetSize(const gfx::Size& size) override;
- CGLContextObj context() override;
- void StartDrawing() override;
- void EndDrawing() override;
-
- private:
- WebPluginAcceleratedSurfaceProxy(WebPluginProxy* plugin_proxy,
- AcceleratedSurface* surface);
-
- WebPluginProxy* plugin_proxy_; // Weak ref.
- AcceleratedSurface* surface_;
-
- DISALLOW_COPY_AND_ASSIGN(WebPluginAcceleratedSurfaceProxy);
-};
-
-} // namespace content
-
-#endif // CONTENT_PLUGIN_WEBPLUGIN_ACCELERATED_SURFACE_PROXY_MAC_H_
diff --git a/chromium/content/plugin/webplugin_delegate_stub.cc b/chromium/content/plugin/webplugin_delegate_stub.cc
deleted file mode 100644
index ba53302e7a0..00000000000
--- a/chromium/content/plugin/webplugin_delegate_stub.cc
+++ /dev/null
@@ -1,352 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/plugin/webplugin_delegate_stub.h"
-
-#include "build/build_config.h"
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/strings/string_number_conversions.h"
-#include "content/child/npapi/plugin_instance.h"
-#include "content/child/npapi/webplugin_delegate_impl.h"
-#include "content/child/npapi/webplugin_resource_client.h"
-#include "content/child/plugin_messages.h"
-#include "content/common/cursors/webcursor.h"
-#include "content/plugin/plugin_channel.h"
-#include "content/plugin/plugin_thread.h"
-#include "content/plugin/webplugin_proxy.h"
-#include "content/public/common/content_client.h"
-#include "content/public/common/content_constants.h"
-#include "content/public/common/content_switches.h"
-#include "third_party/WebKit/public/platform/WebCursorInfo.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
-#include "third_party/npapi/bindings/npapi.h"
-#include "third_party/npapi/bindings/npruntime.h"
-
-using blink::WebBindings;
-using blink::WebCursorInfo;
-
-namespace content {
-
-static void DestroyWebPluginAndDelegate(
- base::WeakPtr<NPObjectStub> scriptable_object,
- WebPluginDelegateImpl* delegate,
- WebPlugin* webplugin) {
- // The plugin may not expect us to try to release the scriptable object
- // after calling NPP_Destroy on the instance, so delete the stub now.
- if (scriptable_object.get())
- scriptable_object->DeleteSoon();
-
- if (delegate)
- delegate->PluginDestroyed();
-
- delete webplugin;
-}
-
-WebPluginDelegateStub::WebPluginDelegateStub(
- const std::string& mime_type, int instance_id, PluginChannel* channel) :
- mime_type_(mime_type),
- instance_id_(instance_id),
- channel_(channel),
- delegate_(NULL),
- webplugin_(NULL),
- in_destructor_(false) {
- DCHECK(channel);
-}
-
-WebPluginDelegateStub::~WebPluginDelegateStub() {
- in_destructor_ = true;
- GetContentClient()->SetActiveURL(page_url_);
-
- if (channel_->in_send()) {
- // The delegate or an npobject is in the callstack, so don't delete it
- // right away.
- base::MessageLoop::current()->PostNonNestableTask(
- FROM_HERE,
- base::Bind(&DestroyWebPluginAndDelegate,
- plugin_scriptable_object_,
- delegate_,
- webplugin_));
- } else {
- // Safe to delete right away.
- DestroyWebPluginAndDelegate(
- plugin_scriptable_object_, delegate_, webplugin_);
- }
-
- // Remove the NPObject owner mapping for this instance.
- if (delegate_)
- channel_->RemoveMappingForNPObjectOwner(instance_id_);
-}
-
-bool WebPluginDelegateStub::OnMessageReceived(const IPC::Message& msg) {
- GetContentClient()->SetActiveURL(page_url_);
-
- // A plugin can execute a script to delete itself in any of its NPP methods.
- // Hold an extra reference to ourself so that if this does occur and we're
- // handling a sync message, we don't crash when attempting to send a reply.
- // The exception to this is when we're already in the destructor.
- if (!in_destructor_)
- AddRef();
-
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(WebPluginDelegateStub, msg)
- IPC_MESSAGE_HANDLER(PluginMsg_Init, OnInit)
- IPC_MESSAGE_HANDLER(PluginMsg_WillSendRequest, OnWillSendRequest)
- IPC_MESSAGE_HANDLER(PluginMsg_DidReceiveResponse, OnDidReceiveResponse)
- IPC_MESSAGE_HANDLER(PluginMsg_DidReceiveData, OnDidReceiveData)
- IPC_MESSAGE_HANDLER(PluginMsg_DidFinishLoading, OnDidFinishLoading)
- IPC_MESSAGE_HANDLER(PluginMsg_DidFail, OnDidFail)
- IPC_MESSAGE_HANDLER(PluginMsg_SetFocus, OnSetFocus)
- IPC_MESSAGE_HANDLER(PluginMsg_HandleInputEvent, OnHandleInputEvent)
- IPC_MESSAGE_HANDLER(PluginMsg_Paint, OnPaint)
- IPC_MESSAGE_HANDLER(PluginMsg_DidPaint, OnDidPaint)
- IPC_MESSAGE_HANDLER(PluginMsg_GetPluginScriptableObject,
- OnGetPluginScriptableObject)
- IPC_MESSAGE_HANDLER(PluginMsg_GetFormValue, OnGetFormValue)
- IPC_MESSAGE_HANDLER(PluginMsg_UpdateGeometry, OnUpdateGeometry)
- IPC_MESSAGE_HANDLER(PluginMsg_UpdateGeometrySync, OnUpdateGeometry)
- IPC_MESSAGE_HANDLER(PluginMsg_SetContentAreaFocus, OnSetContentAreaFocus)
-#if defined(OS_WIN) && !defined(USE_AURA)
- IPC_MESSAGE_HANDLER(PluginMsg_ImeCompositionUpdated,
- OnImeCompositionUpdated)
- IPC_MESSAGE_HANDLER(PluginMsg_ImeCompositionCompleted,
- OnImeCompositionCompleted)
-#endif
-#if defined(OS_MACOSX)
- IPC_MESSAGE_HANDLER(PluginMsg_SetWindowFocus, OnSetWindowFocus)
- IPC_MESSAGE_HANDLER(PluginMsg_ContainerHidden, OnContainerHidden)
- IPC_MESSAGE_HANDLER(PluginMsg_ContainerShown, OnContainerShown)
- IPC_MESSAGE_HANDLER(PluginMsg_WindowFrameChanged, OnWindowFrameChanged)
- IPC_MESSAGE_HANDLER(PluginMsg_ImeCompositionCompleted,
- OnImeCompositionCompleted)
-#endif
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
-
- if (!in_destructor_)
- Release();
-
- DCHECK(handled);
- return handled;
-}
-
-bool WebPluginDelegateStub::Send(IPC::Message* msg) {
- return channel_->Send(msg);
-}
-
-void WebPluginDelegateStub::OnInit(const PluginMsg_Init_Params& params,
- bool* transparent,
- bool* result) {
- page_url_ = params.page_url;
- GetContentClient()->SetActiveURL(page_url_);
-
- *transparent = false;
- *result = false;
- if (params.arg_names.size() != params.arg_values.size()) {
- NOTREACHED();
- return;
- }
-
- const base::CommandLine& command_line =
- *base::CommandLine::ForCurrentProcess();
- base::FilePath path =
- command_line.GetSwitchValuePath(switches::kPluginPath);
-
- webplugin_ = new WebPluginProxy(channel_.get(),
- instance_id_,
- page_url_,
- params.host_render_view_routing_id);
- delegate_ = WebPluginDelegateImpl::Create(webplugin_, path, mime_type_);
- if (delegate_) {
- if (delegate_->GetQuirks() &
- WebPluginDelegateImpl::PLUGIN_QUIRK_DIE_AFTER_UNLOAD) {
- PluginThread::current()->SetForcefullyTerminatePluginProcess();
- }
-
- webplugin_->set_delegate(delegate_);
- std::vector<std::string> arg_names = params.arg_names;
- std::vector<std::string> arg_values = params.arg_values;
-
- // Add an NPObject owner mapping for this instance, to support ownership
- // tracking in the renderer.
- channel_->AddMappingForNPObjectOwner(instance_id_,
- delegate_->GetPluginNPP());
-
- *result = delegate_->Initialize(params.url,
- arg_names,
- arg_values,
- params.load_manually);
- *transparent = delegate_->instance()->transparent();
- }
-}
-
-void WebPluginDelegateStub::OnWillSendRequest(int id, const GURL& url,
- int http_status_code) {
- WebPluginResourceClient* client = webplugin_->GetResourceClient(id);
- if (!client)
- return;
-
- client->WillSendRequest(url, http_status_code);
-}
-
-void WebPluginDelegateStub::OnDidReceiveResponse(
- const PluginMsg_DidReceiveResponseParams& params) {
- WebPluginResourceClient* client = webplugin_->GetResourceClient(params.id);
- if (!client)
- return;
-
- client->DidReceiveResponse(params.mime_type,
- params.headers,
- params.expected_length,
- params.last_modified,
- params.request_is_seekable);
-}
-
-void WebPluginDelegateStub::OnDidReceiveData(int id,
- const std::vector<char>& buffer,
- int data_offset) {
- WebPluginResourceClient* client = webplugin_->GetResourceClient(id);
- if (!client)
- return;
-
- client->DidReceiveData(&buffer.front(), static_cast<int>(buffer.size()),
- data_offset);
-}
-
-void WebPluginDelegateStub::OnDidFinishLoading(int id) {
- WebPluginResourceClient* client = webplugin_->GetResourceClient(id);
- if (!client)
- return;
-
- client->DidFinishLoading(id);
-}
-
-void WebPluginDelegateStub::OnDidFail(int id) {
- WebPluginResourceClient* client = webplugin_->GetResourceClient(id);
- if (!client)
- return;
-
- client->DidFail(id);
-}
-
-void WebPluginDelegateStub::OnSetFocus(bool focused) {
- delegate_->SetFocus(focused);
-#if defined(OS_WIN) && !defined(USE_AURA)
- if (focused)
- webplugin_->UpdateIMEStatus();
-#endif
-}
-
-void WebPluginDelegateStub::OnHandleInputEvent(
- const blink::WebInputEvent *event,
- bool* handled,
- WebCursor* cursor) {
- WebCursor::CursorInfo cursor_info;
- *handled = delegate_->HandleInputEvent(*event, &cursor_info);
- cursor->InitFromCursorInfo(cursor_info);
-}
-
-void WebPluginDelegateStub::OnPaint(const gfx::Rect& damaged_rect) {
- webplugin_->Paint(damaged_rect);
-}
-
-void WebPluginDelegateStub::OnDidPaint() {
- webplugin_->DidPaint();
-}
-
-void WebPluginDelegateStub::OnUpdateGeometry(
- const PluginMsg_UpdateGeometry_Param& param) {
- webplugin_->UpdateGeometry(
- param.window_rect, param.clip_rect,
- param.windowless_buffer0, param.windowless_buffer1,
- param.windowless_buffer_index);
-}
-
-void WebPluginDelegateStub::OnGetPluginScriptableObject(int* route_id) {
- NPObject* object = delegate_->GetPluginScriptableObject();
- if (!object) {
- *route_id = MSG_ROUTING_NONE;
- return;
- }
-
- *route_id = channel_->GenerateRouteID();
- // We will delete the stub immediately before calling PluginDestroyed on the
- // delegate. It will delete itself sooner if the proxy tells it that it has
- // been released, or if the channel to the proxy is closed.
- NPObjectStub* scriptable_stub = new NPObjectStub(
- object, channel_.get(), *route_id,
- webplugin_->host_render_view_routing_id(), page_url_);
- plugin_scriptable_object_ = scriptable_stub->AsWeakPtr();
-
- // Release ref added by GetPluginScriptableObject (our stub holds its own).
- WebBindings::releaseObject(object);
-}
-
-void WebPluginDelegateStub::OnGetFormValue(base::string16* value,
- bool* success) {
- *success = false;
- if (!delegate_)
- return;
- *success = delegate_->GetFormValue(value);
-}
-
-void WebPluginDelegateStub::OnSetContentAreaFocus(bool has_focus) {
- if (delegate_)
- delegate_->SetContentAreaHasFocus(has_focus);
-}
-
-#if defined(OS_WIN) && !defined(USE_AURA)
-void WebPluginDelegateStub::OnImeCompositionUpdated(
- const base::string16& text,
- const std::vector<int>& clauses,
- const std::vector<int>& target,
- int cursor_position) {
- if (delegate_)
- delegate_->ImeCompositionUpdated(text, clauses, target, cursor_position);
- webplugin_->UpdateIMEStatus();
-}
-
-void WebPluginDelegateStub::OnImeCompositionCompleted(
- const base::string16& text) {
- if (delegate_)
- delegate_->ImeCompositionCompleted(text);
-}
-#endif
-
-#if defined(OS_MACOSX)
-void WebPluginDelegateStub::OnSetWindowFocus(bool has_focus) {
- if (delegate_)
- delegate_->SetWindowHasFocus(has_focus);
-}
-
-void WebPluginDelegateStub::OnContainerHidden() {
- if (delegate_)
- delegate_->SetContainerVisibility(false);
-}
-
-void WebPluginDelegateStub::OnContainerShown(gfx::Rect window_frame,
- gfx::Rect view_frame,
- bool has_focus) {
- if (delegate_) {
- delegate_->WindowFrameChanged(window_frame, view_frame);
- delegate_->SetContainerVisibility(true);
- delegate_->SetWindowHasFocus(has_focus);
- }
-}
-
-void WebPluginDelegateStub::OnWindowFrameChanged(const gfx::Rect& window_frame,
- const gfx::Rect& view_frame) {
- if (delegate_)
- delegate_->WindowFrameChanged(window_frame, view_frame);
-}
-
-void WebPluginDelegateStub::OnImeCompositionCompleted(
- const base::string16& text) {
- if (delegate_)
- delegate_->ImeCompositionCompleted(text);
-}
-#endif // OS_MACOSX
-
-} // namespace content
diff --git a/chromium/content/plugin/webplugin_delegate_stub.h b/chromium/content/plugin/webplugin_delegate_stub.h
deleted file mode 100644
index aae66df8f4b..00000000000
--- a/chromium/content/plugin/webplugin_delegate_stub.h
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_PLUGIN_WEBPLUGIN_DELEGATE_STUB_H_
-#define CONTENT_PLUGIN_WEBPLUGIN_DELEGATE_STUB_H_
-
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "build/build_config.h"
-#include "content/child/npapi/npobject_stub.h"
-#include "ipc/ipc_listener.h"
-#include "ipc/ipc_sender.h"
-#include "third_party/npapi/bindings/npapi.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/native_widget_types.h"
-#include "url/gurl.h"
-
-struct PluginMsg_Init_Params;
-struct PluginMsg_DidReceiveResponseParams;
-struct PluginMsg_FetchURL_Params;
-struct PluginMsg_UpdateGeometry_Param;
-
-namespace blink {
-class WebInputEvent;
-}
-
-namespace content {
-class PluginChannel;
-class WebCursor;
-class WebPluginDelegateImpl;
-class WebPluginProxy;
-
-// Converts the IPC messages from WebPluginDelegateProxy into calls to the
-// actual WebPluginDelegateImpl object.
-class WebPluginDelegateStub : public IPC::Listener,
- public IPC::Sender,
- public base::RefCounted<WebPluginDelegateStub> {
- public:
- WebPluginDelegateStub(const std::string& mime_type, int instance_id,
- PluginChannel* channel);
-
- // IPC::Listener implementation:
- bool OnMessageReceived(const IPC::Message& msg) override;
-
- // IPC::Sender implementation:
- bool Send(IPC::Message* msg) override;
-
- int instance_id() { return instance_id_; }
- WebPluginDelegateImpl* delegate() { return delegate_; }
- WebPluginProxy* webplugin() { return webplugin_; }
-
- private:
- friend class base::RefCounted<WebPluginDelegateStub>;
-
- ~WebPluginDelegateStub() override;
-
- // Message handlers for the WebPluginDelegate calls that are proxied from the
- // renderer over the IPC channel.
- void OnInit(const PluginMsg_Init_Params& params,
- bool* transparent,
- bool* result);
- void OnWillSendRequest(int id, const GURL& url, int http_status_code);
- void OnDidReceiveResponse(const PluginMsg_DidReceiveResponseParams& params);
- void OnDidReceiveData(int id, const std::vector<char>& buffer,
- int data_offset);
- void OnDidFinishLoading(int id);
- void OnDidFail(int id);
- void OnSetFocus(bool focused);
- void OnHandleInputEvent(const blink::WebInputEvent* event,
- bool* handled, WebCursor* cursor);
- void OnPaint(const gfx::Rect& damaged_rect);
- void OnDidPaint();
- void OnUpdateGeometry(const PluginMsg_UpdateGeometry_Param& param);
- void OnGetPluginScriptableObject(int* route_id);
- void OnGetFormValue(base::string16* value, bool* success);
-
- void OnSetContentAreaFocus(bool has_focus);
-#if defined(OS_WIN) && !defined(USE_AURA)
- void OnImeCompositionUpdated(const base::string16& text,
- const std::vector<int>& clauses,
- const std::vector<int>& target,
- int cursor_position);
- void OnImeCompositionCompleted(const base::string16& text);
-#endif
-#if defined(OS_MACOSX)
- void OnSetWindowFocus(bool has_focus);
- void OnContainerHidden();
- void OnContainerShown(gfx::Rect window_frame, gfx::Rect view_frame,
- bool has_focus);
- void OnWindowFrameChanged(const gfx::Rect& window_frame,
- const gfx::Rect& view_frame);
- void OnImeCompositionCompleted(const base::string16& text);
-#endif
-
- std::string mime_type_;
- int instance_id_;
-
- scoped_refptr<PluginChannel> channel_;
-
- base::WeakPtr<NPObjectStub> plugin_scriptable_object_;
- WebPluginDelegateImpl* delegate_;
- WebPluginProxy* webplugin_;
- bool in_destructor_;
-
- // The url of the main frame hosting the plugin.
- GURL page_url_;
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(WebPluginDelegateStub);
-};
-
-} // namespace content
-
-#endif // CONTENT_PLUGIN_WEBPLUGIN_DELEGATE_STUB_H_
diff --git a/chromium/content/plugin/webplugin_proxy.cc b/chromium/content/plugin/webplugin_proxy.cc
deleted file mode 100644
index 3d322543054..00000000000
--- a/chromium/content/plugin/webplugin_proxy.cc
+++ /dev/null
@@ -1,566 +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/plugin/webplugin_proxy.h"
-
-#include "build/build_config.h"
-
-#include "base/bind.h"
-#include "base/lazy_instance.h"
-#include "content/child/npapi/npobject_proxy.h"
-#include "content/child/npapi/npobject_util.h"
-#include "content/child/npapi/webplugin_delegate_impl.h"
-#include "content/child/npapi/webplugin_resource_client.h"
-#include "content/child/plugin_messages.h"
-#include "content/plugin/plugin_channel.h"
-#include "content/plugin/plugin_thread.h"
-#include "content/public/common/content_client.h"
-#include "skia/ext/platform_canvas.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
-#include "ui/gfx/canvas.h"
-#include "url/url_constants.h"
-
-#if defined(OS_MACOSX)
-#include "base/mac/mac_util.h"
-#include "base/mac/scoped_cftyperef.h"
-#include "content/plugin/webplugin_accelerated_surface_proxy_mac.h"
-#endif
-
-#if defined(OS_WIN)
-#include "content/common/plugin_process_messages.h"
-#include "content/public/common/sandbox_init.h"
-#endif
-
-using blink::WebBindings;
-
-namespace content {
-
-WebPluginProxy::SharedTransportDIB::SharedTransportDIB(TransportDIB* dib)
- : dib_(dib) {
-}
-
-WebPluginProxy::SharedTransportDIB::~SharedTransportDIB() {
-}
-
-WebPluginProxy::WebPluginProxy(
- PluginChannel* channel,
- int route_id,
- const GURL& page_url,
- int host_render_view_routing_id)
- : channel_(channel),
- route_id_(route_id),
- window_npobject_(NULL),
- plugin_element_(NULL),
- delegate_(NULL),
- waiting_for_paint_(false),
- page_url_(page_url),
- windowless_buffer_index_(0),
- host_render_view_routing_id_(host_render_view_routing_id),
- weak_factory_(this) {
-}
-
-WebPluginProxy::~WebPluginProxy() {
-#if defined(OS_MACOSX)
- // Destroy the surface early, since it may send messages during cleanup.
- if (accelerated_surface_)
- accelerated_surface_.reset();
-#endif
-
- if (plugin_element_)
- WebBindings::releaseObject(plugin_element_);
- if (window_npobject_)
- WebBindings::releaseObject(window_npobject_);
-}
-
-bool WebPluginProxy::Send(IPC::Message* msg) {
- return channel_->Send(msg);
-}
-
-void WebPluginProxy::SetWindow(gfx::PluginWindowHandle window) {
- Send(new PluginHostMsg_SetWindow(route_id_, window));
-}
-
-void WebPluginProxy::SetAcceptsInputEvents(bool accepts) {
- NOTREACHED();
-}
-
-void WebPluginProxy::WillDestroyWindow(gfx::PluginWindowHandle window) {
-#if defined(OS_WIN)
- PluginThread::current()->Send(
- new PluginProcessHostMsg_PluginWindowDestroyed(
- window, ::GetParent(window)));
-#else
- NOTIMPLEMENTED();
-#endif
-}
-
-#if defined(OS_WIN)
-void WebPluginProxy::SetWindowlessData(
- HANDLE pump_messages_event, gfx::NativeViewId dummy_activation_window) {
- HANDLE pump_messages_event_for_renderer = NULL;
- BrokerDuplicateHandle(pump_messages_event, channel_->peer_pid(),
- &pump_messages_event_for_renderer,
- SYNCHRONIZE | EVENT_MODIFY_STATE, 0);
- DCHECK(pump_messages_event_for_renderer);
- Send(new PluginHostMsg_SetWindowlessData(
- route_id_, pump_messages_event_for_renderer, dummy_activation_window));
-}
-#endif
-
-void WebPluginProxy::CancelResource(unsigned long id) {
- Send(new PluginHostMsg_CancelResource(route_id_, id));
- resource_clients_.erase(id);
-}
-
-void WebPluginProxy::Invalidate() {
- gfx::Rect rect(0, 0,
- delegate_->GetRect().width(),
- delegate_->GetRect().height());
- InvalidateRect(rect);
-}
-
-void WebPluginProxy::InvalidateRect(const gfx::Rect& rect) {
-#if defined(OS_MACOSX)
- // If this is a Core Animation plugin, all we need to do is inform the
- // delegate.
- if (!windowless_context()) {
- delegate_->PluginDidInvalidate();
- return;
- }
-
- // Some plugins will send invalidates larger than their own rect when
- // offscreen, so constrain invalidates to the plugin rect.
- gfx::Rect plugin_rect = delegate_->GetRect();
- plugin_rect.set_origin(gfx::Point(0, 0));
- plugin_rect.Intersect(rect);
- const gfx::Rect invalidate_rect(plugin_rect);
-#else
- const gfx::Rect invalidate_rect(rect);
-#endif
- damaged_rect_.Union(invalidate_rect);
- // Ignore NPN_InvalidateRect calls with empty rects. Also don't send an
- // invalidate if it's outside the clipping region, since if we did it won't
- // lead to a paint and we'll be stuck waiting forever for a DidPaint response.
- //
- // TODO(piman): There is a race condition here, because this test assumes
- // that when the paint actually occurs, the clip rect will not have changed.
- // This is not true because scrolling (or window resize) could occur and be
- // handled by the renderer before it receives the InvalidateRect message,
- // changing the clip rect and then not painting.
- if (damaged_rect_.IsEmpty() ||
- !delegate_->GetClipRect().Intersects(damaged_rect_))
- return;
-
- // Only send a single InvalidateRect message at a time. From DidPaint we
- // will dispatch an additional InvalidateRect message if necessary.
- if (!waiting_for_paint_) {
- waiting_for_paint_ = true;
- // Invalidates caused by calls to NPN_InvalidateRect/NPN_InvalidateRgn
- // need to be painted asynchronously as per the NPAPI spec.
- base::MessageLoop::current()->PostTask(
- FROM_HERE,
- base::Bind(&WebPluginProxy::OnPaint,
- weak_factory_.GetWeakPtr(),
- damaged_rect_));
- damaged_rect_ = gfx::Rect();
- }
-}
-
-NPObject* WebPluginProxy::GetWindowScriptNPObject() {
- if (window_npobject_)
- return window_npobject_;
-
- int npobject_route_id = channel_->GenerateRouteID();
- bool success = false;
- Send(new PluginHostMsg_GetWindowScriptNPObject(
- route_id_, npobject_route_id, &success));
- if (!success)
- return NULL;
-
- // PluginChannel creates a dummy owner identifier for unknown owners, so
- // use that.
- NPP owner = channel_->GetExistingNPObjectOwner(MSG_ROUTING_NONE);
-
- window_npobject_ = NPObjectProxy::Create(channel_.get(),
- npobject_route_id,
- host_render_view_routing_id_,
- page_url_,
- owner);
-
- return window_npobject_;
-}
-
-NPObject* WebPluginProxy::GetPluginElement() {
- if (plugin_element_)
- return plugin_element_;
-
- int npobject_route_id = channel_->GenerateRouteID();
- bool success = false;
- Send(new PluginHostMsg_GetPluginElement(route_id_, npobject_route_id,
- &success));
- if (!success)
- return NULL;
-
- // PluginChannel creates a dummy owner identifier for unknown owners, so
- // use that.
- NPP owner = channel_->GetExistingNPObjectOwner(MSG_ROUTING_NONE);
-
- plugin_element_ = NPObjectProxy::Create(channel_.get(),
- npobject_route_id,
- host_render_view_routing_id_,
- page_url_,
- owner);
-
- return plugin_element_;
-}
-
-bool WebPluginProxy::FindProxyForUrl(const GURL& url, std::string* proxy_list) {
- bool result = false;
- Send(new PluginHostMsg_ResolveProxy(route_id_, url, &result, proxy_list));
- return result;
-}
-
-void WebPluginProxy::SetCookie(const GURL& url,
- const GURL& first_party_for_cookies,
- const std::string& cookie) {
- Send(new PluginHostMsg_SetCookie(route_id_, url,
- first_party_for_cookies, cookie));
-}
-
-std::string WebPluginProxy::GetCookies(const GURL& url,
- const GURL& first_party_for_cookies) {
- std::string cookies;
- Send(new PluginHostMsg_GetCookies(route_id_, url,
- first_party_for_cookies, &cookies));
-
- return cookies;
-}
-
-WebPluginResourceClient* WebPluginProxy::GetResourceClient(int id) {
- ResourceClientMap::iterator iterator = resource_clients_.find(id);
- // The IPC messages which deal with streams are now asynchronous. It is
- // now possible to receive stream messages from the renderer for streams
- // which may have been cancelled by the plugin.
- if (iterator == resource_clients_.end()) {
- return NULL;
- }
-
- return iterator->second;
-}
-
-int WebPluginProxy::GetRendererId() {
- if (channel_.get())
- return channel_->renderer_id();
- return -1;
-}
-
-void WebPluginProxy::DidPaint() {
- // If we have an accumulated damaged rect, then check to see if we need to
- // send out another InvalidateRect message.
- waiting_for_paint_ = false;
- if (!damaged_rect_.IsEmpty())
- InvalidateRect(damaged_rect_);
-}
-
-void WebPluginProxy::OnResourceCreated(int resource_id,
- WebPluginResourceClient* client) {
- DCHECK(resource_clients_.find(resource_id) == resource_clients_.end());
- resource_clients_[resource_id] = client;
-}
-
-void WebPluginProxy::Paint(const gfx::Rect& rect) {
-#if defined(OS_MACOSX)
- if (!windowless_context())
- return;
-#else
- if (!windowless_canvas() || !windowless_canvas()->getDevice())
- return;
-#endif
-
- // Clear the damaged area so that if the plugin doesn't paint there we won't
- // end up with the old values.
- gfx::Rect offset_rect = rect;
- offset_rect.Offset(delegate_->GetRect().OffsetFromOrigin());
-#if defined(OS_MACOSX)
- CGContextSaveGState(windowless_context());
- // It is possible for windowless_contexts_ to change during plugin painting
- // (since the plugin can make a synchronous call during paint event handling),
- // in which case we don't want to try to restore later. Not an owning ref
- // since owning the ref without owning the shared backing memory doesn't make
- // sense, so this should only be used for pointer comparisons.
- CGContextRef saved_context_weak = windowless_context();
- // We also save the buffer index for the comparison because if we flip buffers
- // but haven't reallocated them then we do need to restore the context because
- // it is going to continue to be used.
- int saved_index = windowless_buffer_index_;
-
- CGContextClipToRect(windowless_context(), rect.ToCGRect());
- // TODO(caryclark): This is a temporary workaround to allow the Darwin / Skia
- // port to share code with the Darwin / CG port. All ports will eventually use
- // the common code below.
- delegate_->CGPaint(windowless_context(), rect);
- if (windowless_contexts_[saved_index].get() == saved_context_weak)
- CGContextRestoreGState(windowless_contexts_[saved_index]);
-#else
- // See above comment about windowless_context_ changing.
- // http::/crbug.com/139462
- skia::RefPtr<skia::PlatformCanvas> saved_canvas = windowless_canvas();
-
- saved_canvas->save();
-
- // The given clip rect is relative to the plugin coordinate system.
- SkRect sk_rect = { SkIntToScalar(rect.x()),
- SkIntToScalar(rect.y()),
- SkIntToScalar(rect.right()),
- SkIntToScalar(rect.bottom()) };
- saved_canvas->clipRect(sk_rect);
-
- // Fill a transparent value so that if the plugin supports transparency that
- // will work.
- saved_canvas->drawColor(SkColorSetARGB(0, 0, 0, 0), SkXfermode::kSrc_Mode);
-
- // Bring the windowless canvas into the window coordinate system, which is
- // how the plugin expects to draw (since the windowless API was originally
- // designed just for scribbling over the web page).
- saved_canvas->translate(SkIntToScalar(-delegate_->GetRect().x()),
- SkIntToScalar(-delegate_->GetRect().y()));
-
- // Before we send the invalidate, paint so that renderer uses the updated
- // bitmap.
- delegate_->Paint(saved_canvas.get(), offset_rect);
-
- saved_canvas->restore();
-#endif
-}
-
-void WebPluginProxy::UpdateGeometry(
- const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect,
- const TransportDIB::Handle& windowless_buffer0,
- const TransportDIB::Handle& windowless_buffer1,
- int windowless_buffer_index) {
- gfx::Rect old = delegate_->GetRect();
- gfx::Rect old_clip_rect = delegate_->GetClipRect();
-
- // Update the buffers before doing anything that could call into plugin code,
- // so that we don't process buffer changes out of order if plugins make
- // synchronous calls that lead to nested UpdateGeometry calls.
- if (TransportDIB::is_valid_handle(windowless_buffer0)) {
- // The plugin's rect changed, so now we have new buffers to draw into.
- SetWindowlessBuffers(windowless_buffer0,
- windowless_buffer1,
- window_rect);
- }
-
- DCHECK(0 <= windowless_buffer_index && windowless_buffer_index <= 1);
- windowless_buffer_index_ = windowless_buffer_index;
-
-#if defined(OS_MACOSX)
- delegate_->UpdateGeometryAndContext(
- window_rect, clip_rect, windowless_context());
-#else
- delegate_->UpdateGeometry(window_rect, clip_rect);
-#endif
-
- // Send over any pending invalidates which occured when the plugin was
- // off screen.
- if (delegate_->IsWindowless() && !clip_rect.IsEmpty() &&
- !damaged_rect_.IsEmpty()) {
- InvalidateRect(damaged_rect_);
- }
-}
-
-#if defined(OS_WIN)
-
-void WebPluginProxy::CreateCanvasFromHandle(
- const TransportDIB::Handle& dib_handle,
- const gfx::Rect& window_rect,
- skia::RefPtr<skia::PlatformCanvas>* canvas) {
- *canvas = skia::AdoptRef(skia::CreatePlatformCanvas(
- window_rect.width(), window_rect.height(), true, dib_handle.GetHandle(),
- skia::RETURN_NULL_ON_FAILURE));
- // The canvas does not own the section so we need to close it now.
- dib_handle.Close();
-}
-
-void WebPluginProxy::SetWindowlessBuffers(
- const TransportDIB::Handle& windowless_buffer0,
- const TransportDIB::Handle& windowless_buffer1,
- const gfx::Rect& window_rect) {
- CreateCanvasFromHandle(windowless_buffer0,
- window_rect,
- &windowless_canvases_[0]);
- if (!windowless_canvases_[0]) {
- windowless_canvases_[1].clear();
- return;
- }
- CreateCanvasFromHandle(windowless_buffer1,
- window_rect,
- &windowless_canvases_[1]);
- if (!windowless_canvases_[1]) {
- windowless_canvases_[0].clear();
- return;
- }
-}
-
-#elif defined(OS_MACOSX)
-
-void WebPluginProxy::CreateDIBAndCGContextFromHandle(
- const TransportDIB::Handle& dib_handle,
- const gfx::Rect& window_rect,
- scoped_ptr<TransportDIB>* dib_out,
- base::ScopedCFTypeRef<CGContextRef>* cg_context_out) {
- // Convert the shared memory handle to a handle that works in our process,
- // and then use that to create a CGContextRef.
- TransportDIB* dib = TransportDIB::Map(dib_handle);
- CGContextRef cg_context = NULL;
- if (dib) {
- cg_context = CGBitmapContextCreate(
- dib->memory(),
- window_rect.width(),
- window_rect.height(),
- 8,
- 4 * window_rect.width(),
- base::mac::GetSystemColorSpace(),
- kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);
- CGContextTranslateCTM(cg_context, 0, window_rect.height());
- CGContextScaleCTM(cg_context, 1, -1);
- }
- dib_out->reset(dib);
- cg_context_out->reset(cg_context);
-}
-
-void WebPluginProxy::SetWindowlessBuffers(
- const TransportDIB::Handle& windowless_buffer0,
- const TransportDIB::Handle& windowless_buffer1,
- const gfx::Rect& window_rect) {
- CreateDIBAndCGContextFromHandle(windowless_buffer0,
- window_rect,
- &windowless_dibs_[0],
- &windowless_contexts_[0]);
- CreateDIBAndCGContextFromHandle(windowless_buffer1,
- window_rect,
- &windowless_dibs_[1],
- &windowless_contexts_[1]);
-}
-
-#else
-
-void WebPluginProxy::SetWindowlessBuffers(
- const TransportDIB::Handle& windowless_buffer0,
- const TransportDIB::Handle& windowless_buffer1,
- const gfx::Rect& window_rect) {
- NOTIMPLEMENTED();
-}
-
-#endif
-
-void WebPluginProxy::CancelDocumentLoad() {
- Send(new PluginHostMsg_CancelDocumentLoad(route_id_));
-}
-
-void WebPluginProxy::DidStartLoading() {
- Send(new PluginHostMsg_DidStartLoading(route_id_));
-}
-
-void WebPluginProxy::DidStopLoading() {
- Send(new PluginHostMsg_DidStopLoading(route_id_));
-}
-
-void WebPluginProxy::SetDeferResourceLoading(unsigned long resource_id,
- bool defer) {
- Send(new PluginHostMsg_DeferResourceLoading(route_id_, resource_id, defer));
-}
-
-#if defined(OS_MACOSX)
-void WebPluginProxy::FocusChanged(bool focused) {
- IPC::Message* msg = new PluginHostMsg_FocusChanged(route_id_, focused);
- Send(msg);
-}
-
-void WebPluginProxy::StartIme() {
- IPC::Message* msg = new PluginHostMsg_StartIme(route_id_);
- // This message can be sent during event-handling, and needs to be delivered
- // within that context.
- msg->set_unblock(true);
- Send(msg);
-}
-
-WebPluginAcceleratedSurface* WebPluginProxy::GetAcceleratedSurface(
- gfx::GpuPreference gpu_preference) {
- if (!accelerated_surface_)
- accelerated_surface_.reset(
- WebPluginAcceleratedSurfaceProxy::Create(this, gpu_preference));
- return accelerated_surface_.get();
-}
-
-void WebPluginProxy::AcceleratedPluginEnabledRendering() {
- Send(new PluginHostMsg_AcceleratedPluginEnabledRendering(route_id_));
-}
-
-void WebPluginProxy::AcceleratedPluginAllocatedIOSurface(int32_t width,
- int32_t height,
- uint32_t surface_id) {
- Send(new PluginHostMsg_AcceleratedPluginAllocatedIOSurface(
- route_id_, width, height, surface_id));
-}
-
-void WebPluginProxy::AcceleratedPluginSwappedIOSurface() {
- Send(new PluginHostMsg_AcceleratedPluginSwappedIOSurface(
- route_id_));
-}
-#endif
-
-void WebPluginProxy::OnPaint(const gfx::Rect& damaged_rect) {
- GetContentClient()->SetActiveURL(page_url_);
-
- Paint(damaged_rect);
- Send(new PluginHostMsg_InvalidateRect(route_id_, damaged_rect));
-}
-
-bool WebPluginProxy::IsOffTheRecord() {
- return channel_->incognito();
-}
-
-void WebPluginProxy::ResourceClientDeleted(
- WebPluginResourceClient* resource_client) {
- // resource_client->ResourceId() is 0 at this point, so can't use it as an
- // index into the map.
- ResourceClientMap::iterator index = resource_clients_.begin();
- while (index != resource_clients_.end()) {
- WebPluginResourceClient* client = (*index).second;
- if (client == resource_client) {
- resource_clients_.erase(index);
- return;
- } else {
- index++;
- }
- }
-}
-
-void WebPluginProxy::URLRedirectResponse(bool allow, int resource_id) {
- Send(new PluginHostMsg_URLRedirectResponse(route_id_, allow, resource_id));
-}
-
-bool WebPluginProxy::CheckIfRunInsecureContent(const GURL& url) {
- bool result = true;
- Send(new PluginHostMsg_CheckIfRunInsecureContent(
- route_id_, url, &result));
- return result;
-}
-
-#if defined(OS_WIN) && !defined(USE_AURA)
-void WebPluginProxy::UpdateIMEStatus() {
- // Retrieve the IME status from a plugin and send it to a renderer process
- // when the plugin has updated it.
- int input_type;
- gfx::Rect caret_rect;
- if (!delegate_->GetIMEStatus(&input_type, &caret_rect))
- return;
-
- Send(new PluginHostMsg_NotifyIMEStatus(route_id_, input_type, caret_rect));
-}
-#endif
-
-} // namespace content
diff --git a/chromium/content/plugin/webplugin_proxy.h b/chromium/content/plugin/webplugin_proxy.h
deleted file mode 100644
index 696dc0e0b0a..00000000000
--- a/chromium/content/plugin/webplugin_proxy.h
+++ /dev/null
@@ -1,212 +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_PLUGIN_WEBPLUGIN_PROXY_H_
-#define CONTENT_PLUGIN_WEBPLUGIN_PROXY_H_
-
-#include <stdint.h>
-
-#include <string>
-
-#include "base/containers/hash_tables.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "build/build_config.h"
-#include "content/child/npapi/webplugin.h"
-#include "ipc/ipc_message.h"
-#include "ipc/ipc_sender.h"
-#include "skia/ext/refptr.h"
-#include "third_party/skia/include/core/SkCanvas.h"
-#include "ui/gl/gpu_preference.h"
-#include "ui/surface/transport_dib.h"
-#include "url/gurl.h"
-
-#if defined(OS_MACOSX)
-#include <ApplicationServices/ApplicationServices.h>
-
-#include "base/mac/scoped_cftyperef.h"
-#endif
-
-struct PluginMsg_FetchURL_Params;
-
-namespace content {
-class PluginChannel;
-class WebPluginDelegateImpl;
-
-#if defined(OS_MACOSX)
-class WebPluginAcceleratedSurfaceProxy;
-#endif
-
-// This is an implementation of WebPlugin that proxies all calls to the
-// renderer.
-class WebPluginProxy : public WebPlugin,
- public IPC::Sender {
- public:
- // Creates a new proxy for WebPlugin, using the given sender to send the
- // marshalled WebPlugin calls.
- WebPluginProxy(PluginChannel* channel,
- int route_id,
- const GURL& page_url,
- int host_render_view_routing_id);
- ~WebPluginProxy() override;
-
- void set_delegate(WebPluginDelegateImpl* d) { delegate_ = d; }
-
- // WebPlugin overrides
- void SetWindow(gfx::PluginWindowHandle window) override;
- void SetAcceptsInputEvents(bool accepts) override;
- void WillDestroyWindow(gfx::PluginWindowHandle window) override;
- void CancelResource(unsigned long id) override;
- void Invalidate() override;
- void InvalidateRect(const gfx::Rect& rect) override;
- NPObject* GetWindowScriptNPObject() override;
- NPObject* GetPluginElement() override;
- bool FindProxyForUrl(const GURL& url, std::string* proxy_list) override;
- void SetCookie(const GURL& url,
- const GURL& first_party_for_cookies,
- const std::string& cookie) override;
- std::string GetCookies(const GURL& url,
- const GURL& first_party_for_cookies) override;
- void UpdateGeometry(const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect,
- const TransportDIB::Handle& windowless_buffer0,
- const TransportDIB::Handle& windowless_buffer1,
- int windowless_buffer_index);
- void CancelDocumentLoad() override;
- void DidStartLoading() override;
- void DidStopLoading() override;
- void SetDeferResourceLoading(unsigned long resource_id, bool defer) override;
- bool IsOffTheRecord() override;
- void ResourceClientDeleted(WebPluginResourceClient* resource_client) override;
- void URLRedirectResponse(bool allow, int resource_id) override;
- bool CheckIfRunInsecureContent(const GURL& url) override;
-#if defined(OS_WIN)
- void SetWindowlessData(HANDLE pump_messages_event,
- gfx::NativeViewId dummy_activation_window) override;
-#endif
-#if defined(OS_MACOSX)
- void FocusChanged(bool focused) override;
- void StartIme() override;
- WebPluginAcceleratedSurface* GetAcceleratedSurface(
- gfx::GpuPreference gpu_preference) override;
- void AcceleratedPluginEnabledRendering() override;
- void AcceleratedPluginAllocatedIOSurface(int32_t width,
- int32_t height,
- uint32_t surface_id) override;
- void AcceleratedPluginSwappedIOSurface() override;
-#endif
-
- // IPC::Sender implementation.
- bool Send(IPC::Message* msg) override;
-
- // class-specific methods
-
- // Returns a WebPluginResourceClient object given its id, or NULL if no
- // object with that id exists.
- WebPluginResourceClient* GetResourceClient(int id);
-
- // Returns the id of the renderer that contains this plugin.
- int GetRendererId();
-
- // Returns the id of the associated render view.
- int host_render_view_routing_id() const {
- return host_render_view_routing_id_;
- }
-
- // For windowless plugins, paints the given rectangle into the local buffer.
- void Paint(const gfx::Rect& rect);
-
- // Callback from the renderer to let us know that a paint occurred.
- void DidPaint();
-
- // Notification received on a plugin issued resource request creation.
- void OnResourceCreated(int resource_id, WebPluginResourceClient* client);
-
-#if defined(OS_WIN) && !defined(USE_AURA)
- // Retrieves the IME status from a windowless plugin and sends it to a
- // renderer process. A renderer process will convert the coordinates from
- // local to the window coordinates and send the converted coordinates to a
- // browser process.
- void UpdateIMEStatus();
-#endif
-
- private:
- class SharedTransportDIB : public base::RefCounted<SharedTransportDIB> {
- public:
- explicit SharedTransportDIB(TransportDIB* dib);
- TransportDIB* dib() { return dib_.get(); }
- private:
- friend class base::RefCounted<SharedTransportDIB>;
- ~SharedTransportDIB();
-
- scoped_ptr<TransportDIB> dib_;
- };
-
- // Handler for sending over the paint event to the plugin.
- void OnPaint(const gfx::Rect& damaged_rect);
-
-#if defined(OS_WIN)
- void CreateCanvasFromHandle(const TransportDIB::Handle& dib_handle,
- const gfx::Rect& window_rect,
- skia::RefPtr<SkCanvas>* canvas);
-#elif defined(OS_MACOSX)
- static void CreateDIBAndCGContextFromHandle(
- const TransportDIB::Handle& dib_handle,
- const gfx::Rect& window_rect,
- scoped_ptr<TransportDIB>* dib_out,
- base::ScopedCFTypeRef<CGContextRef>* cg_context_out);
-#endif
-
- // Updates the shared memory sections where windowless plugins paint.
- void SetWindowlessBuffers(const TransportDIB::Handle& windowless_buffer0,
- const TransportDIB::Handle& windowless_buffer1,
- const gfx::Rect& window_rect);
-
-#if defined(OS_MACOSX)
- CGContextRef windowless_context() const {
- return windowless_contexts_[windowless_buffer_index_].get();
- }
-#else
- skia::RefPtr<SkCanvas> windowless_canvas() const {
- return windowless_canvases_[windowless_buffer_index_];
- }
-#endif
-
- typedef base::hash_map<int, WebPluginResourceClient*> ResourceClientMap;
- ResourceClientMap resource_clients_;
-
- scoped_refptr<PluginChannel> channel_;
- int route_id_;
- NPObject* window_npobject_;
- NPObject* plugin_element_;
- WebPluginDelegateImpl* delegate_;
- gfx::Rect damaged_rect_;
- bool waiting_for_paint_;
- // The url of the main frame hosting the plugin.
- GURL page_url_;
-
- // Variables used for desynchronized windowless plugin painting. See note in
- // webplugin_delegate_proxy.h for how this works. The two sets of windowless_*
- // fields are for the front-buffer and back-buffer of a buffer flipping system
- // and windowless_buffer_index_ identifies which set we are using as the
- // back-buffer at any given time.
- int windowless_buffer_index_;
-#if defined(OS_MACOSX)
- scoped_ptr<TransportDIB> windowless_dibs_[2];
- base::ScopedCFTypeRef<CGContextRef> windowless_contexts_[2];
- scoped_ptr<WebPluginAcceleratedSurfaceProxy> accelerated_surface_;
-#else
- skia::RefPtr<SkCanvas> windowless_canvases_[2];
-#endif
-
- // Contains the routing id of the host render view.
- int host_render_view_routing_id_;
-
- base::WeakPtrFactory<WebPluginProxy> weak_factory_;
-};
-
-} // namespace content
-
-#endif // CONTENT_PLUGIN_WEBPLUGIN_PROXY_H_
diff --git a/chromium/content/ppapi_plugin/BUILD.gn b/chromium/content/ppapi_plugin/BUILD.gn
index e127a3d2756..e8dfe47d7df 100644
--- a/chromium/content/ppapi_plugin/BUILD.gn
+++ b/chromium/content/ppapi_plugin/BUILD.gn
@@ -3,7 +3,7 @@
# found in the LICENSE file.
group("ppapi_plugin") {
- visibility = [ "//content/*" ]
+ visibility = [ "//content/*" ] # This is an internal content API.
if (is_component_build) {
public_deps = [
@@ -17,7 +17,12 @@ group("ppapi_plugin") {
}
source_set("ppapi_plugin_sources") {
- visibility = [ "//content/*" ]
+ # Depend on via ":ppapi_plugin above.
+ visibility = [
+ ":ppapi_plugin",
+ "//content", # For the component build.
+ "//gin",
+ ]
sources = [
"broker_process_dispatcher.cc",
@@ -32,7 +37,10 @@ source_set("ppapi_plugin_sources") {
"ppapi_thread.h",
]
- configs += [ "//content:content_implementation" ]
+ configs += [
+ "//content:content_implementation",
+ "//v8:external_startup_data",
+ ]
deps = [
"//base",
diff --git a/chromium/content/ppapi_plugin/DEPS b/chromium/content/ppapi_plugin/DEPS
index bde9e92ce49..9959c2fe7b8 100644
--- a/chromium/content/ppapi_plugin/DEPS
+++ b/chromium/content/ppapi_plugin/DEPS
@@ -1,6 +1,7 @@
include_rules = [
"+content/child",
- "+content/public/plugin",
+ "+gin/public/isolate_holder.h",
+ "+gin/v8_initializer.h",
"+ppapi/c",
"+ppapi/proxy",
]
diff --git a/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.cc b/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.cc
index e2f25c651a2..01c04ece935 100644
--- a/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.cc
+++ b/chromium/content/ppapi_plugin/ppapi_blink_platform_impl.cc
@@ -50,9 +50,9 @@ class PpapiBlinkPlatformImpl::SandboxSupport : public WebSandboxSupport {
WebUChar32 character,
const char* preferred_locale,
blink::WebFallbackFont* fallbackFont) override;
- void getRenderStyleForStrike(const char* family,
- int sizeAndStyle,
- blink::WebFontRenderStyle* out) override;
+ void getWebFontRenderStyleForStrike(const char* family,
+ int sizeAndStyle,
+ blink::WebFontRenderStyle* out) override;
private:
// WebKit likes to ask us for the correct font family to use for a set of
@@ -105,7 +105,7 @@ void PpapiBlinkPlatformImpl::SandboxSupport::getFallbackFontForCharacter(
unicode_font_families_.insert(std::make_pair(character, *fallbackFont));
}
-void PpapiBlinkPlatformImpl::SandboxSupport::getRenderStyleForStrike(
+void PpapiBlinkPlatformImpl::SandboxSupport::getWebFontRenderStyleForStrike(
const char* family,
int sizeAndStyle,
blink::WebFontRenderStyle* out) {
diff --git a/chromium/content/ppapi_plugin/ppapi_plugin_main.cc b/chromium/content/ppapi_plugin/ppapi_plugin_main.cc
index 53bd14ce34b..ccd05e9111b 100644
--- a/chromium/content/ppapi_plugin/ppapi_plugin_main.cc
+++ b/chromium/content/ppapi_plugin/ppapi_plugin_main.cc
@@ -19,7 +19,6 @@
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/main_function_params.h"
-#include "content/public/plugin/content_plugin_client.h"
#include "ipc/ipc_sender.h"
#include "ppapi/proxy/plugin_globals.h"
#include "ppapi/proxy/proxy_module.h"
@@ -29,8 +28,6 @@
#include "base/win/win_util.h"
#include "base/win/windows_version.h"
#include "content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.h"
-#include "content/common/font_warmup_win.h"
-#include "content/public/common/dwrite_font_platform_win.h"
#include "sandbox/win/src/sandbox.h"
#include "third_party/WebKit/public/web/win/WebFontRendering.h"
#include "third_party/skia/include/ports/SkTypeface_win.h"
@@ -46,6 +43,10 @@
#include "content/public/common/sandbox_init.h"
#endif
+#ifdef V8_USE_EXTERNAL_STARTUP_DATA
+#include "gin/v8_initializer.h"
+#endif
+
#if defined(OS_POSIX) && !defined(OS_ANDROID)
#include <stdlib.h>
#endif
@@ -124,10 +125,10 @@ int PpapiPluginMain(const MainFunctionParams& parameters) {
base::trace_event::TraceLog::GetInstance()->SetProcessSortIndex(
kTraceEventPpapiProcessSortIndex);
- // Allow the embedder to perform any necessary per-process initialization
- // before the sandbox is initialized.
- if (GetContentClient()->plugin())
- GetContentClient()->plugin()->PreSandboxInitialization();
+#ifdef V8_USE_EXTERNAL_STARTUP_DATA
+ gin::V8Initializer::LoadV8Snapshot();
+ gin::V8Initializer::LoadV8Natives();
+#endif
#if defined(OS_LINUX)
LinuxSandbox::InitializeSandbox();
@@ -142,13 +143,7 @@ int PpapiPluginMain(const MainFunctionParams& parameters) {
gfx::win::MaybeInitializeDirectWrite();
bool use_direct_write = gfx::win::IsDirectWriteEnabled();
if (use_direct_write) {
- if (ShouldUseDirectWriteFontProxyFieldTrial()) {
- InitializeDWriteFontProxy(
- base::Bind(&ppapi::proxy::PluginGlobals::GetBrowserSender,
- base::Unretained(ppapi::proxy::PluginGlobals::Get())));
- } else {
- WarmupDirectWrite();
- }
+ InitializeDWriteFontProxy();
} else {
SkTypeface_SetEnsureLOGFONTAccessibleProc(SkiaPreCacheFont);
}
@@ -160,8 +155,7 @@ int PpapiPluginMain(const MainFunctionParams& parameters) {
main_message_loop.Run();
#if defined(OS_WIN)
- if (ShouldUseDirectWriteFontProxyFieldTrial())
- UninitializeDWriteFontProxy();
+ UninitializeDWriteFontProxy();
#endif
return 0;
}
diff --git a/chromium/content/ppapi_plugin/ppapi_thread.cc b/chromium/content/ppapi_plugin/ppapi_thread.cc
index c1cd0801d07..8e0724b5e6b 100644
--- a/chromium/content/ppapi_plugin/ppapi_thread.cc
+++ b/chromium/content/ppapi_plugin/ppapi_thread.cc
@@ -36,7 +36,6 @@
#include "content/public/common/content_switches.h"
#include "content/public/common/pepper_plugin_info.h"
#include "content/public/common/sandbox_init.h"
-#include "content/public/plugin/content_plugin_client.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_platform_file.h"
#include "ipc/ipc_sync_channel.h"
@@ -55,7 +54,7 @@
#if defined(OS_WIN)
#include "base/win/win_util.h"
#include "base/win/windows_version.h"
-#include "content/common/font_warmup_win.h"
+#include "content/child/font_warmup_win.h"
#include "sandbox/win/src/sandbox.h"
#elif defined(OS_MACOSX)
#include "content/common/sandbox_init_mac.h"
@@ -118,7 +117,7 @@ PpapiThread::PpapiThread(const base::CommandLine& command_line, bool is_broker)
command_line.GetSwitchValueASCII(switches::kPpapiFlashArgs));
blink_platform_impl_.reset(new PpapiBlinkPlatformImpl);
- blink::initializeWithoutV8(blink_platform_impl_.get());
+ blink::Platform::initialize(blink_platform_impl_.get());
if (!is_broker_) {
scoped_refptr<ppapi::proxy::PluginMessageFilter> plugin_filter(
@@ -146,7 +145,7 @@ void PpapiThread::Shutdown() {
if (plugin_entry_points_.shutdown_module)
plugin_entry_points_.shutdown_module();
blink_platform_impl_->Shutdown();
- blink::shutdownWithoutV8();
+ blink::Platform::shutdown();
}
bool PpapiThread::Send(IPC::Message* msg) {
@@ -196,8 +195,7 @@ IPC::PlatformFileForTransit PpapiThread::ShareHandleWithRemote(
#if defined(OS_WIN)
if (peer_handle_.IsValid()) {
DCHECK(is_broker_);
- return IPC::GetFileHandleForProcess(handle, peer_handle_.Get(),
- should_close_source);
+ return IPC::GetPlatformFileForTransit(handle, should_close_source);
}
#endif
@@ -208,27 +206,8 @@ IPC::PlatformFileForTransit PpapiThread::ShareHandleWithRemote(
base::SharedMemoryHandle PpapiThread::ShareSharedMemoryHandleWithRemote(
const base::SharedMemoryHandle& handle,
base::ProcessId remote_pid) {
-#if defined(OS_WIN)
- if (peer_handle_.IsValid()) {
- DCHECK(is_broker_);
- IPC::PlatformFileForTransit platform_file = IPC::GetFileHandleForProcess(
- handle.GetHandle(), peer_handle_.Get(), false);
- base::ProcessId pid = base::GetProcId(peer_handle_.Get());
- return base::SharedMemoryHandle(platform_file, pid);
- }
-#endif
-
DCHECK(remote_pid != base::kNullProcessId);
-#if defined(OS_WIN) || defined(OS_MACOSX)
- base::SharedMemoryHandle duped_handle;
- bool success =
- BrokerDuplicateSharedMemoryHandle(handle, remote_pid, &duped_handle);
- if (success)
- return duped_handle;
- return base::SharedMemory::NULLHandle();
-#else
return base::SharedMemory::DuplicateHandle(handle);
-#endif // defined(OS_WIN) || defined(OS_MACOSX)
}
std::set<PP_Instance>* PpapiThread::GetGloballySeenInstanceIDSet() {
@@ -569,13 +548,6 @@ bool PpapiThread::SetupRendererChannel(base::ProcessId renderer_pid,
void PpapiThread::SavePluginName(const base::FilePath& path) {
ppapi::proxy::PluginGlobals::Get()->set_plugin_name(
path.BaseName().AsUTF8Unsafe());
-
- // plugin() is NULL when in-process, which is fine, because this is
- // just a hook for setting the process name.
- if (GetContentClient()->plugin()) {
- GetContentClient()->plugin()->PluginProcessStarted(
- path.BaseName().RemoveExtension().LossyDisplayName());
- }
}
static std::string GetHistogramName(bool is_broker,
diff --git a/chromium/content/public/DEPS b/chromium/content/public/DEPS
index 7358adbd762..d811be30bb6 100644
--- a/chromium/content/public/DEPS
+++ b/chromium/content/public/DEPS
@@ -1,6 +1,8 @@
include_rules = [
"-content",
+ "+mojo/shell/public",
+
# This file does not belong in content/public as it should not be
# included directly by embedders of content/. It must however be
# available to code in content/public.
diff --git a/chromium/content/public/android/BUILD.gn b/chromium/content/public/android/BUILD.gn
index e726c4634a5..071478c1640 100644
--- a/chromium/content/public/android/BUILD.gn
+++ b/chromium/content/public/android/BUILD.gn
@@ -39,6 +39,7 @@ android_library("content_java") {
"//device/vibration:mojo_bindings_java",
"//device/vibration/android:vibration_manager_android",
"//media/base/android:media_java",
+ "//media/capture/video/android:capture_java",
"//media/midi:midi_java",
"//mojo/android:system_java",
"//mojo/public/java:bindings",
@@ -61,7 +62,151 @@ android_library("content_java") {
"//ui/touch_selection:ui_touch_handle_orientation_srcjar",
]
- DEPRECATED_java_in_dir = "java/src"
+ java_files = [
+ "java/src/org/chromium/content/app/ChildProcessService.java",
+ "java/src/org/chromium/content/app/ChromiumLinkerParams.java",
+ "java/src/org/chromium/content/app/ContentApplication.java",
+ "java/src/org/chromium/content/app/ContentMain.java",
+ "java/src/org/chromium/content/app/DownloadProcessService.java",
+ "java/src/org/chromium/content/app/PrivilegedProcessService.java",
+ "java/src/org/chromium/content/app/PrivilegedProcessService0.java",
+ "java/src/org/chromium/content/app/PrivilegedProcessService1.java",
+ "java/src/org/chromium/content/app/PrivilegedProcessService2.java",
+ "java/src/org/chromium/content/app/SandboxedProcessService.java",
+ "java/src/org/chromium/content/app/SandboxedProcessService0.java",
+ "java/src/org/chromium/content/app/SandboxedProcessService1.java",
+ "java/src/org/chromium/content/app/SandboxedProcessService10.java",
+ "java/src/org/chromium/content/app/SandboxedProcessService11.java",
+ "java/src/org/chromium/content/app/SandboxedProcessService12.java",
+ "java/src/org/chromium/content/app/SandboxedProcessService13.java",
+ "java/src/org/chromium/content/app/SandboxedProcessService14.java",
+ "java/src/org/chromium/content/app/SandboxedProcessService15.java",
+ "java/src/org/chromium/content/app/SandboxedProcessService16.java",
+ "java/src/org/chromium/content/app/SandboxedProcessService17.java",
+ "java/src/org/chromium/content/app/SandboxedProcessService18.java",
+ "java/src/org/chromium/content/app/SandboxedProcessService19.java",
+ "java/src/org/chromium/content/app/SandboxedProcessService2.java",
+ "java/src/org/chromium/content/app/SandboxedProcessService3.java",
+ "java/src/org/chromium/content/app/SandboxedProcessService4.java",
+ "java/src/org/chromium/content/app/SandboxedProcessService5.java",
+ "java/src/org/chromium/content/app/SandboxedProcessService6.java",
+ "java/src/org/chromium/content/app/SandboxedProcessService7.java",
+ "java/src/org/chromium/content/app/SandboxedProcessService8.java",
+ "java/src/org/chromium/content/app/SandboxedProcessService9.java",
+ "java/src/org/chromium/content/browser/ActivityContentVideoViewEmbedder.java",
+ "java/src/org/chromium/content/browser/BackgroundSyncNetworkObserver.java",
+ "java/src/org/chromium/content/browser/BindingManager.java",
+ "java/src/org/chromium/content/browser/BindingManagerImpl.java",
+ "java/src/org/chromium/content/browser/BrowserStartupController.java",
+ "java/src/org/chromium/content/browser/ChildProcessConnection.java",
+ "java/src/org/chromium/content/browser/ChildProcessConnectionImpl.java",
+ "java/src/org/chromium/content/browser/ChildProcessConstants.java",
+ "java/src/org/chromium/content/browser/ChildProcessLauncher.java",
+ "java/src/org/chromium/content/browser/ContainerViewObserver.java",
+ "java/src/org/chromium/content/browser/ContentVideoView.java",
+ "java/src/org/chromium/content/browser/ContentVideoViewEmbedder.java",
+ "java/src/org/chromium/content/browser/ContentView.java",
+ "java/src/org/chromium/content/browser/ContentViewClient.java",
+ "java/src/org/chromium/content/browser/ContentViewCore.java",
+ "java/src/org/chromium/content/browser/ContentViewDownloadDelegate.java",
+ "java/src/org/chromium/content/browser/ContentViewRenderView.java",
+ "java/src/org/chromium/content/browser/ContentViewStatics.java",
+ "java/src/org/chromium/content/browser/ContextualSearchClient.java",
+ "java/src/org/chromium/content/browser/DeviceSensors.java",
+ "java/src/org/chromium/content/browser/DeviceUtils.java",
+ "java/src/org/chromium/content/browser/DownloadController.java",
+ "java/src/org/chromium/content/browser/DownloadInfo.java",
+ "java/src/org/chromium/content/browser/FileDescriptorInfo.java",
+ "java/src/org/chromium/content/browser/FloatingWebActionModeCallback.java",
+ "java/src/org/chromium/content/browser/InterstitialPageDelegateAndroid.java",
+ "java/src/org/chromium/content/browser/JavascriptInterface.java",
+ "java/src/org/chromium/content/browser/LocationProviderAdapter.java",
+ "java/src/org/chromium/content/browser/LocationProviderFactory.java",
+ "java/src/org/chromium/content/browser/MediaResourceGetter.java",
+ "java/src/org/chromium/content/browser/MediaSessionDelegate.java",
+ "java/src/org/chromium/content/browser/MediaThrottler.java",
+ "java/src/org/chromium/content/browser/MotionEventSynthesizer.java",
+ "java/src/org/chromium/content/browser/OverscrollRefreshHandler.java",
+ "java/src/org/chromium/content/browser/PepperPluginManager.java",
+ "java/src/org/chromium/content/browser/PopupZoomer.java",
+ "java/src/org/chromium/content/browser/PositionObserver.java",
+ "java/src/org/chromium/content/browser/PowerSaveBlocker.java",
+ "java/src/org/chromium/content/browser/RenderCoordinates.java",
+ "java/src/org/chromium/content/browser/SPenSupport.java",
+ "java/src/org/chromium/content/browser/ScreenOrientationListener.java",
+ "java/src/org/chromium/content/browser/ScreenOrientationProvider.java",
+ "java/src/org/chromium/content/browser/ServiceRegistrar.java",
+ "java/src/org/chromium/content/browser/ServiceRegistry.java",
+ "java/src/org/chromium/content/browser/SmartClipProvider.java",
+ "java/src/org/chromium/content/browser/SpeechRecognition.java",
+ "java/src/org/chromium/content/browser/TimeZoneMonitor.java",
+ "java/src/org/chromium/content/browser/TracingControllerAndroid.java",
+ "java/src/org/chromium/content/browser/ViewPositionObserver.java",
+ "java/src/org/chromium/content/browser/WebActionMode.java",
+ "java/src/org/chromium/content/browser/WebActionModeCallback.java",
+ "java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityManager.java",
+ "java/src/org/chromium/content/browser/accessibility/KitKatBrowserAccessibilityManager.java",
+ "java/src/org/chromium/content/browser/accessibility/LollipopBrowserAccessibilityManager.java",
+ "java/src/org/chromium/content/browser/accessibility/captioning/CaptioningBridgeFactory.java",
+ "java/src/org/chromium/content/browser/accessibility/captioning/CaptioningChangeDelegate.java",
+ "java/src/org/chromium/content/browser/accessibility/captioning/CaptioningStyle.java",
+ "java/src/org/chromium/content/browser/accessibility/captioning/EmptyCaptioningBridge.java",
+ "java/src/org/chromium/content/browser/accessibility/captioning/KitKatCaptioningBridge.java",
+ "java/src/org/chromium/content/browser/accessibility/captioning/SystemCaptioningBridge.java",
+ "java/src/org/chromium/content/browser/accessibility/captioning/TextTrackSettings.java",
+ "java/src/org/chromium/content/browser/crypto/ByteArrayGenerator.java",
+ "java/src/org/chromium/content/browser/crypto/CipherFactory.java",
+ "java/src/org/chromium/content/browser/framehost/NavigationControllerImpl.java",
+ "java/src/org/chromium/content/browser/input/AnimationIntervalProvider.java",
+ "java/src/org/chromium/content/browser/input/CardboardVRDevice.java",
+ "java/src/org/chromium/content/browser/input/ChromiumBaseInputConnection.java",
+ "java/src/org/chromium/content/browser/input/CursorAnchorInfoController.java",
+ "java/src/org/chromium/content/browser/input/DateTimeChooserAndroid.java",
+ "java/src/org/chromium/content/browser/input/FloatingPastePopupMenu.java",
+ "java/src/org/chromium/content/browser/input/GamepadDevice.java",
+ "java/src/org/chromium/content/browser/input/GamepadList.java",
+ "java/src/org/chromium/content/browser/input/GamepadMappings.java",
+ "java/src/org/chromium/content/browser/input/HandleViewResources.java",
+ "java/src/org/chromium/content/browser/input/ImeAdapter.java",
+ "java/src/org/chromium/content/browser/input/ImeUtils.java",
+ "java/src/org/chromium/content/browser/input/InputMethodManagerWrapper.java",
+ "java/src/org/chromium/content/browser/input/InputMethodUma.java",
+ "java/src/org/chromium/content/browser/input/JoystickScrollProvider.java",
+ "java/src/org/chromium/content/browser/input/JoystickZoomProvider.java",
+ "java/src/org/chromium/content/browser/input/LegacyPastePopupMenu.java",
+ "java/src/org/chromium/content/browser/input/PastePopupMenu.java",
+ "java/src/org/chromium/content/browser/input/PopupTouchHandleDrawable.java",
+ "java/src/org/chromium/content/browser/input/Range.java",
+ "java/src/org/chromium/content/browser/input/ReplicaInputConnection.java",
+ "java/src/org/chromium/content/browser/input/SelectPopup.java",
+ "java/src/org/chromium/content/browser/input/SelectPopupAdapter.java",
+ "java/src/org/chromium/content/browser/input/SelectPopupDialog.java",
+ "java/src/org/chromium/content/browser/input/SelectPopupDropdown.java",
+ "java/src/org/chromium/content/browser/input/SelectPopupItem.java",
+ "java/src/org/chromium/content/browser/input/TextInputState.java",
+ "java/src/org/chromium/content/browser/input/ThreadedInputConnection.java",
+ "java/src/org/chromium/content/browser/input/ThreadedInputConnectionFactory.java",
+ "java/src/org/chromium/content/browser/input/ThreadedInputConnectionProxyView.java",
+ "java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java",
+ "java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java",
+ "java/src/org/chromium/content/common/CleanupReference.java",
+ "java/src/org/chromium/content/common/ContentSwitches.java",
+ "java/src/org/chromium/content/common/SurfaceWrapper.java",
+ "java/src/org/chromium/content_public/browser/AccessibilitySnapshotCallback.java",
+ "java/src/org/chromium/content_public/browser/AccessibilitySnapshotNode.java",
+ "java/src/org/chromium/content_public/browser/ContentBitmapCallback.java",
+ "java/src/org/chromium/content_public/browser/GestureStateListener.java",
+ "java/src/org/chromium/content_public/browser/JavaScriptCallback.java",
+ "java/src/org/chromium/content_public/browser/LoadUrlParams.java",
+ "java/src/org/chromium/content_public/browser/NavigationController.java",
+ "java/src/org/chromium/content_public/browser/NavigationEntry.java",
+ "java/src/org/chromium/content_public/browser/NavigationHistory.java",
+ "java/src/org/chromium/content_public/browser/WebContents.java",
+ "java/src/org/chromium/content_public/browser/WebContentsObserver.java",
+ "java/src/org/chromium/content_public/common/MediaMetadata.java",
+ "java/src/org/chromium/content_public/common/Referrer.java",
+ "java/src/org/chromium/content_public/common/ScreenOrientationConstants.java",
+ ]
if (enable_webvr) {
deps += [ "//third_party/cardboard-java:cardboard-java" ]
@@ -177,6 +322,7 @@ android_library("content_javatests") {
"//device/vibration:mojo_bindings_java",
"//device/vibration/android:vibration_manager_android",
"//media/base/android:media_java",
+ "//media/capture/video/android:capture_java",
"//mojo/android:system_java",
"//mojo/public/interfaces/bindings/tests:test_interfaces_java",
"//mojo/public/java:bindings",
@@ -188,12 +334,74 @@ android_library("content_javatests") {
"//ui/android:ui_java",
]
- DEPRECATED_java_in_dir = "javatests/src"
+ java_files = [
+ "javatests/src/org/chromium/content/browser/AddressDetectionTest.java",
+ "javatests/src/org/chromium/content/browser/BrowserStartupControllerTest.java",
+ "javatests/src/org/chromium/content/browser/ChildProcessLauncherTest.java",
+ "javatests/src/org/chromium/content/browser/ClickListenerTest.java",
+ "javatests/src/org/chromium/content/browser/ClipboardTest.java",
+ "javatests/src/org/chromium/content/browser/ContentCommandLineTest.java",
+ "javatests/src/org/chromium/content/browser/ContentDetectionTestBase.java",
+ "javatests/src/org/chromium/content/browser/ContentViewCoreFocusTest.java",
+ "javatests/src/org/chromium/content/browser/ContentViewCoreSelectionTest.java",
+ "javatests/src/org/chromium/content/browser/ContentViewCoreViewAndroidDelegateTest.java",
+ "javatests/src/org/chromium/content/browser/ContentViewLocationTest.java",
+ "javatests/src/org/chromium/content/browser/ContentViewPopupZoomerTest.java",
+ "javatests/src/org/chromium/content/browser/ContentViewScrollingTest.java",
+ "javatests/src/org/chromium/content/browser/ContentViewZoomingTest.java",
+ "javatests/src/org/chromium/content/browser/DeviceSensorsTest.java",
+ "javatests/src/org/chromium/content/browser/DownloadInfoTest.java",
+ "javatests/src/org/chromium/content/browser/EmailAddressDetectionTest.java",
+ "javatests/src/org/chromium/content/browser/EncodeHtmlDataUriTest.java",
+ "javatests/src/org/chromium/content/browser/GestureDetectorResetTest.java",
+ "javatests/src/org/chromium/content/browser/ImportantFileWriterAndroidTest.java",
+ "javatests/src/org/chromium/content/browser/InterstitialPageTest.java",
+ "javatests/src/org/chromium/content/browser/JavaBridgeArrayCoercionTest.java",
+ "javatests/src/org/chromium/content/browser/JavaBridgeArrayTest.java",
+ "javatests/src/org/chromium/content/browser/JavaBridgeBareboneTest.java",
+ "javatests/src/org/chromium/content/browser/JavaBridgeBasicsTest.java",
+ "javatests/src/org/chromium/content/browser/JavaBridgeChildFrameTest.java",
+ "javatests/src/org/chromium/content/browser/JavaBridgeCoercionTest.java",
+ "javatests/src/org/chromium/content/browser/JavaBridgeFieldsTest.java",
+ "javatests/src/org/chromium/content/browser/JavaBridgeReturnValuesTest.java",
+ "javatests/src/org/chromium/content/browser/JavaBridgeTestBase.java",
+ "javatests/src/org/chromium/content/browser/LocationProviderTest.java",
+ "javatests/src/org/chromium/content/browser/MediaResourceGetterTest.java",
+ "javatests/src/org/chromium/content/browser/MediaSessionTest.java",
+ "javatests/src/org/chromium/content/browser/NavigationTest.java",
+ "javatests/src/org/chromium/content/browser/PhoneNumberDetectionTest.java",
+ "javatests/src/org/chromium/content/browser/PopupZoomerTest.java",
+ "javatests/src/org/chromium/content/browser/ScreenOrientationListenerTest.java",
+ "javatests/src/org/chromium/content/browser/ScreenOrientationProviderTest.java",
+ "javatests/src/org/chromium/content/browser/ServiceRegistryTest.java",
+ "javatests/src/org/chromium/content/browser/TestsJavaScriptEvalTest.java",
+ "javatests/src/org/chromium/content/browser/TracingControllerAndroidTest.java",
+ "javatests/src/org/chromium/content/browser/VSyncMonitorTest.java",
+ "javatests/src/org/chromium/content/browser/VibrationManagerImplTest.java",
+ "javatests/src/org/chromium/content/browser/ViewportTest.java",
+ "javatests/src/org/chromium/content/browser/WebContentsObserverAndroidTest.java",
+ "javatests/src/org/chromium/content/browser/accessibility/captioning/CaptioningChangeDelegateTest.java",
+ "javatests/src/org/chromium/content/browser/crypto/CipherFactoryTest.java",
+ "javatests/src/org/chromium/content/browser/input/CursorAnchorInfoControllerTest.java",
+ "javatests/src/org/chromium/content/browser/input/ImeLollipopTest.java",
+ "javatests/src/org/chromium/content/browser/input/ImeTest.java",
+ "javatests/src/org/chromium/content/browser/input/ImeTestUtils.java",
+ "javatests/src/org/chromium/content/browser/input/InputDialogContainerTest.java",
+ "javatests/src/org/chromium/content/browser/input/ReplicaInputConnectionTest.java",
+ "javatests/src/org/chromium/content/browser/input/SelectPopupTest.java",
+ "javatests/src/org/chromium/content/browser/input/TestImeAdapterDelegate.java",
+ "javatests/src/org/chromium/content/browser/webcontents/AccessibilitySnapshotTest.java",
+ "javatests/src/org/chromium/content/browser/webcontents/WebContentsTest.java",
+ "javatests/src/org/chromium/content/common/CleanupReferenceTest.java",
+ ]
}
# GYP: //content/content_tests.gypi:content_junit_tests
junit_binary("content_junit_tests") {
- java_files = [ "junit/src/org/chromium/content/browser/input/GamepadMappingsTest.java" ]
+ java_files = [
+ "junit/src/org/chromium/content/browser/input/GamepadMappingsTest.java",
+ "junit/src/org/chromium/content/browser/BindingManagerImplTest.java",
+ ]
deps = [
":content_java",
"//base:base_java",
diff --git a/chromium/content/public/app/BUILD.gn b/chromium/content/public/app/BUILD.gn
index aade0abbc50..5fe62495402 100644
--- a/chromium/content/public/app/BUILD.gn
+++ b/chromium/content/public/app/BUILD.gn
@@ -21,6 +21,7 @@
# //content/public/app:both_sources (source set)
import("//build/config/chrome_build.gni")
+import("//mojo/public/mojo_application_manifest.gni")
public_app_shared_sources = [
"content_jni_onload.h",
@@ -36,6 +37,9 @@ public_app_shared_deps = [
"//base:i18n",
"//content:export",
"//content/public/common:common_sources",
+ "//content/public/gpu:gpu_sources",
+ "//content/public/renderer:renderer_sources",
+ "//content/public/utility:utility_sources",
]
if (is_component_build) {
@@ -137,3 +141,15 @@ if (is_component_build) {
}
}
}
+
+mojo_application_manifest("browser_manifest") {
+ type = "exe"
+ application_name = "content_browser"
+ source = "mojo/content_browser_manifest.json"
+}
+
+mojo_application_manifest("renderer_manifest") {
+ type = "exe"
+ application_name = "content_renderer"
+ source = "mojo/content_renderer_manifest.json"
+}
diff --git a/chromium/content/public/app/DEPS b/chromium/content/public/app/DEPS
index 255cb723a1d..8fe71581df8 100644
--- a/chromium/content/public/app/DEPS
+++ b/chromium/content/public/app/DEPS
@@ -1,6 +1,6 @@
include_rules = [
"+content/public/browser/content_browser_client.h",
- "+content/public/plugin/content_plugin_client.h",
+ "+content/public/gpu/content_gpu_client.h",
"+content/public/renderer/content_renderer_client.h",
"+content/public/utility/content_utility_client.h",
]
diff --git a/chromium/content/public/app/content_main_delegate.cc b/chromium/content/public/app/content_main_delegate.cc
index 3c979be537e..d833cb0abc2 100644
--- a/chromium/content/public/app/content_main_delegate.cc
+++ b/chromium/content/public/app/content_main_delegate.cc
@@ -6,14 +6,12 @@
#include "build/build_config.h"
-#if !defined(CHROME_MULTIPLE_DLL_CHILD)
-#include "content/public/browser/content_browser_client.h"
-#endif
-
-#if !defined(OS_IOS)
-#include "content/public/plugin/content_plugin_client.h"
+#include "content/public/gpu/content_gpu_client.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/public/utility/content_utility_client.h"
+
+#if !defined(CHROME_MULTIPLE_DLL_CHILD)
+#include "content/public/browser/content_browser_client.h"
#endif
namespace content {
@@ -28,7 +26,7 @@ int ContentMainDelegate::RunProcess(
return -1;
}
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MACOSX)
bool ContentMainDelegate::ProcessRegistersWithSystemProcess(
const std::string& process_type) {
@@ -44,7 +42,7 @@ bool ContentMainDelegate::DelaySandboxInitialization(
return false;
}
-#elif defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_IOS)
+#elif defined(OS_POSIX) && !defined(OS_ANDROID)
void ContentMainDelegate::ZygoteStarting(
ScopedVector<ZygoteForkDelegate>* delegates) {
@@ -64,16 +62,16 @@ ContentBrowserClient* ContentMainDelegate::CreateContentBrowserClient() {
#endif
}
-ContentPluginClient* ContentMainDelegate::CreateContentPluginClient() {
-#if defined(OS_IOS) || defined(CHROME_MULTIPLE_DLL_BROWSER)
+ContentGpuClient* ContentMainDelegate::CreateContentGpuClient() {
+#if defined(CHROME_MULTIPLE_DLL_BROWSER)
return NULL;
#else
- return new ContentPluginClient();
+ return new ContentGpuClient();
#endif
}
ContentRendererClient* ContentMainDelegate::CreateContentRendererClient() {
-#if defined(OS_IOS) || defined(CHROME_MULTIPLE_DLL_BROWSER)
+#if defined(CHROME_MULTIPLE_DLL_BROWSER)
return NULL;
#else
return new ContentRendererClient();
@@ -81,7 +79,7 @@ ContentRendererClient* ContentMainDelegate::CreateContentRendererClient() {
}
ContentUtilityClient* ContentMainDelegate::CreateContentUtilityClient() {
-#if defined(OS_IOS) || defined(CHROME_MULTIPLE_DLL_BROWSER)
+#if defined(CHROME_MULTIPLE_DLL_BROWSER)
return NULL;
#else
return new ContentUtilityClient();
diff --git a/chromium/content/public/app/content_main_delegate.h b/chromium/content/public/app/content_main_delegate.h
index 6bd725d0f5c..1dcb57fadee 100644
--- a/chromium/content/public/app/content_main_delegate.h
+++ b/chromium/content/public/app/content_main_delegate.h
@@ -16,7 +16,7 @@ class ScopedVector;
namespace content {
class ContentBrowserClient;
-class ContentPluginClient;
+class ContentGpuClient;
class ContentRendererClient;
class ContentUtilityClient;
class ZygoteForkDelegate;
@@ -49,7 +49,7 @@ class CONTENT_EXPORT ContentMainDelegate {
// Called right before the process exits.
virtual void ProcessExiting(const std::string& process_type) {}
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MACOSX)
// Returns true if the process registers with the system monitor, so that we
// can allocate an IO port for it before the sandbox is initialized. Embedders
// are called only for process types that content doesn't know about.
@@ -66,7 +66,7 @@ class CONTENT_EXPORT ContentMainDelegate {
// want it at all.
virtual bool DelaySandboxInitialization(const std::string& process_type);
-#elif defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_IOS)
+#elif defined(OS_POSIX) && !defined(OS_ANDROID)
// Tells the embedder that the zygote process is starting, and allows it to
// specify one or more zygote delegates if it wishes by storing them in
// |*delegates|.
@@ -88,7 +88,7 @@ class CONTENT_EXPORT ContentMainDelegate {
// content. If an embedder wants the default (empty) implementation, don't
// override this.
virtual ContentBrowserClient* CreateContentBrowserClient();
- virtual ContentPluginClient* CreateContentPluginClient();
+ virtual ContentGpuClient* CreateContentGpuClient();
virtual ContentRendererClient* CreateContentRendererClient();
virtual ContentUtilityClient* CreateContentUtilityClient();
};
diff --git a/chromium/content/public/app/mojo/content_browser_manifest.json b/chromium/content/public/app/mojo/content_browser_manifest.json
new file mode 100644
index 00000000000..96ff4737578
--- /dev/null
+++ b/chromium/content/public/app/mojo/content_browser_manifest.json
@@ -0,0 +1,14 @@
+{
+ "manifest_version": 1,
+ "name": "exe:content_browser",
+ "display_name": "Content Browser",
+ "capabilities": {
+ "required": {
+ "*": { "interfaces": [ "*" ] },
+ "mojo:shell": {
+ "classes": [ "client_process", "instance_name" ],
+ "interfaces": [ "*" ]
+ }
+ }
+ }
+}
diff --git a/chromium/content/public/app/mojo/content_renderer_manifest.json b/chromium/content/public/app/mojo/content_renderer_manifest.json
new file mode 100644
index 00000000000..053edd01bea
--- /dev/null
+++ b/chromium/content/public/app/mojo/content_renderer_manifest.json
@@ -0,0 +1,5 @@
+{
+ "name": "exe:content_renderer",
+ "display_name": "Content Renderer",
+ "capabilities": { "mojo:mus": [ "mus::mojom::Gpu" ] }
+}
diff --git a/chromium/content/public/browser/BUILD.gn b/chromium/content/public/browser/BUILD.gn
index 89fdec11fd4..5b04b1e5ad3 100644
--- a/chromium/content/public/browser/BUILD.gn
+++ b/chromium/content/public/browser/BUILD.gn
@@ -19,29 +19,12 @@ group("browser") {
}
source_set("browser_sources") {
+ # External code should depend on via ":browser" above.
visibility = [ "//content/*" ]
- if (is_ios) {
- # iOS doesn't get the normal file list and only takes these whitelisted
- # files.
- sources = [
- "browser_main_parts.cc",
- "content_browser_client.cc",
- "favicon_status.cc",
- "navigation_details.cc",
- "notification_registrar.cc",
- "page_navigator.cc",
- "web_ui_controller.cc",
- ]
- } else {
- sources = rebase_path(content_browser_gypi_values.public_browser_sources,
- ".",
- "//content")
- }
-
- if (use_aura) {
- sources -= [ "context_factory.h" ]
- }
+ sources = rebase_path(content_browser_gypi_values.public_browser_sources,
+ ".",
+ "//content")
configs += [
"//build/config:precompiled_headers",
@@ -57,12 +40,19 @@ source_set("browser_sources") {
"//skia",
]
deps = [
- "//content/browser",
+ "//cc",
+ "//content/browser", # Must not be public_deps!
"//content/public/common:common_sources",
+ "//gpu",
+ "//media",
"//net",
+ "//ppapi/c",
+ "//storage/browser",
"//ui/accessibility",
"//ui/base",
"//ui/events",
+ "//ui/gl",
+ "//ui/surface",
]
allow_circular_includes_from = [
@@ -70,4 +60,13 @@ source_set("browser_sources") {
# include headers from each other.
"//content/browser",
]
+
+ if (is_android) {
+ deps += [ "//ui/android" ]
+ }
+
+ if (use_aura) {
+ sources -= [ "context_factory.h" ]
+ deps += [ "//ui/aura" ]
+ }
}
diff --git a/chromium/content/public/browser/access_token_store.h b/chromium/content/public/browser/access_token_store.h
index bd130144c6c..bf1483a801a 100644
--- a/chromium/content/public/browser/access_token_store.h
+++ b/chromium/content/public/browser/access_token_store.h
@@ -33,18 +33,16 @@ namespace content {
class AccessTokenStore : public base::RefCountedThreadSafe<AccessTokenStore> {
public:
// Map of server URLs to associated access token.
- typedef std::map<GURL, base::string16> AccessTokenSet;
- typedef base::Callback<void(AccessTokenSet, net::URLRequestContextGetter*)>
- LoadAccessTokensCallbackType;
+ typedef std::map<GURL, base::string16> AccessTokenMap;
+ typedef base::Callback<void(AccessTokenMap, net::URLRequestContextGetter*)>
+ LoadAccessTokensCallback;
// |callback| will be invoked once per LoadAccessTokens call, after existing
// access tokens have been loaded from persistent store. As a convenience the
// URLRequestContextGetter is also supplied as an argument in |callback|, as
// in Chrome the call to obtain this must also be performed on the UI thread
// so it is efficient to piggyback it onto this request.
- // Takes ownership of |callback|.
- virtual void LoadAccessTokens(
- const LoadAccessTokensCallbackType& callback) = 0;
+ virtual void LoadAccessTokens(const LoadAccessTokensCallback& callback) = 0;
virtual void SaveAccessToken(
const GURL& server_url, const base::string16& access_token) = 0;
diff --git a/chromium/content/public/browser/android/compositor.h b/chromium/content/public/browser/android/compositor.h
index 6ce49e98b87..1a96ee6ee90 100644
--- a/chromium/content/public/browser/android/compositor.h
+++ b/chromium/content/public/browser/android/compositor.h
@@ -17,7 +17,6 @@ class SkBitmap;
namespace cc {
class Layer;
-class LayerSettings;
}
namespace gfx {
@@ -46,9 +45,6 @@ class CONTENT_EXPORT Compositor {
static Compositor* Create(CompositorClient* client,
gfx::NativeWindow root_window);
- static const cc::LayerSettings& LayerSettings();
- static void SetLayerSettings(const cc::LayerSettings& settings);
-
// Attaches the layer tree.
virtual void SetRootLayer(scoped_refptr<cc::Layer> root) = 0;
diff --git a/chromium/content/public/browser/android/download_controller_android.h b/chromium/content/public/browser/android/download_controller_android.h
index 859a8a0a4e7..7eda0e9774b 100644
--- a/chromium/content/public/browser/android/download_controller_android.h
+++ b/chromium/content/public/browser/android/download_controller_android.h
@@ -7,6 +7,7 @@
#include "base/callback.h"
#include "content/common/content_export.h"
+#include "content/public/browser/download_item.h"
#include "content/public/common/context_menu_params.h"
namespace content {
@@ -15,7 +16,7 @@ class WebContents;
// Interface to request GET downloads and send notifications for POST
// downloads.
-class CONTENT_EXPORT DownloadControllerAndroid {
+class CONTENT_EXPORT DownloadControllerAndroid : public DownloadItem::Observer {
public:
// Returns the singleton instance of the DownloadControllerAndroid.
static DownloadControllerAndroid* Get();
@@ -27,7 +28,7 @@ class CONTENT_EXPORT DownloadControllerAndroid {
// Starts a new download request with Android. Should be called on the
// UI thread.
virtual void CreateGETDownload(int render_process_id, int render_view_id,
- int request_id) = 0;
+ int request_id, bool must_download) = 0;
// Should be called when a download is started. It can be either a GET
// request with authentication or a POST request. Notifies the embedding
@@ -40,8 +41,9 @@ class CONTENT_EXPORT DownloadControllerAndroid {
bool is_link, const std::string& extra_headers) = 0;
// Called when a dangerous download item is verified or rejected.
- virtual void DangerousDownloadValidated(
- WebContents* web_contents, int download_id, bool accept) = 0;
+ virtual void DangerousDownloadValidated(WebContents* web_contents,
+ const std::string& download_guid,
+ bool accept) = 0;
// Callback when user permission prompt finishes. Args: whether file access
// permission is acquired.
@@ -56,8 +58,12 @@ class CONTENT_EXPORT DownloadControllerAndroid {
// Called by unit test to approve or disapprove file access request.
virtual void SetApproveFileAccessRequestForTesting(bool approve) {};
+ // Called to set the default download file name if it cannot be resolved
+ // from url and content disposition
+ virtual void SetDefaultDownloadFileName(const std::string& file_name) {}
+
protected:
- virtual ~DownloadControllerAndroid() {};
+ ~DownloadControllerAndroid() override {};
static DownloadControllerAndroid* download_controller_;
};
diff --git a/chromium/content/public/browser/android/service_registry_android.h b/chromium/content/public/browser/android/service_registry_android.h
new file mode 100644
index 00000000000..e134b431ab7
--- /dev/null
+++ b/chromium/content/public/browser/android/service_registry_android.h
@@ -0,0 +1,51 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_BROWSER_ANDROID_SERVICE_REGISTRY_ANDROID_H_
+#define CONTENT_PUBLIC_BROWSER_ANDROID_SERVICE_REGISTRY_ANDROID_H_
+
+#include <jni.h>
+#include <memory>
+
+#include "base/android/scoped_java_ref.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class ServiceRegistry;
+
+// Android wrapper over ServiceRegistry, allowing the browser services in Java
+// to register with ServiceRegistry.java (and abstracting away the JNI calls).
+class CONTENT_EXPORT ServiceRegistryAndroid {
+ public:
+ virtual ~ServiceRegistryAndroid() {}
+
+ // The |registry| parameter must outlive |ServiceRegistryAndroid|.
+ static std::unique_ptr<ServiceRegistryAndroid> Create(
+ ServiceRegistry* registry);
+
+ // Called from Java.
+ virtual void AddService(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& j_service_registry,
+ const base::android::JavaParamRef<jobject>& j_manager,
+ const base::android::JavaParamRef<jobject>& j_factory,
+ const base::android::JavaParamRef<jstring>& j_name) = 0;
+ virtual void RemoveService(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& j_service_registry,
+ const base::android::JavaParamRef<jstring>& j_name) = 0;
+ virtual void ConnectToRemoteService(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& j_service_registry,
+ const base::android::JavaParamRef<jstring>& j_name,
+ jint handle) = 0;
+
+ // Accessor to the Java object.
+ virtual const base::android::ScopedJavaGlobalRef<jobject>& GetObj() = 0;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_ANDROID_SERVICE_REGISTRY_ANDROID_H_
diff --git a/chromium/content/public/browser/android/synchronous_compositor.cc b/chromium/content/public/browser/android/synchronous_compositor.cc
new file mode 100644
index 00000000000..4e52b6130c4
--- /dev/null
+++ b/chromium/content/public/browser/android/synchronous_compositor.cc
@@ -0,0 +1,27 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/browser/android/synchronous_compositor.h"
+
+#include <utility>
+
+#include "cc/output/compositor_frame.h"
+
+namespace content {
+
+SynchronousCompositor::Frame::Frame() : output_surface_id(0u) {}
+
+SynchronousCompositor::Frame::~Frame() {}
+
+SynchronousCompositor::Frame::Frame(Frame&& rhs)
+ : output_surface_id(rhs.output_surface_id), frame(std::move(rhs.frame)) {}
+
+SynchronousCompositor::Frame& SynchronousCompositor::Frame::operator=(
+ Frame&& rhs) {
+ output_surface_id = rhs.output_surface_id;
+ frame = std::move(rhs.frame);
+ return *this;
+}
+
+} // namespace content
diff --git a/chromium/content/public/browser/android/synchronous_compositor.h b/chromium/content/public/browser/android/synchronous_compositor.h
index e0d09d8d5b9..560f7428e68 100644
--- a/chromium/content/public/browser/android/synchronous_compositor.h
+++ b/chromium/content/public/browser/android/synchronous_compositor.h
@@ -21,6 +21,7 @@ class CompositorFrameAck;
}
namespace gfx {
+class Point;
class ScrollOffset;
class Transform;
};
@@ -47,9 +48,24 @@ class CONTENT_EXPORT SynchronousCompositor {
static void SetGpuService(
scoped_refptr<gpu::InProcessCommandBuffer::Service> service);
+ struct Frame {
+ Frame();
+ ~Frame();
+
+ // Movable type.
+ Frame(Frame&& rhs);
+ Frame& operator=(Frame&& rhs);
+
+ uint32_t output_surface_id;
+ scoped_ptr<cc::CompositorFrame> frame;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Frame);
+ };
+
// "On demand" hardware draw. The content is first clipped to |damage_area|,
// then transformed through |transform|, and finally clipped to |view_size|.
- virtual scoped_ptr<cc::CompositorFrame> DemandDrawHw(
+ virtual Frame DemandDrawHw(
const gfx::Size& surface_size,
const gfx::Transform& transform,
const gfx::Rect& viewport,
@@ -59,7 +75,8 @@ class CONTENT_EXPORT SynchronousCompositor {
// For delegated rendering, return resources from parent compositor to this.
// Note that all resources must be returned before ReleaseHwDraw.
- virtual void ReturnResources(const cc::CompositorFrameAck& frame_ack) = 0;
+ virtual void ReturnResources(uint32_t output_surface_id,
+ const cc::CompositorFrameAck& frame_ack) = 0;
// "On demand" SW draw, into the supplied canvas (observing the transform
// and clip set there-in).
@@ -73,6 +90,11 @@ class CONTENT_EXPORT SynchronousCompositor {
virtual void DidChangeRootLayerScrollOffset(
const gfx::ScrollOffset& root_offset) = 0;
+ // Allows embedder to synchronously update the zoom level, ie page scale
+ // factor, around the anchor point.
+ virtual void SynchronouslyZoomBy(float zoom_delta,
+ const gfx::Point& anchor) = 0;
+
// Called by the embedder to notify that the compositor is active. The
// compositor won't ask for vsyncs when it's inactive. NOTE: The compositor
// starts off as inactive and needs a SetActive(true) call to begin.
diff --git a/chromium/content/public/browser/arc_video_host_delegate.h b/chromium/content/public/browser/arc_video_host_delegate.h
deleted file mode 100644
index 08f54f8dca0..00000000000
--- a/chromium/content/public/browser/arc_video_host_delegate.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_PUBLIC_BROWSER_ARC_VIDEO_HOST_DELEGATE_H_
-#define CONTENT_PUBLIC_BROWSER_ARC_VIDEO_HOST_DELEGATE_H_
-
-#include "base/memory/scoped_ptr.h"
-#include "content/common/content_export.h"
-
-namespace arc {
-class VideoHostDelegate;
-}
-
-namespace content {
-
-CONTENT_EXPORT scoped_ptr<arc::VideoHostDelegate> CreateArcVideoHostDelegate();
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_BROWSER_ARC_VIDEO_HOST_DELEGATE_H_
diff --git a/chromium/content/public/browser/ax_event_notification_details.cc b/chromium/content/public/browser/ax_event_notification_details.cc
index ead942c8ae1..703f76f7137 100644
--- a/chromium/content/public/browser/ax_event_notification_details.cc
+++ b/chromium/content/public/browser/ax_event_notification_details.cc
@@ -12,6 +12,9 @@ AXEventNotificationDetails::AXEventNotificationDetails()
ax_tree_id(-1) {
}
+AXEventNotificationDetails::AXEventNotificationDetails(
+ const AXEventNotificationDetails& other) = default;
+
AXEventNotificationDetails::~AXEventNotificationDetails() {}
} // namespace content
diff --git a/chromium/content/public/browser/ax_event_notification_details.h b/chromium/content/public/browser/ax_event_notification_details.h
index 50eeeb031dd..7054452e820 100644
--- a/chromium/content/public/browser/ax_event_notification_details.h
+++ b/chromium/content/public/browser/ax_event_notification_details.h
@@ -19,6 +19,7 @@ namespace content {
struct CONTENT_EXPORT AXEventNotificationDetails {
public:
AXEventNotificationDetails();
+ AXEventNotificationDetails(const AXEventNotificationDetails& other);
~AXEventNotificationDetails();
ui::AXTreeUpdate update;
diff --git a/chromium/content/public/browser/background_tracing_config.h b/chromium/content/public/browser/background_tracing_config.h
index 22d788599a4..b7af5bbad79 100644
--- a/chromium/content/public/browser/background_tracing_config.h
+++ b/chromium/content/public/browser/background_tracing_config.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_PUBLIC_BROWSER_BACKGROUND_TRACING_CONFIG_H_
#define CONTENT_PUBLIC_BROWSER_BACKGROUND_TRACING_CONFIG_H_
+#include "base/memory/scoped_ptr.h"
#include "base/trace_event/trace_event_impl.h"
#include "content/common/content_export.h"
diff --git a/chromium/content/public/browser/background_tracing_manager.h b/chromium/content/public/browser/background_tracing_manager.h
index 652047e45f8..61258edca40 100644
--- a/chromium/content/public/browser/background_tracing_manager.h
+++ b/chromium/content/public/browser/background_tracing_manager.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_PUBLIC_BROWSER_BACKGROUND_TRACING_MANAGER_H_
#define CONTENT_PUBLIC_BROWSER_BACKGROUND_TRACING_MANAGER_H_
+#include "base/memory/scoped_ptr.h"
#include "base/trace_event/trace_event_impl.h"
#include "base/values.h"
#include "content/common/content_export.h"
diff --git a/chromium/content/public/browser/bluetooth_chooser.h b/chromium/content/public/browser/bluetooth_chooser.h
index b9f44a48230..aec3c2f1941 100644
--- a/chromium/content/public/browser/bluetooth_chooser.h
+++ b/chromium/content/public/browser/bluetooth_chooser.h
@@ -28,8 +28,6 @@ class CONTENT_EXPORT BluetoothChooser {
RESCAN,
// Show overview page for Bluetooth.
SHOW_OVERVIEW_HELP,
- // Show help page explaining what Bluetooth pairing means.
- SHOW_PAIRING_HELP,
// Show help page explaining why scanning failed because Bluetooth is off.
SHOW_ADAPTER_OFF_HELP,
// Show help page explaining why Chromium needs the Location permission to
@@ -46,9 +44,9 @@ class CONTENT_EXPORT BluetoothChooser {
//
// The EventHandler won't be called after the chooser object is destroyed.
//
- // After the EventHandler is called with Event::CANCELLED or Event::SELECTED,
- // it won't be called again, and users must not call any more BluetoothChooser
- // methods.
+ // After the EventHandler is called with Event::CANCELLED, Event::SELECTED,
+ // Event::DENIED_PERMISSION or Event::SHOW_*, it won't be called again, and
+ // users must not call any more BluetoothChooser methods.
typedef base::Callback<void(Event, const std::string& opt_device_id)>
EventHandler;
diff --git a/chromium/content/public/browser/browser_child_process_host.h b/chromium/content/public/browser/browser_child_process_host.h
index 15935468609..07193afd0cd 100644
--- a/chromium/content/public/browser/browser_child_process_host.h
+++ b/chromium/content/public/browser/browser_child_process_host.h
@@ -14,7 +14,7 @@
#include "content/public/common/process_type.h"
#include "ipc/ipc_sender.h"
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MACOSX)
#include "base/process/port_provider_mac.h"
#endif
@@ -85,7 +85,7 @@ class CONTENT_EXPORT BrowserChildProcessHost : public IPC::Sender {
// nullptr if no service registry exists.
virtual ServiceRegistry* GetServiceRegistry() = 0;
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MACOSX)
// Returns a PortProvider used to get the task port for child processes.
static base::PortProvider* GetPortProvider();
#endif
diff --git a/chromium/content/public/browser/browser_child_process_observer.h b/chromium/content/public/browser/browser_child_process_observer.h
index ab3b56ab055..faaa175a53a 100644
--- a/chromium/content/public/browser/browser_child_process_observer.h
+++ b/chromium/content/public/browser/browser_child_process_observer.h
@@ -41,12 +41,6 @@ class CONTENT_EXPORT BrowserChildProcessObserver {
virtual void BrowserChildProcessKilled(const ChildProcessData& data,
int exit_code) {}
- // Called when an instance of a particular child is created in a page. If one
- // page contains several regions rendered by the same child, this will be
- // called once for each region during the page load.
- virtual void BrowserChildProcessInstanceCreated(
- const ChildProcessData& data) {}
-
protected:
// The observer can be destroyed on any thread.
virtual ~BrowserChildProcessObserver() {}
diff --git a/chromium/content/public/browser/browser_context.h b/chromium/content/public/browser/browser_context.h
index 9897d4d3f88..369e5bd0ccc 100644
--- a/chromium/content/public/browser/browser_context.h
+++ b/chromium/content/public/browser/browser_context.h
@@ -8,13 +8,20 @@
#include <stddef.h>
#include <stdint.h>
+#include <map>
+
#include "base/callback_forward.h"
#include "base/containers/hash_tables.h"
+#include "base/memory/linked_ptr.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/scoped_vector.h"
#include "base/supports_user_data.h"
#include "content/common/content_export.h"
#include "content/public/browser/zoom_level_delegate.h"
+#include "content/public/common/push_event_payload.h"
#include "content/public/common/push_messaging_status.h"
+#include "net/url_request/url_request_interceptor.h"
+#include "net/url_request/url_request_job_factory.h"
class GURL;
@@ -50,6 +57,16 @@ class SiteInstance;
class StoragePartition;
class SSLHostStateDelegate;
+// A mapping from the scheme name to the protocol handler that services its
+// content.
+typedef std::map<
+ std::string, linked_ptr<net::URLRequestJobFactory::ProtocolHandler> >
+ ProtocolHandlerMap;
+
+// A scoped vector of protocol interceptors.
+typedef ScopedVector<net::URLRequestInterceptor>
+ URLRequestInterceptorScopedVector;
+
// This class holds the context needed for a browsing session.
// It lives on the UI thread. All these methods must only be called on the UI
// thread.
@@ -108,7 +125,7 @@ class CONTENT_EXPORT BrowserContext : public base::SupportsUserData {
BrowserContext* browser_context,
const GURL& origin,
int64_t service_worker_registration_id,
- const std::string& data,
+ const PushEventPayload& payload,
const base::Callback<void(PushDeliveryStatus)>& callback);
static void NotifyWillBeDestroyed(BrowserContext* browser_context);
@@ -127,6 +144,15 @@ class CONTENT_EXPORT BrowserContext : public base::SupportsUserData {
static void SetDownloadManagerForTesting(BrowserContext* browser_context,
DownloadManager* download_manager);
+ // Makes mojo aware of this BrowserContext, and assigns a user ID number to
+ // it. Should be called for each BrowserContext created.
+ static void Initialize(BrowserContext* browser_context,
+ const base::FilePath& path);
+
+ // Returns a Mojo User ID associated with this BrowserContext. This ID is not
+ // persistent across runs. See mojo/shell/public/interfaces/connector.mojom.
+ static const std::string& GetMojoUserIdFor(BrowserContext* browser_context);
+
~BrowserContext() override;
// Creates a delegate to initialize a HostZoomMap and persist its information.
@@ -146,13 +172,6 @@ class CONTENT_EXPORT BrowserContext : public base::SupportsUserData {
// TODO(creis): Remove this version in favor of the one below.
virtual net::URLRequestContextGetter* GetRequestContext() = 0;
- // Returns the request context appropriate for the given renderer. If the
- // renderer process doesn't have an associated installed app, or if the
- // installed app doesn't have isolated storage, this is equivalent to calling
- // GetRequestContext().
- virtual net::URLRequestContextGetter* GetRequestContextForRenderProcess(
- int renderer_child_id) = 0;
-
// Returns the default request context for media resources associated with
// this context.
// TODO(creis): Remove this version in favor of the one below.
@@ -197,6 +216,19 @@ class CONTENT_EXPORT BrowserContext : public base::SupportsUserData {
// Returns the BackgroundSyncController associated with that context if any,
// nullptr otherwise.
virtual BackgroundSyncController* GetBackgroundSyncController() = 0;
+
+ // Creates the main net::URLRequestContextGetter. It's called only once.
+ virtual net::URLRequestContextGetter* CreateRequestContext(
+ ProtocolHandlerMap* protocol_handlers,
+ URLRequestInterceptorScopedVector request_interceptors) = 0;
+
+ // Creates the net::URLRequestContextGetter for a StoragePartition. It's
+ // called only once per partition_path.
+ virtual net::URLRequestContextGetter* CreateRequestContextForStoragePartition(
+ const base::FilePath& partition_path,
+ bool in_memory,
+ ProtocolHandlerMap* protocol_handlers,
+ URLRequestInterceptorScopedVector request_interceptors) = 0;
};
} // namespace content
diff --git a/chromium/content/public/browser/browser_message_filter.cc b/chromium/content/public/browser/browser_message_filter.cc
index b2482cd408a..76a0e0499ca 100644
--- a/chromium/content/public/browser/browser_message_filter.cc
+++ b/chromium/content/public/browser/browser_message_filter.cc
@@ -69,11 +69,6 @@ class BrowserMessageFilter::Internal : public IPC::MessageFilter {
return DispatchMessage(message);
}
- if (thread == BrowserThread::UI &&
- !BrowserMessageFilter::CheckCanDispatchOnUI(message, filter_.get())) {
- return true;
- }
-
BrowserThread::PostTask(
thread, FROM_HERE,
base::Bind(
@@ -157,31 +152,6 @@ base::TaskRunner* BrowserMessageFilter::OverrideTaskRunnerForMessage(
return nullptr;
}
-bool BrowserMessageFilter::CheckCanDispatchOnUI(const IPC::Message& message,
- IPC::Sender* sender) {
-#if defined(OS_WIN)
- // On Windows there's a potential deadlock with sync messsages going in
- // a circle from browser -> plugin -> renderer -> browser.
- // On Linux we can avoid this by avoiding sync messages from browser->plugin.
- // On Mac we avoid this by not supporting windowed plugins.
- if (message.is_sync() && !message.is_caller_pumping_messages()) {
- // NOTE: IF YOU HIT THIS ASSERT, THE SOLUTION IS ALMOST NEVER TO RUN A
- // NESTED MESSAGE LOOP IN THE RENDERER!!!
- // That introduces reentrancy which causes hard to track bugs. You should
- // find a way to either turn this into an asynchronous message, or one
- // that can be answered on the IO thread.
- NOTREACHED() << "Can't send sync messages to UI thread without pumping "
- "messages in the renderer or else deadlocks can occur if the page "
- "has windowed plugins! (message type " << message.type() << ")";
- IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message);
- reply->set_reply_error();
- sender->Send(reply);
- return false;
- }
-#endif
- return true;
-}
-
void BrowserMessageFilter::ShutdownForBadMessage() {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch(switches::kDisableKillAfterBadIPC))
diff --git a/chromium/content/public/browser/browser_message_filter.h b/chromium/content/public/browser/browser_message_filter.h
index 8f652ecb9b4..22b0e7d8a8c 100644
--- a/chromium/content/public/browser/browser_message_filter.h
+++ b/chromium/content/public/browser/browser_message_filter.h
@@ -92,11 +92,6 @@ class CONTENT_EXPORT BrowserMessageFilter
peer_process_ = std::move(peer_process);
}
- // Checks that the given message can be dispatched on the UI thread, depending
- // on the platform. If not, returns false and an error ot the sender.
- static bool CheckCanDispatchOnUI(const IPC::Message& message,
- IPC::Sender* sender);
-
// Called by bad_message.h helpers if a message couldn't be deserialized. This
// kills the renderer. Can be called on any thread. This doesn't log the
// error details to UMA, so use the bad_message.h for your module instead.
diff --git a/chromium/content/public/browser/content_browser_client.cc b/chromium/content/public/browser/content_browser_client.cc
index 3f6d970c9f3..23fd868a00f 100644
--- a/chromium/content/public/browser/content_browser_client.cc
+++ b/chromium/content/public/browser/content_browser_client.cc
@@ -27,6 +27,10 @@ void ContentBrowserClient::PostAfterStartupTask(
task_runner->PostTask(from_here, task);
}
+bool ContentBrowserClient::IsBrowserStartupComplete() {
+ return true;
+}
+
WebContentsViewDelegate* ContentBrowserClient::GetWebContentsViewDelegate(
WebContents* web_contents) {
return nullptr;
@@ -57,23 +61,6 @@ bool ContentBrowserClient::LogWebUIUrl(const GURL& web_ui_url) const {
return false;
}
-net::URLRequestContextGetter* ContentBrowserClient::CreateRequestContext(
- BrowserContext* browser_context,
- ProtocolHandlerMap* protocol_handlers,
- URLRequestInterceptorScopedVector request_interceptors) {
- return nullptr;
-}
-
-net::URLRequestContextGetter*
-ContentBrowserClient::CreateRequestContextForStoragePartition(
- BrowserContext* browser_context,
- const base::FilePath& partition_path,
- bool in_memory,
- ProtocolHandlerMap* protocol_handlers,
- URLRequestInterceptorScopedVector request_interceptors) {
- return nullptr;
-}
-
bool ContentBrowserClient::IsHandledURL(const GURL& url) {
return false;
}
@@ -161,6 +148,10 @@ bool ContentBrowserClient::AllowServiceWorker(const GURL& scope,
return true;
}
+bool ContentBrowserClient::IsDataSaverEnabled(BrowserContext* context) {
+ return false;
+}
+
bool ContentBrowserClient::AllowGetCookie(const GURL& url,
const GURL& first_party,
const net::CookieList& cookie_list,
@@ -184,16 +175,6 @@ bool ContentBrowserClient::AllowSaveLocalState(ResourceContext* context) {
return true;
}
-bool ContentBrowserClient::AllowWorkerDatabase(
- const GURL& url,
- const base::string16& name,
- const base::string16& display_name,
- unsigned long estimated_size,
- ResourceContext* context,
- const std::vector<std::pair<int, int> >& render_frames) {
- return true;
-}
-
void ContentBrowserClient::AllowWorkerFileSystem(
const GURL& url,
ResourceContext* context,
@@ -223,6 +204,18 @@ bool ContentBrowserClient::AllowKeygen(const GURL& url,
return true;
}
+ContentBrowserClient::AllowWebBluetoothResult
+ContentBrowserClient::AllowWebBluetooth(
+ content::BrowserContext* browser_context,
+ const url::Origin& requesting_origin,
+ const url::Origin& embedding_origin) {
+ return AllowWebBluetoothResult::ALLOW;
+}
+
+std::string ContentBrowserClient::GetWebBluetoothBlacklist() {
+ return std::string();
+}
+
QuotaPermissionContext* ContentBrowserClient::CreateQuotaPermissionContext() {
return nullptr;
}
@@ -358,10 +351,6 @@ TracingDelegate* ContentBrowserClient::GetTracingDelegate() {
return nullptr;
}
-bool ContentBrowserClient::IsNPAPIEnabled() {
- return false;
-}
-
bool ContentBrowserClient::IsPluginAllowedToCallRequestOSFileHandle(
BrowserContext* browser_context,
const GURL& url) {
diff --git a/chromium/content/public/browser/content_browser_client.h b/chromium/content/public/browser/content_browser_client.h
index 5ecc56efe97..8b111979952 100644
--- a/chromium/content/public/browser/content_browser_client.h
+++ b/chromium/content/public/browser/content_browser_client.h
@@ -13,7 +13,6 @@
#include <vector>
#include "base/callback_forward.h"
-#include "base/memory/linked_ptr.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/values.h"
@@ -27,8 +26,6 @@
#include "content/public/common/window_container_type.h"
#include "net/base/mime_util.h"
#include "net/cookies/canonical_cookie.h"
-#include "net/url_request/url_request_interceptor.h"
-#include "net/url_request/url_request_job_factory.h"
#include "storage/browser/fileapi/file_system_context.h"
#include "third_party/WebKit/public/platform/WebPageVisibilityState.h"
#include "ui/base/window_open_disposition.h"
@@ -62,7 +59,7 @@ class CdmFactory;
}
namespace mojo {
-class ApplicationDelegate;
+class ShellClient;
}
namespace net {
@@ -84,6 +81,10 @@ namespace ui {
class SelectFilePolicy;
}
+namespace url {
+class Origin;
+}
+
namespace storage {
class ExternalMountPoints;
class FileSystemBackend;
@@ -106,8 +107,6 @@ class ExternalVideoSurfaceContainer;
class LocationProvider;
class MediaObserver;
class NavigationHandle;
-class NavigatorConnectContext;
-class NavigatorConnectServiceFactory;
class PlatformNotificationService;
class PresentationServiceDelegate;
class QuotaPermissionContext;
@@ -126,16 +125,6 @@ struct OpenURLParams;
struct Referrer;
struct WebPreferences;
-// A mapping from the scheme name to the protocol handler that services its
-// content.
-typedef std::map<
- std::string, linked_ptr<net::URLRequestJobFactory::ProtocolHandler> >
- ProtocolHandlerMap;
-
-// A scoped vector of protocol interceptors.
-typedef ScopedVector<net::URLRequestInterceptor>
- URLRequestInterceptorScopedVector;
-
// Embedder API (or SPI) for participating in browser logic, to be implemented
// by the client of the content browser. See ChromeContentBrowserClient for the
// principal implementation. The methods are assumed to be called on the UI
@@ -164,6 +153,12 @@ class CONTENT_EXPORT ContentBrowserClient {
const scoped_refptr<base::TaskRunner>& task_runner,
const base::Closure& task);
+ // Allows the embedder to indicate whether it considers startup to be
+ // complete. May be called on any thread. This should be called on a one-off
+ // basis; if you need to poll this function constantly, use the above
+ // PostAfterStartupTask() API instead.
+ virtual bool IsBrowserStartupComplete();
+
// If content creates the WebContentsView implementation, it will ask the
// embedder to return an (optional) delegate to customize it. The view will
// own the delegate.
@@ -227,24 +222,6 @@ class CONTENT_EXPORT ContentBrowserClient {
// chrome://) URLs are logged. Returns whether the URL was actually logged.
virtual bool LogWebUIUrl(const GURL& web_ui_url) const;
- // Creates the main net::URLRequestContextGetter. Should only be called once
- // per ContentBrowserClient object.
- // TODO(ajwong): Remove once http://crbug.com/159193 is resolved.
- virtual net::URLRequestContextGetter* CreateRequestContext(
- BrowserContext* browser_context,
- ProtocolHandlerMap* protocol_handlers,
- URLRequestInterceptorScopedVector request_interceptors);
-
- // Creates the net::URLRequestContextGetter for a StoragePartition. Should
- // only be called once per partition_path per ContentBrowserClient object.
- // TODO(ajwong): Remove once http://crbug.com/159193 is resolved.
- virtual net::URLRequestContextGetter* CreateRequestContextForStoragePartition(
- BrowserContext* browser_context,
- const base::FilePath& partition_path,
- bool in_memory,
- ProtocolHandlerMap* protocol_handlers,
- URLRequestInterceptorScopedVector request_interceptors);
-
// Returns whether a specified URL is handled by the embedder's internal
// protocol handlers.
virtual bool IsHandledURL(const GURL& url);
@@ -347,6 +324,8 @@ class CONTENT_EXPORT ContentBrowserClient {
int render_process_id,
int render_frame_id);
+ virtual bool IsDataSaverEnabled(BrowserContext* context);
+
// Allow the embedder to control if the given cookie can be read.
// This is called on the IO thread.
virtual bool AllowGetCookie(const GURL& url,
@@ -369,18 +348,6 @@ class CONTENT_EXPORT ContentBrowserClient {
// This is called on the IO thread.
virtual bool AllowSaveLocalState(ResourceContext* context);
- // Allow the embedder to control if access to web database by a shared worker
- // is allowed. |render_frame| is a vector of pairs of
- // RenderProcessID/RenderFrameID of RenderFrame that are using this worker.
- // This is called on the IO thread.
- virtual bool AllowWorkerDatabase(
- const GURL& url,
- const base::string16& name,
- const base::string16& display_name,
- unsigned long estimated_size,
- ResourceContext* context,
- const std::vector<std::pair<int, int> >& render_frames);
-
// Allow the embedder to control if access to file system by a shared worker
// is allowed.
// This is called on the IO thread.
@@ -411,6 +378,33 @@ class CONTENT_EXPORT ContentBrowserClient {
// Allow the embedder to control whether we can use <keygen>.
virtual bool AllowKeygen(const GURL& url, content::ResourceContext* context);
+ // Allow the embedder to control whether we can use Web Bluetooth.
+ // TODO(crbug.com/589228): Replace this with a use of the permission system.
+ enum class AllowWebBluetoothResult {
+ ALLOW,
+ BLOCK_POLICY,
+ BLOCK_GLOBALLY_DISABLED,
+ };
+ virtual AllowWebBluetoothResult AllowWebBluetooth(
+ content::BrowserContext* browser_context,
+ const url::Origin& requesting_origin,
+ const url::Origin& embedding_origin);
+
+ // Returns a blacklist of UUIDs that have restrictions when accessed
+ // via Web Bluetooth. Parsed by BluetoothBlacklist::Add().
+ //
+ // The blacklist string must be a comma-separated list of UUID:exclusion
+ // pairs. The pairs may be separated by whitespace. Pair components are
+ // colon-separated and must not have whitespace around the colon.
+ //
+ // UUIDs are a string that BluetoothUUID can parse (See BluetoothUUID
+ // constructor comment). Exclusion values are a single lower case character
+ // string "e", "r", or "w" for EXCLUDE, EXCLUDE_READS, or EXCLUDE_WRITES.
+ //
+ // Example:
+ // "1812:e, 00001800-0000-1000-8000-00805f9b34fb:w, ignored:1, alsoignored."
+ virtual std::string GetWebBluetoothBlacklist();
+
// Allow the embedder to override the request context based on the URL for
// certain operations, like cookie access. Returns nullptr to indicate the
// regular request context should be used.
@@ -628,9 +622,6 @@ class CONTENT_EXPORT ContentBrowserClient {
// It's valid to return nullptr.
virtual TracingDelegate* GetTracingDelegate();
- // Returns true if NPAPI plugins are enabled.
- virtual bool IsNPAPIEnabled();
-
// Returns true if plugin referred to by the url can use
// pp::FileIO::RequestOSFileHandle.
virtual bool IsPluginAllowedToCallRequestOSFileHandle(
@@ -659,14 +650,14 @@ class CONTENT_EXPORT ContentBrowserClient {
RenderFrameHost* render_frame_host) {}
using StaticMojoApplicationMap =
- std::map<GURL, base::Callback<scoped_ptr<mojo::ApplicationDelegate>()>>;
+ std::map<std::string, base::Callback<scoped_ptr<mojo::ShellClient>()>>;
// Registers Mojo applications to be loaded in the browser process by the
// browser's global Mojo shell.
virtual void RegisterInProcessMojoApplications(
StaticMojoApplicationMap* apps) {}
- using OutOfProcessMojoApplicationMap = std::map<GURL, base::string16>;
+ using OutOfProcessMojoApplicationMap = std::map<std::string, base::string16>;
// Registers Mojo applications to be loaded out of the browser process, in a
// sandboxed utility process. The value of each map entry should be the
@@ -684,11 +675,6 @@ class CONTENT_EXPORT ContentBrowserClient {
virtual void RegisterUnsandboxedOutOfProcessMojoApplications(
OutOfProcessMojoApplicationMap* apps) {}
- // Registers additional navigator.connect service factories available in a
- // particular NavigatorConnectContext.
- virtual void GetAdditionalNavigatorConnectServices(
- const scoped_refptr<NavigatorConnectContext>& context) {}
-
// Allows to override the visibility state of a RenderFrameHost.
// |visibility_state| should not be null. It will only be set if needed.
virtual void OverridePageVisibilityState(
diff --git a/chromium/content/public/browser/cookie_store_factory.h b/chromium/content/public/browser/cookie_store_factory.h
index 5b2bb7ac789..1552342823a 100644
--- a/chromium/content/public/browser/cookie_store_factory.h
+++ b/chromium/content/public/browser/cookie_store_factory.h
@@ -5,8 +5,12 @@
#ifndef CONTENT_PUBLIC_BROWSER_COOKIE_STORE_FACTORY_H_
#define CONTENT_PUBLIC_BROWSER_COOKIE_STORE_FACTORY_H_
+#include <string>
+#include <vector>
+
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
namespace base {
@@ -87,9 +91,12 @@ struct CONTENT_EXPORT CookieStoreConfig {
//
// Only used for persistent cookie stores.
scoped_refptr<base::SequencedTaskRunner> background_task_runner;
+
+ // If non-empty, overrides the default list of schemes that support cookies.
+ std::vector<std::string> cookieable_schemes;
};
-CONTENT_EXPORT net::CookieStore* CreateCookieStore(
+CONTENT_EXPORT scoped_ptr<net::CookieStore> CreateCookieStore(
const CookieStoreConfig& config);
} // namespace content
diff --git a/chromium/content/public/browser/desktop_media_id.cc b/chromium/content/public/browser/desktop_media_id.cc
index 63c2cbf3c61..8a20598af67 100644
--- a/chromium/content/public/browser/desktop_media_id.cc
+++ b/chromium/content/public/browser/desktop_media_id.cc
@@ -16,8 +16,8 @@
#include "base/strings/string_util.h"
#if defined(USE_AURA)
-#include "ui/aura/window.h"
-#include "ui/aura/window_observer.h"
+#include "ui/aura/window.h" // nogncheck
+#include "ui/aura/window_observer.h" // nogncheck
#endif // defined(USE_AURA)
namespace {
@@ -98,21 +98,25 @@ aura::Window* DesktopMediaID::GetAuraWindowById(const DesktopMediaID& id) {
bool DesktopMediaID::operator<(const DesktopMediaID& other) const {
#if defined(USE_AURA)
- return std::tie(type, id, aura_id, web_contents_id) <
- std::tie(other.type, other.id, other.aura_id, other.web_contents_id);
+ return std::tie(type, id, aura_id, web_contents_id, audio_share) <
+ std::tie(other.type, other.id, other.aura_id, other.web_contents_id,
+ other.audio_share);
#else
- return std::tie(type, id, web_contents_id) <
- std::tie(other.type, other.id, web_contents_id);
+ return std::tie(type, id, web_contents_id, audio_share) <
+ std::tie(other.type, other.id, other.web_contents_id,
+ other.audio_share);
#endif
}
bool DesktopMediaID::operator==(const DesktopMediaID& other) const {
#if defined(USE_AURA)
return type == other.type && id == other.id && aura_id == other.aura_id &&
- web_contents_id == other.web_contents_id;
+ web_contents_id == other.web_contents_id &&
+ audio_share == other.audio_share;
#else
return type == other.type && id == other.id &&
- web_contents_id == other.web_contents_id;
+ web_contents_id == other.web_contents_id &&
+ audio_share == other.audio_share;
#endif
}
diff --git a/chromium/content/public/browser/desktop_media_id.h b/chromium/content/public/browser/desktop_media_id.h
index 1d0ac67fa42..7b6cd1f1011 100644
--- a/chromium/content/public/browser/desktop_media_id.h
+++ b/chromium/content/public/browser/desktop_media_id.h
@@ -46,6 +46,9 @@ struct CONTENT_EXPORT DesktopMediaID {
DesktopMediaID(Type type, Id id, WebContentsMediaCaptureId web_contents_id)
: type(type), id(id), web_contents_id(web_contents_id) {}
+ DesktopMediaID(Type type, Id id, bool audio_share)
+ : type(type), id(id), audio_share(audio_share) {}
+
// Operators so that DesktopMediaID can be used with STL containers.
bool operator<(const DesktopMediaID& other) const;
bool operator==(const DesktopMediaID& other) const;
@@ -67,6 +70,9 @@ struct CONTENT_EXPORT DesktopMediaID {
Id aura_id = kNullId;
#endif
+ // This records whether the desktop share has sound or not.
+ bool audio_share = false;
+
// This id contains information for WebContents capture.
WebContentsMediaCaptureId web_contents_id;
};
diff --git a/chromium/content/public/browser/download_interrupt_reason_values.h b/chromium/content/public/browser/download_interrupt_reason_values.h
index 95c4f4a9621..bfffa12c866 100644
--- a/chromium/content/public/browser/download_interrupt_reason_values.h
+++ b/chromium/content/public/browser/download_interrupt_reason_values.h
@@ -51,6 +51,9 @@ INTERRUPT_REASON(FILE_SECURITY_CHECK_FAILED, 12)
// a file (as part of resuming a previously interrupted download).
INTERRUPT_REASON(FILE_TOO_SHORT, 13)
+// The partial file didn't match the expected hash.
+INTERRUPT_REASON(FILE_HASH_MISMATCH, 14)
+
// Network errors.
// Generic network failure.
@@ -106,6 +109,10 @@ INTERRUPT_REASON(SERVER_CERT_PROBLEM, 35)
// Server access forbidden.
INTERRUPT_REASON(SERVER_FORBIDDEN, 36)
+// Unexpected server response. This might indicate that the responding server
+// may not be the intended server.
+INTERRUPT_REASON(SERVER_UNREACHABLE, 37)
+
// User input.
// The user canceled the download.
diff --git a/chromium/content/public/browser/download_item.h b/chromium/content/public/browser/download_item.h
index d3a7798a019..6182cd4185b 100644
--- a/chromium/content/public/browser/download_item.h
+++ b/chromium/content/public/browser/download_item.h
@@ -82,8 +82,6 @@ class CONTENT_EXPORT DownloadItem : public base::SupportsUserData {
static const uint32_t kInvalidId;
- static const char kEmptyFileHash[];
-
// Interface that observers of a particular download must implement in order
// to receive updates to the download's status.
class CONTENT_EXPORT Observer {
@@ -154,7 +152,18 @@ class CONTENT_EXPORT DownloadItem : public base::SupportsUserData {
// State accessors -----------------------------------------------------------
+ // Retrieve the ID for this download. The ID is provided by the owner of the
+ // DownloadItem and is expected to uniquely identify the download within the
+ // context of its container during the lifetime of the download.
virtual uint32_t GetId() const = 0;
+
+ // Retrieve the GUID for this download. The returned string is never empty and
+ // will satisfy base::IsValidGUID(), in addition to uniquely identifying the
+ // download during its lifetime regardless of its container.
+ virtual const std::string& GetGuid() const = 0;
+
+ // Get the current state of the download. See DownloadState for descriptions
+ // of each download state.
virtual DownloadState GetState() const = 0;
// Returns the most recent interrupt reason for this download. Returns
@@ -228,13 +237,12 @@ class CONTENT_EXPORT DownloadItem : public base::SupportsUserData {
virtual TargetDisposition GetTargetDisposition() const = 0;
- // Final hash of completely downloaded file; not valid if
- // GetState() != COMPLETED.
+ // Final hash of completely downloaded file, or partial hash of an interrupted
+ // download; only valid if GetState() == COMPLETED or INTERRUPTED. If
+ // non-empty the returned string contains a raw SHA-256 hash (i.e. not hex
+ // encoded).
virtual const std::string& GetHash() const = 0;
- // Intermediate hash state, for persisting partial downloads.
- virtual const std::string& GetHashState() const = 0;
-
// True if the file associated with the download has been removed by
// external action.
virtual bool GetFileExternallyRemoved() const = 0;
diff --git a/chromium/content/public/browser/download_manager.h b/chromium/content/public/browser/download_manager.h
index ca367eb3884..41246623879 100644
--- a/chromium/content/public/browser/download_manager.h
+++ b/chromium/content/public/browser/download_manager.h
@@ -114,22 +114,14 @@ class CONTENT_EXPORT DownloadManager : public base::SupportsUserData::Data {
scoped_ptr<ByteStreamReader> stream,
const DownloadUrlParameters::OnStartedCallback& on_started) = 0;
- // Remove downloads which are same-origin with the given origin and pertain to
- // the given time constraints. (See |RemoveDownloadsBetween|.)
- virtual int RemoveDownloadsByOriginAndTime(const url::Origin& origin,
- base::Time remove_begin,
- base::Time remove_end) = 0;
-
- // Remove downloads after remove_begin (inclusive) and before remove_end
- // (exclusive). You may pass in null Time values to do an unbounded delete
- // in either direction.
- virtual int RemoveDownloadsBetween(base::Time remove_begin,
- base::Time remove_end) = 0;
-
- // Remove downloads will delete all downloads that have a timestamp that is
- // the same or more recent than |remove_begin|. The number of downloads
- // deleted is returned back to the caller.
- virtual int RemoveDownloads(base::Time remove_begin) = 0;
+ // Remove downloads whose URLs match the |url_filter| and are within
+ // the given time constraints - after remove_begin (inclusive) and before
+ // remove_end (exclusive). You may pass in null Time values to do an unbounded
+ // delete in either direction.
+ virtual int RemoveDownloadsByURLAndTime(
+ const base::Callback<bool(const GURL&)>& url_filter,
+ base::Time remove_begin,
+ base::Time remove_end) = 0;
// Remove all downloads will delete all downloads. The number of downloads
// deleted is returned back to the caller.
@@ -147,6 +139,7 @@ class CONTENT_EXPORT DownloadManager : public base::SupportsUserData::Data {
// Called by the embedder, after creating the download manager, to let it know
// about downloads from previous runs of the browser.
virtual DownloadItem* CreateDownloadItem(
+ const std::string& guid,
uint32_t id,
const base::FilePath& current_path,
const base::FilePath& target_path,
@@ -160,6 +153,7 @@ class CONTENT_EXPORT DownloadManager : public base::SupportsUserData::Data {
const std::string& last_modified,
int64_t received_bytes,
int64_t total_bytes,
+ const std::string& hash,
DownloadItem::DownloadState state,
DownloadDangerType danger_type,
DownloadInterruptReason interrupt_reason,
@@ -185,7 +179,13 @@ class CONTENT_EXPORT DownloadManager : public base::SupportsUserData::Data {
// Get the download item for |id| if present, no matter what type of download
// it is or state it's in.
+ // DEPRECATED: Don't add new callers for GetDownload(uint32_t). Instead keep
+ // track of the GUID and use GetDownloadByGuid(), or observe the DownloadItem
+ // if you need to keep track of a specific download. (http://crbug.com/593020)
virtual DownloadItem* GetDownload(uint32_t id) = 0;
+
+ // Get the download item for |guid|.
+ virtual DownloadItem* GetDownloadByGuid(const std::string& guid) = 0;
};
} // namespace content
diff --git a/chromium/content/public/browser/download_save_info.cc b/chromium/content/public/browser/download_save_info.cc
index 3093ee68445..eabc761ec67 100644
--- a/chromium/content/public/browser/download_save_info.cc
+++ b/chromium/content/public/browser/download_save_info.cc
@@ -13,4 +13,13 @@ DownloadSaveInfo::DownloadSaveInfo()
DownloadSaveInfo::~DownloadSaveInfo() {
}
+DownloadSaveInfo::DownloadSaveInfo(DownloadSaveInfo&& that)
+ : file_path(std::move(that.file_path)),
+ suggested_name(std::move(that.suggested_name)),
+ file(std::move(that.file)),
+ offset(that.offset),
+ hash_state(std::move(that.hash_state)),
+ hash_of_partial_file(std::move(that.hash_of_partial_file)),
+ prompt_for_save_location(that.prompt_for_save_location) {}
+
} // namespace content
diff --git a/chromium/content/public/browser/download_save_info.h b/chromium/content/public/browser/download_save_info.h
index 231783d987a..bd901d38cd2 100644
--- a/chromium/content/public/browser/download_save_info.h
+++ b/chromium/content/public/browser/download_save_info.h
@@ -10,7 +10,9 @@
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
+#include "crypto/secure_hash.h"
namespace content {
@@ -21,6 +23,7 @@ namespace content {
struct CONTENT_EXPORT DownloadSaveInfo {
DownloadSaveInfo();
~DownloadSaveInfo();
+ DownloadSaveInfo(DownloadSaveInfo&& that);
// If non-empty, contains the full target path of the download that has been
// determined prior to download initiation. This is considered to be a trusted
@@ -37,8 +40,15 @@ struct CONTENT_EXPORT DownloadSaveInfo {
// The file offset at which to start the download. May be 0.
int64_t offset;
- // The state of the hash at the start of the download. May be empty.
- std::string hash_state;
+ // The state of the hash. If specified, this hash state must indicate the
+ // state of the partial file for the first |offset| bytes.
+ scoped_ptr<crypto::SecureHash> hash_state;
+
+ // SHA-256 hash of the first |offset| bytes of the file. Only used if |offset|
+ // is non-zero and either |file_path| or |file| specifies the file which
+ // contains the |offset| number of bytes. Can be empty, in which case no
+ // verification is done on the existing file.
+ std::string hash_of_partial_file;
// If |prompt_for_save_location| is true, and |file_path| is empty, then
// the user will be prompted for a location to save the download. Otherwise,
diff --git a/chromium/content/public/browser/download_url_parameters.h b/chromium/content/public/browser/download_url_parameters.h
index a2b9b00d6e9..319f1581635 100644
--- a/chromium/content/public/browser/download_url_parameters.h
+++ b/chromium/content/public/browser/download_url_parameters.h
@@ -16,6 +16,7 @@
#include "content/public/browser/download_interrupt_reasons.h"
#include "content/public/browser/download_save_info.h"
#include "content/public/common/referrer.h"
+#include "storage/browser/blob/blob_data_handle.h"
#include "url/gurl.h"
namespace content {
@@ -41,71 +42,158 @@ class WebContents;
class CONTENT_EXPORT DownloadUrlParameters {
public:
- // If there is an error, then |item| will be nullptr.
+ // An OnStartedCallback is invoked when a response is available for the
+ // download request. For new downloads, this callback is invoked after the
+ // OnDownloadCreated notification is issued by the DownloadManager. If the
+ // download fails, then the DownloadInterruptReason parameter will indicate
+ // the failure.
+ //
+ // DownloadItem* may be nullptr if no DownloadItem was created. DownloadItems
+ // are not created when a resource throttle or a resource handler blocks the
+ // download request. I.e. the download triggered a warning of some sort and
+ // the user chose to not to proceed with the download as a result.
typedef base::Callback<void(DownloadItem*, DownloadInterruptReason)>
OnStartedCallback;
typedef std::pair<std::string, std::string> RequestHeadersNameValuePair;
typedef std::vector<RequestHeadersNameValuePair> RequestHeadersType;
+ // Construct DownloadUrlParameters for downloading the resource at |url| and
+ // associating the download with |web_contents|.
static scoped_ptr<DownloadUrlParameters> FromWebContents(
WebContents* web_contents,
const GURL& url);
- DownloadUrlParameters(
- const GURL& url,
- int render_process_host_id,
- int render_view_host_routing_id,
- int render_frame_host_routing_id,
- content::ResourceContext* resource_context);
+ // Construct DownloadUrlParameters for downloading the resource at |url| and
+ // associating the download with the WebContents identified by
+ // |render_process_host_id| and |render_view_host_routing_id|.
+ //
+ // If the download is not associated with a WebContents, then set the IDs to
+ // -1.
+ // NOTE: This is not safe and should only be done in a limited set of cases
+ // where the download URL has been previously vetted. A download that's
+ // initiated without associating it with a WebContents don't receive the same
+ // security checks as a request that's associated with one. Hence, downloads
+ // that are not associated with a WebContents should only be made for URLs
+ // that are either trusted or URLs that have previously been successfully
+ // issued using a non-privileged WebContents.
+ DownloadUrlParameters(const GURL& url,
+ int render_process_host_id,
+ int render_view_host_routing_id,
+ int render_frame_host_routing_id,
+ ResourceContext* resource_context);
~DownloadUrlParameters();
+ // Should be set to true if the download was initiated by a script or a web
+ // page. I.e. if the download request cannot be attributed to an explicit user
+ // request for a download, then set this value to true.
void set_content_initiated(bool content_initiated) {
content_initiated_ = content_initiated;
}
void add_request_header(const std::string& name, const std::string& value) {
request_headers_.push_back(make_pair(name, value));
}
+
+ // HTTP Referrer and referrer encoding.
void set_referrer(const Referrer& referrer) { referrer_ = referrer; }
void set_referrer_encoding(const std::string& referrer_encoding) {
referrer_encoding_ = referrer_encoding;
}
+
+ // If this is a request for resuming an HTTP/S download, |last_modified|
+ // should be the value of the last seen Last-Modified response header.
void set_last_modified(const std::string& last_modified) {
last_modified_ = last_modified;
}
+
+ // If this is a request for resuming an HTTP/S download, |etag| should be the
+ // last seen Etag response header.
void set_etag(const std::string& etag) {
etag_ = etag;
}
+
+ // HTTP method to use.
void set_method(const std::string& method) {
method_ = method;
}
+
+ // Body of the HTTP POST request.
void set_post_body(const std::string& post_body) {
post_body_ = post_body;
}
+
+ // If |prefer_cache| is true and the response to |url| is in the HTTP cache,
+ // it will be used without validation. If |method| is POST, then |post_id_|
+ // shoud be set via |set_post_id()| below to the identifier of the POST
+ // transaction used to originally retrieve the resource.
void set_prefer_cache(bool prefer_cache) {
prefer_cache_ = prefer_cache;
}
+
+ // See set_prefer_cache() above.
void set_post_id(int64_t post_id) { post_id_ = post_id; }
+
+ // See OnStartedCallback above.
void set_callback(const OnStartedCallback& callback) {
callback_ = callback;
}
+
+ // If not empty, specifies the full target path for the download. This value
+ // overrides the filename suggested by a Content-Disposition headers. It
+ // should only be set for programmatic downloads where the caller can verify
+ // the safety of the filename and the resulting download.
void set_file_path(const base::FilePath& file_path) {
save_info_.file_path = file_path;
}
+
+ // Suggested filename for the download. The suggestion can be overridden by
+ // either a Content-Disposition response header or a |file_path|.
void set_suggested_name(const base::string16& suggested_name) {
save_info_.suggested_name = suggested_name;
}
+
+ // If |offset| is non-zero, then a byte range request will be issued to fetch
+ // the range of bytes starting at |offset| through to the end of thedownload.
void set_offset(int64_t offset) { save_info_.offset = offset; }
- void set_hash_state(const std::string& hash_state) {
- save_info_.hash_state = hash_state;
+
+ // If |offset| is non-zero, then |hash_of_partial_file| contains the raw
+ // SHA-256 hash of the first |offset| bytes of the target file. Only
+ // meaningful if a partial file exists and is identified by either the
+ // |file_path()| or |file()|.
+ void set_hash_of_partial_file(const std::string& hash_of_partial_file) {
+ save_info_.hash_of_partial_file = hash_of_partial_file;
}
+
+ // If |offset| is non-zero, then |hash_state| indicates the SHA-256 hash state
+ // of the first |offset| bytes of the target file. In this case, the prefix
+ // hash will be ignored since the |hash_state| is assumed to be correct if
+ // provided.
+ void set_hash_state(scoped_ptr<crypto::SecureHash> hash_state) {
+ save_info_.hash_state = std::move(hash_state);
+ }
+
+ // If |prompt| is true, then the user will be prompted for a filename. Ignored
+ // if |file_path| is non-empty.
void set_prompt(bool prompt) { save_info_.prompt_for_save_location = prompt; }
void set_file(base::File file) { save_info_.file = std::move(file); }
void set_do_not_prompt_for_login(bool do_not_prompt) {
do_not_prompt_for_login_ = do_not_prompt;
}
+ // For downloads of blob URLs, the caller can store a BlobDataHandle in the
+ // DownloadUrlParameters object so that the blob will remain valid until
+ // the download starts. The BlobDataHandle will be attached to the associated
+ // URLRequest.
+ //
+ // This is optional. If left unspecified, and the blob URL cannot be mapped to
+ // a blob by the time the download request starts, then the download will
+ // fail.
+ void set_blob_data_handle(
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle) {
+ blob_data_handle_ = std::move(blob_data_handle);
+ }
+
const OnStartedCallback& callback() const { return callback_; }
bool content_initiated() const { return content_initiated_; }
const std::string& last_modified() const { return last_modified_; }
@@ -123,28 +211,28 @@ class CONTENT_EXPORT DownloadUrlParameters {
int render_frame_host_routing_id() const {
return render_frame_host_routing_id_;
}
- RequestHeadersType::const_iterator request_headers_begin() const {
- return request_headers_.begin();
- }
- RequestHeadersType::const_iterator request_headers_end() const {
- return request_headers_.end();
- }
- content::ResourceContext* resource_context() const {
- return resource_context_;
- }
+ const RequestHeadersType& request_headers() const { return request_headers_; }
+ ResourceContext* resource_context() const { return resource_context_; }
const base::FilePath& file_path() const { return save_info_.file_path; }
const base::string16& suggested_name() const {
return save_info_.suggested_name;
}
int64_t offset() const { return save_info_.offset; }
- const std::string& hash_state() const { return save_info_.hash_state; }
+ const std::string& hash_of_partial_file() const {
+ return save_info_.hash_of_partial_file;
+ }
bool prompt() const { return save_info_.prompt_for_save_location; }
const GURL& url() const { return url_; }
bool do_not_prompt_for_login() const { return do_not_prompt_for_login_; }
- // Note that this is state changing--the DownloadUrlParameters object
- // will not have a file attached to it after this call.
- base::File GetFile() { return std::move(save_info_.file); }
+ // STATE_CHANGING: Return the BlobDataHandle.
+ scoped_ptr<storage::BlobDataHandle> GetBlobDataHandle() {
+ return std::move(blob_data_handle_);
+ }
+
+ // STATE CHANGING: All save_info_ sub-objects will be in an indeterminate
+ // state following this call.
+ DownloadSaveInfo GetSaveInfo() { return std::move(save_info_); }
private:
OnStartedCallback callback_;
@@ -165,6 +253,7 @@ class CONTENT_EXPORT DownloadUrlParameters {
DownloadSaveInfo save_info_;
GURL url_;
bool do_not_prompt_for_login_;
+ scoped_ptr<storage::BlobDataHandle> blob_data_handle_;
DISALLOW_COPY_AND_ASSIGN(DownloadUrlParameters);
};
diff --git a/chromium/content/public/browser/geolocation_provider.h b/chromium/content/public/browser/geolocation_provider.h
index dea3c7ee3f4..01064925042 100644
--- a/chromium/content/public/browser/geolocation_provider.h
+++ b/chromium/content/public/browser/geolocation_provider.h
@@ -6,6 +6,7 @@
#define CONTENT_PUBLIC_BROWSER_GEOLOCATION_PROVIDER_H_
#include "base/callback_list.h"
+#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
namespace content {
@@ -30,11 +31,12 @@ class GeolocationProvider {
typedef base::CallbackList<void(const Geoposition&)>::Subscription
Subscription;
- // |use_high_accuracy| is used as a 'hint' for the provider preferences for
+ // |enable_high_accuracy| is used as a 'hint' for the provider preferences for
// this particular observer, however the observer could receive updates for
// best available locations from any active provider whilst it is registered.
virtual scoped_ptr<Subscription> AddLocationUpdateCallback(
- const LocationUpdateCallback& callback, bool use_high_accuracy) = 0;
+ const LocationUpdateCallback& callback,
+ bool enable_high_accuracy) = 0;
// Calling this method indicates the user has opted into using location
// services, including sending network requests to [Google servers to] resolve
diff --git a/chromium/content/public/browser/gpu_data_manager.h b/chromium/content/public/browser/gpu_data_manager.h
index 4991a4e6fdf..9edf2bccf96 100644
--- a/chromium/content/public/browser/gpu_data_manager.h
+++ b/chromium/content/public/browser/gpu_data_manager.h
@@ -78,10 +78,6 @@ class GpuDataManager {
// Register a path to SwiftShader.
virtual void RegisterSwiftShaderPath(const base::FilePath& path) = 0;
- // Returns current state about WARP, which may be due to command-line
- // arguments or saved state.
- virtual bool ShouldUseWarp() const = 0;
-
// Registers/unregister |observer|.
virtual void AddObserver(GpuDataManagerObserver* observer) = 0;
virtual void RemoveObserver(GpuDataManagerObserver* observer) = 0;
diff --git a/chromium/content/public/browser/gpu_data_manager_observer.h b/chromium/content/public/browser/gpu_data_manager_observer.h
index 2f36feb63e3..64a6b9e17ed 100644
--- a/chromium/content/public/browser/gpu_data_manager_observer.h
+++ b/chromium/content/public/browser/gpu_data_manager_observer.h
@@ -7,11 +7,14 @@
#include "base/process/kill.h"
#include "content/common/content_export.h"
-#include "content/public/common/gpu_memory_stats.h"
#include "content/public/common/three_d_api_types.h"
class GURL;
+namespace gpu {
+struct VideoMemoryUsageStats;
+}
+
namespace content {
// Observers can register themselves via GpuDataManager::AddObserver, and
@@ -23,7 +26,7 @@ class CONTENT_EXPORT GpuDataManagerObserver {
// Called for any observers whenever there is a GPU video memory update.
virtual void OnVideoMemoryUsageStatsUpdate(
- const GPUVideoMemoryUsageStats& video_memory_usage_stats) {}
+ const gpu::VideoMemoryUsageStats& video_memory_usage_stats) {}
// Indicates that client 3D APIs (Pepper 3D, WebGL) were just blocked on the
// given page, specifically because the GPU was reset recently.
diff --git a/chromium/content/public/browser/gpu_service_registry.cc b/chromium/content/public/browser/gpu_service_registry.cc
new file mode 100644
index 00000000000..e6a2ba740d2
--- /dev/null
+++ b/chromium/content/public/browser/gpu_service_registry.cc
@@ -0,0 +1,18 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/browser/gpu_service_registry.h"
+
+#include "content/browser/gpu/gpu_process_host.h"
+
+namespace content {
+
+ServiceRegistry* GetGpuServiceRegistry() {
+ GpuProcessHost* host =
+ GpuProcessHost::Get(GpuProcessHost::GPU_PROCESS_KIND_SANDBOXED,
+ CAUSE_FOR_GPU_LAUNCH_GET_GPU_SERVICE_REGISTRY);
+ return host->GetServiceRegistry();
+}
+
+} // namespace content
diff --git a/chromium/content/public/browser/gpu_service_registry.h b/chromium/content/public/browser/gpu_service_registry.h
new file mode 100644
index 00000000000..0e025ee986f
--- /dev/null
+++ b/chromium/content/public/browser/gpu_service_registry.h
@@ -0,0 +1,19 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_BROWSER_GPU_SERVICE_REGISTRY_H_
+#define CONTENT_PUBLIC_BROWSER_GPU_SERVICE_REGISTRY_H_
+
+#include "content/common/content_export.h"
+
+namespace content {
+class ServiceRegistry;
+
+// Get ServiceRegistry registered via ContentGpuClient::RegisterMojoServices().
+// This must be called on IO thread.
+CONTENT_EXPORT ServiceRegistry* GetGpuServiceRegistry();
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_GPU_SERVICE_REGISTRY_H_
diff --git a/chromium/content/public/browser/gpu_utils.cc b/chromium/content/public/browser/gpu_utils.cc
new file mode 100644
index 00000000000..b6c00000887
--- /dev/null
+++ b/chromium/content/public/browser/gpu_utils.cc
@@ -0,0 +1,103 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/browser/gpu_utils.h"
+
+#include "base/command_line.h"
+#include "base/strings/string_number_conversions.h"
+#include "content/public/common/content_switches.h"
+#include "gpu/command_buffer/service/gpu_switches.h"
+#include "gpu/config/gpu_switches.h"
+#include "ui/gl/gl_switches.h"
+
+namespace {
+
+bool GetUintFromSwitch(const base::CommandLine* command_line,
+ const base::StringPiece& switch_string,
+ uint32_t* value) {
+ if (!command_line->HasSwitch(switch_string))
+ return false;
+ std::string switch_value(command_line->GetSwitchValueASCII(switch_string));
+ return base::StringToUint(switch_value, value);
+}
+
+} // namespace
+
+namespace content {
+
+const gpu::GpuPreferences GetGpuPreferencesFromCommandLine() {
+ DCHECK(base::CommandLine::InitializedForCurrentProcess());
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
+ gpu::GpuPreferences gpu_preferences;
+ gpu_preferences.single_process =
+ command_line->HasSwitch(switches::kSingleProcess);
+ gpu_preferences.in_process_gpu =
+ command_line->HasSwitch(switches::kInProcessGPU);
+ gpu_preferences.ui_prioritize_in_gpu_process =
+ command_line->HasSwitch(switches::kUIPrioritizeInGpuProcess);
+ gpu_preferences.disable_accelerated_video_decode =
+ command_line->HasSwitch(switches::kDisableAcceleratedVideoDecode);
+#if defined(OS_CHROMEOS)
+ gpu_preferences.disable_vaapi_accelerated_video_encode =
+ command_line->HasSwitch(switches::kDisableVaapiAcceleratedVideoEncode);
+#endif
+#if defined(ENABLE_WEBRTC)
+ gpu_preferences.disable_web_rtc_hw_encoding =
+ command_line->HasSwitch(switches::kDisableWebRtcHWEncoding);
+#endif
+#if defined(OS_WIN)
+ gpu_preferences.enable_accelerated_vpx_decode =
+ command_line->HasSwitch(switches::kEnableAcceleratedVpxDecode);
+#endif
+ gpu_preferences.compile_shader_always_succeeds =
+ command_line->HasSwitch(switches::kCompileShaderAlwaysSucceeds);
+ gpu_preferences.disable_gl_error_limit =
+ command_line->HasSwitch(switches::kDisableGLErrorLimit);
+ gpu_preferences.disable_glsl_translator =
+ command_line->HasSwitch(switches::kDisableGLSLTranslator);
+ gpu_preferences.disable_gpu_driver_bug_workarounds =
+ command_line->HasSwitch(switches::kDisableGpuDriverBugWorkarounds);
+ gpu_preferences.disable_shader_name_hashing =
+ command_line->HasSwitch(switches::kDisableShaderNameHashing);
+ gpu_preferences.enable_gpu_command_logging =
+ command_line->HasSwitch(switches::kEnableGPUCommandLogging);
+ gpu_preferences.enable_gpu_debugging =
+ command_line->HasSwitch(switches::kEnableGPUDebugging);
+ gpu_preferences.enable_gpu_service_logging_gpu =
+ command_line->HasSwitch(switches::kEnableGPUServiceLoggingGPU);
+ gpu_preferences.disable_gpu_program_cache =
+ command_line->HasSwitch(switches::kDisableGpuProgramCache);
+ gpu_preferences.enforce_gl_minimums =
+ command_line->HasSwitch(switches::kEnforceGLMinimums);
+ if (GetUintFromSwitch(command_line, switches::kForceGpuMemAvailableMb,
+ &gpu_preferences.force_gpu_mem_available)) {
+ gpu_preferences.force_gpu_mem_available *= 1024 * 1024;
+ }
+ if (GetUintFromSwitch(command_line, switches::kGpuProgramCacheSizeKb,
+ &gpu_preferences.gpu_program_cache_size)) {
+ gpu_preferences.gpu_program_cache_size *= 1024;
+ }
+ gpu_preferences.disable_gpu_shader_disk_cache =
+ command_line->HasSwitch(switches::kDisableGpuShaderDiskCache);
+ gpu_preferences.enable_share_group_async_texture_upload =
+ command_line->HasSwitch(switches::kEnableShareGroupAsyncTextureUpload);
+ gpu_preferences.enable_subscribe_uniform_extension =
+ command_line->HasSwitch(switches::kEnableSubscribeUniformExtension);
+ gpu_preferences.enable_threaded_texture_mailboxes =
+ command_line->HasSwitch(switches::kEnableThreadedTextureMailboxes);
+ gpu_preferences.gl_shader_interm_output =
+ command_line->HasSwitch(switches::kGLShaderIntermOutput);
+ gpu_preferences.emulate_shader_precision =
+ command_line->HasSwitch(switches::kEmulateShaderPrecision);
+ gpu_preferences.enable_gpu_service_logging =
+ command_line->HasSwitch(switches::kEnableGPUServiceLogging);
+ gpu_preferences.enable_gpu_service_tracing =
+ command_line->HasSwitch(switches::kEnableGPUServiceTracing);
+ gpu_preferences.enable_unsafe_es3_apis =
+ command_line->HasSwitch(switches::kEnableUnsafeES3APIs);
+ return gpu_preferences;
+}
+
+} // namespace content
diff --git a/chromium/content/public/browser/gpu_utils.h b/chromium/content/public/browser/gpu_utils.h
new file mode 100644
index 00000000000..84e78083c3d
--- /dev/null
+++ b/chromium/content/public/browser/gpu_utils.h
@@ -0,0 +1,17 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_BROWSER_GPU_UTILS_H_
+#define CONTENT_PUBLIC_BROWSER_GPU_UTILS_H_
+
+#include "content/common/content_export.h"
+#include "gpu/command_buffer/service/gpu_preferences.h"
+
+namespace content {
+
+CONTENT_EXPORT const gpu::GpuPreferences GetGpuPreferencesFromCommandLine();
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_GPU_UTILS_H_
diff --git a/chromium/content/public/browser/host_zoom_map.h b/chromium/content/public/browser/host_zoom_map.h
index aa7ef23b86f..9146db39f1e 100644
--- a/chromium/content/public/browser/host_zoom_map.h
+++ b/chromium/content/public/browser/host_zoom_map.h
@@ -11,6 +11,7 @@
#include "base/callback.h"
#include "base/callback_list.h"
+#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
#include "url/gurl.h"
diff --git a/chromium/content/public/browser/indexed_db_context.h b/chromium/content/public/browser/indexed_db_context.h
index 2bd01120e94..ef9d61f441b 100644
--- a/chromium/content/public/browser/indexed_db_context.h
+++ b/chromium/content/public/browser/indexed_db_context.h
@@ -42,7 +42,8 @@ class IndexedDBContext : public base::RefCountedThreadSafe<IndexedDBContext> {
// Get the file name of the local storage file for the given origin.
virtual base::FilePath GetFilePathForTesting(
- const std::string& origin_id) const = 0;
+ const GURL& origin_url) const = 0;
+
// Set the task runner for tests if browser main loop is not initialized.
virtual void SetTaskRunnerForTesting(
base::SequencedTaskRunner* task_runner) = 0;
diff --git a/chromium/content/public/browser/javascript_dialog_manager.h b/chromium/content/public/browser/javascript_dialog_manager.h
index 114418cf51a..001137b36a6 100644
--- a/chromium/content/public/browser/javascript_dialog_manager.h
+++ b/chromium/content/public/browser/javascript_dialog_manager.h
@@ -31,7 +31,6 @@ class CONTENT_EXPORT JavaScriptDialogManager {
virtual void RunJavaScriptDialog(
WebContents* web_contents,
const GURL& origin_url,
- const std::string& accept_lang,
JavaScriptMessageType javascript_message_type,
const base::string16& message_text,
const base::string16& default_prompt_text,
@@ -40,7 +39,6 @@ class CONTENT_EXPORT JavaScriptDialogManager {
// Displays a dialog asking the user if they want to leave a page.
virtual void RunBeforeUnloadDialog(WebContents* web_contents,
- const base::string16& message_text,
bool is_reload,
const DialogClosedCallback& callback) = 0;
diff --git a/chromium/content/public/browser/memory_pressure_controller.cc b/chromium/content/public/browser/memory_pressure_controller.cc
new file mode 100644
index 00000000000..7782d9a1890
--- /dev/null
+++ b/chromium/content/public/browser/memory_pressure_controller.cc
@@ -0,0 +1,27 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/browser/memory_pressure_controller.h"
+
+#include "content/browser/memory/memory_pressure_controller_impl.h"
+
+namespace content {
+
+// static
+void MemoryPressureController::SendPressureNotification(
+ const BrowserChildProcessHost* child_process_host,
+ base::MemoryPressureListener::MemoryPressureLevel level) {
+ MemoryPressureControllerImpl::GetInstance()->SendPressureNotification(
+ child_process_host, level);
+}
+
+// static
+void MemoryPressureController::SendPressureNotification(
+ const RenderProcessHost* render_process_host,
+ base::MemoryPressureListener::MemoryPressureLevel level) {
+ MemoryPressureControllerImpl::GetInstance()->SendPressureNotification(
+ render_process_host, level);
+}
+
+} // namespace content
diff --git a/chromium/content/public/browser/memory_pressure_controller.h b/chromium/content/public/browser/memory_pressure_controller.h
new file mode 100644
index 00000000000..0108006d059
--- /dev/null
+++ b/chromium/content/public/browser/memory_pressure_controller.h
@@ -0,0 +1,40 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_BROWSER_MEMORY_PRESSURE_CONTROLLER_H_
+#define CONTENT_PUBLIC_BROWSER_MEMORY_PRESSURE_CONTROLLER_H_
+
+#include "base/memory/memory_pressure_listener.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+class BrowserChildProcessHost;
+class RenderProcessHost;
+
+// Allows content embedders to forward memory pressure events from the main
+// browser process to children processes. For more details see
+// content/browser/memory/memory_pressure_controller_impl.h.
+class CONTENT_EXPORT MemoryPressureController {
+ public:
+
+ // Sends a memory pressure notification to the specified browser child process
+ // via its attached MemoryMessageFilter. May be called on any thread.
+ static void SendPressureNotification(
+ const BrowserChildProcessHost* child_process_host,
+ base::MemoryPressureListener::MemoryPressureLevel level);
+
+ // Sends a memory pressure notification to the specified renderer process via
+ // its attached MemoryMessageFilter. May be called on any thread.
+ static void SendPressureNotification(
+ const RenderProcessHost* render_process_host,
+ base::MemoryPressureListener::MemoryPressureLevel level);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MemoryPressureController);
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_MEMORY_PRESSURE_CONTROLLER_H_
diff --git a/chromium/content/public/browser/message_port_delegate.h b/chromium/content/public/browser/message_port_delegate.h
index bbe6326fecc..7c2de5bbde6 100644
--- a/chromium/content/public/browser/message_port_delegate.h
+++ b/chromium/content/public/browser/message_port_delegate.h
@@ -32,11 +32,6 @@ class CONTENT_EXPORT MessagePortDelegate {
const MessagePortMessage& message,
const std::vector<TransferredMessagePort>& sent_message_ports) = 0;
- // Called when MessagePortService tried to send a message to a port, but
- // instead added it to its queue because the port is currently configured to
- // hold all its messages.
- virtual void MessageWasHeld(int route_id) {}
-
// Requests messages to the given route to be queued.
virtual void SendMessagesAreQueued(int route_id) = 0;
diff --git a/chromium/content/public/browser/mojo_app_connection.h b/chromium/content/public/browser/mojo_app_connection.h
index 925f751dcbd..6ac8055e82b 100644
--- a/chromium/content/public/browser/mojo_app_connection.h
+++ b/chromium/content/public/browser/mojo_app_connection.h
@@ -13,8 +13,6 @@
#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/system/message_pipe.h"
-class GURL;
-
namespace content {
// A virtual app URL identifying the browser itself. This should be used for
@@ -29,20 +27,23 @@ class CONTENT_EXPORT MojoAppConnection {
public:
virtual ~MojoAppConnection() {}
- // Creates a new connection to the application at |url| using |requestor_url|
- // to identify the requestor upon connection. This may be called from any
- // thread.
- static scoped_ptr<MojoAppConnection> Create(const GURL& url,
- const GURL& requestor_url);
+ // Creates a new connection to the application at |name| using
+ // |requestor_name| to identify the requestor and |context|'s mojo userid to
+ // specify a profile specific application instantiation. This may be called
+ // from any thread.
+ static scoped_ptr<MojoAppConnection> Create(
+ const std::string& user_id,
+ const std::string& name,
+ const std::string& requestor_name);
// Connects to a service within the application.
template <typename Interface>
- void ConnectToService(mojo::InterfacePtr<Interface>* proxy) {
- ConnectToService(Interface::Name_, mojo::GetProxy(proxy).PassMessagePipe());
+ void GetInterface(mojo::InterfacePtr<Interface>* proxy) {
+ GetInterface(Interface::Name_, mojo::GetProxy(proxy).PassMessagePipe());
}
- virtual void ConnectToService(const std::string& service_name,
- mojo::ScopedMessagePipeHandle handle) = 0;
+ virtual void GetInterface(const std::string& interface_name,
+ mojo::ScopedMessagePipeHandle handle) = 0;
};
} // namespace content
diff --git a/chromium/content/public/browser/native_web_keyboard_event.h b/chromium/content/public/browser/native_web_keyboard_event.h
index fabb2fee64d..7f593dff287 100644
--- a/chromium/content/public/browser/native_web_keyboard_event.h
+++ b/chromium/content/public/browser/native_web_keyboard_event.h
@@ -12,6 +12,10 @@
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/gfx/native_widget_types.h"
+#if defined(OS_ANDROID)
+#include "base/android/scoped_java_ref.h"
+#endif
+
namespace ui {
class KeyEvent;
}
@@ -25,7 +29,7 @@ struct CONTENT_EXPORT NativeWebKeyboardEvent :
NativeWebKeyboardEvent();
explicit NativeWebKeyboardEvent(gfx::NativeEvent native_event);
-#if defined(OS_ANDROID) && !defined(USE_AURA)
+#if defined(OS_ANDROID)
NativeWebKeyboardEvent(blink::WebInputEvent::Type type,
int modifiers,
double time_secs,
@@ -34,14 +38,16 @@ struct CONTENT_EXPORT NativeWebKeyboardEvent :
int unicode_character,
bool is_system_key);
// Takes ownership of android_key_event.
- NativeWebKeyboardEvent(jobject android_key_event,
- blink::WebInputEvent::Type type,
- int modifiers,
- double time_secs,
- int keycode,
- int scancode,
- int unicode_character,
- bool is_system_key);
+ NativeWebKeyboardEvent(
+ JNIEnv* env,
+ const base::android::JavaRef<jobject>& android_key_event,
+ blink::WebInputEvent::Type type,
+ int modifiers,
+ double time_secs,
+ int keycode,
+ int scancode,
+ int unicode_character,
+ bool is_system_key);
#else
explicit NativeWebKeyboardEvent(const ui::KeyEvent& key_event);
#if defined(USE_AURA)
diff --git a/chromium/content/public/browser/navigation_controller.h b/chromium/content/public/browser/navigation_controller.h
index 78d18df4012..6e6c2e410c7 100644
--- a/chromium/content/public/browser/navigation_controller.h
+++ b/chromium/content/public/browser/navigation_controller.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include <map>
+#include <memory>
#include <string>
#include <vector>
@@ -42,10 +43,13 @@ class WebContents;
// exactly one NavigationController.
class NavigationController {
public:
+ // Note: NO_RELOAD is used in general, but behaviors depend on context.
+ // If it is used for tab restore, or history navigation, it loads preferring
+ // cache (which may be stale).
enum ReloadType {
- NO_RELOAD, // Normal load.
+ NO_RELOAD, // Normal load, restore, or history navigation.
RELOAD, // Normal (cache-validating) reload.
- RELOAD_IGNORING_CACHE, // Reload bypassing the cache (shift-reload).
+ RELOAD_BYPASSING_CACHE, // Reload bypassing the cache (shift-reload).
RELOAD_ORIGINAL_REQUEST_URL, // Reload using the original request URL.
RELOAD_DISABLE_LOFI_MODE // Reload with Lo-Fi mode disabled.
};
@@ -107,7 +111,7 @@ class NavigationController {
// Creates a navigation entry and translates the virtual url to a real one.
// This is a general call; prefer LoadURL[FromRenderer]/TransferURL below.
// Extra headers are separated by \n.
- CONTENT_EXPORT static scoped_ptr<NavigationEntry> CreateNavigationEntry(
+ CONTENT_EXPORT static std::unique_ptr<NavigationEntry> CreateNavigationEntry(
const GURL& url,
const Referrer& referrer,
ui::PageTransition transition,
@@ -236,9 +240,10 @@ class NavigationController {
// indicates where the restor comes from. This takes ownership of the
// NavigationEntrys in |entries| and clears it out. This is used for session
// restore.
- virtual void Restore(int selected_navigation,
- RestoreType type,
- std::vector<scoped_ptr<NavigationEntry>>* entries) = 0;
+ virtual void Restore(
+ int selected_navigation,
+ RestoreType type,
+ std::vector<std::unique_ptr<NavigationEntry>>* entries) = 0;
// Entries -------------------------------------------------------------------
@@ -327,7 +332,7 @@ class NavigationController {
// represented as an entry, but should go away when the user navigates away
// from them.
// Note that adding a transient entry does not change the active contents.
- virtual void SetTransientEntry(scoped_ptr<NavigationEntry> entry) = 0;
+ virtual void SetTransientEntry(std::unique_ptr<NavigationEntry> entry) = 0;
// New navigations -----------------------------------------------------------
@@ -376,7 +381,7 @@ class NavigationController {
virtual void ReloadToRefreshContent(bool check_for_repost) = 0;
// Like Reload(), but don't use caches (aka "shift-reload").
- virtual void ReloadIgnoringCache(bool check_for_repost) = 0;
+ virtual void ReloadBypassingCache(bool check_for_repost) = 0;
// Reloads the current entry using the original URL used to create it. This
// is used for cases where the user wants to refresh a page using a different
@@ -395,9 +400,7 @@ class NavigationController {
// Random --------------------------------------------------------------------
- // Session storage depends on dom_storage that depends on blink::WebString,
- // which cannot be used on iOS.
-#if !defined(OS_IOS)
+ // Session storage depends on dom_storage that depends on blink::WebString.
// Returns all the SessionStorageNamespace objects that this
// NavigationController knows about, the map key is a StoragePartition id.
virtual const SessionStorageNamespaceMap&
@@ -406,7 +409,6 @@ class NavigationController {
// TODO(ajwong): Remove this once prerendering, instant, and session restore
// are migrated.
virtual SessionStorageNamespace* GetDefaultSessionStorageNamespace() = 0;
-#endif
// Sets the max restored page ID this NavigationController has seen, if it
// was restored from a previous session.
diff --git a/chromium/content/public/browser/navigation_details.cc b/chromium/content/public/browser/navigation_details.cc
index 19d62998b44..88f247f3925 100644
--- a/chromium/content/public/browser/navigation_details.cc
+++ b/chromium/content/public/browser/navigation_details.cc
@@ -16,4 +16,7 @@ LoadCommittedDetails::LoadCommittedDetails()
http_status_code(0) {
}
+LoadCommittedDetails::LoadCommittedDetails(const LoadCommittedDetails& other) =
+ default;
+
} // namespace content
diff --git a/chromium/content/public/browser/navigation_details.h b/chromium/content/public/browser/navigation_details.h
index b34410578f4..dc473878f3c 100644
--- a/chromium/content/public/browser/navigation_details.h
+++ b/chromium/content/public/browser/navigation_details.h
@@ -22,6 +22,7 @@ struct CONTENT_EXPORT LoadCommittedDetails {
// By default, the entry will be filled according to a new main frame
// navigation.
LoadCommittedDetails();
+ LoadCommittedDetails(const LoadCommittedDetails& other);
// The committed entry. This will be the active entry in the controller.
NavigationEntry* entry;
diff --git a/chromium/content/public/browser/navigation_entry.h b/chromium/content/public/browser/navigation_entry.h
index 008b151631a..5041cbecd9d 100644
--- a/chromium/content/public/browser/navigation_entry.h
+++ b/chromium/content/public/browser/navigation_entry.h
@@ -109,11 +109,8 @@ class NavigationEntry {
// Page-related helpers ------------------------------------------------------
// Returns the title to be displayed on the tab. This could be the title of
- // the page if it is available or the URL. |languages| is the list of
- // accepted languages (e.g., prefs::kAcceptLanguages) or empty if proper
- // URL formatting isn't needed (e.g., unit tests).
- virtual const base::string16& GetTitleForDisplay(
- const std::string& languages) const = 0;
+ // the page if it is available or the URL.
+ virtual const base::string16& GetTitleForDisplay() const = 0;
// Returns true if the current tab is in view source mode. This will be false
// if there is no navigation.
diff --git a/chromium/content/public/browser/navigation_handle.cc b/chromium/content/public/browser/navigation_handle.cc
index 4926947a2e9..c013c0ee19e 100644
--- a/chromium/content/public/browser/navigation_handle.cc
+++ b/chromium/content/public/browser/navigation_handle.cc
@@ -27,7 +27,9 @@ scoped_ptr<NavigationHandle> NavigationHandle::CreateNavigationHandleForTesting(
scoped_ptr<NavigationHandleImpl> handle_impl = NavigationHandleImpl::Create(
url,
static_cast<RenderFrameHostImpl*>(render_frame_host)->frame_tree_node(),
- base::TimeTicks::Now());
+ false, // is_synchronous
+ false, // is_srcdoc
+ base::TimeTicks::Now(), 0);
return scoped_ptr<NavigationHandle>(std::move(handle_impl));
}
diff --git a/chromium/content/public/browser/navigation_handle.h b/chromium/content/public/browser/navigation_handle.h
index 0bfbca8c711..cd1e6ab5ea7 100644
--- a/chromium/content/public/browser/navigation_handle.h
+++ b/chromium/content/public/browser/navigation_handle.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_PUBLIC_BROWSER_NAVIGATION_HANDLE_H_
#define CONTENT_PUBLIC_BROWSER_NAVIGATION_HANDLE_H_
+#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
#include "content/public/browser/navigation_throttle.h"
#include "content/public/common/referrer.h"
@@ -19,6 +20,11 @@ class RenderFrameHost;
class WebContents;
// A NavigationHandle tracks information related to a single navigation.
+// NavigationHandles are provided to several WebContentsObserver methods to
+// allow observers to track specific navigations. Observers should clear any
+// references to a NavigationHandle at the time of
+// WebContentsObserver::DidFinishNavigation, just before the handle is
+// destroyed.
class CONTENT_EXPORT NavigationHandle {
public:
virtual ~NavigationHandle() {}
@@ -36,6 +42,29 @@ class CONTENT_EXPORT NavigationHandle {
// This remains constant over the navigation lifetime.
virtual bool IsInMainFrame() = 0;
+ // Whether the navigation is taking place in a frame that is a direct child
+ // of the main frame. This remains constant over the navigation lifetime.
+ virtual bool IsParentMainFrame() = 0;
+
+ // Whether the navigation is synchronous or not. Examples of synchronous
+ // navigations are:
+ // * reference fragment navigations
+ // * pushState/popState
+ virtual bool IsSynchronousNavigation() = 0;
+
+ // Whether the navigation is for an iframe with srcdoc attribute.
+ virtual bool IsSrcdoc() = 0;
+
+ // Returns the FrameTreeNode ID for the frame in which the navigation is
+ // performed. This ID is browser-global and uniquely identifies a frame that
+ // hosts content. The identifier is fixed at the creation of the frame and
+ // stays constant for the lifetime of the frame.
+ virtual int GetFrameTreeNodeId() = 0;
+
+ // Returns the FrameTreeNode ID for the parent frame. If this navigation is
+ // taking place in the main frame, the value returned is -1.
+ virtual int GetParentFrameTreeNodeId() = 0;
+
// The WebContents the navigation is taking place in.
WebContents* GetWebContents();
@@ -85,6 +114,9 @@ class CONTENT_EXPORT NavigationHandle {
// before the navigation has committed.
virtual bool IsSamePage() = 0;
+ // Whether the navigation has encountered a server redirect or not.
+ virtual bool WasServerRedirect() = 0;
+
// Whether the navigation has committed. This returns true for either
// successful commits or error pages that replace the previous page
// (distinguished by |IsErrorPage|), and false for errors that leave the user
diff --git a/chromium/content/public/browser/navigation_throttle.cc b/chromium/content/public/browser/navigation_throttle.cc
index ac3b3aa4056..5c795d655d2 100644
--- a/chromium/content/public/browser/navigation_throttle.cc
+++ b/chromium/content/public/browser/navigation_throttle.cc
@@ -20,4 +20,9 @@ NavigationThrottle::WillRedirectRequest() {
return NavigationThrottle::PROCEED;
}
+NavigationThrottle::ThrottleCheckResult
+NavigationThrottle::WillProcessResponse() {
+ return NavigationThrottle::PROCEED;
+}
+
} // namespace content
diff --git a/chromium/content/public/browser/navigation_throttle.h b/chromium/content/public/browser/navigation_throttle.h
index fff64b1f4fb..5876343db0d 100644
--- a/chromium/content/public/browser/navigation_throttle.h
+++ b/chromium/content/public/browser/navigation_throttle.h
@@ -55,6 +55,15 @@ class CONTENT_EXPORT NavigationThrottle {
// CANCEL_AND_IGNORE or DEFER and perform the destruction asynchronously.
virtual ThrottleCheckResult WillRedirectRequest();
+ // Called when a response's headers and metadata are available.
+ //
+ // The implementer is responsible for ensuring that the WebContents this
+ // throttle is associated with remain alive during the duration of this
+ // method. Failing to do so will result in use-after-free bugs. Should the
+ // implementer need to destroy the WebContents, it should return CANCEL,
+ // CANCEL_AND_IGNORE and perform the destruction asynchronously.
+ virtual ThrottleCheckResult WillProcessResponse();
+
// The NavigationHandle that is tracking the information related to this
// navigation.
NavigationHandle* navigation_handle() const { return navigation_handle_; }
diff --git a/chromium/content/public/browser/navigator_connect_context.h b/chromium/content/public/browser/navigator_connect_context.h
deleted file mode 100644
index 1c6dc7efa87..00000000000
--- a/chromium/content/public/browser/navigator_connect_context.h
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_PUBLIC_BROWSER_NAVIGATOR_CONNECT_CONTEXT_H_
-#define CONTENT_PUBLIC_BROWSER_NAVIGATOR_CONNECT_CONTEXT_H_
-
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-
-namespace content {
-
-class NavigatorConnectServiceFactory;
-
-// Use this class to register additional navigator.connect service factories.
-// One instance of this class exists per StoragePartition.
-// TODO(mek): Add API so services can close a connection.
-class NavigatorConnectContext
- : public base::RefCountedThreadSafe<NavigatorConnectContext> {
- public:
- // Register a service factory. The most recently added factory that claims to
- // handle a URL will be used to handle a connection request for that URL.
- // This method must always be called on the UI thread. No guarantees are
- // given as to on what thread the passed in factory will get destroyed.
- virtual void AddFactory(
- scoped_ptr<NavigatorConnectServiceFactory> factory) = 0;
-
- protected:
- friend class base::RefCountedThreadSafe<NavigatorConnectContext>;
- NavigatorConnectContext() {}
- virtual ~NavigatorConnectContext() {}
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_BROWSER_NAVIGATOR_CONNECT_CONTEXT_H_
diff --git a/chromium/content/public/browser/navigator_connect_service_factory.h b/chromium/content/public/browser/navigator_connect_service_factory.h
deleted file mode 100644
index 4a71f27b801..00000000000
--- a/chromium/content/public/browser/navigator_connect_service_factory.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_PUBLIC_BROWSER_NAVIGATOR_CONNECT_SERVICE_FACTORY_H_
-#define CONTENT_PUBLIC_BROWSER_NAVIGATOR_CONNECT_SERVICE_FACTORY_H_
-
-#include "base/callback.h"
-
-class GURL;
-
-namespace content {
-
-struct NavigatorConnectClient;
-class MessagePortDelegate;
-
-// Implement this interface to provide a new kind of navigator.connect
-// accessible service.
-// Instances of this class are owned by NavigatorConnectContext. Register new
-// factories by calling NavigatorConnectContext::AddFactory.
-class NavigatorConnectServiceFactory {
- public:
- // Call with nullptr to indicate connection failure. Ownership of the delegate
- // remains with the factory. It is assumed that for the passed
- // MessagePortDelegate implementation the route_id and message_port_id of a
- // connection are the same.
- // Pass true to |data_as_values| if the delegate expects to receive messages
- // from the client encoded as base::Value instead of the normal serialization
- // format.
- using ConnectCallback =
- base::Callback<void(MessagePortDelegate*, bool data_as_values)>;
-
- virtual ~NavigatorConnectServiceFactory() {}
-
- // Return true if this factory is responsible for handling connections to the
- // |target_url|. The most recently added factory that returns true for a
- // particular url is picked to handle the connection attempt.
- virtual bool HandlesUrl(const GURL& target_url) = 0;
-
- // Called to try to establish a connection. Only called if this factory was
- // the most recently added factory that returned true from |HandlesUrl| for
- // the url being connected to.
- virtual void Connect(const NavigatorConnectClient& client,
- const ConnectCallback& callback) = 0;
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_BROWSER_NAVIGATOR_CONNECT_SERVICE_FACTORY_H_
diff --git a/chromium/content/public/browser/notification_event_dispatcher.h b/chromium/content/public/browser/notification_event_dispatcher.h
index bb3df945e23..9cc43d4017c 100644
--- a/chromium/content/public/browser/notification_event_dispatcher.h
+++ b/chromium/content/public/browser/notification_event_dispatcher.h
@@ -27,7 +27,7 @@ class CONTENT_EXPORT NotificationEventDispatcher {
public:
static NotificationEventDispatcher* GetInstance();
- using NotificationClickDispatchCompleteCallback =
+ using NotificationDispatchCompleteCallback =
base::Callback<void(PersistentNotificationStatus)>;
// Dispatches the "notificationclick" event on the Service Worker associated
@@ -38,7 +38,19 @@ class CONTENT_EXPORT NotificationEventDispatcher {
int64_t persistent_notification_id,
const GURL& origin,
int action_index,
- const NotificationClickDispatchCompleteCallback&
+ const NotificationDispatchCompleteCallback&
+ dispatch_complete_callback) = 0;
+
+ // Dispatches the "notificationclose" event on the Service Worker associated
+ // with |persistent_notification_id| belonging to |origin|. The
+ // |dispatch_complete_callback| will be invoked when it's known whether the
+ // event successfully executed.
+ virtual void DispatchNotificationCloseEvent(
+ BrowserContext* browser_context,
+ int64_t persistent_notification_id,
+ const GURL& origin,
+ bool by_user,
+ const NotificationDispatchCompleteCallback&
dispatch_complete_callback) = 0;
protected:
diff --git a/chromium/content/public/browser/page_navigator.cc b/chromium/content/public/browser/page_navigator.cc
index c919ee2d8ca..40225e1aae8 100644
--- a/chromium/content/public/browser/page_navigator.cc
+++ b/chromium/content/public/browser/page_navigator.cc
@@ -51,6 +51,8 @@ OpenURLParams::OpenURLParams()
user_gesture(true) {
}
+OpenURLParams::OpenURLParams(const OpenURLParams& other) = default;
+
OpenURLParams::~OpenURLParams() {
}
diff --git a/chromium/content/public/browser/page_navigator.h b/chromium/content/public/browser/page_navigator.h
index 3e06d5688d1..51f02349648 100644
--- a/chromium/content/public/browser/page_navigator.h
+++ b/chromium/content/public/browser/page_navigator.h
@@ -37,6 +37,7 @@ struct CONTENT_EXPORT OpenURLParams {
WindowOpenDisposition disposition,
ui::PageTransition transition,
bool is_renderer_initiated);
+ OpenURLParams(const OpenURLParams& other);
~OpenURLParams();
// The URL/referrer to be opened.
diff --git a/chromium/content/public/browser/permission_manager.h b/chromium/content/public/browser/permission_manager.h
index 32c8f7fa510..c783c33a63e 100644
--- a/chromium/content/public/browser/permission_manager.h
+++ b/chromium/content/public/browser/permission_manager.h
@@ -6,7 +6,7 @@
#define CONTENT_PUBLIC_BROWSER_PERMISSION_MANAGER_H_
#include "content/common/content_export.h"
-#include "content/public/common/permission_status.mojom.h"
+#include "third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h"
class GURL;
@@ -37,8 +37,7 @@ class CONTENT_EXPORT PermissionManager {
PermissionType permission,
RenderFrameHost* render_frame_host,
const GURL& requesting_origin,
- bool user_gesture,
- const base::Callback<void(PermissionStatus)>& callback) = 0;
+ const base::Callback<void(blink::mojom::PermissionStatus)>& callback) = 0;
// Requests multiple permissions on behalf of a frame identified by
// render_frame_host.
@@ -54,9 +53,8 @@ class CONTENT_EXPORT PermissionManager {
const std::vector<PermissionType>& permission,
RenderFrameHost* render_frame_host,
const GURL& requesting_origin,
- bool user_gesture,
const base::Callback<void(
- const std::vector<PermissionStatus>&)>& callback) = 0;
+ const std::vector<blink::mojom::PermissionStatus>&)>& callback) = 0;
// Cancels a previous permission request specified by |request_id|. Cancelling
// an already cancelled request or providing the |request_id|
@@ -66,7 +64,7 @@ class CONTENT_EXPORT PermissionManager {
// Returns the permission status of a given requesting_origin/embedding_origin
// tuple. This is not taking a RenderFrameHost because the call might happen
// outside of a frame context.
- virtual PermissionStatus GetPermissionStatus(
+ virtual blink::mojom::PermissionStatus GetPermissionStatus(
PermissionType permission,
const GURL& requesting_origin,
const GURL& embedding_origin) = 0;
@@ -91,7 +89,7 @@ class CONTENT_EXPORT PermissionManager {
PermissionType permission,
const GURL& requesting_origin,
const GURL& embedding_origin,
- const base::Callback<void(PermissionStatus)>& callback) = 0;
+ const base::Callback<void(blink::mojom::PermissionStatus)>& callback) = 0;
// Unregisters from permission status change notifications.
// The |subscription_id| must match the value returned by the
diff --git a/chromium/content/public/browser/permission_type.h b/chromium/content/public/browser/permission_type.h
index d2f7b6d85a1..ec9e8c5c082 100644
--- a/chromium/content/public/browser/permission_type.h
+++ b/chromium/content/public/browser/permission_type.h
@@ -22,6 +22,7 @@ enum class PermissionType {
DURABLE_STORAGE = 7,
AUDIO_CAPTURE = 8,
VIDEO_CAPTURE = 9,
+ BACKGROUND_SYNC = 10,
// Always keep this at the end.
NUM,
diff --git a/chromium/content/public/browser/platform_notification_service.h b/chromium/content/public/browser/platform_notification_service.h
index 6c9e50904cf..e3be5704136 100644
--- a/chromium/content/public/browser/platform_notification_service.h
+++ b/chromium/content/public/browser/platform_notification_service.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include <set>
#include <string>
+#include <vector>
#include "base/callback_forward.h"
#include "base/memory/scoped_ptr.h"
@@ -15,12 +16,12 @@
#include "third_party/WebKit/public/platform/modules/notifications/WebNotificationPermission.h"
class GURL;
-class SkBitmap;
namespace content {
class BrowserContext;
class DesktopNotificationDelegate;
+struct NotificationResources;
struct PlatformNotificationData;
class ResourceContext;
@@ -48,14 +49,14 @@ class CONTENT_EXPORT PlatformNotificationService {
const GURL& origin,
int render_process_id) = 0;
- // Displays the notification described in |params| to the user. A closure
- // through which the notification can be closed will be stored in the
+ // Displays the notification described in |notification_data| to the user. A
+ // closure through which the notification can be closed will be stored in the
// |cancel_callback| argument. This method must be called on the UI thread.
virtual void DisplayNotification(
BrowserContext* browser_context,
const GURL& origin,
- const SkBitmap& icon,
const PlatformNotificationData& notification_data,
+ const NotificationResources& notification_resources,
scoped_ptr<DesktopNotificationDelegate> delegate,
base::Closure* cancel_callback) = 0;
@@ -65,8 +66,8 @@ class CONTENT_EXPORT PlatformNotificationService {
BrowserContext* browser_context,
int64_t persistent_notification_id,
const GURL& origin,
- const SkBitmap& icon,
- const PlatformNotificationData& notification_data) = 0;
+ const PlatformNotificationData& notification_data,
+ const NotificationResources& notification_resources) = 0;
// Closes the persistent notification identified by
// |persistent_notification_id|. This method must be called on the UI thread.
diff --git a/chromium/content/public/browser/plugin_service.h b/chromium/content/public/browser/plugin_service.h
index 3fa762332da..10522556f9e 100644
--- a/chromium/content/public/browser/plugin_service.h
+++ b/chromium/content/public/browser/plugin_service.h
@@ -22,7 +22,6 @@ class FilePath;
namespace content {
class BrowserContext;
-class PluginProcessHost;
class PluginServiceFilter;
class ResourceContext;
struct PepperPluginInfo;
@@ -54,9 +53,6 @@ class PluginService {
// Must be called on the instance to finish initialization.
virtual void Init() = 0;
- // Starts watching for changes in the list of installed plugins.
- virtual void StartWatchingPlugins() = 0;
-
// Gets the plugin in the list of plugins that matches the given url and mime
// type. Returns true if the data is frome a stale plugin list, false if it
// is up to date. This can be called from any thread.
@@ -106,9 +102,6 @@ class PluginService {
virtual void SetFilter(PluginServiceFilter* filter) = 0;
virtual PluginServiceFilter* GetFilter() = 0;
- // If the plugin with the given path is running, cleanly shuts it down.
- virtual void ForcePluginShutdown(const base::FilePath& plugin_path) = 0;
-
// Used to monitor plugin stability. An unstable plugin is one that has
// crashed more than a set number of times in a set time period.
virtual bool IsPluginUnstable(const base::FilePath& plugin_path) = 0;
@@ -117,14 +110,6 @@ class PluginService {
// of whether they are already loaded.
virtual void RefreshPlugins() = 0;
- // Add/Remove an extra plugin to load when we actually do the loading. Must
- // be called before the plugins have been loaded.
- virtual void AddExtraPluginPath(const base::FilePath& path) = 0;
- virtual void RemoveExtraPluginPath(const base::FilePath& path) = 0;
-
- // Same as above, but specifies a directory in which to search for plugins.
- virtual void AddExtraPluginDir(const base::FilePath& path) = 0;
-
// Register an internal plugin with the specified plugin information.
// An internal plugin must be registered before it can
// be loaded using PluginList::LoadPlugin().
@@ -140,27 +125,6 @@ class PluginService {
// Gets a list of all the registered internal plugins.
virtual void GetInternalPlugins(std::vector<WebPluginInfo>* plugins) = 0;
- // Returns true iff NPAPI plugins are supported on the current platform.
- // This can be called from any thread.
- virtual bool NPAPIPluginsSupported() = 0;
-
- // This is equivalent to specifying kDisablePluginsDiscovery, but is useful
- // for unittests.
- virtual void DisablePluginsDiscoveryForTesting() = 0;
-
-#if defined(OS_MACOSX)
- // Called when the application is made active so that modal plugin windows can
- // be made forward too.
- virtual void AppActivated() = 0;
-#elif defined(OS_WIN)
- // Returns the name and version of a plugin HWND. If the HWND isn't a valid
- // plugin, returns false.
- // This can be called from any thread.
- virtual bool GetPluginInfoFromWindow(HWND window,
- base::string16* plugin_name,
- base::string16* plugin_version) = 0;
-#endif
-
// Returns true iff PPAPI "dev channel" methods are supported.
virtual bool PpapiDevChannelSupported(BrowserContext* browser_context,
const GURL& document_url) = 0;
diff --git a/chromium/content/public/browser/plugin_service_filter.h b/chromium/content/public/browser/plugin_service_filter.h
index 5b9d216e88c..e2dac555b84 100644
--- a/chromium/content/public/browser/plugin_service_filter.h
+++ b/chromium/content/public/browser/plugin_service_filter.h
@@ -35,13 +35,6 @@ class PluginServiceFilter {
// Whether the renderer has permission to load available |plugin|.
virtual bool CanLoadPlugin(int render_process_id,
const base::FilePath& path) = 0;
-
- // Called when a renderer loads an NPAPI |plugin| that matched |mime_type|.
- // TODO(wfh): Remove when NPAPI is gone.
- virtual void NPAPIPluginLoaded(int render_process_id,
- int render_frame_id,
- const std::string& mime_type,
- const WebPluginInfo& plugin) {}
};
} // namespace content
diff --git a/chromium/content/public/browser/presentation_service_delegate.h b/chromium/content/public/browser/presentation_service_delegate.h
index d3b92be08ed..fdd25c38b1b 100644
--- a/chromium/content/public/browser/presentation_service_delegate.h
+++ b/chromium/content/public/browser/presentation_service_delegate.h
@@ -23,8 +23,6 @@ using PresentationSessionStartedCallback =
base::Callback<void(const PresentationSessionInfo&)>;
using PresentationSessionErrorCallback =
base::Callback<void(const PresentationError&)>;
-using PresentationConnectionStateChangedCallback =
- base::Callback<void(PresentationConnectionState)>;
// Param #0: a vector of messages that are received.
// Param #1: tells the callback handler that it may reuse strings or buffers
@@ -32,6 +30,23 @@ using PresentationConnectionStateChangedCallback =
using PresentationSessionMessageCallback = base::Callback<
void(const ScopedVector<content::PresentationSessionMessage>&, bool)>;
+struct PresentationConnectionStateChangeInfo {
+ explicit PresentationConnectionStateChangeInfo(
+ PresentationConnectionState state)
+ : state(state),
+ close_reason(PRESENTATION_CONNECTION_CLOSE_REASON_CONNECTION_ERROR) {}
+ ~PresentationConnectionStateChangeInfo() = default;
+
+ PresentationConnectionState state;
+
+ // |close_reason| and |messsage| are only used for state change to CLOSED.
+ PresentationConnectionCloseReason close_reason;
+ std::string message;
+};
+
+using PresentationConnectionStateChangedCallback =
+ base::Callback<void(const PresentationConnectionStateChangeInfo&)>;
+
// An interface implemented by embedders to handle presentation API calls
// forwarded from PresentationServiceImpl.
class CONTENT_EXPORT PresentationServiceDelegate {
diff --git a/chromium/content/public/browser/presentation_session.h b/chromium/content/public/browser/presentation_session.h
index 336912baeff..8662f304920 100644
--- a/chromium/content/public/browser/presentation_session.h
+++ b/chromium/content/public/browser/presentation_session.h
@@ -18,6 +18,14 @@ enum PresentationConnectionState {
PRESENTATION_CONNECTION_STATE_TERMINATED
};
+// TODO(imcheng): Use WENT_AWAY for 1-UA mode when it is implemented
+// (crbug.com/513859).
+enum PresentationConnectionCloseReason {
+ PRESENTATION_CONNECTION_CLOSE_REASON_CONNECTION_ERROR,
+ PRESENTATION_CONNECTION_CLOSE_REASON_CLOSED,
+ PRESENTATION_CONNECTION_CLOSE_REASON_WENT_AWAY
+};
+
// TODO(imcheng): Rename to PresentationConnectionInfo.
// Represents a presentation session that has been established via either
// browser actions or Presentation API.
diff --git a/chromium/content/public/browser/push_messaging_service.h b/chromium/content/public/browser/push_messaging_service.h
index 31163d4b3a1..993e2816da8 100644
--- a/chromium/content/public/browser/push_messaging_service.h
+++ b/chromium/content/public/browser/push_messaging_service.h
@@ -19,6 +19,7 @@ namespace content {
class BrowserContext;
class ServiceWorkerContext;
+struct PushSubscriptionOptions;
// A push service-agnostic interface that the Push API uses for talking to
// push messaging services like GCM. Must only be used on the UI thread.
@@ -49,24 +50,22 @@ class CONTENT_EXPORT PushMessagingService {
// origins and push registrations.
virtual GURL GetPushEndpoint() = 0;
- // Subscribe the given |sender_id| with the push messaging service in a
- // document context. The frame is known and a permission UI may be displayed
- // to the user.
+ // Subscribe the given |options.sender_info| with the push messaging service
+ // in a document context. The frame is known and a permission UI may be
+ // displayed to the user.
virtual void SubscribeFromDocument(const GURL& requesting_origin,
int64_t service_worker_registration_id,
- const std::string& sender_id,
int renderer_id,
int render_frame_id,
- bool user_visible,
+ const PushSubscriptionOptions& options,
const RegisterCallback& callback) = 0;
- // Subscribe the given |sender_id| with the push messaging service. The frame
- // is not known so if permission was not previously granted by the user this
- // request should fail.
+ // Subscribe the given |options.sender_info| with the push messaging service.
+ // The frame is not known so if permission was not previously granted by the
+ // user this request should fail.
virtual void SubscribeFromWorker(const GURL& requesting_origin,
int64_t service_worker_registration_id,
- const std::string& sender_id,
- bool user_visible,
+ const PushSubscriptionOptions& options,
const RegisterCallback& callback) = 0;
// Retrieves the encryption information associated with the subscription
@@ -83,13 +82,11 @@ class CONTENT_EXPORT PushMessagingService {
const std::string& sender_id,
const UnregisterCallback& callback) = 0;
- // Checks the permission status for the requesting origin. Permission is only
- // ever granted when the requesting origin matches the top level embedding
- // origin. The |user_visible| boolean indicates whether the permission status
- // only has to cover push messages resulting in visible effects to the user.
+ // Checks the permission status for the |origin|. The |user_visible| boolean
+ // indicates whether the permission status only has to cover push messages
+ // resulting in visible effects to the user.
virtual blink::WebPushPermissionStatus GetPermissionStatus(
- const GURL& requesting_origin,
- const GURL& embedding_origin,
+ const GURL& origin,
bool user_visible) = 0;
// Returns whether subscriptions that do not mandate user visible UI upon
diff --git a/chromium/content/public/browser/readback_types.h b/chromium/content/public/browser/readback_types.h
index 1e1f8f7b94d..80a9ab74639 100644
--- a/chromium/content/public/browser/readback_types.h
+++ b/chromium/content/public/browser/readback_types.h
@@ -11,7 +11,8 @@ class SkBitmap;
namespace content {
-// ReadbackResponse type used in ContentReadbackHandler.
+// ReadbackResponse indicates success/failure for an operation that reads pixel
+// content back into normal memory.
//
// A Java counterpart will be generated for this enum.
// GENERATED_JAVA_ENUM_PACKAGE: (
@@ -24,6 +25,8 @@ enum ReadbackResponse {
READBACK_BITMAP_ALLOCATION_FAILURE,
};
+// A callback that is invoked upon completion or failure of a request to read
+// pixel data back into an SkBitmap.
using ReadbackRequestCallback =
base::Callback<void(const SkBitmap&, ReadbackResponse)>;
diff --git a/chromium/content/public/browser/render_frame_host.h b/chromium/content/public/browser/render_frame_host.h
index 4a45df26931..b8fa796f8c1 100644
--- a/chromium/content/public/browser/render_frame_host.h
+++ b/chromium/content/public/browser/render_frame_host.h
@@ -26,6 +26,7 @@ class Value;
namespace content {
class RenderProcessHost;
class RenderViewHost;
+class RenderWidgetHostView;
class ServiceRegistry;
class SiteInstance;
@@ -73,6 +74,10 @@ class CONTENT_EXPORT RenderFrameHost : public IPC::Listener,
// Returns the process for this frame.
virtual RenderProcessHost* GetProcess() = 0;
+ // Returns the RenderWidgetHostView that can be used to control focus and
+ // visibility for this frame.
+ virtual RenderWidgetHostView* GetView() = 0;
+
// Returns the current RenderFrameHost of the parent frame, or nullptr if
// there is no parent. The result may be in a different process than the
// current RenderFrameHost.
@@ -99,13 +104,7 @@ class CONTENT_EXPORT RenderFrameHost : public IPC::Listener,
virtual bool IsCrossProcessSubframe() = 0;
// Returns the last committed URL of the frame.
- //
- // The URL is only accurate if this RenderFrameHost is current in the frame
- // tree -- i.e., it would be visited by WebContents::ForEachFrame. In
- // particular, this method may return a misleading value if called from
- // WebContentsObserver::RenderFrameCreated, since non-current frames can be
- // passed to that observer method.
- virtual GURL GetLastCommittedURL() = 0;
+ virtual const GURL& GetLastCommittedURL() = 0;
// Returns the last committed origin of the frame.
//
@@ -188,6 +187,19 @@ class CONTENT_EXPORT RenderFrameHost : public IPC::Listener,
// and still has a connection. This is valid for all frames.
virtual bool IsRenderFrameLive() = 0;
+ // Get the number of proxies to this frame, in all processes. Exposed for
+ // use by resource metrics.
+ virtual int GetProxyCount() = 0;
+
+#if defined(OS_ANDROID)
+ // Selects and zooms to the find result nearest to the point (x,y)
+ // defined in find-in-page coordinates.
+ virtual void ActivateNearestFindResult(int request_id, float x, float y) = 0;
+
+ // Asks the renderer process to send the rects of the current find matches.
+ virtual void RequestFindMatchRects(int current_version) = 0;
+#endif
+
private:
// This interface should only be implemented inside content.
friend class RenderFrameHostImpl;
diff --git a/chromium/content/public/browser/render_process_host.h b/chromium/content/public/browser/render_process_host.h
index 96f6dd58459..f20c2ebb5ca 100644
--- a/chromium/content/public/browser/render_process_host.h
+++ b/chromium/content/public/browser/render_process_host.h
@@ -22,6 +22,7 @@
class GURL;
namespace base {
+class SharedPersistentMemoryAllocator;
class TimeDelta;
}
@@ -111,10 +112,6 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
virtual bool IsForGuestsOnly() const = 0;
// Returns the storage partition associated with this process.
- //
- // TODO(nasko): Remove this function from the public API once
- // URLRequestContextGetter's creation is moved into StoragePartition.
- // http://crbug.com/158595
virtual StoragePartition* GetStoragePartition() const = 0;
// Try to shut down the associated renderer process without running unload
@@ -213,10 +210,6 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
// 10 milliseconds.
virtual base::TimeDelta GetChildProcessIdleTime() const = 0;
- // Called to resume the requests for a view created through window.open that
- // were initially blocked.
- virtual void ResumeRequestsForView(int route_id) = 0;
-
// Checks that the given renderer can request |url|, if not it sets it to
// about:blank.
// |empty_allowed| must be set to false for navigations for security reasons.
@@ -234,6 +227,7 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
// process associated with this RenderProcessHost.
virtual void SetWebRtcLogMessageCallback(
base::Callback<void(const std::string&)> callback) = 0;
+ virtual void ClearWebRtcLogMessageCallback() = 0;
typedef base::Callback<void(scoped_ptr<uint8_t[]> packet_header,
size_t header_length,
@@ -262,6 +256,14 @@ class CONTENT_EXPORT RenderProcessHost : public IPC::Sender,
// Returns the ServiceRegistry for this process.
virtual ServiceRegistry* GetServiceRegistry() = 0;
+ // Extracts any persistent-memory-allocator used for renderer metrics.
+ // Ownership is passed to the caller. To support sharing of histogram data
+ // between the Renderer and the Browser, the allocator is created when the
+ // process is created and later retrieved by the SubprocessMetricsProvider
+ // for management.
+ virtual scoped_ptr<base::SharedPersistentMemoryAllocator>
+ TakeMetricsAllocator() = 0;
+
// PlzNavigate
// Returns the time the first call to Init completed successfully (after a new
// renderer process was created); further calls to Init won't change this
diff --git a/chromium/content/public/browser/render_view_host.h b/chromium/content/public/browser/render_view_host.h
index 44acef8076f..1a4d1646d70 100644
--- a/chromium/content/public/browser/render_view_host.h
+++ b/chromium/content/public/browser/render_view_host.h
@@ -216,15 +216,6 @@ class CONTENT_EXPORT RenderViewHost : public IPC::Sender {
// Notify the render view host to select the word around the caret.
virtual void SelectWordAroundCaret() = 0;
-#if defined(OS_ANDROID)
- // Selects and zooms to the find result nearest to the point (x,y)
- // defined in find-in-page coordinates.
- virtual void ActivateNearestFindResult(int request_id, float x, float y) = 0;
-
- // Asks the renderer to send the rects of the current find matches.
- virtual void RequestFindMatchRects(int current_version) = 0;
-#endif
-
private:
// This interface should only be implemented inside content.
friend class RenderViewHostImpl;
diff --git a/chromium/content/public/browser/render_widget_host_view.h b/chromium/content/public/browser/render_widget_host_view.h
index 9b48ddba29d..99459addbd3 100644
--- a/chromium/content/public/browser/render_widget_host_view.h
+++ b/chromium/content/public/browser/render_widget_host_view.h
@@ -65,6 +65,19 @@ class CONTENT_EXPORT RenderWidgetHostView {
// Retrieves the last known scroll position.
virtual gfx::Vector2dF GetLastScrollOffset() const = 0;
+ // Coordinate points received from a renderer process need to be transformed
+ // to the top-level frame's coordinate space. For coordinates received from
+ // the top-level frame's renderer this is a no-op as they are already
+ // properly transformed; however, coordinates received from an out-of-process
+ // iframe renderer process require transformation.
+ virtual gfx::Point TransformPointToRootCoordSpace(
+ const gfx::Point& point) = 0;
+
+ // A floating point variant of the above. PointF values will be snapped to
+ // integral points before transformation.
+ virtual gfx::PointF TransformPointToRootCoordSpaceF(
+ const gfx::PointF& point) = 0;
+
// Retrieves the native view used to contain plugins and identify the
// renderer in IPC messages.
virtual gfx::NativeView GetNativeView() const = 0;
@@ -150,17 +163,6 @@ class CONTENT_EXPORT RenderWidgetHostView {
// Set the view's active state (i.e., tint state of controls).
virtual void SetActive(bool active) = 0;
- // Notifies the view that its enclosing window has changed visibility
- // (minimized/unminimized, app hidden/unhidden, etc).
- // TODO(stuartmorgan): This is a temporary plugin-specific workaround for
- // <http://crbug.com/34266>. Once that is fixed, this (and the corresponding
- // message and renderer-side handling) can be removed in favor of using
- // WasHidden/WasShown.
- virtual void SetWindowVisibility(bool visible) = 0;
-
- // Informs the view that its containing window's frame changed.
- virtual void WindowFrameChanged() = 0;
-
// Brings up the dictionary showing a definition for the selected text.
virtual void ShowDefinitionForSelection() = 0;
diff --git a/chromium/content/public/browser/render_widget_host_view_mac_delegate.h b/chromium/content/public/browser/render_widget_host_view_mac_delegate.h
index c00d8bd3109..427f466f117 100644
--- a/chromium/content/public/browser/render_widget_host_view_mac_delegate.h
+++ b/chromium/content/public/browser/render_widget_host_view_mac_delegate.h
@@ -8,6 +8,7 @@
#import <Cocoa/Cocoa.h>
namespace blink {
+class WebGestureEvent;
class WebMouseWheelEvent;
}
@@ -60,6 +61,8 @@ class WebMouseWheelEvent;
// |event|.
- (void)rendererHandledWheelEvent:(const blink::WebMouseWheelEvent&)event
consumed:(BOOL)consumed;
+- (void)rendererHandledGestureScrollEvent:(const blink::WebGestureEvent&)event
+ consumed:(BOOL)consumed;
@end
#endif // CONTENT_PUBLIC_BROWSER_RENDER_WIDGET_HOST_VIEW_MAC_DELEGATE_H_
diff --git a/chromium/content/public/browser/resource_context.h b/chromium/content/public/browser/resource_context.h
index e96f7c235d7..5a9419b8ddf 100644
--- a/chromium/content/public/browser/resource_context.h
+++ b/chromium/content/public/browser/resource_context.h
@@ -33,9 +33,7 @@ class AppCacheService;
// the UI thread. It must be destructed on the IO thread.
class CONTENT_EXPORT ResourceContext : public base::SupportsUserData {
public:
-#if !defined(OS_IOS)
ResourceContext();
-#endif
~ResourceContext() override;
virtual net::HostResolver* GetHostResolver() = 0;
diff --git a/chromium/content/public/browser/resource_dispatcher_host.cc b/chromium/content/public/browser/resource_dispatcher_host.cc
new file mode 100644
index 00000000000..3e2050eb8fc
--- /dev/null
+++ b/chromium/content/public/browser/resource_dispatcher_host.cc
@@ -0,0 +1,28 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/browser/resource_dispatcher_host.h"
+
+#include "base/callback.h"
+#include "content/browser/frame_host/render_frame_host_impl.h"
+#include "content/browser/loader/global_routing_id.h"
+#include "content/browser/loader/resource_dispatcher_host_impl.h"
+#include "content/public/browser/browser_thread.h"
+
+namespace content {
+
+// static
+void ResourceDispatcherHost::BlockRequestsForFrameFromUI(
+ RenderFrameHost* root_frame_host) {
+ ResourceDispatcherHostImpl::BlockRequestsForFrameFromUI(root_frame_host);
+}
+
+// static
+void ResourceDispatcherHost::ResumeBlockedRequestsForFrameFromUI(
+ RenderFrameHost* root_frame_host) {
+ ResourceDispatcherHostImpl::ResumeBlockedRequestsForFrameFromUI(
+ root_frame_host);
+}
+
+} // namespace content
diff --git a/chromium/content/public/browser/resource_dispatcher_host.h b/chromium/content/public/browser/resource_dispatcher_host.h
index d8b2495f22c..49366749251 100644
--- a/chromium/content/public/browser/resource_dispatcher_host.h
+++ b/chromium/content/public/browser/resource_dispatcher_host.h
@@ -9,7 +9,7 @@
#include "base/callback_forward.h"
#include "base/memory/scoped_ptr.h"
-#include "content/public/browser/download_interrupt_reasons.h"
+#include "content/common/content_export.h"
namespace net {
class URLRequest;
@@ -22,15 +22,23 @@ class ResourceContext;
class ResourceDispatcherHostDelegate;
struct DownloadSaveInfo;
struct Referrer;
+class RenderFrameHost;
class CONTENT_EXPORT ResourceDispatcherHost {
public:
- typedef base::Callback<void(DownloadItem*, DownloadInterruptReason)>
- DownloadStartedCallback;
-
// Returns the singleton instance of the ResourceDispatcherHost.
static ResourceDispatcherHost* Get();
+ // Causes all new requests for the root RenderFrameHost and its children to be
+ // blocked (not being started) until ResumeBlockedRequestsForFrameFromUI is
+ // called.
+ static void BlockRequestsForFrameFromUI(RenderFrameHost* root_frame_host);
+
+ // Resumes any blocked request for the specified root RenderFrameHost and
+ // child frame hosts.
+ static void ResumeBlockedRequestsForFrameFromUI(
+ RenderFrameHost* root_frame_host);
+
// This does not take ownership of the delegate. It is expected that the
// delegate have a longer lifetime than the ResourceDispatcherHost.
virtual void SetDelegate(ResourceDispatcherHostDelegate* delegate) = 0;
@@ -39,41 +47,9 @@ class CONTENT_EXPORT ResourceDispatcherHost {
// dialog boxes.
virtual void SetAllowCrossOriginAuthPrompt(bool value) = 0;
- // Initiates a download by explicit request of the renderer (e.g. due to
- // alt-clicking a link) or some other chrome subsystem.
- // |is_content_initiated| is used to indicate that the request was generated
- // from a web page, and hence may not be as trustworthy as a browser
- // generated request. If |download_id| is invalid, a download id will be
- // automatically assigned to the request, otherwise the specified download id
- // will be used. (Note that this will result in re-use of an existing
- // download item if the download id was already assigned.) If the download
- // is started, |started_callback| will be called on the UI thread with the
- // DownloadItem; otherwise an interrupt reason will be returned.
- virtual DownloadInterruptReason BeginDownload(
- scoped_ptr<net::URLRequest> request,
- const Referrer& referrer,
- bool is_content_initiated,
- ResourceContext* context,
- int child_id,
- int render_view_route_id,
- int render_frame_route_id,
- bool prefer_cache,
- bool do_not_prompt_for_login,
- scoped_ptr<DownloadSaveInfo> save_info,
- uint32_t download_id,
- const DownloadStartedCallback& started_callback) = 0;
-
// Clears the ResourceDispatcherHostLoginDelegate associated with the request.
virtual void ClearLoginDelegateForRequest(net::URLRequest* request) = 0;
- // Causes all new requests for the route identified by |child_id| and
- // |route_id| to be blocked (not being started) until
- // ResumeBlockedRequestsForRoute is called.
- virtual void BlockRequestsForRoute(int child_id, int route_id) = 0;
-
- // Resumes any blocked request for the specified route id.
- virtual void ResumeBlockedRequestsForRoute(int child_id, int route_id) = 0;
-
protected:
virtual ~ResourceDispatcherHost() {}
};
diff --git a/chromium/content/public/browser/resource_request_info.h b/chromium/content/public/browser/resource_request_info.h
index d5ee296b659..68c32fbdb94 100644
--- a/chromium/content/public/browser/resource_request_info.h
+++ b/chromium/content/public/browser/resource_request_info.h
@@ -52,6 +52,10 @@ class ResourceRequestInfo {
int* render_process_id,
int* render_frame_id);
+ // Returns true if the request originated from a Service Worker.
+ CONTENT_EXPORT static bool OriginatedFromServiceWorker(
+ const net::URLRequest* request);
+
// A callback that returns a pointer to a WebContents. The callback can
// always be used, but it may return nullptr: if the info used to
// instantiate the callback can no longer be used to return a WebContents,
@@ -78,6 +82,7 @@ class ResourceRequestInfo {
// The IPC route identifier for this request (this identifies the RenderView
// or like-thing in the renderer that the request gets routed to).
// To get a WebContents, use GetWebContentsGetterForRequest instead.
+ // Don't use this method for new code, as RenderViews are going away.
virtual int GetRouteID() const = 0;
// The pid of the originating process, if the request is sent on behalf of a
diff --git a/chromium/content/public/browser/screen_orientation_provider.cc b/chromium/content/public/browser/screen_orientation_provider.cc
index 165c0a7d68d..e50be45c7e0 100644
--- a/chromium/content/public/browser/screen_orientation_provider.cc
+++ b/chromium/content/public/browser/screen_orientation_provider.cc
@@ -113,7 +113,7 @@ void ScreenOrientationProvider::SetDelegate(
}
void ScreenOrientationProvider::DidToggleFullscreenModeForTab(
- bool entered_fullscreen) {
+ bool entered_fullscreen, bool will_cause_resize) {
if (!lock_applied_ || !delegate_)
return;
diff --git a/chromium/content/public/browser/screen_orientation_provider.h b/chromium/content/public/browser/screen_orientation_provider.h
index c3bda14ba89..75f8a3992d9 100644
--- a/chromium/content/public/browser/screen_orientation_provider.h
+++ b/chromium/content/public/browser/screen_orientation_provider.h
@@ -41,7 +41,8 @@ class CONTENT_EXPORT ScreenOrientationProvider : public WebContentsObserver {
static void SetDelegate(ScreenOrientationDelegate* delegate_);
// WebContentsObserver
- void DidToggleFullscreenModeForTab(bool entered_fullscreen) override;
+ void DidToggleFullscreenModeForTab(bool entered_fullscreen,
+ bool will_cause_resize) override;
private:
struct LockInformation {
diff --git a/chromium/content/public/browser/service_worker_context.h b/chromium/content/public/browser/service_worker_context.h
index 2d721cac2fe..72650154c72 100644
--- a/chromium/content/public/browser/service_worker_context.h
+++ b/chromium/content/public/browser/service_worker_context.h
@@ -49,6 +49,9 @@ class ServiceWorkerContext {
// * |script_url| fails to parse or its top-level execution fails.
// TODO: The error message for this needs to be available to developers.
// * Something unexpected goes wrong, like a renderer crash or a full disk.
+ //
+ // This function can be called from any thread, but the callback will always
+ // be called on the UI thread.
virtual void RegisterServiceWorker(const Scope& pattern,
const GURL& script_url,
const ResultCallback& callback) = 0;
@@ -61,11 +64,19 @@ class ServiceWorkerContext {
// Unregistration can fail if:
// * No Service Worker was registered for |pattern|.
// * Something unexpected goes wrong, like a renderer crash.
+ //
+ // This function can be called from any thread, but the callback will always
+ // be called on the UI thread.
virtual void UnregisterServiceWorker(const Scope& pattern,
const ResultCallback& callback) = 0;
// Methods used in response to browsing data and quota manager requests.
+
+ // Must be called from the IO thread.
virtual void GetAllOriginsInfo(const GetUsageInfoCallback& callback) = 0;
+
+ // This function can be called from any thread, but the callback will always
+ // be called on the IO thread.
virtual void DeleteForOrigin(const GURL& origin_url,
const ResultCallback& callback) = 0;
@@ -73,6 +84,7 @@ class ServiceWorkerContext {
// and if |other_url| falls inside the scope of the same registration. Note
// this still returns true even if there is a Service Worker registration
// which has a longer match for |other_url|.
+ //
// This function can be called from any thread, but the callback will always
// be called on the UI thread.
virtual void CheckHasServiceWorker(
@@ -81,11 +93,16 @@ class ServiceWorkerContext {
const CheckHasServiceWorkerCallback& callback) = 0;
// Stops all running workers on the given |origin|.
+ //
+ // This function can be called from any thread.
virtual void StopAllServiceWorkersForOrigin(const GURL& origin) = 0;
// Stops all running service workers and unregisters all service worker
// registrations. This method is used in LayoutTests to make sure that the
// existing service worker will not affect the succeeding tests.
+ //
+ // This function can be called from any thread, but the callback will always
+ // be called on the UI thread.
virtual void ClearAllServiceWorkersForTest(const base::Closure& callback) = 0;
protected:
diff --git a/chromium/content/public/browser/service_worker_usage_info.cc b/chromium/content/public/browser/service_worker_usage_info.cc
index 6d72ea3f77a..fdc3830b852 100644
--- a/chromium/content/public/browser/service_worker_usage_info.cc
+++ b/chromium/content/public/browser/service_worker_usage_info.cc
@@ -16,6 +16,9 @@ ServiceWorkerUsageInfo::ServiceWorkerUsageInfo(const GURL& origin)
ServiceWorkerUsageInfo::ServiceWorkerUsageInfo() : total_size_bytes(0) {
}
+ServiceWorkerUsageInfo::ServiceWorkerUsageInfo(
+ const ServiceWorkerUsageInfo& other) = default;
+
ServiceWorkerUsageInfo::~ServiceWorkerUsageInfo() {
}
diff --git a/chromium/content/public/browser/service_worker_usage_info.h b/chromium/content/public/browser/service_worker_usage_info.h
index 4c69d95cadb..6e50cc98fbd 100644
--- a/chromium/content/public/browser/service_worker_usage_info.h
+++ b/chromium/content/public/browser/service_worker_usage_info.h
@@ -19,6 +19,7 @@ struct CONTENT_EXPORT ServiceWorkerUsageInfo {
ServiceWorkerUsageInfo(const GURL& origin, const std::vector<GURL>& scopes);
ServiceWorkerUsageInfo(const GURL& origin);
ServiceWorkerUsageInfo();
+ ServiceWorkerUsageInfo(const ServiceWorkerUsageInfo& other);
~ServiceWorkerUsageInfo();
// The origin this object is describing.
diff --git a/chromium/content/public/browser/site_instance.h b/chromium/content/public/browser/site_instance.h
index 6cf9217fdeb..1ab1b5c3c03 100644
--- a/chromium/content/public/browser/site_instance.h
+++ b/chromium/content/public/browser/site_instance.h
@@ -104,13 +104,9 @@ class CONTENT_EXPORT SiteInstance : public base::RefCounted<SiteInstance> {
// Gets a SiteInstance for the given URL that shares the current
// BrowsingInstance, creating a new SiteInstance if necessary. This ensures
// that a BrowsingInstance only has one SiteInstance per site, so that pages
- // in a BrowsingInstance have the ability to script each other. Callers
- // should ensure that this SiteInstance becomes ref counted, by storing it in
- // a scoped_refptr. (By having this method, we can hide the BrowsingInstance
- // class from the rest of the codebase.)
- // TODO(creis): This may be an argument to build a pass_refptr<T> class, as
- // Darin suggests.
- virtual SiteInstance* GetRelatedSiteInstance(const GURL& url) = 0;
+ // in a BrowsingInstance have the ability to script each other.
+ virtual scoped_refptr<SiteInstance> GetRelatedSiteInstance(
+ const GURL& url) = 0;
// Returns whether the given SiteInstance is in the same BrowsingInstance as
// this one. If so, JavaScript interactions that are permitted across
@@ -127,22 +123,20 @@ class CONTENT_EXPORT SiteInstance : public base::RefCounted<SiteInstance> {
// Factory method to create a new SiteInstance. This will create a new
// new BrowsingInstance, so it should only be used when creating a new tab
- // from scratch (or similar circumstances). Callers should ensure that
- // this SiteInstance becomes ref counted, by storing it in a scoped_refptr.
+ // from scratch (or similar circumstances).
//
// The render process host factory may be nullptr. See SiteInstance
// constructor.
- //
- // TODO(creis): This may be an argument to build a pass_refptr<T> class, as
- // Darin suggests.
- static SiteInstance* Create(content::BrowserContext* browser_context);
+ static scoped_refptr<SiteInstance> Create(
+ content::BrowserContext* browser_context);
// Factory method to get the appropriate SiteInstance for the given URL, in
// a new BrowsingInstance. Use this instead of Create when you know the URL,
// since it allows special site grouping rules to be applied (for example,
// to group chrome-ui pages into the same instance).
- static SiteInstance* CreateForURL(
- content::BrowserContext* browser_context, const GURL& url);
+ static scoped_refptr<SiteInstance> CreateForURL(
+ content::BrowserContext* browser_context,
+ const GURL& url);
// Return whether both URLs are part of the same web site, for the purpose of
// assigning them to processes accordingly. The decision is currently based
diff --git a/chromium/content/public/browser/speech_recognition_session_config.cc b/chromium/content/public/browser/speech_recognition_session_config.cc
index 7bfdf5ab612..74392a16a9e 100644
--- a/chromium/content/public/browser/speech_recognition_session_config.cc
+++ b/chromium/content/public/browser/speech_recognition_session_config.cc
@@ -18,6 +18,9 @@ SpeechRecognitionSessionConfig::SpeechRecognitionSessionConfig()
max_hypotheses(kDefaultMaxHypotheses) {
}
+SpeechRecognitionSessionConfig::SpeechRecognitionSessionConfig(
+ const SpeechRecognitionSessionConfig& other) = default;
+
SpeechRecognitionSessionConfig::~SpeechRecognitionSessionConfig() {
}
diff --git a/chromium/content/public/browser/speech_recognition_session_config.h b/chromium/content/public/browser/speech_recognition_session_config.h
index 964f94fdbc0..da2b011a406 100644
--- a/chromium/content/public/browser/speech_recognition_session_config.h
+++ b/chromium/content/public/browser/speech_recognition_session_config.h
@@ -24,6 +24,7 @@ class SpeechRecognitionEventListener;
// Configuration params for creating a new speech recognition session.
struct CONTENT_EXPORT SpeechRecognitionSessionConfig {
SpeechRecognitionSessionConfig();
+ SpeechRecognitionSessionConfig(const SpeechRecognitionSessionConfig& other);
~SpeechRecognitionSessionConfig();
// TODO(hans): The legacy API is dead; remove this flag (crbug.com/223198).
diff --git a/chromium/content/public/browser/speech_recognition_session_context.cc b/chromium/content/public/browser/speech_recognition_session_context.cc
index b185be8f6c3..1e4ae1cfed5 100644
--- a/chromium/content/public/browser/speech_recognition_session_context.cc
+++ b/chromium/content/public/browser/speech_recognition_session_context.cc
@@ -18,6 +18,9 @@ SpeechRecognitionSessionContext::SpeechRecognitionSessionContext()
request_id(0) {
}
+SpeechRecognitionSessionContext::SpeechRecognitionSessionContext(
+ const SpeechRecognitionSessionContext& other) = default;
+
SpeechRecognitionSessionContext::~SpeechRecognitionSessionContext() {
}
diff --git a/chromium/content/public/browser/speech_recognition_session_context.h b/chromium/content/public/browser/speech_recognition_session_context.h
index 94931894e68..d868c9d48f8 100644
--- a/chromium/content/public/browser/speech_recognition_session_context.h
+++ b/chromium/content/public/browser/speech_recognition_session_context.h
@@ -22,6 +22,7 @@ namespace content {
// SpeechRecognitionManager::LookupSessionByContext methods).
struct CONTENT_EXPORT SpeechRecognitionSessionContext {
SpeechRecognitionSessionContext();
+ SpeechRecognitionSessionContext(const SpeechRecognitionSessionContext& other);
~SpeechRecognitionSessionContext();
int render_process_id;
diff --git a/chromium/content/public/browser/storage_partition.h b/chromium/content/public/browser/storage_partition.h
index b749378b1b8..5c4f7072b62 100644
--- a/chromium/content/public/browser/storage_partition.h
+++ b/chromium/content/public/browser/storage_partition.h
@@ -48,7 +48,6 @@ class GeofencingManager;
class HostZoomLevelContext;
class HostZoomMap;
class IndexedDBContext;
-class NavigatorConnectContext;
class PlatformNotificationContext;
class ServiceWorkerContext;
class ZoomLevelDelegate;
@@ -76,7 +75,6 @@ class CONTENT_EXPORT StoragePartition {
virtual HostZoomMap* GetHostZoomMap() = 0;
virtual HostZoomLevelContext* GetHostZoomLevelContext() = 0;
virtual ZoomLevelDelegate* GetZoomLevelDelegate() = 0;
- virtual NavigatorConnectContext* GetNavigatorConnectContext() = 0;
virtual PlatformNotificationContext* GetPlatformNotificationContext() = 0;
virtual BackgroundSyncContext* GetBackgroundSyncContext() = 0;
diff --git a/chromium/content/public/browser/tracing_controller.h b/chromium/content/public/browser/tracing_controller.h
index c91037716da..64bf8ceed09 100644
--- a/chromium/content/public/browser/tracing_controller.h
+++ b/chromium/content/public/browser/tracing_controller.h
@@ -30,9 +30,9 @@ class TracingController {
CONTENT_EXPORT static TracingController* GetInstance();
- // An interface for trace data consumer. An implemnentation of this interface
- // is passed to either DisableTracing() or CaptureMonitoringSnapshot() and
- // receives the trace data followed by a notification that all child processes
+ // An interface for trace data consumer. An implementation of this interface
+ // is passed to DisableTracing() and receives the trace data
+ // followed by a notification that all child processes
// have completed tracing and the data collection is over.
// All methods are called on the UI thread.
// Close method will be called exactly once and no methods will be
@@ -90,8 +90,8 @@ class TracingController {
virtual ~TraceDataEndpoint() {}
};
- // Create a trace sink that may be supplied to StopTracing or
- // CaptureMonitoringSnapshot to capture the trace data as a string.
+ // Create a trace sink that may be supplied to StopTracing
+ // to capture the trace data as a string.
CONTENT_EXPORT static scoped_refptr<TraceDataSink> CreateStringSink(
const base::Callback<void(scoped_ptr<const base::DictionaryValue>,
base::RefCountedString*)>& callback);
@@ -99,8 +99,8 @@ class TracingController {
CONTENT_EXPORT static scoped_refptr<TraceDataSink> CreateCompressedStringSink(
scoped_refptr<TraceDataEndpoint> endpoint);
- // Create a trace sink that may be supplied to StopTracing or
- // CaptureMonitoringSnapshot to dump the trace data to a file.
+ // Create a trace sink that may be supplied to StopTracing
+ // to dump the trace data to a file.
CONTENT_EXPORT static scoped_refptr<TraceDataSink> CreateFileSink(
const base::FilePath& file_path,
const base::Closure& callback);
@@ -170,54 +170,6 @@ class TracingController {
virtual bool StopTracing(
const scoped_refptr<TraceDataSink>& trace_data_sink) = 0;
- // Start monitoring on all processes.
- //
- // Monitoring begins immediately locally, and asynchronously on child
- // processes as soon as they receive the StartMonitoring request.
- //
- // Once all child processes have acked to the StartMonitoring request,
- // StartMonitoringDoneCallback will be called back.
- //
- // |category_filter| is a filter to control what category groups should be
- // traced.
- //
- // |trace_config| controls what kind of tracing is enabled.
- typedef base::Callback<void()> StartMonitoringDoneCallback;
- virtual bool StartMonitoring(
- const base::trace_event::TraceConfig& trace_config,
- const StartMonitoringDoneCallback& callback) = 0;
-
- // Stop monitoring on all processes.
- //
- // Once all child processes have acked to the StopMonitoring request,
- // StopMonitoringDoneCallback is called back.
- typedef base::Callback<void()> StopMonitoringDoneCallback;
- virtual bool StopMonitoring(
- const StopMonitoringDoneCallback& callback) = 0;
-
- // Get the current monitoring configuration.
- virtual void GetMonitoringStatus(
- bool* out_enabled,
- base::trace_event::TraceConfig* out_trace_config) = 0;
-
- // Get the current monitoring traced data.
- //
- // Child processes typically are caching trace data and only rarely flush
- // and send trace data back to the browser process. That is because it may be
- // an expensive operation to send the trace data over IPC, and we would like
- // to avoid much runtime overhead of tracing. So, to end tracing, we must
- // asynchronously ask all child processes to flush any pending trace data.
- //
- // Once all child processes have acked to the CaptureMonitoringSnapshot
- // request, TracingFileResultCallback will be called back with a file that
- // contains the traced data.
- //
- // If |trace_data_sink| is not null, it will receive chunks of trace data
- // as a comma-separated sequences of JSON-stringified events, followed by
- // a notification that the trace collection is finished.
- virtual bool CaptureMonitoringSnapshot(
- const scoped_refptr<TraceDataSink>& trace_data_sink) = 0;
-
// Get the maximum across processes of trace buffer percent full state.
// When the TraceBufferUsage value is determined, the callback is
// called.
diff --git a/chromium/content/public/browser/utility_process_host.h b/chromium/content/public/browser/utility_process_host.h
index 1a903136f26..98cca9b3bbc 100644
--- a/chromium/content/public/browser/utility_process_host.h
+++ b/chromium/content/public/browser/utility_process_host.h
@@ -29,7 +29,7 @@ struct ChildProcessData;
// If you need multiple batches of work to be done in the process, use
// StartBatchMode(), then multiple calls to StartFooBar(p), then finish with
// EndBatchMode().
-// If you need to call Mojo services, use StartMojoMode() to start the child
+// If you need to call Mojo services, use Start() to start the child
// process and GetServiceRegistry() to get the service registry to connect to
// the child's Mojo services.
//
@@ -76,11 +76,10 @@ class UtilityProcessHost : public IPC::Sender {
virtual void SetEnv(const base::EnvironmentMap& env) = 0;
#endif
- // Starts the utility process in Mojo mode.
- virtual bool StartMojoMode() = 0;
+ // Starts the utility process.
+ virtual bool Start() = 0;
- // Returns the ServiceRegistry for this process. Will return nullptr if
- // the process was not started with StartMojoMode().
+ // Returns the ServiceRegistry for this process. Will never return nullptr.
virtual ServiceRegistry* GetServiceRegistry() = 0;
// Set the name of the process to appear in the task manager.
diff --git a/chromium/content/public/browser/web_contents.cc b/chromium/content/public/browser/web_contents.cc
index 1b6d8a68752..69190cfd6d0 100644
--- a/chromium/content/public/browser/web_contents.cc
+++ b/chromium/content/public/browser/web_contents.cc
@@ -3,8 +3,10 @@
// found in the LICENSE file.
#include "content/public/browser/web_contents.h"
-#include "content/public/common/child_process_host.h"
+#include <utility>
+
+#include "content/public/common/child_process_host.h"
#include "ipc/ipc_message.h"
namespace content {
@@ -13,9 +15,9 @@ WebContents::CreateParams::CreateParams(BrowserContext* context)
: CreateParams(context, nullptr) {}
WebContents::CreateParams::CreateParams(BrowserContext* context,
- SiteInstance* site)
+ scoped_refptr<SiteInstance> site)
: browser_context(context),
- site_instance(site),
+ site_instance(std::move(site)),
opener_render_process_id(content::ChildProcessHost::kInvalidUniqueID),
opener_render_frame_id(MSG_ROUTING_NONE),
opener_suppressed(false),
@@ -28,6 +30,8 @@ WebContents::CreateParams::CreateParams(BrowserContext* context,
context(nullptr),
renderer_initiated_creation(false) {}
+WebContents::CreateParams::CreateParams(const CreateParams& other) = default;
+
WebContents::CreateParams::~CreateParams() {
}
diff --git a/chromium/content/public/browser/web_contents.h b/chromium/content/public/browser/web_contents.h
index a96ed1cfc41..7c46c737e62 100644
--- a/chromium/content/public/browser/web_contents.h
+++ b/chromium/content/public/browser/web_contents.h
@@ -20,6 +20,7 @@
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/page_navigator.h"
#include "content/public/browser/save_page_type.h"
+#include "content/public/browser/site_instance.h"
#include "content/public/browser/web_ui.h"
#include "content/public/common/stop_find_action.h"
#include "ipc/ipc_sender.h"
@@ -55,7 +56,6 @@ class RenderFrameHost;
class RenderProcessHost;
class RenderViewHost;
class RenderWidgetHostView;
-class SiteInstance;
class WebContentsDelegate;
struct CustomContextMenuContext;
struct DropData;
@@ -89,15 +89,16 @@ class WebContents : public PageNavigator,
public:
struct CONTENT_EXPORT CreateParams {
explicit CreateParams(BrowserContext* context);
+ CreateParams(const CreateParams& other);
~CreateParams();
- CreateParams(BrowserContext* context, SiteInstance* site);
+ CreateParams(BrowserContext* context, scoped_refptr<SiteInstance> site);
BrowserContext* browser_context;
// Specifying a SiteInstance here is optional. It can be set to avoid an
// extra process swap if the first navigation is expected to require a
// privileged process.
- SiteInstance* site_instance;
+ scoped_refptr<SiteInstance> site_instance;
// The process id of the frame initiating the open.
int opener_render_process_id;
@@ -228,9 +229,12 @@ class WebContents : public PageNavigator,
virtual void ForEachFrame(
const base::Callback<void(RenderFrameHost*)>& on_frame) = 0;
- // Sends the given IPC to all frames in the currently active view and returns
- // the number of sent messages (i.e. the number of processed frames). This is
- // a convenience method instead of calling ForEach.
+ // Returns a vector of all RenderFrameHosts in the currently active view in
+ // breadth-first traversal order.
+ virtual std::vector<RenderFrameHost*> GetAllFrames() = 0;
+
+ // Sends the given IPC to all live frames in this WebContents and returns the
+ // number of sent messages (i.e. the number of processed frames).
virtual int SendToAllFrames(IPC::Message* message) = 0;
// Gets the current RenderViewHost for this tab.
@@ -284,11 +288,6 @@ class WebContents : public PageNavigator,
// both renderer accessibility, and a native browser accessibility tree.
virtual bool IsFullAccessibilityModeForTesting() const = 0;
-#if defined(OS_WIN)
- virtual void SetParentNativeViewAccessible(
- gfx::NativeViewAccessible accessible_parent) = 0;
-#endif
-
virtual const PageImportanceSignals& GetPageImportanceSignals() const = 0;
// Tab navigation state ------------------------------------------------------
@@ -358,12 +357,17 @@ class WebContents : public PageNavigator,
virtual bool IsAudioMuted() const = 0;
virtual void SetAudioMuted(bool mute) = 0;
+ // Indicates whether any frame in the WebContents is connected to a Bluetooth
+ // Device.
+ virtual bool IsConnectedToBluetoothDevice() const = 0;
+
// Indicates whether this tab should be considered crashed. The setter will
// also notify the delegate when the flag is changed.
virtual bool IsCrashed() const = 0;
virtual void SetIsCrashed(base::TerminationStatus status, int error_code) = 0;
virtual base::TerminationStatus GetCrashedStatus() const = 0;
+ virtual int GetCrashedErrorCode() const = 0;
// Whether the tab is in the process of being destroyed.
virtual bool IsBeingDestroyed() const = 0;
@@ -414,7 +418,11 @@ class WebContents : public PageNavigator,
virtual WebContents* Clone() = 0;
// Reloads the focused frame.
- virtual void ReloadFocusedFrame(bool ignore_cache) = 0;
+ virtual void ReloadFocusedFrame(bool bypass_cache) = 0;
+
+ // Reloads all the Lo-Fi images in this WebContents. Ignores the cache and
+ // reloads from the network.
+ virtual void ReloadLoFiImages() = 0;
// Editing commands ----------------------------------------------------------
@@ -676,7 +684,10 @@ class WebContents : public PageNavigator,
virtual void HasManifest(const HasManifestCallback& callback) = 0;
// Requests the renderer to exit fullscreen.
- virtual void ExitFullscreen() = 0;
+ // |will_cause_resize| indicates whether the fullscreen change causes a
+ // view resize. e.g. This will be false when going from tab fullscreen to
+ // browser fullscreen.
+ virtual void ExitFullscreen(bool will_cause_resize) = 0;
// Unblocks requests from renderer for a newly created window. This is
// used in showCreatedWindow() or sometimes later in cases where
@@ -685,18 +696,17 @@ class WebContents : public PageNavigator,
// as soon as they are ready.
virtual void ResumeLoadingCreatedWebContents() = 0;
-#if defined(OS_ANDROID)
// Requests to resume the current media session.
virtual void ResumeMediaSession() = 0;
// Requests to suspend the current media session.
virtual void SuspendMediaSession() = 0;
// Requests to stop the current media session.
virtual void StopMediaSession() = 0;
-#if !defined(USE_AURA)
+
+#if defined(OS_ANDROID)
CONTENT_EXPORT static WebContents* FromJavaWebContents(
jobject jweb_contents_android);
virtual base::android::ScopedJavaLocalRef<jobject> GetJavaWebContents() = 0;
-#endif // !USE_AURA
#elif defined(OS_MACOSX)
// Allowing other views disables optimizations which assume that only a single
// WebContents is present.
diff --git a/chromium/content/public/browser/web_contents_delegate.cc b/chromium/content/public/browser/web_contents_delegate.cc
index 0a1d3f13480..fede9312d4c 100644
--- a/chromium/content/public/browser/web_contents_delegate.cc
+++ b/chromium/content/public/browser/web_contents_delegate.cc
@@ -154,9 +154,8 @@ JavaScriptDialogManager* WebContentsDelegate::GetJavaScriptDialogManager(
}
scoped_ptr<BluetoothChooser> WebContentsDelegate::RunBluetoothChooser(
- WebContents* web_contents,
- const BluetoothChooser::EventHandler& event_handler,
- const GURL& origin) {
+ RenderFrameHost* frame,
+ const BluetoothChooser::EventHandler& event_handler) {
return nullptr;
}
@@ -259,4 +258,8 @@ void WebContentsDelegate::ShowCertificateViewerInDevTools(
int cert_id) {
}
+void WebContentsDelegate::RequestAppBannerFromDevTools(
+ content::WebContents* web_contents) {
+}
+
} // namespace content
diff --git a/chromium/content/public/browser/web_contents_delegate.h b/chromium/content/public/browser/web_contents_delegate.h
index ed46e438dee..074333a1af8 100644
--- a/chromium/content/public/browser/web_contents_delegate.h
+++ b/chromium/content/public/browser/web_contents_delegate.h
@@ -40,6 +40,7 @@ class ColorChooser;
class DownloadItem;
class JavaScriptDialogManager;
class PageState;
+class RenderFrameHost;
class RenderViewHost;
class SessionStorageNamespace;
class WebContents;
@@ -60,11 +61,16 @@ class Rect;
class Size;
}
+namespace url {
+class Origin;
+}
+
namespace blink {
class WebGestureEvent;
}
namespace content {
+class RenderWidgetHost;
struct OpenURLParams;
@@ -352,9 +358,8 @@ class CONTENT_EXPORT WebContentsDelegate {
// Shows a chooser for the user to select a nearby Bluetooth device. The
// observer must live at least as long as the returned chooser object.
virtual scoped_ptr<BluetoothChooser> RunBluetoothChooser(
- WebContents* web_contents,
- const BluetoothChooser::EventHandler& event_handler,
- const GURL& origin);
+ RenderFrameHost* frame,
+ const BluetoothChooser::EventHandler& event_handler);
// Returns true if the delegate will embed a WebContents-owned fullscreen
// render widget. In this case, the delegate may access the widget by calling
@@ -521,7 +526,12 @@ class CONTENT_EXPORT WebContentsDelegate {
// Called when the active render widget is forwarding a RemoteChannel
// compositor proto. This is used in Blimp mode.
- virtual void ForwardCompositorProto(const std::vector<uint8_t>& proto) {}
+ virtual void ForwardCompositorProto(
+ RenderWidgetHost* render_widget_host,
+ const std::vector<uint8_t>& proto) {}
+
+ // Requests the app banner. This method is called from the DevTools.
+ virtual void RequestAppBannerFromDevTools(content::WebContents* web_contents);
protected:
virtual ~WebContentsDelegate();
diff --git a/chromium/content/public/browser/web_contents_observer.h b/chromium/content/public/browser/web_contents_observer.h
index 3d770b73791..a3bc77f1564 100644
--- a/chromium/content/public/browser/web_contents_observer.h
+++ b/chromium/content/public/browser/web_contents_observer.h
@@ -13,6 +13,7 @@
#include "content/common/content_export.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/common/frame_navigate_params.h"
+#include "content/public/common/media_metadata.h"
#include "content/public/common/security_style.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
@@ -27,6 +28,7 @@ class NavigationEntry;
class NavigationHandle;
class RenderFrameHost;
class RenderViewHost;
+class RenderWidgetHost;
class WebContents;
class WebContentsImpl;
struct AXEventNotificationDetails;
@@ -121,13 +123,18 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
virtual void RenderViewHostChanged(RenderViewHost* old_host,
RenderViewHost* new_host) {}
+ // This method is invoked when the process for the current main
+ // RenderFrameHost becomes unresponsive.
+ virtual void OnRendererUnresponsive(RenderWidgetHost* render_widget_host) {}
+
// Navigation related events ------------------------------------------------
// Called when a navigation started in the WebContents. |navigation_handle|
// is unique to a specific navigation. The same |navigation_handle| will be
- // provided on subsequent calls to
- // DidRedirect/FinishNavigation/ReadyToCommitNavigation related to this
- // navigation.
+ // provided on subsequent calls to DidRedirectNavigation, DidFinishNavigation,
+ // and ReadyToCommitNavigation when related to this navigation. Observers
+ // should clear any references to |navigation_handle| in DidFinishNavigation,
+ // just before it is destroyed.
//
// Note that this is fired by navigations in any frame of the WebContents,
// not just the main frame.
@@ -157,7 +164,7 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
// Called when a navigation finished in the WebContents. This happens when a
// navigation is committed, aborted or replaced by a new one. To know if the
- // navigation has committed, use NavigationHandle::HasCommited; use
+ // navigation has committed, use NavigationHandle::HasCommitted; use
// NavigationHandle::IsErrorPage to know if the navigation resulted in an
// error page.
//
@@ -316,22 +323,14 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
// failure methods will also be invoked.
virtual void NavigationStopped() {}
- // This indicates that the next navigation was triggered by a user gesture.
- // TODO(dominickn): remove this method in favor of DidGetUserInteraction,
- // with the appropriate filtering by input event type.
- virtual void DidGetUserGesture() {}
-
// Called when there has been direct user interaction with the WebContents.
// The type argument specifies the kind of interaction. Direct user input
// signalled through this callback includes:
// 1) any mouse down event (blink::WebInputEvent::MouseDown);
- // 2) the start of a mouse wheel scroll (blink::WebInputEvent::MouseWheel);
- // 3) any raw key down event (blink::WebInputEvent::RawKeyDown); and
- // 4) any gesture tap event (blink::WebInputEvent::GestureTapDown).
- // The start of a mouse wheel scroll is heuristically detected: a mouse
- // wheel event fired at least 0.1 seconds after any other wheel event is
- // regarded as the beginning of a scroll. This matches the interval used by
- // the Blink EventHandler to detect the end of scrolls.
+ // 2) the start of a scroll (blink::WebInputEvent::GestureScrollBegin);
+ // 3) any raw key down event (blink::WebInputEvent::RawKeyDown);
+ // 4) any gesture tap event (blink::WebInputEvent::GestureTapDown); and
+ // 5) a browser navigation or reload (blink::WebInputEvent::Undefined).
virtual void DidGetUserInteraction(const blink::WebInputEvent::Type type) {}
// This method is invoked when a RenderViewHost of this WebContents was
@@ -407,7 +406,8 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
// Invoked when the renderer process has toggled the tab into/out of
// fullscreen mode.
- virtual void DidToggleFullscreenModeForTab(bool entered_fullscreen) {}
+ virtual void DidToggleFullscreenModeForTab(bool entered_fullscreen,
+ bool will_cause_resize) {}
// Invoked when an interstitial page is attached or detached.
virtual void DidAttachInterstitialPage() {}
@@ -435,13 +435,14 @@ class CONTENT_EXPORT WebContentsObserver : public IPC::Listener,
// and subsequently within a WebContents. MediaStartedPlaying() will always
// be followed by MediaStoppedPlaying() after player teardown. Observers must
// release all stored copies of |id| when MediaStoppedPlaying() is received.
- using MediaPlayerId = std::pair<RenderFrameHost*, int64_t>;
+ using MediaPlayerId = std::pair<RenderFrameHost*, int>;
virtual void MediaStartedPlaying(const MediaPlayerId& id) {}
virtual void MediaStoppedPlaying(const MediaPlayerId& id) {}
// Invoked when media session has changed its state.
virtual void MediaSessionStateChanged(bool is_controllable,
- bool is_suspended) {}
+ bool is_suspended,
+ const MediaMetadata& metadata) {}
// Invoked when the renderer process changes the page scale factor.
virtual void OnPageScaleFactorChanged(float page_scale_factor) {}
diff --git a/chromium/content/public/browser/web_ui_data_source.h b/chromium/content/public/browser/web_ui_data_source.h
index 2966da39d22..3b174c443f8 100644
--- a/chromium/content/public/browser/web_ui_data_source.h
+++ b/chromium/content/public/browser/web_ui_data_source.h
@@ -72,9 +72,6 @@ class WebUIDataSource {
// Allows a caller to add a filter for URL requests.
virtual void SetRequestFilter(const HandleRequestCallback& callback) = 0;
- // Adds the necessary resources for mojo bindings.
- virtual void AddMojoResources() = 0;
-
// The following map to methods on URLDataSource. See the documentation there.
// NOTE: it's not acceptable to call DisableContentSecurityPolicy for new
// pages, see URLDataSource::ShouldAddContentSecurityPolicy and talk to
diff --git a/chromium/content/public/browser/zygote_handle_linux.h b/chromium/content/public/browser/zygote_handle_linux.h
new file mode 100644
index 00000000000..6419b7475b6
--- /dev/null
+++ b/chromium/content/public/browser/zygote_handle_linux.h
@@ -0,0 +1,24 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_BROWSER_ZYGOTE_HANDLE_LINUX_H_
+#define CONTENT_PUBLIC_BROWSER_ZYGOTE_HANDLE_LINUX_H_
+
+#include "content/common/content_export.h"
+#include "content/public/common/zygote_handle.h"
+
+namespace content {
+
+// Allocates and initializes a zygote process, and returns the
+// ZygoteHandle used to communicate with it.
+CONTENT_EXPORT ZygoteHandle CreateZygote();
+
+// Returns a handle to a global generic zygote object. This function allows the
+// browser to launch and use a single zygote process until the performance
+// issues around launching multiple zygotes are resolved.
+CONTENT_EXPORT ZygoteHandle* GetGenericZygote();
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_BROWSER_ZYGOTE_HANDLE_LINUX_H_
diff --git a/chromium/content/public/browser/zygote_host_linux.h b/chromium/content/public/browser/zygote_host_linux.h
index ebe5ee7387f..537d6d3f763 100644
--- a/chromium/content/public/browser/zygote_host_linux.h
+++ b/chromium/content/public/browser/zygote_host_linux.h
@@ -12,9 +12,9 @@
namespace content {
-// http://code.google.com/p/chromium/wiki/LinuxZygote
+// https://chromium.googlesource.com/chromium/src/+/master/docs/linux_zygote.md
-// The zygote host is the interface, in the browser process, to the zygote
+// The zygote host is an interface, in the browser process, to the zygote
// process.
class ZygoteHost {
public:
@@ -24,11 +24,11 @@ class ZygoteHost {
virtual ~ZygoteHost() {}
// Returns the pid of the Zygote process.
- virtual pid_t GetPid() const = 0;
+ virtual bool IsZygotePid(pid_t pid) = 0;
// Returns an int which is a bitmask of kSandboxLinux* values. Only valid
// after the first render has been forked.
- virtual int GetSandboxStatus() const = 0;
+ virtual int GetRendererSandboxStatus() const = 0;
// Adjust the OOM score of the given renderer's PID. The allowed
// range for the score is [0, 1000], where higher values are more
diff --git a/chromium/content/public/child/BUILD.gn b/chromium/content/public/child/BUILD.gn
index fb5c5bf4334..68c9986910a 100644
--- a/chromium/content/public/child/BUILD.gn
+++ b/chromium/content/public/child/BUILD.gn
@@ -24,6 +24,7 @@ group("child") {
}
source_set("child_sources") {
+ # External code should depend in via ":child" above.
visibility = [ "//content/*" ]
sources = rebase_path(content_child_gypi_values.public_child_sources,
@@ -38,5 +39,6 @@ source_set("child_sources") {
deps = [
"//content/public/common:common_sources",
+ "//gin",
]
}
diff --git a/chromium/content/public/child/child_thread.h b/chromium/content/public/child/child_thread.h
index 6afc0cba319..94eb3212a03 100644
--- a/chromium/content/public/child/child_thread.h
+++ b/chromium/content/public/child/child_thread.h
@@ -5,6 +5,9 @@
#ifndef CONTENT_PUBLIC_CHILD_CHILD_THREAD_H_
#define CONTENT_PUBLIC_CHILD_CHILD_THREAD_H_
+#include <string>
+
+#include "base/logging.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
#include "ipc/ipc_sender.h"
@@ -13,6 +16,10 @@
#include <windows.h>
#endif
+namespace base {
+struct UserMetricsAction;
+}
+
namespace content {
// An abstract base class that contains logic shared between most child
@@ -33,6 +40,25 @@ class CONTENT_EXPORT ChildThread : public IPC::Sender {
// Release cached font.
virtual void ReleaseCachedFonts() = 0;
#endif
+
+ // Sends over a base::UserMetricsAction to be recorded by user metrics as
+ // an action. Once a new user metric is added, run
+ // tools/metrics/actions/extract_actions.py
+ // to add the metric to actions.xml, then update the <owner>s and
+ // <description> sections. Make sure to include the actions.xml file when you
+ // upload your code for review!
+ //
+ // WARNING: When using base::UserMetricsAction, base::UserMetricsAction
+ // and a string literal parameter must be on the same line, e.g.
+ // RenderThread::Get()->RecordAction(
+ // base::UserMetricsAction("my extremely long action name"));
+ // because otherwise our processing scripts won't pick up on new actions.
+ virtual void RecordAction(const base::UserMetricsAction& action) = 0;
+
+ // Sends over a string to be recorded by user metrics as a computed action.
+ // When you use this you need to also update the rules for extracting known
+ // actions in chrome/tools/extract_actions.py.
+ virtual void RecordComputedAction(const std::string& action) = 0;
};
} // namespace content
diff --git a/chromium/content/public/child/request_peer.h b/chromium/content/public/child/request_peer.h
index c12c19e717d..cda0c71fc20 100644
--- a/chromium/content/public/child/request_peer.h
+++ b/chromium/content/public/child/request_peer.h
@@ -97,27 +97,6 @@ class CONTENT_EXPORT RequestPeer {
const base::TimeTicks& completion_time,
int64_t total_transfer_size) = 0;
- // This is a combined notification of
- // - OnReceivedResponse,
- // - OnReceivedData and
- // - OnCompletedRequest.
- // Unlike OnReceivedData, |data| can be null.
- // This method is introduced to avoid repetitive method calls which might
- // lead to use-after-free issues. See https://crbug.com/485413,
- // https://crbug.com/507170.
- // TODO(yhirano): Fix the RequestPeer lifecycle problem and remove this
- // function.
- virtual void OnReceivedCompletedResponse(
- const ResourceResponseInfo& info,
- scoped_ptr<ReceivedData> data,
- int error_code,
- bool was_ignored_by_handler,
- bool stale_copy_in_cache,
- const std::string& security_info,
- const base::TimeTicks& completion_time,
- int64_t total_transfer_size) = 0;
-
- protected:
virtual ~RequestPeer() {}
};
diff --git a/chromium/content/public/child/resource_dispatcher_delegate.h b/chromium/content/public/child/resource_dispatcher_delegate.h
index 6a5da1c0136..e6ac4134386 100644
--- a/chromium/content/public/child/resource_dispatcher_delegate.h
+++ b/chromium/content/public/child/resource_dispatcher_delegate.h
@@ -16,19 +16,23 @@ namespace content {
class RequestPeer;
-// Interface that allows observing request events and optionally replacing the
-// peer.
+// Interface that allows observing request events and optionally replacing
+// the peer. Note that if it doesn't replace the peer it must return the
+// current peer so that the ownership is continued to be held by
+// ResourceDispatcher.
class CONTENT_EXPORT ResourceDispatcherDelegate {
public:
virtual ~ResourceDispatcherDelegate() {}
- virtual RequestPeer* OnRequestComplete(RequestPeer* current_peer,
- ResourceType resource_type,
- int error_code) = 0;
+ virtual scoped_ptr<RequestPeer> OnRequestComplete(
+ scoped_ptr<RequestPeer> current_peer,
+ ResourceType resource_type,
+ int error_code) = 0;
- virtual RequestPeer* OnReceivedResponse(RequestPeer* current_peer,
- const std::string& mime_type,
- const GURL& url) = 0;
+ virtual scoped_ptr<RequestPeer> OnReceivedResponse(
+ scoped_ptr<RequestPeer> current_peer,
+ const std::string& mime_type,
+ const GURL& url) = 0;
};
} // namespace content
diff --git a/chromium/content/public/common/BUILD.gn b/chromium/content/public/common/BUILD.gn
index b8a7cd1f699..40c08f1cb02 100644
--- a/chromium/content/public/common/BUILD.gn
+++ b/chromium/content/public/common/BUILD.gn
@@ -2,10 +2,12 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build/buildflag_header.gni")
import("//build/config/chromecast_build.gni")
import("//build/config/features.gni")
import("//content/common/common.gni")
import("//mojo/public/tools/bindings/mojom.gni")
+import("//third_party/webrtc/build/webrtc.gni")
# See //content/BUILD.gn for how this works.
group("common") {
@@ -34,7 +36,13 @@ source_set("content_descriptors") {
sources = [
"content_descriptors.h",
]
+
+ # The header uses V8_USE_EXTERNAL_STARTUP_DATA.
public_configs = [ "//v8:external_startup_data" ]
+
+ deps = [
+ "//ipc",
+ ]
}
# Forces static linking for targets using the static_switches constants, even
@@ -70,6 +78,7 @@ source_set("static_switches") {
}
source_set("common_sources") {
+ # External code should depend on via ":common" above.
visibility = [ "//content/*" ]
sources = rebase_path(content_common_gypi_values.public_common_sources,
@@ -86,16 +95,31 @@ source_set("common_sources") {
public_deps = [
"//content/common",
"//mojo/public/cpp/bindings",
+ "//ui/accessibility",
+ "//url/ipc:url_ipc",
]
deps = [
+ "//ipc",
+ "//ipc/mojo",
+ "//media",
+ "//mojo/common",
"//net",
+ "//ppapi/c",
"//skia",
+ "//storage/common",
"//third_party/WebKit/public:blink_headers",
"//third_party/icu",
+ "//ui/accessibility",
"//ui/base",
"//ui/gfx",
+ "//ui/gfx/ipc",
+ "//ui/gfx/ipc/skia",
+ "//ui/surface",
]
+ # //content/common needs to include public headers.
+ allow_circular_includes_from = [ "//content/common" ]
+
if (!enable_plugins) {
sources -= [
"pepper_plugin_info.cc",
@@ -114,8 +138,23 @@ source_set("common_sources") {
mojom("mojo_bindings") {
sources = [
"background_sync.mojom",
- "mojo_geoposition.mojom",
- "permission_status.mojom",
"service_worker_event_status.mojom",
]
}
+
+buildflag_header("features") {
+ header = "features.h"
+
+ flags = [ "RTC_USE_H264=$rtc_use_h264" ]
+}
+
+source_set("feature_h264_with_openh264_ffmpeg") {
+ deps = [
+ ":features",
+ "//base",
+ ]
+ sources = [
+ "feature_h264_with_openh264_ffmpeg.cc",
+ "feature_h264_with_openh264_ffmpeg.h",
+ ]
+}
diff --git a/chromium/content/public/common/appcache_info.h b/chromium/content/public/common/appcache_info.h
index 75b5499502b..a8f186db097 100644
--- a/chromium/content/public/common/appcache_info.h
+++ b/chromium/content/public/common/appcache_info.h
@@ -32,6 +32,7 @@ enum AppCacheStatus {
struct CONTENT_EXPORT AppCacheInfo {
AppCacheInfo();
+ AppCacheInfo(const AppCacheInfo& other);
~AppCacheInfo();
GURL manifest_url;
diff --git a/chromium/content/public/common/background_sync.mojom b/chromium/content/public/common/background_sync.mojom
index 6b5b95dd216..fedaf9b3274 100644
--- a/chromium/content/public/common/background_sync.mojom
+++ b/chromium/content/public/common/background_sync.mojom
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-module content;
+module content.mojom;
enum BackgroundSyncNetworkState {
ANY,
@@ -11,23 +11,8 @@ enum BackgroundSyncNetworkState {
MAX=ONLINE
};
-enum BackgroundSyncPowerState {
- AUTO,
- AVOID_DRAINING,
- MAX=AVOID_DRAINING
-};
-
-enum BackgroundSyncPeriodicity {
- PERIODIC,
- ONE_SHOT,
- MAX=ONE_SHOT
-};
-
struct SyncRegistration {
- int64 handle_id = -1;
- BackgroundSyncPeriodicity periodicity = ONE_SHOT;
+ int64 id = -1;
string tag = "";
- uint64 min_period_ms = 0;
BackgroundSyncNetworkState network_state = ONLINE;
- BackgroundSyncPowerState power_state = AUTO;
};
diff --git a/chromium/content/public/common/bindings_policy.h b/chromium/content/public/common/bindings_policy.h
index 9a4745c4295..ee3b0e87efd 100644
--- a/chromium/content/public/common/bindings_policy.h
+++ b/chromium/content/public/common/bindings_policy.h
@@ -22,6 +22,16 @@ enum BindingsPolicy {
// metrics. (By default this isn't allowed unless the app has been started up
// with the --enable-stats-collection-bindings switch.)
BINDINGS_POLICY_STATS_COLLECTION = 1 << 2,
+ // Bindings that allows the JS content to access Mojo system API and
+ // ServiceRegistry modules. The system API modules are defined in
+ // //mojo/public/js and provide the ability to create Mojo primitives such as
+ // message and data pipes. The ServiceRegistry module (see
+ // //content/renderer/mojo/service_registry_js_wrapper.h) in turn allows these
+ // Mojo primitives to be used to connect to named services exposed either by
+ // the browser or testing code. These bindings should not be exposed to
+ // normal web contents and are intended only for use with WebUI and layout
+ // tests.
+ BINDINGS_POLICY_MOJO = 1 << 3,
};
diff --git a/chromium/content/public/common/common_param_traits.cc b/chromium/content/public/common/common_param_traits.cc
index f953fa33f83..641ac26d0a7 100644
--- a/chromium/content/public/common/common_param_traits.cc
+++ b/chromium/content/public/common/common_param_traits.cc
@@ -15,55 +15,14 @@
namespace IPC {
-void ParamTraits<GURL>::Write(Message* m, const GURL& p) {
- if (p.possibly_invalid_spec().length() > content::kMaxURLChars) {
- m->WriteString(std::string());
- return;
- }
-
- // Beware of print-parse inconsistency which would change an invalid
- // URL into a valid one. Ideally, the message would contain this flag
- // so that the read side could make the check, but performing it here
- // avoids changing the on-the-wire representation of such a fundamental
- // type as GURL. See https://crbug.com/166486 for additional work in
- // this area.
- if (!p.is_valid()) {
- m->WriteString(std::string());
- return;
- }
-
- m->WriteString(p.possibly_invalid_spec());
- // TODO(brettw) bug 684583: Add encoding for query params.
-}
-
-bool ParamTraits<GURL>::Read(const Message* m,
- base::PickleIterator* iter,
- GURL* p) {
- std::string s;
- if (!iter->ReadString(&s) || s.length() > content::kMaxURLChars) {
- *p = GURL();
- return false;
- }
- *p = GURL(s);
- if (!s.empty() && !p->is_valid()) {
- *p = GURL();
- return false;
- }
- return true;
-}
-
-void ParamTraits<GURL>::Log(const GURL& p, std::string* l) {
- l->append(p.spec());
-}
-
-void ParamTraits<url::Origin>::Write(Message* m, const url::Origin& p) {
+void ParamTraits<url::Origin>::Write(base::Pickle* m, const url::Origin& p) {
WriteParam(m, p.unique());
WriteParam(m, p.scheme());
WriteParam(m, p.host());
WriteParam(m, p.port());
}
-bool ParamTraits<url::Origin>::Read(const Message* m,
+bool ParamTraits<url::Origin>::Read(const base::Pickle* m,
base::PickleIterator* iter,
url::Origin* p) {
bool unique;
@@ -93,12 +52,13 @@ void ParamTraits<url::Origin>::Log(const url::Origin& p, std::string* l) {
l->append(p.Serialize());
}
-void ParamTraits<net::HostPortPair>::Write(Message* m, const param_type& p) {
+void ParamTraits<net::HostPortPair>::Write(base::Pickle* m,
+ const param_type& p) {
WriteParam(m, p.host());
WriteParam(m, p.port());
}
-bool ParamTraits<net::HostPortPair>::Read(const Message* m,
+bool ParamTraits<net::HostPortPair>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
std::string host;
@@ -115,23 +75,21 @@ void ParamTraits<net::HostPortPair>::Log(const param_type& p, std::string* l) {
l->append(p.ToString());
}
-void ParamTraits<net::IPEndPoint>::Write(Message* m, const param_type& p) {
+void ParamTraits<net::IPEndPoint>::Write(base::Pickle* m, const param_type& p) {
WriteParam(m, p.address());
WriteParam(m, p.port());
}
-bool ParamTraits<net::IPEndPoint>::Read(const Message* m,
+bool ParamTraits<net::IPEndPoint>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* p) {
- net::IPAddressNumber address;
+ net::IPAddress address;
uint16_t port;
if (!ReadParam(m, iter, &address) || !ReadParam(m, iter, &port))
return false;
- if (address.size() &&
- address.size() != net::kIPv4AddressSize &&
- address.size() != net::kIPv6AddressSize) {
+ if (!address.empty() && !address.IsValid())
return false;
- }
+
*p = net::IPEndPoint(address, port);
return true;
}
@@ -140,11 +98,11 @@ void ParamTraits<net::IPEndPoint>::Log(const param_type& p, std::string* l) {
LogParam("IPEndPoint:" + p.ToString(), l);
}
-void ParamTraits<net::IPAddress>::Write(Message* m, const param_type& p) {
+void ParamTraits<net::IPAddress>::Write(base::Pickle* m, const param_type& p) {
WriteParam(m, p.bytes());
}
-bool ParamTraits<net::IPAddress>::Read(const Message* m,
+bool ParamTraits<net::IPAddress>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* p) {
std::vector<uint8_t> bytes;
@@ -163,12 +121,12 @@ void ParamTraits<net::IPAddress>::Log(const param_type& p, std::string* l) {
LogParam("IPAddress:" + (p.empty() ? "(empty)" : p.ToString()), l);
}
-void ParamTraits<content::PageState>::Write(
- Message* m, const param_type& p) {
+void ParamTraits<content::PageState>::Write(base::Pickle* m,
+ const param_type& p) {
WriteParam(m, p.ToEncodedData());
}
-bool ParamTraits<content::PageState>::Read(const Message* m,
+bool ParamTraits<content::PageState>::Read(const base::Pickle* m,
base::PickleIterator* iter,
param_type* r) {
std::string data;
diff --git a/chromium/content/public/common/common_param_traits.h b/chromium/content/public/common/common_param_traits.h
index e3f5142a1d4..4e7610cdc04 100644
--- a/chromium/content/public/common/common_param_traits.h
+++ b/chromium/content/public/common/common_param_traits.h
@@ -25,7 +25,7 @@
#include "ipc/ipc_message_utils.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/surface/transport_dib.h"
-#include "url/gurl.h"
+#include "url/ipc/url_param_traits.h"
#include "url/origin.h"
#if defined(OS_WIN)
@@ -45,64 +45,67 @@ class IPEndPoint;
namespace IPC {
template <>
-struct CONTENT_EXPORT ParamTraits<GURL> {
- typedef GURL param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* p);
- static void Log(const param_type& p, std::string* l);
-};
-
-template <>
struct CONTENT_EXPORT ParamTraits<url::Origin> {
typedef url::Origin param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* p);
static void Log(const param_type& p, std::string* l);
};
template<>
struct CONTENT_EXPORT ParamTraits<net::HostPortPair> {
typedef net::HostPortPair param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* r);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* r);
static void Log(const param_type& p, std::string* l);
};
template <>
struct CONTENT_EXPORT ParamTraits<net::IPEndPoint> {
typedef net::IPEndPoint param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* p);
static void Log(const param_type& p, std::string* l);
};
template <>
struct CONTENT_EXPORT ParamTraits<net::IPAddress> {
typedef net::IPAddress param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* p);
static void Log(const param_type& p, std::string* l);
};
template <>
struct CONTENT_EXPORT ParamTraits<content::PageState> {
typedef content::PageState param_type;
- static void Write(Message* m, const param_type& p);
- static bool Read(const Message* m, base::PickleIterator* iter, param_type* p);
+ static void Write(base::Pickle* m, const param_type& p);
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
+ param_type* p);
static void Log(const param_type& p, std::string* l);
};
template <>
struct ParamTraits<gfx::NativeWindow> {
typedef gfx::NativeWindow param_type;
- static void Write(Message* m, const param_type& p) {
+ static void Write(base::Pickle* m, const param_type& p) {
#if defined(OS_WIN)
m->WriteUInt32(base::win::HandleToUint32(p));
#else
m->WriteData(reinterpret_cast<const char*>(&p), sizeof(p));
#endif
}
- static bool Read(const Message* m, base::PickleIterator* iter,
+ static bool Read(const base::Pickle* m,
+ base::PickleIterator* iter,
param_type* r) {
#if defined(OS_WIN)
return iter->ReadUInt32(reinterpret_cast<uint32_t*>(r));
diff --git a/chromium/content/public/common/common_param_traits_macros.h b/chromium/content/public/common/common_param_traits_macros.h
index a1917f553fb..ae29c732a2c 100644
--- a/chromium/content/public/common/common_param_traits_macros.h
+++ b/chromium/content/public/common/common_param_traits_macros.h
@@ -28,6 +28,7 @@
#include "ui/base/page_transition_types.h"
#include "ui/base/window_open_disposition.h"
#include "ui/gfx/ipc/gfx_param_traits.h"
+#include "ui/gfx/ipc/skia/gfx_skia_param_traits.h"
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
@@ -142,16 +143,15 @@ IPC_STRUCT_TRAITS_BEGIN(content::WebPreferences)
IPC_STRUCT_TRAITS_MEMBER(hyperlink_auditing_enabled)
IPC_STRUCT_TRAITS_MEMBER(allow_universal_access_from_file_urls)
IPC_STRUCT_TRAITS_MEMBER(allow_file_access_from_file_urls)
- IPC_STRUCT_TRAITS_MEMBER(webaudio_enabled)
IPC_STRUCT_TRAITS_MEMBER(experimental_webgl_enabled)
IPC_STRUCT_TRAITS_MEMBER(pepper_3d_enabled)
IPC_STRUCT_TRAITS_MEMBER(inert_visual_viewport)
+ IPC_STRUCT_TRAITS_MEMBER(record_whole_document)
IPC_STRUCT_TRAITS_MEMBER(pinch_overlay_scrollbar_thickness)
IPC_STRUCT_TRAITS_MEMBER(use_solid_color_scrollbars)
IPC_STRUCT_TRAITS_MEMBER(flash_3d_enabled)
IPC_STRUCT_TRAITS_MEMBER(flash_stage3d_enabled)
IPC_STRUCT_TRAITS_MEMBER(flash_stage3d_baseline_enabled)
- IPC_STRUCT_TRAITS_MEMBER(gl_multisampling_enabled)
IPC_STRUCT_TRAITS_MEMBER(privileged_webgl_extensions_enabled)
IPC_STRUCT_TRAITS_MEMBER(webgl_errors_to_console_enabled)
IPC_STRUCT_TRAITS_MEMBER(mock_scrollbars_enabled)
@@ -170,6 +170,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::WebPreferences)
IPC_STRUCT_TRAITS_MEMBER(disable_reading_from_canvas)
IPC_STRUCT_TRAITS_MEMBER(strict_mixed_content_checking)
IPC_STRUCT_TRAITS_MEMBER(strict_powerful_feature_restrictions)
+ IPC_STRUCT_TRAITS_MEMBER(allow_geolocation_on_insecure_origins)
IPC_STRUCT_TRAITS_MEMBER(strictly_block_blockable_mixed_content)
IPC_STRUCT_TRAITS_MEMBER(block_mixed_plugin_content)
IPC_STRUCT_TRAITS_MEMBER(enable_scroll_animator)
@@ -201,6 +202,8 @@ IPC_STRUCT_TRAITS_BEGIN(content::WebPreferences)
IPC_STRUCT_TRAITS_MEMBER(v8_cache_options)
IPC_STRUCT_TRAITS_MEMBER(pepper_accelerated_video_decode_enabled)
IPC_STRUCT_TRAITS_MEMBER(animation_policy)
+ IPC_STRUCT_TRAITS_MEMBER(user_gesture_required_for_presentation)
+ IPC_STRUCT_TRAITS_MEMBER(text_track_margin_percentage)
#if defined(OS_ANDROID)
IPC_STRUCT_TRAITS_MEMBER(text_autosizing_enabled)
IPC_STRUCT_TRAITS_MEMBER(font_scale_factor)
@@ -222,7 +225,7 @@ IPC_STRUCT_TRAITS_BEGIN(content::WebPreferences)
IPC_STRUCT_TRAITS_MEMBER(clobber_user_agent_initial_scale_quirk)
IPC_STRUCT_TRAITS_MEMBER(ignore_main_frame_overflow_hidden_quirk)
IPC_STRUCT_TRAITS_MEMBER(report_screen_size_in_physical_pixels_quirk)
- IPC_STRUCT_TRAITS_MEMBER(record_whole_document)
+ IPC_STRUCT_TRAITS_MEMBER(resue_global_for_unowned_main_frame)
IPC_STRUCT_TRAITS_MEMBER(autoplay_experiment_mode)
#endif
IPC_STRUCT_TRAITS_MEMBER(default_minimum_page_scale_factor)
diff --git a/chromium/content/public/common/content_client.cc b/chromium/content/public/common/content_client.cc
index e7f50c8df98..0c6a8b2afd0 100644
--- a/chromium/content/public/common/content_client.cc
+++ b/chromium/content/public/common/content_client.cc
@@ -62,8 +62,10 @@ ContentUtilityClient* SetUtilityClientForTesting(ContentUtilityClient* u) {
}
ContentClient::ContentClient()
- : browser_(NULL), plugin_(NULL), renderer_(NULL), utility_(NULL) {
-}
+ : browser_(NULL),
+ gpu_(NULL),
+ renderer_(NULL),
+ utility_(NULL) {}
ContentClient::~ContentClient() {
}
@@ -105,7 +107,7 @@ std::string ContentClient::GetProcessTypeNameInEnglish(int type) {
return std::string();
}
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MACOSX)
bool ContentClient::GetSandboxProfileForSandboxType(
int sandbox_type,
int* sandbox_profile_resource_id) const {
@@ -117,4 +119,14 @@ bool ContentClient::IsSupplementarySiteIsolationModeEnabled() {
return false;
}
+base::StringPiece ContentClient::GetOriginTrialPublicKey() {
+ return base::StringPiece();
+}
+
+#if defined(OS_ANDROID)
+media::MediaClientAndroid* ContentClient::GetMediaClientAndroid() {
+ return nullptr;
+}
+#endif // OS_ANDROID
+
} // namespace content
diff --git a/chromium/content/public/common/content_client.h b/chromium/content/public/common/content_client.h
index 9d51d5ba83d..46f932a22b2 100644
--- a/chromium/content/public/common/content_client.h
+++ b/chromium/content/public/common/content_client.h
@@ -34,6 +34,10 @@ namespace gpu {
struct GPUInfo;
}
+namespace media {
+class MediaClientAndroid;
+}
+
namespace sandbox {
class TargetPolicy;
}
@@ -42,7 +46,7 @@ namespace content {
class ContentBrowserClient;
class ContentClient;
-class ContentPluginClient;
+class ContentGpuClient;
class ContentRendererClient;
class ContentUtilityClient;
struct PepperPluginInfo;
@@ -72,7 +76,7 @@ class CONTENT_EXPORT ContentClient {
virtual ~ContentClient();
ContentBrowserClient* browser() { return browser_; }
- ContentPluginClient* plugin() { return plugin_; }
+ ContentGpuClient* gpu() { return gpu_; }
ContentRendererClient* renderer() { return renderer_; }
ContentUtilityClient* utility() { return utility_; }
@@ -86,10 +90,11 @@ class CONTENT_EXPORT ContentClient {
virtual void AddPepperPlugins(
std::vector<content::PepperPluginInfo>* plugins) {}
- // Gives the embedder a chance to register its own standard and saveable
- // url schemes early on in the startup sequence.
+ // Gives the embedder a chance to register its own standard, referrer and
+ // saveable url schemes early on in the startup sequence.
virtual void AddAdditionalSchemes(
std::vector<url::SchemeWithType>* standard_schemes,
+ std::vector<url::SchemeWithType>* referrer_schemes,
std::vector<std::string>* savable_schemes) {}
// Returns whether the given message should be sent in a swapped out renderer.
@@ -122,7 +127,7 @@ class CONTENT_EXPORT ContentClient {
// doesn't know about because they're from the embedder.
virtual std::string GetProcessTypeNameInEnglish(int type);
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MACOSX)
// Allows the embedder to define a new |sandbox_type| by mapping it to the
// resource ID corresponding to the sandbox profile to use. The legal values
// for |sandbox_type| are defined by the embedder and should start with
@@ -153,14 +158,23 @@ class CONTENT_EXPORT ContentClient {
// model decisions.
virtual bool IsSupplementarySiteIsolationModeEnabled();
+ // Returns the public key to be used for origin trials, or an empty string if
+ // origin trials are not enabled in this context.
+ virtual base::StringPiece GetOriginTrialPublicKey();
+
+#if defined(OS_ANDROID)
+ // Returns the MediaClientAndroid to be used by media code on Android.
+ virtual media::MediaClientAndroid* GetMediaClientAndroid();
+#endif // OS_ANDROID
+
private:
friend class ContentClientInitializer; // To set these pointers.
friend class InternalTestInitializer;
// The embedder API for participating in browser logic.
ContentBrowserClient* browser_;
- // The embedder API for participating in plugin logic.
- ContentPluginClient* plugin_;
+ // The embedder API for participating in gpu logic.
+ ContentGpuClient* gpu_;
// The embedder API for participating in renderer logic.
ContentRendererClient* renderer_;
// The embedder API for participating in utility logic.
diff --git a/chromium/content/public/common/content_constants.cc b/chromium/content/public/common/content_constants.cc
index 3a97a0903ac..e33743361cb 100644
--- a/chromium/content/public/common/content_constants.cc
+++ b/chromium/content/public/common/content_constants.cc
@@ -26,7 +26,6 @@ const char kSilverlightPluginMimeTypePrefix[] = "application/x-silverlight";
const size_t kMaxRendererProcessCount = 82;
const int kMaxSessionHistoryEntries = 50;
const size_t kMaxTitleChars = 4 * 1024;
-const size_t kMaxURLChars = 2 * 1024 * 1024;
const size_t kMaxURLDisplayChars = 32 * 1024;
#if defined(GOOGLE_CHROME_BUILD)
diff --git a/chromium/content/public/common/content_descriptors.h b/chromium/content/public/common/content_descriptors.h
index 17d160e3098..ff282ae4be2 100644
--- a/chromium/content/public/common/content_descriptors.h
+++ b/chromium/content/public/common/content_descriptors.h
@@ -12,12 +12,20 @@
// base::GlobalDescriptors object (see base/posix/global_descriptors.h)
enum {
kCrashDumpSignal = kIPCDescriptorMax,
- kSandboxIPCChannel, // http://code.google.com/p/chromium/LinuxSandboxIPC
+ kSandboxIPCChannel, // https://chromium.googlesource.com/chromium/src/+/master/docs/linux_sandbox_ipc.md
+ kMojoIPCChannel,
#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
+#if defined(OS_ANDROID)
+ kV8NativesDataDescriptor32,
+ kV8SnapshotDataDescriptor32,
+ kV8NativesDataDescriptor64,
+ kV8SnapshotDataDescriptor64,
+#else
kV8NativesDataDescriptor,
kV8SnapshotDataDescriptor,
#endif
+#endif
#if defined(OS_ANDROID)
kAndroidPropertyDescriptor,
diff --git a/chromium/content/public/common/content_features.cc b/chromium/content/public/common/content_features.cc
index 4329349b165..d904a83099e 100644
--- a/chromium/content/public/common/content_features.cc
+++ b/chromium/content/public/common/content_features.cc
@@ -14,26 +14,88 @@ namespace features {
const base::Feature kBrotliEncoding{"brotli-encoding",
base::FEATURE_DISABLED_BY_DEFAULT};
+// Enables the credential management API:
+// https://w3c.github.io/webappsec-credential-management/
+const base::Feature kCredentialManagementAPI{"CredentialManagementAPI",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
// Downloads resumption will be controllable via a flag until it's enabled
// permanently. See https://crbug.com/7648
const base::Feature kDownloadResumption{"DownloadResumption",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
+// Speculatively pre-evaluate Javascript which will likely use document.write to
+// load an external script. The feature extracts the written markup and sends it
+// to the preload scanner.
+const base::Feature kDocumentWriteEvaluator{"DocumentWriteEvaluator",
+ base::FEATURE_DISABLED_BY_DEFAULT};
// The Experimental Framework for controlling access to API experiments.
const base::Feature kExperimentalFramework{"ExperimentalFramework",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
+// Enable the material design playback UI for media elements. This is always
+// on for OS_ANDROID, but may be enabled by experiment for other platforms.
+const base::Feature kNewMediaPlaybackUi{"NewMediaPlaybackUi",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// FeatureList definition for trials to enable the download button on
+// MediaDocument.
+const base::Feature kMediaDocumentDownloadButton{
+ "MediaDocumentDownloadButton",
+ base::FEATURE_DISABLED_BY_DEFAULT
+};
+
+// Non-validating reload on reload-to-refresh-content (e.g. pull-to-refresh).
+// See https://crbug.com/558829
+const base::Feature kNonValidatingReloadOnRefreshContent{
+ "NonValidatingReloadOnRefreshContent",
+ base::FEATURE_DISABLED_BY_DEFAULT};
-// Control whether the priority of a renderer is set when the process is
-// launched. This is in response to a bug seen on Windows. See
-// https://crbug.com/560446
-const base::Feature kUpdateRendererPriorityOnStartup{
- "UpdateRendererPriorityOnStartup", base::FEATURE_ENABLED_BY_DEFAULT};
+// An experiment to optimize resource loading IPC for small resources.
+// http://crbug.com/580928
+const base::Feature kOptimizeIPCForSmallResource{
+ "OptimizeForSmallResource",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Throttle Blink's rendering pipeline based on frame visibility.
+const base::Feature kRenderingPipelineThrottling{
+ "RenderingPipelineThrottling", base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Scrolls to compensate for layout movements (bit.ly/scroll-anchoring).
+const base::Feature kScrollAnchoring{"ScrollAnchoring",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Enables implementation of the Cache-Control: stale-while-revalidate directive
+// which permits servers to allow the use of stale resources while revalidation
+// proceeds in the background. See http://crbug.com/348877
+const base::Feature kStaleWhileRevalidate{"StaleWhileRevalidate2",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Enables token binding
+// (https://www.ietf.org/id/draft-ietf-tokbind-protocol-04.txt).
+const base::Feature kTokenBinding{"token-binding",
+ base::FEATURE_DISABLED_BY_DEFAULT};
// An experimental User Agent Intervention on WebFonts loading.
const base::Feature kWebFontsIntervention{"WebFontsIntervention",
base::FEATURE_DISABLED_BY_DEFAULT};
+// Makes WebRTC use ECDSA certs by default (i.e., when no cert type was
+// specified in JS).
+const base::Feature kWebRtcEcdsaDefault {"WebRTC-EnableWebRtcEcdsa",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Controls whether the WebUSB API is enabled:
+// https://wicg.github.io/webusb
+const base::Feature kWebUsb{"WebUSB", base::FEATURE_ENABLED_BY_DEFAULT};
+
#if defined(OS_ANDROID)
+// Use IME's own thread instead of using main UI thread. It also means that
+// we will not use replica editor and do a round trip to renderer to synchronize
+// with Blink data.
+const base::Feature kImeThread{"ImeThread", base::FEATURE_DISABLED_BY_DEFAULT};
+
// FeatureList definition for the Seccomp field trial.
const base::Feature kSeccompSandboxAndroid{"SeccompSandboxAndroid",
base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chromium/content/public/common/content_features.h b/chromium/content/public/common/content_features.h
index 77d264f2e59..14205702448 100644
--- a/chromium/content/public/common/content_features.h
+++ b/chromium/content/public/common/content_features.h
@@ -17,12 +17,24 @@ namespace features {
// All features in alphabetical order. The features should be documented
// alongside the definition of their values in the .cc file.
CONTENT_EXPORT extern const base::Feature kBrotliEncoding;
+CONTENT_EXPORT extern const base::Feature kCredentialManagementAPI;
CONTENT_EXPORT extern const base::Feature kDownloadResumption;
+CONTENT_EXPORT extern const base::Feature kDocumentWriteEvaluator;
CONTENT_EXPORT extern const base::Feature kExperimentalFramework;
-CONTENT_EXPORT extern const base::Feature kUpdateRendererPriorityOnStartup;
+CONTENT_EXPORT extern const base::Feature kNewMediaPlaybackUi;
+CONTENT_EXPORT extern const base::Feature kMediaDocumentDownloadButton;
+CONTENT_EXPORT extern const base::Feature kNonValidatingReloadOnRefreshContent;
+CONTENT_EXPORT extern const base::Feature kOptimizeIPCForSmallResource;
+CONTENT_EXPORT extern const base::Feature kRenderingPipelineThrottling;
+CONTENT_EXPORT extern const base::Feature kScrollAnchoring;
+CONTENT_EXPORT extern const base::Feature kStaleWhileRevalidate;
+CONTENT_EXPORT extern const base::Feature kTokenBinding;
CONTENT_EXPORT extern const base::Feature kWebFontsIntervention;
+CONTENT_EXPORT extern const base::Feature kWebRtcEcdsaDefault;
+CONTENT_EXPORT extern const base::Feature kWebUsb;
#if defined(OS_ANDROID)
+CONTENT_EXPORT extern const base::Feature kImeThread;
CONTENT_EXPORT extern const base::Feature kSeccompSandboxAndroid;
#endif // defined(OS_ANDROID)
diff --git a/chromium/content/public/common/content_switches.cc b/chromium/content/public/common/content_switches.cc
index 094ecf1c9fe..eae2357b8d6 100644
--- a/chromium/content/public/common/content_switches.cc
+++ b/chromium/content/public/common/content_switches.cc
@@ -11,6 +11,14 @@ namespace switches {
// have an effect. 0 disables MSAA.
const char kAcceleratedCanvas2dMSAASampleCount[] = "canvas-msaa-sample-count";
+// Enables a new tuning of the WebRTC Acoustic Echo Canceler (AEC). The new
+// tuning aims at resolving two issues with the AEC:
+// https://bugs.chromium.org/p/webrtc/issues/detail?id=5777
+// https://bugs.chromium.org/p/webrtc/issues/detail?id=5778
+// TODO(hlundin): Remove this switch when experimentation is over;
+// crbug.com/603821.
+const char kAecRefinedAdaptiveFilter[] = "aec-refined-adaptive-filter";
+
// Override the default minimum starting volume of the Automatic Gain Control
// algorithm in WebRTC used with audio tracks from getUserMedia.
// The valid range is 12-255. Values outside that range will be clamped
@@ -37,6 +45,11 @@ const char kAllowNoSandboxJob[] = "allow-no-sandbox-job";
// Allows debugging of sandboxed processes (see zygote_main_linux.cc).
const char kAllowSandboxDebugging[] = "allow-sandbox-debugging";
+// Uses the android SkFontManager on linux. The specified directory should
+// include the configuration xml file with the name "fonts.xml".
+// This is used in blimp to emulate android fonts on linux.
+const char kAndroidFontsPath[] = "android-fonts-path";
+
// Choose which logging channels in blink platform to activate. See
// Logging.cpp in blink's Source/platform for a list of available channels.
const char kBlinkPlatformLogChannels[] = "blink-platform-log-channels";
@@ -58,9 +71,6 @@ const char kBrowserSubprocessPath[] = "browser-subprocess-path";
const char kUseCrossProcessFramesForGuests[] =
"use-cross-process-frames-for-guests";
-// Dumps extra logging about plugin loading to the log file.
-const char kDebugPluginLoading[] = "debug-plugin-loading";
-
// Sets the tile size used by composited layers.
const char kDefaultTileWidth[] = "default-tile-width";
const char kDefaultTileHeight[] = "default-tile-height";
@@ -68,6 +78,9 @@ const char kDefaultTileHeight[] = "default-tile-height";
// Disable antialiasing on 2d canvas.
const char kDisable2dCanvasAntialiasing[] = "disable-canvas-aa";
+// Disables Canvas2D rendering into a scanout buffer for overlay support.
+const char kDisable2dCanvasImageChromium[] = "disable-2d-canvas-image-chromium";
+
// Disables client-visible 3D APIs, in particular WebGL and Pepper 3D.
// This is controlled by policy and is kept separate from the other
// enable/disable switches to avoid accidentally regressing the policy
@@ -90,25 +103,20 @@ const char kDisableAcceleratedVideoDecode[] =
// users with many windows/tabs and lots of memory.
const char kDisableBackingStoreLimit[] = "disable-backing-store-limit";
+// Disable backgrounding renders for occluded windows. Done for tests to avoid
+// nondeterministic behavior.
+extern const char kDisableBackgroundingOccludedWindowsForTesting[] =
+ "disable-backgrounding-occluded-windows";
+
// Disable one or more Blink runtime-enabled features.
// Use names from RuntimeEnabledFeatures.in, separated by commas.
// Applied after kEnableBlinkFeatures, and after other flags that change these
// features.
const char kDisableBlinkFeatures[] = "disable-blink-features";
-// Disables new cc/animation system (Project Heaviside). crbug.com/394772
-const char kDisableCompositorAnimationTimelines[] =
- "disable-compositor-animation-timelines";
-
// Disables HTML5 DB support.
const char kDisableDatabases[] = "disable-databases";
-// Disables Delay Agnostic AEC in WebRTC.
-const char kDisableDelayAgnosticAec[] = "disable-delay-agnostic-aec";
-
-// Handles URL requests by NPAPI plugins through the renderer.
-const char kDisableDirectNPAPIRequests[] = "disable-direct-npapi-requests";
-
// Disable the per-domain blocking for 3D APIs after GPU reset.
// This switch is intended only for tests.
const char kDisableDomainBlockingFor3DAPIs[] =
@@ -133,6 +141,10 @@ const char kDisableFlashStage3d[] = "disable-flash-stage3d";
const char kDisableGestureRequirementForMediaPlayback[] =
"disable-gesture-requirement-for-media-playback";
+// Disable user gesture requirement for presentation.
+const char kDisableGestureRequirementForPresentation[] =
+ "disable-gesture-requirement-for-presentation";
+
// Disables GPU hardware acceleration. If software renderer is not in place,
// then the GPU process won't launch.
const char kDisableGpu[] = "disable-gpu";
@@ -171,6 +183,9 @@ const char kDisableGpuSandbox[] = "disable-gpu-sandbox";
// messages.
const char kDisableGpuWatchdog[] = "disable-gpu-watchdog";
+// Disable in-process stack traces.
+const char kDisableInProcessStackTraces[] = "disable-in-process-stack-traces";
+
// Suppresses hang monitor dialogs in renderer processes. This may allow slow
// unload handlers on a page to prevent the tab from closing, but the Task
// Manager can be used to terminate the offending process in this case.
@@ -189,10 +204,6 @@ const char kDisableHistogramCustomizer[] = "disable-histogram-customizer";
// this switch.
const char kDisableKillAfterBadIPC[] = "disable-kill-after-bad-ipc";
-// Enables prefixed Encrypted Media API (e.g. webkitGenerateKeyRequest()).
-const char kEnablePrefixedEncryptedMedia[] =
- "enable-prefixed-encrypted-media";
-
// Disables LCD text.
const char kDisableLCDText[] = "disable-lcd-text";
@@ -206,9 +217,6 @@ const char kDisableLocalStorage[] = "disable-local-storage";
// builds.
const char kDisableLogging[] = "disable-logging";
-// Disables Media Source API (i.e., the MediaSource object).
-const char kDisableMediaSource[] = "disable-media-source";
-
// Disables usage of the namespace sandbox.
const char kDisableNamespaceSandbox[] = "disable-namespace-sandbox";
@@ -219,6 +227,13 @@ const char kDisableNativeGpuMemoryBuffers[] =
// Disables the Web Notification and the Push APIs.
const char kDisableNotifications[] = "disable-notifications";
+// Disable partial raster in the renderer. Disabling this switch also disables
+// the use of persistent gpu memory buffers.
+const char kDisablePartialRaster[] = "disable-partial-raster";
+
+// Enable partial raster in the renderer.
+const char kEnablePartialRaster[] = "enable-partial-raster";
+
// Disable Pepper3D.
const char kDisablePepper3d[] = "disable-pepper-3d";
@@ -228,11 +243,6 @@ const char kDisablePermissionsAPI[] = "disable-permissions-api";
// Disables compositor-accelerated touch-screen pinch gestures.
const char kDisablePinch[] = "disable-pinch";
-// Disable discovering third-party plugins. Effectively loading only
-// ones shipped with the browser plus third-party ones as specified by
-// --extra-plugin-dir and --load-plugin switches.
-const char kDisablePluginsDiscovery[] = "disable-plugins-discovery";
-
// Disable the creation of compositing layers when it would prevent LCD text.
const char kDisablePreferCompositingToLCDText[] =
"disable-prefer-compositing-to-lcd-text";
@@ -283,12 +293,18 @@ const char kDisableThreadedScrolling[] = "disable-threaded-scrolling";
// Disable V8 idle tasks.
const char kDisableV8IdleTasks[] = "disable-v8-idle-tasks";
+// Disables WebGL rendering into a scanout buffer for overlay support.
+const char kDisableWebGLImageChromium[] = "disable-webgl-image-chromium";
+
// Don't enforce the same-origin policy. (Used by people testing their sites.)
const char kDisableWebSecurity[] = "disable-web-security";
// Disables Blink's XSSAuditor. The XSSAuditor mitigates reflective XSS.
const char kDisableXSSAuditor[] = "disable-xss-auditor";
+// Disable gesture generation for wheel events.
+const char kDisableWheelGestures[] = "disable-wheel-gestures";
+
// Disable rasterizer that writes directly to GPU memory associated with tiles.
const char kDisableZeroCopy[] = "disable-zero-copy";
@@ -298,6 +314,9 @@ const char kDisableZeroCopy[] = "disable-zero-copy";
// based tests.
const char kDomAutomationController[] = "dom-automation";
+// Causes the process to run as a download subprocess.
+const char kDownloadProcess[] = "download";
+
// Enable antialiasing on 2d canvas clips (as opposed to draw operations)
const char kEnable2dCanvasClipAntialiasing[] = "enable-2d-canvas-clip-aa";
@@ -314,9 +333,6 @@ const char kEnableLCDText[] = "enable-lcd-text";
// Only valid if GPU rasterization is enabled as well.
const char kEnableDistanceFieldText[] = "enable-distance-field-text";
-// Enable the experimental Credential Manager JavaScript API.
-const char kEnableCredentialManagerAPI[] = "enable-credential-manager-api";
-
// Enable the creation of compositing layers when it would prevent LCD text.
const char kEnablePreferCompositingToLCDText[] =
"enable-prefer-compositing-to-lcd-text";
@@ -338,9 +354,6 @@ const char kEnableDisplayList2dCanvas[] = "enable-display-list-2d-canvas";
const char kForceDisplayList2dCanvas[] = "force-display-list-2d-canvas";
const char kDisableDisplayList2dCanvas[] = "disable-display-list-2d-canvas";
-// Disables (unprefixed) Encrypted Media Extensions.
-const char kDisableEncryptedMedia[] = "disable-encrypted-media";
-
// Enable experimental canvas features, e.g. canvas 2D context attributes
const char kEnableExperimentalCanvasFeatures[] =
"enable-experimental-canvas-features";
@@ -355,9 +368,6 @@ const char kEnableFeatures[] = "enable-features";
// Enable Web Bluetooth.
const char kEnableWebBluetooth[] = "enable-web-bluetooth";
-// Enables TRACE for GL calls in the renderer.
-const char kEnableGpuClientTracing[] = "enable-gpu-client-tracing";
-
// Specify that all compositor resources should be backed by GPU memory buffers.
const char kEnableGpuMemoryBufferCompositorResources[] =
"enable-gpu-memory-buffer-compositor-resources";
@@ -385,20 +395,12 @@ const char kEnableLogging[] = "enable-logging";
// Enables the memory benchmarking extension
const char kEnableMemoryBenchmarking[] = "enable-memory-benchmarking";
-// Enable the Mojo shell connection in renderers.
-const char kEnableMojoShellConnection[] = "enable-mojo-shell-connection";
-
// Enables the network information API.
const char kEnableNetworkInformation[] = "enable-network-information";
-// Enables non-validating reload on reload-to-refresh-content (e.g. pull-
-// to-refresh).
-const char kEnableNonValidatingReloadOnRefreshContent[] =
- "enable-non-validating-reload-on-refresh-content";
-
-// Enables partial raster. Enabling this switch also enables the use of
-// persistent gpu memory buffers.
-const char kEnablePartialRaster[] = "enable-partial-raster";
+// Enables action button icons for the Web Notification API.
+const char kEnableNotificationActionIcons[] =
+ "enable-notification-action-icons";
// Enables compositor-accelerated touch-screen pinch gestures.
const char kEnablePinch[] = "enable-pinch";
@@ -443,11 +445,6 @@ const char kEnableSmoothScrolling[] = "enable-smooth-scrolling";
// Enable spatial navigation
const char kEnableSpatialNavigation[] = "enable-spatial-navigation";
-// Enables implementation of the Cache-Control: stale-while-revalidate directive
-// which permits servers to allow the use of stale resources while revalidation
-// proceeds in the background.
-const char kEnableStaleWhileRevalidate[] = "enable-stale-while-revalidate";
-
// Enables StatsTable, logging statistics to a global named shared memory table.
const char kEnableStatsTable[] = "enable-stats-table";
@@ -456,8 +453,8 @@ const char kEnableStatsTable[] = "enable-stats-table";
const char kEnableStrictMixedContentChecking[] =
"enable-strict-mixed-content-checking";
-// Blocks insecure usage of number of powerful features (geolocation, for
-// example) that we haven't yet deprecated for the web at large.
+// Blocks insecure usage of a number of powerful features (device orientation,
+// for example) that we haven't yet deprecated for the web at large.
const char kEnableStrictPowerfulFeatureRestrictions[] =
"enable-strict-powerful-feature-restrictions";
@@ -489,6 +486,10 @@ const char kEnableViewport[] = "enable-viewport";
// Enable the Vtune profiler support.
const char kEnableVtune[] = "enable-vtune-support";
+// Enable WebFonts intervention and trigger the signal always.
+const char kEnableWebFontsInterventionTrigger[] =
+ "enable-webfonts-intervention-trigger";
+
// Enables WebGL extensions not yet approved by the community.
const char kEnableWebGLDraftExtensions[] = "enable-webgl-draft-extensions";
@@ -498,6 +499,9 @@ const char kEnableWebGLImageChromium[] = "enable-webgl-image-chromium";
// Enables interaction with virtual reality devices.
const char kEnableWebVR[] = "enable-webvr";
+// Enables gesture generation for wheel events.
+const char kEnableWheelGestures[] = "enable-wheel-gestures";
+
// Enable rasterizer that writes directly to GPU memory associated with tiles.
const char kEnableZeroCopy[] = "enable-zero-copy";
@@ -505,9 +509,6 @@ const char kEnableZeroCopy[] = "enable-zero-copy";
// numbers.
const char kExplicitlyAllowedPorts[] = "explicitly-allowed-ports";
-// Load NPAPI plugins from the specified directory.
-const char kExtraPluginDir[] = "extra-plugin-dir";
-
// Always use the Skia GPU backend for drawing layer tiles. Only valid with GPU
// accelerated compositing + impl-side painting. Overrides the
// kEnableGpuRasterization flag.
@@ -583,12 +584,19 @@ const char kInProcessGPU[] = "in-process-gpu";
// connection from the browser before killing itself.
const char kIPCConnectionTimeout[] = "ipc-connection-timeout";
+// Disable latest shipping ECMAScript 6 features.
+const char kDisableJavaScriptHarmonyShipping[] =
+ "disable-javascript-harmony-shipping";
+
+// Enables experimental Harmony (ECMAScript 6) features.
+const char kJavaScriptHarmony[] = "javascript-harmony";
+
+// Enables experimental WebAssembly.
+const char kEnableWasm[] = "enable-wasm";
+
// Specifies the flags passed to JS engine
const char kJavaScriptFlags[] = "js-flags";
-// Load an NPAPI plugin from the specified path.
-const char kLoadPlugin[] = "load-plugin";
-
// Logs GPU control list decisions when enforcing blacklist rules.
const char kLogGpuControlListDecisions[] = "log-gpu-control-list-decisions";
@@ -599,9 +607,6 @@ const char kLoggingLevel[] = "log-level";
// Enables saving net log events to a file and sets the file name to use.
const char kLogNetLog[] = "log-net-log";
-// Make plugin processes log their sent and received messages to VLOG(1).
-const char kLogPluginMessages[] = "log-plugin-messages";
-
// Resizes of the main frame are caused by changing between landscape and
// portrait mode (i.e. Android) so the page should be rescaled to fit.
const char kMainFrameResizesAreOrientationChanges[] =
@@ -615,6 +620,9 @@ const char kMaxUntiledLayerWidth[] = "max-untiled-layer-width";
// Renderer.Memory histogram. Used in memory tests.
const char kMemoryMetrics[] = "memory-metrics";
+// Use a Mojo-based LocalStorage implementation.
+const char kMojoLocalStorage[] = "mojo-local-storage";
+
// Mutes audio sent to the audio device so it is not audible during
// automated testing.
const char kMuteAudio[] = "mute-audio";
@@ -652,20 +660,6 @@ const char kOverridePluginPowerSaverForTesting[] =
const char kOverscrollHistoryNavigation[] =
"overscroll-history-navigation";
-// Specifies a command that should be used to launch the plugin process. Useful
-// for running the plugin process through purify or quantify. Ex:
-// --plugin-launcher="path\to\purify /Run=yes"
-const char kPluginLauncher[] = "plugin-launcher";
-
-// Tells the plugin process the path of the plugin to load
-const char kPluginPath[] = "plugin-path";
-
-// Causes the process to run as a plugin subprocess.
-const char kPluginProcess[] = "plugin";
-
-// Causes the plugin process to display a dialog on launch.
-const char kPluginStartupDialog[] = "plugin-startup-dialog";
-
// Argument to the process type that indicates a PPAPI broker process type.
const char kPpapiBrokerProcess[] = "ppapi-broker";
@@ -675,7 +669,9 @@ const char kPpapiFlashArgs[] = "ppapi-flash-args";
// Runs PPAPI (Pepper) plugins in-process.
const char kPpapiInProcess[] = "ppapi-in-process";
-// Like kPluginLauncher for PPAPI plugins.
+// Specifies a command that should be used to launch the ppapi plugin process.
+// Useful for running the plugin process through purify or quantify. Ex:
+// --ppapi-plugin-launcher="path\to\purify /Run=yes"
const char kPpapiPluginLauncher[] = "ppapi-plugin-launcher";
// Argument to the process type that indicates a PPAPI plugin process type.
@@ -685,10 +681,15 @@ const char kPpapiPluginProcess[] = "ppapi";
// --no-sandbox as well or the sandbox won't allow the dialog to display.
const char kPpapiStartupDialog[] = "ppapi-startup-dialog";
-// Runs a single process for each site (i.e., group of pages from the same
-// registered domain) the user visits. We default to using a renderer process
-// for each site instance (i.e., group of pages from the same registered
-// domain with script connections to each other).
+// Enable the "Process Per Site" process model for all domains. This mode
+// consolidates same-site pages so that they share a single process.
+//
+// More details here:
+// - http://www.chromium.org/developers/design-documents/process-models
+// - The class comment in site_instance.h, listing the supported process models.
+//
+// IMPORTANT: This isn't to be confused with --site-per-process (which is about
+// isolation, not consolidation). You probably want the other one.
const char kProcessPerSite[] = "process-per-site";
// Runs each set of script-connected tabs (i.e., a BrowsingInstance) in its own
@@ -723,7 +724,9 @@ const char kRendererProcess[] = "renderer";
// or instability.
const char kRendererProcessLimit[] = "renderer-process-limit";
-// Causes the renderer process to display a dialog on launch.
+// Causes the renderer process to display a dialog on launch. Passing this flag
+// also adds kNoSandbox on Windows non-official builds, since that's needed to
+// show a dialog.
const char kRendererStartupDialog[] = "renderer-startup-dialog";
// Reduce the default `referer` header's granularity.
@@ -757,7 +760,12 @@ const char kSingleProcess[] = "single-process";
// * <iframe>s are rendered out-of-process whenever the src= is cross-site.
//
// More details here:
-// http://www.chromium.org/developers/design-documents/site-isolation
+// - http://www.chromium.org/developers/design-documents/site-isolation
+// - http://www.chromium.org/developers/design-documents/process-models
+// - The class comment in site_instance.h, listing the supported process models.
+//
+// IMPORTANT: this isn't to be confused with --process-per-site (which is about
+// process consolidation, not isolation). You probably want this one.
const char kSitePerProcess[] = "site-per-process";
// Skip gpu info collection, blacklist loading, and blacklist auto-update
@@ -767,6 +775,12 @@ const char kSitePerProcess[] = "site-per-process";
// TODO(gab): Get rid of this switch entirely.
const char kSkipGpuDataLoading[] = "skip-gpu-data-loading";
+// Skips reencoding bitmaps as PNGs when the encoded data is unavailable
+// during SKP capture. This allows for obtaining an accurate sample of
+// the types of images on the web, rather than being weighted towards PNGs
+// that we have encoded ourselves.
+const char kSkipReencodingOnSKPCapture[] = "skip-reencoding-on-skp-capture";
+
// Specifies if the browser should start in fullscreen mode, like if the user
// had pressed F11 right after startup.
const char kStartFullscreen[] = "start-fullscreen";
@@ -778,14 +792,6 @@ const char kStartFullscreen[] = "start-fullscreen";
const char kStatsCollectionController[] =
"enable-stats-collection-bindings";
-// Upscale defaults to "good".
-const char kTabCaptureDownscaleQuality[] = "tab-capture-downscale-quality";
-
-// Scaling quality for capturing tab. Should be one of "fast", "good" or "best".
-// One flag for upscaling, one for downscaling.
-// Upscale defaults to "best".
-const char kTabCaptureUpscaleQuality[] = "tab-capture-upscale-quality";
-
// Allows for forcing socket connections to http/https to use fixed ports.
const char kTestingFixedHttpPort[] = "testing-fixed-http-port";
const char kTestingFixedHttpsPort[] = "testing-fixed-https-port";
@@ -793,6 +799,10 @@ const char kTestingFixedHttpsPort[] = "testing-fixed-https-port";
// Type of the current test harness ("browser" or "ui").
const char kTestType[] = "test-type";
+// Groups all out-of-process iframes to a different process from the process
+// of the top document. This is a performance isolation mode.
+const char kTopDocumentIsolation[] = "top-document-isolation";
+
// Controls how text selection granularity changes when touch text selection
// handles are dragged. Should be "character" or "direction". If not specified,
// the platform default is used.
@@ -820,20 +830,9 @@ const char kVideoImageTextureTarget[] = "video-image-texture-target";
// Set when Chromium should use a mobile user agent.
const char kUseMobileUserAgent[] = "use-mobile-user-agent";
-// Use normal priority for tile task worker threads. Otherwise they may
-// be run at background priority on some platforms.
-const char kUseNormalPriorityForTileTaskWorkerThreads[] =
- "use-normal-priority-for-tile-task-worker-threads";
-
// Use remote compositor for the renderer.
const char kUseRemoteCompositing[] = "use-remote-compositing";
-// Use the new surfaces system to handle compositor delegation.
-const char kUseSurfaces[] = "use-surfaces";
-
-// Disable the use of the new surfaces system to handle compositor delegation.
-const char kDisableSurfaces[] = "disable-surfaces";
-
// The contents of this flag are prepended to the utility process command line.
// Useful values might be "valgrind" or "xterm -e gdb --args".
const char kUtilityCmdPrefix[] = "utility-cmd-prefix";
@@ -855,6 +854,12 @@ const char kValidateInputEventStream[] = "validate-input-event-stream";
// kWaitForDebugger flag passed on or not.
const char kWaitForDebuggerChildren[] = "wait-for-debugger-children";
+// Forces processes to wait for Mojo shell connection initialization before
+// proceeding with main thread startup.
+//
+// TODO(rockot): Remove this. http://crbug.com/594852.
+const char kWaitForMojoShell[] = "wait-for-mojo-shell";
+
// The prefix used when starting the zygote process. (i.e. 'gdb --args')
const char kZygoteCmdPrefix[] = "zygote-cmd-prefix";
@@ -901,11 +906,6 @@ const char kWebRtcMaxCaptureFramerate[] = "max-gum-fps";
#endif
#if defined(OS_ANDROID)
-// Disable external animation system for Android compositor.
-// See also kDisableCompositorAnimationTimelines for renderer compositors.
-const char kDisableAndroidCompositorAnimationTimelines[] =
- "disable-android-compositor-animation-timelines";
-
// Disable overscroll edge effects like those found in Android views.
const char kDisableOverscrollEdgeEffect[] = "disable-overscroll-edge-effect";
@@ -935,14 +935,24 @@ const char kRemoteDebuggingSocketName[] = "remote-debugging-socket-name";
// Block ChildProcessMain thread of the renderer's ChildProcessService until a
// Java debugger is attached.
const char kRendererWaitForJavaDebugger[] = "renderer-wait-for-java-debugger";
+
+// Use synchronous input code path for IPC-synchronous compositing. This is the
+// legacy input code path used by the in-process synchronous compositor.
+// Maintaining this code path in case there are compatibility bugs with the
+// standard async input path. Remove tracked as part of crbug.com/545628.
+const char kSyncInputForSyncCompositor[] = "sync-input-for-sync-compositor";
+
+// Enables overscrolling for the OSK on Android.
+const char kEnableOSKOverscroll[] = "enable-osk-overscroll";
#endif
// Enable the aggressive flushing of DOM Storage to minimize data loss.
const char kEnableAggressiveDOMStorageFlushing[] =
"enable-aggressive-domstorage-flushing";
-// Disable web audio API.
-const char kDisableWebAudio[] = "disable-webaudio";
+// Enable audio for desktop share.
+const char kDisableAudioSupportForDesktopShare[] =
+ "disable-audio-support-for-desktop-share";
#if defined(OS_CHROMEOS)
// Disables panel fitting (used for mirror mode).
@@ -960,13 +970,6 @@ const char kDisableVaapiAcceleratedVideoEncode[] =
const char kEnableSpeechDispatcher[] = "enable-speech-dispatcher";
#endif
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-// Disables support for Core Animation plugins. This is triggered when
-// accelerated compositing is disabled. See http://crbug.com/122430.
-const char kDisableCoreAnimationPlugins[] =
- "disable-core-animation-plugins";
-#endif
-
#if defined(OS_WIN)
// /prefetch:# arguments to use when launching various process types. It has
// been observed that when file reads are consistent for 3 process launches with
diff --git a/chromium/content/public/common/content_switches.h b/chromium/content/public/common/content_switches.h
index f45e53907ee..525366fd20c 100644
--- a/chromium/content/public/common/content_switches.h
+++ b/chromium/content/public/common/content_switches.h
@@ -15,41 +15,43 @@ namespace switches {
// All switches in alphabetical order. The switches should be documented
// alongside the definition of their values in the .cc file.
CONTENT_EXPORT extern const char kAcceleratedCanvas2dMSAASampleCount[];
+CONTENT_EXPORT extern const char kAecRefinedAdaptiveFilter[];
CONTENT_EXPORT extern const char kAgcStartupMinVolume[];
CONTENT_EXPORT extern const char kAllowFileAccessFromFiles[];
CONTENT_EXPORT extern const char kAllowLoopbackInPeerConnection[];
CONTENT_EXPORT extern const char kAllowNoSandboxJob[];
CONTENT_EXPORT extern const char kAllowSandboxDebugging[];
+CONTENT_EXPORT extern const char kAndroidFontsPath[];
CONTENT_EXPORT extern const char kBlinkSettings[];
CONTENT_EXPORT extern const char kBlinkPlatformLogChannels[];
CONTENT_EXPORT extern const char kBrowserCrashTest[];
CONTENT_EXPORT extern const char kBrowserSubprocessPath[];
-extern const char kUseCrossProcessFramesForGuests[];
-extern const char kDebugPluginLoading[];
+CONTENT_EXPORT extern const char kUseCrossProcessFramesForGuests[];
CONTENT_EXPORT extern const char kDefaultTileWidth[];
CONTENT_EXPORT extern const char kDefaultTileHeight[];
CONTENT_EXPORT extern const char kDisable2dCanvasAntialiasing[];
+CONTENT_EXPORT extern const char kDisable2dCanvasImageChromium[];
CONTENT_EXPORT extern const char kDisable3DAPIs[];
CONTENT_EXPORT extern const char kDisableAccelerated2dCanvas[];
CONTENT_EXPORT extern const char kDisableAcceleratedJpegDecoding[];
CONTENT_EXPORT extern const char kDisableAcceleratedMjpegDecode[];
CONTENT_EXPORT extern const char kDisableAcceleratedVideoDecode[];
+CONTENT_EXPORT extern const char kDisableAudioSupportForDesktopShare[];
extern const char kDisableBackingStoreLimit[];
+CONTENT_EXPORT extern const char
+ kDisableBackgroundingOccludedWindowsForTesting[];
CONTENT_EXPORT extern const char kDisableBlinkFeatures[];
-CONTENT_EXPORT extern const char kDisableCompositorAnimationTimelines[];
CONTENT_EXPORT extern const char kDisableDatabases[];
-CONTENT_EXPORT extern const char kDisableDelayAgnosticAec[];
-extern const char kDisableDirectNPAPIRequests[];
CONTENT_EXPORT extern const char kDisableDistanceFieldText[];
CONTENT_EXPORT extern const char kDisableDisplayList2dCanvas[];
extern const char kDisableDomainBlockingFor3DAPIs[];
-CONTENT_EXPORT extern const char kDisableEncryptedMedia[];
CONTENT_EXPORT extern const char kDisableExperimentalWebGL[];
CONTENT_EXPORT extern const char kDisableFeatures[];
CONTENT_EXPORT extern const char kDisableFileSystem[];
CONTENT_EXPORT extern const char kDisableFlash3d[];
CONTENT_EXPORT extern const char kDisableFlashStage3d[];
CONTENT_EXPORT extern const char kDisableGestureRequirementForMediaPlayback[];
+CONTENT_EXPORT extern const char kDisableGestureRequirementForPresentation[];
CONTENT_EXPORT extern const char kDisableGpu[];
CONTENT_EXPORT extern const char kDisableGpuCompositing[];
CONTENT_EXPORT extern const char kDisableGpuEarlyInit[];
@@ -59,24 +61,25 @@ extern const char kDisableGpuProcessCrashLimit[];
CONTENT_EXPORT extern const char kDisableGpuRasterization[];
CONTENT_EXPORT extern const char kDisableGpuSandbox[];
CONTENT_EXPORT extern const char kDisableGpuWatchdog[];
+CONTENT_EXPORT extern const char kDisableInProcessStackTraces[];
+CONTENT_EXPORT extern const char kDisableJavaScriptHarmonyShipping[];
CONTENT_EXPORT extern const char kDisableLowResTiling[];
CONTENT_EXPORT extern const char kDisableHangMonitor[];
CONTENT_EXPORT extern const char kDisableHideInactiveStackedTabCloseButtons[];
extern const char kDisableHistogramCustomizer[];
CONTENT_EXPORT extern const char kDisableLCDText[];
CONTENT_EXPORT extern const char kDisablePreferCompositingToLCDText[];
-CONTENT_EXPORT extern const char kEnablePrefixedEncryptedMedia[];
-extern const char kDisableKillAfterBadIPC[];
+CONTENT_EXPORT extern const char kDisableKillAfterBadIPC[];
CONTENT_EXPORT extern const char kDisableLocalStorage[];
CONTENT_EXPORT extern const char kDisableLogging[];
-CONTENT_EXPORT extern const char kDisableMediaSource[];
CONTENT_EXPORT extern const char kDisableNamespaceSandbox[];
CONTENT_EXPORT extern const char kDisableNativeGpuMemoryBuffers[];
CONTENT_EXPORT extern const char kDisableNotifications[];
+CONTENT_EXPORT extern const char kDisablePartialRaster[];
+CONTENT_EXPORT extern const char kEnablePartialRaster[];
extern const char kDisablePepper3d[];
CONTENT_EXPORT extern const char kDisablePermissionsAPI[];
CONTENT_EXPORT extern const char kDisablePinch[];
-CONTENT_EXPORT extern const char kDisablePluginsDiscovery[];
CONTENT_EXPORT extern const char kDisablePresentationAPI[];
CONTENT_EXPORT extern const char kDisableRGBA4444Textures[];
CONTENT_EXPORT extern const char kDisableReadingFromCanvas[];
@@ -92,13 +95,15 @@ CONTENT_EXPORT extern const char kDisableSpeechAPI[];
CONTENT_EXPORT extern const char kDisableThreadedCompositing[];
CONTENT_EXPORT extern const char kDisableThreadedScrolling[];
extern const char kDisableV8IdleTasks[];
+CONTENT_EXPORT extern const char kDisableWebGLImageChromium[];
CONTENT_EXPORT extern const char kDisableWebSecurity[];
extern const char kDisableXSSAuditor[];
+CONTENT_EXPORT extern const char kDisableWheelGestures[];
CONTENT_EXPORT extern const char kDisableZeroCopy[];
CONTENT_EXPORT extern const char kDomAutomationController[];
+CONTENT_EXPORT extern const char kDownloadProcess[];
extern const char kEnable2dCanvasClipAntialiasing[];
CONTENT_EXPORT extern const char kEnableAggressiveDOMStorageFlushing[];
-CONTENT_EXPORT extern const char kEnableCredentialManagerAPI[];
CONTENT_EXPORT extern const char kEnablePreferCompositingToLCDText[];
CONTENT_EXPORT extern const char kEnableBlinkFeatures[];
CONTENT_EXPORT extern const char kEnableBrowserSideNavigation[];
@@ -107,8 +112,8 @@ CONTENT_EXPORT extern const char kEnableDistanceFieldText[];
CONTENT_EXPORT extern const char kEnableExperimentalCanvasFeatures[];
CONTENT_EXPORT extern const char kEnableExperimentalWebPlatformFeatures[];
CONTENT_EXPORT extern const char kEnableFeatures[];
+CONTENT_EXPORT extern const char kEnableWasm[];
CONTENT_EXPORT extern const char kEnableWebBluetooth[];
-extern const char kEnableGpuClientTracing[];
CONTENT_EXPORT extern const char kEnableGpuMemoryBufferCompositorResources[];
CONTENT_EXPORT extern const char kEnableGpuMemoryBufferVideoFrames[];
CONTENT_EXPORT extern const char kEnableGpuRasterization[];
@@ -118,10 +123,8 @@ CONTENT_EXPORT extern const char kEnableImageColorProfiles[];
CONTENT_EXPORT extern const char kEnableLCDText[];
CONTENT_EXPORT extern const char kEnableLogging[];
extern const char kEnableMemoryBenchmarking[];
-CONTENT_EXPORT extern const char kEnableMojoShellConnection[];
CONTENT_EXPORT extern const char kEnableNetworkInformation[];
-CONTENT_EXPORT extern const char kEnableNonValidatingReloadOnRefreshContent[];
-CONTENT_EXPORT extern const char kEnablePartialRaster[];
+CONTENT_EXPORT extern const char kEnableNotificationActionIcons[];
CONTENT_EXPORT extern const char kEnablePinch[];
CONTENT_EXPORT extern const char kEnablePluginPlaceholderTesting[];
CONTENT_EXPORT extern const char kEnablePreciseMemoryInfo[];
@@ -131,7 +134,6 @@ extern const char kEnableSkiaBenchmarking[];
CONTENT_EXPORT extern const char kEnableSlimmingPaintV2[];
CONTENT_EXPORT extern const char kEnableSmoothScrolling[];
CONTENT_EXPORT extern const char kEnableSpatialNavigation[];
-CONTENT_EXPORT extern const char kEnableStaleWhileRevalidate[];
CONTENT_EXPORT extern const char kEnableStatsTable[];
CONTENT_EXPORT extern const char kEnableStrictMixedContentChecking[];
CONTENT_EXPORT extern const char kEnableStrictPowerfulFeatureRestrictions[];
@@ -143,12 +145,13 @@ CONTENT_EXPORT extern const char kEnableUserMediaScreenCapturing[];
CONTENT_EXPORT extern const char kEnableUseZoomForDSF[];
CONTENT_EXPORT extern const char kEnableViewport[];
CONTENT_EXPORT extern const char kEnableVtune[];
+CONTENT_EXPORT extern const char kEnableWebFontsInterventionTrigger[];
CONTENT_EXPORT extern const char kEnableWebGLDraftExtensions[];
CONTENT_EXPORT extern const char kEnableWebGLImageChromium[];
CONTENT_EXPORT extern const char kEnableWebVR[];
+CONTENT_EXPORT extern const char kEnableWheelGestures[];
CONTENT_EXPORT extern const char kEnableZeroCopy[];
CONTENT_EXPORT extern const char kExplicitlyAllowedPorts[];
-CONTENT_EXPORT extern const char kExtraPluginDir[];
CONTENT_EXPORT extern const char kForceDisplayList2dCanvas[];
CONTENT_EXPORT extern const char kForceGpuRasterization[];
CONTENT_EXPORT extern const char kForceOverlayFullscreenVideo[];
@@ -171,15 +174,15 @@ CONTENT_EXPORT extern const char kInertVisualViewport[];
CONTENT_EXPORT extern const char kInProcessGPU[];
CONTENT_EXPORT extern const char kIPCConnectionTimeout[];
CONTENT_EXPORT extern const char kJavaScriptFlags[];
-extern const char kLoadPlugin[];
+CONTENT_EXPORT extern const char kJavaScriptHarmony[];
CONTENT_EXPORT extern const char kLogGpuControlListDecisions[];
CONTENT_EXPORT extern const char kLoggingLevel[];
CONTENT_EXPORT extern const char kLogNetLog[];
-extern const char kLogPluginMessages[];
CONTENT_EXPORT extern const char kMainFrameResizesAreOrientationChanges[];
extern const char kMaxUntiledLayerHeight[];
extern const char kMaxUntiledLayerWidth[];
extern const char kMemoryMetrics[];
+extern const char kMojoLocalStorage[];
CONTENT_EXPORT extern const char kMuteAudio[];
CONTENT_EXPORT extern const char kNoReferrers[];
CONTENT_EXPORT extern const char kNoSandbox[];
@@ -188,10 +191,6 @@ CONTENT_EXPORT extern const char kDisableAppContainer[];
CONTENT_EXPORT extern const char kNumRasterThreads[];
CONTENT_EXPORT extern const char kOverridePluginPowerSaverForTesting[];
CONTENT_EXPORT extern const char kOverscrollHistoryNavigation[];
-extern const char kPluginLauncher[];
-CONTENT_EXPORT extern const char kPluginPath[];
-CONTENT_EXPORT extern const char kPluginProcess[];
-extern const char kPluginStartupDialog[];
CONTENT_EXPORT extern const char kPpapiBrokerProcess[];
CONTENT_EXPORT extern const char kPpapiFlashArgs[];
CONTENT_EXPORT extern const char kPpapiInProcess[];
@@ -216,13 +215,13 @@ extern const char kShowPaintRects[];
CONTENT_EXPORT extern const char kSingleProcess[];
CONTENT_EXPORT extern const char kSitePerProcess[];
CONTENT_EXPORT extern const char kSkipGpuDataLoading[];
+extern const char kSkipReencodingOnSKPCapture[];
CONTENT_EXPORT extern const char kStartFullscreen[];
CONTENT_EXPORT extern const char kStatsCollectionController[];
-CONTENT_EXPORT extern const char kTabCaptureDownscaleQuality[];
-CONTENT_EXPORT extern const char kTabCaptureUpscaleQuality[];
CONTENT_EXPORT extern const char kTestingFixedHttpPort[];
CONTENT_EXPORT extern const char kTestingFixedHttpsPort[];
CONTENT_EXPORT extern const char kTestType[];
+CONTENT_EXPORT extern const char kTopDocumentIsolation[];
CONTENT_EXPORT extern const char kTouchTextSelectionStrategy[];
CONTENT_EXPORT extern const char kUIPrioritizeInGpuProcess[];
CONTENT_EXPORT extern const char kUseFakeUIForMediaStream[];
@@ -231,10 +230,7 @@ CONTENT_EXPORT extern const char kEnableNativeGpuMemoryBuffers[];
CONTENT_EXPORT extern const char kContentImageTextureTarget[];
CONTENT_EXPORT extern const char kVideoImageTextureTarget[];
CONTENT_EXPORT extern const char kUseMobileUserAgent[];
-CONTENT_EXPORT extern const char kUseNormalPriorityForTileTaskWorkerThreads[];
CONTENT_EXPORT extern const char kUseRemoteCompositing[];
-extern const char kUseSurfaces[];
-CONTENT_EXPORT extern const char kDisableSurfaces[];
extern const char kUtilityCmdPrefix[];
CONTENT_EXPORT extern const char kUtilityProcess[];
extern const char kUtilityProcessAllowedDir[];
@@ -244,6 +240,7 @@ CONTENT_EXPORT extern const char kV8NativesPassedByFD[];
CONTENT_EXPORT extern const char kV8SnapshotPassedByFD[];
CONTENT_EXPORT extern const char kValidateInputEventStream[];
CONTENT_EXPORT extern const char kWaitForDebuggerChildren[];
+CONTENT_EXPORT extern const char kWaitForMojoShell[];
CONTENT_EXPORT extern const char kZygoteCmdPrefix[];
CONTENT_EXPORT extern const char kZygoteProcess[];
@@ -261,7 +258,6 @@ extern const char kWebRtcMaxCaptureFramerate[];
#endif
#if defined(OS_ANDROID)
-CONTENT_EXPORT extern const char kDisableAndroidCompositorAnimationTimelines[];
CONTENT_EXPORT extern const char kDisableOverscrollEdgeEffect[];
CONTENT_EXPORT extern const char kDisablePullToRefreshEffect[];
CONTENT_EXPORT extern const char kDisableScreenOrientationLock[];
@@ -272,10 +268,10 @@ CONTENT_EXPORT extern const char kHideScrollbars[];
extern const char kNetworkCountryIso[];
CONTENT_EXPORT extern const char kRemoteDebuggingSocketName[];
CONTENT_EXPORT extern const char kRendererWaitForJavaDebugger[];
+CONTENT_EXPORT extern const char kSyncInputForSyncCompositor[];
+CONTENT_EXPORT extern const char kEnableOSKOverscroll[];
#endif
-CONTENT_EXPORT extern const char kDisableWebAudio[];
-
#if defined(OS_CHROMEOS)
CONTENT_EXPORT extern const char kDisablePanelFitting[];
CONTENT_EXPORT extern const char kDisableVaapiAcceleratedVideoEncode[];
@@ -285,11 +281,6 @@ CONTENT_EXPORT extern const char kDisableVaapiAcceleratedVideoEncode[];
CONTENT_EXPORT extern const char kEnableSpeechDispatcher[];
#endif
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-extern const char kDisableCoreAnimationPlugins[];
-extern const char kDisableThreadedEventHandlingMac[];
-#endif
-
#if defined(OS_WIN)
CONTENT_EXPORT extern const char kPrefetchArgumentRenderer[];
CONTENT_EXPORT extern const char kPrefetchArgumentGpu[];
diff --git a/chromium/content/public/common/context_menu_params.cc b/chromium/content/public/common/context_menu_params.cc
index ebd54553fd8..e29305b744d 100644
--- a/chromium/content/public/common/context_menu_params.cc
+++ b/chromium/content/public/common/context_menu_params.cc
@@ -35,6 +35,8 @@ ContextMenuParams::ContextMenuParams()
input_field_type(blink::WebContextMenuData::InputFieldTypeNone) {
}
+ContextMenuParams::ContextMenuParams(const ContextMenuParams& other) = default;
+
ContextMenuParams::~ContextMenuParams() {
}
diff --git a/chromium/content/public/common/context_menu_params.h b/chromium/content/public/common/context_menu_params.h
index 46510e874c4..7269f1b6991 100644
--- a/chromium/content/public/common/context_menu_params.h
+++ b/chromium/content/public/common/context_menu_params.h
@@ -17,6 +17,7 @@
#include "content/public/common/menu_item.h"
#include "content/public/common/page_state.h"
#include "content/public/common/ssl_status.h"
+#include "third_party/WebKit/public/platform/WebCString.h"
#include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
#include "third_party/WebKit/public/web/WebContextMenuData.h"
#include "ui/base/ui_base_types.h"
@@ -54,6 +55,7 @@ struct CONTENT_EXPORT CustomContextMenuContext {
// could be used for more contextual actions.
struct CONTENT_EXPORT ContextMenuParams {
ContextMenuParams();
+ ContextMenuParams(const ContextMenuParams& other);
~ContextMenuParams();
// This is the type of Context Node that the context menu was invoked on.
diff --git a/chromium/content/public/common/drop_data.cc b/chromium/content/public/common/drop_data.cc
index 5f9466b39bf..c3bb9251b7e 100644
--- a/chromium/content/public/common/drop_data.cc
+++ b/chromium/content/public/common/drop_data.cc
@@ -10,6 +10,8 @@ DropData::DropData()
: did_originate_from_renderer(false),
referrer_policy(blink::WebReferrerPolicyDefault) {}
+DropData::DropData(const DropData& other) = default;
+
DropData::~DropData() {
}
diff --git a/chromium/content/public/common/drop_data.h b/chromium/content/public/common/drop_data.h
index e589184b41f..fce6db13774 100644
--- a/chromium/content/public/common/drop_data.h
+++ b/chromium/content/public/common/drop_data.h
@@ -33,6 +33,7 @@ struct CONTENT_EXPORT DropData {
};
DropData();
+ DropData(const DropData& other);
~DropData();
// Whether this drag originated from a renderer.
diff --git a/chromium/content/public/common/dwrite_font_platform_win.h b/chromium/content/public/common/dwrite_font_platform_win.h
deleted file mode 100644
index d049f280b1c..00000000000
--- a/chromium/content/public/common/dwrite_font_platform_win.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_PUBLIC_COMMON_DWRITE_FONT_PLATFORM_WIN_H_
-#define CONTENT_PUBLIC_COMMON_DWRITE_FONT_PLATFORM_WIN_H_
-
-#include "base/files/file.h"
-#include "content/common/content_export.h"
-
-struct IDWriteFactory;
-struct IDWriteFontCollection;
-
-namespace content {
-
-// This is the shared section that is used between browser and renderer for
-// loading font cache. Section name is suffixed with browser process id so that
-// multiple instance chrome scenario works fine.
-CONTENT_EXPORT extern const char kFontCacheSharedSectionName[];
-
-// Function returns custom font collection in terms of IDWriteFontCollection.
-// This function maintains singleton instance of font collection and returns
-// it on repeated calls.
-CONTENT_EXPORT IDWriteFontCollection* GetCustomFontCollection(
- IDWriteFactory* factory);
-
-// Builds static font cache. As this function need to iterate through all
-// available fonts in the system, it may take a while.
-CONTENT_EXPORT bool BuildFontCache(const base::FilePath& file);
-
-// Loads font cache from file. This is supposed to be used from browser
-// side where loading means creating readonly shared memory file mapping so that
-// renderers can read from it.
-CONTENT_EXPORT bool LoadFontCache(const base::FilePath& path);
-
-// Added in header mainly for unittest
-CONTENT_EXPORT bool ValidateFontCacheFile(base::File* file);
-
-// Determines whether code should use the DirectWrite font proxy codepath.
-// Note that this function only checks whether the field trial is enabled.
-// Callers are still expected to take appropriate action based on the return
-// value.
-CONTENT_EXPORT bool ShouldUseDirectWriteFontProxyFieldTrial();
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_COMMON_DWRITE_FONT_PLATFORM_WIN_H_
diff --git a/chromium/content/public/common/favicon_url.cc b/chromium/content/public/common/favicon_url.cc
index 68ba481b531..80debff64ba 100644
--- a/chromium/content/public/common/favicon_url.cc
+++ b/chromium/content/public/common/favicon_url.cc
@@ -15,6 +15,8 @@ FaviconURL::FaviconURL(const GURL& url,
const std::vector<gfx::Size>& sizes)
: icon_url(url), icon_type(type), icon_sizes(sizes) {}
+FaviconURL::FaviconURL(const FaviconURL& other) = default;
+
FaviconURL::~FaviconURL() {
}
diff --git a/chromium/content/public/common/favicon_url.h b/chromium/content/public/common/favicon_url.h
index 43770c2b86b..349fc8785ae 100644
--- a/chromium/content/public/common/favicon_url.h
+++ b/chromium/content/public/common/favicon_url.h
@@ -28,6 +28,7 @@ struct CONTENT_EXPORT FaviconURL {
FaviconURL(const GURL& url,
IconType type,
const std::vector<gfx::Size>& sizes);
+ FaviconURL(const FaviconURL& other);
~FaviconURL();
// The url of the icon.
diff --git a/chromium/content/public/common/feature_h264_with_openh264_ffmpeg.cc b/chromium/content/public/common/feature_h264_with_openh264_ffmpeg.cc
new file mode 100644
index 00000000000..b13cfdfbf4b
--- /dev/null
+++ b/chromium/content/public/common/feature_h264_with_openh264_ffmpeg.cc
@@ -0,0 +1,17 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/common/feature_h264_with_openh264_ffmpeg.h"
+
+namespace content {
+
+#if BUILDFLAG(RTC_USE_H264)
+
+const base::Feature kWebRtcH264WithOpenH264FFmpeg {
+ "WebRTC-H264WithOpenH264FFmpeg", base::FEATURE_DISABLED_BY_DEFAULT
+};
+
+#endif // BUILDFLAG(RTC_USE_H264)
+
+} // namespace content
diff --git a/chromium/content/public/common/feature_h264_with_openh264_ffmpeg.h b/chromium/content/public/common/feature_h264_with_openh264_ffmpeg.h
new file mode 100644
index 00000000000..ba21bd0802d
--- /dev/null
+++ b/chromium/content/public/common/feature_h264_with_openh264_ffmpeg.h
@@ -0,0 +1,22 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_COMMON_FEATURE_H264_WITH_OPENH264_FFMPEG_H_
+#define CONTENT_PUBLIC_COMMON_FEATURE_H264_WITH_OPENH264_FFMPEG_H_
+
+#include "base/feature_list.h"
+#include "content/public/common/features.h"
+
+namespace content {
+
+#if BUILDFLAG(RTC_USE_H264)
+
+// Run-time feature for the |rtc_use_h264| encoder/decoder.
+extern const base::Feature kWebRtcH264WithOpenH264FFmpeg;
+
+#endif // BUILDFLAG(RTC_USE_H264)
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_COMMON_FEATURE_H264_WITH_OPENH264_FFMPEG_H_
diff --git a/chromium/content/public/common/file_chooser_file_info.cc b/chromium/content/public/common/file_chooser_file_info.cc
index 9f9a02878ff..8605b123c07 100644
--- a/chromium/content/public/common/file_chooser_file_info.cc
+++ b/chromium/content/public/common/file_chooser_file_info.cc
@@ -9,6 +9,9 @@ namespace content {
FileChooserFileInfo::FileChooserFileInfo() : length(0), is_directory(false) {
}
+FileChooserFileInfo::FileChooserFileInfo(const FileChooserFileInfo& other) =
+ default;
+
FileChooserFileInfo::~FileChooserFileInfo() {
}
diff --git a/chromium/content/public/common/file_chooser_file_info.h b/chromium/content/public/common/file_chooser_file_info.h
index d2bb5e0bb00..0f338238696 100644
--- a/chromium/content/public/common/file_chooser_file_info.h
+++ b/chromium/content/public/common/file_chooser_file_info.h
@@ -17,6 +17,7 @@ namespace content {
// Result of file chooser.
struct CONTENT_EXPORT FileChooserFileInfo {
FileChooserFileInfo();
+ FileChooserFileInfo(const FileChooserFileInfo& other);
~FileChooserFileInfo();
base::FilePath file_path;
diff --git a/chromium/content/public/common/file_chooser_params.cc b/chromium/content/public/common/file_chooser_params.cc
index 97de9e3b6ef..da1ca6f6d97 100644
--- a/chromium/content/public/common/file_chooser_params.cc
+++ b/chromium/content/public/common/file_chooser_params.cc
@@ -9,6 +9,8 @@ namespace content {
FileChooserParams::FileChooserParams() : mode(Open), need_local_path(true) {
}
+FileChooserParams::FileChooserParams(const FileChooserParams& other) = default;
+
FileChooserParams::~FileChooserParams() {
}
diff --git a/chromium/content/public/common/file_chooser_params.h b/chromium/content/public/common/file_chooser_params.h
index ef43f7be30f..c189785370b 100644
--- a/chromium/content/public/common/file_chooser_params.h
+++ b/chromium/content/public/common/file_chooser_params.h
@@ -18,6 +18,7 @@ namespace content {
// Struct used by WebContentsDelegate.
struct CONTENT_EXPORT FileChooserParams {
FileChooserParams();
+ FileChooserParams(const FileChooserParams& other);
~FileChooserParams();
enum Mode {
diff --git a/chromium/content/public/common/frame_navigate_params.cc b/chromium/content/public/common/frame_navigate_params.cc
index bcc90b5e783..d15f4c13139 100644
--- a/chromium/content/public/common/frame_navigate_params.cc
+++ b/chromium/content/public/common/frame_navigate_params.cc
@@ -15,6 +15,9 @@ FrameNavigateParams::FrameNavigateParams()
should_update_history(false) {
}
+FrameNavigateParams::FrameNavigateParams(const FrameNavigateParams& other) =
+ default;
+
FrameNavigateParams::~FrameNavigateParams() {
}
diff --git a/chromium/content/public/common/frame_navigate_params.h b/chromium/content/public/common/frame_navigate_params.h
index 2c80fd29e40..49c039f357d 100644
--- a/chromium/content/public/common/frame_navigate_params.h
+++ b/chromium/content/public/common/frame_navigate_params.h
@@ -12,6 +12,7 @@
#include "content/common/content_export.h"
#include "content/public/common/referrer.h"
+#include "ipc/ipc_message_utils.h"
#include "net/base/host_port_pair.h"
#include "ui/base/page_transition_types.h"
#include "url/gurl.h"
@@ -19,8 +20,12 @@
namespace content {
// Struct used by WebContentsObserver.
-struct CONTENT_EXPORT FrameNavigateParams {
+// Note that we derived from IPC::NoParams here, because this struct is used in
+// an IPC struct as a parent. Deriving from NoParams allows us to by-pass the
+// out of line constructor checks in our clang plugins.
+struct CONTENT_EXPORT FrameNavigateParams : public IPC::NoParams {
FrameNavigateParams();
+ FrameNavigateParams(const FrameNavigateParams& other);
~FrameNavigateParams();
// Page ID of this navigation. The renderer creates a new unique page ID
diff --git a/chromium/content/public/common/geoposition.cc b/chromium/content/public/common/geoposition.cc
index 3a0f1f08b18..d885d4e539c 100644
--- a/chromium/content/public/common/geoposition.cc
+++ b/chromium/content/public/common/geoposition.cc
@@ -29,6 +29,8 @@ Geoposition::Geoposition()
error_code(ERROR_CODE_NONE) {
}
+Geoposition::Geoposition(const Geoposition& other) = default;
+
bool Geoposition::Validate() const {
return latitude >= -90. && latitude <= 90. &&
longitude >= -180. && longitude <= 180. &&
diff --git a/chromium/content/public/common/geoposition.h b/chromium/content/public/common/geoposition.h
index 0bcb839e6b9..23b29078e15 100644
--- a/chromium/content/public/common/geoposition.h
+++ b/chromium/content/public/common/geoposition.h
@@ -32,6 +32,8 @@ struct CONTENT_EXPORT Geoposition {
// error code is set to ERROR_CODE_NONE.
Geoposition();
+ Geoposition(const Geoposition& other);
+
// A valid fix has a valid latitude, longitude, accuracy and timestamp.
bool Validate() const;
diff --git a/chromium/content/public/common/gpu_memory_stats.cc b/chromium/content/public/common/gpu_memory_stats.cc
deleted file mode 100644
index 2b4e0fad14c..00000000000
--- a/chromium/content/public/common/gpu_memory_stats.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/public/common/gpu_memory_stats.h"
-
-namespace content {
-
-GPUVideoMemoryUsageStats::GPUVideoMemoryUsageStats()
- : bytes_allocated(0),
- bytes_allocated_historical_max(0) {
-}
-
-GPUVideoMemoryUsageStats::~GPUVideoMemoryUsageStats() {
-}
-
-GPUVideoMemoryUsageStats::ProcessStats::ProcessStats()
- : video_memory(0),
- has_duplicates(false) {
-}
-
-GPUVideoMemoryUsageStats::ProcessStats::~ProcessStats() {
-}
-
-} // namespace content
diff --git a/chromium/content/public/common/gpu_memory_stats.h b/chromium/content/public/common/gpu_memory_stats.h
deleted file mode 100644
index cb28b23404c..00000000000
--- a/chromium/content/public/common/gpu_memory_stats.h
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_PUBLIC_COMMON_GPU_MEMORY_STATS_H_
-#define CONTENT_PUBLIC_COMMON_GPU_MEMORY_STATS_H_
-
-// Provides access to the GPU information for the system
-// on which chrome is currently running.
-
-#include <stddef.h>
-
-#include <map>
-
-#include "base/process/process.h"
-#include "content/common/content_export.h"
-
-namespace content {
-
-struct CONTENT_EXPORT GPUVideoMemoryUsageStats {
- GPUVideoMemoryUsageStats();
- ~GPUVideoMemoryUsageStats();
-
- struct CONTENT_EXPORT ProcessStats {
- ProcessStats();
- ~ProcessStats();
-
- // The bytes of GPU resources accessible by this process
- size_t video_memory;
-
- // Set to true if this process' GPU resource count is inflated because
- // it is counting other processes' resources (e.g, the GPU process has
- // duplicate set to true because it is the aggregate of all processes)
- bool has_duplicates;
- };
- typedef std::map<base::ProcessId, ProcessStats> ProcessMap;
-
- // A map of processes to their GPU resource consumption
- ProcessMap process_map;
-
- // The total amount of GPU memory allocated at the time of the request.
- size_t bytes_allocated;
-
- // The maximum amount of GPU memory ever allocated at once.
- size_t bytes_allocated_historical_max;
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_COMMON_GPU_MEMORY_STATS_H_
diff --git a/chromium/content/public/common/manifest.cc b/chromium/content/public/common/manifest.cc
index 744be0ec3a5..e38a9043c37 100644
--- a/chromium/content/public/common/manifest.cc
+++ b/chromium/content/public/common/manifest.cc
@@ -19,6 +19,8 @@ Manifest::Icon::Icon()
: density(kDefaultDensity) {
}
+Manifest::Icon::Icon(const Icon& other) = default;
+
Manifest::Icon::~Icon() {
}
@@ -36,6 +38,8 @@ Manifest::Manifest()
background_color(Manifest::kInvalidOrMissingColor) {
}
+Manifest::Manifest(const Manifest& other) = default;
+
Manifest::~Manifest() {
}
diff --git a/chromium/content/public/common/manifest.h b/chromium/content/public/common/manifest.h
index 35671b8aff0..7dc15ca5167 100644
--- a/chromium/content/public/common/manifest.h
+++ b/chromium/content/public/common/manifest.h
@@ -27,6 +27,7 @@ struct CONTENT_EXPORT Manifest {
// http://w3c.github.io/manifest/#dfn-icon-object
struct CONTENT_EXPORT Icon {
Icon();
+ Icon(const Icon& other);
~Icon();
// MUST be a valid url. If an icon doesn't have a valid URL, it will not be
@@ -71,6 +72,7 @@ struct CONTENT_EXPORT Manifest {
};
Manifest();
+ Manifest(const Manifest& other);
~Manifest();
// Returns whether this Manifest had no attribute set. A newly created
diff --git a/chromium/content/public/common/media_metadata.cc b/chromium/content/public/common/media_metadata.cc
new file mode 100644
index 00000000000..dc3824c25b0
--- /dev/null
+++ b/chromium/content/public/common/media_metadata.cc
@@ -0,0 +1,23 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/common/media_metadata.h"
+
+namespace content {
+
+const size_t MediaMetadata::kMaxIPCStringLength = 4 * 1024;
+
+MediaMetadata::MediaMetadata() = default;
+
+MediaMetadata::~MediaMetadata() = default;
+
+bool MediaMetadata::operator==(const MediaMetadata& other) const {
+ return title == other.title && artist == other.artist && album == other.album;
+}
+
+bool MediaMetadata::operator!=(const MediaMetadata& other) const {
+ return !this->operator==(other);
+}
+
+} // namespace content
diff --git a/chromium/content/public/common/media_metadata.h b/chromium/content/public/common/media_metadata.h
new file mode 100644
index 00000000000..3d7f13c5936
--- /dev/null
+++ b/chromium/content/public/common/media_metadata.h
@@ -0,0 +1,40 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_COMMON_MEDIA_METADATA_H_
+#define CONTENT_PUBLIC_COMMON_MEDIA_METADATA_H_
+
+#include "base/strings/string16.h"
+#include "content/common/content_export.h"
+
+namespace content {
+
+// The MediaMetadata is a structure carrying information associated to a
+// content::MediaSession.
+struct CONTENT_EXPORT MediaMetadata {
+ MediaMetadata();
+ ~MediaMetadata();
+
+ bool operator==(const MediaMetadata& other) const;
+ bool operator!=(const MediaMetadata& other) const;
+
+ // Title associated to the MediaSession.
+ base::string16 title;
+
+ // Artist associated to the MediaSession.
+ base::string16 artist;
+
+ // Album associated to the MediaSession.
+ base::string16 album;
+
+ // Maximum length for all the strings inside the MediaMetadata when it is sent
+ // over IPC. The renderer process should truncate the strings before sending
+ // the MediaMetadata and the browser process must do the same when receiving
+ // it.
+ static const size_t kMaxIPCStringLength;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_COMMON_MEDIA_METADATA_H_
diff --git a/chromium/content/public/common/media_stream_request.cc b/chromium/content/public/common/media_stream_request.cc
index 72a4b160ef4..d1dd847e264 100644
--- a/chromium/content/public/common/media_stream_request.cc
+++ b/chromium/content/public/common/media_stream_request.cc
@@ -57,6 +57,8 @@ MediaStreamDevice::MediaStreamDevice(
input(sample_rate, channel_layout, frames_per_buffer) {
}
+MediaStreamDevice::MediaStreamDevice(const MediaStreamDevice& other) = default;
+
MediaStreamDevice::~MediaStreamDevice() {}
bool MediaStreamDevice::IsEqual(const MediaStreamDevice& second) const {
@@ -96,6 +98,9 @@ MediaStreamDevice::AudioDeviceParameters::AudioDeviceParameters(
frames_per_buffer(frames_per_buffer),
effects() {}
+MediaStreamDevice::AudioDeviceParameters::AudioDeviceParameters(
+ const AudioDeviceParameters& other) = default;
+
MediaStreamDevice::AudioDeviceParameters::~AudioDeviceParameters() {}
MediaStreamRequest::MediaStreamRequest(
@@ -122,6 +127,9 @@ MediaStreamRequest::MediaStreamRequest(
all_ancestors_have_same_origin(false) {
}
+MediaStreamRequest::MediaStreamRequest(const MediaStreamRequest& other) =
+ default;
+
MediaStreamRequest::~MediaStreamRequest() {}
} // namespace content
diff --git a/chromium/content/public/common/media_stream_request.h b/chromium/content/public/common/media_stream_request.h
index c4b6a7ee3ed..7486fd59993 100644
--- a/chromium/content/public/common/media_stream_request.h
+++ b/chromium/content/public/common/media_stream_request.h
@@ -106,6 +106,8 @@ struct CONTENT_EXPORT MediaStreamDevice {
int channel_layout,
int frames_per_buffer);
+ MediaStreamDevice(const MediaStreamDevice& other);
+
~MediaStreamDevice();
bool IsEqual(const MediaStreamDevice& second) const;
@@ -134,6 +136,7 @@ struct CONTENT_EXPORT MediaStreamDevice {
AudioDeviceParameters(int sample_rate,
int channel_layout,
int frames_per_buffer);
+ AudioDeviceParameters(const AudioDeviceParameters& other);
~AudioDeviceParameters();
@@ -203,6 +206,8 @@ struct CONTENT_EXPORT MediaStreamRequest {
MediaStreamType audio_type,
MediaStreamType video_type);
+ MediaStreamRequest(const MediaStreamRequest& other);
+
~MediaStreamRequest();
// This is the render process id for the renderer associated with generating
diff --git a/chromium/content/public/common/mojo_channel_switches.cc b/chromium/content/public/common/mojo_channel_switches.cc
index 8f70ce287d0..f649eb8a324 100644
--- a/chromium/content/public/common/mojo_channel_switches.cc
+++ b/chromium/content/public/common/mojo_channel_switches.cc
@@ -5,33 +5,39 @@
#include "content/public/common/mojo_channel_switches.h"
#include "base/command_line.h"
+#include "base/metrics/field_trial.h"
#include "ipc/mojo/ipc_channel_mojo.h"
#include "mojo/common/common_type_converters.h"
namespace switches {
-// Replaces renderer-browser IPC channel with ChnanelMojo.
-// TODO(morrita): Now ChannelMojo for the renderer is on by default.
-// Remove this once the change sticks.
-const char kEnableRendererMojoChannel[] =
- "enable-renderer-mojo-channel";
+// Enable ChannelMojo on any supported platform.
+const char kEnableMojoChannel[] = "enable-mojo-channel";
-// Disale ChannelMojo usage regardless of the platform or the process type.
-const char kDisableMojoChannel[] = "disable-mojo-channel";
+// The token to use to construct the message pipe on which to layer ChannelMojo.
+const char kMojoChannelToken[] = "mojo-channel-token";
} // namespace switches
+namespace {
+
+const char kMojoChannelExperimentName[] = "MojoChannel";
+
+} // namespace
+
namespace content {
bool ShouldUseMojoChannel() {
- const base::CommandLine& command_line =
- *base::CommandLine::ForCurrentProcess();
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableMojoChannel))
+ return true;
- if (command_line.HasSwitch(switches::kDisableMojoChannel))
- return false;
- if (command_line.HasSwitch(switches::kEnableRendererMojoChannel))
+ const std::string group =
+ base::FieldTrialList::FindFullName(kMojoChannelExperimentName);
+ if (group == "Enabled")
return true;
- return IPC::ChannelMojo::ShouldBeUsed();
+
+ return false;
}
} // namespace content
diff --git a/chromium/content/public/common/mojo_channel_switches.h b/chromium/content/public/common/mojo_channel_switches.h
index 5e2af68f8d6..20daf110042 100644
--- a/chromium/content/public/common/mojo_channel_switches.h
+++ b/chromium/content/public/common/mojo_channel_switches.h
@@ -9,8 +9,8 @@
namespace switches {
-extern const char kEnableRendererMojoChannel[];
-extern const char kDisableMojoChannel[];
+extern const char kEnableMojoChannel[];
+CONTENT_EXPORT extern const char kMojoChannelToken[];
} // namespace switches
diff --git a/chromium/content/public/common/mojo_geoposition.mojom b/chromium/content/public/common/mojo_geoposition.mojom
deleted file mode 100644
index 852f2a9c44b..00000000000
--- a/chromium/content/public/common/mojo_geoposition.mojom
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file declares the Geoposition structure, used to represent a position
-// fix. It was originally derived from:
-// http://gears.googlecode.com/svn/trunk/gears/geolocation/geolocation.h
-// TODO(blundell): Investigate killing content::Geoposition in favor of using
-// this struct everywhere (and renaming it to Geoposition).
-
-module content;
-
-struct MojoGeoposition {
- // These values follow the W3C geolocation specification and can be returned
- // to JavaScript without the need for a conversion.
- enum ErrorCode {
- ERROR_CODE_NONE = 0, // Chrome addition.
- ERROR_CODE_PERMISSION_DENIED = 1,
- ERROR_CODE_POSITION_UNAVAILABLE = 2,
- ERROR_CODE_TIMEOUT = 3,
- ERROR_CODE_LAST = ERROR_CODE_TIMEOUT
- };
-
- // Whether this geoposition is valid.
- bool valid;
-
- // These properties correspond to those of the JavaScript Position object
- // although their types may differ.
- // Latitude in decimal degrees north (WGS84 coordinate frame).
- double latitude;
- // Longitude in decimal degrees west (WGS84 coordinate frame).
- double longitude;
- // Altitude in meters (above WGS84 datum).
- double altitude;
- // Accuracy of horizontal position in meters.
- double accuracy;
- // Accuracy of altitude in meters.
- double altitude_accuracy;
- // Heading in decimal degrees clockwise from true north.
- double heading;
- // Horizontal component of device velocity in meters per second.
- double speed;
- // TODO(blundell): If I need to represent this differently to use this
- // struct to replace content::Geolocation, I'll need to convert
- // correctly into seconds-since-epoch when using this in
- // GeolocationDispatcher::OnLocationUpdate().
- // Time of position measurement in seconds since Epoch in UTC time. This is
- // taken from the host computer's system clock (i.e. from Time::Now(), not the
- // source device's clock).
- double timestamp;
-
- // Error code, see enum above.
- ErrorCode error_code;
- // Human-readable error message.
- string error_message;
-};
diff --git a/chromium/content/public/common/mojo_shell_connection.h b/chromium/content/public/common/mojo_shell_connection.h
index e42e3c08512..6ae92bbe45f 100644
--- a/chromium/content/public/common/mojo_shell_connection.h
+++ b/chromium/content/public/common/mojo_shell_connection.h
@@ -5,11 +5,13 @@
#ifndef CONTENT_PUBLIC_COMMON_MOJO_SHELL_CONNECTION_H_
#define CONTENT_PUBLIC_COMMON_MOJO_SHELL_CONNECTION_H_
+#include "base/callback_forward.h"
#include "content/common/content_export.h"
+#include "mojo/shell/public/interfaces/shell_client.mojom.h"
namespace mojo {
-class ApplicationConnection;
-class ApplicationImpl;
+class Connection;
+class Connector;
}
namespace content {
@@ -24,14 +26,19 @@ namespace content {
class CONTENT_EXPORT MojoShellConnection {
public:
// Override to add additional services to inbound connections.
+ // TODO(beng): This should just be ShellClient.
class Listener {
public:
- virtual bool ConfigureIncomingConnection(
- mojo::ApplicationConnection* connection) = 0;
+ virtual bool AcceptConnection(mojo::Connection* connection) = 0;
virtual ~Listener() {}
};
+ using Factory = base::Closure;
+ // Sets the factory used to create the MojoShellConnection. This must be
+ // called before the MojoShellConnection has been created.
+ static void SetFactoryForTest(Factory* factory);
+
// Will return null if no connection has been established (either because it
// hasn't happened yet or the application was not spawned from the external
// Mojo shell.
@@ -41,11 +48,22 @@ class CONTENT_EXPORT MojoShellConnection {
// created on.
static void Destroy();
- // Returns an Initialized() ApplicationImpl.
- virtual mojo::ApplicationImpl* GetApplication() = 0;
+ // Creates the appropriate MojoShellConnection from |request|. See
+ // UsingExternalShell() for details of |is_external|.
+ static void Create(mojo::shell::mojom::ShellClientRequest request,
+ bool is_external);
+
+ virtual mojo::Connector* GetConnector() = 0;
+
+ // Indicates whether the shell connection is to an external shell (true) or
+ // a shell embedded in the browser process (false).
+ virtual bool UsingExternalShell() const = 0;
+
+ // Sets a closure that is called when the connection is lost.
+ virtual void SetConnectionLostClosure(const base::Closure& closure) = 0;
// [De]Register an impl of Listener that will be consulted when the wrapped
- // ApplicationImpl exposes services to inbound connections.
+ // ShellConnection exposes services to inbound connections.
// Registered listeners are owned by this MojoShellConnection.
virtual void AddListener(Listener* listener) = 0;
virtual void RemoveListener(Listener* listener) = 0;
diff --git a/chromium/content/public/common/navigator_connect_client.cc b/chromium/content/public/common/navigator_connect_client.cc
deleted file mode 100644
index bf21bc96cdd..00000000000
--- a/chromium/content/public/common/navigator_connect_client.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/public/common/navigator_connect_client.h"
-
-namespace content {
-
-NavigatorConnectClient::NavigatorConnectClient() : message_port_id(-1) {
-}
-
-NavigatorConnectClient::NavigatorConnectClient(const GURL& target_url,
- const GURL& origin,
- int message_port_id)
- : target_url(target_url), origin(origin), message_port_id(message_port_id) {
-}
-
-NavigatorConnectClient::~NavigatorConnectClient() {
-}
-
-} // namespace content
diff --git a/chromium/content/public/common/navigator_connect_client.h b/chromium/content/public/common/navigator_connect_client.h
deleted file mode 100644
index 9cc66ec7163..00000000000
--- a/chromium/content/public/common/navigator_connect_client.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_PUBLIC_COMMON_NAVIGATOR_CONNECT_CLIENT_H_
-#define CONTENT_PUBLIC_COMMON_NAVIGATOR_CONNECT_CLIENT_H_
-
-#include "url/gurl.h"
-
-namespace content {
-
-// This struct represents a connection to a navigator.connect exposed service.
-struct NavigatorConnectClient {
- NavigatorConnectClient();
- NavigatorConnectClient(const GURL& target_url,
- const GURL& origin,
- int message_port_id);
- ~NavigatorConnectClient();
-
- // The URL this client is connected to (or trying to connect to).
- GURL target_url;
-
- // The origin of the client.
- GURL origin;
-
- // Message port ID for the service side message port associated with this
- // client.
- int message_port_id;
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_COMMON_NAVIGATOR_CONNECT_CLIENT_H_
diff --git a/chromium/content/public/common/notification_resources.cc b/chromium/content/public/common/notification_resources.cc
new file mode 100644
index 00000000000..75619a0a0a6
--- /dev/null
+++ b/chromium/content/public/common/notification_resources.cc
@@ -0,0 +1,16 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/common/notification_resources.h"
+
+namespace content {
+
+NotificationResources::NotificationResources() {}
+
+NotificationResources::NotificationResources(
+ const NotificationResources& other) = default;
+
+NotificationResources::~NotificationResources() {}
+
+} // namespace content
diff --git a/chromium/content/public/common/notification_resources.h b/chromium/content/public/common/notification_resources.h
new file mode 100644
index 00000000000..2594836eceb
--- /dev/null
+++ b/chromium/content/public/common/notification_resources.h
@@ -0,0 +1,36 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_COMMON_NOTIFICATION_RESOURCES_H_
+#define CONTENT_PUBLIC_COMMON_NOTIFICATION_RESOURCES_H_
+
+#include <vector>
+
+#include "content/common/content_export.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+
+namespace content {
+
+// Structure to hold the resources associated with a Web Notification.
+struct CONTENT_EXPORT NotificationResources {
+ NotificationResources();
+ NotificationResources(const NotificationResources& other);
+ ~NotificationResources();
+
+ // Main icon for the notification. The bitmap may be empty if the developer
+ // did not provide an icon, or fetching of the icon failed.
+ SkBitmap notification_icon;
+
+ // Badge for the notification. The bitmap may be empty if the developer
+ // did not provide a badge, or fetching of the badge failed.
+ SkBitmap badge;
+
+ // Icons for the actions. A bitmap may be empty if the developer did not
+ // provide an icon, or fetching of the icon failed.
+ std::vector<SkBitmap> action_icons;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_COMMON_NOTIFICATION_RESOURCES_H_
diff --git a/chromium/content/public/common/pepper_plugin_info.cc b/chromium/content/public/common/pepper_plugin_info.cc
index 25b00c3be8d..5c909afc71e 100644
--- a/chromium/content/public/common/pepper_plugin_info.cc
+++ b/chromium/content/public/common/pepper_plugin_info.cc
@@ -5,6 +5,7 @@
#include "content/public/common/pepper_plugin_info.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/version.h"
namespace content {
@@ -18,9 +19,14 @@ PepperPluginInfo::PepperPluginInfo()
: is_internal(false),
is_out_of_process(false),
is_debug(false),
+ is_on_local_drive(true),
+ is_external(false),
+ is_bundled(false),
permissions(0) {
}
+PepperPluginInfo::PepperPluginInfo(const PepperPluginInfo& other) = default;
+
PepperPluginInfo::~PepperPluginInfo() {
}
diff --git a/chromium/content/public/common/pepper_plugin_info.h b/chromium/content/public/common/pepper_plugin_info.h
index 253d8213dc6..e7170026f98 100644
--- a/chromium/content/public/common/pepper_plugin_info.h
+++ b/chromium/content/public/common/pepper_plugin_info.h
@@ -37,6 +37,7 @@ struct CONTENT_EXPORT PepperPluginInfo {
};
PepperPluginInfo();
+ PepperPluginInfo(const PepperPluginInfo& other);
~PepperPluginInfo();
WebPluginInfo ToWebPluginInfo() const;
@@ -60,6 +61,20 @@ struct CONTENT_EXPORT PepperPluginInfo {
// Defaults to false.
bool is_debug;
+ // True when the plugin is on a local drive. The sandbox will not successfully
+ // load a plugin on a remote drive.
+ // Defaults to true.
+ bool is_on_local_drive;
+
+ // True when the plugin is an external plugin i.e. not bundled with Chrome or
+ // via the component updater.
+ // Defaults to false.
+ bool is_external;
+
+ // True when the plugin is bundled with Chrome.
+ // Defaults to false.
+ bool is_bundled;
+
// When is_internal is set, this contains the function pointers to the
// entry points for the internal plugins.
EntryPoints internal_entry_points;
diff --git a/chromium/content/public/common/permission_status.mojom b/chromium/content/public/common/permission_status.mojom
deleted file mode 100644
index 8373104a8d4..00000000000
--- a/chromium/content/public/common/permission_status.mojom
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-module content;
-
-enum PermissionStatus {
- GRANTED,
- DENIED,
- ASK,
- LAST = ASK
-};
diff --git a/chromium/content/public/common/platform_notification_data.cc b/chromium/content/public/common/platform_notification_data.cc
index dba6c16f8a4..904015aa701 100644
--- a/chromium/content/public/common/platform_notification_data.cc
+++ b/chromium/content/public/common/platform_notification_data.cc
@@ -8,10 +8,16 @@ namespace content {
PlatformNotificationAction::PlatformNotificationAction() {}
+PlatformNotificationAction::PlatformNotificationAction(
+ const PlatformNotificationAction& other) = default;
+
PlatformNotificationAction::~PlatformNotificationAction() {}
PlatformNotificationData::PlatformNotificationData() {}
+PlatformNotificationData::PlatformNotificationData(
+ const PlatformNotificationData& other) = default;
+
PlatformNotificationData::~PlatformNotificationData() {}
} // namespace content
diff --git a/chromium/content/public/common/platform_notification_data.h b/chromium/content/public/common/platform_notification_data.h
index 4a9609ef169..97f723493f7 100644
--- a/chromium/content/public/common/platform_notification_data.h
+++ b/chromium/content/public/common/platform_notification_data.h
@@ -10,22 +10,41 @@
#include <string>
#include <vector>
+#include "base/strings/nullable_string16.h"
#include "base/strings/string16.h"
+#include "base/time/time.h"
#include "content/common/content_export.h"
#include "url/gurl.h"
namespace content {
-// A notification action (button); corresponds to Blink WebNotificationAction.
+enum PlatformNotificationActionType {
+ PLATFORM_NOTIFICATION_ACTION_TYPE_BUTTON = 0,
+ PLATFORM_NOTIFICATION_ACTION_TYPE_TEXT,
+};
+
+// A notification action (button or text input); corresponds to Blink
+// WebNotificationAction.
struct CONTENT_EXPORT PlatformNotificationAction {
PlatformNotificationAction();
+ PlatformNotificationAction(const PlatformNotificationAction& other);
~PlatformNotificationAction();
+ // Type of the action (button or text input).
+ PlatformNotificationActionType type;
+
// Action name that the author can use to distinguish them.
std::string action;
// Title of the button.
base::string16 title;
+
+ // URL of the icon for the button. May be empty if no url was specified.
+ GURL icon;
+
+ // Optional text to use as placeholder for text inputs. May be null if it was
+ // not specified.
+ base::NullableString16 placeholder;
};
// Structure representing the information associated with a Web Notification.
@@ -33,6 +52,7 @@ struct CONTENT_EXPORT PlatformNotificationAction {
// synchronized with the WebNotificationData structure defined in the Blink API.
struct CONTENT_EXPORT PlatformNotificationData {
PlatformNotificationData();
+ PlatformNotificationData(const PlatformNotificationData& other);
~PlatformNotificationData();
// The maximum size of developer-provided data to be stored in the |data|
@@ -66,10 +86,21 @@ struct CONTENT_EXPORT PlatformNotificationData {
// URL of the icon which is to be displayed with the notification.
GURL icon;
+ // URL of the badge for representing the notification. May be empty if no url
+ // was specified.
+ GURL badge;
+
// Vibration pattern for the notification, following the syntax of the
// Vibration API. https://www.w3.org/TR/vibration/
std::vector<int> vibration_pattern;
+ // The time at which the event the notification represents took place.
+ base::Time timestamp;
+
+ // Whether default notification indicators (sound, vibration, light) should
+ // be played again if the notification is replacing an older notification.
+ bool renotify = false;
+
// Whether default notification indicators (sound, vibration, light) should
// be suppressed.
bool silent = false;
diff --git a/chromium/content/public/common/process_type.h b/chromium/content/public/common/process_type.h
index 14696697857..13218e0724d 100644
--- a/chromium/content/public/common/process_type.h
+++ b/chromium/content/public/common/process_type.h
@@ -19,7 +19,7 @@ enum ProcessType {
PROCESS_TYPE_UNKNOWN = 1,
PROCESS_TYPE_BROWSER,
PROCESS_TYPE_RENDERER,
- PROCESS_TYPE_PLUGIN,
+ PROCESS_TYPE_PLUGIN_DEPRECATED,
PROCESS_TYPE_WORKER_DEPRECATED,
PROCESS_TYPE_UTILITY,
PROCESS_TYPE_ZYGOTE,
@@ -36,7 +36,7 @@ enum ProcessType {
};
// Returns an English name of the process type, should only be used for non
-// user-visible strings, or debugging pages like about:memory.
+// user-visible strings or debugging pages.
CONTENT_EXPORT std::string GetProcessTypeNameInEnglish(int type);
} // namespace content
diff --git a/chromium/content/public/common/push_event_payload.h b/chromium/content/public/common/push_event_payload.h
new file mode 100644
index 00000000000..a560cdac69b
--- /dev/null
+++ b/chromium/content/public/common/push_event_payload.h
@@ -0,0 +1,37 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_COMMON_PUSH_EVENT_PAYLOAD_H_
+#define CONTENT_PUBLIC_COMMON_PUSH_EVENT_PAYLOAD_H_
+
+#include <string>
+
+#include "content/common/content_export.h"
+
+namespace content {
+
+// Structure representing the payload delivered as part of a push message.
+// This struct contains the decrypted information sent from the push
+// service as part of a PushEvent as well as metadata about the information.
+struct CONTENT_EXPORT PushEventPayload {
+ PushEventPayload() : is_null(true) {}
+ ~PushEventPayload() {}
+
+ // Method to both set the data string and update the null status.
+ void setData(const std::string& data_in) {
+ data = data_in;
+ is_null = false;
+ }
+
+ // Data contained in the payload.
+ std::string data;
+
+ // Whether the payload is null or not. Payloads can be valid with non-empty
+ // content, valid with empty content, or null.
+ bool is_null;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_COMMON_PUSH_EVENT_PAYLOAD_H_
diff --git a/chromium/content/public/common/push_subscription_options.h b/chromium/content/public/common/push_subscription_options.h
new file mode 100644
index 00000000000..1a2da0a9e4c
--- /dev/null
+++ b/chromium/content/public/common/push_subscription_options.h
@@ -0,0 +1,32 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_COMMON_PUSH_SUBSCRIPTION_OPTIONS_H_
+#define CONTENT_PUBLIC_COMMON_PUSH_SUBSCRIPTION_OPTIONS_H_
+
+#include <string>
+
+#include "content/common/content_export.h"
+
+namespace content {
+
+// Structure to hold the options provided from the web app developer as
+// part of asking for a new push subscription.
+struct CONTENT_EXPORT PushSubscriptionOptions {
+ PushSubscriptionOptions() {}
+ ~PushSubscriptionOptions() {}
+
+ // Whether or not the app developer agrees to provide user visible
+ // notifications whenever they receive a push message.
+ bool user_visible_only = false;
+
+ // The unique identifier of the application service which is used to
+ // verify the push message before delivery. This could either be an ID
+ // assigned by the developer console or the app server's public key.
+ std::string sender_info;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_COMMON_CONTENT_PUSH_SUBSCRIPTION_OPTIONS_H_
diff --git a/chromium/content/public/common/referrer.cc b/chromium/content/public/common/referrer.cc
index 183c950673f..bd145a29125 100644
--- a/chromium/content/public/common/referrer.cc
+++ b/chromium/content/public/common/referrer.cc
@@ -14,7 +14,7 @@ Referrer Referrer::SanitizeForRequest(const GURL& request,
Referrer sanitized_referrer(referrer.url.GetAsReferrer(), referrer.policy);
if (!request.SchemeIsHTTPOrHTTPS() ||
- !sanitized_referrer.url.SchemeIsHTTPOrHTTPS()) {
+ !sanitized_referrer.url.SchemeIsValidForReferrer()) {
sanitized_referrer.url = GURL();
return sanitized_referrer;
}
diff --git a/chromium/content/public/common/renderer_preferences.cc b/chromium/content/public/common/renderer_preferences.cc
index 9bb824ccfb9..2a9f86761f8 100644
--- a/chromium/content/public/common/renderer_preferences.cc
+++ b/chromium/content/public/common/renderer_preferences.cc
@@ -52,6 +52,9 @@ RendererPreferences::RendererPreferences()
, default_font_size(0)
{}
+RendererPreferences::RendererPreferences(const RendererPreferences& other) =
+ default;
+
RendererPreferences::~RendererPreferences() { }
} // namespace content
diff --git a/chromium/content/public/common/renderer_preferences.h b/chromium/content/public/common/renderer_preferences.h
index 975394a73fa..2b085ae17ce 100644
--- a/chromium/content/public/common/renderer_preferences.h
+++ b/chromium/content/public/common/renderer_preferences.h
@@ -35,6 +35,7 @@ enum TapMultipleTargetsStrategy {
struct CONTENT_EXPORT RendererPreferences {
RendererPreferences();
+ RendererPreferences(const RendererPreferences& other);
~RendererPreferences();
// Whether the renderer's current browser context accept drops from the OS
diff --git a/chromium/content/public/common/resource_response.cc b/chromium/content/public/common/resource_response.cc
index 1277355445f..2e8d97e16c4 100644
--- a/chromium/content/public/common/resource_response.cc
+++ b/chromium/content/public/common/resource_response.cc
@@ -51,6 +51,7 @@ scoped_refptr<ResourceResponse> ResourceResponse::DeepCopy() const {
head.service_worker_start_time;
new_response->head.service_worker_ready_time =
head.service_worker_ready_time;
+ new_response->head.is_using_lofi = head.is_using_lofi;
return new_response;
}
diff --git a/chromium/content/public/common/resource_response_info.cc b/chromium/content/public/common/resource_response_info.cc
index f05ee195f9a..39131cfe36b 100644
--- a/chromium/content/public/common/resource_response_info.cc
+++ b/chromium/content/public/common/resource_response_info.cc
@@ -25,6 +25,9 @@ ResourceResponseInfo::ResourceResponseInfo()
blink::WebServiceWorkerResponseTypeDefault),
is_using_lofi(false) {}
+ResourceResponseInfo::ResourceResponseInfo(const ResourceResponseInfo& other) =
+ default;
+
ResourceResponseInfo::~ResourceResponseInfo() {
}
diff --git a/chromium/content/public/common/resource_response_info.h b/chromium/content/public/common/resource_response_info.h
index e7b7c7a7131..f5ff68eb830 100644
--- a/chromium/content/public/common/resource_response_info.h
+++ b/chromium/content/public/common/resource_response_info.h
@@ -27,6 +27,7 @@ namespace content {
// in resource_response.cc.
struct ResourceResponseInfo {
CONTENT_EXPORT ResourceResponseInfo();
+ CONTENT_EXPORT ResourceResponseInfo(const ResourceResponseInfo& other);
CONTENT_EXPORT ~ResourceResponseInfo();
// The time at which the request was made that resulted in this response.
@@ -134,6 +135,14 @@ struct ResourceResponseInfo {
// TODO(ksakamoto): Move this to net::LoadTimingInfo.
base::TimeTicks service_worker_ready_time;
+ // True when the response is served from the CacheStorage via the
+ // ServiceWorker.
+ bool is_in_cache_storage = false;
+
+ // The cache name of the CacheStorage from where the response is served via
+ // the ServiceWorker. Empty if the response isn't from the CacheStorage.
+ std::string cache_storage_cache_name;
+
// Whether or not the request was for a LoFi version of the resource.
bool is_using_lofi;
};
diff --git a/chromium/content/public/common/sandbox_init.h b/chromium/content/public/common/sandbox_init.h
index 1a312339ee8..cbd8142fc9f 100644
--- a/chromium/content/public/common/sandbox_init.h
+++ b/chromium/content/public/common/sandbox_init.h
@@ -8,6 +8,7 @@
#include "base/files/scoped_file.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory.h"
+#include "base/process/launch.h"
#include "base/process/process.h"
#include "base/process/process_handle.h"
#include "build/build_config.h"
@@ -28,17 +29,6 @@ struct SandboxInterfaceInfo;
namespace content {
class SandboxedProcessLauncherDelegate;
-#if defined(OS_WIN) || defined(OS_MACOSX)
-// This function allows a sandboxed process to duplicate a SharedMemoryHandle
-// to itself or to another process. The duplicated SharedMemoryHandle has the
-// same access rights as the original. Returns true on success, false
-// otherwise.
-CONTENT_EXPORT bool BrokerDuplicateSharedMemoryHandle(
- const base::SharedMemoryHandle& source_handle,
- base::ProcessId target_process_id,
- base::SharedMemoryHandle* target_handle);
-#endif // defined(OS_WIN) || defined(OS_MACOSX)
-
#if defined(OS_WIN)
// Initialize the sandbox for renderer, gpu, utility, worker, nacl, and plugin
@@ -71,10 +61,13 @@ CONTENT_EXPORT bool BrokerDuplicateHandle(HANDLE source_handle,
CONTENT_EXPORT bool BrokerAddTargetPeer(HANDLE peer_process);
// Launch a sandboxed process. |delegate| may be NULL. If |delegate| is non-NULL
-// then it just has to outlive this method call.
+// then it just has to outlive this method call. |handles_to_inherit| is a list
+// of handles for the child process to inherit. The caller retains ownership of
+// the handles.
CONTENT_EXPORT base::Process StartSandboxedProcess(
SandboxedProcessLauncherDelegate* delegate,
- base::CommandLine* cmd_line);
+ base::CommandLine* cmd_line,
+ const base::HandlesToInheritVector& handles_to_inherit);
#elif defined(OS_MACOSX)
diff --git a/chromium/content/public/common/sandboxed_process_launcher_delegate.cc b/chromium/content/public/common/sandboxed_process_launcher_delegate.cc
index e0204c48e34..5435816be6d 100644
--- a/chromium/content/public/common/sandboxed_process_launcher_delegate.cc
+++ b/chromium/content/public/common/sandboxed_process_launcher_delegate.cc
@@ -26,9 +26,11 @@ bool SandboxedProcessLauncherDelegate::PreSpawnTarget(
}
#elif(OS_POSIX)
-bool SandboxedProcessLauncherDelegate::ShouldUseZygote() {
- return false;
+#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
+ZygoteHandle* SandboxedProcessLauncherDelegate::GetZygote() {
+ return nullptr;
}
+#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
base::EnvironmentMap SandboxedProcessLauncherDelegate::GetEnvironment() {
return base::EnvironmentMap();
diff --git a/chromium/content/public/common/sandboxed_process_launcher_delegate.h b/chromium/content/public/common/sandboxed_process_launcher_delegate.h
index a3aa4e06426..9dfcb3267c0 100644
--- a/chromium/content/public/common/sandboxed_process_launcher_delegate.h
+++ b/chromium/content/public/common/sandboxed_process_launcher_delegate.h
@@ -5,12 +5,15 @@
#ifndef CONTENT_PUBLIC_COMMON_SANDBOXED_PROCESS_LAUNCHER_DELEGATE_H_
#define CONTENT_PUBLIC_COMMON_SANDBOXED_PROCESS_LAUNCHER_DELEGATE_H_
+#include <cstddef>
+
#include "base/environment.h"
#include "base/files/scoped_file.h"
#include "base/process/process.h"
#include "build/build_config.h"
#include "content/common/content_export.h"
#include "content/public/common/sandbox_type.h"
+#include "content/public/common/zygote_handle.h"
namespace base {
class FilePath;
@@ -51,8 +54,10 @@ class CONTENT_EXPORT SandboxedProcessLauncherDelegate {
virtual void PostSpawnTarget(base::ProcessHandle process) {}
#elif defined(OS_POSIX)
+#if !defined(OS_MACOSX) && !defined(OS_ANDROID)
// Override this to return true to use the setuid sandbox.
- virtual bool ShouldUseZygote();
+ virtual ZygoteHandle* GetZygote();
+#endif // !defined(OS_MACOSX) && !defined(OS_ANDROID)
// Override this if the process needs a non-empty environment map.
virtual base::EnvironmentMap GetEnvironment();
diff --git a/chromium/content/public/common/service_registry.h b/chromium/content/public/common/service_registry.h
index ad8aaf0dada..41edc199ce7 100644
--- a/chromium/content/public/common/service_registry.h
+++ b/chromium/content/public/common/service_registry.h
@@ -60,6 +60,18 @@ class CONTENT_EXPORT ServiceRegistry {
virtual void ConnectToRemoteService(const base::StringPiece& name,
mojo::ScopedMessagePipeHandle handle) = 0;
+ // Registers a local service factory to intercept ConnectToRemoteService
+ // requests instead of actually connecting to the remote registry. Used only
+ // for testing.
+ virtual void AddServiceOverrideForTesting(
+ const std::string& service_name,
+ const base::Callback<void(mojo::ScopedMessagePipeHandle)>&
+ service_factory) = 0;
+
+ // Removes all local service factories registered
+ // by AddServiceOverrideForTesting. Used only for testing.
+ virtual void ClearServiceOverridesForTesting() = 0;
+
private:
template <typename Interface>
static void ForwardToServiceFactory(
diff --git a/chromium/content/public/common/service_worker_event_status.mojom b/chromium/content/public/common/service_worker_event_status.mojom
index 020d0e82e88..75aa593bffb 100644
--- a/chromium/content/public/common/service_worker_event_status.mojom
+++ b/chromium/content/public/common/service_worker_event_status.mojom
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-module content;
+module content.mojom;
enum ServiceWorkerEventStatus {
COMPLETED,
diff --git a/chromium/content/public/common/speech_recognition_result.cc b/chromium/content/public/common/speech_recognition_result.cc
index af05fc7e10b..9f4c2ca8a9f 100644
--- a/chromium/content/public/common/speech_recognition_result.cc
+++ b/chromium/content/public/common/speech_recognition_result.cc
@@ -10,6 +10,9 @@ SpeechRecognitionResult::SpeechRecognitionResult()
: is_provisional(false) {
}
+SpeechRecognitionResult::SpeechRecognitionResult(
+ const SpeechRecognitionResult& other) = default;
+
SpeechRecognitionResult::~SpeechRecognitionResult() {
}
diff --git a/chromium/content/public/common/speech_recognition_result.h b/chromium/content/public/common/speech_recognition_result.h
index 980abddd010..6c3f2ab3dde 100644
--- a/chromium/content/public/common/speech_recognition_result.h
+++ b/chromium/content/public/common/speech_recognition_result.h
@@ -33,6 +33,7 @@ struct CONTENT_EXPORT SpeechRecognitionResult {
bool is_provisional;
SpeechRecognitionResult();
+ SpeechRecognitionResult(const SpeechRecognitionResult& other);
~SpeechRecognitionResult();
};
diff --git a/chromium/content/public/common/ssl_status.cc b/chromium/content/public/common/ssl_status.cc
index eaaed4138c3..3490a81c46a 100644
--- a/chromium/content/public/common/ssl_status.cc
+++ b/chromium/content/public/common/ssl_status.cc
@@ -32,6 +32,8 @@ SSLStatus::SSLStatus(SecurityStyle security_style,
content_status(NORMAL_CONTENT),
signed_certificate_timestamp_ids(signed_certificate_timestamp_ids) {}
+SSLStatus::SSLStatus(const SSLStatus& other) = default;
+
SSLStatus::~SSLStatus() {}
} // namespace content
diff --git a/chromium/content/public/common/ssl_status.h b/chromium/content/public/common/ssl_status.h
index bb3501c0a25..79c4ef40810 100644
--- a/chromium/content/public/common/ssl_status.h
+++ b/chromium/content/public/common/ssl_status.h
@@ -39,6 +39,7 @@ struct CONTENT_EXPORT SSLStatus {
const SignedCertificateTimestampIDStatusList&
signed_certificate_timestamp_ids,
const net::SSLInfo& ssl_info);
+ SSLStatus(const SSLStatus& other);
~SSLStatus();
bool Equals(const SSLStatus& status) const {
diff --git a/chromium/content/public/common/url_constants.cc b/chromium/content/public/common/url_constants.cc
index b0f73f68a3c..f3f298ceb32 100644
--- a/chromium/content/public/common/url_constants.cc
+++ b/chromium/content/public/common/url_constants.cc
@@ -41,6 +41,7 @@ const char kChromeUIBadCastCrashURL[] = "chrome://badcastcrash";
const char kChromeUIBrowserCrashURL[] = "chrome://inducebrowsercrashforrealz";
const char kChromeUIBrowserUIHang[] = "chrome://uithreadhang";
const char kChromeUICrashURL[] = "chrome://crash";
+const char kChromeUIDelayedBrowserUIHang[] = "chrome://delayeduithreadhang";
const char kChromeUIDumpURL[] = "chrome://crashdump";
const char kChromeUIGpuCleanURL[] = "chrome://gpuclean";
const char kChromeUIGpuCrashURL[] = "chrome://gpucrash";
@@ -51,8 +52,6 @@ const char kChromeUINetworkErrorURL[] = "chrome://network-error";
const char kChromeUINetworkErrorsListingURL[] = "chrome://network-errors";
const char kChromeUIPpapiFlashCrashURL[] = "chrome://ppapiflashcrash";
const char kChromeUIPpapiFlashHangURL[] = "chrome://ppapiflashhang";
-const char kChromeUIServiceWorkerInternalsURL[] =
- "chrome://serviceworker-internals";
// This error URL is loaded in normal web renderer processes, so it should not
// have a chrome:// scheme that might let it be confused with a WebUI page.
@@ -62,9 +61,4 @@ const char kChromeUINetworkViewCacheURL[] = "chrome://view-http-cache/";
const char kChromeUIResourcesURL[] = "chrome://resources/";
const char kChromeUIShorthangURL[] = "chrome://shorthang";
-// This URL is loaded when a page is swapped out and replaced by a page in a
-// different renderer process. It must have a unique origin that cannot be
-// scripted by other pages in the process.
-const char kSwappedOutURL[] = "swappedout://";
-
} // namespace content
diff --git a/chromium/content/public/common/url_constants.h b/chromium/content/public/common/url_constants.h
index 8efe57db871..cb49d5a7190 100644
--- a/chromium/content/public/common/url_constants.h
+++ b/chromium/content/public/common/url_constants.h
@@ -50,17 +50,17 @@ CONTENT_EXPORT extern const char kChromeUIBadCastCrashURL[];
CONTENT_EXPORT extern const char kChromeUIBrowserCrashURL[];
CONTENT_EXPORT extern const char kChromeUIBrowserUIHang[];
CONTENT_EXPORT extern const char kChromeUICrashURL[];
+CONTENT_EXPORT extern const char kChromeUIDelayedBrowserUIHang[];
CONTENT_EXPORT extern const char kChromeUIDumpURL[];
CONTENT_EXPORT extern const char kChromeUIGpuCleanURL[];
CONTENT_EXPORT extern const char kChromeUIGpuCrashURL[];
CONTENT_EXPORT extern const char kChromeUIGpuHangURL[];
CONTENT_EXPORT extern const char kChromeUIHangURL[];
CONTENT_EXPORT extern const char kChromeUIKillURL[];
-CONTENT_EXPORT extern const char kChromeUINetworkErrorURL[];
CONTENT_EXPORT extern const char kChromeUINetworkErrorsListingURL[];
+CONTENT_EXPORT extern const char kChromeUINetworkErrorURL[];
CONTENT_EXPORT extern const char kChromeUIPpapiFlashCrashURL[];
CONTENT_EXPORT extern const char kChromeUIPpapiFlashHangURL[];
-CONTENT_EXPORT extern const char kChromeUIServiceWorkerInternalsURL[];
// Special URL used to start a navigation to an error page.
CONTENT_EXPORT extern const char kUnreachableWebDataURL[];
@@ -70,9 +70,6 @@ CONTENT_EXPORT extern const char kChromeUINetworkViewCacheURL[];
CONTENT_EXPORT extern const char kChromeUIResourcesURL[];
CONTENT_EXPORT extern const char kChromeUIShorthangURL[];
-// Special URL used to swap out a view being rendered by another process.
-CONTENT_EXPORT extern const char kSwappedOutURL[];
-
} // namespace content
#endif // CONTENT_PUBLIC_COMMON_URL_CONSTANTS_H_
diff --git a/chromium/content/public/common/url_utils.cc b/chromium/content/public/common/url_utils.cc
index 40cd67c2481..4133cb01542 100644
--- a/chromium/content/public/common/url_utils.cc
+++ b/chromium/content/public/common/url_utils.cc
@@ -16,10 +16,7 @@ const char* const* GetSavableSchemes() {
}
bool HasWebUIScheme(const GURL& url) {
- return
-#if !defined(OS_IOS)
- url.SchemeIs(kChromeDevToolsScheme) ||
-#endif
+ return url.SchemeIs(kChromeDevToolsScheme) ||
url.SchemeIs(kChromeUIScheme);
}
diff --git a/chromium/content/public/common/web_preferences.cc b/chromium/content/public/common/web_preferences.cc
index 68ccbb4af14..c1cdd19a8ea 100644
--- a/chromium/content/public/common/web_preferences.cc
+++ b/chromium/content/public/common/web_preferences.cc
@@ -8,7 +8,6 @@
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "third_party/WebKit/public/web/WebSettings.h"
-#include "third_party/icu/source/common/unicode/uchar.h"
using blink::WebSettings;
@@ -17,51 +16,37 @@ namespace content {
// "Zyyy" is the ISO 15924 script code for undetermined script aka Common.
const char kCommonScript[] = "Zyyy";
-#define STATIC_ASSERT_MATCHING_ENUMS(content_name, blink_name) \
- static_assert( \
- static_cast<int>(content_name) == static_cast<int>(blink_name), \
- "mismatching enums: " #content_name)
+#define STATIC_ASSERT_ENUM(a, b) \
+ static_assert(static_cast<int>(a) == static_cast<int>(b), \
+ "mismatching enums: " #a)
-STATIC_ASSERT_MATCHING_ENUMS(EDITING_BEHAVIOR_MAC,
- WebSettings::EditingBehaviorMac);
-STATIC_ASSERT_MATCHING_ENUMS(EDITING_BEHAVIOR_WIN,
- WebSettings::EditingBehaviorWin);
-STATIC_ASSERT_MATCHING_ENUMS(EDITING_BEHAVIOR_UNIX,
- WebSettings::EditingBehaviorUnix);
-STATIC_ASSERT_MATCHING_ENUMS(EDITING_BEHAVIOR_ANDROID,
- WebSettings::EditingBehaviorAndroid);
+STATIC_ASSERT_ENUM(EDITING_BEHAVIOR_MAC, WebSettings::EditingBehaviorMac);
+STATIC_ASSERT_ENUM(EDITING_BEHAVIOR_WIN, WebSettings::EditingBehaviorWin);
+STATIC_ASSERT_ENUM(EDITING_BEHAVIOR_UNIX, WebSettings::EditingBehaviorUnix);
+STATIC_ASSERT_ENUM(EDITING_BEHAVIOR_ANDROID,
+ WebSettings::EditingBehaviorAndroid);
-STATIC_ASSERT_MATCHING_ENUMS(V8_CACHE_OPTIONS_DEFAULT,
- WebSettings::V8CacheOptionsDefault);
-STATIC_ASSERT_MATCHING_ENUMS(V8_CACHE_OPTIONS_NONE,
- WebSettings::V8CacheOptionsNone);
-STATIC_ASSERT_MATCHING_ENUMS(V8_CACHE_OPTIONS_PARSE,
- WebSettings::V8CacheOptionsParse);
-STATIC_ASSERT_MATCHING_ENUMS(V8_CACHE_OPTIONS_CODE,
- WebSettings::V8CacheOptionsCode);
-STATIC_ASSERT_MATCHING_ENUMS(V8_CACHE_OPTIONS_LAST,
- WebSettings::V8CacheOptionsCode);
+STATIC_ASSERT_ENUM(V8_CACHE_OPTIONS_DEFAULT,
+ WebSettings::V8CacheOptionsDefault);
+STATIC_ASSERT_ENUM(V8_CACHE_OPTIONS_NONE, WebSettings::V8CacheOptionsNone);
+STATIC_ASSERT_ENUM(V8_CACHE_OPTIONS_PARSE, WebSettings::V8CacheOptionsParse);
+STATIC_ASSERT_ENUM(V8_CACHE_OPTIONS_CODE, WebSettings::V8CacheOptionsCode);
+STATIC_ASSERT_ENUM(V8_CACHE_OPTIONS_LAST, WebSettings::V8CacheOptionsCode);
-STATIC_ASSERT_MATCHING_ENUMS(IMAGE_ANIMATION_POLICY_ALLOWED,
- WebSettings::ImageAnimationPolicyAllowed);
-STATIC_ASSERT_MATCHING_ENUMS(IMAGE_ANIMATION_POLICY_ANIMATION_ONCE,
- WebSettings::ImageAnimationPolicyAnimateOnce);
-STATIC_ASSERT_MATCHING_ENUMS(IMAGE_ANIMATION_POLICY_NO_ANIMATION,
- WebSettings::ImageAnimationPolicyNoAnimation);
+STATIC_ASSERT_ENUM(IMAGE_ANIMATION_POLICY_ALLOWED,
+ WebSettings::ImageAnimationPolicyAllowed);
+STATIC_ASSERT_ENUM(IMAGE_ANIMATION_POLICY_ANIMATION_ONCE,
+ WebSettings::ImageAnimationPolicyAnimateOnce);
+STATIC_ASSERT_ENUM(IMAGE_ANIMATION_POLICY_NO_ANIMATION,
+ WebSettings::ImageAnimationPolicyNoAnimation);
-STATIC_ASSERT_MATCHING_ENUMS(ui::POINTER_TYPE_NONE,
- blink::PointerTypeNone);
-STATIC_ASSERT_MATCHING_ENUMS(ui::POINTER_TYPE_COARSE,
- blink::PointerTypeCoarse);
-STATIC_ASSERT_MATCHING_ENUMS(ui::POINTER_TYPE_FINE,
- blink::PointerTypeFine);
+STATIC_ASSERT_ENUM(ui::POINTER_TYPE_NONE, blink::PointerTypeNone);
+STATIC_ASSERT_ENUM(ui::POINTER_TYPE_COARSE, blink::PointerTypeCoarse);
+STATIC_ASSERT_ENUM(ui::POINTER_TYPE_FINE, blink::PointerTypeFine);
-STATIC_ASSERT_MATCHING_ENUMS(ui::HOVER_TYPE_NONE,
- blink::HoverTypeNone);
-STATIC_ASSERT_MATCHING_ENUMS(ui::HOVER_TYPE_ON_DEMAND,
- blink::HoverTypeOnDemand);
-STATIC_ASSERT_MATCHING_ENUMS(ui::HOVER_TYPE_HOVER,
- blink::HoverTypeHover);
+STATIC_ASSERT_ENUM(ui::HOVER_TYPE_NONE, blink::HoverTypeNone);
+STATIC_ASSERT_ENUM(ui::HOVER_TYPE_ON_DEMAND, blink::HoverTypeOnDemand);
+STATIC_ASSERT_ENUM(ui::HOVER_TYPE_HOVER, blink::HoverTypeHover);
WebPreferences::WebPreferences()
: default_font_size(16),
@@ -99,13 +84,11 @@ WebPreferences::WebPreferences()
hyperlink_auditing_enabled(true),
allow_universal_access_from_file_urls(false),
allow_file_access_from_file_urls(false),
- webaudio_enabled(false),
experimental_webgl_enabled(false),
pepper_3d_enabled(false),
flash_3d_enabled(true),
flash_stage3d_enabled(false),
flash_stage3d_baseline_enabled(false),
- gl_multisampling_enabled(true),
privileged_webgl_extensions_enabled(false),
webgl_errors_to_console_enabled(true),
mock_scrollbars_enabled(false),
@@ -124,6 +107,7 @@ WebPreferences::WebPreferences()
disable_reading_from_canvas(false),
strict_mixed_content_checking(false),
strict_powerful_feature_restrictions(false),
+ allow_geolocation_on_insecure_origins(false),
strictly_block_blockable_mixed_content(false),
block_mixed_plugin_content(false),
password_echo_enabled(false),
@@ -174,9 +158,12 @@ WebPreferences::WebPreferences()
navigate_on_drag_drop(true),
v8_cache_options(V8_CACHE_OPTIONS_DEFAULT),
inert_visual_viewport(false),
+ record_whole_document(false),
cookie_enabled(true),
pepper_accelerated_video_decode_enabled(false),
animation_policy(IMAGE_ANIMATION_POLICY_ALLOWED),
+ user_gesture_required_for_presentation(true),
+ text_track_margin_percentage(0.0f),
#if defined(OS_ANDROID)
text_autosizing_enabled(true),
font_scale_factor(1.0f),
@@ -197,7 +184,7 @@ WebPreferences::WebPreferences()
clobber_user_agent_initial_scale_quirk(false),
ignore_main_frame_overflow_hidden_quirk(false),
report_screen_size_in_physical_pixels_quirk(false),
- record_whole_document(false),
+ resue_global_for_unowned_main_frame(false),
#endif
#if defined(OS_ANDROID)
default_minimum_page_scale_factor(0.25f),
@@ -221,6 +208,8 @@ WebPreferences::WebPreferences()
base::ASCIIToUTF16("Times New Roman");
}
+WebPreferences::WebPreferences(const WebPreferences& other) = default;
+
WebPreferences::~WebPreferences() {
}
diff --git a/chromium/content/public/common/web_preferences.h b/chromium/content/public/common/web_preferences.h
index b7844432874..7b72351b187 100644
--- a/chromium/content/public/common/web_preferences.h
+++ b/chromium/content/public/common/web_preferences.h
@@ -107,13 +107,11 @@ struct CONTENT_EXPORT WebPreferences {
bool hyperlink_auditing_enabled;
bool allow_universal_access_from_file_urls;
bool allow_file_access_from_file_urls;
- bool webaudio_enabled;
bool experimental_webgl_enabled;
bool pepper_3d_enabled;
bool flash_3d_enabled;
bool flash_stage3d_enabled;
bool flash_stage3d_baseline_enabled;
- bool gl_multisampling_enabled;
bool privileged_webgl_extensions_enabled;
bool webgl_errors_to_console_enabled;
bool mock_scrollbars_enabled;
@@ -136,9 +134,11 @@ struct CONTENT_EXPORT WebPreferences {
// requested (thereby preventing user override).
bool strict_mixed_content_checking;
// Strict powerful feature restrictions block insecure usage of powerful
- // features (like geolocation) that we haven't yet disabled for the web at
- // large.
+ // features (like device orientation) that we haven't yet disabled for the web
+ // at large.
bool strict_powerful_feature_restrictions;
+ // TODO(jww): Remove when WebView no longer needs this exception.
+ bool allow_geolocation_on_insecure_origins;
// Disallow user opt-in for blockable mixed content.
bool strictly_block_blockable_mixed_content;
bool block_mixed_plugin_content;
@@ -175,6 +175,7 @@ struct CONTENT_EXPORT WebPreferences {
bool navigate_on_drag_drop;
V8CacheOptions v8_cache_options;
bool inert_visual_viewport;
+ bool record_whole_document;
// This flags corresponds to a Page's Settings' setCookieEnabled state. It
// only controls whether or not the "document.cookie" field is properly
@@ -189,6 +190,13 @@ struct CONTENT_EXPORT WebPreferences {
ImageAnimationPolicy animation_policy;
+ bool user_gesture_required_for_presentation;
+
+ // Specifies the margin for WebVTT text tracks as a percentage of media
+ // element height/width (for horizontal/vertical text respectively).
+ // Cues will not be placed in this margin area.
+ float text_track_margin_percentage;
+
#if defined(OS_ANDROID)
bool text_autosizing_enabled;
float font_scale_factor;
@@ -210,7 +218,9 @@ struct CONTENT_EXPORT WebPreferences {
bool clobber_user_agent_initial_scale_quirk;
bool ignore_main_frame_overflow_hidden_quirk;
bool report_screen_size_in_physical_pixels_quirk;
- bool record_whole_document;
+ // Used by Android_WebView only to support legacy apps that inject script into
+ // a top-level initial empty document and expect it to persist on navigation.
+ bool resue_global_for_unowned_main_frame;
std::string autoplay_experiment_mode;
#endif
@@ -224,6 +234,7 @@ struct CONTENT_EXPORT WebPreferences {
// chrome, except for the cases where it would require lots of extra work for
// the embedder to use the same default value.
WebPreferences();
+ WebPreferences(const WebPreferences& other);
~WebPreferences();
};
diff --git a/chromium/content/public/common/webplugininfo.cc b/chromium/content/public/common/webplugininfo.cc
index 95a7bfc5257..39c02c6cd21 100644
--- a/chromium/content/public/common/webplugininfo.cc
+++ b/chromium/content/public/common/webplugininfo.cc
@@ -27,10 +27,12 @@ WebPluginMimeType::WebPluginMimeType(const std::string& m,
file_extensions.push_back(f);
}
+WebPluginMimeType::WebPluginMimeType(const WebPluginMimeType& other) = default;
+
WebPluginMimeType::~WebPluginMimeType() {}
WebPluginInfo::WebPluginInfo()
- : type(PLUGIN_TYPE_NPAPI),
+ : type(PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS),
pepper_permissions(0) {
}
@@ -66,7 +68,7 @@ WebPluginInfo::WebPluginInfo(const base::string16& fake_name,
version(fake_version),
desc(fake_desc),
mime_types(),
- type(PLUGIN_TYPE_NPAPI),
+ type(PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS),
pepper_permissions(0) {
}
diff --git a/chromium/content/public/common/webplugininfo.h b/chromium/content/public/common/webplugininfo.h
index f487a4eb875..3fb1998f4e0 100644
--- a/chromium/content/public/common/webplugininfo.h
+++ b/chromium/content/public/common/webplugininfo.h
@@ -26,6 +26,7 @@ struct CONTENT_EXPORT WebPluginMimeType {
WebPluginMimeType(const std::string& m,
const std::string& f,
const std::string& d);
+ WebPluginMimeType(const WebPluginMimeType& other);
~WebPluginMimeType();
// The name of the mime type (e.g., "application/x-shockwave-flash").
@@ -45,7 +46,6 @@ struct CONTENT_EXPORT WebPluginMimeType {
// Describes an available NPAPI or Pepper plugin.
struct CONTENT_EXPORT WebPluginInfo {
enum PluginType {
- PLUGIN_TYPE_NPAPI,
PLUGIN_TYPE_PEPPER_IN_PROCESS,
PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS,
PLUGIN_TYPE_BROWSER_PLUGIN
diff --git a/chromium/content/public/common/zygote_fork_delegate_linux.h b/chromium/content/public/common/zygote_fork_delegate_linux.h
index 2f2f0b2a55c..ad87c6278a6 100644
--- a/chromium/content/public/common/zygote_fork_delegate_linux.h
+++ b/chromium/content/public/common/zygote_fork_delegate_linux.h
@@ -56,6 +56,7 @@ class ZygoteForkDelegate {
// The child process is required to write to the socket after
// successfully forking.
kPIDOracleFDIndex,
+ kMojoParentFDIndex,
kNumPassedFDs // Number of FDs in the vector passed to Fork().
};
diff --git a/chromium/content/public/common/zygote_handle.h b/chromium/content/public/common/zygote_handle.h
new file mode 100644
index 00000000000..9aa07c42454
--- /dev/null
+++ b/chromium/content/public/common/zygote_handle.h
@@ -0,0 +1,23 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_COMMON_ZYGOTE_HANDLE_H_
+#define CONTENT_PUBLIC_COMMON_ZYGOTE_HANDLE_H_
+
+#include <cstddef>
+
+#include "build/build_config.h"
+
+namespace content {
+
+#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_MACOSX)
+class ZygoteCommunication;
+using ZygoteHandle = ZygoteCommunication*;
+#else
+using ZygoteHandle = std::nullptr_t;
+#endif
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_COMMON_ZYGOTE_HANDLE_H_
diff --git a/chromium/content/public/gpu/BUILD.gn b/chromium/content/public/gpu/BUILD.gn
new file mode 100644
index 00000000000..e240a1ea9c1
--- /dev/null
+++ b/chromium/content/public/gpu/BUILD.gn
@@ -0,0 +1,42 @@
+# Copyright 2016 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# See //content/BUILD.gn for how this works.
+group("gpu") {
+ if (is_component_build) {
+ public_deps = [
+ "//content",
+ ]
+ } else {
+ public_deps = [
+ ":gpu_sources",
+ ]
+ }
+}
+
+source_set("gpu_sources") {
+ # You must depend on this via //content/public/gpu above for the component
+ # build to work properly.
+ visibility = [ "//content/*" ]
+
+ configs += [ "//content:content_implementation" ]
+
+ sources = [
+ "content_gpu_client.h",
+ "gpu_video_decode_accelerator_factory.cc",
+ "gpu_video_decode_accelerator_factory.h",
+ ]
+
+ deps = [
+ "//base",
+ "//content:export",
+ "//content/gpu:gpu_sources",
+ "//content/public/common:common_sources",
+ "//gpu/command_buffer/service",
+ "//gpu/config",
+ "//media:media",
+ ]
+
+ allow_circular_includes_from = [ "//content/gpu:gpu_sources" ]
+}
diff --git a/chromium/content/public/gpu/DEPS b/chromium/content/public/gpu/DEPS
new file mode 100644
index 00000000000..21c9bfc3ee3
--- /dev/null
+++ b/chromium/content/public/gpu/DEPS
@@ -0,0 +1,10 @@
+specific_include_rules = {
+ ".*\.cc": [
+ "+content/common",
+ "+content/gpu",
+ ],
+ "gpu_video_decode_accelerator_factory.h": [
+ "+gpu",
+ "+media",
+ ],
+}
diff --git a/chromium/content/public/gpu/content_gpu_client.h b/chromium/content/public/gpu/content_gpu_client.h
new file mode 100644
index 00000000000..3b0095b1f94
--- /dev/null
+++ b/chromium/content/public/gpu/content_gpu_client.h
@@ -0,0 +1,27 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_GPU_CONTENT_GPU_CLIENT_H_
+#define CONTENT_PUBLIC_GPU_CONTENT_GPU_CLIENT_H_
+
+#include "content/public/common/content_client.h"
+
+namespace content {
+
+class ServiceRegistry;
+
+// Embedder API for participating in gpu logic.
+class CONTENT_EXPORT ContentGpuClient {
+ public:
+ virtual ~ContentGpuClient() {}
+
+ // Allows client to register Mojo services in |registry| on the GPU process.
+ // The registered services will be exposed to the browser process through
+ // GpuProcessHost.
+ virtual void RegisterMojoServices(ServiceRegistry* registry) {}
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_GPU_CONTENT_GPU_CLIENT_H_
diff --git a/chromium/content/public/gpu/gpu_video_decode_accelerator_factory.cc b/chromium/content/public/gpu/gpu_video_decode_accelerator_factory.cc
new file mode 100644
index 00000000000..6d6e4c3497a
--- /dev/null
+++ b/chromium/content/public/gpu/gpu_video_decode_accelerator_factory.cc
@@ -0,0 +1,72 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/gpu/gpu_video_decode_accelerator_factory.h"
+
+#include "content/common/gpu/media/gpu_video_decode_accelerator_factory_impl.h"
+#include "content/gpu/gpu_child_thread.h"
+
+namespace content {
+
+GpuVideoDecodeAcceleratorFactory::~GpuVideoDecodeAcceleratorFactory() {}
+
+// static
+scoped_ptr<GpuVideoDecodeAcceleratorFactory>
+GpuVideoDecodeAcceleratorFactory::Create(
+ const GetGLContextCallback& get_gl_context_cb,
+ const MakeGLContextCurrentCallback& make_context_current_cb,
+ const BindGLImageCallback& bind_image_cb) {
+ auto gvdafactory_impl = GpuVideoDecodeAcceleratorFactoryImpl::Create(
+ get_gl_context_cb, make_context_current_cb, bind_image_cb);
+ if (!gvdafactory_impl)
+ return nullptr;
+
+ return make_scoped_ptr(
+ new GpuVideoDecodeAcceleratorFactory(std::move(gvdafactory_impl)));
+}
+
+// static
+scoped_ptr<GpuVideoDecodeAcceleratorFactory>
+GpuVideoDecodeAcceleratorFactory::CreateWithGLES2Decoder(
+ const GetGLContextCallback& get_gl_context_cb,
+ const MakeGLContextCurrentCallback& make_context_current_cb,
+ const BindGLImageCallback& bind_image_cb,
+ const GetGLES2DecoderCallback& get_gles2_decoder_cb) {
+ auto gvdafactory_impl =
+ GpuVideoDecodeAcceleratorFactoryImpl::CreateWithGLES2Decoder(
+ get_gl_context_cb, make_context_current_cb, bind_image_cb,
+ get_gles2_decoder_cb);
+ if (!gvdafactory_impl)
+ return nullptr;
+
+ return make_scoped_ptr(
+ new GpuVideoDecodeAcceleratorFactory(std::move(gvdafactory_impl)));
+}
+
+// static
+gpu::VideoDecodeAcceleratorCapabilities
+GpuVideoDecodeAcceleratorFactory::GetDecoderCapabilities() {
+ const gpu::GpuPreferences gpu_preferences =
+ GpuChildThread::current()->gpu_preferences();
+ return GpuVideoDecodeAcceleratorFactoryImpl::GetDecoderCapabilities(
+ gpu_preferences);
+}
+
+scoped_ptr<media::VideoDecodeAccelerator>
+GpuVideoDecodeAcceleratorFactory::CreateVDA(
+ media::VideoDecodeAccelerator::Client* client,
+ const media::VideoDecodeAccelerator::Config& config) {
+ if (!gvdafactory_impl_)
+ return nullptr;
+
+ const gpu::GpuPreferences gpu_preferences =
+ GpuChildThread::current()->gpu_preferences();
+ return gvdafactory_impl_->CreateVDA(client, config, gpu_preferences);
+}
+
+GpuVideoDecodeAcceleratorFactory::GpuVideoDecodeAcceleratorFactory(
+ scoped_ptr<GpuVideoDecodeAcceleratorFactoryImpl> gvdafactory_impl)
+ : gvdafactory_impl_(std::move(gvdafactory_impl)) {}
+
+} // namespace content
diff --git a/chromium/content/public/gpu/gpu_video_decode_accelerator_factory.h b/chromium/content/public/gpu/gpu_video_decode_accelerator_factory.h
new file mode 100644
index 00000000000..fe449546791
--- /dev/null
+++ b/chromium/content/public/gpu/gpu_video_decode_accelerator_factory.h
@@ -0,0 +1,93 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_GPU_GPU_VIDEO_DECODE_ACCELERATOR_FACTORY_H_
+#define CONTENT_PUBLIC_GPU_GPU_VIDEO_DECODE_ACCELERATOR_FACTORY_H_
+
+#include "base/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "content/common/content_export.h"
+#include "gpu/config/gpu_info.h"
+#include "media/video/video_decode_accelerator.h"
+
+namespace gfx {
+class GLContext;
+}
+
+namespace gl {
+class GLImage;
+}
+
+namespace gpu {
+namespace gles2 {
+class GLES2Decoder;
+}
+}
+
+namespace content {
+
+class GpuVideoDecodeAcceleratorFactoryImpl;
+
+// This factory allows creation of VideoDecodeAccelerator implementations,
+// providing the most applicable VDA for current platform and given
+// configuration. To be used in GPU process only.
+class CONTENT_EXPORT GpuVideoDecodeAcceleratorFactory {
+ public:
+ virtual ~GpuVideoDecodeAcceleratorFactory();
+
+ // Return current GLContext.
+ using GetGLContextCallback = base::Callback<gfx::GLContext*(void)>;
+
+ // Make the applicable GL context current. To be called by VDAs before
+ // executing any GL calls. Return true on success, false otherwise.
+ using MakeGLContextCurrentCallback = base::Callback<bool(void)>;
+
+ // Bind |image| to |client_texture_id| given |texture_target|. If
+ // |can_bind_to_sampler| is true, then the image may be used as a sampler
+ // directly, otherwise a copy to a staging buffer is required.
+ // Return true on success, false otherwise.
+ using BindGLImageCallback =
+ base::Callback<bool(uint32_t client_texture_id,
+ uint32_t texture_target,
+ const scoped_refptr<gl::GLImage>& image,
+ bool can_bind_to_sampler)>;
+
+ // Return a WeakPtr to a GLES2Decoder, if one is available.
+ using GetGLES2DecoderCallback =
+ base::Callback<base::WeakPtr<gpu::gles2::GLES2Decoder>(void)>;
+
+ // Create a factory capable of producing VDA instances for current platform.
+ static scoped_ptr<GpuVideoDecodeAcceleratorFactory> Create(
+ const GetGLContextCallback& get_gl_context_cb,
+ const MakeGLContextCurrentCallback& make_context_current_cb,
+ const BindGLImageCallback& bind_image_cb);
+
+ static scoped_ptr<GpuVideoDecodeAcceleratorFactory> CreateWithGLES2Decoder(
+ const GetGLContextCallback& get_gl_context_cb,
+ const MakeGLContextCurrentCallback& make_context_current_cb,
+ const BindGLImageCallback& bind_image_cb,
+ const GetGLES2DecoderCallback& get_gles2_decoder_cb);
+
+ // Return decoder capabilities supported on the current platform.
+ static gpu::VideoDecodeAcceleratorCapabilities GetDecoderCapabilities();
+
+ // Create a VDA for the current platform for |client| with the given |config|
+ // and for given |gpu_preferences|. Return nullptr on failure.
+ virtual scoped_ptr<media::VideoDecodeAccelerator> CreateVDA(
+ media::VideoDecodeAccelerator::Client* client,
+ const media::VideoDecodeAccelerator::Config& config);
+
+ private:
+ // TODO(posciak): This is temporary and will not be needed once
+ // GpuVideoDecodeAcceleratorFactoryImpl implements
+ // GpuVideoDecodeAcceleratorFactory, see crbug.com/597150 and related.
+ GpuVideoDecodeAcceleratorFactory(
+ scoped_ptr<GpuVideoDecodeAcceleratorFactoryImpl> gvdafactory_impl);
+
+ scoped_ptr<GpuVideoDecodeAcceleratorFactoryImpl> gvdafactory_impl_;
+};
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_GPU_GPU_VIDEO_DECODE_ACCELERATOR_FACTORY_H_
diff --git a/chromium/content/public/plugin/BUILD.gn b/chromium/content/public/plugin/BUILD.gn
deleted file mode 100644
index e4c4d368193..00000000000
--- a/chromium/content/public/plugin/BUILD.gn
+++ /dev/null
@@ -1,30 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-# See //content/BUILD.gn for how this works.
-group("plugin") {
- if (is_component_build) {
- public_deps = [
- "//content",
- ]
- } else {
- public_deps = [
- ":plugin_sources",
- ]
- }
-}
-
-source_set("plugin_sources") {
- visibility = [ "//content/*" ]
-
- sources = [
- "content_plugin_client.h",
- ]
-
- deps = [
- "//base",
- "//content/plugin",
- "//content/public/common:common_sources",
- ]
-}
diff --git a/chromium/content/public/plugin/content_plugin_client.h b/chromium/content/public/plugin/content_plugin_client.h
deleted file mode 100644
index f68c3ad56f6..00000000000
--- a/chromium/content/public/plugin/content_plugin_client.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_PUBLIC_PLUGIN_CONTENT_PLUGIN_CLIENT_H_
-#define CONTENT_PUBLIC_PLUGIN_CONTENT_PLUGIN_CLIENT_H_
-
-#include "base/strings/string16.h"
-#include "content/public/common/content_client.h"
-
-namespace content {
-
-// Embedder API for participating in plugin logic.
-class CONTENT_EXPORT ContentPluginClient {
- public:
- virtual ~ContentPluginClient() {}
-
- // Called to perform any per-process initialization necessary before
- // the sandbox is initialized for the plugin process.
- virtual void PreSandboxInitialization() {}
-
- // Notifies that a plugin process has started.
- virtual void PluginProcessStarted(const base::string16& plugin_name) {}
-};
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_PLUGIN_CONTENT_PLUGIN_CLIENT_H_
diff --git a/chromium/content/public/renderer/BUILD.gn b/chromium/content/public/renderer/BUILD.gn
index 719eadf6771..75d44398960 100644
--- a/chromium/content/public/renderer/BUILD.gn
+++ b/chromium/content/public/renderer/BUILD.gn
@@ -19,6 +19,7 @@ group("renderer") {
}
source_set("renderer_sources") {
+ # External code should depend on via ":renderer" above.
visibility = [ "//content/*" ]
sources = rebase_path(content_renderer_gypi_values.public_renderer_sources,
@@ -28,12 +29,20 @@ source_set("renderer_sources") {
configs += [ "//content:content_implementation" ]
deps = [
+ "//content/public/child:child_sources",
"//content/public/common:common_sources",
"//content/renderer",
+ "//gin",
+ "//media",
+ "//media/gpu/ipc/client",
+ "//net",
+ "//ppapi/c",
"//skia",
"//third_party/WebKit/public:blink_headers",
"//third_party/libjingle",
"//third_party/widevine/cdm:version_h",
+ "//ui/base",
+ "//ui/base/ime",
"//ui/gfx",
"//v8",
]
@@ -49,7 +58,11 @@ source_set("renderer_sources") {
rebase_path(content_renderer_gypi_values.public_renderer_webrtc_sources,
".",
"//content")
- deps += [ "//third_party/webrtc" ]
+ deps += [
+ "//content/public/common:feature_h264_with_openh264_ffmpeg",
+ "//content/public/common:features",
+ "//third_party/webrtc",
+ ]
}
if (enable_plugins) {
diff --git a/chromium/content/public/renderer/DEPS b/chromium/content/public/renderer/DEPS
index 0e936afdb9d..1ad8a8ad199 100644
--- a/chromium/content/public/renderer/DEPS
+++ b/chromium/content/public/renderer/DEPS
@@ -2,6 +2,7 @@ include_rules = [
"+content/common/media",
"+content/public/child",
"+media/base",
+ "+media/gpu/ipc/client",
"+media/renderers",
"+media/video",
"+gin",
diff --git a/chromium/content/public/renderer/content_renderer_client.cc b/chromium/content/public/renderer/content_renderer_client.cc
index 3d0316f068f..a1389fc5808 100644
--- a/chromium/content/public/renderer/content_renderer_client.cc
+++ b/chromium/content/public/renderer/content_renderer_client.cc
@@ -98,7 +98,7 @@ bool ContentRendererClient::AllowPopup() {
return false;
}
-#ifdef OS_ANDROID
+#if defined(OS_ANDROID)
bool ContentRendererClient::HandleNavigation(
RenderFrame* render_frame,
bool is_content_initiated,
@@ -110,6 +110,10 @@ bool ContentRendererClient::HandleNavigation(
bool is_redirect) {
return false;
}
+
+bool ContentRendererClient::ShouldUseMediaPlayerForURL(const GURL& url) {
+ return false;
+}
#endif
bool ContentRendererClient::ShouldFork(blink::WebLocalFrame* frame,
@@ -150,11 +154,6 @@ bool ContentRendererClient::ShouldOverridePageVisibilityState(
return false;
}
-const void* ContentRendererClient::CreatePPAPIInterface(
- const std::string& interface_name) {
- return nullptr;
-}
-
bool ContentRendererClient::IsExternalPepperPlugin(
const std::string& module_name) {
return false;
@@ -181,6 +180,11 @@ ContentRendererClient::CreateMediaStreamRendererFactory() {
return nullptr;
}
+cc::ImageSerializationProcessor*
+ContentRendererClient::GetImageSerializationProcessor() {
+ return nullptr;
+}
+
bool ContentRendererClient::ShouldReportDetailedMessageForSource(
const base::string16& source) const {
return false;
diff --git a/chromium/content/public/renderer/content_renderer_client.h b/chromium/content/public/renderer/content_renderer_client.h
index 45686b56691..0fab0377ad0 100644
--- a/chromium/content/public/renderer/content_renderer_client.h
+++ b/chromium/content/public/renderer/content_renderer_client.h
@@ -14,8 +14,8 @@
#include "base/bind.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
+#include "build/build_config.h"
#include "content/public/common/content_client.h"
#include "third_party/WebKit/public/platform/WebPageVisibilityState.h"
#include "third_party/WebKit/public/web/WebNavigationPolicy.h"
@@ -56,6 +56,10 @@ struct WebPluginParams;
struct WebURLError;
}
+namespace cc {
+class ImageSerializationProcessor;
+}
+
namespace media {
class GpuVideoAcceleratorFactories;
class MediaLog;
@@ -104,6 +108,8 @@ class CONTENT_EXPORT ContentRendererClient {
// Creates a replacement plugin that is shown when the plugin at |file_path|
// couldn't be loaded. This allows the embedder to show a custom placeholder.
+ // This may return nullptr. However, if it does return a WebPlugin, it must
+ // never fail to initialize.
virtual blink::WebPlugin* CreatePluginReplacement(
RenderFrame* render_frame,
const base::FilePath& plugin_path);
@@ -194,7 +200,7 @@ class CONTENT_EXPORT ContentRendererClient {
// Returns true if a popup window should be allowed.
virtual bool AllowPopup();
-#ifdef OS_ANDROID
+#if defined(OS_ANDROID)
// TODO(sgurun) This callback is deprecated and will be removed as soon
// as android webview completes implementation of a resource throttle based
// shouldoverrideurl implementation. See crbug.com/325351
@@ -209,6 +215,10 @@ class CONTENT_EXPORT ContentRendererClient {
blink::WebNavigationType type,
blink::WebNavigationPolicy default_policy,
bool is_redirect);
+
+ // Indicates if the Android MediaPlayer should be used instead of Chrome's
+ // built in media player for the given |url|. Defaults to false.
+ virtual bool ShouldUseMediaPlayerForURL(const GURL& url);
#endif
// Returns true if we should fork a new process for the given navigation.
@@ -239,10 +249,6 @@ class CONTENT_EXPORT ContentRendererClient {
const RenderFrame* render_frame,
blink::WebPageVisibilityState* override_state);
- // Allows an embedder to return custom PPAPI interfaces.
- virtual const void* CreatePPAPIInterface(
- const std::string& interface_name);
-
// Returns true if the given Pepper plugin is external (requiring special
// startup steps).
virtual bool IsExternalPepperPlugin(const std::string& module_name);
@@ -260,6 +266,9 @@ class CONTENT_EXPORT ContentRendererClient {
virtual scoped_ptr<MediaStreamRendererFactory>
CreateMediaStreamRendererFactory();
+ // Allows an embedder to provde a cc::ImageSerializationProcessor.
+ virtual cc::ImageSerializationProcessor* GetImageSerializationProcessor();
+
// Gives the embedder a chance to register the key system(s) it supports by
// populating |key_systems|.
virtual void AddKeySystems(std::vector<media::KeySystemInfo>* key_systems);
@@ -309,6 +318,15 @@ class CONTENT_EXPORT ContentRendererClient {
const blink::WebURLResponse& response,
std::map<std::string, std::string>* properties) {}
+ // Notifies that a document element has been inserted in the frame's document.
+ // This may be called multiple times for the same document. This method may
+ // invalidate the frame.
+ virtual void RunScriptsAtDocumentStart(RenderFrame* render_frame) {}
+
+ // Notifies that the DOM is ready in the frame's document.
+ // This method may invalidate the frame.
+ virtual void RunScriptsAtDocumentEnd(RenderFrame* render_frame) {}
+
// Notifies that a service worker context has been created. This function
// is called from the worker thread.
virtual void DidInitializeServiceWorkerContextOnWorkerThread(
diff --git a/chromium/content/public/renderer/document_state.h b/chromium/content/public/renderer/document_state.h
index edb66bd358a..99beb47147e 100644
--- a/chromium/content/public/renderer/document_state.h
+++ b/chromium/content/public/renderer/document_state.h
@@ -45,7 +45,7 @@ class CONTENT_EXPORT DocumentState
~DocumentState() override;
static DocumentState* FromDataSource(blink::WebDataSource* ds) {
- return static_cast<DocumentState*>(ds->extraData());
+ return static_cast<DocumentState*>(ds->getExtraData());
}
// The time that this navigation was requested.
diff --git a/chromium/content/public/renderer/media_stream_api.cc b/chromium/content/public/renderer/media_stream_api.cc
deleted file mode 100644
index 9ec76b70310..00000000000
--- a/chromium/content/public/renderer/media_stream_api.cc
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/public/renderer/media_stream_api.h"
-
-#include <utility>
-
-#include "base/base64.h"
-#include "base/callback.h"
-#include "base/rand_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/renderer/media/media_stream_audio_source.h"
-#include "content/renderer/media/media_stream_video_capturer_source.h"
-#include "content/renderer/media/media_stream_video_track.h"
-#include "content/renderer/render_thread_impl.h"
-#include "third_party/WebKit/public/platform/WebMediaStream.h"
-#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
-#include "third_party/WebKit/public/platform/WebURL.h"
-#include "third_party/WebKit/public/web/WebMediaStreamRegistry.h"
-#include "url/gurl.h"
-
-namespace content {
-
-namespace {
-
-blink::WebString MakeTrackId() {
- std::string track_id;
- base::Base64Encode(base::RandBytesAsString(64), &track_id);
- return base::UTF8ToUTF16(track_id);
-}
-
-} // namespace
-
-bool AddVideoTrackToMediaStream(scoped_ptr<media::VideoCapturerSource> source,
- bool is_remote,
- bool is_readonly,
- const std::string& media_stream_url) {
- blink::WebMediaStream web_stream =
- blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(
- GURL(media_stream_url));
- return AddVideoTrackToMediaStream(std::move(source), is_remote, is_readonly,
- &web_stream);
-}
-
-bool AddVideoTrackToMediaStream(scoped_ptr<media::VideoCapturerSource> source,
- bool is_remote,
- bool is_readonly,
- blink::WebMediaStream* web_stream) {
- if (web_stream->isNull()) {
- DLOG(ERROR) << "Stream not found";
- return false;
- }
- const blink::WebString track_id = MakeTrackId();
- blink::WebMediaStreamSource webkit_source;
- scoped_ptr<MediaStreamVideoSource> media_stream_source(
- new MediaStreamVideoCapturerSource(
- MediaStreamSource::SourceStoppedCallback(), std::move(source)));
- webkit_source.initialize(track_id, blink::WebMediaStreamSource::TypeVideo,
- track_id, is_remote, is_readonly);
- webkit_source.setExtraData(media_stream_source.get());
-
- blink::WebMediaConstraints constraints;
- constraints.initialize();
- web_stream->addTrack(MediaStreamVideoTrack::CreateVideoTrack(
- media_stream_source.release(), constraints,
- MediaStreamVideoSource::ConstraintsCallback(), true));
- return true;
-}
-
-bool AddAudioTrackToMediaStream(
- const scoped_refptr<media::AudioCapturerSource>& source,
- const media::AudioParameters& params,
- bool is_remote,
- bool is_readonly,
- const std::string& media_stream_url) {
- DCHECK(params.IsValid()) << params.AsHumanReadableString();
- blink::WebMediaStream web_stream =
- blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(
- GURL(media_stream_url));
- return AddAudioTrackToMediaStream(source,
- is_remote, is_readonly, &web_stream);
-}
-
-bool AddAudioTrackToMediaStream(
- const scoped_refptr<media::AudioCapturerSource>& source,
- bool is_remote,
- bool is_readonly,
- blink::WebMediaStream* web_stream) {
- if (web_stream->isNull()) {
- DLOG(ERROR) << "Stream not found";
- return false;
- }
-
- media::AudioParameters params(
- media::AudioParameters::AUDIO_PCM_LINEAR, media::CHANNEL_LAYOUT_STEREO,
- 48000, /* sample rate */
- 16, /* bits per sample */
- 480); /* frames per buffer */
-
- blink::WebMediaStreamSource webkit_source;
- const blink::WebString track_id = MakeTrackId();
- webkit_source.initialize(track_id,
- blink::WebMediaStreamSource::TypeAudio,
- track_id,
- is_remote,
- is_readonly);
-
- MediaStreamAudioSource* audio_source(
- new MediaStreamAudioSource(
- -1,
- StreamDeviceInfo(),
- MediaStreamSource::SourceStoppedCallback(),
- RenderThreadImpl::current()->GetPeerConnectionDependencyFactory()));
-
- blink::WebMediaConstraints constraints;
- constraints.initialize();
- scoped_refptr<WebRtcAudioCapturer> capturer(
- WebRtcAudioCapturer::CreateCapturer(-1, StreamDeviceInfo(), constraints,
- nullptr, audio_source));
- capturer->SetCapturerSource(source, params);
- audio_source->SetAudioCapturer(capturer);
- webkit_source.setExtraData(audio_source);
-
- blink::WebMediaStreamTrack web_media_audio_track;
- web_media_audio_track.initialize(webkit_source);
- RenderThreadImpl::current()->GetPeerConnectionDependencyFactory()->
- CreateLocalAudioTrack(web_media_audio_track);
-
- web_stream->addTrack(web_media_audio_track);
- return true;
-}
-
-} // namespace content
diff --git a/chromium/content/public/renderer/media_stream_api.h b/chromium/content/public/renderer/media_stream_api.h
deleted file mode 100644
index dfb2aaf6ea1..00000000000
--- a/chromium/content/public/renderer/media_stream_api.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_PUBLIC_RENDERER_MEDIA_STREAM_API_H_
-#define CONTENT_PUBLIC_RENDERER_MEDIA_STREAM_API_H_
-
-#include "content/common/content_export.h"
-#include "media/base/audio_capturer_source.h"
-#include "media/base/video_capturer_source.h"
-
-namespace blink {
-class WebMediaStream;
-}
-
-namespace media {
-class AudioParameters;
-}
-
-namespace content {
-// These methods create a WebMediaStreamSource + MediaStreamSource pair with the
-// provided audio or video capturer source. A new WebMediaStreamTrack +
-// MediaStreamTrack pair is created, holding the previous MediaStreamSource, and
-// is plugged into the stream identified by |media_stream_url| (or passed as
-// |web_stream|).
-// |is_remote| should be true if the source of the data is not a local device.
-// |is_readonly| should be true if the format of the data cannot be changed by
-// MediaTrackConstraints.
-CONTENT_EXPORT bool AddVideoTrackToMediaStream(
- scoped_ptr<media::VideoCapturerSource> source,
- bool is_remote,
- bool is_readonly,
- const std::string& media_stream_url);
-CONTENT_EXPORT bool AddVideoTrackToMediaStream(
- scoped_ptr<media::VideoCapturerSource> source,
- bool is_remote,
- bool is_readonly,
- blink::WebMediaStream* web_stream);
-
-CONTENT_EXPORT bool AddAudioTrackToMediaStream(
- const scoped_refptr<media::AudioCapturerSource>& source,
- const media::AudioParameters& params,
- bool is_remote,
- bool is_readonly,
- const std::string& media_stream_url);
-CONTENT_EXPORT bool AddAudioTrackToMediaStream(
- const scoped_refptr<media::AudioCapturerSource>& source,
- bool is_remote,
- bool is_readonly,
- blink::WebMediaStream* web_stream);
-
-} // namespace content
-
-#endif // CONTENT_PUBLIC_RENDERER_MEDIA_STREAM_API_H_
diff --git a/chromium/content/public/renderer/media_stream_audio_renderer.h b/chromium/content/public/renderer/media_stream_audio_renderer.h
index 5a5d68d3d62..3061d6427f5 100644
--- a/chromium/content/public/renderer/media_stream_audio_renderer.h
+++ b/chromium/content/public/renderer/media_stream_audio_renderer.h
@@ -10,8 +10,8 @@
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
-#include "media/base/output_device.h"
-#include "url/gurl.h"
+#include "media/base/output_device_info.h"
+#include "url/origin.h"
namespace content {
@@ -34,12 +34,24 @@ class MediaStreamAudioRenderer
// Sets the output volume.
virtual void SetVolume(float volume) = 0;
- // Returns a pointer to the internal output device.
- // The pointer is not to be owned by the caller and is valid only during
- // the lifetime of the MediaStreamAudioRenderer.
- // It can be null, which means that access to the output device is not
- // supported.
- virtual media::OutputDevice* GetOutputDevice() = 0;
+ // Returns current output device information. If the information is not
+ // available yet, this method may block until it becomes available.
+ // If the renderer is not associated with any output device, |device_status|
+ // of OutputDeviceInfo should be set to OUTPUT_DEVICE_STATUS_ERROR_INTERNAL.
+ // Must never be called on the IO thread.
+ virtual media::OutputDeviceInfo GetOutputDeviceInfo() = 0;
+
+ // Attempts to switch the audio output device.
+ // Once the attempt is finished, |callback| is invoked with the result of the
+ // operation passed as a parameter. The result is a value from the
+ // media::OutputDeviceStatus enum.
+ // There is no guarantee about the thread where |callback| will be invoked.
+ // TODO(olka): make sure callback is always called on the client thread,
+ // update clients accordingly and fix the comment.
+ virtual void SwitchOutputDevice(
+ const std::string& device_id,
+ const url::Origin& security_origin,
+ const media::OutputDeviceStatusCB& callback) = 0;
// Time stamp that reflects the current render time. Should not be updated
// when paused.
diff --git a/chromium/content/public/renderer/media_stream_audio_sink.cc b/chromium/content/public/renderer/media_stream_audio_sink.cc
index a6e01a9c7cf..875a635939a 100644
--- a/chromium/content/public/renderer/media_stream_audio_sink.cc
+++ b/chromium/content/public/renderer/media_stream_audio_sink.cc
@@ -14,21 +14,24 @@ namespace content {
void MediaStreamAudioSink::AddToAudioTrack(
MediaStreamAudioSink* sink,
const blink::WebMediaStreamTrack& track) {
- DCHECK(track.source().type() == blink::WebMediaStreamSource::TypeAudio);
- MediaStreamAudioTrack* native_track = MediaStreamAudioTrack::GetTrack(track);
+ DCHECK(track.source().getType() == blink::WebMediaStreamSource::TypeAudio);
+ MediaStreamAudioTrack* native_track = MediaStreamAudioTrack::From(track);
+ DCHECK(native_track);
native_track->AddSink(sink);
}
void MediaStreamAudioSink::RemoveFromAudioTrack(
MediaStreamAudioSink* sink,
const blink::WebMediaStreamTrack& track) {
- MediaStreamAudioTrack* native_track = MediaStreamAudioTrack::GetTrack(track);
+ MediaStreamAudioTrack* native_track = MediaStreamAudioTrack::From(track);
+ DCHECK(native_track);
native_track->RemoveSink(sink);
}
media::AudioParameters MediaStreamAudioSink::GetFormatFromAudioTrack(
const blink::WebMediaStreamTrack& track) {
- MediaStreamAudioTrack* native_track = MediaStreamAudioTrack::GetTrack(track);
+ MediaStreamAudioTrack* native_track = MediaStreamAudioTrack::From(track);
+ DCHECK(native_track);
return native_track->GetOutputFormat();
}
diff --git a/chromium/content/public/renderer/media_stream_utils.cc b/chromium/content/public/renderer/media_stream_utils.cc
new file mode 100644
index 00000000000..5b91b182531
--- /dev/null
+++ b/chromium/content/public/renderer/media_stream_utils.cc
@@ -0,0 +1,139 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/public/renderer/media_stream_utils.h"
+
+#include <utility>
+
+#include "base/callback.h"
+#include "base/guid.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/rand_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/renderer/media/media_stream_audio_source.h"
+#include "content/renderer/media/media_stream_video_capturer_source.h"
+#include "content/renderer/media/media_stream_video_source.h"
+#include "content/renderer/media/media_stream_video_track.h"
+#include "content/renderer/render_thread_impl.h"
+#include "media/base/audio_capturer_source.h"
+#include "media/base/video_capturer_source.h"
+#include "third_party/WebKit/public/platform/WebMediaStream.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
+#include "third_party/WebKit/public/web/WebMediaStreamRegistry.h"
+
+namespace content {
+
+bool AddVideoTrackToMediaStream(
+ scoped_ptr<media::VideoCapturerSource> video_source,
+ bool is_remote,
+ bool is_readonly,
+ blink::WebMediaStream* web_media_stream) {
+ DCHECK(video_source.get());
+ if (!web_media_stream || web_media_stream->isNull()) {
+ DLOG(ERROR) << "WebMediaStream is null";
+ return false;
+ }
+
+ blink::WebMediaStreamSource web_media_stream_source;
+ MediaStreamVideoSource* const media_stream_source =
+ new MediaStreamVideoCapturerSource(
+ MediaStreamSource::SourceStoppedCallback(), std::move(video_source));
+ const blink::WebString track_id =
+ blink::WebString::fromUTF8(base::GenerateGUID());
+ web_media_stream_source.initialize(track_id,
+ blink::WebMediaStreamSource::TypeVideo,
+ track_id, is_remote, is_readonly);
+ // Takes ownership of |media_stream_source|.
+ web_media_stream_source.setExtraData(media_stream_source);
+
+ blink::WebMediaConstraints constraints;
+ constraints.initialize();
+ web_media_stream->addTrack(MediaStreamVideoTrack::CreateVideoTrack(
+ media_stream_source, constraints,
+ MediaStreamVideoSource::ConstraintsCallback(), true));
+ return true;
+}
+
+bool AddAudioTrackToMediaStream(
+ scoped_refptr<media::AudioCapturerSource> audio_source,
+ int sample_rate,
+ media::ChannelLayout channel_layout,
+ int frames_per_buffer,
+ bool is_remote,
+ bool is_readonly,
+ blink::WebMediaStream* web_media_stream) {
+ DCHECK(audio_source.get());
+ if (!web_media_stream || web_media_stream->isNull()) {
+ DLOG(ERROR) << "WebMediaStream is null";
+ return false;
+ }
+
+ const media::AudioParameters params(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
+ sample_rate, sizeof(int16_t) * 8, frames_per_buffer);
+ if (!params.IsValid()) {
+ DLOG(ERROR) << "Invalid audio parameters.";
+ return false;
+ }
+
+ blink::WebMediaStreamSource web_media_stream_source;
+ const blink::WebString track_id =
+ blink::WebString::fromUTF8(base::GenerateGUID());
+ web_media_stream_source.initialize(track_id,
+ blink::WebMediaStreamSource::TypeAudio,
+ track_id, is_remote, is_readonly);
+
+ MediaStreamAudioSource* media_stream_source(new MediaStreamAudioSource(
+ -1, StreamDeviceInfo(), MediaStreamSource::SourceStoppedCallback(),
+ RenderThreadImpl::current()->GetPeerConnectionDependencyFactory()));
+
+ blink::WebMediaConstraints constraints;
+ constraints.initialize();
+ {
+ // TODO(miu): In an upcoming change, a source purposed for passing audio
+ // directly (i.e., without modification) will replace this "hacky" use of
+ // WebRtcAudioCapturer. http://crbug.com/577881
+ scoped_ptr<WebRtcAudioCapturer> capturer(
+ WebRtcAudioCapturer::CreateCapturer(-1, StreamDeviceInfo(), constraints,
+ nullptr, media_stream_source));
+ capturer->SetCapturerSource(std::move(audio_source), params);
+ media_stream_source->SetAudioCapturer(std::move(capturer));
+ }
+ web_media_stream_source.setExtraData(
+ media_stream_source); // Takes ownership.
+
+ blink::WebMediaStreamTrack web_media_stream_track;
+ web_media_stream_track.initialize(web_media_stream_source);
+ RenderThreadImpl::current()
+ ->GetPeerConnectionDependencyFactory()
+ ->CreateLocalAudioTrack(web_media_stream_track);
+
+ web_media_stream->addTrack(web_media_stream_track);
+ return true;
+}
+
+const media::VideoCaptureFormat* GetCurrentVideoTrackFormat(
+ const blink::WebMediaStreamTrack& video_track) {
+ if (video_track.isNull())
+ return nullptr;
+
+ MediaStreamVideoSource* const source =
+ MediaStreamVideoSource::GetVideoSource(video_track.source());
+ if (!source)
+ return nullptr;
+
+ return source->GetCurrentFormat();
+}
+
+void RequestRefreshFrameFromVideoTrack(
+ const blink::WebMediaStreamTrack& video_track) {
+ if (video_track.isNull())
+ return;
+ MediaStreamVideoSource* const source =
+ MediaStreamVideoSource::GetVideoSource(video_track.source());
+ if (source)
+ source->RequestRefreshFrame();
+}
+
+} // namespace content
diff --git a/chromium/content/public/renderer/media_stream_utils.h b/chromium/content/public/renderer/media_stream_utils.h
new file mode 100644
index 00000000000..8b94b7222b9
--- /dev/null
+++ b/chromium/content/public/renderer/media_stream_utils.h
@@ -0,0 +1,64 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_PUBLIC_RENDERER_MEDIA_STREAM_UTILS_H_
+#define CONTENT_PUBLIC_RENDERER_MEDIA_STREAM_UTILS_H_
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "content/common/content_export.h"
+#include "media/base/channel_layout.h"
+#include "media/base/video_capture_types.h"
+
+namespace blink {
+class WebMediaStream;
+class WebMediaStreamTrack;
+}
+
+namespace media {
+class AudioCapturerSource;
+class VideoCapturerSource;
+}
+
+namespace content {
+// These methods create a WebMediaStreamSource + MediaStreamSource pair with the
+// provided audio or video capturer source. A new WebMediaStreamTrack +
+// MediaStreamTrack pair is created, connected to the source and is plugged into
+// the WebMediaStream (|web_media_stream|).
+// |is_remote| should be true if the source of the data is not a local device.
+// |is_readonly| should be true if the format of the data cannot be changed by
+// MediaTrackConstraints.
+CONTENT_EXPORT bool AddVideoTrackToMediaStream(
+ scoped_ptr<media::VideoCapturerSource> video_source,
+ bool is_remote,
+ bool is_readonly,
+ blink::WebMediaStream* web_media_stream);
+
+// |sample_rate|, |channel_layout|, and |frames_per_buffer| specify the audio
+// parameters of the track. Generally, these should match the |audio_source| so
+// that it does not have to perform unnecessary sample rate conversion or
+// channel mixing.
+CONTENT_EXPORT bool AddAudioTrackToMediaStream(
+ scoped_refptr<media::AudioCapturerSource> audio_source,
+ int sample_rate,
+ media::ChannelLayout channel_layout,
+ int frames_per_buffer,
+ bool is_remote,
+ bool is_readonly,
+ blink::WebMediaStream* web_media_stream);
+
+// On success returns pointer to the current format of the given video track;
+// returns nullptr on failure (if the argument is invalid or if the format
+// cannot be retrieved at the moment).
+CONTENT_EXPORT const media::VideoCaptureFormat* GetCurrentVideoTrackFormat(
+ const blink::WebMediaStreamTrack& video_track);
+
+// Requests that a refresh frame be sent "soon" (e.g., to resolve picture loss
+// or quality issues).
+CONTENT_EXPORT void RequestRefreshFrameFromVideoTrack(
+ const blink::WebMediaStreamTrack& video_track);
+
+} // namespace content
+
+#endif // CONTENT_PUBLIC_RENDERER_MEDIA_STREAM_UTILS_H_
diff --git a/chromium/content/public/renderer/media_stream_video_sink.cc b/chromium/content/public/renderer/media_stream_video_sink.cc
index efd38ea9351..d2c3488af04 100644
--- a/chromium/content/public/renderer/media_stream_video_sink.cc
+++ b/chromium/content/public/renderer/media_stream_video_sink.cc
@@ -4,29 +4,34 @@
#include "content/public/renderer/media_stream_video_sink.h"
-#include "base/logging.h"
#include "content/renderer/media/media_stream_video_track.h"
-#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
namespace content {
-void MediaStreamVideoSink::AddToVideoTrack(
- MediaStreamVideoSink* sink,
- const VideoCaptureDeliverFrameCB& callback,
- const blink::WebMediaStreamTrack& track) {
- DCHECK_EQ(blink::WebMediaStreamSource::TypeVideo, track.source().type());
+MediaStreamVideoSink::MediaStreamVideoSink() : MediaStreamSink() {}
+
+MediaStreamVideoSink::~MediaStreamVideoSink() {
+ // Ensure this sink has disconnected from the track.
+ DisconnectFromTrack();
+}
+
+void MediaStreamVideoSink::ConnectToTrack(
+ const blink::WebMediaStreamTrack& track,
+ const VideoCaptureDeliverFrameCB& callback) {
+ DCHECK(connected_track_.isNull());
+ connected_track_ = track;
MediaStreamVideoTrack* const video_track =
- static_cast<MediaStreamVideoTrack*>(track.extraData());
- video_track->AddSink(sink, callback);
+ MediaStreamVideoTrack::GetVideoTrack(connected_track_);
+ DCHECK(video_track);
+ video_track->AddSink(this, callback);
}
-void MediaStreamVideoSink::RemoveFromVideoTrack(
- MediaStreamVideoSink* sink,
- const blink::WebMediaStreamTrack& track) {
- DCHECK_EQ(blink::WebMediaStreamSource::TypeVideo, track.source().type());
+void MediaStreamVideoSink::DisconnectFromTrack() {
MediaStreamVideoTrack* const video_track =
- static_cast<MediaStreamVideoTrack*>(track.extraData());
- video_track->RemoveSink(sink);
+ MediaStreamVideoTrack::GetVideoTrack(connected_track_);
+ if (video_track)
+ video_track->RemoveSink(this);
+ connected_track_.reset();
}
} // namespace content
diff --git a/chromium/content/public/renderer/media_stream_video_sink.h b/chromium/content/public/renderer/media_stream_video_sink.h
index b1dda9c46fa..fd5334c4e6d 100644
--- a/chromium/content/public/renderer/media_stream_video_sink.h
+++ b/chromium/content/public/renderer/media_stream_video_sink.h
@@ -13,37 +13,46 @@
#include "content/common/media/video_capture.h"
#include "content/public/renderer/media_stream_sink.h"
#include "media/base/video_capturer_source.h"
-
-namespace blink {
-class WebMediaStreamTrack;
-}
+#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
namespace content {
// MediaStreamVideoSink is an interface used for receiving video frames from a
-// Video Stream Track or a Video Source.
+// Video Stream Track or a Video Source. It should be extended by embedders,
+// which connect/disconnect the sink implementation to a track to start/stop the
+// flow of video frames.
+//
// http://dev.w3.org/2011/webrtc/editor/getusermedia.html
// All methods calls will be done from the main render thread.
class CONTENT_EXPORT MediaStreamVideoSink : public MediaStreamSink {
- public:
- // An implementation of MediaStreamVideoSink should call AddToVideoTrack when
+ protected:
+ MediaStreamVideoSink();
+ ~MediaStreamVideoSink() override;
+
+ // An implementation of MediaStreamVideoSink should call ConnectToTrack when
// it is ready to receive data from a video track. Before the implementation
- // is destroyed, RemoveFromVideoTrack must be called.
+ // is destroyed, DisconnectFromTrack must be called. This MediaStreamVideoSink
+ // base class holds a reference to the WebMediaStreamTrack until
+ // DisconnectFromTrack is called.
//
// Calls to these methods must be done on the main render thread.
// Note that |callback| for frame delivery happens on the IO thread.
//
- // Calling RemoveFromVideoTrack also not stop frame delivery through the
- // callback immediately because it may happen on another thread.
- // The added callback will be reset on the render thread.
- static void AddToVideoTrack(MediaStreamVideoSink* sink,
- const VideoCaptureDeliverFrameCB& callback,
- const blink::WebMediaStreamTrack& track);
- static void RemoveFromVideoTrack(MediaStreamVideoSink* sink,
- const blink::WebMediaStreamTrack& track);
-
- protected:
- ~MediaStreamVideoSink() override {}
+ // Warning: Calling DisconnectFromTrack does not immediately stop frame
+ // delivery through the |callback|, since frames are being delivered on a
+ // different thread.
+ void ConnectToTrack(const blink::WebMediaStreamTrack& track,
+ const VideoCaptureDeliverFrameCB& callback);
+ void DisconnectFromTrack();
+
+ // Returns the currently-connected track, or a null instance otherwise.
+ const blink::WebMediaStreamTrack& connected_track() const {
+ return connected_track_;
+ }
+
+ private:
+ // Set by ConnectToTrack() and cleared by DisconnectFromTrack().
+ blink::WebMediaStreamTrack connected_track_;
};
diff --git a/chromium/content/public/renderer/render_frame_observer.h b/chromium/content/public/renderer/render_frame_observer.h
index 43182a691f8..bf7c6eee7a7 100644
--- a/chromium/content/public/renderer/render_frame_observer.h
+++ b/chromium/content/public/renderer/render_frame_observer.h
@@ -13,6 +13,7 @@
#include "content/common/content_export.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
+#include "third_party/WebKit/public/platform/WebLoadingBehaviorFlag.h"
#include "third_party/WebKit/public/platform/WebVector.h"
#include "third_party/WebKit/public/web/WebMeaningfulLayout.h"
#include "v8/include/v8.h"
@@ -96,7 +97,7 @@ class CONTENT_EXPORT RenderFrameObserver : public IPC::Listener,
virtual void DetailedConsoleMessageAdded(const base::string16& message,
const base::string16& source,
const base::string16& stack_trace,
- int32_t line_number,
+ uint32_t line_number,
int32_t severity_level) {}
// Called when an interesting (from document lifecycle perspective),
@@ -112,6 +113,11 @@ class CONTENT_EXPORT RenderFrameObserver : public IPC::Listener,
// Notifications when |PerformanceTiming| data becomes available
virtual void DidChangePerformanceTiming() {}
+ // Notification when the renderer uses a particular code path during a page
+ // load. This is used for metrics collection.
+ virtual void DidObserveLoadingBehavior(
+ blink::WebLoadingBehaviorFlag behavior) {}
+
// Called when the focused node has changed to |node|.
virtual void FocusedNodeChanged(const blink::WebNode& node) {}
diff --git a/chromium/content/public/renderer/render_process_observer.h b/chromium/content/public/renderer/render_process_observer.h
index f53ba65f9ff..30f855daf2e 100644
--- a/chromium/content/public/renderer/render_process_observer.h
+++ b/chromium/content/public/renderer/render_process_observer.h
@@ -27,9 +27,6 @@ class CONTENT_EXPORT RenderProcessObserver {
// Notification that the render process is shutting down.
virtual void OnRenderProcessShutdown() {}
- // Called right after the WebKit API is initialized.
- virtual void WebKitInitialized() {}
-
// Called when the renderer cache of the plugin list has changed.
virtual void PluginListChanged() {}
diff --git a/chromium/content/public/renderer/render_thread.h b/chromium/content/public/renderer/render_thread.h
index 76cb48f9044..7f88da91b1d 100644
--- a/chromium/content/public/renderer/render_thread.h
+++ b/chromium/content/public/renderer/render_thread.h
@@ -75,29 +75,6 @@ class CONTENT_EXPORT RenderThread : virtual public ChildThread {
virtual void SetResourceDispatcherDelegate(
ResourceDispatcherDelegate* delegate) = 0;
- // We initialize WebKit as late as possible. Call this to force
- // initialization.
- virtual void EnsureWebKitInitialized() = 0;
-
- // Sends over a base::UserMetricsAction to be recorded by user metrics as
- // an action. Once a new user metric is added, run
- // tools/metrics/actions/extract_actions.py
- // to add the metric to actions.xml, then update the <owner>s and
- // <description> sections. Make sure to include the actions.xml file when you
- // upload your code for review!
- //
- // WARNING: When using base::UserMetricsAction, base::UserMetricsAction
- // and a string literal parameter must be on the same line, e.g.
- // RenderThread::Get()->RecordAction(
- // base::UserMetricsAction("my extremely long action name"));
- // because otherwise our processing scripts won't pick up on new actions.
- virtual void RecordAction(const base::UserMetricsAction& action) = 0;
-
- // Sends over a string to be recorded by user metrics as a computed action.
- // When you use this you need to also update the rules for extracting known
- // actions in chrome/tools/extract_actions.py.
- virtual void RecordComputedAction(const std::string& action) = 0;
-
// Asks the host to create a block of shared memory for the renderer.
// The shared memory allocated by the host is returned back.
virtual scoped_ptr<base::SharedMemory> HostAllocateSharedMemoryBuffer(
@@ -132,7 +109,7 @@ class CONTENT_EXPORT RenderThread : virtual public ChildThread {
// Gets the shutdown event for the process.
virtual base::WaitableEvent* GetShutdownEvent() = 0;
- // Returns the ServiceRegistry for this thread.
+ // Returns the ServiceRegistry for this thread. Never returns nullptr.
virtual ServiceRegistry* GetServiceRegistry() = 0;
};
diff --git a/chromium/content/public/renderer/render_view.h b/chromium/content/public/renderer/render_view.h
index d02fa8f537d..8c036d505a8 100644
--- a/chromium/content/public/renderer/render_view.h
+++ b/chromium/content/public/renderer/render_view.h
@@ -21,6 +21,7 @@
namespace blink {
class WebElement;
class WebFrame;
+class WebFrameWidget;
class WebLocalFrame;
class WebNode;
class WebString;
@@ -38,6 +39,7 @@ class Size;
namespace content {
class RenderFrame;
+class RenderWidget;
class RenderViewVisitor;
struct SSLStatus;
struct WebPreferences;
@@ -66,6 +68,9 @@ class CONTENT_EXPORT RenderView : public IPC::Sender {
static void ApplyWebPreferences(const WebPreferences& preferences,
blink::WebView* web_view);
+ // Returns the RenderWidget for this RenderView.
+ virtual RenderWidget* GetWidget() const = 0;
+
// Returns the main RenderFrame.
virtual RenderFrame* GetMainRenderFrame() = 0;
@@ -88,6 +93,9 @@ class CONTENT_EXPORT RenderView : public IPC::Sender {
// Returns the associated WebView. May return NULL when the view is closing.
virtual blink::WebView* GetWebView() = 0;
+ // Returns the associated WebFrameWidget.
+ virtual blink::WebFrameWidget* GetWebFrameWidget() = 0;
+
// Returns true if we should display scrollbars for the given view size and
// false if the scrollbars should be hidden.
virtual bool ShouldDisplayScrollbars(int width, int height) const = 0;
@@ -132,7 +140,7 @@ class CONTENT_EXPORT RenderView : public IPC::Sender {
// Converts the |rect| from Viewport coordinates to Window coordinates.
// See blink::WebWidgetClient::convertViewportToWindow for more details.
- virtual void convertViewportToWindow(blink::WebRect* rect) = 0;
+ virtual void ConvertViewportToWindowViaWidget(blink::WebRect* rect) = 0;
// Returns the bounds of |element| in Window coordinates. The bounds have been
// adjusted to include any transformations, including page scale.
diff --git a/chromium/content/public/renderer/render_view_observer.cc b/chromium/content/public/renderer/render_view_observer.cc
index 8289da949e1..5e876cc1bff 100644
--- a/chromium/content/public/renderer/render_view_observer.cc
+++ b/chromium/content/public/renderer/render_view_observer.cc
@@ -6,27 +6,22 @@
#include "content/renderer/render_view_impl.h"
-using blink::WebFrame;
-
namespace content {
RenderViewObserver::RenderViewObserver(RenderView* render_view)
- : render_view_(render_view),
+ : render_view_(static_cast<RenderViewImpl*>(render_view)),
routing_id_(MSG_ROUTING_NONE) {
- // |render_view| can be NULL on unit testing or if Observe() is used.
- if (render_view) {
- RenderViewImpl* impl = static_cast<RenderViewImpl*>(render_view);
- routing_id_ = impl->routing_id();
+ // |render_view_| can be null on unit testing or if Observe() is used.
+ if (render_view_) {
+ routing_id_ = render_view_->GetRoutingID();
// TODO(jam): bring this back DCHECK_NE(routing_id_, MSG_ROUTING_NONE);
- impl->AddObserver(this);
+ render_view_->AddObserver(this);
}
}
RenderViewObserver::~RenderViewObserver() {
- if (render_view_) {
- RenderViewImpl* impl = static_cast<RenderViewImpl*>(render_view_);
- impl->RemoveObserver(this);
- }
+ if (render_view_)
+ render_view_->RemoveObserver(this);
}
void RenderViewObserver::OnDestruct() {
@@ -50,21 +45,19 @@ RenderView* RenderViewObserver::render_view() const {
}
void RenderViewObserver::RenderViewGone() {
- render_view_ = NULL;
+ render_view_ = nullptr;
}
void RenderViewObserver::Observe(RenderView* render_view) {
- RenderViewImpl* impl = static_cast<RenderViewImpl*>(render_view_);
- if (impl) {
- impl->RemoveObserver(this);
+ if (render_view_) {
+ render_view_->RemoveObserver(this);
routing_id_ = 0;
}
- render_view_ = render_view;
- impl = static_cast<RenderViewImpl*>(render_view_);
- if (impl) {
- routing_id_ = impl->routing_id();
- impl->AddObserver(this);
+ render_view_ = static_cast<RenderViewImpl*>(render_view);
+ if (render_view_) {
+ routing_id_ = render_view_->GetRoutingID();
+ render_view_->AddObserver(this);
}
}
diff --git a/chromium/content/public/renderer/render_view_observer.h b/chromium/content/public/renderer/render_view_observer.h
index 5eeb45b55ab..a245e632c91 100644
--- a/chromium/content/public/renderer/render_view_observer.h
+++ b/chromium/content/public/renderer/render_view_observer.h
@@ -103,7 +103,7 @@ class CONTENT_EXPORT RenderViewObserver : public IPC::Listener,
// can null out its pointer.
void RenderViewGone();
- RenderView* render_view_;
+ RenderViewImpl* render_view_;
// The routing ID of the associated RenderView.
int routing_id_;
diff --git a/chromium/content/public/renderer/resource_fetcher.h b/chromium/content/public/renderer/resource_fetcher.h
index 2c402aab395..64fece51f04 100644
--- a/chromium/content/public/renderer/resource_fetcher.h
+++ b/chromium/content/public/renderer/resource_fetcher.h
@@ -20,6 +20,7 @@ class TimeDelta;
namespace blink {
class WebFrame;
class WebURLResponse;
+enum class WebCachePolicy;
struct WebURLLoaderOptions;
}
@@ -55,7 +56,7 @@ class CONTENT_EXPORT ResourceFetcher {
virtual void SetHeader(const std::string& header,
const std::string& value) = 0;
virtual void SetSkipServiceWorker(bool skip_service_worker) = 0;
- virtual void SetCachePolicy(blink::WebURLRequest::CachePolicy policy) = 0;
+ virtual void SetCachePolicy(blink::WebCachePolicy policy) = 0;
// Associate the corresponding WebURLLoaderOptions to the loader. Must be
// called before Start. Used if the LoaderType is FRAME_ASSOCIATED_LOADER.
diff --git a/chromium/content/public/renderer/video_encode_accelerator.cc b/chromium/content/public/renderer/video_encode_accelerator.cc
index 88d6c5ae304..5efbbb7c00e 100644
--- a/chromium/content/public/renderer/video_encode_accelerator.cc
+++ b/chromium/content/public/renderer/video_encode_accelerator.cc
@@ -5,8 +5,8 @@
#include "content/public/renderer/video_encode_accelerator.h"
#include "base/task_runner_util.h"
-#include "content/common/gpu/client/gpu_video_encode_accelerator_host.h"
#include "content/renderer/render_thread_impl.h"
+#include "media/gpu/ipc/client/gpu_video_encode_accelerator_host.h"
#include "media/renderers/gpu_video_accelerator_factories.h"
namespace content {
diff --git a/chromium/content/public/utility/BUILD.gn b/chromium/content/public/utility/BUILD.gn
index 1f3e9874595..c0e514cf3fb 100644
--- a/chromium/content/public/utility/BUILD.gn
+++ b/chromium/content/public/utility/BUILD.gn
@@ -18,6 +18,7 @@ group("utility") {
}
source_set("utility_sources") {
+ # External code should depend on via ":utility" above.
visibility = [ "//content/*" ]
sources = rebase_path(content_utility_gypi_values.public_utility_sources,
@@ -29,6 +30,7 @@ source_set("utility_sources") {
deps = [
"//base",
"//content:export",
+ "//content/public/child:child_sources",
"//content/public/common:common_sources",
"//content/utility",
"//ipc",
diff --git a/chromium/content/public/utility/content_utility_client.h b/chromium/content/public/utility/content_utility_client.h
index b326eae140c..299974a6436 100644
--- a/chromium/content/public/utility/content_utility_client.h
+++ b/chromium/content/public/utility/content_utility_client.h
@@ -14,7 +14,7 @@
class GURL;
namespace mojo {
-class ApplicationDelegate;
+class ShellClient;
}
namespace content {
@@ -25,7 +25,7 @@ class ServiceRegistry;
class CONTENT_EXPORT ContentUtilityClient {
public:
using StaticMojoApplicationMap =
- std::map<GURL, base::Callback<scoped_ptr<mojo::ApplicationDelegate>()>>;
+ std::map<std::string, base::Callback<scoped_ptr<mojo::ShellClient>()>>;
virtual ~ContentUtilityClient() {}
diff --git a/chromium/content/renderer/BUILD.gn b/chromium/content/renderer/BUILD.gn
index 141edcb0f49..790a7488326 100644
--- a/chromium/content/renderer/BUILD.gn
+++ b/chromium/content/renderer/BUILD.gn
@@ -10,7 +10,10 @@ import("//media/media_options.gni")
source_set("renderer") {
# Only the public target should depend on this. All other targets (even
# internal content ones) should depend on the public one.
- visibility = [ "//content/public/renderer:renderer_sources" ]
+ visibility = [
+ ":for_content_tests",
+ "//content/public/renderer:renderer_sources",
+ ]
sources = rebase_path(content_renderer_gypi_values.private_renderer_sources,
".",
@@ -23,30 +26,28 @@ source_set("renderer") {
]
defines = []
+ public_deps = []
deps = [
"//base:i18n",
-
- # TODO(GYP) bug 376846 remove this. This should be inherited from //net but
- # those don't cross component boundaries.
- "//base/allocator",
"//cc",
"//cc/blink",
"//cc/proto",
"//cc/surfaces",
+ "//cc/surfaces:surface_id",
"//components/scheduler:scheduler",
- "//components/startup_metric_utils/common",
"//components/url_formatter",
- "//components/webusb",
"//content:resources",
- "//content/common:mojo_bindings",
+ "//content/common",
+ "//content/gpu:gpu_sources",
"//content/public/child:child_sources",
"//content/public/common:common_sources",
+ "//content/public/common:feature_h264_with_openh264_ffmpeg",
+ "//content/public/common:features",
"//content/public/common:mojo_bindings",
"//crypto:platform",
"//device/battery:mojo_bindings",
"//device/bluetooth",
- "//device/devices_app/public/cpp",
- "//device/devices_app/usb/public/interfaces",
+ "//device/usb/public/interfaces",
"//device/vibration:mojo_bindings",
"//gin",
"//gpu",
@@ -56,24 +57,26 @@ source_set("renderer") {
"//jingle:jingle_glue",
"//media",
"//media/blink",
+ "//media/gpu/ipc/client",
+ "//media/gpu/ipc/common",
"//media/midi",
"//mojo/common",
"//mojo/converters/geometry",
- "//mojo/environment:chromium",
+ "//mojo/edk/js",
"//mojo/public/cpp/bindings",
"//mojo/public/js",
"//mojo/shell/public/cpp",
"//mojo/shell/public/interfaces",
"//net",
+ "//sandbox",
"//skia",
"//skia/public",
"//storage/common",
"//third_party/WebKit/public:blink",
+ "//third_party/boringssl",
"//third_party/icu",
"//third_party/libjingle",
"//third_party/libyuv",
- "//third_party/mojo/src/mojo/edk/js",
- "//third_party/npapi",
"//third_party/widevine/cdm:version_h",
"//ui/accessibility",
"//ui/base",
@@ -86,9 +89,11 @@ source_set("renderer") {
"//ui/surface",
"//v8",
]
+ allow_circular_includes_from = []
if (use_aura) {
- deps += [ "//content/renderer/mus" ]
+ public_deps += [ "//content/renderer/mus" ]
+ allow_circular_includes_from += [ "//content/renderer/mus" ]
}
if (is_mac) {
@@ -157,12 +162,13 @@ source_set("renderer") {
deps += [
"//crypto",
"//third_party/libjingle:libjingle_webrtc",
- "//third_party/libjingle:libpeerconnection",
"//third_party/libjingle:libstunprober",
+ "//third_party/libvpx",
"//third_party/webrtc/base:rtc_base",
"//third_party/webrtc/common_video",
"//third_party/webrtc/modules/audio_device",
"//third_party/webrtc/modules/audio_processing",
+ "//third_party/webrtc/modules/video_coding:webrtc_h264",
"//third_party/webrtc/system_wrappers",
]
} else {
@@ -181,7 +187,7 @@ source_set("renderer") {
"//ppapi/host",
"//ppapi/proxy",
"//ppapi/shared_impl",
- "//third_party/libvpx_new",
+ "//third_party/libvpx",
"//third_party/opus",
]
}
@@ -203,7 +209,7 @@ source_set("renderer") {
]
}
- if (enable_print_preview) {
+ if (enable_basic_printing || enable_print_preview) {
deps += [ "//printing" ]
}
@@ -216,9 +222,16 @@ source_set("renderer") {
]
}
- if (enable_mojo_media != "none") {
+ if (enable_mojo_media) {
+ sources += [
+ "media/media_interface_provider.cc",
+ "media/media_interface_provider.h",
+ ]
+
deps += [
"//media/mojo/interfaces",
+
+ # Defines in mojo_media_config are also pulled in here.
"//media/mojo/services:proxy",
]
}
@@ -235,4 +248,24 @@ source_set("renderer") {
if (use_seccomp_bpf) {
defines += [ "USE_SECCOMP_BPF" ]
}
+
+ if (use_ozone) {
+ deps += [ "//ui/ozone" ]
+ }
+}
+
+# See comment at the top of //content/BUILD.gn for how this works.
+group("for_content_tests") {
+ visibility = [ "//content/test/*" ]
+
+ if (enable_mojo_media) {
+ # For the defines in mojo_media_config.
+ public_configs = [ "//media/mojo/services:mojo_media_config" ]
+ }
+
+ if (!is_component_build) {
+ public_deps = [
+ ":renderer",
+ ]
+ }
}
diff --git a/chromium/content/renderer/DEPS b/chromium/content/renderer/DEPS
index c9157c3c450..313339e1cb5 100644
--- a/chromium/content/renderer/DEPS
+++ b/chromium/content/renderer/DEPS
@@ -6,12 +6,11 @@ include_rules = [
"+components/url_formatter",
"+cc/blink",
- "+components/startup_metric_utils/common",
"+content/public/child",
"+content/public/renderer",
"+content/child",
"+device/battery", # For battery status service.
- "+device/devices_app/public",
+ "+device/usb/public",
"+device/vibration",
"+gin",
"+jingle/glue",
@@ -20,7 +19,6 @@ include_rules = [
"-storage/browser",
"+third_party/hyphen/hyphen.h",
"+third_party/libjingle",
- "+third_party/tcmalloc",
"+v8/include",
"+v8/src/third_party/vtune",
]
diff --git a/chromium/content/renderer/OWNERS b/chromium/content/renderer/OWNERS
index c7ecacde977..d285f81502f 100644
--- a/chromium/content/renderer/OWNERS
+++ b/chromium/content/renderer/OWNERS
@@ -1,3 +1,6 @@
+# For Blink API usage
+esprehn@chromium.org
+
# Mac Sandbox profiles.
per-file *.sb=set noparent
per-file *.sb=rsesek@chromium.org
diff --git a/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc b/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc
index 1c56d5ae116..1ad022c08ab 100644
--- a/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc
+++ b/chromium/content/renderer/accessibility/blink_ax_enum_conversion.cc
@@ -24,9 +24,6 @@ uint32_t AXStateFromBlink(const blink::WebAXObject& o) {
if (o.canSetFocusAttribute())
state |= (1 << ui::AX_STATE_FOCUSABLE);
- if (o.isFocused())
- state |= (1 << ui::AX_STATE_FOCUSED);
-
if (o.role() == blink::WebAXRolePopUpButton ||
o.ariaHasPopup())
state |= (1 << ui::AX_STATE_HASPOPUP);
@@ -92,6 +89,8 @@ uint32_t AXStateFromBlink(const blink::WebAXObject& o) {
ui::AXRole AXRoleFromBlink(blink::WebAXRole role) {
switch (role) {
+ case blink::WebAXRoleAbbr:
+ return ui::AX_ROLE_ABBR;
case blink::WebAXRoleAlert:
return ui::AX_ROLE_ALERT;
case blink::WebAXRoleAlertDialog:
@@ -355,6 +354,8 @@ ui::AXEvent AXEventFromBlink(blink::WebAXEvent event) {
return ui::AX_EVENT_CHECKED_STATE_CHANGED;
case blink::WebAXEventChildrenChanged:
return ui::AX_EVENT_CHILDREN_CHANGED;
+ case blink::WebAXEventClicked:
+ return ui::AX_EVENT_CLICKED;
case blink::WebAXEventDocumentSelectionChanged:
return ui::AX_EVENT_DOCUMENT_SELECTION_CHANGED;
case blink::WebAXEventFocus:
diff --git a/chromium/content/renderer/accessibility/blink_ax_tree_source.cc b/chromium/content/renderer/accessibility/blink_ax_tree_source.cc
index eab8b3462e2..ac907ab1f40 100644
--- a/chromium/content/renderer/accessibility/blink_ax_tree_source.cc
+++ b/chromium/content/renderer/accessibility/blink_ax_tree_source.cc
@@ -18,6 +18,7 @@
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_frame_proxy.h"
#include "content/renderer/render_view_impl.h"
+#include "content/renderer/web_frame_utils.h"
#include "third_party/WebKit/public/platform/WebRect.h"
#include "third_party/WebKit/public/platform/WebSize.h"
#include "third_party/WebKit/public/platform/WebString.h"
@@ -138,12 +139,16 @@ AXContentTreeData BlinkAXTreeSource::GetTreeData() const {
blink::WebDocument document = BlinkAXTreeSource::GetMainDocument();
const blink::WebAXObject& root = GetRoot();
- tree_data.title = document.title().utf8();
- tree_data.url = document.url().string().utf8();
- tree_data.mimetype = document.isXHTMLDocument() ? "text/xhtml" : "text/html";
+ tree_data.doctype = "html";
tree_data.loaded = root.isLoaded();
tree_data.loading_progress = root.estimatedLoadingProgress();
- tree_data.doctype = "html";
+ tree_data.mimetype = document.isXHTMLDocument() ? "text/xhtml" : "text/html";
+ tree_data.title = document.title().utf8();
+ tree_data.url = document.url().string().utf8();
+
+ WebAXObject focus = document.focusedAccessibilityObject();
+ if (!focus.isNull())
+ tree_data.focus_id = focus.axID();
WebAXObject anchor_object, focus_object;
int anchor_offset, focus_offset;
@@ -158,19 +163,17 @@ AXContentTreeData BlinkAXTreeSource::GetTreeData() const {
tree_data.sel_focus_offset = focus_offset;
}
- // Get the tree ID for this frame and possibly the parent frame.
+ // Get the tree ID for this frame and the parent frame.
WebLocalFrame* web_frame = document.frame();
if (web_frame) {
RenderFrame* render_frame = RenderFrame::FromWebFrame(web_frame);
tree_data.routing_id = render_frame->GetRoutingID();
- // Get the tree ID for the parent frame, if it's remote.
- // (If it's local, it's already part of this same tree.)
+ // Get the tree ID for the parent frame.
blink::WebFrame* parent_web_frame = web_frame->parent();
- if (parent_web_frame && parent_web_frame->isWebRemoteFrame()) {
- RenderFrameProxy* parent_render_frame_proxy =
- RenderFrameProxy::FromWebFrame(parent_web_frame);
- tree_data.parent_routing_id = parent_render_frame_proxy->routing_id();
+ if (parent_web_frame) {
+ tree_data.parent_routing_id =
+ GetRoutingIdForFrameOrProxy(parent_web_frame);
}
}
@@ -305,6 +308,12 @@ void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src,
if (src.color())
dst->AddIntAttribute(ui::AX_ATTR_COLOR, src.color());
+ if (src.fontFamily().length()) {
+ WebAXObject parent = src.parentObject();
+ if (parent.isNull() || parent.fontFamily() != src.fontFamily())
+ dst->AddStringAttribute(ui::AX_ATTR_FONT_FAMILY, src.fontFamily().utf8());
+ }
+
// Font size is in pixels.
if (src.fontSize())
dst->AddFloatAttribute(ui::AX_ATTR_FONT_SIZE, src.fontSize());
@@ -313,7 +322,8 @@ void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src,
dst->AddIntAttribute(ui::AX_ATTR_INVALID_STATE,
AXInvalidStateFromBlink(src.invalidState()));
}
- if (src.invalidState() == blink::WebAXInvalidStateOther) {
+ if (src.invalidState() == blink::WebAXInvalidStateOther &&
+ src.ariaInvalidValue().length()) {
dst->AddStringAttribute(
ui::AX_ATTR_ARIA_INVALID_VALUE, src.ariaInvalidValue().utf8());
}
@@ -360,25 +370,39 @@ void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src,
if (src.actionVerb().length()) {
dst->AddStringAttribute(ui::AX_ATTR_ACTION, src.actionVerb().utf8());
}
- if (src.ariaAutoComplete().length())
+
+ if (src.ariaAutoComplete().length()) {
dst->AddStringAttribute(
ui::AX_ATTR_AUTO_COMPLETE,
src.ariaAutoComplete().utf8());
+ }
+
if (src.isAriaReadOnly())
dst->AddBoolAttribute(ui::AX_ATTR_ARIA_READONLY, true);
+
if (src.isButtonStateMixed())
dst->AddBoolAttribute(ui::AX_ATTR_STATE_MIXED, true);
+
if (src.canSetValueAttribute())
dst->AddBoolAttribute(ui::AX_ATTR_CAN_SET_VALUE, true);
+
if (src.hasComputedStyle()) {
dst->AddStringAttribute(
ui::AX_ATTR_DISPLAY, src.computedStyleDisplay().utf8());
}
+
+ if (src.language().length()) {
+ WebAXObject parent = src.parentObject();
+ if (parent.isNull() || parent.language() != src.language())
+ dst->AddStringAttribute(ui::AX_ATTR_LANGUAGE, src.language().utf8());
+ }
+
if (src.keyboardShortcut().length()) {
dst->AddStringAttribute(
ui::AX_ATTR_SHORTCUT,
src.keyboardShortcut().utf8());
}
+
if (!src.ariaActiveDescendant().isDetached()) {
dst->AddIntAttribute(ui::AX_ATTR_ACTIVEDESCENDANT_ID,
src.ariaActiveDescendant().axID());
@@ -402,12 +426,6 @@ void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src,
if (src.posInSet())
dst->AddIntAttribute(ui::AX_ATTR_POS_IN_SET, src.posInSet());
- // Treat the active list box item as focused.
- if (dst->role == ui::AX_ROLE_LIST_BOX_OPTION &&
- src.isSelectedOptionActive()) {
- dst->state |= (1 << ui::AX_STATE_FOCUSED);
- }
-
if (src.canvasHasFallbackContent())
dst->AddBoolAttribute(ui::AX_ATTR_CANVAS_HAS_FALLBACK, true);
@@ -467,17 +485,13 @@ void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src,
browser_plugin->browser_plugin_instance_id());
}
- // Out-of-process iframe.
+ // Iframe.
if (is_iframe) {
WebFrame* frame = WebFrame::fromFrameOwnerElement(element);
-
- if (frame && frame->isWebRemoteFrame()) {
- RenderFrameProxy* render_frame_proxy =
- RenderFrameProxy::FromWebFrame(frame);
- DCHECK(render_frame_proxy);
+ if (frame) {
dst->AddContentIntAttribute(
AX_CONTENT_ATTR_CHILD_ROUTING_ID,
- render_frame_proxy->routing_id());
+ GetRoutingIdForFrameOrProxy(frame));
}
}
}
@@ -519,8 +533,11 @@ void BlinkAXTreeSource::SerializeNode(blink::WebAXObject src,
src.minValueForRange());
}
- if (dst->role == ui::AX_ROLE_WEB_AREA)
+ if (dst->role == ui::AX_ROLE_WEB_AREA) {
dst->AddStringAttribute(ui::AX_ATTR_HTML_TAG, "#document");
+ dst->transform.reset(
+ new gfx::Transform(src.transformFromLocalParentFrame()));
+ }
if (dst->role == ui::AX_ROLE_TABLE) {
int column_count = src.columnCount();
diff --git a/chromium/content/renderer/accessibility/renderer_accessibility.cc b/chromium/content/renderer/accessibility/renderer_accessibility.cc
index 843644f8e63..fb8bf2d6a9f 100644
--- a/chromium/content/renderer/accessibility/renderer_accessibility.cc
+++ b/chromium/content/renderer/accessibility/renderer_accessibility.cc
@@ -70,6 +70,15 @@ RendererAccessibility::RendererAccessibility(RenderFrameImpl* render_frame)
ack_pending_(false),
reset_token_(0),
weak_factory_(this) {
+ // There's only one AXObjectCache for the root of a local frame tree,
+ // so if this frame's parent is local we can safely do nothing.
+ if (render_frame_ &&
+ render_frame_->GetWebFrame() &&
+ render_frame_->GetWebFrame()->parent() &&
+ render_frame_->GetWebFrame()->parent()->isWebLocalFrame()) {
+ return;
+ }
+
WebView* web_view = render_frame_->GetRenderView()->GetWebView();
WebSettings* settings = web_view->settings();
settings->setAccessibilityEnabled(true);
@@ -229,9 +238,6 @@ void RendererAccessibility::SendPendingAccessibilityEvents() {
if (pending_events_.empty())
return;
- if (render_frame_->is_swapped_out())
- return;
-
ack_pending_ = true;
// Make a copy of the events, because it's possible that
@@ -378,8 +384,24 @@ void RendererAccessibility::OnHitTest(gfx::Point point) {
return;
WebAXObject obj = root_obj.hitTest(point);
- if (!obj.isDetached())
- HandleAXEvent(obj, ui::AX_EVENT_HOVER);
+ if (obj.isDetached())
+ return;
+
+ // If the object that was hit has a child frame, we have to send a
+ // message back to the browser to do the hit test in the child frame,
+ // recursively.
+ AXContentNodeData data;
+ tree_source_.SerializeNode(obj, &data);
+ if (data.HasContentIntAttribute(AX_CONTENT_ATTR_CHILD_ROUTING_ID) ||
+ data.HasContentIntAttribute(
+ AX_CONTENT_ATTR_CHILD_BROWSER_PLUGIN_INSTANCE_ID)) {
+ Send(new AccessibilityHostMsg_ChildFrameHitTestResult(routing_id(), point,
+ obj.axID()));
+ return;
+ }
+
+ // Otherwise, send a HOVER event on the node that was hit.
+ HandleAXEvent(obj, ui::AX_EVENT_HOVER);
}
void RendererAccessibility::OnSetAccessibilityFocus(int acc_obj_id) {
diff --git a/chromium/content/renderer/accessibility/renderer_accessibility_browsertest.cc b/chromium/content/renderer/accessibility/renderer_accessibility_browsertest.cc
index 0c6958e43a6..ed8b4ebae7b 100644
--- a/chromium/content/renderer/accessibility/renderer_accessibility_browsertest.cc
+++ b/chromium/content/renderer/accessibility/renderer_accessibility_browsertest.cc
@@ -166,72 +166,6 @@ TEST_F(RendererAccessibilityTest, SendFullAccessibilityTreeOnReload) {
EXPECT_EQ(4, CountAccessibilityNodesSentToBrowser());
}
-// http://crbug.com/253537
-#if defined(OS_ANDROID)
-#define MAYBE_AccessibilityMessagesQueueWhileSwappedOut \
- DISABLED_AccessibilityMessagesQueueWhileSwappedOut
-#else
-#define MAYBE_AccessibilityMessagesQueueWhileSwappedOut \
- AccessibilityMessagesQueueWhileSwappedOut
-#endif
-
-TEST_F(RendererAccessibilityTest,
- MAYBE_AccessibilityMessagesQueueWhileSwappedOut) {
- // This test breaks down in --site-per-process, as swapping out destroys
- // the main frame and it cannot be further navigated.
- // TODO(nasko): Figure out what this behavior looks like when swapped out
- // no longer exists.
- if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- return;
- }
- std::string html =
- "<body>"
- " <p>Hello, world.</p>"
- "</body>";
- LoadHTML(html.c_str());
- static const int kProxyRoutingId = 13;
-
- // Creating a RendererAccessibility should send the tree to the browser.
- scoped_ptr<TestRendererAccessibility> accessibility(
- new TestRendererAccessibility(frame()));
- accessibility->SendPendingAccessibilityEvents();
- EXPECT_EQ(5, CountAccessibilityNodesSentToBrowser());
-
- // Post a "value changed" event, but then swap out
- // before sending it. It shouldn't send the event while
- // swapped out.
- sink_->ClearMessages();
- WebDocument document = view()->GetWebView()->mainFrame()->document();
- WebAXObject root_obj = document.accessibilityObject();
- accessibility->HandleAXEvent(
- root_obj,
- ui::AX_EVENT_VALUE_CHANGED);
- view()->GetMainRenderFrame()->OnSwapOut(kProxyRoutingId, true,
- content::FrameReplicationState());
- accessibility->SendPendingAccessibilityEvents();
- EXPECT_FALSE(sink_->GetUniqueMessageMatching(
- AccessibilityHostMsg_Events::ID));
-
- // Navigate, so we're not swapped out anymore. Now we should
- // send accessibility events again. Note that the
- // message that was queued up before will be quickly discarded
- // because the element it was referring to no longer exists,
- // so the event here is from loading this new page.
- CommonNavigationParams common_params;
- RequestNavigationParams request_params;
- common_params.url = GURL("data:text/html,<p>Hello, again.</p>");
- common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
- common_params.transition = ui::PAGE_TRANSITION_TYPED;
- request_params.current_history_list_length = 1;
- request_params.current_history_list_offset = 0;
- request_params.pending_history_list_offset = 1;
- request_params.page_id = -1;
- frame()->OnNavigate(common_params, StartNavigationParams(), request_params);
- accessibility->SendPendingAccessibilityEvents();
- EXPECT_TRUE(sink_->GetUniqueMessageMatching(
- AccessibilityHostMsg_Events::ID));
-}
-
TEST_F(RendererAccessibilityTest, HideAccessibilityObject) {
// Test RendererAccessibility and make sure it sends the
// proper event to the browser when an object in the tree
@@ -403,38 +337,4 @@ TEST_F(RendererAccessibilityTest, DetachAccessibilityObject) {
// so we don't have a test expectation for it.
}
-TEST_F(RendererAccessibilityTest, EventOnObjectNotInTree) {
- // Test RendererAccessibility and make sure it doesn't send anything
- // if we get a notification from Blink for an object that isn't in the
- // tree, like the scroll area that's the parent of the main document,
- // which we don't expose.
- std::string html = "<body><input></body>";
- LoadHTML(html.c_str());
-
- scoped_ptr<TestRendererAccessibility> accessibility(
- new TestRendererAccessibility(frame()));
- accessibility->SendPendingAccessibilityEvents();
- EXPECT_EQ(3, CountAccessibilityNodesSentToBrowser());
-
- WebDocument document = view()->GetWebView()->mainFrame()->document();
- WebAXObject root_obj = document.accessibilityObject();
- WebAXObject scroll_area = root_obj.parentObject();
- EXPECT_EQ(blink::WebAXRoleScrollArea, scroll_area.role());
-
- // Try to fire a message on the scroll area, and assert that we just
- // ignore it.
- sink_->ClearMessages();
- accessibility->HandleAXEvent(scroll_area,
- ui::AX_EVENT_VALUE_CHANGED);
-
- accessibility->SendPendingAccessibilityEvents();
-
- const IPC::Message* message =
- sink_->GetUniqueMessageMatching(AccessibilityHostMsg_Events::ID);
- ASSERT_TRUE(message);
- base::Tuple<std::vector<AccessibilityHostMsg_EventParams>, int> param;
- AccessibilityHostMsg_Events::Read(message, &param);
- ASSERT_EQ(0U, base::get<0>(param).size());
-}
-
} // namespace content
diff --git a/chromium/content/renderer/android/phone_number_detector.cc b/chromium/content/renderer/android/phone_number_detector.cc
index 54da5fee51a..871ee853cc0 100644
--- a/chromium/content/renderer/android/phone_number_detector.cc
+++ b/chromium/content/renderer/android/phone_number_detector.cc
@@ -10,10 +10,10 @@
#include "base/strings/utf_string_conversions.h"
#include "content/public/renderer/android_content_detection_prefixes.h"
#include "net/base/escape.h"
-#include "third_party/libphonenumber/src/phonenumber_api.h"
-#include "third_party/libphonenumber/src/phonenumbers/phonenumbermatch.h"
-#include "third_party/libphonenumber/src/phonenumbers/phonenumbermatcher.h"
-#include "third_party/libphonenumber/src/phonenumbers/region_code.h"
+#include "third_party/libphonenumber/dist/cpp/src/phonenumbers/phonenumbermatch.h"
+#include "third_party/libphonenumber/dist/cpp/src/phonenumbers/phonenumbermatcher.h"
+#include "third_party/libphonenumber/dist/cpp/src/phonenumbers/region_code.h"
+#include "third_party/libphonenumber/phonenumber_api.h"
using i18n::phonenumbers::PhoneNumberMatch;
using i18n::phonenumbers::PhoneNumberMatcher;
diff --git a/chromium/content/renderer/android/synchronous_compositor_external_begin_frame_source.cc b/chromium/content/renderer/android/synchronous_compositor_external_begin_frame_source.cc
index c5337d0f122..7bb1dc8f727 100644
--- a/chromium/content/renderer/android/synchronous_compositor_external_begin_frame_source.cc
+++ b/chromium/content/renderer/android/synchronous_compositor_external_begin_frame_source.cc
@@ -48,21 +48,25 @@ void SynchronousCompositorExternalBeginFrameSource::SetClient(
client_ = client;
if (client_)
- client_->OnNeedsBeginFramesChange(needs_begin_frames_);
+ client_->OnNeedsBeginFramesChange(needs_begin_frames());
// State without client is paused, and default client state is not paused.
SetBeginFrameSourcePaused(!client_);
}
-void SynchronousCompositorExternalBeginFrameSource::OnNeedsBeginFramesChange(
+void SynchronousCompositorExternalBeginFrameSource::OnNeedsBeginFramesChanged(
bool needs_begin_frames) {
DCHECK(CalledOnValidThread());
if (client_)
client_->OnNeedsBeginFramesChange(needs_begin_frames);
}
-void SynchronousCompositorExternalBeginFrameSource::SetClientReady() {
+void SynchronousCompositorExternalBeginFrameSource::AddObserver(
+ cc::BeginFrameObserver* obs) {
DCHECK(CalledOnValidThread());
+ BeginFrameSourceBase::AddObserver(obs);
+ if (registered_)
+ return;
registry_->RegisterBeginFrameSource(routing_id_, this);
registered_ = true;
}
diff --git a/chromium/content/renderer/android/synchronous_compositor_external_begin_frame_source.h b/chromium/content/renderer/android/synchronous_compositor_external_begin_frame_source.h
index 83fed03bf58..e058c37662e 100644
--- a/chromium/content/renderer/android/synchronous_compositor_external_begin_frame_source.h
+++ b/chromium/content/renderer/android/synchronous_compositor_external_begin_frame_source.h
@@ -37,8 +37,8 @@ class SynchronousCompositorExternalBeginFrameSource
using cc::BeginFrameSourceBase::SetBeginFrameSourcePaused;
// cc::BeginFrameSourceBase implementation.
- void OnNeedsBeginFramesChange(bool needs_begin_frames) override;
- void SetClientReady() override;
+ void OnNeedsBeginFramesChanged(bool needs_begin_frames) override;
+ void AddObserver(cc::BeginFrameObserver* obs) override;
private:
bool CalledOnValidThread() const;
diff --git a/chromium/content/renderer/android/synchronous_compositor_factory.cc b/chromium/content/renderer/android/synchronous_compositor_factory.cc
index 550b76b77b3..e2724be0b7f 100644
--- a/chromium/content/renderer/android/synchronous_compositor_factory.cc
+++ b/chromium/content/renderer/android/synchronous_compositor_factory.cc
@@ -9,13 +9,13 @@
namespace content {
namespace {
-SynchronousCompositorFactory* g_instance = NULL;
+SynchronousCompositorFactory* g_instance = nullptr;
} // namespace
// static
void SynchronousCompositorFactory::SetInstance(
SynchronousCompositorFactory* instance) {
- DCHECK(g_instance == NULL);
+ DCHECK(g_instance == nullptr);
g_instance = instance;
}
diff --git a/chromium/content/renderer/android/synchronous_compositor_factory.h b/chromium/content/renderer/android/synchronous_compositor_factory.h
index 0f001fb6273..91185ffbd9d 100644
--- a/chromium/content/renderer/android/synchronous_compositor_factory.h
+++ b/chromium/content/renderer/android/synchronous_compositor_factory.h
@@ -31,6 +31,7 @@ class WebGraphicsContext3DInProcessCommandBufferImpl;
namespace content {
class InputHandlerManagerClient;
+class SynchronousInputHandlerProxyClient;
class StreamTextureFactory;
class FrameSwapMessageQueue;
@@ -49,23 +50,24 @@ class SynchronousCompositorFactory {
GetCompositorTaskRunner() = 0;
virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface(
int routing_id,
+ uint32_t output_surface_id,
const scoped_refptr<FrameSwapMessageQueue>& frame_swap_message_queue,
const scoped_refptr<cc::ContextProvider>& onscreen_context,
const scoped_refptr<cc::ContextProvider>& worker_context) = 0;
// The factory maintains ownership of the returned interface.
virtual InputHandlerManagerClient* GetInputHandlerManagerClient() = 0;
+ virtual SynchronousInputHandlerProxyClient*
+ GetSynchronousInputHandlerProxyClient() = 0;
virtual scoped_ptr<cc::BeginFrameSource> CreateExternalBeginFrameSource(
int routing_id) = 0;
- virtual scoped_refptr<StreamTextureFactory> CreateStreamTextureFactory(
- int frame_id) = 0;
protected:
SynchronousCompositorFactory() {}
virtual ~SynchronousCompositorFactory() {}
};
-}
+} // namespace content
#endif // CONTENT_RENDERER_ANDROID_SYNCHRONOUS_COMPOSITOR_FACTORY_H_
diff --git a/chromium/content/renderer/android/synchronous_compositor_filter.cc b/chromium/content/renderer/android/synchronous_compositor_filter.cc
index 5f4c9d27338..ae42cc31d45 100644
--- a/chromium/content/renderer/android/synchronous_compositor_filter.cc
+++ b/chromium/content/renderer/android/synchronous_compositor_filter.cc
@@ -4,6 +4,8 @@
#include "content/renderer/android/synchronous_compositor_filter.h"
+#include <utility>
+
#include "base/callback.h"
#include "base/stl_util.h"
#include "base/thread_task_runner_handle.h"
@@ -128,7 +130,11 @@ void SynchronousCompositorFilter::RegisterOutputSurface(
Entry& entry = entry_map_[routing_id];
DCHECK(!entry.output_surface);
entry.output_surface = output_surface;
- CheckIsReady(routing_id);
+
+ SynchronousCompositorProxy* proxy = FindProxy(routing_id);
+ if (proxy) {
+ proxy->SetOutputSurface(output_surface);
+ }
}
void SynchronousCompositorFilter::UnregisterOutputSurface(
@@ -140,8 +146,10 @@ void SynchronousCompositorFilter::UnregisterOutputSurface(
Entry& entry = entry_map_[routing_id];
DCHECK_EQ(output_surface, entry.output_surface);
- if (entry.IsReady())
- UnregisterObjects(routing_id);
+ SynchronousCompositorProxy* proxy = FindProxy(routing_id);
+ if (proxy) {
+ proxy->SetOutputSurface(nullptr);
+ }
entry.output_surface = nullptr;
RemoveEntryIfNeeded(routing_id);
}
@@ -178,11 +186,12 @@ void SynchronousCompositorFilter::CheckIsReady(int routing_id) {
Entry& entry = entry_map_[routing_id];
if (filter_ready_ && entry.IsReady()) {
DCHECK(!sync_compositor_map_.contains(routing_id));
- sync_compositor_map_.add(
- routing_id,
- make_scoped_ptr(new SynchronousCompositorProxy(
- routing_id, this, entry.output_surface, entry.begin_frame_source,
- entry.synchronous_input_handler_proxy, &input_handler_)));
+ scoped_ptr<SynchronousCompositorProxy> proxy(new SynchronousCompositorProxy(
+ routing_id, this, entry.begin_frame_source,
+ entry.synchronous_input_handler_proxy, &input_handler_));
+ if (entry.output_surface)
+ proxy->SetOutputSurface(entry.output_surface);
+ sync_compositor_map_.add(routing_id, std::move(proxy));
}
}
@@ -210,13 +219,37 @@ void SynchronousCompositorFilter::SetBoundHandler(const Handler& handler) {
handler));
}
+void SynchronousCompositorFilter::DidAddInputHandler(int routing_id) {}
+void SynchronousCompositorFilter::DidRemoveInputHandler(int routing_id) {}
+
void SynchronousCompositorFilter::SetBoundHandlerOnCompositorThread(
const Handler& handler) {
DCHECK(compositor_task_runner_->BelongsToCurrentThread());
input_handler_ = handler;
}
-void SynchronousCompositorFilter::DidAddInputHandler(
+void SynchronousCompositorFilter::DidOverscroll(
+ int routing_id,
+ const DidOverscrollParams& params) {
+ DCHECK(compositor_task_runner_->BelongsToCurrentThread());
+ SynchronousCompositorProxy* proxy = FindProxy(routing_id);
+ if (!proxy) {
+ DLOG(WARNING) << "No matching proxy in DidOverScroll " << routing_id;
+ return;
+ }
+ proxy->DidOverscroll(params);
+}
+
+void SynchronousCompositorFilter::DidStopFlinging(int routing_id) {
+ DCHECK(compositor_task_runner_->BelongsToCurrentThread());
+ Send(new InputHostMsg_DidStopFlinging(routing_id));
+}
+
+void SynchronousCompositorFilter::NotifyInputEventHandled(
+ int routing_id,
+ blink::WebInputEvent::Type type) {}
+
+void SynchronousCompositorFilter::DidAddSynchronousHandlerProxy(
int routing_id,
ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy) {
DCHECK(compositor_task_runner_->BelongsToCurrentThread());
@@ -227,7 +260,8 @@ void SynchronousCompositorFilter::DidAddInputHandler(
CheckIsReady(routing_id);
}
-void SynchronousCompositorFilter::DidRemoveInputHandler(int routing_id) {
+void SynchronousCompositorFilter::DidRemoveSynchronousHandlerProxy(
+ int routing_id) {
DCHECK(compositor_task_runner_->BelongsToCurrentThread());
DCHECK(ContainsKey(entry_map_, routing_id));
Entry& entry = entry_map_[routing_id];
@@ -238,31 +272,13 @@ void SynchronousCompositorFilter::DidRemoveInputHandler(int routing_id) {
RemoveEntryIfNeeded(routing_id);
}
-void SynchronousCompositorFilter::DidOverscroll(
- int routing_id,
- const DidOverscrollParams& params) {
- DCHECK(compositor_task_runner_->BelongsToCurrentThread());
- SynchronousCompositorProxy* proxy = FindProxy(routing_id);
- if (!proxy) {
- DLOG(WARNING) << "No matching proxy in DidOverScroll " << routing_id;
- return;
- }
- proxy->DidOverscroll(params);
-}
-
-void SynchronousCompositorFilter::DidStopFlinging(int routing_id) {
- DCHECK(compositor_task_runner_->BelongsToCurrentThread());
- Send(new InputHostMsg_DidStopFlinging(routing_id));
-}
-
SynchronousCompositorFilter::Entry::Entry()
: begin_frame_source(nullptr),
output_surface(nullptr),
synchronous_input_handler_proxy(nullptr) {}
bool SynchronousCompositorFilter::Entry::IsReady() {
- return begin_frame_source && output_surface &&
- synchronous_input_handler_proxy;
+ return begin_frame_source && synchronous_input_handler_proxy;
}
} // namespace content
diff --git a/chromium/content/renderer/android/synchronous_compositor_filter.h b/chromium/content/renderer/android/synchronous_compositor_filter.h
index 89d83002029..dc31ecff0ee 100644
--- a/chromium/content/renderer/android/synchronous_compositor_filter.h
+++ b/chromium/content/renderer/android/synchronous_compositor_filter.h
@@ -9,6 +9,7 @@
#include "base/containers/scoped_ptr_hash_map.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/single_thread_task_runner.h"
#include "content/renderer/android/synchronous_compositor_registry.h"
#include "content/renderer/input/input_handler_manager_client.h"
@@ -23,10 +24,12 @@ namespace content {
class SynchronousCompositorProxy;
-class SynchronousCompositorFilter : public IPC::MessageFilter,
- public IPC::Sender,
- public SynchronousCompositorRegistry,
- public InputHandlerManagerClient {
+class SynchronousCompositorFilter
+ : public IPC::MessageFilter,
+ public IPC::Sender,
+ public SynchronousCompositorRegistry,
+ public InputHandlerManagerClient,
+ public SynchronousInputHandlerProxyClient {
public:
SynchronousCompositorFilter(const scoped_refptr<base::SingleThreadTaskRunner>&
compositor_task_runner);
@@ -58,14 +61,20 @@ class SynchronousCompositorFilter : public IPC::MessageFilter,
// InputHandlerManagerClient overrides.
void SetBoundHandler(const Handler& handler) override;
- void DidAddInputHandler(
- int routing_id,
- ui::SynchronousInputHandlerProxy*
- synchronous_input_handler_proxy) override;
+ void DidAddInputHandler(int routing_id) override;
void DidRemoveInputHandler(int routing_id) override;
void DidOverscroll(int routing_id,
const DidOverscrollParams& params) override;
void DidStopFlinging(int routing_id) override;
+ void NotifyInputEventHandled(int routing_id,
+ blink::WebInputEvent::Type type) override;
+
+ // SynchronousInputHandlerProxyClient overrides.
+ void DidAddSynchronousHandlerProxy(
+ int routing_id,
+ ui::SynchronousInputHandlerProxy* synchronous_input_handler_proxy)
+ override;
+ void DidRemoveSynchronousHandlerProxy(int routing_id) override;
private:
~SynchronousCompositorFilter() override;
diff --git a/chromium/content/renderer/android/synchronous_compositor_output_surface.cc b/chromium/content/renderer/android/synchronous_compositor_output_surface.cc
index cb41202d297..567de401f87 100644
--- a/chromium/content/renderer/android/synchronous_compositor_output_surface.cc
+++ b/chromium/content/renderer/android/synchronous_compositor_output_surface.cc
@@ -26,6 +26,8 @@ namespace content {
namespace {
+const int64_t kFallbackTickTimeoutInMilliseconds = 100;
+
// Do not limit number of resources, so use an unrealistically high value.
const size_t kNumResourcesLimit = 10 * 1000 * 1000;
@@ -62,6 +64,7 @@ SynchronousCompositorOutputSurface::SynchronousCompositorOutputSurface(
const scoped_refptr<cc::ContextProvider>& context_provider,
const scoped_refptr<cc::ContextProvider>& worker_context_provider,
int routing_id,
+ uint32_t output_surface_id,
SynchronousCompositorRegistry* registry,
scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue)
: cc::OutputSurface(
@@ -69,13 +72,16 @@ SynchronousCompositorOutputSurface::SynchronousCompositorOutputSurface(
worker_context_provider,
scoped_ptr<cc::SoftwareOutputDevice>(new SoftwareDevice(this))),
routing_id_(routing_id),
+ output_surface_id_(output_surface_id),
registry_(registry),
registered_(false),
sync_client_(nullptr),
current_sw_canvas_(nullptr),
memory_policy_(0u),
did_swap_(false),
- frame_swap_message_queue_(frame_swap_message_queue) {
+ frame_swap_message_queue_(frame_swap_message_queue),
+ fallback_tick_pending_(false),
+ fallback_tick_running_(false) {
thread_checker_.DetachFromThread();
DCHECK(registry_);
capabilities_.adjust_deadline_for_parent = false;
@@ -92,11 +98,6 @@ void SynchronousCompositorOutputSurface::SetSyncClient(
sync_client_ = compositor;
}
-void SynchronousCompositorOutputSurface::DidLoseOutputSurface() {
- // Android WebView does not handle context loss.
- LOG(FATAL) << "Renderer compositor context loss";
-}
-
bool SynchronousCompositorOutputSurface::BindToClient(
cc::OutputSurfaceClient* surface_client) {
DCHECK(CalledOnValidThread());
@@ -115,6 +116,7 @@ void SynchronousCompositorOutputSurface::DetachFromClient() {
registry_->UnregisterOutputSurface(routing_id_, this);
}
cc::OutputSurface::DetachFromClient();
+ CancelFallbackTick();
}
void SynchronousCompositorOutputSurface::Reshape(const gfx::Size& size,
@@ -127,15 +129,44 @@ void SynchronousCompositorOutputSurface::SwapBuffers(
cc::CompositorFrame* frame) {
DCHECK(CalledOnValidThread());
DCHECK(sync_client_);
- sync_client_->SwapBuffers(frame);
+ if (!fallback_tick_running_)
+ sync_client_->SwapBuffers(output_surface_id_, frame);
client_->DidSwapBuffers();
did_swap_ = true;
}
+void SynchronousCompositorOutputSurface::CancelFallbackTick() {
+ fallback_tick_.Cancel();
+ fallback_tick_pending_ = false;
+}
+
+void SynchronousCompositorOutputSurface::FallbackTickFired() {
+ DCHECK(CalledOnValidThread());
+ TRACE_EVENT0("renderer",
+ "SynchronousCompositorOutputSurface::FallbackTickFired");
+ base::AutoReset<bool> in_fallback_tick(&fallback_tick_running_, true);
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(1, 1);
+ bitmap.eraseColor(0);
+ SkCanvas canvas(bitmap);
+ fallback_tick_pending_ = false;
+ DemandDrawSw(&canvas);
+}
+
void SynchronousCompositorOutputSurface::Invalidate() {
DCHECK(CalledOnValidThread());
if (sync_client_)
sync_client_->Invalidate();
+
+ if (!fallback_tick_pending_) {
+ fallback_tick_.Reset(
+ base::Bind(&SynchronousCompositorOutputSurface::FallbackTickFired,
+ base::Unretained(this)));
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE, fallback_tick_.callback(),
+ base::TimeDelta::FromMilliseconds(kFallbackTickTimeoutInMilliseconds));
+ fallback_tick_pending_ = true;
+ }
}
void SynchronousCompositorOutputSurface::DemandDrawHw(
@@ -148,6 +179,7 @@ void SynchronousCompositorOutputSurface::DemandDrawHw(
DCHECK(CalledOnValidThread());
DCHECK(HasClient());
DCHECK(context_provider_.get());
+ CancelFallbackTick();
surface_size_ = surface_size;
client_->SetExternalTilePriorityConstraints(viewport_rect_for_tile_priority,
@@ -160,6 +192,7 @@ void SynchronousCompositorOutputSurface::DemandDrawSw(SkCanvas* canvas) {
DCHECK(CalledOnValidThread());
DCHECK(canvas);
DCHECK(!current_sw_canvas_);
+ CancelFallbackTick();
base::AutoReset<SkCanvas*> canvas_resetter(&current_sw_canvas_, canvas);
@@ -191,8 +224,10 @@ void SynchronousCompositorOutputSurface::InvokeComposite(
}
void SynchronousCompositorOutputSurface::ReturnResources(
+ uint32_t output_surface_id,
const cc::CompositorFrameAck& frame_ack) {
- ReclaimResources(&frame_ack);
+ if (output_surface_id_ == output_surface_id)
+ ReclaimResources(&frame_ack);
}
void SynchronousCompositorOutputSurface::SetMemoryPolicy(size_t bytes_limit) {
diff --git a/chromium/content/renderer/android/synchronous_compositor_output_surface.h b/chromium/content/renderer/android/synchronous_compositor_output_surface.h
index 7509460ab7b..97f4bf90727 100644
--- a/chromium/content/renderer/android/synchronous_compositor_output_surface.h
+++ b/chromium/content/renderer/android/synchronous_compositor_output_surface.h
@@ -10,6 +10,7 @@
#include <vector>
#include "base/callback.h"
+#include "base/cancelable_callback.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
@@ -39,7 +40,8 @@ class WebGraphicsContext3DCommandBufferImpl;
class SynchronousCompositorOutputSurfaceClient {
public:
virtual void Invalidate() = 0;
- virtual void SwapBuffers(cc::CompositorFrame* frame) = 0;
+ virtual void SwapBuffers(uint32_t output_surface_id,
+ cc::CompositorFrame* frame) = 0;
protected:
virtual ~SynchronousCompositorOutputSurfaceClient() {}
@@ -60,6 +62,7 @@ class SynchronousCompositorOutputSurface
const scoped_refptr<cc::ContextProvider>& context_provider,
const scoped_refptr<cc::ContextProvider>& worker_context_provider,
int routing_id,
+ uint32_t output_surface_id,
SynchronousCompositorRegistry* registry,
scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue);
~SynchronousCompositorOutputSurface() override;
@@ -67,7 +70,6 @@ class SynchronousCompositorOutputSurface
void SetSyncClient(SynchronousCompositorOutputSurfaceClient* compositor);
// OutputSurface.
- void DidLoseOutputSurface() override;
bool BindToClient(cc::OutputSurfaceClient* surface_client) override;
void DetachFromClient() override;
void Reshape(const gfx::Size& size,
@@ -83,7 +85,8 @@ class SynchronousCompositorOutputSurface
const gfx::Rect& clip,
const gfx::Rect& viewport_rect_for_tile_priority,
const gfx::Transform& transform_for_tile_priority);
- void ReturnResources(const cc::CompositorFrameAck& frame_ack);
+ void ReturnResources(uint32_t output_surface_id,
+ const cc::CompositorFrameAck& frame_ack);
void DemandDrawSw(SkCanvas* canvas);
void SetMemoryPolicy(size_t bytes_limit);
void SetTreeActivationCallback(const base::Closure& callback);
@@ -103,7 +106,11 @@ class SynchronousCompositorOutputSurface
bool hardware_draw);
bool CalledOnValidThread() const;
+ void CancelFallbackTick();
+ void FallbackTickFired();
+
const int routing_id_;
+ const uint32_t output_surface_id_;
SynchronousCompositorRegistry* const registry_; // unowned
bool registered_;
@@ -117,6 +124,10 @@ class SynchronousCompositorOutputSurface
bool did_swap_;
scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue_;
+ base::CancelableClosure fallback_tick_;
+ bool fallback_tick_pending_;
+ bool fallback_tick_running_;
+
base::ThreadChecker thread_checker_;
DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorOutputSurface);
diff --git a/chromium/content/renderer/android/synchronous_compositor_proxy.cc b/chromium/content/renderer/android/synchronous_compositor_proxy.cc
index e8fc5f3c9bf..dc9c00af7bc 100644
--- a/chromium/content/renderer/android/synchronous_compositor_proxy.cc
+++ b/chromium/content/renderer/android/synchronous_compositor_proxy.cc
@@ -5,9 +5,11 @@
#include "content/renderer/android/synchronous_compositor_proxy.h"
#include "base/auto_reset.h"
+#include "base/command_line.h"
#include "base/memory/shared_memory.h"
#include "content/common/android/sync_compositor_messages.h"
#include "content/common/cc_messages.h"
+#include "content/public/common/content_switches.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_sender.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -22,16 +24,18 @@ namespace content {
SynchronousCompositorProxy::SynchronousCompositorProxy(
int routing_id,
IPC::Sender* sender,
- SynchronousCompositorOutputSurface* output_surface,
SynchronousCompositorExternalBeginFrameSource* begin_frame_source,
ui::SynchronousInputHandlerProxy* input_handler_proxy,
InputHandlerManagerClient::Handler* handler)
: routing_id_(routing_id),
sender_(sender),
- output_surface_(output_surface),
begin_frame_source_(begin_frame_source),
input_handler_proxy_(input_handler_proxy),
input_handler_(handler),
+ use_in_process_zero_copy_software_draw_(
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSingleProcess)),
+ output_surface_(nullptr),
inside_receive_(false),
hardware_draw_reply_(nullptr),
software_draw_reply_(nullptr),
@@ -41,28 +45,39 @@ SynchronousCompositorProxy::SynchronousCompositorProxy(
min_page_scale_factor_(0.f),
max_page_scale_factor_(0.f),
need_animate_scroll_(false),
- need_invalidate_(false),
+ need_invalidate_count_(0u),
need_begin_frame_(false),
- did_activate_pending_tree_(false) {
- DCHECK(output_surface_);
+ did_activate_pending_tree_count_(0u) {
DCHECK(begin_frame_source_);
DCHECK(input_handler_proxy_);
DCHECK(input_handler_);
- output_surface_->SetSyncClient(this);
- output_surface_->SetTreeActivationCallback(
- base::Bind(&SynchronousCompositorProxy::DidActivatePendingTree,
- base::Unretained(this)));
begin_frame_source_->SetClient(this);
input_handler_proxy_->SetOnlySynchronouslyAnimateRootFlings(this);
}
SynchronousCompositorProxy::~SynchronousCompositorProxy() {
- output_surface_->SetSyncClient(nullptr);
- output_surface_->SetTreeActivationCallback(base::Closure());
+ SetOutputSurface(nullptr);
begin_frame_source_->SetClient(nullptr);
input_handler_proxy_->SetOnlySynchronouslyAnimateRootFlings(nullptr);
}
+void SynchronousCompositorProxy::SetOutputSurface(
+ SynchronousCompositorOutputSurface* output_surface) {
+ DCHECK_NE(output_surface_, output_surface);
+ if (output_surface_) {
+ output_surface_->SetSyncClient(nullptr);
+ output_surface_->SetTreeActivationCallback(base::Closure());
+ }
+ output_surface_ = output_surface;
+ if (output_surface_) {
+ output_surface_->SetSyncClient(this);
+ output_surface_->SetTreeActivationCallback(
+ base::Bind(&SynchronousCompositorProxy::DidActivatePendingTree,
+ base::Unretained(this)));
+ output_surface_->SetMemoryPolicy(bytes_limit_);
+ }
+}
+
void SynchronousCompositorProxy::SetNeedsSynchronousAnimateInput() {
need_animate_scroll_ = true;
Invalidate();
@@ -101,17 +116,18 @@ void SynchronousCompositorProxy::OnNeedsBeginFramesChange(
}
void SynchronousCompositorProxy::Invalidate() {
- need_invalidate_ = true;
+ ++need_invalidate_count_;
SendAsyncRendererStateIfNeeded();
}
void SynchronousCompositorProxy::DidActivatePendingTree() {
- did_activate_pending_tree_ = true;
+ ++did_activate_pending_tree_count_;
SendAsyncRendererStateIfNeeded();
DeliverMessages();
}
void SynchronousCompositorProxy::DeliverMessages() {
+ DCHECK(output_surface_);
std::vector<scoped_ptr<IPC::Message>> messages;
output_surface_->GetMessagesToDeliver(&messages);
for (auto& msg : messages) {
@@ -128,7 +144,7 @@ void SynchronousCompositorProxy::SendAsyncRendererStateIfNeeded() {
}
void SynchronousCompositorProxy::PopulateCommonParams(
- SyncCompositorCommonRendererParams* params) {
+ SyncCompositorCommonRendererParams* params) const {
params->version = ++version_;
params->total_scroll_offset = total_scroll_offset_;
params->max_scroll_offset = max_scroll_offset_;
@@ -137,12 +153,9 @@ void SynchronousCompositorProxy::PopulateCommonParams(
params->min_page_scale_factor = min_page_scale_factor_;
params->max_page_scale_factor = max_page_scale_factor_;
params->need_animate_scroll = need_animate_scroll_;
- params->need_invalidate = need_invalidate_;
+ params->need_invalidate_count = need_invalidate_count_;
params->need_begin_frame = need_begin_frame_;
- params->did_activate_pending_tree = did_activate_pending_tree_;
-
- need_invalidate_ = false;
- did_activate_pending_tree_ = false;
+ params->did_activate_pending_tree_count = did_activate_pending_tree_count_;
}
void SynchronousCompositorProxy::OnMessageReceived(
@@ -158,6 +171,7 @@ void SynchronousCompositorProxy::OnMessageReceived(
IPC_MESSAGE_HANDLER_DELAY_REPLY(SyncCompositorMsg_DemandDrawSw,
DemandDrawSw)
IPC_MESSAGE_HANDLER(SyncCompositorMsg_UpdateState, ProcessCommonParams)
+ IPC_MESSAGE_HANDLER(SyncCompositorMsg_ZoomBy, SynchronouslyZoomBy)
IPC_END_MESSAGE_MAP()
}
@@ -204,7 +218,7 @@ void SynchronousCompositorProxy::DemandDrawHw(
inside_receive_ = true;
ProcessCommonParams(common_params);
- {
+ if (output_surface_) {
base::AutoReset<IPC::Message*> scoped_hardware_draw_reply(
&hardware_draw_reply_, reply_message);
output_surface_->DemandDrawHw(params.surface_size, params.transform,
@@ -216,30 +230,30 @@ void SynchronousCompositorProxy::DemandDrawHw(
if (inside_receive_) {
// Did not swap.
cc::CompositorFrame empty_frame;
- SendDemandDrawHwReply(&empty_frame, reply_message);
+ SendDemandDrawHwReply(&empty_frame, 0u, reply_message);
inside_receive_ = false;
} else {
DeliverMessages();
}
}
-void SynchronousCompositorProxy::SwapBuffersHw(cc::CompositorFrame* frame) {
+void SynchronousCompositorProxy::SwapBuffersHw(uint32_t output_surface_id,
+ cc::CompositorFrame* frame) {
DCHECK(inside_receive_);
DCHECK(hardware_draw_reply_);
DCHECK(frame);
- SendDemandDrawHwReply(frame, hardware_draw_reply_);
+ SendDemandDrawHwReply(frame, output_surface_id, hardware_draw_reply_);
inside_receive_ = false;
}
void SynchronousCompositorProxy::SendDemandDrawHwReply(
cc::CompositorFrame* frame,
+ uint32_t output_surface_id,
IPC::Message* reply_message) {
SyncCompositorCommonRendererParams common_renderer_params;
PopulateCommonParams(&common_renderer_params);
- // Not using WriteParams because cc::CompositorFrame is not copy-able.
- IPC::ParamTraits<SyncCompositorCommonRendererParams>::Write(
- reply_message, common_renderer_params);
- IPC::ParamTraits<cc::CompositorFrame>::Write(reply_message, *frame);
+ SyncCompositorMsg_DemandDrawHw::WriteReplyParams(
+ reply_message, common_renderer_params, output_surface_id, *frame);
Send(reply_message);
}
@@ -274,6 +288,19 @@ void SynchronousCompositorProxy::SetSharedMemory(
*success = true;
}
+namespace {
+SkCanvas* g_sk_canvas_for_draw = nullptr;
+}
+
+// static
+void SynchronousCompositorProxy::SetSkCanvasForDraw(SkCanvas* canvas) {
+ DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kSingleProcess));
+ DCHECK(canvas || g_sk_canvas_for_draw) << !!canvas;
+ DCHECK(!canvas || !g_sk_canvas_for_draw) << !!canvas;
+ g_sk_canvas_for_draw = canvas;
+}
+
void SynchronousCompositorProxy::ZeroSharedMemory() {
DCHECK(!software_draw_shm_->zeroed);
memset(software_draw_shm_->shm.memory(), 0, software_draw_shm_->buffer_size);
@@ -287,10 +314,16 @@ void SynchronousCompositorProxy::DemandDrawSw(
DCHECK(!inside_receive_);
inside_receive_ = true;
ProcessCommonParams(common_params);
- {
+ if (output_surface_) {
base::AutoReset<IPC::Message*> scoped_software_draw_reply(
&software_draw_reply_, reply_message);
- DoDemandDrawSw(params);
+ if (use_in_process_zero_copy_software_draw_) {
+ DCHECK(g_sk_canvas_for_draw);
+ output_surface_->DemandDrawSw(g_sk_canvas_for_draw);
+ } else {
+ DCHECK(!g_sk_canvas_for_draw);
+ DoDemandDrawSw(params);
+ }
}
if (inside_receive_) {
// Did not swap.
@@ -304,6 +337,7 @@ void SynchronousCompositorProxy::DemandDrawSw(
void SynchronousCompositorProxy::DoDemandDrawSw(
const SyncCompositorDemandDrawSwParams& params) {
+ DCHECK(output_surface_);
DCHECK(software_draw_shm_->zeroed);
software_draw_shm_->zeroed = false;
@@ -337,19 +371,17 @@ void SynchronousCompositorProxy::SendDemandDrawSwReply(
IPC::Message* reply_message) {
SyncCompositorCommonRendererParams common_renderer_params;
PopulateCommonParams(&common_renderer_params);
- // Not using WriteParams because cc::CompositorFrame is not copy-able.
- IPC::ParamTraits<bool>::Write(reply_message, success);
- IPC::ParamTraits<SyncCompositorCommonRendererParams>::Write(
- reply_message, common_renderer_params);
- IPC::ParamTraits<cc::CompositorFrame>::Write(reply_message, *frame);
+ SyncCompositorMsg_DemandDrawSw::WriteReplyParams(
+ reply_message, success, common_renderer_params, *frame);
Send(reply_message);
}
-void SynchronousCompositorProxy::SwapBuffers(cc::CompositorFrame* frame) {
+void SynchronousCompositorProxy::SwapBuffers(uint32_t output_surface_id,
+ cc::CompositorFrame* frame) {
DCHECK(hardware_draw_reply_ || software_draw_reply_);
DCHECK(!(hardware_draw_reply_ && software_draw_reply_));
if (hardware_draw_reply_) {
- SwapBuffersHw(frame);
+ SwapBuffersHw(output_surface_id, frame);
} else if (software_draw_reply_) {
SwapBuffersSw(frame);
}
@@ -357,16 +389,23 @@ void SynchronousCompositorProxy::SwapBuffers(cc::CompositorFrame* frame) {
void SynchronousCompositorProxy::OnComputeScroll(
const SyncCompositorCommonBrowserParams& common_params,
- base::TimeTicks animation_time,
- SyncCompositorCommonRendererParams* common_renderer_params) {
- DCHECK(!inside_receive_);
- base::AutoReset<bool> scoped_inside_receive(&inside_receive_, true);
-
+ base::TimeTicks animation_time) {
ProcessCommonParams(common_params);
if (need_animate_scroll_) {
need_animate_scroll_ = false;
input_handler_proxy_->SynchronouslyAnimate(animation_time);
}
+}
+
+void SynchronousCompositorProxy::SynchronouslyZoomBy(
+ const SyncCompositorCommonBrowserParams& common_params,
+ float zoom_delta,
+ const gfx::Point& anchor,
+ SyncCompositorCommonRendererParams* common_renderer_params) {
+ DCHECK(!inside_receive_);
+ base::AutoReset<bool> scoped_inside_receive(&inside_receive_, true);
+ ProcessCommonParams(common_params);
+ input_handler_proxy_->SynchronouslyZoomBy(zoom_delta, anchor);
PopulateCommonParams(common_renderer_params);
}
@@ -382,7 +421,8 @@ void SynchronousCompositorProxy::ProcessCommonParams(
const SyncCompositorCommonBrowserParams& common_params) {
if (bytes_limit_ != common_params.bytes_limit) {
bytes_limit_ = common_params.bytes_limit;
- output_surface_->SetMemoryPolicy(bytes_limit_);
+ if (output_surface_)
+ output_surface_->SetMemoryPolicy(bytes_limit_);
}
if (common_params.update_root_scroll_offset &&
total_scroll_offset_ != common_params.root_scroll_offset) {
@@ -392,8 +432,10 @@ void SynchronousCompositorProxy::ProcessCommonParams(
}
begin_frame_source_->SetBeginFrameSourcePaused(
common_params.begin_frame_source_paused);
- if (!common_params.ack.resources.empty()) {
- output_surface_->ReturnResources(common_params.ack);
+ if (output_surface_ && !common_params.ack.resources.empty()) {
+ output_surface_->ReturnResources(
+ common_params.output_surface_id_for_returned_resources,
+ common_params.ack);
}
}
diff --git a/chromium/content/renderer/android/synchronous_compositor_proxy.h b/chromium/content/renderer/android/synchronous_compositor_proxy.h
index aca6819b497..8d89833795f 100644
--- a/chromium/content/renderer/android/synchronous_compositor_proxy.h
+++ b/chromium/content/renderer/android/synchronous_compositor_proxy.h
@@ -17,6 +17,8 @@
#include "ui/gfx/geometry/scroll_offset.h"
#include "ui/gfx/geometry/size_f.h"
+class SkCanvas;
+
namespace IPC {
class Message;
class Sender;
@@ -44,10 +46,12 @@ class SynchronousCompositorProxy
public SynchronousCompositorExternalBeginFrameSourceClient,
public SynchronousCompositorOutputSurfaceClient {
public:
+ // Called by browser side.
+ static void SetSkCanvasForDraw(SkCanvas* canvas);
+
SynchronousCompositorProxy(
int routing_id,
IPC::Sender* sender,
- SynchronousCompositorOutputSurface* output_surface,
SynchronousCompositorExternalBeginFrameSource* begin_frame_source,
ui::SynchronousInputHandlerProxy* input_handler_proxy,
InputHandlerManagerClient::Handler* handler);
@@ -67,8 +71,10 @@ class SynchronousCompositorProxy
// SynchronousCompositorOutputSurfaceClient overrides.
void Invalidate() override;
- void SwapBuffers(cc::CompositorFrame* frame) override;
+ void SwapBuffers(uint32_t output_surface_id,
+ cc::CompositorFrame* frame) override;
+ void SetOutputSurface(SynchronousCompositorOutputSurface* output_surface);
void OnMessageReceived(const IPC::Message& message);
bool Send(IPC::Message* message);
void DidOverscroll(const DidOverscrollParams& did_overscroll_params);
@@ -78,7 +84,7 @@ class SynchronousCompositorProxy
void ProcessCommonParams(
const SyncCompositorCommonBrowserParams& common_params);
- void PopulateCommonParams(SyncCompositorCommonRendererParams* params);
+ void PopulateCommonParams(SyncCompositorCommonRendererParams* params) const;
// IPC handlers.
void HandleInputEvent(
@@ -89,10 +95,8 @@ class SynchronousCompositorProxy
void BeginFrame(const SyncCompositorCommonBrowserParams& common_params,
const cc::BeginFrameArgs& args,
SyncCompositorCommonRendererParams* common_renderer_params);
- void OnComputeScroll(
- const SyncCompositorCommonBrowserParams& common_params,
- base::TimeTicks animation_time,
- SyncCompositorCommonRendererParams* common_renderer_params);
+ void OnComputeScroll(const SyncCompositorCommonBrowserParams& common_params,
+ base::TimeTicks animation_time);
void DemandDrawHw(const SyncCompositorCommonBrowserParams& common_params,
const SyncCompositorDemandDrawHwParams& params,
IPC::Message* reply_message);
@@ -105,9 +109,15 @@ class SynchronousCompositorProxy
void DemandDrawSw(const SyncCompositorCommonBrowserParams& common_params,
const SyncCompositorDemandDrawSwParams& params,
IPC::Message* reply_message);
+ void SynchronouslyZoomBy(
+ const SyncCompositorCommonBrowserParams& common_params,
+ float zoom_delta,
+ const gfx::Point& anchor,
+ SyncCompositorCommonRendererParams* common_renderer_params);
- void SwapBuffersHw(cc::CompositorFrame* frame);
+ void SwapBuffersHw(uint32_t output_surface_id, cc::CompositorFrame* frame);
void SendDemandDrawHwReply(cc::CompositorFrame* frame,
+ uint32_t output_surface_id,
IPC::Message* reply_message);
void DoDemandDrawSw(const SyncCompositorDemandDrawSwParams& params);
void SwapBuffersSw(cc::CompositorFrame* frame);
@@ -120,10 +130,11 @@ class SynchronousCompositorProxy
const int routing_id_;
IPC::Sender* const sender_;
- SynchronousCompositorOutputSurface* const output_surface_;
SynchronousCompositorExternalBeginFrameSource* const begin_frame_source_;
ui::SynchronousInputHandlerProxy* const input_handler_proxy_;
InputHandlerManagerClient::Handler* const input_handler_;
+ const bool use_in_process_zero_copy_software_draw_;
+ SynchronousCompositorOutputSurface* output_surface_;
bool inside_receive_;
IPC::Message* hardware_draw_reply_;
IPC::Message* software_draw_reply_;
@@ -133,7 +144,7 @@ class SynchronousCompositorProxy
scoped_ptr<SharedMemoryWithSize> software_draw_shm_;
// To browser.
- uint32_t version_;
+ mutable uint32_t version_; // Mustable so PopulateCommonParams can be const.
gfx::ScrollOffset total_scroll_offset_; // Modified by both.
gfx::ScrollOffset max_scroll_offset_;
gfx::SizeF scrollable_size_;
@@ -141,9 +152,9 @@ class SynchronousCompositorProxy
float min_page_scale_factor_;
float max_page_scale_factor_;
bool need_animate_scroll_;
- bool need_invalidate_;
+ uint32_t need_invalidate_count_;
bool need_begin_frame_;
- bool did_activate_pending_tree_;
+ uint32_t did_activate_pending_tree_count_;
DISALLOW_COPY_AND_ASSIGN(SynchronousCompositorProxy);
};
diff --git a/chromium/content/renderer/background_sync/background_sync_client_impl.cc b/chromium/content/renderer/background_sync/background_sync_client_impl.cc
index 4b1c928c0ee..58bfe2bbfd4 100644
--- a/chromium/content/renderer/background_sync/background_sync_client_impl.cc
+++ b/chromium/content/renderer/background_sync/background_sync_client_impl.cc
@@ -19,77 +19,34 @@ namespace content {
// static
void BackgroundSyncClientImpl::Create(
- mojo::InterfaceRequest<BackgroundSyncServiceClient> request) {
+ mojo::InterfaceRequest<mojom::BackgroundSyncServiceClient> request) {
new BackgroundSyncClientImpl(std::move(request));
}
BackgroundSyncClientImpl::~BackgroundSyncClientImpl() {}
BackgroundSyncClientImpl::BackgroundSyncClientImpl(
- mojo::InterfaceRequest<BackgroundSyncServiceClient> request)
- : binding_(this, std::move(request)), callback_seq_num_(0) {}
+ mojo::InterfaceRequest<mojom::BackgroundSyncServiceClient> request)
+ : binding_(this, std::move(request)) {}
void BackgroundSyncClientImpl::Sync(
- int64_t handle_id,
- content::BackgroundSyncEventLastChance last_chance,
+ const mojo::String& tag,
+ content::mojom::BackgroundSyncEventLastChance last_chance,
const SyncCallback& callback) {
DCHECK(!blink::Platform::current()->mainThread()->isCurrentThread());
- // Get a registration for the given handle_id from the provider. This way
- // the provider knows about the handle and can delete it once Blink releases
- // it.
- // TODO(jkarlin): Change the WebSyncPlatform to support
- // DuplicateRegistrationHandle and then this cast can go.
- BackgroundSyncProvider* provider = static_cast<BackgroundSyncProvider*>(
- blink::Platform::current()->backgroundSyncProvider());
-
- if (provider == nullptr) {
- // This can happen if the renderer is shutting down when sync fires. See
- // crbug.com/543898. No need to fire the callback as the browser will
- // automatically fail all pending sync events when the mojo connection
- // closes.
- return;
- }
-
- // TODO(jkarlin): Find a way to claim the handle safely without requiring a
- // round-trip IPC.
- int64_t id = ++callback_seq_num_;
- sync_callbacks_[id] = callback;
- provider->DuplicateRegistrationHandle(
- handle_id, base::Bind(&BackgroundSyncClientImpl::SyncDidGetRegistration,
- base::Unretained(this), id, last_chance));
-}
-
-void BackgroundSyncClientImpl::SyncDidGetRegistration(
- int64_t callback_id,
- content::BackgroundSyncEventLastChance last_chance,
- BackgroundSyncError error,
- SyncRegistrationPtr registration) {
- SyncCallback callback;
- auto it = sync_callbacks_.find(callback_id);
- DCHECK(it != sync_callbacks_.end());
- callback = it->second;
- sync_callbacks_.erase(it);
-
- if (error != BACKGROUND_SYNC_ERROR_NONE) {
- callback.Run(SERVICE_WORKER_EVENT_STATUS_ABORTED);
- return;
- }
ServiceWorkerContextClient* client =
ServiceWorkerContextClient::ThreadSpecificInstance();
if (!client) {
- callback.Run(SERVICE_WORKER_EVENT_STATUS_ABORTED);
+ callback.Run(mojom::ServiceWorkerEventStatus::ABORTED);
return;
}
- scoped_ptr<blink::WebSyncRegistration> web_registration =
- mojo::ConvertTo<scoped_ptr<blink::WebSyncRegistration>>(registration);
-
blink::WebServiceWorkerContextProxy::LastChanceOption web_last_chance =
mojo::ConvertTo<blink::WebServiceWorkerContextProxy::LastChanceOption>(
last_chance);
- client->DispatchSyncEvent(*web_registration, web_last_chance, callback);
+ client->DispatchSyncEvent(tag, web_last_chance, callback);
}
} // namespace content
diff --git a/chromium/content/renderer/background_sync/background_sync_client_impl.h b/chromium/content/renderer/background_sync/background_sync_client_impl.h
index 3b209b343e0..d977ff12b0c 100644
--- a/chromium/content/renderer/background_sync/background_sync_client_impl.h
+++ b/chromium/content/renderer/background_sync/background_sync_client_impl.h
@@ -18,32 +18,24 @@
namespace content {
class CONTENT_EXPORT BackgroundSyncClientImpl
- : public NON_EXPORTED_BASE(BackgroundSyncServiceClient) {
+ : public NON_EXPORTED_BASE(mojom::BackgroundSyncServiceClient) {
public:
static void Create(
- mojo::InterfaceRequest<BackgroundSyncServiceClient> request);
+ mojo::InterfaceRequest<mojom::BackgroundSyncServiceClient> request);
~BackgroundSyncClientImpl() override;
private:
- using SyncCallback = mojo::Callback<void(ServiceWorkerEventStatus)>;
+ using SyncCallback = mojo::Callback<void(mojom::ServiceWorkerEventStatus)>;
explicit BackgroundSyncClientImpl(
- mojo::InterfaceRequest<BackgroundSyncServiceClient> request);
+ mojo::InterfaceRequest<mojom::BackgroundSyncServiceClient> request);
// BackgroundSyncServiceClient methods:
- void Sync(int64_t handle_id,
- content::BackgroundSyncEventLastChance last_chance,
+ void Sync(const mojo::String& tag,
+ content::mojom::BackgroundSyncEventLastChance last_chance,
const SyncCallback& callback) override;
- void SyncDidGetRegistration(
- int64_t callback_id,
- content::BackgroundSyncEventLastChance last_chance,
- BackgroundSyncError error,
- SyncRegistrationPtr registration);
- mojo::StrongBinding<BackgroundSyncServiceClient> binding_;
-
- int64_t callback_seq_num_;
- std::map<int64_t, SyncCallback> sync_callbacks_;
+ mojo::StrongBinding<mojom::BackgroundSyncServiceClient> binding_;
DISALLOW_COPY_AND_ASSIGN(BackgroundSyncClientImpl);
};
diff --git a/chromium/content/renderer/battery_status/OWNERS b/chromium/content/renderer/battery_status/OWNERS
deleted file mode 100644
index 1fd89e0e2eb..00000000000
--- a/chromium/content/renderer/battery_status/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-timvolodine@chromium.org
diff --git a/chromium/content/renderer/battery_status/battery_status_dispatcher.cc b/chromium/content/renderer/battery_status/battery_status_dispatcher.cc
deleted file mode 100644
index 1034cb36d38..00000000000
--- a/chromium/content/renderer/battery_status/battery_status_dispatcher.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/battery_status/battery_status_dispatcher.h"
-
-#include "content/public/common/service_registry.h"
-#include "content/public/renderer/render_thread.h"
-#include "third_party/WebKit/public/platform/WebBatteryStatusListener.h"
-
-namespace content {
-
-BatteryStatusDispatcher::BatteryStatusDispatcher(
- blink::WebBatteryStatusListener* listener)
- : listener_(listener) {
- DCHECK(listener_);
-
- if (ServiceRegistry* registry = RenderThread::Get()->GetServiceRegistry()) {
- // registry can be null during testing.
- registry->ConnectToRemoteService(mojo::GetProxy(&monitor_));
- QueryNextStatus();
- }
-}
-
-BatteryStatusDispatcher::~BatteryStatusDispatcher() {
-}
-
-void BatteryStatusDispatcher::QueryNextStatus() {
- monitor_->QueryNextStatus(
- base::Bind(&BatteryStatusDispatcher::DidChange, base::Unretained(this)));
-}
-
-void BatteryStatusDispatcher::DidChange(
- device::BatteryStatusPtr battery_status) {
- // monitor_ can be null during testing.
- if (monitor_)
- QueryNextStatus();
-
- DCHECK(battery_status);
-
- blink::WebBatteryStatus web_battery_status;
- web_battery_status.charging = battery_status->charging;
- web_battery_status.chargingTime = battery_status->charging_time;
- web_battery_status.dischargingTime = battery_status->discharging_time;
- web_battery_status.level = battery_status->level;
- listener_->updateBatteryStatus(web_battery_status);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/battery_status/battery_status_dispatcher.h b/chromium/content/renderer/battery_status/battery_status_dispatcher.h
deleted file mode 100644
index f117a4b385e..00000000000
--- a/chromium/content/renderer/battery_status/battery_status_dispatcher.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_BATTERY_STATUS_BATTERY_STATUS_DISPATCHER_H_
-#define CONTENT_RENDERER_BATTERY_STATUS_BATTERY_STATUS_DISPATCHER_H_
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "content/common/content_export.h"
-#include "device/battery/battery_monitor.mojom.h"
-
-namespace blink {
-class WebBatteryStatusListener;
-}
-
-namespace content {
-
-class CONTENT_EXPORT BatteryStatusDispatcher {
- public:
- explicit BatteryStatusDispatcher(blink::WebBatteryStatusListener* listener);
- ~BatteryStatusDispatcher();
-
- private:
- friend class BatteryStatusDispatcherTest;
-
- void QueryNextStatus();
- void DidChange(device::BatteryStatusPtr battery_status);
-
- device::BatteryMonitorPtr monitor_;
- blink::WebBatteryStatusListener* listener_;
-
- DISALLOW_COPY_AND_ASSIGN(BatteryStatusDispatcher);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_BATTERY_STATUS_BATTERY_STATUS_DISPATCHER_H_
diff --git a/chromium/content/renderer/battery_status/battery_status_dispatcher_unittest.cc b/chromium/content/renderer/battery_status/battery_status_dispatcher_unittest.cc
deleted file mode 100644
index 5af344546b7..00000000000
--- a/chromium/content/renderer/battery_status/battery_status_dispatcher_unittest.cc
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/battery_status/battery_status_dispatcher.h"
-
-#include <utility>
-
-#include "base/macros.h"
-#include "content/public/test/mock_render_thread.h"
-#include "content/public/test/test_utils.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/platform/WebBatteryStatusListener.h"
-
-namespace content {
-
-class MockBatteryStatusListener : public blink::WebBatteryStatusListener {
- public:
- MockBatteryStatusListener() : did_change_battery_status_(false) {}
- ~MockBatteryStatusListener() override {}
-
- // blink::WebBatteryStatusListener method.
- void updateBatteryStatus(const blink::WebBatteryStatus& status) override {
- status_ = status;
- did_change_battery_status_ = true;
- }
-
- const blink::WebBatteryStatus& status() const { return status_; }
- bool did_change_battery_status() const { return did_change_battery_status_; }
-
- private:
- bool did_change_battery_status_;
- blink::WebBatteryStatus status_;
-
- DISALLOW_COPY_AND_ASSIGN(MockBatteryStatusListener);
-};
-
-class BatteryStatusDispatcherTest : public testing::Test {
- public:
- void UpdateBatteryStatus(const device::BatteryStatus& status) {
- device::BatteryStatusPtr status_ptr(device::BatteryStatus::New());
- *status_ptr = status;
- dispatcher_->DidChange(std::move(status_ptr));
- }
-
- const MockBatteryStatusListener& listener() const {
- return listener_;
- }
-
- protected:
- void SetUp() override {
- dispatcher_.reset(new BatteryStatusDispatcher(&listener_));
- }
-
- private:
- // We need to create a MockRenderThread so RenderThread::Get() doesn't return
- // null.
- MockRenderThread render_thread_;
- MockBatteryStatusListener listener_;
- scoped_ptr<BatteryStatusDispatcher> dispatcher_;
-};
-
-TEST_F(BatteryStatusDispatcherTest, UpdateListener) {
- // TODO(darin): This test isn't super interesting. It just exercises
- // conversion b/w device::BatteryStatus and blink::WebBatteryStatus.
-
- device::BatteryStatus status;
- status.charging = true;
- status.charging_time = 100;
- status.discharging_time = 200;
- status.level = 0.5;
-
- UpdateBatteryStatus(status);
-
- const blink::WebBatteryStatus& received_status = listener().status();
- EXPECT_TRUE(listener().did_change_battery_status());
- EXPECT_EQ(status.charging, received_status.charging);
- EXPECT_EQ(status.charging_time, received_status.chargingTime);
- EXPECT_EQ(status.discharging_time, received_status.dischargingTime);
- EXPECT_EQ(status.level, received_status.level);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/bluetooth/bluetooth_dispatcher.cc b/chromium/content/renderer/bluetooth/bluetooth_dispatcher.cc
index bc91cc632d0..37805454bfc 100644
--- a/chromium/content/renderer/bluetooth/bluetooth_dispatcher.cc
+++ b/chromium/content/renderer/bluetooth/bluetooth_dispatcher.cc
@@ -6,28 +6,29 @@
#include <stddef.h>
+#include <memory>
+#include <utility>
+
#include "base/lazy_instance.h"
+#include "base/memory/ptr_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/thread_task_runner_handle.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/bluetooth/bluetooth_messages.h"
#include "device/bluetooth/bluetooth_uuid.h"
-#include "third_party/WebKit/public/platform/WebPassOwnPtr.h"
#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothDevice.h"
#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothError.h"
-#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTCharacteristic.h"
-#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTCharacteristicInit.h"
-#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTRemoteServer.h"
-#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothGATTService.h"
+#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothRemoteGATTCharacteristic.h"
+#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothRemoteGATTCharacteristicInit.h"
+#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetoothRemoteGATTService.h"
#include "third_party/WebKit/public/platform/modules/bluetooth/WebRequestDeviceOptions.h"
-using blink::WebBluetoothConnectGATTCallbacks;
using blink::WebBluetoothDevice;
using blink::WebBluetoothError;
-using blink::WebBluetoothGATTCharacteristicInit;
-using blink::WebBluetoothGATTRemoteServer;
-using blink::WebBluetoothGATTService;
+using blink::WebBluetoothRemoteGATTCharacteristicInit;
+using blink::WebBluetoothRemoteGATTServerConnectCallbacks;
+using blink::WebBluetoothRemoteGATTService;
using blink::WebBluetoothReadValueCallbacks;
using blink::WebBluetoothRequestDeviceCallbacks;
using blink::WebBluetoothScanFilter;
@@ -67,12 +68,23 @@ struct BluetoothCharacteristicRequest {
scoped_ptr<blink::WebBluetoothGetCharacteristicCallbacks> callbacks;
};
+struct BluetoothCharacteristicsRequest {
+ BluetoothCharacteristicsRequest(
+ blink::WebString service_instance_id,
+ blink::WebBluetoothGetCharacteristicsCallbacks* callbacks)
+ : service_instance_id(service_instance_id), callbacks(callbacks) {}
+ ~BluetoothCharacteristicsRequest() {}
+
+ blink::WebString service_instance_id;
+ scoped_ptr<blink::WebBluetoothGetCharacteristicsCallbacks> callbacks;
+};
+
// Struct that holds a pending Start/StopNotifications request.
struct BluetoothNotificationsRequest {
BluetoothNotificationsRequest(
int frame_routing_id,
const std::string characteristic_instance_id,
- blink::WebBluetoothGATTCharacteristic* characteristic,
+ blink::WebBluetoothRemoteGATTCharacteristic* characteristic,
blink::WebBluetoothNotificationsCallbacks* callbacks,
NotificationsRequestType type)
: frame_routing_id(frame_routing_id),
@@ -90,7 +102,7 @@ struct BluetoothNotificationsRequest {
// destroyed, which in turn calls characteristicObjectRemoved.
// characteristicObjectRemoved will null any pointers to the object
// and queue a stop notifications request if necessary.
- blink::WebBluetoothGATTCharacteristic* characteristic;
+ blink::WebBluetoothRemoteGATTCharacteristic* characteristic;
scoped_ptr<blink::WebBluetoothNotificationsCallbacks> callbacks;
NotificationsRequestType type;
};
@@ -158,8 +170,10 @@ void BluetoothDispatcher::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(BluetoothMsg_RequestDeviceSuccess,
OnRequestDeviceSuccess);
IPC_MESSAGE_HANDLER(BluetoothMsg_RequestDeviceError, OnRequestDeviceError);
- IPC_MESSAGE_HANDLER(BluetoothMsg_ConnectGATTSuccess, OnConnectGATTSuccess);
- IPC_MESSAGE_HANDLER(BluetoothMsg_ConnectGATTError, OnConnectGATTError);
+ IPC_MESSAGE_HANDLER(BluetoothMsg_GATTServerConnectSuccess,
+ OnGATTServerConnectSuccess);
+ IPC_MESSAGE_HANDLER(BluetoothMsg_GATTServerConnectError,
+ OnGATTServerConnectError);
IPC_MESSAGE_HANDLER(BluetoothMsg_GetPrimaryServiceSuccess,
OnGetPrimaryServiceSuccess);
IPC_MESSAGE_HANDLER(BluetoothMsg_GetPrimaryServiceError,
@@ -168,14 +182,14 @@ void BluetoothDispatcher::OnMessageReceived(const IPC::Message& msg) {
OnGetCharacteristicSuccess);
IPC_MESSAGE_HANDLER(BluetoothMsg_GetCharacteristicError,
OnGetCharacteristicError);
+ IPC_MESSAGE_HANDLER(BluetoothMsg_GetCharacteristicsSuccess,
+ OnGetCharacteristicsSuccess);
+ IPC_MESSAGE_HANDLER(BluetoothMsg_GetCharacteristicsError,
+ OnGetCharacteristicsError);
IPC_MESSAGE_HANDLER(BluetoothMsg_ReadCharacteristicValueSuccess,
OnReadValueSuccess);
IPC_MESSAGE_HANDLER(BluetoothMsg_ReadCharacteristicValueError,
OnReadValueError);
- IPC_MESSAGE_HANDLER(BluetoothMsg_WriteCharacteristicValueSuccess,
- OnWriteValueSuccess);
- IPC_MESSAGE_HANDLER(BluetoothMsg_WriteCharacteristicValueError,
- OnWriteValueError);
IPC_MESSAGE_HANDLER(BluetoothMsg_StartNotificationsSuccess,
OnStartNotificationsSuccess)
IPC_MESSAGE_HANDLER(BluetoothMsg_StartNotificationsError,
@@ -218,13 +232,19 @@ void BluetoothDispatcher::requestDevice(
optional_services));
}
-void BluetoothDispatcher::connectGATT(
+void BluetoothDispatcher::connect(
int frame_routing_id,
const blink::WebString& device_id,
- blink::WebBluetoothConnectGATTCallbacks* callbacks) {
+ blink::WebBluetoothRemoteGATTServerConnectCallbacks* callbacks) {
int request_id = pending_connect_requests_.Add(callbacks);
- Send(new BluetoothHostMsg_ConnectGATT(CurrentWorkerId(), request_id,
- frame_routing_id, device_id.utf8()));
+ Send(new BluetoothHostMsg_GATTServerConnect(
+ CurrentWorkerId(), request_id, frame_routing_id, device_id.utf8()));
+}
+
+void BluetoothDispatcher::disconnect(int frame_routing_id,
+ const blink::WebString& device_id) {
+ Send(new BluetoothHostMsg_GATTServerDisconnect(
+ CurrentWorkerId(), frame_routing_id, device_id.utf8()));
}
void BluetoothDispatcher::getPrimaryService(
@@ -252,6 +272,18 @@ void BluetoothDispatcher::getCharacteristic(
service_instance_id.utf8(), characteristic_uuid.utf8()));
}
+void BluetoothDispatcher::getCharacteristics(
+ int frame_routing_id,
+ const blink::WebString& service_instance_id,
+ const blink::WebString& characteristics_uuid,
+ blink::WebBluetoothGetCharacteristicsCallbacks* callbacks) {
+ int request_id = pending_characteristics_requests_.Add(
+ new BluetoothCharacteristicsRequest(service_instance_id, callbacks));
+ Send(new BluetoothHostMsg_GetCharacteristics(
+ CurrentWorkerId(), request_id, frame_routing_id,
+ service_instance_id.utf8(), characteristics_uuid.utf8()));
+}
+
void BluetoothDispatcher::readValue(
int frame_routing_id,
const blink::WebString& characteristic_instance_id,
@@ -262,23 +294,10 @@ void BluetoothDispatcher::readValue(
characteristic_instance_id.utf8()));
}
-void BluetoothDispatcher::writeValue(
- int frame_routing_id,
- const blink::WebString& characteristic_instance_id,
- const blink::WebVector<uint8_t>& value,
- blink::WebBluetoothWriteValueCallbacks* callbacks) {
- int request_id = pending_write_value_requests_.Add(callbacks);
-
- Send(new BluetoothHostMsg_WriteValue(
- CurrentWorkerId(), request_id, frame_routing_id,
- characteristic_instance_id.utf8(),
- std::vector<uint8_t>(value.begin(), value.end())));
-}
-
void BluetoothDispatcher::startNotifications(
int frame_routing_id,
const blink::WebString& characteristic_instance_id,
- blink::WebBluetoothGATTCharacteristic* characteristic,
+ blink::WebBluetoothRemoteGATTCharacteristic* characteristic,
blink::WebBluetoothNotificationsCallbacks* callbacks) {
int request_id = QueueNotificationRequest(
frame_routing_id, characteristic_instance_id.utf8(), characteristic,
@@ -297,7 +316,7 @@ void BluetoothDispatcher::startNotifications(
void BluetoothDispatcher::stopNotifications(
int frame_routing_id,
const blink::WebString& characteristic_instance_id,
- blink::WebBluetoothGATTCharacteristic* characteristic,
+ blink::WebBluetoothRemoteGATTCharacteristic* characteristic,
blink::WebBluetoothNotificationsCallbacks* callbacks) {
int request_id = QueueNotificationRequest(
frame_routing_id, characteristic_instance_id.utf8(), characteristic,
@@ -313,7 +332,7 @@ void BluetoothDispatcher::stopNotifications(
void BluetoothDispatcher::characteristicObjectRemoved(
int frame_routing_id,
const blink::WebString& characteristic_instance_id,
- blink::WebBluetoothGATTCharacteristic* characteristic) {
+ blink::WebBluetoothRemoteGATTCharacteristic* characteristic) {
// We need to remove references to the object from the following:
// 1) The set of active characteristics
// 2) The queue waiting for a response
@@ -377,7 +396,7 @@ void BluetoothDispatcher::characteristicObjectRemoved(
void BluetoothDispatcher::registerCharacteristicObject(
int frame_routing_id,
const blink::WebString& characteristic_instance_id,
- blink::WebBluetoothGATTCharacteristic* characteristic) {
+ blink::WebBluetoothRemoteGATTCharacteristic* characteristic) {
// TODO(ortuno): After the Object manager is implemented, there will
// only be one object per characteristic. But for now we remove
// the previous object.
@@ -398,7 +417,7 @@ void BluetoothDispatcher::WillStopCurrentWorkerThread() {
int BluetoothDispatcher::QueueNotificationRequest(
int frame_routing_id,
const std::string& characteristic_instance_id,
- blink::WebBluetoothGATTCharacteristic* characteristic,
+ blink::WebBluetoothRemoteGATTCharacteristic* characteristic,
blink::WebBluetoothNotificationsCallbacks* callbacks,
NotificationsRequestType type) {
int request_id =
@@ -461,14 +480,14 @@ bool BluetoothDispatcher::HasActiveNotificationSubscription(
void BluetoothDispatcher::AddToActiveNotificationSubscriptions(
const std::string& characteristic_instance_id,
- blink::WebBluetoothGATTCharacteristic* characteristic) {
+ blink::WebBluetoothRemoteGATTCharacteristic* characteristic) {
active_notification_subscriptions_[characteristic_instance_id].insert(
characteristic);
}
bool BluetoothDispatcher::RemoveFromActiveNotificationSubscriptions(
const std::string& characteristic_instance_id,
- blink::WebBluetoothGATTCharacteristic* characteristic) {
+ blink::WebBluetoothRemoteGATTCharacteristic* characteristic) {
auto active_map =
active_notification_subscriptions_.find(characteristic_instance_id);
@@ -493,7 +512,7 @@ void BluetoothDispatcher::ResolveOrSendStartNotificationRequest(
const int frame_routing_id = request->frame_routing_id;
const std::string& characteristic_instance_id =
request->characteristic_instance_id;
- blink::WebBluetoothGATTCharacteristic* characteristic =
+ blink::WebBluetoothRemoteGATTCharacteristic* characteristic =
request->characteristic;
blink::WebBluetoothNotificationsCallbacks* callbacks =
request->callbacks.get();
@@ -527,7 +546,7 @@ void BluetoothDispatcher::ResolveOrSendStopNotificationsRequest(
const int frame_routing_id = request->frame_routing_id;
const std::string& characteristic_instance_id =
request->characteristic_instance_id;
- blink::WebBluetoothGATTCharacteristic* characteristic =
+ blink::WebBluetoothRemoteGATTCharacteristic* characteristic =
request->characteristic;
blink::WebBluetoothNotificationsCallbacks* callbacks =
request->callbacks.get();
@@ -575,7 +594,7 @@ void BluetoothDispatcher::OnRequestDeviceSuccess(
uuids[i] = WebString::fromUTF8(device.uuids[i].c_str());
pending_requests_.Lookup(request_id)
- ->onSuccess(blink::adoptWebPtr(new WebBluetoothDevice(
+ ->onSuccess(base::WrapUnique(new WebBluetoothDevice(
WebString::fromUTF8(device.id), WebString(device.name),
device.tx_power, device.rssi, device.device_class,
GetWebVendorIdSource(device.vendor_id_source), device.vendor_id,
@@ -591,19 +610,16 @@ void BluetoothDispatcher::OnRequestDeviceError(int thread_id,
pending_requests_.Remove(request_id);
}
-void BluetoothDispatcher::OnConnectGATTSuccess(int thread_id,
- int request_id,
- const std::string& device_id) {
+void BluetoothDispatcher::OnGATTServerConnectSuccess(int thread_id,
+ int request_id) {
DCHECK(pending_connect_requests_.Lookup(request_id)) << request_id;
- pending_connect_requests_.Lookup(request_id)
- ->onSuccess(blink::adoptWebPtr(new WebBluetoothGATTRemoteServer(
- WebString::fromUTF8(device_id), true /* connected */)));
+ pending_connect_requests_.Lookup(request_id)->onSuccess();
pending_connect_requests_.Remove(request_id);
}
-void BluetoothDispatcher::OnConnectGATTError(int thread_id,
- int request_id,
- WebBluetoothError error) {
+void BluetoothDispatcher::OnGATTServerConnectError(int thread_id,
+ int request_id,
+ WebBluetoothError error) {
DCHECK(pending_connect_requests_.Lookup(request_id)) << request_id;
pending_connect_requests_.Lookup(request_id)
->onError(WebBluetoothError(error));
@@ -617,9 +633,10 @@ void BluetoothDispatcher::OnGetPrimaryServiceSuccess(
DCHECK(pending_primary_service_requests_.Lookup(request_id)) << request_id;
BluetoothPrimaryServiceRequest* request =
pending_primary_service_requests_.Lookup(request_id);
- request->callbacks->onSuccess(blink::adoptWebPtr(new WebBluetoothGATTService(
- WebString::fromUTF8(service_instance_id), request->service_uuid,
- true /* isPrimary */, request->device_id)));
+ request->callbacks->onSuccess(
+ base::WrapUnique(new WebBluetoothRemoteGATTService(
+ WebString::fromUTF8(service_instance_id), request->service_uuid,
+ true /* isPrimary */, request->device_id)));
pending_primary_service_requests_.Remove(request_id);
}
@@ -643,10 +660,10 @@ void BluetoothDispatcher::OnGetCharacteristicSuccess(
BluetoothCharacteristicRequest* request =
pending_characteristic_requests_.Lookup(request_id);
request->callbacks->onSuccess(
- blink::adoptWebPtr(new WebBluetoothGATTCharacteristicInit(
+ base::WrapUnique(new WebBluetoothRemoteGATTCharacteristicInit(
+ request->service_instance_id,
WebString::fromUTF8(characteristic_instance_id),
- request->service_instance_id, request->characteristic_uuid,
- characteristic_properties)));
+ request->characteristic_uuid, characteristic_properties)));
pending_characteristic_requests_.Remove(request_id);
}
@@ -662,6 +679,46 @@ void BluetoothDispatcher::OnGetCharacteristicError(int thread_id,
pending_characteristic_requests_.Remove(request_id);
}
+void BluetoothDispatcher::OnGetCharacteristicsSuccess(
+ int thread_id,
+ int request_id,
+ const std::vector<std::string>& characteristics_instance_ids,
+ const std::vector<std::string>& characteristics_uuids,
+ const std::vector<uint32_t>& characteristics_properties) {
+ DCHECK(pending_characteristics_requests_.Lookup(request_id)) << request_id;
+
+ BluetoothCharacteristicsRequest* request =
+ pending_characteristics_requests_.Lookup(request_id);
+
+ // TODO(dcheng): This WebVector should use smart pointers.
+ std::unique_ptr<WebVector<blink::WebBluetoothRemoteGATTCharacteristicInit*>>
+ characteristics(new WebVector<WebBluetoothRemoteGATTCharacteristicInit*>(
+ characteristics_instance_ids.size()));
+
+ for (size_t i = 0; i < characteristics_instance_ids.size(); i++) {
+ (*characteristics)[i] = new WebBluetoothRemoteGATTCharacteristicInit(
+ request->service_instance_id,
+ WebString::fromUTF8(characteristics_instance_ids[i]),
+ WebString::fromUTF8(characteristics_uuids[i]),
+ characteristics_properties[i]);
+ }
+
+ request->callbacks->onSuccess(std::move(characteristics));
+
+ pending_characteristics_requests_.Remove(request_id);
+}
+
+void BluetoothDispatcher::OnGetCharacteristicsError(int thread_id,
+ int request_id,
+ WebBluetoothError error) {
+ DCHECK(pending_characteristics_requests_.Lookup(request_id)) << request_id;
+
+ pending_characteristics_requests_.Lookup(request_id)
+ ->callbacks->onError(WebBluetoothError(error));
+
+ pending_characteristics_requests_.Remove(request_id);
+}
+
void BluetoothDispatcher::OnReadValueSuccess(
int thread_id,
int request_id,
@@ -686,25 +743,6 @@ void BluetoothDispatcher::OnReadValueError(int thread_id,
pending_read_value_requests_.Remove(request_id);
}
-void BluetoothDispatcher::OnWriteValueSuccess(int thread_id, int request_id) {
- DCHECK(pending_write_value_requests_.Lookup(request_id)) << request_id;
-
- pending_write_value_requests_.Lookup(request_id)->onSuccess();
-
- pending_write_value_requests_.Remove(request_id);
-}
-
-void BluetoothDispatcher::OnWriteValueError(int thread_id,
- int request_id,
- WebBluetoothError error) {
- DCHECK(pending_write_value_requests_.Lookup(request_id)) << request_id;
-
- pending_write_value_requests_.Lookup(request_id)
- ->onError(WebBluetoothError(error));
-
- pending_write_value_requests_.Remove(request_id);
-}
-
void BluetoothDispatcher::OnStartNotificationsSuccess(int thread_id,
int request_id) {
DCHECK(pending_notifications_requests_.Lookup(request_id)) << request_id;
diff --git a/chromium/content/renderer/bluetooth/bluetooth_dispatcher.h b/chromium/content/renderer/bluetooth/bluetooth_dispatcher.h
index 1d978e12ed4..6eb83998c69 100644
--- a/chromium/content/renderer/bluetooth/bluetooth_dispatcher.h
+++ b/chromium/content/renderer/bluetooth/bluetooth_dispatcher.h
@@ -24,7 +24,7 @@ class TaskRunner;
}
namespace blink {
-class WebBluetoothGATTCharacteristic;
+class WebBluetoothRemoteGATTCharacteristic;
}
namespace IPC {
@@ -32,6 +32,7 @@ class Message;
}
struct BluetoothCharacteristicRequest;
+struct BluetoothCharacteristicsRequest;
struct BluetoothPrimaryServiceRequest;
struct BluetoothNotificationsRequest;
@@ -64,43 +65,44 @@ class BluetoothDispatcher : public WorkerThread::Observer {
void requestDevice(int frame_routing_id,
const blink::WebRequestDeviceOptions& options,
blink::WebBluetoothRequestDeviceCallbacks* callbacks);
- void connectGATT(int frame_routing_id,
- const blink::WebString& device_id,
- blink::WebBluetoothConnectGATTCallbacks* callbacks);
+ void connect(int frame_routing_id,
+ const blink::WebString& device_id,
+ blink::WebBluetoothRemoteGATTServerConnectCallbacks* callbacks);
+ void disconnect(int frame_routing_id, const blink::WebString& device_id);
void getPrimaryService(
int frame_routing_id,
const blink::WebString& device_id,
const blink::WebString& service_uuid,
blink::WebBluetoothGetPrimaryServiceCallbacks* callbacks);
-
void getCharacteristic(
int frame_routing_id,
const blink::WebString& service_instance_id,
const blink::WebString& characteristic_uuid,
blink::WebBluetoothGetCharacteristicCallbacks* callbacks);
+ void getCharacteristics(
+ int frame_routing_id,
+ const blink::WebString& service_instance_id,
+ const blink::WebString& characteristics_uuid,
+ blink::WebBluetoothGetCharacteristicsCallbacks* callbacks);
void readValue(int frame_routing_id,
const blink::WebString& characteristic_instance_id,
blink::WebBluetoothReadValueCallbacks* callbacks);
- void writeValue(int frame_routing_id,
- const blink::WebString& characteristic_instance_id,
- const blink::WebVector<uint8_t>& value,
- blink::WebBluetoothWriteValueCallbacks*);
void startNotifications(int frame_routing_id,
const blink::WebString& characteristic_instance_id,
- blink::WebBluetoothGATTCharacteristic* delegate,
+ blink::WebBluetoothRemoteGATTCharacteristic* delegate,
blink::WebBluetoothNotificationsCallbacks*);
void stopNotifications(int frame_routing_id,
const blink::WebString& characteristic_instance_id,
- blink::WebBluetoothGATTCharacteristic* delegate,
+ blink::WebBluetoothRemoteGATTCharacteristic* delegate,
blink::WebBluetoothNotificationsCallbacks*);
void characteristicObjectRemoved(
int frame_routing_id,
const blink::WebString& characteristic_instance_id,
- blink::WebBluetoothGATTCharacteristic* delegate);
+ blink::WebBluetoothRemoteGATTCharacteristic* delegate);
void registerCharacteristicObject(
int frame_routing_id,
const blink::WebString& characteristic_instance_id,
- blink::WebBluetoothGATTCharacteristic* characteristic);
+ blink::WebBluetoothRemoteGATTCharacteristic* characteristic);
// WorkerThread::Observer implementation.
void WillStopCurrentWorkerThread() override;
@@ -124,7 +126,7 @@ class BluetoothDispatcher : public WorkerThread::Observer {
int QueueNotificationRequest(
int frame_routing_id,
const std::string& characteristic_instance_id,
- blink::WebBluetoothGATTCharacteristic* characteristic,
+ blink::WebBluetoothRemoteGATTCharacteristic* characteristic,
blink::WebBluetoothNotificationsCallbacks* callbacks,
NotificationsRequestType type);
// Pops the last requests and runs the next request in the queue.
@@ -141,13 +143,13 @@ class BluetoothDispatcher : public WorkerThread::Observer {
// notifications.
void AddToActiveNotificationSubscriptions(
const std::string& characteristic_instance_id,
- blink::WebBluetoothGATTCharacteristic* characteristic);
+ blink::WebBluetoothRemoteGATTCharacteristic* characteristic);
// Removes the object from the set of subscribed object to the
// characteristic's notifications. Returns true if the subscription
// becomes inactive.
bool RemoveFromActiveNotificationSubscriptions(
const std::string& characteristic_instance_id,
- blink::WebBluetoothGATTCharacteristic* characteristic);
+ blink::WebBluetoothRemoteGATTCharacteristic* characteristic);
// The following functions decide whether to resolve the request immediately
// or send an IPC to change the subscription state.
@@ -177,12 +179,10 @@ class BluetoothDispatcher : public WorkerThread::Observer {
void OnRequestDeviceError(int thread_id,
int request_id,
blink::WebBluetoothError error);
- void OnConnectGATTSuccess(int thread_id,
- int request_id,
- const std::string& message);
- void OnConnectGATTError(int thread_id,
- int request_id,
- blink::WebBluetoothError error);
+ void OnGATTServerConnectSuccess(int thread_id, int request_id);
+ void OnGATTServerConnectError(int thread_id,
+ int request_id,
+ blink::WebBluetoothError error);
void OnGetPrimaryServiceSuccess(int thread_id,
int request_id,
const std::string& service_instance_id);
@@ -196,16 +196,21 @@ class BluetoothDispatcher : public WorkerThread::Observer {
void OnGetCharacteristicError(int thread_id,
int request_id,
blink::WebBluetoothError error);
+ void OnGetCharacteristicsSuccess(
+ int thread_id,
+ int request_id,
+ const std::vector<std::string>& characteristics_instance_ids,
+ const std::vector<std::string>& characteristics_uuids,
+ const std::vector<uint32_t>& characteristic_properties);
+ void OnGetCharacteristicsError(int thread_id,
+ int request_id,
+ blink::WebBluetoothError error);
void OnReadValueSuccess(int thread_id,
int request_id,
const std::vector<uint8_t>& value);
void OnReadValueError(int thread_id,
int request_id,
blink::WebBluetoothError error);
- void OnWriteValueSuccess(int thread_id, int request_id);
- void OnWriteValueError(int thread_id,
- int request_id,
- blink::WebBluetoothError error);
void OnStartNotificationsSuccess(int thread_id, int request_id);
void OnStartNotificationsError(int thread_id,
int request_id,
@@ -228,7 +233,7 @@ class BluetoothDispatcher : public WorkerThread::Observer {
pending_requests_;
// Tracks requests to connect to a device.
// Owns callback objects.
- IDMap<blink::WebBluetoothConnectGATTCallbacks, IDMapOwnPointer>
+ IDMap<blink::WebBluetoothRemoteGATTServerConnectCallbacks, IDMapOwnPointer>
pending_connect_requests_;
// Tracks requests to get a primary service from a device.
// Owns request objects.
@@ -237,28 +242,30 @@ class BluetoothDispatcher : public WorkerThread::Observer {
// Tracks requests to get a characteristic from a service.
IDMap<BluetoothCharacteristicRequest, IDMapOwnPointer>
pending_characteristic_requests_;
+ // Tracks requests to get characteristics from a service.
+ IDMap<BluetoothCharacteristicsRequest, IDMapOwnPointer>
+ pending_characteristics_requests_;
// Tracks requests to read from a characteristics.
IDMap<blink::WebBluetoothReadValueCallbacks, IDMapOwnPointer>
pending_read_value_requests_;
- IDMap<blink::WebBluetoothWriteValueCallbacks, IDMapOwnPointer>
- pending_write_value_requests_;
IDMap<BluetoothNotificationsRequest, IDMapOwnPointer>
pending_notifications_requests_;
// Map of characteristic_instance_id to a set of
- // WebBluetoothGATTCharacteristic pointers. Keeps track of which
+ // WebBluetoothRemoteGATTCharacteristic pointers. Keeps track of which
// objects are subscribed to notifications.
- std::map<std::string, std::set<blink::WebBluetoothGATTCharacteristic*>>
+ std::map<std::string, std::set<blink::WebBluetoothRemoteGATTCharacteristic*>>
active_notification_subscriptions_;
- // Map of characteristic_instance_ids to WebBluetoothGATTCharacteristics.
+ // Map of characteristic_instance_ids to
+ // WebBluetoothRemoteGATTCharacteristics.
// Keeps track of what characteristics have listeners.
// TODO(ortuno): We are assuming that there exists a single frame per
// dispatcher, so there could be at most one characteristic object per
// characteristic_instance_id. Change to a set when we support multiple
// frames.
// http://crbug.com/541388
- std::map<std::string, blink::WebBluetoothGATTCharacteristic*>
+ std::map<std::string, blink::WebBluetoothRemoteGATTCharacteristic*>
active_characteristics_;
DISALLOW_COPY_AND_ASSIGN(BluetoothDispatcher);
diff --git a/chromium/content/renderer/bluetooth/web_bluetooth_impl.cc b/chromium/content/renderer/bluetooth/web_bluetooth_impl.cc
index 8e3039d66cd..7665e8079a2 100644
--- a/chromium/content/renderer/bluetooth/web_bluetooth_impl.cc
+++ b/chromium/content/renderer/bluetooth/web_bluetooth_impl.cc
@@ -4,18 +4,20 @@
#include "content/renderer/bluetooth/web_bluetooth_impl.h"
+#include "content/child/mojo/type_converters.h"
#include "content/child/thread_safe_sender.h"
+#include "content/public/common/service_registry.h"
#include "content/renderer/bluetooth/bluetooth_dispatcher.h"
#include "ipc/ipc_message.h"
+#include "mojo/public/cpp/bindings/array.h"
namespace content {
-WebBluetoothImpl::WebBluetoothImpl(ThreadSafeSender* thread_safe_sender)
- : WebBluetoothImpl(thread_safe_sender, MSG_ROUTING_NONE) {}
-
-WebBluetoothImpl::WebBluetoothImpl(ThreadSafeSender* thread_safe_sender,
+WebBluetoothImpl::WebBluetoothImpl(ServiceRegistry* service_registry,
+ ThreadSafeSender* thread_safe_sender,
int frame_routing_id)
- : thread_safe_sender_(thread_safe_sender),
+ : service_registry_(service_registry),
+ thread_safe_sender_(thread_safe_sender),
frame_routing_id_(frame_routing_id) {}
WebBluetoothImpl::~WebBluetoothImpl() {
@@ -27,10 +29,14 @@ void WebBluetoothImpl::requestDevice(
GetDispatcher()->requestDevice(frame_routing_id_, options, callbacks);
}
-void WebBluetoothImpl::connectGATT(
+void WebBluetoothImpl::connect(
const blink::WebString& device_id,
- blink::WebBluetoothConnectGATTCallbacks* callbacks) {
- GetDispatcher()->connectGATT(frame_routing_id_, device_id, callbacks);
+ blink::WebBluetoothRemoteGATTServerConnectCallbacks* callbacks) {
+ GetDispatcher()->connect(frame_routing_id_, device_id, callbacks);
+}
+
+void WebBluetoothImpl::disconnect(const blink::WebString& device_id) {
+ GetDispatcher()->disconnect(frame_routing_id_, device_id);
}
void WebBluetoothImpl::getPrimaryService(
@@ -43,10 +49,18 @@ void WebBluetoothImpl::getPrimaryService(
void WebBluetoothImpl::getCharacteristic(
const blink::WebString& service_instance_id,
- const blink::WebString& characteristic_uuid,
+ const blink::WebString& characteristics_uuid,
blink::WebBluetoothGetCharacteristicCallbacks* callbacks) {
GetDispatcher()->getCharacteristic(frame_routing_id_, service_instance_id,
- characteristic_uuid, callbacks);
+ characteristics_uuid, callbacks);
+}
+
+void WebBluetoothImpl::getCharacteristics(
+ const blink::WebString& service_instance_id,
+ const blink::WebString& characteristic_uuid,
+ blink::WebBluetoothGetCharacteristicsCallbacks* callbacks) {
+ GetDispatcher()->getCharacteristics(frame_routing_id_, service_instance_id,
+ characteristic_uuid, callbacks);
}
void WebBluetoothImpl::readValue(
@@ -60,13 +74,17 @@ void WebBluetoothImpl::writeValue(
const blink::WebString& characteristic_instance_id,
const blink::WebVector<uint8_t>& value,
blink::WebBluetoothWriteValueCallbacks* callbacks) {
- GetDispatcher()->writeValue(frame_routing_id_, characteristic_instance_id,
- value, callbacks);
+ GetWebBluetoothService().RemoteCharacteristicWriteValue(
+ mojo::String::From(characteristic_instance_id),
+ mojo::Array<uint8_t>::From(value),
+ base::Bind(&WebBluetoothImpl::OnWriteValueComplete,
+ base::Unretained(this), value,
+ base::Passed(make_scoped_ptr(callbacks))));
}
void WebBluetoothImpl::startNotifications(
const blink::WebString& characteristic_instance_id,
- blink::WebBluetoothGATTCharacteristic* characteristic,
+ blink::WebBluetoothRemoteGATTCharacteristic* characteristic,
blink::WebBluetoothNotificationsCallbacks* callbacks) {
GetDispatcher()->startNotifications(
frame_routing_id_, characteristic_instance_id, characteristic, callbacks);
@@ -74,7 +92,7 @@ void WebBluetoothImpl::startNotifications(
void WebBluetoothImpl::stopNotifications(
const blink::WebString& characteristic_instance_id,
- blink::WebBluetoothGATTCharacteristic* characteristic,
+ blink::WebBluetoothRemoteGATTCharacteristic* characteristic,
blink::WebBluetoothNotificationsCallbacks* callbacks) {
GetDispatcher()->stopNotifications(
frame_routing_id_, characteristic_instance_id, characteristic, callbacks);
@@ -82,21 +100,40 @@ void WebBluetoothImpl::stopNotifications(
void WebBluetoothImpl::characteristicObjectRemoved(
const blink::WebString& characteristic_instance_id,
- blink::WebBluetoothGATTCharacteristic* characteristic) {
+ blink::WebBluetoothRemoteGATTCharacteristic* characteristic) {
GetDispatcher()->characteristicObjectRemoved(
frame_routing_id_, characteristic_instance_id, characteristic);
}
void WebBluetoothImpl::registerCharacteristicObject(
const blink::WebString& characteristic_instance_id,
- blink::WebBluetoothGATTCharacteristic* characteristic) {
+ blink::WebBluetoothRemoteGATTCharacteristic* characteristic) {
GetDispatcher()->registerCharacteristicObject(
frame_routing_id_, characteristic_instance_id, characteristic);
}
+void WebBluetoothImpl::OnWriteValueComplete(
+ const blink::WebVector<uint8_t>& value,
+ scoped_ptr<blink::WebBluetoothWriteValueCallbacks> callbacks,
+ blink::mojom::WebBluetoothError error) {
+ if (error == blink::mojom::WebBluetoothError::SUCCESS) {
+ callbacks->onSuccess(value);
+ } else {
+ callbacks->onError(error);
+ }
+}
+
BluetoothDispatcher* WebBluetoothImpl::GetDispatcher() {
return BluetoothDispatcher::GetOrCreateThreadSpecificInstance(
thread_safe_sender_.get());
}
+blink::mojom::WebBluetoothService& WebBluetoothImpl::GetWebBluetoothService() {
+ if (!web_bluetooth_service_) {
+ service_registry_->ConnectToRemoteService(
+ mojo::GetProxy(&web_bluetooth_service_));
+ }
+ return *web_bluetooth_service_;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/bluetooth/web_bluetooth_impl.h b/chromium/content/renderer/bluetooth/web_bluetooth_impl.h
index b5f85d47c05..09fb5e08df3 100644
--- a/chromium/content/renderer/bluetooth/web_bluetooth_impl.h
+++ b/chromium/content/renderer/bluetooth/web_bluetooth_impl.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef CONTENT_CHILD_BLUETOOTH_WEB_BLUETOOTH_IMPL_H_
-#define CONTENT_CHILD_BLUETOOTH_WEB_BLUETOOTH_IMPL_H_
+#ifndef CONTENT_RENDERER_BLUETOOTH_WEB_BLUETOOTH_IMPL_H_
+#define CONTENT_RENDERER_BLUETOOTH_WEB_BLUETOOTH_IMPL_H_
#include <stdint.h>
@@ -14,31 +14,36 @@
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
#include "third_party/WebKit/public/platform/modules/bluetooth/WebBluetooth.h"
+#include "third_party/WebKit/public/platform/modules/bluetooth/web_bluetooth.mojom.h"
namespace blink {
-class WebBluetoothGATTCharacteristic;
+class WebBluetoothRemoteGATTCharacteristic;
}
namespace content {
class BluetoothDispatcher;
class ThreadSafeSender;
+class ServiceRegistry;
// Implementation of blink::WebBluetooth. Passes calls through to the thread
// specific BluetoothDispatcher.
class CONTENT_EXPORT WebBluetoothImpl
: NON_EXPORTED_BASE(public blink::WebBluetooth) {
public:
- explicit WebBluetoothImpl(ThreadSafeSender* thread_safe_sender);
- WebBluetoothImpl(ThreadSafeSender* thread_safe_sender, int frame_routing_id);
+ WebBluetoothImpl(ServiceRegistry* service_registry,
+ ThreadSafeSender* thread_safe_sender,
+ int frame_routing_id);
~WebBluetoothImpl() override;
// blink::WebBluetooth interface:
void requestDevice(
const blink::WebRequestDeviceOptions& options,
blink::WebBluetoothRequestDeviceCallbacks* callbacks) override;
- void connectGATT(const blink::WebString& device_id,
- blink::WebBluetoothConnectGATTCallbacks* callbacks) override;
+ void connect(
+ const blink::WebString& device_id,
+ blink::WebBluetoothRemoteGATTServerConnectCallbacks* callbacks) override;
+ void disconnect(const blink::WebString& device_id) override;
void getPrimaryService(
const blink::WebString& device_id,
const blink::WebString& service_uuid,
@@ -47,27 +52,43 @@ class CONTENT_EXPORT WebBluetoothImpl
const blink::WebString& service_instance_id,
const blink::WebString& characteristic_uuid,
blink::WebBluetoothGetCharacteristicCallbacks* callbacks) override;
+ void getCharacteristics(
+ const blink::WebString& service_instance_id,
+ const blink::WebString& characteristics_uuid,
+ blink::WebBluetoothGetCharacteristicsCallbacks* callbacks) override;
+
void readValue(const blink::WebString& characteristic_instance_id,
blink::WebBluetoothReadValueCallbacks* callbacks) override;
void writeValue(const blink::WebString& characteristic_instance_id,
const blink::WebVector<uint8_t>& value,
blink::WebBluetoothWriteValueCallbacks*) override;
- void startNotifications(const blink::WebString& characteristic_instance_id,
- blink::WebBluetoothGATTCharacteristic* characteristic,
- blink::WebBluetoothNotificationsCallbacks*) override;
- void stopNotifications(const blink::WebString& characteristic_instance_id,
- blink::WebBluetoothGATTCharacteristic* characteristic,
- blink::WebBluetoothNotificationsCallbacks*) override;
+ void startNotifications(
+ const blink::WebString& characteristic_instance_id,
+ blink::WebBluetoothRemoteGATTCharacteristic* characteristic,
+ blink::WebBluetoothNotificationsCallbacks*) override;
+ void stopNotifications(
+ const blink::WebString& characteristic_instance_id,
+ blink::WebBluetoothRemoteGATTCharacteristic* characteristic,
+ blink::WebBluetoothNotificationsCallbacks*) override;
void characteristicObjectRemoved(
const blink::WebString& characteristic_instance_id,
- blink::WebBluetoothGATTCharacteristic* characteristic) override;
+ blink::WebBluetoothRemoteGATTCharacteristic* characteristic) override;
void registerCharacteristicObject(
const blink::WebString& characteristic_instance_id,
- blink::WebBluetoothGATTCharacteristic* characteristic) override;
+ blink::WebBluetoothRemoteGATTCharacteristic* characteristic) override;
private:
+ void OnWriteValueComplete(
+ const blink::WebVector<uint8_t>& value,
+ scoped_ptr<blink::WebBluetoothWriteValueCallbacks> callbacks,
+ blink::mojom::WebBluetoothError error);
+
BluetoothDispatcher* GetDispatcher();
+ blink::mojom::WebBluetoothService& GetWebBluetoothService();
+ ServiceRegistry* const service_registry_;
+ blink::mojom::WebBluetoothServicePtr web_bluetooth_service_;
+
const scoped_refptr<ThreadSafeSender> thread_safe_sender_;
const int frame_routing_id_;
@@ -76,4 +97,4 @@ class CONTENT_EXPORT WebBluetoothImpl
} // namespace content
-#endif // CONTENT_CHILD_BLUETOOTH_WEB_BLUETOOTH_IMPL_H_
+#endif // CONTENT_RENDERER_BLUETOOTH_WEB_BLUETOOTH_IMPL_H_
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin.cc b/chromium/content/renderer/browser_plugin/browser_plugin.cc
index b5611278190..e9c4bffa202 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin.cc
+++ b/chromium/content/renderer/browser_plugin/browser_plugin.cc
@@ -34,10 +34,8 @@
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebPluginContainer.h"
#include "third_party/WebKit/public/web/WebView.h"
-#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/events/keycodes/keyboard_codes.h"
-using blink::WebCanvas;
using blink::WebPluginContainer;
using blink::WebPoint;
using blink::WebRect;
@@ -104,8 +102,6 @@ bool BrowserPlugin::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(BrowserPlugin, message)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_AdvanceFocus, OnAdvanceFocus)
- IPC_MESSAGE_HANDLER_GENERIC(BrowserPluginMsg_CompositorFrameSwapped,
- OnCompositorFrameSwapped(message))
IPC_MESSAGE_HANDLER(BrowserPluginMsg_GuestGone, OnGuestGone)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetCursor, OnSetCursor)
IPC_MESSAGE_HANDLER(BrowserPluginMsg_SetMouseLock, OnSetMouseLock)
@@ -129,7 +125,6 @@ void BrowserPlugin::OnSetChildFrameSurface(
EnableCompositing(true);
DCHECK(compositing_helper_.get());
-
compositing_helper_->OnSetSurface(surface_id, frame_size, scale_factor,
sequence);
}
@@ -179,18 +174,12 @@ void BrowserPlugin::Detach() {
attached_ = false;
guest_crashed_ = false;
EnableCompositing(false);
- if (compositing_helper_.get()) {
- compositing_helper_->OnContainerDestroy();
- compositing_helper_ = nullptr;
- }
BrowserPluginManager::Get()->Send(
new BrowserPluginHostMsg_Detach(browser_plugin_instance_id_));
}
void BrowserPlugin::DidCommitCompositorFrame() {
- if (compositing_helper_.get())
- compositing_helper_->DidCommitCompositorFrame();
}
void BrowserPlugin::OnAdvanceFocus(int browser_plugin_instance_id,
@@ -202,42 +191,11 @@ void BrowserPlugin::OnAdvanceFocus(int browser_plugin_instance_id,
render_view->GetWebView()->advanceFocus(reverse);
}
-void BrowserPlugin::OnCompositorFrameSwapped(const IPC::Message& message) {
- if (!attached())
- return;
-
- BrowserPluginMsg_CompositorFrameSwapped::Param param;
- if (!BrowserPluginMsg_CompositorFrameSwapped::Read(&message, &param))
- return;
- // Note that there is no need to send ACK for this message.
- // If the guest has updated pixels then it is no longer crashed.
- guest_crashed_ = false;
-
- scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
- base::get<1>(param).frame.AssignTo(frame.get());
-
- EnableCompositing(true);
- compositing_helper_->OnCompositorFrameSwapped(
- std::move(frame), base::get<1>(param).producing_route_id,
- base::get<1>(param).output_surface_id,
- base::get<1>(param).producing_host_id,
- base::get<1>(param).shared_memory_handle);
-}
-
void BrowserPlugin::OnGuestGone(int browser_plugin_instance_id) {
guest_crashed_ = true;
- // Turn off compositing so we can display the sad graphic. Changes to
- // compositing state will show up at a later time after a layout and commit.
- EnableCompositing(false);
-
- // Queue up showing the sad graphic to give content embedders an opportunity
- // to fire their listeners and potentially overlay the webview with custom
- // behavior. If the BrowserPlugin is destroyed in the meantime, then the
- // task will not be executed.
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&BrowserPlugin::ShowSadGraphic,
- weak_ptr_factory_.GetWeakPtr()));
+ EnableCompositing(true);
+ compositing_helper_->ChildFrameGone();
}
void BrowserPlugin::OnSetCursor(int browser_plugin_instance_id,
@@ -280,13 +238,6 @@ void BrowserPlugin::OnShouldAcceptTouchEvents(int browser_plugin_instance_id,
}
}
-void BrowserPlugin::ShowSadGraphic() {
- // If the BrowserPlugin is scheduled to be deleted, then container_ will be
- // nullptr so we shouldn't attempt to access it.
- if (container_)
- container_->invalidate();
-}
-
void BrowserPlugin::UpdateInternalInstanceId() {
// This is a way to notify observers of our attributes that this plugin is
// available in render tree.
@@ -322,8 +273,8 @@ WebPluginContainer* BrowserPlugin::container() const {
}
bool BrowserPlugin::initialize(WebPluginContainer* container) {
- if (!container)
- return false;
+ DCHECK(container);
+ DCHECK_EQ(this, container->plugin());
container_ = container;
container_->setWantsWheelEvents(true);
@@ -401,46 +352,24 @@ bool BrowserPlugin::canProcessDrag() const {
return true;
}
-void BrowserPlugin::paint(WebCanvas* canvas, const WebRect& rect) {
- if (guest_crashed_) {
- if (!sad_guest_) // Lazily initialize bitmap.
- sad_guest_ = GetContentClient()->renderer()->GetSadWebViewBitmap();
- // content_shell does not have the sad plugin bitmap, so we'll paint black
- // instead to make it clear that something went wrong.
- if (sad_guest_) {
- PaintSadPlugin(canvas, view_rect_, *sad_guest_);
- return;
- }
- }
- SkAutoCanvasRestore auto_restore(canvas, true);
- canvas->translate(view_rect_.x(), view_rect_.y());
- SkRect image_data_rect = SkRect::MakeXYWH(
- SkIntToScalar(0),
- SkIntToScalar(0),
- SkIntToScalar(view_rect_.width()),
- SkIntToScalar(view_rect_.height()));
- canvas->clipRect(image_data_rect);
- // Paint black or white in case we have nothing in our backing store or we
- // need to show a gutter.
- SkPaint paint;
- paint.setStyle(SkPaint::kFill_Style);
- paint.setColor(guest_crashed_ ? SK_ColorBLACK : SK_ColorWHITE);
- canvas->drawRect(image_data_rect, paint);
-}
-
// static
bool BrowserPlugin::ShouldForwardToBrowserPlugin(
const IPC::Message& message) {
return IPC_MESSAGE_CLASS(message) == BrowserPluginMsgStart;
}
-void BrowserPlugin::updateGeometry(const WebRect& window_rect,
+void BrowserPlugin::updateGeometry(const WebRect& plugin_rect_in_viewport,
const WebRect& clip_rect,
const WebRect& unobscured_rect,
const WebVector<WebRect>& cut_outs_rects,
bool is_visible) {
gfx::Rect old_view_rect = view_rect_;
- view_rect_ = window_rect;
+ // Convert the plugin_rect_in_viewport to window coordinates, which is css.
+ WebRect rect_in_css(plugin_rect_in_viewport);
+ blink::WebView* webview = container()->element().document().frame()->view();
+ RenderView::FromWebView(webview)->GetWidget()->convertViewportToWindow(
+ &rect_in_css);
+ view_rect_ = rect_in_css;
if (!ready_) {
if (delegate_)
@@ -483,10 +412,6 @@ void BrowserPlugin::updateVisibility(bool visible) {
visible));
}
-bool BrowserPlugin::acceptsInputEvents() {
- return true;
-}
-
blink::WebInputEventResult BrowserPlugin::handleInputEvent(
const blink::WebInputEvent& event,
blink::WebCursorInfo& cursor_info) {
@@ -521,7 +446,6 @@ blink::WebInputEventResult BrowserPlugin::handleInputEvent(
BrowserPluginManager::Get()->Send(
new BrowserPluginHostMsg_HandleInputEvent(browser_plugin_instance_id_,
- view_rect_,
&event));
GetWebCursorInfo(cursor_, &cursor_info);
@@ -646,7 +570,6 @@ bool BrowserPlugin::HandleMouseLockedInputEvent(
const blink::WebMouseEvent& event) {
BrowserPluginManager::Get()->Send(
new BrowserPluginHostMsg_HandleInputEvent(browser_plugin_instance_id_,
- view_rect_,
&event));
return true;
}
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin.h b/chromium/content/renderer/browser_plugin/browser_plugin.h
index b166f5e58f7..3808e0f792e 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin.h
+++ b/chromium/content/renderer/browser_plugin/browser_plugin.h
@@ -89,7 +89,7 @@ class CONTENT_EXPORT BrowserPlugin :
bool supportsInputMethod() const override;
bool canProcessDrag() const override;
void updateAllLifecyclePhases() override {}
- void paint(blink::WebCanvas* canvas, const blink::WebRect& rect) override;
+ void paint(blink::WebCanvas* canvas, const blink::WebRect& rect) override {}
void updateGeometry(const blink::WebRect& window_rect,
const blink::WebRect& clip_rect,
const blink::WebRect& unobscured_rect,
@@ -97,7 +97,6 @@ class CONTENT_EXPORT BrowserPlugin :
bool is_visible) override;
void updateFocus(bool focused, blink::WebFocusType focus_type) override;
void updateVisibility(bool visible) override;
- bool acceptsInputEvents() override;
blink::WebInputEventResult handleInputEvent(
const blink::WebInputEvent& event,
blink::WebCursorInfo& cursor_info) override;
@@ -146,13 +145,11 @@ class CONTENT_EXPORT BrowserPlugin :
gfx::Rect view_rect() const { return view_rect_; }
- void ShowSadGraphic();
void UpdateInternalInstanceId();
// IPC message handlers.
// Please keep in alphabetical order.
void OnAdvanceFocus(int instance_id, bool reverse);
- void OnCompositorFrameSwapped(const IPC::Message& message);
void OnGuestGone(int instance_id);
void OnSetChildFrameSurface(int instance_id,
const cc::SurfaceId& surface_id,
@@ -174,6 +171,7 @@ class CONTENT_EXPORT BrowserPlugin :
// then we will attempt to access a nullptr.
const int render_frame_routing_id_;
blink::WebPluginContainer* container_;
+ // The plugin's rect in css pixels.
gfx::Rect view_rect_;
// Bitmap for crashed plugin. Lazily initialized, non-owning pointer.
SkBitmap* sad_guest_;
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_manager.cc b/chromium/content/renderer/browser_plugin/browser_plugin_manager.cc
index 9cde4738788..b6dbd2e90fd 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin_manager.cc
+++ b/chromium/content/renderer/browser_plugin/browser_plugin_manager.cc
@@ -96,35 +96,11 @@ bool BrowserPluginManager::OnControlMessageReceived(
bool success = iter.ReadInt(&browser_plugin_instance_id);
DCHECK(success);
BrowserPlugin* plugin = GetBrowserPlugin(browser_plugin_instance_id);
- if (plugin && plugin->OnMessageReceived(message))
- return true;
-
- // TODO(fsamuel): This is probably forcing the compositor to continue working
- // even on display:none. We should optimize this.
- if (message.type() == BrowserPluginMsg_CompositorFrameSwapped::ID) {
- OnCompositorFrameSwappedPluginUnavailable(message);
- return true;
- }
-
- return false;
+ return plugin && plugin->OnMessageReceived(message);
}
bool BrowserPluginManager::Send(IPC::Message* msg) {
return RenderThreadImpl::current()->Send(msg);
}
-void BrowserPluginManager::OnCompositorFrameSwappedPluginUnavailable(
- const IPC::Message& message) {
- BrowserPluginMsg_CompositorFrameSwapped::Param param;
- if (!BrowserPluginMsg_CompositorFrameSwapped::Read(&message, &param))
- return;
-
- FrameHostMsg_CompositorFrameSwappedACK_Params params;
- params.producing_host_id = base::get<1>(param).producing_host_id;
- params.producing_route_id = base::get<1>(param).producing_route_id;
- params.output_surface_id = base::get<1>(param).output_surface_id;
- Send(new BrowserPluginHostMsg_CompositorFrameSwappedACK(
- base::get<0>(param), params));
-}
-
} // namespace content
diff --git a/chromium/content/renderer/browser_plugin/browser_plugin_manager.h b/chromium/content/renderer/browser_plugin/browser_plugin_manager.h
index 4703fd8127c..b8471afbddd 100644
--- a/chromium/content/renderer/browser_plugin/browser_plugin_manager.h
+++ b/chromium/content/renderer/browser_plugin/browser_plugin_manager.h
@@ -64,9 +64,6 @@ class CONTENT_EXPORT BrowserPluginManager : public RenderProcessObserver {
bool OnControlMessageReceived(const IPC::Message& message) override;
private:
- // IPC message handlers.
- void OnCompositorFrameSwappedPluginUnavailable(const IPC::Message& message);
-
// This map is keyed by guest instance IDs.
IDMap<BrowserPlugin> instances_;
diff --git a/chromium/content/renderer/browser_render_view_browsertest.cc b/chromium/content/renderer/browser_render_view_browsertest.cc
index 380f95f33b4..448120c4047 100644
--- a/chromium/content/renderer/browser_render_view_browsertest.cc
+++ b/chromium/content/renderer/browser_render_view_browsertest.cc
@@ -16,6 +16,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "content/public/renderer/render_view.h"
@@ -203,14 +204,13 @@ IN_PROC_BROWSER_TEST_F(RenderViewBrowserTest, ConfirmCacheInformationPlumbed) {
// Reload same URL after forcing an error from the the network layer;
// confirm that the error page is told the cached copy exists.
- int renderer_id =
- shell()->web_contents()->GetMainFrame()->GetProcess()->GetID();
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter =
- ShellContentBrowserClient::Get()->browser_context()->
- GetRequestContextForRenderProcess(renderer_id);
+ shell()->web_contents()->GetRenderProcessHost()->GetStoragePartition()->
+ GetURLRequestContext();
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&InterceptNetworkTransactions, url_request_context_getter,
+ base::Bind(&InterceptNetworkTransactions,
+ base::RetainedRef(url_request_context_getter),
net::ERR_FAILED));
// An error results in one completed navigation.
@@ -226,7 +226,7 @@ IN_PROC_BROWSER_TEST_F(RenderViewBrowserTest, ConfirmCacheInformationPlumbed) {
scoped_refptr<MessageLoopRunner> runner = new MessageLoopRunner;
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
- base::Bind(&ClearCache, url_request_context_getter,
+ base::Bind(&ClearCache, base::RetainedRef(url_request_context_getter),
runner->QuitClosure()));
runner->Run();
diff --git a/chromium/content/renderer/cache_storage/cache_storage_dispatcher.cc b/chromium/content/renderer/cache_storage/cache_storage_dispatcher.cc
index 90914688593..25b5f86762e 100644
--- a/chromium/content/renderer/cache_storage/cache_storage_dispatcher.cc
+++ b/chromium/content/renderer/cache_storage/cache_storage_dispatcher.cc
@@ -23,6 +23,7 @@
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerCache.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerRequest.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerResponse.h"
+#include "url/origin.h"
using base::TimeTicks;
@@ -89,7 +90,10 @@ ServiceWorkerResponse ResponseFromWebResponse(
web_response.responseType(), headers,
base::UTF16ToASCII(base::StringPiece16(web_response.blobUUID())),
web_response.blobSize(), web_response.streamURL(),
- blink::WebServiceWorkerResponseErrorUnknown);
+ blink::WebServiceWorkerResponseErrorUnknown,
+ base::Time::FromInternalValue(web_response.responseTime()),
+ !web_response.cacheStorageCacheName().isNull(),
+ web_response.cacheStorageCacheName().utf8());
}
CacheStorageCacheQueryParams QueryParamsFromWebQueryParams(
@@ -299,7 +303,7 @@ void CacheStorageDispatcher::OnCacheStorageOpenSuccess(int thread_id,
TimeTicks::Now() - open_times_[request_id]);
WebServiceWorkerCacheStorage::CacheStorageWithCacheCallbacks* callbacks =
open_callbacks_.Lookup(request_id);
- callbacks->onSuccess(blink::adoptWebPtr(web_cache.release()));
+ callbacks->onSuccess(std::move(web_cache));
open_callbacks_.Remove(request_id);
open_times_.erase(request_id);
}
@@ -522,7 +526,7 @@ void CacheStorageDispatcher::OnCacheBatchError(
void CacheStorageDispatcher::dispatchHas(
WebServiceWorkerCacheStorage::CacheStorageCallbacks* callbacks,
- const GURL& origin,
+ const url::Origin& origin,
const blink::WebString& cacheName) {
int request_id = has_callbacks_.Add(callbacks);
has_times_[request_id] = base::TimeTicks::Now();
@@ -532,7 +536,7 @@ void CacheStorageDispatcher::dispatchHas(
void CacheStorageDispatcher::dispatchOpen(
WebServiceWorkerCacheStorage::CacheStorageWithCacheCallbacks* callbacks,
- const GURL& origin,
+ const url::Origin& origin,
const blink::WebString& cacheName) {
int request_id = open_callbacks_.Add(callbacks);
open_times_[request_id] = base::TimeTicks::Now();
@@ -542,7 +546,7 @@ void CacheStorageDispatcher::dispatchOpen(
void CacheStorageDispatcher::dispatchDelete(
WebServiceWorkerCacheStorage::CacheStorageCallbacks* callbacks,
- const GURL& origin,
+ const url::Origin& origin,
const blink::WebString& cacheName) {
int request_id = delete_callbacks_.Add(callbacks);
delete_times_[request_id] = base::TimeTicks::Now();
@@ -552,7 +556,7 @@ void CacheStorageDispatcher::dispatchDelete(
void CacheStorageDispatcher::dispatchKeys(
WebServiceWorkerCacheStorage::CacheStorageKeysCallbacks* callbacks,
- const GURL& origin) {
+ const url::Origin& origin) {
int request_id = keys_callbacks_.Add(callbacks);
keys_times_[request_id] = base::TimeTicks::Now();
Send(new CacheStorageHostMsg_CacheStorageKeys(CurrentWorkerId(), request_id,
@@ -561,7 +565,7 @@ void CacheStorageDispatcher::dispatchKeys(
void CacheStorageDispatcher::dispatchMatch(
WebServiceWorkerCacheStorage::CacheStorageMatchCallbacks* callbacks,
- const GURL& origin,
+ const url::Origin& origin,
const blink::WebServiceWorkerRequest& request,
const blink::WebServiceWorkerCache::QueryParams& query_params) {
int request_id = match_callbacks_.Add(callbacks);
@@ -646,6 +650,11 @@ void CacheStorageDispatcher::PopulateWebResponseFromResponse(
web_response->setStatus(response.status_code);
web_response->setStatusText(base::ASCIIToUTF16(response.status_text));
web_response->setResponseType(response.response_type);
+ web_response->setResponseTime(response.response_time.ToInternalValue());
+ web_response->setCacheStorageCacheName(
+ response.is_in_cache_storage
+ ? blink::WebString::fromUTF8(response.cache_storage_cache_name)
+ : blink::WebString());
for (const auto& i : response.headers) {
web_response->setHeader(base::ASCIIToUTF16(i.first),
diff --git a/chromium/content/renderer/cache_storage/cache_storage_dispatcher.h b/chromium/content/renderer/cache_storage/cache_storage_dispatcher.h
index a43757d0f82..88a393378b7 100644
--- a/chromium/content/renderer/cache_storage/cache_storage_dispatcher.h
+++ b/chromium/content/renderer/cache_storage/cache_storage_dispatcher.h
@@ -20,6 +20,10 @@
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerCacheError.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerCacheStorage.h"
+namespace url {
+class Origin;
+}
+
namespace content {
class ThreadSafeSender;
@@ -105,24 +109,24 @@ class CacheStorageDispatcher : public WorkerThread::Observer {
// and should be renamed to match Chromium conventions. crbug.com/439389
void dispatchHas(
blink::WebServiceWorkerCacheStorage::CacheStorageCallbacks* callbacks,
- const GURL& origin,
+ const url::Origin& origin,
const blink::WebString& cacheName);
void dispatchOpen(
blink::WebServiceWorkerCacheStorage::CacheStorageWithCacheCallbacks*
callbacks,
- const GURL& origin,
+ const url::Origin& origin,
const blink::WebString& cacheName);
void dispatchDelete(
blink::WebServiceWorkerCacheStorage::CacheStorageCallbacks* callbacks,
- const GURL& origin,
+ const url::Origin& origin,
const blink::WebString& cacheName);
void dispatchKeys(
blink::WebServiceWorkerCacheStorage::CacheStorageKeysCallbacks* callbacks,
- const GURL& origin);
+ const url::Origin& origin);
void dispatchMatch(
blink::WebServiceWorkerCacheStorage::CacheStorageMatchCallbacks*
callbacks,
- const GURL& origin,
+ const url::Origin& origin,
const blink::WebServiceWorkerRequest& request,
const blink::WebServiceWorkerCache::QueryParams& query_params);
diff --git a/chromium/content/renderer/cache_storage/webserviceworkercachestorage_impl.cc b/chromium/content/renderer/cache_storage/webserviceworkercachestorage_impl.cc
index 4febfca40ea..2103c9cd21b 100644
--- a/chromium/content/renderer/cache_storage/webserviceworkercachestorage_impl.cc
+++ b/chromium/content/renderer/cache_storage/webserviceworkercachestorage_impl.cc
@@ -17,9 +17,8 @@ namespace content {
WebServiceWorkerCacheStorageImpl::WebServiceWorkerCacheStorageImpl(
ThreadSafeSender* thread_safe_sender,
- const GURL& origin)
- : thread_safe_sender_(thread_safe_sender), origin_(origin) {
-}
+ const url::Origin& origin)
+ : thread_safe_sender_(thread_safe_sender), origin_(origin) {}
WebServiceWorkerCacheStorageImpl::~WebServiceWorkerCacheStorageImpl() {
}
diff --git a/chromium/content/renderer/cache_storage/webserviceworkercachestorage_impl.h b/chromium/content/renderer/cache_storage/webserviceworkercachestorage_impl.h
index cc6d8e8ec0c..de77cad88c6 100644
--- a/chromium/content/renderer/cache_storage/webserviceworkercachestorage_impl.h
+++ b/chromium/content/renderer/cache_storage/webserviceworkercachestorage_impl.h
@@ -11,6 +11,7 @@
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerCache.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerCacheError.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerCacheStorage.h"
+#include "url/origin.h"
namespace content {
@@ -28,7 +29,7 @@ class WebServiceWorkerCacheStorageImpl
: public blink::WebServiceWorkerCacheStorage {
public:
WebServiceWorkerCacheStorageImpl(ThreadSafeSender* thread_safe_sender,
- const GURL& origin);
+ const url::Origin& origin);
~WebServiceWorkerCacheStorageImpl() override;
// From WebServiceWorkerCacheStorage:
@@ -49,7 +50,7 @@ class WebServiceWorkerCacheStorageImpl
CacheStorageDispatcher* GetDispatcher() const;
scoped_refptr<ThreadSafeSender> thread_safe_sender_;
- const GURL origin_;
+ const url::Origin origin_;
DISALLOW_COPY_AND_ASSIGN(WebServiceWorkerCacheStorageImpl);
};
diff --git a/chromium/content/renderer/child_frame_compositing_helper.cc b/chromium/content/renderer/child_frame_compositing_helper.cc
index ef8538437bd..cad94adbde0 100644
--- a/chromium/content/renderer/child_frame_compositing_helper.cc
+++ b/chromium/content/renderer/child_frame_compositing_helper.cc
@@ -7,9 +7,7 @@
#include <utility>
#include "cc/blink/web_layer_impl.h"
-#include "cc/layers/delegated_frame_provider.h"
-#include "cc/layers/delegated_frame_resource_collection.h"
-#include "cc/layers/delegated_renderer_layer.h"
+#include "cc/layers/picture_image_layer.h"
#include "cc/layers/solid_color_layer.h"
#include "cc/layers/surface_layer.h"
#include "cc/output/context_provider.h"
@@ -18,8 +16,11 @@
#include "cc/resources/single_release_callback.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/browser_plugin/browser_plugin_messages.h"
+#include "content/common/content_switches_internal.h"
#include "content/common/frame_messages.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
+#include "content/public/common/content_client.h"
+#include "content/public/renderer/content_renderer_client.h"
#include "content/renderer/browser_plugin/browser_plugin.h"
#include "content/renderer/browser_plugin/browser_plugin_manager.h"
#include "content/renderer/render_frame_impl.h"
@@ -29,6 +30,9 @@
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebPluginContainer.h"
#include "third_party/khronos/GLES2/gl2.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkImage.h"
+#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/skia_util.h"
@@ -56,17 +60,11 @@ ChildFrameCompositingHelper::ChildFrameCompositingHelper(
RenderFrameProxy* render_frame_proxy,
int host_routing_id)
: host_routing_id_(host_routing_id),
- last_route_id_(0),
- last_output_surface_id_(0),
- last_host_id_(0),
- ack_pending_(true),
browser_plugin_(browser_plugin),
render_frame_proxy_(render_frame_proxy),
frame_(frame) {}
ChildFrameCompositingHelper::~ChildFrameCompositingHelper() {
- if (resource_collection_.get())
- resource_collection_->SetClient(nullptr);
}
BrowserPluginManager* ChildFrameCompositingHelper::GetBrowserPluginManager() {
@@ -90,50 +88,6 @@ int ChildFrameCompositingHelper::GetInstanceID() {
return browser_plugin_->browser_plugin_instance_id();
}
-void ChildFrameCompositingHelper::SendCompositorFrameSwappedACKToBrowser(
- FrameHostMsg_CompositorFrameSwappedACK_Params& params) {
- // This function will be removed when BrowserPluginManager is removed and
- // BrowserPlugin is modified to use a RenderFrame.
- if (GetBrowserPluginManager()) {
- GetBrowserPluginManager()->Send(
- new BrowserPluginHostMsg_CompositorFrameSwappedACK(GetInstanceID(),
- params));
- } else if (render_frame_proxy_) {
- render_frame_proxy_->Send(
- new FrameHostMsg_CompositorFrameSwappedACK(host_routing_id_, params));
- }
-}
-
-void ChildFrameCompositingHelper::SendReclaimCompositorResourcesToBrowser(
- FrameHostMsg_ReclaimCompositorResources_Params& params) {
- // This function will be removed when BrowserPluginManager is removed and
- // BrowserPlugin is modified to use a RenderFrame.
- if (GetBrowserPluginManager()) {
- GetBrowserPluginManager()->Send(
- new BrowserPluginHostMsg_ReclaimCompositorResources(GetInstanceID(),
- params));
- } else if (render_frame_proxy_) {
- render_frame_proxy_->Send(
- new FrameHostMsg_ReclaimCompositorResources(host_routing_id_, params));
- }
-}
-
-void ChildFrameCompositingHelper::DidCommitCompositorFrame() {
- if (!resource_collection_.get() || !ack_pending_)
- return;
-
- FrameHostMsg_CompositorFrameSwappedACK_Params params;
- params.producing_host_id = last_host_id_;
- params.producing_route_id = last_route_id_;
- params.output_surface_id = last_output_surface_id_;
- resource_collection_->TakeUnusedResourcesForChildCompositor(
- &params.ack.resources);
-
- SendCompositorFrameSwappedACKToBrowser(params);
-
- ack_pending_ = false;
-}
-
void ChildFrameCompositingHelper::UpdateWebLayer(blink::WebLayer* layer) {
if (GetContainer()) {
GetContainer()->setWebLayer(layer);
@@ -159,93 +113,38 @@ void ChildFrameCompositingHelper::CheckSizeAndAdjustLayerProperties(
}
void ChildFrameCompositingHelper::OnContainerDestroy() {
- // If we have a pending ACK, then ACK now so we don't lose frames in the
- // future.
- DidCommitCompositorFrame();
-
UpdateWebLayer(nullptr);
-
- if (resource_collection_.get())
- resource_collection_->SetClient(nullptr);
-
- ack_pending_ = false;
- resource_collection_ = nullptr;
- frame_provider_ = nullptr;
}
void ChildFrameCompositingHelper::ChildFrameGone() {
scoped_refptr<cc::SolidColorLayer> crashed_layer =
- cc::SolidColorLayer::Create(cc_blink::WebLayerImpl::LayerSettings());
+ cc::SolidColorLayer::Create();
crashed_layer->SetMasksToBounds(true);
- crashed_layer->SetBackgroundColor(SkColorSetARGBInline(255, 0, 128, 0));
- blink::WebLayer* layer = new cc_blink::WebLayerImpl(crashed_layer);
- UpdateWebLayer(layer);
-}
-
-void ChildFrameCompositingHelper::OnCompositorFrameSwapped(
- scoped_ptr<cc::CompositorFrame> frame,
- int route_id,
- uint32_t output_surface_id,
- int host_id,
- base::SharedMemoryHandle handle) {
- cc::DelegatedFrameData* frame_data = frame->delegated_frame_data.get();
-
- // Do nothing if we are getting destroyed or have no frame data.
- if (!frame_data)
- return;
-
- DCHECK(!frame_data->render_pass_list.empty());
- cc::RenderPass* root_pass = frame_data->render_pass_list.back().get();
- gfx::Size frame_size = root_pass->output_rect.size();
-
- if (last_route_id_ != route_id ||
- last_output_surface_id_ != output_surface_id ||
- last_host_id_ != host_id) {
- // Resource ids are scoped by the output surface.
- // If the originating output surface doesn't match the last one, it
- // indicates the guest's output surface may have been recreated, in which
- // case we should recreate the DelegatedRendererLayer, to avoid matching
- // resources from the old one with resources from the new one which would
- // have the same id.
- frame_provider_ = nullptr;
-
- // Drop the cc::DelegatedFrameResourceCollection so that we will not return
- // any resources from the old output surface with the new output surface id.
- if (resource_collection_.get()) {
- resource_collection_->SetClient(nullptr);
-
- if (resource_collection_->LoseAllResources())
- SendReturnedDelegatedResources();
- resource_collection_ = nullptr;
+ crashed_layer->SetBackgroundColor(SK_ColorBLACK);
+
+ if (web_layer_) {
+ SkBitmap* sad_bitmap =
+ GetContentClient()->renderer()->GetSadWebViewBitmap();
+ if (sad_bitmap && web_layer_->bounds().width > sad_bitmap->width() &&
+ web_layer_->bounds().height > sad_bitmap->height()) {
+ scoped_refptr<cc::PictureImageLayer> sad_layer =
+ cc::PictureImageLayer::Create();
+ skia::RefPtr<SkImage> image =
+ skia::AdoptRef(SkImage::NewFromBitmap(*sad_bitmap));
+ sad_layer->SetImage(image);
+ sad_layer->SetBounds(
+ gfx::Size(sad_bitmap->width(), sad_bitmap->height()));
+ sad_layer->SetPosition(gfx::PointF(
+ (web_layer_->bounds().width - sad_bitmap->width()) / 2,
+ (web_layer_->bounds().height - sad_bitmap->height()) / 2));
+ sad_layer->SetIsDrawable(true);
+
+ crashed_layer->AddChild(sad_layer);
}
- last_output_surface_id_ = output_surface_id;
- last_route_id_ = route_id;
- last_host_id_ = host_id;
- }
- if (!resource_collection_.get()) {
- resource_collection_ = new cc::DelegatedFrameResourceCollection;
- resource_collection_->SetClient(this);
}
- if (!frame_provider_.get() || frame_provider_->frame_size() != frame_size) {
- frame_provider_ = new cc::DelegatedFrameProvider(
- resource_collection_.get(), std::move(frame->delegated_frame_data));
- scoped_refptr<cc::DelegatedRendererLayer> delegated_layer =
- cc::DelegatedRendererLayer::Create(
- cc_blink::WebLayerImpl::LayerSettings(), frame_provider_.get());
- delegated_layer->SetIsDrawable(true);
- buffer_size_ = gfx::Size();
- blink::WebLayer* layer = new cc_blink::WebLayerImpl(delegated_layer);
- UpdateWebLayer(layer);
- } else {
- frame_provider_->SetFrameData(std::move(frame->delegated_frame_data));
- }
-
- CheckSizeAndAdjustLayerProperties(
- frame_data->render_pass_list.back()->output_rect.size(),
- frame->metadata.device_scale_factor,
- static_cast<cc_blink::WebLayerImpl*>(web_layer_.get())->layer());
- ack_pending_ = true;
+ blink::WebLayer* layer = new cc_blink::WebLayerImpl(crashed_layer);
+ UpdateWebLayer(layer);
}
// static
@@ -293,6 +192,7 @@ void ChildFrameCompositingHelper::OnSetSurface(
const gfx::Size& frame_size,
float scale_factor,
const cc::SurfaceSequence& sequence) {
+ surface_id_ = surface_id;
scoped_refptr<ThreadSafeSender> sender(
RenderThreadImpl::current()->thread_safe_sender());
cc::SurfaceLayer::SatisfyCallback satisfy_callback =
@@ -312,8 +212,13 @@ void ChildFrameCompositingHelper::OnSetSurface(
sender, host_routing_id_,
browser_plugin_->browser_plugin_instance_id());
scoped_refptr<cc::SurfaceLayer> surface_layer =
- cc::SurfaceLayer::Create(cc_blink::WebLayerImpl::LayerSettings(),
- satisfy_callback, require_callback);
+ cc::SurfaceLayer::Create(satisfy_callback, require_callback);
+ // TODO(oshima): This is a stopgap fix so that the compositor does not
+ // scaledown the content when 2x frame data is added to 1x parent frame data.
+ // Fix this in cc/.
+ if (IsUseZoomForDSFEnabled())
+ scale_factor = 1.0f;
+
surface_layer->SetSurfaceId(surface_id, scale_factor, frame_size);
surface_layer->SetMasksToBounds(true);
blink::WebLayer* layer = new cc_blink::WebLayerImpl(surface_layer);
@@ -342,24 +247,4 @@ void ChildFrameCompositingHelper::UpdateVisibility(bool visible) {
web_layer_->setDrawsContent(visible);
}
-void ChildFrameCompositingHelper::UnusedResourcesAreAvailable() {
- if (ack_pending_)
- return;
-
- SendReturnedDelegatedResources();
-}
-
-void ChildFrameCompositingHelper::SendReturnedDelegatedResources() {
- FrameHostMsg_ReclaimCompositorResources_Params params;
- if (resource_collection_.get())
- resource_collection_->TakeUnusedResourcesForChildCompositor(
- &params.ack.resources);
- DCHECK(!params.ack.resources.empty());
-
- params.route_id = last_route_id_;
- params.output_surface_id = last_output_surface_id_;
- params.renderer_host_id = last_host_id_;
- SendReclaimCompositorResourcesToBrowser(params);
-}
-
} // namespace content
diff --git a/chromium/content/renderer/child_frame_compositing_helper.h b/chromium/content/renderer/child_frame_compositing_helper.h
index d2d4e78cda2..fda84a7755d 100644
--- a/chromium/content/renderer/child_frame_compositing_helper.h
+++ b/chromium/content/renderer/child_frame_compositing_helper.h
@@ -14,7 +14,8 @@
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory.h"
-#include "cc/layers/delegated_frame_resource_collection.h"
+#include "base/memory/weak_ptr.h"
+#include "cc/surfaces/surface_id.h"
#include "content/common/content_export.h"
#include "ui/gfx/geometry/size.h"
@@ -23,16 +24,12 @@ class SharedMemory;
}
namespace cc {
-struct SurfaceId;
struct SurfaceSequence;
class CompositorFrame;
class Layer;
class SolidColorLayer;
class SurfaceLayer;
-class DelegatedFrameProvider;
-class DelegatedFrameResourceCollection;
-class DelegatedRendererLayer;
}
namespace blink {
@@ -57,21 +54,14 @@ class RenderFrameProxy;
class ThreadSafeSender;
class CONTENT_EXPORT ChildFrameCompositingHelper
- : public base::RefCounted<ChildFrameCompositingHelper>,
- public cc::DelegatedFrameResourceCollectionClient {
+ : public base::RefCounted<ChildFrameCompositingHelper> {
public:
static ChildFrameCompositingHelper* CreateForBrowserPlugin(
const base::WeakPtr<BrowserPlugin>& browser_plugin);
static ChildFrameCompositingHelper* CreateForRenderFrameProxy(
RenderFrameProxy* render_frame_proxy);
- void DidCommitCompositorFrame();
void OnContainerDestroy();
- void OnCompositorFrameSwapped(scoped_ptr<cc::CompositorFrame> frame,
- int route_id,
- uint32_t output_surface_id,
- int host_id,
- base::SharedMemoryHandle handle);
void OnSetSurface(const cc::SurfaceId& surface_id,
const gfx::Size& frame_size,
float scale_factor,
@@ -79,8 +69,7 @@ class CONTENT_EXPORT ChildFrameCompositingHelper
void UpdateVisibility(bool);
void ChildFrameGone();
- // cc::DelegatedFrameProviderClient implementation.
- void UnusedResourcesAreAvailable() override;
+ cc::SurfaceId surface_id() const { return surface_id_; }
protected:
// Friend RefCounted so that the dtor can be non-public.
@@ -99,14 +88,9 @@ class CONTENT_EXPORT ChildFrameCompositingHelper
blink::WebPluginContainer* GetContainer();
int GetInstanceID();
- void SendCompositorFrameSwappedACKToBrowser(
- FrameHostMsg_CompositorFrameSwappedACK_Params& params);
- void SendReclaimCompositorResourcesToBrowser(
- FrameHostMsg_ReclaimCompositorResources_Params& params);
void CheckSizeAndAdjustLayerProperties(const gfx::Size& new_size,
float device_scale_factor,
cc::Layer* layer);
- void SendReturnedDelegatedResources();
static void SatisfyCallback(scoped_refptr<ThreadSafeSender> sender,
int host_routing_id,
cc::SurfaceSequence sequence);
@@ -128,10 +112,6 @@ class CONTENT_EXPORT ChildFrameCompositingHelper
void UpdateWebLayer(blink::WebLayer* layer);
int host_routing_id_;
- int last_route_id_;
- uint32_t last_output_surface_id_;
- int last_host_id_;
- bool ack_pending_;
bool opaque_;
gfx::Size buffer_size_;
@@ -142,10 +122,8 @@ class CONTENT_EXPORT ChildFrameCompositingHelper
base::WeakPtr<BrowserPlugin> browser_plugin_;
RenderFrameProxy* render_frame_proxy_;
- scoped_refptr<cc::DelegatedFrameResourceCollection> resource_collection_;
- scoped_refptr<cc::DelegatedFrameProvider> frame_provider_;
-
scoped_ptr<blink::WebLayer> web_layer_;
+ cc::SurfaceId surface_id_;
blink::WebFrame* frame_;
DISALLOW_COPY_AND_ASSIGN(ChildFrameCompositingHelper);
diff --git a/chromium/content/renderer/device_sensors/OWNERS b/chromium/content/renderer/device_sensors/OWNERS
index 30ee6ee9175..1fd89e0e2eb 100644
--- a/chromium/content/renderer/device_sensors/OWNERS
+++ b/chromium/content/renderer/device_sensors/OWNERS
@@ -1,3 +1 @@
-darin@chromium.org
-jamesr@chromium.org
timvolodine@chromium.org
diff --git a/chromium/content/renderer/devtools/devtools_agent.cc b/chromium/content/renderer/devtools/devtools_agent.cc
index 6de2625df8b..9d638d57589 100644
--- a/chromium/content/renderer/devtools/devtools_agent.cc
+++ b/chromium/content/renderer/devtools/devtools_agent.cc
@@ -25,10 +25,6 @@
#include "third_party/WebKit/public/web/WebDevToolsAgent.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
-#if defined(USE_TCMALLOC)
-#include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
-#endif
-
using blink::WebConsoleMessage;
using blink::WebDevToolsAgent;
using blink::WebDevToolsAgentClient;
@@ -91,6 +87,8 @@ bool DevToolsAgent::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(DevToolsAgentMsg_DispatchOnInspectorBackend,
OnDispatchOnInspectorBackend)
IPC_MESSAGE_HANDLER(DevToolsAgentMsg_InspectElement, OnInspectElement)
+ IPC_MESSAGE_HANDLER(DevToolsAgentMsg_RequestNewWindow_ACK,
+ OnRequestNewWindowACK)
IPC_MESSAGE_HANDLER(DevToolsMsg_SetupDevToolsClient, OnSetupDevToolsClient)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
@@ -109,6 +107,11 @@ void DevToolsAgent::sendProtocolMessage(int session_id,
int call_id,
const blink::WebString& message,
const blink::WebString& state_cookie) {
+ if (!send_protocol_message_callback_for_test_.is_null()) {
+ send_protocol_message_callback_for_test_.Run(
+ session_id, call_id, message.utf8(), state_cookie.utf8());
+ return;
+ }
SendChunkedProtocolMessage(this, routing_id(), session_id, call_id,
message.utf8(), state_cookie.utf8());
}
@@ -134,6 +137,15 @@ void DevToolsAgent::didExitDebugLoop() {
}
}
+bool DevToolsAgent::requestDevToolsForFrame(blink::WebLocalFrame* webFrame) {
+ RenderFrameImpl* frame = RenderFrameImpl::FromWebFrame(webFrame);
+ if (!frame)
+ return false;
+ Send(new DevToolsAgentHostMsg_RequestNewWindow(routing_id(),
+ frame->GetRoutingID()));
+ return true;
+}
+
void DevToolsAgent::enableTracing(const WebString& category_filter) {
// Tracing is already started by DevTools TracingHandler::Start for the
// renderer target in the browser process. It will eventually start tracing in
@@ -200,54 +212,42 @@ void DevToolsAgent::SendChunkedProtocolMessage(IPC::Sender* sender,
}
void DevToolsAgent::OnAttach(const std::string& host_id, int session_id) {
- WebDevToolsAgent* web_agent = GetWebAgent();
- if (web_agent) {
- web_agent->attach(WebString::fromUTF8(host_id), session_id);
- is_attached_ = true;
- }
+ GetWebAgent()->attach(WebString::fromUTF8(host_id), session_id);
+ is_attached_ = true;
}
void DevToolsAgent::OnReattach(const std::string& host_id,
int session_id,
const std::string& agent_state) {
- WebDevToolsAgent* web_agent = GetWebAgent();
- if (web_agent) {
- web_agent->reattach(WebString::fromUTF8(host_id), session_id,
- WebString::fromUTF8(agent_state));
- is_attached_ = true;
- }
+ GetWebAgent()->reattach(WebString::fromUTF8(host_id), session_id,
+ WebString::fromUTF8(agent_state));
+ is_attached_ = true;
}
void DevToolsAgent::OnDetach() {
- WebDevToolsAgent* web_agent = GetWebAgent();
- if (web_agent) {
- web_agent->detach();
- is_attached_ = false;
- }
+ GetWebAgent()->detach();
+ is_attached_ = false;
}
void DevToolsAgent::OnDispatchOnInspectorBackend(int session_id,
const std::string& message) {
TRACE_EVENT0("devtools", "DevToolsAgent::OnDispatchOnInspectorBackend");
- WebDevToolsAgent* web_agent = GetWebAgent();
- if (web_agent)
- web_agent->dispatchOnInspectorBackend(session_id,
- WebString::fromUTF8(message));
+ GetWebAgent()->dispatchOnInspectorBackend(session_id,
+ WebString::fromUTF8(message));
}
void DevToolsAgent::OnInspectElement(int x, int y) {
- WebDevToolsAgent* web_agent = GetWebAgent();
- if (web_agent) {
- DCHECK(is_attached_);
- web_agent->inspectElementAt(WebPoint(x, y));
- }
+ GetWebAgent()->inspectElementAt(WebPoint(x, y));
+}
+
+void DevToolsAgent::OnRequestNewWindowACK(bool success) {
+ if (!success)
+ GetWebAgent()->failedToRequestDevTools();
}
void DevToolsAgent::AddMessageToConsole(ConsoleMessageLevel level,
const std::string& message) {
WebLocalFrame* web_frame = frame_->GetWebFrame();
- if (!web_frame)
- return;
WebConsoleMessage::Level target_level = WebConsoleMessage::LevelLog;
switch (level) {
@@ -269,15 +269,13 @@ void DevToolsAgent::AddMessageToConsole(ConsoleMessageLevel level,
}
void DevToolsAgent::ContinueProgram() {
- WebDevToolsAgent* web_agent = GetWebAgent();
- if (web_agent)
- web_agent->continueProgram();
+ GetWebAgent()->continueProgram();
}
void DevToolsAgent::OnSetupDevToolsClient(
const std::string& compatibility_script) {
// We only want to register once; and only in main frame.
- DCHECK(!frame_->GetWebFrame() || !frame_->GetWebFrame()->parent());
+ DCHECK(!frame_->GetWebFrame()->parent());
if (is_devtools_client_)
return;
is_devtools_client_ = true;
@@ -285,8 +283,7 @@ void DevToolsAgent::OnSetupDevToolsClient(
}
WebDevToolsAgent* DevToolsAgent::GetWebAgent() {
- WebLocalFrame* web_frame = frame_->GetWebFrame();
- return web_frame ? web_frame->devToolsAgent() : nullptr;
+ return frame_->GetWebFrame()->devToolsAgent();
}
bool DevToolsAgent::IsAttached() {
diff --git a/chromium/content/renderer/devtools/devtools_agent.h b/chromium/content/renderer/devtools/devtools_agent.h
index ca763b7cf12..a54e41572af 100644
--- a/chromium/content/renderer/devtools/devtools_agent.h
+++ b/chromium/content/renderer/devtools/devtools_agent.h
@@ -7,6 +7,7 @@
#include <string>
+#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
@@ -67,6 +68,8 @@ class CONTENT_EXPORT DevToolsAgent
void willEnterDebugLoop() override;
void didExitDebugLoop() override;
+ bool requestDevToolsForFrame(blink::WebLocalFrame* frame) override;
+
void enableTracing(const blink::WebString& category_filter) override;
void disableTracing() override;
@@ -79,6 +82,7 @@ class CONTENT_EXPORT DevToolsAgent
void OnDetach();
void OnDispatchOnInspectorBackend(int session_id, const std::string& message);
void OnInspectElement(int x, int y);
+ void OnRequestNewWindowACK(bool success);
void ContinueProgram();
void OnSetupDevToolsClient(const std::string& compatibility_script);
@@ -87,6 +91,8 @@ class CONTENT_EXPORT DevToolsAgent
bool paused_in_mouse_move_;
bool paused_;
RenderFrameImpl* frame_;
+ base::Callback<void(int, int, const std::string&, const std::string&)>
+ send_protocol_message_callback_for_test_;
scoped_ptr<DevToolsCPUThrottler> cpu_throttler_;
DISALLOW_COPY_AND_ASSIGN(DevToolsAgent);
diff --git a/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator.cc b/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator.cc
new file mode 100644
index 00000000000..bad6fa72699
--- /dev/null
+++ b/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator.cc
@@ -0,0 +1,177 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/devtools/render_widget_screen_metrics_emulator.h"
+
+#include "content/common/resize_params.h"
+#include "content/public/common/context_menu_params.h"
+#include "content/renderer/devtools/render_widget_screen_metrics_emulator_delegate.h"
+
+namespace content {
+
+RenderWidgetScreenMetricsEmulator::RenderWidgetScreenMetricsEmulator(
+ RenderWidgetScreenMetricsEmulatorDelegate* delegate,
+ const blink::WebDeviceEmulationParams& params,
+ const ResizeParams& resize_params,
+ const gfx::Rect& view_screen_rect,
+ const gfx::Rect& window_screen_rect)
+ : delegate_(delegate),
+ emulation_params_(params),
+ scale_(1.f),
+ original_resize_params_(resize_params),
+ original_view_screen_rect_(view_screen_rect),
+ original_window_screen_rect_(window_screen_rect) {
+}
+
+RenderWidgetScreenMetricsEmulator::~RenderWidgetScreenMetricsEmulator() {
+ delegate_->SetScreenMetricsEmulationParameters(false, emulation_params_);
+ delegate_->SetScreenRects(original_view_screen_rect_,
+ original_window_screen_rect_);
+ delegate_->Resize(original_resize_params_);
+}
+
+void RenderWidgetScreenMetricsEmulator::ChangeEmulationParams(
+ const blink::WebDeviceEmulationParams& params) {
+ emulation_params_ = params;
+ Apply();
+}
+
+void RenderWidgetScreenMetricsEmulator::Apply() {
+ ResizeParams modified_resize_params = original_resize_params_;
+ applied_widget_rect_.set_size(gfx::Size(emulation_params_.viewSize));
+
+ if (!applied_widget_rect_.width())
+ applied_widget_rect_.set_width(original_size().width());
+
+ if (!applied_widget_rect_.height())
+ applied_widget_rect_.set_height(original_size().height());
+
+ if (emulation_params_.fitToView && !original_size().IsEmpty()) {
+ int original_width = std::max(original_size().width(), 1);
+ int original_height = std::max(original_size().height(), 1);
+ float width_ratio =
+ static_cast<float>(applied_widget_rect_.width()) / original_width;
+ float height_ratio =
+ static_cast<float>(applied_widget_rect_.height()) / original_height;
+ float ratio = std::max(1.0f, std::max(width_ratio, height_ratio));
+ scale_ = 1.f / ratio;
+
+ // Center emulated view inside available view space.
+ offset_.set_x(
+ (original_size().width() - scale_ * applied_widget_rect_.width()) / 2);
+ offset_.set_y(
+ (original_size().height() - scale_ * applied_widget_rect_.height()) /
+ 2);
+ } else {
+ scale_ = emulation_params_.scale;
+ offset_.SetPoint(emulation_params_.offset.x, emulation_params_.offset.y);
+ if (!emulation_params_.viewSize.width &&
+ !emulation_params_.viewSize.height && scale_) {
+ applied_widget_rect_.set_size(
+ gfx::ScaleToRoundedSize(original_size(), 1.f / scale_));
+ }
+ }
+
+ gfx::Rect window_screen_rect;
+ if (emulation_params_.screenPosition ==
+ blink::WebDeviceEmulationParams::Desktop) {
+ applied_widget_rect_.set_origin(original_view_screen_rect_.origin());
+ modified_resize_params.screen_info.rect = original_screen_info().rect;
+ modified_resize_params.screen_info.availableRect =
+ original_screen_info().availableRect;
+ window_screen_rect = original_window_screen_rect_;
+ } else {
+ applied_widget_rect_.set_origin(emulation_params_.viewPosition);
+ gfx::Rect screen_rect = applied_widget_rect_;
+ if (!emulation_params_.screenSize.isEmpty()) {
+ screen_rect = gfx::Rect(0, 0, emulation_params_.screenSize.width,
+ emulation_params_.screenSize.height);
+ }
+ modified_resize_params.screen_info.rect = screen_rect;
+ modified_resize_params.screen_info.availableRect = screen_rect;
+ window_screen_rect = applied_widget_rect_;
+ }
+
+ modified_resize_params.screen_info.deviceScaleFactor =
+ emulation_params_.deviceScaleFactor
+ ? emulation_params_.deviceScaleFactor
+ : original_screen_info().deviceScaleFactor;
+
+ if (emulation_params_.screenOrientationType !=
+ blink::WebScreenOrientationUndefined) {
+ modified_resize_params.screen_info.orientationType =
+ emulation_params_.screenOrientationType;
+ modified_resize_params.screen_info.orientationAngle =
+ emulation_params_.screenOrientationAngle;
+ }
+
+ // Pass three emulation parameters to the blink side:
+ // - we keep the real device scale factor in compositor to produce sharp image
+ // even when emulating different scale factor;
+ // - in order to fit into view, WebView applies offset and scale to the
+ // root layer.
+ blink::WebDeviceEmulationParams modified_emulation_params = emulation_params_;
+ modified_emulation_params.deviceScaleFactor =
+ original_screen_info().deviceScaleFactor;
+ modified_emulation_params.offset =
+ blink::WebFloatPoint(offset_.x(), offset_.y());
+ modified_emulation_params.scale = scale_;
+ delegate_->SetScreenMetricsEmulationParameters(true,
+ modified_emulation_params);
+
+ delegate_->SetScreenRects(applied_widget_rect_, window_screen_rect);
+
+ modified_resize_params.physical_backing_size =
+ gfx::ScaleToCeiledSize(original_resize_params_.new_size,
+ original_screen_info().deviceScaleFactor);
+ modified_resize_params.new_size = applied_widget_rect_.size();
+ modified_resize_params.visible_viewport_size = applied_widget_rect_.size();
+ modified_resize_params.needs_resize_ack = false;
+ delegate_->Resize(modified_resize_params);
+}
+
+void RenderWidgetScreenMetricsEmulator::OnResize(const ResizeParams& params) {
+ original_resize_params_ = params;
+ Apply();
+
+ if (params.needs_resize_ack)
+ delegate_->Redraw();
+}
+
+void RenderWidgetScreenMetricsEmulator::OnUpdateWindowScreenRect(
+ const gfx::Rect& window_screen_rect) {
+ original_window_screen_rect_ = window_screen_rect;
+ if (emulation_params_.screenPosition ==
+ blink::WebDeviceEmulationParams::Desktop)
+ Apply();
+}
+
+void RenderWidgetScreenMetricsEmulator::OnUpdateScreenRects(
+ const gfx::Rect& view_screen_rect,
+ const gfx::Rect& window_screen_rect) {
+ original_view_screen_rect_ = view_screen_rect;
+ original_window_screen_rect_ = window_screen_rect;
+ if (emulation_params_.screenPosition ==
+ blink::WebDeviceEmulationParams::Desktop) {
+ Apply();
+ }
+}
+
+void RenderWidgetScreenMetricsEmulator::OnShowContextMenu(
+ ContextMenuParams* params) {
+ params->x *= scale_;
+ params->x += offset_.x();
+ params->y *= scale_;
+ params->y += offset_.y();
+}
+
+gfx::Rect RenderWidgetScreenMetricsEmulator::AdjustValidationMessageAnchor(
+ const gfx::Rect& anchor) {
+ gfx::Rect scaled = gfx::ScaleToEnclosedRect(anchor, scale_);
+ scaled.set_x(scaled.x() + offset_.x());
+ scaled.set_y(scaled.y() + offset_.y());
+ return scaled;
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator.h b/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator.h
new file mode 100644
index 00000000000..5650d0a3ed7
--- /dev/null
+++ b/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator.h
@@ -0,0 +1,89 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_DEVTOOLS_RENDER_WIDGET_SCREEN_METRICS_EMULATOR_H_
+#define CONTENT_RENDERER_DEVTOOLS_RENDER_WIDGET_SCREEN_METRICS_EMULATOR_H_
+
+#include "base/memory/scoped_ptr.h"
+#include "content/common/resize_params.h"
+#include "third_party/WebKit/public/web/WebDeviceEmulationParams.h"
+
+namespace gfx {
+class PointF;
+class Rect;
+}
+
+namespace content {
+
+class RenderWidgetScreenMetricsEmulatorDelegate;
+struct ContextMenuParams;
+
+// RenderWidgetScreenMetricsEmulator class manages screen emulation inside a
+// RenderWidget. This includes resizing, placing view on the screen at desired
+// position, changing device scale factor, and scaling down the whole
+// widget if required to fit into the browser window.
+class RenderWidgetScreenMetricsEmulator {
+ public:
+ RenderWidgetScreenMetricsEmulator(
+ RenderWidgetScreenMetricsEmulatorDelegate* delegate,
+ const blink::WebDeviceEmulationParams& params,
+ const ResizeParams& resize_params,
+ const gfx::Rect& view_screen_rect,
+ const gfx::Rect& window_screen_rect);
+ virtual ~RenderWidgetScreenMetricsEmulator();
+
+ // Scale and offset used to convert between host coordinates
+ // and webwidget coordinates.
+ const gfx::Size& original_size() const {
+ return original_resize_params_.new_size;
+ }
+
+ float scale() const { return scale_; }
+ const gfx::PointF& offset() const { return offset_; }
+ const gfx::Rect& applied_widget_rect() const { return applied_widget_rect_; }
+ const blink::WebScreenInfo& original_screen_info() const {
+ return original_resize_params_.screen_info;
+ }
+ const gfx::Rect& original_screen_rect() const {
+ return original_view_screen_rect_;
+ }
+
+ void ChangeEmulationParams(const blink::WebDeviceEmulationParams& params);
+
+ // The following methods alter handlers' behavior for messages related to
+ // widget size and position.
+ void OnResize(const ResizeParams& params);
+ void OnUpdateWindowScreenRect(const gfx::Rect& window_screen_rect);
+ void OnUpdateScreenRects(const gfx::Rect& view_screen_rect,
+ const gfx::Rect& window_screen_rect);
+ void OnShowContextMenu(ContextMenuParams* params);
+ gfx::Rect AdjustValidationMessageAnchor(const gfx::Rect& anchor);
+
+ // Apply parameters to the render widget.
+ void Apply();
+
+ private:
+ RenderWidgetScreenMetricsEmulatorDelegate* const delegate_;
+
+ // Parameters as passed by RenderWidget::EnableScreenMetricsEmulation.
+ blink::WebDeviceEmulationParams emulation_params_;
+
+ // The computed scale and offset used to fit widget into browser window.
+ float scale_;
+ gfx::PointF offset_;
+
+ // Widget rect as passed to webwidget.
+ gfx::Rect applied_widget_rect_;
+
+ // Original values to restore back after emulation ends.
+ ResizeParams original_resize_params_;
+ gfx::Rect original_view_screen_rect_;
+ gfx::Rect original_window_screen_rect_;
+
+ DISALLOW_COPY_AND_ASSIGN(RenderWidgetScreenMetricsEmulator);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_DEVTOOLS_RENDER_WIDGET_SCREEN_METRICS_EMULATOR_H_
diff --git a/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator_delegate.h b/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator_delegate.h
new file mode 100644
index 00000000000..af79f1967b6
--- /dev/null
+++ b/chromium/content/renderer/devtools/render_widget_screen_metrics_emulator_delegate.h
@@ -0,0 +1,44 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_DEVTOOLS_RENDER_WIDGET_SCREEN_METRICS_EMULATOR_DELEGATE_H_
+#define CONTENT_RENDERER_DEVTOOLS_RENDER_WIDGET_SCREEN_METRICS_EMULATOR_DELEGATE_H_
+
+#include "content/common/content_export.h"
+
+namespace blink {
+struct WebDeviceEmulationParams;
+}
+
+namespace content {
+
+struct ResizeParams;
+
+// Consumers of RenderWidgetScreenMetricsEmulatorDelegate implement this
+// delegate in order to transport emulation information across processes.
+class CONTENT_EXPORT RenderWidgetScreenMetricsEmulatorDelegate {
+ public:
+ // Requests a full redraw of the contents of the renderer.
+ virtual void Redraw() = 0;
+
+ // Resizes the Widget with the provided |resize_params|.
+ virtual void Resize(const ResizeParams& resize_params) = 0;
+
+ // Passes device emulation parameters to the delegate.
+ virtual void SetScreenMetricsEmulationParameters(
+ bool enabled,
+ const blink::WebDeviceEmulationParams& params) = 0;
+
+ // Passes new view bounds and window bounds in screen coordinates to the
+ // delegate.
+ virtual void SetScreenRects(const gfx::Rect& view_screen_rect,
+ const gfx::Rect& window_screen_rect) = 0;
+
+ protected:
+ virtual ~RenderWidgetScreenMetricsEmulatorDelegate() {}
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_DEVTOOLS_RENDER_WIDGET_SCREEN_METRICS_EMULATOR_DELEGATE_H_
diff --git a/chromium/content/renderer/devtools/v8_sampling_profiler.cc b/chromium/content/renderer/devtools/v8_sampling_profiler.cc
index dfd21870974..4ad7ffaf654 100644
--- a/chromium/content/renderer/devtools/v8_sampling_profiler.cc
+++ b/chromium/content/renderer/devtools/v8_sampling_profiler.cc
@@ -106,7 +106,7 @@ class SampleRecord {
void Collect(v8::Isolate* isolate,
base::TimeTicks timestamp,
const v8::RegisterState& state);
- scoped_refptr<ConvertableToTraceFormat> ToTraceFormat() const;
+ scoped_ptr<ConvertableToTraceFormat> ToTraceFormat() const;
private:
base::TimeTicks timestamp_;
@@ -128,8 +128,9 @@ void SampleRecord::Collect(v8::Isolate* isolate,
vm_state_ = sample_info.vm_state;
}
-scoped_refptr<ConvertableToTraceFormat> SampleRecord::ToTraceFormat() const {
- scoped_refptr<TracedValue> data(new TracedValue());
+scoped_ptr<ConvertableToTraceFormat> SampleRecord::ToTraceFormat() const {
+ scoped_ptr<base::trace_event::TracedValue> data(
+ new base::trace_event::TracedValue());
const char* vm_state = nullptr;
switch (vm_state_) {
case v8::StateTag::JS:
@@ -159,7 +160,7 @@ scoped_refptr<ConvertableToTraceFormat> SampleRecord::ToTraceFormat() const {
data->AppendString(PtrToString(frames_[i]));
}
data->EndArray();
- return data;
+ return std::move(data);
}
} // namespace
@@ -196,7 +197,7 @@ class Sampler {
static void InstallJitCodeEventHandler(Isolate* isolate, void* data);
static void HandleJitCodeEvent(const v8::JitCodeEvent* event);
- static scoped_refptr<ConvertableToTraceFormat> JitCodeEventToTraceFormat(
+ static scoped_ptr<ConvertableToTraceFormat> JitCodeEventToTraceFormat(
const v8::JitCodeEvent* event);
void InjectPendingEvents();
@@ -332,23 +333,23 @@ void Sampler::HandleJitCodeEvent(const v8::JitCodeEvent* event) {
return;
switch (event->type) {
case v8::JitCodeEvent::CODE_ADDED:
- TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("v8.cpu_profile"),
- "JitCodeAdded", TRACE_EVENT_SCOPE_THREAD, "data",
- JitCodeEventToTraceFormat(event));
+ TRACE_EVENT_METADATA1(TRACE_DISABLED_BY_DEFAULT("v8.cpu_profile"),
+ "JitCodeAdded", "data",
+ JitCodeEventToTraceFormat(event));
base::subtle::NoBarrier_AtomicIncrement(
&sampler->code_added_events_count_, 1);
break;
case v8::JitCodeEvent::CODE_MOVED:
- TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("v8.cpu_profile"),
- "JitCodeMoved", TRACE_EVENT_SCOPE_THREAD, "data",
- JitCodeEventToTraceFormat(event));
+ TRACE_EVENT_METADATA1(TRACE_DISABLED_BY_DEFAULT("v8.cpu_profile"),
+ "JitCodeMoved", "data",
+ JitCodeEventToTraceFormat(event));
break;
case v8::JitCodeEvent::CODE_REMOVED:
- TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("v8.cpu_profile"),
- "JitCodeRemoved", TRACE_EVENT_SCOPE_THREAD, "data",
- JitCodeEventToTraceFormat(event));
+ TRACE_EVENT_METADATA1(TRACE_DISABLED_BY_DEFAULT("v8.cpu_profile"),
+ "JitCodeRemoved", "data",
+ JitCodeEventToTraceFormat(event));
break;
case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO:
@@ -359,33 +360,36 @@ void Sampler::HandleJitCodeEvent(const v8::JitCodeEvent* event) {
}
// static
-scoped_refptr<ConvertableToTraceFormat> Sampler::JitCodeEventToTraceFormat(
+scoped_ptr<ConvertableToTraceFormat> Sampler::JitCodeEventToTraceFormat(
const v8::JitCodeEvent* event) {
switch (event->type) {
case v8::JitCodeEvent::CODE_ADDED: {
- scoped_refptr<TracedValue> data(new TracedValue());
+ scoped_ptr<base::trace_event::TracedValue> data(
+ new base::trace_event::TracedValue());
data->SetString("code_start", PtrToString(event->code_start));
data->SetInteger("code_len", static_cast<unsigned>(event->code_len));
data->SetString("name", std::string(event->name.str, event->name.len));
if (!event->script.IsEmpty()) {
data->SetInteger("script_id", event->script->GetId());
}
- return data;
+ return std::move(data);
}
case v8::JitCodeEvent::CODE_MOVED: {
- scoped_refptr<TracedValue> data(new TracedValue());
+ scoped_ptr<base::trace_event::TracedValue> data(
+ new base::trace_event::TracedValue());
data->SetString("code_start", PtrToString(event->code_start));
data->SetInteger("code_len", static_cast<unsigned>(event->code_len));
data->SetString("new_code_start", PtrToString(event->new_code_start));
- return data;
+ return std::move(data);
}
case v8::JitCodeEvent::CODE_REMOVED: {
- scoped_refptr<TracedValue> data(new TracedValue());
+ scoped_ptr<base::trace_event::TracedValue> data(
+ new base::trace_event::TracedValue());
data->SetString("code_start", PtrToString(event->code_start));
data->SetInteger("code_len", static_cast<unsigned>(event->code_len));
- return data;
+ return std::move(data);
}
case v8::JitCodeEvent::CODE_ADD_LINE_POS_INFO:
diff --git a/chromium/content/renderer/devtools/v8_sampling_profiler.h b/chromium/content/renderer/devtools/v8_sampling_profiler.h
index 84fa97d252b..6d5b4322444 100644
--- a/chromium/content/renderer/devtools/v8_sampling_profiler.h
+++ b/chromium/content/renderer/devtools/v8_sampling_profiler.h
@@ -6,6 +6,7 @@
#define CONTENT_RENDERER_DEVTOOLS_V8_SAMPLING_PROFILER_H_
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/waitable_event.h"
#include "base/trace_event/trace_log.h"
diff --git a/chromium/content/renderer/devtools/v8_sampling_profiler_browsertest.cc b/chromium/content/renderer/devtools/v8_sampling_profiler_browsertest.cc
index 9e7df0bec0f..302b7454c9b 100644
--- a/chromium/content/renderer/devtools/v8_sampling_profiler_browsertest.cc
+++ b/chromium/content/renderer/devtools/v8_sampling_profiler_browsertest.cc
@@ -5,6 +5,7 @@
#include <stddef.h>
#include "base/json/json_reader.h"
+#include "base/memory/ref_counted_memory.h"
#include "base/run_loop.h"
#include "base/trace_event/trace_buffer.h"
#include "base/trace_event/trace_event.h"
diff --git a/chromium/content/renderer/dom_serializer_browsertest.cc b/chromium/content/renderer/dom_serializer_browsertest.cc
index 526725466aa..3c3e549c12b 100644
--- a/chromium/content/renderer/dom_serializer_browsertest.cc
+++ b/chromium/content/renderer/dom_serializer_browsertest.cc
@@ -152,12 +152,37 @@ class DomSerializerTests : public ContentBrowserTest,
ASSERT_TRUE(web_frame != NULL);
- web_frame->loadData(data, "text/html", encoding_info, base_url);
+ web_frame->toWebLocalFrame()->loadData(data, "text/html", encoding_info,
+ base_url);
}
runner->Run();
}
+ class SingleLinkRewritingDelegate
+ : public WebFrameSerializer::LinkRewritingDelegate {
+ public:
+ SingleLinkRewritingDelegate(const WebURL& url, const WebString& localPath)
+ : url_(url), local_path_(localPath) {}
+
+ bool rewriteFrameSource(WebFrame* frame,
+ WebString* rewritten_link) override {
+ return false;
+ }
+
+ bool rewriteLink(const WebURL& url, WebString* rewritten_link) override {
+ if (url != url_)
+ return false;
+
+ *rewritten_link = local_path_;
+ return true;
+ }
+
+ private:
+ const WebURL url_;
+ const WebString local_path_;
+ };
+
// Serialize DOM belonging to a frame with the specified |frame_url|.
void SerializeDomForURL(const GURL& frame_url) {
// Find corresponding WebFrame according to frame_url.
@@ -165,12 +190,10 @@ class DomSerializerTests : public ContentBrowserTest,
ASSERT_TRUE(web_frame != NULL);
WebString file_path =
base::FilePath(FILE_PATH_LITERAL("c:\\dummy.htm")).AsUTF16Unsafe();
- std::vector<std::pair<WebURL, WebString>> url_to_local_path;
- url_to_local_path.push_back(std::make_pair(WebURL(frame_url), file_path));
+ SingleLinkRewritingDelegate delegate(frame_url, file_path);
// Start serializing DOM.
- bool result = WebFrameSerializer::serialize(
- web_frame->toWebLocalFrame(),
- static_cast<WebFrameSerializerClient*>(this), url_to_local_path);
+ bool result = WebFrameSerializer::serialize(web_frame->toWebLocalFrame(),
+ this, &delegate);
ASSERT_TRUE(result);
}
@@ -617,15 +640,11 @@ class DomSerializerTests : public ContentBrowserTest,
// If original contents have document type, the serialized contents also have
// document type.
-// Disabled by ellyjones@ on 2015-05-18, see https://crbug.com/488495.
-#if defined(OS_MACOSX)
-#define MAYBE_SerializeHTMLDOMWithDocType DISABLED_SerializeHTMLDOMWithDocType
-#else
-#define MAYBE_SerializeHTMLDOMWithDocType SerializeHTMLDOMWithDocType
-#endif
+// Disabled on OSX by ellyjones@ on 2015-05-18, see https://crbug.com/488495,
+// on all platforms by tsergeant@ on 2016-03-10, see https://crbug.com/593575
IN_PROC_BROWSER_TEST_F(DomSerializerTests,
- MAYBE_SerializeHTMLDOMWithDocType) {
+ DISABLED_SerializeHTMLDOMWithDocType) {
base::FilePath page_file_path =
GetTestFilePath("dom_serializer", "youtube_1.htm");
GURL file_url = net::FilePathToFileURL(page_file_path);
@@ -702,16 +721,11 @@ IN_PROC_BROWSER_TEST_F(DomSerializerTests, SerializeHTMLDOMWithAddingMOTW) {
// declaration as first child of HEAD element for resolving WebKit bug:
// http://bugs.webkit.org/show_bug.cgi?id=16621 even the original document
// does not have META charset declaration.
-// Disabled by battre@ on 2015-05-21, see https://crbug.com/488495.
-#if defined(OS_MACOSX)
-#define MAYBE_SerializeHTMLDOMWithNoMetaCharsetInOriginalDoc \
- DISABLED_SerializeHTMLDOMWithNoMetaCharsetInOriginalDoc
-#else
-#define MAYBE_SerializeHTMLDOMWithNoMetaCharsetInOriginalDoc \
- SerializeHTMLDOMWithNoMetaCharsetInOriginalDoc
-#endif
-IN_PROC_BROWSER_TEST_F(DomSerializerTests,
- MAYBE_SerializeHTMLDOMWithNoMetaCharsetInOriginalDoc) {
+// Disabled on OSX by battre@ on 2015-05-21, see https://crbug.com/488495,
+// on all platforms by tsergeant@ on 2016-03-10, see https://crbug.com/593575
+IN_PROC_BROWSER_TEST_F(
+ DomSerializerTests,
+ DISABLED_SerializeHTMLDOMWithNoMetaCharsetInOriginalDoc) {
base::FilePath page_file_path =
GetTestFilePath("dom_serializer", "youtube_1.htm");
// Get file URL.
diff --git a/chromium/content/renderer/dom_storage/DEPS b/chromium/content/renderer/dom_storage/DEPS
new file mode 100644
index 00000000000..495daf36db9
--- /dev/null
+++ b/chromium/content/renderer/dom_storage/DEPS
@@ -0,0 +1,11 @@
+specific_include_rules = {
+ 'local_storage\.*': [
+ "-content/renderer",
+ "+components/leveldb/public/interfaces",
+ "+content/common/dom_storage/dom_storage_map.h",
+ "+content/renderer/dom_storage/local_storage_cached_area.h",
+ "+content/renderer/dom_storage/local_storage_cached_areas.h",
+ "+content/renderer/dom_storage/local_storage_area.h",
+ "+content/renderer/dom_storage/local_storage_namespace.h",
+ ],
+}
diff --git a/chromium/content/renderer/dom_storage/dom_storage_cached_area.cc b/chromium/content/renderer/dom_storage/dom_storage_cached_area.cc
index 23f3d35428e..b408f2adaf8 100644
--- a/chromium/content/renderer/dom_storage/dom_storage_cached_area.cc
+++ b/chromium/content/renderer/dom_storage/dom_storage_cached_area.cc
@@ -140,10 +140,6 @@ void DOMStorageCachedArea::ApplyMutation(
map_->set_quota(kPerStorageAreaQuota);
}
-size_t DOMStorageCachedArea::MemoryBytesUsedByCache() const {
- return map_.get() ? map_->bytes_used() : 0;
-}
-
void DOMStorageCachedArea::Prime(int connection_id) {
DCHECK(!map_.get());
diff --git a/chromium/content/renderer/dom_storage/dom_storage_cached_area.h b/chromium/content/renderer/dom_storage/dom_storage_cached_area.h
index 61219146ccf..be365c087a4 100644
--- a/chromium/content/renderer/dom_storage/dom_storage_cached_area.h
+++ b/chromium/content/renderer/dom_storage/dom_storage_cached_area.h
@@ -52,8 +52,6 @@ class CONTENT_EXPORT DOMStorageCachedArea
void ApplyMutation(const base::NullableString16& key,
const base::NullableString16& new_value);
- size_t MemoryBytesUsedByCache() const;
-
private:
friend class DOMStorageCachedAreaTest;
friend class base::RefCounted<DOMStorageCachedArea>;
diff --git a/chromium/content/renderer/dom_storage/dom_storage_dispatcher.cc b/chromium/content/renderer/dom_storage/dom_storage_dispatcher.cc
index 29dbb043e06..05ac68d9b04 100644
--- a/chromium/content/renderer/dom_storage/dom_storage_dispatcher.cc
+++ b/chromium/content/renderer/dom_storage/dom_storage_dispatcher.cc
@@ -299,11 +299,8 @@ bool DomStorageDispatcher::OnMessageReceived(const IPC::Message& msg) {
void DomStorageDispatcher::OnStorageEvent(
const DOMStorageMsg_Event_Params& params) {
- RenderThreadImpl::current()->EnsureWebKitInitialized();
-
- bool originated_in_process = params.connection_id != 0;
WebStorageAreaImpl* originating_area = NULL;
- if (originated_in_process) {
+ if (params.connection_id) {
originating_area = WebStorageAreaImpl::FromConnectionId(
params.connection_id);
} else {
@@ -320,8 +317,7 @@ void DomStorageDispatcher::OnStorageEvent(
params.new_value,
params.origin,
params.page_url,
- originating_area,
- originated_in_process);
+ originating_area);
} else {
WebStorageNamespaceImpl
session_namespace_for_event_dispatch(params.namespace_id);
@@ -332,8 +328,7 @@ void DomStorageDispatcher::OnStorageEvent(
params.origin,
params.page_url,
session_namespace_for_event_dispatch,
- originating_area,
- originated_in_process);
+ originating_area);
}
}
diff --git a/chromium/content/renderer/dom_storage/local_storage_area.cc b/chromium/content/renderer/dom_storage/local_storage_area.cc
new file mode 100644
index 00000000000..c551790c113
--- /dev/null
+++ b/chromium/content/renderer/dom_storage/local_storage_area.cc
@@ -0,0 +1,57 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/dom_storage/local_storage_area.h"
+
+#include "base/rand_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
+
+using blink::WebString;
+using blink::WebURL;
+
+namespace content {
+
+LocalStorageArea::LocalStorageArea(
+ scoped_refptr<LocalStorageCachedArea> cached_area)
+ : cached_area_(std::move(cached_area)),
+ id_(base::Uint64ToString(base::RandUint64())) {
+ cached_area_->AreaCreated(this);
+}
+
+LocalStorageArea::~LocalStorageArea() {
+ cached_area_->AreaDestroyed(this);
+}
+
+unsigned LocalStorageArea::length() {
+ return cached_area_->GetLength();
+}
+
+WebString LocalStorageArea::key(unsigned index) {
+ return cached_area_->GetKey(index);
+}
+
+WebString LocalStorageArea::getItem(const WebString& key) {
+ return cached_area_->GetItem(key);
+}
+
+void LocalStorageArea::setItem(
+ const WebString& key, const WebString& value, const WebURL& page_url,
+ WebStorageArea::Result& result) {
+ if (!cached_area_->SetItem(key, value, page_url, id_))
+ result = ResultBlockedByQuota;
+ else
+ result = ResultOK;
+}
+
+void LocalStorageArea::removeItem(
+ const WebString& key, const WebURL& page_url) {
+ cached_area_->RemoveItem(key, page_url, id_);
+}
+
+void LocalStorageArea::clear(const WebURL& page_url) {
+ cached_area_->Clear(page_url, id_);
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/dom_storage/local_storage_area.h b/chromium/content/renderer/dom_storage/local_storage_area.h
new file mode 100644
index 00000000000..31252154513
--- /dev/null
+++ b/chromium/content/renderer/dom_storage/local_storage_area.h
@@ -0,0 +1,48 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_DOM_STORAGE_LOCAL_STORAGE_AREA_H_
+#define CONTENT_RENDERER_DOM_STORAGE_LOCAL_STORAGE_AREA_H_
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "content/renderer/dom_storage/local_storage_cached_area.h"
+#include "third_party/WebKit/public/platform/WebStorageArea.h"
+
+namespace content {
+
+// There could be n instances of this class for the same origin in a renderer
+// process. It delegates to the one LocalStorageCachedArea instance in a process
+// for a given origin.
+class LocalStorageArea : public blink::WebStorageArea {
+ public:
+ explicit LocalStorageArea(scoped_refptr<LocalStorageCachedArea> cached_area);
+ ~LocalStorageArea() override;
+
+ // blink::WebStorageArea:
+ unsigned length() override;
+ blink::WebString key(unsigned index) override;
+ blink::WebString getItem(const blink::WebString& key) override;
+ void setItem(const blink::WebString& key,
+ const blink::WebString& value,
+ const blink::WebURL& page_url,
+ WebStorageArea::Result& result) override;
+ void removeItem(const blink::WebString& key,
+ const blink::WebURL& page_url) override;
+ void clear(const blink::WebURL& url) override;
+
+ const std::string& id() const { return id_; }
+
+ private:
+ scoped_refptr<LocalStorageCachedArea> cached_area_;
+ // A globally unique identifier for this storage area. It's used to pass the
+ // source storage area, if any, in mutation events.
+ std::string id_;
+
+ DISALLOW_COPY_AND_ASSIGN(LocalStorageArea);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_DOM_STORAGE_LOCAL_STORAGE_AREA_H_
diff --git a/chromium/content/renderer/dom_storage/local_storage_cached_area.cc b/chromium/content/renderer/dom_storage/local_storage_cached_area.cc
new file mode 100644
index 00000000000..1f191a20da2
--- /dev/null
+++ b/chromium/content/renderer/dom_storage/local_storage_cached_area.cc
@@ -0,0 +1,336 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/dom_storage/local_storage_cached_area.h"
+
+#include "base/bind.h"
+#include "base/metrics/histogram_macros.h"
+#include "base/rand_util.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
+#include "base/time/time.h"
+#include "content/common/dom_storage/dom_storage_map.h"
+#include "content/common/storage_partition_service.mojom.h"
+#include "content/renderer/dom_storage/local_storage_area.h"
+#include "content/renderer/dom_storage/local_storage_cached_areas.h"
+#include "mojo/common/common_type_converters.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
+#include "third_party/WebKit/public/web/WebStorageEventDispatcher.h"
+#include "url/gurl.h"
+
+namespace content {
+
+// These methods are used to pack and unpack the page_url/storage_area_id into
+// source strings to/from the browser.
+std::string PackSource(const GURL& page_url,
+ const std::string& storage_area_id) {
+ return page_url.spec() + "\n" + storage_area_id;
+}
+
+void UnpackSource(const mojo::String& source,
+ GURL* page_url,
+ std::string* storage_area_id) {
+ std::vector<std::string> result = base::SplitString(
+ source.To<std::string>(), "\n", base::KEEP_WHITESPACE,
+ base::SPLIT_WANT_ALL);
+ DCHECK_EQ(result.size(), 2u);
+ *page_url = GURL(result[0]);
+ *storage_area_id = result[1];
+}
+
+LocalStorageCachedArea::LocalStorageCachedArea(
+ const url::Origin& origin,
+ mojom::StoragePartitionService* storage_partition_service,
+ LocalStorageCachedAreas* cached_areas)
+ : origin_(origin), binding_(this),
+ cached_areas_(cached_areas), weak_factory_(this) {
+ storage_partition_service->OpenLocalStorage(
+ origin_, binding_.CreateInterfacePtrAndBind(), mojo::GetProxy(&leveldb_));
+}
+
+LocalStorageCachedArea::~LocalStorageCachedArea() {
+ cached_areas_->CacheAreaClosed(this);
+}
+
+unsigned LocalStorageCachedArea::GetLength() {
+ EnsureLoaded();
+ return map_->Length();
+}
+
+base::NullableString16 LocalStorageCachedArea::GetKey(unsigned index) {
+ EnsureLoaded();
+ return map_->Key(index);
+}
+
+base::NullableString16 LocalStorageCachedArea::GetItem(
+ const base::string16& key) {
+ EnsureLoaded();
+ return map_->GetItem(key);
+}
+
+bool LocalStorageCachedArea::SetItem(const base::string16& key,
+ const base::string16& value,
+ const GURL& page_url,
+ const std::string& storage_area_id) {
+ // A quick check to reject obviously overbudget items to avoid priming the
+ // cache.
+ if (key.length() + value.length() > kPerStorageAreaQuota)
+ return false;
+
+ EnsureLoaded();
+ base::NullableString16 unused;
+ if (!map_->SetItem(key, value, &unused))
+ return false;
+
+ // Ignore mutations to |key| until OnSetItemComplete.
+ ignore_key_mutations_[key]++;
+ leveldb_->Put(mojo::Array<uint8_t>::From(key),
+ mojo::Array<uint8_t>::From(value),
+ PackSource(page_url, storage_area_id),
+ base::Bind(&LocalStorageCachedArea::OnSetItemComplete,
+ weak_factory_.GetWeakPtr(), key));
+ return true;
+}
+
+void LocalStorageCachedArea::RemoveItem(const base::string16& key,
+ const GURL& page_url,
+ const std::string& storage_area_id) {
+ EnsureLoaded();
+ base::string16 unused;
+ if (!map_->RemoveItem(key, &unused))
+ return;
+
+ // Ignore mutations to |key| until OnRemoveItemComplete.
+ ignore_key_mutations_[key]++;
+ leveldb_->Delete(mojo::Array<uint8_t>::From(key),
+ PackSource(page_url, storage_area_id),
+ base::Bind(&LocalStorageCachedArea::OnRemoveItemComplete,
+ weak_factory_.GetWeakPtr(), key));
+}
+
+void LocalStorageCachedArea::Clear(const GURL& page_url,
+ const std::string& storage_area_id) {
+ // No need to prime the cache in this case.
+
+ Reset();
+ map_ = new DOMStorageMap(kPerStorageAreaQuota);
+ ignore_all_mutations_ = true;
+ leveldb_->DeleteAll(PackSource(page_url, storage_area_id),
+ base::Bind(&LocalStorageCachedArea::OnClearComplete,
+ weak_factory_.GetWeakPtr()));
+}
+
+void LocalStorageCachedArea::AreaCreated(LocalStorageArea* area) {
+ areas_[area->id()] = area;
+}
+
+void LocalStorageCachedArea::AreaDestroyed(LocalStorageArea* area) {
+ areas_.erase(area->id());
+}
+
+void LocalStorageCachedArea::KeyAdded(mojo::Array<uint8_t> key,
+ mojo::Array<uint8_t> value,
+ const mojo::String& source) {
+ base::NullableString16 null_value;
+ KeyAddedOrChanged(std::move(key), std::move(value),
+ null_value, source);
+}
+
+void LocalStorageCachedArea::KeyChanged(mojo::Array<uint8_t> key,
+ mojo::Array<uint8_t> new_value,
+ mojo::Array<uint8_t> old_value,
+ const mojo::String& source) {
+ base::NullableString16 old_value_str(old_value.To<base::string16>(), false);
+ KeyAddedOrChanged(std::move(key), std::move(new_value),
+ old_value_str, source);
+}
+
+void LocalStorageCachedArea::KeyDeleted(mojo::Array<uint8_t> key,
+ mojo::Array<uint8_t> old_value,
+ const mojo::String& source) {
+ GURL page_url;
+ std::string storage_area_id;
+ UnpackSource(source, &page_url, &storage_area_id);
+
+ base::string16 key_string = key.To<base::string16>();
+
+ blink::WebStorageArea* originating_area = nullptr;
+ if (areas_.find(storage_area_id) != areas_.end()) {
+ // The source storage area is in this process.
+ originating_area = areas_[storage_area_id];
+ } else if (map_ && !ignore_all_mutations_) {
+ // This was from another process or the storage area is gone. If the former,
+ // remove it from our cache if we haven't already changed it and are waiting
+ // for the confirmation callback. In the latter case, we won't do anything
+ // because ignore_key_mutations_ won't be updated until the callback runs.
+ if (ignore_key_mutations_.find(key_string) != ignore_key_mutations_.end()) {
+ base::string16 unused;
+ map_->RemoveItem(key_string, &unused);
+ }
+ }
+
+ blink::WebStorageEventDispatcher::dispatchLocalStorageEvent(
+ key_string, old_value.To<base::string16>(), base::NullableString16(),
+ GURL(origin_.Serialize()), page_url, originating_area);
+}
+
+void LocalStorageCachedArea::AllDeleted(const mojo::String& source) {
+ GURL page_url;
+ std::string storage_area_id;
+ UnpackSource(source, &page_url, &storage_area_id);
+
+ blink::WebStorageArea* originating_area = nullptr;
+ if (areas_.find(storage_area_id) != areas_.end()) {
+ // The source storage area is in this process.
+ originating_area = areas_[storage_area_id];
+ } else if (map_ && !ignore_all_mutations_) {
+ scoped_refptr<DOMStorageMap> old = map_;
+ map_ = new DOMStorageMap(kPerStorageAreaQuota);
+
+ // We have to retain local additions which happened after this clear
+ // operation from another process.
+ auto iter = ignore_key_mutations_.begin();
+ while (iter != ignore_key_mutations_.end()) {
+ base::NullableString16 value = old->GetItem(iter->first);
+ if (!value.is_null()) {
+ base::NullableString16 unused;
+ map_->SetItem(iter->first, value.string(), &unused);
+ }
+ ++iter;
+ }
+ }
+
+ blink::WebStorageEventDispatcher::dispatchLocalStorageEvent(
+ base::NullableString16(), base::NullableString16(),
+ base::NullableString16(), GURL(origin_.Serialize()), page_url,
+ originating_area);
+}
+
+void LocalStorageCachedArea::GetAllComplete(const mojo::String& source) {
+ // Since the GetAll method is synchronous, we need this asynchronously
+ // delivered notification to avoid applying changes to the returned array
+ // that we already have.
+ if (source.To<std::string>() == get_all_request_id_) {
+ DCHECK(ignore_all_mutations_);
+ DCHECK(!get_all_request_id_.empty());
+ ignore_all_mutations_ = false;
+ get_all_request_id_.clear();
+ }
+}
+
+void LocalStorageCachedArea::KeyAddedOrChanged(
+ mojo::Array<uint8_t> key,
+ mojo::Array<uint8_t> new_value,
+ const base::NullableString16& old_value,
+ const mojo::String& source) {
+ GURL page_url;
+ std::string storage_area_id;
+ UnpackSource(source, &page_url, &storage_area_id);
+
+ base::string16 key_string = key.To<base::string16>();
+ base::string16 new_value_string = new_value.To<base::string16>();
+
+ blink::WebStorageArea* originating_area = nullptr;
+ if (areas_.find(storage_area_id) != areas_.end()) {
+ // The source storage area is in this process.
+ originating_area = areas_[storage_area_id];
+ } else if (map_ && !ignore_all_mutations_) {
+ // This was from another process or the storage area is gone. If the former,
+ // apply it to our cache if we haven't already changed it and are waiting
+ // for the confirmation callback. In the latter case, we won't do anything
+ // because ignore_key_mutations_ won't be updated until the callback runs.
+ if (ignore_key_mutations_.find(key_string) != ignore_key_mutations_.end()) {
+ // We turn off quota checking here to accomodate the over budget allowance
+ // that's provided in the browser process.
+ base::NullableString16 unused;
+ map_->set_quota(std::numeric_limits<int32_t>::max());
+ map_->SetItem(key_string, new_value_string, &unused);
+ map_->set_quota(kPerStorageAreaQuota);
+ }
+ }
+
+ blink::WebStorageEventDispatcher::dispatchLocalStorageEvent(
+ key_string, old_value, new_value_string,
+ GURL(origin_.Serialize()), page_url, originating_area);
+
+}
+
+void LocalStorageCachedArea::EnsureLoaded() {
+ if (map_)
+ return;
+
+ base::TimeTicks before = base::TimeTicks::Now();
+ ignore_all_mutations_ = true;
+ get_all_request_id_ = base::Uint64ToString(base::RandUint64());
+ leveldb::DatabaseError status = leveldb::DatabaseError::OK;
+ mojo::Array<content::mojom::KeyValuePtr> data;
+ leveldb_->GetAll(get_all_request_id_, &status, &data);
+
+ DOMStorageValuesMap values;
+ for (size_t i = 0; i < data.size(); ++i) {
+ values[data[i]->key.To<base::string16>()] =
+ base::NullableString16(data[i]->value.To<base::string16>(), false);
+ }
+
+ map_ = new DOMStorageMap(kPerStorageAreaQuota);
+ map_->SwapValues(&values);
+
+ base::TimeDelta time_to_prime = base::TimeTicks::Now() - before;
+ UMA_HISTOGRAM_TIMES("LocalStorage.MojoTimeToPrime", time_to_prime);
+
+ size_t local_storage_size_kb = map_->bytes_used() / 1024;
+ // Track localStorage size, from 0-6MB. Note that the maximum size should be
+ // 5MB, but we add some slop since we want to make sure the max size is always
+ // above what we see in practice, since histograms can't change.
+ UMA_HISTOGRAM_CUSTOM_COUNTS("LocalStorage.MojoSizeInKB",
+ local_storage_size_kb,
+ 0, 6 * 1024, 50);
+ if (local_storage_size_kb < 100) {
+ UMA_HISTOGRAM_TIMES("LocalStorage.MojoTimeToPrimeForUnder100KB",
+ time_to_prime);
+ } else if (local_storage_size_kb < 1000) {
+ UMA_HISTOGRAM_TIMES("LocalStorage.MojoTimeToPrimeFor100KBTo1MB",
+ time_to_prime);
+ } else {
+ UMA_HISTOGRAM_TIMES("LocalStorage.MojoTimeToPrimeFor1MBTo5MB",
+ time_to_prime);
+ }
+}
+
+void LocalStorageCachedArea::OnSetItemComplete(const base::string16& key,
+ bool success) {
+ if (!success) {
+ Reset();
+ return;
+ }
+
+ auto found = ignore_key_mutations_.find(key);
+ DCHECK(found != ignore_key_mutations_.end());
+ if (--found->second == 0)
+ ignore_key_mutations_.erase(found);
+}
+
+void LocalStorageCachedArea::OnRemoveItemComplete(
+ const base::string16& key, bool success) {
+ DCHECK(success);
+ auto found = ignore_key_mutations_.find(key);
+ DCHECK(found != ignore_key_mutations_.end());
+ if (--found->second == 0)
+ ignore_key_mutations_.erase(found);
+}
+
+void LocalStorageCachedArea::OnClearComplete(bool success) {
+ DCHECK(success);
+ DCHECK(ignore_all_mutations_);
+ ignore_all_mutations_ = false;
+}
+
+void LocalStorageCachedArea::Reset() {
+ map_ = NULL;
+ ignore_key_mutations_.clear();
+ ignore_all_mutations_ = false;
+ weak_factory_.InvalidateWeakPtrs();
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/dom_storage/local_storage_cached_area.h b/chromium/content/renderer/dom_storage/local_storage_cached_area.h
new file mode 100644
index 00000000000..316f4e81082
--- /dev/null
+++ b/chromium/content/renderer/dom_storage/local_storage_cached_area.h
@@ -0,0 +1,114 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_DOM_STORAGE_LOCAL_STORAGE_CACHED_AREA_H_
+#define CONTENT_RENDERER_DOM_STORAGE_LOCAL_STORAGE_CACHED_AREA_H_
+
+#include <map>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/strings/nullable_string16.h"
+#include "content/common/leveldb_wrapper.mojom.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+namespace content {
+class DOMStorageMap;
+class LocalStorageArea;
+class LocalStorageCachedAreas;
+
+namespace mojom {
+class StoragePartitionService;
+}
+
+// An in-process implementation of LocalStorage using a LevelDB Mojo service.
+// Maintains a complete cache of the origin's Map of key/value pairs for fast
+// access. The cache is primed on first access and changes are written to the
+// backend through the level db interface pointer. Mutations originating in
+// other processes are applied to the cache via mojom::LevelDBObserver
+// callbacks.
+// There is one LocalStorageCachedArea for potentially many LocalStorageArea
+// objects.
+class LocalStorageCachedArea : public mojom::LevelDBObserver,
+ public base::RefCounted<LocalStorageCachedArea> {
+ public:
+ LocalStorageCachedArea(
+ const url::Origin& origin,
+ mojom::StoragePartitionService* storage_partition_service,
+ LocalStorageCachedAreas* cached_areas);
+
+ // These correspond to blink::WebStorageArea.
+ unsigned GetLength();
+ base::NullableString16 GetKey(unsigned index);
+ base::NullableString16 GetItem(const base::string16& key);
+ bool SetItem(const base::string16& key,
+ const base::string16& value,
+ const GURL& page_url,
+ const std::string& storage_area_id);
+ void RemoveItem(const base::string16& key,
+ const GURL& page_url,
+ const std::string& storage_area_id);
+ void Clear(const GURL& page_url, const std::string& storage_area_id);
+
+ // Allow this object to keep track of the LocalStorageAreas corresponding to
+ // it, which is needed for mutation event notifications.
+ void AreaCreated(LocalStorageArea* area);
+ void AreaDestroyed(LocalStorageArea* area);
+
+ const url::Origin& origin() { return origin_; }
+
+ private:
+ friend class base::RefCounted<LocalStorageCachedArea>;
+ ~LocalStorageCachedArea() override;
+
+ // LevelDBObserver:
+ void KeyAdded(mojo::Array<uint8_t> key,
+ mojo::Array<uint8_t> value,
+ const mojo::String& source) override;
+ void KeyChanged(mojo::Array<uint8_t> key,
+ mojo::Array<uint8_t> new_value,
+ mojo::Array<uint8_t> old_value,
+ const mojo::String& source) override;
+ void KeyDeleted(mojo::Array<uint8_t> key,
+ mojo::Array<uint8_t> old_value,
+ const mojo::String& source) override;
+ void AllDeleted(const mojo::String& source) override;
+ void GetAllComplete(const mojo::String& source) override;
+
+ // Common helper for KeyAdded() and KeyChanged()
+ void KeyAddedOrChanged(mojo::Array<uint8_t> key,
+ mojo::Array<uint8_t> new_value,
+ const base::NullableString16& old_value,
+ const mojo::String& source);
+
+ // Synchronously fetches the origin's local storage data if it hasn't been
+ // fetched already.
+ void EnsureLoaded();
+
+ void OnSetItemComplete(const base::string16& key, bool success);
+ void OnRemoveItemComplete(const base::string16& key, bool success);
+ void OnClearComplete(bool success);
+
+ // Resets the object back to its newly constructed state.
+ void Reset();
+
+ url::Origin origin_;
+ scoped_refptr<DOMStorageMap> map_;
+ std::map<base::string16, int> ignore_key_mutations_;
+ bool ignore_all_mutations_ = false;
+ std::string get_all_request_id_;
+ mojom::LevelDBWrapperPtr leveldb_;
+ mojo::Binding<mojom::LevelDBObserver> binding_;
+ LocalStorageCachedAreas* cached_areas_;
+ std::map<std::string, LocalStorageArea*> areas_;
+ base::WeakPtrFactory<LocalStorageCachedArea> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(LocalStorageCachedArea);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_DOM_STORAGE_LOCAL_STORAGE_CACHED_AREA_H_
diff --git a/chromium/content/renderer/dom_storage/local_storage_cached_areas.cc b/chromium/content/renderer/dom_storage/local_storage_cached_areas.cc
new file mode 100644
index 00000000000..a9d89455fd1
--- /dev/null
+++ b/chromium/content/renderer/dom_storage/local_storage_cached_areas.cc
@@ -0,0 +1,34 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/dom_storage/local_storage_cached_areas.h"
+
+#include "content/renderer/dom_storage/local_storage_cached_area.h"
+
+namespace content {
+
+LocalStorageCachedAreas::LocalStorageCachedAreas(
+ mojom::StoragePartitionService* storage_partition_service)
+ : storage_partition_service_(storage_partition_service) {}
+
+LocalStorageCachedAreas::~LocalStorageCachedAreas() {
+}
+
+scoped_refptr<LocalStorageCachedArea> LocalStorageCachedAreas::GetCachedArea(
+ const url::Origin& origin) {
+ if (cached_areas_.find(origin) == cached_areas_.end()) {
+ cached_areas_[origin] = new LocalStorageCachedArea(
+ origin, storage_partition_service_, this);
+ }
+
+ return make_scoped_refptr(cached_areas_[origin]);
+}
+
+void LocalStorageCachedAreas::CacheAreaClosed(
+ LocalStorageCachedArea* cached_area) {
+ DCHECK(cached_areas_.find(cached_area->origin()) != cached_areas_.end());
+ cached_areas_.erase(cached_area->origin());
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/dom_storage/local_storage_cached_areas.h b/chromium/content/renderer/dom_storage/local_storage_cached_areas.h
new file mode 100644
index 00000000000..662d36910ae
--- /dev/null
+++ b/chromium/content/renderer/dom_storage/local_storage_cached_areas.h
@@ -0,0 +1,50 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_DOM_STORAGE_LOCAL_STORAGE_CACHED_AREAS_H_
+#define CONTENT_RENDERER_DOM_STORAGE_LOCAL_STORAGE_CACHED_AREAS_H_
+
+#include <map>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "url/origin.h"
+
+namespace content {
+class LocalStorageCachedArea;
+
+namespace mojom {
+class StoragePartitionService;
+}
+
+// Keeps a map of all the LocalStorageCachedArea objects in a renderer. This is
+// needed because we can have n LocalStorageArea objects for the same origin but
+// we want just one LocalStorageCachedArea to service them (no point in having
+// multiple caches of the same data in the same process).
+class LocalStorageCachedAreas {
+ public:
+ explicit LocalStorageCachedAreas(
+ mojom::StoragePartitionService* storage_partition_service);
+ ~LocalStorageCachedAreas();
+
+ // Returns, creating if necessary, a cached storage area for the given origin.
+ scoped_refptr<LocalStorageCachedArea>
+ GetCachedArea(const url::Origin& origin);
+
+ // Called by LocalStorageCachedArea on destruction.
+ void CacheAreaClosed(LocalStorageCachedArea* cached_area);
+
+ private:
+ mojom::StoragePartitionService* const storage_partition_service_;
+
+ // Maps from an origin to its LocalStorageCachedArea object. The object owns
+ // itself.
+ std::map<url::Origin, LocalStorageCachedArea*> cached_areas_;
+
+ DISALLOW_COPY_AND_ASSIGN(LocalStorageCachedAreas);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_DOM_STORAGE_LOCAL_STORAGE_CACHED_AREAS_H_
diff --git a/chromium/content/renderer/dom_storage/local_storage_namespace.cc b/chromium/content/renderer/dom_storage/local_storage_namespace.cc
new file mode 100644
index 00000000000..7ccb8bf9c5a
--- /dev/null
+++ b/chromium/content/renderer/dom_storage/local_storage_namespace.cc
@@ -0,0 +1,40 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/dom_storage/local_storage_namespace.h"
+
+#include "content/renderer/dom_storage/local_storage_area.h"
+#include "content/renderer/dom_storage/local_storage_cached_areas.h"
+#include "third_party/WebKit/public/platform/URLConversion.h"
+#include "third_party/WebKit/public/platform/WebURL.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+using blink::WebStorageArea;
+using blink::WebStorageNamespace;
+using blink::WebString;
+
+namespace content {
+
+LocalStorageNamespace::LocalStorageNamespace(
+ LocalStorageCachedAreas* local_storage_cached_areas)
+ : local_storage_cached_areas_(local_storage_cached_areas) {
+}
+
+LocalStorageNamespace::~LocalStorageNamespace() {
+}
+
+WebStorageArea* LocalStorageNamespace::createStorageArea(
+ const WebString& origin) {
+ return new LocalStorageArea(local_storage_cached_areas_->GetCachedArea(
+ url::Origin(blink::WebStringToGURL(origin))));
+}
+
+bool LocalStorageNamespace::isSameNamespace(
+ const WebStorageNamespace& other) const {
+ NOTREACHED() << "This method should only be called for session storage.";
+ return false;
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/dom_storage/local_storage_namespace.h b/chromium/content/renderer/dom_storage/local_storage_namespace.h
new file mode 100644
index 00000000000..08045c57481
--- /dev/null
+++ b/chromium/content/renderer/dom_storage/local_storage_namespace.h
@@ -0,0 +1,34 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_DOM_STORAGE_LOCAL_STORAGE_NAMESPACE_H_
+#define CONTENT_RENDERER_DOM_STORAGE_LOCAL_STORAGE_NAMESPACE_H_
+
+#include "base/macros.h"
+#include "third_party/WebKit/public/platform/WebStorageNamespace.h"
+
+namespace content {
+class LocalStorageCachedAreas;
+
+class LocalStorageNamespace : public blink::WebStorageNamespace {
+ public:
+ // |local_storage_cached_areas| is guaranteed to outlive this object.
+ explicit LocalStorageNamespace(
+ LocalStorageCachedAreas* local_storage_cached_areas);
+ ~LocalStorageNamespace() override;
+
+ // blink::WebStorageNamespace:
+ blink::WebStorageArea* createStorageArea(
+ const blink::WebString& origin) override;
+ bool isSameNamespace(const WebStorageNamespace&) const override;
+
+ private:
+ LocalStorageCachedAreas* const local_storage_cached_areas_;
+
+ DISALLOW_COPY_AND_ASSIGN(LocalStorageNamespace);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_DOM_STORAGE_LOCAL_STORAGE_NAMESPACE_H_
diff --git a/chromium/content/renderer/dom_storage/webstoragearea_impl.cc b/chromium/content/renderer/dom_storage/webstoragearea_impl.cc
index dd20bece433..1c12a80549a 100644
--- a/chromium/content/renderer/dom_storage/webstoragearea_impl.cc
+++ b/chromium/content/renderer/dom_storage/webstoragearea_impl.cc
@@ -76,8 +76,4 @@ void WebStorageAreaImpl::clear(const WebURL& page_url) {
cached_area_->Clear(connection_id_, page_url);
}
-size_t WebStorageAreaImpl::memoryBytesUsedByCache() const {
- return cached_area_->MemoryBytesUsedByCache();
-}
-
} // namespace content
diff --git a/chromium/content/renderer/dom_storage/webstoragearea_impl.h b/chromium/content/renderer/dom_storage/webstoragearea_impl.h
index 310250b7fd7..3276ff87db9 100644
--- a/chromium/content/renderer/dom_storage/webstoragearea_impl.h
+++ b/chromium/content/renderer/dom_storage/webstoragearea_impl.h
@@ -36,7 +36,6 @@ class WebStorageAreaImpl : public blink::WebStorageArea {
void removeItem(const blink::WebString& key,
const blink::WebURL& page_url) override;
void clear(const blink::WebURL& url) override;
- size_t memoryBytesUsedByCache() const override;
private:
int connection_id_;
diff --git a/chromium/content/renderer/dom_storage/webstoragenamespace_impl.cc b/chromium/content/renderer/dom_storage/webstoragenamespace_impl.cc
index 4c86057d75c..e87a857d8f7 100644
--- a/chromium/content/renderer/dom_storage/webstoragenamespace_impl.cc
+++ b/chromium/content/renderer/dom_storage/webstoragenamespace_impl.cc
@@ -7,6 +7,7 @@
#include "base/logging.h"
#include "content/common/dom_storage/dom_storage_types.h"
#include "content/renderer/dom_storage/webstoragearea_impl.h"
+#include "third_party/WebKit/public/platform/URLConversion.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "url/gurl.h"
@@ -30,7 +31,7 @@ WebStorageNamespaceImpl::~WebStorageNamespaceImpl() {
WebStorageArea* WebStorageNamespaceImpl::createStorageArea(
const WebString& origin) {
- return new WebStorageAreaImpl(namespace_id_, GURL(origin));
+ return new WebStorageAreaImpl(namespace_id_, blink::WebStringToGURL(origin));
}
WebStorageNamespace* WebStorageNamespaceImpl::copy() {
diff --git a/chromium/content/renderer/drop_data_builder.cc b/chromium/content/renderer/drop_data_builder.cc
index beb98b6dec2..1016bcffe5b 100644
--- a/chromium/content/renderer/drop_data_builder.cc
+++ b/chromium/content/renderer/drop_data_builder.cc
@@ -8,6 +8,8 @@
#include "base/strings/string_util.h"
#include "content/public/common/drop_data.h"
+#include "third_party/WebKit/public/platform/FilePathConversion.h"
+#include "third_party/WebKit/public/platform/URLConversion.h"
#include "third_party/WebKit/public/platform/WebDragData.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebVector.h"
@@ -34,7 +36,7 @@ DropData DropDataBuilder::Build(const WebDragData& drag_data) {
break;
}
if (base::EqualsASCII(str_type, ui::Clipboard::kMimeTypeURIList)) {
- result.url = GURL(item.stringData);
+ result.url = blink::WebStringToGURL(item.stringData);
result.url_title = item.title;
break;
}
@@ -59,8 +61,8 @@ DropData DropDataBuilder::Build(const WebDragData& drag_data) {
case WebDragData::Item::StorageTypeFilename:
// TODO(varunjain): This only works on chromeos. Support win/mac/gtk.
result.filenames.push_back(ui::FileInfo(
- base::FilePath::FromUTF16Unsafe(item.filenameData),
- base::FilePath::FromUTF16Unsafe(item.displayNameData)));
+ blink::WebStringToFilePath(item.filenameData),
+ blink::WebStringToFilePath(item.displayNameData)));
break;
case WebDragData::Item::StorageTypeFileSystemFile: {
DropData::FileSystemFileInfo info;
diff --git a/chromium/content/renderer/external_popup_menu_browsertest.cc b/chromium/content/renderer/external_popup_menu_browsertest.cc
index d7f93124a29..ea6054b92d3 100644
--- a/chromium/content/renderer/external_popup_menu_browsertest.cc
+++ b/chromium/content/renderer/external_popup_menu_browsertest.cc
@@ -58,8 +58,8 @@ class ExternalPopupMenuTest : public RenderViewTest {
LoadHTML(html.c_str());
// Set a minimum size and give focus so simulated events work.
- view()->webwidget()->resize(blink::WebSize(500, 500));
- view()->webwidget()->setFocus(true);
+ view()->GetWidget()->webwidget()->resize(blink::WebSize(500, 500));
+ view()->GetWidget()->webwidget()->setFocus(true);
}
int GetSelectedIndex() {
@@ -174,8 +174,8 @@ class ExternalPopupMenuDisplayNoneTest : public ExternalPopupMenuTest {
LoadHTML(html.c_str());
// Set a minimum size and give focus so simulated events work.
- view()->webwidget()->resize(blink::WebSize(500, 500));
- view()->webwidget()->setFocus(true);
+ view()->GetWidget()->webwidget()->resize(blink::WebSize(500, 500));
+ view()->GetWidget()->webwidget()->setFocus(true);
}
};
diff --git a/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc b/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc
index fa88aa9e711..d97dbe23377 100644
--- a/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc
+++ b/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.cc
@@ -26,7 +26,7 @@ MultiResolutionImageResourceFetcher::MultiResolutionImageResourceFetcher(
WebFrame* frame,
int id,
WebURLRequest::RequestContext request_context,
- blink::WebURLRequest::CachePolicy cache_policy,
+ blink::WebCachePolicy cache_policy,
const Callback& callback)
: callback_(callback),
id_(id),
diff --git a/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.h b/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.h
index 0b8671e6d14..4d132ce8f84 100644
--- a/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.h
+++ b/chromium/content/renderer/fetchers/multi_resolution_image_resource_fetcher.h
@@ -19,6 +19,7 @@ class SkBitmap;
namespace blink {
class WebFrame;
class WebURLResponse;
+enum class WebCachePolicy;
}
namespace content {
@@ -37,7 +38,7 @@ class MultiResolutionImageResourceFetcher {
blink::WebFrame* frame,
int id,
blink::WebURLRequest::RequestContext request_context,
- blink::WebURLRequest::CachePolicy cache_policy,
+ blink::WebCachePolicy cache_policy,
const Callback& callback);
virtual ~MultiResolutionImageResourceFetcher();
diff --git a/chromium/content/renderer/fetchers/resource_fetcher_impl.cc b/chromium/content/renderer/fetchers/resource_fetcher_impl.cc
index b48ad21d89d..fa58f999c84 100644
--- a/chromium/content/renderer/fetchers/resource_fetcher_impl.cc
+++ b/chromium/content/renderer/fetchers/resource_fetcher_impl.cc
@@ -76,8 +76,7 @@ void ResourceFetcherImpl::SetSkipServiceWorker(bool skip_service_worker) {
request_.setSkipServiceWorker(skip_service_worker);
}
-void ResourceFetcherImpl::SetCachePolicy(
- blink::WebURLRequest::CachePolicy policy) {
+void ResourceFetcherImpl::SetCachePolicy(blink::WebCachePolicy policy) {
DCHECK(!request_.isNull());
DCHECK(!loader_);
diff --git a/chromium/content/renderer/fetchers/resource_fetcher_impl.h b/chromium/content/renderer/fetchers/resource_fetcher_impl.h
index e260b098172..d1f190701d1 100644
--- a/chromium/content/renderer/fetchers/resource_fetcher_impl.h
+++ b/chromium/content/renderer/fetchers/resource_fetcher_impl.h
@@ -23,6 +23,7 @@ class GURL;
namespace blink {
class WebFrame;
class WebURLLoader;
+enum class WebCachePolicy;
}
namespace content {
@@ -35,7 +36,7 @@ class ResourceFetcherImpl : public ResourceFetcher,
void SetBody(const std::string& body) override;
void SetHeader(const std::string& header, const std::string& value) override;
void SetSkipServiceWorker(bool skip_service_worker) override;
- void SetCachePolicy(blink::WebURLRequest::CachePolicy policy) override;
+ void SetCachePolicy(blink::WebCachePolicy policy) override;
void SetLoaderOptions(const blink::WebURLLoaderOptions& options) override;
void Start(blink::WebFrame* frame,
blink::WebURLRequest::RequestContext request_context,
diff --git a/chromium/content/renderer/frame_blame_context.cc b/chromium/content/renderer/frame_blame_context.cc
new file mode 100644
index 00000000000..74ed6ee2b25
--- /dev/null
+++ b/chromium/content/renderer/frame_blame_context.cc
@@ -0,0 +1,41 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/frame_blame_context.h"
+
+#include "base/trace_event/trace_event_argument.h"
+#include "content/renderer/render_frame_impl.h"
+#include "content/renderer/top_level_blame_context.h"
+#include "third_party/WebKit/public/platform/Platform.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
+
+namespace content {
+namespace {
+
+base::trace_event::BlameContext* GetParentBlameContext(
+ RenderFrameImpl* parent_frame) {
+ if (parent_frame)
+ return parent_frame->frameBlameContext();
+ return blink::Platform::current()->topLevelBlameContext();
+}
+
+} // namespace
+
+const char kFrameBlameContextCategory[] = "blink";
+const char kFrameBlameContextName[] = "FrameBlameContext";
+const char kFrameBlameContextType[] = "Frame";
+const char kFrameBlameContextScope[] = "RenderFrame";
+
+FrameBlameContext::FrameBlameContext(RenderFrameImpl* render_frame,
+ RenderFrameImpl* parent_frame)
+ : base::trace_event::BlameContext(kFrameBlameContextCategory,
+ kFrameBlameContextName,
+ kFrameBlameContextType,
+ kFrameBlameContextScope,
+ render_frame->GetRoutingID(),
+ GetParentBlameContext(parent_frame)) {}
+
+FrameBlameContext::~FrameBlameContext() {}
+
+} // namespace content
diff --git a/chromium/content/renderer/frame_blame_context.h b/chromium/content/renderer/frame_blame_context.h
new file mode 100644
index 00000000000..5e4d3dcbd5a
--- /dev/null
+++ b/chromium/content/renderer/frame_blame_context.h
@@ -0,0 +1,26 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_FRAME_BLAME_CONTEXT_H_
+#define CONTENT_RENDERER_FRAME_BLAME_CONTEXT_H_
+
+#include "base/trace_event/blame_context.h"
+
+namespace content {
+
+class RenderFrameImpl;
+class RenderThreadBlameContext;
+
+// A blame context which represents a single render frame.
+class FrameBlameContext : public base::trace_event::BlameContext {
+ public:
+ FrameBlameContext(RenderFrameImpl* frame, RenderFrameImpl* parent_frame);
+ ~FrameBlameContext() override;
+
+ DISALLOW_COPY_AND_ASSIGN(FrameBlameContext);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_FRAME_BLAME_CONTEXT_H_
diff --git a/chromium/content/renderer/geolocation_dispatcher.cc b/chromium/content/renderer/geolocation_dispatcher.cc
index 9f54473664f..083927fce88 100644
--- a/chromium/content/renderer/geolocation_dispatcher.cc
+++ b/chromium/content/renderer/geolocation_dispatcher.cc
@@ -12,7 +12,6 @@
#include "third_party/WebKit/public/web/WebGeolocationClient.h"
#include "third_party/WebKit/public/web/WebGeolocationPosition.h"
#include "third_party/WebKit/public/web/WebGeolocationError.h"
-#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
using blink::WebGeolocationController;
using blink::WebGeolocationError;
@@ -81,12 +80,10 @@ void GeolocationDispatcher::requestPermission(
int permission_request_id = pending_permissions_->add(permissionRequest);
permission_service_->RequestPermission(
- PERMISSION_NAME_GEOLOCATION,
- permissionRequest.securityOrigin().toString().utf8(),
- blink::WebUserGestureIndicator::isProcessingUserGesture(),
+ blink::mojom::PermissionName::GEOLOCATION,
+ permissionRequest.getSecurityOrigin().toString().utf8(),
base::Bind(&GeolocationDispatcher::OnPermissionSet,
- base::Unretained(this),
- permission_request_id));
+ base::Unretained(this), permission_request_id));
}
void GeolocationDispatcher::cancelPermissionRequest(
@@ -98,12 +95,13 @@ void GeolocationDispatcher::cancelPermissionRequest(
// Permission for using geolocation has been set.
void GeolocationDispatcher::OnPermissionSet(
int permission_request_id,
- PermissionStatus status) {
+ blink::mojom::PermissionStatus status) {
WebGeolocationPermissionRequest permissionRequest;
if (!pending_permissions_->remove(permission_request_id, permissionRequest))
return;
- permissionRequest.setIsAllowed(status == PERMISSION_STATUS_GRANTED);
+ permissionRequest.setIsAllowed(status ==
+ blink::mojom::PermissionStatus::GRANTED);
}
void GeolocationDispatcher::QueryNextPosition() {
@@ -113,7 +111,8 @@ void GeolocationDispatcher::QueryNextPosition() {
base::Unretained(this)));
}
-void GeolocationDispatcher::OnPositionUpdate(MojoGeopositionPtr geoposition) {
+void GeolocationDispatcher::OnPositionUpdate(
+ blink::mojom::GeopositionPtr geoposition) {
QueryNextPosition();
if (geoposition->valid) {
@@ -134,10 +133,10 @@ void GeolocationDispatcher::OnPositionUpdate(MojoGeopositionPtr geoposition) {
} else {
WebGeolocationError::Error code;
switch (geoposition->error_code) {
- case Geoposition::ERROR_CODE_PERMISSION_DENIED:
+ case blink::mojom::Geoposition::ErrorCode::PERMISSION_DENIED:
code = WebGeolocationError::ErrorPermissionDenied;
break;
- case Geoposition::ERROR_CODE_POSITION_UNAVAILABLE:
+ case blink::mojom::Geoposition::ErrorCode::POSITION_UNAVAILABLE:
code = WebGeolocationError::ErrorPositionUnavailable;
break;
default:
diff --git a/chromium/content/renderer/geolocation_dispatcher.h b/chromium/content/renderer/geolocation_dispatcher.h
index 705ff9f330c..71766be04a0 100644
--- a/chromium/content/renderer/geolocation_dispatcher.h
+++ b/chromium/content/renderer/geolocation_dispatcher.h
@@ -6,9 +6,9 @@
#define CONTENT_RENDERER_GEOLOCATION_DISPATCHER_H_
#include "base/memory/scoped_ptr.h"
-#include "content/common/geolocation_service.mojom.h"
-#include "content/common/permission_service.mojom.h"
#include "content/public/renderer/render_frame_observer.h"
+#include "third_party/WebKit/public/platform/modules/geolocation/geolocation.mojom.h"
+#include "third_party/WebKit/public/platform/modules/permissions/permission.mojom.h"
#include "third_party/WebKit/public/web/WebGeolocationClient.h"
#include "third_party/WebKit/public/web/WebGeolocationController.h"
@@ -45,18 +45,19 @@ class GeolocationDispatcher
const blink::WebGeolocationPermissionRequest& permissionRequest) override;
void QueryNextPosition();
- void OnPositionUpdate(MojoGeopositionPtr geoposition);
+ void OnPositionUpdate(blink::mojom::GeopositionPtr geoposition);
// Permission for using geolocation has been set.
- void OnPermissionSet(int permission_request_id, PermissionStatus status);
+ void OnPermissionSet(int permission_request_id,
+ blink::mojom::PermissionStatus status);
scoped_ptr<blink::WebGeolocationController> controller_;
scoped_ptr<blink::WebGeolocationPermissionRequestManager>
pending_permissions_;
- GeolocationServicePtr geolocation_service_;
+ blink::mojom::GeolocationServicePtr geolocation_service_;
bool enable_high_accuracy_;
- PermissionServicePtr permission_service_;
+ blink::mojom::PermissionServicePtr permission_service_;
};
} // namespace content
diff --git a/chromium/content/renderer/gpu/compositor_dependencies.h b/chromium/content/renderer/gpu/compositor_dependencies.h
index fd46a1106e8..3f82883dff0 100644
--- a/chromium/content/renderer/gpu/compositor_dependencies.h
+++ b/chromium/content/renderer/gpu/compositor_dependencies.h
@@ -17,6 +17,7 @@ class SingleThreadTaskRunner;
namespace cc {
class BeginFrameSource;
class ContextProvider;
+class ImageSerializationProcessor;
class SharedBitmapManager;
class TaskGraphRunner;
}
@@ -55,6 +56,7 @@ class CompositorDependencies {
virtual cc::ContextProvider* GetSharedMainThreadContextProvider() = 0;
virtual scoped_ptr<cc::BeginFrameSource> CreateExternalBeginFrameSource(
int routing_id) = 0;
+ virtual cc::ImageSerializationProcessor* GetImageSerializationProcessor() = 0;
virtual cc::TaskGraphRunner* GetTaskGraphRunner() = 0;
virtual bool AreImageDecodeTasksEnabled() = 0;
virtual bool IsThreadedAnimationEnabled() = 0;
diff --git a/chromium/content/renderer/gpu/compositor_external_begin_frame_source.cc b/chromium/content/renderer/gpu/compositor_external_begin_frame_source.cc
index ae18568e04e..aa4a456ac29 100644
--- a/chromium/content/renderer/gpu/compositor_external_begin_frame_source.cc
+++ b/chromium/content/renderer/gpu/compositor_external_begin_frame_source.cc
@@ -32,15 +32,33 @@ CompositorExternalBeginFrameSource::~CompositorExternalBeginFrameSource() {
}
}
-void CompositorExternalBeginFrameSource::OnNeedsBeginFramesChange(
+void CompositorExternalBeginFrameSource::OnNeedsBeginFramesChanged(
bool needs_begin_frames) {
DCHECK(CalledOnValidThread());
+ if (!needs_begin_frames)
+ missed_begin_frame_args_ = cc::BeginFrameArgs();
Send(new ViewHostMsg_SetNeedsBeginFrames(routing_id_, needs_begin_frames));
}
+void CompositorExternalBeginFrameSource::AddObserver(
+ cc::BeginFrameObserver* obs) {
+ DCHECK(CalledOnValidThread());
+ SetClientReady();
+ BeginFrameSourceBase::AddObserver(obs);
+ // Send a MISSED begin frame if necessary.
+ if (missed_begin_frame_args_.IsValid()) {
+ cc::BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs();
+ if (!last_args.IsValid() ||
+ (missed_begin_frame_args_.frame_time > last_args.frame_time)) {
+ obs->OnBeginFrame(missed_begin_frame_args_);
+ }
+ }
+}
+
void CompositorExternalBeginFrameSource::SetClientReady() {
DCHECK(CalledOnValidThread());
- DCHECK(!begin_frame_source_proxy_.get());
+ if (begin_frame_source_proxy_)
+ return;
begin_frame_source_proxy_ =
new CompositorExternalBeginFrameSourceProxy(this);
begin_frame_source_filter_handler_ = base::Bind(
@@ -57,12 +75,14 @@ void CompositorExternalBeginFrameSource::OnMessageReceived(
DCHECK(begin_frame_source_proxy_.get());
IPC_BEGIN_MESSAGE_MAP(CompositorExternalBeginFrameSource, message)
IPC_MESSAGE_HANDLER(ViewMsg_BeginFrame, OnBeginFrame)
- IPC_END_MESSAGE_MAP();
+ IPC_END_MESSAGE_MAP()
}
void CompositorExternalBeginFrameSource::OnBeginFrame(
const cc::BeginFrameArgs& args) {
DCHECK(CalledOnValidThread());
+ missed_begin_frame_args_ = args;
+ missed_begin_frame_args_.type = cc::BeginFrameArgs::MISSED;
CallOnBeginFrame(args);
}
diff --git a/chromium/content/renderer/gpu/compositor_external_begin_frame_source.h b/chromium/content/renderer/gpu/compositor_external_begin_frame_source.h
index d555832eb52..116529a229f 100644
--- a/chromium/content/renderer/gpu/compositor_external_begin_frame_source.h
+++ b/chromium/content/renderer/gpu/compositor_external_begin_frame_source.h
@@ -31,8 +31,8 @@ class CompositorExternalBeginFrameSource
~CompositorExternalBeginFrameSource() override;
// cc::BeginFrameSourceBase implementation.
- void OnNeedsBeginFramesChange(bool needs_begin_frames) override;
- void SetClientReady() override;
+ void AddObserver(cc::BeginFrameObserver* obs) override;
+ void OnNeedsBeginFramesChanged(bool needs_begin_frames) override;
private:
class CompositorExternalBeginFrameSourceProxy
@@ -58,6 +58,7 @@ class CompositorExternalBeginFrameSource
DISALLOW_COPY_AND_ASSIGN(CompositorExternalBeginFrameSourceProxy);
};
+ void SetClientReady();
void OnMessageReceived(const IPC::Message& message);
void OnBeginFrame(const cc::BeginFrameArgs& args);
@@ -69,6 +70,7 @@ class CompositorExternalBeginFrameSource
scoped_refptr<IPC::SyncMessageFilter> message_sender_;
int routing_id_;
CompositorForwardingMessageFilter::Handler begin_frame_source_filter_handler_;
+ cc::BeginFrameArgs missed_begin_frame_args_;
DISALLOW_COPY_AND_ASSIGN(CompositorExternalBeginFrameSource);
};
diff --git a/chromium/content/renderer/gpu/compositor_output_surface.cc b/chromium/content/renderer/gpu/compositor_output_surface.cc
index 8210e688180..72e0d0148cc 100644
--- a/chromium/content/renderer/gpu/compositor_output_surface.cc
+++ b/chromium/content/renderer/gpu/compositor_output_surface.cc
@@ -15,7 +15,6 @@
#include "cc/output/compositor_frame_ack.h"
#include "cc/output/managed_memory_policy.h"
#include "cc/output/output_surface_client.h"
-#include "content/common/gpu/client/command_buffer_proxy_impl.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
#include "content/common/view_messages.h"
@@ -24,6 +23,7 @@
#include "content/renderer/render_thread_impl.h"
#include "gpu/command_buffer/client/context_support.h"
#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/ipc/client/command_buffer_proxy_impl.h"
#include "ipc/ipc_sync_channel.h"
namespace content {
@@ -33,22 +33,24 @@ CompositorOutputSurface::CompositorOutputSurface(
uint32_t output_surface_id,
const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
const scoped_refptr<ContextProviderCommandBuffer>& worker_context_provider,
+#if defined(ENABLE_VULKAN)
+ const scoped_refptr<cc::VulkanContextProvider>& vulkan_context_provider,
+#endif
scoped_ptr<cc::SoftwareOutputDevice> software_device,
scoped_refptr<FrameSwapMessageQueue> swap_frame_message_queue,
bool use_swap_compositor_frame_message)
: OutputSurface(context_provider,
worker_context_provider,
+#if defined(ENABLE_VULKAN)
+ vulkan_context_provider,
+#endif
std::move(software_device)),
output_surface_id_(output_surface_id),
use_swap_compositor_frame_message_(use_swap_compositor_frame_message),
- output_surface_filter_(RenderThreadImpl::current()
- ->compositor_message_filter()),
+ output_surface_filter_(
+ RenderThreadImpl::current()->compositor_message_filter()),
frame_swap_message_queue_(swap_frame_message_queue),
routing_id_(routing_id),
-#if defined(OS_ANDROID)
- prefers_smoothness_(false),
- main_thread_runner_(base::MessageLoop::current()->task_runner()),
-#endif
layout_test_mode_(RenderThreadImpl::current()->layout_test_mode()),
weak_ptrs_(this) {
DCHECK(output_surface_filter_.get());
@@ -86,7 +88,6 @@ bool CompositorOutputSurface::BindToClient(
void CompositorOutputSurface::DetachFromClient() {
if (!HasClient())
return;
- UpdateSmoothnessTakesPriority(false);
if (output_surface_proxy_.get())
output_surface_proxy_->ClearOutputSurface();
output_surface_filter_->RemoveHandlerOnCompositorThread(
@@ -202,32 +203,4 @@ bool CompositorOutputSurface::Send(IPC::Message* message) {
return message_sender_->Send(message);
}
-#if defined(OS_ANDROID)
-namespace {
-void SetThreadPriorityToIdle() {
- base::PlatformThread::SetCurrentThreadPriority(
- base::ThreadPriority::BACKGROUND);
-}
-void SetThreadPriorityToDefault() {
- base::PlatformThread::SetCurrentThreadPriority(base::ThreadPriority::NORMAL);
-}
-} // namespace
-#endif
-
-void CompositorOutputSurface::UpdateSmoothnessTakesPriority(
- bool prefers_smoothness) {
-#if defined(OS_ANDROID)
- if (prefers_smoothness_ == prefers_smoothness)
- return;
- prefers_smoothness_ = prefers_smoothness;
- if (prefers_smoothness) {
- main_thread_runner_->PostTask(FROM_HERE,
- base::Bind(&SetThreadPriorityToIdle));
- } else {
- main_thread_runner_->PostTask(FROM_HERE,
- base::Bind(&SetThreadPriorityToDefault));
- }
-#endif
-}
-
} // namespace content
diff --git a/chromium/content/renderer/gpu/compositor_output_surface.h b/chromium/content/renderer/gpu/compositor_output_surface.h
index cbbad42389c..97a14c0e783 100644
--- a/chromium/content/renderer/gpu/compositor_output_surface.h
+++ b/chromium/content/renderer/gpu/compositor_output_surface.h
@@ -47,6 +47,9 @@ class CompositorOutputSurface
const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
const scoped_refptr<ContextProviderCommandBuffer>&
worker_context_provider,
+#if defined(ENABLE_VULKAN)
+ const scoped_refptr<cc::VulkanContextProvider>& vulkan_context_provider,
+#endif
scoped_ptr<cc::SoftwareOutputDevice> software,
scoped_refptr<FrameSwapMessageQueue> swap_frame_message_queue,
bool use_swap_compositor_frame_message);
@@ -57,10 +60,6 @@ class CompositorOutputSurface
void DetachFromClient() override;
void SwapBuffers(cc::CompositorFrame* frame) override;
- // TODO(epenner): This seems out of place here and would be a better fit
- // int CompositorThread after it is fully refactored (http://crbug/170828)
- void UpdateSmoothnessTakesPriority(bool prefer_smoothness) override;
-
protected:
void ShortcutSwapAck(uint32_t output_surface_id,
scoped_ptr<cc::GLFrameData> gl_frame_data);
@@ -104,10 +103,6 @@ class CompositorOutputSurface
scoped_refptr<IPC::SyncMessageFilter> message_sender_;
scoped_refptr<FrameSwapMessageQueue> frame_swap_message_queue_;
int routing_id_;
-#if defined(OS_ANDROID)
- bool prefers_smoothness_;
- scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner_;
-#endif
// TODO(danakj): Remove this when crbug.com/311404
bool layout_test_mode_;
diff --git a/chromium/content/renderer/gpu/delegated_compositor_output_surface.cc b/chromium/content/renderer/gpu/delegated_compositor_output_surface.cc
index 9e8ad78af10..aff1ba5b502 100644
--- a/chromium/content/renderer/gpu/delegated_compositor_output_surface.cc
+++ b/chromium/content/renderer/gpu/delegated_compositor_output_surface.cc
@@ -12,11 +12,17 @@ DelegatedCompositorOutputSurface::DelegatedCompositorOutputSurface(
uint32_t output_surface_id,
const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
const scoped_refptr<ContextProviderCommandBuffer>& worker_context_provider,
+#if defined(ENABLE_VULKAN)
+ const scoped_refptr<cc::VulkanContextProvider>& vulkan_context_provider,
+#endif
scoped_refptr<FrameSwapMessageQueue> swap_frame_message_queue)
: CompositorOutputSurface(routing_id,
output_surface_id,
context_provider,
worker_context_provider,
+#if defined(ENABLE_VULKAN)
+ vulkan_context_provider,
+#endif
scoped_ptr<cc::SoftwareOutputDevice>(),
swap_frame_message_queue,
true) {
diff --git a/chromium/content/renderer/gpu/delegated_compositor_output_surface.h b/chromium/content/renderer/gpu/delegated_compositor_output_surface.h
index f98d60a22b7..cfa3961c235 100644
--- a/chromium/content/renderer/gpu/delegated_compositor_output_surface.h
+++ b/chromium/content/renderer/gpu/delegated_compositor_output_surface.h
@@ -21,6 +21,9 @@ class DelegatedCompositorOutputSurface : public CompositorOutputSurface {
const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
const scoped_refptr<ContextProviderCommandBuffer>&
worker_context_provider,
+#if defined(ENABLE_VULKAN)
+ const scoped_refptr<cc::VulkanContextProvider>& vulkan_context_provider,
+#endif
scoped_refptr<FrameSwapMessageQueue> swap_frame_message_queue);
~DelegatedCompositorOutputSurface() override {}
};
diff --git a/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc b/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc
index e5b67abd97d..028bdee749c 100644
--- a/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc
+++ b/chromium/content/renderer/gpu/gpu_benchmarking_extension.cc
@@ -9,17 +9,20 @@
#include <utility>
#include "base/base64.h"
+#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/macros.h"
#include "base/strings/string_number_conversions.h"
#include "cc/layers/layer.h"
+#include "content/common/child_process_messages.h"
#include "content/common/input/synthetic_gesture_params.h"
#include "content/common/input/synthetic_pinch_gesture_params.h"
#include "content/common/input/synthetic_smooth_drag_gesture_params.h"
#include "content/common/input/synthetic_smooth_scroll_gesture_params.h"
#include "content/common/input/synthetic_tap_gesture_params.h"
#include "content/public/child/v8_value_converter.h"
+#include "content/public/common/content_switches.h"
#include "content/public/renderer/chrome_object_extensions_utils.h"
#include "content/public/renderer/render_thread.h"
#include "content/renderer/gpu/render_widget_compositor.h"
@@ -29,6 +32,7 @@
#include "gin/arguments.h"
#include "gin/handle.h"
#include "gin/object_template_builder.h"
+#include "gpu/ipc/common/gpu_messages.h"
#include "third_party/WebKit/public/web/WebImageCache.h"
#include "third_party/WebKit/public/web/WebKit.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
@@ -53,19 +57,52 @@ namespace content {
namespace {
-class PNGSerializer : public SkPixelSerializer {
+class EncodingSerializer : public SkPixelSerializer {
protected:
bool onUseEncodedData(const void* data, size_t len) override { return true; }
SkData* onEncode(const SkPixmap& pixmap) override {
- SkBitmap bm;
- // The const_cast is fine, since we only read from the bitmap.
- if (bm.installPixels(pixmap.info(),
- const_cast<void*>(pixmap.addr()),
- pixmap.rowBytes())) {
- std::vector<unsigned char> vector;
- if (gfx::PNGCodec::EncodeBGRASkBitmap(bm, false, &vector)) {
+ std::vector<uint8_t> vector;
+
+ const base::CommandLine& commandLine =
+ *base::CommandLine::ForCurrentProcess();
+ if (commandLine.HasSwitch(switches::kSkipReencodingOnSKPCapture)) {
+ // In this case, we just want to store some useful information
+ // about the image to replace the missing encoded data.
+
+ // First make sure that the data does not accidentally match any
+ // image signatures.
+ vector.push_back(0xFF);
+ vector.push_back(0xFF);
+ vector.push_back(0xFF);
+ vector.push_back(0xFF);
+
+ // Save the width and height.
+ uint32_t width = pixmap.width();
+ uint32_t height = pixmap.height();
+ vector.push_back(width & 0xFF);
+ vector.push_back((width >> 8) & 0xFF);
+ vector.push_back((width >> 16) & 0xFF);
+ vector.push_back((width >> 24) & 0xFF);
+ vector.push_back(height & 0xFF);
+ vector.push_back((height >> 8) & 0xFF);
+ vector.push_back((height >> 16) & 0xFF);
+ vector.push_back((height >> 24) & 0xFF);
+
+ // Save any additional information about the bitmap that may be
+ // interesting.
+ vector.push_back(pixmap.colorType());
+ vector.push_back(pixmap.alphaType());
return SkData::NewWithCopy(&vector.front(), vector.size());
+ } else {
+ SkBitmap bm;
+ // The const_cast is fine, since we only read from the bitmap.
+ if (bm.installPixels(pixmap.info(),
+ const_cast<void*>(pixmap.addr()),
+ pixmap.rowBytes())) {
+ if (gfx::PNGCodec::EncodeBGRASkBitmap(bm, false, &vector)) {
+ return SkData::NewWithCopy(&vector.front(), vector.size());
+ }
}
}
return nullptr;
@@ -91,7 +128,7 @@ class SkPictureSerializer {
Serialize(children[i].get());
}
- skia::RefPtr<SkPicture> picture = layer->GetPicture();
+ sk_sp<SkPicture> picture = layer->GetPicture();
if (!picture)
return;
@@ -105,7 +142,7 @@ class SkPictureSerializer {
SkFILEWStream file(filepath.c_str());
DCHECK(file.isValid());
- PNGSerializer serializer;
+ EncodingSerializer serializer;
picture->serialize(&file, &serializer);
file.fsync();
}
@@ -208,7 +245,7 @@ class GpuBenchmarkingContext {
if (!init_compositor)
return true;
- compositor_ = render_view_impl_->compositor();
+ compositor_ = render_view_impl_->GetWidget()->compositor();
if (!compositor_) {
web_frame_ = NULL;
web_view_ = NULL;
@@ -360,9 +397,10 @@ bool BeginSmoothScroll(v8::Isolate* isolate,
// TODO(nduca): If the render_view_impl is destroyed while the gesture is in
// progress, we will leak the callback and context. This needs to be fixed,
// somehow.
- context.render_view_impl()->QueueSyntheticGesture(
+ context.render_view_impl()->GetWidget()->QueueSyntheticGesture(
std::move(gesture_params),
- base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
+ base::Bind(&OnSyntheticGestureCompleted,
+ base::RetainedRef(callback_and_context)));
return true;
}
@@ -402,9 +440,10 @@ bool BeginSmoothDrag(v8::Isolate* isolate,
// TODO(nduca): If the render_view_impl is destroyed while the gesture is in
// progress, we will leak the callback and context. This needs to be fixed,
// somehow.
- context.render_view_impl()->QueueSyntheticGesture(
+ context.render_view_impl()->GetWidget()->QueueSyntheticGesture(
std::move(gesture_params),
- base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
+ base::Bind(&OnSyntheticGestureCompleted,
+ base::RetainedRef(callback_and_context)));
return true;
}
@@ -456,10 +495,10 @@ gin::ObjectTemplateBuilder GpuBenchmarking::GetObjectTemplateBuilder(
.SetMethod("smoothDrag", &GpuBenchmarking::SmoothDrag)
.SetMethod("swipe", &GpuBenchmarking::Swipe)
.SetMethod("scrollBounce", &GpuBenchmarking::ScrollBounce)
- // TODO(dominikg): Remove once JS interface changes have rolled into
- // stable.
- .SetValue("newPinchInterface", true)
.SetMethod("pinchBy", &GpuBenchmarking::PinchBy)
+ .SetMethod("pageScaleFactor", &GpuBenchmarking::PageScaleFactor)
+ .SetMethod("visualViewportX", &GpuBenchmarking::VisualViewportX)
+ .SetMethod("visualViewportY", &GpuBenchmarking::VisualViewportY)
.SetMethod("visualViewportHeight", &GpuBenchmarking::VisualViewportHeight)
.SetMethod("visualViewportWidth", &GpuBenchmarking::VisualViewportWidth)
.SetMethod("tap", &GpuBenchmarking::Tap)
@@ -467,7 +506,10 @@ gin::ObjectTemplateBuilder GpuBenchmarking::GetObjectTemplateBuilder(
.SetMethod("runMicroBenchmark", &GpuBenchmarking::RunMicroBenchmark)
.SetMethod("sendMessageToMicroBenchmark",
&GpuBenchmarking::SendMessageToMicroBenchmark)
- .SetMethod("hasGpuProcess", &GpuBenchmarking::HasGpuProcess);
+ .SetMethod("hasGpuChannel", &GpuBenchmarking::HasGpuChannel)
+ .SetMethod("hasGpuProcess", &GpuBenchmarking::HasGpuProcess)
+ .SetMethod("getGpuDriverBugWorkarounds",
+ &GpuBenchmarking::GetGpuDriverBugWorkarounds);
}
void GpuBenchmarking::SetNeedsDisplayOnAllLayers() {
@@ -527,7 +569,7 @@ bool GpuBenchmarking::SmoothScrollBy(gin::Arguments* args) {
return false;
float page_scale_factor = context.web_view()->pageScaleFactor();
- blink::WebRect rect = context.render_view_impl()->windowRect();
+ blink::WebRect rect = context.render_view_impl()->GetWidget()->windowRect();
float pixels_to_scroll = 0;
v8::Local<v8::Function> callback;
@@ -597,7 +639,7 @@ bool GpuBenchmarking::Swipe(gin::Arguments* args) {
return false;
float page_scale_factor = context.web_view()->pageScaleFactor();
- blink::WebRect rect = context.render_view_impl()->windowRect();
+ blink::WebRect rect = context.render_view_impl()->GetWidget()->windowRect();
std::string direction = "up";
float pixels_to_scroll = 0;
@@ -632,7 +674,7 @@ bool GpuBenchmarking::ScrollBounce(gin::Arguments* args) {
return false;
float page_scale_factor = context.web_view()->pageScaleFactor();
- blink::WebRect rect = context.render_view_impl()->windowRect();
+ blink::WebRect rect = context.render_view_impl()->GetWidget()->windowRect();
std::string direction = "down";
float distance_length = 0;
@@ -695,9 +737,10 @@ bool GpuBenchmarking::ScrollBounce(gin::Arguments* args) {
// TODO(nduca): If the render_view_impl is destroyed while the gesture is in
// progress, we will leak the callback and context. This needs to be fixed,
// somehow.
- context.render_view_impl()->QueueSyntheticGesture(
+ context.render_view_impl()->GetWidget()->QueueSyntheticGesture(
std::move(gesture_params),
- base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
+ base::Bind(&OnSyntheticGestureCompleted,
+ base::RetainedRef(callback_and_context)));
return true;
}
@@ -725,6 +768,7 @@ bool GpuBenchmarking::PinchBy(gin::Arguments* args) {
scoped_ptr<SyntheticPinchGestureParams> gesture_params(
new SyntheticPinchGestureParams);
+ // TODO(bokan): Remove page scale here when change land in Catapult.
// Convert coordinates from CSS pixels to density independent pixels (DIPs).
float page_scale_factor = context.web_view()->pageScaleFactor();
@@ -743,13 +787,35 @@ bool GpuBenchmarking::PinchBy(gin::Arguments* args) {
// TODO(nduca): If the render_view_impl is destroyed while the gesture is in
// progress, we will leak the callback and context. This needs to be fixed,
// somehow.
- context.render_view_impl()->QueueSyntheticGesture(
+ context.render_view_impl()->GetWidget()->QueueSyntheticGesture(
std::move(gesture_params),
- base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
+ base::Bind(&OnSyntheticGestureCompleted,
+ base::RetainedRef(callback_and_context)));
return true;
}
+float GpuBenchmarking::PageScaleFactor() {
+ GpuBenchmarkingContext context;
+ if (!context.Init(false))
+ return 0.0;
+ return context.web_view()->pageScaleFactor();
+}
+
+float GpuBenchmarking::VisualViewportY() {
+ GpuBenchmarkingContext context;
+ if (!context.Init(false))
+ return 0.0;
+ return context.web_view()->visualViewportOffset().y;
+}
+
+float GpuBenchmarking::VisualViewportX() {
+ GpuBenchmarkingContext context;
+ if (!context.Init(false))
+ return 0.0;
+ return context.web_view()->visualViewportOffset().x;
+}
+
float GpuBenchmarking::VisualViewportHeight() {
GpuBenchmarkingContext context;
if (!context.Init(false))
@@ -809,9 +875,10 @@ bool GpuBenchmarking::Tap(gin::Arguments* args) {
// TODO(nduca): If the render_view_impl is destroyed while the gesture is in
// progress, we will leak the callback and context. This needs to be fixed,
// somehow.
- context.render_view_impl()->QueueSyntheticGesture(
+ context.render_view_impl()->GetWidget()->QueueSyntheticGesture(
std::move(gesture_params),
- base::Bind(&OnSyntheticGestureCompleted, callback_and_context));
+ base::Bind(&OnSyntheticGestureCompleted,
+ base::RetainedRef(callback_and_context)));
return true;
}
@@ -847,7 +914,8 @@ int GpuBenchmarking::RunMicroBenchmark(gin::Arguments* args) {
return context.compositor()->ScheduleMicroBenchmark(
name, std::move(value),
- base::Bind(&OnMicroBenchmarkCompleted, callback_and_context));
+ base::Bind(&OnMicroBenchmarkCompleted,
+ base::RetainedRef(callback_and_context)));
}
bool GpuBenchmarking::SendMessageToMicroBenchmark(
@@ -868,9 +936,33 @@ bool GpuBenchmarking::SendMessageToMicroBenchmark(
std::move(value));
}
+bool GpuBenchmarking::HasGpuChannel() {
+ gpu::GpuChannelHost* gpu_channel =
+ RenderThreadImpl::current()->GetGpuChannel();
+ return !!gpu_channel;
+}
+
bool GpuBenchmarking::HasGpuProcess() {
- GpuChannelHost* gpu_channel = RenderThreadImpl::current()->GetGpuChannel();
- return !!gpu_channel;
+ bool has_gpu_process = false;
+ if (!RenderThreadImpl::current()->Send(
+ new ChildProcessHostMsg_HasGpuProcess(&has_gpu_process)))
+ return false;
+
+ return has_gpu_process;
+}
+
+void GpuBenchmarking::GetGpuDriverBugWorkarounds(gin::Arguments* args) {
+ std::vector<std::string> gpu_driver_bug_workarounds;
+ gpu::GpuChannelHost* gpu_channel =
+ RenderThreadImpl::current()->GetGpuChannel();
+ if (!gpu_channel->Send(new GpuChannelMsg_GetDriverBugWorkArounds(
+ &gpu_driver_bug_workarounds))) {
+ return;
+ }
+
+ v8::Local<v8::Value> result;
+ if (gin::TryConvertToV8(args->isolate(), gpu_driver_bug_workarounds, &result))
+ args->Return(result);
}
} // namespace content
diff --git a/chromium/content/renderer/gpu/gpu_benchmarking_extension.h b/chromium/content/renderer/gpu/gpu_benchmarking_extension.h
index 4da04484557..19fcbcb91a0 100644
--- a/chromium/content/renderer/gpu/gpu_benchmarking_extension.h
+++ b/chromium/content/renderer/gpu/gpu_benchmarking_extension.h
@@ -48,13 +48,18 @@ class GpuBenchmarking : public gin::Wrappable<GpuBenchmarking> {
bool Swipe(gin::Arguments* args);
bool ScrollBounce(gin::Arguments* args);
bool PinchBy(gin::Arguments* args);
+ float VisualViewportX();
+ float VisualViewportY();
float VisualViewportHeight();
float VisualViewportWidth();
+ float PageScaleFactor();
bool Tap(gin::Arguments* args);
void ClearImageCache();
int RunMicroBenchmark(gin::Arguments* args);
bool SendMessageToMicroBenchmark(int id, v8::Local<v8::Object> message);
+ bool HasGpuChannel();
bool HasGpuProcess();
+ void GetGpuDriverBugWorkarounds(gin::Arguments* args);
DISALLOW_COPY_AND_ASSIGN(GpuBenchmarking);
};
diff --git a/chromium/content/renderer/gpu/mailbox_output_surface.cc b/chromium/content/renderer/gpu/mailbox_output_surface.cc
index 0b7159876bf..8ef6f29b102 100644
--- a/chromium/content/renderer/gpu/mailbox_output_surface.cc
+++ b/chromium/content/renderer/gpu/mailbox_output_surface.cc
@@ -33,6 +33,9 @@ MailboxOutputSurface::MailboxOutputSurface(
output_surface_id,
context_provider,
worker_context_provider,
+#if defined(ENABLE_VULKAN)
+ nullptr,
+#endif
nullptr,
swap_frame_message_queue,
true),
diff --git a/chromium/content/renderer/gpu/render_widget_compositor.cc b/chromium/content/renderer/gpu/render_widget_compositor.cc
index 4048e3b6ffd..5befb978652 100644
--- a/chromium/content/renderer/gpu/render_widget_compositor.cc
+++ b/chromium/content/renderer/gpu/render_widget_compositor.cc
@@ -24,7 +24,6 @@
#include "cc/animation/animation_host.h"
#include "cc/animation/animation_timeline.h"
#include "cc/base/switches.h"
-#include "cc/blink/web_compositor_animation_timeline_impl.h"
#include "cc/blink/web_layer_impl.h"
#include "cc/debug/layer_tree_debug_state.h"
#include "cc/debug/micro_benchmark.h"
@@ -44,7 +43,9 @@
#include "components/scheduler/renderer/renderer_scheduler.h"
#include "content/common/content_switches_internal.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
+#include "content/common/input/input_event_utils.h"
#include "content/public/common/content_switches.h"
+#include "content/renderer/gpu/render_widget_compositor_delegate.h"
#include "content/renderer/input/input_handler_manager.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/service/gpu_switches.h"
@@ -54,7 +55,6 @@
#include "third_party/WebKit/public/web/WebKit.h"
#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
#include "third_party/WebKit/public/web/WebSelection.h"
-#include "third_party/WebKit/public/web/WebWidget.h"
#include "ui/gl/gl_switches.h"
#include "ui/native_theme/native_theme_switches.h"
@@ -135,7 +135,7 @@ cc::LayerSelection ConvertWebSelection(const WebSelection& web_selection) {
return cc_selection;
}
-gfx::Size CalculateDefaultTileSize(RenderWidget* widget) {
+gfx::Size CalculateDefaultTileSize(float initial_device_scale_factor) {
int default_tile_size = 256;
#if defined(OS_ANDROID)
// TODO(epenner): unify this for all platforms if it
@@ -178,9 +178,9 @@ gfx::Size CalculateDefaultTileSize(RenderWidget* widget) {
if (numTiles >= 40)
default_tile_size = 512;
}
-#elif defined(OS_CHROMEOS)
+#elif defined(OS_CHROMEOS) || defined(OS_MACOSX)
// Use 512 for high DPI (dsf=2.0f) devices.
- if (widget->screen_info().deviceScaleFactor >= 2.0f)
+ if (initial_device_scale_factor >= 2.0f)
default_tile_size = 512;
#endif
@@ -205,27 +205,27 @@ static cc::TopControlsState ConvertTopControlsState(
// static
scoped_ptr<RenderWidgetCompositor> RenderWidgetCompositor::Create(
- RenderWidget* widget,
+ RenderWidgetCompositorDelegate* delegate,
+ float device_scale_factor,
CompositorDependencies* compositor_deps) {
scoped_ptr<RenderWidgetCompositor> compositor(
- new RenderWidgetCompositor(widget, compositor_deps));
- compositor->Initialize();
+ new RenderWidgetCompositor(delegate, compositor_deps));
+ compositor->Initialize(device_scale_factor);
return compositor;
}
RenderWidgetCompositor::RenderWidgetCompositor(
- RenderWidget* widget,
+ RenderWidgetCompositorDelegate* delegate,
CompositorDependencies* compositor_deps)
: num_failed_recreate_attempts_(0),
- widget_(widget),
+ delegate_(delegate),
compositor_deps_(compositor_deps),
never_visible_(false),
layout_and_paint_async_callback_(nullptr),
remote_proto_channel_receiver_(nullptr),
- weak_factory_(this) {
-}
+ weak_factory_(this) {}
-void RenderWidgetCompositor::Initialize() {
+void RenderWidgetCompositor::Initialize(float device_scale_factor) {
base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
cc::LayerTreeSettings settings;
@@ -249,15 +249,9 @@ void RenderWidgetCompositor::Initialize() {
settings.main_frame_before_activation_enabled =
cmd->HasSwitch(cc::switches::kEnableMainFrameBeforeActivation) &&
!cmd->HasSwitch(cc::switches::kDisableMainFrameBeforeActivation);
- settings.accelerated_animation_enabled =
- compositor_deps_->IsThreadedAnimationEnabled();
-
- settings.use_compositor_animation_timelines =
- !cmd->HasSwitch(switches::kDisableCompositorAnimationTimelines);
- blink::WebRuntimeFeatures::enableCompositorAnimationTimelines(
- settings.use_compositor_animation_timelines);
+ settings.use_mouse_wheel_gestures = UseGestureBasedWheelScrolling();
- settings.default_tile_size = CalculateDefaultTileSize(widget_);
+ settings.default_tile_size = CalculateDefaultTileSize(device_scale_factor);
if (cmd->HasSwitch(switches::kDefaultTileWidth)) {
int tile_width = 0;
GetSwitchValueAsInt(*cmd,
@@ -332,10 +326,6 @@ void RenderWidgetCompositor::Initialize() {
settings.top_controls_hide_threshold = hide_threshold;
}
- settings.verify_property_trees =
- cmd->HasSwitch(cc::switches::kEnablePropertyTreeVerification);
- if (cmd->HasSwitch(cc::switches::kDisableCompositorPropertyTrees))
- settings.use_property_trees = false;
settings.renderer_settings.allow_antialiasing &=
!cmd->HasSwitch(cc::switches::kDisableCompositedAntialiasing);
// The means the renderer compositor has 2 possible modes:
@@ -375,9 +365,6 @@ void RenderWidgetCompositor::Initialize() {
&settings.initial_debug_state.slow_down_raster_scale_factor);
}
- settings.strict_layer_property_change_checking =
- cmd->HasSwitch(cc::switches::kStrictLayerPropertyChangeChecking);
-
#if defined(OS_ANDROID)
DCHECK(!SynchronousCompositorFactory::GetInstance() ||
!cmd->HasSwitch(switches::kIPCSyncCompositing));
@@ -408,14 +395,16 @@ void RenderWidgetCompositor::Initialize() {
// low end, so always use default policy.
bool use_low_memory_policy =
base::SysInfo::IsLowEndDevice() && !using_synchronous_compositor;
- // RGBA_4444 textures are only enabled by default for low end devices
- // and are disabled for Android WebView as it doesn't support the format.
- settings.renderer_settings.use_rgba_4444_textures = use_low_memory_policy;
if (use_low_memory_policy) {
// On low-end we want to be very carefull about killing other
// apps. So initially we use 50% more memory to avoid flickering
// or raster-on-demand.
settings.max_memory_for_prepaint_percentage = 67;
+
+ // RGBA_4444 textures are only enabled by default for low end devices
+ // and are disabled for Android WebView as it doesn't support the format.
+ if (!cmd->HasSwitch(switches::kDisableRGBA4444Textures))
+ settings.renderer_settings.preferred_tile_format = cc::RGBA_4444;
} else {
// On other devices we have increased memory excessively to avoid
// raster-on-demand already, so now we reserve 50% _only_ to avoid
@@ -451,12 +440,16 @@ void RenderWidgetCompositor::Initialize() {
if (cmd->HasSwitch(cc::switches::kEnableBeginFrameScheduling))
settings.use_external_begin_frame_source = true;
- settings.renderer_settings.use_rgba_4444_textures |=
- cmd->HasSwitch(switches::kEnableRGBA4444Textures);
- settings.renderer_settings.use_rgba_4444_textures &=
- !cmd->HasSwitch(switches::kDisableRGBA4444Textures);
+ if (cmd->HasSwitch(switches::kEnableRGBA4444Textures) &&
+ !cmd->HasSwitch(switches::kDisableRGBA4444Textures)) {
+ settings.renderer_settings.preferred_tile_format = cc::RGBA_4444;
+ }
+
+ if (cmd->HasSwitch(cc::switches::kEnableTileCompression)) {
+ settings.renderer_settings.preferred_tile_format = cc::ETC1;
+ }
- if (widget_->for_oopif()) {
+ if (delegate_->ForOOPIF()) {
// TODO(simonhong): Apply BeginFrame scheduling for OOPIF.
// See crbug.com/471411.
settings.use_external_begin_frame_source = false;
@@ -470,6 +463,9 @@ void RenderWidgetCompositor::Initialize() {
cc::ManagedMemoryPolicy current = settings.memory_policy_;
settings.memory_policy_ = GetGpuMemoryPolicy(current);
+ settings.use_cached_picture_raster = !cmd->HasSwitch(
+ cc::switches::kDisableCachedPictureRaster);
+
scoped_refptr<base::SingleThreadTaskRunner> compositor_thread_task_runner =
compositor_deps_->GetCompositorImplThreadTaskRunner();
scoped_refptr<base::SingleThreadTaskRunner>
@@ -489,8 +485,7 @@ void RenderWidgetCompositor::Initialize() {
scoped_ptr<cc::BeginFrameSource> external_begin_frame_source;
if (settings.use_external_begin_frame_source) {
- external_begin_frame_source =
- compositor_deps_->CreateExternalBeginFrameSource(widget_->routing_id());
+ external_begin_frame_source = delegate_->CreateExternalBeginFrameSource();
}
cc::LayerTreeHost::InitParams params;
@@ -503,10 +498,9 @@ void RenderWidgetCompositor::Initialize() {
params.external_begin_frame_source = std::move(external_begin_frame_source);
if (use_remote_compositing) {
DCHECK(!compositor_thread_task_runner.get());
-
- // TODO(khushalsagar): Replace this with LayerTreeHost::CreateRemote
- // See crbug/550687.
- layer_tree_host_ = cc::LayerTreeHost::CreateSingleThreaded(this, &params);
+ params.image_serialization_processor =
+ compositor_deps_->GetImageSerializationProcessor();
+ layer_tree_host_ = cc::LayerTreeHost::CreateRemoteServer(this, &params);
} else if (compositor_thread_task_runner.get()) {
layer_tree_host_ = cc::LayerTreeHost::CreateThreaded(
compositor_thread_task_runner, &params);
@@ -608,21 +602,16 @@ void RenderWidgetCompositor::clearRootLayer() {
}
void RenderWidgetCompositor::attachCompositorAnimationTimeline(
- blink::WebCompositorAnimationTimeline* compositor_timeline) {
- DCHECK(compositor_timeline);
+ cc::AnimationTimeline* compositor_timeline) {
DCHECK(layer_tree_host_->animation_host());
- layer_tree_host_->animation_host()->AddAnimationTimeline(
- static_cast<const cc_blink::WebCompositorAnimationTimelineImpl*>(
- compositor_timeline)->animation_timeline());
+ layer_tree_host_->animation_host()->AddAnimationTimeline(compositor_timeline);
}
void RenderWidgetCompositor::detachCompositorAnimationTimeline(
- blink::WebCompositorAnimationTimeline* compositor_timeline) {
- DCHECK(compositor_timeline);
+ cc::AnimationTimeline* compositor_timeline) {
DCHECK(layer_tree_host_->animation_host());
layer_tree_host_->animation_host()->RemoveAnimationTimeline(
- static_cast<const cc_blink::WebCompositorAnimationTimelineImpl*>(
- compositor_timeline)->animation_timeline());
+ compositor_timeline);
}
void RenderWidgetCompositor::setViewportSize(
@@ -696,11 +685,6 @@ void RenderWidgetCompositor::didStopFlinging() {
layer_tree_host_->DidStopFlinging();
}
-void RenderWidgetCompositor::registerForAnimations(blink::WebLayer* layer) {
- cc::Layer* cc_layer = static_cast<cc_blink::WebLayerImpl*>(layer)->layer();
- cc_layer->RegisterForAnimations(layer_tree_host_->animation_registrar());
-}
-
void RenderWidgetCompositor::registerViewportLayers(
const blink::WebLayer* overscrollElasticityLayer,
const blink::WebLayer* pageScaleLayer,
@@ -746,6 +730,56 @@ void RenderWidgetCompositor::clearSelection() {
layer_tree_host_->RegisterSelection(empty_selection);
}
+static_assert(static_cast<cc::EventListenerClass>(
+ blink::WebEventListenerClass::TouchStartOrMove) ==
+ cc::EventListenerClass::kTouchStartOrMove,
+ "EventListenerClass and WebEventListenerClass enums must match");
+static_assert(static_cast<cc::EventListenerClass>(
+ blink::WebEventListenerClass::MouseWheel) ==
+ cc::EventListenerClass::kMouseWheel,
+ "EventListenerClass and WebEventListenerClass enums must match");
+
+static_assert(static_cast<cc::EventListenerProperties>(
+ blink::WebEventListenerProperties::Nothing) ==
+ cc::EventListenerProperties::kNone,
+ "EventListener and WebEventListener enums must match");
+static_assert(static_cast<cc::EventListenerProperties>(
+ blink::WebEventListenerProperties::Passive) ==
+ cc::EventListenerProperties::kPassive,
+ "EventListener and WebEventListener enums must match");
+static_assert(static_cast<cc::EventListenerProperties>(
+ blink::WebEventListenerProperties::Blocking) ==
+ cc::EventListenerProperties::kBlocking,
+ "EventListener and WebEventListener enums must match");
+static_assert(static_cast<cc::EventListenerProperties>(
+ blink::WebEventListenerProperties::BlockingAndPassive) ==
+ cc::EventListenerProperties::kBlockingAndPassive,
+ "EventListener and WebEventListener enums must match");
+
+void RenderWidgetCompositor::setEventListenerProperties(
+ blink::WebEventListenerClass eventClass,
+ blink::WebEventListenerProperties properties) {
+ layer_tree_host_->SetEventListenerProperties(
+ static_cast<cc::EventListenerClass>(eventClass),
+ static_cast<cc::EventListenerProperties>(properties));
+}
+
+blink::WebEventListenerProperties
+RenderWidgetCompositor::eventListenerProperties(
+ blink::WebEventListenerClass event_class) const {
+ return static_cast<blink::WebEventListenerProperties>(
+ layer_tree_host_->event_listener_properties(
+ static_cast<cc::EventListenerClass>(event_class)));
+}
+
+void RenderWidgetCompositor::setHaveScrollEventHandlers(bool has_handlers) {
+ layer_tree_host_->SetHaveScrollEventHandlers(has_handlers);
+}
+
+bool RenderWidgetCompositor::haveScrollEventHandlers() const {
+ return layer_tree_host_->have_scroll_event_handlers();
+}
+
void CompositeAndReadbackAsyncCallback(
blink::WebCompositeAndReadbackAsyncCallback* callback,
scoped_ptr<cc::CopyOutputResult> result) {
@@ -865,7 +899,7 @@ void RenderWidgetCompositor::setTopControlsShownRatio(float ratio) {
}
void RenderWidgetCompositor::WillBeginMainFrame() {
- widget_->WillBeginCompositorFrame();
+ delegate_->WillBeginCompositorFrame();
}
void RenderWidgetCompositor::DidBeginMainFrame() {
@@ -874,7 +908,7 @@ void RenderWidgetCompositor::DidBeginMainFrame() {
void RenderWidgetCompositor::BeginMainFrame(const cc::BeginFrameArgs& args) {
compositor_deps_->GetRendererScheduler()->WillBeginFrame(args);
double frame_time_sec = (args.frame_time - base::TimeTicks()).InSecondsF();
- widget_->webwidget()->beginFrame(frame_time_sec);
+ delegate_->BeginMainFrame(frame_time_sec);
}
void RenderWidgetCompositor::BeginMainFrameNotExpectedSoon() {
@@ -882,8 +916,7 @@ void RenderWidgetCompositor::BeginMainFrameNotExpectedSoon() {
}
void RenderWidgetCompositor::UpdateLayerTreeHost() {
- widget_->webwidget()->updateAllLifecyclePhases();
-
+ delegate_->UpdateVisualState();
if (temporary_copy_output_request_) {
// For WebViewImpl, this will always have a root layer. For other widgets,
// the widget may be closed before servicing this request, so ignore it.
@@ -903,24 +936,22 @@ void RenderWidgetCompositor::ApplyViewportDeltas(
const gfx::Vector2dF& elastic_overscroll_delta,
float page_scale,
float top_controls_delta) {
- widget_->webwidget()->applyViewportDeltas(
- inner_delta,
- outer_delta,
- elastic_overscroll_delta,
- page_scale,
- top_controls_delta);
+ delegate_->ApplyViewportDeltas(inner_delta, outer_delta,
+ elastic_overscroll_delta, page_scale,
+ top_controls_delta);
}
void RenderWidgetCompositor::RequestNewOutputSurface() {
// If the host is closing, then no more compositing is possible. This
// prevents shutdown races between handling the close message and
// the CreateOutputSurface task.
- if (widget_->host_closing())
+ if (delegate_->IsClosing())
return;
bool fallback =
num_failed_recreate_attempts_ >= OUTPUT_SURFACE_RETRIES_BEFORE_FALLBACK;
- scoped_ptr<cc::OutputSurface> surface(widget_->CreateOutputSurface(fallback));
+ scoped_ptr<cc::OutputSurface> surface(
+ delegate_->CreateOutputSurface(fallback));
if (!surface) {
DidFailToInitializeOutputSurface();
@@ -954,35 +985,35 @@ void RenderWidgetCompositor::WillCommit() {
void RenderWidgetCompositor::DidCommit() {
DCHECK(!temporary_copy_output_request_);
- widget_->DidCommitCompositorFrame();
+ delegate_->DidCommitCompositorFrame();
compositor_deps_->GetRendererScheduler()->DidCommitFrameToCompositor();
}
void RenderWidgetCompositor::DidCommitAndDrawFrame() {
- widget_->DidCommitAndDrawCompositorFrame();
+ delegate_->DidCommitAndDrawCompositorFrame();
}
void RenderWidgetCompositor::DidCompleteSwapBuffers() {
- widget_->DidCompleteSwapBuffers();
+ delegate_->DidCompleteSwapBuffers();
bool threaded = !!compositor_deps_->GetCompositorImplThreadTaskRunner().get();
if (!threaded)
- widget_->OnSwapBuffersComplete();
+ delegate_->OnSwapBuffersComplete();
}
void RenderWidgetCompositor::DidCompletePageScaleAnimation() {
- widget_->DidCompletePageScaleAnimation();
+ delegate_->DidCompletePageScaleAnimation();
}
-void RenderWidgetCompositor::ScheduleAnimation() {
- widget_->scheduleAnimation();
+void RenderWidgetCompositor::RequestScheduleAnimation() {
+ delegate_->RequestScheduleAnimation();
}
void RenderWidgetCompositor::DidPostSwapBuffers() {
- widget_->OnSwapBuffersPosted();
+ delegate_->OnSwapBuffersPosted();
}
void RenderWidgetCompositor::DidAbortSwapBuffers() {
- widget_->OnSwapBuffersAborted();
+ delegate_->OnSwapBuffersAborted();
}
void RenderWidgetCompositor::SetProtoReceiver(ProtoReceiver* receiver) {
@@ -995,39 +1026,14 @@ void RenderWidgetCompositor::SendCompositorProto(
size_t unsigned_size = base::checked_cast<size_t>(signed_size);
std::vector<uint8_t> serialized(unsigned_size);
proto.SerializeToArray(serialized.data(), signed_size);
- widget_->ForwardCompositorProto(serialized);
+ delegate_->ForwardCompositorProto(serialized);
}
void RenderWidgetCompositor::RecordFrameTimingEvents(
scoped_ptr<cc::FrameTimingTracker::CompositeTimingSet> composite_events,
scoped_ptr<cc::FrameTimingTracker::MainFrameTimingSet> main_frame_events) {
- for (const auto& composite_event : *composite_events ) {
- int64_t frameId = composite_event.first;
- const std::vector<cc::FrameTimingTracker::CompositeTimingEvent>& events =
- composite_event.second;
- std::vector<blink::WebFrameTimingEvent> webEvents;
- for (size_t i = 0; i < events.size(); ++i) {
- webEvents.push_back(blink::WebFrameTimingEvent(
- events[i].frame_id,
- (events[i].timestamp - base::TimeTicks()).InSecondsF()));
- }
- widget_->webwidget()->recordFrameTimingEvent(
- blink::WebWidget::CompositeEvent, frameId, webEvents);
- }
- for (const auto& main_frame_event : *main_frame_events ) {
- int64_t frameId = main_frame_event.first;
- const std::vector<cc::FrameTimingTracker::MainFrameTimingEvent>& events =
- main_frame_event.second;
- std::vector<blink::WebFrameTimingEvent> webEvents;
- for (size_t i = 0; i < events.size(); ++i) {
- webEvents.push_back(blink::WebFrameTimingEvent(
- events[i].frame_id,
- (events[i].timestamp - base::TimeTicks()).InSecondsF(),
- (events[i].end_time - base::TimeTicks()).InSecondsF()));
- }
- widget_->webwidget()->recordFrameTimingEvent(
- blink::WebWidget::RenderEvent, frameId, webEvents);
- }
+ delegate_->RecordFrameTimingEvents(std::move(composite_events),
+ std::move(main_frame_events));
}
void RenderWidgetCompositor::SetSurfaceIdNamespace(
diff --git a/chromium/content/renderer/gpu/render_widget_compositor.h b/chromium/content/renderer/gpu/render_widget_compositor.h
index 0eac7cd9739..aacbfac858c 100644
--- a/chromium/content/renderer/gpu/render_widget_compositor.h
+++ b/chromium/content/renderer/gpu/render_widget_compositor.h
@@ -42,7 +42,8 @@ class CompositorMessage;
}
namespace content {
-class RenderWidget;
+
+class RenderWidgetCompositorDelegate;
class CONTENT_EXPORT RenderWidgetCompositor
: NON_EXPORTED_BASE(public blink::WebLayerTreeView),
@@ -53,7 +54,8 @@ class CONTENT_EXPORT RenderWidgetCompositor
// Attempt to construct and initialize a compositor instance for the widget
// with the given settings. Returns NULL if initialization fails.
static scoped_ptr<RenderWidgetCompositor> Create(
- RenderWidget* widget,
+ RenderWidgetCompositorDelegate* delegate,
+ float device_scale_factor,
CompositorDependencies* compositor_deps);
~RenderWidgetCompositor() override;
@@ -97,9 +99,9 @@ class CONTENT_EXPORT RenderWidgetCompositor
void setRootLayer(const blink::WebLayer& layer) override;
void clearRootLayer() override;
void attachCompositorAnimationTimeline(
- blink::WebCompositorAnimationTimeline* compositor_timeline) override;
+ cc::AnimationTimeline* compositor_timeline) override;
void detachCompositorAnimationTimeline(
- blink::WebCompositorAnimationTimeline* compositor_timeline) override;
+ cc::AnimationTimeline* compositor_timeline) override;
void setViewportSize(const blink::WebSize& device_viewport_size) override;
virtual blink::WebFloatPoint adjustEventPointForPinchZoom(
const blink::WebFloatPoint& point) const;
@@ -124,7 +126,6 @@ class CONTENT_EXPORT RenderWidgetCompositor
void compositeAndReadbackAsync(
blink::WebCompositeAndReadbackAsyncCallback* callback) override;
void setDeferCommits(bool defer_commits) override;
- void registerForAnimations(blink::WebLayer* layer) override;
void registerViewportLayers(
const blink::WebLayer* overscrollElasticityLayer,
const blink::WebLayer* pageScaleLayer,
@@ -133,6 +134,13 @@ class CONTENT_EXPORT RenderWidgetCompositor
void clearViewportLayers() override;
void registerSelection(const blink::WebSelection& selection) override;
void clearSelection() override;
+ void setEventListenerProperties(
+ blink::WebEventListenerClass eventClass,
+ blink::WebEventListenerProperties properties) override;
+ blink::WebEventListenerProperties eventListenerProperties(
+ blink::WebEventListenerClass eventClass) const override;
+ void setHaveScrollEventHandlers(bool) override;
+ bool haveScrollEventHandlers() const override;
int layerTreeId() const override;
void setShowFPSCounter(bool show) override;
void setShowPaintRects(bool show) override;
@@ -170,7 +178,7 @@ class CONTENT_EXPORT RenderWidgetCompositor
override;
// cc::LayerTreeHostSingleThreadClient implementation.
- void ScheduleAnimation() override;
+ void RequestScheduleAnimation() override;
void DidPostSwapBuffers() override;
void DidAbortSwapBuffers() override;
@@ -184,10 +192,12 @@ class CONTENT_EXPORT RenderWidgetCompositor
};
protected:
- RenderWidgetCompositor(RenderWidget* widget,
+ friend class RenderViewImplScaleFactorTest;
+
+ RenderWidgetCompositor(RenderWidgetCompositorDelegate* delegate,
CompositorDependencies* compositor_deps);
- void Initialize();
+ void Initialize(float device_scale_factor);
cc::LayerTreeHost* layer_tree_host() { return layer_tree_host_.get(); }
private:
@@ -197,8 +207,8 @@ class CONTENT_EXPORT RenderWidgetCompositor
void SynchronouslyComposite();
int num_failed_recreate_attempts_;
- RenderWidget* widget_;
- CompositorDependencies* compositor_deps_;
+ RenderWidgetCompositorDelegate* const delegate_;
+ CompositorDependencies* const compositor_deps_;
scoped_ptr<cc::LayerTreeHost> layer_tree_host_;
bool never_visible_;
diff --git a/chromium/content/renderer/gpu/render_widget_compositor_delegate.h b/chromium/content/renderer/gpu/render_widget_compositor_delegate.h
new file mode 100644
index 00000000000..cd2d53f3939
--- /dev/null
+++ b/chromium/content/renderer/gpu/render_widget_compositor_delegate.h
@@ -0,0 +1,103 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_GPU_RENDER_WIDGET_COMPOSITOR_DELEGATE_H_
+#define CONTENT_RENDERER_GPU_RENDER_WIDGET_COMPOSITOR_DELEGATE_H_
+
+#include "cc/debug/frame_timing_tracker.h"
+
+namespace blink {
+class WebWidget;
+struct WebScreenInfo;
+}
+
+namespace cc {
+class BeginFrameSource;
+class OutputSurface;
+}
+
+namespace content {
+
+// Consumers of RenderWidgetCompositor implement this delegate in order to
+// transport compositing information across processes.
+class CONTENT_EXPORT RenderWidgetCompositorDelegate {
+ public:
+ // Report viewport related properties during a commit from the compositor
+ // thread.
+ virtual void ApplyViewportDeltas(
+ const gfx::Vector2dF& inner_delta,
+ const gfx::Vector2dF& outer_delta,
+ const gfx::Vector2dF& elastic_overscroll_delta,
+ float page_scale,
+ float top_controls_delta) = 0;
+
+ // Notifies that the compositor has issed a BeginMainFrame.
+ virtual void BeginMainFrame(double frame_time_sec) = 0;
+
+ // Requests an OutputSurface to render into.
+ virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface(bool fallback) = 0;
+
+ // Requests an external BeginFrameSource from the delegate.
+ virtual scoped_ptr<cc::BeginFrameSource> CreateExternalBeginFrameSource() = 0;
+
+ // Notifies that the draw commands for a committed frame have been issued.
+ virtual void DidCommitAndDrawCompositorFrame() = 0;
+
+ // Notifies about a compositor frame commit operation having finished.
+ virtual void DidCommitCompositorFrame() = 0;
+
+ // Called by the compositor when page scale animation completed.
+ virtual void DidCompletePageScaleAnimation() = 0;
+
+ // Notifies that the compositor has posted a swapbuffers operation to the GPU
+ // process.
+ virtual void DidCompleteSwapBuffers() = 0;
+
+ // TODO(simonhong, fsamuel): Remove this once crbug.com/471411 is resolved.
+ // Indicates whether this RenderWidgetCompositor is for an out-of-process
+ // iframe or not.
+ virtual bool ForOOPIF() const = 0;
+
+ // Called by the compositor to forward a proto that represents serialized
+ // compositor state.
+ virtual void ForwardCompositorProto(const std::vector<uint8_t>& proto) = 0;
+
+ // Indicates whether the RenderWidgetCompositor is about to close.
+ virtual bool IsClosing() const = 0;
+
+ // Called by the compositor in single-threaded mode when a swap is aborted.
+ virtual void OnSwapBuffersAborted() = 0;
+
+ // Called by the compositor in single-threaded mode when a swap completes.
+ virtual void OnSwapBuffersComplete() = 0;
+
+ // Called by the compositor in single-threaded mode when a swap is posted.
+ virtual void OnSwapBuffersPosted() = 0;
+
+ // Called by the compositor to request the delegate to record frame timing.
+ virtual void RecordFrameTimingEvents(
+ scoped_ptr<cc::FrameTimingTracker::CompositeTimingSet> composite_events,
+ scoped_ptr<cc::FrameTimingTracker::MainFrameTimingSet>
+ main_frame_events) = 0;
+
+ // Requests that the client schedule a composite now, and calculate
+ // appropriate delay for potential future frame.
+ virtual void RequestScheduleAnimation() = 0;
+
+ // Requests a visual frame-based update to the state of the delegate if there
+ // an update available.
+ virtual void UpdateVisualState() = 0;
+
+ // Indicates that the compositor is about to begin a frame. This is primarily
+ // to signal to flow control mechanisms that a frame is beginning, not to
+ // perform actual painting work.
+ virtual void WillBeginCompositorFrame() = 0;
+
+ protected:
+ virtual ~RenderWidgetCompositorDelegate() {}
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_GPU_RENDER_WIDGET_COMPOSITOR_DELEGATE_H_
diff --git a/chromium/content/renderer/gpu/render_widget_compositor_unittest.cc b/chromium/content/renderer/gpu/render_widget_compositor_unittest.cc
index 228fc47bea3..b217639d780 100644
--- a/chromium/content/renderer/gpu/render_widget_compositor_unittest.cc
+++ b/chromium/content/renderer/gpu/render_widget_compositor_unittest.cc
@@ -62,9 +62,10 @@ class RenderWidgetCompositorTest : public testing::Test {
RenderWidgetCompositorTest()
: compositor_deps_(new FakeCompositorDependencies),
render_widget_(new TestRenderWidget(compositor_deps_.get())),
- render_widget_compositor_(
- RenderWidgetCompositor::Create(render_widget_.get(),
- compositor_deps_.get())) {}
+ render_widget_compositor_(RenderWidgetCompositor::Create(
+ render_widget_.get(),
+ 1.f /* initial_device_scale_factor */,
+ compositor_deps_.get())) {}
~RenderWidgetCompositorTest() override {}
protected:
@@ -243,7 +244,8 @@ class RenderWidgetCompositorOutputSurfaceTest : public testing::Test {
render_widget_(new RenderWidgetOutputSurface(compositor_deps_.get())) {
render_widget_compositor_.reset(new RenderWidgetCompositorOutputSurface(
render_widget_.get(), compositor_deps_.get()));
- render_widget_compositor_->Initialize();
+ render_widget_compositor_->Initialize(
+ 1.f /* initial_device_scale_factor */);
render_widget_->SetCompositor(render_widget_compositor_.get());
}
diff --git a/chromium/content/renderer/gpu/stream_texture_host_android.cc b/chromium/content/renderer/gpu/stream_texture_host_android.cc
index 41e96b73c9d..3e62f98c162 100644
--- a/chromium/content/renderer/gpu/stream_texture_host_android.cc
+++ b/chromium/content/renderer/gpu/stream_texture_host_android.cc
@@ -4,14 +4,14 @@
#include "content/renderer/gpu/stream_texture_host_android.h"
-#include "content/common/gpu/client/gpu_channel_host.h"
-#include "content/common/gpu/gpu_messages.h"
#include "content/renderer/render_thread_impl.h"
+#include "gpu/ipc/client/gpu_channel_host.h"
+#include "gpu/ipc/common/gpu_messages.h"
#include "ipc/ipc_message_macros.h"
namespace content {
-StreamTextureHost::StreamTextureHost(GpuChannelHost* channel)
+StreamTextureHost::StreamTextureHost(gpu::GpuChannelHost* channel)
: stream_id_(0),
listener_(NULL),
channel_(channel),
@@ -42,8 +42,6 @@ bool StreamTextureHost::OnMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(StreamTextureHost, message)
IPC_MESSAGE_HANDLER(GpuStreamTextureMsg_FrameAvailable,
OnFrameAvailable);
- IPC_MESSAGE_HANDLER(GpuStreamTextureMsg_MatrixChanged,
- OnMatrixChanged);
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
DCHECK(handled);
@@ -58,12 +56,4 @@ void StreamTextureHost::OnFrameAvailable() {
listener_->OnFrameAvailable();
}
-void StreamTextureHost::OnMatrixChanged(
- const GpuStreamTextureMsg_MatrixChanged_Params& params) {
- static_assert(sizeof(params) == sizeof(float) * 16,
- "bad GpuStreamTextureMsg MatrixChanged_Params format");
- if (listener_)
- listener_->OnMatrixChanged((const float*)&params);
-}
-
} // namespace content
diff --git a/chromium/content/renderer/gpu/stream_texture_host_android.h b/chromium/content/renderer/gpu/stream_texture_host_android.h
index 998cff548fe..d03151b69c0 100644
--- a/chromium/content/renderer/gpu/stream_texture_host_android.h
+++ b/chromium/content/renderer/gpu/stream_texture_host_android.h
@@ -9,7 +9,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "content/common/android/surface_texture_peer.h"
+#include "gpu/ipc/common/android/surface_texture_peer.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_message.h"
@@ -17,16 +17,19 @@ namespace gfx {
class Size;
}
+namespace gpu {
+class GpuChannelHost;
+}
+
struct GpuStreamTextureMsg_MatrixChanged_Params;
namespace content {
-class GpuChannelHost;
// Class for handling all the IPC messages between the GPU process and
// StreamTextureProxy.
class StreamTextureHost : public IPC::Listener {
public:
- explicit StreamTextureHost(GpuChannelHost* channel);
+ explicit StreamTextureHost(gpu::GpuChannelHost* channel);
~StreamTextureHost() override;
// Listener class that is listening to the stream texture updates. It is
@@ -34,7 +37,6 @@ class StreamTextureHost : public IPC::Listener {
class Listener {
public:
virtual void OnFrameAvailable() = 0;
- virtual void OnMatrixChanged(const float mtx[16]) = 0;
virtual ~Listener() {}
};
@@ -47,11 +49,10 @@ class StreamTextureHost : public IPC::Listener {
private:
// Message handlers:
void OnFrameAvailable();
- void OnMatrixChanged(const GpuStreamTextureMsg_MatrixChanged_Params& param);
int stream_id_;
Listener* listener_;
- scoped_refptr<GpuChannelHost> channel_;
+ scoped_refptr<gpu::GpuChannelHost> channel_;
base::WeakPtrFactory<StreamTextureHost> weak_ptr_factory_;
DISALLOW_IMPLICIT_CONSTRUCTORS(StreamTextureHost);
diff --git a/chromium/content/renderer/history_controller.cc b/chromium/content/renderer/history_controller.cc
index 80b20dd56b2..ae04b877916 100644
--- a/chromium/content/renderer/history_controller.cc
+++ b/chromium/content/renderer/history_controller.cc
@@ -44,6 +44,7 @@
#include "third_party/WebKit/public/web/WebFrameLoadType.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
+using blink::WebCachePolicy;
using blink::WebFrame;
using blink::WebHistoryCommitType;
using blink::WebHistoryItem;
@@ -60,11 +61,11 @@ HistoryController::HistoryController(RenderViewImpl* render_view)
HistoryController::~HistoryController() {
}
-void HistoryController::GoToEntry(
+bool HistoryController::GoToEntry(
blink::WebLocalFrame* main_frame,
scoped_ptr<HistoryEntry> target_entry,
scoped_ptr<NavigationParams> navigation_params,
- WebURLRequest::CachePolicy cache_policy) {
+ WebCachePolicy cache_policy) {
DCHECK(!main_frame->parent());
HistoryFrameLoadVector same_document_loads;
HistoryFrameLoadVector different_document_loads;
@@ -89,6 +90,7 @@ void HistoryController::GoToEntry(
std::make_pair(main_frame, provisional_entry_->root()));
}
+ bool has_main_frame_request = false;
for (const auto& item : same_document_loads) {
WebFrame* frame = item.first;
RenderFrameImpl* render_frame = RenderFrameImpl::FromWebFrame(frame);
@@ -101,6 +103,8 @@ void HistoryController::GoToEntry(
frame->toWebLocalFrame()->load(
request, blink::WebFrameLoadType::BackForward, item.second,
blink::WebHistorySameDocumentLoad);
+ if (frame == main_frame)
+ has_main_frame_request = true;
}
for (const auto& item : different_document_loads) {
WebFrame* frame = item.first;
@@ -114,7 +118,11 @@ void HistoryController::GoToEntry(
frame->toWebLocalFrame()->load(
request, blink::WebFrameLoadType::BackForward, item.second,
blink::WebHistoryDifferentDocumentLoad);
+ if (frame == main_frame)
+ has_main_frame_request = true;
}
+
+ return has_main_frame_request;
}
void HistoryController::RecursiveGoToEntry(
@@ -134,11 +142,15 @@ void HistoryController::RecursiveGoToEntry(
if (old_item.isNull() ||
new_item.itemSequenceNumber() != old_item.itemSequenceNumber()) {
if (!old_item.isNull() &&
- new_item.documentSequenceNumber() == old_item.documentSequenceNumber())
+ new_item.documentSequenceNumber() ==
+ old_item.documentSequenceNumber()) {
same_document_loads.push_back(std::make_pair(frame, new_item));
- else
+ } else {
different_document_loads.push_back(std::make_pair(frame, new_item));
- return;
+ // For a different document, the subframes will be destroyed, so there's
+ // no need to consider them.
+ return;
+ }
}
for (WebFrame* child = frame->firstChild(); child;
@@ -176,7 +188,36 @@ void HistoryController::UpdateForCommit(RenderFrameImpl* frame,
case blink::WebBackForwardCommit:
if (!provisional_entry_)
return;
- current_entry_.reset(provisional_entry_.release());
+
+ // If the current entry is null, this must be a main frame commit.
+ DCHECK(current_entry_ || frame->IsMainFrame());
+
+ // Commit the provisional entry, but only if it is a plausible transition.
+ // Do not commit it if the navigation is in a subframe and the provisional
+ // entry's main frame item does not match the current entry's main frame,
+ // which can happen if multiple forward navigations occur. In that case,
+ // committing the provisional entry would corrupt it, leading to a URL
+ // spoof. See https://crbug.com/597322. (Note that the race in this bug
+ // does not affect main frame navigations, only navigations in subframes.)
+ //
+ // Note that we cannot compare the provisional entry against |item|, since
+ // |item| may have redirected to a different URL and ISN. We also cannot
+ // compare against the main frame's URL, since that may have changed due
+ // to a replaceState. (Even origin can change on replaceState in certain
+ // modes.)
+ //
+ // It would be safe to additionally check the ISNs of all parent frames
+ // (and not just the root), but that is less critical because it won't
+ // lead to a URL spoof.
+ if (frame->IsMainFrame() ||
+ current_entry_->root().itemSequenceNumber() ==
+ provisional_entry_->root().itemSequenceNumber()) {
+ current_entry_.reset(provisional_entry_.release());
+ }
+
+ // We're guaranteed to have a current entry now.
+ DCHECK(current_entry_);
+
if (HistoryEntry::HistoryNode* node =
current_entry_->GetHistoryNodeForFrame(frame)) {
node->set_item(item);
diff --git a/chromium/content/renderer/history_controller.h b/chromium/content/renderer/history_controller.h
index c8b00f2d33f..7787efb9d75 100644
--- a/chromium/content/renderer/history_controller.h
+++ b/chromium/content/renderer/history_controller.h
@@ -42,13 +42,13 @@
#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
#include "content/renderer/history_entry.h"
-#include "third_party/WebKit/public/platform/WebURLRequest.h"
#include "third_party/WebKit/public/web/WebHistoryCommitType.h"
#include "third_party/WebKit/public/web/WebHistoryItem.h"
namespace blink {
class WebFrame;
class WebLocalFrame;
+enum class WebCachePolicy;
}
namespace content {
@@ -117,10 +117,12 @@ class CONTENT_EXPORT HistoryController {
provisional_entry_ = std::move(entry);
}
- void GoToEntry(blink::WebLocalFrame* main_frame,
+ // Return true if the main frame ended up loading a request as part of the
+ // history navigation.
+ bool GoToEntry(blink::WebLocalFrame* main_frame,
scoped_ptr<HistoryEntry> entry,
scoped_ptr<NavigationParams> navigation_params,
- blink::WebURLRequest::CachePolicy cache_policy);
+ blink::WebCachePolicy cache_policy);
void UpdateForCommit(RenderFrameImpl* frame,
const blink::WebHistoryItem& item,
diff --git a/chromium/content/renderer/idle_user_detector.cc b/chromium/content/renderer/idle_user_detector.cc
index 339f68a5b2c..9ca35709fbc 100644
--- a/chromium/content/renderer/idle_user_detector.cc
+++ b/chromium/content/renderer/idle_user_detector.cc
@@ -25,8 +25,10 @@ bool IdleUserDetector::OnMessageReceived(const IPC::Message& message) {
return false;
}
-void IdleUserDetector::OnHandleInputEvent(const blink::WebInputEvent* event,
- const ui::LatencyInfo& latency_info) {
+void IdleUserDetector::OnHandleInputEvent(
+ const blink::WebInputEvent* event,
+ const ui::LatencyInfo& latency_info,
+ InputEventDispatchType dispatch_type) {
if (GetContentClient()->renderer()->RunIdleHandlerWhenWidgetsHidden()) {
RenderThreadImpl* render_thread = RenderThreadImpl::current();
if (render_thread != NULL) {
diff --git a/chromium/content/renderer/idle_user_detector.h b/chromium/content/renderer/idle_user_detector.h
index 3e3beba9eca..cbe85a0f697 100644
--- a/chromium/content/renderer/idle_user_detector.h
+++ b/chromium/content/renderer/idle_user_detector.h
@@ -6,6 +6,7 @@
#define CONTENT_RENDERER_IDLE_USER_DETECTOR_H_
#include "base/macros.h"
+#include "content/common/input/input_event_dispatch_type.h"
#include "content/public/renderer/render_view_observer.h"
namespace blink {
@@ -30,7 +31,8 @@ class IdleUserDetector : public RenderViewObserver {
bool OnMessageReceived(const IPC::Message& message) override;
void OnHandleInputEvent(const blink::WebInputEvent* event,
- const ui::LatencyInfo& latency_info);
+ const ui::LatencyInfo& latency_info,
+ InputEventDispatchType dispatch_type);
DISALLOW_COPY_AND_ASSIGN(IdleUserDetector);
};
diff --git a/chromium/content/renderer/image_downloader/image_downloader_impl.cc b/chromium/content/renderer/image_downloader/image_downloader_impl.cc
index c05998b20d3..421f421a927 100644
--- a/chromium/content/renderer/image_downloader/image_downloader_impl.cc
+++ b/chromium/content/renderer/image_downloader/image_downloader_impl.cc
@@ -26,6 +26,7 @@
#include "ui/gfx/skbitmap_operations.h"
#include "url/url_constants.h"
+using blink::WebCachePolicy;
using blink::WebFrame;
using blink::WebVector;
using blink::WebURL;
@@ -117,7 +118,7 @@ namespace content {
ImageDownloaderImpl::ImageDownloaderImpl(
RenderFrame* render_frame,
- mojo::InterfaceRequest<image_downloader::ImageDownloader> request)
+ mojo::InterfaceRequest<content::mojom::ImageDownloader> request)
: RenderFrameObserver(render_frame), binding_(this, std::move(request)) {
DCHECK(render_frame);
}
@@ -128,7 +129,7 @@ ImageDownloaderImpl::~ImageDownloaderImpl() {
// static
void ImageDownloaderImpl::CreateMojoService(
RenderFrame* render_frame,
- mojo::InterfaceRequest<image_downloader::ImageDownloader> request) {
+ mojo::InterfaceRequest<content::mojom::ImageDownloader> request) {
DVLOG(1) << "ImageDownloaderImpl::CreateService";
DCHECK(render_frame);
@@ -136,13 +137,12 @@ void ImageDownloaderImpl::CreateMojoService(
}
// ImageDownloader methods:
-void ImageDownloaderImpl::DownloadImage(
- image_downloader::DownloadRequestPtr req,
- const DownloadImageCallback& callback) {
- const GURL image_url = req->url.To<GURL>();
- bool is_favicon = req->is_favicon;
- uint32_t max_image_size = req->max_bitmap_size;
- bool bypass_cache = req->bypass_cache;
+void ImageDownloaderImpl::DownloadImage(const mojo::String& url,
+ bool is_favicon,
+ uint32_t max_bitmap_size,
+ bool bypass_cache,
+ const DownloadImageCallback& callback) {
+ const GURL image_url = url.To<GURL>();
std::vector<SkBitmap> result_images;
std::vector<gfx::Size> result_original_image_sizes;
@@ -150,12 +150,12 @@ void ImageDownloaderImpl::DownloadImage(
if (image_url.SchemeIs(url::kDataScheme)) {
SkBitmap data_image = ImageFromDataUrl(image_url);
if (!data_image.empty()) {
- result_images.push_back(ResizeImage(data_image, max_image_size));
+ result_images.push_back(ResizeImage(data_image, max_bitmap_size));
result_original_image_sizes.push_back(
gfx::Size(data_image.width(), data_image.height()));
}
} else {
- if (FetchImage(image_url, is_favicon, max_image_size, bypass_cache,
+ if (FetchImage(image_url, is_favicon, max_bitmap_size, bypass_cache,
callback)) {
// Will complete asynchronously via ImageDownloaderImpl::DidFetchImage
return;
@@ -177,8 +177,8 @@ bool ImageDownloaderImpl::FetchImage(const GURL& image_url,
image_fetchers_.push_back(new MultiResolutionImageResourceFetcher(
image_url, frame, 0, is_favicon ? WebURLRequest::RequestContextFavicon
: WebURLRequest::RequestContextImage,
- bypass_cache ? WebURLRequest::ReloadBypassingCache
- : WebURLRequest::UseProtocolCachePolicy,
+ bypass_cache ? WebCachePolicy::BypassingCache
+ : WebCachePolicy::UseProtocolCachePolicy,
base::Bind(&ImageDownloaderImpl::DidFetchImage, base::Unretained(this),
max_image_size, callback)));
return true;
@@ -212,15 +212,9 @@ void ImageDownloaderImpl::ReplyDownloadResult(
const std::vector<SkBitmap>& result_images,
const std::vector<gfx::Size>& result_original_image_sizes,
const DownloadImageCallback& callback) {
- image_downloader::DownloadResultPtr result =
- image_downloader::DownloadResult::New();
-
- result->http_status_code = http_status_code;
- result->images = mojo::Array<skia::BitmapPtr>::From(result_images);
- result->original_image_sizes =
- mojo::Array<mojo::SizePtr>::From(result_original_image_sizes);
-
- callback.Run(std::move(result));
+ callback.Run(http_status_code,
+ mojo::Array<skia::mojom::BitmapPtr>::From(result_images),
+ mojo::Array<mojo::SizePtr>::From(result_original_image_sizes));
}
} // namespace content
diff --git a/chromium/content/renderer/image_downloader/image_downloader_impl.h b/chromium/content/renderer/image_downloader/image_downloader_impl.h
index 888d839384c..cdbb75493d2 100644
--- a/chromium/content/renderer/image_downloader/image_downloader_impl.h
+++ b/chromium/content/renderer/image_downloader/image_downloader_impl.h
@@ -27,21 +27,24 @@ namespace content {
class MultiResolutionImageResourceFetcher;
class RenderFrame;
-class ImageDownloaderImpl : public image_downloader::ImageDownloader,
+class ImageDownloaderImpl : public content::mojom::ImageDownloader,
public RenderFrameObserver {
public:
static void CreateMojoService(
RenderFrame* render_frame,
- mojo::InterfaceRequest<image_downloader::ImageDownloader> request);
+ mojo::InterfaceRequest<content::mojom::ImageDownloader> request);
private:
ImageDownloaderImpl(
RenderFrame* render_frame,
- mojo::InterfaceRequest<image_downloader::ImageDownloader> request);
+ mojo::InterfaceRequest<content::mojom::ImageDownloader> request);
~ImageDownloaderImpl() override;
// ImageDownloader methods:
- void DownloadImage(image_downloader::DownloadRequestPtr req,
+ void DownloadImage(const mojo::String& url,
+ bool is_favicon,
+ uint32_t max_bitmap_size,
+ bool bypass_cache,
const DownloadImageCallback& callback) override;
// Requests to fetch an image. When done, the ImageDownloaderImpl
diff --git a/chromium/content/renderer/ime_event_guard.cc b/chromium/content/renderer/ime_event_guard.cc
index aaed1712a7b..668c531a5f6 100644
--- a/chromium/content/renderer/ime_event_guard.cc
+++ b/chromium/content/renderer/ime_event_guard.cc
@@ -8,14 +8,13 @@
namespace content {
+// When ThreadedInputConnection is used, we want to make sure that FROM_IME
+// is set only for OnRequestTextInputStateUpdate() so that we can distinguish
+// it from other updates so that we can wait for it safely. So it is false by
+// default.
ImeEventGuard::ImeEventGuard(RenderWidget* widget)
- : ImeEventGuard(widget, false, true) {
-}
-
-ImeEventGuard::ImeEventGuard(RenderWidget* widget, bool show_ime, bool from_ime)
- : widget_(widget),
- show_ime_(show_ime),
- from_ime_(from_ime) {
+ : widget_(widget), show_ime_(false),
+ from_ime_(!widget->IsUsingImeThread()) {
widget_->OnImeEventGuardStart(this);
}
diff --git a/chromium/content/renderer/ime_event_guard.h b/chromium/content/renderer/ime_event_guard.h
index c3854b17539..6d6991214e4 100644
--- a/chromium/content/renderer/ime_event_guard.h
+++ b/chromium/content/renderer/ime_event_guard.h
@@ -13,7 +13,6 @@ class RenderWidget;
class ImeEventGuard {
public:
explicit ImeEventGuard(RenderWidget* widget);
- ImeEventGuard(RenderWidget* widget, bool show_ime, bool from_ime);
~ImeEventGuard();
bool show_ime() const { return show_ime_; }
diff --git a/chromium/content/renderer/in_process_renderer_thread.h b/chromium/content/renderer/in_process_renderer_thread.h
index ab256f4a357..d7d0e71848e 100644
--- a/chromium/content/renderer/in_process_renderer_thread.h
+++ b/chromium/content/renderer/in_process_renderer_thread.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/threading/thread.h"
#include "content/common/content_export.h"
#include "content/common/in_process_child_thread_params.h"
diff --git a/chromium/content/renderer/input/input_event_filter.cc b/chromium/content/renderer/input/input_event_filter.cc
index c85586272fd..543e62a4c1b 100644
--- a/chromium/content/renderer/input/input_event_filter.cc
+++ b/chromium/content/renderer/input/input_event_filter.cc
@@ -19,15 +19,15 @@
#include "content/public/common/content_switches.h"
#include "ipc/ipc_listener.h"
#include "ipc/ipc_sender.h"
-#include "ui/events/blink/synchronous_input_handler_proxy.h"
#include "ui/gfx/geometry/vector2d_f.h"
using blink::WebInputEvent;
#include "ipc/ipc_message_null_macros.h"
#undef IPC_MESSAGE_DECL
-#define IPC_MESSAGE_DECL(kind, type, name, in, out, ilist, olist) \
- case name::ID: return #name;
+#define IPC_MESSAGE_DECL(name, ...) \
+ case name::ID: \
+ return #name;
const char* GetInputMessageTypeName(const IPC::Message& message) {
switch (message.type()) {
@@ -58,17 +58,16 @@ void InputEventFilter::SetBoundHandler(const Handler& handler) {
handler_ = handler;
}
-void InputEventFilter::DidAddInputHandler(
- int routing_id,
- ui::SynchronousInputHandlerProxy*
- synchronous_input_handler_proxy) {
+void InputEventFilter::DidAddInputHandler(int routing_id) {
base::AutoLock locked(routes_lock_);
routes_.insert(routing_id);
+ route_queues_[routing_id].reset(new MainThreadEventQueue(routing_id, this));
}
void InputEventFilter::DidRemoveInputHandler(int routing_id) {
base::AutoLock locked(routes_lock_);
routes_.erase(routing_id);
+ route_queues_.erase(routing_id);
}
void InputEventFilter::DidOverscroll(int routing_id,
@@ -86,6 +85,17 @@ void InputEventFilter::DidStopFlinging(int routing_id) {
SendMessage(make_scoped_ptr(new InputHostMsg_DidStopFlinging(routing_id)));
}
+void InputEventFilter::NotifyInputEventHandled(
+ int routing_id,
+ blink::WebInputEvent::Type type) {
+ DCHECK(target_task_runner_->BelongsToCurrentThread());
+ RouteQueueMap::iterator iter = route_queues_.find(routing_id);
+ if (iter == route_queues_.end() || !iter->second)
+ return;
+
+ iter->second->EventHandled(type);
+}
+
void InputEventFilter::OnFilterAdded(IPC::Sender* sender) {
io_task_runner_ = base::ThreadTaskRunnerHandle::Get();
sender_ = sender;
@@ -151,9 +161,12 @@ void InputEventFilter::ForwardToHandler(const IPC::Message& message) {
return;
const WebInputEvent* event = base::get<0>(params);
ui::LatencyInfo latency_info = base::get<1>(params);
+ InputEventDispatchType dispatch_type = base::get<2>(params);
DCHECK(event);
+ DCHECK(dispatch_type == DISPATCH_TYPE_BLOCKING ||
+ dispatch_type == DISPATCH_TYPE_NON_BLOCKING);
- const bool send_ack = WebInputEventTraits::WillReceiveAckFromRenderer(*event);
+ bool send_ack = dispatch_type == DISPATCH_TYPE_BLOCKING;
// Intercept |DidOverscroll| notifications, bundling any triggered overscroll
// response with the input event ack.
@@ -164,16 +177,13 @@ void InputEventFilter::ForwardToHandler(const IPC::Message& message) {
InputEventAckState ack_state = handler_.Run(routing_id, event, &latency_info);
- if (ack_state == INPUT_EVENT_ACK_STATE_NOT_CONSUMED) {
+ if (ack_state == INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING ||
+ ack_state == INPUT_EVENT_ACK_STATE_NOT_CONSUMED) {
DCHECK(!overscroll_params);
- TRACE_EVENT_INSTANT0(
- "input",
- "InputEventFilter::ForwardToHandler::ForwardToMainListener",
- TRACE_EVENT_SCOPE_THREAD);
- IPC::Message new_msg =
- InputMsg_HandleInputEvent(routing_id, event, latency_info);
- main_task_runner_->PostTask(FROM_HERE, base::Bind(main_listener_, new_msg));
- return;
+ RouteQueueMap::iterator iter = route_queues_.find(routing_id);
+ if (iter != route_queues_.end())
+ send_ack &= iter->second->HandleEvent(event, latency_info, dispatch_type,
+ ack_state);
}
if (!send_ack)
@@ -203,4 +213,17 @@ void InputEventFilter::SendMessageOnIOThread(scoped_ptr<IPC::Message> message) {
sender_->Send(message.release());
}
+void InputEventFilter::SendEventToMainThread(
+ int routing_id,
+ const blink::WebInputEvent* event,
+ const ui::LatencyInfo& latency_info,
+ InputEventDispatchType dispatch_type) {
+ TRACE_EVENT_INSTANT0(
+ "input", "InputEventFilter::ForwardToHandler::SendEventToMainThread",
+ TRACE_EVENT_SCOPE_THREAD);
+ IPC::Message new_msg =
+ InputMsg_HandleInputEvent(routing_id, event, latency_info, dispatch_type);
+ main_task_runner_->PostTask(FROM_HERE, base::Bind(main_listener_, new_msg));
+}
+
} // namespace content
diff --git a/chromium/content/renderer/input/input_event_filter.h b/chromium/content/renderer/input/input_event_filter.h
index e2d18f398df..ed93fa4e33b 100644
--- a/chromium/content/renderer/input/input_event_filter.h
+++ b/chromium/content/renderer/input/input_event_filter.h
@@ -7,12 +7,14 @@
#include <queue>
#include <set>
+#include <unordered_map>
#include "base/callback.h"
#include "base/synchronization/lock.h"
#include "content/common/content_export.h"
#include "content/common/input/input_event_ack_state.h"
#include "content/renderer/input/input_handler_manager_client.h"
+#include "content/renderer/input/main_thread_event_queue.h"
#include "ipc/message_filter.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
@@ -40,7 +42,8 @@ class Sender;
namespace content {
class CONTENT_EXPORT InputEventFilter : public InputHandlerManagerClient,
- public IPC::MessageFilter {
+ public IPC::MessageFilter,
+ public MainThreadEventQueueClient {
public:
InputEventFilter(
const base::Callback<void(const IPC::Message&)>& main_listener,
@@ -58,14 +61,13 @@ class CONTENT_EXPORT InputEventFilter : public InputHandlerManagerClient,
// InputHostMsg_HandleInputEvent_ACK.
//
void SetBoundHandler(const Handler& handler) override;
- void DidAddInputHandler(
- int routing_id,
- ui::SynchronousInputHandlerProxy*
- synchronous_input_handler_proxy) override;
+ void DidAddInputHandler(int routing_id) override;
void DidRemoveInputHandler(int routing_id) override;
void DidOverscroll(int routing_id,
const DidOverscrollParams& params) override;
void DidStopFlinging(int routing_id) override;
+ void NotifyInputEventHandled(int routing_id,
+ blink::WebInputEvent::Type type) override;
// IPC::MessageFilter methods:
void OnFilterAdded(IPC::Sender* sender) override;
@@ -73,6 +75,12 @@ class CONTENT_EXPORT InputEventFilter : public InputHandlerManagerClient,
void OnChannelClosing() override;
bool OnMessageReceived(const IPC::Message& message) override;
+ // MainThreadEventQueueClient methods:
+ void SendEventToMainThread(int routing_id,
+ const blink::WebInputEvent* event,
+ const ui::LatencyInfo& latency,
+ InputEventDispatchType dispatch_type) override;
+
private:
~InputEventFilter() override;
@@ -97,6 +105,10 @@ class CONTENT_EXPORT InputEventFilter : public InputHandlerManagerClient,
// Indicates the routing_ids for which input events should be filtered.
std::set<int> routes_;
+ using RouteQueueMap =
+ std::unordered_map<int, scoped_ptr<MainThreadEventQueue>>;
+ RouteQueueMap route_queues_;
+
// Used to intercept overscroll notifications while an event is being
// dispatched. If the event causes overscroll, the overscroll metadata can be
// bundled in the event ack, saving an IPC. Note that we must continue
diff --git a/chromium/content/renderer/input/input_event_filter_unittest.cc b/chromium/content/renderer/input/input_event_filter_unittest.cc
index 1aace83da9f..16b3f524616 100644
--- a/chromium/content/renderer/input/input_event_filter_unittest.cc
+++ b/chromium/content/renderer/input/input_event_filter_unittest.cc
@@ -23,6 +23,8 @@
using blink::WebInputEvent;
using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
+using blink::WebTouchEvent;
namespace content {
namespace {
@@ -34,12 +36,13 @@ class InputEventRecorder {
InputEventRecorder()
: filter_(NULL),
handle_events_(false),
- send_to_widget_(false) {
- }
+ send_to_widget_(false),
+ passive_(false) {}
void set_filter(InputEventFilter* filter) { filter_ = filter; }
void set_handle_events(bool value) { handle_events_ = value; }
void set_send_to_widget(bool value) { send_to_widget_ = value; }
+ void set_passive(bool value) { passive_ = value; }
size_t record_count() const { return records_.size(); }
@@ -56,14 +59,16 @@ class InputEventRecorder {
const WebInputEvent* event,
ui::LatencyInfo* latency_info) {
DCHECK_EQ(kTestRoutingID, routing_id);
-
records_.push_back(Record(event));
-
if (handle_events_) {
return INPUT_EVENT_ACK_STATE_CONSUMED;
+ } else if (send_to_widget_) {
+ if (passive_)
+ return INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING;
+ else
+ return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
} else {
- return send_to_widget_ ? INPUT_EVENT_ACK_STATE_NOT_CONSUMED
- : INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
+ return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
}
}
@@ -79,6 +84,7 @@ class InputEventRecorder {
InputEventFilter* filter_;
bool handle_events_;
bool send_to_widget_;
+ bool passive_;
std::vector<Record> records_;
};
@@ -105,20 +111,23 @@ class IPCMessageRecorder : public IPC::Listener {
void AddMessagesToFilter(IPC::MessageFilter* message_filter,
const std::vector<IPC::Message>& events) {
- for (size_t i = 0; i < events.size(); ++i) {
+ for (size_t i = 0; i < events.size(); ++i)
message_filter->OnMessageReceived(events[i]);
- }
base::MessageLoop::current()->RunUntilIdle();
}
+template <typename T>
void AddEventsToFilter(IPC::MessageFilter* message_filter,
- const WebMouseEvent events[],
+ const T events[],
size_t count) {
std::vector<IPC::Message> messages;
for (size_t i = 0; i < count; ++i) {
- messages.push_back(InputMsg_HandleInputEvent(kTestRoutingID, &events[i],
- ui::LatencyInfo()));
+ messages.push_back(InputMsg_HandleInputEvent(
+ kTestRoutingID, &events[i], ui::LatencyInfo(),
+ WebInputEventTraits::ShouldBlockEventStream(events[i])
+ ? InputEventDispatchType::DISPATCH_TYPE_BLOCKING
+ : InputEventDispatchType::DISPATCH_TYPE_NON_BLOCKING));
}
AddMessagesToFilter(message_filter, messages);
@@ -168,7 +177,7 @@ TEST_F(InputEventFilterTest, Basic) {
EXPECT_EQ(0U, event_recorder_.record_count());
EXPECT_EQ(0U, message_recorder_.message_count());
- filter_->DidAddInputHandler(kTestRoutingID, nullptr);
+ filter_->DidAddInputHandler(kTestRoutingID);
AddEventsToFilter(filter_.get(), kEvents, arraysize(kEvents));
ASSERT_EQ(arraysize(kEvents), ipc_sink_.message_count());
@@ -244,7 +253,7 @@ TEST_F(InputEventFilterTest, Basic) {
}
TEST_F(InputEventFilterTest, PreserveRelativeOrder) {
- filter_->DidAddInputHandler(kTestRoutingID, nullptr);
+ filter_->DidAddInputHandler(kTestRoutingID);
event_recorder_.set_send_to_widget(true);
@@ -254,8 +263,11 @@ TEST_F(InputEventFilterTest, PreserveRelativeOrder) {
SyntheticWebMouseEventBuilder::Build(WebMouseEvent::MouseUp);
std::vector<IPC::Message> messages;
- messages.push_back(InputMsg_HandleInputEvent(kTestRoutingID, &mouse_down,
- ui::LatencyInfo()));
+ messages.push_back(InputMsg_HandleInputEvent(
+ kTestRoutingID, &mouse_down, ui::LatencyInfo(),
+ WebInputEventTraits::ShouldBlockEventStream(mouse_down)
+ ? InputEventDispatchType::DISPATCH_TYPE_BLOCKING
+ : InputEventDispatchType::DISPATCH_TYPE_NON_BLOCKING));
// Control where input events are delivered.
messages.push_back(InputMsg_MouseCaptureLost(kTestRoutingID));
messages.push_back(InputMsg_SetFocus(kTestRoutingID, true));
@@ -281,8 +293,11 @@ TEST_F(InputEventFilterTest, PreserveRelativeOrder) {
gfx::Point(), gfx::Point()));
messages.push_back(InputMsg_MoveCaret(kTestRoutingID, gfx::Point()));
- messages.push_back(
- InputMsg_HandleInputEvent(kTestRoutingID, &mouse_up, ui::LatencyInfo()));
+ messages.push_back(InputMsg_HandleInputEvent(
+ kTestRoutingID, &mouse_up, ui::LatencyInfo(),
+ WebInputEventTraits::ShouldBlockEventStream(mouse_up)
+ ? InputEventDispatchType::DISPATCH_TYPE_BLOCKING
+ : InputEventDispatchType::DISPATCH_TYPE_NON_BLOCKING));
AddMessagesToFilter(filter_.get(), messages);
// We should have sent all messages back to the main thread and preserved
@@ -293,4 +308,236 @@ TEST_F(InputEventFilterTest, PreserveRelativeOrder) {
}
}
+TEST_F(InputEventFilterTest, NonBlockingWheel) {
+ WebMouseWheelEvent kEvents[4] = {
+ SyntheticWebMouseWheelEventBuilder::Build(10, 10, 0, 53, 0, false),
+ SyntheticWebMouseWheelEventBuilder::Build(20, 20, 0, 53, 0, false),
+ SyntheticWebMouseWheelEventBuilder::Build(30, 30, 0, 53, 1, false),
+ SyntheticWebMouseWheelEventBuilder::Build(30, 30, 0, 53, 1, false),
+ };
+
+ filter_->DidAddInputHandler(kTestRoutingID);
+ event_recorder_.set_send_to_widget(true);
+ event_recorder_.set_passive(true);
+
+ AddEventsToFilter(filter_.get(), kEvents, arraysize(kEvents));
+ EXPECT_EQ(arraysize(kEvents), event_recorder_.record_count());
+ ASSERT_EQ(4u, ipc_sink_.message_count());
+
+ // First event is sent right away.
+ EXPECT_EQ(1u, message_recorder_.message_count());
+
+ // Second event was queued; ack the first.
+ filter_->NotifyInputEventHandled(kTestRoutingID, WebInputEvent::MouseWheel);
+ base::MessageLoop::current()->RunUntilIdle();
+ ASSERT_EQ(4u, ipc_sink_.message_count());
+ EXPECT_EQ(2u, message_recorder_.message_count());
+
+ // Third event won't be coalesced into the second because modifiers are
+ // different.
+ filter_->NotifyInputEventHandled(kTestRoutingID, WebInputEvent::MouseWheel);
+ base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_EQ(3u, message_recorder_.message_count());
+
+ // The last events will be coalesced.
+ filter_->NotifyInputEventHandled(kTestRoutingID, WebInputEvent::MouseWheel);
+ base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_EQ(3u, message_recorder_.message_count());
+
+ // First two messages should be identical.
+ for (size_t i = 0; i < 2; ++i) {
+ const IPC::Message& message = message_recorder_.message_at(i);
+
+ ASSERT_EQ(InputMsg_HandleInputEvent::ID, message.type());
+ InputMsg_HandleInputEvent::Param params;
+ EXPECT_TRUE(InputMsg_HandleInputEvent::Read(&message, &params));
+ const WebInputEvent* event = base::get<0>(params);
+ InputEventDispatchType dispatch_type = base::get<2>(params);
+
+ EXPECT_EQ(kEvents[i].size, event->size);
+ kEvents[i].dispatchType =
+ WebInputEvent::DispatchType::ListenersNonBlockingPassive;
+ EXPECT_TRUE(memcmp(&kEvents[i], event, event->size) == 0);
+ EXPECT_EQ(InputEventDispatchType::DISPATCH_TYPE_NON_BLOCKING_NOTIFY_MAIN,
+ dispatch_type);
+ }
+
+ // Third message is coalesced.
+ {
+ const IPC::Message& message = message_recorder_.message_at(2);
+
+ ASSERT_EQ(InputMsg_HandleInputEvent::ID, message.type());
+ InputMsg_HandleInputEvent::Param params;
+ EXPECT_TRUE(InputMsg_HandleInputEvent::Read(&message, &params));
+ const WebMouseWheelEvent* event =
+ static_cast<const WebMouseWheelEvent*>(base::get<0>(params));
+ InputEventDispatchType dispatch_type = base::get<2>(params);
+
+ kEvents[2].dispatchType =
+ WebInputEvent::DispatchType::ListenersNonBlockingPassive;
+ EXPECT_EQ(kEvents[2].size, event->size);
+ EXPECT_EQ(kEvents[2].deltaX + kEvents[3].deltaX, event->deltaX);
+ EXPECT_EQ(kEvents[2].deltaY + kEvents[3].deltaY, event->deltaY);
+ EXPECT_EQ(InputEventDispatchType::DISPATCH_TYPE_NON_BLOCKING_NOTIFY_MAIN,
+ dispatch_type);
+ }
+}
+
+TEST_F(InputEventFilterTest, NonBlockingTouch) {
+ SyntheticWebTouchEvent kEvents[4];
+ kEvents[0].PressPoint(10, 10);
+ kEvents[1].PressPoint(10, 10);
+ kEvents[1].modifiers = 1;
+ kEvents[1].MovePoint(0, 20, 20);
+ kEvents[2].PressPoint(10, 10);
+ kEvents[2].MovePoint(0, 30, 30);
+ kEvents[3].PressPoint(10, 10);
+ kEvents[3].MovePoint(0, 35, 35);
+
+ filter_->DidAddInputHandler(kTestRoutingID);
+ event_recorder_.set_send_to_widget(true);
+ event_recorder_.set_passive(true);
+
+ AddEventsToFilter(filter_.get(), kEvents, arraysize(kEvents));
+ EXPECT_EQ(arraysize(kEvents), event_recorder_.record_count());
+ ASSERT_EQ(4u, ipc_sink_.message_count());
+
+ // First event is sent right away.
+ EXPECT_EQ(1u, message_recorder_.message_count());
+
+ // Second event was queued; ack the first.
+ filter_->NotifyInputEventHandled(kTestRoutingID, WebInputEvent::TouchStart);
+ base::MessageLoop::current()->RunUntilIdle();
+ ASSERT_EQ(4u, ipc_sink_.message_count());
+ EXPECT_EQ(2u, message_recorder_.message_count());
+
+ // Third event won't be coalesced into the second because modifiers are
+ // different.
+ filter_->NotifyInputEventHandled(kTestRoutingID, WebInputEvent::TouchMove);
+ base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_EQ(3u, message_recorder_.message_count());
+
+ // The last events will be coalesced.
+ filter_->NotifyInputEventHandled(kTestRoutingID, WebInputEvent::TouchMove);
+ base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_EQ(3u, message_recorder_.message_count());
+
+ // First two messages should be identical.
+ for (size_t i = 0; i < 2; ++i) {
+ const IPC::Message& message = message_recorder_.message_at(i);
+
+ ASSERT_EQ(InputMsg_HandleInputEvent::ID, message.type());
+ InputMsg_HandleInputEvent::Param params;
+ EXPECT_TRUE(InputMsg_HandleInputEvent::Read(&message, &params));
+ const WebInputEvent* event = base::get<0>(params);
+ InputEventDispatchType dispatch_type = base::get<2>(params);
+
+ EXPECT_EQ(kEvents[i].size, event->size);
+ kEvents[i].dispatchType =
+ WebInputEvent::DispatchType::ListenersNonBlockingPassive;
+ EXPECT_TRUE(memcmp(&kEvents[i], event, event->size) == 0);
+ EXPECT_EQ(InputEventDispatchType::DISPATCH_TYPE_NON_BLOCKING_NOTIFY_MAIN,
+ dispatch_type);
+ }
+
+ // Third message is coalesced.
+ {
+ const IPC::Message& message = message_recorder_.message_at(2);
+
+ ASSERT_EQ(InputMsg_HandleInputEvent::ID, message.type());
+ InputMsg_HandleInputEvent::Param params;
+ EXPECT_TRUE(InputMsg_HandleInputEvent::Read(&message, &params));
+ const WebTouchEvent* event =
+ static_cast<const WebTouchEvent*>(base::get<0>(params));
+ InputEventDispatchType dispatch_type = base::get<2>(params);
+
+ EXPECT_EQ(kEvents[3].size, event->size);
+ EXPECT_EQ(1u, kEvents[3].touchesLength);
+ EXPECT_EQ(kEvents[3].touches[0].position.x, event->touches[0].position.x);
+ EXPECT_EQ(kEvents[3].touches[0].position.y, event->touches[0].position.y);
+ EXPECT_EQ(InputEventDispatchType::DISPATCH_TYPE_NON_BLOCKING_NOTIFY_MAIN,
+ dispatch_type);
+ }
+}
+
+TEST_F(InputEventFilterTest, IntermingledNonBlockingTouch) {
+ SyntheticWebTouchEvent kEvents[2];
+ kEvents[0].PressPoint(10, 10);
+ kEvents[1].PressPoint(10, 10);
+ kEvents[1].ReleasePoint(0);
+ SyntheticWebTouchEvent kBlockingEvents[1];
+ kBlockingEvents[0].PressPoint(10, 10);
+
+ filter_->DidAddInputHandler(kTestRoutingID);
+ event_recorder_.set_send_to_widget(true);
+ event_recorder_.set_passive(true);
+ AddEventsToFilter(filter_.get(), kEvents, arraysize(kEvents));
+ EXPECT_EQ(arraysize(kEvents), event_recorder_.record_count());
+
+ event_recorder_.set_passive(false);
+ AddEventsToFilter(filter_.get(), kBlockingEvents, arraysize(kBlockingEvents));
+ EXPECT_EQ(arraysize(kEvents) + arraysize(kBlockingEvents),
+ event_recorder_.record_count());
+ ASSERT_EQ(3u, event_recorder_.record_count());
+
+ {
+ // First event is sent right away.
+ EXPECT_EQ(1u, message_recorder_.message_count());
+
+ const IPC::Message& message = message_recorder_.message_at(0);
+ ASSERT_EQ(InputMsg_HandleInputEvent::ID, message.type());
+ InputMsg_HandleInputEvent::Param params;
+ EXPECT_TRUE(InputMsg_HandleInputEvent::Read(&message, &params));
+ const WebInputEvent* event = base::get<0>(params);
+ InputEventDispatchType dispatch_type = base::get<2>(params);
+
+ EXPECT_EQ(kEvents[0].size, event->size);
+ kEvents[0].dispatchType =
+ WebInputEvent::DispatchType::ListenersNonBlockingPassive;
+ EXPECT_TRUE(memcmp(&kEvents[0], event, event->size) == 0);
+ EXPECT_EQ(InputEventDispatchType::DISPATCH_TYPE_NON_BLOCKING_NOTIFY_MAIN,
+ dispatch_type);
+ }
+
+ {
+ // Second event was queued; ack the first.
+ filter_->NotifyInputEventHandled(kTestRoutingID, WebInputEvent::TouchStart);
+ base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_EQ(2u, message_recorder_.message_count());
+
+ const IPC::Message& message = message_recorder_.message_at(1);
+ ASSERT_EQ(InputMsg_HandleInputEvent::ID, message.type());
+ InputMsg_HandleInputEvent::Param params;
+ EXPECT_TRUE(InputMsg_HandleInputEvent::Read(&message, &params));
+ const WebInputEvent* event = base::get<0>(params);
+ InputEventDispatchType dispatch_type = base::get<2>(params);
+
+ EXPECT_EQ(kEvents[1].size, event->size);
+ kEvents[1].dispatchType =
+ WebInputEvent::DispatchType::ListenersNonBlockingPassive;
+ EXPECT_TRUE(memcmp(&kEvents[1], event, event->size) == 0);
+ EXPECT_EQ(InputEventDispatchType::DISPATCH_TYPE_NON_BLOCKING_NOTIFY_MAIN,
+ dispatch_type);
+ }
+
+ {
+ // Third event should be put in the queue.
+ filter_->NotifyInputEventHandled(kTestRoutingID, WebInputEvent::TouchEnd);
+ base::MessageLoop::current()->RunUntilIdle();
+ EXPECT_EQ(3u, message_recorder_.message_count());
+
+ const IPC::Message& message = message_recorder_.message_at(2);
+ ASSERT_EQ(InputMsg_HandleInputEvent::ID, message.type());
+ InputMsg_HandleInputEvent::Param params;
+ EXPECT_TRUE(InputMsg_HandleInputEvent::Read(&message, &params));
+ const WebInputEvent* event = base::get<0>(params);
+ InputEventDispatchType dispatch_type = base::get<2>(params);
+
+ EXPECT_EQ(kBlockingEvents[0].size, event->size);
+ EXPECT_TRUE(memcmp(&kBlockingEvents[0], event, event->size) == 0);
+ EXPECT_EQ(InputEventDispatchType::DISPATCH_TYPE_BLOCKING_NOTIFY_MAIN,
+ dispatch_type);
+ }
+}
+
} // namespace content
diff --git a/chromium/content/renderer/input/input_handler_manager.cc b/chromium/content/renderer/input/input_handler_manager.cc
index 35ef3b46733..092e4286442 100644
--- a/chromium/content/renderer/input/input_handler_manager.cc
+++ b/chromium/content/renderer/input/input_handler_manager.cc
@@ -36,6 +36,8 @@ InputEventAckState InputEventDispositionToAck(
return INPUT_EVENT_ACK_STATE_NOT_CONSUMED;
case InputHandlerProxy::DROP_EVENT:
return INPUT_EVENT_ACK_STATE_NO_CONSUMER_EXISTS;
+ case InputHandlerProxy::DID_HANDLE_NON_BLOCKING:
+ return INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING;
}
NOTREACHED();
return INPUT_EVENT_ACK_STATE_UNKNOWN;
@@ -46,9 +48,11 @@ InputEventAckState InputEventDispositionToAck(
InputHandlerManager::InputHandlerManager(
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
InputHandlerManagerClient* client,
+ SynchronousInputHandlerProxyClient* sync_handler_client,
scheduler::RendererScheduler* renderer_scheduler)
: task_runner_(task_runner),
client_(client),
+ synchronous_handler_proxy_client_(sync_handler_client),
renderer_scheduler_(renderer_scheduler) {
DCHECK(client_);
client_->SetBoundHandler(base::Bind(&InputHandlerManager::HandleInputEvent,
@@ -63,20 +67,20 @@ void InputHandlerManager::AddInputHandler(
int routing_id,
const base::WeakPtr<cc::InputHandler>& input_handler,
const base::WeakPtr<RenderViewImpl>& render_view_impl,
- bool enable_smooth_scrolling) {
+ bool enable_smooth_scrolling,
+ bool enable_wheel_gestures) {
if (task_runner_->BelongsToCurrentThread()) {
- AddInputHandlerOnCompositorThread(routing_id,
- base::ThreadTaskRunnerHandle::Get(),
- input_handler, render_view_impl,
- enable_smooth_scrolling);
+ AddInputHandlerOnCompositorThread(
+ routing_id, base::ThreadTaskRunnerHandle::Get(), input_handler,
+ render_view_impl, enable_smooth_scrolling, enable_wheel_gestures);
} else {
task_runner_->PostTask(
FROM_HERE,
base::Bind(&InputHandlerManager::AddInputHandlerOnCompositorThread,
base::Unretained(this), routing_id,
base::ThreadTaskRunnerHandle::Get(), input_handler,
- render_view_impl,
- enable_smooth_scrolling));
+ render_view_impl, enable_smooth_scrolling,
+ enable_wheel_gestures));
}
}
@@ -85,7 +89,8 @@ void InputHandlerManager::AddInputHandlerOnCompositorThread(
const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
const base::WeakPtr<cc::InputHandler>& input_handler,
const base::WeakPtr<RenderViewImpl>& render_view_impl,
- bool enable_smooth_scrolling) {
+ bool enable_smooth_scrolling,
+ bool enable_wheel_gestures) {
DCHECK(task_runner_->BelongsToCurrentThread());
// The handler could be gone by this point if the compositor has shut down.
@@ -101,8 +106,12 @@ void InputHandlerManager::AddInputHandlerOnCompositorThread(
"result", "AddingRoute");
scoped_ptr<InputHandlerWrapper> wrapper(new InputHandlerWrapper(
this, routing_id, main_task_runner, input_handler, render_view_impl,
- enable_smooth_scrolling));
- client_->DidAddInputHandler(routing_id, wrapper->input_handler_proxy());
+ enable_smooth_scrolling, enable_wheel_gestures));
+ client_->DidAddInputHandler(routing_id);
+ if (synchronous_handler_proxy_client_) {
+ synchronous_handler_proxy_client_->DidAddSynchronousHandlerProxy(
+ routing_id, wrapper->input_handler_proxy());
+ }
input_handlers_.add(routing_id, std::move(wrapper));
}
@@ -113,6 +122,10 @@ void InputHandlerManager::RemoveInputHandler(int routing_id) {
TRACE_EVENT0("input", "InputHandlerManager::RemoveInputHandler");
client_->DidRemoveInputHandler(routing_id);
+ if (synchronous_handler_proxy_client_) {
+ synchronous_handler_proxy_client_->DidRemoveSynchronousHandlerProxy(
+ routing_id);
+ }
input_handlers_.erase(routing_id);
}
@@ -131,6 +144,7 @@ void InputHandlerManager::ObserveWheelEventAndResultOnCompositorThread(
int routing_id,
const blink::WebMouseWheelEvent& wheel_event,
const cc::InputHandlerScrollResult& scroll_result) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
auto it = input_handlers_.find(routing_id);
if (it == input_handlers_.end())
return;
@@ -141,6 +155,53 @@ void InputHandlerManager::ObserveWheelEventAndResultOnCompositorThread(
wheel_event, scroll_result);
}
+void InputHandlerManager::ObserveGestureEventAndResultOnMainThread(
+ int routing_id,
+ const blink::WebGestureEvent& gesture_event,
+ const cc::InputHandlerScrollResult& scroll_result) {
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &InputHandlerManager::ObserveGestureEventAndResultOnCompositorThread,
+ base::Unretained(this), routing_id, gesture_event, scroll_result));
+}
+
+void InputHandlerManager::ObserveGestureEventAndResultOnCompositorThread(
+ int routing_id,
+ const blink::WebGestureEvent& gesture_event,
+ const cc::InputHandlerScrollResult& scroll_result) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ auto it = input_handlers_.find(routing_id);
+ if (it == input_handlers_.end())
+ return;
+
+ InputHandlerProxy* proxy = it->second->input_handler_proxy();
+ DCHECK(proxy->scroll_elasticity_controller());
+ proxy->scroll_elasticity_controller()->ObserveGestureEventAndResult(
+ gesture_event, scroll_result);
+}
+
+void InputHandlerManager::NotifyInputEventHandledOnMainThread(
+ int routing_id,
+ blink::WebInputEvent::Type type) {
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &InputHandlerManager::NotifyInputEventHandledOnCompositorThread,
+ base::Unretained(this), routing_id, type));
+}
+
+void InputHandlerManager::NotifyInputEventHandledOnCompositorThread(
+ int routing_id,
+ blink::WebInputEvent::Type handled_type) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ auto it = input_handlers_.find(routing_id);
+ if (it == input_handlers_.end())
+ return;
+
+ client_->NotifyInputEventHandled(routing_id, handled_type);
+}
+
InputEventAckState InputHandlerManager::HandleInputEvent(
int routing_id,
const WebInputEvent* input_event,
diff --git a/chromium/content/renderer/input/input_handler_manager.h b/chromium/content/renderer/input/input_handler_manager.h
index 6905a88375b..948759c0abc 100644
--- a/chromium/content/renderer/input/input_handler_manager.h
+++ b/chromium/content/renderer/input/input_handler_manager.h
@@ -8,6 +8,7 @@
#include "base/containers/scoped_ptr_hash_map.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "content/common/content_export.h"
#include "content/common/input/input_event_ack_state.h"
#include "content/renderer/render_view_impl.h"
@@ -32,12 +33,13 @@ class RendererScheduler;
namespace content {
class InputHandlerWrapper;
+class SynchronousInputHandlerProxyClient;
class InputHandlerManagerClient;
struct DidOverscrollParams;
// InputHandlerManager class manages InputHandlerProxy instances for
// the WebViews in this renderer.
-class InputHandlerManager {
+class CONTENT_EXPORT InputHandlerManager {
public:
// |task_runner| is the SingleThreadTaskRunner of the compositor thread. The
// underlying MessageLoop and supplied |client| and the |renderer_scheduler|
@@ -46,28 +48,38 @@ class InputHandlerManager {
InputHandlerManager(
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
InputHandlerManagerClient* client,
+ SynchronousInputHandlerProxyClient* sync_handler_client,
scheduler::RendererScheduler* renderer_scheduler);
- ~InputHandlerManager();
+ virtual ~InputHandlerManager();
// Callable from the main thread only.
- void AddInputHandler(
- int routing_id,
- const base::WeakPtr<cc::InputHandler>& input_handler,
- const base::WeakPtr<RenderViewImpl>& render_view_impl,
- bool enable_smooth_scrolling);
+ void AddInputHandler(int routing_id,
+ const base::WeakPtr<cc::InputHandler>& input_handler,
+ const base::WeakPtr<RenderViewImpl>& render_view_impl,
+ bool enable_smooth_scrolling,
+ bool enable_wheel_gestures);
void ObserveWheelEventAndResultOnMainThread(
int routing_id,
const blink::WebMouseWheelEvent& wheel_event,
const cc::InputHandlerScrollResult& scroll_result);
+ void ObserveGestureEventAndResultOnMainThread(
+ int routing_id,
+ const blink::WebGestureEvent& gesture_event,
+ const cc::InputHandlerScrollResult& scroll_result);
+
+ void NotifyInputEventHandledOnMainThread(int routing_id,
+ blink::WebInputEvent::Type);
+
// Callback only from the compositor's thread.
void RemoveInputHandler(int routing_id);
// Called from the compositor's thread.
- InputEventAckState HandleInputEvent(int routing_id,
- const blink::WebInputEvent* input_event,
- ui::LatencyInfo* latency_info);
+ virtual InputEventAckState HandleInputEvent(
+ int routing_id,
+ const blink::WebInputEvent* input_event,
+ ui::LatencyInfo* latency_info);
// Called from the compositor's thread.
void DidOverscroll(int routing_id, const DidOverscrollParams& params);
@@ -85,21 +97,32 @@ class InputHandlerManager {
const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
const base::WeakPtr<cc::InputHandler>& input_handler,
const base::WeakPtr<RenderViewImpl>& render_view_impl,
- bool enable_smooth_scrolling);
+ bool enable_smooth_scrolling,
+ bool enable_wheel_gestures);
void ObserveWheelEventAndResultOnCompositorThread(
int routing_id,
const blink::WebMouseWheelEvent& wheel_event,
const cc::InputHandlerScrollResult& scroll_result);
+ void ObserveGestureEventAndResultOnCompositorThread(
+ int routing_id,
+ const blink::WebGestureEvent& gesture_event,
+ const cc::InputHandlerScrollResult& scroll_result);
+
+ void NotifyInputEventHandledOnCompositorThread(int routing_id,
+ blink::WebInputEvent::Type);
+
typedef base::ScopedPtrHashMap<int, // routing_id
scoped_ptr<InputHandlerWrapper>>
InputHandlerMap;
InputHandlerMap input_handlers_;
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- InputHandlerManagerClient* client_;
- scheduler::RendererScheduler* renderer_scheduler_; // Not owned.
+ const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ InputHandlerManagerClient* const client_;
+ // May be null.
+ SynchronousInputHandlerProxyClient* const synchronous_handler_proxy_client_;
+ scheduler::RendererScheduler* const renderer_scheduler_; // Not owned.
};
} // namespace content
diff --git a/chromium/content/renderer/input/input_handler_manager_client.h b/chromium/content/renderer/input/input_handler_manager_client.h
index cf4fe00f35a..7400afe97a1 100644
--- a/chromium/content/renderer/input/input_handler_manager_client.h
+++ b/chromium/content/renderer/input/input_handler_manager_client.h
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "content/common/content_export.h"
#include "content/common/input/input_event_ack_state.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/gfx/geometry/vector2d_f.h"
namespace ui {
@@ -20,10 +21,6 @@ namespace cc {
class InputHandler;
}
-namespace blink {
-class WebInputEvent;
-}
-
namespace ui {
class SynchronousInputHandlerProxy;
}
@@ -47,13 +44,13 @@ class CONTENT_EXPORT InputHandlerManagerClient {
virtual void SetBoundHandler(const Handler& handler) = 0;
// Called from the compositor thread.
- virtual void DidAddInputHandler(
- int routing_id,
- ui::SynchronousInputHandlerProxy* synchronous_handler) = 0;
+ virtual void DidAddInputHandler(int routing_id) = 0;
virtual void DidRemoveInputHandler(int routing_id) = 0;
virtual void DidOverscroll(int routing_id,
const DidOverscrollParams& params) = 0;
virtual void DidStopFlinging(int routing_id) = 0;
+ virtual void NotifyInputEventHandled(int routing_id,
+ blink::WebInputEvent::Type type) = 0;
protected:
InputHandlerManagerClient() {}
@@ -62,6 +59,22 @@ class CONTENT_EXPORT InputHandlerManagerClient {
DISALLOW_COPY_AND_ASSIGN(InputHandlerManagerClient);
};
+class CONTENT_EXPORT SynchronousInputHandlerProxyClient {
+ public:
+ virtual ~SynchronousInputHandlerProxyClient() {}
+
+ virtual void DidAddSynchronousHandlerProxy(
+ int routing_id,
+ ui::SynchronousInputHandlerProxy* synchronous_handler) = 0;
+ virtual void DidRemoveSynchronousHandlerProxy(int routing_id) = 0;
+
+ protected:
+ SynchronousInputHandlerProxyClient() {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SynchronousInputHandlerProxyClient);
+};
+
} // namespace content
#endif // CONTENT_RENDERER_INPUT_INPUT_HANDLER_MANAGER_CLIENT_H_
diff --git a/chromium/content/renderer/input/input_handler_wrapper.cc b/chromium/content/renderer/input/input_handler_wrapper.cc
index 6265744773c..c8280e4a316 100644
--- a/chromium/content/renderer/input/input_handler_wrapper.cc
+++ b/chromium/content/renderer/input/input_handler_wrapper.cc
@@ -20,7 +20,8 @@ InputHandlerWrapper::InputHandlerWrapper(
const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
const base::WeakPtr<cc::InputHandler>& input_handler,
const base::WeakPtr<RenderViewImpl>& render_view_impl,
- bool enable_smooth_scrolling)
+ bool enable_smooth_scrolling,
+ bool enable_wheel_gestures)
: input_handler_manager_(input_handler_manager),
routing_id_(routing_id),
input_handler_proxy_(input_handler.get(), this),
@@ -28,6 +29,8 @@ InputHandlerWrapper::InputHandlerWrapper(
render_view_impl_(render_view_impl) {
DCHECK(input_handler);
input_handler_proxy_.set_smooth_scroll_enabled(enable_smooth_scrolling);
+ input_handler_proxy_.set_use_gesture_events_for_mouse_wheel(
+ enable_wheel_gestures);
}
InputHandlerWrapper::~InputHandlerWrapper() {
diff --git a/chromium/content/renderer/input/input_handler_wrapper.h b/chromium/content/renderer/input/input_handler_wrapper.h
index bc864d9f2a5..d3781315694 100644
--- a/chromium/content/renderer/input/input_handler_wrapper.h
+++ b/chromium/content/renderer/input/input_handler_wrapper.h
@@ -28,7 +28,8 @@ class InputHandlerWrapper : public ui::InputHandlerProxyClient {
const scoped_refptr<base::SingleThreadTaskRunner>& main_task_runner,
const base::WeakPtr<cc::InputHandler>& input_handler,
const base::WeakPtr<RenderViewImpl>& render_view_impl,
- bool enable_smooth_scrolling);
+ bool enable_smooth_scrolling,
+ bool enable_wheel_gestures);
~InputHandlerWrapper() override;
int routing_id() const { return routing_id_; }
diff --git a/chromium/content/renderer/input/main_thread_event_queue.cc b/chromium/content/renderer/input/main_thread_event_queue.cc
new file mode 100644
index 00000000000..0342c592973
--- /dev/null
+++ b/chromium/content/renderer/input/main_thread_event_queue.cc
@@ -0,0 +1,122 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/input/main_thread_event_queue.h"
+
+namespace content {
+
+MainThreadEventQueue::MainThreadEventQueue(int routing_id,
+ MainThreadEventQueueClient* client)
+ : routing_id_(routing_id), client_(client) {}
+
+MainThreadEventQueue::~MainThreadEventQueue() {}
+
+bool MainThreadEventQueue::HandleEvent(
+ const blink::WebInputEvent* event,
+ const ui::LatencyInfo& latency,
+ InputEventDispatchType original_dispatch_type,
+ InputEventAckState ack_result) {
+ DCHECK(original_dispatch_type == DISPATCH_TYPE_BLOCKING ||
+ original_dispatch_type == DISPATCH_TYPE_NON_BLOCKING);
+ DCHECK(ack_result == INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING ||
+ ack_result == INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ bool non_blocking = original_dispatch_type == DISPATCH_TYPE_NON_BLOCKING ||
+ ack_result == INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING;
+
+ InputEventDispatchType dispatch_type =
+ non_blocking ? DISPATCH_TYPE_NON_BLOCKING_NOTIFY_MAIN
+ : DISPATCH_TYPE_BLOCKING_NOTIFY_MAIN;
+
+ if (event->type == blink::WebInputEvent::MouseWheel) {
+ PendingMouseWheelEvent modified_dispatch_type_event =
+ PendingMouseWheelEvent(
+ *static_cast<const blink::WebMouseWheelEvent*>(event), latency,
+ dispatch_type);
+
+ // Adjust the |dispatchType| on the event since the compositor
+ // determined all event listeners are passive.
+ if (non_blocking) {
+ modified_dispatch_type_event.event.dispatchType =
+ blink::WebInputEvent::ListenersNonBlockingPassive;
+ }
+
+ if (wheel_events_.state() == WebInputEventQueueState::ITEM_PENDING) {
+ wheel_events_.Queue(modified_dispatch_type_event);
+ } else {
+ if (non_blocking) {
+ wheel_events_.set_state(WebInputEventQueueState::ITEM_PENDING);
+ client_->SendEventToMainThread(routing_id_,
+ &modified_dispatch_type_event.event,
+ latency, dispatch_type);
+ } else {
+ // If there is nothing in the event queue and the event is
+ // blocking pass the |original_dispatch_type| to avoid
+ // having the main thread call us back as an optimization.
+ client_->SendEventToMainThread(routing_id_,
+ &modified_dispatch_type_event.event,
+ latency, original_dispatch_type);
+ }
+ }
+ } else if (blink::WebInputEvent::isTouchEventType(event->type)) {
+ PendingTouchEvent modified_dispatch_type_event =
+ PendingTouchEvent(*static_cast<const blink::WebTouchEvent*>(event),
+ latency, dispatch_type);
+
+ // Adjust the |dispatchType| on the event since the compositor
+ // determined all event listeners are passive.
+ if (non_blocking) {
+ modified_dispatch_type_event.event.dispatchType =
+ blink::WebInputEvent::ListenersNonBlockingPassive;
+ }
+
+ if (touch_events_.state() == WebInputEventQueueState::ITEM_PENDING) {
+ touch_events_.Queue(modified_dispatch_type_event);
+ } else {
+ if (non_blocking) {
+ touch_events_.set_state(WebInputEventQueueState::ITEM_PENDING);
+ client_->SendEventToMainThread(routing_id_,
+ &modified_dispatch_type_event.event,
+ latency, dispatch_type);
+ } else {
+ // If there is nothing in the event queue and the event is
+ // blocking pass the |original_dispatch_type| to avoid
+ // having the main thread call us back as an optimization.
+ client_->SendEventToMainThread(routing_id_,
+ &modified_dispatch_type_event.event,
+ latency, original_dispatch_type);
+ }
+ }
+ } else {
+ client_->SendEventToMainThread(routing_id_, event, latency,
+ original_dispatch_type);
+ }
+
+ // send an ack when we are non-blocking.
+ return non_blocking;
+}
+
+void MainThreadEventQueue::EventHandled(blink::WebInputEvent::Type type) {
+ if (type == blink::WebInputEvent::MouseWheel) {
+ if (!wheel_events_.empty()) {
+ scoped_ptr<PendingMouseWheelEvent> event = wheel_events_.Pop();
+ client_->SendEventToMainThread(routing_id_, &event->event, event->latency,
+ event->type);
+ } else {
+ wheel_events_.set_state(WebInputEventQueueState::ITEM_NOT_PENDING);
+ }
+ } else if (blink::WebInputEvent::isTouchEventType(type)) {
+ if (!touch_events_.empty()) {
+ scoped_ptr<PendingTouchEvent> event = touch_events_.Pop();
+ client_->SendEventToMainThread(routing_id_, &event->event, event->latency,
+ event->type);
+ } else {
+ touch_events_.set_state(WebInputEventQueueState::ITEM_NOT_PENDING);
+ }
+ } else {
+ NOTREACHED() << "Invalid passive event type";
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/input/main_thread_event_queue.h b/chromium/content/renderer/input/main_thread_event_queue.h
new file mode 100644
index 00000000000..0eb2d147f89
--- /dev/null
+++ b/chromium/content/renderer/input/main_thread_event_queue.h
@@ -0,0 +1,121 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_INPUT_MAIN_THREAD_EVENT_QUEUE_H_
+#define CONTENT_RENDERER_INPUT_MAIN_THREAD_EVENT_QUEUE_H_
+
+#include <deque>
+#include "content/common/content_export.h"
+#include "content/common/input/event_with_latency_info.h"
+#include "content/common/input/input_event_ack_state.h"
+#include "content/common/input/input_event_dispatch_type.h"
+#include "content/common/input/web_input_event_queue.h"
+#include "third_party/WebKit/public/web/WebInputEvent.h"
+#include "ui/events/latency_info.h"
+
+namespace content {
+
+template <typename BaseClass, typename BaseType>
+class EventWithDispatchType : public BaseClass {
+ public:
+ EventWithDispatchType(const BaseType& e,
+ const ui::LatencyInfo& l,
+ InputEventDispatchType t)
+ : BaseClass(e, l), type(t) {}
+
+ InputEventDispatchType type;
+
+ bool CanCoalesceWith(const EventWithDispatchType& other) const
+ WARN_UNUSED_RESULT {
+ return other.type == type && BaseClass::CanCoalesceWith(other);
+ }
+
+ void CoalesceWith(const EventWithDispatchType& other) {
+ BaseClass::CoalesceWith(other);
+ }
+};
+
+using PendingMouseWheelEvent =
+ EventWithDispatchType<MouseWheelEventWithLatencyInfo,
+ blink::WebMouseWheelEvent>;
+
+using PendingTouchEvent =
+ EventWithDispatchType<TouchEventWithLatencyInfo, blink::WebTouchEvent>;
+
+class CONTENT_EXPORT MainThreadEventQueueClient {
+ public:
+ // Send an |event| that was previously queued (possibly
+ // coalesced with another event) to the |routing_id|'s
+ // channel. Implementors must implement this callback.
+ virtual void SendEventToMainThread(int routing_id,
+ const blink::WebInputEvent* event,
+ const ui::LatencyInfo& latency,
+ InputEventDispatchType dispatch_type) = 0;
+};
+
+// MainThreadEventQueue implements a series of queues (one touch
+// and one mouse wheel) for events that need to be queued between
+// the compositor and main threads. When an event is sent
+// from the compositor to main it can either be sent directly if no
+// outstanding events of that type are in flight; or it needs to
+// wait in a queue until the main thread has finished processing
+// the in-flight event. This class tracks the state and queues
+// for the event types. Methods on this class should only be called
+// from the compositor thread.
+//
+// Below some example flows are how the code behaves.
+// Legend: B=Browser, C=Compositor, M=Main Thread, NB=Non-blocking
+// BL=Blocking, PT=Post Task, ACK=Acknowledgement
+//
+// Normal blocking event sent to main thread.
+// B C M
+// ---(BL)-->
+// ---(PT)-->
+// <-------(ACK)------
+//
+// Non-blocking event sent to main thread.
+// B C M
+// ---(NB)-->
+// ---(PT)-->
+// <--(PT)---
+//
+// Non-blocking followed by blocking event sent to main thread.
+// B C M
+// ---(NB)-->
+// ---(PT)-->
+// ---(BL)-->
+// <--(PT)--- // Notify from NB event.
+// ---(PT)--> // Release blocking event.
+// <--(PT)--- // Notify from BL event.
+// <-------(ACK)------
+//
+class CONTENT_EXPORT MainThreadEventQueue {
+ public:
+ MainThreadEventQueue(int routing_id, MainThreadEventQueueClient* client);
+ ~MainThreadEventQueue();
+
+ // Called once the compositor has handled |event| and indicated that it is
+ // a non-blocking event to be queued to the main thread.
+ bool HandleEvent(const blink::WebInputEvent* event,
+ const ui::LatencyInfo& latency,
+ InputEventDispatchType dispatch_type,
+ InputEventAckState ack_result);
+
+ // Call once the main thread has handled an outstanding |type| event
+ // in flight.
+ void EventHandled(blink::WebInputEvent::Type type);
+
+ private:
+ friend class MainThreadEventQueueTest;
+ int routing_id_;
+ MainThreadEventQueueClient* client_;
+ WebInputEventQueue<PendingMouseWheelEvent> wheel_events_;
+ WebInputEventQueue<PendingTouchEvent> touch_events_;
+
+ DISALLOW_COPY_AND_ASSIGN(MainThreadEventQueue);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_INPUT_MAIN_THREAD_EVENT_QUEUE_H_
diff --git a/chromium/content/renderer/input/main_thread_event_queue_unittest.cc b/chromium/content/renderer/input/main_thread_event_queue_unittest.cc
new file mode 100644
index 00000000000..2a435619881
--- /dev/null
+++ b/chromium/content/renderer/input/main_thread_event_queue_unittest.cc
@@ -0,0 +1,139 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+
+#include <new>
+#include <utility>
+#include <vector>
+
+#include "base/macros.h"
+#include "build/build_config.h"
+#include "content/common/input/synthetic_web_input_event_builders.h"
+#include "content/renderer/input/main_thread_event_queue.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using blink::WebInputEvent;
+using blink::WebMouseEvent;
+using blink::WebMouseWheelEvent;
+using blink::WebTouchEvent;
+
+namespace content {
+namespace {
+
+const int kTestRoutingID = 13;
+}
+
+class MainThreadEventQueueTest : public testing::Test,
+ public MainThreadEventQueueClient {
+ public:
+ MainThreadEventQueueTest() : queue_(kTestRoutingID, this) {}
+
+ void SendEventToMainThread(int routing_id,
+ const blink::WebInputEvent* event,
+ const ui::LatencyInfo& latency,
+ InputEventDispatchType type) override {
+ ASSERT_EQ(kTestRoutingID, routing_id);
+ const unsigned char* eventPtr =
+ reinterpret_cast<const unsigned char*>(event);
+ last_event_.assign(eventPtr, eventPtr + event->size);
+ }
+
+ WebInputEventQueue<PendingMouseWheelEvent>& wheel_event_queue() {
+ return queue_.wheel_events_;
+ }
+
+ WebInputEventQueue<PendingTouchEvent>& touch_event_queue() {
+ return queue_.touch_events_;
+ }
+
+ protected:
+ MainThreadEventQueue queue_;
+ std::vector<unsigned char> last_event_;
+};
+
+TEST_F(MainThreadEventQueueTest, NonBlockingWheel) {
+ WebMouseWheelEvent kEvents[4] = {
+ SyntheticWebMouseWheelEventBuilder::Build(10, 10, 0, 53, 0, false),
+ SyntheticWebMouseWheelEventBuilder::Build(20, 20, 0, 53, 0, false),
+ SyntheticWebMouseWheelEventBuilder::Build(30, 30, 0, 53, 1, false),
+ SyntheticWebMouseWheelEventBuilder::Build(30, 30, 0, 53, 1, false),
+ };
+
+ ASSERT_EQ(WebInputEventQueueState::ITEM_NOT_PENDING,
+ wheel_event_queue().state());
+ queue_.HandleEvent(&kEvents[0], ui::LatencyInfo(), DISPATCH_TYPE_BLOCKING,
+ INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
+ ASSERT_EQ(WebInputEventQueueState::ITEM_PENDING, wheel_event_queue().state());
+ queue_.HandleEvent(&kEvents[1], ui::LatencyInfo(), DISPATCH_TYPE_BLOCKING,
+ INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
+ ASSERT_EQ(kEvents[0].size, last_event_.size());
+ kEvents[0].dispatchType =
+ WebInputEvent::DispatchType::ListenersNonBlockingPassive;
+ ASSERT_TRUE(memcmp(&last_event_[0], &kEvents[0], kEvents[0].size) == 0);
+ queue_.EventHandled(blink::WebInputEvent::MouseWheel);
+ ASSERT_EQ(kEvents[1].size, last_event_.size());
+ kEvents[1].dispatchType =
+ WebInputEvent::DispatchType::ListenersNonBlockingPassive;
+ ASSERT_TRUE(memcmp(&last_event_[0], &kEvents[1], kEvents[1].size) == 0);
+ ASSERT_EQ(WebInputEventQueueState::ITEM_PENDING, wheel_event_queue().state());
+ queue_.EventHandled(blink::WebInputEvent::MouseWheel);
+ ASSERT_EQ(WebInputEventQueueState::ITEM_NOT_PENDING,
+ wheel_event_queue().state());
+
+ // Ensure that coalescing takes place.
+ queue_.HandleEvent(&kEvents[0], ui::LatencyInfo(), DISPATCH_TYPE_BLOCKING,
+ INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
+ queue_.HandleEvent(&kEvents[2], ui::LatencyInfo(), DISPATCH_TYPE_BLOCKING,
+ INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
+ queue_.HandleEvent(&kEvents[3], ui::LatencyInfo(), DISPATCH_TYPE_BLOCKING,
+ INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
+ ASSERT_EQ(1u, wheel_event_queue().size());
+ ASSERT_EQ(WebInputEventQueueState::ITEM_PENDING, wheel_event_queue().state());
+}
+
+TEST_F(MainThreadEventQueueTest, NonBlockingTouch) {
+ SyntheticWebTouchEvent kEvents[4];
+ kEvents[0].PressPoint(10, 10);
+ kEvents[1].PressPoint(10, 10);
+ kEvents[1].modifiers = 1;
+ kEvents[1].MovePoint(0, 20, 20);
+ kEvents[2].PressPoint(10, 10);
+ kEvents[2].MovePoint(0, 30, 30);
+ kEvents[3].PressPoint(10, 10);
+ kEvents[3].MovePoint(0, 35, 35);
+
+ ASSERT_EQ(WebInputEventQueueState::ITEM_NOT_PENDING,
+ touch_event_queue().state());
+ queue_.HandleEvent(&kEvents[0], ui::LatencyInfo(), DISPATCH_TYPE_BLOCKING,
+ INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
+ ASSERT_EQ(WebInputEventQueueState::ITEM_PENDING, touch_event_queue().state());
+ queue_.HandleEvent(&kEvents[1], ui::LatencyInfo(), DISPATCH_TYPE_BLOCKING,
+ INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
+ ASSERT_EQ(kEvents[0].size, last_event_.size());
+ kEvents[0].dispatchType =
+ WebInputEvent::DispatchType::ListenersNonBlockingPassive;
+ ASSERT_TRUE(memcmp(&last_event_[0], &kEvents[0], kEvents[0].size) == 0);
+ queue_.EventHandled(blink::WebInputEvent::TouchStart);
+ ASSERT_EQ(kEvents[1].size, last_event_.size());
+ kEvents[1].dispatchType =
+ WebInputEvent::DispatchType::ListenersNonBlockingPassive;
+ ASSERT_TRUE(memcmp(&last_event_[0], &kEvents[1], kEvents[1].size) == 0);
+ ASSERT_EQ(WebInputEventQueueState::ITEM_PENDING, touch_event_queue().state());
+ queue_.EventHandled(blink::WebInputEvent::TouchMove);
+ ASSERT_EQ(WebInputEventQueueState::ITEM_NOT_PENDING,
+ touch_event_queue().state());
+
+ // Ensure that coalescing takes place.
+ queue_.HandleEvent(&kEvents[0], ui::LatencyInfo(), DISPATCH_TYPE_BLOCKING,
+ INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
+ queue_.HandleEvent(&kEvents[2], ui::LatencyInfo(), DISPATCH_TYPE_BLOCKING,
+ INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
+ queue_.HandleEvent(&kEvents[3], ui::LatencyInfo(), DISPATCH_TYPE_BLOCKING,
+ INPUT_EVENT_ACK_STATE_SET_NON_BLOCKING);
+ ASSERT_EQ(1u, touch_event_queue().size());
+ ASSERT_EQ(WebInputEventQueueState::ITEM_PENDING, touch_event_queue().state());
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/input/render_widget_input_handler.cc b/chromium/content/renderer/input/render_widget_input_handler.cc
index d5d5255c02f..751923c0864 100644
--- a/chromium/content/renderer/input/render_widget_input_handler.cc
+++ b/chromium/content/renderer/input/render_widget_input_handler.cc
@@ -9,6 +9,7 @@
#include <utility>
#include "base/auto_reset.h"
+#include "base/command_line.h"
#include "base/metrics/histogram_macros.h"
#include "base/trace_event/trace_event_synthetic_delay.h"
#include "build/build_config.h"
@@ -17,6 +18,7 @@
#include "content/common/input/input_event_ack.h"
#include "content/common/input/input_event_ack_state.h"
#include "content/common/input/web_input_event_traits.h"
+#include "content/public/common/content_switches.h"
#include "content/renderer/gpu/render_widget_compositor.h"
#include "content/renderer/ime_event_guard.h"
#include "content/renderer/input/render_widget_input_handler_delegate.h"
@@ -57,18 +59,17 @@ int64_t GetEventLatencyMicros(double event_timestamp, base::TimeTicks now) {
.ToInternalValue();
}
-void LogInputEventLatencyUmaImpl(WebInputEvent::Type event_type,
- double event_timestamp,
- base::TimeTicks now) {
- UMA_HISTOGRAM_CUSTOM_COUNTS("Event.AggregatedLatency.Renderer2",
- GetEventLatencyMicros(event_timestamp, now), 1,
- 10000000, 100);
-
-#define CASE_TYPE(t) \
- case WebInputEvent::t: \
- UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Renderer2." #t, \
- GetEventLatencyMicros(event_timestamp, now), \
- 1, 10000000, 100); \
+void LogInputEventLatencyUma(const WebInputEvent& event, base::TimeTicks now) {
+ WebInputEvent::Type event_type = event.type;
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Event.AggregatedLatency.Renderer2",
+ GetEventLatencyMicros(event.timeStampSeconds, now), 1, 10000000, 100);
+
+#define CASE_TYPE(t) \
+ case WebInputEvent::t: \
+ UMA_HISTOGRAM_CUSTOM_COUNTS( \
+ "Event.Latency.Renderer2." #t, \
+ GetEventLatencyMicros(event.timeStampSeconds, now), 1, 10000000, 100); \
break;
switch (event_type) {
@@ -115,24 +116,13 @@ void LogInputEventLatencyUmaImpl(WebInputEvent::Type event_type,
#undef CASE_TYPE
}
-void LogInputEventLatencyUma(const WebInputEvent& event,
- base::TimeTicks now,
- const ui::LatencyInfo& latency_info) {
- LogInputEventLatencyUmaImpl(event.type, event.timeStampSeconds, now);
- for (size_t i = 0; i < latency_info.coalesced_events_size(); i++) {
- LogInputEventLatencyUmaImpl(
- event.type, latency_info.timestamps_of_coalesced_events()[i], now);
- }
-}
-
void LogPassiveLatency(int64_t latency) {
UMA_HISTOGRAM_CUSTOM_COUNTS("Event.PassiveListeners.Latency", latency, 1,
10000000, 100);
}
void LogPassiveEventListenersUma(WebInputEventResult result,
- bool passive,
- bool cancelable,
+ WebInputEvent::DispatchType dispatch_type,
double event_timestamp,
const ui::LatencyInfo& latency_info) {
enum {
@@ -141,20 +131,33 @@ void LogPassiveEventListenersUma(WebInputEventResult result,
PASSIVE_LISTENER_UMA_ENUM_SUPPRESSED,
PASSIVE_LISTENER_UMA_ENUM_CANCELABLE,
PASSIVE_LISTENER_UMA_ENUM_CANCELABLE_AND_CANCELED,
+ PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING,
PASSIVE_LISTENER_UMA_ENUM_COUNT
};
int enum_value;
- if (passive)
- enum_value = PASSIVE_LISTENER_UMA_ENUM_PASSIVE;
- else if (!cancelable)
- enum_value = PASSIVE_LISTENER_UMA_ENUM_UNCANCELABLE;
- else if (result == WebInputEventResult::HandledApplication)
- enum_value = PASSIVE_LISTENER_UMA_ENUM_CANCELABLE_AND_CANCELED;
- else if (result == WebInputEventResult::HandledSuppressed)
- enum_value = PASSIVE_LISTENER_UMA_ENUM_SUPPRESSED;
- else
- enum_value = PASSIVE_LISTENER_UMA_ENUM_CANCELABLE;
+ switch (dispatch_type) {
+ case WebInputEvent::ListenersForcedNonBlockingPassive:
+ enum_value = PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING;
+ break;
+ case WebInputEvent::ListenersNonBlockingPassive:
+ enum_value = PASSIVE_LISTENER_UMA_ENUM_PASSIVE;
+ break;
+ case WebInputEvent::EventNonBlocking:
+ enum_value = PASSIVE_LISTENER_UMA_ENUM_UNCANCELABLE;
+ break;
+ case WebInputEvent::Blocking:
+ if (result == WebInputEventResult::HandledApplication)
+ enum_value = PASSIVE_LISTENER_UMA_ENUM_CANCELABLE_AND_CANCELED;
+ else if (result == WebInputEventResult::HandledSuppressed)
+ enum_value = PASSIVE_LISTENER_UMA_ENUM_SUPPRESSED;
+ else
+ enum_value = PASSIVE_LISTENER_UMA_ENUM_CANCELABLE;
+ break;
+ default:
+ NOTREACHED();
+ return;
+ }
UMA_HISTOGRAM_ENUMERATION("Event.PassiveListeners", enum_value,
PASSIVE_LISTENER_UMA_ENUM_COUNT);
@@ -163,9 +166,6 @@ void LogPassiveEventListenersUma(WebInputEventResult result,
base::TimeTicks::IsHighResolution()) {
base::TimeTicks now = base::TimeTicks::Now();
LogPassiveLatency(GetEventLatencyMicros(event_timestamp, now));
- for (size_t i = 0; i < latency_info.coalesced_events_size(); i++)
- LogPassiveLatency(GetEventLatencyMicros(
- latency_info.timestamps_of_coalesced_events()[i], now));
}
}
@@ -191,9 +191,8 @@ RenderWidgetInputHandler::~RenderWidgetInputHandler() {}
void RenderWidgetInputHandler::HandleInputEvent(
const WebInputEvent& input_event,
- const ui::LatencyInfo& latency_info) {
- // TODO(dtapuska): Passive support not implemented yet crbug.com/489802
- bool passive = false;
+ const ui::LatencyInfo& latency_info,
+ InputEventDispatchType dispatch_type) {
base::AutoReset<bool> handling_input_event_resetter(&handling_input_event_,
true);
base::AutoReset<WebInputEvent::Type> handling_event_type_resetter(
@@ -210,27 +209,30 @@ void RenderWidgetInputHandler::HandleInputEvent(
bool from_ime = false;
// For most keyboard events, we want the change source to be FROM_IME because
- // we don't need to update IME states in AdapterInputConnection.
- if (WebInputEvent::isKeyboardEventType(input_event.type)) {
+ // we don't need to update IME states in ReplicaInputConnection.
+ if (!widget_->IsUsingImeThread() &&
+ WebInputEvent::isKeyboardEventType(input_event.type)) {
const WebKeyboardEvent& key_event =
*static_cast<const WebKeyboardEvent*>(&input_event);
// TODO(changwan): this if-condition is a stop-gap solution to update IME
- // states in AdapterInputConnection when using DPAD navigation. This is not
+ // states in ReplicaInputConnection when using DPAD navigation. This is not
// a correct solution because InputConnection#getTextBeforeCursor()
// immediately after InputConnection#sendKeyEvent() will not return the
// correct value. The correct solution is either redesign the architecture
- // or emulate the DPAD behavior in AdapterInputConnection, either is
+ // or emulate the DPAD behavior in ReplicaInputConnection, either is
// non-trivial.
if (key_event.nativeKeyCode != AKEYCODE_TAB &&
key_event.nativeKeyCode != AKEYCODE_DPAD_CENTER &&
key_event.nativeKeyCode != AKEYCODE_DPAD_LEFT &&
key_event.nativeKeyCode != AKEYCODE_DPAD_RIGHT &&
key_event.nativeKeyCode != AKEYCODE_DPAD_UP &&
- key_event.nativeKeyCode != AKEYCODE_DPAD_DOWN)
+ key_event.nativeKeyCode != AKEYCODE_DPAD_DOWN) {
from_ime = true;
+ }
}
- ImeEventGuard guard(widget_, false, from_ime);
+ ImeEventGuard guard(widget_);
+ guard.set_from_ime(from_ime);
#endif
base::TimeTicks start_time;
@@ -249,10 +251,11 @@ void RenderWidgetInputHandler::HandleInputEvent(
// If we don't have a high res timer, these metrics won't be accurate enough
// to be worth collecting. Note that this does introduce some sampling bias.
if (!start_time.is_null())
- LogInputEventLatencyUma(input_event, start_time, latency_info);
+ LogInputEventLatencyUma(input_event, start_time);
scoped_ptr<cc::SwapPromiseMonitor> latency_info_swap_promise_monitor;
ui::LatencyInfo swap_latency_info(latency_info);
+
if (widget_->compositor()) {
latency_info_swap_promise_monitor =
widget_->compositor()->CreateLatencyInfoSwapPromiseMonitor(
@@ -294,7 +297,13 @@ void RenderWidgetInputHandler::HandleInputEvent(
if (WebInputEvent::isGestureEventType(input_event.type)) {
const WebGestureEvent& gesture_event =
static_cast<const WebGestureEvent&>(input_event);
- context_menu_source_type_ = ui::MENU_SOURCE_TOUCH;
+ if (input_event.type == WebInputEvent::GestureLongPress) {
+ context_menu_source_type_ = ui::MENU_SOURCE_LONG_PRESS;
+ } else if (input_event.type == WebInputEvent::GestureLongTap) {
+ context_menu_source_type_ = ui::MENU_SOURCE_LONG_TAP;
+ } else {
+ context_menu_source_type_ = ui::MENU_SOURCE_TOUCH;
+ }
prevent_default =
prevent_default || delegate_->WillHandleGestureEvent(gesture_event);
}
@@ -315,12 +324,13 @@ void RenderWidgetInputHandler::HandleInputEvent(
input_event.type == WebInputEvent::TouchMove ||
input_event.type == WebInputEvent::TouchEnd) {
LogPassiveEventListenersUma(
- processed, passive,
- static_cast<const WebTouchEvent&>(input_event).cancelable,
+ processed, static_cast<const WebTouchEvent&>(input_event).dispatchType,
input_event.timeStampSeconds, latency_info);
} else if (input_event.type == WebInputEvent::MouseWheel) {
- LogPassiveEventListenersUma(processed, passive, !passive,
- input_event.timeStampSeconds, latency_info);
+ LogPassiveEventListenersUma(
+ processed,
+ static_cast<const WebMouseWheelEvent&>(input_event).dispatchType,
+ input_event.timeStampSeconds, latency_info);
}
// If this RawKeyDown event corresponds to a browser keyboard shortcut and
@@ -356,11 +366,27 @@ void RenderWidgetInputHandler::HandleInputEvent(
// Send mouse wheel events and their disposition to the compositor thread, so
// that they can be used to produce the elastic overscroll effect on Mac.
if (input_event.type == WebInputEvent::MouseWheel) {
- delegate_->ObserveWheelEventAndResult(
- static_cast<const WebMouseWheelEvent&>(input_event),
- event_overscroll ? event_overscroll->latest_overscroll_delta
- : gfx::Vector2dF(),
- processed != WebInputEventResult::NotHandled);
+ const WebMouseWheelEvent& wheel_event =
+ static_cast<const WebMouseWheelEvent&>(input_event);
+ if (wheel_event.canScroll) {
+ delegate_->ObserveWheelEventAndResult(
+ wheel_event,
+ event_overscroll ? event_overscroll->latest_overscroll_delta
+ : gfx::Vector2dF(),
+ processed != WebInputEventResult::NotHandled);
+ }
+ } else if (input_event.type == WebInputEvent::GestureScrollBegin ||
+ input_event.type == WebInputEvent::GestureScrollEnd ||
+ input_event.type == WebInputEvent::GestureScrollUpdate) {
+ const WebGestureEvent& gesture_event =
+ static_cast<const WebGestureEvent&>(input_event);
+ if (gesture_event.sourceDevice == blink::WebGestureDeviceTouchpad) {
+ delegate_->ObserveGestureEventAndResult(
+ gesture_event,
+ event_overscroll ? event_overscroll->latest_overscroll_delta
+ : gfx::Vector2dF(),
+ processed != WebInputEventResult::NotHandled);
+ }
}
bool frame_pending =
@@ -382,9 +408,18 @@ void RenderWidgetInputHandler::HandleInputEvent(
// Note that we can't use handling_event_type_ here since it will be overriden
// by reentrant calls for events after the paused one.
- bool no_ack = ignore_ack_for_mouse_move_from_debugger_ &&
- input_event.type == WebInputEvent::MouseMove;
- if (WebInputEventTraits::WillReceiveAckFromRenderer(input_event) && !no_ack) {
+ bool can_send_ack = !(ignore_ack_for_mouse_move_from_debugger_ &&
+ input_event.type == WebInputEvent::MouseMove);
+ if (dispatch_type == DISPATCH_TYPE_BLOCKING_NOTIFY_MAIN ||
+ dispatch_type == DISPATCH_TYPE_NON_BLOCKING_NOTIFY_MAIN) {
+ // |non_blocking| means it was ack'd already by the InputHandlerProxy
+ // so let the delegate know the event has been handled.
+ delegate_->NotifyInputEventHandled(input_event.type);
+ }
+
+ if ((dispatch_type == DISPATCH_TYPE_BLOCKING ||
+ dispatch_type == DISPATCH_TYPE_BLOCKING_NOTIFY_MAIN) &&
+ can_send_ack) {
scoped_ptr<InputEventAck> response(new InputEventAck(
input_event.type, ack_result, swap_latency_info,
std::move(event_overscroll),
@@ -417,7 +452,7 @@ void RenderWidgetInputHandler::HandleInputEvent(
} else {
DCHECK(!event_overscroll) << "Unexpected overscroll for un-acked event";
}
- if (!no_ack && RenderThreadImpl::current()) {
+ if (can_send_ack && RenderThreadImpl::current()) {
RenderThreadImpl::current()
->GetRendererScheduler()
->DidHandleInputEventOnMainThread(input_event);
diff --git a/chromium/content/renderer/input/render_widget_input_handler.h b/chromium/content/renderer/input/render_widget_input_handler.h
index f8ff1d3fc63..a82968bfe3b 100644
--- a/chromium/content/renderer/input/render_widget_input_handler.h
+++ b/chromium/content/renderer/input/render_widget_input_handler.h
@@ -10,6 +10,7 @@
#include "base/time/time.h"
#include "content/common/input/did_overscroll_params.h"
#include "content/common/input/input_event_ack.h"
+#include "content/common/input/input_event_dispatch_type.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/base/ui_base_types.h"
@@ -33,11 +34,12 @@ class CONTENT_EXPORT RenderWidgetInputHandler {
public:
RenderWidgetInputHandler(RenderWidgetInputHandlerDelegate* delegate,
RenderWidget* widget);
- ~RenderWidgetInputHandler();
+ virtual ~RenderWidgetInputHandler();
// Handle input events from the input event provider.
- void HandleInputEvent(const blink::WebInputEvent& input_event,
- const ui::LatencyInfo& latency_info);
+ virtual void HandleInputEvent(const blink::WebInputEvent& input_event,
+ const ui::LatencyInfo& latency_info,
+ InputEventDispatchType dispatch_type);
// Handle overscroll from Blink.
void DidOverscrollFromBlink(
diff --git a/chromium/content/renderer/input/render_widget_input_handler_delegate.h b/chromium/content/renderer/input/render_widget_input_handler_delegate.h
index d00a080aa4f..9f49294c0eb 100644
--- a/chromium/content/renderer/input/render_widget_input_handler_delegate.h
+++ b/chromium/content/renderer/input/render_widget_input_handler_delegate.h
@@ -49,6 +49,13 @@ class CONTENT_EXPORT RenderWidgetInputHandlerDelegate {
const gfx::Vector2dF& wheel_unused_delta,
bool event_processed) = 0;
+ // Called to forward a gesture event to the compositor thread, to effect
+ // the elastic overscroll effect.
+ virtual void ObserveGestureEventAndResult(
+ const blink::WebGestureEvent& gesture_event,
+ const gfx::Vector2dF& unused_delta,
+ bool event_processed) = 0;
+
// Notifies that a key event was just handled.
virtual void OnDidHandleKeyEvent() = 0;
@@ -58,6 +65,12 @@ class CONTENT_EXPORT RenderWidgetInputHandlerDelegate {
// Called when an ACK is ready to be sent to the input event provider.
virtual void OnInputEventAck(scoped_ptr<InputEventAck> input_event_ack) = 0;
+ // Called when an event with a notify dispatch type
+ // (DISPATCH_TYPE_*_NOTIFY_MAIN) of |handled_type| has been processed
+ // by the main thread.
+ virtual void NotifyInputEventHandled(
+ blink::WebInputEvent::Type handled_type) = 0;
+
// Notifies the delegate of the |input_handler| managing it.
virtual void SetInputHandler(RenderWidgetInputHandler* input_handler) = 0;
diff --git a/chromium/content/renderer/internal_document_state_data.cc b/chromium/content/renderer/internal_document_state_data.cc
index d250853982f..cede79d4bf2 100644
--- a/chromium/content/renderer/internal_document_state_data.cc
+++ b/chromium/content/renderer/internal_document_state_data.cc
@@ -21,13 +21,12 @@ InternalDocumentStateData::InternalDocumentStateData()
is_overriding_user_agent_(false),
must_reset_scroll_and_scale_state_(false),
cache_policy_override_set_(false),
- cache_policy_override_(blink::WebURLRequest::UseProtocolCachePolicy) {
-}
+ cache_policy_override_(blink::WebCachePolicy::UseProtocolCachePolicy) {}
// static
InternalDocumentStateData* InternalDocumentStateData::FromDataSource(
blink::WebDataSource* ds) {
- return FromDocumentState(static_cast<DocumentState*>(ds->extraData()));
+ return FromDocumentState(static_cast<DocumentState*>(ds->getExtraData()));
}
// static
diff --git a/chromium/content/renderer/internal_document_state_data.h b/chromium/content/renderer/internal_document_state_data.h
index 23335a5d740..3963daeae34 100644
--- a/chromium/content/renderer/internal_document_state_data.h
+++ b/chromium/content/renderer/internal_document_state_data.h
@@ -10,11 +10,12 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/supports_user_data.h"
-#include "third_party/WebKit/public/platform/WebURLRequest.h"
+#include "third_party/WebKit/public/platform/WebCachePolicy.h"
#include "url/gurl.h"
namespace blink {
class WebDataSource;
+enum class WebCachePolicy;
}
namespace content {
@@ -61,17 +62,16 @@ class InternalDocumentStateData : public base::SupportsUserData::Data {
// Sets the cache policy. The cache policy is only used if explicitly set and
// by default is not set. You can mark a NavigationState as not having a cache
// state by way of clear_cache_policy_override.
- void set_cache_policy_override(
- blink::WebURLRequest::CachePolicy cache_policy) {
+ void set_cache_policy_override(blink::WebCachePolicy cache_policy) {
cache_policy_override_ = cache_policy;
cache_policy_override_set_ = true;
}
- blink::WebURLRequest::CachePolicy cache_policy_override() const {
+ blink::WebCachePolicy cache_policy_override() const {
return cache_policy_override_;
}
void clear_cache_policy_override() {
cache_policy_override_set_ = false;
- cache_policy_override_ = blink::WebURLRequest::UseProtocolCachePolicy;
+ cache_policy_override_ = blink::WebCachePolicy::UseProtocolCachePolicy;
}
bool is_cache_policy_override_set() const {
return cache_policy_override_set_;
@@ -87,7 +87,7 @@ class InternalDocumentStateData : public base::SupportsUserData::Data {
bool is_overriding_user_agent_;
bool must_reset_scroll_and_scale_state_;
bool cache_policy_override_set_;
- blink::WebURLRequest::CachePolicy cache_policy_override_;
+ blink::WebCachePolicy cache_policy_override_;
DISALLOW_COPY_AND_ASSIGN(InternalDocumentStateData);
};
diff --git a/chromium/content/renderer/java/gin_java_bridge_value_converter_unittest.cc b/chromium/content/renderer/java/gin_java_bridge_value_converter_unittest.cc
index 2de3e1242cb..33c3222771a 100644
--- a/chromium/content/renderer/java/gin_java_bridge_value_converter_unittest.cc
+++ b/chromium/content/renderer/java/gin_java_bridge_value_converter_unittest.cc
@@ -99,6 +99,8 @@ TEST_F(GinJavaBridgeValueConverterTest, TypedArrays) {
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
v8::Context::Scope context_scope(context);
+ v8::MicrotasksScope microtasks_scope(
+ isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks);
scoped_ptr<GinJavaBridgeValueConverter> converter(
new GinJavaBridgeValueConverter());
diff --git a/chromium/content/renderer/manifest/manifest_parser.cc b/chromium/content/renderer/manifest/manifest_parser.cc
index 8816ecba48e..a8f5520037b 100644
--- a/chromium/content/renderer/manifest/manifest_parser.cc
+++ b/chromium/content/renderer/manifest/manifest_parser.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include "base/json/json_reader.h"
+#include "base/memory/ptr_util.h"
#include "base/strings/nullable_string16.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
@@ -108,7 +109,7 @@ void ManifestParser::Parse() {
std::string error_msg;
int error_line = 0;
int error_column = 0;
- scoped_ptr<base::Value> value = base::JSONReader::ReadAndReturnError(
+ std::unique_ptr<base::Value> value = base::JSONReader::ReadAndReturnError(
data_, base::JSON_PARSE_RFC, nullptr, &error_msg, &error_line,
&error_column);
@@ -149,7 +150,7 @@ const Manifest& ManifestParser::manifest() const {
return manifest_;
}
-const std::vector<scoped_ptr<ManifestParser::ErrorInfo>>&
+const std::vector<std::unique_ptr<ManifestParser::ErrorInfo>>&
ManifestParser::errors() const {
return errors_;
}
@@ -460,6 +461,6 @@ void ManifestParser::AddErrorInfo(const std::string& error_msg,
int error_line,
int error_column) {
errors_.push_back(
- make_scoped_ptr(new ErrorInfo(error_msg, error_line, error_column)));
+ base::WrapUnique(new ErrorInfo(error_msg, error_line, error_column)));
}
} // namespace content
diff --git a/chromium/content/renderer/manifest/manifest_parser.h b/chromium/content/renderer/manifest/manifest_parser.h
index 5f683a0e634..86f24a51450 100644
--- a/chromium/content/renderer/manifest/manifest_parser.h
+++ b/chromium/content/renderer/manifest/manifest_parser.h
@@ -7,6 +7,8 @@
#include <stdint.h>
+#include <memory>
+
#include "base/macros.h"
#include "base/strings/nullable_string16.h"
#include "base/strings/string_piece.h"
@@ -46,7 +48,7 @@ class CONTENT_EXPORT ManifestParser {
void Parse();
const Manifest& manifest() const;
- const std::vector<scoped_ptr<ErrorInfo>>& errors() const;
+ const std::vector<std::unique_ptr<ErrorInfo>>& errors() const;
bool failed() const;
private:
@@ -203,7 +205,7 @@ class CONTENT_EXPORT ManifestParser {
bool failed_;
Manifest manifest_;
- std::vector<scoped_ptr<ErrorInfo>> errors_;
+ std::vector<std::unique_ptr<ErrorInfo>> errors_;
DISALLOW_COPY_AND_ASSIGN(ManifestParser);
};
diff --git a/chromium/content/renderer/manifest/manifest_parser_unittest.cc b/chromium/content/renderer/manifest/manifest_parser_unittest.cc
index cc5d1feaa28..9a8569d14b2 100644
--- a/chromium/content/renderer/manifest/manifest_parser_unittest.cc
+++ b/chromium/content/renderer/manifest/manifest_parser_unittest.cc
@@ -6,6 +6,8 @@
#include <stdint.h>
+#include <memory>
+
#include "base/macros.h"
#include "base/strings/string_util.h"
#include "content/public/common/manifest.h"
@@ -32,7 +34,7 @@ class ManifestParserTest : public testing::Test {
ManifestParser parser(data, document_url, manifest_url);
parser.Parse();
errors_.clear();
- for (const scoped_ptr<ManifestParser::ErrorInfo>& error_info :
+ for (const std::unique_ptr<ManifestParser::ErrorInfo>& error_info :
parser.errors()) {
errors_.push_back(error_info->error_msg);
}
diff --git a/chromium/content/renderer/media/DEPS b/chromium/content/renderer/media/DEPS
index c7f6f642fb7..8f7e9650f46 100644
--- a/chromium/content/renderer/media/DEPS
+++ b/chromium/content/renderer/media/DEPS
@@ -1,5 +1,5 @@
include_rules = [
- "+third_party/libvpx_new",
+ "+third_party/libvpx",
# For video copying, cropping and scaling.
# TODO(wuchengli): remove this when RTCVideoEncoder supports zero copy.
"+third_party/libyuv",
diff --git a/chromium/content/renderer/media/OWNERS b/chromium/content/renderer/media/OWNERS
index 69a9c2fe8c5..b4e0fd04a54 100644
--- a/chromium/content/renderer/media/OWNERS
+++ b/chromium/content/renderer/media/OWNERS
@@ -1,11 +1,6 @@
-dalecurtis@chromium.org
-ddorwin@chromium.org
-jrummell@chromium.org
+file://media/OWNERS
mcasas@chromium.org
miu@chromium.org
-sandersd@chromium.org
-wolenetz@chromium.org
-xhwang@chromium.org
# WebRTC OWNERS.
perkj@chromium.org
diff --git a/chromium/content/renderer/media/aec_dump_message_filter.h b/chromium/content/renderer/media/aec_dump_message_filter.h
index 0fb0cf93026..a211a8aebca 100644
--- a/chromium/content/renderer/media/aec_dump_message_filter.h
+++ b/chromium/content/renderer/media/aec_dump_message_filter.h
@@ -5,8 +5,9 @@
#ifndef CONTENT_RENDERER_MEDIA_AEC_DUMP_MESSAGE_FILTER_H_
#define CONTENT_RENDERER_MEDIA_AEC_DUMP_MESSAGE_FILTER_H_
+#include <memory>
+
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
#include "content/renderer/render_thread_impl.h"
#include "ipc/ipc_platform_file.h"
diff --git a/chromium/content/renderer/media/android/media_info_loader.cc b/chromium/content/renderer/media/android/media_info_loader.cc
index cf1764a6d3a..25a907f6656 100644
--- a/chromium/content/renderer/media/android/media_info_loader.cc
+++ b/chromium/content/renderer/media/android/media_info_loader.cc
@@ -59,7 +59,7 @@ void MediaInfoLoader::Start(blink::WebFrame* frame) {
// worse than the previous request+cancel code. See http://crbug.com/400788
request.addHTTPHeaderField("Range", "bytes=0-1");
- scoped_ptr<WebURLLoader> loader;
+ std::unique_ptr<WebURLLoader> loader;
if (test_loader_) {
loader = std::move(test_loader_);
} else {
diff --git a/chromium/content/renderer/media/android/media_info_loader.h b/chromium/content/renderer/media/android/media_info_loader.h
index d09ac136e93..99c35e2f932 100644
--- a/chromium/content/renderer/media/android/media_info_loader.h
+++ b/chromium/content/renderer/media/android/media_info_loader.h
@@ -7,11 +7,11 @@
#include <stdint.h>
+#include <memory>
#include <string>
#include "base/callback.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
#include "media/blink/active_loader.h"
@@ -106,10 +106,10 @@ class CONTENT_EXPORT MediaInfoLoader : private blink::WebURLLoaderClient {
void DidBecomeReady(Status status);
// Injected WebURLLoader instance for testing purposes.
- scoped_ptr<blink::WebURLLoader> test_loader_;
+ std::unique_ptr<blink::WebURLLoader> test_loader_;
// Keeps track of an active WebURLLoader and associated state.
- scoped_ptr<media::ActiveLoader> active_loader_;
+ std::unique_ptr<media::ActiveLoader> active_loader_;
bool loader_failed_;
GURL url_;
diff --git a/chromium/content/renderer/media/android/media_info_loader_unittest.cc b/chromium/content/renderer/media/android/media_info_loader_unittest.cc
index 8438924c492..306ccdb50b8 100644
--- a/chromium/content/renderer/media/android/media_info_loader_unittest.cc
+++ b/chromium/content/renderer/media/android/media_info_loader_unittest.cc
@@ -62,7 +62,7 @@ class MediaInfoLoaderTest : public testing::Test {
// |test_loader_| will be used when Start() is called.
url_loader_ = new NiceMock<MockWebURLLoader>();
- loader_->test_loader_ = scoped_ptr<blink::WebURLLoader>(url_loader_);
+ loader_->test_loader_ = std::unique_ptr<blink::WebURLLoader>(url_loader_);
}
void Start() {
@@ -112,7 +112,7 @@ class MediaInfoLoaderTest : public testing::Test {
protected:
GURL gurl_;
- scoped_ptr<MediaInfoLoader> loader_;
+ std::unique_ptr<MediaInfoLoader> loader_;
NiceMock<MockWebURLLoader>* url_loader_;
MockWebFrameClient client_;
diff --git a/chromium/content/renderer/media/android/media_source_delegate.cc b/chromium/content/renderer/media/android/media_source_delegate.cc
index 2d1831c3601..a642e6c49b9 100644
--- a/chromium/content/renderer/media/android/media_source_delegate.cc
+++ b/chromium/content/renderer/media/android/media_source_delegate.cc
@@ -9,6 +9,7 @@
#include <utility>
#include <vector>
+#include "base/callback_helpers.h"
#include "base/strings/string_number_conversions.h"
#include "base/thread_task_runner_handle.h"
#include "content/renderer/media/android/renderer_demuxer_android.h"
@@ -147,7 +148,7 @@ void MediaSourceDelegate::InitializeMediaSource(
const MediaSourceOpenedCB& media_source_opened_cb,
const media::Demuxer::EncryptedMediaInitDataCB&
encrypted_media_init_data_cb,
- const media::SetCdmReadyCB& set_cdm_ready_cb,
+ const SetCdmReadyCB& set_cdm_ready_cb,
const UpdateNetworkStateCB& update_network_state_cb,
const DurationChangeCB& duration_change_cb,
const base::Closure& waiting_for_decryption_key_cb) {
@@ -346,15 +347,16 @@ void MediaSourceDelegate::OnReadFromDemuxer(media::DemuxerStream::Type type) {
DCHECK(type == DemuxerStream::AUDIO || type == DemuxerStream::VIDEO);
// The access unit size should have been initialized properly at this stage.
DCHECK_GT(access_unit_size_, 0u);
- scoped_ptr<DemuxerData> data(new DemuxerData());
+ std::unique_ptr<DemuxerData> data(new DemuxerData());
data->type = type;
data->access_units.resize(access_unit_size_);
ReadFromDemuxerStream(type, std::move(data), 0);
}
-void MediaSourceDelegate::ReadFromDemuxerStream(media::DemuxerStream::Type type,
- scoped_ptr<DemuxerData> data,
- size_t index) {
+void MediaSourceDelegate::ReadFromDemuxerStream(
+ media::DemuxerStream::Type type,
+ std::unique_ptr<DemuxerData> data,
+ size_t index) {
DCHECK(media_task_runner_->BelongsToCurrentThread());
// DemuxerStream::Read() always returns the read callback asynchronously.
DemuxerStream* stream =
@@ -366,7 +368,7 @@ void MediaSourceDelegate::ReadFromDemuxerStream(media::DemuxerStream::Type type,
void MediaSourceDelegate::OnBufferReady(
media::DemuxerStream::Type type,
- scoped_ptr<DemuxerData> data,
+ std::unique_ptr<DemuxerData> data,
size_t index,
DemuxerStream::Status status,
const scoped_refptr<media::DecoderBuffer>& buffer) {
@@ -501,6 +503,38 @@ void MediaSourceDelegate::OnDemuxerInitDone(media::PipelineStatus status) {
audio_stream_ = chunk_demuxer_->GetStream(DemuxerStream::AUDIO);
video_stream_ = chunk_demuxer_->GetStream(DemuxerStream::VIDEO);
+ DCHECK(audio_stream_ || video_stream_);
+
+ if (HasEncryptedStream()) {
+ set_cdm_ready_cb_.Run(BindToCurrentLoop(base::Bind(
+ &MediaSourceDelegate::SetCdm, media_weak_factory_.GetWeakPtr())));
+ return;
+ }
+
+ // Notify demuxer ready when both streams are not encrypted.
+ NotifyDemuxerReady(false);
+}
+
+bool MediaSourceDelegate::HasEncryptedStream() {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+ DCHECK(audio_stream_ || video_stream_);
+
+ return (audio_stream_ &&
+ audio_stream_->audio_decoder_config().is_encrypted()) ||
+ (video_stream_ &&
+ video_stream_->video_decoder_config().is_encrypted());
+}
+
+void MediaSourceDelegate::SetCdm(media::CdmContext* cdm_context,
+ const media::CdmAttachedCB& cdm_attached_cb) {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+ DCHECK(cdm_context);
+ DCHECK(!cdm_attached_cb.is_null());
+ DCHECK(!is_demuxer_ready_);
+ DCHECK(HasEncryptedStream());
+
+ cdm_context_ = cdm_context;
+ pending_cdm_attached_cb_ = cdm_attached_cb;
if (audio_stream_ && audio_stream_->audio_decoder_config().is_encrypted()) {
InitAudioDecryptingDemuxerStream();
@@ -514,19 +548,17 @@ void MediaSourceDelegate::OnDemuxerInitDone(media::PipelineStatus status) {
return;
}
- // Notify demuxer ready when both streams are not encrypted.
- is_demuxer_ready_ = true;
- NotifyDemuxerReady();
+ NOTREACHED() << "No encrytped stream.";
}
void MediaSourceDelegate::InitAudioDecryptingDemuxerStream() {
DCHECK(media_task_runner_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
- DCHECK(!set_cdm_ready_cb_.is_null());
+ DCHECK(cdm_context_);
audio_decrypting_demuxer_stream_.reset(new media::DecryptingDemuxerStream(
media_task_runner_, media_log_, waiting_for_decryption_key_cb_));
audio_decrypting_demuxer_stream_->Initialize(
- audio_stream_, set_cdm_ready_cb_,
+ audio_stream_, cdm_context_,
base::Bind(&MediaSourceDelegate::OnAudioDecryptingDemuxerStreamInitDone,
media_weak_factory_.GetWeakPtr()));
}
@@ -534,12 +566,12 @@ void MediaSourceDelegate::InitAudioDecryptingDemuxerStream() {
void MediaSourceDelegate::InitVideoDecryptingDemuxerStream() {
DCHECK(media_task_runner_->BelongsToCurrentThread());
DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
- DCHECK(!set_cdm_ready_cb_.is_null());
+ DCHECK(cdm_context_);
video_decrypting_demuxer_stream_.reset(new media::DecryptingDemuxerStream(
media_task_runner_, media_log_, waiting_for_decryption_key_cb_));
video_decrypting_demuxer_stream_->Initialize(
- video_stream_, set_cdm_ready_cb_,
+ video_stream_, cdm_context_,
base::Bind(&MediaSourceDelegate::OnVideoDecryptingDemuxerStreamInitDone,
media_weak_factory_.GetWeakPtr()));
}
@@ -560,8 +592,7 @@ void MediaSourceDelegate::OnAudioDecryptingDemuxerStreamInitDone(
// now to try that path. Note there's no need to try DecryptingDemuxerStream
// for video here since it is impossible to handle audio in the browser and
// handle video in the render process.
- is_demuxer_ready_ = true;
- NotifyDemuxerReady();
+ NotifyDemuxerReady(false);
return;
}
@@ -574,8 +605,7 @@ void MediaSourceDelegate::OnAudioDecryptingDemuxerStreamInitDone(
// Try to notify demuxer ready when audio DDS initialization finished and
// video is not encrypted.
- is_demuxer_ready_ = true;
- NotifyDemuxerReady();
+ NotifyDemuxerReady(true);
}
void MediaSourceDelegate::OnVideoDecryptingDemuxerStreamInitDone(
@@ -584,14 +614,15 @@ void MediaSourceDelegate::OnVideoDecryptingDemuxerStreamInitDone(
DVLOG(1) << __FUNCTION__ << "(" << status << ") : " << demuxer_client_id_;
DCHECK(chunk_demuxer_);
- if (status != media::PIPELINE_OK)
+ bool success = status == media::PIPELINE_OK;
+
+ if (!success)
video_decrypting_demuxer_stream_.reset();
else
video_stream_ = video_decrypting_demuxer_stream_.get();
// Try to notify demuxer ready when video DDS initialization finished.
- is_demuxer_ready_ = true;
- NotifyDemuxerReady();
+ NotifyDemuxerReady(success);
}
void MediaSourceDelegate::OnDemuxerSeekDone(media::PipelineStatus status) {
@@ -644,12 +675,18 @@ void MediaSourceDelegate::FinishResettingDecryptingDemuxerStreams() {
demuxer_client_->DemuxerSeekDone(demuxer_client_id_, browser_seek_time_);
}
-void MediaSourceDelegate::NotifyDemuxerReady() {
+void MediaSourceDelegate::NotifyDemuxerReady(bool is_cdm_attached) {
DCHECK(media_task_runner_->BelongsToCurrentThread());
- DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_;
- DCHECK(is_demuxer_ready_);
+ DVLOG(1) << __FUNCTION__ << " : " << demuxer_client_id_
+ << ", is_cdm_attached: " << is_cdm_attached;
+ DCHECK(!is_demuxer_ready_);
+
+ is_demuxer_ready_ = true;
+
+ if (!pending_cdm_attached_cb_.is_null())
+ base::ResetAndReturn(&pending_cdm_attached_cb_).Run(is_cdm_attached);
- scoped_ptr<DemuxerConfigs> configs(new DemuxerConfigs());
+ std::unique_ptr<DemuxerConfigs> configs(new DemuxerConfigs());
GetDemuxerConfigFromStream(configs.get(), true);
GetDemuxerConfigFromStream(configs.get(), false);
configs->duration = GetDuration();
diff --git a/chromium/content/renderer/media/android/media_source_delegate.h b/chromium/content/renderer/media/android/media_source_delegate.h
index 6d9719cd4ea..f3b7e37eac1 100644
--- a/chromium/content/renderer/media/android/media_source_delegate.h
+++ b/chromium/content/renderer/media/android/media_source_delegate.h
@@ -8,13 +8,13 @@
#include <stddef.h>
#include <stdint.h>
+#include <memory>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "media/base/cdm_context.h"
@@ -51,6 +51,14 @@ class MediaSourceDelegate : public media::DemuxerHost {
UpdateNetworkStateCB;
typedef base::Callback<void(const base::TimeDelta&)> DurationChangeCB;
+ // Callback to notify that a CDM is ready. CdmAttachedCB is called when the
+ // CDM has been completely attached to the media pipeline.
+ typedef base::Callback<void(media::CdmContext*, const media::CdmAttachedCB&)>
+ CdmReadyCB;
+
+ // Callback to set a CdmReadyCB, which will be called when a CDM is ready.
+ typedef base::Callback<void(const CdmReadyCB&)> SetCdmReadyCB;
+
MediaSourceDelegate(
RendererDemuxerAndroid* demuxer_client,
int demuxer_client_id,
@@ -64,7 +72,7 @@ class MediaSourceDelegate : public media::DemuxerHost {
const MediaSourceOpenedCB& media_source_opened_cb,
const media::Demuxer::EncryptedMediaInitDataCB&
encrypted_media_init_data_cb,
- const media::SetCdmReadyCB& set_cdm_ready_cb,
+ const SetCdmReadyCB& set_cdm_ready_cb,
const UpdateNetworkStateCB& update_network_state_cb,
const DurationChangeCB& duration_change_cb,
const base::Closure& waiting_for_decryption_key_cb);
@@ -124,6 +132,12 @@ class MediaSourceDelegate : public media::DemuxerHost {
// Callback for ChunkDemuxer initialization.
void OnDemuxerInitDone(media::PipelineStatus status);
+ bool HasEncryptedStream();
+
+ // Callback to set CDM and fires |cdm_attached_cb| with the result.
+ void SetCdm(media::CdmContext* cdm_context,
+ const media::CdmAttachedCB& cdm_attached_cb);
+
// Initializes DecryptingDemuxerStreams if audio/video stream is encrypted.
void InitAudioDecryptingDemuxerStream();
void InitVideoDecryptingDemuxerStream();
@@ -144,7 +158,7 @@ class MediaSourceDelegate : public media::DemuxerHost {
void OnDemuxerOpened();
void OnEncryptedMediaInitData(media::EmeInitDataType init_data_type,
const std::vector<uint8_t>& init_data);
- void NotifyDemuxerReady();
+ void NotifyDemuxerReady(bool is_cdm_attached);
// Stops and clears objects on the media thread.
void StopDemuxer(const base::Closure& stop_cb);
@@ -154,10 +168,10 @@ class MediaSourceDelegate : public media::DemuxerHost {
// Reads an access unit from the demuxer stream |stream| and stores it in
// the |index|th access unit in |params|.
void ReadFromDemuxerStream(media::DemuxerStream::Type type,
- scoped_ptr<media::DemuxerData> data,
+ std::unique_ptr<media::DemuxerData> data,
size_t index);
void OnBufferReady(media::DemuxerStream::Type type,
- scoped_ptr<media::DemuxerData> data,
+ std::unique_ptr<media::DemuxerData> data,
size_t index,
media::DemuxerStream::Status status,
const scoped_refptr<media::DecoderBuffer>& buffer);
@@ -187,13 +201,17 @@ class MediaSourceDelegate : public media::DemuxerHost {
UpdateNetworkStateCB update_network_state_cb_;
DurationChangeCB duration_change_cb_;
- scoped_ptr<media::ChunkDemuxer> chunk_demuxer_;
+ std::unique_ptr<media::ChunkDemuxer> chunk_demuxer_;
bool is_demuxer_ready_;
- media::SetCdmReadyCB set_cdm_ready_cb_;
+ SetCdmReadyCB set_cdm_ready_cb_;
+ media::CdmContext* cdm_context_;
+ media::CdmAttachedCB pending_cdm_attached_cb_;
- scoped_ptr<media::DecryptingDemuxerStream> audio_decrypting_demuxer_stream_;
- scoped_ptr<media::DecryptingDemuxerStream> video_decrypting_demuxer_stream_;
+ std::unique_ptr<media::DecryptingDemuxerStream>
+ audio_decrypting_demuxer_stream_;
+ std::unique_ptr<media::DecryptingDemuxerStream>
+ video_decrypting_demuxer_stream_;
media::DemuxerStream* audio_stream_;
media::DemuxerStream* video_stream_;
diff --git a/chromium/content/renderer/media/android/renderer_media_player_manager.cc b/chromium/content/renderer/media/android/renderer_media_player_manager.cc
index 3c054fcac32..a115772c0bc 100644
--- a/chromium/content/renderer/media/android/renderer_media_player_manager.cc
+++ b/chromium/content/renderer/media/android/renderer_media_player_manager.cc
@@ -51,6 +51,8 @@ bool RendererMediaPlayerManager::OnMessageReceived(const IPC::Message& msg) {
OnConnectedToRemoteDevice)
IPC_MESSAGE_HANDLER(MediaPlayerMsg_DisconnectedFromRemoteDevice,
OnDisconnectedFromRemoteDevice)
+ IPC_MESSAGE_HANDLER(MediaPlayerMsg_CancelledRemotePlaybackRequest,
+ OnCancelledRemotePlaybackRequest)
IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidExitFullscreen, OnDidExitFullscreen)
IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidMediaPlayerPlay, OnPlayerPlay)
IPC_MESSAGE_HANDLER(MediaPlayerMsg_DidMediaPlayerPause, OnPlayerPause)
@@ -61,22 +63,6 @@ bool RendererMediaPlayerManager::OnMessageReceived(const IPC::Message& msg) {
return handled;
}
-void RendererMediaPlayerManager::WasHidden() {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableMediaSuspend)) {
- return;
- }
-
- // Suspend and release resources of all playing video.
- for (auto& player_it : media_players_) {
- media::RendererMediaPlayerInterface* player = player_it.second;
- if (!player || player->paused() || !player->hasVideo())
- continue;
-
- player->SuspendAndReleaseResources();
- }
-}
-
void RendererMediaPlayerManager::Initialize(
MediaPlayerHostMsg_Initialize_Type type,
int player_id,
@@ -84,7 +70,9 @@ void RendererMediaPlayerManager::Initialize(
const GURL& first_party_for_cookies,
int demuxer_client_id,
const GURL& frame_url,
- bool allow_credentials) {
+ bool allow_credentials,
+ int delegate_id,
+ int media_session_id) {
MediaPlayerHostMsg_Initialize_Params media_player_params;
media_player_params.type = type;
media_player_params.player_id = player_id;
@@ -93,6 +81,8 @@ void RendererMediaPlayerManager::Initialize(
media_player_params.first_party_for_cookies = first_party_for_cookies;
media_player_params.frame_url = frame_url;
media_player_params.allow_credentials = allow_credentials;
+ media_player_params.delegate_id = delegate_id;
+ media_player_params.media_session_id = media_session_id;
Send(new MediaPlayerHostMsg_Initialize(routing_id(), media_player_params));
}
@@ -227,6 +217,13 @@ void RendererMediaPlayerManager::OnDisconnectedFromRemoteDevice(int player_id) {
player->OnDisconnectedFromRemoteDevice();
}
+void RendererMediaPlayerManager::OnCancelledRemotePlaybackRequest(
+ int player_id) {
+ media::RendererMediaPlayerInterface* player = GetMediaPlayer(player_id);
+ if (player)
+ player->OnCancelledRemotePlaybackRequest();
+}
+
void RendererMediaPlayerManager::OnDidExitFullscreen(int player_id) {
media::RendererMediaPlayerInterface* player = GetMediaPlayer(player_id);
if (player)
diff --git a/chromium/content/renderer/media/android/renderer_media_player_manager.h b/chromium/content/renderer/media/android/renderer_media_player_manager.h
index b4eb44be7c9..2baa846a0ad 100644
--- a/chromium/content/renderer/media/android/renderer_media_player_manager.h
+++ b/chromium/content/renderer/media/android/renderer_media_player_manager.h
@@ -40,7 +40,6 @@ class RendererMediaPlayerManager :
// RenderFrameObserver overrides.
bool OnMessageReceived(const IPC::Message& msg) override;
- void WasHidden() override;
// Initializes a MediaPlayerAndroid object in browser process.
void Initialize(MediaPlayerHostMsg_Initialize_Type type,
@@ -49,7 +48,9 @@ class RendererMediaPlayerManager :
const GURL& first_party_for_cookies,
int demuxer_client_id,
const GURL& frame_url,
- bool allow_credentials) override;
+ bool allow_credentials,
+ int delegate_id,
+ int media_session_id) override;
// Starts the player.
void Start(int player_id) override;
@@ -136,6 +137,7 @@ class RendererMediaPlayerManager :
void OnConnectedToRemoteDevice(int player_id,
const std::string& remote_playback_message);
void OnDisconnectedFromRemoteDevice(int player_id);
+ void OnCancelledRemotePlaybackRequest(int player_id);
void OnDidExitFullscreen(int player_id);
void OnDidEnterFullscreen(int player_id);
void OnPlayerPlay(int player_id);
diff --git a/chromium/content/renderer/media/android/renderer_media_session_manager.cc b/chromium/content/renderer/media/android/renderer_media_session_manager.cc
index 58b0888f568..93d19281f94 100644
--- a/chromium/content/renderer/media/android/renderer_media_session_manager.cc
+++ b/chromium/content/renderer/media/android/renderer_media_session_manager.cc
@@ -6,17 +6,16 @@
#include "base/logging.h"
#include "content/common/media/media_session_messages_android.h"
+#include "content/public/common/media_metadata.h"
#include "content/public/renderer/render_thread.h"
#include "content/renderer/media/android/webmediasession_android.h"
namespace content {
-static const int kDefaultMediaSessionID = 0;
-
RendererMediaSessionManager::RendererMediaSessionManager(
RenderFrame* render_frame)
: RenderFrameObserver(render_frame),
- next_session_id_(kDefaultMediaSessionID + 1) {}
+ next_session_id_(blink::WebMediaSession::DefaultID + 1) {}
RendererMediaSessionManager::~RendererMediaSessionManager() {
DCHECK(sessions_.empty())
@@ -46,19 +45,36 @@ void RendererMediaSessionManager::UnregisterMediaSession(int session_id) {
void RendererMediaSessionManager::Activate(
int session_id,
- scoped_ptr<blink::WebMediaSessionActivateCallback> callback) {
+ std::unique_ptr<blink::WebMediaSessionActivateCallback> callback) {
int request_id = pending_activation_requests_.Add(callback.release());
Send(new MediaSessionHostMsg_Activate(routing_id(), session_id, request_id));
}
void RendererMediaSessionManager::Deactivate(
int session_id,
- scoped_ptr<blink::WebMediaSessionDeactivateCallback> callback) {
+ std::unique_ptr<blink::WebMediaSessionDeactivateCallback> callback) {
int request_id = pending_deactivation_requests_.Add(callback.release());
Send(
new MediaSessionHostMsg_Deactivate(routing_id(), session_id, request_id));
}
+void RendererMediaSessionManager::SetMetadata(
+ int session_id,
+ const MediaMetadata& metadata) {
+ // Apply some sanity checks on the MediaMetadata before sending over IPC.
+ MediaMetadata ipc_metadata;
+ ipc_metadata.title =
+ metadata.title.substr(0, MediaMetadata::kMaxIPCStringLength);
+ ipc_metadata.artist =
+ metadata.artist.substr(0, MediaMetadata::kMaxIPCStringLength);
+ ipc_metadata.album =
+ metadata.album.substr(0, MediaMetadata::kMaxIPCStringLength);
+
+ Send(new MediaSessionHostMsg_SetMetadata(routing_id(),
+ session_id,
+ ipc_metadata));
+}
+
void RendererMediaSessionManager::OnDidActivate(int request_id, bool success) {
DCHECK(pending_activation_requests_.Lookup(request_id)) << request_id;
blink::WebMediaSessionActivateCallback* callback =
diff --git a/chromium/content/renderer/media/android/renderer_media_session_manager.h b/chromium/content/renderer/media/android/renderer_media_session_manager.h
index c7f7504430a..bc1808c3feb 100644
--- a/chromium/content/renderer/media/android/renderer_media_session_manager.h
+++ b/chromium/content/renderer/media/android/renderer_media_session_manager.h
@@ -6,6 +6,7 @@
#define CONTENT_RENDERER_MEDIA_ANDROID_RENDERER_MEDIA_SESSION_MANAGER_H_
#include <map>
+#include <memory>
#include "base/id_map.h"
#include "base/macros.h"
@@ -16,6 +17,7 @@
namespace content {
class WebMediaSessionAndroid;
+struct MediaMetadata;
class CONTENT_EXPORT RendererMediaSessionManager : public RenderFrameObserver {
public:
@@ -28,11 +30,13 @@ class CONTENT_EXPORT RendererMediaSessionManager : public RenderFrameObserver {
int RegisterMediaSession(WebMediaSessionAndroid* session);
void UnregisterMediaSession(int session_id);
- void Activate(int session_id,
- scoped_ptr<blink::WebMediaSessionActivateCallback> callback);
+ void Activate(
+ int session_id,
+ std::unique_ptr<blink::WebMediaSessionActivateCallback> callback);
void Deactivate(
int session_id,
- scoped_ptr<blink::WebMediaSessionDeactivateCallback> callback);
+ std::unique_ptr<blink::WebMediaSessionDeactivateCallback> callback);
+ void SetMetadata(int session_id, const MediaMetadata& metadata);
void OnDidActivate(int request_id, bool success);
void OnDidDeactivate(int request_id);
diff --git a/chromium/content/renderer/media/android/renderer_surface_view_manager.cc b/chromium/content/renderer/media/android/renderer_surface_view_manager.cc
new file mode 100644
index 00000000000..6f54b1e30a1
--- /dev/null
+++ b/chromium/content/renderer/media/android/renderer_surface_view_manager.cc
@@ -0,0 +1,50 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/android/renderer_surface_view_manager.h"
+
+#include "content/common/media/surface_view_manager_messages_android.h"
+#include "ipc/ipc_message_macros.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace content {
+
+RendererSurfaceViewManager::RendererSurfaceViewManager(
+ RenderFrame* render_frame)
+ : RenderFrameObserver(render_frame) {}
+
+RendererSurfaceViewManager::~RendererSurfaceViewManager() {}
+
+bool RendererSurfaceViewManager::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(RendererSurfaceViewManager, msg)
+ IPC_MESSAGE_HANDLER(SurfaceViewManagerMsg_FullscreenSurfaceCreated,
+ OnFullscreenSurfaceCreated)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void RendererSurfaceViewManager::CreateFullscreenSurface(
+ const gfx::Size& video_natural_size,
+ const media::SurfaceCreatedCB& surface_created_cb) {
+ DCHECK(!surface_created_cb.is_null());
+ pending_surface_created_cb_ = surface_created_cb;
+ Send(new SurfaceViewManagerHostMsg_CreateFullscreenSurface(
+ routing_id(), video_natural_size));
+}
+
+void RendererSurfaceViewManager::NaturalSizeChanged(const gfx::Size& size) {
+ DVLOG(3) << __FUNCTION__ << ": size: " << size.ToString();
+ Send(new SurfaceViewManagerHostMsg_NaturalSizeChanged(routing_id(), size));
+}
+
+void RendererSurfaceViewManager::OnFullscreenSurfaceCreated(int surface_id) {
+ DVLOG(3) << __FUNCTION__ << ": surface_id: " << surface_id;
+ DCHECK(!pending_surface_created_cb_.is_null());
+ pending_surface_created_cb_.Run(surface_id);
+ pending_surface_created_cb_.Reset();
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/android/renderer_surface_view_manager.h b/chromium/content/renderer/media/android/renderer_surface_view_manager.h
new file mode 100644
index 00000000000..7022744bae1
--- /dev/null
+++ b/chromium/content/renderer/media/android/renderer_surface_view_manager.h
@@ -0,0 +1,46 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_ANDROID_RENDERER_SURFACE_VIEW_MANAGER_H_
+#define CONTENT_RENDERER_MEDIA_ANDROID_RENDERER_SURFACE_VIEW_MANAGER_H_
+
+#include "base/callback.h"
+#include "content/common/content_export.h"
+#include "content/public/renderer/render_frame_observer.h"
+#include "media/base/surface_manager.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace content {
+
+// RendererSurfaceViewManager creates delegates requests for video SurfaceViews
+// to BrowserSurfaceViewManager. The returned surface ids may be invalidated
+// at any time (e.g., when the app is backgrounded), so clients should handle
+// this gracefully. It should be created and used on a single thread only.
+class CONTENT_EXPORT RendererSurfaceViewManager : public media::SurfaceManager,
+ public RenderFrameObserver {
+ public:
+ explicit RendererSurfaceViewManager(RenderFrame* render_frame);
+ ~RendererSurfaceViewManager() override;
+
+ // RenderFrameObserver override.
+ bool OnMessageReceived(const IPC::Message& msg) override;
+
+ // SurfaceManager overrides.
+ void CreateFullscreenSurface(
+ const gfx::Size& video_natural_size,
+ const media::SurfaceCreatedCB& surface_created_cb) override;
+ void NaturalSizeChanged(const gfx::Size& size) override;
+
+ private:
+ void OnFullscreenSurfaceCreated(int surface_id);
+
+ // Set when a surface request is in progress.
+ media::SurfaceCreatedCB pending_surface_created_cb_;
+
+ DISALLOW_COPY_AND_ASSIGN(RendererSurfaceViewManager);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_ANDROID_RENDERER_SURFACE_VIEW_MANAGER_H_
diff --git a/chromium/content/renderer/media/android/stream_texture_factory.h b/chromium/content/renderer/media/android/stream_texture_factory.h
index 87977cf1fc6..d9c7323759c 100644
--- a/chromium/content/renderer/media/android/stream_texture_factory.h
+++ b/chromium/content/renderer/media/android/stream_texture_factory.h
@@ -7,8 +7,9 @@
#include <stdint.h>
+#include <memory>
+
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/single_thread_task_runner.h"
#include "cc/layers/video_frame_provider.h"
#include "gpu/command_buffer/common/mailbox.h"
@@ -43,7 +44,7 @@ class StreamTextureProxy {
};
};
-typedef scoped_ptr<StreamTextureProxy, StreamTextureProxy::Deleter>
+typedef std::unique_ptr<StreamTextureProxy, StreamTextureProxy::Deleter>
ScopedStreamTextureProxy;
class StreamTextureFactoryContextObserver {
@@ -66,8 +67,8 @@ class StreamTextureFactory : public base::RefCounted<StreamTextureFactory> {
int player_id,
int frame_id) = 0;
- // Creates a StreamTexture and returns its id. Sets |*texture_id| to the
- // client-side id of the StreamTexture. The texture is produced into
+ // Creates a gpu::StreamTexture and returns its id. Sets |*texture_id| to the
+ // client-side id of the gpu::StreamTexture. The texture is produced into
// a mailbox so it can be shipped in a VideoFrame.
virtual unsigned CreateStreamTexture(unsigned texture_target,
unsigned* texture_id,
diff --git a/chromium/content/renderer/media/android/stream_texture_factory_impl.cc b/chromium/content/renderer/media/android/stream_texture_factory_impl.cc
index 945442e8ba4..e79faa7e352 100644
--- a/chromium/content/renderer/media/android/stream_texture_factory_impl.cc
+++ b/chromium/content/renderer/media/android/stream_texture_factory_impl.cc
@@ -7,10 +7,10 @@
#include "base/macros.h"
#include "cc/output/context_provider.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
-#include "content/common/gpu/client/gpu_channel_host.h"
-#include "content/common/gpu/gpu_messages.h"
#include "content/renderer/gpu/stream_texture_host_android.h"
#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/ipc/client/gpu_channel_host.h"
+#include "gpu/ipc/common/gpu_messages.h"
#include "ui/gfx/geometry/size.h"
namespace content {
@@ -31,12 +31,11 @@ class StreamTextureProxyImpl : public StreamTextureProxy,
// StreamTextureHost::Listener implementation:
void OnFrameAvailable() override;
- void OnMatrixChanged(const float matrix[16]) override;
private:
void BindOnThread(int32_t stream_id);
- const scoped_ptr<StreamTextureHost> host_;
+ const std::unique_ptr<StreamTextureHost> host_;
// Protects access to |client_| and |loop_|.
base::Lock lock_;
@@ -102,24 +101,18 @@ void StreamTextureProxyImpl::OnFrameAvailable() {
client_->DidReceiveFrame();
}
-void StreamTextureProxyImpl::OnMatrixChanged(const float matrix[16]) {
- base::AutoLock lock(lock_);
- if (client_)
- client_->DidUpdateMatrix(matrix);
-}
-
} // namespace
// static
scoped_refptr<StreamTextureFactoryImpl> StreamTextureFactoryImpl::Create(
const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
- GpuChannelHost* channel) {
+ gpu::GpuChannelHost* channel) {
return new StreamTextureFactoryImpl(context_provider, channel);
}
StreamTextureFactoryImpl::StreamTextureFactoryImpl(
const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
- GpuChannelHost* channel)
+ gpu::GpuChannelHost* channel)
: context_provider_(context_provider), channel_(channel) {
DCHECK(channel);
}
diff --git a/chromium/content/renderer/media/android/stream_texture_factory_impl.h b/chromium/content/renderer/media/android/stream_texture_factory_impl.h
index 648f70fbced..e07122d1237 100644
--- a/chromium/content/renderer/media/android/stream_texture_factory_impl.h
+++ b/chromium/content/renderer/media/android/stream_texture_factory_impl.h
@@ -18,18 +18,18 @@ namespace gpu {
namespace gles2 {
class GLES2Interface;
} // namespace gles2
+class GpuChannelHost;
} // namespace gpu
namespace content {
class ContextProviderCommandBuffer;
-class GpuChannelHost;
class StreamTextureFactoryImpl : public StreamTextureFactory {
public:
static scoped_refptr<StreamTextureFactoryImpl> Create(
const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
- GpuChannelHost* channel);
+ gpu::GpuChannelHost* channel);
// StreamTextureFactory implementation.
StreamTextureProxy* CreateProxy() override;
@@ -46,11 +46,11 @@ class StreamTextureFactoryImpl : public StreamTextureFactory {
friend class base::RefCounted<StreamTextureFactoryImpl>;
StreamTextureFactoryImpl(
const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
- GpuChannelHost* channel);
+ gpu::GpuChannelHost* channel);
~StreamTextureFactoryImpl() override;
- scoped_refptr<content::ContextProviderCommandBuffer> context_provider_;
- scoped_refptr<GpuChannelHost> channel_;
+ scoped_refptr<ContextProviderCommandBuffer> context_provider_;
+ scoped_refptr<gpu::GpuChannelHost> channel_;
DISALLOW_IMPLICIT_CONSTRUCTORS(StreamTextureFactoryImpl);
};
diff --git a/chromium/content/renderer/media/android/stream_texture_factory_synchronous_impl.cc b/chromium/content/renderer/media/android/stream_texture_factory_synchronous_impl.cc
index 44ae072b447..513432a7e7c 100644
--- a/chromium/content/renderer/media/android/stream_texture_factory_synchronous_impl.cc
+++ b/chromium/content/renderer/media/android/stream_texture_factory_synchronous_impl.cc
@@ -15,9 +15,9 @@
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
#include "cc/output/context_provider.h"
-#include "content/common/android/surface_texture_peer.h"
#include "content/renderer/render_thread_impl.h"
#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/ipc/common/android/surface_texture_peer.h"
#include "ui/gl/android/surface_texture.h"
using gpu::gles2::GLES2Interface;
@@ -54,16 +54,13 @@ class StreamTextureProxyImpl
scoped_refptr<StreamTextureFactorySynchronousImpl::ContextProvider>
context_provider_;
scoped_refptr<gfx::SurfaceTexture> surface_texture_;
- float current_matrix_[16];
- bool has_updated_;
DISALLOW_IMPLICIT_CONSTRUCTORS(StreamTextureProxyImpl);
};
StreamTextureProxyImpl::StreamTextureProxyImpl(
StreamTextureFactorySynchronousImpl::ContextProvider* provider)
- : client_(NULL), context_provider_(provider), has_updated_(false) {
- std::fill(current_matrix_, current_matrix_ + 16, 0);
+ : client_(NULL), context_provider_(provider) {
}
StreamTextureProxyImpl::~StreamTextureProxyImpl() {}
@@ -122,25 +119,6 @@ void StreamTextureProxyImpl::BindOnThread(int32_t stream_id) {
}
void StreamTextureProxyImpl::OnFrameAvailable() {
- // GetTransformMatrix only returns something valid after both is true:
- // - OnFrameAvailable was called
- // - we called UpdateTexImage
- if (has_updated_) {
- float matrix[16];
- surface_texture_->GetTransformMatrix(matrix);
-
- if (memcmp(current_matrix_, matrix, sizeof(matrix)) != 0) {
- memcpy(current_matrix_, matrix, sizeof(matrix));
-
- base::AutoLock lock(lock_);
- if (client_)
- client_->DidUpdateMatrix(current_matrix_);
- }
- }
- // OnFrameAvailable being called a second time implies that we called
- // updateTexImage since after we received the first frame.
- has_updated_ = true;
-
base::AutoLock lock(lock_);
if (client_)
client_->DidReceiveFrame();
@@ -151,18 +129,13 @@ void StreamTextureProxyImpl::OnFrameAvailable() {
// static
scoped_refptr<StreamTextureFactorySynchronousImpl>
StreamTextureFactorySynchronousImpl::Create(
- const CreateContextProviderCallback& try_create_callback,
- int frame_id) {
- return new StreamTextureFactorySynchronousImpl(try_create_callback, frame_id);
+ const CreateContextProviderCallback& try_create_callback) {
+ return new StreamTextureFactorySynchronousImpl(try_create_callback);
}
StreamTextureFactorySynchronousImpl::StreamTextureFactorySynchronousImpl(
- const CreateContextProviderCallback& try_create_callback,
- int frame_id)
- : create_context_provider_callback_(try_create_callback),
- context_provider_(create_context_provider_callback_.Run()),
- frame_id_(frame_id),
- observer_(NULL) {}
+ const CreateContextProviderCallback& try_create_callback)
+ : create_context_provider_callback_(try_create_callback) {}
StreamTextureFactorySynchronousImpl::~StreamTextureFactorySynchronousImpl() {}
@@ -174,8 +147,10 @@ StreamTextureProxy* StreamTextureFactorySynchronousImpl::CreateProxy() {
if (!context_provider_.get())
return NULL;
- if (observer_ && !had_proxy)
- context_provider_->AddObserver(observer_);
+ if (!observers_.empty() && !had_proxy) {
+ for (auto& observer : observers_)
+ context_provider_->AddObserver(observer);
+ }
return new StreamTextureProxyImpl(context_provider_.get());
}
@@ -186,11 +161,8 @@ void StreamTextureFactorySynchronousImpl::EstablishPeer(int32_t stream_id,
scoped_refptr<gfx::SurfaceTexture> surface_texture =
context_provider_->GetSurfaceTexture(stream_id);
if (surface_texture.get()) {
- SurfaceTexturePeer::GetInstance()->EstablishSurfaceTexturePeer(
- base::GetCurrentProcessHandle(),
- surface_texture,
- frame_id_,
- player_id);
+ gpu::SurfaceTexturePeer::GetInstance()->EstablishSurfaceTexturePeer(
+ base::GetCurrentProcessHandle(), surface_texture, frame_id, player_id);
}
}
@@ -221,16 +193,16 @@ gpu::gles2::GLES2Interface* StreamTextureFactorySynchronousImpl::ContextGL() {
void StreamTextureFactorySynchronousImpl::AddObserver(
StreamTextureFactoryContextObserver* obs) {
- DCHECK(!observer_);
- observer_ = obs;
+ DCHECK(observers_.find(obs) == observers_.end());
+ observers_.insert(obs);
if (context_provider_.get())
context_provider_->AddObserver(obs);
}
void StreamTextureFactorySynchronousImpl::RemoveObserver(
StreamTextureFactoryContextObserver* obs) {
- DCHECK_EQ(observer_, obs);
- observer_ = NULL;
+ DCHECK(observers_.find(obs) != observers_.end());
+ observers_.erase(obs);
if (context_provider_.get())
context_provider_->RemoveObserver(obs);
}
diff --git a/chromium/content/renderer/media/android/stream_texture_factory_synchronous_impl.h b/chromium/content/renderer/media/android/stream_texture_factory_synchronous_impl.h
index cca38a855a3..a8b759a8c17 100644
--- a/chromium/content/renderer/media/android/stream_texture_factory_synchronous_impl.h
+++ b/chromium/content/renderer/media/android/stream_texture_factory_synchronous_impl.h
@@ -7,6 +7,8 @@
#include <stdint.h>
+#include <set>
+
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
@@ -49,8 +51,7 @@ class StreamTextureFactorySynchronousImpl : public StreamTextureFactory {
CreateContextProviderCallback;
static scoped_refptr<StreamTextureFactorySynchronousImpl> Create(
- const CreateContextProviderCallback& try_create_callback,
- int frame_id);
+ const CreateContextProviderCallback& try_create_callback);
StreamTextureProxy* CreateProxy() override;
void EstablishPeer(int32_t stream_id, int player_id, int frame_id) override;
@@ -65,14 +66,12 @@ class StreamTextureFactorySynchronousImpl : public StreamTextureFactory {
private:
friend class base::RefCounted<StreamTextureFactorySynchronousImpl>;
StreamTextureFactorySynchronousImpl(
- const CreateContextProviderCallback& try_create_callback,
- int frame_id);
+ const CreateContextProviderCallback& try_create_callback);
~StreamTextureFactorySynchronousImpl() override;
CreateContextProviderCallback create_context_provider_callback_;
scoped_refptr<ContextProvider> context_provider_;
- int frame_id_;
- StreamTextureFactoryContextObserver* observer_;
+ std::set<StreamTextureFactoryContextObserver*> observers_;
DISALLOW_IMPLICIT_CONSTRUCTORS(StreamTextureFactorySynchronousImpl);
};
diff --git a/chromium/content/renderer/media/android/webmediaplayer_android.cc b/chromium/content/renderer/media/android/webmediaplayer_android.cc
index ea8636b0c5e..955e17df399 100644
--- a/chromium/content/renderer/media/android/webmediaplayer_android.cc
+++ b/chromium/content/renderer/media/android/webmediaplayer_android.cc
@@ -26,20 +26,19 @@
#include "content/public/renderer/render_frame.h"
#include "content/renderer/media/android/renderer_demuxer_android.h"
#include "content/renderer/media/android/renderer_media_player_manager.h"
-#include "content/renderer/media/cdm/render_cdm_factory.h"
-#include "content/renderer/media/cdm/renderer_cdm_manager.h"
+#include "content/renderer/media/android/webmediasession_android.h"
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_view_impl.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/command_buffer/common/constants.h"
#include "gpu/command_buffer/common/mailbox_holder.h"
#include "media/base/android/media_codec_util.h"
#include "media/base/android/media_common_android.h"
#include "media/base/android/media_player_android.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/cdm_context.h"
-#include "media/base/key_systems.h"
#include "media/base/media_keys.h"
#include "media/base/media_log.h"
#include "media/base/media_switches.h"
@@ -50,18 +49,19 @@
#include "media/blink/webmediaplayer_delegate.h"
#include "media/blink/webmediaplayer_util.h"
#include "net/base/mime_util.h"
+#include "skia/ext/texture_handle.h"
#include "third_party/WebKit/public/platform/Platform.h"
+#include "third_party/WebKit/public/platform/URLConversion.h"
#include "third_party/WebKit/public/platform/WebContentDecryptionModuleResult.h"
#include "third_party/WebKit/public/platform/WebEncryptedMediaTypes.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3DProvider.h"
#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
#include "third_party/WebKit/public/platform/WebMediaPlayerEncryptedMediaClient.h"
+#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFrame.h"
-#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
-#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkPaint.h"
@@ -84,8 +84,6 @@ using media::MediaPlayerAndroid;
using media::VideoFrame;
namespace {
-// Prefix for histograms related to Encrypted Media Extensions.
-const char* kMediaEme = "Media.EME.";
// Values for Media.Android.IsHttpLiveStreamingMediaPredictionResult UMA.
// Never reuse values!
@@ -130,9 +128,8 @@ bool AllocateSkBitmapTexture(GrContext* gr,
desc.fOrigin = kTopLeft_GrSurfaceOrigin;
desc.fWidth = size.width();
desc.fHeight = size.height();
- skia::RefPtr<GrTexture> texture = skia::AdoptRef(
- gr->textureProvider()->refScratchTexture(
- desc, GrTextureProvider::kExact_ScratchTexMatch));
+ sk_sp<GrTexture> texture(gr->textureProvider()->refScratchTexture(
+ desc, GrTextureProvider::kExact_ScratchTexMatch));
if (!texture.get())
return false;
@@ -147,25 +144,19 @@ bool AllocateSkBitmapTexture(GrContext* gr,
class SyncTokenClientImpl : public media::VideoFrame::SyncTokenClient {
public:
- explicit SyncTokenClientImpl(
- blink::WebGraphicsContext3D* web_graphics_context)
- : web_graphics_context_(web_graphics_context) {}
+ explicit SyncTokenClientImpl(gpu::gles2::GLES2Interface* gl) : gl_(gl) {}
~SyncTokenClientImpl() override {}
void GenerateSyncToken(gpu::SyncToken* sync_token) override {
- const blink::WGC3Duint64 fence_sync =
- web_graphics_context_->insertFenceSyncCHROMIUM();
- web_graphics_context_->shallowFlushCHROMIUM();
- if (!web_graphics_context_->genSyncTokenCHROMIUM(fence_sync,
- sync_token->GetData())) {
- sync_token->Clear();
- }
+ const GLuint64 fence_sync = gl_->InsertFenceSyncCHROMIUM();
+ gl_->ShallowFlushCHROMIUM();
+ gl_->GenSyncTokenCHROMIUM(fence_sync, sync_token->GetData());
}
void WaitSyncToken(const gpu::SyncToken& sync_token) override {
- web_graphics_context_->waitSyncTokenCHROMIUM(sync_token.GetConstData());
+ gl_->WaitSyncTokenCHROMIUM(sync_token.GetConstData());
}
private:
- blink::WebGraphicsContext3D* web_graphics_context_;
+ gpu::gles2::GLES2Interface* gl_;
};
} // namespace
@@ -178,16 +169,15 @@ WebMediaPlayerAndroid::WebMediaPlayerAndroid(
blink::WebMediaPlayerEncryptedMediaClient* encrypted_client,
base::WeakPtr<media::WebMediaPlayerDelegate> delegate,
RendererMediaPlayerManager* player_manager,
- media::CdmFactory* cdm_factory,
scoped_refptr<StreamTextureFactory> factory,
int frame_id,
bool enable_texture_copy,
const media::WebMediaPlayerParams& params)
- : RenderFrameObserver(RenderFrame::FromWebFrame(frame)),
- frame_(frame),
+ : frame_(frame),
client_(client),
encrypted_client_(encrypted_client),
delegate_(delegate),
+ delegate_id_(0),
defer_load_cb_(params.defer_load_cb()),
buffered_(static_cast<size_t>(1)),
media_task_runner_(params.media_task_runner()),
@@ -196,14 +186,18 @@ WebMediaPlayerAndroid::WebMediaPlayerAndroid(
seeking_(false),
did_loading_progress_(false),
player_manager_(player_manager),
- cdm_factory_(cdm_factory),
- media_permission_(params.media_permission()),
+ media_session_id_(params.media_session()
+ ? static_cast<const WebMediaSessionAndroid*>(
+ params.media_session())
+ ->media_session_id()
+ : blink::WebMediaSession::DefaultID),
network_state_(WebMediaPlayer::NetworkStateEmpty),
ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
texture_id_(0),
stream_id_(0),
is_player_initialized_(false),
is_playing_(false),
+ is_play_pending_(false),
needs_establish_peer_(true),
has_size_info_(false),
// Threaded compositing isn't enabled universally yet.
@@ -217,7 +211,6 @@ WebMediaPlayerAndroid::WebMediaPlayerAndroid(
player_type_(MEDIA_PLAYER_TYPE_URL),
is_remote_(false),
media_log_(params.media_log()),
- init_data_type_(media::EmeInitDataType::UNKNOWN),
cdm_context_(nullptr),
allow_stored_credentials_(false),
is_local_resource_(false),
@@ -225,20 +218,24 @@ WebMediaPlayerAndroid::WebMediaPlayerAndroid(
frame_id_(frame_id),
enable_texture_copy_(enable_texture_copy),
suppress_deleting_texture_(false),
+ playback_completed_(false),
+ volume_(1.0),
+ volume_multiplier_(1.0),
weak_factory_(this) {
DCHECK(player_manager_);
- DCHECK(cdm_factory_);
DCHECK(main_thread_checker_.CalledOnValidThread());
stream_texture_factory_->AddObserver(this);
+ if (delegate_)
+ delegate_id_ = delegate_->AddObserver(this);
+
player_id_ = player_manager_->RegisterMediaPlayer(this);
#if defined(VIDEO_HOLE)
- const RendererPreferences& prefs =
- static_cast<RenderFrameImpl*>(render_frame())
- ->render_view()
- ->renderer_preferences();
+ const RendererPreferences& prefs = RenderFrameImpl::FromRoutingID(frame_id)
+ ->render_view()
+ ->renderer_preferences();
force_use_overlay_embedded_video_ = prefs.use_view_overlay_for_all_video;
if (force_use_overlay_embedded_video_ ||
player_manager_->ShouldUseVideoOverlayForEmbeddedEncryptedVideo()) {
@@ -281,8 +278,10 @@ WebMediaPlayerAndroid::~WebMediaPlayerAndroid() {
current_frame_ = NULL;
}
- if (delegate_)
- delegate_->PlayerGone(this);
+ if (delegate_) {
+ delegate_->PlayerGone(delegate_id_);
+ delegate_->RemoveObserver(delegate_id_);
+ }
stream_texture_factory_->RemoveObserver(this);
@@ -314,8 +313,7 @@ void WebMediaPlayerAndroid::DoLoad(LoadType load_type,
CORSMode cors_mode) {
DCHECK(main_thread_checker_.CalledOnValidThread());
- media::ReportMetrics(load_type, GURL(url),
- GURL(frame_->document().securityOrigin().toString()));
+ media::ReportMetrics(load_type, GURL(url), frame_->getSecurityOrigin());
switch (load_type) {
case LoadTypeURL:
@@ -409,6 +407,14 @@ bool WebMediaPlayerAndroid::IsLocalResource() {
void WebMediaPlayerAndroid::play() {
DCHECK(main_thread_checker_.CalledOnValidThread());
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableMediaSuspend) &&
+ hasVideo() && player_manager_->render_frame()->IsHidden()) {
+ is_play_pending_ = true;
+ return;
+ }
+ is_play_pending_ = false;
+
// For HLS streams, some devices cannot detect the video size unless a surface
// texture is bind to it. See http://crbug.com/400145.
#if defined(VIDEO_HOLE)
@@ -427,9 +433,13 @@ void WebMediaPlayerAndroid::play() {
EstablishSurfaceTexturePeer();
}
- if (paused())
- player_manager_->Start(player_id_);
+ // UpdatePlayingState() must be run before calling Start() to ensure that the
+ // browser side MediaPlayerAndroid values for hasAudio() and hasVideo() take
+ // precedent over the guesses that we make based on mime type.
+ const bool is_paused = paused();
UpdatePlayingState(true);
+ if (is_paused)
+ player_manager_->Start(player_id_);
UpdateNetworkState(WebMediaPlayer::NetworkStateLoading);
}
@@ -450,6 +460,7 @@ void WebMediaPlayerAndroid::seek(double seconds) {
DCHECK(main_thread_checker_.CalledOnValidThread());
DVLOG(1) << __FUNCTION__ << "(" << seconds << ")";
+ playback_completed_ = false;
base::TimeDelta new_seek_time = base::TimeDelta::FromSecondsD(seconds);
if (seeking_) {
@@ -493,13 +504,12 @@ bool WebMediaPlayerAndroid::supportsSave() const {
return false;
}
-void WebMediaPlayerAndroid::setRate(double rate) {
- NOTIMPLEMENTED();
-}
+void WebMediaPlayerAndroid::setRate(double rate) {}
void WebMediaPlayerAndroid::setVolume(double volume) {
DCHECK(main_thread_checker_.CalledOnValidThread());
- player_manager_->SetVolume(player_id_, volume);
+ volume_ = volume;
+ player_manager_->SetVolume(player_id_, volume_ * volume_multiplier_);
}
void WebMediaPlayerAndroid::setSinkId(
@@ -507,7 +517,7 @@ void WebMediaPlayerAndroid::setSinkId(
const blink::WebSecurityOrigin& security_origin,
blink::WebSetSinkIdCallbacks* web_callback) {
DCHECK(main_thread_checker_.CalledOnValidThread());
- scoped_ptr<blink::WebSetSinkIdCallbacks> callback(web_callback);
+ std::unique_ptr<blink::WebSetSinkIdCallbacks> callback(web_callback);
callback->onError(blink::WebSetSinkIdError::NotSupported);
}
@@ -600,14 +610,18 @@ WebSize WebMediaPlayerAndroid::naturalSize() const {
return natural_size_;
}
-WebMediaPlayer::NetworkState WebMediaPlayerAndroid::networkState() const {
+WebMediaPlayer::NetworkState WebMediaPlayerAndroid::getNetworkState() const {
return network_state_;
}
-WebMediaPlayer::ReadyState WebMediaPlayerAndroid::readyState() const {
+WebMediaPlayer::ReadyState WebMediaPlayerAndroid::getReadyState() const {
return ready_state_;
}
+blink::WebString WebMediaPlayerAndroid::getErrorMessage() {
+ return blink::WebString::fromUTF8(media_log_->GetLastErrorMessage());
+}
+
blink::WebTimeRanges WebMediaPlayerAndroid::buffered() const {
if (media_source_delegate_)
return media_source_delegate_->Buffered();
@@ -636,14 +650,12 @@ void WebMediaPlayerAndroid::paint(blink::WebCanvas* canvas,
unsigned char alpha,
SkXfermode::Mode mode) {
DCHECK(main_thread_checker_.CalledOnValidThread());
- scoped_ptr<blink::WebGraphicsContext3DProvider> provider =
- scoped_ptr<blink::WebGraphicsContext3DProvider>(blink::Platform::current(
- )->createSharedOffscreenGraphicsContext3DProvider());
+ std::unique_ptr<blink::WebGraphicsContext3DProvider> provider(
+ blink::Platform::current()
+ ->createSharedOffscreenGraphicsContext3DProvider());
if (!provider)
return;
- blink::WebGraphicsContext3D* context3D = provider->context3d();
- if (!context3D)
- return;
+ gpu::gles2::GLES2Interface* gl = provider->contextGL();
// Copy video texture into a RGBA texture based bitmap first as video texture
// on Android is GL_TEXTURE_EXTERNAL_OES which is not supported by Skia yet.
@@ -658,10 +670,11 @@ void WebMediaPlayerAndroid::paint(blink::WebCanvas* canvas,
}
}
- unsigned textureId = static_cast<unsigned>(
- (bitmap_.getTexture())->getTextureHandle());
- if (!copyVideoTextureToPlatformTexture(context3D, textureId,
- GL_RGBA, GL_UNSIGNED_BYTE, true, false)) {
+ unsigned textureId = skia::GrBackendObjectToGrGLTextureInfo(
+ (bitmap_.getTexture())->getTextureHandle())
+ ->fID;
+ if (!copyVideoTextureToPlatformTexture(gl, textureId, GL_RGBA,
+ GL_UNSIGNED_BYTE, true, false)) {
return;
}
@@ -684,7 +697,7 @@ void WebMediaPlayerAndroid::paint(blink::WebCanvas* canvas,
}
bool WebMediaPlayerAndroid::copyVideoTextureToPlatformTexture(
- blink::WebGraphicsContext3D* web_graphics_context,
+ gpu::gles2::GLES2Interface* gl,
unsigned int texture,
unsigned int internal_format,
unsigned int type,
@@ -709,26 +722,24 @@ bool WebMediaPlayerAndroid::copyVideoTextureToPlatformTexture(
mailbox_holder.texture_target == GL_TEXTURE_EXTERNAL_OES) ||
(is_remote_ && mailbox_holder.texture_target == GL_TEXTURE_2D));
- web_graphics_context->waitSyncTokenCHROMIUM(
- mailbox_holder.sync_token.GetConstData());
+ gl->WaitSyncTokenCHROMIUM(mailbox_holder.sync_token.GetConstData());
// Ensure the target of texture is set before copyTextureCHROMIUM, otherwise
// an invalid texture target may be used for copy texture.
- uint32_t src_texture = web_graphics_context->createAndConsumeTextureCHROMIUM(
+ uint32_t src_texture = gl->CreateAndConsumeTextureCHROMIUM(
mailbox_holder.texture_target, mailbox_holder.mailbox.name);
// Application itself needs to take care of setting the right flip_y
// value down to get the expected result.
// flip_y==true means to reverse the video orientation while
// flip_y==false means to keep the intrinsic orientation.
- web_graphics_context->copyTextureCHROMIUM(src_texture, texture,
- internal_format, type, flip_y,
- premultiply_alpha, false);
+ gl->CopyTextureCHROMIUM(src_texture, texture, internal_format, type, flip_y,
+ premultiply_alpha, false);
- web_graphics_context->deleteTexture(src_texture);
- web_graphics_context->flush();
+ gl->DeleteTextures(1, &src_texture);
+ gl->Flush();
- SyncTokenClientImpl client(web_graphics_context);
+ SyncTokenClientImpl client(gl);
video_frame->UpdateReleaseSyncToken(&client);
return true;
}
@@ -741,6 +752,11 @@ bool WebMediaPlayerAndroid::hasSingleSecurityOrigin() const {
if (!info_loader_ || !info_loader_->HasSingleOrigin())
return false;
+ // TODO(qinmin): After fixing crbug.com/592017, remove this command line.
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kReduceSecurityForTesting))
+ return true;
+
// TODO(qinmin): The url might be redirected when android media player
// requests the stream. As a result, we cannot guarantee there is only
// a single origin. Only if the HTTP request was made without credentials,
@@ -779,14 +795,14 @@ unsigned WebMediaPlayerAndroid::droppedFrameCount() const {
return 0;
}
-unsigned WebMediaPlayerAndroid::audioDecodedByteCount() const {
+size_t WebMediaPlayerAndroid::audioDecodedByteCount() const {
if (media_source_delegate_)
return media_source_delegate_->AudioDecodedByteCount();
NOTIMPLEMENTED();
return 0;
}
-unsigned WebMediaPlayerAndroid::videoDecodedByteCount() const {
+size_t WebMediaPlayerAndroid::videoDecodedByteCount() const {
if (media_source_delegate_)
return media_source_delegate_->VideoDecodedByteCount();
NOTIMPLEMENTED();
@@ -850,6 +866,8 @@ void WebMediaPlayerAndroid::OnPlaybackComplete() {
// playing after seek completes.
if (seeking_ && seek_time_ == base::TimeDelta())
player_manager_->Start(player_id_);
+ else
+ playback_completed_ = true;
}
void WebMediaPlayerAndroid::OnBufferingUpdate(int percentage) {
@@ -949,9 +967,14 @@ void WebMediaPlayerAndroid::OnVideoSizeChanged(int width, int height) {
// Lazily allocate compositing layer.
if (!video_weblayer_) {
video_weblayer_.reset(new cc_blink::WebLayerImpl(
- cc::VideoLayer::Create(cc_blink::WebLayerImpl::LayerSettings(), this,
- media::VIDEO_ROTATION_0)));
+ cc::VideoLayer::Create(this, media::VIDEO_ROTATION_0)));
client_->setWebLayer(video_weblayer_.get());
+
+ // If we're paused after we receive metadata for the first time, tell the
+ // delegate we can now be safely suspended due to inactivity if a subsequent
+ // play event does not occur.
+ if (paused() && delegate_)
+ delegate_->DidPause(delegate_id_, false);
}
}
@@ -1000,6 +1023,11 @@ void WebMediaPlayerAndroid::OnDisconnectedFromRemoteDevice() {
client_->disconnectedFromRemoteDevice();
}
+void WebMediaPlayerAndroid::OnCancelledRemotePlaybackRequest() {
+ DCHECK(main_thread_checker_.CalledOnValidThread());
+ client_->cancelledRemotePlaybackRequest();
+}
+
void WebMediaPlayerAndroid::OnDidExitFullscreen() {
// |needs_external_surface_| is always false on non-TV devices.
if (!needs_external_surface_)
@@ -1017,6 +1045,7 @@ void WebMediaPlayerAndroid::OnDidExitFullscreen() {
player_manager_->RequestExternalSurface(player_id_, last_computed_rect_);
#endif // defined(VIDEO_HOLE)
is_fullscreen_ = false;
+ ReallocateVideoFrame();
client_->repaint();
}
@@ -1086,6 +1115,9 @@ void WebMediaPlayerAndroid::OnPlayerReleased() {
if (is_playing_)
OnMediaPlayerPause();
+ if (delegate_)
+ delegate_->PlayerGone(delegate_id_);
+
#if defined(VIDEO_HOLE)
last_computed_rect_ = gfx::RectF();
#endif // defined(VIDEO_HOLE)
@@ -1100,6 +1132,8 @@ void WebMediaPlayerAndroid::SuspendAndReleaseResources() {
case WebMediaPlayer::NetworkStateLoaded:
Pause(false);
client_->playbackStateChanged();
+ if (delegate_)
+ delegate_->PlayerGone(delegate_id_);
break;
// If a WebMediaPlayer instance has entered into one of these states,
// the internal network state in HTMLMediaElement could be set to empty.
@@ -1115,12 +1149,6 @@ void WebMediaPlayerAndroid::SuspendAndReleaseResources() {
SetNeedsEstablishPeer(true);
}
-void WebMediaPlayerAndroid::OnDestruct() {
- NOTREACHED() << "WebMediaPlayer should be destroyed before any "
- "RenderFrameObserver::OnDestruct() gets called when "
- "the RenderFrame goes away.";
-}
-
void WebMediaPlayerAndroid::InitializePlayer(
const GURL& url,
const GURL& first_party_for_cookies,
@@ -1131,7 +1159,8 @@ void WebMediaPlayerAndroid::InitializePlayer(
allow_stored_credentials_ = allow_stored_credentials;
player_manager_->Initialize(
player_type_, player_id_, url, first_party_for_cookies, demuxer_client_id,
- frame_->document().url(), allow_stored_credentials);
+ frame_->document().url(), allow_stored_credentials, delegate_id_,
+ media_session_id_);
is_player_initialized_ = true;
if (is_fullscreen_)
@@ -1177,6 +1206,8 @@ void WebMediaPlayerAndroid::DrawRemotePlaybackText(
void WebMediaPlayerAndroid::ReallocateVideoFrame() {
DCHECK(main_thread_checker_.CalledOnValidThread());
+
+ if (is_fullscreen_) return;
if (needs_external_surface_) {
// VideoFrame::CreateHoleFrame is only defined under VIDEO_HOLE.
#if defined(VIDEO_HOLE)
@@ -1198,8 +1229,19 @@ void WebMediaPlayerAndroid::ReallocateVideoFrame() {
GLuint texture_target = kGLTextureExternalOES;
GLuint texture_id_ref = gl->CreateAndConsumeTextureCHROMIUM(
texture_target, texture_mailbox_.name);
+ const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM();
gl->Flush();
- gpu::SyncToken texture_mailbox_sync_token(gl->InsertSyncPointCHROMIUM());
+
+ gpu::SyncToken texture_mailbox_sync_token;
+ gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync,
+ texture_mailbox_sync_token.GetData());
+ if (texture_mailbox_sync_token.namespace_id() ==
+ gpu::CommandBufferNamespace::IN_PROCESS) {
+ // TODO(boliu): Remove this once Android WebView switches to IPC-based
+ // command buffer for video.
+ GLbyte* sync_tokens[] = {texture_mailbox_sync_token.GetData()};
+ gl->VerifySyncTokensCHROMIUM(sync_tokens, arraysize(sync_tokens));
+ }
scoped_refptr<VideoFrame> new_frame = VideoFrame::WrapNativeTexture(
media::PIXEL_FORMAT_ARGB,
@@ -1209,8 +1251,10 @@ void WebMediaPlayerAndroid::ReallocateVideoFrame() {
&OnReleaseTexture, stream_texture_factory_, texture_id_ref)),
natural_size_, gfx::Rect(natural_size_), natural_size_,
base::TimeDelta());
- new_frame->metadata()->SetBoolean(media::VideoFrameMetadata::COPY_REQUIRED,
- enable_texture_copy_);
+ if (new_frame.get()) {
+ new_frame->metadata()->SetBoolean(
+ media::VideoFrameMetadata::COPY_REQUIRED, enable_texture_copy_);
+ }
SetCurrentFrameInternal(new_frame);
}
}
@@ -1367,10 +1411,20 @@ void WebMediaPlayerAndroid::UpdatePlayingState(bool is_playing) {
interpolator_.StopInterpolating();
if (delegate_) {
- if (is_playing)
- delegate_->DidPlay(this);
- else
- delegate_->DidPause(this);
+ if (is_playing) {
+ // We must specify either video or audio to the delegate, but neither may
+ // be known at this point -- there are no video only containers, so only
+ // send audio if we know for sure its audio. The browser side player will
+ // fill in the correct value later for media sessions.
+ delegate_->DidPlay(delegate_id_, hasVideo(), !hasVideo(), isRemote(),
+ duration_);
+ } else {
+ // Even if OnPlaybackComplete() has not been called yet, Blink may have
+ // already fired the ended event based on current time relative to
+ // duration -- so we need to check both possibilities here.
+ delegate_->DidPause(delegate_id_,
+ playback_completed_ || currentTime() >= duration());
+ }
}
}
@@ -1401,236 +1455,6 @@ const gfx::RectF WebMediaPlayerAndroid::GetBoundaryRectangle() {
}
#endif
-// The following EME related code is copied from WebMediaPlayerImpl.
-// TODO(xhwang): Remove duplicate code between WebMediaPlayerAndroid and
-// WebMediaPlayerImpl.
-
-// Convert a WebString to ASCII, falling back on an empty string in the case
-// of a non-ASCII string.
-static std::string ToASCIIOrEmpty(const blink::WebString& string) {
- return base::IsStringASCII(string)
- ? base::UTF16ToASCII(base::StringPiece16(string))
- : std::string();
-}
-
-// Helper functions to report media EME related stats to UMA. They follow the
-// convention of more commonly used macros UMA_HISTOGRAM_ENUMERATION and
-// UMA_HISTOGRAM_COUNTS. The reason that we cannot use those macros directly is
-// that UMA_* macros require the names to be constant throughout the process'
-// lifetime.
-
-static void EmeUMAHistogramEnumeration(const std::string& key_system,
- const std::string& method,
- int sample,
- int boundary_value) {
- base::LinearHistogram::FactoryGet(
- kMediaEme + media::GetKeySystemNameForUMA(key_system) + "." + method,
- 1, boundary_value, boundary_value + 1,
- base::Histogram::kUmaTargetedHistogramFlag)->Add(sample);
-}
-
-static void EmeUMAHistogramCounts(const std::string& key_system,
- const std::string& method,
- int sample) {
- // Use the same parameters as UMA_HISTOGRAM_COUNTS.
- base::Histogram::FactoryGet(
- kMediaEme + media::GetKeySystemNameForUMA(key_system) + "." + method,
- 1, 1000000, 50, base::Histogram::kUmaTargetedHistogramFlag)->Add(sample);
-}
-
-// Helper enum for reporting generateKeyRequest/addKey histograms.
-enum MediaKeyException {
- kUnknownResultId,
- kSuccess,
- kKeySystemNotSupported,
- kInvalidPlayerState,
- kMaxMediaKeyException
-};
-
-static MediaKeyException MediaKeyExceptionForUMA(
- WebMediaPlayer::MediaKeyException e) {
- switch (e) {
- case WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported:
- return kKeySystemNotSupported;
- case WebMediaPlayer::MediaKeyExceptionInvalidPlayerState:
- return kInvalidPlayerState;
- case WebMediaPlayer::MediaKeyExceptionNoError:
- return kSuccess;
- default:
- return kUnknownResultId;
- }
-}
-
-// Helper for converting |key_system| name and exception |e| to a pair of enum
-// values from above, for reporting to UMA.
-static void ReportMediaKeyExceptionToUMA(const std::string& method,
- const std::string& key_system,
- WebMediaPlayer::MediaKeyException e) {
- MediaKeyException result_id = MediaKeyExceptionForUMA(e);
- DCHECK_NE(result_id, kUnknownResultId) << e;
- EmeUMAHistogramEnumeration(
- key_system, method, result_id, kMaxMediaKeyException);
-}
-
-bool WebMediaPlayerAndroid::IsKeySystemSupported(
- const std::string& key_system) {
- // On Android, EME only works with MSE.
- return player_type_ == MEDIA_PLAYER_TYPE_MEDIA_SOURCE &&
- media::PrefixedIsSupportedConcreteKeySystem(key_system);
-}
-
-WebMediaPlayer::MediaKeyException WebMediaPlayerAndroid::generateKeyRequest(
- const WebString& key_system,
- const unsigned char* init_data,
- unsigned init_data_length) {
- DVLOG(1) << "generateKeyRequest: " << base::string16(key_system) << ": "
- << std::string(reinterpret_cast<const char*>(init_data),
- static_cast<size_t>(init_data_length));
-
- std::string ascii_key_system =
- media::GetUnprefixedKeySystemName(ToASCIIOrEmpty(key_system));
-
- WebMediaPlayer::MediaKeyException e =
- GenerateKeyRequestInternal(ascii_key_system, init_data, init_data_length);
- ReportMediaKeyExceptionToUMA("generateKeyRequest", ascii_key_system, e);
- return e;
-}
-
-// Guess the type of |init_data|. This is only used to handle some corner cases
-// so we keep it as simple as possible without breaking major use cases.
-static media::EmeInitDataType GuessInitDataType(const unsigned char* init_data,
- unsigned init_data_length) {
- // Most WebM files use KeyId of 16 bytes. CENC init data is always >16 bytes.
- if (init_data_length == 16)
- return media::EmeInitDataType::WEBM;
-
- return media::EmeInitDataType::CENC;
-}
-
-// TODO(xhwang): Report an error when there is encrypted stream but EME is
-// not enabled. Currently the player just doesn't start and waits for
-// ever.
-WebMediaPlayer::MediaKeyException
-WebMediaPlayerAndroid::GenerateKeyRequestInternal(
- const std::string& key_system,
- const unsigned char* init_data,
- unsigned init_data_length) {
- if (!IsKeySystemSupported(key_system))
- return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
-
- if (!proxy_decryptor_) {
- DCHECK(current_key_system_.empty());
- proxy_decryptor_.reset(new media::ProxyDecryptor(
- media_permission_,
- player_manager_->ShouldUseVideoOverlayForEmbeddedEncryptedVideo(),
- base::Bind(&WebMediaPlayerAndroid::OnKeyAdded,
- weak_factory_.GetWeakPtr()),
- base::Bind(&WebMediaPlayerAndroid::OnKeyError,
- weak_factory_.GetWeakPtr()),
- base::Bind(&WebMediaPlayerAndroid::OnKeyMessage,
- weak_factory_.GetWeakPtr())));
-
- GURL security_origin(frame_->document().securityOrigin().toString());
- proxy_decryptor_->CreateCdm(
- cdm_factory_, key_system, security_origin,
- base::Bind(&WebMediaPlayerAndroid::OnCdmContextReady,
- weak_factory_.GetWeakPtr()));
- current_key_system_ = key_system;
- }
-
- // We do not support run-time switching between key systems for now.
- DCHECK(!current_key_system_.empty());
- if (key_system != current_key_system_)
- return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
-
- media::EmeInitDataType init_data_type = init_data_type_;
- if (init_data_type == media::EmeInitDataType::UNKNOWN)
- init_data_type = GuessInitDataType(init_data, init_data_length);
-
- proxy_decryptor_->GenerateKeyRequest(init_data_type, init_data,
- init_data_length);
-
- return WebMediaPlayer::MediaKeyExceptionNoError;
-}
-
-WebMediaPlayer::MediaKeyException WebMediaPlayerAndroid::addKey(
- const WebString& key_system,
- const unsigned char* key,
- unsigned key_length,
- const unsigned char* init_data,
- unsigned init_data_length,
- const WebString& session_id) {
- DVLOG(1) << "addKey: " << base::string16(key_system) << ": "
- << std::string(reinterpret_cast<const char*>(key),
- static_cast<size_t>(key_length)) << ", "
- << std::string(reinterpret_cast<const char*>(init_data),
- static_cast<size_t>(init_data_length)) << " ["
- << base::string16(session_id) << "]";
-
- std::string ascii_key_system =
- media::GetUnprefixedKeySystemName(ToASCIIOrEmpty(key_system));
- std::string ascii_session_id = ToASCIIOrEmpty(session_id);
-
- WebMediaPlayer::MediaKeyException e = AddKeyInternal(ascii_key_system,
- key,
- key_length,
- init_data,
- init_data_length,
- ascii_session_id);
- ReportMediaKeyExceptionToUMA("addKey", ascii_key_system, e);
- return e;
-}
-
-WebMediaPlayer::MediaKeyException WebMediaPlayerAndroid::AddKeyInternal(
- const std::string& key_system,
- const unsigned char* key,
- unsigned key_length,
- const unsigned char* init_data,
- unsigned init_data_length,
- const std::string& session_id) {
- DCHECK(key);
- DCHECK_GT(key_length, 0u);
-
- if (!IsKeySystemSupported(key_system))
- return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
-
- if (current_key_system_.empty() || key_system != current_key_system_)
- return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
-
- proxy_decryptor_->AddKey(
- key, key_length, init_data, init_data_length, session_id);
- return WebMediaPlayer::MediaKeyExceptionNoError;
-}
-
-WebMediaPlayer::MediaKeyException WebMediaPlayerAndroid::cancelKeyRequest(
- const WebString& key_system,
- const WebString& session_id) {
- DVLOG(1) << "cancelKeyRequest: " << base::string16(key_system) << ": "
- << " [" << base::string16(session_id) << "]";
-
- std::string ascii_key_system =
- media::GetUnprefixedKeySystemName(ToASCIIOrEmpty(key_system));
- std::string ascii_session_id = ToASCIIOrEmpty(session_id);
-
- WebMediaPlayer::MediaKeyException e =
- CancelKeyRequestInternal(ascii_key_system, ascii_session_id);
- ReportMediaKeyExceptionToUMA("cancelKeyRequest", ascii_key_system, e);
- return e;
-}
-
-WebMediaPlayer::MediaKeyException
-WebMediaPlayerAndroid::CancelKeyRequestInternal(const std::string& key_system,
- const std::string& session_id) {
- if (!IsKeySystemSupported(key_system))
- return WebMediaPlayer::MediaKeyExceptionKeySystemNotSupported;
-
- if (current_key_system_.empty() || key_system != current_key_system_)
- return WebMediaPlayer::MediaKeyExceptionInvalidPlayerState;
-
- proxy_decryptor_->CancelKeyRequest(session_id);
- return WebMediaPlayer::MediaKeyExceptionNoError;
-}
-
void WebMediaPlayerAndroid::setContentDecryptionModule(
blink::WebContentDecryptionModule* cdm,
blink::WebContentDecryptionModuleResult result) {
@@ -1673,47 +1497,6 @@ void WebMediaPlayerAndroid::ContentDecryptionModuleAttached(
"Unable to set MediaKeys object");
}
-void WebMediaPlayerAndroid::OnKeyAdded(const std::string& session_id) {
- EmeUMAHistogramCounts(current_key_system_, "KeyAdded", 1);
-
- encrypted_client_->keyAdded(
- WebString::fromUTF8(media::GetPrefixedKeySystemName(current_key_system_)),
- WebString::fromUTF8(session_id));
-}
-
-void WebMediaPlayerAndroid::OnKeyError(const std::string& session_id,
- media::MediaKeys::KeyError error_code,
- uint32_t system_code) {
- EmeUMAHistogramEnumeration(current_key_system_, "KeyError",
- error_code, media::MediaKeys::kMaxKeyError);
-
- unsigned short short_system_code = 0;
- if (system_code > std::numeric_limits<unsigned short>::max()) {
- LOG(WARNING) << "system_code exceeds unsigned short limit.";
- short_system_code = std::numeric_limits<unsigned short>::max();
- } else {
- short_system_code = static_cast<unsigned short>(system_code);
- }
-
- encrypted_client_->keyError(
- WebString::fromUTF8(media::GetPrefixedKeySystemName(current_key_system_)),
- WebString::fromUTF8(session_id),
- static_cast<blink::WebMediaPlayerEncryptedMediaClient::MediaKeyErrorCode>(
- error_code),
- short_system_code);
-}
-
-void WebMediaPlayerAndroid::OnKeyMessage(const std::string& session_id,
- const std::vector<uint8_t>& message,
- const GURL& destination_url) {
- DCHECK(destination_url.is_empty() || destination_url.is_valid());
-
- encrypted_client_->keyMessage(
- WebString::fromUTF8(media::GetPrefixedKeySystemName(current_key_system_)),
- WebString::fromUTF8(session_id), message.empty() ? NULL : &message[0],
- message.size(), destination_url);
-}
-
void WebMediaPlayerAndroid::OnMediaSourceOpened(
blink::WebMediaSource* web_media_source) {
client_->mediaSourceOpened(web_media_source);
@@ -1724,20 +1507,10 @@ void WebMediaPlayerAndroid::OnEncryptedMediaInitData(
const std::vector<uint8_t>& init_data) {
DCHECK(main_thread_checker_.CalledOnValidThread());
- // Do not fire NeedKey event if encrypted media is not enabled.
- if (!blink::WebRuntimeFeatures::isPrefixedEncryptedMediaEnabled() &&
- !blink::WebRuntimeFeatures::isEncryptedMediaEnabled()) {
- return;
- }
-
- UMA_HISTOGRAM_COUNTS(kMediaEme + std::string("NeedKey"), 1);
+ // TODO(xhwang): Update this UMA name. https://crbug.com/589251
+ UMA_HISTOGRAM_COUNTS("Media.EME.NeedKey", 1);
DCHECK(init_data_type != media::EmeInitDataType::UNKNOWN);
- DLOG_IF(WARNING, init_data_type_ != media::EmeInitDataType::UNKNOWN &&
- init_data_type != init_data_type_)
- << "Mixed init data type not supported. The new type is ignored.";
- if (init_data_type_ == media::EmeInitDataType::UNKNOWN)
- init_data_type_ = init_data_type;
encrypted_client_->encrypted(ConvertToWebInitDataType(init_data_type),
init_data.data(), init_data.size());
@@ -1752,6 +1525,42 @@ void WebMediaPlayerAndroid::OnWaitingForDecryptionKey() {
encrypted_client_->didResumePlaybackBlockedForKey();
}
+void WebMediaPlayerAndroid::OnHidden() {
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableMediaSuspend)) {
+ return;
+ }
+
+ OnSuspendRequested(false);
+}
+
+void WebMediaPlayerAndroid::OnShown() {
+ if (is_play_pending_)
+ play();
+}
+
+void WebMediaPlayerAndroid::OnSuspendRequested(bool must_suspend) {
+ // If we're idle or playing video, pause and release resources; audio only
+ // players are allowed to continue unless indicated otherwise by the call.
+ if (must_suspend || (paused() && playback_completed_) || hasVideo())
+ SuspendAndReleaseResources();
+}
+
+void WebMediaPlayerAndroid::OnPlay() {
+ play();
+ client_->playbackStateChanged();
+}
+
+void WebMediaPlayerAndroid::OnPause() {
+ pause();
+ client_->playbackStateChanged();
+}
+
+void WebMediaPlayerAndroid::OnVolumeMultiplierUpdate(double multiplier) {
+ volume_multiplier_ = multiplier;
+ setVolume(volume_);
+}
+
void WebMediaPlayerAndroid::OnCdmContextReady(media::CdmContext* cdm_context) {
DCHECK(!cdm_context_);
@@ -1790,6 +1599,7 @@ void WebMediaPlayerAndroid::SetCdmInternal(
void WebMediaPlayerAndroid::OnCdmAttached(
const media::CdmAttachedCB& cdm_attached_cb,
bool success) {
+ DVLOG(1) << __FUNCTION__ << ": success: " << success;
DCHECK(main_thread_checker_.CalledOnValidThread());
if (!success) {
@@ -1808,7 +1618,7 @@ void WebMediaPlayerAndroid::OnCdmAttached(
}
void WebMediaPlayerAndroid::SetCdmReadyCB(
- const media::CdmReadyCB& cdm_ready_cb) {
+ const MediaSourceDelegate::CdmReadyCB& cdm_ready_cb) {
DCHECK(main_thread_checker_.CalledOnValidThread());
DCHECK(is_player_initialized_);
@@ -1837,12 +1647,22 @@ bool WebMediaPlayerAndroid::supportsOverlayFullscreenVideo() {
return true;
}
-void WebMediaPlayerAndroid::enterFullscreen() {
+void WebMediaPlayerAndroid::enteredFullscreen() {
if (is_player_initialized_)
player_manager_->EnterFullscreen(player_id_);
SetNeedsEstablishPeer(false);
is_fullscreen_ = true;
suppress_deleting_texture_ = false;
+
+ // Create a transparent video frame. Blink will already have made the
+ // background transparent because we returned true from
+ // supportsOverlayFullscreenVideo(). By making the video frame transparent,
+ // as well, everything in the LayerTreeView will be transparent except for
+ // media controls. The video will be on visible on the underlaid surface.
+ if (!fullscreen_frame_)
+ fullscreen_frame_ = VideoFrame::CreateTransparentFrame(gfx::Size(1, 1));
+ SetCurrentFrameInternal(fullscreen_frame_);
+ client_->repaint();
}
bool WebMediaPlayerAndroid::IsHLSStream() const {
@@ -1858,7 +1678,7 @@ void WebMediaPlayerAndroid::ReportHLSMetrics() const {
UMA_HISTOGRAM_BOOLEAN("Media.Android.IsHttpLiveStreamingMedia", is_hls);
if (is_hls) {
media::RecordOriginOfHLSPlayback(
- GURL(frame_->document().securityOrigin().toString()));
+ blink::WebStringToGURL(frame_->getSecurityOrigin().toString()));
}
// Assuming that |is_hls| is the ground truth, test predictions.
diff --git a/chromium/content/renderer/media/android/webmediaplayer_android.h b/chromium/content/renderer/media/android/webmediaplayer_android.h
index 6fa9ca5b498..f89824fe420 100644
--- a/chromium/content/renderer/media/android/webmediaplayer_android.h
+++ b/chromium/content/renderer/media/android/webmediaplayer_android.h
@@ -7,18 +7,17 @@
#include <stdint.h>
+#include <memory>
#include <string>
#include <vector>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
#include "cc/layers/video_frame_provider.h"
-#include "content/public/renderer/render_frame_observer.h"
#include "content/renderer/media/android/media_info_loader.h"
#include "content/renderer/media/android/media_source_delegate.h"
#include "content/renderer/media/android/renderer_media_player_manager.h"
@@ -27,11 +26,11 @@
#include "media/base/android/media_player_android.h"
#include "media/base/cdm_context.h"
#include "media/base/demuxer_stream.h"
+#include "media/base/eme_constants.h"
#include "media/base/media_keys.h"
#include "media/base/time_delta_interpolator.h"
+#include "media/blink/webmediaplayer_delegate.h"
#include "media/blink/webmediaplayer_params.h"
-#include "media/cdm/proxy_decryptor.h"
-#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
#include "third_party/WebKit/public/platform/WebSetSinkIdCallbacks.h"
#include "third_party/WebKit/public/platform/WebSize.h"
@@ -57,38 +56,38 @@ class WebLayerImpl;
}
namespace gpu {
+namespace gles2 {
+class GLES2Interface;
+}
struct MailboxHolder;
}
namespace media {
class CdmContext;
-class CdmFactory;
class MediaLog;
-class MediaPermission;
class WebContentDecryptionModuleImpl;
-class WebMediaPlayerDelegate;
}
namespace content {
-class RendererCdmManager;
class RendererMediaPlayerManager;
// This class implements blink::WebMediaPlayer by keeping the android
// media player in the browser process. It listens to all the status changes
// sent from the browser process and sends playback controls to the media
// player.
-class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
- public cc::VideoFrameProvider,
- public RenderFrameObserver,
- public StreamTextureFactoryContextObserver,
- public media::RendererMediaPlayerInterface {
+class WebMediaPlayerAndroid
+ : public blink::WebMediaPlayer,
+ public cc::VideoFrameProvider,
+ public StreamTextureFactoryContextObserver,
+ public media::RendererMediaPlayerInterface,
+ public NON_EXPORTED_BASE(media::WebMediaPlayerDelegate::Observer) {
public:
// Construct a WebMediaPlayerAndroid object. This class communicates with the
// MediaPlayerAndroid object in the browser process through |proxy|.
// TODO(qinmin): |frame| argument is used to determine whether the current
// player can enter fullscreen. This logic should probably be moved into
- // blink, so that enterFullscreen() will not be called if another video is
+ // blink, so that enteredFullscreen() will not be called if another video is
// already in fullscreen.
WebMediaPlayerAndroid(
blink::WebFrame* frame,
@@ -96,7 +95,6 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
blink::WebMediaPlayerEncryptedMediaClient* encrypted_client,
base::WeakPtr<media::WebMediaPlayerDelegate> delegate,
RendererMediaPlayerManager* player_manager,
- media::CdmFactory* cdm_factory,
scoped_refptr<StreamTextureFactory> factory,
int frame_id,
bool enable_texture_copy,
@@ -105,7 +103,7 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
// blink::WebMediaPlayer implementation.
bool supportsOverlayFullscreenVideo() override;
- void enterFullscreen() override;
+ void enteredFullscreen() override;
// Resource loading.
void load(LoadType load_type,
@@ -140,13 +138,12 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
unsigned char alpha,
SkXfermode::Mode mode) override;
- bool copyVideoTextureToPlatformTexture(
- blink::WebGraphicsContext3D* web_graphics_context,
- unsigned int texture,
- unsigned int internal_format,
- unsigned int type,
- bool premultiply_alpha,
- bool flip_y) override;
+ bool copyVideoTextureToPlatformTexture(gpu::gles2::GLES2Interface* gl,
+ unsigned int texture,
+ unsigned int internal_format,
+ unsigned int type,
+ bool premultiply_alpha,
+ bool flip_y) override;
// True if the loaded media has a playable video/audio track.
bool hasVideo() const override;
@@ -167,8 +164,10 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
bool didLoadingProgress() override;
// Internal states of loading and network.
- blink::WebMediaPlayer::NetworkState networkState() const override;
- blink::WebMediaPlayer::ReadyState readyState() const override;
+ blink::WebMediaPlayer::NetworkState getNetworkState() const override;
+ blink::WebMediaPlayer::ReadyState getReadyState() const override;
+
+ blink::WebString getErrorMessage() override;
bool hasSingleSecurityOrigin() const override;
bool didPassCORSAccessCheck() const override;
@@ -178,8 +177,8 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
// Provide statistics.
unsigned decodedFrameCount() const override;
unsigned droppedFrameCount() const override;
- unsigned audioDecodedByteCount() const override;
- unsigned videoDecodedByteCount() const override;
+ size_t audioDecodedByteCount() const override;
+ size_t videoDecodedByteCount() const override;
// cc::VideoFrameProvider implementation. These methods are running on the
// compositor thread.
@@ -210,6 +209,7 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
void OnConnectedToRemoteDevice(const std::string& remote_playback_message)
override;
void OnDisconnectedFromRemoteDevice() override;
+ void OnCancelledRemotePlaybackRequest() override;
void OnDidExitFullscreen() override;
void OnMediaPlayerPlay() override;
void OnMediaPlayerPause() override;
@@ -226,9 +226,6 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
// However, the actual GlTexture is not released to keep the video screenshot.
void SuspendAndReleaseResources() override;
- // RenderFrameObserver implementation.
- void OnDestruct() override;
-
#if defined(VIDEO_HOLE)
// Calculate the boundary rectangle of the media player (i.e. location and
// size of the video frame).
@@ -238,31 +235,10 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
const gfx::RectF GetBoundaryRectangle() override;
#endif // defined(VIDEO_HOLE)
- MediaKeyException generateKeyRequest(const blink::WebString& key_system,
- const unsigned char* init_data,
- unsigned init_data_length) override;
- MediaKeyException addKey(const blink::WebString& key_system,
- const unsigned char* key,
- unsigned key_length,
- const unsigned char* init_data,
- unsigned init_data_length,
- const blink::WebString& session_id) override;
- MediaKeyException cancelKeyRequest(
- const blink::WebString& key_system,
- const blink::WebString& session_id) override;
-
void setContentDecryptionModule(
blink::WebContentDecryptionModule* cdm,
blink::WebContentDecryptionModuleResult result) override;
- void OnKeyAdded(const std::string& session_id);
- void OnKeyError(const std::string& session_id,
- media::MediaKeys::KeyError error_code,
- uint32_t system_code);
- void OnKeyMessage(const std::string& session_id,
- const std::vector<uint8_t>& message,
- const GURL& destination_url);
-
void OnMediaSourceOpened(blink::WebMediaSource* web_media_source);
void OnEncryptedMediaInitData(media::EmeInitDataType init_data_type,
@@ -272,6 +248,14 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
// is not available.
void OnWaitingForDecryptionKey() override;
+ // WebMediaPlayerDelegate::Observer implementation.
+ void OnHidden() override;
+ void OnShown() override;
+ void OnSuspendRequested(bool must_suspend) override;
+ void OnPlay() override;
+ void OnPause() override;
+ void OnVolumeMultiplierUpdate(double multiplier) override;
+
protected:
// Helper method to update the playing state.
void UpdatePlayingState(bool is_playing_);
@@ -306,20 +290,6 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
bool IsKeySystemSupported(const std::string& key_system);
bool IsLocalResource();
- // Actually do the work for generateKeyRequest/addKey so they can easily
- // report results to UMA.
- MediaKeyException GenerateKeyRequestInternal(const std::string& key_system,
- const unsigned char* init_data,
- unsigned init_data_length);
- MediaKeyException AddKeyInternal(const std::string& key_system,
- const unsigned char* key,
- unsigned key_length,
- const unsigned char* init_data,
- unsigned init_data_length,
- const std::string& session_id);
- MediaKeyException CancelKeyRequestInternal(const std::string& key_system,
- const std::string& session_id);
-
// Called when |cdm_context| is ready.
void OnCdmContextReady(media::CdmContext* cdm_context);
@@ -335,7 +305,7 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
// |cdm_ready_cb| provided.
// If |cdm_ready_cb| is null, the existing callback will be fired with
// NULL immediately and reset.
- void SetCdmReadyCB(const media::CdmReadyCB& cdm_ready_cb);
+ void SetCdmReadyCB(const MediaSourceDelegate::CdmReadyCB& cdm_ready_cb);
// Called when the ContentDecryptionModule has been attached to the
// pipeline/decoders.
@@ -357,12 +327,12 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
blink::WebMediaPlayerClient* const client_;
blink::WebMediaPlayerEncryptedMediaClient* const encrypted_client_;
- // |delegate_| is used to notify the browser process of the player status, so
- // that the browser process can control screen locks.
- // TODO(qinmin): Currently android mediaplayer takes care of the screen
- // lock. So this is only used for media source. Will apply this to regular
- // media tag once http://crbug.com/247892 is fixed.
+ // WebMediaPlayer notifies the |delegate_| of playback state changes using
+ // |delegate_id_|; an id provided after registering with the delegate. The
+ // WebMediaPlayer may also receive directives (play, pause) from the delegate
+ // via the WebMediaPlayerDelegate::Observer interface after registration.
base::WeakPtr<media::WebMediaPlayerDelegate> delegate_;
+ int delegate_id_;
// Callback responsible for determining if loading of media should be deferred
// for external reasons; called during load().
@@ -374,13 +344,16 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
// Size of the video.
blink::WebSize natural_size_;
- // Size that has been sent to StreamTexture.
+ // Size that has been sent to gpu::StreamTexture.
blink::WebSize cached_stream_texture_size_;
// The video frame object used for rendering by the compositor.
scoped_refptr<media::VideoFrame> current_frame_;
base::Lock current_frame_lock_;
+ // A lazily created transparent video frame to be displayed in fullscreen.
+ scoped_refptr<media::VideoFrame> fullscreen_frame_;
+
base::ThreadChecker main_thread_checker_;
// Message loop for media thread.
@@ -417,15 +390,16 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
// Owned by RenderFrameImpl.
RendererMediaPlayerManager* const player_manager_;
- // TODO(xhwang): Remove |cdm_factory_| when prefixed EME is deprecated. See
- // http://crbug.com/249976
- media::CdmFactory* const cdm_factory_;
-
- media::MediaPermission* media_permission_;
-
// Player ID assigned by the |player_manager_|.
int player_id_;
+ // User created media session id, if any.
+ //
+ // blink::WebMediaSession::DefaultID represents the non web
+ // exposed default media session. User created session ids are
+ // greater than blink::WebMediaSession::DefaultID.
+ const int media_session_id_;
+
// Current player states.
blink::WebMediaPlayer::NetworkState network_state_;
blink::WebMediaPlayer::ReadyState ready_state_;
@@ -446,6 +420,9 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
// Whether the media player is playing.
bool is_playing_;
+ // Whether the media player is pending to play.
+ bool is_play_pending_;
+
// Whether media player needs to re-establish the surface texture peer.
bool needs_establish_peer_;
@@ -476,7 +453,7 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
// blocked.
cc::VideoFrameProvider::Client* video_frame_provider_client_;
- scoped_ptr<cc_blink::WebLayerImpl> video_weblayer_;
+ std::unique_ptr<cc_blink::WebLayerImpl> video_weblayer_;
#if defined(VIDEO_HOLE)
// A rectangle represents the geometry of video frame, when computed last
@@ -495,18 +472,7 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
scoped_refptr<media::MediaLog> media_log_;
- scoped_ptr<MediaInfoLoader> info_loader_;
-
- // The currently selected key system. Empty string means that no key system
- // has been selected.
- std::string current_key_system_;
-
- // Temporary for EME v0.1. Not needed for unprefixed EME, and can be removed
- // when prefixed EME is removed.
- media::EmeInitDataType init_data_type_;
-
- // Manages decryption keys and decrypts encrypted frames.
- scoped_ptr<media::ProxyDecryptor> proxy_decryptor_;
+ std::unique_ptr<MediaInfoLoader> info_loader_;
// Non-owned pointer to the CdmContext. Updated in the constructor,
// generateKeyRequest() or setContentDecryptionModule().
@@ -516,7 +482,7 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
// side CDM will be used. This is similar to WebMediaPlayerImpl. For other key
// systems, a browser side CDM will be used and we set CDM by calling
// player_manager_->SetCdm() directly.
- media::CdmReadyCB cdm_ready_cb_;
+ MediaSourceDelegate::CdmReadyCB cdm_ready_cb_;
SkBitmap bitmap_;
@@ -533,7 +499,7 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
// as playback progresses.
media::TimeDeltaInterpolator interpolator_;
- scoped_ptr<MediaSourceDelegate> media_source_delegate_;
+ std::unique_ptr<MediaSourceDelegate> media_source_delegate_;
int frame_id_;
@@ -544,6 +510,16 @@ class WebMediaPlayerAndroid : public blink::WebMediaPlayer,
// Whether to delete the existing texture and re-create it.
bool suppress_deleting_texture_;
+ // Whether OnPlaybackComplete() has been called since the last playback.
+ bool playback_completed_;
+
+ // The last volume received by setVolume() and the last volume multiplier from
+ // OnVolumeMultiplierUpdate(). The multiplier is typical 1.0, but may be less
+ // if the WebMediaPlayerDelegate has requested a volume reduction (ducking)
+ // for a transient sound. Playout volume is derived by volume * multiplier.
+ double volume_;
+ double volume_multiplier_;
+
// NOTE: Weak pointers must be invalidated before all other member variables.
base::WeakPtrFactory<WebMediaPlayerAndroid> weak_factory_;
diff --git a/chromium/content/renderer/media/android/webmediasession_android.cc b/chromium/content/renderer/media/android/webmediasession_android.cc
index b10d5f260b9..c1a936d1e25 100644
--- a/chromium/content/renderer/media/android/webmediasession_android.cc
+++ b/chromium/content/renderer/media/android/webmediasession_android.cc
@@ -4,9 +4,13 @@
#include "content/renderer/media/android/webmediasession_android.h"
+#include <memory>
+
#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
+#include "base/memory/ptr_util.h"
+#include "content/public/common/media_metadata.h"
#include "content/renderer/media/android/renderer_media_session_manager.h"
+#include "third_party/WebKit/public/platform/modules/mediasession/WebMediaMetadata.h"
namespace content {
@@ -14,26 +18,33 @@ WebMediaSessionAndroid::WebMediaSessionAndroid(
RendererMediaSessionManager* session_manager)
: session_manager_(session_manager) {
DCHECK(session_manager_);
- session_id_ = session_manager_->RegisterMediaSession(this);
+ media_session_id_ = session_manager_->RegisterMediaSession(this);
}
WebMediaSessionAndroid::~WebMediaSessionAndroid() {
- session_manager_->UnregisterMediaSession(session_id_);
+ session_manager_->UnregisterMediaSession(media_session_id_);
}
void WebMediaSessionAndroid::activate(
blink::WebMediaSessionActivateCallback* callback) {
- session_manager_->Activate(session_id_, make_scoped_ptr(callback));
+ session_manager_->Activate(media_session_id_, base::WrapUnique(callback));
}
void WebMediaSessionAndroid::deactivate(
blink::WebMediaSessionDeactivateCallback* callback) {
- session_manager_->Deactivate(session_id_, make_scoped_ptr(callback));
+ session_manager_->Deactivate(media_session_id_, base::WrapUnique(callback));
}
void WebMediaSessionAndroid::setMetadata(
- const blink::WebMediaMetadata* metadata) {
- NOTIMPLEMENTED();
+ const blink::WebMediaMetadata* web_metadata) {
+ MediaMetadata metadata;
+ if (web_metadata) {
+ metadata.title = web_metadata->title;
+ metadata.artist = web_metadata->artist;
+ metadata.album = web_metadata->album;
+ }
+
+ session_manager_->SetMetadata(media_session_id_, metadata);
}
} // namespace content
diff --git a/chromium/content/renderer/media/android/webmediasession_android.h b/chromium/content/renderer/media/android/webmediasession_android.h
index 576079f407f..a9b3c0517c2 100644
--- a/chromium/content/renderer/media/android/webmediasession_android.h
+++ b/chromium/content/renderer/media/android/webmediasession_android.h
@@ -22,9 +22,11 @@ class CONTENT_EXPORT WebMediaSessionAndroid : public blink::WebMediaSession {
void deactivate(blink::WebMediaSessionDeactivateCallback*) override;
void setMetadata(const blink::WebMediaMetadata*) override;
+ int media_session_id() const { return media_session_id_; }
+
private:
RendererMediaSessionManager* const session_manager_;
- int session_id_;
+ int media_session_id_;
DISALLOW_COPY_AND_ASSIGN(WebMediaSessionAndroid);
};
diff --git a/chromium/content/renderer/media/android/webmediasession_android_unittest.cc b/chromium/content/renderer/media/android/webmediasession_android_unittest.cc
index 69e8138cb6d..0b870bc3a46 100644
--- a/chromium/content/renderer/media/android/webmediasession_android_unittest.cc
+++ b/chromium/content/renderer/media/android/webmediasession_android_unittest.cc
@@ -4,7 +4,8 @@
#include "content/renderer/media/android/webmediasession_android.h"
-#include "base/memory/scoped_ptr.h"
+#include <memory>
+
#include "content/common/media/media_session_messages_android.h"
#include "content/renderer/media/android/renderer_media_session_manager.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -65,11 +66,11 @@ class TestDeactivateCallback : public blink::WebMediaSessionDeactivateCallback {
};
TEST_F(WebMediaSessionTest, TestRegistration) {
- scoped_ptr<RendererMediaSessionManager> session_manager(
+ std::unique_ptr<RendererMediaSessionManager> session_manager(
new RendererMediaSessionManager(nullptr));
EXPECT_TRUE(IsSessionManagerEmpty(session_manager.get()));
{
- scoped_ptr<WebMediaSessionAndroid> session(
+ std::unique_ptr<WebMediaSessionAndroid> session(
new WebMediaSessionAndroid(session_manager.get()));
EXPECT_TRUE(SessionManagerHasSession(session_manager.get(), session.get()));
}
@@ -77,18 +78,18 @@ TEST_F(WebMediaSessionTest, TestRegistration) {
}
TEST_F(WebMediaSessionTest, TestMultipleRegistration) {
- scoped_ptr<RendererMediaSessionManager> session_manager(
+ std::unique_ptr<RendererMediaSessionManager> session_manager(
new RendererMediaSessionManager(nullptr));
EXPECT_TRUE(IsSessionManagerEmpty(session_manager.get()));
{
- scoped_ptr<WebMediaSessionAndroid> session1(
+ std::unique_ptr<WebMediaSessionAndroid> session1(
new WebMediaSessionAndroid(session_manager.get()));
EXPECT_TRUE(
SessionManagerHasSession(session_manager.get(), session1.get()));
{
- scoped_ptr<WebMediaSessionAndroid> session2(
+ std::unique_ptr<WebMediaSessionAndroid> session2(
new WebMediaSessionAndroid(session_manager.get()));
EXPECT_TRUE(
SessionManagerHasSession(session_manager.get(), session2.get()));
@@ -102,7 +103,7 @@ TEST_F(WebMediaSessionTest, TestMultipleRegistration) {
}
TEST_F(WebMediaSessionTest, TestMultipleRegistrationOutOfOrder) {
- scoped_ptr<RendererMediaSessionManager> session_manager(
+ std::unique_ptr<RendererMediaSessionManager> session_manager(
new RendererMediaSessionManager(nullptr));
EXPECT_TRUE(IsSessionManagerEmpty(session_manager.get()));
@@ -122,10 +123,10 @@ TEST_F(WebMediaSessionTest, TestMultipleRegistrationOutOfOrder) {
}
TEST_F(WebMediaSessionTest, ActivationOutOfOrder) {
- scoped_ptr<RendererMediaSessionManager> session_manager(
+ std::unique_ptr<RendererMediaSessionManager> session_manager(
new RendererMediaSessionManager(nullptr));
- scoped_ptr<WebMediaSessionAndroid> session(
+ std::unique_ptr<WebMediaSessionAndroid> session(
new WebMediaSessionAndroid(session_manager.get()));
// Request activate three times
@@ -148,10 +149,10 @@ TEST_F(WebMediaSessionTest, ActivationOutOfOrder) {
}
TEST_F(WebMediaSessionTest, ActivationInOrder) {
- scoped_ptr<RendererMediaSessionManager> session_manager(
+ std::unique_ptr<RendererMediaSessionManager> session_manager(
new RendererMediaSessionManager(nullptr));
- scoped_ptr<WebMediaSessionAndroid> session(
+ std::unique_ptr<WebMediaSessionAndroid> session(
new WebMediaSessionAndroid(session_manager.get()));
// Request activate three times
@@ -172,10 +173,10 @@ TEST_F(WebMediaSessionTest, ActivationInOrder) {
}
TEST_F(WebMediaSessionTest, ActivationInFlight) {
- scoped_ptr<RendererMediaSessionManager> session_manager(
+ std::unique_ptr<RendererMediaSessionManager> session_manager(
new RendererMediaSessionManager(nullptr));
- scoped_ptr<WebMediaSessionAndroid> session(
+ std::unique_ptr<WebMediaSessionAndroid> session(
new WebMediaSessionAndroid(session_manager.get()));
session->activate(new TestActivateCallback(this)); // request 1
@@ -202,10 +203,10 @@ TEST_F(WebMediaSessionTest, ActivationInFlight) {
}
TEST_F(WebMediaSessionTest, ActivationFailure) {
- scoped_ptr<RendererMediaSessionManager> session_manager(
+ std::unique_ptr<RendererMediaSessionManager> session_manager(
new RendererMediaSessionManager(nullptr));
- scoped_ptr<WebMediaSessionAndroid> session(
+ std::unique_ptr<WebMediaSessionAndroid> session(
new WebMediaSessionAndroid(session_manager.get()));
session->activate(new TestActivateCallback(this)); // request 1
@@ -227,10 +228,10 @@ TEST_F(WebMediaSessionTest, ActivationFailure) {
}
TEST_F(WebMediaSessionTest, Deactivation) {
- scoped_ptr<RendererMediaSessionManager> session_manager(
+ std::unique_ptr<RendererMediaSessionManager> session_manager(
new RendererMediaSessionManager(nullptr));
- scoped_ptr<WebMediaSessionAndroid> session(
+ std::unique_ptr<WebMediaSessionAndroid> session(
new WebMediaSessionAndroid(session_manager.get()));
// Request deactivate three times
diff --git a/chromium/content/renderer/media/audio_decoder.cc b/chromium/content/renderer/media/audio_decoder.cc
index d6978fe56bb..ca1b2d2467a 100644
--- a/chromium/content/renderer/media/audio_decoder.cc
+++ b/chromium/content/renderer/media/audio_decoder.cc
@@ -65,8 +65,8 @@ bool DecodeAudioFileData(
audio_data.push_back(destination_bus->channelData(i));
}
- scoped_ptr<AudioBus> audio_bus = AudioBus::WrapVector(
- number_of_frames, audio_data);
+ std::unique_ptr<AudioBus> audio_bus =
+ AudioBus::WrapVector(number_of_frames, audio_data);
// Decode the audio file data.
// TODO(crogers): If our estimate was low, then we still may fail to read
diff --git a/chromium/content/renderer/media/audio_device_factory.cc b/chromium/content/renderer/media/audio_device_factory.cc
index f3c4f0f1020..f36cf4b2d43 100644
--- a/chromium/content/renderer/media/audio_device_factory.cc
+++ b/chromium/content/renderer/media/audio_device_factory.cc
@@ -7,8 +7,11 @@
#include "base/logging.h"
#include "content/renderer/media/audio_input_message_filter.h"
#include "content/renderer/media/audio_message_filter.h"
+#include "content/renderer/media/audio_renderer_mixer_manager.h"
+#include "content/renderer/render_thread_impl.h"
#include "media/audio/audio_input_device.h"
#include "media/audio/audio_output_device.h"
+#include "media/base/audio_renderer_mixer_input.h"
#include "url/origin.h"
namespace content {
@@ -16,42 +19,150 @@ namespace content {
// static
AudioDeviceFactory* AudioDeviceFactory::factory_ = NULL;
-// static
-scoped_refptr<media::AudioOutputDevice> AudioDeviceFactory::NewOutputDevice(
+namespace {
+
+scoped_refptr<media::AudioOutputDevice> NewOutputDevice(
int render_frame_id,
int session_id,
const std::string& device_id,
const url::Origin& security_origin) {
- if (factory_) {
- media::AudioOutputDevice* const device = factory_->CreateOutputDevice(
- render_frame_id, session_id, device_id, security_origin);
- if (device)
- return device;
- }
-
AudioMessageFilter* const filter = AudioMessageFilter::Get();
- scoped_refptr<media::AudioOutputDevice> device = new media::AudioOutputDevice(
+ scoped_refptr<media::AudioOutputDevice> device(new media::AudioOutputDevice(
filter->CreateAudioOutputIPC(render_frame_id), filter->io_task_runner(),
- session_id, device_id, security_origin);
+ session_id, device_id, security_origin));
device->RequestDeviceAuthorization();
return device;
}
+// This is where we decide which audio will go to mixers and which one to
+// AudioOutpuDevice directly.
+bool IsMixable(AudioDeviceFactory::SourceType source_type) {
+ if (source_type == AudioDeviceFactory::kSourceMediaElement)
+ return true; // Must ALWAYS go through mixer.
+
+ // TODO(olka): make a decision for the rest of the sources basing on OS
+ // type and configuration parameters.
+ return false;
+}
+
+scoped_refptr<media::SwitchableAudioRendererSink> NewMixableSink(
+ int render_frame_id,
+ const std::string& device_id,
+ const url::Origin& security_origin) {
+ RenderThreadImpl* render_thread = RenderThreadImpl::current();
+ return scoped_refptr<media::AudioRendererMixerInput>(
+ render_thread->GetAudioRendererMixerManager()->CreateInput(
+ render_frame_id, device_id, security_origin));
+}
+
+scoped_refptr<media::AudioRendererSink> NewUnmixableSink(
+ int render_frame_id,
+ int session_id,
+ const std::string& device_id,
+ const url::Origin& security_origin) {
+ return NewOutputDevice(render_frame_id, session_id, device_id,
+ security_origin);
+}
+
+} // namespace
+
+scoped_refptr<media::AudioRendererSink>
+AudioDeviceFactory::NewAudioRendererMixerSink(
+ int render_frame_id,
+ int session_id,
+ const std::string& device_id,
+ const url::Origin& security_origin) {
+ if (factory_) {
+ scoped_refptr<media::AudioRendererSink> sink =
+ factory_->CreateAudioRendererMixerSink(render_frame_id, session_id,
+ device_id, security_origin);
+ if (sink)
+ return sink;
+ }
+ return NewOutputDevice(render_frame_id, session_id, device_id,
+ security_origin);
+}
+
// static
-scoped_refptr<media::AudioInputDevice> AudioDeviceFactory::NewInputDevice(
- int render_frame_id) {
+scoped_refptr<media::AudioRendererSink>
+AudioDeviceFactory::NewAudioRendererSink(SourceType source_type,
+ int render_frame_id,
+ int session_id,
+ const std::string& device_id,
+ const url::Origin& security_origin) {
if (factory_) {
- media::AudioInputDevice* const device =
- factory_->CreateInputDevice(render_frame_id);
+ scoped_refptr<media::AudioRendererSink> device =
+ factory_->CreateAudioRendererSink(source_type, render_frame_id,
+ session_id, device_id,
+ security_origin);
if (device)
return device;
}
+ if (IsMixable(source_type))
+ return NewMixableSink(render_frame_id, device_id, security_origin);
+
+ return NewUnmixableSink(render_frame_id, session_id, device_id,
+ security_origin);
+}
+
+// static
+scoped_refptr<media::SwitchableAudioRendererSink>
+AudioDeviceFactory::NewSwitchableAudioRendererSink(
+ SourceType source_type,
+ int render_frame_id,
+ int session_id,
+ const std::string& device_id,
+ const url::Origin& security_origin) {
+ if (factory_) {
+ scoped_refptr<media::SwitchableAudioRendererSink> sink =
+ factory_->CreateSwitchableAudioRendererSink(source_type,
+ render_frame_id, session_id,
+ device_id, security_origin);
+ if (sink)
+ return sink;
+ }
+
+ if (IsMixable(source_type))
+ return NewMixableSink(render_frame_id, device_id, security_origin);
+
+ // AudioOutputDevice is not RestartableAudioRendererSink, so we can't return
+ // anything for those who wants to create an unmixable sink.
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+// static
+scoped_refptr<media::AudioCapturerSource>
+AudioDeviceFactory::NewAudioCapturerSource(int render_frame_id) {
+ if (factory_) {
+ scoped_refptr<media::AudioCapturerSource> source =
+ factory_->CreateAudioCapturerSource(render_frame_id);
+ if (source)
+ return source;
+ }
+
AudioInputMessageFilter* const filter = AudioInputMessageFilter::Get();
return new media::AudioInputDevice(
filter->CreateAudioInputIPC(render_frame_id), filter->io_task_runner());
}
+// static
+// TODO(http://crbug.com/587461): Find a better way to check if device exists
+// and is authorized.
+media::OutputDeviceInfo AudioDeviceFactory::GetOutputDeviceInfo(
+ int render_frame_id,
+ int session_id,
+ const std::string& device_id,
+ const url::Origin& security_origin) {
+ scoped_refptr<media::AudioOutputDevice> device =
+ NewOutputDevice(render_frame_id, session_id, device_id, security_origin);
+
+ const media::OutputDeviceInfo& device_info = device->GetOutputDeviceInfo();
+ device->Stop(); // Must be stopped.
+ return device_info;
+}
+
AudioDeviceFactory::AudioDeviceFactory() {
DCHECK(!factory_) << "Can't register two factories at once.";
factory_ = this;
diff --git a/chromium/content/renderer/media/audio_device_factory.h b/chromium/content/renderer/media/audio_device_factory.h
index 1d6a53ad584..73ce7ee88fc 100644
--- a/chromium/content/renderer/media/audio_device_factory.h
+++ b/chromium/content/renderer/media/audio_device_factory.h
@@ -11,10 +11,12 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
+#include "media/base/output_device_info.h"
namespace media {
-class AudioInputDevice;
-class AudioOutputDevice;
+class AudioRendererSink;
+class SwitchableAudioRendererSink;
+class AudioCapturerSource;
}
namespace url {
@@ -23,12 +25,24 @@ class Origin;
namespace content {
-// A factory for creating AudioOutputDevices and AudioInputDevices. There is a
-// global factory function that can be installed for the purposes of testing to
-// provide specialized implementations.
+// A factory for creating AudioRendererSinks and AudioCapturerSources. There is
+// a global factory function that can be installed for the purposes of testing
+// to provide specialized implementations.
+// TODO(olka): rename it, probably split it into AudioRendererSinkFactory and
+// AudioCapturerSourceFactory.
class CONTENT_EXPORT AudioDeviceFactory {
public:
- // Creates an AudioOutputDevice.
+ // Types of audio sources.
+ enum SourceType {
+ kSourceNone = 0,
+ kSourceMediaElement,
+ kSourceWebRtc,
+ kSourceNonRtcAudioTrack,
+ kSourceWebAudio,
+ kSourceLast = kSourceWebAudio // Only used for validation of format.
+ };
+
+ // Creates a sink for AudioRendererMixer.
// |render_frame_id| refers to the RenderFrame containing the entity
// producing the audio. If |session_id| is nonzero, it is used by the browser
// to select the correct input device ID and its associated output device, if
@@ -36,16 +50,45 @@ class CONTENT_EXPORT AudioDeviceFactory {
// identify the output device to use.
// If |session_id| is zero and |device_id| and |security_origin| are empty,
// the default output device will be selected.
- static scoped_refptr<media::AudioOutputDevice> NewOutputDevice(
+ static scoped_refptr<media::AudioRendererSink> NewAudioRendererMixerSink(
+ int render_frame_id,
+ int session_id,
+ const std::string& device_id,
+ const url::Origin& security_origin);
+
+ // Creates an AudioRendererSink bound to an AudioOutputDevice.
+ // Basing on |source_type| and build configuration, audio played out through
+ // the sink goes to AOD directly or can be mixed with other audio before that.
+ // TODO(olka): merge it with NewRestartableOutputDevice() as soon as
+ // AudioOutputDevice is fixed to be restartable.
+ static scoped_refptr<media::AudioRendererSink> NewAudioRendererSink(
+ SourceType source_type,
int render_frame_id,
int session_id,
const std::string& device_id,
const url::Origin& security_origin);
- // Creates an AudioInputDevice using the currently registered factory.
+ // Creates a SwitchableAudioRendererSink bound to an AudioOutputDevice
+ // Basing on |source_type| and build configuration, audio played out through
+ // the sink goes to AOD directly or can be mixed with other audio before that.
+ static scoped_refptr<media::SwitchableAudioRendererSink>
+ NewSwitchableAudioRendererSink(SourceType source_type,
+ int render_frame_id,
+ int session_id,
+ const std::string& device_id,
+ const url::Origin& security_origin);
+
+ // A helper to get device info in the absence of AudioOutputDevice.
+ static media::OutputDeviceInfo GetOutputDeviceInfo(
+ int render_frame_id,
+ int session_id,
+ const std::string& device_id,
+ const url::Origin& security_origin);
+
+ // Creates an AudioCapturerSource using the currently registered factory.
// |render_frame_id| refers to the RenderFrame containing the entity
// consuming the audio.
- static scoped_refptr<media::AudioInputDevice> NewInputDevice(
+ static scoped_refptr<media::AudioCapturerSource> NewAudioCapturerSource(
int render_frame_id);
protected:
@@ -56,12 +99,28 @@ class CONTENT_EXPORT AudioDeviceFactory {
// functions to provide alternate audio device implementations.
// If the return value of either of these function is NULL, we fall back
// on the default implementation.
- virtual media::AudioOutputDevice* CreateOutputDevice(
+ virtual scoped_refptr<media::AudioRendererSink> CreateAudioRendererMixerSink(
int render_frame_id,
int sesssion_id,
const std::string& device_id,
const url::Origin& security_origin) = 0;
- virtual media::AudioInputDevice* CreateInputDevice(int render_frame_id) = 0;
+
+ virtual scoped_refptr<media::AudioRendererSink> CreateAudioRendererSink(
+ SourceType source_type,
+ int render_frame_id,
+ int sesssion_id,
+ const std::string& device_id,
+ const url::Origin& security_origin) = 0;
+
+ virtual scoped_refptr<media::SwitchableAudioRendererSink>
+ CreateSwitchableAudioRendererSink(SourceType source_type,
+ int render_frame_id,
+ int sesssion_id,
+ const std::string& device_id,
+ const url::Origin& security_origin) = 0;
+
+ virtual scoped_refptr<media::AudioCapturerSource> CreateAudioCapturerSource(
+ int render_frame_id) = 0;
private:
// The current globally registered factory. This is NULL when we should
diff --git a/chromium/content/renderer/media/audio_input_message_filter.cc b/chromium/content/renderer/media/audio_input_message_filter.cc
index 09a417426af..672e1febeb3 100644
--- a/chromium/content/renderer/media/audio_input_message_filter.cc
+++ b/chromium/content/renderer/media/audio_input_message_filter.cc
@@ -178,10 +178,10 @@ AudioInputMessageFilter::AudioInputIPCImpl::AudioInputIPCImpl(
AudioInputMessageFilter::AudioInputIPCImpl::~AudioInputIPCImpl() {}
-scoped_ptr<media::AudioInputIPC> AudioInputMessageFilter::CreateAudioInputIPC(
- int render_frame_id) {
+std::unique_ptr<media::AudioInputIPC>
+AudioInputMessageFilter::CreateAudioInputIPC(int render_frame_id) {
DCHECK_GT(render_frame_id, 0);
- return scoped_ptr<media::AudioInputIPC>(
+ return std::unique_ptr<media::AudioInputIPC>(
new AudioInputIPCImpl(this, render_frame_id));
}
diff --git a/chromium/content/renderer/media/audio_input_message_filter.h b/chromium/content/renderer/media/audio_input_message_filter.h
index 30a8d2395b3..548234b7fc8 100644
--- a/chromium/content/renderer/media/audio_input_message_filter.h
+++ b/chromium/content/renderer/media/audio_input_message_filter.h
@@ -7,9 +7,10 @@
#include <stdint.h>
+#include <memory>
+
#include "base/id_map.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory.h"
#include "base/sync_socket.h"
#include "build/build_config.h"
@@ -40,7 +41,8 @@ class CONTENT_EXPORT AudioInputMessageFilter : public IPC::MessageFilter {
//
// The returned object is not thread-safe, and must be used on
// |io_task_runner|.
- scoped_ptr<media::AudioInputIPC> CreateAudioInputIPC(int render_frame_id);
+ std::unique_ptr<media::AudioInputIPC> CreateAudioInputIPC(
+ int render_frame_id);
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner() const {
return io_task_runner_;
diff --git a/chromium/content/renderer/media/audio_message_filter.cc b/chromium/content/renderer/media/audio_message_filter.cc
index 7ecf9b16414..c3db8e29afe 100644
--- a/chromium/content/renderer/media/audio_message_filter.cc
+++ b/chromium/content/renderer/media/audio_message_filter.cc
@@ -75,10 +75,10 @@ AudioMessageFilter::AudioOutputIPCImpl::AudioOutputIPCImpl(
AudioMessageFilter::AudioOutputIPCImpl::~AudioOutputIPCImpl() {}
-scoped_ptr<media::AudioOutputIPC> AudioMessageFilter::CreateAudioOutputIPC(
+std::unique_ptr<media::AudioOutputIPC> AudioMessageFilter::CreateAudioOutputIPC(
int render_frame_id) {
DCHECK_GT(render_frame_id, 0);
- return scoped_ptr<media::AudioOutputIPC>(
+ return std::unique_ptr<media::AudioOutputIPC>(
new AudioOutputIPCImpl(this, render_frame_id));
}
diff --git a/chromium/content/renderer/media/audio_message_filter.h b/chromium/content/renderer/media/audio_message_filter.h
index dcdc7cd361a..15db8df3130 100644
--- a/chromium/content/renderer/media/audio_message_filter.h
+++ b/chromium/content/renderer/media/audio_message_filter.h
@@ -7,10 +7,11 @@
#include <stdint.h>
+#include <memory>
+
#include "base/gtest_prod_util.h"
#include "base/id_map.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory.h"
#include "base/sync_socket.h"
#include "base/synchronization/lock.h"
@@ -42,7 +43,8 @@ class CONTENT_EXPORT AudioMessageFilter : public IPC::MessageFilter {
//
// The returned object is not thread-safe, and must be used on
// |io_task_runner|.
- scoped_ptr<media::AudioOutputIPC> CreateAudioOutputIPC(int render_frame_id);
+ std::unique_ptr<media::AudioOutputIPC> CreateAudioOutputIPC(
+ int render_frame_id);
// IO task runner associated with this message filter.
base::SingleThreadTaskRunner* io_task_runner() const {
diff --git a/chromium/content/renderer/media/audio_message_filter_unittest.cc b/chromium/content/renderer/media/audio_message_filter_unittest.cc
index 46302a4038a..2ae2c3041b9 100644
--- a/chromium/content/renderer/media/audio_message_filter_unittest.cc
+++ b/chromium/content/renderer/media/audio_message_filter_unittest.cc
@@ -107,7 +107,7 @@ TEST(AudioMessageFilterTest, Basic) {
new AudioMessageFilter(message_loop.task_runner()));
MockAudioDelegate delegate;
- const scoped_ptr<media::AudioOutputIPC> ipc =
+ const std::unique_ptr<media::AudioOutputIPC> ipc =
filter->CreateAudioOutputIPC(kRenderFrameId);
static const int kSessionId = 0;
static const std::string kDeviceId;
@@ -159,9 +159,9 @@ TEST(AudioMessageFilterTest, Delegates) {
MockAudioDelegate delegate1;
MockAudioDelegate delegate2;
- const scoped_ptr<media::AudioOutputIPC> ipc1 =
+ const std::unique_ptr<media::AudioOutputIPC> ipc1 =
filter->CreateAudioOutputIPC(kRenderFrameId);
- const scoped_ptr<media::AudioOutputIPC> ipc2 =
+ const std::unique_ptr<media::AudioOutputIPC> ipc2 =
filter->CreateAudioOutputIPC(kRenderFrameId);
ipc1->CreateStream(&delegate1, media::AudioParameters());
ipc2->CreateStream(&delegate2, media::AudioParameters());
diff --git a/chromium/content/renderer/media/audio_renderer_mixer_manager.cc b/chromium/content/renderer/media/audio_renderer_mixer_manager.cc
index 97d0e153fc7..14359b3b967 100644
--- a/chromium/content/renderer/media/audio_renderer_mixer_manager.cc
+++ b/chromium/content/renderer/media/audio_renderer_mixer_manager.cc
@@ -17,8 +17,7 @@
namespace content {
-AudioRendererMixerManager::AudioRendererMixerManager()
- : sink_for_testing_(nullptr) {}
+AudioRendererMixerManager::AudioRendererMixerManager() {}
AudioRendererMixerManager::~AudioRendererMixerManager() {
// References to AudioRendererMixers may be owned by garbage collected
@@ -35,12 +34,8 @@ media::AudioRendererMixerInput* AudioRendererMixerManager::CreateInput(
source_render_frame_id),
base::Bind(&AudioRendererMixerManager::RemoveMixer,
base::Unretained(this), source_render_frame_id),
- device_id, security_origin);
-}
-
-void AudioRendererMixerManager::SetAudioRendererSinkForTesting(
- media::AudioRendererSink* sink) {
- sink_for_testing_ = sink;
+ device_id,
+ security_origin);
}
media::AudioRendererMixer* AudioRendererMixerManager::GetMixer(
@@ -66,40 +61,35 @@ media::AudioRendererMixer* AudioRendererMixerManager::GetMixer(
}
scoped_refptr<media::AudioRendererSink> sink =
- sink_for_testing_
- ? sink_for_testing_
- : AudioDeviceFactory::NewOutputDevice(source_render_frame_id, 0,
- device_id, security_origin)
- .get();
-
- media::OutputDeviceStatus new_device_status =
- sink->GetOutputDevice()->GetDeviceStatus();
+ AudioDeviceFactory::NewAudioRendererMixerSink(source_render_frame_id, 0,
+ device_id, security_origin);
+
+ const media::OutputDeviceInfo& device_info = sink->GetOutputDeviceInfo();
if (device_status)
- *device_status = new_device_status;
- if (new_device_status != media::OUTPUT_DEVICE_STATUS_OK) {
+ *device_status = device_info.device_status();
+ if (device_info.device_status() != media::OUTPUT_DEVICE_STATUS_OK) {
sink->Stop();
return nullptr;
}
- media::AudioParameters hardware_params =
- sink->GetOutputDevice()->GetOutputParameters();
-
-// On ChromeOS and Android we can rely on the playback device to handle
-// resampling, so don't waste cycles on it here.
-#if defined(OS_CHROMEOS) || defined(OS_ANDROID)
+ // On ChromeOS as well as when a fake device is used, we can rely on the
+ // playback device to handle resampling, so don't waste cycles on it here.
int sample_rate = params.sample_rate();
-#else
- int sample_rate =
- hardware_params.format() != media::AudioParameters::AUDIO_FAKE
- ? hardware_params.sample_rate()
- : params.sample_rate();
-#endif
-
int buffer_size =
- hardware_params.format() != media::AudioParameters::AUDIO_FAKE
- ? media::AudioHardwareConfig::GetHighLatencyBufferSize(
- hardware_params)
- : params.frames_per_buffer();
+ media::AudioHardwareConfig::GetHighLatencyBufferSize(sample_rate, 0);
+
+#if !defined(OS_CHROMEOS)
+ const media::AudioParameters& hardware_params = device_info.output_params();
+
+ // If we have valid, non-fake hardware parameters, use them. Otherwise, pass
+ // on the input params and let the browser side handle automatic fallback.
+ if (hardware_params.format() != media::AudioParameters::AUDIO_FAKE &&
+ hardware_params.IsValid()) {
+ sample_rate = hardware_params.sample_rate();
+ buffer_size = media::AudioHardwareConfig::GetHighLatencyBufferSize(
+ sample_rate, hardware_params.frames_per_buffer());
+ }
+#endif
// Create output parameters based on the audio hardware configuration for
// passing on to the output sink. Force to 16-bit output for now since we
@@ -107,11 +97,7 @@ media::AudioRendererMixer* AudioRendererMixerManager::GetMixer(
media::AudioParameters output_params(
media::AudioParameters::AUDIO_PCM_LOW_LATENCY, params.channel_layout(),
sample_rate, 16, buffer_size);
-
- // If we've created invalid output parameters, simply pass on the input
- // params and let the browser side handle automatic fallback.
- if (!output_params.IsValid())
- output_params = params;
+ DCHECK(output_params.IsValid());
media::AudioRendererMixer* mixer =
new media::AudioRendererMixer(output_params, sink);
@@ -150,4 +136,6 @@ AudioRendererMixerManager::MixerKey::MixerKey(
device_id(device_id),
security_origin(security_origin) {}
+AudioRendererMixerManager::MixerKey::MixerKey(const MixerKey& other) = default;
+
} // namespace content
diff --git a/chromium/content/renderer/media/audio_renderer_mixer_manager.h b/chromium/content/renderer/media/audio_renderer_mixer_manager.h
index fa8f9620857..a245a10294b 100644
--- a/chromium/content/renderer/media/audio_renderer_mixer_manager.h
+++ b/chromium/content/renderer/media/audio_renderer_mixer_manager.h
@@ -13,7 +13,7 @@
#include "base/synchronization/lock.h"
#include "content/common/content_export.h"
#include "media/audio/audio_parameters.h"
-#include "media/base/output_device.h"
+#include "media/base/output_device_info.h"
#include "url/origin.h"
namespace media {
@@ -80,6 +80,7 @@ class CONTENT_EXPORT AudioRendererMixerManager {
const media::AudioParameters& params,
const std::string& device_id,
const url::Origin& security_origin);
+ MixerKey(const MixerKey& other);
int source_render_frame_id;
media::AudioParameters params;
std::string device_id;
@@ -118,15 +119,10 @@ class CONTENT_EXPORT AudioRendererMixerManager {
typedef std::map<MixerKey, AudioRendererMixerReference, MixerKeyCompare>
AudioRendererMixerMap;
- // Overrides the AudioRendererSink implementation for unit testing.
- void SetAudioRendererSinkForTesting(media::AudioRendererSink* sink);
-
// Active mixers.
AudioRendererMixerMap mixers_;
base::Lock mixers_lock_;
- media::AudioRendererSink* sink_for_testing_;
-
DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerManager);
};
diff --git a/chromium/content/renderer/media/audio_renderer_mixer_manager_unittest.cc b/chromium/content/renderer/media/audio_renderer_mixer_manager_unittest.cc
index b1371b22283..66c2d43caf2 100644
--- a/chromium/content/renderer/media/audio_renderer_mixer_manager_unittest.cc
+++ b/chromium/content/renderer/media/audio_renderer_mixer_manager_unittest.cc
@@ -2,20 +2,24 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "content/renderer/media/audio_renderer_mixer_manager.h"
+
+#include <memory>
+
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "content/renderer/media/audio_renderer_mixer_manager.h"
-#include "ipc/ipc_message.h"
+#include "content/renderer/media/audio_device_factory.h"
+#include "media/audio/audio_manager_base.h"
#include "media/audio/audio_parameters.h"
-#include "media/base/audio_hardware_config.h"
+#include "media/base/audio_capturer_source.h"
#include "media/base/audio_renderer_mixer.h"
#include "media/base/audio_renderer_mixer_input.h"
#include "media/base/fake_audio_render_callback.h"
#include "media/base/mock_audio_renderer_sink.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
namespace content {
@@ -25,24 +29,26 @@ static const int kBufferSize = 8192;
static const media::ChannelLayout kChannelLayout = media::CHANNEL_LAYOUT_STEREO;
static const media::ChannelLayout kAnotherChannelLayout =
media::CHANNEL_LAYOUT_2_1;
-static const std::string kDefaultDeviceId;
-static const url::Origin kSecurityOrigin;
+static const char* const kDefaultDeviceId =
+ media::AudioManagerBase::kDefaultDeviceId;
+static const char kAnotherDeviceId[] = "another-device-id";
+static const char kNonexistentDeviceId[] = "nonexistent-device-id";
static const int kRenderFrameId = 124;
static const int kAnotherRenderFrameId = 678;
using media::AudioParameters;
-class AudioRendererMixerManagerTest : public testing::Test {
+class AudioRendererMixerManagerTest : public testing::Test,
+ public AudioDeviceFactory {
public:
- AudioRendererMixerManagerTest() {
- manager_.reset(new AudioRendererMixerManager());
-
- // We don't want to deal with instantiating a real AudioOutputDevice since
- // it's not important to our testing, so we inject a mock.
- mock_sink_ = new media::MockAudioRendererSink();
- manager_->SetAudioRendererSinkForTesting(mock_sink_.get());
- }
+ AudioRendererMixerManagerTest()
+ : manager_(new AudioRendererMixerManager()),
+ mock_sink_(new media::MockAudioRendererSink()),
+ mock_sink_no_device_(new media::MockAudioRendererSink(
+ kNonexistentDeviceId,
+ media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND)),
+ kSecurityOrigin2(GURL("http://localhost")) {}
media::AudioRendererMixer* GetMixer(
int source_render_frame_id,
@@ -62,20 +68,55 @@ class AudioRendererMixerManagerTest : public testing::Test {
security_origin);
}
- void UseNonexistentSink() {
- mock_sink_ = new media::MockAudioRendererSink(
- media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND);
- manager_->SetAudioRendererSinkForTesting(mock_sink_.get());
- }
-
// Number of instantiated mixers.
int mixer_count() {
return manager_->mixers_.size();
}
protected:
- scoped_ptr<AudioRendererMixerManager> manager_;
+ MOCK_METHOD1(CreateAudioCapturerSource,
+ scoped_refptr<media::AudioCapturerSource>(int));
+ MOCK_METHOD5(
+ CreateSwitchableAudioRendererSink,
+ scoped_refptr<media::SwitchableAudioRendererSink>(SourceType,
+ int,
+ int,
+ const std::string&,
+ const url::Origin&));
+ MOCK_METHOD5(CreateAudioRendererSink,
+ scoped_refptr<media::AudioRendererSink>(SourceType,
+ int,
+ int,
+ const std::string&,
+ const url::Origin&));
+
+ scoped_refptr<media::AudioRendererSink> CreateAudioRendererMixerSink(
+ int render_frame_id,
+ int session_id,
+ const std::string& device_id,
+ const url::Origin& security_origin) {
+ if ((device_id == kDefaultDeviceId) || (device_id == kAnotherDeviceId)) {
+ // We don't care about separate sinks for these devices
+ return mock_sink_;
+ }
+ if (device_id == kNonexistentDeviceId) {
+ return mock_sink_no_device_;
+ }
+ if (device_id.empty()) {
+ return mock_sink_;
+ }
+
+ NOTREACHED();
+ return nullptr;
+ }
+
+ std::unique_ptr<AudioRendererMixerManager> manager_;
scoped_refptr<media::MockAudioRendererSink> mock_sink_;
+ scoped_refptr<media::MockAudioRendererSink> mock_sink_no_device_;
+
+ // To avoid global/static non-POD constants.
+ const url::Origin kSecurityOrigin;
+ const url::Origin kSecurityOrigin2;
private:
DISALLOW_COPY_AND_ASSIGN(AudioRendererMixerManagerTest);
@@ -90,7 +131,7 @@ TEST_F(AudioRendererMixerManagerTest, GetRemoveMixer) {
EXPECT_CALL(*mock_sink_.get(), Stop()).Times(2);
// There should be no mixers outstanding to start with.
- EXPECT_EQ(mixer_count(), 0);
+ EXPECT_EQ(0, mixer_count());
media::AudioParameters params1(
AudioParameters::AUDIO_PCM_LINEAR, kChannelLayout, kSampleRate,
@@ -99,16 +140,16 @@ TEST_F(AudioRendererMixerManagerTest, GetRemoveMixer) {
media::AudioRendererMixer* mixer1 = GetMixer(
kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin, nullptr);
ASSERT_TRUE(mixer1);
- EXPECT_EQ(mixer_count(), 1);
+ EXPECT_EQ(1, mixer_count());
// The same parameters should return the same mixer1.
EXPECT_EQ(mixer1, GetMixer(kRenderFrameId, params1, kDefaultDeviceId,
kSecurityOrigin, nullptr));
- EXPECT_EQ(mixer_count(), 1);
+ EXPECT_EQ(1, mixer_count());
// Remove the extra mixer we just acquired.
RemoveMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin);
- EXPECT_EQ(mixer_count(), 1);
+ EXPECT_EQ(1, mixer_count());
media::AudioParameters params2(
AudioParameters::AUDIO_PCM_LINEAR, kAnotherChannelLayout, kSampleRate * 2,
@@ -116,16 +157,16 @@ TEST_F(AudioRendererMixerManagerTest, GetRemoveMixer) {
media::AudioRendererMixer* mixer2 = GetMixer(
kRenderFrameId, params2, kDefaultDeviceId, kSecurityOrigin, nullptr);
ASSERT_TRUE(mixer2);
- EXPECT_EQ(mixer_count(), 2);
+ EXPECT_EQ(2, mixer_count());
// Different parameters should result in a different mixer1.
EXPECT_NE(mixer1, mixer2);
// Remove both outstanding mixers.
RemoveMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin);
- EXPECT_EQ(mixer_count(), 1);
+ EXPECT_EQ(1, mixer_count());
RemoveMixer(kRenderFrameId, params2, kDefaultDeviceId, kSecurityOrigin);
- EXPECT_EQ(mixer_count(), 0);
+ EXPECT_EQ(0, mixer_count());
}
// Verify GetMixer() correctly deduplicates mixer with irrelevant AudioParameter
@@ -143,7 +184,7 @@ TEST_F(AudioRendererMixerManagerTest, MixerReuse) {
media::AudioRendererMixer* mixer1 = GetMixer(
kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin, nullptr);
ASSERT_TRUE(mixer1);
- EXPECT_EQ(mixer_count(), 1);
+ EXPECT_EQ(1, mixer_count());
// Different sample rates, formats, bit depths, and buffer sizes should not
// result in a different mixer.
@@ -154,9 +195,9 @@ TEST_F(AudioRendererMixerManagerTest, MixerReuse) {
kBufferSize * 2);
EXPECT_EQ(mixer1, GetMixer(kRenderFrameId, params2, kDefaultDeviceId,
kSecurityOrigin, nullptr));
- EXPECT_EQ(mixer_count(), 1);
+ EXPECT_EQ(1, mixer_count());
RemoveMixer(kRenderFrameId, params2, kDefaultDeviceId, kSecurityOrigin);
- EXPECT_EQ(mixer_count(), 1);
+ EXPECT_EQ(1, mixer_count());
// Modify some parameters that do matter: channel layout
media::AudioParameters params3(AudioParameters::AUDIO_PCM_LOW_LATENCY,
@@ -168,13 +209,13 @@ TEST_F(AudioRendererMixerManagerTest, MixerReuse) {
EXPECT_NE(mixer1, GetMixer(kRenderFrameId, params3, kDefaultDeviceId,
kSecurityOrigin, nullptr));
- EXPECT_EQ(mixer_count(), 2);
+ EXPECT_EQ(2, mixer_count());
RemoveMixer(kRenderFrameId, params3, kDefaultDeviceId, kSecurityOrigin);
- EXPECT_EQ(mixer_count(), 1);
+ EXPECT_EQ(1, mixer_count());
// Remove final mixer.
RemoveMixer(kRenderFrameId, params1, kDefaultDeviceId, kSecurityOrigin);
- EXPECT_EQ(mixer_count(), 0);
+ EXPECT_EQ(0, mixer_count());
}
// Verify CreateInput() provides AudioRendererMixerInput with the appropriate
@@ -192,33 +233,33 @@ TEST_F(AudioRendererMixerManagerTest, CreateInput) {
kBitsPerChannel, kBufferSize);
// Create two mixer inputs and ensure this doesn't instantiate any mixers yet.
- EXPECT_EQ(mixer_count(), 0);
+ EXPECT_EQ(0, mixer_count());
media::FakeAudioRenderCallback callback(0);
scoped_refptr<media::AudioRendererMixerInput> input(
manager_->CreateInput(kRenderFrameId, kDefaultDeviceId, kSecurityOrigin));
input->Initialize(params, &callback);
- EXPECT_EQ(mixer_count(), 0);
+ EXPECT_EQ(0, mixer_count());
media::FakeAudioRenderCallback another_callback(1);
scoped_refptr<media::AudioRendererMixerInput> another_input(
manager_->CreateInput(kAnotherRenderFrameId, kDefaultDeviceId,
kSecurityOrigin));
another_input->Initialize(params, &another_callback);
- EXPECT_EQ(mixer_count(), 0);
+ EXPECT_EQ(0, mixer_count());
// Implicitly test that AudioRendererMixerInput was provided with the expected
// callbacks needed to acquire an AudioRendererMixer and remove it.
input->Start();
- EXPECT_EQ(mixer_count(), 1);
+ EXPECT_EQ(1, mixer_count());
another_input->Start();
- EXPECT_EQ(mixer_count(), 2);
+ EXPECT_EQ(2, mixer_count());
// Destroying the inputs should destroy the mixers.
input->Stop();
- input = NULL;
- EXPECT_EQ(mixer_count(), 1);
+ input = nullptr;
+ EXPECT_EQ(1, mixer_count());
another_input->Stop();
- another_input = NULL;
- EXPECT_EQ(mixer_count(), 0);
+ another_input = nullptr;
+ EXPECT_EQ(0, mixer_count());
}
// Verify GetMixer() correctly creates different mixers with the same
@@ -226,7 +267,7 @@ TEST_F(AudioRendererMixerManagerTest, CreateInput) {
TEST_F(AudioRendererMixerManagerTest, MixerDevices) {
EXPECT_CALL(*mock_sink_.get(), Start()).Times(3);
EXPECT_CALL(*mock_sink_.get(), Stop()).Times(3);
- EXPECT_EQ(mixer_count(), 0);
+ EXPECT_EQ(0, mixer_count());
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
kChannelLayout, kSampleRate, kBitsPerChannel,
@@ -234,48 +275,44 @@ TEST_F(AudioRendererMixerManagerTest, MixerDevices) {
media::AudioRendererMixer* mixer1 = GetMixer(
kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin, nullptr);
ASSERT_TRUE(mixer1);
- EXPECT_EQ(mixer_count(), 1);
+ EXPECT_EQ(1, mixer_count());
- std::string device_id2("fake-device-id");
- media::AudioRendererMixer* mixer2 =
- GetMixer(kRenderFrameId, params, device_id2, kSecurityOrigin, nullptr);
+ media::AudioRendererMixer* mixer2 = GetMixer(
+ kRenderFrameId, params, kAnotherDeviceId, kSecurityOrigin, nullptr);
ASSERT_TRUE(mixer2);
- EXPECT_EQ(mixer_count(), 2);
+ EXPECT_EQ(2, mixer_count());
EXPECT_NE(mixer1, mixer2);
- url::Origin security_origin2(GURL("http://localhost"));
media::AudioRendererMixer* mixer3 = GetMixer(
- kRenderFrameId, params, kDefaultDeviceId, security_origin2, nullptr);
+ kRenderFrameId, params, kAnotherDeviceId, kSecurityOrigin2, nullptr);
ASSERT_TRUE(mixer3);
- EXPECT_EQ(mixer_count(), 3);
+ EXPECT_EQ(3, mixer_count());
EXPECT_NE(mixer1, mixer3);
EXPECT_NE(mixer2, mixer3);
RemoveMixer(kRenderFrameId, params, kDefaultDeviceId, kSecurityOrigin);
- EXPECT_EQ(mixer_count(), 2);
- RemoveMixer(kRenderFrameId, params, device_id2, kSecurityOrigin);
- EXPECT_EQ(mixer_count(), 1);
- RemoveMixer(kRenderFrameId, params, kDefaultDeviceId, security_origin2);
- EXPECT_EQ(mixer_count(), 0);
+ EXPECT_EQ(2, mixer_count());
+ RemoveMixer(kRenderFrameId, params, kAnotherDeviceId, kSecurityOrigin);
+ EXPECT_EQ(1, mixer_count());
+ RemoveMixer(kRenderFrameId, params, kAnotherDeviceId, kSecurityOrigin2);
+ EXPECT_EQ(0, mixer_count());
}
// Verify that GetMixer() correctly returns a null mixer and an appropriate
// status code when a nonexistent device is requested.
TEST_F(AudioRendererMixerManagerTest, NonexistentDevice) {
- EXPECT_EQ(mixer_count(), 0);
- UseNonexistentSink();
+ EXPECT_EQ(0, mixer_count());
media::AudioParameters params(AudioParameters::AUDIO_PCM_LINEAR,
kChannelLayout, kSampleRate, kBitsPerChannel,
kBufferSize);
- std::string nonexistent_device_id("nonexistent-device-id");
media::OutputDeviceStatus device_status = media::OUTPUT_DEVICE_STATUS_OK;
- EXPECT_CALL(*mock_sink_.get(), Stop());
+ EXPECT_CALL(*mock_sink_no_device_.get(), Stop());
media::AudioRendererMixer* mixer =
- GetMixer(kRenderFrameId, params, nonexistent_device_id, kSecurityOrigin,
+ GetMixer(kRenderFrameId, params, kNonexistentDeviceId, kSecurityOrigin,
&device_status);
EXPECT_FALSE(mixer);
- EXPECT_EQ(device_status, media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND);
- EXPECT_EQ(mixer_count(), 0);
+ EXPECT_EQ(media::OUTPUT_DEVICE_STATUS_ERROR_NOT_FOUND, device_status);
+ EXPECT_EQ(0, mixer_count());
}
} // namespace content
diff --git a/chromium/content/renderer/media/audio_repetition_detector_unittest.cc b/chromium/content/renderer/media/audio_repetition_detector_unittest.cc
index 487a7a09e0e..eca9b367263 100644
--- a/chromium/content/renderer/media/audio_repetition_detector_unittest.cc
+++ b/chromium/content/renderer/media/audio_repetition_detector_unittest.cc
@@ -2,14 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "content/renderer/media/audio_repetition_detector.h"
+
#include <stddef.h>
#include <map>
+#include <memory>
#include "base/bind.h"
#include "base/macros.h"
#include "base/rand_util.h"
-#include "content/renderer/media/audio_repetition_detector.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -91,7 +93,7 @@ class AudioRepetitionDetectorTest : public ::testing::Test {
static const size_t kNumChannels = 2;
// Get memory to store interleaved stereo.
- scoped_ptr<float[]> tester_stereo(
+ std::unique_ptr<float[]> tester_stereo(
new float[num_frames * kNumChannels]);
for (size_t idx = 0; idx < num_frames; ++idx, ++tester) {
@@ -116,7 +118,7 @@ class AudioRepetitionDetectorTest : public ::testing::Test {
}
private:
- scoped_ptr<AudioRepetitionDetectorForTest> detector_;
+ std::unique_ptr<AudioRepetitionDetectorForTest> detector_;
};
TEST_F(AudioRepetitionDetectorTest, Basic) {
diff --git a/chromium/content/renderer/media/audio_track_recorder.cc b/chromium/content/renderer/media/audio_track_recorder.cc
index 71f35cb888d..f13c6b3d5f3 100644
--- a/chromium/content/renderer/media/audio_track_recorder.cc
+++ b/chromium/content/renderer/media/audio_track_recorder.cc
@@ -10,94 +10,161 @@
#include "base/bind.h"
#include "base/macros.h"
#include "base/stl_util.h"
+#include "content/renderer/media/media_stream_audio_track.h"
#include "media/audio/audio_parameters.h"
#include "media/base/audio_bus.h"
+#include "media/base/audio_converter.h"
+#include "media/base/audio_fifo.h"
#include "media/base/bind_to_current_loop.h"
#include "third_party/opus/src/include/opus.h"
// Note that this code follows the Chrome media convention of defining a "frame"
-// as "one multi-channel sample" as opposed to another common definition
-// meaning "a chunk of samples". Here this second definition of "frame" is
-// called a "buffer"; so what might be called "frame duration" is instead
-// "buffer duration", and so on.
+// as "one multi-channel sample" as opposed to another common definition meaning
+// "a chunk of samples". Here this second definition of "frame" is called a
+// "buffer"; so what might be called "frame duration" is instead "buffer
+// duration", and so on.
namespace content {
namespace {
-enum {
- // This is the recommended value, according to documentation in
+enum : int {
+ // Recommended value for opus_encode_float(), according to documentation in
// third_party/opus/src/include/opus.h, so that the Opus encoder does not
- // degrade the audio due to memory constraints.
- OPUS_MAX_PAYLOAD_SIZE = 4000,
+ // degrade the audio due to memory constraints, and is independent of the
+ // duration of the encoded buffer.
+ kOpusMaxDataBytes = 4000,
- // Support for max sampling rate of 48KHz, 2 channels, 60 ms duration.
- MAX_SAMPLES_PER_BUFFER = 48 * 2 * 60,
+ // Opus preferred sampling rate for encoding. This is also the one WebM likes
+ // to have: https://wiki.xiph.org/MatroskaOpus.
+ kOpusPreferredSamplingRate = 48000,
+
+ // For quality reasons we try to encode 60ms, the maximum Opus buffer.
+ kOpusPreferredBufferDurationMs = 60,
+
+ // Maximum amount of buffers that can be held in the AudioEncoders' AudioFifo.
+ // Recording is not real time, hence a certain buffering is allowed.
+ kMaxNumberOfFifoBuffers = 2,
};
+// The amount of Frames in a 60 ms buffer @ 48000 samples/second.
+const int kOpusPreferredFramesPerBuffer = kOpusPreferredSamplingRate *
+ kOpusPreferredBufferDurationMs /
+ base::Time::kMillisecondsPerSecond;
+
+// Tries to encode |data_in|'s |num_samples| into |data_out|.
+bool DoEncode(OpusEncoder* opus_encoder,
+ float* data_in,
+ int num_samples,
+ std::string* data_out) {
+ DCHECK_EQ(kOpusPreferredFramesPerBuffer, num_samples);
+
+ data_out->resize(kOpusMaxDataBytes);
+ const opus_int32 result = opus_encode_float(
+ opus_encoder, data_in, num_samples,
+ reinterpret_cast<uint8_t*>(string_as_array(data_out)), kOpusMaxDataBytes);
+
+ if (result > 1) {
+ // TODO(ajose): Investigate improving this. http://crbug.com/547918
+ data_out->resize(result);
+ return true;
+ }
+ // If |result| in {0,1}, do nothing; the documentation says that a return
+ // value of zero or one means the packet does not need to be transmitted.
+ // Otherwise, we have an error.
+ DLOG_IF(ERROR, result < 0) << " encode failed: " << opus_strerror(result);
+ return false;
+}
+
+// Interleaves |audio_bus| channels() of floats into a single output linear
+// |buffer|.
+// TODO(mcasas) https://crbug.com/580391 use AudioBus::ToInterleavedFloat().
+void ToInterleaved(media::AudioBus* audio_bus, float* buffer) {
+ for (int ch = 0; ch < audio_bus->channels(); ++ch) {
+ const float* src = audio_bus->channel(ch);
+ const float* const src_end = src + audio_bus->frames();
+ float* dest = buffer + ch;
+ for (; src < src_end; ++src, dest += audio_bus->channels())
+ *dest = *src;
+ }
+}
+
} // anonymous namespace
-// Nested class encapsulating opus-related encoding details.
-// AudioEncoder is created and destroyed on ATR's main thread (usually the
-// main render thread) but otherwise should operate entirely on
-// |encoder_thread_|, which is owned by AudioTrackRecorder. Be sure to delete
-// |encoder_thread_| before deleting the AudioEncoder using it.
+// Nested class encapsulating opus-related encoding details. It contains an
+// AudioConverter to adapt incoming data to the format Opus likes to have.
+// AudioEncoder is created and destroyed on ATR's main thread (usually the main
+// render thread) but otherwise should operate entirely on |encoder_thread_|,
+// which is owned by AudioTrackRecorder. Be sure to delete |encoder_thread_|
+// before deleting the AudioEncoder using it.
class AudioTrackRecorder::AudioEncoder
- : public base::RefCountedThreadSafe<AudioEncoder> {
+ : public base::RefCountedThreadSafe<AudioEncoder>,
+ public media::AudioConverter::InputCallback {
public:
- explicit AudioEncoder(const OnEncodedAudioCB& on_encoded_audio_cb)
- : on_encoded_audio_cb_(on_encoded_audio_cb), opus_encoder_(nullptr) {
- // AudioEncoder is constructed on the thread that ATR lives on, but should
- // operate only on the encoder thread after that. Reset
- // |encoder_thread_checker_| here, as the next call to CalledOnValidThread()
- // will be from the encoder thread.
- encoder_thread_checker_.DetachFromThread();
- }
+ AudioEncoder(const OnEncodedAudioCB& on_encoded_audio_cb,
+ int32_t bits_per_second);
void OnSetFormat(const media::AudioParameters& params);
- void EncodeAudio(scoped_ptr<media::AudioBus> audio_bus,
+ void EncodeAudio(std::unique_ptr<media::AudioBus> audio_bus,
const base::TimeTicks& capture_time);
+ void set_paused(bool paused) { paused_ = paused; }
+
private:
friend class base::RefCountedThreadSafe<AudioEncoder>;
-
- ~AudioEncoder();
+ ~AudioEncoder() override;
bool is_initialized() const { return !!opus_encoder_; }
- void DestroyExistingOpusEncoder();
+ // media::AudioConverted::InputCallback implementation.
+ double ProvideInput(media::AudioBus* audio_bus,
+ base::TimeDelta buffer_delay) override;
- void TransferSamplesIntoBuffer(const media::AudioBus* audio_bus,
- int source_offset,
- int buffer_fill_offset,
- int num_samples);
- bool EncodeFromFilledBuffer(std::string* out);
+ void DestroyExistingOpusEncoder();
const OnEncodedAudioCB on_encoded_audio_cb_;
- base::ThreadChecker encoder_thread_checker_;
-
- // In the case where a call to EncodeAudio() cannot completely fill the
- // buffer, this points to the position at which to populate data in a later
- // call.
- int buffer_fill_end_;
+ // Target bitrate for Opus. If 0, Opus provide automatic bitrate is used.
+ const int32_t bits_per_second_;
- int frames_per_buffer_;
+ base::ThreadChecker encoder_thread_checker_;
- // The duration of one set of frames of encoded audio samples.
- base::TimeDelta buffer_duration_;
+ // Track Audio (ingress) and Opus encoder input parameters, respectively. They
+ // only differ in their sample_rate() and frames_per_buffer(): output is
+ // 48ksamples/s and 2880, respectively.
+ media::AudioParameters input_params_;
+ media::AudioParameters output_params_;
- media::AudioParameters audio_params_;
+ // Sampling rate adapter between an OpusEncoder supported and the provided.
+ std::unique_ptr<media::AudioConverter> converter_;
+ std::unique_ptr<media::AudioFifo> fifo_;
// Buffer for passing AudioBus data to OpusEncoder.
- scoped_ptr<float[]> buffer_;
+ std::unique_ptr<float[]> buffer_;
+
+ // While |paused_|, AudioBuses are not encoded.
+ bool paused_;
OpusEncoder* opus_encoder_;
DISALLOW_COPY_AND_ASSIGN(AudioEncoder);
};
+AudioTrackRecorder::AudioEncoder::AudioEncoder(
+ const OnEncodedAudioCB& on_encoded_audio_cb,
+ int32_t bits_per_second)
+ : on_encoded_audio_cb_(on_encoded_audio_cb),
+ bits_per_second_(bits_per_second),
+ paused_(false),
+ opus_encoder_(nullptr) {
+ // AudioEncoder is constructed on the thread that ATR lives on, but should
+ // operate only on the encoder thread after that. Reset
+ // |encoder_thread_checker_| here, as the next call to CalledOnValidThread()
+ // will be from the encoder thread.
+ encoder_thread_checker_.DetachFromThread();
+}
+
AudioTrackRecorder::AudioEncoder::~AudioEncoder() {
// We don't DCHECK that we're on the encoder thread here, as it should have
// already been deleted at this point.
@@ -105,45 +172,56 @@ AudioTrackRecorder::AudioEncoder::~AudioEncoder() {
}
void AudioTrackRecorder::AudioEncoder::OnSetFormat(
- const media::AudioParameters& params) {
+ const media::AudioParameters& input_params) {
+ DVLOG(1) << __FUNCTION__;
DCHECK(encoder_thread_checker_.CalledOnValidThread());
- if (audio_params_.Equals(params))
+ if (input_params_.Equals(input_params))
return;
DestroyExistingOpusEncoder();
- if (!params.IsValid()) {
- DLOG(ERROR) << "Invalid audio params: " << params.AsHumanReadableString();
+ if (!input_params.IsValid()) {
+ DLOG(ERROR) << "Invalid params: " << input_params.AsHumanReadableString();
return;
}
-
- buffer_duration_ = base::TimeDelta::FromMilliseconds(
- AudioTrackRecorder::GetOpusBufferDuration(params.sample_rate()));
- if (buffer_duration_ == base::TimeDelta()) {
- DLOG(ERROR) << "Could not find a valid |buffer_duration| for the given "
- << "sample rate: " << params.sample_rate();
- return;
- }
-
- frames_per_buffer_ =
- params.sample_rate() * buffer_duration_.InMilliseconds() / 1000;
- if (frames_per_buffer_ * params.channels() > MAX_SAMPLES_PER_BUFFER) {
- DLOG(ERROR) << "Invalid |frames_per_buffer_|: " << frames_per_buffer_;
- return;
- }
-
- // Initialize AudioBus buffer for OpusEncoder.
- buffer_fill_end_ = 0;
- buffer_.reset(new float[params.channels() * frames_per_buffer_]);
+ input_params_ = input_params;
+ input_params_.set_frames_per_buffer(input_params_.sample_rate() *
+ kOpusPreferredBufferDurationMs /
+ base::Time::kMillisecondsPerSecond);
+
+ // third_party/libopus supports up to 2 channels (see implementation of
+ // opus_encoder_create()): force |output_params_| to at most those.
+ output_params_ = media::AudioParameters(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::GuessChannelLayout(std::min(input_params_.channels(), 2)),
+ kOpusPreferredSamplingRate,
+ input_params_.bits_per_sample(),
+ kOpusPreferredFramesPerBuffer);
+ DVLOG(1) << "|input_params_|:" << input_params_.AsHumanReadableString()
+ << " -->|output_params_|:" << output_params_.AsHumanReadableString();
+
+ converter_.reset(new media::AudioConverter(input_params_, output_params_,
+ false /* disable_fifo */));
+ converter_->AddInput(this);
+ converter_->PrimeWithSilence();
+
+ fifo_.reset(new media::AudioFifo(
+ input_params_.channels(),
+ kMaxNumberOfFifoBuffers * input_params_.frames_per_buffer()));
+
+ buffer_.reset(new float[output_params_.channels() *
+ output_params_.frames_per_buffer()]);
// Initialize OpusEncoder.
int opus_result;
- opus_encoder_ = opus_encoder_create(params.sample_rate(), params.channels(),
- OPUS_APPLICATION_AUDIO, &opus_result);
+ opus_encoder_ = opus_encoder_create(output_params_.sample_rate(),
+ output_params_.channels(),
+ OPUS_APPLICATION_AUDIO,
+ &opus_result);
if (opus_result < 0) {
DLOG(ERROR) << "Couldn't init opus encoder: " << opus_strerror(opus_result)
- << ", sample rate: " << params.sample_rate()
- << ", channels: " << params.channels();
+ << ", sample rate: " << output_params_.sample_rate()
+ << ", channels: " << output_params_.channels();
return;
}
@@ -151,112 +229,79 @@ void AudioTrackRecorder::AudioEncoder::OnSetFormat(
// variable bitrate up to 102kbps for 2-channel, 48 kHz audio and a 10 ms
// buffer duration. The opus library authors may, of course, adjust this in
// later versions.
- if (opus_encoder_ctl(opus_encoder_, OPUS_SET_BITRATE(OPUS_AUTO)) != OPUS_OK) {
- DLOG(ERROR) << "Failed to set opus bitrate.";
+ const opus_int32 bitrate =
+ (bits_per_second_ > 0) ? bits_per_second_ : OPUS_AUTO;
+ if (opus_encoder_ctl(opus_encoder_, OPUS_SET_BITRATE(bitrate)) != OPUS_OK) {
+ DLOG(ERROR) << "Failed to set opus bitrate: " << bitrate;
return;
}
-
- audio_params_ = params;
}
void AudioTrackRecorder::AudioEncoder::EncodeAudio(
- scoped_ptr<media::AudioBus> audio_bus,
+ std::unique_ptr<media::AudioBus> input_bus,
const base::TimeTicks& capture_time) {
+ DVLOG(3) << __FUNCTION__ << ", #frames " << input_bus->frames();
DCHECK(encoder_thread_checker_.CalledOnValidThread());
- DCHECK_EQ(audio_bus->channels(), audio_params_.channels());
+ DCHECK_EQ(input_bus->channels(), input_params_.channels());
+ DCHECK(!capture_time.is_null());
+ DCHECK(converter_);
- if (!is_initialized())
+ if (!is_initialized() || paused_)
return;
-
- base::TimeDelta buffer_fill_duration =
- buffer_fill_end_ * buffer_duration_ / frames_per_buffer_;
- base::TimeTicks buffer_capture_time = capture_time - buffer_fill_duration;
-
- // Encode all audio in |audio_bus| into zero or more packets.
- int src_pos = 0;
- while (src_pos < audio_bus->frames()) {
- const int num_samples_to_xfer = std::min(
- frames_per_buffer_ - buffer_fill_end_, audio_bus->frames() - src_pos);
- TransferSamplesIntoBuffer(audio_bus.get(), src_pos, buffer_fill_end_,
- num_samples_to_xfer);
- src_pos += num_samples_to_xfer;
- buffer_fill_end_ += num_samples_to_xfer;
-
- if (buffer_fill_end_ < frames_per_buffer_)
- break;
-
- scoped_ptr<std::string> encoded_data(new std::string());
- if (EncodeFromFilledBuffer(encoded_data.get())) {
- on_encoded_audio_cb_.Run(audio_params_, std::move(encoded_data),
- buffer_capture_time);
+ // TODO(mcasas): Consider using a std::deque<std::unique_ptr<AudioBus>>
+ // instead of
+ // an AudioFifo, to avoid copying data needlessly since we know the sizes of
+ // both input and output and they are multiples.
+ fifo_->Push(input_bus.get());
+
+ // Wait to have enough |input_bus|s to guarantee a satisfactory conversion.
+ while (fifo_->frames() >= input_params_.frames_per_buffer()) {
+ std::unique_ptr<media::AudioBus> audio_bus = media::AudioBus::Create(
+ output_params_.channels(), kOpusPreferredFramesPerBuffer);
+ converter_->Convert(audio_bus.get());
+ ToInterleaved(audio_bus.get(), buffer_.get());
+
+ std::unique_ptr<std::string> encoded_data(new std::string());
+ if (DoEncode(opus_encoder_, buffer_.get(), kOpusPreferredFramesPerBuffer,
+ encoded_data.get())) {
+ const base::TimeTicks capture_time_of_first_sample =
+ capture_time -
+ base::TimeDelta::FromMicroseconds(fifo_->frames() *
+ base::Time::kMicrosecondsPerSecond /
+ input_params_.sample_rate());
+ on_encoded_audio_cb_.Run(output_params_, std::move(encoded_data),
+ capture_time_of_first_sample);
}
-
- // Reset the capture timestamp and internal buffer for next set of frames.
- buffer_capture_time += buffer_duration_;
- buffer_fill_end_ = 0;
}
}
+double AudioTrackRecorder::AudioEncoder::ProvideInput(
+ media::AudioBus* audio_bus,
+ base::TimeDelta buffer_delay) {
+ fifo_->Consume(audio_bus, 0, audio_bus->frames());
+ return 1.0; // Return volume greater than zero to indicate we have more data.
+}
+
void AudioTrackRecorder::AudioEncoder::DestroyExistingOpusEncoder() {
// We don't DCHECK that we're on the encoder thread here, as this could be
- // called from the dtor (main thread) or from OnSetForamt() (render thread);
+ // called from the dtor (main thread) or from OnSetFormat() (encoder thread).
if (opus_encoder_) {
opus_encoder_destroy(opus_encoder_);
opus_encoder_ = nullptr;
}
}
-void AudioTrackRecorder::AudioEncoder::TransferSamplesIntoBuffer(
- const media::AudioBus* audio_bus,
- int source_offset,
- int buffer_fill_offset,
- int num_samples) {
- // TODO(ajose): Consider replacing with AudioBus::ToInterleaved().
- // http://crbug.com/547918
- DCHECK(encoder_thread_checker_.CalledOnValidThread());
- DCHECK(is_initialized());
- // Opus requires channel-interleaved samples in a single array.
- for (int ch = 0; ch < audio_bus->channels(); ++ch) {
- const float* src = audio_bus->channel(ch) + source_offset;
- const float* const src_end = src + num_samples;
- float* dest =
- buffer_.get() + buffer_fill_offset * audio_params_.channels() + ch;
- for (; src < src_end; ++src, dest += audio_params_.channels())
- *dest = *src;
- }
-}
-
-bool AudioTrackRecorder::AudioEncoder::EncodeFromFilledBuffer(
- std::string* out) {
- DCHECK(encoder_thread_checker_.CalledOnValidThread());
- DCHECK(is_initialized());
-
- out->resize(OPUS_MAX_PAYLOAD_SIZE);
- const opus_int32 result = opus_encode_float(
- opus_encoder_, buffer_.get(), frames_per_buffer_,
- reinterpret_cast<uint8_t*>(string_as_array(out)), OPUS_MAX_PAYLOAD_SIZE);
- if (result > 1) {
- // TODO(ajose): Investigate improving this. http://crbug.com/547918
- out->resize(result);
- return true;
- }
- // If |result| in {0,1}, do nothing; the documentation says that a return
- // value of zero or one means the packet does not need to be transmitted.
- // Otherwise, we have an error.
- DLOG_IF(ERROR, result < 0) << __FUNCTION__
- << " failed: " << opus_strerror(result);
- return false;
-}
-
AudioTrackRecorder::AudioTrackRecorder(
const blink::WebMediaStreamTrack& track,
- const OnEncodedAudioCB& on_encoded_audio_cb)
+ const OnEncodedAudioCB& on_encoded_audio_cb,
+ int32_t bits_per_second)
: track_(track),
- encoder_(new AudioEncoder(media::BindToCurrentLoop(on_encoded_audio_cb))),
+ encoder_(new AudioEncoder(media::BindToCurrentLoop(on_encoded_audio_cb),
+ bits_per_second)),
encoder_thread_("AudioEncoderThread") {
DCHECK(main_render_thread_checker_.CalledOnValidThread());
DCHECK(!track_.isNull());
- DCHECK(track_.extraData());
+ DCHECK(MediaStreamAudioTrack::From(track_));
// Start the |encoder_thread_|. From this point on, |encoder_| should work
// only on |encoder_thread_|, as enforced by DCHECKs.
@@ -288,7 +333,7 @@ void AudioTrackRecorder::OnData(const media::AudioBus& audio_bus,
DCHECK(capture_thread_checker_.CalledOnValidThread());
DCHECK(!capture_time.is_null());
- scoped_ptr<media::AudioBus> audio_data =
+ std::unique_ptr<media::AudioBus> audio_data =
media::AudioBus::Create(audio_bus.channels(), audio_bus.frames());
audio_bus.CopyTo(audio_data.get());
@@ -297,22 +342,18 @@ void AudioTrackRecorder::OnData(const media::AudioBus& audio_bus,
base::Passed(&audio_data), capture_time));
}
-int AudioTrackRecorder::GetOpusBufferDuration(int sample_rate) {
- // Valid buffer durations in millseconds. Note there are other valid
- // durations for Opus, see https://tools.ietf.org/html/rfc6716#section-2.1.4
- // Descending order as longer durations can increase compression performance.
- const std::vector<int> opus_valid_buffer_durations_ms = {60, 40, 20, 10};
-
- // Search for a duration such that |sample_rate| % |buffers_per_second| == 0,
- // where |buffers_per_second| = 1000ms / |possible_duration|.
- for (auto possible_duration : opus_valid_buffer_durations_ms) {
- if (sample_rate * possible_duration % 1000 == 0) {
- return possible_duration;
- }
- }
+void AudioTrackRecorder::Pause() {
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
+ DCHECK(encoder_);
+ encoder_thread_.task_runner()->PostTask(
+ FROM_HERE, base::Bind(&AudioEncoder::set_paused, encoder_, true));
+}
- // Otherwise, couldn't find a good duration.
- return 0;
+void AudioTrackRecorder::Resume() {
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
+ DCHECK(encoder_);
+ encoder_thread_.task_runner()->PostTask(
+ FROM_HERE, base::Bind(&AudioEncoder::set_paused, encoder_, false));
}
} // namespace content
diff --git a/chromium/content/renderer/media/audio_track_recorder.h b/chromium/content/renderer/media/audio_track_recorder.h
index 353331cec0f..15eb3cbf818 100644
--- a/chromium/content/renderer/media/audio_track_recorder.h
+++ b/chromium/content/renderer/media/audio_track_recorder.h
@@ -5,10 +5,11 @@
#ifndef CONTENT_RENDERER_MEDIA_AUDIO_TRACK_RECORDER_H_
#define CONTENT_RENDERER_MEDIA_AUDIO_TRACK_RECORDER_H_
+#include <memory>
+
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/threading/thread.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
@@ -17,6 +18,7 @@
namespace media {
class AudioBus;
+class AudioParameters;
} // namespace media
namespace content {
@@ -33,11 +35,12 @@ class CONTENT_EXPORT AudioTrackRecorder
public:
using OnEncodedAudioCB =
base::Callback<void(const media::AudioParameters& params,
- scoped_ptr<std::string> encoded_data,
+ std::unique_ptr<std::string> encoded_data,
base::TimeTicks capture_time)>;
AudioTrackRecorder(const blink::WebMediaStreamTrack& track,
- const OnEncodedAudioCB& on_encoded_audio_cb);
+ const OnEncodedAudioCB& on_encoded_audio_cb,
+ int32_t bits_per_second);
~AudioTrackRecorder() override;
// Implement MediaStreamAudioSink.
@@ -45,18 +48,14 @@ class CONTENT_EXPORT AudioTrackRecorder
void OnData(const media::AudioBus& audio_bus,
base::TimeTicks capture_time) override;
- private:
- friend class AudioTrackRecorderTest;
- class AudioParameters;
+ void Pause();
+ void Resume();
+ private:
// Forward declaration of nested class for handling encoding.
// See the implementation file for details.
class AudioEncoder;
- // Returns the Opus buffer duration in milliseconds, or zero if none will work
- // for the given |sample_rate|.
- static int GetOpusBufferDuration(int sample_rate);
-
// Used to check that we are destroyed on the same thread we were created on.
base::ThreadChecker main_render_thread_checker_;
diff --git a/chromium/content/renderer/media/audio_track_recorder_unittest.cc b/chromium/content/renderer/media/audio_track_recorder_unittest.cc
index eac49563fc4..ad05ccd7aa0 100644
--- a/chromium/content/renderer/media/audio_track_recorder_unittest.cc
+++ b/chromium/content/renderer/media/audio_track_recorder_unittest.cc
@@ -11,7 +11,6 @@
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/renderer/media/media_stream_audio_source.h"
-#include "content/renderer/media/mock_media_constraint_factory.h"
#include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
#include "content/renderer/media/webrtc_local_audio_track.h"
#include "media/audio/simple_sources.h"
@@ -28,17 +27,23 @@ using ::testing::Return;
using ::testing::SaveArg;
using ::testing::TestWithParam;
using ::testing::ValuesIn;
+using base::TimeTicks;
namespace {
-// Input audio format.
-const media::AudioParameters::Format kDefaultInputFormat =
- media::AudioParameters::AUDIO_PCM_LOW_LATENCY;
const int kDefaultBitsPerSample = 16;
const int kDefaultSampleRate = 48000;
// The |frames_per_buffer| field of AudioParameters is not used by ATR.
const int kIgnoreFramesPerBuffer = 1;
-const int kOpusMaxBufferDurationMS = 120;
+
+// The following parameters replicate those in audio_track_recorder.cc, see this
+// file for explanations.
+const int kMediaStreamAudioTrackBufferDurationMs = 10;
+const int kOpusBufferDurationMs = 60;
+const int kRatioInputToOutputFrames =
+ kOpusBufferDurationMs / kMediaStreamAudioTrackBufferDurationMs;
+
+const int kFramesPerBuffer = kOpusBufferDurationMs * kDefaultSampleRate / 1000;
} // namespace
@@ -62,13 +67,32 @@ const ATRTestParams kATRTestParams[] = {
kDefaultSampleRate, /* sample rate */
kDefaultBitsPerSample}, /* bits per sample */
// Change to mono:
- {media::AudioParameters::AUDIO_PCM_LOW_LATENCY, media::CHANNEL_LAYOUT_MONO,
- kDefaultSampleRate, kDefaultBitsPerSample},
+ {media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_MONO,
+ kDefaultSampleRate,
+ kDefaultBitsPerSample},
// Different sampling rate as well:
- {media::AudioParameters::AUDIO_PCM_LOW_LATENCY, media::CHANNEL_LAYOUT_MONO,
- 24000, kDefaultBitsPerSample},
{media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_STEREO, 8000, kDefaultBitsPerSample},
+ media::CHANNEL_LAYOUT_MONO,
+ 24000,
+ kDefaultBitsPerSample},
+ {media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_STEREO,
+ 8000,
+ kDefaultBitsPerSample},
+ // Using a non-default Opus sampling rate (48, 24, 16, 12, or 8 kHz).
+ {media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_MONO,
+ 22050,
+ kDefaultBitsPerSample},
+ {media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_STEREO,
+ 44100,
+ kDefaultBitsPerSample},
+ {media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_STEREO,
+ 96000,
+ kDefaultBitsPerSample},
};
class AudioTrackRecorderTest : public TestWithParam<ATRTestParams> {
@@ -81,7 +105,7 @@ class AudioTrackRecorderTest : public TestWithParam<ATRTestParams> {
GetParam().sample_rate,
GetParam().bits_per_sample,
kIgnoreFramesPerBuffer),
- second_params_(kDefaultInputFormat,
+ second_params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::CHANNEL_LAYOUT_STEREO,
kDefaultSampleRate,
kDefaultBitsPerSample,
@@ -97,15 +121,18 @@ class AudioTrackRecorderTest : public TestWithParam<ATRTestParams> {
PrepareBlinkTrack();
audio_track_recorder_.reset(new AudioTrackRecorder(
blink_track_, base::Bind(&AudioTrackRecorderTest::OnEncodedAudio,
- base::Unretained(this))));
+ base::Unretained(this)),
+ 0 /* bits_per_second */));
}
~AudioTrackRecorderTest() {
opus_decoder_destroy(opus_decoder_);
opus_decoder_ = nullptr;
- audio_track_recorder_.reset();
blink_track_.reset();
blink::WebHeap::collectAllGarbageForTesting();
+ audio_track_recorder_.reset();
+ // Let the message loop run to finish destroying the recorder properly.
+ base::RunLoop().RunUntilIdle();
}
void ResetDecoder(const media::AudioParameters& params) {
@@ -116,31 +143,25 @@ class AudioTrackRecorderTest : public TestWithParam<ATRTestParams> {
int error;
opus_decoder_ =
- opus_decoder_create(params.sample_rate(), params.channels(), &error);
+ opus_decoder_create(kDefaultSampleRate, params.channels(), &error);
EXPECT_TRUE(error == OPUS_OK && opus_decoder_);
- max_frames_per_buffer_ =
- kOpusMaxBufferDurationMS * params.sample_rate() / 1000;
- buffer_.reset(new float[max_frames_per_buffer_ * params.channels()]);
+ buffer_.reset(new float[kFramesPerBuffer * params.channels()]);
}
- scoped_ptr<media::AudioBus> GetFirstSourceAudioBus() {
- scoped_ptr<media::AudioBus> bus(media::AudioBus::Create(
- first_params_.channels(),
- first_params_.sample_rate() *
- audio_track_recorder_->GetOpusBufferDuration(
- first_params_.sample_rate()) /
- 1000));
+ std::unique_ptr<media::AudioBus> GetFirstSourceAudioBus() {
+ std::unique_ptr<media::AudioBus> bus(media::AudioBus::Create(
+ first_params_.channels(), first_params_.sample_rate() *
+ kMediaStreamAudioTrackBufferDurationMs /
+ base::Time::kMillisecondsPerSecond));
first_source_.OnMoreData(bus.get(), 0, 0);
return bus;
}
- scoped_ptr<media::AudioBus> GetSecondSourceAudioBus() {
- scoped_ptr<media::AudioBus> bus(media::AudioBus::Create(
- second_params_.channels(),
- second_params_.sample_rate() *
- audio_track_recorder_->GetOpusBufferDuration(
- second_params_.sample_rate()) /
- 1000));
+ std::unique_ptr<media::AudioBus> GetSecondSourceAudioBus() {
+ std::unique_ptr<media::AudioBus> bus(media::AudioBus::Create(
+ second_params_.channels(), second_params_.sample_rate() *
+ kMediaStreamAudioTrackBufferDurationMs /
+ base::Time::kMillisecondsPerSecond));
second_source_.OnMoreData(bus.get(), 0, 0);
return bus;
}
@@ -148,23 +169,19 @@ class AudioTrackRecorderTest : public TestWithParam<ATRTestParams> {
MOCK_METHOD3(DoOnEncodedAudio,
void(const media::AudioParameters& params,
std::string encoded_data,
- base::TimeTicks timestamp));
+ TimeTicks timestamp));
void OnEncodedAudio(const media::AudioParameters& params,
- scoped_ptr<std::string> encoded_data,
- base::TimeTicks timestamp) {
+ std::unique_ptr<std::string> encoded_data,
+ TimeTicks timestamp) {
EXPECT_TRUE(!encoded_data->empty());
-
// Decode |encoded_data| and check we get the expected number of frames
// per buffer.
- EXPECT_EQ(
- params.sample_rate() *
- audio_track_recorder_->GetOpusBufferDuration(params.sample_rate()) /
- 1000,
- opus_decode_float(
- opus_decoder_,
- reinterpret_cast<uint8_t*>(string_as_array(encoded_data.get())),
- encoded_data->size(), buffer_.get(), max_frames_per_buffer_, 0));
+ EXPECT_EQ(kDefaultSampleRate * kOpusBufferDurationMs / 1000,
+ opus_decode_float(
+ opus_decoder_, reinterpret_cast<uint8_t*>(
+ string_as_array(encoded_data.get())),
+ encoded_data->size(), buffer_.get(), kFramesPerBuffer, 0));
DoOnEncodedAudio(params, *encoded_data, timestamp);
}
@@ -172,7 +189,7 @@ class AudioTrackRecorderTest : public TestWithParam<ATRTestParams> {
const base::MessageLoop message_loop_;
// ATR and WebMediaStreamTrack for fooling it.
- scoped_ptr<AudioTrackRecorder> audio_track_recorder_;
+ std::unique_ptr<AudioTrackRecorder> audio_track_recorder_;
blink::WebMediaStreamTrack blink_track_;
// Two different sets of AudioParameters for testing re-init of ATR.
@@ -185,23 +202,17 @@ class AudioTrackRecorderTest : public TestWithParam<ATRTestParams> {
// Decoder for verifying data was properly encoded.
OpusDecoder* opus_decoder_;
- int max_frames_per_buffer_;
- scoped_ptr<float[]> buffer_;
+ std::unique_ptr<float[]> buffer_;
private:
// Prepares a blink track of a given MediaStreamType and attaches the native
// track, which can be used to capture audio data and pass it to the producer.
// Adapted from media::WebRTCLocalAudioSourceProviderTest.
void PrepareBlinkTrack() {
- MockMediaConstraintFactory constraint_factory;
- scoped_refptr<WebRtcAudioCapturer> capturer(
- WebRtcAudioCapturer::CreateCapturer(
- -1, StreamDeviceInfo(),
- constraint_factory.CreateWebMediaConstraints(), NULL, NULL));
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
- scoped_ptr<WebRtcLocalAudioTrack> native_track(
- new WebRtcLocalAudioTrack(adapter.get(), capturer, NULL));
+ std::unique_ptr<WebRtcLocalAudioTrack> native_track(
+ new WebRtcLocalAudioTrack(adapter.get()));
blink::WebMediaStreamSource audio_source;
audio_source.initialize(base::UTF8ToUTF16("dummy_source_id"),
blink::WebMediaStreamSource::TypeAudio,
@@ -222,35 +233,71 @@ TEST_P(AudioTrackRecorderTest, OnData) {
// Give ATR initial audio parameters.
audio_track_recorder_->OnSetFormat(first_params_);
+
// TODO(ajose): consider adding WillOnce(SaveArg...) and inspecting, as done
// in VTR unittests. http://crbug.com/548856
- const base::TimeTicks time1 = base::TimeTicks::Now();
- EXPECT_CALL(*this, DoOnEncodedAudio(_, _, time1)).Times(1);
- audio_track_recorder_->OnData(*GetFirstSourceAudioBus(), time1);
+ EXPECT_CALL(*this, DoOnEncodedAudio(_, _, _)).Times(1);
+ audio_track_recorder_->OnData(*GetFirstSourceAudioBus(), TimeTicks::Now());
+ for (int i = 0; i < kRatioInputToOutputFrames - 1; ++i)
+ audio_track_recorder_->OnData(*GetFirstSourceAudioBus(), TimeTicks::Now());
- // Send more audio.
- const base::TimeTicks time2 = base::TimeTicks::Now();
EXPECT_CALL(*this, DoOnEncodedAudio(_, _, _))
.Times(1)
// Only reset the decoder once we've heard back:
.WillOnce(RunClosure(base::Bind(&AudioTrackRecorderTest::ResetDecoder,
base::Unretained(this), second_params_)));
- audio_track_recorder_->OnData(*GetFirstSourceAudioBus(), time2);
+ audio_track_recorder_->OnData(*GetFirstSourceAudioBus(), TimeTicks::Now());
+ for (int i = 0; i < kRatioInputToOutputFrames - 1; ++i)
+ audio_track_recorder_->OnData(*GetFirstSourceAudioBus(), TimeTicks::Now());
+
+ // If the amount of samples/10ms buffer is not an integer (e.g. 22050Hz) we
+ // need an extra OnData() to account for the round-off error.
+ if (GetParam().sample_rate % 100)
+ audio_track_recorder_->OnData(*GetFirstSourceAudioBus(), TimeTicks::Now());
// Give ATR new audio parameters.
audio_track_recorder_->OnSetFormat(second_params_);
// Send audio with different params.
- const base::TimeTicks time3 = base::TimeTicks::Now();
EXPECT_CALL(*this, DoOnEncodedAudio(_, _, _))
.Times(1)
.WillOnce(RunClosure(quit_closure));
- audio_track_recorder_->OnData(*GetSecondSourceAudioBus(), time3);
+ audio_track_recorder_->OnData(*GetSecondSourceAudioBus(), TimeTicks::Now());
+ for (int i = 0; i < kRatioInputToOutputFrames - 1; ++i)
+ audio_track_recorder_->OnData(*GetSecondSourceAudioBus(), TimeTicks::Now());
run_loop.Run();
Mock::VerifyAndClearExpectations(this);
}
-INSTANTIATE_TEST_CASE_P(, AudioTrackRecorderTest, ValuesIn(kATRTestParams));
+TEST_P(AudioTrackRecorderTest, PauseResume) {
+ InSequence s;
+ base::RunLoop run_loop;
+ base::Closure quit_closure = run_loop.QuitClosure();
+
+ // Give ATR initial audio parameters.
+ audio_track_recorder_->OnSetFormat(first_params_);
+ audio_track_recorder_->Pause();
+ EXPECT_CALL(*this, DoOnEncodedAudio(_, _, _)).Times(0);
+ audio_track_recorder_->OnData(*GetFirstSourceAudioBus(), TimeTicks::Now());
+ for (int i = 0; i < kRatioInputToOutputFrames - 1; ++i)
+ audio_track_recorder_->OnData(*GetFirstSourceAudioBus(), TimeTicks::Now());
+
+ audio_track_recorder_->Resume();
+ EXPECT_CALL(*this, DoOnEncodedAudio(_, _, _))
+ .Times(1)
+ .WillOnce(RunClosure(quit_closure));
+ audio_track_recorder_->OnData(*GetFirstSourceAudioBus(), TimeTicks::Now());
+ for (int i = 0; i < kRatioInputToOutputFrames - 1; ++i)
+ audio_track_recorder_->OnData(*GetFirstSourceAudioBus(), TimeTicks::Now());
+
+ if (GetParam().sample_rate % 100)
+ audio_track_recorder_->OnData(*GetFirstSourceAudioBus(), TimeTicks::Now());
+
+ run_loop.Run();
+ Mock::VerifyAndClearExpectations(this);
+}
+
+INSTANTIATE_TEST_CASE_P(, AudioTrackRecorderTest, ValuesIn(kATRTestParams));
} // namespace content
diff --git a/chromium/content/renderer/media/canvas_capture_handler.cc b/chromium/content/renderer/media/canvas_capture_handler.cc
index 634267eb153..7990739097c 100644
--- a/chromium/content/renderer/media/canvas_capture_handler.cc
+++ b/chromium/content/renderer/media/canvas_capture_handler.cc
@@ -21,10 +21,39 @@
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/libyuv/include/libyuv.h"
+namespace {
+
+static void CopyAlphaChannelIntoVideoFrame(
+ const uint8_t* const source,
+ const scoped_refptr<media::VideoFrame>& dest_frame) {
+ const gfx::Size& size = dest_frame->coded_size();
+ const int stride = dest_frame->stride(media::VideoFrame::kAPlane);
+
+ if (stride == size.width()) {
+ for (int p = 0; p < size.GetArea(); ++p)
+ dest_frame->data(media::VideoFrame::kAPlane)[p] = source[p * 4 + 3];
+ return;
+ }
+
+ // Copy apha values one-by-one if the destination stride != source width.
+ for (int h = 0; h < size.height(); ++h) {
+ const uint8_t* const src_ptr = &source[4 * h * size.width()];
+ uint8_t* dest_ptr =
+ &dest_frame->data(media::VideoFrame::kAPlane)[h * stride];
+ for (int pixel_index = 0; pixel_index < 4 * size.width(); pixel_index += 4)
+ *(dest_ptr++) = src_ptr[pixel_index + 3];
+ }
+}
+
+} // namespace
+
namespace content {
-class CanvasCaptureHandler::VideoCapturerSource
- : public media::VideoCapturerSource {
+// Implementation VideoCapturerSource that is owned by
+// MediaStreamVideoCapturerSource and delegates the Start/Stop calls to
+// CanvasCaptureHandler.
+// This class is single threaded and pinned to main render thread.
+class VideoCapturerSource : public media::VideoCapturerSource {
public:
explicit VideoCapturerSource(base::WeakPtr<CanvasCaptureHandler>
canvas_handler,
@@ -38,28 +67,40 @@ class CanvasCaptureHandler::VideoCapturerSource
int max_requested_height,
double max_requested_frame_rate,
const VideoCaptureDeviceFormatsCB& callback) override {
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
const blink::WebSize& size = canvas_handler_->GetSourceSize();
- const media::VideoCaptureFormat format(gfx::Size(size.width, size.height),
- frame_rate_,
- media::PIXEL_FORMAT_I420);
media::VideoCaptureFormats formats;
- formats.push_back(format);
+ formats.push_back(
+ media::VideoCaptureFormat(gfx::Size(size.width, size.height),
+ frame_rate_, media::PIXEL_FORMAT_I420));
+ formats.push_back(
+ media::VideoCaptureFormat(gfx::Size(size.width, size.height),
+ frame_rate_, media::PIXEL_FORMAT_YV12A));
callback.Run(formats);
}
void StartCapture(const media::VideoCaptureParams& params,
const VideoCaptureDeliverFrameCB& frame_callback,
const RunningCallback& running_callback) override {
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
canvas_handler_->StartVideoCapture(params, frame_callback,
running_callback);
}
+ void RequestRefreshFrame() override {
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
+ canvas_handler_->RequestRefreshFrame();
+ }
void StopCapture() override {
- canvas_handler_->StopVideoCapture();
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
+ if (canvas_handler_.get())
+ canvas_handler_->StopVideoCapture();
}
private:
- double frame_rate_;
- // CanvasCaptureHandler is owned by CanvasDrawListener in blink and
- // guaranteed to be alive during the lifetime of this class.
+ const double frame_rate_;
+ // Bound to Main Render thread.
+ base::ThreadChecker main_render_thread_checker_;
+ // CanvasCaptureHandler is owned by CanvasDrawListener in blink and might be
+ // destroyed before StopCapture() call.
base::WeakPtr<CanvasCaptureHandler> canvas_handler_;
};
@@ -69,16 +110,16 @@ class CanvasCaptureHandler::CanvasCaptureHandlerDelegate {
media::VideoCapturerSource::VideoCaptureDeliverFrameCB new_frame_callback)
: new_frame_callback_(new_frame_callback),
weak_ptr_factory_(this) {
- thread_checker_.DetachFromThread();
+ io_thread_checker_.DetachFromThread();
}
~CanvasCaptureHandlerDelegate() {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(io_thread_checker_.CalledOnValidThread());
}
void SendNewFrameOnIOThread(
const scoped_refptr<media::VideoFrame>& video_frame,
const base::TimeTicks& current_time) {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(io_thread_checker_.CalledOnValidThread());
new_frame_callback_.Run(video_frame, current_time);
}
@@ -89,7 +130,8 @@ class CanvasCaptureHandler::CanvasCaptureHandlerDelegate {
private:
const media::VideoCapturerSource::VideoCaptureDeliverFrameCB
new_frame_callback_;
- base::ThreadChecker thread_checker_;
+ // Bound to IO thread.
+ base::ThreadChecker io_thread_checker_;
base::WeakPtrFactory<CanvasCaptureHandlerDelegate> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(CanvasCaptureHandlerDelegate);
@@ -104,15 +146,14 @@ CanvasCaptureHandler::CanvasCaptureHandler(
size_(size),
io_task_runner_(io_task_runner),
weak_ptr_factory_(this) {
- scoped_ptr<media::VideoCapturerSource> video_source(
- new CanvasCaptureHandler::VideoCapturerSource(
- weak_ptr_factory_.GetWeakPtr(), frame_rate));
+ std::unique_ptr<media::VideoCapturerSource> video_source(
+ new VideoCapturerSource(weak_ptr_factory_.GetWeakPtr(), frame_rate));
AddVideoCapturerSourceToVideoTrack(std::move(video_source), track);
}
CanvasCaptureHandler::~CanvasCaptureHandler() {
DVLOG(3) << __FUNCTION__;
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
io_task_runner_->DeleteSoon(FROM_HERE, delegate_.release());
}
@@ -130,12 +171,12 @@ CanvasCaptureHandler* CanvasCaptureHandler::CreateCanvasCaptureHandler(
}
void CanvasCaptureHandler::sendNewFrame(const SkImage* image) {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
CreateNewFrame(image);
}
bool CanvasCaptureHandler::needsNewFrame() const {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
return ask_for_new_frame_;
}
@@ -146,8 +187,8 @@ void CanvasCaptureHandler::StartVideoCapture(
const media::VideoCapturerSource::RunningCallback& running_callback) {
DVLOG(3) << __FUNCTION__ << " requested "
<< media::VideoCaptureFormat::ToString(params.requested_format);
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
DCHECK(params.requested_format.IsValid());
- DCHECK(thread_checker_.CalledOnValidThread());
// TODO(emircan): Accomodate to the given frame rate constraints here.
capture_format_ = params.requested_format;
@@ -157,17 +198,31 @@ void CanvasCaptureHandler::StartVideoCapture(
running_callback.Run(true);
}
+void CanvasCaptureHandler::RequestRefreshFrame() {
+ DVLOG(3) << __FUNCTION__;
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
+ if (last_frame_ && delegate_) {
+ io_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&CanvasCaptureHandler::CanvasCaptureHandlerDelegate::
+ SendNewFrameOnIOThread,
+ delegate_->GetWeakPtrForIOThread(), last_frame_,
+ base::TimeTicks::Now()));
+ }
+}
+
void CanvasCaptureHandler::StopVideoCapture() {
DVLOG(3) << __FUNCTION__;
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
ask_for_new_frame_ = false;
io_task_runner_->DeleteSoon(FROM_HERE, delegate_.release());
}
void CanvasCaptureHandler::CreateNewFrame(const SkImage* image) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
+ DVLOG(4) << __FUNCTION__;
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
DCHECK(image);
+
const gfx::Size size(image->width(), image->height());
if (size != last_size) {
temp_data_.resize(
@@ -176,14 +231,20 @@ void CanvasCaptureHandler::CreateNewFrame(const SkImage* image) {
media::VideoFrame::RowBytes(0, media::PIXEL_FORMAT_ARGB, size.width());
image_info_ =
SkImageInfo::Make(size.width(), size.height(), kBGRA_8888_SkColorType,
- kPremul_SkAlphaType);
+ kUnpremul_SkAlphaType);
last_size = size;
}
- image->readPixels(image_info_, &temp_data_[0], row_bytes_, 0, 0);
- scoped_refptr<media::VideoFrame> video_frame =
- frame_pool_.CreateFrame(media::PIXEL_FORMAT_I420, size, gfx::Rect(size),
- size, base::TimeTicks::Now() - base::TimeTicks());
+ if(!image->readPixels(image_info_, &temp_data_[0], row_bytes_, 0, 0)) {
+ DLOG(ERROR) << "Couldn't read SkImage pixels";
+ return;
+ }
+
+ const bool isOpaque = image->isOpaque();
+ const base::TimeTicks timestamp = base::TimeTicks::Now();
+ scoped_refptr<media::VideoFrame> video_frame = frame_pool_.CreateFrame(
+ isOpaque ? media::PIXEL_FORMAT_I420 : media::PIXEL_FORMAT_YV12A, size,
+ gfx::Rect(size), size, timestamp - base::TimeTicks());
DCHECK(video_frame);
libyuv::ARGBToI420(temp_data_.data(), row_bytes_,
@@ -194,22 +255,28 @@ void CanvasCaptureHandler::CreateNewFrame(const SkImage* image) {
video_frame->data(media::VideoFrame::kVPlane),
video_frame->stride(media::VideoFrame::kVPlane),
size.width(), size.height());
+ if (!isOpaque) {
+ // TODO(emircan): Use https://code.google.com/p/libyuv/issues/detail?id=572
+ // when it becomes available.
+ CopyAlphaChannelIntoVideoFrame(temp_data_.data(), video_frame);
+ }
+
+ last_frame_ = video_frame;
io_task_runner_->PostTask(
FROM_HERE,
base::Bind(&CanvasCaptureHandler::CanvasCaptureHandlerDelegate::
SendNewFrameOnIOThread,
- delegate_->GetWeakPtrForIOThread(), video_frame,
- base::TimeTicks()));
+ delegate_->GetWeakPtrForIOThread(), video_frame, timestamp));
}
void CanvasCaptureHandler::AddVideoCapturerSourceToVideoTrack(
- scoped_ptr<media::VideoCapturerSource> source,
+ std::unique_ptr<media::VideoCapturerSource> source,
blink::WebMediaStreamTrack* web_track) {
std::string str_track_id;
base::Base64Encode(base::RandBytesAsString(64), &str_track_id);
const blink::WebString track_id = base::UTF8ToUTF16(str_track_id);
blink::WebMediaStreamSource webkit_source;
- scoped_ptr<MediaStreamVideoSource> media_stream_source(
+ std::unique_ptr<MediaStreamVideoSource> media_stream_source(
new MediaStreamVideoCapturerSource(
MediaStreamSource::SourceStoppedCallback(), std::move(source)));
webkit_source.initialize(track_id, blink::WebMediaStreamSource::TypeVideo,
diff --git a/chromium/content/renderer/media/canvas_capture_handler.h b/chromium/content/renderer/media/canvas_capture_handler.h
index c9aa31372d4..4df1692223a 100644
--- a/chromium/content/renderer/media/canvas_capture_handler.h
+++ b/chromium/content/renderer/media/canvas_capture_handler.h
@@ -8,9 +8,10 @@
#include <stddef.h>
#include <stdint.h>
+#include <memory>
+
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
#include "media/base/video_capturer_source.h"
@@ -53,6 +54,7 @@ class CONTENT_EXPORT CanvasCaptureHandler final
const media::VideoCapturerSource::VideoCaptureDeliverFrameCB&
new_frame_callback,
const media::VideoCapturerSource::RunningCallback& running_callback);
+ void RequestRefreshFrame();
void StopVideoCapture();
blink::WebSize GetSourceSize() const { return size_; }
@@ -69,13 +71,9 @@ class CONTENT_EXPORT CanvasCaptureHandler final
void CreateNewFrame(const SkImage* image);
void AddVideoCapturerSourceToVideoTrack(
- scoped_ptr<media::VideoCapturerSource> source,
+ std::unique_ptr<media::VideoCapturerSource> source,
blink::WebMediaStreamTrack* web_track);
- // Implementation VideoCapturerSource that is owned by Blink and delegates
- // the Start/Stop calls to CanvasCaptureHandler.
- class VideoCapturerSource;
-
// Object that does all the work of running |new_frame_callback_|.
// Destroyed on |frame_callback_task_runner_| after the class is destroyed.
class CanvasCaptureHandlerDelegate;
@@ -90,10 +88,13 @@ class CONTENT_EXPORT CanvasCaptureHandler final
SkImageInfo image_info_;
media::VideoFramePool frame_pool_;
+ scoped_refptr<media::VideoFrame> last_frame_;
+
const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
- scoped_ptr<CanvasCaptureHandlerDelegate> delegate_;
- // Bound to the main render thread.
- base::ThreadChecker thread_checker_;
+ std::unique_ptr<CanvasCaptureHandlerDelegate> delegate_;
+
+ // Bound to Main Render thread.
+ base::ThreadChecker main_render_thread_checker_;
base::WeakPtrFactory<CanvasCaptureHandler> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(CanvasCaptureHandler);
diff --git a/chromium/content/renderer/media/canvas_capture_handler_unittest.cc b/chromium/content/renderer/media/canvas_capture_handler_unittest.cc
index 6f23ed103ef..d5153123206 100644
--- a/chromium/content/renderer/media/canvas_capture_handler_unittest.cc
+++ b/chromium/content/renderer/media/canvas_capture_handler_unittest.cc
@@ -9,7 +9,6 @@
#include "content/renderer/media/canvas_capture_handler.h"
#include "content/renderer/media/media_stream_video_capturer_source.h"
#include "media/base/limits.h"
-#include "skia/ext/refptr.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
@@ -22,9 +21,12 @@ using ::testing::InSequence;
using ::testing::Mock;
using ::testing::SaveArg;
using ::testing::Test;
+using ::testing::TestWithParam;
namespace content {
+namespace {
+
static const int kTestCanvasCaptureWidth = 320;
static const int kTestCanvasCaptureHeight = 240;
static const double kTestCanvasCaptureFramesPerSecond = 55.5;
@@ -32,12 +34,15 @@ static const double kTestCanvasCaptureFramesPerSecond = 55.5;
static const int kTestCanvasCaptureFrameWidth = 2;
static const int kTestCanvasCaptureFrameHeight = 2;
static const int kTestCanvasCaptureFrameErrorTolerance = 2;
+static const int kTestAlphaValue = 175;
ACTION_P(RunClosure, closure) {
closure.Run();
}
-class CanvasCaptureHandlerTest : public Test {
+} // namespace
+
+class CanvasCaptureHandlerTest : public TestWithParam<bool> {
public:
CanvasCaptureHandlerTest() {}
@@ -76,32 +81,44 @@ class CanvasCaptureHandlerTest : public Test {
void OnRunning(bool state) { DoOnRunning(state); }
// Verify returned frames.
- static skia::RefPtr<SkImage> GenerateTestImage() {
+ static sk_sp<SkImage> GenerateTestImage(bool opaque) {
+
SkBitmap testBitmap;
testBitmap.allocN32Pixels(kTestCanvasCaptureFrameWidth,
- kTestCanvasCaptureFrameHeight);
- testBitmap.eraseColor(SK_ColorBLUE);
- return skia::AdoptRef(SkImage::NewFromBitmap(testBitmap));
+ kTestCanvasCaptureFrameHeight, opaque);
+ testBitmap.eraseARGB(kTestAlphaValue, 30, 60, 200);
+ return SkImage::MakeFromBitmap(testBitmap);
}
void OnVerifyDeliveredFrame(
+ bool opaque,
const scoped_refptr<media::VideoFrame>& video_frame,
base::TimeTicks estimated_capture_time) {
- EXPECT_EQ(media::PIXEL_FORMAT_I420, video_frame->format());
+ if (opaque)
+ EXPECT_EQ(media::PIXEL_FORMAT_I420, video_frame->format());
+ else
+ EXPECT_EQ(media::PIXEL_FORMAT_YV12A, video_frame->format());
+
+ EXPECT_EQ(video_frame->timestamp().InMilliseconds(),
+ (estimated_capture_time - base::TimeTicks()).InMilliseconds());
const gfx::Size& size = video_frame->coded_size();
EXPECT_EQ(kTestCanvasCaptureFrameWidth, size.width());
EXPECT_EQ(kTestCanvasCaptureFrameHeight, size.height());
- const uint8_t* y_plane = video_frame->data(0);
- EXPECT_NEAR(41, y_plane[0], kTestCanvasCaptureFrameErrorTolerance);
- const uint8_t* u_plane = video_frame->data(1);
- EXPECT_NEAR(239, u_plane[0], kTestCanvasCaptureFrameErrorTolerance);
- const uint8_t* v_plane = video_frame->data(2);
- EXPECT_NEAR(110, v_plane[0], kTestCanvasCaptureFrameErrorTolerance);
+ const uint8_t* y_plane = video_frame->data(media::VideoFrame::kYPlane);
+ EXPECT_NEAR(74, y_plane[0], kTestCanvasCaptureFrameErrorTolerance);
+ const uint8_t* u_plane = video_frame->data(media::VideoFrame::kUPlane);
+ EXPECT_NEAR(193, u_plane[0], kTestCanvasCaptureFrameErrorTolerance);
+ const uint8_t* v_plane = video_frame->data(media::VideoFrame::kVPlane);
+ EXPECT_NEAR(105, v_plane[0], kTestCanvasCaptureFrameErrorTolerance);
+ if (!opaque) {
+ const uint8_t* a_plane = video_frame->data(media::VideoFrame::kAPlane);
+ EXPECT_EQ(kTestAlphaValue, a_plane[0]);
+ }
}
blink::WebMediaStreamTrack track_;
// The Class under test. Needs to be scoped_ptr to force its destruction.
- scoped_ptr<CanvasCaptureHandler> canvas_capture_handler_;
+ std::unique_ptr<CanvasCaptureHandler> canvas_capture_handler_;
protected:
media::VideoCapturerSource* GetVideoCapturerSource(
@@ -124,14 +141,28 @@ TEST_F(CanvasCaptureHandlerTest, ConstructAndDestruct) {
base::RunLoop().RunUntilIdle();
}
+// Checks that the destruction sequence works fine.
+TEST_F(CanvasCaptureHandlerTest, DestructTrack) {
+ EXPECT_TRUE(canvas_capture_handler_->needsNewFrame());
+ track_.reset();
+ base::RunLoop().RunUntilIdle();
+}
+
+// Checks that the destruction sequence works fine.
+TEST_F(CanvasCaptureHandlerTest, DestructHandler) {
+ EXPECT_TRUE(canvas_capture_handler_->needsNewFrame());
+ canvas_capture_handler_.reset();
+ base::RunLoop().RunUntilIdle();
+}
+
// Checks that VideoCapturerSource call sequence works fine.
-TEST_F(CanvasCaptureHandlerTest, GetFormatsStartAndStop) {
+TEST_P(CanvasCaptureHandlerTest, GetFormatsStartAndStop) {
InSequence s;
const blink::WebMediaStreamSource& web_media_stream_source = track_.source();
EXPECT_FALSE(web_media_stream_source.isNull());
MediaStreamVideoCapturerSource* const ms_source =
static_cast<MediaStreamVideoCapturerSource*>(
- web_media_stream_source.extraData());
+ web_media_stream_source.getExtraData());
EXPECT_TRUE(ms_source != nullptr);
media::VideoCapturerSource* source = GetVideoCapturerSource(ms_source);
EXPECT_TRUE(source != nullptr);
@@ -146,7 +177,7 @@ TEST_F(CanvasCaptureHandlerTest, GetFormatsStartAndStop) {
media::limits::kMaxFramesPerSecond /* max_requested_frame_rate */,
base::Bind(&CanvasCaptureHandlerTest::OnVideoCaptureDeviceFormats,
base::Unretained(this)));
- ASSERT_EQ(1u, formats.size());
+ ASSERT_EQ(2u, formats.size());
EXPECT_EQ(kTestCanvasCaptureWidth, formats[0].frame_size.width());
EXPECT_EQ(kTestCanvasCaptureHeight, formats[0].frame_size.height());
media::VideoCaptureParams params;
@@ -162,18 +193,19 @@ TEST_F(CanvasCaptureHandlerTest, GetFormatsStartAndStop) {
params, base::Bind(&CanvasCaptureHandlerTest::OnDeliverFrame,
base::Unretained(this)),
base::Bind(&CanvasCaptureHandlerTest::OnRunning, base::Unretained(this)));
- canvas_capture_handler_->sendNewFrame(GenerateTestImage().get());
+ canvas_capture_handler_->sendNewFrame(GenerateTestImage(GetParam()).get());
run_loop.Run();
source->StopCapture();
}
// Verifies that SkImage is processed and produces VideoFrame as expected.
-TEST_F(CanvasCaptureHandlerTest, VerifyFrame) {
+TEST_P(CanvasCaptureHandlerTest, VerifyOpaqueFrame) {
+ const bool isOpaque = GetParam();
InSequence s;
media::VideoCapturerSource* const source =
GetVideoCapturerSource(static_cast<MediaStreamVideoCapturerSource*>(
- track_.source().extraData()));
+ track_.source().getExtraData()));
EXPECT_TRUE(source != nullptr);
base::RunLoop run_loop;
@@ -181,9 +213,9 @@ TEST_F(CanvasCaptureHandlerTest, VerifyFrame) {
media::VideoCaptureParams params;
source->StartCapture(
params, base::Bind(&CanvasCaptureHandlerTest::OnVerifyDeliveredFrame,
- base::Unretained(this)),
+ base::Unretained(this), isOpaque),
base::Bind(&CanvasCaptureHandlerTest::OnRunning, base::Unretained(this)));
- canvas_capture_handler_->sendNewFrame(GenerateTestImage().get());
+ canvas_capture_handler_->sendNewFrame(GenerateTestImage(isOpaque).get());
run_loop.RunUntilIdle();
}
@@ -192,11 +224,13 @@ TEST_F(CanvasCaptureHandlerTest, CheckNeedsNewFrame) {
InSequence s;
media::VideoCapturerSource* source =
GetVideoCapturerSource(static_cast<MediaStreamVideoCapturerSource*>(
- track_.source().extraData()));
+ track_.source().getExtraData()));
EXPECT_TRUE(source != nullptr);
EXPECT_TRUE(canvas_capture_handler_->needsNewFrame());
source->StopCapture();
EXPECT_FALSE(canvas_capture_handler_->needsNewFrame());
}
+INSTANTIATE_TEST_CASE_P(, CanvasCaptureHandlerTest, ::testing::Bool());
+
} // namespace content
diff --git a/chromium/content/renderer/media/cdm/pepper_cdm_wrapper.h b/chromium/content/renderer/media/cdm/pepper_cdm_wrapper.h
index db09bbc52fb..f241df97721 100644
--- a/chromium/content/renderer/media/cdm/pepper_cdm_wrapper.h
+++ b/chromium/content/renderer/media/cdm/pepper_cdm_wrapper.h
@@ -9,6 +9,7 @@
#error This file should only be included when ENABLE_PEPPER_CDMS is defined
#endif
+#include <memory>
#include <string>
#include "base/callback.h"
@@ -36,9 +37,10 @@ class PepperCdmWrapper {
// Callback used to create a PepperCdmWrapper. This may return null if the
// Pepper CDM can not be created.
-typedef base::Callback<scoped_ptr<PepperCdmWrapper>(
+typedef base::Callback<std::unique_ptr<PepperCdmWrapper>(
const std::string& pluginType,
- const GURL& security_origin)> CreatePepperCdmCB;
+ const GURL& security_origin)>
+ CreatePepperCdmCB;
} // namespace content
diff --git a/chromium/content/renderer/media/cdm/pepper_cdm_wrapper_impl.cc b/chromium/content/renderer/media/cdm/pepper_cdm_wrapper_impl.cc
index 8d24724d434..43513536ac1 100644
--- a/chromium/content/renderer/media/cdm/pepper_cdm_wrapper_impl.cc
+++ b/chromium/content/renderer/media/cdm/pepper_cdm_wrapper_impl.cc
@@ -9,6 +9,7 @@
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/pepper_webplugin_impl.h"
+#include "third_party/WebKit/public/platform/URLConversion.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebElement.h"
@@ -25,7 +26,7 @@ void WebHelperPluginDeleter::operator()(blink::WebHelperPlugin* plugin) const {
plugin->destroy();
}
-scoped_ptr<PepperCdmWrapper> PepperCdmWrapperImpl::Create(
+std::unique_ptr<PepperCdmWrapper> PepperCdmWrapperImpl::Create(
blink::WebLocalFrame* frame,
const std::string& pluginType,
const GURL& security_origin) {
@@ -36,16 +37,17 @@ scoped_ptr<PepperCdmWrapper> PepperCdmWrapperImpl::Create(
// Note: The code will continue after navigation to the "same" origin, even
// though the CDM is no longer necessary.
// TODO: Consider avoiding this possibility entirely. http://crbug.com/575236
- GURL frame_security_origin(frame->securityOrigin().toString());
+ GURL frame_security_origin(
+ blink::WebStringToGURL(frame->getSecurityOrigin().toString()));
if (frame_security_origin != security_origin) {
LOG(ERROR) << "Frame has a different origin than the EME call.";
- return scoped_ptr<PepperCdmWrapper>();
+ return std::unique_ptr<PepperCdmWrapper>();
}
ScopedHelperPlugin helper_plugin(blink::WebHelperPlugin::create(
blink::WebString::fromUTF8(pluginType), frame));
if (!helper_plugin)
- return scoped_ptr<PepperCdmWrapper>();
+ return std::unique_ptr<PepperCdmWrapper>();
blink::WebPlugin* plugin = helper_plugin->getPlugin();
DCHECK(!plugin->isPlaceholder()); // Prevented by Blink.
@@ -55,7 +57,7 @@ scoped_ptr<PepperCdmWrapper> PepperCdmWrapperImpl::Create(
scoped_refptr<PepperPluginInstanceImpl> plugin_instance =
ppapi_plugin->instance();
if (!plugin_instance.get())
- return scoped_ptr<PepperCdmWrapper>();
+ return std::unique_ptr<PepperCdmWrapper>();
GURL plugin_url(plugin_instance->container()->element().document().url());
GURL plugin_security_origin = plugin_url.GetOrigin();
@@ -63,9 +65,9 @@ scoped_ptr<PepperCdmWrapper> PepperCdmWrapperImpl::Create(
<< "Pepper instance has a different origin than the EME call.";
if (!plugin_instance->GetContentDecryptorDelegate())
- return scoped_ptr<PepperCdmWrapper>();
+ return std::unique_ptr<PepperCdmWrapper>();
- return scoped_ptr<PepperCdmWrapper>(
+ return std::unique_ptr<PepperCdmWrapper>(
new PepperCdmWrapperImpl(std::move(helper_plugin), plugin_instance));
}
diff --git a/chromium/content/renderer/media/cdm/pepper_cdm_wrapper_impl.h b/chromium/content/renderer/media/cdm/pepper_cdm_wrapper_impl.h
index 20b4f4c0d61..68d855e3bb3 100644
--- a/chromium/content/renderer/media/cdm/pepper_cdm_wrapper_impl.h
+++ b/chromium/content/renderer/media/cdm/pepper_cdm_wrapper_impl.h
@@ -9,10 +9,11 @@
#error This file should only be included when ENABLE_PEPPER_CDMS is defined
#endif
+#include <memory>
+
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "content/renderer/media/cdm/pepper_cdm_wrapper.h"
namespace blink {
@@ -41,9 +42,9 @@ struct WebHelperPluginDeleter {
// blink:: objects.
class PepperCdmWrapperImpl : public PepperCdmWrapper {
public:
- static scoped_ptr<PepperCdmWrapper> Create(blink::WebLocalFrame* frame,
- const std::string& pluginType,
- const GURL& security_origin);
+ static std::unique_ptr<PepperCdmWrapper> Create(blink::WebLocalFrame* frame,
+ const std::string& pluginType,
+ const GURL& security_origin);
~PepperCdmWrapperImpl() override;
@@ -51,7 +52,7 @@ class PepperCdmWrapperImpl : public PepperCdmWrapper {
ContentDecryptorDelegate* GetCdmDelegate() override;
private:
- typedef scoped_ptr<blink::WebHelperPlugin, WebHelperPluginDeleter>
+ typedef std::unique_ptr<blink::WebHelperPlugin, WebHelperPluginDeleter>
ScopedHelperPlugin;
// Takes ownership of |helper_plugin| and |plugin_instance|.
diff --git a/chromium/content/renderer/media/cdm/ppapi_decryptor.cc b/chromium/content/renderer/media/cdm/ppapi_decryptor.cc
index b505f3c6b5f..07853c408ae 100644
--- a/chromium/content/renderer/media/cdm/ppapi_decryptor.cc
+++ b/chromium/content/renderer/media/cdm/ppapi_decryptor.cc
@@ -41,7 +41,7 @@ void PpapiDecryptor::Create(
std::string plugin_type = media::GetPepperType(key_system);
DCHECK(!plugin_type.empty());
- scoped_ptr<PepperCdmWrapper> pepper_cdm_wrapper;
+ std::unique_ptr<PepperCdmWrapper> pepper_cdm_wrapper;
{
TRACE_EVENT0("media", "PpapiDecryptor::CreatePepperCDM");
pepper_cdm_wrapper = create_pepper_cdm_cb.Run(plugin_type, security_origin);
@@ -62,7 +62,7 @@ void PpapiDecryptor::Create(
session_keys_change_cb, session_expiration_update_cb));
// |ppapi_decryptor| ownership is passed to the promise.
- scoped_ptr<media::CdmInitializedPromise> promise(
+ std::unique_ptr<media::CdmInitializedPromise> promise(
new media::CdmInitializedPromise(cdm_created_cb, ppapi_decryptor));
ppapi_decryptor->InitializeCdm(key_system, allow_distinctive_identifier,
@@ -70,7 +70,7 @@ void PpapiDecryptor::Create(
}
PpapiDecryptor::PpapiDecryptor(
- scoped_ptr<PepperCdmWrapper> pepper_cdm_wrapper,
+ std::unique_ptr<PepperCdmWrapper> pepper_cdm_wrapper,
const media::SessionMessageCB& session_message_cb,
const media::SessionClosedCB& session_closed_cb,
const media::LegacySessionErrorCB& legacy_session_error_cb,
@@ -100,7 +100,7 @@ void PpapiDecryptor::InitializeCdm(
const std::string& key_system,
bool allow_distinctive_identifier,
bool allow_persistent_state,
- scoped_ptr<media::SimpleCdmPromise> promise) {
+ std::unique_ptr<media::SimpleCdmPromise> promise) {
base::WeakPtr<PpapiDecryptor> weak_this = weak_ptr_factory_.GetWeakPtr();
CdmDelegate()->Initialize(
key_system, allow_distinctive_identifier, allow_persistent_state,
@@ -115,7 +115,7 @@ void PpapiDecryptor::InitializeCdm(
void PpapiDecryptor::SetServerCertificate(
const std::vector<uint8_t>& certificate,
- scoped_ptr<media::SimpleCdmPromise> promise) {
+ std::unique_ptr<media::SimpleCdmPromise> promise) {
DVLOG(2) << __FUNCTION__;
DCHECK(render_task_runner_->BelongsToCurrentThread());
@@ -131,7 +131,7 @@ void PpapiDecryptor::CreateSessionAndGenerateRequest(
SessionType session_type,
media::EmeInitDataType init_data_type,
const std::vector<uint8_t>& init_data,
- scoped_ptr<media::NewSessionCdmPromise> promise) {
+ std::unique_ptr<media::NewSessionCdmPromise> promise) {
DVLOG(2) << __FUNCTION__;
DCHECK(render_task_runner_->BelongsToCurrentThread());
@@ -147,7 +147,7 @@ void PpapiDecryptor::CreateSessionAndGenerateRequest(
void PpapiDecryptor::LoadSession(
SessionType session_type,
const std::string& session_id,
- scoped_ptr<media::NewSessionCdmPromise> promise) {
+ std::unique_ptr<media::NewSessionCdmPromise> promise) {
DVLOG(2) << __FUNCTION__;
DCHECK(render_task_runner_->BelongsToCurrentThread());
@@ -161,7 +161,7 @@ void PpapiDecryptor::LoadSession(
void PpapiDecryptor::UpdateSession(
const std::string& session_id,
const std::vector<uint8_t>& response,
- scoped_ptr<media::SimpleCdmPromise> promise) {
+ std::unique_ptr<media::SimpleCdmPromise> promise) {
DVLOG(2) << __FUNCTION__;
DCHECK(render_task_runner_->BelongsToCurrentThread());
@@ -172,8 +172,9 @@ void PpapiDecryptor::UpdateSession(
CdmDelegate()->UpdateSession(session_id, response, std::move(promise));
}
-void PpapiDecryptor::CloseSession(const std::string& session_id,
- scoped_ptr<media::SimpleCdmPromise> promise) {
+void PpapiDecryptor::CloseSession(
+ const std::string& session_id,
+ std::unique_ptr<media::SimpleCdmPromise> promise) {
DVLOG(2) << __FUNCTION__;
DCHECK(render_task_runner_->BelongsToCurrentThread());
@@ -187,7 +188,7 @@ void PpapiDecryptor::CloseSession(const std::string& session_id,
void PpapiDecryptor::RemoveSession(
const std::string& session_id,
- scoped_ptr<media::SimpleCdmPromise> promise) {
+ std::unique_ptr<media::SimpleCdmPromise> promise) {
DVLOG(2) << __FUNCTION__;
DCHECK(render_task_runner_->BelongsToCurrentThread());
diff --git a/chromium/content/renderer/media/cdm/ppapi_decryptor.h b/chromium/content/renderer/media/cdm/ppapi_decryptor.h
index 7aff248ab31..39079ff1fea 100644
--- a/chromium/content/renderer/media/cdm/ppapi_decryptor.h
+++ b/chromium/content/renderer/media/cdm/ppapi_decryptor.h
@@ -53,22 +53,23 @@ class PpapiDecryptor : public media::MediaKeys,
// media::MediaKeys implementation.
void SetServerCertificate(
const std::vector<uint8_t>& certificate,
- scoped_ptr<media::SimpleCdmPromise> promise) override;
+ std::unique_ptr<media::SimpleCdmPromise> promise) override;
void CreateSessionAndGenerateRequest(
SessionType session_type,
media::EmeInitDataType init_data_type,
const std::vector<uint8_t>& init_data,
- scoped_ptr<media::NewSessionCdmPromise> promise) override;
- void LoadSession(SessionType session_type,
- const std::string& session_id,
- scoped_ptr<media::NewSessionCdmPromise> promise) override;
+ std::unique_ptr<media::NewSessionCdmPromise> promise) override;
+ void LoadSession(
+ SessionType session_type,
+ const std::string& session_id,
+ std::unique_ptr<media::NewSessionCdmPromise> promise) override;
void UpdateSession(const std::string& session_id,
const std::vector<uint8_t>& response,
- scoped_ptr<media::SimpleCdmPromise> promise) override;
+ std::unique_ptr<media::SimpleCdmPromise> promise) override;
void CloseSession(const std::string& session_id,
- scoped_ptr<media::SimpleCdmPromise> promise) override;
+ std::unique_ptr<media::SimpleCdmPromise> promise) override;
void RemoveSession(const std::string& session_id,
- scoped_ptr<media::SimpleCdmPromise> promise) override;
+ std::unique_ptr<media::SimpleCdmPromise> promise) override;
CdmContext* GetCdmContext() override;
// media::CdmContext implementation.
@@ -97,7 +98,7 @@ class PpapiDecryptor : public media::MediaKeys,
private:
PpapiDecryptor(
- scoped_ptr<PepperCdmWrapper> pepper_cdm_wrapper,
+ std::unique_ptr<PepperCdmWrapper> pepper_cdm_wrapper,
const media::SessionMessageCB& session_message_cb,
const media::SessionClosedCB& session_closed_cb,
const media::LegacySessionErrorCB& legacy_session_error_cb,
@@ -109,7 +110,7 @@ class PpapiDecryptor : public media::MediaKeys,
void InitializeCdm(const std::string& key_system,
bool allow_distinctive_identifier,
bool allow_persistent_state,
- scoped_ptr<media::SimpleCdmPromise> promise);
+ std::unique_ptr<media::SimpleCdmPromise> promise);
void OnDecoderInitialized(StreamType stream_type, bool success);
@@ -140,7 +141,7 @@ class PpapiDecryptor : public media::MediaKeys,
// Hold a reference of the Pepper CDM wrapper to make sure the plugin lives
// as long as needed.
- scoped_ptr<PepperCdmWrapper> pepper_cdm_wrapper_;
+ std::unique_ptr<PepperCdmWrapper> pepper_cdm_wrapper_;
// Callbacks for firing session events.
media::SessionMessageCB session_message_cb_;
diff --git a/chromium/content/renderer/media/cdm/proxy_media_keys.cc b/chromium/content/renderer/media/cdm/proxy_media_keys.cc
index 2e5752eb6ee..a1299eac3d1 100644
--- a/chromium/content/renderer/media/cdm/proxy_media_keys.cc
+++ b/chromium/content/renderer/media/cdm/proxy_media_keys.cc
@@ -13,7 +13,6 @@
#include "media/base/cdm_initialized_promise.h"
#include "media/base/cdm_key_information.h"
#include "media/base/cdm_promise.h"
-#include "media/base/key_systems.h"
namespace content {
@@ -34,7 +33,7 @@ void ProxyMediaKeys::Create(
session_keys_change_cb, session_expiration_update_cb));
// ProxyMediaKeys ownership passed to the promise.
- scoped_ptr<media::CdmInitializedPromise> promise(
+ std::unique_ptr<media::CdmInitializedPromise> promise(
new media::CdmInitializedPromise(cdm_created_cb, proxy_media_keys));
proxy_media_keys->InitializeCdm(key_system, security_origin,
@@ -43,7 +42,7 @@ void ProxyMediaKeys::Create(
void ProxyMediaKeys::SetServerCertificate(
const std::vector<uint8_t>& certificate,
- scoped_ptr<media::SimpleCdmPromise> promise) {
+ std::unique_ptr<media::SimpleCdmPromise> promise) {
uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
manager_->SetServerCertificate(cdm_id_, promise_id, certificate);
}
@@ -52,7 +51,7 @@ void ProxyMediaKeys::CreateSessionAndGenerateRequest(
SessionType session_type,
media::EmeInitDataType init_data_type,
const std::vector<uint8_t>& init_data,
- scoped_ptr<media::NewSessionCdmPromise> promise) {
+ std::unique_ptr<media::NewSessionCdmPromise> promise) {
CdmHostMsg_CreateSession_InitDataType create_session_init_data_type =
INIT_DATA_TYPE_WEBM;
switch (init_data_type) {
@@ -79,7 +78,7 @@ void ProxyMediaKeys::CreateSessionAndGenerateRequest(
void ProxyMediaKeys::LoadSession(
SessionType session_type,
const std::string& session_id,
- scoped_ptr<media::NewSessionCdmPromise> promise) {
+ std::unique_ptr<media::NewSessionCdmPromise> promise) {
uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
manager_->LoadSession(cdm_id_, promise_id, session_type, session_id);
}
@@ -87,20 +86,21 @@ void ProxyMediaKeys::LoadSession(
void ProxyMediaKeys::UpdateSession(
const std::string& session_id,
const std::vector<uint8_t>& response,
- scoped_ptr<media::SimpleCdmPromise> promise) {
+ std::unique_ptr<media::SimpleCdmPromise> promise) {
uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
manager_->UpdateSession(cdm_id_, promise_id, session_id, response);
}
-void ProxyMediaKeys::CloseSession(const std::string& session_id,
- scoped_ptr<media::SimpleCdmPromise> promise) {
+void ProxyMediaKeys::CloseSession(
+ const std::string& session_id,
+ std::unique_ptr<media::SimpleCdmPromise> promise) {
uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
manager_->CloseSession(cdm_id_, promise_id, session_id);
}
void ProxyMediaKeys::RemoveSession(
const std::string& session_id,
- scoped_ptr<media::SimpleCdmPromise> promise) {
+ std::unique_ptr<media::SimpleCdmPromise> promise) {
uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
manager_->RemoveSession(cdm_id_, promise_id, session_id);
}
@@ -195,7 +195,7 @@ void ProxyMediaKeys::InitializeCdm(
const std::string& key_system,
const GURL& security_origin,
bool use_hw_secure_codecs,
- scoped_ptr<media::SimpleCdmPromise> promise) {
+ std::unique_ptr<media::SimpleCdmPromise> promise) {
uint32_t promise_id = cdm_promise_adapter_.SavePromise(std::move(promise));
manager_->InitializeCdm(cdm_id_, promise_id, this, key_system,
security_origin, use_hw_secure_codecs);
diff --git a/chromium/content/renderer/media/cdm/proxy_media_keys.h b/chromium/content/renderer/media/cdm/proxy_media_keys.h
index e80924472cc..e78ea365bef 100644
--- a/chromium/content/renderer/media/cdm/proxy_media_keys.h
+++ b/chromium/content/renderer/media/cdm/proxy_media_keys.h
@@ -44,22 +44,23 @@ class ProxyMediaKeys : public media::MediaKeys, public media::CdmContext {
// MediaKeys implementation.
void SetServerCertificate(
const std::vector<uint8_t>& certificate,
- scoped_ptr<media::SimpleCdmPromise> promise) override;
+ std::unique_ptr<media::SimpleCdmPromise> promise) override;
void CreateSessionAndGenerateRequest(
SessionType session_type,
media::EmeInitDataType init_data_type,
const std::vector<uint8_t>& init_data,
- scoped_ptr<media::NewSessionCdmPromise> promise) override;
- void LoadSession(SessionType session_type,
- const std::string& session_id,
- scoped_ptr<media::NewSessionCdmPromise> promise) override;
+ std::unique_ptr<media::NewSessionCdmPromise> promise) override;
+ void LoadSession(
+ SessionType session_type,
+ const std::string& session_id,
+ std::unique_ptr<media::NewSessionCdmPromise> promise) override;
void UpdateSession(const std::string& session_id,
const std::vector<uint8_t>& response,
- scoped_ptr<media::SimpleCdmPromise> promise) override;
+ std::unique_ptr<media::SimpleCdmPromise> promise) override;
void CloseSession(const std::string& session_id,
- scoped_ptr<media::SimpleCdmPromise> promise) override;
+ std::unique_ptr<media::SimpleCdmPromise> promise) override;
void RemoveSession(const std::string& session_id,
- scoped_ptr<media::SimpleCdmPromise> promise) override;
+ std::unique_ptr<media::SimpleCdmPromise> promise) override;
media::CdmContext* GetCdmContext() override;
// media::CdmContext implementation.
@@ -104,7 +105,7 @@ class ProxyMediaKeys : public media::MediaKeys, public media::CdmContext {
void InitializeCdm(const std::string& key_system,
const GURL& security_origin,
bool use_hw_secure_codecs,
- scoped_ptr<media::SimpleCdmPromise> promise);
+ std::unique_ptr<media::SimpleCdmPromise> promise);
RendererCdmManager* manager_;
int cdm_id_;
diff --git a/chromium/content/renderer/media/cdm/render_cdm_factory.cc b/chromium/content/renderer/media/cdm/render_cdm_factory.cc
index e539cddfe9e..8363084bc38 100644
--- a/chromium/content/renderer/media/cdm/render_cdm_factory.cc
+++ b/chromium/content/renderer/media/cdm/render_cdm_factory.cc
@@ -4,10 +4,11 @@
#include "content/renderer/media/cdm/render_cdm_factory.h"
+#include <memory>
+
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
-#include "base/memory/scoped_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
#include "media/base/cdm_config.h"
@@ -58,7 +59,8 @@ void RenderCdmFactory::Create(
}
if (media::CanUseAesDecryptor(key_system)) {
- // TODO(sandersd): Currently the prefixed API always allows distinctive
+ // TODO(sandersd): Address this now that prefixed EME has been removed.
+ // http://crbug.com/249976. The prefixed API always allowed distinctive
// identifiers and persistent state. Once that changes we can sanity check
// here that neither is allowed for AesDecryptor, since it does not support
// them and should never be configured that way. http://crbug.com/455271
diff --git a/chromium/content/renderer/media/cdm/render_cdm_factory.h b/chromium/content/renderer/media/cdm/render_cdm_factory.h
index da7ec96cc5c..9824bf99e95 100644
--- a/chromium/content/renderer/media/cdm/render_cdm_factory.h
+++ b/chromium/content/renderer/media/cdm/render_cdm_factory.h
@@ -5,10 +5,10 @@
#ifndef CONTENT_RENDERER_MEDIA_CDM_RENDER_CDM_FACTORY_H_
#define CONTENT_RENDERER_MEDIA_CDM_RENDER_CDM_FACTORY_H_
+#include <memory>
#include <string>
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/threading/thread_checker.h"
#include "media/base/cdm_factory.h"
#include "media/base/media_keys.h"
diff --git a/chromium/content/renderer/media/html_video_element_capturer_source.cc b/chromium/content/renderer/media/html_video_element_capturer_source.cc
index 293b9fe95e4..04dd824f9d6 100644
--- a/chromium/content/renderer/media/html_video_element_capturer_source.cc
+++ b/chromium/content/renderer/media/html_video_element_capturer_source.cc
@@ -4,10 +4,12 @@
#include "content/renderer/media/html_video_element_capturer_source.h"
+#include "base/memory/ptr_util.h"
#include "base/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "content/public/renderer/render_thread.h"
#include "content/renderer/media/media_stream_video_source.h"
+#include "content/renderer/media/webrtc_uma_histograms.h"
#include "media/base/limits.h"
#include "media/blink/webmediaplayer_impl.h"
#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
@@ -24,11 +26,15 @@ const float kMinFramesPerSecond = 1.0;
namespace content {
//static
-scoped_ptr<HtmlVideoElementCapturerSource>
+std::unique_ptr<HtmlVideoElementCapturerSource>
HtmlVideoElementCapturerSource::CreateFromWebMediaPlayerImpl(
blink::WebMediaPlayer* player,
const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) {
- return make_scoped_ptr(new HtmlVideoElementCapturerSource(
+ // Save histogram data so we can see how much HTML Video capture is used.
+ // The histogram counts the number of calls to the JS API.
+ UpdateWebRTCMethodCount(WEBKIT_VIDEO_CAPTURE_STREAM);
+
+ return base::WrapUnique(new HtmlVideoElementCapturerSource(
static_cast<media::WebMediaPlayerImpl*>(player)->AsWeakPtr(),
io_task_runner));
}
@@ -85,8 +91,9 @@ void HtmlVideoElementCapturerSource::StartCapture(
return;
}
const blink::WebSize resolution = web_media_player_->naturalSize();
- canvas_.reset(skia::CreatePlatformCanvas(resolution.width, resolution.height,
- true /* is_opaque */));
+ canvas_ = sk_sp<SkCanvas>(skia::CreatePlatformCanvas(resolution.width,
+ resolution.height,
+ true /* is_opaque */));
new_frame_callback_ = new_frame_callback;
// Force |capture_frame_rate_| to be in between k{Min,Max}FramesPerSecond.
diff --git a/chromium/content/renderer/media/html_video_element_capturer_source.h b/chromium/content/renderer/media/html_video_element_capturer_source.h
index 5bac2c290ff..e248358846d 100644
--- a/chromium/content/renderer/media/html_video_element_capturer_source.h
+++ b/chromium/content/renderer/media/html_video_element_capturer_source.h
@@ -14,6 +14,7 @@
#include "media/base/video_frame_pool.h"
#include "media/base/video_types.h"
#include "skia/ext/platform_canvas.h"
+#include "skia/ext/refptr.h"
#include "third_party/WebKit/public/platform/WebSize.h"
namespace blink {
@@ -28,10 +29,10 @@ namespace content {
class CONTENT_EXPORT HtmlVideoElementCapturerSource final
: public media::VideoCapturerSource {
public:
- static scoped_ptr<HtmlVideoElementCapturerSource>
- CreateFromWebMediaPlayerImpl(
- blink::WebMediaPlayer* player,
- const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
+ static std::unique_ptr<HtmlVideoElementCapturerSource>
+ CreateFromWebMediaPlayerImpl(
+ blink::WebMediaPlayer* player,
+ const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner);
HtmlVideoElementCapturerSource(
const base::WeakPtr<blink::WebMediaPlayer>& player,
@@ -55,7 +56,7 @@ class CONTENT_EXPORT HtmlVideoElementCapturerSource final
void sendNewFrame();
media::VideoFramePool frame_pool_;
- scoped_ptr<SkCanvas> canvas_;
+ sk_sp<SkCanvas> canvas_;
const base::WeakPtr<blink::WebMediaPlayer> web_media_player_;
const scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
diff --git a/chromium/content/renderer/media/html_video_element_capturer_source_unittest.cc b/chromium/content/renderer/media/html_video_element_capturer_source_unittest.cc
index af949ecf62d..b3bbc3b2469 100644
--- a/chromium/content/renderer/media/html_video_element_capturer_source_unittest.cc
+++ b/chromium/content/renderer/media/html_video_element_capturer_source_unittest.cc
@@ -10,6 +10,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
+#include "third_party/WebKit/public/platform/WebString.h"
using ::testing::_;
using ::testing::InSequence;
@@ -54,12 +55,13 @@ class MockWebMediaPlayer : public blink::WebMediaPlayer,
bool seeking() const override { return false; }
double duration() const override { return 0.0; }
double currentTime() const override { return 0.0; }
- NetworkState networkState() const override {
+ NetworkState getNetworkState() const override {
return NetworkStateEmpty;
}
- ReadyState readyState() const override {
+ ReadyState getReadyState() const override {
return ReadyStateHaveNothing;
}
+ blink::WebString getErrorMessage() override { return blink::WebString(); }
bool didLoadingProgress() override { return true; }
bool hasSingleSecurityOrigin() const override { return true; }
bool didPassCORSAccessCheck() const override { return true; }
@@ -67,8 +69,8 @@ class MockWebMediaPlayer : public blink::WebMediaPlayer,
unsigned decodedFrameCount() const override { return 0; }
unsigned droppedFrameCount() const override { return 0; }
unsigned corruptedFrameCount() const override { return 0; }
- unsigned audioDecodedByteCount() const override { return 0; }
- unsigned videoDecodedByteCount() const override { return 0; }
+ size_t audioDecodedByteCount() const override { return 0; }
+ size_t videoDecodedByteCount() const override { return 0; }
void paint(blink::WebCanvas* canvas,
const blink::WebRect& paint_rectangle,
@@ -111,8 +113,8 @@ class HTMLVideoElementCapturerSourceTest : public testing::Test {
// schedule capture events.
const base::MessageLoopForUI message_loop_;
- scoped_ptr<MockWebMediaPlayer> web_media_player_;
- scoped_ptr<HtmlVideoElementCapturerSource> html_video_capturer_;
+ std::unique_ptr<MockWebMediaPlayer> web_media_player_;
+ std::unique_ptr<HtmlVideoElementCapturerSource> html_video_capturer_;
};
// Constructs and destructs all objects, in particular |html_video_capturer_|
diff --git a/chromium/content/renderer/media/media_interface_provider.cc b/chromium/content/renderer/media/media_interface_provider.cc
new file mode 100644
index 00000000000..e19723a7c4b
--- /dev/null
+++ b/chromium/content/renderer/media/media_interface_provider.cc
@@ -0,0 +1,68 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/media_interface_provider.h"
+
+#include "base/bind.h"
+#include "media/mojo/interfaces/content_decryption_module.mojom.h"
+#include "media/mojo/interfaces/renderer.mojom.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "mojo/shell/public/cpp/connect.h"
+
+namespace content {
+
+MediaInterfaceProvider::MediaInterfaceProvider(
+ const ConnectToApplicationCB& connect_to_app_cb)
+ : connect_to_app_cb_(connect_to_app_cb) {
+ DCHECK(!connect_to_app_cb_.is_null());
+}
+
+MediaInterfaceProvider::~MediaInterfaceProvider() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+}
+
+void MediaInterfaceProvider::GetInterface(const mojo::String& interface_name,
+ mojo::ScopedMessagePipeHandle pipe) {
+ DVLOG(1) << __FUNCTION__;
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (interface_name == media::interfaces::ContentDecryptionModule::Name_) {
+ GetMediaServiceFactory()->CreateCdm(
+ mojo::MakeRequest<media::interfaces::ContentDecryptionModule>(
+ std::move(pipe)));
+ } else if (interface_name == media::interfaces::Renderer::Name_) {
+ GetMediaServiceFactory()->CreateRenderer(
+ mojo::MakeRequest<media::interfaces::Renderer>(std::move(pipe)));
+ } else if (interface_name == media::interfaces::AudioDecoder::Name_) {
+ GetMediaServiceFactory()->CreateAudioDecoder(
+ mojo::MakeRequest<media::interfaces::AudioDecoder>(std::move(pipe)));
+ } else {
+ NOTREACHED();
+ }
+}
+
+media::interfaces::ServiceFactory*
+MediaInterfaceProvider::GetMediaServiceFactory() {
+ DVLOG(1) << __FUNCTION__;
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ if (!media_service_factory_) {
+ mojo::shell::mojom::InterfaceProviderPtr interface_provider =
+ connect_to_app_cb_.Run(GURL("mojo:media"));
+ mojo::GetInterface(interface_provider.get(), &media_service_factory_);
+ media_service_factory_.set_connection_error_handler(base::Bind(
+ &MediaInterfaceProvider::OnConnectionError, base::Unretained(this)));
+ }
+
+ return media_service_factory_.get();
+}
+
+void MediaInterfaceProvider::OnConnectionError() {
+ DVLOG(1) << __FUNCTION__;
+ DCHECK(thread_checker_.CalledOnValidThread());
+
+ media_service_factory_.reset();
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/media_interface_provider.h b/chromium/content/renderer/media/media_interface_provider.h
new file mode 100644
index 00000000000..0e9166aa401
--- /dev/null
+++ b/chromium/content/renderer/media/media_interface_provider.h
@@ -0,0 +1,49 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_MEDIA_INTERFACE_PROVIDER_H_
+#define CONTENT_RENDERER_MEDIA_MEDIA_INTERFACE_PROVIDER_H_
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/threading/thread_checker.h"
+#include "content/common/content_export.h"
+#include "media/mojo/interfaces/service_factory.mojom.h"
+#include "mojo/shell/public/interfaces/interface_provider.mojom.h"
+#include "url/gurl.h"
+
+namespace content {
+
+// MediaInterfaceProvider is an implementation of mojo InterfaceProvider that
+// provides media related services and handles app disconnection automatically.
+// This class is single threaded.
+class CONTENT_EXPORT MediaInterfaceProvider
+ : public mojo::shell::mojom::InterfaceProvider {
+ public:
+ // Callback used to connect to a mojo application.
+ using ConnectToApplicationCB =
+ base::Callback<mojo::shell::mojom::InterfaceProviderPtr(const GURL& url)>;
+
+ explicit MediaInterfaceProvider(
+ const ConnectToApplicationCB& connect_to_app_cb);
+ ~MediaInterfaceProvider() final;
+
+ // InterfaceProvider implementation.
+ void GetInterface(const mojo::String& interface_name,
+ mojo::ScopedMessagePipeHandle pipe) final;
+
+ private:
+ media::interfaces::ServiceFactory* GetMediaServiceFactory();
+ void OnConnectionError();
+
+ base::ThreadChecker thread_checker_;
+ ConnectToApplicationCB connect_to_app_cb_;
+ media::interfaces::ServiceFactoryPtr media_service_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaInterfaceProvider);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_MEDIA_INTERFACE_PROVIDER_H_
diff --git a/chromium/content/renderer/media/media_permission_dispatcher.cc b/chromium/content/renderer/media/media_permission_dispatcher.cc
index 666d194e76b..d8e55195ae2 100644
--- a/chromium/content/renderer/media/media_permission_dispatcher.cc
+++ b/chromium/content/renderer/media/media_permission_dispatcher.cc
@@ -4,45 +4,128 @@
#include "content/renderer/media/media_permission_dispatcher.h"
+#include "base/bind.h"
#include "base/logging.h"
+#include "base/single_thread_task_runner.h"
+#include "base/thread_task_runner_handle.h"
+#include "media/base/bind_to_current_loop.h"
+#include "url/gurl.h"
+
+namespace {
+
+using Type = media::MediaPermission::Type;
+
+blink::mojom::PermissionName MediaPermissionTypeToPermissionName(Type type) {
+ switch (type) {
+ case Type::PROTECTED_MEDIA_IDENTIFIER:
+ return blink::mojom::PermissionName::PROTECTED_MEDIA_IDENTIFIER;
+ case Type::AUDIO_CAPTURE:
+ return blink::mojom::PermissionName::AUDIO_CAPTURE;
+ case Type::VIDEO_CAPTURE:
+ return blink::mojom::PermissionName::VIDEO_CAPTURE;
+ }
+ NOTREACHED();
+ return blink::mojom::PermissionName::PROTECTED_MEDIA_IDENTIFIER;
+}
+
+} // namespace
namespace content {
-MediaPermissionDispatcher::MediaPermissionDispatcher() : next_request_id_(0) {}
+MediaPermissionDispatcher::MediaPermissionDispatcher(
+ const ConnectToServiceCB& connect_to_service_cb)
+ : connect_to_service_cb_(connect_to_service_cb),
+ task_runner_(base::ThreadTaskRunnerHandle::Get()),
+ next_request_id_(0),
+ weak_factory_(this) {
+ DCHECK(!connect_to_service_cb_.is_null());
+ weak_ptr_ = weak_factory_.GetWeakPtr();
+}
MediaPermissionDispatcher::~MediaPermissionDispatcher() {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+
// Fire all pending callbacks with |false|.
for (auto& request : requests_)
request.second.Run(false);
+}
+
+void MediaPermissionDispatcher::HasPermission(
+ Type type,
+ const GURL& security_origin,
+ const PermissionStatusCB& permission_status_cb) {
+ if (!task_runner_->RunsTasksOnCurrentThread()) {
+ task_runner_->PostTask(
+ FROM_HERE, base::Bind(&MediaPermissionDispatcher::HasPermission,
+ weak_ptr_, type, security_origin,
+ media::BindToCurrentLoop(permission_status_cb)));
+ return;
+ }
+
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+
+ if (!permission_service_)
+ connect_to_service_cb_.Run(mojo::GetProxy(&permission_service_));
- requests_.clear();
+ int request_id = RegisterCallback(permission_status_cb);
+ DVLOG(2) << __FUNCTION__ << ": request ID " << request_id;
+
+ permission_service_->HasPermission(
+ MediaPermissionTypeToPermissionName(type), security_origin.spec(),
+ base::Bind(&MediaPermissionDispatcher::OnPermissionStatus, weak_ptr_,
+ request_id));
+}
+
+void MediaPermissionDispatcher::RequestPermission(
+ Type type,
+ const GURL& security_origin,
+ const PermissionStatusCB& permission_status_cb) {
+ if (!task_runner_->RunsTasksOnCurrentThread()) {
+ task_runner_->PostTask(
+ FROM_HERE, base::Bind(&MediaPermissionDispatcher::RequestPermission,
+ weak_ptr_, type, security_origin,
+ media::BindToCurrentLoop(permission_status_cb)));
+ return;
+ }
+
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+
+ if (!permission_service_)
+ connect_to_service_cb_.Run(mojo::GetProxy(&permission_service_));
+
+ int request_id = RegisterCallback(permission_status_cb);
+ DVLOG(2) << __FUNCTION__ << ": request ID " << request_id;
+
+ permission_service_->RequestPermission(
+ MediaPermissionTypeToPermissionName(type), security_origin.spec(),
+ base::Bind(&MediaPermissionDispatcher::OnPermissionStatus, weak_ptr_,
+ request_id));
}
uint32_t MediaPermissionDispatcher::RegisterCallback(
const PermissionStatusCB& permission_status_cb) {
- DCHECK(thread_checker_.CalledOnValidThread());
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
+
uint32_t request_id = next_request_id_++;
DCHECK(!requests_.count(request_id));
requests_[request_id] = permission_status_cb;
+
return request_id;
}
-void MediaPermissionDispatcher::DeliverResult(uint32_t request_id,
- bool granted) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DVLOG(2) << __FUNCTION__ << ": (" << request_id << ", " << granted << ")";
+void MediaPermissionDispatcher::OnPermissionStatus(
+ uint32_t request_id,
+ blink::mojom::PermissionStatus status) {
+ DVLOG(2) << __FUNCTION__ << ": (" << request_id << ", " << status << ")";
+ DCHECK(task_runner_->RunsTasksOnCurrentThread());
RequestMap::iterator iter = requests_.find(request_id);
- if (iter == requests_.end()) {
- DVLOG(2) << "Request not found.";
- return;
- }
+ DCHECK(iter != requests_.end()) << "Request not found.";
PermissionStatusCB permission_status_cb = iter->second;
requests_.erase(iter);
- permission_status_cb.Run(granted);
+ permission_status_cb.Run(status == blink::mojom::PermissionStatus::GRANTED);
}
} // namespace content
diff --git a/chromium/content/renderer/media/media_permission_dispatcher.h b/chromium/content/renderer/media/media_permission_dispatcher.h
index 7bed6fc0977..2a94defebcb 100644
--- a/chromium/content/renderer/media/media_permission_dispatcher.h
+++ b/chromium/content/renderer/media/media_permission_dispatcher.h
@@ -2,11 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// Base class for MediaPermission implementations in content. This class allows
-// multiple pending PermissionService calls by managing callbacks for its
-// subclasses. This class is not thread safe and should only be used on one
-// thread.
-
#ifndef CONTENT_RENDERER_MEDIA_MEDIA_PERMISSION_DISPATCHER_H_
#define CONTENT_RENDERER_MEDIA_MEDIA_PERMISSION_DISPATCHER_H_
@@ -14,37 +9,63 @@
#include <map>
+#include "base/callback.h"
#include "base/macros.h"
+#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
#include "media/base/media_permission.h"
+#include "third_party/WebKit/public/platform/modules/permissions/permission.mojom.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
namespace content {
+// MediaPermission implementation using content PermissionService.
class CONTENT_EXPORT MediaPermissionDispatcher : public media::MediaPermission {
public:
- MediaPermissionDispatcher();
- ~MediaPermissionDispatcher() override;
-
- protected:
- // Register callbacks for PermissionService calls.
- uint32_t RegisterCallback(const PermissionStatusCB& permission_status_cb);
+ using ConnectToServiceCB = base::Callback<void(
+ mojo::InterfaceRequest<blink::mojom::PermissionService>)>;
- // Deliver the permission status |granted| to the callback identified by
- // |request_id|.
- void DeliverResult(uint32_t request_id, bool granted);
+ explicit MediaPermissionDispatcher(
+ const ConnectToServiceCB& connect_to_service_cb);
+ ~MediaPermissionDispatcher() override;
- base::ThreadChecker& thread_checker() { return thread_checker_; }
+ // media::MediaPermission implementation.
+ // Note: Can be called on any thread. The |permission_status_cb| will always
+ // be fired on the thread where these methods are called.
+ void HasPermission(Type type,
+ const GURL& security_origin,
+ const PermissionStatusCB& permission_status_cb) override;
+ void RequestPermission(
+ Type type,
+ const GURL& security_origin,
+ const PermissionStatusCB& permission_status_cb) override;
private:
// Map of request IDs and pending PermissionStatusCBs.
typedef std::map<uint32_t, PermissionStatusCB> RequestMap;
- base::ThreadChecker thread_checker_;
+ // Register PermissionStatusCBs. Returns |request_id| that can be used to make
+ // PermissionService calls.
+ uint32_t RegisterCallback(const PermissionStatusCB& permission_status_cb);
+
+ // Callback for |permission_service_| calls.
+ void OnPermissionStatus(uint32_t request_id,
+ blink::mojom::PermissionStatus status);
+ ConnectToServiceCB connect_to_service_cb_;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
uint32_t next_request_id_;
RequestMap requests_;
+ blink::mojom::PermissionServicePtr permission_service_;
+
+ // Used to safely post MediaPermission calls for execution on |task_runner_|.
+ base::WeakPtr<MediaPermissionDispatcher> weak_ptr_;
+
+ base::WeakPtrFactory<MediaPermissionDispatcher> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(MediaPermissionDispatcher);
};
diff --git a/chromium/content/renderer/media/media_permission_dispatcher_impl.cc b/chromium/content/renderer/media/media_permission_dispatcher_impl.cc
deleted file mode 100644
index a1daf8c3e82..00000000000
--- a/chromium/content/renderer/media/media_permission_dispatcher_impl.cc
+++ /dev/null
@@ -1,99 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media/media_permission_dispatcher_impl.h"
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/thread_task_runner_handle.h"
-#include "content/public/common/service_registry.h"
-#include "content/public/renderer/render_frame.h"
-#include "content/renderer/media/media_permission_dispatcher_proxy.h"
-#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
-#include "url/gurl.h"
-
-namespace {
-
-using Type = media::MediaPermission::Type;
-
-content::PermissionName MediaPermissionTypeToPermissionName(Type type) {
- switch (type) {
- case Type::PROTECTED_MEDIA_IDENTIFIER:
- return content::PERMISSION_NAME_PROTECTED_MEDIA_IDENTIFIER;
- case Type::AUDIO_CAPTURE:
- return content::PERMISSION_NAME_AUDIO_CAPTURE;
- case Type::VIDEO_CAPTURE:
- return content::PERMISSION_NAME_VIDEO_CAPTURE;
- }
- NOTREACHED();
- return content::PERMISSION_NAME_PROTECTED_MEDIA_IDENTIFIER;
-}
-
-} // namespace
-
-namespace content {
-
-MediaPermissionDispatcherImpl::MediaPermissionDispatcherImpl(
- RenderFrame* render_frame)
- : RenderFrameObserver(render_frame),
- task_runner_(base::ThreadTaskRunnerHandle::Get()),
- weak_ptr_factory_(this) {}
-
-MediaPermissionDispatcherImpl::~MediaPermissionDispatcherImpl() {
- DCHECK(thread_checker().CalledOnValidThread());
-}
-
-void MediaPermissionDispatcherImpl::HasPermission(
- Type type,
- const GURL& security_origin,
- const PermissionStatusCB& permission_status_cb) {
- DCHECK(thread_checker().CalledOnValidThread());
-
- if (!permission_service_.get()) {
- render_frame()->GetServiceRegistry()->ConnectToRemoteService(
- mojo::GetProxy(&permission_service_));
- }
-
- permission_service_->HasPermission(
- MediaPermissionTypeToPermissionName(type), security_origin.spec(),
- base::Bind(&MediaPermissionDispatcherImpl::OnPermissionStatus,
- weak_ptr_factory_.GetWeakPtr(),
- RegisterCallback(permission_status_cb)));
-}
-
-void MediaPermissionDispatcherImpl::RequestPermission(
- Type type,
- const GURL& security_origin,
- const PermissionStatusCB& permission_status_cb) {
- DCHECK(thread_checker().CalledOnValidThread());
-
- if (!permission_service_.get()) {
- render_frame()->GetServiceRegistry()->ConnectToRemoteService(
- mojo::GetProxy(&permission_service_));
- }
-
- permission_service_->RequestPermission(
- MediaPermissionTypeToPermissionName(type), security_origin.spec(),
- blink::WebUserGestureIndicator::isProcessingUserGesture(),
- base::Bind(&MediaPermissionDispatcherImpl::OnPermissionStatus,
- weak_ptr_factory_.GetWeakPtr(),
- RegisterCallback(permission_status_cb)));
-}
-
-scoped_ptr<media::MediaPermission> MediaPermissionDispatcherImpl::CreateProxy(
- scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner) {
- scoped_ptr<media::MediaPermission> media_permission_proxy(
- new MediaPermissionDispatcherProxy(task_runner_, caller_task_runner,
- weak_ptr_factory_.GetWeakPtr()));
- return media_permission_proxy;
-}
-
-void MediaPermissionDispatcherImpl::OnPermissionStatus(
- uint32_t request_id,
- PermissionStatus status) {
- DCHECK(thread_checker().CalledOnValidThread());
- DeliverResult(request_id, status == PERMISSION_STATUS_GRANTED);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/media_permission_dispatcher_impl.h b/chromium/content/renderer/media/media_permission_dispatcher_impl.h
deleted file mode 100644
index 8aebc89a09a..00000000000
--- a/chromium/content/renderer/media/media_permission_dispatcher_impl.h
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// MediaPermission implementation which dispatches queries/requests to Mojo
-// PermissionService. It relies on its base class MediaPermissionDispatcher to
-// manage pending callbacks. Non-UI threads could create
-// MediaPermissionDispatcherProxy by calling CreateProxy such that calls will be
-// executed on the UI thread which is where this object lives.
-
-#ifndef CONTENT_RENDERER_MEDIA_MEDIA_PERMISSION_DISPATCHER_IMPL_H_
-#define CONTENT_RENDERER_MEDIA_MEDIA_PERMISSION_DISPATCHER_IMPL_H_
-
-#include <stdint.h>
-
-#include <map>
-
-#include "base/macros.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_checker.h"
-#include "content/common/content_export.h"
-#include "content/common/permission_service.mojom.h"
-#include "content/public/renderer/render_frame_observer.h"
-#include "content/renderer/media/media_permission_dispatcher.h"
-#include "media/base/media_permission.h"
-
-namespace content {
-
-class CONTENT_EXPORT MediaPermissionDispatcherImpl
- : public MediaPermissionDispatcher,
- public RenderFrameObserver {
- public:
- explicit MediaPermissionDispatcherImpl(RenderFrame* render_frame);
- ~MediaPermissionDispatcherImpl() override;
-
- // media::MediaPermission implementation.
- void HasPermission(Type type,
- const GURL& security_origin,
- const PermissionStatusCB& permission_status_cb) override;
-
- // MediaStreamDevicePermissionContext doesn't support RequestPermission yet
- // and will always return CONTENT_SETTING_BLOCK.
- void RequestPermission(
- Type type,
- const GURL& security_origin,
- const PermissionStatusCB& permission_status_cb) override;
-
- // Create MediaPermissionDispatcherProxy object which will dispatch the
- // callback between the |caller_task_runner| and |task_runner_| in a thread
- // safe way. This can be called from non-UI thread.
- scoped_ptr<media::MediaPermission> CreateProxy(
- scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner);
-
- private:
- // Callback for |permission_service_| calls.
- void OnPermissionStatus(uint32_t request_id, PermissionStatus status);
-
- const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
- PermissionServicePtr permission_service_;
-
- base::WeakPtrFactory<MediaPermissionDispatcherImpl> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(MediaPermissionDispatcherImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_MEDIA_PERMISSION_DISPATCHER_IMPL_H_
diff --git a/chromium/content/renderer/media/media_permission_dispatcher_proxy.cc b/chromium/content/renderer/media/media_permission_dispatcher_proxy.cc
deleted file mode 100644
index e883ac953af..00000000000
--- a/chromium/content/renderer/media/media_permission_dispatcher_proxy.cc
+++ /dev/null
@@ -1,161 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media/media_permission_dispatcher_proxy.h"
-
-#include <stdint.h>
-
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/thread_task_runner_handle.h"
-#include "url/gurl.h"
-
-namespace content {
-
-class MediaPermissionDispatcherProxy::Core {
- public:
- Core(scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
- base::WeakPtr<MediaPermissionDispatcher> parent,
- base::WeakPtr<MediaPermissionDispatcher> media_permission_dispatcher);
- ~Core();
-
- void HasPermission(Type type,
- const GURL& security_origin,
- uint32_t request_id);
-
- void RequestPermission(Type type,
- const GURL& security_origin,
- uint32_t request_id);
-
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner() {
- return ui_task_runner_;
- }
-
- scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner() {
- return caller_task_runner_;
- }
-
- base::WeakPtr<MediaPermissionDispatcherProxy::Core> GetWeakPtr() {
- return weak_ptr_factory_.GetWeakPtr();
- }
-
- private:
- // Reports the result on the caller's thread.
- void ReportResult(uint32_t request_id, bool granted);
-
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
- scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner_;
-
- // |parent_| is the proxy which holds this Core.
- base::WeakPtr<MediaPermissionDispatcher> parent_;
-
- // |media_permission_| is the real implementation which calls
- // PermissionServices on the UI thread.
- base::WeakPtr<MediaPermissionDispatcher> media_permission_;
-
- base::WeakPtrFactory<MediaPermissionDispatcherProxy::Core> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(Core);
-};
-
-MediaPermissionDispatcherProxy::Core::Core(
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
- base::WeakPtr<MediaPermissionDispatcher> parent,
- base::WeakPtr<MediaPermissionDispatcher> media_permission)
- : ui_task_runner_(ui_task_runner),
- caller_task_runner_(caller_task_runner),
- parent_(parent),
- media_permission_(media_permission),
- weak_ptr_factory_(this) {}
-
-MediaPermissionDispatcherProxy::Core::~Core() {
- DCHECK(ui_task_runner_->BelongsToCurrentThread());
-}
-
-void MediaPermissionDispatcherProxy::Core::HasPermission(
- Type type,
- const GURL& security_origin,
- uint32_t request_id) {
- DCHECK(ui_task_runner_->BelongsToCurrentThread());
-
- if (media_permission_.get()) {
- media_permission_->HasPermission(
- type, security_origin,
- base::Bind(&MediaPermissionDispatcherProxy::Core::ReportResult,
- GetWeakPtr(), request_id));
- } else {
- ReportResult(request_id, false);
- }
-}
-
-void MediaPermissionDispatcherProxy::Core::RequestPermission(
- Type type,
- const GURL& security_origin,
- uint32_t request_id) {
- DCHECK(ui_task_runner_->BelongsToCurrentThread());
-
- if (media_permission_.get()) {
- media_permission_->RequestPermission(
- type, security_origin,
- base::Bind(&MediaPermissionDispatcherProxy::Core::ReportResult,
- GetWeakPtr(), request_id));
- } else {
- ReportResult(request_id, false);
- }
-}
-
-void MediaPermissionDispatcherProxy::Core::ReportResult(uint32_t request_id,
- bool result) {
- DCHECK(ui_task_runner_->BelongsToCurrentThread());
- caller_task_runner_->PostTask(
- FROM_HERE, base::Bind(&MediaPermissionDispatcherProxy::DeliverResult,
- parent_, request_id, result));
-}
-
-MediaPermissionDispatcherProxy::MediaPermissionDispatcherProxy(
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
- base::WeakPtr<MediaPermissionDispatcher> media_permission)
- : weak_ptr_factory_(this) {
- thread_checker().DetachFromThread();
- core_.reset(new Core(ui_task_runner, caller_task_runner,
- weak_ptr_factory_.GetWeakPtr(), media_permission));
-}
-
-MediaPermissionDispatcherProxy::~MediaPermissionDispatcherProxy() {
- DCHECK(core_->caller_task_runner()->BelongsToCurrentThread());
-
- auto ui_task_runner = core_->ui_task_runner();
- ui_task_runner->DeleteSoon(FROM_HERE, core_.release());
-}
-
-void MediaPermissionDispatcherProxy::HasPermission(
- Type type,
- const GURL& security_origin,
- const PermissionStatusCB& permission_status_cb) {
- DCHECK(core_->caller_task_runner()->BelongsToCurrentThread());
-
- core_->ui_task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&Core::HasPermission, core_->GetWeakPtr(), type,
- security_origin, RegisterCallback(permission_status_cb)));
-}
-
-void MediaPermissionDispatcherProxy::RequestPermission(
- Type type,
- const GURL& security_origin,
- const PermissionStatusCB& permission_status_cb) {
- DCHECK(core_->caller_task_runner()->BelongsToCurrentThread());
-
- core_->ui_task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&Core::RequestPermission, core_->GetWeakPtr(), type,
- security_origin, RegisterCallback(permission_status_cb)));
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/media_permission_dispatcher_proxy.h b/chromium/content/renderer/media/media_permission_dispatcher_proxy.h
deleted file mode 100644
index aa931e80bf5..00000000000
--- a/chromium/content/renderer/media/media_permission_dispatcher_proxy.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// A helper class to forward the calls to MediaPermissionDispatcherImpl on UI
-// thread and have the permission status callback on the caller's original
-// non-UI thread.
-
-#ifndef CONTENT_RENDERER_MEDIA_MEDIA_PERMISSION_PROXY_H_
-#define CONTENT_RENDERER_MEDIA_MEDIA_PERMISSION_PROXY_H_
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/single_thread_task_runner.h"
-#include "content/common/content_export.h"
-#include "content/renderer/media/media_permission_dispatcher.h"
-#include "media/base/media_permission.h"
-
-namespace content {
-
-class CONTENT_EXPORT MediaPermissionDispatcherProxy
- : public MediaPermissionDispatcher {
- public:
- // |ui_task_runner| must be the UI thread. It will be used to call into the
- // |media_permission| which is the MediaPermissionDispatcherImpl.
- MediaPermissionDispatcherProxy(
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner,
- scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner,
- base::WeakPtr<MediaPermissionDispatcher> media_permission);
-
- ~MediaPermissionDispatcherProxy() override;
-
- // MediaPermission implementation.
- void HasPermission(Type type,
- const GURL& security_origin,
- const PermissionStatusCB& permission_status_cb) override;
-
- void RequestPermission(
- Type type,
- const GURL& security_origin,
- const PermissionStatusCB& permission_status_cb) override;
-
- private:
- class Core;
-
- void ReportResult(bool result);
-
- scoped_ptr<Core> core_;
-
- base::WeakPtrFactory<MediaPermissionDispatcherProxy> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(MediaPermissionDispatcherProxy);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_MEDIA_PERMISSION_PROXY_H_
diff --git a/chromium/content/renderer/media/media_recorder_handler.cc b/chromium/content/renderer/media/media_recorder_handler.cc
index 2944013d3a5..aa416728d1a 100644
--- a/chromium/content/renderer/media/media_recorder_handler.cc
+++ b/chromium/content/renderer/media/media_recorder_handler.cc
@@ -22,8 +22,9 @@
#include "media/base/bind_to_current_loop.h"
#include "media/base/mime_util.h"
#include "media/base/video_frame.h"
-#include "media/capture/webm_muxer.h"
+#include "media/muxers/webm_muxer.h"
#include "third_party/WebKit/public/platform/WebMediaRecorderHandlerClient.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
#include "third_party/WebKit/public/platform/WebString.h"
using base::TimeDelta;
@@ -32,7 +33,9 @@ using base::TimeTicks;
namespace content {
MediaRecorderHandler::MediaRecorderHandler()
- : use_vp9_(false),
+ : video_bits_per_second_(0),
+ audio_bits_per_second_(0),
+ use_vp9_(false),
recording_(false),
client_(nullptr),
weak_factory_(this) {}
@@ -84,7 +87,9 @@ bool MediaRecorderHandler::initialize(
blink::WebMediaRecorderHandlerClient* client,
const blink::WebMediaStream& media_stream,
const blink::WebString& type,
- const blink::WebString& codecs) {
+ const blink::WebString& codecs,
+ int32_t audio_bits_per_second,
+ int32_t video_bits_per_second) {
DCHECK(main_render_thread_checker_.CalledOnValidThread());
// Save histogram data so we can see how much MediaStream Recorder is used.
// The histogram counts the number of calls to the JS API.
@@ -100,6 +105,8 @@ bool MediaRecorderHandler::initialize(
DCHECK(client);
client_ = client;
+ audio_bits_per_second_ = audio_bits_per_second;
+ video_bits_per_second_ = video_bits_per_second;
return true;
}
@@ -128,17 +135,22 @@ bool MediaRecorderHandler::start(int timeslice) {
return false;
}
- const bool use_audio_tracks =
- !audio_tracks.isEmpty() &&
- MediaStreamAudioTrack::GetTrack(audio_tracks[0]);
+ const bool use_video_tracks = !video_tracks.isEmpty() &&
+ video_tracks[0].isEnabled() &&
+ video_tracks[0].source().getReadyState() ==
+ blink::WebMediaStreamSource::ReadyStateLive;
+ const bool use_audio_tracks = !audio_tracks.isEmpty() &&
+ MediaStreamAudioTrack::From(audio_tracks[0]) &&
+ audio_tracks[0].isEnabled() &&
+ audio_tracks[0].source().getReadyState() ==
+ blink::WebMediaStreamSource::ReadyStateLive;
webm_muxer_.reset(new media::WebmMuxer(
- use_vp9_ ? media::kCodecVP9 : media::kCodecVP8,
- video_tracks.size() > 0, use_audio_tracks,
- base::Bind(&MediaRecorderHandler::WriteData,
- weak_factory_.GetWeakPtr())));
+ use_vp9_ ? media::kCodecVP9 : media::kCodecVP8, use_video_tracks,
+ use_audio_tracks, base::Bind(&MediaRecorderHandler::WriteData,
+ weak_factory_.GetWeakPtr())));
- if (!video_tracks.isEmpty()) {
+ if (use_video_tracks) {
// TODO(mcasas): The muxer API supports only one video track. Extend it to
// several video tracks, see http://crbug.com/528523.
LOG_IF(WARNING, video_tracks.size() > 1u)
@@ -152,8 +164,8 @@ bool MediaRecorderHandler::start(int timeslice) {
media::BindToCurrentLoop(base::Bind(
&MediaRecorderHandler::OnEncodedVideo, weak_factory_.GetWeakPtr()));
- video_recorders_.push_back(
- new VideoTrackRecorder(use_vp9_, video_track, on_encoded_video_cb));
+ video_recorders_.push_back(new VideoTrackRecorder(
+ use_vp9_, video_track, on_encoded_video_cb, video_bits_per_second_));
}
if (use_audio_tracks) {
@@ -170,8 +182,8 @@ bool MediaRecorderHandler::start(int timeslice) {
media::BindToCurrentLoop(base::Bind(
&MediaRecorderHandler::OnEncodedAudio, weak_factory_.GetWeakPtr()));
- audio_recorders_.push_back(
- new AudioTrackRecorder(audio_track, on_encoded_audio_cb));
+ audio_recorders_.push_back(new AudioTrackRecorder(
+ audio_track, on_encoded_audio_cb, audio_bits_per_second_));
}
recording_ = true;
@@ -195,6 +207,9 @@ void MediaRecorderHandler::pause() {
recording_ = false;
for (const auto& video_recorder : video_recorders_)
video_recorder->Pause();
+ for (const auto& audio_recorder : audio_recorders_)
+ audio_recorder->Pause();
+ webm_muxer_->Pause();
}
void MediaRecorderHandler::resume() {
@@ -203,11 +218,14 @@ void MediaRecorderHandler::resume() {
recording_ = true;
for (const auto& video_recorder : video_recorders_)
video_recorder->Resume();
+ for (const auto& audio_recorder : audio_recorders_)
+ audio_recorder->Resume();
+ webm_muxer_->Resume();
}
void MediaRecorderHandler::OnEncodedVideo(
const scoped_refptr<media::VideoFrame>& video_frame,
- scoped_ptr<std::string> encoded_data,
+ std::unique_ptr<std::string> encoded_data,
TimeTicks timestamp,
bool is_key_frame) {
DCHECK(main_render_thread_checker_.CalledOnValidThread());
@@ -217,9 +235,10 @@ void MediaRecorderHandler::OnEncodedVideo(
is_key_frame);
}
-void MediaRecorderHandler::OnEncodedAudio(const media::AudioParameters& params,
- scoped_ptr<std::string> encoded_data,
- base::TimeTicks timestamp) {
+void MediaRecorderHandler::OnEncodedAudio(
+ const media::AudioParameters& params,
+ std::unique_ptr<std::string> encoded_data,
+ base::TimeTicks timestamp) {
DCHECK(main_render_thread_checker_.CalledOnValidThread());
if (webm_muxer_)
webm_muxer_->OnEncodedAudio(params, std::move(encoded_data), timestamp);
@@ -227,7 +246,6 @@ void MediaRecorderHandler::OnEncodedAudio(const media::AudioParameters& params,
void MediaRecorderHandler::WriteData(base::StringPiece data) {
DCHECK(main_render_thread_checker_.CalledOnValidThread());
-
// Non-buffered mode does not need to check timestamps.
if (timeslice_.is_zero()) {
client_->writeData(data.data(), data.length(), true /* lastInSlice */);
diff --git a/chromium/content/renderer/media/media_recorder_handler.h b/chromium/content/renderer/media/media_recorder_handler.h
index cc50c84ee84..df4645a0198 100644
--- a/chromium/content/renderer/media/media_recorder_handler.h
+++ b/chromium/content/renderer/media/media_recorder_handler.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_RENDERER_MEDIA_MEDIA_RECORDER_HANDLER_H_
#define CONTENT_RENDERER_MEDIA_MEDIA_RECORDER_HANDLER_H_
+#include <memory>
+
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/scoped_vector.h"
@@ -53,7 +55,9 @@ class CONTENT_EXPORT MediaRecorderHandler final
bool initialize(blink::WebMediaRecorderHandlerClient* client,
const blink::WebMediaStream& media_stream,
const blink::WebString& type,
- const blink::WebString& codecs) override;
+ const blink::WebString& codecs,
+ int32_t audio_bits_per_second,
+ int32_t video_bits_per_second) override;
bool start() override;
bool start(int timeslice) override;
void stop() override;
@@ -64,11 +68,11 @@ class CONTENT_EXPORT MediaRecorderHandler final
friend class MediaRecorderHandlerTest;
void OnEncodedVideo(const scoped_refptr<media::VideoFrame>& video_frame,
- scoped_ptr<std::string> encoded_data,
+ std::unique_ptr<std::string> encoded_data,
base::TimeTicks timestamp,
bool is_key_frame);
void OnEncodedAudio(const media::AudioParameters& params,
- scoped_ptr<std::string> encoded_data,
+ std::unique_ptr<std::string> encoded_data,
base::TimeTicks timestamp);
void WriteData(base::StringPiece data);
@@ -81,6 +85,10 @@ class CONTENT_EXPORT MediaRecorderHandler final
// Bound to the main render thread.
base::ThreadChecker main_render_thread_checker_;
+ // Sanitized video and audio bitrate settings passed on initialize().
+ int32_t video_bits_per_second_;
+ int32_t audio_bits_per_second_;
+
// Force using VP9 for video encoding, otherwise VP8 will be used by default.
bool use_vp9_;
@@ -100,7 +108,7 @@ class CONTENT_EXPORT MediaRecorderHandler final
ScopedVector<AudioTrackRecorder> audio_recorders_;
// Worker class doing the actual Webm Muxing work.
- scoped_ptr<media::WebmMuxer> webm_muxer_;
+ std::unique_ptr<media::WebmMuxer> webm_muxer_;
base::WeakPtrFactory<MediaRecorderHandler> weak_factory_;
diff --git a/chromium/content/renderer/media/media_recorder_handler_unittest.cc b/chromium/content/renderer/media/media_recorder_handler_unittest.cc
index 6989ca68ade..5bc99aedc20 100644
--- a/chromium/content/renderer/media/media_recorder_handler_unittest.cc
+++ b/chromium/content/renderer/media/media_recorder_handler_unittest.cc
@@ -22,6 +22,7 @@
using ::testing::_;
using ::testing::AtLeast;
using ::testing::InSequence;
+using ::testing::Gt;
using ::testing::Lt;
using ::testing::Mock;
using ::testing::TestWithParam;
@@ -41,25 +42,24 @@ static const std::string kTestAudioTrackId = "audio_track_id";
static const int kTestAudioChannels = 2;
static const int kTestAudioBitsPerSample = 16;
static const int kTestAudioSampleRate = 48000;
-static const int kTestAudioBufferDurationMS = 60;
+static const int kTestAudioBufferDurationMs = 10;
+// Opus works with 60ms buffers, so 6 MediaStreamAudioTrack Buffers are needed
+// to encode one output buffer.
+static const int kRatioOpusToTestAudioBuffers = 6;
struct MediaRecorderTestParams {
const bool has_video;
const bool has_audio;
const char* const mime_type;
const char* const codecs;
- const size_t first_encoded_video_frame_size;
- const size_t second_encoded_video_frame_size;
- const size_t first_encoded_audio_frame_size;
- const size_t second_encoded_audio_frame_size;
};
// Array of valid combinations of video/audio/codecs and expected collected
// encoded sizes to use for parameterizing MediaRecorderHandlerTest.
static const MediaRecorderTestParams kMediaRecorderTestParams[] = {
- {true, false, "video/webm", "vp8", 52, 32, 0, 0},
- {true, false, "video/webm", "vp9", 33, 18, 0, 0},
- {false, true, "video/webm", "vp8", 0, 0, 990, 706}};
+ {true, false, "video/webm", "vp8"},
+ {true, false, "video/webm", "vp9"},
+ {false, true, "video/webm", "vp8"}};
class MediaRecorderHandlerTest : public TestWithParam<MediaRecorderTestParams>,
public blink::WebMediaRecorderHandlerClient {
@@ -110,10 +110,10 @@ class MediaRecorderHandlerTest : public TestWithParam<MediaRecorderTestParams>,
registry_.AddAudioTrack(kTestAudioTrackId);
}
- scoped_ptr<media::AudioBus> NextAudioBus() {
- scoped_ptr<media::AudioBus> bus(media::AudioBus::Create(
+ std::unique_ptr<media::AudioBus> NextAudioBus() {
+ std::unique_ptr<media::AudioBus> bus(media::AudioBus::Create(
kTestAudioChannels,
- kTestAudioSampleRate * kTestAudioBufferDurationMS / 1000));
+ kTestAudioSampleRate * kTestAudioBufferDurationMs / 1000));
audio_source_.OnMoreData(bus.get(), 0, 0);
return bus;
}
@@ -125,7 +125,7 @@ class MediaRecorderHandlerTest : public TestWithParam<MediaRecorderTestParams>,
MockMediaStreamRegistry registry_;
// The Class under test. Needs to be scoped_ptr to force its destruction.
- scoped_ptr<MediaRecorderHandler> media_recorder_handler_;
+ std::unique_ptr<MediaRecorderHandler> media_recorder_handler_;
// For generating test AudioBuses
media::SineWaveAudioSource audio_source_;
@@ -181,10 +181,8 @@ TEST_P(MediaRecorderHandlerTest, InitializeStartStop) {
AddTracks();
const WebString mime_type(base::UTF8ToUTF16(GetParam().mime_type));
const WebString codecs(base::UTF8ToUTF16(GetParam().codecs));
- EXPECT_TRUE(media_recorder_handler_->initialize(this,
- registry_.test_stream(),
- mime_type,
- codecs));
+ EXPECT_TRUE(media_recorder_handler_->initialize(this, registry_.test_stream(),
+ mime_type, codecs, 0, 0));
EXPECT_FALSE(recording());
EXPECT_FALSE(hasVideoRecorders());
EXPECT_FALSE(hasAudioRecorders());
@@ -216,38 +214,38 @@ TEST_P(MediaRecorderHandlerTest, EncodeVideoFrames) {
const WebString mime_type(base::UTF8ToUTF16(GetParam().mime_type));
const WebString codecs(base::UTF8ToUTF16(GetParam().codecs));
EXPECT_TRUE(media_recorder_handler_->initialize(this, registry_.test_stream(),
- mime_type, codecs));
+ mime_type, codecs, 0, 0));
EXPECT_TRUE(media_recorder_handler_->start());
InSequence s;
const scoped_refptr<media::VideoFrame> video_frame =
media::VideoFrame::CreateBlackFrame(gfx::Size(160, 80));
+ const size_t kEncodedSizeThreshold = 16;
{
base::RunLoop run_loop;
base::Closure quit_closure = run_loop.QuitClosure();
// writeData() is pinged a number of times as the WebM header is written;
// the last time it is called it has the encoded data.
- const size_t encoded_data_size = GetParam().first_encoded_video_frame_size;
- EXPECT_CALL(*this, writeData(_, Lt(encoded_data_size), _))
+ EXPECT_CALL(*this, writeData(_, Lt(kEncodedSizeThreshold), _))
.Times(AtLeast(1));
- EXPECT_CALL(*this, writeData(_, encoded_data_size, _))
+ EXPECT_CALL(*this, writeData(_, Gt(kEncodedSizeThreshold), _))
.Times(1)
.WillOnce(RunClosure(quit_closure));
OnVideoFrameForTesting(video_frame);
run_loop.Run();
}
+ Mock::VerifyAndClearExpectations(this);
{
base::RunLoop run_loop;
base::Closure quit_closure = run_loop.QuitClosure();
// The second time around writeData() is called a number of times to write
// the WebM frame header, and then is pinged with the encoded data.
- const size_t encoded_data_size = GetParam().second_encoded_video_frame_size;
- EXPECT_CALL(*this, writeData(_, Lt(encoded_data_size), _))
+ EXPECT_CALL(*this, writeData(_, Lt(kEncodedSizeThreshold), _))
.Times(AtLeast(1));
- EXPECT_CALL(*this, writeData(_, encoded_data_size, _))
+ EXPECT_CALL(*this, writeData(_, Gt(kEncodedSizeThreshold), _))
.Times(1)
.WillOnce(RunClosure(quit_closure));
@@ -275,49 +273,51 @@ TEST_P(MediaRecorderHandlerTest, EncodeAudioFrames) {
AddTracks();
const WebString mime_type(base::UTF8ToUTF16("audio/webm"));
- EXPECT_TRUE(media_recorder_handler_->initialize(this, registry_.test_stream(),
- mime_type, WebString()));
+ EXPECT_TRUE(media_recorder_handler_->initialize(
+ this, registry_.test_stream(), mime_type, WebString(), 0, 0));
EXPECT_TRUE(media_recorder_handler_->start());
InSequence s;
- const scoped_ptr<media::AudioBus> audio_bus1 = NextAudioBus();
- const scoped_ptr<media::AudioBus> audio_bus2 = NextAudioBus();
+ const std::unique_ptr<media::AudioBus> audio_bus1 = NextAudioBus();
+ const std::unique_ptr<media::AudioBus> audio_bus2 = NextAudioBus();
media::AudioParameters params(
media::AudioParameters::AUDIO_PCM_LINEAR, media::CHANNEL_LAYOUT_STEREO,
kTestAudioSampleRate, kTestAudioBitsPerSample,
- kTestAudioSampleRate * kTestAudioBufferDurationMS / 1000);
+ kTestAudioSampleRate * kTestAudioBufferDurationMs / 1000);
SetAudioFormatForTesting(params);
+ const size_t kEncodedSizeThreshold = 24;
{
base::RunLoop run_loop;
base::Closure quit_closure = run_loop.QuitClosure();
// writeData() is pinged a number of times as the WebM header is written;
// the last time it is called it has the encoded data.
- const size_t kEncodedDataSize = GetParam().first_encoded_audio_frame_size;
- EXPECT_CALL(*this, writeData(_, Lt(kEncodedDataSize), _)).Times(AtLeast(1));
- EXPECT_CALL(*this, writeData(_, kEncodedDataSize, _))
+ EXPECT_CALL(*this, writeData(_, Lt(kEncodedSizeThreshold), _))
+ .Times(AtLeast(1));
+ EXPECT_CALL(*this, writeData(_, Gt(kEncodedSizeThreshold), _))
.Times(1)
.WillOnce(RunClosure(quit_closure));
- OnAudioBusForTesting(*audio_bus1);
+ for (int i = 0; i < kRatioOpusToTestAudioBuffers; ++i)
+ OnAudioBusForTesting(*audio_bus1);
run_loop.Run();
}
+ Mock::VerifyAndClearExpectations(this);
{
base::RunLoop run_loop;
base::Closure quit_closure = run_loop.QuitClosure();
// The second time around writeData() is called a number of times to write
// the WebM frame header, and then is pinged with the encoded data.
- const size_t kSecondEncodedDataSize =
- GetParam().second_encoded_audio_frame_size;
- EXPECT_CALL(*this, writeData(_, Lt(kSecondEncodedDataSize), _))
+ EXPECT_CALL(*this, writeData(_, Lt(kEncodedSizeThreshold), _))
.Times(AtLeast(1));
- EXPECT_CALL(*this, writeData(_, kSecondEncodedDataSize, _))
+ EXPECT_CALL(*this, writeData(_, Gt(kEncodedSizeThreshold), _))
.Times(1)
.WillOnce(RunClosure(quit_closure));
- OnAudioBusForTesting(*audio_bus2);
+ for (int i = 0; i < kRatioOpusToTestAudioBuffers; ++i)
+ OnAudioBusForTesting(*audio_bus2);
run_loop.Run();
}
diff --git a/chromium/content/renderer/media/media_stream.cc b/chromium/content/renderer/media/media_stream.cc
index 27e61b914ed..d95de283a4c 100644
--- a/chromium/content/renderer/media/media_stream.cc
+++ b/chromium/content/renderer/media/media_stream.cc
@@ -14,7 +14,7 @@ namespace content {
// static
MediaStream* MediaStream::GetMediaStream(
const blink::WebMediaStream& stream) {
- return static_cast<MediaStream*>(stream.extraData());
+ return static_cast<MediaStream*>(stream.getExtraData());
}
MediaStream::MediaStream() {
diff --git a/chromium/content/renderer/media/media_stream_audio_level_calculator.cc b/chromium/content/renderer/media/media_stream_audio_level_calculator.cc
index ad76a43dd2f..936dcf25c1f 100644
--- a/chromium/content/renderer/media/media_stream_audio_level_calculator.cc
+++ b/chromium/content/renderer/media/media_stream_audio_level_calculator.cc
@@ -5,6 +5,7 @@
#include "content/renderer/media/media_stream_audio_level_calculator.h"
#include <cmath>
+#include <limits>
#include "base/logging.h"
#include "base/stl_util.h"
@@ -28,23 +29,36 @@ float MaxAmplitude(const float* audio_data, int length) {
} // namespace
-MediaStreamAudioLevelCalculator::MediaStreamAudioLevelCalculator()
- : counter_(0),
- max_amplitude_(0.0f),
- level_(0.0f) {
+MediaStreamAudioLevelCalculator::Level::Level() : level_(0.0f) {}
+
+MediaStreamAudioLevelCalculator::Level::~Level() {}
+
+float MediaStreamAudioLevelCalculator::Level::GetCurrent() const {
+ base::AutoLock auto_lock(lock_);
+ return level_;
+}
+
+void MediaStreamAudioLevelCalculator::Level::Set(float level) {
+ base::AutoLock auto_lock(lock_);
+ level_ = level;
}
+MediaStreamAudioLevelCalculator::MediaStreamAudioLevelCalculator()
+ : counter_(0), max_amplitude_(0.0f), level_(new Level()) {}
+
MediaStreamAudioLevelCalculator::~MediaStreamAudioLevelCalculator() {
+ level_->Set(0.0f);
}
-float MediaStreamAudioLevelCalculator::Calculate(
- const media::AudioBus& audio_bus) {
- DCHECK(thread_checker_.CalledOnValidThread());
+void MediaStreamAudioLevelCalculator::Calculate(
+ const media::AudioBus& audio_bus,
+ bool assume_nonzero_energy) {
// |level_| is updated every 10 callbacks. For the case where callback comes
// every 10ms, |level_| will be updated approximately every 100ms.
static const int kUpdateFrequency = 10;
- float max = 0.0f;
+ float max =
+ assume_nonzero_energy ? 1.0f / std::numeric_limits<int16_t>::max() : 0.0f;
for (int i = 0; i < audio_bus.channels(); ++i) {
const float max_this_channel =
MaxAmplitude(audio_bus.channel(i), audio_bus.frames());
@@ -54,7 +68,8 @@ float MediaStreamAudioLevelCalculator::Calculate(
max_amplitude_ = std::max(max_amplitude_, max);
if (counter_++ == kUpdateFrequency) {
- level_ = max_amplitude_;
+ // Clip the exposed signal level to make sure it is in the range [0.0,1.0].
+ level_->Set(std::min(1.0f, max_amplitude_));
// Decay the absolute maximum amplitude by 1/4.
max_amplitude_ /= 4.0f;
@@ -62,8 +77,6 @@ float MediaStreamAudioLevelCalculator::Calculate(
// Reset the counter.
counter_ = 0;
}
-
- return level_;
}
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_audio_level_calculator.h b/chromium/content/renderer/media/media_stream_audio_level_calculator.h
index e7d25cc5d54..792e65c39ba 100644
--- a/chromium/content/renderer/media/media_stream_audio_level_calculator.h
+++ b/chromium/content/renderer/media/media_stream_audio_level_calculator.h
@@ -5,7 +5,9 @@
#ifndef CONTENT_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_LEVEL_CALCULATOR_H_
#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_LEVEL_CALCULATOR_H_
-#include "base/threading/thread_checker.h"
+#include "base/memory/ref_counted.h"
+#include "base/synchronization/lock.h"
+#include "content/common/content_export.h"
namespace media {
class AudioBus;
@@ -13,30 +15,49 @@ class AudioBus;
namespace content {
-// This class is used by the WebRtcLocalAudioTrack to calculate the level of
-// the audio signal. And the audio level will be eventually used by the volume
+// This class is used by the WebRtcAudioCapturer to calculate the level of the
+// audio signal. And the audio level will be eventually used by the volume
// animation UI.
+//
// The algorithm used by this class is the same as how it is done in
// third_party/webrtc/voice_engine/level_indicator.cc.
-class MediaStreamAudioLevelCalculator {
+class CONTENT_EXPORT MediaStreamAudioLevelCalculator {
public:
+ // Provides thread-safe access to the current signal level. This object is
+ // intended to be passed to modules running on other threads that poll for the
+ // current signal level.
+ class CONTENT_EXPORT Level : public base::RefCountedThreadSafe<Level> {
+ public:
+ float GetCurrent() const;
+
+ private:
+ friend class MediaStreamAudioLevelCalculator;
+ friend class base::RefCountedThreadSafe<Level>;
+
+ Level();
+ ~Level();
+
+ void Set(float level);
+
+ mutable base::Lock lock_;
+ float level_;
+ };
+
MediaStreamAudioLevelCalculator();
~MediaStreamAudioLevelCalculator();
- // Calculates the signal level of the audio data, returning the absolute value
- // of the amplitude of the signal.
- float Calculate(const media::AudioBus& audio_bus);
+ const scoped_refptr<Level>& level() const { return level_; }
- private:
- // Used to DCHECK that the constructor and Calculate() are always called on
- // the same audio thread. Note that the destructor will be called on a
- // different thread, which can be either the main render thread or a new
- // audio thread where WebRtcLocalAudioTrack::OnSetFormat() is called.
- base::ThreadChecker thread_checker_;
+ // Scans the audio signal in |audio_bus| and computes a new signal level
+ // exposed by Level. If |assume_nonzero_energy| is true, then a completely
+ // zero'ed-out |audio_bus| will be accounted for as having a very faint,
+ // non-zero level.
+ void Calculate(const media::AudioBus& audio_bus, bool assume_nonzero_energy);
+ private:
int counter_;
float max_amplitude_;
- float level_;
+ const scoped_refptr<Level> level_;
};
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_audio_processor.cc b/chromium/content/renderer/media/media_stream_audio_processor.cc
index 79988e22e84..23039de63c5 100644
--- a/chromium/content/renderer/media/media_stream_audio_processor.cc
+++ b/chromium/content/renderer/media/media_stream_audio_processor.cc
@@ -16,14 +16,13 @@
#include "build/build_config.h"
#include "content/public/common/content_switches.h"
#include "content/renderer/media/media_stream_audio_processor_options.h"
-#include "content/renderer/media/rtc_media_constraints.h"
#include "content/renderer/media/webrtc_audio_device_impl.h"
#include "media/audio/audio_parameters.h"
#include "media/base/audio_converter.h"
#include "media/base/audio_fifo.h"
#include "media/base/channel_layout.h"
#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h"
+#include "third_party/webrtc/api/mediaconstraintsinterface.h"
#include "third_party/webrtc/modules/audio_processing/typing_detection.h"
namespace content {
@@ -101,11 +100,6 @@ void RecordProcessingState(AudioTrackProcessingStates state) {
state, AUDIO_PROCESSING_MAX);
}
-bool IsDelayAgnosticAecEnabled() {
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- return !command_line->HasSwitch(switches::kDisableDelayAgnosticAec);
-}
-
// Checks if the default minimum starting volume value for the AGC is overridden
// on the command line.
bool GetStartupMinVolumeForAgc(int* startup_min_volume) {
@@ -117,6 +111,13 @@ bool GetStartupMinVolumeForAgc(int* startup_min_volume) {
base::StringToInt(min_volume_str, startup_min_volume);
}
+// Checks if the AEC's refined adaptive filter tuning was enabled on the command
+// line.
+bool UseAecRefinedAdaptiveFilter() {
+ return base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kAecRefinedAdaptiveFilter);
+}
+
} // namespace
// Wraps AudioBus to provide access to the array of channel pointers, since this
@@ -150,8 +151,8 @@ class MediaStreamAudioBus {
private:
base::ThreadChecker thread_checker_;
- scoped_ptr<media::AudioBus> bus_;
- scoped_ptr<float*[]> channel_ptrs_;
+ std::unique_ptr<media::AudioBus> bus_;
+ std::unique_ptr<float* []> channel_ptrs_;
};
// Wraps AudioFifo to provide a cleaner interface to MediaStreamAudioProcessor.
@@ -255,9 +256,9 @@ class MediaStreamAudioFifo {
const int source_channels_; // For a DCHECK.
const int source_frames_; // For a DCHECK.
const int sample_rate_;
- scoped_ptr<media::AudioBus> audio_source_intermediate_;
- scoped_ptr<MediaStreamAudioBus> destination_;
- scoped_ptr<media::AudioFifo> fifo_;
+ std::unique_ptr<media::AudioBus> audio_source_intermediate_;
+ std::unique_ptr<MediaStreamAudioBus> destination_;
+ std::unique_ptr<media::AudioFifo> fifo_;
// When using |fifo_|, this is the audio delay of the first sample to be
// consumed next from the FIFO. When not using |fifo_|, this is the audio
@@ -432,8 +433,13 @@ void MediaStreamAudioProcessor::OnPlayoutData(media::AudioBus* audio_bus,
int sample_rate,
int audio_delay_milliseconds) {
DCHECK(render_thread_checker_.CalledOnValidThread());
- DCHECK(audio_processing_->echo_control_mobile()->is_enabled() ^
- audio_processing_->echo_cancellation()->is_enabled());
+#if defined(OS_ANDROID)
+ DCHECK(audio_processing_->echo_control_mobile()->is_enabled());
+ DCHECK(!audio_processing_->echo_cancellation()->is_enabled());
+#else
+ DCHECK(!audio_processing_->echo_control_mobile()->is_enabled());
+ DCHECK(audio_processing_->echo_cancellation()->is_enabled());
+#endif
TRACE_EVENT0("audio", "MediaStreamAudioProcessor::OnPlayoutData");
DCHECK_LT(audio_delay_milliseconds,
@@ -481,38 +487,27 @@ void MediaStreamAudioProcessor::InitializeAudioProcessingModule(
// Audio mirroring can be enabled even though audio processing is otherwise
// disabled.
- audio_mirroring_ = audio_constraints.GetProperty(
- MediaAudioConstraints::kGoogAudioMirroring);
+ audio_mirroring_ = audio_constraints.GetGoogAudioMirroring();
-#if defined(OS_IOS)
- // On iOS, VPIO provides built-in AGC and AEC.
- const bool echo_cancellation = false;
- const bool goog_agc = false;
-#else
const bool echo_cancellation =
audio_constraints.GetEchoCancellationProperty();
- const bool goog_agc = audio_constraints.GetProperty(
- MediaAudioConstraints::kGoogAutoGainControl);
-#endif
+ const bool goog_agc = audio_constraints.GetGoogAutoGainControl();
-#if defined(OS_IOS) || defined(OS_ANDROID)
+#if defined(OS_ANDROID)
const bool goog_experimental_aec = false;
const bool goog_typing_detection = false;
#else
- const bool goog_experimental_aec = audio_constraints.GetProperty(
- MediaAudioConstraints::kGoogExperimentalEchoCancellation);
- const bool goog_typing_detection = audio_constraints.GetProperty(
- MediaAudioConstraints::kGoogTypingNoiseDetection);
+ const bool goog_experimental_aec =
+ audio_constraints.GetGoogExperimentalEchoCancellation();
+ const bool goog_typing_detection =
+ audio_constraints.GetGoogTypingNoiseDetection();
#endif
- const bool goog_ns = audio_constraints.GetProperty(
- MediaAudioConstraints::kGoogNoiseSuppression);
- const bool goog_experimental_ns = audio_constraints.GetProperty(
- MediaAudioConstraints::kGoogExperimentalNoiseSuppression);
- const bool goog_beamforming = audio_constraints.GetProperty(
- MediaAudioConstraints::kGoogBeamforming);
- const bool goog_high_pass_filter = audio_constraints.GetProperty(
- MediaAudioConstraints::kGoogHighpassFilter);
+ const bool goog_ns = audio_constraints.GetGoogNoiseSuppression();
+ const bool goog_experimental_ns =
+ audio_constraints.GetGoogExperimentalNoiseSuppression();
+ const bool goog_beamforming = audio_constraints.GetGoogBeamforming();
+ const bool goog_high_pass_filter = audio_constraints.GetGoogHighpassFilter();
// Return immediately if no goog constraint is enabled.
if (!echo_cancellation && !goog_experimental_aec && !goog_ns &&
!goog_high_pass_filter && !goog_typing_detection &&
@@ -527,8 +522,11 @@ void MediaStreamAudioProcessor::InitializeAudioProcessingModule(
new webrtc::ExtendedFilter(goog_experimental_aec));
config.Set<webrtc::ExperimentalNs>(
new webrtc::ExperimentalNs(goog_experimental_ns));
- if (IsDelayAgnosticAecEnabled())
- config.Set<webrtc::DelayAgnostic>(new webrtc::DelayAgnostic(true));
+ config.Set<webrtc::DelayAgnostic>(new webrtc::DelayAgnostic(true));
+ if (UseAecRefinedAdaptiveFilter()) {
+ config.Set<webrtc::RefinedAdaptiveFilter>(
+ new webrtc::RefinedAdaptiveFilter(true));
+ }
if (goog_beamforming) {
const auto& geometry =
GetArrayGeometryPreferringConstraints(audio_constraints, input_params);
@@ -539,8 +537,7 @@ void MediaStreamAudioProcessor::InitializeAudioProcessingModule(
}
// If the experimental AGC is enabled, check for overridden config params.
- if (audio_constraints.GetProperty(
- MediaAudioConstraints::kGoogExperimentalAutoGainControl)) {
+ if (audio_constraints.GetGoogExperimentalAutoGainControl()) {
int startup_min_volume = 0;
if (GetStartupMinVolumeForAgc(&startup_min_volume)) {
config.Set<webrtc::ExperimentalAgc>(
diff --git a/chromium/content/renderer/media/media_stream_audio_processor.h b/chromium/content/renderer/media/media_stream_audio_processor.h
index dabc42f291c..66290159ce2 100644
--- a/chromium/content/renderer/media/media_stream_audio_processor.h
+++ b/chromium/content/renderer/media/media_stream_audio_processor.h
@@ -18,7 +18,7 @@
#include "content/renderer/media/audio_repetition_detector.h"
#include "content/renderer/media/webrtc_audio_device_impl.h"
#include "media/base/audio_converter.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
#include "third_party/webrtc/modules/audio_processing/include/audio_processing.h"
namespace blink {
@@ -157,18 +157,18 @@ class CONTENT_EXPORT MediaStreamAudioProcessor :
base::subtle::Atomic32 render_delay_ms_;
// Module to detect and report (to UMA) bit exact audio repetition.
- scoped_ptr<AudioRepetitionDetector> audio_repetition_detector_;
+ std::unique_ptr<AudioRepetitionDetector> audio_repetition_detector_;
// Module to handle processing and format conversion.
- scoped_ptr<webrtc::AudioProcessing> audio_processing_;
+ std::unique_ptr<webrtc::AudioProcessing> audio_processing_;
// FIFO to provide 10 ms capture chunks.
- scoped_ptr<MediaStreamAudioFifo> capture_fifo_;
+ std::unique_ptr<MediaStreamAudioFifo> capture_fifo_;
// Receives processing output.
- scoped_ptr<MediaStreamAudioBus> output_bus_;
+ std::unique_ptr<MediaStreamAudioBus> output_bus_;
// FIFO to provide 10 ms render chunks when the AEC is enabled.
- scoped_ptr<MediaStreamAudioFifo> render_fifo_;
+ std::unique_ptr<MediaStreamAudioFifo> render_fifo_;
// These are mutated on the main render thread in OnCaptureFormatChanged().
// The caller guarantees this does not run concurrently with accesses on the
@@ -192,7 +192,7 @@ class CONTENT_EXPORT MediaStreamAudioProcessor :
// Flag to enable stereo channel mirroring.
bool audio_mirroring_;
- scoped_ptr<webrtc::TypingDetection> typing_detector_;
+ std::unique_ptr<webrtc::TypingDetection> typing_detector_;
// This flag is used to show the result of typing detection.
// It can be accessed by the capture audio thread and by the libjingle thread
// which calls GetStats().
@@ -206,7 +206,7 @@ class CONTENT_EXPORT MediaStreamAudioProcessor :
// Object for logging echo information when the AEC is enabled. Accessible by
// the libjingle thread through GetStats().
- scoped_ptr<EchoInformation> echo_information_;
+ std::unique_ptr<EchoInformation> echo_information_;
DISALLOW_COPY_AND_ASSIGN(MediaStreamAudioProcessor);
};
diff --git a/chromium/content/renderer/media/media_stream_audio_processor_options.cc b/chromium/content/renderer/media/media_stream_audio_processor_options.cc
index 52ed1d7ee7b..ac8c9c23a40 100644
--- a/chromium/content/renderer/media/media_stream_audio_processor_options.cc
+++ b/chromium/content/renderer/media/media_stream_audio_processor_options.cc
@@ -11,7 +11,6 @@
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/metrics/field_trial.h"
#include "base/metrics/histogram.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
@@ -21,7 +20,6 @@
#include "content/common/media/media_stream_options.h"
#include "content/renderer/media/media_stream_constraints_util.h"
#include "content/renderer/media/media_stream_source.h"
-#include "content/renderer/media/rtc_media_constraints.h"
#include "media/audio/audio_parameters.h"
#include "third_party/webrtc/modules/audio_processing/include/audio_processing.h"
#include "third_party/webrtc/modules/audio_processing/typing_detection.h"
@@ -58,7 +56,7 @@ struct {
} const kDefaultAudioConstraints[] = {
{ MediaAudioConstraints::kEchoCancellation, true },
{ MediaAudioConstraints::kGoogEchoCancellation, true },
-#if defined(OS_ANDROID) || defined(OS_IOS)
+#if defined(OS_ANDROID)
{ MediaAudioConstraints::kGoogExperimentalEchoCancellation, false },
#else
// Enable the extended filter mode AEC on all non-mobile platforms.
@@ -119,24 +117,50 @@ std::vector<webrtc::Point> WebrtcPointsFromMediaPoints(
return webrtc_points;
}
+// Scan the basic and advanced constraints until a value is found.
+// If nothing is found, the default is returned.
+// Argument 2 is a pointer to class data member.
+bool ScanConstraintsForBoolean(
+ const blink::WebMediaConstraints& constraints,
+ blink::BooleanConstraint blink::WebMediaTrackConstraintSet::*picker,
+ bool the_default) {
+ const auto& the_field = constraints.basic().*picker;
+ if (the_field.hasExact()) {
+ return the_field.exact();
+ }
+ for (const auto& advanced_constraint : constraints.advanced()) {
+ const auto& the_field = advanced_constraint.*picker;
+ if (the_field.hasExact()) {
+ return the_field.exact();
+ }
+ }
+ return the_default;
+}
+
+void SetIfNotSet(rtc::Optional<bool>* field, bool value) {
+ if (!*field) {
+ *field = rtc::Optional<bool>(value);
+ }
+}
+
} // namespace
// TODO(xians): Remove this method after the APM in WebRtc is deprecated.
void MediaAudioConstraints::ApplyFixedAudioConstraints(
- RTCMediaConstraints* constraints) {
- for (size_t i = 0; i < arraysize(kDefaultAudioConstraints); ++i) {
- bool already_set_value;
- if (!webrtc::FindConstraint(constraints, kDefaultAudioConstraints[i].key,
- &already_set_value, NULL)) {
- const std::string value = kDefaultAudioConstraints[i].value ?
- webrtc::MediaConstraintsInterface::kValueTrue :
- webrtc::MediaConstraintsInterface::kValueFalse;
- constraints->AddOptional(kDefaultAudioConstraints[i].key, value, false);
- } else {
- DVLOG(1) << "Constraint " << kDefaultAudioConstraints[i].key
- << " already set to " << already_set_value;
- }
- }
+ cricket::AudioOptions* options) {
+ SetIfNotSet(&options->echo_cancellation, true);
+#if defined(OS_ANDROID)
+ SetIfNotSet(&options->extended_filter_aec, false);
+#else
+ // Enable the extended filter mode AEC on all non-mobile platforms.
+ SetIfNotSet(&options->extended_filter_aec, true);
+#endif
+ SetIfNotSet(&options->auto_gain_control, true);
+ SetIfNotSet(&options->experimental_agc, true);
+ SetIfNotSet(&options->noise_suppression, true);
+ SetIfNotSet(&options->highpass_filter, true);
+ SetIfNotSet(&options->typing_detection, true);
+ SetIfNotSet(&options->experimental_ns, true);
}
MediaAudioConstraints::MediaAudioConstraints(
@@ -148,35 +172,18 @@ MediaAudioConstraints::MediaAudioConstraints(
// - gUM has a specific kMediaStreamSource, which is used by tab capture
// and screen capture.
// - |kEchoCancellation| is explicitly set to false.
- std::string value_str;
- bool value_bool = false;
- if ((GetConstraintValueAsString(constraints, kMediaStreamSource,
- &value_str)) ||
- (GetConstraintValueAsBoolean(constraints_, kEchoCancellation,
- &value_bool) && !value_bool)) {
+ bool echo_constraint;
+ if (!constraints.basic().mediaStreamSource.isEmpty() ||
+ (GetConstraintValueAsBoolean(
+ constraints, &blink::WebMediaTrackConstraintSet::echoCancellation,
+ &echo_constraint) &&
+ echo_constraint == false)) {
default_audio_processing_constraint_value_ = false;
}
}
MediaAudioConstraints::~MediaAudioConstraints() {}
-bool MediaAudioConstraints::GetProperty(const std::string& key) const {
- // Return the value if the constraint is specified in |constraints|,
- // otherwise return the default value.
- bool value = false;
- if (!GetConstraintValueAsBoolean(constraints_, key, &value))
- value = GetDefaultValueForConstraint(constraints_, key);
-
- return value;
-}
-
-std::string MediaAudioConstraints::GetPropertyAsString(
- const std::string& key) const {
- std::string value;
- GetConstraintValueAsString(constraints_, key, &value);
- return value;
-}
-
bool MediaAudioConstraints::GetEchoCancellationProperty() const {
// If platform echo canceller is enabled, disable the software AEC.
if (effects_ & media::AudioParameters::ECHO_CANCELLER)
@@ -184,44 +191,38 @@ bool MediaAudioConstraints::GetEchoCancellationProperty() const {
// If |kEchoCancellation| is specified in the constraints, it will
// override the value of |kGoogEchoCancellation|.
- bool value = false;
- if (GetConstraintValueAsBoolean(constraints_, kEchoCancellation, &value))
- return value;
-
- return GetProperty(kGoogEchoCancellation);
+ const blink::WebMediaTrackConstraintSet& basic = constraints_.basic();
+ if (basic.echoCancellation.hasExact()) {
+ return basic.echoCancellation.exact();
+ }
+ for (const auto& advanced_constraint : constraints_.advanced()) {
+ if (advanced_constraint.echoCancellation.hasExact()) {
+ return advanced_constraint.echoCancellation.exact();
+ }
+ }
+ return ScanConstraintsForBoolean(
+ constraints_, &blink::WebMediaTrackConstraintSet::googEchoCancellation,
+ GetDefaultValueForConstraint(kGoogEchoCancellation));
}
bool MediaAudioConstraints::IsValid() const {
- blink::WebVector<blink::WebMediaConstraint> mandatory;
- constraints_.getMandatoryConstraints(mandatory);
- for (size_t i = 0; i < mandatory.size(); ++i) {
- const std::string key = mandatory[i].m_name.utf8();
- if (key == kMediaStreamSource || key == kMediaStreamSourceId ||
- key == MediaStreamSource::kSourceId) {
- // Ignore Chrome specific Tab capture and |kSourceId| constraints.
- continue;
- }
-
- bool valid = false;
- for (size_t j = 0; j < arraysize(kDefaultAudioConstraints); ++j) {
- if (key == kDefaultAudioConstraints[j].key) {
- bool value = false;
- valid = GetMandatoryConstraintValueAsBoolean(constraints_, key, &value);
- break;
- }
- }
-
- if (!valid) {
- DLOG(ERROR) << "Invalid MediaStream constraint. Name: " << key;
- return false;
- }
+ std::vector<std::string> legal_names(
+ {constraints_.basic().mediaStreamSource.name(),
+ constraints_.basic().deviceId.name(),
+ constraints_.basic().renderToAssociatedSink.name()});
+ for (size_t j = 0; j < arraysize(kDefaultAudioConstraints); ++j) {
+ legal_names.push_back(kDefaultAudioConstraints[j].key);
+ }
+ std::string failing_name;
+ if (constraints_.basic().hasMandatoryOutsideSet(legal_names, failing_name)) {
+ DLOG(ERROR) << "Invalid MediaStream constraint for audio. Name: "
+ << failing_name;
+ return false;
}
-
return true;
}
bool MediaAudioConstraints::GetDefaultValueForConstraint(
- const blink::WebMediaConstraints& constraints,
const std::string& key) const {
if (!default_audio_processing_constraint_value_)
return false;
@@ -234,6 +235,77 @@ bool MediaAudioConstraints::GetDefaultValueForConstraint(
return false;
}
+bool MediaAudioConstraints::GetGoogAudioMirroring() const {
+ return ScanConstraintsForBoolean(
+ constraints_, &blink::WebMediaTrackConstraintSet::googAudioMirroring,
+ GetDefaultValueForConstraint(kGoogAudioMirroring));
+}
+
+bool MediaAudioConstraints::GetGoogAutoGainControl() const {
+ return ScanConstraintsForBoolean(
+ constraints_, &blink::WebMediaTrackConstraintSet::googAutoGainControl,
+ GetDefaultValueForConstraint(kGoogAutoGainControl));
+}
+
+bool MediaAudioConstraints::GetGoogExperimentalEchoCancellation() const {
+ return ScanConstraintsForBoolean(
+ constraints_,
+ &blink::WebMediaTrackConstraintSet::googExperimentalEchoCancellation,
+ GetDefaultValueForConstraint(kGoogExperimentalEchoCancellation));
+}
+
+bool MediaAudioConstraints::GetGoogTypingNoiseDetection() const {
+ return ScanConstraintsForBoolean(
+ constraints_,
+ &blink::WebMediaTrackConstraintSet::googTypingNoiseDetection,
+ GetDefaultValueForConstraint(kGoogTypingNoiseDetection));
+}
+bool MediaAudioConstraints::GetGoogNoiseSuppression() const {
+ return ScanConstraintsForBoolean(
+ constraints_, &blink::WebMediaTrackConstraintSet::googNoiseSuppression,
+ GetDefaultValueForConstraint(kGoogNoiseSuppression));
+}
+
+bool MediaAudioConstraints::GetGoogExperimentalNoiseSuppression() const {
+ return ScanConstraintsForBoolean(
+ constraints_,
+ &blink::WebMediaTrackConstraintSet::googExperimentalNoiseSuppression,
+ GetDefaultValueForConstraint(kGoogExperimentalNoiseSuppression));
+}
+
+bool MediaAudioConstraints::GetGoogBeamforming() const {
+ return ScanConstraintsForBoolean(
+ constraints_, &blink::WebMediaTrackConstraintSet::googBeamforming,
+ GetDefaultValueForConstraint(kGoogBeamforming));
+}
+
+bool MediaAudioConstraints::GetGoogHighpassFilter() const {
+ return ScanConstraintsForBoolean(
+ constraints_, &blink::WebMediaTrackConstraintSet::googHighpassFilter,
+ GetDefaultValueForConstraint(kGoogHighpassFilter));
+}
+
+bool MediaAudioConstraints::GetGoogExperimentalAutoGainControl() const {
+ return ScanConstraintsForBoolean(
+ constraints_,
+ &blink::WebMediaTrackConstraintSet::googExperimentalAutoGainControl,
+ GetDefaultValueForConstraint(kGoogExperimentalAutoGainControl));
+}
+
+std::string MediaAudioConstraints::GetGoogArrayGeometry() const {
+ const auto& the_field = constraints_.basic().googArrayGeometry;
+ if (the_field.hasMandatory()) {
+ return the_field.exact()[0].utf8();
+ }
+ for (const auto& advanced_constraint : constraints_.advanced()) {
+ const auto& the_field = advanced_constraint.googArrayGeometry;
+ if (the_field.hasMandatory()) {
+ return the_field.exact()[0].utf8();
+ }
+ }
+ return "";
+}
+
EchoInformation::EchoInformation()
: num_chunks_(0), echo_frames_received_(false) {
}
@@ -281,18 +353,12 @@ void EchoInformation::UpdateAecDelayStats(
}
void EnableEchoCancellation(AudioProcessing* audio_processing) {
-#if defined(OS_ANDROID) || defined(OS_IOS)
- const std::string group_name =
- base::FieldTrialList::FindFullName("ReplaceAECMWithAEC");
- if (group_name.empty() ||
- !(group_name == "Enabled" || group_name == "DefaultEnabled")) {
- // Mobile devices are using AECM.
- int err = audio_processing->echo_control_mobile()->set_routing_mode(
- webrtc::EchoControlMobile::kSpeakerphone);
- err |= audio_processing->echo_control_mobile()->Enable(true);
- CHECK_EQ(err, 0);
- return;
- }
+#if defined(OS_ANDROID)
+ // Mobile devices are using AECM.
+ CHECK_EQ(0, audio_processing->echo_control_mobile()->set_routing_mode(
+ webrtc::EchoControlMobile::kSpeakerphone));
+ CHECK_EQ(0, audio_processing->echo_control_mobile()->Enable(true));
+ return;
#endif
int err = audio_processing->echo_cancellation()->set_suppression_level(
webrtc::EchoCancellation::kHighSuppression);
@@ -346,7 +412,7 @@ void StopEchoCancellationDump(AudioProcessing* audio_processing) {
}
void EnableAutomaticGainControl(AudioProcessing* audio_processing) {
-#if defined(OS_ANDROID) || defined(OS_IOS)
+#if defined(OS_ANDROID)
const webrtc::GainControl::Mode mode = webrtc::GainControl::kFixedDigital;
#else
const webrtc::GainControl::Mode mode = webrtc::GainControl::kAdaptiveAnalog;
@@ -401,8 +467,7 @@ std::vector<webrtc::Point> GetArrayGeometryPreferringConstraints(
const MediaAudioConstraints& audio_constraints,
const MediaStreamDevice::AudioDeviceParameters& input_params) {
const std::string constraints_geometry =
- audio_constraints.GetPropertyAsString(
- MediaAudioConstraints::kGoogArrayGeometry);
+ audio_constraints.GetGoogArrayGeometry();
// Give preference to the audio constraint over the device-supplied mic
// positions. This is mainly for testing purposes.
diff --git a/chromium/content/renderer/media/media_stream_audio_processor_options.h b/chromium/content/renderer/media/media_stream_audio_processor_options.h
index 6a2048a63f1..2d5af1d4f41 100644
--- a/chromium/content/renderer/media/media_stream_audio_processor_options.h
+++ b/chromium/content/renderer/media/media_stream_audio_processor_options.h
@@ -12,13 +12,13 @@
#include "content/common/content_export.h"
#include "content/public/common/media_stream_request.h"
#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
+#include "third_party/webrtc/media/base/mediachannel.h"
#include "third_party/webrtc/modules/audio_processing/include/audio_processing.h"
namespace webrtc {
class EchoCancellation;
-class MediaConstraintsInterface;
class TypingDetection;
}
@@ -28,7 +28,6 @@ namespace content {
class RTCMediaConstraints;
using webrtc::AudioProcessing;
-using webrtc::MediaConstraintsInterface;
// A helper class to parse audio constraints from a blink::WebMediaConstraints
// object.
@@ -48,11 +47,13 @@ class CONTENT_EXPORT MediaAudioConstraints {
static const char kGoogTypingNoiseDetection[];
static const char kGoogAudioMirroring[];
- // Merge |constraints| with |kDefaultAudioConstraints|. For any key which
- // exists in both, the value from |constraints| is maintained, including its
- // mandatory/optional status. New values from |kDefaultAudioConstraints| will
- // be added with optional status.
- static void ApplyFixedAudioConstraints(RTCMediaConstraints* constraints);
+ // Merge |options| with |kDefaultAudioConstraints|. For any key which
+ // exists in both, the value from |options| is maintained.
+ // New values from |kDefaultAudioConstraints| will
+ // be added.
+ // TODO(hta): Switch to an interface without "cricket::" when webrtc has one.
+
+ static void ApplyFixedAudioConstraints(cricket::AudioOptions* options);
// |effects| is the bitmasks telling whether certain platform
// hardware audio effects are enabled, like hardware echo cancellation. If
@@ -62,17 +63,16 @@ class CONTENT_EXPORT MediaAudioConstraints {
int effects);
virtual ~MediaAudioConstraints();
- // Gets the property of the constraint named by |key| in |constraints_|.
- // Returns the constraint's value if the key is found; otherwise returns the
- // default value of the constraint.
- // Note, for constraint of |kEchoCancellation| or |kGoogEchoCancellation|,
- // clients should use GetEchoCancellationProperty().
- bool GetProperty(const std::string& key) const;
-
- // Gets the property of the constraint named by |key| in |constraints_| as a
- // string. Returns the constraint's string value if the key is found;
- // otherwise returns an empty string.
- std::string GetPropertyAsString(const std::string& key) const;
+ bool GetGoogAudioMirroring() const;
+ bool GetGoogAutoGainControl() const;
+ bool GetGoogExperimentalEchoCancellation() const;
+ bool GetGoogTypingNoiseDetection() const;
+ bool GetGoogNoiseSuppression() const;
+ bool GetGoogExperimentalNoiseSuppression() const;
+ bool GetGoogBeamforming() const;
+ bool GetGoogHighpassFilter() const;
+ bool GetGoogExperimentalAutoGainControl() const;
+ std::string GetGoogArrayGeometry() const;
// Gets the property of echo cancellation defined in |constraints_|. The
// returned value depends on a combination of |effects_|, |kEchoCancellation|
@@ -83,12 +83,14 @@ class CONTENT_EXPORT MediaAudioConstraints {
// Otherwise return false.
bool IsValid() const;
+ // Exposed for testing.
+ bool default_audio_processing_constraint_value() const {
+ return default_audio_processing_constraint_value_;
+ }
+
private:
// Gets the default value of constraint named by |key| in |constraints|.
- bool GetDefaultValueForConstraint(
- const blink::WebMediaConstraints& constraints,
- const std::string& key) const;
-
+ bool GetDefaultValueForConstraint(const std::string& key) const;
const blink::WebMediaConstraints constraints_;
const int effects_;
bool default_audio_processing_constraint_value_;
diff --git a/chromium/content/renderer/media/media_stream_audio_processor_unittest.cc b/chromium/content/renderer/media/media_stream_audio_processor_unittest.cc
index a23d03e8e71..2e3ea78789f 100644
--- a/chromium/content/renderer/media/media_stream_audio_processor_unittest.cc
+++ b/chromium/content/renderer/media/media_stream_audio_processor_unittest.cc
@@ -18,13 +18,13 @@
#include "content/public/common/media_stream_request.h"
#include "content/renderer/media/media_stream_audio_processor.h"
#include "content/renderer/media/media_stream_audio_processor_options.h"
-#include "content/renderer/media/mock_media_constraint_factory.h"
+#include "content/renderer/media/mock_constraint_factory.h"
#include "media/audio/audio_parameters.h"
#include "media/base/audio_bus.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
using ::testing::_;
using ::testing::AnyNumber;
@@ -91,17 +91,17 @@ class MediaStreamAudioProcessorTest : public ::testing::Test {
const int packet_size =
params.frames_per_buffer() * 2 * params.channels();
const size_t length = packet_size * kNumberOfPacketsForTest;
- scoped_ptr<char[]> capture_data(new char[length]);
+ std::unique_ptr<char[]> capture_data(new char[length]);
ReadDataFromSpeechFile(capture_data.get(), length);
const int16_t* data_ptr =
reinterpret_cast<const int16_t*>(capture_data.get());
- scoped_ptr<media::AudioBus> data_bus = media::AudioBus::Create(
- params.channels(), params.frames_per_buffer());
+ std::unique_ptr<media::AudioBus> data_bus =
+ media::AudioBus::Create(params.channels(), params.frames_per_buffer());
// |data_bus_playout| is used if the number of capture channels is larger
// that max allowed playout channels. |data_bus_playout_to_use| points to
// the AudioBus to use, either |data_bus| or |data_bus_playout|.
- scoped_ptr<media::AudioBus> data_bus_playout;
+ std::unique_ptr<media::AudioBus> data_bus_playout;
media::AudioBus* data_bus_playout_to_use = data_bus.get();
if (params.channels() > kMaxNumberOfPlayoutDataChannels) {
data_bus_playout =
@@ -122,7 +122,7 @@ class MediaStreamAudioProcessorTest : public ::testing::Test {
// |audio_processor| does nothing when the audio processing is off in
// the processor.
webrtc::AudioProcessing* ap = audio_processor->audio_processing_.get();
-#if defined(OS_ANDROID) || defined(OS_IOS)
+#if defined(OS_ANDROID)
const bool is_aec_enabled = ap && ap->echo_control_mobile()->is_enabled();
// AEC should be turned off for mobiles.
DCHECK(!ap || !ap->echo_cancellation()->is_enabled());
@@ -169,7 +169,7 @@ class MediaStreamAudioProcessorTest : public ::testing::Test {
EXPECT_TRUE(audio_processing->echo_control_mobile()->routing_mode() ==
webrtc::EchoControlMobile::kSpeakerphone);
EXPECT_FALSE(audio_processing->echo_cancellation()->is_enabled());
-#elif !defined(OS_IOS)
+#else
EXPECT_TRUE(audio_processing->echo_cancellation()->is_enabled());
EXPECT_TRUE(audio_processing->echo_cancellation()->suppression_level() ==
webrtc::EchoCancellation::kHighSuppression);
@@ -183,7 +183,7 @@ class MediaStreamAudioProcessorTest : public ::testing::Test {
webrtc::NoiseSuppression::kHigh);
EXPECT_TRUE(audio_processing->high_pass_filter()->is_enabled());
EXPECT_TRUE(audio_processing->gain_control()->is_enabled());
-#if defined(OS_ANDROID) || defined(OS_IOS)
+#if defined(OS_ANDROID)
EXPECT_TRUE(audio_processing->gain_control()->mode() ==
webrtc::GainControl::kFixedDigital);
EXPECT_FALSE(audio_processing->voice_detection()->is_enabled());
@@ -207,7 +207,7 @@ class MediaStreamAudioProcessorTest : public ::testing::Test {
#define MAYBE_WithAudioProcessing WithAudioProcessing
#endif
TEST_F(MediaStreamAudioProcessorTest, MAYBE_WithAudioProcessing) {
- MockMediaConstraintFactory constraint_factory;
+ MockConstraintFactory constraint_factory;
scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
new WebRtcAudioDeviceImpl());
scoped_refptr<MediaStreamAudioProcessor> audio_processor(
@@ -231,10 +231,10 @@ TEST_F(MediaStreamAudioProcessorTest, VerifyTabCaptureWithoutAudioProcessing) {
scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
new WebRtcAudioDeviceImpl());
// Create MediaStreamAudioProcessor instance for kMediaStreamSourceTab source.
- MockMediaConstraintFactory tab_constraint_factory;
+ MockConstraintFactory tab_constraint_factory;
const std::string tab_string = kMediaStreamSourceTab;
- tab_constraint_factory.AddMandatory(kMediaStreamSource,
- tab_string);
+ tab_constraint_factory.basic().mediaStreamSource.setExact(
+ blink::WebString::fromUTF8(tab_string));
scoped_refptr<MediaStreamAudioProcessor> audio_processor(
new rtc::RefCountedObject<MediaStreamAudioProcessor>(
tab_constraint_factory.CreateWebMediaConstraints(),
@@ -249,10 +249,10 @@ TEST_F(MediaStreamAudioProcessorTest, VerifyTabCaptureWithoutAudioProcessing) {
// Create MediaStreamAudioProcessor instance for kMediaStreamSourceSystem
// source.
- MockMediaConstraintFactory system_constraint_factory;
+ MockConstraintFactory system_constraint_factory;
const std::string system_string = kMediaStreamSourceSystem;
- system_constraint_factory.AddMandatory(kMediaStreamSource,
- system_string);
+ system_constraint_factory.basic().mediaStreamSource.setExact(
+ blink::WebString::fromUTF8(system_string));
audio_processor = new rtc::RefCountedObject<MediaStreamAudioProcessor>(
system_constraint_factory.CreateWebMediaConstraints(),
input_device_params_, webrtc_audio_device.get());
@@ -265,7 +265,7 @@ TEST_F(MediaStreamAudioProcessorTest, VerifyTabCaptureWithoutAudioProcessing) {
TEST_F(MediaStreamAudioProcessorTest, TurnOffDefaultConstraints) {
// Turn off the default constraints and pass it to MediaStreamAudioProcessor.
- MockMediaConstraintFactory constraint_factory;
+ MockConstraintFactory constraint_factory;
constraint_factory.DisableDefaultAudioConstraints();
scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
new WebRtcAudioDeviceImpl());
@@ -286,43 +286,9 @@ TEST_F(MediaStreamAudioProcessorTest, TurnOffDefaultConstraints) {
}
TEST_F(MediaStreamAudioProcessorTest, VerifyConstraints) {
- static const char* kDefaultAudioConstraints[] = {
- MediaAudioConstraints::kEchoCancellation,
- MediaAudioConstraints::kGoogAudioMirroring,
- MediaAudioConstraints::kGoogAutoGainControl,
- MediaAudioConstraints::kGoogEchoCancellation,
- MediaAudioConstraints::kGoogExperimentalEchoCancellation,
- MediaAudioConstraints::kGoogExperimentalAutoGainControl,
- MediaAudioConstraints::kGoogExperimentalNoiseSuppression,
- MediaAudioConstraints::kGoogHighpassFilter,
- MediaAudioConstraints::kGoogNoiseSuppression,
- MediaAudioConstraints::kGoogTypingNoiseDetection,
- kMediaStreamAudioHotword
- };
-
- // Verify mandatory constraints.
- for (size_t i = 0; i < arraysize(kDefaultAudioConstraints); ++i) {
- MockMediaConstraintFactory constraint_factory;
- constraint_factory.AddMandatory(kDefaultAudioConstraints[i], false);
- blink::WebMediaConstraints constraints =
- constraint_factory.CreateWebMediaConstraints();
- MediaAudioConstraints audio_constraints(constraints, 0);
- EXPECT_FALSE(audio_constraints.GetProperty(kDefaultAudioConstraints[i]));
- }
-
- // Verify optional constraints.
- for (size_t i = 0; i < arraysize(kDefaultAudioConstraints); ++i) {
- MockMediaConstraintFactory constraint_factory;
- constraint_factory.AddOptional(kDefaultAudioConstraints[i], false);
- blink::WebMediaConstraints constraints =
- constraint_factory.CreateWebMediaConstraints();
- MediaAudioConstraints audio_constraints(constraints, 0);
- EXPECT_FALSE(audio_constraints.GetProperty(kDefaultAudioConstraints[i]));
- }
-
{
- // Verify echo cancellation is off when platform aec effect is on.
- MockMediaConstraintFactory constraint_factory;
+ // Verify that echo cancellation is off when platform aec effect is on.
+ MockConstraintFactory constraint_factory;
MediaAudioConstraints audio_constraints(
constraint_factory.CreateWebMediaConstraints(),
media::AudioParameters::ECHO_CANCELLER);
@@ -331,61 +297,82 @@ TEST_F(MediaStreamAudioProcessorTest, VerifyConstraints) {
{
// Verify |kEchoCancellation| overwrite |kGoogEchoCancellation|.
- MockMediaConstraintFactory constraint_factory_1;
- constraint_factory_1.AddOptional(MediaAudioConstraints::kEchoCancellation,
- true);
- constraint_factory_1.AddOptional(
- MediaAudioConstraints::kGoogEchoCancellation, false);
+ MockConstraintFactory constraint_factory_1;
+ constraint_factory_1.AddAdvanced().echoCancellation.setExact(true);
+ constraint_factory_1.AddAdvanced().googEchoCancellation.setExact(false);
blink::WebMediaConstraints constraints_1 =
constraint_factory_1.CreateWebMediaConstraints();
MediaAudioConstraints audio_constraints_1(constraints_1, 0);
EXPECT_TRUE(audio_constraints_1.GetEchoCancellationProperty());
- MockMediaConstraintFactory constraint_factory_2;
- constraint_factory_2.AddOptional(MediaAudioConstraints::kEchoCancellation,
- false);
- constraint_factory_2.AddOptional(
- MediaAudioConstraints::kGoogEchoCancellation, true);
+ MockConstraintFactory constraint_factory_2;
+ constraint_factory_2.AddAdvanced().echoCancellation.setExact(false);
+ constraint_factory_2.AddAdvanced().googEchoCancellation.setExact(true);
blink::WebMediaConstraints constraints_2 =
constraint_factory_2.CreateWebMediaConstraints();
MediaAudioConstraints audio_constraints_2(constraints_2, 0);
EXPECT_FALSE(audio_constraints_2.GetEchoCancellationProperty());
}
-
{
// When |kEchoCancellation| is explicitly set to false, the default values
// for all the constraints are false.
- MockMediaConstraintFactory constraint_factory;
- constraint_factory.AddOptional(MediaAudioConstraints::kEchoCancellation,
- false);
+ MockConstraintFactory constraint_factory;
+ constraint_factory.AddAdvanced().echoCancellation.setExact(false);
blink::WebMediaConstraints constraints =
constraint_factory.CreateWebMediaConstraints();
MediaAudioConstraints audio_constraints(constraints, 0);
- for (size_t i = 0; i < arraysize(kDefaultAudioConstraints); ++i) {
- EXPECT_FALSE(audio_constraints.GetProperty(kDefaultAudioConstraints[i]));
- }
- }
-
- {
- // |kMediaStreamAudioHotword| is always off by default.
- MockMediaConstraintFactory constraint_factory;
- MediaAudioConstraints audio_constraints(
- constraint_factory.CreateWebMediaConstraints(), 0);
- EXPECT_FALSE(audio_constraints.GetProperty(kMediaStreamAudioHotword));
}
}
-TEST_F(MediaStreamAudioProcessorTest, ValidateConstraints) {
- MockMediaConstraintFactory constraint_factory;
- const std::string dummy_constraint = "dummy";
- constraint_factory.AddMandatory(dummy_constraint, true);
+TEST_F(MediaStreamAudioProcessorTest, ValidateBadConstraints) {
+ MockConstraintFactory constraint_factory;
+ // Add a constraint that is not valid for audio.
+ constraint_factory.basic().width.setExact(240);
MediaAudioConstraints audio_constraints(
constraint_factory.CreateWebMediaConstraints(), 0);
EXPECT_FALSE(audio_constraints.IsValid());
}
+TEST_F(MediaStreamAudioProcessorTest, ValidateGoodConstraints) {
+ MockConstraintFactory constraint_factory;
+ // Check that the renderToAssociatedSink constraint is considered valid.
+ constraint_factory.basic().renderToAssociatedSink.setExact(true);
+ MediaAudioConstraints audio_constraints(
+ constraint_factory.CreateWebMediaConstraints(), 0);
+ EXPECT_TRUE(audio_constraints.IsValid());
+}
+
+TEST_F(MediaStreamAudioProcessorTest, NoEchoTurnsOffProcessing) {
+ {
+ MockConstraintFactory constraint_factory;
+ MediaAudioConstraints audio_constraints(
+ constraint_factory.CreateWebMediaConstraints(), 0);
+ // The default value for echo cancellation is true, except when all
+ // audio processing has been turned off.
+ EXPECT_TRUE(audio_constraints.default_audio_processing_constraint_value());
+ }
+ // Turning off audio processing via a mandatory constraint.
+ {
+ MockConstraintFactory constraint_factory;
+ constraint_factory.basic().echoCancellation.setExact(false);
+ MediaAudioConstraints audio_constraints(
+ constraint_factory.CreateWebMediaConstraints(), 0);
+ // The default value for echo cancellation is true, except when all
+ // audio processing has been turned off.
+ EXPECT_FALSE(audio_constraints.default_audio_processing_constraint_value());
+ }
+ // Turning off audio processing via an optional constraint.
+ {
+ MockConstraintFactory constraint_factory;
+ constraint_factory.AddAdvanced().echoCancellation.setExact(false);
+ MediaAudioConstraints audio_constraints(
+ constraint_factory.CreateWebMediaConstraints(), 0);
+ EXPECT_FALSE(audio_constraints.default_audio_processing_constraint_value());
+ }
+}
+
MediaAudioConstraints MakeMediaAudioConstraints(
- const MockMediaConstraintFactory& constraint_factory) {
+ const MockConstraintFactory& constraint_factory) {
return MediaAudioConstraints(constraint_factory.CreateWebMediaConstraints(),
AudioParameters::NO_EFFECTS);
}
@@ -400,7 +387,7 @@ TEST_F(MediaStreamAudioProcessorTest, SelectsConstraintsArrayGeometryIfExists) {
{
// Both geometries empty.
- MockMediaConstraintFactory constraint_factory;
+ MockConstraintFactory constraint_factory;
MediaStreamDevice::AudioDeviceParameters input_params;
const auto& actual_geometry = GetArrayGeometryPreferringConstraints(
@@ -409,7 +396,7 @@ TEST_F(MediaStreamAudioProcessorTest, SelectsConstraintsArrayGeometryIfExists) {
}
{
// Constraints geometry empty.
- MockMediaConstraintFactory constraint_factory;
+ MockConstraintFactory constraint_factory;
MediaStreamDevice::AudioDeviceParameters input_params;
input_params.mic_positions.push_back(media::Point(0, 0, 0));
input_params.mic_positions.push_back(media::Point(0, 0.05f, 0));
@@ -420,9 +407,9 @@ TEST_F(MediaStreamAudioProcessorTest, SelectsConstraintsArrayGeometryIfExists) {
}
{
// Input device geometry empty.
- MockMediaConstraintFactory constraint_factory;
- constraint_factory.AddOptional(MediaAudioConstraints::kGoogArrayGeometry,
- std::string("-0.02 0 0 0.02 0 0"));
+ MockConstraintFactory constraint_factory;
+ constraint_factory.AddAdvanced().googArrayGeometry.setExact(
+ blink::WebString::fromUTF8("-0.02 0 0 0.02 0 0"));
MediaStreamDevice::AudioDeviceParameters input_params;
const auto& actual_geometry = GetArrayGeometryPreferringConstraints(
@@ -431,9 +418,9 @@ TEST_F(MediaStreamAudioProcessorTest, SelectsConstraintsArrayGeometryIfExists) {
}
{
// Both geometries existing.
- MockMediaConstraintFactory constraint_factory;
- constraint_factory.AddOptional(MediaAudioConstraints::kGoogArrayGeometry,
- std::string("-0.02 0 0 0.02 0 0"));
+ MockConstraintFactory constraint_factory;
+ constraint_factory.AddAdvanced().googArrayGeometry.setExact(
+ blink::WebString::fromUTF8("-0.02 0 0 0.02 0 0"));
MediaStreamDevice::AudioDeviceParameters input_params;
input_params.mic_positions.push_back(media::Point(0, 0, 0));
input_params.mic_positions.push_back(media::Point(0, 0.05f, 0));
@@ -452,7 +439,7 @@ TEST_F(MediaStreamAudioProcessorTest, SelectsConstraintsArrayGeometryIfExists) {
#define MAYBE_TestAllSampleRates TestAllSampleRates
#endif
TEST_F(MediaStreamAudioProcessorTest, MAYBE_TestAllSampleRates) {
- MockMediaConstraintFactory constraint_factory;
+ MockConstraintFactory constraint_factory;
scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
new WebRtcAudioDeviceImpl());
scoped_refptr<MediaStreamAudioProcessor> audio_processor(
@@ -493,7 +480,7 @@ TEST_F(MediaStreamAudioProcessorTest, GetAecDumpMessageFilter) {
new AecDumpMessageFilter(message_loop.task_runner(),
message_loop.task_runner(), nullptr));
- MockMediaConstraintFactory constraint_factory;
+ MockConstraintFactory constraint_factory;
scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
new WebRtcAudioDeviceImpl());
scoped_refptr<MediaStreamAudioProcessor> audio_processor(
@@ -509,11 +496,9 @@ TEST_F(MediaStreamAudioProcessorTest, GetAecDumpMessageFilter) {
TEST_F(MediaStreamAudioProcessorTest, TestStereoAudio) {
// Set up the correct constraints to turn off the audio processing and turn
// on the stereo channels mirroring.
- MockMediaConstraintFactory constraint_factory;
- constraint_factory.AddMandatory(MediaAudioConstraints::kEchoCancellation,
- false);
- constraint_factory.AddMandatory(MediaAudioConstraints::kGoogAudioMirroring,
- true);
+ MockConstraintFactory constraint_factory;
+ constraint_factory.basic().echoCancellation.setExact(false);
+ constraint_factory.basic().googAudioMirroring.setExact(true);
scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
new WebRtcAudioDeviceImpl());
scoped_refptr<MediaStreamAudioProcessor> audio_processor(
@@ -525,17 +510,18 @@ TEST_F(MediaStreamAudioProcessorTest, TestStereoAudio) {
media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::CHANNEL_LAYOUT_STEREO, 48000, 16, 480);
audio_processor->OnCaptureFormatChanged(source_params);
- EXPECT_EQ(audio_processor->OutputFormat().channels(), 2);
+ // There's no sense in continuing if this fails.
+ ASSERT_EQ(2, audio_processor->OutputFormat().channels());
// Construct left and right channels, and assign different values to the
// first data of the left channel and right channel.
const int size = media::AudioBus::CalculateMemorySize(source_params);
- scoped_ptr<float, base::AlignedFreeDeleter> left_channel(
+ std::unique_ptr<float, base::AlignedFreeDeleter> left_channel(
static_cast<float*>(base::AlignedAlloc(size, 32)));
- scoped_ptr<float, base::AlignedFreeDeleter> right_channel(
+ std::unique_ptr<float, base::AlignedFreeDeleter> right_channel(
static_cast<float*>(base::AlignedAlloc(size, 32)));
- scoped_ptr<media::AudioBus> wrapper = media::AudioBus::CreateWrapper(
- source_params.channels());
+ std::unique_ptr<media::AudioBus> wrapper =
+ media::AudioBus::CreateWrapper(source_params.channels());
wrapper->set_frames(source_params.frames_per_buffer());
wrapper->SetChannelData(0, left_channel.get());
wrapper->SetChannelData(1, right_channel.get());
@@ -575,9 +561,8 @@ TEST_F(MediaStreamAudioProcessorTest, TestStereoAudio) {
#endif
TEST_F(MediaStreamAudioProcessorTest, MAYBE_TestWithKeyboardMicChannel) {
- MockMediaConstraintFactory constraint_factory;
- constraint_factory.AddMandatory(
- MediaAudioConstraints::kGoogExperimentalNoiseSuppression, true);
+ MockConstraintFactory constraint_factory;
+ constraint_factory.basic().googExperimentalNoiseSuppression.setExact(true);
scoped_refptr<WebRtcAudioDeviceImpl> webrtc_audio_device(
new WebRtcAudioDeviceImpl());
scoped_refptr<MediaStreamAudioProcessor> audio_processor(
diff --git a/chromium/content/renderer/media/media_stream_audio_source.cc b/chromium/content/renderer/media/media_stream_audio_source.cc
index c643140e4db..d2027fd939e 100644
--- a/chromium/content/renderer/media/media_stream_audio_source.cc
+++ b/chromium/content/renderer/media/media_stream_audio_source.cc
@@ -4,7 +4,9 @@
#include "content/renderer/media/media_stream_audio_source.h"
+#include "content/renderer/media/webrtc_local_audio_track.h"
#include "content/renderer/render_frame_impl.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
namespace content {
@@ -13,20 +15,33 @@ MediaStreamAudioSource::MediaStreamAudioSource(
const StreamDeviceInfo& device_info,
const SourceStoppedCallback& stop_callback,
PeerConnectionDependencyFactory* factory)
- : render_frame_id_(render_frame_id), factory_(factory) {
+ : render_frame_id_(render_frame_id), factory_(factory),
+ weak_factory_(this) {
SetDeviceInfo(device_info);
SetStopCallback(stop_callback);
}
MediaStreamAudioSource::MediaStreamAudioSource()
- : render_frame_id_(-1), factory_(NULL) {
+ : render_frame_id_(-1), factory_(NULL), weak_factory_(this) {
}
MediaStreamAudioSource::~MediaStreamAudioSource() {}
+// static
+MediaStreamAudioSource* MediaStreamAudioSource::From(
+ const blink::WebMediaStreamSource& source) {
+ if (source.isNull() ||
+ source.getType() != blink::WebMediaStreamSource::TypeAudio) {
+ return nullptr;
+ }
+ return static_cast<MediaStreamAudioSource*>(source.getExtraData());
+}
+
void MediaStreamAudioSource::DoStopSource() {
- if (audio_capturer_.get())
+ if (audio_capturer_)
audio_capturer_->Stop();
+ if (webaudio_capturer_)
+ webaudio_capturer_->Stop();
}
void MediaStreamAudioSource::AddTrack(
@@ -52,4 +67,20 @@ void MediaStreamAudioSource::AddTrack(
callback.Run(this, MEDIA_DEVICE_OK, "");
}
+void MediaStreamAudioSource::StopAudioDeliveryTo(MediaStreamAudioTrack* track) {
+ DCHECK(track);
+ if (audio_capturer_) {
+ // The cast here is safe because only WebRtcLocalAudioTracks are ever used
+ // with WebRtcAudioCapturer sources.
+ //
+ // TODO(miu): That said, this ugly cast won't be necessary after my
+ // soon-upcoming refactoring change.
+ audio_capturer_->RemoveTrack(static_cast<WebRtcLocalAudioTrack*>(track));
+ }
+ if (webaudio_capturer_) {
+ // A separate source is created for each track, so just stop the source.
+ webaudio_capturer_->Stop();
+ }
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_audio_source.h b/chromium/content/renderer/media/media_stream_audio_source.h
index e332b83e0c8..3d55f224071 100644
--- a/chromium/content/renderer/media/media_stream_audio_source.h
+++ b/chromium/content/renderer/media/media_stream_audio_source.h
@@ -5,16 +5,26 @@
#ifndef CONTENT_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_SOURCE_H_
#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_SOURCE_H_
+#include <memory>
+
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "content/common/content_export.h"
#include "content/renderer/media/media_stream_source.h"
+#include "content/renderer/media/webaudio_capturer_source.h"
#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
#include "content/renderer/media/webrtc_audio_capturer.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
namespace content {
+class MediaStreamAudioTrack;
+
+// TODO(miu): In a soon-upcoming set of refactoring changes, this class will
+// become a base class for managing tracks (part of what WebRtcAudioCapturer
+// does today). Then, the rest of WebRtcAudioCapturer will be rolled into a
+// subclass. http://crbug.com/577874
class CONTENT_EXPORT MediaStreamAudioSource
: NON_EXPORTED_BASE(public MediaStreamSource) {
public:
@@ -25,27 +35,46 @@ class CONTENT_EXPORT MediaStreamAudioSource
MediaStreamAudioSource();
~MediaStreamAudioSource() override;
+ // Returns the MediaStreamAudioSource instance owned by the given blink
+ // |source| or null.
+ static MediaStreamAudioSource* From(const blink::WebMediaStreamSource& track);
+
void AddTrack(const blink::WebMediaStreamTrack& track,
const blink::WebMediaConstraints& constraints,
const ConstraintsCallback& callback);
- void SetLocalAudioSource(webrtc::AudioSourceInterface* source) {
- local_audio_source_ = source;
+ base::WeakPtr<MediaStreamAudioSource> GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
}
- void SetAudioCapturer(const scoped_refptr<WebRtcAudioCapturer>& capturer) {
- DCHECK(!audio_capturer_.get());
- audio_capturer_ = capturer;
- }
+ // Removes |track| from the list of instances that get a copy of the source
+ // audio data.
+ void StopAudioDeliveryTo(MediaStreamAudioTrack* track);
+
+ WebRtcAudioCapturer* audio_capturer() const { return audio_capturer_.get(); }
- const scoped_refptr<WebRtcAudioCapturer>& GetAudioCapturer() {
- return audio_capturer_;
+ void SetAudioCapturer(std::unique_ptr<WebRtcAudioCapturer> capturer) {
+ DCHECK(!audio_capturer_.get());
+ audio_capturer_ = std::move(capturer);
}
webrtc::AudioSourceInterface* local_audio_source() {
return local_audio_source_.get();
}
+ void SetLocalAudioSource(scoped_refptr<webrtc::AudioSourceInterface> source) {
+ local_audio_source_ = std::move(source);
+ }
+
+ WebAudioCapturerSource* webaudio_capturer() const {
+ return webaudio_capturer_.get();
+ }
+
+ void SetWebAudioCapturer(std::unique_ptr<WebAudioCapturerSource> capturer) {
+ DCHECK(!webaudio_capturer_.get());
+ webaudio_capturer_ = std::move(capturer);
+ }
+
protected:
void DoStopSource() override;
@@ -53,11 +82,22 @@ class CONTENT_EXPORT MediaStreamAudioSource
const int render_frame_id_;
PeerConnectionDependencyFactory* const factory_;
+ // MediaStreamAudioSource is the owner of either a WebRtcAudioCapturer or a
+ // WebAudioCapturerSource.
+ //
+ // TODO(miu): In a series of soon-upcoming changes, WebRtcAudioCapturer and
+ // WebAudioCapturerSource will become subclasses of MediaStreamAudioSource
+ // instead.
+ std::unique_ptr<WebRtcAudioCapturer> audio_capturer_;
+ std::unique_ptr<WebAudioCapturerSource> webaudio_capturer_;
+
// This member holds an instance of webrtc::LocalAudioSource. This is used
// as a container for audio options.
scoped_refptr<webrtc::AudioSourceInterface> local_audio_source_;
- scoped_refptr<WebRtcAudioCapturer> audio_capturer_;
+ // Provides weak pointers so that MediaStreamAudioTracks won't call
+ // StopAudioDeliveryTo() if this instance dies first.
+ base::WeakPtrFactory<MediaStreamAudioSource> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(MediaStreamAudioSource);
};
diff --git a/chromium/content/renderer/media/media_stream_audio_track.cc b/chromium/content/renderer/media/media_stream_audio_track.cc
index 89bc39f66bc..9eee57d6142 100644
--- a/chromium/content/renderer/media/media_stream_audio_track.cc
+++ b/chromium/content/renderer/media/media_stream_audio_track.cc
@@ -4,29 +4,54 @@
#include "content/renderer/media/media_stream_audio_track.h"
+#include "base/callback_helpers.h"
#include "base/logging.h"
#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
namespace content {
MediaStreamAudioTrack::MediaStreamAudioTrack(bool is_local_track)
: MediaStreamTrack(is_local_track) {
+ DVLOG(1) << "MediaStreamAudioTrack::MediaStreamAudioTrack(is a "
+ << (is_local_track ? "local" : "remote") << " track)";
}
MediaStreamAudioTrack::~MediaStreamAudioTrack() {
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
+ DVLOG(1) << "MediaStreamAudioTrack::~MediaStreamAudioTrack()";
+ DCHECK(stop_callback_.is_null())
+ << "BUG: Subclass must ensure Stop() is called.";
}
// static
-MediaStreamAudioTrack* MediaStreamAudioTrack::GetTrack(
+MediaStreamAudioTrack* MediaStreamAudioTrack::From(
const blink::WebMediaStreamTrack& track) {
if (track.isNull() ||
- track.source().type() != blink::WebMediaStreamSource::TypeAudio) {
+ track.source().getType() != blink::WebMediaStreamSource::TypeAudio) {
return nullptr;
}
- return static_cast<MediaStreamAudioTrack*>(track.extraData());
+ return static_cast<MediaStreamAudioTrack*>(track.getExtraData());
}
+void MediaStreamAudioTrack::Start(const base::Closure& stop_callback) {
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
+ DCHECK(!stop_callback.is_null());
+ DCHECK(stop_callback_.is_null());
+ DVLOG(1) << "MediaStreamAudioTrack::Start()";
+ stop_callback_ = stop_callback;
+}
+
+void MediaStreamAudioTrack::Stop() {
+ DCHECK(main_render_thread_checker_.CalledOnValidThread());
+ DVLOG(1) << "MediaStreamAudioTrack::Stop()";
+ if (!stop_callback_.is_null())
+ base::ResetAndReturn(&stop_callback_).Run();
+ OnStop();
+}
+
+void MediaStreamAudioTrack::OnStop() {}
+
webrtc::AudioTrackInterface* MediaStreamAudioTrack::GetAudioAdapter() {
NOTREACHED();
return nullptr;
diff --git a/chromium/content/renderer/media/media_stream_audio_track.h b/chromium/content/renderer/media/media_stream_audio_track.h
index 2175b4e186f..0ef126b431a 100644
--- a/chromium/content/renderer/media/media_stream_audio_track.h
+++ b/chromium/content/renderer/media/media_stream_audio_track.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_TRACK_H_
#define CONTENT_RENDERER_MEDIA_MEDIA_STREAM_AUDIO_TRACK_H_
+#include "base/callback.h"
#include "base/macros.h"
#include "content/renderer/media/media_stream_track.h"
@@ -16,13 +17,21 @@ namespace content {
class MediaStreamAudioSink;
+// TODO(miu): In a soon-upcoming set of refactoring changes, this class will
+// take on the functionality of managing sink connections and the audio data
+// flow between source and sinks. The WebRTC-specific elements will then be
+// moved into a subclass. http://crbug.com/577874
class CONTENT_EXPORT MediaStreamAudioTrack : public MediaStreamTrack {
public:
explicit MediaStreamAudioTrack(bool is_local_track);
+
+ // Subclasses must ensure the track is stopped (i.e., Stop() has been called
+ // at least once) before this destructor is invoked.
~MediaStreamAudioTrack() override;
- static MediaStreamAudioTrack* GetTrack(
- const blink::WebMediaStreamTrack& track);
+ // Returns the MediaStreamAudioTrack instance owned by the given blink |track|
+ // or null.
+ static MediaStreamAudioTrack* From(const blink::WebMediaStreamTrack& track);
// Add a sink to the track. This function will trigger a OnSetFormat()
// call on the |sink|.
@@ -34,6 +43,7 @@ class CONTENT_EXPORT MediaStreamAudioTrack : public MediaStreamTrack {
virtual void RemoveSink(MediaStreamAudioSink* sink) = 0;
// TODO(tommi, xians): Remove this method.
+ // TODO(miu): See class-level TODO comment. ;-)
virtual webrtc::AudioTrackInterface* GetAudioAdapter();
// Returns the output format of the capture source. May return an invalid
@@ -44,7 +54,23 @@ class CONTENT_EXPORT MediaStreamAudioTrack : public MediaStreamTrack {
// to the complexity of all types of audio tracks+source implementations.
virtual media::AudioParameters GetOutputFormat() const = 0;
+ // Called to notify this track that the flow of audio data has started from
+ // the source. |stop_callback| is run by Stop() when the source must halt the
+ // flow of audio data to this track.
+ void Start(const base::Closure& stop_callback);
+
+ // Halts the flow of audio data from the source (and to the sinks), and then
+ // invokes OnStop() to perform any additional actions.
+ void Stop() final;
+
+ protected:
+ // Called by Stop() after the source has halted the flow of audio data.
+ virtual void OnStop();
+
private:
+ // Callback provided to Start() which is run when the audio flow must halt.
+ base::Closure stop_callback_;
+
DISALLOW_COPY_AND_ASSIGN(MediaStreamAudioTrack);
};
diff --git a/chromium/content/renderer/media/media_stream_center.cc b/chromium/content/renderer/media/media_stream_center.cc
index ad7f8ddf6f1..2f84bd8eb2b 100644
--- a/chromium/content/renderer/media/media_stream_center.cc
+++ b/chromium/content/renderer/media/media_stream_center.cc
@@ -15,6 +15,7 @@
#include "content/public/renderer/media_stream_audio_sink.h"
#include "content/public/renderer/render_thread.h"
#include "content/renderer/media/media_stream.h"
+#include "content/renderer/media/media_stream_audio_track.h"
#include "content/renderer/media/media_stream_source.h"
#include "content/renderer/media/media_stream_video_source.h"
#include "content/renderer/media/media_stream_video_track.h"
@@ -40,9 +41,9 @@ namespace {
void CreateNativeAudioMediaStreamTrack(
const blink::WebMediaStreamTrack& track,
PeerConnectionDependencyFactory* factory) {
- DCHECK(!track.extraData());
+ DCHECK(!MediaStreamAudioTrack::From(track));
blink::WebMediaStreamSource source = track.source();
- DCHECK_EQ(source.type(), blink::WebMediaStreamSource::TypeAudio);
+ DCHECK_EQ(source.getType(), blink::WebMediaStreamSource::TypeAudio);
if (source.remote()) {
factory->CreateRemoteAudioTrack(track);
} else {
@@ -52,9 +53,9 @@ void CreateNativeAudioMediaStreamTrack(
void CreateNativeVideoMediaStreamTrack(
const blink::WebMediaStreamTrack& track) {
- DCHECK(track.extraData() == NULL);
+ DCHECK(track.getExtraData() == NULL);
blink::WebMediaStreamSource source = track.source();
- DCHECK_EQ(source.type(), blink::WebMediaStreamSource::TypeVideo);
+ DCHECK_EQ(source.getType(), blink::WebMediaStreamSource::TypeVideo);
MediaStreamVideoSource* native_source =
MediaStreamVideoSource::GetVideoSource(source);
DCHECK(native_source);
@@ -75,10 +76,10 @@ void CreateNativeVideoMediaStreamTrack(
void CreateNativeMediaStreamTrack(const blink::WebMediaStreamTrack& track,
PeerConnectionDependencyFactory* factory) {
- DCHECK(!track.isNull() && !track.extraData());
+ DCHECK(!track.isNull() && !track.getExtraData());
DCHECK(!track.source().isNull());
- switch (track.source().type()) {
+ switch (track.source().getType()) {
case blink::WebMediaStreamSource::TypeAudio:
CreateNativeAudioMediaStreamTrack(track, factory);
break;
@@ -131,14 +132,14 @@ MediaStreamCenter::createWebAudioSourceFromMediaStreamTrack(
const blink::WebMediaStreamTrack& track) {
DVLOG(1) << "MediaStreamCenter::createWebAudioSourceFromMediaStreamTrack";
MediaStreamTrack* media_stream_track =
- static_cast<MediaStreamTrack*>(track.extraData());
+ static_cast<MediaStreamTrack*>(track.getExtraData());
if (!media_stream_track) {
DLOG(ERROR) << "Native track missing for webaudio source.";
return nullptr;
}
blink::WebMediaStreamSource source = track.source();
- DCHECK_EQ(source.type(), blink::WebMediaStreamSource::TypeAudio);
+ DCHECK_EQ(source.getType(), blink::WebMediaStreamSource::TypeAudio);
// TODO(tommi): Rename WebRtcLocalAudioSourceProvider to
// WebRtcAudioSourceProvider since it's not specific to local.
diff --git a/chromium/content/renderer/media/media_stream_constraints_util.cc b/chromium/content/renderer/media/media_stream_constraints_util.cc
index 7846582457a..d313f3b9424 100644
--- a/chromium/content/renderer/media/media_stream_constraints_util.cc
+++ b/chromium/content/renderer/media/media_stream_constraints_util.cc
@@ -13,127 +13,134 @@ namespace content {
namespace {
-// Convert a string ("true", "false") to a boolean.
-bool ConvertStringToBoolean(const std::string& string, bool* value) {
- static const char kValueTrue[] = "true";
- static const char kValueFalse[] = "false";
-
- *value = (string == kValueTrue);
- return *value || (string == kValueFalse);
-}
-
-} // namespace
-
-bool GetConstraintValueAsBoolean(const blink::WebMediaConstraints& constraints,
- const std::string& name,
- bool* value) {
- return GetMandatoryConstraintValueAsBoolean(constraints, name, value) ||
- GetOptionalConstraintValueAsBoolean(constraints, name, value);
-}
-
-bool GetConstraintValueAsInteger(const blink::WebMediaConstraints& constraints,
- const std::string& name,
- int* value) {
- return GetMandatoryConstraintValueAsInteger(constraints, name, value) ||
- GetOptionalConstraintValueAsInteger(constraints, name, value);
+template <typename P, typename T>
+bool ScanConstraintsForExactValue(const blink::WebMediaConstraints& constraints,
+ P picker,
+ T* value) {
+ const auto& the_field = constraints.basic().*picker;
+ if (the_field.hasExact()) {
+ *value = the_field.exact();
+ return true;
+ }
+ for (const auto& advanced_constraint : constraints.advanced()) {
+ const auto& the_field = advanced_constraint.*picker;
+ if (the_field.hasExact()) {
+ *value = the_field.exact();
+ return true;
+ }
+ }
+ return false;
}
-bool GetConstraintValueAsDouble(const blink::WebMediaConstraints& constraints,
- const std::string& name,
- double* value) {
- return GetMandatoryConstraintValueAsDouble(constraints, name, value) ||
- GetOptionalConstraintValueAsDouble(constraints, name, value);
+template <typename P, typename T>
+bool ScanConstraintsForMaxValue(const blink::WebMediaConstraints& constraints,
+ P picker,
+ T* value) {
+ const auto& the_field = constraints.basic().*picker;
+ if (the_field.hasMax()) {
+ *value = the_field.max();
+ return true;
+ }
+ for (const auto& advanced_constraint : constraints.advanced()) {
+ const auto& the_field = advanced_constraint.*picker;
+ if (the_field.hasMax()) {
+ *value = the_field.max();
+ return true;
+ }
+ }
+ return false;
}
-bool GetConstraintValueAsString(const blink::WebMediaConstraints& constraints,
- const std::string& name,
- std::string* value) {
- blink::WebString value_str;
- base::string16 name_16 = base::UTF8ToUTF16(name);
- if (!constraints.getMandatoryConstraintValue(name_16, value_str) &&
- !constraints.getOptionalConstraintValue(name_16, value_str)) {
- return false;
+template <typename P, typename T>
+bool ScanConstraintsForMinValue(const blink::WebMediaConstraints& constraints,
+ P picker,
+ T* value) {
+ const auto& the_field = constraints.basic().*picker;
+ if (the_field.hasMin()) {
+ *value = the_field.min();
+ return true;
}
-
- *value = value_str.utf8();
- return true;
+ for (const auto& advanced_constraint : constraints.advanced()) {
+ const auto& the_field = advanced_constraint.*picker;
+ if (the_field.hasMin()) {
+ *value = the_field.min();
+ return true;
+ }
+ }
+ return false;
}
-bool GetMandatoryConstraintValueAsBoolean(
+} // namespace
+
+bool GetConstraintValueAsBoolean(
const blink::WebMediaConstraints& constraints,
- const std::string& name,
+ const blink::BooleanConstraint blink::WebMediaTrackConstraintSet::*picker,
bool* value) {
- blink::WebString value_str;
- if (!constraints.getMandatoryConstraintValue(base::UTF8ToUTF16(name),
- value_str)) {
- return false;
- }
+ return ScanConstraintsForExactValue(constraints, picker, value);
+}
- return ConvertStringToBoolean(value_str.utf8(), value);
+bool GetConstraintValueAsInteger(
+ const blink::WebMediaConstraints& constraints,
+ const blink::LongConstraint blink::WebMediaTrackConstraintSet::*picker,
+ int* value) {
+ return ScanConstraintsForExactValue(constraints, picker, value);
}
-bool GetMandatoryConstraintValueAsInteger(
+bool GetConstraintMinAsInteger(
const blink::WebMediaConstraints& constraints,
- const std::string& name,
+ const blink::LongConstraint blink::WebMediaTrackConstraintSet::*picker,
int* value) {
- blink::WebString value_str;
- if (!constraints.getMandatoryConstraintValue(base::UTF8ToUTF16(name),
- value_str)) {
- return false;
- }
+ return ScanConstraintsForMinValue(constraints, picker, value);
+}
- return base::StringToInt(value_str.utf8(), value);
+bool GetConstraintMaxAsInteger(
+ const blink::WebMediaConstraints& constraints,
+ const blink::LongConstraint blink::WebMediaTrackConstraintSet::*picker,
+ int* value) {
+ return ScanConstraintsForMaxValue(constraints, picker, value);
}
-bool GetMandatoryConstraintValueAsDouble(
+bool GetConstraintValueAsDouble(
const blink::WebMediaConstraints& constraints,
- const std::string& name,
+ const blink::DoubleConstraint blink::WebMediaTrackConstraintSet::*picker,
double* value) {
- blink::WebString value_str;
- if (!constraints.getMandatoryConstraintValue(base::UTF8ToUTF16(name),
- value_str)) {
- return false;
- }
- return base::StringToDouble(value_str.utf8(), value);
+ return ScanConstraintsForExactValue(constraints, picker, value);
}
-bool GetOptionalConstraintValueAsBoolean(
+bool GetConstraintMinAsDouble(
const blink::WebMediaConstraints& constraints,
- const std::string& name,
- bool* value) {
- blink::WebString value_str;
- if (!constraints.getOptionalConstraintValue(base::UTF8ToUTF16(name),
- value_str)) {
- return false;
- }
+ const blink::DoubleConstraint blink::WebMediaTrackConstraintSet::*picker,
+ double* value) {
+ return ScanConstraintsForMinValue(constraints, picker, value);
+}
- return ConvertStringToBoolean(value_str.utf8(), value);
+bool GetConstraintMaxAsDouble(
+ const blink::WebMediaConstraints& constraints,
+ const blink::DoubleConstraint blink::WebMediaTrackConstraintSet::*picker,
+ double* value) {
+ return ScanConstraintsForMaxValue(constraints, picker, value);
}
-bool GetOptionalConstraintValueAsInteger(
+bool GetConstraintValueAsString(
const blink::WebMediaConstraints& constraints,
- const std::string& name,
- int* value) {
- blink::WebString value_str;
- if (!constraints.getOptionalConstraintValue(base::UTF8ToUTF16(name),
- value_str)) {
- return false;
+ const blink::StringConstraint blink::WebMediaTrackConstraintSet::*picker,
+ std::string* value) {
+ blink::WebVector<blink::WebString> return_value;
+ if (ScanConstraintsForExactValue(constraints, picker, &return_value)) {
+ *value = return_value[0].utf8();
+ return true;
}
-
- return base::StringToInt(value_str.utf8(), value);
+ return false;
}
-bool GetOptionalConstraintValueAsDouble(
+rtc::Optional<bool> ConstraintToOptional(
const blink::WebMediaConstraints& constraints,
- const std::string& name,
- double* value) {
- blink::WebString value_str;
- if (!constraints.getOptionalConstraintValue(base::UTF8ToUTF16(name),
- value_str)) {
- return false;
+ const blink::BooleanConstraint blink::WebMediaTrackConstraintSet::*picker) {
+ bool value;
+ if (GetConstraintValueAsBoolean(constraints, picker, &value)) {
+ return rtc::Optional<bool>(value);
}
-
- return base::StringToDouble(value_str.utf8(), value);
+ return rtc::Optional<bool>();
}
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_constraints_util.h b/chromium/content/renderer/media/media_stream_constraints_util.h
index 71e9a492d18..7b24be2f25f 100644
--- a/chromium/content/renderer/media/media_stream_constraints_util.h
+++ b/chromium/content/renderer/media/media_stream_constraints_util.h
@@ -8,11 +8,8 @@
#include <string>
#include "content/common/content_export.h"
-
-namespace blink {
-class WebMediaConstraints;
-class WebString;
-}
+#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
+#include "third_party/webrtc/base/optional.h"
namespace content {
@@ -21,7 +18,7 @@ namespace content {
// constraints.
bool CONTENT_EXPORT GetConstraintValueAsBoolean(
const blink::WebMediaConstraints& constraints,
- const std::string& name,
+ const blink::BooleanConstraint blink::WebMediaTrackConstraintSet::*picker,
bool* value);
// Method to get int value of constraint with |name| from constraints.
@@ -29,7 +26,17 @@ bool CONTENT_EXPORT GetConstraintValueAsBoolean(
// constraints.
bool CONTENT_EXPORT GetConstraintValueAsInteger(
const blink::WebMediaConstraints& constraints,
- const std::string& name,
+ const blink::LongConstraint blink::WebMediaTrackConstraintSet::*picker,
+ int* value);
+
+bool CONTENT_EXPORT GetConstraintMinAsInteger(
+ const blink::WebMediaConstraints& constraints,
+ const blink::LongConstraint blink::WebMediaTrackConstraintSet::*picker,
+ int* value);
+
+bool CONTENT_EXPORT GetConstraintMaxAsInteger(
+ const blink::WebMediaConstraints& constraints,
+ const blink::LongConstraint blink::WebMediaTrackConstraintSet::*picker,
int* value);
// Method to get double precision value of constraint with |name| from
@@ -37,58 +44,30 @@ bool CONTENT_EXPORT GetConstraintValueAsInteger(
// or Optional constraints.
bool CONTENT_EXPORT GetConstraintValueAsDouble(
const blink::WebMediaConstraints& constraints,
- const std::string& name,
+ const blink::DoubleConstraint blink::WebMediaTrackConstraintSet::*picker,
double* value);
-// Method to get std::string value of constraint with |name| from constraints.
-// Returns true if the constraint is specified in either mandatory or Optional
-// constraints.
-bool CONTENT_EXPORT GetConstraintValueAsString(
+bool CONTENT_EXPORT GetConstraintMinAsDouble(
const blink::WebMediaConstraints& constraints,
- const std::string& name,
- std::string* value);
-
-// Method to get boolean value of constraint with |name| from the
-// mandatory constraints.
-bool CONTENT_EXPORT GetMandatoryConstraintValueAsBoolean(
- const blink::WebMediaConstraints& constraints,
- const std::string& name,
- bool* value);
-
-// Method to get int value of constraint with |name| from the
-// mandatory constraints.
-bool CONTENT_EXPORT GetMandatoryConstraintValueAsInteger(
- const blink::WebMediaConstraints& constraints,
- const std::string& name,
- int* value);
-
-// Method to get double value of constraint with |name| from the
-// mandatory constraints.
-bool CONTENT_EXPORT GetMandatoryConstraintValueAsDouble(
- const blink::WebMediaConstraints& constraints,
- const std::string& name,
+ const blink::DoubleConstraint blink::WebMediaTrackConstraintSet::*picker,
double* value);
-// Method to get bool value of constraint with |name| from the
-// optional constraints.
-bool CONTENT_EXPORT GetOptionalConstraintValueAsBoolean(
+bool CONTENT_EXPORT GetConstraintMaxAsDouble(
const blink::WebMediaConstraints& constraints,
- const std::string& name,
- bool* value);
+ const blink::DoubleConstraint blink::WebMediaTrackConstraintSet::*picker,
+ double* value);
-// Method to get int value of constraint with |name| from the
-// optional constraints.
-bool CONTENT_EXPORT GetOptionalConstraintValueAsInteger(
+// Method to get std::string value of constraint with |name| from constraints.
+// Returns true if the constraint is specified in either mandatory or Optional
+// constraints.
+bool CONTENT_EXPORT GetConstraintValueAsString(
const blink::WebMediaConstraints& constraints,
- const std::string& name,
- int* value);
+ const blink::StringConstraint blink::WebMediaTrackConstraintSet::*picker,
+ std::string* value);
-// Method to get double value of constraint with |name| from the
-// optional constraints.
-bool CONTENT_EXPORT GetOptionalConstraintValueAsDouble(
+rtc::Optional<bool> ConstraintToOptional(
const blink::WebMediaConstraints& constraints,
- const std::string& name,
- double* value);
+ const blink::BooleanConstraint blink::WebMediaTrackConstraintSet::*picker);
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_constraints_util_unittest.cc b/chromium/content/renderer/media/media_stream_constraints_util_unittest.cc
index 09b95110c45..5d71cbc5408 100644
--- a/chromium/content/renderer/media/media_stream_constraints_util_unittest.cc
+++ b/chromium/content/renderer/media/media_stream_constraints_util_unittest.cc
@@ -7,7 +7,7 @@
#include "content/renderer/media/media_stream_audio_processor_options.h"
#include "content/renderer/media/media_stream_constraints_util.h"
#include "content/renderer/media/media_stream_video_source.h"
-#include "content/renderer/media/mock_media_constraint_factory.h"
+#include "content/renderer/media/mock_constraint_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
@@ -19,127 +19,76 @@ TEST_F(MediaStreamConstraintsUtilTest, BooleanConstraints) {
static const std::string kValueTrue = "true";
static const std::string kValueFalse = "false";
- MockMediaConstraintFactory constraint_factory;
+ MockConstraintFactory constraint_factory;
// Mandatory constraints.
- constraint_factory.AddMandatory(MediaAudioConstraints::kEchoCancellation,
- kValueTrue);
- constraint_factory.AddMandatory(MediaAudioConstraints::kGoogEchoCancellation,
- kValueFalse);
+ constraint_factory.basic().echoCancellation.setExact(true);
+ constraint_factory.basic().googEchoCancellation.setExact(false);
blink::WebMediaConstraints constraints =
constraint_factory.CreateWebMediaConstraints();
bool value_true = false;
bool value_false = false;
- EXPECT_TRUE(GetMandatoryConstraintValueAsBoolean(
- constraints, MediaAudioConstraints::kEchoCancellation, &value_true));
- EXPECT_TRUE(GetMandatoryConstraintValueAsBoolean(
- constraints, MediaAudioConstraints::kGoogEchoCancellation, &value_false));
+ EXPECT_TRUE(GetConstraintValueAsBoolean(
+ constraints, &blink::WebMediaTrackConstraintSet::echoCancellation,
+ &value_true));
+ EXPECT_TRUE(GetConstraintValueAsBoolean(
+ constraints, &blink::WebMediaTrackConstraintSet::googEchoCancellation,
+ &value_false));
EXPECT_TRUE(value_true);
EXPECT_FALSE(value_false);
- // Optional constraints.
- constraint_factory.AddOptional(MediaAudioConstraints::kEchoCancellation,
- kValueFalse);
- constraint_factory.AddOptional(MediaAudioConstraints::kGoogEchoCancellation,
- kValueTrue);
+ // Optional constraints, represented as "advanced"
+ constraint_factory.Reset();
+ constraint_factory.AddAdvanced().echoCancellation.setExact(false);
+ constraint_factory.AddAdvanced().googEchoCancellation.setExact(true);
constraints = constraint_factory.CreateWebMediaConstraints();
- EXPECT_TRUE(GetOptionalConstraintValueAsBoolean(
- constraints, MediaAudioConstraints::kEchoCancellation, &value_false));
- EXPECT_TRUE(GetOptionalConstraintValueAsBoolean(
- constraints, MediaAudioConstraints::kGoogEchoCancellation,
+ EXPECT_TRUE(GetConstraintValueAsBoolean(
+ constraints, &blink::WebMediaTrackConstraintSet::echoCancellation,
+ &value_false));
+ EXPECT_TRUE(GetConstraintValueAsBoolean(
+ constraints, &blink::WebMediaTrackConstraintSet::googEchoCancellation,
&value_true));
EXPECT_TRUE(value_true);
EXPECT_FALSE(value_false);
-}
-
-TEST_F(MediaStreamConstraintsUtilTest, MandatoryDoubleConstraints) {
- MockMediaConstraintFactory constraint_factory;
- const std::string test_key = "test key";
- const double test_value= 0.01f;
-
- constraint_factory.AddMandatory(test_key, test_value);
- blink::WebMediaConstraints constraints =
- constraint_factory.CreateWebMediaConstraints();
- double value;
- EXPECT_FALSE(GetOptionalConstraintValueAsDouble(constraints, test_key,
- &value));
- EXPECT_TRUE(GetMandatoryConstraintValueAsDouble(constraints, test_key,
- &value));
- EXPECT_EQ(test_value, value);
-
- value = 0;
- EXPECT_TRUE(GetConstraintValueAsDouble(constraints, test_key, &value));
- EXPECT_EQ(test_value, value);
+ // A mandatory constraint should override an optional one.
+ constraint_factory.Reset();
+ constraint_factory.AddAdvanced().echoCancellation.setExact(false);
+ constraint_factory.basic().echoCancellation.setExact(true);
+ constraints = constraint_factory.CreateWebMediaConstraints();
+ EXPECT_TRUE(GetConstraintValueAsBoolean(
+ constraints, &blink::WebMediaTrackConstraintSet::echoCancellation,
+ &value_true));
+ EXPECT_TRUE(value_true);
}
-TEST_F(MediaStreamConstraintsUtilTest, OptionalDoubleConstraints) {
- MockMediaConstraintFactory constraint_factory;
- const std::string test_key = "test key";
+TEST_F(MediaStreamConstraintsUtilTest, DoubleConstraints) {
+ MockConstraintFactory constraint_factory;
const double test_value= 0.01f;
- constraint_factory.AddOptional(test_key, test_value);
+ constraint_factory.basic().aspectRatio.setExact(test_value);
blink::WebMediaConstraints constraints =
constraint_factory.CreateWebMediaConstraints();
double value;
- EXPECT_FALSE(GetMandatoryConstraintValueAsDouble(constraints, test_key,
- &value));
- EXPECT_TRUE(GetOptionalConstraintValueAsDouble(constraints, test_key,
- &value));
- EXPECT_EQ(test_value, value);
-
- value = 0;
- EXPECT_TRUE(GetConstraintValueAsDouble(constraints, test_key, &value));
+ EXPECT_FALSE(GetConstraintValueAsDouble(
+ constraints, &blink::WebMediaTrackConstraintSet::frameRate, &value));
+ EXPECT_TRUE(GetConstraintValueAsDouble(
+ constraints, &blink::WebMediaTrackConstraintSet::aspectRatio, &value));
EXPECT_EQ(test_value, value);
}
TEST_F(MediaStreamConstraintsUtilTest, IntConstraints) {
- MockMediaConstraintFactory constraint_factory;
- int width = 600;
- int height = 480;
- constraint_factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, width);
- constraint_factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, height);
- blink::WebMediaConstraints constraints =
- constraint_factory.CreateWebMediaConstraints();
- int value_width = 0;
- int value_height = 0;
- EXPECT_TRUE(GetMandatoryConstraintValueAsInteger(
- constraints, MediaStreamVideoSource::kMaxWidth, &value_width));
- EXPECT_TRUE(GetMandatoryConstraintValueAsInteger(
- constraints, MediaStreamVideoSource::kMaxHeight, &value_height));
- EXPECT_EQ(width, value_width);
- EXPECT_EQ(height, value_height);
+ MockConstraintFactory constraint_factory;
+ const int test_value = 327;
- width = 720;
- height = 600;
- constraint_factory.AddOptional(MediaStreamVideoSource::kMaxWidth, width);
- constraint_factory.AddOptional(MediaStreamVideoSource::kMaxHeight, height);
- constraints = constraint_factory.CreateWebMediaConstraints();
- EXPECT_TRUE(GetOptionalConstraintValueAsInteger(
- constraints, MediaStreamVideoSource::kMaxWidth, &value_width));
- EXPECT_TRUE(GetOptionalConstraintValueAsInteger(
- constraints, MediaStreamVideoSource::kMaxHeight, &value_height));
- EXPECT_EQ(width, value_width);
- EXPECT_EQ(height, value_height);
-}
-
-TEST_F(MediaStreamConstraintsUtilTest, WrongBooleanConstraints) {
- static const std::string kWrongValueTrue = "True";
- static const std::string kWrongValueFalse = "False";
- MockMediaConstraintFactory constraint_factory;
- constraint_factory.AddMandatory(MediaAudioConstraints::kEchoCancellation,
- kWrongValueTrue);
- constraint_factory.AddMandatory(MediaAudioConstraints::kGoogEchoCancellation,
- kWrongValueFalse);
+ constraint_factory.basic().width.setExact(test_value);
blink::WebMediaConstraints constraints =
constraint_factory.CreateWebMediaConstraints();
- bool value_false = false;
- EXPECT_FALSE(GetMandatoryConstraintValueAsBoolean(
- constraints, MediaAudioConstraints::kEchoCancellation, &value_false));
- EXPECT_FALSE(value_false);
- EXPECT_FALSE(GetMandatoryConstraintValueAsBoolean(
- constraints, MediaAudioConstraints::kGoogEchoCancellation, &value_false));
- EXPECT_FALSE(value_false);
+
+ int value;
+ EXPECT_TRUE(GetConstraintValueAsInteger(
+ constraints, &blink::WebMediaTrackConstraintSet::width, &value));
+ EXPECT_EQ(test_value, value);
}
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_dispatcher.h b/chromium/content/renderer/media/media_stream_dispatcher.h
index 15374608125..6c0220e2070 100644
--- a/chromium/content/renderer/media/media_stream_dispatcher.h
+++ b/chromium/content/renderer/media/media_stream_dispatcher.h
@@ -7,11 +7,11 @@
#include <list>
#include <map>
+#include <memory>
#include <string>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
diff --git a/chromium/content/renderer/media/media_stream_dispatcher_unittest.cc b/chromium/content/renderer/media/media_stream_dispatcher_unittest.cc
index bc82587cb4c..fa9e80b0fb2 100644
--- a/chromium/content/renderer/media/media_stream_dispatcher_unittest.cc
+++ b/chromium/content/renderer/media/media_stream_dispatcher_unittest.cc
@@ -2,17 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "content/renderer/media/media_stream_dispatcher.h"
+
#include <stddef.h>
+#include <memory>
#include <string>
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/string_number_conversions.h"
#include "content/common/media/media_stream_messages.h"
#include "content/public/common/media_stream_request.h"
-#include "content/renderer/media/media_stream_dispatcher.h"
#include "content/renderer/media/media_stream_dispatcher_eventhandler.h"
#include "media/audio/audio_parameters.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -174,8 +175,8 @@ class MediaStreamDispatcherTest : public ::testing::Test {
protected:
base::MessageLoop message_loop_;
- scoped_ptr<MediaStreamDispatcherUnderTest> dispatcher_;
- scoped_ptr<MockMediaStreamDispatcherEventHandler> handler_;
+ std::unique_ptr<MediaStreamDispatcherUnderTest> dispatcher_;
+ std::unique_ptr<MockMediaStreamDispatcherEventHandler> handler_;
GURL security_origin_;
int request_id_;
};
@@ -215,11 +216,12 @@ TEST_F(MediaStreamDispatcherTest, GenerateStreamAndStopDevices) {
}
TEST_F(MediaStreamDispatcherTest, BasicVideoDevice) {
- scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL));
- scoped_ptr<MockMediaStreamDispatcherEventHandler>
- handler1(new MockMediaStreamDispatcherEventHandler);
- scoped_ptr<MockMediaStreamDispatcherEventHandler>
- handler2(new MockMediaStreamDispatcherEventHandler);
+ std::unique_ptr<MediaStreamDispatcher> dispatcher(
+ new MediaStreamDispatcher(NULL));
+ std::unique_ptr<MockMediaStreamDispatcherEventHandler> handler1(
+ new MockMediaStreamDispatcherEventHandler);
+ std::unique_ptr<MockMediaStreamDispatcherEventHandler> handler2(
+ new MockMediaStreamDispatcherEventHandler);
GURL security_origin;
int ipc_request_id1 = dispatcher->next_ipc_id_;
@@ -304,9 +306,10 @@ TEST_F(MediaStreamDispatcherTest, BasicVideoDevice) {
}
TEST_F(MediaStreamDispatcherTest, TestFailure) {
- scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL));
- scoped_ptr<MockMediaStreamDispatcherEventHandler>
- handler(new MockMediaStreamDispatcherEventHandler);
+ std::unique_ptr<MediaStreamDispatcher> dispatcher(
+ new MediaStreamDispatcher(NULL));
+ std::unique_ptr<MockMediaStreamDispatcherEventHandler> handler(
+ new MockMediaStreamDispatcherEventHandler);
StreamControls components(true, true);
GURL security_origin;
@@ -351,9 +354,10 @@ TEST_F(MediaStreamDispatcherTest, TestFailure) {
}
TEST_F(MediaStreamDispatcherTest, CancelGenerateStream) {
- scoped_ptr<MediaStreamDispatcher> dispatcher(new MediaStreamDispatcher(NULL));
- scoped_ptr<MockMediaStreamDispatcherEventHandler>
- handler(new MockMediaStreamDispatcherEventHandler);
+ std::unique_ptr<MediaStreamDispatcher> dispatcher(
+ new MediaStreamDispatcher(NULL));
+ std::unique_ptr<MockMediaStreamDispatcherEventHandler> handler(
+ new MockMediaStreamDispatcherEventHandler);
StreamControls components(true, true);
int ipc_request_id1 = dispatcher->next_ipc_id_;
diff --git a/chromium/content/renderer/media/media_stream_renderer_factory_impl.cc b/chromium/content/renderer/media/media_stream_renderer_factory_impl.cc
index 40463f58d3d..f31dde18b37 100644
--- a/chromium/content/renderer/media/media_stream_renderer_factory_impl.cc
+++ b/chromium/content/renderer/media/media_stream_renderer_factory_impl.cc
@@ -9,15 +9,15 @@
#include "content/renderer/media/media_stream_audio_track.h"
#include "content/renderer/media/media_stream_video_renderer_sink.h"
#include "content/renderer/media/media_stream_video_track.h"
+#include "content/renderer/media/track_audio_renderer.h"
#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
#include "content/renderer/media/webrtc_audio_renderer.h"
-#include "content/renderer/media/webrtc_local_audio_renderer.h"
#include "content/renderer/render_thread_impl.h"
#include "media/base/audio_hardware_config.h"
#include "third_party/WebKit/public/platform/WebMediaStream.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/web/WebMediaStreamRegistry.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
namespace content {
@@ -27,59 +27,26 @@ PeerConnectionDependencyFactory* GetPeerConnectionDependencyFactory() {
return RenderThreadImpl::current()->GetPeerConnectionDependencyFactory();
}
-// Returns a valid session id if a single capture device is currently open
-// (and then the matching session_id), otherwise -1.
-// This is used to pass on a session id to a webrtc audio renderer (either
-// local or remote), so that audio will be rendered to a matching output
-// device, should one exist.
+// Returns a valid session id if a single WebRTC capture device is currently
+// open (and then the matching session_id), otherwise 0.
+// This is used to pass on a session id to an audio renderer, so that audio will
+// be rendered to a matching output device, should one exist.
// Note that if there are more than one open capture devices the function
-// will not be able to pick an appropriate device and return false.
-bool GetSessionIdForAudioRenderer(int* session_id) {
+// will not be able to pick an appropriate device and return 0.
+int GetSessionIdForWebRtcAudioRenderer() {
WebRtcAudioDeviceImpl* audio_device =
GetPeerConnectionDependencyFactory()->GetWebRtcAudioDevice();
if (!audio_device)
- return false;
+ return 0;
+ int session_id = 0;
int sample_rate; // ignored, read from output device
int frames_per_buffer; // ignored, read from output device
- return audio_device->GetAuthorizedDeviceInfoForAudioRenderer(
- session_id, &sample_rate, &frames_per_buffer);
-}
-
-scoped_refptr<WebRtcAudioRenderer> CreateRemoteAudioRenderer(
- const blink::WebMediaStream& stream,
- int render_frame_id,
- const std::string& device_id,
- const url::Origin& security_origin) {
- DVLOG(1) << "MediaStreamRendererFactoryImpl::CreateRemoteAudioRenderer id:"
- << stream.id().utf8();
- // |stream| will always contain at least one audio track.
- // See MediaStreamRendererFactoryImpl::GetAudioRenderer.
-
- // TODO(tommi): Change the default value of session_id to be
- // StreamDeviceInfo::kNoId. Also update AudioOutputDevice etc.
- int session_id = 0;
- GetSessionIdForAudioRenderer(&session_id);
-
- return new WebRtcAudioRenderer(
- GetPeerConnectionDependencyFactory()->GetWebRtcSignalingThread(), stream,
- render_frame_id, session_id, device_id, security_origin);
-}
-
-scoped_refptr<WebRtcLocalAudioRenderer> CreateLocalAudioRenderer(
- const blink::WebMediaStreamTrack& audio_track,
- int render_frame_id,
- const std::string& device_id,
- const url::Origin& security_origin) {
- DVLOG(1) << "MediaStreamRendererFactoryImpl::CreateLocalAudioRenderer";
-
- int session_id = 0;
- GetSessionIdForAudioRenderer(&session_id);
-
- // Create a new WebRtcLocalAudioRenderer instance and connect it to the
- // existing WebRtcAudioCapturer so that the renderer can use it as source.
- return new WebRtcLocalAudioRenderer(audio_track, render_frame_id, session_id,
- device_id, security_origin);
+ if (!audio_device->GetAuthorizedDeviceInfoForAudioRenderer(
+ &session_id, &sample_rate, &frames_per_buffer)) {
+ session_id = 0;
+ }
+ return session_id;
}
} // namespace
@@ -142,8 +109,8 @@ MediaStreamRendererFactoryImpl::GetAudioRenderer(
// and mixes audio from all the tracks that belong to the media stream.
// For now, we have separate renderers depending on if the first audio track
// in the stream is local or remote.
- MediaStreamAudioTrack* audio_track = MediaStreamAudioTrack::GetTrack(
- audio_tracks[0]);
+ MediaStreamAudioTrack* audio_track =
+ MediaStreamAudioTrack::From(audio_tracks[0]);
if (!audio_track) {
// This can happen if the track was cloned.
// TODO(tommi, perkj): Fix cloning of tracks to handle extra data too.
@@ -151,29 +118,44 @@ MediaStreamRendererFactoryImpl::GetAudioRenderer(
return nullptr;
}
- if (audio_track->is_local_track()) {
+ // If the track has a local source, or is a remote track that does not use the
+ // WebRTC audio pipeline, return a new TrackAudioRenderer instance.
+ //
+ // TODO(miu): In a soon up-coming change, I'll introduce a cleaner way (i.e.,
+ // rather than calling GetAudioAdapter()) to determine whether a remote source
+ // is via WebRTC or something else.
+ if (audio_track->is_local_track() || !audio_track->GetAudioAdapter()) {
// TODO(xians): Add support for the case where the media stream contains
// multiple audio tracks.
- return CreateLocalAudioRenderer(audio_tracks[0], render_frame_id, device_id,
- security_origin);
+ DVLOG(1) << "Creating TrackAudioRenderer for "
+ << (audio_track->is_local_track() ? "local" : "remote")
+ << " track.";
+ return new TrackAudioRenderer(audio_tracks[0], render_frame_id,
+ 0 /* no session_id */, device_id,
+ security_origin);
}
// This is a remote WebRTC media stream.
WebRtcAudioDeviceImpl* audio_device =
GetPeerConnectionDependencyFactory()->GetWebRtcAudioDevice();
+ DCHECK(audio_device);
// Share the existing renderer if any, otherwise create a new one.
scoped_refptr<WebRtcAudioRenderer> renderer(audio_device->renderer());
- if (!renderer.get()) {
- renderer = CreateRemoteAudioRenderer(web_stream, render_frame_id,
- device_id, security_origin);
-
- if (renderer.get() && !audio_device->SetAudioRenderer(renderer.get()))
- renderer = NULL;
+ if (renderer) {
+ DVLOG(1) << "Using existing WebRtcAudioRenderer for remote WebRTC track.";
+ } else {
+ DVLOG(1) << "Creating WebRtcAudioRenderer for remote WebRTC track.";
+ renderer = new WebRtcAudioRenderer(
+ GetPeerConnectionDependencyFactory()->GetWebRtcSignalingThread(),
+ web_stream, render_frame_id, GetSessionIdForWebRtcAudioRenderer(),
+ device_id, security_origin);
+
+ if (!audio_device->SetAudioRenderer(renderer.get()))
+ return nullptr;
}
- return renderer.get() ? renderer->CreateSharedAudioRendererProxy(web_stream)
- : NULL;
+ return renderer->CreateSharedAudioRendererProxy(web_stream);
}
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_track.cc b/chromium/content/renderer/media/media_stream_track.cc
index 7992e237f83..fa0cb90d266 100644
--- a/chromium/content/renderer/media/media_stream_track.cc
+++ b/chromium/content/renderer/media/media_stream_track.cc
@@ -9,8 +9,8 @@ namespace content {
// static
MediaStreamTrack* MediaStreamTrack::GetTrack(
const blink::WebMediaStreamTrack& track) {
- return track.isNull() ?
- nullptr : static_cast<MediaStreamTrack*>(track.extraData());
+ return track.isNull() ? nullptr
+ : static_cast<MediaStreamTrack*>(track.getExtraData());
}
MediaStreamTrack::MediaStreamTrack(bool is_local_track)
diff --git a/chromium/content/renderer/media/media_stream_video_capturer_source.cc b/chromium/content/renderer/media/media_stream_video_capturer_source.cc
index 59be54802d7..b080ec826df 100644
--- a/chromium/content/renderer/media/media_stream_video_capturer_source.cc
+++ b/chromium/content/renderer/media/media_stream_video_capturer_source.cc
@@ -96,14 +96,11 @@ void SetContentCaptureParamsFromConstraints(
int width = 0;
int height = 0;
gfx::Size desired_max_frame_size;
- if (GetConstraintValueAsInteger(constraints,
- MediaStreamVideoSource::kMaxWidth,
- &width) &&
- GetConstraintValueAsInteger(constraints,
- MediaStreamVideoSource::kMaxHeight,
- &height) &&
- DimensionValueIsValid(width) &&
- DimensionValueIsValid(height)) {
+ if (GetConstraintMaxAsInteger(
+ constraints, &blink::WebMediaTrackConstraintSet::width, &width) &&
+ GetConstraintMaxAsInteger(
+ constraints, &blink::WebMediaTrackConstraintSet::height, &height) &&
+ DimensionValueIsValid(width) && DimensionValueIsValid(height)) {
desired_max_frame_size.SetSize(width, height);
if (params->requested_format.frame_size.IsEmpty() ||
desired_max_frame_size.width() <
@@ -124,9 +121,9 @@ void SetContentCaptureParamsFromConstraints(
// If the maximum frame rate was provided, use it if either: 1) none has been
// set yet; or 2) the maximum specificed is smaller than the current setting.
double frame_rate = 0.0;
- if (GetConstraintValueAsDouble(constraints,
- MediaStreamVideoSource::kMaxFrameRate,
- &frame_rate) &&
+ if (GetConstraintMaxAsDouble(constraints,
+ &blink::WebMediaTrackConstraintSet::frameRate,
+ &frame_rate) &&
FrameRateValueIsValid(frame_rate)) {
if (params->requested_format.frame_rate <= 0.0f ||
frame_rate < params->requested_format.frame_rate) {
@@ -143,12 +140,10 @@ void SetContentCaptureParamsFromConstraints(
// If the minimum frame resolution was provided, compare it to the maximum
// frame resolution to determine the intended resolution change policy.
if (!desired_max_frame_size.IsEmpty() &&
- GetConstraintValueAsInteger(constraints,
- MediaStreamVideoSource::kMinWidth,
- &width) &&
- GetConstraintValueAsInteger(constraints,
- MediaStreamVideoSource::kMinHeight,
- &height) &&
+ GetConstraintMinAsInteger(
+ constraints, &blink::WebMediaTrackConstraintSet::width, &width) &&
+ GetConstraintMinAsInteger(
+ constraints, &blink::WebMediaTrackConstraintSet::height, &height) &&
width <= desired_max_frame_size.width() &&
height <= desired_max_frame_size.height()) {
if (width == desired_max_frame_size.width() &&
@@ -186,8 +181,9 @@ void SetPowerLineFrequencyParamFromConstraints(
media::VideoCaptureParams* params) {
int freq;
params->power_line_frequency = media::PowerLineFrequency::FREQUENCY_DEFAULT;
- if (!GetOptionalConstraintValueAsInteger(constraints, kPowerLineFrequency,
- &freq)) {
+ if (!GetConstraintValueAsInteger(
+ constraints,
+ &blink::WebMediaTrackConstraintSet::googPowerLineFrequency, &freq)) {
return;
}
if (freq == static_cast<int>(media::PowerLineFrequency::FREQUENCY_50HZ))
@@ -214,6 +210,7 @@ class LocalVideoCapturerSource final : public media::VideoCapturerSource {
void StartCapture(const media::VideoCaptureParams& params,
const VideoCaptureDeliverFrameCB& new_frame_callback,
const RunningCallback& running_callback) override;
+ void RequestRefreshFrame() override;
void StopCapture() override;
private:
@@ -313,6 +310,15 @@ void LocalVideoCapturerSource::StartCapture(
new_frame_callback);
}
+void LocalVideoCapturerSource::RequestRefreshFrame() {
+ DVLOG(3) << __FUNCTION__;
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (stop_capture_cb_.is_null())
+ return; // Do not request frames if the source is stopped.
+ manager_->RequestRefreshFrame(session_id_);
+}
+
+
void LocalVideoCapturerSource::StopCapture() {
DVLOG(3) << __FUNCTION__;
DCHECK(thread_checker_.CalledOnValidThread());
@@ -386,7 +392,7 @@ void LocalVideoCapturerSource::OnDeviceSupportedFormatsEnumerated(
MediaStreamVideoCapturerSource::MediaStreamVideoCapturerSource(
const SourceStoppedCallback& stop_callback,
- scoped_ptr<media::VideoCapturerSource> source)
+ std::unique_ptr<media::VideoCapturerSource> source)
: source_(std::move(source)) {
SetStopCallback(stop_callback);
}
@@ -402,6 +408,10 @@ MediaStreamVideoCapturerSource::MediaStreamVideoCapturerSource(
MediaStreamVideoCapturerSource::~MediaStreamVideoCapturerSource() {
}
+void MediaStreamVideoCapturerSource::RequestRefreshFrame() {
+ source_->RequestRefreshFrame();
+}
+
void MediaStreamVideoCapturerSource::GetCurrentSupportedFormats(
int max_requested_width,
int max_requested_height,
diff --git a/chromium/content/renderer/media/media_stream_video_capturer_source.h b/chromium/content/renderer/media/media_stream_video_capturer_source.h
index 9dc7b1fb9f1..2d79f944b84 100644
--- a/chromium/content/renderer/media/media_stream_video_capturer_source.h
+++ b/chromium/content/renderer/media/media_stream_video_capturer_source.h
@@ -25,12 +25,16 @@ namespace content {
class CONTENT_EXPORT MediaStreamVideoCapturerSource
: public MediaStreamVideoSource {
public:
- MediaStreamVideoCapturerSource(const SourceStoppedCallback& stop_callback,
- scoped_ptr<media::VideoCapturerSource> source);
+ MediaStreamVideoCapturerSource(
+ const SourceStoppedCallback& stop_callback,
+ std::unique_ptr<media::VideoCapturerSource> source);
MediaStreamVideoCapturerSource(const SourceStoppedCallback& stop_callback,
const StreamDeviceInfo& device_info);
~MediaStreamVideoCapturerSource() override;
+ // Implements MediaStreamVideoSource.
+ void RequestRefreshFrame() override;
+
private:
friend class CanvasCaptureHandlerTest;
friend class MediaStreamVideoCapturerSourceTest;
@@ -53,7 +57,7 @@ class CONTENT_EXPORT MediaStreamVideoCapturerSource
const char* GetPowerLineFrequencyForTesting() const;
// The source that provides video frames.
- const scoped_ptr<media::VideoCapturerSource> source_;
+ const std::unique_ptr<media::VideoCapturerSource> source_;
DISALLOW_COPY_AND_ASSIGN(MediaStreamVideoCapturerSource);
};
diff --git a/chromium/content/renderer/media/media_stream_video_capturer_source_unittest.cc b/chromium/content/renderer/media/media_stream_video_capturer_source_unittest.cc
index b26d74d5869..2161443dfcd 100644
--- a/chromium/content/renderer/media/media_stream_video_capturer_source_unittest.cc
+++ b/chromium/content/renderer/media/media_stream_video_capturer_source_unittest.cc
@@ -15,7 +15,7 @@
#include "content/child/child_process.h"
#include "content/public/renderer/media_stream_video_sink.h"
#include "content/renderer/media/media_stream_video_track.h"
-#include "content/renderer/media/mock_media_constraint_factory.h"
+#include "content/renderer/media/mock_constraint_factory.h"
#include "media/base/bind_to_current_loop.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -36,6 +36,7 @@ class MockVideoCapturerSource : public media::VideoCapturerSource {
Invoke(this, &MockVideoCapturerSource::EnumerateDeviceFormats)));
}
+ MOCK_METHOD0(RequestRefreshFrame, void());
MOCK_METHOD4(GetCurrentSupportedFormats,
void(int max_requested_width,
int max_requested_height,
@@ -73,7 +74,8 @@ class MediaStreamVideoCapturerSourceTest : public testing::Test {
}
void InitWithDeviceInfo(const StreamDeviceInfo& device_info) {
- scoped_ptr<MockVideoCapturerSource> delegate(new MockVideoCapturerSource());
+ std::unique_ptr<MockVideoCapturerSource> delegate(
+ new MockVideoCapturerSource());
delegate_ = delegate.get();
source_ = new MediaStreamVideoCapturerSource(
base::Bind(&MediaStreamVideoCapturerSourceTest::OnSourceStopped,
@@ -90,9 +92,7 @@ class MediaStreamVideoCapturerSourceTest : public testing::Test {
webkit_source_id_ = webkit_source_.id();
}
- MockMediaConstraintFactory* constraint_factory() {
- return &constraint_factory_;
- }
+ MockConstraintFactory* constraint_factory() { return &constraint_factory_; }
blink::WebMediaStreamTrack StartSource() {
bool enabled = true;
@@ -124,14 +124,14 @@ class MediaStreamVideoCapturerSourceTest : public testing::Test {
// A ChildProcess and a MessageLoopForUI are both needed to fool the Tracks
// and Sources below into believing they are on the right threads.
base::MessageLoopForUI message_loop_;
- scoped_ptr<ChildProcess> child_process_;
+ std::unique_ptr<ChildProcess> child_process_;
blink::WebMediaStreamSource webkit_source_;
MediaStreamVideoCapturerSource* source_; // owned by |webkit_source_|.
MockVideoCapturerSource* delegate_; // owned by |source|.
blink::WebString webkit_source_id_;
bool source_stopped_;
- MockMediaConstraintFactory constraint_factory_;
+ MockConstraintFactory constraint_factory_;
};
TEST_F(MediaStreamVideoCapturerSourceTest, TabCaptureFixedResolutionByDefault) {
@@ -192,12 +192,11 @@ TEST_F(MediaStreamVideoCapturerSourceTest,
InitWithDeviceInfo(device_info);
// Specify max and min size constraints that have the same ~16:9 aspect ratio.
- constraint_factory()->AddMandatory(MediaStreamVideoSource::kMaxWidth, 1920);
- constraint_factory()->AddMandatory(MediaStreamVideoSource::kMaxHeight, 1080);
- constraint_factory()->AddMandatory(MediaStreamVideoSource::kMinWidth, 854);
- constraint_factory()->AddMandatory(MediaStreamVideoSource::kMinHeight, 480);
- constraint_factory()->AddMandatory(MediaStreamVideoSource::kMaxFrameRate,
- 60.0);
+ constraint_factory()->basic().width.setMax(1920);
+ constraint_factory()->basic().height.setMax(1080);
+ constraint_factory()->basic().width.setMin(854);
+ constraint_factory()->basic().height.setMin(480);
+ constraint_factory()->basic().frameRate.setMax(60.0);
media::VideoCaptureParams expected_params;
expected_params.requested_format.frame_size.SetSize(1920, 1080);
@@ -226,12 +225,11 @@ TEST_F(MediaStreamVideoCapturerSourceTest,
InitWithDeviceInfo(device_info);
// Specify max and min size constraints with different aspect ratios.
- constraint_factory()->AddMandatory(MediaStreamVideoSource::kMaxWidth, 1920);
- constraint_factory()->AddMandatory(MediaStreamVideoSource::kMaxHeight, 1080);
- constraint_factory()->AddMandatory(MediaStreamVideoSource::kMinWidth, 0);
- constraint_factory()->AddMandatory(MediaStreamVideoSource::kMinHeight, 0);
- constraint_factory()->AddMandatory(MediaStreamVideoSource::kMaxFrameRate,
- 60.0);
+ constraint_factory()->basic().width.setMax(1920);
+ constraint_factory()->basic().height.setMax(1080);
+ constraint_factory()->basic().width.setMin(0);
+ constraint_factory()->basic().height.setMin(0);
+ constraint_factory()->basic().frameRate.setMax(60.0);
media::VideoCaptureParams expected_params;
expected_params.requested_format.frame_size.SetSize(1920, 1080);
@@ -259,10 +257,10 @@ TEST_F(MediaStreamVideoCapturerSourceTest,
StreamDeviceInfo device_info;
device_info.device.type = MEDIA_DEVICE_VIDEO_CAPTURE;
InitWithDeviceInfo(device_info);
- constraint_factory_ = MockMediaConstraintFactory();
+ constraint_factory_.Reset();
- constraint_factory()->AddOptional(GetPowerLineFrequencyForTesting(),
- frequency);
+ constraint_factory()->AddAdvanced().googPowerLineFrequency.setExact(
+ frequency);
media::VideoCaptureParams expected_params;
expected_params.requested_format.frame_size.SetSize(
@@ -293,40 +291,9 @@ TEST_F(MediaStreamVideoCapturerSourceTest,
}
}
-TEST_F(MediaStreamVideoCapturerSourceTest,
- InvalidPowerLineFrequencyHandledProperly) {
- // Test out other varieties of invalid input, like non-numeric strings.
- StreamDeviceInfo device_info;
- device_info.device.type = MEDIA_DEVICE_VIDEO_CAPTURE;
- InitWithDeviceInfo(device_info);
- constraint_factory_ = MockMediaConstraintFactory();
-
- constraint_factory()->AddOptional(GetPowerLineFrequencyForTesting(),
- std::string("this is not a frequency"));
-
- media::VideoCaptureParams expected_params;
- expected_params.requested_format.frame_size.SetSize(
- MediaStreamVideoSource::kDefaultWidth,
- MediaStreamVideoSource::kDefaultHeight);
- expected_params.requested_format.frame_rate =
- MediaStreamVideoSource::kDefaultFrameRate;
- expected_params.requested_format.pixel_format = media::PIXEL_FORMAT_I420;
- expected_params.resolution_change_policy =
- media::RESOLUTION_POLICY_FIXED_RESOLUTION;
- // Invalid frequencies should result in default setting.
- expected_params.power_line_frequency =
- media::PowerLineFrequency::FREQUENCY_DEFAULT;
-
- InSequence s;
- EXPECT_CALL(mock_delegate(), GetCurrentSupportedFormats(_, _, _, _));
- EXPECT_CALL(mock_delegate(), StartCapture(expected_params, _, _));
- blink::WebMediaStreamTrack track = StartSource();
- // When the track goes out of scope, the source will be stopped.
- EXPECT_CALL(mock_delegate(), StopCapture());
-}
-
TEST_F(MediaStreamVideoCapturerSourceTest, Ended) {
- scoped_ptr<MockVideoCapturerSource> delegate(new MockVideoCapturerSource());
+ std::unique_ptr<MockVideoCapturerSource> delegate(
+ new MockVideoCapturerSource());
delegate_ = delegate.get();
source_ = new MediaStreamVideoCapturerSource(
base::Bind(&MediaStreamVideoCapturerSourceTest::OnSourceStopped,
@@ -348,7 +315,7 @@ TEST_F(MediaStreamVideoCapturerSourceTest, Ended) {
OnStarted(true);
message_loop_.RunUntilIdle();
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive,
- webkit_source_.readyState());
+ webkit_source_.getReadyState());
EXPECT_FALSE(source_stopped_);
@@ -356,7 +323,7 @@ TEST_F(MediaStreamVideoCapturerSourceTest, Ended) {
OnStarted(false);
message_loop_.RunUntilIdle();
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded,
- webkit_source_.readyState());
+ webkit_source_.getReadyState());
// Verify that MediaStreamSource::SourceStoppedCallback has been triggered.
EXPECT_TRUE(source_stopped_);
}
@@ -370,6 +337,17 @@ class FakeMediaStreamVideoSink : public MediaStreamVideoSink {
metadata_(metadata),
got_frame_cb_(got_frame_cb) {}
+ void ConnectToTrack(const blink::WebMediaStreamTrack& track) {
+ MediaStreamVideoSink::ConnectToTrack(
+ track,
+ base::Bind(&FakeMediaStreamVideoSink::OnVideoFrame,
+ base::Unretained(this)));
+ }
+
+ void DisconnectFromTrack() {
+ MediaStreamVideoSink::DisconnectFromTrack();
+ }
+
void OnVideoFrame(const scoped_refptr<media::VideoFrame>& frame,
base::TimeTicks capture_time) {
*capture_time_ = capture_time;
@@ -399,6 +377,7 @@ TEST_F(MediaStreamVideoCapturerSourceTest, CaptureTimeAndMetadataPlumbing) {
EXPECT_CALL(mock_delegate(), StartCapture(_, _, _))
.WillOnce(testing::DoAll(testing::SaveArg<1>(&deliver_frame_cb),
testing::SaveArg<2>(&running_cb)));
+ EXPECT_CALL(mock_delegate(), RequestRefreshFrame());
EXPECT_CALL(mock_delegate(), StopCapture());
blink::WebMediaStreamTrack track = StartSource();
running_cb.Run(true);
@@ -411,17 +390,14 @@ TEST_F(MediaStreamVideoCapturerSourceTest, CaptureTimeAndMetadataPlumbing) {
FakeMediaStreamVideoSink fake_sink(
&capture_time, &metadata,
media::BindToCurrentLoop(run_loop.QuitClosure()));
- FakeMediaStreamVideoSink::AddToVideoTrack(
- &fake_sink, base::Bind(&FakeMediaStreamVideoSink::OnVideoFrame,
- base::Unretained(&fake_sink)),
- track);
+ fake_sink.ConnectToTrack(track);
const scoped_refptr<media::VideoFrame> frame =
media::VideoFrame::CreateBlackFrame(gfx::Size(2, 2));
frame->metadata()->SetDouble(media::VideoFrameMetadata::FRAME_RATE, 30.0);
child_process_->io_task_runner()->PostTask(
FROM_HERE, base::Bind(deliver_frame_cb, frame, reference_capture_time));
run_loop.Run();
- FakeMediaStreamVideoSink::RemoveFromVideoTrack(&fake_sink, track);
+ fake_sink.DisconnectFromTrack();
EXPECT_EQ(reference_capture_time, capture_time);
double metadata_value;
EXPECT_TRUE(metadata.GetDouble(media::VideoFrameMetadata::FRAME_RATE,
diff --git a/chromium/content/renderer/media/media_stream_video_renderer_sink.cc b/chromium/content/renderer/media/media_stream_video_renderer_sink.cc
index 6fff1d9c81f..8e9eccd33f8 100644
--- a/chromium/content/renderer/media/media_stream_video_renderer_sink.cc
+++ b/chromium/content/renderer/media/media_stream_video_renderer_sink.cc
@@ -50,16 +50,14 @@ void MediaStreamVideoRendererSink::Start() {
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK_EQ(state_, STOPPED);
- AddToVideoTrack(
- this,
+ MediaStreamVideoSink::ConnectToTrack(video_track_,
media::BindToCurrentLoop(
base::Bind(
&MediaStreamVideoRendererSink::OnVideoFrame,
- weak_factory_.GetWeakPtr())),
- video_track_);
+ weak_factory_.GetWeakPtr())));
state_ = STARTED;
- if (video_track_.source().readyState() ==
+ if (video_track_.source().getReadyState() ==
blink::WebMediaStreamSource::ReadyStateEnded ||
!video_track_.isEnabled()) {
RenderSignalingFrame();
@@ -69,7 +67,7 @@ void MediaStreamVideoRendererSink::Start() {
void MediaStreamVideoRendererSink::Stop() {
DCHECK(task_runner_->BelongsToCurrentThread());
DCHECK(state_ == STARTED || state_ == PAUSED);
- RemoveFromVideoTrack(this, video_track_);
+ MediaStreamVideoSink::DisconnectFromTrack();
weak_factory_.InvalidateWeakPtrs();
state_ = STOPPED;
frame_size_.set_width(kMinFrameSize);
diff --git a/chromium/content/renderer/media/media_stream_video_renderer_sink.h b/chromium/content/renderer/media/media_stream_video_renderer_sink.h
index ad3c9eb6698..d858062a453 100644
--- a/chromium/content/renderer/media/media_stream_video_renderer_sink.h
+++ b/chromium/content/renderer/media/media_stream_video_renderer_sink.h
@@ -30,9 +30,9 @@ namespace content {
// MediaStreamVideoRendererSink is a VideoFrameProvider designed for rendering
// Video MediaStreamTracks [1], MediaStreamVideoRendererSink implements
// MediaStreamVideoSink in order to render video frames provided from a
-// MediaStreamVideoTrack, to which it AddToVideoTrack()s itself when the
-// VideoFrameProvider is Start()ed and RemoveFromVideoTrack()s itself when the
-// latter is Stop()ed.
+// MediaStreamVideoTrack, to which it connects itself when the
+// VideoFrameProvider is Start()ed, and disconnects itself when the latter is
+// Stop()ed.
//
// [1] http://dev.w3.org/2011/webrtc/editor/getusermedia.html#mediastreamtrack
//
@@ -89,7 +89,7 @@ class CONTENT_EXPORT MediaStreamVideoRendererSink
const blink::WebMediaStreamTrack video_track_;
// Pool of GpuMemoryBuffers and resources used to create hardware frames.
- scoped_ptr<media::GpuMemoryBufferVideoFramePool> gpu_memory_buffer_pool_;
+ std::unique_ptr<media::GpuMemoryBufferVideoFramePool> gpu_memory_buffer_pool_;
const scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
base::WeakPtrFactory<MediaStreamVideoRendererSink> weak_factory_;
diff --git a/chromium/content/renderer/media/media_stream_video_renderer_sink_unittest.cc b/chromium/content/renderer/media/media_stream_video_renderer_sink_unittest.cc
index 32b23e39ab5..77edaf85ce1 100644
--- a/chromium/content/renderer/media/media_stream_video_renderer_sink_unittest.cc
+++ b/chromium/content/renderer/media/media_stream_video_renderer_sink_unittest.cc
@@ -39,12 +39,11 @@ class MediaStreamVideoRendererSinkTest : public testing::Test {
registry_.AddVideoTrack(kTestVideoTrackId);
// Extract the Blink Video Track for the MSVRSink.
- blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
- registry_.test_stream().videoTracks(video_tracks);
- EXPECT_EQ(1u, video_tracks.size());
+ registry_.test_stream().videoTracks(video_tracks_);
+ EXPECT_EQ(1u, video_tracks_.size());
media_stream_video_renderer_sink_ = new MediaStreamVideoRendererSink(
- video_tracks[0],
+ video_tracks_[0],
base::Bind(&MediaStreamVideoRendererSinkTest::ErrorCallback,
base::Unretained(this)),
base::Bind(&MediaStreamVideoRendererSinkTest::RepaintCallback,
@@ -91,6 +90,8 @@ class MediaStreamVideoRendererSinkTest : public testing::Test {
// and Sources in |registry_| into believing they are on the right threads.
base::MessageLoopForUI message_loop_;
const ChildProcess child_process_;
+
+ blink::WebVector<blink::WebMediaStreamTrack> video_tracks_;
MockMediaStreamRegistry registry_;
private:
@@ -158,4 +159,40 @@ TEST_F(MediaStreamVideoRendererSinkAsyncAddFrameReadyTest,
media_stream_video_renderer_sink_->Stop();
}
+class MediaStreamVideoRendererSinkTransparencyTest
+ : public MediaStreamVideoRendererSinkTest {
+ public:
+ MediaStreamVideoRendererSinkTransparencyTest() {
+ media_stream_video_renderer_sink_ = new MediaStreamVideoRendererSink(
+ video_tracks_[0],
+ base::Bind(&MediaStreamVideoRendererSinkTest::ErrorCallback,
+ base::Unretained(this)),
+ base::Bind(&MediaStreamVideoRendererSinkTransparencyTest::
+ VerifyTransparentFrame,
+ base::Unretained(this)),
+ message_loop_.task_runner(), message_loop_.task_runner().get(),
+ nullptr /* gpu_factories */);
+ }
+
+ void VerifyTransparentFrame(const scoped_refptr<media::VideoFrame>& frame) {
+ EXPECT_EQ(media::PIXEL_FORMAT_YV12A, frame->format());
+ }
+};
+
+TEST_F(MediaStreamVideoRendererSinkTransparencyTest,
+ SendTransparentFrame) {
+ media_stream_video_renderer_sink_->Start();
+
+ InSequence s;
+ const gfx::Size kSize(10, 10);
+ const base::TimeDelta kTimestamp = base::TimeDelta();
+ const scoped_refptr<media::VideoFrame> video_frame =
+ media::VideoFrame::CreateFrame(media::PIXEL_FORMAT_YV12A, kSize,
+ gfx::Rect(kSize), kSize, kTimestamp);
+ OnVideoFrame(video_frame);
+ message_loop_.RunUntilIdle();
+
+ media_stream_video_renderer_sink_->Stop();
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_video_source.cc b/chromium/content/renderer/media/media_stream_video_source.cc
index 38f19b0d301..c40638c8293 100644
--- a/chromium/content/renderer/media/media_stream_video_source.cc
+++ b/chromium/content/renderer/media/media_stream_video_source.cc
@@ -13,7 +13,6 @@
#include "base/strings/string_number_conversions.h"
#include "base/trace_event/trace_event.h"
#include "content/child/child_process.h"
-#include "content/renderer/media/media_stream_constraints_util.h"
#include "content/renderer/media/media_stream_video_track.h"
#include "content/renderer/media/video_track_adapter.h"
@@ -43,15 +42,14 @@ const char* kSupportedConstraints[] = {
namespace {
-// Google-specific key prefix. Constraints with this prefix are ignored if they
-// are unknown.
-const char kGooglePrefix[] = "goog";
+const char* kLegalVideoConstraints[] = {
+ "width", "height", "aspectRatio", "frameRate",
+ "facingMode", "deviceId", "groupId", "mediaStreamSource",
+};
// Returns true if |constraint| has mandatory constraints.
bool HasMandatoryConstraints(const blink::WebMediaConstraints& constraints) {
- blink::WebVector<blink::WebMediaConstraint> mandatory_constraints;
- constraints.getMandatoryConstraints(mandatory_constraints);
- return !mandatory_constraints.isEmpty();
+ return constraints.basic().hasMandatory();
}
// Retrieve the desired max width and height from |constraints|. If not set,
@@ -64,23 +62,21 @@ void GetDesiredMaxWidthAndHeight(const blink::WebMediaConstraints& constraints,
*desired_width = std::numeric_limits<int>::max();
*desired_height = std::numeric_limits<int>::max();
- bool mandatory = GetMandatoryConstraintValueAsInteger(
- constraints,
- MediaStreamVideoSource::kMaxWidth,
- desired_width);
- mandatory |= GetMandatoryConstraintValueAsInteger(
- constraints,
- MediaStreamVideoSource::kMaxHeight,
- desired_height);
- if (mandatory)
+ const auto& basic_constraints = constraints.basic();
+ if (basic_constraints.width.hasMax() || basic_constraints.height.hasMax()) {
+ if (basic_constraints.width.hasMax())
+ *desired_width = basic_constraints.width.max();
+ if (basic_constraints.height.hasMax())
+ *desired_height = basic_constraints.height.max();
return;
+ }
- GetOptionalConstraintValueAsInteger(constraints,
- MediaStreamVideoSource::kMaxWidth,
- desired_width);
- GetOptionalConstraintValueAsInteger(constraints,
- MediaStreamVideoSource::kMaxHeight,
- desired_height);
+ for (const auto& constraint_set : constraints.advanced()) {
+ if (constraint_set.width.hasMax())
+ *desired_width = constraint_set.width.max();
+ if (constraint_set.height.hasMax())
+ *desired_height = constraint_set.height.max();
+ }
}
// Retrieve the desired max and min aspect ratio from |constraints|. If not set,
@@ -95,128 +91,119 @@ void GetDesiredMinAndMaxAspectRatio(
*min_aspect_ratio = 0;
*max_aspect_ratio = std::numeric_limits<double>::max();
- bool mandatory = GetMandatoryConstraintValueAsDouble(
- constraints,
- MediaStreamVideoSource::kMinAspectRatio,
- min_aspect_ratio);
- mandatory |= GetMandatoryConstraintValueAsDouble(
- constraints,
- MediaStreamVideoSource::kMaxAspectRatio,
- max_aspect_ratio);
- if (mandatory)
+ if (constraints.basic().aspectRatio.hasMin() ||
+ constraints.basic().aspectRatio.hasMax()) {
+ if (constraints.basic().aspectRatio.hasMin())
+ *min_aspect_ratio = constraints.basic().aspectRatio.min();
+ if (constraints.basic().aspectRatio.hasMax())
+ *max_aspect_ratio = constraints.basic().aspectRatio.max();
return;
-
- GetOptionalConstraintValueAsDouble(constraints,
- MediaStreamVideoSource::kMinAspectRatio,
- min_aspect_ratio);
- GetOptionalConstraintValueAsDouble(constraints,
- MediaStreamVideoSource::kMaxAspectRatio,
- max_aspect_ratio);
+ // Note - the code will ignore attempts at successive refinement
+ // of the aspect ratio with advanced constraint. This may be wrong.
+ }
+ // Note - the code below will potentially pick min and max from different
+ // constraint sets, some of which might have been ignored.
+ for (const auto& constraint_set : constraints.advanced()) {
+ if (constraint_set.aspectRatio.hasMin()) {
+ *min_aspect_ratio = constraint_set.aspectRatio.min();
+ break;
+ }
+ }
+ for (const auto& constraint_set : constraints.advanced()) {
+ if (constraint_set.aspectRatio.hasMax()) {
+ *max_aspect_ratio = constraint_set.aspectRatio.max();
+ break;
+ }
+ }
}
-// Returns true if |constraint| is fulfilled. |format| can be changed by a
+// Returns true if |constraints| are fulfilled. |format| can be changed by a
// constraint, e.g. the frame rate can be changed by setting maxFrameRate.
-bool UpdateFormatForConstraint(const blink::WebMediaConstraint& constraint,
- bool mandatory,
- media::VideoCaptureFormat* format) {
+bool UpdateFormatForConstraints(
+ const blink::WebMediaTrackConstraintSet& constraints,
+ media::VideoCaptureFormat* format,
+ std::string* failing_constraint_name) {
DCHECK(format != NULL);
if (!format->IsValid())
return false;
- const std::string constraint_name = constraint.m_name.utf8();
- const std::string constraint_value = constraint.m_value.utf8();
-
- if (constraint_name.find(kGooglePrefix) == 0) {
- // These are actually options, not constraints, so they can be satisfied
- // regardless of the format.
- return true;
- }
-
- if (constraint_name == MediaStreamSource::kSourceId) {
- // This is a constraint that doesn't affect the format.
- return true;
- }
-
- // Ignore Chrome specific Tab capture constraints.
- if (constraint_name == kMediaStreamSource ||
- constraint_name == kMediaStreamSourceId)
- return true;
-
- if (constraint_name == MediaStreamVideoSource::kMinAspectRatio ||
- constraint_name == MediaStreamVideoSource::kMaxAspectRatio) {
- // These constraints are handled by cropping if the camera outputs the wrong
- // aspect ratio.
- double value;
- return base::StringToDouble(constraint_value, &value);
- }
-
- double value = 0.0;
- if (!base::StringToDouble(constraint_value, &value)) {
- DLOG(WARNING) << "Can't parse MediaStream constraint. Name:"
- << constraint_name << " Value:" << constraint_value;
- return false;
- }
-
- if (constraint_name == MediaStreamVideoSource::kMinWidth) {
- return (value <= format->frame_size.width());
- } else if (constraint_name == MediaStreamVideoSource::kMaxWidth) {
- return value > 0.0;
- } else if (constraint_name == MediaStreamVideoSource::kMinHeight) {
- return (value <= format->frame_size.height());
- } else if (constraint_name == MediaStreamVideoSource::kMaxHeight) {
- return value > 0.0;
- } else if (constraint_name == MediaStreamVideoSource::kMinFrameRate) {
- return (value > 0.0) && (value <= format->frame_rate);
- } else if (constraint_name == MediaStreamVideoSource::kMaxFrameRate) {
- if (value <= 0.0) {
- // The frame rate is set by constraint.
- // Don't allow 0 as frame rate if it is a mandatory constraint.
- // Set the frame rate to 1 if it is not mandatory.
- if (mandatory) {
- return false;
- } else {
- value = 1.0;
+ // The width and height are matched based on cropping occuring later:
+ // min width/height has to be >= the size of the frame (no upscale).
+ // max width/height just has to be > 0 (we can crop anything too large).
+ if ((constraints.width.hasMin() &&
+ constraints.width.min() > format->frame_size.width()) ||
+ (constraints.width.hasMax() && constraints.width.max() <= 0)) {
+ *failing_constraint_name = constraints.width.name();
+ } else if ((constraints.height.hasMin() &&
+ constraints.height.min() > format->frame_size.height()) ||
+ (constraints.height.hasMax() && constraints.height.max() <= 0)) {
+ *failing_constraint_name = constraints.height.name();
+ } else if (!constraints.frameRate.matches(format->frame_rate)) {
+ if (constraints.frameRate.hasMax()) {
+ const double value = constraints.frameRate.max();
+ // TODO(hta): Check if handling of max = 0.0 is relevant.
+ // (old handling was to set rate to 1.0 if 0.0 was specified)
+ if (constraints.frameRate.matches(value)) {
+ format->frame_rate =
+ (format->frame_rate > value) ? value : format->frame_rate;
+ return true;
}
}
- format->frame_rate =
- (format->frame_rate > value) ? value : format->frame_rate;
- return true;
+ *failing_constraint_name = constraints.frameRate.name();
} else {
- LOG(WARNING) << "Found unknown MediaStream constraint. Name:"
- << constraint_name << " Value:" << constraint_value;
- return false;
+ return true;
}
+
+ DCHECK(!failing_constraint_name->empty());
+ return false;
}
// Removes media::VideoCaptureFormats from |formats| that don't meet
-// |constraint|.
-void FilterFormatsByConstraint(const blink::WebMediaConstraint& constraint,
- bool mandatory,
- media::VideoCaptureFormats* formats) {
- DVLOG(3) << "FilterFormatsByConstraint("
- << "{ constraint.m_name = " << constraint.m_name.utf8()
- << " constraint.m_value = " << constraint.m_value.utf8()
- << " mandatory = " << mandatory << "})";
+// |constraints|.
+void FilterFormatsByConstraints(
+ const blink::WebMediaTrackConstraintSet& constraints,
+ media::VideoCaptureFormats* formats,
+ std::string* failing_constraint_name) {
media::VideoCaptureFormats::iterator format_it = formats->begin();
while (format_it != formats->end()) {
- // Modify the format_it to fulfill the constraint if possible.
+ // Modify |format_it| to fulfill the constraint if possible.
// Delete it otherwise.
- if (!UpdateFormatForConstraint(constraint, mandatory, &(*format_it)))
+ if (!UpdateFormatForConstraints(constraints, &(*format_it),
+ failing_constraint_name)) {
format_it = formats->erase(format_it);
- else
+ } else {
++format_it;
+ }
}
}
// Returns the media::VideoCaptureFormats that matches |constraints|.
+// If the return value is empty, and the reason is a specific constraint,
+// |unsatisfied_constraint| returns the name of the constraint.
media::VideoCaptureFormats FilterFormats(
const blink::WebMediaConstraints& constraints,
const media::VideoCaptureFormats& supported_formats,
- blink::WebString* unsatisfied_constraint) {
+ std::string* unsatisfied_constraint) {
if (constraints.isNull())
return supported_formats;
+ const auto& basic = constraints.basic();
+
+ // Do some checks that won't be done when filtering candidates.
+
+ if (basic.width.hasMin() && basic.width.hasMax() &&
+ basic.width.min() > basic.width.max()) {
+ *unsatisfied_constraint = basic.width.name();
+ return media::VideoCaptureFormats();
+ }
+
+ if (basic.height.hasMin() && basic.height.hasMax() &&
+ basic.height.min() > basic.height.max()) {
+ *unsatisfied_constraint = basic.height.name();
+ return media::VideoCaptureFormats();
+ }
+
double max_aspect_ratio;
double min_aspect_ratio;
GetDesiredMinAndMaxAspectRatio(constraints,
@@ -224,64 +211,39 @@ media::VideoCaptureFormats FilterFormats(
&max_aspect_ratio);
if (min_aspect_ratio > max_aspect_ratio || max_aspect_ratio < 0.05f) {
- DLOG(WARNING) << "Wrong requested aspect ratio.";
+ DLOG(WARNING) << "Wrong requested aspect ratio: min " << min_aspect_ratio
+ << " max " << max_aspect_ratio;
+ *unsatisfied_constraint = basic.aspectRatio.name();
return media::VideoCaptureFormats();
}
- int min_width = 0;
- GetMandatoryConstraintValueAsInteger(constraints,
- MediaStreamVideoSource::kMinWidth,
- &min_width);
- int min_height = 0;
- GetMandatoryConstraintValueAsInteger(constraints,
- MediaStreamVideoSource::kMinHeight,
- &min_height);
- int max_width;
- int max_height;
- GetDesiredMaxWidthAndHeight(constraints, &max_width, &max_height);
-
- if (min_width > max_width || min_height > max_height)
+ std::vector<std::string> temp(
+ &kLegalVideoConstraints[0],
+ &kLegalVideoConstraints[sizeof(kLegalVideoConstraints) /
+ sizeof(kLegalVideoConstraints[0])]);
+ std::string failing_name;
+ if (basic.hasMandatoryOutsideSet(temp, failing_name)) {
+ *unsatisfied_constraint = failing_name;
return media::VideoCaptureFormats();
-
- double min_frame_rate = 0.0f;
- double max_frame_rate = 0.0f;
- if (GetConstraintValueAsDouble(constraints,
- MediaStreamVideoSource::kMaxFrameRate,
- &max_frame_rate) &&
- GetConstraintValueAsDouble(constraints,
- MediaStreamVideoSource::kMinFrameRate,
- &min_frame_rate)) {
- if (min_frame_rate > max_frame_rate) {
- DLOG(WARNING) << "Wrong requested frame rate.";
- return media::VideoCaptureFormats();
- }
}
- blink::WebVector<blink::WebMediaConstraint> mandatory;
- blink::WebVector<blink::WebMediaConstraint> optional;
- constraints.getMandatoryConstraints(mandatory);
- constraints.getOptionalConstraints(optional);
media::VideoCaptureFormats candidates = supported_formats;
- for (const auto& constraint : mandatory) {
- FilterFormatsByConstraint(constraint, true, &candidates);
- if (candidates.empty()) {
- *unsatisfied_constraint = constraint.m_name;
- return candidates;
- }
- }
+ FilterFormatsByConstraints(basic, &candidates, unsatisfied_constraint);
if (candidates.empty())
return candidates;
// Ok - all mandatory checked and we still have candidates.
- // Let's try filtering using the optional constraints. The optional
- // constraints must be filtered in the order they occur in |optional|.
+ // Let's try filtering using the advanced constraints. The advanced
+ // constraints must be filtered in the order they occur in |advanced|.
// But if a constraint produce zero candidates, the constraint is ignored and
// the next constraint is tested.
- // http://dev.w3.org/2011/webrtc/editor/getusermedia.html#idl-def-Constraints
- for (const auto& constraint : optional) {
+ // http://w3c.github.io/mediacapture-main/getusermedia.html#dfn-selectsettings
+ for (const auto& constraint_set : constraints.advanced()) {
media::VideoCaptureFormats current_candidates = candidates;
- FilterFormatsByConstraint(constraint, false, &current_candidates);
+ std::string unsatisfied_constraint;
+ FilterFormatsByConstraints(constraint_set, &current_candidates,
+ &unsatisfied_constraint);
if (!current_candidates.empty())
candidates = current_candidates;
}
@@ -303,6 +265,8 @@ media::VideoCaptureFormat GetBestFormatBasedOnArea(
best_format = &format;
}
}
+ DVLOG(3) << "GetBestFormatBasedOnArea chose format "
+ << media::VideoCaptureFormat::ToString(*best_format);
return *best_format;
}
@@ -334,10 +298,14 @@ media::VideoCaptureFormat GetBestCaptureFormat(
// static
MediaStreamVideoSource* MediaStreamVideoSource::GetVideoSource(
const blink::WebMediaStreamSource& source) {
- return static_cast<MediaStreamVideoSource*>(source.extraData());
+ if (source.isNull() ||
+ source.getType() != blink::WebMediaStreamSource::TypeVideo) {
+ return nullptr;
+ }
+ return static_cast<MediaStreamVideoSource*>(source.getExtraData());
}
-// static
+// static, deprecated
bool MediaStreamVideoSource::IsConstraintSupported(const std::string& name) {
return std::find(kSupportedConstraints,
kSupportedConstraints + arraysize(kSupportedConstraints),
@@ -374,16 +342,16 @@ void MediaStreamVideoSource::AddTrack(
// Tab capture and Screen capture needs the maximum requested height
// and width to decide on the resolution.
int max_requested_width = 0;
- GetMandatoryConstraintValueAsInteger(constraints, kMaxWidth,
- &max_requested_width);
+ if (constraints.basic().width.hasMax())
+ max_requested_width = constraints.basic().width.max();
int max_requested_height = 0;
- GetMandatoryConstraintValueAsInteger(constraints, kMaxHeight,
- &max_requested_height);
+ if (constraints.basic().height.hasMax())
+ max_requested_height = constraints.basic().height.max();
double max_requested_frame_rate = kDefaultFrameRate;
- GetConstraintValueAsDouble(constraints, kMaxFrameRate,
- &max_requested_frame_rate);
+ if (constraints.basic().frameRate.hasMax())
+ max_requested_frame_rate = constraints.basic().frameRate.max();
state_ = RETRIEVING_CAPABILITIES;
GetCurrentSupportedFormats(
@@ -437,6 +405,14 @@ base::SingleThreadTaskRunner* MediaStreamVideoSource::io_task_runner() const {
return track_adapter_->io_task_runner();
}
+const media::VideoCaptureFormat*
+ MediaStreamVideoSource::GetCurrentFormat() const {
+ DCHECK(CalledOnValidThread());
+ if (state_ == STARTING || state_ == STARTED)
+ return &current_format_;
+ return nullptr;
+}
+
void MediaStreamVideoSource::DoStopSource() {
DCHECK(CalledOnValidThread());
DVLOG(3) << "DoStopSource()";
@@ -459,6 +435,7 @@ void MediaStreamVideoSource::OnSupportedFormats(
&current_format_,
&fulfilled_constraints)) {
SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded);
+ DVLOG(3) << "OnSupportedFormats failed to find an usable format";
// This object can be deleted after calling FinalizeAddTrack. See comment
// in the header file.
FinalizeAddTrack();
@@ -480,7 +457,9 @@ bool MediaStreamVideoSource::FindBestFormatWithConstraints(
media::VideoCaptureFormat* best_format,
blink::WebMediaConstraints* fulfilled_constraints) {
DCHECK(CalledOnValidThread());
- // Find the first constraints that we can fulfill.
+ DVLOG(3) << "MediaStreamVideoSource::FindBestFormatWithConstraints "
+ << "with " << formats.size() << " formats";
+ // Find the first track descriptor that can fulfil the constraints.
for (const auto& track : track_descriptors_) {
const blink::WebMediaConstraints& track_constraints = track.constraints;
@@ -488,11 +467,12 @@ bool MediaStreamVideoSource::FindBestFormatWithConstraints(
// no mandatory constraints have been specified. That just means that
// we will start with whatever format is native to the source.
if (formats.empty() && !HasMandatoryConstraints(track_constraints)) {
+ DVLOG(3) << "No mandatory constraints and no formats";
*fulfilled_constraints = track_constraints;
*best_format = media::VideoCaptureFormat();
return true;
}
- blink::WebString unsatisfied_constraint;
+ std::string unsatisfied_constraint;
const media::VideoCaptureFormats filtered_formats =
FilterFormats(track_constraints, formats, &unsatisfied_constraint);
if (filtered_formats.empty())
@@ -501,8 +481,10 @@ bool MediaStreamVideoSource::FindBestFormatWithConstraints(
// A request with constraints that can be fulfilled.
*fulfilled_constraints = track_constraints;
*best_format = GetBestCaptureFormat(filtered_formats, track_constraints);
+ DVLOG(3) << "Found a track that matches the constraints";
return true;
}
+ DVLOG(3) << "No usable format found";
return false;
}
@@ -536,12 +518,14 @@ void MediaStreamVideoSource::FinalizeAddTrack() {
track_descriptors.swap(track_descriptors_);
for (const auto& track : track_descriptors) {
MediaStreamRequestResult result = MEDIA_DEVICE_OK;
- blink::WebString unsatisfied_constraint;
+ std::string unsatisfied_constraint;
if (HasMandatoryConstraints(track.constraints) &&
FilterFormats(track.constraints, formats, &unsatisfied_constraint)
.empty()) {
result = MEDIA_DEVICE_CONSTRAINT_NOT_SATISFIED;
+ DVLOG(3) << "FinalizeAddTrack() ignoring device on constraint "
+ << unsatisfied_constraint;
}
if (state_ != STARTED && result == MEDIA_DEVICE_OK)
@@ -557,8 +541,8 @@ void MediaStreamVideoSource::FinalizeAddTrack() {
&min_aspect_ratio,
&max_aspect_ratio);
double max_frame_rate = 0.0f;
- GetConstraintValueAsDouble(track.constraints,
- kMaxFrameRate, &max_frame_rate);
+ if (track.constraints.basic().frameRate.hasMax())
+ max_frame_rate = track.constraints.basic().frameRate.max();
track_adapter_->AddTrack(track.track, track.frame_callback, max_width,
max_height, min_aspect_ratio, max_aspect_ratio,
@@ -568,7 +552,8 @@ void MediaStreamVideoSource::FinalizeAddTrack() {
DVLOG(3) << "FinalizeAddTrack() result " << result;
if (!track.callback.is_null())
- track.callback.Run(this, result, unsatisfied_constraint);
+ track.callback.Run(this, result,
+ blink::WebString::fromUTF8(unsatisfied_constraint));
}
}
@@ -603,6 +588,9 @@ MediaStreamVideoSource::TrackDescriptor::TrackDescriptor(
callback(callback) {
}
+MediaStreamVideoSource::TrackDescriptor::TrackDescriptor(
+ const TrackDescriptor& other) = default;
+
MediaStreamVideoSource::TrackDescriptor::~TrackDescriptor() {
}
diff --git a/chromium/content/renderer/media/media_stream_video_source.h b/chromium/content/renderer/media/media_stream_video_source.h
index cd403750797..e2e24f008c9 100644
--- a/chromium/content/renderer/media/media_stream_video_source.h
+++ b/chromium/content/renderer/media/media_stream_video_source.h
@@ -84,9 +84,14 @@ class CONTENT_EXPORT MediaStreamVideoSource
// Return true if |name| is a constraint supported by MediaStreamVideoSource.
static bool IsConstraintSupported(const std::string& name);
+ // Request underlying source to capture a new frame.
+ virtual void RequestRefreshFrame() {}
+
// Returns the task runner where video frames will be delivered on.
base::SingleThreadTaskRunner* io_task_runner() const;
+ const media::VideoCaptureFormat* GetCurrentFormat() const;
+
protected:
void DoStopSource() override;
@@ -164,6 +169,7 @@ class CONTENT_EXPORT MediaStreamVideoSource
const VideoCaptureDeliverFrameCB& frame_callback,
const blink::WebMediaConstraints& constraints,
const ConstraintsCallback& callback);
+ TrackDescriptor(const TrackDescriptor& other);
~TrackDescriptor();
MediaStreamVideoTrack* track;
diff --git a/chromium/content/renderer/media/media_stream_video_source_unittest.cc b/chromium/content/renderer/media/media_stream_video_source_unittest.cc
index b2afab4f4ad..6b13a3edce6 100644
--- a/chromium/content/renderer/media/media_stream_video_source_unittest.cc
+++ b/chromium/content/renderer/media/media_stream_video_source_unittest.cc
@@ -13,9 +13,10 @@
#include "content/child/child_process.h"
#include "content/renderer/media/media_stream_video_source.h"
#include "content/renderer/media/media_stream_video_track.h"
-#include "content/renderer/media/mock_media_constraint_factory.h"
+#include "content/renderer/media/mock_constraint_factory.h"
#include "content/renderer/media/mock_media_stream_video_sink.h"
#include "content/renderer/media/mock_media_stream_video_source.h"
+#include "media/base/limits.h"
#include "media/base/video_frame.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/web/WebHeap.h"
@@ -121,15 +122,14 @@ class MediaStreamVideoSourceTest : public ::testing::Test {
30);
MockMediaStreamVideoSink sink;
- MediaStreamVideoSink::AddToVideoTrack(
- &sink, sink.GetDeliverFrameCB(), track);
+ sink.ConnectToTrack(track);
DeliverVideoFrameAndWaitForRenderer(capture_width, capture_height, &sink);
EXPECT_EQ(1, sink.number_of_frames());
// Expect the delivered frame to be cropped.
EXPECT_EQ(expected_height, sink.frame_size().height());
EXPECT_EQ(expected_width, sink.frame_size().width());
- MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
+ sink.DisconnectFromTrack();
}
void DeliverVideoFrameAndWaitForRenderer(int width, int height,
@@ -176,13 +176,11 @@ class MediaStreamVideoSourceTest : public ::testing::Test {
blink::WebMediaStreamTrack track2 = CreateTrack("dummy", constraints2);
MockMediaStreamVideoSink sink1;
- MediaStreamVideoSink::AddToVideoTrack(&sink1, sink1.GetDeliverFrameCB(),
- track1);
+ sink1.ConnectToTrack(track1);
EXPECT_EQ(0, sink1.number_of_frames());
MockMediaStreamVideoSink sink2;
- MediaStreamVideoSink::AddToVideoTrack(&sink2, sink2.GetDeliverFrameCB(),
- track2);
+ sink2.ConnectToTrack(track2);
EXPECT_EQ(0, sink2.number_of_frames());
DeliverVideoFrameAndWaitForTwoRenderers(capture_width,
@@ -198,8 +196,8 @@ class MediaStreamVideoSourceTest : public ::testing::Test {
EXPECT_EQ(expected_width2, sink2.frame_size().width());
EXPECT_EQ(expected_height2, sink2.frame_size().height());
- MediaStreamVideoSink::RemoveFromVideoTrack(&sink1, track1);
- MediaStreamVideoSink::RemoveFromVideoTrack(&sink2, track2);
+ sink1.DisconnectFromTrack();
+ sink2.DisconnectFromTrack();
}
void SetSourceSupportedFormats(const media::VideoCaptureFormats& formats) {
@@ -215,7 +213,7 @@ class MediaStreamVideoSourceTest : public ::testing::Test {
void OnConstraintsApplied(MediaStreamSource* source,
MediaStreamRequestResult result,
const blink::WebString& result_name) {
- ASSERT_EQ(source, webkit_source_.extraData());
+ ASSERT_EQ(source, webkit_source_.getExtraData());
if (result == MEDIA_DEVICE_OK) {
++number_of_successful_constraints_applied_;
@@ -232,7 +230,7 @@ class MediaStreamVideoSourceTest : public ::testing::Test {
}
}
const base::MessageLoopForUI message_loop_;
- const scoped_ptr<ChildProcess> child_process_;
+ const std::unique_ptr<ChildProcess> child_process_;
blink::WebMediaStreamTrack track_to_release_;
int number_of_successful_constraints_applied_;
int number_of_failed_constraints_applied_;
@@ -296,10 +294,10 @@ TEST_F(MediaStreamVideoSourceTest, AddTwoTracksBeforeGetSupportedFormats) {
// Test that the capture output is CIF if we set max constraints to CIF.
// and the capture device support CIF.
TEST_F(MediaStreamVideoSourceTest, MandatoryConstraintCif5Fps) {
- MockMediaConstraintFactory factory;
- factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, 352);
- factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, 288);
- factory.AddMandatory(MediaStreamVideoSource::kMaxFrameRate, 5);
+ MockConstraintFactory factory;
+ factory.basic().width.setMax(352);
+ factory.basic().height.setMax(288);
+ factory.basic().frameRate.setMax(5.0);
CreateTrackAndStartSource(factory.CreateWebMediaConstraints(), 352, 288, 5);
}
@@ -307,11 +305,11 @@ TEST_F(MediaStreamVideoSourceTest, MandatoryConstraintCif5Fps) {
// Test that the capture output is 720P if the camera support it and the
// optional constraint is set to 720P.
TEST_F(MediaStreamVideoSourceTest, MandatoryMinVgaOptional720P) {
- MockMediaConstraintFactory factory;
- factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 640);
- factory.AddMandatory(MediaStreamVideoSource::kMinHeight, 480);
- factory.AddOptional(MediaStreamVideoSource::kMinWidth, 1280);
- factory.AddOptional(MediaStreamVideoSource::kMinAspectRatio, 1280.0 / 720);
+ MockConstraintFactory factory;
+ factory.basic().width.setMin(640);
+ factory.basic().height.setMin(480);
+ factory.AddAdvanced().width.setMin(1280);
+ factory.AddAdvanced().aspectRatio.setMin(1280.0 / 720);
CreateTrackAndStartSource(factory.CreateWebMediaConstraints(), 1280, 720, 30);
}
@@ -320,11 +318,11 @@ TEST_F(MediaStreamVideoSourceTest, MandatoryMinVgaOptional720P) {
// require it even if an optional constraint request a higher resolution
// that don't have this aspect ratio.
TEST_F(MediaStreamVideoSourceTest, MandatoryAspectRatio4To3) {
- MockMediaConstraintFactory factory;
- factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 640);
- factory.AddMandatory(MediaStreamVideoSource::kMinHeight, 480);
- factory.AddMandatory(MediaStreamVideoSource::kMaxAspectRatio, 640.0 / 480);
- factory.AddOptional(MediaStreamVideoSource::kMinWidth, 1280);
+ MockConstraintFactory factory;
+ factory.basic().width.setMin(640);
+ factory.basic().height.setMin(480);
+ factory.basic().aspectRatio.setMax(640.0 / 480);
+ factory.AddAdvanced().width.setMin(1280);
TestSourceCropFrame(1280, 720,
factory.CreateWebMediaConstraints(), 960, 720);
@@ -332,8 +330,8 @@ TEST_F(MediaStreamVideoSourceTest, MandatoryAspectRatio4To3) {
// Test that AddTrack succeeds if the mandatory min aspect ratio it set to 2.
TEST_F(MediaStreamVideoSourceTest, MandatoryAspectRatio2) {
- MockMediaConstraintFactory factory;
- factory.AddMandatory(MediaStreamVideoSource::kMinAspectRatio, 2);
+ MockConstraintFactory factory;
+ factory.basic().aspectRatio.setMin(2.0);
TestSourceCropFrame(MediaStreamVideoSource::kDefaultWidth,
MediaStreamVideoSource::kDefaultHeight,
@@ -341,18 +339,9 @@ TEST_F(MediaStreamVideoSourceTest, MandatoryAspectRatio2) {
}
TEST_F(MediaStreamVideoSourceTest, MinAspectRatioLargerThanMaxAspectRatio) {
- MockMediaConstraintFactory factory;
- factory.AddMandatory(MediaStreamVideoSource::kMinAspectRatio, 2);
- factory.AddMandatory(MediaStreamVideoSource::kMaxAspectRatio, 1);
- blink::WebMediaStreamTrack track = CreateTrack(
- "123", factory.CreateWebMediaConstraints());
- mock_source()->CompleteGetSupportedFormats();
- EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
-}
-
-TEST_F(MediaStreamVideoSourceTest, MaxAspectRatioZero) {
- MockMediaConstraintFactory factory;
- factory.AddOptional(MediaStreamVideoSource::kMaxAspectRatio, 0);
+ MockConstraintFactory factory;
+ factory.basic().aspectRatio.setMin(2.0);
+ factory.basic().aspectRatio.setMax(1.0);
blink::WebMediaStreamTrack track = CreateTrack(
"123", factory.CreateWebMediaConstraints());
mock_source()->CompleteGetSupportedFormats();
@@ -360,9 +349,9 @@ TEST_F(MediaStreamVideoSourceTest, MaxAspectRatioZero) {
}
TEST_F(MediaStreamVideoSourceTest, MinWidthLargerThanMaxWidth) {
- MockMediaConstraintFactory factory;
- factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 640);
- factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, 320);
+ MockConstraintFactory factory;
+ factory.basic().width.setMin(640);
+ factory.basic().width.setMax(320);
blink::WebMediaStreamTrack track = CreateTrack(
"123", factory.CreateWebMediaConstraints());
mock_source()->CompleteGetSupportedFormats();
@@ -370,9 +359,10 @@ TEST_F(MediaStreamVideoSourceTest, MinWidthLargerThanMaxWidth) {
}
TEST_F(MediaStreamVideoSourceTest, MinHeightLargerThanMaxHeight) {
- MockMediaConstraintFactory factory;
- factory.AddMandatory(MediaStreamVideoSource::kMinHeight, 480);
- factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, 360);
+ MockConstraintFactory factory;
+ factory.basic().height.setMin(480);
+ factory.basic().height.setMax(360);
+
blink::WebMediaStreamTrack track = CreateTrack(
"123", factory.CreateWebMediaConstraints());
mock_source()->CompleteGetSupportedFormats();
@@ -380,9 +370,9 @@ TEST_F(MediaStreamVideoSourceTest, MinHeightLargerThanMaxHeight) {
}
TEST_F(MediaStreamVideoSourceTest, MinFrameRateLargerThanMaxFrameRate) {
- MockMediaConstraintFactory factory;
- factory.AddMandatory(MediaStreamVideoSource::kMinFrameRate, 25);
- factory.AddMandatory(MediaStreamVideoSource::kMaxFrameRate, 15);
+ MockConstraintFactory factory;
+ factory.basic().frameRate.setMin(25);
+ factory.basic().frameRate.setMax(15);
blink::WebMediaStreamTrack track = CreateTrack(
"123", factory.CreateWebMediaConstraints());
mock_source()->CompleteGetSupportedFormats();
@@ -392,7 +382,7 @@ TEST_F(MediaStreamVideoSourceTest, MinFrameRateLargerThanMaxFrameRate) {
// Test that its safe to release the last reference of a blink track and the
// source during the callback if adding a track succeeds.
TEST_F(MediaStreamVideoSourceTest, ReleaseTrackAndSourceOnSuccessCallBack) {
- MockMediaConstraintFactory factory;
+ MockConstraintFactory factory;
{
blink::WebMediaStreamTrack track =
CreateTrack("123", factory.CreateWebMediaConstraints());
@@ -406,8 +396,8 @@ TEST_F(MediaStreamVideoSourceTest, ReleaseTrackAndSourceOnSuccessCallBack) {
// Test that its safe to release the last reference of a blink track and the
// source during the callback if adding a track fails.
TEST_F(MediaStreamVideoSourceTest, ReleaseTrackAndSourceOnFailureCallBack) {
- MockMediaConstraintFactory factory;
- factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 99999);
+ MockConstraintFactory factory;
+ factory.basic().width.setMin(99999);
{
blink::WebMediaStreamTrack track =
CreateTrack("123", factory.CreateWebMediaConstraints());
@@ -420,8 +410,8 @@ TEST_F(MediaStreamVideoSourceTest, ReleaseTrackAndSourceOnFailureCallBack) {
// Test that the source ignores an optional aspect ratio that is higher than
// supported.
TEST_F(MediaStreamVideoSourceTest, OptionalAspectRatioTooHigh) {
- MockMediaConstraintFactory factory;
- factory.AddOptional(MediaStreamVideoSource::kMinAspectRatio, 2);
+ MockConstraintFactory factory;
+ factory.AddAdvanced().aspectRatio.setMin(2.0);
blink::WebMediaStreamTrack track = CreateTrack(
"123", factory.CreateWebMediaConstraints());
mock_source()->CompleteGetSupportedFormats();
@@ -452,20 +442,21 @@ TEST_F(MediaStreamVideoSourceTest, DefaultCapability) {
}
TEST_F(MediaStreamVideoSourceTest, InvalidMandatoryConstraint) {
- MockMediaConstraintFactory factory;
- factory.AddMandatory("weird key", 640);
+ MockConstraintFactory factory;
+ // Use a constraint that is only known for audio.
+ factory.basic().echoCancellation.setExact(true);
blink::WebMediaStreamTrack track = CreateTrack(
"123", factory.CreateWebMediaConstraints());
mock_source()->CompleteGetSupportedFormats();
EXPECT_EQ(MEDIA_DEVICE_CONSTRAINT_NOT_SATISFIED, error_type());
- EXPECT_EQ("weird key", error_name());
+ EXPECT_EQ("echoCancellation", error_name());
EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
}
// Test that the source ignores an unknown optional constraint.
TEST_F(MediaStreamVideoSourceTest, InvalidOptionalConstraint) {
- MockMediaConstraintFactory factory;
- factory.AddOptional("weird key", 640);
+ MockConstraintFactory factory;
+ factory.AddAdvanced().echoCancellation.setExact(true);
CreateTrackAndStartSource(factory.CreateWebMediaConstraints(),
MediaStreamVideoSource::kDefaultWidth,
@@ -480,9 +471,9 @@ TEST_F(MediaStreamVideoSourceTest, ScreencastResolutionWithConstraint) {
formats.push_back(media::VideoCaptureFormat(
gfx::Size(480, 270), 30, media::PIXEL_FORMAT_I420));
mock_source()->SetSupportedFormats(formats);
- MockMediaConstraintFactory factory;
- factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, 480);
- factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, 270);
+ MockConstraintFactory factory;
+ factory.basic().width.setMax(480);
+ factory.basic().height.setMax(270);
blink::WebMediaStreamTrack track = CreateTrackAndStartSource(
factory.CreateWebMediaConstraints(), 480, 270, 30);
@@ -492,75 +483,75 @@ TEST_F(MediaStreamVideoSourceTest, ScreencastResolutionWithConstraint) {
// Test that optional constraints are applied in order.
TEST_F(MediaStreamVideoSourceTest, OptionalConstraints) {
- MockMediaConstraintFactory factory;
+ MockConstraintFactory factory;
// Min width of 2056 pixels can not be fulfilled.
- factory.AddOptional(MediaStreamVideoSource::kMinWidth, 2056);
- factory.AddOptional(MediaStreamVideoSource::kMinWidth, 641);
+ factory.AddAdvanced().width.setMin(2056);
+ factory.AddAdvanced().width.setMin(641);
// Since min width is set to 641 pixels, max width 640 can not be fulfilled.
- factory.AddOptional(MediaStreamVideoSource::kMaxWidth, 640);
+ factory.AddAdvanced().width.setMax(640);
CreateTrackAndStartSource(factory.CreateWebMediaConstraints(), 1280, 720, 30);
}
// Test that the source crops to the requested max width and
// height even though the camera delivers a larger frame.
TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrameOptional640360) {
- MockMediaConstraintFactory factory;
- factory.AddOptional(MediaStreamVideoSource::kMaxWidth, 640);
- factory.AddOptional(MediaStreamVideoSource::kMaxHeight, 360);
+ MockConstraintFactory factory;
+ factory.AddAdvanced().width.setMax(640);
+ factory.AddAdvanced().height.setMax(360);
TestSourceCropFrame(640, 480, factory.CreateWebMediaConstraints(), 640, 360);
}
TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrameMandatory640360) {
- MockMediaConstraintFactory factory;
- factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, 640);
- factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, 360);
+ MockConstraintFactory factory;
+ factory.basic().width.setMax(640);
+ factory.basic().height.setMax(360);
TestSourceCropFrame(640, 480, factory.CreateWebMediaConstraints(), 640, 360);
}
TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrameMandatory732489) {
- MockMediaConstraintFactory factory;
- factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, 732);
- factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, 489);
- factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 732);
- factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 489);
+ MockConstraintFactory factory;
+ factory.basic().width.setMax(732);
+ factory.basic().height.setMax(489);
+ factory.basic().width.setMin(732);
+ factory.basic().height.setMin(489);
TestSourceCropFrame(1280, 720, factory.CreateWebMediaConstraints(), 732, 489);
}
// Test that the source crops to the requested max width and
// height even though the requested frame has odd size.
TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrame637359) {
- MockMediaConstraintFactory factory;
- factory.AddOptional(MediaStreamVideoSource::kMaxWidth, 637);
- factory.AddOptional(MediaStreamVideoSource::kMaxHeight, 359);
+ MockConstraintFactory factory;
+ factory.AddAdvanced().width.setMax(637);
+ factory.AddAdvanced().height.setMax(359);
TestSourceCropFrame(640, 480, factory.CreateWebMediaConstraints(), 637, 359);
}
TEST_F(MediaStreamVideoSourceTest, DeliverCroppedVideoFrame320320) {
- MockMediaConstraintFactory factory;
- factory.AddMandatory(MediaStreamVideoSource::kMaxWidth, 320);
- factory.AddMandatory(MediaStreamVideoSource::kMaxHeight, 320);
- factory.AddMandatory(MediaStreamVideoSource::kMinHeight, 320);
- factory.AddMandatory(MediaStreamVideoSource::kMinWidth, 320);
+ MockConstraintFactory factory;
+ factory.basic().width.setMax(320);
+ factory.basic().height.setMax(320);
+ factory.basic().height.setMin(320);
+ factory.basic().width.setMax(320);
TestSourceCropFrame(640, 480, factory.CreateWebMediaConstraints(), 320, 320);
}
TEST_F(MediaStreamVideoSourceTest, DeliverSmallerSizeWhenTooLargeMax) {
- MockMediaConstraintFactory factory;
- factory.AddOptional(MediaStreamVideoSource::kMaxWidth, 1920);
- factory.AddOptional(MediaStreamVideoSource::kMaxHeight, 1080);
- factory.AddOptional(MediaStreamVideoSource::kMinWidth, 1280);
- factory.AddOptional(MediaStreamVideoSource::kMinHeight, 720);
+ MockConstraintFactory factory;
+ factory.AddAdvanced().width.setMax(1920);
+ factory.AddAdvanced().height.setMax(1080);
+ factory.AddAdvanced().width.setMin(1280);
+ factory.AddAdvanced().height.setMin(720);
TestSourceCropFrame(1280, 720, factory.CreateWebMediaConstraints(),
1280, 720);
}
TEST_F(MediaStreamVideoSourceTest, TwoTracksWithVGAAndWVGA) {
- MockMediaConstraintFactory factory1;
- factory1.AddOptional(MediaStreamVideoSource::kMaxWidth, 640);
- factory1.AddOptional(MediaStreamVideoSource::kMaxHeight, 480);
+ MockConstraintFactory factory1;
+ factory1.AddAdvanced().width.setMax(640);
+ factory1.AddAdvanced().height.setMax(480);
- MockMediaConstraintFactory factory2;
- factory2.AddOptional(MediaStreamVideoSource::kMaxHeight, 360);
+ MockConstraintFactory factory2;
+ factory2.AddAdvanced().height.setMax(360);
TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
factory2.CreateWebMediaConstraints(),
@@ -570,14 +561,13 @@ TEST_F(MediaStreamVideoSourceTest, TwoTracksWithVGAAndWVGA) {
}
TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndWVGA) {
- MockMediaConstraintFactory factory1;
- factory1.AddOptional(MediaStreamVideoSource::kMinWidth, 1280);
- factory1.AddOptional(MediaStreamVideoSource::kMinHeight, 720);
-
+ MockConstraintFactory factory1;
+ factory1.AddAdvanced().width.setMin(1280);
+ factory1.AddAdvanced().height.setMin(720);
- MockMediaConstraintFactory factory2;
- factory2.AddMandatory(MediaStreamVideoSource::kMaxWidth, 640);
- factory2.AddMandatory(MediaStreamVideoSource::kMaxHeight, 360);
+ MockConstraintFactory factory2;
+ factory2.basic().width.setMax(640);
+ factory2.basic().height.setMax(360);
TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
factory2.CreateWebMediaConstraints(),
@@ -587,13 +577,13 @@ TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndWVGA) {
}
TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndW700H700) {
- MockMediaConstraintFactory factory1;
- factory1.AddOptional(MediaStreamVideoSource::kMinWidth, 1280);
- factory1.AddOptional(MediaStreamVideoSource::kMinHeight, 720);
+ MockConstraintFactory factory1;
+ factory1.AddAdvanced().width.setMin(1280);
+ factory1.AddAdvanced().height.setMin(720);
- MockMediaConstraintFactory factory2;
- factory2.AddMandatory(MediaStreamVideoSource::kMaxWidth, 700);
- factory2.AddMandatory(MediaStreamVideoSource::kMaxHeight, 700);
+ MockConstraintFactory factory2;
+ factory2.basic().width.setMax(700);
+ factory2.basic().height.setMax(700);
TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
factory2.CreateWebMediaConstraints(),
@@ -603,12 +593,12 @@ TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndW700H700) {
}
TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndMaxAspectRatio4To3) {
- MockMediaConstraintFactory factory1;
- factory1.AddOptional(MediaStreamVideoSource::kMinWidth, 1280);
- factory1.AddOptional(MediaStreamVideoSource::kMinHeight, 720);
+ MockConstraintFactory factory1;
+ factory1.AddAdvanced().width.setMin(1280);
+ factory1.AddAdvanced().height.setMin(720);
- MockMediaConstraintFactory factory2;
- factory2.AddMandatory(MediaStreamVideoSource::kMaxAspectRatio, 640.0 / 480);
+ MockConstraintFactory factory2;
+ factory2.basic().aspectRatio.setMax(640.0 / 480);
TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
factory2.CreateWebMediaConstraints(),
@@ -618,12 +608,12 @@ TEST_F(MediaStreamVideoSourceTest, TwoTracksWith720AndMaxAspectRatio4To3) {
}
TEST_F(MediaStreamVideoSourceTest, TwoTracksWithVgaAndMinAspectRatio) {
- MockMediaConstraintFactory factory1;
- factory1.AddOptional(MediaStreamVideoSource::kMaxWidth, 640);
- factory1.AddOptional(MediaStreamVideoSource::kMaxHeight, 480);
+ MockConstraintFactory factory1;
+ factory1.AddAdvanced().width.setMax(640);
+ factory1.AddAdvanced().height.setMax(480);
- MockMediaConstraintFactory factory2;
- factory2.AddMandatory(MediaStreamVideoSource::kMinAspectRatio, 640.0 / 360);
+ MockConstraintFactory factory2;
+ factory2.basic().aspectRatio.setMin(640.0 / 360);
TestTwoTracksWithDifferentConstraints(factory1.CreateWebMediaConstraints(),
factory2.CreateWebMediaConstraints(),
@@ -634,9 +624,9 @@ TEST_F(MediaStreamVideoSourceTest, TwoTracksWithVgaAndMinAspectRatio) {
TEST_F(MediaStreamVideoSourceTest,
TwoTracksWithSecondTrackFrameRateHigherThanFirst) {
- MockMediaConstraintFactory factory1;
- factory1.AddMandatory(MediaStreamVideoSource::kMinFrameRate, 15);
- factory1.AddMandatory(MediaStreamVideoSource::kMaxFrameRate, 15);
+ MockConstraintFactory factory1;
+ factory1.basic().frameRate.setMin(15);
+ factory1.basic().frameRate.setMax(15);
blink::WebMediaStreamTrack track1 =
CreateTrackAndStartSource(factory1.CreateWebMediaConstraints(),
@@ -644,8 +634,8 @@ TEST_F(MediaStreamVideoSourceTest,
MediaStreamVideoSource::kDefaultHeight,
15);
- MockMediaConstraintFactory factory2;
- factory2.AddMandatory(MediaStreamVideoSource::kMinFrameRate, 30);
+ MockConstraintFactory factory2;
+ factory2.basic().frameRate.setMin(30);
blink::WebMediaStreamTrack track2 = CreateTrack(
"123", factory2.CreateWebMediaConstraints());
EXPECT_EQ(1, NumberOfFailedConstraintsCallbacks());
@@ -655,9 +645,9 @@ TEST_F(MediaStreamVideoSourceTest,
// tracks sinks get the new frame size unless constraints force the frame to be
// cropped.
TEST_F(MediaStreamVideoSourceTest, SourceChangeFrameSize) {
- MockMediaConstraintFactory factory;
- factory.AddOptional(MediaStreamVideoSource::kMaxWidth, 800);
- factory.AddOptional(MediaStreamVideoSource::kMaxHeight, 700);
+ MockConstraintFactory factory;
+ factory.AddAdvanced().width.setMax(800);
+ factory.AddAdvanced().height.setMax(700);
// Expect the source to start capture with the supported resolution.
blink::WebMediaStreamTrack track =
@@ -665,8 +655,7 @@ TEST_F(MediaStreamVideoSourceTest, SourceChangeFrameSize) {
640, 480, 30);
MockMediaStreamVideoSink sink;
- MediaStreamVideoSink::AddToVideoTrack(
- &sink, sink.GetDeliverFrameCB(), track);
+ sink.ConnectToTrack(track);
EXPECT_EQ(0, sink.number_of_frames());
DeliverVideoFrameAndWaitForRenderer(320, 240, &sink);
EXPECT_EQ(1, sink.number_of_frames());
@@ -689,7 +678,7 @@ TEST_F(MediaStreamVideoSourceTest, SourceChangeFrameSize) {
EXPECT_EQ(800, sink.frame_size().width());
EXPECT_EQ(700, sink.frame_size().height());
- MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
+ sink.DisconnectFromTrack();
}
TEST_F(MediaStreamVideoSourceTest, IsConstraintSupported) {
@@ -731,8 +720,7 @@ TEST_F(MediaStreamVideoSourceTest, Use0FpsSupportedFormat) {
EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
MockMediaStreamVideoSink sink;
- MediaStreamVideoSink::AddToVideoTrack(
- &sink, sink.GetDeliverFrameCB(), track);
+ sink.ConnectToTrack(track);
EXPECT_EQ(0, sink.number_of_frames());
DeliverVideoFrameAndWaitForRenderer(320, 240, &sink);
EXPECT_EQ(1, sink.number_of_frames());
@@ -740,27 +728,29 @@ TEST_F(MediaStreamVideoSourceTest, Use0FpsSupportedFormat) {
// max requested.
EXPECT_EQ(320, sink.frame_size().width());
EXPECT_EQ(240, sink.frame_size().height());
- MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
+ sink.DisconnectFromTrack();
}
-// Test that a source producing no frames change the source readyState to muted.
+// Test that a source producing no frames change the source ReadyState to muted.
// that in a reasonable time frame the muted state turns to false.
TEST_F(MediaStreamVideoSourceTest, MutedSource) {
- // Setup the source for support a frame rate of 2000fps in order to test
+ // Setup the source for support a frame rate of 999 fps in order to test
// the muted event faster. This is since the frame monitoring uses
// PostDelayedTask that is dependent on the source frame rate.
+ // Note that media::limits::kMaxFramesPerSecond is 1000.
media::VideoCaptureFormats formats;
formats.push_back(media::VideoCaptureFormat(
- gfx::Size(640, 480), 2000, media::PIXEL_FORMAT_I420));
+ gfx::Size(640, 480), media::limits::kMaxFramesPerSecond - 1,
+ media::PIXEL_FORMAT_I420));
SetSourceSupportedFormats(formats);
- MockMediaConstraintFactory factory;
+ MockConstraintFactory factory;
blink::WebMediaStreamTrack track =
- CreateTrackAndStartSource(factory.CreateWebMediaConstraints(),
- 640, 480, 2000);
+ CreateTrackAndStartSource(factory.CreateWebMediaConstraints(), 640, 480,
+ media::limits::kMaxFramesPerSecond - 1);
MockMediaStreamVideoSink sink;
- MediaStreamVideoSink::AddToVideoTrack(&sink, sink.GetDeliverFrameCB(), track);
- EXPECT_EQ(track.source().readyState(),
+ sink.ConnectToTrack(track);
+ EXPECT_EQ(track.source().getReadyState(),
blink::WebMediaStreamSource::ReadyStateLive);
base::RunLoop run_loop;
@@ -771,7 +761,7 @@ TEST_F(MediaStreamVideoSourceTest, MutedSource) {
run_loop.Run();
EXPECT_EQ(muted_state, true);
- EXPECT_EQ(track.source().readyState(),
+ EXPECT_EQ(track.source().getReadyState(),
blink::WebMediaStreamSource::ReadyStateMuted);
base::RunLoop run_loop2;
@@ -782,10 +772,10 @@ TEST_F(MediaStreamVideoSourceTest, MutedSource) {
run_loop2.Run();
EXPECT_EQ(muted_state, false);
- EXPECT_EQ(track.source().readyState(),
+ EXPECT_EQ(track.source().getReadyState(),
blink::WebMediaStreamSource::ReadyStateLive);
- MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
+ sink.DisconnectFromTrack();
}
} // namespace content
diff --git a/chromium/content/renderer/media/media_stream_video_track.cc b/chromium/content/renderer/media/media_stream_video_track.cc
index 6ff4688ce3d..4a0bca04d07 100644
--- a/chromium/content/renderer/media/media_stream_video_track.cc
+++ b/chromium/content/renderer/media/media_stream_video_track.cc
@@ -15,7 +15,7 @@
namespace content {
namespace {
-void ResetCallback(scoped_ptr<VideoCaptureDeliverFrameCB> callback) {
+void ResetCallback(std::unique_ptr<VideoCaptureDeliverFrameCB> callback) {
// |callback| will be deleted when this exits.
}
@@ -129,7 +129,7 @@ void MediaStreamVideoTrack::FrameDeliverer::RemoveCallbackOnIO(
for (; it != callbacks_.end(); ++it) {
if (it->first == id) {
// Callback is copied to heap and then deleted on the target thread.
- scoped_ptr<VideoCaptureDeliverFrameCB> callback;
+ std::unique_ptr<VideoCaptureDeliverFrameCB> callback;
callback.reset(new VideoCaptureDeliverFrameCB(it->second));
callbacks_.erase(it);
task_runner->PostTask(
@@ -175,9 +175,9 @@ MediaStreamVideoTrack::FrameDeliverer::GetBlackFrame(
// Wrap |black_frame_| so we get a fresh timestamp we can modify. Frames
// returned from this function may still be in use.
scoped_refptr<media::VideoFrame> wrapped_black_frame =
- media::VideoFrame::WrapVideoFrame(
- black_frame_, black_frame_->visible_rect(),
- black_frame_->natural_size());
+ media::VideoFrame::WrapVideoFrame(black_frame_, black_frame_->format(),
+ black_frame_->visible_rect(),
+ black_frame_->natural_size());
if (!wrapped_black_frame)
return nullptr;
wrapped_black_frame->AddDestructionObserver(
@@ -212,7 +212,11 @@ blink::WebMediaStreamTrack MediaStreamVideoTrack::CreateVideoTrack(
// static
MediaStreamVideoTrack* MediaStreamVideoTrack::GetVideoTrack(
const blink::WebMediaStreamTrack& track) {
- return static_cast<MediaStreamVideoTrack*>(track.extraData());
+ if (track.isNull() ||
+ track.source().getType() != blink::WebMediaStreamSource::TypeVideo) {
+ return nullptr;
+ }
+ return static_cast<MediaStreamVideoTrack*>(track.getExtraData());
}
MediaStreamVideoTrack::MediaStreamVideoTrack(
@@ -247,6 +251,9 @@ void MediaStreamVideoTrack::AddSink(
DCHECK(std::find(sinks_.begin(), sinks_.end(), sink) == sinks_.end());
sinks_.push_back(sink);
frame_deliverer_->AddCallback(sink, callback);
+ // Request source to deliver a frame because a new sink is added.
+ if (source_)
+ source_->RequestRefreshFrame();
}
void MediaStreamVideoTrack::RemoveSink(MediaStreamVideoSink* sink) {
diff --git a/chromium/content/renderer/media/media_stream_video_track.h b/chromium/content/renderer/media/media_stream_video_track.h
index bfcf419fe40..9769d3bb7f1 100644
--- a/chromium/content/renderer/media/media_stream_video_track.h
+++ b/chromium/content/renderer/media/media_stream_video_track.h
@@ -21,7 +21,7 @@ namespace content {
// MediaStreamVideoTrack is a video specific representation of a
// blink::WebMediaStreamTrack in content. It is owned by the blink object
// and can be retrieved from a blink object using
-// WebMediaStreamTrack::extraData() or MediaStreamVideoTrack::GetVideoTrack.
+// WebMediaStreamTrack::getExtraData() or MediaStreamVideoTrack::GetVideoTrack.
class CONTENT_EXPORT MediaStreamVideoTrack : public MediaStreamTrack {
public:
// Help method to create a blink::WebMediaStreamTrack and a
@@ -49,8 +49,8 @@ class CONTENT_EXPORT MediaStreamVideoTrack : public MediaStreamTrack {
bool enabled);
~MediaStreamVideoTrack() override;
+ // MediaStreamTrack overrides.
void SetEnabled(bool enabled) override;
-
void Stop() override;
void OnReadyStateChanged(blink::WebMediaStreamSource::ReadyState state);
diff --git a/chromium/content/renderer/media/media_stream_video_track_unittest.cc b/chromium/content/renderer/media/media_stream_video_track_unittest.cc
index 9959efeb044..392d2f67741 100644
--- a/chromium/content/renderer/media/media_stream_video_track_unittest.cc
+++ b/chromium/content/renderer/media/media_stream_video_track_unittest.cc
@@ -82,6 +82,16 @@ class MediaStreamVideoTrackTest : public ::testing::Test {
return track;
}
+ void UpdateVideoSourceToRespondToRequestRefreshFrame() {
+ blink_source_.reset();
+ mock_source_ = new MockMediaStreamVideoSource(false, true);
+ blink_source_.initialize(base::UTF8ToUTF16("dummy_source_id"),
+ blink::WebMediaStreamSource::TypeVideo,
+ base::UTF8ToUTF16("dummy_source_name"),
+ false /* remote */, true /* readonly */);
+ blink_source_.setExtraData(mock_source_);
+ }
+
MockMediaStreamVideoSource* mock_source() { return mock_source_; }
const blink::WebMediaStreamSource& blink_source() const {
return blink_source_;
@@ -89,7 +99,7 @@ class MediaStreamVideoTrackTest : public ::testing::Test {
private:
const base::MessageLoopForUI message_loop_;
- const scoped_ptr<ChildProcess> child_process_;
+ const std::unique_ptr<ChildProcess> child_process_;
blink::WebMediaStreamSource blink_source_;
// |mock_source_| is owned by |webkit_source_|.
MockMediaStreamVideoSource* mock_source_;
@@ -99,14 +109,14 @@ class MediaStreamVideoTrackTest : public ::testing::Test {
TEST_F(MediaStreamVideoTrackTest, AddAndRemoveSink) {
MockMediaStreamVideoSink sink;
blink::WebMediaStreamTrack track = CreateTrack();
- MediaStreamVideoSink::AddToVideoTrack(&sink, sink.GetDeliverFrameCB(), track);
+ sink.ConnectToTrack(track);
DeliverVideoFrameAndWaitForRenderer(&sink);
EXPECT_EQ(1, sink.number_of_frames());
DeliverVideoFrameAndWaitForRenderer(&sink);
- MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
+ sink.DisconnectFromTrack();
scoped_refptr<media::VideoFrame> frame =
media::VideoFrame::CreateBlackFrame(
@@ -150,13 +160,12 @@ TEST_F(MediaStreamVideoTrackTest, ResetCallbackOnThread) {
base::RunLoop run_loop;
bool correct = false;
- MediaStreamVideoSink::AddToVideoTrack(
- &sink,
- base::Bind(
- &CheckThreadVideoFrameReceiver,
- base::Owned(new CheckThreadHelper(run_loop.QuitClosure(), &correct))),
- track);
- MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
+ sink.ConnectToTrackWithCallback(
+ track,
+ base::Bind(&CheckThreadVideoFrameReceiver,
+ base::Owned(new CheckThreadHelper(run_loop.QuitClosure(),
+ &correct))));
+ sink.DisconnectFromTrack();
run_loop.Run();
EXPECT_TRUE(correct) << "Not called on correct thread.";
}
@@ -164,7 +173,7 @@ TEST_F(MediaStreamVideoTrackTest, ResetCallbackOnThread) {
TEST_F(MediaStreamVideoTrackTest, SetEnabled) {
MockMediaStreamVideoSink sink;
blink::WebMediaStreamTrack track = CreateTrack();
- MediaStreamVideoSink::AddToVideoTrack(&sink, sink.GetDeliverFrameCB(), track);
+ sink.ConnectToTrack(track);
MediaStreamVideoTrack* video_track =
MediaStreamVideoTrack::GetVideoTrack(track);
@@ -185,34 +194,32 @@ TEST_F(MediaStreamVideoTrackTest, SetEnabled) {
DeliverVideoFrameAndWaitForRenderer(&sink);
EXPECT_EQ(3, sink.number_of_frames());
EXPECT_EQ(kColorValue, *sink.last_frame()->data(media::VideoFrame::kYPlane));
- MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
+ sink.DisconnectFromTrack();
}
TEST_F(MediaStreamVideoTrackTest, SourceStopped) {
MockMediaStreamVideoSink sink;
blink::WebMediaStreamTrack track = CreateTrack();
- MediaStreamVideoSink::AddToVideoTrack(&sink, sink.GetDeliverFrameCB(), track);
+ sink.ConnectToTrack(track);
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive, sink.state());
mock_source()->StopSource();
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded, sink.state());
- MediaStreamVideoSink::RemoveFromVideoTrack(&sink, track);
+ sink.DisconnectFromTrack();
}
TEST_F(MediaStreamVideoTrackTest, StopLastTrack) {
MockMediaStreamVideoSink sink1;
blink::WebMediaStreamTrack track1 = CreateTrack();
- MediaStreamVideoSink::AddToVideoTrack(
- &sink1, sink1.GetDeliverFrameCB(), track1);
+ sink1.ConnectToTrack(track1);
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive, sink1.state());
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive,
- blink_source().readyState());
+ blink_source().getReadyState());
MockMediaStreamVideoSink sink2;
blink::WebMediaStreamTrack track2 = CreateTrack();
- MediaStreamVideoSink::AddToVideoTrack(
- &sink2, sink2.GetDeliverFrameCB(), track2);
+ sink2.ConnectToTrack(track2);
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive, sink2.state());
MediaStreamVideoTrack* const native_track1 =
@@ -220,16 +227,32 @@ TEST_F(MediaStreamVideoTrackTest, StopLastTrack) {
native_track1->Stop();
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded, sink1.state());
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive,
- blink_source().readyState());
- MediaStreamVideoSink::RemoveFromVideoTrack(&sink1, track1);
+ blink_source().getReadyState());
+ sink1.DisconnectFromTrack();
MediaStreamVideoTrack* const native_track2 =
MediaStreamVideoTrack::GetVideoTrack(track2);
native_track2->Stop();
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded, sink2.state());
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded,
- blink_source().readyState());
- MediaStreamVideoSink::RemoveFromVideoTrack(&sink2, track2);
+ blink_source().getReadyState());
+ sink2.DisconnectFromTrack();
+}
+
+TEST_F(MediaStreamVideoTrackTest, CheckTrackRequestsFrame) {
+ UpdateVideoSourceToRespondToRequestRefreshFrame();
+ blink::WebMediaStreamTrack track = CreateTrack();
+
+ // Add sink and expect to get a frame.
+ MockMediaStreamVideoSink sink;
+ base::RunLoop run_loop;
+ base::Closure quit_closure = run_loop.QuitClosure();
+ EXPECT_CALL(sink, OnVideoFrame()).WillOnce(RunClosure(quit_closure));
+ sink.ConnectToTrack(track);
+ run_loop.Run();
+ EXPECT_EQ(1, sink.number_of_frames());
+
+ sink.DisconnectFromTrack();
}
} // namespace content
diff --git a/chromium/content/renderer/media/midi_dispatcher.cc b/chromium/content/renderer/media/midi_dispatcher.cc
index 40fca8472be..65f42a95d44 100644
--- a/chromium/content/renderer/media/midi_dispatcher.cc
+++ b/chromium/content/renderer/media/midi_dispatcher.cc
@@ -7,12 +7,13 @@
#include "base/bind.h"
#include "content/public/common/service_registry.h"
#include "content/public/renderer/render_frame.h"
+#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/web/WebMIDIPermissionRequest.h"
-#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
-#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
+#include "third_party/WebKit/public/web/modules/webmidi/WebMIDIOptions.h"
+#include "third_party/WebKit/public/web/modules/webmidi/WebMIDIPermissionRequest.h"
using blink::WebMIDIPermissionRequest;
+using blink::WebMIDIOptions;
using blink::WebSecurityOrigin;
namespace content {
@@ -23,8 +24,8 @@ MidiDispatcher::MidiDispatcher(RenderFrame* render_frame)
MidiDispatcher::~MidiDispatcher() {}
-void MidiDispatcher::requestSysexPermission(
- const WebMIDIPermissionRequest& request) {
+void MidiDispatcher::requestPermission(const WebMIDIPermissionRequest& request,
+ const WebMIDIOptions& options) {
if (!permission_service_.get()) {
render_frame()->GetServiceRegistry()->ConnectToRemoteService(
mojo::GetProxy(&permission_service_));
@@ -33,16 +34,18 @@ void MidiDispatcher::requestSysexPermission(
int permission_request_id =
requests_.Add(new WebMIDIPermissionRequest(request));
+ blink::mojom::PermissionName permission_name =
+ (options.sysex == WebMIDIOptions::SysexPermission::WithSysex)
+ ? blink::mojom::PermissionName::MIDI_SYSEX
+ : blink::mojom::PermissionName::MIDI;
+
permission_service_->RequestPermission(
- PERMISSION_NAME_MIDI_SYSEX,
- request.securityOrigin().toString().utf8(),
- blink::WebUserGestureIndicator::isProcessingUserGesture(),
- base::Bind(&MidiDispatcher::OnSysExPermissionSet,
- base::Unretained(this),
+ permission_name, request.getSecurityOrigin().toString().utf8(),
+ base::Bind(&MidiDispatcher::OnPermissionSet, base::Unretained(this),
permission_request_id));
}
-void MidiDispatcher::cancelSysexPermissionRequest(
+void MidiDispatcher::cancelPermissionRequest(
const WebMIDIPermissionRequest& request) {
for (Requests::iterator it(&requests_); !it.IsAtEnd(); it.Advance()) {
WebMIDIPermissionRequest* value = it.GetCurrentValue();
@@ -53,13 +56,13 @@ void MidiDispatcher::cancelSysexPermissionRequest(
}
}
-void MidiDispatcher::OnSysExPermissionSet(int request_id,
- PermissionStatus status) {
+void MidiDispatcher::OnPermissionSet(int request_id,
+ blink::mojom::PermissionStatus status) {
// |request| can be NULL when the request is canceled.
WebMIDIPermissionRequest* request = requests_.Lookup(request_id);
if (!request)
return;
- request->setIsAllowed(status == PERMISSION_STATUS_GRANTED);
+ request->setIsAllowed(status == blink::mojom::PermissionStatus::GRANTED);
requests_.Remove(request_id);
}
diff --git a/chromium/content/renderer/media/midi_dispatcher.h b/chromium/content/renderer/media/midi_dispatcher.h
index ab85d770866..802328a770c 100644
--- a/chromium/content/renderer/media/midi_dispatcher.h
+++ b/chromium/content/renderer/media/midi_dispatcher.h
@@ -7,9 +7,9 @@
#include "base/id_map.h"
#include "base/macros.h"
-#include "content/common/permission_service.mojom.h"
#include "content/public/renderer/render_frame_observer.h"
-#include "third_party/WebKit/public/web/WebMIDIClient.h"
+#include "third_party/WebKit/public/platform/modules/permissions/permission.mojom.h"
+#include "third_party/WebKit/public/web/modules/webmidi/WebMIDIClient.h"
namespace blink {
class WebMIDIPermissionRequest;
@@ -29,13 +29,13 @@ class MidiDispatcher : public RenderFrameObserver,
private:
// blink::WebMIDIClient implementation.
- void requestSysexPermission(
- const blink::WebMIDIPermissionRequest& request) override;
- void cancelSysexPermissionRequest(
+ void requestPermission(const blink::WebMIDIPermissionRequest& request,
+ const blink::WebMIDIOptions& options) override;
+ void cancelPermissionRequest(
const blink::WebMIDIPermissionRequest& request) override;
- // Permission for using system exclusive messages has been set.
- void OnSysExPermissionSet(int request_id, PermissionStatus status);
+ // Permission for using MIDI system has been set.
+ void OnPermissionSet(int request_id, blink::mojom::PermissionStatus status);
// Each WebMIDIPermissionRequest object is valid until
// cancelSysexPermissionRequest() is called with the object, or used to call
@@ -43,7 +43,7 @@ class MidiDispatcher : public RenderFrameObserver,
typedef IDMap<blink::WebMIDIPermissionRequest, IDMapOwnPointer> Requests;
Requests requests_;
- PermissionServicePtr permission_service_;
+ blink::mojom::PermissionServicePtr permission_service_;
DISALLOW_COPY_AND_ASSIGN(MidiDispatcher);
};
diff --git a/chromium/content/renderer/media/midi_message_filter.cc b/chromium/content/renderer/media/midi_message_filter.cc
index 7bc0a54eca7..e92d0fc9dae 100644
--- a/chromium/content/renderer/media/midi_message_filter.cc
+++ b/chromium/content/renderer/media/midi_message_filter.cc
@@ -23,7 +23,6 @@ static const size_t kMaxUnacknowledgedBytesSent = 10 * 1024 * 1024; // 10 MB.
namespace content {
-// TODO(crbug.com/425389): Rewrite this class as a RenderFrameObserver.
MidiMessageFilter::MidiMessageFilter(
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner)
: sender_(nullptr),
diff --git a/chromium/content/renderer/media/midi_message_filter.h b/chromium/content/renderer/media/midi_message_filter.h
index bf818ad3e55..ae0279acfb0 100644
--- a/chromium/content/renderer/media/midi_message_filter.h
+++ b/chromium/content/renderer/media/midi_message_filter.h
@@ -8,16 +8,16 @@
#include <stddef.h>
#include <stdint.h>
+#include <memory>
#include <set>
#include <vector>
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
#include "ipc/message_filter.h"
#include "media/midi/midi_port_info.h"
#include "media/midi/result.h"
-#include "third_party/WebKit/public/platform/WebMIDIAccessorClient.h"
+#include "third_party/WebKit/public/platform/modules/webmidi/WebMIDIAccessorClient.h"
namespace base {
class SingleThreadTaskRunner;
@@ -25,7 +25,13 @@ class SingleThreadTaskRunner;
namespace content {
-// MessageFilter that handles MIDI messages.
+// MessageFilter that handles MIDI messages. Created on render thread, and
+// host multiple clients running on multiple frames on IO thread.
+// Web MIDI intentionally uses MessageFilter (in a renderer process) and
+// BrowserMessageFilter (in the browser process) to intercept MIDI messages and
+// process them on IO thread in the browser process since these messages are
+// time critical. Non-critical operations like permission management are
+// handled in MidiDispatcher.
class CONTENT_EXPORT MidiMessageFilter : public IPC::MessageFilter {
public:
explicit MidiMessageFilter(
diff --git a/chromium/content/renderer/media/mock_constraint_factory.cc b/chromium/content/renderer/media/mock_constraint_factory.cc
new file mode 100644
index 00000000000..133c63aca97
--- /dev/null
+++ b/chromium/content/renderer/media/mock_constraint_factory.cc
@@ -0,0 +1,50 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+
+#include "base/macros.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "content/renderer/media/media_stream_audio_processor_options.h"
+#include "content/renderer/media/mock_constraint_factory.h"
+#include "third_party/webrtc/api/mediaconstraintsinterface.h"
+
+namespace content {
+
+MockConstraintFactory::MockConstraintFactory() {}
+
+MockConstraintFactory::~MockConstraintFactory() {}
+
+blink::WebMediaTrackConstraintSet& MockConstraintFactory::AddAdvanced() {
+ advanced_.emplace_back();
+ return advanced_.back();
+}
+
+blink::WebMediaConstraints MockConstraintFactory::CreateWebMediaConstraints()
+ const {
+ blink::WebMediaConstraints constraints;
+ constraints.initialize(basic_, advanced_);
+ return constraints;
+}
+
+void MockConstraintFactory::DisableDefaultAudioConstraints() {
+ basic_.googEchoCancellation.setExact(false);
+ basic_.googExperimentalEchoCancellation.setExact(false);
+ basic_.googAutoGainControl.setExact(false);
+ basic_.googExperimentalAutoGainControl.setExact(false);
+ basic_.googNoiseSuppression.setExact(false);
+ basic_.googNoiseSuppression.setExact(false);
+ basic_.googHighpassFilter.setExact(false);
+ basic_.googTypingNoiseDetection.setExact(false);
+ basic_.googExperimentalNoiseSuppression.setExact(false);
+ basic_.googBeamforming.setExact(false);
+}
+
+void MockConstraintFactory::Reset() {
+ basic_ = blink::WebMediaTrackConstraintSet();
+ advanced_.clear();
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/mock_constraint_factory.h b/chromium/content/renderer/media/mock_constraint_factory.h
new file mode 100644
index 00000000000..1aebc176856
--- /dev/null
+++ b/chromium/content/renderer/media/mock_constraint_factory.h
@@ -0,0 +1,37 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_MOCK_CONSTRAINT_FACTORY_H_
+#define CONTENT_RENDERER_MEDIA_MOCK_CONSTRAINT_FACTORY_H_
+
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
+
+namespace content {
+
+class MockConstraintFactory {
+ public:
+ MockConstraintFactory();
+ ~MockConstraintFactory();
+
+ blink::WebMediaConstraints CreateWebMediaConstraints() const;
+ blink::WebMediaTrackConstraintSet& basic() { return basic_; }
+ blink::WebMediaTrackConstraintSet& AddAdvanced();
+
+ void DisableDefaultAudioConstraints();
+ void Reset();
+
+ private:
+ blink::WebMediaTrackConstraintSet basic_;
+ std::vector<blink::WebMediaTrackConstraintSet> advanced_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockConstraintFactory);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_MOCK_CONSTRAINT_FACTORY_H_
diff --git a/chromium/content/renderer/media/mock_data_channel_impl.h b/chromium/content/renderer/media/mock_data_channel_impl.h
index 9b826696e0b..0b763dc77e6 100644
--- a/chromium/content/renderer/media/mock_data_channel_impl.h
+++ b/chromium/content/renderer/media/mock_data_channel_impl.h
@@ -10,7 +10,7 @@
#include <string>
#include "base/macros.h"
-#include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h"
+#include "third_party/webrtc/api/peerconnectioninterface.h"
namespace content {
diff --git a/chromium/content/renderer/media/mock_media_constraint_factory.cc b/chromium/content/renderer/media/mock_media_constraint_factory.cc
deleted file mode 100644
index 66bb1c6a352..00000000000
--- a/chromium/content/renderer/media/mock_media_constraint_factory.cc
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/renderer/media/media_stream_audio_processor_options.h"
-#include "content/renderer/media/mock_media_constraint_factory.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h"
-
-namespace content {
-
-namespace {
-
-static const char kValueTrue[] = "true";
-static const char kValueFalse[] = "false";
-
-} // namespace
-
-MockMediaConstraintFactory::MockMediaConstraintFactory() {
-}
-
-MockMediaConstraintFactory::~MockMediaConstraintFactory() {
-}
-
-blink::WebMediaConstraints
-MockMediaConstraintFactory::CreateWebMediaConstraints() const {
- blink::WebVector<blink::WebMediaConstraint> mandatory(mandatory_);
- blink::WebVector<blink::WebMediaConstraint> optional(optional_);
- blink::WebMediaConstraints constraints;
- blink::WebMediaTrackConstraintSet basic;
- blink::WebVector<blink::WebMediaTrackConstraintSet> advanced;
- constraints.initialize(optional, mandatory, basic, advanced);
- return constraints;
-}
-
-void MockMediaConstraintFactory::AddMandatory(const std::string& key,
- int value) {
- mandatory_.push_back(blink::WebMediaConstraint(base::UTF8ToUTF16(key),
- base::IntToString16(value)));
-}
-
-void MockMediaConstraintFactory::AddMandatory(const std::string& key,
- double value) {
- mandatory_.push_back(blink::WebMediaConstraint(
- base::UTF8ToUTF16(key),
- base::UTF8ToUTF16(base::DoubleToString(value))));
-}
-
-void MockMediaConstraintFactory::AddMandatory(const std::string& key,
- const std::string& value) {
- mandatory_.push_back(blink::WebMediaConstraint(
- base::UTF8ToUTF16(key), base::UTF8ToUTF16(value)));
-}
-
-void MockMediaConstraintFactory::AddMandatory(const std::string& key,
- bool value) {
- const std::string string_value = value ? kValueTrue : kValueFalse;
- AddMandatory(key, string_value);
-}
-
-void MockMediaConstraintFactory::AddOptional(const std::string& key,
- int value) {
- optional_.push_back(blink::WebMediaConstraint(base::UTF8ToUTF16(key),
- base::IntToString16(value)));
-}
-
-void MockMediaConstraintFactory::AddOptional(const std::string& key,
- double value) {
- optional_.push_back(blink::WebMediaConstraint(
- base::UTF8ToUTF16(key),
- base::UTF8ToUTF16(base::DoubleToString(value))));
-}
-
-void MockMediaConstraintFactory::AddOptional(const std::string& key,
- const std::string& value) {
- optional_.push_back(blink::WebMediaConstraint(
- base::UTF8ToUTF16(key), base::UTF8ToUTF16(value)));
-}
-
-void MockMediaConstraintFactory::AddOptional(const std::string& key,
- bool value) {
- const std::string string_value = value ? kValueTrue : kValueFalse;
- AddOptional(key, string_value);
-}
-
-void MockMediaConstraintFactory::DisableDefaultAudioConstraints() {
- static const char* kDefaultAudioConstraints[] = {
- webrtc::MediaConstraintsInterface::kGoogEchoCancellation,
- webrtc::MediaConstraintsInterface::kExtendedFilterEchoCancellation,
- webrtc::MediaConstraintsInterface::kAutoGainControl,
- webrtc::MediaConstraintsInterface::kExperimentalAutoGainControl,
- webrtc::MediaConstraintsInterface::kNoiseSuppression,
- webrtc::MediaConstraintsInterface::kHighpassFilter,
- webrtc::MediaConstraintsInterface::kTypingNoiseDetection,
- webrtc::MediaConstraintsInterface::kExperimentalNoiseSuppression,
- // This isn't part of the MediaConstraintsInterface.
- MediaAudioConstraints::kGoogBeamforming
- };
- MockMediaConstraintFactory factory;
- for (size_t i = 0; i < arraysize(kDefaultAudioConstraints); ++i) {
- AddMandatory(kDefaultAudioConstraints[i], false);
- }
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/mock_media_constraint_factory.h b/chromium/content/renderer/media/mock_media_constraint_factory.h
deleted file mode 100644
index 3ea20bcd0b3..00000000000
--- a/chromium/content/renderer/media/mock_media_constraint_factory.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_MEDIA_MOCK_MEDIA_CONSTRAINT_FACTORY_H_
-#define CONTENT_RENDERER_MEDIA_MOCK_MEDIA_CONSTRAINT_FACTORY_H_
-
-#include <string>
-#include <vector>
-
-#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
-
-namespace content {
-
-class MockMediaConstraintFactory {
- public:
- MockMediaConstraintFactory();
- ~MockMediaConstraintFactory();
-
- blink::WebMediaConstraints CreateWebMediaConstraints() const;
- void AddMandatory(const std::string& key, int value);
- void AddMandatory(const std::string& key, double value);
- void AddMandatory(const std::string& key, const std::string& value);
- void AddMandatory(const std::string& key, bool value);
- void AddOptional(const std::string& key, int value);
- void AddOptional(const std::string& key, double value);
- void AddOptional(const std::string& key, const std::string& value);
- void AddOptional(const std::string& key, bool value);
- void DisableDefaultAudioConstraints();
-
- private:
- std::vector<blink::WebMediaConstraint> mandatory_;
- std::vector<blink::WebMediaConstraint> optional_;
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_MOCK_MEDIA_CONSTRAINT_FACTORY_H_
diff --git a/chromium/content/renderer/media/mock_media_stream_registry.cc b/chromium/content/renderer/media/mock_media_stream_registry.cc
index a37ca33b751..9bef2c5f46d 100644
--- a/chromium/content/renderer/media/mock_media_stream_registry.cc
+++ b/chromium/content/renderer/media/mock_media_stream_registry.cc
@@ -10,7 +10,6 @@
#include "content/renderer/media/media_stream.h"
#include "content/renderer/media/media_stream_audio_source.h"
#include "content/renderer/media/media_stream_video_track.h"
-#include "content/renderer/media/mock_media_constraint_factory.h"
#include "content/renderer/media/mock_media_stream_video_source.h"
#include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
#include "content/renderer/media/webrtc_local_audio_track.h"
@@ -63,21 +62,11 @@ void MockMediaStreamRegistry::AddAudioTrack(const std::string& track_id) {
audio_source.setExtraData(new MediaStreamAudioSource());
blink::WebMediaStreamTrack blink_track;
blink_track.initialize(audio_source);
- const StreamDeviceInfo device_info(
- MEDIA_DEVICE_AUDIO_CAPTURE, "Mock audio device", "mock_audio_device_id");
- const MockMediaConstraintFactory constraint_factory;
- const blink::WebMediaConstraints constraints =
- constraint_factory.CreateWebMediaConstraints();
- const scoped_refptr<WebRtcAudioCapturer> capturer(
- WebRtcAudioCapturer::CreateCapturer(-1, /* render frame id */
- device_info, constraints,
- nullptr, /* audio device */
- nullptr /* audio source */));
const scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
WebRtcLocalAudioTrackAdapter::Create(track_id,
nullptr /* track source */));
- scoped_ptr<WebRtcLocalAudioTrack> native_track(new WebRtcLocalAudioTrack(
- adapter.get(), capturer, nullptr /* webaudio source */));
+ std::unique_ptr<WebRtcLocalAudioTrack> native_track(
+ new WebRtcLocalAudioTrack(adapter.get()));
blink_track.setExtraData(native_track.release());
test_stream_.addTrack(blink_track);
}
diff --git a/chromium/content/renderer/media/mock_media_stream_video_sink.h b/chromium/content/renderer/media/mock_media_stream_video_sink.h
index 91270190d8f..b637b891f5d 100644
--- a/chromium/content/renderer/media/mock_media_stream_video_sink.h
+++ b/chromium/content/renderer/media/mock_media_stream_video_sink.h
@@ -19,6 +19,19 @@ class MockMediaStreamVideoSink : public MediaStreamVideoSink {
MockMediaStreamVideoSink();
~MockMediaStreamVideoSink() override;
+ void ConnectToTrack(const blink::WebMediaStreamTrack& track) {
+ MediaStreamVideoSink::ConnectToTrack(track, GetDeliverFrameCB());
+ }
+
+ void ConnectToTrackWithCallback(const blink::WebMediaStreamTrack& track,
+ const VideoCaptureDeliverFrameCB& callback) {
+ MediaStreamVideoSink::ConnectToTrack(track, callback);
+ }
+
+ void DisconnectFromTrack() {
+ MediaStreamVideoSink::DisconnectFromTrack();
+ }
+
void OnReadyStateChanged(
blink::WebMediaStreamSource::ReadyState state) override;
void OnEnabledChanged(bool enabled) override;
diff --git a/chromium/content/renderer/media/mock_media_stream_video_source.cc b/chromium/content/renderer/media/mock_media_stream_video_source.cc
index f80e2c53277..3cfa3c0b914 100644
--- a/chromium/content/renderer/media/mock_media_stream_video_source.cc
+++ b/chromium/content/renderer/media/mock_media_stream_video_source.cc
@@ -12,7 +12,13 @@ namespace content {
MockMediaStreamVideoSource::MockMediaStreamVideoSource(
bool manual_get_supported_formats)
+ : MockMediaStreamVideoSource(manual_get_supported_formats, false) {}
+
+MockMediaStreamVideoSource::MockMediaStreamVideoSource(
+ bool manual_get_supported_formats,
+ bool respond_to_request_refresh_frame)
: manual_get_supported_formats_(manual_get_supported_formats),
+ respond_to_request_refresh_frame_(respond_to_request_refresh_frame),
max_requested_height_(0),
max_requested_width_(0),
max_requested_frame_rate_(0.0),
@@ -20,8 +26,7 @@ MockMediaStreamVideoSource::MockMediaStreamVideoSource(
supported_formats_.push_back(media::VideoCaptureFormat(
gfx::Size(MediaStreamVideoSource::kDefaultWidth,
MediaStreamVideoSource::kDefaultHeight),
- MediaStreamVideoSource::kDefaultFrameRate,
- media::PIXEL_FORMAT_I420));
+ MediaStreamVideoSource::kDefaultFrameRate, media::PIXEL_FORMAT_I420));
}
MockMediaStreamVideoSource::~MockMediaStreamVideoSource() {}
@@ -43,6 +48,17 @@ void MockMediaStreamVideoSource::CompleteGetSupportedFormats() {
base::ResetAndReturn(&formats_callback_).Run(supported_formats_);
}
+void MockMediaStreamVideoSource::RequestRefreshFrame() {
+ DCHECK(!frame_callback_.is_null());
+ if (respond_to_request_refresh_frame_) {
+ const scoped_refptr<media::VideoFrame> frame =
+ media::VideoFrame::CreateColorFrame(format_.frame_size, 0, 0, 0,
+ base::TimeDelta());
+ io_task_runner()->PostTask(
+ FROM_HERE, base::Bind(frame_callback_, frame, base::TimeTicks()));
+ }
+}
+
void MockMediaStreamVideoSource::GetCurrentSupportedFormats(
int max_requested_height,
int max_requested_width,
diff --git a/chromium/content/renderer/media/mock_media_stream_video_source.h b/chromium/content/renderer/media/mock_media_stream_video_source.h
index e5e4d7e969e..4a44e03f478 100644
--- a/chromium/content/renderer/media/mock_media_stream_video_source.h
+++ b/chromium/content/renderer/media/mock_media_stream_video_source.h
@@ -15,6 +15,8 @@ namespace content {
class MockMediaStreamVideoSource : public MediaStreamVideoSource {
public:
explicit MockMediaStreamVideoSource(bool manual_get_supported_formats);
+ MockMediaStreamVideoSource(bool manual_get_supported_formats,
+ bool respond_to_request_refresh_frame);
virtual ~MockMediaStreamVideoSource();
MOCK_METHOD1(DoSetMutedState, void(bool muted_state));
@@ -50,6 +52,9 @@ class MockMediaStreamVideoSource : public MediaStreamVideoSource {
DoSetMutedState(muted_state);
}
+ // Implements MediaStreamVideoSource.
+ void RequestRefreshFrame() override;
+
protected:
// Implements MediaStreamVideoSource.
void GetCurrentSupportedFormats(
@@ -67,6 +72,7 @@ class MockMediaStreamVideoSource : public MediaStreamVideoSource {
media::VideoCaptureFormat format_;
media::VideoCaptureFormats supported_formats_;
bool manual_get_supported_formats_;
+ bool respond_to_request_refresh_frame_;
int max_requested_height_;
int max_requested_width_;
double max_requested_frame_rate_;
diff --git a/chromium/content/renderer/media/mock_peer_connection_impl.cc b/chromium/content/renderer/media/mock_peer_connection_impl.cc
index cc8f0bb93f3..759147b67df 100644
--- a/chromium/content/renderer/media/mock_peer_connection_impl.cc
+++ b/chromium/content/renderer/media/mock_peer_connection_impl.cc
@@ -18,7 +18,6 @@ using webrtc::CreateSessionDescriptionObserver;
using webrtc::DtmfSenderInterface;
using webrtc::DtmfSenderObserverInterface;
using webrtc::IceCandidateInterface;
-using webrtc::MediaConstraintsInterface;
using webrtc::MediaStreamInterface;
using webrtc::PeerConnectionInterface;
using webrtc::SessionDescriptionInterface;
@@ -226,7 +225,7 @@ void MockPeerConnectionImpl::AddRemoteStream(MediaStreamInterface* stream) {
void MockPeerConnectionImpl::CreateOffer(
CreateSessionDescriptionObserver* observer,
- const MediaConstraintsInterface* constraints) {
+ const RTCOfferAnswerOptions& options) {
DCHECK(observer);
created_sessiondescription_.reset(
dependency_factory_->CreateSessionDescription("unknown", kDummyOffer,
@@ -235,7 +234,7 @@ void MockPeerConnectionImpl::CreateOffer(
void MockPeerConnectionImpl::CreateAnswer(
CreateSessionDescriptionObserver* observer,
- const MediaConstraintsInterface* constraints) {
+ const RTCOfferAnswerOptions& options) {
DCHECK(observer);
created_sessiondescription_.reset(
dependency_factory_->CreateSessionDescription("unknown", kDummyAnswer,
@@ -256,9 +255,7 @@ void MockPeerConnectionImpl::SetRemoteDescriptionWorker(
remote_desc_.reset(desc);
}
-bool MockPeerConnectionImpl::UpdateIce(
- const IceServers& configuration,
- const MediaConstraintsInterface* constraints) {
+bool MockPeerConnectionImpl::UpdateIce(const IceServers& configuration) {
return true;
}
diff --git a/chromium/content/renderer/media/mock_peer_connection_impl.h b/chromium/content/renderer/media/mock_peer_connection_impl.h
index dae0b9ca3f0..da60d59b85b 100644
--- a/chromium/content/renderer/media/mock_peer_connection_impl.h
+++ b/chromium/content/renderer/media/mock_peer_connection_impl.h
@@ -5,14 +5,14 @@
#ifndef CONTENT_RENDERER_MEDIA_MOCK_PEER_CONNECTION_IMPL_H_
#define CONTENT_RENDERER_MEDIA_MOCK_PEER_CONNECTION_IMPL_H_
+#include <memory>
#include <string>
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "testing/gmock/include/gmock/gmock.h"
-#include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h"
+#include "third_party/webrtc/api/peerconnectioninterface.h"
namespace content {
@@ -69,12 +69,10 @@ class MockPeerConnectionImpl : public webrtc::PeerConnectionInterface {
const override;
// JSEP01 APIs
- void CreateOffer(
- webrtc::CreateSessionDescriptionObserver* observer,
- const webrtc::MediaConstraintsInterface* constraints) override;
- void CreateAnswer(
- webrtc::CreateSessionDescriptionObserver* observer,
- const webrtc::MediaConstraintsInterface* constraints) override;
+ void CreateOffer(webrtc::CreateSessionDescriptionObserver* observer,
+ const RTCOfferAnswerOptions& options) override;
+ void CreateAnswer(webrtc::CreateSessionDescriptionObserver* observer,
+ const RTCOfferAnswerOptions& options) override;
MOCK_METHOD2(SetLocalDescription,
void(webrtc::SetSessionDescriptionObserver* observer,
webrtc::SessionDescriptionInterface* desc));
@@ -87,8 +85,7 @@ class MockPeerConnectionImpl : public webrtc::PeerConnectionInterface {
void SetRemoteDescriptionWorker(
webrtc::SetSessionDescriptionObserver* observer,
webrtc::SessionDescriptionInterface* desc);
- bool UpdateIce(const IceServers& configuration,
- const webrtc::MediaConstraintsInterface* constraints) override;
+ bool UpdateIce(const IceServers& configuration) override;
bool AddIceCandidate(const webrtc::IceCandidateInterface* candidate) override;
void RegisterUMAObserver(webrtc::UMAObserver* observer) override;
@@ -120,9 +117,10 @@ class MockPeerConnectionImpl : public webrtc::PeerConnectionInterface {
std::string stream_label_;
rtc::scoped_refptr<MockStreamCollection> local_streams_;
rtc::scoped_refptr<MockStreamCollection> remote_streams_;
- scoped_ptr<webrtc::SessionDescriptionInterface> local_desc_;
- scoped_ptr<webrtc::SessionDescriptionInterface> remote_desc_;
- scoped_ptr<webrtc::SessionDescriptionInterface> created_sessiondescription_;
+ std::unique_ptr<webrtc::SessionDescriptionInterface> local_desc_;
+ std::unique_ptr<webrtc::SessionDescriptionInterface> remote_desc_;
+ std::unique_ptr<webrtc::SessionDescriptionInterface>
+ created_sessiondescription_;
bool hint_audio_;
bool hint_video_;
bool getstats_result_;
diff --git a/chromium/content/renderer/media/peer_connection_identity_store.cc b/chromium/content/renderer/media/peer_connection_identity_store.cc
index c6f432dc6c4..d76a217506f 100644
--- a/chromium/content/renderer/media/peer_connection_identity_store.cc
+++ b/chromium/content/renderer/media/peer_connection_identity_store.cc
@@ -4,9 +4,10 @@
#include "content/renderer/media/peer_connection_identity_store.h"
+#include <memory>
+
#include "base/bind.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/thread_task_runner_handle.h"
#include "content/renderer/media/webrtc_identity_service.h"
#include "content/renderer/render_thread_impl.h"
@@ -91,7 +92,7 @@ class RequestHandler : public base::RefCountedThreadSafe<RequestHandler> {
// Used to invoke |observer|->OnSuccess in a PostTask.
void ObserverOnSuccess(
const rtc::scoped_refptr<webrtc::DtlsIdentityRequestObserver>& observer,
- scoped_ptr<rtc::SSLIdentity> identity) {
+ std::unique_ptr<rtc::SSLIdentity> identity) {
observer->OnSuccess(rtc::scoped_ptr<rtc::SSLIdentity>(identity.release()));
}
@@ -140,8 +141,8 @@ void PeerConnectionIdentityStore::RequestIdentity(
} else {
// Fall back on WebRTC identity generation code for everything else, e.g.
// RSA with any other parameters or ECDSA. These will not be cached.
- scoped_ptr<rtc::SSLIdentity> identity(rtc::SSLIdentity::Generate(
- kIdentityName, key_params));
+ std::unique_ptr<rtc::SSLIdentity> identity(
+ rtc::SSLIdentity::Generate(kIdentityName, key_params));
// Invoke |observer| callbacks asynchronously. The callbacks of
// DtlsIdentityStoreInterface implementations have to be async.
diff --git a/chromium/content/renderer/media/peer_connection_identity_store.h b/chromium/content/renderer/media/peer_connection_identity_store.h
index 82afbdc344c..35d99c5a6c4 100644
--- a/chromium/content/renderer/media/peer_connection_identity_store.h
+++ b/chromium/content/renderer/media/peer_connection_identity_store.h
@@ -8,7 +8,7 @@
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
-#include "third_party/libjingle/source/talk/app/webrtc/dtlsidentitystore.h"
+#include "third_party/webrtc/api/dtlsidentitystore.h"
#include "url/gurl.h"
namespace content {
diff --git a/chromium/content/renderer/media/peer_connection_tracker.cc b/chromium/content/renderer/media/peer_connection_tracker.cc
index 63d6f56ae02..60f3d26b18c 100644
--- a/chromium/content/renderer/media/peer_connection_tracker.cc
+++ b/chromium/content/renderer/media/peer_connection_tracker.cc
@@ -10,20 +10,20 @@
#include "base/strings/utf_string_conversions.h"
#include "base/thread_task_runner_handle.h"
#include "content/common/media/peer_connection_tracker_messages.h"
-#include "content/renderer/media/rtc_media_constraints.h"
#include "content/renderer/media/rtc_peer_connection_handler.h"
#include "content/renderer/render_thread_impl.h"
#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
#include "third_party/WebKit/public/platform/WebMediaStream.h"
#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
+#include "third_party/WebKit/public/platform/WebRTCAnswerOptions.h"
#include "third_party/WebKit/public/platform/WebRTCICECandidate.h"
+#include "third_party/WebKit/public/platform/WebRTCOfferOptions.h"
#include "third_party/WebKit/public/platform/WebRTCPeerConnectionHandlerClient.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebUserMediaRequest.h"
-using std::string;
using webrtc::MediaConstraintsInterface;
using webrtc::StatsReport;
using webrtc::StatsReports;
@@ -31,9 +31,15 @@ using blink::WebRTCPeerConnectionHandlerClient;
namespace content {
-static string SerializeServers(
+// TODO(hta): This module should be redesigned to reduce string copies.
+
+static const char* SerializeBoolean(bool value) {
+ return value ? "true" : "false";
+}
+
+static std::string SerializeServers(
const std::vector<webrtc::PeerConnectionInterface::IceServer>& servers) {
- string result = "[";
+ std::string result = "[";
for (size_t i = 0; i < servers.size(); ++i) {
result += servers[i].uri;
if (i != servers.size() - 1)
@@ -43,67 +49,45 @@ static string SerializeServers(
return result;
}
-static RTCMediaConstraints GetNativeMediaConstraints(
+static std::string SerializeMediaConstraints(
const blink::WebMediaConstraints& constraints) {
- RTCMediaConstraints native_constraints;
+ return constraints.toString().utf8();
+}
- if (constraints.isNull())
- return native_constraints;
+static std::string SerializeOfferOptions(
+ const blink::WebRTCOfferOptions& options) {
+ if (options.isNull())
+ return "null";
- blink::WebVector<blink::WebMediaConstraint> mandatory;
- constraints.getMandatoryConstraints(mandatory);
- for (size_t i = 0; i < mandatory.size(); ++i) {
- native_constraints.AddMandatory(
- mandatory[i].m_name.utf8(), mandatory[i].m_value.utf8(), false);
- }
+ std::ostringstream result;
+ result << "offerToReceiveVideo: " << options.offerToReceiveVideo()
+ << ", offerToReceiveAudio: " << options.offerToReceiveAudio()
+ << ", voiceActivityDetection: "
+ << SerializeBoolean(options.voiceActivityDetection())
+ << ", iceRestart: " << SerializeBoolean(options.iceRestart());
+ return result.str();
+}
- blink::WebVector<blink::WebMediaConstraint> optional;
- constraints.getOptionalConstraints(optional);
- for (size_t i = 0; i < optional.size(); ++i) {
- native_constraints.AddOptional(
- optional[i].m_name.utf8(), optional[i].m_value.utf8(), false);
- }
- return native_constraints;
-}
-
-static string SerializeMediaConstraints(
- const RTCMediaConstraints& constraints) {
- string result;
- MediaConstraintsInterface::Constraints mandatory = constraints.GetMandatory();
- if (!mandatory.empty()) {
- result += "mandatory: {";
- for (size_t i = 0; i < mandatory.size(); ++i) {
- result += mandatory[i].key + ":" + mandatory[i].value;
- if (i != mandatory.size() - 1)
- result += ", ";
- }
- result += "}";
- }
- MediaConstraintsInterface::Constraints optional = constraints.GetOptional();
- if (!optional.empty()) {
- if (!result.empty())
- result += ", ";
- result += "optional: {";
- for (size_t i = 0; i < optional.size(); ++i) {
- result += optional[i].key + ":" + optional[i].value;
- if (i != optional.size() - 1)
- result += ", ";
- }
- result += "}";
- }
- return result;
+static std::string SerializeAnswerOptions(
+ const blink::WebRTCAnswerOptions& options) {
+ if (options.isNull())
+ return "null";
+
+ std::ostringstream result;
+ result << ", voiceActivityDetection: "
+ << SerializeBoolean(options.voiceActivityDetection());
+ return result.str();
}
-static string SerializeMediaStreamComponent(
- const blink::WebMediaStreamTrack component) {
- string id = base::UTF16ToUTF8(base::StringPiece16(component.source().id()));
- return id;
+static std::string SerializeMediaStreamComponent(
+ const blink::WebMediaStreamTrack& component) {
+ return base::UTF16ToUTF8(base::StringPiece16(component.source().id()));
}
-static string SerializeMediaDescriptor(
+static std::string SerializeMediaDescriptor(
const blink::WebMediaStream& stream) {
- string label = base::UTF16ToUTF8(base::StringPiece16(stream.id()));
- string result = "label: " + label;
+ std::string label = base::UTF16ToUTF8(base::StringPiece16(stream.id()));
+ std::string result = "label: " + label;
blink::WebVector<blink::WebMediaStreamTrack> tracks;
stream.audioTracks(tracks);
if (!tracks.isEmpty()) {
@@ -128,9 +112,9 @@ static string SerializeMediaDescriptor(
return result;
}
-static std::string SerializeIceTransportType(
+static const char* SerializeIceTransportType(
webrtc::PeerConnectionInterface::IceTransportsType type) {
- string transport_type;
+ const char* transport_type = "";
switch (type) {
case webrtc::PeerConnectionInterface::kNone:
transport_type = "none";
@@ -150,9 +134,9 @@ static std::string SerializeIceTransportType(
return transport_type;
}
-static std::string SerializeBundlePolicy(
+static const char* SerializeBundlePolicy(
webrtc::PeerConnectionInterface::BundlePolicy policy) {
- string policy_str;
+ const char* policy_str = "";
switch (policy) {
case webrtc::PeerConnectionInterface::kBundlePolicyBalanced:
policy_str = "balanced";
@@ -169,9 +153,9 @@ static std::string SerializeBundlePolicy(
return policy_str;
}
-static std::string SerializeRtcpMuxPolicy(
+static const char* SerializeRtcpMuxPolicy(
webrtc::PeerConnectionInterface::RtcpMuxPolicy policy) {
- string policy_str;
+ const char* policy_str = "";
switch (policy) {
case webrtc::PeerConnectionInterface::kRtcpMuxPolicyNegotiate:
policy_str = "negotiate";
@@ -190,9 +174,9 @@ static std::string SerializeRtcpMuxPolicy(
result = #state; \
break;
-static string GetSignalingStateString(
+static const char* GetSignalingStateString(
WebRTCPeerConnectionHandlerClient::SignalingState state) {
- string result;
+ const char* result = "";
switch (state) {
GET_STRING_OF_STATE(SignalingStateStable)
GET_STRING_OF_STATE(SignalingStateHaveLocalOffer)
@@ -207,9 +191,9 @@ static string GetSignalingStateString(
return result;
}
-static string GetIceConnectionStateString(
+static const char* GetIceConnectionStateString(
WebRTCPeerConnectionHandlerClient::ICEConnectionState state) {
- string result;
+ const char* result = "";
switch (state) {
GET_STRING_OF_STATE(ICEConnectionStateStarting)
GET_STRING_OF_STATE(ICEConnectionStateChecking)
@@ -225,9 +209,9 @@ static string GetIceConnectionStateString(
return result;
}
-static string GetIceGatheringStateString(
+static const char* GetIceGatheringStateString(
WebRTCPeerConnectionHandlerClient::ICEGatheringState state) {
- string result;
+ const char* result = "";
switch (state) {
GET_STRING_OF_STATE(ICEGatheringStateNew)
GET_STRING_OF_STATE(ICEGatheringStateGathering)
@@ -288,7 +272,7 @@ static base::DictionaryValue* GetDictValueStats(const StatsReport& report) {
// Builds a DictionaryValue from the StatsReport.
// The caller takes the ownership of the returned value.
static base::DictionaryValue* GetDictValue(const StatsReport& report) {
- scoped_ptr<base::DictionaryValue> stats, result;
+ std::unique_ptr<base::DictionaryValue> stats, result;
stats.reset(GetDictValueStats(report));
if (!stats)
@@ -311,7 +295,7 @@ class InternalStatsObserver : public webrtc::StatsObserver {
: lid_(lid), main_thread_(base::ThreadTaskRunnerHandle::Get()) {}
void OnComplete(const StatsReports& reports) override {
- scoped_ptr<base::ListValue> list(new base::ListValue());
+ std::unique_ptr<base::ListValue> list(new base::ListValue());
for (const auto* r : reports) {
base::DictionaryValue* report = GetDictValue(*r);
@@ -337,7 +321,7 @@ class InternalStatsObserver : public webrtc::StatsObserver {
private:
// Static since |this| will most likely have been deleted by the time we
// get here.
- static void OnCompleteImpl(scoped_ptr<base::ListValue> list, int lid) {
+ static void OnCompleteImpl(std::unique_ptr<base::ListValue> list, int lid) {
DCHECK(!list->empty());
RenderThreadImpl::current()->Send(
new PeerConnectionTrackerHost_AddStats(lid, *list.get()));
@@ -347,8 +331,8 @@ class InternalStatsObserver : public webrtc::StatsObserver {
const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
};
-PeerConnectionTracker::PeerConnectionTracker() : next_lid_(1) {
-}
+PeerConnectionTracker::PeerConnectionTracker()
+ : next_local_id_(1), send_target_for_test_(nullptr) {}
PeerConnectionTracker::~PeerConnectionTracker() {
}
@@ -381,6 +365,13 @@ void PeerConnectionTracker::OnGetAllStats() {
}
}
+RenderThread* PeerConnectionTracker::SendTarget() {
+ if (send_target_for_test_) {
+ return send_target_for_test_;
+ }
+ return RenderThreadImpl::current();
+}
+
void PeerConnectionTracker::OnSuspend() {
DCHECK(main_thread_.CalledOnValidThread());
for (PeerConnectionIdMap::iterator it = peer_connection_id_map_.begin();
@@ -392,9 +383,10 @@ void PeerConnectionTracker::OnSuspend() {
void PeerConnectionTracker::RegisterPeerConnection(
RTCPeerConnectionHandler* pc_handler,
const webrtc::PeerConnectionInterface::RTCConfiguration& config,
- const RTCMediaConstraints& constraints,
+ const blink::WebMediaConstraints& constraints,
const blink::WebFrame* frame) {
DCHECK(main_thread_.CalledOnValidThread());
+ DCHECK_EQ(GetLocalIDForHandler(pc_handler), -1);
DVLOG(1) << "PeerConnectionTracker::RegisterPeerConnection()";
PeerConnectionInfo info;
@@ -406,13 +398,13 @@ void PeerConnectionTracker::RegisterPeerConnection(
"rtcpMuxPolicy: " + SerializeRtcpMuxPolicy(config.rtcp_mux_policy) + " }";
info.constraints = SerializeMediaConstraints(constraints);
- info.url = frame->document().url().string().utf8();
- RenderThreadImpl::current()->Send(
- new PeerConnectionTrackerHost_AddPeerConnection(info));
+ if (frame)
+ info.url = frame->document().url().string().utf8();
+ else
+ info.url = "test:testing";
+ SendTarget()->Send(new PeerConnectionTrackerHost_AddPeerConnection(info));
- DCHECK(peer_connection_id_map_.find(pc_handler) ==
- peer_connection_id_map_.end());
- peer_connection_id_map_[pc_handler] = info.lid;
+ peer_connection_id_map_.insert(std::make_pair(pc_handler, info.lid));
}
void PeerConnectionTracker::UnregisterPeerConnection(
@@ -429,7 +421,7 @@ void PeerConnectionTracker::UnregisterPeerConnection(
return;
}
- RenderThreadImpl::current()->Send(
+ SendTarget()->Send(
new PeerConnectionTrackerHost_RemovePeerConnection(it->second));
peer_connection_id_map_.erase(it);
@@ -437,19 +429,47 @@ void PeerConnectionTracker::UnregisterPeerConnection(
void PeerConnectionTracker::TrackCreateOffer(
RTCPeerConnectionHandler* pc_handler,
- const RTCMediaConstraints& constraints) {
+ const blink::WebRTCOfferOptions& options) {
+ DCHECK(main_thread_.CalledOnValidThread());
+ int id = GetLocalIDForHandler(pc_handler);
+ if (id == -1)
+ return;
+ SendPeerConnectionUpdate(id, "createOffer",
+ "options: {" + SerializeOfferOptions(options) + "}");
+}
+
+void PeerConnectionTracker::TrackCreateOffer(
+ RTCPeerConnectionHandler* pc_handler,
+ const blink::WebMediaConstraints& constraints) {
DCHECK(main_thread_.CalledOnValidThread());
+ int id = GetLocalIDForHandler(pc_handler);
+ if (id == -1)
+ return;
SendPeerConnectionUpdate(
- pc_handler, "createOffer",
+ id, "createOffer",
"constraints: {" + SerializeMediaConstraints(constraints) + "}");
}
void PeerConnectionTracker::TrackCreateAnswer(
RTCPeerConnectionHandler* pc_handler,
- const RTCMediaConstraints& constraints) {
+ const blink::WebRTCAnswerOptions& options) {
DCHECK(main_thread_.CalledOnValidThread());
+ int id = GetLocalIDForHandler(pc_handler);
+ if (id == -1)
+ return;
SendPeerConnectionUpdate(
- pc_handler, "createAnswer",
+ id, "createAnswer", "options: {" + SerializeAnswerOptions(options) + "}");
+}
+
+void PeerConnectionTracker::TrackCreateAnswer(
+ RTCPeerConnectionHandler* pc_handler,
+ const blink::WebMediaConstraints& constraints) {
+ DCHECK(main_thread_.CalledOnValidThread());
+ int id = GetLocalIDForHandler(pc_handler);
+ if (id == -1)
+ return;
+ SendPeerConnectionUpdate(
+ id, "createAnswer",
"constraints: {" + SerializeMediaConstraints(constraints) + "}");
}
@@ -457,38 +477,35 @@ void PeerConnectionTracker::TrackSetSessionDescription(
RTCPeerConnectionHandler* pc_handler,
const std::string& sdp, const std::string& type, Source source) {
DCHECK(main_thread_.CalledOnValidThread());
- string value = "type: " + type + ", sdp: " + sdp;
+ int id = GetLocalIDForHandler(pc_handler);
+ if (id == -1)
+ return;
+ std::string value = "type: " + type + ", sdp: " + sdp;
SendPeerConnectionUpdate(
- pc_handler,
+ id,
source == SOURCE_LOCAL ? "setLocalDescription" : "setRemoteDescription",
value);
}
void PeerConnectionTracker::TrackUpdateIce(
- RTCPeerConnectionHandler* pc_handler,
- const webrtc::PeerConnectionInterface::RTCConfiguration& config,
- const RTCMediaConstraints& options) {
+ RTCPeerConnectionHandler* pc_handler,
+ const webrtc::PeerConnectionInterface::RTCConfiguration& config) {
DCHECK(main_thread_.CalledOnValidThread());
- string servers_string = "servers: " + SerializeServers(config.servers);
-
- string transport_type =
- "iceTransportType: " + SerializeIceTransportType(config.type);
-
- string bundle_policy =
- "bundlePolicy: " + SerializeBundlePolicy(config.bundle_policy);
-
- string rtcp_mux_policy =
- "rtcpMuxPolicy: " + SerializeRtcpMuxPolicy(config.rtcp_mux_policy);
+ int id = GetLocalIDForHandler(pc_handler);
+ if (id == -1)
+ return;
- string constraints =
- "constraints: {" + SerializeMediaConstraints(options) + "}";
+ std::ostringstream result;
+ result << "servers: " << SerializeServers(config.servers)
+ << "iceTransportType: " << SerializeIceTransportType(config.type)
+ << "bundlePolicy: " << SerializeBundlePolicy(config.bundle_policy)
+ << "rtcpMuxPolicy: " << SerializeRtcpMuxPolicy(config.rtcp_mux_policy)
+ << "}";
SendPeerConnectionUpdate(
- pc_handler,
+ id,
"updateIce",
- servers_string + ", " + transport_type + ", " +
- bundle_policy + ", " + rtcp_mux_policy + ", " +
- constraints);
+ result.str());
}
void PeerConnectionTracker::TrackAddIceCandidate(
@@ -497,22 +514,24 @@ void PeerConnectionTracker::TrackAddIceCandidate(
Source source,
bool succeeded) {
DCHECK(main_thread_.CalledOnValidThread());
- string value =
- "sdpMid: " +
- base::UTF16ToUTF8(base::StringPiece16(candidate.sdpMid())) + ", " +
- "sdpMLineIndex: " + base::UintToString(candidate.sdpMLineIndex()) +
+ int id = GetLocalIDForHandler(pc_handler);
+ if (id == -1)
+ return;
+ std::string value =
+ "sdpMid: " + base::UTF16ToUTF8(base::StringPiece16(candidate.sdpMid())) +
+ ", " + "sdpMLineIndex: " + base::UintToString(candidate.sdpMLineIndex()) +
", " + "candidate: " +
base::UTF16ToUTF8(base::StringPiece16(candidate.candidate()));
// OnIceCandidate always succeeds as it's a callback from the browser.
DCHECK(source != SOURCE_LOCAL || succeeded);
- string event =
+ const char* event =
(source == SOURCE_LOCAL) ? "onIceCandidate"
: (succeeded ? "addIceCandidate"
: "addIceCandidateFailed");
- SendPeerConnectionUpdate(pc_handler, event, value);
+ SendPeerConnectionUpdate(id, event, value);
}
void PeerConnectionTracker::TrackAddStream(
@@ -520,8 +539,11 @@ void PeerConnectionTracker::TrackAddStream(
const blink::WebMediaStream& stream,
Source source) {
DCHECK(main_thread_.CalledOnValidThread());
+ int id = GetLocalIDForHandler(pc_handler);
+ if (id == -1)
+ return;
SendPeerConnectionUpdate(
- pc_handler, source == SOURCE_LOCAL ? "addStream" : "onAddStream",
+ id, source == SOURCE_LOCAL ? "addStream" : "onAddStream",
SerializeMediaDescriptor(stream));
}
@@ -530,8 +552,11 @@ void PeerConnectionTracker::TrackRemoveStream(
const blink::WebMediaStream& stream,
Source source){
DCHECK(main_thread_.CalledOnValidThread());
+ int id = GetLocalIDForHandler(pc_handler);
+ if (id == -1)
+ return;
SendPeerConnectionUpdate(
- pc_handler, source == SOURCE_LOCAL ? "removeStream" : "onRemoveStream",
+ id, source == SOURCE_LOCAL ? "removeStream" : "onRemoveStream",
SerializeMediaDescriptor(stream));
}
@@ -540,33 +565,45 @@ void PeerConnectionTracker::TrackCreateDataChannel(
const webrtc::DataChannelInterface* data_channel,
Source source) {
DCHECK(main_thread_.CalledOnValidThread());
- string value = "label: " + data_channel->label() +
- ", reliable: " + (data_channel->reliable() ? "true" : "false");
+ int id = GetLocalIDForHandler(pc_handler);
+ if (id == -1)
+ return;
+ std::string value = "label: " + data_channel->label() + ", reliable: " +
+ SerializeBoolean(data_channel->reliable());
SendPeerConnectionUpdate(
- pc_handler,
+ id,
source == SOURCE_LOCAL ? "createLocalDataChannel" : "onRemoteDataChannel",
value);
}
void PeerConnectionTracker::TrackStop(RTCPeerConnectionHandler* pc_handler) {
DCHECK(main_thread_.CalledOnValidThread());
- SendPeerConnectionUpdate(pc_handler, "stop", std::string());
+ int id = GetLocalIDForHandler(pc_handler);
+ if (id == -1)
+ return;
+ SendPeerConnectionUpdate(id, "stop", std::string());
}
void PeerConnectionTracker::TrackSignalingStateChange(
RTCPeerConnectionHandler* pc_handler,
WebRTCPeerConnectionHandlerClient::SignalingState state) {
DCHECK(main_thread_.CalledOnValidThread());
+ int id = GetLocalIDForHandler(pc_handler);
+ if (id == -1)
+ return;
SendPeerConnectionUpdate(
- pc_handler, "signalingStateChange", GetSignalingStateString(state));
+ id, "signalingStateChange", GetSignalingStateString(state));
}
void PeerConnectionTracker::TrackIceConnectionStateChange(
RTCPeerConnectionHandler* pc_handler,
WebRTCPeerConnectionHandlerClient::ICEConnectionState state) {
DCHECK(main_thread_.CalledOnValidThread());
+ int id = GetLocalIDForHandler(pc_handler);
+ if (id == -1)
+ return;
SendPeerConnectionUpdate(
- pc_handler, "iceConnectionStateChange",
+ id, "iceConnectionStateChange",
GetIceConnectionStateString(state));
}
@@ -574,16 +611,24 @@ void PeerConnectionTracker::TrackIceGatheringStateChange(
RTCPeerConnectionHandler* pc_handler,
WebRTCPeerConnectionHandlerClient::ICEGatheringState state) {
DCHECK(main_thread_.CalledOnValidThread());
+ int id = GetLocalIDForHandler(pc_handler);
+ if (id == -1)
+ return;
SendPeerConnectionUpdate(
- pc_handler, "iceGatheringStateChange",
+ id, "iceGatheringStateChange",
GetIceGatheringStateString(state));
}
void PeerConnectionTracker::TrackSessionDescriptionCallback(
- RTCPeerConnectionHandler* pc_handler, Action action,
- const string& callback_type, const string& value) {
+ RTCPeerConnectionHandler* pc_handler,
+ Action action,
+ const std::string& callback_type,
+ const std::string& value) {
DCHECK(main_thread_.CalledOnValidThread());
- string update_type;
+ int id = GetLocalIDForHandler(pc_handler);
+ if (id == -1)
+ return;
+ std::string update_type;
switch (action) {
case ACTION_SET_LOCAL_DESCRIPTION:
update_type = "setLocalDescription";
@@ -603,55 +648,68 @@ void PeerConnectionTracker::TrackSessionDescriptionCallback(
}
update_type += callback_type;
- SendPeerConnectionUpdate(pc_handler, update_type, value);
+ SendPeerConnectionUpdate(id, update_type.c_str(), value);
}
void PeerConnectionTracker::TrackOnRenegotiationNeeded(
RTCPeerConnectionHandler* pc_handler) {
DCHECK(main_thread_.CalledOnValidThread());
- SendPeerConnectionUpdate(pc_handler, "onRenegotiationNeeded", std::string());
+ int id = GetLocalIDForHandler(pc_handler);
+ if (id == -1)
+ return;
+ SendPeerConnectionUpdate(id, "onRenegotiationNeeded", std::string());
}
void PeerConnectionTracker::TrackCreateDTMFSender(
RTCPeerConnectionHandler* pc_handler,
const blink::WebMediaStreamTrack& track) {
DCHECK(main_thread_.CalledOnValidThread());
- SendPeerConnectionUpdate(pc_handler, "createDTMFSender",
+ int id = GetLocalIDForHandler(pc_handler);
+ if (id == -1)
+ return;
+ SendPeerConnectionUpdate(id, "createDTMFSender",
base::UTF16ToUTF8(base::StringPiece16(track.id())));
}
void PeerConnectionTracker::TrackGetUserMedia(
const blink::WebUserMediaRequest& user_media_request) {
DCHECK(main_thread_.CalledOnValidThread());
- RTCMediaConstraints audio_constraints(
- GetNativeMediaConstraints(user_media_request.audioConstraints()));
- RTCMediaConstraints video_constraints(
- GetNativeMediaConstraints(user_media_request.videoConstraints()));
- RenderThreadImpl::current()->Send(new PeerConnectionTrackerHost_GetUserMedia(
- user_media_request.securityOrigin().toString().utf8(),
- user_media_request.audio(),
- user_media_request.video(),
- SerializeMediaConstraints(audio_constraints),
- SerializeMediaConstraints(video_constraints)));
+ SendTarget()->Send(new PeerConnectionTrackerHost_GetUserMedia(
+ user_media_request.getSecurityOrigin().toString().utf8(),
+ user_media_request.audio(), user_media_request.video(),
+ SerializeMediaConstraints(user_media_request.audioConstraints()),
+ SerializeMediaConstraints(user_media_request.videoConstraints())));
}
int PeerConnectionTracker::GetNextLocalID() {
DCHECK(main_thread_.CalledOnValidThread());
- return next_lid_++;
+ if (next_local_id_< 0)
+ next_local_id_ = 1;
+ return next_local_id_++;
+}
+
+int PeerConnectionTracker::GetLocalIDForHandler(
+ RTCPeerConnectionHandler* handler) const {
+ DCHECK(main_thread_.CalledOnValidThread());
+ const auto found = peer_connection_id_map_.find(handler);
+ if (found == peer_connection_id_map_.end())
+ return -1;
+ DCHECK_NE(found->second, -1);
+ return found->second;
}
void PeerConnectionTracker::SendPeerConnectionUpdate(
- RTCPeerConnectionHandler* pc_handler,
- const std::string& type,
+ int local_id,
+ const char* callback_type,
const std::string& value) {
DCHECK(main_thread_.CalledOnValidThread());
- if (peer_connection_id_map_.find(pc_handler) == peer_connection_id_map_.end())
- return;
+ SendTarget()->Send(new PeerConnectionTrackerHost_UpdatePeerConnection(
+ local_id, std::string(callback_type), value));
+}
- RenderThreadImpl::current()->Send(
- new PeerConnectionTrackerHost_UpdatePeerConnection(
- peer_connection_id_map_[pc_handler], type, value));
+void PeerConnectionTracker::OverrideSendTargetForTesting(RenderThread* target) {
+ send_target_for_test_ = target;
}
} // namespace content
diff --git a/chromium/content/renderer/media/peer_connection_tracker.h b/chromium/content/renderer/media/peer_connection_tracker.h
index 63c55145e35..80b823c6101 100644
--- a/chromium/content/renderer/media/peer_connection_tracker.h
+++ b/chromium/content/renderer/media/peer_connection_tracker.h
@@ -15,11 +15,14 @@
#include "third_party/WebKit/public/platform/WebMediaStream.h"
#include "third_party/WebKit/public/platform/WebRTCPeerConnectionHandlerClient.h"
#include "third_party/WebKit/public/platform/WebRTCSessionDescription.h"
-#include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h"
+#include "third_party/webrtc/api/peerconnectioninterface.h"
namespace blink {
class WebFrame;
+class WebMediaConstraints;
+class WebRTCAnswerOptions;
class WebRTCICECandidate;
+class WebRTCOfferOptions;
class WebString;
class WebRTCSessionDescription;
class WebUserMediaRequest;
@@ -30,8 +33,8 @@ class DataChannelInterface;
} // namespace webrtc
namespace content {
-class RTCMediaConstraints;
class RTCPeerConnectionHandler;
+class RenderThread;
// This class collects data about each peer connection,
// sends it to the browser process, and handles messages
@@ -75,7 +78,7 @@ class CONTENT_EXPORT PeerConnectionTracker
void RegisterPeerConnection(
RTCPeerConnectionHandler* pc_handler,
const webrtc::PeerConnectionInterface::RTCConfiguration& config,
- const RTCMediaConstraints& constraints,
+ const blink::WebMediaConstraints& constraints,
const blink::WebFrame* frame);
// Sends an update when a PeerConnection has been destroyed.
@@ -85,9 +88,14 @@ class CONTENT_EXPORT PeerConnectionTracker
// The |pc_handler| is the handler object associated with the PeerConnection,
// the |constraints| is the media constraints used to create the offer/answer.
virtual void TrackCreateOffer(RTCPeerConnectionHandler* pc_handler,
- const RTCMediaConstraints& constraints);
+ const blink::WebRTCOfferOptions& options);
+ // TODO(hta): Get rid of the version below.
+ virtual void TrackCreateOffer(RTCPeerConnectionHandler* pc_handler,
+ const blink::WebMediaConstraints& options);
+ virtual void TrackCreateAnswer(RTCPeerConnectionHandler* pc_handler,
+ const blink::WebRTCAnswerOptions& options);
virtual void TrackCreateAnswer(RTCPeerConnectionHandler* pc_handler,
- const RTCMediaConstraints& constraints);
+ const blink::WebMediaConstraints& constraints);
// Sends an update when setLocalDescription or setRemoteDescription is called.
virtual void TrackSetSessionDescription(
@@ -97,8 +105,7 @@ class CONTENT_EXPORT PeerConnectionTracker
// Sends an update when Ice candidates are updated.
virtual void TrackUpdateIce(
RTCPeerConnectionHandler* pc_handler,
- const webrtc::PeerConnectionInterface::RTCConfiguration& config,
- const RTCMediaConstraints& options);
+ const webrtc::PeerConnectionInterface::RTCConfiguration& config);
// Sends an update when an Ice candidate is added.
virtual void TrackAddIceCandidate(
@@ -160,28 +167,50 @@ class CONTENT_EXPORT PeerConnectionTracker
virtual void TrackGetUserMedia(
const blink::WebUserMediaRequest& user_media_request);
+ // For testing: Override the class that gets posted messages.
+ void OverrideSendTargetForTesting(RenderThread* target);
+
private:
// Assign a local ID to a peer connection so that the browser process can
// uniquely identify a peer connection in the renderer process.
+ // The return value will always be positive.
int GetNextLocalID();
+ // Looks up a handler in our map and if found, returns its ID. If the handler
+ // is not registered, the return value will be -1.
+ int GetLocalIDForHandler(RTCPeerConnectionHandler* handler) const;
+
// IPC Message handler for getting all stats.
void OnGetAllStats();
// Called when the browser process reports a suspend event from the OS.
void OnSuspend();
- void SendPeerConnectionUpdate(RTCPeerConnectionHandler* pc_handler,
- const std::string& callback_type,
+ // Called to deliver an update to the host (PeerConnectionTrackerHost).
+ // |local_id| - The id of the registered RTCPeerConnectionHandler.
+ // Using an id instead of the hander pointer is done on purpose
+ // to force doing the lookup before building the callback data
+ // in case the handler isn't registered.
+ // |callback_type| - A string, most often static, that represents the type
+ // of operation that the data stored in |value| comes from.
+ // E.g. "createOffer", "createAnswer",
+ // "setRemoteDescription" etc.
+ // |value| - A json serialized string containing all the information for the
+ // update event.
+ void SendPeerConnectionUpdate(int local_id,
+ const char* callback_type,
const std::string& value);
+ RenderThread* SendTarget();
+
// This map stores the local ID assigned to each RTCPeerConnectionHandler.
typedef std::map<RTCPeerConnectionHandler*, int> PeerConnectionIdMap;
PeerConnectionIdMap peer_connection_id_map_;
// This keeps track of the next available local ID.
- int next_lid_;
+ int next_local_id_;
base::ThreadChecker main_thread_;
+ RenderThread* send_target_for_test_;
DISALLOW_COPY_AND_ASSIGN(PeerConnectionTracker);
};
diff --git a/chromium/content/renderer/media/peer_connection_tracker_unittest.cc b/chromium/content/renderer/media/peer_connection_tracker_unittest.cc
new file mode 100644
index 00000000000..ca5ff796c8c
--- /dev/null
+++ b/chromium/content/renderer/media/peer_connection_tracker_unittest.cc
@@ -0,0 +1,82 @@
+// Copyright (c) 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/peer_connection_tracker.h"
+
+#include "content/common/media/peer_connection_tracker_messages.h"
+#include "content/public/test/mock_render_thread.h"
+#include "content/renderer/media/mock_web_rtc_peer_connection_handler_client.h"
+#include "content/renderer/media/rtc_peer_connection_handler.h"
+#include "ipc/ipc_message_macros.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
+#include "third_party/WebKit/public/platform/WebRTCOfferOptions.h"
+
+using ::testing::_;
+
+namespace content {
+
+namespace {
+
+class MockSendTargetThread : public MockRenderThread {
+ public:
+ MOCK_METHOD3(OnUpdatePeerConnection, void(int, std::string, std::string));
+ MOCK_METHOD1(OnAddPeerConnection, void(PeerConnectionInfo));
+
+ private:
+ bool OnMessageReceived(const IPC::Message& msg) override;
+};
+
+bool MockSendTargetThread::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(MockSendTargetThread, msg)
+ IPC_MESSAGE_HANDLER(PeerConnectionTrackerHost_UpdatePeerConnection,
+ OnUpdatePeerConnection)
+ IPC_MESSAGE_HANDLER(PeerConnectionTrackerHost_AddPeerConnection,
+ OnAddPeerConnection)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+class MockPeerConnectionHandler : public RTCPeerConnectionHandler {
+ public:
+ MockPeerConnectionHandler() : RTCPeerConnectionHandler(&client_, nullptr) {}
+
+ private:
+ MockWebRTCPeerConnectionHandlerClient client_;
+};
+
+} // namespace
+
+TEST(PeerConnectionTrackerTest, CreatingObject) {
+ PeerConnectionTracker tracker;
+}
+
+TEST(PeerConnectionTrackerTest, TrackCreateOffer) {
+ PeerConnectionTracker tracker;
+ // Note: blink::WebRTCOfferOptions is not mockable. So we can't write
+ // tests for anything but a null options parameter.
+ blink::WebRTCOfferOptions options(0, 0, false, false);
+ // Initialization stuff. This can be separated into a test class.
+ MockPeerConnectionHandler pc_handler;
+ MockSendTargetThread target_thread;
+ webrtc::PeerConnectionInterface::RTCConfiguration config;
+ blink::WebMediaConstraints constraints;
+ tracker.OverrideSendTargetForTesting(&target_thread);
+ EXPECT_CALL(target_thread, OnAddPeerConnection(_));
+ tracker.RegisterPeerConnection(&pc_handler, config, constraints, nullptr);
+ // Back to the test.
+ EXPECT_CALL(target_thread,
+ OnUpdatePeerConnection(
+ _, "createOffer",
+ "options: {offerToReceiveVideo: 0, offerToReceiveAudio: 0, "
+ "voiceActivityDetection: false, iceRestart: false}"));
+ tracker.TrackCreateOffer(&pc_handler, options);
+}
+
+// TODO(hta): Write tests for the other tracking functions.
+
+} // namespace
diff --git a/chromium/content/renderer/media/pepper_to_video_track_adapter_unittest.cc b/chromium/content/renderer/media/pepper_to_video_track_adapter_unittest.cc
index 219667eed66..42aec361951 100644
--- a/chromium/content/renderer/media/pepper_to_video_track_adapter_unittest.cc
+++ b/chromium/content/renderer/media/pepper_to_video_track_adapter_unittest.cc
@@ -49,7 +49,7 @@ class PepperToVideoTrackAdapterTest : public PpapiUnittest {
// Sources inside |registry_| into believing they are on the right threads.
const ChildProcess child_process_;
const MockRenderThread render_thread_;
- scoped_ptr<MockMediaStreamRegistry> registry_;
+ std::unique_ptr<MockMediaStreamRegistry> registry_;
};
TEST_F(PepperToVideoTrackAdapterTest, Open) {
diff --git a/chromium/content/renderer/media/remote_media_stream_impl.cc b/chromium/content/renderer/media/remote_media_stream_impl.cc
index b365e6dbe80..35a3cb49280 100644
--- a/chromium/content/renderer/media/remote_media_stream_impl.cc
+++ b/chromium/content/renderer/media/remote_media_stream_impl.cc
@@ -133,7 +133,7 @@ class RemoteVideoTrackAdapter
const scoped_refptr<base::SingleThreadTaskRunner>& main_thread,
webrtc::VideoTrackInterface* webrtc_track)
: RemoteMediaStreamTrackAdapter(main_thread, webrtc_track) {
- scoped_ptr<TrackObserver> observer(
+ std::unique_ptr<TrackObserver> observer(
new TrackObserver(main_thread, observed_track().get()));
// Here, we use base::Unretained() to avoid a circular reference.
webkit_initialize_ = base::Bind(
@@ -147,15 +147,16 @@ class RemoteVideoTrackAdapter
DCHECK(main_thread_->BelongsToCurrentThread());
if (initialized()) {
static_cast<MediaStreamRemoteVideoSource*>(
- webkit_track()->source().extraData())->OnSourceTerminated();
+ webkit_track()->source().getExtraData())
+ ->OnSourceTerminated();
}
}
private:
- void InitializeWebkitVideoTrack(scoped_ptr<TrackObserver> observer,
+ void InitializeWebkitVideoTrack(std::unique_ptr<TrackObserver> observer,
bool enabled) {
DCHECK(main_thread_->BelongsToCurrentThread());
- scoped_ptr<MediaStreamRemoteVideoSource> video_source(
+ std::unique_ptr<MediaStreamRemoteVideoSource> video_source(
new MediaStreamRemoteVideoSource(std::move(observer)));
InitializeWebkitTrack(blink::WebMediaStreamSource::TypeVideo);
webkit_track()->source().setExtraData(video_source.get());
@@ -261,10 +262,6 @@ void RemoteAudioTrackAdapter::OnChangedOnMainThread(
state_ = state;
switch (state) {
- case webrtc::MediaStreamTrackInterface::kInitializing:
- // Ignore the kInitializing state since there is no match in
- // WebMediaStreamSource::ReadyState.
- break;
case webrtc::MediaStreamTrackInterface::kLive:
webkit_track()->source().setReadyState(
blink::WebMediaStreamSource::ReadyStateLive);
@@ -309,8 +306,10 @@ void RemoteMediaStreamImpl::Observer::Unregister() {
}
void RemoteMediaStreamImpl::Observer::OnChanged() {
- scoped_ptr<RemoteAudioTrackAdapters> audio(new RemoteAudioTrackAdapters());
- scoped_ptr<RemoteVideoTrackAdapters> video(new RemoteVideoTrackAdapters());
+ std::unique_ptr<RemoteAudioTrackAdapters> audio(
+ new RemoteAudioTrackAdapters());
+ std::unique_ptr<RemoteVideoTrackAdapters> video(
+ new RemoteVideoTrackAdapters());
CreateAdaptersForTracks(
webrtc_stream_->GetAudioTracks(), audio.get(), main_thread_);
@@ -323,8 +322,8 @@ void RemoteMediaStreamImpl::Observer::OnChanged() {
}
void RemoteMediaStreamImpl::Observer::OnChangedOnMainThread(
- scoped_ptr<RemoteAudioTrackAdapters> audio_tracks,
- scoped_ptr<RemoteVideoTrackAdapters> video_tracks) {
+ std::unique_ptr<RemoteAudioTrackAdapters> audio_tracks,
+ std::unique_ptr<RemoteVideoTrackAdapters> video_tracks) {
DCHECK(main_thread_->BelongsToCurrentThread());
if (media_stream_)
media_stream_->OnChanged(std::move(audio_tracks), std::move(video_tracks));
@@ -377,8 +376,8 @@ void RemoteMediaStreamImpl::InitializeOnMainThread(const std::string& label) {
}
void RemoteMediaStreamImpl::OnChanged(
- scoped_ptr<RemoteAudioTrackAdapters> audio_tracks,
- scoped_ptr<RemoteVideoTrackAdapters> video_tracks) {
+ std::unique_ptr<RemoteAudioTrackAdapters> audio_tracks,
+ std::unique_ptr<RemoteVideoTrackAdapters> video_tracks) {
// Find removed tracks.
auto audio_it = audio_track_observers_.begin();
while (audio_it != audio_track_observers_.end()) {
diff --git a/chromium/content/renderer/media/remote_media_stream_impl.h b/chromium/content/renderer/media/remote_media_stream_impl.h
index 91b929401c1..2106ad1cc9e 100644
--- a/chromium/content/renderer/media/remote_media_stream_impl.h
+++ b/chromium/content/renderer/media/remote_media_stream_impl.h
@@ -5,16 +5,17 @@
#ifndef CONTENT_RENDERER_MEDIA_REMOTE_MEDIA_STREAM_IMPL_H_
#define CONTENT_RENDERER_MEDIA_REMOTE_MEDIA_STREAM_IMPL_H_
+#include <memory>
+
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
#include "third_party/WebKit/public/platform/WebMediaStream.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
namespace content {
@@ -77,16 +78,16 @@ class CONTENT_EXPORT RemoteMediaStreamImpl {
void OnChanged() override;
void OnChangedOnMainThread(
- scoped_ptr<RemoteAudioTrackAdapters> audio_tracks,
- scoped_ptr<RemoteVideoTrackAdapters> video_tracks);
+ std::unique_ptr<RemoteAudioTrackAdapters> audio_tracks,
+ std::unique_ptr<RemoteVideoTrackAdapters> video_tracks);
base::WeakPtr<RemoteMediaStreamImpl> media_stream_;
const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
scoped_refptr<webrtc::MediaStreamInterface> webrtc_stream_;
};
- void OnChanged(scoped_ptr<RemoteAudioTrackAdapters> audio_tracks,
- scoped_ptr<RemoteVideoTrackAdapters> video_tracks);
+ void OnChanged(std::unique_ptr<RemoteAudioTrackAdapters> audio_tracks,
+ std::unique_ptr<RemoteVideoTrackAdapters> video_tracks);
const scoped_refptr<base::SingleThreadTaskRunner> signaling_thread_;
scoped_refptr<Observer> observer_;
diff --git a/chromium/content/renderer/media/render_media_client.cc b/chromium/content/renderer/media/render_media_client.cc
index 4c8876cd693..d84f30da91b 100644
--- a/chromium/content/renderer/media/render_media_client.cc
+++ b/chromium/content/renderer/media/render_media_client.cc
@@ -34,7 +34,7 @@ void RenderMediaClient::AddKeySystemsInfoForUMA(
DVLOG(2) << __FUNCTION__;
#if defined(WIDEVINE_CDM_AVAILABLE)
key_systems_info_for_uma->push_back(media::KeySystemInfoForUMA(
- kWidevineKeySystem, kWidevineKeySystemNameForUMA, true));
+ kWidevineKeySystem, kWidevineKeySystemNameForUMA));
#endif // WIDEVINE_CDM_AVAILABLE
}
@@ -92,7 +92,7 @@ void RenderMediaClient::RecordRapporURL(const std::string& metric,
}
void RenderMediaClient::SetTickClockForTesting(
- scoped_ptr<base::TickClock> tick_clock) {
+ std::unique_ptr<base::TickClock> tick_clock) {
tick_clock_.swap(tick_clock);
}
diff --git a/chromium/content/renderer/media/render_media_client.h b/chromium/content/renderer/media/render_media_client.h
index 01d5189bbc7..a0ad2efe3a6 100644
--- a/chromium/content/renderer/media/render_media_client.h
+++ b/chromium/content/renderer/media/render_media_client.h
@@ -5,16 +5,16 @@
#ifndef CONTENT_RENDERER_MEDIA_RENDER_MEDIA_CLIENT_H_
#define CONTENT_RENDERER_MEDIA_RENDER_MEDIA_CLIENT_H_
+#include <memory>
+
#include "base/lazy_instance.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/threading/thread_checker.h"
#include "base/time/tick_clock.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
#include "media/base/media_client.h"
-
-#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
+#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
namespace content {
@@ -32,7 +32,7 @@ class CONTENT_EXPORT RenderMediaClient : public media::MediaClient {
std::vector<media::KeySystemInfo>* key_systems_info) final;
void RecordRapporURL(const std::string& metric, const GURL& url) final;
- void SetTickClockForTesting(scoped_ptr<base::TickClock> tick_clock);
+ void SetTickClockForTesting(std::unique_ptr<base::TickClock> tick_clock);
private:
friend struct base::DefaultLazyInstanceTraits<RenderMediaClient>;
@@ -52,7 +52,7 @@ class CONTENT_EXPORT RenderMediaClient : public media::MediaClient {
bool is_update_needed_;
base::TimeTicks last_update_time_ticks_;
- scoped_ptr<base::TickClock> tick_clock_;
+ std::unique_ptr<base::TickClock> tick_clock_;
DISALLOW_COPY_AND_ASSIGN(RenderMediaClient);
};
diff --git a/chromium/content/renderer/media/render_media_client_unittest.cc b/chromium/content/renderer/media/render_media_client_unittest.cc
index 5147c49b3b1..4bac0b78091 100644
--- a/chromium/content/renderer/media/render_media_client_unittest.cc
+++ b/chromium/content/renderer/media/render_media_client_unittest.cc
@@ -126,7 +126,7 @@ TEST_F(RenderMediaClientTest, KeySystemNameForUMA) {
TEST_F(RenderMediaClientTest, IsKeySystemsUpdateNeeded) {
base::SimpleTestTickClock* tick_clock = new base::SimpleTestTickClock();
render_media_client_->SetTickClockForTesting(
- scoped_ptr<base::TickClock>(tick_clock));
+ std::unique_ptr<base::TickClock>(tick_clock));
// IsKeySystemsUpdateNeeded() always returns true after construction.
EXPECT_TRUE(render_media_client_->IsKeySystemsUpdateNeeded());
diff --git a/chromium/content/renderer/media/render_media_log.cc b/chromium/content/renderer/media/render_media_log.cc
index eae60c006a9..0d1e88fe2ef 100644
--- a/chromium/content/renderer/media/render_media_log.cc
+++ b/chromium/content/renderer/media/render_media_log.cc
@@ -4,11 +4,14 @@
#include "content/renderer/media/render_media_log.h"
+#include <sstream>
+
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
+#include "base/time/default_tick_clock.h"
#include "content/common/view_messages.h"
#include "content/public/renderer/render_thread.h"
@@ -34,43 +37,56 @@ namespace content {
RenderMediaLog::RenderMediaLog()
: task_runner_(base::ThreadTaskRunnerHandle::Get()),
tick_clock_(new base::DefaultTickClock()),
- last_ipc_send_time_(tick_clock_->NowTicks()) {
+ last_ipc_send_time_(tick_clock_->NowTicks()),
+ ipc_send_pending_(false) {
DCHECK(RenderThread::Get())
<< "RenderMediaLog must be constructed on the render thread";
}
-void RenderMediaLog::AddEvent(scoped_ptr<media::MediaLogEvent> event) {
- // Always post to preserve the correct order of events.
- // TODO(xhwang): Consider using sorted containers to keep the order and
- // avoid extra posting.
- task_runner_->PostTask(FROM_HERE,
- base::Bind(&RenderMediaLog::AddEventInternal, this,
- base::Passed(&event)));
-}
-
-void RenderMediaLog::AddEventInternal(scoped_ptr<media::MediaLogEvent> event) {
- DCHECK(task_runner_->BelongsToCurrentThread());
-
+void RenderMediaLog::AddEvent(std::unique_ptr<media::MediaLogEvent> event) {
Log(event.get());
- // If there is an event waiting to be sent, there must be a send task pending.
- const bool delayed_ipc_send_pending =
- !queued_media_events_.empty() || last_buffered_extents_changed_event_;
-
- // Keep track of the latest buffered extents properties to avoid sending
- // thousands of events over IPC. See http://crbug.com/352585 for details.
- if (event->type == media::MediaLogEvent::BUFFERED_EXTENTS_CHANGED)
- last_buffered_extents_changed_event_.swap(event);
- else
- queued_media_events_.push_back(*event);
-
- if (delayed_ipc_send_pending)
- return;
+ // For enforcing delay until it's been a second since the last ipc message was
+ // sent.
+ base::TimeDelta delay_for_next_ipc_send;
+
+ {
+ base::AutoLock auto_lock(lock_);
+
+ switch (event->type) {
+ case media::MediaLogEvent::BUFFERED_EXTENTS_CHANGED:
+ // Keep track of the latest buffered extents properties to avoid sending
+ // thousands of events over IPC. See http://crbug.com/352585 for
+ // details.
+ last_buffered_extents_changed_event_.swap(event);
+ // SendQueuedMediaEvents() will enqueue the most recent event of this
+ // kind, if any, prior to sending the event batch.
+ break;
+
+ // Hold onto the most recent PIPELINE_ERROR and MEDIA_LOG_ERROR_ENTRY for
+ // use in GetLastErrorMessage().
+ case media::MediaLogEvent::PIPELINE_ERROR:
+ queued_media_events_.push_back(*event);
+ last_pipeline_error_.swap(event);
+ break;
+ case media::MediaLogEvent::MEDIA_ERROR_LOG_ENTRY:
+ queued_media_events_.push_back(*event);
+ last_media_error_log_entry_.swap(event);
+ break;
+
+ // Just enqueue all other event types for throttled transmission.
+ default:
+ queued_media_events_.push_back(*event);
+ }
+
+ if (ipc_send_pending_)
+ return;
+
+ ipc_send_pending_ = true;
+ delay_for_next_ipc_send = base::TimeDelta::FromSeconds(1) -
+ (tick_clock_->NowTicks() - last_ipc_send_time_);
+ }
- // Delay until it's been a second since the last ipc message was sent.
- base::TimeDelta delay_for_next_ipc_send =
- base::TimeDelta::FromSeconds(1) -
- (tick_clock_->NowTicks() - last_ipc_send_time_);
if (delay_for_next_ipc_send > base::TimeDelta()) {
task_runner_->PostDelayedTask(
FROM_HERE, base::Bind(&RenderMediaLog::SendQueuedMediaEvents, this),
@@ -78,29 +94,58 @@ void RenderMediaLog::AddEventInternal(scoped_ptr<media::MediaLogEvent> event) {
return;
}
- // It's been more than a second so send now.
- SendQueuedMediaEvents();
+ // It's been more than a second so send ASAP.
+ if (task_runner_->BelongsToCurrentThread()) {
+ SendQueuedMediaEvents();
+ return;
+ }
+ task_runner_->PostTask(
+ FROM_HERE, base::Bind(&RenderMediaLog::SendQueuedMediaEvents, this));
+}
+
+std::string RenderMediaLog::GetLastErrorMessage() {
+ base::AutoLock auto_lock(lock_);
+
+ // Return the conditional concatenation of the last pipeline error and the
+ // last media error log.
+ std::stringstream result;
+ if (last_pipeline_error_) {
+ result << MediaEventToLogString(*last_pipeline_error_)
+ << (last_media_error_log_entry_ ? ", " : "");
+ }
+ if (last_media_error_log_entry_)
+ result << MediaEventToLogString(*last_media_error_log_entry_);
+ return result.str();
}
void RenderMediaLog::SendQueuedMediaEvents() {
DCHECK(task_runner_->BelongsToCurrentThread());
- if (last_buffered_extents_changed_event_) {
- queued_media_events_.push_back(*last_buffered_extents_changed_event_);
- last_buffered_extents_changed_event_.reset();
+ std::vector<media::MediaLogEvent> events_to_send;
+ {
+ base::AutoLock auto_lock(lock_);
+
+ DCHECK(ipc_send_pending_);
+ ipc_send_pending_ = false;
+
+ if (last_buffered_extents_changed_event_) {
+ queued_media_events_.push_back(*last_buffered_extents_changed_event_);
+ last_buffered_extents_changed_event_.reset();
+ }
+
+ queued_media_events_.swap(events_to_send);
+ last_ipc_send_time_ = tick_clock_->NowTicks();
}
- RenderThread::Get()->Send(
- new ViewHostMsg_MediaLogEvents(queued_media_events_));
- queued_media_events_.clear();
- last_ipc_send_time_ = tick_clock_->NowTicks();
+ RenderThread::Get()->Send(new ViewHostMsg_MediaLogEvents(events_to_send));
}
RenderMediaLog::~RenderMediaLog() {
}
void RenderMediaLog::SetTickClockForTesting(
- scoped_ptr<base::TickClock> tick_clock) {
+ std::unique_ptr<base::TickClock> tick_clock) {
+ base::AutoLock auto_lock(lock_);
tick_clock_.swap(tick_clock);
last_ipc_send_time_ = tick_clock_->NowTicks();
}
diff --git a/chromium/content/renderer/media/render_media_log.h b/chromium/content/renderer/media/render_media_log.h
index bc486305693..3606b98e928 100644
--- a/chromium/content/renderer/media/render_media_log.h
+++ b/chromium/content/renderer/media/render_media_log.h
@@ -5,18 +5,27 @@
#ifndef CONTENT_RENDERER_MEDIA_RENDER_MEDIA_LOG_H_
#define CONTENT_RENDERER_MEDIA_RENDER_MEDIA_LOG_H_
+#include <string>
#include <vector>
#include "base/macros.h"
+#include "base/synchronization/lock.h"
#include "base/time/time.h"
#include "content/common/content_export.h"
#include "media/base/media_log.h"
+namespace base {
+class TickClock;
+}
+
namespace content {
// RenderMediaLog is an implementation of MediaLog that forwards events to the
// browser process, throttling as necessary.
//
+// It also caches the last error events to support renderer-side reporting to
+// entities like HTMLMediaElement and devtools console.
+//
// To minimize the number of events sent over the wire, only the latest event
// added is sent for high frequency events (e.g., BUFFERED_EXTENTS_CHANGED).
//
@@ -26,29 +35,43 @@ class CONTENT_EXPORT RenderMediaLog : public media::MediaLog {
RenderMediaLog();
// MediaLog implementation.
- void AddEvent(scoped_ptr<media::MediaLogEvent> event) override;
+ void AddEvent(std::unique_ptr<media::MediaLogEvent> event) override;
+ std::string GetLastErrorMessage() override;
// Will reset |last_ipc_send_time_| with the value of NowTicks().
- void SetTickClockForTesting(scoped_ptr<base::TickClock> tick_clock);
+ void SetTickClockForTesting(std::unique_ptr<base::TickClock> tick_clock);
void SetTaskRunnerForTesting(
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner);
private:
~RenderMediaLog() override;
- // Add event on the |task_runner_|.
- void AddEventInternal(scoped_ptr<media::MediaLogEvent> event);
-
- // Posted as a delayed task to throttle ipc message frequency.
+ // Posted as a delayed task on |task_runner_| to throttle ipc message
+ // frequency.
void SendQueuedMediaEvents();
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- scoped_ptr<base::TickClock> tick_clock_;
+
+ // |lock_| protects access to all of the following member variables. It
+ // allows any render process thread to AddEvent(), while preserving their
+ // sequence for throttled send on |task_runner_| and coherent retrieval by
+ // GetLastErrorMessage().
+ mutable base::Lock lock_;
+ std::unique_ptr<base::TickClock> tick_clock_;
base::TimeTicks last_ipc_send_time_;
std::vector<media::MediaLogEvent> queued_media_events_;
+ // For enforcing max 1 pending send.
+ bool ipc_send_pending_;
+
// Limits the number buffered extents changed events we send over IPC to one.
- scoped_ptr<media::MediaLogEvent> last_buffered_extents_changed_event_;
+ std::unique_ptr<media::MediaLogEvent> last_buffered_extents_changed_event_;
+
+ // Holds a copy of the most recent MEDIA_ERROR_LOG_ENTRY, if any.
+ std::unique_ptr<media::MediaLogEvent> last_media_error_log_entry_;
+
+ // Holds a copy of the most recent PIPELINE_ERROR, if any.
+ std::unique_ptr<media::MediaLogEvent> last_pipeline_error_;
DISALLOW_COPY_AND_ASSIGN(RenderMediaLog);
};
diff --git a/chromium/content/renderer/media/render_media_log_unittest.cc b/chromium/content/renderer/media/render_media_log_unittest.cc
index a6a58a4c84c..131da078c19 100644
--- a/chromium/content/renderer/media/render_media_log_unittest.cc
+++ b/chromium/content/renderer/media/render_media_log_unittest.cc
@@ -18,7 +18,7 @@ class RenderMediaLogTest : public testing::Test {
: log_(new RenderMediaLog()),
tick_clock_(new base::SimpleTestTickClock()),
task_runner_(new base::TestMockTimeTaskRunner()) {
- log_->SetTickClockForTesting(scoped_ptr<base::TickClock>(tick_clock_));
+ log_->SetTickClockForTesting(std::unique_ptr<base::TickClock>(tick_clock_));
log_->SetTaskRunnerForTesting(task_runner_);
}
diff --git a/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.cc b/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.cc
index 940636a0119..ee7911bd680 100644
--- a/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.cc
+++ b/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.cc
@@ -8,45 +8,66 @@
#include <GLES2/gl2ext.h>
#include "base/bind.h"
+#include "base/memory/ptr_util.h"
+#include "base/metrics/histogram_macros.h"
#include "cc/output/context_provider.h"
#include "content/child/child_gpu_memory_buffer_manager.h"
#include "content/child/child_thread_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"
-#include "content/common/gpu/media/gpu_video_accelerator_util.h"
#include "content/renderer/render_thread_impl.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/client/gpu_memory_buffer_manager.h"
+#include "gpu/ipc/client/gpu_channel_host.h"
+#include "media/gpu/ipc/client/gpu_video_decode_accelerator_host.h"
+#include "media/gpu/ipc/client/gpu_video_encode_accelerator_host.h"
+#include "media/gpu/ipc/common/gpu_video_accelerator_util.h"
#include "media/video/video_decode_accelerator.h"
#include "media/video/video_encode_accelerator.h"
namespace content {
+namespace {
+
+// This enum values match ContextProviderPhase in histograms.xml
+enum ContextProviderPhase {
+ CONTEXT_PROVIDER_ACQUIRED = 0,
+ CONTEXT_PROVIDER_RELEASED = 1,
+ CONTEXT_PROVIDER_RELEASED_MAX_VALUE = CONTEXT_PROVIDER_RELEASED,
+};
+
+void RecordContextProviderPhaseUmaEnum(const ContextProviderPhase phase) {
+ UMA_HISTOGRAM_ENUMERATION("Media.GPU.HasEverLostContext", phase,
+ CONTEXT_PROVIDER_RELEASED_MAX_VALUE + 1);
+}
+
+} // namespace
+
// static
-scoped_ptr<RendererGpuVideoAcceleratorFactories>
+std::unique_ptr<RendererGpuVideoAcceleratorFactories>
RendererGpuVideoAcceleratorFactories::Create(
- GpuChannelHost* gpu_channel_host,
+ gpu::GpuChannelHost* gpu_channel_host,
const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
bool enable_gpu_memory_buffer_video_frames,
- unsigned image_texture_target,
+ std::vector<unsigned> image_texture_targets,
bool enable_video_accelerator) {
- return make_scoped_ptr(new RendererGpuVideoAcceleratorFactories(
+ RecordContextProviderPhaseUmaEnum(
+ ContextProviderPhase::CONTEXT_PROVIDER_ACQUIRED);
+ return base::WrapUnique(new RendererGpuVideoAcceleratorFactories(
gpu_channel_host, main_thread_task_runner, task_runner, context_provider,
- enable_gpu_memory_buffer_video_frames, image_texture_target,
+ enable_gpu_memory_buffer_video_frames, image_texture_targets,
enable_video_accelerator));
}
RendererGpuVideoAcceleratorFactories::RendererGpuVideoAcceleratorFactories(
- GpuChannelHost* gpu_channel_host,
+ gpu::GpuChannelHost* gpu_channel_host,
const scoped_refptr<base::SingleThreadTaskRunner>& main_thread_task_runner,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
bool enable_gpu_memory_buffer_video_frames,
- unsigned image_texture_target,
+ std::vector<unsigned> image_texture_targets,
bool enable_video_accelerator)
: main_thread_task_runner_(main_thread_task_runner),
task_runner_(task_runner),
@@ -55,10 +76,10 @@ RendererGpuVideoAcceleratorFactories::RendererGpuVideoAcceleratorFactories(
context_provider_(context_provider.get()),
enable_gpu_memory_buffer_video_frames_(
enable_gpu_memory_buffer_video_frames),
- image_texture_target_(image_texture_target),
+ image_texture_targets_(image_texture_targets),
video_accelerator_enabled_(enable_video_accelerator),
- gpu_memory_buffer_manager_(ChildThreadImpl::current()
- ->gpu_memory_buffer_manager()),
+ gpu_memory_buffer_manager_(
+ ChildThreadImpl::current()->gpu_memory_buffer_manager()),
thread_safe_sender_(ChildThreadImpl::current()->thread_safe_sender()) {
DCHECK(main_thread_task_runner_);
DCHECK(gpu_channel_host_);
@@ -87,22 +108,36 @@ bool RendererGpuVideoAcceleratorFactories::IsGpuVideoAcceleratorEnabled() {
return video_accelerator_enabled_;
}
-scoped_ptr<media::VideoDecodeAccelerator>
+std::unique_ptr<media::VideoDecodeAccelerator>
RendererGpuVideoAcceleratorFactories::CreateVideoDecodeAccelerator() {
DCHECK(video_accelerator_enabled_);
DCHECK(task_runner_->BelongsToCurrentThread());
if (CheckContextLost())
return nullptr;
- return context_provider_->GetCommandBufferProxy()->CreateVideoDecoder();
+
+ gpu::GpuChannelHost* channel =
+ context_provider_->GetCommandBufferProxy()->channel();
+ DCHECK(channel);
+
+ return std::unique_ptr<media::VideoDecodeAccelerator>(
+ new media::GpuVideoDecodeAcceleratorHost(
+ channel, context_provider_->GetCommandBufferProxy()));
}
-scoped_ptr<media::VideoEncodeAccelerator>
+std::unique_ptr<media::VideoEncodeAccelerator>
RendererGpuVideoAcceleratorFactories::CreateVideoEncodeAccelerator() {
DCHECK(video_accelerator_enabled_);
DCHECK(task_runner_->BelongsToCurrentThread());
if (CheckContextLost())
return nullptr;
- return context_provider_->GetCommandBufferProxy()->CreateVideoEncoder();
+
+ gpu::GpuChannelHost* channel =
+ context_provider_->GetCommandBufferProxy()->channel();
+ DCHECK(channel);
+
+ return std::unique_ptr<media::VideoEncodeAccelerator>(
+ new media::GpuVideoEncodeAcceleratorHost(
+ channel, context_provider_->GetCommandBufferProxy()));
}
bool RendererGpuVideoAcceleratorFactories::CreateTextures(
@@ -180,13 +215,14 @@ void RendererGpuVideoAcceleratorFactories::WaitSyncToken(
gles2->ShallowFlushCHROMIUM();
}
-scoped_ptr<gfx::GpuMemoryBuffer>
+std::unique_ptr<gfx::GpuMemoryBuffer>
RendererGpuVideoAcceleratorFactories::AllocateGpuMemoryBuffer(
const gfx::Size& size,
gfx::BufferFormat format,
gfx::BufferUsage usage) {
- scoped_ptr<gfx::GpuMemoryBuffer> buffer =
- gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer(size, format, usage);
+ std::unique_ptr<gfx::GpuMemoryBuffer> buffer =
+ gpu_memory_buffer_manager_->AllocateGpuMemoryBuffer(size, format, usage,
+ 0 /* surface_id */);
return buffer;
}
bool RendererGpuVideoAcceleratorFactories::
@@ -194,8 +230,9 @@ bool RendererGpuVideoAcceleratorFactories::
return enable_gpu_memory_buffer_video_frames_;
}
-unsigned RendererGpuVideoAcceleratorFactories::ImageTextureTarget() {
- return image_texture_target_;
+unsigned RendererGpuVideoAcceleratorFactories::ImageTextureTarget(
+ gfx::BufferFormat format) {
+ return image_texture_targets_[static_cast<int>(format)];
}
media::VideoPixelFormat
@@ -205,6 +242,8 @@ RendererGpuVideoAcceleratorFactories::VideoFrameOutputFormat() {
return media::PIXEL_FORMAT_UNKNOWN;
cc::ContextProvider::ScopedContextLock lock(context_provider_);
auto capabilities = context_provider_->ContextCapabilities();
+ if (capabilities.gpu.image_ycbcr_420v)
+ return media::PIXEL_FORMAT_NV12;
if (capabilities.gpu.image_ycbcr_422)
return media::PIXEL_FORMAT_UYVY;
if (capabilities.gpu.texture_rg)
@@ -225,16 +264,16 @@ class ScopedGLContextLockImpl
};
} // namespace
-scoped_ptr<media::GpuVideoAcceleratorFactories::ScopedGLContextLock>
+std::unique_ptr<media::GpuVideoAcceleratorFactories::ScopedGLContextLock>
RendererGpuVideoAcceleratorFactories::GetGLContextLock() {
if (CheckContextLost())
return nullptr;
- return make_scoped_ptr(new ScopedGLContextLockImpl(context_provider_));
+ return base::WrapUnique(new ScopedGLContextLockImpl(context_provider_));
}
-scoped_ptr<base::SharedMemory>
+std::unique_ptr<base::SharedMemory>
RendererGpuVideoAcceleratorFactories::CreateSharedMemory(size_t size) {
- scoped_ptr<base::SharedMemory> mem(
+ std::unique_ptr<base::SharedMemory> mem(
ChildThreadImpl::AllocateSharedMemory(size, thread_safe_sender_.get()));
if (mem && !mem->Map(size))
return nullptr;
@@ -248,20 +287,22 @@ RendererGpuVideoAcceleratorFactories::GetTaskRunner() {
media::VideoDecodeAccelerator::Capabilities
RendererGpuVideoAcceleratorFactories::GetVideoDecodeAcceleratorCapabilities() {
- return GpuVideoAcceleratorUtil::ConvertGpuToMediaDecodeCapabilities(
+ return media::GpuVideoAcceleratorUtil::ConvertGpuToMediaDecodeCapabilities(
gpu_channel_host_->gpu_info().video_decode_accelerator_capabilities);
}
media::VideoEncodeAccelerator::SupportedProfiles
RendererGpuVideoAcceleratorFactories::
GetVideoEncodeAcceleratorSupportedProfiles() {
- return GpuVideoAcceleratorUtil::ConvertGpuToMediaEncodeProfiles(
+ return media::GpuVideoAcceleratorUtil::ConvertGpuToMediaEncodeProfiles(
gpu_channel_host_->gpu_info()
.video_encode_accelerator_supported_profiles);
}
void RendererGpuVideoAcceleratorFactories::ReleaseContextProvider() {
DCHECK(main_thread_task_runner_->BelongsToCurrentThread());
+ RecordContextProviderPhaseUmaEnum(
+ ContextProviderPhase::CONTEXT_PROVIDER_RELEASED);
context_provider_refptr_ = nullptr;
}
diff --git a/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.h b/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.h
index 05dcd6d6daf..a1f1e392354 100644
--- a/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.h
+++ b/chromium/content/renderer/media/renderer_gpu_video_accelerator_factories.h
@@ -24,12 +24,12 @@ class WaitableEvent;
}
namespace gpu {
+class GpuChannelHost;
class GpuMemoryBufferManager;
}
namespace content {
class ContextProviderCommandBuffer;
-class GpuChannelHost;
class WebGraphicsContext3DCommandBufferImpl;
// Glue code to expose functionality needed by media::GpuVideoAccelerator to
@@ -45,21 +45,21 @@ class CONTENT_EXPORT RendererGpuVideoAcceleratorFactories
public:
// Takes a ref on |gpu_channel_host| and tests |context| for loss before each
// use. Safe to call from any thread.
- static scoped_ptr<RendererGpuVideoAcceleratorFactories> Create(
- GpuChannelHost* gpu_channel_host,
+ static std::unique_ptr<RendererGpuVideoAcceleratorFactories> Create(
+ gpu::GpuChannelHost* gpu_channel_host,
const scoped_refptr<base::SingleThreadTaskRunner>&
main_thread_task_runner,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
bool enable_gpu_memory_buffer_video_frames,
- unsigned image_texture_target,
+ std::vector<unsigned> image_texture_targets,
bool enable_video_accelerator);
// media::GpuVideoAcceleratorFactories implementation.
bool IsGpuVideoAcceleratorEnabled() override;
- scoped_ptr<media::VideoDecodeAccelerator> CreateVideoDecodeAccelerator()
+ std::unique_ptr<media::VideoDecodeAccelerator> CreateVideoDecodeAccelerator()
override;
- scoped_ptr<media::VideoEncodeAccelerator> CreateVideoEncodeAccelerator()
+ std::unique_ptr<media::VideoEncodeAccelerator> CreateVideoEncodeAccelerator()
override;
// Creates textures and produces them into mailboxes. Returns true on success
// or false on failure.
@@ -71,18 +71,18 @@ class CONTENT_EXPORT RendererGpuVideoAcceleratorFactories
void DeleteTexture(uint32_t texture_id) override;
void WaitSyncToken(const gpu::SyncToken& sync_token) override;
- scoped_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer(
+ std::unique_ptr<gfx::GpuMemoryBuffer> AllocateGpuMemoryBuffer(
const gfx::Size& size,
gfx::BufferFormat format,
gfx::BufferUsage usage) override;
bool ShouldUseGpuMemoryBuffersForVideoFrames() const override;
- unsigned ImageTextureTarget() override;
+ unsigned ImageTextureTarget(gfx::BufferFormat format) override;
media::VideoPixelFormat VideoFrameOutputFormat() override;
- scoped_ptr<media::GpuVideoAcceleratorFactories::ScopedGLContextLock>
+ std::unique_ptr<media::GpuVideoAcceleratorFactories::ScopedGLContextLock>
GetGLContextLock() override;
bool CheckContextLost();
- scoped_ptr<base::SharedMemory> CreateSharedMemory(size_t size) override;
+ std::unique_ptr<base::SharedMemory> CreateSharedMemory(size_t size) override;
scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override;
media::VideoDecodeAccelerator::Capabilities
@@ -97,18 +97,18 @@ class CONTENT_EXPORT RendererGpuVideoAcceleratorFactories
private:
RendererGpuVideoAcceleratorFactories(
- GpuChannelHost* gpu_channel_host,
+ gpu::GpuChannelHost* gpu_channel_host,
const scoped_refptr<base::SingleThreadTaskRunner>&
main_thread_task_runner,
const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
const scoped_refptr<ContextProviderCommandBuffer>& context_provider,
bool enable_gpu_memory_buffer_video_frames,
- unsigned image_texture_target,
+ std::vector<unsigned> image_texture_targets,
bool enable_video_accelerator);
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- scoped_refptr<GpuChannelHost> gpu_channel_host_;
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel_host_;
// Shared pointer to a shared context provider that should be accessed
// and set only on the main thread.
@@ -119,7 +119,7 @@ class CONTENT_EXPORT RendererGpuVideoAcceleratorFactories
// Whether gpu memory buffers should be used to hold video frames data.
bool enable_gpu_memory_buffer_video_frames_;
- const unsigned image_texture_target_;
+ const std::vector<unsigned> image_texture_targets_;
// Whether video acceleration encoding/decoding should be enabled.
const bool video_accelerator_enabled_;
diff --git a/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc b/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc
index 221679b1cdf..10437b3b599 100644
--- a/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc
+++ b/chromium/content/renderer/media/renderer_webaudiodevice_impl.cc
@@ -16,7 +16,6 @@
#include "build/build_config.h"
#include "content/renderer/media/audio_device_factory.h"
#include "content/renderer/render_frame_impl.h"
-#include "media/audio/audio_output_device.h"
#include "media/audio/null_audio_sink.h"
#include "media/base/media_switches.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
@@ -36,7 +35,8 @@ static const int kSilenceInSecondsToEnterIdleMode = 30;
RendererWebAudioDeviceImpl::RendererWebAudioDeviceImpl(
const media::AudioParameters& params,
WebAudioDevice::RenderCallback* callback,
- int session_id)
+ int session_id,
+ const url::Origin& security_origin)
: params_(params),
client_callback_(callback),
session_id_(session_id),
@@ -44,20 +44,21 @@ RendererWebAudioDeviceImpl::RendererWebAudioDeviceImpl(
null_audio_sink_(new media::NullAudioSink(task_runner_)),
is_using_null_audio_sink_(false),
first_buffer_after_silence_(media::AudioBus::Create(params_)),
- is_first_buffer_after_silence_(false) {
+ is_first_buffer_after_silence_(false),
+ security_origin_(security_origin) {
DCHECK(client_callback_);
null_audio_sink_->Initialize(params_, this);
null_audio_sink_->Start();
}
RendererWebAudioDeviceImpl::~RendererWebAudioDeviceImpl() {
- DCHECK(!output_device_);
+ DCHECK(!sink_);
}
void RendererWebAudioDeviceImpl::start() {
DCHECK(thread_checker_.CalledOnValidThread());
- if (output_device_)
+ if (sink_)
return; // Already started.
// Assumption: This method is being invoked within a V8 call stack. CHECKs
@@ -70,11 +71,13 @@ void RendererWebAudioDeviceImpl::start() {
WebLocalFrame* const web_frame = WebLocalFrame::frameForCurrentContext();
RenderFrame* const render_frame =
web_frame ? RenderFrame::FromWebFrame(web_frame) : NULL;
- output_device_ = AudioDeviceFactory::NewOutputDevice(
+ sink_ = AudioDeviceFactory::NewAudioRendererSink(
+ AudioDeviceFactory::kSourceWebAudio,
render_frame ? render_frame->GetRoutingID() : MSG_ROUTING_NONE,
- session_id_, std::string(), url::Origin());
- output_device_->Initialize(params_, this);
- output_device_->Start();
+ session_id_, std::string(), security_origin_);
+ sink_->Initialize(params_, this);
+ sink_->Start();
+ sink_->Play();
start_null_audio_sink_callback_.Reset(
base::Bind(&media::NullAudioSink::Play, null_audio_sink_));
// Note: Default behavior is to auto-play on start.
@@ -83,9 +86,9 @@ void RendererWebAudioDeviceImpl::start() {
void RendererWebAudioDeviceImpl::stop() {
DCHECK(thread_checker_.CalledOnValidThread());
- if (output_device_) {
- output_device_->Stop();
- output_device_ = NULL;
+ if (sink_) {
+ sink_->Stop();
+ sink_ = NULL;
}
null_audio_sink_->Stop();
is_using_null_audio_sink_ = false;
@@ -98,7 +101,7 @@ double RendererWebAudioDeviceImpl::sampleRate() {
}
int RendererWebAudioDeviceImpl::Render(media::AudioBus* dest,
- uint32_t audio_delay_milliseconds,
+ uint32_t frames_delayed,
uint32_t frames_skipped) {
#if defined(OS_ANDROID)
if (is_first_buffer_after_silence_) {
@@ -134,9 +137,9 @@ int RendererWebAudioDeviceImpl::Render(media::AudioBus* dest,
task_runner_->PostTask(
FROM_HERE,
base::Bind(&media::NullAudioSink::Pause, null_audio_sink_));
- // Calling output_device_->Play() may trigger reentrancy into this
+ // Calling sink_->Play() may trigger reentrancy into this
// function, so this should be called at the end.
- output_device_->Play();
+ sink_->Play();
return dest->frames();
}
} else if (!is_using_null_audio_sink_) {
@@ -146,7 +149,7 @@ int RendererWebAudioDeviceImpl::Render(media::AudioBus* dest,
first_silence_time_ = now;
if (now - first_silence_time_
> base::TimeDelta::FromSeconds(kSilenceInSecondsToEnterIdleMode)) {
- output_device_->Pause();
+ sink_->Pause();
is_using_null_audio_sink_ = true;
// If Stop() is called right after the task is posted, need to cancel
// this task.
diff --git a/chromium/content/renderer/media/renderer_webaudiodevice_impl.h b/chromium/content/renderer/media/renderer_webaudiodevice_impl.h
index e90c74bb742..3d97a9e7d86 100644
--- a/chromium/content/renderer/media/renderer_webaudiodevice_impl.h
+++ b/chromium/content/renderer/media/renderer_webaudiodevice_impl.h
@@ -15,13 +15,13 @@
#include "media/base/audio_renderer_sink.h"
#include "third_party/WebKit/public/platform/WebAudioDevice.h"
#include "third_party/WebKit/public/platform/WebVector.h"
+#include "url/origin.h"
namespace base {
class SingleThreadTaskRunner;
}
namespace media {
-class AudioOutputDevice;
class NullAudioSink;
}
@@ -33,7 +33,8 @@ class RendererWebAudioDeviceImpl
public:
RendererWebAudioDeviceImpl(const media::AudioParameters& params,
blink::WebAudioDevice::RenderCallback* callback,
- int session_id);
+ int session_id,
+ const url::Origin& security_origin);
~RendererWebAudioDeviceImpl() override;
// blink::WebAudioDevice implementation.
@@ -43,7 +44,7 @@ class RendererWebAudioDeviceImpl
// AudioRendererSink::RenderCallback implementation.
int Render(media::AudioBus* dest,
- uint32_t audio_delay_milliseconds,
+ uint32_t frames_delayed,
uint32_t frames_skipped) override;
void OnRenderError() override;
@@ -59,7 +60,7 @@ class RendererWebAudioDeviceImpl
base::ThreadChecker thread_checker_;
// When non-NULL, we are started. When NULL, we are stopped.
- scoped_refptr<media::AudioOutputDevice> output_device_;
+ scoped_refptr<media::AudioRendererSink> sink_;
// ID to allow browser to select the correct input device for unified IO.
int session_id_;
@@ -80,7 +81,7 @@ class RendererWebAudioDeviceImpl
// First audio buffer after silence finishes. We store this buffer so that
// it can be sent to the |output_device_| later after switching from
// |null_audio_sink_|.
- scoped_ptr<media::AudioBus> first_buffer_after_silence_;
+ std::unique_ptr<media::AudioBus> first_buffer_after_silence_;
bool is_first_buffer_after_silence_;
@@ -88,6 +89,9 @@ class RendererWebAudioDeviceImpl
// period of silence. We do this on android to save battery consumption.
base::CancelableClosure start_null_audio_sink_callback_;
+ // Security origin, used to check permissions for |output_device_|.
+ url::Origin security_origin_;
+
DISALLOW_COPY_AND_ASSIGN(RendererWebAudioDeviceImpl);
};
diff --git a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc
index 722b13d5440..57a25e69958 100644
--- a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc
+++ b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.cc
@@ -6,7 +6,8 @@
#include <stdint.h>
-#include "content/common/frame_messages.h"
+#include "base/auto_reset.h"
+#include "content/common/media/media_player_delegate_messages.h"
#include "content/public/renderer/render_frame.h"
#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
@@ -14,44 +15,163 @@ namespace media {
RendererWebMediaPlayerDelegate::RendererWebMediaPlayerDelegate(
content::RenderFrame* render_frame)
- : RenderFrameObserver(render_frame) {}
+ : RenderFrameObserver(render_frame),
+ default_tick_clock_(new base::DefaultTickClock()),
+ tick_clock_(default_tick_clock_.get()) {
+ idle_cleanup_interval_ = base::TimeDelta::FromSeconds(5);
+ idle_timeout_ = base::TimeDelta::FromSeconds(15);
+}
RendererWebMediaPlayerDelegate::~RendererWebMediaPlayerDelegate() {}
-void RendererWebMediaPlayerDelegate::DidPlay(blink::WebMediaPlayer* player) {
- has_played_media_ = true;
- Send(new FrameHostMsg_MediaPlayingNotification(
- routing_id(), reinterpret_cast<int64_t>(player), player->hasVideo(),
- player->hasAudio(), player->isRemote()));
+int RendererWebMediaPlayerDelegate::AddObserver(Observer* observer) {
+ return id_map_.Add(observer);
+}
+
+void RendererWebMediaPlayerDelegate::RemoveObserver(int delegate_id) {
+ DCHECK(id_map_.Lookup(delegate_id));
+ id_map_.Remove(delegate_id);
+ RemoveIdleDelegate(delegate_id);
}
-void RendererWebMediaPlayerDelegate::DidPause(blink::WebMediaPlayer* player) {
- Send(new FrameHostMsg_MediaPausedNotification(
- routing_id(), reinterpret_cast<int64_t>(player)));
+void RendererWebMediaPlayerDelegate::DidPlay(int delegate_id,
+ bool has_video,
+ bool has_audio,
+ bool is_remote,
+ base::TimeDelta duration) {
+ DCHECK(id_map_.Lookup(delegate_id));
+ has_played_media_ = true;
+ RemoveIdleDelegate(delegate_id);
+ Send(new MediaPlayerDelegateHostMsg_OnMediaPlaying(
+ routing_id(), delegate_id, has_video, has_audio, is_remote, duration));
}
-void RendererWebMediaPlayerDelegate::PlayerGone(blink::WebMediaPlayer* player) {
- DidPause(player);
+void RendererWebMediaPlayerDelegate::DidPause(int delegate_id,
+ bool reached_end_of_stream) {
+ DCHECK(id_map_.Lookup(delegate_id));
+ AddIdleDelegate(delegate_id);
+ Send(new MediaPlayerDelegateHostMsg_OnMediaPaused(routing_id(), delegate_id,
+ reached_end_of_stream));
}
-void RendererWebMediaPlayerDelegate::AddObserver(Observer* observer) {
- observer_list_.AddObserver(observer);
+void RendererWebMediaPlayerDelegate::PlayerGone(int delegate_id) {
+ DCHECK(id_map_.Lookup(delegate_id));
+ RemoveIdleDelegate(delegate_id);
+ Send(new MediaPlayerDelegateHostMsg_OnMediaDestroyed(routing_id(),
+ delegate_id));
}
-void RendererWebMediaPlayerDelegate::RemoveObserver(Observer* observer) {
- observer_list_.RemoveObserver(observer);
+bool RendererWebMediaPlayerDelegate::IsHidden() {
+ return render_frame()->IsHidden();
}
void RendererWebMediaPlayerDelegate::WasHidden() {
- FOR_EACH_OBSERVER(Observer, observer_list_, OnHidden());
+ for (IDMap<Observer>::iterator it(&id_map_); !it.IsAtEnd(); it.Advance())
+ it.GetCurrentValue()->OnHidden();
}
void RendererWebMediaPlayerDelegate::WasShown() {
- FOR_EACH_OBSERVER(Observer, observer_list_, OnShown());
+ for (IDMap<Observer>::iterator it(&id_map_); !it.IsAtEnd(); it.Advance())
+ it.GetCurrentValue()->OnShown();
}
-bool RendererWebMediaPlayerDelegate::IsHidden() {
- return render_frame()->IsHidden();
+bool RendererWebMediaPlayerDelegate::OnMessageReceived(
+ const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(RendererWebMediaPlayerDelegate, msg)
+ IPC_MESSAGE_HANDLER(MediaPlayerDelegateMsg_Pause, OnMediaDelegatePause)
+ IPC_MESSAGE_HANDLER(MediaPlayerDelegateMsg_Play, OnMediaDelegatePlay)
+ IPC_MESSAGE_HANDLER(MediaPlayerDelegateMsg_SuspendAllMediaPlayers,
+ OnMediaDelegateSuspendAllMediaPlayers)
+ IPC_MESSAGE_HANDLER(MediaPlayerDelegateMsg_UpdateVolumeMultiplier,
+ OnMediaDelegateVolumeMultiplierUpdate)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void RendererWebMediaPlayerDelegate::SetIdleCleanupParamsForTesting(
+ base::TimeDelta idle_timeout,
+ base::TickClock* tick_clock) {
+ idle_cleanup_interval_ = base::TimeDelta();
+ idle_timeout_ = idle_timeout;
+ tick_clock_ = tick_clock;
+}
+
+void RendererWebMediaPlayerDelegate::OnMediaDelegatePause(int delegate_id) {
+ Observer* observer = id_map_.Lookup(delegate_id);
+ if (observer)
+ observer->OnPause();
+}
+
+void RendererWebMediaPlayerDelegate::OnMediaDelegatePlay(int delegate_id) {
+ Observer* observer = id_map_.Lookup(delegate_id);
+ if (observer)
+ observer->OnPlay();
+}
+
+void RendererWebMediaPlayerDelegate::OnMediaDelegateSuspendAllMediaPlayers() {
+ for (IDMap<Observer>::iterator it(&id_map_); !it.IsAtEnd(); it.Advance())
+ it.GetCurrentValue()->OnSuspendRequested(true);
+}
+
+void RendererWebMediaPlayerDelegate::OnMediaDelegateVolumeMultiplierUpdate(
+ int delegate_id,
+ double multiplier) {
+ Observer* observer = id_map_.Lookup(delegate_id);
+ if (observer)
+ observer->OnVolumeMultiplierUpdate(multiplier);
+}
+
+void RendererWebMediaPlayerDelegate::AddIdleDelegate(int delegate_id) {
+ idle_delegate_map_[delegate_id] = tick_clock_->NowTicks();
+ if (!idle_cleanup_timer_.IsRunning()) {
+ idle_cleanup_timer_.Start(
+ FROM_HERE, idle_cleanup_interval_, this,
+ &RendererWebMediaPlayerDelegate::CleanupIdleDelegates);
+ }
+}
+
+void RendererWebMediaPlayerDelegate::RemoveIdleDelegate(int delegate_id) {
+ // To avoid invalidating the iterator, just mark the delegate for deletion
+ // using a sentinel value of an empty TimeTicks.
+ if (idle_cleanup_running_) {
+ idle_delegate_map_[delegate_id] = base::TimeTicks();
+ return;
+ }
+
+ idle_delegate_map_.erase(delegate_id);
+ if (idle_delegate_map_.empty())
+ idle_cleanup_timer_.Stop();
+}
+
+void RendererWebMediaPlayerDelegate::CleanupIdleDelegates() {
+ // Iterate over the delegates and suspend the idle ones. Note: The call to
+ // OnHidden() can trigger calls into RemoveIdleDelegate(), so for iterator
+ // validity we set |idle_cleanup_running_| to true and defer deletions.
+ base::AutoReset<bool> scoper(&idle_cleanup_running_, true);
+ const base::TimeTicks now = tick_clock_->NowTicks();
+ for (auto& idle_delegate_entry : idle_delegate_map_) {
+ if (now - idle_delegate_entry.second > idle_timeout_) {
+ id_map_.Lookup(idle_delegate_entry.first)->OnSuspendRequested(false);
+
+ // Whether or not the player accepted the suspension, mark it for removal
+ // from future polls to avoid running the timer forever.
+ idle_delegate_entry.second = base::TimeTicks();
+ }
+ }
+
+ // Take care of any removals that happened during the above iteration.
+ for (auto it = idle_delegate_map_.begin(); it != idle_delegate_map_.end();) {
+ if (it->second.is_null())
+ it = idle_delegate_map_.erase(it);
+ else
+ ++it;
+ }
+
+ // Shutdown the timer if no delegates are left.
+ if (idle_delegate_map_.empty())
+ idle_cleanup_timer_.Stop();
}
} // namespace media
diff --git a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h
index 3b1e3560e5d..b12a58f971d 100644
--- a/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h
+++ b/chromium/content/renderer/media/renderer_webmediaplayer_delegate.h
@@ -5,9 +5,15 @@
#ifndef CONTENT_RENDERER_MEDIA_RENDERER_WEBMEDIAPLAYER_DELEGATE_H_
#define CONTENT_RENDERER_MEDIA_RENDERER_WEBMEDIAPLAYER_DELEGATE_H_
+#include <map>
+#include <memory>
+
+#include "base/id_map.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
-#include "base/observer_list.h"
+#include "base/time/default_tick_clock.h"
+#include "base/timer/timer.h"
+#include "content/common/content_export.h"
#include "content/public/renderer/render_frame_observer.h"
#include "media/blink/webmediaplayer_delegate.h"
@@ -19,10 +25,11 @@ namespace media {
// An interface to allow a WebMediaPlayerImpl to communicate changes of state
// to objects that need to know.
-class RendererWebMediaPlayerDelegate
+class CONTENT_EXPORT RendererWebMediaPlayerDelegate
: public content::RenderFrameObserver,
- public WebMediaPlayerDelegate,
- public base::SupportsWeakPtr<RendererWebMediaPlayerDelegate> {
+ public NON_EXPORTED_BASE(WebMediaPlayerDelegate),
+ public NON_EXPORTED_BASE(
+ base::SupportsWeakPtr<RendererWebMediaPlayerDelegate>) {
public:
explicit RendererWebMediaPlayerDelegate(content::RenderFrame* render_frame);
~RendererWebMediaPlayerDelegate() override;
@@ -31,20 +38,67 @@ class RendererWebMediaPlayerDelegate
bool has_played_media() const { return has_played_media_; }
// WebMediaPlayerDelegate implementation.
- void DidPlay(blink::WebMediaPlayer* player) override;
- void DidPause(blink::WebMediaPlayer* player) override;
- void PlayerGone(blink::WebMediaPlayer* player) override;
- void AddObserver(Observer* observer) override;
- void RemoveObserver(Observer* observer) override;
+ int AddObserver(Observer* observer) override;
+ void RemoveObserver(int delegate_id) override;
+ void DidPlay(int delegate_id,
+ bool has_video,
+ bool has_audio,
+ bool is_remote,
+ base::TimeDelta duration) override;
+ void DidPause(int delegate_id, bool reached_end_of_stream) override;
+ void PlayerGone(int delegate_id) override;
bool IsHidden() override;
// content::RenderFrameObserver overrides.
void WasHidden() override;
void WasShown() override;
+ bool OnMessageReceived(const IPC::Message& msg) override;
+
+ // Zeros out |idle_cleanup_interval_|, and sets |idle_timeout_| to
+ // |idle_timeout|. A zero cleanup interval will cause the idle timer to run
+ // with each run of the message loop.
+ void SetIdleCleanupParamsForTesting(base::TimeDelta idle_timeout,
+ base::TickClock* tick_clock);
+ bool IsIdleCleanupTimerRunningForTesting() const {
+ return idle_cleanup_timer_.IsRunning();
+ }
private:
+ void OnMediaDelegatePause(int delegate_id);
+ void OnMediaDelegatePlay(int delegate_id);
+ void OnMediaDelegateSuspendAllMediaPlayers();
+ void OnMediaDelegateVolumeMultiplierUpdate(int delegate_id,
+ double multiplier);
+
+ // Adds or removes a delegate from |idle_delegate_map_|. The first insertion
+ // or last removal will start or stop |idle_cleanup_timer_| respectively.
+ void AddIdleDelegate(int delegate_id);
+ void RemoveIdleDelegate(int delegate_id);
+
+ // Runs periodically to suspend idle delegates in |idle_delegate_map_|.
+ void CleanupIdleDelegates();
+
bool has_played_media_ = false;
- base::ObserverList<Observer> observer_list_;
+ IDMap<Observer> id_map_;
+
+ // Tracks which delegates have entered an idle state. After some period of
+ // inactivity these players will be suspended to release unused resources.
+ bool idle_cleanup_running_ = false;
+ std::map<int, base::TimeTicks> idle_delegate_map_;
+ base::RepeatingTimer idle_cleanup_timer_;
+
+ // Amount of time allowed to elapse after a delegate enters the paused before
+ // the delegate is suspended.
+ base::TimeDelta idle_timeout_;
+
+ // The polling interval used for checking the delegates to see if any have
+ // exceeded |idle_timeout_| since their last pause state.
+ base::TimeDelta idle_cleanup_interval_;
+
+ // Clock used for calculating when delegates have expired. May be overridden
+ // for testing.
+ std::unique_ptr<base::DefaultTickClock> default_tick_clock_;
+ base::TickClock* tick_clock_;
DISALLOW_COPY_AND_ASSIGN(RendererWebMediaPlayerDelegate);
};
diff --git a/chromium/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc b/chromium/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc
new file mode 100644
index 00000000000..4872ec891cd
--- /dev/null
+++ b/chromium/content/renderer/media/renderer_webmediaplayer_delegate_browsertest.cc
@@ -0,0 +1,266 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/bind.h"
+#include "base/bind_helpers.h"
+#include "base/run_loop.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "base/tuple.h"
+#include "content/common/media/media_player_delegate_messages.h"
+#include "content/public/renderer/render_view.h"
+#include "content/public/test/render_view_test.h"
+#include "content/renderer/media/renderer_webmediaplayer_delegate.h"
+#include "content/renderer/render_process.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace media {
+
+ACTION_P(RunClosure, closure) {
+ closure.Run();
+}
+
+class MockWebMediaPlayerDelegateObserver
+ : public WebMediaPlayerDelegate::Observer {
+ public:
+ MockWebMediaPlayerDelegateObserver() {}
+ ~MockWebMediaPlayerDelegateObserver() {}
+
+ // WebMediaPlayerDelegate::Observer implementation.
+ MOCK_METHOD0(OnHidden, void());
+ MOCK_METHOD0(OnShown, void());
+ MOCK_METHOD1(OnSuspendRequested, void(bool));
+ MOCK_METHOD0(OnPlay, void());
+ MOCK_METHOD0(OnPause, void());
+ MOCK_METHOD1(OnVolumeMultiplierUpdate, void(double));
+};
+
+class RendererWebMediaPlayerDelegateTest : public content::RenderViewTest {
+ public:
+ RendererWebMediaPlayerDelegateTest() {}
+ ~RendererWebMediaPlayerDelegateTest() override {}
+
+ void SetUp() override {
+ RenderViewTest::SetUp();
+ delegate_manager_.reset(
+ new RendererWebMediaPlayerDelegate(view_->GetMainRenderFrame()));
+ }
+
+ void TearDown() override {
+ // Destruct the controller prior to any other tear down to avoid out of
+ // order destruction relative to the test render frame.
+ delegate_manager_.reset();
+ RenderViewTest::TearDown();
+ }
+
+ protected:
+ IPC::TestSink& test_sink() { return render_thread_->sink(); }
+
+ std::unique_ptr<RendererWebMediaPlayerDelegate> delegate_manager_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(RendererWebMediaPlayerDelegateTest);
+};
+
+TEST_F(RendererWebMediaPlayerDelegateTest, SendsMessagesCorrectly) {
+ testing::StrictMock<MockWebMediaPlayerDelegateObserver> observer;
+ const int delegate_id = delegate_manager_->AddObserver(&observer);
+
+ // Verify the playing message.
+ {
+ const bool kHasVideo = true, kHasAudio = false, kIsRemote = false;
+ const base::TimeDelta kDuration = base::TimeDelta::FromSeconds(5);
+ delegate_manager_->DidPlay(delegate_id, kHasVideo, kHasAudio, kIsRemote,
+ kDuration);
+
+ const IPC::Message* msg = test_sink().GetUniqueMessageMatching(
+ MediaPlayerDelegateHostMsg_OnMediaPlaying::ID);
+ ASSERT_TRUE(msg);
+
+ base::Tuple<int, bool, bool, bool, base::TimeDelta> result;
+ ASSERT_TRUE(MediaPlayerDelegateHostMsg_OnMediaPlaying::Read(msg, &result));
+ EXPECT_EQ(delegate_id, base::get<0>(result));
+ EXPECT_EQ(kHasVideo, base::get<1>(result));
+ EXPECT_EQ(kHasAudio, base::get<2>(result));
+ EXPECT_EQ(kIsRemote, base::get<3>(result));
+ EXPECT_EQ(kDuration, base::get<4>(result));
+ }
+
+ // Verify the paused message.
+ {
+ test_sink().ClearMessages();
+ const bool kReachedEndOfStream = true;
+ delegate_manager_->DidPause(delegate_id, kReachedEndOfStream);
+
+ const IPC::Message* msg = test_sink().GetUniqueMessageMatching(
+ MediaPlayerDelegateHostMsg_OnMediaPaused::ID);
+ ASSERT_TRUE(msg);
+
+ base::Tuple<int, bool> result;
+ ASSERT_TRUE(MediaPlayerDelegateHostMsg_OnMediaPaused::Read(msg, &result));
+ EXPECT_EQ(delegate_id, base::get<0>(result));
+ EXPECT_EQ(kReachedEndOfStream, base::get<1>(result));
+ }
+
+ // Verify the destruction message.
+ {
+ test_sink().ClearMessages();
+ delegate_manager_->PlayerGone(delegate_id);
+ const IPC::Message* msg = test_sink().GetUniqueMessageMatching(
+ MediaPlayerDelegateHostMsg_OnMediaDestroyed::ID);
+ ASSERT_TRUE(msg);
+
+ base::Tuple<int> result;
+ ASSERT_TRUE(
+ MediaPlayerDelegateHostMsg_OnMediaDestroyed::Read(msg, &result));
+ EXPECT_EQ(delegate_id, base::get<0>(result));
+ }
+
+ delegate_manager_->RemoveObserver(delegate_id);
+}
+
+TEST_F(RendererWebMediaPlayerDelegateTest, DeliversObserverNotifications) {
+ testing::StrictMock<MockWebMediaPlayerDelegateObserver> observer;
+ const int delegate_id = delegate_manager_->AddObserver(&observer);
+
+ EXPECT_CALL(observer, OnHidden());
+ delegate_manager_->WasHidden();
+
+ EXPECT_CALL(observer, OnShown());
+ delegate_manager_->WasShown();
+
+ EXPECT_CALL(observer, OnPause());
+ MediaPlayerDelegateMsg_Pause pause_msg(0, delegate_id);
+ delegate_manager_->OnMessageReceived(pause_msg);
+
+ EXPECT_CALL(observer, OnPlay());
+ MediaPlayerDelegateMsg_Play play_msg(0, delegate_id);
+ delegate_manager_->OnMessageReceived(play_msg);
+
+ const double kTestMultiplier = 0.5;
+ EXPECT_CALL(observer, OnVolumeMultiplierUpdate(kTestMultiplier));
+ MediaPlayerDelegateMsg_UpdateVolumeMultiplier volume_msg(0, delegate_id,
+ kTestMultiplier);
+ delegate_manager_->OnMessageReceived(volume_msg);
+
+ EXPECT_CALL(observer, OnSuspendRequested(true));
+ MediaPlayerDelegateMsg_SuspendAllMediaPlayers suspend_msg(0);
+ delegate_manager_->OnMessageReceived(suspend_msg);
+
+ delegate_manager_->RemoveObserver(delegate_id);
+}
+
+TEST_F(RendererWebMediaPlayerDelegateTest, IdleDelegatesAreSuspended) {
+ // Start the tick clock off at a non-null value.
+ base::SimpleTestTickClock tick_clock;
+ tick_clock.Advance(base::TimeDelta::FromSeconds(1234));
+
+ const base::TimeDelta kIdleTimeout = base::TimeDelta::FromSeconds(2);
+ delegate_manager_->SetIdleCleanupParamsForTesting(kIdleTimeout, &tick_clock);
+ EXPECT_FALSE(delegate_manager_->IsIdleCleanupTimerRunningForTesting());
+
+ // Just adding an observer should not start the idle timer.
+ testing::StrictMock<MockWebMediaPlayerDelegateObserver> observer_1;
+ const int delegate_id_1 = delegate_manager_->AddObserver(&observer_1);
+ EXPECT_FALSE(delegate_manager_->IsIdleCleanupTimerRunningForTesting());
+
+ // Starting playback should not have an idle timer.
+ delegate_manager_->DidPlay(delegate_id_1, true, true, false,
+ base::TimeDelta());
+ EXPECT_FALSE(delegate_manager_->IsIdleCleanupTimerRunningForTesting());
+
+ // Never calling DidPlay() but calling DidPause() should count as idle.
+ testing::StrictMock<MockWebMediaPlayerDelegateObserver> observer_2;
+ const int delegate_id_2 = delegate_manager_->AddObserver(&observer_2);
+ delegate_manager_->DidPause(delegate_id_2, false);
+ EXPECT_TRUE(delegate_manager_->IsIdleCleanupTimerRunningForTesting());
+
+ // Adding the observer should instantly queue the timeout task, once run the
+ // second delegate should be expired while the first is kept alive.
+ {
+ EXPECT_CALL(observer_2, OnSuspendRequested(false))
+ .WillOnce(RunClosure(base::Bind(
+ &RendererWebMediaPlayerDelegate::PlayerGone,
+ base::Unretained(delegate_manager_.get()), delegate_id_2)));
+ base::RunLoop run_loop;
+ base::MessageLoop::current()->PostTask(FROM_HERE, run_loop.QuitClosure());
+ tick_clock.Advance(kIdleTimeout + base::TimeDelta::FromMicroseconds(1));
+ run_loop.Run();
+ }
+
+ // Pausing should count as idle if playback didn't reach end of stream, but
+ // in this case the player will not remove the MediaSession.
+ delegate_manager_->DidPause(delegate_id_1, false /* reached_end_of_stream */);
+ testing::StrictMock<MockWebMediaPlayerDelegateObserver> observer_3;
+ const int delegate_id_3 = delegate_manager_->AddObserver(&observer_3);
+ delegate_manager_->DidPlay(delegate_id_3, true, true, false,
+ base::TimeDelta());
+
+ // Adding the observer should instantly queue the timeout task, once run no
+ // delegates should have been expired.
+ {
+ EXPECT_CALL(observer_1, OnSuspendRequested(false))
+ .Times(testing::AtLeast(1));
+ base::RunLoop run_loop;
+ base::MessageLoop::current()->PostTask(FROM_HERE, run_loop.QuitClosure());
+ tick_clock.Advance(kIdleTimeout + base::TimeDelta::FromMicroseconds(1));
+ run_loop.Run();
+ }
+
+ delegate_manager_->DidPlay(delegate_id_1, true, true, false,
+ base::TimeDelta());
+
+ // Pausing after reaching end of stream should count as idle.
+ delegate_manager_->DidPause(delegate_id_1, true /* reached_end_of_stream */);
+
+ // Once the timeout task runs the first delegate should be expired while the
+ // third is kept alive.
+ {
+ EXPECT_CALL(observer_1, OnSuspendRequested(false))
+ .WillOnce(RunClosure(base::Bind(
+ &RendererWebMediaPlayerDelegate::PlayerGone,
+ base::Unretained(delegate_manager_.get()), delegate_id_1)));
+ base::RunLoop run_loop;
+ base::MessageLoop::current()->PostTask(FROM_HERE, run_loop.QuitClosure());
+ tick_clock.Advance(kIdleTimeout + base::TimeDelta::FromMicroseconds(1));
+ run_loop.Run();
+ }
+
+ delegate_manager_->RemoveObserver(delegate_id_1);
+ delegate_manager_->RemoveObserver(delegate_id_2);
+ delegate_manager_->RemoveObserver(delegate_id_3);
+ EXPECT_FALSE(delegate_manager_->IsIdleCleanupTimerRunningForTesting());
+}
+
+TEST_F(RendererWebMediaPlayerDelegateTest, IdleDelegatesIgnoresSuspendRequest) {
+ // Start the tick clock off at a non-null value.
+ base::SimpleTestTickClock tick_clock;
+ tick_clock.Advance(base::TimeDelta::FromSeconds(1234));
+
+ const base::TimeDelta kIdleTimeout = base::TimeDelta::FromSeconds(2);
+ delegate_manager_->SetIdleCleanupParamsForTesting(kIdleTimeout, &tick_clock);
+ EXPECT_FALSE(delegate_manager_->IsIdleCleanupTimerRunningForTesting());
+
+ testing::StrictMock<MockWebMediaPlayerDelegateObserver> observer_1;
+ const int delegate_id_1 = delegate_manager_->AddObserver(&observer_1);
+ EXPECT_FALSE(delegate_manager_->IsIdleCleanupTimerRunningForTesting());
+
+ // Calling DidPause() should instantly queue the timeout task.
+ delegate_manager_->DidPause(delegate_id_1, false);
+ EXPECT_TRUE(delegate_manager_->IsIdleCleanupTimerRunningForTesting());
+
+ // Wait for the suspend request, but don't call PlayerGone().
+ EXPECT_CALL(observer_1, OnSuspendRequested(false));
+ base::RunLoop run_loop;
+ base::MessageLoop::current()->PostTask(FROM_HERE, run_loop.QuitClosure());
+ tick_clock.Advance(kIdleTimeout + base::TimeDelta::FromMicroseconds(1));
+ run_loop.Run();
+
+ // Even though the player did not call PlayerGone() it should be removed from
+ // future idle cleanup polls.
+ EXPECT_FALSE(delegate_manager_->IsIdleCleanupTimerRunningForTesting());
+ delegate_manager_->RemoveObserver(delegate_id_1);
+}
+
+} // namespace media
diff --git a/chromium/content/renderer/media/renderer_webmidiaccessor_impl.h b/chromium/content/renderer/media/renderer_webmidiaccessor_impl.h
index 07ea63d5b31..0058c5ca94c 100644
--- a/chromium/content/renderer/media/renderer_webmidiaccessor_impl.h
+++ b/chromium/content/renderer/media/renderer_webmidiaccessor_impl.h
@@ -9,8 +9,8 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "third_party/WebKit/public/platform/WebMIDIAccessor.h"
-#include "third_party/WebKit/public/platform/WebMIDIAccessorClient.h"
+#include "third_party/WebKit/public/platform/modules/webmidi/WebMIDIAccessor.h"
+#include "third_party/WebKit/public/platform/modules/webmidi/WebMIDIAccessorClient.h"
namespace content {
diff --git a/chromium/content/renderer/media/rtc_certificate.cc b/chromium/content/renderer/media/rtc_certificate.cc
index 9a1ce11d513..7c2ff289238 100644
--- a/chromium/content/renderer/media/rtc_certificate.cc
+++ b/chromium/content/renderer/media/rtc_certificate.cc
@@ -4,6 +4,7 @@
#include "content/renderer/media/rtc_certificate.h"
+#include "base/memory/ptr_util.h"
#include "content/renderer/media/peer_connection_identity_store.h"
#include "url/gurl.h"
@@ -19,8 +20,8 @@ RTCCertificate::RTCCertificate(
RTCCertificate::~RTCCertificate() {
}
-RTCCertificate* RTCCertificate::shallowCopy() const {
- return new RTCCertificate(key_params_, certificate_);
+std::unique_ptr<blink::WebRTCCertificate> RTCCertificate::shallowCopy() const {
+ return base::WrapUnique(new RTCCertificate(key_params_, certificate_));
}
const blink::WebRTCKeyParams& RTCCertificate::keyParams() const {
diff --git a/chromium/content/renderer/media/rtc_certificate.h b/chromium/content/renderer/media/rtc_certificate.h
index e38e9ae625d..60af2492a2e 100644
--- a/chromium/content/renderer/media/rtc_certificate.h
+++ b/chromium/content/renderer/media/rtc_certificate.h
@@ -25,7 +25,7 @@ class RTCCertificate : public blink::WebRTCCertificate {
~RTCCertificate() override;
// blink::WebRTCCertificate implementation.
- RTCCertificate* shallowCopy() const override;
+ std::unique_ptr<blink::WebRTCCertificate> shallowCopy() const override;
const blink::WebRTCKeyParams& keyParams() const override;
uint64_t expires() const override;
diff --git a/chromium/content/renderer/media/rtc_certificate_generator.cc b/chromium/content/renderer/media/rtc_certificate_generator.cc
index 83e17cb8dbe..05661d304af 100644
--- a/chromium/content/renderer/media/rtc_certificate_generator.cc
+++ b/chromium/content/renderer/media/rtc_certificate_generator.cc
@@ -4,9 +4,11 @@
#include "content/renderer/media/rtc_certificate_generator.h"
+#include <string>
#include <utility>
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "content/renderer/media/peer_connection_identity_store.h"
#include "content/renderer/media/rtc_certificate.h"
#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
@@ -55,12 +57,12 @@ class RTCCertificateIdentityObserver
const blink::WebRTCKeyParams& key_params,
const GURL& url,
const GURL& first_party_for_cookies,
- blink::WebCallbacks<blink::WebRTCCertificate*, void>* observer) {
+ std::unique_ptr<blink::WebRTCCertificateCallback> observer) {
DCHECK(main_thread_->BelongsToCurrentThread());
DCHECK(!observer_) << "Already have a RequestIdentity in progress.";
- DCHECK(observer);
key_params_ = key_params;
- observer_ = observer;
+ observer_ = std::move(observer);
+ DCHECK(observer_);
// Identity request must be performed on the WebRTC signaling thread.
signaling_thread_->PostTask(FROM_HERE, base::Bind(
&RTCCertificateIdentityObserver::RequestIdentityOnWebRtcSignalingThread,
@@ -73,8 +75,8 @@ class RTCCertificateIdentityObserver
GURL first_party_for_cookies) {
DCHECK(signaling_thread_->BelongsToCurrentThread());
rtc::scoped_ptr<PeerConnectionIdentityStore> store(
- new PeerConnectionIdentityStore(
- main_thread_, signaling_thread_, url, first_party_for_cookies));
+ new PeerConnectionIdentityStore(main_thread_, signaling_thread_, url,
+ first_party_for_cookies));
// Request identity with |this| as the observer. OnSuccess/OnFailure will be
// called asynchronously.
store->RequestIdentity(WebRTCKeyParamsToKeyParams(key_params_), this);
@@ -106,18 +108,22 @@ class RTCCertificateIdentityObserver
DCHECK(observer_);
rtc::scoped_refptr<rtc::RTCCertificate> certificate =
rtc::RTCCertificate::Create(std::move(identity));
- main_thread_->PostTask(FROM_HERE, base::Bind(
- &RTCCertificateIdentityObserver::DoCallbackOnMainThread,
- this, new RTCCertificate(key_params_, certificate)));
+ main_thread_->PostTask(
+ FROM_HERE,
+ base::Bind(&RTCCertificateIdentityObserver::DoCallbackOnMainThread,
+ this, base::Passed(base::WrapUnique(
+ new RTCCertificate(key_params_, certificate)))));
}
- void DoCallbackOnMainThread(blink::WebRTCCertificate* certificate) {
+ void DoCallbackOnMainThread(
+ std::unique_ptr<blink::WebRTCCertificate> certificate) {
DCHECK(main_thread_->BelongsToCurrentThread());
DCHECK(observer_);
if (certificate)
- observer_->onSuccess(certificate);
+ observer_->onSuccess(std::move(certificate));
else
observer_->onError();
+ observer_.reset();
}
// The main thread is the renderer thread.
@@ -126,7 +132,7 @@ class RTCCertificateIdentityObserver
// PeerConnectionIdentityStore::RequestIdentity on, as is required.
const scoped_refptr<base::SingleThreadTaskRunner> signaling_thread_;
blink::WebRTCKeyParams key_params_;
- blink::WebCallbacks<blink::WebRTCCertificate*, void>* observer_;
+ std::unique_ptr<blink::WebRTCCertificateCallback> observer_;
DISALLOW_COPY_AND_ASSIGN(RTCCertificateIdentityObserver);
};
@@ -137,7 +143,7 @@ void RTCCertificateGenerator::generateCertificate(
const blink::WebRTCKeyParams& key_params,
const blink::WebURL& url,
const blink::WebURL& first_party_for_cookies,
- blink::WebCallbacks<blink::WebRTCCertificate*, void>* observer) {
+ std::unique_ptr<blink::WebRTCCertificateCallback> observer) {
DCHECK(isSupportedKeyParams(key_params));
#if defined(ENABLE_WEBRTC)
@@ -154,8 +160,8 @@ void RTCCertificateGenerator::generateCertificate(
new rtc::RefCountedObject<RTCCertificateIdentityObserver>(
main_thread, signaling_thread));
// |identity_observer| lives until request has completed.
- identity_observer->RequestIdentity(
- key_params, url, first_party_for_cookies, observer);
+ identity_observer->RequestIdentity(key_params, url, first_party_for_cookies,
+ std::move(observer));
#else
observer->onError();
#endif
diff --git a/chromium/content/renderer/media/rtc_certificate_generator.h b/chromium/content/renderer/media/rtc_certificate_generator.h
index 46dfbb0a882..95734fddf16 100644
--- a/chromium/content/renderer/media/rtc_certificate_generator.h
+++ b/chromium/content/renderer/media/rtc_certificate_generator.h
@@ -25,7 +25,7 @@ class RTCCertificateGenerator : public blink::WebRTCCertificateGenerator {
const blink::WebRTCKeyParams& key_params,
const blink::WebURL& url,
const blink::WebURL& first_party_for_cookies,
- blink::WebCallbacks<blink::WebRTCCertificate*, void>* observer) override;
+ std::unique_ptr<blink::WebRTCCertificateCallback> observer) override;
bool isSupportedKeyParams(const blink::WebRTCKeyParams& key_params) override;
private:
diff --git a/chromium/content/renderer/media/rtc_data_channel_handler.cc b/chromium/content/renderer/media/rtc_data_channel_handler.cc
index dfdb43268cf..804423c1e80 100644
--- a/chromium/content/renderer/media/rtc_data_channel_handler.cc
+++ b/chromium/content/renderer/media/rtc_data_channel_handler.cc
@@ -99,7 +99,8 @@ void RtcDataChannelHandler::Observer::OnMessage(
const webrtc::DataBuffer& buffer) {
// TODO(tommi): Figure out a way to transfer ownership of the buffer without
// having to create a copy. See webrtc bug 3967.
- scoped_ptr<webrtc::DataBuffer> new_buffer(new webrtc::DataBuffer(buffer));
+ std::unique_ptr<webrtc::DataBuffer> new_buffer(
+ new webrtc::DataBuffer(buffer));
main_thread_->PostTask(FROM_HERE,
base::Bind(&RtcDataChannelHandler::Observer::OnMessageImpl, this,
base::Passed(&new_buffer)));
@@ -120,7 +121,7 @@ void RtcDataChannelHandler::Observer::OnBufferedAmountDecreaseImpl(
}
void RtcDataChannelHandler::Observer::OnMessageImpl(
- scoped_ptr<webrtc::DataBuffer> buffer) {
+ std::unique_ptr<webrtc::DataBuffer> buffer) {
DCHECK(main_thread_->BelongsToCurrentThread());
if (handler_)
handler_->OnMessage(std::move(buffer));
@@ -254,15 +255,14 @@ unsigned long RtcDataChannelHandler::bufferedAmount() {
bool RtcDataChannelHandler::sendStringData(const blink::WebString& data) {
DCHECK(thread_checker_.CalledOnValidThread());
std::string utf8_buffer = base::UTF16ToUTF8(base::StringPiece16(data));
- rtc::Buffer buffer(utf8_buffer.c_str(), utf8_buffer.length());
- webrtc::DataBuffer data_buffer(buffer, false);
+ webrtc::DataBuffer data_buffer(utf8_buffer);
RecordMessageSent(data_buffer.size());
return channel()->Send(data_buffer);
}
bool RtcDataChannelHandler::sendRawData(const char* data, size_t length) {
DCHECK(thread_checker_.CalledOnValidThread());
- rtc::Buffer buffer(data, length);
+ rtc::CopyOnWriteBuffer buffer(data, length);
webrtc::DataBuffer data_buffer(buffer, true);
RecordMessageSent(data_buffer.size());
return channel()->Send(data_buffer);
@@ -316,7 +316,8 @@ void RtcDataChannelHandler::OnBufferedAmountDecrease(
webkit_client_->didDecreaseBufferedAmount(previous_amount);
}
-void RtcDataChannelHandler::OnMessage(scoped_ptr<webrtc::DataBuffer> buffer) {
+void RtcDataChannelHandler::OnMessage(
+ std::unique_ptr<webrtc::DataBuffer> buffer) {
DCHECK(thread_checker_.CalledOnValidThread());
if (!webkit_client_) {
// If this happens, the web application will not get notified of changes.
diff --git a/chromium/content/renderer/media/rtc_data_channel_handler.h b/chromium/content/renderer/media/rtc_data_channel_handler.h
index 1206d75fc1e..3b4d87350ae 100644
--- a/chromium/content/renderer/media/rtc_data_channel_handler.h
+++ b/chromium/content/renderer/media/rtc_data_channel_handler.h
@@ -8,14 +8,15 @@
#include <stddef.h>
#include <stdint.h>
+#include <memory>
+
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
#include "third_party/WebKit/public/platform/WebRTCDataChannelHandler.h"
#include "third_party/WebKit/public/platform/WebRTCDataChannelHandlerClient.h"
-#include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h"
+#include "third_party/webrtc/api/peerconnectioninterface.h"
namespace content {
@@ -64,7 +65,7 @@ class CONTENT_EXPORT RtcDataChannelHandler
private:
void OnStateChange(webrtc::DataChannelInterface::DataState state);
void OnBufferedAmountDecrease(unsigned previous_amount);
- void OnMessage(scoped_ptr<webrtc::DataBuffer> buffer);
+ void OnMessage(std::unique_ptr<webrtc::DataBuffer> buffer);
void RecordMessageSent(size_t num_bytes);
class CONTENT_EXPORT Observer
@@ -95,7 +96,7 @@ class CONTENT_EXPORT RtcDataChannelHandler
void OnStateChangeImpl(webrtc::DataChannelInterface::DataState state);
void OnBufferedAmountDecreaseImpl(unsigned previous_amount);
- void OnMessageImpl(scoped_ptr<webrtc::DataBuffer> buffer);
+ void OnMessageImpl(std::unique_ptr<webrtc::DataBuffer> buffer);
RtcDataChannelHandler* handler_;
const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
diff --git a/chromium/content/renderer/media/rtc_data_channel_handler_unittest.cc b/chromium/content/renderer/media/rtc_data_channel_handler_unittest.cc
index 3a403177951..072d5c88020 100644
--- a/chromium/content/renderer/media/rtc_data_channel_handler_unittest.cc
+++ b/chromium/content/renderer/media/rtc_data_channel_handler_unittest.cc
@@ -2,12 +2,14 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "content/renderer/media/rtc_data_channel_handler.h"
+
#include <stddef.h>
-#include "base/memory/scoped_ptr.h"
+#include <memory>
+
#include "base/test/test_simple_task_runner.h"
#include "content/renderer/media/mock_data_channel_impl.h"
-#include "content/renderer/media/rtc_data_channel_handler.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebRTCDataChannelHandlerClient.h"
@@ -49,7 +51,7 @@ class RtcDataChannelHandlerTest : public ::testing::Test {
webrtc::DataChannelInit config;
scoped_refptr<base::TestSimpleTaskRunner> signaling_thread_;
scoped_refptr<MockDataChannel> channel_;
- scoped_ptr<RtcDataChannelHandler> handler_;
+ std::unique_ptr<RtcDataChannelHandler> handler_;
};
// Add a client, change to the open state, and verify that the client has
diff --git a/chromium/content/renderer/media/rtc_dtmf_sender_handler.h b/chromium/content/renderer/media/rtc_dtmf_sender_handler.h
index 6967d484f59..b18abce6c58 100644
--- a/chromium/content/renderer/media/rtc_dtmf_sender_handler.h
+++ b/chromium/content/renderer/media/rtc_dtmf_sender_handler.h
@@ -14,7 +14,7 @@
#include "content/common/content_export.h"
#include "third_party/WebKit/public/platform/WebRTCDTMFSenderHandler.h"
#include "third_party/WebKit/public/platform/WebRTCDTMFSenderHandlerClient.h"
-#include "third_party/libjingle/source/talk/app/webrtc/dtmfsenderinterface.h"
+#include "third_party/webrtc/api/dtmfsenderinterface.h"
namespace content {
diff --git a/chromium/content/renderer/media/rtc_media_constraints.cc b/chromium/content/renderer/media/rtc_media_constraints.cc
deleted file mode 100644
index 22226ce9ea5..00000000000
--- a/chromium/content/renderer/media/rtc_media_constraints.cc
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-#include "content/renderer/media/rtc_media_constraints.h"
-
-#include <stddef.h>
-
-#include <string>
-
-#include "base/logging.h"
-#include "base/strings/string_util.h"
-#include "content/common/media/media_stream_options.h"
-#include "content/renderer/media/media_stream_video_source.h"
-#include "third_party/WebKit/public/platform/WebCString.h"
-#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-
-namespace content {
-namespace {
-
-void GetNativeMediaConstraints(
- const blink::WebVector<blink::WebMediaConstraint>& constraints,
- webrtc::MediaConstraintsInterface::Constraints* native_constraints) {
- DCHECK(native_constraints);
- for (size_t i = 0; i < constraints.size(); ++i) {
- webrtc::MediaConstraintsInterface::Constraint new_constraint;
- new_constraint.key = constraints[i].m_name.utf8();
- new_constraint.value = constraints[i].m_value.utf8();
-
- // Ignore Chrome specific Tab capture constraints.
- if (new_constraint.key == kMediaStreamSource ||
- new_constraint.key == kMediaStreamSourceId)
- continue;
-
- // Ignore sourceId constraint since that has nothing to do with webrtc.
- if (new_constraint.key == kMediaStreamSourceInfoId)
- continue;
-
- // Ignore constraints that are handled by Chrome in MediaStreamVideoSource.
- if (MediaStreamVideoSource::IsConstraintSupported(new_constraint.key))
- continue;
-
- DVLOG(3) << "MediaStreamConstraints:" << new_constraint.key
- << " : " << new_constraint.value;
- native_constraints->push_back(new_constraint);
- }
-}
-
-} // namespace
-
-RTCMediaConstraints::RTCMediaConstraints() {}
-
-RTCMediaConstraints::RTCMediaConstraints(
- const blink::WebMediaConstraints& constraints) {
- if (constraints.isNull())
- return; // Will happen in unit tests.
- blink::WebVector<blink::WebMediaConstraint> mandatory;
- constraints.getMandatoryConstraints(mandatory);
- GetNativeMediaConstraints(mandatory, &mandatory_);
- blink::WebVector<blink::WebMediaConstraint> optional;
- constraints.getOptionalConstraints(optional);
- GetNativeMediaConstraints(optional, &optional_);
-}
-
-RTCMediaConstraints::~RTCMediaConstraints() {}
-
-const webrtc::MediaConstraintsInterface::Constraints&
-RTCMediaConstraints::GetMandatory() const {
- return mandatory_;
-}
-
-const webrtc::MediaConstraintsInterface::Constraints&
-RTCMediaConstraints::GetOptional() const {
- return optional_;
-}
-
-bool RTCMediaConstraints::AddOptional(const std::string& key,
- const std::string& value,
- bool override_if_exists) {
- return AddConstraint(&optional_, key, value, override_if_exists);
-}
-
-bool RTCMediaConstraints::AddMandatory(const std::string& key,
- const std::string& value,
- bool override_if_exists) {
- return AddConstraint(&mandatory_, key, value, override_if_exists);
-}
-
-bool RTCMediaConstraints::AddConstraint(Constraints* constraints,
- const std::string& key,
- const std::string& value,
- bool override_if_exists) {
- for (Constraints::iterator iter = constraints->begin();
- iter != constraints->end();
- ++iter) {
- if (iter->key == key) {
- if (override_if_exists)
- iter->value = value;
- return override_if_exists;
- }
- }
- // The key wasn't found, add it.
- constraints->push_back(Constraint(key, value));
- return true;
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/rtc_media_constraints.h b/chromium/content/renderer/media/rtc_media_constraints.h
deleted file mode 100644
index 2c6ab27cef9..00000000000
--- a/chromium/content/renderer/media/rtc_media_constraints.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_MEDIA_RTC_MEDIA_CONSTRAINTS_H_
-#define CONTENT_RENDERER_MEDIA_RTC_MEDIA_CONSTRAINTS_H_
-
-#include "base/compiler_specific.h"
-#include "content/common/content_export.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h"
-
-namespace blink {
-class WebMediaConstraints;
-}
-
-namespace content {
-
-// RTCMediaConstraints acts as a glue layer between WebKits MediaConstraints and
-// libjingle webrtc::MediaConstraintsInterface.
-// Constraints are used by PeerConnection and getUserMedia API calls.
-class CONTENT_EXPORT RTCMediaConstraints
- : public NON_EXPORTED_BASE(webrtc::MediaConstraintsInterface) {
- public:
- RTCMediaConstraints();
- explicit RTCMediaConstraints(
- const blink::WebMediaConstraints& constraints);
- ~RTCMediaConstraints() override;
- const Constraints& GetMandatory() const override;
- const Constraints& GetOptional() const override;
- // Adds a mandatory constraint, optionally overriding an existing one.
- // If the constraint is already set and |override_if_exists| is false,
- // the function will return false, otherwise true.
- bool AddMandatory(const std::string& key, const std::string& value,
- bool override_if_exists);
- // As above, but against the optional constraints.
- bool AddOptional(const std::string& key, const std::string& value,
- bool override_if_exists);
-
- protected:
- bool AddConstraint(Constraints* constraints,
- const std::string& key,
- const std::string& value,
- bool override_if_exists);
- Constraints mandatory_;
- Constraints optional_;
-};
-
-} // namespace content
-
-
-#endif // CONTENT_RENDERER_MEDIA_RTC_MEDIA_CONSTRAINTS_H_
diff --git a/chromium/content/renderer/media/rtc_peer_connection_handler.cc b/chromium/content/renderer/media/rtc_peer_connection_handler.cc
index 47e37822656..b7095b485ac 100644
--- a/chromium/content/renderer/media/rtc_peer_connection_handler.cc
+++ b/chromium/content/renderer/media/rtc_peer_connection_handler.cc
@@ -20,15 +20,16 @@
#include "base/strings/utf_string_conversions.h"
#include "base/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/renderer/media/media_stream_audio_track.h"
+#include "content/renderer/media/media_stream_constraints_util.h"
#include "content/renderer/media/media_stream_track.h"
#include "content/renderer/media/peer_connection_tracker.h"
#include "content/renderer/media/remote_media_stream_impl.h"
#include "content/renderer/media/rtc_certificate.h"
#include "content/renderer/media/rtc_data_channel_handler.h"
#include "content/renderer/media/rtc_dtmf_sender_handler.h"
-#include "content/renderer/media/rtc_media_constraints.h"
#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
#include "content/renderer/media/webrtc/webrtc_media_stream_adapter.h"
#include "content/renderer/media/webrtc_audio_capturer.h"
@@ -37,6 +38,7 @@
#include "content/renderer/render_thread_impl.h"
#include "media/base/media_switches.h"
#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
+#include "third_party/WebKit/public/platform/WebRTCAnswerOptions.h"
#include "third_party/WebKit/public/platform/WebRTCConfiguration.h"
#include "third_party/WebKit/public/platform/WebRTCDataChannelInit.h"
#include "third_party/WebKit/public/platform/WebRTCICECandidate.h"
@@ -45,7 +47,7 @@
#include "third_party/WebKit/public/platform/WebRTCSessionDescriptionRequest.h"
#include "third_party/WebKit/public/platform/WebRTCVoidRequest.h"
#include "third_party/WebKit/public/platform/WebURL.h"
-#include "third_party/libjingle/source/talk/session/media/mediasession.h"
+#include "third_party/webrtc/pc/mediasession.h"
using webrtc::DataChannelInterface;
using webrtc::IceCandidateInterface;
@@ -256,6 +258,88 @@ void GetNativeRtcConfiguration(
blink_config.certificate(i))->rtcCertificate());
}
}
+// Scan the basic and advanced constraints until a value is found.
+// If nothing is found, the default is returned.
+// Argument 2 is a pointer to class data member.
+// Note: This code is a near duplicate of code in media_stream_audio_processor.
+// Consider extracting to a generic helper file.
+// It is NOT behaving according to spec, so should not go into blink.
+bool ScanConstraintsForBoolean(
+ const blink::WebMediaConstraints& constraints,
+ blink::BooleanConstraint blink::WebMediaTrackConstraintSet::*picker,
+ bool the_default,
+ bool* found) {
+ const auto& the_field = constraints.basic().*picker;
+ if (the_field.hasExact()) {
+ if (found) {
+ *found = true;
+ }
+ return the_field.exact();
+ }
+ for (const auto& advanced_constraint : constraints.advanced()) {
+ const auto& the_field = advanced_constraint.*picker;
+ if (the_field.hasExact()) {
+ if (found) {
+ *found = true;
+ }
+ return the_field.exact();
+ }
+ }
+ if (found) {
+ *found = false;
+ }
+ return the_default;
+}
+
+rtc::Optional<bool> ConstraintToOptional(
+ const blink::WebMediaConstraints& constraints,
+ blink::BooleanConstraint blink::WebMediaTrackConstraintSet::*picker) {
+ bool found;
+ bool the_value;
+ the_value = ScanConstraintsForBoolean(constraints, picker, false, &found);
+ if (found) {
+ return rtc::Optional<bool>(the_value);
+ }
+ return rtc::Optional<bool>();
+}
+
+void CopyConstraintsIntoRtcConfiguration(
+ const blink::WebMediaConstraints constraints,
+ webrtc::PeerConnectionInterface::RTCConfiguration* configuration) {
+ // Copy info from constraints into configuration, if present.
+ if (constraints.isEmpty()) {
+ return;
+ }
+
+ // Note: IPv6 WebRTC value is "disable" while Blink is "enable".
+ configuration->disable_ipv6 = !ScanConstraintsForBoolean(
+ constraints, &blink::WebMediaTrackConstraintSet::enableIPv6, true,
+ nullptr);
+ // Note: If an optional is not present, webrtc decides on its own
+ // what the value should be.
+ configuration->enable_dscp = ConstraintToOptional(
+ constraints, &blink::WebMediaTrackConstraintSet::enableDscp);
+ configuration->cpu_overuse_detection = ConstraintToOptional(
+ constraints, &blink::WebMediaTrackConstraintSet::googCpuOveruseDetection);
+ configuration->enable_rtp_data_channel = ScanConstraintsForBoolean(
+ constraints, &blink::WebMediaTrackConstraintSet::enableRtpDataChannels,
+ false, nullptr);
+ configuration->suspend_below_min_bitrate = ConstraintToOptional(
+ constraints, &blink::WebMediaTrackConstraintSet::
+ googEnableVideoSuspendBelowMinBitrate);
+ int rate;
+ if (GetConstraintValueAsInteger(
+ constraints,
+ &blink::WebMediaTrackConstraintSet::googScreencastMinBitrate,
+ &rate)) {
+ configuration->screencast_min_bitrate = rtc::Optional<int>(rate);
+ }
+ configuration->combined_audio_video_bwe = ConstraintToOptional(
+ constraints,
+ &blink::WebMediaTrackConstraintSet::googCombinedAudioVideoBwe);
+ configuration->enable_dtls_srtp = ConstraintToOptional(
+ constraints, &blink::WebMediaTrackConstraintSet::enableDtlsSrtp);
+}
class SessionDescriptionRequestTracker {
public:
@@ -616,6 +700,53 @@ class PeerConnectionUMAObserver : public webrtc::UMAObserver {
}
};
+void ConvertOfferOptionsToWebrtcOfferOptions(
+ const blink::WebRTCOfferOptions& options,
+ webrtc::PeerConnectionInterface::RTCOfferAnswerOptions* output) {
+ output->offer_to_receive_audio = options.offerToReceiveAudio();
+ output->offer_to_receive_video = options.offerToReceiveVideo();
+ output->voice_activity_detection = options.voiceActivityDetection();
+ output->ice_restart = options.iceRestart();
+}
+
+void ConvertAnswerOptionsToWebrtcAnswerOptions(
+ const blink::WebRTCAnswerOptions& options,
+ webrtc::PeerConnectionInterface::RTCOfferAnswerOptions* output) {
+ output->voice_activity_detection = options.voiceActivityDetection();
+}
+
+void ConvertConstraintsToWebrtcOfferOptions(
+ const blink::WebMediaConstraints& constraints,
+ webrtc::PeerConnectionInterface::RTCOfferAnswerOptions* output) {
+ if (constraints.isEmpty()) {
+ return;
+ }
+ std::string failing_name;
+ if (constraints.basic().hasMandatoryOutsideSet(
+ {constraints.basic().offerToReceiveAudio.name(),
+ constraints.basic().offerToReceiveVideo.name(),
+ constraints.basic().voiceActivityDetection.name(),
+ constraints.basic().iceRestart.name()},
+ failing_name)) {
+ // TODO(hta): Reject the calling operation with "constraint error"
+ // https://crbug.com/594894
+ DLOG(ERROR) << "Invalid mandatory constraint to CreateOffer/Answer: "
+ << failing_name;
+ }
+ GetConstraintValueAsInteger(
+ constraints, &blink::WebMediaTrackConstraintSet::offerToReceiveAudio,
+ &output->offer_to_receive_audio);
+ GetConstraintValueAsInteger(
+ constraints, &blink::WebMediaTrackConstraintSet::offerToReceiveVideo,
+ &output->offer_to_receive_video);
+ GetConstraintValueAsBoolean(
+ constraints, &blink::WebMediaTrackConstraintSet::voiceActivityDetection,
+ &output->voice_activity_detection);
+ GetConstraintValueAsBoolean(constraints,
+ &blink::WebMediaTrackConstraintSet::iceRestart,
+ &output->ice_restart);
+}
+
base::LazyInstance<std::set<RTCPeerConnectionHandler*> >::Leaky
g_peer_connection_handlers = LAZY_INSTANCE_INITIALIZER;
@@ -695,7 +826,7 @@ class RTCPeerConnectionHandler::Observer
void OnAddStream(MediaStreamInterface* stream) override {
DCHECK(stream);
- scoped_ptr<RemoteMediaStreamImpl> remote_stream(
+ std::unique_ptr<RemoteMediaStreamImpl> remote_stream(
new RemoteMediaStreamImpl(main_thread_, stream));
// The webkit object owned by RemoteMediaStreamImpl, will be initialized
@@ -713,7 +844,7 @@ class RTCPeerConnectionHandler::Observer
}
void OnDataChannel(DataChannelInterface* data_channel) override {
- scoped_ptr<RtcDataChannelHandler> handler(
+ std::unique_ptr<RtcDataChannelHandler> handler(
new RtcDataChannelHandler(main_thread_, data_channel));
main_thread_->PostTask(FROM_HERE,
base::Bind(&RTCPeerConnectionHandler::Observer::OnDataChannelImpl,
@@ -767,8 +898,8 @@ class RTCPeerConnectionHandler::Observer
candidate->candidate().address().family()));
}
- void OnAddStreamImpl(scoped_ptr<RemoteMediaStreamImpl> stream) {
- DCHECK(stream->webkit_stream().extraData()) << "Initialization not done";
+ void OnAddStreamImpl(std::unique_ptr<RemoteMediaStreamImpl> stream) {
+ DCHECK(stream->webkit_stream().getExtraData()) << "Initialization not done";
if (handler_)
handler_->OnAddStream(std::move(stream));
}
@@ -778,7 +909,7 @@ class RTCPeerConnectionHandler::Observer
handler_->OnRemoveStream(stream);
}
- void OnDataChannelImpl(scoped_ptr<RtcDataChannelHandler> handler) {
+ void OnDataChannelImpl(std::unique_ptr<RtcDataChannelHandler> handler) {
if (handler_)
handler_->OnDataChannel(std::move(handler));
}
@@ -832,33 +963,6 @@ void RTCPeerConnectionHandler::DestructAllHandlers() {
handler->client_->releasePeerConnectionHandler();
}
-// static
-void RTCPeerConnectionHandler::ConvertOfferOptionsToConstraints(
- const blink::WebRTCOfferOptions& options,
- RTCMediaConstraints* output) {
- output->AddMandatory(
- webrtc::MediaConstraintsInterface::kOfferToReceiveAudio,
- options.offerToReceiveAudio() > 0 ? "true" : "false",
- true);
-
- output->AddMandatory(
- webrtc::MediaConstraintsInterface::kOfferToReceiveVideo,
- options.offerToReceiveVideo() > 0 ? "true" : "false",
- true);
-
- if (!options.voiceActivityDetection()) {
- output->AddMandatory(
- webrtc::MediaConstraintsInterface::kVoiceActivityDetection,
- "false",
- true);
- }
-
- if (options.iceRestart()) {
- output->AddMandatory(
- webrtc::MediaConstraintsInterface::kIceRestart, "true", true);
- }
-}
-
void RTCPeerConnectionHandler::associateWithFrame(blink::WebFrame* frame) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(frame);
@@ -876,15 +980,25 @@ bool RTCPeerConnectionHandler::initialize(
webrtc::PeerConnectionInterface::RTCConfiguration config;
GetNativeRtcConfiguration(server_configuration, &config);
+
+ if (base::FeatureList::IsEnabled(features::kWebRtcEcdsaDefault)) {
+ if (config.certificates.empty()) {
+ rtc::scoped_refptr<rtc::RTCCertificate> certificate =
+ PeerConnectionDependencyFactory::GenerateDefaultCertificate();
+ config.certificates.push_back(certificate);
+ }
+ }
+
config.disable_prerenderer_smoothing =
!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableRTCSmoothnessAlgorithm);
- RTCMediaConstraints constraints(options);
+ // Copy all the relevant constraints into |config|.
+ CopyConstraintsIntoRtcConfiguration(options, &config);
peer_connection_observer_ = new Observer(weak_factory_.GetWeakPtr());
native_peer_connection_ = dependency_factory_->CreatePeerConnection(
- config, &constraints, frame_, peer_connection_observer_.get());
+ config, frame_, peer_connection_observer_.get());
if (!native_peer_connection_.get()) {
LOG(ERROR) << "Failed to initialize native PeerConnection.";
@@ -892,8 +1006,8 @@ bool RTCPeerConnectionHandler::initialize(
}
if (peer_connection_tracker_) {
- peer_connection_tracker_->RegisterPeerConnection(
- this, config, constraints, frame_);
+ peer_connection_tracker_->RegisterPeerConnection(this, config, options,
+ frame_);
}
uma_observer_ = new rtc::RefCountedObject<PeerConnectionUMAObserver>();
@@ -909,10 +1023,19 @@ bool RTCPeerConnectionHandler::InitializeForTest(
webrtc::PeerConnectionInterface::RTCConfiguration config;
GetNativeRtcConfiguration(server_configuration, &config);
+ if (base::FeatureList::IsEnabled(features::kWebRtcEcdsaDefault)) {
+ if (config.certificates.empty()) {
+ rtc::scoped_refptr<rtc::RTCCertificate> certificate =
+ PeerConnectionDependencyFactory::GenerateDefaultCertificate();
+ config.certificates.push_back(certificate);
+ }
+ }
+
peer_connection_observer_ = new Observer(weak_factory_.GetWeakPtr());
- RTCMediaConstraints constraints(options);
+ CopyConstraintsIntoRtcConfiguration(options, &config);
+
native_peer_connection_ = dependency_factory_->CreatePeerConnection(
- config, &constraints, NULL, peer_connection_observer_.get());
+ config, nullptr, peer_connection_observer_.get());
if (!native_peer_connection_.get()) {
LOG(ERROR) << "Failed to initialize native PeerConnection.";
return false;
@@ -934,11 +1057,13 @@ void RTCPeerConnectionHandler::createOffer(
PeerConnectionTracker::ACTION_CREATE_OFFER));
// TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
- RTCMediaConstraints constraints(options);
- native_peer_connection_->CreateOffer(description_request.get(), &constraints);
+ webrtc::PeerConnectionInterface::RTCOfferAnswerOptions webrtc_options;
+ ConvertConstraintsToWebrtcOfferOptions(options, &webrtc_options);
+ native_peer_connection_->CreateOffer(description_request.get(),
+ webrtc_options);
if (peer_connection_tracker_)
- peer_connection_tracker_->TrackCreateOffer(this, constraints);
+ peer_connection_tracker_->TrackCreateOffer(this, options);
}
void RTCPeerConnectionHandler::createOffer(
@@ -954,12 +1079,13 @@ void RTCPeerConnectionHandler::createOffer(
PeerConnectionTracker::ACTION_CREATE_OFFER));
// TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
- RTCMediaConstraints constraints;
- ConvertOfferOptionsToConstraints(options, &constraints);
- native_peer_connection_->CreateOffer(description_request.get(), &constraints);
+ webrtc::PeerConnectionInterface::RTCOfferAnswerOptions webrtc_options;
+ ConvertOfferOptionsToWebrtcOfferOptions(options, &webrtc_options);
+ native_peer_connection_->CreateOffer(description_request.get(),
+ webrtc_options);
if (peer_connection_tracker_)
- peer_connection_tracker_->TrackCreateOffer(this, constraints);
+ peer_connection_tracker_->TrackCreateOffer(this, options);
}
void RTCPeerConnectionHandler::createAnswer(
@@ -972,13 +1098,34 @@ void RTCPeerConnectionHandler::createAnswer(
base::ThreadTaskRunnerHandle::Get(), request,
weak_factory_.GetWeakPtr(), peer_connection_tracker_,
PeerConnectionTracker::ACTION_CREATE_ANSWER));
+ webrtc::PeerConnectionInterface::RTCOfferAnswerOptions webrtc_options;
+ ConvertConstraintsToWebrtcOfferOptions(options, &webrtc_options);
// TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
- RTCMediaConstraints constraints(options);
native_peer_connection_->CreateAnswer(description_request.get(),
- &constraints);
+ webrtc_options);
if (peer_connection_tracker_)
- peer_connection_tracker_->TrackCreateAnswer(this, constraints);
+ peer_connection_tracker_->TrackCreateAnswer(this, options);
+}
+
+void RTCPeerConnectionHandler::createAnswer(
+ const blink::WebRTCSessionDescriptionRequest& request,
+ const blink::WebRTCAnswerOptions& options) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createAnswer");
+ scoped_refptr<CreateSessionDescriptionRequest> description_request(
+ new rtc::RefCountedObject<CreateSessionDescriptionRequest>(
+ base::ThreadTaskRunnerHandle::Get(), request,
+ weak_factory_.GetWeakPtr(), peer_connection_tracker_,
+ PeerConnectionTracker::ACTION_CREATE_ANSWER));
+ // TODO(tommi): Do this asynchronously via e.g. PostTaskAndReply.
+ webrtc::PeerConnectionInterface::RTCOfferAnswerOptions webrtc_options;
+ ConvertAnswerOptionsToWebrtcAnswerOptions(options, &webrtc_options);
+ native_peer_connection_->CreateAnswer(description_request.get(),
+ webrtc_options);
+
+ if (peer_connection_tracker_)
+ peer_connection_tracker_->TrackCreateAnswer(this, options);
}
bool IsOfferOrAnswer(const webrtc::SessionDescriptionInterface* native_desc) {
@@ -1031,11 +1178,13 @@ void RTCPeerConnectionHandler::setLocalDescription(
weak_factory_.GetWeakPtr(), peer_connection_tracker_,
PeerConnectionTracker::ACTION_SET_LOCAL_DESCRIPTION));
- signaling_thread()->PostTask(FROM_HERE,
- base::Bind(&RunClosureWithTrace,
+ signaling_thread()->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &RunClosureWithTrace,
base::Bind(&webrtc::PeerConnectionInterface::SetLocalDescription,
- native_peer_connection_, set_request,
- base::Unretained(native_desc)),
+ native_peer_connection_, base::RetainedRef(set_request),
+ base::Unretained(native_desc)),
"SetLocalDescription"));
}
@@ -1082,11 +1231,13 @@ void RTCPeerConnectionHandler::setRemoteDescription(
base::ThreadTaskRunnerHandle::Get(), request,
weak_factory_.GetWeakPtr(), peer_connection_tracker_,
PeerConnectionTracker::ACTION_SET_REMOTE_DESCRIPTION));
- signaling_thread()->PostTask(FROM_HERE,
- base::Bind(&RunClosureWithTrace,
+ signaling_thread()->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &RunClosureWithTrace,
base::Bind(&webrtc::PeerConnectionInterface::SetRemoteDescription,
- native_peer_connection_, set_request,
- base::Unretained(native_desc)),
+ native_peer_connection_, base::RetainedRef(set_request),
+ base::Unretained(native_desc)),
"SetRemoteDescription"));
}
@@ -1132,18 +1283,16 @@ RTCPeerConnectionHandler::remoteDescription() {
}
bool RTCPeerConnectionHandler::updateICE(
- const blink::WebRTCConfiguration& server_configuration,
- const blink::WebMediaConstraints& options) {
+ const blink::WebRTCConfiguration& server_configuration) {
DCHECK(thread_checker_.CalledOnValidThread());
TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::updateICE");
webrtc::PeerConnectionInterface::RTCConfiguration config;
GetNativeRtcConfiguration(server_configuration, &config);
- RTCMediaConstraints constraints(options);
if (peer_connection_tracker_)
- peer_connection_tracker_->TrackUpdateIce(this, config, constraints);
+ peer_connection_tracker_->TrackUpdateIce(this, config);
- return native_peer_connection_->UpdateIce(config.servers, &constraints);
+ return native_peer_connection_->UpdateIce(config.servers);
}
bool RTCPeerConnectionHandler::addICECandidate(
@@ -1168,7 +1317,7 @@ bool RTCPeerConnectionHandler::addICECandidate(
const blink::WebRTCICECandidate& candidate) {
DCHECK(thread_checker_.CalledOnValidThread());
TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::addICECandidate");
- scoped_ptr<webrtc::IceCandidateInterface> native_candidate(
+ std::unique_ptr<webrtc::IceCandidateInterface> native_candidate(
dependency_factory_->CreateIceCandidate(
base::UTF16ToUTF8(base::StringPiece16(candidate.sdpMid())),
candidate.sdpMLineIndex(),
@@ -1234,14 +1383,13 @@ bool RTCPeerConnectionHandler::addStream(
track_metrics_.AddStream(MediaStreamTrackMetrics::SENT_STREAM,
webrtc_stream);
- RTCMediaConstraints constraints(options);
- if (!constraints.GetMandatory().empty() ||
- !constraints.GetOptional().empty()) {
+ if (!options.isEmpty()) {
// TODO(perkj): |mediaConstraints| is the name of the optional constraints
// argument in RTCPeerConnection.idl. It has been removed from the spec and
// should be removed from blink as well.
LOG(WARNING)
<< "mediaConstraints is not a supported argument to addStream.";
+ LOG(WARNING) << "mediaConstraints was " << options.toString().utf8();
}
return native_peer_connection_->AddStream(webrtc_stream);
@@ -1296,7 +1444,7 @@ void RTCPeerConnectionHandler::getStats(
blink::WebMediaStreamSource::Type track_type =
blink::WebMediaStreamSource::TypeAudio;
if (request->hasSelector()) {
- track_type = request->component().source().type();
+ track_type = request->component().source().getType();
track_id = request->component().id().utf8();
}
@@ -1364,9 +1512,9 @@ blink::WebRTCDTMFSenderHandler* RTCPeerConnectionHandler::createDTMFSender(
TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::createDTMFSender");
DVLOG(1) << "createDTMFSender.";
- MediaStreamAudioTrack* native_track = MediaStreamAudioTrack::GetTrack(track);
+ MediaStreamAudioTrack* native_track = MediaStreamAudioTrack::From(track);
if (!native_track || !native_track->is_local_track() ||
- track.source().type() != blink::WebMediaStreamSource::TypeAudio) {
+ track.source().getType() != blink::WebMediaStreamSource::TypeAudio) {
DLOG(ERROR) << "The DTMF sender requires a local audio track.";
return nullptr;
}
@@ -1480,7 +1628,7 @@ void RTCPeerConnectionHandler::OnIceGatheringChange(
GetWebKitIceGatheringState(new_state);
if (peer_connection_tracker_)
peer_connection_tracker_->TrackIceGatheringStateChange(this, state);
- if (client_)
+ if (!is_closed_)
client_->didChangeICEGatheringState(state);
}
@@ -1489,16 +1637,16 @@ void RTCPeerConnectionHandler::OnRenegotiationNeeded() {
TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnRenegotiationNeeded");
if (peer_connection_tracker_)
peer_connection_tracker_->TrackOnRenegotiationNeeded(this);
- if (client_)
+ if (!is_closed_)
client_->negotiationNeeded();
}
void RTCPeerConnectionHandler::OnAddStream(
- scoped_ptr<RemoteMediaStreamImpl> stream) {
+ std::unique_ptr<RemoteMediaStreamImpl> stream) {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(remote_streams_.find(stream->webrtc_stream().get()) ==
remote_streams_.end());
- DCHECK(stream->webkit_stream().extraData()) << "Initialization not done";
+ DCHECK(stream->webkit_stream().getExtraData()) << "Initialization not done";
TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnAddStreamImpl");
// Ownership is with remote_streams_ now.
@@ -1534,7 +1682,7 @@ void RTCPeerConnectionHandler::OnRemoveStream(
stream.get());
PerSessionWebRTCAPIMetrics::GetInstance()->DecrementStreamCounter();
- scoped_ptr<RemoteMediaStreamImpl> remote_stream(it->second);
+ std::unique_ptr<RemoteMediaStreamImpl> remote_stream(it->second);
const blink::WebMediaStream& webkit_stream = remote_stream->webkit_stream();
DCHECK(!webkit_stream.isNull());
remote_streams_.erase(it);
@@ -1549,7 +1697,7 @@ void RTCPeerConnectionHandler::OnRemoveStream(
}
void RTCPeerConnectionHandler::OnDataChannel(
- scoped_ptr<RtcDataChannelHandler> handler) {
+ std::unique_ptr<RtcDataChannelHandler> handler) {
DCHECK(thread_checker_.CalledOnValidThread());
TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnDataChannelImpl");
diff --git a/chromium/content/renderer/media/rtc_peer_connection_handler.h b/chromium/content/renderer/media/rtc_peer_connection_handler.h
index 25e30311908..7fe3bf259b7 100644
--- a/chromium/content/renderer/media/rtc_peer_connection_handler.h
+++ b/chromium/content/renderer/media/rtc_peer_connection_handler.h
@@ -8,6 +8,7 @@
#include <stddef.h>
#include <map>
+#include <memory>
#include <string>
#include "base/compiler_specific.h"
@@ -26,6 +27,7 @@
namespace blink {
class WebFrame;
+class WebRTCAnswerOptions;
class WebRTCDataChannelHandler;
class WebRTCOfferOptions;
class WebRTCPeerConnectionHandlerClient;
@@ -37,7 +39,6 @@ class PeerConnectionDependencyFactory;
class PeerConnectionTracker;
class RemoteMediaStreamImpl;
class RtcDataChannelHandler;
-class RTCMediaConstraints;
class WebRtcMediaStreamAdapter;
// Mockable wrapper for blink::WebRTCStatsResponse
@@ -100,10 +101,6 @@ class CONTENT_EXPORT RTCPeerConnectionHandler
// Destroy all existing RTCPeerConnectionHandler objects.
static void DestructAllHandlers();
- static void ConvertOfferOptionsToConstraints(
- const blink::WebRTCOfferOptions& options,
- RTCMediaConstraints* output);
-
void associateWithFrame(blink::WebFrame* frame);
// Initialize method only used for unit test.
@@ -123,6 +120,8 @@ class CONTENT_EXPORT RTCPeerConnectionHandler
void createAnswer(const blink::WebRTCSessionDescriptionRequest& request,
const blink::WebMediaConstraints& options) override;
+ void createAnswer(const blink::WebRTCSessionDescriptionRequest& request,
+ const blink::WebRTCAnswerOptions& options) override;
void setLocalDescription(
const blink::WebRTCVoidRequest& request,
@@ -134,8 +133,8 @@ class CONTENT_EXPORT RTCPeerConnectionHandler
blink::WebRTCSessionDescription localDescription() override;
blink::WebRTCSessionDescription remoteDescription() override;
- bool updateICE(const blink::WebRTCConfiguration& server_configuration,
- const blink::WebMediaConstraints& options) override;
+ bool updateICE(
+ const blink::WebRTCConfiguration& server_configuration) override;
bool addICECandidate(const blink::WebRTCICECandidate& candidate) override;
bool addICECandidate(const blink::WebRTCVoidRequest& request,
const blink::WebRTCICECandidate& candidate) override;
@@ -182,10 +181,10 @@ class CONTENT_EXPORT RTCPeerConnectionHandler
void OnIceGatheringChange(
webrtc::PeerConnectionInterface::IceGatheringState new_state);
void OnRenegotiationNeeded();
- void OnAddStream(scoped_ptr<RemoteMediaStreamImpl> stream);
+ void OnAddStream(std::unique_ptr<RemoteMediaStreamImpl> stream);
void OnRemoveStream(
const scoped_refptr<webrtc::MediaStreamInterface>& stream);
- void OnDataChannel(scoped_ptr<RtcDataChannelHandler> handler);
+ void OnDataChannel(std::unique_ptr<RtcDataChannelHandler> handler);
void OnIceCandidate(const std::string& sdp, const std::string& sdp_mid,
int sdp_mline_index, int component, int address_family);
@@ -266,8 +265,8 @@ class CONTENT_EXPORT RTCPeerConnectionHandler
// remote side to record UMA stats once both are set. We only check
// for the first offer or answer. "pranswer"s and "unknown"s (from
// unit tests) are ignored.
- scoped_ptr<FirstSessionDescription> first_local_description_;
- scoped_ptr<FirstSessionDescription> first_remote_description_;
+ std::unique_ptr<FirstSessionDescription> first_local_description_;
+ std::unique_ptr<FirstSessionDescription> first_remote_description_;
typedef std::map<webrtc::MediaStreamInterface*,
content::RemoteMediaStreamImpl*> RemoteStreamMap;
diff --git a/chromium/content/renderer/media/rtc_peer_connection_handler_unittest.cc b/chromium/content/renderer/media/rtc_peer_connection_handler_unittest.cc
index 3ae6bb27d2d..c99c27f2716 100644
--- a/chromium/content/renderer/media/rtc_peer_connection_handler_unittest.cc
+++ b/chromium/content/renderer/media/rtc_peer_connection_handler_unittest.cc
@@ -2,13 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "content/renderer/media/rtc_peer_connection_handler.h"
+
#include <stddef.h>
+#include <memory>
#include <string>
#include <vector>
#include "base/location.h"
-#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
@@ -19,13 +21,11 @@
#include "content/renderer/media/media_stream_audio_source.h"
#include "content/renderer/media/media_stream_source.h"
#include "content/renderer/media/media_stream_video_track.h"
-#include "content/renderer/media/mock_media_constraint_factory.h"
+#include "content/renderer/media/mock_data_channel_impl.h"
#include "content/renderer/media/mock_media_stream_video_source.h"
#include "content/renderer/media/mock_peer_connection_impl.h"
#include "content/renderer/media/mock_web_rtc_peer_connection_handler_client.h"
#include "content/renderer/media/peer_connection_tracker.h"
-#include "content/renderer/media/rtc_media_constraints.h"
-#include "content/renderer/media/rtc_peer_connection_handler.h"
#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
#include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
#include "content/renderer/media/webrtc_local_audio_track.h"
@@ -47,7 +47,7 @@
#include "third_party/WebKit/public/platform/WebRTCVoidRequest.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/web/WebHeap.h"
-#include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h"
+#include "third_party/webrtc/api/peerconnectioninterface.h"
static const char kDummySdp[] = "dummy sdp";
static const char kDummySdpType[] = "dummy type";
@@ -139,19 +139,18 @@ class MockPeerConnectionTracker : public PeerConnectionTracker {
// TODO(jiayl): add coverage for the following methods
MOCK_METHOD2(TrackCreateOffer,
void(RTCPeerConnectionHandler* pc_handler,
- const RTCMediaConstraints& constraints));
+ const blink::WebMediaConstraints& constraints));
MOCK_METHOD2(TrackCreateAnswer,
void(RTCPeerConnectionHandler* pc_handler,
- const RTCMediaConstraints& constraints));
+ const blink::WebMediaConstraints& constraints));
MOCK_METHOD4(TrackSetSessionDescription,
void(RTCPeerConnectionHandler* pc_handler,
const std::string& sdp, const std::string& type,
Source source));
- MOCK_METHOD3(
+ MOCK_METHOD2(
TrackUpdateIce,
void(RTCPeerConnectionHandler* pc_handler,
- const webrtc::PeerConnectionInterface::RTCConfiguration& config,
- const RTCMediaConstraints& options));
+ const webrtc::PeerConnectionInterface::RTCConfiguration& config));
MOCK_METHOD4(TrackAddIceCandidate,
void(RTCPeerConnectionHandler* pc_handler,
const blink::WebRTCICECandidate& candidate,
@@ -267,18 +266,10 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test {
blink::WebVector<blink::WebMediaStreamTrack> audio_tracks(
static_cast<size_t>(1));
audio_tracks[0].initialize(audio_source.id(), audio_source);
- StreamDeviceInfo device_info(MEDIA_DEVICE_AUDIO_CAPTURE, "Mock device",
- "mock_device_id");
- MockMediaConstraintFactory constraint_factory;
- const blink::WebMediaConstraints constraints =
- constraint_factory.CreateWebMediaConstraints();
- scoped_refptr<WebRtcAudioCapturer> capturer(
- WebRtcAudioCapturer::CreateCapturer(-1, device_info, constraints,
- nullptr, nullptr));
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
WebRtcLocalAudioTrackAdapter::Create(audio_track_label, nullptr));
- scoped_ptr<WebRtcLocalAudioTrack> native_track(
- new WebRtcLocalAudioTrack(adapter.get(), capturer, nullptr));
+ std::unique_ptr<WebRtcLocalAudioTrack> native_track(
+ new WebRtcLocalAudioTrack(adapter.get()));
audio_tracks[0].setExtraData(native_track.release());
blink::WebVector<blink::WebMediaStreamTrack> video_tracks(
static_cast<size_t>(1));
@@ -304,27 +295,21 @@ class RTCPeerConnectionHandlerTest : public ::testing::Test {
scoped_refptr<webrtc::MediaStreamInterface> stream(
mock_dependency_factory_->CreateLocalMediaStream(stream_label));
if (!video_track_label.empty()) {
- webrtc::VideoSourceInterface* source = NULL;
- scoped_refptr<webrtc::VideoTrackInterface> video_track(
- mock_dependency_factory_->CreateLocalVideoTrack(
- video_track_label, source));
- stream->AddTrack(video_track.get());
+ stream->AddTrack(MockWebRtcVideoTrack::Create(video_track_label).get());
}
if (!audio_track_label.empty()) {
- scoped_refptr<webrtc::AudioTrackInterface> audio_track(
- WebRtcLocalAudioTrackAdapter::Create(audio_track_label, NULL));
- stream->AddTrack(audio_track.get());
+ stream->AddTrack(MockWebRtcAudioTrack::Create(audio_track_label).get());
}
mock_peer_connection_->AddRemoteStream(stream.get());
return stream;
}
base::MessageLoop message_loop_;
- scoped_ptr<ChildProcess> child_process_;
- scoped_ptr<MockWebRTCPeerConnectionHandlerClient> mock_client_;
- scoped_ptr<MockPeerConnectionDependencyFactory> mock_dependency_factory_;
- scoped_ptr<NiceMock<MockPeerConnectionTracker> > mock_tracker_;
- scoped_ptr<RTCPeerConnectionHandlerUnderTest> pc_handler_;
+ std::unique_ptr<ChildProcess> child_process_;
+ std::unique_ptr<MockWebRTCPeerConnectionHandlerClient> mock_client_;
+ std::unique_ptr<MockPeerConnectionDependencyFactory> mock_dependency_factory_;
+ std::unique_ptr<NiceMock<MockPeerConnectionTracker>> mock_tracker_;
+ std::unique_ptr<RTCPeerConnectionHandlerUnderTest> pc_handler_;
// Weak reference to the mocked native peer connection implementation.
MockPeerConnectionImpl* mock_peer_connection_;
@@ -336,11 +321,53 @@ TEST_F(RTCPeerConnectionHandlerTest, Destruct) {
pc_handler_.reset(NULL);
}
+TEST_F(RTCPeerConnectionHandlerTest, NoCallbacksToClientAfterStop) {
+ pc_handler_->stop();
+
+ EXPECT_CALL(*mock_client_.get(), negotiationNeeded()).Times(0);
+ pc_handler_->observer()->OnRenegotiationNeeded();
+
+ EXPECT_CALL(*mock_client_.get(), didGenerateICECandidate(_)).Times(0);
+ std::unique_ptr<webrtc::IceCandidateInterface> native_candidate(
+ mock_dependency_factory_->CreateIceCandidate("sdpMid", 1, kDummySdp));
+ pc_handler_->observer()->OnIceCandidate(native_candidate.get());
+
+ EXPECT_CALL(*mock_client_.get(), didChangeSignalingState(_)).Times(0);
+ pc_handler_->observer()->OnSignalingChange(
+ webrtc::PeerConnectionInterface::kHaveRemoteOffer);
+
+ EXPECT_CALL(*mock_client_.get(), didChangeICEGatheringState(_)).Times(0);
+ pc_handler_->observer()->OnIceGatheringChange(
+ webrtc::PeerConnectionInterface::kIceGatheringNew);
+
+ EXPECT_CALL(*mock_client_.get(), didChangeICEConnectionState(_)).Times(0);
+ pc_handler_->observer()->OnIceConnectionChange(
+ webrtc::PeerConnectionInterface::kIceConnectionDisconnected);
+
+ EXPECT_CALL(*mock_client_.get(), didAddRemoteStream(_)).Times(0);
+ std::string remote_stream_label("remote_stream");
+ scoped_refptr<webrtc::MediaStreamInterface> remote_stream(
+ AddRemoteMockMediaStream(remote_stream_label, "video", "audio"));
+ pc_handler_->observer()->OnAddStream(remote_stream.get());
+
+ EXPECT_CALL(*mock_client_.get(), didRemoveRemoteStream(_)).Times(0);
+ pc_handler_->observer()->OnRemoveStream(remote_stream.get());
+
+ EXPECT_CALL(*mock_client_.get(), didAddRemoteDataChannel(_)).Times(0);
+ webrtc::DataChannelInit config;
+ scoped_refptr<webrtc::DataChannelInterface> remote_data_channel(
+ new rtc::RefCountedObject<MockDataChannel>("dummy", &config));
+ pc_handler_->observer()->OnDataChannel(remote_data_channel.get());
+
+ base::RunLoop().RunUntilIdle();
+}
+
TEST_F(RTCPeerConnectionHandlerTest, DestructAllHandlers) {
EXPECT_CALL(*mock_client_.get(), releasePeerConnectionHandler())
.Times(1);
RTCPeerConnectionHandler::DestructAllHandlers();
}
+
TEST_F(RTCPeerConnectionHandlerTest, CreateOffer) {
blink::WebRTCSessionDescriptionRequest request;
blink::WebMediaConstraints options;
@@ -419,13 +446,12 @@ TEST_F(RTCPeerConnectionHandlerTest, setRemoteDescription) {
TEST_F(RTCPeerConnectionHandlerTest, updateICE) {
blink::WebRTCConfiguration config;
- blink::WebMediaConstraints constraints;
- EXPECT_CALL(*mock_tracker_.get(), TrackUpdateIce(pc_handler_.get(), _, _));
+ EXPECT_CALL(*mock_tracker_.get(), TrackUpdateIce(pc_handler_.get(), _));
// TODO(perkj): Test that the parameters in |config| can be translated when a
// WebRTCConfiguration can be constructed. It's WebKit class and can't be
// initialized from a test.
- EXPECT_TRUE(pc_handler_->updateICE(config, constraints));
+ EXPECT_TRUE(pc_handler_->updateICE(config));
}
TEST_F(RTCPeerConnectionHandlerTest, addICECandidate) {
@@ -479,15 +505,14 @@ TEST_F(RTCPeerConnectionHandlerTest, addStreamWithStoppedAudioAndVideoTrack) {
blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
local_stream.audioTracks(audio_tracks);
MediaStreamAudioSource* native_audio_source =
- static_cast<MediaStreamAudioSource*>(
- audio_tracks[0].source().extraData());
+ MediaStreamAudioSource::From(audio_tracks[0].source());
native_audio_source->StopSource();
blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
local_stream.videoTracks(video_tracks);
MediaStreamVideoSource* native_video_source =
static_cast<MediaStreamVideoSource*>(
- video_tracks[0].source().extraData());
+ video_tracks[0].source().getExtraData());
native_video_source->StopSource();
EXPECT_TRUE(pc_handler_->addStream(local_stream, constraints));
@@ -763,24 +788,24 @@ TEST_F(RTCPeerConnectionHandlerTest, RemoteTrackState) {
blink::WebVector<blink::WebMediaStreamTrack> audio_tracks;
webkit_stream.audioTracks(audio_tracks);
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive,
- audio_tracks[0].source().readyState());
+ audio_tracks[0].source().getReadyState());
blink::WebVector<blink::WebMediaStreamTrack> video_tracks;
webkit_stream.videoTracks(video_tracks);
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive,
- video_tracks[0].source().readyState());
+ video_tracks[0].source().getReadyState());
- remote_stream->GetAudioTracks()[0]->set_state(
- webrtc::MediaStreamTrackInterface::kEnded);
+ static_cast<MockWebRtcAudioTrack*>(remote_stream->GetAudioTracks()[0].get())
+ ->SetEnded();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded,
- audio_tracks[0].source().readyState());
+ audio_tracks[0].source().getReadyState());
- remote_stream->GetVideoTracks()[0]->set_state(
- webrtc::MediaStreamTrackInterface::kEnded);
+ static_cast<MockWebRtcVideoTrack*>(remote_stream->GetVideoTracks()[0].get())
+ ->SetEnded();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded,
- video_tracks[0].source().readyState());
+ video_tracks[0].source().getReadyState());
}
TEST_F(RTCPeerConnectionHandlerTest, RemoveAndAddAudioTrackFromRemoteStream) {
@@ -948,7 +973,7 @@ TEST_F(RTCPeerConnectionHandlerTest, OnIceCandidate) {
PeerConnectionTracker::SOURCE_LOCAL, true));
EXPECT_CALL(*mock_client_.get(), didGenerateICECandidate(_));
- scoped_ptr<webrtc::IceCandidateInterface> native_candidate(
+ std::unique_ptr<webrtc::IceCandidateInterface> native_candidate(
mock_dependency_factory_->CreateIceCandidate("sdpMid", 1, kDummySdp));
pc_handler_->observer()->OnIceCandidate(native_candidate.get());
base::RunLoop().RunUntilIdle();
@@ -971,7 +996,7 @@ TEST_F(RTCPeerConnectionHandlerTest, CreateDataChannel) {
TrackCreateDataChannel(pc_handler_.get(),
testing::NotNull(),
PeerConnectionTracker::SOURCE_LOCAL));
- scoped_ptr<blink::WebRTCDataChannelHandler> channel(
+ std::unique_ptr<blink::WebRTCDataChannelHandler> channel(
pc_handler_->createDataChannel("d1", blink::WebRTCDataChannelInit()));
EXPECT_TRUE(channel.get() != NULL);
EXPECT_EQ(label, channel->label());
@@ -997,7 +1022,7 @@ TEST_F(RTCPeerConnectionHandlerTest, CreateDtmfSender) {
TrackCreateDTMFSender(pc_handler_.get(),
testing::Ref(tracks[0])));
- scoped_ptr<blink::WebRTCDTMFSenderHandler> sender(
+ std::unique_ptr<blink::WebRTCDTMFSenderHandler> sender(
pc_handler_->createDTMFSender(tracks[0]));
EXPECT_TRUE(sender.get());
}
diff --git a/chromium/content/renderer/media/rtc_video_decoder.cc b/chromium/content/renderer/media/rtc_video_decoder.cc
index 423b1434427..302d5d5ef85 100644
--- a/chromium/content/renderer/media/rtc_video_decoder.cc
+++ b/chromium/content/renderer/media/rtc_video_decoder.cc
@@ -20,7 +20,7 @@
#include "media/renderers/gpu_video_accelerator_factories.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/webrtc/base/bind.h"
-#include "third_party/webrtc/system_wrappers/include/ref_count.h"
+#include "third_party/webrtc/base/refcount.h"
#include "third_party/webrtc/video_frame.h"
namespace content {
@@ -28,6 +28,7 @@ namespace content {
const int32_t RTCVideoDecoder::ID_LAST = 0x3FFFFFFF;
const int32_t RTCVideoDecoder::ID_HALF = 0x20000000;
const int32_t RTCVideoDecoder::ID_INVALID = -1;
+const uint32_t kNumVDAErrorsBeforeSWFallback = 50;
// Maximum number of concurrent VDA::Decode() operations RVD will maintain.
// Higher values allow better pipelining in the GPU, but also require more
@@ -55,7 +56,8 @@ RTCVideoDecoder::BufferData::~BufferData() {}
RTCVideoDecoder::RTCVideoDecoder(webrtc::VideoCodecType type,
media::GpuVideoAcceleratorFactories* factories)
- : video_codec_type_(type),
+ : vda_error_counter_(0),
+ video_codec_type_(type),
factories_(factories),
decoder_texture_target_(0),
next_picture_buffer_id_(0),
@@ -83,10 +85,10 @@ RTCVideoDecoder::~RTCVideoDecoder() {
}
// static
-scoped_ptr<RTCVideoDecoder> RTCVideoDecoder::Create(
+std::unique_ptr<RTCVideoDecoder> RTCVideoDecoder::Create(
webrtc::VideoCodecType type,
media::GpuVideoAcceleratorFactories* factories) {
- scoped_ptr<RTCVideoDecoder> decoder;
+ std::unique_ptr<RTCVideoDecoder> decoder;
// Convert WebRTC codec type to media codec profile.
media::VideoCodecProfile profile;
switch (type) {
@@ -160,6 +162,14 @@ int32_t RTCVideoDecoder::Decode(
if (state_ == DECODE_ERROR) {
LOG(ERROR) << "Decoding error occurred.";
+ // Try reseting the session up to |kNumVDAErrorsHandled| times.
+ if (vda_error_counter_ > kNumVDAErrorsBeforeSWFallback) {
+ DLOG(ERROR) << vda_error_counter_
+ << " errors reported by VDA, falling back to software decode";
+ return WEBRTC_VIDEO_CODEC_FALLBACK_SOFTWARE;
+ }
+ base::AutoUnlock auto_unlock(lock_);
+ Release();
return WEBRTC_VIDEO_CODEC_ERROR;
}
@@ -219,7 +229,7 @@ int32_t RTCVideoDecoder::Decode(
// If a shared memory segment is available, there are no pending buffers, and
// this isn't a mid-stream resolution change, then send the buffer for decode
// immediately. Otherwise, save the buffer in the queue for later decode.
- scoped_ptr<base::SharedMemory> shm_buffer;
+ std::unique_ptr<base::SharedMemory> shm_buffer;
if (!need_to_reset_for_midstream_resize && pending_buffers_.empty())
shm_buffer = GetSHM_Locked(inputImage._length);
if (!shm_buffer) {
@@ -235,9 +245,10 @@ int32_t RTCVideoDecoder::Decode(
if (need_to_reset_for_midstream_resize) {
base::AutoUnlock auto_unlock(lock_);
- Reset();
+ Release();
}
+ TryResetVDAErrorCounter_Locked();
return WEBRTC_VIDEO_CODEC_OK;
}
@@ -246,6 +257,7 @@ int32_t RTCVideoDecoder::Decode(
FROM_HERE,
base::Bind(&RTCVideoDecoder::RequestBufferDecode,
weak_factory_.GetWeakPtr()));
+ TryResetVDAErrorCounter_Locked();
return WEBRTC_VIDEO_CODEC_OK;
}
@@ -262,11 +274,6 @@ int32_t RTCVideoDecoder::Release() {
DVLOG(2) << "Release";
// Do not destroy VDA because WebRTC can call InitDecode and start decoding
// again.
- return Reset();
-}
-
-int32_t RTCVideoDecoder::Reset() {
- DVLOG(2) << "Reset";
base::AutoLock auto_lock(lock_);
if (state_ == UNINITIALIZED) {
LOG(ERROR) << "Decoder not initialized.";
@@ -288,10 +295,12 @@ int32_t RTCVideoDecoder::Reset() {
}
void RTCVideoDecoder::ProvidePictureBuffers(uint32_t count,
+ uint32_t textures_per_buffer,
const gfx::Size& size,
uint32_t texture_target) {
DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
DVLOG(3) << "ProvidePictureBuffers. texture_target=" << texture_target;
+ DCHECK_EQ(1u, textures_per_buffer);
if (!vda_)
return;
@@ -312,8 +321,13 @@ void RTCVideoDecoder::ProvidePictureBuffers(uint32_t count,
std::vector<media::PictureBuffer> picture_buffers;
for (size_t i = 0; i < texture_ids.size(); ++i) {
- picture_buffers.push_back(media::PictureBuffer(
- next_picture_buffer_id_++, size, texture_ids[i], texture_mailboxes[i]));
+ media::PictureBuffer::TextureIds ids;
+ ids.push_back(texture_ids[i]);
+ std::vector<gpu::Mailbox> mailboxes;
+ mailboxes.push_back(texture_mailboxes[i]);
+
+ picture_buffers.push_back(
+ media::PictureBuffer(next_picture_buffer_id_++, size, ids, mailboxes));
bool inserted = assigned_picture_buffers_.insert(std::make_pair(
picture_buffers.back().id(), picture_buffers.back())).second;
DCHECK(inserted);
@@ -337,7 +351,7 @@ void RTCVideoDecoder::DismissPictureBuffer(int32_t id) {
if (!picture_buffers_at_display_.count(id)) {
// We can delete the texture immediately as it's not being displayed.
- factories_->DeleteTexture(buffer_to_dismiss.texture_id());
+ factories_->DeleteTexture(buffer_to_dismiss.texture_ids()[0]);
return;
}
// Not destroying a texture in display in |picture_buffers_at_display_|.
@@ -376,10 +390,10 @@ void RTCVideoDecoder::PictureReady(const media::Picture& picture) {
NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
return;
}
- bool inserted =
- picture_buffers_at_display_.insert(std::make_pair(
- picture.picture_buffer_id(),
- pb.texture_id())).second;
+ bool inserted = picture_buffers_at_display_
+ .insert(std::make_pair(picture.picture_buffer_id(),
+ pb.texture_ids()[0]))
+ .second;
DCHECK(inserted);
// Create a WebRTC video frame.
@@ -387,7 +401,7 @@ void RTCVideoDecoder::PictureReady(const media::Picture& picture) {
new rtc::RefCountedObject<WebRtcVideoFrameAdapter>(frame), timestamp, 0,
webrtc::kVideoRotation_0);
- // Invoke decode callback. WebRTC expects no callback after Reset or Release.
+ // Invoke decode callback. WebRTC expects no callback after Release.
{
base::AutoLock auto_lock(lock_);
DCHECK(decode_complete_callback_);
@@ -413,11 +427,11 @@ scoped_refptr<media::VideoFrame> RTCVideoDecoder::CreateVideoFrame(
// correct format is used and everyone down the line understands it.
scoped_refptr<media::VideoFrame> frame = media::VideoFrame::WrapNativeTexture(
media::PIXEL_FORMAT_ARGB,
- gpu::MailboxHolder(pb.texture_mailbox(), gpu::SyncToken(),
+ gpu::MailboxHolder(pb.texture_mailbox(0), gpu::SyncToken(),
decoder_texture_target_),
media::BindToCurrentLoop(base::Bind(
&RTCVideoDecoder::ReleaseMailbox, weak_factory_.GetWeakPtr(),
- factories_, picture.picture_buffer_id(), pb.texture_id())),
+ factories_, picture.picture_buffer_id(), pb.texture_ids()[0])),
pb.size(), visible_rect, visible_rect.size(), timestamp_ms);
if (frame && picture.allow_overlay()) {
frame->metadata()->SetBoolean(media::VideoFrameMetadata::ALLOW_OVERLAY,
@@ -440,7 +454,7 @@ void RTCVideoDecoder::NotifyEndOfBitstreamBuffer(int32_t id) {
{
base::AutoLock auto_lock(lock_);
- PutSHM_Locked(scoped_ptr<base::SharedMemory>(it->second));
+ PutSHM_Locked(std::unique_ptr<base::SharedMemory>(it->second));
}
bitstream_buffers_in_decoder_.erase(it);
@@ -474,13 +488,13 @@ void RTCVideoDecoder::NotifyError(media::VideoDecodeAccelerator::Error error) {
return;
LOG(ERROR) << "VDA Error:" << error;
- UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoDecoderError",
- error,
- media::VideoDecodeAccelerator::LARGEST_ERROR_ENUM);
+ UMA_HISTOGRAM_ENUMERATION("Media.RTCVideoDecoderError", error,
+ media::VideoDecodeAccelerator::ERROR_MAX + 1);
DestroyVDA();
base::AutoLock auto_lock(lock_);
state_ = DECODE_ERROR;
+ ++vda_error_counter_;
}
void RTCVideoDecoder::RequestBufferDecode() {
@@ -492,7 +506,7 @@ void RTCVideoDecoder::RequestBufferDecode() {
while (CanMoreDecodeWorkBeDone()) {
// Get a buffer and data from the queue.
- scoped_ptr<base::SharedMemory> shm_buffer;
+ std::unique_ptr<base::SharedMemory> shm_buffer;
BufferData buffer_data;
{
base::AutoLock auto_lock(lock_);
@@ -502,7 +516,7 @@ void RTCVideoDecoder::RequestBufferDecode() {
shm_buffer.reset(decode_buffers_.front().first);
buffer_data = decode_buffers_.front().second;
decode_buffers_.pop_front();
- // Drop the buffers before Reset or Release is called.
+ // Drop the buffers before Release is called.
if (!IsBufferAfterReset(buffer_data.bitstream_buffer_id,
reset_bitstream_buffer_id_)) {
PutSHM_Locked(std::move(shm_buffer));
@@ -513,7 +527,7 @@ void RTCVideoDecoder::RequestBufferDecode() {
// Create a BitstreamBuffer and send to VDA to decode.
media::BitstreamBuffer bitstream_buffer(
buffer_data.bitstream_buffer_id, shm_buffer->handle(), buffer_data.size,
- base::TimeDelta::FromInternalValue(buffer_data.timestamp));
+ 0, base::TimeDelta::FromInternalValue(buffer_data.timestamp));
const bool inserted =
bitstream_buffers_in_decoder_.insert(
std::make_pair(bitstream_buffer.id(), shm_buffer.release())).second;
@@ -546,7 +560,7 @@ bool RTCVideoDecoder::IsFirstBufferAfterReset(int32_t id_buffer,
void RTCVideoDecoder::SaveToDecodeBuffers_Locked(
const webrtc::EncodedImage& input_image,
- scoped_ptr<base::SharedMemory> shm_buffer,
+ std::unique_ptr<base::SharedMemory> shm_buffer,
const BufferData& buffer_data) {
memcpy(shm_buffer->memory(), input_image._buffer, input_image._length);
std::pair<base::SharedMemory*, BufferData> buffer_pair =
@@ -591,7 +605,7 @@ void RTCVideoDecoder::MovePendingBuffersToDecodeBuffers() {
const webrtc::EncodedImage& input_image = pending_buffers_.front().first;
const BufferData& buffer_data = pending_buffers_.front().second;
- // Drop the frame if it comes before Reset or Release.
+ // Drop the frame if it comes before Release.
if (!IsBufferAfterReset(buffer_data.bitstream_buffer_id,
reset_bitstream_buffer_id_)) {
delete[] input_image._buffer;
@@ -599,7 +613,7 @@ void RTCVideoDecoder::MovePendingBuffersToDecodeBuffers() {
continue;
}
// Get shared memory and save it to decode buffers.
- scoped_ptr<base::SharedMemory> shm_buffer =
+ std::unique_ptr<base::SharedMemory> shm_buffer =
GetSHM_Locked(input_image._length);
if (!shm_buffer)
return;
@@ -610,10 +624,16 @@ void RTCVideoDecoder::MovePendingBuffersToDecodeBuffers() {
}
void RTCVideoDecoder::ResetInternal() {
+ DVLOG(2) << __FUNCTION__;
DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent();
- DVLOG(2) << "ResetInternal";
- if (vda_)
+
+ if (vda_) {
vda_->Reset();
+ } else {
+ CreateVDA(vda_codec_profile_, nullptr);
+ if (vda_)
+ state_ = INITIALIZED;
+ }
}
// static
@@ -685,9 +705,11 @@ void RTCVideoDecoder::CreateVDA(media::VideoCodecProfile profile,
media::VideoDecodeAccelerator::Config config(profile);
if (vda_ && !vda_->Initialize(config, this))
vda_.release()->Destroy();
+ vda_codec_profile_ = profile;
}
- waiter->Signal();
+ if (waiter)
+ waiter->Signal();
}
void RTCVideoDecoder::DestroyTextures() {
@@ -699,7 +721,7 @@ void RTCVideoDecoder::DestroyTextures() {
assigned_picture_buffers_.erase(picture_buffer_at_display.first);
for (const auto& assigned_picture_buffer : assigned_picture_buffers_)
- factories_->DeleteTexture(assigned_picture_buffer.second.texture_id());
+ factories_->DeleteTexture(assigned_picture_buffer.second.texture_ids()[0]);
assigned_picture_buffers_.clear();
}
@@ -710,15 +732,23 @@ void RTCVideoDecoder::DestroyVDA() {
if (vda_)
vda_.release()->Destroy();
DestroyTextures();
+
base::AutoLock auto_lock(lock_);
+
+ // Put the buffers back in case we restart the decoder.
+ for (const auto& buffer : bitstream_buffers_in_decoder_)
+ PutSHM_Locked(std::unique_ptr<base::SharedMemory>(buffer.second));
+ bitstream_buffers_in_decoder_.clear();
+
state_ = UNINITIALIZED;
}
-scoped_ptr<base::SharedMemory> RTCVideoDecoder::GetSHM_Locked(size_t min_size) {
+std::unique_ptr<base::SharedMemory> RTCVideoDecoder::GetSHM_Locked(
+ size_t min_size) {
// Reuse a SHM if possible.
if (!available_shm_segments_.empty() &&
available_shm_segments_.back()->mapped_size() >= min_size) {
- scoped_ptr<base::SharedMemory> buffer(available_shm_segments_.back());
+ std::unique_ptr<base::SharedMemory> buffer(available_shm_segments_.back());
available_shm_segments_.pop_back();
return buffer;
}
@@ -747,7 +777,8 @@ scoped_ptr<base::SharedMemory> RTCVideoDecoder::GetSHM_Locked(size_t min_size) {
return NULL;
}
-void RTCVideoDecoder::PutSHM_Locked(scoped_ptr<base::SharedMemory> shm_buffer) {
+void RTCVideoDecoder::PutSHM_Locked(
+ std::unique_ptr<base::SharedMemory> shm_buffer) {
lock_.AssertAcquired();
available_shm_segments_.push_back(shm_buffer.release());
}
@@ -757,7 +788,8 @@ void RTCVideoDecoder::CreateSHM(size_t count, size_t size) {
DVLOG(2) << "CreateSHM. count=" << count << ", size=" << size;
for (size_t i = 0; i < count; i++) {
- scoped_ptr<base::SharedMemory> shm = factories_->CreateSharedMemory(size);
+ std::unique_ptr<base::SharedMemory> shm =
+ factories_->CreateSharedMemory(size);
if (!shm) {
LOG(ERROR) << "Failed allocating shared memory of size=" << size;
NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
@@ -818,4 +850,12 @@ void RTCVideoDecoder::ClearPendingBuffers() {
pending_buffers_.clear();
}
+void RTCVideoDecoder::TryResetVDAErrorCounter_Locked() {
+ lock_.AssertAcquired();
+
+ if (vda_error_counter_ == 0)
+ return;
+ vda_error_counter_ = 0;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/rtc_video_decoder.h b/chromium/content/renderer/media/rtc_video_decoder.h
index 9728866432b..20c6a3364b4 100644
--- a/chromium/content/renderer/media/rtc_video_decoder.h
+++ b/chromium/content/renderer/media/rtc_video_decoder.h
@@ -56,7 +56,7 @@ class CONTENT_EXPORT RTCVideoDecoder
// Creates a RTCVideoDecoder on the message loop of |factories|. Returns NULL
// if failed. The video decoder will run on the message loop of |factories|.
- static scoped_ptr<RTCVideoDecoder> Create(
+ static std::unique_ptr<RTCVideoDecoder> Create(
webrtc::VideoCodecType type,
media::GpuVideoAcceleratorFactories* factories);
// Destroys |decoder| on the loop of |factories|
@@ -79,12 +79,10 @@ class CONTENT_EXPORT RTCVideoDecoder
// Called on Chrome_libJingle_WorkerThread. The child thread is blocked while
// this runs.
int32_t Release() override;
- // Called on Chrome_libJingle_WorkerThread. The child thread is blocked while
- // this runs.
- int32_t Reset() override;
// VideoDecodeAccelerator::Client implementation.
void ProvidePictureBuffers(uint32_t count,
+ uint32_t textures_per_buffer,
const gfx::Size& size,
uint32_t texture_target) override;
void DismissPictureBuffer(int32_t id) override;
@@ -111,6 +109,7 @@ class CONTENT_EXPORT RTCVideoDecoder
FRIEND_TEST_ALL_PREFIXES(RTCVideoDecoderTest, IsBufferAfterReset);
FRIEND_TEST_ALL_PREFIXES(RTCVideoDecoderTest, IsFirstBufferAfterReset);
+ FRIEND_TEST_ALL_PREFIXES(RTCVideoDecoderTest, GetVDAErrorCounterForTesting);
RTCVideoDecoder(webrtc::VideoCodecType type,
media::GpuVideoAcceleratorFactories* factories);
@@ -128,10 +127,13 @@ class CONTENT_EXPORT RTCVideoDecoder
// |id_reset|.
bool IsFirstBufferAfterReset(int32_t id_buffer, int32_t id_reset);
+ int GetVDAErrorCounterForTesting() { return vda_error_counter_; }
+
// Saves a WebRTC buffer in |decode_buffers_| for decode.
- void SaveToDecodeBuffers_Locked(const webrtc::EncodedImage& input_image,
- scoped_ptr<base::SharedMemory> shm_buffer,
- const BufferData& buffer_data);
+ void SaveToDecodeBuffers_Locked(
+ const webrtc::EncodedImage& input_image,
+ std::unique_ptr<base::SharedMemory> shm_buffer,
+ const BufferData& buffer_data);
// Saves a WebRTC buffer in |pending_buffers_| waiting for SHM available.
// Returns true on success.
@@ -159,7 +161,7 @@ class CONTENT_EXPORT RTCVideoDecoder
// Tells VDA that a picture buffer can be recycled.
void ReusePictureBuffer(int64_t picture_buffer_id);
- // Create |vda_| on |vda_loop_proxy_|.
+ // Creates |vda_| on |vda_loop_proxy_|.
void CreateVDA(media::VideoCodecProfile profile, base::WaitableEvent* waiter);
void DestroyTextures();
@@ -168,10 +170,10 @@ class CONTENT_EXPORT RTCVideoDecoder
// Gets a shared-memory segment of at least |min_size| bytes from
// |available_shm_segments_|. Returns NULL if there is no buffer or the
// buffer is not big enough.
- scoped_ptr<base::SharedMemory> GetSHM_Locked(size_t min_size);
+ std::unique_ptr<base::SharedMemory> GetSHM_Locked(size_t min_size);
// Returns a shared-memory segment to the available pool.
- void PutSHM_Locked(scoped_ptr<base::SharedMemory> shm_buffer);
+ void PutSHM_Locked(std::unique_ptr<base::SharedMemory> shm_buffer);
// Allocates |count| shared memory buffers of |size| bytes.
void CreateSHM(size_t count, size_t size);
@@ -186,17 +188,20 @@ class CONTENT_EXPORT RTCVideoDecoder
// Records the result of InitDecode to UMA and returns |status|.
int32_t RecordInitDecodeUMA(int32_t status);
- // Assert the contract that this class is operated on the right thread.
+ // Asserts the contract that this class is operated on the right thread.
void DCheckGpuVideoAcceleratorFactoriesTaskRunnerIsCurrent() const;
- // Query factories_ whether |profile| is supported and return true is so,
+ // Queries factories_ whether |profile| is supported and return true is so,
// false otherwise. If true, also set resolution limits for |profile|
// in min/max_resolution_.
bool IsProfileSupported(media::VideoCodecProfile profile);
- // Clear the pending_buffers_ queue, freeing memory.
+ // Clears the pending_buffers_ queue, freeing memory.
void ClearPendingBuffers();
+ // Resets |vda_error_counter_| after a successfull run of decode.
+ void TryResetVDAErrorCounter_Locked();
+
enum State {
UNINITIALIZED, // The decoder has not initialized.
INITIALIZED, // The decoder has initialized.
@@ -209,7 +214,12 @@ class CONTENT_EXPORT RTCVideoDecoder
static const int32_t ID_INVALID; // indicates Reset or Release never occurred
// The hardware video decoder.
- scoped_ptr<media::VideoDecodeAccelerator> vda_;
+ std::unique_ptr<media::VideoDecodeAccelerator> vda_;
+
+ media::VideoCodecProfile vda_codec_profile_;
+
+ // Number of times that |vda_| notified of an error.
+ uint32_t vda_error_counter_;
// The video codec type, as reported by WebRTC.
const webrtc::VideoCodecType video_codec_type_;
@@ -244,7 +254,8 @@ class CONTENT_EXPORT RTCVideoDecoder
// Protects |state_|, |decode_complete_callback_| , |num_shm_buffers_|,
// |available_shm_segments_|, |pending_buffers_|, |decode_buffers_|,
- // |next_bitstream_buffer_id_| and |reset_bitstream_buffer_id_|.
+ // |next_bitstream_buffer_id_|, |reset_bitstream_buffer_id_| and
+ // |vda_error_counter_|.
base::Lock lock_;
// The state of RTCVideoDecoder. Guarded by |lock_|.
diff --git a/chromium/content/renderer/media/rtc_video_decoder_factory.cc b/chromium/content/renderer/media/rtc_video_decoder_factory.cc
index e65ac03375b..0802698385e 100644
--- a/chromium/content/renderer/media/rtc_video_decoder_factory.cc
+++ b/chromium/content/renderer/media/rtc_video_decoder_factory.cc
@@ -4,7 +4,8 @@
#include "content/renderer/media/rtc_video_decoder_factory.h"
-#include "base/memory/scoped_ptr.h"
+#include <memory>
+
#include "content/renderer/media/rtc_video_decoder.h"
#include "media/renderers/gpu_video_accelerator_factories.h"
diff --git a/chromium/content/renderer/media/rtc_video_decoder_factory.h b/chromium/content/renderer/media/rtc_video_decoder_factory.h
index c3475de6de8..7212b98bc78 100644
--- a/chromium/content/renderer/media/rtc_video_decoder_factory.h
+++ b/chromium/content/renderer/media/rtc_video_decoder_factory.h
@@ -8,7 +8,7 @@
#include "base/macros.h"
#include "base/threading/thread.h"
#include "content/common/content_export.h"
-#include "third_party/libjingle/source/talk/media/webrtc/webrtcvideodecoderfactory.h"
+#include "third_party/webrtc/media/engine/webrtcvideodecoderfactory.h"
#include "third_party/webrtc/modules/video_coding/include/video_codec_interface.h"
namespace webrtc {
diff --git a/chromium/content/renderer/media/rtc_video_decoder_unittest.cc b/chromium/content/renderer/media/rtc_video_decoder_unittest.cc
index 01df562357b..4b765efdd97 100644
--- a/chromium/content/renderer/media/rtc_video_decoder_unittest.cc
+++ b/chromium/content/renderer/media/rtc_video_decoder_unittest.cc
@@ -21,13 +21,24 @@ using ::testing::_;
using ::testing::Invoke;
using ::testing::Return;
using ::testing::SaveArg;
+using ::testing::Values;
using ::testing::WithArgs;
namespace content {
-// TODO(wuchengli): add MockSharedMemroy so more functions can be tested.
-class RTCVideoDecoderTest : public ::testing::Test,
- webrtc::DecodedImageCallback {
+namespace {
+
+static const int kMinResolutionWidth = 16;
+static const int kMinResolutionHeight = 16;
+static const int kMaxResolutionWidth = 1920;
+static const int kMaxResolutionHeight = 1088;
+
+} // namespace
+
+// TODO(wuchengli): add MockSharedMemory so more functions can be tested.
+class RTCVideoDecoderTest
+ : public ::testing::TestWithParam<webrtc::VideoCodecType>,
+ webrtc::DecodedImageCallback {
public:
RTCVideoDecoderTest()
: mock_gpu_factories_(
@@ -43,8 +54,10 @@ class RTCVideoDecoderTest : public ::testing::Test,
mock_vda_ = new media::MockVideoDecodeAccelerator;
media::VideoDecodeAccelerator::SupportedProfile supported_profile;
- supported_profile.min_resolution.SetSize(16, 16);
- supported_profile.max_resolution.SetSize(1920, 1088);
+ supported_profile.min_resolution.SetSize(kMinResolutionWidth,
+ kMinResolutionHeight);
+ supported_profile.max_resolution.SetSize(kMaxResolutionWidth,
+ kMaxResolutionHeight);
supported_profile.profile = media::H264PROFILE_MAIN;
capabilities_.supported_profiles.push_back(supported_profile);
supported_profile.profile = media::VP8PROFILE_ANY;
@@ -101,6 +114,14 @@ class RTCVideoDecoderTest : public ::testing::Test,
base::Unretained(rtc_decoder_.get())));
}
+ void NotifyError(media::VideoDecodeAccelerator::Error error) {
+ DVLOG(2) << "NotifyError";
+ vda_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&RTCVideoDecoder::NotifyError,
+ base::Unretained(rtc_decoder_.get()), error));
+ }
+
void RunUntilIdle() {
DVLOG(2) << "RunUntilIdle";
vda_task_runner_->PostTask(FROM_HERE,
@@ -109,10 +130,21 @@ class RTCVideoDecoderTest : public ::testing::Test,
idle_waiter_.Wait();
}
+ void SetUpResetVDA() {
+ mock_vda_after_reset_ = new media::MockVideoDecodeAccelerator;
+ EXPECT_CALL(*mock_gpu_factories_.get(), DoCreateVideoDecodeAccelerator())
+ .WillRepeatedly(Return(mock_vda_after_reset_));
+ EXPECT_CALL(*mock_vda_after_reset_, Initialize(_, _))
+ .Times(1)
+ .WillRepeatedly(Return(true));
+ EXPECT_CALL(*mock_vda_after_reset_, Destroy()).Times(1);
+ }
+
protected:
- scoped_ptr<media::MockGpuVideoAcceleratorFactories> mock_gpu_factories_;
+ std::unique_ptr<media::MockGpuVideoAcceleratorFactories> mock_gpu_factories_;
media::MockVideoDecodeAccelerator* mock_vda_;
- scoped_ptr<RTCVideoDecoder> rtc_decoder_;
+ media::MockVideoDecodeAccelerator* mock_vda_after_reset_;
+ std::unique_ptr<RTCVideoDecoder> rtc_decoder_;
webrtc::VideoCodec codec_;
base::Thread vda_thread_;
media::VideoDecodeAccelerator::Capabilities capabilities_;
@@ -126,13 +158,14 @@ class RTCVideoDecoderTest : public ::testing::Test,
TEST_F(RTCVideoDecoderTest, CreateReturnsNullOnUnsupportedCodec) {
CreateDecoder(webrtc::kVideoCodecVP8);
- scoped_ptr<RTCVideoDecoder> null_rtc_decoder(RTCVideoDecoder::Create(
+ std::unique_ptr<RTCVideoDecoder> null_rtc_decoder(RTCVideoDecoder::Create(
webrtc::kVideoCodecI420, mock_gpu_factories_.get()));
EXPECT_EQ(NULL, null_rtc_decoder.get());
}
-TEST_F(RTCVideoDecoderTest, CreateAndInitSucceedsForH264Codec) {
- CreateDecoder(webrtc::kVideoCodecH264);
+TEST_P(RTCVideoDecoderTest, CreateAndInitSucceeds) {
+ const webrtc::VideoCodecType codec_type = GetParam();
+ CreateDecoder(codec_type);
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->InitDecode(&codec_, 1));
}
@@ -146,7 +179,7 @@ TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorWithoutInitDecode) {
CreateDecoder(webrtc::kVideoCodecVP8);
webrtc::EncodedImage input_image;
EXPECT_EQ(WEBRTC_VIDEO_CODEC_UNINITIALIZED,
- rtc_decoder_->Decode(input_image, false, NULL, NULL, 0));
+ rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
}
TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnIncompleteFrame) {
@@ -155,7 +188,7 @@ TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnIncompleteFrame) {
webrtc::EncodedImage input_image;
input_image._completeFrame = false;
EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
- rtc_decoder_->Decode(input_image, false, NULL, NULL, 0));
+ rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
}
TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnMissingFrames) {
@@ -164,16 +197,9 @@ TEST_F(RTCVideoDecoderTest, DecodeReturnsErrorOnMissingFrames) {
webrtc::EncodedImage input_image;
input_image._completeFrame = true;
bool missingFrames = true;
- EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
- rtc_decoder_->Decode(input_image, missingFrames, NULL, NULL, 0));
-}
-
-TEST_F(RTCVideoDecoderTest, ResetReturnsOk) {
- CreateDecoder(webrtc::kVideoCodecVP8);
- Initialize();
- EXPECT_CALL(*mock_vda_, Reset())
- .WillOnce(Invoke(this, &RTCVideoDecoderTest::NotifyResetDone));
- EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK, rtc_decoder_->Reset());
+ EXPECT_EQ(
+ WEBRTC_VIDEO_CODEC_ERROR,
+ rtc_decoder_->Decode(input_image, missingFrames, nullptr, nullptr, 0));
}
TEST_F(RTCVideoDecoderTest, ReleaseReturnsOk) {
@@ -245,4 +271,47 @@ TEST_F(RTCVideoDecoderTest, IsFirstBufferAfterReset) {
rtc_decoder_->IsFirstBufferAfterReset(1, RTCVideoDecoder::ID_LAST));
}
+
+TEST_P(RTCVideoDecoderTest, GetVDAErrorCounterForTesting) {
+ const webrtc::VideoCodecType codec_type = GetParam();
+ CreateDecoder(codec_type);
+ Initialize();
+
+ webrtc::EncodedImage input_image;
+ input_image._completeFrame = true;
+ input_image._encodedWidth = kMinResolutionWidth;
+ input_image._encodedHeight = kMaxResolutionHeight;
+ input_image._frameType = webrtc::kVideoFrameDelta;
+ EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
+ rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
+ RunUntilIdle();
+
+ // Notify the decoder about a platform error.
+ NotifyError(media::VideoDecodeAccelerator::PLATFORM_FAILURE);
+ RunUntilIdle();
+ EXPECT_EQ(1, rtc_decoder_->GetVDAErrorCounterForTesting());
+
+ // Expect decode call to reset decoder, and set up a new VDA to track it.
+ SetUpResetVDA();
+ EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
+ rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
+ EXPECT_EQ(1, rtc_decoder_->GetVDAErrorCounterForTesting());
+
+ // Decoder expects a keyframe after reset, so drops any other frames.
+ EXPECT_EQ(WEBRTC_VIDEO_CODEC_ERROR,
+ rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 0));
+ EXPECT_EQ(1, rtc_decoder_->GetVDAErrorCounterForTesting());
+
+ // Decoder resets error counter after a successfull decode.
+ input_image._frameType = webrtc::kVideoFrameKey;
+ EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
+ rtc_decoder_->Decode(input_image, false, nullptr, nullptr, 10));
+ EXPECT_EQ(0, rtc_decoder_->GetVDAErrorCounterForTesting());
+}
+
+INSTANTIATE_TEST_CASE_P(CodecProfiles,
+ RTCVideoDecoderTest,
+ Values(webrtc::kVideoCodecVP8,
+ webrtc::kVideoCodecH264));
+
} // content
diff --git a/chromium/content/renderer/media/rtc_video_encoder.cc b/chromium/content/renderer/media/rtc_video_encoder.cc
index c9406f1bfc9..3b8bf254164 100644
--- a/chromium/content/renderer/media/rtc_video_encoder.cc
+++ b/chromium/content/renderer/media/rtc_video_encoder.cc
@@ -200,7 +200,7 @@ class RTCVideoEncoder::Impl
int32_t* async_retval_;
// The underlying VEA to perform encoding on.
- scoped_ptr<media::VideoEncodeAccelerator> video_encoder_;
+ std::unique_ptr<media::VideoEncodeAccelerator> video_encoder_;
// Next input frame. Since there is at most one next frame, a single-element
// queue is sufficient.
@@ -365,7 +365,7 @@ void RTCVideoEncoder::Impl::RequireBitstreamBuffers(
input_frame_coded_size_ = input_coded_size;
for (unsigned int i = 0; i < input_count + kInputBufferExtraCount; ++i) {
- scoped_ptr<base::SharedMemory> shm =
+ std::unique_ptr<base::SharedMemory> shm =
gpu_factories_->CreateSharedMemory(media::VideoFrame::AllocationSize(
media::PIXEL_FORMAT_I420, input_coded_size));
if (!shm) {
@@ -378,7 +378,7 @@ void RTCVideoEncoder::Impl::RequireBitstreamBuffers(
}
for (int i = 0; i < kOutputBufferCount; ++i) {
- scoped_ptr<base::SharedMemory> shm =
+ std::unique_ptr<base::SharedMemory> shm =
gpu_factories_->CreateSharedMemory(output_buffer_size);
if (!shm) {
LogAndNotifyError(FROM_HERE, "failed to create output buffer",
@@ -429,9 +429,8 @@ void RTCVideoEncoder::Impl::BitstreamBufferReady(int32_t bitstream_buffer_id,
const uint32_t rtp_timestamp =
static_cast<uint32_t>(capture_time_us * 90 / 1000);
- scoped_ptr<webrtc::EncodedImage> image(new webrtc::EncodedImage(
- reinterpret_cast<uint8_t*>(output_buffer->memory()),
- payload_size,
+ std::unique_ptr<webrtc::EncodedImage> image(new webrtc::EncodedImage(
+ reinterpret_cast<uint8_t*>(output_buffer->memory()), payload_size,
output_buffer->mapped_size()));
image->_encodedWidth = input_visible_size_.width();
image->_encodedHeight = input_visible_size_.height();
@@ -732,9 +731,10 @@ int32_t RTCVideoEncoder::SetRates(uint32_t new_bit_rate, uint32_t frame_rate) {
return WEBRTC_VIDEO_CODEC_OK;
}
-void RTCVideoEncoder::ReturnEncodedImage(scoped_ptr<webrtc::EncodedImage> image,
- int32_t bitstream_buffer_id,
- uint16_t picture_id) {
+void RTCVideoEncoder::ReturnEncodedImage(
+ std::unique_ptr<webrtc::EncodedImage> image,
+ int32_t bitstream_buffer_id,
+ uint16_t picture_id) {
DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(3) << "ReturnEncodedImage(): "
<< "bitstream_buffer_id=" << bitstream_buffer_id
diff --git a/chromium/content/renderer/media/rtc_video_encoder.h b/chromium/content/renderer/media/rtc_video_encoder.h
index 4997ad298b0..d0cd43a8691 100644
--- a/chromium/content/renderer/media/rtc_video_encoder.h
+++ b/chromium/content/renderer/media/rtc_video_encoder.h
@@ -8,11 +8,11 @@
#include <stddef.h>
#include <stdint.h>
+#include <memory>
#include <vector>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
@@ -65,7 +65,7 @@ class CONTENT_EXPORT RTCVideoEncoder
friend class RTCVideoEncoder::Impl;
// Return an encoded output buffer to WebRTC.
- void ReturnEncodedImage(scoped_ptr<webrtc::EncodedImage> image,
+ void ReturnEncodedImage(std::unique_ptr<webrtc::EncodedImage> image,
int32_t bitstream_buffer_id,
uint16_t picture_id);
diff --git a/chromium/content/renderer/media/rtc_video_encoder_factory.cc b/chromium/content/renderer/media/rtc_video_encoder_factory.cc
index d9fc4eef6dc..194a236fb5b 100644
--- a/chromium/content/renderer/media/rtc_video_encoder_factory.cc
+++ b/chromium/content/renderer/media/rtc_video_encoder_factory.cc
@@ -5,9 +5,9 @@
#include "content/renderer/media/rtc_video_encoder_factory.h"
#include "base/command_line.h"
-#include "content/common/gpu/client/gpu_video_encode_accelerator_host.h"
#include "content/public/common/content_switches.h"
#include "content/renderer/media/rtc_video_encoder.h"
+#include "media/gpu/ipc/client/gpu_video_encode_accelerator_host.h"
#include "media/renderers/gpu_video_accelerator_factories.h"
#include "media/video/video_encode_accelerator.h"
diff --git a/chromium/content/renderer/media/rtc_video_encoder_factory.h b/chromium/content/renderer/media/rtc_video_encoder_factory.h
index a4abe6f206d..45b48ca82e1 100644
--- a/chromium/content/renderer/media/rtc_video_encoder_factory.h
+++ b/chromium/content/renderer/media/rtc_video_encoder_factory.h
@@ -11,7 +11,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
-#include "third_party/libjingle/source/talk/media/webrtc/webrtcvideoencoderfactory.h"
+#include "third_party/webrtc/media/engine/webrtcvideoencoderfactory.h"
namespace media {
class GpuVideoAcceleratorFactories;
diff --git a/chromium/content/renderer/media/speech_recognition_audio_sink.cc b/chromium/content/renderer/media/speech_recognition_audio_sink.cc
index 1035aff13da..ecac9d55357 100644
--- a/chromium/content/renderer/media/speech_recognition_audio_sink.cc
+++ b/chromium/content/renderer/media/speech_recognition_audio_sink.cc
@@ -20,7 +20,7 @@ SpeechRecognitionAudioSink::SpeechRecognitionAudioSink(
const blink::WebMediaStreamTrack& track,
const media::AudioParameters& params,
const base::SharedMemoryHandle memory,
- scoped_ptr<base::SyncSocket> socket,
+ std::unique_ptr<base::SyncSocket> socket,
const OnStoppedCB& on_stopped_cb)
: track_(track),
shared_memory_(memory, false),
@@ -61,11 +61,8 @@ SpeechRecognitionAudioSink::~SpeechRecognitionAudioSink() {
// static
bool SpeechRecognitionAudioSink::IsSupportedTrack(
const blink::WebMediaStreamTrack& track) {
- if (track.source().type() != blink::WebMediaStreamSource::TypeAudio)
- return false;
-
MediaStreamAudioSource* native_source =
- static_cast<MediaStreamAudioSource*>(track.source().extraData());
+ MediaStreamAudioSource::From(track.source());
if (!native_source)
return false;
diff --git a/chromium/content/renderer/media/speech_recognition_audio_sink.h b/chromium/content/renderer/media/speech_recognition_audio_sink.h
index c70420f7135..2a281310575 100644
--- a/chromium/content/renderer/media/speech_recognition_audio_sink.h
+++ b/chromium/content/renderer/media/speech_recognition_audio_sink.h
@@ -7,9 +7,10 @@
#include <stdint.h>
+#include <memory>
+
#include "base/callback.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/shared_memory.h"
#include "base/sync_socket.h"
#include "base/threading/thread_checker.h"
@@ -42,7 +43,7 @@ class CONTENT_EXPORT SpeechRecognitionAudioSink
SpeechRecognitionAudioSink(const blink::WebMediaStreamTrack& track,
const media::AudioParameters& params,
const base::SharedMemoryHandle memory,
- scoped_ptr<base::SyncSocket> socket,
+ std::unique_ptr<base::SyncSocket> socket,
const OnStoppedCB& on_stopped_cb);
~SpeechRecognitionAudioSink() override;
@@ -85,16 +86,16 @@ class CONTENT_EXPORT SpeechRecognitionAudioSink
// Socket for synchronization of audio bus reads/writes.
// Created on the renderer client and passed here. Accessed on capture thread.
- scoped_ptr<base::SyncSocket> socket_;
+ std::unique_ptr<base::SyncSocket> socket_;
// Used as a resampler to deliver appropriate format to speech recognition.
- scoped_ptr<media::AudioConverter> audio_converter_;
+ std::unique_ptr<media::AudioConverter> audio_converter_;
// FIFO is used for queuing audio frames before we resample.
- scoped_ptr<media::AudioFifo> fifo_;
+ std::unique_ptr<media::AudioFifo> fifo_;
// Audio bus shared with the browser process via |shared_memory_|.
- scoped_ptr<media::AudioBus> output_bus_;
+ std::unique_ptr<media::AudioBus> output_bus_;
// Params of the source audio. Can change when |OnSetFormat()| occurs.
media::AudioParameters input_params_;
diff --git a/chromium/content/renderer/media/speech_recognition_audio_sink_unittest.cc b/chromium/content/renderer/media/speech_recognition_audio_sink_unittest.cc
index 64ee4348f10..49890b5158a 100644
--- a/chromium/content/renderer/media/speech_recognition_audio_sink_unittest.cc
+++ b/chromium/content/renderer/media/speech_recognition_audio_sink_unittest.cc
@@ -13,7 +13,6 @@
#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
#include "content/renderer/media/media_stream_audio_source.h"
-#include "content/renderer/media/mock_media_constraint_factory.h"
#include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
#include "content/renderer/media/webrtc_local_audio_track.h"
#include "media/audio/audio_parameters.h"
@@ -188,15 +187,15 @@ class FakeSpeechRecognizer {
bool is_responsive_;
// Shared memory for the audio and synchronization.
- scoped_ptr<base::SharedMemory> shared_memory_;
+ std::unique_ptr<base::SharedMemory> shared_memory_;
// Fake sockets and their shared buffer.
- scoped_ptr<MockSyncSocket::SharedBuffer> shared_buffer_;
- scoped_ptr<MockSyncSocket> receiving_socket_;
+ std::unique_ptr<MockSyncSocket::SharedBuffer> shared_buffer_;
+ std::unique_ptr<MockSyncSocket> receiving_socket_;
MockSyncSocket* sending_socket_;
// Audio bus wrapping the shared memory from the renderer.
- scoped_ptr<media::AudioBus> audio_track_bus_;
+ std::unique_ptr<media::AudioBus> audio_track_bus_;
DISALLOW_COPY_AND_ASSIGN(FakeSpeechRecognizer);
};
@@ -244,7 +243,7 @@ class SpeechRecognitionAudioSinkTest : public testing::Test {
// Get the native track from the blink track and initialize.
native_track_ =
- static_cast<WebRtcLocalAudioTrack*>(blink_track.extraData());
+ static_cast<WebRtcLocalAudioTrack*>(blink_track.getExtraData());
native_track_->OnSetFormat(source_params_);
// Create and initialize the consumer.
@@ -253,7 +252,8 @@ class SpeechRecognitionAudioSinkTest : public testing::Test {
recognizer_->Initialize(blink_track, sink_params_, &foreign_memory_handle);
// Create the producer.
- scoped_ptr<base::SyncSocket> sending_socket(recognizer_->sending_socket());
+ std::unique_ptr<base::SyncSocket> sending_socket(
+ recognizer_->sending_socket());
speech_audio_sink_.reset(new SpeechRecognitionAudioSink(
blink_track, sink_params_, foreign_memory_handle,
std::move(sending_socket),
@@ -275,26 +275,19 @@ class SpeechRecognitionAudioSinkTest : public testing::Test {
static void PrepareBlinkTrackOfType(
const MediaStreamType device_type,
blink::WebMediaStreamTrack* blink_track) {
- StreamDeviceInfo device_info(device_type, "Mock device",
- "mock_device_id");
- MockMediaConstraintFactory constraint_factory;
- const blink::WebMediaConstraints constraints =
- constraint_factory.CreateWebMediaConstraints();
- scoped_refptr<WebRtcAudioCapturer> capturer(
- WebRtcAudioCapturer::CreateCapturer(-1, device_info, constraints, NULL,
- NULL));
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
- scoped_ptr<WebRtcLocalAudioTrack> native_track(
- new WebRtcLocalAudioTrack(adapter.get(), capturer, NULL));
+ std::unique_ptr<WebRtcLocalAudioTrack> native_track(
+ new WebRtcLocalAudioTrack(adapter.get()));
blink::WebMediaStreamSource blink_audio_source;
blink_audio_source.initialize(base::UTF8ToUTF16("dummy_source_id"),
blink::WebMediaStreamSource::TypeAudio,
base::UTF8ToUTF16("dummy_source_name"),
false /* remote */, true /* readonly */);
MediaStreamSource::SourceStoppedCallback cb;
- blink_audio_source.setExtraData(
- new MediaStreamAudioSource(-1, device_info, cb, NULL));
+ blink_audio_source.setExtraData(new MediaStreamAudioSource(
+ -1, StreamDeviceInfo(device_type, "Mock device", "mock_device_id"), cb,
+ nullptr));
blink_track->initialize(blink::WebString::fromUTF8("dummy_track"),
blink_audio_source);
blink_track->setExtraData(native_track.release());
@@ -306,7 +299,7 @@ class SpeechRecognitionAudioSinkTest : public testing::Test {
const base::TimeTicks estimated_capture_time = first_frame_capture_time_ +
(sample_frames_captured_ * base::TimeDelta::FromSeconds(1) /
source_params_.sample_rate());
- native_track()->Capture(*source_bus_, estimated_capture_time, false);
+ native_track()->Capture(*source_bus_, estimated_capture_time);
sample_frames_captured_ += source_bus_->frames();
}
}
@@ -364,13 +357,13 @@ class SpeechRecognitionAudioSinkTest : public testing::Test {
private:
// Producer.
- scoped_ptr<SpeechRecognitionAudioSink> speech_audio_sink_;
+ std::unique_ptr<SpeechRecognitionAudioSink> speech_audio_sink_;
// Consumer.
- scoped_ptr<FakeSpeechRecognizer> recognizer_;
+ std::unique_ptr<FakeSpeechRecognizer> recognizer_;
// Audio related members.
- scoped_ptr<media::AudioBus> source_bus_;
+ std::unique_ptr<media::AudioBus> source_bus_;
media::AudioParameters source_params_;
media::AudioParameters sink_params_;
WebRtcLocalAudioTrack* native_track_;
diff --git a/chromium/content/renderer/media/track_audio_renderer.cc b/chromium/content/renderer/media/track_audio_renderer.cc
new file mode 100644
index 00000000000..07491289cd9
--- /dev/null
+++ b/chromium/content/renderer/media/track_audio_renderer.cc
@@ -0,0 +1,390 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/track_audio_renderer.h"
+
+#include "base/location.h"
+#include "base/logging.h"
+#include "base/metrics/histogram.h"
+#include "base/synchronization/lock.h"
+#include "base/thread_task_runner_handle.h"
+#include "base/trace_event/trace_event.h"
+#include "content/renderer/media/audio_device_factory.h"
+#include "content/renderer/media/media_stream_audio_track.h"
+#include "content/renderer/media/webrtc_audio_renderer.h"
+#include "media/base/audio_bus.h"
+#include "media/base/audio_shifter.h"
+
+namespace content {
+
+namespace {
+
+enum LocalRendererSinkStates {
+ kSinkStarted = 0,
+ kSinkNeverStarted,
+ kSinkStatesMax // Must always be last!
+};
+
+// Translates |num_samples_rendered| into a TimeDelta duration and adds it to
+// |prior_elapsed_render_time|.
+base::TimeDelta ComputeTotalElapsedRenderTime(
+ base::TimeDelta prior_elapsed_render_time,
+ int64_t num_samples_rendered,
+ int sample_rate) {
+ return prior_elapsed_render_time + base::TimeDelta::FromMicroseconds(
+ num_samples_rendered * base::Time::kMicrosecondsPerSecond / sample_rate);
+}
+
+} // namespace
+
+// media::AudioRendererSink::RenderCallback implementation
+int TrackAudioRenderer::Render(media::AudioBus* audio_bus,
+ uint32_t frames_delayed,
+ uint32_t frames_skipped) {
+ TRACE_EVENT0("audio", "TrackAudioRenderer::Render");
+ base::AutoLock auto_lock(thread_lock_);
+
+ if (!audio_shifter_) {
+ audio_bus->Zero();
+ return 0;
+ }
+
+ // Source sample rate equals to output one, see MaybeStartSink(), so using it.
+ uint32_t audio_delay_milliseconds = static_cast<double>(frames_delayed) *
+ base::Time::kMillisecondsPerSecond /
+ source_params_.sample_rate();
+
+ // TODO(miu): Plumbing is needed to determine the actual playout timestamp
+ // of the audio, instead of just snapshotting TimeTicks::Now(), for proper
+ // audio/video sync. http://crbug.com/335335
+ const base::TimeTicks playout_time =
+ base::TimeTicks::Now() +
+ base::TimeDelta::FromMilliseconds(audio_delay_milliseconds);
+ DVLOG(2) << "Pulling audio out of shifter to be played "
+ << audio_delay_milliseconds << " ms from now.";
+ audio_shifter_->Pull(audio_bus, playout_time);
+ num_samples_rendered_ += audio_bus->frames();
+ return audio_bus->frames();
+}
+
+void TrackAudioRenderer::OnRenderError() {
+ NOTIMPLEMENTED();
+}
+
+// content::MediaStreamAudioSink implementation
+void TrackAudioRenderer::OnData(const media::AudioBus& audio_bus,
+ base::TimeTicks reference_time) {
+ DCHECK(audio_thread_checker_.CalledOnValidThread());
+ DCHECK(!reference_time.is_null());
+
+ TRACE_EVENT0("audio", "TrackAudioRenderer::CaptureData");
+
+ base::AutoLock auto_lock(thread_lock_);
+ if (!audio_shifter_)
+ return;
+
+ std::unique_ptr<media::AudioBus> audio_data(
+ media::AudioBus::Create(audio_bus.channels(), audio_bus.frames()));
+ audio_bus.CopyTo(audio_data.get());
+ // Note: For remote audio sources, |reference_time| is the local playout time,
+ // the ideal point-in-time at which the first audio sample should be played
+ // out in the future. For local sources, |reference_time| is the
+ // point-in-time at which the first audio sample was captured in the past. In
+ // either case, AudioShifter will auto-detect and do the right thing when
+ // audio is pulled from it.
+ audio_shifter_->Push(std::move(audio_data), reference_time);
+}
+
+void TrackAudioRenderer::OnSetFormat(const media::AudioParameters& params) {
+ DVLOG(1) << "TrackAudioRenderer::OnSetFormat()";
+ // If the source is restarted, we might have changed to another capture
+ // thread.
+ audio_thread_checker_.DetachFromThread();
+ DCHECK(audio_thread_checker_.CalledOnValidThread());
+
+ // If the parameters changed, the audio in the AudioShifter is invalid and
+ // should be dropped.
+ {
+ base::AutoLock auto_lock(thread_lock_);
+ if (audio_shifter_ &&
+ (audio_shifter_->sample_rate() != params.sample_rate() ||
+ audio_shifter_->channels() != params.channels())) {
+ HaltAudioFlowWhileLockHeld();
+ }
+ }
+
+ // Post a task on the main render thread to reconfigure the |sink_| with the
+ // new format.
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&TrackAudioRenderer::ReconfigureSink, this, params));
+}
+
+TrackAudioRenderer::TrackAudioRenderer(
+ const blink::WebMediaStreamTrack& audio_track,
+ int playout_render_frame_id,
+ int session_id,
+ const std::string& device_id,
+ const url::Origin& security_origin)
+ : audio_track_(audio_track),
+ playout_render_frame_id_(playout_render_frame_id),
+ session_id_(session_id),
+ task_runner_(base::ThreadTaskRunnerHandle::Get()),
+ num_samples_rendered_(0),
+ playing_(false),
+ output_device_id_(device_id),
+ security_origin_(security_origin),
+ volume_(0.0),
+ sink_started_(false) {
+ DCHECK(MediaStreamAudioTrack::From(audio_track_));
+ DVLOG(1) << "TrackAudioRenderer::TrackAudioRenderer()";
+}
+
+TrackAudioRenderer::~TrackAudioRenderer() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK(!sink_);
+ DVLOG(1) << "TrackAudioRenderer::~TrackAudioRenderer()";
+}
+
+void TrackAudioRenderer::Start() {
+ DVLOG(1) << "TrackAudioRenderer::Start()";
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ DCHECK_EQ(playing_, false);
+
+ // We get audio data from |audio_track_|...
+ MediaStreamAudioSink::AddToAudioTrack(this, audio_track_);
+ // ...and |sink_| will get audio data from us.
+ DCHECK(!sink_);
+ sink_ = AudioDeviceFactory::NewAudioRendererSink(
+ AudioDeviceFactory::kSourceNonRtcAudioTrack, playout_render_frame_id_,
+ session_id_, output_device_id_, security_origin_);
+
+ base::AutoLock auto_lock(thread_lock_);
+ prior_elapsed_render_time_ = base::TimeDelta();
+ num_samples_rendered_ = 0;
+}
+
+void TrackAudioRenderer::Stop() {
+ DVLOG(1) << "TrackAudioRenderer::Stop()";
+ DCHECK(task_runner_->BelongsToCurrentThread());
+
+ Pause();
+
+ // Stop the output audio stream, i.e, stop asking for data to render.
+ // It is safer to call Stop() on the |sink_| to clean up the resources even
+ // when the |sink_| is never started.
+ if (sink_) {
+ sink_->Stop();
+ sink_ = NULL;
+ }
+
+ if (!sink_started_ && IsLocalRenderer()) {
+ UMA_HISTOGRAM_ENUMERATION("Media.LocalRendererSinkStates",
+ kSinkNeverStarted, kSinkStatesMax);
+ }
+ sink_started_ = false;
+
+ // Ensure that the capturer stops feeding us with captured audio.
+ MediaStreamAudioSink::RemoveFromAudioTrack(this, audio_track_);
+}
+
+void TrackAudioRenderer::Play() {
+ DVLOG(1) << "TrackAudioRenderer::Play()";
+ DCHECK(task_runner_->BelongsToCurrentThread());
+
+ if (!sink_)
+ return;
+
+ playing_ = true;
+
+ MaybeStartSink();
+}
+
+void TrackAudioRenderer::Pause() {
+ DVLOG(1) << "TrackAudioRenderer::Pause()";
+ DCHECK(task_runner_->BelongsToCurrentThread());
+
+ if (!sink_)
+ return;
+
+ playing_ = false;
+
+ base::AutoLock auto_lock(thread_lock_);
+ HaltAudioFlowWhileLockHeld();
+}
+
+void TrackAudioRenderer::SetVolume(float volume) {
+ DVLOG(1) << "TrackAudioRenderer::SetVolume(" << volume << ")";
+ DCHECK(task_runner_->BelongsToCurrentThread());
+
+ // Cache the volume. Whenever |sink_| is re-created, call SetVolume() with
+ // this cached volume.
+ volume_ = volume;
+ if (sink_)
+ sink_->SetVolume(volume);
+}
+
+media::OutputDeviceInfo TrackAudioRenderer::GetOutputDeviceInfo() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ return sink_ ? sink_->GetOutputDeviceInfo() : media::OutputDeviceInfo();
+}
+
+base::TimeDelta TrackAudioRenderer::GetCurrentRenderTime() const {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ base::AutoLock auto_lock(thread_lock_);
+ if (source_params_.IsValid()) {
+ return ComputeTotalElapsedRenderTime(prior_elapsed_render_time_,
+ num_samples_rendered_,
+ source_params_.sample_rate());
+ }
+ return prior_elapsed_render_time_;
+}
+
+bool TrackAudioRenderer::IsLocalRenderer() const {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ return MediaStreamAudioTrack::From(audio_track_)->is_local_track();
+}
+
+void TrackAudioRenderer::SwitchOutputDevice(
+ const std::string& device_id,
+ const url::Origin& security_origin,
+ const media::OutputDeviceStatusCB& callback) {
+ DVLOG(1) << "TrackAudioRenderer::SwitchOutputDevice()";
+ DCHECK(task_runner_->BelongsToCurrentThread());
+
+ {
+ base::AutoLock auto_lock(thread_lock_);
+ HaltAudioFlowWhileLockHeld();
+ }
+
+ scoped_refptr<media::AudioRendererSink> new_sink =
+ AudioDeviceFactory::NewAudioRendererSink(
+ AudioDeviceFactory::kSourceNonRtcAudioTrack, playout_render_frame_id_,
+ session_id_, device_id, security_origin);
+
+ media::OutputDeviceStatus new_sink_status =
+ new_sink->GetOutputDeviceInfo().device_status();
+ if (new_sink_status != media::OUTPUT_DEVICE_STATUS_OK) {
+ callback.Run(new_sink_status);
+ return;
+ }
+
+ output_device_id_ = device_id;
+ security_origin_ = security_origin;
+ bool was_sink_started = sink_started_;
+
+ if (sink_)
+ sink_->Stop();
+
+ sink_started_ = false;
+ sink_ = new_sink;
+ if (was_sink_started)
+ MaybeStartSink();
+
+ callback.Run(media::OUTPUT_DEVICE_STATUS_OK);
+}
+
+void TrackAudioRenderer::MaybeStartSink() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+ DVLOG(1) << "TrackAudioRenderer::MaybeStartSink()";
+
+ if (!sink_ || !source_params_.IsValid() || !playing_)
+ return;
+
+ // Re-create the AudioShifter to drop old audio data and reset to a starting
+ // state. MaybeStartSink() is always called in a situation where either the
+ // source or sink has changed somehow and so all of AudioShifter's internal
+ // time-sync state is invalid.
+ CreateAudioShifter();
+
+ if (sink_started_)
+ return;
+
+ const media::OutputDeviceInfo& device_info = sink_->GetOutputDeviceInfo();
+ if (device_info.device_status() != media::OUTPUT_DEVICE_STATUS_OK)
+ return;
+
+ // Output parameters consist of the same channel layout and sample rate as the
+ // source, but having the buffer duration preferred by the hardware.
+ const media::AudioParameters& hardware_params = device_info.output_params();
+ media::AudioParameters sink_params(
+ hardware_params.format(), source_params_.channel_layout(),
+ source_params_.sample_rate(), source_params_.bits_per_sample(),
+ WebRtcAudioRenderer::GetOptimalBufferSize(
+ source_params_.sample_rate(), hardware_params.frames_per_buffer()));
+ DVLOG(1) << ("TrackAudioRenderer::MaybeStartSink() -- Starting sink. "
+ "source_params_={")
+ << source_params_.AsHumanReadableString() << "}, hardware_params_={"
+ << hardware_params.AsHumanReadableString() << "}, sink parameters={"
+ << sink_params.AsHumanReadableString() << '}';
+ sink_->Initialize(sink_params, this);
+ sink_->Start();
+ sink_->SetVolume(volume_);
+ sink_->Play(); // Not all the sinks play on start.
+ sink_started_ = true;
+ if (IsLocalRenderer()) {
+ UMA_HISTOGRAM_ENUMERATION("Media.LocalRendererSinkStates", kSinkStarted,
+ kSinkStatesMax);
+ }
+}
+
+void TrackAudioRenderer::ReconfigureSink(const media::AudioParameters& params) {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+
+ DVLOG(1) << "TrackAudioRenderer::ReconfigureSink()";
+
+ if (source_params_.Equals(params))
+ return;
+ source_params_ = params;
+
+ if (!sink_)
+ return; // TrackAudioRenderer has not yet been started.
+
+ // Stop |sink_| and re-create a new one to be initialized with different audio
+ // parameters. Then, invoke MaybeStartSink() to restart everything again.
+ sink_->Stop();
+ sink_started_ = false;
+ sink_ = AudioDeviceFactory::NewAudioRendererSink(
+ AudioDeviceFactory::kSourceNonRtcAudioTrack, playout_render_frame_id_,
+ session_id_, output_device_id_, security_origin_);
+ MaybeStartSink();
+}
+
+void TrackAudioRenderer::CreateAudioShifter() {
+ DCHECK(task_runner_->BelongsToCurrentThread());
+
+ // Note 1: The max buffer is fairly large to cover the case where
+ // remotely-sourced audio is delivered well ahead of its scheduled playout
+ // time (e.g., content streaming with a very large end-to-end
+ // latency). However, there is no penalty for making it large in the
+ // low-latency use cases since AudioShifter will discard data as soon as it is
+ // no longer needed.
+ //
+ // Note 2: The clock accuracy is set to 20ms because clock accuracy is
+ // ~15ms on Windows machines without a working high-resolution clock. See
+ // comments in base/time/time.h for details.
+ media::AudioShifter* const new_shifter = new media::AudioShifter(
+ base::TimeDelta::FromSeconds(5), base::TimeDelta::FromMilliseconds(20),
+ base::TimeDelta::FromSeconds(20), source_params_.sample_rate(),
+ source_params_.channels());
+
+ base::AutoLock auto_lock(thread_lock_);
+ audio_shifter_.reset(new_shifter);
+}
+
+void TrackAudioRenderer::HaltAudioFlowWhileLockHeld() {
+ thread_lock_.AssertAcquired();
+
+ audio_shifter_.reset();
+
+ if (source_params_.IsValid()) {
+ prior_elapsed_render_time_ =
+ ComputeTotalElapsedRenderTime(prior_elapsed_render_time_,
+ num_samples_rendered_,
+ source_params_.sample_rate());
+ num_samples_rendered_ = 0;
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/media/track_audio_renderer.h b/chromium/content/renderer/media/track_audio_renderer.h
new file mode 100644
index 00000000000..43c0d7fa71b
--- /dev/null
+++ b/chromium/content/renderer/media/track_audio_renderer.h
@@ -0,0 +1,182 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MEDIA_TRACK_AUDIO_RENDERER_H_
+#define CONTENT_RENDERER_MEDIA_TRACK_AUDIO_RENDERER_H_
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/single_thread_task_runner.h"
+#include "base/synchronization/lock.h"
+#include "base/threading/thread_checker.h"
+#include "content/common/content_export.h"
+#include "content/public/renderer/media_stream_audio_renderer.h"
+#include "content/public/renderer/media_stream_audio_sink.h"
+#include "media/base/audio_renderer_sink.h"
+#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
+
+namespace media {
+class AudioBus;
+class AudioShifter;
+class AudioParameters;
+}
+
+namespace content {
+
+// TrackAudioRenderer is a MediaStreamAudioRenderer for plumbing audio data
+// generated from either local or remote (but not PeerConnection/WebRTC-sourced)
+// MediaStreamAudioTracks to an audio output device, reconciling differences in
+// the rates of production and consumption of the audio data. Note that remote
+// PeerConnection-sourced tracks are NOT rendered by this implementation (see
+// MediaStreamRendererFactoryImpl).
+//
+// This class uses AudioDeviceFactory to create media::AudioRendererSink and
+// owns/manages their lifecycles. Output devices are automatically re-created
+// in response to audio format changes, or use of the SwitchOutputDevice() API
+// by client code.
+//
+// Audio data is feed-in from the source via calls to OnData(). The
+// internally-owned media::AudioOutputDevice calls Render() to pull-out that
+// audio data. However, because of clock differences and other environmental
+// factors, the audio will inevitably feed-in at a rate different from the rate
+// it is being rendered-out. media::AudioShifter is used to buffer, stretch
+// and skip audio to maintain time synchronization between the producer and
+// consumer.
+class CONTENT_EXPORT TrackAudioRenderer
+ : NON_EXPORTED_BASE(public MediaStreamAudioRenderer),
+ NON_EXPORTED_BASE(public MediaStreamAudioSink),
+ NON_EXPORTED_BASE(public media::AudioRendererSink::RenderCallback) {
+ public:
+ // Creates a renderer for the given |audio_track|. |playout_render_frame_id|
+ // refers to the RenderFrame that owns this instance (e.g., it contains the
+ // DOM widget representing the player). |session_id| and |device_id| are
+ // optional, and are used to direct audio output to a pre-selected device;
+ // otherwise, audio is output to the default device for the system.
+ //
+ // Called on the main thread.
+ TrackAudioRenderer(const blink::WebMediaStreamTrack& audio_track,
+ int playout_render_frame_id,
+ int session_id,
+ const std::string& device_id,
+ const url::Origin& security_origin);
+
+ // MediaStreamAudioRenderer implementation.
+ // Called on the main thread.
+ void Start() override;
+ void Stop() override;
+ void Play() override;
+ void Pause() override;
+ void SetVolume(float volume) override;
+ media::OutputDeviceInfo GetOutputDeviceInfo() override;
+ base::TimeDelta GetCurrentRenderTime() const override;
+ bool IsLocalRenderer() const override;
+ void SwitchOutputDevice(const std::string& device_id,
+ const url::Origin& security_origin,
+ const media::OutputDeviceStatusCB& callback) override;
+
+ protected:
+ ~TrackAudioRenderer() override;
+
+ private:
+ // MediaStreamAudioSink implementation.
+
+ // Called on the AudioInputDevice worker thread.
+ void OnData(const media::AudioBus& audio_bus,
+ base::TimeTicks reference_time) override;
+
+ // Called on the AudioInputDevice worker thread.
+ void OnSetFormat(const media::AudioParameters& params) override;
+
+ // media::AudioRendererSink::RenderCallback implementation.
+ // Render() is called on the AudioOutputDevice thread and OnRenderError()
+ // on the IO thread.
+ int Render(media::AudioBus* audio_bus,
+ uint32_t frames_delayed,
+ uint32_t frames_skipped) override;
+ void OnRenderError() override;
+
+ // Initializes and starts the |sink_| if
+ // we have received valid |source_params_| &&
+ // |playing_| has been set to true.
+ void MaybeStartSink();
+
+ // Sets new |source_params_| and then re-initializes and restarts |sink_|.
+ void ReconfigureSink(const media::AudioParameters& params);
+
+ // Creates a new AudioShifter, destroying the old one (if any). This is
+ // called any time playback is started/stopped, or the sink changes.
+ void CreateAudioShifter();
+
+ // Called when either the source or sink has changed somehow, or audio has
+ // been paused. Drops the AudioShifter and updates
+ // |prior_elapsed_render_time_|. May be called from either the main thread or
+ // the audio thread. Assumption: |thread_lock_| is already acquired.
+ void HaltAudioFlowWhileLockHeld();
+
+ // The audio track which provides access to the source data to render.
+ //
+ // This class is calling MediaStreamAudioSink::AddToAudioTrack() and
+ // MediaStreamAudioSink::RemoveFromAudioTrack() to connect and disconnect
+ // with the audio track.
+ blink::WebMediaStreamTrack audio_track_;
+
+ // The render view and frame in which the audio is rendered into |sink_|.
+ const int playout_render_frame_id_;
+ const int session_id_;
+
+ // MessageLoop associated with the single thread that performs all control
+ // tasks. Set to the MessageLoop that invoked the ctor.
+ const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+
+ // The sink (destination) for rendered audio.
+ scoped_refptr<media::AudioRendererSink> sink_;
+
+ // This does all the synchronization/resampling/smoothing.
+ std::unique_ptr<media::AudioShifter> audio_shifter_;
+
+ // These track the time duration of all the audio rendered so far by this
+ // instance. |prior_elapsed_render_time_| tracks the time duration of all
+ // audio rendered before the last format change. |num_samples_rendered_|
+ // tracks the number of audio samples rendered since the last format change.
+ base::TimeDelta prior_elapsed_render_time_;
+ int64_t num_samples_rendered_;
+
+ // The audio parameters of the track's source.
+ // Must only be touched on the main thread.
+ media::AudioParameters source_params_;
+
+ // Set when playing, cleared when paused.
+ bool playing_;
+
+ // Protects |audio_shifter_|, |prior_elapsed_render_time_|, and
+ // |num_samples_rendered_|.
+ mutable base::Lock thread_lock_;
+
+ // The preferred device id of the output device or empty for the default
+ // output device.
+ std::string output_device_id_;
+ url::Origin security_origin_;
+
+ // Cache value for the volume. Whenever |sink_| is re-created, its volume
+ // should be set to this.
+ float volume_;
+
+ // Flag to indicate whether |sink_| has been started yet.
+ bool sink_started_;
+
+ // Used to DCHECK that some methods are called on the audio thread.
+ base::ThreadChecker audio_thread_checker_;
+
+ DISALLOW_COPY_AND_ASSIGN(TrackAudioRenderer);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MEDIA_TRACK_AUDIO_RENDERER_H_
diff --git a/chromium/content/renderer/media/user_media_client_impl.cc b/chromium/content/renderer/media/user_media_client_impl.cc
index 15153c113eb..62dca219828 100644
--- a/chromium/content/renderer/media/user_media_client_impl.cc
+++ b/chromium/content/renderer/media/user_media_client_impl.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include <utility>
+#include <vector>
#include "base/hash.h"
#include "base/location.h"
@@ -20,6 +21,7 @@
#include "content/public/renderer/render_frame.h"
#include "content/renderer/media/media_stream.h"
#include "content/renderer/media/media_stream_audio_source.h"
+#include "content/renderer/media/media_stream_constraints_util.h"
#include "content/renderer/media/media_stream_dispatcher.h"
#include "content/renderer/media/media_stream_video_capturer_source.h"
#include "content/renderer/media/media_stream_video_track.h"
@@ -29,6 +31,7 @@
#include "content/renderer/media/webrtc_logging.h"
#include "content/renderer/media/webrtc_uma_histograms.h"
#include "content/renderer/render_thread_impl.h"
+#include "third_party/WebKit/public/platform/URLConversion.h"
#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
#include "third_party/WebKit/public/platform/WebMediaDeviceInfo.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
@@ -39,60 +42,17 @@
namespace content {
namespace {
-bool GetMandatory(const blink::WebMediaConstraints& constraints,
- const std::string& name,
- std::string* value) {
- if (constraints.isNull())
- return false;
- blink::WebString temp;
- bool found =
- constraints.getMandatoryConstraintValue(base::UTF8ToUTF16(name), temp);
- if (found)
- *value = temp.utf8();
- return found;
-}
-
-void GetMandatoryList(const blink::WebMediaConstraints& constraints,
- const std::string& name,
- std::vector<std::string>* values) {
- if (constraints.isNull()) {
- return;
- }
- blink::WebString temp;
- bool found =
- constraints.getMandatoryConstraintValue(base::UTF8ToUTF16(name), temp);
- if (found) {
- values->push_back(temp.utf8());
+void CopyVector(const blink::WebVector<blink::WebString>& source,
+ std::vector<std::string>* destination) {
+ for (const auto& web_string : source) {
+ destination->push_back(web_string.utf8());
}
}
-bool GetOptional(const blink::WebMediaConstraints& constraints,
- const std::string& name,
- std::string* value) {
- if (constraints.isNull())
- return false;
- blink::WebString temp;
- bool found =
- constraints.getOptionalConstraintValue(base::UTF8ToUTF16(name), temp);
- if (found)
- *value = temp.utf8();
- return found;
-}
-
-void GetOptionalList(const blink::WebMediaConstraints constraints,
- const std::string& name,
- std::vector<std::string>* values) {
- if (constraints.isNull()) {
- return;
- }
- blink::WebVector<blink::WebMediaConstraint> constraint_list;
- constraints.getOptionalConstraints(constraint_list);
- blink::WebString web_name = base::UTF8ToUTF16(name);
- for (const auto& pair : constraint_list) {
- if (pair.m_name == web_name) {
- values->push_back(pair.m_value.utf8());
- }
- }
+void CopyFirstString(const blink::WebVector<blink::WebString>& source,
+ std::string* destination) {
+ if (!source.isEmpty())
+ *destination = source[0].utf8();
}
void CopyBlinkRequestToStreamControls(const blink::WebUserMediaRequest& request,
@@ -100,32 +60,47 @@ void CopyBlinkRequestToStreamControls(const blink::WebUserMediaRequest& request,
if (request.isNull()) {
return;
}
- GetMandatory(request.audioConstraints(), kMediaStreamSource,
- &controls->audio.stream_source);
- GetMandatory(request.videoConstraints(), kMediaStreamSource,
- &controls->video.stream_source);
- GetMandatoryList(request.audioConstraints(), kMediaStreamSourceInfoId,
- &controls->audio.device_ids);
- GetMandatoryList(request.videoConstraints(), kMediaStreamSourceInfoId,
- &controls->video.device_ids);
- GetOptionalList(request.audioConstraints(), kMediaStreamSourceInfoId,
- &controls->audio.alternate_device_ids);
- GetOptionalList(request.videoConstraints(), kMediaStreamSourceInfoId,
- &controls->video.alternate_device_ids);
- GetMandatoryList(request.audioConstraints(), kMediaStreamSourceId,
- &controls->audio.device_ids);
- GetMandatoryList(request.videoConstraints(), kMediaStreamSourceId,
- &controls->video.device_ids);
- std::string hotword_string;
- GetOptional(request.audioConstraints(), kMediaStreamAudioHotword,
- &hotword_string);
- if (hotword_string == "true")
- controls->hotword_enabled = true;
- // DCHECK for some combinations that seem to be unusual/useless
- // It should not be possible to have both MediaStreamSourceId
- // and MediaStreamSourceInfoId on the same request.
- DCHECK(controls->video.device_ids.size() <= 1);
- DCHECK(controls->audio.device_ids.size() <= 1);
+ if (!request.audioConstraints().isNull()) {
+ const blink::WebMediaTrackConstraintSet& audio_basic =
+ request.audioConstraints().basic();
+ CopyFirstString(audio_basic.mediaStreamSource.exact(),
+ &controls->audio.stream_source);
+ CopyVector(audio_basic.deviceId.exact(), &(controls->audio.device_ids));
+ // Optionals. They may be either in ideal or in advanced.exact.
+ CopyVector(audio_basic.deviceId.ideal(),
+ &controls->audio.alternate_device_ids);
+ for (const auto& constraint : request.audioConstraints().advanced()) {
+ CopyVector(constraint.deviceId.exact(),
+ &controls->audio.alternate_device_ids);
+ CopyVector(constraint.deviceId.ideal(),
+ &controls->audio.alternate_device_ids);
+ }
+ if (audio_basic.hotwordEnabled.hasExact()) {
+ controls->hotword_enabled = audio_basic.hotwordEnabled.exact();
+ } else {
+ for (const auto& audio_advanced : request.audioConstraints().advanced()) {
+ if (audio_advanced.hotwordEnabled.hasExact()) {
+ controls->hotword_enabled = audio_advanced.hotwordEnabled.exact();
+ break;
+ }
+ }
+ }
+ }
+ if (!request.videoConstraints().isNull()) {
+ const blink::WebMediaTrackConstraintSet& video_basic =
+ request.videoConstraints().basic();
+ CopyFirstString(video_basic.mediaStreamSource.exact(),
+ &(controls->video.stream_source));
+ CopyVector(video_basic.deviceId.exact(), &(controls->video.device_ids));
+ CopyVector(video_basic.deviceId.ideal(),
+ &(controls->video.alternate_device_ids));
+ for (const auto& constraint : request.videoConstraints().advanced()) {
+ CopyVector(constraint.deviceId.exact(),
+ &controls->video.alternate_device_ids);
+ CopyVector(constraint.deviceId.ideal(),
+ &controls->video.alternate_device_ids);
+ }
+ }
}
static int g_next_request_id = 0;
@@ -179,7 +154,7 @@ struct UserMediaClientImpl::MediaDevicesRequestInfo {
UserMediaClientImpl::UserMediaClientImpl(
RenderFrame* render_frame,
PeerConnectionDependencyFactory* dependency_factory,
- scoped_ptr<MediaStreamDispatcher> media_stream_dispatcher)
+ std::unique_ptr<MediaStreamDispatcher> media_stream_dispatcher)
: RenderFrameObserver(render_frame),
dependency_factory_(dependency_factory),
media_stream_dispatcher_(std::move(media_stream_dispatcher)),
@@ -224,20 +199,22 @@ void UserMediaClientImpl::requestUserMedia(
controls.audio.requested = true;
// Check if this input device should be used to select a matching output
// device for audio rendering.
- std::string enable;
- if (GetMandatory(user_media_request.audioConstraints(),
- kMediaStreamRenderToAssociatedSink, &enable) &&
- base::LowerCaseEqualsASCII(enable, "true")) {
- enable_automatic_output_device_selection = true;
- }
+ enable_automatic_output_device_selection = true; // On by default.
+ GetConstraintValueAsBoolean(
+ user_media_request.audioConstraints(),
+ &blink::WebMediaTrackConstraintSet::renderToAssociatedSink,
+ &enable_automatic_output_device_selection);
}
if (user_media_request.video()) {
controls.video.requested = true;
}
CopyBlinkRequestToStreamControls(user_media_request, &controls);
-
- security_origin = GURL(user_media_request.securityOrigin().toString());
- DCHECK(render_frame()->GetWebFrame() ==
+ security_origin = blink::WebStringToGURL(
+ user_media_request.getSecurityOrigin().toString());
+ // ownerDocument may be null if we are in a test.
+ // In that case, it's OK to not check frame().
+ DCHECK(user_media_request.ownerDocument().isNull() ||
+ render_frame()->GetWebFrame() ==
static_cast<blink::WebFrame*>(
user_media_request.ownerDocument().frame()));
}
@@ -249,37 +226,25 @@ void UserMediaClientImpl::requestUserMedia(
<< ", video=" << (controls.video.requested) << " ], "
<< security_origin.spec() << ")";
- blink::WebString audio_device_id;
- bool mandatory_audio = false;
+ std::string audio_device_id;
if (!user_media_request.isNull() && user_media_request.audio()) {
- mandatory_audio =
- user_media_request.audioConstraints().getMandatoryConstraintValue(
- base::UTF8ToUTF16(kMediaStreamSourceInfoId), audio_device_id);
- if (!mandatory_audio) {
- user_media_request.audioConstraints().getOptionalConstraintValue(
- base::UTF8ToUTF16(kMediaStreamSourceInfoId), audio_device_id);
- }
+ GetConstraintValueAsString(user_media_request.audioConstraints(),
+ &blink::WebMediaTrackConstraintSet::deviceId,
+ &audio_device_id);
}
- blink::WebString video_device_id;
- bool mandatory_video = false;
+ std::string video_device_id;
if (!user_media_request.isNull() && user_media_request.video()) {
- mandatory_video =
- user_media_request.videoConstraints().getMandatoryConstraintValue(
- base::UTF8ToUTF16(kMediaStreamSourceInfoId), video_device_id);
- if (!mandatory_video) {
- user_media_request.videoConstraints().getOptionalConstraintValue(
- base::UTF8ToUTF16(kMediaStreamSourceInfoId), video_device_id);
- }
+ GetConstraintValueAsString(user_media_request.videoConstraints(),
+ &blink::WebMediaTrackConstraintSet::deviceId,
+ &video_device_id);
}
WebRtcLogMessage(base::StringPrintf(
"MSI::requestUserMedia. request_id=%d"
- ", audio source id=%s mandatory= %s "
- ", video source id=%s mandatory= %s",
- request_id, audio_device_id.utf8().c_str(),
- mandatory_audio ? "true" : "false", video_device_id.utf8().c_str(),
- mandatory_video ? "true" : "false"));
+ ", audio source id=%s"
+ ", video source id=%s",
+ request_id, audio_device_id.c_str(), video_device_id.c_str()));
user_media_requests_.push_back(
new UserMediaRequestInfo(request_id, user_media_request,
@@ -315,8 +280,10 @@ void UserMediaClientImpl::requestMediaDevices(
// underlying pointer is null). In order to use this function in a test we
// need to check if it isNull.
GURL security_origin;
- if (!media_devices_request.isNull())
- security_origin = GURL(media_devices_request.securityOrigin().toString());
+ if (!media_devices_request.isNull()) {
+ security_origin = blink::WebStringToGURL(
+ media_devices_request.getSecurityOrigin().toString());
+ }
DVLOG(1) << "UserMediaClientImpl::requestMediaDevices("
<< audio_input_request_id
@@ -910,7 +877,7 @@ const blink::WebMediaStreamSource* UserMediaClientImpl::FindLocalSource(
for (LocalStreamSources::const_iterator it = local_sources_.begin();
it != local_sources_.end(); ++it) {
MediaStreamSource* const source =
- static_cast<MediaStreamSource*>(it->extraData());
+ static_cast<MediaStreamSource*>(it->getExtraData());
const StreamDeviceInfo& active_device = source->device_info();
if (active_device.device.id == device.device.id &&
active_device.device.type == device.device.type &&
@@ -1052,7 +1019,7 @@ void UserMediaClientImpl::OnLocalSourceStopped(
CHECK(device_found);
MediaStreamSource* source_impl =
- static_cast<MediaStreamSource*>(source.extraData());
+ static_cast<MediaStreamSource*>(source.getExtraData());
media_stream_dispatcher_->StopStreamDevice(source_impl->device_info());
}
@@ -1060,7 +1027,7 @@ void UserMediaClientImpl::StopLocalSource(
const blink::WebMediaStreamSource& source,
bool notify_dispatcher) {
MediaStreamSource* source_impl =
- static_cast<MediaStreamSource*>(source.extraData());
+ static_cast<MediaStreamSource*>(source.getExtraData());
DVLOG(1) << "UserMediaClientImpl::StopLocalSource("
<< "{device_id = " << source_impl->device_info().device.id << "})";
@@ -1091,9 +1058,9 @@ UserMediaClientImpl::UserMediaRequestInfo::~UserMediaRequestInfo() {
void UserMediaClientImpl::UserMediaRequestInfo::StartAudioTrack(
const blink::WebMediaStreamTrack& track,
const blink::WebMediaConstraints& constraints) {
- DCHECK(track.source().type() == blink::WebMediaStreamSource::TypeAudio);
+ DCHECK(track.source().getType() == blink::WebMediaStreamSource::TypeAudio);
MediaStreamAudioSource* native_source =
- static_cast <MediaStreamAudioSource*>(track.source().extraData());
+ MediaStreamAudioSource::From(track.source());
DCHECK(native_source);
sources_.push_back(track.source());
@@ -1108,7 +1075,7 @@ blink::WebMediaStreamTrack
UserMediaClientImpl::UserMediaRequestInfo::CreateAndStartVideoTrack(
const blink::WebMediaStreamSource& source,
const blink::WebMediaConstraints& constraints) {
- DCHECK(source.type() == blink::WebMediaStreamSource::TypeVideo);
+ DCHECK(source.getType() == blink::WebMediaStreamSource::TypeVideo);
MediaStreamVideoSource* native_source =
MediaStreamVideoSource::GetVideoSource(source);
DCHECK(native_source);
diff --git a/chromium/content/renderer/media/user_media_client_impl.h b/chromium/content/renderer/media/user_media_client_impl.h
index 04cc2e0dac6..03cff89b5c9 100644
--- a/chromium/content/renderer/media/user_media_client_impl.h
+++ b/chromium/content/renderer/media/user_media_client_impl.h
@@ -5,13 +5,13 @@
#ifndef CONTENT_RENDERER_MEDIA_USER_MEDIA_CLIENT_IMPL_H_
#define CONTENT_RENDERER_MEDIA_USER_MEDIA_CLIENT_IMPL_H_
+#include <memory>
#include <string>
#include <vector>
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/scoped_vector.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/non_thread_safe.h"
@@ -26,7 +26,7 @@
#include "third_party/WebKit/public/web/WebMediaDevicesRequest.h"
#include "third_party/WebKit/public/web/WebUserMediaClient.h"
#include "third_party/WebKit/public/web/WebUserMediaRequest.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
namespace content {
class PeerConnectionDependencyFactory;
@@ -49,7 +49,7 @@ class CONTENT_EXPORT UserMediaClientImpl
UserMediaClientImpl(
RenderFrame* render_frame,
PeerConnectionDependencyFactory* dependency_factory,
- scoped_ptr<MediaStreamDispatcher> media_stream_dispatcher);
+ std::unique_ptr<MediaStreamDispatcher> media_stream_dispatcher);
~UserMediaClientImpl() override;
MediaStreamDispatcher* media_stream_dispatcher() const {
@@ -121,7 +121,6 @@ class CONTENT_EXPORT UserMediaClientImpl
const StreamDeviceInfo& device,
const MediaStreamSource::SourceStoppedCallback& stop_callback);
- private:
// Class for storing information about a WebKit request to create a
// MediaStream.
class UserMediaRequestInfo
@@ -176,6 +175,15 @@ class CONTENT_EXPORT UserMediaClientImpl
};
typedef ScopedVector<UserMediaRequestInfo> UserMediaRequests;
+ protected:
+ // These methods can be accessed in unit tests.
+ UserMediaRequestInfo* FindUserMediaRequestInfo(int request_id);
+ UserMediaRequestInfo* FindUserMediaRequestInfo(
+ const blink::WebUserMediaRequest& request);
+
+ void DeleteUserMediaRequestInfo(UserMediaRequestInfo* request);
+
+ private:
typedef std::vector<blink::WebMediaStreamSource> LocalStreamSources;
struct MediaDevicesRequestInfo;
@@ -215,10 +223,6 @@ class CONTENT_EXPORT UserMediaClientImpl
void FinalizeEnumerateDevices(MediaDevicesRequestInfo* request);
void FinalizeEnumerateSources(MediaDevicesRequestInfo* request);
- UserMediaRequestInfo* FindUserMediaRequestInfo(int request_id);
- UserMediaRequestInfo* FindUserMediaRequestInfo(
- const blink::WebUserMediaRequest& request);
- void DeleteUserMediaRequestInfo(UserMediaRequestInfo* request);
void DeleteAllUserMediaRequests();
MediaDevicesRequestInfo* FindMediaDevicesRequestInfo(int request_id);
@@ -242,7 +246,7 @@ class CONTENT_EXPORT UserMediaClientImpl
// UserMediaClientImpl owns MediaStreamDispatcher instead of RenderFrameImpl
// (or RenderFrameObserver) to ensure tear-down occurs in the right order.
- const scoped_ptr<MediaStreamDispatcher> media_stream_dispatcher_;
+ const std::unique_ptr<MediaStreamDispatcher> media_stream_dispatcher_;
LocalStreamSources local_sources_;
diff --git a/chromium/content/renderer/media/user_media_client_impl_unittest.cc b/chromium/content/renderer/media/user_media_client_impl_unittest.cc
index a9d1911e6b1..ebaeedb686d 100644
--- a/chromium/content/renderer/media/user_media_client_impl_unittest.cc
+++ b/chromium/content/renderer/media/user_media_client_impl_unittest.cc
@@ -5,14 +5,17 @@
#include "content/renderer/media/user_media_client_impl.h"
#include <stddef.h>
+
+#include <memory>
#include <utility>
-#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "content/child/child_process.h"
#include "content/renderer/media/media_stream.h"
+#include "content/renderer/media/media_stream_audio_source.h"
#include "content/renderer/media/media_stream_track.h"
+#include "content/renderer/media/mock_constraint_factory.h"
#include "content/renderer/media/mock_media_stream_dispatcher.h"
#include "content/renderer/media/mock_media_stream_video_source.h"
#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
@@ -51,7 +54,7 @@ class UserMediaClientImplUnderTest : public UserMediaClientImpl {
UserMediaClientImplUnderTest(
PeerConnectionDependencyFactory* dependency_factory,
- scoped_ptr<MediaStreamDispatcher> media_stream_dispatcher)
+ std::unique_ptr<MediaStreamDispatcher> media_stream_dispatcher)
: UserMediaClientImpl(NULL,
dependency_factory,
std::move(media_stream_dispatcher)),
@@ -61,12 +64,16 @@ class UserMediaClientImplUnderTest : public UserMediaClientImpl {
factory_(dependency_factory),
video_source_(NULL) {}
- void RequestUserMedia() {
- blink::WebUserMediaRequest user_media_request;
+ void RequestUserMedia(const blink::WebUserMediaRequest& user_media_request) {
state_ = REQUEST_NOT_COMPLETE;
requestUserMedia(user_media_request);
}
+ void RequestUserMedia() {
+ blink::WebUserMediaRequest user_media_request;
+ RequestUserMedia(user_media_request);
+ }
+
void RequestMediaDevices() {
blink::WebMediaDevicesRequest media_devices_request;
state_ = REQUEST_NOT_COMPLETE;
@@ -143,6 +150,18 @@ class UserMediaClientImplUnderTest : public UserMediaClientImpl {
content::MediaStreamRequestResult error_reason() const { return result_; }
blink::WebString error_name() const { return result_name_; }
+ // Access to the request queue for testing.
+ bool UserMediaRequestHasAutomaticDeviceSelection(int request_id) {
+ auto* request = FindUserMediaRequestInfo(request_id);
+ EXPECT_TRUE(request != nullptr);
+ return request && request->enable_automatic_output_device_selection;
+ }
+
+ void DeleteRequest(int request_id) {
+ auto* request = FindUserMediaRequestInfo(request_id);
+ DeleteUserMediaRequestInfo(request);
+ }
+
private:
blink::WebMediaStream last_generated_stream_;
RequestState state_;
@@ -163,7 +182,7 @@ class UserMediaClientImplTest : public ::testing::Test {
ms_dispatcher_ = new MockMediaStreamDispatcher();
used_media_impl_.reset(new UserMediaClientImplUnderTest(
dependency_factory_.get(),
- scoped_ptr<MediaStreamDispatcher>(ms_dispatcher_)));
+ std::unique_ptr<MediaStreamDispatcher>(ms_dispatcher_)));
}
void TearDown() override {
@@ -248,12 +267,25 @@ class UserMediaClientImplTest : public ::testing::Test {
blink::WebHeap::collectGarbageForTesting();
}
+ bool AudioRequestHasAutomaticDeviceSelection(
+ const blink::WebMediaConstraints& audio_constraints) {
+ blink::WebMediaConstraints null_constraints;
+ blink::WebUserMediaRequest request =
+ blink::WebUserMediaRequest::createForTesting(audio_constraints,
+ null_constraints);
+ used_media_impl_->RequestUserMedia(request);
+ bool result = used_media_impl_->UserMediaRequestHasAutomaticDeviceSelection(
+ ms_dispatcher_->audio_input_request_id());
+ used_media_impl_->DeleteRequest(ms_dispatcher_->audio_input_request_id());
+ return result;
+ }
+
protected:
base::MessageLoop message_loop_;
- scoped_ptr<ChildProcess> child_process_;
+ std::unique_ptr<ChildProcess> child_process_;
MockMediaStreamDispatcher* ms_dispatcher_; // Owned by |used_media_impl_|.
- scoped_ptr<UserMediaClientImplUnderTest> used_media_impl_;
- scoped_ptr<MockPeerConnectionDependencyFactory> dependency_factory_;
+ std::unique_ptr<UserMediaClientImplUnderTest> used_media_impl_;
+ std::unique_ptr<MockPeerConnectionDependencyFactory> dependency_factory_;
};
TEST_F(UserMediaClientImplTest, GenerateMediaStream) {
@@ -274,8 +306,8 @@ TEST_F(UserMediaClientImplTest, GenerateTwoMediaStreamsWithSameSource) {
EXPECT_EQ(desc1_video_tracks[0].source().id(),
desc2_video_tracks[0].source().id());
- EXPECT_EQ(desc1_video_tracks[0].source().extraData(),
- desc2_video_tracks[0].source().extraData());
+ EXPECT_EQ(desc1_video_tracks[0].source().getExtraData(),
+ desc2_video_tracks[0].source().getExtraData());
blink::WebVector<blink::WebMediaStreamTrack> desc1_audio_tracks;
desc1.audioTracks(desc1_audio_tracks);
@@ -284,8 +316,8 @@ TEST_F(UserMediaClientImplTest, GenerateTwoMediaStreamsWithSameSource) {
EXPECT_EQ(desc1_audio_tracks[0].source().id(),
desc2_audio_tracks[0].source().id());
- EXPECT_EQ(desc1_audio_tracks[0].source().extraData(),
- desc2_audio_tracks[0].source().extraData());
+ EXPECT_EQ(MediaStreamAudioSource::From(desc1_audio_tracks[0].source()),
+ MediaStreamAudioSource::From(desc2_audio_tracks[0].source()));
}
// Test that the same source object is not used if two MediaStreams are
@@ -304,8 +336,8 @@ TEST_F(UserMediaClientImplTest, GenerateTwoMediaStreamsWithDifferentSources) {
EXPECT_NE(desc1_video_tracks[0].source().id(),
desc2_video_tracks[0].source().id());
- EXPECT_NE(desc1_video_tracks[0].source().extraData(),
- desc2_video_tracks[0].source().extraData());
+ EXPECT_NE(desc1_video_tracks[0].source().getExtraData(),
+ desc2_video_tracks[0].source().getExtraData());
blink::WebVector<blink::WebMediaStreamTrack> desc1_audio_tracks;
desc1.audioTracks(desc1_audio_tracks);
@@ -314,8 +346,8 @@ TEST_F(UserMediaClientImplTest, GenerateTwoMediaStreamsWithDifferentSources) {
EXPECT_NE(desc1_audio_tracks[0].source().id(),
desc2_audio_tracks[0].source().id());
- EXPECT_NE(desc1_audio_tracks[0].source().extraData(),
- desc2_audio_tracks[0].source().extraData());
+ EXPECT_NE(MediaStreamAudioSource::From(desc1_audio_tracks[0].source()),
+ MediaStreamAudioSource::From(desc2_audio_tracks[0].source()));
}
TEST_F(UserMediaClientImplTest, StopLocalTracks) {
@@ -575,4 +607,35 @@ TEST_F(UserMediaClientImplTest, EnumerateSources) {
EXPECT_EQ(blink::WebSourceInfo::VideoFacingModeEnvironment, source->facing());
}
+TEST_F(UserMediaClientImplTest, RenderToAssociatedSinkConstraint) {
+ // For a null UserMediaRequest (no audio requested), we expect false.
+ used_media_impl_->RequestUserMedia();
+ EXPECT_FALSE(used_media_impl_->UserMediaRequestHasAutomaticDeviceSelection(
+ ms_dispatcher_->audio_input_request_id()));
+ used_media_impl_->DeleteRequest(ms_dispatcher_->audio_input_request_id());
+
+ // If audio is requested, but no constraint, it should be true.
+ MockConstraintFactory factory;
+ blink::WebMediaConstraints audio_constraints =
+ factory.CreateWebMediaConstraints();
+ EXPECT_TRUE(AudioRequestHasAutomaticDeviceSelection(
+ factory.CreateWebMediaConstraints()));
+
+ // If the constraint is present, it should dictate the result.
+ factory.Reset();
+ factory.AddAdvanced().renderToAssociatedSink.setExact(true);
+ EXPECT_TRUE(AudioRequestHasAutomaticDeviceSelection(
+ factory.CreateWebMediaConstraints()));
+
+ factory.Reset();
+ factory.AddAdvanced().renderToAssociatedSink.setExact(false);
+ EXPECT_FALSE(AudioRequestHasAutomaticDeviceSelection(
+ factory.CreateWebMediaConstraints()));
+
+ factory.Reset();
+ factory.basic().renderToAssociatedSink.setExact(false);
+ EXPECT_FALSE(AudioRequestHasAutomaticDeviceSelection(
+ factory.CreateWebMediaConstraints()));
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/video_capture_impl.cc b/chromium/content/renderer/media/video_capture_impl.cc
index 8e50ede0063..d6ef0e21775 100644
--- a/chromium/content/renderer/media/video_capture_impl.cc
+++ b/chromium/content/renderer/media/video_capture_impl.cc
@@ -19,8 +19,8 @@
#include "base/stl_util.h"
#include "base/thread_task_runner_handle.h"
#include "content/child/child_process.h"
-#include "content/common/gpu/client/gpu_memory_buffer_impl.h"
#include "content/common/media/video_capture_messages.h"
+#include "gpu/ipc/client/gpu_memory_buffer_impl.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/limits.h"
#include "media/base/video_frame.h"
@@ -31,7 +31,7 @@ namespace content {
class VideoCaptureImpl::ClientBuffer
: public base::RefCountedThreadSafe<ClientBuffer> {
public:
- ClientBuffer(scoped_ptr<base::SharedMemory> buffer, size_t buffer_size)
+ ClientBuffer(std::unique_ptr<base::SharedMemory> buffer, size_t buffer_size)
: buffer_(std::move(buffer)), buffer_size_(buffer_size) {}
base::SharedMemory* buffer() const { return buffer_.get(); }
@@ -42,7 +42,7 @@ class VideoCaptureImpl::ClientBuffer
virtual ~ClientBuffer() {}
- const scoped_ptr<base::SharedMemory> buffer_;
+ const std::unique_ptr<base::SharedMemory> buffer_;
const size_t buffer_size_;
DISALLOW_COPY_AND_ASSIGN(ClientBuffer);
@@ -63,7 +63,7 @@ class VideoCaptureImpl::ClientBuffer2
for (size_t i = 0; i < handles_.size(); ++i) {
const size_t width = media::VideoFrame::Columns(i, format, size_.width());
const size_t height = media::VideoFrame::Rows(i, format, size_.height());
- buffers_.push_back(GpuMemoryBufferImpl::CreateFromHandle(
+ buffers_.push_back(gpu::GpuMemoryBufferImpl::CreateFromHandle(
handles_[i], gfx::Size(width, height), gfx::BufferFormat::R_8,
gfx::BufferUsage::GPU_READ_CPU_READ_WRITE,
base::Bind(&ClientBuffer2::DestroyGpuMemoryBuffer,
@@ -101,6 +101,7 @@ class VideoCaptureImpl::ClientBuffer2
};
VideoCaptureImpl::ClientInfo::ClientInfo() {}
+VideoCaptureImpl::ClientInfo::ClientInfo(const ClientInfo& other) = default;
VideoCaptureImpl::ClientInfo::~ClientInfo() {}
VideoCaptureImpl::VideoCaptureImpl(
@@ -216,6 +217,11 @@ void VideoCaptureImpl::StopCapture(int client_id) {
}
}
+void VideoCaptureImpl::RequestRefreshFrame() {
+ DCHECK(io_task_runner_->BelongsToCurrentThread());
+ Send(new VideoCaptureHostMsg_RequestRefreshFrame(device_id_));
+}
+
void VideoCaptureImpl::GetDeviceSupportedFormats(
const VideoCaptureDeviceFormatsCB& callback) {
DCHECK(io_task_runner_->BelongsToCurrentThread());
@@ -246,7 +252,8 @@ void VideoCaptureImpl::OnBufferCreated(base::SharedMemoryHandle handle,
return;
}
- scoped_ptr<base::SharedMemory> shm(new base::SharedMemory(handle, false));
+ std::unique_ptr<base::SharedMemory> shm(
+ new base::SharedMemory(handle, false));
if (!shm->Map(length)) {
DLOG(ERROR) << "OnBufferCreated: Map failed.";
return;
@@ -328,7 +335,7 @@ void VideoCaptureImpl::OnBufferReceived(
scoped_refptr<media::VideoFrame> frame;
BufferFinishedCallback buffer_finished_callback;
- scoped_ptr<gpu::SyncToken> release_sync_token(new gpu::SyncToken);
+ std::unique_ptr<gpu::SyncToken> release_sync_token(new gpu::SyncToken);
switch (storage_type) {
case media::VideoFrame::STORAGE_GPU_MEMORY_BUFFERS: {
const auto& iter = client_buffer2s_.find(buffer_id);
@@ -544,7 +551,7 @@ bool VideoCaptureImpl::RemoveClient(int client_id, ClientInfoMap* clients) {
// static
void VideoCaptureImpl::DidFinishConsumingFrame(
const media::VideoFrameMetadata* metadata,
- scoped_ptr<gpu::SyncToken> release_sync_token,
+ std::unique_ptr<gpu::SyncToken> release_sync_token,
const BufferFinishedCallback& callback_to_io_thread) {
// Note: This function may be called on any thread by the VideoFrame
// destructor. |metadata| is still valid for read-access at this point.
diff --git a/chromium/content/renderer/media/video_capture_impl.h b/chromium/content/renderer/media/video_capture_impl.h
index cd2a8090af1..b07823486d8 100644
--- a/chromium/content/renderer/media/video_capture_impl.h
+++ b/chromium/content/renderer/media/video_capture_impl.h
@@ -73,6 +73,10 @@ class CONTENT_EXPORT VideoCaptureImpl
// Stop capturing. |client_id| is the identifier used to call StartCapture.
void StopCapture(int client_id);
+ // Requests that the video capturer send a frame "soon" (e.g., to resolve
+ // picture loss or quality issues).
+ void RequestRefreshFrame();
+
// Get capturing formats supported by this device.
// |callback| will be invoked with the results.
void GetDeviceSupportedFormats(const VideoCaptureDeviceFormatsCB& callback);
@@ -96,6 +100,7 @@ class CONTENT_EXPORT VideoCaptureImpl
// for capturing and callbacks to the client.
struct ClientInfo {
ClientInfo();
+ ClientInfo(const ClientInfo& other);
~ClientInfo();
media::VideoCaptureParams params;
VideoCaptureStateUpdateCB state_update_cb;
@@ -156,7 +161,7 @@ class CONTENT_EXPORT VideoCaptureImpl
// callback, to trampoline back to the IO thread with the values.
static void DidFinishConsumingFrame(
const media::VideoFrameMetadata* metadata,
- scoped_ptr<gpu::SyncToken> release_sync_token,
+ std::unique_ptr<gpu::SyncToken> release_sync_token,
const BufferFinishedCallback& callback_to_io_thread);
const scoped_refptr<VideoCaptureMessageFilter> message_filter_;
diff --git a/chromium/content/renderer/media/video_capture_impl_manager.cc b/chromium/content/renderer/media/video_capture_impl_manager.cc
index 1ce78d6b0bd..478a169cea3 100644
--- a/chromium/content/renderer/media/video_capture_impl_manager.cc
+++ b/chromium/content/renderer/media/video_capture_impl_manager.cc
@@ -96,6 +96,19 @@ base::Closure VideoCaptureImplManager::StartCapture(
weak_factory_.GetWeakPtr(), client_id, id);
}
+void VideoCaptureImplManager::RequestRefreshFrame(
+ media::VideoCaptureSessionId id) {
+ DCHECK(render_main_task_runner_->BelongsToCurrentThread());
+ const VideoCaptureDeviceMap::const_iterator it = devices_.find(id);
+ DCHECK(it != devices_.end());
+ VideoCaptureImpl* const impl = it->second.second;
+ ChildProcess::current()->io_task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&VideoCaptureImpl::RequestRefreshFrame,
+ base::Unretained(impl)));
+}
+
+
void VideoCaptureImplManager::GetDeviceSupportedFormats(
media::VideoCaptureSessionId id,
const VideoCaptureDeviceFormatsCB& callback) {
diff --git a/chromium/content/renderer/media/video_capture_impl_manager.h b/chromium/content/renderer/media/video_capture_impl_manager.h
index ef1a16889a7..1b7c28b3fb7 100644
--- a/chromium/content/renderer/media/video_capture_impl_manager.h
+++ b/chromium/content/renderer/media/video_capture_impl_manager.h
@@ -6,11 +6,11 @@
#define CONTENT_RENDERER_MEDIA_VIDEO_CAPTURE_IMPL_MANAGER_H_
#include <map>
+#include <memory>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
@@ -73,6 +73,10 @@ class CONTENT_EXPORT VideoCaptureImplManager {
const VideoCaptureStateUpdateCB& state_update_cb,
const VideoCaptureDeliverFrameCB& deliver_frame_cb);
+ // Requests that the video capturer send a frame "soon" (e.g., to resolve
+ // picture loss or quality issues).
+ void RequestRefreshFrame(media::VideoCaptureSessionId id);
+
// Get supported formats supported by the device for the given session
// ID. |callback| will be called on the IO thread.
void GetDeviceSupportedFormats(media::VideoCaptureSessionId id,
diff --git a/chromium/content/renderer/media/video_capture_impl_manager_unittest.cc b/chromium/content/renderer/media/video_capture_impl_manager_unittest.cc
index 3bb923eef76..349a32eca34 100644
--- a/chromium/content/renderer/media/video_capture_impl_manager_unittest.cc
+++ b/chromium/content/renderer/media/video_capture_impl_manager_unittest.cc
@@ -118,10 +118,10 @@ class VideoCaptureImplManagerTest : public ::testing::Test {
}
base::MessageLoop message_loop_;
- scoped_ptr<ChildProcess> child_process_;
+ std::unique_ptr<ChildProcess> child_process_;
media::VideoCaptureParams params_;
base::RunLoop cleanup_run_loop_;
- scoped_ptr<MockVideoCaptureImplManager> manager_;
+ std::unique_ptr<MockVideoCaptureImplManager> manager_;
private:
DISALLOW_COPY_AND_ASSIGN(VideoCaptureImplManagerTest);
diff --git a/chromium/content/renderer/media/video_capture_impl_unittest.cc b/chromium/content/renderer/media/video_capture_impl_unittest.cc
index 1f0ad49a8d2..1fc43c024b8 100644
--- a/chromium/content/renderer/media/video_capture_impl_unittest.cc
+++ b/chromium/content/renderer/media/video_capture_impl_unittest.cc
@@ -199,10 +199,10 @@ class VideoCaptureImplTest : public ::testing::Test {
}
base::MessageLoop message_loop_;
- scoped_ptr<ChildProcess> child_process_;
+ std::unique_ptr<ChildProcess> child_process_;
scoped_refptr<MockVideoCaptureMessageFilter> message_filter_;
media::VideoCaptureSessionId session_id_;
- scoped_ptr<MockVideoCaptureImpl> video_capture_impl_;
+ std::unique_ptr<MockVideoCaptureImpl> video_capture_impl_;
media::VideoCaptureParams params_small_;
media::VideoCaptureParams params_large_;
diff --git a/chromium/content/renderer/media/video_capture_message_filter_unittest.cc b/chromium/content/renderer/media/video_capture_message_filter_unittest.cc
index edf0e6047ed..fd189a64e21 100644
--- a/chromium/content/renderer/media/video_capture_message_filter_unittest.cc
+++ b/chromium/content/renderer/media/video_capture_message_filter_unittest.cc
@@ -97,18 +97,23 @@ TEST(VideoCaptureMessageFilterTest, Basic) {
Mock::VerifyAndClearExpectations(&delegate);
// VideoCaptureMsg_NewBuffer
- const base::SharedMemoryHandle handle =
#if defined(OS_WIN)
- base::SharedMemoryHandle(reinterpret_cast<HANDLE>(10),
- base::GetCurrentProcId());
+ HANDLE h = reinterpret_cast<HANDLE>(10);
+ // Passing a process ID that is not the current process's to prevent
+ // attachment brokering.
+ const base::SharedMemoryHandle handle =
+ base::SharedMemoryHandle(h, base::GetCurrentProcId() + 1);
+ EXPECT_CALL(delegate,
+ OnBufferCreated(
+ ::testing::Property(&base::SharedMemoryHandle::GetHandle, h),
+ 100, 1));
#else
- base::SharedMemoryHandle(10, true);
-#endif
+ const base::SharedMemoryHandle handle = base::SharedMemoryHandle(10, true);
EXPECT_CALL(delegate, OnBufferCreated(handle, 100, 1));
+#endif
filter->OnMessageReceived(VideoCaptureMsg_NewBuffer(
delegate.device_id(), handle, 100, 1));
Mock::VerifyAndClearExpectations(&delegate);
-
// VideoCaptureMsg_BufferReady
VideoCaptureMsg_BufferReady_Params params;
params.device_id = delegate.device_id();
diff --git a/chromium/content/renderer/media/video_track_adapter.cc b/chromium/content/renderer/media/video_track_adapter.cc
index f4ca1d2c746..1b727845f62 100644
--- a/chromium/content/renderer/media/video_track_adapter.cc
+++ b/chromium/content/renderer/media/video_track_adapter.cc
@@ -43,7 +43,7 @@ void ReleaseOriginalFrame(const scoped_refptr<media::VideoFrame>& frame) {
}
void ResetCallbackOnMainRenderThread(
- scoped_ptr<VideoCaptureDeliverFrameCB> callback) {
+ std::unique_ptr<VideoCaptureDeliverFrameCB> callback) {
// |callback| will be deleted when this exits.
}
@@ -184,7 +184,7 @@ void VideoTrackAdapter::VideoFrameResolutionAdapter::RemoveCallback(
// Make sure the VideoCaptureDeliverFrameCB is released on the main
// render thread since it was added on the main render thread in
// VideoTrackAdapter::AddTrack.
- scoped_ptr<VideoCaptureDeliverFrameCB> callback(
+ std::unique_ptr<VideoCaptureDeliverFrameCB> callback(
new VideoCaptureDeliverFrameCB(it->second));
callbacks_.erase(it);
renderer_task_runner_->PostTask(
@@ -266,8 +266,8 @@ void VideoTrackAdapter::VideoFrameResolutionAdapter::DeliverFrame(
const gfx::Rect region_in_frame =
media::ComputeLetterboxRegion(frame->visible_rect(), desired_size);
- video_frame =
- media::VideoFrame::WrapVideoFrame(frame, region_in_frame, desired_size);
+ video_frame = media::VideoFrame::WrapVideoFrame(
+ frame, frame->format(), region_in_frame, desired_size);
if (!video_frame)
return;
video_frame->AddDestructionObserver(
diff --git a/chromium/content/renderer/media/video_track_recorder.cc b/chromium/content/renderer/media/video_track_recorder.cc
index 9c923cc11f7..980a90ba8a2 100644
--- a/chromium/content/renderer/media/video_track_recorder.cc
+++ b/chromium/content/renderer/media/video_track_recorder.cc
@@ -14,14 +14,15 @@
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "media/base/video_frame.h"
+#include "media/base/video_util.h"
#include "ui/gfx/geometry/size.h"
extern "C" {
// VPX_CODEC_DISABLE_COMPAT excludes parts of the libvpx API that provide
// backwards compatibility for legacy applications using the library.
#define VPX_CODEC_DISABLE_COMPAT 1
-#include "third_party/libvpx_new/source/libvpx/vpx/vp8cx.h"
-#include "third_party/libvpx_new/source/libvpx/vpx/vpx_encoder.h"
+#include "third_party/libvpx/source/libvpx/vpx/vp8cx.h"
+#include "third_party/libvpx/source/libvpx/vpx/vpx_encoder.h"
}
using media::VideoFrame;
@@ -45,12 +46,12 @@ struct VpxCodecDeleter {
}
};
-typedef scoped_ptr<vpx_codec_ctx_t, VpxCodecDeleter> ScopedVpxCodecCtxPtr;
+typedef std::unique_ptr<vpx_codec_ctx_t, VpxCodecDeleter> ScopedVpxCodecCtxPtr;
void OnFrameEncodeCompleted(
const VideoTrackRecorder::OnEncodedVideoCB& on_encoded_video_cb,
const scoped_refptr<VideoFrame>& frame,
- scoped_ptr<std::string> data,
+ std::unique_ptr<std::string> data,
base::TimeTicks capture_timestamp,
bool keyframe) {
DVLOG(1) << (keyframe ? "" : "non ") << "keyframe "<< data->length() << "B, "
@@ -75,10 +76,12 @@ void OnFrameEncodeCompleted(
class VideoTrackRecorder::VpxEncoder final
: public base::RefCountedThreadSafe<VpxEncoder> {
public:
- static void ShutdownEncoder(scoped_ptr<base::Thread> encoding_thread,
+ static void ShutdownEncoder(std::unique_ptr<base::Thread> encoding_thread,
ScopedVpxCodecCtxPtr encoder);
- VpxEncoder(bool use_vp9, const OnEncodedVideoCB& on_encoded_video_callback);
+ VpxEncoder(bool use_vp9,
+ const OnEncodedVideoCB& on_encoded_video_callback,
+ int32_t bits_per_second);
void StartFrameEncode(const scoped_refptr<VideoFrame>& frame,
base::TimeTicks capture_timestamp);
@@ -107,18 +110,21 @@ class VideoTrackRecorder::VpxEncoder final
// Force usage of VP9 for encoding, instead of VP8 which is the default.
const bool use_vp9_;
+ // This callback should be exercised on IO thread.
+ const OnEncodedVideoCB on_encoded_video_callback_;
+
+ // Target bitrate or video encoding. If 0, a standard bitrate is used.
+ const int32_t bits_per_second_;
+
// Used to shutdown properly on the same thread we were created.
const scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
// Task runner where frames to encode and reply callbacks must happen.
scoped_refptr<base::SingleThreadTaskRunner> origin_task_runner_;
- // This callback should be exercised on IO thread.
- const OnEncodedVideoCB on_encoded_video_callback_;
-
// Thread for encoding. Active for the lifetime of VpxEncoder. All variables
// below this are used in this thread.
- scoped_ptr<base::Thread> encoding_thread_;
+ std::unique_ptr<base::Thread> encoding_thread_;
// VP8 internal objects: configuration and encoder.
vpx_codec_enc_cfg_t codec_config_;
// |encoder_| is a special scoped pointer to guarantee proper destruction.
@@ -134,7 +140,7 @@ class VideoTrackRecorder::VpxEncoder final
// static
void VideoTrackRecorder::VpxEncoder::ShutdownEncoder(
- scoped_ptr<base::Thread> encoding_thread,
+ std::unique_ptr<base::Thread> encoding_thread,
ScopedVpxCodecCtxPtr encoder) {
DCHECK(encoding_thread->IsRunning());
encoding_thread->Stop();
@@ -143,11 +149,13 @@ void VideoTrackRecorder::VpxEncoder::ShutdownEncoder(
VideoTrackRecorder::VpxEncoder::VpxEncoder(
bool use_vp9,
- const OnEncodedVideoCB& on_encoded_video_callback)
+ const OnEncodedVideoCB& on_encoded_video_callback,
+ int32_t bits_per_second)
: paused_(false),
use_vp9_(use_vp9),
- main_task_runner_(base::MessageLoop::current()->task_runner()),
on_encoded_video_callback_(on_encoded_video_callback),
+ bits_per_second_(bits_per_second),
+ main_task_runner_(base::MessageLoop::current()->task_runner()),
encoding_thread_(new base::Thread("EncodingThread")) {
DCHECK(!on_encoded_video_callback_.is_null());
@@ -179,12 +187,23 @@ void VideoTrackRecorder::VpxEncoder::StartFrameEncode(
}
void VideoTrackRecorder::VpxEncoder::EncodeOnEncodingThread(
- const scoped_refptr<VideoFrame>& frame,
+ const scoped_refptr<VideoFrame>& video_frame,
base::TimeTicks capture_timestamp) {
TRACE_EVENT0("video",
"VideoTrackRecorder::VpxEncoder::EncodeOnEncodingThread");
DCHECK(encoding_thread_->task_runner()->BelongsToCurrentThread());
+ if (!(video_frame->format() == media::PIXEL_FORMAT_I420 ||
+ video_frame->format() == media::PIXEL_FORMAT_YV12 ||
+ video_frame->format() == media::PIXEL_FORMAT_YV12A)) {
+ NOTREACHED();
+ return;
+ }
+ scoped_refptr<media::VideoFrame> frame = video_frame;
+ // Drop alpha channel since we do not support it yet.
+ if (frame->format() == media::PIXEL_FORMAT_YV12A)
+ frame = media::WrapAsI420VideoFrame(video_frame);
+
const gfx::Size frame_size = frame->visible_rect().size();
if (!IsInitialized() ||
gfx::Size(codec_config_.g_w, codec_config_.g_h) != frame_size) {
@@ -220,7 +239,7 @@ void VideoTrackRecorder::VpxEncoder::EncodeOnEncodingThread(
<< vpx_codec_error(encoder_.get()) << " -"
<< vpx_codec_error_detail(encoder_.get());
- scoped_ptr<std::string> data(new std::string);
+ std::unique_ptr<std::string> data(new std::string);
bool keyframe = false;
vpx_codec_iter_t iter = NULL;
const vpx_codec_cx_pkt_t* pkt = NULL;
@@ -253,18 +272,22 @@ void VideoTrackRecorder::VpxEncoder::ConfigureEncoding(const gfx::Size& size) {
const vpx_codec_iface_t* interface =
use_vp9_ ? vpx_codec_vp9_cx() : vpx_codec_vp8_cx();
- const vpx_codec_err_t result = vpx_codec_enc_config_default(interface,
- &codec_config_,
- 0 /* reserved */);
+ vpx_codec_err_t result =
+ vpx_codec_enc_config_default(interface, &codec_config_, 0 /* reserved */);
DCHECK_EQ(VPX_CODEC_OK, result);
- // Adjust default bit rate to account for the actual size.
DCHECK_EQ(320u, codec_config_.g_w);
DCHECK_EQ(240u, codec_config_.g_h);
DCHECK_EQ(256u, codec_config_.rc_target_bitrate);
- codec_config_.rc_target_bitrate = size.GetArea() *
- codec_config_.rc_target_bitrate /
- codec_config_.g_w / codec_config_.g_h;
+ // Use the selected bitrate or adjust default bit rate to account for the
+ // actual size. Note: |rc_target_bitrate| units are kbit per second.
+ if (bits_per_second_ > 0) {
+ codec_config_.rc_target_bitrate = bits_per_second_ / 1000;
+ } else {
+ codec_config_.rc_target_bitrate = size.GetArea() *
+ codec_config_.rc_target_bitrate /
+ codec_config_.g_w / codec_config_.g_h;
+ }
// Both VP8/VP9 configuration should be Variable BitRate by default.
DCHECK_EQ(VPX_VBR, codec_config_.rc_end_usage);
if (use_vp9_) {
@@ -295,9 +318,11 @@ void VideoTrackRecorder::VpxEncoder::ConfigureEncoding(const gfx::Size& size) {
// Note that due to http://crbug.com/440223, it might be necessary to force a
// key frame after 10,000frames since decoding fails after 30,000 non-key
// frames.
+ // Forcing a keyframe in regular intervals also allows seeking in the
+ // resulting recording with decent performance.
codec_config_.kf_mode = VPX_KF_AUTO;
codec_config_.kf_min_dist = 0;
- codec_config_.kf_max_dist = 30000;
+ codec_config_.kf_max_dist = 100;
// Do not saturate CPU utilization just for encoding. On a lower-end system
// with only 1 or 2 cores, use only one thread for encoding. On systems with
@@ -313,6 +338,17 @@ void VideoTrackRecorder::VpxEncoder::ConfigureEncoding(const gfx::Size& size) {
const vpx_codec_err_t ret = vpx_codec_enc_init(encoder_.get(), interface,
&codec_config_, kNoFlags);
DCHECK_EQ(VPX_CODEC_OK, ret);
+
+ if (use_vp9_) {
+ // Values of VP8E_SET_CPUUSED greater than 0 will increase encoder speed at
+ // the expense of quality up to a maximum value of 8 for VP9, by tuning the
+ // target time spent encoding the frame. Go from 8 to 5 (values for real
+ // time encoding) depending on the amount of cores available in the system.
+ const int kCpuUsed =
+ std::max(5, 8 - base::SysInfo::NumberOfProcessors() / 2);
+ result = vpx_codec_control(encoder_.get(), VP8E_SET_CPUUSED, kCpuUsed);
+ DLOG_IF(WARNING, VPX_CODEC_OK != result) << "VP8E_SET_CPUUSED failed";
+ }
}
bool VideoTrackRecorder::VpxEncoder::IsInitialized() const {
@@ -348,23 +384,24 @@ base::TimeDelta VideoTrackRecorder::VpxEncoder::CalculateFrameDuration(
VideoTrackRecorder::VideoTrackRecorder(
bool use_vp9,
const blink::WebMediaStreamTrack& track,
- const OnEncodedVideoCB& on_encoded_video_callback)
+ const OnEncodedVideoCB& on_encoded_video_callback,
+ int32_t bits_per_second)
: track_(track),
- encoder_(new VpxEncoder(use_vp9, on_encoded_video_callback)) {
+ encoder_(
+ new VpxEncoder(use_vp9, on_encoded_video_callback, bits_per_second)) {
DCHECK(main_render_thread_checker_.CalledOnValidThread());
DCHECK(!track_.isNull());
- DCHECK(track_.extraData());
+ DCHECK(track_.getExtraData());
// StartFrameEncode() will be called on Render IO thread.
- AddToVideoTrack(this,
- base::Bind(&VideoTrackRecorder::VpxEncoder::StartFrameEncode,
- encoder_),
- track_);
+ MediaStreamVideoSink::ConnectToTrack(
+ track_,
+ base::Bind(&VideoTrackRecorder::VpxEncoder::StartFrameEncode, encoder_));
}
VideoTrackRecorder::~VideoTrackRecorder() {
DCHECK(main_render_thread_checker_.CalledOnValidThread());
- RemoveFromVideoTrack(this, track_);
+ MediaStreamVideoSink::DisconnectFromTrack();
track_.reset();
}
diff --git a/chromium/content/renderer/media/video_track_recorder.h b/chromium/content/renderer/media/video_track_recorder.h
index c5c31b5996b..971257bf726 100644
--- a/chromium/content/renderer/media/video_track_recorder.h
+++ b/chromium/content/renderer/media/video_track_recorder.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_RENDERER_MEDIA_VIDEO_TRACK_RECORDER_H_
#define CONTENT_RENDERER_MEDIA_VIDEO_TRACK_RECORDER_H_
+#include <memory>
+
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/threading/thread_checker.h"
@@ -28,14 +30,15 @@ class CONTENT_EXPORT VideoTrackRecorder
public:
using OnEncodedVideoCB =
base::Callback<void(const scoped_refptr<media::VideoFrame>& video_frame,
- scoped_ptr<std::string> encoded_data,
+ std::unique_ptr<std::string> encoded_data,
base::TimeTicks capture_timestamp,
bool is_key_frame)>;
// |use_vp9| forces using VP9, otherwise VP8 will be used by default.
VideoTrackRecorder(bool use_vp9,
const blink::WebMediaStreamTrack& track,
- const OnEncodedVideoCB& on_encoded_video_cb);
+ const OnEncodedVideoCB& on_encoded_video_cb,
+ int32_t bits_per_second);
~VideoTrackRecorder() override;
void Pause();
diff --git a/chromium/content/renderer/media/video_track_recorder_unittest.cc b/chromium/content/renderer/media/video_track_recorder_unittest.cc
index 6605bb6c31d..12ed36c710c 100644
--- a/chromium/content/renderer/media/video_track_recorder_unittest.cc
+++ b/chromium/content/renderer/media/video_track_recorder_unittest.cc
@@ -2,19 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "content/renderer/media/video_track_recorder.h"
+
#include <stddef.h>
+#include <memory>
+
#include "base/bind.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "content/child/child_process.h"
#include "content/renderer/media/media_stream_video_track.h"
#include "content/renderer/media/mock_media_stream_video_source.h"
-#include "content/renderer/media/video_track_recorder.h"
#include "media/base/video_frame.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -38,17 +40,9 @@ ACTION_P(RunClosure, closure) {
closure.Run();
}
-struct TrackRecorderTestParams {
- const bool use_vp9;
- const size_t first_encoded_frame_size;
- const size_t second_encoded_frame_size;
- const size_t third_encoded_frame_size;
-};
-
-const TrackRecorderTestParams kTrackRecorderTestParams[] = {{false, 52, 32, 57},
- {true, 33, 18, 33}};
+const bool kTrackRecorderTestUseVp9OrNot[] = {false, true};
-class VideoTrackRecorderTest : public TestWithParam<TrackRecorderTestParams> {
+class VideoTrackRecorderTest : public TestWithParam<bool> {
public:
VideoTrackRecorderTest()
: mock_source_(new MockMediaStreamVideoSource(false)) {
@@ -67,12 +61,13 @@ class VideoTrackRecorderTest : public TestWithParam<TrackRecorderTestParams> {
blink_track_.setExtraData(track_);
video_track_recorder_.reset(new VideoTrackRecorder(
- GetParam().use_vp9 /* use_vp9 */,
- blink_track_,
+ GetParam() /* use_vp9 */, blink_track_,
base::Bind(&VideoTrackRecorderTest::OnEncodedVideo,
- base::Unretained(this))));
+ base::Unretained(this)),
+ 0 /* bits_per_second */));
// Paranoia checks.
- EXPECT_EQ(blink_track_.source().extraData(), blink_source_.extraData());
+ EXPECT_EQ(blink_track_.source().getExtraData(),
+ blink_source_.getExtraData());
EXPECT_TRUE(message_loop_.IsCurrent());
}
@@ -89,7 +84,7 @@ class VideoTrackRecorderTest : public TestWithParam<TrackRecorderTestParams> {
base::TimeTicks timestamp,
bool keyframe));
void OnEncodedVideo(const scoped_refptr<VideoFrame>& video_frame,
- scoped_ptr<std::string> encoded_data,
+ std::unique_ptr<std::string> encoded_data,
base::TimeTicks timestamp,
bool is_key_frame) {
DoOnEncodedVideo(video_frame, *encoded_data, timestamp, is_key_frame);
@@ -113,7 +108,7 @@ class VideoTrackRecorderTest : public TestWithParam<TrackRecorderTestParams> {
MediaStreamVideoTrack* track_;
blink::WebMediaStreamTrack blink_track_;
- scoped_ptr<VideoTrackRecorder> video_track_recorder_;
+ std::unique_ptr<VideoTrackRecorder> video_track_recorder_;
private:
DISALLOW_COPY_AND_ASSIGN(VideoTrackRecorderTest);
@@ -168,18 +163,16 @@ TEST_P(VideoTrackRecorderTest, VideoEncoding) {
run_loop.Run();
- EXPECT_EQ(GetParam().first_encoded_frame_size,
- first_frame_encoded_data.size());
- EXPECT_EQ(GetParam().second_encoded_frame_size,
- second_frame_encoded_data.size());
- EXPECT_EQ(GetParam().third_encoded_frame_size,
- third_frame_encoded_data.size());
+ const size_t kEncodedSizeThreshold = 18;
+ EXPECT_GE(first_frame_encoded_data.size(), kEncodedSizeThreshold);
+ EXPECT_GE(second_frame_encoded_data.size(), kEncodedSizeThreshold);
+ EXPECT_GE(third_frame_encoded_data.size(), kEncodedSizeThreshold);
Mock::VerifyAndClearExpectations(this);
}
INSTANTIATE_TEST_CASE_P(,
VideoTrackRecorderTest,
- ValuesIn(kTrackRecorderTestParams));
+ ValuesIn(kTrackRecorderTestUseVp9OrNot));
} // namespace content
diff --git a/chromium/content/renderer/media/video_track_to_pepper_adapter.cc b/chromium/content/renderer/media/video_track_to_pepper_adapter.cc
index c59155f85db..1b0a2436e34 100644
--- a/chromium/content/renderer/media/video_track_to_pepper_adapter.cc
+++ b/chromium/content/renderer/media/video_track_to_pepper_adapter.cc
@@ -40,13 +40,13 @@ class PpFrameReceiver : public MediaStreamVideoSink {
DCHECK((reader_ && !reader) || (!reader_ && reader))
<< " |reader| = " << reader << ", |reader_| = " << reader_;
if (reader) {
- AddToVideoTrack(this,
- media::BindToCurrentLoop(
- base::Bind(&PpFrameReceiver::OnVideoFrame,
- weak_factory_.GetWeakPtr())),
- track_);
+ MediaStreamVideoSink::ConnectToTrack(
+ track_,
+ media::BindToCurrentLoop(
+ base::Bind(&PpFrameReceiver::OnVideoFrame,
+ weak_factory_.GetWeakPtr())));
} else {
- RemoveFromVideoTrack(this, track_);
+ MediaStreamVideoSink::DisconnectFromTrack();
weak_factory_.InvalidateWeakPtrs();
}
reader_ = reader;
diff --git a/chromium/content/renderer/media/video_track_to_pepper_adapter.h b/chromium/content/renderer/media/video_track_to_pepper_adapter.h
index fc78de97d18..0d8eb0f1f50 100644
--- a/chromium/content/renderer/media/video_track_to_pepper_adapter.h
+++ b/chromium/content/renderer/media/video_track_to_pepper_adapter.h
@@ -6,11 +6,11 @@
#define CONTENT_RENDERER_MEDIA_VIDEO_SOURCE_HANDLER_H_
#include <map>
+#include <memory>
#include <string>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
#include "media/base/video_frame.h"
@@ -56,7 +56,7 @@ class CONTENT_EXPORT VideoTrackToPepperAdapter {
FrameReaderInterface* reader);
~SourceInfo();
- scoped_ptr<PpFrameReceiver> receiver_;
+ std::unique_ptr<PpFrameReceiver> receiver_;
};
typedef std::map<FrameReaderInterface*, SourceInfo*> SourceInfoMap;
diff --git a/chromium/content/renderer/media/video_track_to_pepper_adapter_unittest.cc b/chromium/content/renderer/media/video_track_to_pepper_adapter_unittest.cc
index 9439f602a9c..e1b859a5766 100644
--- a/chromium/content/renderer/media/video_track_to_pepper_adapter_unittest.cc
+++ b/chromium/content/renderer/media/video_track_to_pepper_adapter_unittest.cc
@@ -42,12 +42,12 @@ class VideoTrackToPepperAdapterTest : public ::testing::Test,
}
protected:
- scoped_ptr<VideoTrackToPepperAdapter> handler_;
+ std::unique_ptr<VideoTrackToPepperAdapter> handler_;
// A ChildProcess and a MessageLoop are both needed to fool the Tracks and
// Sources inside |registry_| into believing they are on the right threads.
const ChildProcess child_process_;
const base::MessageLoop message_loop_;
- scoped_ptr<MockMediaStreamRegistry> registry_;
+ std::unique_ptr<MockMediaStreamRegistry> registry_;
};
// Open |handler_| and send a VideoFrame to be received at the other side.
diff --git a/chromium/content/renderer/media/webaudio_capturer_source.cc b/chromium/content/renderer/media/webaudio_capturer_source.cc
index bcebcbb3e24..3fca41942df 100644
--- a/chromium/content/renderer/media/webaudio_capturer_source.cc
+++ b/chromium/content/renderer/media/webaudio_capturer_source.cc
@@ -4,31 +4,36 @@
#include "content/renderer/media/webaudio_capturer_source.h"
+#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/logging.h"
-#include "base/time/time.h"
#include "content/renderer/media/webrtc_local_audio_track.h"
using media::AudioBus;
-using media::AudioFifo;
using media::AudioParameters;
using media::ChannelLayout;
using media::CHANNEL_LAYOUT_MONO;
using media::CHANNEL_LAYOUT_STEREO;
-static const int kMaxNumberOfBuffersInFifo = 5;
-
namespace content {
WebAudioCapturerSource::WebAudioCapturerSource(
- const blink::WebMediaStreamSource& blink_source)
+ blink::WebMediaStreamSource* blink_source)
: track_(NULL),
audio_format_changed_(false),
- blink_source_(blink_source) {
+ fifo_(base::Bind(&WebAudioCapturerSource::DeliverRebufferedAudio,
+ base::Unretained(this))),
+ blink_source_(*blink_source) {
+ DCHECK(blink_source);
+ DCHECK(!blink_source_.isNull());
+ DVLOG(1) << "WebAudioCapturerSource::WebAudioCapturerSource()";
+ blink_source_.addAudioConsumer(this);
}
WebAudioCapturerSource::~WebAudioCapturerSource() {
DCHECK(thread_checker_.CalledOnValidThread());
- removeFromBlinkSource();
+ DVLOG(1) << "WebAudioCapturerSource::~WebAudioCapturerSource()";
+ DeregisterFromBlinkSource();
}
void WebAudioCapturerSource::setFormat(
@@ -48,20 +53,19 @@ void WebAudioCapturerSource::setFormat(
// Set the format used by this WebAudioCapturerSource. We are using 10ms data
// as buffer size since that is the native buffer size of WebRtc packet
// running on.
+ fifo_.Reset(sample_rate / 100);
params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY, channel_layout,
- sample_rate, 16, sample_rate / 100);
+ sample_rate, 16, fifo_.frames_per_buffer());
// Take care of the discrete channel layout case.
params_.set_channels_for_discrete(number_of_channels);
audio_format_changed_ = true;
- wrapper_bus_ = AudioBus::CreateWrapper(params_.channels());
- capture_bus_ = AudioBus::Create(params_);
-
- fifo_.reset(new AudioFifo(
- params_.channels(),
- kMaxNumberOfBuffersInFifo * params_.frames_per_buffer()));
+ if (!wrapper_bus_ ||
+ wrapper_bus_->channels() != static_cast<int>(number_of_channels)) {
+ wrapper_bus_ = AudioBus::CreateWrapper(params_.channels());
+ }
}
void WebAudioCapturerSource::Start(WebRtcLocalAudioTrack* track) {
@@ -77,14 +81,19 @@ void WebAudioCapturerSource::Stop() {
base::AutoLock auto_lock(lock_);
track_ = NULL;
}
- // removeFromBlinkSource() should not be called while |lock_| is acquired,
+ // DeregisterFromBlinkSource() should not be called while |lock_| is acquired,
// as it could result in a deadlock.
- removeFromBlinkSource();
+ DeregisterFromBlinkSource();
}
void WebAudioCapturerSource::consumeAudio(
const blink::WebVector<const float*>& audio_data,
size_t number_of_frames) {
+ // TODO(miu): Plumbing is needed to determine the actual capture timestamp
+ // of the audio, instead of just snapshotting TimeTicks::Now(), for proper
+ // audio/video sync. http://crbug.com/335335
+ current_reference_time_ = base::TimeTicks::Now();
+
base::AutoLock auto_lock(lock_);
if (!track_)
return;
@@ -96,44 +105,28 @@ void WebAudioCapturerSource::consumeAudio(
}
wrapper_bus_->set_frames(number_of_frames);
-
- // Make sure WebKit is honoring what it told us up front
- // about the channels.
DCHECK_EQ(params_.channels(), static_cast<int>(audio_data.size()));
-
for (size_t i = 0; i < audio_data.size(); ++i)
wrapper_bus_->SetChannelData(i, const_cast<float*>(audio_data[i]));
- // Handle mismatch between WebAudio buffer-size and WebRTC.
- int available = fifo_->max_frames() - fifo_->frames();
- if (available < static_cast<int>(number_of_frames)) {
- NOTREACHED() << "WebAudioCapturerSource::Consume() : FIFO overrun.";
- return;
- }
-
- // Compute the estimated capture time of the first sample frame of audio that
- // will be consumed from the FIFO in the loop below.
- base::TimeTicks estimated_capture_time = base::TimeTicks::Now() -
- fifo_->frames() * base::TimeDelta::FromSeconds(1) / params_.sample_rate();
-
- fifo_->Push(wrapper_bus_.get());
- while (fifo_->frames() >= capture_bus_->frames()) {
- fifo_->Consume(capture_bus_.get(), 0, capture_bus_->frames());
- track_->Capture(*capture_bus_, estimated_capture_time, false);
+ // The following will result in zero, one, or multiple synchronous calls to
+ // DeliverRebufferedAudio().
+ fifo_.Push(*wrapper_bus_);
+}
- // Advance the estimated capture time for the next FIFO consume operation.
- estimated_capture_time +=
- capture_bus_->frames() * base::TimeDelta::FromSeconds(1) /
- params_.sample_rate();
- }
+void WebAudioCapturerSource::DeliverRebufferedAudio(
+ const media::AudioBus& audio_bus,
+ int frame_delay) {
+ lock_.AssertAcquired();
+ const base::TimeTicks reference_time =
+ current_reference_time_ +
+ base::TimeDelta::FromMicroseconds(frame_delay *
+ base::Time::kMicrosecondsPerSecond /
+ params_.sample_rate());
+ track_->Capture(audio_bus, reference_time);
}
-// If registered as audio consumer in |blink_source_|, deregister from
-// |blink_source_| and stop keeping a reference to |blink_source_|.
-// Failure to call this method when stopping the track might leave an invalid
-// WebAudioCapturerSource reference still registered as an audio consumer on
-// the blink side.
-void WebAudioCapturerSource::removeFromBlinkSource() {
+void WebAudioCapturerSource::DeregisterFromBlinkSource() {
if (!blink_source_.isNull()) {
blink_source_.removeAudioConsumer(this);
blink_source_.reset();
diff --git a/chromium/content/renderer/media/webaudio_capturer_source.h b/chromium/content/renderer/media/webaudio_capturer_source.h
index b0ee262ccd7..3063aeec9af 100644
--- a/chromium/content/renderer/media/webaudio_capturer_source.h
+++ b/chromium/content/renderer/media/webaudio_capturer_source.h
@@ -8,12 +8,13 @@
#include <stddef.h>
#include "base/macros.h"
-#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
+#include "base/time/time.h"
#include "media/audio/audio_parameters.h"
+#include "media/base/audio_bus.h"
#include "media/base/audio_capturer_source.h"
-#include "media/base/audio_fifo.h"
+#include "media/base/audio_push_fifo.h"
#include "third_party/WebKit/public/platform/WebAudioDestinationConsumer.h"
#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
#include "third_party/WebKit/public/platform/WebVector.h"
@@ -29,12 +30,11 @@ class WebRtcLocalAudioTrack;
// (channels, and sample-rate).
// 2. consumeAudio() is called periodically by WebKit which dispatches the
// audio stream to the WebRtcLocalAudioTrack::Capture() method.
-class WebAudioCapturerSource
- : public base::RefCountedThreadSafe<WebAudioCapturerSource>,
- public blink::WebAudioDestinationConsumer {
+class WebAudioCapturerSource : public blink::WebAudioDestinationConsumer {
public:
- explicit WebAudioCapturerSource(
- const blink::WebMediaStreamSource& blink_source);
+ explicit WebAudioCapturerSource(blink::WebMediaStreamSource* blink_source);
+
+ ~WebAudioCapturerSource() override;
// WebAudioDestinationConsumer implementation.
// setFormat() is called early on, so that we can configure the audio track.
@@ -45,29 +45,27 @@ class WebAudioCapturerSource
size_t number_of_frames) override;
// Called when the WebAudioCapturerSource is hooking to a media audio track.
- // |track| is the sink of the data flow. |source_provider| is the source of
- // the data flow where stream information like delay, volume, key_pressed,
- // is stored.
+ // |track| is the sink of the data flow and must remain alive until Stop() is
+ // called.
void Start(WebRtcLocalAudioTrack* track);
// Called when the media audio track is stopping.
void Stop();
- protected:
- friend class base::RefCountedThreadSafe<WebAudioCapturerSource>;
- ~WebAudioCapturerSource() override;
-
private:
- // Removes this object from a blink::WebMediaStreamSource with which it
- // might be registered. The goal is to avoid dangling pointers.
- void removeFromBlinkSource();
+ // Called by AudioPushFifo zero or more times during the call to
+ // consumeAudio(). Delivers audio data with the required buffer size to the
+ // track.
+ void DeliverRebufferedAudio(const media::AudioBus& audio_bus,
+ int frame_delay);
+
+ // Deregisters this object from its blink::WebMediaStreamSource.
+ void DeregisterFromBlinkSource();
// Used to DCHECK that some methods are called on the correct thread.
base::ThreadChecker thread_checker_;
// The audio track this WebAudioCapturerSource is feeding data to.
- // WebRtcLocalAudioTrack is reference counted, and owning this object.
- // To avoid circular reference, a raw pointer is kept here.
WebRtcLocalAudioTrack* track_;
media::AudioParameters params_;
@@ -75,14 +73,18 @@ class WebAudioCapturerSource
// Flag to help notify the |track_| when the audio format has changed.
bool audio_format_changed_;
- // Wraps data coming from HandleCapture().
- scoped_ptr<media::AudioBus> wrapper_bus_;
+ // A wrapper used for providing audio to |fifo_|.
+ std::unique_ptr<media::AudioBus> wrapper_bus_;
- // Bus for reading from FIFO and calling the CaptureCallback.
- scoped_ptr<media::AudioBus> capture_bus_;
+ // Takes in the audio data passed to consumeAudio() and re-buffers it into 10
+ // ms chunks for the track. This ensures each chunk of audio delivered to the
+ // track has the required buffer size, regardless of the amount of audio
+ // provided via each consumeAudio() call.
+ media::AudioPushFifo fifo_;
- // Handles mismatch between WebAudio buffer size and WebRTC.
- scoped_ptr<media::AudioFifo> fifo_;
+ // Used to pass the reference timestamp between DeliverDecodedAudio() and
+ // DeliverRebufferedAudio().
+ base::TimeTicks current_reference_time_;
// Synchronizes HandleCapture() with AudioCapturerSource calls.
base::Lock lock_;
diff --git a/chromium/content/renderer/media/webmediaplayer_ms.cc b/chromium/content/renderer/media/webmediaplayer_ms.cc
index e302d9dcd93..f362c514618 100644
--- a/chromium/content/renderer/media/webmediaplayer_ms.cc
+++ b/chromium/content/renderer/media/webmediaplayer_ms.cc
@@ -22,9 +22,9 @@
#include "content/renderer/media/webmediaplayer_ms_compositor.h"
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_thread_impl.h"
-#include "gpu/blink/webgraphicscontext3d_impl.h"
#include "media/base/media_log.h"
#include "media/base/video_frame.h"
+#include "media/blink/webmediaplayer_util.h"
#include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
#include "third_party/WebKit/public/platform/WebRect.h"
#include "third_party/WebKit/public/platform/WebSize.h"
@@ -32,31 +32,25 @@
namespace content {
-namespace {
-
-static const float DEFAULT_AUDIO_VOLUME = 1.0f;
-
-} // anonymous namespace
-
WebMediaPlayerMS::WebMediaPlayerMS(
blink::WebFrame* frame,
blink::WebMediaPlayerClient* client,
base::WeakPtr<media::WebMediaPlayerDelegate> delegate,
media::MediaLog* media_log,
- scoped_ptr<MediaStreamRendererFactory> factory,
+ std::unique_ptr<MediaStreamRendererFactory> factory,
const scoped_refptr<base::SingleThreadTaskRunner>& compositor_task_runner,
const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
const scoped_refptr<base::TaskRunner>& worker_task_runner,
media::GpuVideoAcceleratorFactories* gpu_factories,
const blink::WebString& sink_id,
const blink::WebSecurityOrigin& security_origin)
- : RenderFrameObserver(RenderFrame::FromWebFrame(frame)),
- frame_(frame),
+ : frame_(frame),
network_state_(WebMediaPlayer::NetworkStateEmpty),
ready_state_(WebMediaPlayer::ReadyStateHaveNothing),
buffered_(static_cast<size_t>(0)),
client_(client),
delegate_(delegate),
+ delegate_id_(0),
paused_(true),
render_frame_suspended_(false),
received_first_frame_(false),
@@ -69,9 +63,15 @@ WebMediaPlayerMS::WebMediaPlayerMS(
initial_audio_output_device_id_(sink_id.utf8()),
initial_security_origin_(security_origin.isNull()
? url::Origin()
- : url::Origin(security_origin)) {
+ : url::Origin(security_origin)),
+ volume_(1.0),
+ volume_multiplier_(1.0),
+ should_play_upon_shown_(false) {
DVLOG(1) << __FUNCTION__;
DCHECK(client);
+ if (delegate_)
+ delegate_id_ = delegate_->AddObserver(this);
+
media_log_->AddEvent(
media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_CREATED));
}
@@ -94,8 +94,10 @@ WebMediaPlayerMS::~WebMediaPlayerMS() {
media_log_->AddEvent(
media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_DESTROYED));
- if (delegate_.get())
- delegate_->PlayerGone(this);
+ if (delegate_) {
+ delegate_->PlayerGone(delegate_id_);
+ delegate_->RemoveObserver(delegate_id_);
+ }
}
void WebMediaPlayerMS::load(LoadType load_type,
@@ -126,6 +128,9 @@ void WebMediaPlayerMS::load(LoadType load_type,
RenderFrame* const frame = RenderFrame::FromWebFrame(frame_);
if (frame) {
+ // Report UMA and RAPPOR metrics.
+ media::ReportMetrics(load_type, GURL(url), frame_->getSecurityOrigin());
+
audio_renderer_ = renderer_factory_->GetAudioRenderer(
url, frame->GetRoutingID(), initial_audio_output_device_id_,
initial_security_origin_);
@@ -137,7 +142,7 @@ void WebMediaPlayerMS::load(LoadType load_type,
}
if (audio_renderer_) {
- audio_renderer_->SetVolume(DEFAULT_AUDIO_VOLUME);
+ audio_renderer_->SetVolume(volume_);
audio_renderer_->Start();
}
if (video_frame_provider_)
@@ -152,45 +157,53 @@ void WebMediaPlayerMS::load(LoadType load_type,
void WebMediaPlayerMS::play() {
DVLOG(1) << __FUNCTION__;
DCHECK(thread_checker_.CalledOnValidThread());
- if (paused_) {
- if (video_frame_provider_.get())
- video_frame_provider_->Play();
- compositor_->StartRendering();
+ media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PLAY));
+ if (!paused_)
+ return;
- if (audio_renderer_.get())
- audio_renderer_->Play();
+ if (video_frame_provider_)
+ video_frame_provider_->Play();
+
+ compositor_->StartRendering();
- if (delegate_.get())
- delegate_->DidPlay(this);
+ if (audio_renderer_)
+ audio_renderer_->Play();
+
+ if (delegate_) {
+ // TODO(perkj, magjed): We send a duration of 1 second here to avoid
+ // creating an interactive media session on Android. We'd like to use zero
+ // here, but that is treated as an unknown duration and assumed to be
+ // interactive. See http://crbug.com/595297 for more details.
+ delegate_->DidPlay(delegate_id_, hasVideo(), hasAudio(), false,
+ base::TimeDelta::FromSeconds(1));
}
paused_ = false;
-
- media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PLAY));
}
void WebMediaPlayerMS::pause() {
DVLOG(1) << __FUNCTION__;
DCHECK(thread_checker_.CalledOnValidThread());
- if (video_frame_provider_.get())
+ should_play_upon_shown_ = false;
+ media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PAUSE));
+ if (paused_)
+ return;
+
+ if (video_frame_provider_)
video_frame_provider_->Pause();
compositor_->StopRendering();
compositor_->ReplaceCurrentFrameWithACopy();
- if (!paused_) {
- if (audio_renderer_.get())
- audio_renderer_->Pause();
+ if (audio_renderer_)
+ audio_renderer_->Pause();
- if (delegate_.get())
- delegate_->DidPause(this);
- }
+ if (delegate_)
+ delegate_->DidPause(delegate_id_, false);
paused_ = true;
-
- media_log_->AddEvent(media_log_->CreateEvent(media::MediaLogEvent::PAUSE));
}
bool WebMediaPlayerMS::supportsSave() const {
@@ -209,8 +222,9 @@ void WebMediaPlayerMS::setRate(double rate) {
void WebMediaPlayerMS::setVolume(double volume) {
DVLOG(1) << __FUNCTION__ << "(volume=" << volume << ")";
DCHECK(thread_checker_.CalledOnValidThread());
+ volume_ = volume;
if (audio_renderer_.get())
- audio_renderer_->SetVolume(volume);
+ audio_renderer_->SetVolume(volume_ * volume_multiplier_);
}
void WebMediaPlayerMS::setSinkId(
@@ -219,11 +233,11 @@ void WebMediaPlayerMS::setSinkId(
blink::WebSetSinkIdCallbacks* web_callback) {
DVLOG(1) << __FUNCTION__;
DCHECK(thread_checker_.CalledOnValidThread());
- const media::SwitchOutputDeviceCB callback =
- media::ConvertToSwitchOutputDeviceCB(web_callback);
- if (audio_renderer_ && audio_renderer_->GetOutputDevice()) {
- audio_renderer_->GetOutputDevice()->SwitchOutputDevice(
- sink_id.utf8(), security_origin, callback);
+ const media::OutputDeviceStatusCB callback =
+ media::ConvertToOutputDeviceStatusCB(web_callback);
+ if (audio_renderer_) {
+ audio_renderer_->SwitchOutputDevice(sink_id.utf8(), security_origin,
+ callback);
} else {
callback.Run(media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL);
}
@@ -273,18 +287,22 @@ double WebMediaPlayerMS::currentTime() const {
return 0.0;
}
-blink::WebMediaPlayer::NetworkState WebMediaPlayerMS::networkState() const {
+blink::WebMediaPlayer::NetworkState WebMediaPlayerMS::getNetworkState() const {
DVLOG(1) << __FUNCTION__ << ", state:" << network_state_;
DCHECK(thread_checker_.CalledOnValidThread());
return network_state_;
}
-blink::WebMediaPlayer::ReadyState WebMediaPlayerMS::readyState() const {
+blink::WebMediaPlayer::ReadyState WebMediaPlayerMS::getReadyState() const {
DVLOG(1) << __FUNCTION__ << ", state:" << ready_state_;
DCHECK(thread_checker_.CalledOnValidThread());
return ready_state_;
}
+blink::WebString WebMediaPlayerMS::getErrorMessage() {
+ return blink::WebString::fromUTF8(media_log_->GetLastErrorMessage());
+}
+
blink::WebTimeRanges WebMediaPlayerMS::buffered() const {
DCHECK(thread_checker_.CalledOnValidThread());
return buffered_;
@@ -348,42 +366,81 @@ unsigned WebMediaPlayerMS::droppedFrameCount() const {
return compositor_->dropped_frame_count();
}
-unsigned WebMediaPlayerMS::audioDecodedByteCount() const {
+size_t WebMediaPlayerMS::audioDecodedByteCount() const {
DCHECK(thread_checker_.CalledOnValidThread());
NOTIMPLEMENTED();
return 0;
}
-unsigned WebMediaPlayerMS::videoDecodedByteCount() const {
+size_t WebMediaPlayerMS::videoDecodedByteCount() const {
DCHECK(thread_checker_.CalledOnValidThread());
NOTIMPLEMENTED();
return 0;
}
-void WebMediaPlayerMS::WasHidden() {
+void WebMediaPlayerMS::OnHidden() {
#if defined(OS_ANDROID)
DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(!render_frame_suspended_);
// Method called when the RenderFrame is sent to background and suspended
// (android). Substitute the displayed VideoFrame with a copy to avoid
// holding on to it unnecessarily.
- render_frame_suspended_=true;
+ //
+ // During undoable tab closures OnHidden() may be called back to back, so we
+ // can't rely on |render_frame_suspended_| being false here.
+
+ render_frame_suspended_ = true;
if (!paused_)
compositor_->ReplaceCurrentFrameWithACopy();
#endif // defined(OS_ANDROID)
}
-void WebMediaPlayerMS::WasShown() {
+void WebMediaPlayerMS::OnShown() {
#if defined(OS_ANDROID)
DCHECK(thread_checker_.CalledOnValidThread());
render_frame_suspended_ = false;
+
+ // Resume playback on visibility. play() clears |should_play_upon_shown_|.
+ if (should_play_upon_shown_)
+ play();
#endif // defined(OS_ANDROID)
}
+void WebMediaPlayerMS::OnSuspendRequested(bool must_suspend) {
+#if defined(OS_ANDROID)
+ if (!must_suspend)
+ return;
+
+ if (!paused_) {
+ pause();
+ should_play_upon_shown_ = true;
+ }
+
+ if (delegate_)
+ delegate_->PlayerGone(delegate_id_);
+
+ render_frame_suspended_ = true;
+#endif
+}
+
+void WebMediaPlayerMS::OnPlay() {
+ // TODO(perkj, magjed): It's not clear how WebRTC should work with an
+ // MediaSession, until these issues are resolved, disable session controls.
+ // http://crbug.com/595297.
+}
+
+void WebMediaPlayerMS::OnPause() {
+ // TODO(perkj, magjed): See TODO in Onplay().
+}
+
+void WebMediaPlayerMS::OnVolumeMultiplierUpdate(double multiplier) {
+ volume_multiplier_ = multiplier;
+ setVolume(volume_);
+}
+
bool WebMediaPlayerMS::copyVideoTextureToPlatformTexture(
- blink::WebGraphicsContext3D* web_graphics_context,
+ gpu::gles2::GLES2Interface* gl,
unsigned int texture,
unsigned int internal_format,
unsigned int type,
@@ -394,16 +451,11 @@ bool WebMediaPlayerMS::copyVideoTextureToPlatformTexture(
scoped_refptr<media::VideoFrame> video_frame = compositor_->GetCurrentFrame();
- if (!video_frame.get() || video_frame->HasTextures() ||
+ if (!video_frame.get() || !video_frame->HasTextures() ||
media::VideoFrame::NumPlanes(video_frame->format()) != 1) {
return false;
}
- // TODO(dshwang): need more elegant way to convert WebGraphicsContext3D to
- // GLES2Interface.
- gpu::gles2::GLES2Interface* const gl =
- static_cast<gpu_blink::WebGraphicsContext3DImpl*>(web_graphics_context)
- ->GetGLInterface();
media::SkCanvasVideoRenderer::CopyVideoFrameSingleTextureToGLTexture(
gl, video_frame.get(), texture, internal_format, type, premultiply_alpha,
flip_y);
@@ -434,23 +486,14 @@ void WebMediaPlayerMS::OnFrameAvailable(
if (video_frame_provider_.get()) {
video_weblayer_.reset(new cc_blink::WebLayerImpl(
- cc::VideoLayer::Create(cc_blink::WebLayerImpl::LayerSettings(),
- compositor_.get(), media::VIDEO_ROTATION_0)));
- video_weblayer_->layer()->SetContentsOpaque(true);
+ cc::VideoLayer::Create(compositor_.get(), media::VIDEO_ROTATION_0)));
+ video_weblayer_->layer()->SetContentsOpaque(false);
video_weblayer_->SetContentsOpaqueIsFixed(true);
get_client()->setWebLayer(video_weblayer_.get());
}
}
- // As EnqueueFrame can potentially change |current_frame_|, we need to do
- // the size change check before it. Otherwise, we are running the risk of not
- // detecting a size change event.
- const bool size_changed =
- compositor_->GetCurrentSize() != frame->natural_size();
-
compositor_->EnqueueFrame(frame);
- if (size_changed)
- get_client()->sizeChanged();
}
void WebMediaPlayerMS::RepaintInternal() {
@@ -488,4 +531,8 @@ void WebMediaPlayerMS::ResetCanvasCache() {
video_renderer_.ResetCache();
}
+void WebMediaPlayerMS::TriggerResize() {
+ get_client()->sizeChanged();
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/webmediaplayer_ms.h b/chromium/content/renderer/media/webmediaplayer_ms.h
index 24b2d6b6b2c..e58892d05bf 100644
--- a/chromium/content/renderer/media/webmediaplayer_ms.h
+++ b/chromium/content/renderer/media/webmediaplayer_ms.h
@@ -5,15 +5,15 @@
#ifndef CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_MS_H_
#define CONTENT_RENDERER_MEDIA_WEBMEDIAPLAYER_MS_H_
+#include <memory>
#include <string>
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
-#include "content/public/renderer/render_frame_observer.h"
+#include "media/blink/webmediaplayer_delegate.h"
#include "media/blink/webmediaplayer_util.h"
#include "media/renderers/gpu_video_accelerator_factories.h"
#include "media/renderers/skcanvas_video_renderer.h"
@@ -22,7 +22,6 @@
namespace blink {
class WebFrame;
-class WebGraphicsContext3D;
class WebMediaPlayerClient;
class WebSecurityOrigin;
class WebString;
@@ -30,7 +29,6 @@ class WebString;
namespace media {
class MediaLog;
-class WebMediaPlayerDelegate;
class VideoFrame;
}
@@ -38,6 +36,12 @@ namespace cc_blink {
class WebLayerImpl;
}
+namespace gpu {
+namespace gles2 {
+class GLES2Interface;
+}
+}
+
namespace content {
class MediaStreamAudioRenderer;
class MediaStreamRendererFactory;
@@ -60,8 +64,8 @@ class RenderFrameObserver;
// WebKit client of this media player object.
class CONTENT_EXPORT WebMediaPlayerMS
: public NON_EXPORTED_BASE(blink::WebMediaPlayer),
- public NON_EXPORTED_BASE(base::SupportsWeakPtr<WebMediaPlayerMS>),
- public NON_EXPORTED_BASE(RenderFrameObserver) {
+ public NON_EXPORTED_BASE(media::WebMediaPlayerDelegate::Observer),
+ public NON_EXPORTED_BASE(base::SupportsWeakPtr<WebMediaPlayerMS>) {
public:
// Construct a WebMediaPlayerMS with reference to the client, and
// a MediaStreamClient which provides VideoFrameProvider.
@@ -70,7 +74,7 @@ class CONTENT_EXPORT WebMediaPlayerMS
blink::WebMediaPlayerClient* client,
base::WeakPtr<media::WebMediaPlayerDelegate> delegate,
media::MediaLog* media_log,
- scoped_ptr<MediaStreamRendererFactory> factory,
+ std::unique_ptr<MediaStreamRendererFactory> factory,
const scoped_refptr<base::SingleThreadTaskRunner>& compositor_task_runner,
const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner,
const scoped_refptr<base::TaskRunner>& worker_task_runner,
@@ -106,6 +110,9 @@ class CONTENT_EXPORT WebMediaPlayerMS
media::SkCanvasVideoRenderer* GetSkCanvasVideoRenderer();
void ResetCanvasCache();
+ // Methods to trigger resize event.
+ void TriggerResize();
+
// True if the loaded media has a playable video/audio track.
bool hasVideo() const override;
bool hasAudio() const override;
@@ -120,9 +127,10 @@ class CONTENT_EXPORT WebMediaPlayerMS
double currentTime() const override;
// Internal states of loading and network.
- blink::WebMediaPlayer::NetworkState networkState() const override;
- blink::WebMediaPlayer::ReadyState readyState() const override;
+ blink::WebMediaPlayer::NetworkState getNetworkState() const override;
+ blink::WebMediaPlayer::ReadyState getReadyState() const override;
+ blink::WebString getErrorMessage() override;
bool didLoadingProgress() override;
bool hasSingleSecurityOrigin() const override;
@@ -132,21 +140,23 @@ class CONTENT_EXPORT WebMediaPlayerMS
unsigned decodedFrameCount() const override;
unsigned droppedFrameCount() const override;
- unsigned audioDecodedByteCount() const override;
- unsigned videoDecodedByteCount() const override;
-
- // RenderFrameObserver implementation. Called when the RenderFrame visiblity
- // is changed.
- void WasHidden() override;
- void WasShown() override;
-
- bool copyVideoTextureToPlatformTexture(
- blink::WebGraphicsContext3D* web_graphics_context,
- unsigned int texture,
- unsigned int internal_format,
- unsigned int type,
- bool premultiply_alpha,
- bool flip_y) override;
+ size_t audioDecodedByteCount() const override;
+ size_t videoDecodedByteCount() const override;
+
+ // WebMediaPlayerDelegate::Observer implementation.
+ void OnHidden() override;
+ void OnShown() override;
+ void OnSuspendRequested(bool must_suspend) override;
+ void OnPlay() override;
+ void OnPause() override;
+ void OnVolumeMultiplierUpdate(double multiplier) override;
+
+ bool copyVideoTextureToPlatformTexture(gpu::gles2::GLES2Interface* gl,
+ unsigned int texture,
+ unsigned int internal_format,
+ unsigned int type,
+ bool premultiply_alpha,
+ bool flip_y) override;
private:
friend class WebMediaPlayerMSTest;
@@ -176,12 +186,17 @@ class CONTENT_EXPORT WebMediaPlayerMS
blink::WebMediaPlayerClient* const client_;
+ // WebMediaPlayer notifies the |delegate_| of playback state changes using
+ // |delegate_id_|; an id provided after registering with the delegate. The
+ // WebMediaPlayer may also receive directives (play, pause) from the delegate
+ // via the WebMediaPlayerDelegate::Observer interface after registration.
const base::WeakPtr<media::WebMediaPlayerDelegate> delegate_;
+ int delegate_id_;
// Specify content:: to disambiguate from cc::.
scoped_refptr<content::VideoFrameProvider> video_frame_provider_; // Weak
- scoped_ptr<cc_blink::WebLayerImpl> video_weblayer_;
+ std::unique_ptr<cc_blink::WebLayerImpl> video_weblayer_;
scoped_refptr<MediaStreamAudioRenderer> audio_renderer_; // Weak
media::SkCanvasVideoRenderer video_renderer_;
@@ -192,7 +207,7 @@ class CONTENT_EXPORT WebMediaPlayerMS
scoped_refptr<media::MediaLog> media_log_;
- scoped_ptr<MediaStreamRendererFactory> renderer_factory_;
+ std::unique_ptr<MediaStreamRendererFactory> renderer_factory_;
const scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
const scoped_refptr<base::TaskRunner> worker_task_runner_;
@@ -203,13 +218,24 @@ class CONTENT_EXPORT WebMediaPlayerMS
// WebMediaPlayerMS owns |compositor_| and destroys it on
// |compositor_task_runner_|.
- scoped_ptr<WebMediaPlayerMSCompositor> compositor_;
+ std::unique_ptr<WebMediaPlayerMSCompositor> compositor_;
const scoped_refptr<base::SingleThreadTaskRunner> compositor_task_runner_;
const std::string initial_audio_output_device_id_;
const url::Origin initial_security_origin_;
+ // The last volume received by setVolume() and the last volume multiplier from
+ // OnVolumeMultiplierUpdate(). The multiplier is typical 1.0, but may be less
+ // if the WebMediaPlayerDelegate has requested a volume reduction (ducking)
+ // for a transient sound. Playout volume is derived by volume * multiplier.
+ double volume_;
+ double volume_multiplier_;
+
+ // True if playback should be started upon the next call to OnShown(). Only
+ // used on Android.
+ bool should_play_upon_shown_;
+
DISALLOW_COPY_AND_ASSIGN(WebMediaPlayerMS);
};
diff --git a/chromium/content/renderer/media/webmediaplayer_ms_compositor.cc b/chromium/content/renderer/media/webmediaplayer_ms_compositor.cc
index 166d436ba64..36613d9cf22 100644
--- a/chromium/content/renderer/media/webmediaplayer_ms_compositor.cc
+++ b/chromium/content/renderer/media/webmediaplayer_ms_compositor.cc
@@ -9,6 +9,7 @@
#include "base/command_line.h"
#include "base/hash.h"
#include "base/single_thread_task_runner.h"
+#include "base/values.h"
#include "cc/blink/context_provider_web_context.h"
#include "content/renderer/media/webmediaplayer_ms.h"
#include "content/renderer/render_thread_impl.h"
@@ -30,21 +31,22 @@ namespace content {
namespace {
-// This function copies |frame| to a new I420 media::VideoFrame.
-scoped_refptr<media::VideoFrame> CopyFrameToI420(
+// This function copies |frame| to a new I420 or YV12A media::VideoFrame.
+scoped_refptr<media::VideoFrame> CopyFrame(
const scoped_refptr<media::VideoFrame>& frame,
media::SkCanvasVideoRenderer* video_renderer) {
- const scoped_refptr<media::VideoFrame> new_frame =
- media::VideoFrame::CreateFrame(media::PIXEL_FORMAT_YV12,
- frame->coded_size(), frame->visible_rect(),
- frame->natural_size(), frame->timestamp());
+ scoped_refptr<media::VideoFrame> new_frame;
const gfx::Size& size = frame->coded_size();
if (frame->HasTextures()) {
DCHECK(frame->format() == media::PIXEL_FORMAT_ARGB ||
frame->format() == media::PIXEL_FORMAT_XRGB ||
frame->format() == media::PIXEL_FORMAT_I420 ||
- frame->format() == media::PIXEL_FORMAT_UYVY);
+ frame->format() == media::PIXEL_FORMAT_UYVY ||
+ frame->format() == media::PIXEL_FORMAT_NV12);
+ new_frame = media::VideoFrame::CreateFrame(
+ media::PIXEL_FORMAT_I420, frame->coded_size(), frame->visible_rect(),
+ frame->natural_size(), frame->timestamp());
SkBitmap bitmap;
bitmap.allocN32Pixels(frame->visible_rect().width(),
frame->visible_rect().height());
@@ -73,7 +75,13 @@ scoped_refptr<media::VideoFrame> CopyFrameToI420(
} else {
DCHECK(frame->IsMappable());
DCHECK(frame->format() == media::PIXEL_FORMAT_YV12 ||
+ frame->format() == media::PIXEL_FORMAT_YV12A ||
frame->format() == media::PIXEL_FORMAT_I420);
+ new_frame = media::VideoFrame::CreateFrame(
+ media::IsOpaque(frame->format()) ? media::PIXEL_FORMAT_I420
+ : media::PIXEL_FORMAT_YV12A,
+ frame->coded_size(), frame->visible_rect(), frame->natural_size(),
+ frame->timestamp());
libyuv::I420Copy(frame->data(media::VideoFrame::kYPlane),
frame->stride(media::VideoFrame::kYPlane),
frame->data(media::VideoFrame::kUPlane),
@@ -87,7 +95,20 @@ scoped_refptr<media::VideoFrame> CopyFrameToI420(
new_frame->data(media::VideoFrame::kVPlane),
new_frame->stride(media::VideoFrame::kVPlane),
size.width(), size.height());
+ if (frame->format() == media::PIXEL_FORMAT_YV12A) {
+ libyuv::CopyPlane(frame->data(media::VideoFrame::kAPlane),
+ frame->stride(media::VideoFrame::kAPlane),
+ new_frame->data(media::VideoFrame::kAPlane),
+ new_frame->stride(media::VideoFrame::kAPlane),
+ size.width(),
+ size.height());
+ }
}
+
+ // Transfer metadata keys.
+ base::DictionaryValue original_metadata;
+ frame->metadata()->MergeInternalValuesInto(&original_metadata);
+ new_frame->metadata()->MergeInternalValuesFrom(original_metadata);
return new_frame;
}
@@ -178,6 +199,7 @@ void WebMediaPlayerMSCompositor::EnqueueFrame(
base::AutoLock auto_lock(current_frame_lock_);
++total_frame_count_;
+ // With algorithm off, just let |current_frame_| hold the incoming |frame|.
if (!rendering_frame_buffer_) {
SetCurrentFrame(frame);
return;
@@ -193,6 +215,9 @@ void WebMediaPlayerMSCompositor::EnqueueFrame(
return;
}
+ // If we detect a bad frame without |render_time|, we switch off algorithm,
+ // because without |render_time|, algorithm cannot work.
+ // In general, this should not happen.
base::TimeTicks render_time;
if (!frame->metadata()->GetTimeTicks(
media::VideoFrameMetadata::REFERENCE_TIME, &render_time)) {
@@ -204,20 +229,25 @@ void WebMediaPlayerMSCompositor::EnqueueFrame(
return;
}
- timestamps_to_clock_times_[frame->timestamp()] = render_time;
-
- rendering_frame_buffer_->EnqueueFrame(frame);
-
+ // The code below handles the case where UpdateCurrentFrame() callbacks stop.
+ // These callbacks can stop when the tab is hidden or the page area containing
+ // the video frame is scrolled out of view.
+ // Since some hardware decoders only have a limited number of output frames,
+ // we must aggressively release frames in this case.
const base::TimeTicks now = base::TimeTicks::Now();
- if (now <= last_deadline_max_)
- return;
-
- // This shows vsyncs stops rendering frames. A probable cause is that the
- // tab is not in the front. But we still have to let old frames go.
- const base::TimeTicks deadline_max =
- std::max(now, last_deadline_max_ + last_render_length_);
+ if (now > last_deadline_max_) {
+ // Note: the frame in |rendering_frame_buffer_| with lowest index is the
+ // same as |current_frame_|. Function SetCurrentFrame() handles whether
+ // to increase |dropped_frame_count_| for that frame, so here we should
+ // increase |dropped_frame_count_| by the count of all other frames.
+ dropped_frame_count_ += rendering_frame_buffer_->frames_queued() - 1;
+ rendering_frame_buffer_->Reset();
+ timestamps_to_clock_times_.clear();
+ SetCurrentFrame(frame);
+ }
- Render(deadline_max - last_render_length_, deadline_max);
+ timestamps_to_clock_times_[frame->timestamp()] = render_time;
+ rendering_frame_buffer_->EnqueueFrame(frame);
}
bool WebMediaPlayerMSCompositor::UpdateCurrentFrame(
@@ -320,7 +350,7 @@ void WebMediaPlayerMSCompositor::ReplaceCurrentFrameWithACopy() {
// there might be a finite number of available buffers. E.g, video that
// originates from a video camera.
current_frame_ =
- CopyFrameToI420(current_frame_, player_->GetSkCanvasVideoRenderer());
+ CopyFrame(current_frame_, player_->GetSkCanvasVideoRenderer());
}
bool WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks(
@@ -368,10 +398,19 @@ void WebMediaPlayerMSCompositor::Render(base::TimeTicks deadline_min,
void WebMediaPlayerMSCompositor::SetCurrentFrame(
const scoped_refptr<media::VideoFrame>& frame) {
current_frame_lock_.AssertAcquired();
+
if (!current_frame_used_by_compositor_)
++dropped_frame_count_;
current_frame_used_by_compositor_ = false;
+
+ const bool size_changed =
+ !current_frame_ ||
+ current_frame_->natural_size() != frame->natural_size();
current_frame_ = frame;
+ if (size_changed) {
+ main_message_loop_->PostTask(
+ FROM_HERE, base::Bind(&WebMediaPlayerMS::TriggerResize, player_));
+ }
main_message_loop_->PostTask(
FROM_HERE, base::Bind(&WebMediaPlayerMS::ResetCanvasCache, player_));
}
diff --git a/chromium/content/renderer/media/webmediaplayer_ms_compositor.h b/chromium/content/renderer/media/webmediaplayer_ms_compositor.h
index baed21e5f53..5c2c4d1975b 100644
--- a/chromium/content/renderer/media/webmediaplayer_ms_compositor.h
+++ b/chromium/content/renderer/media/webmediaplayer_ms_compositor.h
@@ -8,9 +8,9 @@
#include <stddef.h>
#include <map>
+#include <memory>
#include <vector>
-#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/synchronization/lock.h"
@@ -125,7 +125,7 @@ class CONTENT_EXPORT WebMediaPlayerMSCompositor
// |rendering_frame_buffer_| stores the incoming frames, and provides a frame
// selection method which returns the best frame for the render interval.
- scoped_ptr<media::VideoRendererAlgorithm> rendering_frame_buffer_;
+ std::unique_ptr<media::VideoRendererAlgorithm> rendering_frame_buffer_;
// |current_frame_used_by_compositor_| is updated on compositor thread only.
// It's used to track whether |current_frame_| was painted for detecting
diff --git a/chromium/content/renderer/media/webmediaplayer_ms_unittest.cc b/chromium/content/renderer/media/webmediaplayer_ms_unittest.cc
index af4cf20d104..d930ddc740e 100644
--- a/chromium/content/renderer/media/webmediaplayer_ms_unittest.cc
+++ b/chromium/content/renderer/media/webmediaplayer_ms_unittest.cc
@@ -24,6 +24,63 @@ enum class FrameType {
using TestFrame = std::pair<FrameType, scoped_refptr<media::VideoFrame>>;
+class FakeWebMediaPlayerDelegate
+ : public media::WebMediaPlayerDelegate,
+ public base::SupportsWeakPtr<FakeWebMediaPlayerDelegate> {
+ public:
+ FakeWebMediaPlayerDelegate() {}
+ ~FakeWebMediaPlayerDelegate() override {
+ DCHECK(!observer_);
+ DCHECK(is_gone_);
+ }
+
+ int AddObserver(Observer* observer) override {
+ observer_ = observer;
+ return delegate_id_;
+ }
+
+ void RemoveObserver(int delegate_id) override {
+ EXPECT_EQ(delegate_id_, delegate_id);
+ observer_ = nullptr;
+ }
+
+ void DidPlay(int delegate_id,
+ bool has_video,
+ bool has_audio,
+ bool is_remote,
+ base::TimeDelta duration) override {
+ EXPECT_EQ(delegate_id_, delegate_id);
+ EXPECT_FALSE(playing_);
+ playing_ = true;
+ is_gone_ = false;
+ }
+
+ void DidPause(int delegate_id, bool reached_end_of_stream) override {
+ EXPECT_EQ(delegate_id_, delegate_id);
+ EXPECT_TRUE(playing_);
+ EXPECT_FALSE(is_gone_);
+ playing_ = false;
+ }
+
+ void PlayerGone(int delegate_id) override {
+ EXPECT_EQ(delegate_id_, delegate_id);
+ is_gone_ = true;
+ }
+
+ bool IsHidden() override { return is_hidden_; }
+
+ void set_hidden(bool is_hidden) { is_hidden_ = is_hidden; }
+
+ private:
+ int delegate_id_ = 1234;
+ Observer* observer_ = nullptr;
+ bool playing_ = false;
+ bool is_hidden_ = false;
+ bool is_gone_ = true;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeWebMediaPlayerDelegate);
+};
+
class ReusableMessageLoopEvent {
public:
ReusableMessageLoopEvent() : event_(new media::WaitableMessageLoopEvent()) {}
@@ -45,7 +102,7 @@ class ReusableMessageLoopEvent {
}
private:
- scoped_ptr<media::WaitableMessageLoopEvent> event_;
+ std::unique_ptr<media::WaitableMessageLoopEvent> event_;
};
// The class is used mainly to inject VideoFrames into WebMediaPlayerMS.
@@ -71,7 +128,8 @@ class MockVideoFrameProvider : public VideoFrameProvider {
void Pause() override;
// Methods for test use
- void QueueFrames(const std::vector<int>& timestamps_or_frame_type);
+ void QueueFrames(const std::vector<int>& timestamps_or_frame_type,
+ bool opaque_frame = true);
bool Started() { return started_; }
bool Paused() { return paused_; }
@@ -127,7 +185,8 @@ void MockVideoFrameProvider::AddFrame(
}
void MockVideoFrameProvider::QueueFrames(
- const std::vector<int>& timestamp_or_frame_type) {
+ const std::vector<int>& timestamp_or_frame_type,
+ bool opaque_frame) {
for (const int token : timestamp_or_frame_type) {
if (token < static_cast<int>(FrameType::MIN_TYPE)) {
CHECK(false) << "Unrecognized frame type: " << token;
@@ -141,9 +200,10 @@ void MockVideoFrameProvider::QueueFrames(
if (token >= 0) {
gfx::Size natural_size = media::TestVideoConfig::NormalCodedSize();
- auto frame = media::VideoFrame::CreateFrame(
- media::PIXEL_FORMAT_YV12, natural_size, gfx::Rect(natural_size),
- natural_size, base::TimeDelta::FromMilliseconds(token));
+ auto frame = media::VideoFrame::CreateZeroInitializedFrame(
+ opaque_frame ? media::PIXEL_FORMAT_YV12 : media::PIXEL_FORMAT_YV12A,
+ natural_size, gfx::Rect(natural_size), natural_size,
+ base::TimeDelta::FromMilliseconds(token));
frame->metadata()->SetTimeTicks(
media::VideoFrameMetadata::Key::REFERENCE_TIME,
@@ -272,7 +332,7 @@ scoped_refptr<VideoFrameProvider> MockRenderFactory::GetVideoFrameProvider(
// WebMediaPlayerMSCompositor.
// 7. When WebMediaPlayerMS::play gets called, evething paused in step 6 should
// be resumed.
-class WebMediaPlayerMSTest : public testing::Test,
+class WebMediaPlayerMSTest : public testing::TestWithParam<bool>,
public blink::WebMediaPlayerClient,
public cc::VideoFrameProvider::Client {
public:
@@ -281,9 +341,9 @@ class WebMediaPlayerMSTest : public testing::Test,
&message_loop_controller_)),
player_(nullptr,
this,
- base::WeakPtr<media::WebMediaPlayerDelegate>(),
+ delegate_.AsWeakPtr(),
new media::MediaLog(),
- scoped_ptr<MediaStreamRendererFactory>(render_factory_),
+ std::unique_ptr<MediaStreamRendererFactory>(render_factory_),
message_loop_.task_runner(),
message_loop_.task_runner(),
message_loop_.task_runner(),
@@ -328,13 +388,13 @@ class WebMediaPlayerMSTest : public testing::Test,
void remoteRouteAvailabilityChanged(bool) override {}
void connectedToRemoteDevice() override {}
void disconnectedFromRemoteDevice() override {}
+ void cancelledRemotePlaybackRequest() override {}
// Implementation of cc::VideoFrameProvider::Client
void StopUsingProvider() override;
void StartRendering() override;
void StopRendering() override;
void DidReceiveFrame() override {}
- void DidUpdateMatrix(const float* matrix) override {}
// For test use
void SetBackgroundRendering(bool background_rendering) {
@@ -352,6 +412,7 @@ class WebMediaPlayerMSTest : public testing::Test,
base::MessageLoop message_loop_;
MockRenderFactory* render_factory_;
+ FakeWebMediaPlayerDelegate delegate_;
WebMediaPlayerMS player_;
WebMediaPlayerMSCompositor* compositor_;
ReusableMessageLoopEvent message_loop_controller_;
@@ -389,7 +450,7 @@ MockVideoFrameProvider* WebMediaPlayerMSTest::LoadAndGetFrameProvider(
}
void WebMediaPlayerMSTest::networkStateChanged() {
- blink::WebMediaPlayer::NetworkState state = player_.networkState();
+ blink::WebMediaPlayer::NetworkState state = player_.getNetworkState();
DoNetworkStateChanged(state);
if (state == blink::WebMediaPlayer::NetworkState::NetworkStateFormatError ||
state == blink::WebMediaPlayer::NetworkState::NetworkStateDecodeError ||
@@ -400,7 +461,7 @@ void WebMediaPlayerMSTest::networkStateChanged() {
}
void WebMediaPlayerMSTest::readyStateChanged() {
- blink::WebMediaPlayer::ReadyState state = player_.readyState();
+ blink::WebMediaPlayer::ReadyState state = player_.getReadyState();
DoReadyStateChanged(state);
if (state == blink::WebMediaPlayer::ReadyState::ReadyStateHaveEnoughData)
player_.play();
@@ -510,7 +571,8 @@ TEST_F(WebMediaPlayerMSTest, Playing_ErrorFrame) {
EXPECT_CALL(*this, DoStopRendering());
}
-TEST_F(WebMediaPlayerMSTest, PlayThenPause) {
+TEST_P(WebMediaPlayerMSTest, PlayThenPause) {
+ const bool opaque_frame = GetParam();
// In the middle of this test, WebMediaPlayerMS::pause will be called, and we
// are going to verify that during the pause stage, a frame gets freezed, and
// cc::VideoFrameProviderClient should also be paused.
@@ -520,7 +582,7 @@ TEST_F(WebMediaPlayerMSTest, PlayThenPause) {
int tokens[] = {0, 33, 66, 100, 133, kTestBrake, 166, 200, 233, 266,
300, 333, 366, 400, 433, 466, 500, 533, 566, 600};
std::vector<int> timestamps(tokens, tokens + sizeof(tokens) / sizeof(int));
- provider->QueueFrames(timestamps);
+ provider->QueueFrames(timestamps, opaque_frame);
EXPECT_CALL(*this, DoSetWebLayer(true));
EXPECT_CALL(*this, DoStartRendering());
@@ -545,7 +607,8 @@ TEST_F(WebMediaPlayerMSTest, PlayThenPause) {
EXPECT_CALL(*this, DoSetWebLayer(false));
}
-TEST_F(WebMediaPlayerMSTest, PlayThenPauseThenPlay) {
+TEST_P(WebMediaPlayerMSTest, PlayThenPauseThenPlay) {
+ const bool opaque_frame = GetParam();
// Similary to PlayAndPause test above, this one focuses on testing that
// WebMediaPlayerMS can be resumed after a period of paused status.
MockVideoFrameProvider* provider = LoadAndGetFrameProvider(false);
@@ -555,7 +618,7 @@ TEST_F(WebMediaPlayerMSTest, PlayThenPauseThenPlay) {
200, 233, 266, 300, 333, 366, 400,
433, kTestBrake, 466, 500, 533, 566, 600};
std::vector<int> timestamps(tokens, tokens + sizeof(tokens) / sizeof(int));
- provider->QueueFrames(timestamps);
+ provider->QueueFrames(timestamps, opaque_frame);
EXPECT_CALL(*this, DoSetWebLayer(true));
EXPECT_CALL(*this, DoStartRendering());
@@ -591,6 +654,8 @@ TEST_F(WebMediaPlayerMSTest, PlayThenPauseThenPlay) {
EXPECT_CALL(*this, DoStopRendering());
}
+INSTANTIATE_TEST_CASE_P(, WebMediaPlayerMSTest, ::testing::Bool());
+
TEST_F(WebMediaPlayerMSTest, BackgroudRendering) {
// During this test, we will switch to background rendering mode, in which
// WebMediaPlayerMS::pause does not get called, but
@@ -639,4 +704,53 @@ TEST_F(WebMediaPlayerMSTest, BackgroudRendering) {
EXPECT_CALL(*this, DoStopRendering());
}
+#if defined(OS_ANDROID)
+TEST_F(WebMediaPlayerMSTest, HiddenPlayerTests) {
+ LoadAndGetFrameProvider(true);
+
+ // Hidden status should not affect playback.
+ delegate_.set_hidden(true);
+ player_.play();
+ EXPECT_FALSE(player_.paused());
+
+ // A pause delivered via the delegate should not pause the video since these
+ // calls are currently ignored.
+ player_.OnPause();
+ EXPECT_FALSE(player_.paused());
+
+ // A hidden player should start still be playing upon shown.
+ delegate_.set_hidden(false);
+ player_.OnShown();
+ EXPECT_FALSE(player_.paused());
+
+ // A hidden event should not pause the player.
+ delegate_.set_hidden(true);
+ player_.OnHidden();
+ EXPECT_FALSE(player_.paused());
+
+ // A user generated pause() should clear the automatic resumption.
+ player_.pause();
+ delegate_.set_hidden(false);
+ player_.OnShown();
+ EXPECT_TRUE(player_.paused());
+
+ // A user generated play() should start playback.
+ player_.play();
+ EXPECT_FALSE(player_.paused());
+
+ // An OnSuspendRequested() without forced suspension should do nothing.
+ player_.OnSuspendRequested(false);
+ EXPECT_FALSE(player_.paused());
+
+ // An OnSuspendRequested() with forced suspension should pause playback.
+ player_.OnSuspendRequested(true);
+ EXPECT_TRUE(player_.paused());
+
+ // OnShown() should restart after a forced suspension.
+ player_.OnShown();
+ EXPECT_FALSE(player_.paused());
+ EXPECT_CALL(*this, DoSetWebLayer(false));
+}
+#endif
+
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/media_stream_remote_audio_track.cc b/chromium/content/renderer/media/webrtc/media_stream_remote_audio_track.cc
index 8bb5e0a5a30..e3940ab72b3 100644
--- a/chromium/content/renderer/media/webrtc/media_stream_remote_audio_track.cc
+++ b/chromium/content/renderer/media/webrtc/media_stream_remote_audio_track.cc
@@ -10,7 +10,7 @@
#include "base/logging.h"
#include "content/public/renderer/media_stream_audio_sink.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
namespace content {
@@ -109,18 +109,20 @@ class MediaStreamRemoteAudioSource::AudioSink
std::list<SinkInfo> sinks_;
base::ThreadChecker thread_checker_;
media::AudioParameters params_; // Only used on the callback thread.
- scoped_ptr<media::AudioBus> audio_bus_; // Only used on the callback thread.
+ std::unique_ptr<media::AudioBus>
+ audio_bus_; // Only used on the callback thread.
};
MediaStreamRemoteAudioTrack::MediaStreamRemoteAudioTrack(
const blink::WebMediaStreamSource& source, bool enabled)
: MediaStreamAudioTrack(false), source_(source), enabled_(enabled) {
- DCHECK(source.extraData()); // Make sure the source has a native source.
+ DCHECK(source.getExtraData()); // Make sure the source has a native source.
}
MediaStreamRemoteAudioTrack::~MediaStreamRemoteAudioTrack() {
DCHECK(main_render_thread_checker_.CalledOnValidThread());
- source()->RemoveAll(this);
+ // Ensure the track is stopped.
+ MediaStreamAudioTrack::Stop();
}
void MediaStreamRemoteAudioTrack::SetEnabled(bool enabled) {
@@ -139,8 +141,12 @@ void MediaStreamRemoteAudioTrack::SetEnabled(bool enabled) {
source()->SetSinksEnabled(this, enabled);
}
-void MediaStreamRemoteAudioTrack::Stop() {
+void MediaStreamRemoteAudioTrack::OnStop() {
DCHECK(main_render_thread_checker_.CalledOnValidThread());
+ DVLOG(1) << "MediaStreamRemoteAudioTrack::OnStop()";
+
+ source()->RemoveAll(this);
+
// Stop means that a track should be stopped permanently. But
// since there is no proper way of doing that on a remote track, we can
// at least disable the track. Blink will not call down to the content layer
@@ -172,7 +178,7 @@ webrtc::AudioTrackInterface* MediaStreamRemoteAudioTrack::GetAudioAdapter() {
}
MediaStreamRemoteAudioSource* MediaStreamRemoteAudioTrack::source() const {
- return static_cast<MediaStreamRemoteAudioSource*>(source_.extraData());
+ return static_cast<MediaStreamRemoteAudioSource*>(source_.getExtraData());
}
MediaStreamRemoteAudioSource::MediaStreamRemoteAudioSource(
diff --git a/chromium/content/renderer/media/webrtc/media_stream_remote_audio_track.h b/chromium/content/renderer/media/webrtc/media_stream_remote_audio_track.h
index e2a6eaa9dd9..9e48dfb40d7 100644
--- a/chromium/content/renderer/media/webrtc/media_stream_remote_audio_track.h
+++ b/chromium/content/renderer/media/webrtc/media_stream_remote_audio_track.h
@@ -25,9 +25,10 @@ class MediaStreamRemoteAudioTrack : public MediaStreamAudioTrack {
const blink::WebMediaStreamSource& source, bool enabled);
~MediaStreamRemoteAudioTrack() override;
+ // MediaStreamTrack override.
void SetEnabled(bool enabled) override;
- void Stop() override;
+ // MediaStreamAudioTrack overrides.
void AddSink(MediaStreamAudioSink* sink) override;
void RemoveSink(MediaStreamAudioSink* sink) override;
media::AudioParameters GetOutputFormat() const override;
@@ -35,6 +36,9 @@ class MediaStreamRemoteAudioTrack : public MediaStreamAudioTrack {
webrtc::AudioTrackInterface* GetAudioAdapter() override;
private:
+ // MediaStreamAudioTrack override.
+ void OnStop() final;
+
MediaStreamRemoteAudioSource* source() const;
blink::WebMediaStreamSource source_;
@@ -44,6 +48,7 @@ class MediaStreamRemoteAudioTrack : public MediaStreamAudioTrack {
// Inheriting from ExtraData directly since MediaStreamAudioSource has
// too much unrelated bloat.
// TODO(tommi): MediaStreamAudioSource needs refactoring.
+// TODO(miu): On it! ;-)
class MediaStreamRemoteAudioSource
: public blink::WebMediaStreamSource::ExtraData {
public:
@@ -74,7 +79,7 @@ class MediaStreamRemoteAudioSource
private:
class AudioSink;
- scoped_ptr<AudioSink> sink_;
+ std::unique_ptr<AudioSink> sink_;
const scoped_refptr<webrtc::AudioTrackInterface> track_;
base::ThreadChecker thread_checker_;
};
diff --git a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc
index 88ceba3a97a..03b6125128f 100644
--- a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc
+++ b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.cc
@@ -17,7 +17,8 @@
#include "media/base/timestamp_constants.h"
#include "media/base/video_frame.h"
#include "media/base/video_util.h"
-#include "third_party/libjingle/source/talk/media/base/videoframe.h"
+#include "third_party/webrtc/media/base/videoframe.h"
+#include "third_party/webrtc/media/base/videosinkinterface.h"
#include "third_party/webrtc/system_wrappers/include/tick_util.h"
namespace content {
@@ -26,7 +27,7 @@ namespace content {
// libjingle thread and forward it to the IO-thread.
class MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate
: public base::RefCountedThreadSafe<RemoteVideoSourceDelegate>,
- public webrtc::VideoRendererInterface {
+ public rtc::VideoSinkInterface<cricket::VideoFrame> {
public:
RemoteVideoSourceDelegate(
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
@@ -36,10 +37,10 @@ class MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate
friend class base::RefCountedThreadSafe<RemoteVideoSourceDelegate>;
~RemoteVideoSourceDelegate() override;
- // Implements webrtc::VideoRendererInterface used for receiving video frames
+ // Implements rtc::VideoSinkInterface used for receiving video frames
// from the PeerConnection video track. May be called on a libjingle internal
// thread.
- void RenderFrame(const cricket::VideoFrame* frame) override;
+ void OnFrame(const cricket::VideoFrame& frame) override;
void DoRenderFrameOnIOThread(
const scoped_refptr<media::VideoFrame>& video_frame);
@@ -77,10 +78,10 @@ MediaStreamRemoteVideoSource::
RemoteVideoSourceDelegate::~RemoteVideoSourceDelegate() {
}
-void MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate::RenderFrame(
- const cricket::VideoFrame* incoming_frame) {
+void MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate::OnFrame(
+ const cricket::VideoFrame& incoming_frame) {
const base::TimeDelta incoming_timestamp = base::TimeDelta::FromMicroseconds(
- incoming_frame->GetTimeStamp() / rtc::kNumNanosecsPerMicrosec);
+ incoming_frame.GetTimeStamp() / rtc::kNumNanosecsPerMicrosec);
const base::TimeTicks render_time =
base::TimeTicks() + incoming_timestamp + time_diff_;
@@ -94,13 +95,13 @@ void MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate::RenderFrame(
incoming_timestamp - start_timestamp_;
scoped_refptr<media::VideoFrame> video_frame;
- if (incoming_frame->GetNativeHandle() != NULL) {
+ if (incoming_frame.GetNativeHandle() != NULL) {
video_frame =
- static_cast<media::VideoFrame*>(incoming_frame->GetNativeHandle());
+ static_cast<media::VideoFrame*>(incoming_frame.GetNativeHandle());
video_frame->set_timestamp(elapsed_timestamp);
} else {
const cricket::VideoFrame* frame =
- incoming_frame->GetCopyWithRotationApplied();
+ incoming_frame.GetCopyWithRotationApplied();
gfx::Size size(frame->GetWidth(), frame->GetHeight());
@@ -139,7 +140,7 @@ RemoteVideoSourceDelegate::DoRenderFrameOnIOThread(
}
MediaStreamRemoteVideoSource::MediaStreamRemoteVideoSource(
- scoped_ptr<TrackObserver> observer)
+ std::unique_ptr<TrackObserver> observer)
: observer_(std::move(observer)) {
// The callback will be automatically cleared when 'observer_' goes out of
// scope and no further callbacks will occur.
@@ -178,7 +179,7 @@ void MediaStreamRemoteVideoSource::StartSourceImpl(
delegate_ = new RemoteVideoSourceDelegate(io_task_runner(), frame_callback);
scoped_refptr<webrtc::VideoTrackInterface> video_track(
static_cast<webrtc::VideoTrackInterface*>(observer_->track().get()));
- video_track->AddRenderer(delegate_.get());
+ video_track->AddOrUpdateSink(delegate_.get(), rtc::VideoSinkWants());
OnStartDone(MEDIA_DEVICE_OK);
}
@@ -193,13 +194,13 @@ void MediaStreamRemoteVideoSource::StopSourceImpl() {
DCHECK(state() != MediaStreamVideoSource::ENDED);
scoped_refptr<webrtc::VideoTrackInterface> video_track(
static_cast<webrtc::VideoTrackInterface*>(observer_->track().get()));
- video_track->RemoveRenderer(delegate_.get());
+ video_track->RemoveSink(delegate_.get());
// This removes the references to the webrtc video track.
observer_.reset();
}
-webrtc::VideoRendererInterface*
-MediaStreamRemoteVideoSource::RenderInterfaceForTest() {
+rtc::VideoSinkInterface<cricket::VideoFrame>*
+MediaStreamRemoteVideoSource::SinkInterfaceForTest() {
return delegate_.get();
}
@@ -207,10 +208,6 @@ void MediaStreamRemoteVideoSource::OnChanged(
webrtc::MediaStreamTrackInterface::TrackState state) {
DCHECK(CalledOnValidThread());
switch (state) {
- case webrtc::MediaStreamTrackInterface::kInitializing:
- // Ignore the kInitializing state since there is no match in
- // WebMediaStreamSource::ReadyState.
- break;
case webrtc::MediaStreamTrackInterface::kLive:
SetReadyState(blink::WebMediaStreamSource::ReadyStateLive);
break;
diff --git a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.h b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.h
index 1f24c75ba11..5f1d4fb6caa 100644
--- a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.h
+++ b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source.h
@@ -11,7 +11,7 @@
#include "content/common/content_export.h"
#include "content/renderer/media/media_stream_video_source.h"
#include "third_party/WebKit/public/platform/WebMediaStreamSource.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
namespace content {
@@ -24,7 +24,7 @@ class TrackObserver;
class CONTENT_EXPORT MediaStreamRemoteVideoSource
: public MediaStreamVideoSource {
public:
- MediaStreamRemoteVideoSource(scoped_ptr<TrackObserver> observer);
+ MediaStreamRemoteVideoSource(std::unique_ptr<TrackObserver> observer);
~MediaStreamRemoteVideoSource() override;
// Should be called when the remote video track this source originates from is
@@ -49,7 +49,7 @@ class CONTENT_EXPORT MediaStreamRemoteVideoSource
// Used by tests to test that a frame can be received and that the
// MediaStreamRemoteVideoSource behaves as expected.
- webrtc::VideoRendererInterface* RenderInterfaceForTest();
+ rtc::VideoSinkInterface<cricket::VideoFrame>* SinkInterfaceForTest();
private:
void OnChanged(webrtc::MediaStreamTrackInterface::TrackState state);
@@ -58,7 +58,7 @@ class CONTENT_EXPORT MediaStreamRemoteVideoSource
// libjingle thread and forward it to the IO-thread.
class RemoteVideoSourceDelegate;
scoped_refptr<RemoteVideoSourceDelegate> delegate_;
- scoped_ptr<TrackObserver> observer_;
+ std::unique_ptr<TrackObserver> observer_;
DISALLOW_COPY_AND_ASSIGN(MediaStreamRemoteVideoSource);
};
diff --git a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
index b5fcae5983d..52a580bc233 100644
--- a/chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/media_stream_remote_video_source_unittest.cc
@@ -18,7 +18,7 @@
#include "media/base/video_frame.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/web/WebHeap.h"
-#include "third_party/libjingle/source/talk/media/webrtc/webrtcvideoframe.h"
+#include "third_party/webrtc/media/engine/webrtcvideoframe.h"
namespace content {
@@ -30,9 +30,9 @@ class MediaStreamRemoteVideoSourceUnderTest
: public MediaStreamRemoteVideoSource {
public:
explicit MediaStreamRemoteVideoSourceUnderTest(
- scoped_ptr<TrackObserver> observer)
+ std::unique_ptr<TrackObserver> observer)
: MediaStreamRemoteVideoSource(std::move(observer)) {}
- using MediaStreamRemoteVideoSource::RenderInterfaceForTest;
+ using MediaStreamRemoteVideoSource::SinkInterfaceForTest;
};
class MediaStreamRemoteVideoSourceTest
@@ -44,8 +44,8 @@ class MediaStreamRemoteVideoSourceTest
webrtc_video_track_(mock_factory_->CreateLocalVideoTrack(
"test",
static_cast<cricket::VideoCapturer*>(NULL))),
- remote_source_(
- new MediaStreamRemoteVideoSourceUnderTest(scoped_ptr<TrackObserver>(
+ remote_source_(new MediaStreamRemoteVideoSourceUnderTest(
+ std::unique_ptr<TrackObserver>(
new TrackObserver(base::ThreadTaskRunnerHandle::Get(),
webrtc_video_track_.get())))),
number_of_successful_constraints_applied_(0),
@@ -89,8 +89,7 @@ class MediaStreamRemoteVideoSourceTest
}
void StopWebRtcTrack() {
- static_cast<MockWebRtcVideoTrack*>(webrtc_video_track_.get())->set_state(
- webrtc::MediaStreamTrackInterface::kEnded);
+ static_cast<MockWebRtcVideoTrack*>(webrtc_video_track_.get())->SetEnded();
}
const blink::WebMediaStreamSource& webkit_source() const {
@@ -109,8 +108,8 @@ class MediaStreamRemoteVideoSourceTest
}
base::MessageLoopForUI message_loop_;
- scoped_ptr<ChildProcess> child_process_;
- scoped_ptr<MockPeerConnectionDependencyFactory> mock_factory_;
+ std::unique_ptr<ChildProcess> child_process_;
+ std::unique_ptr<MockPeerConnectionDependencyFactory> mock_factory_;
scoped_refptr<webrtc::VideoTrackInterface> webrtc_video_track_;
// |remote_source_| is owned by |webkit_source_|.
MediaStreamRemoteVideoSourceUnderTest* remote_source_;
@@ -120,7 +119,7 @@ class MediaStreamRemoteVideoSourceTest
};
TEST_F(MediaStreamRemoteVideoSourceTest, StartTrack) {
- scoped_ptr<MediaStreamVideoTrack> track(CreateTrack());
+ std::unique_ptr<MediaStreamVideoTrack> track(CreateTrack());
EXPECT_EQ(1, NumberOfSuccessConstraintsCallbacks());
MockMediaStreamVideoSink sink;
@@ -130,8 +129,8 @@ TEST_F(MediaStreamRemoteVideoSourceTest, StartTrack) {
EXPECT_CALL(sink, OnVideoFrame()).WillOnce(
RunClosure(quit_closure));
cricket::WebRtcVideoFrame webrtc_frame;
- webrtc_frame.InitToBlack(320, 240, 1, 1, 1);
- source()->RenderInterfaceForTest()->RenderFrame(&webrtc_frame);
+ webrtc_frame.InitToBlack(320, 240, 1);
+ source()->SinkInterfaceForTest()->OnFrame(webrtc_frame);
run_loop.Run();
EXPECT_EQ(1, sink.number_of_frames());
@@ -139,17 +138,17 @@ TEST_F(MediaStreamRemoteVideoSourceTest, StartTrack) {
}
TEST_F(MediaStreamRemoteVideoSourceTest, RemoteTrackStop) {
- scoped_ptr<MediaStreamVideoTrack> track(CreateTrack());
+ std::unique_ptr<MediaStreamVideoTrack> track(CreateTrack());
MockMediaStreamVideoSink sink;
track->AddSink(&sink, sink.GetDeliverFrameCB());
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive, sink.state());
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateLive,
- webkit_source().readyState());
+ webkit_source().getReadyState());
StopWebRtcTrack();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded,
- webkit_source().readyState());
+ webkit_source().getReadyState());
EXPECT_EQ(blink::WebMediaStreamSource::ReadyStateEnded, sink.state());
track->RemoveSink(&sink);
diff --git a/chromium/content/renderer/media/webrtc/media_stream_track_metrics.cc b/chromium/content/renderer/media/webrtc/media_stream_track_metrics.cc
index 33536923870..21f2da67a52 100644
--- a/chromium/content/renderer/media/webrtc/media_stream_track_metrics.cc
+++ b/chromium/content/renderer/media/webrtc/media_stream_track_metrics.cc
@@ -12,7 +12,7 @@
#include "base/thread_task_runner_handle.h"
#include "content/common/media/media_stream_track_metrics_host_messages.h"
#include "content/renderer/render_thread_impl.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
using webrtc::AudioTrackVector;
using webrtc::MediaStreamInterface;
diff --git a/chromium/content/renderer/media/webrtc/media_stream_track_metrics.h b/chromium/content/renderer/media/webrtc/media_stream_track_metrics.h
index 4f2cd0e3bd5..2f3feca6819 100644
--- a/chromium/content/renderer/media/webrtc/media_stream_track_metrics.h
+++ b/chromium/content/renderer/media/webrtc/media_stream_track_metrics.h
@@ -10,7 +10,7 @@
#include "base/memory/scoped_vector.h"
#include "base/threading/non_thread_safe.h"
#include "content/common/content_export.h"
-#include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h"
+#include "third_party/webrtc/api/peerconnectioninterface.h"
namespace webrtc {
class MediaStreamInterface;
diff --git a/chromium/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc b/chromium/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc
index 8f10d553200..29d0e1e9885 100644
--- a/chromium/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/media_stream_track_metrics_unittest.cc
@@ -12,7 +12,7 @@
#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
using webrtc::AudioSourceInterface;
using webrtc::AudioTrackInterface;
@@ -20,8 +20,7 @@ using webrtc::AudioTrackSinkInterface;
using webrtc::MediaStreamInterface;
using webrtc::ObserverInterface;
using webrtc::PeerConnectionInterface;
-using webrtc::VideoRendererInterface;
-using webrtc::VideoSourceInterface;
+using webrtc::VideoTrackSourceInterface;
using webrtc::VideoTrackInterface;
namespace content {
@@ -64,9 +63,11 @@ class MockVideoTrackInterface : public VideoTrackInterface {
MOCK_CONST_METHOD0(state, TrackState());
MOCK_METHOD1(set_enabled, bool(bool));
MOCK_METHOD1(set_state, bool(TrackState));
- MOCK_METHOD1(AddRenderer, void(VideoRendererInterface*));
- MOCK_METHOD1(RemoveRenderer, void(VideoRendererInterface*));
- MOCK_CONST_METHOD0(GetSource, VideoSourceInterface*());
+ MOCK_METHOD2(AddOrUpdateSink,
+ void(rtc::VideoSinkInterface<cricket::VideoFrame>*,
+ const rtc::VideoSinkWants&));
+ MOCK_METHOD1(RemoveSink, void(rtc::VideoSinkInterface<cricket::VideoFrame>*));
+ MOCK_CONST_METHOD0(GetSource, VideoTrackSourceInterface*());
private:
std::string id_;
@@ -142,7 +143,7 @@ class MediaStreamTrackMetricsTest : public testing::Test {
return new rtc::RefCountedObject<MockVideoTrackInterface>(id);
}
- scoped_ptr<MockMediaStreamTrackMetrics> metrics_;
+ std::unique_ptr<MockMediaStreamTrackMetrics> metrics_;
scoped_refptr<MediaStreamInterface> stream_;
base::MessageLoopForUI message_loop_;
diff --git a/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc b/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc
index f8ac666bf7f..2fc6e2aefab 100644
--- a/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc
+++ b/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.cc
@@ -5,26 +5,33 @@
#include "content/renderer/media/webrtc/media_stream_video_webrtc_sink.h"
#include "base/location.h"
+#include "base/numerics/safe_conversions.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock.h"
#include "base/thread_task_runner_handle.h"
+#include "base/timer/timer.h"
#include "content/common/media/media_stream_options.h"
+#include "content/public/renderer/media_stream_utils.h"
+#include "content/renderer/media/media_stream_constraints_util.h"
#include "content/renderer/media/media_stream_video_track.h"
#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
+#include "media/base/limits.h"
+
+namespace content {
namespace {
-bool ConstraintKeyExists(const blink::WebMediaConstraints& constraints,
- const blink::WebString& name) {
- blink::WebString value_str;
- return constraints.getMandatoryConstraintValue(name, value_str) ||
- constraints.getOptionalConstraintValue(name, value_str);
-}
+// The default number of microseconds that should elapse since the last video
+// frame was received, before requesting a refresh frame.
+const int64_t kDefaultRefreshIntervalMicros =
+ base::Time::kMicrosecondsPerSecond;
-} // anonymouse namespace
+// A lower-bound for the refresh interval.
+const int64_t kLowerBoundRefreshIntervalMicros =
+ base::Time::kMicrosecondsPerSecond / media::limits::kMaxFramesPerSecond;
-namespace content {
+} // namespace
// Simple help class used for receiving video frames on the IO-thread from a
// MediaStreamVideoTrack and forward the frames to a WebRtcVideoCapturerAdapter
@@ -36,8 +43,10 @@ class MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter
WebRtcVideoSourceAdapter(
const scoped_refptr<base::SingleThreadTaskRunner>&
libjingle_worker_thread,
- const scoped_refptr<webrtc::VideoSourceInterface>& source,
- WebRtcVideoCapturerAdapter* capture_adapter);
+ const scoped_refptr<webrtc::VideoTrackSourceInterface>& source,
+ WebRtcVideoCapturerAdapter* capture_adapter,
+ base::TimeDelta refresh_interval,
+ const base::Closure& refresh_callback);
// MediaStreamVideoWebRtcSink can be destroyed on the main render thread or
// libjingles worker thread since it posts video frames on that thread. But
@@ -56,6 +65,11 @@ class MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter
friend class base::RefCountedThreadSafe<WebRtcVideoSourceAdapter>;
virtual ~WebRtcVideoSourceAdapter();
+ // Called whenever a video frame was just delivered on the IO thread. This
+ // restarts the delay period before the |refresh_timer_| will fire the next
+ // time.
+ void ResetRefreshTimerOnMainThread();
+
scoped_refptr<base::SingleThreadTaskRunner> render_thread_task_runner_;
// |render_thread_checker_| is bound to the main render thread.
@@ -67,7 +81,7 @@ class MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter
// IO-thread.
scoped_refptr<base::SingleThreadTaskRunner> libjingle_worker_thread_;
- scoped_refptr<webrtc::VideoSourceInterface> video_source_;
+ scoped_refptr<webrtc::VideoTrackSourceInterface> video_source_;
// Used to protect |capture_adapter_|. It is taken by libjingle's worker
// thread for each video frame that is delivered but only taken on the
@@ -76,17 +90,38 @@ class MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter
base::Lock capture_adapter_stop_lock_;
// |capture_adapter_| is owned by |video_source_|
WebRtcVideoCapturerAdapter* capture_adapter_;
+
+ // Requests a refresh frame at regular intervals. The delay on this timer is
+ // reset each time a frame is received so that it will not fire for at least
+ // an additional period. This means refresh frames will only be requested when
+ // the source has halted delivery (e.g., a screen capturer stops sending
+ // frames because the screen is not being updated).
+ //
+ // This mechanism solves a number of problems. First, it will ensure that
+ // remote clients that join a distributed session receive a first video frame
+ // in a timely manner. Second, it will allow WebRTC's internal bandwidth
+ // estimation logic to maintain a more optimal state, since sending a video
+ // frame will "prime it." Third, it allows lossy encoders to clean up
+ // artifacts in a still image. http://crbug.com/486274
+ base::RepeatingTimer refresh_timer_;
};
MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::WebRtcVideoSourceAdapter(
const scoped_refptr<base::SingleThreadTaskRunner>& libjingle_worker_thread,
- const scoped_refptr<webrtc::VideoSourceInterface>& source,
- WebRtcVideoCapturerAdapter* capture_adapter)
+ const scoped_refptr<webrtc::VideoTrackSourceInterface>& source,
+ WebRtcVideoCapturerAdapter* capture_adapter,
+ base::TimeDelta refresh_interval,
+ const base::Closure& refresh_callback)
: render_thread_task_runner_(base::ThreadTaskRunnerHandle::Get()),
libjingle_worker_thread_(libjingle_worker_thread),
video_source_(source),
capture_adapter_(capture_adapter) {
io_thread_checker_.DetachFromThread();
+ if (!refresh_interval.is_zero()) {
+ VLOG(1) << "Starting frame refresh timer with interval "
+ << refresh_interval.InMillisecondsF() << " ms.";
+ refresh_timer_.Start(FROM_HERE, refresh_interval, refresh_callback);
+ }
}
MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::
@@ -101,6 +136,13 @@ MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::
}
void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::
+ResetRefreshTimerOnMainThread() {
+ DCHECK(render_thread_checker_.CalledOnValidThread());
+ if (refresh_timer_.IsRunning())
+ refresh_timer_.Reset();
+}
+
+void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::
ReleaseSourceOnMainThread() {
DCHECK(render_thread_checker_.CalledOnValidThread());
// Since frames are posted to the worker thread, this object might be deleted
@@ -116,6 +158,10 @@ void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::OnVideoFrameOnIO(
const scoped_refptr<media::VideoFrame>& frame,
base::TimeTicks estimated_capture_time) {
DCHECK(io_thread_checker_.CalledOnValidThread());
+ render_thread_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&WebRtcVideoSourceAdapter::ResetRefreshTimerOnMainThread,
+ this));
libjingle_worker_thread_->PostTask(
FROM_HERE,
base::Bind(&WebRtcVideoSourceAdapter::OnVideoFrameOnWorkerThread,
@@ -134,34 +180,73 @@ void MediaStreamVideoWebRtcSink::WebRtcVideoSourceAdapter::
MediaStreamVideoWebRtcSink::MediaStreamVideoWebRtcSink(
const blink::WebMediaStreamTrack& track,
PeerConnectionDependencyFactory* factory)
- : web_track_(track) {
+ : weak_factory_(this) {
const blink::WebMediaConstraints& constraints =
MediaStreamVideoTrack::GetVideoTrack(track)->constraints();
- bool is_screencast = ConstraintKeyExists(
- constraints, base::UTF8ToUTF16(kMediaStreamSource));
+ // Check for presence of mediaStreamSource constraint. The value is ignored.
+ std::string value;
+ bool is_screencast = GetConstraintValueAsString(
+ constraints, &blink::WebMediaTrackConstraintSet::mediaStreamSource,
+ &value);
+
+ // Enable automatic frame refreshes for the screen capture sources, which will
+ // stop producing frames whenever screen content is not changing. Check the
+ // frameRate constraint to determine the rate of refreshes. If a minimum
+ // frameRate is provided, use that. Otherwise, use the maximum frameRate if it
+ // happens to be less than the default.
+ base::TimeDelta refresh_interval = base::TimeDelta::FromMicroseconds(0);
+ if (is_screencast) {
+ // Start with the default refresh interval, and refine based on constraints.
+ refresh_interval =
+ base::TimeDelta::FromMicroseconds(kDefaultRefreshIntervalMicros);
+ double value = 0.0;
+ if (GetConstraintMinAsDouble(
+ constraints, &blink::WebMediaTrackConstraintSet::frameRate,
+ &value) &&
+ value > 0.0) {
+ refresh_interval =
+ base::TimeDelta::FromMicroseconds(base::saturated_cast<int64_t>(
+ base::Time::kMicrosecondsPerSecond / value));
+ }
+ if (GetConstraintMaxAsDouble(
+ constraints, &blink::WebMediaTrackConstraintSet::frameRate,
+ &value) &&
+ value > 0.0) {
+ const base::TimeDelta alternate_refresh_interval =
+ base::TimeDelta::FromMicroseconds(base::saturated_cast<int64_t>(
+ base::Time::kMicrosecondsPerSecond / value));
+ refresh_interval = std::max(refresh_interval, alternate_refresh_interval);
+ }
+ if (refresh_interval.InMicroseconds() < kLowerBoundRefreshIntervalMicros) {
+ refresh_interval =
+ base::TimeDelta::FromMicroseconds(kLowerBoundRefreshIntervalMicros);
+ }
+ }
+
WebRtcVideoCapturerAdapter* capture_adapter =
factory->CreateVideoCapturer(is_screencast);
// |video_source| owns |capture_adapter|
- scoped_refptr<webrtc::VideoSourceInterface> video_source(
- factory->CreateVideoSource(capture_adapter,
- track.source().constraints()));
+ scoped_refptr<webrtc::VideoTrackSourceInterface> video_source(
+ factory->CreateVideoSource(capture_adapter));
- video_track_ = factory->CreateLocalVideoTrack(web_track_.id().utf8(),
+ video_track_ = factory->CreateLocalVideoTrack(track.id().utf8(),
video_source.get());
- video_track_->set_enabled(web_track_.isEnabled());
+ video_track_->set_enabled(track.isEnabled());
source_adapter_ = new WebRtcVideoSourceAdapter(
factory->GetWebRtcWorkerThread(),
video_source,
- capture_adapter);
+ capture_adapter,
+ refresh_interval,
+ base::Bind(&MediaStreamVideoWebRtcSink::RequestRefreshFrame,
+ weak_factory_.GetWeakPtr()));
- AddToVideoTrack(
- this,
- base::Bind(&WebRtcVideoSourceAdapter::OnVideoFrameOnIO, source_adapter_),
- web_track_);
+ MediaStreamVideoSink::ConnectToTrack(
+ track,
+ base::Bind(&WebRtcVideoSourceAdapter::OnVideoFrameOnIO, source_adapter_));
DVLOG(3) << "MediaStreamVideoWebRtcSink ctor() : is_screencast "
<< is_screencast;
@@ -170,7 +255,8 @@ MediaStreamVideoWebRtcSink::MediaStreamVideoWebRtcSink(
MediaStreamVideoWebRtcSink::~MediaStreamVideoWebRtcSink() {
DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(3) << "MediaStreamVideoWebRtcSink dtor().";
- RemoveFromVideoTrack(this, web_track_);
+ weak_factory_.InvalidateWeakPtrs();
+ MediaStreamVideoSink::DisconnectFromTrack();
source_adapter_->ReleaseSourceOnMainThread();
}
@@ -179,4 +265,9 @@ void MediaStreamVideoWebRtcSink::OnEnabledChanged(bool enabled) {
video_track_->set_enabled(enabled);
}
+void MediaStreamVideoWebRtcSink::RequestRefreshFrame() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ content::RequestRefreshFrameFromVideoTrack(connected_track());
+}
+
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.h b/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.h
index 57c3702141c..97137319b22 100644
--- a/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.h
+++ b/chromium/content/renderer/media/webrtc/media_stream_video_webrtc_sink.h
@@ -6,12 +6,12 @@
#define CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_VIDEO_TRACK_ADAPTER_H_
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "content/public/renderer/media_stream_video_sink.h"
#include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
-#include "third_party/libjingle/source/talk/app/webrtc/videosourceinterface.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
namespace content {
@@ -42,15 +42,23 @@ class MediaStreamVideoWebRtcSink : public MediaStreamVideoSink {
void OnEnabledChanged(bool enabled) override;
private:
+ // Helper to request a refresh frame from the source. Called via the callback
+ // passed to WebRtcVideoSourceAdapter.
+ void RequestRefreshFrame();
+
// Used to DCHECK that we are called on the correct thread.
base::ThreadChecker thread_checker_;
scoped_refptr<webrtc::VideoTrackInterface> video_track_;
- blink::WebMediaStreamTrack web_track_;
class WebRtcVideoSourceAdapter;
scoped_refptr<WebRtcVideoSourceAdapter> source_adapter_;
+ // Provides WebRtcVideoSourceAdapter a weak reference to
+ // MediaStreamVideoWebRtcSink in order to allow it to request refresh frames.
+ // See comments in media_stream_video_webrtc_sink.cc.
+ base::WeakPtrFactory<MediaStreamVideoWebRtcSink> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(MediaStreamVideoWebRtcSink);
};
diff --git a/chromium/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.cc b/chromium/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.cc
index d4e61168d6d..982291bdbf8 100644
--- a/chromium/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.cc
+++ b/chromium/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.cc
@@ -15,9 +15,9 @@
#include "content/renderer/media/webrtc_audio_capturer.h"
#include "content/renderer/media/webrtc_local_audio_track.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
-#include "third_party/libjingle/source/talk/media/base/videocapturer.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
#include "third_party/webrtc/base/scoped_ref_ptr.h"
+#include "third_party/webrtc/media/base/videocapturer.h"
using webrtc::AudioSourceInterface;
using webrtc::AudioTrackInterface;
@@ -27,8 +27,7 @@ using webrtc::IceCandidateInterface;
using webrtc::MediaStreamInterface;
using webrtc::ObserverInterface;
using webrtc::SessionDescriptionInterface;
-using webrtc::VideoRendererInterface;
-using webrtc::VideoSourceInterface;
+using webrtc::VideoTrackSourceInterface;
using webrtc::VideoTrackInterface;
using webrtc::VideoTrackVector;
@@ -157,22 +156,9 @@ class MockRtcVideoCapturer : public WebRtcVideoCapturerAdapter {
int height_;
};
-MockVideoRenderer::MockVideoRenderer()
- : num_(0) {}
-
-MockVideoRenderer::~MockVideoRenderer() {}
-
-bool MockVideoRenderer::RenderFrame(const cricket::VideoFrame* frame) {
- ++num_;
- return true;
-}
-
-MockAudioSource::MockAudioSource(
- const webrtc::MediaConstraintsInterface* constraints, bool remote)
- : remote_(remote), state_(MediaSourceInterface::kLive),
- optional_constraints_(constraints->GetOptional()),
- mandatory_constraints_(constraints->GetMandatory()) {
-}
+MockAudioSource::MockAudioSource(const cricket::AudioOptions& options,
+ bool remote)
+ : remote_(remote), state_(MediaSourceInterface::kLive) {}
MockAudioSource::~MockAudioSource() {}
@@ -194,129 +180,96 @@ bool MockAudioSource::remote() const {
return remote_;
}
-MockVideoSource::MockVideoSource(bool remote)
- : state_(MediaSourceInterface::kInitializing), remote_(remote) {
-}
-
-MockVideoSource::~MockVideoSource() {}
-
-void MockVideoSource::SetVideoCapturer(cricket::VideoCapturer* capturer) {
- capturer_.reset(capturer);
+scoped_refptr<MockWebRtcAudioTrack> MockWebRtcAudioTrack::Create(
+ const std::string& id) {
+ return new rtc::RefCountedObject<MockWebRtcAudioTrack>(id);
}
-cricket::VideoCapturer* MockVideoSource::GetVideoCapturer() {
- return capturer_.get();
-}
+MockWebRtcAudioTrack::MockWebRtcAudioTrack(const std::string& id)
+ : id_(id),
+ enabled_(true),
+ state_(webrtc::MediaStreamTrackInterface::kLive) {}
-void MockVideoSource::AddSink(cricket::VideoRenderer* output) {
- NOTIMPLEMENTED();
-}
+MockWebRtcAudioTrack::~MockWebRtcAudioTrack() {}
-void MockVideoSource::RemoveSink(cricket::VideoRenderer* output) {
- NOTIMPLEMENTED();
+std::string MockWebRtcAudioTrack::kind() const {
+ return kAudioKind;
}
-void MockVideoSource::Stop() {
- NOTIMPLEMENTED();
-}
-void MockVideoSource::Restart() {
- NOTIMPLEMENTED();
+webrtc::AudioSourceInterface* MockWebRtcAudioTrack::GetSource() const {
+ NOTREACHED();
+ return nullptr;
}
-cricket::VideoRenderer* MockVideoSource::FrameInput() {
- return &renderer_;
+std::string MockWebRtcAudioTrack::id() const {
+ return id_;
}
-void MockVideoSource::RegisterObserver(webrtc::ObserverInterface* observer) {
- observers_.push_back(observer);
+bool MockWebRtcAudioTrack::enabled() const {
+ return enabled_;
}
-void MockVideoSource::UnregisterObserver(webrtc::ObserverInterface* observer) {
- for (std::vector<ObserverInterface*>::iterator it = observers_.begin();
- it != observers_.end(); ++it) {
- if (*it == observer) {
- observers_.erase(it);
- break;
- }
- }
-}
-
-void MockVideoSource::FireOnChanged() {
- std::vector<ObserverInterface*> observers(observers_);
- for (std::vector<ObserverInterface*>::iterator it = observers.begin();
- it != observers.end(); ++it) {
- (*it)->OnChanged();
- }
-}
-
-void MockVideoSource::SetLive() {
- DCHECK(state_ == MediaSourceInterface::kInitializing ||
- state_ == MediaSourceInterface::kLive);
- state_ = MediaSourceInterface::kLive;
- FireOnChanged();
-}
-
-void MockVideoSource::SetEnded() {
- DCHECK_NE(MediaSourceInterface::kEnded, state_);
- state_ = MediaSourceInterface::kEnded;
- FireOnChanged();
-}
-
-webrtc::MediaSourceInterface::SourceState MockVideoSource::state() const {
+MockWebRtcVideoTrack::TrackState MockWebRtcAudioTrack::state() const {
return state_;
}
-bool MockVideoSource::remote() const {
- return remote_;
-}
-
-const cricket::VideoOptions* MockVideoSource::options() const {
- NOTIMPLEMENTED();
- return NULL;
+bool MockWebRtcAudioTrack::set_enabled(bool enable) {
+ enabled_ = enable;
+ return true;
}
-int MockVideoSource::GetLastFrameWidth() const {
- DCHECK(capturer_);
- return
- static_cast<MockRtcVideoCapturer*>(capturer_.get())->GetLastFrameWidth();
+void MockWebRtcAudioTrack::RegisterObserver(ObserverInterface* observer) {
+ DCHECK(observers_.find(observer) == observers_.end());
+ observers_.insert(observer);
}
-int MockVideoSource::GetLastFrameHeight() const {
- DCHECK(capturer_);
- return
- static_cast<MockRtcVideoCapturer*>(capturer_.get())->GetLastFrameHeight();
+void MockWebRtcAudioTrack::UnregisterObserver(ObserverInterface* observer) {
+ DCHECK(observers_.find(observer) != observers_.end());
+ observers_.erase(observer);
}
-int MockVideoSource::GetFrameNum() const {
- DCHECK(capturer_);
- return static_cast<MockRtcVideoCapturer*>(capturer_.get())->GetFrameNum();
+void MockWebRtcAudioTrack::SetEnded() {
+ DCHECK_EQ(webrtc::MediaStreamTrackInterface::kLive, state_);
+ state_ = webrtc::MediaStreamTrackInterface::kEnded;
+ for (auto& o : observers_)
+ o->OnChanged();
}
MockWebRtcVideoTrack::MockWebRtcVideoTrack(
const std::string& id,
- webrtc::VideoSourceInterface* source)
- : enabled_(false),
- id_(id),
- state_(MediaStreamTrackInterface::kLive),
+ webrtc::VideoTrackSourceInterface* source)
+ : id_(id),
source_(source),
- renderer_(NULL) {
-}
+ enabled_(true),
+ state_(webrtc::MediaStreamTrackInterface::kLive),
+ sink_(NULL) {}
MockWebRtcVideoTrack::~MockWebRtcVideoTrack() {}
-void MockWebRtcVideoTrack::AddRenderer(VideoRendererInterface* renderer) {
- DCHECK(!renderer_);
- renderer_ = renderer;
+scoped_refptr<MockWebRtcVideoTrack> MockWebRtcVideoTrack::Create(
+ const std::string& id) {
+ return new rtc::RefCountedObject<MockWebRtcVideoTrack>(id, nullptr);
+}
+
+void MockWebRtcVideoTrack::AddOrUpdateSink(
+ rtc::VideoSinkInterface<cricket::VideoFrame>* sink,
+ const rtc::VideoSinkWants& wants) {
+ DCHECK(!sink_);
+ sink_ = sink;
+}
+
+void MockWebRtcVideoTrack::RemoveSink(
+ rtc::VideoSinkInterface<cricket::VideoFrame>* sink) {
+ DCHECK(sink_ == sink);
+ sink_ = NULL;
}
-void MockWebRtcVideoTrack::RemoveRenderer(VideoRendererInterface* renderer) {
- DCHECK_EQ(renderer_, renderer);
- renderer_ = NULL;
+VideoTrackSourceInterface* MockWebRtcVideoTrack::GetSource() const {
+ return source_.get();
}
std::string MockWebRtcVideoTrack::kind() const {
- NOTIMPLEMENTED();
- return std::string();
+ return kVideoKind;
}
std::string MockWebRtcVideoTrack::id() const { return id_; }
@@ -332,13 +285,6 @@ bool MockWebRtcVideoTrack::set_enabled(bool enable) {
return true;
}
-bool MockWebRtcVideoTrack::set_state(TrackState new_state) {
- state_ = new_state;
- for (auto& o : observers_)
- o->OnChanged();
- return true;
-}
-
void MockWebRtcVideoTrack::RegisterObserver(ObserverInterface* observer) {
DCHECK(observers_.find(observer) == observers_.end());
observers_.insert(observer);
@@ -349,8 +295,11 @@ void MockWebRtcVideoTrack::UnregisterObserver(ObserverInterface* observer) {
observers_.erase(observer);
}
-VideoSourceInterface* MockWebRtcVideoTrack::GetSource() const {
- return source_.get();
+void MockWebRtcVideoTrack::SetEnded() {
+ DCHECK_EQ(webrtc::MediaStreamTrackInterface::kLive, state_);
+ state_ = webrtc::MediaStreamTrackInterface::kEnded;
+ for (auto& o : observers_)
+ o->OnChanged();
}
class MockSessionDescription : public SessionDescriptionInterface {
@@ -439,7 +388,6 @@ MockPeerConnectionDependencyFactory::~MockPeerConnectionDependencyFactory() {}
scoped_refptr<webrtc::PeerConnectionInterface>
MockPeerConnectionDependencyFactory::CreatePeerConnection(
const webrtc::PeerConnectionInterface::RTCConfiguration& config,
- const webrtc::MediaConstraintsInterface* constraints,
blink::WebFrame* frame,
webrtc::PeerConnectionObserver* observer) {
return new rtc::RefCountedObject<MockPeerConnectionImpl>(this, observer);
@@ -447,9 +395,9 @@ MockPeerConnectionDependencyFactory::CreatePeerConnection(
scoped_refptr<webrtc::AudioSourceInterface>
MockPeerConnectionDependencyFactory::CreateLocalAudioSource(
- const webrtc::MediaConstraintsInterface* constraints) {
+ const cricket::AudioOptions& options) {
last_audio_source_ =
- new rtc::RefCountedObject<MockAudioSource>(constraints, false);
+ new rtc::RefCountedObject<MockAudioSource>(options, false);
return last_audio_source_;
}
@@ -459,20 +407,17 @@ MockPeerConnectionDependencyFactory::CreateVideoCapturer(
return new MockRtcVideoCapturer(is_screen_capture);
}
-scoped_refptr<webrtc::VideoSourceInterface>
+scoped_refptr<webrtc::VideoTrackSourceInterface>
MockPeerConnectionDependencyFactory::CreateVideoSource(
- cricket::VideoCapturer* capturer,
- const blink::WebMediaConstraints& constraints) {
- last_video_source_ = new rtc::RefCountedObject<MockVideoSource>(false);
- last_video_source_->SetVideoCapturer(capturer);
- return last_video_source_;
+ cricket::VideoCapturer* capturer) {
+ // Video source normally take ownership of |capturer|.
+ delete capturer;
+ NOTIMPLEMENTED();
+ return nullptr;
}
-scoped_refptr<WebAudioCapturerSource>
-MockPeerConnectionDependencyFactory::CreateWebAudioSource(
- blink::WebMediaStreamSource* source) {
- return NULL;
-}
+void MockPeerConnectionDependencyFactory::CreateWebAudioSource(
+ blink::WebMediaStreamSource* source) {}
scoped_refptr<webrtc::MediaStreamInterface>
MockPeerConnectionDependencyFactory::CreateLocalMediaStream(
@@ -483,7 +428,7 @@ MockPeerConnectionDependencyFactory::CreateLocalMediaStream(
scoped_refptr<webrtc::VideoTrackInterface>
MockPeerConnectionDependencyFactory::CreateLocalVideoTrack(
const std::string& id,
- webrtc::VideoSourceInterface* source) {
+ webrtc::VideoTrackSourceInterface* source) {
scoped_refptr<webrtc::VideoTrackInterface> track(
new rtc::RefCountedObject<MockWebRtcVideoTrack>(
id, source));
@@ -494,11 +439,7 @@ scoped_refptr<webrtc::VideoTrackInterface>
MockPeerConnectionDependencyFactory::CreateLocalVideoTrack(
const std::string& id,
cricket::VideoCapturer* capturer) {
- scoped_refptr<MockVideoSource> source =
- new rtc::RefCountedObject<MockVideoSource>(false);
- source->SetVideoCapturer(capturer);
-
- return new rtc::RefCountedObject<MockWebRtcVideoTrack>(id, source.get());
+ return new rtc::RefCountedObject<MockWebRtcVideoTrack>(id, nullptr);
}
SessionDescriptionInterface*
@@ -517,7 +458,7 @@ MockPeerConnectionDependencyFactory::CreateIceCandidate(
return new MockIceCandidate(sdp_mid, sdp_mline_index, sdp);
}
-scoped_refptr<WebRtcAudioCapturer>
+std::unique_ptr<WebRtcAudioCapturer>
MockPeerConnectionDependencyFactory::CreateAudioCapturer(
int render_frame_id,
const StreamDeviceInfo& device_info,
@@ -532,9 +473,4 @@ MockPeerConnectionDependencyFactory::CreateAudioCapturer(
audio_source);
}
-void MockPeerConnectionDependencyFactory::StartLocalAudioTrack(
- WebRtcLocalAudioTrack* audio_track) {
- audio_track->Start();
-}
-
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h b/chromium/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h
index 15d6bf217f1..39881c633d6 100644
--- a/chromium/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h
+++ b/chromium/content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h
@@ -12,128 +12,93 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "content/renderer/media/webrtc/peer_connection_dependency_factory.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h"
-#include "third_party/libjingle/source/talk/media/base/videorenderer.h"
+#include "third_party/webrtc/api/mediaconstraintsinterface.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
namespace content {
-class WebAudioCapturerSource;
typedef std::set<webrtc::ObserverInterface*> ObserverSet;
-class MockVideoRenderer : public cricket::VideoRenderer {
- public:
- MockVideoRenderer();
- ~MockVideoRenderer() override;
- bool RenderFrame(const cricket::VideoFrame* frame) override;
-
- int num() const { return num_; }
-
- private:
- int num_;
-};
-
-class MockVideoSource : public webrtc::VideoSourceInterface {
+class MockAudioSource : public webrtc::AudioSourceInterface {
public:
- MockVideoSource(bool remote);
+ explicit MockAudioSource(const cricket::AudioOptions& options, bool remote);
void RegisterObserver(webrtc::ObserverInterface* observer) override;
void UnregisterObserver(webrtc::ObserverInterface* observer) override;
MediaSourceInterface::SourceState state() const override;
bool remote() const override;
- cricket::VideoCapturer* GetVideoCapturer() override;
- void AddSink(cricket::VideoRenderer* output) override;
- void RemoveSink(cricket::VideoRenderer* output) override;
- cricket::VideoRenderer* FrameInput() override;
- const cricket::VideoOptions* options() const override;
- void Stop() override;
- void Restart() override;
-
- // Changes the state of the source to live and notifies the observer.
- void SetLive();
- // Changes the state of the source to ended and notifies the observer.
- void SetEnded();
- // Set the video capturer.
- void SetVideoCapturer(cricket::VideoCapturer* capturer);
-
- // Test helpers.
- int GetLastFrameWidth() const;
- int GetLastFrameHeight() const;
- int GetFrameNum() const;
protected:
- ~MockVideoSource() override;
+ ~MockAudioSource() override;
private:
- void FireOnChanged();
-
- std::vector<webrtc::ObserverInterface*> observers_;
- MediaSourceInterface::SourceState state_;
bool remote_;
- scoped_ptr<cricket::VideoCapturer> capturer_;
- MockVideoRenderer renderer_;
+ ObserverSet observers_;
+ MediaSourceInterface::SourceState state_;
};
-class MockAudioSource : public webrtc::AudioSourceInterface {
+class MockWebRtcAudioTrack : public webrtc::AudioTrackInterface {
public:
- explicit MockAudioSource(
- const webrtc::MediaConstraintsInterface* constraints, bool remote);
+ static scoped_refptr<MockWebRtcAudioTrack> Create(const std::string& id);
+
+ void AddSink(webrtc::AudioTrackSinkInterface* sink) override {}
+ void RemoveSink(webrtc::AudioTrackSinkInterface* sink) override {}
+ webrtc::AudioSourceInterface* GetSource() const override;
+
+ std::string kind() const override;
+ std::string id() const override;
+ bool enabled() const override;
+ webrtc::MediaStreamTrackInterface::TrackState state() const override;
+ bool set_enabled(bool enable) override;
void RegisterObserver(webrtc::ObserverInterface* observer) override;
void UnregisterObserver(webrtc::ObserverInterface* observer) override;
- MediaSourceInterface::SourceState state() const override;
- bool remote() const override;
- // Changes the state of the source to live and notifies the observer.
- void SetLive();
- // Changes the state of the source to ended and notifies the observer.
void SetEnded();
- const webrtc::MediaConstraintsInterface::Constraints& optional_constraints() {
- return optional_constraints_;
- }
-
- const webrtc::MediaConstraintsInterface::Constraints&
- mandatory_constraints() {
- return mandatory_constraints_;
- }
-
protected:
- ~MockAudioSource() override;
+ MockWebRtcAudioTrack(const std::string& id);
+ ~MockWebRtcAudioTrack() override;
private:
- bool remote_;
+ std::string id_;
+ scoped_refptr<webrtc::VideoTrackSourceInterface> source_;
+ bool enabled_;
+ TrackState state_;
ObserverSet observers_;
- MediaSourceInterface::SourceState state_;
- webrtc::MediaConstraintsInterface::Constraints optional_constraints_;
- webrtc::MediaConstraintsInterface::Constraints mandatory_constraints_;
};
class MockWebRtcVideoTrack : public webrtc::VideoTrackInterface {
public:
+ static scoped_refptr<MockWebRtcVideoTrack> Create(const std::string& id);
MockWebRtcVideoTrack(const std::string& id,
- webrtc::VideoSourceInterface* source);
- void AddRenderer(webrtc::VideoRendererInterface* renderer) override;
- void RemoveRenderer(webrtc::VideoRendererInterface* renderer) override;
+ webrtc::VideoTrackSourceInterface* source);
+ void AddOrUpdateSink(rtc::VideoSinkInterface<cricket::VideoFrame>* sink,
+ const rtc::VideoSinkWants& wants) override;
+ void RemoveSink(rtc::VideoSinkInterface<cricket::VideoFrame>* sink) override;
+ webrtc::VideoTrackSourceInterface* GetSource() const override;
+
std::string kind() const override;
std::string id() const override;
bool enabled() const override;
- TrackState state() const override;
+ webrtc::MediaStreamTrackInterface::TrackState state() const override;
bool set_enabled(bool enable) override;
- bool set_state(TrackState new_state) override;
+
void RegisterObserver(webrtc::ObserverInterface* observer) override;
void UnregisterObserver(webrtc::ObserverInterface* observer) override;
- webrtc::VideoSourceInterface* GetSource() const override;
+
+ void SetEnded();
protected:
~MockWebRtcVideoTrack() override;
private:
- bool enabled_;
std::string id_;
+ scoped_refptr<webrtc::VideoTrackSourceInterface> source_;
+ bool enabled_;
TrackState state_;
- scoped_refptr<webrtc::VideoSourceInterface> source_;
ObserverSet observers_;
- webrtc::VideoRendererInterface* renderer_;
+ rtc::VideoSinkInterface<cricket::VideoFrame>* sink_;
};
class MockMediaStream : public webrtc::MediaStreamInterface {
@@ -177,23 +142,20 @@ class MockPeerConnectionDependencyFactory
scoped_refptr<webrtc::PeerConnectionInterface> CreatePeerConnection(
const webrtc::PeerConnectionInterface::RTCConfiguration& config,
- const webrtc::MediaConstraintsInterface* constraints,
blink::WebFrame* frame,
webrtc::PeerConnectionObserver* observer) override;
scoped_refptr<webrtc::AudioSourceInterface> CreateLocalAudioSource(
- const webrtc::MediaConstraintsInterface* constraints) override;
+ const cricket::AudioOptions& options) override;
WebRtcVideoCapturerAdapter* CreateVideoCapturer(
bool is_screen_capture) override;
- scoped_refptr<webrtc::VideoSourceInterface> CreateVideoSource(
- cricket::VideoCapturer* capturer,
- const blink::WebMediaConstraints& constraints) override;
- scoped_refptr<WebAudioCapturerSource> CreateWebAudioSource(
- blink::WebMediaStreamSource* source) override;
+ scoped_refptr<webrtc::VideoTrackSourceInterface> CreateVideoSource(
+ cricket::VideoCapturer* capturer) override;
+ void CreateWebAudioSource(blink::WebMediaStreamSource* source) override;
scoped_refptr<webrtc::MediaStreamInterface> CreateLocalMediaStream(
const std::string& label) override;
scoped_refptr<webrtc::VideoTrackInterface> CreateLocalVideoTrack(
const std::string& id,
- webrtc::VideoSourceInterface* source) override;
+ webrtc::VideoTrackSourceInterface* source) override;
scoped_refptr<webrtc::VideoTrackInterface> CreateLocalVideoTrack(
const std::string& id,
cricket::VideoCapturer* capturer) override;
@@ -206,7 +168,7 @@ class MockPeerConnectionDependencyFactory
int sdp_mline_index,
const std::string& sdp) override;
- scoped_refptr<WebRtcAudioCapturer> CreateAudioCapturer(
+ std::unique_ptr<WebRtcAudioCapturer> CreateAudioCapturer(
int render_frame_id,
const StreamDeviceInfo& device_info,
const blink::WebMediaConstraints& constraints,
@@ -215,15 +177,11 @@ class MockPeerConnectionDependencyFactory
fail_to_create_next_audio_capturer_ = true;
}
- void StartLocalAudioTrack(WebRtcLocalAudioTrack* audio_track) override;
-
MockAudioSource* last_audio_source() { return last_audio_source_.get(); }
- MockVideoSource* last_video_source() { return last_video_source_.get(); }
private:
bool fail_to_create_next_audio_capturer_;
scoped_refptr <MockAudioSource> last_audio_source_;
- scoped_refptr <MockVideoSource> last_video_source_;
DISALLOW_COPY_AND_ASSIGN(MockPeerConnectionDependencyFactory);
};
diff --git a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
index 270cf169851..0885aefb1e6 100644
--- a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
+++ b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.cc
@@ -9,10 +9,13 @@
#include <utility>
#include <vector>
+#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/metrics/field_trial.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -21,6 +24,8 @@
#include "content/common/media/media_stream_messages.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
+#include "content/public/common/feature_h264_with_openh264_ffmpeg.h"
+#include "content/public/common/features.h"
#include "content/public/common/renderer_preferences.h"
#include "content/public/common/webrtc_ip_handling_policy.h"
#include "content/public/renderer/content_renderer_client.h"
@@ -28,10 +33,10 @@
#include "content/renderer/media/media_stream_audio_processor.h"
#include "content/renderer/media/media_stream_audio_processor_options.h"
#include "content/renderer/media/media_stream_audio_source.h"
+#include "content/renderer/media/media_stream_constraints_util.h"
#include "content/renderer/media/media_stream_video_source.h"
#include "content/renderer/media/media_stream_video_track.h"
#include "content/renderer/media/peer_connection_identity_store.h"
-#include "content/renderer/media/rtc_media_constraints.h"
#include "content/renderer/media/rtc_peer_connection_handler.h"
#include "content/renderer/media/rtc_video_decoder_factory.h"
#include "content/renderer/media/rtc_video_encoder_factory.h"
@@ -55,6 +60,7 @@
#include "crypto/openssl_util.h"
#include "jingle/glue/thread_wrapper.h"
#include "media/base/media_permission.h"
+#include "media/filters/ffmpeg_glue.h"
#include "media/renderers/gpu_video_accelerator_factories.h"
#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
#include "third_party/WebKit/public/platform/WebMediaStream.h"
@@ -63,8 +69,11 @@
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebFrame.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediaconstraintsinterface.h"
+#include "third_party/webrtc/api/dtlsidentitystore.h"
+#include "third_party/webrtc/api/mediaconstraintsinterface.h"
#include "third_party/webrtc/base/ssladapter.h"
+#include "third_party/webrtc/media/base/mediachannel.h"
+#include "third_party/webrtc/modules/video_coding/codecs/h264/include/h264.h"
#if defined(OS_ANDROID)
#include "media/base/android/media_codec_util.h"
@@ -94,52 +103,6 @@ WebRTCIPHandlingPolicy GetWebRTCIPHandlingPolicy(
} // namespace
-// Map of corresponding media constraints and platform effects.
-struct {
- const char* constraint;
- const media::AudioParameters::PlatformEffectsMask effect;
-} const kConstraintEffectMap[] = {
- { webrtc::MediaConstraintsInterface::kGoogEchoCancellation,
- media::AudioParameters::ECHO_CANCELLER },
-};
-
-// If any platform effects are available, check them against the constraints.
-// Disable effects to match false constraints, but if a constraint is true, set
-// the constraint to false to later disable the software effect.
-//
-// This function may modify both |constraints| and |effects|.
-void HarmonizeConstraintsAndEffects(RTCMediaConstraints* constraints,
- int* effects) {
- if (*effects != media::AudioParameters::NO_EFFECTS) {
- for (size_t i = 0; i < arraysize(kConstraintEffectMap); ++i) {
- bool value;
- size_t is_mandatory = 0;
- if (!webrtc::FindConstraint(constraints,
- kConstraintEffectMap[i].constraint,
- &value,
- &is_mandatory) || !value) {
- // If the constraint is false, or does not exist, disable the platform
- // effect.
- *effects &= ~kConstraintEffectMap[i].effect;
- DVLOG(1) << "Disabling platform effect: "
- << kConstraintEffectMap[i].effect;
- } else if (*effects & kConstraintEffectMap[i].effect) {
- // If the constraint is true, leave the platform effect enabled, and
- // set the constraint to false to later disable the software effect.
- if (is_mandatory) {
- constraints->AddMandatory(kConstraintEffectMap[i].constraint,
- webrtc::MediaConstraintsInterface::kValueFalse, true);
- } else {
- constraints->AddOptional(kConstraintEffectMap[i].constraint,
- webrtc::MediaConstraintsInterface::kValueFalse, true);
- }
- DVLOG(1) << "Disabling constraint: "
- << kConstraintEffectMap[i].constraint;
- }
- }
- }
-}
-
PeerConnectionDependencyFactory::PeerConnectionDependencyFactory(
P2PSocketDispatcher* p2p_socket_dispatcher)
: network_manager_(NULL),
@@ -175,17 +138,55 @@ bool PeerConnectionDependencyFactory::InitializeMediaStreamAudioSource(
// Do additional source initialization if the audio source is a valid
// microphone or tab audio.
- RTCMediaConstraints native_audio_constraints(audio_constraints);
- MediaAudioConstraints::ApplyFixedAudioConstraints(&native_audio_constraints);
StreamDeviceInfo device_info = source_data->device_info();
- RTCMediaConstraints constraints = native_audio_constraints;
- // May modify both |constraints| and |effects|.
- HarmonizeConstraintsAndEffects(&constraints,
- &device_info.device.input.effects);
- scoped_refptr<WebRtcAudioCapturer> capturer(CreateAudioCapturer(
- render_frame_id, device_info, audio_constraints, source_data));
+ cricket::AudioOptions options;
+ // Apply relevant constraints.
+ options.echo_cancellation = ConstraintToOptional(
+ audio_constraints, &blink::WebMediaTrackConstraintSet::echoCancellation);
+ options.delay_agnostic_aec = ConstraintToOptional(
+ audio_constraints,
+ &blink::WebMediaTrackConstraintSet::googDAEchoCancellation);
+ options.auto_gain_control = ConstraintToOptional(
+ audio_constraints,
+ &blink::WebMediaTrackConstraintSet::googAutoGainControl);
+ options.experimental_agc = ConstraintToOptional(
+ audio_constraints,
+ &blink::WebMediaTrackConstraintSet::googExperimentalAutoGainControl);
+ options.noise_suppression = ConstraintToOptional(
+ audio_constraints,
+ &blink::WebMediaTrackConstraintSet::googNoiseSuppression);
+ options.experimental_ns = ConstraintToOptional(
+ audio_constraints,
+ &blink::WebMediaTrackConstraintSet::googExperimentalNoiseSuppression);
+ options.highpass_filter = ConstraintToOptional(
+ audio_constraints,
+ &blink::WebMediaTrackConstraintSet::googHighpassFilter);
+ options.typing_detection = ConstraintToOptional(
+ audio_constraints,
+ &blink::WebMediaTrackConstraintSet::googTypingNoiseDetection);
+ options.stereo_swapping = ConstraintToOptional(
+ audio_constraints,
+ &blink::WebMediaTrackConstraintSet::googAudioMirroring);
+
+ MediaAudioConstraints::ApplyFixedAudioConstraints(&options);
+
+ if (device_info.device.input.effects &
+ media::AudioParameters::ECHO_CANCELLER) {
+ // TODO(hta): Figure out if we should be looking at echoCancellation.
+ // Previous code had googEchoCancellation only.
+ const blink::BooleanConstraint& echoCancellation =
+ audio_constraints.basic().googEchoCancellation;
+ if (echoCancellation.hasExact() && !echoCancellation.exact()) {
+ device_info.device.input.effects &=
+ ~media::AudioParameters::ECHO_CANCELLER;
+ }
+ options.echo_cancellation = rtc::Optional<bool>(false);
+ }
+
+ std::unique_ptr<WebRtcAudioCapturer> capturer = CreateAudioCapturer(
+ render_frame_id, device_info, audio_constraints, source_data);
if (!capturer.get()) {
const std::string log_string =
"PCDF::InitializeMediaStreamAudioSource: fails to create capturer";
@@ -197,7 +198,7 @@ bool PeerConnectionDependencyFactory::InitializeMediaStreamAudioSource(
// be called multiple times which is likely also a bug.
return false;
}
- source_data->SetAudioCapturer(capturer.get());
+ source_data->SetAudioCapturer(std::move(capturer));
// Creates a LocalAudioSource object which holds audio options.
// TODO(xians): The option should apply to the track instead of the source.
@@ -205,7 +206,7 @@ bool PeerConnectionDependencyFactory::InitializeMediaStreamAudioSource(
// Currently there are a few constraints that are parsed by libjingle and
// the state is set to ended if parsing fails.
scoped_refptr<webrtc::AudioSourceInterface> rtc_source(
- CreateLocalAudioSource(&constraints).get());
+ CreateLocalAudioSource(options).get());
if (rtc_source->state() != webrtc::MediaSourceInterface::kLive) {
DLOG(WARNING) << "Failed to create rtc LocalAudioSource.";
return false;
@@ -226,13 +227,11 @@ PeerConnectionDependencyFactory::CreateVideoCapturer(
return new WebRtcVideoCapturerAdapter(is_screeencast);
}
-scoped_refptr<webrtc::VideoSourceInterface>
+scoped_refptr<webrtc::VideoTrackSourceInterface>
PeerConnectionDependencyFactory::CreateVideoSource(
- cricket::VideoCapturer* capturer,
- const blink::WebMediaConstraints& constraints) {
- RTCMediaConstraints webrtc_constraints(constraints);
- scoped_refptr<webrtc::VideoSourceInterface> source =
- GetPcFactory()->CreateVideoSource(capturer, &webrtc_constraints).get();
+ cricket::VideoCapturer* capturer) {
+ scoped_refptr<webrtc::VideoTrackSourceInterface> source =
+ GetPcFactory()->CreateVideoSource(capturer).get();
return source;
}
@@ -259,6 +258,18 @@ void PeerConnectionDependencyFactory::CreatePeerConnectionFactory() {
DVLOG(1) << "PeerConnectionDependencyFactory::CreatePeerConnectionFactory()";
+#if BUILDFLAG(RTC_USE_H264)
+ // Building /w |rtc_use_h264|, is the corresponding run-time feature enabled?
+ if (base::FeatureList::IsEnabled(kWebRtcH264WithOpenH264FFmpeg)) {
+ // |H264DecoderImpl| may be used which depends on FFmpeg, therefore we need
+ // to initialize FFmpeg before going further.
+ media::FFmpegGlue::InitializeFFmpeg();
+ } else {
+ // Feature is to be disabled, no need to make sure FFmpeg is initialized.
+ webrtc::DisableRtcUseH264();
+ }
+#endif
+
base::MessageLoop::current()->AddDestructionObserver(this);
// To allow sending to the signaling/worker threads.
jingle_glue::JingleThreadWrapper::EnsureForCurrentMessageLoop();
@@ -286,12 +297,6 @@ void PeerConnectionDependencyFactory::CreatePeerConnectionFactory() {
CHECK(worker_thread_);
// Init SSL, which will be needed by PeerConnection.
- //
- // TODO(davidben): BoringSSL must be initialized by Chromium code. If the
- // initialization requirement is removed or when different libraries are
- // allowed to call CRYPTO_library_init concurrently, remove this line and
- // initialize within WebRTC. See https://crbug.com/542879.
- crypto::EnsureOpenSSLInit();
if (!rtc::InitializeSSL()) {
LOG(ERROR) << "Failed on InitializeSSL.";
NOTREACHED();
@@ -326,8 +331,8 @@ void PeerConnectionDependencyFactory::InitializeSignalingThread(
socket_factory_.reset(
new IpcPacketSocketFactory(p2p_socket_dispatcher_.get()));
- scoped_ptr<cricket::WebRtcVideoDecoderFactory> decoder_factory;
- scoped_ptr<cricket::WebRtcVideoEncoderFactory> encoder_factory;
+ std::unique_ptr<cricket::WebRtcVideoDecoderFactory> decoder_factory;
+ std::unique_ptr<cricket::WebRtcVideoEncoderFactory> encoder_factory;
const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
if (gpu_factories && gpu_factories->IsGpuVideoAcceleratorEnabled()) {
@@ -372,7 +377,6 @@ bool PeerConnectionDependencyFactory::PeerConnectionFactoryCreated() {
scoped_refptr<webrtc::PeerConnectionInterface>
PeerConnectionDependencyFactory::CreatePeerConnection(
const webrtc::PeerConnectionInterface::RTCConfiguration& config,
- const webrtc::MediaConstraintsInterface* constraints,
blink::WebFrame* web_frame,
webrtc::PeerConnectionObserver* observer) {
CHECK(web_frame);
@@ -382,8 +386,7 @@ PeerConnectionDependencyFactory::CreatePeerConnection(
rtc::scoped_ptr<PeerConnectionIdentityStore> identity_store(
new PeerConnectionIdentityStore(
- base::ThreadTaskRunnerHandle::Get(),
- GetWebRtcSignalingThread(),
+ base::ThreadTaskRunnerHandle::Get(), GetWebRtcSignalingThread(),
GURL(web_frame->document().url()),
GURL(web_frame->document().firstPartyForCookies())));
@@ -396,7 +399,17 @@ PeerConnectionDependencyFactory::CreatePeerConnection(
// which means the permission will be granted automatically. This could be the
// case when either the experiment is not enabled or the preference is not
// enforced.
- scoped_ptr<media::MediaPermission> media_permission;
+ //
+ // Note on |media_permission| lifetime: |media_permission| is owned by a frame
+ // (RenderFrameImpl). It is also stored as an indirect member of
+ // RTCPeerConnectionHandler (through PeerConnection/PeerConnectionInterface ->
+ // P2PPortAllocator -> FilteringNetworkManager -> |media_permission|).
+ // The RTCPeerConnectionHandler is owned as RTCPeerConnection::m_peerHandler
+ // in Blink, which will be reset in RTCPeerConnection::stop(). Since
+ // ActiveDOMObject::stop() is guaranteed to be called before a frame is
+ // detached, it is impossible for RTCPeerConnectionHandler to outlive the
+ // frame. Therefore using a raw pointer of |media_permission| is safe here.
+ media::MediaPermission* media_permission = nullptr;
if (!GetContentClient()
->renderer()
->ShouldEnforceWebRTCRoutingPreferences()) {
@@ -447,16 +460,14 @@ PeerConnectionDependencyFactory::CreatePeerConnection(
switches::kEnforceWebRtcIPPermissionCheck);
create_media_permission =
create_media_permission ||
- StartsWith(base::FieldTrialList::FindFullName(
- "WebRTC-LocalIPPermissionCheck"),
- "Enabled", base::CompareCase::SENSITIVE);
+ !StartsWith(base::FieldTrialList::FindFullName(
+ "WebRTC-LocalIPPermissionCheck"),
+ "Disabled", base::CompareCase::SENSITIVE);
if (create_media_permission) {
content::RenderFrameImpl* render_frame =
content::RenderFrameImpl::FromWebFrame(web_frame);
- if (render_frame) {
- media_permission = render_frame->CreateMediaPermissionProxy(
- chrome_worker_thread_.task_runner());
- }
+ if (render_frame)
+ media_permission = render_frame->GetMediaPermission();
DCHECK(media_permission);
}
}
@@ -465,13 +476,12 @@ PeerConnectionDependencyFactory::CreatePeerConnection(
const GURL& requesting_origin =
GURL(web_frame->document().url()).GetOrigin();
- scoped_ptr<rtc::NetworkManager> network_manager;
+ std::unique_ptr<rtc::NetworkManager> network_manager;
if (port_config.enable_multiple_routes) {
- media::MediaPermission* media_permission_ptr = media_permission.get();
FilteringNetworkManager* filtering_network_manager =
new FilteringNetworkManager(network_manager_, requesting_origin,
- std::move(media_permission));
- if (media_permission_ptr) {
+ media_permission);
+ if (media_permission) {
// Start permission check earlier to reduce any impact to call set up
// time. It's safe to use Unretained here since both destructor and
// Initialize can only be called on the worker thread.
@@ -488,11 +498,31 @@ PeerConnectionDependencyFactory::CreatePeerConnection(
port_config, requesting_origin, chrome_worker_thread_.task_runner()));
return GetPcFactory()
- ->CreatePeerConnection(config, constraints, std::move(port_allocator),
+ ->CreatePeerConnection(config, std::move(port_allocator),
std::move(identity_store), observer)
.get();
}
+// static
+void PeerConnectionDependencyFactory::SetDefaultCertificate(
+ webrtc::PeerConnectionInterface::RTCConfiguration* config) {
+ if (config->certificates.empty()) {
+ rtc::scoped_ptr<rtc::SSLIdentity> identity(rtc::SSLIdentity::Generate(
+ webrtc::kIdentityName, rtc::KeyParams::ECDSA(rtc::EC_NIST_P256)));
+ rtc::scoped_refptr<rtc::RTCCertificate> certificate =
+ rtc::RTCCertificate::Create(std::move(identity));
+ config->certificates.push_back(certificate);
+ }
+}
+
+// static
+rtc::scoped_refptr<rtc::RTCCertificate>
+PeerConnectionDependencyFactory::GenerateDefaultCertificate() {
+ rtc::scoped_ptr<rtc::SSLIdentity> identity(rtc::SSLIdentity::Generate(
+ webrtc::kIdentityName, rtc::KeyParams::ECDSA(rtc::EC_NIST_P256)));
+ return rtc::RTCCertificate::Create(std::move(identity));
+}
+
scoped_refptr<webrtc::MediaStreamInterface>
PeerConnectionDependencyFactory::CreateLocalMediaStream(
const std::string& label) {
@@ -501,30 +531,27 @@ PeerConnectionDependencyFactory::CreateLocalMediaStream(
scoped_refptr<webrtc::AudioSourceInterface>
PeerConnectionDependencyFactory::CreateLocalAudioSource(
- const webrtc::MediaConstraintsInterface* constraints) {
+ const cricket::AudioOptions& options) {
scoped_refptr<webrtc::AudioSourceInterface> source =
- GetPcFactory()->CreateAudioSource(constraints).get();
+ GetPcFactory()->CreateAudioSource(options).get();
return source;
}
void PeerConnectionDependencyFactory::CreateLocalAudioTrack(
const blink::WebMediaStreamTrack& track) {
blink::WebMediaStreamSource source = track.source();
- DCHECK_EQ(source.type(), blink::WebMediaStreamSource::TypeAudio);
- DCHECK(!source.remote());
- MediaStreamAudioSource* source_data =
- static_cast<MediaStreamAudioSource*>(source.extraData());
+ DCHECK_EQ(source.getType(), blink::WebMediaStreamSource::TypeAudio);
+ MediaStreamAudioSource* source_data = MediaStreamAudioSource::From(source);
- scoped_refptr<WebAudioCapturerSource> webaudio_source;
if (!source_data) {
if (source.requiresAudioConsumer()) {
// We're adding a WebAudio MediaStream.
// Create a specific capturer for each WebAudio consumer.
- webaudio_source = CreateWebAudioSource(&source);
- source_data =
- static_cast<MediaStreamAudioSource*>(source.extraData());
+ CreateWebAudioSource(&source);
+ source_data = MediaStreamAudioSource::From(source);
+ DCHECK(source_data->webaudio_capturer());
} else {
- NOTREACHED() << "Local track missing source extra data.";
+ NOTREACHED() << "Local track missing MediaStreamAudioSource instance.";
return;
}
}
@@ -539,10 +566,22 @@ void PeerConnectionDependencyFactory::CreateLocalAudioTrack(
// TODO(xians): Merge |source| to the capturer(). We can't do this today
// because only one capturer() is supported while one |source| is created
// for each audio track.
- scoped_ptr<WebRtcLocalAudioTrack> audio_track(new WebRtcLocalAudioTrack(
- adapter.get(), source_data->GetAudioCapturer(), webaudio_source.get()));
+ std::unique_ptr<WebRtcLocalAudioTrack> audio_track(
+ new WebRtcLocalAudioTrack(adapter.get()));
- StartLocalAudioTrack(audio_track.get());
+ // Start the source and connect the audio data flow to the track.
+ //
+ // TODO(miu): This logic will me moved to MediaStreamAudioSource (or a
+ // subclass of it) in soon-upcoming changes.
+ audio_track->Start(base::Bind(&MediaStreamAudioSource::StopAudioDeliveryTo,
+ source_data->GetWeakPtr(),
+ audio_track.get()));
+ if (source_data->webaudio_capturer())
+ source_data->webaudio_capturer()->Start(audio_track.get());
+ else if (source_data->audio_capturer())
+ source_data->audio_capturer()->AddTrack(audio_track.get());
+ else
+ NOTREACHED();
// Pass the ownership of the native local audio track to the blink track.
blink::WebMediaStreamTrack writable_track = track;
@@ -552,56 +591,34 @@ void PeerConnectionDependencyFactory::CreateLocalAudioTrack(
void PeerConnectionDependencyFactory::CreateRemoteAudioTrack(
const blink::WebMediaStreamTrack& track) {
blink::WebMediaStreamSource source = track.source();
- DCHECK_EQ(source.type(), blink::WebMediaStreamSource::TypeAudio);
+ DCHECK_EQ(source.getType(), blink::WebMediaStreamSource::TypeAudio);
DCHECK(source.remote());
- DCHECK(source.extraData());
+ DCHECK(MediaStreamAudioSource::From(source));
blink::WebMediaStreamTrack writable_track = track;
writable_track.setExtraData(
new MediaStreamRemoteAudioTrack(source, track.isEnabled()));
}
-void PeerConnectionDependencyFactory::StartLocalAudioTrack(
- WebRtcLocalAudioTrack* audio_track) {
- // Start the audio track. This will hook the |audio_track| to the capturer
- // as the sink of the audio, and only start the source of the capturer if
- // it is the first audio track connecting to the capturer.
- audio_track->Start();
-}
-
-scoped_refptr<WebAudioCapturerSource>
-PeerConnectionDependencyFactory::CreateWebAudioSource(
+void PeerConnectionDependencyFactory::CreateWebAudioSource(
blink::WebMediaStreamSource* source) {
DVLOG(1) << "PeerConnectionDependencyFactory::CreateWebAudioSource()";
- scoped_refptr<WebAudioCapturerSource>
- webaudio_capturer_source(new WebAudioCapturerSource(*source));
MediaStreamAudioSource* source_data = new MediaStreamAudioSource();
-
- // Use the current default capturer for the WebAudio track so that the
- // WebAudio track can pass a valid delay value and |need_audio_processing|
- // flag to PeerConnection.
- // TODO(xians): Remove this after moving APM to Chrome.
- if (GetWebRtcAudioDevice()) {
- source_data->SetAudioCapturer(
- GetWebRtcAudioDevice()->GetDefaultCapturer());
- }
+ source_data->SetWebAudioCapturer(
+ base::WrapUnique(new WebAudioCapturerSource(source)));
// Create a LocalAudioSource object which holds audio options.
// SetLocalAudioSource() affects core audio parts in third_party/Libjingle.
- source_data->SetLocalAudioSource(CreateLocalAudioSource(NULL).get());
+ cricket::AudioOptions options;
+ source_data->SetLocalAudioSource(CreateLocalAudioSource(options).get());
source->setExtraData(source_data);
-
- // Replace the default source with WebAudio as source instead.
- source->addAudioConsumer(webaudio_capturer_source.get());
-
- return webaudio_capturer_source;
}
scoped_refptr<webrtc::VideoTrackInterface>
PeerConnectionDependencyFactory::CreateLocalVideoTrack(
const std::string& id,
- webrtc::VideoSourceInterface* source) {
+ webrtc::VideoTrackSourceInterface* source) {
return GetPcFactory()->CreateVideoTrack(id, source).get();
}
@@ -614,7 +631,7 @@ PeerConnectionDependencyFactory::CreateLocalVideoTrack(
}
// Create video source from the |capturer|.
- scoped_refptr<webrtc::VideoSourceInterface> source =
+ scoped_refptr<webrtc::VideoTrackSourceInterface> source =
GetPcFactory()->CreateVideoSource(capturer, NULL).get();
// Create native track from the source.
@@ -736,7 +753,7 @@ void PeerConnectionDependencyFactory::CleanupPeerConnectionFactory() {
}
}
-scoped_refptr<WebRtcAudioCapturer>
+std::unique_ptr<WebRtcAudioCapturer>
PeerConnectionDependencyFactory::CreateAudioCapturer(
int render_frame_id,
const StreamDeviceInfo& device_info,
diff --git a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h
index a5bdb342be6..e58174311a6 100644
--- a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h
+++ b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory.h
@@ -16,8 +16,7 @@
#include "content/renderer/media/webrtc/stun_field_trial.h"
#include "content/renderer/p2p/socket_dispatcher.h"
#include "ipc/ipc_platform_file.h"
-#include "third_party/libjingle/source/talk/app/webrtc/peerconnectioninterface.h"
-#include "third_party/libjingle/source/talk/app/webrtc/videosourceinterface.h"
+#include "third_party/webrtc/api/peerconnectioninterface.h"
#include "third_party/webrtc/p2p/stunprober/stunprober.h"
namespace base {
@@ -49,7 +48,6 @@ namespace content {
class IpcNetworkManager;
class IpcPacketSocketFactory;
class MediaStreamAudioSource;
-class RTCMediaConstraints;
class WebAudioCapturerSource;
class WebRtcAudioCapturer;
class WebRtcAudioDeviceImpl;
@@ -73,6 +71,12 @@ class CONTENT_EXPORT PeerConnectionDependencyFactory
blink::WebRTCPeerConnectionHandler* CreateRTCPeerConnectionHandler(
blink::WebRTCPeerConnectionHandlerClient* client);
+ // Add an ECDSA certificate to |config| in case it contains no certificate.
+ static void SetDefaultCertificate(
+ webrtc::PeerConnectionInterface::RTCConfiguration* config);
+
+ static rtc::scoped_refptr<rtc::RTCCertificate> GenerateDefaultCertificate();
+
// Asks the PeerConnection factory to create a Local MediaStream object.
virtual scoped_refptr<webrtc::MediaStreamInterface>
CreateLocalMediaStream(const std::string& label);
@@ -85,7 +89,7 @@ class CONTENT_EXPORT PeerConnectionDependencyFactory
MediaStreamAudioSource* source_data);
// Creates an implementation of a cricket::VideoCapturer object that can be
- // used when creating a libjingle webrtc::VideoSourceInterface object.
+ // used when creating a libjingle webrtc::VideoTrackSourceInterface object.
virtual WebRtcVideoCapturerAdapter* CreateVideoCapturer(
bool is_screen_capture);
@@ -98,15 +102,14 @@ class CONTENT_EXPORT PeerConnectionDependencyFactory
void CreateRemoteAudioTrack(const blink::WebMediaStreamTrack& track);
// Asks the PeerConnection factory to create a Local VideoTrack object.
- virtual scoped_refptr<webrtc::VideoTrackInterface>
- CreateLocalVideoTrack(const std::string& id,
- webrtc::VideoSourceInterface* source);
+ virtual scoped_refptr<webrtc::VideoTrackInterface> CreateLocalVideoTrack(
+ const std::string& id,
+ webrtc::VideoTrackSourceInterface* source);
// Asks the PeerConnection factory to create a Video Source.
// The video source takes ownership of |capturer|.
- virtual scoped_refptr<webrtc::VideoSourceInterface>
- CreateVideoSource(cricket::VideoCapturer* capturer,
- const blink::WebMediaConstraints& constraints);
+ virtual scoped_refptr<webrtc::VideoTrackSourceInterface> CreateVideoSource(
+ cricket::VideoCapturer* capturer);
// Asks the libjingle PeerConnection factory to create a libjingle
// PeerConnection object.
@@ -114,7 +117,6 @@ class CONTENT_EXPORT PeerConnectionDependencyFactory
virtual scoped_refptr<webrtc::PeerConnectionInterface>
CreatePeerConnection(
const webrtc::PeerConnectionInterface::RTCConfiguration& config,
- const webrtc::MediaConstraintsInterface* constraints,
blink::WebFrame* web_frame,
webrtc::PeerConnectionObserver* observer);
@@ -145,16 +147,15 @@ class CONTENT_EXPORT PeerConnectionDependencyFactory
protected:
// Asks the PeerConnection factory to create a Local Audio Source.
- virtual scoped_refptr<webrtc::AudioSourceInterface>
- CreateLocalAudioSource(
- const webrtc::MediaConstraintsInterface* constraints);
+ virtual scoped_refptr<webrtc::AudioSourceInterface> CreateLocalAudioSource(
+ const cricket::AudioOptions& options);
// Creates a media::AudioCapturerSource with an implementation that is
// specific for a WebAudio source. The created WebAudioCapturerSource
// instance will function as audio source instead of the default
- // WebRtcAudioCapturer.
- virtual scoped_refptr<WebAudioCapturerSource> CreateWebAudioSource(
- blink::WebMediaStreamSource* source);
+ // WebRtcAudioCapturer. Ownership of the new WebAudioCapturerSource is
+ // transferred to |source|.
+ virtual void CreateWebAudioSource(blink::WebMediaStreamSource* source);
// Asks the PeerConnection factory to create a Local VideoTrack object with
// the video source using |capturer|.
@@ -169,17 +170,12 @@ class CONTENT_EXPORT PeerConnectionDependencyFactory
// Returns a new capturer or existing capturer based on the |render_frame_id|
// and |device_info|; if both are valid, it reuses existing capture if any --
// otherwise it creates a new capturer.
- virtual scoped_refptr<WebRtcAudioCapturer> CreateAudioCapturer(
+ virtual std::unique_ptr<WebRtcAudioCapturer> CreateAudioCapturer(
int render_frame_id,
const StreamDeviceInfo& device_info,
const blink::WebMediaConstraints& constraints,
MediaStreamAudioSource* audio_source);
- // Adds the audio device as a sink to the audio track and starts the local
- // audio track. This is virtual for test purposes since no real audio device
- // exist in unit tests.
- virtual void StartLocalAudioTrack(WebRtcLocalAudioTrack* audio_track);
-
private:
// Implement base::MessageLoop::DestructionObserver.
// This makes sure the libjingle PeerConnectionFactory is released before
@@ -212,14 +208,14 @@ class CONTENT_EXPORT PeerConnectionDependencyFactory
// We own network_manager_, must be deleted on the worker thread.
// The network manager uses |p2p_socket_dispatcher_|.
IpcNetworkManager* network_manager_;
- scoped_ptr<IpcPacketSocketFactory> socket_factory_;
+ std::unique_ptr<IpcPacketSocketFactory> socket_factory_;
scoped_refptr<webrtc::PeerConnectionFactoryInterface> pc_factory_;
scoped_refptr<P2PSocketDispatcher> p2p_socket_dispatcher_;
scoped_refptr<WebRtcAudioDeviceImpl> audio_device_;
- scoped_ptr<StunProberTrial> stun_trial_;
+ std::unique_ptr<StunProberTrial> stun_trial_;
// PeerConnection threads. signaling_thread_ is created from the
// "current" chrome thread.
diff --git a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory_unittest.cc b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory_unittest.cc
index 4009d978371..1747aecf857 100644
--- a/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/peer_connection_dependency_factory_unittest.cc
@@ -18,12 +18,12 @@ class PeerConnectionDependencyFactoryTest : public ::testing::Test {
protected:
base::MessageLoop message_loop_;
- scoped_ptr<MockPeerConnectionDependencyFactory> dependency_factory_;
+ std::unique_ptr<MockPeerConnectionDependencyFactory> dependency_factory_;
};
TEST_F(PeerConnectionDependencyFactoryTest, CreateRTCPeerConnectionHandler) {
MockWebRTCPeerConnectionHandlerClient client_jsep;
- scoped_ptr<blink::WebRTCPeerConnectionHandler> pc_handler(
+ std::unique_ptr<blink::WebRTCPeerConnectionHandler> pc_handler(
dependency_factory_->CreateRTCPeerConnectionHandler(&client_jsep));
EXPECT_TRUE(pc_handler.get() != NULL);
}
diff --git a/chromium/content/renderer/media/webrtc/stun_field_trial.cc b/chromium/content/renderer/media/webrtc/stun_field_trial.cc
index 68e8fa1eea6..5f203f26f82 100644
--- a/chromium/content/renderer/media/webrtc/stun_field_trial.cc
+++ b/chromium/content/renderer/media/webrtc/stun_field_trial.cc
@@ -261,7 +261,7 @@ void StunProberTrial::OnNetworksChanged() {
total_probers_ = params.total_batches * batch_size_;
for (int i = 0; i < total_probers_; i++) {
- scoped_ptr<StunProber> prober(
+ std::unique_ptr<StunProber> prober(
new StunProber(factory_, rtc::Thread::Current(), networks));
if (!prober->Prepare(params.servers, (params.shared_socket_mode != 0),
params.interval_ms, params.requests_per_ip, 1000,
diff --git a/chromium/content/renderer/media/webrtc/stun_field_trial.h b/chromium/content/renderer/media/webrtc/stun_field_trial.h
index dc1629e4d4b..79c9ec40e7f 100644
--- a/chromium/content/renderer/media/webrtc/stun_field_trial.h
+++ b/chromium/content/renderer/media/webrtc/stun_field_trial.h
@@ -5,12 +5,12 @@
#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_STUN_FIELD_TRIAL_H_
#define CONTENT_RENDERER_MEDIA_WEBRTC_STUN_FIELD_TRIAL_H_
+#include <memory>
#include <string>
#include <vector>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/threading/thread_checker.h"
#include "base/timer/timer.h"
#include "content/common/content_export.h"
diff --git a/chromium/content/renderer/media/webrtc/track_observer.h b/chromium/content/renderer/media/webrtc/track_observer.h
index c0a6ad4264e..2a542b8d695 100644
--- a/chromium/content/renderer/media/webrtc/track_observer.h
+++ b/chromium/content/renderer/media/webrtc/track_observer.h
@@ -10,7 +10,7 @@
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
#include "content/common/content_export.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
namespace content {
diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_sink_adapter.cc b/chromium/content/renderer/media/webrtc/webrtc_audio_sink_adapter.cc
index 715309e7d38..2679aff9648 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_audio_sink_adapter.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_audio_sink_adapter.cc
@@ -5,7 +5,7 @@
#include "base/logging.h"
#include "content/renderer/media/webrtc/webrtc_audio_sink_adapter.h"
#include "media/base/audio_bus.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
namespace content {
diff --git a/chromium/content/renderer/media/webrtc/webrtc_audio_sink_adapter.h b/chromium/content/renderer/media/webrtc/webrtc_audio_sink_adapter.h
index 4e70d194b5a..726441156bd 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_audio_sink_adapter.h
+++ b/chromium/content/renderer/media/webrtc/webrtc_audio_sink_adapter.h
@@ -7,8 +7,9 @@
#include <stdint.h>
+#include <memory>
+
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "content/public/renderer/media_stream_audio_sink.h"
#include "media/audio/audio_parameters.h"
@@ -40,7 +41,7 @@ class WebRtcAudioSinkAdapter : public MediaStreamAudioSink {
webrtc::AudioTrackSinkInterface* const sink_;
media::AudioParameters params_;
- scoped_ptr<int16_t[]> interleaved_data_;
+ std::unique_ptr<int16_t[]> interleaved_data_;
DISALLOW_COPY_AND_ASSIGN(WebRtcAudioSinkAdapter);
};
diff --git a/chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.cc b/chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.cc
index 81ac6fc73b9..c86881b07a9 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.cc
@@ -11,7 +11,7 @@
#include "content/renderer/media/webrtc/webrtc_audio_sink_adapter.h"
#include "content/renderer/media/webrtc_local_audio_track.h"
#include "content/renderer/render_thread_impl.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
namespace content {
@@ -23,34 +23,31 @@ WebRtcLocalAudioTrackAdapter::Create(
webrtc::AudioSourceInterface* track_source) {
// TODO(tommi): Change this so that the signaling thread is one of the
// parameters to this method.
- scoped_refptr<base::SingleThreadTaskRunner> signaling_thread;
+ scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner;
RenderThreadImpl* current = RenderThreadImpl::current();
if (current) {
PeerConnectionDependencyFactory* pc_factory =
current->GetPeerConnectionDependencyFactory();
- signaling_thread = pc_factory->GetWebRtcSignalingThread();
+ signaling_task_runner = pc_factory->GetWebRtcSignalingThread();
+ LOG_IF(ERROR, !signaling_task_runner) << "No signaling thread!";
+ } else {
+ LOG(WARNING) << "Assuming single-threaded operation for unit test.";
}
- LOG_IF(ERROR, !signaling_thread.get()) << "No signaling thread!";
-
rtc::RefCountedObject<WebRtcLocalAudioTrackAdapter>* adapter =
new rtc::RefCountedObject<WebRtcLocalAudioTrackAdapter>(
- label, track_source, signaling_thread);
+ label, track_source, std::move(signaling_task_runner));
return adapter;
}
WebRtcLocalAudioTrackAdapter::WebRtcLocalAudioTrackAdapter(
const std::string& label,
webrtc::AudioSourceInterface* track_source,
- const scoped_refptr<base::SingleThreadTaskRunner>& signaling_thread)
+ scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner)
: webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>(label),
owner_(NULL),
track_source_(track_source),
- signaling_thread_(signaling_thread),
- signal_level_(0) {
- signaling_thread_checker_.DetachFromThread();
- capture_thread_.DetachFromThread();
-}
+ signaling_task_runner_(std::move(signaling_task_runner)) {}
WebRtcLocalAudioTrackAdapter::~WebRtcLocalAudioTrackAdapter() {
}
@@ -62,14 +59,17 @@ void WebRtcLocalAudioTrackAdapter::Initialize(WebRtcLocalAudioTrack* owner) {
}
void WebRtcLocalAudioTrackAdapter::SetAudioProcessor(
- const scoped_refptr<MediaStreamAudioProcessor>& processor) {
- // SetAudioProcessor will be called when a new capture thread has been
- // initialized, so we need to detach from any current capture thread we're
- // checking and attach to the current one.
- capture_thread_.DetachFromThread();
- DCHECK(capture_thread_.CalledOnValidThread());
- base::AutoLock auto_lock(lock_);
- audio_processor_ = processor;
+ scoped_refptr<MediaStreamAudioProcessor> processor) {
+ DCHECK(processor.get());
+ DCHECK(!audio_processor_);
+ audio_processor_ = std::move(processor);
+}
+
+void WebRtcLocalAudioTrackAdapter::SetLevel(
+ scoped_refptr<MediaStreamAudioLevelCalculator::Level> level) {
+ DCHECK(level.get());
+ DCHECK(!level_);
+ level_ = std::move(level);
}
std::string WebRtcLocalAudioTrackAdapter::kind() const {
@@ -79,8 +79,9 @@ std::string WebRtcLocalAudioTrackAdapter::kind() const {
bool WebRtcLocalAudioTrackAdapter::set_enabled(bool enable) {
// If we're not called on the signaling thread, we need to post a task to
// change the state on the correct thread.
- if (signaling_thread_.get() && !signaling_thread_->BelongsToCurrentThread()) {
- signaling_thread_->PostTask(FROM_HERE,
+ if (signaling_task_runner_ &&
+ !signaling_task_runner_->BelongsToCurrentThread()) {
+ signaling_task_runner_->PostTask(FROM_HERE,
base::Bind(
base::IgnoreResult(&WebRtcLocalAudioTrackAdapter::set_enabled),
this, enable));
@@ -93,7 +94,8 @@ bool WebRtcLocalAudioTrackAdapter::set_enabled(bool enable) {
void WebRtcLocalAudioTrackAdapter::AddSink(
webrtc::AudioTrackSinkInterface* sink) {
- DCHECK(signaling_thread_checker_.CalledOnValidThread());
+ DCHECK(!signaling_task_runner_ ||
+ signaling_task_runner_->RunsTasksOnCurrentThread());
DCHECK(sink);
#ifndef NDEBUG
// Verify that |sink| has not been added.
@@ -104,7 +106,7 @@ void WebRtcLocalAudioTrackAdapter::AddSink(
}
#endif
- scoped_ptr<WebRtcAudioSinkAdapter> adapter(
+ std::unique_ptr<WebRtcAudioSinkAdapter> adapter(
new WebRtcAudioSinkAdapter(sink));
owner_->AddSink(adapter.get());
sink_adapters_.push_back(adapter.release());
@@ -112,7 +114,8 @@ void WebRtcLocalAudioTrackAdapter::AddSink(
void WebRtcLocalAudioTrackAdapter::RemoveSink(
webrtc::AudioTrackSinkInterface* sink) {
- DCHECK(signaling_thread_checker_.CalledOnValidThread());
+ DCHECK(!signaling_task_runner_ ||
+ signaling_task_runner_->RunsTasksOnCurrentThread());
DCHECK(sink);
for (ScopedVector<WebRtcAudioSinkAdapter>::iterator it =
sink_adapters_.begin();
@@ -126,33 +129,33 @@ void WebRtcLocalAudioTrackAdapter::RemoveSink(
}
bool WebRtcLocalAudioTrackAdapter::GetSignalLevel(int* level) {
- DCHECK(signaling_thread_checker_.CalledOnValidThread());
-
- base::AutoLock auto_lock(lock_);
- *level = signal_level_;
+ DCHECK(!signaling_task_runner_ ||
+ signaling_task_runner_->RunsTasksOnCurrentThread());
+
+ // |level_| is only set once, so it's safe to read without first acquiring a
+ // mutex.
+ if (!level_)
+ return false;
+ const float signal_level = level_->GetCurrent();
+ DCHECK_GE(signal_level, 0.0f);
+ DCHECK_LE(signal_level, 1.0f);
+ // Convert from float in range [0.0,1.0] to an int in range [0,32767].
+ *level = static_cast<int>(signal_level * std::numeric_limits<int16_t>::max() +
+ 0.5f /* rounding to nearest int */);
return true;
}
rtc::scoped_refptr<webrtc::AudioProcessorInterface>
WebRtcLocalAudioTrackAdapter::GetAudioProcessor() {
- DCHECK(signaling_thread_checker_.CalledOnValidThread());
- base::AutoLock auto_lock(lock_);
+ DCHECK(!signaling_task_runner_ ||
+ signaling_task_runner_->RunsTasksOnCurrentThread());
return audio_processor_.get();
}
-void WebRtcLocalAudioTrackAdapter::SetSignalLevel(int signal_level) {
- DCHECK(capture_thread_.CalledOnValidThread());
- base::AutoLock auto_lock(lock_);
- signal_level_ = signal_level;
-}
-
webrtc::AudioSourceInterface* WebRtcLocalAudioTrackAdapter::GetSource() const {
- DCHECK(signaling_thread_checker_.CalledOnValidThread());
+ DCHECK(!signaling_task_runner_ ||
+ signaling_task_runner_->RunsTasksOnCurrentThread());
return track_source_;
}
-cricket::AudioRenderer* WebRtcLocalAudioTrackAdapter::GetRenderer() {
- return NULL;
-}
-
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h b/chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h
index e27a4caf481..72b80194b08 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h
+++ b/chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h
@@ -11,10 +11,11 @@
#include "base/memory/scoped_vector.h"
#include "base/single_thread_task_runner.h"
#include "base/synchronization/lock.h"
-#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreamtrack.h"
-#include "third_party/libjingle/source/talk/media/base/audiorenderer.h"
+#include "content/renderer/media/media_stream_audio_level_calculator.h"
+#include "content/renderer/media/media_stream_audio_processor.h"
+#include "third_party/webrtc/api/mediastreamtrack.h"
+#include "third_party/webrtc/media/base/audiorenderer.h"
namespace cricket {
class AudioRenderer;
@@ -31,6 +32,10 @@ class MediaStreamAudioProcessor;
class WebRtcAudioSinkAdapter;
class WebRtcLocalAudioTrack;
+// Provides an implementation of the webrtc::AudioTrackInterface that can be
+// bound/unbound to/from a MediaStreamAudioTrack. In other words, this is an
+// adapter that sits between the media stream object graph and WebRtc's object
+// graph and proxies between the two.
class CONTENT_EXPORT WebRtcLocalAudioTrackAdapter
: NON_EXPORTED_BASE(
public webrtc::MediaStreamTrack<webrtc::AudioTrackInterface>) {
@@ -42,22 +47,24 @@ class CONTENT_EXPORT WebRtcLocalAudioTrackAdapter
WebRtcLocalAudioTrackAdapter(
const std::string& label,
webrtc::AudioSourceInterface* track_source,
- const scoped_refptr<base::SingleThreadTaskRunner>& signaling_thread);
+ scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner);
~WebRtcLocalAudioTrackAdapter() override;
void Initialize(WebRtcLocalAudioTrack* owner);
- // Called on the audio thread by the WebRtcLocalAudioTrack to set the signal
- // level of the audio data.
- void SetSignalLevel(int signal_level);
+ // Set the object that provides shared access to the current audio signal
+ // level. This method may only be called once, before the audio data flow
+ // starts, and before any calls to GetSignalLevel() might be made.
+ void SetLevel(scoped_refptr<MediaStreamAudioLevelCalculator::Level> level);
// Method called by the WebRtcLocalAudioTrack to set the processor that
// applies signal processing on the data of the track.
// This class will keep a reference of the |processor|.
// Called on the main render thread.
- void SetAudioProcessor(
- const scoped_refptr<MediaStreamAudioProcessor>& processor);
+ // This method may only be called once, before the audio data flow starts, and
+ // before any calls to GetAudioProcessor() might be made.
+ void SetAudioProcessor(scoped_refptr<MediaStreamAudioProcessor> processor);
// webrtc::MediaStreamTrack implementation.
std::string kind() const override;
@@ -71,7 +78,6 @@ class CONTENT_EXPORT WebRtcLocalAudioTrackAdapter
rtc::scoped_refptr<webrtc::AudioProcessorInterface> GetAudioProcessor()
override;
webrtc::AudioSourceInterface* GetSource() const override;
- cricket::AudioRenderer* GetRenderer() override;
// Weak reference.
WebRtcLocalAudioTrack* owner_;
@@ -81,28 +87,19 @@ class CONTENT_EXPORT WebRtcLocalAudioTrackAdapter
rtc::scoped_refptr<webrtc::AudioSourceInterface> track_source_;
// Libjingle's signaling thread.
- const scoped_refptr<base::SingleThreadTaskRunner> signaling_thread_;
+ const scoped_refptr<base::SingleThreadTaskRunner> signaling_task_runner_;
// The audio processsor that applies audio processing on the data of audio
- // track.
+ // track. This must be set before calls to GetAudioProcessor() are made.
scoped_refptr<MediaStreamAudioProcessor> audio_processor_;
- // A vector of WebRtc VoE channels that the capturer sends data to.
- std::vector<int> voe_channels_;
-
// A vector of the peer connection sink adapters which receive the audio data
// from the audio track.
ScopedVector<WebRtcAudioSinkAdapter> sink_adapters_;
- // The amplitude of the signal.
- int signal_level_;
-
- // Thread checker for libjingle's signaling thread.
- base::ThreadChecker signaling_thread_checker_;
- base::ThreadChecker capture_thread_;
-
- // Protects |voe_channels_|, |audio_processor_| and |signal_level_|.
- mutable base::Lock lock_;
+ // Thread-safe accessor to current audio signal level. This must be set
+ // before calls to GetSignalLevel() are made.
+ scoped_refptr<MediaStreamAudioLevelCalculator::Level> level_;
};
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter_unittest.cc b/chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter_unittest.cc
index e34ddb73e17..0a30d4ec0e3 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_local_audio_track_adapter_unittest.cc
@@ -4,13 +4,13 @@
#include <stddef.h>
-#include "content/renderer/media/mock_media_constraint_factory.h"
+#include "content/renderer/media/media_stream_audio_level_calculator.h"
#include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
#include "content/renderer/media/webrtc_audio_capturer.h"
#include "content/renderer/media/webrtc_local_audio_track.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
using ::testing::_;
using ::testing::AnyNumber;
@@ -38,11 +38,7 @@ class WebRtcLocalAudioTrackAdapterTest : public ::testing::Test {
: params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::CHANNEL_LAYOUT_STEREO, 48000, 16, 480),
adapter_(WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL)) {
- MockMediaConstraintFactory constraint_factory;
- capturer_ = WebRtcAudioCapturer::CreateCapturer(
- -1, StreamDeviceInfo(MEDIA_DEVICE_AUDIO_CAPTURE, "", ""),
- constraint_factory.CreateWebMediaConstraints(), NULL, NULL);
- track_.reset(new WebRtcLocalAudioTrack(adapter_.get(), capturer_, NULL));
+ track_.reset(new WebRtcLocalAudioTrack(adapter_.get()));
}
protected:
@@ -53,21 +49,20 @@ class WebRtcLocalAudioTrackAdapterTest : public ::testing::Test {
media::AudioParameters params_;
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_;
- scoped_refptr<WebRtcAudioCapturer> capturer_;
- scoped_ptr<WebRtcLocalAudioTrack> track_;
+ std::unique_ptr<WebRtcLocalAudioTrack> track_;
};
// Adds and Removes a WebRtcAudioSink to a local audio track.
TEST_F(WebRtcLocalAudioTrackAdapterTest, AddAndRemoveSink) {
// Add a sink to the webrtc track.
- scoped_ptr<MockWebRtcAudioSink> sink(new MockWebRtcAudioSink());
+ std::unique_ptr<MockWebRtcAudioSink> sink(new MockWebRtcAudioSink());
webrtc::AudioTrackInterface* webrtc_track =
static_cast<webrtc::AudioTrackInterface*>(adapter_.get());
webrtc_track->AddSink(sink.get());
// Send a packet via |track_| and the data should reach the sink of the
// |adapter_|.
- const scoped_ptr<media::AudioBus> audio_bus =
+ const std::unique_ptr<media::AudioBus> audio_bus =
media::AudioBus::Create(params_);
// While this test is not checking the signal data being passed around, the
// implementation in WebRtcLocalAudioTrack reads the data for its signal level
@@ -79,7 +74,7 @@ TEST_F(WebRtcLocalAudioTrackAdapterTest, AddAndRemoveSink) {
EXPECT_CALL(*sink,
OnData(_, 16, params_.sample_rate(), params_.channels(),
params_.frames_per_buffer()));
- track_->Capture(*audio_bus, estimated_capture_time, false);
+ track_->Capture(*audio_bus, estimated_capture_time);
// Remove the sink from the webrtc track.
webrtc_track->RemoveSink(sink.get());
@@ -89,14 +84,19 @@ TEST_F(WebRtcLocalAudioTrackAdapterTest, AddAndRemoveSink) {
estimated_capture_time +=
params_.frames_per_buffer() * base::TimeDelta::FromSeconds(1) /
params_.sample_rate();
- track_->Capture(*audio_bus, estimated_capture_time, false);
+ track_->Capture(*audio_bus, estimated_capture_time);
}
TEST_F(WebRtcLocalAudioTrackAdapterTest, GetSignalLevel) {
webrtc::AudioTrackInterface* webrtc_track =
static_cast<webrtc::AudioTrackInterface*>(adapter_.get());
- int signal_level = 0;
+ int signal_level = -1;
+ EXPECT_FALSE(webrtc_track->GetSignalLevel(&signal_level));
+ MediaStreamAudioLevelCalculator calculator;
+ adapter_->SetLevel(calculator.level());
+ signal_level = -1;
EXPECT_TRUE(webrtc_track->GetSignalLevel(&signal_level));
+ EXPECT_EQ(0, signal_level);
}
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.cc b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.cc
index 4f5d8347f98..3c34d794dde 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.cc
@@ -45,7 +45,7 @@ WebRtcMediaStreamAdapter::~WebRtcMediaStreamAdapter() {
void WebRtcMediaStreamAdapter::TrackAdded(
const blink::WebMediaStreamTrack& track) {
- if (track.source().type() == blink::WebMediaStreamSource::TypeAudio)
+ if (track.source().getType() == blink::WebMediaStreamSource::TypeAudio)
CreateAudioTrack(track);
else
CreateVideoTrack(track);
@@ -54,11 +54,11 @@ void WebRtcMediaStreamAdapter::TrackAdded(
void WebRtcMediaStreamAdapter::TrackRemoved(
const blink::WebMediaStreamTrack& track) {
const std::string track_id = track.id().utf8();
- if (track.source().type() == blink::WebMediaStreamSource::TypeAudio) {
+ if (track.source().getType() == blink::WebMediaStreamSource::TypeAudio) {
webrtc_media_stream_->RemoveTrack(
webrtc_media_stream_->FindAudioTrack(track_id));
} else {
- DCHECK_EQ(track.source().type(), blink::WebMediaStreamSource::TypeVideo);
+ DCHECK_EQ(track.source().getType(), blink::WebMediaStreamSource::TypeVideo);
scoped_refptr<webrtc::VideoTrackInterface> webrtc_track =
webrtc_media_stream_->FindVideoTrack(track_id).get();
webrtc_media_stream_->RemoveTrack(webrtc_track.get());
@@ -75,10 +75,10 @@ void WebRtcMediaStreamAdapter::TrackRemoved(
void WebRtcMediaStreamAdapter::CreateAudioTrack(
const blink::WebMediaStreamTrack& track) {
- DCHECK_EQ(track.source().type(), blink::WebMediaStreamSource::TypeAudio);
+ DCHECK_EQ(track.source().getType(), blink::WebMediaStreamSource::TypeAudio);
// A media stream is connected to a peer connection, enable the
// peer connection mode for the sources.
- MediaStreamAudioTrack* native_track = MediaStreamAudioTrack::GetTrack(track);
+ MediaStreamAudioTrack* native_track = MediaStreamAudioTrack::From(track);
if (!native_track) {
DLOG(ERROR) << "No native track for blink audio track.";
return;
@@ -92,10 +92,9 @@ void WebRtcMediaStreamAdapter::CreateAudioTrack(
if (native_track->is_local_track()) {
const blink::WebMediaStreamSource& source = track.source();
- MediaStreamAudioSource* audio_source =
- static_cast<MediaStreamAudioSource*>(source.extraData());
- if (audio_source && audio_source->GetAudioCapturer().get())
- audio_source->GetAudioCapturer()->EnablePeerConnectionMode();
+ MediaStreamAudioSource* audio_source = MediaStreamAudioSource::From(source);
+ if (audio_source && audio_source->audio_capturer())
+ audio_source->audio_capturer()->EnablePeerConnectionMode();
}
webrtc_media_stream_->AddTrack(audio_track);
@@ -103,7 +102,7 @@ void WebRtcMediaStreamAdapter::CreateAudioTrack(
void WebRtcMediaStreamAdapter::CreateVideoTrack(
const blink::WebMediaStreamTrack& track) {
- DCHECK_EQ(track.source().type(), blink::WebMediaStreamSource::TypeVideo);
+ DCHECK_EQ(track.source().getType(), blink::WebMediaStreamSource::TypeVideo);
MediaStreamVideoWebRtcSink* adapter =
new MediaStreamVideoWebRtcSink(track, factory_);
video_adapters_.push_back(adapter);
diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.h b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.h
index 3b8a3e75764..c4052550242 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.h
+++ b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter.h
@@ -11,7 +11,7 @@
#include "content/common/content_export.h"
#include "content/renderer/media/media_stream.h"
#include "third_party/WebKit/public/platform/WebMediaStream.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
namespace content {
@@ -34,7 +34,7 @@ class CONTENT_EXPORT WebRtcMediaStreamAdapter
~WebRtcMediaStreamAdapter() override;
bool IsEqual(const blink::WebMediaStream& web_stream) {
- return web_stream_.extraData() == web_stream.extraData();
+ return web_stream_.getExtraData() == web_stream.getExtraData();
}
webrtc::MediaStreamInterface* webrtc_media_stream() {
diff --git a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc
index d23cfa9bfa2..f52ccdae568 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_media_stream_adapter_unittest.cc
@@ -2,20 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "content/renderer/media/webrtc/webrtc_media_stream_adapter.h"
+
#include <stddef.h>
-#include "base/memory/scoped_ptr.h"
+#include <memory>
+
#include "base/message_loop/message_loop.h"
#include "content/child/child_process.h"
#include "content/renderer/media/media_stream.h"
#include "content/renderer/media/media_stream_audio_source.h"
#include "content/renderer/media/media_stream_video_source.h"
#include "content/renderer/media/media_stream_video_track.h"
-#include "content/renderer/media/mock_media_constraint_factory.h"
#include "content/renderer/media/mock_media_stream_video_source.h"
#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
#include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
-#include "content/renderer/media/webrtc/webrtc_media_stream_adapter.h"
#include "content/renderer/media/webrtc_local_audio_track.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebMediaStream.h"
@@ -50,19 +51,11 @@ class WebRtcMediaStreamAdapterTest : public ::testing::Test {
audio_source.setExtraData(new MediaStreamAudioSource());
audio_track_vector[0].initialize(audio_source);
- StreamDeviceInfo device_info(MEDIA_DEVICE_AUDIO_CAPTURE, "Mock device",
- "mock_device_id");
- MockMediaConstraintFactory constraint_factory;
- const blink::WebMediaConstraints constraints =
- constraint_factory.CreateWebMediaConstraints();
- scoped_refptr<WebRtcAudioCapturer> capturer(
- WebRtcAudioCapturer::CreateCapturer(-1, device_info, constraints,
- nullptr, nullptr));
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
WebRtcLocalAudioTrackAdapter::Create(
audio_track_vector[0].id().utf8(), nullptr));
- scoped_ptr<WebRtcLocalAudioTrack> native_track(
- new WebRtcLocalAudioTrack(adapter.get(), capturer, nullptr));
+ std::unique_ptr<WebRtcLocalAudioTrack> native_track(
+ new WebRtcLocalAudioTrack(adapter.get()));
audio_track_vector[0].setExtraData(native_track.release());
}
@@ -113,9 +106,9 @@ class WebRtcMediaStreamAdapterTest : public ::testing::Test {
protected:
base::MessageLoop message_loop_;
- scoped_ptr<ChildProcess> child_process_;
- scoped_ptr<MockPeerConnectionDependencyFactory> dependency_factory_;
- scoped_ptr<WebRtcMediaStreamAdapter> adapter_;
+ std::unique_ptr<ChildProcess> child_process_;
+ std::unique_ptr<MockPeerConnectionDependencyFactory> dependency_factory_;
+ std::unique_ptr<WebRtcMediaStreamAdapter> adapter_;
};
TEST_F(WebRtcMediaStreamAdapterTest, CreateWebRtcMediaStream) {
diff --git a/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc b/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc
index abdb1b17fa9..10ad8578a99 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc
+++ b/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.cc
@@ -11,12 +11,13 @@
#include "media/base/timestamp_constants.h"
#include "media/base/video_frame.h"
#include "media/base/video_frame_pool.h"
-#include "third_party/libjingle/source/talk/media/base/videoframefactory.h"
-#include "third_party/libjingle/source/talk/media/webrtc/webrtcvideoframe.h"
+#include "media/base/video_util.h"
#include "third_party/libyuv/include/libyuv/convert_from.h"
#include "third_party/libyuv/include/libyuv/scale.h"
#include "third_party/webrtc/common_video/include/video_frame_buffer.h"
#include "third_party/webrtc/common_video/rotation.h"
+#include "third_party/webrtc/media/base/videoframefactory.h"
+#include "third_party/webrtc/media/engine/webrtcvideoframe.h"
namespace content {
namespace {
@@ -94,7 +95,8 @@ class WebRtcVideoCapturerAdapter::MediaVideoFrameFactory
const gfx::Size output_size(output_width, output_height);
scoped_refptr<media::VideoFrame> video_frame =
- media::VideoFrame::WrapVideoFrame(frame_, visible_rect, output_size);
+ media::VideoFrame::WrapVideoFrame(frame_, frame_->format(),
+ visible_rect, output_size);
if (!video_frame)
return nullptr;
video_frame->AddDestructionObserver(
@@ -216,16 +218,22 @@ bool WebRtcVideoCapturerAdapter::GetBestCaptureFormat(
}
void WebRtcVideoCapturerAdapter::OnFrameCaptured(
- const scoped_refptr<media::VideoFrame>& frame) {
+ const scoped_refptr<media::VideoFrame>& video_frame) {
DCHECK(thread_checker_.CalledOnValidThread());
TRACE_EVENT0("video", "WebRtcVideoCapturerAdapter::OnFrameCaptured");
- if (!(frame->IsMappable() && (frame->format() == media::PIXEL_FORMAT_I420 ||
- frame->format() == media::PIXEL_FORMAT_YV12))) {
+ if (!(video_frame->IsMappable() &&
+ (video_frame->format() == media::PIXEL_FORMAT_I420 ||
+ video_frame->format() == media::PIXEL_FORMAT_YV12 ||
+ video_frame->format() == media::PIXEL_FORMAT_YV12A))) {
// Since connecting sources and sinks do not check the format, we need to
// just ignore formats that we can not handle.
NOTREACHED();
return;
}
+ scoped_refptr<media::VideoFrame> frame = video_frame;
+ // Drop alpha channel since we do not support it yet.
+ if (frame->format() == media::PIXEL_FORMAT_YV12A)
+ frame = media::WrapAsI420VideoFrame(video_frame);
// Inject the frame via the VideoFrameFactory of base class.
MediaVideoFrameFactory* media_video_frame_factory =
diff --git a/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h b/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h
index 922935407ed..f51ca72d2da 100644
--- a/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h
+++ b/chromium/content/renderer/media/webrtc/webrtc_video_capturer_adapter.h
@@ -15,7 +15,7 @@
#include "content/common/content_export.h"
#include "media/base/video_capture_types.h"
#include "media/base/video_frame.h"
-#include "third_party/libjingle/source/talk/media/base/videocapturer.h"
+#include "third_party/webrtc/media/base/videocapturer.h"
namespace content {
@@ -24,8 +24,8 @@ namespace content {
// The class is created and destroyed on the main render thread.
// PeerConnection access cricket::VideoCapturer from a libJingle worker thread.
// An instance of WebRtcVideoCapturerAdapter is owned by an instance of
-// webrtc::VideoSourceInterface in libJingle. The implementation of
-// webrtc::VideoSourceInterface guarantees that this object is not deleted
+// webrtc::VideoTrackSourceInterface in libJingle. The implementation of
+// webrtc::VideoTrackSourceInterface guarantees that this object is not deleted
// while it is still used in libJingle.
class CONTENT_EXPORT WebRtcVideoCapturerAdapter
: NON_EXPORTED_BASE(public cricket::VideoCapturer) {
diff --git a/chromium/content/renderer/media/webrtc_audio_capturer.cc b/chromium/content/renderer/media/webrtc_audio_capturer.cc
index 113233ebefd..de076b6ec55 100644
--- a/chromium/content/renderer/media/webrtc_audio_capturer.cc
+++ b/chromium/content/renderer/media/webrtc_audio_capturer.cc
@@ -24,29 +24,6 @@
namespace content {
-namespace {
-
-// Audio buffer sizes are specified in milliseconds.
-const char kAudioLatency[] = "latencyMs";
-const int kMinAudioLatencyMs = 0;
-const int kMaxAudioLatencyMs = 10000;
-
-// Method to check if any of the data in |audio_source| has energy.
-bool HasDataEnergy(const media::AudioBus& audio_source) {
- for (int ch = 0; ch < audio_source.channels(); ++ch) {
- const float* channel_ptr = audio_source.channel(ch);
- for (int frame = 0; frame < audio_source.frames(); ++frame) {
- if (channel_ptr[frame] != 0)
- return true;
- }
- }
-
- // All the data is zero.
- return false;
-}
-
-} // namespace
-
// Reference counted container of WebRtcLocalAudioTrack delegate.
// TODO(xians): Switch to MediaStreamAudioSinkOwner.
class WebRtcAudioCapturer::TrackOwner
@@ -56,13 +33,10 @@ class WebRtcAudioCapturer::TrackOwner
: delegate_(track) {}
void Capture(const media::AudioBus& audio_bus,
- base::TimeTicks estimated_capture_time,
- bool force_report_nonzero_energy) {
+ base::TimeTicks estimated_capture_time) {
base::AutoLock lock(lock_);
if (delegate_) {
- delegate_->Capture(audio_bus,
- estimated_capture_time,
- force_report_nonzero_energy);
+ delegate_->Capture(audio_bus, estimated_capture_time);
}
}
@@ -72,13 +46,6 @@ class WebRtcAudioCapturer::TrackOwner
delegate_->OnSetFormat(params);
}
- void SetAudioProcessor(
- const scoped_refptr<MediaStreamAudioProcessor>& processor) {
- base::AutoLock lock(lock_);
- if (delegate_)
- delegate_->SetAudioProcessor(processor);
- }
-
void Reset() {
base::AutoLock lock(lock_);
delegate_ = NULL;
@@ -124,14 +91,14 @@ class WebRtcAudioCapturer::TrackOwner
};
// static
-scoped_refptr<WebRtcAudioCapturer> WebRtcAudioCapturer::CreateCapturer(
+std::unique_ptr<WebRtcAudioCapturer> WebRtcAudioCapturer::CreateCapturer(
int render_frame_id,
const StreamDeviceInfo& device_info,
const blink::WebMediaConstraints& constraints,
WebRtcAudioDeviceImpl* audio_device,
MediaStreamAudioSource* audio_source) {
- scoped_refptr<WebRtcAudioCapturer> capturer = new WebRtcAudioCapturer(
- render_frame_id, device_info, constraints, audio_device, audio_source);
+ std::unique_ptr<WebRtcAudioCapturer> capturer(new WebRtcAudioCapturer(
+ render_frame_id, device_info, constraints, audio_device, audio_source));
if (capturer->Initialize())
return capturer;
@@ -170,9 +137,8 @@ bool WebRtcAudioCapturer::Initialize() {
// If KEYBOARD_MIC effect is set, change the layout to the corresponding
// layout that includes the keyboard mic.
if ((device_info_.device.input.effects &
- media::AudioParameters::KEYBOARD_MIC) &&
- audio_constraints.GetProperty(
- MediaAudioConstraints::kGoogExperimentalNoiseSuppression)) {
+ media::AudioParameters::KEYBOARD_MIC) &&
+ audio_constraints.GetGoogExperimentalNoiseSuppression()) {
if (channel_layout == media::CHANNEL_LAYOUT_STEREO) {
channel_layout = media::CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC;
DVLOG(1) << "Changed stereo layout to stereo + keyboard mic layout due "
@@ -207,27 +173,10 @@ bool WebRtcAudioCapturer::Initialize() {
device_info_.device.input.sample_rate);
}
- // Initialize the buffer size to zero, which means it wasn't specified.
- // If it is out of range, we return it to zero.
- int buffer_size_ms = 0;
- int buffer_size_samples = 0;
- GetConstraintValueAsInteger(constraints_, kAudioLatency, &buffer_size_ms);
- if (buffer_size_ms < kMinAudioLatencyMs ||
- buffer_size_ms > kMaxAudioLatencyMs) {
- DVLOG(1) << "Ignoring out of range buffer size " << buffer_size_ms;
- } else {
- buffer_size_samples =
- device_info_.device.input.sample_rate * buffer_size_ms / 1000;
- }
- DVLOG_IF(1, buffer_size_samples > 0)
- << "Custom audio buffer size: " << buffer_size_samples << " samples";
-
// Create and configure the default audio capturing source.
SetCapturerSourceInternal(
- AudioDeviceFactory::NewInputDevice(render_frame_id_),
- channel_layout,
- device_info_.device.input.sample_rate,
- buffer_size_samples);
+ AudioDeviceFactory::NewAudioCapturerSource(render_frame_id_),
+ channel_layout, device_info_.device.input.sample_rate);
// Add the capturer to the WebRtcAudioDeviceImpl since it needs some hardware
// information from the capturer.
@@ -266,9 +215,18 @@ WebRtcAudioCapturer::~WebRtcAudioCapturer() {
}
void WebRtcAudioCapturer::AddTrack(WebRtcLocalAudioTrack* track) {
+ DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(track);
DVLOG(1) << "WebRtcAudioCapturer::AddTrack()";
+ track->SetLevel(level_calculator_.level());
+
+ // The track only grabs stats from the audio processor. Stats are only
+ // available if audio processing is turned on. Therefore, only provide the
+ // track a reference if audio processing is turned on.
+ if (audio_processor_->has_audio_processing())
+ track->SetAudioProcessor(audio_processor_);
+
{
base::AutoLock auto_lock(lock_);
// Verify that |track| is not already added to the list.
@@ -312,8 +270,7 @@ void WebRtcAudioCapturer::RemoveTrack(WebRtcLocalAudioTrack* track) {
void WebRtcAudioCapturer::SetCapturerSourceInternal(
const scoped_refptr<media::AudioCapturerSource>& source,
media::ChannelLayout channel_layout,
- int sample_rate,
- int buffer_size) {
+ int sample_rate) {
DCHECK(thread_checker_.CalledOnValidThread());
DVLOG(1) << "SetCapturerSource(channel_layout=" << channel_layout << ","
<< "sample_rate=" << sample_rate << ")";
@@ -334,23 +291,25 @@ void WebRtcAudioCapturer::SetCapturerSourceInternal(
if (old_source.get())
old_source->Stop();
- // If the buffer size is zero, it has not been specified.
- // We either default to 10ms, or use the hardware buffer size.
- if (buffer_size == 0)
- buffer_size = GetBufferSize(sample_rate);
-
// Dispatch the new parameters both to the sink(s) and to the new source,
// also apply the new |constraints|.
// The idea is to get rid of any dependency of the microphone parameters
// which would normally be used by default.
// bits_per_sample is always 16 for now.
media::AudioParameters params(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- channel_layout, sample_rate, 16, buffer_size);
+ channel_layout, sample_rate, 16,
+ GetBufferSize(sample_rate));
params.set_effects(device_info_.device.input.effects);
+ DCHECK(params.IsValid());
{
base::AutoLock auto_lock(lock_);
- // Notify the |audio_processor_| of the new format.
+
+ // Notify the |audio_processor_| of the new format. We're doing this while
+ // the lock is held only because the signaling thread might be calling
+ // GetInputFormat(). Simultaneous reads from the audio thread are NOT the
+ // concern here since the source is currently stopped (i.e., no audio
+ // capture calls can be executing).
audio_processor_->OnCaptureFormatChanged(params);
// Notify all tracks about the new format.
@@ -358,7 +317,7 @@ void WebRtcAudioCapturer::SetCapturerSourceInternal(
}
if (source.get())
- source->Initialize(params, this, session_id());
+ source->Initialize(params, this, device_info_.session_id);
Start();
}
@@ -392,10 +351,9 @@ void WebRtcAudioCapturer::EnablePeerConnectionMode() {
// Create a new audio stream as source which will open the hardware using
// WebRtc native buffer size.
- SetCapturerSourceInternal(AudioDeviceFactory::NewInputDevice(render_frame_id),
- input_params.channel_layout(),
- input_params.sample_rate(),
- 0);
+ SetCapturerSourceInternal(
+ AudioDeviceFactory::NewAudioCapturerSource(render_frame_id),
+ input_params.channel_layout(), input_params.sample_rate());
}
void WebRtcAudioCapturer::Start() {
@@ -508,26 +466,28 @@ void WebRtcAudioCapturer::Capture(const media::AudioBus* audio_source,
tracks_.RetrieveAndClearTags(&tracks_to_notify_format);
}
+ // Sanity-check the input audio format in debug builds. Then, notify the
+ // tracks if the format has changed.
+ //
+ // Locking is not needed here to read the audio input/output parameters
+ // because the audio processor format changes only occur while audio capture
+ // is stopped.
DCHECK(audio_processor_->InputFormat().IsValid());
DCHECK_EQ(audio_source->channels(),
audio_processor_->InputFormat().channels());
DCHECK_EQ(audio_source->frames(),
audio_processor_->InputFormat().frames_per_buffer());
-
- // Notify the tracks on when the format changes. This will do nothing if
- // |tracks_to_notify_format| is empty.
- const media::AudioParameters& output_params =
- audio_processor_->OutputFormat();
- for (const auto& track : tracks_to_notify_format) {
- track->OnSetFormat(output_params);
- track->SetAudioProcessor(audio_processor_);
+ if (!tracks_to_notify_format.empty()) {
+ const media::AudioParameters& output_params =
+ audio_processor_->OutputFormat();
+ for (const auto& track : tracks_to_notify_format)
+ track->OnSetFormat(output_params);
}
- // Figure out if the pre-processed data has any energy or not, the
- // information will be passed to the track to force the calculator
- // to report energy in case the post-processed data is zeroed by the audio
- // processing.
- const bool force_report_nonzero_energy = HasDataEnergy(*audio_source);
+ // Figure out if the pre-processed data has any energy or not. This
+ // information will be passed to the level calculator to force it to report
+ // energy in case the post-processed data is zeroed by the audio processing.
+ const bool force_report_nonzero_energy = !audio_source->AreFramesZero();
// Push the data to the processor for processing.
audio_processor_->PushCaptureData(
@@ -543,13 +503,13 @@ void WebRtcAudioCapturer::Capture(const media::AudioBus* audio_source,
current_volume, key_pressed,
&processed_data, &processed_data_audio_delay, &new_volume)) {
DCHECK(processed_data);
+
+ level_calculator_.Calculate(*processed_data, force_report_nonzero_energy);
+
const base::TimeTicks processed_data_capture_time =
reference_clock_snapshot - processed_data_audio_delay;
- for (const auto& track : tracks) {
- track->Capture(*processed_data,
- processed_data_capture_time,
- force_report_nonzero_energy);
- }
+ for (const auto& track : tracks)
+ track->Capture(*processed_data, processed_data_capture_time);
if (new_volume) {
SetVolume(new_volume);
@@ -564,28 +524,9 @@ void WebRtcAudioCapturer::OnCaptureError(const std::string& message) {
WebRtcLogMessage("WAC::OnCaptureError: " + message);
}
-media::AudioParameters WebRtcAudioCapturer::source_audio_parameters() const {
+media::AudioParameters WebRtcAudioCapturer::GetInputFormat() const {
base::AutoLock auto_lock(lock_);
- return audio_processor_.get() ? audio_processor_->InputFormat()
- : media::AudioParameters();
-}
-
-bool WebRtcAudioCapturer::GetPairedOutputParameters(
- int* session_id,
- int* output_sample_rate,
- int* output_frames_per_buffer) const {
- // Don't set output parameters unless all of them are valid.
- if (device_info_.session_id <= 0 ||
- !device_info_.device.matched_output.sample_rate ||
- !device_info_.device.matched_output.frames_per_buffer)
- return false;
-
- *session_id = device_info_.session_id;
- *output_sample_rate = device_info_.device.matched_output.sample_rate;
- *output_frames_per_buffer =
- device_info_.device.matched_output.frames_per_buffer;
-
- return true;
+ return audio_processor_->InputFormat();
}
int WebRtcAudioCapturer::GetBufferSize(int sample_rate) const {
@@ -618,10 +559,8 @@ void WebRtcAudioCapturer::SetCapturerSource(
const scoped_refptr<media::AudioCapturerSource>& source,
media::AudioParameters params) {
// Create a new audio stream as source which uses the new source.
- SetCapturerSourceInternal(source,
- params.channel_layout(),
- params.sample_rate(),
- 0);
+ SetCapturerSourceInternal(source, params.channel_layout(),
+ params.sample_rate());
}
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc_audio_capturer.h b/chromium/content/renderer/media/webrtc_audio_capturer.h
index afa5f9e54b5..df992e1b333 100644
--- a/chromium/content/renderer/media/webrtc_audio_capturer.h
+++ b/chromium/content/renderer/media/webrtc_audio_capturer.h
@@ -6,6 +6,7 @@
#define CONTENT_RENDERER_MEDIA_WEBRTC_AUDIO_CAPTURER_H_
#include <list>
+#include <memory>
#include <string>
#include "base/callback.h"
@@ -16,6 +17,7 @@
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
#include "content/common/media/media_stream_options.h"
+#include "content/renderer/media/media_stream_audio_level_calculator.h"
#include "content/renderer/media/tagged_list.h"
#include "media/audio/audio_input_device.h"
#include "media/base/audio_capturer_source.h"
@@ -41,8 +43,7 @@ class WebRtcLocalAudioTrack;
// thread or on the main render thread but also other client threads
// if an alternative AudioCapturerSource has been set.
class CONTENT_EXPORT WebRtcAudioCapturer
- : public base::RefCountedThreadSafe<WebRtcAudioCapturer>,
- NON_EXPORTED_BASE(public media::AudioCapturerSource::CaptureCallback) {
+ : NON_EXPORTED_BASE(public media::AudioCapturerSource::CaptureCallback) {
public:
// Used to construct the audio capturer. |render_frame_id| specifies the
// RenderFrame consuming audio for capture; -1 is used for tests.
@@ -50,13 +51,15 @@ class CONTENT_EXPORT WebRtcAudioCapturer
// created for. |constraints| contains the settings for audio processing.
// TODO(xians): Implement the interface for the audio source and move the
// |constraints| to ApplyConstraints(). Called on the main render thread.
- static scoped_refptr<WebRtcAudioCapturer> CreateCapturer(
+ static std::unique_ptr<WebRtcAudioCapturer> CreateCapturer(
int render_frame_id,
const StreamDeviceInfo& device_info,
const blink::WebMediaConstraints& constraints,
WebRtcAudioDeviceImpl* audio_device,
MediaStreamAudioSource* audio_source);
+ ~WebRtcAudioCapturer() override;
+
// Add a audio track to the sinks of the capturer.
// WebRtcAudioDeviceImpl calls this method on the main render thread but
// other clients may call it from other threads. The current implementation
@@ -84,16 +87,9 @@ class CONTENT_EXPORT WebRtcAudioCapturer
// Audio parameters utilized by the source of the audio capturer.
// TODO(phoglund): Think over the implications of this accessor and if we can
// remove it.
- media::AudioParameters source_audio_parameters() const;
-
- // Gets information about the paired output device. Returns true if such a
- // device exists.
- bool GetPairedOutputParameters(int* session_id,
- int* output_sample_rate,
- int* output_frames_per_buffer) const;
+ media::AudioParameters GetInputFormat() const;
- const std::string& device_id() const { return device_info_.device.id; }
- int session_id() const { return device_info_.session_id; }
+ const StreamDeviceInfo& device_info() const { return device_info_; }
// Stops recording audio. This method will empty its track lists since
// stopping the capturer will implicitly invalidate all its tracks.
@@ -110,10 +106,6 @@ class CONTENT_EXPORT WebRtcAudioCapturer
const scoped_refptr<media::AudioCapturerSource>& source,
media::AudioParameters params);
- protected:
- friend class base::RefCountedThreadSafe<WebRtcAudioCapturer>;
- ~WebRtcAudioCapturer() override;
-
private:
class TrackOwner;
typedef TaggedList<TrackOwner> TrackList;
@@ -144,8 +136,7 @@ class CONTENT_EXPORT WebRtcAudioCapturer
void SetCapturerSourceInternal(
const scoped_refptr<media::AudioCapturerSource>& source,
media::ChannelLayout channel_layout,
- int sample_rate,
- int buffer_size);
+ int sample_rate);
// Starts recording audio.
// Triggered by AddSink() on the main render thread or a Libjingle working
@@ -176,7 +167,7 @@ class CONTENT_EXPORT WebRtcAudioCapturer
// Audio processor doing processing like FIFO, AGC, AEC and NS. Its output
// data is in a unit of 10 ms data chunk.
- scoped_refptr<MediaStreamAudioProcessor> audio_processor_;
+ const scoped_refptr<MediaStreamAudioProcessor> audio_processor_;
bool running_;
@@ -205,6 +196,9 @@ class CONTENT_EXPORT WebRtcAudioCapturer
// WebRtcAudioCapturer.
MediaStreamAudioSource* const audio_source_;
+ // Used to calculate the signal level that shows in the UI.
+ MediaStreamAudioLevelCalculator level_calculator_;
+
DISALLOW_COPY_AND_ASSIGN(WebRtcAudioCapturer);
};
diff --git a/chromium/content/renderer/media/webrtc_audio_capturer_unittest.cc b/chromium/content/renderer/media/webrtc_audio_capturer_unittest.cc
index 306ca9882d7..1554149d025 100644
--- a/chromium/content/renderer/media/webrtc_audio_capturer_unittest.cc
+++ b/chromium/content/renderer/media/webrtc_audio_capturer_unittest.cc
@@ -5,7 +5,7 @@
#include "base/logging.h"
#include "build/build_config.h"
#include "content/public/renderer/media_stream_audio_sink.h"
-#include "content/renderer/media/mock_media_constraint_factory.h"
+#include "content/renderer/media/mock_constraint_factory.h"
#include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
#include "content/renderer/media/webrtc_audio_capturer.h"
#include "content/renderer/media/webrtc_local_audio_track.h"
@@ -76,67 +76,70 @@ class WebRtcAudioCapturerTest : public testing::Test {
void VerifyAudioParams(const blink::WebMediaConstraints& constraints,
bool need_audio_processing) {
- capturer_ = WebRtcAudioCapturer::CreateCapturer(
- -1, StreamDeviceInfo(MEDIA_DEVICE_AUDIO_CAPTURE, "", "",
- params_.sample_rate(), params_.channel_layout(),
- params_.frames_per_buffer()),
- constraints, NULL, NULL);
- capturer_source_ = new MockCapturerSource();
- EXPECT_CALL(*capturer_source_.get(), Initialize(_, capturer_.get(), -1));
- EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true));
- EXPECT_CALL(*capturer_source_.get(), Start());
- capturer_->SetCapturerSource(capturer_source_, params_);
+ const std::unique_ptr<WebRtcAudioCapturer> capturer =
+ WebRtcAudioCapturer::CreateCapturer(
+ -1, StreamDeviceInfo(
+ MEDIA_DEVICE_AUDIO_CAPTURE, "", "", params_.sample_rate(),
+ params_.channel_layout(), params_.frames_per_buffer()),
+ constraints, nullptr, nullptr);
+ const scoped_refptr<MockCapturerSource> capturer_source(
+ new MockCapturerSource());
+ EXPECT_CALL(*capturer_source.get(), Initialize(_, capturer.get(), -1));
+ EXPECT_CALL(*capturer_source.get(), SetAutomaticGainControl(true));
+ EXPECT_CALL(*capturer_source.get(), Start());
+ capturer->SetCapturerSource(capturer_source, params_);
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
- track_.reset(new WebRtcLocalAudioTrack(adapter.get(), capturer_, NULL));
- track_->Start();
+ const std::unique_ptr<WebRtcLocalAudioTrack> track(
+ new WebRtcLocalAudioTrack(adapter.get()));
+ capturer->AddTrack(track.get());
// Connect a mock sink to the track.
- scoped_ptr<MockMediaStreamAudioSink> sink(new MockMediaStreamAudioSink());
- track_->AddSink(sink.get());
+ std::unique_ptr<MockMediaStreamAudioSink> sink(
+ new MockMediaStreamAudioSink());
+ track->AddSink(sink.get());
int delay_ms = 65;
bool key_pressed = true;
double volume = 0.9;
- scoped_ptr<media::AudioBus> audio_bus = media::AudioBus::Create(params_);
+ std::unique_ptr<media::AudioBus> audio_bus =
+ media::AudioBus::Create(params_);
audio_bus->Zero();
media::AudioCapturerSource::CaptureCallback* callback =
static_cast<media::AudioCapturerSource::CaptureCallback*>(
- capturer_.get());
+ capturer.get());
// Verify the sink is getting the correct values.
EXPECT_CALL(*sink, FormatIsSet());
EXPECT_CALL(*sink, OnDataCallback()).Times(AtLeast(1));
callback->Capture(audio_bus.get(), delay_ms, volume, key_pressed);
- track_->RemoveSink(sink.get());
- EXPECT_CALL(*capturer_source_.get(), Stop());
- capturer_->Stop();
+ track->RemoveSink(sink.get());
+ EXPECT_CALL(*capturer_source.get(), Stop());
+ capturer->Stop();
}
media::AudioParameters params_;
- scoped_refptr<MockCapturerSource> capturer_source_;
- scoped_refptr<WebRtcAudioCapturer> capturer_;
- scoped_ptr<WebRtcLocalAudioTrack> track_;
};
TEST_F(WebRtcAudioCapturerTest, VerifyAudioParamsWithAudioProcessing) {
// Turn off the default constraints to verify that the sink will get packets
// with a buffer size smaller than 10ms.
- MockMediaConstraintFactory constraint_factory;
+ MockConstraintFactory constraint_factory;
constraint_factory.DisableDefaultAudioConstraints();
VerifyAudioParams(constraint_factory.CreateWebMediaConstraints(), false);
}
TEST_F(WebRtcAudioCapturerTest, FailToCreateCapturerWithWrongConstraints) {
- MockMediaConstraintFactory constraint_factory;
+ MockConstraintFactory constraint_factory;
const std::string dummy_constraint = "dummy";
- constraint_factory.AddMandatory(dummy_constraint, true);
+ // Set a non-audio constraint.
+ constraint_factory.basic().width.setExact(240);
- scoped_refptr<WebRtcAudioCapturer> capturer(
+ std::unique_ptr<WebRtcAudioCapturer> capturer(
WebRtcAudioCapturer::CreateCapturer(
0, StreamDeviceInfo(MEDIA_DEVICE_AUDIO_CAPTURE, "", "",
params_.sample_rate(), params_.channel_layout(),
diff --git a/chromium/content/renderer/media/webrtc_audio_device_impl.cc b/chromium/content/renderer/media/webrtc_audio_device_impl.cc
index 9ee3da787e2..17a058506df 100644
--- a/chromium/content/renderer/media/webrtc_audio_device_impl.cc
+++ b/chromium/content/renderer/media/webrtc_audio_device_impl.cc
@@ -82,32 +82,19 @@ void WebRtcAudioDeviceImpl::RenderData(media::AudioBus* audio_bus,
render_buffer_.resize(audio_bus->frames() * audio_bus->channels());
int frames_per_10_ms = (sample_rate / 100);
int bytes_per_sample = sizeof(render_buffer_[0]);
- const int bytes_per_10_ms =
- audio_bus->channels() * frames_per_10_ms * bytes_per_sample;
- DCHECK_EQ(audio_bus->frames() % frames_per_10_ms, 0);
-
- // Get audio frames in blocks of 10 milliseconds from the registered
- // webrtc::AudioTransport source. Keep reading until our internal buffer
- // is full.
- int accumulated_audio_frames = 0;
+ // Client should always ask for 10ms.
+ DCHECK_EQ(audio_bus->frames(), frames_per_10_ms);
+
+ // Get 10ms audio and copy result to temporary byte buffer.
+ int64_t elapsed_time_ms = -1;
+ int64_t ntp_time_ms = -1;
+ static const int kBitsPerByte = 8;
int16_t* audio_data = &render_buffer_[0];
- while (accumulated_audio_frames < audio_bus->frames()) {
- // Get 10ms and append output to temporary byte buffer.
- int64_t elapsed_time_ms = -1;
- int64_t ntp_time_ms = -1;
- static const int kBitsPerByte = 8;
- audio_transport_callback_->PullRenderData(bytes_per_sample * kBitsPerByte,
- sample_rate,
- audio_bus->channels(),
- frames_per_10_ms,
- audio_data,
- &elapsed_time_ms,
- &ntp_time_ms);
- accumulated_audio_frames += frames_per_10_ms;
- if (elapsed_time_ms >= 0) {
- *current_time = base::TimeDelta::FromMilliseconds(elapsed_time_ms);
- }
- audio_data += bytes_per_10_ms;
+ audio_transport_callback_->PullRenderData(
+ bytes_per_sample * kBitsPerByte, sample_rate, audio_bus->channels(),
+ frames_per_10_ms, audio_data, &elapsed_time_ms, &ntp_time_ms);
+ if (elapsed_time_ms >= 0) {
+ *current_time = base::TimeDelta::FromMilliseconds(elapsed_time_ms);
}
// De-interleave each channel and convert to 32-bit floating-point
@@ -183,15 +170,9 @@ int32_t WebRtcAudioDeviceImpl::Terminate() {
DCHECK(!renderer_.get() || !renderer_->IsStarted())
<< "The shared audio renderer shouldn't be running";
- // Stop all the capturers to ensure no further OnData() and
- // RemoveAudioCapturer() callback.
- // Cache the capturers in a local list since WebRtcAudioCapturer::Stop()
- // will trigger RemoveAudioCapturer() callback.
- CapturerList capturers;
- capturers.swap(capturers_);
- for (CapturerList::const_iterator iter = capturers.begin();
- iter != capturers.end(); ++iter) {
- (*iter)->Stop();
+ {
+ base::AutoLock auto_lock(lock_);
+ capturers_.clear();
}
initialized_ = false;
@@ -307,11 +288,10 @@ int32_t WebRtcAudioDeviceImpl::SetMicrophoneVolume(uint32_t volume) {
// Only one microphone is supported at the moment, which is represented by
// the default capturer.
- scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer());
- if (!capturer.get())
+ base::AutoLock auto_lock(lock_);
+ if (capturers_.empty())
return -1;
-
- capturer->SetVolume(volume);
+ capturers_.back()->SetVolume(volume);
return 0;
}
@@ -322,12 +302,10 @@ int32_t WebRtcAudioDeviceImpl::MicrophoneVolume(uint32_t* volume) const {
// We only support one microphone now, which is accessed via the default
// capturer.
DCHECK(initialized_);
- scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer());
- if (!capturer.get())
+ base::AutoLock auto_lock(lock_);
+ if (capturers_.empty())
return -1;
-
- *volume = static_cast<uint32_t>(capturer->Volume());
-
+ *volume = static_cast<uint32_t>(capturers_.back()->Volume());
return 0;
}
@@ -365,11 +343,10 @@ int32_t WebRtcAudioDeviceImpl::StereoRecordingIsAvailable(
// TODO(xians): These kind of hardware methods do not make much sense since we
// support multiple sources. Remove or figure out new APIs for such methods.
- scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer());
- if (!capturer.get())
+ base::AutoLock auto_lock(lock_);
+ if (capturers_.empty())
return -1;
-
- *available = (capturer->source_audio_parameters().channels() == 2);
+ *available = (capturers_.back()->GetInputFormat().channels() == 2);
return 0;
}
@@ -393,12 +370,11 @@ int32_t WebRtcAudioDeviceImpl::RecordingSampleRate(
uint32_t* sample_rate) const {
DCHECK(signaling_thread_checker_.CalledOnValidThread());
// We use the default capturer as the recording sample rate.
- scoped_refptr<WebRtcAudioCapturer> capturer(GetDefaultCapturer());
- if (!capturer.get())
+ base::AutoLock auto_lock(lock_);
+ if (capturers_.empty())
return -1;
-
- *sample_rate = static_cast<uint32_t>(
- capturer->source_audio_parameters().sample_rate());
+ const media::AudioParameters& params = capturers_.back()->GetInputFormat();
+ *sample_rate = static_cast<uint32_t>(params.sample_rate());
return 0;
}
@@ -446,12 +422,11 @@ bool WebRtcAudioDeviceImpl::SetAudioRenderer(WebRtcAudioRenderer* renderer) {
return true;
}
-void WebRtcAudioDeviceImpl::AddAudioCapturer(
- const scoped_refptr<WebRtcAudioCapturer>& capturer) {
+void WebRtcAudioDeviceImpl::AddAudioCapturer(WebRtcAudioCapturer* capturer) {
DCHECK(main_thread_checker_.CalledOnValidThread());
DVLOG(1) << "WebRtcAudioDeviceImpl::AddAudioCapturer()";
- DCHECK(capturer.get());
- DCHECK(!capturer->device_id().empty());
+ DCHECK(capturer);
+ DCHECK(!capturer->device_info().device.id.empty());
base::AutoLock auto_lock(lock_);
DCHECK(std::find(capturers_.begin(), capturers_.end(), capturer) ==
@@ -459,29 +434,14 @@ void WebRtcAudioDeviceImpl::AddAudioCapturer(
capturers_.push_back(capturer);
}
-void WebRtcAudioDeviceImpl::RemoveAudioCapturer(
- const scoped_refptr<WebRtcAudioCapturer>& capturer) {
+void WebRtcAudioDeviceImpl::RemoveAudioCapturer(WebRtcAudioCapturer* capturer) {
DCHECK(main_thread_checker_.CalledOnValidThread());
- DVLOG(1) << "WebRtcAudioDeviceImpl::AddAudioCapturer()";
- DCHECK(capturer.get());
+ DVLOG(1) << "WebRtcAudioDeviceImpl::RemoveAudioCapturer()";
+ DCHECK(capturer);
base::AutoLock auto_lock(lock_);
capturers_.remove(capturer);
}
-scoped_refptr<WebRtcAudioCapturer>
-WebRtcAudioDeviceImpl::GetDefaultCapturer() const {
- // Called on the signaling thread (during initialization), worker
- // thread during capture or main thread for a WebAudio source.
- // We can't DCHECK on those three checks here since GetDefaultCapturer
- // may be the first call and therefore could incorrectly initialize the
- // thread checkers.
- DCHECK(initialized_);
- base::AutoLock auto_lock(lock_);
- // Use the last |capturer| which is from the latest getUserMedia call as
- // the default capture device.
- return capturers_.empty() ? NULL : capturers_.back();
-}
-
void WebRtcAudioDeviceImpl::AddPlayoutSink(
WebRtcPlayoutDataSource::Sink* sink) {
DCHECK(main_thread_checker_.CalledOnValidThread());
@@ -511,8 +471,20 @@ bool WebRtcAudioDeviceImpl::GetAuthorizedDeviceInfoForAudioRenderer(
if (capturers_.size() != 1)
return false;
- return capturers_.back()->GetPairedOutputParameters(
- session_id, output_sample_rate, output_frames_per_buffer);
+ // Don't set output parameters unless all of them are valid.
+ const StreamDeviceInfo& device_info = capturers_.back()->device_info();
+ if (device_info.session_id <= 0 ||
+ !device_info.device.matched_output.sample_rate ||
+ !device_info.device.matched_output.frames_per_buffer) {
+ return false;
+ }
+
+ *session_id = device_info.session_id;
+ *output_sample_rate = device_info.device.matched_output.sample_rate;
+ *output_frames_per_buffer =
+ device_info.device.matched_output.frames_per_buffer;
+
+ return true;
}
} // namespace content
diff --git a/chromium/content/renderer/media/webrtc_audio_device_impl.h b/chromium/content/renderer/media/webrtc_audio_device_impl.h
index a3bbf6b8ee7..490eaf4a6d9 100644
--- a/chromium/content/renderer/media/webrtc_audio_device_impl.h
+++ b/chromium/content/renderer/media/webrtc_audio_device_impl.h
@@ -7,6 +7,8 @@
#include <stdint.h>
+#include <list>
+#include <memory>
#include <string>
#include <vector>
@@ -15,7 +17,6 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/threading/thread_checker.h"
#include "content/common/content_export.h"
#include "content/renderer/media/webrtc_audio_capturer.h"
@@ -306,15 +307,12 @@ class CONTENT_EXPORT WebRtcAudioDeviceImpl
// Called on the main renderer thread.
bool SetAudioRenderer(WebRtcAudioRenderer* renderer);
- // Adds/Removes the capturer to the ADM.
+ // Adds/Removes the |capturer| to the ADM. Does NOT take ownership.
+ // Capturers must remain valid until RemoveAudioCapturer() is called.
// TODO(xians): Remove these two methods once the ADM does not need to pass
// hardware information up to WebRtc.
- void AddAudioCapturer(const scoped_refptr<WebRtcAudioCapturer>& capturer);
- void RemoveAudioCapturer(const scoped_refptr<WebRtcAudioCapturer>& capturer);
-
- // Gets the default capturer, which is the last capturer in |capturers_|.
- // The method can be called by both Libjingle thread and main render thread.
- scoped_refptr<WebRtcAudioCapturer> GetDefaultCapturer() const;
+ void AddAudioCapturer(WebRtcAudioCapturer* capturer);
+ void RemoveAudioCapturer(WebRtcAudioCapturer* capturer);
// Gets paired device information of the capture device for the audio
// renderer. This is used to pass on a session id, sample rate and buffer
@@ -331,7 +329,7 @@ class CONTENT_EXPORT WebRtcAudioDeviceImpl
}
private:
- typedef std::list<scoped_refptr<WebRtcAudioCapturer> > CapturerList;
+ typedef std::list<WebRtcAudioCapturer*> CapturerList;
typedef std::list<WebRtcPlayoutDataSource::Sink*> PlayoutDataSinkList;
class RenderBuffer;
@@ -364,7 +362,9 @@ class CONTENT_EXPORT WebRtcAudioDeviceImpl
mutable int ref_count_;
// List of captures which provides access to the native audio input layer
- // in the browser process.
+ // in the browser process. The last capturer in this list is considered the
+ // "default capturer" by the methods implementing the
+ // webrtc::AudioDeviceModule interface.
CapturerList capturers_;
// Provides access to the audio renderer in the browser process.
diff --git a/chromium/content/renderer/media/webrtc_audio_device_not_impl.cc b/chromium/content/renderer/media/webrtc_audio_device_not_impl.cc
index 234bf87f7d3..a86fca0cdee 100644
--- a/chromium/content/renderer/media/webrtc_audio_device_not_impl.cc
+++ b/chromium/content/renderer/media/webrtc_audio_device_not_impl.cc
@@ -16,9 +16,8 @@ int64_t WebRtcAudioDeviceNotImpl::TimeUntilNextProcess() {
return kMillisecondsBetweenProcessCalls - delta_time.InMilliseconds();
}
-int32_t WebRtcAudioDeviceNotImpl::Process() {
+void WebRtcAudioDeviceNotImpl::Process() {
last_process_time_ = base::TimeTicks::Now();
- return 0;
}
int32_t WebRtcAudioDeviceNotImpl::RegisterEventObserver(
diff --git a/chromium/content/renderer/media/webrtc_audio_device_not_impl.h b/chromium/content/renderer/media/webrtc_audio_device_not_impl.h
index e755b61cd40..f0291ed985c 100644
--- a/chromium/content/renderer/media/webrtc_audio_device_not_impl.h
+++ b/chromium/content/renderer/media/webrtc_audio_device_not_impl.h
@@ -31,7 +31,7 @@ class CONTENT_EXPORT WebRtcAudioDeviceNotImpl
// Only adding very basic support for now without triggering any callback
// in the webrtc::AudioDeviceObserver interface.
int64_t TimeUntilNextProcess() override;
- int32_t Process() override;
+ void Process() override;
// Methods in webrtc::AudioDeviceModule which are not yet implemented.
// The idea is that we can move methods from this class to the real
diff --git a/chromium/content/renderer/media/webrtc_audio_renderer.cc b/chromium/content/renderer/media/webrtc_audio_renderer.cc
index 640d8dc4ad6..5713c826a94 100644
--- a/chromium/content/renderer/media/webrtc_audio_renderer.cc
+++ b/chromium/content/renderer/media/webrtc_audio_renderer.cc
@@ -18,12 +18,12 @@
#include "content/renderer/media/webrtc_audio_device_impl.h"
#include "content/renderer/media/webrtc_logging.h"
#include "content/renderer/render_frame_impl.h"
-#include "media/audio/audio_output_device.h"
#include "media/audio/audio_parameters.h"
#include "media/audio/sample_rates.h"
+#include "media/base/audio_capturer_source.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
-#include "third_party/libjingle/source/talk/media/base/audiorenderer.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
+#include "third_party/webrtc/media/base/audiorenderer.h"
#if defined(OS_WIN)
#include "base/win/windows_version.h"
@@ -39,6 +39,13 @@ namespace {
// between each callback leads to one UMA update each 100ms.
const int kNumCallbacksBetweenRenderTimeHistograms = 10;
+// Audio parameters that don't change.
+const media::AudioParameters::Format kFormat =
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY;
+const media::ChannelLayout kChannelLayout = media::CHANNEL_LAYOUT_STEREO;
+const int kChannels = 2;
+const int kBitsPerSample = 16;
+
// This is a simple wrapper class that's handed out to users of a shared
// WebRtcAudioRenderer instance. This class maintains the per-user 'playing'
// and 'started' states to avoid problems related to incorrect usage which
@@ -112,9 +119,17 @@ class SharedAudioRenderer : public MediaStreamAudioRenderer {
on_play_state_changed_.Run(media_stream_, &playing_state_);
}
- media::OutputDevice* GetOutputDevice() override {
+ media::OutputDeviceInfo GetOutputDeviceInfo() override {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ return delegate_->GetOutputDeviceInfo();
+ }
+
+ void SwitchOutputDevice(
+ const std::string& device_id,
+ const url::Origin& security_origin,
+ const media::OutputDeviceStatusCB& callback) override {
DCHECK(thread_checker_.CalledOnValidThread());
- return delegate_->GetOutputDevice();
+ return delegate_->SwitchOutputDevice(device_id, security_origin, callback);
}
base::TimeDelta GetCurrentRenderTime() const override {
@@ -187,12 +202,7 @@ WebRtcAudioRenderer::WebRtcAudioRenderer(
play_ref_count_(0),
start_ref_count_(0),
audio_delay_milliseconds_(0),
- fifo_delay_milliseconds_(0),
- sink_params_(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_STEREO,
- 0,
- 16,
- 0),
+ sink_params_(kFormat, kChannelLayout, 0, kBitsPerSample, 0),
output_device_id_(device_id),
security_origin_(security_origin),
render_callback_count_(0) {
@@ -219,11 +229,14 @@ bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) {
DCHECK(!source_);
}
- sink_ =
- AudioDeviceFactory::NewOutputDevice(source_render_frame_id_, session_id_,
- output_device_id_, security_origin_);
- if (sink_->GetDeviceStatus() != media::OUTPUT_DEVICE_STATUS_OK)
+ sink_ = AudioDeviceFactory::NewAudioRendererSink(
+ AudioDeviceFactory::kSourceWebRtc, source_render_frame_id_, session_id_,
+ output_device_id_, security_origin_);
+
+ if (sink_->GetOutputDeviceInfo().device_status() !=
+ media::OUTPUT_DEVICE_STATUS_OK) {
return false;
+ }
PrepareSink();
{
@@ -236,6 +249,7 @@ bool WebRtcAudioRenderer::Initialize(WebRtcAudioRendererSource* source) {
state_ = PAUSED;
}
sink_->Start();
+ sink_->Play(); // Not all the sinks play on start.
return true;
}
@@ -350,9 +364,9 @@ void WebRtcAudioRenderer::SetVolume(float volume) {
OnPlayStateChanged(media_stream_, &playing_state_);
}
-media::OutputDevice* WebRtcAudioRenderer::GetOutputDevice() {
+media::OutputDeviceInfo WebRtcAudioRenderer::GetOutputDeviceInfo() {
DCHECK(thread_checker_.CalledOnValidThread());
- return this;
+ return sink_ ? sink_->GetOutputDeviceInfo() : media::OutputDeviceInfo();
}
base::TimeDelta WebRtcAudioRenderer::GetCurrentRenderTime() const {
@@ -368,7 +382,7 @@ bool WebRtcAudioRenderer::IsLocalRenderer() const {
void WebRtcAudioRenderer::SwitchOutputDevice(
const std::string& device_id,
const url::Origin& security_origin,
- const media::SwitchOutputDeviceCB& callback) {
+ const media::OutputDeviceStatusCB& callback) {
DVLOG(1) << "WebRtcAudioRenderer::SwitchOutputDevice()";
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK_GE(session_id_, 0);
@@ -378,11 +392,14 @@ void WebRtcAudioRenderer::SwitchOutputDevice(
DCHECK_NE(state_, UNINITIALIZED);
}
- scoped_refptr<media::AudioOutputDevice> new_sink =
- AudioDeviceFactory::NewOutputDevice(source_render_frame_id_, session_id_,
- device_id, security_origin);
- if (new_sink->GetDeviceStatus() != media::OUTPUT_DEVICE_STATUS_OK) {
- callback.Run(new_sink->GetDeviceStatus());
+ scoped_refptr<media::AudioRendererSink> new_sink =
+ AudioDeviceFactory::NewAudioRendererSink(
+ AudioDeviceFactory::kSourceWebRtc, source_render_frame_id_,
+ session_id_, device_id, security_origin);
+ media::OutputDeviceStatus status =
+ new_sink->GetOutputDeviceInfo().device_status();
+ if (status != media::OUTPUT_DEVICE_STATUS_OK) {
+ callback.Run(status);
return;
}
@@ -404,36 +421,50 @@ void WebRtcAudioRenderer::SwitchOutputDevice(
callback.Run(media::OUTPUT_DEVICE_STATUS_OK);
}
-media::AudioParameters WebRtcAudioRenderer::GetOutputParameters() {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (!sink_.get())
- return media::AudioParameters();
-
- return sink_->GetOutputParameters();
-}
-
-media::OutputDeviceStatus WebRtcAudioRenderer::GetDeviceStatus() {
- DCHECK(thread_checker_.CalledOnValidThread());
- if (!sink_.get())
- return media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL;
-
- return sink_->GetDeviceStatus();
-}
-
int WebRtcAudioRenderer::Render(media::AudioBus* audio_bus,
- uint32_t audio_delay_milliseconds,
+ uint32_t frames_delayed,
uint32_t frames_skipped) {
DCHECK(audio_renderer_thread_checker_.CalledOnValidThread());
base::AutoLock auto_lock(lock_);
if (!source_)
return 0;
+ // TODO(grunell): Converting from frames to milliseconds will potentially lose
+ // hundreds of microseconds which may cause audio video drift. Update
+ // this class and all usage of render delay msec -> frames (possibly even
+ // using a double type for frames). See http://crbug.com/586540
+ uint32_t audio_delay_milliseconds = static_cast<double>(frames_delayed) *
+ base::Time::kMillisecondsPerSecond /
+ sink_params_.sample_rate();
+
DVLOG(2) << "WebRtcAudioRenderer::Render()";
DVLOG(2) << "audio_delay_milliseconds: " << audio_delay_milliseconds;
DCHECK_LE(audio_delay_milliseconds, static_cast<uint32_t>(INT_MAX));
audio_delay_milliseconds_ = static_cast<int>(audio_delay_milliseconds);
+ // If there are skipped frames, pull and throw away the same amount. We always
+ // pull 10 ms of data from the source (see PrepareSink()), so the fifo is only
+ // required if the number of frames to drop doesn't correspond to 10 ms.
+ if (frames_skipped > 0) {
+ const uint32_t source_frames_per_buffer =
+ static_cast<uint32_t>(sink_params_.sample_rate() / 100);
+ if (!audio_fifo_ && frames_skipped != source_frames_per_buffer) {
+ audio_fifo_.reset(new media::AudioPullFifo(
+ kChannels, source_frames_per_buffer,
+ base::Bind(&WebRtcAudioRenderer::SourceCallback,
+ base::Unretained(this))));
+ }
+
+ std::unique_ptr<media::AudioBus> drop_bus =
+ media::AudioBus::Create(audio_bus->channels(), frames_skipped);
+ if (audio_fifo_)
+ audio_fifo_->Consume(drop_bus.get(), drop_bus->frames());
+ else
+ SourceCallback(0, drop_bus.get());
+ }
+
+ // Pull the data we will deliver.
if (audio_fifo_)
audio_fifo_->Consume(audio_bus, audio_bus->frames());
else
@@ -457,7 +488,11 @@ void WebRtcAudioRenderer::SourceCallback(
<< audio_bus->frames() << ")";
int output_delay_milliseconds = audio_delay_milliseconds_;
- output_delay_milliseconds += fifo_delay_milliseconds_;
+ // TODO(grunell): This integer division by sample_rate will cause loss of
+ // partial milliseconds, and may cause avsync drift. http://crbug.com/586540
+ output_delay_milliseconds += fifo_frame_delay *
+ base::Time::kMillisecondsPerSecond /
+ sink_params_.sample_rate();
DVLOG(2) << "output_delay_milliseconds: " << output_delay_milliseconds;
// We need to keep render data for the |source_| regardless of |state_|,
@@ -560,7 +595,7 @@ void WebRtcAudioRenderer::OnPlayStateChanged(
media_stream.audioTracks(web_tracks);
for (const blink::WebMediaStreamTrack& web_track : web_tracks) {
- MediaStreamAudioTrack* track = MediaStreamAudioTrack::GetTrack(web_track);
+ MediaStreamAudioTrack* track = MediaStreamAudioTrack::From(web_track);
// WebRtcAudioRenderer can only render audio tracks received from a remote
// peer. Since the actual MediaStream is mutable from JavaScript, we need
// to make sure |web_track| is actually a remote track.
@@ -586,13 +621,17 @@ void WebRtcAudioRenderer::PrepareSink() {
base::AutoLock lock(lock_);
new_sink_params = sink_params_;
}
+
+ const media::OutputDeviceInfo& device_info = sink_->GetOutputDeviceInfo();
+ DCHECK_EQ(device_info.device_status(), media::OUTPUT_DEVICE_STATUS_OK);
+
// WebRTC does not yet support higher rates than 96000 on the client side
// and 48000 is the preferred sample rate. Therefore, if 192000 is detected,
// we change the rate to 48000 instead. The consequence is that the native
// layer will be opened up at 192kHz but WebRTC will provide data at 48kHz
// which will then be resampled by the audio converted on the browser side
// to match the native audio layer.
- int sample_rate = sink_->GetOutputParameters().sample_rate();
+ int sample_rate = device_info.output_params().sample_rate();
DVLOG(1) << "Audio output hardware sample rate: " << sample_rate;
if (sample_rate >= 192000) {
DVLOG(1) << "Resampling from 48000 to " << sample_rate << " is required";
@@ -606,55 +645,38 @@ void WebRtcAudioRenderer::PrepareSink() {
UMA_HISTOGRAM_COUNTS("WebRTC.AudioOutputSampleRateUnexpected", sample_rate);
}
- // Set up audio parameters for the source, i.e., the WebRTC client.
-
- // The WebRTC client only supports multiples of 10ms as buffer size where
- // 10ms is preferred for lowest possible delay.
- const int frames_per_10ms = (sample_rate / 100);
- DVLOG(1) << "Using WebRTC output buffer size: " << frames_per_10ms;
- media::AudioParameters source_params(
- media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- new_sink_params.channel_layout(), sample_rate, 16, frames_per_10ms);
- source_params.set_channels_for_discrete(new_sink_params.channels());
-
- const int frames_per_buffer = GetOptimalBufferSize(
- sample_rate, sink_->GetOutputParameters().frames_per_buffer());
+ // Calculate the frames per buffer for the source, i.e. the WebRTC client. We
+ // use 10 ms of data since the WebRTC client only supports multiples of 10 ms
+ // as buffer size where 10 ms is preferred for lowest possible delay.
+ const int source_frames_per_buffer = (sample_rate / 100);
+ DVLOG(1) << "Using WebRTC output buffer size: " << source_frames_per_buffer;
- new_sink_params.Reset(
- new_sink_params.format(), new_sink_params.channel_layout(),
- sample_rate, 16, frames_per_buffer);
+ // Setup sink parameters.
+ const int sink_frames_per_buffer = GetOptimalBufferSize(
+ sample_rate, device_info.output_params().frames_per_buffer());
+ new_sink_params.set_sample_rate(sample_rate);
+ new_sink_params.set_frames_per_buffer(sink_frames_per_buffer);
// Create a FIFO if re-buffering is required to match the source input with
// the sink request. The source acts as provider here and the sink as
// consumer.
- int new_fifo_delay_milliseconds = 0;
- scoped_ptr<media::AudioPullFifo> new_audio_fifo;
- if (source_params.frames_per_buffer() !=
- new_sink_params.frames_per_buffer()) {
- DVLOG(1) << "Rebuffering from " << source_params.frames_per_buffer()
- << " to " << new_sink_params.frames_per_buffer();
- new_audio_fifo.reset(new media::AudioPullFifo(
- source_params.channels(), source_params.frames_per_buffer(),
- base::Bind(&WebRtcAudioRenderer::SourceCallback,
- base::Unretained(this))));
-
- if (new_sink_params.frames_per_buffer() >
- source_params.frames_per_buffer()) {
- int frame_duration_milliseconds =
- base::Time::kMillisecondsPerSecond /
- static_cast<double>(source_params.sample_rate());
- new_fifo_delay_milliseconds = (new_sink_params.frames_per_buffer() -
- source_params.frames_per_buffer()) *
- frame_duration_milliseconds;
- }
+ const bool different_source_sink_frames =
+ source_frames_per_buffer != new_sink_params.frames_per_buffer();
+ if (different_source_sink_frames) {
+ DVLOG(1) << "Rebuffering from " << source_frames_per_buffer << " to "
+ << new_sink_params.frames_per_buffer();
}
-
{
base::AutoLock lock(lock_);
+ if ((!audio_fifo_ && different_source_sink_frames) ||
+ (audio_fifo_ &&
+ audio_fifo_->SizeInFrames() != source_frames_per_buffer)) {
+ audio_fifo_.reset(new media::AudioPullFifo(
+ kChannels, source_frames_per_buffer,
+ base::Bind(&WebRtcAudioRenderer::SourceCallback,
+ base::Unretained(this))));
+ }
sink_params_ = new_sink_params;
- fifo_delay_milliseconds_ = new_fifo_delay_milliseconds;
- if (new_audio_fifo.get())
- audio_fifo_ = std::move(new_audio_fifo);
}
sink_->Initialize(new_sink_params, this);
diff --git a/chromium/content/renderer/media/webrtc_audio_renderer.h b/chromium/content/renderer/media/webrtc_audio_renderer.h
index 29d02fbaa28..9383f916401 100644
--- a/chromium/content/renderer/media/webrtc_audio_renderer.h
+++ b/chromium/content/renderer/media/webrtc_audio_renderer.h
@@ -22,13 +22,8 @@
#include "media/base/audio_pull_fifo.h"
#include "media/base/audio_renderer_sink.h"
#include "media/base/channel_layout.h"
-#include "media/base/output_device.h"
#include "third_party/WebKit/public/platform/WebMediaStream.h"
-namespace media {
-class AudioOutputDevice;
-} // namespace media
-
namespace webrtc {
class AudioSourceInterface;
} // namespace webrtc
@@ -41,8 +36,7 @@ class WebRtcAudioRendererSource;
// for connecting WebRtc MediaStream with the audio pipeline.
class CONTENT_EXPORT WebRtcAudioRenderer
: NON_EXPORTED_BASE(public media::AudioRendererSink::RenderCallback),
- NON_EXPORTED_BASE(public MediaStreamAudioRenderer),
- NON_EXPORTED_BASE(public media::OutputDevice) {
+ NON_EXPORTED_BASE(public MediaStreamAudioRenderer) {
public:
// This is a little utility class that holds the configured state of an audio
// stream.
@@ -123,16 +117,12 @@ class CONTENT_EXPORT WebRtcAudioRenderer
void Pause() override;
void Stop() override;
void SetVolume(float volume) override;
- media::OutputDevice* GetOutputDevice() override;
+ media::OutputDeviceInfo GetOutputDeviceInfo() override;
base::TimeDelta GetCurrentRenderTime() const override;
bool IsLocalRenderer() const override;
-
- // media::OutputDevice implementation
void SwitchOutputDevice(const std::string& device_id,
const url::Origin& security_origin,
- const media::SwitchOutputDeviceCB& callback) override;
- media::AudioParameters GetOutputParameters() override;
- media::OutputDeviceStatus GetDeviceStatus() override;
+ const media::OutputDeviceStatusCB& callback) override;
// Called when an audio renderer, either the main or a proxy, starts playing.
// Here we maintain a reference count of how many renderers are currently
@@ -172,7 +162,7 @@ class CONTENT_EXPORT WebRtcAudioRenderer
// media::AudioRendererSink::RenderCallback implementation.
// These two methods are called on the AudioOutputDevice worker thread.
int Render(media::AudioBus* audio_bus,
- uint32_t audio_delay_milliseconds,
+ uint32_t frames_delayed,
uint32_t frames_skipped) override;
void OnRenderError() override;
@@ -203,8 +193,8 @@ class CONTENT_EXPORT WebRtcAudioRenderer
void OnPlayStateChanged(const blink::WebMediaStream& media_stream,
PlayingState* state);
- // Updates |sink_params_|, |audio_fifo_| and |fifo_delay_milliseconds_| based
- // on |sink_|, and initializes |sink_|.
+ // Updates |sink_params_| and |audio_fifo_| based on |sink_|, and initializes
+ // |sink_|.
void PrepareSink();
// The RenderFrame in which the audio is rendered into |sink_|.
@@ -214,7 +204,7 @@ class CONTENT_EXPORT WebRtcAudioRenderer
const scoped_refptr<base::SingleThreadTaskRunner> signaling_thread_;
// The sink (destination) for rendered audio.
- scoped_refptr<media::AudioOutputDevice> sink_;
+ scoped_refptr<media::AudioRendererSink> sink_;
// The media stream that holds the audio tracks that this renderer renders.
const blink::WebMediaStream media_stream_;
@@ -235,15 +225,12 @@ class CONTENT_EXPORT WebRtcAudioRenderer
// Used to buffer data between the client and the output device in cases where
// the client buffer size is not the same as the output device buffer size.
- scoped_ptr<media::AudioPullFifo> audio_fifo_;
+ std::unique_ptr<media::AudioPullFifo> audio_fifo_;
// Contains the accumulated delay estimate which is provided to the WebRTC
// AEC.
int audio_delay_milliseconds_;
- // Delay due to the FIFO in milliseconds.
- int fifo_delay_milliseconds_;
-
base::TimeDelta current_time_;
// Saved volume and playing state of the root renderer.
diff --git a/chromium/content/renderer/media/webrtc_audio_renderer_unittest.cc b/chromium/content/renderer/media/webrtc_audio_renderer_unittest.cc
index 86710d558c1..1b1e7490f68 100644
--- a/chromium/content/renderer/media/webrtc_audio_renderer_unittest.cc
+++ b/chromium/content/renderer/media/webrtc_audio_renderer_unittest.cc
@@ -8,24 +8,19 @@
#include <utility>
#include <vector>
+#include "base/bind.h"
#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
#include "build/build_config.h"
#include "content/public/renderer/media_stream_audio_renderer.h"
#include "content/renderer/media/audio_device_factory.h"
-#include "content/renderer/media/audio_message_filter.h"
-#include "content/renderer/media/webrtc/mock_peer_connection_dependency_factory.h"
#include "content/renderer/media/webrtc_audio_device_impl.h"
-#include "media/audio/audio_output_device.h"
-#include "media/audio/audio_output_ipc.h"
-#include "media/base/audio_bus.h"
#include "media/base/mock_audio_renderer_sink.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebMediaStream.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
#include "third_party/WebKit/public/web/WebHeap.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
using testing::Return;
using testing::_;
@@ -40,68 +35,6 @@ const char kDefaultOutputDeviceId[] = "";
const char kOtherOutputDeviceId[] = "other-output-device";
const char kInvalidOutputDeviceId[] = "invalid-device";
-class MockAudioOutputIPC : public media::AudioOutputIPC {
- public:
- MockAudioOutputIPC() {}
- virtual ~MockAudioOutputIPC() {}
-
- MOCK_METHOD4(RequestDeviceAuthorization,
- void(media::AudioOutputIPCDelegate* delegate,
- int session_id,
- const std::string& device_id,
- const url::Origin& security_origin));
- MOCK_METHOD2(CreateStream,
- void(media::AudioOutputIPCDelegate* delegate,
- const media::AudioParameters& params));
- MOCK_METHOD0(PlayStream, void());
- MOCK_METHOD0(PauseStream, void());
- MOCK_METHOD0(CloseStream, void());
- MOCK_METHOD1(SetVolume, void(double volume));
- MOCK_METHOD2(SwitchOutputDevice,
- void(const std::string& device_id,
- const url::Origin& security_origin));
-};
-
-class FakeAudioOutputDevice
- : NON_EXPORTED_BASE(public media::AudioOutputDevice) {
- public:
- FakeAudioOutputDevice(
- scoped_ptr<media::AudioOutputIPC> ipc,
- const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner,
- const std::string& device_id)
- : AudioOutputDevice(std::move(ipc),
- io_task_runner,
- 0,
- std::string(),
- url::Origin()),
- device_id_(device_id) {}
- MOCK_METHOD0(Start, void());
- MOCK_METHOD0(Stop, void());
- MOCK_METHOD0(Pause, void());
- MOCK_METHOD0(Play, void());
- MOCK_METHOD1(SetVolume, bool(double volume));
-
- media::OutputDeviceStatus GetDeviceStatus() override {
- return device_id_ == kInvalidOutputDeviceId
- ? media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL
- : media::OUTPUT_DEVICE_STATUS_OK;
- }
-
- std::string GetDeviceId() const { return device_id_; }
-
- media::AudioParameters GetOutputParameters() override {
- return media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
- media::CHANNEL_LAYOUT_STEREO,
- kHardwareSampleRate, 16, kHardwareBufferSize);
- }
-
- protected:
- virtual ~FakeAudioOutputDevice() {}
-
- private:
- const std::string device_id_;
-};
-
class MockAudioRendererSource : public WebRtcAudioRendererSource {
public:
MockAudioRendererSource() {}
@@ -129,7 +62,6 @@ class WebRtcAudioRendererTest : public testing::Test,
protected:
WebRtcAudioRendererTest()
: message_loop_(new base::MessageLoopForIO),
- mock_ipc_(nullptr),
source_(new MockAudioRendererSource()) {
blink::WebVector<blink::WebMediaStreamTrack> dummy_tracks;
stream_.initialize("new stream", dummy_tracks, dummy_tracks);
@@ -138,36 +70,54 @@ class WebRtcAudioRendererTest : public testing::Test,
void SetupRenderer(const std::string& device_id) {
renderer_ = new WebRtcAudioRenderer(message_loop_->task_runner(), stream_,
1, 1, device_id, url::Origin());
- EXPECT_CALL(*this, MockCreateOutputDevice(1, _, device_id, _));
+ EXPECT_CALL(
+ *this, MockCreateAudioRendererSink(AudioDeviceFactory::kSourceWebRtc, _,
+ _, device_id, _));
EXPECT_TRUE(renderer_->Initialize(source_.get()));
renderer_proxy_ = renderer_->CreateSharedAudioRendererProxy(stream_);
}
-
- MOCK_METHOD1(CreateInputDevice, media::AudioInputDevice*(int));
- MOCK_METHOD4(MockCreateOutputDevice,
- media::AudioOutputDevice*(int,
- int,
- const std::string&,
- const url::Origin&));
- media::AudioOutputDevice* CreateOutputDevice(
+ MOCK_METHOD1(CreateAudioCapturerSource,
+ scoped_refptr<media::AudioCapturerSource>(int));
+ MOCK_METHOD4(CreateAudioRendererMixerSink,
+ scoped_refptr<media::AudioRendererSink>(int,
+ int,
+ const std::string&,
+ const url::Origin&));
+ MOCK_METHOD5(
+ CreateSwitchableAudioRendererSink,
+ scoped_refptr<media::SwitchableAudioRendererSink>(SourceType,
+ int,
+ int,
+ const std::string&,
+ const url::Origin&));
+ MOCK_METHOD5(
+ MockCreateAudioRendererSink,
+ void(SourceType, int, int, const std::string&, const url::Origin&));
+
+ scoped_refptr<media::AudioRendererSink> CreateAudioRendererSink(
+ SourceType source_type,
int render_frame_id,
int session_id,
const std::string& device_id,
const url::Origin& security_origin) {
- MockAudioOutputIPC* fake_ipc = new MockAudioOutputIPC();
- FakeAudioOutputDevice* fake_device =
- new FakeAudioOutputDevice(scoped_ptr<media::AudioOutputIPC>(fake_ipc),
- message_loop_->task_runner(), device_id);
+ scoped_refptr<media::MockAudioRendererSink> fake_sink(
+ new media::MockAudioRendererSink(
+ device_id, device_id == kInvalidOutputDeviceId
+ ? media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL
+ : media::OUTPUT_DEVICE_STATUS_OK,
+ media::AudioParameters(
+ media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
+ media::CHANNEL_LAYOUT_STEREO, kHardwareSampleRate, 16,
+ kHardwareBufferSize)));
if (device_id != kInvalidOutputDeviceId) {
- mock_output_device_ = fake_device;
- mock_ipc_ = fake_ipc;
- EXPECT_CALL(*mock_output_device_.get(), Start());
+ mock_sink_ = fake_sink;
+ EXPECT_CALL(*mock_sink_.get(), Start());
}
- MockCreateOutputDevice(render_frame_id, session_id, device_id,
- security_origin);
- return fake_device;
+ MockCreateAudioRendererSink(source_type, render_frame_id, session_id,
+ device_id, security_origin);
+ return fake_sink;
}
void TearDown() override {
@@ -175,16 +125,13 @@ class WebRtcAudioRendererTest : public testing::Test,
renderer_ = nullptr;
stream_.reset();
source_.reset();
- mock_output_device_ = nullptr;
+ mock_sink_ = nullptr;
blink::WebHeap::collectAllGarbageForTesting();
}
- // Used to construct |mock_output_device_|.
- scoped_ptr<base::MessageLoopForIO> message_loop_;
- MockAudioOutputIPC* mock_ipc_; // Owned by AudioOuputDevice.
-
- scoped_refptr<FakeAudioOutputDevice> mock_output_device_;
- scoped_ptr<MockAudioRendererSource> source_;
+ std::unique_ptr<base::MessageLoopForIO> message_loop_;
+ scoped_refptr<media::MockAudioRendererSink> mock_sink_;
+ std::unique_ptr<MockAudioRendererSource> source_;
blink::WebMediaStream stream_;
scoped_refptr<WebRtcAudioRenderer> renderer_;
scoped_refptr<MediaStreamAudioRenderer> renderer_proxy_;
@@ -197,7 +144,7 @@ TEST_F(WebRtcAudioRendererTest, StopRenderer) {
// |renderer_| has only one proxy, stopping the proxy should stop the sink of
// |renderer_|.
- EXPECT_CALL(*mock_output_device_.get(), Stop());
+ EXPECT_CALL(*mock_sink_.get(), Stop());
EXPECT_CALL(*source_.get(), RemoveAudioRenderer(renderer_.get()));
renderer_proxy_->Stop();
}
@@ -220,16 +167,16 @@ TEST_F(WebRtcAudioRendererTest, MultipleRenderers) {
// Stop the |renderer_proxy_| should not stop the sink since it is used by
// other proxies.
- EXPECT_CALL(*mock_output_device_.get(), Stop()).Times(0);
+ EXPECT_CALL(*mock_sink_.get(), Stop()).Times(0);
renderer_proxy_->Stop();
for (int i = 0; i < kNumberOfRendererProxy; ++i) {
if (i != kNumberOfRendererProxy -1) {
- EXPECT_CALL(*mock_output_device_.get(), Stop()).Times(0);
+ EXPECT_CALL(*mock_sink_.get(), Stop()).Times(0);
} else {
// When the last proxy is stopped, the sink will stop.
EXPECT_CALL(*source_.get(), RemoveAudioRenderer(renderer_.get()));
- EXPECT_CALL(*mock_output_device_.get(), Stop());
+ EXPECT_CALL(*mock_sink_.get(), Stop());
}
renderer_proxies_[i]->Stop();
}
@@ -252,68 +199,78 @@ TEST_F(WebRtcAudioRendererTest, VerifySinkParameters) {
EXPECT_EQ(kHardwareSampleRate, renderer_->sample_rate());
EXPECT_EQ(2, renderer_->channels());
- EXPECT_CALL(*mock_output_device_.get(), Stop());
+ EXPECT_CALL(*mock_sink_.get(), Stop());
EXPECT_CALL(*source_.get(), RemoveAudioRenderer(renderer_.get()));
renderer_proxy_->Stop();
}
TEST_F(WebRtcAudioRendererTest, NonDefaultDevice) {
SetupRenderer(kDefaultOutputDeviceId);
- EXPECT_EQ(mock_output_device_->GetDeviceId(), kDefaultOutputDeviceId);
+ EXPECT_EQ(kDefaultOutputDeviceId,
+ mock_sink_->GetOutputDeviceInfo().device_id());
renderer_proxy_->Start();
- EXPECT_CALL(*mock_output_device_.get(), Stop());
+ EXPECT_CALL(*mock_sink_.get(), Stop());
EXPECT_CALL(*source_.get(), RemoveAudioRenderer(renderer_.get()));
renderer_proxy_->Stop();
SetupRenderer(kOtherOutputDeviceId);
- EXPECT_EQ(mock_output_device_->GetDeviceId(), kOtherOutputDeviceId);
+ EXPECT_EQ(kOtherOutputDeviceId,
+ mock_sink_->GetOutputDeviceInfo().device_id());
renderer_proxy_->Start();
- EXPECT_CALL(*mock_output_device_.get(), Stop());
+ EXPECT_CALL(*mock_sink_.get(), Stop());
EXPECT_CALL(*source_.get(), RemoveAudioRenderer(renderer_.get()));
renderer_proxy_->Stop();
}
TEST_F(WebRtcAudioRendererTest, SwitchOutputDevice) {
SetupRenderer(kDefaultOutputDeviceId);
- EXPECT_EQ(kDefaultOutputDeviceId, mock_output_device_->GetDeviceId());
+ EXPECT_EQ(kDefaultOutputDeviceId,
+ mock_sink_->GetOutputDeviceInfo().device_id());
renderer_proxy_->Start();
- EXPECT_CALL(*mock_output_device_.get(), Stop());
- EXPECT_CALL(*this, MockCreateOutputDevice(_, _, kOtherOutputDeviceId, _));
+ EXPECT_CALL(*mock_sink_.get(), Stop());
+ EXPECT_CALL(*this,
+ MockCreateAudioRendererSink(AudioDeviceFactory::kSourceWebRtc, _,
+ _, kOtherOutputDeviceId, _));
EXPECT_CALL(*source_.get(), AudioRendererThreadStopped());
EXPECT_CALL(*this, MockSwitchDeviceCallback(media::OUTPUT_DEVICE_STATUS_OK));
base::RunLoop loop;
- renderer_proxy_->GetOutputDevice()->SwitchOutputDevice(
+ renderer_proxy_->SwitchOutputDevice(
kOtherOutputDeviceId, url::Origin(),
base::Bind(&WebRtcAudioRendererTest::SwitchDeviceCallback,
base::Unretained(this), &loop));
loop.Run();
- EXPECT_EQ(kOtherOutputDeviceId, mock_output_device_->GetDeviceId());
+ EXPECT_EQ(kOtherOutputDeviceId,
+ mock_sink_->GetOutputDeviceInfo().device_id());
- EXPECT_CALL(*mock_output_device_.get(), Stop());
+ EXPECT_CALL(*mock_sink_.get(), Stop());
EXPECT_CALL(*source_.get(), RemoveAudioRenderer(renderer_.get()));
renderer_proxy_->Stop();
}
TEST_F(WebRtcAudioRendererTest, SwitchOutputDeviceInvalidDevice) {
SetupRenderer(kDefaultOutputDeviceId);
- EXPECT_EQ(kDefaultOutputDeviceId, mock_output_device_->GetDeviceId());
+ EXPECT_EQ(kDefaultOutputDeviceId,
+ mock_sink_->GetOutputDeviceInfo().device_id());
renderer_proxy_->Start();
- EXPECT_CALL(*this, MockCreateOutputDevice(_, _, kInvalidOutputDeviceId, _));
+ EXPECT_CALL(*this,
+ MockCreateAudioRendererSink(AudioDeviceFactory::kSourceWebRtc, _,
+ _, kInvalidOutputDeviceId, _));
EXPECT_CALL(*this, MockSwitchDeviceCallback(
media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL));
base::RunLoop loop;
- renderer_proxy_->GetOutputDevice()->SwitchOutputDevice(
+ renderer_proxy_->SwitchOutputDevice(
kInvalidOutputDeviceId, url::Origin(),
base::Bind(&WebRtcAudioRendererTest::SwitchDeviceCallback,
base::Unretained(this), &loop));
loop.Run();
- EXPECT_EQ(kDefaultOutputDeviceId, mock_output_device_->GetDeviceId());
+ EXPECT_EQ(kDefaultOutputDeviceId,
+ mock_sink_->GetOutputDeviceInfo().device_id());
- EXPECT_CALL(*mock_output_device_.get(), Stop());
+ EXPECT_CALL(*mock_sink_.get(), Stop());
EXPECT_CALL(*source_.get(), RemoveAudioRenderer(renderer_.get()));
renderer_proxy_->Stop();
}
diff --git a/chromium/content/renderer/media/webrtc_identity_service.cc b/chromium/content/renderer/media/webrtc_identity_service.cc
index c38d19285b0..16cdd99448d 100644
--- a/chromium/content/renderer/media/webrtc_identity_service.cc
+++ b/chromium/content/renderer/media/webrtc_identity_service.cc
@@ -20,6 +20,9 @@ WebRTCIdentityService::RequestInfo::RequestInfo(
success_callback(success_callback),
failure_callback(failure_callback) {}
+WebRTCIdentityService::RequestInfo::RequestInfo(const RequestInfo& other) =
+ default;
+
WebRTCIdentityService::RequestInfo::~RequestInfo() {}
WebRTCIdentityService::WebRTCIdentityService() : next_request_id_(1) {
diff --git a/chromium/content/renderer/media/webrtc_identity_service.h b/chromium/content/renderer/media/webrtc_identity_service.h
index 6092f8aa439..927700d6a0e 100644
--- a/chromium/content/renderer/media/webrtc_identity_service.h
+++ b/chromium/content/renderer/media/webrtc_identity_service.h
@@ -69,6 +69,7 @@ class CONTENT_EXPORT WebRTCIdentityService : public RenderProcessObserver {
RequestInfo(const WebRTCIdentityMsg_RequestIdentity_Params& params,
const SuccessCallback& success_callback,
const FailureCallback& failure_callback);
+ RequestInfo(const RequestInfo& other);
~RequestInfo();
WebRTCIdentityMsg_RequestIdentity_Params params;
diff --git a/chromium/content/renderer/media/webrtc_identity_service_unittest.cc b/chromium/content/renderer/media/webrtc_identity_service_unittest.cc
index cddbd0caf3f..80b71cd6a15 100644
--- a/chromium/content/renderer/media/webrtc_identity_service_unittest.cc
+++ b/chromium/content/renderer/media/webrtc_identity_service_unittest.cc
@@ -69,7 +69,7 @@ class WebRtcIdentityServiceTest : public ::testing::Test {
base::Unretained(this)));
}
- scoped_ptr<WebRtcIdentityServiceForTest> service_;
+ std::unique_ptr<WebRtcIdentityServiceForTest> service_;
std::string last_certificate_;
std::string last_private_key_;
int last_error_;
diff --git a/chromium/content/renderer/media/webrtc_local_audio_renderer.cc b/chromium/content/renderer/media/webrtc_local_audio_renderer.cc
deleted file mode 100644
index f39a017b94d..00000000000
--- a/chromium/content/renderer/media/webrtc_local_audio_renderer.cc
+++ /dev/null
@@ -1,356 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/media/webrtc_local_audio_renderer.h"
-
-#include <utility>
-
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/metrics/histogram.h"
-#include "base/synchronization/lock.h"
-#include "base/thread_task_runner_handle.h"
-#include "base/trace_event/trace_event.h"
-#include "content/renderer/media/audio_device_factory.h"
-#include "content/renderer/media/media_stream_dispatcher.h"
-#include "content/renderer/media/webrtc_audio_capturer.h"
-#include "content/renderer/media/webrtc_audio_renderer.h"
-#include "content/renderer/render_frame_impl.h"
-#include "media/audio/audio_output_device.h"
-#include "media/base/audio_bus.h"
-#include "media/base/audio_shifter.h"
-
-namespace content {
-
-namespace {
-
-enum LocalRendererSinkStates {
- kSinkStarted = 0,
- kSinkNeverStarted,
- kSinkStatesMax // Must always be last!
-};
-
-} // namespace
-
-// media::AudioRendererSink::RenderCallback implementation
-int WebRtcLocalAudioRenderer::Render(media::AudioBus* audio_bus,
- uint32_t audio_delay_milliseconds,
- uint32_t frames_skipped) {
- TRACE_EVENT0("audio", "WebRtcLocalAudioRenderer::Render");
- base::AutoLock auto_lock(thread_lock_);
-
- if (!playing_ || !volume_ || !audio_shifter_) {
- audio_bus->Zero();
- return 0;
- }
-
- audio_shifter_->Pull(
- audio_bus,
- base::TimeTicks::Now() -
- base::TimeDelta::FromMilliseconds(audio_delay_milliseconds));
-
- return audio_bus->frames();
-}
-
-void WebRtcLocalAudioRenderer::OnRenderError() {
- NOTIMPLEMENTED();
-}
-
-// content::MediaStreamAudioSink implementation
-void WebRtcLocalAudioRenderer::OnData(const media::AudioBus& audio_bus,
- base::TimeTicks estimated_capture_time) {
- DCHECK(capture_thread_checker_.CalledOnValidThread());
- DCHECK(!estimated_capture_time.is_null());
-
- TRACE_EVENT0("audio", "WebRtcLocalAudioRenderer::CaptureData");
-
- base::AutoLock auto_lock(thread_lock_);
- if (!playing_ || !volume_ || !audio_shifter_)
- return;
-
- scoped_ptr<media::AudioBus> audio_data(
- media::AudioBus::Create(audio_bus.channels(), audio_bus.frames()));
- audio_bus.CopyTo(audio_data.get());
- audio_shifter_->Push(std::move(audio_data), estimated_capture_time);
- const base::TimeTicks now = base::TimeTicks::Now();
- total_render_time_ += now - last_render_time_;
- last_render_time_ = now;
-}
-
-void WebRtcLocalAudioRenderer::OnSetFormat(
- const media::AudioParameters& params) {
- DVLOG(1) << "WebRtcLocalAudioRenderer::OnSetFormat()";
- // If the source is restarted, we might have changed to another capture
- // thread.
- capture_thread_checker_.DetachFromThread();
- DCHECK(capture_thread_checker_.CalledOnValidThread());
-
- // Post a task on the main render thread to reconfigure the |sink_| with the
- // new format.
- task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&WebRtcLocalAudioRenderer::ReconfigureSink, this, params));
-}
-
-// WebRtcLocalAudioRenderer::WebRtcLocalAudioRenderer implementation.
-WebRtcLocalAudioRenderer::WebRtcLocalAudioRenderer(
- const blink::WebMediaStreamTrack& audio_track,
- int source_render_frame_id,
- int session_id,
- const std::string& device_id,
- const url::Origin& security_origin)
- : audio_track_(audio_track),
- source_render_frame_id_(source_render_frame_id),
- session_id_(session_id),
- task_runner_(base::ThreadTaskRunnerHandle::Get()),
- playing_(false),
- output_device_id_(device_id),
- security_origin_(security_origin),
- volume_(0.0),
- sink_started_(false) {
- DVLOG(1) << "WebRtcLocalAudioRenderer::WebRtcLocalAudioRenderer()";
-}
-
-WebRtcLocalAudioRenderer::~WebRtcLocalAudioRenderer() {
- DCHECK(task_runner_->BelongsToCurrentThread());
- DCHECK(!sink_.get());
- DVLOG(1) << "WebRtcLocalAudioRenderer::~WebRtcLocalAudioRenderer()";
-}
-
-void WebRtcLocalAudioRenderer::Start() {
- DVLOG(1) << "WebRtcLocalAudioRenderer::Start()";
- DCHECK(task_runner_->BelongsToCurrentThread());
-
- // We get audio data from |audio_track_|...
- MediaStreamAudioSink::AddToAudioTrack(this, audio_track_);
- // ...and |sink_| will get audio data from us.
- DCHECK(!sink_.get());
- sink_ =
- AudioDeviceFactory::NewOutputDevice(source_render_frame_id_, session_id_,
- output_device_id_, security_origin_);
-
- base::AutoLock auto_lock(thread_lock_);
- last_render_time_ = base::TimeTicks::Now();
- playing_ = false;
-}
-
-void WebRtcLocalAudioRenderer::Stop() {
- DVLOG(1) << "WebRtcLocalAudioRenderer::Stop()";
- DCHECK(task_runner_->BelongsToCurrentThread());
-
- {
- base::AutoLock auto_lock(thread_lock_);
- playing_ = false;
- audio_shifter_.reset();
- }
-
- // Stop the output audio stream, i.e, stop asking for data to render.
- // It is safer to call Stop() on the |sink_| to clean up the resources even
- // when the |sink_| is never started.
- if (sink_.get()) {
- sink_->Stop();
- sink_ = NULL;
- }
-
- if (!sink_started_) {
- UMA_HISTOGRAM_ENUMERATION("Media.LocalRendererSinkStates",
- kSinkNeverStarted, kSinkStatesMax);
- }
- sink_started_ = false;
-
- // Ensure that the capturer stops feeding us with captured audio.
- MediaStreamAudioSink::RemoveFromAudioTrack(this, audio_track_);
-}
-
-void WebRtcLocalAudioRenderer::Play() {
- DVLOG(1) << "WebRtcLocalAudioRenderer::Play()";
- DCHECK(task_runner_->BelongsToCurrentThread());
-
- if (!sink_.get())
- return;
-
- {
- base::AutoLock auto_lock(thread_lock_);
- // Resumes rendering by ensuring that WebRtcLocalAudioRenderer::Render()
- // now reads data from the local FIFO.
- playing_ = true;
- last_render_time_ = base::TimeTicks::Now();
- }
-
- // Note: If volume_ is currently muted, the |sink_| will not be started yet.
- MaybeStartSink();
-}
-
-void WebRtcLocalAudioRenderer::Pause() {
- DVLOG(1) << "WebRtcLocalAudioRenderer::Pause()";
- DCHECK(task_runner_->BelongsToCurrentThread());
-
- if (!sink_.get())
- return;
-
- base::AutoLock auto_lock(thread_lock_);
- // Temporarily suspends rendering audio.
- // WebRtcLocalAudioRenderer::Render() will return early during this state
- // and only zeros will be provided to the active sink.
- playing_ = false;
-}
-
-void WebRtcLocalAudioRenderer::SetVolume(float volume) {
- DVLOG(1) << "WebRtcLocalAudioRenderer::SetVolume(" << volume << ")";
- DCHECK(task_runner_->BelongsToCurrentThread());
-
- {
- base::AutoLock auto_lock(thread_lock_);
- // Cache the volume.
- volume_ = volume;
- }
-
- // Lazily start the |sink_| when the local renderer is unmuted during
- // playing.
- MaybeStartSink();
-
- if (sink_.get())
- sink_->SetVolume(volume);
-}
-
-media::OutputDevice* WebRtcLocalAudioRenderer::GetOutputDevice() {
- DCHECK(task_runner_->BelongsToCurrentThread());
- return this;
-}
-
-base::TimeDelta WebRtcLocalAudioRenderer::GetCurrentRenderTime() const {
- DCHECK(task_runner_->BelongsToCurrentThread());
- base::AutoLock auto_lock(thread_lock_);
- if (!sink_.get())
- return base::TimeDelta();
- return total_render_time();
-}
-
-bool WebRtcLocalAudioRenderer::IsLocalRenderer() const {
- return true;
-}
-
-void WebRtcLocalAudioRenderer::SwitchOutputDevice(
- const std::string& device_id,
- const url::Origin& security_origin,
- const media::SwitchOutputDeviceCB& callback) {
- DVLOG(1) << "WebRtcLocalAudioRenderer::SwitchOutputDevice()";
- DCHECK(task_runner_->BelongsToCurrentThread());
-
- scoped_refptr<media::AudioOutputDevice> new_sink =
- AudioDeviceFactory::NewOutputDevice(source_render_frame_id_, session_id_,
- device_id, security_origin);
- if (new_sink->GetDeviceStatus() != media::OUTPUT_DEVICE_STATUS_OK) {
- callback.Run(new_sink->GetDeviceStatus());
- return;
- }
-
- output_device_id_ = device_id;
- security_origin_ = security_origin;
- bool was_sink_started = sink_started_;
-
- if (sink_.get())
- sink_->Stop();
-
- sink_started_ = false;
- sink_ = new_sink;
- int frames_per_buffer = sink_->GetOutputParameters().frames_per_buffer();
- sink_params_ = source_params_;
- sink_params_.set_frames_per_buffer(WebRtcAudioRenderer::GetOptimalBufferSize(
- source_params_.sample_rate(), frames_per_buffer));
-
- if (was_sink_started)
- MaybeStartSink();
-
- callback.Run(media::OUTPUT_DEVICE_STATUS_OK);
-}
-
-media::AudioParameters WebRtcLocalAudioRenderer::GetOutputParameters() {
- DCHECK(task_runner_->BelongsToCurrentThread());
- if (!sink_.get())
- return media::AudioParameters();
-
- return sink_->GetOutputParameters();
-}
-
-media::OutputDeviceStatus WebRtcLocalAudioRenderer::GetDeviceStatus() {
- DCHECK(task_runner_->BelongsToCurrentThread());
- if (!sink_.get())
- return media::OUTPUT_DEVICE_STATUS_ERROR_INTERNAL;
-
- return sink_->GetDeviceStatus();
-}
-
-void WebRtcLocalAudioRenderer::MaybeStartSink() {
- DCHECK(task_runner_->BelongsToCurrentThread());
- DVLOG(1) << "WebRtcLocalAudioRenderer::MaybeStartSink()";
-
- if (!sink_.get() || !source_params_.IsValid())
- return;
-
- {
- // Clear up the old data in the FIFO.
- base::AutoLock auto_lock(thread_lock_);
- audio_shifter_->Flush();
- }
-
- if (!sink_params_.IsValid() || !playing_ || !volume_ || sink_started_ ||
- sink_->GetDeviceStatus() != media::OUTPUT_DEVICE_STATUS_OK)
- return;
-
- DVLOG(1) << "WebRtcLocalAudioRenderer::MaybeStartSink() -- Starting sink_.";
- sink_->Initialize(sink_params_, this);
- sink_->Start();
- sink_started_ = true;
- UMA_HISTOGRAM_ENUMERATION("Media.LocalRendererSinkStates",
- kSinkStarted, kSinkStatesMax);
-}
-
-void WebRtcLocalAudioRenderer::ReconfigureSink(
- const media::AudioParameters& params) {
- DCHECK(task_runner_->BelongsToCurrentThread());
-
- DVLOG(1) << "WebRtcLocalAudioRenderer::ReconfigureSink()";
-
- if (source_params_.Equals(params))
- return;
-
- // Reset the |source_params_|, |sink_params_| and |loopback_fifo_| to match
- // the new format.
-
- source_params_ = params;
- {
- // Note: The max buffer is fairly large, but will rarely be used.
- // Cast needs the buffer to hold at least one second of audio.
- // The clock accuracy is set to 20ms because clock accuracy is
- // ~15ms on windows.
- media::AudioShifter* const new_shifter = new media::AudioShifter(
- base::TimeDelta::FromSeconds(2),
- base::TimeDelta::FromMilliseconds(20),
- base::TimeDelta::FromSeconds(20),
- source_params_.sample_rate(),
- params.channels());
-
- base::AutoLock auto_lock(thread_lock_);
- audio_shifter_.reset(new_shifter);
- }
-
- if (!sink_.get())
- return; // WebRtcLocalAudioRenderer has not yet been started.
-
- // Stop |sink_| and re-create a new one to be initialized with different audio
- // parameters. Then, invoke MaybeStartSink() to restart everything again.
- sink_->Stop();
- sink_started_ = false;
- sink_ =
- AudioDeviceFactory::NewOutputDevice(source_render_frame_id_, session_id_,
- output_device_id_, security_origin_);
- int frames_per_buffer = sink_->GetOutputParameters().frames_per_buffer();
- sink_params_ = source_params_;
- sink_params_.set_frames_per_buffer(WebRtcAudioRenderer::GetOptimalBufferSize(
- source_params_.sample_rate(), frames_per_buffer));
- MaybeStartSink();
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/media/webrtc_local_audio_renderer.h b/chromium/content/renderer/media/webrtc_local_audio_renderer.h
deleted file mode 100644
index d33c3849750..00000000000
--- a/chromium/content/renderer/media/webrtc_local_audio_renderer.h
+++ /dev/null
@@ -1,183 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_LOCAL_AUDIO_RENDERER_H_
-#define CONTENT_RENDERER_MEDIA_WEBRTC_LOCAL_AUDIO_RENDERER_H_
-
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/thread_checker.h"
-#include "content/common/content_export.h"
-#include "content/public/renderer/media_stream_audio_renderer.h"
-#include "content/public/renderer/media_stream_audio_sink.h"
-#include "content/renderer/media/webrtc_audio_device_impl.h"
-#include "content/renderer/media/webrtc_local_audio_track.h"
-#include "media/base/output_device.h"
-#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
-
-namespace media {
-class AudioBus;
-class AudioShifter;
-class AudioOutputDevice;
-class AudioParameters;
-}
-
-namespace content {
-
-class WebRtcAudioCapturer;
-
-// WebRtcLocalAudioRenderer is a MediaStreamAudioRenderer designed for rendering
-// local audio media stream tracks,
-// http://dev.w3.org/2011/webrtc/editor/getusermedia.html#mediastreamtrack
-// It also implements media::AudioRendererSink::RenderCallback to render audio
-// data provided from a WebRtcLocalAudioTrack source.
-// When the audio layer in the browser process asks for data to render, this
-// class provides the data by implementing the MediaStreamAudioSink
-// interface, i.e., we are a sink seen from the WebRtcAudioCapturer perspective.
-// TODO(henrika): improve by using similar principles as in
-// MediaStreamVideoRendererSink which register itself to the video track when
-// the provider is started and deregisters itself when it is stopped. Tracking
-// this at http://crbug.com/164813.
-class CONTENT_EXPORT WebRtcLocalAudioRenderer
- : NON_EXPORTED_BASE(public MediaStreamAudioRenderer),
- NON_EXPORTED_BASE(public MediaStreamAudioSink),
- NON_EXPORTED_BASE(public media::AudioRendererSink::RenderCallback),
- NON_EXPORTED_BASE(public media::OutputDevice) {
- public:
- // Creates a local renderer and registers a capturing |source| object.
- // The |source| is owned by the WebRtcAudioDeviceImpl.
- // Called on the main thread.
- WebRtcLocalAudioRenderer(const blink::WebMediaStreamTrack& audio_track,
- int source_render_frame_id,
- int session_id,
- const std::string& device_id,
- const url::Origin& security_origin);
-
- // MediaStreamAudioRenderer implementation.
- // Called on the main thread.
- void Start() override;
- void Stop() override;
- void Play() override;
- void Pause() override;
- void SetVolume(float volume) override;
- media::OutputDevice* GetOutputDevice() override;
- base::TimeDelta GetCurrentRenderTime() const override;
- bool IsLocalRenderer() const override;
-
- // media::OutputDevice implementation
- void SwitchOutputDevice(const std::string& device_id,
- const url::Origin& security_origin,
- const media::SwitchOutputDeviceCB& callback) override;
- media::AudioParameters GetOutputParameters() override;
- media::OutputDeviceStatus GetDeviceStatus() override;
-
- const base::TimeDelta& total_render_time() const {
- return total_render_time_;
- }
-
- protected:
- ~WebRtcLocalAudioRenderer() override;
-
- private:
- // MediaStreamAudioSink implementation.
-
- // Called on the AudioInputDevice worker thread.
- void OnData(const media::AudioBus& audio_bus,
- base::TimeTicks estimated_capture_time) override;
-
- // Called on the AudioInputDevice worker thread.
- void OnSetFormat(const media::AudioParameters& params) override;
-
- // media::AudioRendererSink::RenderCallback implementation.
- // Render() is called on the AudioOutputDevice thread and OnRenderError()
- // on the IO thread.
- int Render(media::AudioBus* audio_bus,
- uint32_t audio_delay_milliseconds,
- uint32_t frames_skipped) override;
- void OnRenderError() override;
-
- // Initializes and starts the |sink_| if
- // we have received valid |source_params_| &&
- // |playing_| has been set to true &&
- // |volume_| is not zero.
- void MaybeStartSink();
-
- // Sets new |source_params_| and then re-initializes and restarts |sink_|.
- void ReconfigureSink(const media::AudioParameters& params);
-
- // The audio track which provides data to render. Given that this class
- // implements local loopback, the audio track is getting data from a capture
- // instance like a selected microphone and forwards the recorded data to its
- // sinks. The recorded data is stored in a FIFO and consumed
- // by this class when the sink asks for new data.
- // This class is calling MediaStreamAudioSink::AddToAudioTrack() and
- // MediaStreamAudioSink::RemoveFromAudioTrack() to connect and disconnect
- // with the audio track.
- blink::WebMediaStreamTrack audio_track_;
-
- // The render view and frame in which the audio is rendered into |sink_|.
- const int source_render_frame_id_;
- const int session_id_;
-
- // MessageLoop associated with the single thread that performs all control
- // tasks. Set to the MessageLoop that invoked the ctor.
- const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-
- // The sink (destination) for rendered audio.
- scoped_refptr<media::AudioOutputDevice> sink_;
-
- // This does all the synchronization/resampling/smoothing.
- scoped_ptr<media::AudioShifter> audio_shifter_;
-
- // Stores last time a render callback was received. The time difference
- // between a new time stamp and this value can be used to derive the
- // total render time.
- base::TimeTicks last_render_time_;
-
- // Keeps track of total time audio has been rendered.
- base::TimeDelta total_render_time_;
-
- // The audio parameters of the capture source.
- // Must only be touched on the main thread.
- media::AudioParameters source_params_;
-
- // The audio parameters used by the sink.
- // Must only be touched on the main thread.
- media::AudioParameters sink_params_;
-
- // Set when playing, cleared when paused.
- bool playing_;
-
- // Protects |audio_shifter_|, |playing_|, |last_render_time_|,
- // |total_render_time_| and |volume_|.
- mutable base::Lock thread_lock_;
-
- // The preferred device id of the output device or empty for the default
- // output device.
- std::string output_device_id_;
- url::Origin security_origin_;
-
- // Cache value for the volume.
- float volume_;
-
- // Flag to indicate whether |sink_| has been started yet.
- bool sink_started_;
-
- // Used to DCHECK that some methods are called on the capture audio thread.
- base::ThreadChecker capture_thread_checker_;
-
- DISALLOW_COPY_AND_ASSIGN(WebRtcLocalAudioRenderer);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEDIA_WEBRTC_LOCAL_AUDIO_RENDERER_H_
diff --git a/chromium/content/renderer/media/webrtc_local_audio_source_provider.h b/chromium/content/renderer/media/webrtc_local_audio_source_provider.h
index 9a9cc8e50aa..d9432805b40 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_source_provider.h
+++ b/chromium/content/renderer/media/webrtc_local_audio_source_provider.h
@@ -7,10 +7,10 @@
#include <stddef.h>
+#include <memory>
#include <vector>
#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
#include "base/time/time.h"
@@ -86,9 +86,9 @@ class CONTENT_EXPORT WebRtcLocalAudioSourceProvider
// Used to DCHECK that some methods are called on the capture audio thread.
base::ThreadChecker capture_thread_checker_;
- scoped_ptr<media::AudioConverter> audio_converter_;
- scoped_ptr<media::AudioFifo> fifo_;
- scoped_ptr<media::AudioBus> output_wrapper_;
+ std::unique_ptr<media::AudioConverter> audio_converter_;
+ std::unique_ptr<media::AudioFifo> fifo_;
+ std::unique_ptr<media::AudioBus> output_wrapper_;
bool is_enabled_;
media::AudioParameters source_params_;
media::AudioParameters sink_params_;
diff --git a/chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc b/chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc
index 28acddd2d4f..b6e9d5ad06d 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc
+++ b/chromium/content/renderer/media/webrtc_local_audio_source_provider_unittest.cc
@@ -5,16 +5,14 @@
#include <stddef.h>
#include "base/logging.h"
-#include "base/strings/utf_string_conversions.h"
-#include "content/renderer/media/mock_media_constraint_factory.h"
#include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
-#include "content/renderer/media/webrtc_audio_capturer.h"
#include "content/renderer/media/webrtc_local_audio_source_provider.h"
#include "content/renderer/media/webrtc_local_audio_track.h"
#include "media/audio/audio_parameters.h"
#include "media/base/audio_bus.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebMediaStreamTrack.h"
+#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/web/WebHeap.h"
namespace content {
@@ -29,19 +27,14 @@ class WebRtcLocalAudioSourceProviderTest : public testing::Test {
media::CHANNEL_LAYOUT_STEREO, 44100, 16,
WebRtcLocalAudioSourceProvider::kWebAudioRenderBufferSize);
sink_bus_ = media::AudioBus::Create(sink_params_);
- MockMediaConstraintFactory constraint_factory;
- scoped_refptr<WebRtcAudioCapturer> capturer(
- WebRtcAudioCapturer::CreateCapturer(
- -1, StreamDeviceInfo(),
- constraint_factory.CreateWebMediaConstraints(), NULL, NULL));
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
- scoped_ptr<WebRtcLocalAudioTrack> native_track(
- new WebRtcLocalAudioTrack(adapter.get(), capturer, NULL));
+ std::unique_ptr<WebRtcLocalAudioTrack> native_track(
+ new WebRtcLocalAudioTrack(adapter.get()));
blink::WebMediaStreamSource audio_source;
- audio_source.initialize(base::UTF8ToUTF16("dummy_source_id"),
+ audio_source.initialize(blink::WebString::fromUTF8("dummy_source_id"),
blink::WebMediaStreamSource::TypeAudio,
- base::UTF8ToUTF16("dummy_source_name"),
+ blink::WebString::fromUTF8("dummy_source_name"),
false /* remote */, true /* readonly */);
blink_track_.initialize(blink::WebString::fromUTF8("audio_track"),
audio_source);
@@ -59,9 +52,9 @@ class WebRtcLocalAudioSourceProviderTest : public testing::Test {
media::AudioParameters source_params_;
media::AudioParameters sink_params_;
- scoped_ptr<media::AudioBus> sink_bus_;
+ std::unique_ptr<media::AudioBus> sink_bus_;
blink::WebMediaStreamTrack blink_track_;
- scoped_ptr<WebRtcLocalAudioSourceProvider> source_provider_;
+ std::unique_ptr<WebRtcLocalAudioSourceProvider> source_provider_;
};
TEST_F(WebRtcLocalAudioSourceProviderTest, VerifyDataFlow) {
@@ -78,7 +71,7 @@ TEST_F(WebRtcLocalAudioSourceProviderTest, VerifyDataFlow) {
EXPECT_EQ(0, sink_bus_->channel(0)[0]);
// Create a source AudioBus with channel data filled with non-zero values.
- const scoped_ptr<media::AudioBus> source_bus =
+ const std::unique_ptr<media::AudioBus> source_bus =
media::AudioBus::Create(source_params_);
std::fill(source_bus->channel(0),
source_bus->channel(0) + source_bus->frames(),
diff --git a/chromium/content/renderer/media/webrtc_local_audio_track.cc b/chromium/content/renderer/media/webrtc_local_audio_track.cc
index cb48668eaec..53c55b2d0d4 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_track.cc
+++ b/chromium/content/renderer/media/webrtc_local_audio_track.cc
@@ -13,78 +13,49 @@
#include "content/renderer/media/media_stream_audio_processor.h"
#include "content/renderer/media/media_stream_audio_sink_owner.h"
#include "content/renderer/media/media_stream_audio_track_sink.h"
-#include "content/renderer/media/webaudio_capturer_source.h"
#include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
-#include "content/renderer/media/webrtc_audio_capturer.h"
namespace content {
WebRtcLocalAudioTrack::WebRtcLocalAudioTrack(
- WebRtcLocalAudioTrackAdapter* adapter,
- const scoped_refptr<WebRtcAudioCapturer>& capturer,
- WebAudioCapturerSource* webaudio_source)
- : MediaStreamAudioTrack(true),
- adapter_(adapter),
- capturer_(capturer),
- webaudio_source_(webaudio_source) {
- DCHECK(capturer.get() || webaudio_source);
+ scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter)
+ : MediaStreamAudioTrack(true), adapter_(std::move(adapter)) {
signal_thread_checker_.DetachFromThread();
+ DVLOG(1) << "WebRtcLocalAudioTrack::WebRtcLocalAudioTrack()";
adapter_->Initialize(this);
-
- DVLOG(1) << "WebRtcLocalAudioTrack::WebRtcLocalAudioTrack()";
}
WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack() {
DCHECK(main_render_thread_checker_.CalledOnValidThread());
DVLOG(1) << "WebRtcLocalAudioTrack::~WebRtcLocalAudioTrack()";
- // Users might not call Stop() on the track.
- Stop();
+ // Ensure the track is stopped.
+ MediaStreamAudioTrack::Stop();
}
media::AudioParameters WebRtcLocalAudioTrack::GetOutputFormat() const {
DCHECK(main_render_thread_checker_.CalledOnValidThread());
- if (webaudio_source_.get()) {
- return media::AudioParameters();
- } else {
- return capturer_->GetOutputFormat();
- }
+ base::AutoLock auto_lock(lock_);
+ return audio_parameters_;
}
void WebRtcLocalAudioTrack::Capture(const media::AudioBus& audio_bus,
- base::TimeTicks estimated_capture_time,
- bool force_report_nonzero_energy) {
+ base::TimeTicks estimated_capture_time) {
DCHECK(capture_thread_checker_.CalledOnValidThread());
DCHECK(!estimated_capture_time.is_null());
- // Calculate the signal level regardless of whether the track is disabled or
- // enabled. If |force_report_nonzero_energy| is true, |audio_bus| contains
- // post-processed data that may be all zeros even though the signal contained
- // energy before the processing. In this case, report nonzero energy even if
- // the energy of the data in |audio_bus| is zero.
- const float minimum_signal_level =
- force_report_nonzero_energy ? 1.0f / std::numeric_limits<int16_t>::max()
- : 0.0f;
- const float signal_level = std::max(
- minimum_signal_level,
- std::min(1.0f, level_calculator_->Calculate(audio_bus)));
- const int signal_level_as_pcm16 =
- static_cast<int>(signal_level * std::numeric_limits<int16_t>::max() +
- 0.5f /* rounding to nearest int */);
- adapter_->SetSignalLevel(signal_level_as_pcm16);
-
- scoped_refptr<WebRtcAudioCapturer> capturer;
SinkList::ItemList sinks;
SinkList::ItemList sinks_to_notify_format;
{
base::AutoLock auto_lock(lock_);
- capturer = capturer_;
sinks = sinks_.Items();
sinks_.RetrieveAndClearTags(&sinks_to_notify_format);
}
// Notify the tracks on when the format changes. This will do nothing if
- // |sinks_to_notify_format| is empty.
+ // |sinks_to_notify_format| is empty. Note that accessing |audio_parameters_|
+ // without holding the |lock_| is valid since |audio_parameters_| is only
+ // changed on the current thread.
for (const auto& sink : sinks_to_notify_format)
sink->OnSetFormat(audio_parameters_);
@@ -105,22 +76,20 @@ void WebRtcLocalAudioTrack::OnSetFormat(
capture_thread_checker_.DetachFromThread();
DCHECK(capture_thread_checker_.CalledOnValidThread());
- audio_parameters_ = params;
- level_calculator_.reset(new MediaStreamAudioLevelCalculator());
-
base::AutoLock auto_lock(lock_);
+ audio_parameters_ = params;
// Remember to notify all sinks of the new format.
sinks_.TagAll();
}
+void WebRtcLocalAudioTrack::SetLevel(
+ scoped_refptr<MediaStreamAudioLevelCalculator::Level> level) {
+ adapter_->SetLevel(std::move(level));
+}
+
void WebRtcLocalAudioTrack::SetAudioProcessor(
- const scoped_refptr<MediaStreamAudioProcessor>& processor) {
- // if the |processor| does not have audio processing, which can happen if
- // kDisableAudioTrackProcessing is set set or all the constraints in
- // the |processor| are turned off. In such case, we pass NULL to the
- // adapter to indicate that no stats can be gotten from the processor.
- adapter_->SetAudioProcessor(processor->has_audio_processing() ?
- processor : NULL);
+ scoped_refptr<MediaStreamAudioProcessor> processor) {
+ adapter_->SetAudioProcessor(std::move(processor));
}
void WebRtcLocalAudioTrack::AddSink(MediaStreamAudioSink* sink) {
@@ -166,63 +135,22 @@ void WebRtcLocalAudioTrack::RemoveSink(MediaStreamAudioSink* sink) {
removed_item->Reset();
}
-void WebRtcLocalAudioTrack::Start() {
- DCHECK(main_render_thread_checker_.CalledOnValidThread());
- DVLOG(1) << "WebRtcLocalAudioTrack::Start()";
- if (webaudio_source_.get()) {
- // If the track is hooking up with WebAudio, do NOT add the track to the
- // capturer as its sink otherwise two streams in different clock will be
- // pushed through the same track.
- webaudio_source_->Start(this);
- } else if (capturer_.get()) {
- capturer_->AddTrack(this);
- }
-
- SinkList::ItemList sinks;
- {
- base::AutoLock auto_lock(lock_);
- sinks = sinks_.Items();
- }
- for (SinkList::ItemList::const_iterator it = sinks.begin();
- it != sinks.end();
- ++it) {
- (*it)->OnReadyStateChanged(blink::WebMediaStreamSource::ReadyStateLive);
- }
-}
-
void WebRtcLocalAudioTrack::SetEnabled(bool enabled) {
DCHECK(main_render_thread_checker_.CalledOnValidThread());
if (adapter_.get())
adapter_->set_enabled(enabled);
}
-void WebRtcLocalAudioTrack::Stop() {
+void WebRtcLocalAudioTrack::OnStop() {
DCHECK(main_render_thread_checker_.CalledOnValidThread());
- DVLOG(1) << "WebRtcLocalAudioTrack::Stop()";
- if (!capturer_.get() && !webaudio_source_.get())
- return;
-
- if (webaudio_source_.get()) {
- // Called Stop() on the |webaudio_source_| explicitly so that
- // |webaudio_source_| won't push more data to the track anymore.
- // Also note that the track is not registered as a sink to the |capturer_|
- // in such case and no need to call RemoveTrack().
- webaudio_source_->Stop();
- } else {
- // It is necessary to call RemoveTrack on the |capturer_| to avoid getting
- // audio callback after Stop().
- capturer_->RemoveTrack(this);
- }
+ DVLOG(1) << "WebRtcLocalAudioTrack::OnStop()";
- // Protect the pointers using the lock when accessing |sinks_| and
- // setting the |capturer_| to NULL.
+ // Protect the pointers using the lock when accessing |sinks_|.
SinkList::ItemList sinks;
{
base::AutoLock auto_lock(lock_);
sinks = sinks_.Items();
sinks_.Clear();
- webaudio_source_ = NULL;
- capturer_ = NULL;
}
for (SinkList::ItemList::const_iterator it = sinks.begin();
diff --git a/chromium/content/renderer/media/webrtc_local_audio_track.h b/chromium/content/renderer/media/webrtc_local_audio_track.h
index 2eafbd160ee..d3d28d5143f 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_track.h
+++ b/chromium/content/renderer/media/webrtc_local_audio_track.h
@@ -10,11 +10,11 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
#include "content/renderer/media/media_stream_audio_track.h"
#include "content/renderer/media/tagged_list.h"
+#include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
#include "media/audio/audio_parameters.h"
namespace media {
@@ -28,22 +28,14 @@ class MediaStreamAudioProcessor;
class MediaStreamAudioSink;
class MediaStreamAudioSinkOwner;
class MediaStreamAudioTrackSink;
-class WebAudioCapturerSource;
-class WebRtcAudioCapturer;
-class WebRtcLocalAudioTrackAdapter;
-
-// A WebRtcLocalAudioTrack instance contains the implementations of
-// MediaStreamTrackExtraData.
-// When an instance is created, it will register itself as a track to the
-// WebRtcAudioCapturer to get the captured data, and forward the data to
-// its |sinks_|. The data flow can be stopped by disabling the audio track.
-// TODO(tommi): Rename to MediaStreamLocalAudioTrack.
+
+// A WebRtcLocalAudioTrack manages thread-safe connects/disconnects to sinks,
+// and the delivery of audio data from the source to the sinks.
class CONTENT_EXPORT WebRtcLocalAudioTrack
: NON_EXPORTED_BASE(public MediaStreamAudioTrack) {
public:
- WebRtcLocalAudioTrack(WebRtcLocalAudioTrackAdapter* adapter,
- const scoped_refptr<WebRtcAudioCapturer>& capturer,
- WebAudioCapturerSource* webaudio_source);
+ explicit WebRtcLocalAudioTrack(
+ scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter);
~WebRtcLocalAudioTrack() override;
@@ -56,56 +48,39 @@ class CONTENT_EXPORT WebRtcLocalAudioTrack
// Called on the main render thread.
void RemoveSink(MediaStreamAudioSink* sink) override;
- // Starts the local audio track. Called on the main render thread and
- // should be called only once when audio track is created.
- void Start();
-
// Overrides for MediaStreamTrack.
-
void SetEnabled(bool enabled) override;
-
- // Stops the local audio track. Called on the main render thread and
- // should be called only once when audio track going away.
- void Stop() override;
-
webrtc::AudioTrackInterface* GetAudioAdapter() override;
-
- // Returns the output format of the capture source. May return an invalid
- // AudioParameters if the format is not yet available.
- // Called on the main render thread.
media::AudioParameters GetOutputFormat() const override;
// Method called by the capturer to deliver the capture data.
// Called on the capture audio thread.
void Capture(const media::AudioBus& audio_bus,
- base::TimeTicks estimated_capture_time,
- bool force_report_nonzero_energy);
+ base::TimeTicks estimated_capture_time);
// Method called by the capturer to set the audio parameters used by source
// of the capture data..
// Called on the capture audio thread.
void OnSetFormat(const media::AudioParameters& params);
- // Method called by the capturer to set the processor that applies signal
- // processing on the data of the track.
- // Called on the capture audio thread.
- void SetAudioProcessor(
- const scoped_refptr<MediaStreamAudioProcessor>& processor);
+ // Called by the capturer before the audio data flow begins to set the object
+ // that provides shared access to the current audio signal level.
+ void SetLevel(scoped_refptr<MediaStreamAudioLevelCalculator::Level> level);
+
+ // Called by the capturer before the audio data flow begins to provide a
+ // reference to the audio processor so that the track can query stats from it.
+ void SetAudioProcessor(scoped_refptr<MediaStreamAudioProcessor> processor);
private:
typedef TaggedList<MediaStreamAudioTrackSink> SinkList;
+ // MediaStreamAudioTrack override.
+ void OnStop() final;
+
// All usage of libjingle is through this adapter. The adapter holds
// a pointer to this object, but no reference.
const scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_;
- // The provider of captured data to render.
- scoped_refptr<WebRtcAudioCapturer> capturer_;
-
- // The source of the audio track which is used by WebAudio, which provides
- // data to the audio track when hooking up with WebAudio.
- scoped_refptr<WebAudioCapturerSource> webaudio_source_;
-
// A tagged list of sinks that the audio data is fed to. Tags
// indicate tracks that need to be notified that the audio format
// has changed.
@@ -121,13 +96,8 @@ class CONTENT_EXPORT WebRtcLocalAudioTrack
mutable base::Lock lock_;
// Audio parameters of the audio capture stream.
- // Accessed on only the audio capture thread.
media::AudioParameters audio_parameters_;
- // Used to calculate the signal level that shows in the UI.
- // Accessed on only the audio thread.
- scoped_ptr<MediaStreamAudioLevelCalculator> level_calculator_;
-
DISALLOW_COPY_AND_ASSIGN(WebRtcLocalAudioTrack);
};
diff --git a/chromium/content/renderer/media/webrtc_local_audio_track_unittest.cc b/chromium/content/renderer/media/webrtc_local_audio_track_unittest.cc
index 60123b0b937..16a6b8db127 100644
--- a/chromium/content/renderer/media/webrtc_local_audio_track_unittest.cc
+++ b/chromium/content/renderer/media/webrtc_local_audio_track_unittest.cc
@@ -8,7 +8,7 @@
#include "build/build_config.h"
#include "content/public/renderer/media_stream_audio_sink.h"
#include "content/renderer/media/media_stream_audio_source.h"
-#include "content/renderer/media/mock_media_constraint_factory.h"
+#include "content/renderer/media/mock_constraint_factory.h"
#include "content/renderer/media/webrtc/webrtc_local_audio_track_adapter.h"
#include "content/renderer/media/webrtc_audio_capturer.h"
#include "content/renderer/media/webrtc_local_audio_track.h"
@@ -19,7 +19,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebMediaConstraints.h"
#include "third_party/WebKit/public/web/WebHeap.h"
-#include "third_party/libjingle/source/talk/app/webrtc/mediastreaminterface.h"
+#include "third_party/webrtc/api/mediastreaminterface.h"
using ::testing::_;
using ::testing::AnyNumber;
@@ -79,7 +79,7 @@ class FakeAudioThread : public base::PlatformThread::Delegate {
}
private:
- scoped_ptr<media::AudioBus> audio_bus_;
+ std::unique_ptr<media::AudioBus> audio_bus_;
WebRtcAudioCapturer* capturer_;
base::PlatformThreadHandle thread_;
base::WaitableEvent closure_;
@@ -95,7 +95,7 @@ class MockCapturerSource : public media::AudioCapturerSource {
int session_id));
MOCK_METHOD0(OnStart, void());
MOCK_METHOD0(OnStop, void());
- MOCK_METHOD1(SetVolume, void(double volume));
+ void SetVolume(double volume) final {}
MOCK_METHOD1(SetAutomaticGainControl, void(bool enable));
void Initialize(const media::AudioParameters& params,
@@ -120,7 +120,7 @@ class MockCapturerSource : public media::AudioCapturerSource {
~MockCapturerSource() override {}
private:
- scoped_ptr<FakeAudioThread> audio_thread_;
+ std::unique_ptr<FakeAudioThread> audio_thread_;
WebRtcAudioCapturer* capturer_;
media::AudioParameters params_;
};
@@ -156,7 +156,7 @@ class WebRtcLocalAudioTrackTest : public ::testing::Test {
void SetUp() override {
params_.Reset(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::CHANNEL_LAYOUT_STEREO, 48000, 16, 480);
- MockMediaConstraintFactory constraint_factory;
+ MockConstraintFactory constraint_factory;
blink_source_.initialize("dummy", blink::WebMediaStreamSource::TypeAudio,
"dummy",
false /* remote */, true /* readonly */);
@@ -165,12 +165,16 @@ class WebRtcLocalAudioTrackTest : public ::testing::Test {
StreamDeviceInfo device(MEDIA_DEVICE_AUDIO_CAPTURE,
std::string(), std::string());
- capturer_ = WebRtcAudioCapturer::CreateCapturer(
- -1, device, constraint_factory.CreateWebMediaConstraints(), NULL,
- audio_source);
- audio_source->SetAudioCapturer(capturer_.get());
- capturer_source_ = new MockCapturerSource(capturer_.get());
- EXPECT_CALL(*capturer_source_.get(), OnInitialize(_, capturer_.get(), -1))
+ {
+ std::unique_ptr<WebRtcAudioCapturer> capturer =
+ WebRtcAudioCapturer::CreateCapturer(
+ -1, device, constraint_factory.CreateWebMediaConstraints(),
+ nullptr, audio_source);
+ capturer_ = capturer.get();
+ audio_source->SetAudioCapturer(std::move(capturer));
+ }
+ capturer_source_ = new MockCapturerSource(capturer_);
+ EXPECT_CALL(*capturer_source_.get(), OnInitialize(_, capturer_, -1))
.WillOnce(Return());
EXPECT_CALL(*capturer_source_.get(), SetAutomaticGainControl(true));
EXPECT_CALL(*capturer_source_.get(), OnStart());
@@ -184,8 +188,8 @@ class WebRtcLocalAudioTrackTest : public ::testing::Test {
media::AudioParameters params_;
blink::WebMediaStreamSource blink_source_;
+ WebRtcAudioCapturer* capturer_; // Owned by |blink_source_|.
scoped_refptr<MockCapturerSource> capturer_source_;
- scoped_refptr<WebRtcAudioCapturer> capturer_;
};
// Creates a capturer and audio track, fakes its audio thread, and
@@ -195,12 +199,17 @@ class WebRtcLocalAudioTrackTest : public ::testing::Test {
TEST_F(WebRtcLocalAudioTrackTest, ConnectAndDisconnectOneSink) {
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
- scoped_ptr<WebRtcLocalAudioTrack> track(
- new WebRtcLocalAudioTrack(adapter.get(), capturer_, NULL));
- track->Start();
+ std::unique_ptr<WebRtcLocalAudioTrack> track(
+ new WebRtcLocalAudioTrack(adapter.get()));
+ track->Start(
+ base::Bind(&MediaStreamAudioSource::StopAudioDeliveryTo,
+ MediaStreamAudioSource::From(blink_source_)->GetWeakPtr(),
+ track.get()));
+ capturer_->AddTrack(track.get());
EXPECT_TRUE(track->GetAudioAdapter()->enabled());
- scoped_ptr<MockMediaStreamAudioSink> sink(new MockMediaStreamAudioSink());
+ std::unique_ptr<MockMediaStreamAudioSink> sink(
+ new MockMediaStreamAudioSink());
base::WaitableEvent event(false, false);
EXPECT_CALL(*sink, FormatIsSet());
EXPECT_CALL(*sink,
@@ -225,13 +234,18 @@ TEST_F(WebRtcLocalAudioTrackTest, DISABLED_DisableEnableAudioTrack) {
EXPECT_CALL(*capturer_source_.get(), OnStart());
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
- scoped_ptr<WebRtcLocalAudioTrack> track(
- new WebRtcLocalAudioTrack(adapter.get(), capturer_, NULL));
- track->Start();
+ std::unique_ptr<WebRtcLocalAudioTrack> track(
+ new WebRtcLocalAudioTrack(adapter.get()));
+ track->Start(
+ base::Bind(&MediaStreamAudioSource::StopAudioDeliveryTo,
+ MediaStreamAudioSource::From(blink_source_)->GetWeakPtr(),
+ track.get()));
+ capturer_->AddTrack(track.get());
EXPECT_TRUE(track->GetAudioAdapter()->enabled());
EXPECT_TRUE(track->GetAudioAdapter()->set_enabled(false));
- scoped_ptr<MockMediaStreamAudioSink> sink(new MockMediaStreamAudioSink());
- const media::AudioParameters params = capturer_->source_audio_parameters();
+ std::unique_ptr<MockMediaStreamAudioSink> sink(
+ new MockMediaStreamAudioSink());
+ const media::AudioParameters params = capturer_->GetInputFormat();
base::WaitableEvent event(false, false);
EXPECT_CALL(*sink, FormatIsSet()).Times(1);
EXPECT_CALL(*sink, CaptureData()).Times(0);
@@ -258,12 +272,17 @@ TEST_F(WebRtcLocalAudioTrackTest, DISABLED_DisableEnableAudioTrack) {
TEST_F(WebRtcLocalAudioTrackTest, DISABLED_MultipleAudioTracks) {
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_1(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
- scoped_ptr<WebRtcLocalAudioTrack> track_1(
- new WebRtcLocalAudioTrack(adapter_1.get(), capturer_, NULL));
- track_1->Start();
+ std::unique_ptr<WebRtcLocalAudioTrack> track_1(
+ new WebRtcLocalAudioTrack(adapter_1.get()));
+ track_1->Start(
+ base::Bind(&MediaStreamAudioSource::StopAudioDeliveryTo,
+ MediaStreamAudioSource::From(blink_source_)->GetWeakPtr(),
+ track_1.get()));
+ capturer_->AddTrack(track_1.get());
EXPECT_TRUE(track_1->GetAudioAdapter()->enabled());
- scoped_ptr<MockMediaStreamAudioSink> sink_1(new MockMediaStreamAudioSink());
- const media::AudioParameters params = capturer_->source_audio_parameters();
+ std::unique_ptr<MockMediaStreamAudioSink> sink_1(
+ new MockMediaStreamAudioSink());
+ const media::AudioParameters params = capturer_->GetInputFormat();
base::WaitableEvent event_1(false, false);
EXPECT_CALL(*sink_1, FormatIsSet()).WillOnce(Return());
EXPECT_CALL(*sink_1, CaptureData()).Times(AtLeast(1))
@@ -275,16 +294,21 @@ TEST_F(WebRtcLocalAudioTrackTest, DISABLED_MultipleAudioTracks) {
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_2(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
- scoped_ptr<WebRtcLocalAudioTrack> track_2(
- new WebRtcLocalAudioTrack(adapter_2.get(), capturer_, NULL));
- track_2->Start();
+ std::unique_ptr<WebRtcLocalAudioTrack> track_2(
+ new WebRtcLocalAudioTrack(adapter_2.get()));
+ track_2->Start(
+ base::Bind(&MediaStreamAudioSource::StopAudioDeliveryTo,
+ MediaStreamAudioSource::From(blink_source_)->GetWeakPtr(),
+ track_2.get()));
+ capturer_->AddTrack(track_2.get());
EXPECT_TRUE(track_2->GetAudioAdapter()->enabled());
// Verify both |sink_1| and |sink_2| get data.
event_1.Reset();
base::WaitableEvent event_2(false, false);
- scoped_ptr<MockMediaStreamAudioSink> sink_2(new MockMediaStreamAudioSink());
+ std::unique_ptr<MockMediaStreamAudioSink> sink_2(
+ new MockMediaStreamAudioSink());
EXPECT_CALL(*sink_2, FormatIsSet()).WillOnce(Return());
EXPECT_CALL(*sink_1, CaptureData()).Times(AtLeast(1))
.WillRepeatedly(SignalEvent(&event_1));
@@ -314,9 +338,13 @@ TEST_F(WebRtcLocalAudioTrackTest, DISABLED_MultipleAudioTracks) {
TEST_F(WebRtcLocalAudioTrackTest, StartOneAudioTrack) {
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
- scoped_ptr<WebRtcLocalAudioTrack> track(
- new WebRtcLocalAudioTrack(adapter.get(), capturer_, NULL));
- track->Start();
+ std::unique_ptr<WebRtcLocalAudioTrack> track(
+ new WebRtcLocalAudioTrack(adapter.get()));
+ track->Start(
+ base::Bind(&MediaStreamAudioSource::StopAudioDeliveryTo,
+ MediaStreamAudioSource::From(blink_source_)->GetWeakPtr(),
+ track.get()));
+ capturer_->AddTrack(track.get());
// When the track goes away, it will automatically stop the
// |capturer_source_|.
@@ -330,15 +358,23 @@ TEST_F(WebRtcLocalAudioTrackTest, StartOneAudioTrack) {
TEST_F(WebRtcLocalAudioTrackTest, StartTwoAudioTracks) {
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter1(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
- scoped_ptr<WebRtcLocalAudioTrack> track1(
- new WebRtcLocalAudioTrack(adapter1.get(), capturer_, NULL));
- track1->Start();
+ std::unique_ptr<WebRtcLocalAudioTrack> track1(
+ new WebRtcLocalAudioTrack(adapter1.get()));
+ track1->Start(
+ base::Bind(&MediaStreamAudioSource::StopAudioDeliveryTo,
+ MediaStreamAudioSource::From(blink_source_)->GetWeakPtr(),
+ track1.get()));
+ capturer_->AddTrack(track1.get());
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter2(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
- scoped_ptr<WebRtcLocalAudioTrack> track2(
- new WebRtcLocalAudioTrack(adapter2.get(), capturer_, NULL));
- track2->Start();
+ std::unique_ptr<WebRtcLocalAudioTrack> track2(
+ new WebRtcLocalAudioTrack(adapter2.get()));
+ track2->Start(
+ base::Bind(&MediaStreamAudioSource::StopAudioDeliveryTo,
+ MediaStreamAudioSource::From(blink_source_)->GetWeakPtr(),
+ track2.get()));
+ capturer_->AddTrack(track2.get());
track1->Stop();
// When the last track is stopped, it will automatically stop the
@@ -353,12 +389,17 @@ TEST_F(WebRtcLocalAudioTrackTest, StartAndStopAudioTracks) {
base::WaitableEvent event(false, false);
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_1(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
- scoped_ptr<WebRtcLocalAudioTrack> track_1(
- new WebRtcLocalAudioTrack(adapter_1.get(), capturer_, NULL));
- track_1->Start();
+ std::unique_ptr<WebRtcLocalAudioTrack> track_1(
+ new WebRtcLocalAudioTrack(adapter_1.get()));
+ track_1->Start(
+ base::Bind(&MediaStreamAudioSource::StopAudioDeliveryTo,
+ MediaStreamAudioSource::From(blink_source_)->GetWeakPtr(),
+ track_1.get()));
+ capturer_->AddTrack(track_1.get());
// Verify the data flow by connecting the sink to |track_1|.
- scoped_ptr<MockMediaStreamAudioSink> sink(new MockMediaStreamAudioSink());
+ std::unique_ptr<MockMediaStreamAudioSink> sink(
+ new MockMediaStreamAudioSink());
event.Reset();
EXPECT_CALL(*sink, FormatIsSet()).WillOnce(SignalEvent(&event));
EXPECT_CALL(*sink, CaptureData())
@@ -371,9 +412,13 @@ TEST_F(WebRtcLocalAudioTrackTest, StartAndStopAudioTracks) {
EXPECT_CALL(*capturer_source_.get(), OnStart()).Times(0);
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_2(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
- scoped_ptr<WebRtcLocalAudioTrack> track_2(
- new WebRtcLocalAudioTrack(adapter_2.get(), capturer_, NULL));
- track_2->Start();
+ std::unique_ptr<WebRtcLocalAudioTrack> track_2(
+ new WebRtcLocalAudioTrack(adapter_2.get()));
+ track_2->Start(
+ base::Bind(&MediaStreamAudioSource::StopAudioDeliveryTo,
+ MediaStreamAudioSource::From(blink_source_)->GetWeakPtr(),
+ track_2.get()));
+ capturer_->AddTrack(track_2.get());
// Stop the capturer will clear up the track lists in the capturer.
EXPECT_CALL(*capturer_source_.get(), OnStop());
@@ -403,22 +448,27 @@ TEST_F(WebRtcLocalAudioTrackTest, MAYBE_ConnectTracksToDifferentCapturers) {
// Setup the first audio track and start it.
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_1(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
- scoped_ptr<WebRtcLocalAudioTrack> track_1(
- new WebRtcLocalAudioTrack(adapter_1.get(), capturer_, NULL));
- track_1->Start();
+ std::unique_ptr<WebRtcLocalAudioTrack> track_1(
+ new WebRtcLocalAudioTrack(adapter_1.get()));
+ track_1->Start(
+ base::Bind(&MediaStreamAudioSource::StopAudioDeliveryTo,
+ MediaStreamAudioSource::From(blink_source_)->GetWeakPtr(),
+ track_1.get()));
+ capturer_->AddTrack(track_1.get());
// Verify the data flow by connecting the |sink_1| to |track_1|.
- scoped_ptr<MockMediaStreamAudioSink> sink_1(new MockMediaStreamAudioSink());
+ std::unique_ptr<MockMediaStreamAudioSink> sink_1(
+ new MockMediaStreamAudioSink());
EXPECT_CALL(*sink_1.get(), CaptureData())
.Times(AnyNumber()).WillRepeatedly(Return());
EXPECT_CALL(*sink_1.get(), FormatIsSet()).Times(AnyNumber());
track_1->AddSink(sink_1.get());
// Create a new capturer with new source with different audio format.
- MockMediaConstraintFactory constraint_factory;
+ MockConstraintFactory constraint_factory;
StreamDeviceInfo device(MEDIA_DEVICE_AUDIO_CAPTURE,
std::string(), std::string());
- scoped_refptr<WebRtcAudioCapturer> new_capturer(
+ std::unique_ptr<WebRtcAudioCapturer> new_capturer(
WebRtcAudioCapturer::CreateCapturer(
-1, device, constraint_factory.CreateWebMediaConstraints(), NULL,
NULL));
@@ -436,12 +486,17 @@ TEST_F(WebRtcLocalAudioTrackTest, MAYBE_ConnectTracksToDifferentCapturers) {
// Setup the second audio track, connect it to the new capturer and start it.
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter_2(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
- scoped_ptr<WebRtcLocalAudioTrack> track_2(
- new WebRtcLocalAudioTrack(adapter_2.get(), new_capturer, NULL));
- track_2->Start();
+ std::unique_ptr<WebRtcLocalAudioTrack> track_2(
+ new WebRtcLocalAudioTrack(adapter_2.get()));
+ track_2->Start(
+ base::Bind(&MediaStreamAudioSource::StopAudioDeliveryTo,
+ MediaStreamAudioSource::From(blink_source_)->GetWeakPtr(),
+ track_2.get()));
+ new_capturer->AddTrack(track_2.get());
// Verify the data flow by connecting the |sink_2| to |track_2|.
- scoped_ptr<MockMediaStreamAudioSink> sink_2(new MockMediaStreamAudioSink());
+ std::unique_ptr<MockMediaStreamAudioSink> sink_2(
+ new MockMediaStreamAudioSink());
base::WaitableEvent event(false, false);
EXPECT_CALL(*sink_2, CaptureData())
.Times(AnyNumber()).WillRepeatedly(Return());
@@ -469,9 +524,9 @@ TEST_F(WebRtcLocalAudioTrackTest, TrackWorkWithSmallBufferSize) {
media::CHANNEL_LAYOUT_STEREO, 48000, 16, 128);
// Create a capturer with new source which works with the format above.
- MockMediaConstraintFactory factory;
+ MockConstraintFactory factory;
factory.DisableDefaultAudioConstraints();
- scoped_refptr<WebRtcAudioCapturer> capturer(
+ std::unique_ptr<WebRtcAudioCapturer> capturer(
WebRtcAudioCapturer::CreateCapturer(
-1, StreamDeviceInfo(MEDIA_DEVICE_AUDIO_CAPTURE, "", "",
params.sample_rate(), params.channel_layout(),
@@ -487,12 +542,17 @@ TEST_F(WebRtcLocalAudioTrackTest, TrackWorkWithSmallBufferSize) {
// Setup a audio track, connect it to the capturer and start it.
scoped_refptr<WebRtcLocalAudioTrackAdapter> adapter(
WebRtcLocalAudioTrackAdapter::Create(std::string(), NULL));
- scoped_ptr<WebRtcLocalAudioTrack> track(
- new WebRtcLocalAudioTrack(adapter.get(), capturer, NULL));
- track->Start();
+ std::unique_ptr<WebRtcLocalAudioTrack> track(
+ new WebRtcLocalAudioTrack(adapter.get()));
+ track->Start(
+ base::Bind(&MediaStreamAudioSource::StopAudioDeliveryTo,
+ MediaStreamAudioSource::From(blink_source_)->GetWeakPtr(),
+ track.get()));
+ capturer->AddTrack(track.get());
// Verify the data flow by connecting the |sink| to |track|.
- scoped_ptr<MockMediaStreamAudioSink> sink(new MockMediaStreamAudioSink());
+ std::unique_ptr<MockMediaStreamAudioSink> sink(
+ new MockMediaStreamAudioSink());
base::WaitableEvent event(false, false);
EXPECT_CALL(*sink, FormatIsSet()).Times(1);
// Verify the sinks are getting the packets with an expecting buffer size.
diff --git a/chromium/content/renderer/media/webrtc_uma_histograms.h b/chromium/content/renderer/media/webrtc_uma_histograms.h
index c4a5f054815..e333178d66b 100644
--- a/chromium/content/renderer/media/webrtc_uma_histograms.h
+++ b/chromium/content/renderer/media/webrtc_uma_histograms.h
@@ -40,6 +40,7 @@ enum JavaScriptAPIName {
WEBKIT_GET_MEDIA_DEVICES,
WEBKIT_MEDIA_STREAM_RECORDER,
WEBKIT_CANVAS_CAPTURE_STREAM,
+ WEBKIT_VIDEO_CAPTURE_STREAM,
INVALID_NAME
};
diff --git a/chromium/content/renderer/memory_benchmarking_extension.cc b/chromium/content/renderer/memory_benchmarking_extension.cc
deleted file mode 100644
index be554c34dfe..00000000000
--- a/chromium/content/renderer/memory_benchmarking_extension.cc
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/memory_benchmarking_extension.h"
-
-#include "build/build_config.h"
-#include "content/common/memory_benchmark_messages.h"
-#include "content/public/renderer/chrome_object_extensions_utils.h"
-#include "content/renderer/render_thread_impl.h"
-#include "gin/arguments.h"
-#include "gin/handle.h"
-#include "gin/object_template_builder.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
-#include "third_party/WebKit/public/web/WebKit.h"
-
-#if defined(USE_TCMALLOC) && (defined(OS_LINUX) || defined(OS_ANDROID))
-#include "third_party/tcmalloc/chromium/src/gperftools/heap-profiler.h"
-#endif
-
-namespace content {
-
-gin::WrapperInfo MemoryBenchmarkingExtension::kWrapperInfo = {
- gin::kEmbedderNativeGin};
-
-// static
-void MemoryBenchmarkingExtension::Install(blink::WebFrame* frame) {
- v8::Isolate* isolate = blink::mainThreadIsolate();
- v8::HandleScope handle_scope(isolate);
- v8::Local<v8::Context> context = frame->mainWorldScriptContext();
- if (context.IsEmpty())
- return;
-
- v8::Context::Scope context_scope(context);
- gin::Handle<MemoryBenchmarkingExtension> controller =
- gin::CreateHandle(isolate, new MemoryBenchmarkingExtension());
- if (controller.IsEmpty())
- return;
-
- v8::Local<v8::Object> chrome = GetOrCreateChromeObject(isolate,
- context->Global());
- chrome->Set(gin::StringToV8(isolate, "memoryBenchmarking"),
- controller.ToV8());
-}
-
-MemoryBenchmarkingExtension::MemoryBenchmarkingExtension() {}
-
-MemoryBenchmarkingExtension::~MemoryBenchmarkingExtension() {}
-
-gin::ObjectTemplateBuilder
-MemoryBenchmarkingExtension::GetObjectTemplateBuilder(v8::Isolate* isolate) {
- return gin::Wrappable<MemoryBenchmarkingExtension>::GetObjectTemplateBuilder(
- isolate)
- .SetMethod("isHeapProfilerRunning",
- &MemoryBenchmarkingExtension::IsHeapProfilerRunning)
- .SetMethod("heapProfilerDump",
- &MemoryBenchmarkingExtension::HeapProfilerDump);
-}
-
-bool MemoryBenchmarkingExtension::IsHeapProfilerRunning() {
-#if defined(USE_TCMALLOC) && (defined(OS_LINUX) || defined(OS_ANDROID))
- return ::IsHeapProfilerRunning();
-#else
- return false;
-#endif
-}
-
-void MemoryBenchmarkingExtension::HeapProfilerDump(gin::Arguments* args) {
- std::string process_type;
- std::string reason("benchmarking_extension");
-
- if (!args->PeekNext().IsEmpty() && args->PeekNext()->IsString()) {
- args->GetNext(&process_type);
- if (!args->PeekNext().IsEmpty() && args->PeekNext()->IsString())
- args->GetNext(&reason);
- }
-
-#if defined(USE_TCMALLOC) && (defined(OS_LINUX) || defined(OS_ANDROID))
- if (process_type == "browser") {
- content::RenderThreadImpl::current()->Send(
- new MemoryBenchmarkHostMsg_HeapProfilerDump(reason));
- } else {
- ::HeapProfilerDump(reason.c_str());
- }
-#endif
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/memory_benchmarking_extension.h b/chromium/content/renderer/memory_benchmarking_extension.h
deleted file mode 100644
index af7f4f25e2e..00000000000
--- a/chromium/content/renderer/memory_benchmarking_extension.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_MEMORY_BENCHMARKING_EXTENSION_H_
-#define CONTENT_RENDERER_MEMORY_BENCHMARKING_EXTENSION_H_
-
-#include "base/macros.h"
-#include "gin/wrappable.h"
-
-namespace blink {
-class WebFrame;
-}
-
-namespace gin {
-class Arguments;
-}
-
-namespace content {
-
-class MemoryBenchmarkingExtension
- : public gin::Wrappable<MemoryBenchmarkingExtension> {
- public:
- static gin::WrapperInfo kWrapperInfo;
-
- static void Install(blink::WebFrame* frame);
-
- private:
- MemoryBenchmarkingExtension();
- ~MemoryBenchmarkingExtension() override;
-
- // gin::Wrappable.
- gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
- v8::Isolate* isolate) override;
-
- bool IsHeapProfilerRunning();
-
- void HeapProfilerDump(gin::Arguments* args);
-
- DISALLOW_COPY_AND_ASSIGN(MemoryBenchmarkingExtension);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_MEMORY_BENCHMARKING_EXTENSION_H_
diff --git a/chromium/content/renderer/mojo/blink_service_registry_impl.cc b/chromium/content/renderer/mojo/blink_service_registry_impl.cc
new file mode 100644
index 00000000000..6a2fdf09a6a
--- /dev/null
+++ b/chromium/content/renderer/mojo/blink_service_registry_impl.cc
@@ -0,0 +1,28 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/mojo/blink_service_registry_impl.h"
+
+#include <utility>
+
+#include "content/common/mojo/service_registry_impl.h"
+
+namespace content {
+
+BlinkServiceRegistryImpl::BlinkServiceRegistryImpl(
+ base::WeakPtr<content::ServiceRegistry> service_registry)
+ : service_registry_(service_registry) {}
+
+BlinkServiceRegistryImpl::~BlinkServiceRegistryImpl() = default;
+
+void BlinkServiceRegistryImpl::connectToRemoteService(
+ const char* name,
+ mojo::ScopedMessagePipeHandle handle) {
+ if (!service_registry_)
+ return;
+
+ service_registry_->ConnectToRemoteService(name, std::move(handle));
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/mojo/blink_service_registry_impl.h b/chromium/content/renderer/mojo/blink_service_registry_impl.h
new file mode 100644
index 00000000000..8bd86321e68
--- /dev/null
+++ b/chromium/content/renderer/mojo/blink_service_registry_impl.h
@@ -0,0 +1,37 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_MOJO_BLINK_SERVICE_REGISTRY_IMPL_H_
+#define CONTENT_RENDERER_MOJO_BLINK_SERVICE_REGISTRY_IMPL_H_
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+#include "third_party/WebKit/public/platform/ServiceRegistry.h"
+
+namespace content {
+
+class ServiceRegistry;
+
+// An implementation of blink::ServiceRegistry that forwards to a
+// content::ServiceRegistry.
+class BlinkServiceRegistryImpl : public blink::ServiceRegistry {
+ public:
+ explicit BlinkServiceRegistryImpl(
+ base::WeakPtr<content::ServiceRegistry> service_registry);
+ ~BlinkServiceRegistryImpl();
+
+ // blink::ServiceRegistry override.
+ void connectToRemoteService(const char* name,
+ mojo::ScopedMessagePipeHandle handle) override;
+
+ private:
+ const base::WeakPtr<content::ServiceRegistry> service_registry_;
+
+ DISALLOW_COPY_AND_ASSIGN(BlinkServiceRegistryImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_MOJO_BLINK_SERVICE_REGISTRY_IMPL_H_
diff --git a/chromium/content/renderer/mojo/service_registry_js_wrapper.cc b/chromium/content/renderer/mojo/service_registry_js_wrapper.cc
index b91a16225e1..1ab8b86fb31 100644
--- a/chromium/content/renderer/mojo/service_registry_js_wrapper.cc
+++ b/chromium/content/renderer/mojo/service_registry_js_wrapper.cc
@@ -6,16 +6,20 @@
#include <utility>
+#include "base/memory/scoped_ptr.h"
#include "content/common/mojo/service_registry_impl.h"
#include "content/public/common/service_registry.h"
-#include "third_party/mojo/src/mojo/edk/js/handle.h"
+#include "mojo/edk/js/handle.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
namespace content {
gin::WrapperInfo ServiceRegistryJsWrapper::kWrapperInfo = {
gin::kEmbedderNativeGin};
-const char ServiceRegistryJsWrapper::kModuleName[] =
- "content/public/renderer/service_provider";
+const char ServiceRegistryJsWrapper::kPerFrameModuleName[] =
+ "content/public/renderer/frame_service_registry";
+const char ServiceRegistryJsWrapper::kPerProcessModuleName[] =
+ "content/public/renderer/service_registry";
ServiceRegistryJsWrapper::~ServiceRegistryJsWrapper() {
}
@@ -23,18 +27,24 @@ ServiceRegistryJsWrapper::~ServiceRegistryJsWrapper() {
// static
gin::Handle<ServiceRegistryJsWrapper> ServiceRegistryJsWrapper::Create(
v8::Isolate* isolate,
+ v8::Handle<v8::Context> context,
ServiceRegistry* service_registry) {
return gin::CreateHandle(
isolate,
new ServiceRegistryJsWrapper(
+ isolate, context,
static_cast<ServiceRegistryImpl*>(service_registry)->GetWeakPtr()));
}
gin::ObjectTemplateBuilder ServiceRegistryJsWrapper::GetObjectTemplateBuilder(
v8::Isolate* isolate) {
- return Wrappable<ServiceRegistryJsWrapper>::GetObjectTemplateBuilder(isolate).
- SetMethod("connectToService",
- &ServiceRegistryJsWrapper::ConnectToService);
+ return Wrappable<ServiceRegistryJsWrapper>::GetObjectTemplateBuilder(isolate)
+ .SetMethod("connectToService",
+ &ServiceRegistryJsWrapper::ConnectToService)
+ .SetMethod("addServiceOverrideForTesting",
+ &ServiceRegistryJsWrapper::AddServiceOverrideForTesting)
+ .SetMethod("clearServiceOverridesForTesting",
+ &ServiceRegistryJsWrapper::ClearServiceOverridesForTesting);
}
mojo::Handle ServiceRegistryJsWrapper::ConnectToService(
@@ -46,9 +56,60 @@ mojo::Handle ServiceRegistryJsWrapper::ConnectToService(
return pipe.handle1.release();
}
+void ServiceRegistryJsWrapper::AddServiceOverrideForTesting(
+ const std::string& service_name,
+ v8::Local<v8::Function> service_factory) {
+ ServiceRegistry* registry = service_registry_.get();
+ if (!registry)
+ return;
+ ScopedJsFactory factory(v8::Isolate::GetCurrent(), service_factory);
+ registry->AddServiceOverrideForTesting(
+ service_name, base::Bind(&ServiceRegistryJsWrapper::CallJsFactory,
+ weak_factory_.GetWeakPtr(), factory));
+}
+
+void ServiceRegistryJsWrapper::ClearServiceOverridesForTesting() {
+ ServiceRegistryImpl* registry =
+ static_cast<ServiceRegistryImpl*>(service_registry_.get());
+ if (!registry)
+ return;
+
+ registry->ClearServiceOverridesForTesting();
+}
+
ServiceRegistryJsWrapper::ServiceRegistryJsWrapper(
+ v8::Isolate* isolate,
+ v8::Handle<v8::Context> context,
base::WeakPtr<ServiceRegistry> service_registry)
- : service_registry_(service_registry) {
+ : isolate_(isolate),
+ context_(isolate, context),
+ service_registry_(service_registry),
+ weak_factory_(this) {
+ context_.SetWeak(this, &ServiceRegistryJsWrapper::ClearContext,
+ v8::WeakCallbackType::kParameter);
+}
+
+void ServiceRegistryJsWrapper::CallJsFactory(
+ const ScopedJsFactory& factory,
+ mojo::ScopedMessagePipeHandle pipe) {
+ if (context_.IsEmpty())
+ return;
+
+ v8::HandleScope handle_scope(isolate_);
+ v8::Handle<v8::Context> context = context_.Get(isolate_);
+ v8::Context::Scope context_scope(context);
+ v8::Local<v8::Value> argv[] = {
+ gin::ConvertToV8(isolate_, mojo::Handle(pipe.release().value()))};
+ blink::WebLocalFrame::frameForContext(context)
+ ->callFunctionEvenIfScriptDisabled(factory.Get(isolate_),
+ v8::Undefined(isolate_), 1, argv);
+}
+
+// static
+void ServiceRegistryJsWrapper::ClearContext(
+ const v8::WeakCallbackInfo<ServiceRegistryJsWrapper>& data) {
+ ServiceRegistryJsWrapper* service_registry = data.GetParameter();
+ service_registry->context_.Reset();
}
} // namespace content
diff --git a/chromium/content/renderer/mojo/service_registry_js_wrapper.h b/chromium/content/renderer/mojo/service_registry_js_wrapper.h
index 73046862dbb..5fc2f63729b 100644
--- a/chromium/content/renderer/mojo/service_registry_js_wrapper.h
+++ b/chromium/content/renderer/mojo/service_registry_js_wrapper.h
@@ -12,7 +12,8 @@
#include "gin/handle.h"
#include "gin/object_template_builder.h"
#include "gin/wrappable.h"
-#include "mojo/public/cpp/system/core.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+#include "v8/include/v8.h"
namespace content {
@@ -26,6 +27,7 @@ class CONTENT_EXPORT ServiceRegistryJsWrapper
~ServiceRegistryJsWrapper() override;
static gin::Handle<ServiceRegistryJsWrapper> Create(
v8::Isolate* isolate,
+ v8::Handle<v8::Context> context,
ServiceRegistry* service_registry);
// gin::Wrappable<ServiceRegistryJsWrapper> overrides.
@@ -33,17 +35,35 @@ class CONTENT_EXPORT ServiceRegistryJsWrapper
v8::Isolate* isolate) override;
// JS interface implementation.
+ void AddServiceOverrideForTesting(const std::string& service_name,
+ v8::Local<v8::Function> service_factory);
+ void ClearServiceOverridesForTesting();
mojo::Handle ConnectToService(const std::string& service_name);
static gin::WrapperInfo kWrapperInfo;
- static const char kModuleName[];
+ static const char kPerFrameModuleName[];
+ static const char kPerProcessModuleName[];
private:
- explicit ServiceRegistryJsWrapper(
- base::WeakPtr<ServiceRegistry> service_registry);
+ using ScopedJsFactory =
+ v8::Persistent<v8::Function, v8::CopyablePersistentTraits<v8::Function>>;
+ ServiceRegistryJsWrapper(v8::Isolate* isolate,
+ v8::Handle<v8::Context> context,
+ base::WeakPtr<ServiceRegistry> service_registry);
+
+ void CallJsFactory(const ScopedJsFactory& factory,
+ mojo::ScopedMessagePipeHandle pipe);
+
+ static void ClearContext(
+ const v8::WeakCallbackInfo<ServiceRegistryJsWrapper>& data);
+
+ v8::Isolate* isolate_;
+ v8::Global<v8::Context> context_;
base::WeakPtr<ServiceRegistry> service_registry_;
+ base::WeakPtrFactory<ServiceRegistryJsWrapper> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(ServiceRegistryJsWrapper);
};
diff --git a/chromium/content/renderer/mojo_bindings_controller.cc b/chromium/content/renderer/mojo_bindings_controller.cc
index 08abcf574f2..84a61b2bcd9 100644
--- a/chromium/content/renderer/mojo_bindings_controller.cc
+++ b/chromium/content/renderer/mojo_bindings_controller.cc
@@ -26,21 +26,22 @@ struct MojoContextStateData : public base::SupportsUserData::Data {
} // namespace
-MojoBindingsController::MojoBindingsController(RenderFrame* render_frame)
+MojoBindingsController::MojoBindingsController(RenderFrame* render_frame,
+ bool for_layout_tests)
: RenderFrameObserver(render_frame),
- RenderFrameObserverTracker<MojoBindingsController>(render_frame) {}
+ RenderFrameObserverTracker<MojoBindingsController>(render_frame),
+ for_layout_tests_(for_layout_tests) {}
MojoBindingsController::~MojoBindingsController() {
}
void MojoBindingsController::CreateContextState() {
v8::HandleScope handle_scope(blink::mainThreadIsolate());
- blink::WebLocalFrame* frame =
- render_frame()->GetWebFrame()->toWebLocalFrame();
+ blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
v8::Local<v8::Context> context = frame->mainWorldScriptContext();
gin::PerContextData* context_data = gin::PerContextData::From(context);
MojoContextStateData* data = new MojoContextStateData;
- data->state.reset(new MojoContextState(frame, context));
+ data->state.reset(new MojoContextState(frame, context, for_layout_tests_));
context_data->SetUserData(kMojoContextStateKey, data);
}
@@ -70,17 +71,17 @@ void MojoBindingsController::WillReleaseScriptContext(
DestroyContextState(context);
}
-void MojoBindingsController::DidFinishDocumentLoad() {
+void MojoBindingsController::RunScriptsAtDocumentStart() {
+ CreateContextState();
+}
+
+void MojoBindingsController::RunScriptsAtDocumentReady() {
v8::HandleScope handle_scope(blink::mainThreadIsolate());
MojoContextState* state = GetContextState();
if (state)
state->Run();
}
-void MojoBindingsController::DidCreateDocumentElement() {
- CreateContextState();
-}
-
void MojoBindingsController::DidClearWindowObject() {
// NOTE: this function may be called early on twice. From the constructor
// mainWorldScriptContext() may trigger this to be called. If we are created
diff --git a/chromium/content/renderer/mojo_bindings_controller.h b/chromium/content/renderer/mojo_bindings_controller.h
index 3ebb744cb06..d26f17a85cf 100644
--- a/chromium/content/renderer/mojo_bindings_controller.h
+++ b/chromium/content/renderer/mojo_bindings_controller.h
@@ -28,7 +28,9 @@ class MojoBindingsController
: public RenderFrameObserver,
public RenderFrameObserverTracker<MojoBindingsController> {
public:
- explicit MojoBindingsController(RenderFrame* render_frame);
+ MojoBindingsController(RenderFrame* render_frame, bool for_layout_tests);
+ void RunScriptsAtDocumentStart();
+ void RunScriptsAtDocumentReady();
private:
~MojoBindingsController() override;
@@ -40,10 +42,10 @@ class MojoBindingsController
// RenderFrameObserver overrides:
void WillReleaseScriptContext(v8::Local<v8::Context> context,
int world_id) override;
- void DidFinishDocumentLoad() override;
- void DidCreateDocumentElement() override;
void DidClearWindowObject() override;
+ const bool for_layout_tests_;
+
DISALLOW_COPY_AND_ASSIGN(MojoBindingsController);
};
diff --git a/chromium/content/renderer/mojo_context_state.cc b/chromium/content/renderer/mojo_context_state.cc
index 2d3bdea933b..4274fee2060 100644
--- a/chromium/content/renderer/mojo_context_state.cc
+++ b/chromium/content/renderer/mojo_context_state.cc
@@ -6,8 +6,16 @@
#include <stddef.h>
+#include <map>
+#include <string>
+
#include "base/bind.h"
+#include "base/lazy_instance.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/ref_counted_memory.h"
#include "base/stl_util.h"
+#include "content/grit/content_resources.h"
+#include "content/public/common/content_client.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/resource_fetcher.h"
#include "content/renderer/mojo_main_runner.h"
@@ -16,10 +24,11 @@
#include "gin/per_context_data.h"
#include "gin/public/context_holder.h"
#include "gin/try_catch.h"
+#include "mojo/public/js/constants.h"
+#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/platform/WebURLResponse.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "third_party/WebKit/public/web/WebScriptSource.h"
-#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
using v8::Context;
using v8::HandleScope;
@@ -40,13 +49,58 @@ void RunMain(base::WeakPtr<gin::Runner> runner,
runner->Call(start, runner->global(), 0, NULL);
}
+using ModuleSourceMap =
+ std::map<std::string, scoped_refptr<base::RefCountedMemory>>;
+
+base::LazyInstance<scoped_ptr<ModuleSourceMap>>::Leaky g_module_sources;
+
+scoped_refptr<base::RefCountedMemory> GetBuiltinModuleData(
+ const std::string& path) {
+ static const struct {
+ const char* path;
+ const int id;
+ } kBuiltinModuleResources[] = {
+ { mojo::kBindingsModuleName, IDR_MOJO_BINDINGS_JS },
+ { mojo::kBufferModuleName, IDR_MOJO_BUFFER_JS },
+ { mojo::kCodecModuleName, IDR_MOJO_CODEC_JS },
+ { mojo::kConnectionModuleName, IDR_MOJO_CONNECTION_JS },
+ { mojo::kConnectorModuleName, IDR_MOJO_CONNECTOR_JS },
+ { mojo::kRouterModuleName, IDR_MOJO_ROUTER_JS },
+ { mojo::kUnicodeModuleName, IDR_MOJO_UNICODE_JS },
+ { mojo::kValidatorModuleName, IDR_MOJO_VALIDATOR_JS },
+ };
+
+ scoped_ptr<ModuleSourceMap>& module_sources = g_module_sources.Get();
+ if (!module_sources) {
+ // Initialize the module source map on first access.
+ module_sources.reset(new ModuleSourceMap);
+ for (size_t i = 0; i < arraysize(kBuiltinModuleResources); ++i) {
+ const auto& resource = kBuiltinModuleResources[i];
+ scoped_refptr<base::RefCountedMemory> data =
+ GetContentClient()->GetDataResourceBytes(resource.id);
+ DCHECK_GT(data->size(), 0u);
+ module_sources->insert(std::make_pair(std::string(resource.path), data));
+ }
+ }
+
+ DCHECK(module_sources);
+ auto source_iter = module_sources->find(path);
+ if (source_iter == module_sources->end())
+ return nullptr;
+ return source_iter->second;
+}
+
} // namespace
MojoContextState::MojoContextState(blink::WebFrame* frame,
- v8::Local<v8::Context> context)
+ v8::Local<v8::Context> context,
+ bool for_layout_tests)
: frame_(frame),
module_added_(false),
- module_prefix_(frame_->securityOrigin().toString().utf8() + "/") {
+ module_prefix_(for_layout_tests
+ ? "layout-test-mojom://"
+ : frame_->getSecurityOrigin().toString().utf8() +
+ "/") {
gin::PerContextData* context_data = gin::PerContextData::From(context);
gin::ContextHolder* context_holder = context_data->context_holder();
runner_.reset(new MojoMainRunner(frame_, context_holder));
@@ -54,7 +108,21 @@ MojoContextState::MojoContextState(blink::WebFrame* frame,
gin::ModuleRegistry::From(context)->AddObserver(this);
content::RenderFrame::FromWebFrame(frame)
->EnsureMojoBuiltinsAreAvailable(context_holder->isolate(), context);
- gin::ModuleRegistry::InstallGlobals(context->GetIsolate(), context->Global());
+ v8::Local<v8::Object> install_target;
+ if (for_layout_tests) {
+ // In layout tests we install the module system under 'mojo.define'
+ // for now to avoid globally exposing something as generic as 'define'.
+ //
+ // TODO(rockot): Remove this if/when we can integrate gin + ES6 modules.
+ install_target = v8::Object::New(context->GetIsolate());
+ gin::SetProperty(context->GetIsolate(), context->Global(),
+ gin::StringToSymbol(context->GetIsolate(), "mojo"),
+ install_target);
+ } else {
+ // Otherwise we're fine installing a global 'define'.
+ install_target = context->Global();
+ }
+ gin::ModuleRegistry::InstallGlobals(context->GetIsolate(), install_target);
// Warning |frame| may be destroyed.
// TODO(sky): add test for this.
}
@@ -81,7 +149,11 @@ void MojoContextState::FetchModules(const std::vector<std::string>& ids) {
for (size_t i = 0; i < ids.size(); ++i) {
if (fetched_modules_.find(ids[i]) == fetched_modules_.end() &&
registry->available_modules().count(ids[i]) == 0) {
- FetchModule(ids[i]);
+ scoped_refptr<base::RefCountedMemory> data = GetBuiltinModuleData(ids[i]);
+ if (data)
+ runner_->Run(std::string(data->front_as<char>(), data->size()), ids[i]);
+ else
+ FetchModule(ids[i]);
}
}
}
@@ -99,28 +171,30 @@ void MojoContextState::FetchModule(const std::string& id) {
blink::WebURLRequest::FrameTypeNone,
ResourceFetcher::PLATFORM_LOADER,
base::Bind(&MojoContextState::OnFetchModuleComplete,
- base::Unretained(this), fetcher));
+ base::Unretained(this), fetcher, id));
}
void MojoContextState::OnFetchModuleComplete(
ResourceFetcher* fetcher,
+ const std::string& id,
const blink::WebURLResponse& response,
const std::string& data) {
- DCHECK_EQ(module_prefix_,
- response.url().string().utf8().substr(0, module_prefix_.size()));
- const std::string module =
- response.url().string().utf8().substr(module_prefix_.size());
+ if (response.isNull()) {
+ LOG(ERROR) << "Failed to fetch source for module \"" << id << "\"";
+ return;
+ }
+ DCHECK_EQ(module_prefix_ + id, response.url().string().utf8());
// We can't delete fetch right now as the arguments to this function come from
// it and are used below. Instead use a scope_ptr to cleanup.
scoped_ptr<ResourceFetcher> deleter(fetcher);
module_fetchers_.weak_erase(
std::find(module_fetchers_.begin(), module_fetchers_.end(), fetcher));
if (data.empty()) {
- NOTREACHED();
- return; // TODO(sky): log something?
+ LOG(ERROR) << "Fetched empty source for module \"" << id << "\"";
+ return;
}
- runner_->Run(data, module);
+ runner_->Run(data, id);
}
void MojoContextState::OnDidAddPendingModule(
diff --git a/chromium/content/renderer/mojo_context_state.h b/chromium/content/renderer/mojo_context_state.h
index f6516b4f71a..eaca5306997 100644
--- a/chromium/content/renderer/mojo_context_state.h
+++ b/chromium/content/renderer/mojo_context_state.h
@@ -33,7 +33,9 @@ class MojoMainRunner;
// by way of gin. Non-builtin modules are downloaded by way of ResourceFetchers.
class MojoContextState : public gin::ModuleRegistryObserver {
public:
- MojoContextState(blink::WebFrame* frame, v8::Local<v8::Context> context);
+ MojoContextState(blink::WebFrame* frame,
+ v8::Local<v8::Context> context,
+ bool for_layout_tests);
~MojoContextState() override;
void Run();
@@ -53,6 +55,7 @@ class MojoContextState : public gin::ModuleRegistryObserver {
// Callback once a module has finished downloading. Passes data to |runner_|.
void OnFetchModuleComplete(ResourceFetcher* fetcher,
+ const std::string& id,
const blink::WebURLResponse& response,
const std::string& data);
diff --git a/chromium/content/renderer/mus/BUILD.gn b/chromium/content/renderer/mus/BUILD.gn
index f66108bd360..6155680e5ca 100644
--- a/chromium/content/renderer/mus/BUILD.gn
+++ b/chromium/content/renderer/mus/BUILD.gn
@@ -3,6 +3,9 @@
# found in the LICENSE file.
source_set("mus") {
+ # Depend on this only via //content/renderer.
+ visibility = [ "//content/renderer/*" ]
+
sources = [
"compositor_mus_connection.cc",
"compositor_mus_connection.h",
@@ -17,9 +20,18 @@ source_set("mus") {
deps = [
"//base",
"//cc",
+ "//components/mus/public/cpp",
"//components/mus/public/interfaces",
- "//content/common:mojo_bindings",
+ "//content/common",
+ "//content/public/common:common_sources",
+ "//mojo/common",
"//mojo/converters/blink",
+ "//mojo/converters/geometry",
+ "//mojo/converters/input_events",
+ "//mojo/converters/surfaces",
+ "//mojo/shell/public/cpp",
"//third_party/WebKit/public:blink",
+ "//ui/events:events",
+ "//ui/events:events_base",
]
}
diff --git a/chromium/content/renderer/mus/compositor_mus_connection.cc b/chromium/content/renderer/mus/compositor_mus_connection.cc
index 00b9e4920c6..d303789626b 100644
--- a/chromium/content/renderer/mus/compositor_mus_connection.cc
+++ b/chromium/content/renderer/mus/compositor_mus_connection.cc
@@ -9,8 +9,15 @@
#include "content/renderer/input/input_handler_manager.h"
#include "content/renderer/mus/render_widget_mus_connection.h"
#include "mojo/converters/blink/blink_input_events_type_converters.h"
+#include "mojo/converters/input_events/input_events_type_converters.h"
#include "ui/events/latency_info.h"
+namespace {
+
+void DoNothingBool(bool result) {}
+
+} // namespace
+
namespace content {
CompositorMusConnection::CompositorMusConnection(
@@ -47,7 +54,7 @@ void CompositorMusConnection::AttachSurfaceOnCompositorThread(
DCHECK(compositor_task_runner_->BelongsToCurrentThread());
window_surface_binding_ = std::move(surface_binding);
if (root_) {
- root_->AttachSurface(mus::mojom::SURFACE_TYPE_DEFAULT,
+ root_->AttachSurface(mus::mojom::SurfaceType::DEFAULT,
std::move(window_surface_binding_));
}
}
@@ -71,21 +78,22 @@ void CompositorMusConnection::OnConnectionLostOnMainThread() {
void CompositorMusConnection::OnWindowInputEventOnMainThread(
scoped_ptr<blink::WebInputEvent> web_event,
- const base::Closure& ack) {
+ const base::Callback<void(bool)>& ack) {
DCHECK(main_task_runner_->BelongsToCurrentThread());
RenderWidgetMusConnection* connection =
RenderWidgetMusConnection::Get(routing_id_);
if (!connection) {
- ack.Run();
+ ack.Run(false);
return;
}
connection->OnWindowInputEvent(std::move(web_event), ack);
}
void CompositorMusConnection::OnWindowInputEventAckOnMainThread(
- const base::Closure& ack) {
+ const base::Callback<void(bool)>& ack,
+ bool handled) {
DCHECK(main_task_runner_->BelongsToCurrentThread());
- compositor_task_runner_->PostTask(FROM_HERE, ack);
+ compositor_task_runner_->PostTask(FROM_HERE, base::Bind(ack, handled));
}
void CompositorMusConnection::OnConnectionLost(
@@ -101,27 +109,29 @@ void CompositorMusConnection::OnEmbed(mus::Window* root) {
root_ = root;
root_->set_input_event_handler(this);
if (window_surface_binding_) {
- root->AttachSurface(mus::mojom::SURFACE_TYPE_DEFAULT,
+ root->AttachSurface(mus::mojom::SurfaceType::DEFAULT,
std::move(window_surface_binding_));
}
}
void CompositorMusConnection::OnWindowInputEvent(
mus::Window* window,
- mus::mojom::EventPtr event,
- scoped_ptr<base::Closure>* ack_callback) {
+ const ui::Event& event,
+ scoped_ptr<base::Callback<void(bool)>>* ack_callback) {
DCHECK(compositor_task_runner_->BelongsToCurrentThread());
- scoped_ptr<blink::WebInputEvent> web_event =
- event.To<scoped_ptr<blink::WebInputEvent>>();
+ // TODO(moshayedi): Convert ui::Event directly to blink::WebInputEvent.
+ scoped_ptr<blink::WebInputEvent> web_event(
+ mus::mojom::Event::From(event).To<scoped_ptr<blink::WebInputEvent>>());
// TODO(sad): We probably need to plumb LatencyInfo through Mus.
ui::LatencyInfo info;
InputEventAckState ack_state = input_handler_manager_->HandleInputEvent(
routing_id_, web_event.get(), &info);
+ // TODO(jonross): We probably need to ack the event based on the consumed
+ // state.
if (ack_state != INPUT_EVENT_ACK_STATE_NOT_CONSUMED)
return;
- base::Closure ack = base::Bind(&base::DoNothing);
- const bool send_ack =
- WebInputEventTraits::WillReceiveAckFromRenderer(*web_event);
+ base::Callback<void(bool)> ack = base::Bind(&::DoNothingBool);
+ const bool send_ack = WebInputEventTraits::ShouldBlockEventStream(*web_event);
if (send_ack) {
// Ultimately, this ACK needs to go back to the Mus client lib which is not
// thread-safe and lives on the compositor thread. For ACKs that are passed
diff --git a/chromium/content/renderer/mus/compositor_mus_connection.h b/chromium/content/renderer/mus/compositor_mus_connection.h
index 7b0f69611b6..8003e4787d7 100644
--- a/chromium/content/renderer/mus/compositor_mus_connection.h
+++ b/chromium/content/renderer/mus/compositor_mus_connection.h
@@ -6,11 +6,13 @@
#define CONTENT_RENDERER_MUS_COMPOSITOR_MUS_CONNECTION_H_
#include "base/bind.h"
+#include "base/compiler_specific.h"
#include "base/macros.h"
#include "components/mus/public/cpp/input_event_handler.h"
#include "components/mus/public/cpp/window.h"
#include "components/mus/public/cpp/window_tree_connection.h"
#include "components/mus/public/cpp/window_tree_delegate.h"
+#include "content/common/content_export.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
namespace content {
@@ -23,9 +25,9 @@ class InputHandlerManager;
// threads. CompositorMusConnection is constructed on the main thread. By
// default all other methods are assumed to run on the compositor thread unless
// explicited suffixed with OnMainThread.
-class CompositorMusConnection
- : public mus::WindowTreeDelegate,
- public mus::InputEventHandler,
+class CONTENT_EXPORT CompositorMusConnection
+ : NON_EXPORTED_BASE(public mus::WindowTreeDelegate),
+ NON_EXPORTED_BASE(public mus::InputEventHandler),
public base::RefCountedThreadSafe<CompositorMusConnection> {
public:
// Created on main thread.
@@ -42,6 +44,7 @@ class CompositorMusConnection
scoped_ptr<mus::WindowSurfaceBinding> surface_binding);
private:
+ friend class CompositorMusConnectionTest;
friend class base::RefCountedThreadSafe<CompositorMusConnection>;
~CompositorMusConnection() override;
@@ -56,18 +59,20 @@ class CompositorMusConnection
void OnWindowInputEventOnMainThread(
scoped_ptr<blink::WebInputEvent> web_event,
- const base::Closure& ack);
+ const base::Callback<void(bool)>& ack);
- void OnWindowInputEventAckOnMainThread(const base::Closure& ack);
+ void OnWindowInputEventAckOnMainThread(const base::Callback<void(bool)>& ack,
+ bool handled);
// WindowTreeDelegate implementation:
void OnConnectionLost(mus::WindowTreeConnection* connection) override;
void OnEmbed(mus::Window* root) override;
// InputEventHandler implementation:
- void OnWindowInputEvent(mus::Window* window,
- mus::mojom::EventPtr event,
- scoped_ptr<base::Closure>* ack_callback) override;
+ void OnWindowInputEvent(
+ mus::Window* window,
+ const ui::Event& event,
+ scoped_ptr<base::Callback<void(bool)>>* ack_callback) override;
const int routing_id_;
mus::Window* root_;
diff --git a/chromium/content/renderer/mus/compositor_mus_connection_unittest.cc b/chromium/content/renderer/mus/compositor_mus_connection_unittest.cc
new file mode 100644
index 00000000000..aab11f540f2
--- /dev/null
+++ b/chromium/content/renderer/mus/compositor_mus_connection_unittest.cc
@@ -0,0 +1,454 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/mus/compositor_mus_connection.h"
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/test/test_simple_task_runner.h"
+#include "base/time/time.h"
+#include "components/mus/public/cpp/tests/test_window.h"
+#include "components/mus/public/interfaces/input_event_constants.mojom.h"
+#include "components/mus/public/interfaces/input_events.mojom.h"
+#include "components/mus/public/interfaces/input_key_codes.mojom.h"
+#include "content/common/input/did_overscroll_params.h"
+#include "content/common/input/input_event_ack.h"
+#include "content/common/input/input_event_ack_state.h"
+#include "content/public/test/mock_render_thread.h"
+#include "content/renderer/input/input_handler_manager.h"
+#include "content/renderer/input/input_handler_manager_client.h"
+#include "content/renderer/input/render_widget_input_handler.h"
+#include "content/renderer/mus/render_widget_mus_connection.h"
+#include "content/renderer/render_widget.h"
+#include "content/test/fake_compositor_dependencies.h"
+#include "content/test/fake_renderer_scheduler.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/event_utils.h"
+
+namespace {
+
+// Wrapper for the callback provided to
+// CompositorMusConnection:OnWindowInputEvent. This tracks whether the it was
+// called, along with the result.
+class TestCallback : public base::RefCounted<TestCallback> {
+ public:
+ TestCallback() : called_(false), result_(false) {}
+
+ bool called() { return called_; }
+ bool result() { return result_; }
+
+ void BoolCallback(bool result) {
+ called_ = true;
+ result_ = result;
+ }
+
+ private:
+ friend class base::RefCounted<TestCallback>;
+
+ ~TestCallback() {}
+
+ bool called_;
+ bool result_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestCallback);
+};
+
+// Allows for overriding the behaviour of HandleInputEvent, to simulate input
+// handlers which consume events before they are sent to the renderer.
+class TestInputHandlerManager : public content::InputHandlerManager {
+ public:
+ TestInputHandlerManager(
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
+ content::InputHandlerManagerClient* client,
+ scheduler::RendererScheduler* renderer_scheduler)
+ : InputHandlerManager(task_runner, client, nullptr, renderer_scheduler),
+ override_result_(false),
+ result_(content::InputEventAckState::INPUT_EVENT_ACK_STATE_UNKNOWN) {}
+ ~TestInputHandlerManager() override {}
+
+ // Stops overriding the behaviour of HandleInputEvent
+ void ClearHandleInputEventOverride();
+
+ // Overrides the behaviour of HandleInputEvent, returing |result|.
+ void SetHandleInputEventResult(content::InputEventAckState result);
+
+ // content::InputHandlerManager:
+ content::InputEventAckState HandleInputEvent(
+ int routing_id,
+ const blink::WebInputEvent* input_event,
+ ui::LatencyInfo* latency_info) override;
+
+ private:
+ // If true content::InputHandlerManager::HandleInputEvent is not called.
+ bool override_result_;
+
+ // The result to return in HandleInputEvent if |override_result_|.
+ content::InputEventAckState result_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestInputHandlerManager);
+};
+
+void TestInputHandlerManager::ClearHandleInputEventOverride() {
+ override_result_ = false;
+}
+
+void TestInputHandlerManager::SetHandleInputEventResult(
+ content::InputEventAckState result) {
+ override_result_ = true;
+ result_ = result;
+}
+
+content::InputEventAckState TestInputHandlerManager::HandleInputEvent(
+ int routing_id,
+ const blink::WebInputEvent* input_event,
+ ui::LatencyInfo* latency_info) {
+ if (override_result_)
+ return result_;
+ return content::InputHandlerManager::HandleInputEvent(routing_id, input_event,
+ latency_info);
+}
+
+// Empty implementation of InputHandlerManagerClient.
+class TestInputHandlerManagerClient
+ : public content::InputHandlerManagerClient {
+ public:
+ TestInputHandlerManagerClient() {}
+ ~TestInputHandlerManagerClient() override{};
+
+ // content::InputHandlerManagerClient:
+ void SetBoundHandler(const Handler& handler) override {}
+ void DidAddInputHandler(int routing_id) override {}
+ void DidRemoveInputHandler(int routing_id) override {}
+ void DidOverscroll(int routing_id,
+ const content::DidOverscrollParams& params) override {}
+ void DidStopFlinging(int routing_id) override {}
+ void NotifyInputEventHandled(int routing_id,
+ blink::WebInputEvent::Type type) override {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestInputHandlerManagerClient);
+};
+
+// Implementation of RenderWidget for testing, performs no initialization.
+class TestRenderWidget : public content::RenderWidget {
+ public:
+ explicit TestRenderWidget(content::CompositorDependencies* compositor_deps)
+ : content::RenderWidget(compositor_deps,
+ blink::WebPopupTypeNone,
+ blink::WebScreenInfo(),
+ true,
+ false,
+ false) {}
+
+ protected:
+ ~TestRenderWidget() override {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestRenderWidget);
+};
+
+// Test override of RenderWidgetInputHandler to allow the control of
+// HandleInputEvent. This will perform no actions on input until a
+// RenderWidgetInputHandlerDelegate is set. Once set this will always ack
+// received events.
+class TestRenderWidgetInputHandler : public content::RenderWidgetInputHandler {
+ public:
+ TestRenderWidgetInputHandler(content::RenderWidget* render_widget);
+ ~TestRenderWidgetInputHandler() override {}
+
+ void set_delegate(content::RenderWidgetInputHandlerDelegate* delegate) {
+ delegate_ = delegate;
+ }
+ void set_state(content::InputEventAckState state) { state_ = state; }
+
+ // content::RenderWidgetInputHandler:
+ void HandleInputEvent(const blink::WebInputEvent& input_event,
+ const ui::LatencyInfo& latency_info,
+ content::InputEventDispatchType dispatch_type) override;
+
+ private:
+ // The input delegate which receives event acks.
+ content::RenderWidgetInputHandlerDelegate* delegate_;
+
+ // The result of input handling to send to |delegate_| during the ack.
+ content::InputEventAckState state_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestRenderWidgetInputHandler);
+};
+
+TestRenderWidgetInputHandler::TestRenderWidgetInputHandler(
+ content::RenderWidget* render_widget)
+ : content::RenderWidgetInputHandler(render_widget, render_widget),
+ delegate_(nullptr),
+ state_(content::InputEventAckState::INPUT_EVENT_ACK_STATE_UNKNOWN) {}
+
+void TestRenderWidgetInputHandler::HandleInputEvent(
+ const blink::WebInputEvent& input_event,
+ const ui::LatencyInfo& latency_info,
+ content::InputEventDispatchType dispatch_type) {
+ if (delegate_) {
+ scoped_ptr<content::InputEventAck> ack(
+ new content::InputEventAck(input_event.type, state_));
+ delegate_->OnInputEventAck(std::move(ack));
+ }
+}
+
+} // namespace
+
+namespace content {
+
+// Test suite for CompositorMusConnection, this does not setup a full renderer
+// environment. This does not establish a connection to a mus server, nor does
+// it initialize one.
+class CompositorMusConnectionTest : public testing::Test {
+ public:
+ CompositorMusConnectionTest() {}
+ ~CompositorMusConnectionTest() override {}
+
+ // Returns a valid key event, so that it can be converted to a web event by
+ // CompositorMusConnection.
+ scoped_ptr<ui::Event> GenerateKeyEvent();
+
+ // Calls CompositorMusConnection::OnWindowInputEvent.
+ void OnWindowInputEvent(mus::Window* window,
+ const ui::Event& event,
+ scoped_ptr<base::Callback<void(bool)>>* ack_callback);
+
+ // Confirms the state of pending tasks enqueued on each task runner, and runs
+ // until idle.
+ void VerifyAndRunQueues(bool main_task_runner_enqueued,
+ bool compositor_task_runner_enqueued);
+
+ CompositorMusConnection* compositor_connection() {
+ return compositor_connection_.get();
+ }
+ RenderWidgetMusConnection* connection() { return connection_; }
+ TestInputHandlerManager* input_handler_manager() {
+ return input_handler_manager_.get();
+ }
+ TestRenderWidgetInputHandler* render_widget_input_handler() {
+ return render_widget_input_handler_.get();
+ }
+
+ // testing::Test:
+ void SetUp() override;
+ void TearDown() override;
+
+ private:
+ // Mocks/Fakes of the testing environment.
+ TestInputHandlerManagerClient input_handler_manager_client_;
+ FakeCompositorDependencies compositor_dependencies_;
+ FakeRendererScheduler renderer_scheduler_;
+ MockRenderThread render_thread_;
+ scoped_refptr<TestRenderWidget> render_widget_;
+ mojo::InterfaceRequest<mus::mojom::WindowTreeClient> request_;
+
+ // Not owned, RenderWidgetMusConnection tracks in static state. Cleared during
+ // TearDown.
+ RenderWidgetMusConnection* connection_;
+
+ // Test versions of task runners, see VerifyAndRunQueues to use in testing.
+ scoped_refptr<base::TestSimpleTaskRunner> main_task_runner_;
+ scoped_refptr<base::TestSimpleTaskRunner> compositor_task_runner_;
+
+ // Actual CompositorMusConnection for testing.
+ scoped_refptr<CompositorMusConnection> compositor_connection_;
+
+ // Test implementations, to control input given to |compositor_connection_|.
+ scoped_ptr<TestInputHandlerManager> input_handler_manager_;
+ scoped_ptr<TestRenderWidgetInputHandler> render_widget_input_handler_;
+
+ DISALLOW_COPY_AND_ASSIGN(CompositorMusConnectionTest);
+};
+
+scoped_ptr<ui::Event> CompositorMusConnectionTest::GenerateKeyEvent() {
+ return scoped_ptr<ui::Event>(new ui::KeyEvent(
+ ui::ET_KEY_PRESSED, ui::KeyboardCode::VKEY_A, ui::EF_NONE));
+}
+
+void CompositorMusConnectionTest::OnWindowInputEvent(
+ mus::Window* window,
+ const ui::Event& event,
+ scoped_ptr<base::Callback<void(bool)>>* ack_callback) {
+ compositor_connection_->OnWindowInputEvent(window, event, ack_callback);
+}
+
+void CompositorMusConnectionTest::VerifyAndRunQueues(
+ bool main_task_runner_enqueued,
+ bool compositor_task_runner_enqueued) {
+ // Run through the enqueued actions.
+ EXPECT_EQ(main_task_runner_enqueued, main_task_runner_->HasPendingTask());
+ main_task_runner_->RunUntilIdle();
+
+ EXPECT_EQ(compositor_task_runner_enqueued,
+ compositor_task_runner_->HasPendingTask());
+ compositor_task_runner_->RunUntilIdle();
+}
+
+void CompositorMusConnectionTest::SetUp() {
+ testing::Test::SetUp();
+
+ main_task_runner_ = new base::TestSimpleTaskRunner();
+ compositor_task_runner_ = new base::TestSimpleTaskRunner();
+
+ input_handler_manager_.reset(new TestInputHandlerManager(
+ compositor_task_runner_, &input_handler_manager_client_,
+ &renderer_scheduler_));
+
+ const int routing_id = 42;
+ compositor_connection_ = new CompositorMusConnection(
+ routing_id, main_task_runner_, compositor_task_runner_,
+ std::move(request_), input_handler_manager_.get());
+
+ // CompositorMusConnection attempts to create connection to the non-existant
+ // server. Clear that.
+ compositor_task_runner_->ClearPendingTasks();
+
+ render_widget_ = new TestRenderWidget(&compositor_dependencies_);
+ render_widget_input_handler_.reset(
+ new TestRenderWidgetInputHandler(render_widget_.get()));
+ connection_ = RenderWidgetMusConnection::GetOrCreate(routing_id);
+ connection_->SetInputHandler(render_widget_input_handler_.get());
+}
+
+void CompositorMusConnectionTest::TearDown() {
+ // Clear static state.
+ connection_->OnConnectionLost();
+ testing::Test::TearDown();
+}
+
+// Tests that for events which the renderer will ack, yet not consume, that
+// CompositorMusConnection consumes the ack during OnWindowInputEvent, and calls
+// it with the correct state once processed.
+TEST_F(CompositorMusConnectionTest, NotConsumed) {
+ TestRenderWidgetInputHandler* input_handler = render_widget_input_handler();
+ input_handler->set_delegate(connection());
+ input_handler->set_state(
+ InputEventAckState::INPUT_EVENT_ACK_STATE_NOT_CONSUMED);
+
+ mus::TestWindow test_window;
+ scoped_ptr<ui::Event> event(GenerateKeyEvent());
+ scoped_refptr<TestCallback> test_callback(new TestCallback);
+ scoped_ptr<base::Callback<void(bool)>> ack_callback(
+ new base::Callback<void(bool)>(
+ base::Bind(&::TestCallback::BoolCallback, test_callback)));
+
+ OnWindowInputEvent(&test_window, *event.get(), &ack_callback);
+ // OnWindowInputEvent is expected to clear the callback if it plans on
+ // handling the ack.
+ EXPECT_FALSE(ack_callback.get());
+
+ VerifyAndRunQueues(true, true);
+
+ // The ack callback should have been called
+ EXPECT_TRUE(test_callback->called());
+ EXPECT_FALSE(test_callback->result());
+}
+
+// Tests that for events which the renderer will ack, and consume, that
+// CompositorMusConnection consumes the ack during OnWindowInputEvent, and calls
+// it with the correct state once processed.
+TEST_F(CompositorMusConnectionTest, Consumed) {
+ TestRenderWidgetInputHandler* input_handler = render_widget_input_handler();
+ input_handler->set_delegate(connection());
+ input_handler->set_state(InputEventAckState::INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ mus::TestWindow test_window;
+ scoped_ptr<ui::Event> event(GenerateKeyEvent());
+ scoped_refptr<TestCallback> test_callback(new TestCallback);
+ scoped_ptr<base::Callback<void(bool)>> ack_callback(
+ new base::Callback<void(bool)>(
+ base::Bind(&::TestCallback::BoolCallback, test_callback)));
+
+ OnWindowInputEvent(&test_window, *event.get(), &ack_callback);
+ // OnWindowInputEvent is expected to clear the callback if it plans on
+ // handling the ack.
+ EXPECT_FALSE(ack_callback.get());
+
+ VerifyAndRunQueues(true, true);
+
+ // The ack callback should have been called
+ EXPECT_TRUE(test_callback->called());
+ EXPECT_TRUE(test_callback->result());
+}
+
+// Tests that when the RenderWidgetInputHandler does not ack before a new event
+// arrives, that only the most recent ack is fired.
+TEST_F(CompositorMusConnectionTest, LostAck) {
+ mus::TestWindow test_window;
+ scoped_ptr<ui::Event> event1(GenerateKeyEvent());
+ scoped_refptr<TestCallback> test_callback1(new TestCallback);
+ scoped_ptr<base::Callback<void(bool)>> ack_callback1(
+ new base::Callback<void(bool)>(
+ base::Bind(&::TestCallback::BoolCallback, test_callback1)));
+
+ OnWindowInputEvent(&test_window, *event1.get(), &ack_callback1);
+ EXPECT_FALSE(ack_callback1.get());
+ // When simulating the timeout the ack is never enqueued
+ VerifyAndRunQueues(true, false);
+
+ // Setting a delegate will lead to the next event being acked. Having a
+ // cleared queue simulates the input handler timing out on an event.
+ TestRenderWidgetInputHandler* input_handler = render_widget_input_handler();
+ input_handler->set_delegate(connection());
+ input_handler->set_state(InputEventAckState::INPUT_EVENT_ACK_STATE_CONSUMED);
+
+ scoped_ptr<ui::Event> event2(GenerateKeyEvent());
+ scoped_refptr<TestCallback> test_callback2(new TestCallback);
+ scoped_ptr<base::Callback<void(bool)>> ack_callback2(
+ new base::Callback<void(bool)>(
+ base::Bind(&::TestCallback::BoolCallback, test_callback2)));
+ OnWindowInputEvent(&test_window, *event2.get(), &ack_callback2);
+ EXPECT_FALSE(ack_callback2.get());
+
+ VerifyAndRunQueues(true, true);
+
+ // Only the most recent ack was called.
+ EXPECT_FALSE(test_callback1->called());
+ EXPECT_TRUE(test_callback2->called());
+ EXPECT_TRUE(test_callback2->result());
+}
+
+// Tests that when an input handler consumes the event, that
+// CompositorMusConnection does not consume the ack, nor calls it.
+TEST_F(CompositorMusConnectionTest, InputHandlerConsumes) {
+ input_handler_manager()->SetHandleInputEventResult(
+ InputEventAckState::INPUT_EVENT_ACK_STATE_CONSUMED);
+ mus::TestWindow test_window;
+ scoped_ptr<ui::Event> event(GenerateKeyEvent());
+ scoped_refptr<TestCallback> test_callback(new TestCallback);
+ scoped_ptr<base::Callback<void(bool)>> ack_callback(
+ new base::Callback<void(bool)>(
+ base::Bind(&::TestCallback::BoolCallback, test_callback)));
+
+ OnWindowInputEvent(&test_window, *event.get(), &ack_callback);
+
+ EXPECT_TRUE(ack_callback.get());
+ VerifyAndRunQueues(false, false);
+ EXPECT_FALSE(test_callback->called());
+}
+
+// Tests that when the renderer will not ack an event, that
+// CompositorMusConnection does not consume the ack, nor calls it.
+TEST_F(CompositorMusConnectionTest, RendererWillNotSendAck) {
+ mus::TestWindow test_window;
+ ui::PointerEvent event(ui::ET_POINTER_DOWN,
+ ui::EventPointerType::POINTER_TYPE_MOUSE, gfx::Point(),
+ gfx::Point(), ui::EF_NONE, 0, ui::EventTimeForNow());
+
+ scoped_refptr<TestCallback> test_callback(new TestCallback);
+ scoped_ptr<base::Callback<void(bool)>> ack_callback(
+ new base::Callback<void(bool)>(
+ base::Bind(&::TestCallback::BoolCallback, test_callback)));
+
+ OnWindowInputEvent(&test_window, event, &ack_callback);
+ EXPECT_TRUE(ack_callback.get());
+
+ VerifyAndRunQueues(true, false);
+ EXPECT_FALSE(test_callback->called());
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/mus/render_widget_mus_connection.cc b/chromium/content/renderer/mus/render_widget_mus_connection.cc
index d34fad9e674..e0f1c74989c 100644
--- a/chromium/content/renderer/mus/render_widget_mus_connection.cc
+++ b/chromium/content/renderer/mus/render_widget_mus_connection.cc
@@ -20,7 +20,7 @@
#include "content/renderer/render_view_impl.h"
#include "mojo/converters/geometry/geometry_type_converters.h"
#include "mojo/converters/surfaces/surfaces_utils.h"
-#include "mojo/shell/public/cpp/application_impl.h"
+#include "mojo/shell/public/cpp/connector.h"
namespace content {
@@ -49,7 +49,7 @@ scoped_ptr<cc::OutputSurface> RenderWidgetMusConnection::CreateOutputSurface() {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(!window_surface_binding_);
mus::mojom::GpuPtr gpu_service;
- MojoShellConnection::Get()->GetApplication()->ConnectToService("mojo:mus",
+ MojoShellConnection::Get()->GetConnector()->ConnectToInterface("mojo:mus",
&gpu_service);
mus::mojom::CommandBufferPtr cb;
gpu_service->CreateOffscreenGLES2Context(GetProxy(&cb));
@@ -106,6 +106,13 @@ void RenderWidgetMusConnection::ObserveWheelEventAndResult(
NOTIMPLEMENTED();
}
+void RenderWidgetMusConnection::ObserveGestureEventAndResult(
+ const blink::WebGestureEvent& gesture_event,
+ const gfx::Vector2dF& wheel_unused_delta,
+ bool event_processed) {
+ NOTIMPLEMENTED();
+}
+
void RenderWidgetMusConnection::OnDidHandleKeyEvent() {
NOTIMPLEMENTED();
}
@@ -118,11 +125,16 @@ void RenderWidgetMusConnection::OnDidOverscroll(
void RenderWidgetMusConnection::OnInputEventAck(
scoped_ptr<InputEventAck> input_event_ack) {
DCHECK(!pending_ack_.is_null());
- // TODO(fsamuel): Use the state in |input_event_ack|.
- pending_ack_.Run();
+ pending_ack_.Run(input_event_ack->state ==
+ InputEventAckState::INPUT_EVENT_ACK_STATE_CONSUMED);
pending_ack_.Reset();
}
+void RenderWidgetMusConnection::NotifyInputEventHandled(
+ blink::WebInputEvent::Type handled_type) {
+ NOTIMPLEMENTED();
+}
+
void RenderWidgetMusConnection::SetInputHandler(
RenderWidgetInputHandler* input_handler) {
DCHECK(!input_handler_);
@@ -156,12 +168,12 @@ void RenderWidgetMusConnection::OnConnectionLost() {
void RenderWidgetMusConnection::OnWindowInputEvent(
scoped_ptr<blink::WebInputEvent> input_event,
- const base::Closure& ack) {
+ const base::Callback<void(bool)>& ack) {
DCHECK(thread_checker_.CalledOnValidThread());
// If we don't yet have a RenderWidgetInputHandler then we don't yet have
// an initialized RenderWidget.
if (!input_handler_) {
- ack.Run();
+ ack.Run(false);
return;
}
// TODO(fsamuel): It would be nice to add this DCHECK but the reality is an
@@ -171,7 +183,8 @@ void RenderWidgetMusConnection::OnWindowInputEvent(
pending_ack_ = ack;
// TODO(fsamuel, sadrul): Track real latency info.
ui::LatencyInfo latency_info;
- input_handler_->HandleInputEvent(*input_event, latency_info);
+ input_handler_->HandleInputEvent(*input_event, latency_info,
+ DISPATCH_TYPE_BLOCKING);
}
} // namespace content
diff --git a/chromium/content/renderer/mus/render_widget_mus_connection.h b/chromium/content/renderer/mus/render_widget_mus_connection.h
index c6bb3626a94..0792095c7e0 100644
--- a/chromium/content/renderer/mus/render_widget_mus_connection.h
+++ b/chromium/content/renderer/mus/render_widget_mus_connection.h
@@ -9,6 +9,7 @@
#include "base/threading/thread_checker.h"
#include "cc/output/output_surface.h"
#include "components/mus/public/cpp/window_surface.h"
+#include "content/common/content_export.h"
#include "content/renderer/input/render_widget_input_handler_delegate.h"
#include "content/renderer/mus/compositor_mus_connection.h"
@@ -17,7 +18,8 @@ namespace content {
class InputHandlerManager;
// Use on main thread.
-class RenderWidgetMusConnection : public RenderWidgetInputHandlerDelegate {
+class CONTENT_EXPORT RenderWidgetMusConnection
+ : public RenderWidgetInputHandlerDelegate {
public:
// Bind to a WindowTreeClient request.
void Bind(mojo::InterfaceRequest<mus::mojom::WindowTreeClient> request);
@@ -33,6 +35,7 @@ class RenderWidgetMusConnection : public RenderWidgetInputHandlerDelegate {
private:
friend class CompositorMusConnection;
+ friend class CompositorMusConnectionTest;
explicit RenderWidgetMusConnection(int routing_id);
~RenderWidgetMusConnection() override;
@@ -43,9 +46,14 @@ class RenderWidgetMusConnection : public RenderWidgetInputHandlerDelegate {
void ObserveWheelEventAndResult(const blink::WebMouseWheelEvent& wheel_event,
const gfx::Vector2dF& wheel_unused_delta,
bool event_processed) override;
+ void ObserveGestureEventAndResult(const blink::WebGestureEvent& gesture_event,
+ const gfx::Vector2dF& gesture_unused_delta,
+ bool event_processed) override;
void OnDidHandleKeyEvent() override;
void OnDidOverscroll(const DidOverscrollParams& params) override;
void OnInputEventAck(scoped_ptr<InputEventAck> input_event_ack) override;
+ void NotifyInputEventHandled(
+ blink::WebInputEvent::Type handled_type) override;
void SetInputHandler(RenderWidgetInputHandler* input_handler) override;
void UpdateTextInputState(ShowIme show_ime,
ChangeSource change_source) override;
@@ -54,14 +62,14 @@ class RenderWidgetMusConnection : public RenderWidgetInputHandlerDelegate {
void OnConnectionLost();
void OnWindowInputEvent(scoped_ptr<blink::WebInputEvent> input_event,
- const base::Closure& ack);
+ const base::Callback<void(bool)>& ack);
const int routing_id_;
RenderWidgetInputHandler* input_handler_;
scoped_ptr<mus::WindowSurfaceBinding> window_surface_binding_;
scoped_refptr<CompositorMusConnection> compositor_mus_connection_;
- base::Closure pending_ack_;
+ base::Callback<void(bool)> pending_ack_;
// Used to verify single threaded access.
base::ThreadChecker thread_checker_;
diff --git a/chromium/content/renderer/mus/render_widget_window_tree_client_factory.cc b/chromium/content/renderer/mus/render_widget_window_tree_client_factory.cc
index 1451490f322..04f5a522b2f 100644
--- a/chromium/content/renderer/mus/render_widget_window_tree_client_factory.cc
+++ b/chromium/content/renderer/mus/render_widget_window_tree_client_factory.cc
@@ -12,8 +12,8 @@
#include "content/common/render_widget_window_tree_client_factory.mojom.h"
#include "content/public/common/mojo_shell_connection.h"
#include "content/renderer/mus/render_widget_mus_connection.h"
-#include "mojo/common/weak_binding_set.h"
-#include "mojo/shell/public/cpp/application_connection.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/shell/public/cpp/connection.h"
#include "mojo/shell/public/cpp/interface_factory.h"
#include "url/gurl.h"
@@ -37,14 +37,13 @@ class RenderWidgetWindowTreeClientFactoryImpl
private:
// MojoShellConnection::Listener implementation:
- bool ConfigureIncomingConnection(
- mojo::ApplicationConnection* connection) override {
- connection->AddService<mojom::RenderWidgetWindowTreeClientFactory>(this);
+ bool AcceptConnection(mojo::Connection* connection) override {
+ connection->AddInterface<mojom::RenderWidgetWindowTreeClientFactory>(this);
return true;
}
// mojo::InterfaceFactory<mojom::RenderWidgetWindowTreeClientFactory>:
- void Create(mojo::ApplicationConnection* connection,
+ void Create(mojo::Connection* connection,
mojo::InterfaceRequest<mojom::RenderWidgetWindowTreeClientFactory>
request) override {
bindings_.AddBinding(this, std::move(request));
@@ -59,7 +58,7 @@ class RenderWidgetWindowTreeClientFactoryImpl
connection->Bind(std::move(request));
}
- mojo::WeakBindingSet<mojom::RenderWidgetWindowTreeClientFactory> bindings_;
+ mojo::BindingSet<mojom::RenderWidgetWindowTreeClientFactory> bindings_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetWindowTreeClientFactoryImpl);
};
diff --git a/chromium/content/renderer/notification_permission_dispatcher.cc b/chromium/content/renderer/notification_permission_dispatcher.cc
index 9c2f767df3a..f4ce9d40c87 100644
--- a/chromium/content/renderer/notification_permission_dispatcher.cc
+++ b/chromium/content/renderer/notification_permission_dispatcher.cc
@@ -9,9 +9,8 @@
#include "base/bind.h"
#include "content/public/common/service_registry.h"
#include "content/public/renderer/render_frame.h"
+#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
-#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
#include "third_party/WebKit/public/web/modules/notifications/WebNotificationPermissionCallback.h"
using blink::WebNotificationPermissionCallback;
@@ -37,8 +36,7 @@ void NotificationPermissionDispatcher::RequestPermission(
// base::Unretained is safe here because the Mojo channel, with associated
// callbacks, will be deleted before the "this" instance is deleted.
permission_service_->RequestPermission(
- PERMISSION_NAME_NOTIFICATIONS, origin.toString().utf8(),
- blink::WebUserGestureIndicator::isProcessingUserGesture(),
+ blink::mojom::PermissionName::NOTIFICATIONS, origin.toString().utf8(),
base::Bind(&NotificationPermissionDispatcher::OnPermissionRequestComplete,
base::Unretained(this),
base::Passed(std::move(owned_callback))));
@@ -46,19 +44,19 @@ void NotificationPermissionDispatcher::RequestPermission(
void NotificationPermissionDispatcher::OnPermissionRequestComplete(
scoped_ptr<WebNotificationPermissionCallback> callback,
- PermissionStatus status) {
+ blink::mojom::PermissionStatus status) {
DCHECK(callback);
blink::WebNotificationPermission permission =
blink::WebNotificationPermissionDefault;
switch (status) {
- case PERMISSION_STATUS_GRANTED:
+ case blink::mojom::PermissionStatus::GRANTED:
permission = blink::WebNotificationPermissionAllowed;
break;
- case PERMISSION_STATUS_DENIED:
+ case blink::mojom::PermissionStatus::DENIED:
permission = blink::WebNotificationPermissionDenied;
break;
- case PERMISSION_STATUS_ASK:
+ case blink::mojom::PermissionStatus::ASK:
permission = blink::WebNotificationPermissionDefault;
break;
}
diff --git a/chromium/content/renderer/notification_permission_dispatcher.h b/chromium/content/renderer/notification_permission_dispatcher.h
index df23dee15b5..68002d73968 100644
--- a/chromium/content/renderer/notification_permission_dispatcher.h
+++ b/chromium/content/renderer/notification_permission_dispatcher.h
@@ -7,8 +7,8 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
-#include "content/common/permission_service.mojom.h"
#include "content/public/renderer/render_frame_observer.h"
+#include "third_party/WebKit/public/platform/modules/permissions/permission.mojom.h"
namespace blink {
class WebNotificationPermissionCallback;
@@ -34,9 +34,9 @@ class NotificationPermissionDispatcher : public RenderFrameObserver {
private:
void OnPermissionRequestComplete(
scoped_ptr<blink::WebNotificationPermissionCallback> callback,
- PermissionStatus status);
+ blink::mojom::PermissionStatus status);
- PermissionServicePtr permission_service_;
+ blink::mojom::PermissionServicePtr permission_service_;
DISALLOW_COPY_AND_ASSIGN(NotificationPermissionDispatcher);
};
diff --git a/chromium/content/renderer/npapi/plugin_channel_host.cc b/chromium/content/renderer/npapi/plugin_channel_host.cc
deleted file mode 100644
index 3f9eaf905d9..00000000000
--- a/chromium/content/renderer/npapi/plugin_channel_host.cc
+++ /dev/null
@@ -1,168 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/npapi/plugin_channel_host.h"
-
-#include <stddef.h>
-
-#include "base/metrics/histogram.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "content/child/child_process.h"
-#include "content/child/npapi/npobject_base.h"
-#include "content/child/plugin_messages.h"
-
-#if defined(OS_POSIX)
-#include "ipc/ipc_channel_posix.h"
-#endif
-
-#include "third_party/WebKit/public/web/WebBindings.h"
-
-// TODO(shess): Debugging for http://crbug.com/97285
-//
-// The hypothesis at #55 requires that RemoveRoute() be called between
-// sending ViewHostMsg_OpenChannelToPlugin to the browser, and calling
-// GetPluginChannelHost() on the result. This code detects that case
-// and stores the backtrace of the RemoveRoute() in a breakpad key.
-// The specific RemoveRoute() is not tracked (there could be multiple,
-// and which is the one can't be known until the open completes), but
-// the backtrace from any such nested call should be sufficient to
-// drive a repro.
-#if defined(OS_MACOSX)
-#include "base/debug/crash_logging.h"
-#include "base/debug/stack_trace.h"
-#include "base/strings/sys_string_conversions.h"
-
-namespace {
-
-// Breakpad key for the RemoveRoute() backtrace.
-const char* kRemoveRouteTraceKey = "remove_route_bt";
-
-// Breakpad key for the OnChannelError() backtrace.
-const char* kChannelErrorTraceKey = "channel_error_bt";
-
-// GetRemoveTrackingFlag() exposes this so that
-// WebPluginDelegateProxy::Initialize() can do scoped set/reset. When
-// true, RemoveRoute() knows WBDP::Initialize() is on the stack, and
-// records the backtrace.
-bool remove_tracking = false;
-
-} // namespace
-#endif
-
-namespace content {
-
-#if defined(OS_MACOSX)
-// static
-bool* PluginChannelHost::GetRemoveTrackingFlag() {
- return &remove_tracking;
-}
-#endif
-
-// static
-PluginChannelHost* PluginChannelHost::GetPluginChannelHost(
- const IPC::ChannelHandle& channel_handle,
- base::SingleThreadTaskRunner* ipc_task_runner) {
- PluginChannelHost* result =
- static_cast<PluginChannelHost*>(NPChannelBase::GetChannel(
- channel_handle, IPC::Channel::MODE_CLIENT, ClassFactory,
- ipc_task_runner, true, ChildProcess::current()->GetShutDownEvent()));
- return result;
-}
-
-PluginChannelHost::PluginChannelHost() : expecting_shutdown_(false) {
-}
-
-PluginChannelHost::~PluginChannelHost() {
-}
-
-bool PluginChannelHost::Init(base::SingleThreadTaskRunner* ipc_task_runner,
- bool create_pipe_now,
- base::WaitableEvent* shutdown_event) {
- return NPChannelBase::Init(ipc_task_runner, create_pipe_now, shutdown_event);
-}
-
-int PluginChannelHost::GenerateRouteID() {
- int route_id = MSG_ROUTING_NONE;
- Send(new PluginMsg_GenerateRouteID(&route_id));
-
- return route_id;
-}
-
-void PluginChannelHost::AddRoute(int route_id,
- IPC::Listener* listener,
- NPObjectBase* npobject) {
- NPChannelBase::AddRoute(route_id, listener, npobject);
-
- if (!npobject)
- proxies_[route_id] = listener;
-}
-
-void PluginChannelHost::RemoveRoute(int route_id) {
-#if defined(OS_MACOSX)
- if (remove_tracking) {
- base::debug::StackTrace trace;
- size_t count = 0;
- const void* const* addresses = trace.Addresses(&count);
- base::debug::SetCrashKeyFromAddresses(
- kRemoveRouteTraceKey, addresses, count);
- }
-#endif
-
- proxies_.erase(route_id);
- NPChannelBase::RemoveRoute(route_id);
-}
-
-bool PluginChannelHost::OnControlMessageReceived(const IPC::Message& message) {
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(PluginChannelHost, message)
- IPC_MESSAGE_HANDLER(PluginHostMsg_SetException, OnSetException)
- IPC_MESSAGE_HANDLER(PluginHostMsg_PluginShuttingDown, OnPluginShuttingDown)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- DCHECK(handled);
- return handled;
-}
-
-void PluginChannelHost::OnSetException(const std::string& message) {
- blink::WebBindings::setException(NULL, message.c_str());
-}
-
-void PluginChannelHost::OnPluginShuttingDown() {
- expecting_shutdown_ = true;
-}
-
-bool PluginChannelHost::Send(IPC::Message* msg) {
- if (msg->is_sync()) {
- base::TimeTicks start_time(base::TimeTicks::Now());
- bool result = NPChannelBase::Send(msg);
- UMA_HISTOGRAM_TIMES("Plugin.SyncMessageTime",
- base::TimeTicks::Now() - start_time);
- return result;
- }
- return NPChannelBase::Send(msg);
-}
-
-void PluginChannelHost::OnChannelError() {
-#if defined(OS_MACOSX)
- if (remove_tracking) {
- base::debug::StackTrace trace;
- size_t count = 0;
- const void* const* addresses = trace.Addresses(&count);
- base::debug::SetCrashKeyFromAddresses(
- kChannelErrorTraceKey, addresses, count);
- }
-#endif
-
- NPChannelBase::OnChannelError();
-
- for (ProxyMap::iterator iter = proxies_.begin();
- iter != proxies_.end(); iter++) {
- iter->second->OnChannelError();
- }
-
- proxies_.clear();
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/npapi/plugin_channel_host.h b/chromium/content/renderer/npapi/plugin_channel_host.h
deleted file mode 100644
index 8494f640083..00000000000
--- a/chromium/content/renderer/npapi/plugin_channel_host.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_NPAPI_PLUGIN_CHANNEL_HOST_H_
-#define CONTENT_RENDERER_NPAPI_PLUGIN_CHANNEL_HOST_H_
-
-#include "base/containers/hash_tables.h"
-#include "base/macros.h"
-#include "build/build_config.h"
-#include "content/child/npapi/np_channel_base.h"
-#include "ipc/ipc_channel_handle.h"
-
-namespace content {
-class NPObjectBase;
-
-// Encapsulates an IPC channel between the renderer and one plugin process.
-// On the plugin side there's a corresponding PluginChannel.
-class PluginChannelHost : public NPChannelBase {
- public:
-#if defined(OS_MACOSX)
- // TODO(shess): Debugging for http://crbug.com/97285 . See comment
- // in plugin_channel_host.cc.
- static bool* GetRemoveTrackingFlag();
-#endif
- static PluginChannelHost* GetPluginChannelHost(
- const IPC::ChannelHandle& channel_handle,
- base::SingleThreadTaskRunner* ipc_task_runner);
-
- bool Init(base::SingleThreadTaskRunner* ipc_task_runner,
- bool create_pipe_now,
- base::WaitableEvent* shutdown_event) override;
-
- int GenerateRouteID() override;
-
- void AddRoute(int route_id, IPC::Listener* listener,
- NPObjectBase* npobject);
- void RemoveRoute(int route_id);
-
- // NPChannelBase override:
- bool Send(IPC::Message* msg) override;
-
- // IPC::Listener override
- void OnChannelError() override;
-
- static void Broadcast(IPC::Message* message) {
- NPChannelBase::Broadcast(message);
- }
-
- bool expecting_shutdown() { return expecting_shutdown_; }
-
- private:
- // Called on the render thread
- PluginChannelHost();
- ~PluginChannelHost() override;
-
- static NPChannelBase* ClassFactory() { return new PluginChannelHost(); }
-
- bool OnControlMessageReceived(const IPC::Message& message) override;
- void OnSetException(const std::string& message);
- void OnPluginShuttingDown();
-
- // Keep track of all the registered WebPluginDelegeProxies to
- // inform about OnChannelError
- typedef base::hash_map<int, IPC::Listener*> ProxyMap;
- ProxyMap proxies_;
-
- // True if we are expecting the plugin process to go away - in which case,
- // don't treat it as a crash.
- bool expecting_shutdown_;
-
- DISALLOW_COPY_AND_ASSIGN(PluginChannelHost);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_NPAPI_PLUGIN_CHANNEL_HOST_H_
diff --git a/chromium/content/renderer/npapi/webplugin_delegate_proxy.cc b/chromium/content/renderer/npapi/webplugin_delegate_proxy.cc
deleted file mode 100644
index 66f88217fd8..00000000000
--- a/chromium/content/renderer/npapi/webplugin_delegate_proxy.cc
+++ /dev/null
@@ -1,1088 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/npapi/webplugin_delegate_proxy.h"
-
-#include <stddef.h>
-
-#include <algorithm>
-
-#include "base/auto_reset.h"
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/process/process.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/version.h"
-#include "build/build_config.h"
-#include "cc/resources/shared_bitmap.h"
-#include "content/child/child_process.h"
-#include "content/child/child_shared_bitmap_manager.h"
-#include "content/child/npapi/npobject_proxy.h"
-#include "content/child/npapi/npobject_stub.h"
-#include "content/child/npapi/npobject_util.h"
-#include "content/child/npapi/webplugin_resource_client.h"
-#include "content/child/plugin_messages.h"
-#include "content/common/content_constants_internal.h"
-#include "content/common/cursors/webcursor.h"
-#include "content/common/frame_messages.h"
-#include "content/common/view_messages.h"
-#include "content/public/renderer/content_renderer_client.h"
-#include "content/renderer/npapi/plugin_channel_host.h"
-#include "content/renderer/npapi/webplugin_impl.h"
-#include "content/renderer/render_thread_impl.h"
-#include "content/renderer/render_view_impl.h"
-#include "content/renderer/sad_plugin.h"
-#include "ipc/ipc_channel_handle.h"
-#include "net/base/mime_util.h"
-#include "skia/ext/platform_canvas.h"
-#include "third_party/WebKit/public/platform/WebDragData.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
-#include "third_party/WebKit/public/web/WebDocument.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
-#include "third_party/WebKit/public/web/WebView.h"
-#include "ui/gfx/blit.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gfx/skia_util.h"
-
-#if defined(OS_POSIX)
-#include "ipc/ipc_channel_posix.h"
-#endif
-
-#if defined(OS_WIN)
-#include "base/win/scoped_handle.h"
-#include "content/public/common/sandbox_init.h"
-#endif
-
-using blink::WebBindings;
-using blink::WebCursorInfo;
-using blink::WebDragData;
-using blink::WebInputEvent;
-using blink::WebString;
-using blink::WebView;
-
-namespace content {
-
-namespace {
-
-class ScopedLogLevel {
- public:
- explicit ScopedLogLevel(int level);
- ~ScopedLogLevel();
-
- private:
- int old_level_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedLogLevel);
-};
-
-ScopedLogLevel::ScopedLogLevel(int level)
- : old_level_(logging::GetMinLogLevel()) {
- logging::SetMinLogLevel(level);
-}
-
-ScopedLogLevel::~ScopedLogLevel() {
- logging::SetMinLogLevel(old_level_);
-}
-
-// Proxy for WebPluginResourceClient. The object owns itself after creation,
-// deleting itself after its callback has been called.
-class ResourceClientProxy : public WebPluginResourceClient {
- public:
- ResourceClientProxy(PluginChannelHost* channel, int instance_id)
- : channel_(channel), instance_id_(instance_id), resource_id_(0) {
- }
-
- ~ResourceClientProxy() override {}
-
- // PluginResourceClient implementation:
- void WillSendRequest(const GURL& url, int http_status_code) override {
- DCHECK(channel_.get() != NULL);
- channel_->Send(new PluginMsg_WillSendRequest(
- instance_id_, resource_id_, url, http_status_code));
- }
-
- void DidReceiveResponse(const std::string& mime_type,
- const std::string& headers,
- uint32_t expected_length,
- uint32_t last_modified,
- bool request_is_seekable) override {
- DCHECK(channel_.get() != NULL);
- PluginMsg_DidReceiveResponseParams params;
- params.id = resource_id_;
- params.mime_type = mime_type;
- params.headers = headers;
- params.expected_length = expected_length;
- params.last_modified = last_modified;
- params.request_is_seekable = request_is_seekable;
- // Grab a reference on the underlying channel so it does not get
- // deleted from under us.
- scoped_refptr<PluginChannelHost> channel_ref(channel_);
- channel_->Send(new PluginMsg_DidReceiveResponse(instance_id_, params));
- }
-
- void DidReceiveData(const char* buffer,
- int length,
- int data_offset) override {
- DCHECK(channel_.get() != NULL);
- DCHECK_GT(length, 0);
- std::vector<char> data;
- data.resize(static_cast<size_t>(length));
- memcpy(&data.front(), buffer, length);
- // Grab a reference on the underlying channel so it does not get
- // deleted from under us.
- scoped_refptr<PluginChannelHost> channel_ref(channel_);
- channel_->Send(new PluginMsg_DidReceiveData(instance_id_, resource_id_,
- data, data_offset));
- }
-
- void DidFinishLoading(unsigned long resource_id) override {
- DCHECK(channel_.get() != NULL);
- DCHECK_EQ(resource_id, resource_id_);
- channel_->Send(new PluginMsg_DidFinishLoading(instance_id_, resource_id_));
- channel_ = NULL;
- base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
- }
-
- void DidFail(unsigned long resource_id) override {
- DCHECK(channel_.get() != NULL);
- DCHECK_EQ(resource_id, resource_id_);
- channel_->Send(new PluginMsg_DidFail(instance_id_, resource_id_));
- channel_ = NULL;
- base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
- }
-
- int ResourceId() override { return resource_id_; }
-
- private:
- scoped_refptr<PluginChannelHost> channel_;
- int instance_id_;
- unsigned long resource_id_;
-};
-
-} // namespace
-
-WebPluginDelegateProxy::WebPluginDelegateProxy(
- WebPluginImpl* plugin,
- const std::string& mime_type,
- const base::WeakPtr<RenderViewImpl>& render_view,
- RenderFrameImpl* render_frame)
- : render_view_(render_view),
- render_frame_(render_frame),
- plugin_(plugin),
- uses_shared_bitmaps_(false),
-#if defined(OS_MACOSX)
- uses_compositor_(false),
-#elif defined(OS_WIN)
- dummy_activation_window_(NULL),
-#endif
- window_(gfx::kNullPluginWindow),
- mime_type_(mime_type),
- instance_id_(MSG_ROUTING_NONE),
- npobject_(NULL),
- npp_(new NPP_t),
- sad_plugin_(NULL),
- invalidate_pending_(false),
- transparent_(false),
- front_buffer_index_(0),
- page_url_(render_view_->webview()->mainFrame()->document().url()) {
-}
-
-WebPluginDelegateProxy::~WebPluginDelegateProxy() {
- if (npobject_)
- WebBindings::releaseObject(npobject_);
-}
-
-WebPluginDelegateProxy::SharedBitmap::SharedBitmap() {}
-
-WebPluginDelegateProxy::SharedBitmap::~SharedBitmap() {}
-
-void WebPluginDelegateProxy::PluginDestroyed() {
-#if defined(OS_MACOSX) || defined(OS_WIN)
- // Ensure that the renderer doesn't think the plugin still has focus.
- if (render_view_)
- render_view_->PluginFocusChanged(false, instance_id_);
-#endif
-
-#if defined(OS_WIN)
- if (dummy_activation_window_ && render_view_) {
- render_view_->Send(new ViewHostMsg_WindowlessPluginDummyWindowDestroyed(
- render_view_->routing_id(), dummy_activation_window_));
- }
- dummy_activation_window_ = NULL;
-#endif
-
- if (window_)
- WillDestroyWindow();
-
- if (render_view_.get())
- render_view_->UnregisterPluginDelegate(this);
-
- if (channel_host_.get()) {
- Send(new PluginMsg_DestroyInstance(instance_id_));
-
- // Must remove the route after sending the destroy message, rather than
- // before, since RemoveRoute can lead to all the outstanding NPObjects
- // being told the channel went away if this was the last instance.
- channel_host_->RemoveRoute(instance_id_);
-
- // Remove the mapping between our instance-Id and NPP identifiers, used by
- // the channel to track object ownership, before releasing it.
- channel_host_->RemoveMappingForNPObjectOwner(instance_id_);
-
- // Release the channel host now. If we are is the last reference to the
- // channel, this avoids a race where this renderer asks a new connection to
- // the same plugin between now and the time 'this' is actually deleted.
- // Destroying the channel host is what releases the channel name -> FD
- // association on POSIX, and if we ask for a new connection before it is
- // released, the plugin will give us a new FD, and we'll assert when trying
- // to associate it with the channel name.
- channel_host_ = NULL;
- }
-
- plugin_ = NULL;
-
- base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
-}
-
-bool WebPluginDelegateProxy::Initialize(
- const GURL& url,
- const std::vector<std::string>& arg_names,
- const std::vector<std::string>& arg_values,
- bool load_manually) {
- // TODO(shess): Attempt to work around http://crbug.com/97285 and
- // http://crbug.com/141055 by retrying the connection. Reports seem
- // to indicate that the plugin hasn't crashed, and that the problem
- // is not 100% persistent.
- const size_t kAttempts = 2;
-
- bool result = false;
- scoped_refptr<PluginChannelHost> channel_host;
- int instance_id = 0;
-
- for (size_t attempt = 0; !result && attempt < kAttempts; attempt++) {
-#if defined(OS_MACOSX)
- // TODO(shess): Debugging for http://crbug.com/97285 . See comment
- // in plugin_channel_host.cc.
- scoped_ptr<base::AutoReset<bool> > track_nested_removes(
- new base::AutoReset<bool>(PluginChannelHost::GetRemoveTrackingFlag(),
- true));
-#endif
-
- IPC::ChannelHandle channel_handle;
- if (!RenderThreadImpl::current()->Send(new FrameHostMsg_OpenChannelToPlugin(
- render_frame_->GetRoutingID(), url, page_url_, mime_type_,
- &channel_handle, &info_))) {
- continue;
- }
-
- if (channel_handle.name.empty()) {
- // We got an invalid handle. Either the plugin couldn't be found (which
- // shouldn't happen, since if we got here the plugin should exist) or the
- // plugin crashed on initialization.
- if (!info_.path.empty()) {
- render_view_->GetMainRenderFrame()->PluginCrashed(
- info_.path, base::kNullProcessId);
- LOG(ERROR) << "Plugin crashed on start";
-
- // Return true so that the plugin widget is created and we can paint the
- // crashed plugin there.
- return true;
- }
- LOG(ERROR) << "Plugin couldn't be found";
- return false;
- }
-
- channel_host = PluginChannelHost::GetPluginChannelHost(
- channel_handle, ChildProcess::current()->io_task_runner());
- if (!channel_host.get()) {
- LOG(ERROR) << "Couldn't get PluginChannelHost";
- continue;
- }
-#if defined(OS_MACOSX)
- track_nested_removes.reset();
-#endif
-
- {
- // TODO(bauerb): Debugging for http://crbug.com/141055.
- ScopedLogLevel log_level(-2); // Equivalent to --v=2
- result = channel_host->Send(new PluginMsg_CreateInstance(
- mime_type_, &instance_id));
- if (!result) {
- LOG(ERROR) << "Couldn't send PluginMsg_CreateInstance";
- continue;
- }
- }
- }
-
- // Failed too often, give up.
- if (!result)
- return false;
-
- channel_host_ = channel_host;
- instance_id_ = instance_id;
-
- channel_host_->AddRoute(instance_id_, this, NULL);
-
- // Inform the channel of the mapping between our instance-Id and dummy NPP
- // identifier, for use in object ownership tracking.
- channel_host_->AddMappingForNPObjectOwner(instance_id_, GetPluginNPP());
-
- // Now tell the PluginInstance in the plugin process to initialize.
- PluginMsg_Init_Params params;
- params.url = url;
- params.page_url = page_url_;
- params.arg_names = arg_names;
- params.arg_values = arg_values;
- params.host_render_view_routing_id = render_view_->routing_id();
- params.load_manually = load_manually;
-
- result = false;
- Send(new PluginMsg_Init(instance_id_, params, &transparent_, &result));
-
- if (!result)
- LOG(WARNING) << "PluginMsg_Init returned false";
-
- render_view_->RegisterPluginDelegate(this);
-
- return result;
-}
-
-bool WebPluginDelegateProxy::Send(IPC::Message* msg) {
- if (!channel_host_.get()) {
- DLOG(WARNING) << "dropping message because channel host is null";
- delete msg;
- return false;
- }
-
- return channel_host_->Send(msg);
-}
-
-bool WebPluginDelegateProxy::OnMessageReceived(const IPC::Message& msg) {
- GetContentClient()->SetActiveURL(page_url_);
-
- bool handled = true;
- IPC_BEGIN_MESSAGE_MAP(WebPluginDelegateProxy, msg)
- IPC_MESSAGE_HANDLER(PluginHostMsg_SetWindow, OnSetWindow)
- IPC_MESSAGE_HANDLER(PluginHostMsg_CancelResource, OnCancelResource)
- IPC_MESSAGE_HANDLER(PluginHostMsg_InvalidateRect, OnInvalidateRect)
- IPC_MESSAGE_HANDLER(PluginHostMsg_GetWindowScriptNPObject,
- OnGetWindowScriptNPObject)
- IPC_MESSAGE_HANDLER(PluginHostMsg_GetPluginElement, OnGetPluginElement)
- IPC_MESSAGE_HANDLER(PluginHostMsg_ResolveProxy, OnResolveProxy)
- IPC_MESSAGE_HANDLER(PluginHostMsg_SetCookie, OnSetCookie)
- IPC_MESSAGE_HANDLER(PluginHostMsg_GetCookies, OnGetCookies)
- IPC_MESSAGE_HANDLER(PluginHostMsg_CancelDocumentLoad, OnCancelDocumentLoad)
- IPC_MESSAGE_HANDLER(PluginHostMsg_DidStartLoading, OnDidStartLoading)
- IPC_MESSAGE_HANDLER(PluginHostMsg_DidStopLoading, OnDidStopLoading)
- IPC_MESSAGE_HANDLER(PluginHostMsg_DeferResourceLoading,
- OnDeferResourceLoading)
- IPC_MESSAGE_HANDLER(PluginHostMsg_URLRedirectResponse,
- OnURLRedirectResponse)
- IPC_MESSAGE_HANDLER(PluginHostMsg_CheckIfRunInsecureContent,
- OnCheckIfRunInsecureContent)
-#if defined(OS_WIN)
- IPC_MESSAGE_HANDLER(PluginHostMsg_SetWindowlessData, OnSetWindowlessData)
- IPC_MESSAGE_HANDLER(PluginHostMsg_NotifyIMEStatus, OnNotifyIMEStatus)
-#endif
-#if defined(OS_MACOSX)
- IPC_MESSAGE_HANDLER(PluginHostMsg_FocusChanged,
- OnFocusChanged);
- IPC_MESSAGE_HANDLER(PluginHostMsg_StartIme,
- OnStartIme);
- IPC_MESSAGE_HANDLER(PluginHostMsg_AcceleratedPluginEnabledRendering,
- OnAcceleratedPluginEnabledRendering)
- IPC_MESSAGE_HANDLER(PluginHostMsg_AcceleratedPluginAllocatedIOSurface,
- OnAcceleratedPluginAllocatedIOSurface)
- IPC_MESSAGE_HANDLER(PluginHostMsg_AcceleratedPluginSwappedIOSurface,
- OnAcceleratedPluginSwappedIOSurface)
-#endif
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
- DCHECK(handled);
- return handled;
-}
-
-void WebPluginDelegateProxy::OnChannelError() {
- if (plugin_) {
- if (window_) {
- // The actual WebPluginDelegate never got a chance to tell the WebPlugin
- // its window was going away. Do it on its behalf.
- WillDestroyWindow();
- }
- plugin_->Invalidate();
- }
- if (channel_host_.get() && !channel_host_->expecting_shutdown()) {
- render_view_->GetMainRenderFrame()->PluginCrashed(
- info_.path, channel_host_->peer_pid());
- }
-
-#if defined(OS_MACOSX) || defined(OS_WIN)
- // Ensure that the renderer doesn't think the plugin still has focus.
- if (render_view_)
- render_view_->PluginFocusChanged(false, instance_id_);
-#endif
-}
-
-static void CopySharedMemoryHandleForMessage(
- const base::SharedMemoryHandle& handle_in,
- base::SharedMemoryHandle* handle_out,
- base::ProcessId peer_pid) {
-#if defined(OS_POSIX)
- *handle_out = base::SharedMemory::DuplicateHandle(handle_in);
-#elif defined(OS_WIN)
- // On Windows we need to duplicate the handle for the plugin process.
- BrokerDuplicateSharedMemoryHandle(handle_in, peer_pid, handle_out);
-#else
-#error Shared memory copy not implemented.
-#endif
-}
-
-void WebPluginDelegateProxy::SendUpdateGeometry(
- bool bitmaps_changed) {
- if (!channel_host_.get())
- return;
-
- PluginMsg_UpdateGeometry_Param param;
- param.window_rect = plugin_rect_;
- param.clip_rect = clip_rect_;
- param.windowless_buffer0 = base::SharedMemory::NULLHandle();
- param.windowless_buffer1 = base::SharedMemory::NULLHandle();
- param.windowless_buffer_index = back_buffer_index();
-
-#if defined(OS_POSIX)
- // If we're using POSIX mmap'd TransportDIBs, sending the handle across
- // IPC establishes a new mapping rather than just sending a window ID,
- // so only do so if we've actually changed the shared memory bitmaps.
- if (bitmaps_changed)
-#endif
- {
- if (transport_stores_[0].bitmap)
- CopySharedMemoryHandleForMessage(
- transport_stores_[0].bitmap->shared_memory()->handle(),
- &param.windowless_buffer0, channel_host_->peer_pid());
-
- if (transport_stores_[1].bitmap)
- CopySharedMemoryHandleForMessage(
- transport_stores_[1].bitmap->shared_memory()->handle(),
- &param.windowless_buffer1, channel_host_->peer_pid());
- }
-
- IPC::Message* msg;
-#if defined(OS_WIN)
- if (UseSynchronousGeometryUpdates()) {
- msg = new PluginMsg_UpdateGeometrySync(instance_id_, param);
- } else // NOLINT
-#endif
- {
- msg = new PluginMsg_UpdateGeometry(instance_id_, param);
- msg->set_unblock(true);
- }
-
- Send(msg);
-}
-
-void WebPluginDelegateProxy::UpdateGeometry(const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect) {
- // window_rect becomes either a window in native windowing system
- // coords, or a backing buffer. In either case things will go bad
- // if the rectangle is very large.
- if (window_rect.width() < 0 || window_rect.width() > kMaxPluginSideLength ||
- window_rect.height() < 0 || window_rect.height() > kMaxPluginSideLength ||
- // We know this won't overflow due to above checks.
- static_cast<uint32_t>(window_rect.width()) *
- static_cast<uint32_t>(window_rect.height()) >
- kMaxPluginSize) {
- return;
- }
-
- plugin_rect_ = window_rect;
- clip_rect_ = clip_rect;
-
- bool bitmaps_changed = false;
-
- if (uses_shared_bitmaps_) {
- if (!front_buffer_canvas() ||
- (window_rect.width() !=
- front_buffer_canvas()->getBaseLayerSize().width() ||
- window_rect.height() !=
- front_buffer_canvas()->getBaseLayerSize().height()))
- {
- bitmaps_changed = true;
-
- // Create a shared memory section that the plugin paints into
- // asynchronously.
- ResetWindowlessBitmaps();
- if (!window_rect.IsEmpty()) {
- if (!CreateSharedBitmap(&transport_stores_[0].bitmap,
- &transport_stores_[0].canvas) ||
- !CreateSharedBitmap(&transport_stores_[1].bitmap,
- &transport_stores_[1].canvas)) {
- DCHECK(false);
- ResetWindowlessBitmaps();
- return;
- }
- }
- }
- }
-
- SendUpdateGeometry(bitmaps_changed);
-}
-
-void WebPluginDelegateProxy::ResetWindowlessBitmaps() {
- transport_stores_[0].bitmap.reset();
- transport_stores_[1].bitmap.reset();
-
- transport_stores_[0].canvas.reset();
- transport_stores_[1].canvas.reset();
- transport_store_painted_ = gfx::Rect();
- front_buffer_diff_ = gfx::Rect();
-}
-
-#if !defined(OS_WIN)
-static size_t BitmapSizeForPluginRect(const gfx::Rect& plugin_rect) {
- const size_t stride =
- skia::PlatformCanvasStrideForWidth(plugin_rect.width());
- return stride * plugin_rect.height();
-}
-
-bool WebPluginDelegateProxy::CreateLocalBitmap(
- std::vector<uint8_t>* memory,
- scoped_ptr<skia::PlatformCanvas>* canvas) {
- const size_t size = BitmapSizeForPluginRect(plugin_rect_);
- memory->resize(size);
- if (memory->size() != size)
- return false;
- canvas->reset(skia::CreatePlatformCanvas(
- plugin_rect_.width(), plugin_rect_.height(), true, &((*memory)[0]),
- skia::CRASH_ON_FAILURE));
- return true;
-}
-#endif
-
-bool WebPluginDelegateProxy::CreateSharedBitmap(
- scoped_ptr<SharedMemoryBitmap>* memory,
- scoped_ptr<skia::PlatformCanvas>* canvas) {
- *memory = ChildThreadImpl::current()
- ->shared_bitmap_manager()
- ->AllocateSharedMemoryBitmap(plugin_rect_.size());
- if (!memory->get())
- return false;
- DCHECK((*memory)->shared_memory());
-#if defined(OS_POSIX)
- canvas->reset(skia::CreatePlatformCanvas(
- plugin_rect_.width(), plugin_rect_.height(), true, (*memory)->pixels(),
- skia::RETURN_NULL_ON_FAILURE));
-#else
- canvas->reset(skia::CreatePlatformCanvas(
- plugin_rect_.width(), plugin_rect_.height(), true,
- (*memory)->shared_memory()->handle().GetHandle(),
- skia::RETURN_NULL_ON_FAILURE));
-#endif
- return !!canvas->get();
-}
-
-void WebPluginDelegateProxy::Paint(SkCanvas* canvas,
- const gfx::Rect& damaged_rect) {
- // Limit the damaged rectangle to whatever is contained inside the plugin
- // rectangle, as that's the rectangle that we'll actually draw.
- gfx::Rect rect = gfx::IntersectRects(damaged_rect, plugin_rect_);
-
- // If the plugin is no longer connected (channel crashed) draw a crashed
- // plugin bitmap
- if (!channel_host_.get() || !channel_host_->channel_valid()) {
- // Lazily load the sad plugin image.
- if (!sad_plugin_)
- sad_plugin_ = GetContentClient()->renderer()->GetSadPluginBitmap();
- if (sad_plugin_)
- PaintSadPlugin(canvas, plugin_rect_, *sad_plugin_);
- return;
- }
-
- if (!uses_shared_bitmaps_)
- return;
-
- // We got a paint before the plugin's coordinates, so there's no buffer to
- // copy from.
- if (!front_buffer_canvas())
- return;
-
- gfx::Rect offset_rect = rect;
- offset_rect.Offset(-plugin_rect_.x(), -plugin_rect_.y());
-
- // transport_store_painted_ is really a bounding box, so in principle this
- // check could falsely indicate that we don't need to paint offset_rect, but
- // in practice it works fine.
- if (!transport_store_painted_.Contains(offset_rect)) {
- Send(new PluginMsg_Paint(instance_id_, offset_rect));
- // Since the plugin is not blocked on the renderer in this context, there is
- // a chance that it will begin repainting the back-buffer before we complete
- // capturing the data. Buffer flipping would increase that risk because
- // geometry update is asynchronous, so we don't want to use buffer flipping
- // here.
- UpdateFrontBuffer(offset_rect, false);
- }
-
- const SkBitmap bitmap = skia::ReadPixels(front_buffer_canvas());
- SkPaint paint;
- paint.setXfermodeMode(
- transparent_ ? SkXfermode::kSrcATop_Mode : SkXfermode::kSrc_Mode);
- SkRect src_rect = gfx::RectToSkRect(offset_rect);
- canvas->drawBitmapRect(bitmap,
- src_rect,
- gfx::RectToSkRect(rect),
- &paint);
-
- if (invalidate_pending_) {
- // Only send the PaintAck message if this paint is in response to an
- // invalidate from the plugin, since this message acts as an access token
- // to ensure only one process is using the shared bitmap at a time.
- invalidate_pending_ = false;
- Send(new PluginMsg_DidPaint(instance_id_));
- }
-}
-
-NPObject* WebPluginDelegateProxy::GetPluginScriptableObject() {
- if (npobject_)
- return WebBindings::retainObject(npobject_);
-
- if (!channel_host_.get())
- return NULL;
-
- int route_id = MSG_ROUTING_NONE;
- Send(new PluginMsg_GetPluginScriptableObject(instance_id_, &route_id));
- if (route_id == MSG_ROUTING_NONE)
- return NULL;
-
- if (!channel_host_.get())
- return nullptr;
-
- npobject_ = NPObjectProxy::Create(
- channel_host_.get(), route_id, 0, page_url_, GetPluginNPP());
-
- return WebBindings::retainObject(npobject_);
-}
-
-NPP WebPluginDelegateProxy::GetPluginNPP() {
- // Return a dummy NPP for WebKit to use to identify this plugin.
- return npp_.get();
-}
-
-bool WebPluginDelegateProxy::GetFormValue(base::string16* value) {
- bool success = false;
- Send(new PluginMsg_GetFormValue(instance_id_, value, &success));
- return success;
-}
-
-void WebPluginDelegateProxy::SetFocus(bool focused) {
- Send(new PluginMsg_SetFocus(instance_id_, focused));
-#if defined(OS_WIN)
- if (render_view_)
- render_view_->PluginFocusChanged(focused, instance_id_);
-#endif
-}
-
-bool WebPluginDelegateProxy::HandleInputEvent(
- const WebInputEvent& event,
- WebCursor::CursorInfo* cursor_info) {
- bool handled = false;
- WebCursor cursor;
- // A windowless plugin can enter a modal loop in the context of a
- // NPP_HandleEvent call, in which case we need to pump messages to
- // the plugin. We pass of the corresponding event handle to the
- // plugin process, which is set if the plugin does enter a modal loop.
- IPC::SyncMessage* message = new PluginMsg_HandleInputEvent(
- instance_id_, &event, &handled, &cursor);
- message->set_pump_messages_event(modal_loop_pump_messages_event_.get());
- Send(message);
- return handled;
-}
-
-int WebPluginDelegateProxy::GetProcessId() {
- return channel_host_->peer_pid();
-}
-
-void WebPluginDelegateProxy::SetContentAreaFocus(bool has_focus) {
- IPC::Message* msg = new PluginMsg_SetContentAreaFocus(instance_id_,
- has_focus);
- // Make sure focus events are delivered in the right order relative to
- // sync messages they might interact with (Paint, HandleEvent, etc.).
- msg->set_unblock(true);
- Send(msg);
-}
-
-#if defined(OS_WIN)
-void WebPluginDelegateProxy::ImeCompositionUpdated(
- const base::string16& text,
- const std::vector<int>& clauses,
- const std::vector<int>& target,
- int cursor_position,
- int plugin_id) {
- // Dispatch the raw IME data if this plugin is the focused one.
- if (instance_id_ != plugin_id)
- return;
-
- IPC::Message* msg = new PluginMsg_ImeCompositionUpdated(instance_id_,
- text, clauses, target, cursor_position);
- msg->set_unblock(true);
- Send(msg);
-}
-
-void WebPluginDelegateProxy::ImeCompositionCompleted(const base::string16& text,
- int plugin_id) {
- // Dispatch the IME text if this plugin is the focused one.
- if (instance_id_ != plugin_id)
- return;
-
- IPC::Message* msg = new PluginMsg_ImeCompositionCompleted(instance_id_, text);
- msg->set_unblock(true);
- Send(msg);
-}
-#endif
-
-#if defined(OS_MACOSX)
-void WebPluginDelegateProxy::SetWindowFocus(bool window_has_focus) {
- IPC::Message* msg = new PluginMsg_SetWindowFocus(instance_id_,
- window_has_focus);
- // Make sure focus events are delivered in the right order relative to
- // sync messages they might interact with (Paint, HandleEvent, etc.).
- msg->set_unblock(true);
- Send(msg);
-}
-
-void WebPluginDelegateProxy::SetContainerVisibility(bool is_visible) {
- IPC::Message* msg;
- if (is_visible) {
- gfx::Rect window_frame = render_view_->rootWindowRect();
- gfx::Rect view_frame = render_view_->windowRect();
- blink::WebView* webview = render_view_->webview();
- msg = new PluginMsg_ContainerShown(instance_id_, window_frame, view_frame,
- webview && webview->isActive());
- } else {
- msg = new PluginMsg_ContainerHidden(instance_id_);
- }
- // Make sure visibility events are delivered in the right order relative to
- // sync messages they might interact with (Paint, HandleEvent, etc.).
- msg->set_unblock(true);
- Send(msg);
-}
-
-void WebPluginDelegateProxy::WindowFrameChanged(gfx::Rect window_frame,
- gfx::Rect view_frame) {
- IPC::Message* msg = new PluginMsg_WindowFrameChanged(instance_id_,
- window_frame,
- view_frame);
- // Make sure frame events are delivered in the right order relative to
- // sync messages they might interact with (e.g., HandleEvent).
- msg->set_unblock(true);
- Send(msg);
-}
-void WebPluginDelegateProxy::ImeCompositionCompleted(const base::string16& text,
- int plugin_id) {
- // If the message isn't intended for this plugin, there's nothing to do.
- if (instance_id_ != plugin_id)
- return;
-
- IPC::Message* msg = new PluginMsg_ImeCompositionCompleted(instance_id_,
- text);
- // Order relative to other key events is important.
- msg->set_unblock(true);
- Send(msg);
-}
-#endif // OS_MACOSX
-
-void WebPluginDelegateProxy::OnSetWindow(gfx::PluginWindowHandle window) {
-#if defined(OS_MACOSX)
- uses_shared_bitmaps_ = !window && !uses_compositor_;
-#else
- uses_shared_bitmaps_ = !window;
-#endif
- window_ = window;
- if (plugin_)
- plugin_->SetWindow(window);
-}
-
-void WebPluginDelegateProxy::WillDestroyWindow() {
- DCHECK(window_);
- plugin_->WillDestroyWindow(window_);
- window_ = gfx::kNullPluginWindow;
-}
-
-#if defined(OS_WIN)
-void WebPluginDelegateProxy::OnSetWindowlessData(
- HANDLE modal_loop_pump_messages_event_handle,
- gfx::NativeViewId dummy_activation_window) {
- DCHECK(!modal_loop_pump_messages_event_.get());
- DCHECK(!dummy_activation_window_);
- base::win::ScopedHandle modal_loop_pump_messages_event(
- modal_loop_pump_messages_event_handle);
-
- dummy_activation_window_ = dummy_activation_window;
- render_view_->Send(new ViewHostMsg_WindowlessPluginDummyWindowCreated(
- render_view_->routing_id(), dummy_activation_window_));
-
- // Bug 25583: this can be null because some "virus scanners" block the
- // DuplicateHandle call in the plugin process.
- if (!modal_loop_pump_messages_event.IsValid())
- return;
-
- modal_loop_pump_messages_event_.reset(
- new base::WaitableEvent(modal_loop_pump_messages_event.Pass()));
-}
-
-void WebPluginDelegateProxy::OnNotifyIMEStatus(int input_type,
- const gfx::Rect& caret_rect) {
- if (!render_view_)
- return;
-
- ViewHostMsg_TextInputState_Params params;
- params.type = static_cast<ui::TextInputType>(input_type);
- params.mode = ui::TEXT_INPUT_MODE_DEFAULT;
- params.can_compose_inline = true;
- render_view_->Send(new ViewHostMsg_TextInputStateChanged(
- render_view_->routing_id(), params));
-
- ViewHostMsg_SelectionBounds_Params bounds_params;
- bounds_params.anchor_rect = bounds_params.focus_rect = caret_rect;
- bounds_params.anchor_dir = bounds_params.focus_dir =
- blink::WebTextDirectionLeftToRight;
- bounds_params.is_anchor_first = true;
- render_view_->Send(new ViewHostMsg_SelectionBoundsChanged(
- render_view_->routing_id(),
- bounds_params));
-}
-#endif
-
-void WebPluginDelegateProxy::OnCancelResource(int id) {
- if (plugin_)
- plugin_->CancelResource(id);
-}
-
-void WebPluginDelegateProxy::OnInvalidateRect(const gfx::Rect& rect) {
- if (!plugin_)
- return;
-
- // Clip the invalidation rect to the plugin bounds; the plugin may have been
- // resized since the invalidate message was sent.
- gfx::Rect clipped_rect =
- gfx::IntersectRects(rect, gfx::Rect(plugin_rect_.size()));
-
- invalidate_pending_ = true;
- // The plugin is blocked on the renderer because the invalidate message it has
- // sent us is synchronous, so we can use buffer flipping here if the caller
- // allows it.
- UpdateFrontBuffer(clipped_rect, true);
- plugin_->InvalidateRect(clipped_rect);
-}
-
-void WebPluginDelegateProxy::OnGetWindowScriptNPObject(
- int route_id, bool* success) {
- *success = false;
- NPObject* npobject = NULL;
- if (plugin_)
- npobject = plugin_->GetWindowScriptNPObject();
-
- if (!npobject)
- return;
-
- // The stub will delete itself when the proxy tells it that it's released, or
- // otherwise when the channel is closed.
- new NPObjectStub(npobject, channel_host_.get(), route_id, 0, page_url_);
- *success = true;
-}
-
-void WebPluginDelegateProxy::OnResolveProxy(const GURL& url,
- bool* result,
- std::string* proxy_list) {
- *result = RenderThreadImpl::current()->ResolveProxy(url, proxy_list);
-}
-
-void WebPluginDelegateProxy::OnGetPluginElement(int route_id, bool* success) {
- *success = false;
- NPObject* npobject = NULL;
- if (plugin_)
- npobject = plugin_->GetPluginElement();
- if (!npobject)
- return;
-
- // The stub will delete itself when the proxy tells it that it's released, or
- // otherwise when the channel is closed.
- new NPObjectStub(
- npobject, channel_host_.get(), route_id, 0, page_url_);
- *success = true;
-}
-
-void WebPluginDelegateProxy::OnSetCookie(const GURL& url,
- const GURL& first_party_for_cookies,
- const std::string& cookie) {
- if (plugin_)
- plugin_->SetCookie(url, first_party_for_cookies, cookie);
-}
-
-void WebPluginDelegateProxy::OnGetCookies(const GURL& url,
- const GURL& first_party_for_cookies,
- std::string* cookies) {
- DCHECK(cookies);
- if (plugin_)
- *cookies = plugin_->GetCookies(url, first_party_for_cookies);
-}
-
-void WebPluginDelegateProxy::CopyFromBackBufferToFrontBuffer(
- const gfx::Rect& rect) {
- // Blitting the bits directly is much faster than going through CG, and since
- // the goal is just to move the raw pixels between two bitmaps with the same
- // pixel format (no compositing, color correction, etc.), it's safe.
- const size_t stride =
- skia::PlatformCanvasStrideForWidth(plugin_rect_.width());
- const size_t chunk_size = 4 * rect.width();
- DCHECK(back_buffer_bitmap() != NULL);
- uint8_t* source_data =
- back_buffer_bitmap()->pixels() + rect.y() * stride + 4 * rect.x();
- DCHECK(front_buffer_bitmap() != NULL);
- uint8_t* target_data =
- front_buffer_bitmap()->pixels() + rect.y() * stride + 4 * rect.x();
- for (int row = 0; row < rect.height(); ++row) {
- memcpy(target_data, source_data, chunk_size);
- source_data += stride;
- target_data += stride;
- }
-}
-
-void WebPluginDelegateProxy::UpdateFrontBuffer(
- const gfx::Rect& rect,
- bool allow_buffer_flipping) {
- if (!front_buffer_canvas()) {
- return;
- }
-
-#if defined(OS_WIN)
- // If SendUpdateGeometry() would block on the plugin process then we don't
- // want to use buffer flipping at all since it would add extra locking.
- // (Alternatively we could probably safely use async updates for buffer
- // flipping all the time since the size is not changing.)
- if (UseSynchronousGeometryUpdates()) {
- allow_buffer_flipping = false;
- }
-#endif
-
- // Plugin has just painted "rect" into the back-buffer, so the front-buffer
- // no longer holds the latest content for that rectangle.
- front_buffer_diff_.Subtract(rect);
- if (allow_buffer_flipping && front_buffer_diff_.IsEmpty()) {
- // Back-buffer contains the latest content for all areas; simply flip
- // the buffers.
- front_buffer_index_ = back_buffer_index();
- SendUpdateGeometry(false);
- // The front-buffer now holds newer content for this region than the
- // back-buffer.
- front_buffer_diff_ = rect;
- } else {
- // Back-buffer contains the latest content for "rect" but the front-buffer
- // contains the latest content for some other areas (or buffer flipping not
- // allowed); fall back to copying the data.
- CopyFromBackBufferToFrontBuffer(rect);
- }
- transport_store_painted_.Union(rect);
-}
-
-#if defined(OS_MACOSX)
-void WebPluginDelegateProxy::OnFocusChanged(bool focused) {
- if (render_view_)
- render_view_->PluginFocusChanged(focused, instance_id_);
-}
-
-void WebPluginDelegateProxy::OnStartIme() {
- if (render_view_)
- render_view_->StartPluginIme();
-}
-#endif
-
-gfx::PluginWindowHandle WebPluginDelegateProxy::GetPluginWindowHandle() {
- return window_;
-}
-
-void WebPluginDelegateProxy::OnCancelDocumentLoad() {
- plugin_->CancelDocumentLoad();
-}
-
-void WebPluginDelegateProxy::OnDidStartLoading() {
- plugin_->DidStartLoading();
-}
-
-void WebPluginDelegateProxy::OnDidStopLoading() {
- plugin_->DidStopLoading();
-}
-
-void WebPluginDelegateProxy::OnDeferResourceLoading(unsigned long resource_id,
- bool defer) {
- plugin_->SetDeferResourceLoading(resource_id, defer);
-}
-
-#if defined(OS_MACOSX)
-void WebPluginDelegateProxy::OnAcceleratedPluginEnabledRendering() {
- uses_compositor_ = true;
- OnSetWindow(gfx::kNullPluginWindow);
-}
-
-void WebPluginDelegateProxy::OnAcceleratedPluginAllocatedIOSurface(
- int32_t width,
- int32_t height,
- uint32_t surface_id) {
- if (plugin_)
- plugin_->AcceleratedPluginAllocatedIOSurface(width, height, surface_id);
-}
-
-void WebPluginDelegateProxy::OnAcceleratedPluginSwappedIOSurface() {
- if (plugin_)
- plugin_->AcceleratedPluginSwappedIOSurface();
-}
-#endif
-
-#if defined(OS_WIN)
-bool WebPluginDelegateProxy::UseSynchronousGeometryUpdates() {
- // Need to update geometry synchronously with WMP, otherwise if a site
- // scripts the plugin to start playing while it's in the middle of handling
- // an update geometry message, videos don't play. See urls in bug 20260.
- if (info_.name.find(base::ASCIIToUTF16("Windows Media Player")) !=
- base::string16::npos)
- return true;
-
- // The move networks plugin needs to be informed of geometry updates
- // synchronously.
- std::vector<WebPluginMimeType>::iterator index;
- for (index = info_.mime_types.begin(); index != info_.mime_types.end();
- index++) {
- if (index->mime_type == "application/x-vnd.moveplayer.qm" ||
- index->mime_type == "application/x-vnd.moveplay2.qm" ||
- index->mime_type == "application/x-vnd.movenetworks.qm" ||
- index->mime_type == "application/x-vnd.mnplayer.qm") {
- return true;
- }
- }
- return false;
-}
-#endif
-
-void WebPluginDelegateProxy::OnURLRedirectResponse(bool allow,
- int resource_id) {
- if (!plugin_)
- return;
-
- plugin_->URLRedirectResponse(allow, resource_id);
-}
-
-void WebPluginDelegateProxy::OnCheckIfRunInsecureContent(const GURL& url,
- bool* result) {
- *result = plugin_->CheckIfRunInsecureContent(url);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/npapi/webplugin_delegate_proxy.h b/chromium/content/renderer/npapi/webplugin_delegate_proxy.h
deleted file mode 100644
index 62fa840618d..00000000000
--- a/chromium/content/renderer/npapi/webplugin_delegate_proxy.h
+++ /dev/null
@@ -1,286 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_NPAPI_WEBPLUGIN_DELEGATE_PROXY_H_
-#define CONTENT_RENDERER_NPAPI_WEBPLUGIN_DELEGATE_PROXY_H_
-
-#include <stdint.h>
-
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "base/sequenced_task_runner_helpers.h"
-#include "build/build_config.h"
-#include "content/child/npapi/webplugin_delegate.h"
-#include "content/public/common/webplugininfo.h"
-#include "ipc/ipc_listener.h"
-#include "ipc/ipc_message.h"
-#include "ipc/ipc_sender.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/native_widget_types.h"
-#include "url/gurl.h"
-
-#if defined(OS_MACOSX)
-#include "base/containers/hash_tables.h"
-#endif
-
-struct NPObject;
-struct PluginHostMsg_URLRequest_Params;
-class SkBitmap;
-
-namespace base {
-class WaitableEvent;
-}
-
-
-namespace content {
-class NPObjectStub;
-class PluginChannelHost;
-class RenderFrameImpl;
-class RenderViewImpl;
-class SharedMemoryBitmap;
-class WebPluginImpl;
-
-// An implementation of WebPluginDelegate that proxies all calls to
-// the plugin process.
-class WebPluginDelegateProxy
- : public WebPluginDelegate,
- public IPC::Listener,
- public IPC::Sender,
- public base::SupportsWeakPtr<WebPluginDelegateProxy> {
- public:
- WebPluginDelegateProxy(WebPluginImpl* plugin,
- const std::string& mime_type,
- const base::WeakPtr<RenderViewImpl>& render_view,
- RenderFrameImpl* render_frame);
-
- // WebPluginDelegate implementation:
- void PluginDestroyed() override;
- bool Initialize(const GURL& url,
- const std::vector<std::string>& arg_names,
- const std::vector<std::string>& arg_values,
- bool load_manually) override;
- void UpdateGeometry(const gfx::Rect& window_rect,
- const gfx::Rect& clip_rect) override;
- void Paint(SkCanvas* canvas, const gfx::Rect& rect) override;
- NPObject* GetPluginScriptableObject() override;
- struct _NPP* GetPluginNPP() override;
- bool GetFormValue(base::string16* value) override;
- void SetFocus(bool focused) override;
- bool HandleInputEvent(const blink::WebInputEvent& event,
- WebCursor::CursorInfo* cursor) override;
- int GetProcessId() override;
-
- // Informs the plugin that its containing content view has gained or lost
- // first responder status.
- virtual void SetContentAreaFocus(bool has_focus);
-#if defined(OS_WIN)
- // Informs the plugin that plugin IME has updated its status.
- virtual void ImeCompositionUpdated(
- const base::string16& text,
- const std::vector<int>& clauses,
- const std::vector<int>& target,
- int cursor_position,
- int plugin_id);
- // Informs the plugin that plugin IME has completed.
- // If |text| is empty, composition was cancelled.
- virtual void ImeCompositionCompleted(const base::string16& text,
- int plugin_id);
-#endif
-#if defined(OS_MACOSX)
- // Informs the plugin that its enclosing window has gained or lost focus.
- virtual void SetWindowFocus(bool window_has_focus);
- // Informs the plugin that its container (window/tab) has changed visibility.
- virtual void SetContainerVisibility(bool is_visible);
- // Informs the plugin that its enclosing window's frame has changed.
- virtual void WindowFrameChanged(gfx::Rect window_frame, gfx::Rect view_frame);
- // Informs the plugin that plugin IME has completed.
- // If |text| is empty, composition was cancelled.
- virtual void ImeCompositionCompleted(const base::string16& text,
- int plugin_id);
-#endif
-
- // IPC::Listener implementation:
- bool OnMessageReceived(const IPC::Message& msg) override;
- void OnChannelError() override;
-
- // IPC::Sender implementation:
- bool Send(IPC::Message* msg) override;
-
- gfx::PluginWindowHandle GetPluginWindowHandle();
-
- protected:
- friend class base::DeleteHelper<WebPluginDelegateProxy>;
- ~WebPluginDelegateProxy() override;
-
- private:
- struct SharedBitmap {
- SharedBitmap();
- ~SharedBitmap();
-
- scoped_ptr<SharedMemoryBitmap> bitmap;
- scoped_ptr<SkCanvas> canvas;
- };
-
- // Message handlers for messages that proxy WebPlugin methods, which
- // we translate into calls to the real WebPlugin.
- void OnSetWindow(gfx::PluginWindowHandle window);
- void OnCompleteURL(const std::string& url_in, std::string* url_out,
- bool* result);
- void OnHandleURLRequest(const PluginHostMsg_URLRequest_Params& params);
- void OnCancelResource(int id);
- void OnInvalidateRect(const gfx::Rect& rect);
- void OnGetWindowScriptNPObject(int route_id, bool* success);
- void OnResolveProxy(const GURL& url, bool* result, std::string* proxy_list);
- void OnGetPluginElement(int route_id, bool* success);
- void OnSetCookie(const GURL& url,
- const GURL& first_party_for_cookies,
- const std::string& cookie);
- void OnGetCookies(const GURL& url, const GURL& first_party_for_cookies,
- std::string* cookies);
- void OnCancelDocumentLoad();
- void OnInitiateHTTPRangeRequest(const std::string& url,
- const std::string& range_info,
- int range_request_id);
- void OnDidStartLoading();
- void OnDidStopLoading();
- void OnDeferResourceLoading(unsigned long resource_id, bool defer);
- void OnURLRedirectResponse(bool allow, int resource_id);
- void OnCheckIfRunInsecureContent(const GURL& url, bool* result);
-#if defined(OS_MACOSX)
- void OnFocusChanged(bool focused);
- void OnStartIme();
- // Accelerated (Core Animation) plugin implementation.
- void OnAcceleratedPluginEnabledRendering();
- void OnAcceleratedPluginAllocatedIOSurface(int32_t width,
- int32_t height,
- uint32_t surface_id);
- void OnAcceleratedPluginSwappedIOSurface();
-#endif
-#if defined(OS_WIN)
- void OnSetWindowlessData(HANDLE modal_loop_pump_messages_event_handle,
- gfx::NativeViewId dummy_activation_window);
- void OnNotifyIMEStatus(const int input_mode, const gfx::Rect& caret_rect);
-#endif
- // Helper function that sends the UpdateGeometry message.
- void SendUpdateGeometry(bool bitmaps_changed);
-
- // Copies the given rectangle from the back-buffer transport_stores_ bitmap to
- // the front-buffer transport_stores_ bitmap.
- void CopyFromBackBufferToFrontBuffer(const gfx::Rect& rect);
-
- // Updates the front-buffer with the given rectangle from the back-buffer,
- // either by copying the rectangle or flipping the buffers.
- void UpdateFrontBuffer(const gfx::Rect& rect, bool allow_buffer_flipping);
-
- // Clears the shared memory section and canvases used for windowless plugins.
- void ResetWindowlessBitmaps();
-
- int front_buffer_index() const {
- return front_buffer_index_;
- }
-
- int back_buffer_index() const {
- return 1 - front_buffer_index_;
- }
-
- SkCanvas* front_buffer_canvas() const {
- return transport_stores_[front_buffer_index()].canvas.get();
- }
-
- SkCanvas* back_buffer_canvas() const {
- return transport_stores_[back_buffer_index()].canvas.get();
- }
-
- SharedMemoryBitmap* front_buffer_bitmap() const {
- return transport_stores_[front_buffer_index()].bitmap.get();
- }
-
- SharedMemoryBitmap* back_buffer_bitmap() const {
- return transport_stores_[back_buffer_index()].bitmap.get();
- }
-
-#if !defined(OS_WIN)
- // Creates a process-local memory section and canvas. PlatformCanvas on
- // Windows only works with a DIB, not arbitrary memory.
- bool CreateLocalBitmap(std::vector<uint8_t>* memory,
- scoped_ptr<SkCanvas>* canvas);
-#endif
-
- // Creates a shared memory section and canvas.
- bool CreateSharedBitmap(scoped_ptr<SharedMemoryBitmap>* memory,
- scoped_ptr<SkCanvas>* canvas);
-
- // Called for cleanup during plugin destruction. Normally right before the
- // plugin window gets destroyed, or when the plugin has crashed (at which
- // point the window has already been destroyed).
- void WillDestroyWindow();
-
-#if defined(OS_WIN)
- // Returns true if we should update the plugin geometry synchronously.
- bool UseSynchronousGeometryUpdates();
-#endif
-
- base::WeakPtr<RenderViewImpl> render_view_;
- RenderFrameImpl* render_frame_;
- WebPluginImpl* plugin_;
- bool uses_shared_bitmaps_;
-#if defined(OS_MACOSX)
- bool uses_compositor_;
-#elif defined(OS_WIN)
- // Used for windowless plugins so that keyboard activation works.
- gfx::NativeViewId dummy_activation_window_;
-#endif
- gfx::PluginWindowHandle window_;
- scoped_refptr<PluginChannelHost> channel_host_;
- std::string mime_type_;
- int instance_id_;
- WebPluginInfo info_;
-
- gfx::Rect plugin_rect_;
- gfx::Rect clip_rect_;
-
- NPObject* npobject_;
-
- // Dummy NPP used to uniquely identify this plugin.
- scoped_ptr<NPP_t> npp_;
-
- // Event passed in by the plugin process and is used to decide if messages
- // need to be pumped in the NPP_HandleEvent sync call.
- scoped_ptr<base::WaitableEvent> modal_loop_pump_messages_event_;
-
- // Bitmap for crashed plugin
- SkBitmap* sad_plugin_;
-
- // True if we got an invalidate from the plugin and are waiting for a paint.
- bool invalidate_pending_;
-
- // If the plugin is transparent or not.
- bool transparent_;
-
- // The index in the transport_stores_ array of the current front buffer
- // (i.e., the buffer to display).
- int front_buffer_index_;
- SharedBitmap transport_stores_[2];
- // This lets us know the total portion of the transport store that has been
- // painted since the buffers were created.
- gfx::Rect transport_store_painted_;
- // This is a bounding box on the portion of the front-buffer that was painted
- // on the last buffer flip and which has not yet been re-painted in the
- // back-buffer.
- gfx::Rect front_buffer_diff_;
-
- // The url of the main frame hosting the plugin.
- GURL page_url_;
-
- DISALLOW_COPY_AND_ASSIGN(WebPluginDelegateProxy);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_NPAPI_WEBPLUGIN_DELEGATE_PROXY_H_
diff --git a/chromium/content/renderer/npapi/webplugin_impl.cc b/chromium/content/renderer/npapi/webplugin_impl.cc
deleted file mode 100644
index cfa4f2962a0..00000000000
--- a/chromium/content/renderer/npapi/webplugin_impl.cc
+++ /dev/null
@@ -1,1228 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "content/renderer/npapi/webplugin_impl.h"
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/debug/crash_logging.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/memory/linked_ptr.h"
-#include "base/metrics/user_metrics_action.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/thread_task_runner_handle.h"
-#include "build/build_config.h"
-#include "cc/blink/web_layer_impl.h"
-#include "cc/layers/io_surface_layer.h"
-#include "content/child/appcache/web_application_cache_host_impl.h"
-#include "content/child/multipart_response_delegate.h"
-#include "content/child/npapi/plugin_host.h"
-#include "content/child/npapi/plugin_instance.h"
-#include "content/child/npapi/webplugin_delegate_impl.h"
-#include "content/child/npapi/webplugin_resource_client.h"
-#include "content/common/view_messages.h"
-#include "content/public/common/content_constants.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/renderer/content_renderer_client.h"
-#include "content/renderer/npapi/webplugin_delegate_proxy.h"
-#include "content/renderer/render_frame_impl.h"
-#include "content/renderer/render_process.h"
-#include "content/renderer/render_thread_impl.h"
-#include "content/renderer/render_view_impl.h"
-#include "net/base/escape.h"
-#include "net/base/net_errors.h"
-#include "net/http/http_response_headers.h"
-#include "skia/ext/platform_canvas.h"
-#include "third_party/WebKit/public/platform/WebCString.h"
-#include "third_party/WebKit/public/platform/WebCookieJar.h"
-#include "third_party/WebKit/public/platform/WebCursorInfo.h"
-#include "third_party/WebKit/public/platform/WebData.h"
-#include "third_party/WebKit/public/platform/WebHTTPBody.h"
-#include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
-#include "third_party/WebKit/public/platform/WebURL.h"
-#include "third_party/WebKit/public/platform/WebURLError.h"
-#include "third_party/WebKit/public/platform/WebURLLoader.h"
-#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
-#include "third_party/WebKit/public/platform/WebURLResponse.h"
-#include "third_party/WebKit/public/web/WebConsoleMessage.h"
-#include "third_party/WebKit/public/web/WebDocument.h"
-#include "third_party/WebKit/public/web/WebFrame.h"
-#include "third_party/WebKit/public/web/WebInputEvent.h"
-#include "third_party/WebKit/public/web/WebKit.h"
-#include "third_party/WebKit/public/web/WebPluginContainer.h"
-#include "third_party/WebKit/public/web/WebPluginParams.h"
-#include "third_party/WebKit/public/web/WebURLLoaderOptions.h"
-#include "third_party/WebKit/public/web/WebView.h"
-#include "ui/gfx/geometry/rect.h"
-#include "url/gurl.h"
-#include "url/url_util.h"
-
-using blink::WebCString;
-using blink::WebCanvas;
-using blink::WebConsoleMessage;
-using blink::WebCookieJar;
-using blink::WebCursorInfo;
-using blink::WebData;
-using blink::WebDataSource;
-using blink::WebFrame;
-using blink::WebHTTPBody;
-using blink::WebHTTPHeaderVisitor;
-using blink::WebInputEvent;
-using blink::WebInputEventResult;
-using blink::WebKeyboardEvent;
-using blink::WebMouseEvent;
-using blink::WebPluginContainer;
-using blink::WebPluginParams;
-using blink::WebRect;
-using blink::WebString;
-using blink::WebURL;
-using blink::WebURLError;
-using blink::WebURLLoader;
-using blink::WebURLLoaderClient;
-using blink::WebURLLoaderOptions;
-using blink::WebURLRequest;
-using blink::WebURLResponse;
-using blink::WebVector;
-using blink::WebView;
-
-namespace content {
-
-namespace {
-
-// This class handles individual multipart responses. It is instantiated when
-// we receive HTTP status code 206 in the HTTP response. This indicates
-// that the response could have multiple parts each separated by a boundary
-// specified in the response header.
-class MultiPartResponseClient : public WebURLLoaderClient {
- public:
- explicit MultiPartResponseClient(WebPluginResourceClient* resource_client)
- : byte_range_lower_bound_(0), resource_client_(resource_client) {}
-
- void willFollowRedirect(WebURLLoader*,
- WebURLRequest&,
- const WebURLResponse&) override {}
- void didSendData(WebURLLoader*,
- unsigned long long,
- unsigned long long) override {}
-
- // Called when the multipart parser encounters an embedded multipart
- // response.
- void didReceiveResponse(WebURLLoader*,
- const WebURLResponse& response) override {
- int64_t byte_range_upper_bound, instance_size;
- if (!MultipartResponseDelegate::ReadContentRanges(
- response,
- &byte_range_lower_bound_,
- &byte_range_upper_bound,
- &instance_size)) {
- NOTREACHED();
- }
- }
-
- // Receives individual part data from a multipart response.
- void didReceiveData(WebURLLoader*,
- const char* data,
- int data_length,
- int encoded_data_length) override {
- // TODO(ananta)
- // We should defer further loads on multipart resources on the same lines
- // as regular resources requested by plugins to prevent reentrancy.
- resource_client_->DidReceiveData(
- data, data_length, byte_range_lower_bound_);
- byte_range_lower_bound_ += data_length;
- }
-
- void didFinishLoading(WebURLLoader*,
- double finishTime,
- int64_t total_encoded_data_length) override {}
- void didFail(WebURLLoader*, const WebURLError&) override {}
-
- private:
- // The lower bound of the byte range.
- int64_t byte_range_lower_bound_;
- // The handler for the data.
- WebPluginResourceClient* resource_client_;
-};
-
-class HeaderFlattener : public WebHTTPHeaderVisitor {
- public:
- explicit HeaderFlattener(std::string* buf) : buf_(buf) {
- }
-
- void visitHeader(const WebString& name, const WebString& value) override {
- // TODO(darin): Should we really exclude headers with an empty value?
- if (!name.isEmpty() && !value.isEmpty()) {
- buf_->append(name.utf8());
- buf_->append(": ");
- buf_->append(value.utf8());
- buf_->append("\n");
- }
- }
-
- private:
- std::string* buf_;
-};
-
-std::string GetAllHeaders(const WebURLResponse& response) {
- // TODO(darin): It is possible for httpStatusText to be empty and still have
- // an interesting response, so this check seems wrong.
- std::string result;
- const WebString& status = response.httpStatusText();
- if (status.isEmpty())
- return result;
-
- // TODO(darin): Shouldn't we also report HTTP version numbers?
- result = base::StringPrintf("HTTP %d ", response.httpStatusCode());
- result.append(status.utf8());
- result.append("\n");
-
- HeaderFlattener flattener(&result);
- response.visitHTTPHeaderFields(&flattener);
-
- return result;
-}
-
-struct ResponseInfo {
- GURL url;
- std::string mime_type;
- uint32_t last_modified;
- uint32_t expected_length;
-};
-
-void GetResponseInfo(const WebURLResponse& response,
- ResponseInfo* response_info) {
- response_info->url = response.url();
- response_info->mime_type = response.mimeType().utf8();
-
- // Measured in seconds since 12:00 midnight GMT, January 1, 1970.
- response_info->last_modified =
- static_cast<uint32_t>(response.lastModifiedDate());
-
- // If the length comes in as -1, then it indicates that it was not
- // read off the HTTP headers. We replicate Safari webkit behavior here,
- // which is to set it to 0.
- response_info->expected_length =
- static_cast<uint32_t>(std::max(response.expectedContentLength(), 0LL));
-
- WebString content_encoding =
- response.httpHeaderField(WebString::fromUTF8("Content-Encoding"));
- if (!content_encoding.isNull() &&
- !base::EqualsASCII(base::StringPiece16(content_encoding), "identity")) {
- // Don't send the compressed content length to the plugin, which only
- // cares about the decoded length.
- response_info->expected_length = 0;
- }
-}
-
-} // namespace
-
-// blink::WebPlugin ----------------------------------------------------------
-
-struct WebPluginImpl::ClientInfo {
- unsigned long id;
- WebPluginResourceClient* client;
- blink::WebURLRequest request;
- bool pending_failure_notification;
- linked_ptr<blink::WebURLLoader> loader;
- bool notify_redirects;
- bool is_plugin_src_load;
- int64_t data_offset;
-};
-
-bool WebPluginImpl::initialize(WebPluginContainer* container) {
- if (!render_view_.get()) {
- LOG(ERROR) << "No RenderView";
- return false;
- }
-
- WebPluginDelegateProxy* plugin_delegate = new WebPluginDelegateProxy(
- this, mime_type_, render_view_, render_frame_);
-
- // Store the plugin's unique identifier, used by the container to track its
- // script objects.
- npp_ = plugin_delegate->GetPluginNPP();
-
- // Set the container before Initialize because the plugin may
- // synchronously call NPN_GetValue to get its container, or make calls
- // passing script objects that need to be tracked, during initialization.
- SetContainer(container);
-
- bool ok = plugin_delegate->Initialize(
- plugin_url_, arg_names_, arg_values_, load_manually_);
- if (!ok) {
- plugin_delegate->PluginDestroyed();
-
- blink::WebPlugin* replacement_plugin =
- GetContentClient()->renderer()->CreatePluginReplacement(
- render_frame_, file_path_);
- if (!replacement_plugin) {
- // Maintain invariant that container() returns null when initialize()
- // returns false.
- SetContainer(nullptr);
- return false;
- }
-
- // Disable scripting by this plugin before replacing it with the new
- // one. This plugin also needs destroying, so use destroy(), which will
- // implicitly disable scripting while un-setting the container.
- destroy();
-
- // Inform the container of the replacement plugin, then initialize it.
- container->setPlugin(replacement_plugin);
- return replacement_plugin->initialize(container);
- }
-
- delegate_ = plugin_delegate;
-
- return true;
-}
-
-void WebPluginImpl::destroy() {
- SetContainer(NULL);
- base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
-}
-
-NPObject* WebPluginImpl::scriptableObject() {
- if (!delegate_)
- return NULL;
-
- return delegate_->GetPluginScriptableObject();
-}
-
-NPP WebPluginImpl::pluginNPP() {
- return npp_;
-}
-
-bool WebPluginImpl::getFormValue(blink::WebString& value) {
- if (!delegate_)
- return false;
- base::string16 form_value;
- if (!delegate_->GetFormValue(&form_value))
- return false;
- value = form_value;
- return true;
-}
-
-void WebPluginImpl::updateAllLifecyclePhases() {
- if (!container_)
- return;
-
-#if defined(OS_WIN)
- // Force a geometry update if needed to allow plugins like media player
- // which defer the initial geometry update to work. Do it now, rather
- // than in paint, so that the paint rect invalidation is registered.
- // Otherwise we may never get the paint call.
- container_->reportGeometry();
-#endif // OS_WIN
-}
-
-void WebPluginImpl::paint(WebCanvas* canvas, const WebRect& paint_rect) {
- if (!delegate_ || !container_)
- return;
-
- // Note that |canvas| is only used when in windowless mode.
- delegate_->Paint(canvas, paint_rect);
-}
-
-void WebPluginImpl::updateGeometry(const WebRect& window_rect,
- const WebRect& clip_rect,
- const WebRect& unobscured_rect,
- const WebVector<WebRect>& cut_outs_rects,
- bool is_visible) {
- WebPluginGeometry new_geometry;
- new_geometry.window = window_;
- new_geometry.window_rect = window_rect;
- new_geometry.clip_rect = clip_rect;
- new_geometry.visible = is_visible;
- new_geometry.rects_valid = true;
- for (size_t i = 0; i < cut_outs_rects.size(); ++i)
- new_geometry.cutout_rects.push_back(cut_outs_rects[i]);
-
- // Only send DidMovePlugin if the geometry changed in some way.
- if (window_ && (first_geometry_update_ || !new_geometry.Equals(geometry_))) {
- render_frame_->GetRenderWidget()->SchedulePluginMove(new_geometry);
- // We invalidate windowed plugins during the first geometry update to
- // ensure that they get reparented to the wrapper window in the browser.
- // This ensures that they become visible and are painted by the OS. This is
- // required as some pages don't invalidate when the plugin is added.
- if (first_geometry_update_ && window_) {
- InvalidateRect(window_rect);
- }
- }
-
- // Only UpdateGeometry if either the window or clip rects have changed.
- if (delegate_ && (first_geometry_update_ ||
- new_geometry.window_rect != geometry_.window_rect ||
- new_geometry.clip_rect != geometry_.clip_rect)) {
- // Notify the plugin that its parameters have changed.
- delegate_->UpdateGeometry(new_geometry.window_rect, new_geometry.clip_rect);
- }
-
-#if defined(OS_WIN)
- // Don't cache the geometry during the first geometry update. The first
- // geometry update sequence is received when Widget::setParent is called.
- // For plugins like media player which have a bug where they only honor
- // the first geometry update, we have a quirk which ignores the first
- // geometry update. To ensure that these plugins work correctly in cases
- // where we receive only one geometry update from webkit, we also force
- // a geometry update during paint which should go out correctly as the
- // initial geometry update was not cached.
- if (!first_geometry_update_)
- geometry_ = new_geometry;
-#else // OS_WIN
- geometry_ = new_geometry;
-#endif // OS_WIN
- first_geometry_update_ = false;
-}
-
-void WebPluginImpl::updateFocus(bool focused, blink::WebFocusType focus_type) {
- if (accepts_input_events_)
- delegate_->SetFocus(focused);
-}
-
-void WebPluginImpl::updateVisibility(bool visible) {
- if (!window_)
- return;
-
- WebPluginGeometry move;
- move.window = window_;
- move.window_rect = gfx::Rect();
- move.clip_rect = gfx::Rect();
- move.rects_valid = false;
- move.visible = visible;
-
- render_frame_->GetRenderWidget()->SchedulePluginMove(move);
-}
-
-bool WebPluginImpl::acceptsInputEvents() {
- return accepts_input_events_;
-}
-
-WebInputEventResult WebPluginImpl::handleInputEvent(
- const WebInputEvent& event,
- WebCursorInfo& cursor_info) {
- // Swallow context menu events in order to suppress the default context menu.
- if (event.type == WebInputEvent::ContextMenu)
- return WebInputEventResult::HandledSuppressed;
-
- WebCursor::CursorInfo web_cursor_info;
- bool ret = delegate_->HandleInputEvent(event, &web_cursor_info);
- cursor_info.type = web_cursor_info.type;
- cursor_info.hotSpot = web_cursor_info.hotspot;
- cursor_info.customImage = web_cursor_info.custom_image;
- cursor_info.imageScaleFactor = web_cursor_info.image_scale_factor;
-#if defined(OS_WIN)
- cursor_info.externalHandle = web_cursor_info.external_handle;
-#endif
- return ret ? WebInputEventResult::HandledApplication
- : WebInputEventResult::NotHandled;
-}
-
-bool WebPluginImpl::isPlaceholder() {
- return false;
-}
-
-WebPluginImpl::LoaderClient::LoaderClient(WebPluginImpl* parent)
- : parent_(parent) {}
-
-void WebPluginImpl::LoaderClient::willFollowRedirect(
- blink::WebURLLoader* loader, blink::WebURLRequest& new_request,
- const blink::WebURLResponse& redirect_response) {
- parent_->willFollowRedirect(loader, new_request, redirect_response);
-}
-
-void WebPluginImpl::LoaderClient::didSendData(
- blink::WebURLLoader* loader, unsigned long long bytesSent,
- unsigned long long totalBytesToBeSent) {
- parent_->didSendData(loader, bytesSent, totalBytesToBeSent);
-}
-
-void WebPluginImpl::LoaderClient::didReceiveResponse(
- blink::WebURLLoader* loader, const blink::WebURLResponse& response) {
- parent_->didReceiveResponse(loader, response);
-}
-
-void WebPluginImpl::LoaderClient::didDownloadData(
- blink::WebURLLoader* loader, int dataLength, int encodedDataLength) {
-}
-
-void WebPluginImpl::LoaderClient::didReceiveData(
- blink::WebURLLoader* loader, const char* data,
- int dataLength, int encodedDataLength) {
- parent_->didReceiveData(loader, data, dataLength, encodedDataLength);
-}
-
-void WebPluginImpl::LoaderClient::didReceiveCachedMetadata(
- blink::WebURLLoader* loader, const char* data, int dataLength) {
-}
-
-void WebPluginImpl::LoaderClient::didFinishLoading(
- blink::WebURLLoader* loader, double finishTime,
- int64_t total_encoded_data_length) {
- parent_->didFinishLoading(loader, finishTime);
-}
-
-void WebPluginImpl::LoaderClient::didFail(
- blink::WebURLLoader* loader, const blink::WebURLError& error) {
- parent_->didFail(loader, error);
-}
-
-// -----------------------------------------------------------------------------
-
-WebPluginImpl::WebPluginImpl(
- WebFrame* webframe,
- const WebPluginParams& params,
- const base::FilePath& file_path,
- const base::WeakPtr<RenderViewImpl>& render_view,
- RenderFrameImpl* render_frame)
- : windowless_(false),
- window_(gfx::kNullPluginWindow),
- accepts_input_events_(false),
- render_frame_(render_frame),
- render_view_(render_view),
- webframe_(webframe),
- delegate_(NULL),
- container_(NULL),
- npp_(NULL),
- plugin_url_(params.url),
- load_manually_(params.loadManually),
- first_geometry_update_(true),
- ignore_response_error_(false),
- file_path_(file_path),
- mime_type_(base::ToLowerASCII(base::UTF16ToASCII(
- base::StringPiece16(params.mimeType)))),
- loader_client_(this) {
- DCHECK_EQ(params.attributeNames.size(), params.attributeValues.size());
-
- for (size_t i = 0; i < params.attributeNames.size(); ++i) {
- arg_names_.push_back(params.attributeNames[i].utf8());
- arg_values_.push_back(params.attributeValues[i].utf8());
- }
-
- // Set subresource URL for crash reporting.
- base::debug::SetCrashKeyValue("subresource_url", plugin_url_.spec());
-}
-
-WebPluginImpl::~WebPluginImpl() {
-}
-
-void WebPluginImpl::SetWindow(gfx::PluginWindowHandle window) {
- if (window) {
- DCHECK(!windowless_);
- window_ = window;
-#if defined(OS_MACOSX)
- // TODO(kbr): remove. http://crbug.com/105344
-
- // Lie to ourselves about being windowless even if we got a fake
- // plugin window handle, so we continue to get input events.
- windowless_ = true;
- accepts_input_events_ = true;
- // We do not really need to notify the page delegate that a plugin
- // window was created -- so don't.
-#else
- accepts_input_events_ = false;
-
-#endif // OS_MACOSX
- } else {
- DCHECK(!window_); // Make sure not called twice.
- windowless_ = true;
- accepts_input_events_ = true;
- }
-}
-
-void WebPluginImpl::SetAcceptsInputEvents(bool accepts) {
- accepts_input_events_ = accepts;
-}
-
-void WebPluginImpl::WillDestroyWindow(gfx::PluginWindowHandle window) {
- DCHECK_EQ(window, window_);
- window_ = gfx::kNullPluginWindow;
- if (render_view_.get())
- render_frame_->GetRenderWidget()->CleanupWindowInPluginMoves(window);
-}
-
-GURL WebPluginImpl::CompleteURL(const char* url) {
- if (!webframe_) {
- NOTREACHED();
- return GURL();
- }
- // TODO(darin): Is conversion from UTF8 correct here?
- return webframe_->document().completeURL(WebString::fromUTF8(url));
-}
-
-void WebPluginImpl::CancelResource(unsigned long id) {
- for (size_t i = 0; i < clients_.size(); ++i) {
- if (clients_[i].id == id) {
- if (clients_[i].loader.get()) {
- clients_[i].loader->setDefersLoading(false);
- clients_[i].loader->cancel();
- RemoveClient(i);
- }
- return;
- }
- }
-}
-
-bool WebPluginImpl::SetPostData(WebURLRequest* request,
- const char* buf,
- uint32_t length) {
- std::vector<std::string> names;
- std::vector<std::string> values;
- std::vector<char> body;
- bool rv = PluginHost::SetPostData(buf, length, &names, &values, &body);
-
- for (size_t i = 0; i < names.size(); ++i) {
- request->addHTTPHeaderField(WebString::fromUTF8(names[i]),
- WebString::fromUTF8(values[i]));
- }
-
- WebString content_type_header = WebString::fromUTF8("Content-Type");
- const WebString& content_type =
- request->httpHeaderField(content_type_header);
- if (content_type.isEmpty()) {
- request->setHTTPHeaderField(
- content_type_header,
- WebString::fromUTF8("application/x-www-form-urlencoded"));
- }
-
- WebHTTPBody http_body;
- if (body.size()) {
- http_body.initialize();
- http_body.appendData(WebData(&body[0], body.size()));
- }
- request->setHTTPBody(http_body);
-
- return rv;
-}
-
-bool WebPluginImpl::IsValidUrl(const GURL& url, ReferrerValue referrer_flag) {
- if (referrer_flag == PLUGIN_SRC &&
- mime_type_ == kFlashPluginSwfMimeType &&
- url.GetOrigin() != plugin_url_.GetOrigin()) {
- // Do url check to make sure that there are no @, ;, \ chars in between url
- // scheme and url path.
- const char* url_to_check(url.spec().data());
- url::Parsed parsed;
- url::ParseStandardURL(url_to_check, strlen(url_to_check), &parsed);
- if (parsed.path.begin <= parsed.scheme.end())
- return true;
- std::string string_to_search;
- string_to_search.assign(url_to_check + parsed.scheme.end(),
- parsed.path.begin - parsed.scheme.end());
- if (string_to_search.find("@") != std::string::npos ||
- string_to_search.find(";") != std::string::npos ||
- string_to_search.find("\\") != std::string::npos)
- return false;
- }
-
- return true;
-}
-
-WebPluginImpl::RoutingStatus WebPluginImpl::RouteToFrame(
- const char* url,
- bool is_javascript_url,
- bool popups_allowed,
- const char* method,
- const char* target,
- const char* buf,
- unsigned int len,
- ReferrerValue referrer_flag) {
- // If there is no target, there is nothing to do
- if (!target)
- return NOT_ROUTED;
-
- // This could happen if the WebPluginContainer was already deleted.
- if (!webframe_)
- return NOT_ROUTED;
-
- WebString target_str = WebString::fromUTF8(target);
-
- // Take special action for JavaScript URLs
- if (is_javascript_url) {
- WebFrame* target_frame =
- webframe_->view()->findFrameByName(target_str, webframe_);
- // For security reasons, do not allow JavaScript on frames
- // other than this frame.
- if (target_frame != webframe_) {
- // TODO(darin): Localize this message.
- const char kMessage[] =
- "Ignoring cross-frame javascript URL load requested by plugin.";
- webframe_->addMessageToConsole(
- WebConsoleMessage(WebConsoleMessage::LevelError,
- WebString::fromUTF8(kMessage)));
- return ROUTED;
- }
-
- // Route javascript calls back to the plugin.
- return NOT_ROUTED;
- }
-
- // If we got this far, we're routing content to a target frame.
- // Go fetch the URL.
-
- GURL complete_url = CompleteURL(url);
- // Remove when flash bug is fixed. http://crbug.com/40016.
- if (!WebPluginImpl::IsValidUrl(complete_url, referrer_flag))
- return INVALID_URL;
-
- if (strcmp(method, "GET") != 0) {
- // We're only going to route HTTP/HTTPS requests
- if (!complete_url.SchemeIsHTTPOrHTTPS())
- return INVALID_URL;
- }
-
- WebURLRequest request(complete_url);
- SetReferrer(&request, referrer_flag);
-
- request.setHTTPMethod(WebString::fromUTF8(method));
- request.setFirstPartyForCookies(
- webframe_->document().firstPartyForCookies());
- request.setHasUserGesture(popups_allowed);
- // ServiceWorker is disabled for NPAPI.
- request.setSkipServiceWorker(true);
- if (len > 0) {
- if (!SetPostData(&request, buf, len)) {
- // Uhoh - we're in trouble. There isn't a good way
- // to recover at this point. Break out.
- NOTREACHED();
- return ROUTED;
- }
- }
-
- container_->loadFrameRequest(request, target_str);
- return ROUTED;
-}
-
-NPObject* WebPluginImpl::GetWindowScriptNPObject() {
- if (!webframe_) {
- NOTREACHED();
- return NULL;
- }
- return webframe_->windowObject();
-}
-
-NPObject* WebPluginImpl::GetPluginElement() {
- return container_->scriptableObjectForElement();
-}
-
-bool WebPluginImpl::FindProxyForUrl(const GURL& url, std::string* proxy_list) {
- // Proxy resolving doesn't work in single-process mode.
- return false;
-}
-
-void WebPluginImpl::SetCookie(const GURL& url,
- const GURL& first_party_for_cookies,
- const std::string& cookie) {
- if (!render_view_.get())
- return;
-
- WebCookieJar* cookie_jar = render_frame_->cookie_jar();
- if (!cookie_jar) {
- DLOG(WARNING) << "No cookie jar!";
- return;
- }
-
- cookie_jar->setCookie(
- url, first_party_for_cookies, WebString::fromUTF8(cookie));
-}
-
-std::string WebPluginImpl::GetCookies(const GURL& url,
- const GURL& first_party_for_cookies) {
- if (!render_view_.get())
- return std::string();
-
- WebCookieJar* cookie_jar = render_frame_->cookie_jar();
- if (!cookie_jar) {
- DLOG(WARNING) << "No cookie jar!";
- return std::string();
- }
-
- return base::UTF16ToUTF8(base::StringPiece16(
- cookie_jar->cookies(url, first_party_for_cookies)));
-}
-
-void WebPluginImpl::URLRedirectResponse(bool allow, int resource_id) {
- for (size_t i = 0; i < clients_.size(); ++i) {
- if (clients_[i].id == static_cast<unsigned long>(resource_id)) {
- if (clients_[i].loader.get()) {
- if (allow) {
- clients_[i].loader->setDefersLoading(false);
- } else {
- clients_[i].loader->cancel();
- if (clients_[i].client)
- clients_[i].client->DidFail(clients_[i].id);
- }
- }
- break;
- }
- }
-}
-
-bool WebPluginImpl::CheckIfRunInsecureContent(const GURL& url) {
- if (!webframe_)
- return true;
-
- return webframe_->checkIfRunInsecureContent(url);
-}
-
-#if defined(OS_MACOSX)
-WebPluginAcceleratedSurface* WebPluginImpl::GetAcceleratedSurface(
- gfx::GpuPreference gpu_preference) {
- return NULL;
-}
-
-void WebPluginImpl::AcceleratedPluginEnabledRendering() {
-}
-
-void WebPluginImpl::AcceleratedPluginAllocatedIOSurface(int32_t width,
- int32_t height,
- uint32_t surface_id) {
- next_io_surface_allocated_ = true;
- next_io_surface_width_ = width;
- next_io_surface_height_ = height;
- next_io_surface_id_ = surface_id;
-}
-
-void WebPluginImpl::AcceleratedPluginSwappedIOSurface() {
- if (!container_)
- return;
- // Deferring the call to setBackingIOSurfaceId is an attempt to
- // work around garbage occasionally showing up in the plugin's
- // area during live resizing of Core Animation plugins. The
- // assumption was that by the time this was called, the plugin
- // process would have populated the newly allocated IOSurface. It
- // is not 100% clear at this point why any garbage is getting
- // through. More investigation is needed. http://crbug.com/105346
- if (next_io_surface_allocated_) {
- if (next_io_surface_id_) {
- if (!io_surface_layer_.get()) {
- io_surface_layer_ =
- cc::IOSurfaceLayer::Create(cc_blink::WebLayerImpl::LayerSettings());
- web_layer_.reset(new cc_blink::WebLayerImpl(io_surface_layer_));
- container_->setWebLayer(web_layer_.get());
- }
- io_surface_layer_->SetIOSurfaceProperties(
- next_io_surface_id_,
- gfx::Size(next_io_surface_width_, next_io_surface_height_));
- } else {
- container_->setWebLayer(NULL);
- web_layer_.reset();
- io_surface_layer_ = NULL;
- }
- next_io_surface_allocated_ = false;
- } else {
- if (io_surface_layer_.get())
- io_surface_layer_->SetNeedsDisplay();
- }
-}
-#endif
-
-void WebPluginImpl::Invalidate() {
- if (container_)
- container_->invalidate();
-}
-
-void WebPluginImpl::InvalidateRect(const gfx::Rect& rect) {
- if (container_)
- container_->invalidateRect(rect);
-}
-
-WebPluginResourceClient* WebPluginImpl::GetClientFromLoader(
- WebURLLoader* loader) {
- ClientInfo* client_info = GetClientInfoFromLoader(loader);
- if (client_info)
- return client_info->client;
- return NULL;
-}
-
-WebPluginImpl::ClientInfo* WebPluginImpl::GetClientInfoFromLoader(
- WebURLLoader* loader) {
- for (size_t i = 0; i < clients_.size(); ++i) {
- if (clients_[i].loader.get() == loader)
- return &clients_[i];
- }
-
- NOTREACHED();
- return 0;
-}
-
-void WebPluginImpl::willFollowRedirect(WebURLLoader* loader,
- WebURLRequest& new_request,
- const WebURLResponse& response) {
- // TODO(jam): THIS LOGIC IS COPIED IN PluginURLFetcher::OnReceivedRedirect
- // until kDirectNPAPIRequests is the default and we can remove this old path.
- WebPluginImpl::ClientInfo* client_info = GetClientInfoFromLoader(loader);
- if (client_info) {
- // Currently this check is just to catch an https -> http redirect when
- // loading the main plugin src URL. Longer term, we could investigate
- // firing mixed diplay or scripting issues for subresource loads
- // initiated by plugins.
- if (client_info->is_plugin_src_load &&
- webframe_ &&
- !webframe_->checkIfRunInsecureContent(new_request.url())) {
- loader->cancel();
- client_info->client->DidFail(client_info->id);
- return;
- }
- if (net::HttpResponseHeaders::IsRedirectResponseCode(
- response.httpStatusCode())) {
- // If the plugin does not participate in url redirect notifications then
- // just block cross origin 307 POST redirects.
- if (!client_info->notify_redirects) {
- if (response.httpStatusCode() == 307 &&
- base::LowerCaseEqualsASCII(
- new_request.httpMethod().utf8(), "post")) {
- GURL original_request_url(response.url());
- GURL response_url(new_request.url());
- if (original_request_url.GetOrigin() != response_url.GetOrigin()) {
- loader->setDefersLoading(true);
- loader->cancel();
- client_info->client->DidFail(client_info->id);
- return;
- }
- }
- } else {
- loader->setDefersLoading(true);
- }
- }
- client_info->client->WillSendRequest(new_request.url(),
- response.httpStatusCode());
- }
-}
-
-void WebPluginImpl::didSendData(WebURLLoader* loader,
- unsigned long long bytes_sent,
- unsigned long long total_bytes_to_be_sent) {
-}
-
-void WebPluginImpl::didReceiveResponse(WebURLLoader* loader,
- const WebURLResponse& response) {
- // TODO(jam): THIS LOGIC IS COPIED IN PluginURLFetcher::OnReceivedResponse
- // until kDirectNPAPIRequests is the default and we can remove this old path.
-
- WebPluginResourceClient* client = GetClientFromLoader(loader);
- if (!client)
- return;
-
- ResponseInfo response_info;
- GetResponseInfo(response, &response_info);
- ClientInfo* client_info = GetClientInfoFromLoader(loader);
- if (!client_info)
- return;
-
- // Calling into a plugin could result in reentrancy if the plugin yields
- // control to the OS like entering a modal loop etc. Prevent this by
- // stopping further loading until the plugin notifies us that it is ready to
- // accept data
- loader->setDefersLoading(true);
-
- client->DidReceiveResponse(
- response_info.mime_type,
- GetAllHeaders(response),
- response_info.expected_length,
- response_info.last_modified,
- true);
-
- // Bug http://b/issue?id=925559. The flash plugin would not handle the HTTP
- // error codes in the stream header and as a result, was unaware of the
- // fate of the HTTP requests issued via NPN_GetURLNotify. Webkit and FF
- // destroy the stream and invoke the NPP_DestroyStream function on the
- // plugin if the HTTP request fails.
- const GURL& url = response.url();
- if (url.SchemeIs(url::kHttpScheme) || url.SchemeIs(url::kHttpsScheme)) {
- if (response.httpStatusCode() < 100 || response.httpStatusCode() >= 400) {
- // The plugin instance could be in the process of deletion here.
- // Verify if the WebPluginResourceClient instance still exists before
- // use.
- ClientInfo* client_info = GetClientInfoFromLoader(loader);
- if (client_info) {
- client_info->pending_failure_notification = true;
- }
- }
- }
-}
-
-void WebPluginImpl::didReceiveData(WebURLLoader* loader,
- const char *buffer,
- int data_length,
- int encoded_data_length) {
- WebPluginResourceClient* client = GetClientFromLoader(loader);
- if (!client)
- return;
-
- MultiPartResponseHandlerMap::iterator index =
- multi_part_response_map_.find(client);
- if (index != multi_part_response_map_.end()) {
- MultipartResponseDelegate* multi_part_handler = (*index).second;
- DCHECK(multi_part_handler != NULL);
- multi_part_handler->OnReceivedData(buffer,
- data_length,
- encoded_data_length);
- } else {
- loader->setDefersLoading(true);
- ClientInfo* client_info = GetClientInfoFromLoader(loader);
- client->DidReceiveData(buffer, data_length, client_info->data_offset);
- client_info->data_offset += data_length;
- }
-}
-
-void WebPluginImpl::didFinishLoading(WebURLLoader* loader, double finishTime) {
- ClientInfo* client_info = GetClientInfoFromLoader(loader);
- if (client_info && client_info->client) {
- MultiPartResponseHandlerMap::iterator index =
- multi_part_response_map_.find(client_info->client);
- if (index != multi_part_response_map_.end()) {
- delete (*index).second;
- multi_part_response_map_.erase(index);
- DidStopLoading();
- }
- loader->setDefersLoading(true);
- WebPluginResourceClient* resource_client = client_info->client;
- // The ClientInfo can get deleted in the call to DidFinishLoading below.
- // It is not safe to access this structure after that.
- client_info->client = NULL;
- resource_client->DidFinishLoading(client_info->id);
- }
-}
-
-void WebPluginImpl::didFail(WebURLLoader* loader,
- const WebURLError& error) {
- ClientInfo* client_info = GetClientInfoFromLoader(loader);
- if (client_info && client_info->client) {
- loader->setDefersLoading(true);
- WebPluginResourceClient* resource_client = client_info->client;
- // The ClientInfo can get deleted in the call to DidFail below.
- // It is not safe to access this structure after that.
- client_info->client = NULL;
- resource_client->DidFail(client_info->id);
- }
-}
-
-void WebPluginImpl::RemoveClient(size_t i) {
- clients_.erase(clients_.begin() + i);
-}
-
-void WebPluginImpl::RemoveClient(WebURLLoader* loader) {
- for (size_t i = 0; i < clients_.size(); ++i) {
- if (clients_[i].loader.get() == loader) {
- RemoveClient(i);
- return;
- }
- }
-}
-
-void WebPluginImpl::SetContainer(WebPluginContainer* container) {
- if (!container)
- TearDownPluginInstance(NULL);
- container_ = container;
- if (container_)
- container_->allowScriptObjects();
-}
-
-unsigned long WebPluginImpl::GetNextResourceId() {
- if (!webframe_)
- return 0;
- WebView* view = webframe_->view();
- if (!view)
- return 0;
- return view->createUniqueIdentifierForRequest();
-}
-
-void WebPluginImpl::CancelDocumentLoad() {
- if (webframe_) {
- ignore_response_error_ = true;
- webframe_->stopLoading();
- }
-}
-
-void WebPluginImpl::DidStartLoading() {
- if (render_view_.get()) {
- // TODO(darin): Make is_loading_ be a counter!
- render_view_->DidStartLoading();
- }
-}
-
-void WebPluginImpl::DidStopLoading() {
- if (render_view_.get()) {
- // TODO(darin): Make is_loading_ be a counter!
- render_view_->DidStopLoading();
- }
-}
-
-void WebPluginImpl::SetDeferResourceLoading(unsigned long resource_id,
- bool defer) {
- std::vector<ClientInfo>::iterator client_index = clients_.begin();
- while (client_index != clients_.end()) {
- ClientInfo& client_info = *client_index;
-
- if (client_info.id == resource_id) {
- client_info.loader->setDefersLoading(defer);
-
- // If we determined that the request had failed via the HTTP headers
- // in the response then we send out a failure notification to the
- // plugin process, as certain plugins don't handle HTTP failure codes
- // correctly.
- if (!defer && client_info.client &&
- client_info.pending_failure_notification) {
- // The ClientInfo and the iterator can become invalid due to the call
- // to DidFail below.
- WebPluginResourceClient* resource_client = client_info.client;
- client_info.loader->cancel();
- clients_.erase(client_index++);
- resource_client->DidFail(resource_id);
- }
- break;
- }
- client_index++;
- }
-}
-
-bool WebPluginImpl::IsOffTheRecord() {
- return false;
-}
-
-bool WebPluginImpl::HandleHttpMultipartResponse(
- const WebURLResponse& response, WebPluginResourceClient* client) {
- std::string multipart_boundary;
- if (!MultipartResponseDelegate::ReadMultipartBoundary(
- response, &multipart_boundary)) {
- return false;
- }
-
- DidStartLoading();
-
- MultiPartResponseClient* multi_part_response_client =
- new MultiPartResponseClient(client);
-
- MultipartResponseDelegate* multi_part_response_handler =
- new MultipartResponseDelegate(multi_part_response_client, NULL,
- response,
- multipart_boundary);
- multi_part_response_map_[client] = multi_part_response_handler;
- return true;
-}
-
-bool WebPluginImpl::ReinitializePluginForResponse(
- WebURLLoader* loader) {
- WebFrame* webframe = webframe_;
- if (!webframe)
- return false;
-
- WebView* webview = webframe->view();
- if (!webview)
- return false;
-
- WebPluginContainer* container_widget = container_;
-
- // Destroy the current plugin instance.
- TearDownPluginInstance(loader);
-
- container_ = container_widget;
- webframe_ = webframe;
-
- WebPluginDelegateProxy* plugin_delegate = new WebPluginDelegateProxy(
- this, mime_type_, render_view_, render_frame_);
-
- // Store the plugin's unique identifier, used by the container to track its
- // script objects, and enable script objects (since Initialize may use them
- // even if it fails).
- npp_ = plugin_delegate->GetPluginNPP();
- container_->allowScriptObjects();
-
- bool ok = plugin_delegate && plugin_delegate->Initialize(
- plugin_url_, arg_names_, arg_values_, load_manually_);
-
- if (!ok) {
- container_->clearScriptObjects();
- container_ = NULL;
- // TODO(iyengar) Should we delete the current plugin instance here?
- return false;
- }
-
- delegate_ = plugin_delegate;
-
- // Force a geometry update to occur to ensure that the plugin becomes
- // visible.
- container_->reportGeometry();
-
- // The plugin move sequences accumulated via DidMove are sent to the browser
- // whenever the renderer paints. Force a paint here to ensure that changes
- // to the plugin window are propagated to the browser.
- container_->invalidate();
- return true;
-}
-
-void WebPluginImpl::TearDownPluginInstance(
- WebURLLoader* loader_to_ignore) {
- // JavaScript garbage collection may cause plugin script object references to
- // be retained long after the plugin is destroyed. Some plugins won't cope
- // with their objects being released after they've been destroyed, and once
- // we've actually unloaded the plugin the object's releaseobject() code may
- // no longer be in memory. The container tracks the plugin's objects and lets
- // us invalidate them, releasing the references to them held by the JavaScript
- // runtime.
- if (container_) {
- container_->clearScriptObjects();
- container_->setWebLayer(NULL);
- }
-
- // Call PluginDestroyed() first to prevent the plugin from calling us back
- // in the middle of tearing down the render tree.
- if (delegate_) {
- // The plugin may call into the browser and pass script objects even during
- // teardown, so temporarily re-enable plugin script objects.
- DCHECK(container_);
- container_->allowScriptObjects();
-
- delegate_->PluginDestroyed();
- delegate_ = NULL;
-
- // Invalidate any script objects created during teardown here, before the
- // plugin might actually be unloaded.
- container_->clearScriptObjects();
- }
-
- // Cancel any pending requests because otherwise this deleted object will
- // be called by the ResourceDispatcher.
- std::vector<ClientInfo>::iterator client_index = clients_.begin();
- while (client_index != clients_.end()) {
- ClientInfo& client_info = *client_index;
-
- if (loader_to_ignore == client_info.loader) {
- client_index++;
- continue;
- }
-
- if (client_info.loader.get())
- client_info.loader->cancel();
-
- client_index = clients_.erase(client_index);
- }
-
- // This needs to be called now and not in the destructor since the
- // webframe_ might not be valid anymore.
- webframe_ = NULL;
-}
-
-void WebPluginImpl::SetReferrer(blink::WebURLRequest* request,
- ReferrerValue referrer_flag) {
- switch (referrer_flag) {
- case DOCUMENT_URL:
- webframe_->setReferrerForRequest(*request, GURL());
- break;
-
- case PLUGIN_SRC:
- webframe_->setReferrerForRequest(*request, plugin_url_);
- break;
-
- default:
- break;
- }
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/npapi/webplugin_impl.h b/chromium/content/renderer/npapi/webplugin_impl.h
deleted file mode 100644
index 108d1b5cf0d..00000000000
--- a/chromium/content/renderer/npapi/webplugin_impl.h
+++ /dev/null
@@ -1,327 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CONTENT_RENDERER_NPAPI_WEBPLUGIN_IMPL_H_
-#define CONTENT_RENDERER_NPAPI_WEBPLUGIN_IMPL_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <map>
-#include <string>
-#include <vector>
-
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/memory/weak_ptr.h"
-#include "build/build_config.h"
-#include "content/child/npapi/webplugin.h"
-#include "content/common/content_export.h"
-#include "content/common/webplugin_geometry.h"
-#include "third_party/WebKit/public/platform/WebRect.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
-#include "third_party/WebKit/public/platform/WebURLRequest.h"
-#include "third_party/WebKit/public/platform/WebVector.h"
-#include "third_party/WebKit/public/web/WebPlugin.h"
-#include "ui/gfx/native_widget_types.h"
-#include "url/gurl.h"
-
-namespace cc {
-class IOSurfaceLayer;
-}
-
-namespace blink {
-class WebFrame;
-class WebLayer;
-class WebPluginContainer;
-class WebURLResponse;
-class WebURLLoader;
-class WebURLRequest;
-struct WebPluginParams;
-}
-
-namespace content {
-class MultipartResponseDelegate;
-class RenderFrameImpl;
-class RenderViewImpl;
-class WebPluginDelegateProxy;
-
-// This is the WebKit side of the plugin implementation that forwards calls,
-// after changing out of WebCore types, to a delegate. The delegate may
-// be in a different process.
-class WebPluginImpl : public WebPlugin,
- public blink::WebPlugin {
- public:
- WebPluginImpl(
- blink::WebFrame* frame,
- const blink::WebPluginParams& params,
- const base::FilePath& file_path,
- const base::WeakPtr<RenderViewImpl>& render_view,
- RenderFrameImpl* render_frame);
- ~WebPluginImpl() override;
-
- // Helper function for sorting post data.
- CONTENT_EXPORT static bool SetPostData(blink::WebURLRequest* request,
- const char* buf,
- uint32_t length);
-
- blink::WebFrame* webframe() { return webframe_; }
-
- // blink::WebPlugin methods:
- bool initialize(blink::WebPluginContainer* container) override;
- void destroy() override;
- NPObject* scriptableObject() override;
- struct _NPP* pluginNPP() override;
- bool getFormValue(blink::WebString& value) override;
- void updateAllLifecyclePhases() override;
- void paint(blink::WebCanvas* canvas,
- const blink::WebRect& paint_rect) override;
- void updateGeometry(const blink::WebRect& window_rect,
- const blink::WebRect& clip_rect,
- const blink::WebRect& unobscured_rect,
- const blink::WebVector<blink::WebRect>& cut_outs_rects,
- bool is_visible) override;
- void updateFocus(bool focused, blink::WebFocusType focus_type) override;
- void updateVisibility(bool visible) override;
- bool acceptsInputEvents() override;
- blink::WebInputEventResult handleInputEvent(
- const blink::WebInputEvent& event,
- blink::WebCursorInfo& cursor_info) override;
- void didReceiveResponse(const blink::WebURLResponse& response) override {}
- void didReceiveData(const char* data, int data_length) override {}
- void didFinishLoading() override {}
- void didFailLoading(const blink::WebURLError& error) override {}
- bool isPlaceholder() override;
-
- // WebPlugin implementation:
- void SetWindow(gfx::PluginWindowHandle window) override;
- void SetAcceptsInputEvents(bool accepts) override;
- void WillDestroyWindow(gfx::PluginWindowHandle window) override;
- void CancelResource(unsigned long id) override;
- void Invalidate() override;
- void InvalidateRect(const gfx::Rect& rect) override;
- NPObject* GetWindowScriptNPObject() override;
- NPObject* GetPluginElement() override;
- bool FindProxyForUrl(const GURL& url, std::string* proxy_list) override;
- void SetCookie(const GURL& url,
- const GURL& first_party_for_cookies,
- const std::string& cookie) override;
- std::string GetCookies(const GURL& url,
- const GURL& first_party_for_cookies) override;
- void CancelDocumentLoad() override;
- void DidStartLoading() override;
- void DidStopLoading() override;
- bool IsOffTheRecord() override;
- void SetDeferResourceLoading(unsigned long resource_id, bool defer) override;
- void URLRedirectResponse(bool allow, int resource_id) override;
- bool CheckIfRunInsecureContent(const GURL& url) override;
-#if defined(OS_WIN)
- void SetWindowlessData(HANDLE pump_messages_event,
- gfx::NativeViewId dummy_activation_window) override {}
- void ReparentPluginWindow(HWND window, HWND parent) { }
- void ReportExecutableMemory(size_t size) { }
-#endif
-#if defined(OS_MACOSX)
- WebPluginAcceleratedSurface* GetAcceleratedSurface(
- gfx::GpuPreference gpu_preference) override;
- void AcceleratedPluginEnabledRendering() override;
- void AcceleratedPluginAllocatedIOSurface(int32_t width,
- int32_t height,
- uint32_t surface_id) override;
- void AcceleratedPluginSwappedIOSurface() override;
-#endif
-
- private:
- // Given a (maybe partial) url, completes using the base url.
- GURL CompleteURL(const char* url);
-
- enum RoutingStatus {
- ROUTED,
- NOT_ROUTED,
- INVALID_URL,
- GENERAL_FAILURE
- };
-
- // Determines the referrer value sent along with outgoing HTTP requests
- // issued by plugins.
- enum ReferrerValue {
- PLUGIN_SRC,
- DOCUMENT_URL,
- NO_REFERRER
- };
-
- // Given a download request, check if we need to route the output to a frame.
- // Returns ROUTED if the load is done and routed to a frame, NOT_ROUTED or
- // corresponding error codes otherwise.
- RoutingStatus RouteToFrame(const char* url,
- bool is_javascript_url,
- bool popups_allowed,
- const char* method,
- const char* target,
- const char* buf,
- unsigned int len,
- ReferrerValue referrer_flag);
-
- // Returns the next avaiable resource id. Returns 0 if the operation fails.
- // It may fail if the page has already been closed.
- unsigned long GetNextResourceId();
-
- gfx::Rect GetWindowClipRect(const gfx::Rect& rect);
-
- // Sets the actual Widget for the plugin.
- void SetContainer(blink::WebPluginContainer* container);
-
- // Destroys the plugin instance.
- // The response_handle_to_ignore parameter if not NULL indicates the
- // resource handle to be left valid during plugin shutdown.
- void TearDownPluginInstance(blink::WebURLLoader* loader_to_ignore);
-
- // WebURLLoaderClient implementation. We implement this interface in the
- // renderer process, and then use the simple WebPluginResourceClient interface
- // to relay the callbacks to the plugin.
- void willFollowRedirect(blink::WebURLLoader* loader,
- blink::WebURLRequest& new_request,
- const blink::WebURLResponse& response);
- void didSendData(blink::WebURLLoader* loader,
- unsigned long long bytes_sent,
- unsigned long long total_bytes_to_be_sent);
- void didReceiveResponse(blink::WebURLLoader* loader,
- const blink::WebURLResponse& response);
-
- void didReceiveData(blink::WebURLLoader* loader, const char *buffer,
- int data_length, int encoded_data_length);
- void didFinishLoading(blink::WebURLLoader* loader,
- double finishTime);
- void didFail(blink::WebURLLoader* loader,
- const blink::WebURLError& error);
-
- // Helper function to remove the stored information about a resource
- // request given its index in m_clients.
- void RemoveClient(size_t i);
-
- // Helper function to remove the stored information about a resource
- // request given a handle.
- void RemoveClient(blink::WebURLLoader* loader);
-
- // Handles HTTP multipart responses, i.e. responses received with a HTTP
- // status code of 206.
- // Returns false if response is not multipart (may be if we requested
- // single range).
- bool HandleHttpMultipartResponse(const blink::WebURLResponse& response,
- WebPluginResourceClient* client);
-
- // Tears down the existing plugin instance and creates a new plugin instance
- // to handle the response identified by the loader parameter.
- bool ReinitializePluginForResponse(blink::WebURLLoader* loader);
-
- struct ClientInfo;
-
- // Helper functions
- WebPluginResourceClient* GetClientFromLoader(blink::WebURLLoader* loader);
- ClientInfo* GetClientInfoFromLoader(blink::WebURLLoader* loader);
-
- // Helper function to set the referrer on the request passed in.
- void SetReferrer(blink::WebURLRequest* request, ReferrerValue referrer_flag);
-
- // Check for invalid chars like @, ;, \ before the first / (in path).
- bool IsValidUrl(const GURL& url, ReferrerValue referrer_flag);
-
- std::vector<ClientInfo> clients_;
-
- bool windowless_;
- gfx::PluginWindowHandle window_;
-#if defined(OS_MACOSX)
- bool next_io_surface_allocated_;
- int32_t next_io_surface_width_;
- int32_t next_io_surface_height_;
- uint32_t next_io_surface_id_;
- scoped_refptr<cc::IOSurfaceLayer> io_surface_layer_;
- scoped_ptr<blink::WebLayer> web_layer_;
-#endif
- bool accepts_input_events_;
- RenderFrameImpl* render_frame_;
- base::WeakPtr<RenderViewImpl> render_view_;
- blink::WebFrame* webframe_;
-
- WebPluginDelegateProxy* delegate_;
-
- // This is just a weak reference.
- blink::WebPluginContainer* container_;
-
- // Unique identifier for this plugin, used to track script objects.
- struct _NPP* npp_;
-
- typedef std::map<WebPluginResourceClient*, MultipartResponseDelegate*>
- MultiPartResponseHandlerMap;
- // Tracks HTTP multipart response handlers instantiated for
- // a WebPluginResourceClient instance.
- MultiPartResponseHandlerMap multi_part_response_map_;
-
- // The plugin source URL.
- GURL plugin_url_;
-
- // Indicates if the download would be initiated by the plugin or us.
- bool load_manually_;
-
- // Indicates if this is the first geometry update received by the plugin.
- bool first_geometry_update_;
-
- // Set to true if the next response error should be ignored.
- bool ignore_response_error_;
-
- // The current plugin geometry and clip rectangle.
- WebPluginGeometry geometry_;
-
- // The location of the plugin on disk.
- base::FilePath file_path_;
-
- // The mime type of the plugin.
- std::string mime_type_;
-
- // Holds the list of argument names and values passed to the plugin. We keep
- // these so that we can re-initialize the plugin if we need to.
- std::vector<std::string> arg_names_;
- std::vector<std::string> arg_values_;
-
- class LoaderClient : public blink::WebURLLoaderClient {
- public:
- LoaderClient(WebPluginImpl*);
-
- void willFollowRedirect(blink::WebURLLoader*,
- blink::WebURLRequest&,
- const blink::WebURLResponse&) override;
- void didSendData(blink::WebURLLoader*,
- unsigned long long bytesSent,
- unsigned long long totalBytesToBeSent) override;
- void didReceiveResponse(blink::WebURLLoader*,
- const blink::WebURLResponse&) override;
- void didDownloadData(blink::WebURLLoader*,
- int dataLength,
- int encodedDataLength) override;
- void didReceiveData(blink::WebURLLoader*,
- const char* data,
- int dataLength,
- int encodedDataLength) override;
- void didReceiveCachedMetadata(blink::WebURLLoader*,
- const char* data,
- int dataLength) override;
- void didFinishLoading(blink::WebURLLoader*,
- double finishTime,
- int64_t total_encoded_data_length) override;
- void didFail(blink::WebURLLoader*, const blink::WebURLError&) override;
-
- private:
- WebPluginImpl* parent_;
- };
-
- LoaderClient loader_client_;
-
- DISALLOW_COPY_AND_ASSIGN(WebPluginImpl);
-};
-
-} // namespace content
-
-#endif // CONTENT_RENDERER_NPAPI_WEBPLUGIN_IMPL_H_
diff --git a/chromium/content/renderer/npapi/webplugin_impl_unittest.cc b/chromium/content/renderer/npapi/webplugin_impl_unittest.cc
deleted file mode 100644
index 2cec6b8231c..00000000000
--- a/chromium/content/renderer/npapi/webplugin_impl_unittest.cc
+++ /dev/null
@@ -1,235 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "base/strings/string_util.h"
-#include "content/renderer/npapi/webplugin_impl.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/WebKit/public/platform/WebCString.h"
-#include "third_party/WebKit/public/platform/WebString.h"
-#include "third_party/WebKit/public/platform/WebURLRequest.h"
-
-using blink::WebHTTPBody;
-using blink::WebString;
-using blink::WebURLRequest;
-
-namespace content {
-
-namespace {
-
-std::string GetHeader(const WebURLRequest& request, const char* name) {
- std::string result;
- base::TrimWhitespaceASCII(
- request.httpHeaderField(WebString::fromUTF8(name)).utf8(),
- base::TRIM_ALL,
- &result);
- return result;
-}
-
-std::string GetBodyText(const WebURLRequest& request) {
- const WebHTTPBody& body = request.httpBody();
- if (body.isNull())
- return std::string();
-
- std::string result;
- size_t i = 0;
- WebHTTPBody::Element element;
- while (body.elementAt(i++, element)) {
- if (element.type == WebHTTPBody::Element::TypeData) {
- result.append(element.data.data(), element.data.size());
- } else {
- NOTREACHED() << "unexpected element type encountered!";
- }
- }
- return result;
-}
-
-} // namespace
-
-// The Host functions for NPN_PostURL and NPN_PostURLNotify
-// need to parse out some HTTP headers. Make sure it works
-// with the following tests
-
-TEST(WebPluginImplTest, PostParserSimple) {
- // Test a simple case with headers & data
- const char *ex1 = "foo: bar\nContent-length: 10\n\nabcdefghij";
- WebURLRequest request;
- request.initialize();
- bool rv = WebPluginImpl::SetPostData(&request, ex1,
- static_cast<uint32_t>(strlen(ex1)));
- EXPECT_TRUE(rv);
- EXPECT_EQ("bar", GetHeader(request, "foo"));
- EXPECT_EQ(0U, GetHeader(request, "bar").length());
- EXPECT_EQ(0U, GetHeader(request, "Content-length").length());
- EXPECT_EQ("abcdefghij", GetBodyText(request));
-}
-
-TEST(WebPluginImplTest, PostParserLongHeader) {
- // Test a simple case with long headers
- const char *ex1 = "foo: 0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789\n\nabcdefghij";
- WebURLRequest request;
- request.initialize();
- bool rv = WebPluginImpl::SetPostData(&request, ex1,
- static_cast<uint32_t>(strlen(ex1)));
- EXPECT_TRUE(rv);
- EXPECT_EQ(100U, GetHeader(request, "foo").length());
-}
-
-TEST(WebPluginImplTest, PostParserManyHeaders) {
- // Test a simple case with long headers
- const char *ex1 = "h1:h1\nh2:h2\nh3:h3\nh4:h4\nh5:h5\nh6:h6\nh7:h7\nh8:h8\nh9:h9\nh10:h10\n\nbody";
- WebURLRequest request;
- request.initialize();
- bool rv = WebPluginImpl::SetPostData(&request, ex1,
- static_cast<uint32_t>(strlen(ex1)));
- EXPECT_TRUE(rv);
- EXPECT_EQ("h1", GetHeader(request, "h1"));
- EXPECT_EQ("h2", GetHeader(request, "h2"));
- EXPECT_EQ("h3", GetHeader(request, "h3"));
- EXPECT_EQ("h4", GetHeader(request, "h4"));
- EXPECT_EQ("h5", GetHeader(request, "h5"));
- EXPECT_EQ("h6", GetHeader(request, "h6"));
- EXPECT_EQ("h7", GetHeader(request, "h7"));
- EXPECT_EQ("h8", GetHeader(request, "h8"));
- EXPECT_EQ("h9", GetHeader(request, "h9"));
- EXPECT_EQ("h10", GetHeader(request, "h10"));
- EXPECT_EQ("body", GetBodyText(request));
-}
-
-TEST(WebPluginImplTest, PostParserDuplicateHeaders) {
- // Test a simple case with long headers
- // What value gets returned doesn't really matter. It shouldn't error
- // out.
- const char *ex1 = "h1:h1\nh1:h2\n\nbody";
- WebURLRequest request;
- request.initialize();
- bool rv = WebPluginImpl::SetPostData(&request, ex1,
- static_cast<uint32_t>(strlen(ex1)));
- EXPECT_TRUE(rv);
-}
-
-TEST(WebPluginImplTest, PostParserNoHeaders) {
- // Test a simple case with no headers but with data
- const char *ex1 = "\nabcdefghij";
- WebURLRequest request;
- request.initialize();
- bool rv = WebPluginImpl::SetPostData(&request, ex1,
- static_cast<uint32_t>(strlen(ex1)));
- EXPECT_TRUE(rv);
- EXPECT_EQ(0U, GetHeader(request, "foo").length());
- EXPECT_EQ(0U, GetHeader(request, "bar").length());
- EXPECT_EQ(0U, GetHeader(request, "Content-length").length());
- EXPECT_EQ("abcdefghij", GetBodyText(request));
-}
-
-TEST(WebPluginImplTest, PostParserNoBody) {
- // Test a simple case with headers and no body
- const char *ex1 = "Foo:bar\n\n";
- WebURLRequest request;
- request.initialize();
- bool rv = WebPluginImpl::SetPostData(&request, ex1,
- static_cast<uint32_t>(strlen(ex1)));
- EXPECT_TRUE(rv);
- EXPECT_EQ("bar", GetHeader(request, "foo"));
- EXPECT_EQ(0U, GetHeader(request, "bar").length());
- EXPECT_EQ(0U, GetHeader(request, "Content-length").length());
- EXPECT_EQ(0U, GetBodyText(request).length());
-}
-
-TEST(WebPluginImplTest, PostParserBodyWithNewLines) {
- // Test a simple case with headers and no body
- const char *ex1 = "Foo:bar\n\n\n\nabcdefg\n\nabcdefg";
- WebURLRequest request;
- request.initialize();
- bool rv = WebPluginImpl::SetPostData(&request, ex1,
- static_cast<uint32_t>(strlen(ex1)));
- EXPECT_TRUE(rv);
- EXPECT_EQ(GetBodyText(request), "\n\nabcdefg\n\nabcdefg");
-}
-
-TEST(WebPluginImplTest, PostParserErrorNoBody) {
- // Test with headers and no body
- const char *ex1 = "Foo:bar\n";
- WebURLRequest request;
- request.initialize();
- bool rv = WebPluginImpl::SetPostData(&request, ex1,
- static_cast<uint32_t>(strlen(ex1)));
- EXPECT_TRUE(rv);
-}
-
-TEST(WebPluginImplTest, PostParserErrorEmpty) {
- // Test with an empty string
- const char *ex1 = "";
- WebURLRequest request;
- request.initialize();
- bool rv = WebPluginImpl::SetPostData(&request, ex1,
- static_cast<uint32_t>(strlen(ex1)));
- EXPECT_TRUE(rv);
-}
-
-TEST(WebPluginImplTest, PostParserEmptyName) {
- // Test an error case with an empty header name field
- const char *ex1 = "foo:bar\n:blat\n\nbody";
- WebURLRequest request;
- request.initialize();
- bool rv = WebPluginImpl::SetPostData(&request, ex1,
- static_cast<uint32_t>(strlen(ex1)));
- EXPECT_TRUE(rv);
- EXPECT_EQ("bar", GetHeader(request, "foo"));
- EXPECT_EQ("body", GetBodyText(request));
-}
-
-TEST(WebPluginImplTest, PostParserEmptyValue) {
- // Test an error case with an empty value field
- const char *ex1 = "foo:bar\nbar:\n\nbody";
- WebURLRequest request;
- request.initialize();
- bool rv = WebPluginImpl::SetPostData(&request, ex1,
- static_cast<uint32_t>(strlen(ex1)));
- EXPECT_TRUE(rv);
- EXPECT_EQ("bar", GetHeader(request, "foo"));
- EXPECT_EQ(0U, GetHeader(request, "bar").length());
- EXPECT_EQ("body", GetBodyText(request));
-}
-
-TEST(WebPluginImplTest, PostParserCRLF) {
- // Test an error case with an empty value field
- const char *ex1 = "foo: bar\r\nbar:\r\n\r\nbody\r\n\r\nbody2";
- WebURLRequest request;
- request.initialize();
- bool rv = WebPluginImpl::SetPostData(&request, ex1,
- static_cast<uint32_t>(strlen(ex1)));
- EXPECT_TRUE(rv);
- EXPECT_EQ("bar", GetHeader(request, "foo"));
- EXPECT_EQ(0U, GetHeader(request, "bar").length());
- EXPECT_EQ("body\r\n\r\nbody2", GetBodyText(request));
-}
-
-TEST(WebPluginImplTest, PostParserBodyWithBinaryData) {
- // Test a simple case with headers and binary data.
- char ex1[33] = "foo: bar\nContent-length: 10\n\n";
- unsigned int binary_data = 0xFFFFFFF0;
- memcpy(ex1 + strlen("foo: bar\nContent-length: 10\n\n"), &binary_data,
- sizeof(binary_data));
-
- WebURLRequest request;
- request.initialize();
- bool rv = WebPluginImpl::SetPostData(&request, ex1,
- sizeof(ex1)/sizeof(ex1[0]));
- EXPECT_TRUE(rv);
- EXPECT_EQ("bar", GetHeader(request, "foo"));
- EXPECT_EQ(0U, GetHeader(request, "bar").length());
- EXPECT_EQ(0U, GetHeader(request, "Content-length").length());
-
- std::string body = GetBodyText(request);
-
- EXPECT_EQ(0xF0, (unsigned char)body[0]);
- EXPECT_EQ(0xFF, (unsigned char)body[1]);
- EXPECT_EQ(0xFF, (unsigned char)body[2]);
- EXPECT_EQ(0xFF, (unsigned char)body[3]);
-}
-
-} // namespace content
diff --git a/chromium/content/renderer/origin_trials/web_trial_token_validator_impl.cc b/chromium/content/renderer/origin_trials/web_trial_token_validator_impl.cc
new file mode 100644
index 00000000000..01078edf564
--- /dev/null
+++ b/chromium/content/renderer/origin_trials/web_trial_token_validator_impl.cc
@@ -0,0 +1,22 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/origin_trials/web_trial_token_validator_impl.h"
+
+#include "content/common/origin_trials/trial_token_validator.h"
+
+namespace content {
+
+WebTrialTokenValidatorImpl::WebTrialTokenValidatorImpl() {}
+WebTrialTokenValidatorImpl::~WebTrialTokenValidatorImpl() {}
+
+bool WebTrialTokenValidatorImpl::validateToken(
+ const blink::WebString& token,
+ const blink::WebSecurityOrigin& origin,
+ const blink::WebString& featureName) {
+ return TrialTokenValidator::ValidateToken(token.utf8(), origin,
+ featureName.utf8());
+}
+
+} // namespace content
diff --git a/chromium/content/renderer/origin_trials/web_trial_token_validator_impl.h b/chromium/content/renderer/origin_trials/web_trial_token_validator_impl.h
new file mode 100644
index 00000000000..7cb11877429
--- /dev/null
+++ b/chromium/content/renderer/origin_trials/web_trial_token_validator_impl.h
@@ -0,0 +1,37 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_ORIGIN_TRIALS_WEB_TRIAL_TOKEN_VALIDATOR_IMPL_H_
+#define CONTENT_RENDERER_ORIGIN_TRIALS_WEB_TRIAL_TOKEN_VALIDATOR_IMPL_H_
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "content/common/content_export.h"
+#include "third_party/WebKit/public/platform/WebTrialTokenValidator.h"
+
+namespace content {
+
+// The TrialTokenValidator is called by the Experimental Framework code in Blink
+// to validate tokens to enable experimental features.
+//
+// This class is thread-safe.
+class CONTENT_EXPORT WebTrialTokenValidatorImpl
+ : public NON_EXPORTED_BASE(blink::WebTrialTokenValidator) {
+ public:
+ WebTrialTokenValidatorImpl();
+ ~WebTrialTokenValidatorImpl() override;
+
+ // blink::WebTrialTokenValidator implementation
+ bool validateToken(const blink::WebString& token,
+ const blink::WebSecurityOrigin& origin,
+ const blink::WebString& featureName) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WebTrialTokenValidatorImpl);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_ORIGIN_TRIALS_WEB_TRIAL_TOKEN_VALIDATOR_IMPL_H_
diff --git a/chromium/content/renderer/p2p/filtering_network_manager.cc b/chromium/content/renderer/p2p/filtering_network_manager.cc
index a835ab8c60b..df7de667fb3 100644
--- a/chromium/content/renderer/p2p/filtering_network_manager.cc
+++ b/chromium/content/renderer/p2p/filtering_network_manager.cc
@@ -17,9 +17,9 @@ namespace content {
FilteringNetworkManager::FilteringNetworkManager(
rtc::NetworkManager* network_manager,
const GURL& requesting_origin,
- scoped_ptr<media::MediaPermission> media_permission)
+ media::MediaPermission* media_permission)
: network_manager_(network_manager),
- media_permission_(std::move(media_permission)),
+ media_permission_(media_permission),
requesting_origin_(requesting_origin),
weak_ptr_factory_(this) {
thread_checker_.DetachFromThread();
diff --git a/chromium/content/renderer/p2p/filtering_network_manager.h b/chromium/content/renderer/p2p/filtering_network_manager.h
index c7c68bf2614..7b0fca26231 100644
--- a/chromium/content/renderer/p2p/filtering_network_manager.h
+++ b/chromium/content/renderer/p2p/filtering_network_manager.h
@@ -42,7 +42,7 @@ class FilteringNetworkManager : public rtc::NetworkManagerBase,
CONTENT_EXPORT FilteringNetworkManager(
rtc::NetworkManager* network_manager,
const GURL& requesting_origin,
- scoped_ptr<media::MediaPermission> media_permission);
+ media::MediaPermission* media_permission);
CONTENT_EXPORT ~FilteringNetworkManager() override;
@@ -95,7 +95,7 @@ class FilteringNetworkManager : public rtc::NetworkManagerBase,
// The class is created by the signaling thread but used by the worker thread.
base::ThreadChecker thread_checker_;
- scoped_ptr<media::MediaPermission> media_permission_;
+ media::MediaPermission* media_permission_;
int pending_permission_checks_ = 0;
diff --git a/chromium/content/renderer/p2p/filtering_network_manager_unittest.cc b/chromium/content/renderer/p2p/filtering_network_manager_unittest.cc
index 29d89e331ca..d708428c042 100644
--- a/chromium/content/renderer/p2p/filtering_network_manager_unittest.cc
+++ b/chromium/content/renderer/p2p/filtering_network_manager_unittest.cc
@@ -10,6 +10,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/test/test_simple_task_runner.h"
#include "base/thread_task_runner_handle.h"
#include "content/renderer/p2p/empty_network_manager.h"
@@ -127,17 +128,15 @@ class FilteringNetworkManagerTest : public testing::Test,
public sigslot::has_slots<> {
public:
FilteringNetworkManagerTest()
- : task_runner_(new base::TestSimpleTaskRunner()),
+ : media_permission_(new MockMediaPermission()),
+ task_runner_(new base::TestSimpleTaskRunner()),
task_runner_handle_(task_runner_) {}
void SetupNetworkManager(bool multiple_routes_requested) {
mock_network_manager_.reset(new MockNetworkManager());
-
- scoped_ptr<MockMediaPermission> media_permission(new MockMediaPermission());
- media_permission_ = media_permission.get();
if (multiple_routes_requested) {
FilteringNetworkManager* filtering_network_manager =
new FilteringNetworkManager(mock_network_manager_.get(), GURL(),
- std::move(media_permission));
+ media_permission_.get());
filtering_network_manager->Initialize();
network_manager_.reset(filtering_network_manager);
} else {
@@ -205,8 +204,7 @@ class FilteringNetworkManagerTest : public testing::Test,
scoped_ptr<rtc::NetworkManager> network_manager_;
scoped_ptr<MockNetworkManager> mock_network_manager_;
- // Raw pointer to MockMediaPermission. It's owned by FilteringNetworkManager.
- MockMediaPermission* media_permission_ = nullptr;
+ scoped_ptr<MockMediaPermission> media_permission_;
NetworkList network_list_;
scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
diff --git a/chromium/content/renderer/p2p/host_address_request.h b/chromium/content/renderer/p2p/host_address_request.h
index 1734d2a1ead..dfcb14f49c6 100644
--- a/chromium/content/renderer/p2p/host_address_request.h
+++ b/chromium/content/renderer/p2p/host_address_request.h
@@ -13,7 +13,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
-#include "net/base/ip_address_number.h"
+#include "net/base/ip_address.h"
#include "third_party/webrtc/base/asyncresolverinterface.h"
namespace base {
diff --git a/chromium/content/renderer/p2p/ipc_network_manager.cc b/chromium/content/renderer/p2p/ipc_network_manager.cc
index 1c9acb91dd4..326d6462a21 100644
--- a/chromium/content/renderer/p2p/ipc_network_manager.cc
+++ b/chromium/content/renderer/p2p/ipc_network_manager.cc
@@ -14,8 +14,7 @@
#include "base/thread_task_runner_handle.h"
#include "content/public/common/content_switches.h"
#include "jingle/glue/utils.h"
-#include "net/base/ip_address_number.h"
-#include "net/base/net_util.h"
+#include "net/base/ip_address.h"
#include "net/base/network_change_notifier.h"
#include "net/base/network_interfaces.h"
#include "third_party/webrtc/base/socketaddress.h"
@@ -74,8 +73,8 @@ void IpcNetworkManager::StopUpdating() {
void IpcNetworkManager::OnNetworkListChanged(
const net::NetworkInterfaceList& list,
- const net::IPAddressNumber& default_ipv4_local_address,
- const net::IPAddressNumber& default_ipv6_local_address) {
+ const net::IPAddress& default_ipv4_local_address,
+ const net::IPAddress& default_ipv6_local_address) {
// Update flag if network list received for the first time.
if (!network_list_received_)
network_list_received_ = true;
@@ -91,7 +90,7 @@ void IpcNetworkManager::OnNetworkListChanged(
for (net::NetworkInterfaceList::const_iterator it = list.begin();
it != list.end(); it++) {
rtc::IPAddress ip_address =
- jingle_glue::IPAddressNumberToIPAddress(it->address);
+ jingle_glue::NetIPAddressToRtcIPAddress(it->address);
DCHECK(!ip_address.IsNil());
rtc::IPAddress prefix = rtc::TruncateIP(ip_address, it->prefix_length);
@@ -101,11 +100,11 @@ void IpcNetworkManager::OnNetworkListChanged(
network->set_default_local_address_provider(this);
rtc::InterfaceAddress iface_addr;
- if (it->address.size() == net::kIPv4AddressSize) {
+ if (it->address.IsIPv4()) {
use_default_ipv4_address |= (default_ipv4_local_address == it->address);
iface_addr = rtc::InterfaceAddress(ip_address);
} else {
- DCHECK(it->address.size() == net::kIPv6AddressSize);
+ DCHECK(it->address.IsIPv6());
iface_addr = rtc::InterfaceAddress(ip_address, it->ip_address_attributes);
// Only allow non-private, non-deprecated IPv6 addresses which don't
@@ -127,11 +126,11 @@ void IpcNetworkManager::OnNetworkListChanged(
rtc::IPAddress ipv6_defualt;
if (use_default_ipv4_address) {
ipv4_default =
- jingle_glue::IPAddressNumberToIPAddress(default_ipv4_local_address);
+ jingle_glue::NetIPAddressToRtcIPAddress(default_ipv4_local_address);
}
if (use_default_ipv6_address) {
ipv6_defualt =
- jingle_glue::IPAddressNumberToIPAddress(default_ipv6_local_address);
+ jingle_glue::NetIPAddressToRtcIPAddress(default_ipv6_local_address);
}
set_default_local_addresses(ipv4_default, ipv6_defualt);
diff --git a/chromium/content/renderer/p2p/ipc_network_manager.h b/chromium/content/renderer/p2p/ipc_network_manager.h
index 40e631ab5d1..c2ee02b7afd 100644
--- a/chromium/content/renderer/p2p/ipc_network_manager.h
+++ b/chromium/content/renderer/p2p/ipc_network_manager.h
@@ -14,6 +14,10 @@
#include "content/renderer/p2p/network_list_observer.h"
#include "third_party/webrtc/base/network.h"
+namespace net {
+class IPAddress;
+}
+
namespace content {
// IpcNetworkManager is a NetworkManager for libjingle that gets a
@@ -32,8 +36,8 @@ class IpcNetworkManager : public rtc::NetworkManagerBase,
// P2PSocketDispatcher::NetworkListObserver interface.
void OnNetworkListChanged(
const net::NetworkInterfaceList& list,
- const net::IPAddressNumber& default_ipv4_local_address,
- const net::IPAddressNumber& default_ipv6_local_address) override;
+ const net::IPAddress& default_ipv4_local_address,
+ const net::IPAddress& default_ipv6_local_address) override;
private:
void SendNetworksChangedSignal();
diff --git a/chromium/content/renderer/p2p/ipc_network_manager_unittest.cc b/chromium/content/renderer/p2p/ipc_network_manager_unittest.cc
index 7baaaf25c05..fb87c9e560c 100644
--- a/chromium/content/renderer/p2p/ipc_network_manager_unittest.cc
+++ b/chromium/content/renderer/p2p/ipc_network_manager_unittest.cc
@@ -5,8 +5,7 @@
#include "base/memory/scoped_ptr.h"
#include "content/renderer/p2p/ipc_network_manager.h"
#include "content/renderer/p2p/network_list_manager.h"
-#include "net/base/ip_address_number.h"
-#include "net/base/net_util.h"
+#include "net/base/ip_address.h"
#include "net/base/network_change_notifier.h"
#include "net/base/network_interfaces.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -54,33 +53,23 @@ class IpcNetworkManagerTest : public testing::Test {
// issue 19249005 integrated into chromium
TEST_F(IpcNetworkManagerTest, TestMergeNetworkList) {
net::NetworkInterfaceList list;
- net::IPAddressNumber ip_number;
+ net::IPAddress ip;
std::vector<rtc::Network*> networks;
rtc::IPAddress ip_address;
// Add 2 networks with the same prefix and prefix length.
- EXPECT_TRUE(net::ParseIPLiteralToNumber(kIPv6PublicAddrString1, &ip_number));
- list.push_back(
- net::NetworkInterface("em1",
- "em1",
- 0,
- net::NetworkChangeNotifier::CONNECTION_UNKNOWN,
- ip_number,
- 64,
- net::IP_ADDRESS_ATTRIBUTE_NONE));
-
- EXPECT_TRUE(net::ParseIPLiteralToNumber(kIPv6PublicAddrString2, &ip_number));
- list.push_back(
- net::NetworkInterface("em1",
- "em1",
- 0,
- net::NetworkChangeNotifier::CONNECTION_UNKNOWN,
- ip_number,
- 64,
- net::IP_ADDRESS_ATTRIBUTE_NONE));
-
- network_manager_->OnNetworkListChanged(list, net::IPAddressNumber(),
- net::IPAddressNumber());
+ EXPECT_TRUE(ip.AssignFromIPLiteral(kIPv6PublicAddrString1));
+ list.push_back(net::NetworkInterface(
+ "em1", "em1", 0, net::NetworkChangeNotifier::CONNECTION_UNKNOWN, ip, 64,
+ net::IP_ADDRESS_ATTRIBUTE_NONE));
+
+ EXPECT_TRUE(ip.AssignFromIPLiteral(kIPv6PublicAddrString2));
+ list.push_back(net::NetworkInterface(
+ "em1", "em1", 0, net::NetworkChangeNotifier::CONNECTION_UNKNOWN, ip, 64,
+ net::IP_ADDRESS_ATTRIBUTE_NONE));
+
+ network_manager_->OnNetworkListChanged(list, net::IPAddress(),
+ net::IPAddress());
network_manager_->GetNetworks(&networks);
EXPECT_EQ(1uL, networks.size());
EXPECT_EQ(2uL, networks[0]->GetIPs().size());
@@ -88,19 +77,13 @@ TEST_F(IpcNetworkManagerTest, TestMergeNetworkList) {
// Add another network with different prefix length, should result in
// a different network.
networks.clear();
- list.push_back(
- net::NetworkInterface("em1",
- "em1",
- 0,
- net::NetworkChangeNotifier::CONNECTION_UNKNOWN,
- ip_number,
- 48,
- net::IP_ADDRESS_ATTRIBUTE_NONE));
+ list.push_back(net::NetworkInterface(
+ "em1", "em1", 0, net::NetworkChangeNotifier::CONNECTION_UNKNOWN, ip, 48,
+ net::IP_ADDRESS_ATTRIBUTE_NONE));
// Push an unknown address as the default address.
- EXPECT_TRUE(net::ParseIPLiteralToNumber(kIPv4MappedAddrString, &ip_number));
- network_manager_->OnNetworkListChanged(list, net::IPAddressNumber(),
- ip_number);
+ EXPECT_TRUE(ip.AssignFromIPLiteral(kIPv4MappedAddrString));
+ network_manager_->OnNetworkListChanged(list, net::IPAddress(), ip);
// The unknown default address should be ignored.
EXPECT_FALSE(network_manager_->GetDefaultLocalAddress(AF_INET6, &ip_address));
diff --git a/chromium/content/renderer/p2p/ipc_socket_factory.cc b/chromium/content/renderer/p2p/ipc_socket_factory.cc
index 779bb216dd5..20fa056aca9 100644
--- a/chromium/content/renderer/p2p/ipc_socket_factory.cc
+++ b/chromium/content/renderer/p2p/ipc_socket_factory.cc
@@ -24,6 +24,7 @@
#include "content/renderer/p2p/socket_client_impl.h"
#include "content/renderer/p2p/socket_dispatcher.h"
#include "jingle/glue/utils.h"
+#include "net/base/ip_address.h"
#include "third_party/webrtc/base/asyncpacketsocket.h"
namespace content {
@@ -317,7 +318,7 @@ bool IpcPacketSocket::Init(P2PSocketType type,
if (remote_address.IsUnresolvedIP()) {
remote_endpoint =
- net::IPEndPoint(net::IPAddressNumber(), remote_address.port());
+ net::IPEndPoint(net::IPAddress(), remote_address.port());
} else {
if (!jingle_glue::SocketAddressToIPEndPoint(remote_address,
&remote_endpoint)) {
@@ -420,7 +421,7 @@ int IpcPacketSocket::SendTo(const void *data, size_t data_size,
net::IPEndPoint address_chrome;
if (address.IsUnresolvedIP()) {
- address_chrome = net::IPEndPoint(net::IPAddressNumber(), address.port());
+ address_chrome = net::IPEndPoint(net::IPAddress(), address.port());
} else {
if (!jingle_glue::SocketAddressToIPEndPoint(address, &address_chrome)) {
LOG(WARNING) << "Failed to convert remote address to IPEndPoint: address="
diff --git a/chromium/content/renderer/p2p/network_list_observer.h b/chromium/content/renderer/p2p/network_list_observer.h
index c0fcc59c8a0..309f0ce0f0b 100644
--- a/chromium/content/renderer/p2p/network_list_observer.h
+++ b/chromium/content/renderer/p2p/network_list_observer.h
@@ -7,9 +7,8 @@
#include <vector>
-#include "net/base/ip_address_number.h"
-
namespace net {
+class IPAddress;
struct NetworkInterface;
typedef std::vector<NetworkInterface> NetworkInterfaceList;
} // namespace net
@@ -22,8 +21,8 @@ class NetworkListObserver {
virtual void OnNetworkListChanged(
const net::NetworkInterfaceList& list,
- const net::IPAddressNumber& default_ipv4_local_address,
- const net::IPAddressNumber& default_ipv6_local_address) = 0;
+ const net::IPAddress& default_ipv4_local_address,
+ const net::IPAddress& default_ipv6_local_address) = 0;
protected:
NetworkListObserver() {}
diff --git a/chromium/content/renderer/p2p/port_allocator.cc b/chromium/content/renderer/p2p/port_allocator.cc
index 89d3b919f6e..c9bc9fadf1d 100644
--- a/chromium/content/renderer/p2p/port_allocator.cc
+++ b/chromium/content/renderer/p2p/port_allocator.cc
@@ -5,6 +5,8 @@
#include "content/renderer/p2p/port_allocator.h"
#include <stdint.h>
+
+#include <memory>
#include <utility>
#include "base/command_line.h"
@@ -16,7 +18,7 @@ namespace content {
P2PPortAllocator::P2PPortAllocator(
const scoped_refptr<P2PSocketDispatcher>& socket_dispatcher,
- scoped_ptr<rtc::NetworkManager> network_manager,
+ std::unique_ptr<rtc::NetworkManager> network_manager,
rtc::PacketSocketFactory* socket_factory,
const Config& config,
const GURL& origin,
diff --git a/chromium/content/renderer/p2p/port_allocator.h b/chromium/content/renderer/p2p/port_allocator.h
index 480ad5c0b8a..945b5f87e6e 100644
--- a/chromium/content/renderer/p2p/port_allocator.h
+++ b/chromium/content/renderer/p2p/port_allocator.h
@@ -5,6 +5,8 @@
#ifndef CONTENT_RENDERER_P2P_PORT_ALLOCATOR_H_
#define CONTENT_RENDERER_P2P_PORT_ALLOCATOR_H_
+#include <memory>
+
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/single_thread_task_runner.h"
@@ -38,7 +40,7 @@ class P2PPortAllocator : public cricket::BasicPortAllocator {
P2PPortAllocator(
const scoped_refptr<P2PSocketDispatcher>& socket_dispatcher,
- scoped_ptr<rtc::NetworkManager> network_manager,
+ std::unique_ptr<rtc::NetworkManager> network_manager,
rtc::PacketSocketFactory* socket_factory,
const Config& config,
const GURL& origin,
@@ -46,7 +48,7 @@ class P2PPortAllocator : public cricket::BasicPortAllocator {
~P2PPortAllocator() override;
private:
- scoped_ptr<rtc::NetworkManager> network_manager_;
+ std::unique_ptr<rtc::NetworkManager> network_manager_;
scoped_refptr<P2PSocketDispatcher> socket_dispatcher_;
Config config_;
GURL origin_;
diff --git a/chromium/content/renderer/p2p/socket_dispatcher.cc b/chromium/content/renderer/p2p/socket_dispatcher.cc
index fce70e27009..c8e0779bc1b 100644
--- a/chromium/content/renderer/p2p/socket_dispatcher.cc
+++ b/chromium/content/renderer/p2p/socket_dispatcher.cc
@@ -125,8 +125,8 @@ void P2PSocketDispatcher::UnregisterHostAddressRequest(int id) {
void P2PSocketDispatcher::OnNetworkListChanged(
const net::NetworkInterfaceList& networks,
- const net::IPAddressNumber& default_ipv4_local_address,
- const net::IPAddressNumber& default_ipv6_local_address) {
+ const net::IPAddress& default_ipv4_local_address,
+ const net::IPAddress& default_ipv6_local_address) {
network_list_observers_->Notify(
FROM_HERE, &NetworkListObserver::OnNetworkListChanged, networks,
default_ipv4_local_address, default_ipv6_local_address);
diff --git a/chromium/content/renderer/p2p/socket_dispatcher.h b/chromium/content/renderer/p2p/socket_dispatcher.h
index 527921b30f4..0b23dd0c3c0 100644
--- a/chromium/content/renderer/p2p/socket_dispatcher.h
+++ b/chromium/content/renderer/p2p/socket_dispatcher.h
@@ -35,8 +35,7 @@
#include "content/common/p2p_socket_type.h"
#include "content/renderer/p2p/network_list_manager.h"
#include "ipc/message_filter.h"
-#include "net/base/ip_address_number.h"
-#include "net/base/ip_endpoint.h"
+#include "net/base/ip_address.h"
#include "net/base/network_interfaces.h"
namespace base {
@@ -96,10 +95,9 @@ class CONTENT_EXPORT P2PSocketDispatcher : public IPC::MessageFilter,
void UnregisterHostAddressRequest(int id);
// Incoming message handlers.
- void OnNetworkListChanged(
- const net::NetworkInterfaceList& networks,
- const net::IPAddressNumber& default_ipv4_local_address,
- const net::IPAddressNumber& default_ipv6_local_address);
+ void OnNetworkListChanged(const net::NetworkInterfaceList& networks,
+ const net::IPAddress& default_ipv4_local_address,
+ const net::IPAddress& default_ipv6_local_address);
void OnGetHostAddressResult(int32_t request_id,
const net::IPAddressList& addresses);
void OnSocketCreated(int socket_id,
diff --git a/chromium/content/renderer/pepper/DEPS b/chromium/content/renderer/pepper/DEPS
index 34f11e757f6..3722ac94c63 100644
--- a/chromium/content/renderer/pepper/DEPS
+++ b/chromium/content/renderer/pepper/DEPS
@@ -6,7 +6,7 @@ include_rules = [
"+media/audio",
"+media/base",
"+media/video",
- "+third_party/libvpx_new",
+ "+third_party/libvpx",
"+third_party/libyuv",
"+third_party/opus",
"+ui/base/ime",
diff --git a/chromium/content/renderer/pepper/content_decryptor_delegate.cc b/chromium/content/renderer/pepper/content_decryptor_delegate.cc
index f9f35db1719..dca5b02b821 100644
--- a/chromium/content/renderer/pepper/content_decryptor_delegate.cc
+++ b/chromium/content/renderer/pepper/content_decryptor_delegate.cc
@@ -169,7 +169,10 @@ PP_VideoCodecProfile MediaVideoCodecProfileToPpVideoCodecProfile(
media::VideoCodecProfile profile) {
switch (profile) {
case media::VP8PROFILE_ANY:
- case media::VP9PROFILE_ANY:
+ case media::VP9PROFILE_PROFILE0:
+ case media::VP9PROFILE_PROFILE1:
+ case media::VP9PROFILE_PROFILE2:
+ case media::VP9PROFILE_PROFILE3:
return PP_VIDEOCODECPROFILE_NOT_NEEDED;
case media::H264PROFILE_BASELINE:
return PP_VIDEOCODECPROFILE_H264_BASELINE;
diff --git a/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.cc b/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.cc
index fc216e1c468..8f13230a843 100644
--- a/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.cc
+++ b/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "base/logging.h"
+#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
#include "build/build_config.h"
#include "content/common/content_switches_internal.h"
@@ -101,7 +102,8 @@ ContentRendererPepperHostFactory::ContentRendererPepperHostFactory(
ContentRendererPepperHostFactory::~ContentRendererPepperHostFactory() {}
-scoped_ptr<ResourceHost> ContentRendererPepperHostFactory::CreateResourceHost(
+std::unique_ptr<ResourceHost>
+ContentRendererPepperHostFactory::CreateResourceHost(
ppapi::host::PpapiHost* host,
PP_Resource resource,
PP_Instance instance,
@@ -110,19 +112,19 @@ scoped_ptr<ResourceHost> ContentRendererPepperHostFactory::CreateResourceHost(
// Make sure the plugin is giving us a valid instance for this resource.
if (!host_->IsValidInstance(instance))
- return scoped_ptr<ResourceHost>();
+ return nullptr;
PepperPluginInstanceImpl* instance_impl =
host_->GetPluginInstanceImpl(instance);
if (!instance_impl->render_frame())
- return scoped_ptr<ResourceHost>();
+ return nullptr;
// Public interfaces.
switch (message.type()) {
case PpapiHostMsg_Compositor_Create::ID: {
if (!CanUseCompositorAPI(host_, instance))
- return scoped_ptr<ResourceHost>();
- return scoped_ptr<ResourceHost>(
+ return nullptr;
+ return base::WrapUnique(
new PepperCompositorHost(host_, instance, resource));
}
case PpapiHostMsg_FileRef_CreateForFileAPI::ID: {
@@ -131,9 +133,9 @@ scoped_ptr<ResourceHost> ContentRendererPepperHostFactory::CreateResourceHost(
if (!UnpackMessage<PpapiHostMsg_FileRef_CreateForFileAPI>(
message, &file_system, &internal_path)) {
NOTREACHED();
- return scoped_ptr<ResourceHost>();
+ return nullptr;
}
- return scoped_ptr<ResourceHost>(new PepperFileRefRendererHost(
+ return base::WrapUnique(new PepperFileRefRendererHost(
host_, instance, resource, file_system, internal_path));
}
case PpapiHostMsg_FileSystem_Create::ID: {
@@ -141,9 +143,9 @@ scoped_ptr<ResourceHost> ContentRendererPepperHostFactory::CreateResourceHost(
if (!UnpackMessage<PpapiHostMsg_FileSystem_Create>(message,
&file_system_type)) {
NOTREACHED();
- return scoped_ptr<ResourceHost>();
+ return nullptr;
}
- return scoped_ptr<ResourceHost>(new PepperFileSystemHost(
+ return base::WrapUnique(new PepperFileSystemHost(
host_, instance, resource, file_system_type));
}
case PpapiHostMsg_Graphics2D_Create::ID: {
@@ -152,7 +154,7 @@ scoped_ptr<ResourceHost> ContentRendererPepperHostFactory::CreateResourceHost(
if (!UnpackMessage<PpapiHostMsg_Graphics2D_Create>(
message, &size, &is_always_opaque)) {
NOTREACHED();
- return scoped_ptr<ResourceHost>();
+ return nullptr;
}
ppapi::PPB_ImageData_Shared::ImageDataType image_type =
ppapi::PPB_ImageData_Shared::PLATFORM;
@@ -169,35 +171,35 @@ scoped_ptr<ResourceHost> ContentRendererPepperHostFactory::CreateResourceHost(
#endif
scoped_refptr<PPB_ImageData_Impl> image_data(new PPB_ImageData_Impl(
instance, image_type));
- return scoped_ptr<ResourceHost>(PepperGraphics2DHost::Create(
+ return base::WrapUnique(PepperGraphics2DHost::Create(
host_, instance, resource, size, is_always_opaque, image_data));
}
case PpapiHostMsg_URLLoader_Create::ID:
- return scoped_ptr<ResourceHost>(
+ return base::WrapUnique(
new PepperURLLoaderHost(host_, false, instance, resource));
case PpapiHostMsg_VideoDecoder_Create::ID:
- return scoped_ptr<ResourceHost>(
+ return base::WrapUnique(
new PepperVideoDecoderHost(host_, instance, resource));
case PpapiHostMsg_VideoEncoder_Create::ID:
- return scoped_ptr<ResourceHost>(
+ return base::WrapUnique(
new PepperVideoEncoderHost(host_, instance, resource));
case PpapiHostMsg_WebSocket_Create::ID:
- return scoped_ptr<ResourceHost>(
+ return base::WrapUnique(
new PepperWebSocketHost(host_, instance, resource));
#if defined(ENABLE_WEBRTC)
case PpapiHostMsg_MediaStreamVideoTrack_Create::ID:
- return scoped_ptr<ResourceHost>(
+ return base::WrapUnique(
new PepperMediaStreamVideoTrackHost(host_, instance, resource));
// These private MediaStream interfaces are exposed as if they were public
// so they can be used by NaCl plugins. However, they are available only
// for whitelisted apps.
case PpapiHostMsg_VideoDestination_Create::ID:
if (CanUseMediaStreamAPI(host_, instance))
- return scoped_ptr<ResourceHost>(
+ return base::WrapUnique(
new PepperVideoDestinationHost(host_, instance, resource));
case PpapiHostMsg_VideoSource_Create::ID:
if (CanUseMediaStreamAPI(host_, instance))
- return scoped_ptr<ResourceHost>(
+ return base::WrapUnique(
new PepperVideoSourceHost(host_, instance, resource));
#endif // defined(ENABLE_WEBRTC)
}
@@ -206,22 +208,18 @@ scoped_ptr<ResourceHost> ContentRendererPepperHostFactory::CreateResourceHost(
if (GetPermissions().HasPermission(ppapi::PERMISSION_DEV)) {
switch (message.type()) {
case PpapiHostMsg_AudioEncoder_Create::ID:
- return scoped_ptr<ResourceHost>(
+ return base::WrapUnique(
new PepperAudioEncoderHost(host_, instance, resource));
case PpapiHostMsg_AudioInput_Create::ID:
- return scoped_ptr<ResourceHost>(
+ return base::WrapUnique(
new PepperAudioInputHost(host_, instance, resource));
case PpapiHostMsg_FileChooser_Create::ID:
- return scoped_ptr<ResourceHost>(
+ return base::WrapUnique(
new PepperFileChooserHost(host_, instance, resource));
case PpapiHostMsg_VideoCapture_Create::ID: {
- PepperVideoCaptureHost* host =
- new PepperVideoCaptureHost(host_, instance, resource);
- if (!host->Init()) {
- delete host;
- return scoped_ptr<ResourceHost>();
- }
- return scoped_ptr<ResourceHost>(host);
+ std::unique_ptr<PepperVideoCaptureHost> host(
+ new PepperVideoCaptureHost(host_, instance, resource));
+ return host->Init() ? std::move(host) : nullptr;
}
}
}
@@ -232,12 +230,12 @@ scoped_ptr<ResourceHost> ContentRendererPepperHostFactory::CreateResourceHost(
if (!GetPermissions().HasPermission(ppapi::PERMISSION_PRIVATE) &&
!CanUseCameraDeviceAPI(host_, instance))
return nullptr;
- scoped_ptr<PepperCameraDeviceHost> host(
+ std::unique_ptr<PepperCameraDeviceHost> host(
new PepperCameraDeviceHost(host_, instance, resource));
return host->Init() ? std::move(host) : nullptr;
}
- return scoped_ptr<ResourceHost>();
+ return nullptr;
}
const ppapi::PpapiPermissions&
diff --git a/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.h b/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.h
index 41ff02a5172..db1f7f2a952 100644
--- a/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.h
+++ b/chromium/content/renderer/pepper/content_renderer_pepper_host_factory.h
@@ -24,7 +24,7 @@ class ContentRendererPepperHostFactory : public ppapi::host::HostFactory {
explicit ContentRendererPepperHostFactory(RendererPpapiHostImpl* host);
~ContentRendererPepperHostFactory() override;
- scoped_ptr<ppapi::host::ResourceHost> CreateResourceHost(
+ std::unique_ptr<ppapi::host::ResourceHost> CreateResourceHost(
ppapi::host::PpapiHost* host,
PP_Resource resource,
PP_Instance instance,
diff --git a/chromium/content/renderer/pepper/event_conversion.cc b/chromium/content/renderer/pepper/event_conversion.cc
index e7f5c698575..88655b2e289 100644
--- a/chromium/content/renderer/pepper/event_conversion.cc
+++ b/chromium/content/renderer/pepper/event_conversion.cc
@@ -270,10 +270,11 @@ void AppendTouchEvent(const WebInputEvent& event,
WebTouchPoint CreateWebTouchPoint(const PP_TouchPoint& pp_pt,
WebTouchPoint::State state) {
WebTouchPoint pt;
+ pt.pointerType = blink::WebPointerProperties::PointerType::Touch;
pt.id = pp_pt.id;
pt.position.x = pp_pt.position.x;
pt.position.y = pp_pt.position.y;
- // TODO bug:http://code.google.com/p/chromium/issues/detail?id=93902
+ // TODO(crbug.com/93902): Add screen coordinate calculation.
pt.screenPosition.x = 0;
pt.screenPosition.y = 0;
pt.force = pp_pt.pressure;
@@ -402,6 +403,8 @@ WebKeyboardEvent* BuildCharEvent(const InputEventData& event) {
WebMouseEvent* BuildMouseEvent(const InputEventData& event) {
WebMouseEvent* mouse_event = new WebMouseEvent();
+ mouse_event->pointerType = blink::WebPointerProperties::PointerType::Mouse;
+
switch (event.event_type) {
case PP_INPUTEVENT_TYPE_MOUSEDOWN:
mouse_event->type = WebInputEvent::MouseDown;
diff --git a/chromium/content/renderer/pepper/fullscreen_container.h b/chromium/content/renderer/pepper/fullscreen_container.h
index 9cc540bc27d..75fbc1cac50 100644
--- a/chromium/content/renderer/pepper/fullscreen_container.h
+++ b/chromium/content/renderer/pepper/fullscreen_container.h
@@ -31,7 +31,7 @@ class FullscreenContainer {
virtual void Destroy() = 0;
// Notifies the container that the mouse cursor has changed.
- virtual void DidChangeCursor(const blink::WebCursorInfo& cursor) = 0;
+ virtual void PepperDidChangeCursor(const blink::WebCursorInfo& cursor) = 0;
virtual void SetLayer(blink::WebLayer* layer) = 0;
diff --git a/chromium/content/renderer/pepper/host_globals.cc b/chromium/content/renderer/pepper/host_globals.cc
index a00748794b4..c3b3de842cf 100644
--- a/chromium/content/renderer/pepper/host_globals.cc
+++ b/chromium/content/renderer/pepper/host_globals.cc
@@ -149,7 +149,11 @@ void HostGlobals::LogWithSource(PP_Instance instance,
const std::string& value) {
PepperPluginInstanceImpl* instance_object =
HostGlobals::Get()->GetInstance(instance);
- if (instance_object) {
+ // It's possible to process this message in a nested message loop while
+ // detaching a Document…
+ // TODO(dcheng): Make it so this can't happen. https://crbug.com/561683
+ if (instance_object &&
+ instance_object->container()->element().document().frame()) {
instance_object->container()
->element()
.document()
diff --git a/chromium/content/renderer/pepper/host_var_tracker_unittest.cc b/chromium/content/renderer/pepper/host_var_tracker_unittest.cc
index 7ee9bc72ab7..ee498b5bdfc 100644
--- a/chromium/content/renderer/pepper/host_var_tracker_unittest.cc
+++ b/chromium/content/renderer/pepper/host_var_tracker_unittest.cc
@@ -16,7 +16,6 @@
#include "gin/wrappable.h"
#include "ppapi/c/pp_var.h"
#include "ppapi/c/ppp_instance.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
using ppapi::V8ObjectVar;
diff --git a/chromium/content/renderer/pepper/message_channel.cc b/chromium/content/renderer/pepper/message_channel.cc
index d66faf1dcc5..abe49d953c2 100644
--- a/chromium/content/renderer/pepper/message_channel.cc
+++ b/chromium/content/renderer/pepper/message_channel.cc
@@ -26,7 +26,6 @@
#include "ppapi/shared_impl/scoped_pp_var.h"
#include "ppapi/shared_impl/var.h"
#include "ppapi/shared_impl/var_tracker.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
#include "third_party/WebKit/public/web/WebDOMMessageEvent.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebElement.h"
@@ -40,7 +39,6 @@ using ppapi::ArrayBufferVar;
using ppapi::PpapiGlobals;
using ppapi::ScopedPPVar;
using ppapi::StringVar;
-using blink::WebBindings;
using blink::WebElement;
using blink::WebDOMEvent;
using blink::WebDOMMessageEvent;
diff --git a/chromium/content/renderer/pepper/pepper_broker.cc b/chromium/content/renderer/pepper/pepper_broker.cc
index b1e06260b50..0869e80d78d 100644
--- a/chromium/content/renderer/pepper/pepper_broker.cc
+++ b/chromium/content/renderer/pepper/pepper_broker.cc
@@ -208,6 +208,9 @@ void PepperBroker::OnBrokerPermissionResult(PPB_Broker_Impl* client,
PepperBroker::PendingConnection::PendingConnection() : is_authorized(false) {}
+PepperBroker::PendingConnection::PendingConnection(
+ const PendingConnection& other) = default;
+
PepperBroker::PendingConnection::~PendingConnection() {}
void PepperBroker::ReportFailureToClients(int error_code) {
diff --git a/chromium/content/renderer/pepper/pepper_broker.h b/chromium/content/renderer/pepper/pepper_broker.h
index 1140d4e6d4c..fda0045facb 100644
--- a/chromium/content/renderer/pepper/pepper_broker.h
+++ b/chromium/content/renderer/pepper/pepper_broker.h
@@ -72,6 +72,7 @@ class PepperBroker : public base::RefCountedThreadSafe<PepperBroker> {
struct PendingConnection {
PendingConnection();
+ PendingConnection(const PendingConnection& other);
~PendingConnection();
bool is_authorized;
diff --git a/chromium/content/renderer/pepper/pepper_compositor_host.cc b/chromium/content/renderer/pepper/pepper_compositor_host.cc
index 939cd988f4c..59b6dc8170c 100644
--- a/chromium/content/renderer/pepper/pepper_compositor_host.cc
+++ b/chromium/content/renderer/pepper/pepper_compositor_host.cc
@@ -145,6 +145,8 @@ PepperCompositorHost::LayerData::LayerData(
const scoped_refptr<cc::Layer>& cc,
const ppapi::CompositorLayerData& pp) : cc_layer(cc), pp_layer(pp) {}
+PepperCompositorHost::LayerData::LayerData(const LayerData& other) = default;
+
PepperCompositorHost::LayerData::~LayerData() {}
PepperCompositorHost::PepperCompositorHost(
@@ -154,7 +156,7 @@ PepperCompositorHost::PepperCompositorHost(
: ResourceHost(host->GetPpapiHost(), instance, resource),
bound_instance_(NULL),
weak_factory_(this) {
- layer_ = cc::Layer::Create(cc_blink::WebLayerImpl::LayerSettings());
+ layer_ = cc::Layer::Create();
// TODO(penghuang): SetMasksToBounds() can be expensive if the layer is
// transformed. Possibly better could be to explicitly clip the child layers
// (by modifying their bounds).
@@ -241,7 +243,7 @@ void PepperCompositorHost::UpdateLayer(
scoped_refptr<cc::Layer> clip_parent = layer->parent();
if (clip_parent.get() == layer_.get()) {
// Create a clip parent layer, if it does not exist.
- clip_parent = cc::Layer::Create(cc_blink::WebLayerImpl::LayerSettings());
+ clip_parent = cc::Layer::Create();
clip_parent->SetMasksToBounds(true);
clip_parent->SetIsDrawable(true);
layer_->ReplaceChild(layer.get(), clip_parent);
@@ -384,11 +386,9 @@ int32_t PepperCompositorHost::OnHostMsgCommitLayers(
if (!cc_layer.get()) {
if (pp_layer->color)
- cc_layer = cc::SolidColorLayer::Create(
- cc_blink::WebLayerImpl::LayerSettings());
+ cc_layer = cc::SolidColorLayer::Create();
else if (pp_layer->texture || pp_layer->image)
- cc_layer = cc::TextureLayer::CreateForMailbox(
- cc_blink::WebLayerImpl::LayerSettings(), NULL);
+ cc_layer = cc::TextureLayer::CreateForMailbox(NULL);
layer_->AddChild(cc_layer);
}
diff --git a/chromium/content/renderer/pepper/pepper_compositor_host.h b/chromium/content/renderer/pepper/pepper_compositor_host.h
index fab64176d31..a8a413bd5d7 100644
--- a/chromium/content/renderer/pepper/pepper_compositor_host.h
+++ b/chromium/content/renderer/pepper/pepper_compositor_host.h
@@ -38,6 +38,8 @@ class PepperCompositorHost : public ppapi::host::ResourceHost {
PepperCompositorHost(RendererPpapiHost* host,
PP_Instance instance,
PP_Resource resource);
+ ~PepperCompositorHost() override;
+
// Associates this device with the given plugin instance. You can pass NULL
// to clear the existing device. Returns true on success. In this case, a
// repaint of the page will also be scheduled. Failure means that the device
@@ -49,8 +51,6 @@ class PepperCompositorHost : public ppapi::host::ResourceHost {
void ViewInitiatedPaint();
private:
- ~PepperCompositorHost() override;
-
void ImageReleased(int32_t id,
scoped_ptr<base::SharedMemory> shared_memory,
scoped_ptr<cc::SharedBitmap> bitmap,
@@ -91,6 +91,7 @@ class PepperCompositorHost : public ppapi::host::ResourceHost {
struct LayerData {
LayerData(const scoped_refptr<cc::Layer>& cc,
const ppapi::CompositorLayerData& pp);
+ LayerData(const LayerData& other);
~LayerData();
scoped_refptr<cc::Layer> cc_layer;
diff --git a/chromium/content/renderer/pepper/pepper_file_chooser_host.cc b/chromium/content/renderer/pepper/pepper_file_chooser_host.cc
index ea107682efe..572b0cd16ba 100644
--- a/chromium/content/renderer/pepper/pepper_file_chooser_host.cc
+++ b/chromium/content/renderer/pepper/pepper_file_chooser_host.cc
@@ -16,7 +16,6 @@
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h"
-#include "third_party/WebKit/public/platform/WebCString.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebVector.h"
#include "third_party/WebKit/public/web/WebFileChooserCompletion.h"
diff --git a/chromium/content/renderer/pepper/pepper_file_chooser_host_unittest.cc b/chromium/content/renderer/pepper/pepper_file_chooser_host_unittest.cc
index 66b4dbdd163..f74c0a181b3 100644
--- a/chromium/content/renderer/pepper/pepper_file_chooser_host_unittest.cc
+++ b/chromium/content/renderer/pepper/pepper_file_chooser_host_unittest.cc
@@ -110,7 +110,7 @@ TEST_F(PepperFileChooserHostTest, Show) {
std::vector<content::FileChooserFileInfo> selected_info_vector;
selected_info_vector.push_back(selected_info);
RenderViewImpl* view_impl = static_cast<RenderViewImpl*>(view_);
- ViewMsg_RunFileChooserResponse response(view_impl->routing_id(),
+ ViewMsg_RunFileChooserResponse response(view_impl->GetRoutingID(),
selected_info_vector);
EXPECT_TRUE(view_impl->OnMessageReceived(response));
diff --git a/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc b/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc
index c6451a12694..13989422655 100644
--- a/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc
+++ b/chromium/content/renderer/pepper/pepper_graphics_2d_host.cc
@@ -36,6 +36,7 @@
#include "ppapi/thunk/enter.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkSwizzle.h"
#include "ui/gfx/blit.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/rect.h"
@@ -89,21 +90,6 @@ bool ValidateAndConvertRect(const PP_Rect* rect,
return true;
}
-// Converts BGRA <-> RGBA.
-void ConvertBetweenBGRAandRGBA(const uint32_t* input,
- int pixel_length,
- uint32_t* output) {
- for (int i = 0; i < pixel_length; i++) {
- const unsigned char* pixel_in =
- reinterpret_cast<const unsigned char*>(&input[i]);
- unsigned char* pixel_out = reinterpret_cast<unsigned char*>(&output[i]);
- pixel_out[0] = pixel_in[2];
- pixel_out[1] = pixel_in[1];
- pixel_out[2] = pixel_in[0];
- pixel_out[3] = pixel_in[3];
- }
-}
-
// Converts ImageData from PP_IMAGEDATAFORMAT_BGRA_PREMUL to
// PP_IMAGEDATAFORMAT_RGBA_PREMUL, or reverse. It's assumed that the
// destination image is always mapped (so will have non-NULL data).
@@ -121,22 +107,22 @@ void ConvertImageData(PPB_ImageData_Impl* src_image,
const SkBitmap* dest_bitmap = dest_image->GetMappedBitmap();
if (src_rect.width() == src_image->width() &&
dest_rect.width() == dest_image->width()) {
- // Fast path if the full line needs to be converted.
- ConvertBetweenBGRAandRGBA(
+ // Fast path if the full frame can be converted at once.
+ SkSwapRB(
+ dest_bitmap->getAddr32(static_cast<int>(dest_rect.fLeft),
+ static_cast<int>(dest_rect.fTop)),
src_bitmap->getAddr32(static_cast<int>(src_rect.fLeft),
static_cast<int>(src_rect.fTop)),
- src_rect.width() * src_rect.height(),
- dest_bitmap->getAddr32(static_cast<int>(dest_rect.fLeft),
- static_cast<int>(dest_rect.fTop)));
+ src_rect.width() * src_rect.height());
} else {
// Slow path where we convert line by line.
for (int y = 0; y < src_rect.height(); y++) {
- ConvertBetweenBGRAandRGBA(
+ SkSwapRB(
+ dest_bitmap->getAddr32(static_cast<int>(dest_rect.fLeft),
+ static_cast<int>(dest_rect.fTop + y)),
src_bitmap->getAddr32(static_cast<int>(src_rect.fLeft),
static_cast<int>(src_rect.fTop + y)),
- src_rect.width(),
- dest_bitmap->getAddr32(static_cast<int>(dest_rect.fLeft),
- static_cast<int>(dest_rect.fTop + y)));
+ src_rect.width());
}
}
}
diff --git a/chromium/content/renderer/pepper/pepper_media_stream_video_track_host.cc b/chromium/content/renderer/pepper/pepper_media_stream_video_track_host.cc
index d0e47c2c95d..9907cf42b8f 100644
--- a/chromium/content/renderer/pepper/pepper_media_stream_video_track_host.cc
+++ b/chromium/content/renderer/pepper/pepper_media_stream_video_track_host.cc
@@ -13,6 +13,7 @@
#include "base/strings/utf_string_conversions.h"
#include "content/renderer/media/media_stream_video_track.h"
#include "media/base/bind_to_current_loop.h"
+#include "media/base/video_util.h"
#include "media/base/yuv_convert.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/ppb_media_stream_video_track.h"
@@ -228,7 +229,6 @@ PepperMediaStreamVideoTrackHost::PepperMediaStreamVideoTrackHost(
const blink::WebMediaStreamTrack& track)
: PepperMediaStreamTrackHostBase(host, instance, resource),
track_(track),
- connected_(false),
number_of_buffers_(kDefaultNumberOfBuffers),
source_frame_format_(PP_VIDEOFRAME_FORMAT_UNKNOWN),
plugin_frame_format_(PP_VIDEOFRAME_FORMAT_UNKNOWN),
@@ -244,7 +244,6 @@ PepperMediaStreamVideoTrackHost::PepperMediaStreamVideoTrackHost(
PP_Instance instance,
PP_Resource resource)
: PepperMediaStreamTrackHostBase(host, instance, resource),
- connected_(false),
number_of_buffers_(kDefaultNumberOfBuffers),
source_frame_format_(PP_VIDEOFRAME_FORMAT_UNKNOWN),
plugin_frame_format_(PP_VIDEOFRAME_FORMAT_UNKNOWN),
@@ -256,14 +255,14 @@ PepperMediaStreamVideoTrackHost::PepperMediaStreamVideoTrackHost(
DCHECK(!track_.isNull());
}
-bool PepperMediaStreamVideoTrackHost::IsMediaStreamVideoTrackHost() {
- return true;
-}
-
PepperMediaStreamVideoTrackHost::~PepperMediaStreamVideoTrackHost() {
OnClose();
}
+bool PepperMediaStreamVideoTrackHost::IsMediaStreamVideoTrackHost() {
+ return true;
+}
+
void PepperMediaStreamVideoTrackHost::InitBuffers() {
gfx::Size size = GetTargetSize(source_frame_size_, plugin_frame_size_);
DCHECK(!size.IsEmpty());
@@ -306,11 +305,8 @@ void PepperMediaStreamVideoTrackHost::InitBuffers() {
}
void PepperMediaStreamVideoTrackHost::OnClose() {
- if (connected_) {
- MediaStreamVideoSink::RemoveFromVideoTrack(this, track_);
- weak_factory_.InvalidateWeakPtrs();
- connected_ = false;
- }
+ MediaStreamVideoSink::DisconnectFromTrack();
+ weak_factory_.InvalidateWeakPtrs();
}
int32_t PepperMediaStreamVideoTrackHost::OnHostMsgEnqueueBuffer(
@@ -370,10 +366,14 @@ int32_t PepperMediaStreamVideoTrackHost::SendFrameToTrack(int32_t index) {
}
void PepperMediaStreamVideoTrackHost::OnVideoFrame(
- const scoped_refptr<VideoFrame>& frame,
+ const scoped_refptr<VideoFrame>& video_frame,
base::TimeTicks estimated_capture_time) {
- DCHECK(frame.get());
+ DCHECK(video_frame.get());
// TODO(penghuang): Check |frame->end_of_stream()| and close the track.
+ scoped_refptr<media::VideoFrame> frame = video_frame;
+ // Drop alpha channel since we do not support it yet.
+ if (frame->format() == media::PIXEL_FORMAT_YV12A)
+ frame = media::WrapAsI420VideoFrame(video_frame);
PP_VideoFrame_Format ppformat = ToPpapiFormat(frame->format());
if (ppformat == PP_VIDEOFRAME_FORMAT_UNKNOWN)
return;
@@ -442,16 +442,14 @@ void PepperMediaStreamVideoTrackHost::StopSourceImpl() {
}
void PepperMediaStreamVideoTrackHost::DidConnectPendingHostToResource() {
- if (!connected_) {
- MediaStreamVideoSink::AddToVideoTrack(
- this,
- media::BindToCurrentLoop(
- base::Bind(
- &PepperMediaStreamVideoTrackHost::OnVideoFrame,
- weak_factory_.GetWeakPtr())),
- track_);
- connected_ = true;
- }
+ if (!MediaStreamVideoSink::connected_track().isNull())
+ return;
+ MediaStreamVideoSink::ConnectToTrack(
+ track_,
+ media::BindToCurrentLoop(
+ base::Bind(
+ &PepperMediaStreamVideoTrackHost::OnVideoFrame,
+ weak_factory_.GetWeakPtr())));
}
int32_t PepperMediaStreamVideoTrackHost::OnResourceMessageReceived(
diff --git a/chromium/content/renderer/pepper/pepper_media_stream_video_track_host.h b/chromium/content/renderer/pepper/pepper_media_stream_video_track_host.h
index 81422146998..b510377001c 100644
--- a/chromium/content/renderer/pepper/pepper_media_stream_video_track_host.h
+++ b/chromium/content/renderer/pepper/pepper_media_stream_video_track_host.h
@@ -40,13 +40,13 @@ class PepperMediaStreamVideoTrackHost : public PepperMediaStreamTrackHostBase,
PP_Instance instance,
PP_Resource resource);
+ ~PepperMediaStreamVideoTrackHost() override;
+
bool IsMediaStreamVideoTrackHost() override;
blink::WebMediaStreamTrack track() { return track_; }
private:
- ~PepperMediaStreamVideoTrackHost() override;
-
void InitBuffers();
// PepperMediaStreamTrackHostBase overrides:
@@ -94,9 +94,6 @@ class PepperMediaStreamVideoTrackHost : public PepperMediaStreamTrackHostBase,
blink::WebMediaStreamTrack track_;
- // True if it has been added to |blink::WebMediaStreamTrack| as a sink.
- bool connected_;
-
// Number of buffers.
int32_t number_of_buffers_;
diff --git a/chromium/content/renderer/pepper/pepper_platform_video_capture.cc b/chromium/content/renderer/pepper/pepper_platform_video_capture.cc
index 13ad0136cc9..8abc4ac9e44 100644
--- a/chromium/content/renderer/pepper/pepper_platform_video_capture.cc
+++ b/chromium/content/renderer/pepper/pepper_platform_video_capture.cc
@@ -6,12 +6,14 @@
#include "base/bind.h"
#include "base/logging.h"
+#include "base/memory/ref_counted.h"
#include "content/renderer/media/video_capture_impl_manager.h"
#include "content/renderer/pepper/pepper_media_device_manager.h"
#include "content/renderer/pepper/pepper_video_capture_host.h"
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "media/base/bind_to_current_loop.h"
+#include "media/base/video_frame.h"
#include "url/gurl.h"
namespace content {
diff --git a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc
index 6d5d72d9a1d..372b503b814 100644
--- a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc
+++ b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.cc
@@ -92,17 +92,17 @@
#include "ppapi/shared_impl/var.h"
#include "ppapi/thunk/enter.h"
#include "ppapi/thunk/ppb_buffer_api.h"
-#include "printing/metafile_skia_wrapper.h"
-#include "printing/pdf_metafile_skia.h"
#include "skia/ext/platform_canvas.h"
+#include "third_party/WebKit/public/platform/URLConversion.h"
#include "third_party/WebKit/public/platform/WebCursorInfo.h"
+#include "third_party/WebKit/public/platform/WebFloatRect.h"
#include "third_party/WebKit/public/platform/WebGamepads.h"
#include "third_party/WebKit/public/platform/WebRect.h"
+#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/WebURLError.h"
#include "third_party/WebKit/public/platform/WebURLRequest.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
#include "third_party/WebKit/public/web/WebCompositionUnderline.h"
#include "third_party/WebKit/public/web/WebDataSource.h"
#include "third_party/WebKit/public/web/WebDocument.h"
@@ -115,16 +115,23 @@
#include "third_party/WebKit/public/web/WebPrintScalingOption.h"
#include "third_party/WebKit/public/web/WebScopedUserGesture.h"
#include "third_party/WebKit/public/web/WebScriptSource.h"
-#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
#include "third_party/WebKit/public/web/WebView.h"
#include "third_party/khronos/GLES2/gl2.h"
+#include "ui/events/blink/blink_event_util.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_rep.h"
#include "ui/gfx/range/range.h"
#include "url/origin.h"
#include "v8/include/v8.h"
+#if defined(ENABLE_PRINTING)
+// nogncheck because dependency on //printing is conditional upon
+// enable_basic_printing or enable_print_preview flags.
+#include "printing/metafile_skia_wrapper.h" // nogncheck
+#include "printing/pdf_metafile_skia.h" // nogncheck
+#endif
+
#if defined(OS_CHROMEOS)
#include "ui/events/keycodes/keyboard_codes_posix.h"
#endif
@@ -149,7 +156,6 @@ using ppapi::thunk::PPB_ImageData_API;
using ppapi::Var;
using ppapi::ArrayBufferVar;
using ppapi::ViewData;
-using blink::WebBindings;
using blink::WebCanvas;
using blink::WebCursorInfo;
using blink::WebDocument;
@@ -176,27 +182,19 @@ namespace content {
namespace {
-#define STATIC_ASSERT_PP_MATCHING_ENUM(a, b) \
+#define STATIC_ASSERT_ENUM(a, b) \
static_assert(static_cast<int>(a) == static_cast<int>(b), \
"mismatching enums: " #a)
// Check PP_TextInput_Type and ui::TextInputType are kept in sync.
-STATIC_ASSERT_PP_MATCHING_ENUM(ui::TEXT_INPUT_TYPE_NONE,
- PP_TEXTINPUT_TYPE_NONE);
-STATIC_ASSERT_PP_MATCHING_ENUM(ui::TEXT_INPUT_TYPE_TEXT,
- PP_TEXTINPUT_TYPE_TEXT);
-STATIC_ASSERT_PP_MATCHING_ENUM(ui::TEXT_INPUT_TYPE_PASSWORD,
- PP_TEXTINPUT_TYPE_PASSWORD);
-STATIC_ASSERT_PP_MATCHING_ENUM(ui::TEXT_INPUT_TYPE_SEARCH,
- PP_TEXTINPUT_TYPE_SEARCH);
-STATIC_ASSERT_PP_MATCHING_ENUM(ui::TEXT_INPUT_TYPE_EMAIL,
- PP_TEXTINPUT_TYPE_EMAIL);
-STATIC_ASSERT_PP_MATCHING_ENUM(ui::TEXT_INPUT_TYPE_NUMBER,
- PP_TEXTINPUT_TYPE_NUMBER);
-STATIC_ASSERT_PP_MATCHING_ENUM(ui::TEXT_INPUT_TYPE_TELEPHONE,
- PP_TEXTINPUT_TYPE_TELEPHONE);
-STATIC_ASSERT_PP_MATCHING_ENUM(ui::TEXT_INPUT_TYPE_URL,
- PP_TEXTINPUT_TYPE_URL);
+STATIC_ASSERT_ENUM(ui::TEXT_INPUT_TYPE_NONE, PP_TEXTINPUT_TYPE_NONE);
+STATIC_ASSERT_ENUM(ui::TEXT_INPUT_TYPE_TEXT, PP_TEXTINPUT_TYPE_TEXT);
+STATIC_ASSERT_ENUM(ui::TEXT_INPUT_TYPE_PASSWORD, PP_TEXTINPUT_TYPE_PASSWORD);
+STATIC_ASSERT_ENUM(ui::TEXT_INPUT_TYPE_SEARCH, PP_TEXTINPUT_TYPE_SEARCH);
+STATIC_ASSERT_ENUM(ui::TEXT_INPUT_TYPE_EMAIL, PP_TEXTINPUT_TYPE_EMAIL);
+STATIC_ASSERT_ENUM(ui::TEXT_INPUT_TYPE_NUMBER, PP_TEXTINPUT_TYPE_NUMBER);
+STATIC_ASSERT_ENUM(ui::TEXT_INPUT_TYPE_TELEPHONE, PP_TEXTINPUT_TYPE_TELEPHONE);
+STATIC_ASSERT_ENUM(ui::TEXT_INPUT_TYPE_URL, PP_TEXTINPUT_TYPE_URL);
// The default text input type is to regard the plugin always accept text input.
// This is for allowing users to use input methods even on completely-IME-
@@ -279,14 +277,12 @@ STATIC_ASSERT_MATCHING_ENUM(TypeGrabbing, PP_MOUSECURSOR_TYPE_GRABBING);
// Do not assert WebCursorInfo::TypeCustom == PP_CURSORTYPE_CUSTOM;
// PP_CURSORTYPE_CUSTOM is pinned to allow new cursor types.
-STATIC_ASSERT_PP_MATCHING_ENUM(blink::WebPrintScalingOptionNone,
- PP_PRINTSCALINGOPTION_NONE);
-STATIC_ASSERT_PP_MATCHING_ENUM(
- blink::WebPrintScalingOptionFitToPrintableArea,
- PP_PRINTSCALINGOPTION_FIT_TO_PRINTABLE_AREA);
-STATIC_ASSERT_PP_MATCHING_ENUM(
- blink::WebPrintScalingOptionSourceSize,
- PP_PRINTSCALINGOPTION_SOURCE_SIZE);
+STATIC_ASSERT_ENUM(blink::WebPrintScalingOptionNone,
+ PP_PRINTSCALINGOPTION_NONE);
+STATIC_ASSERT_ENUM(blink::WebPrintScalingOptionFitToPrintableArea,
+ PP_PRINTSCALINGOPTION_FIT_TO_PRINTABLE_AREA);
+STATIC_ASSERT_ENUM(blink::WebPrintScalingOptionSourceSize,
+ PP_PRINTSCALINGOPTION_SOURCE_SIZE);
// Sets |*security_origin| to be the WebKit security origin associated with the
// document containing the given plugin instance. On success, returns true. If
@@ -300,7 +296,7 @@ bool SecurityOriginForInstance(PP_Instance instance_id,
return false;
WebElement plugin_element = instance->container()->element();
- *security_origin = plugin_element.document().securityOrigin();
+ *security_origin = plugin_element.document().getSecurityOrigin();
return true;
}
@@ -493,6 +489,7 @@ PepperPluginInstanceImpl::PepperPluginInstanceImpl(
has_been_clicked_(false),
javascript_used_(false),
full_frame_(false),
+ viewport_to_dip_scale_(1.0f),
sent_initial_did_change_view_(false),
bound_graphics_2d_platform_(NULL),
bound_compositor_(NULL),
@@ -667,9 +664,8 @@ v8::Local<v8::Context> PepperPluginInstanceImpl::GetMainWorldContext() {
void PepperPluginInstanceImpl::Delete() {
is_deleted_ = true;
- if (render_frame_ && render_frame_->render_view() &&
- render_frame_->render_view()->plugin_find_handler() == this) {
- render_frame_->render_view()->set_plugin_find_handler(NULL);
+ if (render_frame_ && render_frame_->plugin_find_handler() == this) {
+ render_frame_->set_plugin_find_handler(nullptr);
}
// Keep a reference on the stack. See NOTE above.
@@ -1078,19 +1074,22 @@ bool PepperPluginInstanceImpl::IsPluginAcceptingCompositionEvents() const {
gfx::Rect PepperPluginInstanceImpl::GetCaretBounds() const {
if (!text_input_caret_set_) {
// If it is never set by the plugin, use the bottom left corner.
- return gfx::Rect(view_data_.rect.point.x,
- view_data_.rect.point.y + view_data_.rect.size.height,
- 0,
- 0);
- }
-
- // TODO(kinaba) Take CSS transformation into accont.
- // TODO(kinaba) Take bounding_box into account. On some platforms, an
- // "exclude rectangle" where candidate window must avoid the region can be
- // passed to IME. Currently, we pass only the caret rectangle because
- // it is the only information supported uniformly in Chromium.
+ gfx::Rect rect(view_data_.rect.point.x,
+ view_data_.rect.point.y + view_data_.rect.size.height,
+ 0, 0);
+ ConvertDIPToViewport(&rect);
+ return rect;
+ }
+
+ // TODO(kinaba) Take CSS transformation into account.
+ // TODO(kinaba) Take |text_input_caret_bounds_| into account. On
+ // some platforms, an "exclude rectangle" where candidate window
+ // must avoid the region can be passed to IME. Currently, we pass
+ // only the caret rectangle because it is the only information
+ // supported uniformly in Chromium.
gfx::Rect caret(text_input_caret_);
caret.Offset(view_data_.rect.point.x, view_data_.rect.point.y);
+ ConvertDIPToViewport(&caret);
return caret;
}
@@ -1104,6 +1103,7 @@ bool PepperPluginInstanceImpl::HandleInputEvent(
(event.modifiers & blink::WebInputEvent::LeftButtonDown)) {
has_been_clicked_ = true;
blink::WebRect bounds = container()->element().boundsInViewport();
+ render_frame()->GetRenderWidget()->convertViewportToWindow(&bounds);
RecordFlashClickSizeMetric(bounds.width, bounds.height);
}
@@ -1137,7 +1137,12 @@ bool PepperPluginInstanceImpl::HandleInputEvent(
(input_event_mask_ & event_class)) {
// Actually send the event.
std::vector<ppapi::InputEventData> events;
- CreateInputEventData(event, &events);
+ scoped_ptr<const WebInputEvent> event_in_dip(
+ ui::ScaleWebInputEvent(event, viewport_to_dip_scale_));
+ if (event_in_dip)
+ CreateInputEventData(*event_in_dip.get(), &events);
+ else
+ CreateInputEventData(event, &events);
// Allow the user gesture to be pending after the plugin handles the
// event. This allows out-of-process plugins to respond to the user
@@ -1254,6 +1259,14 @@ void PepperPluginInstanceImpl::ViewChanged(
view_data_.device_scale = container_->deviceScaleFactor();
view_data_.css_scale =
container_->pageZoomFactor() * container_->pageScaleFactor();
+ blink::WebFloatRect windowToViewportScale(0, 0, 1.0f, 0);
+ render_frame()->GetRenderWidget()->convertWindowToViewport(
+ &windowToViewportScale);
+ viewport_to_dip_scale_ = 1.0f / windowToViewportScale.width;
+ ConvertRectToDIP(&view_data_.rect);
+ ConvertRectToDIP(&view_data_.clip_rect);
+ view_data_.css_scale *= viewport_to_dip_scale_;
+ view_data_.device_scale /= viewport_to_dip_scale_;
gfx::Size scroll_offset =
container_->element().document().frame()->scrollOffset();
@@ -1735,7 +1748,7 @@ int PepperPluginInstanceImpl::PrintBegin(const WebPrintParams& print_params) {
if (!num_pages)
return 0;
current_print_settings_ = print_settings;
- canvas_.clear();
+ canvas_.reset();
ranges_.clear();
return num_pages;
}
@@ -1754,7 +1767,7 @@ void PepperPluginInstanceImpl::PrintPage(int page_number,
#endif // defined(OS_MACOSX)
if (save_for_later) {
ranges_.push_back(page_range);
- canvas_ = skia::SharePtr(canvas);
+ canvas_ = sk_ref_sp(canvas);
} else {
PrintPageHelper(&page_range, 1, canvas);
}
@@ -1787,7 +1800,7 @@ void PepperPluginInstanceImpl::PrintEnd() {
scoped_refptr<PepperPluginInstanceImpl> ref(this);
if (!ranges_.empty())
PrintPageHelper(&(ranges_.front()), ranges_.size(), canvas_.get());
- canvas_.clear();
+ canvas_.reset();
ranges_.clear();
DCHECK(plugin_print_interface_);
@@ -2023,15 +2036,13 @@ void PepperPluginInstanceImpl::UpdateLayer(bool force_creation) {
bool opaque = false;
if (want_3d_layer) {
DCHECK(bound_graphics_3d_.get());
- texture_layer_ = cc::TextureLayer::CreateForMailbox(
- cc_blink::WebLayerImpl::LayerSettings(), NULL);
+ texture_layer_ = cc::TextureLayer::CreateForMailbox(NULL);
opaque = bound_graphics_3d_->IsOpaque();
texture_layer_->SetTextureMailboxWithoutReleaseCallback(
cc::TextureMailbox(mailbox, sync_token, GL_TEXTURE_2D));
} else {
DCHECK(bound_graphics_2d_platform_);
- texture_layer_ = cc::TextureLayer::CreateForMailbox(
- cc_blink::WebLayerImpl::LayerSettings(), this);
+ texture_layer_ = cc::TextureLayer::CreateForMailbox(this);
bound_graphics_2d_platform_->AttachedToNewLayer();
opaque = bound_graphics_2d_platform_->IsAlwaysOpaque();
texture_layer_->SetFlipped(false);
@@ -2349,8 +2360,8 @@ PP_Var PepperPluginInstanceImpl::ExecuteScript(PP_Instance instance,
RecordFlashJavaScriptUse();
// Executing the script may remove the plugin from the DOM, so we need to keep
- // a reference to ourselves so that we can still process the result after the
- // WebBindings::evaluate() below.
+ // a reference to ourselves so that we can still process the result after
+ // running the script below.
scoped_refptr<PepperPluginInstanceImpl> ref(this);
V8VarConverter converter(pp_instance_, V8VarConverter::kAllowObjectVars);
PepperTryCatchVar try_catch(this, &converter, exception);
@@ -2531,14 +2542,18 @@ void PepperPluginInstanceImpl::SetPluginToHandleFindRequests(
render_frame_->GetRenderView()->GetMainRenderFrame() == render_frame_;
if (!is_main_frame)
return;
- render_frame_->render_view()->set_plugin_find_handler(this);
+ render_frame_->set_plugin_find_handler(this);
}
void PepperPluginInstanceImpl::NumberOfFindResultsChanged(
PP_Instance instance,
int32_t total,
PP_Bool final_result) {
- DCHECK_NE(find_identifier_, -1);
+ // After stopping search and setting find_identifier_ to -1 there still may be
+ // a NumberOfFindResultsChanged notification pending from plug-in. Just ignore
+ // them.
+ if (find_identifier_ == -1)
+ return;
if (render_frame_) {
render_frame_->reportFindInPageMatchCount(
find_identifier_, total, PP_ToBool(final_result));
@@ -2547,7 +2562,8 @@ void PepperPluginInstanceImpl::NumberOfFindResultsChanged(
void PepperPluginInstanceImpl::SelectedFindResultChanged(PP_Instance instance,
int32_t index) {
- DCHECK_NE(find_identifier_, -1);
+ if (find_identifier_ == -1)
+ return;
if (render_frame_) {
render_frame_->reportFindInPageSelection(
find_identifier_, index + 1, blink::WebRect());
@@ -2568,7 +2584,7 @@ void PepperPluginInstanceImpl::SetTickmarks(PP_Instance instance,
tickmarks[i].size.width,
tickmarks[i].size.height);
}
- blink::WebFrame* frame = render_frame_->GetWebFrame();
+ blink::WebLocalFrame* frame = render_frame_->GetWebFrame();
frame->setTickmarks(tickmarks_converted);
}
@@ -2865,8 +2881,8 @@ PP_Var PepperPluginInstanceImpl::GetPluginReferrerURL(
WebString referer = request.httpHeaderField("Referer");
if (referer.isEmpty())
return PP_MakeUndefined();
- return ppapi::PPB_URLUtil_Shared::GenerateURLReturn(GURL(referer),
- components);
+ return ppapi::PPB_URLUtil_Shared::GenerateURLReturn(
+ blink::WebStringToGURL(referer), components);
}
PP_ExternalPluginResult PepperPluginInstanceImpl::ResetAsProxied(
@@ -2979,7 +2995,7 @@ PP_Resource PepperPluginInstanceImpl::CreateImage(gfx::ImageSkia* source_image,
if (!mapper.is_valid())
return 0;
- skia::PlatformCanvas* canvas = image_data->GetPlatformCanvas();
+ SkCanvas* canvas = image_data->GetPlatformCanvas();
// Note: Do not SkBitmap::copyTo the canvas bitmap directly because it will
// ignore the allocated pixels in shared memory and re-allocate a new buffer.
canvas->writePixels(image_skia_rep.sk_bitmap(), 0, 0);
@@ -3024,7 +3040,7 @@ void PepperPluginInstanceImpl::SetAlwaysOnTop(bool on_top) {
void PepperPluginInstanceImpl::DoSetCursor(WebCursorInfo* cursor) {
cursor_.reset(cursor);
if (fullscreen_container_) {
- fullscreen_container_->DidChangeCursor(*cursor);
+ fullscreen_container_->PepperDidChangeCursor(*cursor);
} else if (render_frame_) {
render_frame_->PepperDidChangeCursor(this, *cursor);
}
@@ -3164,8 +3180,8 @@ bool PepperPluginInstanceImpl::CanAccessMainFrame() const {
blink::WebDocument main_document =
containing_document.frame()->view()->mainFrame()->document();
- return containing_document.securityOrigin().canAccess(
- main_document.securityOrigin());
+ return containing_document.getSecurityOrigin().canAccess(
+ main_document.getSecurityOrigin());
}
void PepperPluginInstanceImpl::KeepSizeAttributesBeforeFullscreen() {
@@ -3298,4 +3314,18 @@ void PepperPluginInstanceImpl::RecordFlashJavaScriptUse() {
}
}
+void PepperPluginInstanceImpl::ConvertRectToDIP(PP_Rect* rect) const {
+ rect->point.x *= viewport_to_dip_scale_;
+ rect->point.y *= viewport_to_dip_scale_;
+ rect->size.width *= viewport_to_dip_scale_;
+ rect->size.height *= viewport_to_dip_scale_;
+}
+
+void PepperPluginInstanceImpl::ConvertDIPToViewport(gfx::Rect* rect) const {
+ rect->set_x(rect->x() / viewport_to_dip_scale_);
+ rect->set_y(rect->y() / viewport_to_dip_scale_);
+ rect->set_width(rect->width() / viewport_to_dip_scale_);
+ rect->set_height(rect->height() / viewport_to_dip_scale_);
+}
+
} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h
index cb9b60cc028..db95d8e6c1b 100644
--- a/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h
+++ b/chromium/content/renderer/pepper/pepper_plugin_instance_impl.h
@@ -54,7 +54,6 @@
#include "ppapi/shared_impl/tracked_callback.h"
#include "ppapi/thunk/ppb_gamepad_api.h"
#include "ppapi/thunk/resource_creation_api.h"
-#include "skia/ext/refptr.h"
#include "third_party/WebKit/public/platform/WebCanvas.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
@@ -91,6 +90,7 @@ class TextureLayer;
namespace gfx {
class Range;
+class Rect;
}
namespace ppapi {
@@ -695,6 +695,10 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
void RecordFlashJavaScriptUse();
+ // Converts the PP_Rect between DIP and Viewport.
+ void ConvertRectToDIP(PP_Rect* rect) const;
+ void ConvertDIPToViewport(gfx::Rect* rect) const;
+
RenderFrameImpl* render_frame_;
base::Closure instance_deleted_callback_;
scoped_refptr<PluginModule> module_;
@@ -743,6 +747,8 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
ppapi::ViewData last_sent_view_data_;
// The current unobscured portion of the plugin.
gfx::Rect unobscured_rect_;
+ // The viewport coordinates to window coordinates ratio.
+ float viewport_to_dip_scale_;
// Indicates if we've ever sent a didChangeView to the plugin. This ensures we
// always send an initial notification, even if the position and clip are the
@@ -800,7 +806,7 @@ class CONTENT_EXPORT PepperPluginInstanceImpl
// to generate the entire PDF given the variables below:
//
// The most recently used WebCanvas, guaranteed to be valid.
- skia::RefPtr<blink::WebCanvas> canvas_;
+ sk_sp<blink::WebCanvas> canvas_;
// An array of page ranges.
std::vector<PP_PrintPageNumberRange_Dev> ranges_;
diff --git a/chromium/content/renderer/pepper/pepper_proxy_channel_delegate_impl.cc b/chromium/content/renderer/pepper/pepper_proxy_channel_delegate_impl.cc
index 8b294ab12d3..9b0341591a8 100644
--- a/chromium/content/renderer/pepper/pepper_proxy_channel_delegate_impl.cc
+++ b/chromium/content/renderer/pepper/pepper_proxy_channel_delegate_impl.cc
@@ -40,16 +40,7 @@ base::SharedMemoryHandle
PepperProxyChannelDelegateImpl::ShareSharedMemoryHandleWithRemote(
const base::SharedMemoryHandle& handle,
base::ProcessId remote_pid) {
-#if defined(OS_WIN) || defined(OS_MACOSX)
- base::SharedMemoryHandle duped_handle;
- bool success =
- BrokerDuplicateSharedMemoryHandle(handle, remote_pid, &duped_handle);
- if (success)
- return duped_handle;
- return base::SharedMemory::NULLHandle();
-#else
return base::SharedMemory::DuplicateHandle(handle);
-#endif // defined(OS_WIN) || defined(OS_MACOSX)
}
} // namespace content
diff --git a/chromium/content/renderer/pepper/pepper_url_loader_host.cc b/chromium/content/renderer/pepper/pepper_url_loader_host.cc
index 6f63a639b9c..53bc31305fb 100644
--- a/chromium/content/renderer/pepper/pepper_url_loader_host.cc
+++ b/chromium/content/renderer/pepper/pepper_url_loader_host.cc
@@ -17,6 +17,7 @@
#include "ppapi/host/ppapi_host.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/ppapi_globals.h"
+#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/platform/WebURLError.h"
#include "third_party/WebKit/public/platform/WebURLLoader.h"
#include "third_party/WebKit/public/platform/WebURLRequest.h"
@@ -26,7 +27,6 @@
#include "third_party/WebKit/public/web/WebKit.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebPluginContainer.h"
-#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
#include "third_party/WebKit/public/web/WebURLLoaderOptions.h"
using blink::WebLocalFrame;
diff --git a/chromium/content/renderer/pepper/pepper_url_request_unittest.cc b/chromium/content/renderer/pepper/pepper_url_request_unittest.cc
index 8c374d5f32b..35f12c1119d 100644
--- a/chromium/content/renderer/pepper/pepper_url_request_unittest.cc
+++ b/chromium/content/renderer/pepper/pepper_url_request_unittest.cc
@@ -23,7 +23,6 @@
// test it by making sure the conversion routines actually work at the same
// time.
-using blink::WebCString;
using blink::WebFrameClient;
using blink::WebString;
using blink::WebView;
@@ -32,15 +31,6 @@ using blink::WebURLRequest;
namespace {
-bool IsExpected(const WebCString& web_string, const char* expected) {
- const char* result = web_string.data();
- return strcmp(result, expected) == 0;
-}
-
-bool IsExpected(const WebString& web_string, const char* expected) {
- return IsExpected(web_string.utf8(), expected);
-}
-
// The base class destructor is protected, so derive.
class TestWebFrameClient : public WebFrameClient {};
@@ -79,12 +69,12 @@ class URLRequestInfoTest : public RenderViewTest {
return web_request.downloadToFile();
}
- std::string GetURL() {
+ WebString GetURL() {
WebURLRequest web_request;
URLRequestInfoData data = info_->GetData();
if (!CreateWebURLRequest(pp_instance_, &data, GetMainFrame(), &web_request))
- return WebCString();
- return web_request.url().string().utf8();
+ return WebString();
+ return web_request.url().string();
}
WebString GetMethod() {
@@ -208,7 +198,7 @@ TEST_F(URLRequestInfoTest, AllowCredentials) {
TEST_F(URLRequestInfoTest, SetURL) {
const char* url = "http://www.google.com/";
EXPECT_TRUE(SetStringProperty(PP_URLREQUESTPROPERTY_URL, url));
- EXPECT_TRUE(IsExpected(GetURL(), url));
+ EXPECT_STREQ(url, GetURL().utf8().data());
}
TEST_F(URLRequestInfoTest, JavascriptURL) {
@@ -220,22 +210,22 @@ TEST_F(URLRequestInfoTest, JavascriptURL) {
TEST_F(URLRequestInfoTest, SetMethod) {
// Test default method is "GET".
- EXPECT_TRUE(IsExpected(GetMethod(), "GET"));
+ EXPECT_STREQ("GET", GetMethod().utf8().data());
EXPECT_TRUE(SetStringProperty(PP_URLREQUESTPROPERTY_METHOD, "POST"));
- EXPECT_TRUE(IsExpected(GetMethod(), "POST"));
+ EXPECT_STREQ("POST", GetMethod().utf8().data());
}
TEST_F(URLRequestInfoTest, SetHeaders) {
// Test default header field.
- EXPECT_TRUE(IsExpected(GetHeaderValue("foo"), ""));
+ EXPECT_STREQ("", GetHeaderValue("foo").utf8().data());
// Test that we can set a header field.
EXPECT_TRUE(SetStringProperty(PP_URLREQUESTPROPERTY_HEADERS, "foo: bar"));
- EXPECT_TRUE(IsExpected(GetHeaderValue("foo"), "bar"));
+ EXPECT_STREQ("bar", GetHeaderValue("foo").utf8().data());
// Test that we can set multiple header fields using \n delimiter.
EXPECT_TRUE(
SetStringProperty(PP_URLREQUESTPROPERTY_HEADERS, "foo: bar\nbar: baz"));
- EXPECT_TRUE(IsExpected(GetHeaderValue("foo"), "bar"));
- EXPECT_TRUE(IsExpected(GetHeaderValue("bar"), "baz"));
+ EXPECT_STREQ("bar", GetHeaderValue("foo").utf8().data());
+ EXPECT_STREQ("baz", GetHeaderValue("bar").utf8().data());
}
// TODO(bbudge) Unit tests for AppendDataToBody, AppendFileToBody.
diff --git a/chromium/content/renderer/pepper/pepper_video_capture_host.cc b/chromium/content/renderer/pepper/pepper_video_capture_host.cc
index 4e0866122fb..e960474c50a 100644
--- a/chromium/content/renderer/pepper/pepper_video_capture_host.cc
+++ b/chromium/content/renderer/pepper/pepper_video_capture_host.cc
@@ -412,6 +412,9 @@ PepperVideoCaptureHost::BufferInfo::BufferInfo()
: in_use(false), data(NULL), buffer() {
}
+PepperVideoCaptureHost::BufferInfo::BufferInfo(const BufferInfo& other) =
+ default;
+
PepperVideoCaptureHost::BufferInfo::~BufferInfo() {
}
diff --git a/chromium/content/renderer/pepper/pepper_video_capture_host.h b/chromium/content/renderer/pepper/pepper_video_capture_host.h
index 01d678bab5c..5a2dead2441 100644
--- a/chromium/content/renderer/pepper/pepper_video_capture_host.h
+++ b/chromium/content/renderer/pepper/pepper_video_capture_host.h
@@ -95,6 +95,7 @@ class PepperVideoCaptureHost : public ppapi::host::ResourceHost {
// Buffers of video frame.
struct BufferInfo {
BufferInfo();
+ BufferInfo(const BufferInfo& other);
~BufferInfo();
bool in_use;
diff --git a/chromium/content/renderer/pepper/pepper_video_decoder_host.cc b/chromium/content/renderer/pepper/pepper_video_decoder_host.cc
index c262b5785ec..8016b9e0b2a 100644
--- a/chromium/content/renderer/pepper/pepper_video_decoder_host.cc
+++ b/chromium/content/renderer/pepper/pepper_video_decoder_host.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/memory/shared_memory.h"
#include "build/build_config.h"
-#include "content/common/gpu/client/command_buffer_proxy_impl.h"
#include "content/common/pepper_file_util.h"
#include "content/public/common/content_client.h"
#include "content/public/renderer/content_renderer_client.h"
@@ -18,7 +17,9 @@
#include "content/renderer/pepper/gfx_conversion.h"
#include "content/renderer/pepper/ppb_graphics_3d_impl.h"
#include "content/renderer/pepper/video_decoder_shim.h"
+#include "gpu/ipc/client/command_buffer_proxy_impl.h"
#include "media/base/limits.h"
+#include "media/gpu/ipc/client/gpu_video_decode_accelerator_host.h"
#include "media/video/video_decode_accelerator.h"
#include "ppapi/c/pp_completion_callback.h"
#include "ppapi/c/pp_errors.h"
@@ -64,7 +65,7 @@ media::VideoCodecProfile PepperToMediaVideoProfile(PP_VideoProfile profile) {
case PP_VIDEOPROFILE_VP8_ANY:
return media::VP8PROFILE_ANY;
case PP_VIDEOPROFILE_VP9_ANY:
- return media::VP9PROFILE_ANY;
+ return media::VP9PROFILE_PROFILE0;
// No default case, to catch unhandled PP_VideoProfile values.
}
@@ -133,7 +134,8 @@ int32_t PepperVideoDecoderHost::OnHostMsgInitialize(
PPB_Graphics3D_Impl* graphics3d =
static_cast<PPB_Graphics3D_Impl*>(enter_graphics.object());
- CommandBufferProxyImpl* command_buffer = graphics3d->GetCommandBufferProxy();
+ gpu::CommandBufferProxyImpl* command_buffer =
+ graphics3d->GetCommandBufferProxy();
if (!command_buffer)
return PP_ERROR_FAILED;
@@ -145,10 +147,14 @@ int32_t PepperVideoDecoderHost::OnHostMsgInitialize(
if (acceleration != PP_HARDWAREACCELERATION_NONE) {
// This is not synchronous, but subsequent IPC messages will be buffered, so
// it is okay to immediately send IPC messages.
- decoder_ = command_buffer->CreateVideoDecoder();
- if (decoder_ && decoder_->Initialize(profile_, this)) {
- initialized_ = true;
- return PP_OK;
+ gpu::GpuChannelHost* channel = command_buffer->channel();
+ if (channel) {
+ decoder_.reset(
+ new media::GpuVideoDecodeAcceleratorHost(channel, command_buffer));
+ if (decoder_->Initialize(profile_, this)) {
+ initialized_ = true;
+ return PP_OK;
+ }
}
decoder_.reset();
if (acceleration == PP_HARDWAREACCELERATION_ONLY)
@@ -274,10 +280,11 @@ int32_t PepperVideoDecoderHost::OnHostMsgAssignTextures(
std::vector<media::PictureBuffer> picture_buffers;
for (uint32_t i = 0; i < texture_ids.size(); i++) {
+ media::PictureBuffer::TextureIds ids;
+ ids.push_back(texture_ids[i]);
media::PictureBuffer buffer(
texture_ids[i], // Use the texture_id to identify the buffer.
- gfx::Size(size.width, size.height),
- texture_ids[i]);
+ gfx::Size(size.width, size.height), ids);
picture_buffers.push_back(buffer);
}
decoder_->AssignPictureBuffers(picture_buffers);
@@ -346,8 +353,10 @@ int32_t PepperVideoDecoderHost::OnHostMsgReset(
void PepperVideoDecoderHost::ProvidePictureBuffers(
uint32_t requested_num_of_buffers,
+ uint32_t textures_per_buffer,
const gfx::Size& dimensions,
uint32_t texture_target) {
+ DCHECK_EQ(1u, textures_per_buffer);
RequestTextures(std::max(min_picture_count_, requested_num_of_buffers),
dimensions,
texture_target,
@@ -425,7 +434,6 @@ void PepperVideoDecoderHost::NotifyError(
case media::VideoDecodeAccelerator::ILLEGAL_STATE:
case media::VideoDecodeAccelerator::INVALID_ARGUMENT:
case media::VideoDecodeAccelerator::PLATFORM_FAILURE:
- case media::VideoDecodeAccelerator::LARGEST_ERROR_ENUM:
pp_error = PP_ERROR_RESOURCE_FAILED;
break;
// No default case, to catch unhandled enum values.
diff --git a/chromium/content/renderer/pepper/pepper_video_decoder_host.h b/chromium/content/renderer/pepper/pepper_video_decoder_host.h
index 7a63d4f59e7..f8b4534a63b 100644
--- a/chromium/content/renderer/pepper/pepper_video_decoder_host.h
+++ b/chromium/content/renderer/pepper/pepper_video_decoder_host.h
@@ -73,6 +73,7 @@ class CONTENT_EXPORT PepperVideoDecoderHost
// media::VideoDecodeAccelerator::Client implementation.
void ProvidePictureBuffers(uint32_t requested_num_of_buffers,
+ uint32_t textures_per_buffer,
const gfx::Size& dimensions,
uint32_t texture_target) override;
void DismissPictureBuffer(int32_t picture_buffer_id) override;
diff --git a/chromium/content/renderer/pepper/pepper_video_encoder_host.cc b/chromium/content/renderer/pepper/pepper_video_encoder_host.cc
index b78131d5273..afdc33d63f7 100644
--- a/chromium/content/renderer/pepper/pepper_video_encoder_host.cc
+++ b/chromium/content/renderer/pepper/pepper_video_encoder_host.cc
@@ -10,16 +10,17 @@
#include "base/memory/shared_memory.h"
#include "base/numerics/safe_math.h"
#include "build/build_config.h"
-#include "content/common/gpu/client/command_buffer_proxy_impl.h"
-#include "content/common/gpu/media/gpu_video_accelerator_util.h"
#include "content/common/pepper_file_util.h"
#include "content/public/renderer/renderer_ppapi_host.h"
#include "content/renderer/pepper/gfx_conversion.h"
#include "content/renderer/pepper/host_globals.h"
#include "content/renderer/pepper/video_encoder_shim.h"
#include "content/renderer/render_thread_impl.h"
+#include "gpu/ipc/client/command_buffer_proxy_impl.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/video_frame.h"
+#include "media/gpu/ipc/client/gpu_video_encode_accelerator_host.h"
+#include "media/gpu/ipc/common/gpu_video_accelerator_util.h"
#include "media/renderers/gpu_video_accelerator_factories.h"
#include "media/video/video_encode_accelerator.h"
#include "ppapi/c/pp_codecs.h"
@@ -79,7 +80,7 @@ media::VideoCodecProfile PP_ToMediaVideoProfile(PP_VideoProfile profile) {
case PP_VIDEOPROFILE_VP8_ANY:
return media::VP8PROFILE_ANY;
case PP_VIDEOPROFILE_VP9_ANY:
- return media::VP9PROFILE_ANY;
+ return media::VP9PROFILE_PROFILE0;
// No default case, to catch unhandled PP_VideoProfile values.
}
return media::VIDEO_CODEC_PROFILE_UNKNOWN;
@@ -111,7 +112,7 @@ PP_VideoProfile PP_FromMediaVideoProfile(media::VideoCodecProfile profile) {
return PP_VIDEOPROFILE_H264MULTIVIEWHIGH;
case media::VP8PROFILE_ANY:
return PP_VIDEOPROFILE_VP8_ANY;
- case media::VP9PROFILE_ANY:
+ case media::VP9PROFILE_PROFILE0:
return PP_VIDEOPROFILE_VP9_ANY;
default:
NOTREACHED();
@@ -450,9 +451,14 @@ void PepperVideoEncoderHost::GetSupportedProfiles(
media::VideoEncodeAccelerator::SupportedProfiles profiles;
if (EnsureGpuChannel()) {
- profiles = GpuVideoAcceleratorUtil::ConvertGpuToMediaEncodeProfiles(
+ profiles = media::GpuVideoAcceleratorUtil::ConvertGpuToMediaEncodeProfiles(
channel_->gpu_info().video_encode_accelerator_supported_profiles);
for (media::VideoEncodeAccelerator::SupportedProfile profile : profiles) {
+ if (profile.profile == media::VP9PROFILE_PROFILE1 ||
+ profile.profile == media::VP9PROFILE_PROFILE2 ||
+ profile.profile == media::VP9PROFILE_PROFILE3) {
+ continue;
+ }
pp_profiles->push_back(
PP_FromVideoEncodeAcceleratorSupportedProfile(profile, PP_TRUE));
}
@@ -503,9 +509,10 @@ bool PepperVideoEncoderHost::EnsureGpuChannel() {
return false;
std::vector<int32_t> attribs(1, PP_GRAPHICS3DATTRIB_NONE);
- command_buffer_ = channel_->CreateOffscreenCommandBuffer(
- gfx::Size(), nullptr, GpuChannelHost::kDefaultStreamId,
- GpuChannelHost::kDefaultStreamPriority, attribs, GURL::EmptyGURL(),
+ command_buffer_ = channel_->CreateCommandBuffer(
+ gpu::kNullSurfaceHandle, gfx::Size(), nullptr,
+ gpu::GpuChannelHost::kDefaultStreamId,
+ gpu::GpuChannelHost::kDefaultStreamPriority, attribs, GURL::EmptyGURL(),
gfx::PreferIntegratedGpu);
if (!command_buffer_) {
Close();
@@ -533,13 +540,10 @@ bool PepperVideoEncoderHost::InitializeHardware(
if (!EnsureGpuChannel())
return false;
- encoder_ = command_buffer_->CreateVideoEncoder();
- if (!encoder_ ||
- !encoder_->Initialize(input_format, input_visible_size, output_profile,
- initial_bitrate, this))
- return false;
-
- return true;
+ encoder_.reset(new media::GpuVideoEncodeAcceleratorHost(
+ channel_.get(), command_buffer_.get()));
+ return encoder_->Initialize(input_format, input_visible_size, output_profile,
+ initial_bitrate, this);
}
void PepperVideoEncoderHost::Close() {
diff --git a/chromium/content/renderer/pepper/pepper_video_encoder_host.h b/chromium/content/renderer/pepper/pepper_video_encoder_host.h
index 5bc8d70cac4..d6a47d8f34c 100644
--- a/chromium/content/renderer/pepper/pepper_video_encoder_host.h
+++ b/chromium/content/renderer/pepper/pepper_video_encoder_host.h
@@ -21,14 +21,17 @@
#include "ppapi/proxy/resource_message_params.h"
#include "ppapi/shared_impl/media_stream_buffer_manager.h"
+namespace gpu {
+class CommandBufferProxyImpl;
+class GpuChannelHost;
+}
+
namespace media {
class GpuVideoAcceleratorFactories;
}
namespace content {
-class CommandBufferProxyImpl;
-class GpuChannelHost;
class RendererPpapiHost;
class VideoEncoderShim;
@@ -126,8 +129,8 @@ class CONTENT_EXPORT PepperVideoEncoderHost
// Buffer manager for shared memory that holds video frames.
ppapi::MediaStreamBufferManager buffer_manager_;
- scoped_refptr<GpuChannelHost> channel_;
- scoped_ptr<CommandBufferProxyImpl> command_buffer_;
+ scoped_refptr<gpu::GpuChannelHost> channel_;
+ scoped_ptr<gpu::CommandBufferProxyImpl> command_buffer_;
scoped_ptr<media::VideoEncodeAccelerator> encoder_;
diff --git a/chromium/content/renderer/pepper/pepper_video_source_host.cc b/chromium/content/renderer/pepper/pepper_video_source_host.cc
index db20126b141..cac83ebf76e 100644
--- a/chromium/content/renderer/pepper/pepper_video_source_host.cc
+++ b/chromium/content/renderer/pepper/pepper_video_source_host.cc
@@ -12,6 +12,7 @@
#include "content/renderer/media/video_track_to_pepper_adapter.h"
#include "content/renderer/pepper/ppb_image_data_impl.h"
#include "content/renderer/render_thread_impl.h"
+#include "media/base/video_util.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/host/dispatch_host_message.h"
#include "ppapi/host/ppapi_host.h"
@@ -55,10 +56,21 @@ PepperVideoSourceHost::FrameReceiver::FrameReceiver(
PepperVideoSourceHost::FrameReceiver::~FrameReceiver() {}
void PepperVideoSourceHost::FrameReceiver::GotFrame(
- const scoped_refptr<media::VideoFrame>& frame) {
+ const scoped_refptr<media::VideoFrame>& video_frame) {
DCHECK(thread_checker_.CalledOnValidThread());
if (!host_)
return;
+
+ if (!(video_frame->format() == media::PIXEL_FORMAT_I420 ||
+ video_frame->format() == media::PIXEL_FORMAT_YV12A)) {
+ NOTREACHED();
+ return;
+ }
+ scoped_refptr<media::VideoFrame> frame = video_frame;
+ // Drop alpha channel since we do not support it yet.
+ if (frame->format() == media::PIXEL_FORMAT_YV12A)
+ frame = media::WrapAsI420VideoFrame(video_frame);
+
// Hold a reference to the new frame and release the previous.
host_->last_frame_ = frame;
if (host_->get_frame_pending_)
diff --git a/chromium/content/renderer/pepper/pepper_webplugin_impl.cc b/chromium/content/renderer/pepper/pepper_webplugin_impl.cc
index 7c4e04de0c9..45bf64fc8f9 100644
--- a/chromium/content/renderer/pepper/pepper_webplugin_impl.cc
+++ b/chromium/content/renderer/pepper/pepper_webplugin_impl.cc
@@ -23,7 +23,6 @@
#include "third_party/WebKit/public/platform/WebRect.h"
#include "third_party/WebKit/public/platform/WebSize.h"
#include "third_party/WebKit/public/platform/WebURLLoaderClient.h"
-#include "third_party/WebKit/public/web/WebBindings.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebElement.h"
#include "third_party/WebKit/public/web/WebFrame.h"
@@ -66,8 +65,8 @@ PepperWebPluginImpl::PepperWebPluginImpl(
full_frame_(params.loadManually),
throttler_(std::move(throttler)),
instance_object_(PP_MakeUndefined()),
- container_(NULL),
- weak_factory_(this) {
+ container_(nullptr),
+ destroyed_(false) {
DCHECK(plugin_module);
init_data_->module = plugin_module;
init_data_->render_frame = render_frame;
@@ -91,37 +90,32 @@ blink::WebPluginContainer* PepperWebPluginImpl::container() const {
}
bool PepperWebPluginImpl::initialize(WebPluginContainer* container) {
+ DCHECK(container);
+ DCHECK_EQ(this, container->plugin());
+
+ container_ = container;
+
// The plugin delegate may have gone away.
instance_ = init_data_->module->CreateInstance(
init_data_->render_frame, container, init_data_->url);
- if (!instance_.get())
+ if (!instance_)
return false;
- // Enable script objects for this plugin.
- container->allowScriptObjects();
-
- auto weak_this = weak_factory_.GetWeakPtr();
- bool success =
- instance_->Initialize(init_data_->arg_names, init_data_->arg_values,
- full_frame_, std::move(throttler_));
- // The above call to Initialize can result in re-entrancy and destruction of
- // the plugin instance. In this case it's quite unclear whether this object
- // could also have been destroyed. We could return false here, but it would be
- // better if this object was guaranteed to outlast the recursive call.
- // Otherwise, the caller of this function would also have to take care that,
- // in the case of the object being deleted, we never access it again, and we
- // would just keep passing that responsibility further up the call stack.
- // Classes tend not to be written with this possibility in mind so it's best
- // to make this assumption as far down the call stack (as close to the
- // re-entrant call) as possible. Also take care not to access the plugin
- // instance again in that case. crbug.com/487146.
- CHECK(weak_this);
-
- if (!success) {
- if (instance_) {
- instance_->Delete();
- instance_ = NULL;
- }
+ if (!instance_->Initialize(init_data_->arg_names, init_data_->arg_values,
+ full_frame_, std::move(throttler_))) {
+ // If |container_| is nullptr, this object has already been synchronously
+ // destroy()-ed during |instance_|'s Initialize call. In that case, we early
+ // exit. We neither create a replacement plugin nor destroy() ourselves.
+ if (!container_)
+ return false;
+
+ DCHECK(!destroyed_);
+
+ DCHECK(instance_);
+ ppapi::PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(instance_object_);
+ instance_object_ = PP_MakeUndefined();
+ instance_->Delete();
+ instance_ = nullptr;
blink::WebPlugin* replacement_plugin =
GetContentClient()->renderer()->CreatePluginReplacement(
@@ -129,38 +123,36 @@ bool PepperWebPluginImpl::initialize(WebPluginContainer* container) {
if (!replacement_plugin)
return false;
- // Since we are setting the container to own the replacement plugin, we must
- // schedule ourselves for deletion.
- destroy();
+ // The replacement plugin, if it exists, must never fail to initialize.
container->setPlugin(replacement_plugin);
- if (!replacement_plugin->initialize(container)) {
- CHECK(replacement_plugin->container() == nullptr);
- return false;
- }
+ CHECK(replacement_plugin->initialize(container));
+
+ DCHECK(container->plugin() == replacement_plugin);
+ DCHECK(replacement_plugin->container() == container);
+
+ // Since the container now owns the replacement plugin instead of this
+ // object, we must schedule ourselves for deletion.
+ destroy();
- CHECK(container->plugin() == replacement_plugin);
- CHECK(replacement_plugin->container() == container);
return true;
}
init_data_.reset();
- CHECK(container->plugin() == this);
- container_ = container;
return true;
}
void PepperWebPluginImpl::destroy() {
- // Tell |container_| to clear references to this plugin's script objects.
- if (container_)
- container_->clearScriptObjects();
+ // TODO(tommycli): Remove once we fix https://crbug.com/588624.
+ CHECK(!destroyed_);
+ destroyed_ = true;
container_ = nullptr;
- if (instance_.get()) {
+ if (instance_) {
ppapi::PpapiGlobals::Get()->GetVarTracker()->ReleaseVar(instance_object_);
instance_object_ = PP_MakeUndefined();
instance_->Delete();
- instance_ = NULL;
+ instance_ = nullptr;
}
base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
@@ -170,22 +162,22 @@ v8::Local<v8::Object> PepperWebPluginImpl::v8ScriptableObject(
v8::Isolate* isolate) {
// Re-entrancy may cause JS to try to execute script on the plugin before it
// is fully initialized. See e.g. crbug.com/503401.
- if (!instance_.get())
+ if (!instance_)
return v8::Local<v8::Object>();
// Call through the plugin to get its instance object. The plugin should pass
// us a reference which we release in destroy().
if (instance_object_.type == PP_VARTYPE_UNDEFINED)
instance_object_ = instance_->GetInstanceObject(isolate);
// GetInstanceObject talked to the plugin which may have removed the instance
- // from the DOM, in which case instance_ would be NULL now.
- if (!instance_.get())
+ // from the DOM, in which case instance_ would be nullptr now.
+ if (!instance_)
return v8::Local<v8::Object>();
scoped_refptr<V8ObjectVar> object_var(
V8ObjectVar::FromPPVar(instance_object_));
// If there's an InstanceObject, tell the Instance's MessageChannel to pass
// any non-postMessage calls to it.
- if (object_var.get()) {
+ if (object_var) {
MessageChannel* message_channel = instance_->message_channel();
if (message_channel)
message_channel->SetPassthroughObject(object_var->GetHandle());
@@ -195,8 +187,6 @@ v8::Local<v8::Object> PepperWebPluginImpl::v8ScriptableObject(
return result;
}
-bool PepperWebPluginImpl::getFormValue(WebString& value) { return false; }
-
void PepperWebPluginImpl::paint(WebCanvas* canvas, const WebRect& rect) {
if (!instance_->FlashIsFullscreenOrPending())
instance_->Paint(canvas, plugin_rect_, rect);
@@ -224,8 +214,6 @@ void PepperWebPluginImpl::updateFocus(bool focused,
void PepperWebPluginImpl::updateVisibility(bool visible) {}
-bool PepperWebPluginImpl::acceptsInputEvents() { return true; }
-
blink::WebInputEventResult PepperWebPluginImpl::handleInputEvent(
const blink::WebInputEvent& event,
blink::WebCursorInfo& cursor_info) {
@@ -245,20 +233,20 @@ void PepperWebPluginImpl::didReceiveResponse(
void PepperWebPluginImpl::didReceiveData(const char* data, int data_length) {
blink::WebURLLoaderClient* document_loader = instance_->document_loader();
if (document_loader)
- document_loader->didReceiveData(NULL, data, data_length, 0);
+ document_loader->didReceiveData(nullptr, data, data_length, 0);
}
void PepperWebPluginImpl::didFinishLoading() {
blink::WebURLLoaderClient* document_loader = instance_->document_loader();
if (document_loader)
document_loader->didFinishLoading(
- NULL, 0.0, blink::WebURLLoaderClient::kUnknownEncodedDataLength);
+ nullptr, 0.0, blink::WebURLLoaderClient::kUnknownEncodedDataLength);
}
void PepperWebPluginImpl::didFailLoading(const blink::WebURLError& error) {
blink::WebURLLoaderClient* document_loader = instance_->document_loader();
if (document_loader)
- document_loader->didFail(NULL, error);
+ document_loader->didFail(nullptr, error);
}
bool PepperWebPluginImpl::hasSelection() const {
diff --git a/chromium/content/renderer/pepper/pepper_webplugin_impl.h b/chromium/content/renderer/pepper/pepper_webplugin_impl.h
index 65641ea27f9..3ec6ea20a29 100644
--- a/chromium/content/renderer/pepper/pepper_webplugin_impl.h
+++ b/chromium/content/renderer/pepper/pepper_webplugin_impl.h
@@ -45,7 +45,6 @@ class PepperWebPluginImpl : public blink::WebPlugin {
bool initialize(blink::WebPluginContainer* container) override;
void destroy() override;
v8::Local<v8::Object> v8ScriptableObject(v8::Isolate* isolate) override;
- bool getFormValue(blink::WebString& value) override;
void updateAllLifecyclePhases() override {}
void paint(blink::WebCanvas* canvas, const blink::WebRect& rect) override;
void updateGeometry(const blink::WebRect& window_rect,
@@ -55,7 +54,6 @@ class PepperWebPluginImpl : public blink::WebPlugin {
bool is_visible) override;
void updateFocus(bool focused, blink::WebFocusType focus_type) override;
void updateVisibility(bool visible) override;
- bool acceptsInputEvents() override;
blink::WebInputEventResult handleInputEvent(
const blink::WebInputEvent& event,
blink::WebCursorInfo& cursor_info) override;
@@ -100,7 +98,9 @@ class PepperWebPluginImpl : public blink::WebPlugin {
gfx::Rect plugin_rect_;
PP_Var instance_object_;
blink::WebPluginContainer* container_;
- base::WeakPtrFactory<PepperWebPluginImpl> weak_factory_;
+
+ // TODO(tommycli): Remove once we fix https://crbug.com/588624.
+ bool destroyed_;
DISALLOW_COPY_AND_ASSIGN(PepperWebPluginImpl);
};
diff --git a/chromium/content/renderer/pepper/pepper_websocket_host.cc b/chromium/content/renderer/pepper/pepper_websocket_host.cc
index 2250a691406..aabe86c395d 100644
--- a/chromium/content/renderer/pepper/pepper_websocket_host.cc
+++ b/chromium/content/renderer/pepper/pepper_websocket_host.cc
@@ -19,21 +19,21 @@
#include "third_party/WebKit/public/web/WebArrayBuffer.h"
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebElement.h"
+#include "third_party/WebKit/public/web/WebPepperSocket.h"
#include "third_party/WebKit/public/web/WebPluginContainer.h"
-#include "third_party/WebKit/public/web/WebSocket.h"
using blink::WebArrayBuffer;
using blink::WebDocument;
using blink::WebString;
-using blink::WebSocket;
+using blink::WebPepperSocket;
using blink::WebURL;
namespace content {
-#define COMPILE_ASSERT_MATCHING_ENUM(webkit_name, np_name) \
- static_assert( \
- static_cast<int>(WebSocket::webkit_name) == static_cast<int>(np_name), \
- "WebSocket enums must match PPAPI's")
+#define COMPILE_ASSERT_MATCHING_ENUM(webkit_name, np_name) \
+ static_assert(static_cast<int>(WebPepperSocket::webkit_name) == \
+ static_cast<int>(np_name), \
+ "WebSocket enums must match PPAPI's")
COMPILE_ASSERT_MATCHING_ENUM(CloseEventCodeNormalClosure,
PP_WEBSOCKETSTATUSCODE_NORMAL_CLOSURE);
@@ -176,7 +176,7 @@ void PepperWebSocketHost::didClose(unsigned long unhandled_buffered_amount,
// Set close_was_clean_.
bool was_clean = (initiating_close_ || accepting_close_) &&
!unhandled_buffered_amount &&
- status == WebSocketClient::ClosingHandshakeComplete;
+ status == WebPepperSocketClient::ClosingHandshakeComplete;
if (initiating_close_) {
initiating_close_ = false;
@@ -259,13 +259,13 @@ int32_t PepperWebSocketHost::OnHostMsgConnect(
return PP_ERROR_BADARGUMENT;
// TODO(toyoshim) Remove following WebDocument object copy.
WebDocument document = container->element().document();
- websocket_.reset(WebSocket::create(document, this));
+ websocket_.reset(WebPepperSocket::create(document, this));
DCHECK(websocket_.get());
if (!websocket_)
return PP_ERROR_NOTSUPPORTED;
// Set receiving binary object type.
- websocket_->setBinaryType(WebSocket::BinaryTypeArrayBuffer);
+ websocket_->setBinaryType(WebPepperSocket::BinaryTypeArrayBuffer);
websocket_->connect(web_url, web_protocols);
connect_reply_ = context->MakeReplyMessageContext();
@@ -282,13 +282,13 @@ int32_t PepperWebSocketHost::OnHostMsgClose(
close_reply_ = context->MakeReplyMessageContext();
initiating_close_ = true;
- blink::WebSocket::CloseEventCode event_code =
- static_cast<blink::WebSocket::CloseEventCode>(code);
+ blink::WebPepperSocket::CloseEventCode event_code =
+ static_cast<blink::WebPepperSocket::CloseEventCode>(code);
if (code == PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED) {
// PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED and CloseEventCodeNotSpecified are
// assigned to different values. A conversion is needed if
// PP_WEBSOCKETSTATUSCODE_NOT_SPECIFIED is specified.
- event_code = blink::WebSocket::CloseEventCodeNotSpecified;
+ event_code = blink::WebPepperSocket::CloseEventCodeNotSpecified;
}
WebString web_reason = WebString::fromUTF8(reason);
diff --git a/chromium/content/renderer/pepper/pepper_websocket_host.h b/chromium/content/renderer/pepper/pepper_websocket_host.h
index c0106ad8b6b..baac2427948 100644
--- a/chromium/content/renderer/pepper/pepper_websocket_host.h
+++ b/chromium/content/renderer/pepper/pepper_websocket_host.h
@@ -16,8 +16,8 @@
#include "ppapi/host/host_message_context.h"
#include "ppapi/host/resource_host.h"
#include "ppapi/proxy/resource_message_params.h"
-#include "third_party/WebKit/public/web/WebSocket.h"
-#include "third_party/WebKit/public/web/WebSocketClient.h"
+#include "third_party/WebKit/public/web/WebPepperSocket.h"
+#include "third_party/WebKit/public/web/WebPepperSocketClient.h"
namespace ppapi {
class StringVar;
@@ -30,7 +30,7 @@ class RendererPpapiHost;
class CONTENT_EXPORT PepperWebSocketHost
: public ppapi::host::ResourceHost,
- public NON_EXPORTED_BASE(::blink::WebSocketClient) {
+ public NON_EXPORTED_BASE(::blink::WebPepperSocketClient) {
public:
explicit PepperWebSocketHost(RendererPpapiHost* host,
PP_Instance instance,
@@ -41,7 +41,7 @@ class CONTENT_EXPORT PepperWebSocketHost
const IPC::Message& msg,
ppapi::host::HostMessageContext* context) override;
- // WebSocketClient implementation.
+ // WebPepperSocketClient implementation.
void didConnect() override;
void didReceiveMessage(const blink::WebString& message) override;
void didReceiveArrayBuffer(const blink::WebArrayBuffer& binaryData) override;
@@ -93,7 +93,7 @@ class CONTENT_EXPORT PepperWebSocketHost
// Keeps the WebKit side WebSocket object. This is used for calling WebKit
// side functions via WebKit API.
- scoped_ptr<blink::WebSocket> websocket_;
+ scoped_ptr<blink::WebPepperSocket> websocket_;
DISALLOW_COPY_AND_ASSIGN(PepperWebSocketHost);
};
diff --git a/chromium/content/renderer/pepper/plugin_instance_throttler_impl.cc b/chromium/content/renderer/pepper/plugin_instance_throttler_impl.cc
index 5a153b79b09..009e7d5b8f2 100644
--- a/chromium/content/renderer/pepper/plugin_instance_throttler_impl.cc
+++ b/chromium/content/renderer/pepper/plugin_instance_throttler_impl.cc
@@ -141,7 +141,7 @@ void PluginInstanceThrottlerImpl::Initialize(
if (frame) {
float zoom_factor = GetWebPlugin()->container()->pageZoomFactor();
auto status = frame->GetPeripheralContentStatus(
- frame->GetWebFrame()->top()->securityOrigin(), content_origin,
+ frame->GetWebFrame()->top()->getSecurityOrigin(), content_origin,
gfx::Size(roundf(unobscured_size.width() / zoom_factor),
roundf(unobscured_size.height() / zoom_factor)));
if (status != RenderFrame::CONTENT_STATUS_PERIPHERAL) {
diff --git a/chromium/content/renderer/pepper/plugin_module.cc b/chromium/content/renderer/pepper/plugin_module.cc
index 8b2bfcbc0b8..a1bb699ad1e 100644
--- a/chromium/content/renderer/pepper/plugin_module.cc
+++ b/chromium/content/renderer/pepper/plugin_module.cc
@@ -39,7 +39,6 @@
#include "ppapi/c/dev/ppb_cursor_control_dev.h"
#include "ppapi/c/dev/ppb_device_ref_dev.h"
#include "ppapi/c/dev/ppb_file_chooser_dev.h"
-#include "ppapi/c/dev/ppb_font_dev.h"
#include "ppapi/c/dev/ppb_gles_chromium_texture_mapping_dev.h"
#include "ppapi/c/dev/ppb_memory_dev.h"
#include "ppapi/c/dev/ppb_opengles2ext_dev.h"
@@ -399,12 +398,6 @@ const PPB_Testing_Private testing_interface = {
// GetInterface ----------------------------------------------------------------
const void* InternalGetInterface(const char* name) {
- // Allow custom interface factories first stab at the GetInterface call.
- const void* custom_interface =
- GetContentClient()->renderer()->CreatePPAPIInterface(name);
- if (custom_interface)
- return custom_interface;
-
// TODO(brettw) put these in a hash map for better performance.
#define PROXIED_IFACE(iface_str, iface_struct) \
if (strcmp(name, iface_str) == 0) \
diff --git a/chromium/content/renderer/pepper/plugin_object.cc b/chromium/content/renderer/pepper/plugin_object.cc
index d6023fff08d..cb5ff6af9bb 100644
--- a/chromium/content/renderer/pepper/plugin_object.cc
+++ b/chromium/content/renderer/pepper/plugin_object.cc
@@ -79,8 +79,10 @@ PP_Var PluginObject::Create(PepperPluginInstanceImpl* instance,
// If the V8 context is empty, we may be in the process of tearing down the
// frame and may not have a valid isolate (in particular due to re-entrancy).
// We shouldn't try to call gin::CreateHandle.
- if (try_catch.GetContext().IsEmpty())
+ if (try_catch.GetContext().IsEmpty()) {
+ ppp_class->Deallocate(ppp_class_data);
return PP_MakeUndefined();
+ }
gin::Handle<PluginObject> object =
gin::CreateHandle(instance->GetIsolate(),
new PluginObject(instance, ppp_class, ppp_class_data));
@@ -92,6 +94,12 @@ PP_Var PluginObject::Create(PepperPluginInstanceImpl* instance,
v8::Local<v8::Value> PluginObject::GetNamedProperty(
v8::Isolate* isolate,
const std::string& identifier) {
+ if (!instance_) {
+ std::string error = "Property " + identifier + " does not exist.";
+ isolate->ThrowException(
+ v8::Exception::ReferenceError(gin::StringToV8(isolate, error)));
+ return v8::Local<v8::Value>();
+ }
ScopedPPVar identifier_var(ScopedPPVar::PassRef(),
StringVar::StringToPPVar(identifier));
return GetPropertyOrMethod(instance_->GetIsolate(), identifier_var.get());
@@ -100,8 +108,12 @@ v8::Local<v8::Value> PluginObject::GetNamedProperty(
bool PluginObject::SetNamedProperty(v8::Isolate* isolate,
const std::string& identifier,
v8::Local<v8::Value> value) {
- if (!instance_)
+ if (!instance_) {
+ std::string error = "Property " + identifier + " does not exist.";
+ isolate->ThrowException(
+ v8::Exception::ReferenceError(gin::StringToV8(isolate, error)));
return false;
+ }
ScopedPPVar identifier_var(ScopedPPVar::PassRef(),
StringVar::StringToPPVar(identifier));
V8VarConverter var_converter(instance_->pp_instance(),
@@ -134,8 +146,12 @@ bool PluginObject::SetNamedProperty(v8::Isolate* isolate,
std::vector<std::string> PluginObject::EnumerateNamedProperties(
v8::Isolate* isolate) {
std::vector<std::string> result;
- if (!instance_)
+ if (!instance_) {
+ std::string error = "Plugin object deleted";
+ isolate->ThrowException(
+ v8::Exception::ReferenceError(gin::StringToV8(isolate, error)));
return result;
+ }
V8VarConverter var_converter(instance_->pp_instance(),
V8VarConverter::kAllowObjectVars);
diff --git a/chromium/content/renderer/pepper/plugin_power_saver_helper.cc b/chromium/content/renderer/pepper/plugin_power_saver_helper.cc
index 10f0954a264..36d65e3f8fc 100644
--- a/chromium/content/renderer/pepper/plugin_power_saver_helper.cc
+++ b/chromium/content/renderer/pepper/plugin_power_saver_helper.cc
@@ -33,6 +33,9 @@ PluginPowerSaverHelper::PeripheralPlugin::PeripheralPlugin(
: content_origin(content_origin),
unthrottle_callback(unthrottle_callback) {}
+PluginPowerSaverHelper::PeripheralPlugin::PeripheralPlugin(
+ const PeripheralPlugin& other) = default;
+
PluginPowerSaverHelper::PeripheralPlugin::~PeripheralPlugin() {
}
diff --git a/chromium/content/renderer/pepper/plugin_power_saver_helper.h b/chromium/content/renderer/pepper/plugin_power_saver_helper.h
index 95fbc88ff88..2f3bb442657 100644
--- a/chromium/content/renderer/pepper/plugin_power_saver_helper.h
+++ b/chromium/content/renderer/pepper/plugin_power_saver_helper.h
@@ -37,6 +37,7 @@ class CONTENT_EXPORT PluginPowerSaverHelper : public RenderFrameObserver {
struct PeripheralPlugin {
PeripheralPlugin(const url::Origin& content_origin,
const base::Closure& unthrottle_callback);
+ PeripheralPlugin(const PeripheralPlugin& other);
~PeripheralPlugin();
url::Origin content_origin;
diff --git a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc
index 03e26d763f0..a5625a464da 100644
--- a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.cc
@@ -10,8 +10,6 @@
#include "base/single_thread_task_runner.h"
#include "base/strings/utf_string_conversions.h"
#include "base/thread_task_runner_handle.h"
-#include "content/common/gpu/client/command_buffer_proxy_impl.h"
-#include "content/common/gpu/client/gpu_channel_host.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/web_preferences.h"
#include "content/renderer/pepper/host_globals.h"
@@ -20,7 +18,8 @@
#include "content/renderer/pepper/plugin_module.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_view_impl.h"
-#include "gpu/command_buffer/client/gles2_interface.h"
+#include "gpu/ipc/client/command_buffer_proxy_impl.h"
+#include "gpu/ipc/client/gpu_channel_host.h"
#include "ppapi/c/ppp_graphics_3d.h"
#include "ppapi/thunk/enter.h"
#include "third_party/WebKit/public/platform/WebString.h"
@@ -39,13 +38,6 @@ using blink::WebString;
namespace content {
-namespace {
-
-const int32_t kCommandBufferSize = 1024 * 1024;
-const int32_t kTransferBufferSize = 1024 * 1024;
-
-} // namespace
-
PPB_Graphics3D_Impl::PPB_Graphics3D_Impl(PP_Instance instance)
: PPB_Graphics3D_Shared(instance),
bound_to_instance_(false),
@@ -56,31 +48,13 @@ PPB_Graphics3D_Impl::PPB_Graphics3D_Impl(PP_Instance instance)
PPB_Graphics3D_Impl::~PPB_Graphics3D_Impl() {}
// static
-PP_Resource PPB_Graphics3D_Impl::Create(PP_Instance instance,
- PP_Resource share_context,
- const int32_t* attrib_list) {
- PPB_Graphics3D_API* share_api = NULL;
- if (share_context) {
- EnterResourceNoLock<PPB_Graphics3D_API> enter(share_context, true);
- if (enter.failed())
- return 0;
- share_api = enter.object();
- }
- scoped_refptr<PPB_Graphics3D_Impl> graphics_3d(
- new PPB_Graphics3D_Impl(instance));
- if (!graphics_3d->Init(share_api, attrib_list))
- return 0;
- return graphics_3d->GetReference();
-}
-
-// static
PP_Resource PPB_Graphics3D_Impl::CreateRaw(
PP_Instance instance,
PP_Resource share_context,
const int32_t* attrib_list,
gpu::Capabilities* capabilities,
base::SharedMemoryHandle* shared_state_handle,
- uint64_t* command_buffer_id) {
+ gpu::CommandBufferId* command_buffer_id) {
PPB_Graphics3D_API* share_api = NULL;
if (share_context) {
EnterResourceNoLock<PPB_Graphics3D_API> enter(share_context, true);
@@ -131,18 +105,6 @@ gpu::CommandBuffer::State PPB_Graphics3D_Impl::WaitForGetOffsetInRange(
return GetCommandBuffer()->GetLastState();
}
-uint32_t PPB_Graphics3D_Impl::InsertSyncPoint() {
- return command_buffer_->InsertSyncPoint();
-}
-
-uint32_t PPB_Graphics3D_Impl::InsertFutureSyncPoint() {
- return command_buffer_->InsertFutureSyncPoint();
-}
-
-void PPB_Graphics3D_Impl::RetireSyncPoint(uint32_t sync_point) {
- return command_buffer_->RetireSyncPoint(sync_point);
-}
-
void PPB_Graphics3D_Impl::EnsureWorkVisible() {
command_buffer_->EnsureWorkVisible();
}
@@ -161,7 +123,7 @@ void PPB_Graphics3D_Impl::ViewInitiatedPaint() {
SwapBuffersACK(PP_OK);
}
-CommandBufferProxyImpl* PPB_Graphics3D_Impl::GetCommandBufferProxy() {
+gpu::CommandBufferProxyImpl* PPB_Graphics3D_Impl::GetCommandBufferProxy() {
DCHECK(command_buffer_);
return command_buffer_.get();
}
@@ -179,19 +141,6 @@ int32_t PPB_Graphics3D_Impl::DoSwapBuffers(const gpu::SyncToken& sync_token) {
if (sync_token.HasData())
sync_token_ = sync_token;
- // We do not have a GLES2 implementation when using an OOP proxy.
- // The plugin-side proxy is responsible for adding the SwapBuffers command
- // to the command buffer in that case.
- if (gpu::gles2::GLES2Interface* gl = gles2_interface()) {
- // A valid sync token would indicate a swap buffer already happened somehow.
- DCHECK(!sync_token.HasData());
-
- gl->SwapBuffers();
- const GLuint64 fence_sync = gl->InsertFenceSyncCHROMIUM();
- gl->OrderingBarrierCHROMIUM();
- gl->GenUnverifiedSyncTokenCHROMIUM(fence_sync, sync_token_.GetData());
- }
-
if (bound_to_instance_) {
// If we are bound to the instance, we need to ask the compositor
// to commit our backing texture so that the graphics appears on the page.
@@ -213,26 +162,11 @@ int32_t PPB_Graphics3D_Impl::DoSwapBuffers(const gpu::SyncToken& sync_token) {
return PP_OK_COMPLETIONPENDING;
}
-bool PPB_Graphics3D_Impl::Init(PPB_Graphics3D_API* share_context,
- const int32_t* attrib_list) {
- if (!InitRaw(share_context, attrib_list, NULL, NULL, NULL))
- return false;
-
- gpu::gles2::GLES2Implementation* share_gles2 = NULL;
- if (share_context) {
- share_gles2 =
- static_cast<PPB_Graphics3D_Shared*>(share_context)->gles2_impl();
- }
-
- return CreateGLES2Impl(kCommandBufferSize, kTransferBufferSize, share_gles2);
-}
-
-bool PPB_Graphics3D_Impl::InitRaw(
- PPB_Graphics3D_API* share_context,
- const int32_t* attrib_list,
- gpu::Capabilities* capabilities,
- base::SharedMemoryHandle* shared_state_handle,
- uint64_t* command_buffer_id) {
+bool PPB_Graphics3D_Impl::InitRaw(PPB_Graphics3D_API* share_context,
+ const int32_t* attrib_list,
+ gpu::Capabilities* capabilities,
+ base::SharedMemoryHandle* shared_state_handle,
+ gpu::CommandBufferId* command_buffer_id) {
PepperPluginInstanceImpl* plugin_instance =
HostGlobals::Get()->GetInstance(pp_instance());
if (!plugin_instance)
@@ -265,7 +199,7 @@ bool PPB_Graphics3D_Impl::InitRaw(
gfx::Size surface_size;
std::vector<int32_t> attribs;
gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
- // TODO(alokp): Change GpuChannelHost::CreateOffscreenCommandBuffer()
+ // TODO(alokp): Change GpuChannelHost::CreateCommandBuffer()
// interface to accept width and height in the attrib_list so that
// we do not need to filter for width and height here.
if (attrib_list) {
@@ -296,16 +230,17 @@ bool PPB_Graphics3D_Impl::InitRaw(
attribs.push_back(PP_GRAPHICS3DATTRIB_NONE);
}
- CommandBufferProxyImpl* share_buffer = NULL;
+ gpu::CommandBufferProxyImpl* share_buffer = NULL;
if (share_context) {
PPB_Graphics3D_Impl* share_graphics =
static_cast<PPB_Graphics3D_Impl*>(share_context);
share_buffer = share_graphics->GetCommandBufferProxy();
}
- command_buffer_ = channel_->CreateOffscreenCommandBuffer(
- surface_size, share_buffer, GpuChannelHost::kDefaultStreamId,
- GpuChannelHost::kDefaultStreamPriority, attribs, GURL::EmptyGURL(),
+ command_buffer_ = channel_->CreateCommandBuffer(
+ gpu::kNullSurfaceHandle, surface_size, share_buffer,
+ gpu::GpuChannelHost::kDefaultStreamId,
+ gpu::GpuChannelHost::kDefaultStreamPriority, attribs, GURL::EmptyGURL(),
gpu_preference);
if (!command_buffer_)
return false;
diff --git a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h
index e4dd1566e65..6dd34624f76 100644
--- a/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h
+++ b/chromium/content/renderer/pepper/ppb_graphics_3d_impl.h
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/memory/shared_memory.h"
#include "base/memory/weak_ptr.h"
+#include "gpu/command_buffer/common/command_buffer_id.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "ppapi/shared_impl/ppb_graphics_3d_shared.h"
@@ -17,24 +18,20 @@
namespace gpu {
struct Capabilities;
+class CommandBufferProxyImpl;
+class GpuChannelHost;
}
namespace content {
-class CommandBufferProxyImpl;
-class GpuChannelHost;
class PPB_Graphics3D_Impl : public ppapi::PPB_Graphics3D_Shared {
public:
- static PP_Resource Create(PP_Instance instance,
- PP_Resource share_context,
- const int32_t* attrib_list);
- static PP_Resource CreateRaw(
- PP_Instance instance,
- PP_Resource share_context,
- const int32_t* attrib_list,
- gpu::Capabilities* capabilities,
- base::SharedMemoryHandle* shared_state_handle,
- uint64_t* command_buffer_id);
+ static PP_Resource CreateRaw(PP_Instance instance,
+ PP_Resource share_context,
+ const int32_t* attrib_list,
+ gpu::Capabilities* capabilities,
+ base::SharedMemoryHandle* shared_state_handle,
+ gpu::CommandBufferId* command_buffer_id);
// PPB_Graphics3D_API trusted implementation.
PP_Bool SetGetBuffer(int32_t transfer_buffer_id) override;
@@ -46,9 +43,6 @@ class PPB_Graphics3D_Impl : public ppapi::PPB_Graphics3D_Shared {
int32_t end) override;
gpu::CommandBuffer::State WaitForGetOffsetInRange(int32_t start,
int32_t end) override;
- uint32_t InsertSyncPoint() override;
- uint32_t InsertFutureSyncPoint() override;
- void RetireSyncPoint(uint32_t) override;
void EnsureWorkVisible() override;
// Binds/unbinds the graphics of this context with the associated instance.
@@ -67,9 +61,9 @@ class PPB_Graphics3D_Impl : public ppapi::PPB_Graphics3D_Shared {
*sync_token = sync_token_;
}
- CommandBufferProxyImpl* GetCommandBufferProxy();
+ gpu::CommandBufferProxyImpl* GetCommandBufferProxy();
- GpuChannelHost* channel() { return channel_.get(); }
+ gpu::GpuChannelHost* channel() { return channel_.get(); }
protected:
~PPB_Graphics3D_Impl() override;
@@ -81,12 +75,11 @@ class PPB_Graphics3D_Impl : public ppapi::PPB_Graphics3D_Shared {
private:
explicit PPB_Graphics3D_Impl(PP_Instance instance);
- bool Init(PPB_Graphics3D_API* share_context, const int32_t* attrib_list);
bool InitRaw(PPB_Graphics3D_API* share_context,
const int32_t* attrib_list,
gpu::Capabilities* capabilities,
base::SharedMemoryHandle* shared_state_handle,
- uint64_t* command_buffer_id);
+ gpu::CommandBufferId* command_buffer_id);
// Notifications received from the GPU process.
void OnSwapBuffers();
@@ -103,8 +96,8 @@ class PPB_Graphics3D_Impl : public ppapi::PPB_Graphics3D_Shared {
gpu::Mailbox mailbox_;
gpu::SyncToken sync_token_;
bool has_alpha_;
- scoped_refptr<GpuChannelHost> channel_;
- scoped_ptr<CommandBufferProxyImpl> command_buffer_;
+ scoped_refptr<gpu::GpuChannelHost> channel_;
+ scoped_ptr<gpu::CommandBufferProxyImpl> command_buffer_;
base::WeakPtrFactory<PPB_Graphics3D_Impl> weak_ptr_factory_;
diff --git a/chromium/content/renderer/pepper/ppb_image_data_impl.cc b/chromium/content/renderer/pepper/ppb_image_data_impl.cc
index 56cc3731433..4756cfd4b93 100644
--- a/chromium/content/renderer/pepper/ppb_image_data_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_image_data_impl.cc
@@ -18,6 +18,7 @@
#include "ppapi/c/ppb_image_data.h"
#include "ppapi/thunk/thunk.h"
#include "skia/ext/platform_canvas.h"
+#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColorPriv.h"
#include "third_party/skia/include/core/SkDevice.h"
#include "third_party/skia/include/core/SkPixmap.h"
@@ -112,7 +113,7 @@ int32_t PPB_ImageData_Impl::GetSharedMemory(base::SharedMemory** shm,
return backend_->GetSharedMemory(shm, byte_count);
}
-skia::PlatformCanvas* PPB_ImageData_Impl::GetPlatformCanvas() {
+SkCanvas* PPB_ImageData_Impl::GetPlatformCanvas() {
return backend_->GetPlatformCanvas();
}
@@ -170,7 +171,8 @@ TransportDIB* ImageDataPlatformBackend::GetTransportDIB() const {
void* ImageDataPlatformBackend::Map() {
if (!mapped_canvas_) {
const bool is_opaque = false;
- mapped_canvas_.reset(dib_->GetPlatformCanvas(width_, height_, is_opaque));
+ mapped_canvas_ =
+ sk_sp<SkCanvas>(dib_->GetPlatformCanvas(width_, height_, is_opaque));
if (!mapped_canvas_)
return NULL;
}
@@ -197,7 +199,7 @@ int32_t ImageDataPlatformBackend::GetSharedMemory(base::SharedMemory** shm,
return PP_OK;
}
-skia::PlatformCanvas* ImageDataPlatformBackend::GetPlatformCanvas() {
+SkCanvas* ImageDataPlatformBackend::GetPlatformCanvas() {
return mapped_canvas_.get();
}
@@ -240,7 +242,7 @@ void* ImageDataSimpleBackend::Map() {
skia_bitmap_.setPixels(shared_memory_->memory());
// Our platform bitmaps are set to opaque by default, which we don't want.
skia_bitmap_.setAlphaType(kPremul_SkAlphaType);
- skia_canvas_.reset(new SkCanvas(skia_bitmap_));
+ skia_canvas_ = sk_make_sp<SkCanvas>(skia_bitmap_);
return skia_bitmap_.getAddr32(0, 0);
}
return shared_memory_->memory();
@@ -258,7 +260,7 @@ int32_t ImageDataSimpleBackend::GetSharedMemory(base::SharedMemory** shm,
return PP_OK;
}
-skia::PlatformCanvas* ImageDataSimpleBackend::GetPlatformCanvas() {
+SkCanvas* ImageDataSimpleBackend::GetPlatformCanvas() {
return NULL;
}
diff --git a/chromium/content/renderer/pepper/ppb_image_data_impl.h b/chromium/content/renderer/pepper/ppb_image_data_impl.h
index 3168f0dfa55..13a1e0cdf7b 100644
--- a/chromium/content/renderer/pepper/ppb_image_data_impl.h
+++ b/chromium/content/renderer/pepper/ppb_image_data_impl.h
@@ -144,7 +144,7 @@ class ImageDataPlatformBackend : public PPB_ImageData_Impl::Backend {
scoped_ptr<TransportDIB> dib_;
// When the device is mapped, this is the image. Null when umapped.
- scoped_ptr<SkCanvas> mapped_canvas_;
+ sk_sp<SkCanvas> mapped_canvas_;
DISALLOW_COPY_AND_ASSIGN(ImageDataPlatformBackend);
};
@@ -174,7 +174,7 @@ class ImageDataSimpleBackend : public PPB_ImageData_Impl::Backend {
scoped_ptr<base::SharedMemory> shared_memory_;
// skia_bitmap_ is backed by shared_memory_.
SkBitmap skia_bitmap_;
- scoped_ptr<SkCanvas> skia_canvas_;
+ sk_sp<SkCanvas> skia_canvas_;
uint32_t map_count_;
DISALLOW_COPY_AND_ASSIGN(ImageDataSimpleBackend);
diff --git a/chromium/content/renderer/pepper/ppb_video_decoder_impl.cc b/chromium/content/renderer/pepper/ppb_video_decoder_impl.cc
index fa9f49b559f..50c104bf10a 100644
--- a/chromium/content/renderer/pepper/ppb_video_decoder_impl.cc
+++ b/chromium/content/renderer/pepper/ppb_video_decoder_impl.cc
@@ -9,13 +9,14 @@
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "base/metrics/histogram.h"
-#include "content/common/gpu/client/command_buffer_proxy_impl.h"
#include "content/renderer/pepper/host_globals.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/plugin_module.h"
#include "content/renderer/pepper/ppb_buffer_impl.h"
#include "content/renderer/pepper/ppb_graphics_3d_impl.h"
#include "content/renderer/render_thread_impl.h"
+#include "gpu/ipc/client/command_buffer_proxy_impl.h"
+#include "media/gpu/ipc/client/gpu_video_decode_accelerator_host.h"
#include "media/video/picture.h"
#include "media/video/video_decode_accelerator.h"
#include "ppapi/c/dev/pp_video_dev.h"
@@ -118,7 +119,8 @@ bool PPB_VideoDecoder_Impl::Init(PP_Resource graphics_context,
PPB_Graphics3D_Impl* graphics_3d =
static_cast<PPB_Graphics3D_Impl*>(enter_context.object());
- CommandBufferProxyImpl* command_buffer = graphics_3d->GetCommandBufferProxy();
+ gpu::CommandBufferProxyImpl* command_buffer =
+ graphics_3d->GetCommandBufferProxy();
if (!command_buffer)
return false;
@@ -127,8 +129,13 @@ bool PPB_VideoDecoder_Impl::Init(PP_Resource graphics_context,
// This is not synchronous, but subsequent IPC messages will be buffered, so
// it is okay to immediately send IPC messages.
- decoder_ = command_buffer->CreateVideoDecoder();
- return (decoder_ && decoder_->Initialize(PPToMediaProfile(profile), this));
+ gpu::GpuChannelHost* channel = command_buffer->channel();
+ if (channel) {
+ decoder_.reset(
+ new media::GpuVideoDecodeAcceleratorHost(channel, command_buffer));
+ return decoder_->Initialize(PPToMediaProfile(profile), this);
+ }
+ return false;
}
const PPP_VideoDecoder_Dev* PPB_VideoDecoder_Impl::GetPPP() {
@@ -178,10 +185,10 @@ void PPB_VideoDecoder_Impl::AssignPictureBuffers(
for (uint32_t i = 0; i < no_of_buffers; i++) {
PP_PictureBuffer_Dev in_buf = buffers[i];
DCHECK_GE(in_buf.id, 0);
+ media::PictureBuffer::TextureIds ids;
+ ids.push_back(in_buf.texture_id);
media::PictureBuffer buffer(
- in_buf.id,
- gfx::Size(in_buf.size.width, in_buf.size.height),
- in_buf.texture_id);
+ in_buf.id, gfx::Size(in_buf.size.width, in_buf.size.height), ids);
wrapped_buffers.push_back(buffer);
UMA_HISTOGRAM_COUNTS_10000("Media.PepperVideoDecoderPictureHeight",
in_buf.size.height);
@@ -234,9 +241,11 @@ void PPB_VideoDecoder_Impl::Destroy() {
void PPB_VideoDecoder_Impl::ProvidePictureBuffers(
uint32_t requested_num_of_buffers,
+ uint32_t textures_per_buffer,
const gfx::Size& dimensions,
uint32_t texture_target) {
DCHECK(RenderThreadImpl::current());
+ DCHECK_EQ(1u, textures_per_buffer);
if (!GetPPP())
return;
@@ -275,9 +284,8 @@ void PPB_VideoDecoder_Impl::NotifyError(
PP_VideoDecodeError_Dev pp_error = MediaToPPError(error);
GetPPP()->NotifyError(pp_instance(), pp_resource(), pp_error);
- UMA_HISTOGRAM_ENUMERATION("Media.PepperVideoDecoderError",
- error,
- media::VideoDecodeAccelerator::LARGEST_ERROR_ENUM);
+ UMA_HISTOGRAM_ENUMERATION("Media.PepperVideoDecoderError", error,
+ media::VideoDecodeAccelerator::ERROR_MAX + 1);
}
void PPB_VideoDecoder_Impl::NotifyResetDone() {
diff --git a/chromium/content/renderer/pepper/ppb_video_decoder_impl.h b/chromium/content/renderer/pepper/ppb_video_decoder_impl.h
index b9f4d6ae9f2..ad64e370454 100644
--- a/chromium/content/renderer/pepper/ppb_video_decoder_impl.h
+++ b/chromium/content/renderer/pepper/ppb_video_decoder_impl.h
@@ -45,6 +45,7 @@ class PPB_VideoDecoder_Impl : public ppapi::PPB_VideoDecoder_Shared,
// media::VideoDecodeAccelerator::Client implementation.
void ProvidePictureBuffers(uint32_t requested_num_of_buffers,
+ uint32_t textures_per_buffer,
const gfx::Size& dimensions,
uint32_t texture_target) override;
void DismissPictureBuffer(int32_t picture_buffer_id) override;
diff --git a/chromium/content/renderer/pepper/resource_converter.cc b/chromium/content/renderer/pepper/resource_converter.cc
index 7e66b71ebc9..741e6c62f0c 100644
--- a/chromium/content/renderer/pepper/resource_converter.cc
+++ b/chromium/content/renderer/pepper/resource_converter.cc
@@ -170,7 +170,7 @@ bool DOMMediaStreamTrackToResource(
const blink::WebMediaStreamTrack track = dom_media_stream_track.component();
const std::string id = track.source().id().utf8();
- if (track.source().type() == blink::WebMediaStreamSource::TypeVideo) {
+ if (track.source().getType() == blink::WebMediaStreamSource::TypeVideo) {
*pending_renderer_id = host->GetPpapiHost()->AddPendingResourceHost(
scoped_ptr<ppapi::host::ResourceHost>(
new PepperMediaStreamVideoTrackHost(host, instance, 0, track)));
@@ -180,7 +180,8 @@ bool DOMMediaStreamTrackToResource(
create_message->reset(
new PpapiPluginMsg_MediaStreamVideoTrack_CreateFromPendingHost(id));
return true;
- } else if (track.source().type() == blink::WebMediaStreamSource::TypeAudio) {
+ } else if (track.source().getType() ==
+ blink::WebMediaStreamSource::TypeAudio) {
*pending_renderer_id = host->GetPpapiHost()->AddPendingResourceHost(
scoped_ptr<ppapi::host::ResourceHost>(
new PepperMediaStreamAudioTrackHost(host, instance, 0, track)));
diff --git a/chromium/content/renderer/pepper/resource_creation_impl.cc b/chromium/content/renderer/pepper/resource_creation_impl.cc
index c76d0b1973c..25fd86ecf3f 100644
--- a/chromium/content/renderer/pepper/resource_creation_impl.cc
+++ b/chromium/content/renderer/pepper/resource_creation_impl.cc
@@ -115,7 +115,7 @@ PP_Resource ResourceCreationImpl::CreateFlashMessageLoop(PP_Instance instance) {
PP_Resource ResourceCreationImpl::CreateGraphics3D(PP_Instance instance,
PP_Resource share_context,
const int32_t* attrib_list) {
- return PPB_Graphics3D_Impl::Create(instance, share_context, attrib_list);
+ return 0; // Not supported in-process.
}
PP_Resource ResourceCreationImpl::CreateGraphics3DRaw(
@@ -124,7 +124,7 @@ PP_Resource ResourceCreationImpl::CreateGraphics3DRaw(
const int32_t* attrib_list,
gpu::Capabilities* capabilities,
base::SharedMemoryHandle* shared_state,
- uint64_t* command_buffer_id) {
+ gpu::CommandBufferId* command_buffer_id) {
return PPB_Graphics3D_Impl::CreateRaw(instance, share_context, attrib_list,
capabilities, shared_state,
command_buffer_id);
diff --git a/chromium/content/renderer/pepper/resource_creation_impl.h b/chromium/content/renderer/pepper/resource_creation_impl.h
index 3e44ceefc92..b40d17dcc09 100644
--- a/chromium/content/renderer/pepper/resource_creation_impl.h
+++ b/chromium/content/renderer/pepper/resource_creation_impl.h
@@ -60,7 +60,7 @@ class ResourceCreationImpl : public ppapi::thunk::ResourceCreationAPI {
const int32_t* attrib_list,
gpu::Capabilities* capabilities,
base::SharedMemoryHandle* shared_state,
- uint64_t* command_buffer_id) override;
+ gpu::CommandBufferId* command_buffer_id) override;
PP_Resource CreateHostResolver(PP_Instance instance) override;
PP_Resource CreateHostResolverPrivate(PP_Instance instance) override;
PP_Resource CreateImageData(PP_Instance instance,
diff --git a/chromium/content/renderer/pepper/url_response_info_util.cc b/chromium/content/renderer/pepper/url_response_info_util.cc
index d657800330f..12d05e5b5f2 100644
--- a/chromium/content/renderer/pepper/url_response_info_util.cc
+++ b/chromium/content/renderer/pepper/url_response_info_util.cc
@@ -17,7 +17,7 @@
#include "ipc/ipc_message.h"
#include "ppapi/proxy/ppapi_messages.h"
#include "ppapi/shared_impl/url_response_info_data.h"
-#include "third_party/WebKit/public/platform/WebCString.h"
+#include "third_party/WebKit/public/platform/FilePathConversion.h"
#include "third_party/WebKit/public/platform/WebHTTPHeaderVisitor.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h"
@@ -91,7 +91,7 @@ void DataFromWebURLResponse(RendererPpapiHostImpl* host_impl,
WebString file_path = response.downloadFilePath();
if (!file_path.isEmpty()) {
- base::FilePath external_path = base::FilePath::FromUTF16Unsafe(file_path);
+ base::FilePath external_path = blink::WebStringToFilePath(file_path);
// TODO(teravest): Write a utility function to create resource hosts in the
// renderer and browser.
PepperFileRefRendererHost* renderer_host =
diff --git a/chromium/content/renderer/pepper/v8_var_converter.h b/chromium/content/renderer/pepper/v8_var_converter.h
index 4a65bea684b..998939b0ccf 100644
--- a/chromium/content/renderer/pepper/v8_var_converter.h
+++ b/chromium/content/renderer/pepper/v8_var_converter.h
@@ -8,6 +8,7 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "content/common/content_export.h"
#include "ppapi/c/pp_instance.h"
#include "ppapi/c/pp_var.h"
diff --git a/chromium/content/renderer/pepper/v8_var_converter_unittest.cc b/chromium/content/renderer/pepper/v8_var_converter_unittest.cc
index cd07abb4c3f..283aad61ab2 100644
--- a/chromium/content/renderer/pepper/v8_var_converter_unittest.cc
+++ b/chromium/content/renderer/pepper/v8_var_converter_unittest.cc
@@ -403,6 +403,8 @@ TEST_F(V8VarConverterTest, StrangeDictionaryKeyTest) {
v8::Local<v8::Context> context =
v8::Local<v8::Context>::New(isolate_, context_);
v8::Context::Scope context_scope(context);
+ v8::MicrotasksScope microtasks(
+ isolate_, v8::MicrotasksScope::kDoNotRunMicrotasks);
const char* source =
"(function() {"
diff --git a/chromium/content/renderer/pepper/video_decoder_shim.cc b/chromium/content/renderer/pepper/video_decoder_shim.cc
index a529b747094..25a6fc139e1 100644
--- a/chromium/content/renderer/pepper/video_decoder_shim.cc
+++ b/chromium/content/renderer/pepper/video_decoder_shim.cc
@@ -650,7 +650,7 @@ class VideoDecoderShim::DecoderImpl {
private:
void OnInitDone(bool success);
void DoDecode();
- void OnDecodeComplete(media::VideoDecoder::Status status);
+ void OnDecodeComplete(media::DecodeStatus status);
void OnOutputComplete(const scoped_refptr<media::VideoFrame>& frame);
void OnResetComplete();
@@ -710,7 +710,7 @@ void VideoDecoderShim::DecoderImpl::Initialize(
DCHECK_EQ(decoder_->GetMaxDecodeRequests(), 1);
decoder_->Initialize(
- config, true /* low_delay */, media::SetCdmReadyCB(),
+ config, true /* low_delay */, nullptr,
base::Bind(&VideoDecoderShim::DecoderImpl::OnInitDone,
weak_ptr_factory_.GetWeakPtr()),
base::Bind(&VideoDecoderShim::DecoderImpl::OnOutputComplete,
@@ -732,8 +732,8 @@ void VideoDecoderShim::DecoderImpl::Reset() {
const PendingDecode& decode = pending_decodes_.front();
scoped_ptr<PendingFrame> pending_frame(new PendingFrame(decode.decode_id));
main_task_runner_->PostTask(
- FROM_HERE, base::Bind(&VideoDecoderShim::OnDecodeComplete, shim_,
- media::VideoDecoder::kAborted, decode.decode_id));
+ FROM_HERE, base::Bind(&VideoDecoderShim::OnDecodeComplete, shim_, PP_OK,
+ decode.decode_id));
pending_decodes_.pop();
}
// Don't need to call Reset() if the |decoder_| hasn't been initialized.
@@ -781,23 +781,19 @@ void VideoDecoderShim::DecoderImpl::DoDecode() {
}
void VideoDecoderShim::DecoderImpl::OnDecodeComplete(
- media::VideoDecoder::Status status) {
+ media::DecodeStatus status) {
DCHECK(awaiting_decoder_);
awaiting_decoder_ = false;
int32_t result;
switch (status) {
- case media::VideoDecoder::kOk:
- case media::VideoDecoder::kAborted:
+ case media::DecodeStatus::OK:
+ case media::DecodeStatus::ABORTED:
result = PP_OK;
break;
- case media::VideoDecoder::kDecodeError:
+ case media::DecodeStatus::DECODE_ERROR:
result = PP_ERROR_RESOURCE_FAILED;
break;
- default:
- NOTREACHED();
- result = PP_ERROR_FAILED;
- break;
}
main_task_runner_->PostTask(
@@ -899,7 +895,7 @@ bool VideoDecoderShim::Initialize(const Config& vda_config, Client* client) {
gfx::Size(32, 24), // Small sizes that won't fail.
gfx::Rect(32, 24), gfx::Size(32, 24),
// TODO(bbudge): Verify extra data isn't needed.
- media::EmptyExtraData(), false /* decryption */);
+ media::EmptyExtraData(), media::Unencrypted());
media_task_runner_->PostTask(
FROM_HERE,
@@ -944,10 +940,11 @@ void VideoDecoderShim::AssignPictureBuffers(
std::vector<uint32_t> local_texture_ids(num_textures);
gpu::gles2::GLES2Interface* gles2 = context_provider_->ContextGL();
for (uint32_t i = 0; i < num_textures; i++) {
+ DCHECK_EQ(1u, buffers[i].texture_ids().size());
local_texture_ids[i] = gles2->CreateAndConsumeTextureCHROMIUM(
GL_TEXTURE_2D, pending_texture_mailboxes_[i].name);
// Map the plugin texture id to the local texture id.
- uint32_t plugin_texture_id = buffers[i].texture_id();
+ uint32_t plugin_texture_id = buffers[i].texture_ids()[0];
texture_id_map_[plugin_texture_id] = local_texture_ids[i];
available_textures_.insert(plugin_texture_id);
}
diff --git a/chromium/content/renderer/pepper/video_encoder_shim.cc b/chromium/content/renderer/pepper/video_encoder_shim.cc
index 55d640a359a..c19e4b1b3a2 100644
--- a/chromium/content/renderer/pepper/video_encoder_shim.cc
+++ b/chromium/content/renderer/pepper/video_encoder_shim.cc
@@ -16,8 +16,8 @@
#include "base/thread_task_runner_handle.h"
#include "content/renderer/pepper/pepper_video_encoder_host.h"
#include "content/renderer/render_thread_impl.h"
-#include "third_party/libvpx_new/source/libvpx/vpx/vp8cx.h"
-#include "third_party/libvpx_new/source/libvpx/vpx/vpx_encoder.h"
+#include "third_party/libvpx/source/libvpx/vpx/vp8cx.h"
+#include "third_party/libvpx/source/libvpx/vpx/vpx_encoder.h"
#include "ui/gfx/geometry/size.h"
namespace content {
@@ -74,7 +74,9 @@ void GetVpxCodecParameters(media::VideoCodecProfile codec,
*max_quantizer = kVp8DefaultMaxQuantizer;
*cpu_used = kVp8DefaultCpuUsed;
break;
- case media::VP9PROFILE_ANY:
+ // Only VP9 profile 0 is supported by PPAPI at the moment. VP9 profiles 1-3
+ // are not supported due to backward compatibility.
+ case media::VP9PROFILE_PROFILE0:
*vpx_codec = vpx_codec_vp9_cx();
*min_quantizer = kVp9DefaultMinQuantizer;
*max_quantizer = kVp9DefaultMaxQuantizer;
@@ -165,6 +167,12 @@ void VideoEncoderShim::EncoderImpl::Initialize(
gfx::Size coded_size =
media::VideoFrame::PlaneSize(input_format, 0, input_visible_size);
+ // Only VP9 profile 0 is supported by PPAPI at the moment. VP9 profiles 1-3
+ // are not supported due to backward compatibility.
+ DCHECK_NE(output_profile, media::VP9PROFILE_PROFILE1);
+ DCHECK_NE(output_profile, media::VP9PROFILE_PROFILE2);
+ DCHECK_NE(output_profile, media::VP9PROFILE_PROFILE3);
+
vpx_codec_iface_t* vpx_codec;
int32_t min_quantizer, max_quantizer, cpu_used;
GetVpxCodecParameters(output_profile, &vpx_codec, &min_quantizer,
@@ -196,7 +204,7 @@ void VideoEncoderShim::EncoderImpl::Initialize(
// Use Q/CQ mode if no target bitrate is given. Note that in the VP8/CQ case
// the meaning of rc_target_bitrate changes to target maximum rate.
if (initial_bitrate == 0) {
- if (output_profile == media::VP9PROFILE_ANY) {
+ if (output_profile == media::VP9PROFILE_PROFILE0) {
config_.rc_end_usage = VPX_Q;
} else if (output_profile == media::VP8PROFILE_ANY) {
config_.rc_end_usage = VPX_CQ;
@@ -223,7 +231,7 @@ void VideoEncoderShim::EncoderImpl::Initialize(
return;
}
- if (output_profile == media::VP9PROFILE_ANY) {
+ if (output_profile == media::VP9PROFILE_PROFILE0) {
if (vpx_codec_control(&encoder_, VP9E_SET_AQ_MODE,
kVp9AqModeCyclicRefresh) != VPX_CODEC_OK) {
NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError);
@@ -389,10 +397,10 @@ VideoEncoderShim::GetSupportedProfiles() {
ret = vpx_codec_enc_config_default(vpx_codec_vp9_cx(), &config, 0);
if (ret == VPX_CODEC_OK) {
media::VideoEncodeAccelerator::SupportedProfile profile;
- profile.profile = media::VP9PROFILE_ANY;
profile.max_resolution = gfx::Size(kMaxWidth, kMaxHeight);
profile.max_framerate_numerator = config.g_timebase.den;
profile.max_framerate_denominator = config.g_timebase.num;
+ profile.profile = media::VP9PROFILE_PROFILE0;
profiles.push_back(profile);
}
@@ -412,7 +420,7 @@ bool VideoEncoderShim::Initialize(
return false;
if (output_profile != media::VP8PROFILE_ANY &&
- output_profile != media::VP9PROFILE_ANY)
+ output_profile != media::VP9PROFILE_PROFILE0)
return false;
media_task_runner_->PostTask(
diff --git a/chromium/content/renderer/presentation/presentation_connection_client.cc b/chromium/content/renderer/presentation/presentation_connection_client.cc
index bd3419fd1ee..31083f01181 100644
--- a/chromium/content/renderer/presentation/presentation_connection_client.cc
+++ b/chromium/content/renderer/presentation/presentation_connection_client.cc
@@ -10,10 +10,9 @@
namespace content {
PresentationConnectionClient::PresentationConnectionClient(
- presentation::PresentationSessionInfoPtr session_info)
+ mojom::PresentationSessionInfoPtr session_info)
: url_(blink::WebString::fromUTF8(session_info->url)),
- id_(blink::WebString::fromUTF8(session_info->id)) {
-}
+ id_(blink::WebString::fromUTF8(session_info->id)) {}
PresentationConnectionClient::PresentationConnectionClient(
const mojo::String& url,
diff --git a/chromium/content/renderer/presentation/presentation_connection_client.h b/chromium/content/renderer/presentation/presentation_connection_client.h
index 4e8a591e399..42ffc61c35b 100644
--- a/chromium/content/renderer/presentation/presentation_connection_client.h
+++ b/chromium/content/renderer/presentation/presentation_connection_client.h
@@ -18,7 +18,7 @@ class CONTENT_EXPORT PresentationConnectionClient
: public NON_EXPORTED_BASE(blink::WebPresentationConnectionClient) {
public:
explicit PresentationConnectionClient(
- presentation::PresentationSessionInfoPtr session_info);
+ mojom::PresentationSessionInfoPtr session_info);
explicit PresentationConnectionClient(const mojo::String& url,
const mojo::String& id);
~PresentationConnectionClient() override;
diff --git a/chromium/content/renderer/presentation/presentation_dispatcher.cc b/chromium/content/renderer/presentation/presentation_dispatcher.cc
index bfe9a49aed5..6536f86324a 100644
--- a/chromium/content/renderer/presentation/presentation_dispatcher.cc
+++ b/chromium/content/renderer/presentation/presentation_dispatcher.cc
@@ -9,6 +9,7 @@
#include <vector>
#include "base/logging.h"
+#include "base/memory/ptr_util.h"
#include "content/common/presentation/presentation_service.mojom.h"
#include "content/public/common/presentation_constants.h"
#include "content/public/common/service_registry.h"
@@ -25,29 +26,29 @@
namespace {
blink::WebPresentationError::ErrorType GetWebPresentationErrorTypeFromMojo(
- presentation::PresentationErrorType mojoErrorType) {
+ content::mojom::PresentationErrorType mojoErrorType) {
switch (mojoErrorType) {
- case presentation::PRESENTATION_ERROR_TYPE_NO_AVAILABLE_SCREENS:
+ case content::mojom::PresentationErrorType::NO_AVAILABLE_SCREENS:
return blink::WebPresentationError::ErrorTypeNoAvailableScreens;
- case presentation::PRESENTATION_ERROR_TYPE_SESSION_REQUEST_CANCELLED:
+ case content::mojom::PresentationErrorType::SESSION_REQUEST_CANCELLED:
return blink::WebPresentationError::ErrorTypeSessionRequestCancelled;
- case presentation::PRESENTATION_ERROR_TYPE_NO_PRESENTATION_FOUND:
+ case content::mojom::PresentationErrorType::NO_PRESENTATION_FOUND:
return blink::WebPresentationError::ErrorTypeNoPresentationFound;
- case presentation::PRESENTATION_ERROR_TYPE_UNKNOWN:
+ case content::mojom::PresentationErrorType::UNKNOWN:
default:
return blink::WebPresentationError::ErrorTypeUnknown;
}
}
blink::WebPresentationConnectionState GetWebPresentationConnectionStateFromMojo(
- presentation::PresentationConnectionState mojoSessionState) {
+ content::mojom::PresentationConnectionState mojoSessionState) {
switch (mojoSessionState) {
// TODO(imcheng): Add Connecting state to Blink (crbug.com/575351).
- case presentation::PRESENTATION_CONNECTION_STATE_CONNECTED:
+ case content::mojom::PresentationConnectionState::CONNECTED:
return blink::WebPresentationConnectionState::Connected;
- case presentation::PRESENTATION_CONNECTION_STATE_CLOSED:
+ case content::mojom::PresentationConnectionState::CLOSED:
return blink::WebPresentationConnectionState::Closed;
- case presentation::PRESENTATION_CONNECTION_STATE_TERMINATED:
+ case content::mojom::PresentationConnectionState::TERMINATED:
return blink::WebPresentationConnectionState::Terminated;
default:
NOTREACHED();
@@ -55,6 +56,23 @@ blink::WebPresentationConnectionState GetWebPresentationConnectionStateFromMojo(
}
}
+blink::WebPresentationConnectionCloseReason
+GetWebPresentationConnectionCloseReasonFromMojo(
+ content::mojom::PresentationConnectionCloseReason
+ mojoConnectionCloseReason) {
+ switch (mojoConnectionCloseReason) {
+ case content::mojom::PresentationConnectionCloseReason::CONNECTION_ERROR:
+ return blink::WebPresentationConnectionCloseReason::Error;
+ case content::mojom::PresentationConnectionCloseReason::CLOSED:
+ return blink::WebPresentationConnectionCloseReason::Closed;
+ case content::mojom::PresentationConnectionCloseReason::WENT_AWAY:
+ return blink::WebPresentationConnectionCloseReason::WentAway;
+ default:
+ NOTREACHED();
+ return blink::WebPresentationConnectionCloseReason::Error;
+ }
+}
+
} // namespace
namespace content {
@@ -146,11 +164,9 @@ void PresentationDispatcher::sendArrayBuffer(
return;
}
- message_request_queue_.push(make_scoped_ptr(
- CreateSendBinaryMessageRequest(presentationUrl, presentationId,
- presentation::PresentationMessageType::
- PRESENTATION_MESSAGE_TYPE_ARRAY_BUFFER,
- data, length)));
+ message_request_queue_.push(make_scoped_ptr(CreateSendBinaryMessageRequest(
+ presentationUrl, presentationId,
+ mojom::PresentationMessageType::ARRAY_BUFFER, data, length)));
// Start processing request if only one in the queue.
if (message_request_queue_.size() == 1)
DoSendMessage(message_request_queue_.front().get());
@@ -169,8 +185,7 @@ void PresentationDispatcher::sendBlobData(
}
message_request_queue_.push(make_scoped_ptr(CreateSendBinaryMessageRequest(
- presentationUrl, presentationId,
- presentation::PresentationMessageType::PRESENTATION_MESSAGE_TYPE_BLOB,
+ presentationUrl, presentationId, mojom::PresentationMessageType::BLOB,
data, length)));
// Start processing request if only one in the queue.
if (message_request_queue_.size() == 1)
@@ -343,7 +358,7 @@ void PresentationDispatcher::OnScreenAvailabilityNotSupported(
}
void PresentationDispatcher::OnDefaultSessionStarted(
- presentation::PresentationSessionInfoPtr session_info) {
+ mojom::PresentationSessionInfoPtr session_info) {
if (!controller_)
return;
@@ -356,8 +371,8 @@ void PresentationDispatcher::OnDefaultSessionStarted(
void PresentationDispatcher::OnSessionCreated(
blink::WebPresentationConnectionClientCallbacks* callback,
- presentation::PresentationSessionInfoPtr session_info,
- presentation::PresentationErrorPtr error) {
+ mojom::PresentationSessionInfoPtr session_info,
+ mojom::PresentationErrorPtr error) {
DCHECK(callback);
if (!error.is_null()) {
DCHECK(session_info.is_null());
@@ -369,13 +384,13 @@ void PresentationDispatcher::OnSessionCreated(
DCHECK(!session_info.is_null());
presentation_service_->ListenForSessionMessages(session_info.Clone());
- callback->onSuccess(blink::adoptWebPtr(
+ callback->onSuccess(base::WrapUnique(
new PresentationConnectionClient(std::move(session_info))));
}
void PresentationDispatcher::OnConnectionStateChanged(
- presentation::PresentationSessionInfoPtr connection,
- presentation::PresentationConnectionState state) {
+ mojom::PresentationSessionInfoPtr connection,
+ mojom::PresentationConnectionState state) {
if (!controller_)
return;
@@ -385,9 +400,23 @@ void PresentationDispatcher::OnConnectionStateChanged(
GetWebPresentationConnectionStateFromMojo(state));
}
+void PresentationDispatcher::OnConnectionClosed(
+ mojom::PresentationSessionInfoPtr connection,
+ mojom::PresentationConnectionCloseReason reason,
+ const mojo::String& message) {
+ if (!controller_)
+ return;
+
+ DCHECK(!connection.is_null());
+ controller_->didCloseConnection(
+ new PresentationConnectionClient(std::move(connection)),
+ GetWebPresentationConnectionCloseReasonFromMojo(reason),
+ blink::WebString::fromUTF8(message));
+}
+
void PresentationDispatcher::OnSessionMessagesReceived(
- presentation::PresentationSessionInfoPtr session_info,
- mojo::Array<presentation::SessionMessagePtr> messages) {
+ mojom::PresentationSessionInfoPtr session_info,
+ mojo::Array<mojom::SessionMessagePtr> messages) {
if (!controller_)
return;
@@ -397,17 +426,14 @@ void PresentationDispatcher::OnSessionMessagesReceived(
scoped_ptr<PresentationConnectionClient> session_client(
new PresentationConnectionClient(session_info->url, session_info->id));
switch (messages[i]->type) {
- case presentation::PresentationMessageType::
- PRESENTATION_MESSAGE_TYPE_TEXT: {
+ case mojom::PresentationMessageType::TEXT: {
controller_->didReceiveSessionTextMessage(
session_client.release(),
blink::WebString::fromUTF8(messages[i]->message));
break;
}
- case presentation::PresentationMessageType::
- PRESENTATION_MESSAGE_TYPE_ARRAY_BUFFER:
- case presentation::PresentationMessageType::
- PRESENTATION_MESSAGE_TYPE_BLOB: {
+ case mojom::PresentationMessageType::ARRAY_BUFFER:
+ case mojom::PresentationMessageType::BLOB: {
controller_->didReceiveSessionBinaryMessage(
session_client.release(), &(messages[i]->data.front()),
messages[i]->data.size());
@@ -427,9 +453,7 @@ void PresentationDispatcher::ConnectToPresentationServiceIfNeeded() {
render_frame()->GetServiceRegistry()->ConnectToRemoteService(
mojo::GetProxy(&presentation_service_));
- presentation::PresentationServiceClientPtr client_ptr;
- binding_.Bind(GetProxy(&client_ptr));
- presentation_service_->SetClient(std::move(client_ptr));
+ presentation_service_->SetClient(binding_.CreateInterfacePtrAndBind());
}
void PresentationDispatcher::UpdateListeningState(AvailabilityStatus* status) {
@@ -451,8 +475,8 @@ void PresentationDispatcher::UpdateListeningState(AvailabilityStatus* status) {
}
PresentationDispatcher::SendMessageRequest::SendMessageRequest(
- presentation::PresentationSessionInfoPtr session_info,
- presentation::SessionMessagePtr message)
+ mojom::PresentationSessionInfoPtr session_info,
+ mojom::SessionMessagePtr message)
: session_info(std::move(session_info)), message(std::move(message)) {}
PresentationDispatcher::SendMessageRequest::~SendMessageRequest() {}
@@ -463,15 +487,13 @@ PresentationDispatcher::CreateSendTextMessageRequest(
const blink::WebString& presentationUrl,
const blink::WebString& presentationId,
const blink::WebString& message) {
- presentation::PresentationSessionInfoPtr session_info =
- presentation::PresentationSessionInfo::New();
+ mojom::PresentationSessionInfoPtr session_info =
+ mojom::PresentationSessionInfo::New();
session_info->url = presentationUrl.utf8();
session_info->id = presentationId.utf8();
- presentation::SessionMessagePtr session_message =
- presentation::SessionMessage::New();
- session_message->type =
- presentation::PresentationMessageType::PRESENTATION_MESSAGE_TYPE_TEXT;
+ mojom::SessionMessagePtr session_message = mojom::SessionMessage::New();
+ session_message->type = mojom::PresentationMessageType::TEXT;
session_message->message = message.utf8();
return new SendMessageRequest(std::move(session_info),
std::move(session_message));
@@ -482,16 +504,15 @@ PresentationDispatcher::SendMessageRequest*
PresentationDispatcher::CreateSendBinaryMessageRequest(
const blink::WebString& presentationUrl,
const blink::WebString& presentationId,
- presentation::PresentationMessageType type,
+ mojom::PresentationMessageType type,
const uint8_t* data,
size_t length) {
- presentation::PresentationSessionInfoPtr session_info =
- presentation::PresentationSessionInfo::New();
+ mojom::PresentationSessionInfoPtr session_info =
+ mojom::PresentationSessionInfo::New();
session_info->url = presentationUrl.utf8();
session_info->id = presentationId.utf8();
- presentation::SessionMessagePtr session_message =
- presentation::SessionMessage::New();
+ mojom::SessionMessagePtr session_message = mojom::SessionMessage::New();
session_message->type = type;
std::vector<uint8_t> tmp_data_vector(data, data + length);
session_message->data.Swap(&tmp_data_vector);
diff --git a/chromium/content/renderer/presentation/presentation_dispatcher.h b/chromium/content/renderer/presentation/presentation_dispatcher.h
index ad0954951c8..3688fa4e4a6 100644
--- a/chromium/content/renderer/presentation/presentation_dispatcher.h
+++ b/chromium/content/renderer/presentation/presentation_dispatcher.h
@@ -33,19 +33,19 @@ namespace content {
class CONTENT_EXPORT PresentationDispatcher
: public RenderFrameObserver,
public NON_EXPORTED_BASE(blink::WebPresentationClient),
- public NON_EXPORTED_BASE(presentation::PresentationServiceClient) {
+ public NON_EXPORTED_BASE(mojom::PresentationServiceClient) {
public:
explicit PresentationDispatcher(RenderFrame* render_frame);
~PresentationDispatcher() override;
private:
struct SendMessageRequest {
- SendMessageRequest(presentation::PresentationSessionInfoPtr session_info,
- presentation::SessionMessagePtr message);
+ SendMessageRequest(mojom::PresentationSessionInfoPtr session_info,
+ mojom::SessionMessagePtr message);
~SendMessageRequest();
- presentation::PresentationSessionInfoPtr session_info;
- presentation::SessionMessagePtr message;
+ mojom::PresentationSessionInfoPtr session_info;
+ mojom::SessionMessagePtr message;
};
static SendMessageRequest* CreateSendTextMessageRequest(
@@ -55,7 +55,7 @@ class CONTENT_EXPORT PresentationDispatcher
static SendMessageRequest* CreateSendBinaryMessageRequest(
const blink::WebString& presentationUrl,
const blink::WebString& presentationId,
- presentation::PresentationMessageType type,
+ mojom::PresentationMessageType type,
const uint8_t* data,
size_t length);
@@ -95,23 +95,26 @@ class CONTENT_EXPORT PresentationDispatcher
bool is_new_navigation,
bool is_same_page_navigation) override;
- // presentation::PresentationServiceClient
+ // mojom::PresentationServiceClient
void OnScreenAvailabilityNotSupported(const mojo::String& url) override;
void OnScreenAvailabilityUpdated(const mojo::String& url,
bool available) override;
void OnConnectionStateChanged(
- presentation::PresentationSessionInfoPtr connection,
- presentation::PresentationConnectionState state) override;
+ mojom::PresentationSessionInfoPtr connection,
+ mojom::PresentationConnectionState state) override;
+ void OnConnectionClosed(mojom::PresentationSessionInfoPtr connection,
+ mojom::PresentationConnectionCloseReason reason,
+ const mojo::String& message) override;
void OnSessionMessagesReceived(
- presentation::PresentationSessionInfoPtr session_info,
- mojo::Array<presentation::SessionMessagePtr> messages) override;
+ mojom::PresentationSessionInfoPtr session_info,
+ mojo::Array<mojom::SessionMessagePtr> messages) override;
void OnDefaultSessionStarted(
- presentation::PresentationSessionInfoPtr session_info) override;
+ mojom::PresentationSessionInfoPtr session_info) override;
void OnSessionCreated(
blink::WebPresentationConnectionClientCallbacks* callback,
- presentation::PresentationSessionInfoPtr session_info,
- presentation::PresentationErrorPtr error);
+ mojom::PresentationSessionInfoPtr session_info,
+ mojom::PresentationErrorPtr error);
// Call to PresentationService to send the message in |request|.
// |session_info| and |message| of |reuqest| will be consumed.
@@ -125,8 +128,8 @@ class CONTENT_EXPORT PresentationDispatcher
// Used as a weak reference. Can be null since lifetime is bound to the frame.
blink::WebPresentationController* controller_;
- presentation::PresentationServicePtr presentation_service_;
- mojo::Binding<presentation::PresentationServiceClient> binding_;
+ mojom::PresentationServicePtr presentation_service_;
+ mojo::Binding<mojom::PresentationServiceClient> binding_;
// Message requests are queued here and only one message at a time is sent
// over mojo channel.
diff --git a/chromium/content/renderer/push_messaging/push_messaging_dispatcher.cc b/chromium/content/renderer/push_messaging/push_messaging_dispatcher.cc
index d10704326e5..1cfc044fb31 100644
--- a/chromium/content/renderer/push_messaging/push_messaging_dispatcher.cc
+++ b/chromium/content/renderer/push_messaging/push_messaging_dispatcher.cc
@@ -4,6 +4,7 @@
#include "content/renderer/push_messaging/push_messaging_dispatcher.h"
+#include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/child/service_worker/web_service_worker_registration_impl.h"
#include "content/common/push_messaging_messages.h"
@@ -44,46 +45,65 @@ void PushMessagingDispatcher::subscribe(
blink::WebPushSubscriptionCallbacks* callbacks) {
DCHECK(service_worker_registration);
DCHECK(callbacks);
- RenderFrameImpl::FromRoutingID(routing_id())
- ->manifest_manager()
- ->GetManifest(base::Bind(
- &PushMessagingDispatcher::DoSubscribe, base::Unretained(this),
- service_worker_registration, options, callbacks));
+ // If a developer provided an application server key in |options|, skip
+ // fetching the manifest.
+ if (options.applicationServerKey.isEmpty()) {
+ RenderFrameImpl::FromRoutingID(routing_id())
+ ->manifest_manager()
+ ->GetManifest(base::Bind(
+ &PushMessagingDispatcher::DidGetManifest, base::Unretained(this),
+ service_worker_registration, options, callbacks));
+ } else {
+ PushSubscriptionOptions content_options;
+ content_options.user_visible_only = options.userVisibleOnly;
+ // Just treat the server key as a string of bytes and pass it to the push
+ // service.
+ content_options.sender_info = options.applicationServerKey.latin1();
+ DoSubscribe(service_worker_registration, content_options, callbacks);
+ }
}
-void PushMessagingDispatcher::DoSubscribe(
+void PushMessagingDispatcher::DidGetManifest(
blink::WebServiceWorkerRegistration* service_worker_registration,
const blink::WebPushSubscriptionOptions& options,
blink::WebPushSubscriptionCallbacks* callbacks,
const Manifest& manifest) {
- int request_id = subscription_callbacks_.Add(callbacks);
- int64_t service_worker_registration_id =
- static_cast<WebServiceWorkerRegistrationImpl*>(
- service_worker_registration)
- ->registration_id();
-
+ // Get the sender_info from the manifest since it wasn't provided by
+ // the caller.
if (manifest.IsEmpty()) {
+ int request_id = subscription_callbacks_.Add(callbacks);
OnSubscribeFromDocumentError(
request_id, PUSH_REGISTRATION_STATUS_MANIFEST_EMPTY_OR_MISSING);
return;
}
- std::string sender_id =
- manifest.gcm_sender_id.is_null()
- ? std::string()
- : base::UTF16ToUTF8(manifest.gcm_sender_id.string());
- if (sender_id.empty()) {
+ PushSubscriptionOptions content_options;
+ content_options.user_visible_only = options.userVisibleOnly;
+ if (!manifest.gcm_sender_id.is_null()) {
+ content_options.sender_info =
+ base::UTF16ToUTF8(manifest.gcm_sender_id.string());
+ }
+
+ DoSubscribe(service_worker_registration, content_options, callbacks);
+}
+
+void PushMessagingDispatcher::DoSubscribe(
+ blink::WebServiceWorkerRegistration* service_worker_registration,
+ const PushSubscriptionOptions& options,
+ blink::WebPushSubscriptionCallbacks* callbacks) {
+ int request_id = subscription_callbacks_.Add(callbacks);
+ int64_t service_worker_registration_id =
+ static_cast<WebServiceWorkerRegistrationImpl*>(
+ service_worker_registration)
+ ->registration_id();
+
+ if (options.sender_info.empty()) {
OnSubscribeFromDocumentError(request_id,
PUSH_REGISTRATION_STATUS_NO_SENDER_ID);
return;
}
-
Send(new PushMessagingHostMsg_SubscribeFromDocument(
- routing_id(), request_id,
- manifest.gcm_sender_id.is_null()
- ? std::string()
- : base::UTF16ToUTF8(manifest.gcm_sender_id.string()),
- options.userVisibleOnly, service_worker_registration_id));
+ routing_id(), request_id, options, service_worker_registration_id));
}
void PushMessagingDispatcher::OnSubscribeFromDocumentSuccess(
@@ -95,8 +115,8 @@ void PushMessagingDispatcher::OnSubscribeFromDocumentSuccess(
subscription_callbacks_.Lookup(request_id);
DCHECK(callbacks);
- callbacks->onSuccess(blink::adoptWebPtr(
- new blink::WebPushSubscription(endpoint, p256dh, auth)));
+ callbacks->onSuccess(
+ base::WrapUnique(new blink::WebPushSubscription(endpoint, p256dh, auth)));
subscription_callbacks_.Remove(request_id);
}
diff --git a/chromium/content/renderer/push_messaging/push_messaging_dispatcher.h b/chromium/content/renderer/push_messaging/push_messaging_dispatcher.h
index ca6610b0f3d..71294e22d0d 100644
--- a/chromium/content/renderer/push_messaging/push_messaging_dispatcher.h
+++ b/chromium/content/renderer/push_messaging/push_messaging_dispatcher.h
@@ -29,6 +29,7 @@ class Message;
namespace content {
struct Manifest;
+struct PushSubscriptionOptions;
class PushMessagingDispatcher : public RenderFrameObserver,
public blink::WebPushClient {
@@ -46,12 +47,17 @@ class PushMessagingDispatcher : public RenderFrameObserver,
const blink::WebPushSubscriptionOptions& options,
blink::WebPushSubscriptionCallbacks* callbacks) override;
- void DoSubscribe(
+ void DidGetManifest(
blink::WebServiceWorkerRegistration* service_worker_registration,
const blink::WebPushSubscriptionOptions& options,
blink::WebPushSubscriptionCallbacks* callbacks,
const Manifest& manifest);
+ void DoSubscribe(
+ blink::WebServiceWorkerRegistration* service_worker_registration,
+ const PushSubscriptionOptions& options,
+ blink::WebPushSubscriptionCallbacks* callbacks);
+
void OnSubscribeFromDocumentSuccess(int32_t request_id,
const GURL& endpoint,
const std::vector<uint8_t>& p256dh,
diff --git a/chromium/content/renderer/raster_worker_pool.cc b/chromium/content/renderer/raster_worker_pool.cc
index b1f5edba3dc..65c00140827 100644
--- a/chromium/content/renderer/raster_worker_pool.cc
+++ b/chromium/content/renderer/raster_worker_pool.cc
@@ -4,16 +4,42 @@
#include "content/renderer/raster_worker_pool.h"
-#include <stddef.h>
-#include <stdint.h>
-
+#include <string>
#include <utility>
+#include <vector>
#include "base/strings/stringprintf.h"
#include "base/threading/thread_restrictions.h"
#include "base/trace_event/trace_event.h"
+#include "cc/base/math_util.h"
+#include "cc/raster/task_category.h"
namespace content {
+namespace {
+
+// A thread which forwards to RasterWorkerPool::Run with the runnable
+// categories.
+class RasterWorkerPoolThread : public base::SimpleThread {
+ public:
+ RasterWorkerPoolThread(const std::string& name_prefix,
+ const Options& options,
+ RasterWorkerPool* pool,
+ std::vector<cc::TaskCategory> categories,
+ base::ConditionVariable* has_ready_to_run_tasks_cv)
+ : SimpleThread(name_prefix, options),
+ pool_(pool),
+ categories_(categories),
+ has_ready_to_run_tasks_cv_(has_ready_to_run_tasks_cv) {}
+
+ void Run() override { pool_->Run(categories_, has_ready_to_run_tasks_cv_); }
+
+ private:
+ RasterWorkerPool* const pool_;
+ const std::vector<cc::TaskCategory> categories_;
+ base::ConditionVariable* const has_ready_to_run_tasks_cv_;
+};
+
+} // namespace
// A sequenced task runner which posts tasks to a RasterWorkerPool.
class RasterWorkerPool::RasterWorkerPoolSequencedTaskRunner
@@ -52,7 +78,10 @@ class RasterWorkerPool::RasterWorkerPoolSequencedTaskRunner
if (!graph_.nodes.empty())
dependencies = 1;
- cc::TaskGraph::Node node(graph_task.get(), 0u /* category */,
+ // Treat any tasks that are enqueued through the SequencedTaskRunner as
+ // FOREGROUND priority. We don't have enough information to know the
+ // actual priority of such tasks, so we run them as soon as possible.
+ cc::TaskGraph::Node node(graph_task.get(), cc::TASK_CATEGORY_FOREGROUND,
0u /* priority */, dependencies);
if (dependencies) {
graph_.edges.push_back(
@@ -90,24 +119,46 @@ class RasterWorkerPool::RasterWorkerPoolSequencedTaskRunner
RasterWorkerPool::RasterWorkerPool()
: namespace_token_(GetNamespaceToken()),
- has_ready_to_run_tasks_cv_(&lock_),
+ has_ready_to_run_foreground_tasks_cv_(&lock_),
+ has_ready_to_run_background_tasks_cv_(&lock_),
has_namespaces_with_finished_running_tasks_cv_(&lock_),
shutdown_(false) {}
-void RasterWorkerPool::Start(
- int num_threads,
- const base::SimpleThread::Options& thread_options) {
+void RasterWorkerPool::Start(int num_threads) {
DCHECK(threads_.empty());
- while (threads_.size() < static_cast<size_t>(num_threads)) {
- scoped_ptr<base::DelegateSimpleThread> thread(
- new base::DelegateSimpleThread(
- this, base::StringPrintf("CompositorTileWorker%u",
- static_cast<unsigned>(threads_.size() + 1))
- .c_str(),
- thread_options));
+
+ // Start |num_threads| threads for foreground work, including nonconcurrent
+ // foreground work.
+ std::vector<cc::TaskCategory> foreground_categories;
+ foreground_categories.push_back(cc::TASK_CATEGORY_NONCONCURRENT_FOREGROUND);
+ foreground_categories.push_back(cc::TASK_CATEGORY_FOREGROUND);
+
+ for (int i = 0; i < num_threads; i++) {
+ scoped_ptr<base::SimpleThread> thread(new RasterWorkerPoolThread(
+ base::StringPrintf("CompositorTileWorker%u",
+ static_cast<unsigned>(threads_.size() + 1))
+ .c_str(),
+ base::SimpleThread::Options(), this, foreground_categories,
+ &has_ready_to_run_foreground_tasks_cv_));
thread->Start();
threads_.push_back(std::move(thread));
}
+
+ // Start a single thread for background work.
+ std::vector<cc::TaskCategory> background_categories;
+ background_categories.push_back(cc::TASK_CATEGORY_BACKGROUND);
+
+ // Use background priority for background thread.
+ base::SimpleThread::Options thread_options;
+#if !defined(OS_MACOSX)
+ thread_options.set_priority(base::ThreadPriority::BACKGROUND);
+#endif
+
+ scoped_ptr<base::SimpleThread> thread(new RasterWorkerPoolThread(
+ "CompositorTileWorkerBackground", thread_options, this,
+ background_categories, &has_ready_to_run_background_tasks_cv_));
+ thread->Start();
+ threads_.push_back(std::move(thread));
}
void RasterWorkerPool::Shutdown() {
@@ -124,7 +175,8 @@ void RasterWorkerPool::Shutdown() {
shutdown_ = true;
// Wake up all workers so they exit.
- has_ready_to_run_tasks_cv_.Broadcast();
+ has_ready_to_run_foreground_tasks_cv_.Broadcast();
+ has_ready_to_run_background_tasks_cv_.Broadcast();
}
while (!threads_.empty()) {
threads_.back()->Join();
@@ -153,10 +205,13 @@ bool RasterWorkerPool::PostDelayedTask(
tasks_.push_back(make_scoped_refptr(new ClosureTask(task)));
graph_.Reset();
- for (const auto& graph_task : tasks_)
+ for (const auto& graph_task : tasks_) {
+ // Delayed tasks are assigned FOREGROUND category, ensuring that they run as
+ // soon as possible once their delay has expired.
graph_.nodes.push_back(
- cc::TaskGraph::Node(graph_task.get(), 0u /* category */,
+ cc::TaskGraph::Node(graph_task.get(), cc::TASK_CATEGORY_FOREGROUND,
0u /* priority */, 0u /* dependencies */));
+ }
ScheduleTasksWithLockAcquired(namespace_token_, &graph_);
completed_tasks_.clear();
@@ -167,18 +222,22 @@ bool RasterWorkerPool::RunsTasksOnCurrentThread() const {
return true;
}
-// Overridden from base::DelegateSimpleThread::Delegate:
-void RasterWorkerPool::Run() {
+void RasterWorkerPool::Run(const std::vector<cc::TaskCategory>& categories,
+ base::ConditionVariable* has_ready_to_run_tasks_cv) {
base::AutoLock lock(lock_);
while (true) {
- if (!RunTaskWithLockAcquired()) {
+ if (!RunTaskWithLockAcquired(categories)) {
+ // We are no longer running tasks, which may allow another category to
+ // start running. Signal other worker threads.
+ SignalHasReadyToRunTasksWithLockAcquired();
+
// Exit when shutdown is set and no more tasks are pending.
if (shutdown_)
break;
// Wait for more tasks.
- has_ready_to_run_tasks_cv_.Wait();
+ has_ready_to_run_tasks_cv->Wait();
continue;
}
}
@@ -206,7 +265,8 @@ cc::NamespaceToken RasterWorkerPool::GetNamespaceToken() {
void RasterWorkerPool::ScheduleTasks(cc::NamespaceToken token,
cc::TaskGraph* graph) {
- TRACE_EVENT2("cc", "RasterWorkerPool::ScheduleTasks", "num_nodes",
+ TRACE_EVENT2("disabled-by-default-cc.debug",
+ "RasterWorkerPool::ScheduleTasks", "num_nodes",
graph->nodes.size(), "num_edges", graph->edges.size());
{
base::AutoLock lock(lock_);
@@ -222,13 +282,13 @@ void RasterWorkerPool::ScheduleTasksWithLockAcquired(cc::NamespaceToken token,
work_queue_.ScheduleTasks(token, graph);
- // If there is more work available, wake up worker thread.
- if (work_queue_.HasReadyToRunTasks())
- has_ready_to_run_tasks_cv_.Signal();
+ // There may be more work available, so wake up another worker thread.
+ SignalHasReadyToRunTasksWithLockAcquired();
}
void RasterWorkerPool::WaitForTasksToFinishRunning(cc::NamespaceToken token) {
- TRACE_EVENT0("cc", "RasterWorkerPool::WaitForTasksToFinishRunning");
+ TRACE_EVENT0("disabled-by-default-cc.debug",
+ "RasterWorkerPool::WaitForTasksToFinishRunning");
DCHECK(token.IsValid());
@@ -243,13 +303,18 @@ void RasterWorkerPool::WaitForTasksToFinishRunning(cc::NamespaceToken token) {
while (!work_queue_.HasFinishedRunningTasksInNamespace(task_namespace))
has_namespaces_with_finished_running_tasks_cv_.Wait();
+
+ // There may be other namespaces that have finished running tasks, so wake
+ // up another origin thread.
+ has_namespaces_with_finished_running_tasks_cv_.Signal();
}
}
void RasterWorkerPool::CollectCompletedTasks(
cc::NamespaceToken token,
cc::Task::Vector* completed_tasks) {
- TRACE_EVENT0("cc", "RasterWorkerPool::CollectCompletedTasks");
+ TRACE_EVENT0("disabled-by-default-cc.debug",
+ "RasterWorkerPool::CollectCompletedTasks");
{
base::AutoLock lock(lock_);
@@ -264,33 +329,28 @@ void RasterWorkerPool::CollectCompletedTasksWithLockAcquired(
work_queue_.CollectCompletedTasks(token, completed_tasks);
}
-bool RasterWorkerPool::RunTaskWithLockAcquired() {
+bool RasterWorkerPool::RunTaskWithLockAcquired(
+ const std::vector<cc::TaskCategory>& categories) {
+ for (const auto& category : categories) {
+ if (ShouldRunTaskForCategoryWithLockAcquired(category)) {
+ RunTaskInCategoryWithLockAcquired(category);
+ return true;
+ }
+ }
+ return false;
+}
+
+void RasterWorkerPool::RunTaskInCategoryWithLockAcquired(
+ cc::TaskCategory category) {
TRACE_EVENT0("toplevel", "TaskGraphRunner::RunTask");
lock_.AssertAcquired();
- // Find the first category with any tasks to run. This task graph runner
- // treats categories as an additional priority.
- // TODO(ericrk): Add more category/thread logic.
- const auto& ready_to_run_namespaces = work_queue_.ready_to_run_namespaces();
- auto found = std::find_if(
- ready_to_run_namespaces.cbegin(), ready_to_run_namespaces.cend(),
- [](const std::pair<uint16_t,
- cc::TaskGraphWorkQueue::TaskNamespace::Vector>& pair) {
- return !pair.second.empty();
- });
-
- if (found == ready_to_run_namespaces.cend()) {
- return false;
- }
-
- const uint16_t category = found->first;
auto prioritized_task = work_queue_.GetNextTaskToRun(category);
cc::Task* task = prioritized_task.task;
// There may be more work available, so wake up another worker thread.
- if (work_queue_.HasReadyToRunTasks())
- has_ready_to_run_tasks_cv_.Signal();
+ SignalHasReadyToRunTasksWithLockAcquired();
// Call WillRun() before releasing |lock_| and running task.
task->WillRun();
@@ -309,11 +369,56 @@ bool RasterWorkerPool::RunTaskWithLockAcquired() {
// If namespace has finished running all tasks, wake up origin threads.
if (work_queue_.HasFinishedRunningTasksInNamespace(
prioritized_task.task_namespace))
- has_namespaces_with_finished_running_tasks_cv_.Broadcast();
+ has_namespaces_with_finished_running_tasks_cv_.Signal();
+}
+
+bool RasterWorkerPool::ShouldRunTaskForCategoryWithLockAcquired(
+ cc::TaskCategory category) {
+ lock_.AssertAcquired();
+
+ if (!work_queue_.HasReadyToRunTasksForCategory(category))
+ return false;
+
+ if (category == cc::TASK_CATEGORY_BACKGROUND) {
+ // Only run background tasks if there are no foreground tasks running or
+ // ready to run.
+ size_t num_running_foreground_tasks =
+ work_queue_.NumRunningTasksForCategory(
+ cc::TASK_CATEGORY_NONCONCURRENT_FOREGROUND) +
+ work_queue_.NumRunningTasksForCategory(cc::TASK_CATEGORY_FOREGROUND);
+ bool has_ready_to_run_foreground_tasks =
+ work_queue_.HasReadyToRunTasksForCategory(
+ cc::TASK_CATEGORY_NONCONCURRENT_FOREGROUND) ||
+ work_queue_.HasReadyToRunTasksForCategory(cc::TASK_CATEGORY_FOREGROUND);
+
+ if (num_running_foreground_tasks > 0 || has_ready_to_run_foreground_tasks)
+ return false;
+ }
+
+ // Enforce that only one nonconcurrent task runs at a time.
+ if (category == cc::TASK_CATEGORY_NONCONCURRENT_FOREGROUND &&
+ work_queue_.NumRunningTasksForCategory(
+ cc::TASK_CATEGORY_NONCONCURRENT_FOREGROUND) > 0) {
+ return false;
+ }
return true;
}
+void RasterWorkerPool::SignalHasReadyToRunTasksWithLockAcquired() {
+ lock_.AssertAcquired();
+
+ if (ShouldRunTaskForCategoryWithLockAcquired(cc::TASK_CATEGORY_FOREGROUND) ||
+ ShouldRunTaskForCategoryWithLockAcquired(
+ cc::TASK_CATEGORY_NONCONCURRENT_FOREGROUND)) {
+ has_ready_to_run_foreground_tasks_cv_.Signal();
+ }
+
+ if (ShouldRunTaskForCategoryWithLockAcquired(cc::TASK_CATEGORY_BACKGROUND)) {
+ has_ready_to_run_background_tasks_cv_.Signal();
+ }
+}
+
RasterWorkerPool::ClosureTask::ClosureTask(const base::Closure& closure)
: closure_(closure) {}
diff --git a/chromium/content/renderer/raster_worker_pool.h b/chromium/content/renderer/raster_worker_pool.h
index 1b7cfb1b543..b4ddf9a61c2 100644
--- a/chromium/content/renderer/raster_worker_pool.h
+++ b/chromium/content/renderer/raster_worker_pool.h
@@ -13,6 +13,7 @@
#include "base/synchronization/condition_variable.h"
#include "base/task_runner.h"
#include "base/threading/simple_thread.h"
+#include "cc/raster/task_category.h"
#include "cc/raster/task_graph_runner.h"
#include "cc/raster/task_graph_work_queue.h"
#include "content/common/content_export.h"
@@ -27,10 +28,8 @@ namespace content {
// parallel with other instances of sequenced task runners.
// It's also possible to get the underlying TaskGraphRunner to schedule a graph
// of tasks with their dependencies.
-class CONTENT_EXPORT RasterWorkerPool
- : public base::TaskRunner,
- public cc::TaskGraphRunner,
- public base::DelegateSimpleThread::Delegate {
+class CONTENT_EXPORT RasterWorkerPool : public base::TaskRunner,
+ public cc::TaskGraphRunner {
public:
RasterWorkerPool();
@@ -47,15 +46,16 @@ class CONTENT_EXPORT RasterWorkerPool
void CollectCompletedTasks(cc::NamespaceToken token,
cc::Task::Vector* completed_tasks) override;
- // Overridden from base::DelegateSimpleThread::Delegate:
- void Run() override;
+ // Runs a task from one of the provided categories. Categories listed first
+ // have higher priority.
+ void Run(const std::vector<cc::TaskCategory>& categories,
+ base::ConditionVariable* has_ready_to_run_tasks_cv);
void FlushForTesting();
// Spawn |num_threads| number of threads and start running work on the
// worker threads.
- void Start(int num_threads,
- const base::SimpleThread::Options& thread_options);
+ void Start(int num_threads);
// Finish running all the posted tasks (and nested task posted by those tasks)
// of all the associated task runners.
@@ -75,10 +75,6 @@ class CONTENT_EXPORT RasterWorkerPool
class RasterWorkerPoolSequencedTaskRunner;
friend class RasterWorkerPoolSequencedTaskRunner;
- // Run next task. Caller must acquire |lock_| prior to calling this function.
- // Returns true if there was a task available to run.
- bool RunTaskWithLockAcquired();
-
// Simple Task for the TaskGraphRunner that wraps a closure.
// This class is used to schedule TaskRunner tasks on the
// |task_graph_runner_|.
@@ -103,8 +99,24 @@ class CONTENT_EXPORT RasterWorkerPool
void CollectCompletedTasksWithLockAcquired(cc::NamespaceToken token,
cc::Task::Vector* completed_tasks);
+ // Runs a task from one of the provided categories. Categories listed first
+ // have higher priority. Returns false if there were no tasks to run.
+ bool RunTaskWithLockAcquired(const std::vector<cc::TaskCategory>& categories);
+
+ // Run next task for the given category. Caller must acquire |lock_| prior to
+ // calling this function and make sure at least one task is ready to run.
+ void RunTaskInCategoryWithLockAcquired(cc::TaskCategory category);
+
+ // Helper function which signals worker threads if tasks are ready to run.
+ void SignalHasReadyToRunTasksWithLockAcquired();
+
+ // Determines if we should run a new task for the given category. This factors
+ // in whether a task is available and whether the count of running tasks is
+ // low enough to start a new one.
+ bool ShouldRunTaskForCategoryWithLockAcquired(cc::TaskCategory category);
+
// The actual threads where work is done.
- ScopedVector<base::DelegateSimpleThread> threads_;
+ std::vector<scoped_ptr<base::SimpleThread>> threads_;
// Lock to exclusively access all the following members that are used to
// implement the TaskRunner and TaskGraphRunner interfaces.
@@ -120,9 +132,9 @@ class CONTENT_EXPORT RasterWorkerPool
// Cached vector to avoid allocation when getting the list of complete
// tasks.
cc::Task::Vector completed_tasks_;
- // Condition variable that is waited on by Run() until new tasks are ready to
- // run or shutdown starts.
- base::ConditionVariable has_ready_to_run_tasks_cv_;
+ // Condition variables for foreground and background tasks.
+ base::ConditionVariable has_ready_to_run_foreground_tasks_cv_;
+ base::ConditionVariable has_ready_to_run_background_tasks_cv_;
// Condition variable that is waited on by origin threads until a namespace
// has finished running all associated tasks.
base::ConditionVariable has_namespaces_with_finished_running_tasks_cv_;
diff --git a/chromium/content/renderer/raster_worker_pool_unittest.cc b/chromium/content/renderer/raster_worker_pool_unittest.cc
index 7a402b76183..73f83dcdf6a 100644
--- a/chromium/content/renderer/raster_worker_pool_unittest.cc
+++ b/chromium/content/renderer/raster_worker_pool_unittest.cc
@@ -20,7 +20,7 @@ class RasterWorkerPoolTestDelegate {
: raster_worker_pool_(new content::RasterWorkerPool()) {}
void StartTaskRunner() {
- raster_worker_pool_->Start(kNumThreads, SimpleThread::Options());
+ raster_worker_pool_->Start(kNumThreads);
}
scoped_refptr<content::RasterWorkerPool> GetTaskRunner() {
@@ -45,7 +45,7 @@ class RasterWorkerPoolSequencedTestDelegate {
: raster_worker_pool_(new content::RasterWorkerPool()) {}
void StartTaskRunner() {
- raster_worker_pool_->Start(kNumThreads, SimpleThread::Options());
+ raster_worker_pool_->Start(kNumThreads);
}
scoped_refptr<base::SequencedTaskRunner> GetTaskRunner() {
@@ -77,7 +77,7 @@ class RasterWorkerPoolTaskGraphRunnerTestDelegate {
: raster_worker_pool_(new content::RasterWorkerPool()) {}
void StartTaskGraphRunner() {
- raster_worker_pool_->Start(NumThreads, base::SimpleThread::Options());
+ raster_worker_pool_->Start(NumThreads);
}
cc::TaskGraphRunner* GetTaskGraphRunner() {
diff --git a/chromium/content/renderer/render_frame_impl.cc b/chromium/content/renderer/render_frame_impl.cc
index 7aeebd2bb30..3f3fe7b1de1 100644
--- a/chromium/content/renderer/render_frame_impl.cc
+++ b/chromium/content/renderer/render_frame_impl.cc
@@ -13,6 +13,7 @@
#include "base/command_line.h"
#include "base/debug/alias.h"
#include "base/debug/asan_invalid_access.h"
+#include "base/debug/crash_logging.h"
#include "base/debug/dump_without_crashing.h"
#include "base/files/file.h"
#include "base/i18n/char_iterator.h"
@@ -28,12 +29,12 @@
#include "base/strings/utf_string_conversions.h"
#include "base/thread_task_runner_handle.h"
#include "base/time/time.h"
+#include "base/trace_event/trace_event_argument.h"
#include "build/build_config.h"
#include "cc/base/switches.h"
#include "components/scheduler/renderer/renderer_scheduler.h"
#include "content/child/appcache/appcache_dispatcher.h"
#include "content/child/permissions/permission_dispatcher.h"
-#include "content/child/plugin_messages.h"
#include "content/child/quota_dispatcher.h"
#include "content/child/request_extra_data.h"
#include "content/child/service_worker/service_worker_handle_reference.h"
@@ -52,6 +53,7 @@
#include "content/common/frame_replication_state.h"
#include "content/common/input_messages.h"
#include "content/common/navigation_params.h"
+#include "content/common/page_messages.h"
#include "content/common/savable_subframe.h"
#include "content/common/service_worker/service_worker_types.h"
#include "content/common/site_isolation_policy.h"
@@ -61,6 +63,7 @@
#include "content/public/common/bindings_policy.h"
#include "content/public/common/browser_side_navigation_policy.h"
#include "content/public/common/content_constants.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/context_menu_params.h"
#include "content/public/common/isolated_world_ids.h"
@@ -93,10 +96,7 @@
#include "content/renderer/internal_document_state_data.h"
#include "content/renderer/manifest/manifest_manager.h"
#include "content/renderer/media/audio_device_factory.h"
-#include "content/renderer/media/audio_renderer_mixer_manager.h"
-#include "content/renderer/media/cdm/render_cdm_factory.h"
-#include "content/renderer/media/media_permission_dispatcher_impl.h"
-#include "content/renderer/media/media_permission_dispatcher_proxy.h"
+#include "content/renderer/media/media_permission_dispatcher.h"
#include "content/renderer/media/media_stream_dispatcher.h"
#include "content/renderer/media/media_stream_renderer_factory_impl.h"
#include "content/renderer/media/midi_dispatcher.h"
@@ -104,12 +104,10 @@
#include "content/renderer/media/renderer_webmediaplayer_delegate.h"
#include "content/renderer/media/user_media_client_impl.h"
#include "content/renderer/media/webmediaplayer_ms.h"
-#include "content/renderer/memory_benchmarking_extension.h"
#include "content/renderer/mojo/service_registry_js_wrapper.h"
#include "content/renderer/mojo_bindings_controller.h"
#include "content/renderer/navigation_state_impl.h"
#include "content/renderer/notification_permission_dispatcher.h"
-#include "content/renderer/npapi/plugin_channel_host.h"
#include "content/renderer/pepper/plugin_instance_throttler_impl.h"
#include "content/renderer/presentation/presentation_dispatcher.h"
#include "content/renderer/push_messaging/push_messaging_dispatcher.h"
@@ -134,6 +132,9 @@
#include "gin/modules/module_registry.h"
#include "media/audio/audio_output_device.h"
#include "media/base/audio_renderer_mixer_input.h"
+#include "media/base/cdm_factory.h"
+#include "media/base/decoder_factory.h"
+#include "media/base/media.h"
#include "media/base/media_log.h"
#include "media/base/media_switches.h"
#include "media/blink/url_index.h"
@@ -141,11 +142,17 @@
#include "media/blink/webmediaplayer_impl.h"
#include "media/renderers/gpu_video_accelerator_factories.h"
#include "mojo/common/url_type_converters.h"
+#include "mojo/edk/js/core.h"
+#include "mojo/edk/js/support.h"
#include "net/base/data_url.h"
#include "net/base/net_errors.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/http/http_util.h"
+#include "third_party/WebKit/public/platform/URLConversion.h"
+#include "third_party/WebKit/public/platform/WebCachePolicy.h"
#include "third_party/WebKit/public/platform/WebData.h"
+#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
+#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/platform/WebStorageQuotaCallbacks.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/WebURL.h"
@@ -155,6 +162,7 @@
#include "third_party/WebKit/public/platform/modules/webusb/WebUSBClient.h"
#include "third_party/WebKit/public/web/WebColorSuggestion.h"
#include "third_party/WebKit/public/web/WebDocument.h"
+#include "third_party/WebKit/public/web/WebFindOptions.h"
#include "third_party/WebKit/public/web/WebFrameSerializer.h"
#include "third_party/WebKit/public/web/WebFrameWidget.h"
#include "third_party/WebKit/public/web/WebKit.h"
@@ -162,24 +170,23 @@
#include "third_party/WebKit/public/web/WebMediaStreamRegistry.h"
#include "third_party/WebKit/public/web/WebNavigationPolicy.h"
#include "third_party/WebKit/public/web/WebPlugin.h"
+#include "third_party/WebKit/public/web/WebPluginContainer.h"
+#include "third_party/WebKit/public/web/WebPluginDocument.h"
#include "third_party/WebKit/public/web/WebPluginParams.h"
#include "third_party/WebKit/public/web/WebRange.h"
#include "third_party/WebKit/public/web/WebScopedUserGesture.h"
#include "third_party/WebKit/public/web/WebScriptSource.h"
#include "third_party/WebKit/public/web/WebSearchableFormData.h"
-#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
#include "third_party/WebKit/public/web/WebSecurityPolicy.h"
#include "third_party/WebKit/public/web/WebSerializedScriptValue.h"
#include "third_party/WebKit/public/web/WebSettings.h"
#include "third_party/WebKit/public/web/WebSurroundingText.h"
#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
#include "third_party/WebKit/public/web/WebView.h"
-#include "third_party/mojo/src/mojo/edk/js/core.h"
-#include "third_party/mojo/src/mojo/edk/js/support.h"
+#include "url/url_constants.h"
#include "url/url_util.h"
#if defined(ENABLE_PLUGINS)
-#include "content/renderer/npapi/webplugin_impl.h"
#include "content/renderer/pepper/pepper_browser_connection.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/pepper_webplugin_impl.h"
@@ -194,42 +201,50 @@
#include <cpu-features.h>
#include "content/common/gpu/client/context_provider_command_buffer.h"
-#include "content/renderer/android/synchronous_compositor_factory.h"
#include "content/renderer/java/gin_java_bridge_dispatcher.h"
#include "content/renderer/media/android/renderer_media_player_manager.h"
#include "content/renderer/media/android/renderer_media_session_manager.h"
+#include "content/renderer/media/android/renderer_surface_view_manager.h"
#include "content/renderer/media/android/stream_texture_factory_impl.h"
#include "content/renderer/media/android/webmediaplayer_android.h"
#include "content/renderer/media/android/webmediasession_android.h"
#include "media/base/android/media_codec_util.h"
+#include "third_party/WebKit/public/platform/WebFloatPoint.h"
#else
#include "cc/blink/context_provider_web_context.h"
-#include "device/devices_app/public/cpp/constants.h"
#endif
#if defined(ENABLE_PEPPER_CDMS)
#include "content/renderer/media/cdm/pepper_cdm_wrapper_impl.h"
+#include "content/renderer/media/cdm/render_cdm_factory.h"
#elif defined(ENABLE_BROWSER_CDMS)
+#include "content/renderer/media/cdm/render_cdm_factory.h"
#include "content/renderer/media/cdm/renderer_cdm_manager.h"
#endif
#if defined(ENABLE_MOJO_MEDIA)
+#include "content/renderer/media/media_interface_provider.h"
+#endif
+
+#if defined(ENABLE_MOJO_CDM)
#include "media/mojo/services/mojo_cdm_factory.h" // nogncheck
-#include "mojo/public/cpp/bindings/interface_request.h"
-#include "mojo/shell/public/cpp/connect.h"
-#include "mojo/shell/public/interfaces/shell.mojom.h"
#endif
-#if defined(ENABLE_MOJO_MEDIA) && !defined(OS_ANDROID)
+#if defined(ENABLE_MOJO_RENDERER)
#include "media/mojo/services/mojo_renderer_factory.h" // nogncheck
#else
#include "media/renderers/default_renderer_factory.h"
#endif
+#if defined(ENABLE_MOJO_AUDIO_DECODER) || defined(ENABLE_MOJO_VIDEO_DECODER)
+#include "media/mojo/services/mojo_decoder_factory.h" // nogncheck
+#endif
+
#if defined(ENABLE_WEBVR)
#include "content/renderer/vr/vr_dispatcher.h"
#endif
+using blink::WebCachePolicy;
using blink::WebContentDecryptionModule;
using blink::WebContextMenuData;
using blink::WebCString;
@@ -241,7 +256,9 @@ using blink::WebDOMMessageEvent;
using blink::WebElement;
using blink::WebExternalPopupMenu;
using blink::WebExternalPopupMenuClient;
+using blink::WebFindOptions;
using blink::WebFrame;
+using blink::WebFrameLoadType;
using blink::WebFrameSerializer;
using blink::WebFrameSerializerClient;
using blink::WebHistoryItem;
@@ -254,9 +271,11 @@ using blink::WebMediaSession;
using blink::WebNavigationPolicy;
using blink::WebNavigationType;
using blink::WebNode;
+using blink::WebPluginDocument;
using blink::WebPluginParams;
using blink::WebPopupMenuInfo;
using blink::WebRange;
+using blink::WebRect;
using blink::WebReferrerPolicy;
using blink::WebScriptSource;
using blink::WebSearchableFormData;
@@ -277,15 +296,15 @@ using blink::WebView;
using base::Time;
using base::TimeDelta;
+#if defined(OS_ANDROID)
+using blink::WebFloatPoint;
+using blink::WebFloatRect;
+#endif
+
namespace content {
namespace {
-const char kDefaultAcceptHeader[] =
- "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/"
- "*;q=0.8";
-const char kAcceptHeader[] = "Accept";
-
const size_t kExtraCharsBeforeAndAfterSelection = 100;
typedef std::map<int, RenderFrameImpl*> RoutingIDFrameMap;
@@ -304,20 +323,15 @@ int64_t ExtractPostId(const WebHistoryItem& item) {
WebURLResponseExtraDataImpl* GetExtraDataFromResponse(
const WebURLResponse& response) {
- return static_cast<WebURLResponseExtraDataImpl*>(response.extraData());
+ return static_cast<WebURLResponseExtraDataImpl*>(response.getExtraData());
}
void GetRedirectChain(WebDataSource* ds, std::vector<GURL>* result) {
- // Replace any occurrences of swappedout:// with about:blank.
- const WebURL& blank_url = GURL(url::kAboutBlankURL);
WebVector<WebURL> urls;
ds->redirectChain(urls);
result->reserve(urls.size());
for (size_t i = 0; i < urls.size(); ++i) {
- if (urls[i] != GURL(kSwappedOutURL))
- result->push_back(urls[i]);
- else
- result->push_back(blank_url);
+ result->push_back(urls[i]);
}
}
@@ -416,15 +430,30 @@ NOINLINE void MaybeTriggerAsanError(const GURL& url) {
std::string crash_type(url.path());
if (crash_type == kHeapOverflow) {
+ LOG(ERROR)
+ << "Intentionally causing ASAN heap overflow"
+ << " because user navigated to " << url.spec();
base::debug::AsanHeapOverflow();
} else if (crash_type == kHeapUnderflow) {
+ LOG(ERROR)
+ << "Intentionally causing ASAN heap underflow"
+ << " because user navigated to " << url.spec();
base::debug::AsanHeapUnderflow();
} else if (crash_type == kUseAfterFree) {
+ LOG(ERROR)
+ << "Intentionally causing ASAN heap use-after-free"
+ << " because user navigated to " << url.spec();
base::debug::AsanHeapUseAfterFree();
#if defined(SYZYASAN)
} else if (crash_type == kCorruptHeapBlock) {
+ LOG(ERROR)
+ << "Intentionally causing ASAN corrupt heap block"
+ << " because user navigated to " << url.spec();
base::debug::AsanCorruptHeapBlock();
} else if (crash_type == kCorruptHeap) {
+ LOG(ERROR)
+ << "Intentionally causing ASAN corrupt heap"
+ << " because user navigated to " << url.spec();
base::debug::AsanCorruptHeap();
#endif
}
@@ -435,8 +464,13 @@ void MaybeHandleDebugURL(const GURL& url) {
if (!url.SchemeIs(kChromeUIScheme))
return;
if (url == GURL(kChromeUIBadCastCrashURL)) {
+ LOG(ERROR)
+ << "Intentionally crashing (with bad cast)"
+ << " because user navigated to " << url.spec();
BadCastCrashIntentionally();
} else if (url == GURL(kChromeUICrashURL)) {
+ LOG(ERROR) << "Intentionally crashing (with null pointer dereference)"
+ << " because user navigated to " << url.spec();
CrashIntentionally();
} else if (url == GURL(kChromeUIDumpURL)) {
// This URL will only correctly create a crash dump file if content is
@@ -445,12 +479,18 @@ void MaybeHandleDebugURL(const GURL& url) {
// of base::debug::DumpWithoutCrashing for more details.
base::debug::DumpWithoutCrashing();
} else if (url == GURL(kChromeUIKillURL)) {
+ LOG(ERROR) << "Intentionally issuing kill signal to current process"
+ << " because user navigated to " << url.spec();
base::Process::Current().Terminate(1, false);
} else if (url == GURL(kChromeUIHangURL)) {
+ LOG(ERROR) << "Intentionally hanging ourselves with sleep infinite loop"
+ << " because user navigated to " << url.spec();
for (;;) {
base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
}
} else if (url == GURL(kChromeUIShorthangURL)) {
+ LOG(ERROR) << "Intentionally sleeping renderer for 20 seconds"
+ << " because user navigated to " << url.spec();
base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(20));
}
@@ -470,7 +510,7 @@ WebURLRequest CreateURLRequestForNavigation(
bool is_view_source_mode_enabled) {
WebURLRequest request(common_params.url);
if (is_view_source_mode_enabled)
- request.setCachePolicy(WebURLRequest::ReturnCacheDataElseLoad);
+ request.setCachePolicy(WebCachePolicy::ReturnCacheDataElseLoad);
if (common_params.referrer.url.is_valid()) {
WebString web_referrer = WebSecurityPolicy::generateReferrerHeader(
@@ -481,8 +521,11 @@ WebURLRequest CreateURLRequestForNavigation(
request.setHTTPReferrer(web_referrer, common_params.referrer.policy);
}
+ request.setHTTPMethod(WebString::fromUTF8(common_params.method));
+
RequestExtraData* extra_data = new RequestExtraData();
extra_data->set_stream_override(std::move(stream_override));
+ extra_data->set_lofi_state(common_params.lofi_state);
request.setExtraData(extra_data);
// Set the ui timestamp for this navigation. Currently the timestamp here is
@@ -532,11 +575,6 @@ base::TimeTicks SanitizeNavigationTiming(
CommonNavigationParams MakeCommonNavigationParams(
blink::WebURLRequest* request,
bool should_replace_current_entry) {
- const RequestExtraData kEmptyData;
- const RequestExtraData* extra_data =
- static_cast<RequestExtraData*>(request->extraData());
- if (!extra_data)
- extra_data = &kEmptyData;
Referrer referrer(
GURL(request->httpHeaderField(WebString::fromUTF8("Referer")).latin1()),
request->referrerPolicy());
@@ -552,11 +590,15 @@ CommonNavigationParams MakeCommonNavigationParams(
FrameMsg_UILoadMetricsReportType::Value report_type =
static_cast<FrameMsg_UILoadMetricsReportType::Value>(
request->inputPerfMetricReportPolicy());
+
+ const RequestExtraData* extra_data =
+ static_cast<RequestExtraData*>(request->getExtraData());
+ DCHECK(extra_data);
return CommonNavigationParams(
request->url(), referrer, extra_data->transition_type(),
FrameMsg_Navigate_Type::NORMAL, true, should_replace_current_entry,
- ui_timestamp, report_type, GURL(), GURL(), LOFI_UNSPECIFIED,
- base::TimeTicks::Now());
+ ui_timestamp, report_type, GURL(), GURL(), extra_data->lofi_state(),
+ base::TimeTicks::Now(), request->httpMethod().latin1());
}
media::Context3D GetSharedMainThreadContext3D() {
@@ -569,14 +611,15 @@ media::Context3D GetSharedMainThreadContext3D() {
bool IsReload(FrameMsg_Navigate_Type::Value navigation_type) {
return navigation_type == FrameMsg_Navigate_Type::RELOAD ||
- navigation_type == FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE ||
+ navigation_type == FrameMsg_Navigate_Type::RELOAD_BYPASSING_CACHE ||
navigation_type == FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL;
}
RenderFrameImpl::CreateRenderFrameImplFunction g_create_render_frame_impl =
nullptr;
-void OnGotContentHandlerID(uint32_t content_handler_id) {}
+void OnGotInstanceID(mojo::shell::mojom::ConnectResult result,
+ const std::string& user_id, uint32_t instance_id) {}
WebString ConvertRelativePathToHtmlAttribute(const base::FilePath& path) {
DCHECK(!path.IsAbsolute());
@@ -585,6 +628,42 @@ WebString ConvertRelativePathToHtmlAttribute(const base::FilePath& path) {
path.NormalizePathSeparatorsTo(FILE_PATH_LITERAL('/')).AsUTF8Unsafe());
}
+// Implementation of WebFrameSerializer::LinkRewritingDelegate that responds
+// based on the payload of FrameMsg_GetSerializedHtmlWithLocalLinks.
+class LinkRewritingDelegate : public WebFrameSerializer::LinkRewritingDelegate {
+ public:
+ LinkRewritingDelegate(
+ const std::map<GURL, base::FilePath>& url_to_local_path,
+ const std::map<int, base::FilePath>& frame_routing_id_to_local_path)
+ : url_to_local_path_(url_to_local_path),
+ frame_routing_id_to_local_path_(frame_routing_id_to_local_path) {}
+
+ bool rewriteFrameSource(WebFrame* frame, WebString* rewritten_link) override {
+ int routing_id = GetRoutingIdForFrameOrProxy(frame);
+ auto it = frame_routing_id_to_local_path_.find(routing_id);
+ if (it == frame_routing_id_to_local_path_.end())
+ return false; // This can happen because of https://crbug.com/541354.
+
+ const base::FilePath& local_path = it->second;
+ *rewritten_link = ConvertRelativePathToHtmlAttribute(local_path);
+ return true;
+ }
+
+ bool rewriteLink(const WebURL& url, WebString* rewritten_link) override {
+ auto it = url_to_local_path_.find(url);
+ if (it == url_to_local_path_.end())
+ return false;
+
+ const base::FilePath& local_path = it->second;
+ *rewritten_link = ConvertRelativePathToHtmlAttribute(local_path);
+ return true;
+ }
+
+ private:
+ const std::map<GURL, base::FilePath>& url_to_local_path_;
+ const std::map<int, base::FilePath>& frame_routing_id_to_local_path_;
+};
+
// Implementation of WebFrameSerializer::MHTMLPartsGenerationDelegate that
// 1. Bases shouldSkipResource and getContentID responses on contents of
// FrameMsg_SerializeAsMHTML_Params.
@@ -619,8 +698,8 @@ class MHTMLPartsGenerationDelegate
return false;
}
- WebString getContentID(const WebFrame& frame) override {
- int routing_id = GetRoutingIdForFrameOrProxy(const_cast<WebFrame*>(&frame));
+ WebString getContentID(WebFrame* frame) override {
+ int routing_id = GetRoutingIdForFrameOrProxy(frame);
auto it = params_.frame_routing_id_to_content_id.find(routing_id);
if (it == params_.frame_routing_id_to_content_id.end())
@@ -670,39 +749,46 @@ bool IsContentWithCertificateErrorsRelevantToUI(
}
#if defined(OS_ANDROID)
-// Returns true if WMPI is enabled and is expected to be able to play the URL,
-// false if WMPA should be used instead.
+// Returns true if WMPI should be used for playback, false otherwise.
//
-// Note that HLS and WebM detection are pre-redirect and path-based. It is
-// possible to load such a URL and find different content, in which case
-// playback may fail.
-bool CanUseWebMediaPlayerImpl(const GURL& url) {
+// Note that HLS and MP4 detection are pre-redirect and path-based. It is
+// possible to load such a URL and find different content.
+bool UseWebMediaPlayerImpl(const GURL& url) {
// WMPI does not support HLS.
- if (media::MediaCodecUtil::IsHLSPath(url))
+ if (media::MediaCodecUtil::IsHLSURL(url))
return false;
- // If --enable-unified-media-pipeline was passed, always use WMPI. (This
- // allows for testing the new path.)
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableUnifiedMediaPipeline)) {
- return true;
- }
-
- // Don't use WMPI for blob URLs (MSE in particular) yet.
- if (url.SchemeIsBlob())
+ // Don't use WMPI if the container likely contains a codec we can't decode in
+ // software and platform decoders are not available.
+ if (base::EndsWith(url.path(), ".mp4",
+ base::CompareCase::INSENSITIVE_ASCII) &&
+ !media::HasPlatformDecoderSupport()) {
return false;
+ }
- // WMPI can play VPX even without AVDA.
- if (base::EndsWith(url.path(), ".webm", base::CompareCase::INSENSITIVE_ASCII))
- return true;
-
- // Only use WMPI if AVDA is available.
- return (media::MediaCodecUtil::IsMediaCodecAvailable() &&
- !base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableAcceleratedVideoDecode));
+ // Otherwise enable WMPI if indicated via experiment or command line.
+ return media::IsUnifiedMediaPipelineEnabled();
}
#endif // defined(OS_ANDROID)
+#if defined(ENABLE_MOJO_CDM)
+// Returns whether mojo CDM should be used at runtime. Note that even when mojo
+// CDM is enabled at compile time (ENABLE_MOJO_CDM is defined), there are cases
+// where we want to choose other CDM types. For example, on Android when we use
+// WebMediaPlayerAndroid, we still want to use ProxyMediaKeys. In the future,
+// when we experiment mojo CDM on desktop, we will choose between mojo CDM and
+// pepper CDM at runtime.
+// TODO(xhwang): Remove this when we use mojo CDM for all remote CDM cases by
+// default.
+bool UseMojoCdm() {
+#if defined(OS_ANDROID)
+ return media::IsUnifiedMediaPipelineEnabled();
+#else
+ return true;
+#endif
+}
+#endif // defined(ENABLE_MOJO_CDM)
+
} // namespace
// static
@@ -738,14 +824,16 @@ RenderFrameImpl* RenderFrameImpl::CreateMainFrame(
int32_t widget_routing_id,
bool hidden,
const blink::WebScreenInfo& screen_info,
- CompositorDependencies* compositor_deps) {
+ CompositorDependencies* compositor_deps,
+ blink::WebFrame* opener) {
// A main frame RenderFrame must have a RenderWidget.
DCHECK_NE(MSG_ROUTING_NONE, widget_routing_id);
RenderFrameImpl* render_frame =
RenderFrameImpl::Create(render_view, routing_id);
- WebLocalFrame* web_frame =
- WebLocalFrame::create(blink::WebTreeScopeType::Document, render_frame);
+ render_frame->InitializeBlameContext(nullptr);
+ WebLocalFrame* web_frame = WebLocalFrame::create(
+ blink::WebTreeScopeType::Document, render_frame, opener);
render_frame->BindToWebFrame(web_frame);
render_view->webview()->setMainFrame(web_frame);
render_frame->render_widget_ = RenderWidget::CreateForFrame(
@@ -754,7 +842,7 @@ RenderFrameImpl* RenderFrameImpl::CreateMainFrame(
// WasShown and WasHidden, separating page-level visibility from
// frame-level visibility.
// TODO(avi): This DCHECK is to track cleanup for https://crbug.com/545684
- DCHECK_EQ(render_view, render_frame->render_widget_)
+ DCHECK_EQ(render_view->GetWidget(), render_frame->render_widget_)
<< "Main frame is no longer reusing the RenderView as its widget! "
<< "Does the RenderFrame need to register itself with the RenderWidget?";
return render_frame;
@@ -790,10 +878,13 @@ void RenderFrameImpl::CreateFrame(
// Create the RenderFrame and WebLocalFrame, linking the two.
render_frame =
RenderFrameImpl::Create(parent_proxy->render_view(), routing_id);
+ render_frame->InitializeBlameContext(FromRoutingID(parent_routing_id));
web_frame = parent_web_frame->createLocalChild(
replicated_state.scope, WebString::fromUTF8(replicated_state.name),
+ WebString::fromUTF8(replicated_state.unique_name),
replicated_state.sandbox_flags, render_frame,
- previous_sibling_web_frame, frame_owner_properties);
+ previous_sibling_web_frame, frame_owner_properties,
+ ResolveOpener(opener_routing_id, nullptr));
// The RenderFrame is created and inserted into the frame tree in the above
// call to createLocalChild.
@@ -809,6 +900,7 @@ void RenderFrameImpl::CreateFrame(
return;
render_frame = RenderFrameImpl::Create(proxy->render_view(), routing_id);
+ render_frame->InitializeBlameContext(nullptr);
render_frame->proxy_routing_id_ = proxy_routing_id;
web_frame = blink::WebLocalFrame::createProvisional(
render_frame, proxy->web_frame(), replicated_state.sandbox_flags,
@@ -817,9 +909,6 @@ void RenderFrameImpl::CreateFrame(
render_frame->BindToWebFrame(web_frame);
CHECK(parent_routing_id != MSG_ROUTING_NONE || !web_frame->parent());
- WebFrame* opener = ResolveOpener(opener_routing_id, nullptr);
- web_frame->setOpener(opener);
-
if (widget_params.routing_id != MSG_ROUTING_NONE) {
CHECK(!web_frame->parent() ||
SiteIsolationPolicy::AreCrossProcessFramesPossible());
@@ -877,14 +966,7 @@ blink::WebFrame* RenderFrameImpl::ResolveOpener(int opener_frame_routing_id,
if (opener_view_routing_id)
*opener_view_routing_id = opener_proxy->render_view()->GetRoutingID();
- // TODO(nasko,alexmos): This check won't be needed once swappedout:// is
- // gone.
- if (opener_proxy->IsMainFrameDetachedFromTree()) {
- DCHECK(!SiteIsolationPolicy::IsSwappedOutStateForbidden());
- return opener_proxy->render_view()->webview()->mainFrame();
- } else {
- return opener_proxy->web_frame();
- }
+ return opener_proxy->web_frame();
}
RenderFrameImpl* opener_frame =
@@ -906,12 +988,12 @@ RenderFrameImpl::RenderFrameImpl(const CreateParams& params)
in_frame_tree_(false),
render_view_(params.render_view->AsWeakPtr()),
routing_id_(params.routing_id),
- is_swapped_out_(false),
render_frame_proxy_(NULL),
is_detaching_(false),
proxy_routing_id_(MSG_ROUTING_NONE),
#if defined(ENABLE_PLUGINS)
plugin_power_saver_helper_(nullptr),
+ plugin_find_handler_(nullptr),
#endif
cookie_jar_(this),
selection_text_offset_(0),
@@ -919,12 +1001,12 @@ RenderFrameImpl::RenderFrameImpl(const CreateParams& params)
handling_select_range_(false),
notification_permission_dispatcher_(NULL),
web_user_media_client_(NULL),
- media_permission_dispatcher_(NULL),
midi_dispatcher_(NULL),
#if defined(OS_ANDROID)
media_player_manager_(NULL),
media_session_manager_(NULL),
#endif
+ media_surface_manager_(nullptr),
#if defined(ENABLE_BROWSER_CDMS)
cdm_manager_(NULL),
#endif
@@ -936,6 +1018,7 @@ RenderFrameImpl::RenderFrameImpl(const CreateParams& params)
geolocation_dispatcher_(NULL),
push_messaging_dispatcher_(NULL),
presentation_dispatcher_(NULL),
+ blink_service_registry_(service_registry_.GetWeakPtr()),
screen_orientation_dispatcher_(NULL),
manifest_manager_(NULL),
accessibility_mode_(AccessibilityModeOff),
@@ -943,6 +1026,8 @@ RenderFrameImpl::RenderFrameImpl(const CreateParams& params)
media_player_delegate_(NULL),
is_using_lofi_(false),
is_pasting_(false),
+ suppress_further_dialogs_(false),
+ blame_context_(nullptr),
weak_factory_(this) {
std::pair<RoutingIDFrameMap::iterator, bool> result =
g_routing_id_frame_map.Get().insert(std::make_pair(routing_id_, this));
@@ -978,17 +1063,6 @@ RenderFrameImpl::~RenderFrameImpl() {
#endif
if (is_main_frame_) {
- // When using swapped out frames, RenderFrameProxy is owned by
- // RenderFrameImpl in the case it is the main frame. Ensure it is deleted
- // along with this object.
- if (render_frame_proxy_ &&
- !SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- // The following method calls back into this object and clears
- // |render_frame_proxy_|.
- render_frame_proxy_->frameDetached(
- blink::WebRemoteFrameClient::DetachType::Remove);
- }
-
// Ensure the RenderView doesn't point to this object, once it is destroyed.
// TODO(nasko): Add a check that the |main_render_frame_| of |render_view_|
// is |this|, once the object is no longer leaked.
@@ -1028,17 +1102,14 @@ void RenderFrameImpl::Initialize() {
"parent", parent_id);
}
- if (IsMainFrame() &&
- RenderProcess::current()->GetEnabledBindings() & BINDINGS_POLICY_WEB_UI) {
- EnableMojoBindings();
- }
+ MaybeEnableMojoBindings();
#if defined(ENABLE_PLUGINS)
new PepperBrowserConnection(this);
#endif
new SharedWorkerRepository(this);
- if (IsLocalRoot() && !is_swapped_out_) {
+ if (IsLocalRoot()) {
// DevToolsAgent is a RenderFrameObserver, and will destruct itself
// when |this| is deleted.
devtools_agent_ = new DevToolsAgent(this);
@@ -1051,6 +1122,12 @@ void RenderFrameImpl::Initialize() {
GetContentClient()->renderer()->RenderFrameCreated(this);
}
+void RenderFrameImpl::InitializeBlameContext(RenderFrameImpl* parent_frame) {
+ DCHECK(!blame_context_);
+ blame_context_ = new FrameBlameContext(this, parent_frame);
+ blame_context_->Initialize();
+}
+
RenderWidget* RenderFrameImpl::GetRenderWidget() {
RenderFrameImpl* local_root =
RenderFrameImpl::FromWebFrame(frame_->localRoot());
@@ -1151,7 +1228,8 @@ void RenderFrameImpl::SimulateImeSetComposition(
int selection_start,
int selection_end) {
render_view_->OnImeSetComposition(
- text, underlines, selection_start, selection_end);
+ text, underlines, gfx::Range::InvalidRange(),
+ selection_start, selection_end);
}
void RenderFrameImpl::SimulateImeConfirmComposition(
@@ -1252,12 +1330,6 @@ bool RenderFrameImpl::Send(IPC::Message* message) {
delete message;
return false;
}
- if (is_swapped_out_) {
- if (!SwappedOutMessages::CanSendWhileSwappedOut(message)) {
- delete message;
- return false;
- }
- }
return RenderThread::Get()->Send(message);
}
@@ -1271,6 +1343,14 @@ void RenderFrameImpl::DidHideExternalPopupMenu() {
#endif
bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) {
+ // Forward Page IPCs to the RenderView.
+ if ((IPC_MESSAGE_CLASS(msg) == PageMsgStart)) {
+ if (render_view())
+ return render_view()->OnMessageReceived(msg);
+
+ return false;
+ }
+
// We may get here while detaching, when the WebFrame has been deleted. Do
// not process any messages in this state.
if (!frame_)
@@ -1336,6 +1416,7 @@ bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(FrameMsg_SetEditableSelectionOffsets,
OnSetEditableSelectionOffsets)
IPC_MESSAGE_HANDLER(FrameMsg_Reload, OnReload)
+ IPC_MESSAGE_HANDLER(FrameMsg_ReloadLoFiImages, OnReloadLoFiImages)
IPC_MESSAGE_HANDLER(FrameMsg_TextSurroundingSelectionRequest,
OnTextSurroundingSelectionRequest)
IPC_MESSAGE_HANDLER(FrameMsg_SetAccessibilityMode,
@@ -1358,7 +1439,15 @@ bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(FrameMsg_GetSerializedHtmlWithLocalLinks,
OnGetSerializedHtmlWithLocalLinks)
IPC_MESSAGE_HANDLER(FrameMsg_SerializeAsMHTML, OnSerializeAsMHTML)
+ IPC_MESSAGE_HANDLER(FrameMsg_Find, OnFind)
+ IPC_MESSAGE_HANDLER(FrameMsg_StopFinding, OnStopFinding)
+ IPC_MESSAGE_HANDLER(FrameMsg_EnableViewSourceMode, OnEnableViewSourceMode)
+ IPC_MESSAGE_HANDLER(FrameMsg_SuppressFurtherDialogs,
+ OnSuppressFurtherDialogs)
#if defined(OS_ANDROID)
+ IPC_MESSAGE_HANDLER(InputMsg_ActivateNearestFindResult,
+ OnActivateNearestFindResult)
+ IPC_MESSAGE_HANDLER(FrameMsg_FindMatchRects, OnFindMatchRects)
IPC_MESSAGE_HANDLER(FrameMsg_SelectPopupMenuItems, OnSelectPopupMenuItems)
#elif defined(OS_MACOSX)
IPC_MESSAGE_HANDLER(FrameMsg_SelectPopupMenuItem, OnSelectPopupMenuItem)
@@ -1397,22 +1486,9 @@ void RenderFrameImpl::OnNavigate(
scoped_ptr<StreamOverrideParameters>());
}
-void RenderFrameImpl::NavigateToSwappedOutURL() {
- // We use loadRequest instead of loadHTMLString because the former commits
- // synchronously. Otherwise a new navigation can interrupt the navigation
- // to kSwappedOutURL. If that happens to be to the page we had been
- // showing, then WebKit will never send a commit and we'll be left spinning.
- // Set the is_swapped_out_ bit to true, so IPC filtering is in effect and
- // the navigation to swappedout:// is not announced to the browser side.
- is_swapped_out_ = true;
- GURL swappedOutURL(kSwappedOutURL);
- WebURLRequest request(swappedOutURL);
- frame_->loadRequest(request);
-}
-
void RenderFrameImpl::BindServiceRegistry(
- mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services) {
+ mojo::shell::mojom::InterfaceProviderRequest services,
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services) {
service_registry_.Bind(std::move(services));
service_registry_.BindRemoteServiceProvider(std::move(exposed_services));
}
@@ -1448,92 +1524,66 @@ void RenderFrameImpl::OnSwapOut(
const FrameReplicationState& replicated_frame_state) {
TRACE_EVENT1("navigation", "RenderFrameImpl::OnSwapOut", "id", routing_id_);
RenderFrameProxy* proxy = NULL;
- bool swapped_out_forbidden =
- SiteIsolationPolicy::IsSwappedOutStateForbidden();
// This codepath should only be hit for subframes when in --site-per-process.
CHECK(is_main_frame_ || SiteIsolationPolicy::AreCrossProcessFramesPossible());
- // Only run unload if we're not swapped out yet, but send the ack either way.
- if (!is_swapped_out_) {
- // Swap this RenderFrame out so the frame can navigate to a page rendered by
- // a different process. This involves running the unload handler and
- // clearing the page. We also allow this process to exit if there are no
- // other active RenderFrames in it.
+ // Swap this RenderFrame out so the frame can navigate to a page rendered by
+ // a different process. This involves running the unload handler and
+ // clearing the page. We also allow this process to exit if there are no
+ // other active RenderFrames in it.
- // Send an UpdateState message before we get swapped out.
- if (SiteIsolationPolicy::UseSubframeNavigationEntries())
- SendUpdateState();
- else
- render_view_->SendUpdateState();
-
- // If we need a proxy to replace this, create it now so its routing id is
- // registered for receiving IPC messages.
- if (proxy_routing_id != MSG_ROUTING_NONE) {
- proxy = RenderFrameProxy::CreateProxyToReplaceFrame(
- this, proxy_routing_id, replicated_frame_state.scope);
- }
+ // Send an UpdateState message before we get deleted.
+ if (SiteIsolationPolicy::UseSubframeNavigationEntries())
+ SendUpdateState();
+ else
+ render_view_->SendUpdateState();
- // Synchronously run the unload handler before sending the ACK.
- // TODO(creis): Call dispatchUnloadEvent unconditionally here to support
- // unload on subframes as well.
- if (is_main_frame_)
- frame_->dispatchUnloadEvent();
-
- // Swap out and stop sending any IPC messages that are not ACKs.
- if (is_main_frame_)
- render_view_->SetSwappedOut(true);
- is_swapped_out_ = true;
-
- // Set the proxy here, since OnStop() below could cause an onload event
- // handler to execute, which could trigger code such as
- // willCheckAndDispatchMessageEvent() that needs the proxy.
- if (proxy)
- set_render_frame_proxy(proxy);
-
- // Now that we're swapped out and filtering IPC messages, stop loading to
- // ensure that no other in-progress navigation continues. We do this here
- // to avoid sending a DidStopLoading message to the browser process.
- // TODO(creis): Should we be stopping all frames here and using
- // StopAltErrorPageFetcher with RenderView::OnStop, or just stopping this
- // frame?
- if (!swapped_out_forbidden)
- OnStop();
-
- // Transfer settings such as initial drawing parameters to the remote frame,
- // if one is created, that will replace this frame.
- if (!is_main_frame_ && proxy)
- proxy->web_frame()->initializeFromFrame(frame_);
-
- // Replace the page with a blank dummy URL. The unload handler will not be
- // run a second time, thanks to a check in FrameLoader::stopLoading.
- // TODO(creis): Need to add a better way to do this that avoids running the
- // beforeunload handler. For now, we just run it a second time silently.
- if (!swapped_out_forbidden)
- NavigateToSwappedOutURL();
-
- // Let WebKit know that this view is hidden so it can drop resources and
- // stop compositing.
- // TODO(creis): Support this for subframes as well.
- if (is_main_frame_) {
- render_view_->webview()->setVisibilityState(
- blink::WebPageVisibilityStateHidden, false);
- }
+ // If we need a proxy to replace this, create it now so its routing id is
+ // registered for receiving IPC messages.
+ if (proxy_routing_id != MSG_ROUTING_NONE) {
+ proxy = RenderFrameProxy::CreateProxyToReplaceFrame(
+ this, proxy_routing_id, replicated_frame_state.scope);
}
- // It is now safe to show modal dialogs again.
- // TODO(creis): Deal with modal dialogs from subframes.
+ // Synchronously run the unload handler before sending the ACK.
+ // TODO(creis): Call dispatchUnloadEvent unconditionally here to support
+ // unload on subframes as well.
if (is_main_frame_)
- render_view_->suppress_dialogs_until_swap_out_ = false;
+ frame_->dispatchUnloadEvent();
+
+ // Swap out and stop sending any IPC messages that are not ACKs.
+ if (is_main_frame_)
+ render_view_->SetSwappedOut(true);
+
+ // Set the proxy here, since OnStop() below could cause an onload event
+ // handler to execute, which could trigger code such as
+ // willCheckAndDispatchMessageEvent() that needs the proxy.
+ if (proxy)
+ set_render_frame_proxy(proxy);
+
+ // Transfer settings such as initial drawing parameters to the remote frame,
+ // if one is created, that will replace this frame.
+ if (!is_main_frame_ && proxy)
+ proxy->web_frame()->initializeFromFrame(frame_);
+
+ // Let WebKit know that this view is hidden so it can drop resources and
+ // stop compositing.
+ // TODO(creis): Support this for subframes as well.
+ if (is_main_frame_) {
+ render_view_->webview()->setVisibilityState(
+ blink::WebPageVisibilityStateHidden, false);
+ }
Send(new FrameHostMsg_SwapOut_ACK(routing_id_));
RenderViewImpl* render_view = render_view_.get();
bool is_main_frame = is_main_frame_;
+ int routing_id = GetRoutingID();
// Now that all of the cleanup is complete and the browser side is notified,
// start using the RenderFrameProxy, if one is created.
- if (proxy && swapped_out_forbidden) {
+ if (proxy) {
// The swap call deletes this RenderFrame via frameDetached. Do not access
// any members after this call.
// TODO(creis): WebFrame::swap() can return false. Most of those cases
@@ -1545,30 +1595,30 @@ void RenderFrameImpl::OnSwapOut(
// For main frames, the swap should have cleared the RenderView's pointer to
// this frame.
- if (is_main_frame)
+ if (is_main_frame) {
+ base::debug::SetCrashKeyValue("swapout_frame_id",
+ base::IntToString(routing_id));
+ base::debug::SetCrashKeyValue("swapout_proxy_id",
+ base::IntToString(proxy->routing_id()));
+ base::debug::SetCrashKeyValue(
+ "swapout_view_id", base::IntToString(render_view->GetRoutingID()));
CHECK(!render_view->main_render_frame_);
+ }
if (is_loading)
proxy->OnDidStartLoading();
}
- // In --site-per-process, initialize the WebRemoteFrame with the replication
- // state passed by the process that is now rendering the frame.
- // TODO(alexmos): We cannot yet do this for swapped-out main frames, because
- // in that case we leave the LocalFrame as the main frame visible to Blink
- // and don't call swap() above. Because swap() is what creates a RemoteFrame
- // in proxy->web_frame(), the RemoteFrame will not exist for main frames.
- // When we do an unconditional swap for all frames, we can remove
- // !is_main_frame below.
- if (proxy && swapped_out_forbidden)
+ // Initialize the WebRemoteFrame with the replication state passed by the
+ // process that is now rendering the frame.
+ if (proxy)
proxy->SetReplicatedState(replicated_frame_state);
// Safe to exit if no one else is using the process.
// TODO(nasko): Remove the dependency on RenderViewImpl here and ref count
// the process based on the lifetime of this RenderFrameImpl object.
- if (is_main_frame) {
+ if (is_main_frame)
render_view->WasSwappedOut();
- }
}
void RenderFrameImpl::OnDeleteFrame() {
@@ -1677,7 +1727,8 @@ void RenderFrameImpl::OnSelectRange(const gfx::Point& base,
Send(new InputHostMsg_SelectRange_ACK(GetRenderWidget()->routing_id()));
base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
- frame_->selectRange(base, extent);
+ frame_->selectRange(render_view_->ConvertWindowPointToViewport(base),
+ render_view_->ConvertWindowPointToViewport(extent));
}
void RenderFrameImpl::OnAdjustSelectionByCharacterOffset(int start_adjust,
@@ -1715,7 +1766,8 @@ void RenderFrameImpl::OnMoveRangeSelectionExtent(const gfx::Point& point) {
GetRenderWidget()->routing_id()));
base::AutoReset<bool> handling_select_range(&handling_select_range_, true);
- frame_->moveRangeSelectionExtent(point);
+ frame_->moveRangeSelectionExtent(
+ render_view_->ConvertWindowPointToViewport(point));
}
void RenderFrameImpl::OnReplace(const base::string16& text) {
@@ -2004,18 +2056,8 @@ void RenderFrameImpl::OnPostMessageEvent(
if (params.source_routing_id != MSG_ROUTING_NONE) {
RenderFrameProxy* source_proxy =
RenderFrameProxy::FromRoutingID(params.source_routing_id);
- if (source_proxy) {
- // Currently, navigating a top-level frame cross-process does not swap
- // the WebLocalFrame for a WebRemoteFrame in the frame tree, and the
- // WebRemoteFrame will not have an associated blink::Frame. If this is
- // the case for |source_proxy|, use the corresponding (swapped-out)
- // WebLocalFrame instead, so that event.source for this message can be
- // set and used properly.
- if (source_proxy->IsMainFrameDetachedFromTree())
- source_frame = source_proxy->render_view()->webview()->mainFrame();
- else
- source_frame = source_proxy->web_frame();
- }
+ if (source_proxy)
+ source_frame = source_proxy->web_frame();
}
// If the message contained MessagePorts, create the corresponding endpoints.
@@ -2056,36 +2098,17 @@ void RenderFrameImpl::OnPostMessageEvent(
frame_->dispatchMessageEventWithOriginCheck(target_origin, msg_event);
}
-#if defined(OS_ANDROID)
-void RenderFrameImpl::OnSelectPopupMenuItems(
- bool canceled,
- const std::vector<int>& selected_indices) {
- // It is possible to receive more than one of these calls if the user presses
- // a select faster than it takes for the show-select-popup IPC message to make
- // it to the browser UI thread. Ignore the extra-messages.
- // TODO(jcivelli): http:/b/5793321 Implement a better fix, as detailed in bug.
- if (!external_popup_menu_)
- return;
-
- external_popup_menu_->DidSelectItems(canceled, selected_indices);
- external_popup_menu_.reset();
-}
-#endif
-
-#if defined(OS_MACOSX)
-void RenderFrameImpl::OnSelectPopupMenuItem(int selected_index) {
- if (external_popup_menu_ == NULL)
- return;
- external_popup_menu_->DidSelectItem(selected_index);
- external_popup_menu_.reset();
+void RenderFrameImpl::OnReload(bool bypass_cache) {
+ frame_->reload(bypass_cache ? WebFrameLoadType::ReloadBypassingCache
+ : WebFrameLoadType::Reload);
}
-#endif
-void RenderFrameImpl::OnReload(bool ignore_cache) {
- frame_->reload(ignore_cache);
+void RenderFrameImpl::OnReloadLoFiImages() {
+ is_using_lofi_ = false;
+ GetWebFrame()->reloadLoFiImages();
}
-void RenderFrameImpl::OnTextSurroundingSelectionRequest(size_t max_length) {
+void RenderFrameImpl::OnTextSurroundingSelectionRequest(uint32_t max_length) {
blink::WebSurroundingText surroundingText;
surroundingText.initialize(frame_->selectionRange(), max_length);
@@ -2105,14 +2128,26 @@ void RenderFrameImpl::OnTextSurroundingSelectionRequest(size_t max_length) {
surroundingText.endOffsetInTextContent()));
}
+bool RenderFrameImpl::SendAndRunNestedMessageLoop(IPC::SyncMessage* message) {
+ // Before Blink asks us to show an alert (etc.), it takes care of doing the
+ // equivalent of WebView::willEnterModalLoop. In this case it is particularly
+ // important that we do not call willEnterModalLoop as that would defer
+ // resource loads for the dialog itself.
+ if (RenderThreadImpl::current()) // Will be NULL during unit tests.
+ RenderThreadImpl::current()->DoNotNotifyWebKitOfModalLoop();
+
+ message->EnableMessagePumping(); // Runs a nested message loop.
+ return Send(message);
+}
+
bool RenderFrameImpl::RunJavaScriptMessage(JavaScriptMessageType type,
const base::string16& message,
const base::string16& default_value,
const GURL& frame_url,
base::string16* result) {
// Don't allow further dialogs if we are waiting to swap out, since the
- // PageGroupLoadDeferrer in our stack prevents it.
- if (render_view()->suppress_dialogs_until_swap_out_)
+ // ScopedPageLoadDeferrer in our stack prevents it.
+ if (suppress_further_dialogs_)
return false;
bool success = false;
@@ -2120,10 +2155,8 @@ bool RenderFrameImpl::RunJavaScriptMessage(JavaScriptMessageType type,
if (!result)
result = &result_temp;
- render_view()->SendAndRunNestedMessageLoop(
- new FrameHostMsg_RunJavaScriptMessage(
- routing_id_, message, default_value, frame_url, type, &success,
- result));
+ SendAndRunNestedMessageLoop(new FrameHostMsg_RunJavaScriptMessage(
+ routing_id_, message, default_value, frame_url, type, &success, result));
return success;
}
@@ -2183,6 +2216,12 @@ int RenderFrameImpl::ShowContextMenu(ContextMenuClient* client,
const ContextMenuParams& params) {
DCHECK(client); // A null client means "internal" when we issue callbacks.
ContextMenuParams our_params(params);
+
+ blink::WebRect position_in_window(params.x, params.y, 0, 0);
+ GetRenderWidget()->convertViewportToWindow(&position_in_window);
+ our_params.x = position_in_window.x;
+ our_params.y = position_in_window.y;
+
our_params.custom_context.request_id = pending_context_menus_.Add(client);
Send(new FrameHostMsg_ContextMenu(routing_id_, our_params));
return our_params.custom_context.request_id;
@@ -2226,11 +2265,6 @@ blink::WebPlugin* RenderFrameImpl::CreatePlugin(
}
#if defined(OS_CHROMEOS)
LOG(WARNING) << "Pepper module/plugin creation failed.";
-#else
- if (info.type == WebPluginInfo::PLUGIN_TYPE_NPAPI) {
- // TODO(jam): change to take RenderFrame.
- return new WebPluginImpl(frame, params, info.path, render_view_, this);
- }
#endif
#endif
return NULL;
@@ -2292,7 +2326,7 @@ void RenderFrameImpl::SetSelectedText(const base::string16& selection_text,
// Use the routing id of Render Widget Host.
Send(new ViewHostMsg_SelectionChanged(GetRenderWidget()->routing_id(),
selection_text,
- offset,
+ static_cast<uint32_t>(offset),
range));
}
@@ -2300,19 +2334,23 @@ void RenderFrameImpl::EnsureMojoBuiltinsAreAvailable(
v8::Isolate* isolate,
v8::Local<v8::Context> context) {
gin::ModuleRegistry* registry = gin::ModuleRegistry::From(context);
- if (registry->available_modules().count(mojo::js::Core::kModuleName))
+ if (registry->available_modules().count(mojo::edk::js::Core::kModuleName))
return;
v8::HandleScope handle_scope(isolate);
+ registry->AddBuiltinModule(isolate, mojo::edk::js::Core::kModuleName,
+ mojo::edk::js::Core::GetModule(isolate));
+ registry->AddBuiltinModule(isolate, mojo::edk::js::Support::kModuleName,
+ mojo::edk::js::Support::GetModule(isolate));
registry->AddBuiltinModule(
- isolate, mojo::js::Core::kModuleName, mojo::js::Core::GetModule(isolate));
- registry->AddBuiltinModule(isolate,
- mojo::js::Support::kModuleName,
- mojo::js::Support::GetModule(isolate));
+ isolate, ServiceRegistryJsWrapper::kPerFrameModuleName,
+ ServiceRegistryJsWrapper::Create(isolate, context, &service_registry_)
+ .ToV8());
registry->AddBuiltinModule(
- isolate,
- ServiceRegistryJsWrapper::kModuleName,
- ServiceRegistryJsWrapper::Create(isolate, &service_registry_).ToV8());
+ isolate, ServiceRegistryJsWrapper::kPerProcessModuleName,
+ ServiceRegistryJsWrapper::Create(
+ isolate, context, RenderThread::Get()->GetServiceRegistry())
+ .ToV8());
}
void RenderFrameImpl::AddMessageToConsole(ConsoleMessageLevel level,
@@ -2355,8 +2393,9 @@ blink::WebPlugin* RenderFrameImpl::createPlugin(
WebPluginInfo info;
std::string mime_type;
bool found = false;
- WebString top_origin = frame->top()->securityOrigin().toString();
- Send(new FrameHostMsg_GetPluginInfo(routing_id_, params.url, GURL(top_origin),
+ WebString top_origin = frame->top()->getSecurityOrigin().toString();
+ Send(new FrameHostMsg_GetPluginInfo(routing_id_, params.url,
+ blink::WebStringToGURL(top_origin),
params.mimeType.utf8(), &found, &info,
&mime_type));
if (!found)
@@ -2371,12 +2410,12 @@ blink::WebPlugin* RenderFrameImpl::createPlugin(
}
blink::WebMediaPlayer* RenderFrameImpl::createMediaPlayer(
- blink::WebLocalFrame* frame,
const blink::WebURL& url,
WebMediaPlayerClient* client,
WebMediaPlayerEncryptedMediaClient* encrypted_client,
WebContentDecryptionModule* initial_cdm,
- const blink::WebString& sink_id) {
+ const blink::WebString& sink_id,
+ WebMediaSession* media_session) {
#if defined(VIDEO_HOLE)
if (!contains_media_player_) {
render_view_->RegisterVideoHoleFrame(this);
@@ -2388,17 +2427,22 @@ blink::WebMediaPlayer* RenderFrameImpl::createMediaPlayer(
blink::WebMediaStreamRegistry::lookupMediaStreamDescriptor(url));
if (!web_stream.isNull())
return CreateWebMediaPlayerForMediaStream(client, sink_id,
- frame->securityOrigin());
+ frame_->getSecurityOrigin());
RenderThreadImpl* render_thread = RenderThreadImpl::current();
- scoped_refptr<media::RestartableAudioRendererSink> audio_renderer_sink =
- render_thread->GetAudioRendererMixerManager()->CreateInput(
- routing_id_, sink_id.utf8(), frame->securityOrigin());
+ scoped_refptr<media::SwitchableAudioRendererSink> audio_renderer_sink =
+ AudioDeviceFactory::NewSwitchableAudioRendererSink(
+ AudioDeviceFactory::kSourceMediaElement, routing_id_, 0,
+ sink_id.utf8(), frame_->getSecurityOrigin());
media::WebMediaPlayerParams::Context3DCB context_3d_cb =
base::Bind(&GetSharedMainThreadContext3D);
scoped_refptr<media::MediaLog> media_log(new RenderMediaLog());
+#if defined(OS_ANDROID)
+ if (!media_surface_manager_)
+ media_surface_manager_ = new RendererSurfaceViewManager(this);
+#endif
media::WebMediaPlayerParams params(
base::Bind(&ContentRendererClient::DeferMediaLoad,
base::Unretained(GetContentClient()->renderer()),
@@ -2409,35 +2453,18 @@ blink::WebMediaPlayer* RenderFrameImpl::createMediaPlayer(
render_thread->compositor_task_runner(), context_3d_cb,
base::Bind(&v8::Isolate::AdjustAmountOfExternalAllocatedMemory,
base::Unretained(blink::mainThreadIsolate())),
- GetMediaPermission(), initial_cdm);
+ initial_cdm, media_surface_manager_, media_session);
#if defined(OS_ANDROID)
- if (!CanUseWebMediaPlayerImpl(url)) {
+ if (GetContentClient()->renderer()->ShouldUseMediaPlayerForURL(url) ||
+ !UseWebMediaPlayerImpl(url)) {
return CreateAndroidWebMediaPlayer(client, encrypted_client, params);
- } else {
- // TODO(dalecurtis): This experiment is temporary and should be removed once
- // we have enough data to support the primacy of the unified media pipeline;
- // see http://crbug.com/533190 for details.
- //
- // Note: It's important to query the field trial state first, to ensure that
- // UMA reports the correct group.
- const std::string group_name =
- base::FieldTrialList::FindFullName("UnifiedMediaPipelineTrial");
- const bool enabled_via_cli =
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableUnifiedMediaPipeline);
- const bool enable_unified_media_pipeline =
- enabled_via_cli ||
- base::StartsWith(group_name, "Enabled", base::CompareCase::SENSITIVE);
-
- if (!enable_unified_media_pipeline)
- return CreateAndroidWebMediaPlayer(client, encrypted_client, params);
}
#endif // defined(OS_ANDROID)
-#if defined(ENABLE_MOJO_MEDIA) && !defined(OS_ANDROID)
+#if defined(ENABLE_MOJO_RENDERER)
scoped_ptr<media::RendererFactory> media_renderer_factory(
- new media::MojoRendererFactory(GetMediaServiceFactory()));
+ new media::MojoRendererFactory(GetMediaInterfaceProvider()));
#else
scoped_ptr<media::RendererFactory> media_renderer_factory =
GetContentClient()->renderer()->CreateMediaRendererFactory(
@@ -2445,17 +2472,20 @@ blink::WebMediaPlayer* RenderFrameImpl::createMediaPlayer(
if (!media_renderer_factory.get()) {
media_renderer_factory.reset(new media::DefaultRendererFactory(
- media_log, render_thread->GetGpuFactories(),
+ media_log, GetDecoderFactory(),
+ base::Bind(&RenderThreadImpl::GetGpuFactories,
+ base::Unretained(render_thread)),
*render_thread->GetAudioHardwareConfig()));
}
-#endif // defined(ENABLE_MOJO_MEDIA) && !defined(OS_ANDROID)
+#endif // defined(ENABLE_MOJO_RENDERER)
- if (!url_index_.get() || url_index_->frame() != frame)
- url_index_.reset(new media::UrlIndex(frame));
+ if (!url_index_.get() || url_index_->frame() != frame_)
+ url_index_.reset(new media::UrlIndex(frame_));
media::WebMediaPlayerImpl* media_player = new media::WebMediaPlayerImpl(
- frame, client, encrypted_client, GetWebMediaPlayerDelegate()->AsWeakPtr(),
- std::move(media_renderer_factory), GetCdmFactory(), url_index_, params);
+ frame_, client, encrypted_client,
+ GetWebMediaPlayerDelegate()->AsWeakPtr(),
+ std::move(media_renderer_factory), url_index_, params);
#if defined(OS_ANDROID) // WMPI_CAST
media_player->SetMediaPlayerManager(GetMediaPlayerManager());
@@ -2474,24 +2504,20 @@ blink::WebMediaSession* RenderFrameImpl::createMediaSession() {
}
blink::WebApplicationCacheHost* RenderFrameImpl::createApplicationCacheHost(
- blink::WebLocalFrame* frame,
blink::WebApplicationCacheHostClient* client) {
- if (!frame || !frame->view())
+ if (!frame_ || !frame_->view())
return NULL;
- DCHECK(!frame_ || frame_ == frame);
return new RendererWebApplicationCacheHostImpl(
- RenderViewImpl::FromWebView(frame->view()), client,
+ RenderViewImpl::FromWebView(frame_->view()), client,
RenderThreadImpl::current()->appcache_dispatcher()->backend_proxy());
}
blink::WebWorkerContentSettingsClientProxy*
-RenderFrameImpl::createWorkerContentSettingsClientProxy(
- blink::WebLocalFrame* frame) {
- if (!frame || !frame->view())
+RenderFrameImpl::createWorkerContentSettingsClientProxy() {
+ if (!frame_ || !frame_->view())
return NULL;
- DCHECK(!frame_ || frame_ == frame);
return GetContentClient()->renderer()->CreateWorkerContentSettingsClientProxy(
- this, frame);
+ this, frame_);
}
WebExternalPopupMenu* RenderFrameImpl::createExternalPopupMenu(
@@ -2519,21 +2545,24 @@ WebExternalPopupMenu* RenderFrameImpl::createExternalPopupMenu(
#endif
}
-blink::WebCookieJar* RenderFrameImpl::cookieJar(blink::WebLocalFrame* frame) {
- DCHECK(!frame_ || frame_ == frame);
+blink::WebCookieJar* RenderFrameImpl::cookieJar() {
return &cookie_jar_;
}
-blink::WebServiceWorkerProvider* RenderFrameImpl::createServiceWorkerProvider(
- blink::WebLocalFrame* frame) {
- DCHECK(!frame_ || frame_ == frame);
+blink::BlameContext* RenderFrameImpl::frameBlameContext() {
+ DCHECK(blame_context_);
+ return blame_context_;
+}
+
+blink::WebServiceWorkerProvider*
+RenderFrameImpl::createServiceWorkerProvider() {
// At this point we should have non-null data source.
- DCHECK(frame->dataSource());
+ DCHECK(frame_->dataSource());
if (!ChildThreadImpl::current())
return nullptr; // May be null in some tests.
ServiceWorkerNetworkProvider* provider =
ServiceWorkerNetworkProvider::FromDocumentState(
- DocumentState::FromDataSource(frame->dataSource()));
+ DocumentState::FromDataSource(frame_->dataSource()));
DCHECK(provider);
if (!provider->context()) {
// The context can be null when the frame is sandboxed.
@@ -2544,14 +2573,13 @@ blink::WebServiceWorkerProvider* RenderFrameImpl::createServiceWorkerProvider(
provider->context());
}
-void RenderFrameImpl::didAccessInitialDocument(blink::WebLocalFrame* frame) {
- DCHECK(!frame_ || frame_ == frame);
+void RenderFrameImpl::didAccessInitialDocument() {
// If the request hasn't yet committed, notify the browser process that it is
// no longer safe to show the pending URL of the main frame, since a URL spoof
// is now possible. (If the request has committed, the browser already knows.)
- if (!frame->parent()) {
+ if (!frame_->parent()) {
DocumentState* document_state =
- DocumentState::FromDataSource(frame->dataSource());
+ DocumentState::FromDataSource(frame_->dataSource());
NavigationStateImpl* navigation_state =
static_cast<NavigationStateImpl*>(document_state->navigation_state());
@@ -2565,18 +2593,24 @@ blink::WebFrame* RenderFrameImpl::createChildFrame(
blink::WebLocalFrame* parent,
blink::WebTreeScopeType scope,
const blink::WebString& name,
+ const blink::WebString& unique_name,
blink::WebSandboxFlags sandbox_flags,
- const blink::WebFrameOwnerProperties& frameOwnerProperties) {
+ const blink::WebFrameOwnerProperties& frame_owner_properties) {
// Synchronously notify the browser of a child frame creation to get the
// routing_id for the RenderFrame.
int child_routing_id = MSG_ROUTING_NONE;
- Send(new FrameHostMsg_CreateChildFrame(
- routing_id_, scope, base::UTF16ToUTF8(base::StringPiece16(name)),
- sandbox_flags, frameOwnerProperties, &child_routing_id));
+ FrameHostMsg_CreateChildFrame_Params params;
+ params.parent_routing_id = routing_id_;
+ params.scope = scope;
+ params.frame_name = base::UTF16ToUTF8(base::StringPiece16(name));
+ params.frame_unique_name =
+ base::UTF16ToUTF8(base::StringPiece16(unique_name));
+ params.sandbox_flags = sandbox_flags;
+ params.frame_owner_properties = frame_owner_properties;
+ Send(new FrameHostMsg_CreateChildFrame(params, &child_routing_id));
// Allocation of routing id failed, so we can't create a child frame. This can
- // happen if this RenderFrameImpl's IPCs are being filtered when in swapped
- // out state or synchronous IPC message above has failed.
+ // happen if the synchronous IPC message above has failed.
if (child_routing_id == MSG_ROUTING_NONE) {
NOTREACHED() << "Failed to allocate routing id for child frame.";
return nullptr;
@@ -2593,6 +2627,7 @@ blink::WebFrame* RenderFrameImpl::createChildFrame(
// Create the RenderFrame and WebLocalFrame, linking the two.
RenderFrameImpl* child_render_frame = RenderFrameImpl::Create(
render_view_.get(), child_routing_id);
+ child_render_frame->InitializeBlameContext(this);
blink::WebLocalFrame* web_frame =
WebLocalFrame::create(scope, child_render_frame);
child_render_frame->BindToWebFrame(web_frame);
@@ -2606,10 +2641,6 @@ blink::WebFrame* RenderFrameImpl::createChildFrame(
}
void RenderFrameImpl::didChangeOpener(blink::WebFrame* opener) {
- // Only active frames are able to disown their opener.
- if (!opener && is_swapped_out_)
- return;
-
// Only a local frame should be able to update another frame's opener.
DCHECK(!opener || opener->isWebLocalFrame());
@@ -2624,7 +2655,7 @@ void RenderFrameImpl::frameDetached(blink::WebFrame* frame, DetachType type) {
// the parent frame. This is different from createChildFrame() which is
// called on the parent frame.
CHECK(!is_detaching_);
- DCHECK(!frame_ || frame_ == frame);
+ DCHECK_EQ(frame_, frame);
FOR_EACH_OBSERVER(RenderFrameObserver, observers_, FrameDetached());
FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers(),
@@ -2678,17 +2709,15 @@ void RenderFrameImpl::frameFocused() {
}
void RenderFrameImpl::willClose(blink::WebFrame* frame) {
- DCHECK(!frame_ || frame_ == frame);
+ DCHECK_EQ(frame_, frame);
FOR_EACH_OBSERVER(RenderFrameObserver, observers_, FrameWillClose());
FOR_EACH_OBSERVER(RenderViewObserver, render_view_->observers(),
FrameWillClose(frame));
}
-void RenderFrameImpl::didChangeName(blink::WebLocalFrame* frame,
- const blink::WebString& name) {
- DCHECK(!frame_ || frame_ == frame);
-
+void RenderFrameImpl::didChangeName(const blink::WebString& name,
+ const blink::WebString& unique_name) {
// TODO(alexmos): According to https://crbug.com/169110, sending window.name
// updates may have performance implications for benchmarks like SunSpider.
// For now, send these updates only for --site-per-process, which needs to
@@ -2700,7 +2729,8 @@ void RenderFrameImpl::didChangeName(blink::WebLocalFrame* frame,
if (SiteIsolationPolicy::AreCrossProcessFramesPossible() ||
render_view_->renderer_preferences_.report_frame_name_changes) {
Send(new FrameHostMsg_DidChangeName(
- routing_id_, base::UTF16ToUTF8(base::StringPiece16(name))));
+ routing_id_, base::UTF16ToUTF8(base::StringPiece16(name)),
+ base::UTF16ToUTF8(base::StringPiece16(unique_name))));
}
}
@@ -2708,6 +2738,12 @@ void RenderFrameImpl::didEnforceStrictMixedContentChecking() {
Send(new FrameHostMsg_EnforceStrictMixedContentChecking(routing_id_));
}
+void RenderFrameImpl::didUpdateToUniqueOrigin(
+ bool is_potentially_trustworthy_unique_origin) {
+ Send(new FrameHostMsg_UpdateToUniqueOrigin(
+ routing_id_, is_potentially_trustworthy_unique_origin));
+}
+
void RenderFrameImpl::didChangeSandboxFlags(blink::WebFrame* child_frame,
blink::WebSandboxFlags flags) {
Send(new FrameHostMsg_DidChangeSandboxFlags(
@@ -2726,7 +2762,7 @@ void RenderFrameImpl::didMatchCSS(
blink::WebLocalFrame* frame,
const blink::WebVector<blink::WebString>& newly_matching_selectors,
const blink::WebVector<blink::WebString>& stopped_matching_selectors) {
- DCHECK(!frame_ || frame_ == frame);
+ DCHECK_EQ(frame_, frame);
FOR_EACH_OBSERVER(RenderFrameObserver, observers_,
DidMatchCSS(newly_matching_selectors,
@@ -2767,7 +2803,7 @@ void RenderFrameImpl::didAddMessageToConsole(
FOR_EACH_OBSERVER(RenderFrameObserver, observers_,
DetailedConsoleMessageAdded(
message.text, source_name, stack_trace, source_line,
- static_cast<int32_t>(log_severity)));
+ static_cast<uint32_t>(log_severity)));
}
Send(new FrameHostMsg_AddMessageToConsole(
@@ -2800,18 +2836,13 @@ blink::WebHistoryItem RenderFrameImpl::historyItemForNewChildFrame() {
return render_view_->history_controller()->GetItemForNewChildFrame(this);
}
-void RenderFrameImpl::willSendSubmitEvent(blink::WebLocalFrame* frame,
- const blink::WebFormElement& form) {
- DCHECK(!frame_ || frame_ == frame);
-
+void RenderFrameImpl::willSendSubmitEvent(const blink::WebFormElement& form) {
FOR_EACH_OBSERVER(RenderFrameObserver, observers_, WillSendSubmitEvent(form));
}
-void RenderFrameImpl::willSubmitForm(blink::WebLocalFrame* frame,
- const blink::WebFormElement& form) {
- DCHECK(!frame_ || frame_ == frame);
+void RenderFrameImpl::willSubmitForm(const blink::WebFormElement& form) {
DocumentState* document_state =
- DocumentState::FromDataSource(frame->provisionalDataSource());
+ DocumentState::FromDataSource(frame_->provisionalDataSource());
NavigationStateImpl* navigation_state =
static_cast<NavigationStateImpl*>(document_state->navigation_state());
InternalDocumentStateData* internal_data =
@@ -2884,8 +2915,8 @@ void RenderFrameImpl::didCreateDataSource(blink::WebLocalFrame* frame,
if (webview) {
if (WebFrame* old_frame = webview->mainFrame()) {
const WebURLRequest& original_request = datasource->originalRequest();
- const GURL referrer(
- original_request.httpHeaderField(WebString::fromUTF8("Referer")));
+ const GURL referrer(blink::WebStringToGURL(
+ original_request.httpHeaderField(WebString::fromUTF8("Referer"))));
if (!referrer.is_empty() && old_frame->isWebLocalFrame() &&
DocumentState::FromDataSource(old_frame->dataSource())
->was_prefetcher()) {
@@ -2903,18 +2934,18 @@ void RenderFrameImpl::didCreateDataSource(blink::WebLocalFrame* frame,
if (content_initiated) {
const WebURLRequest& request = datasource->request();
- switch (request.cachePolicy()) {
- case WebURLRequest::UseProtocolCachePolicy: // normal load.
+ switch (request.getCachePolicy()) {
+ case WebCachePolicy::UseProtocolCachePolicy: // normal load.
document_state->set_load_type(DocumentState::LINK_LOAD_NORMAL);
break;
- case WebURLRequest::ReloadIgnoringCacheData: // reload.
- case WebURLRequest::ReloadBypassingCache: // end-to-end reload.
+ case WebCachePolicy::ValidatingCacheData: // reload.
+ case WebCachePolicy::BypassingCache: // end-to-end reload.
document_state->set_load_type(DocumentState::LINK_LOAD_RELOAD);
break;
- case WebURLRequest::ReturnCacheDataElseLoad: // allow stale data.
+ case WebCachePolicy::ReturnCacheDataElseLoad: // allow stale data.
document_state->set_load_type(DocumentState::LINK_LOAD_CACHE_STALE_OK);
break;
- case WebURLRequest::ReturnCacheDataDontLoad: // Don't re-post.
+ case WebCachePolicy::ReturnCacheDataDontLoad: // Don't re-post.
document_state->set_load_type(DocumentState::LINK_LOAD_CACHE_ONLY);
break;
default:
@@ -2949,7 +2980,7 @@ void RenderFrameImpl::didCreateDataSource(blink::WebLocalFrame* frame,
void RenderFrameImpl::didStartProvisionalLoad(blink::WebLocalFrame* frame,
double triggering_event_time) {
- DCHECK(!frame_ || frame_ == frame);
+ DCHECK_EQ(frame_, frame);
WebDataSource* ds = frame->provisionalDataSource();
// In fast/loader/stop-provisional-loads.html, we abort the load before this
@@ -2962,10 +2993,6 @@ void RenderFrameImpl::didStartProvisionalLoad(blink::WebLocalFrame* frame,
"url", ds->request().url().string().utf8());
DocumentState* document_state = DocumentState::FromDataSource(ds);
- // We should only navigate to swappedout:// when is_swapped_out_ is true.
- CHECK(ds->request().url() != GURL(kSwappedOutURL) || is_swapped_out_)
- << "Heard swappedout:// when not swapped out.";
-
// Update the request time if WebKit has better knowledge of it.
if (document_state->request_time().is_null() &&
triggering_event_time != 0.0) {
@@ -3003,7 +3030,7 @@ void RenderFrameImpl::didStartProvisionalLoad(blink::WebLocalFrame* frame,
void RenderFrameImpl::didReceiveServerRedirectForProvisionalLoad(
blink::WebLocalFrame* frame) {
- DCHECK(!frame_ || frame_ == frame);
+ DCHECK_EQ(frame_, frame);
// We don't use HistoryController in OOPIF enabled modes.
if (SiteIsolationPolicy::UseSubframeNavigationEntries())
@@ -3018,7 +3045,7 @@ void RenderFrameImpl::didFailProvisionalLoad(
blink::WebHistoryCommitType commit_type) {
TRACE_EVENT1("navigation,benchmark",
"RenderFrameImpl::didFailProvisionalLoad", "id", routing_id_);
- DCHECK(!frame_ || frame_ == frame);
+ DCHECK_EQ(frame_, frame);
WebDataSource* ds = frame->provisionalDataSource();
DCHECK(ds);
@@ -3074,14 +3101,18 @@ void RenderFrameImpl::didCommitProvisionalLoad(
TRACE_EVENT2("navigation", "RenderFrameImpl::didCommitProvisionalLoad",
"id", routing_id_,
"url", GetLoadingUrl().possibly_invalid_spec());
- DCHECK(!frame_ || frame_ == frame);
+ DCHECK_EQ(frame_, frame);
DocumentState* document_state =
DocumentState::FromDataSource(frame->dataSource());
NavigationStateImpl* navigation_state =
static_cast<NavigationStateImpl*>(document_state->navigation_state());
- WebURLResponseExtraDataImpl* extra_data = GetExtraDataFromResponse(
- frame->dataSource()->response());
- is_using_lofi_ = extra_data && extra_data->is_using_lofi();
+ WebURLResponseExtraDataImpl* extra_data =
+ GetExtraDataFromResponse(frame->dataSource()->response());
+ // Only update LoFi state for new main frame documents. Subframes inherit from
+ // the main frame and should not change at commit time.
+ if (is_main_frame_ && !navigation_state->WasWithinSamePage()) {
+ is_using_lofi_ = extra_data && extra_data->is_using_lofi();
+ }
if (proxy_routing_id_ != MSG_ROUTING_NONE) {
RenderFrameProxy* proxy =
@@ -3096,6 +3127,7 @@ void RenderFrameImpl::didCommitProvisionalLoad(
if (!proxy)
return;
+ int proxy_routing_id = proxy_routing_id_;
proxy->web_frame()->swap(frame_);
proxy_routing_id_ = MSG_ROUTING_NONE;
in_frame_tree_ = true;
@@ -3104,6 +3136,19 @@ void RenderFrameImpl::didCommitProvisionalLoad(
// it needs to set RenderViewImpl's pointer for the main frame to itself
// and ensure RenderWidget is no longer in swapped out mode.
if (is_main_frame_) {
+ // Debug cases of https://crbug.com/575245.
+ base::debug::SetCrashKeyValue("commit_frame_id",
+ base::IntToString(GetRoutingID()));
+ base::debug::SetCrashKeyValue("commit_proxy_id",
+ base::IntToString(proxy_routing_id));
+ base::debug::SetCrashKeyValue(
+ "commit_view_id", base::IntToString(render_view_->GetRoutingID()));
+ if (render_view_->main_render_frame_) {
+ base::debug::SetCrashKeyValue(
+ "commit_main_render_frame_id",
+ base::IntToString(
+ render_view_->main_render_frame_->GetRoutingID()));
+ }
CHECK(!render_view_->main_render_frame_);
render_view_->main_render_frame_ = this;
if (render_view_->is_swapped_out())
@@ -3147,16 +3192,9 @@ void RenderFrameImpl::didCommitProvisionalLoad(
// We bump our Page ID to correspond with the new session history entry.
render_view_->page_id_ = render_view_->next_page_id_++;
- // Don't update history list values for kSwappedOutURL, since
- // we don't want to forget the entry that was there, and since we will
- // never come back to kSwappedOutURL. Note that we have to call
- // SendUpdateState and update page_id_ even in this case, so that
- // the current entry gets a state update and so that we don't send a
- // state update to the wrong entry when we swap back in.
DCHECK(!navigation_state->common_params().should_replace_current_entry ||
render_view_->history_list_length_ > 0);
- if (GetLoadingUrl() != GURL(kSwappedOutURL) &&
- !navigation_state->common_params().should_replace_current_entry) {
+ if (!navigation_state->common_params().should_replace_current_entry) {
// Advance our offset in session history, applying the length limit.
// There is now no forward history.
render_view_->history_list_offset_++;
@@ -3228,7 +3266,7 @@ void RenderFrameImpl::didCreateNewDocument(blink::WebLocalFrame* frame) {
}
void RenderFrameImpl::didClearWindowObject(blink::WebLocalFrame* frame) {
- DCHECK(!frame_ || frame_ == frame);
+ DCHECK_EQ(frame_, frame);
int enabled_bindings = render_view_->GetEnabledBindings();
@@ -3247,9 +3285,6 @@ void RenderFrameImpl::didClearWindowObject(blink::WebLocalFrame* frame) {
if (command_line.HasSwitch(cc::switches::kEnableGpuBenchmarking))
GpuBenchmarking::Install(frame);
- if (command_line.HasSwitch(switches::kEnableMemoryBenchmarking))
- MemoryBenchmarkingExtension::Install(frame);
-
if (command_line.HasSwitch(switches::kEnableSkiaBenchmarking))
SkiaBenchmarking::Install(frame);
@@ -3283,10 +3318,27 @@ void RenderFrameImpl::didCreateDocumentElement(blink::WebLocalFrame* frame) {
DidCreateDocumentElement(frame));
}
+void RenderFrameImpl::runScriptsAtDocumentElementAvailable(
+ blink::WebLocalFrame* frame) {
+ DCHECK(!frame_ || frame_ == frame);
+ base::WeakPtr<RenderFrameImpl> weak_self = weak_factory_.GetWeakPtr();
+
+ MojoBindingsController* mojo_bindings_controller =
+ MojoBindingsController::Get(this);
+ if (mojo_bindings_controller)
+ mojo_bindings_controller->RunScriptsAtDocumentStart();
+
+ if (!weak_self.get())
+ return;
+
+ GetContentClient()->renderer()->RunScriptsAtDocumentStart(this);
+ // Do not use |this| or |frame|! ContentClient might have deleted them by now!
+}
+
void RenderFrameImpl::didReceiveTitle(blink::WebLocalFrame* frame,
const blink::WebString& title,
blink::WebTextDirection direction) {
- DCHECK(!frame_ || frame_ == frame);
+ DCHECK_EQ(frame_, frame);
// Ignore all but top level navigations.
if (!frame->parent()) {
base::string16 title16 = title;
@@ -3304,16 +3356,15 @@ void RenderFrameImpl::didReceiveTitle(blink::WebLocalFrame* frame,
void RenderFrameImpl::didChangeIcon(blink::WebLocalFrame* frame,
blink::WebIconURL::Type icon_type) {
- DCHECK(!frame_ || frame_ == frame);
+ DCHECK_EQ(frame_, frame);
// TODO(nasko): Investigate wheather implementation should move here.
render_view_->didChangeIcon(frame, icon_type);
}
-void RenderFrameImpl::didFinishDocumentLoad(blink::WebLocalFrame* frame,
- bool document_is_empty) {
+void RenderFrameImpl::didFinishDocumentLoad(blink::WebLocalFrame* frame) {
TRACE_EVENT1("navigation,benchmark", "RenderFrameImpl::didFinishDocumentLoad",
"id", routing_id_);
- DCHECK(!frame_ || frame_ == frame);
+ DCHECK_EQ(frame_, frame);
WebDataSource* ds = frame->dataSource();
DocumentState* document_state = DocumentState::FromDataSource(ds);
document_state->set_finish_document_load_time(Time::Now());
@@ -3326,6 +3377,26 @@ void RenderFrameImpl::didFinishDocumentLoad(blink::WebLocalFrame* frame,
// Check whether we have new encoding name.
UpdateEncoding(frame, frame->view()->pageEncoding().utf8());
+}
+
+void RenderFrameImpl::runScriptsAtDocumentReady(blink::WebLocalFrame* frame,
+ bool document_is_empty) {
+ DCHECK_EQ(frame_, frame);
+ base::WeakPtr<RenderFrameImpl> weak_self = weak_factory_.GetWeakPtr();
+
+ MojoBindingsController* mojo_bindings_controller =
+ MojoBindingsController::Get(this);
+ if (mojo_bindings_controller)
+ mojo_bindings_controller->RunScriptsAtDocumentReady();
+
+ if (!weak_self.get())
+ return;
+
+ GetContentClient()->renderer()->RunScriptsAtDocumentEnd(this);
+
+ // ContentClient might have deleted |frame| and |this| by now!
+ if (!weak_self.get())
+ return;
// If this is an empty document with an http status code indicating an error,
// we may want to display our own error page, so the user doesn't end up
@@ -3354,12 +3425,14 @@ void RenderFrameImpl::didFinishDocumentLoad(blink::WebLocalFrame* frame,
error.unreachableURL = frame->document().url();
error.domain = WebString::fromUTF8(error_domain);
error.reason = http_status_code;
+ // This call may run scripts, e.g. via the beforeunload event.
LoadNavigationErrorPage(frame->dataSource()->request(), error, true);
}
+ // Do not use |this| or |frame| here without checking |weak_self|.
}
void RenderFrameImpl::didHandleOnloadEvents(blink::WebLocalFrame* frame) {
- DCHECK(!frame_ || frame_ == frame);
+ DCHECK_EQ(frame_, frame);
if (!frame->parent()) {
FrameMsg_UILoadMetricsReportType::Value report_type =
static_cast<FrameMsg_UILoadMetricsReportType::Value>(
@@ -3378,7 +3451,7 @@ void RenderFrameImpl::didFailLoad(blink::WebLocalFrame* frame,
blink::WebHistoryCommitType commit_type) {
TRACE_EVENT1("navigation", "RenderFrameImpl::didFailLoad",
"id", routing_id_);
- DCHECK(!frame_ || frame_ == frame);
+ DCHECK_EQ(frame_, frame);
// TODO(nasko): Move implementation here. No state needed.
WebDataSource* ds = frame->dataSource();
DCHECK(ds);
@@ -3404,7 +3477,7 @@ void RenderFrameImpl::didFailLoad(blink::WebLocalFrame* frame,
void RenderFrameImpl::didFinishLoad(blink::WebLocalFrame* frame) {
TRACE_EVENT1("navigation,benchmark", "RenderFrameImpl::didFinishLoad", "id",
routing_id_);
- DCHECK(!frame_ || frame_ == frame);
+ DCHECK_EQ(frame_, frame);
WebDataSource* ds = frame->dataSource();
DocumentState* document_state = DocumentState::FromDataSource(ds);
if (document_state->finish_load_time().is_null()) {
@@ -3419,10 +3492,6 @@ void RenderFrameImpl::didFinishLoad(blink::WebLocalFrame* frame) {
DidFinishLoad(frame));
FOR_EACH_OBSERVER(RenderFrameObserver, observers_, DidFinishLoad());
- // Don't send this message while the frame is swapped out.
- if (is_swapped_out())
- return;
-
Send(new FrameHostMsg_DidFinishLoad(routing_id_,
ds->request().url()));
}
@@ -3432,7 +3501,7 @@ void RenderFrameImpl::didNavigateWithinPage(blink::WebLocalFrame* frame,
blink::WebHistoryCommitType commit_type) {
TRACE_EVENT1("navigation", "RenderFrameImpl::didNavigateWithinPage",
"id", routing_id_);
- DCHECK(!frame_ || frame_ == frame);
+ DCHECK_EQ(frame_, frame);
// If this was a reference fragment navigation that we initiated, then we
// could end up having a non-null pending navigation params. We just need to
// update the ExtraData on the datasource so that others who read the
@@ -3449,8 +3518,7 @@ void RenderFrameImpl::didNavigateWithinPage(blink::WebLocalFrame* frame,
didCommitProvisionalLoad(frame, item, commit_type);
}
-void RenderFrameImpl::didUpdateCurrentHistoryItem(blink::WebLocalFrame* frame) {
- DCHECK(!frame_ || frame_ == frame);
+void RenderFrameImpl::didUpdateCurrentHistoryItem() {
render_view_->StartNavStateSyncTimerIfNecessary(this);
}
@@ -3540,28 +3608,19 @@ bool RenderFrameImpl::runModalPromptDialog(
return ok;
}
-bool RenderFrameImpl::runModalBeforeUnloadDialog(
- bool is_reload,
- const blink::WebString& message) {
- // If we are swapping out, we have already run the beforeunload handler.
- // TODO(creis): Fix OnSwapOut to clear the frame without running beforeunload
- // at all, to avoid running it twice.
- if (is_swapped_out_)
- return true;
-
+bool RenderFrameImpl::runModalBeforeUnloadDialog(bool is_reload) {
// Don't allow further dialogs if we are waiting to swap out, since the
- // PageGroupLoadDeferrer in our stack prevents it.
- if (render_view()->suppress_dialogs_until_swap_out_)
+ // ScopedPageLoadDeferrer in our stack prevents it.
+ if (suppress_further_dialogs_)
return false;
bool success = false;
// This is an ignored return value, but is included so we can accept the same
// response as RunJavaScriptMessage.
base::string16 ignored_result;
- render_view()->SendAndRunNestedMessageLoop(
- new FrameHostMsg_RunBeforeUnloadConfirm(
- routing_id_, frame_->document().url(), message, is_reload,
- &success, &ignored_result));
+ SendAndRunNestedMessageLoop(new FrameHostMsg_RunBeforeUnloadConfirm(
+ routing_id_, frame_->document().url(), is_reload, &success,
+ &ignored_result));
return success;
}
@@ -3584,7 +3643,7 @@ void RenderFrameImpl::showContextMenu(const blink::WebContextMenuData& data) {
// in the context menu.
// TODO(jcivelli): http://crbug.com/45160 This prevents us from saving large
// data encoded images. We should have a way to save them.
- if (params.src_url.spec().size() > kMaxURLChars)
+ if (params.src_url.spec().size() > url::kMaxURLChars)
params.src_url = GURL();
context_menu_node_ = data.node;
@@ -3608,7 +3667,7 @@ void RenderFrameImpl::willSendRequest(
unsigned identifier,
blink::WebURLRequest& request,
const blink::WebURLResponse& redirect_response) {
- DCHECK(!frame_ || frame_ == frame);
+ DCHECK_EQ(frame_, frame);
// The request my be empty during tests.
if (request.url().isEmpty())
return;
@@ -3617,7 +3676,7 @@ void RenderFrameImpl::willSendRequest(
// requests). This value will be updated during redirects, consistent with
// https://tools.ietf.org/html/draft-west-first-party-cookies-04#section-2.1.1
if (request.firstPartyForCookies().isEmpty()) {
- if (request.frameType() == blink::WebURLRequest::FrameTypeTopLevel) {
+ if (request.getFrameType() == blink::WebURLRequest::FrameTypeTopLevel) {
request.setFirstPartyForCookies(request.url());
} else {
// TODO(nasko): When the top-level frame is remote, there is no document.
@@ -3631,7 +3690,7 @@ void RenderFrameImpl::willSendRequest(
// If we need to set the first party, then we need to set the request's
// initiator as well; it will not be updated during redirects.
- request.setRequestorOrigin(frame->document().securityOrigin());
+ request.setRequestorOrigin(frame->document().getSecurityOrigin());
}
WebDataSource* provisional_data_source = frame->provisionalDataSource();
@@ -3673,9 +3732,9 @@ void RenderFrameImpl::willSendRequest(
WebString custom_user_agent;
WebString requested_with;
scoped_ptr<StreamOverrideParameters> stream_override;
- if (request.extraData()) {
+ if (request.getExtraData()) {
RequestExtraData* old_extra_data =
- static_cast<RequestExtraData*>(request.extraData());
+ static_cast<RequestExtraData*>(request.getExtraData());
custom_user_agent = old_extra_data->custom_user_agent();
if (!custom_user_agent.isNull()) {
@@ -3695,15 +3754,6 @@ void RenderFrameImpl::willSendRequest(
stream_override = old_extra_data->TakeStreamOverrideOwnership();
}
- // Add the default accept header for frame request if it has not been set
- // already.
- if ((request.frameType() == blink::WebURLRequest::FrameTypeTopLevel ||
- request.frameType() == blink::WebURLRequest::FrameTypeNested) &&
- request.httpHeaderField(WebString::fromUTF8(kAcceptHeader)).isEmpty()) {
- request.setHTTPHeaderField(WebString::fromUTF8(kAcceptHeader),
- WebString::fromUTF8(kDefaultAcceptHeader));
- }
-
// Add an empty HTTP origin header for non GET methods if none is currently
// present.
request.addHTTPOriginIfNeeded(WebString());
@@ -3711,22 +3761,11 @@ void RenderFrameImpl::willSendRequest(
// Attach |should_replace_current_entry| state to requests so that, should
// this navigation later require a request transfer, all state is preserved
// when it is re-created in the new process.
- bool should_replace_current_entry = false;
- if (navigation_state->IsContentInitiated()) {
- should_replace_current_entry = data_source->replacesCurrentHistoryItem();
- } else {
- // If the navigation is browser-initiated, the NavigationState contains the
- // correct value instead of the WebDataSource.
- //
- // TODO(davidben): Avoid this awkward duplication of state. See comment on
- // NavigationState::should_replace_current_entry().
- should_replace_current_entry =
- navigation_state->common_params().should_replace_current_entry;
- }
+ bool should_replace_current_entry = data_source->replacesCurrentHistoryItem();
int provider_id = kInvalidServiceWorkerProviderId;
- if (request.frameType() == blink::WebURLRequest::FrameTypeTopLevel ||
- request.frameType() == blink::WebURLRequest::FrameTypeNested) {
+ if (request.getFrameType() == blink::WebURLRequest::FrameTypeTopLevel ||
+ request.getFrameType() == blink::WebURLRequest::FrameTypeNested) {
// |provisionalDataSource| may be null in some content::ResourceFetcher
// use cases, we don't hook those requests.
if (frame->provisionalDataSource()) {
@@ -3758,7 +3797,7 @@ void RenderFrameImpl::willSendRequest(
extra_data->set_render_frame_id(routing_id_);
extra_data->set_is_main_frame(!parent);
extra_data->set_frame_origin(
- GURL(frame->document().securityOrigin().toString()));
+ blink::WebStringToGURL(frame->document().getSecurityOrigin().toString()));
extra_data->set_parent_is_main_frame(parent && !parent->parent());
extra_data->set_parent_render_frame_id(parent_routing_id);
extra_data->set_allow_download(
@@ -3771,8 +3810,8 @@ void RenderFrameImpl::willSendRequest(
navigation_state->start_params().transferred_request_request_id);
extra_data->set_service_worker_provider_id(provider_id);
extra_data->set_stream_override(std::move(stream_override));
- if (request.loFiState() != WebURLRequest::LoFiUnspecified)
- extra_data->set_lofi_state(static_cast<LoFiState>(request.loFiState()));
+ if (request.getLoFiState() != WebURLRequest::LoFiUnspecified)
+ extra_data->set_lofi_state(static_cast<LoFiState>(request.getLoFiState()));
else if (is_main_frame_ && !navigation_state->request_committed())
extra_data->set_lofi_state(navigation_state->common_params().lofi_state);
else
@@ -3787,7 +3826,7 @@ void RenderFrameImpl::willSendRequest(
if (top_document_state) {
// TODO(gavinp): separate out prefetching and prerender field trials
// if the rel=prerender rel type is sticking around.
- if (request.requestContext() == WebURLRequest::RequestContextPrefetch)
+ if (request.getRequestContext() == WebURLRequest::RequestContextPrefetch)
top_document_state->set_was_prefetcher(true);
}
}
@@ -3822,24 +3861,22 @@ void RenderFrameImpl::willSendRequest(
}
void RenderFrameImpl::didReceiveResponse(
- blink::WebLocalFrame* frame,
unsigned identifier,
const blink::WebURLResponse& response) {
- DCHECK(!frame_ || frame_ == frame);
// Only do this for responses that correspond to a provisional data source
// of the top-most frame. If we have a provisional data source, then we
// can't have any sub-resources yet, so we know that this response must
// correspond to a frame load.
- if (!frame->provisionalDataSource() || frame->parent())
+ if (!frame_->provisionalDataSource() || frame_->parent())
return;
// If we are in view source mode, then just let the user see the source of
// the server's error page.
- if (frame->isViewSourceModeEnabled())
+ if (frame_->isViewSourceModeEnabled())
return;
DocumentState* document_state =
- DocumentState::FromDataSource(frame->provisionalDataSource());
+ DocumentState::FromDataSource(frame_->provisionalDataSource());
int http_status_code = response.httpStatusCode();
// Record page load flags.
@@ -3866,10 +3903,8 @@ void RenderFrameImpl::didReceiveResponse(
}
void RenderFrameImpl::didLoadResourceFromMemoryCache(
- blink::WebLocalFrame* frame,
const blink::WebURLRequest& request,
const blink::WebURLResponse& response) {
- DCHECK(!frame_ || frame_ == frame);
// The recipients of this message have no use for data: URLs: they don't
// affect the page's insecure content list and are not in the disk cache. To
// prevent large (1M+) data: URLs from crashing in the IPC system, we simply
@@ -3931,11 +3966,17 @@ void RenderFrameImpl::didChangePerformanceTiming() {
DidChangePerformanceTiming());
}
+void RenderFrameImpl::didObserveLoadingBehavior(
+ blink::WebLoadingBehaviorFlag behavior) {
+ FOR_EACH_OBSERVER(RenderFrameObserver, observers_,
+ DidObserveLoadingBehavior(behavior));
+}
+
void RenderFrameImpl::didCreateScriptContext(blink::WebLocalFrame* frame,
v8::Local<v8::Context> context,
int extension_group,
int world_id) {
- DCHECK(!frame_ || frame_ == frame);
+ DCHECK_EQ(frame_, frame);
FOR_EACH_OBSERVER(RenderFrameObserver, observers_,
DidCreateScriptContext(context, extension_group, world_id));
@@ -3944,7 +3985,7 @@ void RenderFrameImpl::didCreateScriptContext(blink::WebLocalFrame* frame,
void RenderFrameImpl::willReleaseScriptContext(blink::WebLocalFrame* frame,
v8::Local<v8::Context> context,
int world_id) {
- DCHECK(!frame_ || frame_ == frame);
+ DCHECK_EQ(frame_, frame);
FOR_EACH_OBSERVER(RenderFrameObserver,
observers_,
@@ -3952,7 +3993,7 @@ void RenderFrameImpl::willReleaseScriptContext(blink::WebLocalFrame* frame,
}
void RenderFrameImpl::didChangeScrollOffset(blink::WebLocalFrame* frame) {
- DCHECK(!frame_ || frame_ == frame);
+ DCHECK_EQ(frame_, frame);
render_view_->StartNavStateSyncTimerIfNecessary(this);
FOR_EACH_OBSERVER(RenderFrameObserver, observers_, DidChangeScrollOffset());
@@ -3973,27 +4014,23 @@ void RenderFrameImpl::reportFindInPageMatchCount(int request_id,
if (!count)
active_match_ordinal = 0;
- render_view_->Send(new ViewHostMsg_Find_Reply(
- render_view_->GetRoutingID(), request_id, count,
- gfx::Rect(), active_match_ordinal, final_update));
+ Send(new FrameHostMsg_Find_Reply(routing_id_, request_id, count, gfx::Rect(),
+ active_match_ordinal, final_update));
}
void RenderFrameImpl::reportFindInPageSelection(
int request_id,
int active_match_ordinal,
const blink::WebRect& selection_rect) {
- render_view_->Send(new ViewHostMsg_Find_Reply(
- render_view_->GetRoutingID(), request_id, -1, selection_rect,
- active_match_ordinal, false));
+ Send(new FrameHostMsg_Find_Reply(routing_id_, request_id, -1, selection_rect,
+ active_match_ordinal, false));
}
void RenderFrameImpl::requestStorageQuota(
- blink::WebLocalFrame* frame,
blink::WebStorageQuotaType type,
unsigned long long requested_size,
blink::WebStorageQuotaCallbacks callbacks) {
- DCHECK(!frame_ || frame_ == frame);
- WebSecurityOrigin origin = frame->document().securityOrigin();
+ WebSecurityOrigin origin = frame_->document().getSecurityOrigin();
if (origin.isUnique()) {
// Unique origins cannot store persistent state.
callbacks.didFail(blink::WebStorageQuotaErrorAbort);
@@ -4001,7 +4038,7 @@ void RenderFrameImpl::requestStorageQuota(
}
ChildThreadImpl::current()->quota_dispatcher()->RequestStorageQuota(
render_view_->GetRoutingID(),
- GURL(origin.toString()),
+ blink::WebStringToGURL(origin.toString()),
static_cast<storage::StorageType>(type),
requested_size,
QuotaDispatcher::CreateWebStorageQuotaCallbacksWrapper(callbacks));
@@ -4037,11 +4074,9 @@ blink::WebPushClient* RenderFrameImpl::pushClient() {
}
void RenderFrameImpl::willStartUsingPeerConnectionHandler(
- blink::WebLocalFrame* frame,
blink::WebRTCPeerConnectionHandler* handler) {
- DCHECK(!frame_ || frame_ == frame);
#if defined(ENABLE_WEBRTC)
- static_cast<RTCPeerConnectionHandler*>(handler)->associateWithFrame(frame);
+ static_cast<RTCPeerConnectionHandler*>(handler)->associateWithFrame(frame_);
#endif
}
@@ -4077,19 +4112,9 @@ bool RenderFrameImpl::willCheckAndDispatchMessageEvent(
blink::WebDOMMessageEvent event) {
DCHECK(!frame_ || frame_ == target_frame);
- // Currently, a postMessage that targets a cross-process frame can be plumbed
- // either through this function or RenderFrameProxy::postMessageEvent. This
- // function is used when the target cross-process frame is a top-level frame
- // which has been swapped out. In that case, the corresponding WebLocalFrame
- // currently remains in the frame tree even in site-per-process mode (see
- // OnSwapOut). RenderFrameProxy::postMessageEvent is used in
- // --site-per-process mode for all other cases.
- //
// TODO(alexmos, nasko): When swapped-out:// disappears, this should be
// cleaned up so that RenderFrameProxy::postMessageEvent is the only path for
// cross-process postMessages.
- if (!is_swapped_out_)
- return false;
// It is possible to get here on a swapped-out frame without a
// |render_frame_proxy_|. This happens when:
@@ -4108,9 +4133,7 @@ bool RenderFrameImpl::willCheckAndDispatchMessageEvent(
return true;
}
-blink::WebString RenderFrameImpl::userAgentOverride(
- blink::WebLocalFrame* frame) {
- DCHECK(!frame_ || frame_ == frame);
+blink::WebString RenderFrameImpl::userAgentOverride() {
if (!render_view_->webview() || !render_view_->webview()->mainFrame() ||
render_view_->renderer_preferences_.user_agent_override.empty()) {
return blink::WebString();
@@ -4139,37 +4162,24 @@ blink::WebString RenderFrameImpl::userAgentOverride(
return blink::WebString();
}
-blink::WebString RenderFrameImpl::doNotTrackValue(blink::WebLocalFrame* frame) {
- DCHECK(!frame_ || frame_ == frame);
+blink::WebString RenderFrameImpl::doNotTrackValue() {
if (render_view_->renderer_preferences_.enable_do_not_track)
return WebString::fromUTF8("1");
return WebString();
}
-bool RenderFrameImpl::allowWebGL(blink::WebLocalFrame* frame,
- bool default_value) {
- DCHECK(!frame_ || frame_ == frame);
+bool RenderFrameImpl::allowWebGL(bool default_value) {
if (!default_value)
return false;
bool blocked = true;
Send(new FrameHostMsg_Are3DAPIsBlocked(
routing_id_,
- GURL(frame->top()->securityOrigin().toString()),
- THREE_D_API_TYPE_WEBGL,
- &blocked));
+ blink::WebStringToGURL(frame_->top()->getSecurityOrigin().toString()),
+ THREE_D_API_TYPE_WEBGL, &blocked));
return !blocked;
}
-void RenderFrameImpl::didLoseWebGLContext(blink::WebLocalFrame* frame,
- int arb_robustness_status_code) {
- DCHECK(!frame_ || frame_ == frame);
- Send(new FrameHostMsg_DidLose3DContext(
- GURL(frame->top()->securityOrigin().toString()),
- THREE_D_API_TYPE_WEBGL,
- arb_robustness_status_code));
-}
-
blink::WebScreenOrientationClient*
RenderFrameImpl::webScreenOrientationClient() {
if (!screen_orientation_dispatcher_)
@@ -4212,9 +4222,7 @@ void RenderFrameImpl::handleAccessibilityFindInPageResult(
}
}
-void RenderFrameImpl::didChangeManifest(blink::WebLocalFrame* frame) {
- DCHECK(!frame_ || frame_ == frame);
-
+void RenderFrameImpl::didChangeManifest() {
FOR_EACH_OBSERVER(RenderFrameObserver, observers_, DidChangeManifest());
}
@@ -4267,15 +4275,20 @@ void RenderFrameImpl::unregisterProtocolHandler(const WebString& scheme,
}
blink::WebBluetooth* RenderFrameImpl::bluetooth() {
- if (!bluetooth_) {
+ // ChildThreadImpl::current() is null in some tests.
+ if (!bluetooth_ && ChildThreadImpl::current()) {
bluetooth_.reset(new WebBluetoothImpl(
- ChildThreadImpl::current()->thread_safe_sender(), routing_id_));
+ GetServiceRegistry(), ChildThreadImpl::current()->thread_safe_sender(),
+ routing_id_));
}
return bluetooth_.get();
}
blink::WebUSBClient* RenderFrameImpl::usbClient() {
+ if (!base::FeatureList::IsEnabled(features::kWebUsb))
+ return nullptr;
+
if (!usb_client_)
usb_client_.reset(new WebUSBClientImpl(GetServiceRegistry()));
@@ -4361,7 +4374,7 @@ void RenderFrameImpl::SendDidCommitProvisionalLoad(
blink::WebFrame* frame,
blink::WebHistoryCommitType commit_type,
const blink::WebHistoryItem& item) {
- DCHECK(!frame_ || frame_ == frame);
+ DCHECK_EQ(frame_, frame);
WebDataSource* ds = frame->dataSource();
DCHECK(ds);
@@ -4381,6 +4394,7 @@ void RenderFrameImpl::SendDidCommitProvisionalLoad(
params.intended_as_new_entry =
navigation_state->request_params().intended_as_new_entry;
params.did_create_new_entry = commit_type == blink::WebStandardCommit;
+ params.should_replace_current_entry = ds->replacesCurrentHistoryItem();
params.post_id = -1;
params.page_id = render_view_->page_id_;
params.nav_entry_id = navigation_state->request_params().nav_entry_id;
@@ -4402,29 +4416,23 @@ void RenderFrameImpl::SendDidCommitProvisionalLoad(
// Set the origin of the frame. This will be replicated to the corresponding
// RenderFrameProxies in other processes.
- // TODO(alexmos): Origins for URLs with non-standard schemes are excluded due
- // to https://crbug.com/439608 and will be replicated as unique origins.
- if (!is_swapped_out_) {
- std::string scheme = frame->document().securityOrigin().protocol().utf8();
- if (url::IsStandard(scheme.c_str(),
- url::Component(0, static_cast<int>(scheme.length())))) {
- params.origin = frame->document().securityOrigin();
- }
- }
+ params.origin = frame->document().getSecurityOrigin();
params.should_enforce_strict_mixed_content_checking =
frame->shouldEnforceStrictMixedContentChecking();
+ params.has_potentially_trustworthy_unique_origin =
+ frame->document().getSecurityOrigin().isUnique() &&
+ frame->document().getSecurityOrigin().isPotentiallyTrustworthy();
+
// Set the URL to be displayed in the browser UI to the user.
params.url = GetLoadingUrl();
- DCHECK(!is_swapped_out_ || params.url == GURL(kSwappedOutURL));
-
if (frame->document().baseURL() != params.url)
params.base_url = frame->document().baseURL();
GetRedirectChain(ds, &params.redirects);
- params.should_update_history = !ds->hasUnreachableURL() &&
- !response.isMultipartPayload() && (response.httpStatusCode() != 404);
+ params.should_update_history =
+ !ds->hasUnreachableURL() && response.httpStatusCode() != 404;
params.searchable_form_url = internal_data->searchable_form_url();
params.searchable_form_encoding = internal_data->searchable_form_encoding();
@@ -4454,6 +4462,8 @@ void RenderFrameImpl::SendDidCommitProvisionalLoad(
params.item_sequence_number = item.itemSequenceNumber();
params.document_sequence_number = item.documentSequenceNumber();
+ params.is_srcdoc = params.url == GURL(content::kAboutSrcDocURL);
+
if (!frame->parent()) {
// Top-level navigation.
@@ -4538,12 +4548,6 @@ void RenderFrameImpl::SendDidCommitProvisionalLoad(
frame->dataSource()->request().inputPerfMetricReportPolicy());
params.ui_timestamp = base::TimeTicks() + base::TimeDelta::FromSecondsD(
frame->dataSource()->request().uiStartTime());
-
- // This message needs to be sent before any of allowScripts(),
- // allowImages(), allowPlugins() is called for the new page, so that when
- // these functions send a ViewHostMsg_ContentBlocked message, it arrives
- // after the FrameHostMsg_DidCommitProvisionalLoad message.
- Send(new FrameHostMsg_DidCommitProvisionalLoad(routing_id_, params));
} else {
// Subframe navigation: the type depends on whether this navigation
// generated a new session history entry. When they do generate a session
@@ -4557,12 +4561,14 @@ void RenderFrameImpl::SendDidCommitProvisionalLoad(
DCHECK(!navigation_state->request_params().should_clear_history_list);
params.history_list_was_cleared = false;
params.report_type = FrameMsg_UILoadMetricsReportType::NO_REPORT;
-
- // Don't send this message while the subframe is swapped out.
- if (!is_swapped_out())
- Send(new FrameHostMsg_DidCommitProvisionalLoad(routing_id_, params));
}
+ // This message needs to be sent before any of allowScripts(),
+ // allowImages(), allowPlugins() is called for the new page, so that when
+ // these functions send a ViewHostMsg_ContentBlocked message, it arrives
+ // after the FrameHostMsg_DidCommitProvisionalLoad message.
+ Send(new FrameHostMsg_DidCommitProvisionalLoad(routing_id_, params));
+
// If we end up reusing this WebRequest (for example, due to a #ref click),
// we don't want the transition type to persist. Just clear it.
navigation_state->set_transition_type(ui::PAGE_TRANSITION_LINK);
@@ -4572,7 +4578,11 @@ void RenderFrameImpl::didStartLoading(bool to_different_document) {
TRACE_EVENT1("navigation", "RenderFrameImpl::didStartLoading",
"id", routing_id_);
render_view_->FrameDidStartLoading(frame_);
- Send(new FrameHostMsg_DidStartLoading(routing_id_, to_different_document));
+
+ // PlzNavigate: the browser is responsible for knowing the start of all
+ // non-synchronous navigations.
+ if (!IsBrowserSideNavigationEnabled() || !to_different_document)
+ Send(new FrameHostMsg_DidStartLoading(routing_id_, to_different_document));
}
void RenderFrameImpl::didStopLoading() {
@@ -4619,20 +4629,26 @@ void RenderFrameImpl::OnCommitNavigation(
std::move(stream_override));
}
+// PlzNavigate
void RenderFrameImpl::OnFailedNavigation(
const CommonNavigationParams& common_params,
const RequestNavigationParams& request_params,
bool has_stale_copy_in_cache,
int error_code) {
+ DCHECK(IsBrowserSideNavigationEnabled());
bool is_reload = IsReload(common_params.navigation_type);
- bool is_history_navigation = request_params.page_state.IsValid();
- WebURLRequest::CachePolicy cache_policy =
- WebURLRequest::UseProtocolCachePolicy;
RenderFrameImpl::PrepareRenderViewForNavigation(
- common_params.url, request_params, &is_reload, &cache_policy);
+ common_params.url, request_params);
GetContentClient()->SetActiveURL(common_params.url);
+ // If this frame isn't in the same process as the main frame, it may naively
+ // assume that this is the first navigation in the iframe, but this may not
+ // actually be the case. Inform the frame's state machine if this frame has
+ // already committed other loads.
+ if (request_params.has_committed_real_load && frame_->parent())
+ frame_->setCommittedFirstRealLoad();
+
pending_navigation_params_.reset(new NavigationParams(
common_params, StartNavigationParams(), request_params));
@@ -4649,23 +4665,23 @@ void RenderFrameImpl::OnFailedNavigation(
frame_->isViewSourceModeEnabled());
SendFailedProvisionalLoad(failed_request, error, frame_);
+ // This check should have been done on the browser side already.
if (!ShouldDisplayErrorPageForFailedLoad(error_code, common_params.url)) {
- // TODO(avi): Remove this; we shouldn't ever be dropping navigations.
- // http://crbug.com/501960
- Send(new FrameHostMsg_DidDropNavigation(routing_id_));
+ NOTREACHED();
return;
}
// Make sure errors are not shown in view source mode.
frame_->enableViewSourceMode(false);
- // Replace the current history entry in reloads, history navigations and loads
- // of the same url. This corresponds to Blink's notion of a standard
- // commit.
+ // Replace the current history entry in reloads, and loads of the same url.
+ // This corresponds to Blink's notion of a standard commit.
+ // Also replace the current history entry if the browser asked for it
+ // specifically.
// TODO(clamy): see if initial commits in subframes should be handled
// separately.
- bool replace = is_reload || is_history_navigation ||
- common_params.url == GetLoadingUrl();
+ bool replace = is_reload || common_params.url == GetLoadingUrl() ||
+ common_params.should_replace_current_entry;
LoadNavigationErrorPage(failed_request, error, replace);
}
@@ -4690,8 +4706,7 @@ WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation(
#ifdef OS_ANDROID
// The handlenavigation API is deprecated and will be removed once
// crbug.com/325351 is resolved.
- if (info.urlRequest.url() != GURL(kSwappedOutURL) &&
- GetContentClient()->renderer()->HandleNavigation(
+ if (GetContentClient()->renderer()->HandleNavigation(
this, is_content_initiated, render_view_->opener_id_, frame_,
info.urlRequest, info.navigationType, info.defaultPolicy,
is_redirect)) {
@@ -4702,36 +4717,6 @@ WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation(
Referrer referrer(
RenderViewImpl::GetReferrerFromRequest(frame_, info.urlRequest));
- // TODO(nick): Is consulting |is_main_frame| here correct?
- if (SiteIsolationPolicy::IsSwappedOutStateForbidden() && !is_main_frame_) {
- // There's no reason to ignore navigations on subframes, since the swap out
- // logic no longer applies.
- } else {
- if (is_swapped_out_) {
- if (info.urlRequest.url() != GURL(kSwappedOutURL)) {
- // Targeted links may try to navigate a swapped out frame. Allow the
- // browser process to navigate the tab instead. Note that it is also
- // possible for non-targeted navigations (from this view) to arrive
- // here just after we are swapped out. It's ok to send them to the
- // browser, as long as they're for the top level frame.
- // TODO(creis): Ensure this supports targeted form submissions when
- // fixing http://crbug.com/101395.
- if (frame_->parent() == NULL) {
- OpenURL(info.urlRequest.url(), referrer, info.defaultPolicy,
- info.replacesCurrentHistoryItem, false);
- return blink::WebNavigationPolicyIgnore; // Suppress the load here.
- }
-
- // We should otherwise ignore in-process iframe navigations, if they
- // arrive just after we are swapped out.
- return blink::WebNavigationPolicyIgnore;
- }
-
- // Allow kSwappedOutURL to complete.
- return info.defaultPolicy;
- }
- }
-
// Webkit is asking whether to navigate to a new URL.
// This is fine normally, except if we're showing UI from one security
// context and they're trying to navigate to a different context.
@@ -4865,8 +4850,9 @@ WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation(
if (IsBrowserSideNavigationEnabled() &&
info.urlRequest.checkForBrowserSideNavigation() &&
ShouldMakeNetworkRequestForURL(url)) {
- BeginNavigation(&info.urlRequest);
- return blink::WebNavigationPolicyIgnore;
+ BeginNavigation(&info.urlRequest, info.replacesCurrentHistoryItem,
+ info.isClientRedirect);
+ return blink::WebNavigationPolicyHandledByClient;
}
return info.defaultPolicy;
@@ -4891,20 +4877,16 @@ void RenderFrameImpl::OnGetSavableResourceLinks() {
}
void RenderFrameImpl::OnGetSerializedHtmlWithLocalLinks(
- const std::map<GURL, base::FilePath>& url_to_local_path) {
+ const std::map<GURL, base::FilePath>& url_to_local_path,
+ const std::map<int, base::FilePath>& frame_routing_id_to_local_path) {
// Convert input to the canonical way of passing a map into a Blink API.
- std::vector<std::pair<WebURL, WebString>> weburl_to_local_path;
- for (const auto& it : url_to_local_path) {
- const GURL& url = it.first;
- const base::FilePath& local_path = it.second;
- weburl_to_local_path.push_back(std::make_pair(
- WebURL(url), ConvertRelativePathToHtmlAttribute(local_path)));
- }
+ LinkRewritingDelegate delegate(url_to_local_path,
+ frame_routing_id_to_local_path);
// Serialize the frame (without recursing into subframes).
WebFrameSerializer::serialize(GetWebFrame(),
this, // WebFrameSerializerClient.
- weburl_to_local_path);
+ &delegate);
}
void RenderFrameImpl::OnSerializeAsMHTML(
@@ -4956,6 +4938,246 @@ void RenderFrameImpl::OnSerializeAsMHTML(
digests_of_uris_of_serialized_resources));
}
+void RenderFrameImpl::OnFind(int request_id,
+ const base::string16& search_text,
+ const WebFindOptions& options) {
+ // This should only be received on the main frame, since find-in-page is
+ // currently orchestrated by the main frame.
+ if (!is_main_frame_) {
+ NOTREACHED();
+ return;
+ }
+
+ DCHECK(!search_text.empty());
+
+ blink::WebPlugin* plugin = GetWebPluginForFind();
+ // Check if the plugin still exists in the document.
+ if (plugin) {
+ if (options.findNext) {
+ // Just navigate back/forward.
+ plugin->selectFindResult(options.forward);
+ } else {
+ if (!plugin->startFind(search_text, options.matchCase, request_id)) {
+ // Send "no results".
+ SendFindReply(request_id, 0, 0, gfx::Rect(), true);
+ }
+ }
+ return;
+ }
+
+ WebLocalFrame* main_frame = GetWebFrame();
+ WebLocalFrame* focused_frame =
+ render_view_->webview()->focusedFrame()->toWebLocalFrame();
+ // Start searching in the focused frame.
+ WebLocalFrame* search_frame = focused_frame;
+
+ // Check for multiple searchable frames.
+ bool multi_frame = (main_frame->traverseNextLocal(true) != main_frame);
+
+ // If we have multiple frames, we don't want to wrap the search within the
+ // frame, so we check here if we only have |main_frame| in the chain.
+ bool wrap_within_frame = !multi_frame;
+
+ WebRect selection_rect;
+ bool result = false;
+ bool active_now = false;
+
+ // If something is selected when we start searching it means we cannot just
+ // increment the current match ordinal; we need to re-generate it.
+ WebRange current_selection = focused_frame->selectionRange();
+
+ do {
+ result =
+ search_frame->find(request_id, search_text, options, wrap_within_frame,
+ &selection_rect, &active_now);
+
+ if (!result) {
+ // Don't leave text selected as you move to the next frame.
+ search_frame->executeCommand(WebString::fromUTF8("Unselect"),
+ GetFocusedElement());
+
+ // Find the next frame, but skip the invisible ones.
+ do {
+ // What is the next frame to search (we might be going backwards)? Note
+ // that we specify wrap=true so that search_frame never becomes NULL.
+ search_frame = options.forward
+ ? search_frame->traverseNextLocal(true)
+ : search_frame->traversePreviousLocal(true);
+ } while (!search_frame->hasVisibleContent() &&
+ search_frame != focused_frame);
+
+ // Make sure selection doesn't affect the search operation in new frame.
+ search_frame->executeCommand(WebString::fromUTF8("Unselect"),
+ GetFocusedElement());
+
+ // If we have multiple frames and we have wrapped back around to the
+ // focused frame, we need to search it once more allowing wrap within
+ // the frame, otherwise it will report 'no match' if the focused frame has
+ // reported matches, but no frames after the focused_frame contain a
+ // match for the search word(s).
+ if (multi_frame && search_frame == focused_frame) {
+ result = search_frame->find(request_id, search_text, options,
+ true, // Force wrapping.
+ &selection_rect, &active_now);
+ }
+ }
+
+ render_view_->webview()->setFocusedFrame(search_frame);
+ } while (!result && search_frame != focused_frame);
+
+ if (options.findNext && current_selection.isNull() && active_now) {
+ // Force the main_frame to report the actual count.
+ main_frame->increaseMatchCount(0, request_id);
+ } else {
+ // If nothing is found, set result to "0 of 0", otherwise, set it to
+ // "-1 of 1" to indicate that we found at least one item, but we don't know
+ // yet what is active.
+ int ordinal = result ? -1 : 0; // -1 here means we might know more later.
+ int match_count = result ? 1 : 0; // 1 here means possibly more coming.
+
+ // If we find no matches then this will be our last status update.
+ // Otherwise the scoping effort will send more results.
+ bool final_status_update = !result;
+
+ SendFindReply(request_id, match_count, ordinal, selection_rect,
+ final_status_update);
+
+ // Scoping effort begins, starting with the main frame.
+ search_frame = main_frame;
+
+ main_frame->resetMatchCount();
+
+ do {
+ // Cancel all old scoping requests before starting a new one.
+ search_frame->cancelPendingScopingEffort();
+
+ // We don't start another scoping effort unless at least one match has
+ // been found.
+ if (result) {
+ // Start new scoping request. If the scoping function determines that it
+ // needs to scope, it will defer until later.
+ search_frame->scopeStringMatches(request_id, search_text, options,
+ true); // reset the tickmarks
+ }
+
+ // Iterate to the next frame. The frame will not necessarily scope, for
+ // example if it is not visible.
+ search_frame = search_frame->traverseNextLocal(true);
+ } while (search_frame != main_frame);
+ }
+}
+
+void RenderFrameImpl::OnStopFinding(StopFindAction action) {
+ // This should only be received on the main frame, since find-in-page is
+ // currently orchestrated by the main frame.
+ if (!is_main_frame_) {
+ NOTREACHED();
+ return;
+ }
+
+ WebView* view = render_view_->webview();
+ if (!view)
+ return;
+
+ blink::WebPlugin* plugin = GetWebPluginForFind();
+ if (plugin) {
+ plugin->stopFind();
+ return;
+ }
+
+ bool clear_selection = action == STOP_FIND_ACTION_CLEAR_SELECTION;
+ if (clear_selection) {
+ view->focusedFrame()->executeCommand(WebString::fromUTF8("Unselect"),
+ GetFocusedElement());
+ }
+
+ WebLocalFrame* frame = GetWebFrame();
+ while (frame) {
+ frame->stopFinding(clear_selection);
+ frame = frame->traverseNextLocal(false);
+ }
+
+ if (action == STOP_FIND_ACTION_ACTIVATE_SELECTION) {
+ WebFrame* focused_frame = view->focusedFrame();
+ if (focused_frame) {
+ WebDocument doc = focused_frame->document();
+ if (!doc.isNull()) {
+ WebElement element = doc.focusedElement();
+ if (!element.isNull())
+ element.simulateClick();
+ }
+ }
+ }
+}
+
+void RenderFrameImpl::OnEnableViewSourceMode() {
+ DCHECK(frame_);
+ DCHECK(!frame_->parent());
+ frame_->enableViewSourceMode(true);
+}
+
+void RenderFrameImpl::OnSuppressFurtherDialogs() {
+ suppress_further_dialogs_ = true;
+}
+
+#if defined(OS_ANDROID)
+void RenderFrameImpl::OnActivateNearestFindResult(int request_id,
+ float x,
+ float y) {
+ WebRect selection_rect;
+ int ordinal =
+ frame_->selectNearestFindMatch(WebFloatPoint(x, y), &selection_rect);
+ if (ordinal == -1) {
+ // Something went wrong, so send a no-op reply (force the frame to report
+ // the current match count) in case the host is waiting for a response due
+ // to rate-limiting.
+ frame_->increaseMatchCount(0, request_id);
+ return;
+ }
+
+ SendFindReply(request_id, -1 /* number_of_matches */, ordinal, selection_rect,
+ true /* final_update */);
+}
+
+void RenderFrameImpl::OnFindMatchRects(int current_version) {
+ std::vector<gfx::RectF> match_rects;
+
+ int rects_version = frame_->findMatchMarkersVersion();
+ if (current_version != rects_version) {
+ WebVector<WebFloatRect> web_match_rects;
+ frame_->findMatchRects(web_match_rects);
+ match_rects.reserve(web_match_rects.size());
+ for (size_t i = 0; i < web_match_rects.size(); ++i)
+ match_rects.push_back(gfx::RectF(web_match_rects[i]));
+ }
+
+ gfx::RectF active_rect = frame_->activeFindMatchRect();
+ Send(new FrameHostMsg_FindMatchRects_Reply(routing_id_, rects_version,
+ match_rects, active_rect));
+}
+
+void RenderFrameImpl::OnSelectPopupMenuItems(
+ bool canceled,
+ const std::vector<int>& selected_indices) {
+ // It is possible to receive more than one of these calls if the user presses
+ // a select faster than it takes for the show-select-popup IPC message to make
+ // it to the browser UI thread. Ignore the extra-messages.
+ // TODO(jcivelli): http:/b/5793321 Implement a better fix, as detailed in bug.
+ if (!external_popup_menu_)
+ return;
+
+ external_popup_menu_->DidSelectItems(canceled, selected_indices);
+ external_popup_menu_.reset();
+}
+#elif defined(OS_MACOSX)
+void RenderFrameImpl::OnSelectPopupMenuItem(int selected_index) {
+ if (external_popup_menu_ == NULL)
+ return;
+ external_popup_menu_->DidSelectItem(selected_index);
+ external_popup_menu_.reset();
+}
+#endif
+
void RenderFrameImpl::OpenURL(const GURL& url,
const Referrer& referrer,
WebNavigationPolicy policy,
@@ -4969,11 +5191,9 @@ void RenderFrameImpl::OpenURL(const GURL& url,
if (IsBrowserInitiated(pending_navigation_params_.get())) {
// This is necessary to preserve the should_replace_current_entry value on
// cross-process redirects, in the event it was set by a previous process.
- //
- // TODO(davidben): Avoid this awkward duplication of state. See comment on
- // NavigationState::should_replace_current_entry().
- params.should_replace_current_entry =
- pending_navigation_params_->common_params.should_replace_current_entry;
+ WebDataSource* ds = frame_->provisionalDataSource();
+ DCHECK(ds);
+ params.should_replace_current_entry = ds->replacesCurrentHistoryItem();
} else {
params.should_replace_current_entry =
should_replace_current_entry && render_view_->history_list_length_;
@@ -5009,10 +5229,9 @@ void RenderFrameImpl::NavigateInternal(
base::TimeTicks renderer_navigation_start = base::TimeTicks::Now();
bool is_reload = IsReload(common_params.navigation_type);
bool is_history_navigation = request_params.page_state.IsValid();
- WebURLRequest::CachePolicy cache_policy =
- WebURLRequest::UseProtocolCachePolicy;
+ WebCachePolicy cache_policy = WebCachePolicy::UseProtocolCachePolicy;
RenderFrameImpl::PrepareRenderViewForNavigation(
- common_params.url, request_params, &is_reload, &cache_policy);
+ common_params.url, request_params);
GetContentClient()->SetActiveURL(common_params.url);
@@ -5031,7 +5250,7 @@ void RenderFrameImpl::NavigateInternal(
// We cannot reload if we do not have any history state. This happens, for
// example, when recovering from a crash.
is_reload = false;
- cache_policy = WebURLRequest::ReloadIgnoringCacheData;
+ cache_policy = WebCachePolicy::ValidatingCacheData;
}
// If the navigation is for "view source", the WebLocalFrame needs to be put
@@ -5050,16 +5269,12 @@ void RenderFrameImpl::NavigateInternal(
pending_navigation_params_->common_params.navigation_start =
base::TimeTicks();
- // Unless the load is a WebFrameLoadType::Standard, this should remain
- // uninitialized. It will be updated when the load type is determined to be
- // Standard, or after the previous document's unload handler has been
- // triggered. This occurs in UpdateNavigationState.
- // TODO(csharrison) See if we can always use the browser timestamp.
- pending_navigation_params_->common_params.navigation_start =
- base::TimeTicks();
-
- // Create parameters for a standard navigation.
- blink::WebFrameLoadType load_type = blink::WebFrameLoadType::Standard;
+ // Create parameters for a standard navigation, indicating whether it should
+ // replace the current NavigationEntry.
+ blink::WebFrameLoadType load_type =
+ common_params.should_replace_current_entry
+ ? blink::WebFrameLoadType::ReplaceCurrentItem
+ : blink::WebFrameLoadType::Standard;
blink::WebHistoryLoadType history_load_type =
blink::WebHistoryDifferentDocumentLoad;
bool should_load_request = false;
@@ -5067,6 +5282,11 @@ void RenderFrameImpl::NavigateInternal(
WebURLRequest request =
CreateURLRequestForNavigation(common_params, std::move(stream_params),
frame_->isViewSourceModeEnabled());
+
+ // Used to determine whether this frame is actually loading a request as part
+ // of a history navigation.
+ bool has_history_navigation_in_frame = false;
+
#if defined(OS_ANDROID)
request.setHasUserGesture(start_params.has_user_gesture);
#endif
@@ -5081,10 +5301,10 @@ void RenderFrameImpl::NavigateInternal(
// corresponds to a back/forward navigation event. Update the parameters
// depending on the navigation type.
if (is_reload) {
- bool ignore_cache = (common_params.navigation_type ==
- FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE);
- load_type = ignore_cache ? blink::WebFrameLoadType::ReloadFromOrigin
- : blink::WebFrameLoadType::Reload;
+ bool bypass_cache = (common_params.navigation_type ==
+ FrameMsg_Navigate_Type::RELOAD_BYPASSING_CACHE);
+ load_type = bypass_cache ? WebFrameLoadType::ReloadBypassingCache
+ : WebFrameLoadType::Reload;
if (!browser_side_navigation) {
const GURL override_url =
@@ -5105,10 +5325,6 @@ void RenderFrameImpl::NavigateInternal(
scoped_ptr<HistoryEntry> entry =
PageStateToHistoryEntry(request_params.page_state);
if (entry) {
- // Ensure we didn't save the swapped out URL in UpdateState, since the
- // browser should never be telling us to navigate to swappedout://.
- CHECK(entry->root().urlString() != kSwappedOutURL);
-
if (!SiteIsolationPolicy::UseSubframeNavigationEntries()) {
// By default, tell the HistoryController to go the deserialized
// HistoryEntry. This only works if all frames are in the same
@@ -5117,9 +5333,10 @@ void RenderFrameImpl::NavigateInternal(
DCHECK(!browser_side_navigation);
scoped_ptr<NavigationParams> navigation_params(
new NavigationParams(*pending_navigation_params_.get()));
- render_view_->history_controller()->GoToEntry(
- frame_, std::move(entry), std::move(navigation_params),
- cache_policy);
+ has_history_navigation_in_frame =
+ render_view_->history_controller()->GoToEntry(
+ frame_, std::move(entry), std::move(navigation_params),
+ cache_policy);
} else {
// In --site-per-process, the browser process sends a single
// WebHistoryItem destined for this frame.
@@ -5158,9 +5375,7 @@ void RenderFrameImpl::NavigateInternal(
}
}
- if (start_params.is_post && !browser_side_navigation) {
- request.setHTTPMethod(WebString::fromUTF8("POST"));
-
+ if (common_params.method == "POST" && !browser_side_navigation) {
// Set post data.
WebHTTPBody http_body;
http_body.initialize();
@@ -5185,6 +5400,14 @@ void RenderFrameImpl::NavigateInternal(
pending_navigation_params_->common_params.navigation_start =
SanitizeNavigationTiming(load_type, common_params.navigation_start,
renderer_navigation_start);
+
+ // PlzNavigate: check if the navigation being committed originated as a
+ // client redirect.
+ bool is_client_redirect =
+ browser_side_navigation
+ ? !!(common_params.transition & ui::PAGE_TRANSITION_CLIENT_REDIRECT)
+ : false;
+
// Perform a navigation to a data url if needed.
// Note: the base URL might be invalid, so also check the data URL string.
if (!common_params.base_url_for_data_url.is_empty() ||
@@ -5193,13 +5416,33 @@ void RenderFrameImpl::NavigateInternal(
#endif
(browser_side_navigation &&
common_params.url.SchemeIs(url::kDataScheme))) {
- LoadDataURL(common_params, request_params, frame_, load_type);
+ LoadDataURL(common_params, request_params, frame_, load_type,
+ item_for_history_navigation, history_load_type,
+ is_client_redirect);
} else {
+ // The load of the URL can result in this frame being removed. Use a
+ // WeakPtr as an easy way to detect whether this has occured. If so, this
+ // method should return immediately and not touch any part of the object,
+ // otherwise it will result in a use-after-free bug.
+ base::WeakPtr<RenderFrameImpl> weak_this = weak_factory_.GetWeakPtr();
+
// Load the request.
- frame_->toWebLocalFrame()->load(request, load_type,
- item_for_history_navigation,
- history_load_type);
+ frame_->load(request, load_type, item_for_history_navigation,
+ history_load_type, is_client_redirect);
+
+ if (!weak_this)
+ return;
}
+ } else {
+ // The browser expects the frame to be loading this navigation. Inform it
+ // that the load stopped if needed.
+ // Note: in the case of history navigations, |should_load_request| will be
+ // false, and the frame may not have been set in a loading state. Do not
+ // send a stop message if the HistoryController is loading in this frame
+ // nonetheless. This behavior will go away with subframe navigation
+ // entries.
+ if (!frame_->isLoading() && !has_history_navigation_in_frame)
+ Send(new FrameHostMsg_DidStopLoading(routing_id_));
}
// In case LoadRequest failed before didCreateDataSource was called.
@@ -5328,9 +5571,7 @@ RenderFrameImpl::CreateRendererFactory() {
void RenderFrameImpl::PrepareRenderViewForNavigation(
const GURL& url,
- const RequestNavigationParams& request_params,
- bool* is_reload,
- WebURLRequest::CachePolicy* cache_policy) {
+ const RequestNavigationParams& request_params) {
DCHECK(render_view_->webview());
MaybeHandleDebugURL(url);
@@ -5346,34 +5587,11 @@ void RenderFrameImpl::PrepareRenderViewForNavigation(
CHECK_EQ(-1, render_view_->history_list_offset_);
CHECK_EQ(0, render_view_->history_list_length_);
}
-
- if (!is_swapped_out_ || frame_->parent())
- return;
-
- // This is a swapped out main frame, so swap the renderer back in.
- // We marked the view as hidden when swapping the view out, so be sure to
- // reset the visibility state before navigating to the new URL.
- render_view_->webview()->setVisibilityState(
- render_view_->visibilityState(), false);
-
- // If this is an attempt to reload while we are swapped out, we should not
- // reload swappedout://, but the previous page, which is stored in
- // params.state. Setting is_reload to false will treat this like a back
- // navigation to accomplish that.
- *is_reload = false;
- *cache_policy = WebURLRequest::ReloadIgnoringCacheData;
-
- // We refresh timezone when a view is swapped in since timezone
- // can get out of sync when the system timezone is updated while
- // the view is swapped out.
- RenderThreadImpl::NotifyTimezoneChange();
-
- render_view_->SetSwappedOut(false);
- is_swapped_out_ = false;
- return;
}
-void RenderFrameImpl::BeginNavigation(blink::WebURLRequest* request) {
+void RenderFrameImpl::BeginNavigation(blink::WebURLRequest* request,
+ bool should_replace_current_entry,
+ bool is_client_redirect) {
CHECK(IsBrowserSideNavigationEnabled());
DCHECK(request);
// TODO(clamy): Execute the beforeunload event.
@@ -5390,21 +5608,19 @@ void RenderFrameImpl::BeginNavigation(blink::WebURLRequest* request) {
// else in blink.
willSendRequest(frame_, 0, *request, blink::WebURLResponse());
+ // Update the transition type of the request for client side redirects.
+ if (!request->getExtraData())
+ request->setExtraData(new RequestExtraData());
+ if (is_client_redirect) {
+ RequestExtraData* extra_data =
+ static_cast<RequestExtraData*>(request->getExtraData());
+ extra_data->set_transition_type(ui::PageTransitionFromInt(
+ extra_data->transition_type() | ui::PAGE_TRANSITION_CLIENT_REDIRECT));
+ }
+
// TODO(clamy): Same-document navigations should not be sent back to the
// browser.
// TODO(clamy): Data urls should not be sent back to the browser either.
- bool should_replace_current_entry = false;
- WebDataSource* provisional_data_source = frame_->provisionalDataSource();
- WebDataSource* current_data_source = frame_->dataSource();
- WebDataSource* data_source =
- provisional_data_source ? provisional_data_source : current_data_source;
-
- // The current entry can only be replaced if there already is an entry in the
- // history list.
- if (data_source && render_view_->history_list_length_ > 0) {
- should_replace_current_entry = data_source->replacesCurrentHistoryItem();
- }
-
// These values are assumed on the browser side for navigations. These checks
// ensure the renderer has the correct values.
DCHECK_EQ(FETCH_REQUEST_MODE_NAVIGATE,
@@ -5423,18 +5639,22 @@ void RenderFrameImpl::BeginNavigation(blink::WebURLRequest* request) {
Send(new FrameHostMsg_BeginNavigation(
routing_id_,
MakeCommonNavigationParams(request, should_replace_current_entry),
- BeginNavigationParams(
- request->httpMethod().latin1(), GetWebURLRequestHeaders(*request),
- GetLoadFlagsForWebURLRequest(*request), request->hasUserGesture(),
- request->skipServiceWorker(),
- GetRequestContextTypeForWebURLRequest(*request)),
+ BeginNavigationParams(GetWebURLRequestHeaders(*request),
+ GetLoadFlagsForWebURLRequest(*request),
+ request->hasUserGesture(),
+ request->skipServiceWorker(),
+ GetRequestContextTypeForWebURLRequest(*request)),
GetRequestBodyForWebURLRequest(*request)));
}
-void RenderFrameImpl::LoadDataURL(const CommonNavigationParams& params,
- const RequestNavigationParams& request_params,
- WebFrame* frame,
- blink::WebFrameLoadType load_type) {
+void RenderFrameImpl::LoadDataURL(
+ const CommonNavigationParams& params,
+ const RequestNavigationParams& request_params,
+ WebLocalFrame* frame,
+ blink::WebFrameLoadType load_type,
+ blink::WebHistoryItem item_for_history_navigation,
+ blink::WebHistoryLoadType history_load_type,
+ bool is_client_redirect) {
// A loadData request with a specified base URL.
GURL data_url = params.url;
#if defined(OS_ANDROID)
@@ -5456,16 +5676,15 @@ void RenderFrameImpl::LoadDataURL(const CommonNavigationParams& params,
if (net::DataURL::Parse(data_url, &mime_type, &charset, &data)) {
const GURL base_url = params.base_url_for_data_url.is_empty() ?
params.url : params.base_url_for_data_url;
- bool replace = load_type == blink::WebFrameLoadType::ReloadFromOrigin ||
- load_type == blink::WebFrameLoadType::Reload;
+ bool replace = load_type == WebFrameLoadType::ReloadBypassingCache ||
+ load_type == WebFrameLoadType::Reload;
+
frame->loadData(
- WebData(data.c_str(), data.length()),
- WebString::fromUTF8(mime_type),
- WebString::fromUTF8(charset),
- base_url,
+ WebData(data.c_str(), data.length()), WebString::fromUTF8(mime_type),
+ WebString::fromUTF8(charset), base_url,
// Needed so that history-url-only changes don't become reloads.
- params.history_url_for_data_url,
- replace);
+ params.history_url_for_data_url, replace, load_type,
+ item_for_history_navigation, history_load_type, is_client_redirect);
} else {
CHECK(false) << "Invalid URL passed: "
<< params.url.possibly_invalid_spec();
@@ -5481,12 +5700,26 @@ void RenderFrameImpl::SendUpdateState() {
routing_id_, SingleHistoryItemToPageState(current_history_item_)));
}
-void RenderFrameImpl::EnableMojoBindings() {
+void RenderFrameImpl::MaybeEnableMojoBindings() {
+ int enabled_bindings = RenderProcess::current()->GetEnabledBindings();
+ // BINDINGS_POLICY_WEB_UI and BINDINGS_POLICY_MOJO are mutually exclusive.
+ // They both provide access to Mojo bindings, but do so in incompatible ways.
+ const int kMojoAndWebUiBindings =
+ BINDINGS_POLICY_WEB_UI | BINDINGS_POLICY_MOJO;
+ DCHECK_NE(enabled_bindings & kMojoAndWebUiBindings, kMojoAndWebUiBindings);
+
// If an MojoBindingsController already exists for this RenderFrameImpl, avoid
// creating another one. It is not kept as a member, as it deletes itself when
// the frame is destroyed.
- if (!RenderFrameObserverTracker<MojoBindingsController>::Get(this))
- new MojoBindingsController(this);
+ if (RenderFrameObserverTracker<MojoBindingsController>::Get(this))
+ return;
+
+ if (IsMainFrame() &&
+ enabled_bindings & BINDINGS_POLICY_WEB_UI) {
+ new MojoBindingsController(this, false /* for_layout_tests */);
+ } else if (enabled_bindings & BINDINGS_POLICY_MOJO) {
+ new MojoBindingsController(this, true /* for_layout_tests */);
+ }
}
void RenderFrameImpl::SendFailedProvisionalLoad(
@@ -5569,7 +5802,7 @@ void RenderFrameImpl::PopulateDocumentStateFromPending(
// UseProtocolCachePolicy to mean both "normal load" and "determine cache
// policy based on load type, etc".
internal_data->set_cache_policy_override(
- WebURLRequest::UseProtocolCachePolicy);
+ WebCachePolicy::UseProtocolCachePolicy);
}
if (IsReload(pending_navigation_params_->common_params.navigation_type))
@@ -5635,28 +5868,19 @@ WebMediaPlayer* RenderFrameImpl::CreateAndroidWebMediaPlayer(
WebMediaPlayerClient* client,
WebMediaPlayerEncryptedMediaClient* encrypted_client,
const media::WebMediaPlayerParams& params) {
- scoped_refptr<StreamTextureFactory> stream_texture_factory;
- bool enable_texture_copy = false;
- if (SynchronousCompositorFactory* factory =
- SynchronousCompositorFactory::GetInstance()) {
- stream_texture_factory = factory->CreateStreamTextureFactory(routing_id_);
- } else {
- stream_texture_factory =
- RenderThreadImpl::current()->GetStreamTexureFactory();
- enable_texture_copy =
- RenderThreadImpl::current()->sync_compositor_message_filter() !=
- nullptr;
- if (!stream_texture_factory.get()) {
- LOG(ERROR) << "Failed to get stream texture factory!";
- return NULL;
- }
+ scoped_refptr<StreamTextureFactory> stream_texture_factory =
+ RenderThreadImpl::current()->GetStreamTexureFactory();
+ if (!stream_texture_factory.get()) {
+ LOG(ERROR) << "Failed to get stream texture factory!";
+ return NULL;
}
- return new WebMediaPlayerAndroid(frame_, client, encrypted_client,
- GetWebMediaPlayerDelegate()->AsWeakPtr(),
- GetMediaPlayerManager(), GetCdmFactory(),
- stream_texture_factory, routing_id_,
- enable_texture_copy, params);
+ bool enable_texture_copy =
+ RenderThreadImpl::current()->EnableStreamTextureCopy();
+ return new WebMediaPlayerAndroid(
+ frame_, client, encrypted_client,
+ GetWebMediaPlayerDelegate()->AsWeakPtr(), GetMediaPlayerManager(),
+ stream_texture_factory, routing_id_, enable_texture_copy, params);
}
RendererMediaPlayerManager* RenderFrameImpl::GetMediaPlayerManager() {
@@ -5673,41 +5897,26 @@ RendererMediaSessionManager* RenderFrameImpl::GetMediaSessionManager() {
#endif // defined(OS_ANDROID)
-scoped_ptr<media::MediaPermission> RenderFrameImpl::CreateMediaPermissionProxy(
- scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner) {
- MediaPermissionDispatcherImpl* media_permission =
- static_cast<MediaPermissionDispatcherImpl*>(GetMediaPermission());
- return media_permission->CreateProxy(caller_task_runner);
-}
-
media::MediaPermission* RenderFrameImpl::GetMediaPermission() {
- if (!media_permission_dispatcher_)
- media_permission_dispatcher_ = new MediaPermissionDispatcherImpl(this);
- return media_permission_dispatcher_;
+ if (!media_permission_dispatcher_) {
+ media_permission_dispatcher_.reset(new MediaPermissionDispatcher(base::Bind(
+ &RenderFrameImpl::GetInterface<blink::mojom::PermissionService>,
+ base::Unretained(this))));
+ }
+ return media_permission_dispatcher_.get();
}
#if defined(ENABLE_MOJO_MEDIA)
-media::interfaces::ServiceFactory* RenderFrameImpl::GetMediaServiceFactory() {
- if (!media_service_factory_) {
- mojo::ServiceProviderPtr service_provider =
- ConnectToApplication(GURL("mojo:media"));
- mojo::ConnectToService(service_provider.get(), &media_service_factory_);
- media_service_factory_.set_connection_error_handler(
- base::Bind(&RenderFrameImpl::OnMediaServiceFactoryConnectionError,
- base::Unretained(this)));
+mojo::shell::mojom::InterfaceProvider*
+RenderFrameImpl::GetMediaInterfaceProvider() {
+ if (!media_interface_provider_) {
+ media_interface_provider_.reset(new MediaInterfaceProvider(base::Bind(
+ &RenderFrameImpl::ConnectToApplication, base::Unretained(this))));
}
- return media_service_factory_.get();
+ return media_interface_provider_.get();
}
-
-void RenderFrameImpl::OnMediaServiceFactoryConnectionError() {
- // TODO(xhwang): Resetting |media_service_factory_| could cause access
- // violation on the old |media_service_factory_| by outstanding
- // media::CdmFactory or media::RendererFactory. Find a better way to handle
- // this.
- // media_service_factory_.reset();
-}
-#endif
+#endif // defined(ENABLE_MOJO_MEDIA)
bool RenderFrameImpl::AreSecureCodecsSupported() {
#if defined(OS_ANDROID)
@@ -5720,54 +5929,64 @@ bool RenderFrameImpl::AreSecureCodecsSupported() {
}
media::CdmFactory* RenderFrameImpl::GetCdmFactory() {
-#if defined(ENABLE_BROWSER_CDMS)
- if (!cdm_manager_)
- cdm_manager_ = new RendererCdmManager(this);
-#endif // defined(ENABLE_BROWSER_CDMS)
+ if (cdm_factory_)
+ return cdm_factory_.get();
- if (!cdm_factory_) {
- DCHECK(frame_);
+#if defined(ENABLE_MOJO_CDM)
+ if (UseMojoCdm()) {
+ cdm_factory_.reset(new media::MojoCdmFactory(GetMediaInterfaceProvider()));
+ return cdm_factory_.get();
+ }
+#endif // defined(ENABLE_MOJO_CDM)
-#if defined(ENABLE_MOJO_MEDIA)
- cdm_factory_.reset(new media::MojoCdmFactory(GetMediaServiceFactory()));
-#else
- cdm_factory_.reset(new RenderCdmFactory(
#if defined(ENABLE_PEPPER_CDMS)
- base::Bind(&PepperCdmWrapperImpl::Create, frame_)
+ DCHECK(frame_);
+ cdm_factory_.reset(
+ new RenderCdmFactory(base::Bind(&PepperCdmWrapperImpl::Create, frame_)));
#elif defined(ENABLE_BROWSER_CDMS)
- cdm_manager_
-#endif
- ));
-#endif // defined(ENABLE_MOJO_MEDIA)
- }
+ if (!cdm_manager_)
+ cdm_manager_ = new RendererCdmManager(this);
+ cdm_factory_.reset(new RenderCdmFactory(cdm_manager_));
+#endif // defined(ENABLE_PEPPER_CDMS)
return cdm_factory_.get();
}
+media::DecoderFactory* RenderFrameImpl::GetDecoderFactory() {
+#if defined(ENABLE_MOJO_AUDIO_DECODER) || defined(ENABLE_MOJO_VIDEO_DECODER)
+ if (!decoder_factory_) {
+ decoder_factory_.reset(
+ new media::MojoDecoderFactory(GetMediaInterfaceProvider()));
+ }
+#endif
+ return decoder_factory_.get();
+}
+
void RenderFrameImpl::RegisterMojoServices() {
// Only main frame have ImageDownloader service.
if (!frame_->parent()) {
- GetServiceRegistry()->AddService<image_downloader::ImageDownloader>(
- base::Bind(&ImageDownloaderImpl::CreateMojoService,
- base::Unretained(this)));
+ GetServiceRegistry()->AddService(base::Bind(
+ &ImageDownloaderImpl::CreateMojoService, base::Unretained(this)));
}
}
-mojo::ServiceProviderPtr RenderFrameImpl::ConnectToApplication(
+template <typename Interface>
+void RenderFrameImpl::GetInterface(mojo::InterfaceRequest<Interface> request) {
+ GetServiceRegistry()->ConnectToRemoteService(std::move(request));
+}
+
+mojo::shell::mojom::InterfaceProviderPtr RenderFrameImpl::ConnectToApplication(
const GURL& url) {
- if (!mojo_shell_)
- GetServiceRegistry()->ConnectToRemoteService(mojo::GetProxy(&mojo_shell_));
- mojo::ServiceProviderPtr service_provider;
- mojo::URLRequestPtr request(mojo::URLRequest::New());
- request->url = mojo::String::From(url);
- mojo::CapabilityFilterPtr filter(mojo::CapabilityFilter::New());
- mojo::Array<mojo::String> all_interfaces;
- all_interfaces.push_back("*");
- filter->filter.insert("*", std::move(all_interfaces));
- mojo_shell_->ConnectToApplication(
- std::move(request), GetProxy(&service_provider), nullptr,
- std::move(filter), base::Bind(&OnGotContentHandlerID));
- return service_provider;
+ if (!connector_)
+ GetServiceRegistry()->ConnectToRemoteService(mojo::GetProxy(&connector_));
+ mojo::shell::mojom::InterfaceProviderPtr interface_provider;
+ mojo::shell::mojom::IdentityPtr target(mojo::shell::mojom::Identity::New());
+ target->name = url.spec();
+ target->user_id = mojo::shell::mojom::kInheritUserID;
+ target->instance = "";
+ connector_->Connect(std::move(target), GetProxy(&interface_provider), nullptr,
+ nullptr, base::Bind(&OnGotInstanceID));
+ return interface_provider;
}
media::RendererWebMediaPlayerDelegate*
@@ -5781,14 +6000,40 @@ void RenderFrameImpl::checkIfAudioSinkExistsAndIsAuthorized(
const blink::WebString& sink_id,
const blink::WebSecurityOrigin& security_origin,
blink::WebSetSinkIdCallbacks* web_callbacks) {
- media::SwitchOutputDeviceCB callback =
- media::ConvertToSwitchOutputDeviceCB(web_callbacks);
- scoped_refptr<media::AudioOutputDevice> device =
- AudioDeviceFactory::NewOutputDevice(routing_id_, 0, sink_id.utf8(),
- security_origin);
- media::OutputDeviceStatus status = device->GetDeviceStatus();
- device->Stop();
- callback.Run(status);
+ media::OutputDeviceStatusCB callback =
+ media::ConvertToOutputDeviceStatusCB(web_callbacks);
+ callback.Run(AudioDeviceFactory::GetOutputDeviceInfo(
+ routing_id_, 0, sink_id.utf8(), security_origin)
+ .device_status());
+}
+
+blink::ServiceRegistry* RenderFrameImpl::serviceRegistry() {
+ return &blink_service_registry_;
+}
+
+blink::WebPlugin* RenderFrameImpl::GetWebPluginForFind() {
+ if (!is_main_frame_)
+ return nullptr;
+
+ if (frame_->document().isPluginDocument())
+ return frame_->document().to<WebPluginDocument>().plugin();
+
+#if defined(ENABLE_PLUGINS)
+ if (plugin_find_handler_)
+ return plugin_find_handler_->container()->plugin();
+#endif
+
+ return nullptr;
+}
+
+void RenderFrameImpl::SendFindReply(int request_id,
+ int match_count,
+ int ordinal,
+ const WebRect& selection_rect,
+ bool final_status_update) {
+ Send(new FrameHostMsg_Find_Reply(routing_id_, request_id, match_count,
+ selection_rect, ordinal,
+ final_status_update));
}
} // namespace content
diff --git a/chromium/content/renderer/render_frame_impl.h b/chromium/content/renderer/render_frame_impl.h
index 923af0849a4..cd97a785075 100644
--- a/chromium/content/renderer/render_frame_impl.h
+++ b/chromium/content/renderer/render_frame_impl.h
@@ -27,16 +27,21 @@
#include "content/public/common/console_message_level.h"
#include "content/public/common/javascript_message_type.h"
#include "content/public/common/referrer.h"
+#include "content/public/common/stop_find_action.h"
#include "content/public/renderer/render_frame.h"
+#include "content/renderer/frame_blame_context.h"
+#include "content/renderer/mojo/blink_service_registry_impl.h"
#include "content/renderer/render_frame_proxy.h"
#include "content/renderer/renderer_webcookiejar_impl.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_platform_file.h"
#include "media/blink/webmediaplayer_delegate.h"
#include "media/blink/webmediaplayer_params.h"
-#include "mojo/shell/public/interfaces/service_provider.mojom.h"
-#include "mojo/shell/public/interfaces/shell.mojom.h"
+#include "mojo/shell/public/interfaces/connector.mojom.h"
+#include "mojo/shell/public/interfaces/interface_provider.mojom.h"
#include "third_party/WebKit/public/platform/WebFocusType.h"
+#include "third_party/WebKit/public/platform/WebLoadingBehaviorFlag.h"
+#include "third_party/WebKit/public/platform/WebMediaPlayer.h"
#include "third_party/WebKit/public/platform/modules/app_banner/WebAppBannerClient.h"
#include "third_party/WebKit/public/web/WebAXObject.h"
#include "third_party/WebKit/public/web/WebDataSource.h"
@@ -68,18 +73,23 @@ struct FrameMsg_PostMessage_Params;
struct FrameMsg_SerializeAsMHTML_Params;
struct FrameMsg_TextTrackSettings_Params;
+namespace IPC {
+class SyncMessage;
+}
+
namespace blink {
class WebGeolocationClient;
class WebMouseEvent;
class WebContentDecryptionModule;
-class WebMediaPlayer;
class WebPresentationClient;
class WebPushClient;
class WebSecurityOrigin;
class WebWakeLockClient;
+enum class WebCachePolicy;
struct WebCompositionUnderline;
struct WebContextMenuData;
struct WebCursorInfo;
+struct WebFindOptions;
struct WebScreenInfo;
}
@@ -91,9 +101,11 @@ class Rect;
namespace media {
class CdmFactory;
+class DecoderFactory;
class MediaPermission;
class MediaServiceProvider;
class RendererWebMediaPlayerDelegate;
+class SurfaceManager;
class UrlIndex;
class WebEncryptedMediaClientImpl;
}
@@ -115,9 +127,10 @@ class DocumentState;
class ExternalPopupMenu;
class GeolocationDispatcher;
class ManifestManager;
+class MediaInterfaceProvider;
class MediaStreamDispatcher;
class MediaStreamRendererFactory;
-class MediaPermissionDispatcherImpl;
+class MediaPermissionDispatcher;
class MidiDispatcher;
class NavigationState;
class NotificationPermissionDispatcher;
@@ -131,6 +144,7 @@ class RendererCdmManager;
class RendererMediaPlayerManager;
class RendererMediaSessionManager;
class RendererPpapiHost;
+class RendererSurfaceViewManager;
class RenderFrameObserver;
class RenderViewImpl;
class RenderWidget;
@@ -160,7 +174,8 @@ class CONTENT_EXPORT RenderFrameImpl
int32_t widget_routing_id,
bool hidden,
const blink::WebScreenInfo& screen_info,
- CompositorDependencies* compositor_deps);
+ CompositorDependencies* compositor_deps,
+ blink::WebFrame* opener);
// Creates a new RenderFrame with |routing_id|. If |proxy_routing_id| is
// MSG_ROUTING_NONE, it creates the Blink WebLocalFrame and inserts it into
@@ -218,10 +233,6 @@ class CONTENT_EXPORT RenderFrameImpl
~RenderFrameImpl() override;
- bool is_swapped_out() const {
- return is_swapped_out_;
- }
-
// TODO(nasko): This can be removed once we don't have a swapped out state on
// RenderFrames. See https://crbug.com/357747.
void set_render_frame_proxy(RenderFrameProxy* proxy) {
@@ -288,6 +299,14 @@ class CONTENT_EXPORT RenderFrameImpl
void FocusedNodeChangedForAccessibility(const blink::WebNode& node);
#if defined(ENABLE_PLUGINS)
+ // Get/set the plugin which will be used to handle document find requests.
+ void set_plugin_find_handler(PepperPluginInstanceImpl* plugin) {
+ plugin_find_handler_ = plugin;
+ }
+ PepperPluginInstanceImpl* plugin_find_handler() {
+ return plugin_find_handler_;
+ }
+
// Notification that a PPAPI plugin has been created.
void PepperPluginCreated(RendererPpapiHost* host);
@@ -403,38 +422,40 @@ class CONTENT_EXPORT RenderFrameImpl
blink::WebPlugin* createPlugin(blink::WebLocalFrame* frame,
const blink::WebPluginParams& params) override;
blink::WebMediaPlayer* createMediaPlayer(
- blink::WebLocalFrame* frame,
const blink::WebURL& url,
blink::WebMediaPlayerClient* client,
blink::WebMediaPlayerEncryptedMediaClient* encrypted_client,
blink::WebContentDecryptionModule* initial_cdm,
- const blink::WebString& sink_id) override;
+ const blink::WebString& sink_id,
+ blink::WebMediaSession* media_session) override;
blink::WebMediaSession* createMediaSession() override;
blink::WebApplicationCacheHost* createApplicationCacheHost(
- blink::WebLocalFrame* frame,
blink::WebApplicationCacheHostClient* client) override;
blink::WebWorkerContentSettingsClientProxy*
- createWorkerContentSettingsClientProxy(blink::WebLocalFrame* frame) override;
+ createWorkerContentSettingsClientProxy() override;
blink::WebExternalPopupMenu* createExternalPopupMenu(
const blink::WebPopupMenuInfo& popup_menu_info,
blink::WebExternalPopupMenuClient* popup_menu_client) override;
- blink::WebCookieJar* cookieJar(blink::WebLocalFrame* frame) override;
- blink::WebServiceWorkerProvider* createServiceWorkerProvider(
- blink::WebLocalFrame* frame) override;
- void didAccessInitialDocument(blink::WebLocalFrame* frame) override;
+ blink::WebCookieJar* cookieJar() override;
+ blink::BlameContext* frameBlameContext() override;
+ blink::WebServiceWorkerProvider* createServiceWorkerProvider() override;
+ void didAccessInitialDocument() override;
blink::WebFrame* createChildFrame(
blink::WebLocalFrame* parent,
blink::WebTreeScopeType scope,
const blink::WebString& name,
- blink::WebSandboxFlags sandboxFlags,
- const blink::WebFrameOwnerProperties& frameOwnerProperties) override;
+ const blink::WebString& unique_name,
+ blink::WebSandboxFlags sandbox_flags,
+ const blink::WebFrameOwnerProperties& frame_owner_properties) override;
void didChangeOpener(blink::WebFrame* frame) override;
void frameDetached(blink::WebFrame* frame, DetachType type) override;
void frameFocused() override;
void willClose(blink::WebFrame* frame) override;
- void didChangeName(blink::WebLocalFrame* frame,
- const blink::WebString& name) override;
+ void didChangeName(const blink::WebString& name,
+ const blink::WebString& unique_name) override;
void didEnforceStrictMixedContentChecking() override;
+ void didUpdateToUniqueOrigin(
+ bool is_potentially_trustworthy_unique_origin) override;
void didChangeSandboxFlags(blink::WebFrame* child_frame,
blink::WebSandboxFlags flags) override;
void didChangeFrameOwnerProperties(
@@ -458,10 +479,8 @@ class CONTENT_EXPORT RenderFrameImpl
blink::WebNavigationPolicy decidePolicyForNavigation(
const NavigationPolicyInfo& info) override;
blink::WebHistoryItem historyItemForNewChildFrame() override;
- void willSendSubmitEvent(blink::WebLocalFrame* frame,
- const blink::WebFormElement& form) override;
- void willSubmitForm(blink::WebLocalFrame* frame,
- const blink::WebFormElement& form) override;
+ void willSendSubmitEvent(const blink::WebFormElement& form) override;
+ void willSubmitForm(const blink::WebFormElement& form) override;
void didCreateDataSource(blink::WebLocalFrame* frame,
blink::WebDataSource* datasource) override;
void didStartProvisionalLoad(blink::WebLocalFrame* frame,
@@ -478,13 +497,16 @@ class CONTENT_EXPORT RenderFrameImpl
void didCreateNewDocument(blink::WebLocalFrame* frame) override;
void didClearWindowObject(blink::WebLocalFrame* frame) override;
void didCreateDocumentElement(blink::WebLocalFrame* frame) override;
+ void runScriptsAtDocumentElementAvailable(
+ blink::WebLocalFrame* frame) override;
void didReceiveTitle(blink::WebLocalFrame* frame,
const blink::WebString& title,
blink::WebTextDirection direction) override;
void didChangeIcon(blink::WebLocalFrame* frame,
blink::WebIconURL::Type icon_type) override;
- void didFinishDocumentLoad(blink::WebLocalFrame* frame,
- bool document_is_empty) override;
+ void didFinishDocumentLoad(blink::WebLocalFrame* frame) override;
+ void runScriptsAtDocumentReady(blink::WebLocalFrame* frame,
+ bool document_is_empty) override;
void didHandleOnloadEvents(blink::WebLocalFrame* frame) override;
void didFailLoad(blink::WebLocalFrame* frame,
const blink::WebURLError& error,
@@ -493,7 +515,7 @@ class CONTENT_EXPORT RenderFrameImpl
void didNavigateWithinPage(blink::WebLocalFrame* frame,
const blink::WebHistoryItem& item,
blink::WebHistoryCommitType commit_type) override;
- void didUpdateCurrentHistoryItem(blink::WebLocalFrame* frame) override;
+ void didUpdateCurrentHistoryItem() override;
void didChangeThemeColor() override;
void dispatchLoad() override;
void requestNotificationPermission(
@@ -509,19 +531,16 @@ class CONTENT_EXPORT RenderFrameImpl
bool runModalPromptDialog(const blink::WebString& message,
const blink::WebString& default_value,
blink::WebString* actual_value) override;
- bool runModalBeforeUnloadDialog(bool is_reload,
- const blink::WebString& message) override;
+ bool runModalBeforeUnloadDialog(bool is_reload) override;
void showContextMenu(const blink::WebContextMenuData& data) override;
void clearContextMenu() override;
void willSendRequest(blink::WebLocalFrame* frame,
unsigned identifier,
blink::WebURLRequest& request,
const blink::WebURLResponse& redirect_response) override;
- void didReceiveResponse(blink::WebLocalFrame* frame,
- unsigned identifier,
+ void didReceiveResponse(unsigned identifier,
const blink::WebURLResponse& response) override;
void didLoadResourceFromMemoryCache(
- blink::WebLocalFrame* frame,
const blink::WebURLRequest& request,
const blink::WebURLResponse& response) override;
void didDisplayInsecureContent() override;
@@ -538,6 +557,8 @@ class CONTENT_EXPORT RenderFrameImpl
const blink::WebURL& main_resource_url,
const blink::WebCString& main_resource_security_info) override;
void didChangePerformanceTiming() override;
+ void didObserveLoadingBehavior(
+ blink::WebLoadingBehaviorFlag behavior) override;
void didCreateScriptContext(blink::WebLocalFrame* frame,
v8::Local<v8::Context> context,
int extension_group,
@@ -553,8 +574,7 @@ class CONTENT_EXPORT RenderFrameImpl
void reportFindInPageSelection(int request_id,
int active_match_ordinal,
const blink::WebRect& sel) override;
- void requestStorageQuota(blink::WebLocalFrame* frame,
- blink::WebStorageQuotaType type,
+ void requestStorageQuota(blink::WebStorageQuotaType type,
unsigned long long requested_size,
blink::WebStorageQuotaCallbacks callbacks) override;
void willOpenWebSocket(blink::WebSocketHandle* handle) override;
@@ -563,7 +583,6 @@ class CONTENT_EXPORT RenderFrameImpl
blink::WebPushClient* pushClient() override;
blink::WebPresentationClient* presentationClient() override;
void willStartUsingPeerConnectionHandler(
- blink::WebLocalFrame* frame,
blink::WebRTCPeerConnectionHandler* handler) override;
blink::WebUserMediaClient* userMediaClient() override;
blink::WebEncryptedMediaClient* encryptedMediaClient() override;
@@ -573,11 +592,9 @@ class CONTENT_EXPORT RenderFrameImpl
blink::WebFrame* target_frame,
blink::WebSecurityOrigin target_origin,
blink::WebDOMMessageEvent event) override;
- blink::WebString userAgentOverride(blink::WebLocalFrame* frame) override;
- blink::WebString doNotTrackValue(blink::WebLocalFrame* frame) override;
- bool allowWebGL(blink::WebLocalFrame* frame, bool default_value) override;
- void didLoseWebGLContext(blink::WebLocalFrame* frame,
- int arb_robustness_status_code) override;
+ blink::WebString userAgentOverride() override;
+ blink::WebString doNotTrackValue() override;
+ bool allowWebGL(bool default_value) override;
blink::WebScreenOrientationClient* webScreenOrientationClient() override;
bool isControlledByServiceWorker(blink::WebDataSource& data_source) override;
int64_t serviceWorkerID(blink::WebDataSource& data_source) override;
@@ -590,7 +607,7 @@ class CONTENT_EXPORT RenderFrameImpl
int start_offset,
const blink::WebAXObject& end_object,
int end_offset) override;
- void didChangeManifest(blink::WebLocalFrame*) override;
+ void didChangeManifest() override;
bool enterFullscreen() override;
bool exitFullscreen() override;
blink::WebPermissionClient* permissionClient() override;
@@ -606,6 +623,7 @@ class CONTENT_EXPORT RenderFrameImpl
const blink::WebString& sink_id,
const blink::WebSecurityOrigin& security_origin,
blink::WebSetSinkIdCallbacks* web_callbacks) override;
+ blink::ServiceRegistry* serviceRegistry() override;
#if defined(ENABLE_WEBVR)
blink::WebVRClient* webVRClient() override;
@@ -617,14 +635,10 @@ class CONTENT_EXPORT RenderFrameImpl
blink::WebFrameSerializerClient::FrameSerializationStatus status)
override;
- // Make this frame show an empty, unscriptable page.
- // TODO(nasko): Remove this method once swapped out state is no longer used.
- void NavigateToSwappedOutURL();
-
// Binds this render frame's service registry.
void BindServiceRegistry(
- mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services);
+ mojo::shell::mojom::InterfaceProviderRequest services,
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services);
ManifestManager* manifest_manager();
@@ -633,18 +647,16 @@ class CONTENT_EXPORT RenderFrameImpl
void SetPendingNavigationParams(
scoped_ptr<NavigationParams> navigation_params);
- // Expose MediaPermission to the non-UI threads. Any calls to this will be
- // redirected to |media_permission_dispatcher_| on UI thread and have the
- // callback called on |caller_task_runner|.
- scoped_ptr<media::MediaPermission> CreateMediaPermissionProxy(
- scoped_refptr<base::SingleThreadTaskRunner> caller_task_runner);
+ media::MediaPermission* GetMediaPermission();
// Sends the current frame's navigation state to the browser.
void SendUpdateState();
- // Creates a MojoBindingsController to allow WebUI documents to communicate
- // with the browser process.
- void EnableMojoBindings();
+ // Creates a MojoBindingsController if Mojo bindings have been enabled for
+ // this frame. For WebUI, this allows the page to communicate with the browser
+ // process; for layout tests, this allows the test to mock out services at
+ // the Mojo IPC layer.
+ void MaybeEnableMojoBindings();
protected:
explicit RenderFrameImpl(const CreateParams& params);
@@ -760,8 +772,9 @@ class CONTENT_EXPORT RenderFrameImpl
const std::vector<blink::WebCompositionUnderline>& underlines);
void OnExecuteNoValueEditCommand(const std::string& name);
void OnExtendSelectionAndDelete(int before, int after);
- void OnReload(bool ignore_cache);
- void OnTextSurroundingSelectionRequest(size_t max_length);
+ void OnReload(bool bypass_cache);
+ void OnReloadLoFiImages();
+ void OnTextSurroundingSelectionRequest(uint32_t max_length);
void OnSetAccessibilityMode(AccessibilityMode new_mode);
void OnSnapshotAccessibilityTree(int callback_id);
void OnUpdateOpener(int opener_routing_id);
@@ -773,14 +786,6 @@ class CONTENT_EXPORT RenderFrameImpl
void OnTextTrackSettingsChanged(
const FrameMsg_TextTrackSettings_Params& params);
void OnPostMessageEvent(const FrameMsg_PostMessage_Params& params);
-#if defined(OS_ANDROID)
- void OnSelectPopupMenuItems(bool canceled,
- const std::vector<int>& selected_indices);
-#elif defined(OS_MACOSX)
- void OnSelectPopupMenuItem(int selected_index);
- void OnCopyToFindPboard();
-#endif
-
void OnCommitNavigation(const ResourceResponseHead& response,
const GURL& stream_url,
const CommonNavigationParams& common_params,
@@ -791,8 +796,24 @@ class CONTENT_EXPORT RenderFrameImpl
int error_code);
void OnGetSavableResourceLinks();
void OnGetSerializedHtmlWithLocalLinks(
- const std::map<GURL, base::FilePath>& url_to_local_path);
+ const std::map<GURL, base::FilePath>& url_to_local_path,
+ const std::map<int, base::FilePath>& frame_routing_id_to_local_path);
void OnSerializeAsMHTML(const FrameMsg_SerializeAsMHTML_Params& params);
+ void OnFind(int request_id,
+ const base::string16& search_text,
+ const blink::WebFindOptions& options);
+ void OnStopFinding(StopFindAction action);
+ void OnEnableViewSourceMode();
+ void OnSuppressFurtherDialogs();
+#if defined(OS_ANDROID)
+ void OnActivateNearestFindResult(int request_id, float x, float y);
+ void OnFindMatchRects(int current_version);
+ void OnSelectPopupMenuItems(bool canceled,
+ const std::vector<int>& selected_indices);
+#elif defined(OS_MACOSX)
+ void OnSelectPopupMenuItem(int selected_index);
+ void OnCopyToFindPboard();
+#endif
// Requests that the browser process navigates to |url|. If
// |is_history_navigation_in_new_child| is true, the browser process should
@@ -839,6 +860,9 @@ class CONTENT_EXPORT RenderFrameImpl
// selection handles in sync with the webpage.
void SyncSelectionIfRequired();
+ // Sends a message and runs a nested message loop.
+ bool SendAndRunNestedMessageLoop(IPC::SyncMessage* message);
+
bool RunJavaScriptMessage(JavaScriptMessageType type,
const base::string16& message,
const base::string16& default_value,
@@ -871,20 +895,30 @@ class CONTENT_EXPORT RenderFrameImpl
// Does preparation for the navigation to |url|.
void PrepareRenderViewForNavigation(
const GURL& url,
- const RequestNavigationParams& request_params,
- bool* is_reload,
- blink::WebURLRequest::CachePolicy* cache_policy);
+ const RequestNavigationParams& request_params);
// PlzNavigate
// Sends a FrameHostMsg_BeginNavigation to the browser based on the contents
// of the WebURLRequest.
- void BeginNavigation(blink::WebURLRequest* request);
+ // |should_replace_current_entry| indicates that the current history entry
+ // will be replaced when the navigation commits. |is_client_redirect|
+ // indicates that the navigation originated as a client redirect.
+ // Note: those two concepts are separate. For example, a location.assign is a
+ // client redirect but it only replaces the current entry if called before
+ // load stop. location.replace on the other hand is a client redirect and
+ // always replaces the current entry.
+ void BeginNavigation(blink::WebURLRequest* request,
+ bool should_replace_current_entry,
+ bool is_client_redirect);
// Loads a data url.
void LoadDataURL(const CommonNavigationParams& params,
const RequestNavigationParams& request_params,
- blink::WebFrame* frame,
- blink::WebFrameLoadType load_type);
+ blink::WebLocalFrame* frame,
+ blink::WebFrameLoadType load_type,
+ blink::WebHistoryItem item_for_history_navigation,
+ blink::WebHistoryLoadType history_load_type,
+ bool is_client_redirect);
// Sends a proper FrameHostMsg_DidFailProvisionalLoadWithError_Params IPC for
// the failed request |request|.
@@ -924,27 +958,42 @@ class CONTENT_EXPORT RenderFrameImpl
bool AreSecureCodecsSupported();
- media::MediaPermission* GetMediaPermission();
-
#if defined(ENABLE_MOJO_MEDIA)
- media::interfaces::ServiceFactory* GetMediaServiceFactory();
-
- // Called when a connection error happened on |media_service_factory_|.
- void OnMediaServiceFactoryConnectionError();
+ mojo::shell::mojom::InterfaceProvider* GetMediaInterfaceProvider();
#endif
media::CdmFactory* GetCdmFactory();
+ media::DecoderFactory* GetDecoderFactory();
void RegisterMojoServices();
+ // Connect to an interface provided by the service registry.
+ template <typename Interface>
+ void GetInterface(mojo::InterfaceRequest<Interface> request);
+
// Connects to a Mojo application and returns a proxy to its exposed
// ServiceProvider.
- mojo::ServiceProviderPtr ConnectToApplication(const GURL& url);
+ mojo::shell::mojom::InterfaceProviderPtr ConnectToApplication(
+ const GURL& url);
// Returns the media delegate for WebMediaPlayer usage. If
// |media_player_delegate_| is NULL, one is created.
media::RendererWebMediaPlayerDelegate* GetWebMediaPlayerDelegate();
+ // Called to get the WebPlugin to handle find requests in the document.
+ // Returns nullptr if there is no such WebPlugin.
+ blink::WebPlugin* GetWebPluginForFind();
+
+ // Sends a reply to the current find operation handling if it was a
+ // synchronous find request.
+ void SendFindReply(int request_id,
+ int match_count,
+ int ordinal,
+ const blink::WebRect& selection_rect,
+ bool final_status_update);
+
+ void InitializeBlameContext(RenderFrameImpl* parent_frame);
+
// Stores the WebLocalFrame we are associated with. This is null from the
// constructor until BindToWebFrame is called, and it is null after
// frameDetached is called until destruction (which is asynchronous in the
@@ -976,9 +1025,7 @@ class CONTENT_EXPORT RenderFrameImpl
base::WeakPtr<RenderViewImpl> render_view_;
int routing_id_;
- bool is_swapped_out_;
- // RenderFrameProxy exists only when is_swapped_out_ is true.
// TODO(nasko): This can be removed once we don't have a swapped out state on
// RenderFrame. See https://crbug.com/357747.
RenderFrameProxy* render_frame_proxy_;
@@ -1010,6 +1057,8 @@ class CONTENT_EXPORT RenderFrameImpl
base::string16 pepper_composition_text_;
PluginPowerSaverHelper* plugin_power_saver_helper_;
+
+ PepperPluginInstanceImpl* plugin_find_handler_;
#endif
RendererWebCookieJarImpl cookie_jar_;
@@ -1063,12 +1112,12 @@ class CONTENT_EXPORT RenderFrameImpl
// EncryptedMediaClient attached to this frame; lazily initialized.
scoped_ptr<media::WebEncryptedMediaClientImpl> web_encrypted_media_client_;
- // The media permission dispatcher attached to this frame, lazily initialized.
- MediaPermissionDispatcherImpl* media_permission_dispatcher_;
+ // The media permission dispatcher attached to this frame.
+ scoped_ptr<MediaPermissionDispatcher> media_permission_dispatcher_;
#if defined(ENABLE_MOJO_MEDIA)
- // The media factory attached to this frame, lazily initialized.
- media::interfaces::ServiceFactoryPtr media_service_factory_;
+ // The media interface provider attached to this frame, lazily initialized.
+ scoped_ptr<MediaInterfaceProvider> media_interface_provider_;
#endif
// MidiClient attached to this frame; lazily initialized.
@@ -1083,6 +1132,8 @@ class CONTENT_EXPORT RenderFrameImpl
RendererMediaSessionManager* media_session_manager_;
#endif
+ media::SurfaceManager* media_surface_manager_;
+
#if defined(ENABLE_BROWSER_CDMS)
// Manage all CDMs in this render frame for communicating with the real CDM in
// the browser process. It's okay to use a raw pointer since it's a
@@ -1090,8 +1141,9 @@ class CONTENT_EXPORT RenderFrameImpl
RendererCdmManager* cdm_manager_;
#endif
- // The CDM factory attached to this frame, lazily initialized.
+ // The CDM and decoder factory attached to this frame, lazily initialized.
scoped_ptr<media::CdmFactory> cdm_factory_;
+ scoped_ptr<media::DecoderFactory> decoder_factory_;
// Media resource cache, lazily initialized.
linked_ptr<media::UrlIndex> url_index_;
@@ -1119,9 +1171,10 @@ class CONTENT_EXPORT RenderFrameImpl
PresentationDispatcher* presentation_dispatcher_;
ServiceRegistryImpl service_registry_;
+ BlinkServiceRegistryImpl blink_service_registry_;
// The shell proxy used to connect to Mojo applications.
- mojo::ShellPtr mojo_shell_;
+ mojo::shell::mojom::ConnectorPtr connector_;
// The screen orientation dispatcher attached to the frame, lazily
// initialized.
@@ -1156,6 +1209,11 @@ class CONTENT_EXPORT RenderFrameImpl
// Whether or not this RenderFrame is currently pasting.
bool is_pasting_;
+ // Whether we must stop creating nested message loops for modal dialogs. This
+ // is necessary because modal dialogs have a ScopedPageLoadDeferrer on the
+ // stack that interferes with swapping out.
+ bool suppress_further_dialogs_;
+
#if defined(ENABLE_WEBVR)
// The VR dispatcher attached to the frame, lazily initialized.
scoped_ptr<VRDispatcher> vr_dispatcher_;
@@ -1166,6 +1224,8 @@ class CONTENT_EXPORT RenderFrameImpl
scoped_ptr<ExternalPopupMenu> external_popup_menu_;
#endif
+ FrameBlameContext* blame_context_; // Not owned.
+
base::WeakPtrFactory<RenderFrameImpl> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(RenderFrameImpl);
diff --git a/chromium/content/renderer/render_frame_impl_browsertest.cc b/chromium/content/renderer/render_frame_impl_browsertest.cc
index 3e26089027a..60d9f31a49e 100644
--- a/chromium/content/renderer/render_frame_impl_browsertest.cc
+++ b/chromium/content/renderer/render_frame_impl_browsertest.cc
@@ -9,15 +9,18 @@
#include "build/build_config.h"
#include "content/common/frame_messages.h"
#include "content/common/view_messages.h"
+#include "content/public/renderer/document_state.h"
#include "content/public/test/frame_load_waiter.h"
#include "content/public/test/render_view_test.h"
#include "content/public/test/test_utils.h"
+#include "content/renderer/navigation_state_impl.h"
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_view_impl.h"
#include "content/test/fake_compositor_dependencies.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/platform/WebURLRequest.h"
#include "third_party/WebKit/public/web/WebFrameOwnerProperties.h"
+#include "third_party/WebKit/public/web/WebHistoryItem.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
namespace {
@@ -37,8 +40,7 @@ class RenderFrameImplTest : public RenderViewTest {
void SetUp() override {
RenderViewTest::SetUp();
- EXPECT_TRUE(static_cast<RenderFrameImpl*>(view_->GetMainRenderFrame())
- ->is_main_frame_);
+ EXPECT_TRUE(GetMainRenderFrame()->is_main_frame_);
FrameMsg_NewFrame_WidgetParams widget_params;
widget_params.routing_id = kSubframeWidgetRouteId;
@@ -48,15 +50,18 @@ class RenderFrameImplTest : public RenderViewTest {
LoadHTML("Parent frame <iframe name='frame'></iframe>");
+ FrameReplicationState frame_replication_state;
+ frame_replication_state.name = "frame";
+ frame_replication_state.unique_name = "frame-uniqueName";
+
RenderFrameImpl::FromWebFrame(
view_->GetMainRenderFrame()->GetWebFrame()->firstChild())
- ->OnSwapOut(kFrameProxyRouteId, false, FrameReplicationState());
+ ->OnSwapOut(kFrameProxyRouteId, false, frame_replication_state);
- RenderFrameImpl::CreateFrame(kSubframeRouteId, MSG_ROUTING_NONE,
- MSG_ROUTING_NONE, kFrameProxyRouteId,
- MSG_ROUTING_NONE, FrameReplicationState(),
- &compositor_deps_, widget_params,
- blink::WebFrameOwnerProperties());
+ RenderFrameImpl::CreateFrame(
+ kSubframeRouteId, MSG_ROUTING_NONE, MSG_ROUTING_NONE,
+ kFrameProxyRouteId, MSG_ROUTING_NONE, frame_replication_state,
+ &compositor_deps_, widget_params, blink::WebFrameOwnerProperties());
frame_ = RenderFrameImpl::FromRoutingID(kSubframeRouteId);
EXPECT_FALSE(frame_->is_main_frame_);
@@ -71,6 +76,14 @@ class RenderFrameImplTest : public RenderViewTest {
RenderViewTest::TearDown();
}
+ void SetIsUsingLoFi(RenderFrameImpl* frame, bool is_using_lofi) {
+ frame->is_using_lofi_ = is_using_lofi;
+ }
+
+ RenderFrameImpl* GetMainRenderFrame() {
+ return static_cast<RenderFrameImpl*>(view_->GetMainRenderFrame());
+ }
+
RenderFrameImpl* frame() { return frame_; }
content::RenderWidget* frame_widget() const {
@@ -115,26 +128,13 @@ class RenderFrameTestObserver : public RenderFrameObserver {
// RenderWidget.
TEST_F(RenderFrameImplTest, MAYBE_SubframeWidget) {
EXPECT_TRUE(frame_widget());
- // We can't convert to RenderWidget* directly, because
- // it and RenderView are two unrelated base classes
- // of RenderViewImpl. If a class has multiple base classes,
- // each base class pointer will be distinct, and direct casts
- // between unrelated base classes are undefined, even if they share
- // a common derived class. The compiler has no way in general of
- // determining the displacement between the two classes, so these
- // types of casts cannot be implemented in a type safe way.
- // To overcome this, we make two legal static casts:
- // first, downcast from RenderView* to RenderViewImpl*,
- // then upcast from RenderViewImpl* to RenderWidget*.
- EXPECT_NE(frame_widget(),
- static_cast<content::RenderWidget*>(
- static_cast<content::RenderViewImpl*>((view_))));
+ EXPECT_NE(frame_widget(), view_->GetWidget());
}
// Verify a subframe RenderWidget properly processes its viewport being
// resized.
TEST_F(RenderFrameImplTest, MAYBE_FrameResize) {
- ViewMsg_Resize_Params resize_params;
+ ResizeParams resize_params;
gfx::Size size(200, 200);
resize_params.screen_info = blink::WebScreenInfo();
resize_params.new_size = size;
@@ -177,4 +177,50 @@ TEST_F(RenderFrameImplTest, MAYBE_FrameWasShownAfterWidgetClose) {
EXPECT_TRUE(observer.visible());
}
+// Test that LoFi state only updates for new main frame documents. Subframes
+// inherit from the main frame and should not change at commit time.
+TEST_F(RenderFrameImplTest, LoFiNotUpdatedOnSubframeCommits) {
+ SetIsUsingLoFi(GetMainRenderFrame(), true);
+ SetIsUsingLoFi(frame(), true);
+ EXPECT_TRUE(GetMainRenderFrame()->IsUsingLoFi());
+ EXPECT_TRUE(frame()->IsUsingLoFi());
+
+ blink::WebHistoryItem item;
+ item.initialize();
+
+ // The main frame's and subframe's LoFi states should stay the same on
+ // navigations within the page.
+ frame()->didNavigateWithinPage(frame()->GetWebFrame(), item,
+ blink::WebStandardCommit);
+ EXPECT_TRUE(frame()->IsUsingLoFi());
+ GetMainRenderFrame()->didNavigateWithinPage(
+ GetMainRenderFrame()->GetWebFrame(), item, blink::WebStandardCommit);
+ EXPECT_TRUE(GetMainRenderFrame()->IsUsingLoFi());
+
+ // The subframe's LoFi state should not be reset on commit.
+ DocumentState* document_state =
+ DocumentState::FromDataSource(frame()->GetWebFrame()->dataSource());
+ static_cast<NavigationStateImpl*>(document_state->navigation_state())
+ ->set_was_within_same_page(false);
+
+ frame()->didCommitProvisionalLoad(frame()->GetWebFrame(), item,
+ blink::WebStandardCommit);
+ EXPECT_TRUE(frame()->IsUsingLoFi());
+
+ // The main frame's LoFi state should be reset to off on commit.
+ document_state = DocumentState::FromDataSource(
+ GetMainRenderFrame()->GetWebFrame()->dataSource());
+ static_cast<NavigationStateImpl*>(document_state->navigation_state())
+ ->set_was_within_same_page(false);
+
+ // Calling didCommitProvisionalLoad is not representative of a full navigation
+ // but serves the purpose of testing the LoFi state logic.
+ GetMainRenderFrame()->didCommitProvisionalLoad(
+ GetMainRenderFrame()->GetWebFrame(), item, blink::WebStandardCommit);
+ EXPECT_FALSE(GetMainRenderFrame()->IsUsingLoFi());
+ // The subframe would be deleted here after a cross-document navigation. It
+ // happens to be left around in this test because this does not simulate the
+ // frame detach.
+}
+
} // namespace
diff --git a/chromium/content/renderer/render_frame_proxy.cc b/chromium/content/renderer/render_frame_proxy.cc
index 39a0d348083..37b7059f289 100644
--- a/chromium/content/renderer/render_frame_proxy.cc
+++ b/chromium/content/renderer/render_frame_proxy.cc
@@ -14,6 +14,7 @@
#include "content/common/frame_messages.h"
#include "content/common/frame_replication_state.h"
#include "content/common/input_messages.h"
+#include "content/common/page_messages.h"
#include "content/common/site_isolation_policy.h"
#include "content/common/swapped_out_messages.h"
#include "content/common/view_messages.h"
@@ -21,6 +22,9 @@
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_view_impl.h"
+#include "content/renderer/render_widget.h"
+#include "ipc/ipc_message_macros.h"
+#include "third_party/WebKit/public/platform/URLConversion.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
@@ -56,7 +60,18 @@ RenderFrameProxy* RenderFrameProxy::CreateProxyToReplaceFrame(
// follow later.
blink::WebRemoteFrame* web_frame =
blink::WebRemoteFrame::create(scope, proxy.get());
- proxy->Init(web_frame, frame_to_replace->render_view());
+
+ // If frame_to_replace has a RenderFrameProxy parent, then its
+ // RenderWidget will be destroyed along with it, so the new
+ // RenderFrameProxy uses its parent's RenderWidget.
+ RenderWidget* widget =
+ (!frame_to_replace->GetWebFrame()->parent() ||
+ frame_to_replace->GetWebFrame()->parent()->isWebLocalFrame())
+ ? frame_to_replace->GetRenderWidget()
+ : RenderFrameProxy::FromWebFrame(
+ frame_to_replace->GetWebFrame()->parent())
+ ->render_widget();
+ proxy->Init(web_frame, frame_to_replace->render_view(), widget);
return proxy.release();
}
@@ -76,17 +91,22 @@ RenderFrameProxy* RenderFrameProxy::CreateFrameProxy(
return nullptr;
}
+ blink::WebFrame* opener =
+ RenderFrameImpl::ResolveOpener(opener_routing_id, nullptr);
+
scoped_ptr<RenderFrameProxy> proxy(
new RenderFrameProxy(routing_id, MSG_ROUTING_NONE));
- RenderViewImpl* render_view = NULL;
- blink::WebRemoteFrame* web_frame = NULL;
+ RenderViewImpl* render_view = nullptr;
+ RenderWidget* render_widget = nullptr;
+ blink::WebRemoteFrame* web_frame = nullptr;
if (!parent) {
// Create a top level WebRemoteFrame.
render_view = RenderViewImpl::FromRoutingID(render_view_routing_id);
- web_frame =
- blink::WebRemoteFrame::create(replicated_state.scope, proxy.get());
+ web_frame = blink::WebRemoteFrame::create(replicated_state.scope,
+ proxy.get(), opener);
render_view->webview()->setMainFrame(web_frame);
+ render_widget = render_view->GetWidget();
} else {
// Create a frame under an existing parent. The parent is always expected
// to be a RenderFrameProxy, because navigations initiated by local frames
@@ -95,15 +115,13 @@ RenderFrameProxy* RenderFrameProxy::CreateFrameProxy(
web_frame = parent->web_frame()->createRemoteChild(
replicated_state.scope,
blink::WebString::fromUTF8(replicated_state.name),
- replicated_state.sandbox_flags, proxy.get());
+ blink::WebString::fromUTF8(replicated_state.unique_name),
+ replicated_state.sandbox_flags, proxy.get(), opener);
render_view = parent->render_view();
+ render_widget = parent->render_widget();
}
- blink::WebFrame* opener =
- RenderFrameImpl::ResolveOpener(opener_routing_id, nullptr);
- web_frame->setOpener(opener);
-
- proxy->Init(web_frame, render_view);
+ proxy->Init(web_frame, render_view, render_widget);
// Initialize proxy's WebRemoteFrame with the security origin and other
// replicated information.
@@ -138,8 +156,9 @@ RenderFrameProxy* RenderFrameProxy::FromWebFrame(blink::WebFrame* web_frame) {
RenderFrameProxy::RenderFrameProxy(int routing_id, int frame_routing_id)
: routing_id_(routing_id),
frame_routing_id_(frame_routing_id),
- web_frame_(NULL),
- render_view_(NULL) {
+ web_frame_(nullptr),
+ render_view_(nullptr),
+ render_widget_(nullptr) {
std::pair<RoutingIDProxyMap::iterator, bool> result =
g_routing_id_proxy_map.Get().insert(std::make_pair(routing_id_, this));
CHECK(result.second) << "Inserting a duplicate item.";
@@ -156,7 +175,7 @@ RenderFrameProxy::~RenderFrameProxy() {
if (render_frame)
render_frame->set_render_frame_proxy(nullptr);
- render_view()->UnregisterRenderFrameProxy(this);
+ render_widget_->UnregisterRenderFrameProxy(this);
CHECK(!web_frame_);
RenderThread::Get()->RemoveRoute(routing_id_);
@@ -164,38 +183,47 @@ RenderFrameProxy::~RenderFrameProxy() {
}
void RenderFrameProxy::Init(blink::WebRemoteFrame* web_frame,
- RenderViewImpl* render_view) {
+ RenderViewImpl* render_view,
+ RenderWidget* render_widget) {
CHECK(web_frame);
CHECK(render_view);
+ CHECK(render_widget);
web_frame_ = web_frame;
render_view_ = render_view;
+ render_widget_ = render_widget;
- // TODO(nick): Should all RenderFrameProxies remain observers of their views?
- render_view_->RegisterRenderFrameProxy(this);
+ render_widget_->RegisterRenderFrameProxy(this);
std::pair<FrameMap::iterator, bool> result =
g_frame_map.Get().insert(std::make_pair(web_frame_, this));
CHECK(result.second) << "Inserted a duplicate item.";
}
-bool RenderFrameProxy::IsMainFrameDetachedFromTree() const {
- return web_frame_->top() == web_frame_ &&
- render_view_->webview()->mainFrame()->isWebLocalFrame();
+void RenderFrameProxy::WillBeginCompositorFrame() {
+ if (compositing_helper_) {
+ FrameHostMsg_HittestData_Params params;
+ params.surface_id = compositing_helper_->surface_id();
+ params.ignored_for_hittest = web_frame_->isIgnoredForHitTest();
+ render_widget_->QueueMessage(
+ new FrameHostMsg_HittestData(render_widget_->routing_id(), params),
+ MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE);
+ }
}
void RenderFrameProxy::DidCommitCompositorFrame() {
- if (compositing_helper_.get())
- compositing_helper_->DidCommitCompositorFrame();
}
void RenderFrameProxy::SetReplicatedState(const FrameReplicationState& state) {
DCHECK(web_frame_);
web_frame_->setReplicatedOrigin(state.origin);
web_frame_->setReplicatedSandboxFlags(state.sandbox_flags);
- web_frame_->setReplicatedName(blink::WebString::fromUTF8(state.name));
+ web_frame_->setReplicatedName(blink::WebString::fromUTF8(state.name),
+ blink::WebString::fromUTF8(state.unique_name));
web_frame_->setReplicatedShouldEnforceStrictMixedContentChecking(
state.should_enforce_strict_mixed_content_checking);
+ web_frame_->setReplicatedPotentiallyTrustworthyUniqueOrigin(
+ state.has_potentially_trustworthy_unique_origin);
}
// Update the proxy's SecurityContext and FrameOwner with new sandbox flags
@@ -220,12 +248,18 @@ void RenderFrameProxy::OnDidUpdateSandboxFlags(blink::WebSandboxFlags flags) {
}
bool RenderFrameProxy::OnMessageReceived(const IPC::Message& msg) {
+ // Forward Page IPCs to the RenderView.
+ if ((IPC_MESSAGE_CLASS(msg) == PageMsgStart)) {
+ if (render_view())
+ return render_view()->OnMessageReceived(msg);
+
+ return false;
+ }
+
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(RenderFrameProxy, msg)
IPC_MESSAGE_HANDLER(FrameMsg_DeleteProxy, OnDeleteProxy)
IPC_MESSAGE_HANDLER(FrameMsg_ChildFrameProcessGone, OnChildFrameProcessGone)
- IPC_MESSAGE_HANDLER_GENERIC(FrameMsg_CompositorFrameSwapped,
- OnCompositorFrameSwapped(msg))
IPC_MESSAGE_HANDLER(FrameMsg_SetChildFrameSurface, OnSetChildFrameSurface)
IPC_MESSAGE_HANDLER(FrameMsg_UpdateOpener, OnUpdateOpener)
IPC_MESSAGE_HANDLER(FrameMsg_DidStartLoading, OnDidStartLoading)
@@ -250,7 +284,7 @@ bool RenderFrameProxy::Send(IPC::Message* message) {
}
void RenderFrameProxy::OnDeleteProxy() {
- DCHECK(web_frame_->isWebRemoteFrame());
+ DCHECK(web_frame_);
web_frame_->detach();
}
@@ -259,32 +293,6 @@ void RenderFrameProxy::OnChildFrameProcessGone() {
compositing_helper_->ChildFrameGone();
}
-void RenderFrameProxy::OnCompositorFrameSwapped(const IPC::Message& message) {
- // If this WebFrame has already been detached, its parent will be null. This
- // can happen when swapping a WebRemoteFrame with a WebLocalFrame, where this
- // message may arrive after the frame was removed from the frame tree, but
- // before the frame has been destroyed. http://crbug.com/446575.
- if (!web_frame()->parent())
- return;
-
- FrameMsg_CompositorFrameSwapped::Param param;
- if (!FrameMsg_CompositorFrameSwapped::Read(&message, &param))
- return;
-
- scoped_ptr<cc::CompositorFrame> frame(new cc::CompositorFrame);
- base::get<0>(param).frame.AssignTo(frame.get());
-
- if (!compositing_helper_.get()) {
- compositing_helper_ =
- ChildFrameCompositingHelper::CreateForRenderFrameProxy(this);
- }
- compositing_helper_->OnCompositorFrameSwapped(
- std::move(frame), base::get<0>(param).producing_route_id,
- base::get<0>(param).output_surface_id,
- base::get<0>(param).producing_host_id,
- base::get<0>(param).shared_memory_handle);
-}
-
void RenderFrameProxy::OnSetChildFrameSurface(
const cc::SurfaceId& surface_id,
const gfx::Size& frame_size,
@@ -308,32 +316,14 @@ void RenderFrameProxy::OnSetChildFrameSurface(
void RenderFrameProxy::OnUpdateOpener(int opener_routing_id) {
blink::WebFrame* opener =
RenderFrameImpl::ResolveOpener(opener_routing_id, nullptr);
-
- // When there is a RenderFrame for this proxy, tell it to update its opener.
- // TODO(alexmos, nasko): Remove this when we only have WebRemoteFrames.
- if (!SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- RenderFrameImpl* render_frame =
- RenderFrameImpl::FromRoutingID(frame_routing_id_);
- if (render_frame) {
- render_frame->GetWebFrame()->setOpener(opener);
- return;
- }
- }
-
web_frame_->setOpener(opener);
}
void RenderFrameProxy::OnDidStartLoading() {
- if (IsMainFrameDetachedFromTree())
- return;
-
web_frame_->didStartLoading();
}
void RenderFrameProxy::OnDidStopLoading() {
- if (IsMainFrameDetachedFromTree())
- return;
-
web_frame_->didStopLoading();
}
@@ -341,8 +331,10 @@ void RenderFrameProxy::OnDispatchLoad() {
web_frame_->DispatchLoadEventForFrameOwner();
}
-void RenderFrameProxy::OnDidUpdateName(const std::string& name) {
- web_frame_->setReplicatedName(blink::WebString::fromUTF8(name));
+void RenderFrameProxy::OnDidUpdateName(const std::string& name,
+ const std::string& unique_name) {
+ web_frame_->setReplicatedName(blink::WebString::fromUTF8(name),
+ blink::WebString::fromUTF8(unique_name));
}
void RenderFrameProxy::OnEnforceStrictMixedContentChecking(
@@ -351,8 +343,12 @@ void RenderFrameProxy::OnEnforceStrictMixedContentChecking(
should_enforce);
}
-void RenderFrameProxy::OnDidUpdateOrigin(const url::Origin& origin) {
+void RenderFrameProxy::OnDidUpdateOrigin(
+ const url::Origin& origin,
+ bool is_potentially_trustworthy_unique_origin) {
web_frame_->setReplicatedOrigin(origin);
+ web_frame_->setReplicatedPotentiallyTrustworthyUniqueOrigin(
+ is_potentially_trustworthy_unique_origin);
}
void RenderFrameProxy::OnSetPageFocus(bool is_focused) {
@@ -431,7 +427,8 @@ void RenderFrameProxy::navigate(const blink::WebURLRequest& request,
FrameHostMsg_OpenURL_Params params;
params.url = request.url();
params.referrer = Referrer(
- GURL(request.httpHeaderField(blink::WebString::fromUTF8("Referer"))),
+ blink::WebStringToGURL(
+ request.httpHeaderField(blink::WebString::fromUTF8("Referer"))),
request.referrerPolicy());
params.disposition = CURRENT_TAB;
params.should_replace_current_entry = should_replace_current_entry;
diff --git a/chromium/content/renderer/render_frame_proxy.h b/chromium/content/renderer/render_frame_proxy.h
index 1ce02646014..5fd375c6285 100644
--- a/chromium/content/renderer/render_frame_proxy.h
+++ b/chromium/content/renderer/render_frame_proxy.h
@@ -33,6 +33,7 @@ namespace content {
class ChildFrameCompositingHelper;
class RenderFrameImpl;
class RenderViewImpl;
+class RenderWidget;
struct FrameReplicationState;
// When a page's frames are rendered by multiple processes, each renderer has a
@@ -103,6 +104,10 @@ class CONTENT_EXPORT RenderFrameProxy
bool Send(IPC::Message* msg) override;
// Out-of-process child frames receive a signal from RenderWidgetCompositor
+ // when a compositor frame will begin.
+ void WillBeginCompositorFrame();
+
+ // Out-of-process child frames receive a signal from RenderWidgetCompositor
// when a compositor frame has committed.
void DidCommitCompositorFrame();
@@ -110,16 +115,13 @@ class CONTENT_EXPORT RenderFrameProxy
// RenderFrameProxy's WebRemoteFrame.
void SetReplicatedState(const FrameReplicationState& state);
- // Navigating a top-level frame cross-process does not swap the WebLocalFrame
- // for a WebRemoteFrame in the frame tree. In this case, this WebRemoteFrame
- // is not attached to the frame tree and there is no blink::Frame associated
- // with it, so it is not in state where most operations on it will succeed.
- bool IsMainFrameDetachedFromTree() const;
-
int routing_id() { return routing_id_; }
RenderViewImpl* render_view() { return render_view_; }
blink::WebRemoteFrame* web_frame() { return web_frame_; }
+ // Returns the widget used for the local frame root.
+ RenderWidget* render_widget() { return render_widget_; }
+
// blink::WebRemoteFrameClient implementation:
void frameDetached(DetachType type) override;
void postMessageEvent(blink::WebLocalFrame* sourceFrame,
@@ -144,7 +146,9 @@ class CONTENT_EXPORT RenderFrameProxy
private:
RenderFrameProxy(int routing_id, int frame_routing_id);
- void Init(blink::WebRemoteFrame* frame, RenderViewImpl* render_view);
+ void Init(blink::WebRemoteFrame* frame,
+ RenderViewImpl* render_view,
+ RenderWidget* render_widget);
// IPC::Listener
bool OnMessageReceived(const IPC::Message& msg) override;
@@ -161,9 +165,10 @@ class CONTENT_EXPORT RenderFrameProxy
void OnDidStopLoading();
void OnDidUpdateSandboxFlags(blink::WebSandboxFlags flags);
void OnDispatchLoad();
- void OnDidUpdateName(const std::string& name);
+ void OnDidUpdateName(const std::string& name, const std::string& unique_name);
void OnEnforceStrictMixedContentChecking(bool should_enforce);
- void OnDidUpdateOrigin(const url::Origin& origin);
+ void OnDidUpdateOrigin(const url::Origin& origin,
+ bool is_potentially_trustworthy_unique_origin);
void OnSetPageFocus(bool is_focused);
void OnSetFocusedFrame();
@@ -179,6 +184,7 @@ class CONTENT_EXPORT RenderFrameProxy
scoped_refptr<ChildFrameCompositingHelper> compositing_helper_;
RenderViewImpl* render_view_;
+ RenderWidget* render_widget_;
DISALLOW_COPY_AND_ASSIGN(RenderFrameProxy);
};
diff --git a/chromium/content/renderer/render_process_impl.cc b/chromium/content/renderer/render_process_impl.cc
index 16737ea3166..c9d0d5325a1 100644
--- a/chromium/content/renderer/render_process_impl.cc
+++ b/chromium/content/renderer/render_process_impl.cc
@@ -14,6 +14,7 @@
#include "base/command_line.h"
#include "base/compiler_specific.h"
+#include "base/feature_list.h"
#include "base/sys_info.h"
#include "content/child/site_isolation_stats_gatherer.h"
#include "content/public/common/content_switches.h"
@@ -21,6 +22,32 @@
#include "third_party/WebKit/public/web/WebFrame.h"
#include "v8/include/v8.h"
+namespace {
+
+const base::Feature kV8_ES2015_TailCalls_Feature {
+ "V8_ES2015_TailCalls", base::FEATURE_DISABLED_BY_DEFAULT
+};
+
+const base::Feature kV8SerializeEagerFeature{"V8_Serialize_Eager",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kV8SerializeAgeCodeFeature{
+ "V8_Serialize_Age_Code", base::FEATURE_DISABLED_BY_DEFAULT};
+
+void SetV8FlagIfFeature(const base::Feature& feature, const char* v8_flag) {
+ if (base::FeatureList::IsEnabled(feature)) {
+ v8::V8::SetFlagsFromString(v8_flag, strlen(v8_flag));
+ }
+}
+
+void SetV8FlagIfHasSwitch(const char* switch_name, const char* v8_flag) {
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(switch_name)) {
+ v8::V8::SetFlagsFromString(v8_flag, strlen(v8_flag));
+ }
+}
+
+} // namespace
+
namespace content {
RenderProcessImpl::RenderProcessImpl()
@@ -42,20 +69,23 @@ RenderProcessImpl::RenderProcessImpl()
}
#endif
- std::string scavenge_reclaim_unmodified_flag(
- "--scavenge_reclaim_unmodified_objects");
- v8::V8::SetFlagsFromString(
- scavenge_reclaim_unmodified_flag.c_str(),
- static_cast<int>(scavenge_reclaim_unmodified_flag.size()));
-
if (base::SysInfo::IsLowEndDevice()) {
std::string optimize_flag("--optimize-for-size");
v8::V8::SetFlagsFromString(optimize_flag.c_str(),
static_cast<int>(optimize_flag.size()));
}
+ SetV8FlagIfFeature(kV8_ES2015_TailCalls_Feature, "--harmony-tailcalls");
+ SetV8FlagIfFeature(kV8SerializeEagerFeature, "--serialize_eager");
+ SetV8FlagIfFeature(kV8SerializeAgeCodeFeature, "--serialize_age_code");
+ SetV8FlagIfHasSwitch(switches::kDisableJavaScriptHarmonyShipping,
+ "--noharmony-shipping");
+ SetV8FlagIfHasSwitch(switches::kJavaScriptHarmony, "--harmony");
+ SetV8FlagIfHasSwitch(switches::kEnableWasm, "--expose-wasm");
+
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
+
if (command_line.HasSwitch(switches::kJavaScriptFlags)) {
std::string flags(
command_line.GetSwitchValueASCII(switches::kJavaScriptFlags));
diff --git a/chromium/content/renderer/render_thread_impl.cc b/chromium/content/renderer/render_thread_impl.cc
index dda8f7dbcfd..30047189f7c 100644
--- a/chromium/content/renderer/render_thread_impl.cc
+++ b/chromium/content/renderer/render_thread_impl.cc
@@ -12,6 +12,7 @@
#include "base/allocator/allocator_extension.h"
#include "base/command_line.h"
+#include "base/debug/crash_logging.h"
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/logging.h"
@@ -32,7 +33,6 @@
#include "base/threading/simple_thread.h"
#include "base/threading/thread_local.h"
#include "base/threading/thread_restrictions.h"
-#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "build/build_config.h"
@@ -40,7 +40,6 @@
#include "cc/base/switches.h"
#include "cc/blink/web_external_bitmap_impl.h"
#include "cc/blink/web_layer_impl.h"
-#include "cc/layers/layer_settings.h"
#include "cc/raster/task_graph_runner.h"
#include "cc/trees/layer_tree_host_common.h"
#include "cc/trees/layer_tree_settings.h"
@@ -50,6 +49,7 @@
#include "components/scheduler/renderer/renderer_scheduler.h"
#include "content/child/appcache/appcache_dispatcher.h"
#include "content/child/appcache/appcache_frontend_impl.h"
+#include "content/child/blob_storage/blob_message_filter.h"
#include "content/child/child_discardable_shared_memory_manager.h"
#include "content/child/child_gpu_memory_buffer_manager.h"
#include "content/child/child_histogram_message_filter.h"
@@ -59,8 +59,6 @@
#include "content/child/db_message_filter.h"
#include "content/child/indexed_db/indexed_db_dispatcher.h"
#include "content/child/indexed_db/indexed_db_message_filter.h"
-#include "content/child/npapi/npobject_util.h"
-#include "content/child/plugin_messages.h"
#include "content/child/resource_dispatcher.h"
#include "content/child/resource_scheduling_filter.h"
#include "content/child/runtime_features.h"
@@ -73,9 +71,7 @@
#include "content/common/dom_storage/dom_storage_messages.h"
#include "content/common/frame_messages.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
-#include "content/common/gpu/client/gpu_channel_host.h"
-#include "content/common/gpu/gpu_messages.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
+#include "content/common/gpu_process_launch_causes.h"
#include "content/common/render_frame_setup.mojom.h"
#include "content/common/render_process_messages.h"
#include "content/common/resource_messages.h"
@@ -130,6 +126,7 @@
#include "content/renderer/shared_worker/embedded_shared_worker_stub.h"
#include "gin/public/debug.h"
#include "gpu/GLES2/gl2extchromium.h"
+#include "gpu/ipc/client/gpu_channel_host.h"
#include "ipc/ipc_channel_handle.h"
#include "ipc/ipc_platform_file.h"
#include "ipc/mojo/ipc_channel_mojo.h"
@@ -139,9 +136,9 @@
#include "mojo/common/common_type_converters.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "net/base/net_errors.h"
-#include "net/base/net_util.h"
#include "net/base/port_util.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "net/base/url_util.h"
#include "skia/ext/event_tracer_impl.h"
#include "skia/ext/skia_memory_dump_provider.h"
#include "third_party/WebKit/public/platform/WebImageGenerator.h"
@@ -171,6 +168,7 @@
#include "content/renderer/android/synchronous_compositor_filter.h"
#include "content/renderer/media/android/renderer_demuxer_android.h"
#include "content/renderer/media/android/stream_texture_factory_impl.h"
+#include "media/base/android/media_codec_util.h"
#endif
#if defined(OS_MACOSX)
@@ -186,13 +184,6 @@
#if defined(OS_WIN)
#include <windows.h>
#include <objbase.h>
-#else
-// TODO(port)
-#include "content/child/npapi/np_channel_base.h"
-#endif
-
-#if defined(ENABLE_PLUGINS)
-#include "content/renderer/npapi/plugin_channel_host.h"
#endif
#if defined(ENABLE_WEBRTC)
@@ -363,16 +354,16 @@ void LowMemoryNotificationOnThisThread() {
isolate->LowMemoryNotification();
}
-class RenderFrameSetupImpl : public RenderFrameSetup {
+class RenderFrameSetupImpl : public mojom::RenderFrameSetup {
public:
explicit RenderFrameSetupImpl(
- mojo::InterfaceRequest<RenderFrameSetup> request)
+ mojo::InterfaceRequest<mojom::RenderFrameSetup> request)
: routing_id_highmark_(-1), binding_(this, std::move(request)) {}
- void ExchangeServiceProviders(
+ void ExchangeInterfaceProviders(
int32_t frame_routing_id,
- mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services)
+ mojo::shell::mojom::InterfaceProviderRequest services,
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services)
override {
// TODO(morrita): This is for investigating http://crbug.com/415059 and
// should be removed once it is fixed.
@@ -395,26 +386,17 @@ class RenderFrameSetupImpl : public RenderFrameSetup {
private:
int32_t routing_id_highmark_;
- mojo::StrongBinding<RenderFrameSetup> binding_;
+ mojo::StrongBinding<mojom::RenderFrameSetup> binding_;
};
-void CreateRenderFrameSetup(mojo::InterfaceRequest<RenderFrameSetup> request) {
+void CreateRenderFrameSetup(
+ mojo::InterfaceRequest<mojom::RenderFrameSetup> request) {
new RenderFrameSetupImpl(std::move(request));
}
-blink::WebGraphicsContext3D::Attributes GetOffscreenAttribs() {
- blink::WebGraphicsContext3D::Attributes attributes;
- attributes.shareResources = true;
- attributes.depth = false;
- attributes.stencil = false;
- attributes.antialias = false;
- attributes.noAutomaticFlushes = true;
- return attributes;
-}
-
void SetupEmbeddedWorkerOnWorkerThread(
- mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::InterfacePtrInfo<mojo::ServiceProvider> exposed_services) {
+ mojo::shell::mojom::InterfaceProviderRequest services,
+ mojo::shell::mojom::InterfaceProviderPtrInfo exposed_services) {
ServiceWorkerContextClient* client =
ServiceWorkerContextClient::ThreadSpecificInstance();
// It is possible for client to be null if for some reason the worker died
@@ -426,16 +408,16 @@ void SetupEmbeddedWorkerOnWorkerThread(
mojo::MakeProxy(std::move(exposed_services)));
}
-class EmbeddedWorkerSetupImpl : public EmbeddedWorkerSetup {
+class EmbeddedWorkerSetupImpl : public mojom::EmbeddedWorkerSetup {
public:
explicit EmbeddedWorkerSetupImpl(
- mojo::InterfaceRequest<EmbeddedWorkerSetup> request)
+ mojo::InterfaceRequest<mojom::EmbeddedWorkerSetup> request)
: binding_(this, std::move(request)) {}
- void ExchangeServiceProviders(
+ void ExchangeInterfaceProviders(
int32_t thread_id,
- mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services) override {
+ mojo::shell::mojom::InterfaceProviderRequest services,
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services) override {
WorkerThreadRegistry::Instance()->GetTaskRunnerFor(thread_id)->PostTask(
FROM_HERE,
base::Bind(&SetupEmbeddedWorkerOnWorkerThread, base::Passed(&services),
@@ -443,11 +425,11 @@ class EmbeddedWorkerSetupImpl : public EmbeddedWorkerSetup {
}
private:
- mojo::StrongBinding<EmbeddedWorkerSetup> binding_;
+ mojo::StrongBinding<mojom::EmbeddedWorkerSetup> binding_;
};
void CreateEmbeddedWorkerSetup(
- mojo::InterfaceRequest<EmbeddedWorkerSetup> request) {
+ mojo::InterfaceRequest<mojom::EmbeddedWorkerSetup> request) {
new EmbeddedWorkerSetupImpl(std::move(request));
}
@@ -537,6 +519,8 @@ std::string RenderThreadImpl::HistogramCustomizer::HostToCustomHistogramSuffix(
return ".plus";
if (host == "inbox.google.com")
return ".inbox";
+ if (host == "calendar.google.com")
+ return ".calendar";
if (host == "www.youtube.com")
return ".youtube";
if (IsAlexaTop10NonGoogleSite(host))
@@ -588,7 +572,9 @@ RenderThreadImpl* RenderThreadImpl::Create(
const InProcessChildThreadParams& params) {
scoped_ptr<scheduler::RendererScheduler> renderer_scheduler =
scheduler::RendererScheduler::Create();
- return new RenderThreadImpl(params, std::move(renderer_scheduler));
+ scoped_refptr<base::SingleThreadTaskRunner> test_task_counter;
+ return new RenderThreadImpl(
+ params, std::move(renderer_scheduler), test_task_counter);
}
// static
@@ -605,14 +591,15 @@ RenderThreadImpl* RenderThreadImpl::current() {
RenderThreadImpl::RenderThreadImpl(
const InProcessChildThreadParams& params,
- scoped_ptr<scheduler::RendererScheduler> scheduler)
+ scoped_ptr<scheduler::RendererScheduler> scheduler,
+ scoped_refptr<base::SingleThreadTaskRunner>& resource_task_queue)
: ChildThreadImpl(Options::Builder()
.InBrowserProcess(params)
.UseMojoChannel(ShouldUseMojoChannel())
.Build()),
renderer_scheduler_(std::move(scheduler)),
raster_worker_pool_(new RasterWorkerPool()) {
- Init();
+ Init(resource_task_queue);
}
// When we run plugins in process, we actually run them on the render thread,
@@ -626,10 +613,12 @@ RenderThreadImpl::RenderThreadImpl(
renderer_scheduler_(std::move(scheduler)),
main_message_loop_(std::move(main_message_loop)),
raster_worker_pool_(new RasterWorkerPool()) {
- Init();
+ scoped_refptr<base::SingleThreadTaskRunner> test_task_counter;
+ Init(test_task_counter);
}
-void RenderThreadImpl::Init() {
+void RenderThreadImpl::Init(
+ scoped_refptr<base::SingleThreadTaskRunner>& resource_task_queue) {
TRACE_EVENT0("startup", "RenderThreadImpl::Init");
base::trace_event::TraceLog::GetInstance()->SetThreadSortIndex(
@@ -646,6 +635,8 @@ void RenderThreadImpl::Init() {
// Register this object as the main thread.
ChildProcess::current()->set_main_thread(this);
+ InitializeWebKit(resource_task_queue);
+
// In single process the single process is all there is.
notify_webkit_of_modal_loop_ = true;
webkit_shared_timer_suspended_ = false;
@@ -674,6 +665,8 @@ void RenderThreadImpl::Init() {
media_stream_center_ = NULL;
+ blob_message_filter_ = new BlobMessageFilter();
+ AddFilter(blob_message_filter_.get());
db_message_filter_ = new DBMessageFilter();
AddFilter(db_message_filter_.get());
@@ -732,10 +725,6 @@ void RenderThreadImpl::Init() {
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
- cc::LayerSettings layer_settings;
- layer_settings.use_compositor_animation_timelines =
- !command_line.HasSwitch(switches::kDisableCompositorAnimationTimelines);
- cc_blink::WebLayerImpl::SetLayerSettings(layer_settings);
cc::SetClientNameForMetrics("Renderer");
is_threaded_animation_enabled_ =
@@ -743,11 +732,11 @@ void RenderThreadImpl::Init() {
is_zero_copy_enabled_ = command_line.HasSwitch(switches::kEnableZeroCopy);
is_partial_raster_enabled_ =
- command_line.HasSwitch(switches::kEnablePartialRaster);
+ !command_line.HasSwitch(switches::kDisablePartialRaster);
is_gpu_memory_buffer_compositor_resources_enabled_ = command_line.HasSwitch(
switches::kEnableGpuMemoryBufferCompositorResources);
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MACOSX)
is_elastic_overscroll_enabled_ = base::mac::IsOSLionOrLater();
if (is_elastic_overscroll_enabled_) {
base::ScopedCFTypeRef<CFStringRef> key(
@@ -806,6 +795,13 @@ void RenderThreadImpl::Init() {
// been initialized by the Zygote before this instance became a Renderer.
media::InitializeMediaLibrary();
+#if defined(OS_ANDROID)
+ if (!command_line.HasSwitch(switches::kDisableAcceleratedVideoDecode) &&
+ media::MediaCodecUtil::IsMediaCodecAvailable()) {
+ media::EnablePlatformDecoderSupport();
+ }
+#endif
+
memory_pressure_listener_.reset(new base::MemoryPressureListener(
base::Bind(&RenderThreadImpl::OnMemoryPressure, base::Unretained(this))));
@@ -817,20 +813,15 @@ void RenderThreadImpl::Init() {
DCHECK(parsed_num_raster_threads) << string_value;
DCHECK_GT(num_raster_threads, 0);
+#if defined(OS_ANDROID)
// Note: Currently, enabling image decode tasks only provides a benefit if
- // there's more than one raster thread. This might change in the future but we
- // avoid it for now to reduce the cost of recording.
- are_image_decode_tasks_enabled_ = num_raster_threads > 1;
-
- base::SimpleThread::Options thread_options;
-#if defined(OS_ANDROID) || defined(OS_LINUX)
- if (!command_line.HasSwitch(
- switches::kUseNormalPriorityForTileTaskWorkerThreads)) {
- thread_options.set_priority(base::ThreadPriority::BACKGROUND);
- }
+ // we use high quality interpolation filters, which are disabled on android.
+ are_image_decode_tasks_enabled_ = false;
+#else
+ are_image_decode_tasks_enabled_ = true;
#endif
- raster_worker_pool_->Start(num_raster_threads, thread_options);
+ raster_worker_pool_->Start(num_raster_threads);
// TODO(boliu): In single process, browser main loop should set up the
// discardable memory manager, and should skip this if kSingleProcess.
@@ -838,17 +829,20 @@ void RenderThreadImpl::Init() {
base::DiscardableMemoryAllocator::SetInstance(
ChildThreadImpl::discardable_shared_memory_manager());
- service_registry()->AddService<RenderFrameSetup>(
- base::Bind(CreateRenderFrameSetup));
- service_registry()->AddService<EmbeddedWorkerSetup>(
- base::Bind(CreateEmbeddedWorkerSetup));
+ service_registry()->AddService(base::Bind(CreateRenderFrameSetup));
+ service_registry()->AddService(base::Bind(CreateEmbeddedWorkerSetup));
#if defined(MOJO_SHELL_CLIENT)
// We may not have a MojoShellConnection object in tests that directly
// instantiate a RenderThreadImpl.
- if (MojoShellConnection::Get())
+ if (MojoShellConnection::Get() &&
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kUseMusInRenderer))
CreateRenderWidgetWindowTreeClientFactory();
#endif
+
+ service_registry()->ConnectToRemoteService(
+ mojo::GetProxy(&storage_partition_service_));
}
RenderThreadImpl::~RenderThreadImpl() {
@@ -950,26 +944,33 @@ void RenderThreadImpl::Shutdown() {
if (gpu_channel_.get())
gpu_channel_->DestroyChannel();
- // TODO(port)
-#if defined(OS_WIN)
- // Clean up plugin channels before this thread goes away.
- NPChannelBase::CleanupChannels();
-#endif
-
ChildThreadImpl::Shutdown();
// Shut down the message loop and the renderer scheduler before shutting down
// Blink. This prevents a scenario where a pending task in the message loop
// accesses Blink objects after Blink shuts down.
- // This must be at the very end of the shutdown sequence. You must not touch
- // the message loop after this.
renderer_scheduler_->Shutdown();
- main_message_loop_.reset();
+ if (main_message_loop_)
+ main_message_loop_->RunUntilIdle();
+
if (blink_platform_impl_) {
blink_platform_impl_->Shutdown();
+ // This must be at the very end of the shutdown sequence.
+ // blink::shutdown() must be called after all strong references from
+ // Chromium to Blink are cleared.
blink::shutdown();
}
+ // Delay shutting down DiscardableSharedMemoryManager until blink::shutdown
+ // is complete, because blink::shutdown destructs Blink Resources and they
+ // may try to unlock their underlying discardable memory.
+ ChildThreadImpl::ShutdownDiscardableSharedMemoryManager();
+
+ // The message loop must be cleared after shutting down
+ // the DiscardableSharedMemoryManager, which needs to send messages
+ // to the browser process.
+ main_message_loop_.reset();
+
lazy_tls.Pointer()->Set(NULL);
}
@@ -993,36 +994,16 @@ bool RenderThreadImpl::Send(IPC::Message* msg) {
bool notify_webkit_of_modal_loop = true; // default value
std::swap(notify_webkit_of_modal_loop, notify_webkit_of_modal_loop_);
-#if defined(ENABLE_PLUGINS)
- int render_view_id = MSG_ROUTING_NONE;
-#endif
-
if (pumping_events) {
renderer_scheduler_->SuspendTimerQueue();
if (notify_webkit_of_modal_loop)
WebView::willEnterModalLoop();
-#if defined(ENABLE_PLUGINS)
- RenderViewImpl* render_view =
- RenderViewImpl::FromRoutingID(msg->routing_id());
- if (render_view) {
- render_view_id = msg->routing_id();
- PluginChannelHost::Broadcast(
- new PluginMsg_SignalModalDialogEvent(render_view_id));
- }
-#endif
}
bool rv = ChildThreadImpl::Send(msg);
if (pumping_events) {
-#if defined(ENABLE_PLUGINS)
- if (render_view_id != MSG_ROUTING_NONE) {
- PluginChannelHost::Broadcast(
- new PluginMsg_ResetModalDialogEvent(render_view_id));
- }
-#endif
-
if (notify_webkit_of_modal_loop)
WebView::didExitModalLoop();
@@ -1068,9 +1049,9 @@ void RenderThreadImpl::AddRoute(int32_t routing_id, IPC::Listener* listener) {
return;
scoped_refptr<PendingRenderFrameConnect> connection(it->second);
- mojo::InterfaceRequest<mojo::ServiceProvider> services(
+ mojo::shell::mojom::InterfaceProviderRequest services(
std::move(connection->services()));
- mojo::ServiceProviderPtr exposed_services(
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services(
std::move(connection->exposed_services()));
exposed_services.set_connection_error_handler(mojo::Closure());
pending_render_frame_connects_.erase(it);
@@ -1101,8 +1082,8 @@ void RenderThreadImpl::RemoveEmbeddedWorkerRoute(int32_t routing_id) {
void RenderThreadImpl::RegisterPendingRenderFrameConnect(
int routing_id,
- mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services) {
+ mojo::shell::mojom::InterfaceProviderRequest services,
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services) {
std::pair<PendingRenderFrameConnectMap::iterator, bool> result =
pending_render_frame_connects_.insert(std::make_pair(
routing_id,
@@ -1111,6 +1092,10 @@ void RenderThreadImpl::RegisterPendingRenderFrameConnect(
CHECK(result.second) << "Inserting a duplicate item.";
}
+mojom::StoragePartitionService* RenderThreadImpl::GetStoragePartitionService() {
+ return storage_partition_service_.get();
+}
+
int RenderThreadImpl::GenerateRoutingID() {
int routing_id = MSG_ROUTING_NONE;
Send(new ViewHostMsg_GenerateRoutingID(&routing_id));
@@ -1138,29 +1123,17 @@ void RenderThreadImpl::SetResourceDispatcherDelegate(
resource_dispatcher()->set_delegate(delegate);
}
-void RenderThreadImpl::SetResourceDispatchTaskQueue(
- const scoped_refptr<base::SingleThreadTaskRunner>& resource_task_queue) {
- // Add a filter that forces resource messages to be dispatched via a
- // particular task runner.
- scoped_refptr<ResourceSchedulingFilter> filter(
- new ResourceSchedulingFilter(resource_task_queue, resource_dispatcher()));
- channel()->AddFilter(filter.get());
- resource_dispatcher()->SetResourceSchedulingFilter(filter);
-
- // The ChildResourceMessageFilter and the ResourceDispatcher need to use the
- // same queue to ensure tasks are executed in the expected order.
- child_resource_message_filter()->SetMainThreadTaskRunner(resource_task_queue);
- resource_dispatcher()->SetMainThreadTaskRunner(resource_task_queue);
-}
-
void RenderThreadImpl::InitializeCompositorThread() {
#if defined(OS_ANDROID)
SynchronousCompositorFactory* sync_compositor_factory =
SynchronousCompositorFactory::GetInstance();
+ const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
bool using_ipc_sync_compositing =
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kIPCSyncCompositing);
+ cmd_line->HasSwitch(switches::kIPCSyncCompositing);
+ bool sync_input_for_sync_compositing =
+ cmd_line->HasSwitch(switches::kSyncInputForSyncCompositor);
DCHECK(!sync_compositor_factory || !using_ipc_sync_compositing);
+ DCHECK(!sync_input_for_sync_compositing || using_ipc_sync_compositing);
if (sync_compositor_factory) {
compositor_task_runner_ =
@@ -1174,23 +1147,30 @@ void RenderThreadImpl::InitializeCompositorThread() {
#endif
compositor_thread_.reset(new WebThreadForCompositor(options));
blink_platform_impl_->SetCompositorThread(compositor_thread_.get());
- compositor_task_runner_ = compositor_thread_->TaskRunner();
+ compositor_task_runner_ = compositor_thread_->GetTaskRunner();
compositor_task_runner_->PostTask(
FROM_HERE,
base::Bind(base::IgnoreResult(&ThreadRestrictions::SetIOAllowed),
false));
}
- InputHandlerManagerClient* input_handler_manager_client = NULL;
+ InputHandlerManagerClient* input_handler_manager_client = nullptr;
+ SynchronousInputHandlerProxyClient* synchronous_input_handler_proxy_client =
+ nullptr;
#if defined(OS_ANDROID)
if (using_ipc_sync_compositing) {
sync_compositor_message_filter_ =
new SynchronousCompositorFilter(compositor_task_runner_);
AddFilter(sync_compositor_message_filter_.get());
- input_handler_manager_client = sync_compositor_message_filter_.get();
+ if (sync_input_for_sync_compositing)
+ input_handler_manager_client = sync_compositor_message_filter_.get();
+ synchronous_input_handler_proxy_client =
+ sync_compositor_message_filter_.get();
} else if (sync_compositor_factory) {
input_handler_manager_client =
sync_compositor_factory->GetInputHandlerManagerClient();
+ synchronous_input_handler_proxy_client =
+ sync_compositor_factory->GetSynchronousInputHandlerProxyClient();
}
#endif
if (!input_handler_manager_client) {
@@ -1203,12 +1183,12 @@ void RenderThreadImpl::InitializeCompositorThread() {
}
input_handler_manager_.reset(new InputHandlerManager(
compositor_task_runner_, input_handler_manager_client,
- renderer_scheduler_.get()));
+ synchronous_input_handler_proxy_client, renderer_scheduler_.get()));
}
-void RenderThreadImpl::EnsureWebKitInitialized() {
- if (blink_platform_impl_)
- return;
+void RenderThreadImpl::InitializeWebKit(
+ scoped_refptr<base::SingleThreadTaskRunner>& resource_task_queue) {
+ DCHECK(!blink_platform_impl_);
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
@@ -1220,8 +1200,9 @@ void RenderThreadImpl::EnsureWebKitInitialized() {
SetRuntimeFeaturesDefaultsAndUpdateFromArgs(command_line);
- blink_platform_impl_.reset(
- new RendererBlinkPlatformImpl(renderer_scheduler_.get()));
+ blink_platform_impl_.reset(new RendererBlinkPlatformImpl(
+ renderer_scheduler_.get(),
+ static_cast<ServiceRegistryImpl*>(service_registry())->GetWeakPtr()));
blink::initialize(blink_platform_impl_.get());
v8::Isolate* isolate = blink::mainThreadIsolate();
@@ -1235,7 +1216,26 @@ void RenderThreadImpl::EnsureWebKitInitialized() {
base::Bind(base::IgnoreResult(&RenderThreadImpl::OnMessageReceived),
base::Unretained(this)));
- SetResourceDispatchTaskQueue(renderer_scheduler_->LoadingTaskRunner());
+ scoped_refptr<base::SingleThreadTaskRunner> resource_task_queue2;
+ if (resource_task_queue) {
+ resource_task_queue2 = resource_task_queue;
+ } else {
+ resource_task_queue2 = renderer_scheduler_->LoadingTaskRunner();
+ }
+ // Add a filter that forces resource messages to be dispatched via a
+ // particular task runner.
+ scoped_refptr<ResourceSchedulingFilter> filter(
+ new ResourceSchedulingFilter(
+ resource_task_queue2, resource_dispatcher()));
+ channel()->AddFilter(filter.get());
+ resource_dispatcher()->SetResourceSchedulingFilter(filter);
+
+ // The ChildResourceMessageFilter and the ResourceDispatcher need to use the
+ // same queue to ensure tasks are executed in the expected order.
+ child_resource_message_filter()->SetMainThreadTaskRunner(
+ resource_task_queue2);
+ resource_dispatcher()->SetMainThreadTaskRunner(resource_task_queue2);
+
if (!command_line.HasSwitch(switches::kDisableThreadedCompositing) &&
!command_line.HasSwitch(switches::kUseRemoteCompositing))
InitializeCompositorThread();
@@ -1267,8 +1267,6 @@ void RenderThreadImpl::EnsureWebKitInitialized() {
RenderMediaClient::Initialize();
- FOR_EACH_OBSERVER(RenderProcessObserver, observers_, WebKitInitialized());
-
devtools_agent_message_filter_ = new DevToolsAgentFilter();
AddFilter(devtools_agent_message_filter_.get());
@@ -1351,7 +1349,6 @@ cc::SharedBitmapManager* RenderThreadImpl::GetSharedBitmapManager() {
}
void RenderThreadImpl::RegisterExtension(v8::Extension* extension) {
- EnsureWebKitInitialized();
WebScriptController::registerExtension(extension);
}
@@ -1462,40 +1459,30 @@ media::GpuVideoAcceleratorFactories* RenderThreadImpl::GetGpuFactories() {
const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
-#if defined(OS_ANDROID)
- if (SynchronousCompositorFactory::GetInstance()) {
- if (!cmd_line->HasSwitch(switches::kDisableAcceleratedVideoDecode)) {
- DLOG(WARNING) << "Accelerated video decoding is not explicitly disabled, "
- "but is not supported by in-process rendering";
- }
- return NULL;
- }
-#endif
-
scoped_refptr<base::SingleThreadTaskRunner> media_task_runner =
GetMediaThreadTaskRunner();
scoped_refptr<ContextProviderCommandBuffer> shared_context_provider =
SharedWorkerContextProvider();
- scoped_refptr<GpuChannelHost> gpu_channel_host = GetGpuChannel();
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel_host = GetGpuChannel();
if (shared_context_provider && gpu_channel_host) {
const bool enable_video_accelerator =
!cmd_line->HasSwitch(switches::kDisableAcceleratedVideoDecode);
const bool enable_gpu_memory_buffer_video_frames =
-#if defined(OS_MACOSX)
+#if defined(OS_MACOSX) || defined(OS_LINUX)
!cmd_line->HasSwitch(switches::kDisableGpuMemoryBufferVideoFrames);
#else
cmd_line->HasSwitch(switches::kEnableGpuMemoryBufferVideoFrames);
#endif
- std::string image_texture_target_string =
+ std::vector<unsigned> image_texture_targets;
+ std::string video_frame_image_texture_target_string =
cmd_line->GetSwitchValueASCII(switches::kVideoImageTextureTarget);
- unsigned image_texture_target = 0;
- const bool parsed_image_texture_target =
- base::StringToUint(image_texture_target_string, &image_texture_target);
- DCHECK(parsed_image_texture_target);
+ StringToUintVector(video_frame_image_texture_target_string,
+ &image_texture_targets);
+
gpu_factories_.push_back(RendererGpuVideoAcceleratorFactories::Create(
gpu_channel_host.get(), base::ThreadTaskRunnerHandle::Get(),
media_task_runner, shared_context_provider,
- enable_gpu_memory_buffer_video_frames, image_texture_target,
+ enable_gpu_memory_buffer_video_frames, image_texture_targets,
enable_video_accelerator));
return gpu_factories_.back();
}
@@ -1504,19 +1491,29 @@ media::GpuVideoAcceleratorFactories* RenderThreadImpl::GetGpuFactories() {
scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
RenderThreadImpl::CreateOffscreenContext3d() {
- blink::WebGraphicsContext3D::Attributes attributes(GetOffscreenAttribs());
- bool lose_context_when_out_of_memory = true;
-
- scoped_refptr<GpuChannelHost> gpu_channel_host(EstablishGpuChannelSync(
+ // This is used to create a few different offscreen contexts:
+ // - The shared main thread context (offscreen) used by blink for canvas
+ // - The worker context (offscreen) used for GPU raster and video decoding.
+ // This is for an offscreen context, so the default framebuffer doesn't need
+ // alpha, depth, stencil, antialiasing.
+ gpu::gles2::ContextCreationAttribHelper attributes;
+ attributes.alpha_size = -1;
+ attributes.depth_size = 0;
+ attributes.stencil_size = 0;
+ attributes.samples = 0;
+ attributes.sample_buffers = 0;
+ attributes.bind_generates_resource = false;
+ attributes.lose_context_when_out_of_memory = true;
+ bool share_resources = true;
+ bool automatic_flushes = false;
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel_host(EstablishGpuChannelSync(
CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE));
return make_scoped_ptr(
WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
- gpu_channel_host.get(),
- attributes,
- lose_context_when_out_of_memory,
+ gpu_channel_host.get(), attributes, gfx::PreferIntegratedGpu,
+ share_resources, automatic_flushes,
GURL("chrome://gpu/RenderThreadImpl::CreateOffscreenContext3d"),
- WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits(),
- NULL));
+ WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits(), NULL));
}
scoped_refptr<cc_blink::ContextProviderWebContext>
@@ -1535,16 +1532,30 @@ RenderThreadImpl::SharedMainThreadContextProvider() {
}
#if defined(OS_ANDROID)
+
+namespace {
+base::LazyInstance<scoped_refptr<StreamTextureFactory>>
+ g_stream_texture_factory_override;
+}
+
+// static
+void RenderThreadImpl::SetStreamTextureFactory(
+ scoped_refptr<StreamTextureFactory> factory) {
+ g_stream_texture_factory_override.Get() = factory;
+}
+
scoped_refptr<StreamTextureFactory> RenderThreadImpl::GetStreamTexureFactory() {
DCHECK(IsMainThread());
- if (!stream_texture_factory_.get() ||
- stream_texture_factory_->ContextGL()->GetGraphicsResetStatusKHR() !=
- GL_NO_ERROR) {
+ if (g_stream_texture_factory_override.Get()) {
+ stream_texture_factory_ = g_stream_texture_factory_override.Get();
+ } else if (!stream_texture_factory_.get() ||
+ stream_texture_factory_->ContextGL()
+ ->GetGraphicsResetStatusKHR() != GL_NO_ERROR) {
if (!SharedMainThreadContextProvider().get()) {
stream_texture_factory_ = NULL;
return NULL;
}
- scoped_refptr<GpuChannelHost> gpu_channel_host(EstablishGpuChannelSync(
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel_host(EstablishGpuChannelSync(
CAUSE_FOR_GPU_LAUNCH_VIDEODECODEACCELERATOR_INITIALIZE));
if (!gpu_channel_host.get()) {
LOG(ERROR) << "Failed to establish GPU channel for media player";
@@ -1556,6 +1567,12 @@ scoped_refptr<StreamTextureFactory> RenderThreadImpl::GetStreamTexureFactory() {
}
return stream_texture_factory_;
}
+
+bool RenderThreadImpl::EnableStreamTextureCopy() {
+ return !g_stream_texture_factory_override.Get() &&
+ sync_compositor_message_filter_.get();
+}
+
#endif
AudioRendererMixerManager* RenderThreadImpl::GetAudioRendererMixerManager() {
@@ -1593,6 +1610,7 @@ void RenderThreadImpl::PreCacheFontCharacters(const LOGFONT& log_font,
#endif // OS_WIN
ServiceRegistry* RenderThreadImpl::GetServiceRegistry() {
+ DCHECK(service_registry());
return service_registry();
}
@@ -1674,6 +1692,11 @@ RenderThreadImpl::CreateExternalBeginFrameSource(int routing_id) {
compositor_message_filter_.get(), sync_message_filter(), routing_id));
}
+cc::ImageSerializationProcessor*
+RenderThreadImpl::GetImageSerializationProcessor() {
+ return GetContentClient()->renderer()->GetImageSerializationProcessor();
+}
+
cc::TaskGraphRunner* RenderThreadImpl::GetTaskGraphRunner() {
return raster_worker_pool_->GetTaskGraphRunner();
}
@@ -1700,14 +1723,6 @@ scoped_ptr<base::SharedMemory> RenderThreadImpl::AllocateSharedMemory(
return HostAllocateSharedMemoryBuffer(size);
}
-CreateCommandBufferResult RenderThreadImpl::CreateViewCommandBuffer(
- int32_t surface_id,
- const GPUCreateCommandBufferConfig& init_params,
- int32_t route_id) {
- NOTREACHED();
- return CREATE_COMMAND_BUFFER_FAILED;
-}
-
void RenderThreadImpl::DoNotNotifyWebKitOfModalLoop() {
notify_webkit_of_modal_loop_ = false;
}
@@ -1780,6 +1795,15 @@ void RenderThreadImpl::OnCreateNewFrameProxy(
int opener_routing_id,
int parent_routing_id,
const FrameReplicationState& replicated_state) {
+ // Debug cases of https://crbug.com/575245.
+ base::debug::SetCrashKeyValue("newproxy_proxy_id",
+ base::IntToString(routing_id));
+ base::debug::SetCrashKeyValue("newproxy_view_id",
+ base::IntToString(render_view_routing_id));
+ base::debug::SetCrashKeyValue("newproxy_opener_id",
+ base::IntToString(opener_routing_id));
+ base::debug::SetCrashKeyValue("newproxy_parent_id",
+ base::IntToString(parent_routing_id));
RenderFrameProxy::CreateFrameProxy(routing_id, render_view_routing_id,
opener_routing_id, parent_routing_id,
replicated_state);
@@ -1793,13 +1817,12 @@ void RenderThreadImpl::OnSetZoomLevelForCurrentURL(const std::string& scheme,
}
void RenderThreadImpl::OnCreateNewView(const ViewMsg_New_Params& params) {
- EnsureWebKitInitialized();
CompositorDependencies* compositor_deps = this;
// When bringing in render_view, also bring in webkit's glue and jsbindings.
RenderViewImpl::Create(compositor_deps, params, false);
}
-GpuChannelHost* RenderThreadImpl::EstablishGpuChannelSync(
+gpu::GpuChannelHost* RenderThreadImpl::EstablishGpuChannelSync(
CauseForGpuLaunch cause_for_gpu_launch) {
TRACE_EVENT0("gpu", "RenderThreadImpl::EstablishGpuChannelSync");
@@ -1818,10 +1841,8 @@ GpuChannelHost* RenderThreadImpl::EstablishGpuChannelSync(
int client_id = 0;
IPC::ChannelHandle channel_handle;
gpu::GPUInfo gpu_info;
- if (!Send(new GpuHostMsg_EstablishGpuChannel(cause_for_gpu_launch,
- &client_id,
- &channel_handle,
- &gpu_info)) ||
+ if (!Send(new ChildProcessHostMsg_EstablishGpuChannel(
+ cause_for_gpu_launch, &client_id, &channel_handle, &gpu_info)) ||
#if defined(OS_POSIX)
channel_handle.socket.fd == -1 ||
#endif
@@ -1836,13 +1857,9 @@ GpuChannelHost* RenderThreadImpl::EstablishGpuChannelSync(
// implementation of GpuChannelHostFactory.
io_thread_task_runner_ = ChildProcess::current()->io_task_runner();
- gpu_channel_ =
- GpuChannelHost::Create(this,
- client_id,
- gpu_info,
- channel_handle,
- ChildProcess::current()->GetShutDownEvent(),
- gpu_memory_buffer_manager());
+ gpu_channel_ = gpu::GpuChannelHost::Create(
+ this, client_id, gpu_info, channel_handle,
+ ChildProcess::current()->GetShutDownEvent(), gpu_memory_buffer_manager());
return gpu_channel_.get();
}
@@ -1869,7 +1886,7 @@ RenderThreadImpl::GetPeerConnectionDependencyFactory() {
}
#endif
-GpuChannelHost* RenderThreadImpl::GetGpuChannel() {
+gpu::GpuChannelHost* RenderThreadImpl::GetGpuChannel() {
if (!gpu_channel_.get())
return NULL;
@@ -1881,7 +1898,6 @@ GpuChannelHost* RenderThreadImpl::GetGpuChannel() {
#if defined(ENABLE_PLUGINS)
void RenderThreadImpl::OnPurgePluginListCache(bool reload_pages) {
- EnsureWebKitInitialized();
// The call below will cause a GetPlugins call with refresh=true, but at this
// point we already know that the browser has refreshed its list, so disable
// refresh temporarily to prevent each renderer process causing the list to be
@@ -1897,7 +1913,6 @@ void RenderThreadImpl::OnPurgePluginListCache(bool reload_pages) {
void RenderThreadImpl::OnNetworkConnectionChanged(
net::NetworkChangeNotifier::ConnectionType type,
double max_bandwidth_mbps) {
- EnsureWebKitInitialized();
bool online = type != net::NetworkChangeNotifier::CONNECTION_NONE;
WebNetworkStateNotifier::setOnLine(online);
FOR_EACH_OBSERVER(
@@ -1920,7 +1935,6 @@ void RenderThreadImpl::OnUpdateTimezone(const std::string& zone_id) {
#if defined(OS_ANDROID)
void RenderThreadImpl::OnSetWebKitSharedTimersSuspended(bool suspend) {
- EnsureWebKitInitialized();
if (suspend) {
renderer_scheduler_->SuspendTimerQueue();
} else {
@@ -1933,7 +1947,6 @@ void RenderThreadImpl::OnSetWebKitSharedTimersSuspended(bool suspend) {
#if defined(OS_MACOSX)
void RenderThreadImpl::OnUpdateScrollbarTheme(
const ViewMsg_UpdateScrollbarTheme_Params& params) {
- EnsureWebKitInitialized();
static_cast<WebScrollbarBehaviorImpl*>(
blink_platform_impl_->scrollbarBehavior())
->set_jump_on_track_click(params.jump_on_track_click);
@@ -1941,7 +1954,7 @@ void RenderThreadImpl::OnUpdateScrollbarTheme(
blink::WebScrollbarTheme::updateScrollbarsWithNSDefaults(
params.initial_button_delay, params.autoscroll_button_delay,
params.preferred_scroller_style, params.redraw,
- params.scroll_animation_enabled, params.button_placement);
+ params.button_placement);
}
void RenderThreadImpl::OnSystemColorsChanged(
@@ -1956,12 +1969,10 @@ void RenderThreadImpl::OnSystemColorsChanged(
void RenderThreadImpl::OnCreateNewSharedWorker(
const WorkerProcessMsg_CreateWorker_Params& params) {
// EmbeddedSharedWorkerStub will self-destruct.
- new EmbeddedSharedWorkerStub(params.url,
- params.name,
- params.content_security_policy,
- params.security_policy_type,
- params.pause_on_start,
- params.route_id);
+ new EmbeddedSharedWorkerStub(
+ params.url, params.name, params.content_security_policy,
+ params.security_policy_type, params.creation_address_space,
+ params.pause_on_start, params.route_id);
}
void RenderThreadImpl::OnMemoryPressure(
@@ -1977,10 +1988,13 @@ void RenderThreadImpl::OnMemoryPressure(
// Trigger full v8 garbage collection on memory pressure notifications.
// This will potentially hang the renderer for a long time, however, when
// we receive a memory pressure notification, we might be about to be
- // killed.
- blink::mainThreadIsolate()->LowMemoryNotification();
- RenderThread::Get()->PostTaskToAllWebWorkers(
- base::Bind(&LowMemoryNotificationOnThisThread));
+ // killed. Because of the janky hang don't do this to foreground
+ // renderers.
+ if (RendererIsHidden()) {
+ blink::mainThreadIsolate()->LowMemoryNotification();
+ RenderThread::Get()->PostTaskToAllWebWorkers(
+ base::Bind(&LowMemoryNotificationOnThisThread));
+ }
}
if (memory_pressure_level ==
@@ -2088,19 +2102,19 @@ void RenderThreadImpl::WidgetRestored() {
}
void RenderThreadImpl::OnRendererHidden() {
+ blink::mainThreadIsolate()->IsolateInBackgroundNotification();
// TODO(rmcilroy): Remove IdleHandler and replace it with an IdleTask
// scheduled by the RendererScheduler - http://crbug.com/469210.
if (!GetContentClient()->renderer()->RunIdleHandlerWhenWidgetsHidden())
return;
ScheduleIdleHandler(kInitialIdleHandlerDelayMs);
- blink::mainThreadIsolate()->IsolateInBackgroundNotification();
}
void RenderThreadImpl::OnRendererVisible() {
+ blink::mainThreadIsolate()->IsolateInForegroundNotification();
if (!GetContentClient()->renderer()->RunIdleHandlerWhenWidgetsHidden())
return;
ScheduleIdleHandler(kLongIdleHandlerDelayMs);
- blink::mainThreadIsolate()->IsolateInForegroundNotification();
}
void RenderThreadImpl::ReleaseFreeMemory() {
@@ -2113,14 +2127,15 @@ void RenderThreadImpl::ReleaseFreeMemory() {
RenderThreadImpl::PendingRenderFrameConnect::PendingRenderFrameConnect(
int routing_id,
- mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services)
+ mojo::shell::mojom::InterfaceProviderRequest services,
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services)
: routing_id_(routing_id),
services_(std::move(services)),
exposed_services_(std::move(exposed_services)) {
- // The RenderFrame may be deleted before the ExchangeServiceProviders message
- // is received. In that case, the RenderFrameHost should close the connection,
- // which is detected by setting an error handler on |exposed_services_|.
+ // The RenderFrame may be deleted before the ExchangeInterfaceProviders
+ // message is received. In that case, the RenderFrameHost should close the
+ // connection, which is detected by setting an error handler on
+ // |exposed_services_|.
exposed_services_.set_connection_error_handler(base::Bind(
&RenderThreadImpl::PendingRenderFrameConnect::OnConnectionError,
base::Unretained(this)));
diff --git a/chromium/content/renderer/render_thread_impl.h b/chromium/content/renderer/render_thread_impl.h
index bc5b172624b..3d1b5bfc737 100644
--- a/chromium/content/renderer/render_thread_impl.h
+++ b/chromium/content/renderer/render_thread_impl.h
@@ -25,10 +25,11 @@
#include "content/child/child_thread_impl.h"
#include "content/common/content_export.h"
#include "content/common/frame_replication_state.h"
-#include "content/common/gpu/client/gpu_channel_host.h"
-#include "content/common/gpu/gpu_result_codes.h"
+#include "content/common/gpu_process_launch_causes.h"
+#include "content/common/storage_partition_service.mojom.h"
#include "content/public/renderer/render_thread.h"
#include "content/renderer/gpu/compositor_dependencies.h"
+#include "gpu/ipc/client/gpu_channel_host.h"
#include "net/base/network_change_notifier.h"
#include "third_party/WebKit/public/platform/WebConnectionType.h"
#include "ui/gfx/native_widget_types.h"
@@ -58,6 +59,7 @@ class Thread;
namespace cc {
class ContextProvider;
+class ImageSerializationProcessor;
class TaskGraphRunner;
}
@@ -65,6 +67,10 @@ namespace cc_blink {
class ContextProviderWebContext;
}
+namespace gpu {
+class GpuChannelHost;
+}
+
namespace IPC {
class MessageFilter;
}
@@ -90,6 +96,7 @@ class AecDumpMessageFilter;
class AudioInputMessageFilter;
class AudioMessageFilter;
class AudioRendererMixerManager;
+class BlobMessageFilter;
class BluetoothMessageFilter;
class BrowserPluginManager;
class CacheStorageDispatcher;
@@ -99,7 +106,6 @@ class DBMessageFilter;
class DevToolsAgentFilter;
class DomStorageDispatcher;
class EmbeddedWorkerDispatcher;
-class GpuChannelHost;
class IndexedDBDispatcher;
class InputHandlerManager;
class MediaStreamCenter;
@@ -143,7 +149,7 @@ class SynchronousCompositorFilter;
class CONTENT_EXPORT RenderThreadImpl
: public RenderThread,
public ChildThreadImpl,
- public GpuChannelHostFactory,
+ public gpu::GpuChannelHostFactory,
NON_EXPORTED_BASE(public CompositorDependencies) {
public:
static RenderThreadImpl* Create(const InProcessChildThreadParams& params);
@@ -178,9 +184,6 @@ class CONTENT_EXPORT RenderThreadImpl
void RemoveObserver(RenderProcessObserver* observer) override;
void SetResourceDispatcherDelegate(
ResourceDispatcherDelegate* delegate) override;
- void EnsureWebKitInitialized() override;
- void RecordAction(const base::UserMetricsAction& action) override;
- void RecordComputedAction(const std::string& action) override;
scoped_ptr<base::SharedMemory> HostAllocateSharedMemoryBuffer(
size_t buffer_size) override;
cc::SharedBitmapManager* GetSharedBitmapManager() override;
@@ -216,6 +219,7 @@ class CONTENT_EXPORT RenderThreadImpl
cc::ContextProvider* GetSharedMainThreadContextProvider() override;
scoped_ptr<cc::BeginFrameSource> CreateExternalBeginFrameSource(
int routing_id) override;
+ cc::ImageSerializationProcessor* GetImageSerializationProcessor() override;
cc::TaskGraphRunner* GetTaskGraphRunner() override;
bool AreImageDecodeTasksEnabled() override;
bool IsThreadedAnimationEnabled() override;
@@ -224,8 +228,7 @@ class CONTENT_EXPORT RenderThreadImpl
// established or if it has been lost (for example if the GPU plugin crashed).
// If there is a pending asynchronous request, it will be completed by the
// time this routine returns.
- GpuChannelHost* EstablishGpuChannelSync(CauseForGpuLaunch);
-
+ gpu::GpuChannelHost* EstablishGpuChannelSync(CauseForGpuLaunch);
// This method modifies how the next message is sent. Normally, when sending
// a synchronous message that runs a nested message loop, we need to suspend
@@ -295,7 +298,11 @@ class CONTENT_EXPORT RenderThreadImpl
return sync_compositor_message_filter_.get();
}
+ static void SetStreamTextureFactory(
+ scoped_refptr<StreamTextureFactory> factory);
+
scoped_refptr<StreamTextureFactory> GetStreamTexureFactory();
+ bool EnableStreamTextureCopy();
#endif
// Creates the embedder implementation of WebMediaStreamCenter.
@@ -327,7 +334,7 @@ class CONTENT_EXPORT RenderThreadImpl
// Get the GPU channel. Returns NULL if the channel is not established or
// has been lost.
- GpuChannelHost* GetGpuChannel();
+ gpu::GpuChannelHost* GetGpuChannel();
// Returns a SingleThreadTaskRunner instance corresponding to the message loop
// of the thread on which file operations should be run. Must be called
@@ -447,35 +454,38 @@ class CONTENT_EXPORT RenderThreadImpl
void RegisterPendingRenderFrameConnect(
int routing_id,
- mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services);
+ mojo::shell::mojom::InterfaceProviderRequest services,
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services);
+
+ mojom::StoragePartitionService* GetStoragePartitionService();
protected:
- RenderThreadImpl(const InProcessChildThreadParams& params,
- scoped_ptr<scheduler::RendererScheduler> scheduler);
+ RenderThreadImpl(
+ const InProcessChildThreadParams& params,
+ scoped_ptr<scheduler::RendererScheduler> scheduler,
+ scoped_refptr<base::SingleThreadTaskRunner>& resource_task_queue);
RenderThreadImpl(scoped_ptr<base::MessageLoop> main_message_loop,
scoped_ptr<scheduler::RendererScheduler> scheduler);
- virtual void SetResourceDispatchTaskQueue(
- const scoped_refptr<base::SingleThreadTaskRunner>& resource_task_queue);
private:
// ChildThread
bool OnControlMessageReceived(const IPC::Message& msg) override;
void OnProcessBackgrounded(bool backgrounded) override;
+ void RecordAction(const base::UserMetricsAction& action) override;
+ void RecordComputedAction(const std::string& action) override;
// GpuChannelHostFactory implementation:
bool IsMainThread() override;
scoped_refptr<base::SingleThreadTaskRunner> GetIOThreadTaskRunner() override;
scoped_ptr<base::SharedMemory> AllocateSharedMemory(size_t size) override;
- CreateCommandBufferResult CreateViewCommandBuffer(
- int32_t surface_id,
- const GPUCreateCommandBufferConfig& init_params,
- int32_t route_id) override;
- void Init();
+ void Init(scoped_refptr<base::SingleThreadTaskRunner>& resource_task_queue);
void InitializeCompositorThread();
+ void InitializeWebKit(
+ scoped_refptr<base::SingleThreadTaskRunner>& resource_task_queue);
+
void OnCreateNewFrame(FrameMsg_NewFrame_Params params);
void OnCreateNewFrameProxy(int routing_id,
int render_view_routing_id,
@@ -531,6 +541,7 @@ class CONTENT_EXPORT RenderThreadImpl
blink::WebMediaStreamCenter* media_stream_center_;
// Used on the renderer and IPC threads.
+ scoped_refptr<BlobMessageFilter> blob_message_filter_;
scoped_refptr<DBMessageFilter> db_message_filter_;
scoped_refptr<AudioInputMessageFilter> audio_input_message_filter_;
scoped_refptr<AudioMessageFilter> audio_message_filter_;
@@ -585,7 +596,7 @@ class CONTENT_EXPORT RenderThreadImpl
base::RepeatingTimer idle_timer_;
// The channel from the renderer process to the GPU process.
- scoped_refptr<GpuChannelHost> gpu_channel_;
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel_;
// Cache of variables that are needed on the compositor thread by
// GpuChannelHostFactory methods.
@@ -664,6 +675,7 @@ class CONTENT_EXPORT RenderThreadImpl
bool is_partial_raster_enabled_;
bool is_elastic_overscroll_enabled_;
std::vector<unsigned> use_image_texture_targets_;
+ std::vector<unsigned> use_video_frame_image_texture_targets_;
bool are_image_decode_tasks_enabled_;
bool is_threaded_animation_enabled_;
@@ -672,14 +684,16 @@ class CONTENT_EXPORT RenderThreadImpl
public:
PendingRenderFrameConnect(
int routing_id,
- mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services);
+ mojo::shell::mojom::InterfaceProviderRequest services,
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services);
- mojo::InterfaceRequest<mojo::ServiceProvider>& services() {
+ mojo::shell::mojom::InterfaceProviderRequest& services() {
return services_;
}
- mojo::ServiceProviderPtr& exposed_services() { return exposed_services_; }
+ mojo::shell::mojom::InterfaceProviderPtr& exposed_services() {
+ return exposed_services_;
+ }
private:
friend class base::RefCounted<PendingRenderFrameConnect>;
@@ -690,14 +704,16 @@ class CONTENT_EXPORT RenderThreadImpl
void OnConnectionError();
int routing_id_;
- mojo::InterfaceRequest<mojo::ServiceProvider> services_;
- mojo::ServiceProviderPtr exposed_services_;
+ mojo::shell::mojom::InterfaceProviderRequest services_;
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services_;
};
typedef std::map<int, scoped_refptr<PendingRenderFrameConnect>>
PendingRenderFrameConnectMap;
PendingRenderFrameConnectMap pending_render_frame_connects_;
+ mojom::StoragePartitionServicePtr storage_partition_service_;
+
DISALLOW_COPY_AND_ASSIGN(RenderThreadImpl);
};
diff --git a/chromium/content/renderer/render_thread_impl_browsertest.cc b/chromium/content/renderer/render_thread_impl_browsertest.cc
index 95556d83cdf..f1b21a4f7c9 100644
--- a/chromium/content/renderer/render_thread_impl_browsertest.cc
+++ b/chromium/content/renderer/render_thread_impl_browsertest.cc
@@ -32,8 +32,13 @@
// IPC messages for testing ----------------------------------------------------
+// TODO(mdempsky): Fix properly by moving into a separate
+// browsertest_message_generator.cc file.
+#undef IPC_IPC_MESSAGE_MACROS_H_
+#undef IPC_MESSAGE_EXTRA
#define IPC_MESSAGE_IMPL
#include "ipc/ipc_message_macros.h"
+#include "ipc/ipc_message_templates_impl.h"
#undef IPC_MESSAGE_START
#define IPC_MESSAGE_START TestMsgStart
@@ -96,24 +101,18 @@ class TestTaskCounter : public base::SingleThreadTaskRunner {
class RenderThreadImplForTest : public RenderThreadImpl {
public:
- RenderThreadImplForTest(const InProcessChildThreadParams& params,
- scoped_ptr<scheduler::RendererScheduler> scheduler,
- scoped_refptr<TestTaskCounter> test_task_counter)
- : RenderThreadImpl(params, std::move(scheduler)),
- test_task_counter_(test_task_counter) {}
+ RenderThreadImplForTest(
+ const InProcessChildThreadParams& params,
+ scoped_ptr<scheduler::RendererScheduler> scheduler,
+ scoped_refptr<base::SingleThreadTaskRunner>& test_task_counter)
+ : RenderThreadImpl(params, std::move(scheduler), test_task_counter) {
+ }
~RenderThreadImplForTest() override {}
- void SetResourceDispatchTaskQueue(
- const scoped_refptr<base::SingleThreadTaskRunner>&) override {
- // Use our TestTaskCounter instead.
- RenderThreadImpl::SetResourceDispatchTaskQueue(test_task_counter_);
- }
-
using ChildThreadImpl::OnMessageReceived;
private:
- scoped_refptr<TestTaskCounter> test_task_counter_;
};
#if defined(COMPILER_MSVC)
@@ -180,14 +179,15 @@ class RenderThreadImplBrowserTest : public testing::Test {
scoped_ptr<scheduler::RendererScheduler> renderer_scheduler =
scheduler::RendererScheduler::Create();
InitializeMojo();
+ scoped_refptr<base::SingleThreadTaskRunner> test_task_counter(
+ test_task_counter_.get());
thread_ = new RenderThreadImplForTest(
InProcessChildThreadParams(test_helper_->GetChannelId(),
- test_helper_->GetIOTaskRunner()),
- std::move(renderer_scheduler), test_task_counter_);
+ test_helper_->GetIOTaskRunner(),
+ test_helper_->GetMessagePipeHandle()),
+ std::move(renderer_scheduler), test_task_counter);
cmd->InitFromArgv(old_argv);
- thread_->EnsureWebKitInitialized();
-
test_msg_filter_ = make_scoped_refptr(
new QuitOnTestMsgFilter(test_helper_->GetMessageLoop()));
thread_->AddFilter(test_msg_filter_.get());
diff --git a/chromium/content/renderer/render_view_browsertest.cc b/chromium/content/renderer/render_view_browsertest.cc
index 050d05fa8c8..c4c10b66c84 100644
--- a/chromium/content/renderer/render_view_browsertest.cc
+++ b/chromium/content/renderer/render_view_browsertest.cc
@@ -8,6 +8,8 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/command_line.h"
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/single_thread_task_runner.h"
@@ -15,11 +17,15 @@
#include "base/strings/utf_string_conversions.h"
#include "base/thread_task_runner_handle.h"
#include "base/time/time.h"
+#include "base/values.h"
#include "base/win/windows_version.h"
#include "build/build_config.h"
+#include "cc/trees/layer_tree_host.h"
#include "content/child/request_extra_data.h"
#include "content/child/service_worker/service_worker_network_provider.h"
+#include "content/common/content_switches_internal.h"
#include "content/common/frame_messages.h"
+#include "content/common/frame_replication_state.h"
#include "content/common/site_isolation_policy.h"
#include "content/common/ssl_status_serialization.h"
#include "content/common/view_messages.h"
@@ -41,6 +47,7 @@
#include "content/public/test/test_utils.h"
#include "content/renderer/accessibility/renderer_accessibility.h"
#include "content/renderer/devtools/devtools_agent.h"
+#include "content/renderer/gpu/render_widget_compositor.h"
#include "content/renderer/history_controller.h"
#include "content/renderer/history_serialization.h"
#include "content/renderer/navigation_state_impl.h"
@@ -59,6 +66,7 @@
#include "third_party/WebKit/public/platform/WebURLResponse.h"
#include "third_party/WebKit/public/web/WebDataSource.h"
#include "third_party/WebKit/public/web/WebDeviceEmulationParams.h"
+#include "third_party/WebKit/public/web/WebFrameContentDumper.h"
#include "third_party/WebKit/public/web/WebHistoryCommitType.h"
#include "third_party/WebKit/public/web/WebHistoryItem.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
@@ -87,6 +95,7 @@
#include "url/url_constants.h"
using blink::WebFrame;
+using blink::WebFrameContentDumper;
using blink::WebInputEvent;
using blink::WebLocalFrame;
using blink::WebMouseEvent;
@@ -152,6 +161,31 @@ bool TimeTicksGT(const base::TimeTicks& x, const base::TimeTicks& y) {
return base::TimeTicks::IsHighResolution() ? x > y : x >= y;
}
+// FrameReplicationState is normally maintained in the browser process,
+// but the function below provides a way for tests to construct a partial
+// FrameReplicationState within the renderer process. We say "partial",
+// because some fields of FrameReplicationState cannot be filled out
+// by content-layer, renderer code (still the constructed, partial
+// FrameReplicationState is sufficiently complete to avoid trigerring
+// asserts that a default/empty FrameReplicationState would).
+FrameReplicationState ReconstructReplicationStateForTesting(
+ TestRenderFrame* test_render_frame) {
+ blink::WebLocalFrame* frame = test_render_frame->GetWebFrame();
+
+ FrameReplicationState result;
+ // can't recover result.scope - no way to get WebTreeScopeType via public
+ // blink API...
+ result.name = base::UTF16ToUTF8(base::StringPiece16(frame->assignedName()));
+ result.unique_name =
+ base::UTF16ToUTF8(base::StringPiece16(frame->uniqueName()));
+ result.sandbox_flags = frame->effectiveSandboxFlags();
+ // result.should_enforce_strict_mixed_content_checking is calculated in the
+ // browser...
+ result.origin = frame->getSecurityOrigin();
+
+ return result;
+}
+
} // namespace
class RenderViewImplTest : public RenderViewTest {
@@ -345,11 +379,15 @@ class RenderViewImplTest : public RenderViewTest {
class DevToolsAgentTest : public RenderViewImplTest {
public:
void Attach() {
+ notifications_ = std::vector<std::string>();
std::string host_id = "host_id";
agent()->OnAttach(host_id, 17);
+ agent()->send_protocol_message_callback_for_test_ = base::Bind(
+ &DevToolsAgentTest::OnDevToolsMessage, base::Unretained(this));
}
void Detach() {
+ agent()->send_protocol_message_callback_for_test_.Reset();
agent()->OnDetach();
}
@@ -366,10 +404,38 @@ class DevToolsAgentTest : public RenderViewImplTest {
view()->NotifyOnClose();
}
+ void OnDevToolsMessage(
+ int, int, const std::string& message, const std::string&) {
+ last_received_message_ = message;
+ std::unique_ptr<base::DictionaryValue> root(
+ static_cast<base::DictionaryValue*>(
+ base::JSONReader::Read(message).release()));
+ int id;
+ if (!root->GetInteger("id", &id)) {
+ std::string notification;
+ EXPECT_TRUE(root->GetString("method", &notification));
+ notifications_.push_back(notification);
+ }
+ }
+
+ int CountNotifications(const std::string& notification) {
+ int result = 0;
+ for (const std::string& s : notifications_) {
+ if (s == notification)
+ ++result;
+ }
+ return result;
+ }
+
+ std::string LastReceivedMessage() const { return last_received_message_; }
+
private:
DevToolsAgent* agent() {
return frame()->devtools_agent();
}
+
+ std::vector<std::string> notifications_;
+ std::string last_received_message_;
};
class RenderViewImplBlinkSettingsTest : public RenderViewImplTest {
@@ -393,9 +459,9 @@ class RenderViewImplBlinkSettingsTest : public RenderViewImplTest {
};
class RenderViewImplScaleFactorTest : public RenderViewImplBlinkSettingsTest {
- public:
+ protected:
void SetDeviceScaleFactor(float dsf) {
- ViewMsg_Resize_Params params;
+ ResizeParams params;
params.screen_info.deviceScaleFactor = dsf;
params.new_size = gfx::Size(100, 100);
params.physical_backing_size = gfx::Size(200, 200);
@@ -404,6 +470,33 @@ class RenderViewImplScaleFactorTest : public RenderViewImplBlinkSettingsTest {
view()->OnResize(params);
ASSERT_EQ(dsf, view()->device_scale_factor_);
}
+
+ void TestEmulatedSizeDprDsf(int width, int height, float dpr,
+ float compositor_dsf) {
+ static base::string16 get_width =
+ base::ASCIIToUTF16("Number(window.innerWidth)");
+ static base::string16 get_height =
+ base::ASCIIToUTF16("Number(window.innerHeight)");
+ static base::string16 get_dpr =
+ base::ASCIIToUTF16("Number(window.devicePixelRatio * 10)");
+
+ int emulated_width, emulated_height;
+ int emulated_dpr;
+ blink::WebDeviceEmulationParams params;
+ params.viewSize.width = width;
+ params.viewSize.height = height;
+ params.deviceScaleFactor = dpr;
+ view()->OnEnableDeviceEmulation(params);
+ EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(get_width, &emulated_width));
+ EXPECT_EQ(width, emulated_width);
+ EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(get_height,
+ &emulated_height));
+ EXPECT_EQ(height, emulated_height);
+ EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(get_dpr, &emulated_dpr));
+ EXPECT_EQ(static_cast<int>(dpr * 10), emulated_dpr);
+ EXPECT_EQ(compositor_dsf,
+ view()->compositor()->layer_tree_host()->device_scale_factor());
+ }
};
// Ensure that the main RenderFrame is deleted and cleared from the RenderView
@@ -475,11 +568,7 @@ TEST_F(RenderViewImplTest, SaveImageFromDataURL) {
// Test that we get form state change notifications when input fields change.
TEST_F(RenderViewImplTest, OnNavStateChanged) {
- // Don't want any delay for form state sync changes. This will still post a
- // message so updates will get coalesced, but as soon as we spin the message
- // loop, it will generate an update.
view()->set_send_content_state_immediately(true);
-
LoadHTML("<input type=\"text\" id=\"elt_text\"></input>");
// We should NOT have gotten a form state change notification yet.
@@ -494,6 +583,7 @@ TEST_F(RenderViewImplTest, OnNavStateChanged) {
ExecuteJavaScriptForTests(
"document.getElementById('elt_text').value = 'foo';");
ProcessPendingMessages();
+
if (SiteIsolationPolicy::UseSubframeNavigationEntries()) {
EXPECT_TRUE(render_thread_->sink().GetUniqueMessageMatching(
FrameHostMsg_UpdateState::ID));
@@ -501,7 +591,6 @@ TEST_F(RenderViewImplTest, OnNavStateChanged) {
EXPECT_TRUE(render_thread_->sink().GetUniqueMessageMatching(
ViewHostMsg_UpdateState::ID));
}
- ProcessPendingMessages();
}
TEST_F(RenderViewImplTest, OnNavigationHttpPost) {
@@ -512,6 +601,7 @@ TEST_F(RenderViewImplTest, OnNavigationHttpPost) {
common_params.url = GURL("data:text/html,<div>Page</div>");
common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
common_params.transition = ui::PAGE_TRANSITION_TYPED;
+ common_params.method = "POST";
request_params.page_id = -1;
// Set up post data.
@@ -519,7 +609,6 @@ TEST_F(RenderViewImplTest, OnNavigationHttpPost) {
"post \0\ndata");
const unsigned int length = 11;
const std::vector<unsigned char> post_data(raw_data, raw_data + length);
- start_params.is_post = true;
start_params.browser_initiated_post_data = post_data;
frame()->Navigate(common_params, start_params, request_params);
@@ -585,6 +674,11 @@ TEST_F(RenderViewImplTest, DecideNavigationPolicy) {
// Navigations to normal HTTP URLs can be handled locally.
blink::WebURLRequest request(GURL("http://foo.com"));
+ request.setFetchRequestMode(blink::WebURLRequest::FetchRequestModeNavigate);
+ request.setFetchCredentialsMode(
+ blink::WebURLRequest::FetchCredentialsModeInclude);
+ request.setFetchRedirectMode(blink::WebURLRequest::FetchRedirectModeManual);
+ request.setFrameType(blink::WebURLRequest::FrameTypeTopLevel);
blink::WebFrameClient::NavigationPolicyInfo policy_info(request);
policy_info.navigationType = blink::WebNavigationTypeLinkClicked;
policy_info.defaultPolicy = blink::WebNavigationPolicyCurrentTab;
@@ -595,7 +689,7 @@ TEST_F(RenderViewImplTest, DecideNavigationPolicy) {
} else {
// If this is a renderer-initiated navigation that just begun, it should
// stop and be sent to the browser.
- EXPECT_EQ(blink::WebNavigationPolicyIgnore, policy);
+ EXPECT_EQ(blink::WebNavigationPolicyHandledByClient, policy);
// If this a navigation that is ready to commit, it should be handled
// locally.
@@ -706,141 +800,6 @@ TEST_F(RenderViewImplTest, DecideNavigationPolicyForWebUI) {
new_view->Release();
}
-// Ensure the RenderViewImpl sends an ACK to a SwapOut request, even if it is
-// already swapped out. http://crbug.com/93427.
-TEST_F(RenderViewImplTest, SendSwapOutACK) {
- // This test is invalid in --site-per-process mode, as swapped-out is no
- // longer used.
- if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- return;
- }
- LoadHTML("<div>Page A</div>");
- int initial_page_id = view_page_id();
-
- // Increment the ref count so that we don't exit when swapping out.
- RenderProcess::current()->AddRefProcess();
-
- // Respond to a swap out request.
- frame()->SwapOut(kProxyRoutingId, true, content::FrameReplicationState());
-
- // Ensure the swap out commits synchronously.
- EXPECT_NE(initial_page_id, view_page_id());
-
- // Check for a valid OnSwapOutACK.
- const IPC::Message* msg = render_thread_->sink().GetUniqueMessageMatching(
- FrameHostMsg_SwapOut_ACK::ID);
- ASSERT_TRUE(msg);
-
- // It is possible to get another swap out request. Ensure that we send
- // an ACK, even if we don't have to do anything else.
- render_thread_->sink().ClearMessages();
- frame()->SwapOut(kProxyRoutingId, false, content::FrameReplicationState());
- const IPC::Message* msg2 = render_thread_->sink().GetUniqueMessageMatching(
- FrameHostMsg_SwapOut_ACK::ID);
- ASSERT_TRUE(msg2);
-
- // If we navigate back to this RenderView, ensure we don't send a state
- // update for the swapped out URL. (http://crbug.com/72235)
- CommonNavigationParams common_params;
- RequestNavigationParams request_params;
- common_params.url = GURL("data:text/html,<div>Page B</div>");
- common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
- common_params.transition = ui::PAGE_TRANSITION_TYPED;
- request_params.current_history_list_length = 1;
- request_params.current_history_list_offset = 0;
- request_params.pending_history_list_offset = 1;
- request_params.page_id = -1;
- frame()->Navigate(common_params, StartNavigationParams(), request_params);
- ProcessPendingMessages();
- const IPC::Message* msg3 = render_thread_->sink().GetUniqueMessageMatching(
- ViewHostMsg_UpdateState::ID);
- EXPECT_FALSE(msg3);
-}
-
-// Ensure the RenderViewImpl reloads the previous page if a reload request
-// arrives while it is showing swappedout://. http://crbug.com/143155.
-TEST_F(RenderViewImplTest, ReloadWhileSwappedOut) {
- // This test is invalid in --site-per-process mode, as swapped-out is no
- // longer used.
- if (SiteIsolationPolicy::IsSwappedOutStateForbidden()) {
- return;
- }
-
- // Load page A.
- LoadHTML("<div>Page A</div>");
-
- // Load page B, which will trigger an UpdateState message for page A.
- LoadHTML("<div>Page B</div>");
-
- // Check for a valid UpdateState message for page A.
- ProcessPendingMessages();
- const IPC::Message* msg_A = render_thread_->sink().GetUniqueMessageMatching(
- ViewHostMsg_UpdateState::ID);
- ASSERT_TRUE(msg_A);
- ViewHostMsg_UpdateState::Param params;
- ViewHostMsg_UpdateState::Read(msg_A, &params);
- int page_id_A = base::get<0>(params);
- PageState state_A = base::get<1>(params);
- EXPECT_EQ(1, page_id_A);
- render_thread_->sink().ClearMessages();
-
- // Back to page A (page_id 1) and commit.
- CommonNavigationParams common_params_A;
- RequestNavigationParams request_params_A;
- common_params_A.navigation_type = FrameMsg_Navigate_Type::NORMAL;
- common_params_A.transition = ui::PAGE_TRANSITION_FORWARD_BACK;
- request_params_A.current_history_list_length = 2;
- request_params_A.current_history_list_offset = 1;
- request_params_A.pending_history_list_offset = 0;
- request_params_A.page_id = 1;
- request_params_A.nav_entry_id = 1;
- request_params_A.page_state = state_A;
- frame()->Navigate(common_params_A, StartNavigationParams(), request_params_A);
- EXPECT_EQ(1, view()->historyBackListCount());
- EXPECT_EQ(2, view()->historyBackListCount() +
- view()->historyForwardListCount() + 1);
- ProcessPendingMessages();
-
- // Respond to a swap out request.
- frame()->SwapOut(kProxyRoutingId, true, content::FrameReplicationState());
-
- // Check for a OnSwapOutACK.
- const IPC::Message* msg = render_thread_->sink().GetUniqueMessageMatching(
- FrameHostMsg_SwapOut_ACK::ID);
- ASSERT_TRUE(msg);
- render_thread_->sink().ClearMessages();
-
- // It is possible to get a reload request at this point, containing the
- // params.page_state of the initial page (e.g., if the new page fails the
- // provisional load in the renderer process, after we unload the old page).
- // Ensure the old page gets reloaded, not swappedout://.
- CommonNavigationParams common_params;
- RequestNavigationParams request_params;
- common_params.url = GURL("data:text/html,<div>Page A</div>");
- common_params.navigation_type = FrameMsg_Navigate_Type::RELOAD;
- common_params.transition = ui::PAGE_TRANSITION_RELOAD;
- request_params.current_history_list_length = 2;
- request_params.current_history_list_offset = 0;
- request_params.pending_history_list_offset = 0;
- request_params.page_id = 1;
- request_params.nav_entry_id = 1;
- request_params.page_state = state_A;
- frame()->Navigate(common_params, StartNavigationParams(), request_params);
- ProcessPendingMessages();
-
- // Verify page A committed, not swappedout://.
- const IPC::Message* frame_navigate_msg =
- render_thread_->sink().GetUniqueMessageMatching(
- FrameHostMsg_DidCommitProvisionalLoad::ID);
- EXPECT_TRUE(frame_navigate_msg);
-
- // Read URL out of the parent trait of the params object.
- FrameHostMsg_DidCommitProvisionalLoad::Param commit_load_params;
- FrameHostMsg_DidCommitProvisionalLoad::Read(frame_navigate_msg,
- &commit_load_params);
- EXPECT_NE(GURL("swappedout://"), base::get<0>(commit_load_params).url);
-}
-
// Verify that security origins are replicated properly to RenderFrameProxies
// when swapping out.
TEST_F(RenderViewImplTest, OriginReplicationForSwapOut) {
@@ -858,7 +817,8 @@ TEST_F(RenderViewImplTest, OriginReplicationForSwapOut) {
// Swap the child frame out and pass a replicated origin to be set for
// WebRemoteFrame.
- content::FrameReplicationState replication_state;
+ content::FrameReplicationState replication_state =
+ ReconstructReplicationStateForTesting(child_frame);
replication_state.origin = url::Origin(GURL("http://foo.com"));
child_frame->SwapOut(kProxyRoutingId, true, replication_state);
@@ -866,7 +826,8 @@ TEST_F(RenderViewImplTest, OriginReplicationForSwapOut) {
EXPECT_TRUE(web_frame->firstChild()->isWebRemoteFrame());
// Expect the origin to be updated properly.
- blink::WebSecurityOrigin origin = web_frame->firstChild()->securityOrigin();
+ blink::WebSecurityOrigin origin =
+ web_frame->firstChild()->getSecurityOrigin();
EXPECT_EQ(origin.toString(),
WebString::fromUTF8(replication_state.origin.Serialize()));
@@ -877,7 +838,7 @@ TEST_F(RenderViewImplTest, OriginReplicationForSwapOut) {
RenderFrame::FromWebFrame(web_frame->lastChild()));
child_frame2->SwapOut(kProxyRoutingId + 1, true, replication_state);
EXPECT_TRUE(web_frame->lastChild()->isWebRemoteFrame());
- EXPECT_TRUE(web_frame->lastChild()->securityOrigin().isUnique());
+ EXPECT_TRUE(web_frame->lastChild()->getSecurityOrigin().isUnique());
}
// Test for https://crbug.com/568676, where a parent detaches a remote child
@@ -896,7 +857,9 @@ TEST_F(RenderViewImplTest, NavigateProxyAndDetachBeforeOnNavigate) {
RenderFrame::FromWebFrame(web_frame->firstChild()));
// Swap the child frame out.
- child_frame->SwapOut(kProxyRoutingId, true, content::FrameReplicationState());
+ FrameReplicationState replication_state =
+ ReconstructReplicationStateForTesting(child_frame);
+ child_frame->SwapOut(kProxyRoutingId, true, replication_state);
EXPECT_TRUE(web_frame->firstChild()->isWebRemoteFrame());
// Do the first step of a remote-to-local transition for the child proxy,
@@ -907,13 +870,13 @@ TEST_F(RenderViewImplTest, NavigateProxyAndDetachBeforeOnNavigate) {
widget_params.hidden = false;
RenderFrameImpl::CreateFrame(routing_id, kProxyRoutingId, MSG_ROUTING_NONE,
frame()->GetRoutingID(), MSG_ROUTING_NONE,
- content::FrameReplicationState(), nullptr,
- widget_params, blink::WebFrameOwnerProperties());
+ replication_state, nullptr, widget_params,
+ blink::WebFrameOwnerProperties());
TestRenderFrame* provisional_frame =
static_cast<TestRenderFrame*>(RenderFrameImpl::FromRoutingID(routing_id));
EXPECT_TRUE(provisional_frame);
- // Detach the child frame (current remote) in the main frame.
+ // Detach the child frame (currently remote) in the main frame.
ExecuteJavaScriptForTests(
"document.body.removeChild(document.querySelector('iframe'));");
RenderFrameProxy* child_proxy =
@@ -935,6 +898,10 @@ TEST_F(RenderViewImplTest, NavigateProxyAndDetachBeforeOnNavigate) {
render_thread_->sink().GetUniqueMessageMatching(
FrameHostMsg_DidCommitProvisionalLoad::ID);
EXPECT_FALSE(frame_navigate_msg);
+
+ // Detach the provisional frame to clean it up. Normally, the browser
+ // process would trigger this via FrameMsg_Delete.
+ provisional_frame->GetWebFrame()->detach();
}
// Verify that DidFlushPaint doesn't crash if called after a RenderView is
@@ -951,8 +918,9 @@ TEST_F(RenderViewImplTest, PaintAfterSwapOut) {
// Respond to a swap out request.
TestRenderFrame* new_main_frame =
static_cast<TestRenderFrame*>(new_view->GetMainRenderFrame());
- new_main_frame->SwapOut(kProxyRoutingId, true,
- content::FrameReplicationState());
+ new_main_frame->SwapOut(
+ kProxyRoutingId, true,
+ ReconstructReplicationStateForTesting(new_main_frame));
// Simulate getting painted after swapping out.
new_view->DidFlushPaint();
@@ -978,7 +946,8 @@ TEST_F(RenderViewImplTest, SetZoomLevelAfterCrossProcessNavigation) {
// Swap the main frame out after which it should become a WebRemoteFrame.
TestRenderFrame* main_frame =
static_cast<TestRenderFrame*>(view()->GetMainRenderFrame());
- main_frame->SwapOut(kProxyRoutingId, true, content::FrameReplicationState());
+ main_frame->SwapOut(kProxyRoutingId, true,
+ ReconstructReplicationStateForTesting(main_frame));
EXPECT_TRUE(view()->webview()->mainFrame()->isWebRemoteFrame());
// This should not cause a crash.
@@ -1098,7 +1067,6 @@ TEST_F(RenderViewImplTest, DISABLED_LastCommittedUpdateState) {
// changes.
TEST_F(RenderViewImplTest, OnImeTypeChanged) {
// Load an HTML page consisting of two input fields.
- view()->set_send_content_state_immediately(true);
LoadHTML("<html>"
"<head>"
"</head>"
@@ -1291,7 +1259,6 @@ TEST_F(RenderViewImplTest, ImeComposition) {
// Load an HTML page consisting of a content-editable <div> element,
// and move the input focus to the <div> element, where we can use
// IMEs.
- view()->set_send_content_state_immediately(true);
LoadHTML("<html>"
"<head>"
"</head>"
@@ -1314,6 +1281,7 @@ TEST_F(RenderViewImplTest, ImeComposition) {
view()->OnImeSetComposition(
base::WideToUTF16(ime_message->ime_string),
std::vector<blink::WebCompositionUnderline>(),
+ gfx::Range::InvalidRange(),
ime_message->selection_start,
ime_message->selection_end);
break;
@@ -1329,6 +1297,7 @@ TEST_F(RenderViewImplTest, ImeComposition) {
view()->OnImeSetComposition(
base::string16(),
std::vector<blink::WebCompositionUnderline>(),
+ gfx::Range::InvalidRange(),
0, 0);
break;
}
@@ -1343,8 +1312,8 @@ TEST_F(RenderViewImplTest, ImeComposition) {
// Retrieve the content of this page and compare it with the expected
// result.
const int kMaxOutputCharacters = 128;
- base::string16 output =
- GetMainFrame()->contentAsText(kMaxOutputCharacters);
+ base::string16 output = WebFrameContentDumper::dumpWebViewAsText(
+ view()->GetWebView(), kMaxOutputCharacters);
EXPECT_EQ(base::WideToUTF16(ime_message->result), output);
}
}
@@ -1357,7 +1326,6 @@ TEST_F(RenderViewImplTest, OnSetTextDirection) {
// This test changes the text direction of the <textarea> element, and
// writes the values of its 'dir' attribute and its 'direction' property to
// verify that the text direction is changed.
- view()->set_send_content_state_immediately(true);
LoadHTML("<html>"
"<head>"
"</head>"
@@ -1393,386 +1361,12 @@ TEST_F(RenderViewImplTest, OnSetTextDirection) {
// Copy the document content to std::wstring and compare with the
// expected result.
const int kMaxOutputCharacters = 16;
- base::string16 output = GetMainFrame()->contentAsText(kMaxOutputCharacters);
+ base::string16 output = WebFrameContentDumper::dumpWebViewAsText(
+ view()->GetWebView(), kMaxOutputCharacters);
EXPECT_EQ(base::WideToUTF16(kTextDirection[i].expected_result), output);
}
}
-// Test that we can receive correct DOM events when we send input events
-// through the RenderWidget::OnHandleInputEvent() function.
-TEST_F(RenderViewImplTest, OnHandleKeyboardEvent) {
-#if !defined(OS_MACOSX)
- // Load an HTML page consisting of one <input> element and three
- // contentediable <div> elements.
- // The <input> element is used for sending keyboard events, and the <div>
- // elements are used for writing DOM events in the following format:
- // "<keyCode>,<shiftKey>,<controlKey>,<altKey>".
- // TODO(hbono): <http://crbug.com/2215> Our WebKit port set |ev.metaKey| to
- // true when pressing an alt key, i.e. the |ev.metaKey| value is not
- // trustworthy. We will check the |ev.metaKey| value when this issue is fixed.
- view()->set_send_content_state_immediately(true);
- LoadHTML("<html>"
- "<head>"
- "<title></title>"
- "<script type='text/javascript' language='javascript'>"
- "function OnKeyEvent(ev) {"
- " var result = document.getElementById(ev.type);"
- " result.innerText ="
- " (ev.which || ev.keyCode) + ',' +"
- " ev.shiftKey + ',' +"
- " ev.ctrlKey + ',' +"
- " ev.altKey;"
- " return true;"
- "}"
- "</script>"
- "</head>"
- "<body>"
- "<input id='test' type='text'"
- " onkeydown='return OnKeyEvent(event);'"
- " onkeypress='return OnKeyEvent(event);'"
- " onkeyup='return OnKeyEvent(event);'>"
- "</input>"
- "<div id='keydown' contenteditable='true'>"
- "</div>"
- "<div id='keypress' contenteditable='true'>"
- "</div>"
- "<div id='keyup' contenteditable='true'>"
- "</div>"
- "</body>"
- "</html>");
- ExecuteJavaScriptForTests("document.getElementById('test').focus();");
- render_thread_->sink().ClearMessages();
-
- static const MockKeyboard::Layout kLayouts[] = {
-#if defined(OS_WIN)
- // Since we ignore the mock keyboard layout on Linux and instead just use
- // the screen's keyboard layout, these trivially pass. They are commented
- // out to avoid the illusion that they work.
- MockKeyboard::LAYOUT_ARABIC,
- MockKeyboard::LAYOUT_CANADIAN_FRENCH,
- MockKeyboard::LAYOUT_FRENCH,
- MockKeyboard::LAYOUT_HEBREW,
- MockKeyboard::LAYOUT_RUSSIAN,
-#endif
- MockKeyboard::LAYOUT_UNITED_STATES,
- };
-
- for (size_t i = 0; i < arraysize(kLayouts); ++i) {
- // For each key code, we send three keyboard events.
- // * we press only the key;
- // * we press the key and a left-shift key, and;
- // * we press the key and a right-alt (AltGr) key.
- // For each modifiers, we need a string used for formatting its expected
- // result. (See the above comment for its format.)
- static const struct {
- MockKeyboard::Modifiers modifiers;
- const char* expected_result;
- } kModifierData[] = {
- {MockKeyboard::NONE, "false,false,false"},
- {MockKeyboard::LEFT_SHIFT, "true,false,false"},
-#if defined(OS_WIN)
- {MockKeyboard::RIGHT_ALT, "false,false,true"},
-#endif
- };
-
- MockKeyboard::Layout layout = kLayouts[i];
- for (size_t j = 0; j < arraysize(kModifierData); ++j) {
- // Virtual key codes used for this test.
- static const int kKeyCodes[] = {
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
- 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
- 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
- 'W', 'X', 'Y', 'Z',
- ui::VKEY_OEM_1,
- ui::VKEY_OEM_PLUS,
- ui::VKEY_OEM_COMMA,
- ui::VKEY_OEM_MINUS,
- ui::VKEY_OEM_PERIOD,
- ui::VKEY_OEM_2,
- ui::VKEY_OEM_3,
- ui::VKEY_OEM_4,
- ui::VKEY_OEM_5,
- ui::VKEY_OEM_6,
- ui::VKEY_OEM_7,
-#if defined(OS_WIN)
- // Not sure how to handle this key on Linux.
- ui::VKEY_OEM_8,
-#endif
- };
-
- MockKeyboard::Modifiers modifiers = kModifierData[j].modifiers;
- for (size_t k = 0; k < arraysize(kKeyCodes); ++k) {
- // Send a keyboard event to the RenderView object.
- // We should test a keyboard event only when the given keyboard-layout
- // driver is installed in a PC and the driver can assign a Unicode
- // charcter for the given tuple (key-code and modifiers).
- int key_code = kKeyCodes[k];
- base::string16 char_code;
- if (SendKeyEvent(layout, key_code, modifiers, &char_code) < 0)
- continue;
-
- // Create an expected result from the virtual-key code, the character
- // code, and the modifier-key status.
- // We format a string that emulates a DOM-event string produced hy
- // our JavaScript function. (See the above comment for the format.)
- static char expected_result[1024];
- expected_result[0] = 0;
- base::snprintf(&expected_result[0],
- sizeof(expected_result),
- "\n" // texts in the <input> element
- "%d,%s\n" // texts in the first <div> element
- "%d,%s\n" // texts in the second <div> element
- "%d,%s", // texts in the third <div> element
- key_code, kModifierData[j].expected_result,
- static_cast<int>(char_code[0]),
- kModifierData[j].expected_result,
- key_code, kModifierData[j].expected_result);
-
- // Retrieve the text in the test page and compare it with the expected
- // text created from a virtual-key code, a character code, and the
- // modifier-key status.
- const int kMaxOutputCharacters = 1024;
- std::string output = base::UTF16ToUTF8(base::StringPiece16(
- GetMainFrame()->contentAsText(kMaxOutputCharacters)));
- EXPECT_EQ(expected_result, output);
- }
- }
- }
-#else
- NOTIMPLEMENTED();
-#endif
-}
-
-// Test that our EditorClientImpl class can insert characters when we send
-// keyboard events through the RenderWidget::OnHandleInputEvent() function.
-// This test is for preventing regressions caused only when we use non-US
-// keyboards, such as Issue 10846.
-// see http://crbug.com/244562
-#if defined(OS_WIN)
-#define MAYBE_InsertCharacters DISABLED_InsertCharacters
-#else
-#define MAYBE_InsertCharacters InsertCharacters
-#endif
-TEST_F(RenderViewImplTest, MAYBE_InsertCharacters) {
-#if !defined(OS_MACOSX)
- static const struct {
- MockKeyboard::Layout layout;
- const wchar_t* expected_result;
- } kLayouts[] = {
-#if 0
- // Disabled these keyboard layouts because buildbots do not have their
- // keyboard-layout drivers installed.
- {MockKeyboard::LAYOUT_ARABIC,
- L"\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037"
- L"\x0038\x0039\x0634\x0624\x064a\x062b\x0628\x0644"
- L"\x0627\x0647\x062a\x0646\x0645\x0629\x0649\x062e"
- L"\x062d\x0636\x0642\x0633\x0641\x0639\x0631\x0635"
- L"\x0621\x063a\x0626\x0643\x003d\x0648\x002d\x0632"
- L"\x0638\x0630\x062c\x005c\x062f\x0637\x0028\x0021"
- L"\x0040\x0023\x0024\x0025\x005e\x0026\x002a\x0029"
- L"\x0650\x007d\x005d\x064f\x005b\x0623\x00f7\x0640"
- L"\x060c\x002f\x2019\x0622\x00d7\x061b\x064e\x064c"
- L"\x064d\x2018\x007b\x064b\x0652\x0625\x007e\x003a"
- L"\x002b\x002c\x005f\x002e\x061f\x0651\x003c\x007c"
- L"\x003e\x0022\x0030\x0031\x0032\x0033\x0034\x0035"
- L"\x0036\x0037\x0038\x0039\x0634\x0624\x064a\x062b"
- L"\x0628\x0644\x0627\x0647\x062a\x0646\x0645\x0629"
- L"\x0649\x062e\x062d\x0636\x0642\x0633\x0641\x0639"
- L"\x0631\x0635\x0621\x063a\x0626\x0643\x003d\x0648"
- L"\x002d\x0632\x0638\x0630\x062c\x005c\x062f\x0637"
- },
- {MockKeyboard::LAYOUT_HEBREW,
- L"\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037"
- L"\x0038\x0039\x05e9\x05e0\x05d1\x05d2\x05e7\x05db"
- L"\x05e2\x05d9\x05df\x05d7\x05dc\x05da\x05e6\x05de"
- L"\x05dd\x05e4\x002f\x05e8\x05d3\x05d0\x05d5\x05d4"
- L"\x0027\x05e1\x05d8\x05d6\x05e3\x003d\x05ea\x002d"
- L"\x05e5\x002e\x003b\x005d\x005c\x005b\x002c\x0028"
- L"\x0021\x0040\x0023\x0024\x0025\x005e\x0026\x002a"
- L"\x0029\x0041\x0042\x0043\x0044\x0045\x0046\x0047"
- L"\x0048\x0049\x004a\x004b\x004c\x004d\x004e\x004f"
- L"\x0050\x0051\x0052\x0053\x0054\x0055\x0056\x0057"
- L"\x0058\x0059\x005a\x003a\x002b\x003e\x005f\x003c"
- L"\x003f\x007e\x007d\x007c\x007b\x0022\x0030\x0031"
- L"\x0032\x0033\x0034\x0035\x0036\x0037\x0038\x0039"
- L"\x05e9\x05e0\x05d1\x05d2\x05e7\x05db\x05e2\x05d9"
- L"\x05df\x05d7\x05dc\x05da\x05e6\x05de\x05dd\x05e4"
- L"\x002f\x05e8\x05d3\x05d0\x05d5\x05d4\x0027\x05e1"
- L"\x05d8\x05d6\x05e3\x003d\x05ea\x002d\x05e5\x002e"
- L"\x003b\x005d\x005c\x005b\x002c"
- },
-#endif
-#if defined(OS_WIN)
- // On Linux, the only way to test alternate keyboard layouts is to change
- // the keyboard layout of the whole screen. I'm worried about the side
- // effects this may have on the buildbots.
- {MockKeyboard::LAYOUT_CANADIAN_FRENCH,
- L"\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037"
- L"\x0038\x0039\x0061\x0062\x0063\x0064\x0065\x0066"
- L"\x0067\x0068\x0069\x006a\x006b\x006c\x006d\x006e"
- L"\x006f\x0070\x0071\x0072\x0073\x0074\x0075\x0076"
- L"\x0077\x0078\x0079\x007a\x003b\x003d\x002c\x002d"
- L"\x002e\x00e9\x003c\x0029\x0021\x0022\x002f\x0024"
- L"\x0025\x003f\x0026\x002a\x0028\x0041\x0042\x0043"
- L"\x0044\x0045\x0046\x0047\x0048\x0049\x004a\x004b"
- L"\x004c\x004d\x004e\x004f\x0050\x0051\x0052\x0053"
- L"\x0054\x0055\x0056\x0057\x0058\x0059\x005a\x003a"
- L"\x002b\x0027\x005f\x002e\x00c9\x003e\x0030\x0031"
- L"\x0032\x0033\x0034\x0035\x0036\x0037\x0038\x0039"
- L"\x0061\x0062\x0063\x0064\x0065\x0066\x0067\x0068"
- L"\x0069\x006a\x006b\x006c\x006d\x006e\x006f\x0070"
- L"\x0071\x0072\x0073\x0074\x0075\x0076\x0077\x0078"
- L"\x0079\x007a\x003b\x003d\x002c\x002d\x002e\x00e9"
- L"\x003c"
- },
- {MockKeyboard::LAYOUT_FRENCH,
- L"\x00e0\x0026\x00e9\x0022\x0027\x0028\x002d\x00e8"
- L"\x005f\x00e7\x0061\x0062\x0063\x0064\x0065\x0066"
- L"\x0067\x0068\x0069\x006a\x006b\x006c\x006d\x006e"
- L"\x006f\x0070\x0071\x0072\x0073\x0074\x0075\x0076"
- L"\x0077\x0078\x0079\x007a\x0024\x003d\x002c\x003b"
- L"\x003a\x00f9\x0029\x002a\x0021\x0030\x0031\x0032"
- L"\x0033\x0034\x0035\x0036\x0037\x0038\x0039\x0041"
- L"\x0042\x0043\x0044\x0045\x0046\x0047\x0048\x0049"
- L"\x004a\x004b\x004c\x004d\x004e\x004f\x0050\x0051"
- L"\x0052\x0053\x0054\x0055\x0056\x0057\x0058\x0059"
- L"\x005a\x00a3\x002b\x003f\x002e\x002f\x0025\x00b0"
- L"\x00b5\x00e0\x0026\x00e9\x0022\x0027\x0028\x002d"
- L"\x00e8\x005f\x00e7\x0061\x0062\x0063\x0064\x0065"
- L"\x0066\x0067\x0068\x0069\x006a\x006b\x006c\x006d"
- L"\x006e\x006f\x0070\x0071\x0072\x0073\x0074\x0075"
- L"\x0076\x0077\x0078\x0079\x007a\x0024\x003d\x002c"
- L"\x003b\x003a\x00f9\x0029\x002a\x0021"
- },
- {MockKeyboard::LAYOUT_RUSSIAN,
- L"\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037"
- L"\x0038\x0039\x0444\x0438\x0441\x0432\x0443\x0430"
- L"\x043f\x0440\x0448\x043e\x043b\x0434\x044c\x0442"
- L"\x0449\x0437\x0439\x043a\x044b\x0435\x0433\x043c"
- L"\x0446\x0447\x043d\x044f\x0436\x003d\x0431\x002d"
- L"\x044e\x002e\x0451\x0445\x005c\x044a\x044d\x0029"
- L"\x0021\x0022\x2116\x003b\x0025\x003a\x003f\x002a"
- L"\x0028\x0424\x0418\x0421\x0412\x0423\x0410\x041f"
- L"\x0420\x0428\x041e\x041b\x0414\x042c\x0422\x0429"
- L"\x0417\x0419\x041a\x042b\x0415\x0413\x041c\x0426"
- L"\x0427\x041d\x042f\x0416\x002b\x0411\x005f\x042e"
- L"\x002c\x0401\x0425\x002f\x042a\x042d\x0030\x0031"
- L"\x0032\x0033\x0034\x0035\x0036\x0037\x0038\x0039"
- L"\x0444\x0438\x0441\x0432\x0443\x0430\x043f\x0440"
- L"\x0448\x043e\x043b\x0434\x044c\x0442\x0449\x0437"
- L"\x0439\x043a\x044b\x0435\x0433\x043c\x0446\x0447"
- L"\x043d\x044f\x0436\x003d\x0431\x002d\x044e\x002e"
- L"\x0451\x0445\x005c\x044a\x044d"
- },
-#endif // defined(OS_WIN)
- {MockKeyboard::LAYOUT_UNITED_STATES,
- L"\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037"
- L"\x0038\x0039\x0061\x0062\x0063\x0064\x0065\x0066"
- L"\x0067\x0068\x0069\x006a\x006b\x006c\x006d\x006e"
- L"\x006f\x0070\x0071\x0072\x0073\x0074\x0075\x0076"
- L"\x0077\x0078\x0079\x007a\x003b\x003d\x002c\x002d"
- L"\x002e\x002f\x0060\x005b\x005c\x005d\x0027\x0029"
- L"\x0021\x0040\x0023\x0024\x0025\x005e\x0026\x002a"
- L"\x0028\x0041\x0042\x0043\x0044\x0045\x0046\x0047"
- L"\x0048\x0049\x004a\x004b\x004c\x004d\x004e\x004f"
- L"\x0050\x0051\x0052\x0053\x0054\x0055\x0056\x0057"
- L"\x0058\x0059\x005a\x003a\x002b\x003c\x005f\x003e"
- L"\x003f\x007e\x007b\x007c\x007d\x0022"
-#if defined(OS_WIN)
- // This is ifdefed out for Linux to correspond to the fact that we don't
- // test alt+keystroke for now.
- L"\x0030\x0031\x0032\x0033\x0034\x0035\x0036\x0037"
- L"\x0038\x0039\x0061\x0062\x0063\x0064\x0065\x0066"
- L"\x0067\x0068\x0069\x006a\x006b\x006c\x006d\x006e"
- L"\x006f\x0070\x0071\x0072\x0073\x0074\x0075\x0076"
- L"\x0077\x0078\x0079\x007a\x003b\x003d\x002c\x002d"
- L"\x002e\x002f\x0060\x005b\x005c\x005d\x0027"
-#endif
- },
- };
-
- for (size_t i = 0; i < arraysize(kLayouts); ++i) {
- // Load an HTML page consisting of one <div> element.
- // This <div> element is used by the EditorClientImpl class to insert
- // characters received through the RenderWidget::OnHandleInputEvent()
- // function.
- view()->set_send_content_state_immediately(true);
- LoadHTML("<html>"
- "<head>"
- "<title></title>"
- "</head>"
- "<body>"
- "<div id='test' contenteditable='true'>"
- "</div>"
- "</body>"
- "</html>");
- ExecuteJavaScriptForTests("document.getElementById('test').focus();");
- render_thread_->sink().ClearMessages();
-
- // For each key code, we send three keyboard events.
- // * Pressing only the key;
- // * Pressing the key and a left-shift key, and;
- // * Pressing the key and a right-alt (AltGr) key.
- static const MockKeyboard::Modifiers kModifiers[] = {
- MockKeyboard::NONE,
- MockKeyboard::LEFT_SHIFT,
-#if defined(OS_WIN)
- MockKeyboard::RIGHT_ALT,
-#endif
- };
-
- MockKeyboard::Layout layout = kLayouts[i].layout;
- for (size_t j = 0; j < arraysize(kModifiers); ++j) {
- // Virtual key codes used for this test.
- static const int kKeyCodes[] = {
- '0', '1', '2', '3', '4', '5', '6', '7',
- '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
- 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
- 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
- 'W', 'X', 'Y', 'Z',
- ui::VKEY_OEM_1,
- ui::VKEY_OEM_PLUS,
- ui::VKEY_OEM_COMMA,
- ui::VKEY_OEM_MINUS,
- ui::VKEY_OEM_PERIOD,
- ui::VKEY_OEM_2,
- ui::VKEY_OEM_3,
- ui::VKEY_OEM_4,
- ui::VKEY_OEM_5,
- ui::VKEY_OEM_6,
- ui::VKEY_OEM_7,
-#if defined(OS_WIN)
- // Unclear how to handle this on Linux.
- ui::VKEY_OEM_8,
-#endif
- };
-
- MockKeyboard::Modifiers modifiers = kModifiers[j];
- for (size_t k = 0; k < arraysize(kKeyCodes); ++k) {
- // Send a keyboard event to the RenderView object.
- // We should test a keyboard event only when the given keyboard-layout
- // driver is installed in a PC and the driver can assign a Unicode
- // charcter for the given tuple (layout, key-code, and modifiers).
- int key_code = kKeyCodes[k];
- base::string16 char_code;
- if (SendKeyEvent(layout, key_code, modifiers, &char_code) < 0)
- continue;
- }
- }
-
- // Retrieve the text in the test page and compare it with the expected
- // text created from a virtual-key code, a character code, and the
- // modifier-key status.
- const int kMaxOutputCharacters = 4096;
- base::string16 output = GetMainFrame()->contentAsText(kMaxOutputCharacters);
- EXPECT_EQ(base::WideToUTF16(kLayouts[i].expected_result), output);
- }
-#else
- NOTIMPLEMENTED();
-#endif
-}
-
// Crashy, http://crbug.com/53247.
TEST_F(RenderViewImplTest, DISABLED_DidFailProvisionalLoadWithErrorForError) {
GetMainFrame()->enableViewSourceMode(true);
@@ -1891,26 +1485,38 @@ TEST_F(RenderViewImplTest, TestBackForward) {
EXPECT_EQ(1, was_page_c);
PageState forward_state = GetCurrentPageState();
- GoBack(back_state);
+
+ // Go back.
+ GoBack(GURL("data:text/html;charset=utf-8,<div id=pagename>Page B</div>"),
+ back_state);
+
EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_b, &was_page_b));
EXPECT_EQ(1, was_page_b);
-
PageState back_state2 = GetCurrentPageState();
- GoForward(forward_state);
+ // Go forward.
+ GoForward(GURL("data:text/html;charset=utf-8,<div id=pagename>Page C</div>"),
+ forward_state);
EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_c, &was_page_c));
EXPECT_EQ(1, was_page_c);
- GoBack(back_state2);
+ // Go back.
+ GoBack(GURL("data:text/html;charset=utf-8,<div id=pagename>Page B</div>"),
+ back_state2);
EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_b, &was_page_b));
EXPECT_EQ(1, was_page_b);
forward_state = GetCurrentPageState();
- GoBack(page_a_state);
+
+ // Go back.
+ GoBack(GURL("data:text/html;charset=utf-8,<div id=pagename>Page A</div>"),
+ page_a_state);
EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_a, &was_page_a));
EXPECT_EQ(1, was_page_a);
- GoForward(forward_state);
+ // Go forward.
+ GoForward(GURL("data:text/html;charset=utf-8,<div id=pagename>Page B</div>"),
+ forward_state);
EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(check_page_b, &was_page_b));
EXPECT_EQ(1, was_page_b);
}
@@ -1921,12 +1527,9 @@ TEST_F(RenderViewImplTest, GetCompositionCharacterBoundsTest) {
// http://crbug.com/304193
if (base::win::GetVersion() < base::win::VERSION_VISTA)
return;
- // http://crbug.com/508747
- if (base::win::GetVersion() >= base::win::VERSION_WIN10)
- return;
#endif
- LoadHTML("<textarea id=\"test\"></textarea>");
+ LoadHTML("<textarea id=\"test\" cols=\"100\"></textarea>");
ExecuteJavaScriptForTests("document.getElementById('test').focus();");
const base::string16 empty_string;
@@ -1936,7 +1539,8 @@ TEST_F(RenderViewImplTest, GetCompositionCharacterBoundsTest) {
// ASCII composition
const base::string16 ascii_composition = base::UTF8ToUTF16("aiueo");
- view()->OnImeSetComposition(ascii_composition, empty_underline, 0, 0);
+ view()->OnImeSetComposition(ascii_composition, empty_underline,
+ gfx::Range::InvalidRange(), 0, 0);
view()->GetCompositionCharacterBounds(&bounds);
ASSERT_EQ(ascii_composition.size(), bounds.size());
@@ -1948,7 +1552,8 @@ TEST_F(RenderViewImplTest, GetCompositionCharacterBoundsTest) {
// Non surrogate pair unicode character.
const base::string16 unicode_composition = base::UTF8ToUTF16(
"\xE3\x81\x82\xE3\x81\x84\xE3\x81\x86\xE3\x81\x88\xE3\x81\x8A");
- view()->OnImeSetComposition(unicode_composition, empty_underline, 0, 0);
+ view()->OnImeSetComposition(unicode_composition, empty_underline,
+ gfx::Range::InvalidRange(), 0, 0);
view()->GetCompositionCharacterBounds(&bounds);
ASSERT_EQ(unicode_composition.size(), bounds.size());
for (size_t i = 0; i < bounds.size(); ++i)
@@ -1961,6 +1566,7 @@ TEST_F(RenderViewImplTest, GetCompositionCharacterBoundsTest) {
base::UTF8ToUTF16("\xF0\xA0\xAE\x9F");
view()->OnImeSetComposition(surrogate_pair_char,
empty_underline,
+ gfx::Range::InvalidRange(),
0,
0);
view()->GetCompositionCharacterBounds(&bounds);
@@ -1979,6 +1585,7 @@ TEST_F(RenderViewImplTest, GetCompositionCharacterBoundsTest) {
false, true, false, false, true, false, false, true };
view()->OnImeSetComposition(surrogate_pair_mixed_composition,
empty_underline,
+ gfx::Range::InvalidRange(),
0,
0);
view()->GetCompositionCharacterBounds(&bounds);
@@ -2096,8 +1703,9 @@ TEST_F(RenderViewImplTest, NavigateSubframe) {
// Copy the document content to std::wstring and compare with the
// expected result.
const int kMaxOutputCharacters = 256;
- std::string output = base::UTF16ToUTF8(base::StringPiece16(
- GetMainFrame()->contentAsText(kMaxOutputCharacters)));
+ std::string output = base::UTF16ToUTF8(
+ base::StringPiece16(WebFrameContentDumper::dumpWebViewAsText(
+ view()->GetWebView(), kMaxOutputCharacters)));
EXPECT_EQ(output, "hello \n\nworld");
}
@@ -2123,7 +1731,6 @@ TEST_F(RenderViewImplTest, GetSSLStatusOfFrame) {
}
TEST_F(RenderViewImplTest, MessageOrderInDidChangeSelection) {
- view()->set_send_content_state_immediately(true);
LoadHTML("<textarea id=\"test\"></textarea>");
view()->SetHandlingInputEventForTesting(true);
@@ -2217,8 +1824,9 @@ TEST_F(RendererErrorPageTest, MAYBE_Suppresses) {
main_frame->didFailProvisionalLoad(web_frame, error,
blink::WebStandardCommit);
const int kMaxOutputCharacters = 22;
- EXPECT_EQ("", base::UTF16ToASCII(
- base::StringPiece16(web_frame->contentAsText(kMaxOutputCharacters))));
+ EXPECT_EQ("", base::UTF16ToASCII(base::StringPiece16(
+ WebFrameContentDumper::dumpWebViewAsText(
+ view()->GetWebView(), kMaxOutputCharacters))));
}
#if defined(OS_ANDROID)
@@ -2252,8 +1860,9 @@ TEST_F(RendererErrorPageTest, MAYBE_DoesNotSuppress) {
FrameLoadWaiter(main_frame).Wait();
const int kMaxOutputCharacters = 22;
EXPECT_EQ("A suffusion of yellow.",
- base::UTF16ToASCII(base::StringPiece16(
- web_frame->contentAsText(kMaxOutputCharacters))));
+ base::UTF16ToASCII(
+ base::StringPiece16(WebFrameContentDumper::dumpWebViewAsText(
+ view()->GetWebView(), kMaxOutputCharacters))));
}
#if defined(OS_ANDROID)
@@ -2279,15 +1888,17 @@ TEST_F(RendererErrorPageTest, MAYBE_HttpStatusCodeErrorWithEmptyBody) {
RequestNavigationParams());
// Emulate a 4xx/5xx main resource response with an empty body.
- main_frame->didReceiveResponse(web_frame, 1, response);
- main_frame->didFinishDocumentLoad(web_frame, true);
+ main_frame->didReceiveResponse(1, response);
+ main_frame->didFinishDocumentLoad(web_frame);
+ main_frame->runScriptsAtDocumentReady(web_frame, true);
// The error page itself is loaded asynchronously.
FrameLoadWaiter(main_frame).Wait();
const int kMaxOutputCharacters = 22;
EXPECT_EQ("A suffusion of yellow.",
- base::UTF16ToASCII(base::StringPiece16(
- web_frame->contentAsText(kMaxOutputCharacters))));
+ base::UTF16ToASCII(
+ base::StringPiece16(WebFrameContentDumper::dumpWebViewAsText(
+ view()->GetWebView(), kMaxOutputCharacters))));
}
// Ensure the render view sends favicon url update events correctly.
@@ -2355,7 +1966,7 @@ TEST_F(RenderViewImplTest, ServiceWorkerNetworkProviderSetup) {
DocumentState::FromDataSource(GetMainFrame()->dataSource()));
ASSERT_TRUE(provider);
extra_data = static_cast<RequestExtraData*>(
- GetMainFrame()->dataSource()->request().extraData());
+ GetMainFrame()->dataSource()->request().getExtraData());
ASSERT_TRUE(extra_data);
EXPECT_EQ(extra_data->service_worker_provider_id(),
provider->provider_id());
@@ -2368,7 +1979,7 @@ TEST_F(RenderViewImplTest, ServiceWorkerNetworkProviderSetup) {
ASSERT_TRUE(provider);
EXPECT_NE(provider1_id, provider->provider_id());
extra_data = static_cast<RequestExtraData*>(
- GetMainFrame()->dataSource()->request().extraData());
+ GetMainFrame()->dataSource()->request().getExtraData());
ASSERT_TRUE(extra_data);
EXPECT_EQ(extra_data->service_worker_provider_id(),
provider->provider_id());
@@ -2379,7 +1990,7 @@ TEST_F(RenderViewImplTest, ServiceWorkerNetworkProviderSetup) {
request.setRequestContext(blink::WebURLRequest::RequestContextSubresource);
blink::WebURLResponse redirect_response;
frame()->willSendRequest(GetMainFrame(), 0, request, redirect_response);
- extra_data = static_cast<RequestExtraData*>(request.extraData());
+ extra_data = static_cast<RequestExtraData*>(request.getExtraData());
ASSERT_TRUE(extra_data);
EXPECT_EQ(extra_data->service_worker_provider_id(),
provider->provider_id());
@@ -2402,36 +2013,6 @@ TEST_F(RenderViewImplTest, OnSetAccessibilityMode) {
ASSERT_NE((RendererAccessibility*) NULL, frame()->renderer_accessibility());
}
-TEST_F(RenderViewImplTest, ScreenMetricsEmulation) {
- LoadHTML("<body style='min-height:1000px;'></body>");
-
- blink::WebDeviceEmulationParams params;
- base::string16 get_width = base::ASCIIToUTF16("Number(window.innerWidth)");
- base::string16 get_height = base::ASCIIToUTF16("Number(window.innerHeight)");
- int width, height;
-
- params.viewSize.width = 327;
- params.viewSize.height = 415;
- view()->OnEnableDeviceEmulation(params);
- EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(get_width, &width));
- EXPECT_EQ(params.viewSize.width, width);
- EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(get_height, &height));
- EXPECT_EQ(params.viewSize.height, height);
-
- params.viewSize.width = 1005;
- params.viewSize.height = 1102;
- view()->OnEnableDeviceEmulation(params);
- EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(get_width, &width));
- EXPECT_EQ(params.viewSize.width, width);
- EXPECT_TRUE(ExecuteJavaScriptAndReturnIntValue(get_height, &height));
- EXPECT_EQ(params.viewSize.height, height);
-
- view()->OnDisableDeviceEmulation();
-
- view()->OnEnableDeviceEmulation(params);
- // Don't disable here to test that emulation is being shutdown properly.
-}
-
// Sanity check for the Navigation Timing API |navigationStart| override. We
// are asserting only most basic constraints, as TimeTicks (passed as the
// override) are not comparable with the wall time (returned by the Blink API).
@@ -2440,15 +2021,14 @@ TEST_F(RenderViewImplTest, NavigationStartOverride) {
// days from now is *not* reported as one that starts in the future; as we
// sanitize the override allowing a maximum of ::Now().
CommonNavigationParams late_common_params;
- StartNavigationParams late_start_params;
late_common_params.url = GURL("data:text/html,<div>Another page</div>");
late_common_params.navigation_type = FrameMsg_Navigate_Type::NORMAL;
late_common_params.transition = ui::PAGE_TRANSITION_TYPED;
late_common_params.navigation_start =
base::TimeTicks::Now() + base::TimeDelta::FromDays(42);
- late_start_params.is_post = true;
+ late_common_params.method = "POST";
- frame()->Navigate(late_common_params, late_start_params,
+ frame()->Navigate(late_common_params, StartNavigationParams(),
RequestNavigationParams());
ProcessPendingMessages();
base::Time after_navigation =
@@ -2507,25 +2087,30 @@ TEST_F(RenderViewImplTest, BrowserNavigationStartNotUsedForHistoryNavigation) {
ProcessPendingMessages();
render_thread_->sink().ClearMessages();
- CommonNavigationParams common_params;
- common_params.transition = ui::PAGE_TRANSITION_FORWARD_BACK;
// Go back.
- GoToOffsetWithParams(-1, back_state, common_params, StartNavigationParams(),
- RequestNavigationParams());
+ CommonNavigationParams common_params_back;
+ common_params_back.url =
+ GURL("data:text/html;charset=utf-8,<div id=pagename>Page B</div>");
+ common_params_back.transition = ui::PAGE_TRANSITION_FORWARD_BACK;
+ GoToOffsetWithParams(-1, back_state, common_params_back,
+ StartNavigationParams(), RequestNavigationParams());
FrameHostMsg_DidStartProvisionalLoad::Param host_nav_params =
ProcessAndReadIPC<FrameHostMsg_DidStartProvisionalLoad>();
EXPECT_PRED2(TimeTicksGT, base::get<1>(host_nav_params),
- common_params.navigation_start);
+ common_params_back.navigation_start);
render_thread_->sink().ClearMessages();
// Go forward.
- GoToOffsetWithParams(1, forward_state, common_params,
- StartNavigationParams(),
- RequestNavigationParams());
+ CommonNavigationParams common_params_forward;
+ common_params_forward.url =
+ GURL("data:text/html;charset=utf-8,<div id=pagename>Page C</div>");
+ common_params_forward.transition = ui::PAGE_TRANSITION_FORWARD_BACK;
+ GoToOffsetWithParams(1, forward_state, common_params_forward,
+ StartNavigationParams(), RequestNavigationParams());
FrameHostMsg_DidStartProvisionalLoad::Param host_nav_params2 =
ProcessAndReadIPC<FrameHostMsg_DidStartProvisionalLoad>();
EXPECT_PRED2(TimeTicksGT, base::get<1>(host_nav_params2),
- common_params.navigation_start);
+ common_params_forward.navigation_start);
}
TEST_F(RenderViewImplTest, BrowserNavigationStartSuccessfullyTransmitted) {
@@ -2603,6 +2188,8 @@ TEST_F(RenderViewImplBlinkSettingsTest, Negative) {
TEST_F(RenderViewImplScaleFactorTest, ConverViewportToWindowWithoutZoomForDSF) {
DoSetUp();
+ if (IsUseZoomForDSFEnabled())
+ return;
SetDeviceScaleFactor(2.f);
blink::WebRect rect(20, 10, 200, 100);
view()->convertViewportToWindow(&rect);
@@ -2612,6 +2199,66 @@ TEST_F(RenderViewImplScaleFactorTest, ConverViewportToWindowWithoutZoomForDSF) {
EXPECT_EQ(100, rect.height);
}
+TEST_F(RenderViewImplScaleFactorTest, ScreenMetricsEmulationWithOriginalDSF1) {
+ DoSetUp();
+ SetDeviceScaleFactor(1.f);
+
+ LoadHTML("<body style='min-height:1000px;'></body>");
+ {
+ SCOPED_TRACE("327x415 1dpr");
+ TestEmulatedSizeDprDsf(327, 415, 1.f, 1.f);
+ }
+ {
+ SCOPED_TRACE("327x415 1.5dpr");
+ TestEmulatedSizeDprDsf(327, 415, 1.5f, 1.f);
+ }
+ {
+ SCOPED_TRACE("1005x1102 2dpr");
+ TestEmulatedSizeDprDsf(1005, 1102, 2.f, 1.f);
+ }
+ {
+ SCOPED_TRACE("1005x1102 3dpr");
+ TestEmulatedSizeDprDsf(1005, 1102, 3.f, 1.f);
+ }
+
+ view()->OnDisableDeviceEmulation();
+
+ blink::WebDeviceEmulationParams params;
+ view()->OnEnableDeviceEmulation(params);
+ // Don't disable here to test that emulation is being shutdown properly.
+}
+
+TEST_F(RenderViewImplScaleFactorTest, ScreenMetricsEmulationWithOriginalDSF2) {
+ DoSetUp();
+ SetDeviceScaleFactor(2.f);
+ float compositor_dsf =
+ IsUseZoomForDSFEnabled() ? 1.f : 2.f;
+
+ LoadHTML("<body style='min-height:1000px;'></body>");
+ {
+ SCOPED_TRACE("327x415 1dpr");
+ TestEmulatedSizeDprDsf(327, 415, 1.f, compositor_dsf);
+ }
+ {
+ SCOPED_TRACE("327x415 1.5dpr");
+ TestEmulatedSizeDprDsf(327, 415, 1.5f, compositor_dsf);
+ }
+ {
+ SCOPED_TRACE("1005x1102 2dpr");
+ TestEmulatedSizeDprDsf(1005, 1102, 2.f, compositor_dsf);
+ }
+ {
+ SCOPED_TRACE("1005x1102 3dpr");
+ TestEmulatedSizeDprDsf(1005, 1102, 3.f, compositor_dsf);
+ }
+
+ view()->OnDisableDeviceEmulation();
+
+ blink::WebDeviceEmulationParams params;
+ view()->OnEnableDeviceEmulation(params);
+ // Don't disable here to test that emulation is being shutdown properly.
+}
+
TEST_F(RenderViewImplScaleFactorTest, ConverViewportToWindowWithZoomForDSF) {
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableUseZoomForDSF);
@@ -2638,7 +2285,8 @@ TEST_F(RenderViewImplScaleFactorTest, ConverViewportToWindowWithZoomForDSF) {
}
#if defined(OS_MACOSX) || defined(USE_AURA)
-TEST_F(RenderViewImplScaleFactorTest, GetCompositionCharacterBoundsTest) {
+TEST_F(RenderViewImplScaleFactorTest,
+ DISABLED_GetCompositionCharacterBoundsTest) { // http://crbug.com/582016
base::CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableUseZoomForDSF);
DoSetUp();
@@ -2659,7 +2307,8 @@ TEST_F(RenderViewImplScaleFactorTest, GetCompositionCharacterBoundsTest) {
// ASCII composition
const base::string16 ascii_composition = base::UTF8ToUTF16("aiueo");
- view()->OnImeSetComposition(ascii_composition, empty_underline, 0, 0);
+ view()->OnImeSetComposition(ascii_composition, empty_underline,
+ gfx::Range::InvalidRange(), 0, 0);
view()->GetCompositionCharacterBounds(&bounds_at_1x);
ASSERT_EQ(ascii_composition.size(), bounds_at_1x.size());
@@ -2699,12 +2348,12 @@ TEST_F(RenderViewImplScaleFactorTest, AutoResizeWithZoomForDSF) {
DoSetUp();
view()->EnableAutoResizeForTesting(gfx::Size(5, 5), gfx::Size(1000, 1000));
LoadHTML(kAutoResizeTestPage);
- gfx::Size size_at_1x = view()->size();
+ gfx::Size size_at_1x = view()->GetWidget()->size();
ASSERT_FALSE(size_at_1x.IsEmpty());
SetDeviceScaleFactor(2.f);
LoadHTML(kAutoResizeTestPage);
- gfx::Size size_at_2x = view()->size();
+ gfx::Size size_at_2x = view()->GetWidget()->size();
EXPECT_EQ(size_at_1x, size_at_2x);
}
@@ -2712,12 +2361,12 @@ TEST_F(RenderViewImplScaleFactorTest, AutoResizeWithoutZoomForDSF) {
DoSetUp();
view()->EnableAutoResizeForTesting(gfx::Size(5, 5), gfx::Size(1000, 1000));
LoadHTML(kAutoResizeTestPage);
- gfx::Size size_at_1x = view()->size();
+ gfx::Size size_at_1x = view()->GetWidget()->size();
ASSERT_FALSE(size_at_1x.IsEmpty());
SetDeviceScaleFactor(2.f);
LoadHTML(kAutoResizeTestPage);
- gfx::Size size_at_2x = view()->size();
+ gfx::Size size_at_2x = view()->GetWidget()->size();
EXPECT_EQ(size_at_1x, size_at_2x);
}
@@ -2740,4 +2389,66 @@ TEST_F(DevToolsAgentTest, DevToolsResumeOnClose) {
Detach();
}
+TEST_F(DevToolsAgentTest, RuntimeEnableForcesContexts) {
+ LoadHTML("<body>page<iframe></iframe></body>");
+ Attach();
+ DispatchDevToolsMessage("{\"id\":1,\"method\":\"Runtime.enable\"}");
+ EXPECT_EQ(2, CountNotifications("Runtime.executionContextCreated"));
+}
+
+TEST_F(DevToolsAgentTest, RuntimeEnableForcesContextsAfterNavigation) {
+ Attach();
+ DispatchDevToolsMessage("{\"id\":1,\"method\":\"Runtime.enable\"}");
+ EXPECT_EQ(0, CountNotifications("Runtime.executionContextCreated"));
+ LoadHTML("<body>page<iframe></iframe></body>");
+ EXPECT_EQ(2, CountNotifications("Runtime.executionContextCreated"));
+}
+
+TEST_F(DevToolsAgentTest, RuntimeEvaluateRunMicrotasks) {
+ LoadHTML("<body>page</body>");
+ Attach();
+ DispatchDevToolsMessage("{\"id\":1,\"method\":\"Console.enable\"}");
+ DispatchDevToolsMessage("{\"id\":2,"
+ "\"method\":\"Runtime.evaluate\","
+ "\"params\":{"
+ "\"expression\":\"Promise.resolve().then("
+ "() => console.log(42));\""
+ "}"
+ "}");
+ EXPECT_EQ(1, CountNotifications("Console.messageAdded"));
+}
+
+TEST_F(DevToolsAgentTest, RuntimeCallFunctionOnRunMicrotasks) {
+ LoadHTML("<body>page</body>");
+ Attach();
+ DispatchDevToolsMessage("{\"id\":1,\"method\":\"Console.enable\"}");
+ DispatchDevToolsMessage("{\"id\":2,"
+ "\"method\":\"Runtime.evaluate\","
+ "\"params\":{"
+ "\"expression\":\"window\""
+ "}"
+ "}");
+
+ std::unique_ptr<base::DictionaryValue> root(
+ static_cast<base::DictionaryValue*>(
+ base::JSONReader::Read(LastReceivedMessage()).release()));
+ const base::Value* object_id;
+ ASSERT_TRUE(root->Get("result.result.objectId", &object_id));
+ std::string object_id_str;
+ EXPECT_TRUE(base::JSONWriter::Write(*object_id, &object_id_str));
+
+ DispatchDevToolsMessage("{\"id\":3,"
+ "\"method\":\"Runtime.callFunctionOn\","
+ "\"params\":{"
+ "\"objectId\":" +
+ object_id_str +
+ ","
+ "\"functionDeclaration\":\"function foo(){ "
+ "Promise.resolve().then(() => "
+ "console.log(239))}\""
+ "}"
+ "}");
+ EXPECT_EQ(1, CountNotifications("Console.messageAdded"));
+}
+
} // namespace content
diff --git a/chromium/content/renderer/render_view_browsertest_mac.mm b/chromium/content/renderer/render_view_browsertest_mac.mm
index a973c313c4e..4e1b7320832 100644
--- a/chromium/content/renderer/render_view_browsertest_mac.mm
+++ b/chromium/content/renderer/render_view_browsertest_mac.mm
@@ -10,11 +10,15 @@
#include "content/public/test/render_view_test.h"
#include "content/renderer/render_view_impl.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/web/WebFrameContentDumper.h"
#include "third_party/WebKit/public/web/WebLocalFrame.h"
+#include "third_party/WebKit/public/web/WebView.h"
#include <Carbon/Carbon.h> // for the kVK_* constants.
#include <Cocoa/Cocoa.h>
+using blink::WebFrameContentDumper;
+
namespace content {
NSEvent* CmdDeadKeyEvent(NSEventType type, unsigned short code) {
@@ -104,7 +108,8 @@ TEST_F(RenderViewTest, MacTestCmdUp) {
SendNativeKeyEvent(NativeWebKeyboardEvent(arrowDownKeyDown));
ProcessPendingMessages();
ExecuteJavaScriptForTests("scroll.textContent = window.pageYOffset");
- output = GetMainFrame()->contentAsText(kMaxOutputCharacters);
+ output = WebFrameContentDumper::dumpWebViewAsText(view->GetWebView(),
+ kMaxOutputCharacters);
EXPECT_EQ(kArrowDownScrollDown, base::UTF16ToASCII(output));
const char* kArrowUpScrollUp = "38,false,false,true,false\n0\np1";
@@ -113,7 +118,8 @@ TEST_F(RenderViewTest, MacTestCmdUp) {
SendNativeKeyEvent(NativeWebKeyboardEvent(arrowUpKeyDown));
ProcessPendingMessages();
ExecuteJavaScriptForTests("scroll.textContent = window.pageYOffset");
- output = GetMainFrame()->contentAsText(kMaxOutputCharacters);
+ output = WebFrameContentDumper::dumpWebViewAsText(view->GetWebView(),
+ kMaxOutputCharacters);
EXPECT_EQ(kArrowUpScrollUp, base::UTF16ToASCII(output));
// Now let javascript eat the key events -- no scrolling should happen.
@@ -127,7 +133,8 @@ TEST_F(RenderViewTest, MacTestCmdUp) {
SendNativeKeyEvent(NativeWebKeyboardEvent(arrowDownKeyDown));
ProcessPendingMessages();
ExecuteJavaScriptForTests("scroll.textContent = window.pageYOffset");
- output = GetMainFrame()->contentAsText(kMaxOutputCharacters);
+ output = WebFrameContentDumper::dumpWebViewAsText(view->GetWebView(),
+ kMaxOutputCharacters);
EXPECT_EQ(kArrowDownNoScroll, base::UTF16ToASCII(output));
const char* kArrowUpNoScroll = "38,false,false,true,false\n100\np1";
@@ -136,7 +143,8 @@ TEST_F(RenderViewTest, MacTestCmdUp) {
SendNativeKeyEvent(NativeWebKeyboardEvent(arrowUpKeyDown));
ProcessPendingMessages();
ExecuteJavaScriptForTests("scroll.textContent = window.pageYOffset");
- output = GetMainFrame()->contentAsText(kMaxOutputCharacters);
+ output = WebFrameContentDumper::dumpWebViewAsText(view->GetWebView(),
+ kMaxOutputCharacters);
EXPECT_EQ(kArrowUpNoScroll, base::UTF16ToASCII(output));
}
diff --git a/chromium/content/renderer/render_view_impl.cc b/chromium/content/renderer/render_view_impl.cc
index c2c266c3162..4da799e6cf1 100644
--- a/chromium/content/renderer/render_view_impl.cc
+++ b/chromium/content/renderer/render_view_impl.cc
@@ -13,6 +13,7 @@
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/debug/alias.h"
+#include "base/debug/crash_logging.h"
#include "base/files/file_path.h"
#include "base/i18n/rtl.h"
#include "base/json/json_writer.h"
@@ -31,10 +32,10 @@
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
+#include "cc/base/switches.h"
#include "content/child/appcache/appcache_dispatcher.h"
#include "content/child/appcache/web_application_cache_host_impl.h"
#include "content/child/child_shared_bitmap_manager.h"
-#include "content/child/npapi/webplugin_delegate_impl.h"
#include "content/child/request_extra_data.h"
#include "content/child/v8_value_converter_impl.h"
#include "content/child/webmessageportchannel_impl.h"
@@ -46,7 +47,9 @@
#include "content/common/frame_messages.h"
#include "content/common/frame_replication_state.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
+#include "content/common/input/input_event_utils.h"
#include "content/common/input_messages.h"
+#include "content/common/page_messages.h"
#include "content/common/pepper_messages.h"
#include "content/common/site_isolation_policy.h"
#include "content/common/ssl_status_serialization.h"
@@ -109,7 +112,8 @@
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/http/http_util.h"
#include "skia/ext/platform_canvas.h"
-#include "third_party/WebKit/public/platform/WebCString.h"
+#include "third_party/WebKit/public/platform/FilePathConversion.h"
+#include "third_party/WebKit/public/platform/URLConversion.h"
#include "third_party/WebKit/public/platform/WebConnectionType.h"
#include "third_party/WebKit/public/platform/WebDragData.h"
#include "third_party/WebKit/public/platform/WebHTTPBody.h"
@@ -135,10 +139,11 @@
#include "third_party/WebKit/public/web/WebDocument.h"
#include "third_party/WebKit/public/web/WebElement.h"
#include "third_party/WebKit/public/web/WebFileChooserParams.h"
-#include "third_party/WebKit/public/web/WebFindOptions.h"
#include "third_party/WebKit/public/web/WebFormControlElement.h"
#include "third_party/WebKit/public/web/WebFormElement.h"
#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebFrameContentDumper.h"
+#include "third_party/WebKit/public/web/WebFrameWidget.h"
#include "third_party/WebKit/public/web/WebHistoryItem.h"
#include "third_party/WebKit/public/web/WebHitTestResult.h"
#include "third_party/WebKit/public/web/WebInputElement.h"
@@ -149,13 +154,10 @@
#include "third_party/WebKit/public/web/WebPageImportanceSignals.h"
#include "third_party/WebKit/public/web/WebPlugin.h"
#include "third_party/WebKit/public/web/WebPluginAction.h"
-#include "third_party/WebKit/public/web/WebPluginContainer.h"
-#include "third_party/WebKit/public/web/WebPluginDocument.h"
#include "third_party/WebKit/public/web/WebRange.h"
#include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
#include "third_party/WebKit/public/web/WebScriptSource.h"
#include "third_party/WebKit/public/web/WebSearchableFormData.h"
-#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
#include "third_party/WebKit/public/web/WebSecurityPolicy.h"
#include "third_party/WebKit/public/web/WebSettings.h"
#include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
@@ -172,6 +174,7 @@
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/native_widget_types.h"
+#include "url/url_constants.h"
#include "v8/include/v8.h"
#if defined(OS_ANDROID)
@@ -181,8 +184,6 @@
#include "content/renderer/android/content_detector.h"
#include "content/renderer/android/email_detector.h"
#include "content/renderer/android/phone_number_detector.h"
-#include "third_party/WebKit/public/platform/WebFloatPoint.h"
-#include "third_party/WebKit/public/platform/WebFloatRect.h"
#include "ui/gfx/geometry/rect_f.h"
#elif defined(OS_WIN)
@@ -196,7 +197,6 @@
#endif
#if defined(ENABLE_PLUGINS)
-#include "content/renderer/npapi/webplugin_delegate_proxy.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/pepper/pepper_plugin_registry.h"
#endif
@@ -209,7 +209,6 @@
using blink::WebAXObject;
using blink::WebApplicationCacheHost;
using blink::WebApplicationCacheHostClient;
-using blink::WebCString;
using blink::WebColor;
using blink::WebConsoleMessage;
using blink::WebData;
@@ -220,10 +219,10 @@ using blink::WebDragOperation;
using blink::WebDragOperationsMask;
using blink::WebElement;
using blink::WebFileChooserCompletion;
-using blink::WebFindOptions;
using blink::WebFormControlElement;
using blink::WebFormElement;
using blink::WebFrame;
+using blink::WebFrameContentDumper;
using blink::WebGestureEvent;
using blink::WebHistoryItem;
using blink::WebHTTPBody;
@@ -242,8 +241,6 @@ using blink::WebPeerConnection00HandlerClient;
using blink::WebPeerConnectionHandler;
using blink::WebPeerConnectionHandlerClient;
using blink::WebPluginAction;
-using blink::WebPluginContainer;
-using blink::WebPluginDocument;
using blink::WebPoint;
using blink::WebRange;
using blink::WebRect;
@@ -276,8 +273,6 @@ using base::TimeDelta;
#if defined(OS_ANDROID)
using blink::WebContentDetectionResult;
-using blink::WebFloatPoint;
-using blink::WebFloatRect;
using blink::WebHitTestResult;
#endif
@@ -316,8 +311,10 @@ static RenderViewImpl* (*g_create_render_view_impl)(
Referrer RenderViewImpl::GetReferrerFromRequest(
WebFrame* frame,
const WebURLRequest& request) {
- return Referrer(GURL(request.httpHeaderField(WebString::fromUTF8("Referer"))),
- request.referrerPolicy());
+ return Referrer(
+ blink::WebStringToGURL(request.httpHeaderField(
+ WebString::fromUTF8("Referer"))),
+ request.referrerPolicy());
}
// static
@@ -619,8 +616,6 @@ RenderViewImpl::RenderViewImpl(CompositorDependencies* compositor_deps,
send_preferred_size_changes_(false),
navigation_gesture_(NavigationGestureUnknown),
opened_by_user_gesture_(true),
- opener_suppressed_(false),
- suppress_dialogs_until_swap_out_(false),
page_id_(-1),
next_page_id_(params.next_page_id),
history_list_offset_(-1),
@@ -640,16 +635,13 @@ RenderViewImpl::RenderViewImpl(CompositorDependencies* compositor_deps,
#if defined(OS_ANDROID)
expected_content_intent_id_(0),
#endif
-#if defined(OS_WIN)
- focused_plugin_id_(-1),
-#endif
#if defined(ENABLE_PLUGINS)
- plugin_find_handler_(NULL),
focused_pepper_plugin_(NULL),
pepper_last_mouse_event_target_(NULL),
#endif
enumeration_completion_id_(0),
session_storage_namespace_id_(params.session_storage_namespace_id) {
+ GetWidget()->set_owner_delegate(this);
}
void RenderViewImpl::Initialize(const ViewMsg_New_Params& params,
@@ -671,7 +663,7 @@ void RenderViewImpl::Initialize(const ViewMsg_New_Params& params,
webwidget_mouse_lock_target_.reset(new WebWidgetLockTarget(webwidget_));
g_view_map.Get().insert(std::make_pair(webview(), this));
- g_routing_id_view_map.Get().insert(std::make_pair(routing_id(), this));
+ g_routing_id_view_map.Get().insert(std::make_pair(GetRoutingID(), this));
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
@@ -679,28 +671,51 @@ void RenderViewImpl::Initialize(const ViewMsg_New_Params& params,
if (command_line.HasSwitch(switches::kStatsCollectionController))
stats_collection_observer_.reset(new StatsCollectionObserver(this));
+ // Debug cases of https://crbug.com/575245.
+ base::debug::SetCrashKeyValue("rvinit_view_id",
+ base::IntToString(GetRoutingID()));
+ base::debug::SetCrashKeyValue("rvinit_proxy_id",
+ base::IntToString(params.proxy_routing_id));
+ base::debug::SetCrashKeyValue(
+ "rvinit_main_frame_id", base::IntToString(params.main_frame_routing_id));
+
+ webview()->setDisplayMode(display_mode_);
+ webview()->settings()->setPreferCompositingToLCDTextEnabled(
+ PreferCompositingToLCDText(compositor_deps_, device_scale_factor_));
+ webview()->settings()->setThreadedScrollingEnabled(
+ !command_line.HasSwitch(switches::kDisableThreadedScrolling));
+ webview()->settings()->setRootLayerScrolls(
+ command_line.HasSwitch(switches::kRootLayerScrolls));
+ webview()->setShowFPSCounter(
+ command_line.HasSwitch(cc::switches::kShowFPSCounter));
+
+ ApplyWebPreferencesInternal(webkit_preferences_, webview(), compositor_deps_);
+
+ if (switches::IsTouchDragDropEnabled())
+ webview()->settings()->setTouchDragDropEnabled(true);
+
+ WebSettings::SelectionStrategyType selection_strategy =
+ WebSettings::SelectionStrategyType::Character;
+ const std::string selection_strategy_str =
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kTouchTextSelectionStrategy);
+ if (selection_strategy_str == "direction")
+ selection_strategy = WebSettings::SelectionStrategyType::Direction;
+ webview()->settings()->setSelectionStrategy(selection_strategy);
+
+ ApplyBlinkSettings(command_line, webview()->settings());
+
if (params.main_frame_routing_id != MSG_ROUTING_NONE) {
main_render_frame_ = RenderFrameImpl::CreateMainFrame(
this, params.main_frame_routing_id, params.main_frame_widget_routing_id,
- params.hidden, screen_info(), compositor_deps_);
+ params.hidden, screen_info(), compositor_deps_, opener_frame);
}
if (params.proxy_routing_id != MSG_ROUTING_NONE) {
CHECK(params.swapped_out);
- if (main_render_frame_) {
- DCHECK(!SiteIsolationPolicy::IsSwappedOutStateForbidden());
- RenderFrameProxy* proxy = RenderFrameProxy::CreateProxyToReplaceFrame(
- main_render_frame_, params.proxy_routing_id,
- blink::WebTreeScopeType::Document);
- main_render_frame_->set_render_frame_proxy(proxy);
- } else {
- DCHECK(SiteIsolationPolicy::IsSwappedOutStateForbidden());
- // Pass MSG_ROUTING_NONE for opener, since actual opener (if any) will be
- // set separately below.
- RenderFrameProxy::CreateFrameProxy(params.proxy_routing_id, routing_id(),
- MSG_ROUTING_NONE, MSG_ROUTING_NONE,
- params.replicated_frame_state);
- }
+ RenderFrameProxy::CreateFrameProxy(
+ params.proxy_routing_id, GetRoutingID(), params.opener_frame_route_id,
+ MSG_ROUTING_NONE, params.replicated_frame_state);
}
if (main_render_frame_)
@@ -717,7 +732,7 @@ void RenderViewImpl::Initialize(const ViewMsg_New_Params& params,
content_detectors_.push_back(make_scoped_ptr(new EmailDetector()));
#endif
- RenderThread::Get()->AddRoute(routing_id(), this);
+ RenderThread::Get()->AddRoute(GetRoutingID(), this);
// Take a reference on behalf of the RenderThread. This will be balanced
// when we receive ViewMsg_Close in the RenderWidget (which RenderView
// inherits from).
@@ -732,28 +747,6 @@ void RenderViewImpl::Initialize(const ViewMsg_New_Params& params,
// completing initialization. Otherwise, we can finish it now.
if (opener_id_ == MSG_ROUTING_NONE)
did_show_ = true;
- UpdateWebViewWithDeviceScaleFactor();
- webview()->setDisplayMode(display_mode_);
- webview()->settings()->setPreferCompositingToLCDTextEnabled(
- PreferCompositingToLCDText(compositor_deps_, device_scale_factor_));
- webview()->settings()->setThreadedScrollingEnabled(
- !command_line.HasSwitch(switches::kDisableThreadedScrolling));
- webview()->settings()->setRootLayerScrolls(
- command_line.HasSwitch(switches::kRootLayerScrolls));
-
- ApplyWebPreferencesInternal(webkit_preferences_, webview(), compositor_deps_);
-
- if (switches::IsTouchDragDropEnabled())
- webview()->settings()->setTouchDragDropEnabled(true);
-
- WebSettings::SelectionStrategyType selection_strategy =
- WebSettings::SelectionStrategyType::Character;
- const std::string selection_strategy_str =
- base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kTouchTextSelectionStrategy);
- if (selection_strategy_str == "direction")
- selection_strategy = WebSettings::SelectionStrategyType::Direction;
- webview()->settings()->setSelectionStrategy(selection_strategy);
// Set the main frame's name. Only needs to be done for WebLocalFrames,
// since the remote case was handled as part of SetReplicatedState on the
@@ -768,10 +761,9 @@ void RenderViewImpl::Initialize(const ViewMsg_New_Params& params,
if (params.window_was_created_with_opener)
webview()->setOpenedByDOM();
+ UpdateWebViewWithDeviceScaleFactor();
OnSetRendererPrefs(params.renderer_preferences);
- ApplyBlinkSettings(command_line, webview()->settings());
-
if (!params.enable_auto_resize) {
OnResize(params.initial_size);
} else {
@@ -799,15 +791,13 @@ void RenderViewImpl::Initialize(const ViewMsg_New_Params& params,
GetContentClient()->renderer()->RenderViewCreated(this);
- // If we have an opener_frame but we weren't created by a renderer, then it's
- // the browser asking us to set our opener to another frame.
- if (opener_frame && !was_created_by_renderer)
- webview()->mainFrame()->setOpener(opener_frame);
-
- // If we are initially swapped out, navigate to kSwappedOutURL.
- // This ensures we are in a unique origin that others cannot script.
- if (is_swapped_out_ && webview()->mainFrame()->isWebLocalFrame())
- main_render_frame_->NavigateToSwappedOutURL();
+ // Ensure that sandbox flags are inherited from an opener in a different
+ // process. In that case, the browser process will set any inherited sandbox
+ // flags in |replicated_frame_state|, so apply them here.
+ if (!was_created_by_renderer && webview()->mainFrame()->isWebLocalFrame()) {
+ webview()->mainFrame()->toWebLocalFrame()->forceSandboxFlags(
+ params.replicated_frame_state.sandbox_flags);
+ }
}
RenderViewImpl::~RenderViewImpl() {
@@ -946,16 +936,10 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
settings->setAllowFileAccessFromFileURLs(
prefs.allow_file_access_from_file_urls);
- // Enable the web audio API if requested on the command line.
- settings->setWebAudioEnabled(prefs.webaudio_enabled);
-
// Enable experimental WebGL support if requested on command line
// and support is compiled in.
settings->setExperimentalWebGLEnabled(prefs.experimental_webgl_enabled);
- // Disable GL multisampling if requested on command line.
- settings->setOpenGLMultisamplingEnabled(prefs.gl_multisampling_enabled);
-
// Enable WebGL errors to the JS console if requested.
settings->setWebGLErrorsToConsoleEnabled(
prefs.webgl_errors_to_console_enabled);
@@ -1006,6 +990,8 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
settings->setStrictPowerfulFeatureRestrictions(
prefs.strict_powerful_feature_restrictions);
+ settings->setAllowGeolocationOnInsecureOrigins(
+ prefs.allow_geolocation_on_insecure_origins);
settings->setPasswordEchoEnabled(prefs.password_echo_enabled);
settings->setShouldPrintBackgrounds(prefs.should_print_backgrounds);
settings->setShouldClearDocumentBackground(
@@ -1031,7 +1017,6 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
settings->setShouldRespectImageOrientation(
prefs.should_respect_image_orientation);
- settings->setUnsafePluginPastingEnabled(false);
settings->setEditingBehavior(
static_cast<WebSettings::EditingBehavior>(prefs.editing_behavior));
@@ -1039,6 +1024,8 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
settings->setInertVisualViewport(prefs.inert_visual_viewport);
+ settings->setMainFrameClipsContent(!prefs.record_whole_document);
+
settings->setSmartInsertDeleteEnabled(prefs.smart_insert_delete_enabled);
settings->setSpatialNavigationEnabled(prefs.spatial_navigation_enabled);
@@ -1051,6 +1038,11 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
settings->setImageAnimationPolicy(
static_cast<WebSettings::ImageAnimationPolicy>(prefs.animation_policy));
+ settings->setPresentationRequiresUserGesture(
+ prefs.user_gesture_required_for_presentation);
+
+ settings->setTextTrackMarginPercentage(prefs.text_track_margin_percentage);
+
// Needs to happen before setIgnoreVIewportTagScaleLimits below.
web_view->setDefaultPageScaleLimits(
prefs.default_minimum_page_scale_factor,
@@ -1091,8 +1083,9 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
prefs.ignore_main_frame_overflow_hidden_quirk);
settings->setReportScreenSizeInPhysicalPixelsQuirk(
prefs.report_screen_size_in_physical_pixels_quirk);
+ settings->setShouldReuseGlobalForUnownedMainFrame(
+ prefs.resue_global_for_unowned_main_frame);
settings->setPreferHiddenVolumeControls(true);
- settings->setMainFrameClipsContent(!prefs.record_whole_document);
settings->setShrinksViewportContentToFit(true);
settings->setUseMobileViewportStyle(true);
settings->setAutoplayExperimentMode(
@@ -1115,6 +1108,8 @@ void RenderView::ApplyWebPreferences(const WebPreferences& prefs,
settings->setDoubleTapToZoomEnabled(true);
web_view->setMaximumLegibleScale(prefs.default_maximum_page_scale_factor);
#endif
+
+ settings->setWheelGesturesEnabled(UseGestureBasedWheelScrolling());
}
/*static*/
@@ -1189,61 +1184,29 @@ void RenderViewImpl::PepperFocusChanged(PepperPluginInstanceImpl* instance,
UpdateSelectionBounds();
}
-void RenderViewImpl::RegisterPluginDelegate(WebPluginDelegateProxy* delegate) {
- plugin_delegates_.insert(delegate);
- // If the renderer is visible, set initial visibility and focus state.
- if (!is_hidden()) {
-#if defined(OS_MACOSX)
- delegate->SetContainerVisibility(true);
- if (webview() && webview()->isActive())
- delegate->SetWindowFocus(true);
-#endif
- }
- // Plugins start assuming the content has focus (so that they work in
- // environments where RenderView isn't hosting them), so we always have to
- // set the initial state. See webplugin_delegate_impl.h for details.
- delegate->SetContentAreaFocus(has_focus());
-}
-
-void RenderViewImpl::UnregisterPluginDelegate(
- WebPluginDelegateProxy* delegate) {
- plugin_delegates_.erase(delegate);
-}
-
-#if defined(OS_WIN)
-void RenderViewImpl::PluginFocusChanged(bool focused, int plugin_id) {
- if (focused)
- focused_plugin_id_ = plugin_id;
- else
- focused_plugin_id_ = -1;
-}
-#endif
-
#if defined(OS_MACOSX)
-void RenderViewImpl::PluginFocusChanged(bool focused, int plugin_id) {
- Send(new ViewHostMsg_PluginFocusChanged(routing_id(), focused, plugin_id));
-}
-
void RenderViewImpl::OnGetRenderedText() {
if (!webview())
return;
+
+ if (!webview()->mainFrame()->isWebLocalFrame())
+ return;
+
// Get rendered text from WebLocalFrame.
// TODO: Currently IPC truncates any data that has a
// size > kMaximumMessageSize. May be split the text into smaller chunks and
// send back using multiple IPC. See http://crbug.com/393444.
static const size_t kMaximumMessageSize = 8 * 1024 * 1024;
- std::string text = webview()->mainFrame()->contentAsText(
- kMaximumMessageSize).utf8();
-
- Send(new ViewMsg_GetRenderedTextCompleted(routing_id(), text));
-}
+ // TODO(dglazkov): Using this API is wrong. It's not OOPIF-compatible and
+ // sends text in the wrong order. See http://crbug.com/584798.
+ // TODO(dglazkov): WebFrameContentDumper should only be used for
+ // testing purposes. See http://crbug.com/585164.
+ std::string text =
+ WebFrameContentDumper::deprecatedDumpFrameTreeAsText(
+ webview()->mainFrame()->toWebLocalFrame(), kMaximumMessageSize)
+ .utf8();
-void RenderViewImpl::StartPluginIme() {
- IPC::Message* msg = new ViewHostMsg_StartPluginIme(routing_id());
- // This message can be sent during event-handling, and needs to be delivered
- // within that context.
- msg->set_unblock(true);
- Send(msg);
+ Send(new ViewMsg_GetRenderedTextCompleted(GetRoutingID(), text));
}
#endif // defined(OS_MACOSX)
@@ -1257,22 +1220,22 @@ void RenderViewImpl::TransferActiveWheelFlingAnimation(
// RenderWidgetInputHandlerDelegate -----------------------------------------
-void RenderViewImpl::FocusChangeComplete() {
- RenderWidget::FocusChangeComplete();
+void RenderViewImpl::RenderWidgetFocusChangeComplete() {
FOR_EACH_OBSERVER(RenderViewObserver, observers_, FocusChangeComplete());
}
-bool RenderViewImpl::HasTouchEventHandlersAt(const gfx::Point& point) const {
+bool RenderViewImpl::DoesRenderWidgetHaveTouchEventHandlersAt(
+ const gfx::Point& point) const {
if (!webview())
return false;
return webview()->hasTouchEventHandlersAt(point);
}
-void RenderViewImpl::OnDidHandleKeyEvent() {
+void RenderViewImpl::RenderWidgetDidHandleKeyEvent() {
ClearEditCommands();
}
-bool RenderViewImpl::WillHandleGestureEvent(
+bool RenderViewImpl::RenderWidgetWillHandleGestureEvent(
const blink::WebGestureEvent& event) {
possible_drag_event_info_.event_source =
ui::DragDropTypes::DRAG_EVENT_SOURCE_TOUCH;
@@ -1281,7 +1244,8 @@ bool RenderViewImpl::WillHandleGestureEvent(
return false;
}
-bool RenderViewImpl::WillHandleMouseEvent(const blink::WebMouseEvent& event) {
+bool RenderViewImpl::RenderWidgetWillHandleMouseEvent(
+ const blink::WebMouseEvent& event) {
possible_drag_event_info_.event_source =
ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE;
possible_drag_event_info_.event_location =
@@ -1331,8 +1295,6 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) {
OnSetEditCommandsForNextKeyEvent)
IPC_MESSAGE_HANDLER(ViewMsg_CopyImageAt, OnCopyImageAt)
IPC_MESSAGE_HANDLER(ViewMsg_SaveImageAt, OnSaveImageAt)
- IPC_MESSAGE_HANDLER(ViewMsg_Find, OnFind)
- IPC_MESSAGE_HANDLER(ViewMsg_StopFinding, OnStopFinding)
IPC_MESSAGE_HANDLER(ViewMsg_SetPageScale, OnSetPageScale)
IPC_MESSAGE_HANDLER(ViewMsg_Zoom, OnZoom)
IPC_MESSAGE_HANDLER(ViewMsg_SetZoomLevelForLoadingURL,
@@ -1356,8 +1318,6 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(ViewMsg_EnumerateDirectoryResponse,
OnEnumerateDirectoryResponse)
IPC_MESSAGE_HANDLER(ViewMsg_RunFileChooserResponse, OnFileChooserResponse)
- IPC_MESSAGE_HANDLER(ViewMsg_SuppressDialogsUntilSwapOut,
- OnSuppressDialogsUntilSwapOut)
IPC_MESSAGE_HANDLER(ViewMsg_ClosePage, OnClosePage)
IPC_MESSAGE_HANDLER(ViewMsg_ThemeChanged, OnThemeChanged)
IPC_MESSAGE_HANDLER(ViewMsg_MoveOrResizeStarted, OnMoveOrResizeStarted)
@@ -1377,27 +1337,20 @@ bool RenderViewImpl::OnMessageReceived(const IPC::Message& message) {
// TODO(viettrungluu): Move to a separate message filter.
IPC_MESSAGE_HANDLER(ViewMsg_SetHistoryOffsetAndLength,
OnSetHistoryOffsetAndLength)
- IPC_MESSAGE_HANDLER(ViewMsg_EnableViewSourceMode, OnEnableViewSourceMode)
IPC_MESSAGE_HANDLER(ViewMsg_ReleaseDisambiguationPopupBitmap,
OnReleaseDisambiguationPopupBitmap)
IPC_MESSAGE_HANDLER(ViewMsg_ForceRedraw, OnForceRedraw)
IPC_MESSAGE_HANDLER(ViewMsg_SelectWordAroundCaret, OnSelectWordAroundCaret)
+ IPC_MESSAGE_HANDLER(PageMsg_UpdateWindowScreenRect,
+ OnUpdateWindowScreenRect)
#if defined(OS_ANDROID)
- IPC_MESSAGE_HANDLER(InputMsg_ActivateNearestFindResult,
- OnActivateNearestFindResult)
- IPC_MESSAGE_HANDLER(ViewMsg_FindMatchRects, OnFindMatchRects)
IPC_MESSAGE_HANDLER(ViewMsg_UpdateTopControlsState,
OnUpdateTopControlsState)
IPC_MESSAGE_HANDLER(ViewMsg_ExtractSmartClipData, OnExtractSmartClipData)
#elif defined(OS_MACOSX)
IPC_MESSAGE_HANDLER(ViewMsg_GetRenderedText,
OnGetRenderedText)
- IPC_MESSAGE_HANDLER(ViewMsg_PluginImeCompositionCompleted,
- OnPluginImeCompositionCompleted)
IPC_MESSAGE_HANDLER(ViewMsg_Close, OnClose)
- IPC_MESSAGE_HANDLER(ViewMsg_SetInLiveResize, OnSetInLiveResize)
- IPC_MESSAGE_HANDLER(ViewMsg_SetWindowVisibility, OnSetWindowVisibility)
- IPC_MESSAGE_HANDLER(ViewMsg_WindowFrameChanged, OnWindowFrameChanged)
#endif
// Adding a new message? Add platform independent ones first, then put the
// platform specific ones at the end.
@@ -1429,7 +1382,7 @@ void RenderViewImpl::OnSaveImageAt(int x, int y) {
void RenderViewImpl::OnUpdateTargetURLAck() {
// Check if there is a targeturl waiting to be sent.
if (target_url_status_ == TARGET_PENDING)
- Send(new ViewHostMsg_UpdateTargetURL(routing_id(), pending_target_url_));
+ Send(new ViewHostMsg_UpdateTargetURL(GetRoutingID(), pending_target_url_));
target_url_status_ = TARGET_NONE;
}
@@ -1447,16 +1400,16 @@ void RenderViewImpl::OnMoveCaret(const gfx::Point& point) {
if (!webview())
return;
- Send(new InputHostMsg_MoveCaret_ACK(routing_id()));
-
- webview()->focusedFrame()->moveCaretSelection(point);
+ Send(new InputHostMsg_MoveCaret_ACK(GetRoutingID()));
+ webview()->focusedFrame()->moveCaretSelection(
+ ConvertWindowPointToViewport(point));
}
void RenderViewImpl::OnScrollFocusedEditableNodeIntoRect(
const gfx::Rect& rect) {
if (has_scrolled_focused_editable_node_into_rect_ &&
rect == rect_for_scrolled_focused_editable_node_) {
- FocusChangeComplete();
+ GetWidget()->FocusChangeComplete();
return;
}
@@ -1469,7 +1422,7 @@ void RenderViewImpl::OnScrollFocusedEditableNodeIntoRect(
}
if (!will_animate)
- FocusChangeComplete();
+ GetWidget()->FocusChangeComplete();
}
void RenderViewImpl::OnSetEditCommandsForNextKeyEvent(
@@ -1492,16 +1445,9 @@ void RenderViewImpl::OnSetInitialFocus(bool reverse) {
webview()->setInitialFocus(reverse);
}
-#if defined(OS_MACOSX)
-void RenderViewImpl::OnSetInLiveResize(bool in_live_resize) {
- if (!webview())
- return;
- if (in_live_resize)
- webview()->willStartLiveResize();
- else
- webview()->willEndLiveResize();
+void RenderViewImpl::OnUpdateWindowScreenRect(gfx::Rect window_screen_rect) {
+ RenderWidget::OnUpdateWindowScreenRect(window_screen_rect);
}
-#endif
///////////////////////////////////////////////////////////////////////////////
@@ -1513,11 +1459,7 @@ void RenderViewImpl::SendUpdateState() {
if (!entry)
return;
- // Don't send state updates for kSwappedOutURL.
- if (entry->root().urlString() == kSwappedOutURL)
- return;
-
- Send(new ViewHostMsg_UpdateState(routing_id(), page_id_,
+ Send(new ViewHostMsg_UpdateState(GetRoutingID(), page_id_,
HistoryEntryToPageState(entry)));
}
@@ -1540,24 +1482,6 @@ void RenderViewImpl::ApplyWebPreferencesInternal(
blink::WebView* web_view,
CompositorDependencies* compositor_deps) {
ApplyWebPreferences(prefs, web_view);
-#if defined(OS_MACOSX) && !defined(OS_IOS)
- DCHECK(compositor_deps);
- bool is_elastic_overscroll_enabled =
- compositor_deps->IsElasticOverscrollEnabled();
- web_view->settings()->setReportWheelOverscroll(is_elastic_overscroll_enabled);
-#endif
-}
-
-bool RenderViewImpl::SendAndRunNestedMessageLoop(IPC::SyncMessage* message) {
- // Before WebKit asks us to show an alert (etc.), it takes care of doing the
- // equivalent of WebView::willEnterModalLoop. In the case of showModalDialog
- // it is particularly important that we do not call willEnterModalLoop as
- // that would defer resource loads for the dialog itself.
- if (RenderThreadImpl::current()) // Will be NULL during unit tests.
- RenderThreadImpl::current()->DoNotNotifyWebKitOfModalLoop();
-
- message->EnableMessagePumping(); // Runs a nested message loop.
- return Send(message);
}
void RenderViewImpl::OnForceRedraw(int id) {
@@ -1584,7 +1508,7 @@ WebView* RenderViewImpl::createView(WebLocalFrame* creator,
WebNavigationPolicy policy,
bool suppress_opener) {
ViewHostMsg_CreateWindow_Params params;
- params.opener_id = routing_id();
+ params.opener_id = GetRoutingID();
params.user_gesture = WebUserGestureIndicator::isProcessingUserGesture();
if (GetContentClient()->renderer()->AllowPopup())
params.user_gesture = true;
@@ -1609,10 +1533,11 @@ WebView* RenderViewImpl::createView(WebLocalFrame* creator,
params.opener_top_level_frame_url = creator->top()->document().url();
} else {
params.opener_top_level_frame_url =
- GURL(creator->top()->securityOrigin().toString());
+ blink::WebStringToGURL(creator->top()->getSecurityOrigin().toString());
}
- GURL security_url(creator->document().securityOrigin().toString());
+ GURL security_url(blink::WebStringToGURL(
+ creator->document().getSecurityOrigin().toString()));
if (!security_url.is_valid())
security_url = GURL();
params.opener_security_origin = security_url;
@@ -1640,7 +1565,7 @@ WebView* RenderViewImpl::createView(WebLocalFrame* creator,
// TODO(vangelis): Can we tell if the new view will be a background page?
bool never_visible = false;
- ViewMsg_Resize_Params initial_size = ViewMsg_Resize_Params();
+ ResizeParams initial_size = ResizeParams();
initial_size.screen_info = screen_info_;
// The initial hidden state for the RenderViewImpl here has to match what the
@@ -1652,7 +1577,7 @@ WebView* RenderViewImpl::createView(WebLocalFrame* creator,
RenderFrameImpl* creator_frame = RenderFrameImpl::FromWebFrame(creator);
view_params.opener_frame_route_id = creator_frame->GetRoutingID();
- DCHECK_EQ(routing_id(), creator_frame->render_view()->GetRoutingID());
+ DCHECK_EQ(GetRoutingID(), creator_frame->render_view()->GetRoutingID());
view_params.window_was_created_with_opener = true;
view_params.renderer_preferences = renderer_preferences_;
@@ -1677,14 +1602,11 @@ WebView* RenderViewImpl::createView(WebLocalFrame* creator,
RenderViewImpl::Create(compositor_deps_, view_params, true);
view->opened_by_user_gesture_ = params.user_gesture;
- // Record whether the creator frame is trying to suppress the opener field.
- view->opener_suppressed_ = params.opener_suppressed;
-
return view->webview();
}
WebWidget* RenderViewImpl::createPopupMenu(blink::WebPopupType popup_type) {
- RenderWidget* widget = RenderWidget::Create(routing_id(), compositor_deps_,
+ RenderWidget* widget = RenderWidget::Create(GetRoutingID(), compositor_deps_,
popup_type, screen_info_);
if (!widget)
return NULL;
@@ -1710,7 +1632,7 @@ void RenderViewImpl::saveImageFromDataURL(const blink::WebString& data_url) {
// in order to send a larger data url to save a image for <canvas> or <img>.
if (data_url.length() < kMaxLengthOfDataURLString)
Send(new ViewHostMsg_SaveImageFromDataURL(
- routing_id(), GetMainRenderFrame()->GetRoutingID(), data_url.utf8()));
+ GetRoutingID(), GetMainRenderFrame()->GetRoutingID(), data_url.utf8()));
}
bool RenderViewImpl::enumerateChosenDirectory(
@@ -1719,7 +1641,7 @@ bool RenderViewImpl::enumerateChosenDirectory(
int id = enumeration_completion_id_++;
enumeration_completions_[id] = chooser_completion;
return Send(new ViewHostMsg_EnumerateDirectory(
- routing_id(), id, base::FilePath::FromUTF16Unsafe(path)));
+ GetRoutingID(), id, blink::WebStringToFilePath(path)));
}
void RenderViewImpl::FrameDidStartLoading(WebFrame* frame) {
@@ -1741,7 +1663,7 @@ void RenderViewImpl::FrameDidStopLoading(WebFrame* frame) {
}
}
-void RenderViewImpl::AttachWebFrameWidget(blink::WebWidget* frame_widget) {
+void RenderViewImpl::AttachWebFrameWidget(blink::WebFrameWidget* frame_widget) {
// The previous WebFrameWidget must already be detached by CloseForFrame().
DCHECK(!frame_widget_);
frame_widget_ = frame_widget;
@@ -1753,7 +1675,7 @@ void RenderViewImpl::SetZoomLevel(double zoom_level) {
}
void RenderViewImpl::didCancelCompositionOnSelectionChange() {
- Send(new InputHostMsg_ImeCancelComposition(routing_id()));
+ Send(new InputHostMsg_ImeCancelComposition(GetRoutingID()));
}
bool RenderViewImpl::handleCurrentKeyboardEvent() {
@@ -1799,7 +1721,7 @@ bool RenderViewImpl::runFileChooser(
ipc_params.mode = FileChooserParams::Open;
ipc_params.title = params.title;
ipc_params.default_file_name =
- base::FilePath::FromUTF16Unsafe(params.initialValue).BaseName();
+ blink::WebStringToFilePath(params.initialValue).BaseName();
ipc_params.accept_types.reserve(params.acceptTypes.size());
for (size_t i = 0; i < params.acceptTypes.size(); ++i)
ipc_params.accept_types.push_back(params.acceptTypes[i]);
@@ -1848,18 +1770,18 @@ void RenderViewImpl::showValidationMessage(
&wrapped_main_text, main_text_hint, &wrapped_sub_text, sub_text_hint);
Send(new ViewHostMsg_ShowValidationMessage(
- routing_id(), AdjustValidationMessageAnchor(anchor_in_viewport),
+ GetRoutingID(), AdjustValidationMessageAnchor(anchor_in_viewport),
wrapped_main_text, wrapped_sub_text));
}
void RenderViewImpl::hideValidationMessage() {
- Send(new ViewHostMsg_HideValidationMessage(routing_id()));
+ Send(new ViewHostMsg_HideValidationMessage(GetRoutingID()));
}
void RenderViewImpl::moveValidationMessage(
const blink::WebRect& anchor_in_viewport) {
Send(new ViewHostMsg_MoveValidationMessage(
- routing_id(), AdjustValidationMessageAnchor(anchor_in_viewport)));
+ GetRoutingID(), AdjustValidationMessageAnchor(anchor_in_viewport)));
}
void RenderViewImpl::setStatusText(const WebString& text) {
@@ -1882,9 +1804,9 @@ void RenderViewImpl::UpdateTargetURL(const GURL& url,
} else {
// URLs larger than |kMaxURLChars| cannot be sent through IPC -
// see |ParamTraits<GURL>|.
- if (latest_url.possibly_invalid_spec().size() > kMaxURLChars)
+ if (latest_url.possibly_invalid_spec().size() > url::kMaxURLChars)
latest_url = GURL();
- Send(new ViewHostMsg_UpdateTargetURL(routing_id(), latest_url));
+ Send(new ViewHostMsg_UpdateTargetURL(GetRoutingID(), latest_url));
target_url_ = latest_url;
target_url_status_ = TARGET_INFLIGHT;
}
@@ -1945,10 +1867,12 @@ void RenderViewImpl::startDragging(WebLocalFrame* frame,
WebDragOperationsMask mask,
const WebImage& image,
const WebPoint& webImageOffset) {
+ blink::WebRect offset_in_window(webImageOffset.x, webImageOffset.y, 0, 0);
+ ConvertViewportToWindowViaWidget(&offset_in_window);
DropData drop_data(DropDataBuilder::Build(data));
drop_data.referrer_policy = frame->document().referrerPolicy();
- gfx::Vector2d imageOffset(webImageOffset.x, webImageOffset.y);
- Send(new DragHostMsg_StartDragging(routing_id(), drop_data, mask,
+ gfx::Vector2d imageOffset(offset_in_window.x, offset_in_window.y);
+ Send(new DragHostMsg_StartDragging(GetRoutingID(), drop_data, mask,
image.getSkBitmap(), imageOffset,
possible_drag_event_info_));
}
@@ -1958,11 +1882,11 @@ bool RenderViewImpl::acceptsLoadDrops() {
}
void RenderViewImpl::focusNext() {
- Send(new ViewHostMsg_TakeFocus(routing_id(), false));
+ Send(new ViewHostMsg_TakeFocus(GetRoutingID(), false));
}
void RenderViewImpl::focusPrevious() {
- Send(new ViewHostMsg_TakeFocus(routing_id(), true));
+ Send(new ViewHostMsg_TakeFocus(GetRoutingID(), true));
}
// TODO(esprehn): Blink only ever passes Elements, this should take WebElement.
@@ -1975,11 +1899,11 @@ void RenderViewImpl::focusedNodeChanged(const WebNode& fromNode,
if (!toNode.isNull() && toNode.isElementNode()) {
WebElement element = const_cast<WebNode&>(toNode).to<WebElement>();
blink::WebRect rect = element.boundsInViewport();
- convertViewportToWindow(&rect);
+ ConvertViewportToWindowViaWidget(&rect);
node_bounds = gfx::Rect(rect);
is_editable = element.isEditable();
}
- Send(new ViewHostMsg_FocusedNodeChanged(routing_id(), is_editable,
+ Send(new ViewHostMsg_FocusedNodeChanged(GetRoutingID(), is_editable,
node_bounds));
// TODO(estade): remove.
@@ -2019,7 +1943,7 @@ void RenderViewImpl::didUpdateLayout() {
}
void RenderViewImpl::navigateBackForwardSoon(int offset) {
- Send(new ViewHostMsg_GoToEntryAtOffset(routing_id(), offset));
+ Send(new ViewHostMsg_GoToEntryAtOffset(GetRoutingID(), offset));
}
int RenderViewImpl::historyBackListCount() {
@@ -2038,7 +1962,7 @@ void RenderViewImpl::didFocus() {
// move that code back to render_widget.cc
if (WebUserGestureIndicator::isProcessingUserGesture() &&
!RenderThreadImpl::current()->layout_test_mode()) {
- Send(new ViewHostMsg_Focus(routing_id()));
+ Send(new ViewHostMsg_Focus(GetRoutingID()));
}
}
@@ -2064,7 +1988,7 @@ void RenderViewImpl::show(WebNavigationPolicy policy) {
// NOTE: initial_rect_ may still have its default values at this point, but
// that's okay. It'll be ignored if disposition is not NEW_POPUP, or the
// browser process will impose a default position otherwise.
- Send(new ViewHostMsg_ShowView(opener_id_, routing_id(),
+ Send(new ViewHostMsg_ShowView(opener_id_, GetRoutingID(),
NavigationPolicyToDisposition(policy),
initial_rect_, opened_by_user_gesture_));
SetPendingWindowRect(initial_rect_);
@@ -2109,7 +2033,7 @@ void RenderViewImpl::didHandleGestureEvent(
blink::WebTextInputType text_input_type = GetWebView()->textInputType();
Send(new ViewHostMsg_FocusedNodeTouched(
- routing_id(), text_input_type != blink::WebTextInputTypeNone));
+ GetRoutingID(), text_input_type != blink::WebTextInputTypeNone));
#endif
}
@@ -2120,7 +2044,7 @@ void RenderViewImpl::initializeLayerTreeView() {
return;
bool use_threaded_event_handling = true;
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MACOSX)
// Disable threaded event handling if content is not handling the elastic
// overscroll effect. This includes the cases where the elastic overscroll
// effect is being handled by Blink (because of command line flags) and older
@@ -2135,8 +2059,9 @@ void RenderViewImpl::initializeLayerTreeView() {
render_thread ? render_thread->input_handler_manager() : NULL;
if (input_handler_manager) {
input_handler_manager->AddInputHandler(
- routing_id(), rwc->GetInputHandler(), AsWeakPtr(),
- webkit_preferences_.enable_scroll_animator);
+ GetRoutingID(), rwc->GetInputHandler(), AsWeakPtr(),
+ webkit_preferences_.enable_scroll_animator,
+ UseGestureBasedWheelScrolling());
}
}
}
@@ -2172,14 +2097,14 @@ const std::string& RenderViewImpl::GetAcceptLanguages() const {
return renderer_preferences_.accept_languages;
}
-void RenderViewImpl::convertViewportToWindow(blink::WebRect* rect) {
- RenderWidget::convertViewportToWindow(rect);
+void RenderViewImpl::ConvertViewportToWindowViaWidget(blink::WebRect* rect) {
+ convertViewportToWindow(rect);
}
gfx::RectF RenderViewImpl::ElementBoundsInWindow(
const blink::WebElement& element) {
blink::WebRect bounding_box_in_window = element.boundsInViewport();
- convertViewportToWindow(&bounding_box_in_window);
+ ConvertViewportToWindowViaWidget(&bounding_box_in_window);
return gfx::RectF(bounding_box_in_window);
}
@@ -2187,6 +2112,13 @@ float RenderViewImpl::GetDeviceScaleFactorForTest() const {
return device_scale_factor_;
}
+gfx::Point RenderViewImpl::ConvertWindowPointToViewport(
+ const gfx::Point& point) {
+ blink::WebFloatRect point_in_viewport(point.x(), point.y(), 0, 0);
+ convertWindowToViewport(&point_in_viewport);
+ return gfx::Point(point_in_viewport.x, point_in_viewport.y);
+}
+
void RenderViewImpl::didChangeIcon(WebLocalFrame* frame,
WebIconURL::Type icon_type) {
if (frame->parent())
@@ -2215,20 +2147,10 @@ void RenderViewImpl::CheckPreferredSize() {
return;
preferred_size_ = size;
- Send(new ViewHostMsg_DidContentsPreferredSizeChange(routing_id(),
+ Send(new ViewHostMsg_DidContentsPreferredSizeChange(GetRoutingID(),
preferred_size_));
}
-void RenderViewImpl::SendFindReply(int request_id,
- int match_count,
- int ordinal,
- const WebRect& selection_rect,
- bool final_status_update) {
- Send(new ViewHostMsg_Find_Reply(routing_id(), request_id, match_count,
- selection_rect, ordinal,
- final_status_update));
-}
-
blink::WebString RenderViewImpl::acceptLanguages() {
return WebString::fromUTF8(renderer_preferences_.accept_languages);
}
@@ -2239,6 +2161,10 @@ bool RenderViewImpl::Send(IPC::Message* message) {
return RenderWidget::Send(message);
}
+RenderWidget* RenderViewImpl::GetWidget() const {
+ return const_cast<RenderWidget*>(static_cast<const RenderWidget*>(this));
+}
+
RenderFrameImpl* RenderViewImpl::GetMainRenderFrame() {
return main_render_frame_;
}
@@ -2267,6 +2193,10 @@ blink::WebView* RenderViewImpl::GetWebView() {
return webview();
}
+blink::WebFrameWidget* RenderViewImpl::GetWebFrameWidget() {
+ return frame_widget_;
+}
+
bool RenderViewImpl::ShouldDisplayScrollbars(int width, int height) const {
return (!send_preferred_size_changes_ ||
(disable_scrollbars_size_limit_.width() <= width ||
@@ -2306,227 +2236,6 @@ blink::WebElement RenderViewImpl::GetFocusedElement() const {
return WebElement();
}
-blink::WebPlugin* RenderViewImpl::GetWebPluginForFind() {
- if (!webview())
- return NULL;
-
- WebFrame* main_frame = webview()->mainFrame();
- if (main_frame->isWebLocalFrame() &&
- main_frame->document().isPluginDocument())
- return webview()->mainFrame()->document().to<WebPluginDocument>().plugin();
-
-#if defined(ENABLE_PLUGINS)
- if (plugin_find_handler_)
- return plugin_find_handler_->container()->plugin();
-#endif
-
- return NULL;
-}
-
-void RenderViewImpl::OnFind(int request_id,
- const base::string16& search_text,
- const WebFindOptions& options) {
- DCHECK(!search_text.empty());
-
- WebFrame* main_frame = webview()->mainFrame();
- blink::WebPlugin* plugin = GetWebPluginForFind();
- // Check if the plugin still exists in the document.
- if (plugin) {
- if (options.findNext) {
- // Just navigate back/forward.
- plugin->selectFindResult(options.forward);
- } else {
- if (!plugin->startFind(
- search_text, options.matchCase, request_id)) {
- // Send "no results".
- SendFindReply(request_id, 0, 0, gfx::Rect(), true);
- }
- }
- return;
- }
-
- WebFrame* frame_after_main = main_frame->traverseNext(true);
- WebFrame* focused_frame = webview()->focusedFrame();
- WebFrame* search_frame = focused_frame; // start searching focused frame.
-
- bool multi_frame = (frame_after_main != main_frame);
-
- // If we have multiple frames, we don't want to wrap the search within the
- // frame, so we check here if we only have main_frame in the chain.
- bool wrap_within_frame = !multi_frame;
-
- WebRect selection_rect;
- bool result = false;
-
- // If something is selected when we start searching it means we cannot just
- // increment the current match ordinal; we need to re-generate it.
- WebRange current_selection = focused_frame->selectionRange();
-
- do {
- result = search_frame->find(
- request_id, search_text, options, wrap_within_frame, &selection_rect);
-
- if (!result) {
- // don't leave text selected as you move to the next frame.
- search_frame->executeCommand(WebString::fromUTF8("Unselect"),
- GetFocusedElement());
-
- // Find the next frame, but skip the invisible ones.
- do {
- // What is the next frame to search? (we might be going backwards). Note
- // that we specify wrap=true so that search_frame never becomes NULL.
- search_frame = options.forward ?
- search_frame->traverseNext(true) :
- search_frame->traversePrevious(true);
- } while (!search_frame->hasVisibleContent() &&
- search_frame != focused_frame);
-
- // Make sure selection doesn't affect the search operation in new frame.
- search_frame->executeCommand(WebString::fromUTF8("Unselect"),
- GetFocusedElement());
-
- // If we have multiple frames and we have wrapped back around to the
- // focused frame, we need to search it once more allowing wrap within
- // the frame, otherwise it will report 'no match' if the focused frame has
- // reported matches, but no frames after the focused_frame contain a
- // match for the search word(s).
- if (multi_frame && search_frame == focused_frame) {
- result = search_frame->find(
- request_id, search_text, options, true, // Force wrapping.
- &selection_rect);
- }
- }
-
- webview()->setFocusedFrame(search_frame);
- } while (!result && search_frame != focused_frame);
-
- if (options.findNext && current_selection.isNull()) {
- // Force the main_frame to report the actual count.
- main_frame->increaseMatchCount(0, request_id);
- } else {
- // If nothing is found, set result to "0 of 0", otherwise, set it to
- // "-1 of 1" to indicate that we found at least one item, but we don't know
- // yet what is active.
- int ordinal = result ? -1 : 0; // -1 here means, we might know more later.
- int match_count = result ? 1 : 0; // 1 here means possibly more coming.
-
- // If we find no matches then this will be our last status update.
- // Otherwise the scoping effort will send more results.
- bool final_status_update = !result;
-
- SendFindReply(request_id, match_count, ordinal, selection_rect,
- final_status_update);
-
- // Scoping effort begins, starting with the mainframe.
- search_frame = main_frame;
-
- main_frame->resetMatchCount();
-
- do {
- // Cancel all old scoping requests before starting a new one.
- search_frame->cancelPendingScopingEffort();
-
- // We don't start another scoping effort unless at least one match has
- // been found.
- if (result) {
- // Start new scoping request. If the scoping function determines that it
- // needs to scope, it will defer until later.
- search_frame->scopeStringMatches(request_id,
- search_text,
- options,
- true); // reset the tickmarks
- }
-
- // Iterate to the next frame. The frame will not necessarily scope, for
- // example if it is not visible.
- search_frame = search_frame->traverseNext(true);
- } while (search_frame != main_frame);
- }
-}
-
-void RenderViewImpl::OnStopFinding(StopFindAction action) {
- WebView* view = webview();
- if (!view)
- return;
-
- blink::WebPlugin* plugin = GetWebPluginForFind();
- if (plugin) {
- plugin->stopFind();
- return;
- }
-
- bool clear_selection = action == STOP_FIND_ACTION_CLEAR_SELECTION;
- if (clear_selection) {
- view->focusedFrame()->executeCommand(WebString::fromUTF8("Unselect"),
- GetFocusedElement());
- }
-
- WebFrame* frame = view->mainFrame();
- while (frame) {
- frame->stopFinding(clear_selection);
- frame = frame->traverseNext(false);
- }
-
- if (action == STOP_FIND_ACTION_ACTIVATE_SELECTION) {
- WebFrame* focused_frame = view->focusedFrame();
- if (focused_frame) {
- WebDocument doc = focused_frame->document();
- if (!doc.isNull()) {
- WebElement element = doc.focusedElement();
- if (!element.isNull())
- element.simulateClick();
- }
- }
- }
-}
-
-#if defined(OS_ANDROID)
-void RenderViewImpl::OnActivateNearestFindResult(int request_id,
- float x, float y) {
- if (!webview())
- return;
-
- WebFrame* main_frame = webview()->mainFrame();
- WebRect selection_rect;
- int ordinal = main_frame->selectNearestFindMatch(WebFloatPoint(x, y),
- &selection_rect);
- if (ordinal == -1) {
- // Something went wrong, so send a no-op reply (force the main_frame to
- // report the current match count) in case the host is waiting for a
- // response due to rate-limiting).
- main_frame->increaseMatchCount(0, request_id);
- return;
- }
-
- SendFindReply(request_id,
- -1 /* number_of_matches */,
- ordinal,
- selection_rect,
- true /* final_update */);
-}
-
-void RenderViewImpl::OnFindMatchRects(int current_version) {
- if (!webview())
- return;
-
- WebFrame* main_frame = webview()->mainFrame();
- std::vector<gfx::RectF> match_rects;
-
- int rects_version = main_frame->findMatchMarkersVersion();
- if (current_version != rects_version) {
- WebVector<WebFloatRect> web_match_rects;
- main_frame->findMatchRects(web_match_rects);
- match_rects.reserve(web_match_rects.size());
- for (size_t i = 0; i < web_match_rects.size(); ++i)
- match_rects.push_back(gfx::RectF(web_match_rects[i]));
- }
-
- gfx::RectF active_rect = main_frame->activeFindMatchRect();
- Send(new ViewHostMsg_FindMatchRects_Reply(routing_id(), rects_version,
- match_rects, active_rect));
-}
-#endif
-
void RenderViewImpl::OnSetPageScale(float page_scale_factor) {
if (!webview())
return;
@@ -2596,14 +2305,15 @@ void RenderViewImpl::OnAllowBindings(int enabled_bindings_flags) {
// WebUIExtensionData deletes itself when we're destroyed.
new WebUIExtensionData(this);
- if (main_render_frame_)
- main_render_frame_->EnableMojoBindings();
}
enabled_bindings_ |= enabled_bindings_flags;
// Keep track of the total bindings accumulated in this process.
RenderProcess::current()->AddBindings(enabled_bindings_flags);
+
+ if (main_render_frame_)
+ main_render_frame_->MaybeEnableMojoBindings();
}
void RenderViewImpl::OnDragTargetDragEnter(const DropData& drop_data,
@@ -2613,12 +2323,12 @@ void RenderViewImpl::OnDragTargetDragEnter(const DropData& drop_data,
int key_modifiers) {
WebDragOperation operation = webview()->dragTargetDragEnter(
DropDataToWebDragData(drop_data),
- client_point,
+ ConvertWindowPointToViewport(client_point),
screen_point,
ops,
key_modifiers);
- Send(new DragHostMsg_UpdateDragCursor(routing_id(), operation));
+ Send(new DragHostMsg_UpdateDragCursor(GetRoutingID(), operation));
}
void RenderViewImpl::OnDragTargetDragOver(const gfx::Point& client_point,
@@ -2626,12 +2336,12 @@ void RenderViewImpl::OnDragTargetDragOver(const gfx::Point& client_point,
WebDragOperationsMask ops,
int key_modifiers) {
WebDragOperation operation = webview()->dragTargetDragOver(
- client_point,
+ ConvertWindowPointToViewport(client_point),
screen_point,
ops,
key_modifiers);
- Send(new DragHostMsg_UpdateDragCursor(routing_id(), operation));
+ Send(new DragHostMsg_UpdateDragCursor(GetRoutingID(), operation));
}
void RenderViewImpl::OnDragTargetDragLeave() {
@@ -2641,13 +2351,15 @@ void RenderViewImpl::OnDragTargetDragLeave() {
void RenderViewImpl::OnDragTargetDrop(const gfx::Point& client_point,
const gfx::Point& screen_point,
int key_modifiers) {
- webview()->dragTargetDrop(client_point, screen_point, key_modifiers);
+ webview()->dragTargetDrop(
+ ConvertWindowPointToViewport(client_point), screen_point, key_modifiers);
}
void RenderViewImpl::OnDragSourceEnded(const gfx::Point& client_point,
const gfx::Point& screen_point,
WebDragOperation op) {
- webview()->dragSourceEndedAt(client_point, screen_point, op);
+ webview()->dragSourceEndedAt(
+ ConvertWindowPointToViewport(client_point), screen_point, op);
}
void RenderViewImpl::OnDragSourceSystemDragEnded() {
@@ -2705,7 +2417,7 @@ void RenderViewImpl::OnFileChooserResponse(
// If there are more pending file chooser requests, schedule one now.
if (!file_chooser_completions_.empty()) {
Send(new ViewHostMsg_RunFileChooser(
- routing_id(), file_chooser_completions_.front()->params));
+ GetRoutingID(), file_chooser_completions_.front()->params));
}
}
@@ -2733,15 +2445,18 @@ void RenderViewImpl::OnDisableAutoResize(const gfx::Size& new_size) {
webview()->disableAutoResizeMode();
if (!new_size.IsEmpty()) {
- Resize(new_size,
- physical_backing_size_,
- top_controls_shrink_blink_size_,
- top_controls_height_,
- visible_viewport_size_,
- resizer_rect_,
- is_fullscreen_granted_,
- display_mode_,
- NO_RESIZE_ACK);
+ ResizeParams resize_params;
+ resize_params.new_size = new_size;
+ resize_params.physical_backing_size = physical_backing_size_;
+ resize_params.top_controls_shrink_blink_size =
+ top_controls_shrink_blink_size_;
+ resize_params.top_controls_height = top_controls_height_;
+ resize_params.visible_viewport_size = visible_viewport_size_;
+ resize_params.resizer_rect = resizer_rect_;
+ resize_params.is_fullscreen_granted = is_fullscreen_granted();
+ resize_params.display_mode = display_mode_;
+ resize_params.needs_resize_ack = false;
+ Resize(resize_params);
}
}
@@ -2820,11 +2535,6 @@ void RenderViewImpl::OnPluginActionAt(const gfx::Point& location,
webview()->performPluginAction(action, location);
}
-void RenderViewImpl::OnSuppressDialogsUntilSwapOut() {
- // Don't show any more dialogs until we finish OnSwapOut.
- suppress_dialogs_until_swap_out_ = true;
-}
-
void RenderViewImpl::OnClosePage() {
FOR_EACH_OBSERVER(RenderViewObserver, observers_, ClosePage());
// TODO(creis): We'd rather use webview()->Close() here, but that currently
@@ -2836,12 +2546,12 @@ void RenderViewImpl::OnClosePage() {
// http://b/issue?id=753080.
webview()->mainFrame()->dispatchUnloadEvent();
- Send(new ViewHostMsg_ClosePage_ACK(routing_id()));
+ Send(new ViewHostMsg_ClosePage_ACK(GetRoutingID()));
}
void RenderViewImpl::OnClose() {
if (closing_)
- RenderThread::Get()->Send(new ViewHostMsg_Close_ACK(routing_id()));
+ RenderThread::Get()->Send(new ViewHostMsg_Close_ACK(GetRoutingID()));
RenderWidget::OnClose();
}
@@ -2863,7 +2573,7 @@ void RenderViewImpl::OnMoveOrResizeStarted() {
webview()->hidePopups();
}
-void RenderViewImpl::OnResize(const ViewMsg_Resize_Params& params) {
+void RenderViewImpl::OnResize(const ResizeParams& params) {
TRACE_EVENT0("renderer", "RenderViewImpl::OnResize");
if (webview()) {
webview()->hidePopups();
@@ -2886,7 +2596,7 @@ void RenderViewImpl::OnResize(const ViewMsg_Resize_Params& params) {
has_scrolled_focused_editable_node_into_rect_ = false;
}
-void RenderViewImpl::DidInitiatePaint() {
+void RenderViewImpl::RenderWidgetDidCommitAndDrawCompositorFrame() {
#if defined(ENABLE_PLUGINS)
// Notify all instances that we painted. The same caveats apply as for
// ViewFlushedPaint regarding instances closing themselves, so we take
@@ -2899,7 +2609,7 @@ void RenderViewImpl::DidInitiatePaint() {
#endif
}
-void RenderViewImpl::DidFlushPaint() {
+void RenderViewImpl::RenderWidgetDidFlushPaint() {
// If the RenderWidget is closing down then early-exit, otherwise we'll crash.
// See crbug.com/112921.
if (!webview())
@@ -2946,31 +2656,14 @@ void RenderViewImpl::DidFlushPaint() {
}
}
-gfx::Vector2d RenderViewImpl::GetScrollOffset() {
- WebFrame* main_frame = webview()->mainFrame();
- for (WebFrame* frame = main_frame; frame;
- frame = frame->traverseNext(false)) {
- // TODO(nasko): This is a hack for the case in which the top-level
- // frame is being rendered in another process. It will not
- // behave correctly for out of process iframes.
- if (frame->isWebLocalFrame()) {
- main_frame = frame;
- break;
- }
- }
-
- WebSize scroll_offset = main_frame->scrollOffset();
- return gfx::Vector2d(scroll_offset.width, scroll_offset.height);
-}
-
void RenderViewImpl::OnClearFocusedElement() {
if (webview())
webview()->clearFocusedElement();
}
void RenderViewImpl::OnSetBackgroundOpaque(bool opaque) {
- if (webview())
- webview()->setIsTransparent(!opaque);
+ if (frame_widget_)
+ frame_widget_->setIsTransparent(!opaque);
if (compositor_)
compositor_->setHasTransparentBackground(!opaque);
}
@@ -2978,52 +2671,8 @@ void RenderViewImpl::OnSetBackgroundOpaque(bool opaque) {
void RenderViewImpl::OnSetActive(bool active) {
if (webview())
webview()->setIsActive(active);
-
-#if defined(ENABLE_PLUGINS) && defined(OS_MACOSX)
- std::set<WebPluginDelegateProxy*>::iterator plugin_it;
- for (plugin_it = plugin_delegates_.begin();
- plugin_it != plugin_delegates_.end(); ++plugin_it) {
- (*plugin_it)->SetWindowFocus(active);
- }
-#endif
-}
-
-#if defined(OS_MACOSX)
-void RenderViewImpl::OnSetWindowVisibility(bool visible) {
-#if defined(ENABLE_PLUGINS)
- // Inform plugins that their container has changed visibility.
- std::set<WebPluginDelegateProxy*>::iterator plugin_it;
- for (plugin_it = plugin_delegates_.begin();
- plugin_it != plugin_delegates_.end(); ++plugin_it) {
- (*plugin_it)->SetContainerVisibility(visible);
- }
-#endif
-}
-
-void RenderViewImpl::OnWindowFrameChanged(const gfx::Rect& window_frame,
- const gfx::Rect& view_frame) {
-#if defined(ENABLE_PLUGINS)
- // Inform plugins that their window's frame has changed.
- std::set<WebPluginDelegateProxy*>::iterator plugin_it;
- for (plugin_it = plugin_delegates_.begin();
- plugin_it != plugin_delegates_.end(); ++plugin_it) {
- (*plugin_it)->WindowFrameChanged(window_frame, view_frame);
- }
-#endif
}
-void RenderViewImpl::OnPluginImeCompositionCompleted(const base::string16& text,
- int plugin_id) {
- // WebPluginDelegateProxy is responsible for figuring out if this event
- // applies to it or not, so inform all the delegates.
- std::set<WebPluginDelegateProxy*>::iterator plugin_it;
- for (plugin_it = plugin_delegates_.begin();
- plugin_it != plugin_delegates_.end(); ++plugin_it) {
- (*plugin_it)->ImeCompositionCompleted(text, plugin_id);
- }
-}
-#endif // OS_MACOSX
-
void RenderViewImpl::CloseForFrame() {
DCHECK(frame_widget_);
frame_widget_->close();
@@ -3035,8 +2684,8 @@ void RenderViewImpl::Close() {
WebView* doomed = webview();
RenderWidget::Close();
g_view_map.Get().erase(doomed);
- g_routing_id_view_map.Get().erase(routing_id());
- RenderThread::Get()->Send(new ViewHostMsg_Close_ACK(routing_id()));
+ g_routing_id_view_map.Get().erase(GetRoutingID());
+ RenderThread::Get()->Send(new ViewHostMsg_Close_ACK(GetRoutingID()));
}
void RenderViewImpl::OnWasHidden() {
@@ -3056,15 +2705,6 @@ void RenderViewImpl::OnWasHidden() {
for (PepperPluginSet::iterator i = active_pepper_instances_.begin();
i != active_pepper_instances_.end(); ++i)
(*i)->PageVisibilityChanged(false);
-
-#if defined(OS_MACOSX)
- // Inform NPAPI plugins that their container is no longer visible.
- std::set<WebPluginDelegateProxy*>::iterator plugin_it;
- for (plugin_it = plugin_delegates_.begin();
- plugin_it != plugin_delegates_.end(); ++plugin_it) {
- (*plugin_it)->SetContainerVisibility(false);
- }
-#endif // OS_MACOSX
#endif // ENABLE_PLUGINS
}
@@ -3084,15 +2724,6 @@ void RenderViewImpl::OnWasShown(bool needs_repainting,
for (PepperPluginSet::iterator i = active_pepper_instances_.begin();
i != active_pepper_instances_.end(); ++i)
(*i)->PageVisibilityChanged(true);
-
-#if defined(OS_MACOSX)
- // Inform NPAPI plugins that their container is now visible.
- std::set<WebPluginDelegateProxy*>::iterator plugin_it;
- for (plugin_it = plugin_delegates_.begin();
- plugin_it != plugin_delegates_.end(); ++plugin_it) {
- (*plugin_it)->SetContainerVisibility(true);
- }
-#endif // OS_MACOSX
#endif // ENABLE_PLUGINS
}
@@ -3116,20 +2747,6 @@ void RenderViewImpl::SetFocus(bool enable) {
RenderWidget::OnSetFocus(enable);
#if defined(ENABLE_PLUGINS)
- if (webview() && webview()->isActive()) {
- // Notify all NPAPI plugins.
- std::set<WebPluginDelegateProxy*>::iterator plugin_it;
- for (plugin_it = plugin_delegates_.begin();
- plugin_it != plugin_delegates_.end(); ++plugin_it) {
-#if defined(OS_MACOSX)
- // RenderWidget's call to setFocus can cause the underlying webview's
- // activation state to change just like a call to setIsActive.
- if (enable)
- (*plugin_it)->SetWindowFocus(true);
-#endif
- (*plugin_it)->SetContentAreaFocus(enable);
- }
- }
// Notify all Pepper plugins.
for (PepperPluginSet::iterator i = active_pepper_instances_.begin();
i != active_pepper_instances_.end(); ++i)
@@ -3143,6 +2760,7 @@ void RenderViewImpl::SetFocus(bool enable) {
void RenderViewImpl::OnImeSetComposition(
const base::string16& text,
const std::vector<blink::WebCompositionUnderline>& underlines,
+ const gfx::Range& replacement_range,
int selection_start,
int selection_end) {
#if defined(ENABLE_PLUGINS)
@@ -3151,35 +2769,20 @@ void RenderViewImpl::OnImeSetComposition(
text, underlines, selection_start, selection_end);
return;
}
-
-#if defined(OS_WIN)
- // When a plugin has focus, we create platform-specific IME data used by
- // our IME emulator and send it directly to the focused plugin, i.e. we
- // bypass WebKit. (WebPluginDelegate dispatches this IME data only when its
- // instance ID is the same one as the specified ID.)
- if (focused_plugin_id_ >= 0) {
- std::vector<int> clauses;
- std::vector<int> target;
- for (size_t i = 0; i < underlines.size(); ++i) {
- clauses.push_back(underlines[i].startOffset);
- clauses.push_back(underlines[i].endOffset);
- if (underlines[i].thick) {
- target.clear();
- target.push_back(underlines[i].startOffset);
- target.push_back(underlines[i].endOffset);
- }
- }
- std::set<WebPluginDelegateProxy*>::iterator it;
- for (it = plugin_delegates_.begin(); it != plugin_delegates_.end(); ++it) {
- (*it)->ImeCompositionUpdated(text, clauses, target, selection_end,
- focused_plugin_id_);
+#endif // ENABLE_PLUGINS
+ if (replacement_range.IsValid() && webview()) {
+ // Select the text in |replacement_range|, it will then be replaced by
+ // text added by the call to RenderWidget::OnImeSetComposition().
+ if (WebLocalFrame* frame = webview()->focusedFrame()->toWebLocalFrame()) {
+ WebRange webrange = WebRange::fromDocumentRange(
+ frame, replacement_range.start(), replacement_range.length());
+ if (!webrange.isNull())
+ frame->selectRange(webrange);
}
- return;
}
-#endif // OS_WIN
-#endif // ENABLE_PLUGINS
RenderWidget::OnImeSetComposition(text,
underlines,
+ replacement_range,
selection_start,
selection_end);
}
@@ -3194,20 +2797,6 @@ void RenderViewImpl::OnImeConfirmComposition(
text, replacement_range, keep_selection);
return;
}
-#if defined(OS_WIN)
- // Same as OnImeSetComposition(), we send the text from IMEs directly to
- // plugins. When we send IME text directly to plugins, we should not send
- // it to WebKit to prevent WebKit from controlling IMEs.
- // TODO(thakis): Honor |replacement_range| for plugins?
- if (focused_plugin_id_ >= 0) {
- std::set<WebPluginDelegateProxy*>::iterator it;
- for (it = plugin_delegates_.begin();
- it != plugin_delegates_.end(); ++it) {
- (*it)->ImeCompositionCompleted(text, focused_plugin_id_);
- }
- return;
- }
-#endif // OS_WIN
#endif // ENABLE_PLUGINS
if (replacement_range.IsValid() && webview()) {
// Select the text in |replacement_range|, it will then be replaced by
@@ -3224,20 +2813,18 @@ void RenderViewImpl::OnImeConfirmComposition(
keep_selection);
}
-bool RenderViewImpl::SetDeviceColorProfile(
+void RenderViewImpl::RenderWidgetDidSetColorProfile(
const std::vector<char>& profile) {
- bool changed = RenderWidget::SetDeviceColorProfile(profile);
- if (changed && webview()) {
- WebVector<char> colorProfile = profile;
- webview()->setDeviceColorProfile(colorProfile);
- }
- return changed;
-}
+ if (webview()) {
+ bool was_reset = (profile.size() == 1 && profile[0] == '0');
-void RenderViewImpl::ResetDeviceColorProfileForTesting() {
- RenderWidget::ResetDeviceColorProfileForTesting();
- if (webview())
- webview()->resetDeviceColorProfileForTesting();
+ if (was_reset) {
+ webview()->resetDeviceColorProfileForTesting();
+ } else {
+ WebVector<char> colorProfile = profile;
+ webview()->setDeviceColorProfile(colorProfile);
+ }
+ }
}
ui::TextInputType RenderViewImpl::GetTextInputType() {
@@ -3256,7 +2843,7 @@ void RenderViewImpl::GetSelectionBounds(gfx::Rect* start, gfx::Rect* end) {
// use the caret position as an empty range for now. It will be updated
// after Pepper API equips features related to surrounding text retrieval.
blink::WebRect caret(focused_pepper_plugin_->GetCaretBounds());
- convertViewportToWindow(&caret);
+ ConvertViewportToWindowViaWidget(&caret);
*start = caret;
*end = caret;
return;
@@ -3297,7 +2884,7 @@ void RenderViewImpl::GetCompositionCharacterBounds(
bounds_in_window->clear();
return;
}
- convertViewportToWindow(&webrect);
+ ConvertViewportToWindowViaWidget(&webrect);
bounds_in_window->push_back(webrect);
}
}
@@ -3320,7 +2907,7 @@ bool RenderViewImpl::CanComposeInline() {
}
void RenderViewImpl::DidCompletePageScaleAnimation() {
- FocusChangeComplete();
+ GetWidget()->FocusChangeComplete();
}
void RenderViewImpl::OnDeviceScaleFactorChanged() {
@@ -3361,7 +2948,7 @@ bool RenderViewImpl::ScheduleFileChooser(
make_scoped_ptr(new PendingFileChooser(params, completion)));
if (file_chooser_completions_.size() == 1) {
// Actually show the browse dialog when this is the first request.
- Send(new ViewHostMsg_RunFileChooser(routing_id(), params));
+ Send(new ViewHostMsg_RunFileChooser(GetRoutingID(), params));
}
return true;
}
@@ -3381,7 +2968,7 @@ void RenderViewImpl::zoomLimitsChanged(double minimum_level,
int maximum_percent = round(
ZoomLevelToZoomFactor(maximum_level) * 100);
- Send(new ViewHostMsg_UpdateZoomLimits(routing_id(), minimum_percent,
+ Send(new ViewHostMsg_UpdateZoomLimits(GetRoutingID(), minimum_percent,
maximum_percent));
}
@@ -3394,7 +2981,7 @@ void RenderViewImpl::zoomLevelChanged() {
// Tell the browser which url got zoomed so it can update the menu and the
// saved values if necessary
Send(new ViewHostMsg_DidZoomURL(
- routing_id(), zoom_level,
+ GetRoutingID(), zoom_level,
GURL(webview()->mainFrame()->document().url())));
}
}
@@ -3403,7 +2990,7 @@ void RenderViewImpl::pageScaleFactorChanged() {
if (!webview())
return;
- Send(new ViewHostMsg_PageScaleFactorChanged(routing_id(),
+ Send(new ViewHostMsg_PageScaleFactorChanged(GetRoutingID(),
webview()->pageScaleFactor()));
}
@@ -3489,7 +3076,7 @@ void RenderViewImpl::LaunchAndroidContentIntent(const GURL& intent,
ScheduleComposite();
if (!intent.is_empty()) {
- Send(new ViewHostMsg_StartContentIntent(routing_id(), intent,
+ Send(new ViewHostMsg_StartContentIntent(GetRoutingID(), intent,
is_main_frame));
}
}
@@ -3522,15 +3109,6 @@ void RenderViewImpl::OnShowContextMenu(
has_host_context_menu_location_ = false;
}
-void RenderViewImpl::OnEnableViewSourceMode() {
- if (!webview())
- return;
- WebFrame* main_frame = webview()->mainFrame();
- if (!main_frame)
- return;
- main_frame->enableViewSourceMode(true);
-}
-
#if defined(OS_ANDROID) || defined(USE_AURA)
bool RenderViewImpl::didTapMultipleTargets(
const WebSize& inner_viewport_offset,
@@ -3602,7 +3180,7 @@ bool RenderViewImpl::didTapMultipleTargets(
ClientRectToPhysicalWindowRect(gfx::RectF(zoom_rect_in_screen)));
Send(new ViewHostMsg_ShowDisambiguationPopup(
- routing_id(), physical_window_zoom_rect, canvas_size,
+ GetRoutingID(), physical_window_zoom_rect, canvas_size,
shared_bitmap->id()));
cc::SharedBitmapId id = shared_bitmap->id();
disambiguation_bitmaps_[id] = shared_bitmap.release();
@@ -3637,7 +3215,7 @@ void RenderViewImpl::SetFocusAndActivateForTesting(bool enable) {
}
void RenderViewImpl::SetDeviceScaleFactorForTesting(float factor) {
- ViewMsg_Resize_Params params;
+ ResizeParams params;
params.screen_info = screen_info_;
params.screen_info.deviceScaleFactor = factor;
params.new_size = size();
@@ -3651,11 +3229,6 @@ void RenderViewImpl::SetDeviceScaleFactorForTesting(float factor) {
OnResize(params);
}
-void RenderViewImpl::SetDeviceColorProfileForTesting(
- const std::vector<char>& color_profile) {
- SetDeviceColorProfile(color_profile);
-}
-
void RenderViewImpl::ForceResizeForTesting(const gfx::Size& new_size) {
gfx::Rect new_window_rect(rootWindowRect().x,
rootWindowRect().y,
@@ -3692,7 +3265,7 @@ void RenderViewImpl::DidCommitCompositorFrame() {
void RenderViewImpl::SendUpdateFaviconURL(const std::vector<FaviconURL>& urls) {
if (!urls.empty())
- Send(new ViewHostMsg_UpdateFaviconURL(routing_id(), urls));
+ Send(new ViewHostMsg_UpdateFaviconURL(GetRoutingID(), urls));
}
void RenderViewImpl::DidStopLoadingIcons() {
diff --git a/chromium/content/renderer/render_view_impl.h b/chromium/content/renderer/render_view_impl.h
index b6e54b8cf9c..71f89fb01af 100644
--- a/chromium/content/renderer/render_view_impl.h
+++ b/chromium/content/renderer/render_view_impl.h
@@ -36,17 +36,18 @@
#include "content/public/common/page_zoom.h"
#include "content/public/common/referrer.h"
#include "content/public/common/renderer_preferences.h"
-#include "content/public/common/stop_find_action.h"
#include "content/public/common/top_controls_state.h"
#include "content/public/common/web_preferences.h"
#include "content/public/renderer/render_view.h"
#include "content/renderer/mouse_lock_dispatcher.h"
#include "content/renderer/render_frame_impl.h"
#include "content/renderer/render_widget.h"
+#include "content/renderer/render_widget_owner_delegate.h"
#include "content/renderer/stats_collection_observer.h"
#include "ipc/ipc_platform_file.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
#include "third_party/WebKit/public/platform/WebPageVisibilityState.h"
+#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/web/WebAXObject.h"
#include "third_party/WebKit/public/web/WebConsoleMessage.h"
#include "third_party/WebKit/public/web/WebDataSource.h"
@@ -57,7 +58,6 @@
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "third_party/WebKit/public/web/WebNavigationType.h"
#include "third_party/WebKit/public/web/WebNode.h"
-#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
#include "third_party/WebKit/public/web/WebViewClient.h"
#include "ui/base/window_open_disposition.h"
#include "ui/gfx/geometry/rect.h"
@@ -80,7 +80,6 @@
class SkBitmap;
struct PP_NetAddress_Private;
struct ViewMsg_New_Params;
-struct ViewMsg_Resize_Params;
struct ViewMsg_StopFinding_Params;
namespace base {
@@ -109,7 +108,6 @@ class WebURLRequest;
struct WebActiveWheelFlingParameters;
struct WebDateTimeChooserParams;
struct WebFileChooserParams;
-struct WebFindOptions;
struct WebMediaPlayerAction;
struct WebPluginAction;
struct WebPoint;
@@ -139,6 +137,7 @@ struct FaviconURL;
struct FileChooserParams;
struct FileChooserFileInfo;
struct RenderViewImplParams;
+struct ResizeParams;
#if defined(OS_ANDROID)
class WebMediaPlayerProxyAndroid;
@@ -156,6 +155,7 @@ class WebMediaPlayerProxyAndroid;
class CONTENT_EXPORT RenderViewImpl
: public RenderWidget,
NON_EXPORTED_BASE(public blink::WebViewClient),
+ public RenderWidgetOwnerDelegate,
public RenderView,
public base::SupportsWeakPtr<RenderViewImpl> {
public:
@@ -243,19 +243,11 @@ class CONTENT_EXPORT RenderViewImpl
// FocusController.
void SetFocus(bool enable);
- void AttachWebFrameWidget(blink::WebWidget* frame_widget);
+ void AttachWebFrameWidget(blink::WebFrameWidget* frame_widget);
// Plugin-related functions --------------------------------------------------
#if defined(ENABLE_PLUGINS)
- // Get/set the plugin which will be used as to handle document find requests.
- void set_plugin_find_handler(PepperPluginInstanceImpl* plugin) {
- plugin_find_handler_ = plugin;
- }
- PepperPluginInstanceImpl* plugin_find_handler() {
- return plugin_find_handler_;
- }
-
PepperPluginInstanceImpl* focused_pepper_plugin() {
return focused_pepper_plugin_;
}
@@ -266,16 +258,6 @@ class CONTENT_EXPORT RenderViewImpl
pepper_last_mouse_event_target_ = plugin;
}
-#if defined(OS_MACOSX) || defined(OS_WIN)
- // Informs the render view that the given plugin has gained or lost focus.
- void PluginFocusChanged(bool focused, int plugin_id);
-#endif
-
-#if defined(OS_MACOSX)
- // Starts plugin IME.
- void StartPluginIme();
-#endif
-
// Indicates that the given instance has been created.
void PepperInstanceCreated(PepperPluginInstanceImpl* instance);
@@ -286,9 +268,6 @@ class CONTENT_EXPORT RenderViewImpl
// Notification that the given plugin is focused or unfocused.
void PepperFocusChanged(PepperPluginInstanceImpl* instance, bool focused);
-
- void RegisterPluginDelegate(WebPluginDelegateProxy* delegate);
- void UnregisterPluginDelegate(WebPluginDelegateProxy* delegate);
#endif // ENABLE_PLUGINS
void TransferActiveWheelFlingAnimation(
@@ -315,10 +294,6 @@ class CONTENT_EXPORT RenderViewImpl
// Change the device scale factor and force the compositor to resize.
void SetDeviceScaleFactorForTesting(float factor);
- // Change the device ICC color profile while running a layout test.
- void SetDeviceColorProfileForTesting(const std::vector<char>& color_profile);
- void ResetDeviceColorProfileForTesting() override;
-
// Used to force the size of a window when running layout tests.
void ForceResizeForTesting(const gfx::Size& new_size);
@@ -329,15 +304,6 @@ class CONTENT_EXPORT RenderViewImpl
const gfx::Size& max_size);
void DisableAutoResizeForTesting(const gfx::Size& new_size);
- // RenderWidgetInputHandlerDelegate implementation ---------------------------
-
- // Most methods are handled by RenderWidget
- void FocusChangeComplete() override;
- bool HasTouchEventHandlersAt(const gfx::Point& point) const override;
- void OnDidHandleKeyEvent() override;
- bool WillHandleGestureEvent(const blink::WebGestureEvent& event) override;
- bool WillHandleMouseEvent(const blink::WebMouseEvent& event) override;
-
// IPC::Listener implementation ----------------------------------------------
bool OnMessageReceived(const IPC::Message& msg) override;
@@ -439,6 +405,7 @@ class CONTENT_EXPORT RenderViewImpl
// RenderView implementation -------------------------------------------------
bool Send(IPC::Message* message) override;
+ RenderWidget* GetWidget() const override;
RenderFrameImpl* GetMainRenderFrame() override;
int GetRoutingID() const override;
gfx::Size GetSize() const override;
@@ -446,6 +413,7 @@ class CONTENT_EXPORT RenderViewImpl
WebPreferences& GetWebkitPreferences() override;
void SetWebkitPreferences(const WebPreferences& preferences) override;
blink::WebView* GetWebView() override;
+ blink::WebFrameWidget* GetWebFrameWidget() override;
bool ShouldDisplayScrollbars(int width, int height) const override;
int GetEnabledBindings() const override;
bool GetContentStateImmediately() const override;
@@ -463,10 +431,12 @@ class CONTENT_EXPORT RenderViewImpl
TopControlsState current,
bool animate) override;
#endif
- void convertViewportToWindow(blink::WebRect* rect) override;
+ void ConvertViewportToWindowViaWidget(blink::WebRect* rect) override;
gfx::RectF ElementBoundsInWindow(const blink::WebElement& element) override;
float GetDeviceScaleFactorForTest() const override;
+ gfx::Point ConvertWindowPointToViewport(const gfx::Point& point);
+
bool uses_temporary_zoom_level() const { return uses_temporary_zoom_level_; }
// Please do not add your stuff randomly to the end here. If there is an
@@ -477,10 +447,7 @@ class CONTENT_EXPORT RenderViewImpl
// RenderWidget overrides:
void CloseForFrame() override;
void Close() override;
- void OnResize(const ViewMsg_Resize_Params& params) override;
- void DidInitiatePaint() override;
- void DidFlushPaint() override;
- gfx::Vector2d GetScrollOffset() override;
+ void OnResize(const ResizeParams& params) override;
void OnSetFocus(bool enable) override;
void OnWasHidden() override;
void OnWasShown(bool needs_repainting,
@@ -489,12 +456,12 @@ class CONTENT_EXPORT RenderViewImpl
void OnImeSetComposition(
const base::string16& text,
const std::vector<blink::WebCompositionUnderline>& underlines,
+ const gfx::Range& replacement_range,
int selection_start,
int selection_end) override;
void OnImeConfirmComposition(const base::string16& text,
const gfx::Range& replacement_range,
bool keep_selection) override;
- bool SetDeviceColorProfile(const std::vector<char>& color_profile) override;
void OnOrientationChange() override;
ui::TextInputType GetTextInputType() override;
void GetSelectionBounds(gfx::Rect* start, gfx::Rect* end) override;
@@ -506,7 +473,6 @@ class CONTENT_EXPORT RenderViewImpl
void DidCompletePageScaleAnimation() override;
void OnDeviceScaleFactorChanged() override;
- protected:
RenderViewImpl(CompositorDependencies* compositor_deps,
const ViewMsg_New_Params& params);
@@ -556,7 +522,10 @@ class CONTENT_EXPORT RenderViewImpl
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
GetCompositionCharacterBoundsTest);
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, OnNavigationHttpPost);
- FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest, ScreenMetricsEmulation);
+ FRIEND_TEST_ALL_PREFIXES(RenderViewImplScaleFactorTest,
+ ScreenMetricsEmulationWithOriginalDSF1);
+ FRIEND_TEST_ALL_PREFIXES(RenderViewImplScaleFactorTest,
+ ScreenMetricsEmulationWithOriginalDSF2);
FRIEND_TEST_ALL_PREFIXES(RenderViewImplTest,
DecideNavigationPolicyHandlesAllTopLevel);
#if defined(OS_MACOSX)
@@ -587,6 +556,21 @@ class CONTENT_EXPORT RenderViewImpl
CONNECTION_ERROR,
};
+ // RenderWidgetOwnerDelegate implementation ----------------------------------
+
+ void RenderWidgetDidSetColorProfile(
+ const std::vector<char>& color_profile) override;
+ void RenderWidgetFocusChangeComplete() override;
+ bool DoesRenderWidgetHaveTouchEventHandlersAt(
+ const gfx::Point& point) const override;
+ void RenderWidgetDidHandleKeyEvent() override;
+ bool RenderWidgetWillHandleGestureEvent(
+ const blink::WebGestureEvent& event) override;
+ bool RenderWidgetWillHandleMouseEvent(
+ const blink::WebMouseEvent& event) override;
+ void RenderWidgetDidCommitAndDrawCompositorFrame() override;
+ void RenderWidgetDidFlushPaint() override;
+
// Old WebFrameClient implementations ----------------------------------------
// RenderViewImpl used to be a WebFrameClient, but now RenderFrameImpl is the
@@ -607,9 +591,6 @@ class CONTENT_EXPORT RenderViewImpl
blink::WebView* web_view,
CompositorDependencies* compositor_deps);
- // Sends a message and runs a nested message loop.
- bool SendAndRunNestedMessageLoop(IPC::SyncMessage* message);
-
// IPC message handlers ------------------------------------------------------
//
// The documentation for these functions should be in
@@ -656,9 +637,6 @@ class CONTENT_EXPORT RenderViewImpl
const std::vector<base::FilePath>& paths);
void OnFileChooserResponse(
const std::vector<content::FileChooserFileInfo>& files);
- void OnFind(int request_id,
- const base::string16&,
- const blink::WebFindOptions&);
void OnMediaPlayerActionAt(const gfx::Point& location,
const blink::WebMediaPlayerAction& action);
void OnPluginActionAt(const gfx::Point& location,
@@ -676,19 +654,14 @@ class CONTENT_EXPORT RenderViewImpl
void OnSetWebUIProperty(const std::string& name, const std::string& value);
void OnSetZoomLevelForLoadingURL(const GURL& url, double zoom_level);
void OnSetZoomLevelForView(bool uses_temporary_zoom_level, double level);
- void OnStopFinding(StopFindAction action);
- void OnSuppressDialogsUntilSwapOut();
void OnThemeChanged();
void OnUpdateTargetURLAck();
void OnUpdateWebPreferences(const WebPreferences& prefs);
void OnSetPageScale(float page_scale_factor);
void OnZoom(PageZoom zoom);
- void OnEnableViewSourceMode();
void OnForceRedraw(int request_id);
void OnSelectWordAroundCaret();
#if defined(OS_ANDROID)
- void OnActivateNearestFindResult(int request_id, float x, float y);
- void OnFindMatchRects(int current_version);
void OnUndoScrollFocusedEditableNodeIntoRect();
void OnUpdateTopControlsState(bool enable_hiding,
bool enable_showing,
@@ -696,14 +669,11 @@ class CONTENT_EXPORT RenderViewImpl
void OnExtractSmartClipData(const gfx::Rect& rect);
#elif defined(OS_MACOSX)
void OnGetRenderedText();
- void OnPluginImeCompositionCompleted(const base::string16& text,
- int plugin_id);
- void OnSetInLiveResize(bool in_live_resize);
- void OnSetWindowVisibility(bool visible);
- void OnWindowFrameChanged(const gfx::Rect& window_frame,
- const gfx::Rect& view_frame);
#endif
+ // Page message handlers -----------------------------------------------------
+ void OnUpdateWindowScreenRect(gfx::Rect window_screen_rect);
+
// Adding a new message handler? Please add it in alphabetical order above
// and put it in the same position in the .cc file.
@@ -714,10 +684,6 @@ class CONTENT_EXPORT RenderViewImpl
// Gets the currently focused element, if any.
blink::WebElement GetFocusedElement() const;
- // Called to get the WebPlugin to handle find requests in the document.
- // Returns NULL if there is no such WebPlugin.
- blink::WebPlugin* GetWebPluginForFind();
-
#if defined(OS_ANDROID)
// Launch an Android content intent with the given URL.
void LaunchAndroidContentIntent(const GURL& intent_url,
@@ -725,14 +691,6 @@ class CONTENT_EXPORT RenderViewImpl
bool is_main_frame);
#endif
- // Sends a reply to the current find operation handling if it was a
- // synchronous find request.
- void SendFindReply(int request_id,
- int match_count,
- int ordinal,
- const blink::WebRect& selection_rect,
- bool final_status_update);
-
#if defined(OS_WIN) || (defined(OS_POSIX) && !defined(OS_MACOSX))
void UpdateFontRenderingFromRendererPrefs();
#else
@@ -765,12 +723,6 @@ class CONTENT_EXPORT RenderViewImpl
// this object.
base::ObserverList<RenderViewObserver>& observers() { return observers_; }
- // TODO(nasko): Remove this method when we move to frame proxy objects, since
- // the concept of swapped out will be eliminated.
- void set_is_swapped_out(bool swapped_out) {
- is_swapped_out_ = swapped_out;
- }
-
NavigationGesture navigation_gesture() {
return navigation_gesture_;
}
@@ -831,16 +783,6 @@ class CONTENT_EXPORT RenderViewImpl
// Used for popups.
bool opened_by_user_gesture_;
- // Whether this RenderView was created by a frame that was suppressing its
- // opener. If so, we may want to load pages in a separate process. See
- // decidePolicyForNavigation for details.
- bool opener_suppressed_;
-
- // Whether we must stop creating nested message loops for modal dialogs until
- // OnSwapOut is called. This is necessary because modal dialogs have a
- // PageGroupLoadDeferrer on the stack that interferes with swapping out.
- bool suppress_dialogs_until_swap_out_;
-
// Timer used to delay the updating of nav state (see
// StartNavStateSyncTimerIfNecessary).
base::OneShotTimer nav_state_sync_timer_;
@@ -936,7 +878,7 @@ class CONTENT_EXPORT RenderViewImpl
// Note: RenderViewImpl is pulling double duty: it's the RenderWidget for the
// "view", but it's also the RenderWidget for the main frame.
- blink::WebWidget* frame_widget_;
+ blink::WebFrameWidget* frame_widget_;
// The next group of objects all implement RenderViewObserver, so are deleted
// along with the RenderView automatically. This is why we just store
@@ -966,20 +908,7 @@ class CONTENT_EXPORT RenderViewImpl
#endif
// Plugins -------------------------------------------------------------------
-
- // All the currently active plugin delegates for this RenderView; kept so
- // that we can enumerate them to send updates about things like window
- // location or tab focus and visibily. These are non-owning references.
- std::set<WebPluginDelegateProxy*> plugin_delegates_;
-
-#if defined(OS_WIN)
- // The ID of the focused NPAPI plugin.
- int focused_plugin_id_;
-#endif
-
#if defined(ENABLE_PLUGINS)
- PepperPluginInstanceImpl* plugin_find_handler_;
-
typedef std::set<PepperPluginInstanceImpl*> PepperPluginSet;
PepperPluginSet active_pepper_instances_;
diff --git a/chromium/content/renderer/render_view_mouse_lock_dispatcher.cc b/chromium/content/renderer/render_view_mouse_lock_dispatcher.cc
index 25b4ccc4ff2..bdd747b044e 100644
--- a/chromium/content/renderer/render_view_mouse_lock_dispatcher.cc
+++ b/chromium/content/renderer/render_view_mouse_lock_dispatcher.cc
@@ -59,8 +59,8 @@ void RenderViewMouseLockDispatcher::OnLockMouseACK(bool succeeded) {
// Mouse Capture is implicitly given for the duration of a drag event, and
// sends all mouse events to the initial target of the drag.
// If Lock is entered it supercedes any in progress Capture.
- if (succeeded && render_view_impl_->webwidget())
- render_view_impl_->webwidget()->mouseCaptureLost();
+ if (succeeded && render_view_impl_->GetWidget()->webwidget())
+ render_view_impl_->GetWidget()->webwidget()->mouseCaptureLost();
}
} // namespace content
diff --git a/chromium/content/renderer/render_view_win.cc b/chromium/content/renderer/render_view_win.cc
index 15cb47bf7cd..51f97f5dd7c 100644
--- a/chromium/content/renderer/render_view_win.cc
+++ b/chromium/content/renderer/render_view_win.cc
@@ -32,6 +32,11 @@ void RenderViewImpl::UpdateFontRenderingFromRendererPrefs() {
blink::WebFontRendering::setLCDOrientation(
gfx::FontRenderParams::SubpixelRenderingToSkiaLCDOrientation(
prefs.subpixel_rendering));
+
+ blink::WebFontRendering::setAntialiasedTextEnabled(
+ prefs.should_antialias_text);
+ blink::WebFontRendering::setLCDTextEnabled(prefs.subpixel_rendering
+ != gfx::FontRenderParams::SUBPIXEL_RENDERING_NONE);
}
void RenderViewImpl::UpdateThemePrefs() {
diff --git a/chromium/content/renderer/render_widget.cc b/chromium/content/renderer/render_widget.cc
index 0ddaf21eee1..b9ec5d3818a 100644
--- a/chromium/content/renderer/render_widget.cc
+++ b/chromium/content/renderer/render_widget.cc
@@ -9,6 +9,7 @@
#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/command_line.h"
+#include "base/feature_list.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
@@ -24,22 +25,24 @@
#include "cc/base/switches.h"
#include "cc/debug/benchmark_instrumentation.h"
#include "cc/output/output_surface.h"
+#include "cc/scheduler/begin_frame_source.h"
#include "cc/trees/layer_tree_host.h"
#include "components/scheduler/renderer/render_widget_scheduling_state.h"
#include "components/scheduler/renderer/renderer_scheduler.h"
-#include "content/child/npapi/webplugin.h"
#include "content/common/content_switches_internal.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
+#include "content/common/gpu_process_launch_causes.h"
#include "content/common/input/synthetic_gesture_packet.h"
#include "content/common/input/web_input_event_traits.h"
#include "content/common/input_messages.h"
#include "content/common/swapped_out_messages.h"
#include "content/common/view_messages.h"
+#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/context_menu_params.h"
#include "content/renderer/cursor_utils.h"
+#include "content/renderer/devtools/render_widget_screen_metrics_emulator.h"
#include "content/renderer/external_popup_menu.h"
#include "content/renderer/gpu/compositor_output_surface.h"
#include "content/renderer/gpu/delegated_compositor_output_surface.h"
@@ -55,6 +58,7 @@
#include "content/renderer/render_process.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_view_impl.h"
+#include "content/renderer/render_widget_owner_delegate.h"
#include "content/renderer/renderer_blink_platform_impl.h"
#include "content/renderer/resizing_mode_selector.h"
#include "ipc/ipc_sync_message.h"
@@ -102,6 +106,10 @@
#include "content/renderer/mus/render_widget_mus_connection.h"
#endif
+#if defined(ENABLE_VULKAN)
+#include "cc/output/vulkan_in_process_context_provider.h"
+#endif
+
#include "third_party/WebKit/public/web/WebWidget.h"
using blink::WebCompositionUnderline;
@@ -128,6 +136,10 @@ using blink::WebTouchPoint;
using blink::WebVector;
using blink::WebWidget;
+#define STATIC_ASSERT_ENUM(a, b) \
+ static_assert(static_cast<int>(a) == static_cast<int>(b), \
+ "mismatching enums: " #a)
+
namespace {
typedef std::map<std::string, ui::TextInputMode> TextInputModeMap;
@@ -197,244 +209,6 @@ content::RenderWidgetInputHandlerDelegate* GetRenderWidgetInputHandlerDelegate(
namespace content {
-// RenderWidget::ScreenMetricsEmulator ----------------------------------------
-
-class RenderWidget::ScreenMetricsEmulator {
- public:
- ScreenMetricsEmulator(
- RenderWidget* widget,
- const WebDeviceEmulationParams& params);
- virtual ~ScreenMetricsEmulator();
-
- // Scale and offset used to convert between host coordinates
- // and webwidget coordinates.
- float scale() { return scale_; }
- gfx::PointF offset() { return offset_; }
- gfx::Rect applied_widget_rect() const { return applied_widget_rect_; }
- gfx::Rect original_screen_rect() const { return original_view_screen_rect_; }
- const WebScreenInfo& original_screen_info() { return original_screen_info_; }
-
- void ChangeEmulationParams(
- const WebDeviceEmulationParams& params);
-
- // The following methods alter handlers' behavior for messages related to
- // widget size and position.
- void OnResizeMessage(const ViewMsg_Resize_Params& params);
- void OnUpdateScreenRectsMessage(const gfx::Rect& view_screen_rect,
- const gfx::Rect& window_screen_rect);
- void OnShowContextMenu(ContextMenuParams* params);
- gfx::Rect AdjustValidationMessageAnchor(const gfx::Rect& anchor);
-
- private:
- void Reapply();
- void Apply(bool top_controls_shrink_blink_size,
- float top_controls_height,
- gfx::Rect resizer_rect,
- bool is_fullscreen_granted,
- blink::WebDisplayMode display_mode);
-
- RenderWidget* widget_;
-
- // Parameters as passed by RenderWidget::EnableScreenMetricsEmulation.
- WebDeviceEmulationParams params_;
-
- // The computed scale and offset used to fit widget into browser window.
- float scale_;
- gfx::PointF offset_;
-
- // Widget rect as passed to webwidget.
- gfx::Rect applied_widget_rect_;
-
- // Original values to restore back after emulation ends.
- gfx::Size original_size_;
- gfx::Size original_physical_backing_size_;
- gfx::Size original_visible_viewport_size_;
- blink::WebScreenInfo original_screen_info_;
- gfx::Rect original_view_screen_rect_;
- gfx::Rect original_window_screen_rect_;
-};
-
-RenderWidget::ScreenMetricsEmulator::ScreenMetricsEmulator(
- RenderWidget* widget,
- const WebDeviceEmulationParams& params)
- : widget_(widget),
- params_(params),
- scale_(1.f) {
- original_size_ = widget_->size_;
- original_physical_backing_size_ = widget_->physical_backing_size_;
- original_visible_viewport_size_ = widget_->visible_viewport_size_;
- original_screen_info_ = widget_->screen_info_;
- original_view_screen_rect_ = widget_->view_screen_rect_;
- original_window_screen_rect_ = widget_->window_screen_rect_;
- Apply(widget_->top_controls_shrink_blink_size_,
- widget_->top_controls_height_,
- widget_->resizer_rect_,
- widget_->is_fullscreen_granted_,
- widget_->display_mode_);
-}
-
-RenderWidget::ScreenMetricsEmulator::~ScreenMetricsEmulator() {
- widget_->screen_info_ = original_screen_info_;
-
- widget_->SetDeviceScaleFactor(original_screen_info_.deviceScaleFactor);
- widget_->SetScreenMetricsEmulationParameters(false, params_);
- widget_->view_screen_rect_ = original_view_screen_rect_;
- widget_->window_screen_rect_ = original_window_screen_rect_;
- widget_->Resize(original_size_,
- original_physical_backing_size_,
- widget_->top_controls_shrink_blink_size_,
- widget_->top_controls_height_,
- original_visible_viewport_size_,
- widget_->resizer_rect_,
- widget_->is_fullscreen_granted_,
- widget_->display_mode_,
- NO_RESIZE_ACK);
-}
-
-void RenderWidget::ScreenMetricsEmulator::ChangeEmulationParams(
- const WebDeviceEmulationParams& params) {
- params_ = params;
- Reapply();
-}
-
-void RenderWidget::ScreenMetricsEmulator::Reapply() {
- Apply(widget_->top_controls_shrink_blink_size_,
- widget_->top_controls_height_,
- widget_->resizer_rect_,
- widget_->is_fullscreen_granted_,
- widget_->display_mode_);
-}
-
-void RenderWidget::ScreenMetricsEmulator::Apply(
- bool top_controls_shrink_blink_size,
- float top_controls_height,
- gfx::Rect resizer_rect,
- bool is_fullscreen_granted,
- blink::WebDisplayMode display_mode) {
- applied_widget_rect_.set_size(gfx::Size(params_.viewSize));
- if (!applied_widget_rect_.width())
- applied_widget_rect_.set_width(original_size_.width());
- if (!applied_widget_rect_.height())
- applied_widget_rect_.set_height(original_size_.height());
-
- if (params_.fitToView && !original_size_.IsEmpty()) {
- int original_width = std::max(original_size_.width(), 1);
- int original_height = std::max(original_size_.height(), 1);
- float width_ratio =
- static_cast<float>(applied_widget_rect_.width()) / original_width;
- float height_ratio =
- static_cast<float>(applied_widget_rect_.height()) / original_height;
- float ratio = std::max(1.0f, std::max(width_ratio, height_ratio));
- scale_ = 1.f / ratio;
-
- // Center emulated view inside available view space.
- offset_.set_x(
- (original_size_.width() - scale_ * applied_widget_rect_.width()) / 2);
- offset_.set_y(
- (original_size_.height() - scale_ * applied_widget_rect_.height()) / 2);
- } else {
- scale_ = params_.scale;
- offset_.SetPoint(params_.offset.x, params_.offset.y);
- if (!params_.viewSize.width && !params_.viewSize.height && scale_) {
- applied_widget_rect_.set_size(gfx::ScaleToRoundedSize(
- original_size_, 1.f / scale_));
- }
- }
-
- if (params_.screenPosition == WebDeviceEmulationParams::Desktop) {
- applied_widget_rect_.set_origin(original_view_screen_rect_.origin());
- widget_->screen_info_.rect = original_screen_info_.rect;
- widget_->screen_info_.availableRect = original_screen_info_.availableRect;
- widget_->window_screen_rect_ = original_window_screen_rect_;
- } else {
- applied_widget_rect_.set_origin(params_.viewPosition);
- gfx::Rect screen_rect = applied_widget_rect_;
- if (!params_.screenSize.isEmpty()) {
- screen_rect =
- gfx::Rect(0, 0, params_.screenSize.width, params_.screenSize.height);
- }
- widget_->screen_info_.rect = screen_rect;
- widget_->screen_info_.availableRect = screen_rect;
- widget_->window_screen_rect_ = applied_widget_rect_;
- }
-
- float applied_device_scale_factor = params_.deviceScaleFactor ?
- params_.deviceScaleFactor : original_screen_info_.deviceScaleFactor;
- widget_->screen_info_.deviceScaleFactor = applied_device_scale_factor;
-
- // Pass three emulation parameters to the blink side:
- // - we keep the real device scale factor in compositor to produce sharp image
- // even when emulating different scale factor;
- // - in order to fit into view, WebView applies offset and scale to the
- // root layer.
- blink::WebDeviceEmulationParams modified_params = params_;
- modified_params.deviceScaleFactor = original_screen_info_.deviceScaleFactor;
- modified_params.offset = blink::WebFloatPoint(offset_.x(), offset_.y());
- modified_params.scale = scale_;
- widget_->SetScreenMetricsEmulationParameters(true, modified_params);
-
- widget_->SetDeviceScaleFactor(applied_device_scale_factor);
- widget_->view_screen_rect_ = applied_widget_rect_;
-
- gfx::Size physical_backing_size = gfx::ScaleToCeiledSize(
- original_size_, original_screen_info_.deviceScaleFactor);
- widget_->Resize(applied_widget_rect_.size(),
- physical_backing_size,
- top_controls_shrink_blink_size,
- top_controls_height,
- applied_widget_rect_.size(),
- resizer_rect,
- is_fullscreen_granted,
- display_mode,
- NO_RESIZE_ACK);
-}
-
-void RenderWidget::ScreenMetricsEmulator::OnResizeMessage(
- const ViewMsg_Resize_Params& params) {
- bool need_ack = params.new_size != original_size_ &&
- !params.new_size.IsEmpty() && !params.physical_backing_size.IsEmpty();
- original_size_ = params.new_size;
- original_physical_backing_size_ = params.physical_backing_size;
- original_screen_info_ = params.screen_info;
- original_visible_viewport_size_ = params.visible_viewport_size;
- Apply(params.top_controls_shrink_blink_size,
- params.top_controls_height,
- params.resizer_rect,
- params.is_fullscreen_granted,
- params.display_mode);
-
- if (need_ack) {
- widget_->set_next_paint_is_resize_ack();
- if (widget_->compositor_)
- widget_->compositor_->SetNeedsRedrawRect(gfx::Rect(widget_->size_));
- }
-}
-
-void RenderWidget::ScreenMetricsEmulator::OnUpdateScreenRectsMessage(
- const gfx::Rect& view_screen_rect,
- const gfx::Rect& window_screen_rect) {
- original_view_screen_rect_ = view_screen_rect;
- original_window_screen_rect_ = window_screen_rect;
- if (params_.screenPosition == WebDeviceEmulationParams::Desktop)
- Reapply();
-}
-
-void RenderWidget::ScreenMetricsEmulator::OnShowContextMenu(
- ContextMenuParams* params) {
- params->x *= scale_;
- params->x += offset_.x();
- params->y *= scale_;
- params->y += offset_.y();
-}
-
-gfx::Rect RenderWidget::ScreenMetricsEmulator::AdjustValidationMessageAnchor(
- const gfx::Rect& anchor) {
- gfx::Rect scaled = gfx::ScaleToEnclosedRect(anchor, scale_);
- scaled.set_x(scaled.x() + offset_.x());
- scaled.set_y(scaled.y() + offset_.y());
- return scaled;
-}
-
// RenderWidget ---------------------------------------------------------------
RenderWidget::RenderWidget(CompositorDependencies* compositor_deps,
@@ -446,6 +220,7 @@ RenderWidget::RenderWidget(CompositorDependencies* compositor_deps,
: routing_id_(MSG_ROUTING_NONE),
compositor_deps_(compositor_deps),
webwidget_(nullptr),
+ owner_delegate_(nullptr),
opener_id_(MSG_ROUTING_NONE),
top_controls_shrink_blink_size_(false),
top_controls_height_(0.f),
@@ -530,8 +305,9 @@ RenderWidget* RenderWidget::CreateForFrame(
// routing ID. https://crbug.com/545684
RenderViewImpl* view = RenderViewImpl::FromRoutingID(routing_id);
if (view) {
- view->AttachWebFrameWidget(RenderWidget::CreateWebFrameWidget(view, frame));
- return view;
+ view->AttachWebFrameWidget(
+ RenderWidget::CreateWebFrameWidget(view->GetWidget(), frame));
+ return view->GetWidget();
}
scoped_refptr<RenderWidget> widget(
new RenderWidget(compositor_deps, blink::WebPopupTypeNone, screen_info,
@@ -549,7 +325,7 @@ RenderWidget* RenderWidget::CreateForFrame(
}
// static
-blink::WebWidget* RenderWidget::CreateWebFrameWidget(
+blink::WebFrameWidget* RenderWidget::CreateWebFrameWidget(
RenderWidget* render_widget,
blink::WebLocalFrame* frame) {
if (!frame->parent()) {
@@ -648,7 +424,7 @@ void RenderWidget::WasSwappedOut() {
}
void RenderWidget::SetPopupOriginAdjustmentsForEmulation(
- ScreenMetricsEmulator* emulator) {
+ RenderWidgetScreenMetricsEmulator* emulator) {
popup_origin_scale_for_emulation_ = emulator->scale();
popup_view_origin_for_emulation_ = emulator->applied_widget_rect().origin();
popup_screen_origin_for_emulation_ = gfx::Point(
@@ -664,16 +440,10 @@ gfx::Rect RenderWidget::AdjustValidationMessageAnchor(const gfx::Rect& anchor) {
return anchor;
}
-void RenderWidget::SetScreenMetricsEmulationParameters(
- bool enabled,
- const blink::WebDeviceEmulationParams& params) {
- // This is only supported in RenderView.
- NOTREACHED();
-}
-
#if defined(OS_MACOSX) || defined(OS_ANDROID)
void RenderWidget::SetExternalPopupOriginAdjustmentsForEmulation(
- ExternalPopupMenu* popup, ScreenMetricsEmulator* emulator) {
+ ExternalPopupMenu* popup,
+ RenderWidgetScreenMetricsEmulator* emulator) {
popup->SetOriginScaleAndOffsetForEmulation(
emulator->scale(), emulator->offset());
}
@@ -711,8 +481,12 @@ bool RenderWidget::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(ViewMsg_Move_ACK, OnRequestMoveAck)
IPC_MESSAGE_HANDLER(ViewMsg_UpdateScreenRects, OnUpdateScreenRects)
IPC_MESSAGE_HANDLER(ViewMsg_SetSurfaceIdNamespace, OnSetSurfaceIdNamespace)
+ IPC_MESSAGE_HANDLER(ViewMsg_WaitForNextFrameForTests,
+ OnWaitNextFrameForTests)
#if defined(OS_ANDROID)
IPC_MESSAGE_HANDLER(InputMsg_ImeEventAck, OnImeEventAck)
+ IPC_MESSAGE_HANDLER(InputMsg_RequestTextInputStateUpdate,
+ OnRequestTextInputStateUpdate)
IPC_MESSAGE_HANDLER(ViewMsg_ShowImeIfNeeded, OnShowImeIfNeeded)
#endif
IPC_MESSAGE_HANDLER(ViewMsg_HandleCompositorProto, OnHandleCompositorProto)
@@ -738,97 +512,22 @@ bool RenderWidget::Send(IPC::Message* message) {
return RenderThread::Get()->Send(message);
}
-void RenderWidget::Resize(const gfx::Size& new_size,
- const gfx::Size& physical_backing_size,
- bool top_controls_shrink_blink_size,
- float top_controls_height,
- const gfx::Size& visible_viewport_size,
- const gfx::Rect& resizer_rect,
- bool is_fullscreen_granted,
- blink::WebDisplayMode display_mode,
- const ResizeAck resize_ack) {
- if (resizing_mode_selector_->NeverUsesSynchronousResize()) {
- // A resize ack shouldn't be requested if we have not ACK'd the previous
- // one.
- DCHECK(resize_ack != SEND_RESIZE_ACK || !next_paint_is_resize_ack());
- DCHECK(resize_ack == SEND_RESIZE_ACK || resize_ack == NO_RESIZE_ACK);
- }
-
- // Ignore this during shutdown.
- if (!webwidget_)
- return;
-
- if (compositor_)
- compositor_->setViewportSize(physical_backing_size);
-
- bool resized = size_ != new_size ||
- physical_backing_size_ != physical_backing_size;
-
- size_ = new_size;
- physical_backing_size_ = physical_backing_size;
-
- top_controls_shrink_blink_size_ = top_controls_shrink_blink_size;
- top_controls_height_ = top_controls_height;
- visible_viewport_size_ = visible_viewport_size;
- resizer_rect_ = resizer_rect;
-
- // NOTE: We may have entered fullscreen mode without changing our size.
- bool fullscreen_change = is_fullscreen_granted_ != is_fullscreen_granted;
- is_fullscreen_granted_ = is_fullscreen_granted;
- display_mode_ = display_mode;
-
- webwidget_->setTopControlsHeight(top_controls_height,
- top_controls_shrink_blink_size_);
-
- if (resized) {
- gfx::Size new_widget_size =
- IsUseZoomForDSFEnabled() ? physical_backing_size_ : size_;
- // When resizing, we want to wait to paint before ACK'ing the resize. This
- // ensures that we only resize as fast as we can paint. We only need to
- // send an ACK if we are resized to a non-empty rect.
- webwidget_->resize(new_widget_size);
- }
- WebSize visual_viewport_size;
-
- if (IsUseZoomForDSFEnabled()) {
- visual_viewport_size =
- gfx::ScaleToCeiledSize(visible_viewport_size, device_scale_factor_);
- } else {
- visual_viewport_size = visible_viewport_size_;
- }
-
- webwidget()->resizeVisualViewport(visual_viewport_size);
-
- if (new_size.IsEmpty() || physical_backing_size.IsEmpty()) {
- // In this case there is no paint/composite and therefore no
- // ViewHostMsg_UpdateRect to send the resize ack with. We'd need to send the
- // ack through a fake ViewHostMsg_UpdateRect or a different message.
- DCHECK_EQ(resize_ack, NO_RESIZE_ACK);
- }
-
- // Send the Resize_ACK flag once we paint again if requested.
- if (resize_ack == SEND_RESIZE_ACK)
- set_next_paint_is_resize_ack();
-
- if (fullscreen_change)
- DidToggleFullscreen();
-
- // If a resize ack is requested and it isn't set-up, then no more resizes will
- // come in and in general things will go wrong.
- DCHECK(resize_ack != SEND_RESIZE_ACK || next_paint_is_resize_ack());
-}
-
void RenderWidget::SetWindowRectSynchronously(
const gfx::Rect& new_window_rect) {
- Resize(new_window_rect.size(),
- gfx::ScaleToCeiledSize(new_window_rect.size(), device_scale_factor_),
- top_controls_shrink_blink_size_,
- top_controls_height_,
- new_window_rect.size(),
- gfx::Rect(),
- is_fullscreen_granted_,
- display_mode_,
- NO_RESIZE_ACK);
+ ResizeParams params;
+ params.screen_info = screen_info_;
+ params.new_size = new_window_rect.size();
+ params.physical_backing_size =
+ gfx::ScaleToCeiledSize(new_window_rect.size(), device_scale_factor_);
+ params.top_controls_shrink_blink_size = top_controls_shrink_blink_size_;
+ params.top_controls_height = top_controls_height_;
+ params.visible_viewport_size = new_window_rect.size();
+ params.resizer_rect = gfx::Rect();
+ params.is_fullscreen_granted = is_fullscreen_granted_;
+ params.display_mode = display_mode_;
+ params.needs_resize_ack = false;
+ Resize(params);
+
view_screen_rect_ = new_window_rect;
window_screen_rect_ = new_window_rect;
if (!did_show_)
@@ -869,40 +568,38 @@ void RenderWidget::OnClose() {
Release();
}
-void RenderWidget::OnResize(const ViewMsg_Resize_Params& params) {
+void RenderWidget::OnResize(const ResizeParams& params) {
if (resizing_mode_selector_->ShouldAbortOnResize(this, params))
return;
if (screen_metrics_emulator_) {
- screen_metrics_emulator_->OnResizeMessage(params);
+ screen_metrics_emulator_->OnResize(params);
return;
}
- bool orientation_changed =
- screen_info_.orientationAngle != params.screen_info.orientationAngle;
-
- screen_info_ = params.screen_info;
- SetDeviceScaleFactor(screen_info_.deviceScaleFactor);
- Resize(params.new_size,
- params.physical_backing_size,
- params.top_controls_shrink_blink_size,
- params.top_controls_height,
- params.visible_viewport_size,
- params.resizer_rect,
- params.is_fullscreen_granted,
- params.display_mode,
- params.needs_resize_ack ? SEND_RESIZE_ACK : NO_RESIZE_ACK);
-
- if (orientation_changed)
- OnOrientationChange();
+ Resize(params);
}
void RenderWidget::OnEnableDeviceEmulation(
const blink::WebDeviceEmulationParams& params) {
- if (!screen_metrics_emulator_)
- screen_metrics_emulator_.reset(new ScreenMetricsEmulator(this, params));
- else
+ if (!screen_metrics_emulator_) {
+ ResizeParams resize_params;
+ resize_params.screen_info = screen_info_;
+ resize_params.new_size = size_;
+ resize_params.physical_backing_size = physical_backing_size_;
+ resize_params.visible_viewport_size = visible_viewport_size_;
+ resize_params.top_controls_shrink_blink_size =
+ top_controls_shrink_blink_size_;
+ resize_params.top_controls_height = top_controls_height_;
+ resize_params.resizer_rect = resizer_rect_;
+ resize_params.is_fullscreen_granted = is_fullscreen_granted_;
+ resize_params.display_mode = display_mode_;
+ screen_metrics_emulator_.reset(new RenderWidgetScreenMetricsEmulator(
+ this, params, resize_params, view_screen_rect_, window_screen_rect_));
+ screen_metrics_emulator_->Apply();
+ } else {
screen_metrics_emulator_->ChangeEmulationParams(params);
+ }
}
void RenderWidget::OnDisableDeviceEmulation() {
@@ -963,6 +660,47 @@ GURL RenderWidget::GetURLForGraphicsContext3D() {
return GURL();
}
+void RenderWidget::OnHandleInputEvent(const blink::WebInputEvent* input_event,
+ const ui::LatencyInfo& latency_info,
+ InputEventDispatchType dispatch_type) {
+ if (!input_event)
+ return;
+ input_handler_->HandleInputEvent(*input_event, latency_info, dispatch_type);
+}
+
+void RenderWidget::OnCursorVisibilityChange(bool is_visible) {
+ if (webwidget_)
+ webwidget_->setCursorVisibilityState(is_visible);
+}
+
+void RenderWidget::OnMouseCaptureLost() {
+ if (webwidget_)
+ webwidget_->mouseCaptureLost();
+}
+
+void RenderWidget::OnSetFocus(bool enable) {
+ if (webwidget_)
+ webwidget_->setFocus(enable);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// RenderWidgetCompositorDelegate
+
+void RenderWidget::ApplyViewportDeltas(
+ const gfx::Vector2dF& inner_delta,
+ const gfx::Vector2dF& outer_delta,
+ const gfx::Vector2dF& elastic_overscroll_delta,
+ float page_scale,
+ float top_controls_delta) {
+ webwidget_->applyViewportDeltas(inner_delta, outer_delta,
+ elastic_overscroll_delta, page_scale,
+ top_controls_delta);
+}
+
+void RenderWidget::BeginMainFrame(double frame_time_sec) {
+ webwidget_->beginFrame(frame_time_sec);
+}
+
scoped_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface(bool fallback) {
DCHECK(webwidget_);
// For widgets that are never visible, we don't start the compositor, so we
@@ -976,14 +714,15 @@ scoped_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface(bool fallback) {
use_software = true;
#if defined(MOJO_SHELL_CLIENT)
- if (MojoShellConnection::Get() && !use_software) {
+ if (MojoShellConnection::Get() && !use_software &&
+ command_line.HasSwitch(switches::kUseMusInRenderer)) {
RenderWidgetMusConnection* connection =
RenderWidgetMusConnection::GetOrCreate(routing_id());
return connection->CreateOutputSurface();
}
#endif
- scoped_refptr<GpuChannelHost> gpu_channel_host;
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel_host;
if (!use_software) {
CauseForGpuLaunch cause =
CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE;
@@ -999,9 +738,23 @@ scoped_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface(bool fallback) {
use_software = true;
}
+#if defined(ENABLE_VULKAN)
+ scoped_refptr<cc::VulkanContextProvider> vulkan_context_provider;
+#endif
scoped_refptr<ContextProviderCommandBuffer> context_provider;
scoped_refptr<ContextProviderCommandBuffer> worker_context_provider;
if (!use_software) {
+#if defined(ENABLE_VULKAN)
+ vulkan_context_provider = cc::VulkanInProcessContextProvider::Create();
+ if (vulkan_context_provider) {
+ uint32_t output_surface_id = next_output_surface_id_++;
+ return scoped_ptr<cc::OutputSurface>(new DelegatedCompositorOutputSurface(
+ routing_id(), output_surface_id, context_provider,
+ worker_context_provider, vulkan_context_provider,
+ frame_swap_message_queue_));
+ }
+#endif
+
context_provider = ContextProviderCommandBuffer::Create(
CreateGraphicsContext3D(gpu_channel_host.get()),
RENDER_COMPOSITOR_CONTEXT);
@@ -1016,14 +769,16 @@ scoped_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface(bool fallback) {
#if defined(OS_ANDROID)
if (SynchronousCompositorFactory* factory =
SynchronousCompositorFactory::GetInstance()) {
+ uint32_t output_surface_id = next_output_surface_id_++;
return factory->CreateOutputSurface(
- routing_id(), frame_swap_message_queue_, context_provider,
- worker_context_provider);
+ routing_id(), output_surface_id, frame_swap_message_queue_,
+ context_provider, worker_context_provider);
} else if (RenderThreadImpl::current()->sync_compositor_message_filter()) {
+ uint32_t output_surface_id = next_output_surface_id_++;
return make_scoped_ptr(new SynchronousCompositorOutputSurface(
context_provider, worker_context_provider, routing_id(),
- content::RenderThreadImpl::current()
- ->sync_compositor_message_filter(),
+ output_surface_id, content::RenderThreadImpl::current()
+ ->sync_compositor_message_filter(),
frame_swap_message_queue_));
}
#endif
@@ -1038,7 +793,11 @@ scoped_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface(bool fallback) {
DCHECK(compositor_deps_->GetCompositorImplThreadTaskRunner());
return make_scoped_ptr(new DelegatedCompositorOutputSurface(
routing_id(), output_surface_id, context_provider,
- worker_context_provider, frame_swap_message_queue_));
+ worker_context_provider,
+#if defined(ENABLE_VULKAN)
+ vulkan_context_provider,
+#endif
+ frame_swap_message_queue_));
}
if (!context_provider.get()) {
@@ -1047,6 +806,9 @@ scoped_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface(bool fallback) {
return make_scoped_ptr(new CompositorOutputSurface(
routing_id(), output_surface_id, nullptr, nullptr,
+#if defined(ENABLE_VULKAN)
+ nullptr,
+#endif
std::move(software_device), frame_swap_message_queue_, true));
}
@@ -1055,16 +817,72 @@ scoped_ptr<cc::OutputSurface> RenderWidget::CreateOutputSurface(bool fallback) {
worker_context_provider, frame_swap_message_queue_, cc::RGBA_8888));
}
+scoped_ptr<cc::BeginFrameSource>
+RenderWidget::CreateExternalBeginFrameSource() {
+ return compositor_deps_->CreateExternalBeginFrameSource(routing_id_);
+}
+
+void RenderWidget::DidCommitAndDrawCompositorFrame() {
+ // NOTE: Tests may break if this event is renamed or moved. See
+ // tab_capture_performancetest.cc.
+ TRACE_EVENT0("gpu", "RenderWidget::DidCommitAndDrawCompositorFrame");
+ // Notify subclasses that we initiated the paint operation.
+ DidInitiatePaint();
+}
+
+void RenderWidget::DidCommitCompositorFrame() {
+ FOR_EACH_OBSERVER(RenderFrameImpl, render_frames_,
+ DidCommitCompositorFrame());
+ FOR_EACH_OBSERVER(RenderFrameProxy, render_frame_proxies_,
+ DidCommitCompositorFrame());
+#if defined(VIDEO_HOLE)
+ FOR_EACH_OBSERVER(RenderFrameImpl, video_hole_frames_,
+ DidCommitCompositorFrame());
+#endif // defined(VIDEO_HOLE)
+ input_handler_->FlushPendingInputEventAck();
+}
+
+void RenderWidget::DidCompletePageScaleAnimation() {}
+
+void RenderWidget::DidCompleteSwapBuffers() {
+ TRACE_EVENT0("renderer", "RenderWidget::DidCompleteSwapBuffers");
+
+ // Notify subclasses threaded composited rendering was flushed to the screen.
+ DidFlushPaint();
+
+ if (!next_paint_flags_ && !need_update_rect_for_auto_resize_) {
+ return;
+ }
+
+ ViewHostMsg_UpdateRect_Params params;
+ params.view_size = size_;
+ params.flags = next_paint_flags_;
+
+ Send(new ViewHostMsg_UpdateRect(routing_id_, params));
+ next_paint_flags_ = 0;
+ need_update_rect_for_auto_resize_ = false;
+}
+
+bool RenderWidget::ForOOPIF() const {
+ // TODO(simonhong): Remove this when we enable BeginFrame scheduling for
+ // OOPIF(crbug.com/471411).
+ return for_oopif_;
+}
+
+void RenderWidget::ForwardCompositorProto(const std::vector<uint8_t>& proto) {
+ Send(new ViewHostMsg_ForwardCompositorProto(routing_id_, proto));
+}
+
+bool RenderWidget::IsClosing() const {
+ return host_closing_;
+}
+
void RenderWidget::OnSwapBuffersAborted() {
TRACE_EVENT0("renderer", "RenderWidget::OnSwapBuffersAborted");
// Schedule another frame so the compositor learns about it.
ScheduleComposite();
}
-void RenderWidget::OnSwapBuffersPosted() {
- TRACE_EVENT0("renderer", "RenderWidget::OnSwapBuffersPosted");
-}
-
void RenderWidget::OnSwapBuffersComplete() {
TRACE_EVENT0("renderer", "RenderWidget::OnSwapBuffersComplete");
@@ -1072,34 +890,75 @@ void RenderWidget::OnSwapBuffersComplete() {
DidFlushPaint();
}
-void RenderWidget::OnHandleInputEvent(const blink::WebInputEvent* input_event,
- const ui::LatencyInfo& latency_info) {
- if (!input_event)
- return;
- input_handler_->HandleInputEvent(*input_event, latency_info);
+void RenderWidget::OnSwapBuffersPosted() {
+ TRACE_EVENT0("renderer", "RenderWidget::OnSwapBuffersPosted");
}
-void RenderWidget::OnCursorVisibilityChange(bool is_visible) {
- if (webwidget_)
- webwidget_->setCursorVisibilityState(is_visible);
+void RenderWidget::RecordFrameTimingEvents(
+ scoped_ptr<cc::FrameTimingTracker::CompositeTimingSet> composite_events,
+ scoped_ptr<cc::FrameTimingTracker::MainFrameTimingSet> main_frame_events) {
+ for (const auto& composite_event : *composite_events) {
+ int64_t frameId = composite_event.first;
+ const std::vector<cc::FrameTimingTracker::CompositeTimingEvent>& events =
+ composite_event.second;
+ std::vector<blink::WebFrameTimingEvent> webEvents;
+ for (size_t i = 0; i < events.size(); ++i) {
+ webEvents.push_back(blink::WebFrameTimingEvent(
+ events[i].frame_id,
+ (events[i].timestamp - base::TimeTicks()).InSecondsF()));
+ }
+ webwidget_->recordFrameTimingEvent(blink::WebWidget::CompositeEvent,
+ frameId, webEvents);
+ }
+ for (const auto& main_frame_event : *main_frame_events) {
+ int64_t frameId = main_frame_event.first;
+ const std::vector<cc::FrameTimingTracker::MainFrameTimingEvent>& events =
+ main_frame_event.second;
+ std::vector<blink::WebFrameTimingEvent> webEvents;
+ for (size_t i = 0; i < events.size(); ++i) {
+ webEvents.push_back(blink::WebFrameTimingEvent(
+ events[i].frame_id,
+ (events[i].timestamp - base::TimeTicks()).InSecondsF(),
+ (events[i].end_time - base::TimeTicks()).InSecondsF()));
+ }
+ webwidget_->recordFrameTimingEvent(blink::WebWidget::RenderEvent, frameId,
+ webEvents);
+ }
}
-void RenderWidget::OnMouseCaptureLost() {
- if (webwidget_)
- webwidget_->mouseCaptureLost();
+void RenderWidget::RequestScheduleAnimation() {
+ scheduleAnimation();
}
-void RenderWidget::OnSetFocus(bool enable) {
- if (webwidget_)
- webwidget_->setFocus(enable);
+void RenderWidget::UpdateVisualState() {
+ webwidget_->updateAllLifecyclePhases();
+}
+
+void RenderWidget::WillBeginCompositorFrame() {
+ TRACE_EVENT0("gpu", "RenderWidget::willBeginCompositorFrame");
+
+ // The UpdateTextInputState can result in further layout and possibly
+ // enable GPU acceleration so they need to be called before any painting
+ // is done.
+ UpdateTextInputState(ShowIme::HIDE_IME, ChangeSource::FROM_NON_IME);
+ UpdateSelectionBounds();
+
+ FOR_EACH_OBSERVER(RenderFrameProxy, render_frame_proxies_,
+ WillBeginCompositorFrame());
}
///////////////////////////////////////////////////////////////////////////////
// RenderWidgetInputHandlerDelegate
-void RenderWidget::FocusChangeComplete() {}
+void RenderWidget::FocusChangeComplete() {
+ if (owner_delegate_)
+ owner_delegate_->RenderWidgetFocusChangeComplete();
+}
bool RenderWidget::HasTouchEventHandlersAt(const gfx::Point& point) const {
+ if (owner_delegate_)
+ return owner_delegate_->DoesRenderWidgetHaveTouchEventHandlersAt(point);
+
return true;
}
@@ -1124,7 +983,31 @@ void RenderWidget::ObserveWheelEventAndResult(
}
}
-void RenderWidget::OnDidHandleKeyEvent() {}
+void RenderWidget::ObserveGestureEventAndResult(
+ const blink::WebGestureEvent& gesture_event,
+ const gfx::Vector2dF& unused_delta,
+ bool event_processed) {
+ if (!compositor_deps_->IsElasticOverscrollEnabled())
+ return;
+
+ cc::InputHandlerScrollResult scroll_result;
+ scroll_result.did_scroll = event_processed;
+ scroll_result.did_overscroll_root = !unused_delta.IsZero();
+ scroll_result.unused_scroll_delta = unused_delta;
+
+ RenderThreadImpl* render_thread = RenderThreadImpl::current();
+ InputHandlerManager* input_handler_manager =
+ render_thread ? render_thread->input_handler_manager() : NULL;
+ if (input_handler_manager) {
+ input_handler_manager->ObserveGestureEventAndResultOnMainThread(
+ routing_id_, gesture_event, scroll_result);
+ }
+}
+
+void RenderWidget::OnDidHandleKeyEvent() {
+ if (owner_delegate_)
+ owner_delegate_->RenderWidgetDidHandleKeyEvent();
+}
void RenderWidget::OnDidOverscroll(const DidOverscrollParams& params) {
Send(new InputHostMsg_DidOverscroll(routing_id_, params));
@@ -1134,6 +1017,17 @@ void RenderWidget::OnInputEventAck(scoped_ptr<InputEventAck> input_event_ack) {
Send(new InputHostMsg_HandleInputEvent_ACK(routing_id_, *input_event_ack));
}
+void RenderWidget::NotifyInputEventHandled(
+ blink::WebInputEvent::Type handled_type) {
+ RenderThreadImpl* render_thread = RenderThreadImpl::current();
+ InputHandlerManager* input_handler_manager =
+ render_thread ? render_thread->input_handler_manager() : NULL;
+ if (input_handler_manager) {
+ input_handler_manager->NotifyInputEventHandledOnMainThread(routing_id_,
+ handled_type);
+ }
+}
+
void RenderWidget::SetInputHandler(RenderWidgetInputHandler* input_handler) {
// Nothing to do here. RenderWidget created the |input_handler| and will take
// ownership of it. We just verify here that we don't already have an input
@@ -1167,6 +1061,7 @@ void RenderWidget::UpdateTextInputState(ShowIme show_ime,
// Only sends text input params if they are changed or if the ime should be
// shown.
if (show_ime == ShowIme::IF_NEEDED ||
+ (IsUsingImeThread() && change_source == ChangeSource::FROM_IME) ||
(text_input_type_ != new_type || text_input_mode_ != new_mode ||
text_input_info_ != new_info ||
can_compose_inline_ != new_can_compose_inline)
@@ -1206,14 +1101,128 @@ void RenderWidget::UpdateTextInputState(ShowIme show_ime,
}
bool RenderWidget::WillHandleGestureEvent(const blink::WebGestureEvent& event) {
+ if (owner_delegate_)
+ return owner_delegate_->RenderWidgetWillHandleGestureEvent(event);
+
return false;
}
bool RenderWidget::WillHandleMouseEvent(const blink::WebMouseEvent& event) {
+ if (owner_delegate_)
+ return owner_delegate_->RenderWidgetWillHandleMouseEvent(event);
+
return false;
}
///////////////////////////////////////////////////////////////////////////////
+// RenderWidgetScreenMetricsDelegate
+
+void RenderWidget::Redraw() {
+ set_next_paint_is_resize_ack();
+ if (compositor_)
+ compositor_->SetNeedsRedrawRect(gfx::Rect(size_));
+}
+
+void RenderWidget::Resize(const ResizeParams& params) {
+ bool orientation_changed =
+ screen_info_.orientationAngle != params.screen_info.orientationAngle ||
+ screen_info_.orientationType != params.screen_info.orientationType;
+
+ screen_info_ = params.screen_info;
+ SetDeviceScaleFactor(screen_info_.deviceScaleFactor);
+
+ if (resizing_mode_selector_->NeverUsesSynchronousResize()) {
+ // A resize ack shouldn't be requested if we have not ACK'd the previous
+ // one.
+ DCHECK(!params.needs_resize_ack || !next_paint_is_resize_ack());
+ }
+
+ // Ignore this during shutdown.
+ if (!webwidget_)
+ return;
+
+ if (compositor_)
+ compositor_->setViewportSize(params.physical_backing_size);
+
+ bool resized = size_ != params.new_size ||
+ physical_backing_size_ != params.physical_backing_size;
+
+ size_ = params.new_size;
+ physical_backing_size_ = params.physical_backing_size;
+
+ top_controls_shrink_blink_size_ = params.top_controls_shrink_blink_size;
+ top_controls_height_ = params.top_controls_height;
+ visible_viewport_size_ = params.visible_viewport_size;
+ resizer_rect_ = params.resizer_rect;
+
+ // NOTE: We may have entered fullscreen mode without changing our size.
+ bool fullscreen_change =
+ is_fullscreen_granted_ != params.is_fullscreen_granted;
+ is_fullscreen_granted_ = params.is_fullscreen_granted;
+ display_mode_ = params.display_mode;
+
+ webwidget_->setTopControlsHeight(params.top_controls_height,
+ top_controls_shrink_blink_size_);
+
+ if (resized) {
+ gfx::Size new_widget_size = size_;
+ if (IsUseZoomForDSFEnabled()) {
+ new_widget_size = gfx::ScaleToCeiledSize(new_widget_size,
+ GetOriginalDeviceScaleFactor());
+ }
+ // When resizing, we want to wait to paint before ACK'ing the resize. This
+ // ensures that we only resize as fast as we can paint. We only need to
+ // send an ACK if we are resized to a non-empty rect.
+ webwidget_->resize(new_widget_size);
+ }
+ WebSize visual_viewport_size;
+
+ if (IsUseZoomForDSFEnabled()) {
+ visual_viewport_size = gfx::ScaleToCeiledSize(
+ params.visible_viewport_size,
+ GetOriginalDeviceScaleFactor());
+ } else {
+ visual_viewport_size = visible_viewport_size_;
+ }
+
+ webwidget()->resizeVisualViewport(visual_viewport_size);
+
+ if (params.new_size.IsEmpty() || params.physical_backing_size.IsEmpty()) {
+ // In this case there is no paint/composite and therefore no
+ // ViewHostMsg_UpdateRect to send the resize ack with. We'd need to send the
+ // ack through a fake ViewHostMsg_UpdateRect or a different message.
+ DCHECK(!params.needs_resize_ack);
+ }
+
+ // Send the Resize_ACK flag once we paint again if requested.
+ if (params.needs_resize_ack)
+ set_next_paint_is_resize_ack();
+
+ if (fullscreen_change)
+ DidToggleFullscreen();
+
+ if (orientation_changed)
+ OnOrientationChange();
+
+ // If a resize ack is requested and it isn't set-up, then no more resizes will
+ // come in and in general things will go wrong.
+ DCHECK(!params.needs_resize_ack || next_paint_is_resize_ack());
+}
+
+void RenderWidget::SetScreenMetricsEmulationParameters(
+ bool enabled,
+ const blink::WebDeviceEmulationParams& params) {
+ // This is only supported in RenderView.
+ NOTREACHED();
+}
+
+void RenderWidget::SetScreenRects(const gfx::Rect& view_screen_rect,
+ const gfx::Rect& window_screen_rect) {
+ view_screen_rect_ = view_screen_rect;
+ window_screen_rect_ = window_screen_rect;
+}
+
+///////////////////////////////////////////////////////////////////////////////
// WebWidgetClient
void RenderWidget::didAutoResize(const WebSize& new_size) {
@@ -1248,7 +1257,8 @@ void RenderWidget::AutoResizeCompositor() {
void RenderWidget::initializeLayerTreeView() {
DCHECK(!host_closing_);
- compositor_ = RenderWidgetCompositor::Create(this, compositor_deps_);
+ compositor_ = RenderWidgetCompositor::Create(this, device_scale_factor_,
+ compositor_deps_);
compositor_->setViewportSize(physical_backing_size_);
OnDeviceScaleFactorChanged();
// For background pages and certain tests, we don't want to trigger
@@ -1286,58 +1296,6 @@ void RenderWidget::didMeaningfulLayout(blink::WebMeaningfulLayout layout_type) {
DidMeaningfulLayout(layout_type));
}
-void RenderWidget::WillBeginCompositorFrame() {
- TRACE_EVENT0("gpu", "RenderWidget::willBeginCompositorFrame");
-
- // The UpdateTextInputState can result in further layout and possibly
- // enable GPU acceleration so they need to be called before any painting
- // is done.
- UpdateTextInputState(ShowIme::HIDE_IME, ChangeSource::FROM_NON_IME);
- UpdateSelectionBounds();
-}
-
-void RenderWidget::DidCommitCompositorFrame() {
- FOR_EACH_OBSERVER(RenderFrameImpl, render_frames_,
- DidCommitCompositorFrame());
- FOR_EACH_OBSERVER(RenderFrameProxy, render_frame_proxies_,
- DidCommitCompositorFrame());
-#if defined(VIDEO_HOLE)
- FOR_EACH_OBSERVER(RenderFrameImpl, video_hole_frames_,
- DidCommitCompositorFrame());
-#endif // defined(VIDEO_HOLE)
- input_handler_->FlushPendingInputEventAck();
-}
-
-void RenderWidget::DidCommitAndDrawCompositorFrame() {
- // NOTE: Tests may break if this event is renamed or moved. See
- // tab_capture_performancetest.cc.
- TRACE_EVENT0("gpu", "RenderWidget::DidCommitAndDrawCompositorFrame");
- // Notify subclasses that we initiated the paint operation.
- DidInitiatePaint();
-}
-
-void RenderWidget::DidCompleteSwapBuffers() {
- TRACE_EVENT0("renderer", "RenderWidget::DidCompleteSwapBuffers");
-
- // Notify subclasses threaded composited rendering was flushed to the screen.
- DidFlushPaint();
-
- if (!next_paint_flags_ &&
- !need_update_rect_for_auto_resize_ &&
- !plugin_window_moves_.size()) {
- return;
- }
-
- ViewHostMsg_UpdateRect_Params params;
- params.view_size = size_;
- params.plugin_window_moves.swap(plugin_window_moves_);
- params.flags = next_paint_flags_;
-
- Send(new ViewHostMsg_UpdateRect(routing_id_, params));
- next_paint_flags_ = 0;
- need_update_rect_for_auto_resize_ = false;
-}
-
void RenderWidget::ScheduleComposite() {
if (compositor_ &&
compositor_deps_->GetCompositorImplThreadTaskRunner().get()) {
@@ -1553,6 +1511,7 @@ WebRect RenderWidget::windowResizerRect() {
void RenderWidget::OnImeSetComposition(
const base::string16& text,
const std::vector<WebCompositionUnderline>& underlines,
+ const gfx::Range& replacement_range,
int selection_start, int selection_end) {
if (!ShouldHandleImeEvent())
return;
@@ -1588,9 +1547,8 @@ void RenderWidget::OnImeConfirmComposition(const base::string16& text,
void RenderWidget::OnDeviceScaleFactorChanged() {
if (!compositor_)
return;
-
if (IsUseZoomForDSFEnabled())
- compositor_->SetPaintedDeviceScaleFactor(device_scale_factor_);
+ compositor_->SetPaintedDeviceScaleFactor(GetOriginalDeviceScaleFactor());
else
compositor_->setDeviceScaleFactor(device_scale_factor_);
}
@@ -1627,15 +1585,23 @@ void RenderWidget::OnSetTextDirection(WebTextDirection direction) {
void RenderWidget::OnUpdateScreenRects(const gfx::Rect& view_screen_rect,
const gfx::Rect& window_screen_rect) {
if (screen_metrics_emulator_) {
- screen_metrics_emulator_->OnUpdateScreenRectsMessage(
- view_screen_rect, window_screen_rect);
+ screen_metrics_emulator_->OnUpdateScreenRects(view_screen_rect,
+ window_screen_rect);
} else {
- view_screen_rect_ = view_screen_rect;
- window_screen_rect_ = window_screen_rect;
+ SetScreenRects(view_screen_rect, window_screen_rect);
}
Send(new ViewHostMsg_UpdateScreenRects_ACK(routing_id()));
}
+void RenderWidget::OnUpdateWindowScreenRect(
+ const gfx::Rect& window_screen_rect) {
+ if (screen_metrics_emulator_) {
+ screen_metrics_emulator_->OnUpdateWindowScreenRect(window_screen_rect);
+ } else {
+ window_screen_rect_ = window_screen_rect;
+ }
+}
+
void RenderWidget::OnSetSurfaceIdNamespace(uint32_t surface_id_namespace) {
if (compositor_)
compositor_->SetSurfaceIdNamespace(surface_id_namespace);
@@ -1657,10 +1623,6 @@ ui::TextInputType RenderWidget::GetTextInputType() {
}
void RenderWidget::UpdateCompositionInfo(bool should_update_range) {
-#if defined(OS_ANDROID)
-// TODO(yukawa): Start sending character bounds when the browser side
-// implementation becomes ready (crbug.com/424866).
-#else
TRACE_EVENT0("renderer", "RenderWidget::UpdateCompositionInfo");
gfx::Range range = gfx::Range();
if (should_update_range) {
@@ -1677,12 +1639,11 @@ void RenderWidget::UpdateCompositionInfo(bool should_update_range) {
composition_range_ = range;
Send(new InputHostMsg_ImeCompositionRangeChanged(
routing_id(), composition_range_, composition_character_bounds_));
-#endif
}
void RenderWidget::convertViewportToWindow(blink::WebRect* rect) {
if (IsUseZoomForDSFEnabled()) {
- float reverse = 1 / device_scale_factor_;
+ float reverse = 1 / GetOriginalDeviceScaleFactor();
// TODO(oshima): We may need to allow pixel precision here as the the
// anchor element can be placed at half pixel.
gfx::Rect window_rect =
@@ -1694,6 +1655,15 @@ void RenderWidget::convertViewportToWindow(blink::WebRect* rect) {
}
}
+void RenderWidget::convertWindowToViewport(blink::WebFloatRect* rect) {
+ if (IsUseZoomForDSFEnabled()) {
+ rect->x *= GetOriginalDeviceScaleFactor();
+ rect->y *= GetOriginalDeviceScaleFactor();
+ rect->width *= GetOriginalDeviceScaleFactor();
+ rect->height *= GetOriginalDeviceScaleFactor();
+ }
+}
+
void RenderWidget::OnShowImeIfNeeded() {
#if defined(OS_ANDROID) || defined(USE_AURA)
UpdateTextInputState(ShowIme::IF_NEEDED, ChangeSource::FROM_NON_IME);
@@ -1715,12 +1685,20 @@ void RenderWidget::OnImeEventAck() {
DCHECK_GE(text_input_info_history_.size(), 1u);
text_input_info_history_.pop_front();
}
+
+void RenderWidget::OnRequestTextInputStateUpdate() {
+ DCHECK(!ime_event_guard_);
+ UpdateSelectionBounds();
+ UpdateTextInputState(ShowIme::HIDE_IME, ChangeSource::FROM_IME);
+}
#endif
bool RenderWidget::ShouldHandleImeEvent() {
#if defined(OS_ANDROID)
if (!webwidget_)
return false;
+ if (IsUsingImeThread())
+ return true;
// We cannot handle IME events if there is any chance that the event we are
// receiving here from the browser is based on the state that is different
@@ -1755,21 +1733,24 @@ bool RenderWidget::SetDeviceColorProfile(
return false;
device_color_profile_ = color_profile;
+
+ if (owner_delegate_)
+ owner_delegate_->RenderWidgetDidSetColorProfile(color_profile);
+
return true;
}
-void RenderWidget::ResetDeviceColorProfileForTesting() {
- if (!device_color_profile_.empty())
- device_color_profile_.clear();
- device_color_profile_.push_back('0');
+void RenderWidget::OnOrientationChange() {
}
-void RenderWidget::OnOrientationChange() {
+void RenderWidget::DidInitiatePaint() {
+ if (owner_delegate_)
+ owner_delegate_->RenderWidgetDidCommitAndDrawCompositorFrame();
}
-gfx::Vector2d RenderWidget::GetScrollOffset() {
- // Bare RenderWidgets don't support scroll offset.
- return gfx::Vector2d();
+void RenderWidget::DidFlushPaint() {
+ if (owner_delegate_)
+ owner_delegate_->RenderWidgetDidFlushPaint();
}
void RenderWidget::SetHidden(bool hidden) {
@@ -1813,6 +1794,14 @@ void RenderWidget::set_next_paint_is_repaint_ack() {
next_paint_flags_ |= ViewHostMsg_UpdateRect_Flags::IS_REPAINT_ACK;
}
+bool RenderWidget::IsUsingImeThread() {
+#if defined(OS_ANDROID)
+ return base::FeatureList::IsEnabled(features::kImeThread);
+#else
+ return false;
+#endif
+}
+
void RenderWidget::OnImeEventGuardStart(ImeEventGuard* guard) {
if (!ime_event_guard_)
ime_event_guard_ = guard;
@@ -1823,7 +1812,7 @@ void RenderWidget::OnImeEventGuardFinish(ImeEventGuard* guard) {
#if defined(OS_ANDROID)
// In case a from-IME event (e.g. touch) ends up in not-from-IME event
// (e.g. long press gesture), we want to treat it as not-from-IME event
- // so that AdapterInputConnection can make changes to its Editable model.
+ // so that ReplicaInputConnection can make changes to its Editable model.
// Therefore, we want to mark this text state update as 'from IME' only
// when all the nested events are all originating from IME.
ime_event_guard_->set_from_ime(
@@ -1890,33 +1879,42 @@ void RenderWidget::UpdateSelectionBounds() {
UpdateCompositionInfo(false);
}
-void RenderWidget::ForwardCompositorProto(const std::vector<uint8_t>& proto) {
- Send(new ViewHostMsg_ForwardCompositorProto(routing_id_, proto));
+void RenderWidget::SetDeviceColorProfileForTesting(
+ const std::vector<char>& color_profile) {
+ SetDeviceColorProfile(color_profile);
+}
+
+void RenderWidget::ResetDeviceColorProfileForTesting() {
+ std::vector<char> color_profile;
+ color_profile.push_back('0');
+ SetDeviceColorProfile(color_profile);
}
// Check blink::WebTextInputType and ui::TextInputType is kept in sync.
-#define STATIC_ASSERT_WTIT_ENUM_MATCH(a, b) \
- static_assert(int(blink::WebTextInputType##a) \
- == int(ui::TEXT_INPUT_TYPE_##b), \
- "mismatching enums: " #a)
-
-STATIC_ASSERT_WTIT_ENUM_MATCH(None, NONE);
-STATIC_ASSERT_WTIT_ENUM_MATCH(Text, TEXT);
-STATIC_ASSERT_WTIT_ENUM_MATCH(Password, PASSWORD);
-STATIC_ASSERT_WTIT_ENUM_MATCH(Search, SEARCH);
-STATIC_ASSERT_WTIT_ENUM_MATCH(Email, EMAIL);
-STATIC_ASSERT_WTIT_ENUM_MATCH(Number, NUMBER);
-STATIC_ASSERT_WTIT_ENUM_MATCH(Telephone, TELEPHONE);
-STATIC_ASSERT_WTIT_ENUM_MATCH(URL, URL);
-STATIC_ASSERT_WTIT_ENUM_MATCH(Date, DATE);
-STATIC_ASSERT_WTIT_ENUM_MATCH(DateTime, DATE_TIME);
-STATIC_ASSERT_WTIT_ENUM_MATCH(DateTimeLocal, DATE_TIME_LOCAL);
-STATIC_ASSERT_WTIT_ENUM_MATCH(Month, MONTH);
-STATIC_ASSERT_WTIT_ENUM_MATCH(Time, TIME);
-STATIC_ASSERT_WTIT_ENUM_MATCH(Week, WEEK);
-STATIC_ASSERT_WTIT_ENUM_MATCH(TextArea, TEXT_AREA);
-STATIC_ASSERT_WTIT_ENUM_MATCH(ContentEditable, CONTENT_EDITABLE);
-STATIC_ASSERT_WTIT_ENUM_MATCH(DateTimeField, DATE_TIME_FIELD);
+STATIC_ASSERT_ENUM(blink::WebTextInputTypeNone, ui::TEXT_INPUT_TYPE_NONE);
+STATIC_ASSERT_ENUM(blink::WebTextInputTypeText, ui::TEXT_INPUT_TYPE_TEXT);
+STATIC_ASSERT_ENUM(blink::WebTextInputTypePassword,
+ ui::TEXT_INPUT_TYPE_PASSWORD);
+STATIC_ASSERT_ENUM(blink::WebTextInputTypeSearch, ui::TEXT_INPUT_TYPE_SEARCH);
+STATIC_ASSERT_ENUM(blink::WebTextInputTypeEmail, ui::TEXT_INPUT_TYPE_EMAIL);
+STATIC_ASSERT_ENUM(blink::WebTextInputTypeNumber, ui::TEXT_INPUT_TYPE_NUMBER);
+STATIC_ASSERT_ENUM(blink::WebTextInputTypeTelephone,
+ ui::TEXT_INPUT_TYPE_TELEPHONE);
+STATIC_ASSERT_ENUM(blink::WebTextInputTypeURL, ui::TEXT_INPUT_TYPE_URL);
+STATIC_ASSERT_ENUM(blink::WebTextInputTypeDate, ui::TEXT_INPUT_TYPE_DATE);
+STATIC_ASSERT_ENUM(blink::WebTextInputTypeDateTime,
+ ui::TEXT_INPUT_TYPE_DATE_TIME);
+STATIC_ASSERT_ENUM(blink::WebTextInputTypeDateTimeLocal,
+ ui::TEXT_INPUT_TYPE_DATE_TIME_LOCAL);
+STATIC_ASSERT_ENUM(blink::WebTextInputTypeMonth, ui::TEXT_INPUT_TYPE_MONTH);
+STATIC_ASSERT_ENUM(blink::WebTextInputTypeTime, ui::TEXT_INPUT_TYPE_TIME);
+STATIC_ASSERT_ENUM(blink::WebTextInputTypeWeek, ui::TEXT_INPUT_TYPE_WEEK);
+STATIC_ASSERT_ENUM(blink::WebTextInputTypeTextArea,
+ ui::TEXT_INPUT_TYPE_TEXT_AREA);
+STATIC_ASSERT_ENUM(blink::WebTextInputTypeContentEditable,
+ ui::TEXT_INPUT_TYPE_CONTENT_EDITABLE);
+STATIC_ASSERT_ENUM(blink::WebTextInputTypeDateTimeField,
+ ui::TEXT_INPUT_TYPE_DATE_TIME_FIELD);
ui::TextInputType RenderWidget::WebKitToUiTextInputType(
blink::WebTextInputType type) {
@@ -2020,6 +2018,13 @@ void RenderWidget::didOverscroll(
const blink::WebFloatSize& accumulatedRootOverScroll,
const blink::WebFloatPoint& position,
const blink::WebFloatSize& velocity) {
+#if defined(OS_MACOSX)
+ // On OSX the user can disable the elastic overscroll effect. If that's the
+ // case, don't forward the overscroll notification.
+ DCHECK(compositor_deps());
+ if (!compositor_deps()->IsElasticOverscrollEnabled())
+ return;
+#endif
input_handler_->DidOverscrollFromBlink(unusedDelta, accumulatedRootOverScroll,
position, velocity);
}
@@ -2029,34 +2034,6 @@ void RenderWidget::StartCompositor() {
compositor_->setVisible(true);
}
-void RenderWidget::SchedulePluginMove(const WebPluginGeometry& move) {
- size_t i = 0;
- for (; i < plugin_window_moves_.size(); ++i) {
- if (plugin_window_moves_[i].window == move.window) {
- if (move.rects_valid) {
- plugin_window_moves_[i] = move;
- } else {
- plugin_window_moves_[i].visible = move.visible;
- }
- break;
- }
- }
-
- if (i == plugin_window_moves_.size())
- plugin_window_moves_.push_back(move);
-}
-
-void RenderWidget::CleanupWindowInPluginMoves(gfx::PluginWindowHandle window) {
- for (WebPluginGeometryVector::iterator i = plugin_window_moves_.begin();
- i != plugin_window_moves_.end(); ++i) {
- if (i->window == window) {
- plugin_window_moves_.erase(i);
- break;
- }
- }
-}
-
-
RenderWidgetCompositor* RenderWidget::compositor() const {
return compositor_.get();
}
@@ -2079,10 +2056,21 @@ void RenderWidget::hasTouchEventHandlers(bool has_handlers) {
Send(new ViewHostMsg_HasTouchEventHandlers(routing_id_, has_handlers));
}
-// Check blink::WebTouchAction and blink::WebTouchActionAuto is kept in sync
-#define STATIC_ASSERT_WTI_ENUM_MATCH(a, b) \
- static_assert(int(blink::WebTouchAction##a) == int(TOUCH_ACTION_##b), \
- "mismatching enums: " #a)
+// Check blink::WebTouchAction and content::TouchAction is kept in sync.
+STATIC_ASSERT_ENUM(blink::WebTouchActionNone, TOUCH_ACTION_NONE);
+STATIC_ASSERT_ENUM(blink::WebTouchActionPanLeft, TOUCH_ACTION_PAN_LEFT);
+STATIC_ASSERT_ENUM(blink::WebTouchActionPanRight, TOUCH_ACTION_PAN_RIGHT);
+STATIC_ASSERT_ENUM(blink::WebTouchActionPanX, TOUCH_ACTION_PAN_X);
+STATIC_ASSERT_ENUM(blink::WebTouchActionPanUp, TOUCH_ACTION_PAN_UP);
+STATIC_ASSERT_ENUM(blink::WebTouchActionPanDown, TOUCH_ACTION_PAN_DOWN);
+STATIC_ASSERT_ENUM(blink::WebTouchActionPanY, TOUCH_ACTION_PAN_Y);
+STATIC_ASSERT_ENUM(blink::WebTouchActionPan, TOUCH_ACTION_PAN);
+STATIC_ASSERT_ENUM(blink::WebTouchActionPinchZoom, TOUCH_ACTION_PINCH_ZOOM);
+STATIC_ASSERT_ENUM(blink::WebTouchActionManipulation,
+ TOUCH_ACTION_MANIPULATION);
+STATIC_ASSERT_ENUM(blink::WebTouchActionDoubleTapZoom,
+ TOUCH_ACTION_DOUBLE_TAP_ZOOM);
+STATIC_ASSERT_ENUM(blink::WebTouchActionAuto, TOUCH_ACTION_AUTO);
void RenderWidget::setTouchAction(
blink::WebTouchAction web_touch_action) {
@@ -2092,20 +2080,6 @@ void RenderWidget::setTouchAction(
if (input_handler_->handling_event_type() != WebInputEvent::TouchStart)
return;
- // Verify the same values are used by the types so we can cast between them.
- STATIC_ASSERT_WTI_ENUM_MATCH(None, NONE);
- STATIC_ASSERT_WTI_ENUM_MATCH(PanLeft, PAN_LEFT);
- STATIC_ASSERT_WTI_ENUM_MATCH(PanRight, PAN_RIGHT);
- STATIC_ASSERT_WTI_ENUM_MATCH(PanX, PAN_X);
- STATIC_ASSERT_WTI_ENUM_MATCH(PanUp, PAN_UP);
- STATIC_ASSERT_WTI_ENUM_MATCH(PanDown, PAN_DOWN);
- STATIC_ASSERT_WTI_ENUM_MATCH(PanY, PAN_Y);
- STATIC_ASSERT_WTI_ENUM_MATCH(Pan, PAN);
- STATIC_ASSERT_WTI_ENUM_MATCH(PinchZoom, PINCH_ZOOM);
- STATIC_ASSERT_WTI_ENUM_MATCH(Manipulation, MANIPULATION);
- STATIC_ASSERT_WTI_ENUM_MATCH(DoubleTapZoom, DOUBLE_TAP_ZOOM);
- STATIC_ASSERT_WTI_ENUM_MATCH(Auto, AUTO);
-
content::TouchAction content_touch_action =
static_cast<content::TouchAction>(web_touch_action);
Send(new InputHostMsg_SetTouchAction(routing_id_, content_touch_action));
@@ -2113,29 +2087,24 @@ void RenderWidget::setTouchAction(
void RenderWidget::didUpdateTextOfFocusedElementByNonUserInput() {
#if defined(OS_ANDROID)
- text_field_is_dirty_ = true;
+ if (!IsUsingImeThread())
+ text_field_is_dirty_ = true;
#endif
}
scoped_ptr<WebGraphicsContext3DCommandBufferImpl>
-RenderWidget::CreateGraphicsContext3D(GpuChannelHost* gpu_channel_host) {
- // Explicitly disable antialiasing for the compositor. As of the time of
- // this writing, the only platform that supported antialiasing for the
- // compositor was Mac OS X, because the on-screen OpenGL context creation
- // code paths on Windows and Linux didn't yet have multisampling support.
- // Mac OS X essentially always behaves as though it's rendering offscreen.
- // Multisampling has a heavy cost especially on devices with relatively low
- // fill rate like most notebooks, and the Mac implementation would need to
- // be optimized to resolve directly into the IOSurface shared between the
- // GPU and browser processes. For these reasons and to avoid platform
- // disparities we explicitly disable antialiasing.
- blink::WebGraphicsContext3D::Attributes attributes;
- attributes.antialias = false;
- attributes.shareResources = true;
- attributes.noAutomaticFlushes = true;
- attributes.depth = false;
- attributes.stencil = false;
- bool lose_context_when_out_of_memory = true;
+RenderWidget::CreateGraphicsContext3D(gpu::GpuChannelHost* gpu_channel_host) {
+ // This is for an offscreen context for raster in the compositor. So the
+ // default framebuffer doesn't need alpha, depth, stencil, antialiasing.
+ gpu::gles2::ContextCreationAttribHelper attributes;
+ attributes.alpha_size = -1;
+ attributes.depth_size = 0;
+ attributes.stencil_size = 0;
+ attributes.samples = 0;
+ attributes.sample_buffers = 0;
+ attributes.bind_generates_resource = false;
+ attributes.lose_context_when_out_of_memory = true;
+
WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits;
#if defined(OS_ANDROID)
bool using_synchronous_compositing =
@@ -2170,9 +2139,13 @@ RenderWidget::CreateGraphicsContext3D(GpuChannelHost* gpu_channel_host) {
limits.start_transfer_buffer_size = 64 * 1024;
limits.min_transfer_buffer_size = 64 * 1024;
+ bool share_resources = true;
+ bool automatic_flushes = false;
+
return make_scoped_ptr(new WebGraphicsContext3DCommandBufferImpl(
- 0, GetURLForGraphicsContext3D(), gpu_channel_host, attributes,
- lose_context_when_out_of_memory, limits, NULL));
+ gpu::kNullSurfaceHandle, GetURLForGraphicsContext3D(), gpu_channel_host,
+ attributes, gfx::PreferIntegratedGpu, share_resources, automatic_flushes,
+ limits, nullptr));
}
void RenderWidget::RegisterRenderFrameProxy(RenderFrameProxy* proxy) {
@@ -2201,4 +2174,16 @@ void RenderWidget::UnregisterVideoHoleFrame(RenderFrameImpl* frame) {
}
#endif // defined(VIDEO_HOLE)
+void RenderWidget::OnWaitNextFrameForTests(int routing_id) {
+ QueueMessage(new ViewHostMsg_WaitForNextFrameForTests_ACK(routing_id),
+ MESSAGE_DELIVERY_POLICY_WITH_VISUAL_STATE);
+}
+
+float RenderWidget::GetOriginalDeviceScaleFactor() const {
+ return
+ screen_metrics_emulator_ ?
+ screen_metrics_emulator_->original_screen_info().deviceScaleFactor :
+ device_scale_factor_;
+}
+
} // namespace content
diff --git a/chromium/content/renderer/render_widget.h b/chromium/content/renderer/render_widget.h
index 20d98e87de2..d8851906157 100644
--- a/chromium/content/renderer/render_widget.h
+++ b/chromium/content/renderer/render_widget.h
@@ -23,6 +23,8 @@
#include "content/common/cursors/webcursor.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
#include "content/common/input/synthetic_gesture_params.h"
+#include "content/renderer/devtools/render_widget_screen_metrics_emulator_delegate.h"
+#include "content/renderer/gpu/render_widget_compositor_delegate.h"
#include "content/renderer/input/render_widget_input_handler.h"
#include "content/renderer/input/render_widget_input_handler_delegate.h"
#include "content/renderer/message_delivery_policy.h"
@@ -43,14 +45,11 @@
#include "ui/base/ime/text_input_type.h"
#include "ui/base/ui_base_types.h"
#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/geometry/vector2d_f.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/range/range.h"
#include "ui/surface/transport_dib.h"
-struct ViewMsg_Resize_Params;
-
namespace IPC {
class SyncMessage;
class SyncMessageFilter;
@@ -58,6 +57,7 @@ class SyncMessageFilter;
namespace blink {
struct WebDeviceEmulationParams;
+class WebFrameWidget;
class WebGestureEvent;
class WebLocalFrame;
class WebMouseEvent;
@@ -86,10 +86,12 @@ class ImeEventGuard;
class RenderFrameImpl;
class RenderFrameProxy;
class RenderWidgetCompositor;
+class RenderWidgetOwnerDelegate;
+class RenderWidgetScreenMetricsEmulator;
class ResizingModeSelector;
struct ContextMenuParams;
struct DidOverscrollParams;
-struct WebPluginGeometry;
+struct ResizeParams;
// RenderWidget provides a communication bridge between a WebWidget and
// a RenderWidgetHost, the latter of which lives in a different process.
@@ -103,7 +105,9 @@ class CONTENT_EXPORT RenderWidget
: public IPC::Listener,
public IPC::Sender,
NON_EXPORTED_BASE(virtual public blink::WebWidgetClient),
+ public RenderWidgetCompositorDelegate,
public RenderWidgetInputHandlerDelegate,
+ public RenderWidgetScreenMetricsEmulatorDelegate,
public base::RefCounted<RenderWidget> {
public:
// Creates a new RenderWidget. The opener_id is the routing ID of the
@@ -130,14 +134,13 @@ class CONTENT_EXPORT RenderWidget
CompositorDependencies* compositor_deps() const { return compositor_deps_; }
blink::WebWidget* webwidget() const { return webwidget_; }
- gfx::Size size() const { return size_; }
+ const gfx::Size& size() const { return size_; }
bool is_fullscreen_granted() const { return is_fullscreen_granted_; }
blink::WebDisplayMode display_mode() const { return display_mode_; }
bool is_hidden() const { return is_hidden_; }
// Temporary for debugging purposes...
bool closing() const { return closing_; }
bool is_swapped_out() { return is_swapped_out_; }
- bool for_oopif() { return for_oopif_; }
bool has_host_context_menu_location() {
return has_host_context_menu_location_;
}
@@ -145,6 +148,13 @@ class CONTENT_EXPORT RenderWidget
return host_context_menu_location_;
}
+ void set_owner_delegate(RenderWidgetOwnerDelegate* owner_delegate) {
+ DCHECK(!owner_delegate_);
+ owner_delegate_ = owner_delegate;
+ }
+
+ RenderWidgetOwnerDelegate* owner_delegate() { return owner_delegate_; }
+
// ScreenInfo exposed so it can be passed to subframe RenderWidgets.
blink::WebScreenInfo screen_info() const { return screen_info_; }
@@ -168,21 +178,63 @@ class CONTENT_EXPORT RenderWidget
// IPC::Sender
bool Send(IPC::Message* msg) override;
+ // RenderWidgetCompositorDelegate
+ void ApplyViewportDeltas(const gfx::Vector2dF& inner_delta,
+ const gfx::Vector2dF& outer_delta,
+ const gfx::Vector2dF& elastic_overscroll_delta,
+ float page_scale,
+ float top_controls_delta) override;
+ void BeginMainFrame(double frame_time_sec) override;
+ scoped_ptr<cc::OutputSurface> CreateOutputSurface(bool fallback) override;
+ scoped_ptr<cc::BeginFrameSource> CreateExternalBeginFrameSource() override;
+ void DidCommitAndDrawCompositorFrame() override;
+ void DidCommitCompositorFrame() override;
+ void DidCompletePageScaleAnimation() override;
+ void DidCompleteSwapBuffers() override;
+ bool ForOOPIF() const override;
+ void ForwardCompositorProto(const std::vector<uint8_t>& proto) override;
+ bool IsClosing() const override;
+ void OnSwapBuffersAborted() override;
+ void OnSwapBuffersComplete() override;
+ void OnSwapBuffersPosted() override;
+ void RecordFrameTimingEvents(
+ scoped_ptr<cc::FrameTimingTracker::CompositeTimingSet> composite_events,
+ scoped_ptr<cc::FrameTimingTracker::MainFrameTimingSet> main_frame_events)
+ override;
+ void RequestScheduleAnimation() override;
+ void UpdateVisualState() override;
+ void WillBeginCompositorFrame() override;
+
// RenderWidgetInputHandlerDelegate
void FocusChangeComplete() override;
bool HasTouchEventHandlersAt(const gfx::Point& point) const override;
void ObserveWheelEventAndResult(const blink::WebMouseWheelEvent& wheel_event,
const gfx::Vector2dF& wheel_unused_delta,
bool event_processed) override;
+ void ObserveGestureEventAndResult(const blink::WebGestureEvent& gesture_event,
+ const gfx::Vector2dF& unused_delta,
+ bool event_processed) override;
+
void OnDidHandleKeyEvent() override;
void OnDidOverscroll(const DidOverscrollParams& params) override;
void OnInputEventAck(scoped_ptr<InputEventAck> input_event_ack) override;
+ void NotifyInputEventHandled(
+ blink::WebInputEvent::Type handled_type) override;
void SetInputHandler(RenderWidgetInputHandler* input_handler) override;
void UpdateTextInputState(ShowIme show_ime,
ChangeSource change_source) override;
bool WillHandleGestureEvent(const blink::WebGestureEvent& event) override;
bool WillHandleMouseEvent(const blink::WebMouseEvent& event) override;
+ // RenderWidgetScreenMetricsDelegate
+ void Redraw() override;
+ void Resize(const ResizeParams& resize_params) override;
+ void SetScreenMetricsEmulationParameters(
+ bool enabled,
+ const blink::WebDeviceEmulationParams& params) override;
+ void SetScreenRects(const gfx::Rect& view_screen_rect,
+ const gfx::Rect& window_screen_rect) override;
+
// blink::WebWidgetClient
void didAutoResize(const blink::WebSize& new_size) override;
void initializeLayerTreeView() override;
@@ -208,6 +260,7 @@ class CONTENT_EXPORT RenderWidget
const blink::WebFloatSize& velocity) override;
void showImeIfNeeded() override;
void convertViewportToWindow(blink::WebRect* rect) override;
+ void convertWindowToViewport(blink::WebFloatRect* rect) override;
// Override point to obtain that the current input method state and caret
// position.
@@ -231,14 +284,6 @@ class CONTENT_EXPORT RenderWidget
// Stop compositing.
void WillCloseLayerTreeView();
- // Called when a plugin is moved. These events are queued up and sent with
- // the next paint or scroll message to the host.
- void SchedulePluginMove(const WebPluginGeometry& move);
-
- // Called when a plugin window has been destroyed, to make sure the currently
- // pending moves don't try to reference it.
- void CleanupWindowInPluginMoves(gfx::PluginWindowHandle window);
-
RenderWidgetCompositor* compositor() const;
const RenderWidgetInputHandler& input_handler() const {
@@ -256,8 +301,6 @@ class CONTENT_EXPORT RenderWidget
// we should not send an extra ack (see SendAckForMouseMoveFromDebugger).
void IgnoreAckForMouseMoveFromDebugger();
- virtual scoped_ptr<cc::OutputSurface> CreateOutputSurface(bool fallback);
-
// Callback for use with synthetic gestures (e.g. BeginSmoothScroll).
typedef base::Callback<void()> SyntheticGestureCompletionCallback;
@@ -279,6 +322,9 @@ class CONTENT_EXPORT RenderWidget
// |policy| see the comment on MessageDeliveryPolicy.
void QueueMessage(IPC::Message* msg, MessageDeliveryPolicy policy);
+ // Check whether IME thread is being used or not.
+ bool IsUsingImeThread();
+
// Handle start and finish of IME event guard.
void OnImeEventGuardStart(ImeEventGuard* guard);
void OnImeEventGuardFinish(ImeEventGuard* guard);
@@ -286,49 +332,21 @@ class CONTENT_EXPORT RenderWidget
// Returns whether we currently should handle an IME event.
bool ShouldHandleImeEvent();
- // Called by the compositor when page scale animation completed.
- virtual void DidCompletePageScaleAnimation() {}
-
- // ScreenMetricsEmulator class manages screen emulation inside a render
- // widget. This includes resizing, placing view on the screen at desired
- // position, changing device scale factor, and scaling down the whole
- // widget if required to fit into the browser window.
- class ScreenMetricsEmulator;
+ void SetPopupOriginAdjustmentsForEmulation(
+ RenderWidgetScreenMetricsEmulator* emulator);
- void SetPopupOriginAdjustmentsForEmulation(ScreenMetricsEmulator* emulator);
gfx::Rect AdjustValidationMessageAnchor(const gfx::Rect& anchor);
- // Indicates that the compositor is about to begin a frame. This is primarily
- // to signal to flow control mechanisms that a frame is beginning, not to
- // perform actual painting work.
- void WillBeginCompositorFrame();
-
- // Notifies about a compositor frame commit operation having finished.
- virtual void DidCommitCompositorFrame();
-
- // Notifies that the draw commands for a committed frame have been issued.
- void DidCommitAndDrawCompositorFrame();
-
- // Notifies that the compositor has posted a swapbuffers operation to the GPU
- // process.
- void DidCompleteSwapBuffers();
void ScheduleComposite();
void ScheduleCompositeWithForcedRedraw();
- // Called by the compositor in single-threaded mode when a swap is posted,
- // completes or is aborted.
- void OnSwapBuffersPosted();
- void OnSwapBuffersComplete();
- void OnSwapBuffersAborted();
-
// Checks if the selection bounds have been changed. If they are changed,
// the new value will be sent to the browser process.
void UpdateSelectionBounds();
// Called by the compositor to forward a proto that represents serialized
// compositor state.
- void ForwardCompositorProto(const std::vector<uint8_t>& proto);
virtual void GetSelectionBounds(gfx::Rect* start, gfx::Rect* end);
@@ -340,7 +358,9 @@ class CONTENT_EXPORT RenderWidget
// handle composition range and composition character bounds.
void UpdateCompositionInfo(bool should_update_range);
- bool host_closing() const { return host_closing_; }
+ // Change the device ICC color profile while running a layout test.
+ void SetDeviceColorProfileForTesting(const std::vector<char>& color_profile);
+ void ResetDeviceColorProfileForTesting();
protected:
// Friend RefCounted so that the dtor can be non-public. Using this class
@@ -364,8 +384,9 @@ class CONTENT_EXPORT RenderWidget
~RenderWidget() override;
- static blink::WebWidget* CreateWebFrameWidget(RenderWidget* render_widget,
- blink::WebLocalFrame* frame);
+ static blink::WebFrameWidget* CreateWebFrameWidget(
+ RenderWidget* render_widget,
+ blink::WebLocalFrame* frame);
// Creates a WebWidget based on the popup type.
static blink::WebWidget* CreateWebWidget(RenderWidget* render_widget);
@@ -394,35 +415,24 @@ class CONTENT_EXPORT RenderWidget
// Close the underlying WebWidget.
virtual void Close();
- // Resizes the render widget.
- void Resize(const gfx::Size& new_size,
- const gfx::Size& physical_backing_size,
- bool top_controls_shrink_blink_size,
- float top_controls_height,
- const gfx::Size& visible_viewport_size,
- const gfx::Rect& resizer_rect,
- bool is_fullscreen_granted,
- blink::WebDisplayMode display_mode,
- ResizeAck resize_ack);
// Used to force the size of a window when running layout tests.
void SetWindowRectSynchronously(const gfx::Rect& new_window_rect);
- virtual void SetScreenMetricsEmulationParameters(
- bool enabled,
- const blink::WebDeviceEmulationParams& params);
#if defined(OS_MACOSX) || defined(OS_ANDROID)
void SetExternalPopupOriginAdjustmentsForEmulation(
- ExternalPopupMenu* popup, ScreenMetricsEmulator* emulator);
+ ExternalPopupMenu* popup,
+ RenderWidgetScreenMetricsEmulator* emulator);
#endif
// RenderWidget IPC message handlers
void OnHandleInputEvent(const blink::WebInputEvent* event,
- const ui::LatencyInfo& latency_info);
+ const ui::LatencyInfo& latency_info,
+ InputEventDispatchType dispatch_type);
void OnCursorVisibilityChange(bool is_visible);
void OnMouseCaptureLost();
virtual void OnSetFocus(bool enable);
void OnClose();
void OnCreatingNewAck();
- virtual void OnResize(const ViewMsg_Resize_Params& params);
+ virtual void OnResize(const ResizeParams& params);
void OnEnableDeviceEmulation(const blink::WebDeviceEmulationParams& params);
void OnDisableDeviceEmulation();
void OnColorProfile(const std::vector<char>& color_profile);
@@ -436,6 +446,7 @@ class CONTENT_EXPORT RenderWidget
virtual void OnImeSetComposition(
const base::string16& text,
const std::vector<blink::WebCompositionUnderline>& underlines,
+ const gfx::Range& replacement_range,
int selection_start,
int selection_end);
virtual void OnImeConfirmComposition(const base::string16& text,
@@ -451,6 +462,7 @@ class CONTENT_EXPORT RenderWidget
void OnGetFPS();
void OnUpdateScreenRects(const gfx::Rect& view_screen_rect,
const gfx::Rect& window_screen_rect);
+ void OnUpdateWindowScreenRect(const gfx::Rect& window_screen_rect);
void OnShowImeIfNeeded();
void OnSetSurfaceIdNamespace(uint32_t surface_id_namespace);
void OnHandleCompositorProto(const std::vector<uint8_t>& proto);
@@ -461,6 +473,9 @@ class CONTENT_EXPORT RenderWidget
// Called by the browser process for every required IME acknowledgement.
void OnImeEventAck();
+
+ // Called by the browser process to update text input state.
+ void OnRequestTextInputStateUpdate();
#endif
// Notify the compositor about a change in viewport size. This should be
@@ -469,8 +484,7 @@ class CONTENT_EXPORT RenderWidget
void AutoResizeCompositor();
virtual void SetDeviceScaleFactor(float device_scale_factor);
- virtual bool SetDeviceColorProfile(const std::vector<char>& color_profile);
- virtual void ResetDeviceColorProfileForTesting();
+ bool SetDeviceColorProfile(const std::vector<char>& color_profile);
virtual void OnOrientationChange();
@@ -480,15 +494,11 @@ class CONTENT_EXPORT RenderWidget
// the ACK that the screen has been updated. For a given paint operation,
// these overrides will always be called in the order DidInitiatePaint,
// DidFlushPaint.
- virtual void DidInitiatePaint() {}
- virtual void DidFlushPaint() {}
+ virtual void DidInitiatePaint();
+ virtual void DidFlushPaint();
virtual GURL GetURLForGraphicsContext3D();
- // Gets the scroll offset of this widget, if this widget has a notion of
- // scroll offset.
- virtual gfx::Vector2d GetScrollOffset();
-
// Sets the "hidden" state of this widget. All accesses to is_hidden_ should
// use this method so that we can properly inform the RenderThread of our
// state.
@@ -550,7 +560,10 @@ class CONTENT_EXPORT RenderWidget
// Creates a 3D context associated with this view.
scoped_ptr<WebGraphicsContext3DCommandBufferImpl> CreateGraphicsContext3D(
- GpuChannelHost* gpu_channel_host);
+ gpu::GpuChannelHost* gpu_channel_host);
+
+ // Sends an ACK to the browser process during the next compositor frame.
+ void OnWaitNextFrameForTests(int routing_id);
// Routing ID that allows us to communicate to the parent browser process
// RenderWidgetHost. When MSG_ROUTING_NONE, no messages may be sent.
@@ -564,6 +577,9 @@ class CONTENT_EXPORT RenderWidget
// May be NULL when the window is closing.
blink::WebWidget* webwidget_;
+ // The delegate of the owner of this object.
+ RenderWidgetOwnerDelegate* owner_delegate_;
+
// This is lazily constructed and must not outlive webwidget_.
scoped_ptr<RenderWidgetCompositor> compositor_;
@@ -678,10 +694,6 @@ class CONTENT_EXPORT RenderWidget
// The kind of popup this widget represents, NONE if not a popup.
blink::WebPopupType popup_type_;
- // Holds all the needed plugin window moves for a scroll.
- typedef std::vector<WebPluginGeometry> WebPluginGeometryVector;
- WebPluginGeometryVector plugin_window_moves_;
-
// While we are waiting for the browser to update window sizes, we track the
// pending size temporarily.
int pending_window_rect_count_;
@@ -726,7 +738,7 @@ class CONTENT_EXPORT RenderWidget
std::deque<blink::WebTextInputInfo> text_input_info_history_;
#endif
- scoped_ptr<ScreenMetricsEmulator> screen_metrics_emulator_;
+ scoped_ptr<RenderWidgetScreenMetricsEmulator> screen_metrics_emulator_;
// Popups may be displaced when screen metrics emulation is enabled.
// These values are used to properly adjust popup position.
@@ -755,6 +767,10 @@ class CONTENT_EXPORT RenderWidget
scoped_ptr<scheduler::RenderWidgetSchedulingState>
render_widget_scheduling_state_;
+ private:
+ // When emulated, this returns original device scale factor.
+ float GetOriginalDeviceScaleFactor() const;
+
DISALLOW_COPY_AND_ASSIGN(RenderWidget);
};
diff --git a/chromium/content/renderer/render_widget_browsertest.cc b/chromium/content/renderer/render_widget_browsertest.cc
index e3caf1f71ec..489536df3df 100644
--- a/chromium/content/renderer/render_widget_browsertest.cc
+++ b/chromium/content/renderer/render_widget_browsertest.cc
@@ -2,16 +2,30 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "content/common/view_messages.h"
-#include "content/public/test/render_widget_test.h"
+#include "content/common/resize_params.h"
+#include "content/public/test/render_view_test.h"
+#include "content/renderer/render_view_impl.h"
#include "content/renderer/render_widget.h"
namespace content {
+class RenderWidgetTest : public RenderViewTest {
+ protected:
+ RenderWidget* widget() { return view_->GetWidget(); }
+
+ void OnResize(const ResizeParams& params) {
+ widget()->OnResize(params);
+ }
+
+ bool next_paint_is_resize_ack() {
+ return widget()->next_paint_is_resize_ack();
+ }
+};
+
TEST_F(RenderWidgetTest, OnResize) {
// The initial bounds is empty, so setting it to the same thing should do
// nothing.
- ViewMsg_Resize_Params resize_params;
+ ResizeParams resize_params;
resize_params.screen_info = blink::WebScreenInfo();
resize_params.new_size = gfx::Size();
resize_params.physical_backing_size = gfx::Size();
@@ -68,9 +82,8 @@ class RenderWidgetInitialSizeTest : public RenderWidgetTest {
: RenderWidgetTest(), initial_size_(200, 100) {}
protected:
- scoped_ptr<ViewMsg_Resize_Params> InitialSizeParams() override {
- scoped_ptr<ViewMsg_Resize_Params> initial_size_params(
- new ViewMsg_Resize_Params());
+ scoped_ptr<ResizeParams> InitialSizeParams() override {
+ scoped_ptr<ResizeParams> initial_size_params(new ResizeParams());
initial_size_params->new_size = initial_size_;
initial_size_params->physical_backing_size = initial_size_;
initial_size_params->needs_resize_ack = true;
diff --git a/chromium/content/renderer/render_widget_fullscreen_pepper.cc b/chromium/content/renderer/render_widget_fullscreen_pepper.cc
index 9f9ebe05797..cbd9f948152 100644
--- a/chromium/content/renderer/render_widget_fullscreen_pepper.cc
+++ b/chromium/content/renderer/render_widget_fullscreen_pepper.cc
@@ -11,12 +11,12 @@
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "build/build_config.h"
-#include "content/common/gpu/client/gpu_channel_host.h"
#include "content/common/view_messages.h"
#include "content/public/common/content_switches.h"
#include "content/renderer/gpu/render_widget_compositor.h"
#include "content/renderer/pepper/pepper_plugin_instance_impl.h"
#include "content/renderer/render_thread_impl.h"
+#include "gpu/ipc/client/gpu_channel_host.h"
#include "skia/ext/platform_canvas.h"
#include "third_party/WebKit/public/platform/WebCanvas.h"
#include "third_party/WebKit/public/platform/WebCursorInfo.h"
@@ -43,7 +43,6 @@ using blink::WebTextDirection;
using blink::WebTextInputType;
using blink::WebVector;
using blink::WebWidget;
-using blink::WGC3Dintptr;
namespace content {
@@ -315,7 +314,7 @@ void RenderWidgetFullscreenPepper::Destroy() {
Release();
}
-void RenderWidgetFullscreenPepper::DidChangeCursor(
+void RenderWidgetFullscreenPepper::PepperDidChangeCursor(
const blink::WebCursorInfo& cursor) {
didChangeCursor(cursor);
}
@@ -370,8 +369,7 @@ void RenderWidgetFullscreenPepper::Close() {
RenderWidget::Close();
}
-void RenderWidgetFullscreenPepper::OnResize(
- const ViewMsg_Resize_Params& params) {
+void RenderWidgetFullscreenPepper::OnResize(const ResizeParams& params) {
if (layer_)
layer_->setBounds(blink::WebSize(params.new_size));
RenderWidget::OnResize(params);
@@ -385,11 +383,9 @@ GURL RenderWidgetFullscreenPepper::GetURLForGraphicsContext3D() {
return active_url_;
}
-void RenderWidgetFullscreenPepper::SetDeviceScaleFactor(
- float device_scale_factor) {
- RenderWidget::SetDeviceScaleFactor(device_scale_factor);
+void RenderWidgetFullscreenPepper::OnDeviceScaleFactorChanged() {
if (compositor_)
- compositor_->setDeviceScaleFactor(device_scale_factor);
+ compositor_->setDeviceScaleFactor(device_scale_factor_);
}
} // namespace content
diff --git a/chromium/content/renderer/render_widget_fullscreen_pepper.h b/chromium/content/renderer/render_widget_fullscreen_pepper.h
index 4c144c81872..7f4bd4487ad 100644
--- a/chromium/content/renderer/render_widget_fullscreen_pepper.h
+++ b/chromium/content/renderer/render_widget_fullscreen_pepper.h
@@ -39,7 +39,7 @@ class RenderWidgetFullscreenPepper : public RenderWidgetFullscreen,
void InvalidateRect(const blink::WebRect& rect) override;
void ScrollRect(int dx, int dy, const blink::WebRect& rect) override;
void Destroy() override;
- void DidChangeCursor(const blink::WebCursorInfo& cursor) override;
+ void PepperDidChangeCursor(const blink::WebCursorInfo& cursor) override;
void SetLayer(blink::WebLayer* layer) override;
// IPC::Listener implementation. This overrides the implementation
@@ -64,14 +64,14 @@ class RenderWidgetFullscreenPepper : public RenderWidgetFullscreen,
void DidInitiatePaint() override;
void DidFlushPaint() override;
void Close() override;
- void OnResize(const ViewMsg_Resize_Params& params) override;
+ void OnResize(const ResizeParams& params) override;
// RenderWidgetFullscreen API.
blink::WebWidget* CreateWebWidget() override;
// RenderWidget overrides.
GURL GetURLForGraphicsContext3D() override;
- void SetDeviceScaleFactor(float device_scale_factor) override;
+ void OnDeviceScaleFactorChanged() override;
private:
// URL that is responsible for this widget, passed to ggl::CreateViewContext.
diff --git a/chromium/content/renderer/render_widget_owner_delegate.h b/chromium/content/renderer/render_widget_owner_delegate.h
new file mode 100644
index 00000000000..4c76ddd19bd
--- /dev/null
+++ b/chromium/content/renderer/render_widget_owner_delegate.h
@@ -0,0 +1,58 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_RENDER_WIDGET_OWNER_DELEGATE_H_
+#define CONTENT_RENDERER_RENDER_WIDGET_OWNER_DELEGATE_H_
+
+#include "content/common/content_export.h"
+
+namespace blink {
+class WebGestureEvent;
+class WebMouseEvent;
+}
+
+namespace gfx {
+class Point;
+}
+
+namespace content {
+
+//
+// RenderWidgetOwnerDelegate
+//
+// An interface implemented by an object owning a RenderWidget. This is
+// intended to be temporary until the RenderViewImpl and RenderWidget classes
+// are disentangled; see http://crbug.com/583347 and http://crbug.com/478281.
+class CONTENT_EXPORT RenderWidgetOwnerDelegate {
+ public:
+ // The RenderWidget set a color profile.
+ virtual void RenderWidgetDidSetColorProfile(
+ const std::vector<char>& color_profile) = 0;
+
+ // As in RenderWidgetInputHandlerDelegate.
+ virtual void RenderWidgetFocusChangeComplete() = 0;
+ virtual bool DoesRenderWidgetHaveTouchEventHandlersAt(
+ const gfx::Point& point) const = 0;
+ virtual void RenderWidgetDidHandleKeyEvent() = 0;
+ virtual bool RenderWidgetWillHandleGestureEvent(
+ const blink::WebGestureEvent& event) = 0;
+ virtual bool RenderWidgetWillHandleMouseEvent(
+ const blink::WebMouseEvent& event) = 0;
+
+ // Painting notifications. RenderWidgetDidCommitAndDrawCompositorFrame happens
+ // when that has completed, and subsequent rendering won't affect the painted
+ // content. DidFlushPaint happens once we've received the ACK that the screen
+ // has been updated. For a given paint operation, these overrides will always
+ // be called in the order RenderWidgetDidCommitAndDrawCompositorFrame,
+ // RenderWidgetDidFlushPaint.
+ virtual void RenderWidgetDidCommitAndDrawCompositorFrame() = 0;
+ virtual void RenderWidgetDidFlushPaint() = 0;
+
+ protected:
+ virtual ~RenderWidgetOwnerDelegate() {}
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_RENDER_WIDGET_OWNER_DELEGATE_H_
diff --git a/chromium/content/renderer/render_widget_unittest.cc b/chromium/content/renderer/render_widget_unittest.cc
index cdd195a5a2b..05ebc45a747 100644
--- a/chromium/content/renderer/render_widget_unittest.cc
+++ b/chromium/content/renderer/render_widget_unittest.cc
@@ -7,18 +7,45 @@
#include <vector>
#include "base/macros.h"
+#include "base/test/histogram_tester.h"
#include "content/common/input/synthetic_web_input_event_builders.h"
+#include "content/common/input/web_input_event_traits.h"
#include "content/common/input_messages.h"
#include "content/public/test/mock_render_thread.h"
#include "content/test/fake_compositor_dependencies.h"
#include "content/test/mock_render_process.h"
#include "ipc/ipc_test_sink.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/public/web/WebInputEvent.h"
#include "ui/gfx/geometry/rect.h"
+using testing::_;
+
namespace content {
+namespace {
+
+const char* EVENT_LISTENER_RESULT_HISTOGRAM = "Event.PassiveListeners";
+
+enum {
+ PASSIVE_LISTENER_UMA_ENUM_PASSIVE,
+ PASSIVE_LISTENER_UMA_ENUM_UNCANCELABLE,
+ PASSIVE_LISTENER_UMA_ENUM_SUPPRESSED,
+ PASSIVE_LISTENER_UMA_ENUM_CANCELABLE,
+ PASSIVE_LISTENER_UMA_ENUM_CANCELABLE_AND_CANCELED,
+ PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING,
+ PASSIVE_LISTENER_UMA_ENUM_COUNT
+};
+
+class MockWebWidget : public blink::WebWidget {
+ public:
+ MOCK_METHOD1(handleInputEvent,
+ blink::WebInputEventResult(const blink::WebInputEvent&));
+};
+
+} // namespace
+
class InteractiveRenderWidget : public RenderWidget {
public:
explicit InteractiveRenderWidget(CompositorDependencies* compositor_deps)
@@ -29,6 +56,7 @@ class InteractiveRenderWidget : public RenderWidget {
false,
false),
always_overscroll_(false) {
+ webwidget_ = &mock_webwidget_;
// A RenderWidget is not fully initialized until it has a routing ID.
SetRoutingID(++next_routing_id_);
}
@@ -38,7 +66,11 @@ class InteractiveRenderWidget : public RenderWidget {
}
void SendInputEvent(const blink::WebInputEvent& event) {
- OnHandleInputEvent(&event, ui::LatencyInfo());
+ OnHandleInputEvent(
+ &event, ui::LatencyInfo(),
+ WebInputEventTraits::ShouldBlockEventStream(event)
+ ? InputEventDispatchType::DISPATCH_TYPE_BLOCKING
+ : InputEventDispatchType::DISPATCH_TYPE_NON_BLOCKING);
}
void set_always_overscroll(bool overscroll) {
@@ -47,8 +79,10 @@ class InteractiveRenderWidget : public RenderWidget {
IPC::TestSink* sink() { return &sink_; }
+ MockWebWidget* mock_webwidget() { return &mock_webwidget_; }
+
protected:
- ~InteractiveRenderWidget() override {}
+ ~InteractiveRenderWidget() override { webwidget_ = nullptr; }
// Overridden from RenderWidget:
bool HasTouchEventHandlersAt(const gfx::Point& point) const override {
@@ -86,6 +120,7 @@ class InteractiveRenderWidget : public RenderWidget {
std::vector<gfx::Rect> rects_;
IPC::TestSink sink_;
bool always_overscroll_;
+ MockWebWidget mock_webwidget_;
static int next_routing_id_;
DISALLOW_COPY_AND_ASSIGN(InteractiveRenderWidget);
@@ -101,11 +136,16 @@ class RenderWidgetUnittest : public testing::Test {
InteractiveRenderWidget* widget() const { return widget_.get(); }
+ const base::HistogramTester& histogram_tester() const {
+ return histogram_tester_;
+ }
+
private:
MockRenderProcess render_process_;
MockRenderThread render_thread_;
FakeCompositorDependencies compositor_deps_;
scoped_refptr<InteractiveRenderWidget> widget_;
+ base::HistogramTester histogram_tester_;
DISALLOW_COPY_AND_ASSIGN(RenderWidgetUnittest);
};
@@ -114,6 +154,10 @@ TEST_F(RenderWidgetUnittest, TouchHitTestSinglePoint) {
SyntheticWebTouchEvent touch;
touch.PressPoint(10, 10);
+ EXPECT_CALL(*widget()->mock_webwidget(), handleInputEvent(_))
+ .WillRepeatedly(
+ ::testing::Return(blink::WebInputEventResult::NotHandled));
+
widget()->SendInputEvent(touch);
ASSERT_EQ(1u, widget()->sink()->message_count());
@@ -132,6 +176,10 @@ TEST_F(RenderWidgetUnittest, TouchHitTestSinglePoint) {
rects.push_back(gfx::Rect(25, 0, 10, 10));
widget()->SetTouchRegion(rects);
+ EXPECT_CALL(*widget()->mock_webwidget(), handleInputEvent(_))
+ .WillRepeatedly(
+ ::testing::Return(blink::WebInputEventResult::NotHandled));
+
widget()->SendInputEvent(touch);
ASSERT_EQ(1u, widget()->sink()->message_count());
message = widget()->sink()->GetMessageAt(0);
@@ -151,6 +199,10 @@ TEST_F(RenderWidgetUnittest, TouchHitTestMultiplePoints) {
SyntheticWebTouchEvent touch;
touch.PressPoint(25, 25);
+ EXPECT_CALL(*widget()->mock_webwidget(), handleInputEvent(_))
+ .WillRepeatedly(
+ ::testing::Return(blink::WebInputEventResult::NotHandled));
+
widget()->SendInputEvent(touch);
ASSERT_EQ(1u, widget()->sink()->message_count());
@@ -179,6 +231,10 @@ TEST_F(RenderWidgetUnittest, TouchHitTestMultiplePoints) {
TEST_F(RenderWidgetUnittest, EventOverscroll) {
widget()->set_always_overscroll(true);
+ EXPECT_CALL(*widget()->mock_webwidget(), handleInputEvent(_))
+ .WillRepeatedly(
+ ::testing::Return(blink::WebInputEventResult::NotHandled));
+
blink::WebGestureEvent scroll;
scroll.type = blink::WebInputEvent::GestureScrollUpdate;
scroll.x = -10;
@@ -221,4 +277,54 @@ TEST_F(RenderWidgetUnittest, FlingOverscroll) {
widget()->sink()->ClearMessages();
}
+TEST_F(RenderWidgetUnittest, RenderWidgetInputEventUmaMetrics) {
+ SyntheticWebTouchEvent touch;
+ touch.PressPoint(10, 10);
+
+ EXPECT_CALL(*widget()->mock_webwidget(), handleInputEvent(_))
+ .Times(4)
+ .WillRepeatedly(
+ ::testing::Return(blink::WebInputEventResult::NotHandled));
+
+ widget()->SendInputEvent(touch);
+ histogram_tester().ExpectBucketCount(EVENT_LISTENER_RESULT_HISTOGRAM,
+ PASSIVE_LISTENER_UMA_ENUM_CANCELABLE, 1);
+
+ touch.dispatchType = blink::WebInputEvent::DispatchType::EventNonBlocking;
+ widget()->SendInputEvent(touch);
+ histogram_tester().ExpectBucketCount(EVENT_LISTENER_RESULT_HISTOGRAM,
+ PASSIVE_LISTENER_UMA_ENUM_UNCANCELABLE,
+ 1);
+
+ touch.dispatchType =
+ blink::WebInputEvent::DispatchType::ListenersNonBlockingPassive;
+ widget()->SendInputEvent(touch);
+ histogram_tester().ExpectBucketCount(EVENT_LISTENER_RESULT_HISTOGRAM,
+ PASSIVE_LISTENER_UMA_ENUM_PASSIVE, 1);
+
+ touch.dispatchType =
+ blink::WebInputEvent::DispatchType::ListenersForcedNonBlockingPassive;
+ widget()->SendInputEvent(touch);
+ histogram_tester().ExpectBucketCount(
+ EVENT_LISTENER_RESULT_HISTOGRAM,
+ PASSIVE_LISTENER_UMA_ENUM_FORCED_NON_BLOCKING, 1);
+
+ EXPECT_CALL(*widget()->mock_webwidget(), handleInputEvent(_))
+ .WillOnce(
+ ::testing::Return(blink::WebInputEventResult::HandledSuppressed));
+ touch.dispatchType = blink::WebInputEvent::DispatchType::Blocking;
+ widget()->SendInputEvent(touch);
+ histogram_tester().ExpectBucketCount(EVENT_LISTENER_RESULT_HISTOGRAM,
+ PASSIVE_LISTENER_UMA_ENUM_SUPPRESSED, 1);
+
+ EXPECT_CALL(*widget()->mock_webwidget(), handleInputEvent(_))
+ .WillOnce(
+ ::testing::Return(blink::WebInputEventResult::HandledApplication));
+ touch.dispatchType = blink::WebInputEvent::DispatchType::Blocking;
+ widget()->SendInputEvent(touch);
+ histogram_tester().ExpectBucketCount(
+ EVENT_LISTENER_RESULT_HISTOGRAM,
+ PASSIVE_LISTENER_UMA_ENUM_CANCELABLE_AND_CANCELED, 1);
+}
+
} // namespace content
diff --git a/chromium/content/renderer/renderer.sb b/chromium/content/renderer/renderer.sb
index 7e07985a2f1..10b6b75419b 100644
--- a/chromium/content/renderer/renderer.sb
+++ b/chromium/content/renderer/renderer.sb
@@ -34,9 +34,13 @@
(allow file-read-metadata (regex #"^/(private/)?etc$"))
; https://crbug.com/508935
+; TODO(tkent): Remove this section when we drop 'results' attribute support.
+; https://crbug.com/590117
(if (param-true? elcap-or-later)
(allow file-read*
+ (literal "/usr/lib/libcrypto.0.9.8.dylib")
(literal "/usr/lib/libcsfde.dylib")
(literal "/usr/lib/libcurl.4.dylib")
(literal "/usr/lib/libCoreStorage.dylib")
+ (literal "/usr/lib/libsasl2.2.dylib")
(literal "/usr/lib/libutil.dylib")))
diff --git a/chromium/content/renderer/renderer_blink_platform_impl.cc b/chromium/content/renderer/renderer_blink_platform_impl.cc
index c4d4fed5409..45da15f57e8 100644
--- a/chromium/content/renderer/renderer_blink_platform_impl.cc
+++ b/chromium/content/renderer/renderer_blink_platform_impl.cc
@@ -29,10 +29,10 @@
#include "content/child/file_info_util.h"
#include "content/child/fileapi/webfilesystem_impl.h"
#include "content/child/indexed_db/webidbfactory_impl.h"
-#include "content/child/npapi/npobject_util.h"
#include "content/child/quota_dispatcher.h"
#include "content/child/quota_message_filter.h"
#include "content/child/simple_webmimeregistry_impl.h"
+#include "content/child/storage_util.h"
#include "content/child/thread_safe_sender.h"
#include "content/child/web_database_observer_impl.h"
#include "content/child/web_url_loader_impl.h"
@@ -42,29 +42,32 @@
#include "content/common/file_utilities_messages.h"
#include "content/common/frame_messages.h"
#include "content/common/gpu/client/context_provider_command_buffer.h"
-#include "content/common/gpu/client/gpu_channel_host.h"
#include "content/common/gpu/client/webgraphicscontext3d_command_buffer_impl.h"
-#include "content/common/gpu/gpu_process_launch_causes.h"
+#include "content/common/gpu_process_launch_causes.h"
#include "content/common/mime_registry_messages.h"
#include "content/common/render_process_messages.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/service_registry.h"
#include "content/public/common/webplugininfo.h"
#include "content/public/renderer/content_renderer_client.h"
-#include "content/renderer/battery_status/battery_status_dispatcher.h"
+#include "content/public/renderer/media_stream_utils.h"
#include "content/renderer/cache_storage/webserviceworkercachestorage_impl.h"
#include "content/renderer/device_sensors/device_light_event_pump.h"
#include "content/renderer/device_sensors/device_motion_event_pump.h"
#include "content/renderer/device_sensors/device_orientation_absolute_event_pump.h"
#include "content/renderer/device_sensors/device_orientation_event_pump.h"
+#include "content/renderer/dom_storage/local_storage_cached_areas.h"
+#include "content/renderer/dom_storage/local_storage_namespace.h"
#include "content/renderer/dom_storage/webstoragenamespace_impl.h"
#include "content/renderer/gamepad_shared_memory_reader.h"
#include "content/renderer/media/audio_decoder.h"
#include "content/renderer/media/canvas_capture_handler.h"
+#include "content/renderer/media/html_video_element_capturer_source.h"
#include "content/renderer/media/media_recorder_handler.h"
#include "content/renderer/media/renderer_webaudiodevice_impl.h"
#include "content/renderer/media/renderer_webmidiaccessor_impl.h"
#include "content/renderer/media/rtc_certificate_generator.h"
+#include "content/renderer/mojo/blink_service_registry_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/renderer_clipboard_delegate.h"
#include "content/renderer/screen_orientation/screen_orientation_observer.h"
@@ -72,16 +75,18 @@
#include "content/renderer/webgraphicscontext3d_provider_impl.h"
#include "content/renderer/webpublicsuffixlist_impl.h"
#include "gpu/config/gpu_info.h"
+#include "gpu/ipc/client/gpu_channel_host.h"
#include "ipc/ipc_sync_message_filter.h"
#include "media/audio/audio_output_device.h"
#include "media/base/audio_hardware_config.h"
-#include "media/base/key_systems.h"
#include "media/base/mime_util.h"
#include "media/blink/webcontentdecryptionmodule_impl.h"
#include "media/filters/stream_parser_factory.h"
#include "storage/common/database/database_identifier.h"
#include "storage/common/quota/quota_types.h"
-#include "third_party/WebKit/public/platform/WebBatteryStatusListener.h"
+#include "third_party/WebKit/public/platform/BlameContext.h"
+#include "third_party/WebKit/public/platform/FilePathConversion.h"
+#include "third_party/WebKit/public/platform/URLConversion.h"
#include "third_party/WebKit/public/platform/WebBlobRegistry.h"
#include "third_party/WebKit/public/platform/WebDeviceLightListener.h"
#include "third_party/WebKit/public/platform/WebFileInfo.h"
@@ -89,6 +94,7 @@
#include "third_party/WebKit/public/platform/WebMediaStreamCenter.h"
#include "third_party/WebKit/public/platform/WebMediaStreamCenterClient.h"
#include "third_party/WebKit/public/platform/WebPluginListBuilder.h"
+#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/platform/WebVector.h"
#include "third_party/WebKit/public/platform/modules/device_orientation/WebDeviceMotionListener.h"
@@ -148,7 +154,9 @@ using blink::WebGamepad;
using blink::WebGamepads;
using blink::WebIDBFactory;
using blink::WebMIDIAccessor;
+using blink::WebMediaPlayer;
using blink::WebMediaRecorderHandler;
+using blink::WebMediaStream;
using blink::WebMediaStreamCenter;
using blink::WebMediaStreamCenterClient;
using blink::WebMediaStreamTrack;
@@ -171,9 +179,6 @@ base::LazyInstance<blink::WebDeviceMotionData>::Leaky
g_test_device_motion_data = LAZY_INSTANCE_INITIALIZER;
base::LazyInstance<blink::WebDeviceOrientationData>::Leaky
g_test_device_orientation_data = LAZY_INSTANCE_INITIALIZER;
-// Set in startListening() when running layout tests, unset in stopListening(),
-// not owned by us.
-blink::WebBatteryStatusListener* g_test_battery_status_listener = nullptr;
} // namespace
@@ -184,8 +189,7 @@ class RendererBlinkPlatformImpl::MimeRegistry
public:
blink::WebMimeRegistry::SupportsType supportsMediaMIMEType(
const blink::WebString& mime_type,
- const blink::WebString& codecs,
- const blink::WebString& key_system) override;
+ const blink::WebString& codecs) override;
bool supportsMediaSourceMIMEType(const blink::WebString& mime_type,
const blink::WebString& codecs) override;
blink::WebString mimeTypeForExtension(
@@ -218,9 +222,9 @@ class RendererBlinkPlatformImpl::SandboxSupport
blink::WebUChar32 character,
const char* preferred_locale,
blink::WebFallbackFont* fallbackFont) override;
- void getRenderStyleForStrike(const char* family,
- int sizeAndStyle,
- blink::WebFontRenderStyle* out) override;
+ void getWebFontRenderStyleForStrike(const char* family,
+ int sizeAndStyle,
+ blink::WebFontRenderStyle* out) override;
private:
// WebKit likes to ask us for the correct font family to use for a set of
@@ -235,7 +239,8 @@ class RendererBlinkPlatformImpl::SandboxSupport
//------------------------------------------------------------------------------
RendererBlinkPlatformImpl::RendererBlinkPlatformImpl(
- scheduler::RendererScheduler* renderer_scheduler)
+ scheduler::RendererScheduler* renderer_scheduler,
+ base::WeakPtr<ServiceRegistry> service_registry)
: BlinkPlatformImpl(renderer_scheduler->DefaultTaskRunner()),
main_thread_(renderer_scheduler->CreateMainThread()),
clipboard_delegate_(new RendererClipboardDelegate),
@@ -246,7 +251,8 @@ RendererBlinkPlatformImpl::RendererBlinkPlatformImpl(
default_task_runner_(renderer_scheduler->DefaultTaskRunner()),
loading_task_runner_(renderer_scheduler->LoadingTaskRunner()),
web_scrollbar_behavior_(new WebScrollbarBehaviorImpl),
- renderer_scheduler_(renderer_scheduler) {
+ renderer_scheduler_(renderer_scheduler),
+ blink_service_registry_(new BlinkServiceRegistryImpl(service_registry)) {
#if !defined(OS_ANDROID) && !defined(OS_WIN)
if (g_sandbox_enabled && sandboxEnabled()) {
sandbox_support_.reset(new RendererBlinkPlatformImpl::SandboxSupport);
@@ -260,15 +266,21 @@ RendererBlinkPlatformImpl::RendererBlinkPlatformImpl(
sync_message_filter_ = ChildThreadImpl::current()->sync_message_filter();
thread_safe_sender_ = ChildThreadImpl::current()->thread_safe_sender();
quota_message_filter_ = ChildThreadImpl::current()->quota_message_filter();
- blob_registry_.reset(new WebBlobRegistryImpl(thread_safe_sender_.get()));
+ blob_registry_.reset(new WebBlobRegistryImpl(
+ RenderThreadImpl::current()->GetIOMessageLoopProxy().get(),
+ base::ThreadTaskRunnerHandle::Get(), thread_safe_sender_.get()));
web_idb_factory_.reset(new WebIDBFactoryImpl(thread_safe_sender_.get()));
web_database_observer_impl_.reset(
new WebDatabaseObserverImpl(sync_message_filter_.get()));
}
+
+ top_level_blame_context_.Initialize();
+ renderer_scheduler_->SetTopLevelBlameContext(&top_level_blame_context_);
}
RendererBlinkPlatformImpl::~RendererBlinkPlatformImpl() {
WebFileSystemImpl::DeleteThreadSpecificInstance();
+ renderer_scheduler_->SetTopLevelBlameContext(nullptr);
}
void RendererBlinkPlatformImpl::Shutdown() {
@@ -282,27 +294,13 @@ void RendererBlinkPlatformImpl::Shutdown() {
//------------------------------------------------------------------------------
-double RendererBlinkPlatformImpl::currentTimeSeconds() {
- return renderer_scheduler_->CurrentTimeSeconds();
-}
-
-double RendererBlinkPlatformImpl::monotonicallyIncreasingTimeSeconds() {
- return renderer_scheduler_->MonotonicallyIncreasingTimeSeconds();
-}
-
-//------------------------------------------------------------------------------
-
blink::WebURLLoader* RendererBlinkPlatformImpl::createURLLoader() {
ChildThreadImpl* child_thread = ChildThreadImpl::current();
// There may be no child thread in RenderViewTests. These tests can still use
// data URLs to bypass the ResourceDispatcher.
- scoped_ptr<scheduler::WebTaskRunnerImpl> task_runner(
- new scheduler::WebTaskRunnerImpl(
- loading_task_runner_->BelongsToCurrentThread()
- ? loading_task_runner_ : base::ThreadTaskRunnerHandle::Get()));
return new content::WebURLLoaderImpl(
child_thread ? child_thread->resource_dispatcher() : NULL,
- std::move(task_runner));
+ make_scoped_ptr(currentThread()->getWebTaskRunner()->clone()));
}
blink::WebThread* RendererBlinkPlatformImpl::currentThread() {
@@ -311,6 +309,10 @@ blink::WebThread* RendererBlinkPlatformImpl::currentThread() {
return BlinkPlatformImpl::currentThread();
}
+blink::BlameContext* RendererBlinkPlatformImpl::topLevelBlameContext() {
+ return &top_level_blame_context_;
+}
+
blink::WebClipboard* RendererBlinkPlatformImpl::clipboard() {
blink::WebClipboard* clipboard =
GetContentClient()->renderer()->OverrideWebClipboard();
@@ -425,6 +427,15 @@ void RendererBlinkPlatformImpl::suddenTerminationChanged(bool enabled) {
}
WebStorageNamespace* RendererBlinkPlatformImpl::createLocalStorageNamespace() {
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kMojoLocalStorage)) {
+ if (!local_storage_cached_areas_) {
+ local_storage_cached_areas_.reset(new LocalStorageCachedAreas(
+ RenderThreadImpl::current()->GetStoragePartitionService()));
+ }
+ return new LocalStorageNamespace(local_storage_cached_areas_.get());
+ }
+
return new WebStorageNamespaceImpl();
}
@@ -438,11 +449,9 @@ WebIDBFactory* RendererBlinkPlatformImpl::idbFactory() {
//------------------------------------------------------------------------------
blink::WebServiceWorkerCacheStorage* RendererBlinkPlatformImpl::cacheStorage(
- const WebString& origin_identifier) {
- const GURL origin =
- storage::GetOriginFromIdentifier(origin_identifier.utf8());
+ const blink::WebSecurityOrigin& security_origin) {
return new WebServiceWorkerCacheStorageImpl(thread_safe_sender_.get(),
- origin);
+ security_origin);
}
//------------------------------------------------------------------------------
@@ -451,36 +460,20 @@ WebFileSystem* RendererBlinkPlatformImpl::fileSystem() {
return WebFileSystemImpl::ThreadSpecificInstance(default_task_runner_);
}
+WebString RendererBlinkPlatformImpl::fileSystemCreateOriginIdentifier(
+ const blink::WebSecurityOrigin& origin) {
+ return WebString::fromUTF8(storage::GetIdentifierFromOrigin(
+ WebSecurityOriginToGURL(origin)));
+}
+
//------------------------------------------------------------------------------
WebMimeRegistry::SupportsType
RendererBlinkPlatformImpl::MimeRegistry::supportsMediaMIMEType(
const WebString& mime_type,
- const WebString& codecs,
- const WebString& key_system) {
+ const WebString& codecs) {
const std::string mime_type_ascii = ToASCIIOrEmpty(mime_type);
- if (!key_system.isEmpty()) {
- // Check whether the key system is supported with the mime_type and codecs.
-
- // Chromium only supports ASCII parameters.
- if (!base::IsStringASCII(key_system))
- return IsNotSupported;
-
- std::string key_system_ascii =
- media::GetUnprefixedKeySystemName(base::UTF16ToASCII(
- base::StringPiece16(key_system)));
- std::vector<std::string> codec_vector;
- media::ParseCodecString(ToASCIIOrEmpty(codecs), &codec_vector, true);
-
- if (!media::PrefixedIsSupportedKeySystemWithMediaMimeType(
- mime_type_ascii, codec_vector, key_system_ascii)) {
- return IsNotSupported;
- }
-
- // Continue processing the mime_type and codecs.
- }
-
std::vector<std::string> codec_vector;
media::ParseCodecString(ToASCIIOrEmpty(codecs), &codec_vector, false);
return static_cast<WebMimeRegistry::SupportsType>(
@@ -501,15 +494,12 @@ bool RendererBlinkPlatformImpl::MimeRegistry::supportsMediaSourceMIMEType(
WebString RendererBlinkPlatformImpl::MimeRegistry::mimeTypeForExtension(
const WebString& file_extension) {
- if (IsPluginProcess())
- return SimpleWebMimeRegistryImpl::mimeTypeForExtension(file_extension);
-
// The sandbox restricts our access to the registry, so we need to proxy
// these calls over to the browser process.
std::string mime_type;
RenderThread::Get()->Send(
new MimeRegistryMsg_GetMimeTypeFromExtension(
- base::FilePath::FromUTF16Unsafe(file_extension).value(), &mime_type));
+ blink::WebStringToFilePath(file_extension).value(), &mime_type));
return base::ASCIIToUTF16(mime_type);
}
@@ -521,7 +511,7 @@ bool RendererBlinkPlatformImpl::FileUtilities::getFileInfo(
base::File::Info file_info;
base::File::Error status = base::File::FILE_ERROR_MAX;
if (!SendSyncMessageFromAnyThread(new FileUtilitiesMsg_GetFileInfo(
- base::FilePath::FromUTF16Unsafe(path), &file_info, &status)) ||
+ blink::WebStringToFilePath(path), &file_info, &status)) ||
status != base::File::FILE_OK) {
return false;
}
@@ -595,7 +585,7 @@ void RendererBlinkPlatformImpl::SandboxSupport::getFallbackFontForCharacter(
unicode_font_families_.insert(std::make_pair(character, *fallbackFont));
}
-void RendererBlinkPlatformImpl::SandboxSupport::getRenderStyleForStrike(
+void RendererBlinkPlatformImpl::SandboxSupport::getWebFontRenderStyleForStrike(
const char* family,
int sizeAndStyle,
blink::WebFontRenderStyle* out) {
@@ -633,9 +623,12 @@ long long RendererBlinkPlatformImpl::databaseGetFileSize(
}
long long RendererBlinkPlatformImpl::databaseGetSpaceAvailableForOrigin(
- const WebString& origin_identifier) {
- return DatabaseUtil::DatabaseGetSpaceAvailable(origin_identifier,
- sync_message_filter_.get());
+ const blink::WebSecurityOrigin& origin) {
+ // TODO(jsbell): Pass url::Origin over IPC instead of database
+ // identifier/GURL. https://crbug.com/591482
+ return DatabaseUtil::DatabaseGetSpaceAvailable(WebString::fromUTF8(
+ storage::GetIdentifierFromOrigin(WebSecurityOriginToGURL(origin))),
+ sync_message_filter_.get());
}
bool RendererBlinkPlatformImpl::databaseSetFileSize(
@@ -644,10 +637,16 @@ bool RendererBlinkPlatformImpl::databaseSetFileSize(
vfs_file_name, size, sync_message_filter_.get());
}
+WebString RendererBlinkPlatformImpl::databaseCreateOriginIdentifier(
+ const blink::WebSecurityOrigin& origin) {
+ return WebString::fromUTF8(storage::GetIdentifierFromOrigin(
+ WebSecurityOriginToGURL(origin)));
+}
+
bool RendererBlinkPlatformImpl::canAccelerate2dCanvas() {
RenderThreadImpl* thread = RenderThreadImpl::current();
- GpuChannelHost* host = thread->EstablishGpuChannelSync(
- CAUSE_FOR_GPU_LAUNCH_CANVAS_2D);
+ gpu::GpuChannelHost* host =
+ thread->EstablishGpuChannelSync(CAUSE_FOR_GPU_LAUNCH_CANVAS_2D);
if (!host)
return false;
@@ -690,7 +689,8 @@ WebAudioDevice* RendererBlinkPlatformImpl::createAudioDevice(
unsigned channels,
double sample_rate,
WebAudioDevice::RenderCallback* callback,
- const blink::WebString& input_device_id) {
+ const blink::WebString& input_device_id,
+ const blink::WebSecurityOrigin& security_origin) {
// Use a mock for testing.
blink::WebAudioDevice* mock_device =
GetContentClient()->renderer()->OverrideCreateAudioDevice(sample_rate);
@@ -749,7 +749,8 @@ WebAudioDevice* RendererBlinkPlatformImpl::createAudioDevice(
buffer_size);
params.set_channels_for_discrete(channels);
- return new RendererWebAudioDeviceImpl(params, callback, session_id);
+ return new RendererWebAudioDeviceImpl(
+ params, callback, session_id, static_cast<url::Origin>(security_origin));
}
bool RendererBlinkPlatformImpl::loadAudioResource(
@@ -943,31 +944,34 @@ WebCanvasCaptureHandler* RendererBlinkPlatformImpl::createCanvasCaptureHandler(
//------------------------------------------------------------------------------
-blink::WebSpeechSynthesizer* RendererBlinkPlatformImpl::createSpeechSynthesizer(
- blink::WebSpeechSynthesizerClient* client) {
- return GetContentClient()->renderer()->OverrideSpeechSynthesizer(client);
+void RendererBlinkPlatformImpl::createHTMLVideoElementCapturer(
+ WebMediaStream* web_media_stream,
+ WebMediaPlayer* web_media_player) {
+#if defined(ENABLE_WEBRTC)
+ DCHECK(web_media_stream);
+ DCHECK(web_media_player);
+ AddVideoTrackToMediaStream(
+ HtmlVideoElementCapturerSource::CreateFromWebMediaPlayerImpl(
+ web_media_player,
+ content::RenderThread::Get()->GetIOMessageLoopProxy()),
+ false, // is_remote
+ false, // is_readonly
+ web_media_stream);
+#endif
}
//------------------------------------------------------------------------------
-blink::WebGraphicsContext3D*
-RendererBlinkPlatformImpl::createOffscreenGraphicsContext3D(
- const blink::WebGraphicsContext3D::Attributes& attributes) {
- return createOffscreenGraphicsContext3D(attributes, NULL);
+blink::WebSpeechSynthesizer* RendererBlinkPlatformImpl::createSpeechSynthesizer(
+ blink::WebSpeechSynthesizerClient* client) {
+ return GetContentClient()->renderer()->OverrideSpeechSynthesizer(client);
}
-blink::WebGraphicsContext3D*
-RendererBlinkPlatformImpl::createOffscreenGraphicsContext3D(
- const blink::WebGraphicsContext3D::Attributes& attributes,
- blink::WebGraphicsContext3D* share_context) {
- blink::WebGraphicsContext3D::WebGraphicsInfo gl_info;
- return createOffscreenGraphicsContext3D(attributes, share_context, &gl_info);
-}
+//------------------------------------------------------------------------------
static void Collect3DContextInformationOnFailure(
- blink::WebGraphicsContext3D* share_context,
- blink::WebGraphicsContext3D::WebGraphicsInfo* gl_info,
- GpuChannelHost* host) {
+ blink::Platform::GraphicsInfo* gl_info,
+ gpu::GpuChannelHost* host) {
DCHECK(gl_info);
std::string error_message("OffscreenContext Creation failed, ");
if (host) {
@@ -1003,44 +1007,67 @@ static void Collect3DContextInformationOnFailure(
}
}
-blink::WebGraphicsContext3D*
-RendererBlinkPlatformImpl::createOffscreenGraphicsContext3D(
- const blink::WebGraphicsContext3D::Attributes& attributes,
- blink::WebGraphicsContext3D* share_context,
- blink::WebGraphicsContext3D::WebGraphicsInfo* gl_info) {
+blink::WebGraphicsContext3DProvider*
+RendererBlinkPlatformImpl::createOffscreenGraphicsContext3DProvider(
+ const blink::Platform::ContextAttributes& web_attributes,
+ const blink::WebURL& top_document_web_url,
+ blink::WebGraphicsContext3DProvider* share_provider,
+ blink::Platform::GraphicsInfo* gl_info) {
DCHECK(gl_info);
if (!RenderThreadImpl::current()) {
std::string error_message("Failed to run in Current RenderThreadImpl");
gl_info->errorMessage = WebString::fromUTF8(error_message);
- return NULL;
+ return nullptr;
}
- scoped_refptr<GpuChannelHost> gpu_channel_host(
+ scoped_refptr<gpu::GpuChannelHost> gpu_channel_host(
RenderThreadImpl::current()->EstablishGpuChannelSync(
CAUSE_FOR_GPU_LAUNCH_WEBGRAPHICSCONTEXT3DCOMMANDBUFFERIMPL_INITIALIZE));
+ WebGraphicsContext3DCommandBufferImpl* share_context =
+ share_provider ? static_cast<WebGraphicsContext3DCommandBufferImpl*>(
+ share_provider->context3d())
+ : nullptr;
+
+ // This is an offscreen context, which doesn't use the default frame buffer,
+ // so don't request any alpha, depth, stencil, antialiasing.
+ gpu::gles2::ContextCreationAttribHelper attributes;
+ attributes.alpha_size = -1;
+ attributes.depth_size = 0;
+ attributes.stencil_size = 0;
+ attributes.samples = 0;
+ attributes.sample_buffers = 0;
+ attributes.bind_generates_resource = false;
+
+ attributes.fail_if_major_perf_caveat =
+ web_attributes.failIfMajorPerformanceCaveat;
+ DCHECK_LE(web_attributes.webGLVersion, 2u);
+ if (web_attributes.webGLVersion == 1)
+ attributes.context_type = gpu::gles2::CONTEXT_TYPE_WEBGL1;
+ else if (web_attributes.webGLVersion == 2)
+ attributes.context_type = gpu::gles2::CONTEXT_TYPE_WEBGL2;
+
+ bool share_resources = false;
+ bool automatic_flushes = true;
+ // Prefer discrete GPU for WebGL.
+ gfx::GpuPreference gpu_preference = gfx::PreferDiscreteGpu;
WebGraphicsContext3DCommandBufferImpl::SharedMemoryLimits limits;
- bool lose_context_when_out_of_memory = false;
+
scoped_ptr<WebGraphicsContext3DCommandBufferImpl> context(
WebGraphicsContext3DCommandBufferImpl::CreateOffscreenContext(
- gpu_channel_host.get(),
- attributes,
- lose_context_when_out_of_memory,
- GURL(attributes.topDocumentURL),
- limits,
- static_cast<WebGraphicsContext3DCommandBufferImpl*>(share_context)));
-
- // Most likely the GPU process exited and the attempt to reconnect to it
- // failed. Need to try to restore the context again later.
- if (!context || !context->InitializeOnCurrentThread() ||
- gl_info->testFailContext) {
+ gpu_channel_host.get(), attributes, gpu_preference, share_resources,
+ automatic_flushes, GURL(top_document_web_url), limits,
+ share_context));
+ scoped_refptr<ContextProviderCommandBuffer> provider =
+ ContextProviderCommandBuffer::Create(std::move(context),
+ RENDERER_MAINTHREAD_CONTEXT);
+ if (!provider || !provider->BindToCurrentThread()) {
// Collect Graphicsinfo if there is a context failure or it is failed
// purposefully in case of layout tests.
- Collect3DContextInformationOnFailure(share_context, gl_info,
- gpu_channel_host.get());
- return NULL;
+ Collect3DContextInformationOnFailure(gl_info, gpu_channel_host.get());
+ return nullptr;
}
- return context.release();
+ return new WebGraphicsContext3DProviderImpl(std::move(provider));
}
//------------------------------------------------------------------------------
@@ -1049,9 +1076,9 @@ blink::WebGraphicsContext3DProvider*
RendererBlinkPlatformImpl::createSharedOffscreenGraphicsContext3DProvider() {
scoped_refptr<cc_blink::ContextProviderWebContext> provider =
RenderThreadImpl::current()->SharedMainThreadContextProvider();
- if (!provider.get())
- return NULL;
- return new WebGraphicsContext3DProviderImpl(provider);
+ if (!provider)
+ return nullptr;
+ return new WebGraphicsContext3DProviderImpl(std::move(provider));
}
//------------------------------------------------------------------------------
@@ -1063,9 +1090,8 @@ blink::WebCompositorSupport* RendererBlinkPlatformImpl::compositorSupport() {
//------------------------------------------------------------------------------
blink::WebString RendererBlinkPlatformImpl::convertIDNToUnicode(
- const blink::WebString& host,
- const blink::WebString& languages) {
- return url_formatter::IDNToUnicode(host.utf8(), languages.utf8());
+ const blink::WebString& host) {
+ return url_formatter::IDNToUnicode(host.utf8());
}
//------------------------------------------------------------------------------
@@ -1165,28 +1191,18 @@ RendererBlinkPlatformImpl::CreatePlatformEventObserverFromType(
void RendererBlinkPlatformImpl::SetPlatformEventObserverForTesting(
blink::WebPlatformEventType type,
scoped_ptr<PlatformEventObserverBase> observer) {
- DCHECK(type != blink::WebPlatformEventTypeBattery);
-
if (platform_event_observers_.Lookup(type))
platform_event_observers_.Remove(type);
platform_event_observers_.AddWithID(observer.release(), type);
}
+blink::ServiceRegistry* RendererBlinkPlatformImpl::serviceRegistry() {
+ return blink_service_registry_.get();
+}
+
void RendererBlinkPlatformImpl::startListening(
blink::WebPlatformEventType type,
blink::WebPlatformEventListener* listener) {
- if (type == blink::WebPlatformEventTypeBattery) {
- if (RenderThreadImpl::current() &&
- RenderThreadImpl::current()->layout_test_mode()) {
- g_test_battery_status_listener =
- static_cast<blink::WebBatteryStatusListener*>(listener);
- } else {
- battery_status_dispatcher_.reset(new BatteryStatusDispatcher(
- static_cast<blink::WebBatteryStatusListener*>(listener)));
- }
- return;
- }
-
PlatformEventObserverBase* observer = platform_event_observers_.Lookup(type);
if (!observer) {
observer = CreatePlatformEventObserverFromType(type);
@@ -1246,12 +1262,6 @@ void RendererBlinkPlatformImpl::SendFakeDeviceEventDataForTesting(
void RendererBlinkPlatformImpl::stopListening(
blink::WebPlatformEventType type) {
- if (type == blink::WebPlatformEventTypeBattery) {
- g_test_battery_status_listener = nullptr;
- battery_status_dispatcher_.reset();
- return;
- }
-
PlatformEventObserverBase* observer = platform_event_observers_.Lookup(type);
if (!observer)
return;
@@ -1276,11 +1286,9 @@ void RendererBlinkPlatformImpl::queryStorageUsageAndQuota(
//------------------------------------------------------------------------------
-void RendererBlinkPlatformImpl::MockBatteryStatusChangedForTesting(
- const blink::WebBatteryStatus& status) {
- if (!g_test_battery_status_listener)
- return;
- g_test_battery_status_listener->updateBatteryStatus(status);
+blink::WebTrialTokenValidator*
+RendererBlinkPlatformImpl::trialTokenValidator() {
+ return &trial_token_validator_;
}
} // namespace content
diff --git a/chromium/content/renderer/renderer_blink_platform_impl.h b/chromium/content/renderer/renderer_blink_platform_impl.h
index 8cdb93d4ca5..eb197f84fcf 100644
--- a/chromium/content/renderer/renderer_blink_platform_impl.h
+++ b/chromium/content/renderer/renderer_blink_platform_impl.h
@@ -16,6 +16,8 @@
#include "cc/blink/web_compositor_support_impl.h"
#include "content/child/blink_platform_impl.h"
#include "content/common/content_export.h"
+#include "content/renderer/origin_trials/web_trial_token_validator_impl.h"
+#include "content/renderer/top_level_blame_context.h"
#include "content/renderer/webpublicsuffixlist_impl.h"
#include "device/vibration/vibration_manager.mojom.h"
#include "third_party/WebKit/public/platform/WebGraphicsContext3D.h"
@@ -31,13 +33,14 @@ class SyncMessageFilter;
}
namespace blink {
-class WebBatteryStatus;
class WebCanvasCaptureHandler;
class WebDeviceMotionData;
class WebDeviceOrientationData;
class WebGraphicsContext3DProvider;
+class WebMediaPlayer;
class WebMediaRecorderHandler;
class WebMediaStream;
+class WebSecurityOrigin;
class WebServiceWorkerCacheStorage;
}
@@ -47,14 +50,16 @@ class WebThreadImplForRendererScheduler;
}
namespace content {
-class BatteryStatusDispatcher;
+class BlinkServiceRegistryImpl;
class DeviceLightEventPump;
class DeviceMotionEventPump;
class DeviceOrientationEventPump;
+class LocalStorageCachedAreas;
class PlatformEventObserverBase;
class QuotaMessageFilter;
class RendererClipboardDelegate;
class RenderView;
+class ServiceRegistry;
class ThreadSafeSender;
class WebClipboardImpl;
class WebDatabaseObserverImpl;
@@ -62,8 +67,8 @@ class WebFileSystemImpl;
class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
public:
- explicit RendererBlinkPlatformImpl(
- scheduler::RendererScheduler* renderer_scheduler);
+ RendererBlinkPlatformImpl(scheduler::RendererScheduler* renderer_scheduler,
+ base::WeakPtr<ServiceRegistry> service_registry);
~RendererBlinkPlatformImpl() override;
// Shutdown must be called just prior to shutting down blink.
@@ -104,9 +109,12 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
const blink::WebString& vfs_file_name) override;
long long databaseGetFileSize(const blink::WebString& vfs_file_name) override;
long long databaseGetSpaceAvailableForOrigin(
- const blink::WebString& origin_identifier) override;
+ const blink::WebSecurityOrigin& origin) override;
bool databaseSetFileSize(const blink::WebString& vfs_file_name,
long long size) override;
+ blink::WebString databaseCreateOriginIdentifier(
+ const blink::WebSecurityOrigin& origin) override;
+
blink::WebString signedPublicKeyAndChallengeString(
unsigned key_size_index,
const blink::WebString& challenge,
@@ -119,8 +127,11 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
blink::WebScrollbarBehavior* scrollbarBehavior() override;
blink::WebIDBFactory* idbFactory() override;
blink::WebServiceWorkerCacheStorage* cacheStorage(
- const blink::WebString& origin_identifier) override;
+ const blink::WebSecurityOrigin& security_origin) override;
blink::WebFileSystem* fileSystem() override;
+ blink::WebString fileSystemCreateOriginIdentifier(
+ const blink::WebSecurityOrigin& origin) override;
+
bool canAccelerate2dCanvas() override;
bool isThreadedCompositingEnabled() override;
bool isThreadedAnimationEnabled() override;
@@ -135,7 +146,8 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
unsigned channels,
double sample_rate,
blink::WebAudioDevice::RenderCallback* callback,
- const blink::WebString& input_device_id) override;
+ const blink::WebString& input_device_id,
+ const blink::WebSecurityOrigin& security_origin) override;
bool loadAudioResource(blink::WebAudioBus* destination_bus,
const char* audio_file_data,
@@ -156,21 +168,19 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
const blink::WebSize& size,
double frame_rate,
blink::WebMediaStreamTrack* track) override;
- blink::WebGraphicsContext3D* createOffscreenGraphicsContext3D(
- const blink::WebGraphicsContext3D::Attributes& attributes) override;
- blink::WebGraphicsContext3D* createOffscreenGraphicsContext3D(
- const blink::WebGraphicsContext3D::Attributes& attributes,
- blink::WebGraphicsContext3D* share_context) override;
- blink::WebGraphicsContext3D* createOffscreenGraphicsContext3D(
- const blink::WebGraphicsContext3D::Attributes& attributes,
- blink::WebGraphicsContext3D* share_context,
- blink::WebGraphicsContext3D::WebGraphicsInfo* gl_info) override;
+ void createHTMLVideoElementCapturer(
+ blink::WebMediaStream* web_media_stream,
+ blink::WebMediaPlayer* web_media_player) override;
+ blink::WebGraphicsContext3DProvider* createOffscreenGraphicsContext3DProvider(
+ const blink::Platform::ContextAttributes& attributes,
+ const blink::WebURL& top_document_web_url,
+ blink::WebGraphicsContext3DProvider* share_provider,
+ blink::Platform::GraphicsInfo* gl_info) override;
blink::WebGraphicsContext3DProvider*
createSharedOffscreenGraphicsContext3DProvider() override;
blink::WebCompositorSupport* compositorSupport() override;
- blink::WebString convertIDNToUnicode(
- const blink::WebString& host,
- const blink::WebString& languages) override;
+ blink::WebString convertIDNToUnicode(const blink::WebString& host) override;
+ blink::ServiceRegistry* serviceRegistry() override;
void startListening(blink::WebPlatformEventType,
blink::WebPlatformEventListener*) override;
void stopListening(blink::WebPlatformEventType) override;
@@ -180,11 +190,12 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
void vibrate(unsigned int milliseconds) override;
void cancelVibration() override;
blink::WebThread* currentThread() override;
+ blink::BlameContext* topLevelBlameContext() override;
void recordRappor(const char* metric,
const blink::WebString& sample) override;
void recordRapporURL(const char* metric, const blink::WebURL& url) override;
- double currentTimeSeconds() override;
- double monotonicallyIncreasingTimeSeconds() override;
+
+ blink::WebTrialTokenValidator* trialTokenValidator() override;
// Set the PlatformEventObserverBase in |platform_event_observers_| associated
// with |type| to |observer|. If there was already an observer associated to
@@ -213,10 +224,6 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
static void SetMockDeviceOrientationDataForTesting(
const blink::WebDeviceOrientationData& data);
- // Notifies blink::WebBatteryStatusListener that battery status has changed.
- void MockBatteryStatusChangedForTesting(
- const blink::WebBatteryStatus& status);
-
WebDatabaseObserverImpl* web_database_observer_impl() {
return web_database_observer_impl_.get();
}
@@ -283,14 +290,19 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
scoped_ptr<blink::WebScrollbarBehavior> web_scrollbar_behavior_;
- scoped_ptr<BatteryStatusDispatcher> battery_status_dispatcher_;
-
// Handle to the Vibration mojo service.
device::VibrationManagerPtr vibration_manager_;
IDMap<PlatformEventObserverBase, IDMapOwnPointer> platform_event_observers_;
scheduler::RendererScheduler* renderer_scheduler_; // NOT OWNED
+ TopLevelBlameContext top_level_blame_context_;
+
+ WebTrialTokenValidatorImpl trial_token_validator_;
+
+ scoped_ptr<LocalStorageCachedAreas> local_storage_cached_areas_;
+
+ scoped_ptr<BlinkServiceRegistryImpl> blink_service_registry_;
DISALLOW_COPY_AND_ASSIGN(RendererBlinkPlatformImpl);
};
diff --git a/chromium/content/renderer/renderer_main.cc b/chromium/content/renderer/renderer_main.cc
index d97f2f65482..99c55c5477e 100644
--- a/chromium/content/renderer/renderer_main.cc
+++ b/chromium/content/renderer/renderer_main.cc
@@ -9,24 +9,21 @@
#include "base/command_line.h"
#include "base/debug/debugger.h"
#include "base/debug/leak_annotations.h"
-#include "base/feature_list.h"
#include "base/i18n/rtl.h"
#include "base/message_loop/message_loop.h"
-#include "base/metrics/field_trial.h"
-#include "base/metrics/histogram.h"
+#include "base/metrics/histogram_macros.h"
#include "base/metrics/statistics_recorder.h"
#include "base/pending_task.h"
#include "base/strings/string_util.h"
#include "base/sys_info.h"
#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
#include "base/timer/hi_res_timer_manager.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "components/scheduler/renderer/renderer_scheduler.h"
-#include "components/startup_metric_utils/common/startup_metric_messages.h"
#include "content/child/child_process.h"
#include "content/common/content_constants_internal.h"
+#include "content/common/mojo/mojo_shell_connection_impl.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/main_function_params.h"
#include "content/public/renderer/content_renderer_client.h"
@@ -62,10 +59,6 @@
#include "ui/ozone/public/client_native_pixmap_factory.h"
#endif
-#if defined(MOJO_SHELL_CLIENT)
-#include "content/common/mojo/mojo_shell_connection_impl.h"
-#endif
-
namespace content {
namespace {
// This function provides some ways to test crash and assertion handling
@@ -92,18 +85,13 @@ int RendererMain(const MainFunctionParams& parameters) {
// expect synchronous events around the main loop of a thread.
TRACE_EVENT_ASYNC_BEGIN0("startup", "RendererMain", 0);
- const base::TimeTicks renderer_main_entry_time = base::TimeTicks::Now();
-
base::trace_event::TraceLog::GetInstance()->SetProcessName("Renderer");
base::trace_event::TraceLog::GetInstance()->SetProcessSortIndex(
kTraceEventRendererProcessSortIndex);
const base::CommandLine& parsed_command_line = parameters.command_line;
-#if defined(MOJO_SHELL_CLIENT)
- if (parsed_command_line.HasSwitch(switches::kEnableMojoShellConnection))
- MojoShellConnectionImpl::Create();
-#endif
+ MojoShellConnectionImpl::Create();
#if defined(OS_MACOSX)
base::mac::ScopedNSAutoreleasePool* pool = parameters.autorelease_pool;
@@ -165,25 +153,6 @@ int RendererMain(const MainFunctionParams& parameters) {
base::android::RecordChromiumAndroidLinkerRendererHistogram();
#endif
- // Initialize statistical testing infrastructure. We set the entropy provider
- // to NULL to disallow the renderer process from creating its own one-time
- // randomized trials; they should be created in the browser process.
- base::FieldTrialList field_trial_list(NULL);
- // Ensure any field trials in browser are reflected into renderer.
- if (parsed_command_line.HasSwitch(switches::kForceFieldTrials)) {
- bool result = base::FieldTrialList::CreateTrialsFromString(
- parsed_command_line.GetSwitchValueASCII(switches::kForceFieldTrials),
- base::FieldTrialList::DONT_ACTIVATE_TRIALS,
- std::set<std::string>());
- DCHECK(result);
- }
-
- scoped_ptr<base::FeatureList> feature_list(new base::FeatureList);
- feature_list->InitializeFromCommandLine(
- parsed_command_line.GetSwitchValueASCII(switches::kEnableFeatures),
- parsed_command_line.GetSwitchValueASCII(switches::kDisableFeatures));
- base::FeatureList::SetInstance(std::move(feature_list));
-
scoped_ptr<scheduler::RendererScheduler> renderer_scheduler(
scheduler::RendererScheduler::Create());
@@ -218,9 +187,6 @@ int RendererMain(const MainFunctionParams& parameters) {
RenderThreadImpl::Create(std::move(main_message_loop),
std::move(renderer_scheduler));
#endif
- RenderThreadImpl::current()->Send(
- new StartupMetricHostMsg_RecordRendererMainEntryTime(
- renderer_main_entry_time));
base::HighResolutionTimerManager hi_res_timer_manager;
@@ -233,6 +199,9 @@ int RendererMain(const MainFunctionParams& parameters) {
base::MessageLoop::current()->Run();
TRACE_EVENT_ASYNC_END0("toplevel", "RendererMain.START_MSG_LOOP", 0);
}
+
+ MojoShellConnectionImpl::Destroy();
+
#if defined(LEAK_SANITIZER)
// Run leak detection before RenderProcessImpl goes out of scope. This helps
// ignore shutdown-only leaks.
diff --git a/chromium/content/renderer/renderer_main_platform_delegate_linux.cc b/chromium/content/renderer/renderer_main_platform_delegate_linux.cc
index 4a632b3d51c..5743abd8a4f 100644
--- a/chromium/content/renderer/renderer_main_platform_delegate_linux.cc
+++ b/chromium/content/renderer/renderer_main_platform_delegate_linux.cc
@@ -30,7 +30,7 @@ void RendererMainPlatformDelegate::PlatformUninitialize() {
bool RendererMainPlatformDelegate::EnableSandbox() {
// The setuid sandbox is started in the zygote process: zygote_main_linux.cc
- // http://code.google.com/p/chromium/wiki/LinuxSUIDSandbox
+ // https://chromium.googlesource.com/chromium/src/+/master/docs/linux_suid_sandbox.md
//
// Anything else is started in InitializeSandbox().
LinuxSandbox::InitializeSandbox();
diff --git a/chromium/content/renderer/renderer_main_platform_delegate_win.cc b/chromium/content/renderer/renderer_main_platform_delegate_win.cc
index ae7e7e47f4b..25381a5efaa 100644
--- a/chromium/content/renderer/renderer_main_platform_delegate_win.cc
+++ b/chromium/content/renderer/renderer_main_platform_delegate_win.cc
@@ -14,9 +14,8 @@
#include "base/win/win_util.h"
#include "base/win/windows_version.h"
#include "content/child/dwrite_font_proxy/dwrite_font_proxy_init_win.h"
-#include "content/common/font_warmup_win.h"
+#include "content/child/font_warmup_win.h"
#include "content/public/common/content_switches.h"
-#include "content/public/common/dwrite_font_platform_win.h"
#include "content/public/common/injection_test_win.h"
#include "content/public/renderer/render_thread.h"
#include "content/renderer/render_thread_impl.h"
@@ -40,12 +39,6 @@ void SkiaPreCacheFont(const LOGFONT& logfont) {
}
}
-// Helper function to cast RenderThread to IPC::Sender so we can Bind()
-// it.
-IPC::Sender* GetRenderThreadSender() {
- return RenderThread::Get();
-}
-
} // namespace
RendererMainPlatformDelegate::RendererMainPlatformDelegate(
@@ -75,10 +68,7 @@ void RendererMainPlatformDelegate::PlatformInitialize() {
scoped_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault());
if (use_direct_write) {
- if (ShouldUseDirectWriteFontProxyFieldTrial())
- InitializeDWriteFontProxy(base::Bind(&GetRenderThreadSender));
- else
- WarmupDirectWrite();
+ InitializeDWriteFontProxy();
} else {
SkTypeface_SetEnsureLOGFONTAccessibleProc(SkiaPreCacheFont);
}
@@ -88,8 +78,7 @@ void RendererMainPlatformDelegate::PlatformInitialize() {
}
void RendererMainPlatformDelegate::PlatformUninitialize() {
- if (ShouldUseDirectWriteFontProxyFieldTrial())
- UninitializeDWriteFontProxy();
+ UninitializeDWriteFontProxy();
}
bool RendererMainPlatformDelegate::EnableSandbox() {
diff --git a/chromium/content/renderer/renderer_webapplicationcachehost_impl.cc b/chromium/content/renderer/renderer_webapplicationcachehost_impl.cc
index 42aae612c26..817d69d76d8 100644
--- a/chromium/content/renderer/renderer_webapplicationcachehost_impl.cc
+++ b/chromium/content/renderer/renderer_webapplicationcachehost_impl.cc
@@ -20,8 +20,7 @@ RendererWebApplicationCacheHostImpl::RendererWebApplicationCacheHostImpl(
WebApplicationCacheHostClient* client,
AppCacheBackend* backend)
: WebApplicationCacheHostImpl(client, backend),
- routing_id_(render_view->routing_id()) {
-}
+ routing_id_(render_view->GetRoutingID()) {}
void RendererWebApplicationCacheHostImpl::OnLogMessage(
AppCacheLogLevel log_level, const std::string& message) {
diff --git a/chromium/content/renderer/renderer_webcookiejar_impl.cc b/chromium/content/renderer/renderer_webcookiejar_impl.cc
index 1ae89b4fca0..36706a0605b 100644
--- a/chromium/content/renderer/renderer_webcookiejar_impl.cc
+++ b/chromium/content/renderer/renderer_webcookiejar_impl.cc
@@ -30,11 +30,6 @@ WebString RendererWebCookieJarImpl::cookies(
return WebString::fromUTF8(value_utf8);
}
-WebString RendererWebCookieJarImpl::cookieRequestHeaderFieldValue(
- const WebURL& url, const WebURL& first_party_for_cookies) {
- return cookies(url, first_party_for_cookies);
-}
-
bool RendererWebCookieJarImpl::cookiesEnabled(
const WebURL& url, const WebURL& first_party_for_cookies) {
bool cookies_enabled = false;
diff --git a/chromium/content/renderer/renderer_webcookiejar_impl.h b/chromium/content/renderer/renderer_webcookiejar_impl.h
index 1adbbaea2dc..dce3aeca18c 100644
--- a/chromium/content/renderer/renderer_webcookiejar_impl.h
+++ b/chromium/content/renderer/renderer_webcookiejar_impl.h
@@ -26,9 +26,6 @@ class RendererWebCookieJarImpl : public blink::WebCookieJar {
blink::WebString cookies(
const blink::WebURL& url,
const blink::WebURL& first_party_for_cookies) override;
- blink::WebString cookieRequestHeaderFieldValue(
- const blink::WebURL& url,
- const blink::WebURL& first_party_for_cookies) override;
bool cookiesEnabled(const blink::WebURL& url,
const blink::WebURL& first_party_for_cookies) override;
diff --git a/chromium/content/renderer/resizing_mode_selector.cc b/chromium/content/renderer/resizing_mode_selector.cc
index 58b4af1c02a..20c1cc1bd25 100644
--- a/chromium/content/renderer/resizing_mode_selector.cc
+++ b/chromium/content/renderer/resizing_mode_selector.cc
@@ -18,9 +18,8 @@ bool ResizingModeSelector::NeverUsesSynchronousResize() const {
!RenderThreadImpl::current()->layout_test_mode();
}
-bool ResizingModeSelector::ShouldAbortOnResize(
- RenderWidget* widget,
- const ViewMsg_Resize_Params& params) {
+bool ResizingModeSelector::ShouldAbortOnResize(RenderWidget* widget,
+ const ResizeParams& params) {
return is_synchronous_mode_ &&
params.is_fullscreen_granted == widget->is_fullscreen_granted() &&
params.display_mode == widget->display_mode() &&
diff --git a/chromium/content/renderer/resizing_mode_selector.h b/chromium/content/renderer/resizing_mode_selector.h
index 66a62bcd50b..7b92b9d70e4 100644
--- a/chromium/content/renderer/resizing_mode_selector.h
+++ b/chromium/content/renderer/resizing_mode_selector.h
@@ -7,11 +7,10 @@
#include "base/macros.h"
-struct ViewMsg_Resize_Params;
-
namespace content {
class RenderWidget;
+struct ResizeParams;
// Enables switching between two modes of resizing:
// 1) The "normal" (asynchronous) resizing, which involves sending messages to
@@ -26,8 +25,7 @@ class ResizingModeSelector {
public:
ResizingModeSelector();
bool NeverUsesSynchronousResize() const;
- bool ShouldAbortOnResize(RenderWidget* widget,
- const ViewMsg_Resize_Params& params);
+ bool ShouldAbortOnResize(RenderWidget* widget, const ResizeParams& params);
void set_is_synchronous_mode(bool mode);
bool is_synchronous_mode() const;
diff --git a/chromium/content/renderer/savable_resources.cc b/chromium/content/renderer/savable_resources.cc
index eb6c9da99ec..c1a702bd0fc 100644
--- a/chromium/content/renderer/savable_resources.cc
+++ b/chromium/content/renderer/savable_resources.cc
@@ -61,13 +61,9 @@ void GetSavableResourceLinkForElement(
const WebElement& element,
const WebDocument& current_doc,
SavableResourcesResult* result) {
- // Check whether the node has sub resource URL or not.
- WebString value = GetSubResourceLinkFromElement(element);
- if (value.isNull())
- return;
-
// Get absolute URL.
- GURL element_url = current_doc.completeURL(value);
+ WebString link_attribute_value = GetSubResourceLinkFromElement(element);
+ GURL element_url = current_doc.completeURL(link_attribute_value);
// See whether to report this element as a subframe.
WebFrame* web_frame = WebFrame::fromFrameOwnerElement(element);
@@ -79,6 +75,10 @@ void GetSavableResourceLinkForElement(
return;
}
+ // Check whether the node has sub resource URL or not.
+ if (link_attribute_value.isNull())
+ return;
+
// Ignore invalid URL.
if (!element_url.is_valid())
return;
diff --git a/chromium/content/renderer/scheduler/resource_dispatch_throttler.cc b/chromium/content/renderer/scheduler/resource_dispatch_throttler.cc
index aae15adaace..10e920f3b1f 100644
--- a/chromium/content/renderer/scheduler/resource_dispatch_throttler.cc
+++ b/chromium/content/renderer/scheduler/resource_dispatch_throttler.cc
@@ -66,13 +66,16 @@ bool ResourceDispatchThrottler::Send(IPC::Message* msg) {
if (!IsResourceRequest(*msg))
return ForwardMessage(msg);
- if (!scheduler_->IsHighPriorityWorkAnticipated())
+ if (!scheduler_->IsHighPriorityWorkAnticipated()) {
+ // Treat an unthrottled request as a flush.
+ LogFlush();
return ForwardMessage(msg);
+ }
- if (Now() > (last_sent_request_time_ + flush_period_)) {
- // If sufficient time has passed since the previous send, we can effectively
- // mark the pipeline as flushed.
- sent_requests_since_last_flush_ = 0;
+ if (Now() > (last_flush_time_ + flush_period_)) {
+ // If sufficient time has passed since the previous flush, we can
+ // effectively mark the pipeline as flushed.
+ LogFlush();
return ForwardMessage(msg);
}
@@ -99,7 +102,7 @@ void ResourceDispatchThrottler::Flush() {
DCHECK(thread_checker_.CalledOnValidThread());
TRACE_EVENT1("loader", "ResourceDispatchThrottler::Flush",
"total_throttled_messages", throttled_messages_.size());
- sent_requests_since_last_flush_ = 0;
+ LogFlush();
// If high-priority work is no longer anticipated, dispatch can be safely
// accelerated. Avoid completely flushing in such case in the event that
@@ -121,6 +124,7 @@ void ResourceDispatchThrottler::Flush() {
}
void ResourceDispatchThrottler::FlushAll() {
+ LogFlush();
if (throttled_messages_.empty())
return;
@@ -135,11 +139,15 @@ void ResourceDispatchThrottler::FlushAll() {
DCHECK(throttled_messages_.empty());
}
+void ResourceDispatchThrottler::LogFlush() {
+ sent_requests_since_last_flush_ = 0;
+ last_flush_time_ = Now();
+}
+
bool ResourceDispatchThrottler::ForwardMessage(IPC::Message* msg) {
- if (IsResourceRequest(*msg)) {
- last_sent_request_time_ = Now();
+ if (IsResourceRequest(*msg))
++sent_requests_since_last_flush_;
- }
+
return proxied_sender_->Send(msg);
}
diff --git a/chromium/content/renderer/scheduler/resource_dispatch_throttler.h b/chromium/content/renderer/scheduler/resource_dispatch_throttler.h
index d7f89b72eb7..bf2e77f241b 100644
--- a/chromium/content/renderer/scheduler/resource_dispatch_throttler.h
+++ b/chromium/content/renderer/scheduler/resource_dispatch_throttler.h
@@ -53,6 +53,7 @@ class CONTENT_EXPORT ResourceDispatchThrottler : public IPC::Sender {
void Flush();
void FlushAll();
+ void LogFlush();
bool ForwardMessage(IPC::Message* msg);
base::ThreadChecker thread_checker_;
@@ -63,7 +64,7 @@ class CONTENT_EXPORT ResourceDispatchThrottler : public IPC::Sender {
const uint32_t max_requests_per_flush_;
base::Timer flush_timer_;
- base::TimeTicks last_sent_request_time_;
+ base::TimeTicks last_flush_time_;
uint32_t sent_requests_since_last_flush_;
std::deque<IPC::Message*> throttled_messages_;
diff --git a/chromium/content/renderer/scheduler/resource_dispatch_throttler_unittest.cc b/chromium/content/renderer/scheduler/resource_dispatch_throttler_unittest.cc
index a1dbcac7076..15a233430c4 100644
--- a/chromium/content/renderer/scheduler/resource_dispatch_throttler_unittest.cc
+++ b/chromium/content/renderer/scheduler/resource_dispatch_throttler_unittest.cc
@@ -75,6 +75,7 @@ class ResourceDispatchThrottlerForTest : public ResourceDispatchThrottler {
scheduler,
base::TimeDelta::FromSecondsD(kFlushPeriodSeconds),
kRequestsPerFlush),
+ now_(base::TimeTicks() + base::TimeDelta::FromDays(1)),
flush_scheduled_(false) {}
~ResourceDispatchThrottlerForTest() override {}
@@ -252,6 +253,45 @@ TEST_F(ResourceDispatchThrottlerTest, NotThrottledIfSufficientTimePassed) {
}
}
+TEST_F(ResourceDispatchThrottlerTest, NotThrottledIfSendRateSufficientlyLow) {
+ SetHighPriorityWorkAnticipated(true);
+
+ // Continuous dispatch of resource requests below the allowed send rate
+ // should never throttled.
+ const base::TimeDelta kAllowedContinuousSendInterval =
+ base::TimeDelta::FromSecondsD((kFlushPeriodSeconds / kRequestsPerFlush) +
+ .00001);
+ for (size_t i = 0; i < kRequestsPerFlush * 10; ++i) {
+ Advance(kAllowedContinuousSendInterval);
+ RequestResource();
+ EXPECT_EQ(1U, GetAndResetSentMessageCount());
+ EXPECT_FALSE(FlushScheduled());
+ }
+}
+
+TEST_F(ResourceDispatchThrottlerTest, ThrottledIfSendRateSufficientlyHigh) {
+ SetHighPriorityWorkAnticipated(true);
+
+ // Continuous dispatch of resource requests above the allowed send rate
+ // should be throttled.
+ const base::TimeDelta kThrottledContinuousSendInterval =
+ base::TimeDelta::FromSecondsD((kFlushPeriodSeconds / kRequestsPerFlush) -
+ .00001);
+
+ for (size_t i = 0; i < kRequestsPerFlush * 10; ++i) {
+ Advance(kThrottledContinuousSendInterval);
+ RequestResource();
+ // Only the first batch of requests under the limit should be unthrottled.
+ if (i < kRequestsPerFlush) {
+ EXPECT_EQ(1U, GetAndResetSentMessageCount());
+ EXPECT_FALSE(FlushScheduled());
+ } else {
+ EXPECT_EQ(0U, GetAndResetSentMessageCount());
+ EXPECT_TRUE(FlushScheduled());
+ }
+ }
+}
+
TEST_F(ResourceDispatchThrottlerTest, NotThrottledIfSyncMessage) {
SetHighPriorityWorkAnticipated(true);
diff --git a/chromium/content/renderer/service_worker/embedded_worker_devtools_agent.cc b/chromium/content/renderer/service_worker/embedded_worker_devtools_agent.cc
index a09972937e2..6d44d5f29ee 100644
--- a/chromium/content/renderer/service_worker/embedded_worker_devtools_agent.cc
+++ b/chromium/content/renderer/service_worker/embedded_worker_devtools_agent.cc
@@ -6,7 +6,6 @@
#include "content/common/devtools_messages.h"
#include "content/renderer/render_thread_impl.h"
-#include "third_party/WebKit/public/platform/WebCString.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/web/WebEmbeddedWorker.h"
diff --git a/chromium/content/renderer/service_worker/embedded_worker_dispatcher.cc b/chromium/content/renderer/service_worker/embedded_worker_dispatcher.cc
index c99168cd0cf..f4334ede37e 100644
--- a/chromium/content/renderer/service_worker/embedded_worker_dispatcher.cc
+++ b/chromium/content/renderer/service_worker/embedded_worker_dispatcher.cc
@@ -53,6 +53,8 @@ bool EmbeddedWorkerDispatcher::OnMessageReceived(
IPC_BEGIN_MESSAGE_MAP(EmbeddedWorkerDispatcher, message)
IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_StartWorker, OnStartWorker)
IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_StopWorker, OnStopWorker)
+ IPC_MESSAGE_HANDLER(EmbeddedWorkerMsg_ResumeAfterDownload,
+ OnResumeAfterDownload)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -76,7 +78,6 @@ void EmbeddedWorkerDispatcher::OnStartWorker(
const EmbeddedWorkerMsg_StartWorker_Params& params) {
DCHECK(!workers_.Lookup(params.embedded_worker_id));
TRACE_EVENT0("ServiceWorker", "EmbeddedWorkerDispatcher::OnStartWorker");
- RenderThread::Get()->EnsureWebKitInitialized();
scoped_ptr<WorkerWrapper> wrapper(
new WorkerWrapper(blink::WebEmbeddedWorker::create(
new ServiceWorkerContextClient(
@@ -95,8 +96,13 @@ void EmbeddedWorkerDispatcher::OnStartWorker(
params.wait_for_debugger ?
blink::WebEmbeddedWorkerStartData::WaitForDebugger :
blink::WebEmbeddedWorkerStartData::DontWaitForDebugger;
- start_data.v8CacheOptions =
- static_cast<blink::WebSettings::V8CacheOptions>(params.v8_cache_options);
+ start_data.v8CacheOptions = static_cast<blink::WebSettings::V8CacheOptions>(
+ params.settings.v8_cache_options);
+ start_data.dataSaverEnabled = params.settings.data_saver_enabled;
+ start_data.pauseAfterDownloadMode =
+ params.pause_after_download
+ ? blink::WebEmbeddedWorkerStartData::PauseAfterDownload
+ : blink::WebEmbeddedWorkerStartData::DontPauseAfterDownload;
wrapper->worker()->startWorkerContext(start_data);
workers_.AddWithID(wrapper.release(), params.embedded_worker_id);
@@ -117,4 +123,15 @@ void EmbeddedWorkerDispatcher::OnStopWorker(int embedded_worker_id) {
wrapper->worker()->terminateWorkerContext();
}
+void EmbeddedWorkerDispatcher::OnResumeAfterDownload(int embedded_worker_id) {
+ TRACE_EVENT0("ServiceWorker",
+ "EmbeddedWorkerDispatcher::OnResumeAfterDownload");
+ WorkerWrapper* wrapper = workers_.Lookup(embedded_worker_id);
+ if (!wrapper) {
+ LOG(WARNING) << "Got OnResumeAfterDownload for nonexistent worker";
+ return;
+ }
+ wrapper->worker()->resumeAfterDownload();
+}
+
} // namespace content
diff --git a/chromium/content/renderer/service_worker/embedded_worker_dispatcher.h b/chromium/content/renderer/service_worker/embedded_worker_dispatcher.h
index 2ba1da86b38..f118d587c12 100644
--- a/chromium/content/renderer/service_worker/embedded_worker_dispatcher.h
+++ b/chromium/content/renderer/service_worker/embedded_worker_dispatcher.h
@@ -34,6 +34,7 @@ class EmbeddedWorkerDispatcher : public IPC::Listener {
void OnStartWorker(const EmbeddedWorkerMsg_StartWorker_Params& params);
void OnStopWorker(int embedded_worker_id);
+ void OnResumeAfterDownload(int embedded_worker_id);
IDMap<WorkerWrapper, IDMapOwnPointer> workers_;
std::map<int /* embedded_worker_id */, base::TimeTicks> stop_worker_times_;
diff --git a/chromium/content/renderer/service_worker/service_worker_context_client.cc b/chromium/content/renderer/service_worker/service_worker_context_client.cc
index 9119c5712fa..8d566ab7977 100644
--- a/chromium/content/renderer/service_worker/service_worker_context_client.cc
+++ b/chromium/content/renderer/service_worker/service_worker_context_client.cc
@@ -4,6 +4,7 @@
#include "content/renderer/service_worker/service_worker_context_client.h"
+#include <memory>
#include <utility>
#include "base/lazy_instance.h"
@@ -14,10 +15,10 @@
#include "base/threading/thread_checker.h"
#include "base/threading/thread_local.h"
#include "base/trace_event/trace_event.h"
-#include "content/child/navigator_connect/service_port_dispatcher_impl.h"
#include "content/child/notifications/notification_data_conversions.h"
#include "content/child/request_extra_data.h"
#include "content/child/service_worker/service_worker_dispatcher.h"
+#include "content/child/service_worker/service_worker_handle_reference.h"
#include "content/child/service_worker/service_worker_network_provider.h"
#include "content/child/service_worker/service_worker_provider_context.h"
#include "content/child/service_worker/service_worker_registration_handle_reference.h"
@@ -32,6 +33,7 @@
#include "content/common/mojo/service_registry_impl.h"
#include "content/common/service_worker/embedded_worker_messages.h"
#include "content/common/service_worker/service_worker_messages.h"
+#include "content/public/common/push_event_payload.h"
#include "content/public/common/referrer.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/public/renderer/document_state.h"
@@ -42,10 +44,10 @@
#include "content/renderer/service_worker/service_worker_type_util.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_message_macros.h"
-#include "third_party/WebKit/public/platform/WebCrossOriginServiceWorkerClient.h"
+#include "third_party/WebKit/public/platform/URLConversion.h"
#include "third_party/WebKit/public/platform/WebMessagePortChannel.h"
-#include "third_party/WebKit/public/platform/WebPassOwnPtr.h"
#include "third_party/WebKit/public/platform/WebReferrerPolicy.h"
+#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/platform/modules/background_sync/WebSyncRegistration.h"
#include "third_party/WebKit/public/platform/modules/notifications/WebNotificationData.h"
@@ -94,9 +96,10 @@ class WebServiceWorkerNetworkProviderImpl
blink::WebURLRequest& request) override {
ServiceWorkerNetworkProvider* provider =
ServiceWorkerNetworkProvider::FromDocumentState(
- static_cast<DataSourceExtraData*>(data_source->extraData()));
+ static_cast<DataSourceExtraData*>(data_source->getExtraData()));
scoped_ptr<RequestExtraData> extra_data(new RequestExtraData);
extra_data->set_service_worker_provider_id(provider->provider_id());
+ extra_data->set_originated_from_service_worker(true);
request.setExtraData(extra_data.release());
}
};
@@ -112,16 +115,6 @@ void SendPostMessageToClientOnMainThread(
WebMessagePortChannelImpl::ExtractMessagePortIDs(std::move(channels))));
}
-void SendCrossOriginMessageToClientOnMainThread(
- ThreadSafeSender* sender,
- int message_port_id,
- const base::string16& message,
- scoped_ptr<blink::WebMessagePortChannelArray> channels) {
- sender->Send(new MessagePortHostMsg_PostMessage(
- message_port_id, MessagePortMessage(message),
- WebMessagePortChannelImpl::ExtractMessagePortIDs(std::move(channels))));
-}
-
blink::WebURLRequest::FetchRequestMode GetBlinkFetchRequestMode(
FetchRequestMode mode) {
return static_cast<blink::WebURLRequest::FetchRequestMode>(mode);
@@ -179,7 +172,7 @@ struct ServiceWorkerContextClient::WorkerContextData {
using SkipWaitingCallbacksMap =
IDMap<blink::WebServiceWorkerSkipWaitingCallbacks, IDMapOwnPointer>;
using SyncEventCallbacksMap =
- IDMap<const mojo::Callback<void(ServiceWorkerEventStatus)>,
+ IDMap<const mojo::Callback<void(mojom::ServiceWorkerEventStatus)>,
IDMapOwnPointer>;
explicit WorkerContextData(ServiceWorkerContextClient* owner)
@@ -250,15 +243,18 @@ void ServiceWorkerContextClient::OnMessageReceived(
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(ServiceWorkerContextClient, message)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ActivateEvent, OnActivateEvent)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ExtendableMessageEvent,
+ OnExtendableMessageEvent)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_FetchEvent, OnFetchEvent)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_InstallEvent, OnInstallEvent)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_NotificationClickEvent,
OnNotificationClickEvent)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_NotificationCloseEvent,
+ OnNotificationCloseEvent)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_PushEvent, OnPushEvent)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_GeofencingEvent, OnGeofencingEvent)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_MessageToWorker, OnPostMessage)
- IPC_MESSAGE_HANDLER(ServiceWorkerMsg_CrossOriginMessageToWorker,
- OnCrossOriginMessageToWorker)
+ IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetClient, OnDidGetClient)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_DidGetClients, OnDidGetClients)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_OpenWindowResponse,
OnOpenWindowResponse)
@@ -280,8 +276,8 @@ void ServiceWorkerContextClient::OnMessageReceived(
}
void ServiceWorkerContextClient::BindServiceRegistry(
- mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services) {
+ mojo::shell::mojom::InterfaceProviderRequest services,
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services) {
context_->service_registry.Bind(std::move(services));
context_->service_registry.BindRemoteServiceProvider(
std::move(exposed_services));
@@ -291,6 +287,15 @@ blink::WebURL ServiceWorkerContextClient::scope() const {
return service_worker_scope_;
}
+void ServiceWorkerContextClient::getClient(
+ const blink::WebString& id,
+ blink::WebServiceWorkerClientCallbacks* callbacks) {
+ DCHECK(callbacks);
+ int request_id = context_->client_callbacks.Add(callbacks);
+ Send(new ServiceWorkerHostMsg_GetClient(
+ GetRoutingID(), request_id, base::UTF16ToUTF8(base::StringPiece16(id))));
+}
+
void ServiceWorkerContextClient::getClients(
const blink::WebServiceWorkerClientQueryOptions& weboptions,
blink::WebServiceWorkerClientsCallbacks* callbacks) {
@@ -371,9 +376,6 @@ void ServiceWorkerContextClient::workerContextStarted(
// Register Mojo services.
context_->service_registry.ServiceRegistry::AddService(
- base::Bind(&ServicePortDispatcherImpl::Create,
- context_->proxy_weak_factory.GetWeakPtr()));
- context_->service_registry.ServiceRegistry::AddService(
base::Bind(&BackgroundSyncClientImpl::Create));
SetRegistrationInServiceWorkerGlobalScope(registration_info, version_attrs);
@@ -402,11 +404,7 @@ void ServiceWorkerContextClient::didEvaluateWorkerScript(bool success) {
}
void ServiceWorkerContextClient::didInitializeWorkerContext(
- v8::Local<v8::Context> context,
- const blink::WebURL& url) {
- // TODO(annekao): Remove WebURL parameter from Blink, it's at best redundant
- // given |script_url_|, and may be empty in the future.
- // Also remove m_documentURL from ServiceWorkerGlobalScopeProxy.
+ v8::Local<v8::Context> context) {
GetContentClient()
->renderer()
->DidInitializeServiceWorkerContextOnWorkerThread(context, script_url_);
@@ -448,10 +446,8 @@ void ServiceWorkerContextClient::reportException(
int column_number,
const blink::WebString& source_url) {
Send(new EmbeddedWorkerHostMsg_ReportException(
- embedded_worker_id_,
- error_message,
- line_number,
- column_number, GURL(source_url)));
+ embedded_worker_id_, error_message, line_number, column_number,
+ blink::WebStringToGURL(source_url)));
}
void ServiceWorkerContextClient::reportConsoleMessage(
@@ -465,7 +461,7 @@ void ServiceWorkerContextClient::reportConsoleMessage(
params.message_level = level;
params.message = message;
params.line_number = line_number;
- params.source_url = GURL(source_url);
+ params.source_url = blink::WebStringToGURL(source_url);
Send(new EmbeddedWorkerHostMsg_ReportConsoleMessage(
embedded_worker_id_, params));
@@ -488,6 +484,13 @@ void ServiceWorkerContextClient::didHandleActivateEvent(
GetRoutingID(), request_id, result));
}
+void ServiceWorkerContextClient::didHandleExtendableMessageEvent(
+ int request_id,
+ blink::WebServiceWorkerEventResult result) {
+ Send(new ServiceWorkerHostMsg_ExtendableMessageEventFinished(
+ GetRoutingID(), request_id, result));
+}
+
void ServiceWorkerContextClient::didHandleInstallEvent(
int request_id,
blink::WebServiceWorkerEventResult result) {
@@ -511,7 +514,10 @@ void ServiceWorkerContextClient::didHandleFetchEvent(
web_response.url(), web_response.status(),
web_response.statusText().utf8(), web_response.responseType(), headers,
web_response.blobUUID().utf8(), web_response.blobSize(),
- web_response.streamURL(), web_response.error());
+ web_response.streamURL(), web_response.error(),
+ base::Time::FromInternalValue(web_response.responseTime()),
+ !web_response.cacheStorageCacheName().isNull(),
+ web_response.cacheStorageCacheName().utf8());
Send(new ServiceWorkerHostMsg_FetchEventFinished(
GetRoutingID(), request_id,
SERVICE_WORKER_FETCH_EVENT_RESULT_RESPONSE,
@@ -522,7 +528,14 @@ void ServiceWorkerContextClient::didHandleNotificationClickEvent(
int request_id,
blink::WebServiceWorkerEventResult result) {
Send(new ServiceWorkerHostMsg_NotificationClickEventFinished(
- GetRoutingID(), request_id));
+ GetRoutingID(), request_id, result));
+}
+
+void ServiceWorkerContextClient::didHandleNotificationCloseEvent(
+ int request_id,
+ blink::WebServiceWorkerEventResult result) {
+ Send(new ServiceWorkerHostMsg_NotificationCloseEventFinished(
+ GetRoutingID(), request_id, result));
}
void ServiceWorkerContextClient::didHandlePushEvent(
@@ -540,9 +553,9 @@ void ServiceWorkerContextClient::didHandleSyncEvent(
if (!callback)
return;
if (result == blink::WebServiceWorkerEventResultCompleted) {
- callback->Run(SERVICE_WORKER_EVENT_STATUS_COMPLETED);
+ callback->Run(mojom::ServiceWorkerEventStatus::COMPLETED);
} else {
- callback->Run(SERVICE_WORKER_EVENT_STATUS_REJECTED);
+ callback->Run(mojom::ServiceWorkerEventStatus::REJECTED);
}
context_->sync_event_callbacks.Remove(request_id);
}
@@ -593,30 +606,18 @@ void ServiceWorkerContextClient::postMessageToClient(
// to overtake those messages.
scoped_ptr<blink::WebMessagePortChannelArray> channel_array(channels);
main_thread_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&SendPostMessageToClientOnMainThread,
- sender_,
- GetRoutingID(),
- base::UTF16ToUTF8(base::StringPiece16(uuid)),
- static_cast<base::string16>(message),
- base::Passed(&channel_array)));
+ FROM_HERE, base::Bind(&SendPostMessageToClientOnMainThread,
+ base::RetainedRef(sender_), GetRoutingID(),
+ base::UTF16ToUTF8(base::StringPiece16(uuid)),
+ static_cast<base::string16>(message),
+ base::Passed(&channel_array)));
}
void ServiceWorkerContextClient::postMessageToCrossOriginClient(
- const blink::WebCrossOriginServiceWorkerClient& client,
- const blink::WebString& message,
- blink::WebMessagePortChannelArray* channels) {
- // This may send channels for MessagePorts, and all internal book-keeping
- // messages for MessagePort (e.g. QueueMessages) are sent from main thread
- // (with thread hopping), so we need to do the same thread hopping here not
- // to overtake those messages.
- scoped_ptr<blink::WebMessagePortChannelArray> channel_array(channels);
- main_thread_task_runner_->PostTask(
- FROM_HERE,
- base::Bind(&SendCrossOriginMessageToClientOnMainThread,
- sender_, client.clientID,
- static_cast<base::string16>(message),
- base::Passed(&channel_array)));
+ const blink::WebCrossOriginServiceWorkerClient&,
+ const blink::WebString&,
+ blink::WebMessagePortChannelArray*) {
+ NOTREACHED();
}
void ServiceWorkerContextClient::focus(
@@ -655,20 +656,26 @@ void ServiceWorkerContextClient::claim(
}
void ServiceWorkerContextClient::registerForeignFetchScopes(
- const blink::WebVector<blink::WebURL>& sub_scopes) {
+ const blink::WebVector<blink::WebURL>& sub_scopes,
+ const blink::WebVector<blink::WebSecurityOrigin>& origins) {
Send(new ServiceWorkerHostMsg_RegisterForeignFetchScopes(
- GetRoutingID(), std::vector<GURL>(sub_scopes.begin(), sub_scopes.end())));
+ GetRoutingID(), std::vector<GURL>(sub_scopes.begin(), sub_scopes.end()),
+ std::vector<url::Origin>(origins.begin(), origins.end())));
}
void ServiceWorkerContextClient::DispatchSyncEvent(
- const blink::WebSyncRegistration& registration,
+ const std::string& tag,
blink::WebServiceWorkerContextProxy::LastChanceOption last_chance,
const SyncCallback& callback) {
TRACE_EVENT0("ServiceWorker",
"ServiceWorkerContextClient::DispatchSyncEvent");
int request_id =
context_->sync_event_callbacks.Add(new SyncCallback(callback));
- proxy_->dispatchSyncEvent(request_id, registration, last_chance);
+
+ // TODO(jkarlin): Make this blink::WebString::FromUTF8Lenient once
+ // https://crrev.com/1768063002/ lands.
+ proxy_->dispatchSyncEvent(request_id, blink::WebString::fromUTF8(tag),
+ last_chance);
}
void ServiceWorkerContextClient::Send(IPC::Message* message) {
@@ -706,6 +713,37 @@ void ServiceWorkerContextClient::OnActivateEvent(int request_id) {
proxy_->dispatchActivateEvent(request_id);
}
+void ServiceWorkerContextClient::OnExtendableMessageEvent(
+ int request_id,
+ const ServiceWorkerMsg_ExtendableMessageEvent_Params& params) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerContextClient::OnExtendableMessageEvent");
+ blink::WebMessagePortChannelArray ports =
+ WebMessagePortChannelImpl::CreatePorts(params.message_ports,
+ params.new_routing_ids,
+ main_thread_task_runner_);
+ if (params.source.client_info.IsValid()) {
+ blink::WebServiceWorkerClientInfo web_client =
+ ToWebServiceWorkerClientInfo(params.source.client_info);
+ proxy_->dispatchExtendableMessageEvent(
+ request_id, params.message, params.source_origin, ports, web_client);
+ return;
+ }
+
+ DCHECK(params.source.service_worker_info.IsValid());
+ scoped_ptr<ServiceWorkerHandleReference> handle =
+ ServiceWorkerHandleReference::Adopt(params.source.service_worker_info,
+ sender_.get());
+ ServiceWorkerDispatcher* dispatcher =
+ ServiceWorkerDispatcher::GetOrCreateThreadSpecificInstance(
+ sender_.get(), main_thread_task_runner_.get());
+ scoped_refptr<WebServiceWorkerImpl> worker =
+ dispatcher->GetOrCreateServiceWorker(std::move(handle));
+ proxy_->dispatchExtendableMessageEvent(
+ request_id, params.message, params.source_origin, ports,
+ WebServiceWorkerImpl::CreateHandle(worker));
+}
+
void ServiceWorkerContextClient::OnInstallEvent(int request_id) {
TRACE_EVENT0("ServiceWorker",
"ServiceWorkerContextClient::OnInstallEvent");
@@ -743,7 +781,11 @@ void ServiceWorkerContextClient::OnFetchEvent(
webRequest.setFrameType(GetBlinkFrameType(request.frame_type));
webRequest.setClientId(blink::WebString::fromUTF8(request.client_id));
webRequest.setIsReload(request.is_reload);
- proxy_->dispatchFetchEvent(request_id, webRequest);
+ if (request.fetch_type == ServiceWorkerFetchType::FOREIGN_FETCH) {
+ proxy_->dispatchForeignFetchEvent(request_id, webRequest);
+ } else {
+ proxy_->dispatchFetchEvent(request_id, webRequest);
+ }
}
void ServiceWorkerContextClient::OnNotificationClickEvent(
@@ -760,11 +802,26 @@ void ServiceWorkerContextClient::OnNotificationClickEvent(
action_index);
}
+void ServiceWorkerContextClient::OnNotificationCloseEvent(
+ int request_id,
+ int64_t persistent_notification_id,
+ const PlatformNotificationData& notification_data) {
+ TRACE_EVENT0("ServiceWorker",
+ "ServiceWorkerContextClient::OnNotificationCloseEvent");
+ proxy_->dispatchNotificationCloseEvent(
+ request_id, persistent_notification_id,
+ ToWebNotificationData(notification_data));
+}
+
void ServiceWorkerContextClient::OnPushEvent(int request_id,
- const std::string& data) {
+ const PushEventPayload& payload) {
TRACE_EVENT0("ServiceWorker",
"ServiceWorkerContextClient::OnPushEvent");
- proxy_->dispatchPushEvent(request_id, blink::WebString::fromUTF8(data));
+ // Only set data to be a valid string if the payload had decrypted data.
+ blink::WebString data;
+ if (!payload.is_null)
+ data.assign(blink::WebString::fromUTF8(payload.data));
+ proxy_->dispatchPushEvent(request_id, data);
}
void ServiceWorkerContextClient::OnGeofencingEvent(
@@ -800,23 +857,24 @@ void ServiceWorkerContextClient::OnPostMessage(
base::TimeTicks::Now() - before);
}
-void ServiceWorkerContextClient::OnCrossOriginMessageToWorker(
- const NavigatorConnectClient& client,
- const base::string16& message,
- const std::vector<TransferredMessagePort>& sent_message_ports,
- const std::vector<int>& new_routing_ids) {
- TRACE_EVENT0("ServiceWorker",
- "ServiceWorkerContextClient::OnCrossOriginMessageToWorker");
- blink::WebMessagePortChannelArray ports =
- WebMessagePortChannelImpl::CreatePorts(
- sent_message_ports, new_routing_ids,
- main_thread_task_runner_);
-
- blink::WebCrossOriginServiceWorkerClient web_client;
- web_client.origin = client.origin;
- web_client.targetURL = client.target_url;
- web_client.clientID = client.message_port_id;
- proxy_->dispatchCrossOriginMessageEvent(web_client, message, ports);
+void ServiceWorkerContextClient::OnDidGetClient(
+ int request_id,
+ const ServiceWorkerClientInfo& client) {
+ TRACE_EVENT0("ServiceWorker", "ServiceWorkerContextClient::OnDidGetClient");
+ blink::WebServiceWorkerClientCallbacks* callbacks =
+ context_->client_callbacks.Lookup(request_id);
+ if (!callbacks) {
+ NOTREACHED() << "Got stray response: " << request_id;
+ return;
+ }
+ scoped_ptr<blink::WebServiceWorkerClientInfo> web_client;
+ if (!client.IsEmpty()) {
+ DCHECK(client.IsValid());
+ web_client.reset(new blink::WebServiceWorkerClientInfo(
+ ToWebServiceWorkerClientInfo(client)));
+ }
+ callbacks->onSuccess(std::move(web_client));
+ context_->client_callbacks.Remove(request_id);
}
void ServiceWorkerContextClient::OnDidGetClients(
@@ -856,7 +914,7 @@ void ServiceWorkerContextClient::OnOpenWindowResponse(
web_client.reset(new blink::WebServiceWorkerClientInfo(
ToWebServiceWorkerClientInfo(client)));
}
- callbacks->onSuccess(adoptWebPtr(web_client.release()));
+ callbacks->onSuccess(std::move(web_client));
context_->client_callbacks.Remove(request_id);
}
@@ -892,7 +950,7 @@ void ServiceWorkerContextClient::OnFocusClientResponse(
scoped_ptr<blink::WebServiceWorkerClientInfo> web_client (
new blink::WebServiceWorkerClientInfo(
ToWebServiceWorkerClientInfo(client)));
- callback->onSuccess(adoptWebPtr(web_client.release()));
+ callback->onSuccess(std::move(web_client));
} else {
callback->onError(blink::WebServiceWorkerError(
blink::WebServiceWorkerError::ErrorTypeNotFound,
@@ -919,7 +977,7 @@ void ServiceWorkerContextClient::OnNavigateClientResponse(
web_client.reset(new blink::WebServiceWorkerClientInfo(
ToWebServiceWorkerClientInfo(client)));
}
- callbacks->onSuccess(adoptWebPtr(web_client.release()));
+ callbacks->onSuccess(std::move(web_client));
context_->client_callbacks.Remove(request_id);
}
diff --git a/chromium/content/renderer/service_worker/service_worker_context_client.h b/chromium/content/renderer/service_worker/service_worker_context_client.h
index 6356e37bef0..5cc4121d755 100644
--- a/chromium/content/renderer/service_worker/service_worker_context_client.h
+++ b/chromium/content/renderer/service_worker/service_worker_context_client.h
@@ -22,7 +22,7 @@
#include "content/common/service_worker/service_worker_types.h"
#include "content/public/common/service_worker_event_status.mojom.h"
#include "ipc/ipc_listener.h"
-#include "mojo/shell/public/interfaces/service_provider.mojom.h"
+#include "mojo/shell/public/interfaces/interface_provider.mojom.h"
#include "third_party/WebKit/public/platform/WebGeofencingEventType.h"
#include "third_party/WebKit/public/platform/WebMessagePortChannel.h"
#include "third_party/WebKit/public/platform/modules/serviceworker/WebServiceWorkerError.h"
@@ -30,6 +30,8 @@
#include "third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextProxy.h"
#include "v8/include/v8.h"
+struct ServiceWorkerMsg_ExtendableMessageEvent_Params;
+
namespace base {
class SingleThreadTaskRunner;
class TaskRunner;
@@ -37,7 +39,6 @@ class TaskRunner;
namespace blink {
struct WebCircularGeofencingRegion;
-struct WebCrossOriginServiceWorkerClient;
class WebDataSource;
struct WebServiceWorkerClientQueryOptions;
class WebServiceWorkerContextProxy;
@@ -51,8 +52,8 @@ class Message;
namespace content {
-struct NavigatorConnectClient;
struct PlatformNotificationData;
+struct PushEventPayload;
struct ServiceWorkerClientInfo;
class ServiceWorkerProviderContext;
class ServiceWorkerContextClient;
@@ -64,7 +65,7 @@ class WebServiceWorkerRegistrationImpl;
class ServiceWorkerContextClient
: public blink::WebServiceWorkerContextClient {
public:
- using SyncCallback = mojo::Callback<void(ServiceWorkerEventStatus)>;
+ using SyncCallback = mojo::Callback<void(mojom::ServiceWorkerEventStatus)>;
// Returns a thread-specific client instance. This does NOT create a
// new instance.
@@ -86,11 +87,13 @@ class ServiceWorkerContextClient
// ServiceRegistry to connect to services before this method is called are
// queued up and will resolve after this method is called.
void BindServiceRegistry(
- mojo::InterfaceRequest<mojo::ServiceProvider> services,
- mojo::ServiceProviderPtr exposed_services);
+ mojo::shell::mojom::InterfaceProviderRequest services,
+ mojo::shell::mojom::InterfaceProviderPtr exposed_services);
// WebServiceWorkerContextClient overrides.
blink::WebURL scope() const override;
+ void getClient(const blink::WebString&,
+ blink::WebServiceWorkerClientCallbacks*) override;
void getClients(const blink::WebServiceWorkerClientQueryOptions&,
blink::WebServiceWorkerClientsCallbacks*) override;
void openWindow(const blink::WebURL&,
@@ -108,8 +111,7 @@ class ServiceWorkerContextClient
void workerContextStarted(
blink::WebServiceWorkerContextProxy* proxy) override;
void didEvaluateWorkerScript(bool success) override;
- void didInitializeWorkerContext(v8::Local<v8::Context> context,
- const blink::WebURL& url) override;
+ void didInitializeWorkerContext(v8::Local<v8::Context> context) override;
void willDestroyWorkerContext(v8::Local<v8::Context> context) override;
void workerContextDestroyed() override;
void reportException(const blink::WebString& error_message,
@@ -127,6 +129,9 @@ class ServiceWorkerContextClient
const blink::WebString& state) override;
void didHandleActivateEvent(int request_id,
blink::WebServiceWorkerEventResult) override;
+ void didHandleExtendableMessageEvent(
+ int request_id,
+ blink::WebServiceWorkerEventResult result) override;
void didHandleInstallEvent(
int request_id,
blink::WebServiceWorkerEventResult result) override;
@@ -137,6 +142,9 @@ class ServiceWorkerContextClient
void didHandleNotificationClickEvent(
int request_id,
blink::WebServiceWorkerEventResult result) override;
+ void didHandleNotificationCloseEvent(
+ int request_id,
+ blink::WebServiceWorkerEventResult result) override;
void didHandlePushEvent(int request_id,
blink::WebServiceWorkerEventResult result) override;
void didHandleSyncEvent(int request_id,
@@ -152,9 +160,9 @@ class ServiceWorkerContextClient
const blink::WebString& message,
blink::WebMessagePortChannelArray* channels) override;
void postMessageToCrossOriginClient(
- const blink::WebCrossOriginServiceWorkerClient& client,
- const blink::WebString& message,
- blink::WebMessagePortChannelArray* channels) override;
+ const blink::WebCrossOriginServiceWorkerClient&,
+ const blink::WebString&,
+ blink::WebMessagePortChannelArray*) override;
void focus(const blink::WebString& uuid,
blink::WebServiceWorkerClientCallbacks*) override;
void navigate(const blink::WebString& uuid,
@@ -164,10 +172,11 @@ class ServiceWorkerContextClient
blink::WebServiceWorkerSkipWaitingCallbacks* callbacks) override;
void claim(blink::WebServiceWorkerClientsClaimCallbacks* callbacks) override;
void registerForeignFetchScopes(
- const blink::WebVector<blink::WebURL>& sub_scopes) override;
+ const blink::WebVector<blink::WebURL>& sub_scopes,
+ const blink::WebVector<blink::WebSecurityOrigin>& origins) override;
virtual void DispatchSyncEvent(
- const blink::WebSyncRegistration& registration,
+ const std::string& tag,
blink::WebServiceWorkerContextProxy::LastChanceOption last_chance,
const SyncCallback& callback);
@@ -185,6 +194,9 @@ class ServiceWorkerContextClient
const ServiceWorkerVersionAttributes& attrs);
void OnActivateEvent(int request_id);
+ void OnExtendableMessageEvent(
+ int request_id,
+ const ServiceWorkerMsg_ExtendableMessageEvent_Params& params);
void OnInstallEvent(int request_id);
void OnFetchEvent(int request_id, const ServiceWorkerFetchRequest& request);
void OnNotificationClickEvent(
@@ -192,20 +204,24 @@ class ServiceWorkerContextClient
int64_t persistent_notification_id,
const PlatformNotificationData& notification_data,
int action_index);
- void OnPushEvent(int request_id, const std::string& data);
+ void OnPushEvent(int request_id, const PushEventPayload& payload);
+ void OnNotificationCloseEvent(
+ int request_id,
+ int64_t persistent_notification_id,
+ const PlatformNotificationData& notification_data);
void OnGeofencingEvent(int request_id,
blink::WebGeofencingEventType event_type,
const std::string& region_id,
const blink::WebCircularGeofencingRegion& region);
+
+ // TODO(nhiroki): Remove this after ExtendableMessageEvent is enabled by
+ // default (crbug.com/543198).
void OnPostMessage(
const base::string16& message,
const std::vector<TransferredMessagePort>& sent_message_ports,
const std::vector<int>& new_routing_ids);
- void OnCrossOriginMessageToWorker(
- const NavigatorConnectClient& client,
- const base::string16& message,
- const std::vector<TransferredMessagePort>& sent_message_ports,
- const std::vector<int>& new_routing_ids);
+
+ void OnDidGetClient(int request_id, const ServiceWorkerClientInfo& client);
void OnDidGetClients(
int request_id, const std::vector<ServiceWorkerClientInfo>& clients);
void OnOpenWindowResponse(int request_id,
diff --git a/chromium/content/renderer/shared_worker/embedded_shared_worker_content_settings_client_proxy.cc b/chromium/content/renderer/shared_worker/embedded_shared_worker_content_settings_client_proxy.cc
index 11463635f86..97b5063b8e7 100644
--- a/chromium/content/renderer/shared_worker/embedded_shared_worker_content_settings_client_proxy.cc
+++ b/chromium/content/renderer/shared_worker/embedded_shared_worker_content_settings_client_proxy.cc
@@ -27,18 +27,6 @@ EmbeddedSharedWorkerContentSettingsClientProxy::
~EmbeddedSharedWorkerContentSettingsClientProxy() {
}
-bool EmbeddedSharedWorkerContentSettingsClientProxy::allowDatabase(
- const blink::WebString& name,
- const blink::WebString& display_name,
- unsigned long estimated_size) {
- if (is_unique_origin_)
- return false;
- bool result = false;
- thread_safe_sender_->Send(new WorkerProcessHostMsg_AllowDatabase(
- routing_id_, origin_url_, name, display_name, estimated_size, &result));
- return result;
-}
-
bool
EmbeddedSharedWorkerContentSettingsClientProxy::requestFileSystemAccessSync() {
if (is_unique_origin_)
diff --git a/chromium/content/renderer/shared_worker/embedded_shared_worker_content_settings_client_proxy.h b/chromium/content/renderer/shared_worker/embedded_shared_worker_content_settings_client_proxy.h
index e87e30d3dd6..b93d989a6cf 100644
--- a/chromium/content/renderer/shared_worker/embedded_shared_worker_content_settings_client_proxy.h
+++ b/chromium/content/renderer/shared_worker/embedded_shared_worker_content_settings_client_proxy.h
@@ -27,9 +27,6 @@ class EmbeddedSharedWorkerContentSettingsClientProxy
~EmbeddedSharedWorkerContentSettingsClientProxy() override;
// WebWorkerContentSettingsClientProxy overrides.
- bool allowDatabase(const blink::WebString& name,
- const blink::WebString& display_name,
- unsigned long estimated_size) override;
bool requestFileSystemAccessSync() override;
bool allowIndexedDB(const blink::WebString& name) override;
diff --git a/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc b/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc
index 39b0d3526e3..30ac9cb9ccf 100644
--- a/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc
+++ b/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.cc
@@ -21,9 +21,9 @@
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/shared_worker/embedded_shared_worker_content_settings_client_proxy.h"
#include "ipc/ipc_message_macros.h"
-#include "third_party/WebKit/public/platform/WebURLRequest.h"
+#include "third_party/WebKit/public/platform/URLConversion.h"
+#include "third_party/WebKit/public/platform/WebSecurityOrigin.h"
#include "third_party/WebKit/public/web/WebDataSource.h"
-#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
#include "third_party/WebKit/public/web/WebSharedWorker.h"
#include "third_party/WebKit/public/web/WebSharedWorkerClient.h"
#include "third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerNetworkProvider.h"
@@ -83,12 +83,12 @@ class WebServiceWorkerNetworkProviderImpl
blink::WebURLRequest& request) override {
ServiceWorkerNetworkProvider* provider =
GetNetworkProviderFromDataSource(data_source);
- scoped_ptr<RequestExtraData> extra_data(new RequestExtraData);
+ std::unique_ptr<RequestExtraData> extra_data(new RequestExtraData);
extra_data->set_service_worker_provider_id(provider->provider_id());
request.setExtraData(extra_data.release());
// Explicitly set the SkipServiceWorker flag for subresources here if the
// renderer process hasn't received SetControllerServiceWorker message.
- if (request.requestContext() !=
+ if (request.getRequestContext() !=
blink::WebURLRequest::RequestContextSharedWorker &&
!provider->IsControlledByServiceWorker()) {
request.setSkipServiceWorker(true);
@@ -113,7 +113,7 @@ class WebServiceWorkerNetworkProviderImpl
ServiceWorkerNetworkProvider* GetNetworkProviderFromDataSource(
const blink::WebDataSource* data_source) {
return ServiceWorkerNetworkProvider::FromDocumentState(
- static_cast<DataSourceExtraData*>(data_source->extraData()));
+ static_cast<DataSourceExtraData*>(data_source->getExtraData()));
}
};
@@ -124,11 +124,10 @@ EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub(
const base::string16& name,
const base::string16& content_security_policy,
blink::WebContentSecurityPolicyType security_policy_type,
+ blink::WebAddressSpace creation_address_space,
bool pause_on_start,
int route_id)
- : route_id_(route_id),
- name_(name),
- url_(url) {
+ : route_id_(route_id), name_(name), url_(url) {
RenderThreadImpl::current()->AddEmbeddedWorkerRoute(route_id_, this);
impl_ = blink::WebSharedWorker::create(this);
if (pause_on_start) {
@@ -138,8 +137,8 @@ EmbeddedSharedWorkerStub::EmbeddedSharedWorkerStub(
}
worker_devtools_agent_.reset(
new SharedWorkerDevToolsAgent(route_id, impl_));
- impl_->startWorkerContext(url, name_,
- content_security_policy, security_policy_type);
+ impl_->startWorkerContext(url, name_, content_security_policy,
+ security_policy_type, creation_address_space);
}
EmbeddedSharedWorkerStub::~EmbeddedSharedWorkerStub() {
@@ -229,7 +228,7 @@ blink::WebWorkerContentSettingsClientProxy*
EmbeddedSharedWorkerStub::createWorkerContentSettingsClientProxy(
const blink::WebSecurityOrigin& origin) {
return new EmbeddedSharedWorkerContentSettingsClientProxy(
- GURL(origin.toString()),
+ blink::WebStringToGURL(origin.toString()),
origin.isUnique(),
route_id_,
ChildThreadImpl::current()->thread_safe_sender());
@@ -240,7 +239,7 @@ EmbeddedSharedWorkerStub::createServiceWorkerNetworkProvider(
blink::WebDataSource* data_source) {
// Create a content::ServiceWorkerNetworkProvider for this data source so
// we can observe its requests.
- scoped_ptr<ServiceWorkerNetworkProvider> provider(
+ std::unique_ptr<ServiceWorkerNetworkProvider> provider(
new ServiceWorkerNetworkProvider(
route_id_, SERVICE_WORKER_PROVIDER_FOR_SHARED_WORKER));
diff --git a/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.h b/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.h
index 232f55a7bfb..8442dd6df75 100644
--- a/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.h
+++ b/chromium/content/renderer/shared_worker/embedded_shared_worker_stub.h
@@ -5,12 +5,14 @@
#ifndef CONTENT_RENDERER_SHARED_WORKER_EMBEDDED_SHARED_WORKER_STUB_H_
#define CONTENT_RENDERER_SHARED_WORKER_EMBEDDED_SHARED_WORKER_STUB_H_
+#include <memory>
#include <vector>
#include "base/macros.h"
#include "content/child/child_message_filter.h"
#include "content/child/scoped_child_process_reference.h"
#include "ipc/ipc_listener.h"
+#include "third_party/WebKit/public/platform/WebAddressSpace.h"
#include "third_party/WebKit/public/platform/WebString.h"
#include "third_party/WebKit/public/web/WebContentSecurityPolicy.h"
#include "third_party/WebKit/public/web/WebSharedWorkerClient.h"
@@ -49,6 +51,7 @@ class EmbeddedSharedWorkerStub : public IPC::Listener,
const base::string16& name,
const base::string16& content_security_policy,
blink::WebContentSecurityPolicyType security_policy_type,
+ blink::WebAddressSpace creation_address_space,
bool pause_on_start,
int route_id);
@@ -93,7 +96,7 @@ class EmbeddedSharedWorkerStub : public IPC::Listener,
bool running_ = false;
GURL url_;
blink::WebSharedWorker* impl_ = nullptr;
- scoped_ptr<SharedWorkerDevToolsAgent> worker_devtools_agent_;
+ std::unique_ptr<SharedWorkerDevToolsAgent> worker_devtools_agent_;
typedef std::vector<WebMessagePortChannelImpl*> PendingChannelList;
PendingChannelList pending_channels_;
diff --git a/chromium/content/renderer/shared_worker_repository.cc b/chromium/content/renderer/shared_worker_repository.cc
index 93b1a0647bc..607e044fe27 100644
--- a/chromium/content/renderer/shared_worker_repository.cc
+++ b/chromium/content/renderer/shared_worker_repository.cc
@@ -27,6 +27,7 @@ SharedWorkerRepository::createSharedWorkerConnector(
DocumentID document_id,
const blink::WebString& content_security_policy,
blink::WebContentSecurityPolicyType security_policy_type,
+ blink::WebAddressSpace creation_address_space,
blink::WebSharedWorkerCreationContextType creation_context_type,
blink::WebWorkerCreationError* error) {
ViewHostMsg_CreateWorker_Params params;
@@ -36,6 +37,7 @@ SharedWorkerRepository::createSharedWorkerConnector(
params.security_policy_type = security_policy_type;
params.document_id = document_id;
params.render_frame_route_id = render_frame()->GetRoutingID();
+ params.creation_address_space = creation_address_space;
params.creation_context_type = creation_context_type;
ViewHostMsg_CreateWorker_Reply reply;
Send(new ViewHostMsg_CreateWorker(params, &reply));
diff --git a/chromium/content/renderer/shared_worker_repository.h b/chromium/content/renderer/shared_worker_repository.h
index 70d73d38f67..93ac628c379 100644
--- a/chromium/content/renderer/shared_worker_repository.h
+++ b/chromium/content/renderer/shared_worker_repository.h
@@ -9,6 +9,7 @@
#include "base/macros.h"
#include "content/public/renderer/render_frame_observer.h"
+#include "third_party/WebKit/public/platform/WebAddressSpace.h"
#include "third_party/WebKit/public/web/WebContentSecurityPolicy.h"
#include "third_party/WebKit/public/web/WebSharedWorkerCreationContextType.h"
#include "third_party/WebKit/public/web/WebSharedWorkerRepositoryClient.h"
@@ -30,6 +31,7 @@ class SharedWorkerRepository : public RenderFrameObserver,
DocumentID document_id,
const blink::WebString& content_security_policy,
blink::WebContentSecurityPolicyType,
+ blink::WebAddressSpace,
blink::WebSharedWorkerCreationContextType,
blink::WebWorkerCreationError* error) override;
void documentDetached(DocumentID document_id) override;
diff --git a/chromium/content/renderer/skia_benchmarking_extension.cc b/chromium/content/renderer/skia_benchmarking_extension.cc
index f5180d0fd42..45189302691 100644
--- a/chromium/content/renderer/skia_benchmarking_extension.cc
+++ b/chromium/content/renderer/skia_benchmarking_extension.cc
@@ -40,7 +40,7 @@ namespace {
class Picture {
public:
gfx::Rect layer_rect;
- skia::RefPtr<SkPicture> picture;
+ sk_sp<SkPicture> picture;
};
bool DecodeBitmap(const void* buffer, size_t size, SkBitmap* bm) {
@@ -70,13 +70,14 @@ scoped_ptr<Picture> CreatePictureFromEncodedString(const std::string& encoded) {
base::Base64Decode(encoded, &decoded);
SkMemoryStream stream(decoded.data(), decoded.size());
- SkPicture* skpicture = SkPicture::CreateFromStream(&stream, &DecodeBitmap);
+ sk_sp<SkPicture> skpicture =
+ SkPicture::MakeFromStream(&stream, &DecodeBitmap);
if (!skpicture)
return nullptr;
scoped_ptr<Picture> picture(new Picture);
picture->layer_rect = gfx::SkIRectToRect(skpicture->cullRect().roundOut());
- picture->picture = skia::AdoptRef(skpicture);
+ picture->picture = std::move(skpicture);
return picture;
}
diff --git a/chromium/content/renderer/text_input_client_observer.cc b/chromium/content/renderer/text_input_client_observer.cc
index eda58f206f1..b97be4a31bd 100644
--- a/chromium/content/renderer/text_input_client_observer.cc
+++ b/chromium/content/renderer/text_input_client_observer.cc
@@ -65,7 +65,8 @@ void TextInputClientObserver::OnStringAtPoint(gfx::Point point) {
void TextInputClientObserver::OnCharacterIndexForPoint(gfx::Point point) {
blink::WebPoint web_point(point);
- size_t index = webview()->focusedFrame()->characterIndexForPoint(web_point);
+ uint32_t index = static_cast<uint32_t>(
+ webview()->focusedFrame()->characterIndexForPoint(web_point));
Send(new TextInputClientReplyMsg_GotCharacterIndexForPoint(routing_id(),
index));
}
diff --git a/chromium/content/renderer/top_level_blame_context.cc b/chromium/content/renderer/top_level_blame_context.cc
new file mode 100644
index 00000000000..6b8311a5852
--- /dev/null
+++ b/chromium/content/renderer/top_level_blame_context.cc
@@ -0,0 +1,25 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/top_level_blame_context.h"
+
+#include "base/threading/platform_thread.h"
+#include "content/renderer/frame_blame_context.h"
+
+namespace content {
+
+const char kTopLevelBlameContextCategory[] = "blink";
+const char kTopLevelBlameContextName[] = "FrameBlameContext";
+const char kTopLevelBlameContextType[] = "TopLevel";
+const char kTopLevelBlameContextScope[] = "PlatformThread";
+
+TopLevelBlameContext::TopLevelBlameContext()
+ : base::trace_event::BlameContext(kTopLevelBlameContextCategory,
+ kTopLevelBlameContextName,
+ kTopLevelBlameContextType,
+ kTopLevelBlameContextScope,
+ base::PlatformThread::CurrentId(),
+ nullptr) {}
+
+} // namespace content
diff --git a/chromium/content/renderer/top_level_blame_context.h b/chromium/content/renderer/top_level_blame_context.h
new file mode 100644
index 00000000000..1138373e2cc
--- /dev/null
+++ b/chromium/content/renderer/top_level_blame_context.h
@@ -0,0 +1,25 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_RENDERER_TOP_LEVEL_BLAME_CONTEXT_H_
+#define CONTENT_RENDERER_TOP_LEVEL_BLAME_CONTEXT_H_
+
+#include "base/trace_event/blame_context.h"
+
+namespace content {
+
+// A blame context which spans all the frames in this renderer. Used for
+// attributing work which cannot be associated with a specific frame (e.g.,
+// garbage collection).
+class TopLevelBlameContext : public base::trace_event::BlameContext {
+ public:
+ TopLevelBlameContext();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TopLevelBlameContext);
+};
+
+} // namespace content
+
+#endif // CONTENT_RENDERER_TOP_LEVEL_BLAME_CONTEXT_H_
diff --git a/chromium/content/renderer/usb/DEPS b/chromium/content/renderer/usb/DEPS
index ddfef5f0857..b7aeef531c4 100644
--- a/chromium/content/renderer/usb/DEPS
+++ b/chromium/content/renderer/usb/DEPS
@@ -1,4 +1,3 @@
include_rules = [
- "+components/webusb/public/interfaces",
- "+device/devices_app/usb/public",
+ "+device/usb/public",
]
diff --git a/chromium/content/renderer/usb/type_converters.cc b/chromium/content/renderer/usb/type_converters.cc
index 62c9aab163b..5c47c934662 100644
--- a/chromium/content/renderer/usb/type_converters.cc
+++ b/chromium/content/renderer/usb/type_converters.cc
@@ -16,9 +16,9 @@ TypeConverter<blink::WebUSBDevice::TransferDirection,
device::usb::TransferDirection>::
Convert(const device::usb::TransferDirection& direction) {
switch (direction) {
- case device::usb::TRANSFER_DIRECTION_IN:
+ case device::usb::TransferDirection::INBOUND:
return blink::WebUSBDevice::TransferDirection::In;
- case device::usb::TRANSFER_DIRECTION_OUT:
+ case device::usb::TransferDirection::OUTBOUND:
return blink::WebUSBDevice::TransferDirection::Out;
default:
NOTREACHED();
@@ -33,12 +33,12 @@ TypeConverter<device::usb::TransferDirection,
Convert(const blink::WebUSBDevice::TransferDirection& direction) {
switch (direction) {
case blink::WebUSBDevice::TransferDirection::In:
- return device::usb::TRANSFER_DIRECTION_IN;
+ return device::usb::TransferDirection::INBOUND;
case blink::WebUSBDevice::TransferDirection::Out:
- return device::usb::TRANSFER_DIRECTION_OUT;
+ return device::usb::TransferDirection::OUTBOUND;
default:
NOTREACHED();
- return device::usb::TRANSFER_DIRECTION_IN;
+ return device::usb::TransferDirection::INBOUND;
}
}
@@ -49,14 +49,14 @@ TypeConverter<device::usb::ControlTransferType,
Convert(const blink::WebUSBDevice::RequestType& direction) {
switch (direction) {
case blink::WebUSBDevice::RequestType::Standard:
- return device::usb::CONTROL_TRANSFER_TYPE_STANDARD;
+ return device::usb::ControlTransferType::STANDARD;
case blink::WebUSBDevice::RequestType::Class:
- return device::usb::CONTROL_TRANSFER_TYPE_CLASS;
+ return device::usb::ControlTransferType::CLASS;
case blink::WebUSBDevice::RequestType::Vendor:
- return device::usb::CONTROL_TRANSFER_TYPE_VENDOR;
+ return device::usb::ControlTransferType::VENDOR;
default:
NOTREACHED();
- return device::usb::CONTROL_TRANSFER_TYPE_STANDARD;
+ return device::usb::ControlTransferType::STANDARD;
}
}
@@ -67,16 +67,16 @@ TypeConverter<device::usb::ControlTransferRecipient,
Convert(const blink::WebUSBDevice::RequestRecipient& direction) {
switch (direction) {
case blink::WebUSBDevice::RequestRecipient::Device:
- return device::usb::CONTROL_TRANSFER_RECIPIENT_DEVICE;
+ return device::usb::ControlTransferRecipient::DEVICE;
case blink::WebUSBDevice::RequestRecipient::Interface:
- return device::usb::CONTROL_TRANSFER_RECIPIENT_INTERFACE;
+ return device::usb::ControlTransferRecipient::INTERFACE;
case blink::WebUSBDevice::RequestRecipient::Endpoint:
- return device::usb::CONTROL_TRANSFER_RECIPIENT_ENDPOINT;
+ return device::usb::ControlTransferRecipient::ENDPOINT;
case blink::WebUSBDevice::RequestRecipient::Other:
- return device::usb::CONTROL_TRANSFER_RECIPIENT_OTHER;
+ return device::usb::ControlTransferRecipient::OTHER;
default:
NOTREACHED();
- return device::usb::CONTROL_TRANSFER_RECIPIENT_DEVICE;
+ return device::usb::ControlTransferRecipient::DEVICE;
}
}
@@ -103,11 +103,11 @@ blink::WebUSBDeviceInfo::Endpoint::Type TypeConverter<
device::usb::EndpointType>::Convert(const device::usb::EndpointType&
endpoint_type) {
switch (endpoint_type) {
- case device::usb::ENDPOINT_TYPE_BULK:
+ case device::usb::EndpointType::BULK:
return blink::WebUSBDeviceInfo::Endpoint::Type::Bulk;
- case device::usb::ENDPOINT_TYPE_INTERRUPT:
+ case device::usb::EndpointType::INTERRUPT:
return blink::WebUSBDeviceInfo::Endpoint::Type::Interrupt;
- case device::usb::ENDPOINT_TYPE_ISOCHRONOUS:
+ case device::usb::EndpointType::ISOCHRONOUS:
return blink::WebUSBDeviceInfo::Endpoint::Type::Isochronous;
default:
NOTREACHED();
@@ -213,6 +213,7 @@ TypeConverter<blink::WebUSBDeviceInfo, device::usb::DeviceInfoPtr>::Convert(
device.productName = blink::WebString::fromUTF8(info->product_name);
if (!info->serial_number.is_null())
device.serialNumber = blink::WebString::fromUTF8(info->serial_number);
+ device.activeConfiguration = info->active_configuration;
device.configurations =
blink::WebVector<blink::WebUSBDeviceInfo::Configuration>(
info->configurations.size());
diff --git a/chromium/content/renderer/usb/type_converters.h b/chromium/content/renderer/usb/type_converters.h
index 0ec030a95f7..3bdec856996 100644
--- a/chromium/content/renderer/usb/type_converters.h
+++ b/chromium/content/renderer/usb/type_converters.h
@@ -4,8 +4,8 @@
#include "mojo/public/cpp/bindings/type_converter.h"
-#include "device/devices_app/usb/public/interfaces/device.mojom.h"
-#include "device/devices_app/usb/public/interfaces/device_manager.mojom.h"
+#include "device/usb/public/interfaces/device.mojom.h"
+#include "device/usb/public/interfaces/device_manager.mojom.h"
#include "third_party/WebKit/public/platform/modules/webusb/WebUSBDevice.h"
#include "third_party/WebKit/public/platform/modules/webusb/WebUSBDeviceFilter.h"
#include "third_party/WebKit/public/platform/modules/webusb/WebUSBDeviceInfo.h"
diff --git a/chromium/content/renderer/usb/web_usb_client_impl.cc b/chromium/content/renderer/usb/web_usb_client_impl.cc
index ed9246a0aef..fc79424dfe3 100644
--- a/chromium/content/renderer/usb/web_usb_client_impl.cc
+++ b/chromium/content/renderer/usb/web_usb_client_impl.cc
@@ -5,10 +5,13 @@
#include "content/renderer/usb/web_usb_client_impl.h"
#include <stddef.h>
+
+#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/callback.h"
+#include "base/memory/ptr_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/move.h"
#include "base/strings/utf_string_conversions.h"
@@ -20,7 +23,6 @@
#include "mojo/public/cpp/bindings/array.h"
#include "mojo/public/cpp/bindings/interface_request.h"
#include "third_party/WebKit/public/platform/WebCallbacks.h"
-#include "third_party/WebKit/public/platform/WebPassOwnPtr.h"
#include "third_party/WebKit/public/platform/modules/webusb/WebUSBDeviceFilter.h"
#include "third_party/WebKit/public/platform/modules/webusb/WebUSBDeviceInfo.h"
#include "third_party/WebKit/public/platform/modules/webusb/WebUSBDeviceRequestOptions.h"
@@ -57,8 +59,9 @@ void OnGetDevicesComplete(
ScopedWebCallbacks<blink::WebUSBClientGetDevicesCallbacks> scoped_callbacks,
device::usb::DeviceManager* device_manager,
mojo::Array<device::usb::DeviceInfoPtr> results) {
- blink::WebVector<blink::WebUSBDevice*>* devices =
- new blink::WebVector<blink::WebUSBDevice*>(results.size());
+ // TODO(dcheng): This WebVector should hold smart pointers.
+ std::unique_ptr<blink::WebVector<blink::WebUSBDevice*>> devices(
+ new blink::WebVector<blink::WebUSBDevice*>(results.size()));
for (size_t i = 0; i < results.size(); ++i) {
device::usb::DevicePtr device;
device_manager->GetDevice(results[i]->guid, mojo::GetProxy(&device));
@@ -66,7 +69,7 @@ void OnGetDevicesComplete(
std::move(device),
mojo::ConvertTo<blink::WebUSBDeviceInfo>(results[i]));
}
- scoped_callbacks.PassCallbacks()->onSuccess(blink::adoptWebPtr(devices));
+ scoped_callbacks.PassCallbacks()->onSuccess(std::move(devices));
}
void OnRequestDevicesComplete(
@@ -77,10 +80,10 @@ void OnRequestDevicesComplete(
if (result) {
device::usb::DevicePtr device;
device_manager->GetDevice(result->guid, mojo::GetProxy(&device));
- blink::WebUSBDevice* web_usb_device = new WebUSBDeviceImpl(
- std::move(device), mojo::ConvertTo<blink::WebUSBDeviceInfo>(result));
+ std::unique_ptr<blink::WebUSBDevice> web_usb_device(new WebUSBDeviceImpl(
+ std::move(device), mojo::ConvertTo<blink::WebUSBDeviceInfo>(result)));
- scoped_callbacks->onSuccess(blink::adoptWebPtr(web_usb_device));
+ scoped_callbacks->onSuccess(std::move(web_usb_device));
} else {
scoped_callbacks->onError(
blink::WebUSBError(blink::WebUSBError::Error::NotFound,
@@ -107,9 +110,9 @@ void WebUSBClientImpl::getDevices(
void WebUSBClientImpl::requestDevice(
const blink::WebUSBDeviceRequestOptions& options,
blink::WebUSBClientRequestDeviceCallbacks* callbacks) {
- if (!webusb_permission_bubble_) {
+ if (!chooser_service_) {
service_registry_->ConnectToRemoteService(
- mojo::GetProxy(&webusb_permission_bubble_));
+ mojo::GetProxy(&chooser_service_));
}
auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
@@ -117,14 +120,14 @@ void WebUSBClientImpl::requestDevice(
mojo::Array<device::usb::DeviceFilterPtr> device_filters =
mojo::Array<device::usb::DeviceFilterPtr>::From(options.filters);
- webusb_permission_bubble_->GetPermission(
+ chooser_service_->GetPermission(
std::move(device_filters),
base::Bind(&OnRequestDevicesComplete, base::Passed(&scoped_callbacks),
base::Unretained(device_manager_.get())));
}
-void WebUSBClientImpl::setObserver(Observer* observer) {
- if (!observer_) {
+void WebUSBClientImpl::addObserver(Observer* observer) {
+ if (observers_.empty()) {
// Set up two sequential calls to GetDeviceChanges to avoid latency.
device::usb::DeviceManager* device_manager = GetDeviceManager();
device_manager->GetDeviceChanges(base::Bind(
@@ -133,7 +136,12 @@ void WebUSBClientImpl::setObserver(Observer* observer) {
&WebUSBClientImpl::OnDeviceChangeNotification, base::Unretained(this)));
}
- observer_ = observer;
+ observers_.insert(observer);
+}
+
+void WebUSBClientImpl::removeObserver(Observer* observer) {
+ DCHECK(ContainsKey(observers_, observer));
+ observers_.erase(observer);
}
device::usb::DeviceManager* WebUSBClientImpl::GetDeviceManager() {
@@ -144,7 +152,7 @@ device::usb::DeviceManager* WebUSBClientImpl::GetDeviceManager() {
void WebUSBClientImpl::OnDeviceChangeNotification(
device::usb::DeviceChangeNotificationPtr notification) {
- if (!observer_)
+ if (observers_.empty())
return;
device_manager_->GetDeviceChanges(base::Bind(
@@ -152,20 +160,20 @@ void WebUSBClientImpl::OnDeviceChangeNotification(
for (size_t i = 0; i < notification->devices_added.size(); ++i) {
const device::usb::DeviceInfoPtr& device_info =
notification->devices_added[i];
- device::usb::DevicePtr device;
- device_manager_->GetDevice(device_info->guid, mojo::GetProxy(&device));
- observer_->onDeviceConnected(blink::adoptWebPtr(new WebUSBDeviceImpl(
- std::move(device),
- mojo::ConvertTo<blink::WebUSBDeviceInfo>(device_info))));
+ for (auto observer : observers_) {
+ device::usb::DevicePtr device;
+ device_manager_->GetDevice(device_info->guid, mojo::GetProxy(&device));
+ observer->onDeviceConnected(base::WrapUnique(new WebUSBDeviceImpl(
+ std::move(device),
+ mojo::ConvertTo<blink::WebUSBDeviceInfo>(device_info))));
+ }
}
for (size_t i = 0; i < notification->devices_removed.size(); ++i) {
const device::usb::DeviceInfoPtr& device_info =
notification->devices_removed[i];
- device::usb::DevicePtr device;
- device_manager_->GetDevice(device_info->guid, mojo::GetProxy(&device));
- observer_->onDeviceDisconnected(blink::adoptWebPtr(new WebUSBDeviceImpl(
- std::move(device),
- mojo::ConvertTo<blink::WebUSBDeviceInfo>(device_info))));
+ for (auto observer : observers_)
+ observer->onDeviceDisconnected(base::WrapUnique(new WebUSBDeviceImpl(
+ nullptr, mojo::ConvertTo<blink::WebUSBDeviceInfo>(device_info))));
}
}
diff --git a/chromium/content/renderer/usb/web_usb_client_impl.h b/chromium/content/renderer/usb/web_usb_client_impl.h
index fddd809d8dd..10fe314447e 100644
--- a/chromium/content/renderer/usb/web_usb_client_impl.h
+++ b/chromium/content/renderer/usb/web_usb_client_impl.h
@@ -6,8 +6,8 @@
#define CONTENT_RENDERER_USB_WEB_USB_CLIENT_IMPL_H_
#include "base/macros.h"
-#include "components/webusb/public/interfaces/webusb_permission_bubble.mojom.h"
-#include "device/devices_app/usb/public/interfaces/device_manager.mojom.h"
+#include "device/usb/public/interfaces/chooser_service.mojom.h"
+#include "device/usb/public/interfaces/device_manager.mojom.h"
#include "third_party/WebKit/public/platform/modules/webusb/WebUSBClient.h"
namespace content {
@@ -25,7 +25,8 @@ class WebUSBClientImpl : public blink::WebUSBClient {
void requestDevice(
const blink::WebUSBDeviceRequestOptions& options,
blink::WebUSBClientRequestDeviceCallbacks* callbacks) override;
- void setObserver(Observer* observer) override;
+ void addObserver(Observer* observer) override;
+ void removeObserver(Observer* observer) override;
device::usb::DeviceManager* GetDeviceManager();
void OnDeviceChangeNotification(
@@ -33,8 +34,8 @@ class WebUSBClientImpl : public blink::WebUSBClient {
ServiceRegistry* const service_registry_;
device::usb::DeviceManagerPtr device_manager_;
- webusb::WebUsbPermissionBubblePtr webusb_permission_bubble_;
- Observer* observer_ = nullptr;
+ device::usb::ChooserServicePtr chooser_service_;
+ std::set<Observer*> observers_;
DISALLOW_COPY_AND_ASSIGN(WebUSBClientImpl);
};
diff --git a/chromium/content/renderer/usb/web_usb_device_impl.cc b/chromium/content/renderer/usb/web_usb_device_impl.cc
index d1db890274a..bb2ca99c194 100644
--- a/chromium/content/renderer/usb/web_usb_device_impl.cc
+++ b/chromium/content/renderer/usb/web_usb_device_impl.cc
@@ -9,11 +9,11 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/child/mojo/type_converters.h"
#include "content/child/scoped_web_callbacks.h"
#include "content/renderer/usb/type_converters.h"
-#include "device/devices_app/public/cpp/constants.h"
#include "mojo/shell/public/cpp/connect.h"
-#include "mojo/shell/public/interfaces/shell.mojom.h"
+#include "mojo/shell/public/interfaces/connector.mojom.h"
#include "third_party/WebKit/public/platform/WebVector.h"
#include "third_party/WebKit/public/platform/modules/webusb/WebUSBDeviceInfo.h"
#include "third_party/WebKit/public/platform/modules/webusb/WebUSBTransferInfo.h"
@@ -24,8 +24,8 @@ namespace {
const char kClaimInterfaceFailed[] = "Unable to claim interface.";
const char kClearHaltFailed[] = "Unable to clear endpoint.";
+const char kDeviceAlreadyOpen[] = "Device has already been opened.";
const char kDeviceNoAccess[] = "Access denied.";
-const char kDeviceNotConfigured[] = "Device not configured.";
const char kDeviceUnavailable[] = "Device unavailable.";
const char kDeviceResetFailed[] = "Unable to reset the device.";
const char kReleaseInterfaceFailed[] = "Unable to release interface.";
@@ -66,14 +66,19 @@ void OnOpenDevice(
device::usb::OpenDeviceError error) {
auto scoped_callbacks = callbacks.PassCallbacks();
switch(error) {
- case device::usb::OPEN_DEVICE_ERROR_OK:
+ case device::usb::OpenDeviceError::OK:
scoped_callbacks->onSuccess();
break;
- case device::usb::OPEN_DEVICE_ERROR_ACCESS_DENIED:
+ case device::usb::OpenDeviceError::ACCESS_DENIED:
scoped_callbacks->onError(blink::WebUSBError(
blink::WebUSBError::Error::Security,
base::ASCIIToUTF16(kDeviceNoAccess)));
break;
+ case device::usb::OpenDeviceError::ALREADY_OPEN:
+ scoped_callbacks->onError(blink::WebUSBError(
+ blink::WebUSBError::Error::InvalidState,
+ base::ASCIIToUTF16(kDeviceAlreadyOpen)));
+ break;
default:
NOTREACHED();
}
@@ -84,19 +89,6 @@ void OnDeviceClosed(
callbacks.PassCallbacks()->onSuccess();
}
-void OnGetConfiguration(
- ScopedWebCallbacks<blink::WebUSBDeviceGetConfigurationCallbacks> callbacks,
- uint8_t configuration_value) {
- auto scoped_callbacks = callbacks.PassCallbacks();
- if (configuration_value == 0) {
- RejectWithError(blink::WebUSBError(blink::WebUSBError::Error::NotFound,
- kDeviceNotConfigured),
- std::move(scoped_callbacks));
- } else {
- scoped_callbacks->onSuccess(configuration_value);
- }
-}
-
void HandlePassFailDeviceOperation(
ScopedWebCallbacks<blink::WebCallbacks<void, const blink::WebUSBError&>>
callbacks,
@@ -113,45 +105,113 @@ void HandlePassFailDeviceOperation(
}
void OnTransferIn(
- ScopedWebCallbacks<blink::WebUSBDeviceControlTransferCallbacks> callbacks,
+ ScopedWebCallbacks<blink::WebUSBDeviceTransferCallbacks> callbacks,
device::usb::TransferStatus status,
mojo::Array<uint8_t> data) {
auto scoped_callbacks = callbacks.PassCallbacks();
- if (status != device::usb::TRANSFER_STATUS_COMPLETED) {
- RejectWithTransferError(std::move(scoped_callbacks));
- return;
+ blink::WebUSBTransferInfo::Status web_status;
+ switch (status) {
+ case device::usb::TransferStatus::COMPLETED:
+ web_status = blink::WebUSBTransferInfo::Status::Ok;
+ break;
+ case device::usb::TransferStatus::STALLED:
+ web_status = blink::WebUSBTransferInfo::Status::Stall;
+ break;
+ case device::usb::TransferStatus::BABBLE:
+ web_status = blink::WebUSBTransferInfo::Status::Babble;
+ break;
+ default:
+ RejectWithTransferError(std::move(scoped_callbacks));
+ return;
}
scoped_ptr<blink::WebUSBTransferInfo> info(new blink::WebUSBTransferInfo());
- info->status = blink::WebUSBTransferInfo::Status::Ok;
+ info->status.assign(
+ std::vector<blink::WebUSBTransferInfo::Status>(1, web_status));
info->data.assign(data);
- scoped_callbacks->onSuccess(adoptWebPtr(info.release()));
+ scoped_callbacks->onSuccess(std::move(info));
}
void OnTransferOut(
- ScopedWebCallbacks<blink::WebUSBDeviceControlTransferCallbacks> callbacks,
+ ScopedWebCallbacks<blink::WebUSBDeviceTransferCallbacks> callbacks,
size_t bytes_written,
device::usb::TransferStatus status) {
auto scoped_callbacks = callbacks.PassCallbacks();
- scoped_ptr<blink::WebUSBTransferInfo> info(new blink::WebUSBTransferInfo());
+ blink::WebUSBTransferInfo::Status web_status;
switch (status) {
- case device::usb::TRANSFER_STATUS_COMPLETED:
- info->status = blink::WebUSBTransferInfo::Status::Ok;
+ case device::usb::TransferStatus::COMPLETED:
+ web_status = blink::WebUSBTransferInfo::Status::Ok;
break;
- case device::usb::TRANSFER_STATUS_STALLED:
- info->status = blink::WebUSBTransferInfo::Status::Stall;
- break;
- case device::usb::TRANSFER_STATUS_BABBLE:
- info->status = blink::WebUSBTransferInfo::Status::Babble;
+ case device::usb::TransferStatus::STALLED:
+ web_status = blink::WebUSBTransferInfo::Status::Stall;
break;
default:
RejectWithTransferError(std::move(scoped_callbacks));
return;
}
-
// TODO(rockot): Device::ControlTransferOut should expose the number of bytes
// actually transferred so we can send it from here.
- info->bytesWritten = bytes_written;
- scoped_callbacks->onSuccess(adoptWebPtr(info.release()));
+ scoped_ptr<blink::WebUSBTransferInfo> info(new blink::WebUSBTransferInfo());
+ info->status.assign(
+ std::vector<blink::WebUSBTransferInfo::Status>(1, web_status));
+ info->bytesTransferred.assign(std::vector<uint32_t>(1, bytes_written));
+ scoped_callbacks->onSuccess(std::move(info));
+}
+
+void OnIsochronousTransferIn(
+ ScopedWebCallbacks<blink::WebUSBDeviceTransferCallbacks> callbacks,
+ mojo::Array<uint8_t> data,
+ mojo::Array<device::usb::IsochronousPacketPtr> packets) {
+ auto scoped_callbacks = callbacks.PassCallbacks();
+ scoped_ptr<blink::WebUSBTransferInfo> info(new blink::WebUSBTransferInfo());
+ info->data.assign(data);
+ info->status =
+ blink::WebVector<blink::WebUSBTransferInfo::Status>(packets.size());
+ info->packetLength = blink::WebVector<uint32_t>(packets.size());
+ info->bytesTransferred = blink::WebVector<uint32_t>(packets.size());
+ for (size_t i = 0; i < packets.size(); ++i) {
+ switch (packets[i]->status) {
+ case device::usb::TransferStatus::COMPLETED:
+ info->status[i] = blink::WebUSBTransferInfo::Status::Ok;
+ break;
+ case device::usb::TransferStatus::STALLED:
+ info->status[i] = blink::WebUSBTransferInfo::Status::Stall;
+ break;
+ case device::usb::TransferStatus::BABBLE:
+ info->status[i] = blink::WebUSBTransferInfo::Status::Babble;
+ break;
+ default:
+ RejectWithTransferError(std::move(scoped_callbacks));
+ return;
+ }
+ info->packetLength[i] = packets[i]->length;
+ info->bytesTransferred[i] = packets[i]->transferred_length;
+ }
+ scoped_callbacks->onSuccess(std::move(info));
+}
+
+void OnIsochronousTransferOut(
+ ScopedWebCallbacks<blink::WebUSBDeviceTransferCallbacks> callbacks,
+ mojo::Array<device::usb::IsochronousPacketPtr> packets) {
+ auto scoped_callbacks = callbacks.PassCallbacks();
+ scoped_ptr<blink::WebUSBTransferInfo> info(new blink::WebUSBTransferInfo());
+ info->status =
+ blink::WebVector<blink::WebUSBTransferInfo::Status>(packets.size());
+ info->bytesTransferred = blink::WebVector<uint32_t>(packets.size());
+ for (size_t i = 0; i < packets.size(); ++i) {
+ switch (packets[i]->status) {
+ case device::usb::TransferStatus::COMPLETED:
+ info->status[i] = blink::WebUSBTransferInfo::Status::Ok;
+ break;
+ case device::usb::TransferStatus::STALLED:
+ info->status[i] = blink::WebUSBTransferInfo::Status::Stall;
+ break;
+ default:
+ RejectWithTransferError(std::move(scoped_callbacks));
+ return;
+ }
+ info->bytesTransferred[i] = packets[i]->transferred_length;
+ }
+ scoped_callbacks->onSuccess(std::move(info));
}
} // namespace
@@ -160,7 +220,10 @@ WebUSBDeviceImpl::WebUSBDeviceImpl(device::usb::DevicePtr device,
const blink::WebUSBDeviceInfo& device_info)
: device_(std::move(device)),
device_info_(device_info),
- weak_factory_(this) {}
+ weak_factory_(this) {
+ if (device_)
+ device_.set_connection_error_handler([this]() { device_.reset(); });
+}
WebUSBDeviceImpl::~WebUSBDeviceImpl() {}
@@ -170,49 +233,48 @@ const blink::WebUSBDeviceInfo& WebUSBDeviceImpl::info() const {
void WebUSBDeviceImpl::open(blink::WebUSBDeviceOpenCallbacks* callbacks) {
auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
- device_->Open(base::Bind(&OnOpenDevice, base::Passed(&scoped_callbacks)));
+ if (device_)
+ device_->Open(base::Bind(&OnOpenDevice, base::Passed(&scoped_callbacks)));
}
void WebUSBDeviceImpl::close(blink::WebUSBDeviceCloseCallbacks* callbacks) {
auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
- device_->Close(base::Bind(&OnDeviceClosed, base::Passed(&scoped_callbacks)));
-}
-
-void WebUSBDeviceImpl::getConfiguration(
- blink::WebUSBDeviceGetConfigurationCallbacks* callbacks) {
- auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
- device_->GetConfiguration(
- base::Bind(&OnGetConfiguration, base::Passed(&scoped_callbacks)));
+ if (device_)
+ device_->Close(
+ base::Bind(&OnDeviceClosed, base::Passed(&scoped_callbacks)));
}
void WebUSBDeviceImpl::setConfiguration(
uint8_t configuration_value,
blink::WebUSBDeviceSetConfigurationCallbacks* callbacks) {
auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
- device_->SetConfiguration(
- configuration_value,
- base::Bind(&HandlePassFailDeviceOperation,
- base::Passed(&scoped_callbacks), kSetConfigurationFailed));
+ if (device_)
+ device_->SetConfiguration(
+ configuration_value,
+ base::Bind(&HandlePassFailDeviceOperation,
+ base::Passed(&scoped_callbacks), kSetConfigurationFailed));
}
void WebUSBDeviceImpl::claimInterface(
uint8_t interface_number,
blink::WebUSBDeviceClaimInterfaceCallbacks* callbacks) {
auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
- device_->ClaimInterface(
- interface_number,
- base::Bind(&HandlePassFailDeviceOperation,
- base::Passed(&scoped_callbacks), kClaimInterfaceFailed));
+ if (device_)
+ device_->ClaimInterface(
+ interface_number,
+ base::Bind(&HandlePassFailDeviceOperation,
+ base::Passed(&scoped_callbacks), kClaimInterfaceFailed));
}
void WebUSBDeviceImpl::releaseInterface(
uint8_t interface_number,
blink::WebUSBDeviceReleaseInterfaceCallbacks* callbacks) {
auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
- device_->ReleaseInterface(
- interface_number,
- base::Bind(&HandlePassFailDeviceOperation,
- base::Passed(&scoped_callbacks), kReleaseInterfaceFailed));
+ if (device_)
+ device_->ReleaseInterface(
+ interface_number,
+ base::Bind(&HandlePassFailDeviceOperation,
+ base::Passed(&scoped_callbacks), kReleaseInterfaceFailed));
}
void WebUSBDeviceImpl::setInterface(
@@ -220,20 +282,22 @@ void WebUSBDeviceImpl::setInterface(
uint8_t alternate_setting,
blink::WebUSBDeviceSetInterfaceAlternateSettingCallbacks* callbacks) {
auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
- device_->SetInterfaceAlternateSetting(
- interface_number, alternate_setting,
- base::Bind(&HandlePassFailDeviceOperation,
- base::Passed(&scoped_callbacks), kSetInterfaceFailed));
+ if (device_)
+ device_->SetInterfaceAlternateSetting(
+ interface_number, alternate_setting,
+ base::Bind(&HandlePassFailDeviceOperation,
+ base::Passed(&scoped_callbacks), kSetInterfaceFailed));
}
void WebUSBDeviceImpl::clearHalt(
uint8_t endpoint_number,
blink::WebUSBDeviceClearHaltCallbacks* callbacks) {
auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
- device_->ClearHalt(
- endpoint_number,
- base::Bind(&HandlePassFailDeviceOperation,
- base::Passed(&scoped_callbacks), kClearHaltFailed));
+ if (device_)
+ device_->ClearHalt(
+ endpoint_number,
+ base::Bind(&HandlePassFailDeviceOperation,
+ base::Passed(&scoped_callbacks), kClearHaltFailed));
}
void WebUSBDeviceImpl::controlTransfer(
@@ -241,8 +305,11 @@ void WebUSBDeviceImpl::controlTransfer(
uint8_t* data,
size_t data_size,
unsigned int timeout,
- blink::WebUSBDeviceControlTransferCallbacks* callbacks) {
+ blink::WebUSBDeviceTransferCallbacks* callbacks) {
auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
+ if (!device_)
+ return;
+
device::usb::ControlTransferParamsPtr params =
device::usb::ControlTransferParams::From(parameters);
switch (parameters.direction) {
@@ -274,8 +341,11 @@ void WebUSBDeviceImpl::transfer(
uint8_t* data,
size_t data_size,
unsigned int timeout,
- blink::WebUSBDeviceBulkTransferCallbacks* callbacks) {
+ blink::WebUSBDeviceTransferCallbacks* callbacks) {
auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
+ if (!device_)
+ return;
+
switch (direction) {
case WebUSBDevice::TransferDirection::In:
device_->GenericTransferIn(
@@ -299,11 +369,49 @@ void WebUSBDeviceImpl::transfer(
}
}
+void WebUSBDeviceImpl::isochronousTransfer(
+ blink::WebUSBDevice::TransferDirection direction,
+ uint8_t endpoint_number,
+ uint8_t* data,
+ size_t data_size,
+ blink::WebVector<uint32_t> packet_lengths,
+ unsigned int timeout,
+ blink::WebUSBDeviceTransferCallbacks* callbacks) {
+ auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
+ if (!device_)
+ return;
+
+ switch (direction) {
+ case WebUSBDevice::TransferDirection::In:
+ device_->IsochronousTransferIn(
+ endpoint_number, mojo::Array<uint32_t>::From(packet_lengths), timeout,
+ base::Bind(&OnIsochronousTransferIn,
+ base::Passed(&scoped_callbacks)));
+ break;
+ case WebUSBDevice::TransferDirection::Out: {
+ std::vector<uint8_t> bytes;
+ if (data)
+ bytes.assign(data, data + data_size);
+ mojo::Array<uint8_t> mojo_bytes;
+ mojo_bytes.Swap(&bytes);
+ device_->IsochronousTransferOut(
+ endpoint_number, std::move(mojo_bytes),
+ mojo::Array<uint32_t>::From(packet_lengths), timeout,
+ base::Bind(&OnIsochronousTransferOut,
+ base::Passed(&scoped_callbacks)));
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+}
+
void WebUSBDeviceImpl::reset(blink::WebUSBDeviceResetCallbacks* callbacks) {
auto scoped_callbacks = MakeScopedUSBCallbacks(callbacks);
- device_->Reset(base::Bind(&HandlePassFailDeviceOperation,
- base::Passed(&scoped_callbacks),
- kDeviceResetFailed));
+ if (device_)
+ device_->Reset(base::Bind(&HandlePassFailDeviceOperation,
+ base::Passed(&scoped_callbacks),
+ kDeviceResetFailed));
}
} // namespace content
diff --git a/chromium/content/renderer/usb/web_usb_device_impl.h b/chromium/content/renderer/usb/web_usb_device_impl.h
index dd2e9a211ef..dea2e8f24af 100644
--- a/chromium/content/renderer/usb/web_usb_device_impl.h
+++ b/chromium/content/renderer/usb/web_usb_device_impl.h
@@ -11,9 +11,9 @@
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
-#include "device/devices_app/usb/public/interfaces/device.mojom.h"
-#include "device/devices_app/usb/public/interfaces/device_manager.mojom.h"
-#include "mojo/shell/public/interfaces/service_provider.mojom.h"
+#include "device/usb/public/interfaces/device.mojom.h"
+#include "device/usb/public/interfaces/device_manager.mojom.h"
+#include "mojo/shell/public/interfaces/interface_provider.mojom.h"
#include "third_party/WebKit/public/platform/modules/webusb/WebUSBDevice.h"
#include "third_party/WebKit/public/platform/modules/webusb/WebUSBDeviceInfo.h"
#include "third_party/WebKit/public/platform/modules/webusb/WebUSBError.h"
@@ -35,8 +35,6 @@ class WebUSBDeviceImpl : public blink::WebUSBDevice {
const blink::WebUSBDeviceInfo& info() const override;
void open(blink::WebUSBDeviceOpenCallbacks* callbacks) override;
void close(blink::WebUSBDeviceCloseCallbacks* callbacks) override;
- void getConfiguration(
- blink::WebUSBDeviceGetConfigurationCallbacks* callbacks) override;
void setConfiguration(
uint8_t configuration_value,
blink::WebUSBDeviceSetConfigurationCallbacks* callbacks) override;
@@ -57,13 +55,21 @@ class WebUSBDeviceImpl : public blink::WebUSBDevice {
uint8_t* data,
size_t data_size,
unsigned int timeout,
- blink::WebUSBDeviceControlTransferCallbacks* callbacks) override;
+ blink::WebUSBDeviceTransferCallbacks* callbacks) override;
void transfer(blink::WebUSBDevice::TransferDirection direction,
uint8_t endpoint_number,
uint8_t* data,
size_t data_size,
unsigned int timeout,
- blink::WebUSBDeviceBulkTransferCallbacks* callbacks) override;
+ blink::WebUSBDeviceTransferCallbacks* callbacks) override;
+ void isochronousTransfer(
+ blink::WebUSBDevice::TransferDirection direction,
+ uint8_t endpoint_number,
+ uint8_t* data,
+ size_t data_size,
+ blink::WebVector<uint32_t> packet_lengths,
+ unsigned int timeout,
+ blink::WebUSBDeviceTransferCallbacks* callbacks) override;
void reset(blink::WebUSBDeviceResetCallbacks* callbacks) override;
device::usb::DevicePtr device_;
diff --git a/chromium/content/renderer/vr/vr_dispatcher.cc b/chromium/content/renderer/vr/vr_dispatcher.cc
index 07391761338..acd893747f3 100644
--- a/chromium/content/renderer/vr/vr_dispatcher.cc
+++ b/chromium/content/renderer/vr/vr_dispatcher.cc
@@ -18,7 +18,7 @@ VRDispatcher::VRDispatcher(ServiceRegistry* service_registry)
VRDispatcher::~VRDispatcher() {
}
-VRServicePtr& VRDispatcher::GetVRServicePtr() {
+mojom::VRServicePtr& VRDispatcher::GetVRServicePtr() {
if (!vr_service_) {
service_registry_->ConnectToRemoteService(mojo::GetProxy(&vr_service_));
}
@@ -46,8 +46,9 @@ void VRDispatcher::resetSensor(unsigned int index) {
GetVRServicePtr()->ResetSensor(index);
}
-void VRDispatcher::OnGetDevices(int request_id,
- const mojo::Array<VRDeviceInfoPtr>& devices) {
+void VRDispatcher::OnGetDevices(
+ int request_id,
+ const mojo::Array<mojom::VRDeviceInfoPtr>& devices) {
blink::WebVector<blink::WebVRDevice> web_devices(devices.size());
blink::WebVRGetDevicesCallback* callback =
@@ -64,7 +65,7 @@ void VRDispatcher::OnGetDevices(int request_id,
}
void VRDispatcher::OnGetSensorState(blink::WebHMDSensorState* state,
- const VRSensorStatePtr& mojo_state) {
+ const mojom::VRSensorStatePtr& mojo_state) {
*state = mojo_state.To<blink::WebHMDSensorState>();
}
diff --git a/chromium/content/renderer/vr/vr_dispatcher.h b/chromium/content/renderer/vr/vr_dispatcher.h
index b027d05be74..7e2f422a051 100644
--- a/chromium/content/renderer/vr/vr_dispatcher.h
+++ b/chromium/content/renderer/vr/vr_dispatcher.h
@@ -33,20 +33,20 @@ class VRDispatcher : NON_EXPORTED_BASE(public blink::WebVRClient) {
private:
// Helper method that returns an initialized PermissionServicePtr.
- VRServicePtr& GetVRServicePtr();
+ mojom::VRServicePtr& GetVRServicePtr();
// Callback handlers
void OnGetDevices(int request_id,
- const mojo::Array<VRDeviceInfoPtr>& devices);
+ const mojo::Array<mojom::VRDeviceInfoPtr>& devices);
static void OnGetSensorState(blink::WebHMDSensorState* state,
- const VRSensorStatePtr& mojo_state);
+ const mojom::VRSensorStatePtr& mojo_state);
// Tracks requests sent to browser to match replies with callbacks.
// Owns callback objects.
IDMap<blink::WebVRGetDevicesCallback, IDMapOwnPointer> pending_requests_;
ServiceRegistry* service_registry_;
- VRServicePtr vr_service_;
+ mojom::VRServicePtr vr_service_;
DISALLOW_COPY_AND_ASSIGN(VRDispatcher);
};
diff --git a/chromium/content/renderer/vr/vr_type_converters.cc b/chromium/content/renderer/vr/vr_type_converters.cc
index ba220a4f4f9..61b14d1e9fa 100644
--- a/chromium/content/renderer/vr/vr_type_converters.cc
+++ b/chromium/content/renderer/vr/vr_type_converters.cc
@@ -8,14 +8,14 @@
#include <algorithm>
-using content::VRVector3Ptr;
-using content::VRVector4Ptr;
-using content::VRRectPtr;
-using content::VRFieldOfViewPtr;
-using content::VREyeParametersPtr;
-using content::VRHMDInfoPtr;
-using content::VRDeviceInfoPtr;
-using content::VRSensorStatePtr;
+using content::mojom::VRVector3Ptr;
+using content::mojom::VRVector4Ptr;
+using content::mojom::VRRectPtr;
+using content::mojom::VRFieldOfViewPtr;
+using content::mojom::VREyeParametersPtr;
+using content::mojom::VRHMDInfoPtr;
+using content::mojom::VRDeviceInfoPtr;
+using content::mojom::VRSensorStatePtr;
namespace mojo {
diff --git a/chromium/content/renderer/vr/vr_type_converters.h b/chromium/content/renderer/vr/vr_type_converters.h
index 8902cd5a844..86b874abb2d 100644
--- a/chromium/content/renderer/vr/vr_type_converters.h
+++ b/chromium/content/renderer/vr/vr_type_converters.h
@@ -15,46 +15,50 @@ namespace mojo {
// and vice versa.
template <>
-struct TypeConverter<blink::WebVRVector3, content::VRVector3Ptr> {
- static blink::WebVRVector3 Convert(const content::VRVector3Ptr& input);
+struct TypeConverter<blink::WebVRVector3, content::mojom::VRVector3Ptr> {
+ static blink::WebVRVector3 Convert(const content::mojom::VRVector3Ptr& input);
};
template <>
-struct TypeConverter<blink::WebVRVector4, content::VRVector4Ptr> {
- static blink::WebVRVector4 Convert(const content::VRVector4Ptr& input);
+struct TypeConverter<blink::WebVRVector4, content::mojom::VRVector4Ptr> {
+ static blink::WebVRVector4 Convert(const content::mojom::VRVector4Ptr& input);
};
template <>
-struct TypeConverter<blink::WebVRRect, content::VRRectPtr> {
- static blink::WebVRRect Convert(const content::VRRectPtr& input);
+struct TypeConverter<blink::WebVRRect, content::mojom::VRRectPtr> {
+ static blink::WebVRRect Convert(const content::mojom::VRRectPtr& input);
};
template <>
-struct TypeConverter<blink::WebVRFieldOfView, content::VRFieldOfViewPtr> {
+struct TypeConverter<blink::WebVRFieldOfView,
+ content::mojom::VRFieldOfViewPtr> {
static blink::WebVRFieldOfView Convert(
- const content::VRFieldOfViewPtr& input);
+ const content::mojom::VRFieldOfViewPtr& input);
};
template <>
-struct TypeConverter<blink::WebVREyeParameters, content::VREyeParametersPtr> {
+struct TypeConverter<blink::WebVREyeParameters,
+ content::mojom::VREyeParametersPtr> {
static blink::WebVREyeParameters Convert(
- const content::VREyeParametersPtr& input);
+ const content::mojom::VREyeParametersPtr& input);
};
template <>
-struct TypeConverter<blink::WebVRHMDInfo, content::VRHMDInfoPtr> {
- static blink::WebVRHMDInfo Convert(const content::VRHMDInfoPtr& input);
+struct TypeConverter<blink::WebVRHMDInfo, content::mojom::VRHMDInfoPtr> {
+ static blink::WebVRHMDInfo Convert(const content::mojom::VRHMDInfoPtr& input);
};
template <>
-struct TypeConverter<blink::WebVRDevice, content::VRDeviceInfoPtr> {
- static blink::WebVRDevice Convert(const content::VRDeviceInfoPtr& input);
+struct TypeConverter<blink::WebVRDevice, content::mojom::VRDeviceInfoPtr> {
+ static blink::WebVRDevice Convert(
+ const content::mojom::VRDeviceInfoPtr& input);
};
template <>
-struct TypeConverter<blink::WebHMDSensorState, content::VRSensorStatePtr> {
+struct TypeConverter<blink::WebHMDSensorState,
+ content::mojom::VRSensorStatePtr> {
static blink::WebHMDSensorState Convert(
- const content::VRSensorStatePtr& input);
+ const content::mojom::VRSensorStatePtr& input);
};
} // namespace mojo
diff --git a/chromium/content/renderer/wake_lock/wake_lock_dispatcher.h b/chromium/content/renderer/wake_lock/wake_lock_dispatcher.h
index 70ce86a12e9..5922318a73e 100644
--- a/chromium/content/renderer/wake_lock/wake_lock_dispatcher.h
+++ b/chromium/content/renderer/wake_lock/wake_lock_dispatcher.h
@@ -23,7 +23,7 @@ class WakeLockDispatcher : public RenderFrameObserver,
// WebWakeLockClient implementation.
void requestKeepScreenAwake(bool keepScreenAwake) override;
- WakeLockServicePtr wake_lock_service_;
+ mojom::WakeLockServicePtr wake_lock_service_;
};
} // namespace content
diff --git a/chromium/content/renderer/webgraphicscontext3d_provider_impl.cc b/chromium/content/renderer/webgraphicscontext3d_provider_impl.cc
index 855bd3df44d..28a3327341d 100644
--- a/chromium/content/renderer/webgraphicscontext3d_provider_impl.cc
+++ b/chromium/content/renderer/webgraphicscontext3d_provider_impl.cc
@@ -5,6 +5,7 @@
#include "content/renderer/webgraphicscontext3d_provider_impl.h"
#include "cc/blink/context_provider_web_context.h"
+#include "third_party/WebKit/public/platform/callback/WebClosure.h"
namespace content {
@@ -19,8 +20,17 @@ blink::WebGraphicsContext3D* WebGraphicsContext3DProviderImpl::context3d() {
return provider_->WebContext3D();
}
+gpu::gles2::GLES2Interface* WebGraphicsContext3DProviderImpl::contextGL() {
+ return provider_->ContextGL();
+}
+
GrContext* WebGraphicsContext3DProviderImpl::grContext() {
return provider_->GrContext();
}
+void WebGraphicsContext3DProviderImpl::setLostContextCallback(
+ blink::WebClosure c) {
+ provider_->SetLostContextCallback(c.TakeBaseClosure());
+}
+
} // namespace content
diff --git a/chromium/content/renderer/webgraphicscontext3d_provider_impl.h b/chromium/content/renderer/webgraphicscontext3d_provider_impl.h
index 769dd5685c5..7b1d88c5c2a 100644
--- a/chromium/content/renderer/webgraphicscontext3d_provider_impl.h
+++ b/chromium/content/renderer/webgraphicscontext3d_provider_impl.h
@@ -14,6 +14,12 @@ namespace cc_blink {
class ContextProviderWebContext;
}
+namespace gpu {
+namespace gles2 {
+class GLES2Interface;
+}
+}
+
namespace content {
class CONTENT_EXPORT WebGraphicsContext3DProviderImpl
@@ -25,7 +31,9 @@ class CONTENT_EXPORT WebGraphicsContext3DProviderImpl
// WebGraphicsContext3DProvider implementation.
blink::WebGraphicsContext3D* context3d() override;
+ gpu::gles2::GLES2Interface* contextGL() override;
GrContext* grContext() override;
+ void setLostContextCallback(blink::WebClosure) override;
private:
scoped_refptr<cc_blink::ContextProviderWebContext> provider_;
diff --git a/chromium/content/renderer/websharedworker_proxy.cc b/chromium/content/renderer/websharedworker_proxy.cc
index c4439ded6b2..46bbfe17547 100644
--- a/chromium/content/renderer/websharedworker_proxy.cc
+++ b/chromium/content/renderer/websharedworker_proxy.cc
@@ -7,15 +7,15 @@
#include <stddef.h>
#include "content/child/webmessageportchannel_impl.h"
-#include "content/common/message_router.h"
#include "content/common/view_messages.h"
#include "content/common/worker_messages.h"
+#include "ipc/message_router.h"
#include "third_party/WebKit/public/platform/WebURL.h"
#include "third_party/WebKit/public/web/WebSharedWorkerClient.h"
namespace content {
-WebSharedWorkerProxy::WebSharedWorkerProxy(MessageRouter* router,
+WebSharedWorkerProxy::WebSharedWorkerProxy(IPC::MessageRouter* router,
int route_id)
: route_id_(route_id),
router_(router),
diff --git a/chromium/content/renderer/websharedworker_proxy.h b/chromium/content/renderer/websharedworker_proxy.h
index a413c39c6e5..cb6acb991cc 100644
--- a/chromium/content/renderer/websharedworker_proxy.h
+++ b/chromium/content/renderer/websharedworker_proxy.h
@@ -14,9 +14,11 @@
#include "third_party/WebKit/public/web/WebSharedWorkerConnector.h"
#include "url/gurl.h"
-namespace content {
-
+namespace IPC {
class MessageRouter;
+}
+
+namespace content {
// Implementation of the WebSharedWorker APIs. This object is intended to only
// live long enough to allow the caller to send a "connect" event to the worker
@@ -27,8 +29,7 @@ class WebSharedWorkerProxy : public blink::WebSharedWorkerConnector,
private IPC::Listener {
public:
// If the worker not loaded yet, route_id == MSG_ROUTING_NONE
- WebSharedWorkerProxy(MessageRouter* router,
- int route_id);
+ WebSharedWorkerProxy(IPC::MessageRouter* router, int route_id);
~WebSharedWorkerProxy() override;
// Implementations of WebSharedWorkerConnector APIs
@@ -62,7 +63,7 @@ class WebSharedWorkerProxy : public blink::WebSharedWorkerConnector,
// routing ids).
int route_id_;
- MessageRouter* const router_;
+ IPC::MessageRouter* const router_;
// Stores messages that were sent before the StartWorkerContext message.
std::vector<IPC::Message*> queued_messages_;
diff --git a/chromium/content/shell/common/DEPS b/chromium/content/shell/common/DEPS
index adb5e51966a..5f52568085a 100644
--- a/chromium/content/shell/common/DEPS
+++ b/chromium/content/shell/common/DEPS
@@ -1,4 +1,3 @@
include_rules = [
- "+components/test_runner",
"+gin/public",
]
diff --git a/chromium/content/shell/common/layout_test/layout_test_bluetooth_fake_adapter_setter.mojom b/chromium/content/shell/common/layout_test/layout_test_bluetooth_fake_adapter_setter.mojom
new file mode 100644
index 00000000000..347daa15a04
--- /dev/null
+++ b/chromium/content/shell/common/layout_test/layout_test_bluetooth_fake_adapter_setter.mojom
@@ -0,0 +1,14 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module content.mojom;
+
+interface LayoutTestBluetoothFakeAdapterSetter {
+
+ // Sets a mock BluetoothAdapter. The characteristics of the adapter
+ // depend on |adapter_name|. For a list of available mock adapters
+ // see layout_test_bluetooth_adapter_provider.h
+ Set(string adapter_name) => ();
+
+}; \ No newline at end of file
diff --git a/chromium/content/shell/common/layout_test/layout_test_content_client.cc b/chromium/content/shell/common/layout_test/layout_test_content_client.cc
new file mode 100644
index 00000000000..da2e9629afa
--- /dev/null
+++ b/chromium/content/shell/common/layout_test/layout_test_content_client.cc
@@ -0,0 +1,24 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/shell/common/layout_test/layout_test_content_client.h"
+
+#include "content/shell/common/shell_messages.h"
+
+namespace content {
+
+bool LayoutTestContentClient::CanSendWhileSwappedOut(
+ const IPC::Message* message) {
+ switch (message->type()) {
+ // Used in layout tests; handled in BlinkTestController.
+ case ShellViewHostMsg_PrintMessage::ID:
+ case ShellViewHostMsg_LayoutTestRuntimeFlagsChanged::ID:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+} // namespace content
diff --git a/chromium/content/shell/common/layout_test/layout_test_content_client.h b/chromium/content/shell/common/layout_test/layout_test_content_client.h
new file mode 100644
index 00000000000..2f2b4b9e70b
--- /dev/null
+++ b/chromium/content/shell/common/layout_test/layout_test_content_client.h
@@ -0,0 +1,24 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CONTENT_SHELL_COMMON_LAYOUT_TEST_LAYOUT_TEST_CONTENT_CLIENT_H_
+#define CONTENT_SHELL_COMMON_LAYOUT_TEST_LAYOUT_TEST_CONTENT_CLIENT_H_
+
+#include "base/macros.h"
+#include "content/shell/common/shell_content_client.h"
+
+namespace content {
+
+class LayoutTestContentClient : public ShellContentClient {
+ public:
+ LayoutTestContentClient() {}
+ bool CanSendWhileSwappedOut(const IPC::Message* message) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(LayoutTestContentClient);
+};
+
+} // namespace content
+
+#endif // CONTENT_SHELL_COMMON_LAYOUT_TEST_LAYOUT_TEST_CONTENT_CLIENT_H_
diff --git a/chromium/content/shell/common/layout_test/layout_test_messages.h b/chromium/content/shell/common/layout_test/layout_test_messages.h
index 97b3073899b..1f420f17304 100644
--- a/chromium/content/shell/common/layout_test/layout_test_messages.h
+++ b/chromium/content/shell/common/layout_test/layout_test_messages.h
@@ -6,17 +6,17 @@
#include <string>
#include <vector>
-#include "content/public/common/common_param_traits.h"
-#include "content/public/common/permission_status.mojom.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_platform_file.h"
+#include "third_party/WebKit/public/platform/modules/permissions/permission_status.mojom.h"
#include "url/gurl.h"
+#include "url/ipc/url_param_traits.h"
#define IPC_MESSAGE_START LayoutTestMsgStart
-IPC_ENUM_TRAITS_MIN_MAX_VALUE(content::PermissionStatus,
- content::PERMISSION_STATUS_GRANTED,
- content::PERMISSION_STATUS_ASK)
+IPC_ENUM_TRAITS_MIN_MAX_VALUE(blink::mojom::PermissionStatus,
+ blink::mojom::PermissionStatus::GRANTED,
+ blink::mojom::PermissionStatus::ASK)
IPC_SYNC_MESSAGE_ROUTED1_1(LayoutTestHostMsg_ReadFileToString,
base::FilePath /* local path */,
@@ -30,14 +30,15 @@ IPC_MESSAGE_ROUTED1(LayoutTestHostMsg_SetDatabaseQuota,
IPC_MESSAGE_ROUTED2(LayoutTestHostMsg_SimulateWebNotificationClick,
std::string /* title */,
int /* action_index */)
+IPC_MESSAGE_ROUTED2(LayoutTestHostMsg_SimulateWebNotificationClose,
+ std::string /* title */,
+ bool /* by_user */)
IPC_MESSAGE_ROUTED1(LayoutTestHostMsg_AcceptAllCookies,
bool /* accept */)
IPC_MESSAGE_ROUTED0(LayoutTestHostMsg_DeleteAllCookies)
IPC_MESSAGE_ROUTED4(LayoutTestHostMsg_SetPermission,
std::string /* name */,
- content::PermissionStatus /* status */,
+ blink::mojom::PermissionStatus /* status */,
GURL /* origin */,
- GURL /* embedding_origin */ )
+ GURL /* embedding_origin */)
IPC_MESSAGE_ROUTED0(LayoutTestHostMsg_ResetPermissions)
-IPC_MESSAGE_CONTROL1(LayoutTestHostMsg_SetBluetoothAdapter,
- std::string /* name */)
diff --git a/chromium/content/shell/common/layout_test/layout_test_switches.cc b/chromium/content/shell/common/layout_test/layout_test_switches.cc
new file mode 100644
index 00000000000..bc879a6dee6
--- /dev/null
+++ b/chromium/content/shell/common/layout_test/layout_test_switches.cc
@@ -0,0 +1,48 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/shell/common/layout_test/layout_test_switches.h"
+
+#include "base/command_line.h"
+#include "base/strings/string_split.h"
+
+namespace switches {
+
+// Allow access to external pages during layout tests.
+const char kAllowExternalPages[] = "allow-external-pages";
+
+// Check whether all system dependencies for running layout tests are met.
+const char kCheckLayoutTestSysDeps[] = "check-layout-test-sys-deps";
+
+// When specified to "enable-leak-detection" command-line option,
+// causes the leak detector to cause immediate crash when found leak.
+const char kCrashOnFailure[] = "crash-on-failure";
+
+// Enable accelerated 2D canvas.
+const char kEnableAccelerated2DCanvas[] = "enable-accelerated-2d-canvas";
+
+// Enable font antialiasing for pixel tests.
+const char kEnableFontAntialiasing[] = "enable-font-antialiasing";
+
+// Always use the complex text path for layout tests.
+const char kAlwaysUseComplexText[] = "always-use-complex-text";
+
+// Enables the leak detection of loading webpages. This allows us to check
+// whether or not reloading a webpage releases web-related objects correctly.
+const char kEnableLeakDetection[] = "enable-leak-detection";
+
+// Encode binary layout test results (images, audio) using base64.
+const char kEncodeBinary[] = "encode-binary";
+
+// Request the render trees of pages to be dumped as text once they have
+// finished loading.
+const char kRunLayoutTest[] = "run-layout-test";
+
+// This makes us disable some web-platform runtime features so that we test
+// content_shell as if it was a stable release. It is only followed when
+// kRunLayoutTest is set. For the features' level, see
+// http://dev.chromium.org/blink/runtime-enabled-features.
+const char kStableReleaseMode[] = "stable-release-mode";
+
+} // namespace switches
diff --git a/chromium/content/shell/common/layout_test/layout_test_switches.h b/chromium/content/shell/common/layout_test/layout_test_switches.h
new file mode 100644
index 00000000000..33d5494cadc
--- /dev/null
+++ b/chromium/content/shell/common/layout_test/layout_test_switches.h
@@ -0,0 +1,28 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Defines all the "layout_test" command-line switches.
+
+#ifndef CONTENT_SHELL_COMMON_LAYOUT_TEST_LAYOUT_TEST_SWITCHES_H_
+#define CONTENT_SHELL_COMMON_LAYOUT_TEST_LAYOUT_TEST_SWITCHES_H_
+
+#include <string>
+#include <vector>
+
+namespace switches {
+
+extern const char kAllowExternalPages[];
+extern const char kCheckLayoutTestSysDeps[];
+extern const char kCrashOnFailure[];
+extern const char kEnableAccelerated2DCanvas[];
+extern const char kEnableFontAntialiasing[];
+extern const char kAlwaysUseComplexText[];
+extern const char kEnableLeakDetection[];
+extern const char kEncodeBinary[];
+extern const char kRunLayoutTest[];
+extern const char kStableReleaseMode[];
+
+} // namespace switches
+
+#endif // CONTENT_SHELL_COMMON_LAYOUT_TEST_LAYOUT_TEST_SWITCHES_H_
diff --git a/chromium/content/shell/common/shell_content_client.cc b/chromium/content/shell/common/shell_content_client.cc
index d0940b8b92b..82c2f0c5033 100644
--- a/chromium/content/shell/common/shell_content_client.cc
+++ b/chromium/content/shell/common/shell_content_client.cc
@@ -20,6 +20,19 @@
namespace content {
+namespace {
+
+// This is the public key which the content shell will use to enable origin
+// trial features.
+// TODO(iclelland): Update this comment with the location of the public and
+// private key files when the command-line tool CL lands
+static const uint8_t kOriginTrialPublicKey[] = {
+ 0x75, 0x10, 0xac, 0xf9, 0x3a, 0x1c, 0xb8, 0xa9, 0x28, 0x70, 0xd2,
+ 0x9a, 0xd0, 0x0b, 0x59, 0xe1, 0xac, 0x2b, 0xb7, 0xd5, 0xca, 0x1f,
+ 0x64, 0x90, 0x08, 0x8e, 0xa8, 0xe0, 0x56, 0x3a, 0x04, 0xd0,
+};
+} // namespace
+
std::string GetShellUserAgent() {
std::string product = "Chrome/" CONTENT_SHELL_VERSION;
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
@@ -28,16 +41,19 @@ std::string GetShellUserAgent() {
return BuildUserAgentFromProduct(product);
}
-ShellContentClient::~ShellContentClient() {
-}
+ShellContentClient::ShellContentClient()
+ : origin_trial_public_key_(base::StringPiece(
+ reinterpret_cast<const char*>(kOriginTrialPublicKey),
+ arraysize(kOriginTrialPublicKey))) {}
+
+ShellContentClient::~ShellContentClient() {}
std::string ShellContentClient::GetUserAgent() const {
return GetShellUserAgent();
}
base::string16 ShellContentClient::GetLocalizedString(int message_id) const {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kRunLayoutTest)) {
+ if (switches::IsRunLayoutTestSwitchPresent()) {
switch (message_id) {
case IDS_FORM_OTHER_DATE_LABEL:
return base::ASCIIToUTF16("<<OtherDateLabel>>");
@@ -63,8 +79,7 @@ base::string16 ShellContentClient::GetLocalizedString(int message_id) const {
base::StringPiece ShellContentClient::GetDataResource(
int resource_id,
ui::ScaleFactor scale_factor) const {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kRunLayoutTest)) {
+ if (switches::IsRunLayoutTestSwitchPresent()) {
switch (resource_id) {
case IDR_BROKENIMAGE:
#if defined(OS_MACOSX)
@@ -97,4 +112,8 @@ bool ShellContentClient::IsSupplementarySiteIsolationModeEnabled() {
switches::kIsolateSitesForTesting);
}
+base::StringPiece ShellContentClient::GetOriginTrialPublicKey() {
+ return origin_trial_public_key_;
+}
+
} // namespace content
diff --git a/chromium/content/shell/common/shell_content_client.h b/chromium/content/shell/common/shell_content_client.h
index ceebc52d2bd..2b1e7b65b10 100644
--- a/chromium/content/shell/common/shell_content_client.h
+++ b/chromium/content/shell/common/shell_content_client.h
@@ -17,6 +17,7 @@ std::string GetShellUserAgent();
class ShellContentClient : public ContentClient {
public:
+ ShellContentClient();
~ShellContentClient() override;
std::string GetUserAgent() const override;
@@ -28,6 +29,10 @@ class ShellContentClient : public ContentClient {
int resource_id) const override;
gfx::Image& GetNativeImageNamed(int resource_id) const override;
bool IsSupplementarySiteIsolationModeEnabled() override;
+ base::StringPiece GetOriginTrialPublicKey() override;
+
+ private:
+ base::StringPiece origin_trial_public_key_;
};
} // namespace content
diff --git a/chromium/content/shell/common/shell_messages.h b/chromium/content/shell/common/shell_messages.h
index ebdecb80d8c..f9146b99cc9 100644
--- a/chromium/content/shell/common/shell_messages.h
+++ b/chromium/content/shell/common/shell_messages.h
@@ -6,6 +6,7 @@
#include <string>
#include <vector>
+#include "base/values.h"
#include "content/public/common/common_param_traits.h"
#include "content/public/common/page_state.h"
#include "content/shell/common/leak_detection_result.h"
@@ -14,6 +15,7 @@
#include "ipc/ipc_platform_file.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/ipc/gfx_param_traits.h"
+#include "ui/gfx/ipc/skia/gfx_skia_param_traits.h"
#define IPC_MESSAGE_START ShellMsgStart
@@ -34,12 +36,23 @@ IPC_MESSAGE_ROUTED0(ShellViewMsg_Reset)
IPC_MESSAGE_CONTROL1(ShellViewMsg_SetWebKitSourceDir,
base::FilePath /* webkit source dir */)
-// Sets the initial configuration to use for layout tests.
+// Sets the test config for a layout test that is being started.
IPC_MESSAGE_ROUTED1(ShellViewMsg_SetTestConfiguration,
content::ShellTestConfiguration)
-// Tells the main window that a secondary window in a different process invoked
-// notifyDone().
+// Replicates test config (for an already started test) to a new renderer.
+IPC_MESSAGE_ROUTED2(
+ ShellViewMsg_ReplicateTestConfiguration,
+ content::ShellTestConfiguration,
+ base::DictionaryValue /* accumulated_layout_test_runtime_flags_changes */)
+
+// Used to broadcast changes happening in one renderer to all other renderers.
+IPC_MESSAGE_ROUTED1(
+ ShellViewMsg_ReplicateLayoutTestRuntimeFlagsChanges,
+ base::DictionaryValue /* changed_layout_test_runtime_flags */)
+
+// Tells the main window that a secondary renderer in a different process thinks
+// the test is finished.
IPC_MESSAGE_ROUTED0(ShellViewMsg_NotifyDone)
// Pushes a snapshot of the current session history from the browser process.
@@ -54,10 +67,33 @@ IPC_MESSAGE_ROUTED3(
IPC_MESSAGE_ROUTED0(ShellViewMsg_TryLeakDetection)
+// Asks a frame to dump its contents into a string and send them back over IPC.
+IPC_MESSAGE_ROUTED0(ShellViewMsg_LayoutDumpRequest)
+
+// Notifies BlinkTestRunner that the layout dump has completed
+// (and that it can proceed with finishing up the test).
+IPC_MESSAGE_ROUTED1(ShellViewMsg_LayoutDumpCompleted,
+ std::string /* completed/stitched layout dump */)
+
+// Notifies the browser that one of renderers has changed layout test runtime
+// flags (i.e. has set dump_as_text).
+IPC_MESSAGE_ROUTED1(
+ ShellViewHostMsg_LayoutTestRuntimeFlagsChanged,
+ base::DictionaryValue /* changed_layout_test_runtime_flags */)
+
// Send a text dump of the WebContents to the render host.
IPC_MESSAGE_ROUTED1(ShellViewHostMsg_TextDump,
std::string /* dump */)
+// Asks the browser process to perform a layout dump spanning all the
+// (potentially cross-process) frames. This triggers multiple
+// ShellViewMsg_LayoutDumpRequest / ShellViewHostMsg_LayoutDumpResponse messages
+// and ends with sending of ShellViewMsg_LayoutDumpCompleted.
+IPC_MESSAGE_ROUTED0(ShellViewHostMsg_InitiateLayoutDump)
+
+// Sends a layout dump of a frame (response to ShellViewMsg_LayoutDumpRequest).
+IPC_MESSAGE_ROUTED1(ShellViewHostMsg_LayoutDumpResponse, std::string /* dump */)
+
// Send an image dump of the WebContents to the render host.
IPC_MESSAGE_ROUTED2(ShellViewHostMsg_ImageDump,
std::string /* actual pixel hash */,
@@ -71,7 +107,7 @@ IPC_MESSAGE_ROUTED0(ShellViewHostMsg_TestFinished)
IPC_MESSAGE_ROUTED0(ShellViewHostMsg_ResetDone)
-IPC_MESSAGE_ROUTED0(ShellViewHostMsg_TestFinishedInSecondaryWindow)
+IPC_MESSAGE_ROUTED0(ShellViewHostMsg_TestFinishedInSecondaryRenderer)
// WebTestDelegate related.
IPC_MESSAGE_ROUTED1(ShellViewHostMsg_OverridePreferences,
@@ -82,6 +118,9 @@ IPC_MESSAGE_ROUTED0(ShellViewHostMsg_ClearDevToolsLocalStorage)
IPC_MESSAGE_ROUTED2(ShellViewHostMsg_ShowDevTools,
std::string /* settings */,
std::string /* frontend_url */)
+IPC_MESSAGE_ROUTED2(ShellViewHostMsg_EvaluateInDevTools,
+ int /* call_id */,
+ std::string /* script */)
IPC_MESSAGE_ROUTED0(ShellViewHostMsg_CloseDevTools)
IPC_MESSAGE_ROUTED1(ShellViewHostMsg_GoToOffset,
int /* offset */)
diff --git a/chromium/content/shell/common/shell_switches.cc b/chromium/content/shell/common/shell_switches.cc
index 25c1070e4eb..cf4280b415a 100644
--- a/chromium/content/shell/common/shell_switches.cc
+++ b/chromium/content/shell/common/shell_switches.cc
@@ -6,15 +6,10 @@
#include "base/command_line.h"
#include "base/strings/string_split.h"
+#include "content/shell/common/layout_test/layout_test_switches.h"
namespace switches {
-// Allow access to external pages during layout tests.
-const char kAllowExternalPages[] = "allow-external-pages";
-
-// Check whether all system dependencies for running layout tests are met.
-const char kCheckLayoutTestSysDeps[] = "check-layout-test-sys-deps";
-
// Tells Content Shell that it's running as a content_browsertest.
const char kContentBrowserTest[] = "browser-test";
@@ -24,30 +19,6 @@ const char kContentShellDataPath[] = "data-path";
// The directory breakpad should store minidumps in.
const char kCrashDumpsDir[] = "crash-dumps-dir";
-// When specified to "enable-leak-detection" command-line option,
-// causes the leak detector to cause immediate crash when found leak.
-const char kCrashOnFailure[] = "crash-on-failure";
-
-// When run-layout-test is enabled, this causes the line box tree for
-// each LayoutBlockFlow to be dumped as well.
-const char kDumpLineBoxTrees[] = "dump-line-box-trees";
-
-// Enable accelerated 2D canvas.
-const char kEnableAccelerated2DCanvas[] = "enable-accelerated-2d-canvas";
-
-// Enable font antialiasing for pixel tests.
-const char kEnableFontAntialiasing[] = "enable-font-antialiasing";
-
-// Always use the complex text path for layout tests.
-const char kAlwaysUseComplexText[] = "always-use-complex-text";
-
-// Enables the leak detection of loading webpages. This allows us to check
-// whether or not reloading a webpage releases web-related objects correctly.
-const char kEnableLeakDetection[] = "enable-leak-detection";
-
-// Encode binary layout test results (images, audio) using base64.
-const char kEncodeBinary[] = "encode-binary";
-
// Exposes the window.internals object to JavaScript for interactive development
// and debugging of layout tests that rely on it.
const char kExposeInternalsForTesting[] = "expose-internals-for-testing";
@@ -65,16 +36,6 @@ const char kIsolateSitesForTesting[] = "isolate-sites-for-testing";
// with a semicolon (;).
const char kRegisterFontFiles[] = "register-font-files";
-// Request the render trees of pages to be dumped as text once they have
-// finished loading.
-const char kRunLayoutTest[] = "run-layout-test";
-
-// This makes us disable some web-platform runtime features so that we test
-// content_shell as if it was a stable release. It is only followed when
-// kRunLayoutTest is set. For the features' level, see
-// http://dev.chromium.org/blink/runtime-enabled-features.
-const char kStableReleaseMode[] = "stable-release-mode";
-
// Size for the content_shell's host window (i.e. "800x600").
const char kContentShellHostWindowSize[] = "content-shell-host-window-size";
@@ -90,4 +51,9 @@ std::vector<std::string> GetSideloadFontFiles() {
return files;
}
+bool IsRunLayoutTestSwitchPresent() {
+ return base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kRunLayoutTest);
+}
+
} // namespace switches
diff --git a/chromium/content/shell/common/shell_switches.h b/chromium/content/shell/common/shell_switches.h
index db786144b7f..4b096224646 100644
--- a/chromium/content/shell/common/shell_switches.h
+++ b/chromium/content/shell/common/shell_switches.h
@@ -12,28 +12,23 @@
namespace switches {
-extern const char kAllowExternalPages[];
-extern const char kCheckLayoutTestSysDeps[];
extern const char kContentBrowserTest[];
extern const char kContentShellDataPath[];
extern const char kCrashDumpsDir[];
-extern const char kCrashOnFailure[];
-extern const char kDumpLineBoxTrees[];
-extern const char kEnableAccelerated2DCanvas[];
-extern const char kEnableFontAntialiasing[];
-extern const char kAlwaysUseComplexText[];
-extern const char kEnableLeakDetection[];
-extern const char kEncodeBinary[];
extern const char kExposeInternalsForTesting[];
extern const char kIsolateSitesForTesting[];
extern const char kRegisterFontFiles[];
-extern const char kRunLayoutTest[];
-extern const char kStableReleaseMode[];
extern const char kContentShellHostWindowSize[];
// Returns list of extra font files to be made accessible to the renderer.
std::vector<std::string> GetSideloadFontFiles();
+// Tells if content shell is running layout tests.
+// TODO(lukasza): The function below somewhat violates the layering (by
+// enabling shell -> layout_tests dependency) but at least narrows the extent of
+// the dependency to a single switch...
+bool IsRunLayoutTestSwitchPresent();
+
} // namespace switches
#endif // CONTENT_SHELL_COMMON_SHELL_SWITCHES_H_
diff --git a/chromium/content/shell/shell_resources.grd b/chromium/content/shell/shell_resources.grd
new file mode 100644
index 00000000000..bfb4071d2f5
--- /dev/null
+++ b/chromium/content/shell/shell_resources.grd
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<grit latest_public_release="0" current_release="1">
+ <outputs>
+ <output filename="grit/shell_resources.h" type="rc_header">
+ <emit emit_type='prepend'></emit>
+ </output>
+ <output filename="shell_resources.pak" type="data_package" />
+ </outputs>
+ <translations />
+ <release seq="1">
+ <includes>
+ <include name="IDR_CONTENT_SHELL_DEVTOOLS_DISCOVERY_PAGE" file="resources/shell_devtools_discovery_page.html" type="BINDATA" />
+ <include name="IDR_CONTENT_SHELL_MISSING_IMAGE_GIF" file="resources/missingImage.gif" type="BINDATA" />
+ <include name="IDR_CONTENT_SHELL_MISSING_IMAGE_PNG" file="resources/missingImage.png" type="BINDATA" />
+ <include name="IDR_CONTENT_SHELL_TEXT_AREA_RESIZE_CORNER_PNG" file="resources/textAreaResizeCorner.png" type="BINDATA" />
+ </includes>
+ </release>
+</grit>
diff --git a/chromium/content/utility/BUILD.gn b/chromium/content/utility/BUILD.gn
index 8bb058aeb12..0ef4261ba32 100644
--- a/chromium/content/utility/BUILD.gn
+++ b/chromium/content/utility/BUILD.gn
@@ -7,8 +7,11 @@ import("//media/media_options.gni")
source_set("utility") {
# Only the public target should depend on this. All other targets (even
- # internal content ones) should depend on the public one.
- visibility = [ "//content/public/utility:utility_sources" ]
+ # internal content ones other than test) should depend on the public one.
+ visibility = [
+ ":for_content_tests",
+ "//content/public/utility:utility_sources",
+ ]
sources =
rebase_path(content_utility_gypi_values.utility_sources, ".", "//content")
@@ -17,11 +20,13 @@ source_set("utility") {
deps = [
"//base",
+ "//components/scheduler",
"//content:export",
"//content/public/child:child_sources",
"//content/public/common:common_sources",
"//content/public/common:mojo_bindings",
"//courgette:courgette_lib",
+ "//media/mojo/services:application_factory",
"//mojo/common",
"//mojo/public/cpp/bindings",
"//mojo/shell",
@@ -31,7 +36,17 @@ source_set("utility") {
"//url",
]
- if (enable_mojo_media == "utility") {
- deps += [ "//media/mojo/services:application" ]
+ if (mojo_media_host == "utility") {
+ deps += [ "//media/mojo/services:application_factory" ]
+ }
+}
+
+# See comment at the top of //content/BUILD.gn for how this works.
+group("for_content_tests") {
+ visibility = [ "//content/test/*" ]
+ if (!is_component_build) {
+ public_deps = [
+ ":utility",
+ ]
}
}
diff --git a/chromium/content/utility/in_process_utility_thread.h b/chromium/content/utility/in_process_utility_thread.h
index 850e015a48f..074837b942c 100644
--- a/chromium/content/utility/in_process_utility_thread.h
+++ b/chromium/content/utility/in_process_utility_thread.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "base/threading/thread.h"
#include "content/common/content_export.h"
#include "content/common/in_process_child_thread_params.h"
diff --git a/chromium/content/utility/utility_blink_platform_impl.h b/chromium/content/utility/utility_blink_platform_impl.h
index 3af30519731..d66299eca6f 100644
--- a/chromium/content/utility/utility_blink_platform_impl.h
+++ b/chromium/content/utility/utility_blink_platform_impl.h
@@ -6,6 +6,7 @@
#define CONTENT_UTILITY_UTILITY_BLINK_PLATFORM_IMPL_H_
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
#include "content/child/blink_platform_impl.h"
namespace content {
diff --git a/chromium/content/utility/utility_process_control_impl.cc b/chromium/content/utility/utility_process_control_impl.cc
index 1a886e1abb8..f717f868795 100644
--- a/chromium/content/utility/utility_process_control_impl.cc
+++ b/chromium/content/utility/utility_process_control_impl.cc
@@ -5,14 +5,14 @@
#include "content/utility/utility_process_control_impl.h"
#include "base/bind.h"
+#include "content/common/mojo/static_loader.h"
#include "content/public/common/content_client.h"
#include "content/public/utility/content_utility_client.h"
#include "content/public/utility/utility_thread.h"
#include "content/utility/utility_thread_impl.h"
-#include "mojo/shell/static_application_loader.h"
#if defined(ENABLE_MOJO_MEDIA_IN_UTILITY_PROCESS)
-#include "media/mojo/services/mojo_media_application.h"
+#include "media/mojo/services/mojo_media_application_factory.h"
#endif
namespace content {
@@ -30,22 +30,21 @@ UtilityProcessControlImpl::UtilityProcessControlImpl() {}
UtilityProcessControlImpl::~UtilityProcessControlImpl() {}
-void UtilityProcessControlImpl::RegisterApplicationLoaders(
- URLToLoaderMap* url_to_loader_map) {
- URLToLoaderMap& map_ref = *url_to_loader_map;
+void UtilityProcessControlImpl::RegisterLoaders(
+ NameToLoaderMap* name_to_loader_map) {
+ NameToLoaderMap& map_ref = *name_to_loader_map;
ContentUtilityClient::StaticMojoApplicationMap apps;
GetContentClient()->utility()->RegisterMojoApplications(&apps);
for (const auto& entry : apps) {
- map_ref[entry.first] = new mojo::shell::StaticApplicationLoader(
- entry.second, base::Bind(&QuitProcess));
+ map_ref[entry.first] =
+ new StaticLoader(entry.second, base::Bind(&QuitProcess));
}
#if defined(ENABLE_MOJO_MEDIA_IN_UTILITY_PROCESS)
- map_ref[GURL("mojo:media")] = new mojo::shell::StaticApplicationLoader(
- base::Bind(&media::MojoMediaApplication::CreateApp),
- base::Bind(&QuitProcess));
+ map_ref["mojo:media"] = new StaticLoader(
+ base::Bind(&media::CreateMojoMediaApplication), base::Bind(&QuitProcess));
#endif
}
diff --git a/chromium/content/utility/utility_process_control_impl.h b/chromium/content/utility/utility_process_control_impl.h
index f57dbe6ebf3..9d450fd2fda 100644
--- a/chromium/content/utility/utility_process_control_impl.h
+++ b/chromium/content/utility/utility_process_control_impl.h
@@ -18,7 +18,7 @@ class UtilityProcessControlImpl : public ProcessControlImpl {
~UtilityProcessControlImpl() override;
// ProcessControlImpl:
- void RegisterApplicationLoaders(URLToLoaderMap* url_to_loader_map) override;
+ void RegisterLoaders(NameToLoaderMap* name_to_loader_map) override;
private:
void OnLoadFailed() override;
diff --git a/chromium/content/utility/utility_thread_impl.cc b/chromium/content/utility/utility_thread_impl.cc
index b6587f58aa6..edbf498303a 100644
--- a/chromium/content/utility/utility_thread_impl.cc
+++ b/chromium/content/utility/utility_thread_impl.cc
@@ -57,7 +57,7 @@ void UtilityThreadImpl::Shutdown() {
ChildThreadImpl::Shutdown();
if (blink_platform_impl_)
- blink::shutdownWithoutV8();
+ blink::Platform::shutdown();
}
void UtilityThreadImpl::ReleaseProcessIfNeeded() {
@@ -85,7 +85,7 @@ void UtilityThreadImpl::EnsureBlinkInitialized() {
}
blink_platform_impl_.reset(new UtilityBlinkPlatformImpl);
- blink::initializeWithoutV8(blink_platform_impl_.get());
+ blink::Platform::initialize(blink_platform_impl_.get());
}
void UtilityThreadImpl::Init() {
@@ -108,9 +108,6 @@ bool UtilityThreadImpl::OnControlMessageReceived(const IPC::Message& msg) {
IPC_BEGIN_MESSAGE_MAP(UtilityThreadImpl, msg)
IPC_MESSAGE_HANDLER(UtilityMsg_BatchMode_Started, OnBatchModeStarted)
IPC_MESSAGE_HANDLER(UtilityMsg_BatchMode_Finished, OnBatchModeFinished)
-#if defined(OS_POSIX) && defined(ENABLE_PLUGINS)
- IPC_MESSAGE_HANDLER(UtilityMsg_LoadPlugins, OnLoadPlugins)
-#endif
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
@@ -125,30 +122,8 @@ void UtilityThreadImpl::OnBatchModeFinished() {
ReleaseProcessIfNeeded();
}
-#if defined(OS_POSIX) && defined(ENABLE_PLUGINS)
-void UtilityThreadImpl::OnLoadPlugins(
- const std::vector<base::FilePath>& plugin_paths) {
- PluginList* plugin_list = PluginList::Singleton();
-
- std::vector<WebPluginInfo> plugins;
- // TODO(bauerb): If we restart loading plugins, we might mess up the logic in
- // PluginList::ShouldLoadPlugin due to missing the previously loaded plugins
- // in |plugin_groups|.
- for (size_t i = 0; i < plugin_paths.size(); ++i) {
- WebPluginInfo plugin;
- if (!plugin_list->LoadPluginIntoPluginList(
- plugin_paths[i], &plugins, &plugin))
- Send(new UtilityHostMsg_LoadPluginFailed(i, plugin_paths[i]));
- else
- Send(new UtilityHostMsg_LoadedPlugin(i, plugin));
- }
-
- ReleaseProcessIfNeeded();
-}
-#endif
-
void UtilityThreadImpl::BindProcessControlRequest(
- mojo::InterfaceRequest<ProcessControl> request) {
+ mojo::InterfaceRequest<mojom::ProcessControl> request) {
DCHECK(process_control_);
process_control_bindings_.AddBinding(process_control_.get(),
std::move(request));
diff --git a/chromium/content/utility/utility_thread_impl.h b/chromium/content/utility/utility_thread_impl.h
index 415b2af95e6..2894b3d99ae 100644
--- a/chromium/content/utility/utility_thread_impl.h
+++ b/chromium/content/utility/utility_thread_impl.h
@@ -16,7 +16,7 @@
#include "content/common/content_export.h"
#include "content/common/process_control.mojom.h"
#include "content/public/utility/utility_thread.h"
-#include "mojo/common/weak_binding_set.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
namespace base {
class FilePath;
@@ -56,12 +56,8 @@ class UtilityThreadImpl : public UtilityThread,
void OnBatchModeStarted();
void OnBatchModeFinished();
-#if defined(OS_POSIX) && defined(ENABLE_PLUGINS)
- void OnLoadPlugins(const std::vector<base::FilePath>& plugin_paths);
-#endif
-
void BindProcessControlRequest(
- mojo::InterfaceRequest<content::ProcessControl> request);
+ mojo::InterfaceRequest<content::mojom::ProcessControl> request);
// True when we're running in batch mode.
bool batch_mode_;
@@ -71,8 +67,8 @@ class UtilityThreadImpl : public UtilityThread,
// Process control for Mojo application hosting.
scoped_ptr<UtilityProcessControlImpl> process_control_;
- // Bindings to the ProcessControl impl.
- mojo::WeakBindingSet<ProcessControl> process_control_bindings_;
+ // Bindings to the mojom::ProcessControl impl.
+ mojo::BindingSet<mojom::ProcessControl> process_control_bindings_;
DISALLOW_COPY_AND_ASSIGN(UtilityThreadImpl);
};
diff --git a/chromium/content/utility/webthread_impl_for_utility_thread.cc b/chromium/content/utility/webthread_impl_for_utility_thread.cc
index f72456d7712..9ee10aa8a24 100644
--- a/chromium/content/utility/webthread_impl_for_utility_thread.cc
+++ b/chromium/content/utility/webthread_impl_for_utility_thread.cc
@@ -25,13 +25,13 @@ blink::PlatformThreadId WebThreadImplForUtilityThread::threadId() const {
return thread_id_;
}
-base::SingleThreadTaskRunner* WebThreadImplForUtilityThread::TaskRunner()
+base::SingleThreadTaskRunner* WebThreadImplForUtilityThread::GetTaskRunner()
const {
return task_runner_.get();
}
scheduler::SingleThreadIdleTaskRunner*
-WebThreadImplForUtilityThread::IdleTaskRunner() const {
+WebThreadImplForUtilityThread::GetIdleTaskRunner() const {
NOTIMPLEMENTED();
return nullptr;
}
diff --git a/chromium/content/utility/webthread_impl_for_utility_thread.h b/chromium/content/utility/webthread_impl_for_utility_thread.h
index d2ad637b17e..a5220fe0960 100644
--- a/chromium/content/utility/webthread_impl_for_utility_thread.h
+++ b/chromium/content/utility/webthread_impl_for_utility_thread.h
@@ -21,8 +21,8 @@ class WebThreadImplForUtilityThread : public scheduler::WebThreadBase {
blink::PlatformThreadId threadId() const override;
// WebThreadBase implementation.
- base::SingleThreadTaskRunner* TaskRunner() const override;
- scheduler::SingleThreadIdleTaskRunner* IdleTaskRunner() const override;
+ base::SingleThreadTaskRunner* GetTaskRunner() const override;
+ scheduler::SingleThreadIdleTaskRunner* GetIdleTaskRunner() const override;
private:
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
diff --git a/chromium/content/zygote/zygote_linux.cc b/chromium/content/zygote/zygote_linux.cc
index 71d94da8cdf..09828fb4421 100644
--- a/chromium/content/zygote/zygote_linux.cc
+++ b/chromium/content/zygote/zygote_linux.cc
@@ -46,7 +46,7 @@
#include "sandbox/linux/services/credentials.h"
#include "sandbox/linux/services/namespace_sandbox.h"
-// See http://code.google.com/p/chromium/wiki/LinuxZygote
+// See https://chromium.googlesource.com/chromium/src/+/master/docs/linux_zygote.md
namespace content {
@@ -108,7 +108,7 @@ bool Zygote::ProcessRequests() {
// A SOCK_SEQPACKET socket is installed in fd 3. We get commands from the
// browser on it.
// A SOCK_DGRAM is installed in fd 5. This is the sandbox IPC channel.
- // See http://code.google.com/p/chromium/wiki/LinuxSandboxIPC
+ // See https://chromium.googlesource.com/chromium/src/+/master/docs/linux_sandbox_ipc.md
// We need to accept SIGCHLD, even though our handler is a no-op because
// otherwise we cannot wait on children. (According to POSIX 2001.)
@@ -237,14 +237,14 @@ bool Zygote::HandleRequestFromBrowser(int fd) {
if (len == 0 || (len == -1 && errno == ECONNRESET)) {
// EOF from the browser. We should die.
- // TODO(earthdok): call __sanititizer_cov_dump() here to obtain code
+ // TODO(eugenis): call __sanititizer_cov_dump() here to obtain code
// coverage for the Zygote. Currently it's not possible because of
// confusion over who is responsible for closing the file descriptor.
for (int fd : extra_fds_) {
PCHECK(0 == IGNORE_EINTR(close(fd)));
}
#if !defined(SANITIZER_COVERAGE)
- // TODO(earthdok): add watchdog thread before using this in builds not
+ // TODO(eugenis): add watchdog thread before using this in builds not
// using sanitizer coverage.
CHECK(extra_children_.empty());
#endif
@@ -300,7 +300,6 @@ bool Zygote::HandleRequestFromBrowser(int fd) {
return false;
}
-// TODO(jln): remove callers to this broken API. See crbug.com/274855.
void Zygote::HandleReapRequest(int fd, base::PickleIterator iter) {
base::ProcessId child;
@@ -436,9 +435,15 @@ int Zygote::ForkWithRealPid(const std::string& process_type,
DLOG(ERROR) << "Failed to find kPrimaryIPCChannel in FD mapping";
return -1;
}
+ int mojo_channel_fd = LookUpFd(fd_mapping, kMojoIPCChannel);
+ if (mojo_channel_fd < 0) {
+ DLOG(ERROR) << "Failed to find kMojoIPCChannel in FD mapping";
+ return -1;
+ }
std::vector<int> fds;
fds.push_back(ipc_channel_fd); // kBrowserFDIndex
fds.push_back(pid_oracle.get()); // kPIDOracleFDIndex
+ fds.push_back(mojo_channel_fd); // kMojoParentFDIndex
pid = helper->Fork(process_type, fds, channel_id);
// Helpers should never return in the child process.
diff --git a/chromium/content/zygote/zygote_main_linux.cc b/chromium/content/zygote/zygote_main_linux.cc
index 8a3221a38dd..da5a1e8299f 100644
--- a/chromium/content/zygote/zygote_main_linux.cc
+++ b/chromium/content/zygote/zygote_main_linux.cc
@@ -6,6 +6,7 @@
#include <dlfcn.h>
#include <fcntl.h>
+#include <openssl/crypto.h>
#include <openssl/rand.h>
#include <pthread.h>
#include <signal.h>
@@ -46,8 +47,10 @@
#include "sandbox/linux/services/namespace_sandbox.h"
#include "sandbox/linux/services/thread_helpers.h"
#include "sandbox/linux/suid/client/setuid_sandbox_client.h"
+#include "third_party/WebKit/public/web/linux/WebFontRendering.h"
#include "third_party/icu/source/i18n/unicode/timezone.h"
#include "third_party/skia/include/ports/SkFontConfigInterface.h"
+#include "third_party/skia/include/ports/SkFontMgr_android.h"
#if defined(OS_LINUX)
#include <sys/prctl.h>
@@ -84,7 +87,7 @@ void RunTwoClosures(const base::Closure* first, const base::Closure* second) {
} // namespace
-// See http://code.google.com/p/chromium/wiki/LinuxZygote
+// See https://chromium.googlesource.com/chromium/src/+/master/docs/linux_zygote.md
static void ProxyLocaltimeCallToBrowser(time_t input, struct tm* output,
char* timezone_out,
@@ -148,7 +151,7 @@ static bool g_am_zygote_or_renderer = false;
//
// Our replacement functions can check this global and either proxy
// the call to the browser over the sandbox IPC
-// (http://code.google.com/p/chromium/wiki/LinuxSandboxIPC) or they can use
+// (https://chromium.googlesource.com/chromium/src/+/master/docs/linux_sandbox_ipc.md) or they can use
// dlsym with RTLD_NEXT to resolve the symbol, ignoring any symbols in the
// current module.
//
@@ -333,6 +336,12 @@ static void ZygotePreSandboxInit() {
// cached and there's no more need to access the file system.
scoped_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault());
+#if defined(ARCH_CPU_ARM_FAMILY)
+ // On ARM, BoringSSL requires access to /proc/cpuinfo to determine processor
+ // features. Query this before entering the sandbox.
+ CRYPTO_library_init();
+#endif
+
// Pass BoringSSL a copy of the /dev/urandom file descriptor so RAND_bytes
// will work inside the sandbox.
RAND_set_urandom_fd(base::GetUrandomFD());
@@ -344,8 +353,32 @@ static void ZygotePreSandboxInit() {
#if defined(ENABLE_WEBRTC)
InitializeWebRtcModule();
#endif
+
SkFontConfigInterface::SetGlobal(
new FontConfigIPC(GetSandboxFD()))->unref();
+
+ // Set the android SkFontMgr for blink. We need to ensure this is done
+ // before the sandbox is initialized to allow the font manager to access
+ // font configuration files on disk.
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kAndroidFontsPath)) {
+ std::string android_fonts_dir =
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kAndroidFontsPath);
+
+ if (android_fonts_dir.size() > 0 && android_fonts_dir.back() != '/')
+ android_fonts_dir += '/';
+ std::string font_config = android_fonts_dir + "fonts.xml";
+ SkFontMgr_Android_CustomFonts custom;
+ custom.fSystemFontUse =
+ SkFontMgr_Android_CustomFonts::SystemFontUse::kOnlyCustom;
+ custom.fBasePath = android_fonts_dir.c_str();
+ custom.fFontsXml = font_config.c_str();
+ custom.fFallbackFontsXml = nullptr;
+ custom.fIsolated = true;
+
+ blink::WebFontRendering::setSkiaFontManager(SkFontMgr_New_Android(&custom));
+ }
}
static bool CreateInitProcessReaper(base::Closure* post_fork_parent_callback) {